18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * stv0367.c 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Driver for ST STV0367 DVB-T & DVB-C demodulator IC. 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Copyright (C) ST Microelectronics. 88c2ecf20Sopenharmony_ci * Copyright (C) 2010,2011 NetUP Inc. 98c2ecf20Sopenharmony_ci * Copyright (C) 2010,2011 Igor M. Liplianin <liplianin@netup.ru> 108c2ecf20Sopenharmony_ci */ 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#include <linux/kernel.h> 138c2ecf20Sopenharmony_ci#include <linux/module.h> 148c2ecf20Sopenharmony_ci#include <linux/string.h> 158c2ecf20Sopenharmony_ci#include <linux/slab.h> 168c2ecf20Sopenharmony_ci#include <linux/i2c.h> 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ci#include <media/dvb_math.h> 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci#include "stv0367.h" 218c2ecf20Sopenharmony_ci#include "stv0367_defs.h" 228c2ecf20Sopenharmony_ci#include "stv0367_regs.h" 238c2ecf20Sopenharmony_ci#include "stv0367_priv.h" 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci/* Max transfer size done by I2C transfer functions */ 268c2ecf20Sopenharmony_ci#define MAX_XFER_SIZE 64 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_cistatic int stvdebug; 298c2ecf20Sopenharmony_cimodule_param_named(debug, stvdebug, int, 0644); 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_cistatic int i2cdebug; 328c2ecf20Sopenharmony_cimodule_param_named(i2c_debug, i2cdebug, int, 0644); 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci#define dprintk(args...) \ 358c2ecf20Sopenharmony_ci do { \ 368c2ecf20Sopenharmony_ci if (stvdebug) \ 378c2ecf20Sopenharmony_ci printk(KERN_DEBUG args); \ 388c2ecf20Sopenharmony_ci } while (0) 398c2ecf20Sopenharmony_ci /* DVB-C */ 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_cienum active_demod_state { demod_none, demod_ter, demod_cab }; 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_cistruct stv0367cab_state { 448c2ecf20Sopenharmony_ci enum stv0367_cab_signal_type state; 458c2ecf20Sopenharmony_ci u32 mclk; 468c2ecf20Sopenharmony_ci u32 adc_clk; 478c2ecf20Sopenharmony_ci s32 search_range; 488c2ecf20Sopenharmony_ci s32 derot_offset; 498c2ecf20Sopenharmony_ci /* results */ 508c2ecf20Sopenharmony_ci int locked; /* channel found */ 518c2ecf20Sopenharmony_ci u32 freq_khz; /* found frequency (in kHz) */ 528c2ecf20Sopenharmony_ci u32 symbol_rate; /* found symbol rate (in Bds) */ 538c2ecf20Sopenharmony_ci enum fe_spectral_inversion spect_inv; /* Spectrum Inversion */ 548c2ecf20Sopenharmony_ci u32 qamfec_status_reg; /* status reg to poll for FEC Lock */ 558c2ecf20Sopenharmony_ci}; 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_cistruct stv0367ter_state { 588c2ecf20Sopenharmony_ci /* DVB-T */ 598c2ecf20Sopenharmony_ci enum stv0367_ter_signal_type state; 608c2ecf20Sopenharmony_ci enum stv0367_ter_if_iq_mode if_iq_mode; 618c2ecf20Sopenharmony_ci enum stv0367_ter_mode mode;/* mode 2K or 8K */ 628c2ecf20Sopenharmony_ci enum fe_guard_interval guard; 638c2ecf20Sopenharmony_ci enum stv0367_ter_hierarchy hierarchy; 648c2ecf20Sopenharmony_ci u32 frequency; 658c2ecf20Sopenharmony_ci enum fe_spectral_inversion sense; /* current search spectrum */ 668c2ecf20Sopenharmony_ci u8 force; /* force mode/guard */ 678c2ecf20Sopenharmony_ci u8 bw; /* channel width 6, 7 or 8 in MHz */ 688c2ecf20Sopenharmony_ci u8 pBW; /* channel width used during previous lock */ 698c2ecf20Sopenharmony_ci u32 pBER; 708c2ecf20Sopenharmony_ci u32 pPER; 718c2ecf20Sopenharmony_ci u32 ucblocks; 728c2ecf20Sopenharmony_ci s8 echo_pos; /* echo position */ 738c2ecf20Sopenharmony_ci u8 first_lock; 748c2ecf20Sopenharmony_ci u8 unlock_counter; 758c2ecf20Sopenharmony_ci u32 agc_val; 768c2ecf20Sopenharmony_ci}; 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_cistruct stv0367_state { 798c2ecf20Sopenharmony_ci struct dvb_frontend fe; 808c2ecf20Sopenharmony_ci struct i2c_adapter *i2c; 818c2ecf20Sopenharmony_ci /* config settings */ 828c2ecf20Sopenharmony_ci const struct stv0367_config *config; 838c2ecf20Sopenharmony_ci u8 chip_id; 848c2ecf20Sopenharmony_ci /* DVB-C */ 858c2ecf20Sopenharmony_ci struct stv0367cab_state *cab_state; 868c2ecf20Sopenharmony_ci /* DVB-T */ 878c2ecf20Sopenharmony_ci struct stv0367ter_state *ter_state; 888c2ecf20Sopenharmony_ci /* flags for operation control */ 898c2ecf20Sopenharmony_ci u8 use_i2c_gatectrl; 908c2ecf20Sopenharmony_ci u8 deftabs; 918c2ecf20Sopenharmony_ci u8 reinit_on_setfrontend; 928c2ecf20Sopenharmony_ci u8 auto_if_khz; 938c2ecf20Sopenharmony_ci enum active_demod_state activedemod; 948c2ecf20Sopenharmony_ci}; 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_ci#define RF_LOOKUP_TABLE_SIZE 31 978c2ecf20Sopenharmony_ci#define RF_LOOKUP_TABLE2_SIZE 16 988c2ecf20Sopenharmony_ci/* RF Level (for RF AGC->AGC1) Lookup Table, depends on the board and tuner.*/ 998c2ecf20Sopenharmony_cistatic const s32 stv0367cab_RF_LookUp1[RF_LOOKUP_TABLE_SIZE][RF_LOOKUP_TABLE_SIZE] = { 1008c2ecf20Sopenharmony_ci {/*AGC1*/ 1018c2ecf20Sopenharmony_ci 48, 50, 51, 53, 54, 56, 57, 58, 60, 61, 62, 63, 1028c2ecf20Sopenharmony_ci 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 1038c2ecf20Sopenharmony_ci 76, 77, 78, 80, 83, 85, 88, 1048c2ecf20Sopenharmony_ci }, {/*RF(dbm)*/ 1058c2ecf20Sopenharmony_ci 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 1068c2ecf20Sopenharmony_ci 34, 35, 36, 37, 38, 39, 41, 42, 43, 44, 46, 47, 1078c2ecf20Sopenharmony_ci 49, 50, 52, 53, 54, 55, 56, 1088c2ecf20Sopenharmony_ci } 1098c2ecf20Sopenharmony_ci}; 1108c2ecf20Sopenharmony_ci/* RF Level (for IF AGC->AGC2) Lookup Table, depends on the board and tuner.*/ 1118c2ecf20Sopenharmony_cistatic const s32 stv0367cab_RF_LookUp2[RF_LOOKUP_TABLE2_SIZE][RF_LOOKUP_TABLE2_SIZE] = { 1128c2ecf20Sopenharmony_ci {/*AGC2*/ 1138c2ecf20Sopenharmony_ci 28, 29, 31, 32, 34, 35, 36, 37, 1148c2ecf20Sopenharmony_ci 38, 39, 40, 41, 42, 43, 44, 45, 1158c2ecf20Sopenharmony_ci }, {/*RF(dbm)*/ 1168c2ecf20Sopenharmony_ci 57, 58, 59, 60, 61, 62, 63, 64, 1178c2ecf20Sopenharmony_ci 65, 66, 67, 68, 69, 70, 71, 72, 1188c2ecf20Sopenharmony_ci } 1198c2ecf20Sopenharmony_ci}; 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_cistatic noinline_for_stack 1228c2ecf20Sopenharmony_ciint stv0367_writereg(struct stv0367_state *state, u16 reg, u8 data) 1238c2ecf20Sopenharmony_ci{ 1248c2ecf20Sopenharmony_ci u8 buf[3] = { MSB(reg), LSB(reg), data }; 1258c2ecf20Sopenharmony_ci struct i2c_msg msg = { 1268c2ecf20Sopenharmony_ci .addr = state->config->demod_address, 1278c2ecf20Sopenharmony_ci .flags = 0, 1288c2ecf20Sopenharmony_ci .buf = buf, 1298c2ecf20Sopenharmony_ci .len = 3, 1308c2ecf20Sopenharmony_ci }; 1318c2ecf20Sopenharmony_ci int ret; 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_ci if (i2cdebug) 1348c2ecf20Sopenharmony_ci printk(KERN_DEBUG "%s: [%02x] %02x: %02x\n", __func__, 1358c2ecf20Sopenharmony_ci state->config->demod_address, reg, data); 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci ret = i2c_transfer(state->i2c, &msg, 1); 1388c2ecf20Sopenharmony_ci if (ret != 1) 1398c2ecf20Sopenharmony_ci printk(KERN_ERR "%s: i2c write error! ([%02x] %02x: %02x)\n", 1408c2ecf20Sopenharmony_ci __func__, state->config->demod_address, reg, data); 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_ci return (ret != 1) ? -EREMOTEIO : 0; 1438c2ecf20Sopenharmony_ci} 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_cistatic noinline_for_stack 1468c2ecf20Sopenharmony_ciu8 stv0367_readreg(struct stv0367_state *state, u16 reg) 1478c2ecf20Sopenharmony_ci{ 1488c2ecf20Sopenharmony_ci u8 b0[] = { 0, 0 }; 1498c2ecf20Sopenharmony_ci u8 b1[] = { 0 }; 1508c2ecf20Sopenharmony_ci struct i2c_msg msg[] = { 1518c2ecf20Sopenharmony_ci { 1528c2ecf20Sopenharmony_ci .addr = state->config->demod_address, 1538c2ecf20Sopenharmony_ci .flags = 0, 1548c2ecf20Sopenharmony_ci .buf = b0, 1558c2ecf20Sopenharmony_ci .len = 2 1568c2ecf20Sopenharmony_ci }, { 1578c2ecf20Sopenharmony_ci .addr = state->config->demod_address, 1588c2ecf20Sopenharmony_ci .flags = I2C_M_RD, 1598c2ecf20Sopenharmony_ci .buf = b1, 1608c2ecf20Sopenharmony_ci .len = 1 1618c2ecf20Sopenharmony_ci } 1628c2ecf20Sopenharmony_ci }; 1638c2ecf20Sopenharmony_ci int ret; 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_ci b0[0] = MSB(reg); 1668c2ecf20Sopenharmony_ci b0[1] = LSB(reg); 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_ci ret = i2c_transfer(state->i2c, msg, 2); 1698c2ecf20Sopenharmony_ci if (ret != 2) 1708c2ecf20Sopenharmony_ci printk(KERN_ERR "%s: i2c read error ([%02x] %02x: %02x)\n", 1718c2ecf20Sopenharmony_ci __func__, state->config->demod_address, reg, b1[0]); 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_ci if (i2cdebug) 1748c2ecf20Sopenharmony_ci printk(KERN_DEBUG "%s: [%02x] %02x: %02x\n", __func__, 1758c2ecf20Sopenharmony_ci state->config->demod_address, reg, b1[0]); 1768c2ecf20Sopenharmony_ci 1778c2ecf20Sopenharmony_ci return b1[0]; 1788c2ecf20Sopenharmony_ci} 1798c2ecf20Sopenharmony_ci 1808c2ecf20Sopenharmony_cistatic void extract_mask_pos(u32 label, u8 *mask, u8 *pos) 1818c2ecf20Sopenharmony_ci{ 1828c2ecf20Sopenharmony_ci u8 position = 0, i = 0; 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_ci (*mask) = label & 0xff; 1858c2ecf20Sopenharmony_ci 1868c2ecf20Sopenharmony_ci while ((position == 0) && (i < 8)) { 1878c2ecf20Sopenharmony_ci position = ((*mask) >> i) & 0x01; 1888c2ecf20Sopenharmony_ci i++; 1898c2ecf20Sopenharmony_ci } 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_ci (*pos) = (i - 1); 1928c2ecf20Sopenharmony_ci} 1938c2ecf20Sopenharmony_ci 1948c2ecf20Sopenharmony_cistatic void stv0367_writebits(struct stv0367_state *state, u32 label, u8 val) 1958c2ecf20Sopenharmony_ci{ 1968c2ecf20Sopenharmony_ci u8 reg, mask, pos; 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_ci reg = stv0367_readreg(state, (label >> 16) & 0xffff); 1998c2ecf20Sopenharmony_ci extract_mask_pos(label, &mask, &pos); 2008c2ecf20Sopenharmony_ci 2018c2ecf20Sopenharmony_ci val = mask & (val << pos); 2028c2ecf20Sopenharmony_ci 2038c2ecf20Sopenharmony_ci reg = (reg & (~mask)) | val; 2048c2ecf20Sopenharmony_ci stv0367_writereg(state, (label >> 16) & 0xffff, reg); 2058c2ecf20Sopenharmony_ci 2068c2ecf20Sopenharmony_ci} 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_cistatic void stv0367_setbits(u8 *reg, u32 label, u8 val) 2098c2ecf20Sopenharmony_ci{ 2108c2ecf20Sopenharmony_ci u8 mask, pos; 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_ci extract_mask_pos(label, &mask, &pos); 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_ci val = mask & (val << pos); 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_ci (*reg) = ((*reg) & (~mask)) | val; 2178c2ecf20Sopenharmony_ci} 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_cistatic u8 stv0367_readbits(struct stv0367_state *state, u32 label) 2208c2ecf20Sopenharmony_ci{ 2218c2ecf20Sopenharmony_ci u8 val = 0xff; 2228c2ecf20Sopenharmony_ci u8 mask, pos; 2238c2ecf20Sopenharmony_ci 2248c2ecf20Sopenharmony_ci extract_mask_pos(label, &mask, &pos); 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_ci val = stv0367_readreg(state, label >> 16); 2278c2ecf20Sopenharmony_ci val = (val & mask) >> pos; 2288c2ecf20Sopenharmony_ci 2298c2ecf20Sopenharmony_ci return val; 2308c2ecf20Sopenharmony_ci} 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_ci#if 0 /* Currently, unused */ 2338c2ecf20Sopenharmony_cistatic u8 stv0367_getbits(u8 reg, u32 label) 2348c2ecf20Sopenharmony_ci{ 2358c2ecf20Sopenharmony_ci u8 mask, pos; 2368c2ecf20Sopenharmony_ci 2378c2ecf20Sopenharmony_ci extract_mask_pos(label, &mask, &pos); 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_ci return (reg & mask) >> pos; 2408c2ecf20Sopenharmony_ci} 2418c2ecf20Sopenharmony_ci#endif 2428c2ecf20Sopenharmony_ci 2438c2ecf20Sopenharmony_cistatic void stv0367_write_table(struct stv0367_state *state, 2448c2ecf20Sopenharmony_ci const struct st_register *deftab) 2458c2ecf20Sopenharmony_ci{ 2468c2ecf20Sopenharmony_ci int i = 0; 2478c2ecf20Sopenharmony_ci 2488c2ecf20Sopenharmony_ci while (1) { 2498c2ecf20Sopenharmony_ci if (!deftab[i].addr) 2508c2ecf20Sopenharmony_ci break; 2518c2ecf20Sopenharmony_ci stv0367_writereg(state, deftab[i].addr, deftab[i].value); 2528c2ecf20Sopenharmony_ci i++; 2538c2ecf20Sopenharmony_ci } 2548c2ecf20Sopenharmony_ci} 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_cistatic void stv0367_pll_setup(struct stv0367_state *state, 2578c2ecf20Sopenharmony_ci u32 icspeed, u32 xtal) 2588c2ecf20Sopenharmony_ci{ 2598c2ecf20Sopenharmony_ci /* note on regs: R367TER_* and R367CAB_* defines each point to 2608c2ecf20Sopenharmony_ci * 0xf0d8, so just use R367TER_ for both cases 2618c2ecf20Sopenharmony_ci */ 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_ci switch (icspeed) { 2648c2ecf20Sopenharmony_ci case STV0367_ICSPEED_58000: 2658c2ecf20Sopenharmony_ci switch (xtal) { 2668c2ecf20Sopenharmony_ci default: 2678c2ecf20Sopenharmony_ci case 27000000: 2688c2ecf20Sopenharmony_ci dprintk("STV0367 SetCLKgen for 58MHz IC and 27Mhz crystal\n"); 2698c2ecf20Sopenharmony_ci /* PLLMDIV: 27, PLLNDIV: 232 */ 2708c2ecf20Sopenharmony_ci stv0367_writereg(state, R367TER_PLLMDIV, 0x1b); 2718c2ecf20Sopenharmony_ci stv0367_writereg(state, R367TER_PLLNDIV, 0xe8); 2728c2ecf20Sopenharmony_ci break; 2738c2ecf20Sopenharmony_ci } 2748c2ecf20Sopenharmony_ci break; 2758c2ecf20Sopenharmony_ci default: 2768c2ecf20Sopenharmony_ci case STV0367_ICSPEED_53125: 2778c2ecf20Sopenharmony_ci switch (xtal) { 2788c2ecf20Sopenharmony_ci /* set internal freq to 53.125MHz */ 2798c2ecf20Sopenharmony_ci case 16000000: 2808c2ecf20Sopenharmony_ci stv0367_writereg(state, R367TER_PLLMDIV, 0x2); 2818c2ecf20Sopenharmony_ci stv0367_writereg(state, R367TER_PLLNDIV, 0x1b); 2828c2ecf20Sopenharmony_ci break; 2838c2ecf20Sopenharmony_ci case 25000000: 2848c2ecf20Sopenharmony_ci stv0367_writereg(state, R367TER_PLLMDIV, 0xa); 2858c2ecf20Sopenharmony_ci stv0367_writereg(state, R367TER_PLLNDIV, 0x55); 2868c2ecf20Sopenharmony_ci break; 2878c2ecf20Sopenharmony_ci default: 2888c2ecf20Sopenharmony_ci case 27000000: 2898c2ecf20Sopenharmony_ci dprintk("FE_STV0367TER_SetCLKgen for 27Mhz\n"); 2908c2ecf20Sopenharmony_ci stv0367_writereg(state, R367TER_PLLMDIV, 0x1); 2918c2ecf20Sopenharmony_ci stv0367_writereg(state, R367TER_PLLNDIV, 0x8); 2928c2ecf20Sopenharmony_ci break; 2938c2ecf20Sopenharmony_ci case 30000000: 2948c2ecf20Sopenharmony_ci stv0367_writereg(state, R367TER_PLLMDIV, 0xc); 2958c2ecf20Sopenharmony_ci stv0367_writereg(state, R367TER_PLLNDIV, 0x55); 2968c2ecf20Sopenharmony_ci break; 2978c2ecf20Sopenharmony_ci } 2988c2ecf20Sopenharmony_ci } 2998c2ecf20Sopenharmony_ci 3008c2ecf20Sopenharmony_ci stv0367_writereg(state, R367TER_PLLSETUP, 0x18); 3018c2ecf20Sopenharmony_ci} 3028c2ecf20Sopenharmony_ci 3038c2ecf20Sopenharmony_cistatic int stv0367_get_if_khz(struct stv0367_state *state, u32 *ifkhz) 3048c2ecf20Sopenharmony_ci{ 3058c2ecf20Sopenharmony_ci if (state->auto_if_khz && state->fe.ops.tuner_ops.get_if_frequency) { 3068c2ecf20Sopenharmony_ci state->fe.ops.tuner_ops.get_if_frequency(&state->fe, ifkhz); 3078c2ecf20Sopenharmony_ci *ifkhz = *ifkhz / 1000; /* hz -> khz */ 3088c2ecf20Sopenharmony_ci } else 3098c2ecf20Sopenharmony_ci *ifkhz = state->config->if_khz; 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_ci return 0; 3128c2ecf20Sopenharmony_ci} 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_cistatic int stv0367ter_gate_ctrl(struct dvb_frontend *fe, int enable) 3158c2ecf20Sopenharmony_ci{ 3168c2ecf20Sopenharmony_ci struct stv0367_state *state = fe->demodulator_priv; 3178c2ecf20Sopenharmony_ci u8 tmp = stv0367_readreg(state, R367TER_I2CRPT); 3188c2ecf20Sopenharmony_ci 3198c2ecf20Sopenharmony_ci dprintk("%s:\n", __func__); 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_ci if (enable) { 3228c2ecf20Sopenharmony_ci stv0367_setbits(&tmp, F367TER_STOP_ENABLE, 0); 3238c2ecf20Sopenharmony_ci stv0367_setbits(&tmp, F367TER_I2CT_ON, 1); 3248c2ecf20Sopenharmony_ci } else { 3258c2ecf20Sopenharmony_ci stv0367_setbits(&tmp, F367TER_STOP_ENABLE, 1); 3268c2ecf20Sopenharmony_ci stv0367_setbits(&tmp, F367TER_I2CT_ON, 0); 3278c2ecf20Sopenharmony_ci } 3288c2ecf20Sopenharmony_ci 3298c2ecf20Sopenharmony_ci stv0367_writereg(state, R367TER_I2CRPT, tmp); 3308c2ecf20Sopenharmony_ci 3318c2ecf20Sopenharmony_ci return 0; 3328c2ecf20Sopenharmony_ci} 3338c2ecf20Sopenharmony_ci 3348c2ecf20Sopenharmony_cistatic u32 stv0367_get_tuner_freq(struct dvb_frontend *fe) 3358c2ecf20Sopenharmony_ci{ 3368c2ecf20Sopenharmony_ci struct dvb_frontend_ops *frontend_ops = &fe->ops; 3378c2ecf20Sopenharmony_ci struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops; 3388c2ecf20Sopenharmony_ci u32 freq = 0; 3398c2ecf20Sopenharmony_ci int err = 0; 3408c2ecf20Sopenharmony_ci 3418c2ecf20Sopenharmony_ci dprintk("%s:\n", __func__); 3428c2ecf20Sopenharmony_ci 3438c2ecf20Sopenharmony_ci if (tuner_ops->get_frequency) { 3448c2ecf20Sopenharmony_ci err = tuner_ops->get_frequency(fe, &freq); 3458c2ecf20Sopenharmony_ci if (err < 0) { 3468c2ecf20Sopenharmony_ci printk(KERN_ERR "%s: Invalid parameter\n", __func__); 3478c2ecf20Sopenharmony_ci return err; 3488c2ecf20Sopenharmony_ci } 3498c2ecf20Sopenharmony_ci 3508c2ecf20Sopenharmony_ci dprintk("%s: frequency=%d\n", __func__, freq); 3518c2ecf20Sopenharmony_ci 3528c2ecf20Sopenharmony_ci } else 3538c2ecf20Sopenharmony_ci return -1; 3548c2ecf20Sopenharmony_ci 3558c2ecf20Sopenharmony_ci return freq; 3568c2ecf20Sopenharmony_ci} 3578c2ecf20Sopenharmony_ci 3588c2ecf20Sopenharmony_cistatic u16 CellsCoeffs_8MHz_367cofdm[3][6][5] = { 3598c2ecf20Sopenharmony_ci { 3608c2ecf20Sopenharmony_ci {0x10EF, 0xE205, 0x10EF, 0xCE49, 0x6DA7}, /* CELL 1 COEFFS 27M*/ 3618c2ecf20Sopenharmony_ci {0x2151, 0xc557, 0x2151, 0xc705, 0x6f93}, /* CELL 2 COEFFS */ 3628c2ecf20Sopenharmony_ci {0x2503, 0xc000, 0x2503, 0xc375, 0x7194}, /* CELL 3 COEFFS */ 3638c2ecf20Sopenharmony_ci {0x20E9, 0xca94, 0x20e9, 0xc153, 0x7194}, /* CELL 4 COEFFS */ 3648c2ecf20Sopenharmony_ci {0x06EF, 0xF852, 0x06EF, 0xC057, 0x7207}, /* CELL 5 COEFFS */ 3658c2ecf20Sopenharmony_ci {0x0000, 0x0ECC, 0x0ECC, 0x0000, 0x3647} /* CELL 6 COEFFS */ 3668c2ecf20Sopenharmony_ci }, { 3678c2ecf20Sopenharmony_ci {0x10A0, 0xE2AF, 0x10A1, 0xCE76, 0x6D6D}, /* CELL 1 COEFFS 25M*/ 3688c2ecf20Sopenharmony_ci {0x20DC, 0xC676, 0x20D9, 0xC80A, 0x6F29}, 3698c2ecf20Sopenharmony_ci {0x2532, 0xC000, 0x251D, 0xC391, 0x706F}, 3708c2ecf20Sopenharmony_ci {0x1F7A, 0xCD2B, 0x2032, 0xC15E, 0x711F}, 3718c2ecf20Sopenharmony_ci {0x0698, 0xFA5E, 0x0568, 0xC059, 0x7193}, 3728c2ecf20Sopenharmony_ci {0x0000, 0x0918, 0x149C, 0x0000, 0x3642} /* CELL 6 COEFFS */ 3738c2ecf20Sopenharmony_ci }, { 3748c2ecf20Sopenharmony_ci {0x0000, 0x0000, 0x0000, 0x0000, 0x0000}, /* 30M */ 3758c2ecf20Sopenharmony_ci {0x0000, 0x0000, 0x0000, 0x0000, 0x0000}, 3768c2ecf20Sopenharmony_ci {0x0000, 0x0000, 0x0000, 0x0000, 0x0000}, 3778c2ecf20Sopenharmony_ci {0x0000, 0x0000, 0x0000, 0x0000, 0x0000}, 3788c2ecf20Sopenharmony_ci {0x0000, 0x0000, 0x0000, 0x0000, 0x0000}, 3798c2ecf20Sopenharmony_ci {0x0000, 0x0000, 0x0000, 0x0000, 0x0000} 3808c2ecf20Sopenharmony_ci } 3818c2ecf20Sopenharmony_ci}; 3828c2ecf20Sopenharmony_ci 3838c2ecf20Sopenharmony_cistatic u16 CellsCoeffs_7MHz_367cofdm[3][6][5] = { 3848c2ecf20Sopenharmony_ci { 3858c2ecf20Sopenharmony_ci {0x12CA, 0xDDAF, 0x12CA, 0xCCEB, 0x6FB1}, /* CELL 1 COEFFS 27M*/ 3868c2ecf20Sopenharmony_ci {0x2329, 0xC000, 0x2329, 0xC6B0, 0x725F}, /* CELL 2 COEFFS */ 3878c2ecf20Sopenharmony_ci {0x2394, 0xC000, 0x2394, 0xC2C7, 0x7410}, /* CELL 3 COEFFS */ 3888c2ecf20Sopenharmony_ci {0x251C, 0xC000, 0x251C, 0xC103, 0x74D9}, /* CELL 4 COEFFS */ 3898c2ecf20Sopenharmony_ci {0x0804, 0xF546, 0x0804, 0xC040, 0x7544}, /* CELL 5 COEFFS */ 3908c2ecf20Sopenharmony_ci {0x0000, 0x0CD9, 0x0CD9, 0x0000, 0x370A} /* CELL 6 COEFFS */ 3918c2ecf20Sopenharmony_ci }, { 3928c2ecf20Sopenharmony_ci {0x1285, 0xDE47, 0x1285, 0xCD17, 0x6F76}, /*25M*/ 3938c2ecf20Sopenharmony_ci {0x234C, 0xC000, 0x2348, 0xC6DA, 0x7206}, 3948c2ecf20Sopenharmony_ci {0x23B4, 0xC000, 0x23AC, 0xC2DB, 0x73B3}, 3958c2ecf20Sopenharmony_ci {0x253D, 0xC000, 0x25B6, 0xC10B, 0x747F}, 3968c2ecf20Sopenharmony_ci {0x0721, 0xF79C, 0x065F, 0xC041, 0x74EB}, 3978c2ecf20Sopenharmony_ci {0x0000, 0x08FA, 0x1162, 0x0000, 0x36FF} 3988c2ecf20Sopenharmony_ci }, { 3998c2ecf20Sopenharmony_ci {0x0000, 0x0000, 0x0000, 0x0000, 0x0000}, /* 30M */ 4008c2ecf20Sopenharmony_ci {0x0000, 0x0000, 0x0000, 0x0000, 0x0000}, 4018c2ecf20Sopenharmony_ci {0x0000, 0x0000, 0x0000, 0x0000, 0x0000}, 4028c2ecf20Sopenharmony_ci {0x0000, 0x0000, 0x0000, 0x0000, 0x0000}, 4038c2ecf20Sopenharmony_ci {0x0000, 0x0000, 0x0000, 0x0000, 0x0000}, 4048c2ecf20Sopenharmony_ci {0x0000, 0x0000, 0x0000, 0x0000, 0x0000} 4058c2ecf20Sopenharmony_ci } 4068c2ecf20Sopenharmony_ci}; 4078c2ecf20Sopenharmony_ci 4088c2ecf20Sopenharmony_cistatic u16 CellsCoeffs_6MHz_367cofdm[3][6][5] = { 4098c2ecf20Sopenharmony_ci { 4108c2ecf20Sopenharmony_ci {0x1699, 0xD5B8, 0x1699, 0xCBC3, 0x713B}, /* CELL 1 COEFFS 27M*/ 4118c2ecf20Sopenharmony_ci {0x2245, 0xC000, 0x2245, 0xC568, 0x74D5}, /* CELL 2 COEFFS */ 4128c2ecf20Sopenharmony_ci {0x227F, 0xC000, 0x227F, 0xC1FC, 0x76C6}, /* CELL 3 COEFFS */ 4138c2ecf20Sopenharmony_ci {0x235E, 0xC000, 0x235E, 0xC0A7, 0x778A}, /* CELL 4 COEFFS */ 4148c2ecf20Sopenharmony_ci {0x0ECB, 0xEA0B, 0x0ECB, 0xC027, 0x77DD}, /* CELL 5 COEFFS */ 4158c2ecf20Sopenharmony_ci {0x0000, 0x0B68, 0x0B68, 0x0000, 0xC89A}, /* CELL 6 COEFFS */ 4168c2ecf20Sopenharmony_ci }, { 4178c2ecf20Sopenharmony_ci {0x1655, 0xD64E, 0x1658, 0xCBEF, 0x70FE}, /*25M*/ 4188c2ecf20Sopenharmony_ci {0x225E, 0xC000, 0x2256, 0xC589, 0x7489}, 4198c2ecf20Sopenharmony_ci {0x2293, 0xC000, 0x2295, 0xC209, 0x767E}, 4208c2ecf20Sopenharmony_ci {0x2377, 0xC000, 0x23AA, 0xC0AB, 0x7746}, 4218c2ecf20Sopenharmony_ci {0x0DC7, 0xEBC8, 0x0D07, 0xC027, 0x7799}, 4228c2ecf20Sopenharmony_ci {0x0000, 0x0888, 0x0E9C, 0x0000, 0x3757} 4238c2ecf20Sopenharmony_ci 4248c2ecf20Sopenharmony_ci }, { 4258c2ecf20Sopenharmony_ci {0x0000, 0x0000, 0x0000, 0x0000, 0x0000}, /* 30M */ 4268c2ecf20Sopenharmony_ci {0x0000, 0x0000, 0x0000, 0x0000, 0x0000}, 4278c2ecf20Sopenharmony_ci {0x0000, 0x0000, 0x0000, 0x0000, 0x0000}, 4288c2ecf20Sopenharmony_ci {0x0000, 0x0000, 0x0000, 0x0000, 0x0000}, 4298c2ecf20Sopenharmony_ci {0x0000, 0x0000, 0x0000, 0x0000, 0x0000}, 4308c2ecf20Sopenharmony_ci {0x0000, 0x0000, 0x0000, 0x0000, 0x0000} 4318c2ecf20Sopenharmony_ci } 4328c2ecf20Sopenharmony_ci}; 4338c2ecf20Sopenharmony_ci 4348c2ecf20Sopenharmony_cistatic u32 stv0367ter_get_mclk(struct stv0367_state *state, u32 ExtClk_Hz) 4358c2ecf20Sopenharmony_ci{ 4368c2ecf20Sopenharmony_ci u32 mclk_Hz = 0; /* master clock frequency (Hz) */ 4378c2ecf20Sopenharmony_ci u32 m, n, p; 4388c2ecf20Sopenharmony_ci 4398c2ecf20Sopenharmony_ci dprintk("%s:\n", __func__); 4408c2ecf20Sopenharmony_ci 4418c2ecf20Sopenharmony_ci if (stv0367_readbits(state, F367TER_BYPASS_PLLXN) == 0) { 4428c2ecf20Sopenharmony_ci n = (u32)stv0367_readbits(state, F367TER_PLL_NDIV); 4438c2ecf20Sopenharmony_ci if (n == 0) 4448c2ecf20Sopenharmony_ci n = n + 1; 4458c2ecf20Sopenharmony_ci 4468c2ecf20Sopenharmony_ci m = (u32)stv0367_readbits(state, F367TER_PLL_MDIV); 4478c2ecf20Sopenharmony_ci if (m == 0) 4488c2ecf20Sopenharmony_ci m = m + 1; 4498c2ecf20Sopenharmony_ci 4508c2ecf20Sopenharmony_ci p = (u32)stv0367_readbits(state, F367TER_PLL_PDIV); 4518c2ecf20Sopenharmony_ci if (p > 5) 4528c2ecf20Sopenharmony_ci p = 5; 4538c2ecf20Sopenharmony_ci 4548c2ecf20Sopenharmony_ci mclk_Hz = ((ExtClk_Hz / 2) * n) / (m * (1 << p)); 4558c2ecf20Sopenharmony_ci 4568c2ecf20Sopenharmony_ci dprintk("N=%d M=%d P=%d mclk_Hz=%d ExtClk_Hz=%d\n", 4578c2ecf20Sopenharmony_ci n, m, p, mclk_Hz, ExtClk_Hz); 4588c2ecf20Sopenharmony_ci } else 4598c2ecf20Sopenharmony_ci mclk_Hz = ExtClk_Hz; 4608c2ecf20Sopenharmony_ci 4618c2ecf20Sopenharmony_ci dprintk("%s: mclk_Hz=%d\n", __func__, mclk_Hz); 4628c2ecf20Sopenharmony_ci 4638c2ecf20Sopenharmony_ci return mclk_Hz; 4648c2ecf20Sopenharmony_ci} 4658c2ecf20Sopenharmony_ci 4668c2ecf20Sopenharmony_cistatic int stv0367ter_filt_coeff_init(struct stv0367_state *state, 4678c2ecf20Sopenharmony_ci u16 CellsCoeffs[3][6][5], u32 DemodXtal) 4688c2ecf20Sopenharmony_ci{ 4698c2ecf20Sopenharmony_ci int i, j, k, freq; 4708c2ecf20Sopenharmony_ci 4718c2ecf20Sopenharmony_ci dprintk("%s:\n", __func__); 4728c2ecf20Sopenharmony_ci 4738c2ecf20Sopenharmony_ci freq = stv0367ter_get_mclk(state, DemodXtal); 4748c2ecf20Sopenharmony_ci 4758c2ecf20Sopenharmony_ci if (freq == 53125000) 4768c2ecf20Sopenharmony_ci k = 1; /* equivalent to Xtal 25M on 362*/ 4778c2ecf20Sopenharmony_ci else if (freq == 54000000) 4788c2ecf20Sopenharmony_ci k = 0; /* equivalent to Xtal 27M on 362*/ 4798c2ecf20Sopenharmony_ci else if (freq == 52500000) 4808c2ecf20Sopenharmony_ci k = 2; /* equivalent to Xtal 30M on 362*/ 4818c2ecf20Sopenharmony_ci else 4828c2ecf20Sopenharmony_ci return 0; 4838c2ecf20Sopenharmony_ci 4848c2ecf20Sopenharmony_ci for (i = 1; i <= 6; i++) { 4858c2ecf20Sopenharmony_ci stv0367_writebits(state, F367TER_IIR_CELL_NB, i - 1); 4868c2ecf20Sopenharmony_ci 4878c2ecf20Sopenharmony_ci for (j = 1; j <= 5; j++) { 4888c2ecf20Sopenharmony_ci stv0367_writereg(state, 4898c2ecf20Sopenharmony_ci (R367TER_IIRCX_COEFF1_MSB + 2 * (j - 1)), 4908c2ecf20Sopenharmony_ci MSB(CellsCoeffs[k][i-1][j-1])); 4918c2ecf20Sopenharmony_ci stv0367_writereg(state, 4928c2ecf20Sopenharmony_ci (R367TER_IIRCX_COEFF1_LSB + 2 * (j - 1)), 4938c2ecf20Sopenharmony_ci LSB(CellsCoeffs[k][i-1][j-1])); 4948c2ecf20Sopenharmony_ci } 4958c2ecf20Sopenharmony_ci } 4968c2ecf20Sopenharmony_ci 4978c2ecf20Sopenharmony_ci return 1; 4988c2ecf20Sopenharmony_ci 4998c2ecf20Sopenharmony_ci} 5008c2ecf20Sopenharmony_ci 5018c2ecf20Sopenharmony_cistatic void stv0367ter_agc_iir_lock_detect_set(struct stv0367_state *state) 5028c2ecf20Sopenharmony_ci{ 5038c2ecf20Sopenharmony_ci dprintk("%s:\n", __func__); 5048c2ecf20Sopenharmony_ci 5058c2ecf20Sopenharmony_ci stv0367_writebits(state, F367TER_LOCK_DETECT_LSB, 0x00); 5068c2ecf20Sopenharmony_ci 5078c2ecf20Sopenharmony_ci /* Lock detect 1 */ 5088c2ecf20Sopenharmony_ci stv0367_writebits(state, F367TER_LOCK_DETECT_CHOICE, 0x00); 5098c2ecf20Sopenharmony_ci stv0367_writebits(state, F367TER_LOCK_DETECT_MSB, 0x06); 5108c2ecf20Sopenharmony_ci stv0367_writebits(state, F367TER_AUT_AGC_TARGET_LSB, 0x04); 5118c2ecf20Sopenharmony_ci 5128c2ecf20Sopenharmony_ci /* Lock detect 2 */ 5138c2ecf20Sopenharmony_ci stv0367_writebits(state, F367TER_LOCK_DETECT_CHOICE, 0x01); 5148c2ecf20Sopenharmony_ci stv0367_writebits(state, F367TER_LOCK_DETECT_MSB, 0x06); 5158c2ecf20Sopenharmony_ci stv0367_writebits(state, F367TER_AUT_AGC_TARGET_LSB, 0x04); 5168c2ecf20Sopenharmony_ci 5178c2ecf20Sopenharmony_ci /* Lock detect 3 */ 5188c2ecf20Sopenharmony_ci stv0367_writebits(state, F367TER_LOCK_DETECT_CHOICE, 0x02); 5198c2ecf20Sopenharmony_ci stv0367_writebits(state, F367TER_LOCK_DETECT_MSB, 0x01); 5208c2ecf20Sopenharmony_ci stv0367_writebits(state, F367TER_AUT_AGC_TARGET_LSB, 0x00); 5218c2ecf20Sopenharmony_ci 5228c2ecf20Sopenharmony_ci /* Lock detect 4 */ 5238c2ecf20Sopenharmony_ci stv0367_writebits(state, F367TER_LOCK_DETECT_CHOICE, 0x03); 5248c2ecf20Sopenharmony_ci stv0367_writebits(state, F367TER_LOCK_DETECT_MSB, 0x01); 5258c2ecf20Sopenharmony_ci stv0367_writebits(state, F367TER_AUT_AGC_TARGET_LSB, 0x00); 5268c2ecf20Sopenharmony_ci 5278c2ecf20Sopenharmony_ci} 5288c2ecf20Sopenharmony_ci 5298c2ecf20Sopenharmony_cistatic int stv0367_iir_filt_init(struct stv0367_state *state, u8 Bandwidth, 5308c2ecf20Sopenharmony_ci u32 DemodXtalValue) 5318c2ecf20Sopenharmony_ci{ 5328c2ecf20Sopenharmony_ci dprintk("%s:\n", __func__); 5338c2ecf20Sopenharmony_ci 5348c2ecf20Sopenharmony_ci stv0367_writebits(state, F367TER_NRST_IIR, 0); 5358c2ecf20Sopenharmony_ci 5368c2ecf20Sopenharmony_ci switch (Bandwidth) { 5378c2ecf20Sopenharmony_ci case 6: 5388c2ecf20Sopenharmony_ci if (!stv0367ter_filt_coeff_init(state, 5398c2ecf20Sopenharmony_ci CellsCoeffs_6MHz_367cofdm, 5408c2ecf20Sopenharmony_ci DemodXtalValue)) 5418c2ecf20Sopenharmony_ci return 0; 5428c2ecf20Sopenharmony_ci break; 5438c2ecf20Sopenharmony_ci case 7: 5448c2ecf20Sopenharmony_ci if (!stv0367ter_filt_coeff_init(state, 5458c2ecf20Sopenharmony_ci CellsCoeffs_7MHz_367cofdm, 5468c2ecf20Sopenharmony_ci DemodXtalValue)) 5478c2ecf20Sopenharmony_ci return 0; 5488c2ecf20Sopenharmony_ci break; 5498c2ecf20Sopenharmony_ci case 8: 5508c2ecf20Sopenharmony_ci if (!stv0367ter_filt_coeff_init(state, 5518c2ecf20Sopenharmony_ci CellsCoeffs_8MHz_367cofdm, 5528c2ecf20Sopenharmony_ci DemodXtalValue)) 5538c2ecf20Sopenharmony_ci return 0; 5548c2ecf20Sopenharmony_ci break; 5558c2ecf20Sopenharmony_ci default: 5568c2ecf20Sopenharmony_ci return 0; 5578c2ecf20Sopenharmony_ci } 5588c2ecf20Sopenharmony_ci 5598c2ecf20Sopenharmony_ci stv0367_writebits(state, F367TER_NRST_IIR, 1); 5608c2ecf20Sopenharmony_ci 5618c2ecf20Sopenharmony_ci return 1; 5628c2ecf20Sopenharmony_ci} 5638c2ecf20Sopenharmony_ci 5648c2ecf20Sopenharmony_cistatic void stv0367ter_agc_iir_rst(struct stv0367_state *state) 5658c2ecf20Sopenharmony_ci{ 5668c2ecf20Sopenharmony_ci 5678c2ecf20Sopenharmony_ci u8 com_n; 5688c2ecf20Sopenharmony_ci 5698c2ecf20Sopenharmony_ci dprintk("%s:\n", __func__); 5708c2ecf20Sopenharmony_ci 5718c2ecf20Sopenharmony_ci com_n = stv0367_readbits(state, F367TER_COM_N); 5728c2ecf20Sopenharmony_ci 5738c2ecf20Sopenharmony_ci stv0367_writebits(state, F367TER_COM_N, 0x07); 5748c2ecf20Sopenharmony_ci 5758c2ecf20Sopenharmony_ci stv0367_writebits(state, F367TER_COM_SOFT_RSTN, 0x00); 5768c2ecf20Sopenharmony_ci stv0367_writebits(state, F367TER_COM_AGC_ON, 0x00); 5778c2ecf20Sopenharmony_ci 5788c2ecf20Sopenharmony_ci stv0367_writebits(state, F367TER_COM_SOFT_RSTN, 0x01); 5798c2ecf20Sopenharmony_ci stv0367_writebits(state, F367TER_COM_AGC_ON, 0x01); 5808c2ecf20Sopenharmony_ci 5818c2ecf20Sopenharmony_ci stv0367_writebits(state, F367TER_COM_N, com_n); 5828c2ecf20Sopenharmony_ci 5838c2ecf20Sopenharmony_ci} 5848c2ecf20Sopenharmony_ci 5858c2ecf20Sopenharmony_cistatic int stv0367ter_duration(s32 mode, int tempo1, int tempo2, int tempo3) 5868c2ecf20Sopenharmony_ci{ 5878c2ecf20Sopenharmony_ci int local_tempo = 0; 5888c2ecf20Sopenharmony_ci switch (mode) { 5898c2ecf20Sopenharmony_ci case 0: 5908c2ecf20Sopenharmony_ci local_tempo = tempo1; 5918c2ecf20Sopenharmony_ci break; 5928c2ecf20Sopenharmony_ci case 1: 5938c2ecf20Sopenharmony_ci local_tempo = tempo2; 5948c2ecf20Sopenharmony_ci break ; 5958c2ecf20Sopenharmony_ci 5968c2ecf20Sopenharmony_ci case 2: 5978c2ecf20Sopenharmony_ci local_tempo = tempo3; 5988c2ecf20Sopenharmony_ci break; 5998c2ecf20Sopenharmony_ci 6008c2ecf20Sopenharmony_ci default: 6018c2ecf20Sopenharmony_ci break; 6028c2ecf20Sopenharmony_ci } 6038c2ecf20Sopenharmony_ci /* msleep(local_tempo); */ 6048c2ecf20Sopenharmony_ci return local_tempo; 6058c2ecf20Sopenharmony_ci} 6068c2ecf20Sopenharmony_ci 6078c2ecf20Sopenharmony_cistatic enum 6088c2ecf20Sopenharmony_cistv0367_ter_signal_type stv0367ter_check_syr(struct stv0367_state *state) 6098c2ecf20Sopenharmony_ci{ 6108c2ecf20Sopenharmony_ci int wd = 100; 6118c2ecf20Sopenharmony_ci unsigned short int SYR_var; 6128c2ecf20Sopenharmony_ci s32 SYRStatus; 6138c2ecf20Sopenharmony_ci 6148c2ecf20Sopenharmony_ci dprintk("%s:\n", __func__); 6158c2ecf20Sopenharmony_ci 6168c2ecf20Sopenharmony_ci SYR_var = stv0367_readbits(state, F367TER_SYR_LOCK); 6178c2ecf20Sopenharmony_ci 6188c2ecf20Sopenharmony_ci while ((!SYR_var) && (wd > 0)) { 6198c2ecf20Sopenharmony_ci usleep_range(2000, 3000); 6208c2ecf20Sopenharmony_ci wd -= 2; 6218c2ecf20Sopenharmony_ci SYR_var = stv0367_readbits(state, F367TER_SYR_LOCK); 6228c2ecf20Sopenharmony_ci } 6238c2ecf20Sopenharmony_ci 6248c2ecf20Sopenharmony_ci if (!SYR_var) 6258c2ecf20Sopenharmony_ci SYRStatus = FE_TER_NOSYMBOL; 6268c2ecf20Sopenharmony_ci else 6278c2ecf20Sopenharmony_ci SYRStatus = FE_TER_SYMBOLOK; 6288c2ecf20Sopenharmony_ci 6298c2ecf20Sopenharmony_ci dprintk("stv0367ter_check_syr SYRStatus %s\n", 6308c2ecf20Sopenharmony_ci SYR_var == 0 ? "No Symbol" : "OK"); 6318c2ecf20Sopenharmony_ci 6328c2ecf20Sopenharmony_ci return SYRStatus; 6338c2ecf20Sopenharmony_ci} 6348c2ecf20Sopenharmony_ci 6358c2ecf20Sopenharmony_cistatic enum 6368c2ecf20Sopenharmony_cistv0367_ter_signal_type stv0367ter_check_cpamp(struct stv0367_state *state, 6378c2ecf20Sopenharmony_ci s32 FFTmode) 6388c2ecf20Sopenharmony_ci{ 6398c2ecf20Sopenharmony_ci 6408c2ecf20Sopenharmony_ci s32 CPAMPvalue = 0, CPAMPStatus, CPAMPMin; 6418c2ecf20Sopenharmony_ci int wd = 0; 6428c2ecf20Sopenharmony_ci 6438c2ecf20Sopenharmony_ci dprintk("%s:\n", __func__); 6448c2ecf20Sopenharmony_ci 6458c2ecf20Sopenharmony_ci switch (FFTmode) { 6468c2ecf20Sopenharmony_ci case 0: /*2k mode*/ 6478c2ecf20Sopenharmony_ci CPAMPMin = 20; 6488c2ecf20Sopenharmony_ci wd = 10; 6498c2ecf20Sopenharmony_ci break; 6508c2ecf20Sopenharmony_ci case 1: /*8k mode*/ 6518c2ecf20Sopenharmony_ci CPAMPMin = 80; 6528c2ecf20Sopenharmony_ci wd = 55; 6538c2ecf20Sopenharmony_ci break; 6548c2ecf20Sopenharmony_ci case 2: /*4k mode*/ 6558c2ecf20Sopenharmony_ci CPAMPMin = 40; 6568c2ecf20Sopenharmony_ci wd = 30; 6578c2ecf20Sopenharmony_ci break; 6588c2ecf20Sopenharmony_ci default: 6598c2ecf20Sopenharmony_ci CPAMPMin = 0xffff; /*drives to NOCPAMP */ 6608c2ecf20Sopenharmony_ci break; 6618c2ecf20Sopenharmony_ci } 6628c2ecf20Sopenharmony_ci 6638c2ecf20Sopenharmony_ci dprintk("%s: CPAMPMin=%d wd=%d\n", __func__, CPAMPMin, wd); 6648c2ecf20Sopenharmony_ci 6658c2ecf20Sopenharmony_ci CPAMPvalue = stv0367_readbits(state, F367TER_PPM_CPAMP_DIRECT); 6668c2ecf20Sopenharmony_ci while ((CPAMPvalue < CPAMPMin) && (wd > 0)) { 6678c2ecf20Sopenharmony_ci usleep_range(1000, 2000); 6688c2ecf20Sopenharmony_ci wd -= 1; 6698c2ecf20Sopenharmony_ci CPAMPvalue = stv0367_readbits(state, F367TER_PPM_CPAMP_DIRECT); 6708c2ecf20Sopenharmony_ci /*dprintk("CPAMPvalue= %d at wd=%d\n",CPAMPvalue,wd); */ 6718c2ecf20Sopenharmony_ci } 6728c2ecf20Sopenharmony_ci dprintk("******last CPAMPvalue= %d at wd=%d\n", CPAMPvalue, wd); 6738c2ecf20Sopenharmony_ci if (CPAMPvalue < CPAMPMin) { 6748c2ecf20Sopenharmony_ci CPAMPStatus = FE_TER_NOCPAMP; 6758c2ecf20Sopenharmony_ci dprintk("%s: CPAMP failed\n", __func__); 6768c2ecf20Sopenharmony_ci } else { 6778c2ecf20Sopenharmony_ci dprintk("%s: CPAMP OK !\n", __func__); 6788c2ecf20Sopenharmony_ci CPAMPStatus = FE_TER_CPAMPOK; 6798c2ecf20Sopenharmony_ci } 6808c2ecf20Sopenharmony_ci 6818c2ecf20Sopenharmony_ci return CPAMPStatus; 6828c2ecf20Sopenharmony_ci} 6838c2ecf20Sopenharmony_ci 6848c2ecf20Sopenharmony_cistatic enum stv0367_ter_signal_type 6858c2ecf20Sopenharmony_cistv0367ter_lock_algo(struct stv0367_state *state) 6868c2ecf20Sopenharmony_ci{ 6878c2ecf20Sopenharmony_ci enum stv0367_ter_signal_type ret_flag; 6888c2ecf20Sopenharmony_ci short int wd, tempo; 6898c2ecf20Sopenharmony_ci u8 try, u_var1 = 0, u_var2 = 0, u_var3 = 0, u_var4 = 0, mode, guard; 6908c2ecf20Sopenharmony_ci u8 tmp, tmp2; 6918c2ecf20Sopenharmony_ci 6928c2ecf20Sopenharmony_ci dprintk("%s:\n", __func__); 6938c2ecf20Sopenharmony_ci 6948c2ecf20Sopenharmony_ci if (state == NULL) 6958c2ecf20Sopenharmony_ci return FE_TER_SWNOK; 6968c2ecf20Sopenharmony_ci 6978c2ecf20Sopenharmony_ci try = 0; 6988c2ecf20Sopenharmony_ci do { 6998c2ecf20Sopenharmony_ci ret_flag = FE_TER_LOCKOK; 7008c2ecf20Sopenharmony_ci 7018c2ecf20Sopenharmony_ci stv0367_writebits(state, F367TER_CORE_ACTIVE, 0); 7028c2ecf20Sopenharmony_ci 7038c2ecf20Sopenharmony_ci if (state->config->if_iq_mode != 0) 7048c2ecf20Sopenharmony_ci stv0367_writebits(state, F367TER_COM_N, 0x07); 7058c2ecf20Sopenharmony_ci 7068c2ecf20Sopenharmony_ci stv0367_writebits(state, F367TER_GUARD, 3);/* suggest 2k 1/4 */ 7078c2ecf20Sopenharmony_ci stv0367_writebits(state, F367TER_MODE, 0); 7088c2ecf20Sopenharmony_ci stv0367_writebits(state, F367TER_SYR_TR_DIS, 0); 7098c2ecf20Sopenharmony_ci usleep_range(5000, 10000); 7108c2ecf20Sopenharmony_ci 7118c2ecf20Sopenharmony_ci stv0367_writebits(state, F367TER_CORE_ACTIVE, 1); 7128c2ecf20Sopenharmony_ci 7138c2ecf20Sopenharmony_ci 7148c2ecf20Sopenharmony_ci if (stv0367ter_check_syr(state) == FE_TER_NOSYMBOL) 7158c2ecf20Sopenharmony_ci return FE_TER_NOSYMBOL; 7168c2ecf20Sopenharmony_ci else { /* 7178c2ecf20Sopenharmony_ci if chip locked on wrong mode first try, 7188c2ecf20Sopenharmony_ci it must lock correctly second try */ 7198c2ecf20Sopenharmony_ci mode = stv0367_readbits(state, F367TER_SYR_MODE); 7208c2ecf20Sopenharmony_ci if (stv0367ter_check_cpamp(state, mode) == 7218c2ecf20Sopenharmony_ci FE_TER_NOCPAMP) { 7228c2ecf20Sopenharmony_ci if (try == 0) 7238c2ecf20Sopenharmony_ci ret_flag = FE_TER_NOCPAMP; 7248c2ecf20Sopenharmony_ci 7258c2ecf20Sopenharmony_ci } 7268c2ecf20Sopenharmony_ci } 7278c2ecf20Sopenharmony_ci 7288c2ecf20Sopenharmony_ci try++; 7298c2ecf20Sopenharmony_ci } while ((try < 10) && (ret_flag != FE_TER_LOCKOK)); 7308c2ecf20Sopenharmony_ci 7318c2ecf20Sopenharmony_ci tmp = stv0367_readreg(state, R367TER_SYR_STAT); 7328c2ecf20Sopenharmony_ci tmp2 = stv0367_readreg(state, R367TER_STATUS); 7338c2ecf20Sopenharmony_ci dprintk("state=%p\n", state); 7348c2ecf20Sopenharmony_ci dprintk("LOCK OK! mode=%d SYR_STAT=0x%x R367TER_STATUS=0x%x\n", 7358c2ecf20Sopenharmony_ci mode, tmp, tmp2); 7368c2ecf20Sopenharmony_ci 7378c2ecf20Sopenharmony_ci tmp = stv0367_readreg(state, R367TER_PRVIT); 7388c2ecf20Sopenharmony_ci tmp2 = stv0367_readreg(state, R367TER_I2CRPT); 7398c2ecf20Sopenharmony_ci dprintk("PRVIT=0x%x I2CRPT=0x%x\n", tmp, tmp2); 7408c2ecf20Sopenharmony_ci 7418c2ecf20Sopenharmony_ci tmp = stv0367_readreg(state, R367TER_GAIN_SRC1); 7428c2ecf20Sopenharmony_ci dprintk("GAIN_SRC1=0x%x\n", tmp); 7438c2ecf20Sopenharmony_ci 7448c2ecf20Sopenharmony_ci if ((mode != 0) && (mode != 1) && (mode != 2)) 7458c2ecf20Sopenharmony_ci return FE_TER_SWNOK; 7468c2ecf20Sopenharmony_ci 7478c2ecf20Sopenharmony_ci /*guard=stv0367_readbits(state,F367TER_SYR_GUARD); */ 7488c2ecf20Sopenharmony_ci 7498c2ecf20Sopenharmony_ci /*suppress EPQ auto for SYR_GARD 1/16 or 1/32 7508c2ecf20Sopenharmony_ci and set channel predictor in automatic */ 7518c2ecf20Sopenharmony_ci#if 0 7528c2ecf20Sopenharmony_ci switch (guard) { 7538c2ecf20Sopenharmony_ci 7548c2ecf20Sopenharmony_ci case 0: 7558c2ecf20Sopenharmony_ci case 1: 7568c2ecf20Sopenharmony_ci stv0367_writebits(state, F367TER_AUTO_LE_EN, 0); 7578c2ecf20Sopenharmony_ci stv0367_writereg(state, R367TER_CHC_CTL, 0x01); 7588c2ecf20Sopenharmony_ci break; 7598c2ecf20Sopenharmony_ci case 2: 7608c2ecf20Sopenharmony_ci case 3: 7618c2ecf20Sopenharmony_ci stv0367_writebits(state, F367TER_AUTO_LE_EN, 1); 7628c2ecf20Sopenharmony_ci stv0367_writereg(state, R367TER_CHC_CTL, 0x11); 7638c2ecf20Sopenharmony_ci break; 7648c2ecf20Sopenharmony_ci 7658c2ecf20Sopenharmony_ci default: 7668c2ecf20Sopenharmony_ci return FE_TER_SWNOK; 7678c2ecf20Sopenharmony_ci } 7688c2ecf20Sopenharmony_ci#endif 7698c2ecf20Sopenharmony_ci 7708c2ecf20Sopenharmony_ci /*reset fec an reedsolo FOR 367 only*/ 7718c2ecf20Sopenharmony_ci stv0367_writebits(state, F367TER_RST_SFEC, 1); 7728c2ecf20Sopenharmony_ci stv0367_writebits(state, F367TER_RST_REEDSOLO, 1); 7738c2ecf20Sopenharmony_ci usleep_range(1000, 2000); 7748c2ecf20Sopenharmony_ci stv0367_writebits(state, F367TER_RST_SFEC, 0); 7758c2ecf20Sopenharmony_ci stv0367_writebits(state, F367TER_RST_REEDSOLO, 0); 7768c2ecf20Sopenharmony_ci 7778c2ecf20Sopenharmony_ci u_var1 = stv0367_readbits(state, F367TER_LK); 7788c2ecf20Sopenharmony_ci u_var2 = stv0367_readbits(state, F367TER_PRF); 7798c2ecf20Sopenharmony_ci u_var3 = stv0367_readbits(state, F367TER_TPS_LOCK); 7808c2ecf20Sopenharmony_ci /* u_var4=stv0367_readbits(state,F367TER_TSFIFO_LINEOK); */ 7818c2ecf20Sopenharmony_ci 7828c2ecf20Sopenharmony_ci wd = stv0367ter_duration(mode, 125, 500, 250); 7838c2ecf20Sopenharmony_ci tempo = stv0367ter_duration(mode, 4, 16, 8); 7848c2ecf20Sopenharmony_ci 7858c2ecf20Sopenharmony_ci /*while ( ((!u_var1)||(!u_var2)||(!u_var3)||(!u_var4)) && (wd>=0)) */ 7868c2ecf20Sopenharmony_ci while (((!u_var1) || (!u_var2) || (!u_var3)) && (wd >= 0)) { 7878c2ecf20Sopenharmony_ci usleep_range(1000 * tempo, 1000 * (tempo + 1)); 7888c2ecf20Sopenharmony_ci wd -= tempo; 7898c2ecf20Sopenharmony_ci u_var1 = stv0367_readbits(state, F367TER_LK); 7908c2ecf20Sopenharmony_ci u_var2 = stv0367_readbits(state, F367TER_PRF); 7918c2ecf20Sopenharmony_ci u_var3 = stv0367_readbits(state, F367TER_TPS_LOCK); 7928c2ecf20Sopenharmony_ci /*u_var4=stv0367_readbits(state, F367TER_TSFIFO_LINEOK); */ 7938c2ecf20Sopenharmony_ci } 7948c2ecf20Sopenharmony_ci 7958c2ecf20Sopenharmony_ci if (!u_var1) 7968c2ecf20Sopenharmony_ci return FE_TER_NOLOCK; 7978c2ecf20Sopenharmony_ci 7988c2ecf20Sopenharmony_ci 7998c2ecf20Sopenharmony_ci if (!u_var2) 8008c2ecf20Sopenharmony_ci return FE_TER_NOPRFOUND; 8018c2ecf20Sopenharmony_ci 8028c2ecf20Sopenharmony_ci if (!u_var3) 8038c2ecf20Sopenharmony_ci return FE_TER_NOTPS; 8048c2ecf20Sopenharmony_ci 8058c2ecf20Sopenharmony_ci guard = stv0367_readbits(state, F367TER_SYR_GUARD); 8068c2ecf20Sopenharmony_ci stv0367_writereg(state, R367TER_CHC_CTL, 0x11); 8078c2ecf20Sopenharmony_ci switch (guard) { 8088c2ecf20Sopenharmony_ci case 0: 8098c2ecf20Sopenharmony_ci case 1: 8108c2ecf20Sopenharmony_ci stv0367_writebits(state, F367TER_AUTO_LE_EN, 0); 8118c2ecf20Sopenharmony_ci /*stv0367_writereg(state,R367TER_CHC_CTL, 0x1);*/ 8128c2ecf20Sopenharmony_ci stv0367_writebits(state, F367TER_SYR_FILTER, 0); 8138c2ecf20Sopenharmony_ci break; 8148c2ecf20Sopenharmony_ci case 2: 8158c2ecf20Sopenharmony_ci case 3: 8168c2ecf20Sopenharmony_ci stv0367_writebits(state, F367TER_AUTO_LE_EN, 1); 8178c2ecf20Sopenharmony_ci /*stv0367_writereg(state,R367TER_CHC_CTL, 0x11);*/ 8188c2ecf20Sopenharmony_ci stv0367_writebits(state, F367TER_SYR_FILTER, 1); 8198c2ecf20Sopenharmony_ci break; 8208c2ecf20Sopenharmony_ci 8218c2ecf20Sopenharmony_ci default: 8228c2ecf20Sopenharmony_ci return FE_TER_SWNOK; 8238c2ecf20Sopenharmony_ci } 8248c2ecf20Sopenharmony_ci 8258c2ecf20Sopenharmony_ci /* apply Sfec workaround if 8K 64QAM CR!=1/2*/ 8268c2ecf20Sopenharmony_ci if ((stv0367_readbits(state, F367TER_TPS_CONST) == 2) && 8278c2ecf20Sopenharmony_ci (mode == 1) && 8288c2ecf20Sopenharmony_ci (stv0367_readbits(state, F367TER_TPS_HPCODE) != 0)) { 8298c2ecf20Sopenharmony_ci stv0367_writereg(state, R367TER_SFDLYSETH, 0xc0); 8308c2ecf20Sopenharmony_ci stv0367_writereg(state, R367TER_SFDLYSETM, 0x60); 8318c2ecf20Sopenharmony_ci stv0367_writereg(state, R367TER_SFDLYSETL, 0x0); 8328c2ecf20Sopenharmony_ci } else 8338c2ecf20Sopenharmony_ci stv0367_writereg(state, R367TER_SFDLYSETH, 0x0); 8348c2ecf20Sopenharmony_ci 8358c2ecf20Sopenharmony_ci wd = stv0367ter_duration(mode, 125, 500, 250); 8368c2ecf20Sopenharmony_ci u_var4 = stv0367_readbits(state, F367TER_TSFIFO_LINEOK); 8378c2ecf20Sopenharmony_ci 8388c2ecf20Sopenharmony_ci while ((!u_var4) && (wd >= 0)) { 8398c2ecf20Sopenharmony_ci usleep_range(1000 * tempo, 1000 * (tempo + 1)); 8408c2ecf20Sopenharmony_ci wd -= tempo; 8418c2ecf20Sopenharmony_ci u_var4 = stv0367_readbits(state, F367TER_TSFIFO_LINEOK); 8428c2ecf20Sopenharmony_ci } 8438c2ecf20Sopenharmony_ci 8448c2ecf20Sopenharmony_ci if (!u_var4) 8458c2ecf20Sopenharmony_ci return FE_TER_NOLOCK; 8468c2ecf20Sopenharmony_ci 8478c2ecf20Sopenharmony_ci /* for 367 leave COM_N at 0x7 for IQ_mode*/ 8488c2ecf20Sopenharmony_ci /*if(ter_state->if_iq_mode!=FE_TER_NORMAL_IF_TUNER) { 8498c2ecf20Sopenharmony_ci tempo=0; 8508c2ecf20Sopenharmony_ci while ((stv0367_readbits(state,F367TER_COM_USEGAINTRK)!=1) && 8518c2ecf20Sopenharmony_ci (stv0367_readbits(state,F367TER_COM_AGCLOCK)!=1)&&(tempo<100)) { 8528c2ecf20Sopenharmony_ci ChipWaitOrAbort(state,1); 8538c2ecf20Sopenharmony_ci tempo+=1; 8548c2ecf20Sopenharmony_ci } 8558c2ecf20Sopenharmony_ci 8568c2ecf20Sopenharmony_ci stv0367_writebits(state,F367TER_COM_N,0x17); 8578c2ecf20Sopenharmony_ci } */ 8588c2ecf20Sopenharmony_ci 8598c2ecf20Sopenharmony_ci stv0367_writebits(state, F367TER_SYR_TR_DIS, 1); 8608c2ecf20Sopenharmony_ci 8618c2ecf20Sopenharmony_ci dprintk("FE_TER_LOCKOK !!!\n"); 8628c2ecf20Sopenharmony_ci 8638c2ecf20Sopenharmony_ci return FE_TER_LOCKOK; 8648c2ecf20Sopenharmony_ci 8658c2ecf20Sopenharmony_ci} 8668c2ecf20Sopenharmony_ci 8678c2ecf20Sopenharmony_cistatic void stv0367ter_set_ts_mode(struct stv0367_state *state, 8688c2ecf20Sopenharmony_ci enum stv0367_ts_mode PathTS) 8698c2ecf20Sopenharmony_ci{ 8708c2ecf20Sopenharmony_ci 8718c2ecf20Sopenharmony_ci dprintk("%s:\n", __func__); 8728c2ecf20Sopenharmony_ci 8738c2ecf20Sopenharmony_ci if (state == NULL) 8748c2ecf20Sopenharmony_ci return; 8758c2ecf20Sopenharmony_ci 8768c2ecf20Sopenharmony_ci stv0367_writebits(state, F367TER_TS_DIS, 0); 8778c2ecf20Sopenharmony_ci switch (PathTS) { 8788c2ecf20Sopenharmony_ci default: 8798c2ecf20Sopenharmony_ci /*for removing warning :default we can assume in parallel mode*/ 8808c2ecf20Sopenharmony_ci case STV0367_PARALLEL_PUNCT_CLOCK: 8818c2ecf20Sopenharmony_ci stv0367_writebits(state, F367TER_TSFIFO_SERIAL, 0); 8828c2ecf20Sopenharmony_ci stv0367_writebits(state, F367TER_TSFIFO_DVBCI, 0); 8838c2ecf20Sopenharmony_ci break; 8848c2ecf20Sopenharmony_ci case STV0367_SERIAL_PUNCT_CLOCK: 8858c2ecf20Sopenharmony_ci stv0367_writebits(state, F367TER_TSFIFO_SERIAL, 1); 8868c2ecf20Sopenharmony_ci stv0367_writebits(state, F367TER_TSFIFO_DVBCI, 1); 8878c2ecf20Sopenharmony_ci break; 8888c2ecf20Sopenharmony_ci } 8898c2ecf20Sopenharmony_ci} 8908c2ecf20Sopenharmony_ci 8918c2ecf20Sopenharmony_cistatic void stv0367ter_set_clk_pol(struct stv0367_state *state, 8928c2ecf20Sopenharmony_ci enum stv0367_clk_pol clock) 8938c2ecf20Sopenharmony_ci{ 8948c2ecf20Sopenharmony_ci 8958c2ecf20Sopenharmony_ci dprintk("%s:\n", __func__); 8968c2ecf20Sopenharmony_ci 8978c2ecf20Sopenharmony_ci if (state == NULL) 8988c2ecf20Sopenharmony_ci return; 8998c2ecf20Sopenharmony_ci 9008c2ecf20Sopenharmony_ci switch (clock) { 9018c2ecf20Sopenharmony_ci case STV0367_RISINGEDGE_CLOCK: 9028c2ecf20Sopenharmony_ci stv0367_writebits(state, F367TER_TS_BYTE_CLK_INV, 1); 9038c2ecf20Sopenharmony_ci break; 9048c2ecf20Sopenharmony_ci case STV0367_FALLINGEDGE_CLOCK: 9058c2ecf20Sopenharmony_ci stv0367_writebits(state, F367TER_TS_BYTE_CLK_INV, 0); 9068c2ecf20Sopenharmony_ci break; 9078c2ecf20Sopenharmony_ci /*case FE_TER_CLOCK_POLARITY_DEFAULT:*/ 9088c2ecf20Sopenharmony_ci default: 9098c2ecf20Sopenharmony_ci stv0367_writebits(state, F367TER_TS_BYTE_CLK_INV, 0); 9108c2ecf20Sopenharmony_ci break; 9118c2ecf20Sopenharmony_ci } 9128c2ecf20Sopenharmony_ci} 9138c2ecf20Sopenharmony_ci 9148c2ecf20Sopenharmony_ci#if 0 9158c2ecf20Sopenharmony_cistatic void stv0367ter_core_sw(struct stv0367_state *state) 9168c2ecf20Sopenharmony_ci{ 9178c2ecf20Sopenharmony_ci 9188c2ecf20Sopenharmony_ci dprintk("%s:\n", __func__); 9198c2ecf20Sopenharmony_ci 9208c2ecf20Sopenharmony_ci stv0367_writebits(state, F367TER_CORE_ACTIVE, 0); 9218c2ecf20Sopenharmony_ci stv0367_writebits(state, F367TER_CORE_ACTIVE, 1); 9228c2ecf20Sopenharmony_ci msleep(350); 9238c2ecf20Sopenharmony_ci} 9248c2ecf20Sopenharmony_ci#endif 9258c2ecf20Sopenharmony_cistatic int stv0367ter_standby(struct dvb_frontend *fe, u8 standby_on) 9268c2ecf20Sopenharmony_ci{ 9278c2ecf20Sopenharmony_ci struct stv0367_state *state = fe->demodulator_priv; 9288c2ecf20Sopenharmony_ci 9298c2ecf20Sopenharmony_ci dprintk("%s:\n", __func__); 9308c2ecf20Sopenharmony_ci 9318c2ecf20Sopenharmony_ci if (standby_on) { 9328c2ecf20Sopenharmony_ci stv0367_writebits(state, F367TER_STDBY, 1); 9338c2ecf20Sopenharmony_ci stv0367_writebits(state, F367TER_STDBY_FEC, 1); 9348c2ecf20Sopenharmony_ci stv0367_writebits(state, F367TER_STDBY_CORE, 1); 9358c2ecf20Sopenharmony_ci } else { 9368c2ecf20Sopenharmony_ci stv0367_writebits(state, F367TER_STDBY, 0); 9378c2ecf20Sopenharmony_ci stv0367_writebits(state, F367TER_STDBY_FEC, 0); 9388c2ecf20Sopenharmony_ci stv0367_writebits(state, F367TER_STDBY_CORE, 0); 9398c2ecf20Sopenharmony_ci } 9408c2ecf20Sopenharmony_ci 9418c2ecf20Sopenharmony_ci return 0; 9428c2ecf20Sopenharmony_ci} 9438c2ecf20Sopenharmony_ci 9448c2ecf20Sopenharmony_cistatic int stv0367ter_sleep(struct dvb_frontend *fe) 9458c2ecf20Sopenharmony_ci{ 9468c2ecf20Sopenharmony_ci return stv0367ter_standby(fe, 1); 9478c2ecf20Sopenharmony_ci} 9488c2ecf20Sopenharmony_ci 9498c2ecf20Sopenharmony_cistatic int stv0367ter_init(struct dvb_frontend *fe) 9508c2ecf20Sopenharmony_ci{ 9518c2ecf20Sopenharmony_ci struct stv0367_state *state = fe->demodulator_priv; 9528c2ecf20Sopenharmony_ci struct stv0367ter_state *ter_state = state->ter_state; 9538c2ecf20Sopenharmony_ci 9548c2ecf20Sopenharmony_ci dprintk("%s:\n", __func__); 9558c2ecf20Sopenharmony_ci 9568c2ecf20Sopenharmony_ci ter_state->pBER = 0; 9578c2ecf20Sopenharmony_ci 9588c2ecf20Sopenharmony_ci stv0367_write_table(state, 9598c2ecf20Sopenharmony_ci stv0367_deftabs[state->deftabs][STV0367_TAB_TER]); 9608c2ecf20Sopenharmony_ci 9618c2ecf20Sopenharmony_ci stv0367_pll_setup(state, STV0367_ICSPEED_53125, state->config->xtal); 9628c2ecf20Sopenharmony_ci 9638c2ecf20Sopenharmony_ci stv0367_writereg(state, R367TER_I2CRPT, 0xa0); 9648c2ecf20Sopenharmony_ci stv0367_writereg(state, R367TER_ANACTRL, 0x00); 9658c2ecf20Sopenharmony_ci 9668c2ecf20Sopenharmony_ci /*Set TS1 and TS2 to serial or parallel mode */ 9678c2ecf20Sopenharmony_ci stv0367ter_set_ts_mode(state, state->config->ts_mode); 9688c2ecf20Sopenharmony_ci stv0367ter_set_clk_pol(state, state->config->clk_pol); 9698c2ecf20Sopenharmony_ci 9708c2ecf20Sopenharmony_ci state->chip_id = stv0367_readreg(state, R367TER_ID); 9718c2ecf20Sopenharmony_ci ter_state->first_lock = 0; 9728c2ecf20Sopenharmony_ci ter_state->unlock_counter = 2; 9738c2ecf20Sopenharmony_ci 9748c2ecf20Sopenharmony_ci return 0; 9758c2ecf20Sopenharmony_ci} 9768c2ecf20Sopenharmony_ci 9778c2ecf20Sopenharmony_cistatic int stv0367ter_algo(struct dvb_frontend *fe) 9788c2ecf20Sopenharmony_ci{ 9798c2ecf20Sopenharmony_ci struct dtv_frontend_properties *p = &fe->dtv_property_cache; 9808c2ecf20Sopenharmony_ci struct stv0367_state *state = fe->demodulator_priv; 9818c2ecf20Sopenharmony_ci struct stv0367ter_state *ter_state = state->ter_state; 9828c2ecf20Sopenharmony_ci int offset = 0, tempo = 0; 9838c2ecf20Sopenharmony_ci u8 u_var; 9848c2ecf20Sopenharmony_ci u8 /*constell,*/ counter; 9858c2ecf20Sopenharmony_ci s8 step; 9868c2ecf20Sopenharmony_ci s32 timing_offset = 0; 9878c2ecf20Sopenharmony_ci u32 trl_nomrate = 0, InternalFreq = 0, temp = 0, ifkhz = 0; 9888c2ecf20Sopenharmony_ci 9898c2ecf20Sopenharmony_ci dprintk("%s:\n", __func__); 9908c2ecf20Sopenharmony_ci 9918c2ecf20Sopenharmony_ci stv0367_get_if_khz(state, &ifkhz); 9928c2ecf20Sopenharmony_ci 9938c2ecf20Sopenharmony_ci ter_state->frequency = p->frequency; 9948c2ecf20Sopenharmony_ci ter_state->force = FE_TER_FORCENONE 9958c2ecf20Sopenharmony_ci + stv0367_readbits(state, F367TER_FORCE) * 2; 9968c2ecf20Sopenharmony_ci ter_state->if_iq_mode = state->config->if_iq_mode; 9978c2ecf20Sopenharmony_ci switch (state->config->if_iq_mode) { 9988c2ecf20Sopenharmony_ci case FE_TER_NORMAL_IF_TUNER: /* Normal IF mode */ 9998c2ecf20Sopenharmony_ci dprintk("ALGO: FE_TER_NORMAL_IF_TUNER selected\n"); 10008c2ecf20Sopenharmony_ci stv0367_writebits(state, F367TER_TUNER_BB, 0); 10018c2ecf20Sopenharmony_ci stv0367_writebits(state, F367TER_LONGPATH_IF, 0); 10028c2ecf20Sopenharmony_ci stv0367_writebits(state, F367TER_DEMUX_SWAP, 0); 10038c2ecf20Sopenharmony_ci break; 10048c2ecf20Sopenharmony_ci case FE_TER_LONGPATH_IF_TUNER: /* Long IF mode */ 10058c2ecf20Sopenharmony_ci dprintk("ALGO: FE_TER_LONGPATH_IF_TUNER selected\n"); 10068c2ecf20Sopenharmony_ci stv0367_writebits(state, F367TER_TUNER_BB, 0); 10078c2ecf20Sopenharmony_ci stv0367_writebits(state, F367TER_LONGPATH_IF, 1); 10088c2ecf20Sopenharmony_ci stv0367_writebits(state, F367TER_DEMUX_SWAP, 1); 10098c2ecf20Sopenharmony_ci break; 10108c2ecf20Sopenharmony_ci case FE_TER_IQ_TUNER: /* IQ mode */ 10118c2ecf20Sopenharmony_ci dprintk("ALGO: FE_TER_IQ_TUNER selected\n"); 10128c2ecf20Sopenharmony_ci stv0367_writebits(state, F367TER_TUNER_BB, 1); 10138c2ecf20Sopenharmony_ci stv0367_writebits(state, F367TER_PPM_INVSEL, 0); 10148c2ecf20Sopenharmony_ci break; 10158c2ecf20Sopenharmony_ci default: 10168c2ecf20Sopenharmony_ci printk(KERN_ERR "ALGO: wrong TUNER type selected\n"); 10178c2ecf20Sopenharmony_ci return -EINVAL; 10188c2ecf20Sopenharmony_ci } 10198c2ecf20Sopenharmony_ci 10208c2ecf20Sopenharmony_ci usleep_range(5000, 7000); 10218c2ecf20Sopenharmony_ci 10228c2ecf20Sopenharmony_ci switch (p->inversion) { 10238c2ecf20Sopenharmony_ci case INVERSION_AUTO: 10248c2ecf20Sopenharmony_ci default: 10258c2ecf20Sopenharmony_ci dprintk("%s: inversion AUTO\n", __func__); 10268c2ecf20Sopenharmony_ci if (ter_state->if_iq_mode == FE_TER_IQ_TUNER) 10278c2ecf20Sopenharmony_ci stv0367_writebits(state, F367TER_IQ_INVERT, 10288c2ecf20Sopenharmony_ci ter_state->sense); 10298c2ecf20Sopenharmony_ci else 10308c2ecf20Sopenharmony_ci stv0367_writebits(state, F367TER_INV_SPECTR, 10318c2ecf20Sopenharmony_ci ter_state->sense); 10328c2ecf20Sopenharmony_ci 10338c2ecf20Sopenharmony_ci break; 10348c2ecf20Sopenharmony_ci case INVERSION_ON: 10358c2ecf20Sopenharmony_ci case INVERSION_OFF: 10368c2ecf20Sopenharmony_ci if (ter_state->if_iq_mode == FE_TER_IQ_TUNER) 10378c2ecf20Sopenharmony_ci stv0367_writebits(state, F367TER_IQ_INVERT, 10388c2ecf20Sopenharmony_ci p->inversion); 10398c2ecf20Sopenharmony_ci else 10408c2ecf20Sopenharmony_ci stv0367_writebits(state, F367TER_INV_SPECTR, 10418c2ecf20Sopenharmony_ci p->inversion); 10428c2ecf20Sopenharmony_ci 10438c2ecf20Sopenharmony_ci break; 10448c2ecf20Sopenharmony_ci } 10458c2ecf20Sopenharmony_ci 10468c2ecf20Sopenharmony_ci if ((ter_state->if_iq_mode != FE_TER_NORMAL_IF_TUNER) && 10478c2ecf20Sopenharmony_ci (ter_state->pBW != ter_state->bw)) { 10488c2ecf20Sopenharmony_ci stv0367ter_agc_iir_lock_detect_set(state); 10498c2ecf20Sopenharmony_ci 10508c2ecf20Sopenharmony_ci /*set fine agc target to 180 for LPIF or IQ mode*/ 10518c2ecf20Sopenharmony_ci /* set Q_AGCTarget */ 10528c2ecf20Sopenharmony_ci stv0367_writebits(state, F367TER_SEL_IQNTAR, 1); 10538c2ecf20Sopenharmony_ci stv0367_writebits(state, F367TER_AUT_AGC_TARGET_MSB, 0xB); 10548c2ecf20Sopenharmony_ci /*stv0367_writebits(state,AUT_AGC_TARGET_LSB,0x04); */ 10558c2ecf20Sopenharmony_ci 10568c2ecf20Sopenharmony_ci /* set Q_AGCTarget */ 10578c2ecf20Sopenharmony_ci stv0367_writebits(state, F367TER_SEL_IQNTAR, 0); 10588c2ecf20Sopenharmony_ci stv0367_writebits(state, F367TER_AUT_AGC_TARGET_MSB, 0xB); 10598c2ecf20Sopenharmony_ci /*stv0367_writebits(state,AUT_AGC_TARGET_LSB,0x04); */ 10608c2ecf20Sopenharmony_ci 10618c2ecf20Sopenharmony_ci if (!stv0367_iir_filt_init(state, ter_state->bw, 10628c2ecf20Sopenharmony_ci state->config->xtal)) 10638c2ecf20Sopenharmony_ci return -EINVAL; 10648c2ecf20Sopenharmony_ci /*set IIR filter once for 6,7 or 8MHz BW*/ 10658c2ecf20Sopenharmony_ci ter_state->pBW = ter_state->bw; 10668c2ecf20Sopenharmony_ci 10678c2ecf20Sopenharmony_ci stv0367ter_agc_iir_rst(state); 10688c2ecf20Sopenharmony_ci } 10698c2ecf20Sopenharmony_ci 10708c2ecf20Sopenharmony_ci if (ter_state->hierarchy == FE_TER_HIER_LOW_PRIO) 10718c2ecf20Sopenharmony_ci stv0367_writebits(state, F367TER_BDI_LPSEL, 0x01); 10728c2ecf20Sopenharmony_ci else 10738c2ecf20Sopenharmony_ci stv0367_writebits(state, F367TER_BDI_LPSEL, 0x00); 10748c2ecf20Sopenharmony_ci 10758c2ecf20Sopenharmony_ci InternalFreq = stv0367ter_get_mclk(state, state->config->xtal) / 1000; 10768c2ecf20Sopenharmony_ci temp = (int) 10778c2ecf20Sopenharmony_ci ((((ter_state->bw * 64 * (1 << 15) * 100) 10788c2ecf20Sopenharmony_ci / (InternalFreq)) * 10) / 7); 10798c2ecf20Sopenharmony_ci 10808c2ecf20Sopenharmony_ci stv0367_writebits(state, F367TER_TRL_NOMRATE_LSB, temp % 2); 10818c2ecf20Sopenharmony_ci temp = temp / 2; 10828c2ecf20Sopenharmony_ci stv0367_writebits(state, F367TER_TRL_NOMRATE_HI, temp / 256); 10838c2ecf20Sopenharmony_ci stv0367_writebits(state, F367TER_TRL_NOMRATE_LO, temp % 256); 10848c2ecf20Sopenharmony_ci 10858c2ecf20Sopenharmony_ci temp = stv0367_readbits(state, F367TER_TRL_NOMRATE_HI) * 512 + 10868c2ecf20Sopenharmony_ci stv0367_readbits(state, F367TER_TRL_NOMRATE_LO) * 2 + 10878c2ecf20Sopenharmony_ci stv0367_readbits(state, F367TER_TRL_NOMRATE_LSB); 10888c2ecf20Sopenharmony_ci temp = (int)(((1 << 17) * ter_state->bw * 1000) / (7 * (InternalFreq))); 10898c2ecf20Sopenharmony_ci stv0367_writebits(state, F367TER_GAIN_SRC_HI, temp / 256); 10908c2ecf20Sopenharmony_ci stv0367_writebits(state, F367TER_GAIN_SRC_LO, temp % 256); 10918c2ecf20Sopenharmony_ci temp = stv0367_readbits(state, F367TER_GAIN_SRC_HI) * 256 + 10928c2ecf20Sopenharmony_ci stv0367_readbits(state, F367TER_GAIN_SRC_LO); 10938c2ecf20Sopenharmony_ci 10948c2ecf20Sopenharmony_ci temp = (int) 10958c2ecf20Sopenharmony_ci ((InternalFreq - ifkhz) * (1 << 16) / (InternalFreq)); 10968c2ecf20Sopenharmony_ci 10978c2ecf20Sopenharmony_ci dprintk("DEROT temp=0x%x\n", temp); 10988c2ecf20Sopenharmony_ci stv0367_writebits(state, F367TER_INC_DEROT_HI, temp / 256); 10998c2ecf20Sopenharmony_ci stv0367_writebits(state, F367TER_INC_DEROT_LO, temp % 256); 11008c2ecf20Sopenharmony_ci 11018c2ecf20Sopenharmony_ci ter_state->echo_pos = 0; 11028c2ecf20Sopenharmony_ci ter_state->ucblocks = 0; /* liplianin */ 11038c2ecf20Sopenharmony_ci ter_state->pBER = 0; /* liplianin */ 11048c2ecf20Sopenharmony_ci stv0367_writebits(state, F367TER_LONG_ECHO, ter_state->echo_pos); 11058c2ecf20Sopenharmony_ci 11068c2ecf20Sopenharmony_ci if (stv0367ter_lock_algo(state) != FE_TER_LOCKOK) 11078c2ecf20Sopenharmony_ci return 0; 11088c2ecf20Sopenharmony_ci 11098c2ecf20Sopenharmony_ci ter_state->state = FE_TER_LOCKOK; 11108c2ecf20Sopenharmony_ci 11118c2ecf20Sopenharmony_ci ter_state->mode = stv0367_readbits(state, F367TER_SYR_MODE); 11128c2ecf20Sopenharmony_ci ter_state->guard = stv0367_readbits(state, F367TER_SYR_GUARD); 11138c2ecf20Sopenharmony_ci 11148c2ecf20Sopenharmony_ci ter_state->first_lock = 1; /* we know sense now :) */ 11158c2ecf20Sopenharmony_ci 11168c2ecf20Sopenharmony_ci ter_state->agc_val = 11178c2ecf20Sopenharmony_ci (stv0367_readbits(state, F367TER_AGC1_VAL_LO) << 16) + 11188c2ecf20Sopenharmony_ci (stv0367_readbits(state, F367TER_AGC1_VAL_HI) << 24) + 11198c2ecf20Sopenharmony_ci stv0367_readbits(state, F367TER_AGC2_VAL_LO) + 11208c2ecf20Sopenharmony_ci (stv0367_readbits(state, F367TER_AGC2_VAL_HI) << 8); 11218c2ecf20Sopenharmony_ci 11228c2ecf20Sopenharmony_ci /* Carrier offset calculation */ 11238c2ecf20Sopenharmony_ci stv0367_writebits(state, F367TER_FREEZE, 1); 11248c2ecf20Sopenharmony_ci offset = (stv0367_readbits(state, F367TER_CRL_FOFFSET_VHI) << 16) ; 11258c2ecf20Sopenharmony_ci offset += (stv0367_readbits(state, F367TER_CRL_FOFFSET_HI) << 8); 11268c2ecf20Sopenharmony_ci offset += (stv0367_readbits(state, F367TER_CRL_FOFFSET_LO)); 11278c2ecf20Sopenharmony_ci stv0367_writebits(state, F367TER_FREEZE, 0); 11288c2ecf20Sopenharmony_ci if (offset > 8388607) 11298c2ecf20Sopenharmony_ci offset -= 16777216; 11308c2ecf20Sopenharmony_ci 11318c2ecf20Sopenharmony_ci offset = offset * 2 / 16384; 11328c2ecf20Sopenharmony_ci 11338c2ecf20Sopenharmony_ci if (ter_state->mode == FE_TER_MODE_2K) 11348c2ecf20Sopenharmony_ci offset = (offset * 4464) / 1000;/*** 1 FFT BIN=4.464khz***/ 11358c2ecf20Sopenharmony_ci else if (ter_state->mode == FE_TER_MODE_4K) 11368c2ecf20Sopenharmony_ci offset = (offset * 223) / 100;/*** 1 FFT BIN=2.23khz***/ 11378c2ecf20Sopenharmony_ci else if (ter_state->mode == FE_TER_MODE_8K) 11388c2ecf20Sopenharmony_ci offset = (offset * 111) / 100;/*** 1 FFT BIN=1.1khz***/ 11398c2ecf20Sopenharmony_ci 11408c2ecf20Sopenharmony_ci if (stv0367_readbits(state, F367TER_PPM_INVSEL) == 1) { 11418c2ecf20Sopenharmony_ci if ((stv0367_readbits(state, F367TER_INV_SPECTR) == 11428c2ecf20Sopenharmony_ci (stv0367_readbits(state, 11438c2ecf20Sopenharmony_ci F367TER_STATUS_INV_SPECRUM) == 1))) 11448c2ecf20Sopenharmony_ci offset = offset * -1; 11458c2ecf20Sopenharmony_ci } 11468c2ecf20Sopenharmony_ci 11478c2ecf20Sopenharmony_ci if (ter_state->bw == 6) 11488c2ecf20Sopenharmony_ci offset = (offset * 6) / 8; 11498c2ecf20Sopenharmony_ci else if (ter_state->bw == 7) 11508c2ecf20Sopenharmony_ci offset = (offset * 7) / 8; 11518c2ecf20Sopenharmony_ci 11528c2ecf20Sopenharmony_ci ter_state->frequency += offset; 11538c2ecf20Sopenharmony_ci 11548c2ecf20Sopenharmony_ci tempo = 10; /* exit even if timing_offset stays null */ 11558c2ecf20Sopenharmony_ci while ((timing_offset == 0) && (tempo > 0)) { 11568c2ecf20Sopenharmony_ci usleep_range(10000, 20000); /*was 20ms */ 11578c2ecf20Sopenharmony_ci /* fine tuning of timing offset if required */ 11588c2ecf20Sopenharmony_ci timing_offset = stv0367_readbits(state, F367TER_TRL_TOFFSET_LO) 11598c2ecf20Sopenharmony_ci + 256 * stv0367_readbits(state, 11608c2ecf20Sopenharmony_ci F367TER_TRL_TOFFSET_HI); 11618c2ecf20Sopenharmony_ci if (timing_offset >= 32768) 11628c2ecf20Sopenharmony_ci timing_offset -= 65536; 11638c2ecf20Sopenharmony_ci trl_nomrate = (512 * stv0367_readbits(state, 11648c2ecf20Sopenharmony_ci F367TER_TRL_NOMRATE_HI) 11658c2ecf20Sopenharmony_ci + stv0367_readbits(state, F367TER_TRL_NOMRATE_LO) * 2 11668c2ecf20Sopenharmony_ci + stv0367_readbits(state, F367TER_TRL_NOMRATE_LSB)); 11678c2ecf20Sopenharmony_ci 11688c2ecf20Sopenharmony_ci timing_offset = ((signed)(1000000 / trl_nomrate) * 11698c2ecf20Sopenharmony_ci timing_offset) / 2048; 11708c2ecf20Sopenharmony_ci tempo--; 11718c2ecf20Sopenharmony_ci } 11728c2ecf20Sopenharmony_ci 11738c2ecf20Sopenharmony_ci if (timing_offset <= 0) { 11748c2ecf20Sopenharmony_ci timing_offset = (timing_offset - 11) / 22; 11758c2ecf20Sopenharmony_ci step = -1; 11768c2ecf20Sopenharmony_ci } else { 11778c2ecf20Sopenharmony_ci timing_offset = (timing_offset + 11) / 22; 11788c2ecf20Sopenharmony_ci step = 1; 11798c2ecf20Sopenharmony_ci } 11808c2ecf20Sopenharmony_ci 11818c2ecf20Sopenharmony_ci for (counter = 0; counter < abs(timing_offset); counter++) { 11828c2ecf20Sopenharmony_ci trl_nomrate += step; 11838c2ecf20Sopenharmony_ci stv0367_writebits(state, F367TER_TRL_NOMRATE_LSB, 11848c2ecf20Sopenharmony_ci trl_nomrate % 2); 11858c2ecf20Sopenharmony_ci stv0367_writebits(state, F367TER_TRL_NOMRATE_LO, 11868c2ecf20Sopenharmony_ci trl_nomrate / 2); 11878c2ecf20Sopenharmony_ci usleep_range(1000, 2000); 11888c2ecf20Sopenharmony_ci } 11898c2ecf20Sopenharmony_ci 11908c2ecf20Sopenharmony_ci usleep_range(5000, 6000); 11918c2ecf20Sopenharmony_ci /* unlocks could happen in case of trl centring big step, 11928c2ecf20Sopenharmony_ci then a core off/on restarts demod */ 11938c2ecf20Sopenharmony_ci u_var = stv0367_readbits(state, F367TER_LK); 11948c2ecf20Sopenharmony_ci 11958c2ecf20Sopenharmony_ci if (!u_var) { 11968c2ecf20Sopenharmony_ci stv0367_writebits(state, F367TER_CORE_ACTIVE, 0); 11978c2ecf20Sopenharmony_ci msleep(20); 11988c2ecf20Sopenharmony_ci stv0367_writebits(state, F367TER_CORE_ACTIVE, 1); 11998c2ecf20Sopenharmony_ci } 12008c2ecf20Sopenharmony_ci 12018c2ecf20Sopenharmony_ci return 0; 12028c2ecf20Sopenharmony_ci} 12038c2ecf20Sopenharmony_ci 12048c2ecf20Sopenharmony_cistatic int stv0367ter_set_frontend(struct dvb_frontend *fe) 12058c2ecf20Sopenharmony_ci{ 12068c2ecf20Sopenharmony_ci struct dtv_frontend_properties *p = &fe->dtv_property_cache; 12078c2ecf20Sopenharmony_ci struct stv0367_state *state = fe->demodulator_priv; 12088c2ecf20Sopenharmony_ci struct stv0367ter_state *ter_state = state->ter_state; 12098c2ecf20Sopenharmony_ci 12108c2ecf20Sopenharmony_ci /*u8 trials[2]; */ 12118c2ecf20Sopenharmony_ci s8 num_trials, index; 12128c2ecf20Sopenharmony_ci u8 SenseTrials[] = { INVERSION_ON, INVERSION_OFF }; 12138c2ecf20Sopenharmony_ci 12148c2ecf20Sopenharmony_ci if (state->reinit_on_setfrontend) 12158c2ecf20Sopenharmony_ci stv0367ter_init(fe); 12168c2ecf20Sopenharmony_ci 12178c2ecf20Sopenharmony_ci if (fe->ops.tuner_ops.set_params) { 12188c2ecf20Sopenharmony_ci if (state->use_i2c_gatectrl && fe->ops.i2c_gate_ctrl) 12198c2ecf20Sopenharmony_ci fe->ops.i2c_gate_ctrl(fe, 1); 12208c2ecf20Sopenharmony_ci fe->ops.tuner_ops.set_params(fe); 12218c2ecf20Sopenharmony_ci if (state->use_i2c_gatectrl && fe->ops.i2c_gate_ctrl) 12228c2ecf20Sopenharmony_ci fe->ops.i2c_gate_ctrl(fe, 0); 12238c2ecf20Sopenharmony_ci } 12248c2ecf20Sopenharmony_ci 12258c2ecf20Sopenharmony_ci switch (p->transmission_mode) { 12268c2ecf20Sopenharmony_ci default: 12278c2ecf20Sopenharmony_ci case TRANSMISSION_MODE_AUTO: 12288c2ecf20Sopenharmony_ci case TRANSMISSION_MODE_2K: 12298c2ecf20Sopenharmony_ci ter_state->mode = FE_TER_MODE_2K; 12308c2ecf20Sopenharmony_ci break; 12318c2ecf20Sopenharmony_ci/* case TRANSMISSION_MODE_4K: 12328c2ecf20Sopenharmony_ci pLook.mode = FE_TER_MODE_4K; 12338c2ecf20Sopenharmony_ci break;*/ 12348c2ecf20Sopenharmony_ci case TRANSMISSION_MODE_8K: 12358c2ecf20Sopenharmony_ci ter_state->mode = FE_TER_MODE_8K; 12368c2ecf20Sopenharmony_ci break; 12378c2ecf20Sopenharmony_ci } 12388c2ecf20Sopenharmony_ci 12398c2ecf20Sopenharmony_ci switch (p->guard_interval) { 12408c2ecf20Sopenharmony_ci default: 12418c2ecf20Sopenharmony_ci case GUARD_INTERVAL_1_32: 12428c2ecf20Sopenharmony_ci case GUARD_INTERVAL_1_16: 12438c2ecf20Sopenharmony_ci case GUARD_INTERVAL_1_8: 12448c2ecf20Sopenharmony_ci case GUARD_INTERVAL_1_4: 12458c2ecf20Sopenharmony_ci ter_state->guard = p->guard_interval; 12468c2ecf20Sopenharmony_ci break; 12478c2ecf20Sopenharmony_ci case GUARD_INTERVAL_AUTO: 12488c2ecf20Sopenharmony_ci ter_state->guard = GUARD_INTERVAL_1_32; 12498c2ecf20Sopenharmony_ci break; 12508c2ecf20Sopenharmony_ci } 12518c2ecf20Sopenharmony_ci 12528c2ecf20Sopenharmony_ci switch (p->bandwidth_hz) { 12538c2ecf20Sopenharmony_ci case 6000000: 12548c2ecf20Sopenharmony_ci ter_state->bw = FE_TER_CHAN_BW_6M; 12558c2ecf20Sopenharmony_ci break; 12568c2ecf20Sopenharmony_ci case 7000000: 12578c2ecf20Sopenharmony_ci ter_state->bw = FE_TER_CHAN_BW_7M; 12588c2ecf20Sopenharmony_ci break; 12598c2ecf20Sopenharmony_ci case 8000000: 12608c2ecf20Sopenharmony_ci default: 12618c2ecf20Sopenharmony_ci ter_state->bw = FE_TER_CHAN_BW_8M; 12628c2ecf20Sopenharmony_ci } 12638c2ecf20Sopenharmony_ci 12648c2ecf20Sopenharmony_ci ter_state->hierarchy = FE_TER_HIER_NONE; 12658c2ecf20Sopenharmony_ci 12668c2ecf20Sopenharmony_ci switch (p->inversion) { 12678c2ecf20Sopenharmony_ci case INVERSION_OFF: 12688c2ecf20Sopenharmony_ci case INVERSION_ON: 12698c2ecf20Sopenharmony_ci num_trials = 1; 12708c2ecf20Sopenharmony_ci break; 12718c2ecf20Sopenharmony_ci default: 12728c2ecf20Sopenharmony_ci num_trials = 2; 12738c2ecf20Sopenharmony_ci if (ter_state->first_lock) 12748c2ecf20Sopenharmony_ci num_trials = 1; 12758c2ecf20Sopenharmony_ci break; 12768c2ecf20Sopenharmony_ci } 12778c2ecf20Sopenharmony_ci 12788c2ecf20Sopenharmony_ci ter_state->state = FE_TER_NOLOCK; 12798c2ecf20Sopenharmony_ci index = 0; 12808c2ecf20Sopenharmony_ci 12818c2ecf20Sopenharmony_ci while (((index) < num_trials) && (ter_state->state != FE_TER_LOCKOK)) { 12828c2ecf20Sopenharmony_ci if (!ter_state->first_lock) { 12838c2ecf20Sopenharmony_ci if (p->inversion == INVERSION_AUTO) 12848c2ecf20Sopenharmony_ci ter_state->sense = SenseTrials[index]; 12858c2ecf20Sopenharmony_ci 12868c2ecf20Sopenharmony_ci } 12878c2ecf20Sopenharmony_ci stv0367ter_algo(fe); 12888c2ecf20Sopenharmony_ci 12898c2ecf20Sopenharmony_ci if ((ter_state->state == FE_TER_LOCKOK) && 12908c2ecf20Sopenharmony_ci (p->inversion == INVERSION_AUTO) && 12918c2ecf20Sopenharmony_ci (index == 1)) { 12928c2ecf20Sopenharmony_ci /* invert spectrum sense */ 12938c2ecf20Sopenharmony_ci SenseTrials[index] = SenseTrials[0]; 12948c2ecf20Sopenharmony_ci SenseTrials[(index + 1) % 2] = (SenseTrials[1] + 1) % 2; 12958c2ecf20Sopenharmony_ci } 12968c2ecf20Sopenharmony_ci 12978c2ecf20Sopenharmony_ci index++; 12988c2ecf20Sopenharmony_ci } 12998c2ecf20Sopenharmony_ci 13008c2ecf20Sopenharmony_ci return 0; 13018c2ecf20Sopenharmony_ci} 13028c2ecf20Sopenharmony_ci 13038c2ecf20Sopenharmony_cistatic int stv0367ter_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) 13048c2ecf20Sopenharmony_ci{ 13058c2ecf20Sopenharmony_ci struct stv0367_state *state = fe->demodulator_priv; 13068c2ecf20Sopenharmony_ci struct stv0367ter_state *ter_state = state->ter_state; 13078c2ecf20Sopenharmony_ci u32 errs = 0; 13088c2ecf20Sopenharmony_ci 13098c2ecf20Sopenharmony_ci /*wait for counting completion*/ 13108c2ecf20Sopenharmony_ci if (stv0367_readbits(state, F367TER_SFERRC_OLDVALUE) == 0) { 13118c2ecf20Sopenharmony_ci errs = 13128c2ecf20Sopenharmony_ci ((u32)stv0367_readbits(state, F367TER_ERR_CNT1) 13138c2ecf20Sopenharmony_ci * (1 << 16)) 13148c2ecf20Sopenharmony_ci + ((u32)stv0367_readbits(state, F367TER_ERR_CNT1_HI) 13158c2ecf20Sopenharmony_ci * (1 << 8)) 13168c2ecf20Sopenharmony_ci + ((u32)stv0367_readbits(state, F367TER_ERR_CNT1_LO)); 13178c2ecf20Sopenharmony_ci ter_state->ucblocks = errs; 13188c2ecf20Sopenharmony_ci } 13198c2ecf20Sopenharmony_ci 13208c2ecf20Sopenharmony_ci (*ucblocks) = ter_state->ucblocks; 13218c2ecf20Sopenharmony_ci 13228c2ecf20Sopenharmony_ci return 0; 13238c2ecf20Sopenharmony_ci} 13248c2ecf20Sopenharmony_ci 13258c2ecf20Sopenharmony_cistatic int stv0367ter_get_frontend(struct dvb_frontend *fe, 13268c2ecf20Sopenharmony_ci struct dtv_frontend_properties *p) 13278c2ecf20Sopenharmony_ci{ 13288c2ecf20Sopenharmony_ci struct stv0367_state *state = fe->demodulator_priv; 13298c2ecf20Sopenharmony_ci struct stv0367ter_state *ter_state = state->ter_state; 13308c2ecf20Sopenharmony_ci enum stv0367_ter_mode mode; 13318c2ecf20Sopenharmony_ci int constell = 0,/* snr = 0,*/ Data = 0; 13328c2ecf20Sopenharmony_ci 13338c2ecf20Sopenharmony_ci p->frequency = stv0367_get_tuner_freq(fe); 13348c2ecf20Sopenharmony_ci if ((int)p->frequency < 0) 13358c2ecf20Sopenharmony_ci p->frequency = -p->frequency; 13368c2ecf20Sopenharmony_ci 13378c2ecf20Sopenharmony_ci constell = stv0367_readbits(state, F367TER_TPS_CONST); 13388c2ecf20Sopenharmony_ci if (constell == 0) 13398c2ecf20Sopenharmony_ci p->modulation = QPSK; 13408c2ecf20Sopenharmony_ci else if (constell == 1) 13418c2ecf20Sopenharmony_ci p->modulation = QAM_16; 13428c2ecf20Sopenharmony_ci else 13438c2ecf20Sopenharmony_ci p->modulation = QAM_64; 13448c2ecf20Sopenharmony_ci 13458c2ecf20Sopenharmony_ci p->inversion = stv0367_readbits(state, F367TER_INV_SPECTR); 13468c2ecf20Sopenharmony_ci 13478c2ecf20Sopenharmony_ci /* Get the Hierarchical mode */ 13488c2ecf20Sopenharmony_ci Data = stv0367_readbits(state, F367TER_TPS_HIERMODE); 13498c2ecf20Sopenharmony_ci 13508c2ecf20Sopenharmony_ci switch (Data) { 13518c2ecf20Sopenharmony_ci case 0: 13528c2ecf20Sopenharmony_ci p->hierarchy = HIERARCHY_NONE; 13538c2ecf20Sopenharmony_ci break; 13548c2ecf20Sopenharmony_ci case 1: 13558c2ecf20Sopenharmony_ci p->hierarchy = HIERARCHY_1; 13568c2ecf20Sopenharmony_ci break; 13578c2ecf20Sopenharmony_ci case 2: 13588c2ecf20Sopenharmony_ci p->hierarchy = HIERARCHY_2; 13598c2ecf20Sopenharmony_ci break; 13608c2ecf20Sopenharmony_ci case 3: 13618c2ecf20Sopenharmony_ci p->hierarchy = HIERARCHY_4; 13628c2ecf20Sopenharmony_ci break; 13638c2ecf20Sopenharmony_ci default: 13648c2ecf20Sopenharmony_ci p->hierarchy = HIERARCHY_AUTO; 13658c2ecf20Sopenharmony_ci break; /* error */ 13668c2ecf20Sopenharmony_ci } 13678c2ecf20Sopenharmony_ci 13688c2ecf20Sopenharmony_ci /* Get the FEC Rate */ 13698c2ecf20Sopenharmony_ci if (ter_state->hierarchy == FE_TER_HIER_LOW_PRIO) 13708c2ecf20Sopenharmony_ci Data = stv0367_readbits(state, F367TER_TPS_LPCODE); 13718c2ecf20Sopenharmony_ci else 13728c2ecf20Sopenharmony_ci Data = stv0367_readbits(state, F367TER_TPS_HPCODE); 13738c2ecf20Sopenharmony_ci 13748c2ecf20Sopenharmony_ci switch (Data) { 13758c2ecf20Sopenharmony_ci case 0: 13768c2ecf20Sopenharmony_ci p->code_rate_HP = FEC_1_2; 13778c2ecf20Sopenharmony_ci break; 13788c2ecf20Sopenharmony_ci case 1: 13798c2ecf20Sopenharmony_ci p->code_rate_HP = FEC_2_3; 13808c2ecf20Sopenharmony_ci break; 13818c2ecf20Sopenharmony_ci case 2: 13828c2ecf20Sopenharmony_ci p->code_rate_HP = FEC_3_4; 13838c2ecf20Sopenharmony_ci break; 13848c2ecf20Sopenharmony_ci case 3: 13858c2ecf20Sopenharmony_ci p->code_rate_HP = FEC_5_6; 13868c2ecf20Sopenharmony_ci break; 13878c2ecf20Sopenharmony_ci case 4: 13888c2ecf20Sopenharmony_ci p->code_rate_HP = FEC_7_8; 13898c2ecf20Sopenharmony_ci break; 13908c2ecf20Sopenharmony_ci default: 13918c2ecf20Sopenharmony_ci p->code_rate_HP = FEC_AUTO; 13928c2ecf20Sopenharmony_ci break; /* error */ 13938c2ecf20Sopenharmony_ci } 13948c2ecf20Sopenharmony_ci 13958c2ecf20Sopenharmony_ci mode = stv0367_readbits(state, F367TER_SYR_MODE); 13968c2ecf20Sopenharmony_ci 13978c2ecf20Sopenharmony_ci switch (mode) { 13988c2ecf20Sopenharmony_ci case FE_TER_MODE_2K: 13998c2ecf20Sopenharmony_ci p->transmission_mode = TRANSMISSION_MODE_2K; 14008c2ecf20Sopenharmony_ci break; 14018c2ecf20Sopenharmony_ci/* case FE_TER_MODE_4K: 14028c2ecf20Sopenharmony_ci p->transmission_mode = TRANSMISSION_MODE_4K; 14038c2ecf20Sopenharmony_ci break;*/ 14048c2ecf20Sopenharmony_ci case FE_TER_MODE_8K: 14058c2ecf20Sopenharmony_ci p->transmission_mode = TRANSMISSION_MODE_8K; 14068c2ecf20Sopenharmony_ci break; 14078c2ecf20Sopenharmony_ci default: 14088c2ecf20Sopenharmony_ci p->transmission_mode = TRANSMISSION_MODE_AUTO; 14098c2ecf20Sopenharmony_ci } 14108c2ecf20Sopenharmony_ci 14118c2ecf20Sopenharmony_ci p->guard_interval = stv0367_readbits(state, F367TER_SYR_GUARD); 14128c2ecf20Sopenharmony_ci 14138c2ecf20Sopenharmony_ci return 0; 14148c2ecf20Sopenharmony_ci} 14158c2ecf20Sopenharmony_ci 14168c2ecf20Sopenharmony_cistatic u32 stv0367ter_snr_readreg(struct dvb_frontend *fe) 14178c2ecf20Sopenharmony_ci{ 14188c2ecf20Sopenharmony_ci struct stv0367_state *state = fe->demodulator_priv; 14198c2ecf20Sopenharmony_ci u32 snru32 = 0; 14208c2ecf20Sopenharmony_ci int cpt = 0; 14218c2ecf20Sopenharmony_ci u8 cut = stv0367_readbits(state, F367TER_IDENTIFICATIONREG); 14228c2ecf20Sopenharmony_ci 14238c2ecf20Sopenharmony_ci while (cpt < 10) { 14248c2ecf20Sopenharmony_ci usleep_range(2000, 3000); 14258c2ecf20Sopenharmony_ci if (cut == 0x50) /*cut 1.0 cut 1.1*/ 14268c2ecf20Sopenharmony_ci snru32 += stv0367_readbits(state, F367TER_CHCSNR) / 4; 14278c2ecf20Sopenharmony_ci else /*cu2.0*/ 14288c2ecf20Sopenharmony_ci snru32 += 125 * stv0367_readbits(state, F367TER_CHCSNR); 14298c2ecf20Sopenharmony_ci 14308c2ecf20Sopenharmony_ci cpt++; 14318c2ecf20Sopenharmony_ci } 14328c2ecf20Sopenharmony_ci snru32 /= 10;/*average on 10 values*/ 14338c2ecf20Sopenharmony_ci 14348c2ecf20Sopenharmony_ci return snru32; 14358c2ecf20Sopenharmony_ci} 14368c2ecf20Sopenharmony_ci 14378c2ecf20Sopenharmony_cistatic int stv0367ter_read_snr(struct dvb_frontend *fe, u16 *snr) 14388c2ecf20Sopenharmony_ci{ 14398c2ecf20Sopenharmony_ci u32 snrval = stv0367ter_snr_readreg(fe); 14408c2ecf20Sopenharmony_ci 14418c2ecf20Sopenharmony_ci *snr = snrval / 1000; 14428c2ecf20Sopenharmony_ci 14438c2ecf20Sopenharmony_ci return 0; 14448c2ecf20Sopenharmony_ci} 14458c2ecf20Sopenharmony_ci 14468c2ecf20Sopenharmony_ci#if 0 14478c2ecf20Sopenharmony_cistatic int stv0367ter_status(struct dvb_frontend *fe) 14488c2ecf20Sopenharmony_ci{ 14498c2ecf20Sopenharmony_ci 14508c2ecf20Sopenharmony_ci struct stv0367_state *state = fe->demodulator_priv; 14518c2ecf20Sopenharmony_ci struct stv0367ter_state *ter_state = state->ter_state; 14528c2ecf20Sopenharmony_ci int locked = FALSE; 14538c2ecf20Sopenharmony_ci 14548c2ecf20Sopenharmony_ci locked = (stv0367_readbits(state, F367TER_LK)); 14558c2ecf20Sopenharmony_ci if (!locked) 14568c2ecf20Sopenharmony_ci ter_state->unlock_counter += 1; 14578c2ecf20Sopenharmony_ci else 14588c2ecf20Sopenharmony_ci ter_state->unlock_counter = 0; 14598c2ecf20Sopenharmony_ci 14608c2ecf20Sopenharmony_ci if (ter_state->unlock_counter > 2) { 14618c2ecf20Sopenharmony_ci if (!stv0367_readbits(state, F367TER_TPS_LOCK) || 14628c2ecf20Sopenharmony_ci (!stv0367_readbits(state, F367TER_LK))) { 14638c2ecf20Sopenharmony_ci stv0367_writebits(state, F367TER_CORE_ACTIVE, 0); 14648c2ecf20Sopenharmony_ci usleep_range(2000, 3000); 14658c2ecf20Sopenharmony_ci stv0367_writebits(state, F367TER_CORE_ACTIVE, 1); 14668c2ecf20Sopenharmony_ci msleep(350); 14678c2ecf20Sopenharmony_ci locked = (stv0367_readbits(state, F367TER_TPS_LOCK)) && 14688c2ecf20Sopenharmony_ci (stv0367_readbits(state, F367TER_LK)); 14698c2ecf20Sopenharmony_ci } 14708c2ecf20Sopenharmony_ci 14718c2ecf20Sopenharmony_ci } 14728c2ecf20Sopenharmony_ci 14738c2ecf20Sopenharmony_ci return locked; 14748c2ecf20Sopenharmony_ci} 14758c2ecf20Sopenharmony_ci#endif 14768c2ecf20Sopenharmony_cistatic int stv0367ter_read_status(struct dvb_frontend *fe, 14778c2ecf20Sopenharmony_ci enum fe_status *status) 14788c2ecf20Sopenharmony_ci{ 14798c2ecf20Sopenharmony_ci struct stv0367_state *state = fe->demodulator_priv; 14808c2ecf20Sopenharmony_ci 14818c2ecf20Sopenharmony_ci dprintk("%s:\n", __func__); 14828c2ecf20Sopenharmony_ci 14838c2ecf20Sopenharmony_ci *status = 0; 14848c2ecf20Sopenharmony_ci 14858c2ecf20Sopenharmony_ci if (stv0367_readbits(state, F367TER_LK)) { 14868c2ecf20Sopenharmony_ci *status = FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI 14878c2ecf20Sopenharmony_ci | FE_HAS_SYNC | FE_HAS_LOCK; 14888c2ecf20Sopenharmony_ci dprintk("%s: stv0367 has locked\n", __func__); 14898c2ecf20Sopenharmony_ci } 14908c2ecf20Sopenharmony_ci 14918c2ecf20Sopenharmony_ci return 0; 14928c2ecf20Sopenharmony_ci} 14938c2ecf20Sopenharmony_ci 14948c2ecf20Sopenharmony_cistatic int stv0367ter_read_ber(struct dvb_frontend *fe, u32 *ber) 14958c2ecf20Sopenharmony_ci{ 14968c2ecf20Sopenharmony_ci struct stv0367_state *state = fe->demodulator_priv; 14978c2ecf20Sopenharmony_ci struct stv0367ter_state *ter_state = state->ter_state; 14988c2ecf20Sopenharmony_ci u32 Errors = 0, tber = 0, temporary = 0; 14998c2ecf20Sopenharmony_ci int abc = 0, def = 0; 15008c2ecf20Sopenharmony_ci 15018c2ecf20Sopenharmony_ci 15028c2ecf20Sopenharmony_ci /*wait for counting completion*/ 15038c2ecf20Sopenharmony_ci if (stv0367_readbits(state, F367TER_SFERRC_OLDVALUE) == 0) 15048c2ecf20Sopenharmony_ci Errors = ((u32)stv0367_readbits(state, F367TER_SFEC_ERR_CNT) 15058c2ecf20Sopenharmony_ci * (1 << 16)) 15068c2ecf20Sopenharmony_ci + ((u32)stv0367_readbits(state, F367TER_SFEC_ERR_CNT_HI) 15078c2ecf20Sopenharmony_ci * (1 << 8)) 15088c2ecf20Sopenharmony_ci + ((u32)stv0367_readbits(state, 15098c2ecf20Sopenharmony_ci F367TER_SFEC_ERR_CNT_LO)); 15108c2ecf20Sopenharmony_ci /*measurement not completed, load previous value*/ 15118c2ecf20Sopenharmony_ci else { 15128c2ecf20Sopenharmony_ci tber = ter_state->pBER; 15138c2ecf20Sopenharmony_ci return 0; 15148c2ecf20Sopenharmony_ci } 15158c2ecf20Sopenharmony_ci 15168c2ecf20Sopenharmony_ci abc = stv0367_readbits(state, F367TER_SFEC_ERR_SOURCE); 15178c2ecf20Sopenharmony_ci def = stv0367_readbits(state, F367TER_SFEC_NUM_EVENT); 15188c2ecf20Sopenharmony_ci 15198c2ecf20Sopenharmony_ci if (Errors == 0) { 15208c2ecf20Sopenharmony_ci tber = 0; 15218c2ecf20Sopenharmony_ci } else if (abc == 0x7) { 15228c2ecf20Sopenharmony_ci if (Errors <= 4) { 15238c2ecf20Sopenharmony_ci temporary = (Errors * 1000000000) / (8 * (1 << 14)); 15248c2ecf20Sopenharmony_ci } else if (Errors <= 42) { 15258c2ecf20Sopenharmony_ci temporary = (Errors * 100000000) / (8 * (1 << 14)); 15268c2ecf20Sopenharmony_ci temporary = temporary * 10; 15278c2ecf20Sopenharmony_ci } else if (Errors <= 429) { 15288c2ecf20Sopenharmony_ci temporary = (Errors * 10000000) / (8 * (1 << 14)); 15298c2ecf20Sopenharmony_ci temporary = temporary * 100; 15308c2ecf20Sopenharmony_ci } else if (Errors <= 4294) { 15318c2ecf20Sopenharmony_ci temporary = (Errors * 1000000) / (8 * (1 << 14)); 15328c2ecf20Sopenharmony_ci temporary = temporary * 1000; 15338c2ecf20Sopenharmony_ci } else if (Errors <= 42949) { 15348c2ecf20Sopenharmony_ci temporary = (Errors * 100000) / (8 * (1 << 14)); 15358c2ecf20Sopenharmony_ci temporary = temporary * 10000; 15368c2ecf20Sopenharmony_ci } else if (Errors <= 429496) { 15378c2ecf20Sopenharmony_ci temporary = (Errors * 10000) / (8 * (1 << 14)); 15388c2ecf20Sopenharmony_ci temporary = temporary * 100000; 15398c2ecf20Sopenharmony_ci } else { /*if (Errors<4294967) 2^22 max error*/ 15408c2ecf20Sopenharmony_ci temporary = (Errors * 1000) / (8 * (1 << 14)); 15418c2ecf20Sopenharmony_ci temporary = temporary * 100000; /* still to *10 */ 15428c2ecf20Sopenharmony_ci } 15438c2ecf20Sopenharmony_ci 15448c2ecf20Sopenharmony_ci /* Byte error*/ 15458c2ecf20Sopenharmony_ci if (def == 2) 15468c2ecf20Sopenharmony_ci /*tber=Errors/(8*(1 <<14));*/ 15478c2ecf20Sopenharmony_ci tber = temporary; 15488c2ecf20Sopenharmony_ci else if (def == 3) 15498c2ecf20Sopenharmony_ci /*tber=Errors/(8*(1 <<16));*/ 15508c2ecf20Sopenharmony_ci tber = temporary / 4; 15518c2ecf20Sopenharmony_ci else if (def == 4) 15528c2ecf20Sopenharmony_ci /*tber=Errors/(8*(1 <<18));*/ 15538c2ecf20Sopenharmony_ci tber = temporary / 16; 15548c2ecf20Sopenharmony_ci else if (def == 5) 15558c2ecf20Sopenharmony_ci /*tber=Errors/(8*(1 <<20));*/ 15568c2ecf20Sopenharmony_ci tber = temporary / 64; 15578c2ecf20Sopenharmony_ci else if (def == 6) 15588c2ecf20Sopenharmony_ci /*tber=Errors/(8*(1 <<22));*/ 15598c2ecf20Sopenharmony_ci tber = temporary / 256; 15608c2ecf20Sopenharmony_ci else 15618c2ecf20Sopenharmony_ci /* should not pass here*/ 15628c2ecf20Sopenharmony_ci tber = 0; 15638c2ecf20Sopenharmony_ci 15648c2ecf20Sopenharmony_ci if ((Errors < 4294967) && (Errors > 429496)) 15658c2ecf20Sopenharmony_ci tber *= 10; 15668c2ecf20Sopenharmony_ci 15678c2ecf20Sopenharmony_ci } 15688c2ecf20Sopenharmony_ci 15698c2ecf20Sopenharmony_ci /* save actual value */ 15708c2ecf20Sopenharmony_ci ter_state->pBER = tber; 15718c2ecf20Sopenharmony_ci 15728c2ecf20Sopenharmony_ci (*ber) = tber; 15738c2ecf20Sopenharmony_ci 15748c2ecf20Sopenharmony_ci return 0; 15758c2ecf20Sopenharmony_ci} 15768c2ecf20Sopenharmony_ci#if 0 15778c2ecf20Sopenharmony_cistatic u32 stv0367ter_get_per(struct stv0367_state *state) 15788c2ecf20Sopenharmony_ci{ 15798c2ecf20Sopenharmony_ci struct stv0367ter_state *ter_state = state->ter_state; 15808c2ecf20Sopenharmony_ci u32 Errors = 0, Per = 0, temporary = 0; 15818c2ecf20Sopenharmony_ci int abc = 0, def = 0, cpt = 0; 15828c2ecf20Sopenharmony_ci 15838c2ecf20Sopenharmony_ci while (((stv0367_readbits(state, F367TER_SFERRC_OLDVALUE) == 1) && 15848c2ecf20Sopenharmony_ci (cpt < 400)) || ((Errors == 0) && (cpt < 400))) { 15858c2ecf20Sopenharmony_ci usleep_range(1000, 2000); 15868c2ecf20Sopenharmony_ci Errors = ((u32)stv0367_readbits(state, F367TER_ERR_CNT1) 15878c2ecf20Sopenharmony_ci * (1 << 16)) 15888c2ecf20Sopenharmony_ci + ((u32)stv0367_readbits(state, F367TER_ERR_CNT1_HI) 15898c2ecf20Sopenharmony_ci * (1 << 8)) 15908c2ecf20Sopenharmony_ci + ((u32)stv0367_readbits(state, F367TER_ERR_CNT1_LO)); 15918c2ecf20Sopenharmony_ci cpt++; 15928c2ecf20Sopenharmony_ci } 15938c2ecf20Sopenharmony_ci abc = stv0367_readbits(state, F367TER_ERR_SRC1); 15948c2ecf20Sopenharmony_ci def = stv0367_readbits(state, F367TER_NUM_EVT1); 15958c2ecf20Sopenharmony_ci 15968c2ecf20Sopenharmony_ci if (Errors == 0) 15978c2ecf20Sopenharmony_ci Per = 0; 15988c2ecf20Sopenharmony_ci else if (abc == 0x9) { 15998c2ecf20Sopenharmony_ci if (Errors <= 4) { 16008c2ecf20Sopenharmony_ci temporary = (Errors * 1000000000) / (8 * (1 << 8)); 16018c2ecf20Sopenharmony_ci } else if (Errors <= 42) { 16028c2ecf20Sopenharmony_ci temporary = (Errors * 100000000) / (8 * (1 << 8)); 16038c2ecf20Sopenharmony_ci temporary = temporary * 10; 16048c2ecf20Sopenharmony_ci } else if (Errors <= 429) { 16058c2ecf20Sopenharmony_ci temporary = (Errors * 10000000) / (8 * (1 << 8)); 16068c2ecf20Sopenharmony_ci temporary = temporary * 100; 16078c2ecf20Sopenharmony_ci } else if (Errors <= 4294) { 16088c2ecf20Sopenharmony_ci temporary = (Errors * 1000000) / (8 * (1 << 8)); 16098c2ecf20Sopenharmony_ci temporary = temporary * 1000; 16108c2ecf20Sopenharmony_ci } else if (Errors <= 42949) { 16118c2ecf20Sopenharmony_ci temporary = (Errors * 100000) / (8 * (1 << 8)); 16128c2ecf20Sopenharmony_ci temporary = temporary * 10000; 16138c2ecf20Sopenharmony_ci } else { /*if(Errors<=429496) 2^16 errors max*/ 16148c2ecf20Sopenharmony_ci temporary = (Errors * 10000) / (8 * (1 << 8)); 16158c2ecf20Sopenharmony_ci temporary = temporary * 100000; 16168c2ecf20Sopenharmony_ci } 16178c2ecf20Sopenharmony_ci 16188c2ecf20Sopenharmony_ci /* pkt error*/ 16198c2ecf20Sopenharmony_ci if (def == 2) 16208c2ecf20Sopenharmony_ci /*Per=Errors/(1 << 8);*/ 16218c2ecf20Sopenharmony_ci Per = temporary; 16228c2ecf20Sopenharmony_ci else if (def == 3) 16238c2ecf20Sopenharmony_ci /*Per=Errors/(1 << 10);*/ 16248c2ecf20Sopenharmony_ci Per = temporary / 4; 16258c2ecf20Sopenharmony_ci else if (def == 4) 16268c2ecf20Sopenharmony_ci /*Per=Errors/(1 << 12);*/ 16278c2ecf20Sopenharmony_ci Per = temporary / 16; 16288c2ecf20Sopenharmony_ci else if (def == 5) 16298c2ecf20Sopenharmony_ci /*Per=Errors/(1 << 14);*/ 16308c2ecf20Sopenharmony_ci Per = temporary / 64; 16318c2ecf20Sopenharmony_ci else if (def == 6) 16328c2ecf20Sopenharmony_ci /*Per=Errors/(1 << 16);*/ 16338c2ecf20Sopenharmony_ci Per = temporary / 256; 16348c2ecf20Sopenharmony_ci else 16358c2ecf20Sopenharmony_ci Per = 0; 16368c2ecf20Sopenharmony_ci 16378c2ecf20Sopenharmony_ci } 16388c2ecf20Sopenharmony_ci /* save actual value */ 16398c2ecf20Sopenharmony_ci ter_state->pPER = Per; 16408c2ecf20Sopenharmony_ci 16418c2ecf20Sopenharmony_ci return Per; 16428c2ecf20Sopenharmony_ci} 16438c2ecf20Sopenharmony_ci#endif 16448c2ecf20Sopenharmony_cistatic int stv0367_get_tune_settings(struct dvb_frontend *fe, 16458c2ecf20Sopenharmony_ci struct dvb_frontend_tune_settings 16468c2ecf20Sopenharmony_ci *fe_tune_settings) 16478c2ecf20Sopenharmony_ci{ 16488c2ecf20Sopenharmony_ci fe_tune_settings->min_delay_ms = 1000; 16498c2ecf20Sopenharmony_ci fe_tune_settings->step_size = 0; 16508c2ecf20Sopenharmony_ci fe_tune_settings->max_drift = 0; 16518c2ecf20Sopenharmony_ci 16528c2ecf20Sopenharmony_ci return 0; 16538c2ecf20Sopenharmony_ci} 16548c2ecf20Sopenharmony_ci 16558c2ecf20Sopenharmony_cistatic void stv0367_release(struct dvb_frontend *fe) 16568c2ecf20Sopenharmony_ci{ 16578c2ecf20Sopenharmony_ci struct stv0367_state *state = fe->demodulator_priv; 16588c2ecf20Sopenharmony_ci 16598c2ecf20Sopenharmony_ci kfree(state->ter_state); 16608c2ecf20Sopenharmony_ci kfree(state->cab_state); 16618c2ecf20Sopenharmony_ci kfree(state); 16628c2ecf20Sopenharmony_ci} 16638c2ecf20Sopenharmony_ci 16648c2ecf20Sopenharmony_cistatic const struct dvb_frontend_ops stv0367ter_ops = { 16658c2ecf20Sopenharmony_ci .delsys = { SYS_DVBT }, 16668c2ecf20Sopenharmony_ci .info = { 16678c2ecf20Sopenharmony_ci .name = "ST STV0367 DVB-T", 16688c2ecf20Sopenharmony_ci .frequency_min_hz = 47 * MHz, 16698c2ecf20Sopenharmony_ci .frequency_max_hz = 862 * MHz, 16708c2ecf20Sopenharmony_ci .frequency_stepsize_hz = 15625, 16718c2ecf20Sopenharmony_ci .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | 16728c2ecf20Sopenharmony_ci FE_CAN_FEC_3_4 | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | 16738c2ecf20Sopenharmony_ci FE_CAN_FEC_AUTO | 16748c2ecf20Sopenharmony_ci FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | 16758c2ecf20Sopenharmony_ci FE_CAN_QAM_128 | FE_CAN_QAM_256 | FE_CAN_QAM_AUTO | 16768c2ecf20Sopenharmony_ci FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_RECOVER | 16778c2ecf20Sopenharmony_ci FE_CAN_INVERSION_AUTO | 16788c2ecf20Sopenharmony_ci FE_CAN_MUTE_TS 16798c2ecf20Sopenharmony_ci }, 16808c2ecf20Sopenharmony_ci .release = stv0367_release, 16818c2ecf20Sopenharmony_ci .init = stv0367ter_init, 16828c2ecf20Sopenharmony_ci .sleep = stv0367ter_sleep, 16838c2ecf20Sopenharmony_ci .i2c_gate_ctrl = stv0367ter_gate_ctrl, 16848c2ecf20Sopenharmony_ci .set_frontend = stv0367ter_set_frontend, 16858c2ecf20Sopenharmony_ci .get_frontend = stv0367ter_get_frontend, 16868c2ecf20Sopenharmony_ci .get_tune_settings = stv0367_get_tune_settings, 16878c2ecf20Sopenharmony_ci .read_status = stv0367ter_read_status, 16888c2ecf20Sopenharmony_ci .read_ber = stv0367ter_read_ber,/* too slow */ 16898c2ecf20Sopenharmony_ci/* .read_signal_strength = stv0367_read_signal_strength,*/ 16908c2ecf20Sopenharmony_ci .read_snr = stv0367ter_read_snr, 16918c2ecf20Sopenharmony_ci .read_ucblocks = stv0367ter_read_ucblocks, 16928c2ecf20Sopenharmony_ci}; 16938c2ecf20Sopenharmony_ci 16948c2ecf20Sopenharmony_cistruct dvb_frontend *stv0367ter_attach(const struct stv0367_config *config, 16958c2ecf20Sopenharmony_ci struct i2c_adapter *i2c) 16968c2ecf20Sopenharmony_ci{ 16978c2ecf20Sopenharmony_ci struct stv0367_state *state = NULL; 16988c2ecf20Sopenharmony_ci struct stv0367ter_state *ter_state = NULL; 16998c2ecf20Sopenharmony_ci 17008c2ecf20Sopenharmony_ci /* allocate memory for the internal state */ 17018c2ecf20Sopenharmony_ci state = kzalloc(sizeof(struct stv0367_state), GFP_KERNEL); 17028c2ecf20Sopenharmony_ci if (state == NULL) 17038c2ecf20Sopenharmony_ci goto error; 17048c2ecf20Sopenharmony_ci ter_state = kzalloc(sizeof(struct stv0367ter_state), GFP_KERNEL); 17058c2ecf20Sopenharmony_ci if (ter_state == NULL) 17068c2ecf20Sopenharmony_ci goto error; 17078c2ecf20Sopenharmony_ci 17088c2ecf20Sopenharmony_ci /* setup the state */ 17098c2ecf20Sopenharmony_ci state->i2c = i2c; 17108c2ecf20Sopenharmony_ci state->config = config; 17118c2ecf20Sopenharmony_ci state->ter_state = ter_state; 17128c2ecf20Sopenharmony_ci state->fe.ops = stv0367ter_ops; 17138c2ecf20Sopenharmony_ci state->fe.demodulator_priv = state; 17148c2ecf20Sopenharmony_ci state->chip_id = stv0367_readreg(state, 0xf000); 17158c2ecf20Sopenharmony_ci 17168c2ecf20Sopenharmony_ci /* demod operation options */ 17178c2ecf20Sopenharmony_ci state->use_i2c_gatectrl = 1; 17188c2ecf20Sopenharmony_ci state->deftabs = STV0367_DEFTAB_GENERIC; 17198c2ecf20Sopenharmony_ci state->reinit_on_setfrontend = 1; 17208c2ecf20Sopenharmony_ci state->auto_if_khz = 0; 17218c2ecf20Sopenharmony_ci 17228c2ecf20Sopenharmony_ci dprintk("%s: chip_id = 0x%x\n", __func__, state->chip_id); 17238c2ecf20Sopenharmony_ci 17248c2ecf20Sopenharmony_ci /* check if the demod is there */ 17258c2ecf20Sopenharmony_ci if ((state->chip_id != 0x50) && (state->chip_id != 0x60)) 17268c2ecf20Sopenharmony_ci goto error; 17278c2ecf20Sopenharmony_ci 17288c2ecf20Sopenharmony_ci return &state->fe; 17298c2ecf20Sopenharmony_ci 17308c2ecf20Sopenharmony_cierror: 17318c2ecf20Sopenharmony_ci kfree(ter_state); 17328c2ecf20Sopenharmony_ci kfree(state); 17338c2ecf20Sopenharmony_ci return NULL; 17348c2ecf20Sopenharmony_ci} 17358c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(stv0367ter_attach); 17368c2ecf20Sopenharmony_ci 17378c2ecf20Sopenharmony_cistatic int stv0367cab_gate_ctrl(struct dvb_frontend *fe, int enable) 17388c2ecf20Sopenharmony_ci{ 17398c2ecf20Sopenharmony_ci struct stv0367_state *state = fe->demodulator_priv; 17408c2ecf20Sopenharmony_ci 17418c2ecf20Sopenharmony_ci dprintk("%s:\n", __func__); 17428c2ecf20Sopenharmony_ci 17438c2ecf20Sopenharmony_ci stv0367_writebits(state, F367CAB_I2CT_ON, (enable > 0) ? 1 : 0); 17448c2ecf20Sopenharmony_ci 17458c2ecf20Sopenharmony_ci return 0; 17468c2ecf20Sopenharmony_ci} 17478c2ecf20Sopenharmony_ci 17488c2ecf20Sopenharmony_cistatic u32 stv0367cab_get_mclk(struct dvb_frontend *fe, u32 ExtClk_Hz) 17498c2ecf20Sopenharmony_ci{ 17508c2ecf20Sopenharmony_ci struct stv0367_state *state = fe->demodulator_priv; 17518c2ecf20Sopenharmony_ci u32 mclk_Hz = 0;/* master clock frequency (Hz) */ 17528c2ecf20Sopenharmony_ci u32 M, N, P; 17538c2ecf20Sopenharmony_ci 17548c2ecf20Sopenharmony_ci 17558c2ecf20Sopenharmony_ci if (stv0367_readbits(state, F367CAB_BYPASS_PLLXN) == 0) { 17568c2ecf20Sopenharmony_ci N = (u32)stv0367_readbits(state, F367CAB_PLL_NDIV); 17578c2ecf20Sopenharmony_ci if (N == 0) 17588c2ecf20Sopenharmony_ci N = N + 1; 17598c2ecf20Sopenharmony_ci 17608c2ecf20Sopenharmony_ci M = (u32)stv0367_readbits(state, F367CAB_PLL_MDIV); 17618c2ecf20Sopenharmony_ci if (M == 0) 17628c2ecf20Sopenharmony_ci M = M + 1; 17638c2ecf20Sopenharmony_ci 17648c2ecf20Sopenharmony_ci P = (u32)stv0367_readbits(state, F367CAB_PLL_PDIV); 17658c2ecf20Sopenharmony_ci 17668c2ecf20Sopenharmony_ci if (P > 5) 17678c2ecf20Sopenharmony_ci P = 5; 17688c2ecf20Sopenharmony_ci 17698c2ecf20Sopenharmony_ci mclk_Hz = ((ExtClk_Hz / 2) * N) / (M * (1 << P)); 17708c2ecf20Sopenharmony_ci dprintk("stv0367cab_get_mclk BYPASS_PLLXN mclk_Hz=%d\n", 17718c2ecf20Sopenharmony_ci mclk_Hz); 17728c2ecf20Sopenharmony_ci } else 17738c2ecf20Sopenharmony_ci mclk_Hz = ExtClk_Hz; 17748c2ecf20Sopenharmony_ci 17758c2ecf20Sopenharmony_ci dprintk("stv0367cab_get_mclk final mclk_Hz=%d\n", mclk_Hz); 17768c2ecf20Sopenharmony_ci 17778c2ecf20Sopenharmony_ci return mclk_Hz; 17788c2ecf20Sopenharmony_ci} 17798c2ecf20Sopenharmony_ci 17808c2ecf20Sopenharmony_cistatic u32 stv0367cab_get_adc_freq(struct dvb_frontend *fe, u32 ExtClk_Hz) 17818c2ecf20Sopenharmony_ci{ 17828c2ecf20Sopenharmony_ci u32 ADCClk_Hz = ExtClk_Hz; 17838c2ecf20Sopenharmony_ci 17848c2ecf20Sopenharmony_ci ADCClk_Hz = stv0367cab_get_mclk(fe, ExtClk_Hz); 17858c2ecf20Sopenharmony_ci 17868c2ecf20Sopenharmony_ci return ADCClk_Hz; 17878c2ecf20Sopenharmony_ci} 17888c2ecf20Sopenharmony_ci 17898c2ecf20Sopenharmony_cistatic enum stv0367cab_mod stv0367cab_SetQamSize(struct stv0367_state *state, 17908c2ecf20Sopenharmony_ci u32 SymbolRate, 17918c2ecf20Sopenharmony_ci enum stv0367cab_mod QAMSize) 17928c2ecf20Sopenharmony_ci{ 17938c2ecf20Sopenharmony_ci /* Set QAM size */ 17948c2ecf20Sopenharmony_ci stv0367_writebits(state, F367CAB_QAM_MODE, QAMSize); 17958c2ecf20Sopenharmony_ci 17968c2ecf20Sopenharmony_ci /* Set Registers settings specific to the QAM size */ 17978c2ecf20Sopenharmony_ci switch (QAMSize) { 17988c2ecf20Sopenharmony_ci case FE_CAB_MOD_QAM4: 17998c2ecf20Sopenharmony_ci stv0367_writereg(state, R367CAB_IQDEM_ADJ_AGC_REF, 0x00); 18008c2ecf20Sopenharmony_ci break; 18018c2ecf20Sopenharmony_ci case FE_CAB_MOD_QAM16: 18028c2ecf20Sopenharmony_ci stv0367_writereg(state, R367CAB_AGC_PWR_REF_L, 0x64); 18038c2ecf20Sopenharmony_ci stv0367_writereg(state, R367CAB_IQDEM_ADJ_AGC_REF, 0x00); 18048c2ecf20Sopenharmony_ci stv0367_writereg(state, R367CAB_FSM_STATE, 0x90); 18058c2ecf20Sopenharmony_ci stv0367_writereg(state, R367CAB_EQU_CTR_LPF_GAIN, 0xc1); 18068c2ecf20Sopenharmony_ci stv0367_writereg(state, R367CAB_EQU_CRL_LPF_GAIN, 0xa7); 18078c2ecf20Sopenharmony_ci stv0367_writereg(state, R367CAB_EQU_CRL_LD_SEN, 0x95); 18088c2ecf20Sopenharmony_ci stv0367_writereg(state, R367CAB_EQU_CRL_LIMITER, 0x40); 18098c2ecf20Sopenharmony_ci stv0367_writereg(state, R367CAB_EQU_PNT_GAIN, 0x8a); 18108c2ecf20Sopenharmony_ci break; 18118c2ecf20Sopenharmony_ci case FE_CAB_MOD_QAM32: 18128c2ecf20Sopenharmony_ci stv0367_writereg(state, R367CAB_IQDEM_ADJ_AGC_REF, 0x00); 18138c2ecf20Sopenharmony_ci stv0367_writereg(state, R367CAB_AGC_PWR_REF_L, 0x6e); 18148c2ecf20Sopenharmony_ci stv0367_writereg(state, R367CAB_FSM_STATE, 0xb0); 18158c2ecf20Sopenharmony_ci stv0367_writereg(state, R367CAB_EQU_CTR_LPF_GAIN, 0xc1); 18168c2ecf20Sopenharmony_ci stv0367_writereg(state, R367CAB_EQU_CRL_LPF_GAIN, 0xb7); 18178c2ecf20Sopenharmony_ci stv0367_writereg(state, R367CAB_EQU_CRL_LD_SEN, 0x9d); 18188c2ecf20Sopenharmony_ci stv0367_writereg(state, R367CAB_EQU_CRL_LIMITER, 0x7f); 18198c2ecf20Sopenharmony_ci stv0367_writereg(state, R367CAB_EQU_PNT_GAIN, 0xa7); 18208c2ecf20Sopenharmony_ci break; 18218c2ecf20Sopenharmony_ci case FE_CAB_MOD_QAM64: 18228c2ecf20Sopenharmony_ci stv0367_writereg(state, R367CAB_IQDEM_ADJ_AGC_REF, 0x82); 18238c2ecf20Sopenharmony_ci stv0367_writereg(state, R367CAB_AGC_PWR_REF_L, 0x5a); 18248c2ecf20Sopenharmony_ci if (SymbolRate > 4500000) { 18258c2ecf20Sopenharmony_ci stv0367_writereg(state, R367CAB_FSM_STATE, 0xb0); 18268c2ecf20Sopenharmony_ci stv0367_writereg(state, R367CAB_EQU_CTR_LPF_GAIN, 0xc1); 18278c2ecf20Sopenharmony_ci stv0367_writereg(state, R367CAB_EQU_CRL_LPF_GAIN, 0xa5); 18288c2ecf20Sopenharmony_ci } else if (SymbolRate > 2500000) { 18298c2ecf20Sopenharmony_ci stv0367_writereg(state, R367CAB_FSM_STATE, 0xa0); 18308c2ecf20Sopenharmony_ci stv0367_writereg(state, R367CAB_EQU_CTR_LPF_GAIN, 0xc1); 18318c2ecf20Sopenharmony_ci stv0367_writereg(state, R367CAB_EQU_CRL_LPF_GAIN, 0xa6); 18328c2ecf20Sopenharmony_ci } else { 18338c2ecf20Sopenharmony_ci stv0367_writereg(state, R367CAB_FSM_STATE, 0xa0); 18348c2ecf20Sopenharmony_ci stv0367_writereg(state, R367CAB_EQU_CTR_LPF_GAIN, 0xd1); 18358c2ecf20Sopenharmony_ci stv0367_writereg(state, R367CAB_EQU_CRL_LPF_GAIN, 0xa7); 18368c2ecf20Sopenharmony_ci } 18378c2ecf20Sopenharmony_ci stv0367_writereg(state, R367CAB_EQU_CRL_LD_SEN, 0x95); 18388c2ecf20Sopenharmony_ci stv0367_writereg(state, R367CAB_EQU_CRL_LIMITER, 0x40); 18398c2ecf20Sopenharmony_ci stv0367_writereg(state, R367CAB_EQU_PNT_GAIN, 0x99); 18408c2ecf20Sopenharmony_ci break; 18418c2ecf20Sopenharmony_ci case FE_CAB_MOD_QAM128: 18428c2ecf20Sopenharmony_ci stv0367_writereg(state, R367CAB_IQDEM_ADJ_AGC_REF, 0x00); 18438c2ecf20Sopenharmony_ci stv0367_writereg(state, R367CAB_AGC_PWR_REF_L, 0x76); 18448c2ecf20Sopenharmony_ci stv0367_writereg(state, R367CAB_FSM_STATE, 0x90); 18458c2ecf20Sopenharmony_ci stv0367_writereg(state, R367CAB_EQU_CTR_LPF_GAIN, 0xb1); 18468c2ecf20Sopenharmony_ci if (SymbolRate > 4500000) 18478c2ecf20Sopenharmony_ci stv0367_writereg(state, R367CAB_EQU_CRL_LPF_GAIN, 0xa7); 18488c2ecf20Sopenharmony_ci else if (SymbolRate > 2500000) 18498c2ecf20Sopenharmony_ci stv0367_writereg(state, R367CAB_EQU_CRL_LPF_GAIN, 0xa6); 18508c2ecf20Sopenharmony_ci else 18518c2ecf20Sopenharmony_ci stv0367_writereg(state, R367CAB_EQU_CRL_LPF_GAIN, 0x97); 18528c2ecf20Sopenharmony_ci 18538c2ecf20Sopenharmony_ci stv0367_writereg(state, R367CAB_EQU_CRL_LD_SEN, 0x8e); 18548c2ecf20Sopenharmony_ci stv0367_writereg(state, R367CAB_EQU_CRL_LIMITER, 0x7f); 18558c2ecf20Sopenharmony_ci stv0367_writereg(state, R367CAB_EQU_PNT_GAIN, 0xa7); 18568c2ecf20Sopenharmony_ci break; 18578c2ecf20Sopenharmony_ci case FE_CAB_MOD_QAM256: 18588c2ecf20Sopenharmony_ci stv0367_writereg(state, R367CAB_IQDEM_ADJ_AGC_REF, 0x94); 18598c2ecf20Sopenharmony_ci stv0367_writereg(state, R367CAB_AGC_PWR_REF_L, 0x5a); 18608c2ecf20Sopenharmony_ci stv0367_writereg(state, R367CAB_FSM_STATE, 0xa0); 18618c2ecf20Sopenharmony_ci if (SymbolRate > 4500000) 18628c2ecf20Sopenharmony_ci stv0367_writereg(state, R367CAB_EQU_CTR_LPF_GAIN, 0xc1); 18638c2ecf20Sopenharmony_ci else if (SymbolRate > 2500000) 18648c2ecf20Sopenharmony_ci stv0367_writereg(state, R367CAB_EQU_CTR_LPF_GAIN, 0xc1); 18658c2ecf20Sopenharmony_ci else 18668c2ecf20Sopenharmony_ci stv0367_writereg(state, R367CAB_EQU_CTR_LPF_GAIN, 0xd1); 18678c2ecf20Sopenharmony_ci 18688c2ecf20Sopenharmony_ci stv0367_writereg(state, R367CAB_EQU_CRL_LPF_GAIN, 0xa7); 18698c2ecf20Sopenharmony_ci stv0367_writereg(state, R367CAB_EQU_CRL_LD_SEN, 0x85); 18708c2ecf20Sopenharmony_ci stv0367_writereg(state, R367CAB_EQU_CRL_LIMITER, 0x40); 18718c2ecf20Sopenharmony_ci stv0367_writereg(state, R367CAB_EQU_PNT_GAIN, 0xa7); 18728c2ecf20Sopenharmony_ci break; 18738c2ecf20Sopenharmony_ci case FE_CAB_MOD_QAM512: 18748c2ecf20Sopenharmony_ci stv0367_writereg(state, R367CAB_IQDEM_ADJ_AGC_REF, 0x00); 18758c2ecf20Sopenharmony_ci break; 18768c2ecf20Sopenharmony_ci case FE_CAB_MOD_QAM1024: 18778c2ecf20Sopenharmony_ci stv0367_writereg(state, R367CAB_IQDEM_ADJ_AGC_REF, 0x00); 18788c2ecf20Sopenharmony_ci break; 18798c2ecf20Sopenharmony_ci default: 18808c2ecf20Sopenharmony_ci break; 18818c2ecf20Sopenharmony_ci } 18828c2ecf20Sopenharmony_ci 18838c2ecf20Sopenharmony_ci return QAMSize; 18848c2ecf20Sopenharmony_ci} 18858c2ecf20Sopenharmony_ci 18868c2ecf20Sopenharmony_cistatic u32 stv0367cab_set_derot_freq(struct stv0367_state *state, 18878c2ecf20Sopenharmony_ci u32 adc_hz, s32 derot_hz) 18888c2ecf20Sopenharmony_ci{ 18898c2ecf20Sopenharmony_ci u32 sampled_if = 0; 18908c2ecf20Sopenharmony_ci u32 adc_khz; 18918c2ecf20Sopenharmony_ci 18928c2ecf20Sopenharmony_ci adc_khz = adc_hz / 1000; 18938c2ecf20Sopenharmony_ci 18948c2ecf20Sopenharmony_ci dprintk("%s: adc_hz=%d derot_hz=%d\n", __func__, adc_hz, derot_hz); 18958c2ecf20Sopenharmony_ci 18968c2ecf20Sopenharmony_ci if (adc_khz != 0) { 18978c2ecf20Sopenharmony_ci if (derot_hz < 1000000) 18988c2ecf20Sopenharmony_ci derot_hz = adc_hz / 4; /* ZIF operation */ 18998c2ecf20Sopenharmony_ci if (derot_hz > adc_hz) 19008c2ecf20Sopenharmony_ci derot_hz = derot_hz - adc_hz; 19018c2ecf20Sopenharmony_ci sampled_if = (u32)derot_hz / 1000; 19028c2ecf20Sopenharmony_ci sampled_if *= 32768; 19038c2ecf20Sopenharmony_ci sampled_if /= adc_khz; 19048c2ecf20Sopenharmony_ci sampled_if *= 256; 19058c2ecf20Sopenharmony_ci } 19068c2ecf20Sopenharmony_ci 19078c2ecf20Sopenharmony_ci if (sampled_if > 8388607) 19088c2ecf20Sopenharmony_ci sampled_if = 8388607; 19098c2ecf20Sopenharmony_ci 19108c2ecf20Sopenharmony_ci dprintk("%s: sampled_if=0x%x\n", __func__, sampled_if); 19118c2ecf20Sopenharmony_ci 19128c2ecf20Sopenharmony_ci stv0367_writereg(state, R367CAB_MIX_NCO_LL, sampled_if); 19138c2ecf20Sopenharmony_ci stv0367_writereg(state, R367CAB_MIX_NCO_HL, (sampled_if >> 8)); 19148c2ecf20Sopenharmony_ci stv0367_writebits(state, F367CAB_MIX_NCO_INC_HH, (sampled_if >> 16)); 19158c2ecf20Sopenharmony_ci 19168c2ecf20Sopenharmony_ci return derot_hz; 19178c2ecf20Sopenharmony_ci} 19188c2ecf20Sopenharmony_ci 19198c2ecf20Sopenharmony_cistatic u32 stv0367cab_get_derot_freq(struct stv0367_state *state, u32 adc_hz) 19208c2ecf20Sopenharmony_ci{ 19218c2ecf20Sopenharmony_ci u32 sampled_if; 19228c2ecf20Sopenharmony_ci 19238c2ecf20Sopenharmony_ci sampled_if = stv0367_readbits(state, F367CAB_MIX_NCO_INC_LL) + 19248c2ecf20Sopenharmony_ci (stv0367_readbits(state, F367CAB_MIX_NCO_INC_HL) << 8) + 19258c2ecf20Sopenharmony_ci (stv0367_readbits(state, F367CAB_MIX_NCO_INC_HH) << 16); 19268c2ecf20Sopenharmony_ci 19278c2ecf20Sopenharmony_ci sampled_if /= 256; 19288c2ecf20Sopenharmony_ci sampled_if *= (adc_hz / 1000); 19298c2ecf20Sopenharmony_ci sampled_if += 1; 19308c2ecf20Sopenharmony_ci sampled_if /= 32768; 19318c2ecf20Sopenharmony_ci 19328c2ecf20Sopenharmony_ci return sampled_if; 19338c2ecf20Sopenharmony_ci} 19348c2ecf20Sopenharmony_ci 19358c2ecf20Sopenharmony_cistatic u32 stv0367cab_set_srate(struct stv0367_state *state, u32 adc_hz, 19368c2ecf20Sopenharmony_ci u32 mclk_hz, u32 SymbolRate, 19378c2ecf20Sopenharmony_ci enum stv0367cab_mod QAMSize) 19388c2ecf20Sopenharmony_ci{ 19398c2ecf20Sopenharmony_ci u32 QamSizeCorr = 0; 19408c2ecf20Sopenharmony_ci u32 u32_tmp = 0, u32_tmp1 = 0; 19418c2ecf20Sopenharmony_ci u32 adp_khz; 19428c2ecf20Sopenharmony_ci 19438c2ecf20Sopenharmony_ci dprintk("%s:\n", __func__); 19448c2ecf20Sopenharmony_ci 19458c2ecf20Sopenharmony_ci /* Set Correction factor of SRC gain */ 19468c2ecf20Sopenharmony_ci switch (QAMSize) { 19478c2ecf20Sopenharmony_ci case FE_CAB_MOD_QAM4: 19488c2ecf20Sopenharmony_ci QamSizeCorr = 1110; 19498c2ecf20Sopenharmony_ci break; 19508c2ecf20Sopenharmony_ci case FE_CAB_MOD_QAM16: 19518c2ecf20Sopenharmony_ci QamSizeCorr = 1032; 19528c2ecf20Sopenharmony_ci break; 19538c2ecf20Sopenharmony_ci case FE_CAB_MOD_QAM32: 19548c2ecf20Sopenharmony_ci QamSizeCorr = 954; 19558c2ecf20Sopenharmony_ci break; 19568c2ecf20Sopenharmony_ci case FE_CAB_MOD_QAM64: 19578c2ecf20Sopenharmony_ci QamSizeCorr = 983; 19588c2ecf20Sopenharmony_ci break; 19598c2ecf20Sopenharmony_ci case FE_CAB_MOD_QAM128: 19608c2ecf20Sopenharmony_ci QamSizeCorr = 957; 19618c2ecf20Sopenharmony_ci break; 19628c2ecf20Sopenharmony_ci case FE_CAB_MOD_QAM256: 19638c2ecf20Sopenharmony_ci QamSizeCorr = 948; 19648c2ecf20Sopenharmony_ci break; 19658c2ecf20Sopenharmony_ci case FE_CAB_MOD_QAM512: 19668c2ecf20Sopenharmony_ci QamSizeCorr = 0; 19678c2ecf20Sopenharmony_ci break; 19688c2ecf20Sopenharmony_ci case FE_CAB_MOD_QAM1024: 19698c2ecf20Sopenharmony_ci QamSizeCorr = 944; 19708c2ecf20Sopenharmony_ci break; 19718c2ecf20Sopenharmony_ci default: 19728c2ecf20Sopenharmony_ci break; 19738c2ecf20Sopenharmony_ci } 19748c2ecf20Sopenharmony_ci 19758c2ecf20Sopenharmony_ci /* Transfer ratio calculation */ 19768c2ecf20Sopenharmony_ci if (adc_hz != 0) { 19778c2ecf20Sopenharmony_ci u32_tmp = 256 * SymbolRate; 19788c2ecf20Sopenharmony_ci u32_tmp = u32_tmp / adc_hz; 19798c2ecf20Sopenharmony_ci } 19808c2ecf20Sopenharmony_ci stv0367_writereg(state, R367CAB_EQU_CRL_TFR, (u8)u32_tmp); 19818c2ecf20Sopenharmony_ci 19828c2ecf20Sopenharmony_ci /* Symbol rate and SRC gain calculation */ 19838c2ecf20Sopenharmony_ci adp_khz = (mclk_hz >> 1) / 1000;/* TRL works at half the system clock */ 19848c2ecf20Sopenharmony_ci if (adp_khz != 0) { 19858c2ecf20Sopenharmony_ci u32_tmp = SymbolRate; 19868c2ecf20Sopenharmony_ci u32_tmp1 = SymbolRate; 19878c2ecf20Sopenharmony_ci 19888c2ecf20Sopenharmony_ci if (u32_tmp < 2097152) { /* 2097152 = 2^21 */ 19898c2ecf20Sopenharmony_ci /* Symbol rate calculation */ 19908c2ecf20Sopenharmony_ci u32_tmp *= 2048; /* 2048 = 2^11 */ 19918c2ecf20Sopenharmony_ci u32_tmp = u32_tmp / adp_khz; 19928c2ecf20Sopenharmony_ci u32_tmp = u32_tmp * 16384; /* 16384 = 2^14 */ 19938c2ecf20Sopenharmony_ci u32_tmp /= 125 ; /* 125 = 1000/2^3 */ 19948c2ecf20Sopenharmony_ci u32_tmp = u32_tmp * 8; /* 8 = 2^3 */ 19958c2ecf20Sopenharmony_ci 19968c2ecf20Sopenharmony_ci /* SRC Gain Calculation */ 19978c2ecf20Sopenharmony_ci u32_tmp1 *= 2048; /* *2*2^10 */ 19988c2ecf20Sopenharmony_ci u32_tmp1 /= 439; /* *2/878 */ 19998c2ecf20Sopenharmony_ci u32_tmp1 *= 256; /* *2^8 */ 20008c2ecf20Sopenharmony_ci u32_tmp1 = u32_tmp1 / adp_khz; /* /(AdpClk in kHz) */ 20018c2ecf20Sopenharmony_ci u32_tmp1 *= QamSizeCorr * 9; /* *1000*corr factor */ 20028c2ecf20Sopenharmony_ci u32_tmp1 = u32_tmp1 / 10000000; 20038c2ecf20Sopenharmony_ci 20048c2ecf20Sopenharmony_ci } else if (u32_tmp < 4194304) { /* 4194304 = 2**22 */ 20058c2ecf20Sopenharmony_ci /* Symbol rate calculation */ 20068c2ecf20Sopenharmony_ci u32_tmp *= 1024 ; /* 1024 = 2**10 */ 20078c2ecf20Sopenharmony_ci u32_tmp = u32_tmp / adp_khz; 20088c2ecf20Sopenharmony_ci u32_tmp = u32_tmp * 16384; /* 16384 = 2**14 */ 20098c2ecf20Sopenharmony_ci u32_tmp /= 125 ; /* 125 = 1000/2**3 */ 20108c2ecf20Sopenharmony_ci u32_tmp = u32_tmp * 16; /* 16 = 2**4 */ 20118c2ecf20Sopenharmony_ci 20128c2ecf20Sopenharmony_ci /* SRC Gain Calculation */ 20138c2ecf20Sopenharmony_ci u32_tmp1 *= 1024; /* *2*2^9 */ 20148c2ecf20Sopenharmony_ci u32_tmp1 /= 439; /* *2/878 */ 20158c2ecf20Sopenharmony_ci u32_tmp1 *= 256; /* *2^8 */ 20168c2ecf20Sopenharmony_ci u32_tmp1 = u32_tmp1 / adp_khz; /* /(AdpClk in kHz)*/ 20178c2ecf20Sopenharmony_ci u32_tmp1 *= QamSizeCorr * 9; /* *1000*corr factor */ 20188c2ecf20Sopenharmony_ci u32_tmp1 = u32_tmp1 / 5000000; 20198c2ecf20Sopenharmony_ci } else if (u32_tmp < 8388607) { /* 8388607 = 2**23 */ 20208c2ecf20Sopenharmony_ci /* Symbol rate calculation */ 20218c2ecf20Sopenharmony_ci u32_tmp *= 512 ; /* 512 = 2**9 */ 20228c2ecf20Sopenharmony_ci u32_tmp = u32_tmp / adp_khz; 20238c2ecf20Sopenharmony_ci u32_tmp = u32_tmp * 16384; /* 16384 = 2**14 */ 20248c2ecf20Sopenharmony_ci u32_tmp /= 125 ; /* 125 = 1000/2**3 */ 20258c2ecf20Sopenharmony_ci u32_tmp = u32_tmp * 32; /* 32 = 2**5 */ 20268c2ecf20Sopenharmony_ci 20278c2ecf20Sopenharmony_ci /* SRC Gain Calculation */ 20288c2ecf20Sopenharmony_ci u32_tmp1 *= 512; /* *2*2^8 */ 20298c2ecf20Sopenharmony_ci u32_tmp1 /= 439; /* *2/878 */ 20308c2ecf20Sopenharmony_ci u32_tmp1 *= 256; /* *2^8 */ 20318c2ecf20Sopenharmony_ci u32_tmp1 = u32_tmp1 / adp_khz; /* /(AdpClk in kHz) */ 20328c2ecf20Sopenharmony_ci u32_tmp1 *= QamSizeCorr * 9; /* *1000*corr factor */ 20338c2ecf20Sopenharmony_ci u32_tmp1 = u32_tmp1 / 2500000; 20348c2ecf20Sopenharmony_ci } else { 20358c2ecf20Sopenharmony_ci /* Symbol rate calculation */ 20368c2ecf20Sopenharmony_ci u32_tmp *= 256 ; /* 256 = 2**8 */ 20378c2ecf20Sopenharmony_ci u32_tmp = u32_tmp / adp_khz; 20388c2ecf20Sopenharmony_ci u32_tmp = u32_tmp * 16384; /* 16384 = 2**13 */ 20398c2ecf20Sopenharmony_ci u32_tmp /= 125 ; /* 125 = 1000/2**3 */ 20408c2ecf20Sopenharmony_ci u32_tmp = u32_tmp * 64; /* 64 = 2**6 */ 20418c2ecf20Sopenharmony_ci 20428c2ecf20Sopenharmony_ci /* SRC Gain Calculation */ 20438c2ecf20Sopenharmony_ci u32_tmp1 *= 256; /* 2*2^7 */ 20448c2ecf20Sopenharmony_ci u32_tmp1 /= 439; /* *2/878 */ 20458c2ecf20Sopenharmony_ci u32_tmp1 *= 256; /* *2^8 */ 20468c2ecf20Sopenharmony_ci u32_tmp1 = u32_tmp1 / adp_khz; /* /(AdpClk in kHz) */ 20478c2ecf20Sopenharmony_ci u32_tmp1 *= QamSizeCorr * 9; /* *1000*corr factor */ 20488c2ecf20Sopenharmony_ci u32_tmp1 = u32_tmp1 / 1250000; 20498c2ecf20Sopenharmony_ci } 20508c2ecf20Sopenharmony_ci } 20518c2ecf20Sopenharmony_ci#if 0 20528c2ecf20Sopenharmony_ci /* Filters' coefficients are calculated and written 20538c2ecf20Sopenharmony_ci into registers only if the filters are enabled */ 20548c2ecf20Sopenharmony_ci if (stv0367_readbits(state, F367CAB_ADJ_EN)) { 20558c2ecf20Sopenharmony_ci stv0367cab_SetIirAdjacentcoefficient(state, mclk_hz, 20568c2ecf20Sopenharmony_ci SymbolRate); 20578c2ecf20Sopenharmony_ci /* AllPass filter must be enabled 20588c2ecf20Sopenharmony_ci when the adjacents filter is used */ 20598c2ecf20Sopenharmony_ci stv0367_writebits(state, F367CAB_ALLPASSFILT_EN, 1); 20608c2ecf20Sopenharmony_ci stv0367cab_SetAllPasscoefficient(state, mclk_hz, SymbolRate); 20618c2ecf20Sopenharmony_ci } else 20628c2ecf20Sopenharmony_ci /* AllPass filter must be disabled 20638c2ecf20Sopenharmony_ci when the adjacents filter is not used */ 20648c2ecf20Sopenharmony_ci#endif 20658c2ecf20Sopenharmony_ci stv0367_writebits(state, F367CAB_ALLPASSFILT_EN, 0); 20668c2ecf20Sopenharmony_ci 20678c2ecf20Sopenharmony_ci stv0367_writereg(state, R367CAB_SRC_NCO_LL, u32_tmp); 20688c2ecf20Sopenharmony_ci stv0367_writereg(state, R367CAB_SRC_NCO_LH, (u32_tmp >> 8)); 20698c2ecf20Sopenharmony_ci stv0367_writereg(state, R367CAB_SRC_NCO_HL, (u32_tmp >> 16)); 20708c2ecf20Sopenharmony_ci stv0367_writereg(state, R367CAB_SRC_NCO_HH, (u32_tmp >> 24)); 20718c2ecf20Sopenharmony_ci 20728c2ecf20Sopenharmony_ci stv0367_writereg(state, R367CAB_IQDEM_GAIN_SRC_L, u32_tmp1 & 0x00ff); 20738c2ecf20Sopenharmony_ci stv0367_writebits(state, F367CAB_GAIN_SRC_HI, (u32_tmp1 >> 8) & 0x00ff); 20748c2ecf20Sopenharmony_ci 20758c2ecf20Sopenharmony_ci return SymbolRate ; 20768c2ecf20Sopenharmony_ci} 20778c2ecf20Sopenharmony_ci 20788c2ecf20Sopenharmony_cistatic u32 stv0367cab_GetSymbolRate(struct stv0367_state *state, u32 mclk_hz) 20798c2ecf20Sopenharmony_ci{ 20808c2ecf20Sopenharmony_ci u32 regsym; 20818c2ecf20Sopenharmony_ci u32 adp_khz; 20828c2ecf20Sopenharmony_ci 20838c2ecf20Sopenharmony_ci regsym = stv0367_readreg(state, R367CAB_SRC_NCO_LL) + 20848c2ecf20Sopenharmony_ci (stv0367_readreg(state, R367CAB_SRC_NCO_LH) << 8) + 20858c2ecf20Sopenharmony_ci (stv0367_readreg(state, R367CAB_SRC_NCO_HL) << 16) + 20868c2ecf20Sopenharmony_ci (stv0367_readreg(state, R367CAB_SRC_NCO_HH) << 24); 20878c2ecf20Sopenharmony_ci 20888c2ecf20Sopenharmony_ci adp_khz = (mclk_hz >> 1) / 1000;/* TRL works at half the system clock */ 20898c2ecf20Sopenharmony_ci 20908c2ecf20Sopenharmony_ci if (regsym < 134217728) { /* 134217728L = 2**27*/ 20918c2ecf20Sopenharmony_ci regsym = regsym * 32; /* 32 = 2**5 */ 20928c2ecf20Sopenharmony_ci regsym = regsym / 32768; /* 32768L = 2**15 */ 20938c2ecf20Sopenharmony_ci regsym = adp_khz * regsym; /* AdpClk in kHz */ 20948c2ecf20Sopenharmony_ci regsym = regsym / 128; /* 128 = 2**7 */ 20958c2ecf20Sopenharmony_ci regsym *= 125 ; /* 125 = 1000/2**3 */ 20968c2ecf20Sopenharmony_ci regsym /= 2048 ; /* 2048 = 2**11 */ 20978c2ecf20Sopenharmony_ci } else if (regsym < 268435456) { /* 268435456L = 2**28 */ 20988c2ecf20Sopenharmony_ci regsym = regsym * 16; /* 16 = 2**4 */ 20998c2ecf20Sopenharmony_ci regsym = regsym / 32768; /* 32768L = 2**15 */ 21008c2ecf20Sopenharmony_ci regsym = adp_khz * regsym; /* AdpClk in kHz */ 21018c2ecf20Sopenharmony_ci regsym = regsym / 128; /* 128 = 2**7 */ 21028c2ecf20Sopenharmony_ci regsym *= 125 ; /* 125 = 1000/2**3*/ 21038c2ecf20Sopenharmony_ci regsym /= 1024 ; /* 256 = 2**10*/ 21048c2ecf20Sopenharmony_ci } else if (regsym < 536870912) { /* 536870912L = 2**29*/ 21058c2ecf20Sopenharmony_ci regsym = regsym * 8; /* 8 = 2**3 */ 21068c2ecf20Sopenharmony_ci regsym = regsym / 32768; /* 32768L = 2**15 */ 21078c2ecf20Sopenharmony_ci regsym = adp_khz * regsym; /* AdpClk in kHz */ 21088c2ecf20Sopenharmony_ci regsym = regsym / 128; /* 128 = 2**7 */ 21098c2ecf20Sopenharmony_ci regsym *= 125 ; /* 125 = 1000/2**3 */ 21108c2ecf20Sopenharmony_ci regsym /= 512 ; /* 128 = 2**9 */ 21118c2ecf20Sopenharmony_ci } else { 21128c2ecf20Sopenharmony_ci regsym = regsym * 4; /* 4 = 2**2 */ 21138c2ecf20Sopenharmony_ci regsym = regsym / 32768; /* 32768L = 2**15 */ 21148c2ecf20Sopenharmony_ci regsym = adp_khz * regsym; /* AdpClk in kHz */ 21158c2ecf20Sopenharmony_ci regsym = regsym / 128; /* 128 = 2**7 */ 21168c2ecf20Sopenharmony_ci regsym *= 125 ; /* 125 = 1000/2**3 */ 21178c2ecf20Sopenharmony_ci regsym /= 256 ; /* 64 = 2**8 */ 21188c2ecf20Sopenharmony_ci } 21198c2ecf20Sopenharmony_ci 21208c2ecf20Sopenharmony_ci return regsym; 21218c2ecf20Sopenharmony_ci} 21228c2ecf20Sopenharmony_ci 21238c2ecf20Sopenharmony_cistatic u32 stv0367cab_fsm_status(struct stv0367_state *state) 21248c2ecf20Sopenharmony_ci{ 21258c2ecf20Sopenharmony_ci return stv0367_readbits(state, F367CAB_FSM_STATUS); 21268c2ecf20Sopenharmony_ci} 21278c2ecf20Sopenharmony_ci 21288c2ecf20Sopenharmony_cistatic u32 stv0367cab_qamfec_lock(struct stv0367_state *state) 21298c2ecf20Sopenharmony_ci{ 21308c2ecf20Sopenharmony_ci return stv0367_readbits(state, 21318c2ecf20Sopenharmony_ci (state->cab_state->qamfec_status_reg ? 21328c2ecf20Sopenharmony_ci state->cab_state->qamfec_status_reg : 21338c2ecf20Sopenharmony_ci F367CAB_QAMFEC_LOCK)); 21348c2ecf20Sopenharmony_ci} 21358c2ecf20Sopenharmony_ci 21368c2ecf20Sopenharmony_cistatic 21378c2ecf20Sopenharmony_cienum stv0367_cab_signal_type stv0367cab_fsm_signaltype(u32 qam_fsm_status) 21388c2ecf20Sopenharmony_ci{ 21398c2ecf20Sopenharmony_ci enum stv0367_cab_signal_type signaltype = FE_CAB_NOAGC; 21408c2ecf20Sopenharmony_ci 21418c2ecf20Sopenharmony_ci switch (qam_fsm_status) { 21428c2ecf20Sopenharmony_ci case 1: 21438c2ecf20Sopenharmony_ci signaltype = FE_CAB_NOAGC; 21448c2ecf20Sopenharmony_ci break; 21458c2ecf20Sopenharmony_ci case 2: 21468c2ecf20Sopenharmony_ci signaltype = FE_CAB_NOTIMING; 21478c2ecf20Sopenharmony_ci break; 21488c2ecf20Sopenharmony_ci case 3: 21498c2ecf20Sopenharmony_ci signaltype = FE_CAB_TIMINGOK; 21508c2ecf20Sopenharmony_ci break; 21518c2ecf20Sopenharmony_ci case 4: 21528c2ecf20Sopenharmony_ci signaltype = FE_CAB_NOCARRIER; 21538c2ecf20Sopenharmony_ci break; 21548c2ecf20Sopenharmony_ci case 5: 21558c2ecf20Sopenharmony_ci signaltype = FE_CAB_CARRIEROK; 21568c2ecf20Sopenharmony_ci break; 21578c2ecf20Sopenharmony_ci case 7: 21588c2ecf20Sopenharmony_ci signaltype = FE_CAB_NOBLIND; 21598c2ecf20Sopenharmony_ci break; 21608c2ecf20Sopenharmony_ci case 8: 21618c2ecf20Sopenharmony_ci signaltype = FE_CAB_BLINDOK; 21628c2ecf20Sopenharmony_ci break; 21638c2ecf20Sopenharmony_ci case 10: 21648c2ecf20Sopenharmony_ci signaltype = FE_CAB_NODEMOD; 21658c2ecf20Sopenharmony_ci break; 21668c2ecf20Sopenharmony_ci case 11: 21678c2ecf20Sopenharmony_ci signaltype = FE_CAB_DEMODOK; 21688c2ecf20Sopenharmony_ci break; 21698c2ecf20Sopenharmony_ci case 12: 21708c2ecf20Sopenharmony_ci signaltype = FE_CAB_DEMODOK; 21718c2ecf20Sopenharmony_ci break; 21728c2ecf20Sopenharmony_ci case 13: 21738c2ecf20Sopenharmony_ci signaltype = FE_CAB_NODEMOD; 21748c2ecf20Sopenharmony_ci break; 21758c2ecf20Sopenharmony_ci case 14: 21768c2ecf20Sopenharmony_ci signaltype = FE_CAB_NOBLIND; 21778c2ecf20Sopenharmony_ci break; 21788c2ecf20Sopenharmony_ci case 15: 21798c2ecf20Sopenharmony_ci signaltype = FE_CAB_NOSIGNAL; 21808c2ecf20Sopenharmony_ci break; 21818c2ecf20Sopenharmony_ci default: 21828c2ecf20Sopenharmony_ci break; 21838c2ecf20Sopenharmony_ci } 21848c2ecf20Sopenharmony_ci 21858c2ecf20Sopenharmony_ci return signaltype; 21868c2ecf20Sopenharmony_ci} 21878c2ecf20Sopenharmony_ci 21888c2ecf20Sopenharmony_cistatic int stv0367cab_read_status(struct dvb_frontend *fe, 21898c2ecf20Sopenharmony_ci enum fe_status *status) 21908c2ecf20Sopenharmony_ci{ 21918c2ecf20Sopenharmony_ci struct stv0367_state *state = fe->demodulator_priv; 21928c2ecf20Sopenharmony_ci 21938c2ecf20Sopenharmony_ci dprintk("%s:\n", __func__); 21948c2ecf20Sopenharmony_ci 21958c2ecf20Sopenharmony_ci *status = 0; 21968c2ecf20Sopenharmony_ci 21978c2ecf20Sopenharmony_ci /* update cab_state->state from QAM_FSM_STATUS */ 21988c2ecf20Sopenharmony_ci state->cab_state->state = stv0367cab_fsm_signaltype( 21998c2ecf20Sopenharmony_ci stv0367cab_fsm_status(state)); 22008c2ecf20Sopenharmony_ci 22018c2ecf20Sopenharmony_ci if (stv0367cab_qamfec_lock(state)) { 22028c2ecf20Sopenharmony_ci *status = FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI 22038c2ecf20Sopenharmony_ci | FE_HAS_SYNC | FE_HAS_LOCK; 22048c2ecf20Sopenharmony_ci dprintk("%s: stv0367 has locked\n", __func__); 22058c2ecf20Sopenharmony_ci } else { 22068c2ecf20Sopenharmony_ci if (state->cab_state->state > FE_CAB_NOSIGNAL) 22078c2ecf20Sopenharmony_ci *status |= FE_HAS_SIGNAL; 22088c2ecf20Sopenharmony_ci 22098c2ecf20Sopenharmony_ci if (state->cab_state->state > FE_CAB_NOCARRIER) 22108c2ecf20Sopenharmony_ci *status |= FE_HAS_CARRIER; 22118c2ecf20Sopenharmony_ci 22128c2ecf20Sopenharmony_ci if (state->cab_state->state >= FE_CAB_DEMODOK) 22138c2ecf20Sopenharmony_ci *status |= FE_HAS_VITERBI; 22148c2ecf20Sopenharmony_ci 22158c2ecf20Sopenharmony_ci if (state->cab_state->state >= FE_CAB_DATAOK) 22168c2ecf20Sopenharmony_ci *status |= FE_HAS_SYNC; 22178c2ecf20Sopenharmony_ci } 22188c2ecf20Sopenharmony_ci 22198c2ecf20Sopenharmony_ci return 0; 22208c2ecf20Sopenharmony_ci} 22218c2ecf20Sopenharmony_ci 22228c2ecf20Sopenharmony_cistatic int stv0367cab_standby(struct dvb_frontend *fe, u8 standby_on) 22238c2ecf20Sopenharmony_ci{ 22248c2ecf20Sopenharmony_ci struct stv0367_state *state = fe->demodulator_priv; 22258c2ecf20Sopenharmony_ci 22268c2ecf20Sopenharmony_ci dprintk("%s:\n", __func__); 22278c2ecf20Sopenharmony_ci 22288c2ecf20Sopenharmony_ci if (standby_on) { 22298c2ecf20Sopenharmony_ci stv0367_writebits(state, F367CAB_BYPASS_PLLXN, 0x03); 22308c2ecf20Sopenharmony_ci stv0367_writebits(state, F367CAB_STDBY_PLLXN, 0x01); 22318c2ecf20Sopenharmony_ci stv0367_writebits(state, F367CAB_STDBY, 1); 22328c2ecf20Sopenharmony_ci stv0367_writebits(state, F367CAB_STDBY_CORE, 1); 22338c2ecf20Sopenharmony_ci stv0367_writebits(state, F367CAB_EN_BUFFER_I, 0); 22348c2ecf20Sopenharmony_ci stv0367_writebits(state, F367CAB_EN_BUFFER_Q, 0); 22358c2ecf20Sopenharmony_ci stv0367_writebits(state, F367CAB_POFFQ, 1); 22368c2ecf20Sopenharmony_ci stv0367_writebits(state, F367CAB_POFFI, 1); 22378c2ecf20Sopenharmony_ci } else { 22388c2ecf20Sopenharmony_ci stv0367_writebits(state, F367CAB_STDBY_PLLXN, 0x00); 22398c2ecf20Sopenharmony_ci stv0367_writebits(state, F367CAB_BYPASS_PLLXN, 0x00); 22408c2ecf20Sopenharmony_ci stv0367_writebits(state, F367CAB_STDBY, 0); 22418c2ecf20Sopenharmony_ci stv0367_writebits(state, F367CAB_STDBY_CORE, 0); 22428c2ecf20Sopenharmony_ci stv0367_writebits(state, F367CAB_EN_BUFFER_I, 1); 22438c2ecf20Sopenharmony_ci stv0367_writebits(state, F367CAB_EN_BUFFER_Q, 1); 22448c2ecf20Sopenharmony_ci stv0367_writebits(state, F367CAB_POFFQ, 0); 22458c2ecf20Sopenharmony_ci stv0367_writebits(state, F367CAB_POFFI, 0); 22468c2ecf20Sopenharmony_ci } 22478c2ecf20Sopenharmony_ci 22488c2ecf20Sopenharmony_ci return 0; 22498c2ecf20Sopenharmony_ci} 22508c2ecf20Sopenharmony_ci 22518c2ecf20Sopenharmony_cistatic int stv0367cab_sleep(struct dvb_frontend *fe) 22528c2ecf20Sopenharmony_ci{ 22538c2ecf20Sopenharmony_ci return stv0367cab_standby(fe, 1); 22548c2ecf20Sopenharmony_ci} 22558c2ecf20Sopenharmony_ci 22568c2ecf20Sopenharmony_cistatic int stv0367cab_init(struct dvb_frontend *fe) 22578c2ecf20Sopenharmony_ci{ 22588c2ecf20Sopenharmony_ci struct stv0367_state *state = fe->demodulator_priv; 22598c2ecf20Sopenharmony_ci struct stv0367cab_state *cab_state = state->cab_state; 22608c2ecf20Sopenharmony_ci 22618c2ecf20Sopenharmony_ci dprintk("%s:\n", __func__); 22628c2ecf20Sopenharmony_ci 22638c2ecf20Sopenharmony_ci stv0367_write_table(state, 22648c2ecf20Sopenharmony_ci stv0367_deftabs[state->deftabs][STV0367_TAB_CAB]); 22658c2ecf20Sopenharmony_ci 22668c2ecf20Sopenharmony_ci switch (state->config->ts_mode) { 22678c2ecf20Sopenharmony_ci case STV0367_DVBCI_CLOCK: 22688c2ecf20Sopenharmony_ci dprintk("Setting TSMode = STV0367_DVBCI_CLOCK\n"); 22698c2ecf20Sopenharmony_ci stv0367_writebits(state, F367CAB_OUTFORMAT, 0x03); 22708c2ecf20Sopenharmony_ci break; 22718c2ecf20Sopenharmony_ci case STV0367_SERIAL_PUNCT_CLOCK: 22728c2ecf20Sopenharmony_ci case STV0367_SERIAL_CONT_CLOCK: 22738c2ecf20Sopenharmony_ci stv0367_writebits(state, F367CAB_OUTFORMAT, 0x01); 22748c2ecf20Sopenharmony_ci break; 22758c2ecf20Sopenharmony_ci case STV0367_PARALLEL_PUNCT_CLOCK: 22768c2ecf20Sopenharmony_ci case STV0367_OUTPUTMODE_DEFAULT: 22778c2ecf20Sopenharmony_ci stv0367_writebits(state, F367CAB_OUTFORMAT, 0x00); 22788c2ecf20Sopenharmony_ci break; 22798c2ecf20Sopenharmony_ci } 22808c2ecf20Sopenharmony_ci 22818c2ecf20Sopenharmony_ci switch (state->config->clk_pol) { 22828c2ecf20Sopenharmony_ci case STV0367_RISINGEDGE_CLOCK: 22838c2ecf20Sopenharmony_ci stv0367_writebits(state, F367CAB_CLK_POLARITY, 0x00); 22848c2ecf20Sopenharmony_ci break; 22858c2ecf20Sopenharmony_ci case STV0367_FALLINGEDGE_CLOCK: 22868c2ecf20Sopenharmony_ci case STV0367_CLOCKPOLARITY_DEFAULT: 22878c2ecf20Sopenharmony_ci stv0367_writebits(state, F367CAB_CLK_POLARITY, 0x01); 22888c2ecf20Sopenharmony_ci break; 22898c2ecf20Sopenharmony_ci } 22908c2ecf20Sopenharmony_ci 22918c2ecf20Sopenharmony_ci stv0367_writebits(state, F367CAB_SYNC_STRIP, 0x00); 22928c2ecf20Sopenharmony_ci 22938c2ecf20Sopenharmony_ci stv0367_writebits(state, F367CAB_CT_NBST, 0x01); 22948c2ecf20Sopenharmony_ci 22958c2ecf20Sopenharmony_ci stv0367_writebits(state, F367CAB_TS_SWAP, 0x01); 22968c2ecf20Sopenharmony_ci 22978c2ecf20Sopenharmony_ci stv0367_writebits(state, F367CAB_FIFO_BYPASS, 0x00); 22988c2ecf20Sopenharmony_ci 22998c2ecf20Sopenharmony_ci stv0367_writereg(state, R367CAB_ANACTRL, 0x00);/*PLL enabled and used */ 23008c2ecf20Sopenharmony_ci 23018c2ecf20Sopenharmony_ci cab_state->mclk = stv0367cab_get_mclk(fe, state->config->xtal); 23028c2ecf20Sopenharmony_ci cab_state->adc_clk = stv0367cab_get_adc_freq(fe, state->config->xtal); 23038c2ecf20Sopenharmony_ci 23048c2ecf20Sopenharmony_ci return 0; 23058c2ecf20Sopenharmony_ci} 23068c2ecf20Sopenharmony_cistatic 23078c2ecf20Sopenharmony_cienum stv0367_cab_signal_type stv0367cab_algo(struct stv0367_state *state, 23088c2ecf20Sopenharmony_ci struct dtv_frontend_properties *p) 23098c2ecf20Sopenharmony_ci{ 23108c2ecf20Sopenharmony_ci struct stv0367cab_state *cab_state = state->cab_state; 23118c2ecf20Sopenharmony_ci enum stv0367_cab_signal_type signalType = FE_CAB_NOAGC; 23128c2ecf20Sopenharmony_ci u32 QAMFEC_Lock, QAM_Lock, u32_tmp, ifkhz, 23138c2ecf20Sopenharmony_ci LockTime, TRLTimeOut, AGCTimeOut, CRLSymbols, 23148c2ecf20Sopenharmony_ci CRLTimeOut, EQLTimeOut, DemodTimeOut, FECTimeOut; 23158c2ecf20Sopenharmony_ci u8 TrackAGCAccum; 23168c2ecf20Sopenharmony_ci s32 tmp; 23178c2ecf20Sopenharmony_ci 23188c2ecf20Sopenharmony_ci dprintk("%s:\n", __func__); 23198c2ecf20Sopenharmony_ci 23208c2ecf20Sopenharmony_ci stv0367_get_if_khz(state, &ifkhz); 23218c2ecf20Sopenharmony_ci 23228c2ecf20Sopenharmony_ci /* Timeouts calculation */ 23238c2ecf20Sopenharmony_ci /* A max lock time of 25 ms is allowed for delayed AGC */ 23248c2ecf20Sopenharmony_ci AGCTimeOut = 25; 23258c2ecf20Sopenharmony_ci /* 100000 symbols needed by the TRL as a maximum value */ 23268c2ecf20Sopenharmony_ci TRLTimeOut = 100000000 / p->symbol_rate; 23278c2ecf20Sopenharmony_ci /* CRLSymbols is the needed number of symbols to achieve a lock 23288c2ecf20Sopenharmony_ci within [-4%, +4%] of the symbol rate. 23298c2ecf20Sopenharmony_ci CRL timeout is calculated 23308c2ecf20Sopenharmony_ci for a lock within [-search_range, +search_range]. 23318c2ecf20Sopenharmony_ci EQL timeout can be changed depending on 23328c2ecf20Sopenharmony_ci the micro-reflections we want to handle. 23338c2ecf20Sopenharmony_ci A characterization must be performed 23348c2ecf20Sopenharmony_ci with these echoes to get new timeout values. 23358c2ecf20Sopenharmony_ci */ 23368c2ecf20Sopenharmony_ci switch (p->modulation) { 23378c2ecf20Sopenharmony_ci case QAM_16: 23388c2ecf20Sopenharmony_ci CRLSymbols = 150000; 23398c2ecf20Sopenharmony_ci EQLTimeOut = 100; 23408c2ecf20Sopenharmony_ci break; 23418c2ecf20Sopenharmony_ci case QAM_32: 23428c2ecf20Sopenharmony_ci CRLSymbols = 250000; 23438c2ecf20Sopenharmony_ci EQLTimeOut = 100; 23448c2ecf20Sopenharmony_ci break; 23458c2ecf20Sopenharmony_ci case QAM_64: 23468c2ecf20Sopenharmony_ci CRLSymbols = 200000; 23478c2ecf20Sopenharmony_ci EQLTimeOut = 100; 23488c2ecf20Sopenharmony_ci break; 23498c2ecf20Sopenharmony_ci case QAM_128: 23508c2ecf20Sopenharmony_ci CRLSymbols = 250000; 23518c2ecf20Sopenharmony_ci EQLTimeOut = 100; 23528c2ecf20Sopenharmony_ci break; 23538c2ecf20Sopenharmony_ci case QAM_256: 23548c2ecf20Sopenharmony_ci CRLSymbols = 250000; 23558c2ecf20Sopenharmony_ci EQLTimeOut = 100; 23568c2ecf20Sopenharmony_ci break; 23578c2ecf20Sopenharmony_ci default: 23588c2ecf20Sopenharmony_ci CRLSymbols = 200000; 23598c2ecf20Sopenharmony_ci EQLTimeOut = 100; 23608c2ecf20Sopenharmony_ci break; 23618c2ecf20Sopenharmony_ci } 23628c2ecf20Sopenharmony_ci#if 0 23638c2ecf20Sopenharmony_ci if (pIntParams->search_range < 0) { 23648c2ecf20Sopenharmony_ci CRLTimeOut = (25 * CRLSymbols * 23658c2ecf20Sopenharmony_ci (-pIntParams->search_range / 1000)) / 23668c2ecf20Sopenharmony_ci (pIntParams->symbol_rate / 1000); 23678c2ecf20Sopenharmony_ci } else 23688c2ecf20Sopenharmony_ci#endif 23698c2ecf20Sopenharmony_ci CRLTimeOut = (25 * CRLSymbols * (cab_state->search_range / 1000)) / 23708c2ecf20Sopenharmony_ci (p->symbol_rate / 1000); 23718c2ecf20Sopenharmony_ci 23728c2ecf20Sopenharmony_ci CRLTimeOut = (1000 * CRLTimeOut) / p->symbol_rate; 23738c2ecf20Sopenharmony_ci /* Timeouts below 50ms are coerced */ 23748c2ecf20Sopenharmony_ci if (CRLTimeOut < 50) 23758c2ecf20Sopenharmony_ci CRLTimeOut = 50; 23768c2ecf20Sopenharmony_ci /* A maximum of 100 TS packets is needed to get FEC lock even in case 23778c2ecf20Sopenharmony_ci the spectrum inversion needs to be changed. 23788c2ecf20Sopenharmony_ci This is equal to 20 ms in case of the lowest symbol rate of 0.87Msps 23798c2ecf20Sopenharmony_ci */ 23808c2ecf20Sopenharmony_ci FECTimeOut = 20; 23818c2ecf20Sopenharmony_ci DemodTimeOut = AGCTimeOut + TRLTimeOut + CRLTimeOut + EQLTimeOut; 23828c2ecf20Sopenharmony_ci 23838c2ecf20Sopenharmony_ci dprintk("%s: DemodTimeOut=%d\n", __func__, DemodTimeOut); 23848c2ecf20Sopenharmony_ci 23858c2ecf20Sopenharmony_ci /* Reset the TRL to ensure nothing starts until the 23868c2ecf20Sopenharmony_ci AGC is stable which ensures a better lock time 23878c2ecf20Sopenharmony_ci */ 23888c2ecf20Sopenharmony_ci stv0367_writereg(state, R367CAB_CTRL_1, 0x04); 23898c2ecf20Sopenharmony_ci /* Set AGC accumulation time to minimum and lock threshold to maximum 23908c2ecf20Sopenharmony_ci in order to speed up the AGC lock */ 23918c2ecf20Sopenharmony_ci TrackAGCAccum = stv0367_readbits(state, F367CAB_AGC_ACCUMRSTSEL); 23928c2ecf20Sopenharmony_ci stv0367_writebits(state, F367CAB_AGC_ACCUMRSTSEL, 0x0); 23938c2ecf20Sopenharmony_ci /* Modulus Mapper is disabled */ 23948c2ecf20Sopenharmony_ci stv0367_writebits(state, F367CAB_MODULUSMAP_EN, 0); 23958c2ecf20Sopenharmony_ci /* Disable the sweep function */ 23968c2ecf20Sopenharmony_ci stv0367_writebits(state, F367CAB_SWEEP_EN, 0); 23978c2ecf20Sopenharmony_ci /* The sweep function is never used, Sweep rate must be set to 0 */ 23988c2ecf20Sopenharmony_ci /* Set the derotator frequency in Hz */ 23998c2ecf20Sopenharmony_ci stv0367cab_set_derot_freq(state, cab_state->adc_clk, 24008c2ecf20Sopenharmony_ci (1000 * (s32)ifkhz + cab_state->derot_offset)); 24018c2ecf20Sopenharmony_ci /* Disable the Allpass Filter when the symbol rate is out of range */ 24028c2ecf20Sopenharmony_ci if ((p->symbol_rate > 10800000) | (p->symbol_rate < 1800000)) { 24038c2ecf20Sopenharmony_ci stv0367_writebits(state, F367CAB_ADJ_EN, 0); 24048c2ecf20Sopenharmony_ci stv0367_writebits(state, F367CAB_ALLPASSFILT_EN, 0); 24058c2ecf20Sopenharmony_ci } 24068c2ecf20Sopenharmony_ci#if 0 24078c2ecf20Sopenharmony_ci /* Check if the tuner is locked */ 24088c2ecf20Sopenharmony_ci tuner_lock = stv0367cab_tuner_get_status(fe); 24098c2ecf20Sopenharmony_ci if (tuner_lock == 0) 24108c2ecf20Sopenharmony_ci return FE_367CAB_NOTUNER; 24118c2ecf20Sopenharmony_ci#endif 24128c2ecf20Sopenharmony_ci /* Release the TRL to start demodulator acquisition */ 24138c2ecf20Sopenharmony_ci /* Wait for QAM lock */ 24148c2ecf20Sopenharmony_ci LockTime = 0; 24158c2ecf20Sopenharmony_ci stv0367_writereg(state, R367CAB_CTRL_1, 0x00); 24168c2ecf20Sopenharmony_ci do { 24178c2ecf20Sopenharmony_ci QAM_Lock = stv0367cab_fsm_status(state); 24188c2ecf20Sopenharmony_ci if ((LockTime >= (DemodTimeOut - EQLTimeOut)) && 24198c2ecf20Sopenharmony_ci (QAM_Lock == 0x04)) 24208c2ecf20Sopenharmony_ci /* 24218c2ecf20Sopenharmony_ci * We don't wait longer, the frequency/phase offset 24228c2ecf20Sopenharmony_ci * must be too big 24238c2ecf20Sopenharmony_ci */ 24248c2ecf20Sopenharmony_ci LockTime = DemodTimeOut; 24258c2ecf20Sopenharmony_ci else if ((LockTime >= (AGCTimeOut + TRLTimeOut)) && 24268c2ecf20Sopenharmony_ci (QAM_Lock == 0x02)) 24278c2ecf20Sopenharmony_ci /* 24288c2ecf20Sopenharmony_ci * We don't wait longer, either there is no signal or 24298c2ecf20Sopenharmony_ci * it is not the right symbol rate or it is an analog 24308c2ecf20Sopenharmony_ci * carrier 24318c2ecf20Sopenharmony_ci */ 24328c2ecf20Sopenharmony_ci { 24338c2ecf20Sopenharmony_ci LockTime = DemodTimeOut; 24348c2ecf20Sopenharmony_ci u32_tmp = stv0367_readbits(state, 24358c2ecf20Sopenharmony_ci F367CAB_AGC_PWR_WORD_LO) + 24368c2ecf20Sopenharmony_ci (stv0367_readbits(state, 24378c2ecf20Sopenharmony_ci F367CAB_AGC_PWR_WORD_ME) << 8) + 24388c2ecf20Sopenharmony_ci (stv0367_readbits(state, 24398c2ecf20Sopenharmony_ci F367CAB_AGC_PWR_WORD_HI) << 16); 24408c2ecf20Sopenharmony_ci if (u32_tmp >= 131072) 24418c2ecf20Sopenharmony_ci u32_tmp = 262144 - u32_tmp; 24428c2ecf20Sopenharmony_ci u32_tmp = u32_tmp / (1 << (11 - stv0367_readbits(state, 24438c2ecf20Sopenharmony_ci F367CAB_AGC_IF_BWSEL))); 24448c2ecf20Sopenharmony_ci 24458c2ecf20Sopenharmony_ci if (u32_tmp < stv0367_readbits(state, 24468c2ecf20Sopenharmony_ci F367CAB_AGC_PWRREF_LO) + 24478c2ecf20Sopenharmony_ci 256 * stv0367_readbits(state, 24488c2ecf20Sopenharmony_ci F367CAB_AGC_PWRREF_HI) - 10) 24498c2ecf20Sopenharmony_ci QAM_Lock = 0x0f; 24508c2ecf20Sopenharmony_ci } else { 24518c2ecf20Sopenharmony_ci usleep_range(10000, 20000); 24528c2ecf20Sopenharmony_ci LockTime += 10; 24538c2ecf20Sopenharmony_ci } 24548c2ecf20Sopenharmony_ci dprintk("QAM_Lock=0x%x LockTime=%d\n", QAM_Lock, LockTime); 24558c2ecf20Sopenharmony_ci tmp = stv0367_readreg(state, R367CAB_IT_STATUS1); 24568c2ecf20Sopenharmony_ci 24578c2ecf20Sopenharmony_ci dprintk("R367CAB_IT_STATUS1=0x%x\n", tmp); 24588c2ecf20Sopenharmony_ci 24598c2ecf20Sopenharmony_ci } while (((QAM_Lock != 0x0c) && (QAM_Lock != 0x0b)) && 24608c2ecf20Sopenharmony_ci (LockTime < DemodTimeOut)); 24618c2ecf20Sopenharmony_ci 24628c2ecf20Sopenharmony_ci dprintk("QAM_Lock=0x%x\n", QAM_Lock); 24638c2ecf20Sopenharmony_ci 24648c2ecf20Sopenharmony_ci tmp = stv0367_readreg(state, R367CAB_IT_STATUS1); 24658c2ecf20Sopenharmony_ci dprintk("R367CAB_IT_STATUS1=0x%x\n", tmp); 24668c2ecf20Sopenharmony_ci tmp = stv0367_readreg(state, R367CAB_IT_STATUS2); 24678c2ecf20Sopenharmony_ci dprintk("R367CAB_IT_STATUS2=0x%x\n", tmp); 24688c2ecf20Sopenharmony_ci 24698c2ecf20Sopenharmony_ci tmp = stv0367cab_get_derot_freq(state, cab_state->adc_clk); 24708c2ecf20Sopenharmony_ci dprintk("stv0367cab_get_derot_freq=0x%x\n", tmp); 24718c2ecf20Sopenharmony_ci 24728c2ecf20Sopenharmony_ci if ((QAM_Lock == 0x0c) || (QAM_Lock == 0x0b)) { 24738c2ecf20Sopenharmony_ci /* Wait for FEC lock */ 24748c2ecf20Sopenharmony_ci LockTime = 0; 24758c2ecf20Sopenharmony_ci do { 24768c2ecf20Sopenharmony_ci usleep_range(5000, 7000); 24778c2ecf20Sopenharmony_ci LockTime += 5; 24788c2ecf20Sopenharmony_ci QAMFEC_Lock = stv0367cab_qamfec_lock(state); 24798c2ecf20Sopenharmony_ci } while (!QAMFEC_Lock && (LockTime < FECTimeOut)); 24808c2ecf20Sopenharmony_ci } else 24818c2ecf20Sopenharmony_ci QAMFEC_Lock = 0; 24828c2ecf20Sopenharmony_ci 24838c2ecf20Sopenharmony_ci if (QAMFEC_Lock) { 24848c2ecf20Sopenharmony_ci signalType = FE_CAB_DATAOK; 24858c2ecf20Sopenharmony_ci cab_state->spect_inv = stv0367_readbits(state, 24868c2ecf20Sopenharmony_ci F367CAB_QUAD_INV); 24878c2ecf20Sopenharmony_ci#if 0 24888c2ecf20Sopenharmony_ci/* not clear for me */ 24898c2ecf20Sopenharmony_ci if (ifkhz != 0) { 24908c2ecf20Sopenharmony_ci if (ifkhz > cab_state->adc_clk / 1000) { 24918c2ecf20Sopenharmony_ci cab_state->freq_khz = 24928c2ecf20Sopenharmony_ci FE_Cab_TunerGetFrequency(pIntParams->hTuner) 24938c2ecf20Sopenharmony_ci - stv0367cab_get_derot_freq(state, cab_state->adc_clk) 24948c2ecf20Sopenharmony_ci - cab_state->adc_clk / 1000 + ifkhz; 24958c2ecf20Sopenharmony_ci } else { 24968c2ecf20Sopenharmony_ci cab_state->freq_khz = 24978c2ecf20Sopenharmony_ci FE_Cab_TunerGetFrequency(pIntParams->hTuner) 24988c2ecf20Sopenharmony_ci - stv0367cab_get_derot_freq(state, cab_state->adc_clk) 24998c2ecf20Sopenharmony_ci + ifkhz; 25008c2ecf20Sopenharmony_ci } 25018c2ecf20Sopenharmony_ci } else { 25028c2ecf20Sopenharmony_ci cab_state->freq_khz = 25038c2ecf20Sopenharmony_ci FE_Cab_TunerGetFrequency(pIntParams->hTuner) + 25048c2ecf20Sopenharmony_ci stv0367cab_get_derot_freq(state, 25058c2ecf20Sopenharmony_ci cab_state->adc_clk) - 25068c2ecf20Sopenharmony_ci cab_state->adc_clk / 4000; 25078c2ecf20Sopenharmony_ci } 25088c2ecf20Sopenharmony_ci#endif 25098c2ecf20Sopenharmony_ci cab_state->symbol_rate = stv0367cab_GetSymbolRate(state, 25108c2ecf20Sopenharmony_ci cab_state->mclk); 25118c2ecf20Sopenharmony_ci cab_state->locked = 1; 25128c2ecf20Sopenharmony_ci 25138c2ecf20Sopenharmony_ci /* stv0367_setbits(state, F367CAB_AGC_ACCUMRSTSEL,7);*/ 25148c2ecf20Sopenharmony_ci } else 25158c2ecf20Sopenharmony_ci signalType = stv0367cab_fsm_signaltype(QAM_Lock); 25168c2ecf20Sopenharmony_ci 25178c2ecf20Sopenharmony_ci /* Set the AGC control values to tracking values */ 25188c2ecf20Sopenharmony_ci stv0367_writebits(state, F367CAB_AGC_ACCUMRSTSEL, TrackAGCAccum); 25198c2ecf20Sopenharmony_ci return signalType; 25208c2ecf20Sopenharmony_ci} 25218c2ecf20Sopenharmony_ci 25228c2ecf20Sopenharmony_cistatic int stv0367cab_set_frontend(struct dvb_frontend *fe) 25238c2ecf20Sopenharmony_ci{ 25248c2ecf20Sopenharmony_ci struct dtv_frontend_properties *p = &fe->dtv_property_cache; 25258c2ecf20Sopenharmony_ci struct stv0367_state *state = fe->demodulator_priv; 25268c2ecf20Sopenharmony_ci struct stv0367cab_state *cab_state = state->cab_state; 25278c2ecf20Sopenharmony_ci enum stv0367cab_mod QAMSize = 0; 25288c2ecf20Sopenharmony_ci 25298c2ecf20Sopenharmony_ci dprintk("%s: freq = %d, srate = %d\n", __func__, 25308c2ecf20Sopenharmony_ci p->frequency, p->symbol_rate); 25318c2ecf20Sopenharmony_ci 25328c2ecf20Sopenharmony_ci cab_state->derot_offset = 0; 25338c2ecf20Sopenharmony_ci 25348c2ecf20Sopenharmony_ci switch (p->modulation) { 25358c2ecf20Sopenharmony_ci case QAM_16: 25368c2ecf20Sopenharmony_ci QAMSize = FE_CAB_MOD_QAM16; 25378c2ecf20Sopenharmony_ci break; 25388c2ecf20Sopenharmony_ci case QAM_32: 25398c2ecf20Sopenharmony_ci QAMSize = FE_CAB_MOD_QAM32; 25408c2ecf20Sopenharmony_ci break; 25418c2ecf20Sopenharmony_ci case QAM_64: 25428c2ecf20Sopenharmony_ci QAMSize = FE_CAB_MOD_QAM64; 25438c2ecf20Sopenharmony_ci break; 25448c2ecf20Sopenharmony_ci case QAM_128: 25458c2ecf20Sopenharmony_ci QAMSize = FE_CAB_MOD_QAM128; 25468c2ecf20Sopenharmony_ci break; 25478c2ecf20Sopenharmony_ci case QAM_256: 25488c2ecf20Sopenharmony_ci QAMSize = FE_CAB_MOD_QAM256; 25498c2ecf20Sopenharmony_ci break; 25508c2ecf20Sopenharmony_ci default: 25518c2ecf20Sopenharmony_ci break; 25528c2ecf20Sopenharmony_ci } 25538c2ecf20Sopenharmony_ci 25548c2ecf20Sopenharmony_ci if (state->reinit_on_setfrontend) 25558c2ecf20Sopenharmony_ci stv0367cab_init(fe); 25568c2ecf20Sopenharmony_ci 25578c2ecf20Sopenharmony_ci /* Tuner Frequency Setting */ 25588c2ecf20Sopenharmony_ci if (fe->ops.tuner_ops.set_params) { 25598c2ecf20Sopenharmony_ci if (state->use_i2c_gatectrl && fe->ops.i2c_gate_ctrl) 25608c2ecf20Sopenharmony_ci fe->ops.i2c_gate_ctrl(fe, 1); 25618c2ecf20Sopenharmony_ci fe->ops.tuner_ops.set_params(fe); 25628c2ecf20Sopenharmony_ci if (state->use_i2c_gatectrl && fe->ops.i2c_gate_ctrl) 25638c2ecf20Sopenharmony_ci fe->ops.i2c_gate_ctrl(fe, 0); 25648c2ecf20Sopenharmony_ci } 25658c2ecf20Sopenharmony_ci 25668c2ecf20Sopenharmony_ci stv0367cab_SetQamSize( 25678c2ecf20Sopenharmony_ci state, 25688c2ecf20Sopenharmony_ci p->symbol_rate, 25698c2ecf20Sopenharmony_ci QAMSize); 25708c2ecf20Sopenharmony_ci 25718c2ecf20Sopenharmony_ci stv0367cab_set_srate(state, 25728c2ecf20Sopenharmony_ci cab_state->adc_clk, 25738c2ecf20Sopenharmony_ci cab_state->mclk, 25748c2ecf20Sopenharmony_ci p->symbol_rate, 25758c2ecf20Sopenharmony_ci QAMSize); 25768c2ecf20Sopenharmony_ci /* Search algorithm launch, [-1.1*RangeOffset, +1.1*RangeOffset] scan */ 25778c2ecf20Sopenharmony_ci cab_state->state = stv0367cab_algo(state, p); 25788c2ecf20Sopenharmony_ci return 0; 25798c2ecf20Sopenharmony_ci} 25808c2ecf20Sopenharmony_ci 25818c2ecf20Sopenharmony_cistatic int stv0367cab_get_frontend(struct dvb_frontend *fe, 25828c2ecf20Sopenharmony_ci struct dtv_frontend_properties *p) 25838c2ecf20Sopenharmony_ci{ 25848c2ecf20Sopenharmony_ci struct stv0367_state *state = fe->demodulator_priv; 25858c2ecf20Sopenharmony_ci struct stv0367cab_state *cab_state = state->cab_state; 25868c2ecf20Sopenharmony_ci u32 ifkhz = 0; 25878c2ecf20Sopenharmony_ci 25888c2ecf20Sopenharmony_ci enum stv0367cab_mod QAMSize; 25898c2ecf20Sopenharmony_ci 25908c2ecf20Sopenharmony_ci dprintk("%s:\n", __func__); 25918c2ecf20Sopenharmony_ci 25928c2ecf20Sopenharmony_ci stv0367_get_if_khz(state, &ifkhz); 25938c2ecf20Sopenharmony_ci p->symbol_rate = stv0367cab_GetSymbolRate(state, cab_state->mclk); 25948c2ecf20Sopenharmony_ci 25958c2ecf20Sopenharmony_ci QAMSize = stv0367_readbits(state, F367CAB_QAM_MODE); 25968c2ecf20Sopenharmony_ci switch (QAMSize) { 25978c2ecf20Sopenharmony_ci case FE_CAB_MOD_QAM16: 25988c2ecf20Sopenharmony_ci p->modulation = QAM_16; 25998c2ecf20Sopenharmony_ci break; 26008c2ecf20Sopenharmony_ci case FE_CAB_MOD_QAM32: 26018c2ecf20Sopenharmony_ci p->modulation = QAM_32; 26028c2ecf20Sopenharmony_ci break; 26038c2ecf20Sopenharmony_ci case FE_CAB_MOD_QAM64: 26048c2ecf20Sopenharmony_ci p->modulation = QAM_64; 26058c2ecf20Sopenharmony_ci break; 26068c2ecf20Sopenharmony_ci case FE_CAB_MOD_QAM128: 26078c2ecf20Sopenharmony_ci p->modulation = QAM_128; 26088c2ecf20Sopenharmony_ci break; 26098c2ecf20Sopenharmony_ci case FE_CAB_MOD_QAM256: 26108c2ecf20Sopenharmony_ci p->modulation = QAM_256; 26118c2ecf20Sopenharmony_ci break; 26128c2ecf20Sopenharmony_ci default: 26138c2ecf20Sopenharmony_ci break; 26148c2ecf20Sopenharmony_ci } 26158c2ecf20Sopenharmony_ci 26168c2ecf20Sopenharmony_ci p->frequency = stv0367_get_tuner_freq(fe); 26178c2ecf20Sopenharmony_ci 26188c2ecf20Sopenharmony_ci dprintk("%s: tuner frequency = %d\n", __func__, p->frequency); 26198c2ecf20Sopenharmony_ci 26208c2ecf20Sopenharmony_ci if (ifkhz == 0) { 26218c2ecf20Sopenharmony_ci p->frequency += 26228c2ecf20Sopenharmony_ci (stv0367cab_get_derot_freq(state, cab_state->adc_clk) - 26238c2ecf20Sopenharmony_ci cab_state->adc_clk / 4000); 26248c2ecf20Sopenharmony_ci return 0; 26258c2ecf20Sopenharmony_ci } 26268c2ecf20Sopenharmony_ci 26278c2ecf20Sopenharmony_ci if (ifkhz > cab_state->adc_clk / 1000) 26288c2ecf20Sopenharmony_ci p->frequency += (ifkhz 26298c2ecf20Sopenharmony_ci - stv0367cab_get_derot_freq(state, cab_state->adc_clk) 26308c2ecf20Sopenharmony_ci - cab_state->adc_clk / 1000); 26318c2ecf20Sopenharmony_ci else 26328c2ecf20Sopenharmony_ci p->frequency += (ifkhz 26338c2ecf20Sopenharmony_ci - stv0367cab_get_derot_freq(state, cab_state->adc_clk)); 26348c2ecf20Sopenharmony_ci 26358c2ecf20Sopenharmony_ci return 0; 26368c2ecf20Sopenharmony_ci} 26378c2ecf20Sopenharmony_ci 26388c2ecf20Sopenharmony_ci#if 0 26398c2ecf20Sopenharmony_civoid stv0367cab_GetErrorCount(state, enum stv0367cab_mod QAMSize, 26408c2ecf20Sopenharmony_ci u32 symbol_rate, FE_367qam_Monitor *Monitor_results) 26418c2ecf20Sopenharmony_ci{ 26428c2ecf20Sopenharmony_ci stv0367cab_OptimiseNByteAndGetBER(state, QAMSize, symbol_rate, Monitor_results); 26438c2ecf20Sopenharmony_ci stv0367cab_GetPacketsCount(state, Monitor_results); 26448c2ecf20Sopenharmony_ci 26458c2ecf20Sopenharmony_ci return; 26468c2ecf20Sopenharmony_ci} 26478c2ecf20Sopenharmony_ci 26488c2ecf20Sopenharmony_cistatic int stv0367cab_read_ber(struct dvb_frontend *fe, u32 *ber) 26498c2ecf20Sopenharmony_ci{ 26508c2ecf20Sopenharmony_ci struct stv0367_state *state = fe->demodulator_priv; 26518c2ecf20Sopenharmony_ci 26528c2ecf20Sopenharmony_ci return 0; 26538c2ecf20Sopenharmony_ci} 26548c2ecf20Sopenharmony_ci#endif 26558c2ecf20Sopenharmony_cistatic s32 stv0367cab_get_rf_lvl(struct stv0367_state *state) 26568c2ecf20Sopenharmony_ci{ 26578c2ecf20Sopenharmony_ci s32 rfLevel = 0; 26588c2ecf20Sopenharmony_ci s32 RfAgcPwm = 0, IfAgcPwm = 0; 26598c2ecf20Sopenharmony_ci u8 i; 26608c2ecf20Sopenharmony_ci 26618c2ecf20Sopenharmony_ci stv0367_writebits(state, F367CAB_STDBY_ADCGP, 0x0); 26628c2ecf20Sopenharmony_ci 26638c2ecf20Sopenharmony_ci RfAgcPwm = 26648c2ecf20Sopenharmony_ci (stv0367_readbits(state, F367CAB_RF_AGC1_LEVEL_LO) & 0x03) + 26658c2ecf20Sopenharmony_ci (stv0367_readbits(state, F367CAB_RF_AGC1_LEVEL_HI) << 2); 26668c2ecf20Sopenharmony_ci RfAgcPwm = 100 * RfAgcPwm / 1023; 26678c2ecf20Sopenharmony_ci 26688c2ecf20Sopenharmony_ci IfAgcPwm = 26698c2ecf20Sopenharmony_ci stv0367_readbits(state, F367CAB_AGC_IF_PWMCMD_LO) + 26708c2ecf20Sopenharmony_ci (stv0367_readbits(state, F367CAB_AGC_IF_PWMCMD_HI) << 8); 26718c2ecf20Sopenharmony_ci if (IfAgcPwm >= 2048) 26728c2ecf20Sopenharmony_ci IfAgcPwm -= 2048; 26738c2ecf20Sopenharmony_ci else 26748c2ecf20Sopenharmony_ci IfAgcPwm += 2048; 26758c2ecf20Sopenharmony_ci 26768c2ecf20Sopenharmony_ci IfAgcPwm = 100 * IfAgcPwm / 4095; 26778c2ecf20Sopenharmony_ci 26788c2ecf20Sopenharmony_ci /* For DTT75467 on NIM */ 26798c2ecf20Sopenharmony_ci if (RfAgcPwm < 90 && IfAgcPwm < 28) { 26808c2ecf20Sopenharmony_ci for (i = 0; i < RF_LOOKUP_TABLE_SIZE; i++) { 26818c2ecf20Sopenharmony_ci if (RfAgcPwm <= stv0367cab_RF_LookUp1[0][i]) { 26828c2ecf20Sopenharmony_ci rfLevel = (-1) * stv0367cab_RF_LookUp1[1][i]; 26838c2ecf20Sopenharmony_ci break; 26848c2ecf20Sopenharmony_ci } 26858c2ecf20Sopenharmony_ci } 26868c2ecf20Sopenharmony_ci if (i == RF_LOOKUP_TABLE_SIZE) 26878c2ecf20Sopenharmony_ci rfLevel = -56; 26888c2ecf20Sopenharmony_ci } else { /*if IF AGC>10*/ 26898c2ecf20Sopenharmony_ci for (i = 0; i < RF_LOOKUP_TABLE2_SIZE; i++) { 26908c2ecf20Sopenharmony_ci if (IfAgcPwm <= stv0367cab_RF_LookUp2[0][i]) { 26918c2ecf20Sopenharmony_ci rfLevel = (-1) * stv0367cab_RF_LookUp2[1][i]; 26928c2ecf20Sopenharmony_ci break; 26938c2ecf20Sopenharmony_ci } 26948c2ecf20Sopenharmony_ci } 26958c2ecf20Sopenharmony_ci if (i == RF_LOOKUP_TABLE2_SIZE) 26968c2ecf20Sopenharmony_ci rfLevel = -72; 26978c2ecf20Sopenharmony_ci } 26988c2ecf20Sopenharmony_ci return rfLevel; 26998c2ecf20Sopenharmony_ci} 27008c2ecf20Sopenharmony_ci 27018c2ecf20Sopenharmony_cistatic int stv0367cab_read_strength(struct dvb_frontend *fe, u16 *strength) 27028c2ecf20Sopenharmony_ci{ 27038c2ecf20Sopenharmony_ci struct stv0367_state *state = fe->demodulator_priv; 27048c2ecf20Sopenharmony_ci 27058c2ecf20Sopenharmony_ci s32 signal = stv0367cab_get_rf_lvl(state); 27068c2ecf20Sopenharmony_ci 27078c2ecf20Sopenharmony_ci dprintk("%s: signal=%d dBm\n", __func__, signal); 27088c2ecf20Sopenharmony_ci 27098c2ecf20Sopenharmony_ci if (signal <= -72) 27108c2ecf20Sopenharmony_ci *strength = 65535; 27118c2ecf20Sopenharmony_ci else 27128c2ecf20Sopenharmony_ci *strength = (22 + signal) * (-1311); 27138c2ecf20Sopenharmony_ci 27148c2ecf20Sopenharmony_ci dprintk("%s: strength=%d\n", __func__, (*strength)); 27158c2ecf20Sopenharmony_ci 27168c2ecf20Sopenharmony_ci return 0; 27178c2ecf20Sopenharmony_ci} 27188c2ecf20Sopenharmony_ci 27198c2ecf20Sopenharmony_cistatic int stv0367cab_snr_power(struct dvb_frontend *fe) 27208c2ecf20Sopenharmony_ci{ 27218c2ecf20Sopenharmony_ci struct stv0367_state *state = fe->demodulator_priv; 27228c2ecf20Sopenharmony_ci enum stv0367cab_mod QAMSize; 27238c2ecf20Sopenharmony_ci 27248c2ecf20Sopenharmony_ci QAMSize = stv0367_readbits(state, F367CAB_QAM_MODE); 27258c2ecf20Sopenharmony_ci switch (QAMSize) { 27268c2ecf20Sopenharmony_ci case FE_CAB_MOD_QAM4: 27278c2ecf20Sopenharmony_ci return 21904; 27288c2ecf20Sopenharmony_ci case FE_CAB_MOD_QAM16: 27298c2ecf20Sopenharmony_ci return 20480; 27308c2ecf20Sopenharmony_ci case FE_CAB_MOD_QAM32: 27318c2ecf20Sopenharmony_ci return 23040; 27328c2ecf20Sopenharmony_ci case FE_CAB_MOD_QAM64: 27338c2ecf20Sopenharmony_ci return 21504; 27348c2ecf20Sopenharmony_ci case FE_CAB_MOD_QAM128: 27358c2ecf20Sopenharmony_ci return 23616; 27368c2ecf20Sopenharmony_ci case FE_CAB_MOD_QAM256: 27378c2ecf20Sopenharmony_ci return 21760; 27388c2ecf20Sopenharmony_ci case FE_CAB_MOD_QAM1024: 27398c2ecf20Sopenharmony_ci return 21280; 27408c2ecf20Sopenharmony_ci default: 27418c2ecf20Sopenharmony_ci break; 27428c2ecf20Sopenharmony_ci } 27438c2ecf20Sopenharmony_ci 27448c2ecf20Sopenharmony_ci return 1; 27458c2ecf20Sopenharmony_ci} 27468c2ecf20Sopenharmony_ci 27478c2ecf20Sopenharmony_cistatic int stv0367cab_snr_readreg(struct dvb_frontend *fe, int avgdiv) 27488c2ecf20Sopenharmony_ci{ 27498c2ecf20Sopenharmony_ci struct stv0367_state *state = fe->demodulator_priv; 27508c2ecf20Sopenharmony_ci u32 regval = 0; 27518c2ecf20Sopenharmony_ci int i; 27528c2ecf20Sopenharmony_ci 27538c2ecf20Sopenharmony_ci for (i = 0; i < 10; i++) { 27548c2ecf20Sopenharmony_ci regval += (stv0367_readbits(state, F367CAB_SNR_LO) 27558c2ecf20Sopenharmony_ci + 256 * stv0367_readbits(state, F367CAB_SNR_HI)); 27568c2ecf20Sopenharmony_ci } 27578c2ecf20Sopenharmony_ci 27588c2ecf20Sopenharmony_ci if (avgdiv) 27598c2ecf20Sopenharmony_ci regval /= 10; 27608c2ecf20Sopenharmony_ci 27618c2ecf20Sopenharmony_ci return regval; 27628c2ecf20Sopenharmony_ci} 27638c2ecf20Sopenharmony_ci 27648c2ecf20Sopenharmony_cistatic int stv0367cab_read_snr(struct dvb_frontend *fe, u16 *snr) 27658c2ecf20Sopenharmony_ci{ 27668c2ecf20Sopenharmony_ci struct stv0367_state *state = fe->demodulator_priv; 27678c2ecf20Sopenharmony_ci u32 noisepercentage; 27688c2ecf20Sopenharmony_ci u32 regval = 0, temp = 0; 27698c2ecf20Sopenharmony_ci int power; 27708c2ecf20Sopenharmony_ci 27718c2ecf20Sopenharmony_ci power = stv0367cab_snr_power(fe); 27728c2ecf20Sopenharmony_ci regval = stv0367cab_snr_readreg(fe, 1); 27738c2ecf20Sopenharmony_ci 27748c2ecf20Sopenharmony_ci if (regval != 0) { 27758c2ecf20Sopenharmony_ci temp = power 27768c2ecf20Sopenharmony_ci * (1 << (3 + stv0367_readbits(state, F367CAB_SNR_PER))); 27778c2ecf20Sopenharmony_ci temp /= regval; 27788c2ecf20Sopenharmony_ci } 27798c2ecf20Sopenharmony_ci 27808c2ecf20Sopenharmony_ci /* table values, not needed to calculate logarithms */ 27818c2ecf20Sopenharmony_ci if (temp >= 5012) 27828c2ecf20Sopenharmony_ci noisepercentage = 100; 27838c2ecf20Sopenharmony_ci else if (temp >= 3981) 27848c2ecf20Sopenharmony_ci noisepercentage = 93; 27858c2ecf20Sopenharmony_ci else if (temp >= 3162) 27868c2ecf20Sopenharmony_ci noisepercentage = 86; 27878c2ecf20Sopenharmony_ci else if (temp >= 2512) 27888c2ecf20Sopenharmony_ci noisepercentage = 79; 27898c2ecf20Sopenharmony_ci else if (temp >= 1995) 27908c2ecf20Sopenharmony_ci noisepercentage = 72; 27918c2ecf20Sopenharmony_ci else if (temp >= 1585) 27928c2ecf20Sopenharmony_ci noisepercentage = 65; 27938c2ecf20Sopenharmony_ci else if (temp >= 1259) 27948c2ecf20Sopenharmony_ci noisepercentage = 58; 27958c2ecf20Sopenharmony_ci else if (temp >= 1000) 27968c2ecf20Sopenharmony_ci noisepercentage = 50; 27978c2ecf20Sopenharmony_ci else if (temp >= 794) 27988c2ecf20Sopenharmony_ci noisepercentage = 43; 27998c2ecf20Sopenharmony_ci else if (temp >= 501) 28008c2ecf20Sopenharmony_ci noisepercentage = 36; 28018c2ecf20Sopenharmony_ci else if (temp >= 316) 28028c2ecf20Sopenharmony_ci noisepercentage = 29; 28038c2ecf20Sopenharmony_ci else if (temp >= 200) 28048c2ecf20Sopenharmony_ci noisepercentage = 22; 28058c2ecf20Sopenharmony_ci else if (temp >= 158) 28068c2ecf20Sopenharmony_ci noisepercentage = 14; 28078c2ecf20Sopenharmony_ci else if (temp >= 126) 28088c2ecf20Sopenharmony_ci noisepercentage = 7; 28098c2ecf20Sopenharmony_ci else 28108c2ecf20Sopenharmony_ci noisepercentage = 0; 28118c2ecf20Sopenharmony_ci 28128c2ecf20Sopenharmony_ci dprintk("%s: noisepercentage=%d\n", __func__, noisepercentage); 28138c2ecf20Sopenharmony_ci 28148c2ecf20Sopenharmony_ci *snr = (noisepercentage * 65535) / 100; 28158c2ecf20Sopenharmony_ci 28168c2ecf20Sopenharmony_ci return 0; 28178c2ecf20Sopenharmony_ci} 28188c2ecf20Sopenharmony_ci 28198c2ecf20Sopenharmony_cistatic int stv0367cab_read_ucblcks(struct dvb_frontend *fe, u32 *ucblocks) 28208c2ecf20Sopenharmony_ci{ 28218c2ecf20Sopenharmony_ci struct stv0367_state *state = fe->demodulator_priv; 28228c2ecf20Sopenharmony_ci int corrected, tscount; 28238c2ecf20Sopenharmony_ci 28248c2ecf20Sopenharmony_ci *ucblocks = (stv0367_readreg(state, R367CAB_RS_COUNTER_5) << 8) 28258c2ecf20Sopenharmony_ci | stv0367_readreg(state, R367CAB_RS_COUNTER_4); 28268c2ecf20Sopenharmony_ci corrected = (stv0367_readreg(state, R367CAB_RS_COUNTER_3) << 8) 28278c2ecf20Sopenharmony_ci | stv0367_readreg(state, R367CAB_RS_COUNTER_2); 28288c2ecf20Sopenharmony_ci tscount = (stv0367_readreg(state, R367CAB_RS_COUNTER_2) << 8) 28298c2ecf20Sopenharmony_ci | stv0367_readreg(state, R367CAB_RS_COUNTER_1); 28308c2ecf20Sopenharmony_ci 28318c2ecf20Sopenharmony_ci dprintk("%s: uncorrected blocks=%d corrected blocks=%d tscount=%d\n", 28328c2ecf20Sopenharmony_ci __func__, *ucblocks, corrected, tscount); 28338c2ecf20Sopenharmony_ci 28348c2ecf20Sopenharmony_ci return 0; 28358c2ecf20Sopenharmony_ci}; 28368c2ecf20Sopenharmony_ci 28378c2ecf20Sopenharmony_cistatic const struct dvb_frontend_ops stv0367cab_ops = { 28388c2ecf20Sopenharmony_ci .delsys = { SYS_DVBC_ANNEX_A }, 28398c2ecf20Sopenharmony_ci .info = { 28408c2ecf20Sopenharmony_ci .name = "ST STV0367 DVB-C", 28418c2ecf20Sopenharmony_ci .frequency_min_hz = 47 * MHz, 28428c2ecf20Sopenharmony_ci .frequency_max_hz = 862 * MHz, 28438c2ecf20Sopenharmony_ci .frequency_stepsize_hz = 62500, 28448c2ecf20Sopenharmony_ci .symbol_rate_min = 870000, 28458c2ecf20Sopenharmony_ci .symbol_rate_max = 11700000, 28468c2ecf20Sopenharmony_ci .caps = 0x400 |/* FE_CAN_QAM_4 */ 28478c2ecf20Sopenharmony_ci FE_CAN_QAM_16 | FE_CAN_QAM_32 | 28488c2ecf20Sopenharmony_ci FE_CAN_QAM_64 | FE_CAN_QAM_128 | 28498c2ecf20Sopenharmony_ci FE_CAN_QAM_256 | FE_CAN_FEC_AUTO 28508c2ecf20Sopenharmony_ci }, 28518c2ecf20Sopenharmony_ci .release = stv0367_release, 28528c2ecf20Sopenharmony_ci .init = stv0367cab_init, 28538c2ecf20Sopenharmony_ci .sleep = stv0367cab_sleep, 28548c2ecf20Sopenharmony_ci .i2c_gate_ctrl = stv0367cab_gate_ctrl, 28558c2ecf20Sopenharmony_ci .set_frontend = stv0367cab_set_frontend, 28568c2ecf20Sopenharmony_ci .get_frontend = stv0367cab_get_frontend, 28578c2ecf20Sopenharmony_ci .read_status = stv0367cab_read_status, 28588c2ecf20Sopenharmony_ci/* .read_ber = stv0367cab_read_ber, */ 28598c2ecf20Sopenharmony_ci .read_signal_strength = stv0367cab_read_strength, 28608c2ecf20Sopenharmony_ci .read_snr = stv0367cab_read_snr, 28618c2ecf20Sopenharmony_ci .read_ucblocks = stv0367cab_read_ucblcks, 28628c2ecf20Sopenharmony_ci .get_tune_settings = stv0367_get_tune_settings, 28638c2ecf20Sopenharmony_ci}; 28648c2ecf20Sopenharmony_ci 28658c2ecf20Sopenharmony_cistruct dvb_frontend *stv0367cab_attach(const struct stv0367_config *config, 28668c2ecf20Sopenharmony_ci struct i2c_adapter *i2c) 28678c2ecf20Sopenharmony_ci{ 28688c2ecf20Sopenharmony_ci struct stv0367_state *state = NULL; 28698c2ecf20Sopenharmony_ci struct stv0367cab_state *cab_state = NULL; 28708c2ecf20Sopenharmony_ci 28718c2ecf20Sopenharmony_ci /* allocate memory for the internal state */ 28728c2ecf20Sopenharmony_ci state = kzalloc(sizeof(struct stv0367_state), GFP_KERNEL); 28738c2ecf20Sopenharmony_ci if (state == NULL) 28748c2ecf20Sopenharmony_ci goto error; 28758c2ecf20Sopenharmony_ci cab_state = kzalloc(sizeof(struct stv0367cab_state), GFP_KERNEL); 28768c2ecf20Sopenharmony_ci if (cab_state == NULL) 28778c2ecf20Sopenharmony_ci goto error; 28788c2ecf20Sopenharmony_ci 28798c2ecf20Sopenharmony_ci /* setup the state */ 28808c2ecf20Sopenharmony_ci state->i2c = i2c; 28818c2ecf20Sopenharmony_ci state->config = config; 28828c2ecf20Sopenharmony_ci cab_state->search_range = 280000; 28838c2ecf20Sopenharmony_ci cab_state->qamfec_status_reg = F367CAB_QAMFEC_LOCK; 28848c2ecf20Sopenharmony_ci state->cab_state = cab_state; 28858c2ecf20Sopenharmony_ci state->fe.ops = stv0367cab_ops; 28868c2ecf20Sopenharmony_ci state->fe.demodulator_priv = state; 28878c2ecf20Sopenharmony_ci state->chip_id = stv0367_readreg(state, 0xf000); 28888c2ecf20Sopenharmony_ci 28898c2ecf20Sopenharmony_ci /* demod operation options */ 28908c2ecf20Sopenharmony_ci state->use_i2c_gatectrl = 1; 28918c2ecf20Sopenharmony_ci state->deftabs = STV0367_DEFTAB_GENERIC; 28928c2ecf20Sopenharmony_ci state->reinit_on_setfrontend = 1; 28938c2ecf20Sopenharmony_ci state->auto_if_khz = 0; 28948c2ecf20Sopenharmony_ci 28958c2ecf20Sopenharmony_ci dprintk("%s: chip_id = 0x%x\n", __func__, state->chip_id); 28968c2ecf20Sopenharmony_ci 28978c2ecf20Sopenharmony_ci /* check if the demod is there */ 28988c2ecf20Sopenharmony_ci if ((state->chip_id != 0x50) && (state->chip_id != 0x60)) 28998c2ecf20Sopenharmony_ci goto error; 29008c2ecf20Sopenharmony_ci 29018c2ecf20Sopenharmony_ci return &state->fe; 29028c2ecf20Sopenharmony_ci 29038c2ecf20Sopenharmony_cierror: 29048c2ecf20Sopenharmony_ci kfree(cab_state); 29058c2ecf20Sopenharmony_ci kfree(state); 29068c2ecf20Sopenharmony_ci return NULL; 29078c2ecf20Sopenharmony_ci} 29088c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(stv0367cab_attach); 29098c2ecf20Sopenharmony_ci 29108c2ecf20Sopenharmony_ci/* 29118c2ecf20Sopenharmony_ci * Functions for operation on Digital Devices hardware 29128c2ecf20Sopenharmony_ci */ 29138c2ecf20Sopenharmony_ci 29148c2ecf20Sopenharmony_cistatic void stv0367ddb_setup_ter(struct stv0367_state *state) 29158c2ecf20Sopenharmony_ci{ 29168c2ecf20Sopenharmony_ci stv0367_writereg(state, R367TER_DEBUG_LT4, 0x00); 29178c2ecf20Sopenharmony_ci stv0367_writereg(state, R367TER_DEBUG_LT5, 0x00); 29188c2ecf20Sopenharmony_ci stv0367_writereg(state, R367TER_DEBUG_LT6, 0x00); /* R367CAB_CTRL_1 */ 29198c2ecf20Sopenharmony_ci stv0367_writereg(state, R367TER_DEBUG_LT7, 0x00); /* R367CAB_CTRL_2 */ 29208c2ecf20Sopenharmony_ci stv0367_writereg(state, R367TER_DEBUG_LT8, 0x00); 29218c2ecf20Sopenharmony_ci stv0367_writereg(state, R367TER_DEBUG_LT9, 0x00); 29228c2ecf20Sopenharmony_ci 29238c2ecf20Sopenharmony_ci /* Tuner Setup */ 29248c2ecf20Sopenharmony_ci /* Buffer Q disabled, I Enabled, unsigned ADC */ 29258c2ecf20Sopenharmony_ci stv0367_writereg(state, R367TER_ANADIGCTRL, 0x89); 29268c2ecf20Sopenharmony_ci stv0367_writereg(state, R367TER_DUAL_AD12, 0x04); /* ADCQ disabled */ 29278c2ecf20Sopenharmony_ci 29288c2ecf20Sopenharmony_ci /* Clock setup */ 29298c2ecf20Sopenharmony_ci /* PLL bypassed and disabled */ 29308c2ecf20Sopenharmony_ci stv0367_writereg(state, R367TER_ANACTRL, 0x0D); 29318c2ecf20Sopenharmony_ci stv0367_writereg(state, R367TER_TOPCTRL, 0x00); /* Set OFDM */ 29328c2ecf20Sopenharmony_ci 29338c2ecf20Sopenharmony_ci /* IC runs at 54 MHz with a 27 MHz crystal */ 29348c2ecf20Sopenharmony_ci stv0367_pll_setup(state, STV0367_ICSPEED_53125, state->config->xtal); 29358c2ecf20Sopenharmony_ci 29368c2ecf20Sopenharmony_ci msleep(50); 29378c2ecf20Sopenharmony_ci /* PLL enabled and used */ 29388c2ecf20Sopenharmony_ci stv0367_writereg(state, R367TER_ANACTRL, 0x00); 29398c2ecf20Sopenharmony_ci 29408c2ecf20Sopenharmony_ci state->activedemod = demod_ter; 29418c2ecf20Sopenharmony_ci} 29428c2ecf20Sopenharmony_ci 29438c2ecf20Sopenharmony_cistatic void stv0367ddb_setup_cab(struct stv0367_state *state) 29448c2ecf20Sopenharmony_ci{ 29458c2ecf20Sopenharmony_ci stv0367_writereg(state, R367TER_DEBUG_LT4, 0x00); 29468c2ecf20Sopenharmony_ci stv0367_writereg(state, R367TER_DEBUG_LT5, 0x01); 29478c2ecf20Sopenharmony_ci stv0367_writereg(state, R367TER_DEBUG_LT6, 0x06); /* R367CAB_CTRL_1 */ 29488c2ecf20Sopenharmony_ci stv0367_writereg(state, R367TER_DEBUG_LT7, 0x03); /* R367CAB_CTRL_2 */ 29498c2ecf20Sopenharmony_ci stv0367_writereg(state, R367TER_DEBUG_LT8, 0x00); 29508c2ecf20Sopenharmony_ci stv0367_writereg(state, R367TER_DEBUG_LT9, 0x00); 29518c2ecf20Sopenharmony_ci 29528c2ecf20Sopenharmony_ci /* Tuner Setup */ 29538c2ecf20Sopenharmony_ci /* Buffer Q disabled, I Enabled, signed ADC */ 29548c2ecf20Sopenharmony_ci stv0367_writereg(state, R367TER_ANADIGCTRL, 0x8B); 29558c2ecf20Sopenharmony_ci /* ADCQ disabled */ 29568c2ecf20Sopenharmony_ci stv0367_writereg(state, R367TER_DUAL_AD12, 0x04); 29578c2ecf20Sopenharmony_ci 29588c2ecf20Sopenharmony_ci /* Clock setup */ 29598c2ecf20Sopenharmony_ci /* PLL bypassed and disabled */ 29608c2ecf20Sopenharmony_ci stv0367_writereg(state, R367TER_ANACTRL, 0x0D); 29618c2ecf20Sopenharmony_ci /* Set QAM */ 29628c2ecf20Sopenharmony_ci stv0367_writereg(state, R367TER_TOPCTRL, 0x10); 29638c2ecf20Sopenharmony_ci 29648c2ecf20Sopenharmony_ci /* IC runs at 58 MHz with a 27 MHz crystal */ 29658c2ecf20Sopenharmony_ci stv0367_pll_setup(state, STV0367_ICSPEED_58000, state->config->xtal); 29668c2ecf20Sopenharmony_ci 29678c2ecf20Sopenharmony_ci msleep(50); 29688c2ecf20Sopenharmony_ci /* PLL enabled and used */ 29698c2ecf20Sopenharmony_ci stv0367_writereg(state, R367TER_ANACTRL, 0x00); 29708c2ecf20Sopenharmony_ci 29718c2ecf20Sopenharmony_ci state->cab_state->mclk = stv0367cab_get_mclk(&state->fe, 29728c2ecf20Sopenharmony_ci state->config->xtal); 29738c2ecf20Sopenharmony_ci state->cab_state->adc_clk = stv0367cab_get_adc_freq(&state->fe, 29748c2ecf20Sopenharmony_ci state->config->xtal); 29758c2ecf20Sopenharmony_ci 29768c2ecf20Sopenharmony_ci state->activedemod = demod_cab; 29778c2ecf20Sopenharmony_ci} 29788c2ecf20Sopenharmony_ci 29798c2ecf20Sopenharmony_cistatic int stv0367ddb_set_frontend(struct dvb_frontend *fe) 29808c2ecf20Sopenharmony_ci{ 29818c2ecf20Sopenharmony_ci struct stv0367_state *state = fe->demodulator_priv; 29828c2ecf20Sopenharmony_ci 29838c2ecf20Sopenharmony_ci switch (fe->dtv_property_cache.delivery_system) { 29848c2ecf20Sopenharmony_ci case SYS_DVBT: 29858c2ecf20Sopenharmony_ci if (state->activedemod != demod_ter) 29868c2ecf20Sopenharmony_ci stv0367ddb_setup_ter(state); 29878c2ecf20Sopenharmony_ci 29888c2ecf20Sopenharmony_ci return stv0367ter_set_frontend(fe); 29898c2ecf20Sopenharmony_ci case SYS_DVBC_ANNEX_A: 29908c2ecf20Sopenharmony_ci if (state->activedemod != demod_cab) 29918c2ecf20Sopenharmony_ci stv0367ddb_setup_cab(state); 29928c2ecf20Sopenharmony_ci 29938c2ecf20Sopenharmony_ci /* protect against division error oopses */ 29948c2ecf20Sopenharmony_ci if (fe->dtv_property_cache.symbol_rate == 0) { 29958c2ecf20Sopenharmony_ci printk(KERN_ERR "Invalid symbol rate\n"); 29968c2ecf20Sopenharmony_ci return -EINVAL; 29978c2ecf20Sopenharmony_ci } 29988c2ecf20Sopenharmony_ci 29998c2ecf20Sopenharmony_ci return stv0367cab_set_frontend(fe); 30008c2ecf20Sopenharmony_ci default: 30018c2ecf20Sopenharmony_ci break; 30028c2ecf20Sopenharmony_ci } 30038c2ecf20Sopenharmony_ci 30048c2ecf20Sopenharmony_ci return -EINVAL; 30058c2ecf20Sopenharmony_ci} 30068c2ecf20Sopenharmony_ci 30078c2ecf20Sopenharmony_cistatic void stv0367ddb_read_signal_strength(struct dvb_frontend *fe) 30088c2ecf20Sopenharmony_ci{ 30098c2ecf20Sopenharmony_ci struct stv0367_state *state = fe->demodulator_priv; 30108c2ecf20Sopenharmony_ci struct dtv_frontend_properties *p = &fe->dtv_property_cache; 30118c2ecf20Sopenharmony_ci s32 signalstrength; 30128c2ecf20Sopenharmony_ci 30138c2ecf20Sopenharmony_ci switch (state->activedemod) { 30148c2ecf20Sopenharmony_ci case demod_cab: 30158c2ecf20Sopenharmony_ci signalstrength = stv0367cab_get_rf_lvl(state) * 1000; 30168c2ecf20Sopenharmony_ci break; 30178c2ecf20Sopenharmony_ci default: 30188c2ecf20Sopenharmony_ci p->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 30198c2ecf20Sopenharmony_ci return; 30208c2ecf20Sopenharmony_ci } 30218c2ecf20Sopenharmony_ci 30228c2ecf20Sopenharmony_ci p->strength.stat[0].scale = FE_SCALE_DECIBEL; 30238c2ecf20Sopenharmony_ci p->strength.stat[0].uvalue = signalstrength; 30248c2ecf20Sopenharmony_ci} 30258c2ecf20Sopenharmony_ci 30268c2ecf20Sopenharmony_cistatic void stv0367ddb_read_snr(struct dvb_frontend *fe) 30278c2ecf20Sopenharmony_ci{ 30288c2ecf20Sopenharmony_ci struct stv0367_state *state = fe->demodulator_priv; 30298c2ecf20Sopenharmony_ci struct dtv_frontend_properties *p = &fe->dtv_property_cache; 30308c2ecf20Sopenharmony_ci int cab_pwr; 30318c2ecf20Sopenharmony_ci u32 regval, tmpval, snrval = 0; 30328c2ecf20Sopenharmony_ci 30338c2ecf20Sopenharmony_ci switch (state->activedemod) { 30348c2ecf20Sopenharmony_ci case demod_ter: 30358c2ecf20Sopenharmony_ci snrval = stv0367ter_snr_readreg(fe); 30368c2ecf20Sopenharmony_ci break; 30378c2ecf20Sopenharmony_ci case demod_cab: 30388c2ecf20Sopenharmony_ci cab_pwr = stv0367cab_snr_power(fe); 30398c2ecf20Sopenharmony_ci regval = stv0367cab_snr_readreg(fe, 0); 30408c2ecf20Sopenharmony_ci 30418c2ecf20Sopenharmony_ci /* prevent division by zero */ 30428c2ecf20Sopenharmony_ci if (!regval) { 30438c2ecf20Sopenharmony_ci snrval = 0; 30448c2ecf20Sopenharmony_ci break; 30458c2ecf20Sopenharmony_ci } 30468c2ecf20Sopenharmony_ci 30478c2ecf20Sopenharmony_ci tmpval = (cab_pwr * 320) / regval; 30488c2ecf20Sopenharmony_ci snrval = ((tmpval != 0) ? (intlog2(tmpval) / 5581) : 0); 30498c2ecf20Sopenharmony_ci break; 30508c2ecf20Sopenharmony_ci default: 30518c2ecf20Sopenharmony_ci p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 30528c2ecf20Sopenharmony_ci return; 30538c2ecf20Sopenharmony_ci } 30548c2ecf20Sopenharmony_ci 30558c2ecf20Sopenharmony_ci p->cnr.stat[0].scale = FE_SCALE_DECIBEL; 30568c2ecf20Sopenharmony_ci p->cnr.stat[0].uvalue = snrval; 30578c2ecf20Sopenharmony_ci} 30588c2ecf20Sopenharmony_ci 30598c2ecf20Sopenharmony_cistatic void stv0367ddb_read_ucblocks(struct dvb_frontend *fe) 30608c2ecf20Sopenharmony_ci{ 30618c2ecf20Sopenharmony_ci struct stv0367_state *state = fe->demodulator_priv; 30628c2ecf20Sopenharmony_ci struct dtv_frontend_properties *p = &fe->dtv_property_cache; 30638c2ecf20Sopenharmony_ci u32 ucblocks = 0; 30648c2ecf20Sopenharmony_ci 30658c2ecf20Sopenharmony_ci switch (state->activedemod) { 30668c2ecf20Sopenharmony_ci case demod_ter: 30678c2ecf20Sopenharmony_ci stv0367ter_read_ucblocks(fe, &ucblocks); 30688c2ecf20Sopenharmony_ci break; 30698c2ecf20Sopenharmony_ci case demod_cab: 30708c2ecf20Sopenharmony_ci stv0367cab_read_ucblcks(fe, &ucblocks); 30718c2ecf20Sopenharmony_ci break; 30728c2ecf20Sopenharmony_ci default: 30738c2ecf20Sopenharmony_ci p->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 30748c2ecf20Sopenharmony_ci return; 30758c2ecf20Sopenharmony_ci } 30768c2ecf20Sopenharmony_ci 30778c2ecf20Sopenharmony_ci p->block_error.stat[0].scale = FE_SCALE_COUNTER; 30788c2ecf20Sopenharmony_ci p->block_error.stat[0].uvalue = ucblocks; 30798c2ecf20Sopenharmony_ci} 30808c2ecf20Sopenharmony_ci 30818c2ecf20Sopenharmony_cistatic int stv0367ddb_read_status(struct dvb_frontend *fe, 30828c2ecf20Sopenharmony_ci enum fe_status *status) 30838c2ecf20Sopenharmony_ci{ 30848c2ecf20Sopenharmony_ci struct stv0367_state *state = fe->demodulator_priv; 30858c2ecf20Sopenharmony_ci struct dtv_frontend_properties *p = &fe->dtv_property_cache; 30868c2ecf20Sopenharmony_ci int ret = 0; 30878c2ecf20Sopenharmony_ci 30888c2ecf20Sopenharmony_ci switch (state->activedemod) { 30898c2ecf20Sopenharmony_ci case demod_ter: 30908c2ecf20Sopenharmony_ci ret = stv0367ter_read_status(fe, status); 30918c2ecf20Sopenharmony_ci break; 30928c2ecf20Sopenharmony_ci case demod_cab: 30938c2ecf20Sopenharmony_ci ret = stv0367cab_read_status(fe, status); 30948c2ecf20Sopenharmony_ci break; 30958c2ecf20Sopenharmony_ci default: 30968c2ecf20Sopenharmony_ci break; 30978c2ecf20Sopenharmony_ci } 30988c2ecf20Sopenharmony_ci 30998c2ecf20Sopenharmony_ci /* stop and report on *_read_status failure */ 31008c2ecf20Sopenharmony_ci if (ret) 31018c2ecf20Sopenharmony_ci return ret; 31028c2ecf20Sopenharmony_ci 31038c2ecf20Sopenharmony_ci stv0367ddb_read_signal_strength(fe); 31048c2ecf20Sopenharmony_ci 31058c2ecf20Sopenharmony_ci /* read carrier/noise when a carrier is detected */ 31068c2ecf20Sopenharmony_ci if (*status & FE_HAS_CARRIER) 31078c2ecf20Sopenharmony_ci stv0367ddb_read_snr(fe); 31088c2ecf20Sopenharmony_ci else 31098c2ecf20Sopenharmony_ci p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 31108c2ecf20Sopenharmony_ci 31118c2ecf20Sopenharmony_ci /* read uncorrected blocks on FE_HAS_LOCK */ 31128c2ecf20Sopenharmony_ci if (*status & FE_HAS_LOCK) 31138c2ecf20Sopenharmony_ci stv0367ddb_read_ucblocks(fe); 31148c2ecf20Sopenharmony_ci else 31158c2ecf20Sopenharmony_ci p->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 31168c2ecf20Sopenharmony_ci 31178c2ecf20Sopenharmony_ci return 0; 31188c2ecf20Sopenharmony_ci} 31198c2ecf20Sopenharmony_ci 31208c2ecf20Sopenharmony_cistatic int stv0367ddb_get_frontend(struct dvb_frontend *fe, 31218c2ecf20Sopenharmony_ci struct dtv_frontend_properties *p) 31228c2ecf20Sopenharmony_ci{ 31238c2ecf20Sopenharmony_ci struct stv0367_state *state = fe->demodulator_priv; 31248c2ecf20Sopenharmony_ci 31258c2ecf20Sopenharmony_ci switch (state->activedemod) { 31268c2ecf20Sopenharmony_ci case demod_ter: 31278c2ecf20Sopenharmony_ci return stv0367ter_get_frontend(fe, p); 31288c2ecf20Sopenharmony_ci case demod_cab: 31298c2ecf20Sopenharmony_ci return stv0367cab_get_frontend(fe, p); 31308c2ecf20Sopenharmony_ci default: 31318c2ecf20Sopenharmony_ci break; 31328c2ecf20Sopenharmony_ci } 31338c2ecf20Sopenharmony_ci 31348c2ecf20Sopenharmony_ci return 0; 31358c2ecf20Sopenharmony_ci} 31368c2ecf20Sopenharmony_ci 31378c2ecf20Sopenharmony_cistatic int stv0367ddb_sleep(struct dvb_frontend *fe) 31388c2ecf20Sopenharmony_ci{ 31398c2ecf20Sopenharmony_ci struct stv0367_state *state = fe->demodulator_priv; 31408c2ecf20Sopenharmony_ci 31418c2ecf20Sopenharmony_ci switch (state->activedemod) { 31428c2ecf20Sopenharmony_ci case demod_ter: 31438c2ecf20Sopenharmony_ci state->activedemod = demod_none; 31448c2ecf20Sopenharmony_ci return stv0367ter_sleep(fe); 31458c2ecf20Sopenharmony_ci case demod_cab: 31468c2ecf20Sopenharmony_ci state->activedemod = demod_none; 31478c2ecf20Sopenharmony_ci return stv0367cab_sleep(fe); 31488c2ecf20Sopenharmony_ci default: 31498c2ecf20Sopenharmony_ci break; 31508c2ecf20Sopenharmony_ci } 31518c2ecf20Sopenharmony_ci 31528c2ecf20Sopenharmony_ci return -EINVAL; 31538c2ecf20Sopenharmony_ci} 31548c2ecf20Sopenharmony_ci 31558c2ecf20Sopenharmony_cistatic int stv0367ddb_init(struct stv0367_state *state) 31568c2ecf20Sopenharmony_ci{ 31578c2ecf20Sopenharmony_ci struct stv0367ter_state *ter_state = state->ter_state; 31588c2ecf20Sopenharmony_ci struct dtv_frontend_properties *p = &state->fe.dtv_property_cache; 31598c2ecf20Sopenharmony_ci 31608c2ecf20Sopenharmony_ci stv0367_writereg(state, R367TER_TOPCTRL, 0x10); 31618c2ecf20Sopenharmony_ci 31628c2ecf20Sopenharmony_ci if (stv0367_deftabs[state->deftabs][STV0367_TAB_BASE]) 31638c2ecf20Sopenharmony_ci stv0367_write_table(state, 31648c2ecf20Sopenharmony_ci stv0367_deftabs[state->deftabs][STV0367_TAB_BASE]); 31658c2ecf20Sopenharmony_ci 31668c2ecf20Sopenharmony_ci stv0367_write_table(state, 31678c2ecf20Sopenharmony_ci stv0367_deftabs[state->deftabs][STV0367_TAB_CAB]); 31688c2ecf20Sopenharmony_ci 31698c2ecf20Sopenharmony_ci stv0367_writereg(state, R367TER_TOPCTRL, 0x00); 31708c2ecf20Sopenharmony_ci stv0367_write_table(state, 31718c2ecf20Sopenharmony_ci stv0367_deftabs[state->deftabs][STV0367_TAB_TER]); 31728c2ecf20Sopenharmony_ci 31738c2ecf20Sopenharmony_ci stv0367_writereg(state, R367TER_GAIN_SRC1, 0x2A); 31748c2ecf20Sopenharmony_ci stv0367_writereg(state, R367TER_GAIN_SRC2, 0xD6); 31758c2ecf20Sopenharmony_ci stv0367_writereg(state, R367TER_INC_DEROT1, 0x55); 31768c2ecf20Sopenharmony_ci stv0367_writereg(state, R367TER_INC_DEROT2, 0x55); 31778c2ecf20Sopenharmony_ci stv0367_writereg(state, R367TER_TRL_CTL, 0x14); 31788c2ecf20Sopenharmony_ci stv0367_writereg(state, R367TER_TRL_NOMRATE1, 0xAE); 31798c2ecf20Sopenharmony_ci stv0367_writereg(state, R367TER_TRL_NOMRATE2, 0x56); 31808c2ecf20Sopenharmony_ci stv0367_writereg(state, R367TER_FEPATH_CFG, 0x0); 31818c2ecf20Sopenharmony_ci 31828c2ecf20Sopenharmony_ci /* OFDM TS Setup */ 31838c2ecf20Sopenharmony_ci 31848c2ecf20Sopenharmony_ci stv0367_writereg(state, R367TER_TSCFGH, 0x70); 31858c2ecf20Sopenharmony_ci stv0367_writereg(state, R367TER_TSCFGM, 0xC0); 31868c2ecf20Sopenharmony_ci stv0367_writereg(state, R367TER_TSCFGL, 0x20); 31878c2ecf20Sopenharmony_ci stv0367_writereg(state, R367TER_TSSPEED, 0x40); /* Fixed at 54 MHz */ 31888c2ecf20Sopenharmony_ci 31898c2ecf20Sopenharmony_ci stv0367_writereg(state, R367TER_TSCFGH, 0x71); 31908c2ecf20Sopenharmony_ci stv0367_writereg(state, R367TER_TSCFGH, 0x70); 31918c2ecf20Sopenharmony_ci 31928c2ecf20Sopenharmony_ci stv0367_writereg(state, R367TER_TOPCTRL, 0x10); 31938c2ecf20Sopenharmony_ci 31948c2ecf20Sopenharmony_ci /* Also needed for QAM */ 31958c2ecf20Sopenharmony_ci stv0367_writereg(state, R367TER_AGC12C, 0x01); /* AGC Pin setup */ 31968c2ecf20Sopenharmony_ci 31978c2ecf20Sopenharmony_ci stv0367_writereg(state, R367TER_AGCCTRL1, 0x8A); 31988c2ecf20Sopenharmony_ci 31998c2ecf20Sopenharmony_ci /* QAM TS setup, note exact format also depends on descrambler */ 32008c2ecf20Sopenharmony_ci /* settings */ 32018c2ecf20Sopenharmony_ci /* Inverted Clock, Swap, serial */ 32028c2ecf20Sopenharmony_ci stv0367_writereg(state, R367CAB_OUTFORMAT_0, 0x85); 32038c2ecf20Sopenharmony_ci 32048c2ecf20Sopenharmony_ci /* Clock setup (PLL bypassed and disabled) */ 32058c2ecf20Sopenharmony_ci stv0367_writereg(state, R367TER_ANACTRL, 0x0D); 32068c2ecf20Sopenharmony_ci 32078c2ecf20Sopenharmony_ci /* IC runs at 58 MHz with a 27 MHz crystal */ 32088c2ecf20Sopenharmony_ci stv0367_pll_setup(state, STV0367_ICSPEED_58000, state->config->xtal); 32098c2ecf20Sopenharmony_ci 32108c2ecf20Sopenharmony_ci /* Tuner setup */ 32118c2ecf20Sopenharmony_ci /* Buffer Q disabled, I Enabled, signed ADC */ 32128c2ecf20Sopenharmony_ci stv0367_writereg(state, R367TER_ANADIGCTRL, 0x8b); 32138c2ecf20Sopenharmony_ci stv0367_writereg(state, R367TER_DUAL_AD12, 0x04); /* ADCQ disabled */ 32148c2ecf20Sopenharmony_ci 32158c2ecf20Sopenharmony_ci /* Improves the C/N lock limit */ 32168c2ecf20Sopenharmony_ci stv0367_writereg(state, R367CAB_FSM_SNR2_HTH, 0x23); 32178c2ecf20Sopenharmony_ci /* ZIF/IF Automatic mode */ 32188c2ecf20Sopenharmony_ci stv0367_writereg(state, R367CAB_IQ_QAM, 0x01); 32198c2ecf20Sopenharmony_ci /* Improving burst noise performances */ 32208c2ecf20Sopenharmony_ci stv0367_writereg(state, R367CAB_EQU_FFE_LEAKAGE, 0x83); 32218c2ecf20Sopenharmony_ci /* Improving ACI performances */ 32228c2ecf20Sopenharmony_ci stv0367_writereg(state, R367CAB_IQDEM_ADJ_EN, 0x05); 32238c2ecf20Sopenharmony_ci 32248c2ecf20Sopenharmony_ci /* PLL enabled and used */ 32258c2ecf20Sopenharmony_ci stv0367_writereg(state, R367TER_ANACTRL, 0x00); 32268c2ecf20Sopenharmony_ci 32278c2ecf20Sopenharmony_ci stv0367_writereg(state, R367TER_I2CRPT, (0x08 | ((5 & 0x07) << 4))); 32288c2ecf20Sopenharmony_ci 32298c2ecf20Sopenharmony_ci ter_state->pBER = 0; 32308c2ecf20Sopenharmony_ci ter_state->first_lock = 0; 32318c2ecf20Sopenharmony_ci ter_state->unlock_counter = 2; 32328c2ecf20Sopenharmony_ci 32338c2ecf20Sopenharmony_ci p->strength.len = 1; 32348c2ecf20Sopenharmony_ci p->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 32358c2ecf20Sopenharmony_ci p->cnr.len = 1; 32368c2ecf20Sopenharmony_ci p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 32378c2ecf20Sopenharmony_ci p->block_error.len = 1; 32388c2ecf20Sopenharmony_ci p->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 32398c2ecf20Sopenharmony_ci 32408c2ecf20Sopenharmony_ci return 0; 32418c2ecf20Sopenharmony_ci} 32428c2ecf20Sopenharmony_ci 32438c2ecf20Sopenharmony_cistatic const struct dvb_frontend_ops stv0367ddb_ops = { 32448c2ecf20Sopenharmony_ci .delsys = { SYS_DVBC_ANNEX_A, SYS_DVBT }, 32458c2ecf20Sopenharmony_ci .info = { 32468c2ecf20Sopenharmony_ci .name = "ST STV0367 DDB DVB-C/T", 32478c2ecf20Sopenharmony_ci .frequency_min_hz = 47 * MHz, 32488c2ecf20Sopenharmony_ci .frequency_max_hz = 865 * MHz, 32498c2ecf20Sopenharmony_ci .frequency_stepsize_hz = 166667, 32508c2ecf20Sopenharmony_ci .symbol_rate_min = 870000, 32518c2ecf20Sopenharmony_ci .symbol_rate_max = 11700000, 32528c2ecf20Sopenharmony_ci .caps = /* DVB-C */ 32538c2ecf20Sopenharmony_ci 0x400 |/* FE_CAN_QAM_4 */ 32548c2ecf20Sopenharmony_ci FE_CAN_QAM_16 | FE_CAN_QAM_32 | 32558c2ecf20Sopenharmony_ci FE_CAN_QAM_64 | FE_CAN_QAM_128 | 32568c2ecf20Sopenharmony_ci FE_CAN_QAM_256 | 32578c2ecf20Sopenharmony_ci /* DVB-T */ 32588c2ecf20Sopenharmony_ci FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | 32598c2ecf20Sopenharmony_ci FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | 32608c2ecf20Sopenharmony_ci FE_CAN_QPSK | FE_CAN_TRANSMISSION_MODE_AUTO | 32618c2ecf20Sopenharmony_ci FE_CAN_RECOVER | FE_CAN_INVERSION_AUTO | 32628c2ecf20Sopenharmony_ci FE_CAN_MUTE_TS 32638c2ecf20Sopenharmony_ci }, 32648c2ecf20Sopenharmony_ci .release = stv0367_release, 32658c2ecf20Sopenharmony_ci .sleep = stv0367ddb_sleep, 32668c2ecf20Sopenharmony_ci .i2c_gate_ctrl = stv0367cab_gate_ctrl, /* valid for TER and CAB */ 32678c2ecf20Sopenharmony_ci .set_frontend = stv0367ddb_set_frontend, 32688c2ecf20Sopenharmony_ci .get_frontend = stv0367ddb_get_frontend, 32698c2ecf20Sopenharmony_ci .get_tune_settings = stv0367_get_tune_settings, 32708c2ecf20Sopenharmony_ci .read_status = stv0367ddb_read_status, 32718c2ecf20Sopenharmony_ci}; 32728c2ecf20Sopenharmony_ci 32738c2ecf20Sopenharmony_cistruct dvb_frontend *stv0367ddb_attach(const struct stv0367_config *config, 32748c2ecf20Sopenharmony_ci struct i2c_adapter *i2c) 32758c2ecf20Sopenharmony_ci{ 32768c2ecf20Sopenharmony_ci struct stv0367_state *state = NULL; 32778c2ecf20Sopenharmony_ci struct stv0367ter_state *ter_state = NULL; 32788c2ecf20Sopenharmony_ci struct stv0367cab_state *cab_state = NULL; 32798c2ecf20Sopenharmony_ci 32808c2ecf20Sopenharmony_ci /* allocate memory for the internal state */ 32818c2ecf20Sopenharmony_ci state = kzalloc(sizeof(struct stv0367_state), GFP_KERNEL); 32828c2ecf20Sopenharmony_ci if (state == NULL) 32838c2ecf20Sopenharmony_ci goto error; 32848c2ecf20Sopenharmony_ci ter_state = kzalloc(sizeof(struct stv0367ter_state), GFP_KERNEL); 32858c2ecf20Sopenharmony_ci if (ter_state == NULL) 32868c2ecf20Sopenharmony_ci goto error; 32878c2ecf20Sopenharmony_ci cab_state = kzalloc(sizeof(struct stv0367cab_state), GFP_KERNEL); 32888c2ecf20Sopenharmony_ci if (cab_state == NULL) 32898c2ecf20Sopenharmony_ci goto error; 32908c2ecf20Sopenharmony_ci 32918c2ecf20Sopenharmony_ci /* setup the state */ 32928c2ecf20Sopenharmony_ci state->i2c = i2c; 32938c2ecf20Sopenharmony_ci state->config = config; 32948c2ecf20Sopenharmony_ci state->ter_state = ter_state; 32958c2ecf20Sopenharmony_ci cab_state->search_range = 280000; 32968c2ecf20Sopenharmony_ci cab_state->qamfec_status_reg = F367CAB_DESCR_SYNCSTATE; 32978c2ecf20Sopenharmony_ci state->cab_state = cab_state; 32988c2ecf20Sopenharmony_ci state->fe.ops = stv0367ddb_ops; 32998c2ecf20Sopenharmony_ci state->fe.demodulator_priv = state; 33008c2ecf20Sopenharmony_ci state->chip_id = stv0367_readreg(state, R367TER_ID); 33018c2ecf20Sopenharmony_ci 33028c2ecf20Sopenharmony_ci /* demod operation options */ 33038c2ecf20Sopenharmony_ci state->use_i2c_gatectrl = 0; 33048c2ecf20Sopenharmony_ci state->deftabs = STV0367_DEFTAB_DDB; 33058c2ecf20Sopenharmony_ci state->reinit_on_setfrontend = 0; 33068c2ecf20Sopenharmony_ci state->auto_if_khz = 1; 33078c2ecf20Sopenharmony_ci state->activedemod = demod_none; 33088c2ecf20Sopenharmony_ci 33098c2ecf20Sopenharmony_ci dprintk("%s: chip_id = 0x%x\n", __func__, state->chip_id); 33108c2ecf20Sopenharmony_ci 33118c2ecf20Sopenharmony_ci /* check if the demod is there */ 33128c2ecf20Sopenharmony_ci if ((state->chip_id != 0x50) && (state->chip_id != 0x60)) 33138c2ecf20Sopenharmony_ci goto error; 33148c2ecf20Sopenharmony_ci 33158c2ecf20Sopenharmony_ci dev_info(&i2c->dev, "Found %s with ChipID %02X at adr %02X\n", 33168c2ecf20Sopenharmony_ci state->fe.ops.info.name, state->chip_id, 33178c2ecf20Sopenharmony_ci config->demod_address); 33188c2ecf20Sopenharmony_ci 33198c2ecf20Sopenharmony_ci stv0367ddb_init(state); 33208c2ecf20Sopenharmony_ci 33218c2ecf20Sopenharmony_ci return &state->fe; 33228c2ecf20Sopenharmony_ci 33238c2ecf20Sopenharmony_cierror: 33248c2ecf20Sopenharmony_ci kfree(cab_state); 33258c2ecf20Sopenharmony_ci kfree(ter_state); 33268c2ecf20Sopenharmony_ci kfree(state); 33278c2ecf20Sopenharmony_ci return NULL; 33288c2ecf20Sopenharmony_ci} 33298c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(stv0367ddb_attach); 33308c2ecf20Sopenharmony_ci 33318c2ecf20Sopenharmony_ciMODULE_PARM_DESC(debug, "Set debug"); 33328c2ecf20Sopenharmony_ciMODULE_PARM_DESC(i2c_debug, "Set i2c debug"); 33338c2ecf20Sopenharmony_ci 33348c2ecf20Sopenharmony_ciMODULE_AUTHOR("Igor M. Liplianin"); 33358c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("ST STV0367 DVB-C/T demodulator driver"); 33368c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 3337