18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Linux-DVB Driver for DiBcom's DiB0090 base-band RF Tuner. 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2005-9 DiBcom (http://www.dibcom.fr/) 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * This code is more or less generated from another driver, please 88c2ecf20Sopenharmony_ci * excuse some codingstyle oddities. 98c2ecf20Sopenharmony_ci */ 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci#include <linux/kernel.h> 148c2ecf20Sopenharmony_ci#include <linux/slab.h> 158c2ecf20Sopenharmony_ci#include <linux/i2c.h> 168c2ecf20Sopenharmony_ci#include <linux/mutex.h> 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ci#include <media/dvb_frontend.h> 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci#include "dib0090.h" 218c2ecf20Sopenharmony_ci#include "dibx000_common.h" 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_cistatic int debug; 248c2ecf20Sopenharmony_cimodule_param(debug, int, 0644); 258c2ecf20Sopenharmony_ciMODULE_PARM_DESC(debug, "turn on debugging (default: 0)"); 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_ci#define dprintk(fmt, arg...) do { \ 288c2ecf20Sopenharmony_ci if (debug) \ 298c2ecf20Sopenharmony_ci printk(KERN_DEBUG pr_fmt("%s: " fmt), \ 308c2ecf20Sopenharmony_ci __func__, ##arg); \ 318c2ecf20Sopenharmony_ci} while (0) 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci#define CONFIG_SYS_DVBT 348c2ecf20Sopenharmony_ci#define CONFIG_SYS_ISDBT 358c2ecf20Sopenharmony_ci#define CONFIG_BAND_CBAND 368c2ecf20Sopenharmony_ci#define CONFIG_BAND_VHF 378c2ecf20Sopenharmony_ci#define CONFIG_BAND_UHF 388c2ecf20Sopenharmony_ci#define CONFIG_DIB0090_USE_PWM_AGC 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci#define EN_LNA0 0x8000 418c2ecf20Sopenharmony_ci#define EN_LNA1 0x4000 428c2ecf20Sopenharmony_ci#define EN_LNA2 0x2000 438c2ecf20Sopenharmony_ci#define EN_LNA3 0x1000 448c2ecf20Sopenharmony_ci#define EN_MIX0 0x0800 458c2ecf20Sopenharmony_ci#define EN_MIX1 0x0400 468c2ecf20Sopenharmony_ci#define EN_MIX2 0x0200 478c2ecf20Sopenharmony_ci#define EN_MIX3 0x0100 488c2ecf20Sopenharmony_ci#define EN_IQADC 0x0040 498c2ecf20Sopenharmony_ci#define EN_PLL 0x0020 508c2ecf20Sopenharmony_ci#define EN_TX 0x0010 518c2ecf20Sopenharmony_ci#define EN_BB 0x0008 528c2ecf20Sopenharmony_ci#define EN_LO 0x0004 538c2ecf20Sopenharmony_ci#define EN_BIAS 0x0001 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci#define EN_IQANA 0x0002 568c2ecf20Sopenharmony_ci#define EN_DIGCLK 0x0080 /* not in the 0x24 reg, only in 0x1b */ 578c2ecf20Sopenharmony_ci#define EN_CRYSTAL 0x0002 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci#define EN_UHF 0x22E9 608c2ecf20Sopenharmony_ci#define EN_VHF 0x44E9 618c2ecf20Sopenharmony_ci#define EN_LBD 0x11E9 628c2ecf20Sopenharmony_ci#define EN_SBD 0x44E9 638c2ecf20Sopenharmony_ci#define EN_CAB 0x88E9 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci/* Calibration defines */ 668c2ecf20Sopenharmony_ci#define DC_CAL 0x1 678c2ecf20Sopenharmony_ci#define WBD_CAL 0x2 688c2ecf20Sopenharmony_ci#define TEMP_CAL 0x4 698c2ecf20Sopenharmony_ci#define CAPTRIM_CAL 0x8 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci#define KROSUS_PLL_LOCKED 0x800 728c2ecf20Sopenharmony_ci#define KROSUS 0x2 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci/* Use those defines to identify SOC version */ 758c2ecf20Sopenharmony_ci#define SOC 0x02 768c2ecf20Sopenharmony_ci#define SOC_7090_P1G_11R1 0x82 778c2ecf20Sopenharmony_ci#define SOC_7090_P1G_21R1 0x8a 788c2ecf20Sopenharmony_ci#define SOC_8090_P1G_11R1 0x86 798c2ecf20Sopenharmony_ci#define SOC_8090_P1G_21R1 0x8e 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci/* else use thos ones to check */ 828c2ecf20Sopenharmony_ci#define P1A_B 0x0 838c2ecf20Sopenharmony_ci#define P1C 0x1 848c2ecf20Sopenharmony_ci#define P1D_E_F 0x3 858c2ecf20Sopenharmony_ci#define P1G 0x7 868c2ecf20Sopenharmony_ci#define P1G_21R2 0xf 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci#define MP001 0x1 /* Single 9090/8096 */ 898c2ecf20Sopenharmony_ci#define MP005 0x4 /* Single Sband */ 908c2ecf20Sopenharmony_ci#define MP008 0x6 /* Dual diversity VHF-UHF-LBAND */ 918c2ecf20Sopenharmony_ci#define MP009 0x7 /* Dual diversity 29098 CBAND-UHF-LBAND-SBAND */ 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci#define pgm_read_word(w) (*w) 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_cistruct dc_calibration; 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_cistruct dib0090_tuning { 988c2ecf20Sopenharmony_ci u32 max_freq; /* for every frequency less than or equal to that field: this information is correct */ 998c2ecf20Sopenharmony_ci u8 switch_trim; 1008c2ecf20Sopenharmony_ci u8 lna_tune; 1018c2ecf20Sopenharmony_ci u16 lna_bias; 1028c2ecf20Sopenharmony_ci u16 v2i; 1038c2ecf20Sopenharmony_ci u16 mix; 1048c2ecf20Sopenharmony_ci u16 load; 1058c2ecf20Sopenharmony_ci u16 tuner_enable; 1068c2ecf20Sopenharmony_ci}; 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_cistruct dib0090_pll { 1098c2ecf20Sopenharmony_ci u32 max_freq; /* for every frequency less than or equal to that field: this information is correct */ 1108c2ecf20Sopenharmony_ci u8 vco_band; 1118c2ecf20Sopenharmony_ci u8 hfdiv_code; 1128c2ecf20Sopenharmony_ci u8 hfdiv; 1138c2ecf20Sopenharmony_ci u8 topresc; 1148c2ecf20Sopenharmony_ci}; 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_cistruct dib0090_identity { 1178c2ecf20Sopenharmony_ci u8 version; 1188c2ecf20Sopenharmony_ci u8 product; 1198c2ecf20Sopenharmony_ci u8 p1g; 1208c2ecf20Sopenharmony_ci u8 in_soc; 1218c2ecf20Sopenharmony_ci}; 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_cistruct dib0090_state { 1248c2ecf20Sopenharmony_ci struct i2c_adapter *i2c; 1258c2ecf20Sopenharmony_ci struct dvb_frontend *fe; 1268c2ecf20Sopenharmony_ci const struct dib0090_config *config; 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci u8 current_band; 1298c2ecf20Sopenharmony_ci enum frontend_tune_state tune_state; 1308c2ecf20Sopenharmony_ci u32 current_rf; 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci u16 wbd_offset; 1338c2ecf20Sopenharmony_ci s16 wbd_target; /* in dB */ 1348c2ecf20Sopenharmony_ci 1358c2ecf20Sopenharmony_ci s16 rf_gain_limit; /* take-over-point: where to split between bb and rf gain */ 1368c2ecf20Sopenharmony_ci s16 current_gain; /* keeps the currently programmed gain */ 1378c2ecf20Sopenharmony_ci u8 agc_step; /* new binary search */ 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_ci u16 gain[2]; /* for channel monitoring */ 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_ci const u16 *rf_ramp; 1428c2ecf20Sopenharmony_ci const u16 *bb_ramp; 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_ci /* for the software AGC ramps */ 1458c2ecf20Sopenharmony_ci u16 bb_1_def; 1468c2ecf20Sopenharmony_ci u16 rf_lt_def; 1478c2ecf20Sopenharmony_ci u16 gain_reg[4]; 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci /* for the captrim/dc-offset search */ 1508c2ecf20Sopenharmony_ci s8 step; 1518c2ecf20Sopenharmony_ci s16 adc_diff; 1528c2ecf20Sopenharmony_ci s16 min_adc_diff; 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci s8 captrim; 1558c2ecf20Sopenharmony_ci s8 fcaptrim; 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_ci const struct dc_calibration *dc; 1588c2ecf20Sopenharmony_ci u16 bb6, bb7; 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci const struct dib0090_tuning *current_tune_table_index; 1618c2ecf20Sopenharmony_ci const struct dib0090_pll *current_pll_table_index; 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci u8 tuner_is_tuned; 1648c2ecf20Sopenharmony_ci u8 agc_freeze; 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_ci struct dib0090_identity identity; 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_ci u32 rf_request; 1698c2ecf20Sopenharmony_ci u8 current_standard; 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_ci u8 calibrate; 1728c2ecf20Sopenharmony_ci u32 rest; 1738c2ecf20Sopenharmony_ci u16 bias; 1748c2ecf20Sopenharmony_ci s16 temperature; 1758c2ecf20Sopenharmony_ci 1768c2ecf20Sopenharmony_ci u8 wbd_calibration_gain; 1778c2ecf20Sopenharmony_ci const struct dib0090_wbd_slope *current_wbd_table; 1788c2ecf20Sopenharmony_ci u16 wbdmux; 1798c2ecf20Sopenharmony_ci 1808c2ecf20Sopenharmony_ci /* for the I2C transfer */ 1818c2ecf20Sopenharmony_ci struct i2c_msg msg[2]; 1828c2ecf20Sopenharmony_ci u8 i2c_write_buffer[3]; 1838c2ecf20Sopenharmony_ci u8 i2c_read_buffer[2]; 1848c2ecf20Sopenharmony_ci struct mutex i2c_buffer_lock; 1858c2ecf20Sopenharmony_ci}; 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_cistruct dib0090_fw_state { 1888c2ecf20Sopenharmony_ci struct i2c_adapter *i2c; 1898c2ecf20Sopenharmony_ci struct dvb_frontend *fe; 1908c2ecf20Sopenharmony_ci struct dib0090_identity identity; 1918c2ecf20Sopenharmony_ci const struct dib0090_config *config; 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_ci /* for the I2C transfer */ 1948c2ecf20Sopenharmony_ci struct i2c_msg msg; 1958c2ecf20Sopenharmony_ci u8 i2c_write_buffer[2]; 1968c2ecf20Sopenharmony_ci u8 i2c_read_buffer[2]; 1978c2ecf20Sopenharmony_ci struct mutex i2c_buffer_lock; 1988c2ecf20Sopenharmony_ci}; 1998c2ecf20Sopenharmony_ci 2008c2ecf20Sopenharmony_cistatic u16 dib0090_read_reg(struct dib0090_state *state, u8 reg) 2018c2ecf20Sopenharmony_ci{ 2028c2ecf20Sopenharmony_ci u16 ret; 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ci if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) { 2058c2ecf20Sopenharmony_ci dprintk("could not acquire lock\n"); 2068c2ecf20Sopenharmony_ci return 0; 2078c2ecf20Sopenharmony_ci } 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_ci state->i2c_write_buffer[0] = reg; 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_ci memset(state->msg, 0, 2 * sizeof(struct i2c_msg)); 2128c2ecf20Sopenharmony_ci state->msg[0].addr = state->config->i2c_address; 2138c2ecf20Sopenharmony_ci state->msg[0].flags = 0; 2148c2ecf20Sopenharmony_ci state->msg[0].buf = state->i2c_write_buffer; 2158c2ecf20Sopenharmony_ci state->msg[0].len = 1; 2168c2ecf20Sopenharmony_ci state->msg[1].addr = state->config->i2c_address; 2178c2ecf20Sopenharmony_ci state->msg[1].flags = I2C_M_RD; 2188c2ecf20Sopenharmony_ci state->msg[1].buf = state->i2c_read_buffer; 2198c2ecf20Sopenharmony_ci state->msg[1].len = 2; 2208c2ecf20Sopenharmony_ci 2218c2ecf20Sopenharmony_ci if (i2c_transfer(state->i2c, state->msg, 2) != 2) { 2228c2ecf20Sopenharmony_ci pr_warn("DiB0090 I2C read failed\n"); 2238c2ecf20Sopenharmony_ci ret = 0; 2248c2ecf20Sopenharmony_ci } else 2258c2ecf20Sopenharmony_ci ret = (state->i2c_read_buffer[0] << 8) 2268c2ecf20Sopenharmony_ci | state->i2c_read_buffer[1]; 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_ci mutex_unlock(&state->i2c_buffer_lock); 2298c2ecf20Sopenharmony_ci return ret; 2308c2ecf20Sopenharmony_ci} 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_cistatic int dib0090_write_reg(struct dib0090_state *state, u32 reg, u16 val) 2338c2ecf20Sopenharmony_ci{ 2348c2ecf20Sopenharmony_ci int ret; 2358c2ecf20Sopenharmony_ci 2368c2ecf20Sopenharmony_ci if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) { 2378c2ecf20Sopenharmony_ci dprintk("could not acquire lock\n"); 2388c2ecf20Sopenharmony_ci return -EINVAL; 2398c2ecf20Sopenharmony_ci } 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_ci state->i2c_write_buffer[0] = reg & 0xff; 2428c2ecf20Sopenharmony_ci state->i2c_write_buffer[1] = val >> 8; 2438c2ecf20Sopenharmony_ci state->i2c_write_buffer[2] = val & 0xff; 2448c2ecf20Sopenharmony_ci 2458c2ecf20Sopenharmony_ci memset(state->msg, 0, sizeof(struct i2c_msg)); 2468c2ecf20Sopenharmony_ci state->msg[0].addr = state->config->i2c_address; 2478c2ecf20Sopenharmony_ci state->msg[0].flags = 0; 2488c2ecf20Sopenharmony_ci state->msg[0].buf = state->i2c_write_buffer; 2498c2ecf20Sopenharmony_ci state->msg[0].len = 3; 2508c2ecf20Sopenharmony_ci 2518c2ecf20Sopenharmony_ci if (i2c_transfer(state->i2c, state->msg, 1) != 1) { 2528c2ecf20Sopenharmony_ci pr_warn("DiB0090 I2C write failed\n"); 2538c2ecf20Sopenharmony_ci ret = -EREMOTEIO; 2548c2ecf20Sopenharmony_ci } else 2558c2ecf20Sopenharmony_ci ret = 0; 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_ci mutex_unlock(&state->i2c_buffer_lock); 2588c2ecf20Sopenharmony_ci return ret; 2598c2ecf20Sopenharmony_ci} 2608c2ecf20Sopenharmony_ci 2618c2ecf20Sopenharmony_cistatic u16 dib0090_fw_read_reg(struct dib0090_fw_state *state, u8 reg) 2628c2ecf20Sopenharmony_ci{ 2638c2ecf20Sopenharmony_ci u16 ret; 2648c2ecf20Sopenharmony_ci 2658c2ecf20Sopenharmony_ci if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) { 2668c2ecf20Sopenharmony_ci dprintk("could not acquire lock\n"); 2678c2ecf20Sopenharmony_ci return 0; 2688c2ecf20Sopenharmony_ci } 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_ci state->i2c_write_buffer[0] = reg; 2718c2ecf20Sopenharmony_ci 2728c2ecf20Sopenharmony_ci memset(&state->msg, 0, sizeof(struct i2c_msg)); 2738c2ecf20Sopenharmony_ci state->msg.addr = reg; 2748c2ecf20Sopenharmony_ci state->msg.flags = I2C_M_RD; 2758c2ecf20Sopenharmony_ci state->msg.buf = state->i2c_read_buffer; 2768c2ecf20Sopenharmony_ci state->msg.len = 2; 2778c2ecf20Sopenharmony_ci if (i2c_transfer(state->i2c, &state->msg, 1) != 1) { 2788c2ecf20Sopenharmony_ci pr_warn("DiB0090 I2C read failed\n"); 2798c2ecf20Sopenharmony_ci ret = 0; 2808c2ecf20Sopenharmony_ci } else 2818c2ecf20Sopenharmony_ci ret = (state->i2c_read_buffer[0] << 8) 2828c2ecf20Sopenharmony_ci | state->i2c_read_buffer[1]; 2838c2ecf20Sopenharmony_ci 2848c2ecf20Sopenharmony_ci mutex_unlock(&state->i2c_buffer_lock); 2858c2ecf20Sopenharmony_ci return ret; 2868c2ecf20Sopenharmony_ci} 2878c2ecf20Sopenharmony_ci 2888c2ecf20Sopenharmony_cistatic int dib0090_fw_write_reg(struct dib0090_fw_state *state, u8 reg, u16 val) 2898c2ecf20Sopenharmony_ci{ 2908c2ecf20Sopenharmony_ci int ret; 2918c2ecf20Sopenharmony_ci 2928c2ecf20Sopenharmony_ci if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) { 2938c2ecf20Sopenharmony_ci dprintk("could not acquire lock\n"); 2948c2ecf20Sopenharmony_ci return -EINVAL; 2958c2ecf20Sopenharmony_ci } 2968c2ecf20Sopenharmony_ci 2978c2ecf20Sopenharmony_ci state->i2c_write_buffer[0] = val >> 8; 2988c2ecf20Sopenharmony_ci state->i2c_write_buffer[1] = val & 0xff; 2998c2ecf20Sopenharmony_ci 3008c2ecf20Sopenharmony_ci memset(&state->msg, 0, sizeof(struct i2c_msg)); 3018c2ecf20Sopenharmony_ci state->msg.addr = reg; 3028c2ecf20Sopenharmony_ci state->msg.flags = 0; 3038c2ecf20Sopenharmony_ci state->msg.buf = state->i2c_write_buffer; 3048c2ecf20Sopenharmony_ci state->msg.len = 2; 3058c2ecf20Sopenharmony_ci if (i2c_transfer(state->i2c, &state->msg, 1) != 1) { 3068c2ecf20Sopenharmony_ci pr_warn("DiB0090 I2C write failed\n"); 3078c2ecf20Sopenharmony_ci ret = -EREMOTEIO; 3088c2ecf20Sopenharmony_ci } else 3098c2ecf20Sopenharmony_ci ret = 0; 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_ci mutex_unlock(&state->i2c_buffer_lock); 3128c2ecf20Sopenharmony_ci return ret; 3138c2ecf20Sopenharmony_ci} 3148c2ecf20Sopenharmony_ci 3158c2ecf20Sopenharmony_ci#define HARD_RESET(state) do { if (cfg->reset) { if (cfg->sleep) cfg->sleep(fe, 0); msleep(10); cfg->reset(fe, 1); msleep(10); cfg->reset(fe, 0); msleep(10); } } while (0) 3168c2ecf20Sopenharmony_ci#define ADC_TARGET -220 3178c2ecf20Sopenharmony_ci#define GAIN_ALPHA 5 3188c2ecf20Sopenharmony_ci#define WBD_ALPHA 6 3198c2ecf20Sopenharmony_ci#define LPF 100 3208c2ecf20Sopenharmony_cistatic void dib0090_write_regs(struct dib0090_state *state, u8 r, const u16 * b, u8 c) 3218c2ecf20Sopenharmony_ci{ 3228c2ecf20Sopenharmony_ci do { 3238c2ecf20Sopenharmony_ci dib0090_write_reg(state, r++, *b++); 3248c2ecf20Sopenharmony_ci } while (--c); 3258c2ecf20Sopenharmony_ci} 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_cistatic int dib0090_identify(struct dvb_frontend *fe) 3288c2ecf20Sopenharmony_ci{ 3298c2ecf20Sopenharmony_ci struct dib0090_state *state = fe->tuner_priv; 3308c2ecf20Sopenharmony_ci u16 v; 3318c2ecf20Sopenharmony_ci struct dib0090_identity *identity = &state->identity; 3328c2ecf20Sopenharmony_ci 3338c2ecf20Sopenharmony_ci v = dib0090_read_reg(state, 0x1a); 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_ci identity->p1g = 0; 3368c2ecf20Sopenharmony_ci identity->in_soc = 0; 3378c2ecf20Sopenharmony_ci 3388c2ecf20Sopenharmony_ci dprintk("Tuner identification (Version = 0x%04x)\n", v); 3398c2ecf20Sopenharmony_ci 3408c2ecf20Sopenharmony_ci /* without PLL lock info */ 3418c2ecf20Sopenharmony_ci v &= ~KROSUS_PLL_LOCKED; 3428c2ecf20Sopenharmony_ci 3438c2ecf20Sopenharmony_ci identity->version = v & 0xff; 3448c2ecf20Sopenharmony_ci identity->product = (v >> 8) & 0xf; 3458c2ecf20Sopenharmony_ci 3468c2ecf20Sopenharmony_ci if (identity->product != KROSUS) 3478c2ecf20Sopenharmony_ci goto identification_error; 3488c2ecf20Sopenharmony_ci 3498c2ecf20Sopenharmony_ci if ((identity->version & 0x3) == SOC) { 3508c2ecf20Sopenharmony_ci identity->in_soc = 1; 3518c2ecf20Sopenharmony_ci switch (identity->version) { 3528c2ecf20Sopenharmony_ci case SOC_8090_P1G_11R1: 3538c2ecf20Sopenharmony_ci dprintk("SOC 8090 P1-G11R1 Has been detected\n"); 3548c2ecf20Sopenharmony_ci identity->p1g = 1; 3558c2ecf20Sopenharmony_ci break; 3568c2ecf20Sopenharmony_ci case SOC_8090_P1G_21R1: 3578c2ecf20Sopenharmony_ci dprintk("SOC 8090 P1-G21R1 Has been detected\n"); 3588c2ecf20Sopenharmony_ci identity->p1g = 1; 3598c2ecf20Sopenharmony_ci break; 3608c2ecf20Sopenharmony_ci case SOC_7090_P1G_11R1: 3618c2ecf20Sopenharmony_ci dprintk("SOC 7090 P1-G11R1 Has been detected\n"); 3628c2ecf20Sopenharmony_ci identity->p1g = 1; 3638c2ecf20Sopenharmony_ci break; 3648c2ecf20Sopenharmony_ci case SOC_7090_P1G_21R1: 3658c2ecf20Sopenharmony_ci dprintk("SOC 7090 P1-G21R1 Has been detected\n"); 3668c2ecf20Sopenharmony_ci identity->p1g = 1; 3678c2ecf20Sopenharmony_ci break; 3688c2ecf20Sopenharmony_ci default: 3698c2ecf20Sopenharmony_ci goto identification_error; 3708c2ecf20Sopenharmony_ci } 3718c2ecf20Sopenharmony_ci } else { 3728c2ecf20Sopenharmony_ci switch ((identity->version >> 5) & 0x7) { 3738c2ecf20Sopenharmony_ci case MP001: 3748c2ecf20Sopenharmony_ci dprintk("MP001 : 9090/8096\n"); 3758c2ecf20Sopenharmony_ci break; 3768c2ecf20Sopenharmony_ci case MP005: 3778c2ecf20Sopenharmony_ci dprintk("MP005 : Single Sband\n"); 3788c2ecf20Sopenharmony_ci break; 3798c2ecf20Sopenharmony_ci case MP008: 3808c2ecf20Sopenharmony_ci dprintk("MP008 : diversity VHF-UHF-LBAND\n"); 3818c2ecf20Sopenharmony_ci break; 3828c2ecf20Sopenharmony_ci case MP009: 3838c2ecf20Sopenharmony_ci dprintk("MP009 : diversity 29098 CBAND-UHF-LBAND-SBAND\n"); 3848c2ecf20Sopenharmony_ci break; 3858c2ecf20Sopenharmony_ci default: 3868c2ecf20Sopenharmony_ci goto identification_error; 3878c2ecf20Sopenharmony_ci } 3888c2ecf20Sopenharmony_ci 3898c2ecf20Sopenharmony_ci switch (identity->version & 0x1f) { 3908c2ecf20Sopenharmony_ci case P1G_21R2: 3918c2ecf20Sopenharmony_ci dprintk("P1G_21R2 detected\n"); 3928c2ecf20Sopenharmony_ci identity->p1g = 1; 3938c2ecf20Sopenharmony_ci break; 3948c2ecf20Sopenharmony_ci case P1G: 3958c2ecf20Sopenharmony_ci dprintk("P1G detected\n"); 3968c2ecf20Sopenharmony_ci identity->p1g = 1; 3978c2ecf20Sopenharmony_ci break; 3988c2ecf20Sopenharmony_ci case P1D_E_F: 3998c2ecf20Sopenharmony_ci dprintk("P1D/E/F detected\n"); 4008c2ecf20Sopenharmony_ci break; 4018c2ecf20Sopenharmony_ci case P1C: 4028c2ecf20Sopenharmony_ci dprintk("P1C detected\n"); 4038c2ecf20Sopenharmony_ci break; 4048c2ecf20Sopenharmony_ci case P1A_B: 4058c2ecf20Sopenharmony_ci dprintk("P1-A/B detected: driver is deactivated - not available\n"); 4068c2ecf20Sopenharmony_ci goto identification_error; 4078c2ecf20Sopenharmony_ci break; 4088c2ecf20Sopenharmony_ci default: 4098c2ecf20Sopenharmony_ci goto identification_error; 4108c2ecf20Sopenharmony_ci } 4118c2ecf20Sopenharmony_ci } 4128c2ecf20Sopenharmony_ci 4138c2ecf20Sopenharmony_ci return 0; 4148c2ecf20Sopenharmony_ci 4158c2ecf20Sopenharmony_ciidentification_error: 4168c2ecf20Sopenharmony_ci return -EIO; 4178c2ecf20Sopenharmony_ci} 4188c2ecf20Sopenharmony_ci 4198c2ecf20Sopenharmony_cistatic int dib0090_fw_identify(struct dvb_frontend *fe) 4208c2ecf20Sopenharmony_ci{ 4218c2ecf20Sopenharmony_ci struct dib0090_fw_state *state = fe->tuner_priv; 4228c2ecf20Sopenharmony_ci struct dib0090_identity *identity = &state->identity; 4238c2ecf20Sopenharmony_ci 4248c2ecf20Sopenharmony_ci u16 v = dib0090_fw_read_reg(state, 0x1a); 4258c2ecf20Sopenharmony_ci identity->p1g = 0; 4268c2ecf20Sopenharmony_ci identity->in_soc = 0; 4278c2ecf20Sopenharmony_ci 4288c2ecf20Sopenharmony_ci dprintk("FE: Tuner identification (Version = 0x%04x)\n", v); 4298c2ecf20Sopenharmony_ci 4308c2ecf20Sopenharmony_ci /* without PLL lock info */ 4318c2ecf20Sopenharmony_ci v &= ~KROSUS_PLL_LOCKED; 4328c2ecf20Sopenharmony_ci 4338c2ecf20Sopenharmony_ci identity->version = v & 0xff; 4348c2ecf20Sopenharmony_ci identity->product = (v >> 8) & 0xf; 4358c2ecf20Sopenharmony_ci 4368c2ecf20Sopenharmony_ci if (identity->product != KROSUS) 4378c2ecf20Sopenharmony_ci goto identification_error; 4388c2ecf20Sopenharmony_ci 4398c2ecf20Sopenharmony_ci if ((identity->version & 0x3) == SOC) { 4408c2ecf20Sopenharmony_ci identity->in_soc = 1; 4418c2ecf20Sopenharmony_ci switch (identity->version) { 4428c2ecf20Sopenharmony_ci case SOC_8090_P1G_11R1: 4438c2ecf20Sopenharmony_ci dprintk("SOC 8090 P1-G11R1 Has been detected\n"); 4448c2ecf20Sopenharmony_ci identity->p1g = 1; 4458c2ecf20Sopenharmony_ci break; 4468c2ecf20Sopenharmony_ci case SOC_8090_P1G_21R1: 4478c2ecf20Sopenharmony_ci dprintk("SOC 8090 P1-G21R1 Has been detected\n"); 4488c2ecf20Sopenharmony_ci identity->p1g = 1; 4498c2ecf20Sopenharmony_ci break; 4508c2ecf20Sopenharmony_ci case SOC_7090_P1G_11R1: 4518c2ecf20Sopenharmony_ci dprintk("SOC 7090 P1-G11R1 Has been detected\n"); 4528c2ecf20Sopenharmony_ci identity->p1g = 1; 4538c2ecf20Sopenharmony_ci break; 4548c2ecf20Sopenharmony_ci case SOC_7090_P1G_21R1: 4558c2ecf20Sopenharmony_ci dprintk("SOC 7090 P1-G21R1 Has been detected\n"); 4568c2ecf20Sopenharmony_ci identity->p1g = 1; 4578c2ecf20Sopenharmony_ci break; 4588c2ecf20Sopenharmony_ci default: 4598c2ecf20Sopenharmony_ci goto identification_error; 4608c2ecf20Sopenharmony_ci } 4618c2ecf20Sopenharmony_ci } else { 4628c2ecf20Sopenharmony_ci switch ((identity->version >> 5) & 0x7) { 4638c2ecf20Sopenharmony_ci case MP001: 4648c2ecf20Sopenharmony_ci dprintk("MP001 : 9090/8096\n"); 4658c2ecf20Sopenharmony_ci break; 4668c2ecf20Sopenharmony_ci case MP005: 4678c2ecf20Sopenharmony_ci dprintk("MP005 : Single Sband\n"); 4688c2ecf20Sopenharmony_ci break; 4698c2ecf20Sopenharmony_ci case MP008: 4708c2ecf20Sopenharmony_ci dprintk("MP008 : diversity VHF-UHF-LBAND\n"); 4718c2ecf20Sopenharmony_ci break; 4728c2ecf20Sopenharmony_ci case MP009: 4738c2ecf20Sopenharmony_ci dprintk("MP009 : diversity 29098 CBAND-UHF-LBAND-SBAND\n"); 4748c2ecf20Sopenharmony_ci break; 4758c2ecf20Sopenharmony_ci default: 4768c2ecf20Sopenharmony_ci goto identification_error; 4778c2ecf20Sopenharmony_ci } 4788c2ecf20Sopenharmony_ci 4798c2ecf20Sopenharmony_ci switch (identity->version & 0x1f) { 4808c2ecf20Sopenharmony_ci case P1G_21R2: 4818c2ecf20Sopenharmony_ci dprintk("P1G_21R2 detected\n"); 4828c2ecf20Sopenharmony_ci identity->p1g = 1; 4838c2ecf20Sopenharmony_ci break; 4848c2ecf20Sopenharmony_ci case P1G: 4858c2ecf20Sopenharmony_ci dprintk("P1G detected\n"); 4868c2ecf20Sopenharmony_ci identity->p1g = 1; 4878c2ecf20Sopenharmony_ci break; 4888c2ecf20Sopenharmony_ci case P1D_E_F: 4898c2ecf20Sopenharmony_ci dprintk("P1D/E/F detected\n"); 4908c2ecf20Sopenharmony_ci break; 4918c2ecf20Sopenharmony_ci case P1C: 4928c2ecf20Sopenharmony_ci dprintk("P1C detected\n"); 4938c2ecf20Sopenharmony_ci break; 4948c2ecf20Sopenharmony_ci case P1A_B: 4958c2ecf20Sopenharmony_ci dprintk("P1-A/B detected: driver is deactivated - not available\n"); 4968c2ecf20Sopenharmony_ci goto identification_error; 4978c2ecf20Sopenharmony_ci break; 4988c2ecf20Sopenharmony_ci default: 4998c2ecf20Sopenharmony_ci goto identification_error; 5008c2ecf20Sopenharmony_ci } 5018c2ecf20Sopenharmony_ci } 5028c2ecf20Sopenharmony_ci 5038c2ecf20Sopenharmony_ci return 0; 5048c2ecf20Sopenharmony_ci 5058c2ecf20Sopenharmony_ciidentification_error: 5068c2ecf20Sopenharmony_ci return -EIO; 5078c2ecf20Sopenharmony_ci} 5088c2ecf20Sopenharmony_ci 5098c2ecf20Sopenharmony_cistatic void dib0090_reset_digital(struct dvb_frontend *fe, const struct dib0090_config *cfg) 5108c2ecf20Sopenharmony_ci{ 5118c2ecf20Sopenharmony_ci struct dib0090_state *state = fe->tuner_priv; 5128c2ecf20Sopenharmony_ci u16 PllCfg, i, v; 5138c2ecf20Sopenharmony_ci 5148c2ecf20Sopenharmony_ci HARD_RESET(state); 5158c2ecf20Sopenharmony_ci dib0090_write_reg(state, 0x24, EN_PLL | EN_CRYSTAL); 5168c2ecf20Sopenharmony_ci if (cfg->in_soc) 5178c2ecf20Sopenharmony_ci return; 5188c2ecf20Sopenharmony_ci 5198c2ecf20Sopenharmony_ci dib0090_write_reg(state, 0x1b, EN_DIGCLK | EN_PLL | EN_CRYSTAL); /* PLL, DIG_CLK and CRYSTAL remain */ 5208c2ecf20Sopenharmony_ci /* adcClkOutRatio=8->7, release reset */ 5218c2ecf20Sopenharmony_ci dib0090_write_reg(state, 0x20, ((cfg->io.adc_clock_ratio - 1) << 11) | (0 << 10) | (1 << 9) | (1 << 8) | (0 << 4) | 0); 5228c2ecf20Sopenharmony_ci if (cfg->clkoutdrive != 0) 5238c2ecf20Sopenharmony_ci dib0090_write_reg(state, 0x23, (0 << 15) | ((!cfg->analog_output) << 14) | (2 << 10) | (1 << 9) | (0 << 8) 5248c2ecf20Sopenharmony_ci | (cfg->clkoutdrive << 5) | (cfg->clkouttobamse << 4) | (0 << 2) | (0)); 5258c2ecf20Sopenharmony_ci else 5268c2ecf20Sopenharmony_ci dib0090_write_reg(state, 0x23, (0 << 15) | ((!cfg->analog_output) << 14) | (2 << 10) | (1 << 9) | (0 << 8) 5278c2ecf20Sopenharmony_ci | (7 << 5) | (cfg->clkouttobamse << 4) | (0 << 2) | (0)); 5288c2ecf20Sopenharmony_ci 5298c2ecf20Sopenharmony_ci /* Read Pll current config * */ 5308c2ecf20Sopenharmony_ci PllCfg = dib0090_read_reg(state, 0x21); 5318c2ecf20Sopenharmony_ci 5328c2ecf20Sopenharmony_ci /** Reconfigure PLL if current setting is different from default setting **/ 5338c2ecf20Sopenharmony_ci if ((PllCfg & 0x1FFF) != ((cfg->io.pll_range << 12) | (cfg->io.pll_loopdiv << 6) | (cfg->io.pll_prediv)) && (!cfg->in_soc) 5348c2ecf20Sopenharmony_ci && !cfg->io.pll_bypass) { 5358c2ecf20Sopenharmony_ci 5368c2ecf20Sopenharmony_ci /* Set Bypass mode */ 5378c2ecf20Sopenharmony_ci PllCfg |= (1 << 15); 5388c2ecf20Sopenharmony_ci dib0090_write_reg(state, 0x21, PllCfg); 5398c2ecf20Sopenharmony_ci 5408c2ecf20Sopenharmony_ci /* Set Reset Pll */ 5418c2ecf20Sopenharmony_ci PllCfg &= ~(1 << 13); 5428c2ecf20Sopenharmony_ci dib0090_write_reg(state, 0x21, PllCfg); 5438c2ecf20Sopenharmony_ci 5448c2ecf20Sopenharmony_ci /*** Set new Pll configuration in bypass and reset state ***/ 5458c2ecf20Sopenharmony_ci PllCfg = (1 << 15) | (0 << 13) | (cfg->io.pll_range << 12) | (cfg->io.pll_loopdiv << 6) | (cfg->io.pll_prediv); 5468c2ecf20Sopenharmony_ci dib0090_write_reg(state, 0x21, PllCfg); 5478c2ecf20Sopenharmony_ci 5488c2ecf20Sopenharmony_ci /* Remove Reset Pll */ 5498c2ecf20Sopenharmony_ci PllCfg |= (1 << 13); 5508c2ecf20Sopenharmony_ci dib0090_write_reg(state, 0x21, PllCfg); 5518c2ecf20Sopenharmony_ci 5528c2ecf20Sopenharmony_ci /*** Wait for PLL lock ***/ 5538c2ecf20Sopenharmony_ci i = 100; 5548c2ecf20Sopenharmony_ci do { 5558c2ecf20Sopenharmony_ci v = !!(dib0090_read_reg(state, 0x1a) & 0x800); 5568c2ecf20Sopenharmony_ci if (v) 5578c2ecf20Sopenharmony_ci break; 5588c2ecf20Sopenharmony_ci } while (--i); 5598c2ecf20Sopenharmony_ci 5608c2ecf20Sopenharmony_ci if (i == 0) { 5618c2ecf20Sopenharmony_ci dprintk("Pll: Unable to lock Pll\n"); 5628c2ecf20Sopenharmony_ci return; 5638c2ecf20Sopenharmony_ci } 5648c2ecf20Sopenharmony_ci 5658c2ecf20Sopenharmony_ci /* Finally Remove Bypass mode */ 5668c2ecf20Sopenharmony_ci PllCfg &= ~(1 << 15); 5678c2ecf20Sopenharmony_ci dib0090_write_reg(state, 0x21, PllCfg); 5688c2ecf20Sopenharmony_ci } 5698c2ecf20Sopenharmony_ci 5708c2ecf20Sopenharmony_ci if (cfg->io.pll_bypass) { 5718c2ecf20Sopenharmony_ci PllCfg |= (cfg->io.pll_bypass << 15); 5728c2ecf20Sopenharmony_ci dib0090_write_reg(state, 0x21, PllCfg); 5738c2ecf20Sopenharmony_ci } 5748c2ecf20Sopenharmony_ci} 5758c2ecf20Sopenharmony_ci 5768c2ecf20Sopenharmony_cistatic int dib0090_fw_reset_digital(struct dvb_frontend *fe, const struct dib0090_config *cfg) 5778c2ecf20Sopenharmony_ci{ 5788c2ecf20Sopenharmony_ci struct dib0090_fw_state *state = fe->tuner_priv; 5798c2ecf20Sopenharmony_ci u16 PllCfg; 5808c2ecf20Sopenharmony_ci u16 v; 5818c2ecf20Sopenharmony_ci int i; 5828c2ecf20Sopenharmony_ci 5838c2ecf20Sopenharmony_ci dprintk("fw reset digital\n"); 5848c2ecf20Sopenharmony_ci HARD_RESET(state); 5858c2ecf20Sopenharmony_ci 5868c2ecf20Sopenharmony_ci dib0090_fw_write_reg(state, 0x24, EN_PLL | EN_CRYSTAL); 5878c2ecf20Sopenharmony_ci dib0090_fw_write_reg(state, 0x1b, EN_DIGCLK | EN_PLL | EN_CRYSTAL); /* PLL, DIG_CLK and CRYSTAL remain */ 5888c2ecf20Sopenharmony_ci 5898c2ecf20Sopenharmony_ci dib0090_fw_write_reg(state, 0x20, 5908c2ecf20Sopenharmony_ci ((cfg->io.adc_clock_ratio - 1) << 11) | (0 << 10) | (1 << 9) | (1 << 8) | (cfg->data_tx_drv << 4) | cfg->ls_cfg_pad_drv); 5918c2ecf20Sopenharmony_ci 5928c2ecf20Sopenharmony_ci v = (0 << 15) | ((!cfg->analog_output) << 14) | (1 << 9) | (0 << 8) | (cfg->clkouttobamse << 4) | (0 << 2) | (0); 5938c2ecf20Sopenharmony_ci if (cfg->clkoutdrive != 0) 5948c2ecf20Sopenharmony_ci v |= cfg->clkoutdrive << 5; 5958c2ecf20Sopenharmony_ci else 5968c2ecf20Sopenharmony_ci v |= 7 << 5; 5978c2ecf20Sopenharmony_ci 5988c2ecf20Sopenharmony_ci v |= 2 << 10; 5998c2ecf20Sopenharmony_ci dib0090_fw_write_reg(state, 0x23, v); 6008c2ecf20Sopenharmony_ci 6018c2ecf20Sopenharmony_ci /* Read Pll current config * */ 6028c2ecf20Sopenharmony_ci PllCfg = dib0090_fw_read_reg(state, 0x21); 6038c2ecf20Sopenharmony_ci 6048c2ecf20Sopenharmony_ci /** Reconfigure PLL if current setting is different from default setting **/ 6058c2ecf20Sopenharmony_ci if ((PllCfg & 0x1FFF) != ((cfg->io.pll_range << 12) | (cfg->io.pll_loopdiv << 6) | (cfg->io.pll_prediv)) && !cfg->io.pll_bypass) { 6068c2ecf20Sopenharmony_ci 6078c2ecf20Sopenharmony_ci /* Set Bypass mode */ 6088c2ecf20Sopenharmony_ci PllCfg |= (1 << 15); 6098c2ecf20Sopenharmony_ci dib0090_fw_write_reg(state, 0x21, PllCfg); 6108c2ecf20Sopenharmony_ci 6118c2ecf20Sopenharmony_ci /* Set Reset Pll */ 6128c2ecf20Sopenharmony_ci PllCfg &= ~(1 << 13); 6138c2ecf20Sopenharmony_ci dib0090_fw_write_reg(state, 0x21, PllCfg); 6148c2ecf20Sopenharmony_ci 6158c2ecf20Sopenharmony_ci /*** Set new Pll configuration in bypass and reset state ***/ 6168c2ecf20Sopenharmony_ci PllCfg = (1 << 15) | (0 << 13) | (cfg->io.pll_range << 12) | (cfg->io.pll_loopdiv << 6) | (cfg->io.pll_prediv); 6178c2ecf20Sopenharmony_ci dib0090_fw_write_reg(state, 0x21, PllCfg); 6188c2ecf20Sopenharmony_ci 6198c2ecf20Sopenharmony_ci /* Remove Reset Pll */ 6208c2ecf20Sopenharmony_ci PllCfg |= (1 << 13); 6218c2ecf20Sopenharmony_ci dib0090_fw_write_reg(state, 0x21, PllCfg); 6228c2ecf20Sopenharmony_ci 6238c2ecf20Sopenharmony_ci /*** Wait for PLL lock ***/ 6248c2ecf20Sopenharmony_ci i = 100; 6258c2ecf20Sopenharmony_ci do { 6268c2ecf20Sopenharmony_ci v = !!(dib0090_fw_read_reg(state, 0x1a) & 0x800); 6278c2ecf20Sopenharmony_ci if (v) 6288c2ecf20Sopenharmony_ci break; 6298c2ecf20Sopenharmony_ci } while (--i); 6308c2ecf20Sopenharmony_ci 6318c2ecf20Sopenharmony_ci if (i == 0) { 6328c2ecf20Sopenharmony_ci dprintk("Pll: Unable to lock Pll\n"); 6338c2ecf20Sopenharmony_ci return -EIO; 6348c2ecf20Sopenharmony_ci } 6358c2ecf20Sopenharmony_ci 6368c2ecf20Sopenharmony_ci /* Finally Remove Bypass mode */ 6378c2ecf20Sopenharmony_ci PllCfg &= ~(1 << 15); 6388c2ecf20Sopenharmony_ci dib0090_fw_write_reg(state, 0x21, PllCfg); 6398c2ecf20Sopenharmony_ci } 6408c2ecf20Sopenharmony_ci 6418c2ecf20Sopenharmony_ci if (cfg->io.pll_bypass) { 6428c2ecf20Sopenharmony_ci PllCfg |= (cfg->io.pll_bypass << 15); 6438c2ecf20Sopenharmony_ci dib0090_fw_write_reg(state, 0x21, PllCfg); 6448c2ecf20Sopenharmony_ci } 6458c2ecf20Sopenharmony_ci 6468c2ecf20Sopenharmony_ci return dib0090_fw_identify(fe); 6478c2ecf20Sopenharmony_ci} 6488c2ecf20Sopenharmony_ci 6498c2ecf20Sopenharmony_cistatic int dib0090_wakeup(struct dvb_frontend *fe) 6508c2ecf20Sopenharmony_ci{ 6518c2ecf20Sopenharmony_ci struct dib0090_state *state = fe->tuner_priv; 6528c2ecf20Sopenharmony_ci if (state->config->sleep) 6538c2ecf20Sopenharmony_ci state->config->sleep(fe, 0); 6548c2ecf20Sopenharmony_ci 6558c2ecf20Sopenharmony_ci /* enable dataTX in case we have been restarted in the wrong moment */ 6568c2ecf20Sopenharmony_ci dib0090_write_reg(state, 0x23, dib0090_read_reg(state, 0x23) | (1 << 14)); 6578c2ecf20Sopenharmony_ci return 0; 6588c2ecf20Sopenharmony_ci} 6598c2ecf20Sopenharmony_ci 6608c2ecf20Sopenharmony_cistatic int dib0090_sleep(struct dvb_frontend *fe) 6618c2ecf20Sopenharmony_ci{ 6628c2ecf20Sopenharmony_ci struct dib0090_state *state = fe->tuner_priv; 6638c2ecf20Sopenharmony_ci if (state->config->sleep) 6648c2ecf20Sopenharmony_ci state->config->sleep(fe, 1); 6658c2ecf20Sopenharmony_ci return 0; 6668c2ecf20Sopenharmony_ci} 6678c2ecf20Sopenharmony_ci 6688c2ecf20Sopenharmony_civoid dib0090_dcc_freq(struct dvb_frontend *fe, u8 fast) 6698c2ecf20Sopenharmony_ci{ 6708c2ecf20Sopenharmony_ci struct dib0090_state *state = fe->tuner_priv; 6718c2ecf20Sopenharmony_ci if (fast) 6728c2ecf20Sopenharmony_ci dib0090_write_reg(state, 0x04, 0); 6738c2ecf20Sopenharmony_ci else 6748c2ecf20Sopenharmony_ci dib0090_write_reg(state, 0x04, 1); 6758c2ecf20Sopenharmony_ci} 6768c2ecf20Sopenharmony_ci 6778c2ecf20Sopenharmony_ciEXPORT_SYMBOL(dib0090_dcc_freq); 6788c2ecf20Sopenharmony_ci 6798c2ecf20Sopenharmony_cistatic const u16 bb_ramp_pwm_normal_socs[] = { 6808c2ecf20Sopenharmony_ci 550, /* max BB gain in 10th of dB */ 6818c2ecf20Sopenharmony_ci (1<<9) | 8, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> BB_RAMP2 */ 6828c2ecf20Sopenharmony_ci 440, 6838c2ecf20Sopenharmony_ci (4 << 9) | 0, /* BB_RAMP3 = 26dB */ 6848c2ecf20Sopenharmony_ci (0 << 9) | 208, /* BB_RAMP4 */ 6858c2ecf20Sopenharmony_ci (4 << 9) | 208, /* BB_RAMP5 = 29dB */ 6868c2ecf20Sopenharmony_ci (0 << 9) | 440, /* BB_RAMP6 */ 6878c2ecf20Sopenharmony_ci}; 6888c2ecf20Sopenharmony_ci 6898c2ecf20Sopenharmony_cistatic const u16 rf_ramp_pwm_cband_7090p[] = { 6908c2ecf20Sopenharmony_ci 280, /* max RF gain in 10th of dB */ 6918c2ecf20Sopenharmony_ci 18, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */ 6928c2ecf20Sopenharmony_ci 504, /* ramp_max = maximum X used on the ramp */ 6938c2ecf20Sopenharmony_ci (29 << 10) | 364, /* RF_RAMP5, LNA 1 = 8dB */ 6948c2ecf20Sopenharmony_ci (0 << 10) | 504, /* RF_RAMP6, LNA 1 */ 6958c2ecf20Sopenharmony_ci (60 << 10) | 228, /* RF_RAMP7, LNA 2 = 7.7dB */ 6968c2ecf20Sopenharmony_ci (0 << 10) | 364, /* RF_RAMP8, LNA 2 */ 6978c2ecf20Sopenharmony_ci (34 << 10) | 109, /* GAIN_4_1, LNA 3 = 6.8dB */ 6988c2ecf20Sopenharmony_ci (0 << 10) | 228, /* GAIN_4_2, LNA 3 */ 6998c2ecf20Sopenharmony_ci (37 << 10) | 0, /* RF_RAMP3, LNA 4 = 6.2dB */ 7008c2ecf20Sopenharmony_ci (0 << 10) | 109, /* RF_RAMP4, LNA 4 */ 7018c2ecf20Sopenharmony_ci}; 7028c2ecf20Sopenharmony_ci 7038c2ecf20Sopenharmony_cistatic const u16 rf_ramp_pwm_cband_7090e_sensitivity[] = { 7048c2ecf20Sopenharmony_ci 186, /* max RF gain in 10th of dB */ 7058c2ecf20Sopenharmony_ci 40, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */ 7068c2ecf20Sopenharmony_ci 746, /* ramp_max = maximum X used on the ramp */ 7078c2ecf20Sopenharmony_ci (10 << 10) | 345, /* RF_RAMP5, LNA 1 = 10dB */ 7088c2ecf20Sopenharmony_ci (0 << 10) | 746, /* RF_RAMP6, LNA 1 */ 7098c2ecf20Sopenharmony_ci (0 << 10) | 0, /* RF_RAMP7, LNA 2 = 0 dB */ 7108c2ecf20Sopenharmony_ci (0 << 10) | 0, /* RF_RAMP8, LNA 2 */ 7118c2ecf20Sopenharmony_ci (28 << 10) | 200, /* GAIN_4_1, LNA 3 = 6.8dB */ /* 3.61 dB */ 7128c2ecf20Sopenharmony_ci (0 << 10) | 345, /* GAIN_4_2, LNA 3 */ 7138c2ecf20Sopenharmony_ci (20 << 10) | 0, /* RF_RAMP3, LNA 4 = 6.2dB */ /* 4.96 dB */ 7148c2ecf20Sopenharmony_ci (0 << 10) | 200, /* RF_RAMP4, LNA 4 */ 7158c2ecf20Sopenharmony_ci}; 7168c2ecf20Sopenharmony_ci 7178c2ecf20Sopenharmony_cistatic const u16 rf_ramp_pwm_cband_7090e_aci[] = { 7188c2ecf20Sopenharmony_ci 86, /* max RF gain in 10th of dB */ 7198c2ecf20Sopenharmony_ci 40, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */ 7208c2ecf20Sopenharmony_ci 345, /* ramp_max = maximum X used on the ramp */ 7218c2ecf20Sopenharmony_ci (0 << 10) | 0, /* RF_RAMP5, LNA 1 = 8dB */ /* 7.47 dB */ 7228c2ecf20Sopenharmony_ci (0 << 10) | 0, /* RF_RAMP6, LNA 1 */ 7238c2ecf20Sopenharmony_ci (0 << 10) | 0, /* RF_RAMP7, LNA 2 = 0 dB */ 7248c2ecf20Sopenharmony_ci (0 << 10) | 0, /* RF_RAMP8, LNA 2 */ 7258c2ecf20Sopenharmony_ci (28 << 10) | 200, /* GAIN_4_1, LNA 3 = 6.8dB */ /* 3.61 dB */ 7268c2ecf20Sopenharmony_ci (0 << 10) | 345, /* GAIN_4_2, LNA 3 */ 7278c2ecf20Sopenharmony_ci (20 << 10) | 0, /* RF_RAMP3, LNA 4 = 6.2dB */ /* 4.96 dB */ 7288c2ecf20Sopenharmony_ci (0 << 10) | 200, /* RF_RAMP4, LNA 4 */ 7298c2ecf20Sopenharmony_ci}; 7308c2ecf20Sopenharmony_ci 7318c2ecf20Sopenharmony_cistatic const u16 rf_ramp_pwm_cband_8090[] = { 7328c2ecf20Sopenharmony_ci 345, /* max RF gain in 10th of dB */ 7338c2ecf20Sopenharmony_ci 29, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */ 7348c2ecf20Sopenharmony_ci 1000, /* ramp_max = maximum X used on the ramp */ 7358c2ecf20Sopenharmony_ci (35 << 10) | 772, /* RF_RAMP3, LNA 1 = 8dB */ 7368c2ecf20Sopenharmony_ci (0 << 10) | 1000, /* RF_RAMP4, LNA 1 */ 7378c2ecf20Sopenharmony_ci (58 << 10) | 496, /* RF_RAMP5, LNA 2 = 9.5dB */ 7388c2ecf20Sopenharmony_ci (0 << 10) | 772, /* RF_RAMP6, LNA 2 */ 7398c2ecf20Sopenharmony_ci (27 << 10) | 200, /* RF_RAMP7, LNA 3 = 10.5dB */ 7408c2ecf20Sopenharmony_ci (0 << 10) | 496, /* RF_RAMP8, LNA 3 */ 7418c2ecf20Sopenharmony_ci (40 << 10) | 0, /* GAIN_4_1, LNA 4 = 7dB */ 7428c2ecf20Sopenharmony_ci (0 << 10) | 200, /* GAIN_4_2, LNA 4 */ 7438c2ecf20Sopenharmony_ci}; 7448c2ecf20Sopenharmony_ci 7458c2ecf20Sopenharmony_cistatic const u16 rf_ramp_pwm_uhf_7090[] = { 7468c2ecf20Sopenharmony_ci 407, /* max RF gain in 10th of dB */ 7478c2ecf20Sopenharmony_ci 13, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */ 7488c2ecf20Sopenharmony_ci 529, /* ramp_max = maximum X used on the ramp */ 7498c2ecf20Sopenharmony_ci (23 << 10) | 0, /* RF_RAMP3, LNA 1 = 14.7dB */ 7508c2ecf20Sopenharmony_ci (0 << 10) | 176, /* RF_RAMP4, LNA 1 */ 7518c2ecf20Sopenharmony_ci (63 << 10) | 400, /* RF_RAMP5, LNA 2 = 8dB */ 7528c2ecf20Sopenharmony_ci (0 << 10) | 529, /* RF_RAMP6, LNA 2 */ 7538c2ecf20Sopenharmony_ci (48 << 10) | 316, /* RF_RAMP7, LNA 3 = 6.8dB */ 7548c2ecf20Sopenharmony_ci (0 << 10) | 400, /* RF_RAMP8, LNA 3 */ 7558c2ecf20Sopenharmony_ci (29 << 10) | 176, /* GAIN_4_1, LNA 4 = 11.5dB */ 7568c2ecf20Sopenharmony_ci (0 << 10) | 316, /* GAIN_4_2, LNA 4 */ 7578c2ecf20Sopenharmony_ci}; 7588c2ecf20Sopenharmony_ci 7598c2ecf20Sopenharmony_cistatic const u16 rf_ramp_pwm_uhf_8090[] = { 7608c2ecf20Sopenharmony_ci 388, /* max RF gain in 10th of dB */ 7618c2ecf20Sopenharmony_ci 26, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */ 7628c2ecf20Sopenharmony_ci 1008, /* ramp_max = maximum X used on the ramp */ 7638c2ecf20Sopenharmony_ci (11 << 10) | 0, /* RF_RAMP3, LNA 1 = 14.7dB */ 7648c2ecf20Sopenharmony_ci (0 << 10) | 369, /* RF_RAMP4, LNA 1 */ 7658c2ecf20Sopenharmony_ci (41 << 10) | 809, /* RF_RAMP5, LNA 2 = 8dB */ 7668c2ecf20Sopenharmony_ci (0 << 10) | 1008, /* RF_RAMP6, LNA 2 */ 7678c2ecf20Sopenharmony_ci (27 << 10) | 659, /* RF_RAMP7, LNA 3 = 6dB */ 7688c2ecf20Sopenharmony_ci (0 << 10) | 809, /* RF_RAMP8, LNA 3 */ 7698c2ecf20Sopenharmony_ci (14 << 10) | 369, /* GAIN_4_1, LNA 4 = 11.5dB */ 7708c2ecf20Sopenharmony_ci (0 << 10) | 659, /* GAIN_4_2, LNA 4 */ 7718c2ecf20Sopenharmony_ci}; 7728c2ecf20Sopenharmony_ci 7738c2ecf20Sopenharmony_ci/* GENERAL PWM ramp definition for all other Krosus */ 7748c2ecf20Sopenharmony_cistatic const u16 bb_ramp_pwm_normal[] = { 7758c2ecf20Sopenharmony_ci 500, /* max BB gain in 10th of dB */ 7768c2ecf20Sopenharmony_ci 8, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> BB_RAMP2 */ 7778c2ecf20Sopenharmony_ci 400, 7788c2ecf20Sopenharmony_ci (2 << 9) | 0, /* BB_RAMP3 = 21dB */ 7798c2ecf20Sopenharmony_ci (0 << 9) | 168, /* BB_RAMP4 */ 7808c2ecf20Sopenharmony_ci (2 << 9) | 168, /* BB_RAMP5 = 29dB */ 7818c2ecf20Sopenharmony_ci (0 << 9) | 400, /* BB_RAMP6 */ 7828c2ecf20Sopenharmony_ci}; 7838c2ecf20Sopenharmony_ci 7848c2ecf20Sopenharmony_ci#if 0 7858c2ecf20Sopenharmony_ci/* Currently unused */ 7868c2ecf20Sopenharmony_cistatic const u16 bb_ramp_pwm_boost[] = { 7878c2ecf20Sopenharmony_ci 550, /* max BB gain in 10th of dB */ 7888c2ecf20Sopenharmony_ci 8, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> BB_RAMP2 */ 7898c2ecf20Sopenharmony_ci 440, 7908c2ecf20Sopenharmony_ci (2 << 9) | 0, /* BB_RAMP3 = 26dB */ 7918c2ecf20Sopenharmony_ci (0 << 9) | 208, /* BB_RAMP4 */ 7928c2ecf20Sopenharmony_ci (2 << 9) | 208, /* BB_RAMP5 = 29dB */ 7938c2ecf20Sopenharmony_ci (0 << 9) | 440, /* BB_RAMP6 */ 7948c2ecf20Sopenharmony_ci}; 7958c2ecf20Sopenharmony_ci#endif 7968c2ecf20Sopenharmony_ci 7978c2ecf20Sopenharmony_cistatic const u16 rf_ramp_pwm_cband[] = { 7988c2ecf20Sopenharmony_ci 314, /* max RF gain in 10th of dB */ 7998c2ecf20Sopenharmony_ci 33, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */ 8008c2ecf20Sopenharmony_ci 1023, /* ramp_max = maximum X used on the ramp */ 8018c2ecf20Sopenharmony_ci (8 << 10) | 743, /* RF_RAMP3, LNA 1 = 0dB */ 8028c2ecf20Sopenharmony_ci (0 << 10) | 1023, /* RF_RAMP4, LNA 1 */ 8038c2ecf20Sopenharmony_ci (15 << 10) | 469, /* RF_RAMP5, LNA 2 = 0dB */ 8048c2ecf20Sopenharmony_ci (0 << 10) | 742, /* RF_RAMP6, LNA 2 */ 8058c2ecf20Sopenharmony_ci (9 << 10) | 234, /* RF_RAMP7, LNA 3 = 0dB */ 8068c2ecf20Sopenharmony_ci (0 << 10) | 468, /* RF_RAMP8, LNA 3 */ 8078c2ecf20Sopenharmony_ci (9 << 10) | 0, /* GAIN_4_1, LNA 4 = 0dB */ 8088c2ecf20Sopenharmony_ci (0 << 10) | 233, /* GAIN_4_2, LNA 4 */ 8098c2ecf20Sopenharmony_ci}; 8108c2ecf20Sopenharmony_ci 8118c2ecf20Sopenharmony_cistatic const u16 rf_ramp_pwm_vhf[] = { 8128c2ecf20Sopenharmony_ci 398, /* max RF gain in 10th of dB */ 8138c2ecf20Sopenharmony_ci 24, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */ 8148c2ecf20Sopenharmony_ci 954, /* ramp_max = maximum X used on the ramp */ 8158c2ecf20Sopenharmony_ci (7 << 10) | 0, /* RF_RAMP3, LNA 1 = 13.2dB */ 8168c2ecf20Sopenharmony_ci (0 << 10) | 290, /* RF_RAMP4, LNA 1 */ 8178c2ecf20Sopenharmony_ci (16 << 10) | 699, /* RF_RAMP5, LNA 2 = 10.5dB */ 8188c2ecf20Sopenharmony_ci (0 << 10) | 954, /* RF_RAMP6, LNA 2 */ 8198c2ecf20Sopenharmony_ci (17 << 10) | 580, /* RF_RAMP7, LNA 3 = 5dB */ 8208c2ecf20Sopenharmony_ci (0 << 10) | 699, /* RF_RAMP8, LNA 3 */ 8218c2ecf20Sopenharmony_ci (7 << 10) | 290, /* GAIN_4_1, LNA 4 = 12.5dB */ 8228c2ecf20Sopenharmony_ci (0 << 10) | 580, /* GAIN_4_2, LNA 4 */ 8238c2ecf20Sopenharmony_ci}; 8248c2ecf20Sopenharmony_ci 8258c2ecf20Sopenharmony_cistatic const u16 rf_ramp_pwm_uhf[] = { 8268c2ecf20Sopenharmony_ci 398, /* max RF gain in 10th of dB */ 8278c2ecf20Sopenharmony_ci 24, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */ 8288c2ecf20Sopenharmony_ci 954, /* ramp_max = maximum X used on the ramp */ 8298c2ecf20Sopenharmony_ci (7 << 10) | 0, /* RF_RAMP3, LNA 1 = 13.2dB */ 8308c2ecf20Sopenharmony_ci (0 << 10) | 290, /* RF_RAMP4, LNA 1 */ 8318c2ecf20Sopenharmony_ci (16 << 10) | 699, /* RF_RAMP5, LNA 2 = 10.5dB */ 8328c2ecf20Sopenharmony_ci (0 << 10) | 954, /* RF_RAMP6, LNA 2 */ 8338c2ecf20Sopenharmony_ci (17 << 10) | 580, /* RF_RAMP7, LNA 3 = 5dB */ 8348c2ecf20Sopenharmony_ci (0 << 10) | 699, /* RF_RAMP8, LNA 3 */ 8358c2ecf20Sopenharmony_ci (7 << 10) | 290, /* GAIN_4_1, LNA 4 = 12.5dB */ 8368c2ecf20Sopenharmony_ci (0 << 10) | 580, /* GAIN_4_2, LNA 4 */ 8378c2ecf20Sopenharmony_ci}; 8388c2ecf20Sopenharmony_ci 8398c2ecf20Sopenharmony_ci#if 0 8408c2ecf20Sopenharmony_ci/* Currently unused */ 8418c2ecf20Sopenharmony_cistatic const u16 rf_ramp_pwm_sband[] = { 8428c2ecf20Sopenharmony_ci 253, /* max RF gain in 10th of dB */ 8438c2ecf20Sopenharmony_ci 38, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */ 8448c2ecf20Sopenharmony_ci 961, 8458c2ecf20Sopenharmony_ci (4 << 10) | 0, /* RF_RAMP3, LNA 1 = 14.1dB */ 8468c2ecf20Sopenharmony_ci (0 << 10) | 508, /* RF_RAMP4, LNA 1 */ 8478c2ecf20Sopenharmony_ci (9 << 10) | 508, /* RF_RAMP5, LNA 2 = 11.2dB */ 8488c2ecf20Sopenharmony_ci (0 << 10) | 961, /* RF_RAMP6, LNA 2 */ 8498c2ecf20Sopenharmony_ci (0 << 10) | 0, /* RF_RAMP7, LNA 3 = 0dB */ 8508c2ecf20Sopenharmony_ci (0 << 10) | 0, /* RF_RAMP8, LNA 3 */ 8518c2ecf20Sopenharmony_ci (0 << 10) | 0, /* GAIN_4_1, LNA 4 = 0dB */ 8528c2ecf20Sopenharmony_ci (0 << 10) | 0, /* GAIN_4_2, LNA 4 */ 8538c2ecf20Sopenharmony_ci}; 8548c2ecf20Sopenharmony_ci#endif 8558c2ecf20Sopenharmony_ci 8568c2ecf20Sopenharmony_cistruct slope { 8578c2ecf20Sopenharmony_ci s16 range; 8588c2ecf20Sopenharmony_ci s16 slope; 8598c2ecf20Sopenharmony_ci}; 8608c2ecf20Sopenharmony_cistatic u16 slopes_to_scale(const struct slope *slopes, u8 num, s16 val) 8618c2ecf20Sopenharmony_ci{ 8628c2ecf20Sopenharmony_ci u8 i; 8638c2ecf20Sopenharmony_ci u16 rest; 8648c2ecf20Sopenharmony_ci u16 ret = 0; 8658c2ecf20Sopenharmony_ci for (i = 0; i < num; i++) { 8668c2ecf20Sopenharmony_ci if (val > slopes[i].range) 8678c2ecf20Sopenharmony_ci rest = slopes[i].range; 8688c2ecf20Sopenharmony_ci else 8698c2ecf20Sopenharmony_ci rest = val; 8708c2ecf20Sopenharmony_ci ret += (rest * slopes[i].slope) / slopes[i].range; 8718c2ecf20Sopenharmony_ci val -= rest; 8728c2ecf20Sopenharmony_ci } 8738c2ecf20Sopenharmony_ci return ret; 8748c2ecf20Sopenharmony_ci} 8758c2ecf20Sopenharmony_ci 8768c2ecf20Sopenharmony_cistatic const struct slope dib0090_wbd_slopes[3] = { 8778c2ecf20Sopenharmony_ci {66, 120}, /* -64,-52: offset - 65 */ 8788c2ecf20Sopenharmony_ci {600, 170}, /* -52,-35: 65 - 665 */ 8798c2ecf20Sopenharmony_ci {170, 250}, /* -45,-10: 665 - 835 */ 8808c2ecf20Sopenharmony_ci}; 8818c2ecf20Sopenharmony_ci 8828c2ecf20Sopenharmony_cistatic s16 dib0090_wbd_to_db(struct dib0090_state *state, u16 wbd) 8838c2ecf20Sopenharmony_ci{ 8848c2ecf20Sopenharmony_ci wbd &= 0x3ff; 8858c2ecf20Sopenharmony_ci if (wbd < state->wbd_offset) 8868c2ecf20Sopenharmony_ci wbd = 0; 8878c2ecf20Sopenharmony_ci else 8888c2ecf20Sopenharmony_ci wbd -= state->wbd_offset; 8898c2ecf20Sopenharmony_ci /* -64dB is the floor */ 8908c2ecf20Sopenharmony_ci return -640 + (s16) slopes_to_scale(dib0090_wbd_slopes, ARRAY_SIZE(dib0090_wbd_slopes), wbd); 8918c2ecf20Sopenharmony_ci} 8928c2ecf20Sopenharmony_ci 8938c2ecf20Sopenharmony_cistatic void dib0090_wbd_target(struct dib0090_state *state, u32 rf) 8948c2ecf20Sopenharmony_ci{ 8958c2ecf20Sopenharmony_ci u16 offset = 250; 8968c2ecf20Sopenharmony_ci 8978c2ecf20Sopenharmony_ci /* TODO : DAB digital N+/-1 interferer perfs : offset = 10 */ 8988c2ecf20Sopenharmony_ci 8998c2ecf20Sopenharmony_ci if (state->current_band == BAND_VHF) 9008c2ecf20Sopenharmony_ci offset = 650; 9018c2ecf20Sopenharmony_ci#ifndef FIRMWARE_FIREFLY 9028c2ecf20Sopenharmony_ci if (state->current_band == BAND_VHF) 9038c2ecf20Sopenharmony_ci offset = state->config->wbd_vhf_offset; 9048c2ecf20Sopenharmony_ci if (state->current_band == BAND_CBAND) 9058c2ecf20Sopenharmony_ci offset = state->config->wbd_cband_offset; 9068c2ecf20Sopenharmony_ci#endif 9078c2ecf20Sopenharmony_ci 9088c2ecf20Sopenharmony_ci state->wbd_target = dib0090_wbd_to_db(state, state->wbd_offset + offset); 9098c2ecf20Sopenharmony_ci dprintk("wbd-target: %d dB\n", (u32) state->wbd_target); 9108c2ecf20Sopenharmony_ci} 9118c2ecf20Sopenharmony_ci 9128c2ecf20Sopenharmony_cistatic const int gain_reg_addr[4] = { 9138c2ecf20Sopenharmony_ci 0x08, 0x0a, 0x0f, 0x01 9148c2ecf20Sopenharmony_ci}; 9158c2ecf20Sopenharmony_ci 9168c2ecf20Sopenharmony_cistatic void dib0090_gain_apply(struct dib0090_state *state, s16 gain_delta, s16 top_delta, u8 force) 9178c2ecf20Sopenharmony_ci{ 9188c2ecf20Sopenharmony_ci u16 rf, bb, ref; 9198c2ecf20Sopenharmony_ci u16 i, v, gain_reg[4] = { 0 }, gain; 9208c2ecf20Sopenharmony_ci const u16 *g; 9218c2ecf20Sopenharmony_ci 9228c2ecf20Sopenharmony_ci if (top_delta < -511) 9238c2ecf20Sopenharmony_ci top_delta = -511; 9248c2ecf20Sopenharmony_ci if (top_delta > 511) 9258c2ecf20Sopenharmony_ci top_delta = 511; 9268c2ecf20Sopenharmony_ci 9278c2ecf20Sopenharmony_ci if (force) { 9288c2ecf20Sopenharmony_ci top_delta *= (1 << WBD_ALPHA); 9298c2ecf20Sopenharmony_ci gain_delta *= (1 << GAIN_ALPHA); 9308c2ecf20Sopenharmony_ci } 9318c2ecf20Sopenharmony_ci 9328c2ecf20Sopenharmony_ci if (top_delta >= ((s16) (state->rf_ramp[0] << WBD_ALPHA) - state->rf_gain_limit)) /* overflow */ 9338c2ecf20Sopenharmony_ci state->rf_gain_limit = state->rf_ramp[0] << WBD_ALPHA; 9348c2ecf20Sopenharmony_ci else 9358c2ecf20Sopenharmony_ci state->rf_gain_limit += top_delta; 9368c2ecf20Sopenharmony_ci 9378c2ecf20Sopenharmony_ci if (state->rf_gain_limit < 0) /*underflow */ 9388c2ecf20Sopenharmony_ci state->rf_gain_limit = 0; 9398c2ecf20Sopenharmony_ci 9408c2ecf20Sopenharmony_ci /* use gain as a temporary variable and correct current_gain */ 9418c2ecf20Sopenharmony_ci gain = ((state->rf_gain_limit >> WBD_ALPHA) + state->bb_ramp[0]) << GAIN_ALPHA; 9428c2ecf20Sopenharmony_ci if (gain_delta >= ((s16) gain - state->current_gain)) /* overflow */ 9438c2ecf20Sopenharmony_ci state->current_gain = gain; 9448c2ecf20Sopenharmony_ci else 9458c2ecf20Sopenharmony_ci state->current_gain += gain_delta; 9468c2ecf20Sopenharmony_ci /* cannot be less than 0 (only if gain_delta is less than 0 we can have current_gain < 0) */ 9478c2ecf20Sopenharmony_ci if (state->current_gain < 0) 9488c2ecf20Sopenharmony_ci state->current_gain = 0; 9498c2ecf20Sopenharmony_ci 9508c2ecf20Sopenharmony_ci /* now split total gain to rf and bb gain */ 9518c2ecf20Sopenharmony_ci gain = state->current_gain >> GAIN_ALPHA; 9528c2ecf20Sopenharmony_ci 9538c2ecf20Sopenharmony_ci /* requested gain is bigger than rf gain limit - ACI/WBD adjustment */ 9548c2ecf20Sopenharmony_ci if (gain > (state->rf_gain_limit >> WBD_ALPHA)) { 9558c2ecf20Sopenharmony_ci rf = state->rf_gain_limit >> WBD_ALPHA; 9568c2ecf20Sopenharmony_ci bb = gain - rf; 9578c2ecf20Sopenharmony_ci if (bb > state->bb_ramp[0]) 9588c2ecf20Sopenharmony_ci bb = state->bb_ramp[0]; 9598c2ecf20Sopenharmony_ci } else { /* high signal level -> all gains put on RF */ 9608c2ecf20Sopenharmony_ci rf = gain; 9618c2ecf20Sopenharmony_ci bb = 0; 9628c2ecf20Sopenharmony_ci } 9638c2ecf20Sopenharmony_ci 9648c2ecf20Sopenharmony_ci state->gain[0] = rf; 9658c2ecf20Sopenharmony_ci state->gain[1] = bb; 9668c2ecf20Sopenharmony_ci 9678c2ecf20Sopenharmony_ci /* software ramp */ 9688c2ecf20Sopenharmony_ci /* Start with RF gains */ 9698c2ecf20Sopenharmony_ci g = state->rf_ramp + 1; /* point on RF LNA1 max gain */ 9708c2ecf20Sopenharmony_ci ref = rf; 9718c2ecf20Sopenharmony_ci for (i = 0; i < 7; i++) { /* Go over all amplifiers => 5RF amps + 2 BB amps = 7 amps */ 9728c2ecf20Sopenharmony_ci if (g[0] == 0 || ref < (g[1] - g[0])) /* if total gain of the current amp is null or this amp is not concerned because it starts to work from an higher gain value */ 9738c2ecf20Sopenharmony_ci v = 0; /* force the gain to write for the current amp to be null */ 9748c2ecf20Sopenharmony_ci else if (ref >= g[1]) /* Gain to set is higher than the high working point of this amp */ 9758c2ecf20Sopenharmony_ci v = g[2]; /* force this amp to be full gain */ 9768c2ecf20Sopenharmony_ci else /* compute the value to set to this amp because we are somewhere in his range */ 9778c2ecf20Sopenharmony_ci v = ((ref - (g[1] - g[0])) * g[2]) / g[0]; 9788c2ecf20Sopenharmony_ci 9798c2ecf20Sopenharmony_ci if (i == 0) /* LNA 1 reg mapping */ 9808c2ecf20Sopenharmony_ci gain_reg[0] = v; 9818c2ecf20Sopenharmony_ci else if (i == 1) /* LNA 2 reg mapping */ 9828c2ecf20Sopenharmony_ci gain_reg[0] |= v << 7; 9838c2ecf20Sopenharmony_ci else if (i == 2) /* LNA 3 reg mapping */ 9848c2ecf20Sopenharmony_ci gain_reg[1] = v; 9858c2ecf20Sopenharmony_ci else if (i == 3) /* LNA 4 reg mapping */ 9868c2ecf20Sopenharmony_ci gain_reg[1] |= v << 7; 9878c2ecf20Sopenharmony_ci else if (i == 4) /* CBAND LNA reg mapping */ 9888c2ecf20Sopenharmony_ci gain_reg[2] = v | state->rf_lt_def; 9898c2ecf20Sopenharmony_ci else if (i == 5) /* BB gain 1 reg mapping */ 9908c2ecf20Sopenharmony_ci gain_reg[3] = v << 3; 9918c2ecf20Sopenharmony_ci else if (i == 6) /* BB gain 2 reg mapping */ 9928c2ecf20Sopenharmony_ci gain_reg[3] |= v << 8; 9938c2ecf20Sopenharmony_ci 9948c2ecf20Sopenharmony_ci g += 3; /* go to next gain bloc */ 9958c2ecf20Sopenharmony_ci 9968c2ecf20Sopenharmony_ci /* When RF is finished, start with BB */ 9978c2ecf20Sopenharmony_ci if (i == 4) { 9988c2ecf20Sopenharmony_ci g = state->bb_ramp + 1; /* point on BB gain 1 max gain */ 9998c2ecf20Sopenharmony_ci ref = bb; 10008c2ecf20Sopenharmony_ci } 10018c2ecf20Sopenharmony_ci } 10028c2ecf20Sopenharmony_ci gain_reg[3] |= state->bb_1_def; 10038c2ecf20Sopenharmony_ci gain_reg[3] |= ((bb % 10) * 100) / 125; 10048c2ecf20Sopenharmony_ci 10058c2ecf20Sopenharmony_ci#ifdef DEBUG_AGC 10068c2ecf20Sopenharmony_ci dprintk("GA CALC: DB: %3d(rf) + %3d(bb) = %3d gain_reg[0]=%04x gain_reg[1]=%04x gain_reg[2]=%04x gain_reg[0]=%04x\n", rf, bb, rf + bb, 10078c2ecf20Sopenharmony_ci gain_reg[0], gain_reg[1], gain_reg[2], gain_reg[3]); 10088c2ecf20Sopenharmony_ci#endif 10098c2ecf20Sopenharmony_ci 10108c2ecf20Sopenharmony_ci /* Write the amplifier regs */ 10118c2ecf20Sopenharmony_ci for (i = 0; i < 4; i++) { 10128c2ecf20Sopenharmony_ci v = gain_reg[i]; 10138c2ecf20Sopenharmony_ci if (force || state->gain_reg[i] != v) { 10148c2ecf20Sopenharmony_ci state->gain_reg[i] = v; 10158c2ecf20Sopenharmony_ci dib0090_write_reg(state, gain_reg_addr[i], v); 10168c2ecf20Sopenharmony_ci } 10178c2ecf20Sopenharmony_ci } 10188c2ecf20Sopenharmony_ci} 10198c2ecf20Sopenharmony_ci 10208c2ecf20Sopenharmony_cistatic void dib0090_set_boost(struct dib0090_state *state, int onoff) 10218c2ecf20Sopenharmony_ci{ 10228c2ecf20Sopenharmony_ci state->bb_1_def &= 0xdfff; 10238c2ecf20Sopenharmony_ci state->bb_1_def |= onoff << 13; 10248c2ecf20Sopenharmony_ci} 10258c2ecf20Sopenharmony_ci 10268c2ecf20Sopenharmony_cistatic void dib0090_set_rframp(struct dib0090_state *state, const u16 * cfg) 10278c2ecf20Sopenharmony_ci{ 10288c2ecf20Sopenharmony_ci state->rf_ramp = cfg; 10298c2ecf20Sopenharmony_ci} 10308c2ecf20Sopenharmony_ci 10318c2ecf20Sopenharmony_cistatic void dib0090_set_rframp_pwm(struct dib0090_state *state, const u16 * cfg) 10328c2ecf20Sopenharmony_ci{ 10338c2ecf20Sopenharmony_ci state->rf_ramp = cfg; 10348c2ecf20Sopenharmony_ci 10358c2ecf20Sopenharmony_ci dib0090_write_reg(state, 0x2a, 0xffff); 10368c2ecf20Sopenharmony_ci 10378c2ecf20Sopenharmony_ci dprintk("total RF gain: %ddB, step: %d\n", (u32) cfg[0], dib0090_read_reg(state, 0x2a)); 10388c2ecf20Sopenharmony_ci 10398c2ecf20Sopenharmony_ci dib0090_write_regs(state, 0x2c, cfg + 3, 6); 10408c2ecf20Sopenharmony_ci dib0090_write_regs(state, 0x3e, cfg + 9, 2); 10418c2ecf20Sopenharmony_ci} 10428c2ecf20Sopenharmony_ci 10438c2ecf20Sopenharmony_cistatic void dib0090_set_bbramp(struct dib0090_state *state, const u16 * cfg) 10448c2ecf20Sopenharmony_ci{ 10458c2ecf20Sopenharmony_ci state->bb_ramp = cfg; 10468c2ecf20Sopenharmony_ci dib0090_set_boost(state, cfg[0] > 500); /* we want the boost if the gain is higher that 50dB */ 10478c2ecf20Sopenharmony_ci} 10488c2ecf20Sopenharmony_ci 10498c2ecf20Sopenharmony_cistatic void dib0090_set_bbramp_pwm(struct dib0090_state *state, const u16 * cfg) 10508c2ecf20Sopenharmony_ci{ 10518c2ecf20Sopenharmony_ci state->bb_ramp = cfg; 10528c2ecf20Sopenharmony_ci 10538c2ecf20Sopenharmony_ci dib0090_set_boost(state, cfg[0] > 500); /* we want the boost if the gain is higher that 50dB */ 10548c2ecf20Sopenharmony_ci 10558c2ecf20Sopenharmony_ci dib0090_write_reg(state, 0x33, 0xffff); 10568c2ecf20Sopenharmony_ci dprintk("total BB gain: %ddB, step: %d\n", (u32) cfg[0], dib0090_read_reg(state, 0x33)); 10578c2ecf20Sopenharmony_ci dib0090_write_regs(state, 0x35, cfg + 3, 4); 10588c2ecf20Sopenharmony_ci} 10598c2ecf20Sopenharmony_ci 10608c2ecf20Sopenharmony_civoid dib0090_pwm_gain_reset(struct dvb_frontend *fe) 10618c2ecf20Sopenharmony_ci{ 10628c2ecf20Sopenharmony_ci struct dib0090_state *state = fe->tuner_priv; 10638c2ecf20Sopenharmony_ci const u16 *bb_ramp = bb_ramp_pwm_normal; /* default baseband config */ 10648c2ecf20Sopenharmony_ci const u16 *rf_ramp = NULL; 10658c2ecf20Sopenharmony_ci u8 en_pwm_rf_mux = 1; 10668c2ecf20Sopenharmony_ci 10678c2ecf20Sopenharmony_ci /* reset the AGC */ 10688c2ecf20Sopenharmony_ci if (state->config->use_pwm_agc) { 10698c2ecf20Sopenharmony_ci if (state->current_band == BAND_CBAND) { 10708c2ecf20Sopenharmony_ci if (state->identity.in_soc) { 10718c2ecf20Sopenharmony_ci bb_ramp = bb_ramp_pwm_normal_socs; 10728c2ecf20Sopenharmony_ci if (state->identity.version == SOC_8090_P1G_11R1 || state->identity.version == SOC_8090_P1G_21R1) 10738c2ecf20Sopenharmony_ci rf_ramp = rf_ramp_pwm_cband_8090; 10748c2ecf20Sopenharmony_ci else if (state->identity.version == SOC_7090_P1G_11R1 || state->identity.version == SOC_7090_P1G_21R1) { 10758c2ecf20Sopenharmony_ci if (state->config->is_dib7090e) { 10768c2ecf20Sopenharmony_ci if (state->rf_ramp == NULL) 10778c2ecf20Sopenharmony_ci rf_ramp = rf_ramp_pwm_cband_7090e_sensitivity; 10788c2ecf20Sopenharmony_ci else 10798c2ecf20Sopenharmony_ci rf_ramp = state->rf_ramp; 10808c2ecf20Sopenharmony_ci } else 10818c2ecf20Sopenharmony_ci rf_ramp = rf_ramp_pwm_cband_7090p; 10828c2ecf20Sopenharmony_ci } 10838c2ecf20Sopenharmony_ci } else 10848c2ecf20Sopenharmony_ci rf_ramp = rf_ramp_pwm_cband; 10858c2ecf20Sopenharmony_ci } else 10868c2ecf20Sopenharmony_ci 10878c2ecf20Sopenharmony_ci if (state->current_band == BAND_VHF) { 10888c2ecf20Sopenharmony_ci if (state->identity.in_soc) { 10898c2ecf20Sopenharmony_ci bb_ramp = bb_ramp_pwm_normal_socs; 10908c2ecf20Sopenharmony_ci /* rf_ramp = &rf_ramp_pwm_vhf_socs; */ /* TODO */ 10918c2ecf20Sopenharmony_ci } else 10928c2ecf20Sopenharmony_ci rf_ramp = rf_ramp_pwm_vhf; 10938c2ecf20Sopenharmony_ci } else if (state->current_band == BAND_UHF) { 10948c2ecf20Sopenharmony_ci if (state->identity.in_soc) { 10958c2ecf20Sopenharmony_ci bb_ramp = bb_ramp_pwm_normal_socs; 10968c2ecf20Sopenharmony_ci if (state->identity.version == SOC_8090_P1G_11R1 || state->identity.version == SOC_8090_P1G_21R1) 10978c2ecf20Sopenharmony_ci rf_ramp = rf_ramp_pwm_uhf_8090; 10988c2ecf20Sopenharmony_ci else if (state->identity.version == SOC_7090_P1G_11R1 || state->identity.version == SOC_7090_P1G_21R1) 10998c2ecf20Sopenharmony_ci rf_ramp = rf_ramp_pwm_uhf_7090; 11008c2ecf20Sopenharmony_ci } else 11018c2ecf20Sopenharmony_ci rf_ramp = rf_ramp_pwm_uhf; 11028c2ecf20Sopenharmony_ci } 11038c2ecf20Sopenharmony_ci if (rf_ramp) 11048c2ecf20Sopenharmony_ci dib0090_set_rframp_pwm(state, rf_ramp); 11058c2ecf20Sopenharmony_ci dib0090_set_bbramp_pwm(state, bb_ramp); 11068c2ecf20Sopenharmony_ci 11078c2ecf20Sopenharmony_ci /* activate the ramp generator using PWM control */ 11088c2ecf20Sopenharmony_ci if (state->rf_ramp) 11098c2ecf20Sopenharmony_ci dprintk("ramp RF gain = %d BAND = %s version = %d\n", 11108c2ecf20Sopenharmony_ci state->rf_ramp[0], 11118c2ecf20Sopenharmony_ci (state->current_band == BAND_CBAND) ? "CBAND" : "NOT CBAND", 11128c2ecf20Sopenharmony_ci state->identity.version & 0x1f); 11138c2ecf20Sopenharmony_ci 11148c2ecf20Sopenharmony_ci if (rf_ramp && ((state->rf_ramp && state->rf_ramp[0] == 0) || 11158c2ecf20Sopenharmony_ci (state->current_band == BAND_CBAND && 11168c2ecf20Sopenharmony_ci (state->identity.version & 0x1f) <= P1D_E_F))) { 11178c2ecf20Sopenharmony_ci dprintk("DE-Engage mux for direct gain reg control\n"); 11188c2ecf20Sopenharmony_ci en_pwm_rf_mux = 0; 11198c2ecf20Sopenharmony_ci } else 11208c2ecf20Sopenharmony_ci dprintk("Engage mux for PWM control\n"); 11218c2ecf20Sopenharmony_ci 11228c2ecf20Sopenharmony_ci dib0090_write_reg(state, 0x32, (en_pwm_rf_mux << 12) | (en_pwm_rf_mux << 11)); 11238c2ecf20Sopenharmony_ci 11248c2ecf20Sopenharmony_ci /* Set fast servo cutoff to start AGC; 0 = 1KHz ; 1 = 50Hz ; 2 = 150Hz ; 3 = 50KHz ; 4 = servo fast*/ 11258c2ecf20Sopenharmony_ci if (state->identity.version == SOC_7090_P1G_11R1 || state->identity.version == SOC_7090_P1G_21R1) 11268c2ecf20Sopenharmony_ci dib0090_write_reg(state, 0x04, 3); 11278c2ecf20Sopenharmony_ci else 11288c2ecf20Sopenharmony_ci dib0090_write_reg(state, 0x04, 1); 11298c2ecf20Sopenharmony_ci dib0090_write_reg(state, 0x39, (1 << 10)); /* 0 gain by default */ 11308c2ecf20Sopenharmony_ci } 11318c2ecf20Sopenharmony_ci} 11328c2ecf20Sopenharmony_ciEXPORT_SYMBOL(dib0090_pwm_gain_reset); 11338c2ecf20Sopenharmony_ci 11348c2ecf20Sopenharmony_civoid dib0090_set_dc_servo(struct dvb_frontend *fe, u8 DC_servo_cutoff) 11358c2ecf20Sopenharmony_ci{ 11368c2ecf20Sopenharmony_ci struct dib0090_state *state = fe->tuner_priv; 11378c2ecf20Sopenharmony_ci if (DC_servo_cutoff < 4) 11388c2ecf20Sopenharmony_ci dib0090_write_reg(state, 0x04, DC_servo_cutoff); 11398c2ecf20Sopenharmony_ci} 11408c2ecf20Sopenharmony_ciEXPORT_SYMBOL(dib0090_set_dc_servo); 11418c2ecf20Sopenharmony_ci 11428c2ecf20Sopenharmony_cistatic u32 dib0090_get_slow_adc_val(struct dib0090_state *state) 11438c2ecf20Sopenharmony_ci{ 11448c2ecf20Sopenharmony_ci u16 adc_val = dib0090_read_reg(state, 0x1d); 11458c2ecf20Sopenharmony_ci if (state->identity.in_soc) 11468c2ecf20Sopenharmony_ci adc_val >>= 2; 11478c2ecf20Sopenharmony_ci return adc_val; 11488c2ecf20Sopenharmony_ci} 11498c2ecf20Sopenharmony_ci 11508c2ecf20Sopenharmony_ciint dib0090_gain_control(struct dvb_frontend *fe) 11518c2ecf20Sopenharmony_ci{ 11528c2ecf20Sopenharmony_ci struct dib0090_state *state = fe->tuner_priv; 11538c2ecf20Sopenharmony_ci enum frontend_tune_state *tune_state = &state->tune_state; 11548c2ecf20Sopenharmony_ci int ret = 10; 11558c2ecf20Sopenharmony_ci 11568c2ecf20Sopenharmony_ci u16 wbd_val = 0; 11578c2ecf20Sopenharmony_ci u8 apply_gain_immediatly = 1; 11588c2ecf20Sopenharmony_ci s16 wbd_error = 0, adc_error = 0; 11598c2ecf20Sopenharmony_ci 11608c2ecf20Sopenharmony_ci if (*tune_state == CT_AGC_START) { 11618c2ecf20Sopenharmony_ci state->agc_freeze = 0; 11628c2ecf20Sopenharmony_ci dib0090_write_reg(state, 0x04, 0x0); 11638c2ecf20Sopenharmony_ci 11648c2ecf20Sopenharmony_ci#ifdef CONFIG_BAND_SBAND 11658c2ecf20Sopenharmony_ci if (state->current_band == BAND_SBAND) { 11668c2ecf20Sopenharmony_ci dib0090_set_rframp(state, rf_ramp_sband); 11678c2ecf20Sopenharmony_ci dib0090_set_bbramp(state, bb_ramp_boost); 11688c2ecf20Sopenharmony_ci } else 11698c2ecf20Sopenharmony_ci#endif 11708c2ecf20Sopenharmony_ci#ifdef CONFIG_BAND_VHF 11718c2ecf20Sopenharmony_ci if (state->current_band == BAND_VHF && !state->identity.p1g) { 11728c2ecf20Sopenharmony_ci dib0090_set_rframp(state, rf_ramp_pwm_vhf); 11738c2ecf20Sopenharmony_ci dib0090_set_bbramp(state, bb_ramp_pwm_normal); 11748c2ecf20Sopenharmony_ci } else 11758c2ecf20Sopenharmony_ci#endif 11768c2ecf20Sopenharmony_ci#ifdef CONFIG_BAND_CBAND 11778c2ecf20Sopenharmony_ci if (state->current_band == BAND_CBAND && !state->identity.p1g) { 11788c2ecf20Sopenharmony_ci dib0090_set_rframp(state, rf_ramp_pwm_cband); 11798c2ecf20Sopenharmony_ci dib0090_set_bbramp(state, bb_ramp_pwm_normal); 11808c2ecf20Sopenharmony_ci } else 11818c2ecf20Sopenharmony_ci#endif 11828c2ecf20Sopenharmony_ci if ((state->current_band == BAND_CBAND || state->current_band == BAND_VHF) && state->identity.p1g) { 11838c2ecf20Sopenharmony_ci dib0090_set_rframp(state, rf_ramp_pwm_cband_7090p); 11848c2ecf20Sopenharmony_ci dib0090_set_bbramp(state, bb_ramp_pwm_normal_socs); 11858c2ecf20Sopenharmony_ci } else { 11868c2ecf20Sopenharmony_ci dib0090_set_rframp(state, rf_ramp_pwm_uhf); 11878c2ecf20Sopenharmony_ci dib0090_set_bbramp(state, bb_ramp_pwm_normal); 11888c2ecf20Sopenharmony_ci } 11898c2ecf20Sopenharmony_ci 11908c2ecf20Sopenharmony_ci dib0090_write_reg(state, 0x32, 0); 11918c2ecf20Sopenharmony_ci dib0090_write_reg(state, 0x39, 0); 11928c2ecf20Sopenharmony_ci 11938c2ecf20Sopenharmony_ci dib0090_wbd_target(state, state->current_rf); 11948c2ecf20Sopenharmony_ci 11958c2ecf20Sopenharmony_ci state->rf_gain_limit = state->rf_ramp[0] << WBD_ALPHA; 11968c2ecf20Sopenharmony_ci state->current_gain = ((state->rf_ramp[0] + state->bb_ramp[0]) / 2) << GAIN_ALPHA; 11978c2ecf20Sopenharmony_ci 11988c2ecf20Sopenharmony_ci *tune_state = CT_AGC_STEP_0; 11998c2ecf20Sopenharmony_ci } else if (!state->agc_freeze) { 12008c2ecf20Sopenharmony_ci s16 wbd = 0, i, cnt; 12018c2ecf20Sopenharmony_ci 12028c2ecf20Sopenharmony_ci int adc; 12038c2ecf20Sopenharmony_ci wbd_val = dib0090_get_slow_adc_val(state); 12048c2ecf20Sopenharmony_ci 12058c2ecf20Sopenharmony_ci if (*tune_state == CT_AGC_STEP_0) 12068c2ecf20Sopenharmony_ci cnt = 5; 12078c2ecf20Sopenharmony_ci else 12088c2ecf20Sopenharmony_ci cnt = 1; 12098c2ecf20Sopenharmony_ci 12108c2ecf20Sopenharmony_ci for (i = 0; i < cnt; i++) { 12118c2ecf20Sopenharmony_ci wbd_val = dib0090_get_slow_adc_val(state); 12128c2ecf20Sopenharmony_ci wbd += dib0090_wbd_to_db(state, wbd_val); 12138c2ecf20Sopenharmony_ci } 12148c2ecf20Sopenharmony_ci wbd /= cnt; 12158c2ecf20Sopenharmony_ci wbd_error = state->wbd_target - wbd; 12168c2ecf20Sopenharmony_ci 12178c2ecf20Sopenharmony_ci if (*tune_state == CT_AGC_STEP_0) { 12188c2ecf20Sopenharmony_ci if (wbd_error < 0 && state->rf_gain_limit > 0 && !state->identity.p1g) { 12198c2ecf20Sopenharmony_ci#ifdef CONFIG_BAND_CBAND 12208c2ecf20Sopenharmony_ci /* in case of CBAND tune reduce first the lt_gain2 before adjusting the RF gain */ 12218c2ecf20Sopenharmony_ci u8 ltg2 = (state->rf_lt_def >> 10) & 0x7; 12228c2ecf20Sopenharmony_ci if (state->current_band == BAND_CBAND && ltg2) { 12238c2ecf20Sopenharmony_ci ltg2 >>= 1; 12248c2ecf20Sopenharmony_ci state->rf_lt_def &= ltg2 << 10; /* reduce in 3 steps from 7 to 0 */ 12258c2ecf20Sopenharmony_ci } 12268c2ecf20Sopenharmony_ci#endif 12278c2ecf20Sopenharmony_ci } else { 12288c2ecf20Sopenharmony_ci state->agc_step = 0; 12298c2ecf20Sopenharmony_ci *tune_state = CT_AGC_STEP_1; 12308c2ecf20Sopenharmony_ci } 12318c2ecf20Sopenharmony_ci } else { 12328c2ecf20Sopenharmony_ci /* calc the adc power */ 12338c2ecf20Sopenharmony_ci adc = state->config->get_adc_power(fe); 12348c2ecf20Sopenharmony_ci adc = (adc * ((s32) 355774) + (((s32) 1) << 20)) >> 21; /* included in [0:-700] */ 12358c2ecf20Sopenharmony_ci 12368c2ecf20Sopenharmony_ci adc_error = (s16) (((s32) ADC_TARGET) - adc); 12378c2ecf20Sopenharmony_ci#ifdef CONFIG_STANDARD_DAB 12388c2ecf20Sopenharmony_ci if (state->fe->dtv_property_cache.delivery_system == STANDARD_DAB) 12398c2ecf20Sopenharmony_ci adc_error -= 10; 12408c2ecf20Sopenharmony_ci#endif 12418c2ecf20Sopenharmony_ci#ifdef CONFIG_STANDARD_DVBT 12428c2ecf20Sopenharmony_ci if (state->fe->dtv_property_cache.delivery_system == STANDARD_DVBT && 12438c2ecf20Sopenharmony_ci (state->fe->dtv_property_cache.modulation == QAM_64 || state->fe->dtv_property_cache.modulation == QAM_16)) 12448c2ecf20Sopenharmony_ci adc_error += 60; 12458c2ecf20Sopenharmony_ci#endif 12468c2ecf20Sopenharmony_ci#ifdef CONFIG_SYS_ISDBT 12478c2ecf20Sopenharmony_ci if ((state->fe->dtv_property_cache.delivery_system == SYS_ISDBT) && (((state->fe->dtv_property_cache.layer[0].segment_count > 12488c2ecf20Sopenharmony_ci 0) 12498c2ecf20Sopenharmony_ci && 12508c2ecf20Sopenharmony_ci ((state->fe->dtv_property_cache.layer[0].modulation == 12518c2ecf20Sopenharmony_ci QAM_64) 12528c2ecf20Sopenharmony_ci || (state->fe->dtv_property_cache. 12538c2ecf20Sopenharmony_ci layer[0].modulation == QAM_16))) 12548c2ecf20Sopenharmony_ci || 12558c2ecf20Sopenharmony_ci ((state->fe->dtv_property_cache.layer[1].segment_count > 12568c2ecf20Sopenharmony_ci 0) 12578c2ecf20Sopenharmony_ci && 12588c2ecf20Sopenharmony_ci ((state->fe->dtv_property_cache.layer[1].modulation == 12598c2ecf20Sopenharmony_ci QAM_64) 12608c2ecf20Sopenharmony_ci || (state->fe->dtv_property_cache. 12618c2ecf20Sopenharmony_ci layer[1].modulation == QAM_16))) 12628c2ecf20Sopenharmony_ci || 12638c2ecf20Sopenharmony_ci ((state->fe->dtv_property_cache.layer[2].segment_count > 12648c2ecf20Sopenharmony_ci 0) 12658c2ecf20Sopenharmony_ci && 12668c2ecf20Sopenharmony_ci ((state->fe->dtv_property_cache.layer[2].modulation == 12678c2ecf20Sopenharmony_ci QAM_64) 12688c2ecf20Sopenharmony_ci || (state->fe->dtv_property_cache. 12698c2ecf20Sopenharmony_ci layer[2].modulation == QAM_16))) 12708c2ecf20Sopenharmony_ci ) 12718c2ecf20Sopenharmony_ci ) 12728c2ecf20Sopenharmony_ci adc_error += 60; 12738c2ecf20Sopenharmony_ci#endif 12748c2ecf20Sopenharmony_ci 12758c2ecf20Sopenharmony_ci if (*tune_state == CT_AGC_STEP_1) { /* quickly go to the correct range of the ADC power */ 12768c2ecf20Sopenharmony_ci if (abs(adc_error) < 50 || state->agc_step++ > 5) { 12778c2ecf20Sopenharmony_ci 12788c2ecf20Sopenharmony_ci#ifdef CONFIG_STANDARD_DAB 12798c2ecf20Sopenharmony_ci if (state->fe->dtv_property_cache.delivery_system == STANDARD_DAB) { 12808c2ecf20Sopenharmony_ci dib0090_write_reg(state, 0x02, (1 << 15) | (15 << 11) | (31 << 6) | (63)); /* cap value = 63 : narrow BB filter : Fc = 1.8MHz */ 12818c2ecf20Sopenharmony_ci dib0090_write_reg(state, 0x04, 0x0); 12828c2ecf20Sopenharmony_ci } else 12838c2ecf20Sopenharmony_ci#endif 12848c2ecf20Sopenharmony_ci { 12858c2ecf20Sopenharmony_ci dib0090_write_reg(state, 0x02, (1 << 15) | (3 << 11) | (6 << 6) | (32)); 12868c2ecf20Sopenharmony_ci dib0090_write_reg(state, 0x04, 0x01); /*0 = 1KHz ; 1 = 150Hz ; 2 = 50Hz ; 3 = 50KHz ; 4 = servo fast */ 12878c2ecf20Sopenharmony_ci } 12888c2ecf20Sopenharmony_ci 12898c2ecf20Sopenharmony_ci *tune_state = CT_AGC_STOP; 12908c2ecf20Sopenharmony_ci } 12918c2ecf20Sopenharmony_ci } else { 12928c2ecf20Sopenharmony_ci /* everything higher than or equal to CT_AGC_STOP means tracking */ 12938c2ecf20Sopenharmony_ci ret = 100; /* 10ms interval */ 12948c2ecf20Sopenharmony_ci apply_gain_immediatly = 0; 12958c2ecf20Sopenharmony_ci } 12968c2ecf20Sopenharmony_ci } 12978c2ecf20Sopenharmony_ci#ifdef DEBUG_AGC 12988c2ecf20Sopenharmony_ci dprintk 12998c2ecf20Sopenharmony_ci ("tune state %d, ADC = %3ddB (ADC err %3d) WBD %3ddB (WBD err %3d, WBD val SADC: %4d), RFGainLimit (TOP): %3d, signal: %3ddBm", 13008c2ecf20Sopenharmony_ci (u32) *tune_state, (u32) adc, (u32) adc_error, (u32) wbd, (u32) wbd_error, (u32) wbd_val, 13018c2ecf20Sopenharmony_ci (u32) state->rf_gain_limit >> WBD_ALPHA, (s32) 200 + adc - (state->current_gain >> GAIN_ALPHA)); 13028c2ecf20Sopenharmony_ci#endif 13038c2ecf20Sopenharmony_ci } 13048c2ecf20Sopenharmony_ci 13058c2ecf20Sopenharmony_ci /* apply gain */ 13068c2ecf20Sopenharmony_ci if (!state->agc_freeze) 13078c2ecf20Sopenharmony_ci dib0090_gain_apply(state, adc_error, wbd_error, apply_gain_immediatly); 13088c2ecf20Sopenharmony_ci return ret; 13098c2ecf20Sopenharmony_ci} 13108c2ecf20Sopenharmony_ci 13118c2ecf20Sopenharmony_ciEXPORT_SYMBOL(dib0090_gain_control); 13128c2ecf20Sopenharmony_ci 13138c2ecf20Sopenharmony_civoid dib0090_get_current_gain(struct dvb_frontend *fe, u16 * rf, u16 * bb, u16 * rf_gain_limit, u16 * rflt) 13148c2ecf20Sopenharmony_ci{ 13158c2ecf20Sopenharmony_ci struct dib0090_state *state = fe->tuner_priv; 13168c2ecf20Sopenharmony_ci if (rf) 13178c2ecf20Sopenharmony_ci *rf = state->gain[0]; 13188c2ecf20Sopenharmony_ci if (bb) 13198c2ecf20Sopenharmony_ci *bb = state->gain[1]; 13208c2ecf20Sopenharmony_ci if (rf_gain_limit) 13218c2ecf20Sopenharmony_ci *rf_gain_limit = state->rf_gain_limit; 13228c2ecf20Sopenharmony_ci if (rflt) 13238c2ecf20Sopenharmony_ci *rflt = (state->rf_lt_def >> 10) & 0x7; 13248c2ecf20Sopenharmony_ci} 13258c2ecf20Sopenharmony_ci 13268c2ecf20Sopenharmony_ciEXPORT_SYMBOL(dib0090_get_current_gain); 13278c2ecf20Sopenharmony_ci 13288c2ecf20Sopenharmony_ciu16 dib0090_get_wbd_target(struct dvb_frontend *fe) 13298c2ecf20Sopenharmony_ci{ 13308c2ecf20Sopenharmony_ci struct dib0090_state *state = fe->tuner_priv; 13318c2ecf20Sopenharmony_ci u32 f_MHz = state->fe->dtv_property_cache.frequency / 1000000; 13328c2ecf20Sopenharmony_ci s32 current_temp = state->temperature; 13338c2ecf20Sopenharmony_ci s32 wbd_thot, wbd_tcold; 13348c2ecf20Sopenharmony_ci const struct dib0090_wbd_slope *wbd = state->current_wbd_table; 13358c2ecf20Sopenharmony_ci 13368c2ecf20Sopenharmony_ci while (f_MHz > wbd->max_freq) 13378c2ecf20Sopenharmony_ci wbd++; 13388c2ecf20Sopenharmony_ci 13398c2ecf20Sopenharmony_ci dprintk("using wbd-table-entry with max freq %d\n", wbd->max_freq); 13408c2ecf20Sopenharmony_ci 13418c2ecf20Sopenharmony_ci if (current_temp < 0) 13428c2ecf20Sopenharmony_ci current_temp = 0; 13438c2ecf20Sopenharmony_ci if (current_temp > 128) 13448c2ecf20Sopenharmony_ci current_temp = 128; 13458c2ecf20Sopenharmony_ci 13468c2ecf20Sopenharmony_ci state->wbdmux &= ~(7 << 13); 13478c2ecf20Sopenharmony_ci if (wbd->wbd_gain != 0) 13488c2ecf20Sopenharmony_ci state->wbdmux |= (wbd->wbd_gain << 13); 13498c2ecf20Sopenharmony_ci else 13508c2ecf20Sopenharmony_ci state->wbdmux |= (4 << 13); 13518c2ecf20Sopenharmony_ci 13528c2ecf20Sopenharmony_ci dib0090_write_reg(state, 0x10, state->wbdmux); 13538c2ecf20Sopenharmony_ci 13548c2ecf20Sopenharmony_ci wbd_thot = wbd->offset_hot - (((u32) wbd->slope_hot * f_MHz) >> 6); 13558c2ecf20Sopenharmony_ci wbd_tcold = wbd->offset_cold - (((u32) wbd->slope_cold * f_MHz) >> 6); 13568c2ecf20Sopenharmony_ci 13578c2ecf20Sopenharmony_ci wbd_tcold += ((wbd_thot - wbd_tcold) * current_temp) >> 7; 13588c2ecf20Sopenharmony_ci 13598c2ecf20Sopenharmony_ci state->wbd_target = dib0090_wbd_to_db(state, state->wbd_offset + wbd_tcold); 13608c2ecf20Sopenharmony_ci dprintk("wbd-target: %d dB\n", (u32) state->wbd_target); 13618c2ecf20Sopenharmony_ci dprintk("wbd offset applied is %d\n", wbd_tcold); 13628c2ecf20Sopenharmony_ci 13638c2ecf20Sopenharmony_ci return state->wbd_offset + wbd_tcold; 13648c2ecf20Sopenharmony_ci} 13658c2ecf20Sopenharmony_ciEXPORT_SYMBOL(dib0090_get_wbd_target); 13668c2ecf20Sopenharmony_ci 13678c2ecf20Sopenharmony_ciu16 dib0090_get_wbd_offset(struct dvb_frontend *fe) 13688c2ecf20Sopenharmony_ci{ 13698c2ecf20Sopenharmony_ci struct dib0090_state *state = fe->tuner_priv; 13708c2ecf20Sopenharmony_ci return state->wbd_offset; 13718c2ecf20Sopenharmony_ci} 13728c2ecf20Sopenharmony_ciEXPORT_SYMBOL(dib0090_get_wbd_offset); 13738c2ecf20Sopenharmony_ci 13748c2ecf20Sopenharmony_ciint dib0090_set_switch(struct dvb_frontend *fe, u8 sw1, u8 sw2, u8 sw3) 13758c2ecf20Sopenharmony_ci{ 13768c2ecf20Sopenharmony_ci struct dib0090_state *state = fe->tuner_priv; 13778c2ecf20Sopenharmony_ci 13788c2ecf20Sopenharmony_ci dib0090_write_reg(state, 0x0b, (dib0090_read_reg(state, 0x0b) & 0xfff8) 13798c2ecf20Sopenharmony_ci | ((sw3 & 1) << 2) | ((sw2 & 1) << 1) | (sw1 & 1)); 13808c2ecf20Sopenharmony_ci 13818c2ecf20Sopenharmony_ci return 0; 13828c2ecf20Sopenharmony_ci} 13838c2ecf20Sopenharmony_ciEXPORT_SYMBOL(dib0090_set_switch); 13848c2ecf20Sopenharmony_ci 13858c2ecf20Sopenharmony_ciint dib0090_set_vga(struct dvb_frontend *fe, u8 onoff) 13868c2ecf20Sopenharmony_ci{ 13878c2ecf20Sopenharmony_ci struct dib0090_state *state = fe->tuner_priv; 13888c2ecf20Sopenharmony_ci 13898c2ecf20Sopenharmony_ci dib0090_write_reg(state, 0x09, (dib0090_read_reg(state, 0x09) & 0x7fff) 13908c2ecf20Sopenharmony_ci | ((onoff & 1) << 15)); 13918c2ecf20Sopenharmony_ci return 0; 13928c2ecf20Sopenharmony_ci} 13938c2ecf20Sopenharmony_ciEXPORT_SYMBOL(dib0090_set_vga); 13948c2ecf20Sopenharmony_ci 13958c2ecf20Sopenharmony_ciint dib0090_update_rframp_7090(struct dvb_frontend *fe, u8 cfg_sensitivity) 13968c2ecf20Sopenharmony_ci{ 13978c2ecf20Sopenharmony_ci struct dib0090_state *state = fe->tuner_priv; 13988c2ecf20Sopenharmony_ci 13998c2ecf20Sopenharmony_ci if ((!state->identity.p1g) || (!state->identity.in_soc) 14008c2ecf20Sopenharmony_ci || ((state->identity.version != SOC_7090_P1G_21R1) 14018c2ecf20Sopenharmony_ci && (state->identity.version != SOC_7090_P1G_11R1))) { 14028c2ecf20Sopenharmony_ci dprintk("%s() function can only be used for dib7090P\n", __func__); 14038c2ecf20Sopenharmony_ci return -ENODEV; 14048c2ecf20Sopenharmony_ci } 14058c2ecf20Sopenharmony_ci 14068c2ecf20Sopenharmony_ci if (cfg_sensitivity) 14078c2ecf20Sopenharmony_ci state->rf_ramp = rf_ramp_pwm_cband_7090e_sensitivity; 14088c2ecf20Sopenharmony_ci else 14098c2ecf20Sopenharmony_ci state->rf_ramp = rf_ramp_pwm_cband_7090e_aci; 14108c2ecf20Sopenharmony_ci dib0090_pwm_gain_reset(fe); 14118c2ecf20Sopenharmony_ci 14128c2ecf20Sopenharmony_ci return 0; 14138c2ecf20Sopenharmony_ci} 14148c2ecf20Sopenharmony_ciEXPORT_SYMBOL(dib0090_update_rframp_7090); 14158c2ecf20Sopenharmony_ci 14168c2ecf20Sopenharmony_cistatic const u16 dib0090_defaults[] = { 14178c2ecf20Sopenharmony_ci 14188c2ecf20Sopenharmony_ci 25, 0x01, 14198c2ecf20Sopenharmony_ci 0x0000, 14208c2ecf20Sopenharmony_ci 0x99a0, 14218c2ecf20Sopenharmony_ci 0x6008, 14228c2ecf20Sopenharmony_ci 0x0000, 14238c2ecf20Sopenharmony_ci 0x8bcb, 14248c2ecf20Sopenharmony_ci 0x0000, 14258c2ecf20Sopenharmony_ci 0x0405, 14268c2ecf20Sopenharmony_ci 0x0000, 14278c2ecf20Sopenharmony_ci 0x0000, 14288c2ecf20Sopenharmony_ci 0x0000, 14298c2ecf20Sopenharmony_ci 0xb802, 14308c2ecf20Sopenharmony_ci 0x0300, 14318c2ecf20Sopenharmony_ci 0x2d12, 14328c2ecf20Sopenharmony_ci 0xbac0, 14338c2ecf20Sopenharmony_ci 0x7c00, 14348c2ecf20Sopenharmony_ci 0xdbb9, 14358c2ecf20Sopenharmony_ci 0x0954, 14368c2ecf20Sopenharmony_ci 0x0743, 14378c2ecf20Sopenharmony_ci 0x8000, 14388c2ecf20Sopenharmony_ci 0x0001, 14398c2ecf20Sopenharmony_ci 0x0040, 14408c2ecf20Sopenharmony_ci 0x0100, 14418c2ecf20Sopenharmony_ci 0x0000, 14428c2ecf20Sopenharmony_ci 0xe910, 14438c2ecf20Sopenharmony_ci 0x149e, 14448c2ecf20Sopenharmony_ci 14458c2ecf20Sopenharmony_ci 1, 0x1c, 14468c2ecf20Sopenharmony_ci 0xff2d, 14478c2ecf20Sopenharmony_ci 14488c2ecf20Sopenharmony_ci 1, 0x39, 14498c2ecf20Sopenharmony_ci 0x0000, 14508c2ecf20Sopenharmony_ci 14518c2ecf20Sopenharmony_ci 2, 0x1e, 14528c2ecf20Sopenharmony_ci 0x07FF, 14538c2ecf20Sopenharmony_ci 0x0007, 14548c2ecf20Sopenharmony_ci 14558c2ecf20Sopenharmony_ci 1, 0x24, 14568c2ecf20Sopenharmony_ci EN_UHF | EN_CRYSTAL, 14578c2ecf20Sopenharmony_ci 14588c2ecf20Sopenharmony_ci 2, 0x3c, 14598c2ecf20Sopenharmony_ci 0x3ff, 14608c2ecf20Sopenharmony_ci 0x111, 14618c2ecf20Sopenharmony_ci 0 14628c2ecf20Sopenharmony_ci}; 14638c2ecf20Sopenharmony_ci 14648c2ecf20Sopenharmony_cistatic const u16 dib0090_p1g_additionnal_defaults[] = { 14658c2ecf20Sopenharmony_ci 1, 0x05, 14668c2ecf20Sopenharmony_ci 0xabcd, 14678c2ecf20Sopenharmony_ci 14688c2ecf20Sopenharmony_ci 1, 0x11, 14698c2ecf20Sopenharmony_ci 0x00b4, 14708c2ecf20Sopenharmony_ci 14718c2ecf20Sopenharmony_ci 1, 0x1c, 14728c2ecf20Sopenharmony_ci 0xfffd, 14738c2ecf20Sopenharmony_ci 14748c2ecf20Sopenharmony_ci 1, 0x40, 14758c2ecf20Sopenharmony_ci 0x108, 14768c2ecf20Sopenharmony_ci 0 14778c2ecf20Sopenharmony_ci}; 14788c2ecf20Sopenharmony_ci 14798c2ecf20Sopenharmony_cistatic void dib0090_set_default_config(struct dib0090_state *state, const u16 * n) 14808c2ecf20Sopenharmony_ci{ 14818c2ecf20Sopenharmony_ci u16 l, r; 14828c2ecf20Sopenharmony_ci 14838c2ecf20Sopenharmony_ci l = pgm_read_word(n++); 14848c2ecf20Sopenharmony_ci while (l) { 14858c2ecf20Sopenharmony_ci r = pgm_read_word(n++); 14868c2ecf20Sopenharmony_ci do { 14878c2ecf20Sopenharmony_ci dib0090_write_reg(state, r, pgm_read_word(n++)); 14888c2ecf20Sopenharmony_ci r++; 14898c2ecf20Sopenharmony_ci } while (--l); 14908c2ecf20Sopenharmony_ci l = pgm_read_word(n++); 14918c2ecf20Sopenharmony_ci } 14928c2ecf20Sopenharmony_ci} 14938c2ecf20Sopenharmony_ci 14948c2ecf20Sopenharmony_ci#define CAP_VALUE_MIN (u8) 9 14958c2ecf20Sopenharmony_ci#define CAP_VALUE_MAX (u8) 40 14968c2ecf20Sopenharmony_ci#define HR_MIN (u8) 25 14978c2ecf20Sopenharmony_ci#define HR_MAX (u8) 40 14988c2ecf20Sopenharmony_ci#define POLY_MIN (u8) 0 14998c2ecf20Sopenharmony_ci#define POLY_MAX (u8) 8 15008c2ecf20Sopenharmony_ci 15018c2ecf20Sopenharmony_cistatic void dib0090_set_EFUSE(struct dib0090_state *state) 15028c2ecf20Sopenharmony_ci{ 15038c2ecf20Sopenharmony_ci u8 c, h, n; 15048c2ecf20Sopenharmony_ci u16 e2, e4; 15058c2ecf20Sopenharmony_ci u16 cal; 15068c2ecf20Sopenharmony_ci 15078c2ecf20Sopenharmony_ci e2 = dib0090_read_reg(state, 0x26); 15088c2ecf20Sopenharmony_ci e4 = dib0090_read_reg(state, 0x28); 15098c2ecf20Sopenharmony_ci 15108c2ecf20Sopenharmony_ci if ((state->identity.version == P1D_E_F) || 15118c2ecf20Sopenharmony_ci (state->identity.version == P1G) || (e2 == 0xffff)) { 15128c2ecf20Sopenharmony_ci 15138c2ecf20Sopenharmony_ci dib0090_write_reg(state, 0x22, 0x10); 15148c2ecf20Sopenharmony_ci cal = (dib0090_read_reg(state, 0x22) >> 6) & 0x3ff; 15158c2ecf20Sopenharmony_ci 15168c2ecf20Sopenharmony_ci if ((cal < 670) || (cal == 1023)) 15178c2ecf20Sopenharmony_ci cal = 850; 15188c2ecf20Sopenharmony_ci n = 165 - ((cal * 10)>>6) ; 15198c2ecf20Sopenharmony_ci e2 = e4 = (3<<12) | (34<<6) | (n); 15208c2ecf20Sopenharmony_ci } 15218c2ecf20Sopenharmony_ci 15228c2ecf20Sopenharmony_ci if (e2 != e4) 15238c2ecf20Sopenharmony_ci e2 &= e4; /* Remove the redundancy */ 15248c2ecf20Sopenharmony_ci 15258c2ecf20Sopenharmony_ci if (e2 != 0xffff) { 15268c2ecf20Sopenharmony_ci c = e2 & 0x3f; 15278c2ecf20Sopenharmony_ci n = (e2 >> 12) & 0xf; 15288c2ecf20Sopenharmony_ci h = (e2 >> 6) & 0x3f; 15298c2ecf20Sopenharmony_ci 15308c2ecf20Sopenharmony_ci if ((c >= CAP_VALUE_MAX) || (c <= CAP_VALUE_MIN)) 15318c2ecf20Sopenharmony_ci c = 32; 15328c2ecf20Sopenharmony_ci else 15338c2ecf20Sopenharmony_ci c += 14; 15348c2ecf20Sopenharmony_ci if ((h >= HR_MAX) || (h <= HR_MIN)) 15358c2ecf20Sopenharmony_ci h = 34; 15368c2ecf20Sopenharmony_ci if ((n >= POLY_MAX) || (n <= POLY_MIN)) 15378c2ecf20Sopenharmony_ci n = 3; 15388c2ecf20Sopenharmony_ci 15398c2ecf20Sopenharmony_ci dib0090_write_reg(state, 0x13, (h << 10)); 15408c2ecf20Sopenharmony_ci e2 = (n << 11) | ((h >> 2)<<6) | c; 15418c2ecf20Sopenharmony_ci dib0090_write_reg(state, 0x2, e2); /* Load the BB_2 */ 15428c2ecf20Sopenharmony_ci } 15438c2ecf20Sopenharmony_ci} 15448c2ecf20Sopenharmony_ci 15458c2ecf20Sopenharmony_cistatic int dib0090_reset(struct dvb_frontend *fe) 15468c2ecf20Sopenharmony_ci{ 15478c2ecf20Sopenharmony_ci struct dib0090_state *state = fe->tuner_priv; 15488c2ecf20Sopenharmony_ci 15498c2ecf20Sopenharmony_ci dib0090_reset_digital(fe, state->config); 15508c2ecf20Sopenharmony_ci if (dib0090_identify(fe) < 0) 15518c2ecf20Sopenharmony_ci return -EIO; 15528c2ecf20Sopenharmony_ci 15538c2ecf20Sopenharmony_ci#ifdef CONFIG_TUNER_DIB0090_P1B_SUPPORT 15548c2ecf20Sopenharmony_ci if (!(state->identity.version & 0x1)) /* it is P1B - reset is already done */ 15558c2ecf20Sopenharmony_ci return 0; 15568c2ecf20Sopenharmony_ci#endif 15578c2ecf20Sopenharmony_ci 15588c2ecf20Sopenharmony_ci if (!state->identity.in_soc) { 15598c2ecf20Sopenharmony_ci if ((dib0090_read_reg(state, 0x1a) >> 5) & 0x2) 15608c2ecf20Sopenharmony_ci dib0090_write_reg(state, 0x1b, (EN_IQADC | EN_BB | EN_BIAS | EN_DIGCLK | EN_PLL | EN_CRYSTAL)); 15618c2ecf20Sopenharmony_ci else 15628c2ecf20Sopenharmony_ci dib0090_write_reg(state, 0x1b, (EN_DIGCLK | EN_PLL | EN_CRYSTAL)); 15638c2ecf20Sopenharmony_ci } 15648c2ecf20Sopenharmony_ci 15658c2ecf20Sopenharmony_ci dib0090_set_default_config(state, dib0090_defaults); 15668c2ecf20Sopenharmony_ci 15678c2ecf20Sopenharmony_ci if (state->identity.in_soc) 15688c2ecf20Sopenharmony_ci dib0090_write_reg(state, 0x18, 0x2910); /* charge pump current = 0 */ 15698c2ecf20Sopenharmony_ci 15708c2ecf20Sopenharmony_ci if (state->identity.p1g) 15718c2ecf20Sopenharmony_ci dib0090_set_default_config(state, dib0090_p1g_additionnal_defaults); 15728c2ecf20Sopenharmony_ci 15738c2ecf20Sopenharmony_ci /* Update the efuse : Only available for KROSUS > P1C and SOC as well*/ 15748c2ecf20Sopenharmony_ci if (((state->identity.version & 0x1f) >= P1D_E_F) || (state->identity.in_soc)) 15758c2ecf20Sopenharmony_ci dib0090_set_EFUSE(state); 15768c2ecf20Sopenharmony_ci 15778c2ecf20Sopenharmony_ci /* Congigure in function of the crystal */ 15788c2ecf20Sopenharmony_ci if (state->config->force_crystal_mode != 0) 15798c2ecf20Sopenharmony_ci dib0090_write_reg(state, 0x14, 15808c2ecf20Sopenharmony_ci state->config->force_crystal_mode & 3); 15818c2ecf20Sopenharmony_ci else if (state->config->io.clock_khz >= 24000) 15828c2ecf20Sopenharmony_ci dib0090_write_reg(state, 0x14, 1); 15838c2ecf20Sopenharmony_ci else 15848c2ecf20Sopenharmony_ci dib0090_write_reg(state, 0x14, 2); 15858c2ecf20Sopenharmony_ci dprintk("Pll lock : %d\n", (dib0090_read_reg(state, 0x1a) >> 11) & 0x1); 15868c2ecf20Sopenharmony_ci 15878c2ecf20Sopenharmony_ci state->calibrate = DC_CAL | WBD_CAL | TEMP_CAL; /* enable iq-offset-calibration and wbd-calibration when tuning next time */ 15888c2ecf20Sopenharmony_ci 15898c2ecf20Sopenharmony_ci return 0; 15908c2ecf20Sopenharmony_ci} 15918c2ecf20Sopenharmony_ci 15928c2ecf20Sopenharmony_ci#define steps(u) (((u) > 15) ? ((u)-16) : (u)) 15938c2ecf20Sopenharmony_ci#define INTERN_WAIT 10 15948c2ecf20Sopenharmony_cistatic int dib0090_get_offset(struct dib0090_state *state, enum frontend_tune_state *tune_state) 15958c2ecf20Sopenharmony_ci{ 15968c2ecf20Sopenharmony_ci int ret = INTERN_WAIT * 10; 15978c2ecf20Sopenharmony_ci 15988c2ecf20Sopenharmony_ci switch (*tune_state) { 15998c2ecf20Sopenharmony_ci case CT_TUNER_STEP_2: 16008c2ecf20Sopenharmony_ci /* Turns to positive */ 16018c2ecf20Sopenharmony_ci dib0090_write_reg(state, 0x1f, 0x7); 16028c2ecf20Sopenharmony_ci *tune_state = CT_TUNER_STEP_3; 16038c2ecf20Sopenharmony_ci break; 16048c2ecf20Sopenharmony_ci 16058c2ecf20Sopenharmony_ci case CT_TUNER_STEP_3: 16068c2ecf20Sopenharmony_ci state->adc_diff = dib0090_read_reg(state, 0x1d); 16078c2ecf20Sopenharmony_ci 16088c2ecf20Sopenharmony_ci /* Turns to negative */ 16098c2ecf20Sopenharmony_ci dib0090_write_reg(state, 0x1f, 0x4); 16108c2ecf20Sopenharmony_ci *tune_state = CT_TUNER_STEP_4; 16118c2ecf20Sopenharmony_ci break; 16128c2ecf20Sopenharmony_ci 16138c2ecf20Sopenharmony_ci case CT_TUNER_STEP_4: 16148c2ecf20Sopenharmony_ci state->adc_diff -= dib0090_read_reg(state, 0x1d); 16158c2ecf20Sopenharmony_ci *tune_state = CT_TUNER_STEP_5; 16168c2ecf20Sopenharmony_ci ret = 0; 16178c2ecf20Sopenharmony_ci break; 16188c2ecf20Sopenharmony_ci 16198c2ecf20Sopenharmony_ci default: 16208c2ecf20Sopenharmony_ci break; 16218c2ecf20Sopenharmony_ci } 16228c2ecf20Sopenharmony_ci 16238c2ecf20Sopenharmony_ci return ret; 16248c2ecf20Sopenharmony_ci} 16258c2ecf20Sopenharmony_ci 16268c2ecf20Sopenharmony_cistruct dc_calibration { 16278c2ecf20Sopenharmony_ci u8 addr; 16288c2ecf20Sopenharmony_ci u8 offset; 16298c2ecf20Sopenharmony_ci u8 pga:1; 16308c2ecf20Sopenharmony_ci u16 bb1; 16318c2ecf20Sopenharmony_ci u8 i:1; 16328c2ecf20Sopenharmony_ci}; 16338c2ecf20Sopenharmony_ci 16348c2ecf20Sopenharmony_cistatic const struct dc_calibration dc_table[] = { 16358c2ecf20Sopenharmony_ci /* Step1 BB gain1= 26 with boost 1, gain 2 = 0 */ 16368c2ecf20Sopenharmony_ci {0x06, 5, 1, (1 << 13) | (0 << 8) | (26 << 3), 1}, 16378c2ecf20Sopenharmony_ci {0x07, 11, 1, (1 << 13) | (0 << 8) | (26 << 3), 0}, 16388c2ecf20Sopenharmony_ci /* Step 2 BB gain 1 = 26 with boost = 1 & gain 2 = 29 */ 16398c2ecf20Sopenharmony_ci {0x06, 0, 0, (1 << 13) | (29 << 8) | (26 << 3), 1}, 16408c2ecf20Sopenharmony_ci {0x06, 10, 0, (1 << 13) | (29 << 8) | (26 << 3), 0}, 16418c2ecf20Sopenharmony_ci {0}, 16428c2ecf20Sopenharmony_ci}; 16438c2ecf20Sopenharmony_ci 16448c2ecf20Sopenharmony_cistatic const struct dc_calibration dc_p1g_table[] = { 16458c2ecf20Sopenharmony_ci /* Step1 BB gain1= 26 with boost 1, gain 2 = 0 */ 16468c2ecf20Sopenharmony_ci /* addr ; trim reg offset ; pga ; CTRL_BB1 value ; i or q */ 16478c2ecf20Sopenharmony_ci {0x06, 5, 1, (1 << 13) | (0 << 8) | (15 << 3), 1}, 16488c2ecf20Sopenharmony_ci {0x07, 11, 1, (1 << 13) | (0 << 8) | (15 << 3), 0}, 16498c2ecf20Sopenharmony_ci /* Step 2 BB gain 1 = 26 with boost = 1 & gain 2 = 29 */ 16508c2ecf20Sopenharmony_ci {0x06, 0, 0, (1 << 13) | (29 << 8) | (15 << 3), 1}, 16518c2ecf20Sopenharmony_ci {0x06, 10, 0, (1 << 13) | (29 << 8) | (15 << 3), 0}, 16528c2ecf20Sopenharmony_ci {0}, 16538c2ecf20Sopenharmony_ci}; 16548c2ecf20Sopenharmony_ci 16558c2ecf20Sopenharmony_cistatic void dib0090_set_trim(struct dib0090_state *state) 16568c2ecf20Sopenharmony_ci{ 16578c2ecf20Sopenharmony_ci u16 *val; 16588c2ecf20Sopenharmony_ci 16598c2ecf20Sopenharmony_ci if (state->dc->addr == 0x07) 16608c2ecf20Sopenharmony_ci val = &state->bb7; 16618c2ecf20Sopenharmony_ci else 16628c2ecf20Sopenharmony_ci val = &state->bb6; 16638c2ecf20Sopenharmony_ci 16648c2ecf20Sopenharmony_ci *val &= ~(0x1f << state->dc->offset); 16658c2ecf20Sopenharmony_ci *val |= state->step << state->dc->offset; 16668c2ecf20Sopenharmony_ci 16678c2ecf20Sopenharmony_ci dib0090_write_reg(state, state->dc->addr, *val); 16688c2ecf20Sopenharmony_ci} 16698c2ecf20Sopenharmony_ci 16708c2ecf20Sopenharmony_cistatic int dib0090_dc_offset_calibration(struct dib0090_state *state, enum frontend_tune_state *tune_state) 16718c2ecf20Sopenharmony_ci{ 16728c2ecf20Sopenharmony_ci int ret = 0; 16738c2ecf20Sopenharmony_ci u16 reg; 16748c2ecf20Sopenharmony_ci 16758c2ecf20Sopenharmony_ci switch (*tune_state) { 16768c2ecf20Sopenharmony_ci case CT_TUNER_START: 16778c2ecf20Sopenharmony_ci dprintk("Start DC offset calibration"); 16788c2ecf20Sopenharmony_ci 16798c2ecf20Sopenharmony_ci /* force vcm2 = 0.8V */ 16808c2ecf20Sopenharmony_ci state->bb6 = 0; 16818c2ecf20Sopenharmony_ci state->bb7 = 0x040d; 16828c2ecf20Sopenharmony_ci 16838c2ecf20Sopenharmony_ci /* the LNA AND LO are off */ 16848c2ecf20Sopenharmony_ci reg = dib0090_read_reg(state, 0x24) & 0x0ffb; /* shutdown lna and lo */ 16858c2ecf20Sopenharmony_ci dib0090_write_reg(state, 0x24, reg); 16868c2ecf20Sopenharmony_ci 16878c2ecf20Sopenharmony_ci state->wbdmux = dib0090_read_reg(state, 0x10); 16888c2ecf20Sopenharmony_ci dib0090_write_reg(state, 0x10, (state->wbdmux & ~(0xff << 3)) | (0x7 << 3) | 0x3); 16898c2ecf20Sopenharmony_ci dib0090_write_reg(state, 0x23, dib0090_read_reg(state, 0x23) & ~(1 << 14)); 16908c2ecf20Sopenharmony_ci 16918c2ecf20Sopenharmony_ci state->dc = dc_table; 16928c2ecf20Sopenharmony_ci 16938c2ecf20Sopenharmony_ci if (state->identity.p1g) 16948c2ecf20Sopenharmony_ci state->dc = dc_p1g_table; 16958c2ecf20Sopenharmony_ci 16968c2ecf20Sopenharmony_ci fallthrough; 16978c2ecf20Sopenharmony_ci case CT_TUNER_STEP_0: 16988c2ecf20Sopenharmony_ci dprintk("Start/continue DC calibration for %s path\n", 16998c2ecf20Sopenharmony_ci (state->dc->i == 1) ? "I" : "Q"); 17008c2ecf20Sopenharmony_ci dib0090_write_reg(state, 0x01, state->dc->bb1); 17018c2ecf20Sopenharmony_ci dib0090_write_reg(state, 0x07, state->bb7 | (state->dc->i << 7)); 17028c2ecf20Sopenharmony_ci 17038c2ecf20Sopenharmony_ci state->step = 0; 17048c2ecf20Sopenharmony_ci state->min_adc_diff = 1023; 17058c2ecf20Sopenharmony_ci *tune_state = CT_TUNER_STEP_1; 17068c2ecf20Sopenharmony_ci ret = 50; 17078c2ecf20Sopenharmony_ci break; 17088c2ecf20Sopenharmony_ci 17098c2ecf20Sopenharmony_ci case CT_TUNER_STEP_1: 17108c2ecf20Sopenharmony_ci dib0090_set_trim(state); 17118c2ecf20Sopenharmony_ci *tune_state = CT_TUNER_STEP_2; 17128c2ecf20Sopenharmony_ci break; 17138c2ecf20Sopenharmony_ci 17148c2ecf20Sopenharmony_ci case CT_TUNER_STEP_2: 17158c2ecf20Sopenharmony_ci case CT_TUNER_STEP_3: 17168c2ecf20Sopenharmony_ci case CT_TUNER_STEP_4: 17178c2ecf20Sopenharmony_ci ret = dib0090_get_offset(state, tune_state); 17188c2ecf20Sopenharmony_ci break; 17198c2ecf20Sopenharmony_ci 17208c2ecf20Sopenharmony_ci case CT_TUNER_STEP_5: /* found an offset */ 17218c2ecf20Sopenharmony_ci dprintk("adc_diff = %d, current step= %d\n", (u32) state->adc_diff, state->step); 17228c2ecf20Sopenharmony_ci if (state->step == 0 && state->adc_diff < 0) { 17238c2ecf20Sopenharmony_ci state->min_adc_diff = -1023; 17248c2ecf20Sopenharmony_ci dprintk("Change of sign of the minimum adc diff\n"); 17258c2ecf20Sopenharmony_ci } 17268c2ecf20Sopenharmony_ci 17278c2ecf20Sopenharmony_ci dprintk("adc_diff = %d, min_adc_diff = %d current_step = %d\n", state->adc_diff, state->min_adc_diff, state->step); 17288c2ecf20Sopenharmony_ci 17298c2ecf20Sopenharmony_ci /* first turn for this frequency */ 17308c2ecf20Sopenharmony_ci if (state->step == 0) { 17318c2ecf20Sopenharmony_ci if (state->dc->pga && state->adc_diff < 0) 17328c2ecf20Sopenharmony_ci state->step = 0x10; 17338c2ecf20Sopenharmony_ci if (state->dc->pga == 0 && state->adc_diff > 0) 17348c2ecf20Sopenharmony_ci state->step = 0x10; 17358c2ecf20Sopenharmony_ci } 17368c2ecf20Sopenharmony_ci 17378c2ecf20Sopenharmony_ci /* Look for a change of Sign in the Adc_diff.min_adc_diff is used to STORE the setp N-1 */ 17388c2ecf20Sopenharmony_ci if ((state->adc_diff & 0x8000) == (state->min_adc_diff & 0x8000) && steps(state->step) < 15) { 17398c2ecf20Sopenharmony_ci /* stop search when the delta the sign is changing and Steps =15 and Step=0 is force for continuance */ 17408c2ecf20Sopenharmony_ci state->step++; 17418c2ecf20Sopenharmony_ci state->min_adc_diff = state->adc_diff; 17428c2ecf20Sopenharmony_ci *tune_state = CT_TUNER_STEP_1; 17438c2ecf20Sopenharmony_ci } else { 17448c2ecf20Sopenharmony_ci /* the minimum was what we have seen in the step before */ 17458c2ecf20Sopenharmony_ci if (abs(state->adc_diff) > abs(state->min_adc_diff)) { 17468c2ecf20Sopenharmony_ci dprintk("Since adc_diff N = %d > adc_diff step N-1 = %d, Come back one step\n", state->adc_diff, state->min_adc_diff); 17478c2ecf20Sopenharmony_ci state->step--; 17488c2ecf20Sopenharmony_ci } 17498c2ecf20Sopenharmony_ci 17508c2ecf20Sopenharmony_ci dib0090_set_trim(state); 17518c2ecf20Sopenharmony_ci dprintk("BB Offset Cal, BBreg=%u,Offset=%d,Value Set=%d\n", 17528c2ecf20Sopenharmony_ci state->dc->addr, state->adc_diff, state->step); 17538c2ecf20Sopenharmony_ci 17548c2ecf20Sopenharmony_ci state->dc++; 17558c2ecf20Sopenharmony_ci if (state->dc->addr == 0) /* done */ 17568c2ecf20Sopenharmony_ci *tune_state = CT_TUNER_STEP_6; 17578c2ecf20Sopenharmony_ci else 17588c2ecf20Sopenharmony_ci *tune_state = CT_TUNER_STEP_0; 17598c2ecf20Sopenharmony_ci 17608c2ecf20Sopenharmony_ci } 17618c2ecf20Sopenharmony_ci break; 17628c2ecf20Sopenharmony_ci 17638c2ecf20Sopenharmony_ci case CT_TUNER_STEP_6: 17648c2ecf20Sopenharmony_ci dib0090_write_reg(state, 0x07, state->bb7 & ~0x0008); 17658c2ecf20Sopenharmony_ci dib0090_write_reg(state, 0x1f, 0x7); 17668c2ecf20Sopenharmony_ci *tune_state = CT_TUNER_START; /* reset done -> real tuning can now begin */ 17678c2ecf20Sopenharmony_ci state->calibrate &= ~DC_CAL; 17688c2ecf20Sopenharmony_ci default: 17698c2ecf20Sopenharmony_ci break; 17708c2ecf20Sopenharmony_ci } 17718c2ecf20Sopenharmony_ci return ret; 17728c2ecf20Sopenharmony_ci} 17738c2ecf20Sopenharmony_ci 17748c2ecf20Sopenharmony_cistatic int dib0090_wbd_calibration(struct dib0090_state *state, enum frontend_tune_state *tune_state) 17758c2ecf20Sopenharmony_ci{ 17768c2ecf20Sopenharmony_ci u8 wbd_gain; 17778c2ecf20Sopenharmony_ci const struct dib0090_wbd_slope *wbd = state->current_wbd_table; 17788c2ecf20Sopenharmony_ci 17798c2ecf20Sopenharmony_ci switch (*tune_state) { 17808c2ecf20Sopenharmony_ci case CT_TUNER_START: 17818c2ecf20Sopenharmony_ci while (state->current_rf / 1000 > wbd->max_freq) 17828c2ecf20Sopenharmony_ci wbd++; 17838c2ecf20Sopenharmony_ci if (wbd->wbd_gain != 0) 17848c2ecf20Sopenharmony_ci wbd_gain = wbd->wbd_gain; 17858c2ecf20Sopenharmony_ci else { 17868c2ecf20Sopenharmony_ci wbd_gain = 4; 17878c2ecf20Sopenharmony_ci#if defined(CONFIG_BAND_LBAND) || defined(CONFIG_BAND_SBAND) 17888c2ecf20Sopenharmony_ci if ((state->current_band == BAND_LBAND) || (state->current_band == BAND_SBAND)) 17898c2ecf20Sopenharmony_ci wbd_gain = 2; 17908c2ecf20Sopenharmony_ci#endif 17918c2ecf20Sopenharmony_ci } 17928c2ecf20Sopenharmony_ci 17938c2ecf20Sopenharmony_ci if (wbd_gain == state->wbd_calibration_gain) { /* the WBD calibration has already been done */ 17948c2ecf20Sopenharmony_ci *tune_state = CT_TUNER_START; 17958c2ecf20Sopenharmony_ci state->calibrate &= ~WBD_CAL; 17968c2ecf20Sopenharmony_ci return 0; 17978c2ecf20Sopenharmony_ci } 17988c2ecf20Sopenharmony_ci 17998c2ecf20Sopenharmony_ci dib0090_write_reg(state, 0x10, 0x1b81 | (1 << 10) | (wbd_gain << 13) | (1 << 3)); 18008c2ecf20Sopenharmony_ci 18018c2ecf20Sopenharmony_ci dib0090_write_reg(state, 0x24, ((EN_UHF & 0x0fff) | (1 << 1))); 18028c2ecf20Sopenharmony_ci *tune_state = CT_TUNER_STEP_0; 18038c2ecf20Sopenharmony_ci state->wbd_calibration_gain = wbd_gain; 18048c2ecf20Sopenharmony_ci return 90; /* wait for the WBDMUX to switch and for the ADC to sample */ 18058c2ecf20Sopenharmony_ci 18068c2ecf20Sopenharmony_ci case CT_TUNER_STEP_0: 18078c2ecf20Sopenharmony_ci state->wbd_offset = dib0090_get_slow_adc_val(state); 18088c2ecf20Sopenharmony_ci dprintk("WBD calibration offset = %d\n", state->wbd_offset); 18098c2ecf20Sopenharmony_ci *tune_state = CT_TUNER_START; /* reset done -> real tuning can now begin */ 18108c2ecf20Sopenharmony_ci state->calibrate &= ~WBD_CAL; 18118c2ecf20Sopenharmony_ci break; 18128c2ecf20Sopenharmony_ci 18138c2ecf20Sopenharmony_ci default: 18148c2ecf20Sopenharmony_ci break; 18158c2ecf20Sopenharmony_ci } 18168c2ecf20Sopenharmony_ci return 0; 18178c2ecf20Sopenharmony_ci} 18188c2ecf20Sopenharmony_ci 18198c2ecf20Sopenharmony_cistatic void dib0090_set_bandwidth(struct dib0090_state *state) 18208c2ecf20Sopenharmony_ci{ 18218c2ecf20Sopenharmony_ci u16 tmp; 18228c2ecf20Sopenharmony_ci 18238c2ecf20Sopenharmony_ci if (state->fe->dtv_property_cache.bandwidth_hz / 1000 <= 5000) 18248c2ecf20Sopenharmony_ci tmp = (3 << 14); 18258c2ecf20Sopenharmony_ci else if (state->fe->dtv_property_cache.bandwidth_hz / 1000 <= 6000) 18268c2ecf20Sopenharmony_ci tmp = (2 << 14); 18278c2ecf20Sopenharmony_ci else if (state->fe->dtv_property_cache.bandwidth_hz / 1000 <= 7000) 18288c2ecf20Sopenharmony_ci tmp = (1 << 14); 18298c2ecf20Sopenharmony_ci else 18308c2ecf20Sopenharmony_ci tmp = (0 << 14); 18318c2ecf20Sopenharmony_ci 18328c2ecf20Sopenharmony_ci state->bb_1_def &= 0x3fff; 18338c2ecf20Sopenharmony_ci state->bb_1_def |= tmp; 18348c2ecf20Sopenharmony_ci 18358c2ecf20Sopenharmony_ci dib0090_write_reg(state, 0x01, state->bb_1_def); /* be sure that we have the right bb-filter */ 18368c2ecf20Sopenharmony_ci 18378c2ecf20Sopenharmony_ci dib0090_write_reg(state, 0x03, 0x6008); /* = 0x6008 : vcm3_trim = 1 ; filter2_gm1_trim = 8 ; filter2_cutoff_freq = 0 */ 18388c2ecf20Sopenharmony_ci dib0090_write_reg(state, 0x04, 0x1); /* 0 = 1KHz ; 1 = 50Hz ; 2 = 150Hz ; 3 = 50KHz ; 4 = servo fast */ 18398c2ecf20Sopenharmony_ci if (state->identity.in_soc) { 18408c2ecf20Sopenharmony_ci dib0090_write_reg(state, 0x05, 0x9bcf); /* attenuator_ibias_tri = 2 ; input_stage_ibias_tr = 1 ; nc = 11 ; ext_gm_trim = 1 ; obuf_ibias_trim = 4 ; filter13_gm2_ibias_t = 15 */ 18418c2ecf20Sopenharmony_ci } else { 18428c2ecf20Sopenharmony_ci dib0090_write_reg(state, 0x02, (5 << 11) | (8 << 6) | (22 & 0x3f)); /* 22 = cap_value */ 18438c2ecf20Sopenharmony_ci dib0090_write_reg(state, 0x05, 0xabcd); /* = 0xabcd : attenuator_ibias_tri = 2 ; input_stage_ibias_tr = 2 ; nc = 11 ; ext_gm_trim = 1 ; obuf_ibias_trim = 4 ; filter13_gm2_ibias_t = 13 */ 18448c2ecf20Sopenharmony_ci } 18458c2ecf20Sopenharmony_ci} 18468c2ecf20Sopenharmony_ci 18478c2ecf20Sopenharmony_cistatic const struct dib0090_pll dib0090_pll_table[] = { 18488c2ecf20Sopenharmony_ci#ifdef CONFIG_BAND_CBAND 18498c2ecf20Sopenharmony_ci {56000, 0, 9, 48, 6}, 18508c2ecf20Sopenharmony_ci {70000, 1, 9, 48, 6}, 18518c2ecf20Sopenharmony_ci {87000, 0, 8, 32, 4}, 18528c2ecf20Sopenharmony_ci {105000, 1, 8, 32, 4}, 18538c2ecf20Sopenharmony_ci {115000, 0, 7, 24, 6}, 18548c2ecf20Sopenharmony_ci {140000, 1, 7, 24, 6}, 18558c2ecf20Sopenharmony_ci {170000, 0, 6, 16, 4}, 18568c2ecf20Sopenharmony_ci#endif 18578c2ecf20Sopenharmony_ci#ifdef CONFIG_BAND_VHF 18588c2ecf20Sopenharmony_ci {200000, 1, 6, 16, 4}, 18598c2ecf20Sopenharmony_ci {230000, 0, 5, 12, 6}, 18608c2ecf20Sopenharmony_ci {280000, 1, 5, 12, 6}, 18618c2ecf20Sopenharmony_ci {340000, 0, 4, 8, 4}, 18628c2ecf20Sopenharmony_ci {380000, 1, 4, 8, 4}, 18638c2ecf20Sopenharmony_ci {450000, 0, 3, 6, 6}, 18648c2ecf20Sopenharmony_ci#endif 18658c2ecf20Sopenharmony_ci#ifdef CONFIG_BAND_UHF 18668c2ecf20Sopenharmony_ci {580000, 1, 3, 6, 6}, 18678c2ecf20Sopenharmony_ci {700000, 0, 2, 4, 4}, 18688c2ecf20Sopenharmony_ci {860000, 1, 2, 4, 4}, 18698c2ecf20Sopenharmony_ci#endif 18708c2ecf20Sopenharmony_ci#ifdef CONFIG_BAND_LBAND 18718c2ecf20Sopenharmony_ci {1800000, 1, 0, 2, 4}, 18728c2ecf20Sopenharmony_ci#endif 18738c2ecf20Sopenharmony_ci#ifdef CONFIG_BAND_SBAND 18748c2ecf20Sopenharmony_ci {2900000, 0, 14, 1, 4}, 18758c2ecf20Sopenharmony_ci#endif 18768c2ecf20Sopenharmony_ci}; 18778c2ecf20Sopenharmony_ci 18788c2ecf20Sopenharmony_cistatic const struct dib0090_tuning dib0090_tuning_table_fm_vhf_on_cband[] = { 18798c2ecf20Sopenharmony_ci 18808c2ecf20Sopenharmony_ci#ifdef CONFIG_BAND_CBAND 18818c2ecf20Sopenharmony_ci {184000, 4, 1, 15, 0x280, 0x2912, 0xb94e, EN_CAB}, 18828c2ecf20Sopenharmony_ci {227000, 4, 3, 15, 0x280, 0x2912, 0xb94e, EN_CAB}, 18838c2ecf20Sopenharmony_ci {380000, 4, 7, 15, 0x280, 0x2912, 0xb94e, EN_CAB}, 18848c2ecf20Sopenharmony_ci#endif 18858c2ecf20Sopenharmony_ci#ifdef CONFIG_BAND_UHF 18868c2ecf20Sopenharmony_ci {520000, 2, 0, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF}, 18878c2ecf20Sopenharmony_ci {550000, 2, 2, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF}, 18888c2ecf20Sopenharmony_ci {650000, 2, 3, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF}, 18898c2ecf20Sopenharmony_ci {750000, 2, 5, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF}, 18908c2ecf20Sopenharmony_ci {850000, 2, 6, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF}, 18918c2ecf20Sopenharmony_ci {900000, 2, 7, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF}, 18928c2ecf20Sopenharmony_ci#endif 18938c2ecf20Sopenharmony_ci#ifdef CONFIG_BAND_LBAND 18948c2ecf20Sopenharmony_ci {1500000, 4, 0, 20, 0x300, 0x1912, 0x82c9, EN_LBD}, 18958c2ecf20Sopenharmony_ci {1600000, 4, 1, 20, 0x300, 0x1912, 0x82c9, EN_LBD}, 18968c2ecf20Sopenharmony_ci {1800000, 4, 3, 20, 0x300, 0x1912, 0x82c9, EN_LBD}, 18978c2ecf20Sopenharmony_ci#endif 18988c2ecf20Sopenharmony_ci#ifdef CONFIG_BAND_SBAND 18998c2ecf20Sopenharmony_ci {2300000, 1, 4, 20, 0x300, 0x2d2A, 0x82c7, EN_SBD}, 19008c2ecf20Sopenharmony_ci {2900000, 1, 7, 20, 0x280, 0x2deb, 0x8347, EN_SBD}, 19018c2ecf20Sopenharmony_ci#endif 19028c2ecf20Sopenharmony_ci}; 19038c2ecf20Sopenharmony_ci 19048c2ecf20Sopenharmony_cistatic const struct dib0090_tuning dib0090_tuning_table[] = { 19058c2ecf20Sopenharmony_ci 19068c2ecf20Sopenharmony_ci#ifdef CONFIG_BAND_CBAND 19078c2ecf20Sopenharmony_ci {170000, 4, 1, 15, 0x280, 0x2912, 0xb94e, EN_CAB}, 19088c2ecf20Sopenharmony_ci#endif 19098c2ecf20Sopenharmony_ci#ifdef CONFIG_BAND_VHF 19108c2ecf20Sopenharmony_ci {184000, 1, 1, 15, 0x300, 0x4d12, 0xb94e, EN_VHF}, 19118c2ecf20Sopenharmony_ci {227000, 1, 3, 15, 0x300, 0x4d12, 0xb94e, EN_VHF}, 19128c2ecf20Sopenharmony_ci {380000, 1, 7, 15, 0x300, 0x4d12, 0xb94e, EN_VHF}, 19138c2ecf20Sopenharmony_ci#endif 19148c2ecf20Sopenharmony_ci#ifdef CONFIG_BAND_UHF 19158c2ecf20Sopenharmony_ci {520000, 2, 0, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF}, 19168c2ecf20Sopenharmony_ci {550000, 2, 2, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF}, 19178c2ecf20Sopenharmony_ci {650000, 2, 3, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF}, 19188c2ecf20Sopenharmony_ci {750000, 2, 5, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF}, 19198c2ecf20Sopenharmony_ci {850000, 2, 6, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF}, 19208c2ecf20Sopenharmony_ci {900000, 2, 7, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF}, 19218c2ecf20Sopenharmony_ci#endif 19228c2ecf20Sopenharmony_ci#ifdef CONFIG_BAND_LBAND 19238c2ecf20Sopenharmony_ci {1500000, 4, 0, 20, 0x300, 0x1912, 0x82c9, EN_LBD}, 19248c2ecf20Sopenharmony_ci {1600000, 4, 1, 20, 0x300, 0x1912, 0x82c9, EN_LBD}, 19258c2ecf20Sopenharmony_ci {1800000, 4, 3, 20, 0x300, 0x1912, 0x82c9, EN_LBD}, 19268c2ecf20Sopenharmony_ci#endif 19278c2ecf20Sopenharmony_ci#ifdef CONFIG_BAND_SBAND 19288c2ecf20Sopenharmony_ci {2300000, 1, 4, 20, 0x300, 0x2d2A, 0x82c7, EN_SBD}, 19298c2ecf20Sopenharmony_ci {2900000, 1, 7, 20, 0x280, 0x2deb, 0x8347, EN_SBD}, 19308c2ecf20Sopenharmony_ci#endif 19318c2ecf20Sopenharmony_ci}; 19328c2ecf20Sopenharmony_ci 19338c2ecf20Sopenharmony_cistatic const struct dib0090_tuning dib0090_p1g_tuning_table[] = { 19348c2ecf20Sopenharmony_ci#ifdef CONFIG_BAND_CBAND 19358c2ecf20Sopenharmony_ci {170000, 4, 1, 0x820f, 0x300, 0x2d22, 0x82cb, EN_CAB}, 19368c2ecf20Sopenharmony_ci#endif 19378c2ecf20Sopenharmony_ci#ifdef CONFIG_BAND_VHF 19388c2ecf20Sopenharmony_ci {184000, 1, 1, 15, 0x300, 0x4d12, 0xb94e, EN_VHF}, 19398c2ecf20Sopenharmony_ci {227000, 1, 3, 15, 0x300, 0x4d12, 0xb94e, EN_VHF}, 19408c2ecf20Sopenharmony_ci {380000, 1, 7, 15, 0x300, 0x4d12, 0xb94e, EN_VHF}, 19418c2ecf20Sopenharmony_ci#endif 19428c2ecf20Sopenharmony_ci#ifdef CONFIG_BAND_UHF 19438c2ecf20Sopenharmony_ci {510000, 2, 0, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF}, 19448c2ecf20Sopenharmony_ci {540000, 2, 1, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF}, 19458c2ecf20Sopenharmony_ci {600000, 2, 3, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF}, 19468c2ecf20Sopenharmony_ci {630000, 2, 4, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF}, 19478c2ecf20Sopenharmony_ci {680000, 2, 5, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF}, 19488c2ecf20Sopenharmony_ci {720000, 2, 6, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF}, 19498c2ecf20Sopenharmony_ci {900000, 2, 7, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF}, 19508c2ecf20Sopenharmony_ci#endif 19518c2ecf20Sopenharmony_ci#ifdef CONFIG_BAND_LBAND 19528c2ecf20Sopenharmony_ci {1500000, 4, 0, 20, 0x300, 0x1912, 0x82c9, EN_LBD}, 19538c2ecf20Sopenharmony_ci {1600000, 4, 1, 20, 0x300, 0x1912, 0x82c9, EN_LBD}, 19548c2ecf20Sopenharmony_ci {1800000, 4, 3, 20, 0x300, 0x1912, 0x82c9, EN_LBD}, 19558c2ecf20Sopenharmony_ci#endif 19568c2ecf20Sopenharmony_ci#ifdef CONFIG_BAND_SBAND 19578c2ecf20Sopenharmony_ci {2300000, 1, 4, 20, 0x300, 0x2d2A, 0x82c7, EN_SBD}, 19588c2ecf20Sopenharmony_ci {2900000, 1, 7, 20, 0x280, 0x2deb, 0x8347, EN_SBD}, 19598c2ecf20Sopenharmony_ci#endif 19608c2ecf20Sopenharmony_ci}; 19618c2ecf20Sopenharmony_ci 19628c2ecf20Sopenharmony_cistatic const struct dib0090_pll dib0090_p1g_pll_table[] = { 19638c2ecf20Sopenharmony_ci#ifdef CONFIG_BAND_CBAND 19648c2ecf20Sopenharmony_ci {57000, 0, 11, 48, 6}, 19658c2ecf20Sopenharmony_ci {70000, 1, 11, 48, 6}, 19668c2ecf20Sopenharmony_ci {86000, 0, 10, 32, 4}, 19678c2ecf20Sopenharmony_ci {105000, 1, 10, 32, 4}, 19688c2ecf20Sopenharmony_ci {115000, 0, 9, 24, 6}, 19698c2ecf20Sopenharmony_ci {140000, 1, 9, 24, 6}, 19708c2ecf20Sopenharmony_ci {170000, 0, 8, 16, 4}, 19718c2ecf20Sopenharmony_ci#endif 19728c2ecf20Sopenharmony_ci#ifdef CONFIG_BAND_VHF 19738c2ecf20Sopenharmony_ci {200000, 1, 8, 16, 4}, 19748c2ecf20Sopenharmony_ci {230000, 0, 7, 12, 6}, 19758c2ecf20Sopenharmony_ci {280000, 1, 7, 12, 6}, 19768c2ecf20Sopenharmony_ci {340000, 0, 6, 8, 4}, 19778c2ecf20Sopenharmony_ci {380000, 1, 6, 8, 4}, 19788c2ecf20Sopenharmony_ci {455000, 0, 5, 6, 6}, 19798c2ecf20Sopenharmony_ci#endif 19808c2ecf20Sopenharmony_ci#ifdef CONFIG_BAND_UHF 19818c2ecf20Sopenharmony_ci {580000, 1, 5, 6, 6}, 19828c2ecf20Sopenharmony_ci {680000, 0, 4, 4, 4}, 19838c2ecf20Sopenharmony_ci {860000, 1, 4, 4, 4}, 19848c2ecf20Sopenharmony_ci#endif 19858c2ecf20Sopenharmony_ci#ifdef CONFIG_BAND_LBAND 19868c2ecf20Sopenharmony_ci {1800000, 1, 2, 2, 4}, 19878c2ecf20Sopenharmony_ci#endif 19888c2ecf20Sopenharmony_ci#ifdef CONFIG_BAND_SBAND 19898c2ecf20Sopenharmony_ci {2900000, 0, 1, 1, 6}, 19908c2ecf20Sopenharmony_ci#endif 19918c2ecf20Sopenharmony_ci}; 19928c2ecf20Sopenharmony_ci 19938c2ecf20Sopenharmony_cistatic const struct dib0090_tuning dib0090_p1g_tuning_table_fm_vhf_on_cband[] = { 19948c2ecf20Sopenharmony_ci#ifdef CONFIG_BAND_CBAND 19958c2ecf20Sopenharmony_ci {184000, 4, 3, 0x4187, 0x2c0, 0x2d22, 0x81cb, EN_CAB}, 19968c2ecf20Sopenharmony_ci {227000, 4, 3, 0x4187, 0x2c0, 0x2d22, 0x81cb, EN_CAB}, 19978c2ecf20Sopenharmony_ci {380000, 4, 3, 0x4187, 0x2c0, 0x2d22, 0x81cb, EN_CAB}, 19988c2ecf20Sopenharmony_ci#endif 19998c2ecf20Sopenharmony_ci#ifdef CONFIG_BAND_UHF 20008c2ecf20Sopenharmony_ci {520000, 2, 0, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF}, 20018c2ecf20Sopenharmony_ci {550000, 2, 2, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF}, 20028c2ecf20Sopenharmony_ci {650000, 2, 3, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF}, 20038c2ecf20Sopenharmony_ci {750000, 2, 5, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF}, 20048c2ecf20Sopenharmony_ci {850000, 2, 6, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF}, 20058c2ecf20Sopenharmony_ci {900000, 2, 7, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF}, 20068c2ecf20Sopenharmony_ci#endif 20078c2ecf20Sopenharmony_ci#ifdef CONFIG_BAND_LBAND 20088c2ecf20Sopenharmony_ci {1500000, 4, 0, 20, 0x300, 0x1912, 0x82c9, EN_LBD}, 20098c2ecf20Sopenharmony_ci {1600000, 4, 1, 20, 0x300, 0x1912, 0x82c9, EN_LBD}, 20108c2ecf20Sopenharmony_ci {1800000, 4, 3, 20, 0x300, 0x1912, 0x82c9, EN_LBD}, 20118c2ecf20Sopenharmony_ci#endif 20128c2ecf20Sopenharmony_ci#ifdef CONFIG_BAND_SBAND 20138c2ecf20Sopenharmony_ci {2300000, 1, 4, 20, 0x300, 0x2d2A, 0x82c7, EN_SBD}, 20148c2ecf20Sopenharmony_ci {2900000, 1, 7, 20, 0x280, 0x2deb, 0x8347, EN_SBD}, 20158c2ecf20Sopenharmony_ci#endif 20168c2ecf20Sopenharmony_ci}; 20178c2ecf20Sopenharmony_ci 20188c2ecf20Sopenharmony_cistatic const struct dib0090_tuning dib0090_tuning_table_cband_7090[] = { 20198c2ecf20Sopenharmony_ci#ifdef CONFIG_BAND_CBAND 20208c2ecf20Sopenharmony_ci {300000, 4, 3, 0x018F, 0x2c0, 0x2d22, 0xb9ce, EN_CAB}, 20218c2ecf20Sopenharmony_ci {380000, 4, 10, 0x018F, 0x2c0, 0x2d22, 0xb9ce, EN_CAB}, 20228c2ecf20Sopenharmony_ci {570000, 4, 10, 0x8190, 0x2c0, 0x2d22, 0xb9ce, EN_CAB}, 20238c2ecf20Sopenharmony_ci {858000, 4, 5, 0x8190, 0x2c0, 0x2d22, 0xb9ce, EN_CAB}, 20248c2ecf20Sopenharmony_ci#endif 20258c2ecf20Sopenharmony_ci}; 20268c2ecf20Sopenharmony_ci 20278c2ecf20Sopenharmony_cistatic const struct dib0090_tuning dib0090_tuning_table_cband_7090e_sensitivity[] = { 20288c2ecf20Sopenharmony_ci#ifdef CONFIG_BAND_CBAND 20298c2ecf20Sopenharmony_ci { 300000, 0 , 3, 0x8105, 0x2c0, 0x2d12, 0xb84e, EN_CAB }, 20308c2ecf20Sopenharmony_ci { 380000, 0 , 10, 0x810F, 0x2c0, 0x2d12, 0xb84e, EN_CAB }, 20318c2ecf20Sopenharmony_ci { 600000, 0 , 10, 0x815E, 0x280, 0x2d12, 0xb84e, EN_CAB }, 20328c2ecf20Sopenharmony_ci { 660000, 0 , 5, 0x85E3, 0x280, 0x2d12, 0xb84e, EN_CAB }, 20338c2ecf20Sopenharmony_ci { 720000, 0 , 5, 0x852E, 0x280, 0x2d12, 0xb84e, EN_CAB }, 20348c2ecf20Sopenharmony_ci { 860000, 0 , 4, 0x85E5, 0x280, 0x2d12, 0xb84e, EN_CAB }, 20358c2ecf20Sopenharmony_ci#endif 20368c2ecf20Sopenharmony_ci}; 20378c2ecf20Sopenharmony_ci 20388c2ecf20Sopenharmony_ciint dib0090_update_tuning_table_7090(struct dvb_frontend *fe, 20398c2ecf20Sopenharmony_ci u8 cfg_sensitivity) 20408c2ecf20Sopenharmony_ci{ 20418c2ecf20Sopenharmony_ci struct dib0090_state *state = fe->tuner_priv; 20428c2ecf20Sopenharmony_ci const struct dib0090_tuning *tune = 20438c2ecf20Sopenharmony_ci dib0090_tuning_table_cband_7090e_sensitivity; 20448c2ecf20Sopenharmony_ci static const struct dib0090_tuning dib0090_tuning_table_cband_7090e_aci[] = { 20458c2ecf20Sopenharmony_ci { 300000, 0 , 3, 0x8165, 0x2c0, 0x2d12, 0xb84e, EN_CAB }, 20468c2ecf20Sopenharmony_ci { 650000, 0 , 4, 0x815B, 0x280, 0x2d12, 0xb84e, EN_CAB }, 20478c2ecf20Sopenharmony_ci { 860000, 0 , 5, 0x84EF, 0x280, 0x2d12, 0xb84e, EN_CAB }, 20488c2ecf20Sopenharmony_ci }; 20498c2ecf20Sopenharmony_ci 20508c2ecf20Sopenharmony_ci if ((!state->identity.p1g) || (!state->identity.in_soc) 20518c2ecf20Sopenharmony_ci || ((state->identity.version != SOC_7090_P1G_21R1) 20528c2ecf20Sopenharmony_ci && (state->identity.version != SOC_7090_P1G_11R1))) { 20538c2ecf20Sopenharmony_ci dprintk("%s() function can only be used for dib7090\n", __func__); 20548c2ecf20Sopenharmony_ci return -ENODEV; 20558c2ecf20Sopenharmony_ci } 20568c2ecf20Sopenharmony_ci 20578c2ecf20Sopenharmony_ci if (cfg_sensitivity) 20588c2ecf20Sopenharmony_ci tune = dib0090_tuning_table_cband_7090e_sensitivity; 20598c2ecf20Sopenharmony_ci else 20608c2ecf20Sopenharmony_ci tune = dib0090_tuning_table_cband_7090e_aci; 20618c2ecf20Sopenharmony_ci 20628c2ecf20Sopenharmony_ci while (state->rf_request > tune->max_freq) 20638c2ecf20Sopenharmony_ci tune++; 20648c2ecf20Sopenharmony_ci 20658c2ecf20Sopenharmony_ci dib0090_write_reg(state, 0x09, (dib0090_read_reg(state, 0x09) & 0x8000) 20668c2ecf20Sopenharmony_ci | (tune->lna_bias & 0x7fff)); 20678c2ecf20Sopenharmony_ci dib0090_write_reg(state, 0x0b, (dib0090_read_reg(state, 0x0b) & 0xf83f) 20688c2ecf20Sopenharmony_ci | ((tune->lna_tune << 6) & 0x07c0)); 20698c2ecf20Sopenharmony_ci return 0; 20708c2ecf20Sopenharmony_ci} 20718c2ecf20Sopenharmony_ciEXPORT_SYMBOL(dib0090_update_tuning_table_7090); 20728c2ecf20Sopenharmony_ci 20738c2ecf20Sopenharmony_cistatic int dib0090_captrim_search(struct dib0090_state *state, enum frontend_tune_state *tune_state) 20748c2ecf20Sopenharmony_ci{ 20758c2ecf20Sopenharmony_ci int ret = 0; 20768c2ecf20Sopenharmony_ci u16 lo4 = 0xe900; 20778c2ecf20Sopenharmony_ci 20788c2ecf20Sopenharmony_ci s16 adc_target; 20798c2ecf20Sopenharmony_ci u16 adc; 20808c2ecf20Sopenharmony_ci s8 step_sign; 20818c2ecf20Sopenharmony_ci u8 force_soft_search = 0; 20828c2ecf20Sopenharmony_ci 20838c2ecf20Sopenharmony_ci if (state->identity.version == SOC_8090_P1G_11R1 || state->identity.version == SOC_8090_P1G_21R1) 20848c2ecf20Sopenharmony_ci force_soft_search = 1; 20858c2ecf20Sopenharmony_ci 20868c2ecf20Sopenharmony_ci if (*tune_state == CT_TUNER_START) { 20878c2ecf20Sopenharmony_ci dprintk("Start Captrim search : %s\n", 20888c2ecf20Sopenharmony_ci (force_soft_search == 1) ? "FORCE SOFT SEARCH" : "AUTO"); 20898c2ecf20Sopenharmony_ci dib0090_write_reg(state, 0x10, 0x2B1); 20908c2ecf20Sopenharmony_ci dib0090_write_reg(state, 0x1e, 0x0032); 20918c2ecf20Sopenharmony_ci 20928c2ecf20Sopenharmony_ci if (!state->tuner_is_tuned) { 20938c2ecf20Sopenharmony_ci /* prepare a complete captrim */ 20948c2ecf20Sopenharmony_ci if (!state->identity.p1g || force_soft_search) 20958c2ecf20Sopenharmony_ci state->step = state->captrim = state->fcaptrim = 64; 20968c2ecf20Sopenharmony_ci 20978c2ecf20Sopenharmony_ci state->current_rf = state->rf_request; 20988c2ecf20Sopenharmony_ci } else { /* we are already tuned to this frequency - the configuration is correct */ 20998c2ecf20Sopenharmony_ci if (!state->identity.p1g || force_soft_search) { 21008c2ecf20Sopenharmony_ci /* do a minimal captrim even if the frequency has not changed */ 21018c2ecf20Sopenharmony_ci state->step = 4; 21028c2ecf20Sopenharmony_ci state->captrim = state->fcaptrim = dib0090_read_reg(state, 0x18) & 0x7f; 21038c2ecf20Sopenharmony_ci } 21048c2ecf20Sopenharmony_ci } 21058c2ecf20Sopenharmony_ci state->adc_diff = 3000; 21068c2ecf20Sopenharmony_ci *tune_state = CT_TUNER_STEP_0; 21078c2ecf20Sopenharmony_ci 21088c2ecf20Sopenharmony_ci } else if (*tune_state == CT_TUNER_STEP_0) { 21098c2ecf20Sopenharmony_ci if (state->identity.p1g && !force_soft_search) { 21108c2ecf20Sopenharmony_ci u8 ratio = 31; 21118c2ecf20Sopenharmony_ci 21128c2ecf20Sopenharmony_ci dib0090_write_reg(state, 0x40, (3 << 7) | (ratio << 2) | (1 << 1) | 1); 21138c2ecf20Sopenharmony_ci dib0090_read_reg(state, 0x40); 21148c2ecf20Sopenharmony_ci ret = 50; 21158c2ecf20Sopenharmony_ci } else { 21168c2ecf20Sopenharmony_ci state->step /= 2; 21178c2ecf20Sopenharmony_ci dib0090_write_reg(state, 0x18, lo4 | state->captrim); 21188c2ecf20Sopenharmony_ci 21198c2ecf20Sopenharmony_ci if (state->identity.in_soc) 21208c2ecf20Sopenharmony_ci ret = 25; 21218c2ecf20Sopenharmony_ci } 21228c2ecf20Sopenharmony_ci *tune_state = CT_TUNER_STEP_1; 21238c2ecf20Sopenharmony_ci 21248c2ecf20Sopenharmony_ci } else if (*tune_state == CT_TUNER_STEP_1) { 21258c2ecf20Sopenharmony_ci if (state->identity.p1g && !force_soft_search) { 21268c2ecf20Sopenharmony_ci dib0090_write_reg(state, 0x40, 0x18c | (0 << 1) | 0); 21278c2ecf20Sopenharmony_ci dib0090_read_reg(state, 0x40); 21288c2ecf20Sopenharmony_ci 21298c2ecf20Sopenharmony_ci state->fcaptrim = dib0090_read_reg(state, 0x18) & 0x7F; 21308c2ecf20Sopenharmony_ci dprintk("***Final Captrim= 0x%x\n", state->fcaptrim); 21318c2ecf20Sopenharmony_ci *tune_state = CT_TUNER_STEP_3; 21328c2ecf20Sopenharmony_ci 21338c2ecf20Sopenharmony_ci } else { 21348c2ecf20Sopenharmony_ci /* MERGE for all krosus before P1G */ 21358c2ecf20Sopenharmony_ci adc = dib0090_get_slow_adc_val(state); 21368c2ecf20Sopenharmony_ci dprintk("CAPTRIM=%d; ADC = %d (ADC) & %dmV\n", (u32) state->captrim, (u32) adc, (u32) (adc) * (u32) 1800 / (u32) 1024); 21378c2ecf20Sopenharmony_ci 21388c2ecf20Sopenharmony_ci if (state->rest == 0 || state->identity.in_soc) { /* Just for 8090P SOCS where auto captrim HW bug : TO CHECK IN ACI for SOCS !!! if 400 for 8090p SOC => tune issue !!! */ 21398c2ecf20Sopenharmony_ci adc_target = 200; 21408c2ecf20Sopenharmony_ci } else 21418c2ecf20Sopenharmony_ci adc_target = 400; 21428c2ecf20Sopenharmony_ci 21438c2ecf20Sopenharmony_ci if (adc >= adc_target) { 21448c2ecf20Sopenharmony_ci adc -= adc_target; 21458c2ecf20Sopenharmony_ci step_sign = -1; 21468c2ecf20Sopenharmony_ci } else { 21478c2ecf20Sopenharmony_ci adc = adc_target - adc; 21488c2ecf20Sopenharmony_ci step_sign = 1; 21498c2ecf20Sopenharmony_ci } 21508c2ecf20Sopenharmony_ci 21518c2ecf20Sopenharmony_ci if (adc < state->adc_diff) { 21528c2ecf20Sopenharmony_ci dprintk("CAPTRIM=%d is closer to target (%d/%d)\n", (u32) state->captrim, (u32) adc, (u32) state->adc_diff); 21538c2ecf20Sopenharmony_ci state->adc_diff = adc; 21548c2ecf20Sopenharmony_ci state->fcaptrim = state->captrim; 21558c2ecf20Sopenharmony_ci } 21568c2ecf20Sopenharmony_ci 21578c2ecf20Sopenharmony_ci state->captrim += step_sign * state->step; 21588c2ecf20Sopenharmony_ci if (state->step >= 1) 21598c2ecf20Sopenharmony_ci *tune_state = CT_TUNER_STEP_0; 21608c2ecf20Sopenharmony_ci else 21618c2ecf20Sopenharmony_ci *tune_state = CT_TUNER_STEP_2; 21628c2ecf20Sopenharmony_ci 21638c2ecf20Sopenharmony_ci ret = 25; 21648c2ecf20Sopenharmony_ci } 21658c2ecf20Sopenharmony_ci } else if (*tune_state == CT_TUNER_STEP_2) { /* this step is only used by krosus < P1G */ 21668c2ecf20Sopenharmony_ci /*write the final cptrim config */ 21678c2ecf20Sopenharmony_ci dib0090_write_reg(state, 0x18, lo4 | state->fcaptrim); 21688c2ecf20Sopenharmony_ci 21698c2ecf20Sopenharmony_ci *tune_state = CT_TUNER_STEP_3; 21708c2ecf20Sopenharmony_ci 21718c2ecf20Sopenharmony_ci } else if (*tune_state == CT_TUNER_STEP_3) { 21728c2ecf20Sopenharmony_ci state->calibrate &= ~CAPTRIM_CAL; 21738c2ecf20Sopenharmony_ci *tune_state = CT_TUNER_STEP_0; 21748c2ecf20Sopenharmony_ci } 21758c2ecf20Sopenharmony_ci 21768c2ecf20Sopenharmony_ci return ret; 21778c2ecf20Sopenharmony_ci} 21788c2ecf20Sopenharmony_ci 21798c2ecf20Sopenharmony_cistatic int dib0090_get_temperature(struct dib0090_state *state, enum frontend_tune_state *tune_state) 21808c2ecf20Sopenharmony_ci{ 21818c2ecf20Sopenharmony_ci int ret = 15; 21828c2ecf20Sopenharmony_ci s16 val; 21838c2ecf20Sopenharmony_ci 21848c2ecf20Sopenharmony_ci switch (*tune_state) { 21858c2ecf20Sopenharmony_ci case CT_TUNER_START: 21868c2ecf20Sopenharmony_ci state->wbdmux = dib0090_read_reg(state, 0x10); 21878c2ecf20Sopenharmony_ci dib0090_write_reg(state, 0x10, (state->wbdmux & ~(0xff << 3)) | (0x8 << 3)); 21888c2ecf20Sopenharmony_ci 21898c2ecf20Sopenharmony_ci state->bias = dib0090_read_reg(state, 0x13); 21908c2ecf20Sopenharmony_ci dib0090_write_reg(state, 0x13, state->bias | (0x3 << 8)); 21918c2ecf20Sopenharmony_ci 21928c2ecf20Sopenharmony_ci *tune_state = CT_TUNER_STEP_0; 21938c2ecf20Sopenharmony_ci /* wait for the WBDMUX to switch and for the ADC to sample */ 21948c2ecf20Sopenharmony_ci break; 21958c2ecf20Sopenharmony_ci 21968c2ecf20Sopenharmony_ci case CT_TUNER_STEP_0: 21978c2ecf20Sopenharmony_ci state->adc_diff = dib0090_get_slow_adc_val(state); 21988c2ecf20Sopenharmony_ci dib0090_write_reg(state, 0x13, (state->bias & ~(0x3 << 8)) | (0x2 << 8)); 21998c2ecf20Sopenharmony_ci *tune_state = CT_TUNER_STEP_1; 22008c2ecf20Sopenharmony_ci break; 22018c2ecf20Sopenharmony_ci 22028c2ecf20Sopenharmony_ci case CT_TUNER_STEP_1: 22038c2ecf20Sopenharmony_ci val = dib0090_get_slow_adc_val(state); 22048c2ecf20Sopenharmony_ci state->temperature = ((s16) ((val - state->adc_diff) * 180) >> 8) + 55; 22058c2ecf20Sopenharmony_ci 22068c2ecf20Sopenharmony_ci dprintk("temperature: %d C\n", state->temperature - 30); 22078c2ecf20Sopenharmony_ci 22088c2ecf20Sopenharmony_ci *tune_state = CT_TUNER_STEP_2; 22098c2ecf20Sopenharmony_ci break; 22108c2ecf20Sopenharmony_ci 22118c2ecf20Sopenharmony_ci case CT_TUNER_STEP_2: 22128c2ecf20Sopenharmony_ci dib0090_write_reg(state, 0x13, state->bias); 22138c2ecf20Sopenharmony_ci dib0090_write_reg(state, 0x10, state->wbdmux); /* write back original WBDMUX */ 22148c2ecf20Sopenharmony_ci 22158c2ecf20Sopenharmony_ci *tune_state = CT_TUNER_START; 22168c2ecf20Sopenharmony_ci state->calibrate &= ~TEMP_CAL; 22178c2ecf20Sopenharmony_ci if (state->config->analog_output == 0) 22188c2ecf20Sopenharmony_ci dib0090_write_reg(state, 0x23, dib0090_read_reg(state, 0x23) | (1 << 14)); 22198c2ecf20Sopenharmony_ci 22208c2ecf20Sopenharmony_ci break; 22218c2ecf20Sopenharmony_ci 22228c2ecf20Sopenharmony_ci default: 22238c2ecf20Sopenharmony_ci ret = 0; 22248c2ecf20Sopenharmony_ci break; 22258c2ecf20Sopenharmony_ci } 22268c2ecf20Sopenharmony_ci return ret; 22278c2ecf20Sopenharmony_ci} 22288c2ecf20Sopenharmony_ci 22298c2ecf20Sopenharmony_ci#define WBD 0x781 /* 1 1 1 1 0000 0 0 1 */ 22308c2ecf20Sopenharmony_cistatic int dib0090_tune(struct dvb_frontend *fe) 22318c2ecf20Sopenharmony_ci{ 22328c2ecf20Sopenharmony_ci struct dib0090_state *state = fe->tuner_priv; 22338c2ecf20Sopenharmony_ci const struct dib0090_tuning *tune = state->current_tune_table_index; 22348c2ecf20Sopenharmony_ci const struct dib0090_pll *pll = state->current_pll_table_index; 22358c2ecf20Sopenharmony_ci enum frontend_tune_state *tune_state = &state->tune_state; 22368c2ecf20Sopenharmony_ci 22378c2ecf20Sopenharmony_ci u16 lo5, lo6, Den, tmp; 22388c2ecf20Sopenharmony_ci u32 FBDiv, Rest, FREF, VCOF_kHz = 0; 22398c2ecf20Sopenharmony_ci int ret = 10; /* 1ms is the default delay most of the time */ 22408c2ecf20Sopenharmony_ci u8 c, i; 22418c2ecf20Sopenharmony_ci 22428c2ecf20Sopenharmony_ci /************************* VCO ***************************/ 22438c2ecf20Sopenharmony_ci /* Default values for FG */ 22448c2ecf20Sopenharmony_ci /* from these are needed : */ 22458c2ecf20Sopenharmony_ci /* Cp,HFdiv,VCOband,SD,Num,Den,FB and REFDiv */ 22468c2ecf20Sopenharmony_ci 22478c2ecf20Sopenharmony_ci /* in any case we first need to do a calibration if needed */ 22488c2ecf20Sopenharmony_ci if (*tune_state == CT_TUNER_START) { 22498c2ecf20Sopenharmony_ci /* deactivate DataTX before some calibrations */ 22508c2ecf20Sopenharmony_ci if (state->calibrate & (DC_CAL | TEMP_CAL | WBD_CAL)) 22518c2ecf20Sopenharmony_ci dib0090_write_reg(state, 0x23, dib0090_read_reg(state, 0x23) & ~(1 << 14)); 22528c2ecf20Sopenharmony_ci else 22538c2ecf20Sopenharmony_ci /* Activate DataTX in case a calibration has been done before */ 22548c2ecf20Sopenharmony_ci if (state->config->analog_output == 0) 22558c2ecf20Sopenharmony_ci dib0090_write_reg(state, 0x23, dib0090_read_reg(state, 0x23) | (1 << 14)); 22568c2ecf20Sopenharmony_ci } 22578c2ecf20Sopenharmony_ci 22588c2ecf20Sopenharmony_ci if (state->calibrate & DC_CAL) 22598c2ecf20Sopenharmony_ci return dib0090_dc_offset_calibration(state, tune_state); 22608c2ecf20Sopenharmony_ci else if (state->calibrate & WBD_CAL) { 22618c2ecf20Sopenharmony_ci if (state->current_rf == 0) 22628c2ecf20Sopenharmony_ci state->current_rf = state->fe->dtv_property_cache.frequency / 1000; 22638c2ecf20Sopenharmony_ci return dib0090_wbd_calibration(state, tune_state); 22648c2ecf20Sopenharmony_ci } else if (state->calibrate & TEMP_CAL) 22658c2ecf20Sopenharmony_ci return dib0090_get_temperature(state, tune_state); 22668c2ecf20Sopenharmony_ci else if (state->calibrate & CAPTRIM_CAL) 22678c2ecf20Sopenharmony_ci return dib0090_captrim_search(state, tune_state); 22688c2ecf20Sopenharmony_ci 22698c2ecf20Sopenharmony_ci if (*tune_state == CT_TUNER_START) { 22708c2ecf20Sopenharmony_ci /* if soc and AGC pwm control, disengage mux to be able to R/W access to 0x01 register to set the right filter (cutoff_freq_select) during the tune sequence, otherwise, SOC SERPAR error when accessing to 0x01 */ 22718c2ecf20Sopenharmony_ci if (state->config->use_pwm_agc && state->identity.in_soc) { 22728c2ecf20Sopenharmony_ci tmp = dib0090_read_reg(state, 0x39); 22738c2ecf20Sopenharmony_ci if ((tmp >> 10) & 0x1) 22748c2ecf20Sopenharmony_ci dib0090_write_reg(state, 0x39, tmp & ~(1 << 10)); 22758c2ecf20Sopenharmony_ci } 22768c2ecf20Sopenharmony_ci 22778c2ecf20Sopenharmony_ci state->current_band = (u8) BAND_OF_FREQUENCY(state->fe->dtv_property_cache.frequency / 1000); 22788c2ecf20Sopenharmony_ci state->rf_request = 22798c2ecf20Sopenharmony_ci state->fe->dtv_property_cache.frequency / 1000 + (state->current_band == 22808c2ecf20Sopenharmony_ci BAND_UHF ? state->config->freq_offset_khz_uhf : state->config-> 22818c2ecf20Sopenharmony_ci freq_offset_khz_vhf); 22828c2ecf20Sopenharmony_ci 22838c2ecf20Sopenharmony_ci /* in ISDB-T 1seg we shift tuning frequency */ 22848c2ecf20Sopenharmony_ci if ((state->fe->dtv_property_cache.delivery_system == SYS_ISDBT && state->fe->dtv_property_cache.isdbt_sb_mode == 1 22858c2ecf20Sopenharmony_ci && state->fe->dtv_property_cache.isdbt_partial_reception == 0)) { 22868c2ecf20Sopenharmony_ci const struct dib0090_low_if_offset_table *LUT_offset = state->config->low_if; 22878c2ecf20Sopenharmony_ci u8 found_offset = 0; 22888c2ecf20Sopenharmony_ci u32 margin_khz = 100; 22898c2ecf20Sopenharmony_ci 22908c2ecf20Sopenharmony_ci if (LUT_offset != NULL) { 22918c2ecf20Sopenharmony_ci while (LUT_offset->RF_freq != 0xffff) { 22928c2ecf20Sopenharmony_ci if (((state->rf_request > (LUT_offset->RF_freq - margin_khz)) 22938c2ecf20Sopenharmony_ci && (state->rf_request < (LUT_offset->RF_freq + margin_khz))) 22948c2ecf20Sopenharmony_ci && LUT_offset->std == state->fe->dtv_property_cache.delivery_system) { 22958c2ecf20Sopenharmony_ci state->rf_request += LUT_offset->offset_khz; 22968c2ecf20Sopenharmony_ci found_offset = 1; 22978c2ecf20Sopenharmony_ci break; 22988c2ecf20Sopenharmony_ci } 22998c2ecf20Sopenharmony_ci LUT_offset++; 23008c2ecf20Sopenharmony_ci } 23018c2ecf20Sopenharmony_ci } 23028c2ecf20Sopenharmony_ci 23038c2ecf20Sopenharmony_ci if (found_offset == 0) 23048c2ecf20Sopenharmony_ci state->rf_request += 400; 23058c2ecf20Sopenharmony_ci } 23068c2ecf20Sopenharmony_ci if (state->current_rf != state->rf_request || (state->current_standard != state->fe->dtv_property_cache.delivery_system)) { 23078c2ecf20Sopenharmony_ci state->tuner_is_tuned = 0; 23088c2ecf20Sopenharmony_ci state->current_rf = 0; 23098c2ecf20Sopenharmony_ci state->current_standard = 0; 23108c2ecf20Sopenharmony_ci 23118c2ecf20Sopenharmony_ci tune = dib0090_tuning_table; 23128c2ecf20Sopenharmony_ci if (state->identity.p1g) 23138c2ecf20Sopenharmony_ci tune = dib0090_p1g_tuning_table; 23148c2ecf20Sopenharmony_ci 23158c2ecf20Sopenharmony_ci tmp = (state->identity.version >> 5) & 0x7; 23168c2ecf20Sopenharmony_ci 23178c2ecf20Sopenharmony_ci if (state->identity.in_soc) { 23188c2ecf20Sopenharmony_ci if (state->config->force_cband_input) { /* Use the CBAND input for all band */ 23198c2ecf20Sopenharmony_ci if (state->current_band & BAND_CBAND || state->current_band & BAND_FM || state->current_band & BAND_VHF 23208c2ecf20Sopenharmony_ci || state->current_band & BAND_UHF) { 23218c2ecf20Sopenharmony_ci state->current_band = BAND_CBAND; 23228c2ecf20Sopenharmony_ci if (state->config->is_dib7090e) 23238c2ecf20Sopenharmony_ci tune = dib0090_tuning_table_cband_7090e_sensitivity; 23248c2ecf20Sopenharmony_ci else 23258c2ecf20Sopenharmony_ci tune = dib0090_tuning_table_cband_7090; 23268c2ecf20Sopenharmony_ci } 23278c2ecf20Sopenharmony_ci } else { /* Use the CBAND input for all band under UHF */ 23288c2ecf20Sopenharmony_ci if (state->current_band & BAND_CBAND || state->current_band & BAND_FM || state->current_band & BAND_VHF) { 23298c2ecf20Sopenharmony_ci state->current_band = BAND_CBAND; 23308c2ecf20Sopenharmony_ci if (state->config->is_dib7090e) 23318c2ecf20Sopenharmony_ci tune = dib0090_tuning_table_cband_7090e_sensitivity; 23328c2ecf20Sopenharmony_ci else 23338c2ecf20Sopenharmony_ci tune = dib0090_tuning_table_cband_7090; 23348c2ecf20Sopenharmony_ci } 23358c2ecf20Sopenharmony_ci } 23368c2ecf20Sopenharmony_ci } else 23378c2ecf20Sopenharmony_ci if (tmp == 0x4 || tmp == 0x7) { 23388c2ecf20Sopenharmony_ci /* CBAND tuner version for VHF */ 23398c2ecf20Sopenharmony_ci if (state->current_band == BAND_FM || state->current_band == BAND_CBAND || state->current_band == BAND_VHF) { 23408c2ecf20Sopenharmony_ci state->current_band = BAND_CBAND; /* Force CBAND */ 23418c2ecf20Sopenharmony_ci 23428c2ecf20Sopenharmony_ci tune = dib0090_tuning_table_fm_vhf_on_cband; 23438c2ecf20Sopenharmony_ci if (state->identity.p1g) 23448c2ecf20Sopenharmony_ci tune = dib0090_p1g_tuning_table_fm_vhf_on_cband; 23458c2ecf20Sopenharmony_ci } 23468c2ecf20Sopenharmony_ci } 23478c2ecf20Sopenharmony_ci 23488c2ecf20Sopenharmony_ci pll = dib0090_pll_table; 23498c2ecf20Sopenharmony_ci if (state->identity.p1g) 23508c2ecf20Sopenharmony_ci pll = dib0090_p1g_pll_table; 23518c2ecf20Sopenharmony_ci 23528c2ecf20Sopenharmony_ci /* Look for the interval */ 23538c2ecf20Sopenharmony_ci while (state->rf_request > tune->max_freq) 23548c2ecf20Sopenharmony_ci tune++; 23558c2ecf20Sopenharmony_ci while (state->rf_request > pll->max_freq) 23568c2ecf20Sopenharmony_ci pll++; 23578c2ecf20Sopenharmony_ci 23588c2ecf20Sopenharmony_ci state->current_tune_table_index = tune; 23598c2ecf20Sopenharmony_ci state->current_pll_table_index = pll; 23608c2ecf20Sopenharmony_ci 23618c2ecf20Sopenharmony_ci dib0090_write_reg(state, 0x0b, 0xb800 | (tune->switch_trim)); 23628c2ecf20Sopenharmony_ci 23638c2ecf20Sopenharmony_ci VCOF_kHz = (pll->hfdiv * state->rf_request) * 2; 23648c2ecf20Sopenharmony_ci 23658c2ecf20Sopenharmony_ci FREF = state->config->io.clock_khz; 23668c2ecf20Sopenharmony_ci if (state->config->fref_clock_ratio != 0) 23678c2ecf20Sopenharmony_ci FREF /= state->config->fref_clock_ratio; 23688c2ecf20Sopenharmony_ci 23698c2ecf20Sopenharmony_ci FBDiv = (VCOF_kHz / pll->topresc / FREF); 23708c2ecf20Sopenharmony_ci Rest = (VCOF_kHz / pll->topresc) - FBDiv * FREF; 23718c2ecf20Sopenharmony_ci 23728c2ecf20Sopenharmony_ci if (Rest < LPF) 23738c2ecf20Sopenharmony_ci Rest = 0; 23748c2ecf20Sopenharmony_ci else if (Rest < 2 * LPF) 23758c2ecf20Sopenharmony_ci Rest = 2 * LPF; 23768c2ecf20Sopenharmony_ci else if (Rest > (FREF - LPF)) { 23778c2ecf20Sopenharmony_ci Rest = 0; 23788c2ecf20Sopenharmony_ci FBDiv += 1; 23798c2ecf20Sopenharmony_ci } else if (Rest > (FREF - 2 * LPF)) 23808c2ecf20Sopenharmony_ci Rest = FREF - 2 * LPF; 23818c2ecf20Sopenharmony_ci Rest = (Rest * 6528) / (FREF / 10); 23828c2ecf20Sopenharmony_ci state->rest = Rest; 23838c2ecf20Sopenharmony_ci 23848c2ecf20Sopenharmony_ci /* external loop filter, otherwise: 23858c2ecf20Sopenharmony_ci * lo5 = (0 << 15) | (0 << 12) | (0 << 11) | (3 << 9) | (4 << 6) | (3 << 4) | 4; 23868c2ecf20Sopenharmony_ci * lo6 = 0x0e34 */ 23878c2ecf20Sopenharmony_ci 23888c2ecf20Sopenharmony_ci if (Rest == 0) { 23898c2ecf20Sopenharmony_ci if (pll->vco_band) 23908c2ecf20Sopenharmony_ci lo5 = 0x049f; 23918c2ecf20Sopenharmony_ci else 23928c2ecf20Sopenharmony_ci lo5 = 0x041f; 23938c2ecf20Sopenharmony_ci } else { 23948c2ecf20Sopenharmony_ci if (pll->vco_band) 23958c2ecf20Sopenharmony_ci lo5 = 0x049e; 23968c2ecf20Sopenharmony_ci else if (state->config->analog_output) 23978c2ecf20Sopenharmony_ci lo5 = 0x041d; 23988c2ecf20Sopenharmony_ci else 23998c2ecf20Sopenharmony_ci lo5 = 0x041c; 24008c2ecf20Sopenharmony_ci } 24018c2ecf20Sopenharmony_ci 24028c2ecf20Sopenharmony_ci if (state->identity.p1g) { /* Bias is done automatically in P1G */ 24038c2ecf20Sopenharmony_ci if (state->identity.in_soc) { 24048c2ecf20Sopenharmony_ci if (state->identity.version == SOC_8090_P1G_11R1) 24058c2ecf20Sopenharmony_ci lo5 = 0x46f; 24068c2ecf20Sopenharmony_ci else 24078c2ecf20Sopenharmony_ci lo5 = 0x42f; 24088c2ecf20Sopenharmony_ci } else 24098c2ecf20Sopenharmony_ci lo5 = 0x42c; 24108c2ecf20Sopenharmony_ci } 24118c2ecf20Sopenharmony_ci 24128c2ecf20Sopenharmony_ci lo5 |= (pll->hfdiv_code << 11) | (pll->vco_band << 7); /* bit 15 is the split to the slave, we do not do it here */ 24138c2ecf20Sopenharmony_ci 24148c2ecf20Sopenharmony_ci if (!state->config->io.pll_int_loop_filt) { 24158c2ecf20Sopenharmony_ci if (state->identity.in_soc) 24168c2ecf20Sopenharmony_ci lo6 = 0xff98; 24178c2ecf20Sopenharmony_ci else if (state->identity.p1g || (Rest == 0)) 24188c2ecf20Sopenharmony_ci lo6 = 0xfff8; 24198c2ecf20Sopenharmony_ci else 24208c2ecf20Sopenharmony_ci lo6 = 0xff28; 24218c2ecf20Sopenharmony_ci } else 24228c2ecf20Sopenharmony_ci lo6 = (state->config->io.pll_int_loop_filt << 3); 24238c2ecf20Sopenharmony_ci 24248c2ecf20Sopenharmony_ci Den = 1; 24258c2ecf20Sopenharmony_ci 24268c2ecf20Sopenharmony_ci if (Rest > 0) { 24278c2ecf20Sopenharmony_ci lo6 |= (1 << 2) | 2; 24288c2ecf20Sopenharmony_ci Den = 255; 24298c2ecf20Sopenharmony_ci } 24308c2ecf20Sopenharmony_ci dib0090_write_reg(state, 0x15, (u16) FBDiv); 24318c2ecf20Sopenharmony_ci if (state->config->fref_clock_ratio != 0) 24328c2ecf20Sopenharmony_ci dib0090_write_reg(state, 0x16, (Den << 8) | state->config->fref_clock_ratio); 24338c2ecf20Sopenharmony_ci else 24348c2ecf20Sopenharmony_ci dib0090_write_reg(state, 0x16, (Den << 8) | 1); 24358c2ecf20Sopenharmony_ci dib0090_write_reg(state, 0x17, (u16) Rest); 24368c2ecf20Sopenharmony_ci dib0090_write_reg(state, 0x19, lo5); 24378c2ecf20Sopenharmony_ci dib0090_write_reg(state, 0x1c, lo6); 24388c2ecf20Sopenharmony_ci 24398c2ecf20Sopenharmony_ci lo6 = tune->tuner_enable; 24408c2ecf20Sopenharmony_ci if (state->config->analog_output) 24418c2ecf20Sopenharmony_ci lo6 = (lo6 & 0xff9f) | 0x2; 24428c2ecf20Sopenharmony_ci 24438c2ecf20Sopenharmony_ci dib0090_write_reg(state, 0x24, lo6 | EN_LO | state->config->use_pwm_agc * EN_CRYSTAL); 24448c2ecf20Sopenharmony_ci 24458c2ecf20Sopenharmony_ci } 24468c2ecf20Sopenharmony_ci 24478c2ecf20Sopenharmony_ci state->current_rf = state->rf_request; 24488c2ecf20Sopenharmony_ci state->current_standard = state->fe->dtv_property_cache.delivery_system; 24498c2ecf20Sopenharmony_ci 24508c2ecf20Sopenharmony_ci ret = 20; 24518c2ecf20Sopenharmony_ci state->calibrate = CAPTRIM_CAL; /* captrim search now */ 24528c2ecf20Sopenharmony_ci } 24538c2ecf20Sopenharmony_ci 24548c2ecf20Sopenharmony_ci else if (*tune_state == CT_TUNER_STEP_0) { /* Warning : because of captrim cal, if you change this step, change it also in _cal.c file because it is the step following captrim cal state machine */ 24558c2ecf20Sopenharmony_ci const struct dib0090_wbd_slope *wbd = state->current_wbd_table; 24568c2ecf20Sopenharmony_ci 24578c2ecf20Sopenharmony_ci while (state->current_rf / 1000 > wbd->max_freq) 24588c2ecf20Sopenharmony_ci wbd++; 24598c2ecf20Sopenharmony_ci 24608c2ecf20Sopenharmony_ci dib0090_write_reg(state, 0x1e, 0x07ff); 24618c2ecf20Sopenharmony_ci dprintk("Final Captrim: %d\n", (u32) state->fcaptrim); 24628c2ecf20Sopenharmony_ci dprintk("HFDIV code: %d\n", (u32) pll->hfdiv_code); 24638c2ecf20Sopenharmony_ci dprintk("VCO = %d\n", (u32) pll->vco_band); 24648c2ecf20Sopenharmony_ci dprintk("VCOF in kHz: %d ((%d*%d) << 1))\n", (u32) ((pll->hfdiv * state->rf_request) * 2), (u32) pll->hfdiv, (u32) state->rf_request); 24658c2ecf20Sopenharmony_ci dprintk("REFDIV: %d, FREF: %d\n", (u32) 1, (u32) state->config->io.clock_khz); 24668c2ecf20Sopenharmony_ci dprintk("FBDIV: %d, Rest: %d\n", (u32) dib0090_read_reg(state, 0x15), (u32) dib0090_read_reg(state, 0x17)); 24678c2ecf20Sopenharmony_ci dprintk("Num: %d, Den: %d, SD: %d\n", (u32) dib0090_read_reg(state, 0x17), (u32) (dib0090_read_reg(state, 0x16) >> 8), 24688c2ecf20Sopenharmony_ci (u32) dib0090_read_reg(state, 0x1c) & 0x3); 24698c2ecf20Sopenharmony_ci 24708c2ecf20Sopenharmony_ci#define WBD 0x781 /* 1 1 1 1 0000 0 0 1 */ 24718c2ecf20Sopenharmony_ci c = 4; 24728c2ecf20Sopenharmony_ci i = 3; 24738c2ecf20Sopenharmony_ci 24748c2ecf20Sopenharmony_ci if (wbd->wbd_gain != 0) 24758c2ecf20Sopenharmony_ci c = wbd->wbd_gain; 24768c2ecf20Sopenharmony_ci 24778c2ecf20Sopenharmony_ci state->wbdmux = (c << 13) | (i << 11) | (WBD | (state->config->use_pwm_agc << 1)); 24788c2ecf20Sopenharmony_ci dib0090_write_reg(state, 0x10, state->wbdmux); 24798c2ecf20Sopenharmony_ci 24808c2ecf20Sopenharmony_ci if ((tune->tuner_enable == EN_CAB) && state->identity.p1g) { 24818c2ecf20Sopenharmony_ci dprintk("P1G : The cable band is selected and lna_tune = %d\n", tune->lna_tune); 24828c2ecf20Sopenharmony_ci dib0090_write_reg(state, 0x09, tune->lna_bias); 24838c2ecf20Sopenharmony_ci dib0090_write_reg(state, 0x0b, 0xb800 | (tune->lna_tune << 6) | (tune->switch_trim)); 24848c2ecf20Sopenharmony_ci } else 24858c2ecf20Sopenharmony_ci dib0090_write_reg(state, 0x09, (tune->lna_tune << 5) | tune->lna_bias); 24868c2ecf20Sopenharmony_ci 24878c2ecf20Sopenharmony_ci dib0090_write_reg(state, 0x0c, tune->v2i); 24888c2ecf20Sopenharmony_ci dib0090_write_reg(state, 0x0d, tune->mix); 24898c2ecf20Sopenharmony_ci dib0090_write_reg(state, 0x0e, tune->load); 24908c2ecf20Sopenharmony_ci *tune_state = CT_TUNER_STEP_1; 24918c2ecf20Sopenharmony_ci 24928c2ecf20Sopenharmony_ci } else if (*tune_state == CT_TUNER_STEP_1) { 24938c2ecf20Sopenharmony_ci /* initialize the lt gain register */ 24948c2ecf20Sopenharmony_ci state->rf_lt_def = 0x7c00; 24958c2ecf20Sopenharmony_ci 24968c2ecf20Sopenharmony_ci dib0090_set_bandwidth(state); 24978c2ecf20Sopenharmony_ci state->tuner_is_tuned = 1; 24988c2ecf20Sopenharmony_ci 24998c2ecf20Sopenharmony_ci state->calibrate |= WBD_CAL; 25008c2ecf20Sopenharmony_ci state->calibrate |= TEMP_CAL; 25018c2ecf20Sopenharmony_ci *tune_state = CT_TUNER_STOP; 25028c2ecf20Sopenharmony_ci } else 25038c2ecf20Sopenharmony_ci ret = FE_CALLBACK_TIME_NEVER; 25048c2ecf20Sopenharmony_ci return ret; 25058c2ecf20Sopenharmony_ci} 25068c2ecf20Sopenharmony_ci 25078c2ecf20Sopenharmony_cistatic void dib0090_release(struct dvb_frontend *fe) 25088c2ecf20Sopenharmony_ci{ 25098c2ecf20Sopenharmony_ci kfree(fe->tuner_priv); 25108c2ecf20Sopenharmony_ci fe->tuner_priv = NULL; 25118c2ecf20Sopenharmony_ci} 25128c2ecf20Sopenharmony_ci 25138c2ecf20Sopenharmony_cienum frontend_tune_state dib0090_get_tune_state(struct dvb_frontend *fe) 25148c2ecf20Sopenharmony_ci{ 25158c2ecf20Sopenharmony_ci struct dib0090_state *state = fe->tuner_priv; 25168c2ecf20Sopenharmony_ci 25178c2ecf20Sopenharmony_ci return state->tune_state; 25188c2ecf20Sopenharmony_ci} 25198c2ecf20Sopenharmony_ci 25208c2ecf20Sopenharmony_ciEXPORT_SYMBOL(dib0090_get_tune_state); 25218c2ecf20Sopenharmony_ci 25228c2ecf20Sopenharmony_ciint dib0090_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state) 25238c2ecf20Sopenharmony_ci{ 25248c2ecf20Sopenharmony_ci struct dib0090_state *state = fe->tuner_priv; 25258c2ecf20Sopenharmony_ci 25268c2ecf20Sopenharmony_ci state->tune_state = tune_state; 25278c2ecf20Sopenharmony_ci return 0; 25288c2ecf20Sopenharmony_ci} 25298c2ecf20Sopenharmony_ci 25308c2ecf20Sopenharmony_ciEXPORT_SYMBOL(dib0090_set_tune_state); 25318c2ecf20Sopenharmony_ci 25328c2ecf20Sopenharmony_cistatic int dib0090_get_frequency(struct dvb_frontend *fe, u32 * frequency) 25338c2ecf20Sopenharmony_ci{ 25348c2ecf20Sopenharmony_ci struct dib0090_state *state = fe->tuner_priv; 25358c2ecf20Sopenharmony_ci 25368c2ecf20Sopenharmony_ci *frequency = 1000 * state->current_rf; 25378c2ecf20Sopenharmony_ci return 0; 25388c2ecf20Sopenharmony_ci} 25398c2ecf20Sopenharmony_ci 25408c2ecf20Sopenharmony_cistatic int dib0090_set_params(struct dvb_frontend *fe) 25418c2ecf20Sopenharmony_ci{ 25428c2ecf20Sopenharmony_ci struct dib0090_state *state = fe->tuner_priv; 25438c2ecf20Sopenharmony_ci u32 ret; 25448c2ecf20Sopenharmony_ci 25458c2ecf20Sopenharmony_ci state->tune_state = CT_TUNER_START; 25468c2ecf20Sopenharmony_ci 25478c2ecf20Sopenharmony_ci do { 25488c2ecf20Sopenharmony_ci ret = dib0090_tune(fe); 25498c2ecf20Sopenharmony_ci if (ret == FE_CALLBACK_TIME_NEVER) 25508c2ecf20Sopenharmony_ci break; 25518c2ecf20Sopenharmony_ci 25528c2ecf20Sopenharmony_ci /* 25538c2ecf20Sopenharmony_ci * Despite dib0090_tune returns time at a 0.1 ms range, 25548c2ecf20Sopenharmony_ci * the actual sleep time depends on CONFIG_HZ. The worse case 25558c2ecf20Sopenharmony_ci * is when CONFIG_HZ=100. In such case, the minimum granularity 25568c2ecf20Sopenharmony_ci * is 10ms. On some real field tests, the tuner sometimes don't 25578c2ecf20Sopenharmony_ci * lock when this timer is lower than 10ms. So, enforce a 10ms 25588c2ecf20Sopenharmony_ci * granularity and use usleep_range() instead of msleep(). 25598c2ecf20Sopenharmony_ci */ 25608c2ecf20Sopenharmony_ci ret = 10 * (ret + 99)/100; 25618c2ecf20Sopenharmony_ci usleep_range(ret * 1000, (ret + 1) * 1000); 25628c2ecf20Sopenharmony_ci } while (state->tune_state != CT_TUNER_STOP); 25638c2ecf20Sopenharmony_ci 25648c2ecf20Sopenharmony_ci return 0; 25658c2ecf20Sopenharmony_ci} 25668c2ecf20Sopenharmony_ci 25678c2ecf20Sopenharmony_cistatic const struct dvb_tuner_ops dib0090_ops = { 25688c2ecf20Sopenharmony_ci .info = { 25698c2ecf20Sopenharmony_ci .name = "DiBcom DiB0090", 25708c2ecf20Sopenharmony_ci .frequency_min_hz = 45 * MHz, 25718c2ecf20Sopenharmony_ci .frequency_max_hz = 860 * MHz, 25728c2ecf20Sopenharmony_ci .frequency_step_hz = 1 * kHz, 25738c2ecf20Sopenharmony_ci }, 25748c2ecf20Sopenharmony_ci .release = dib0090_release, 25758c2ecf20Sopenharmony_ci 25768c2ecf20Sopenharmony_ci .init = dib0090_wakeup, 25778c2ecf20Sopenharmony_ci .sleep = dib0090_sleep, 25788c2ecf20Sopenharmony_ci .set_params = dib0090_set_params, 25798c2ecf20Sopenharmony_ci .get_frequency = dib0090_get_frequency, 25808c2ecf20Sopenharmony_ci}; 25818c2ecf20Sopenharmony_ci 25828c2ecf20Sopenharmony_cistatic const struct dvb_tuner_ops dib0090_fw_ops = { 25838c2ecf20Sopenharmony_ci .info = { 25848c2ecf20Sopenharmony_ci .name = "DiBcom DiB0090", 25858c2ecf20Sopenharmony_ci .frequency_min_hz = 45 * MHz, 25868c2ecf20Sopenharmony_ci .frequency_max_hz = 860 * MHz, 25878c2ecf20Sopenharmony_ci .frequency_step_hz = 1 * kHz, 25888c2ecf20Sopenharmony_ci }, 25898c2ecf20Sopenharmony_ci .release = dib0090_release, 25908c2ecf20Sopenharmony_ci 25918c2ecf20Sopenharmony_ci .init = NULL, 25928c2ecf20Sopenharmony_ci .sleep = NULL, 25938c2ecf20Sopenharmony_ci .set_params = NULL, 25948c2ecf20Sopenharmony_ci .get_frequency = NULL, 25958c2ecf20Sopenharmony_ci}; 25968c2ecf20Sopenharmony_ci 25978c2ecf20Sopenharmony_cistatic const struct dib0090_wbd_slope dib0090_wbd_table_default[] = { 25988c2ecf20Sopenharmony_ci {470, 0, 250, 0, 100, 4}, 25998c2ecf20Sopenharmony_ci {860, 51, 866, 21, 375, 4}, 26008c2ecf20Sopenharmony_ci {1700, 0, 800, 0, 850, 4}, 26018c2ecf20Sopenharmony_ci {2900, 0, 250, 0, 100, 6}, 26028c2ecf20Sopenharmony_ci {0xFFFF, 0, 0, 0, 0, 0}, 26038c2ecf20Sopenharmony_ci}; 26048c2ecf20Sopenharmony_ci 26058c2ecf20Sopenharmony_cistruct dvb_frontend *dib0090_register(struct dvb_frontend *fe, struct i2c_adapter *i2c, const struct dib0090_config *config) 26068c2ecf20Sopenharmony_ci{ 26078c2ecf20Sopenharmony_ci struct dib0090_state *st = kzalloc(sizeof(struct dib0090_state), GFP_KERNEL); 26088c2ecf20Sopenharmony_ci if (st == NULL) 26098c2ecf20Sopenharmony_ci return NULL; 26108c2ecf20Sopenharmony_ci 26118c2ecf20Sopenharmony_ci st->config = config; 26128c2ecf20Sopenharmony_ci st->i2c = i2c; 26138c2ecf20Sopenharmony_ci st->fe = fe; 26148c2ecf20Sopenharmony_ci mutex_init(&st->i2c_buffer_lock); 26158c2ecf20Sopenharmony_ci fe->tuner_priv = st; 26168c2ecf20Sopenharmony_ci 26178c2ecf20Sopenharmony_ci if (config->wbd == NULL) 26188c2ecf20Sopenharmony_ci st->current_wbd_table = dib0090_wbd_table_default; 26198c2ecf20Sopenharmony_ci else 26208c2ecf20Sopenharmony_ci st->current_wbd_table = config->wbd; 26218c2ecf20Sopenharmony_ci 26228c2ecf20Sopenharmony_ci if (dib0090_reset(fe) != 0) 26238c2ecf20Sopenharmony_ci goto free_mem; 26248c2ecf20Sopenharmony_ci 26258c2ecf20Sopenharmony_ci pr_info("DiB0090: successfully identified\n"); 26268c2ecf20Sopenharmony_ci memcpy(&fe->ops.tuner_ops, &dib0090_ops, sizeof(struct dvb_tuner_ops)); 26278c2ecf20Sopenharmony_ci 26288c2ecf20Sopenharmony_ci return fe; 26298c2ecf20Sopenharmony_ci free_mem: 26308c2ecf20Sopenharmony_ci kfree(st); 26318c2ecf20Sopenharmony_ci fe->tuner_priv = NULL; 26328c2ecf20Sopenharmony_ci return NULL; 26338c2ecf20Sopenharmony_ci} 26348c2ecf20Sopenharmony_ci 26358c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(dib0090_register); 26368c2ecf20Sopenharmony_ci 26378c2ecf20Sopenharmony_cistruct dvb_frontend *dib0090_fw_register(struct dvb_frontend *fe, struct i2c_adapter *i2c, const struct dib0090_config *config) 26388c2ecf20Sopenharmony_ci{ 26398c2ecf20Sopenharmony_ci struct dib0090_fw_state *st = kzalloc(sizeof(struct dib0090_fw_state), GFP_KERNEL); 26408c2ecf20Sopenharmony_ci if (st == NULL) 26418c2ecf20Sopenharmony_ci return NULL; 26428c2ecf20Sopenharmony_ci 26438c2ecf20Sopenharmony_ci st->config = config; 26448c2ecf20Sopenharmony_ci st->i2c = i2c; 26458c2ecf20Sopenharmony_ci st->fe = fe; 26468c2ecf20Sopenharmony_ci mutex_init(&st->i2c_buffer_lock); 26478c2ecf20Sopenharmony_ci fe->tuner_priv = st; 26488c2ecf20Sopenharmony_ci 26498c2ecf20Sopenharmony_ci if (dib0090_fw_reset_digital(fe, st->config) != 0) 26508c2ecf20Sopenharmony_ci goto free_mem; 26518c2ecf20Sopenharmony_ci 26528c2ecf20Sopenharmony_ci dprintk("DiB0090 FW: successfully identified\n"); 26538c2ecf20Sopenharmony_ci memcpy(&fe->ops.tuner_ops, &dib0090_fw_ops, sizeof(struct dvb_tuner_ops)); 26548c2ecf20Sopenharmony_ci 26558c2ecf20Sopenharmony_ci return fe; 26568c2ecf20Sopenharmony_cifree_mem: 26578c2ecf20Sopenharmony_ci kfree(st); 26588c2ecf20Sopenharmony_ci fe->tuner_priv = NULL; 26598c2ecf20Sopenharmony_ci return NULL; 26608c2ecf20Sopenharmony_ci} 26618c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(dib0090_fw_register); 26628c2ecf20Sopenharmony_ci 26638c2ecf20Sopenharmony_ciMODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@posteo.de>"); 26648c2ecf20Sopenharmony_ciMODULE_AUTHOR("Olivier Grenie <olivier.grenie@parrot.com>"); 26658c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Driver for the DiBcom 0090 base-band RF Tuner"); 26668c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 2667