18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Linux-DVB Driver for DiBcom's DiB8000 chip (ISDB-T). 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2009 DiBcom (http://www.dibcom.fr/) 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#include <linux/kernel.h> 118c2ecf20Sopenharmony_ci#include <linux/slab.h> 128c2ecf20Sopenharmony_ci#include <linux/i2c.h> 138c2ecf20Sopenharmony_ci#include <linux/mutex.h> 148c2ecf20Sopenharmony_ci#include <asm/div64.h> 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci#include <media/dvb_math.h> 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ci#include <media/dvb_frontend.h> 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci#include "dib8000.h" 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ci#define LAYER_ALL -1 238c2ecf20Sopenharmony_ci#define LAYER_A 1 248c2ecf20Sopenharmony_ci#define LAYER_B 2 258c2ecf20Sopenharmony_ci#define LAYER_C 3 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_ci#define MAX_NUMBER_OF_FRONTENDS 6 288c2ecf20Sopenharmony_ci/* #define DIB8000_AGC_FREEZE */ 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_cistatic int debug; 318c2ecf20Sopenharmony_cimodule_param(debug, int, 0644); 328c2ecf20Sopenharmony_ciMODULE_PARM_DESC(debug, "turn on debugging (default: 0)"); 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci#define dprintk(fmt, arg...) do { \ 358c2ecf20Sopenharmony_ci if (debug) \ 368c2ecf20Sopenharmony_ci printk(KERN_DEBUG pr_fmt("%s: " fmt), \ 378c2ecf20Sopenharmony_ci __func__, ##arg); \ 388c2ecf20Sopenharmony_ci} while (0) 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_cistruct i2c_device { 418c2ecf20Sopenharmony_ci struct i2c_adapter *adap; 428c2ecf20Sopenharmony_ci u8 addr; 438c2ecf20Sopenharmony_ci u8 *i2c_write_buffer; 448c2ecf20Sopenharmony_ci u8 *i2c_read_buffer; 458c2ecf20Sopenharmony_ci struct mutex *i2c_buffer_lock; 468c2ecf20Sopenharmony_ci}; 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_cienum param_loop_step { 498c2ecf20Sopenharmony_ci LOOP_TUNE_1, 508c2ecf20Sopenharmony_ci LOOP_TUNE_2 518c2ecf20Sopenharmony_ci}; 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_cienum dib8000_autosearch_step { 548c2ecf20Sopenharmony_ci AS_START = 0, 558c2ecf20Sopenharmony_ci AS_SEARCHING_FFT, 568c2ecf20Sopenharmony_ci AS_SEARCHING_GUARD, 578c2ecf20Sopenharmony_ci AS_DONE = 100, 588c2ecf20Sopenharmony_ci}; 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_cienum timeout_mode { 618c2ecf20Sopenharmony_ci SYMBOL_DEPENDENT_OFF = 0, 628c2ecf20Sopenharmony_ci SYMBOL_DEPENDENT_ON, 638c2ecf20Sopenharmony_ci}; 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_cistruct dib8000_state { 668c2ecf20Sopenharmony_ci struct dib8000_config cfg; 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci struct i2c_device i2c; 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci struct dibx000_i2c_master i2c_master; 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ci u16 wbd_ref; 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci u8 current_band; 758c2ecf20Sopenharmony_ci u32 current_bandwidth; 768c2ecf20Sopenharmony_ci struct dibx000_agc_config *current_agc; 778c2ecf20Sopenharmony_ci u32 timf; 788c2ecf20Sopenharmony_ci u32 timf_default; 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ci u8 div_force_off:1; 818c2ecf20Sopenharmony_ci u8 div_state:1; 828c2ecf20Sopenharmony_ci u16 div_sync_wait; 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ci u8 agc_state; 858c2ecf20Sopenharmony_ci u8 differential_constellation; 868c2ecf20Sopenharmony_ci u8 diversity_onoff; 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci s16 ber_monitored_layer; 898c2ecf20Sopenharmony_ci u16 gpio_dir; 908c2ecf20Sopenharmony_ci u16 gpio_val; 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ci u16 revision; 938c2ecf20Sopenharmony_ci u8 isdbt_cfg_loaded; 948c2ecf20Sopenharmony_ci enum frontend_tune_state tune_state; 958c2ecf20Sopenharmony_ci s32 status; 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci struct dvb_frontend *fe[MAX_NUMBER_OF_FRONTENDS]; 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ci /* for the I2C transfer */ 1008c2ecf20Sopenharmony_ci struct i2c_msg msg[2]; 1018c2ecf20Sopenharmony_ci u8 i2c_write_buffer[4]; 1028c2ecf20Sopenharmony_ci u8 i2c_read_buffer[2]; 1038c2ecf20Sopenharmony_ci struct mutex i2c_buffer_lock; 1048c2ecf20Sopenharmony_ci u8 input_mode_mpeg; 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci u16 tuner_enable; 1078c2ecf20Sopenharmony_ci struct i2c_adapter dib8096p_tuner_adap; 1088c2ecf20Sopenharmony_ci u16 current_demod_bw; 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_ci u16 seg_mask; 1118c2ecf20Sopenharmony_ci u16 seg_diff_mask; 1128c2ecf20Sopenharmony_ci u16 mode; 1138c2ecf20Sopenharmony_ci u8 layer_b_nb_seg; 1148c2ecf20Sopenharmony_ci u8 layer_c_nb_seg; 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ci u8 channel_parameters_set; 1178c2ecf20Sopenharmony_ci u16 autosearch_state; 1188c2ecf20Sopenharmony_ci u16 found_nfft; 1198c2ecf20Sopenharmony_ci u16 found_guard; 1208c2ecf20Sopenharmony_ci u8 subchannel; 1218c2ecf20Sopenharmony_ci u8 symbol_duration; 1228c2ecf20Sopenharmony_ci unsigned long timeout; 1238c2ecf20Sopenharmony_ci u8 longest_intlv_layer; 1248c2ecf20Sopenharmony_ci u16 output_mode; 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ci /* for DVBv5 stats */ 1278c2ecf20Sopenharmony_ci s64 init_ucb; 1288c2ecf20Sopenharmony_ci unsigned long per_jiffies_stats; 1298c2ecf20Sopenharmony_ci unsigned long ber_jiffies_stats; 1308c2ecf20Sopenharmony_ci unsigned long ber_jiffies_stats_layer[3]; 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci#ifdef DIB8000_AGC_FREEZE 1338c2ecf20Sopenharmony_ci u16 agc1_max; 1348c2ecf20Sopenharmony_ci u16 agc1_min; 1358c2ecf20Sopenharmony_ci u16 agc2_max; 1368c2ecf20Sopenharmony_ci u16 agc2_min; 1378c2ecf20Sopenharmony_ci#endif 1388c2ecf20Sopenharmony_ci}; 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_cienum dib8000_power_mode { 1418c2ecf20Sopenharmony_ci DIB8000_POWER_ALL = 0, 1428c2ecf20Sopenharmony_ci DIB8000_POWER_INTERFACE_ONLY, 1438c2ecf20Sopenharmony_ci}; 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_cistatic u16 dib8000_i2c_read16(struct i2c_device *i2c, u16 reg) 1468c2ecf20Sopenharmony_ci{ 1478c2ecf20Sopenharmony_ci u16 ret; 1488c2ecf20Sopenharmony_ci struct i2c_msg msg[2] = { 1498c2ecf20Sopenharmony_ci {.addr = i2c->addr >> 1, .flags = 0, .len = 2}, 1508c2ecf20Sopenharmony_ci {.addr = i2c->addr >> 1, .flags = I2C_M_RD, .len = 2}, 1518c2ecf20Sopenharmony_ci }; 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_ci if (mutex_lock_interruptible(i2c->i2c_buffer_lock) < 0) { 1548c2ecf20Sopenharmony_ci dprintk("could not acquire lock\n"); 1558c2ecf20Sopenharmony_ci return 0; 1568c2ecf20Sopenharmony_ci } 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci msg[0].buf = i2c->i2c_write_buffer; 1598c2ecf20Sopenharmony_ci msg[0].buf[0] = reg >> 8; 1608c2ecf20Sopenharmony_ci msg[0].buf[1] = reg & 0xff; 1618c2ecf20Sopenharmony_ci msg[1].buf = i2c->i2c_read_buffer; 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci if (i2c_transfer(i2c->adap, msg, 2) != 2) 1648c2ecf20Sopenharmony_ci dprintk("i2c read error on %d\n", reg); 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_ci ret = (msg[1].buf[0] << 8) | msg[1].buf[1]; 1678c2ecf20Sopenharmony_ci mutex_unlock(i2c->i2c_buffer_lock); 1688c2ecf20Sopenharmony_ci return ret; 1698c2ecf20Sopenharmony_ci} 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_cistatic u16 __dib8000_read_word(struct dib8000_state *state, u16 reg) 1728c2ecf20Sopenharmony_ci{ 1738c2ecf20Sopenharmony_ci u16 ret; 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_ci state->i2c_write_buffer[0] = reg >> 8; 1768c2ecf20Sopenharmony_ci state->i2c_write_buffer[1] = reg & 0xff; 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ci memset(state->msg, 0, 2 * sizeof(struct i2c_msg)); 1798c2ecf20Sopenharmony_ci state->msg[0].addr = state->i2c.addr >> 1; 1808c2ecf20Sopenharmony_ci state->msg[0].flags = 0; 1818c2ecf20Sopenharmony_ci state->msg[0].buf = state->i2c_write_buffer; 1828c2ecf20Sopenharmony_ci state->msg[0].len = 2; 1838c2ecf20Sopenharmony_ci state->msg[1].addr = state->i2c.addr >> 1; 1848c2ecf20Sopenharmony_ci state->msg[1].flags = I2C_M_RD; 1858c2ecf20Sopenharmony_ci state->msg[1].buf = state->i2c_read_buffer; 1868c2ecf20Sopenharmony_ci state->msg[1].len = 2; 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_ci if (i2c_transfer(state->i2c.adap, state->msg, 2) != 2) 1898c2ecf20Sopenharmony_ci dprintk("i2c read error on %d\n", reg); 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_ci ret = (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1]; 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_ci return ret; 1948c2ecf20Sopenharmony_ci} 1958c2ecf20Sopenharmony_ci 1968c2ecf20Sopenharmony_cistatic u16 dib8000_read_word(struct dib8000_state *state, u16 reg) 1978c2ecf20Sopenharmony_ci{ 1988c2ecf20Sopenharmony_ci u16 ret; 1998c2ecf20Sopenharmony_ci 2008c2ecf20Sopenharmony_ci if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) { 2018c2ecf20Sopenharmony_ci dprintk("could not acquire lock\n"); 2028c2ecf20Sopenharmony_ci return 0; 2038c2ecf20Sopenharmony_ci } 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_ci ret = __dib8000_read_word(state, reg); 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_ci mutex_unlock(&state->i2c_buffer_lock); 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_ci return ret; 2108c2ecf20Sopenharmony_ci} 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_cistatic u32 dib8000_read32(struct dib8000_state *state, u16 reg) 2138c2ecf20Sopenharmony_ci{ 2148c2ecf20Sopenharmony_ci u16 rw[2]; 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_ci if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) { 2178c2ecf20Sopenharmony_ci dprintk("could not acquire lock\n"); 2188c2ecf20Sopenharmony_ci return 0; 2198c2ecf20Sopenharmony_ci } 2208c2ecf20Sopenharmony_ci 2218c2ecf20Sopenharmony_ci rw[0] = __dib8000_read_word(state, reg + 0); 2228c2ecf20Sopenharmony_ci rw[1] = __dib8000_read_word(state, reg + 1); 2238c2ecf20Sopenharmony_ci 2248c2ecf20Sopenharmony_ci mutex_unlock(&state->i2c_buffer_lock); 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_ci return ((rw[0] << 16) | (rw[1])); 2278c2ecf20Sopenharmony_ci} 2288c2ecf20Sopenharmony_ci 2298c2ecf20Sopenharmony_cistatic int dib8000_i2c_write16(struct i2c_device *i2c, u16 reg, u16 val) 2308c2ecf20Sopenharmony_ci{ 2318c2ecf20Sopenharmony_ci struct i2c_msg msg = {.addr = i2c->addr >> 1, .flags = 0, .len = 4}; 2328c2ecf20Sopenharmony_ci int ret = 0; 2338c2ecf20Sopenharmony_ci 2348c2ecf20Sopenharmony_ci if (mutex_lock_interruptible(i2c->i2c_buffer_lock) < 0) { 2358c2ecf20Sopenharmony_ci dprintk("could not acquire lock\n"); 2368c2ecf20Sopenharmony_ci return -EINVAL; 2378c2ecf20Sopenharmony_ci } 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_ci msg.buf = i2c->i2c_write_buffer; 2408c2ecf20Sopenharmony_ci msg.buf[0] = (reg >> 8) & 0xff; 2418c2ecf20Sopenharmony_ci msg.buf[1] = reg & 0xff; 2428c2ecf20Sopenharmony_ci msg.buf[2] = (val >> 8) & 0xff; 2438c2ecf20Sopenharmony_ci msg.buf[3] = val & 0xff; 2448c2ecf20Sopenharmony_ci 2458c2ecf20Sopenharmony_ci ret = i2c_transfer(i2c->adap, &msg, 1) != 1 ? -EREMOTEIO : 0; 2468c2ecf20Sopenharmony_ci mutex_unlock(i2c->i2c_buffer_lock); 2478c2ecf20Sopenharmony_ci 2488c2ecf20Sopenharmony_ci return ret; 2498c2ecf20Sopenharmony_ci} 2508c2ecf20Sopenharmony_ci 2518c2ecf20Sopenharmony_cistatic int dib8000_write_word(struct dib8000_state *state, u16 reg, u16 val) 2528c2ecf20Sopenharmony_ci{ 2538c2ecf20Sopenharmony_ci int ret; 2548c2ecf20Sopenharmony_ci 2558c2ecf20Sopenharmony_ci if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) { 2568c2ecf20Sopenharmony_ci dprintk("could not acquire lock\n"); 2578c2ecf20Sopenharmony_ci return -EINVAL; 2588c2ecf20Sopenharmony_ci } 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_ci state->i2c_write_buffer[0] = (reg >> 8) & 0xff; 2618c2ecf20Sopenharmony_ci state->i2c_write_buffer[1] = reg & 0xff; 2628c2ecf20Sopenharmony_ci state->i2c_write_buffer[2] = (val >> 8) & 0xff; 2638c2ecf20Sopenharmony_ci state->i2c_write_buffer[3] = val & 0xff; 2648c2ecf20Sopenharmony_ci 2658c2ecf20Sopenharmony_ci memset(&state->msg[0], 0, sizeof(struct i2c_msg)); 2668c2ecf20Sopenharmony_ci state->msg[0].addr = state->i2c.addr >> 1; 2678c2ecf20Sopenharmony_ci state->msg[0].flags = 0; 2688c2ecf20Sopenharmony_ci state->msg[0].buf = state->i2c_write_buffer; 2698c2ecf20Sopenharmony_ci state->msg[0].len = 4; 2708c2ecf20Sopenharmony_ci 2718c2ecf20Sopenharmony_ci ret = (i2c_transfer(state->i2c.adap, state->msg, 1) != 1 ? 2728c2ecf20Sopenharmony_ci -EREMOTEIO : 0); 2738c2ecf20Sopenharmony_ci mutex_unlock(&state->i2c_buffer_lock); 2748c2ecf20Sopenharmony_ci 2758c2ecf20Sopenharmony_ci return ret; 2768c2ecf20Sopenharmony_ci} 2778c2ecf20Sopenharmony_ci 2788c2ecf20Sopenharmony_cistatic const s16 coeff_2k_sb_1seg_dqpsk[8] = { 2798c2ecf20Sopenharmony_ci (769 << 5) | 0x0a, (745 << 5) | 0x03, (595 << 5) | 0x0d, (769 << 5) | 0x0a, (920 << 5) | 0x09, (784 << 5) | 0x02, (519 << 5) | 0x0c, 2808c2ecf20Sopenharmony_ci (920 << 5) | 0x09 2818c2ecf20Sopenharmony_ci}; 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_cistatic const s16 coeff_2k_sb_1seg[8] = { 2848c2ecf20Sopenharmony_ci (692 << 5) | 0x0b, (683 << 5) | 0x01, (519 << 5) | 0x09, (692 << 5) | 0x0b, 0 | 0x1f, 0 | 0x1f, 0 | 0x1f, 0 | 0x1f 2858c2ecf20Sopenharmony_ci}; 2868c2ecf20Sopenharmony_ci 2878c2ecf20Sopenharmony_cistatic const s16 coeff_2k_sb_3seg_0dqpsk_1dqpsk[8] = { 2888c2ecf20Sopenharmony_ci (832 << 5) | 0x10, (912 << 5) | 0x05, (900 << 5) | 0x12, (832 << 5) | 0x10, (-931 << 5) | 0x0f, (912 << 5) | 0x04, (807 << 5) | 0x11, 2898c2ecf20Sopenharmony_ci (-931 << 5) | 0x0f 2908c2ecf20Sopenharmony_ci}; 2918c2ecf20Sopenharmony_ci 2928c2ecf20Sopenharmony_cistatic const s16 coeff_2k_sb_3seg_0dqpsk[8] = { 2938c2ecf20Sopenharmony_ci (622 << 5) | 0x0c, (941 << 5) | 0x04, (796 << 5) | 0x10, (622 << 5) | 0x0c, (982 << 5) | 0x0c, (519 << 5) | 0x02, (572 << 5) | 0x0e, 2948c2ecf20Sopenharmony_ci (982 << 5) | 0x0c 2958c2ecf20Sopenharmony_ci}; 2968c2ecf20Sopenharmony_ci 2978c2ecf20Sopenharmony_cistatic const s16 coeff_2k_sb_3seg_1dqpsk[8] = { 2988c2ecf20Sopenharmony_ci (699 << 5) | 0x14, (607 << 5) | 0x04, (944 << 5) | 0x13, (699 << 5) | 0x14, (-720 << 5) | 0x0d, (640 << 5) | 0x03, (866 << 5) | 0x12, 2998c2ecf20Sopenharmony_ci (-720 << 5) | 0x0d 3008c2ecf20Sopenharmony_ci}; 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_cistatic const s16 coeff_2k_sb_3seg[8] = { 3038c2ecf20Sopenharmony_ci (664 << 5) | 0x0c, (925 << 5) | 0x03, (937 << 5) | 0x10, (664 << 5) | 0x0c, (-610 << 5) | 0x0a, (697 << 5) | 0x01, (836 << 5) | 0x0e, 3048c2ecf20Sopenharmony_ci (-610 << 5) | 0x0a 3058c2ecf20Sopenharmony_ci}; 3068c2ecf20Sopenharmony_ci 3078c2ecf20Sopenharmony_cistatic const s16 coeff_4k_sb_1seg_dqpsk[8] = { 3088c2ecf20Sopenharmony_ci (-955 << 5) | 0x0e, (687 << 5) | 0x04, (818 << 5) | 0x10, (-955 << 5) | 0x0e, (-922 << 5) | 0x0d, (750 << 5) | 0x03, (665 << 5) | 0x0f, 3098c2ecf20Sopenharmony_ci (-922 << 5) | 0x0d 3108c2ecf20Sopenharmony_ci}; 3118c2ecf20Sopenharmony_ci 3128c2ecf20Sopenharmony_cistatic const s16 coeff_4k_sb_1seg[8] = { 3138c2ecf20Sopenharmony_ci (638 << 5) | 0x0d, (683 << 5) | 0x02, (638 << 5) | 0x0d, (638 << 5) | 0x0d, (-655 << 5) | 0x0a, (517 << 5) | 0x00, (698 << 5) | 0x0d, 3148c2ecf20Sopenharmony_ci (-655 << 5) | 0x0a 3158c2ecf20Sopenharmony_ci}; 3168c2ecf20Sopenharmony_ci 3178c2ecf20Sopenharmony_cistatic const s16 coeff_4k_sb_3seg_0dqpsk_1dqpsk[8] = { 3188c2ecf20Sopenharmony_ci (-707 << 5) | 0x14, (910 << 5) | 0x06, (889 << 5) | 0x16, (-707 << 5) | 0x14, (-958 << 5) | 0x13, (993 << 5) | 0x05, (523 << 5) | 0x14, 3198c2ecf20Sopenharmony_ci (-958 << 5) | 0x13 3208c2ecf20Sopenharmony_ci}; 3218c2ecf20Sopenharmony_ci 3228c2ecf20Sopenharmony_cistatic const s16 coeff_4k_sb_3seg_0dqpsk[8] = { 3238c2ecf20Sopenharmony_ci (-723 << 5) | 0x13, (910 << 5) | 0x05, (777 << 5) | 0x14, (-723 << 5) | 0x13, (-568 << 5) | 0x0f, (547 << 5) | 0x03, (696 << 5) | 0x12, 3248c2ecf20Sopenharmony_ci (-568 << 5) | 0x0f 3258c2ecf20Sopenharmony_ci}; 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_cistatic const s16 coeff_4k_sb_3seg_1dqpsk[8] = { 3288c2ecf20Sopenharmony_ci (-940 << 5) | 0x15, (607 << 5) | 0x05, (915 << 5) | 0x16, (-940 << 5) | 0x15, (-848 << 5) | 0x13, (683 << 5) | 0x04, (543 << 5) | 0x14, 3298c2ecf20Sopenharmony_ci (-848 << 5) | 0x13 3308c2ecf20Sopenharmony_ci}; 3318c2ecf20Sopenharmony_ci 3328c2ecf20Sopenharmony_cistatic const s16 coeff_4k_sb_3seg[8] = { 3338c2ecf20Sopenharmony_ci (612 << 5) | 0x12, (910 << 5) | 0x04, (864 << 5) | 0x14, (612 << 5) | 0x12, (-869 << 5) | 0x13, (683 << 5) | 0x02, (869 << 5) | 0x12, 3348c2ecf20Sopenharmony_ci (-869 << 5) | 0x13 3358c2ecf20Sopenharmony_ci}; 3368c2ecf20Sopenharmony_ci 3378c2ecf20Sopenharmony_cistatic const s16 coeff_8k_sb_1seg_dqpsk[8] = { 3388c2ecf20Sopenharmony_ci (-835 << 5) | 0x12, (684 << 5) | 0x05, (735 << 5) | 0x14, (-835 << 5) | 0x12, (-598 << 5) | 0x10, (781 << 5) | 0x04, (739 << 5) | 0x13, 3398c2ecf20Sopenharmony_ci (-598 << 5) | 0x10 3408c2ecf20Sopenharmony_ci}; 3418c2ecf20Sopenharmony_ci 3428c2ecf20Sopenharmony_cistatic const s16 coeff_8k_sb_1seg[8] = { 3438c2ecf20Sopenharmony_ci (673 << 5) | 0x0f, (683 << 5) | 0x03, (808 << 5) | 0x12, (673 << 5) | 0x0f, (585 << 5) | 0x0f, (512 << 5) | 0x01, (780 << 5) | 0x0f, 3448c2ecf20Sopenharmony_ci (585 << 5) | 0x0f 3458c2ecf20Sopenharmony_ci}; 3468c2ecf20Sopenharmony_ci 3478c2ecf20Sopenharmony_cistatic const s16 coeff_8k_sb_3seg_0dqpsk_1dqpsk[8] = { 3488c2ecf20Sopenharmony_ci (863 << 5) | 0x17, (930 << 5) | 0x07, (878 << 5) | 0x19, (863 << 5) | 0x17, (0 << 5) | 0x14, (521 << 5) | 0x05, (980 << 5) | 0x18, 3498c2ecf20Sopenharmony_ci (0 << 5) | 0x14 3508c2ecf20Sopenharmony_ci}; 3518c2ecf20Sopenharmony_ci 3528c2ecf20Sopenharmony_cistatic const s16 coeff_8k_sb_3seg_0dqpsk[8] = { 3538c2ecf20Sopenharmony_ci (-924 << 5) | 0x17, (910 << 5) | 0x06, (774 << 5) | 0x17, (-924 << 5) | 0x17, (-877 << 5) | 0x15, (565 << 5) | 0x04, (553 << 5) | 0x15, 3548c2ecf20Sopenharmony_ci (-877 << 5) | 0x15 3558c2ecf20Sopenharmony_ci}; 3568c2ecf20Sopenharmony_ci 3578c2ecf20Sopenharmony_cistatic const s16 coeff_8k_sb_3seg_1dqpsk[8] = { 3588c2ecf20Sopenharmony_ci (-921 << 5) | 0x19, (607 << 5) | 0x06, (881 << 5) | 0x19, (-921 << 5) | 0x19, (-921 << 5) | 0x14, (713 << 5) | 0x05, (1018 << 5) | 0x18, 3598c2ecf20Sopenharmony_ci (-921 << 5) | 0x14 3608c2ecf20Sopenharmony_ci}; 3618c2ecf20Sopenharmony_ci 3628c2ecf20Sopenharmony_cistatic const s16 coeff_8k_sb_3seg[8] = { 3638c2ecf20Sopenharmony_ci (514 << 5) | 0x14, (910 << 5) | 0x05, (861 << 5) | 0x17, (514 << 5) | 0x14, (690 << 5) | 0x14, (683 << 5) | 0x03, (662 << 5) | 0x15, 3648c2ecf20Sopenharmony_ci (690 << 5) | 0x14 3658c2ecf20Sopenharmony_ci}; 3668c2ecf20Sopenharmony_ci 3678c2ecf20Sopenharmony_cistatic const s16 ana_fe_coeff_3seg[24] = { 3688c2ecf20Sopenharmony_ci 81, 80, 78, 74, 68, 61, 54, 45, 37, 28, 19, 11, 4, 1022, 1017, 1013, 1010, 1008, 1008, 1008, 1008, 1010, 1014, 1017 3698c2ecf20Sopenharmony_ci}; 3708c2ecf20Sopenharmony_ci 3718c2ecf20Sopenharmony_cistatic const s16 ana_fe_coeff_1seg[24] = { 3728c2ecf20Sopenharmony_ci 249, 226, 164, 82, 5, 981, 970, 988, 1018, 20, 31, 26, 8, 1012, 1000, 1018, 1012, 8, 15, 14, 9, 3, 1017, 1003 3738c2ecf20Sopenharmony_ci}; 3748c2ecf20Sopenharmony_ci 3758c2ecf20Sopenharmony_cistatic const s16 ana_fe_coeff_13seg[24] = { 3768c2ecf20Sopenharmony_ci 396, 305, 105, -51, -77, -12, 41, 31, -11, -30, -11, 14, 15, -2, -13, -7, 5, 8, 1, -6, -7, -3, 0, 1 3778c2ecf20Sopenharmony_ci}; 3788c2ecf20Sopenharmony_ci 3798c2ecf20Sopenharmony_cistatic u16 fft_to_mode(struct dib8000_state *state) 3808c2ecf20Sopenharmony_ci{ 3818c2ecf20Sopenharmony_ci u16 mode; 3828c2ecf20Sopenharmony_ci switch (state->fe[0]->dtv_property_cache.transmission_mode) { 3838c2ecf20Sopenharmony_ci case TRANSMISSION_MODE_2K: 3848c2ecf20Sopenharmony_ci mode = 1; 3858c2ecf20Sopenharmony_ci break; 3868c2ecf20Sopenharmony_ci case TRANSMISSION_MODE_4K: 3878c2ecf20Sopenharmony_ci mode = 2; 3888c2ecf20Sopenharmony_ci break; 3898c2ecf20Sopenharmony_ci default: 3908c2ecf20Sopenharmony_ci case TRANSMISSION_MODE_AUTO: 3918c2ecf20Sopenharmony_ci case TRANSMISSION_MODE_8K: 3928c2ecf20Sopenharmony_ci mode = 3; 3938c2ecf20Sopenharmony_ci break; 3948c2ecf20Sopenharmony_ci } 3958c2ecf20Sopenharmony_ci return mode; 3968c2ecf20Sopenharmony_ci} 3978c2ecf20Sopenharmony_ci 3988c2ecf20Sopenharmony_cistatic void dib8000_set_acquisition_mode(struct dib8000_state *state) 3998c2ecf20Sopenharmony_ci{ 4008c2ecf20Sopenharmony_ci u16 nud = dib8000_read_word(state, 298); 4018c2ecf20Sopenharmony_ci nud |= (1 << 3) | (1 << 0); 4028c2ecf20Sopenharmony_ci dprintk("acquisition mode activated\n"); 4038c2ecf20Sopenharmony_ci dib8000_write_word(state, 298, nud); 4048c2ecf20Sopenharmony_ci} 4058c2ecf20Sopenharmony_cistatic int dib8000_set_output_mode(struct dvb_frontend *fe, int mode) 4068c2ecf20Sopenharmony_ci{ 4078c2ecf20Sopenharmony_ci struct dib8000_state *state = fe->demodulator_priv; 4088c2ecf20Sopenharmony_ci u16 outreg, fifo_threshold, smo_mode, sram = 0x0205; /* by default SDRAM deintlv is enabled */ 4098c2ecf20Sopenharmony_ci 4108c2ecf20Sopenharmony_ci state->output_mode = mode; 4118c2ecf20Sopenharmony_ci outreg = 0; 4128c2ecf20Sopenharmony_ci fifo_threshold = 1792; 4138c2ecf20Sopenharmony_ci smo_mode = (dib8000_read_word(state, 299) & 0x0050) | (1 << 1); 4148c2ecf20Sopenharmony_ci 4158c2ecf20Sopenharmony_ci dprintk("-I- Setting output mode for demod %p to %d\n", 4168c2ecf20Sopenharmony_ci &state->fe[0], mode); 4178c2ecf20Sopenharmony_ci 4188c2ecf20Sopenharmony_ci switch (mode) { 4198c2ecf20Sopenharmony_ci case OUTMODE_MPEG2_PAR_GATED_CLK: // STBs with parallel gated clock 4208c2ecf20Sopenharmony_ci outreg = (1 << 10); /* 0x0400 */ 4218c2ecf20Sopenharmony_ci break; 4228c2ecf20Sopenharmony_ci case OUTMODE_MPEG2_PAR_CONT_CLK: // STBs with parallel continues clock 4238c2ecf20Sopenharmony_ci outreg = (1 << 10) | (1 << 6); /* 0x0440 */ 4248c2ecf20Sopenharmony_ci break; 4258c2ecf20Sopenharmony_ci case OUTMODE_MPEG2_SERIAL: // STBs with serial input 4268c2ecf20Sopenharmony_ci outreg = (1 << 10) | (2 << 6) | (0 << 1); /* 0x0482 */ 4278c2ecf20Sopenharmony_ci break; 4288c2ecf20Sopenharmony_ci case OUTMODE_DIVERSITY: 4298c2ecf20Sopenharmony_ci if (state->cfg.hostbus_diversity) { 4308c2ecf20Sopenharmony_ci outreg = (1 << 10) | (4 << 6); /* 0x0500 */ 4318c2ecf20Sopenharmony_ci sram &= 0xfdff; 4328c2ecf20Sopenharmony_ci } else 4338c2ecf20Sopenharmony_ci sram |= 0x0c00; 4348c2ecf20Sopenharmony_ci break; 4358c2ecf20Sopenharmony_ci case OUTMODE_MPEG2_FIFO: // e.g. USB feeding 4368c2ecf20Sopenharmony_ci smo_mode |= (3 << 1); 4378c2ecf20Sopenharmony_ci fifo_threshold = 512; 4388c2ecf20Sopenharmony_ci outreg = (1 << 10) | (5 << 6); 4398c2ecf20Sopenharmony_ci break; 4408c2ecf20Sopenharmony_ci case OUTMODE_HIGH_Z: // disable 4418c2ecf20Sopenharmony_ci outreg = 0; 4428c2ecf20Sopenharmony_ci break; 4438c2ecf20Sopenharmony_ci 4448c2ecf20Sopenharmony_ci case OUTMODE_ANALOG_ADC: 4458c2ecf20Sopenharmony_ci outreg = (1 << 10) | (3 << 6); 4468c2ecf20Sopenharmony_ci dib8000_set_acquisition_mode(state); 4478c2ecf20Sopenharmony_ci break; 4488c2ecf20Sopenharmony_ci 4498c2ecf20Sopenharmony_ci default: 4508c2ecf20Sopenharmony_ci dprintk("Unhandled output_mode passed to be set for demod %p\n", 4518c2ecf20Sopenharmony_ci &state->fe[0]); 4528c2ecf20Sopenharmony_ci return -EINVAL; 4538c2ecf20Sopenharmony_ci } 4548c2ecf20Sopenharmony_ci 4558c2ecf20Sopenharmony_ci if (state->cfg.output_mpeg2_in_188_bytes) 4568c2ecf20Sopenharmony_ci smo_mode |= (1 << 5); 4578c2ecf20Sopenharmony_ci 4588c2ecf20Sopenharmony_ci dib8000_write_word(state, 299, smo_mode); 4598c2ecf20Sopenharmony_ci dib8000_write_word(state, 300, fifo_threshold); /* synchronous fread */ 4608c2ecf20Sopenharmony_ci dib8000_write_word(state, 1286, outreg); 4618c2ecf20Sopenharmony_ci dib8000_write_word(state, 1291, sram); 4628c2ecf20Sopenharmony_ci 4638c2ecf20Sopenharmony_ci return 0; 4648c2ecf20Sopenharmony_ci} 4658c2ecf20Sopenharmony_ci 4668c2ecf20Sopenharmony_cistatic int dib8000_set_diversity_in(struct dvb_frontend *fe, int onoff) 4678c2ecf20Sopenharmony_ci{ 4688c2ecf20Sopenharmony_ci struct dib8000_state *state = fe->demodulator_priv; 4698c2ecf20Sopenharmony_ci u16 tmp, sync_wait = dib8000_read_word(state, 273) & 0xfff0; 4708c2ecf20Sopenharmony_ci 4718c2ecf20Sopenharmony_ci dprintk("set diversity input to %i\n", onoff); 4728c2ecf20Sopenharmony_ci if (!state->differential_constellation) { 4738c2ecf20Sopenharmony_ci dib8000_write_word(state, 272, 1 << 9); //dvsy_off_lmod4 = 1 4748c2ecf20Sopenharmony_ci dib8000_write_word(state, 273, sync_wait | (1 << 2) | 2); // sync_enable = 1; comb_mode = 2 4758c2ecf20Sopenharmony_ci } else { 4768c2ecf20Sopenharmony_ci dib8000_write_word(state, 272, 0); //dvsy_off_lmod4 = 0 4778c2ecf20Sopenharmony_ci dib8000_write_word(state, 273, sync_wait); // sync_enable = 0; comb_mode = 0 4788c2ecf20Sopenharmony_ci } 4798c2ecf20Sopenharmony_ci state->diversity_onoff = onoff; 4808c2ecf20Sopenharmony_ci 4818c2ecf20Sopenharmony_ci switch (onoff) { 4828c2ecf20Sopenharmony_ci case 0: /* only use the internal way - not the diversity input */ 4838c2ecf20Sopenharmony_ci dib8000_write_word(state, 270, 1); 4848c2ecf20Sopenharmony_ci dib8000_write_word(state, 271, 0); 4858c2ecf20Sopenharmony_ci break; 4868c2ecf20Sopenharmony_ci case 1: /* both ways */ 4878c2ecf20Sopenharmony_ci dib8000_write_word(state, 270, 6); 4888c2ecf20Sopenharmony_ci dib8000_write_word(state, 271, 6); 4898c2ecf20Sopenharmony_ci break; 4908c2ecf20Sopenharmony_ci case 2: /* only the diversity input */ 4918c2ecf20Sopenharmony_ci dib8000_write_word(state, 270, 0); 4928c2ecf20Sopenharmony_ci dib8000_write_word(state, 271, 1); 4938c2ecf20Sopenharmony_ci break; 4948c2ecf20Sopenharmony_ci } 4958c2ecf20Sopenharmony_ci 4968c2ecf20Sopenharmony_ci if (state->revision == 0x8002) { 4978c2ecf20Sopenharmony_ci tmp = dib8000_read_word(state, 903); 4988c2ecf20Sopenharmony_ci dib8000_write_word(state, 903, tmp & ~(1 << 3)); 4998c2ecf20Sopenharmony_ci msleep(30); 5008c2ecf20Sopenharmony_ci dib8000_write_word(state, 903, tmp | (1 << 3)); 5018c2ecf20Sopenharmony_ci } 5028c2ecf20Sopenharmony_ci return 0; 5038c2ecf20Sopenharmony_ci} 5048c2ecf20Sopenharmony_ci 5058c2ecf20Sopenharmony_cistatic void dib8000_set_power_mode(struct dib8000_state *state, enum dib8000_power_mode mode) 5068c2ecf20Sopenharmony_ci{ 5078c2ecf20Sopenharmony_ci /* by default everything is going to be powered off */ 5088c2ecf20Sopenharmony_ci u16 reg_774 = 0x3fff, reg_775 = 0xffff, reg_776 = 0xffff, 5098c2ecf20Sopenharmony_ci reg_900 = (dib8000_read_word(state, 900) & 0xfffc) | 0x3, 5108c2ecf20Sopenharmony_ci reg_1280; 5118c2ecf20Sopenharmony_ci 5128c2ecf20Sopenharmony_ci if (state->revision != 0x8090) 5138c2ecf20Sopenharmony_ci reg_1280 = (dib8000_read_word(state, 1280) & 0x00ff) | 0xff00; 5148c2ecf20Sopenharmony_ci else 5158c2ecf20Sopenharmony_ci reg_1280 = (dib8000_read_word(state, 1280) & 0x707f) | 0x8f80; 5168c2ecf20Sopenharmony_ci 5178c2ecf20Sopenharmony_ci /* now, depending on the requested mode, we power on */ 5188c2ecf20Sopenharmony_ci switch (mode) { 5198c2ecf20Sopenharmony_ci /* power up everything in the demod */ 5208c2ecf20Sopenharmony_ci case DIB8000_POWER_ALL: 5218c2ecf20Sopenharmony_ci reg_774 = 0x0000; 5228c2ecf20Sopenharmony_ci reg_775 = 0x0000; 5238c2ecf20Sopenharmony_ci reg_776 = 0x0000; 5248c2ecf20Sopenharmony_ci reg_900 &= 0xfffc; 5258c2ecf20Sopenharmony_ci if (state->revision != 0x8090) 5268c2ecf20Sopenharmony_ci reg_1280 &= 0x00ff; 5278c2ecf20Sopenharmony_ci else 5288c2ecf20Sopenharmony_ci reg_1280 &= 0x707f; 5298c2ecf20Sopenharmony_ci break; 5308c2ecf20Sopenharmony_ci case DIB8000_POWER_INTERFACE_ONLY: 5318c2ecf20Sopenharmony_ci if (state->revision != 0x8090) 5328c2ecf20Sopenharmony_ci reg_1280 &= 0x00ff; 5338c2ecf20Sopenharmony_ci else 5348c2ecf20Sopenharmony_ci reg_1280 &= 0xfa7b; 5358c2ecf20Sopenharmony_ci break; 5368c2ecf20Sopenharmony_ci } 5378c2ecf20Sopenharmony_ci 5388c2ecf20Sopenharmony_ci dprintk("powermode : 774 : %x ; 775 : %x; 776 : %x ; 900 : %x; 1280 : %x\n", reg_774, reg_775, reg_776, reg_900, reg_1280); 5398c2ecf20Sopenharmony_ci dib8000_write_word(state, 774, reg_774); 5408c2ecf20Sopenharmony_ci dib8000_write_word(state, 775, reg_775); 5418c2ecf20Sopenharmony_ci dib8000_write_word(state, 776, reg_776); 5428c2ecf20Sopenharmony_ci dib8000_write_word(state, 900, reg_900); 5438c2ecf20Sopenharmony_ci dib8000_write_word(state, 1280, reg_1280); 5448c2ecf20Sopenharmony_ci} 5458c2ecf20Sopenharmony_ci 5468c2ecf20Sopenharmony_cistatic int dib8000_set_adc_state(struct dib8000_state *state, enum dibx000_adc_states no) 5478c2ecf20Sopenharmony_ci{ 5488c2ecf20Sopenharmony_ci int ret = 0; 5498c2ecf20Sopenharmony_ci u16 reg, reg_907 = dib8000_read_word(state, 907); 5508c2ecf20Sopenharmony_ci u16 reg_908 = dib8000_read_word(state, 908); 5518c2ecf20Sopenharmony_ci 5528c2ecf20Sopenharmony_ci switch (no) { 5538c2ecf20Sopenharmony_ci case DIBX000_SLOW_ADC_ON: 5548c2ecf20Sopenharmony_ci if (state->revision != 0x8090) { 5558c2ecf20Sopenharmony_ci reg_908 |= (1 << 1) | (1 << 0); 5568c2ecf20Sopenharmony_ci ret |= dib8000_write_word(state, 908, reg_908); 5578c2ecf20Sopenharmony_ci reg_908 &= ~(1 << 1); 5588c2ecf20Sopenharmony_ci } else { 5598c2ecf20Sopenharmony_ci reg = dib8000_read_word(state, 1925); 5608c2ecf20Sopenharmony_ci /* en_slowAdc = 1 & reset_sladc = 1 */ 5618c2ecf20Sopenharmony_ci dib8000_write_word(state, 1925, reg | 5628c2ecf20Sopenharmony_ci (1<<4) | (1<<2)); 5638c2ecf20Sopenharmony_ci 5648c2ecf20Sopenharmony_ci /* read access to make it works... strange ... */ 5658c2ecf20Sopenharmony_ci reg = dib8000_read_word(state, 1925); 5668c2ecf20Sopenharmony_ci msleep(20); 5678c2ecf20Sopenharmony_ci /* en_slowAdc = 1 & reset_sladc = 0 */ 5688c2ecf20Sopenharmony_ci dib8000_write_word(state, 1925, reg & ~(1<<4)); 5698c2ecf20Sopenharmony_ci 5708c2ecf20Sopenharmony_ci reg = dib8000_read_word(state, 921) & ~((0x3 << 14) 5718c2ecf20Sopenharmony_ci | (0x3 << 12)); 5728c2ecf20Sopenharmony_ci /* ref = Vin1 => Vbg ; sel = Vin0 or Vin3 ; 5738c2ecf20Sopenharmony_ci (Vin2 = Vcm) */ 5748c2ecf20Sopenharmony_ci dib8000_write_word(state, 921, reg | (1 << 14) 5758c2ecf20Sopenharmony_ci | (3 << 12)); 5768c2ecf20Sopenharmony_ci } 5778c2ecf20Sopenharmony_ci break; 5788c2ecf20Sopenharmony_ci 5798c2ecf20Sopenharmony_ci case DIBX000_SLOW_ADC_OFF: 5808c2ecf20Sopenharmony_ci if (state->revision == 0x8090) { 5818c2ecf20Sopenharmony_ci reg = dib8000_read_word(state, 1925); 5828c2ecf20Sopenharmony_ci /* reset_sladc = 1 en_slowAdc = 0 */ 5838c2ecf20Sopenharmony_ci dib8000_write_word(state, 1925, 5848c2ecf20Sopenharmony_ci (reg & ~(1<<2)) | (1<<4)); 5858c2ecf20Sopenharmony_ci } 5868c2ecf20Sopenharmony_ci reg_908 |= (1 << 1) | (1 << 0); 5878c2ecf20Sopenharmony_ci break; 5888c2ecf20Sopenharmony_ci 5898c2ecf20Sopenharmony_ci case DIBX000_ADC_ON: 5908c2ecf20Sopenharmony_ci reg_907 &= 0x0fff; 5918c2ecf20Sopenharmony_ci reg_908 &= 0x0003; 5928c2ecf20Sopenharmony_ci break; 5938c2ecf20Sopenharmony_ci 5948c2ecf20Sopenharmony_ci case DIBX000_ADC_OFF: // leave the VBG voltage on 5958c2ecf20Sopenharmony_ci reg_907 = (1 << 13) | (1 << 12); 5968c2ecf20Sopenharmony_ci reg_908 = (1 << 6) | (1 << 5) | (1 << 4) | (1 << 3) | (1 << 1); 5978c2ecf20Sopenharmony_ci break; 5988c2ecf20Sopenharmony_ci 5998c2ecf20Sopenharmony_ci case DIBX000_VBG_ENABLE: 6008c2ecf20Sopenharmony_ci reg_907 &= ~(1 << 15); 6018c2ecf20Sopenharmony_ci break; 6028c2ecf20Sopenharmony_ci 6038c2ecf20Sopenharmony_ci case DIBX000_VBG_DISABLE: 6048c2ecf20Sopenharmony_ci reg_907 |= (1 << 15); 6058c2ecf20Sopenharmony_ci break; 6068c2ecf20Sopenharmony_ci 6078c2ecf20Sopenharmony_ci default: 6088c2ecf20Sopenharmony_ci break; 6098c2ecf20Sopenharmony_ci } 6108c2ecf20Sopenharmony_ci 6118c2ecf20Sopenharmony_ci ret |= dib8000_write_word(state, 907, reg_907); 6128c2ecf20Sopenharmony_ci ret |= dib8000_write_word(state, 908, reg_908); 6138c2ecf20Sopenharmony_ci 6148c2ecf20Sopenharmony_ci return ret; 6158c2ecf20Sopenharmony_ci} 6168c2ecf20Sopenharmony_ci 6178c2ecf20Sopenharmony_cistatic int dib8000_set_bandwidth(struct dvb_frontend *fe, u32 bw) 6188c2ecf20Sopenharmony_ci{ 6198c2ecf20Sopenharmony_ci struct dib8000_state *state = fe->demodulator_priv; 6208c2ecf20Sopenharmony_ci u32 timf; 6218c2ecf20Sopenharmony_ci 6228c2ecf20Sopenharmony_ci if (bw == 0) 6238c2ecf20Sopenharmony_ci bw = 6000; 6248c2ecf20Sopenharmony_ci 6258c2ecf20Sopenharmony_ci if (state->timf == 0) { 6268c2ecf20Sopenharmony_ci dprintk("using default timf\n"); 6278c2ecf20Sopenharmony_ci timf = state->timf_default; 6288c2ecf20Sopenharmony_ci } else { 6298c2ecf20Sopenharmony_ci dprintk("using updated timf\n"); 6308c2ecf20Sopenharmony_ci timf = state->timf; 6318c2ecf20Sopenharmony_ci } 6328c2ecf20Sopenharmony_ci 6338c2ecf20Sopenharmony_ci dib8000_write_word(state, 29, (u16) ((timf >> 16) & 0xffff)); 6348c2ecf20Sopenharmony_ci dib8000_write_word(state, 30, (u16) ((timf) & 0xffff)); 6358c2ecf20Sopenharmony_ci 6368c2ecf20Sopenharmony_ci return 0; 6378c2ecf20Sopenharmony_ci} 6388c2ecf20Sopenharmony_ci 6398c2ecf20Sopenharmony_cistatic int dib8000_sad_calib(struct dib8000_state *state) 6408c2ecf20Sopenharmony_ci{ 6418c2ecf20Sopenharmony_ci u8 sad_sel = 3; 6428c2ecf20Sopenharmony_ci 6438c2ecf20Sopenharmony_ci if (state->revision == 0x8090) { 6448c2ecf20Sopenharmony_ci dib8000_write_word(state, 922, (sad_sel << 2)); 6458c2ecf20Sopenharmony_ci dib8000_write_word(state, 923, 2048); 6468c2ecf20Sopenharmony_ci 6478c2ecf20Sopenharmony_ci dib8000_write_word(state, 922, (sad_sel << 2) | 0x1); 6488c2ecf20Sopenharmony_ci dib8000_write_word(state, 922, (sad_sel << 2)); 6498c2ecf20Sopenharmony_ci } else { 6508c2ecf20Sopenharmony_ci /* internal */ 6518c2ecf20Sopenharmony_ci dib8000_write_word(state, 923, (0 << 1) | (0 << 0)); 6528c2ecf20Sopenharmony_ci dib8000_write_word(state, 924, 776); 6538c2ecf20Sopenharmony_ci 6548c2ecf20Sopenharmony_ci /* do the calibration */ 6558c2ecf20Sopenharmony_ci dib8000_write_word(state, 923, (1 << 0)); 6568c2ecf20Sopenharmony_ci dib8000_write_word(state, 923, (0 << 0)); 6578c2ecf20Sopenharmony_ci } 6588c2ecf20Sopenharmony_ci 6598c2ecf20Sopenharmony_ci msleep(1); 6608c2ecf20Sopenharmony_ci return 0; 6618c2ecf20Sopenharmony_ci} 6628c2ecf20Sopenharmony_ci 6638c2ecf20Sopenharmony_cistatic int dib8000_set_wbd_ref(struct dvb_frontend *fe, u16 value) 6648c2ecf20Sopenharmony_ci{ 6658c2ecf20Sopenharmony_ci struct dib8000_state *state = fe->demodulator_priv; 6668c2ecf20Sopenharmony_ci if (value > 4095) 6678c2ecf20Sopenharmony_ci value = 4095; 6688c2ecf20Sopenharmony_ci state->wbd_ref = value; 6698c2ecf20Sopenharmony_ci return dib8000_write_word(state, 106, value); 6708c2ecf20Sopenharmony_ci} 6718c2ecf20Sopenharmony_ci 6728c2ecf20Sopenharmony_cistatic void dib8000_reset_pll_common(struct dib8000_state *state, const struct dibx000_bandwidth_config *bw) 6738c2ecf20Sopenharmony_ci{ 6748c2ecf20Sopenharmony_ci dprintk("ifreq: %d %x, inversion: %d\n", bw->ifreq, bw->ifreq, bw->ifreq >> 25); 6758c2ecf20Sopenharmony_ci if (state->revision != 0x8090) { 6768c2ecf20Sopenharmony_ci dib8000_write_word(state, 23, 6778c2ecf20Sopenharmony_ci (u16) (((bw->internal * 1000) >> 16) & 0xffff)); 6788c2ecf20Sopenharmony_ci dib8000_write_word(state, 24, 6798c2ecf20Sopenharmony_ci (u16) ((bw->internal * 1000) & 0xffff)); 6808c2ecf20Sopenharmony_ci } else { 6818c2ecf20Sopenharmony_ci dib8000_write_word(state, 23, (u16) (((bw->internal / 2 * 1000) >> 16) & 0xffff)); 6828c2ecf20Sopenharmony_ci dib8000_write_word(state, 24, 6838c2ecf20Sopenharmony_ci (u16) ((bw->internal / 2 * 1000) & 0xffff)); 6848c2ecf20Sopenharmony_ci } 6858c2ecf20Sopenharmony_ci dib8000_write_word(state, 27, (u16) ((bw->ifreq >> 16) & 0x01ff)); 6868c2ecf20Sopenharmony_ci dib8000_write_word(state, 28, (u16) (bw->ifreq & 0xffff)); 6878c2ecf20Sopenharmony_ci dib8000_write_word(state, 26, (u16) ((bw->ifreq >> 25) & 0x0003)); 6888c2ecf20Sopenharmony_ci 6898c2ecf20Sopenharmony_ci if (state->revision != 0x8090) 6908c2ecf20Sopenharmony_ci dib8000_write_word(state, 922, bw->sad_cfg); 6918c2ecf20Sopenharmony_ci} 6928c2ecf20Sopenharmony_ci 6938c2ecf20Sopenharmony_cistatic void dib8000_reset_pll(struct dib8000_state *state) 6948c2ecf20Sopenharmony_ci{ 6958c2ecf20Sopenharmony_ci const struct dibx000_bandwidth_config *pll = state->cfg.pll; 6968c2ecf20Sopenharmony_ci u16 clk_cfg1, reg; 6978c2ecf20Sopenharmony_ci 6988c2ecf20Sopenharmony_ci if (state->revision != 0x8090) { 6998c2ecf20Sopenharmony_ci dib8000_write_word(state, 901, 7008c2ecf20Sopenharmony_ci (pll->pll_prediv << 8) | (pll->pll_ratio << 0)); 7018c2ecf20Sopenharmony_ci 7028c2ecf20Sopenharmony_ci clk_cfg1 = (1 << 10) | (0 << 9) | (pll->IO_CLK_en_core << 8) | 7038c2ecf20Sopenharmony_ci (pll->bypclk_div << 5) | (pll->enable_refdiv << 4) | 7048c2ecf20Sopenharmony_ci (1 << 3) | (pll->pll_range << 1) | 7058c2ecf20Sopenharmony_ci (pll->pll_reset << 0); 7068c2ecf20Sopenharmony_ci 7078c2ecf20Sopenharmony_ci dib8000_write_word(state, 902, clk_cfg1); 7088c2ecf20Sopenharmony_ci clk_cfg1 = (clk_cfg1 & 0xfff7) | (pll->pll_bypass << 3); 7098c2ecf20Sopenharmony_ci dib8000_write_word(state, 902, clk_cfg1); 7108c2ecf20Sopenharmony_ci 7118c2ecf20Sopenharmony_ci dprintk("clk_cfg1: 0x%04x\n", clk_cfg1); 7128c2ecf20Sopenharmony_ci 7138c2ecf20Sopenharmony_ci /* smpl_cfg: P_refclksel=2, P_ensmplsel=1 nodivsmpl=1 */ 7148c2ecf20Sopenharmony_ci if (state->cfg.pll->ADClkSrc == 0) 7158c2ecf20Sopenharmony_ci dib8000_write_word(state, 904, 7168c2ecf20Sopenharmony_ci (0 << 15) | (0 << 12) | (0 << 10) | 7178c2ecf20Sopenharmony_ci (pll->modulo << 8) | 7188c2ecf20Sopenharmony_ci (pll->ADClkSrc << 7) | (0 << 1)); 7198c2ecf20Sopenharmony_ci else if (state->cfg.refclksel != 0) 7208c2ecf20Sopenharmony_ci dib8000_write_word(state, 904, (0 << 15) | (1 << 12) | 7218c2ecf20Sopenharmony_ci ((state->cfg.refclksel & 0x3) << 10) | 7228c2ecf20Sopenharmony_ci (pll->modulo << 8) | 7238c2ecf20Sopenharmony_ci (pll->ADClkSrc << 7) | (0 << 1)); 7248c2ecf20Sopenharmony_ci else 7258c2ecf20Sopenharmony_ci dib8000_write_word(state, 904, (0 << 15) | (1 << 12) | 7268c2ecf20Sopenharmony_ci (3 << 10) | (pll->modulo << 8) | 7278c2ecf20Sopenharmony_ci (pll->ADClkSrc << 7) | (0 << 1)); 7288c2ecf20Sopenharmony_ci } else { 7298c2ecf20Sopenharmony_ci dib8000_write_word(state, 1856, (!pll->pll_reset<<13) | 7308c2ecf20Sopenharmony_ci (pll->pll_range<<12) | (pll->pll_ratio<<6) | 7318c2ecf20Sopenharmony_ci (pll->pll_prediv)); 7328c2ecf20Sopenharmony_ci 7338c2ecf20Sopenharmony_ci reg = dib8000_read_word(state, 1857); 7348c2ecf20Sopenharmony_ci dib8000_write_word(state, 1857, reg|(!pll->pll_bypass<<15)); 7358c2ecf20Sopenharmony_ci 7368c2ecf20Sopenharmony_ci reg = dib8000_read_word(state, 1858); /* Force clk out pll /2 */ 7378c2ecf20Sopenharmony_ci dib8000_write_word(state, 1858, reg | 1); 7388c2ecf20Sopenharmony_ci 7398c2ecf20Sopenharmony_ci dib8000_write_word(state, 904, (pll->modulo << 8)); 7408c2ecf20Sopenharmony_ci } 7418c2ecf20Sopenharmony_ci 7428c2ecf20Sopenharmony_ci dib8000_reset_pll_common(state, pll); 7438c2ecf20Sopenharmony_ci} 7448c2ecf20Sopenharmony_ci 7458c2ecf20Sopenharmony_cistatic int dib8000_update_pll(struct dvb_frontend *fe, 7468c2ecf20Sopenharmony_ci struct dibx000_bandwidth_config *pll, u32 bw, u8 ratio) 7478c2ecf20Sopenharmony_ci{ 7488c2ecf20Sopenharmony_ci struct dib8000_state *state = fe->demodulator_priv; 7498c2ecf20Sopenharmony_ci u16 reg_1857, reg_1856 = dib8000_read_word(state, 1856); 7508c2ecf20Sopenharmony_ci u8 loopdiv, prediv, oldprediv = state->cfg.pll->pll_prediv ; 7518c2ecf20Sopenharmony_ci u32 internal, xtal; 7528c2ecf20Sopenharmony_ci 7538c2ecf20Sopenharmony_ci /* get back old values */ 7548c2ecf20Sopenharmony_ci prediv = reg_1856 & 0x3f; 7558c2ecf20Sopenharmony_ci loopdiv = (reg_1856 >> 6) & 0x3f; 7568c2ecf20Sopenharmony_ci 7578c2ecf20Sopenharmony_ci if ((pll == NULL) || (pll->pll_prediv == prediv && 7588c2ecf20Sopenharmony_ci pll->pll_ratio == loopdiv)) 7598c2ecf20Sopenharmony_ci return -EINVAL; 7608c2ecf20Sopenharmony_ci 7618c2ecf20Sopenharmony_ci dprintk("Updating pll (prediv: old = %d new = %d ; loopdiv : old = %d new = %d)\n", prediv, pll->pll_prediv, loopdiv, pll->pll_ratio); 7628c2ecf20Sopenharmony_ci if (state->revision == 0x8090) { 7638c2ecf20Sopenharmony_ci reg_1856 &= 0xf000; 7648c2ecf20Sopenharmony_ci reg_1857 = dib8000_read_word(state, 1857); 7658c2ecf20Sopenharmony_ci /* disable PLL */ 7668c2ecf20Sopenharmony_ci dib8000_write_word(state, 1857, reg_1857 & ~(1 << 15)); 7678c2ecf20Sopenharmony_ci 7688c2ecf20Sopenharmony_ci dib8000_write_word(state, 1856, reg_1856 | 7698c2ecf20Sopenharmony_ci ((pll->pll_ratio & 0x3f) << 6) | 7708c2ecf20Sopenharmony_ci (pll->pll_prediv & 0x3f)); 7718c2ecf20Sopenharmony_ci 7728c2ecf20Sopenharmony_ci /* write new system clk into P_sec_len */ 7738c2ecf20Sopenharmony_ci internal = dib8000_read32(state, 23) / 1000; 7748c2ecf20Sopenharmony_ci dprintk("Old Internal = %d\n", internal); 7758c2ecf20Sopenharmony_ci xtal = 2 * (internal / loopdiv) * prediv; 7768c2ecf20Sopenharmony_ci internal = 1000 * (xtal/pll->pll_prediv) * pll->pll_ratio; 7778c2ecf20Sopenharmony_ci dprintk("Xtal = %d , New Fmem = %d New Fdemod = %d, New Fsampling = %d\n", xtal, internal/1000, internal/2000, internal/8000); 7788c2ecf20Sopenharmony_ci dprintk("New Internal = %d\n", internal); 7798c2ecf20Sopenharmony_ci 7808c2ecf20Sopenharmony_ci dib8000_write_word(state, 23, 7818c2ecf20Sopenharmony_ci (u16) (((internal / 2) >> 16) & 0xffff)); 7828c2ecf20Sopenharmony_ci dib8000_write_word(state, 24, (u16) ((internal / 2) & 0xffff)); 7838c2ecf20Sopenharmony_ci /* enable PLL */ 7848c2ecf20Sopenharmony_ci dib8000_write_word(state, 1857, reg_1857 | (1 << 15)); 7858c2ecf20Sopenharmony_ci 7868c2ecf20Sopenharmony_ci while (((dib8000_read_word(state, 1856)>>15)&0x1) != 1) 7878c2ecf20Sopenharmony_ci dprintk("Waiting for PLL to lock\n"); 7888c2ecf20Sopenharmony_ci 7898c2ecf20Sopenharmony_ci /* verify */ 7908c2ecf20Sopenharmony_ci reg_1856 = dib8000_read_word(state, 1856); 7918c2ecf20Sopenharmony_ci dprintk("PLL Updated with prediv = %d and loopdiv = %d\n", 7928c2ecf20Sopenharmony_ci reg_1856&0x3f, (reg_1856>>6)&0x3f); 7938c2ecf20Sopenharmony_ci } else { 7948c2ecf20Sopenharmony_ci if (bw != state->current_demod_bw) { 7958c2ecf20Sopenharmony_ci /** Bandwidth change => force PLL update **/ 7968c2ecf20Sopenharmony_ci dprintk("PLL: Bandwidth Change %d MHz -> %d MHz (prediv: %d->%d)\n", state->current_demod_bw / 1000, bw / 1000, oldprediv, state->cfg.pll->pll_prediv); 7978c2ecf20Sopenharmony_ci 7988c2ecf20Sopenharmony_ci if (state->cfg.pll->pll_prediv != oldprediv) { 7998c2ecf20Sopenharmony_ci /** Full PLL change only if prediv is changed **/ 8008c2ecf20Sopenharmony_ci 8018c2ecf20Sopenharmony_ci /** full update => bypass and reconfigure **/ 8028c2ecf20Sopenharmony_ci dprintk("PLL: New Setting for %d MHz Bandwidth (prediv: %d, ratio: %d)\n", bw/1000, state->cfg.pll->pll_prediv, state->cfg.pll->pll_ratio); 8038c2ecf20Sopenharmony_ci dib8000_write_word(state, 902, dib8000_read_word(state, 902) | (1<<3)); /* bypass PLL */ 8048c2ecf20Sopenharmony_ci dib8000_reset_pll(state); 8058c2ecf20Sopenharmony_ci dib8000_write_word(state, 898, 0x0004); /* sad */ 8068c2ecf20Sopenharmony_ci } else 8078c2ecf20Sopenharmony_ci ratio = state->cfg.pll->pll_ratio; 8088c2ecf20Sopenharmony_ci 8098c2ecf20Sopenharmony_ci state->current_demod_bw = bw; 8108c2ecf20Sopenharmony_ci } 8118c2ecf20Sopenharmony_ci 8128c2ecf20Sopenharmony_ci if (ratio != 0) { 8138c2ecf20Sopenharmony_ci /** ratio update => only change ratio **/ 8148c2ecf20Sopenharmony_ci dprintk("PLL: Update ratio (prediv: %d, ratio: %d)\n", state->cfg.pll->pll_prediv, ratio); 8158c2ecf20Sopenharmony_ci dib8000_write_word(state, 901, (state->cfg.pll->pll_prediv << 8) | (ratio << 0)); /* only the PLL ratio is updated. */ 8168c2ecf20Sopenharmony_ci } 8178c2ecf20Sopenharmony_ci } 8188c2ecf20Sopenharmony_ci 8198c2ecf20Sopenharmony_ci return 0; 8208c2ecf20Sopenharmony_ci} 8218c2ecf20Sopenharmony_ci 8228c2ecf20Sopenharmony_cistatic int dib8000_reset_gpio(struct dib8000_state *st) 8238c2ecf20Sopenharmony_ci{ 8248c2ecf20Sopenharmony_ci /* reset the GPIOs */ 8258c2ecf20Sopenharmony_ci dib8000_write_word(st, 1029, st->cfg.gpio_dir); 8268c2ecf20Sopenharmony_ci dib8000_write_word(st, 1030, st->cfg.gpio_val); 8278c2ecf20Sopenharmony_ci 8288c2ecf20Sopenharmony_ci /* TODO 782 is P_gpio_od */ 8298c2ecf20Sopenharmony_ci 8308c2ecf20Sopenharmony_ci dib8000_write_word(st, 1032, st->cfg.gpio_pwm_pos); 8318c2ecf20Sopenharmony_ci 8328c2ecf20Sopenharmony_ci dib8000_write_word(st, 1037, st->cfg.pwm_freq_div); 8338c2ecf20Sopenharmony_ci return 0; 8348c2ecf20Sopenharmony_ci} 8358c2ecf20Sopenharmony_ci 8368c2ecf20Sopenharmony_cistatic int dib8000_cfg_gpio(struct dib8000_state *st, u8 num, u8 dir, u8 val) 8378c2ecf20Sopenharmony_ci{ 8388c2ecf20Sopenharmony_ci st->cfg.gpio_dir = dib8000_read_word(st, 1029); 8398c2ecf20Sopenharmony_ci st->cfg.gpio_dir &= ~(1 << num); /* reset the direction bit */ 8408c2ecf20Sopenharmony_ci st->cfg.gpio_dir |= (dir & 0x1) << num; /* set the new direction */ 8418c2ecf20Sopenharmony_ci dib8000_write_word(st, 1029, st->cfg.gpio_dir); 8428c2ecf20Sopenharmony_ci 8438c2ecf20Sopenharmony_ci st->cfg.gpio_val = dib8000_read_word(st, 1030); 8448c2ecf20Sopenharmony_ci st->cfg.gpio_val &= ~(1 << num); /* reset the direction bit */ 8458c2ecf20Sopenharmony_ci st->cfg.gpio_val |= (val & 0x01) << num; /* set the new value */ 8468c2ecf20Sopenharmony_ci dib8000_write_word(st, 1030, st->cfg.gpio_val); 8478c2ecf20Sopenharmony_ci 8488c2ecf20Sopenharmony_ci dprintk("gpio dir: %x: gpio val: %x\n", st->cfg.gpio_dir, st->cfg.gpio_val); 8498c2ecf20Sopenharmony_ci 8508c2ecf20Sopenharmony_ci return 0; 8518c2ecf20Sopenharmony_ci} 8528c2ecf20Sopenharmony_ci 8538c2ecf20Sopenharmony_cistatic int dib8000_set_gpio(struct dvb_frontend *fe, u8 num, u8 dir, u8 val) 8548c2ecf20Sopenharmony_ci{ 8558c2ecf20Sopenharmony_ci struct dib8000_state *state = fe->demodulator_priv; 8568c2ecf20Sopenharmony_ci return dib8000_cfg_gpio(state, num, dir, val); 8578c2ecf20Sopenharmony_ci} 8588c2ecf20Sopenharmony_ci 8598c2ecf20Sopenharmony_cistatic const u16 dib8000_defaults[] = { 8608c2ecf20Sopenharmony_ci /* auto search configuration - lock0 by default waiting 8618c2ecf20Sopenharmony_ci * for cpil_lock; lock1 cpil_lock; lock2 tmcc_sync_lock */ 8628c2ecf20Sopenharmony_ci 3, 7, 8638c2ecf20Sopenharmony_ci 0x0004, 8648c2ecf20Sopenharmony_ci 0x0400, 8658c2ecf20Sopenharmony_ci 0x0814, 8668c2ecf20Sopenharmony_ci 8678c2ecf20Sopenharmony_ci 12, 11, 8688c2ecf20Sopenharmony_ci 0x001b, 8698c2ecf20Sopenharmony_ci 0x7740, 8708c2ecf20Sopenharmony_ci 0x005b, 8718c2ecf20Sopenharmony_ci 0x8d80, 8728c2ecf20Sopenharmony_ci 0x01c9, 8738c2ecf20Sopenharmony_ci 0xc380, 8748c2ecf20Sopenharmony_ci 0x0000, 8758c2ecf20Sopenharmony_ci 0x0080, 8768c2ecf20Sopenharmony_ci 0x0000, 8778c2ecf20Sopenharmony_ci 0x0090, 8788c2ecf20Sopenharmony_ci 0x0001, 8798c2ecf20Sopenharmony_ci 0xd4c0, 8808c2ecf20Sopenharmony_ci 8818c2ecf20Sopenharmony_ci /*1, 32, 8828c2ecf20Sopenharmony_ci 0x6680 // P_corm_thres Lock algorithms configuration */ 8838c2ecf20Sopenharmony_ci 8848c2ecf20Sopenharmony_ci 11, 80, /* set ADC level to -16 */ 8858c2ecf20Sopenharmony_ci (1 << 13) - 825 - 117, 8868c2ecf20Sopenharmony_ci (1 << 13) - 837 - 117, 8878c2ecf20Sopenharmony_ci (1 << 13) - 811 - 117, 8888c2ecf20Sopenharmony_ci (1 << 13) - 766 - 117, 8898c2ecf20Sopenharmony_ci (1 << 13) - 737 - 117, 8908c2ecf20Sopenharmony_ci (1 << 13) - 693 - 117, 8918c2ecf20Sopenharmony_ci (1 << 13) - 648 - 117, 8928c2ecf20Sopenharmony_ci (1 << 13) - 619 - 117, 8938c2ecf20Sopenharmony_ci (1 << 13) - 575 - 117, 8948c2ecf20Sopenharmony_ci (1 << 13) - 531 - 117, 8958c2ecf20Sopenharmony_ci (1 << 13) - 501 - 117, 8968c2ecf20Sopenharmony_ci 8978c2ecf20Sopenharmony_ci 4, 108, 8988c2ecf20Sopenharmony_ci 0, 8998c2ecf20Sopenharmony_ci 0, 9008c2ecf20Sopenharmony_ci 0, 9018c2ecf20Sopenharmony_ci 0, 9028c2ecf20Sopenharmony_ci 9038c2ecf20Sopenharmony_ci 1, 175, 9048c2ecf20Sopenharmony_ci 0x0410, 9058c2ecf20Sopenharmony_ci 1, 179, 9068c2ecf20Sopenharmony_ci 8192, // P_fft_nb_to_cut 9078c2ecf20Sopenharmony_ci 9088c2ecf20Sopenharmony_ci 6, 181, 9098c2ecf20Sopenharmony_ci 0x2800, // P_coff_corthres_ ( 2k 4k 8k ) 0x2800 9108c2ecf20Sopenharmony_ci 0x2800, 9118c2ecf20Sopenharmony_ci 0x2800, 9128c2ecf20Sopenharmony_ci 0x2800, // P_coff_cpilthres_ ( 2k 4k 8k ) 0x2800 9138c2ecf20Sopenharmony_ci 0x2800, 9148c2ecf20Sopenharmony_ci 0x2800, 9158c2ecf20Sopenharmony_ci 9168c2ecf20Sopenharmony_ci 2, 193, 9178c2ecf20Sopenharmony_ci 0x0666, // P_pha3_thres 9188c2ecf20Sopenharmony_ci 0x0000, // P_cti_use_cpe, P_cti_use_prog 9198c2ecf20Sopenharmony_ci 9208c2ecf20Sopenharmony_ci 2, 205, 9218c2ecf20Sopenharmony_ci 0x200f, // P_cspu_regul, P_cspu_win_cut 9228c2ecf20Sopenharmony_ci 0x000f, // P_des_shift_work 9238c2ecf20Sopenharmony_ci 9248c2ecf20Sopenharmony_ci 5, 215, 9258c2ecf20Sopenharmony_ci 0x023d, // P_adp_regul_cnt 9268c2ecf20Sopenharmony_ci 0x00a4, // P_adp_noise_cnt 9278c2ecf20Sopenharmony_ci 0x00a4, // P_adp_regul_ext 9288c2ecf20Sopenharmony_ci 0x7ff0, // P_adp_noise_ext 9298c2ecf20Sopenharmony_ci 0x3ccc, // P_adp_fil 9308c2ecf20Sopenharmony_ci 9318c2ecf20Sopenharmony_ci 1, 230, 9328c2ecf20Sopenharmony_ci 0x0000, // P_2d_byp_ti_num 9338c2ecf20Sopenharmony_ci 9348c2ecf20Sopenharmony_ci 1, 263, 9358c2ecf20Sopenharmony_ci 0x800, //P_equal_thres_wgn 9368c2ecf20Sopenharmony_ci 9378c2ecf20Sopenharmony_ci 1, 268, 9388c2ecf20Sopenharmony_ci (2 << 9) | 39, // P_equal_ctrl_synchro, P_equal_speedmode 9398c2ecf20Sopenharmony_ci 9408c2ecf20Sopenharmony_ci 1, 270, 9418c2ecf20Sopenharmony_ci 0x0001, // P_div_lock0_wait 9428c2ecf20Sopenharmony_ci 1, 285, 9438c2ecf20Sopenharmony_ci 0x0020, //p_fec_ 9448c2ecf20Sopenharmony_ci 1, 299, 9458c2ecf20Sopenharmony_ci 0x0062, /* P_smo_mode, P_smo_rs_discard, P_smo_fifo_flush, P_smo_pid_parse, P_smo_error_discard */ 9468c2ecf20Sopenharmony_ci 9478c2ecf20Sopenharmony_ci 1, 338, 9488c2ecf20Sopenharmony_ci (1 << 12) | // P_ctrl_corm_thres4pre_freq_inh=1 9498c2ecf20Sopenharmony_ci (1 << 10) | 9508c2ecf20Sopenharmony_ci (0 << 9) | /* P_ctrl_pre_freq_inh=0 */ 9518c2ecf20Sopenharmony_ci (3 << 5) | /* P_ctrl_pre_freq_step=3 */ 9528c2ecf20Sopenharmony_ci (1 << 0), /* P_pre_freq_win_len=1 */ 9538c2ecf20Sopenharmony_ci 9548c2ecf20Sopenharmony_ci 0, 9558c2ecf20Sopenharmony_ci}; 9568c2ecf20Sopenharmony_ci 9578c2ecf20Sopenharmony_cistatic u16 dib8000_identify(struct i2c_device *client) 9588c2ecf20Sopenharmony_ci{ 9598c2ecf20Sopenharmony_ci u16 value; 9608c2ecf20Sopenharmony_ci 9618c2ecf20Sopenharmony_ci //because of glitches sometimes 9628c2ecf20Sopenharmony_ci value = dib8000_i2c_read16(client, 896); 9638c2ecf20Sopenharmony_ci 9648c2ecf20Sopenharmony_ci if ((value = dib8000_i2c_read16(client, 896)) != 0x01b3) { 9658c2ecf20Sopenharmony_ci dprintk("wrong Vendor ID (read=0x%x)\n", value); 9668c2ecf20Sopenharmony_ci return 0; 9678c2ecf20Sopenharmony_ci } 9688c2ecf20Sopenharmony_ci 9698c2ecf20Sopenharmony_ci value = dib8000_i2c_read16(client, 897); 9708c2ecf20Sopenharmony_ci if (value != 0x8000 && value != 0x8001 && 9718c2ecf20Sopenharmony_ci value != 0x8002 && value != 0x8090) { 9728c2ecf20Sopenharmony_ci dprintk("wrong Device ID (%x)\n", value); 9738c2ecf20Sopenharmony_ci return 0; 9748c2ecf20Sopenharmony_ci } 9758c2ecf20Sopenharmony_ci 9768c2ecf20Sopenharmony_ci switch (value) { 9778c2ecf20Sopenharmony_ci case 0x8000: 9788c2ecf20Sopenharmony_ci dprintk("found DiB8000A\n"); 9798c2ecf20Sopenharmony_ci break; 9808c2ecf20Sopenharmony_ci case 0x8001: 9818c2ecf20Sopenharmony_ci dprintk("found DiB8000B\n"); 9828c2ecf20Sopenharmony_ci break; 9838c2ecf20Sopenharmony_ci case 0x8002: 9848c2ecf20Sopenharmony_ci dprintk("found DiB8000C\n"); 9858c2ecf20Sopenharmony_ci break; 9868c2ecf20Sopenharmony_ci case 0x8090: 9878c2ecf20Sopenharmony_ci dprintk("found DiB8096P\n"); 9888c2ecf20Sopenharmony_ci break; 9898c2ecf20Sopenharmony_ci } 9908c2ecf20Sopenharmony_ci return value; 9918c2ecf20Sopenharmony_ci} 9928c2ecf20Sopenharmony_ci 9938c2ecf20Sopenharmony_cistatic int dib8000_read_unc_blocks(struct dvb_frontend *fe, u32 *unc); 9948c2ecf20Sopenharmony_ci 9958c2ecf20Sopenharmony_cistatic void dib8000_reset_stats(struct dvb_frontend *fe) 9968c2ecf20Sopenharmony_ci{ 9978c2ecf20Sopenharmony_ci struct dib8000_state *state = fe->demodulator_priv; 9988c2ecf20Sopenharmony_ci struct dtv_frontend_properties *c = &state->fe[0]->dtv_property_cache; 9998c2ecf20Sopenharmony_ci u32 ucb; 10008c2ecf20Sopenharmony_ci 10018c2ecf20Sopenharmony_ci memset(&c->strength, 0, sizeof(c->strength)); 10028c2ecf20Sopenharmony_ci memset(&c->cnr, 0, sizeof(c->cnr)); 10038c2ecf20Sopenharmony_ci memset(&c->post_bit_error, 0, sizeof(c->post_bit_error)); 10048c2ecf20Sopenharmony_ci memset(&c->post_bit_count, 0, sizeof(c->post_bit_count)); 10058c2ecf20Sopenharmony_ci memset(&c->block_error, 0, sizeof(c->block_error)); 10068c2ecf20Sopenharmony_ci 10078c2ecf20Sopenharmony_ci c->strength.len = 1; 10088c2ecf20Sopenharmony_ci c->cnr.len = 1; 10098c2ecf20Sopenharmony_ci c->block_error.len = 1; 10108c2ecf20Sopenharmony_ci c->block_count.len = 1; 10118c2ecf20Sopenharmony_ci c->post_bit_error.len = 1; 10128c2ecf20Sopenharmony_ci c->post_bit_count.len = 1; 10138c2ecf20Sopenharmony_ci 10148c2ecf20Sopenharmony_ci c->strength.stat[0].scale = FE_SCALE_DECIBEL; 10158c2ecf20Sopenharmony_ci c->strength.stat[0].uvalue = 0; 10168c2ecf20Sopenharmony_ci 10178c2ecf20Sopenharmony_ci c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 10188c2ecf20Sopenharmony_ci c->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 10198c2ecf20Sopenharmony_ci c->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 10208c2ecf20Sopenharmony_ci c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 10218c2ecf20Sopenharmony_ci c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 10228c2ecf20Sopenharmony_ci 10238c2ecf20Sopenharmony_ci dib8000_read_unc_blocks(fe, &ucb); 10248c2ecf20Sopenharmony_ci 10258c2ecf20Sopenharmony_ci state->init_ucb = -ucb; 10268c2ecf20Sopenharmony_ci state->ber_jiffies_stats = 0; 10278c2ecf20Sopenharmony_ci state->per_jiffies_stats = 0; 10288c2ecf20Sopenharmony_ci memset(&state->ber_jiffies_stats_layer, 0, 10298c2ecf20Sopenharmony_ci sizeof(state->ber_jiffies_stats_layer)); 10308c2ecf20Sopenharmony_ci} 10318c2ecf20Sopenharmony_ci 10328c2ecf20Sopenharmony_cistatic int dib8000_reset(struct dvb_frontend *fe) 10338c2ecf20Sopenharmony_ci{ 10348c2ecf20Sopenharmony_ci struct dib8000_state *state = fe->demodulator_priv; 10358c2ecf20Sopenharmony_ci 10368c2ecf20Sopenharmony_ci if ((state->revision = dib8000_identify(&state->i2c)) == 0) 10378c2ecf20Sopenharmony_ci return -EINVAL; 10388c2ecf20Sopenharmony_ci 10398c2ecf20Sopenharmony_ci /* sram lead in, rdy */ 10408c2ecf20Sopenharmony_ci if (state->revision != 0x8090) 10418c2ecf20Sopenharmony_ci dib8000_write_word(state, 1287, 0x0003); 10428c2ecf20Sopenharmony_ci 10438c2ecf20Sopenharmony_ci if (state->revision == 0x8000) 10448c2ecf20Sopenharmony_ci dprintk("error : dib8000 MA not supported\n"); 10458c2ecf20Sopenharmony_ci 10468c2ecf20Sopenharmony_ci dibx000_reset_i2c_master(&state->i2c_master); 10478c2ecf20Sopenharmony_ci 10488c2ecf20Sopenharmony_ci dib8000_set_power_mode(state, DIB8000_POWER_ALL); 10498c2ecf20Sopenharmony_ci 10508c2ecf20Sopenharmony_ci /* always leave the VBG voltage on - it consumes almost nothing but takes a long time to start */ 10518c2ecf20Sopenharmony_ci dib8000_set_adc_state(state, DIBX000_ADC_OFF); 10528c2ecf20Sopenharmony_ci 10538c2ecf20Sopenharmony_ci /* restart all parts */ 10548c2ecf20Sopenharmony_ci dib8000_write_word(state, 770, 0xffff); 10558c2ecf20Sopenharmony_ci dib8000_write_word(state, 771, 0xffff); 10568c2ecf20Sopenharmony_ci dib8000_write_word(state, 772, 0xfffc); 10578c2ecf20Sopenharmony_ci dib8000_write_word(state, 898, 0x000c); /* restart sad */ 10588c2ecf20Sopenharmony_ci if (state->revision == 0x8090) 10598c2ecf20Sopenharmony_ci dib8000_write_word(state, 1280, 0x0045); 10608c2ecf20Sopenharmony_ci else 10618c2ecf20Sopenharmony_ci dib8000_write_word(state, 1280, 0x004d); 10628c2ecf20Sopenharmony_ci dib8000_write_word(state, 1281, 0x000c); 10638c2ecf20Sopenharmony_ci 10648c2ecf20Sopenharmony_ci dib8000_write_word(state, 770, 0x0000); 10658c2ecf20Sopenharmony_ci dib8000_write_word(state, 771, 0x0000); 10668c2ecf20Sopenharmony_ci dib8000_write_word(state, 772, 0x0000); 10678c2ecf20Sopenharmony_ci dib8000_write_word(state, 898, 0x0004); // sad 10688c2ecf20Sopenharmony_ci dib8000_write_word(state, 1280, 0x0000); 10698c2ecf20Sopenharmony_ci dib8000_write_word(state, 1281, 0x0000); 10708c2ecf20Sopenharmony_ci 10718c2ecf20Sopenharmony_ci /* drives */ 10728c2ecf20Sopenharmony_ci if (state->revision != 0x8090) { 10738c2ecf20Sopenharmony_ci if (state->cfg.drives) 10748c2ecf20Sopenharmony_ci dib8000_write_word(state, 906, state->cfg.drives); 10758c2ecf20Sopenharmony_ci else { 10768c2ecf20Sopenharmony_ci dprintk("using standard PAD-drive-settings, please adjust settings in config-struct to be optimal.\n"); 10778c2ecf20Sopenharmony_ci /* min drive SDRAM - not optimal - adjust */ 10788c2ecf20Sopenharmony_ci dib8000_write_word(state, 906, 0x2d98); 10798c2ecf20Sopenharmony_ci } 10808c2ecf20Sopenharmony_ci } 10818c2ecf20Sopenharmony_ci 10828c2ecf20Sopenharmony_ci dib8000_reset_pll(state); 10838c2ecf20Sopenharmony_ci if (state->revision != 0x8090) 10848c2ecf20Sopenharmony_ci dib8000_write_word(state, 898, 0x0004); 10858c2ecf20Sopenharmony_ci 10868c2ecf20Sopenharmony_ci if (dib8000_reset_gpio(state) != 0) 10878c2ecf20Sopenharmony_ci dprintk("GPIO reset was not successful.\n"); 10888c2ecf20Sopenharmony_ci 10898c2ecf20Sopenharmony_ci if ((state->revision != 0x8090) && 10908c2ecf20Sopenharmony_ci (dib8000_set_output_mode(fe, OUTMODE_HIGH_Z) != 0)) 10918c2ecf20Sopenharmony_ci dprintk("OUTPUT_MODE could not be reset.\n"); 10928c2ecf20Sopenharmony_ci 10938c2ecf20Sopenharmony_ci state->current_agc = NULL; 10948c2ecf20Sopenharmony_ci 10958c2ecf20Sopenharmony_ci // P_iqc_alpha_pha, P_iqc_alpha_amp, P_iqc_dcc_alpha, ... 10968c2ecf20Sopenharmony_ci /* P_iqc_ca2 = 0; P_iqc_impnc_on = 0; P_iqc_mode = 0; */ 10978c2ecf20Sopenharmony_ci if (state->cfg.pll->ifreq == 0) 10988c2ecf20Sopenharmony_ci dib8000_write_word(state, 40, 0x0755); /* P_iqc_corr_inh = 0 enable IQcorr block */ 10998c2ecf20Sopenharmony_ci else 11008c2ecf20Sopenharmony_ci dib8000_write_word(state, 40, 0x1f55); /* P_iqc_corr_inh = 1 disable IQcorr block */ 11018c2ecf20Sopenharmony_ci 11028c2ecf20Sopenharmony_ci { 11038c2ecf20Sopenharmony_ci u16 l = 0, r; 11048c2ecf20Sopenharmony_ci const u16 *n; 11058c2ecf20Sopenharmony_ci n = dib8000_defaults; 11068c2ecf20Sopenharmony_ci l = *n++; 11078c2ecf20Sopenharmony_ci while (l) { 11088c2ecf20Sopenharmony_ci r = *n++; 11098c2ecf20Sopenharmony_ci do { 11108c2ecf20Sopenharmony_ci dib8000_write_word(state, r, *n++); 11118c2ecf20Sopenharmony_ci r++; 11128c2ecf20Sopenharmony_ci } while (--l); 11138c2ecf20Sopenharmony_ci l = *n++; 11148c2ecf20Sopenharmony_ci } 11158c2ecf20Sopenharmony_ci } 11168c2ecf20Sopenharmony_ci 11178c2ecf20Sopenharmony_ci state->isdbt_cfg_loaded = 0; 11188c2ecf20Sopenharmony_ci 11198c2ecf20Sopenharmony_ci //div_cfg override for special configs 11208c2ecf20Sopenharmony_ci if ((state->revision != 8090) && (state->cfg.div_cfg != 0)) 11218c2ecf20Sopenharmony_ci dib8000_write_word(state, 903, state->cfg.div_cfg); 11228c2ecf20Sopenharmony_ci 11238c2ecf20Sopenharmony_ci /* unforce divstr regardless whether i2c enumeration was done or not */ 11248c2ecf20Sopenharmony_ci dib8000_write_word(state, 1285, dib8000_read_word(state, 1285) & ~(1 << 1)); 11258c2ecf20Sopenharmony_ci 11268c2ecf20Sopenharmony_ci dib8000_set_bandwidth(fe, 6000); 11278c2ecf20Sopenharmony_ci 11288c2ecf20Sopenharmony_ci dib8000_set_adc_state(state, DIBX000_SLOW_ADC_ON); 11298c2ecf20Sopenharmony_ci dib8000_sad_calib(state); 11308c2ecf20Sopenharmony_ci if (state->revision != 0x8090) 11318c2ecf20Sopenharmony_ci dib8000_set_adc_state(state, DIBX000_SLOW_ADC_OFF); 11328c2ecf20Sopenharmony_ci 11338c2ecf20Sopenharmony_ci /* ber_rs_len = 3 */ 11348c2ecf20Sopenharmony_ci dib8000_write_word(state, 285, (dib8000_read_word(state, 285) & ~0x60) | (3 << 5)); 11358c2ecf20Sopenharmony_ci 11368c2ecf20Sopenharmony_ci dib8000_set_power_mode(state, DIB8000_POWER_INTERFACE_ONLY); 11378c2ecf20Sopenharmony_ci 11388c2ecf20Sopenharmony_ci dib8000_reset_stats(fe); 11398c2ecf20Sopenharmony_ci 11408c2ecf20Sopenharmony_ci return 0; 11418c2ecf20Sopenharmony_ci} 11428c2ecf20Sopenharmony_ci 11438c2ecf20Sopenharmony_cistatic void dib8000_restart_agc(struct dib8000_state *state) 11448c2ecf20Sopenharmony_ci{ 11458c2ecf20Sopenharmony_ci // P_restart_iqc & P_restart_agc 11468c2ecf20Sopenharmony_ci dib8000_write_word(state, 770, 0x0a00); 11478c2ecf20Sopenharmony_ci dib8000_write_word(state, 770, 0x0000); 11488c2ecf20Sopenharmony_ci} 11498c2ecf20Sopenharmony_ci 11508c2ecf20Sopenharmony_cistatic int dib8000_update_lna(struct dib8000_state *state) 11518c2ecf20Sopenharmony_ci{ 11528c2ecf20Sopenharmony_ci u16 dyn_gain; 11538c2ecf20Sopenharmony_ci 11548c2ecf20Sopenharmony_ci if (state->cfg.update_lna) { 11558c2ecf20Sopenharmony_ci // read dyn_gain here (because it is demod-dependent and not tuner) 11568c2ecf20Sopenharmony_ci dyn_gain = dib8000_read_word(state, 390); 11578c2ecf20Sopenharmony_ci 11588c2ecf20Sopenharmony_ci if (state->cfg.update_lna(state->fe[0], dyn_gain)) { 11598c2ecf20Sopenharmony_ci dib8000_restart_agc(state); 11608c2ecf20Sopenharmony_ci return 1; 11618c2ecf20Sopenharmony_ci } 11628c2ecf20Sopenharmony_ci } 11638c2ecf20Sopenharmony_ci return 0; 11648c2ecf20Sopenharmony_ci} 11658c2ecf20Sopenharmony_ci 11668c2ecf20Sopenharmony_cistatic int dib8000_set_agc_config(struct dib8000_state *state, u8 band) 11678c2ecf20Sopenharmony_ci{ 11688c2ecf20Sopenharmony_ci struct dibx000_agc_config *agc = NULL; 11698c2ecf20Sopenharmony_ci int i; 11708c2ecf20Sopenharmony_ci u16 reg; 11718c2ecf20Sopenharmony_ci 11728c2ecf20Sopenharmony_ci if (state->current_band == band && state->current_agc != NULL) 11738c2ecf20Sopenharmony_ci return 0; 11748c2ecf20Sopenharmony_ci state->current_band = band; 11758c2ecf20Sopenharmony_ci 11768c2ecf20Sopenharmony_ci for (i = 0; i < state->cfg.agc_config_count; i++) 11778c2ecf20Sopenharmony_ci if (state->cfg.agc[i].band_caps & band) { 11788c2ecf20Sopenharmony_ci agc = &state->cfg.agc[i]; 11798c2ecf20Sopenharmony_ci break; 11808c2ecf20Sopenharmony_ci } 11818c2ecf20Sopenharmony_ci 11828c2ecf20Sopenharmony_ci if (agc == NULL) { 11838c2ecf20Sopenharmony_ci dprintk("no valid AGC configuration found for band 0x%02x\n", band); 11848c2ecf20Sopenharmony_ci return -EINVAL; 11858c2ecf20Sopenharmony_ci } 11868c2ecf20Sopenharmony_ci 11878c2ecf20Sopenharmony_ci state->current_agc = agc; 11888c2ecf20Sopenharmony_ci 11898c2ecf20Sopenharmony_ci /* AGC */ 11908c2ecf20Sopenharmony_ci dib8000_write_word(state, 76, agc->setup); 11918c2ecf20Sopenharmony_ci dib8000_write_word(state, 77, agc->inv_gain); 11928c2ecf20Sopenharmony_ci dib8000_write_word(state, 78, agc->time_stabiliz); 11938c2ecf20Sopenharmony_ci dib8000_write_word(state, 101, (agc->alpha_level << 12) | agc->thlock); 11948c2ecf20Sopenharmony_ci 11958c2ecf20Sopenharmony_ci // Demod AGC loop configuration 11968c2ecf20Sopenharmony_ci dib8000_write_word(state, 102, (agc->alpha_mant << 5) | agc->alpha_exp); 11978c2ecf20Sopenharmony_ci dib8000_write_word(state, 103, (agc->beta_mant << 6) | agc->beta_exp); 11988c2ecf20Sopenharmony_ci 11998c2ecf20Sopenharmony_ci dprintk("WBD: ref: %d, sel: %d, active: %d, alpha: %d\n", 12008c2ecf20Sopenharmony_ci state->wbd_ref != 0 ? state->wbd_ref : agc->wbd_ref, agc->wbd_sel, !agc->perform_agc_softsplit, agc->wbd_sel); 12018c2ecf20Sopenharmony_ci 12028c2ecf20Sopenharmony_ci /* AGC continued */ 12038c2ecf20Sopenharmony_ci if (state->wbd_ref != 0) 12048c2ecf20Sopenharmony_ci dib8000_write_word(state, 106, state->wbd_ref); 12058c2ecf20Sopenharmony_ci else // use default 12068c2ecf20Sopenharmony_ci dib8000_write_word(state, 106, agc->wbd_ref); 12078c2ecf20Sopenharmony_ci 12088c2ecf20Sopenharmony_ci if (state->revision == 0x8090) { 12098c2ecf20Sopenharmony_ci reg = dib8000_read_word(state, 922) & (0x3 << 2); 12108c2ecf20Sopenharmony_ci dib8000_write_word(state, 922, reg | (agc->wbd_sel << 2)); 12118c2ecf20Sopenharmony_ci } 12128c2ecf20Sopenharmony_ci 12138c2ecf20Sopenharmony_ci dib8000_write_word(state, 107, (agc->wbd_alpha << 9) | (agc->perform_agc_softsplit << 8)); 12148c2ecf20Sopenharmony_ci dib8000_write_word(state, 108, agc->agc1_max); 12158c2ecf20Sopenharmony_ci dib8000_write_word(state, 109, agc->agc1_min); 12168c2ecf20Sopenharmony_ci dib8000_write_word(state, 110, agc->agc2_max); 12178c2ecf20Sopenharmony_ci dib8000_write_word(state, 111, agc->agc2_min); 12188c2ecf20Sopenharmony_ci dib8000_write_word(state, 112, (agc->agc1_pt1 << 8) | agc->agc1_pt2); 12198c2ecf20Sopenharmony_ci dib8000_write_word(state, 113, (agc->agc1_slope1 << 8) | agc->agc1_slope2); 12208c2ecf20Sopenharmony_ci dib8000_write_word(state, 114, (agc->agc2_pt1 << 8) | agc->agc2_pt2); 12218c2ecf20Sopenharmony_ci dib8000_write_word(state, 115, (agc->agc2_slope1 << 8) | agc->agc2_slope2); 12228c2ecf20Sopenharmony_ci 12238c2ecf20Sopenharmony_ci dib8000_write_word(state, 75, agc->agc1_pt3); 12248c2ecf20Sopenharmony_ci if (state->revision != 0x8090) 12258c2ecf20Sopenharmony_ci dib8000_write_word(state, 923, 12268c2ecf20Sopenharmony_ci (dib8000_read_word(state, 923) & 0xffe3) | 12278c2ecf20Sopenharmony_ci (agc->wbd_inv << 4) | (agc->wbd_sel << 2)); 12288c2ecf20Sopenharmony_ci 12298c2ecf20Sopenharmony_ci return 0; 12308c2ecf20Sopenharmony_ci} 12318c2ecf20Sopenharmony_ci 12328c2ecf20Sopenharmony_cistatic void dib8000_pwm_agc_reset(struct dvb_frontend *fe) 12338c2ecf20Sopenharmony_ci{ 12348c2ecf20Sopenharmony_ci struct dib8000_state *state = fe->demodulator_priv; 12358c2ecf20Sopenharmony_ci dib8000_set_adc_state(state, DIBX000_ADC_ON); 12368c2ecf20Sopenharmony_ci dib8000_set_agc_config(state, (unsigned char)(BAND_OF_FREQUENCY(fe->dtv_property_cache.frequency / 1000))); 12378c2ecf20Sopenharmony_ci} 12388c2ecf20Sopenharmony_ci 12398c2ecf20Sopenharmony_cistatic int dib8000_agc_soft_split(struct dib8000_state *state) 12408c2ecf20Sopenharmony_ci{ 12418c2ecf20Sopenharmony_ci u16 agc, split_offset; 12428c2ecf20Sopenharmony_ci 12438c2ecf20Sopenharmony_ci if (!state->current_agc || !state->current_agc->perform_agc_softsplit || state->current_agc->split.max == 0) 12448c2ecf20Sopenharmony_ci return 0; 12458c2ecf20Sopenharmony_ci 12468c2ecf20Sopenharmony_ci // n_agc_global 12478c2ecf20Sopenharmony_ci agc = dib8000_read_word(state, 390); 12488c2ecf20Sopenharmony_ci 12498c2ecf20Sopenharmony_ci if (agc > state->current_agc->split.min_thres) 12508c2ecf20Sopenharmony_ci split_offset = state->current_agc->split.min; 12518c2ecf20Sopenharmony_ci else if (agc < state->current_agc->split.max_thres) 12528c2ecf20Sopenharmony_ci split_offset = state->current_agc->split.max; 12538c2ecf20Sopenharmony_ci else 12548c2ecf20Sopenharmony_ci split_offset = state->current_agc->split.max * 12558c2ecf20Sopenharmony_ci (agc - state->current_agc->split.min_thres) / 12568c2ecf20Sopenharmony_ci (state->current_agc->split.max_thres - state->current_agc->split.min_thres); 12578c2ecf20Sopenharmony_ci 12588c2ecf20Sopenharmony_ci dprintk("AGC split_offset: %d\n", split_offset); 12598c2ecf20Sopenharmony_ci 12608c2ecf20Sopenharmony_ci // P_agc_force_split and P_agc_split_offset 12618c2ecf20Sopenharmony_ci dib8000_write_word(state, 107, (dib8000_read_word(state, 107) & 0xff00) | split_offset); 12628c2ecf20Sopenharmony_ci return 5000; 12638c2ecf20Sopenharmony_ci} 12648c2ecf20Sopenharmony_ci 12658c2ecf20Sopenharmony_cistatic int dib8000_agc_startup(struct dvb_frontend *fe) 12668c2ecf20Sopenharmony_ci{ 12678c2ecf20Sopenharmony_ci struct dib8000_state *state = fe->demodulator_priv; 12688c2ecf20Sopenharmony_ci enum frontend_tune_state *tune_state = &state->tune_state; 12698c2ecf20Sopenharmony_ci int ret = 0; 12708c2ecf20Sopenharmony_ci u16 reg; 12718c2ecf20Sopenharmony_ci u32 upd_demod_gain_period = 0x8000; 12728c2ecf20Sopenharmony_ci 12738c2ecf20Sopenharmony_ci switch (*tune_state) { 12748c2ecf20Sopenharmony_ci case CT_AGC_START: 12758c2ecf20Sopenharmony_ci // set power-up level: interf+analog+AGC 12768c2ecf20Sopenharmony_ci 12778c2ecf20Sopenharmony_ci if (state->revision != 0x8090) 12788c2ecf20Sopenharmony_ci dib8000_set_adc_state(state, DIBX000_ADC_ON); 12798c2ecf20Sopenharmony_ci else { 12808c2ecf20Sopenharmony_ci dib8000_set_power_mode(state, DIB8000_POWER_ALL); 12818c2ecf20Sopenharmony_ci 12828c2ecf20Sopenharmony_ci reg = dib8000_read_word(state, 1947)&0xff00; 12838c2ecf20Sopenharmony_ci dib8000_write_word(state, 1946, 12848c2ecf20Sopenharmony_ci upd_demod_gain_period & 0xFFFF); 12858c2ecf20Sopenharmony_ci /* bit 14 = enDemodGain */ 12868c2ecf20Sopenharmony_ci dib8000_write_word(state, 1947, reg | (1<<14) | 12878c2ecf20Sopenharmony_ci ((upd_demod_gain_period >> 16) & 0xFF)); 12888c2ecf20Sopenharmony_ci 12898c2ecf20Sopenharmony_ci /* enable adc i & q */ 12908c2ecf20Sopenharmony_ci reg = dib8000_read_word(state, 1920); 12918c2ecf20Sopenharmony_ci dib8000_write_word(state, 1920, (reg | 0x3) & 12928c2ecf20Sopenharmony_ci (~(1 << 7))); 12938c2ecf20Sopenharmony_ci } 12948c2ecf20Sopenharmony_ci 12958c2ecf20Sopenharmony_ci if (dib8000_set_agc_config(state, (unsigned char)(BAND_OF_FREQUENCY(fe->dtv_property_cache.frequency / 1000))) != 0) { 12968c2ecf20Sopenharmony_ci *tune_state = CT_AGC_STOP; 12978c2ecf20Sopenharmony_ci state->status = FE_STATUS_TUNE_FAILED; 12988c2ecf20Sopenharmony_ci break; 12998c2ecf20Sopenharmony_ci } 13008c2ecf20Sopenharmony_ci 13018c2ecf20Sopenharmony_ci ret = 70; 13028c2ecf20Sopenharmony_ci *tune_state = CT_AGC_STEP_0; 13038c2ecf20Sopenharmony_ci break; 13048c2ecf20Sopenharmony_ci 13058c2ecf20Sopenharmony_ci case CT_AGC_STEP_0: 13068c2ecf20Sopenharmony_ci //AGC initialization 13078c2ecf20Sopenharmony_ci if (state->cfg.agc_control) 13088c2ecf20Sopenharmony_ci state->cfg.agc_control(fe, 1); 13098c2ecf20Sopenharmony_ci 13108c2ecf20Sopenharmony_ci dib8000_restart_agc(state); 13118c2ecf20Sopenharmony_ci 13128c2ecf20Sopenharmony_ci // wait AGC rough lock time 13138c2ecf20Sopenharmony_ci ret = 50; 13148c2ecf20Sopenharmony_ci *tune_state = CT_AGC_STEP_1; 13158c2ecf20Sopenharmony_ci break; 13168c2ecf20Sopenharmony_ci 13178c2ecf20Sopenharmony_ci case CT_AGC_STEP_1: 13188c2ecf20Sopenharmony_ci // wait AGC accurate lock time 13198c2ecf20Sopenharmony_ci ret = 70; 13208c2ecf20Sopenharmony_ci 13218c2ecf20Sopenharmony_ci if (dib8000_update_lna(state)) 13228c2ecf20Sopenharmony_ci // wait only AGC rough lock time 13238c2ecf20Sopenharmony_ci ret = 50; 13248c2ecf20Sopenharmony_ci else 13258c2ecf20Sopenharmony_ci *tune_state = CT_AGC_STEP_2; 13268c2ecf20Sopenharmony_ci break; 13278c2ecf20Sopenharmony_ci 13288c2ecf20Sopenharmony_ci case CT_AGC_STEP_2: 13298c2ecf20Sopenharmony_ci dib8000_agc_soft_split(state); 13308c2ecf20Sopenharmony_ci 13318c2ecf20Sopenharmony_ci if (state->cfg.agc_control) 13328c2ecf20Sopenharmony_ci state->cfg.agc_control(fe, 0); 13338c2ecf20Sopenharmony_ci 13348c2ecf20Sopenharmony_ci *tune_state = CT_AGC_STOP; 13358c2ecf20Sopenharmony_ci break; 13368c2ecf20Sopenharmony_ci default: 13378c2ecf20Sopenharmony_ci ret = dib8000_agc_soft_split(state); 13388c2ecf20Sopenharmony_ci break; 13398c2ecf20Sopenharmony_ci } 13408c2ecf20Sopenharmony_ci return ret; 13418c2ecf20Sopenharmony_ci 13428c2ecf20Sopenharmony_ci} 13438c2ecf20Sopenharmony_ci 13448c2ecf20Sopenharmony_cistatic void dib8096p_host_bus_drive(struct dib8000_state *state, u8 drive) 13458c2ecf20Sopenharmony_ci{ 13468c2ecf20Sopenharmony_ci u16 reg; 13478c2ecf20Sopenharmony_ci 13488c2ecf20Sopenharmony_ci drive &= 0x7; 13498c2ecf20Sopenharmony_ci 13508c2ecf20Sopenharmony_ci /* drive host bus 2, 3, 4 */ 13518c2ecf20Sopenharmony_ci reg = dib8000_read_word(state, 1798) & 13528c2ecf20Sopenharmony_ci ~(0x7 | (0x7 << 6) | (0x7 << 12)); 13538c2ecf20Sopenharmony_ci reg |= (drive<<12) | (drive<<6) | drive; 13548c2ecf20Sopenharmony_ci dib8000_write_word(state, 1798, reg); 13558c2ecf20Sopenharmony_ci 13568c2ecf20Sopenharmony_ci /* drive host bus 5,6 */ 13578c2ecf20Sopenharmony_ci reg = dib8000_read_word(state, 1799) & ~((0x7 << 2) | (0x7 << 8)); 13588c2ecf20Sopenharmony_ci reg |= (drive<<8) | (drive<<2); 13598c2ecf20Sopenharmony_ci dib8000_write_word(state, 1799, reg); 13608c2ecf20Sopenharmony_ci 13618c2ecf20Sopenharmony_ci /* drive host bus 7, 8, 9 */ 13628c2ecf20Sopenharmony_ci reg = dib8000_read_word(state, 1800) & 13638c2ecf20Sopenharmony_ci ~(0x7 | (0x7 << 6) | (0x7 << 12)); 13648c2ecf20Sopenharmony_ci reg |= (drive<<12) | (drive<<6) | drive; 13658c2ecf20Sopenharmony_ci dib8000_write_word(state, 1800, reg); 13668c2ecf20Sopenharmony_ci 13678c2ecf20Sopenharmony_ci /* drive host bus 10, 11 */ 13688c2ecf20Sopenharmony_ci reg = dib8000_read_word(state, 1801) & ~((0x7 << 2) | (0x7 << 8)); 13698c2ecf20Sopenharmony_ci reg |= (drive<<8) | (drive<<2); 13708c2ecf20Sopenharmony_ci dib8000_write_word(state, 1801, reg); 13718c2ecf20Sopenharmony_ci 13728c2ecf20Sopenharmony_ci /* drive host bus 12, 13, 14 */ 13738c2ecf20Sopenharmony_ci reg = dib8000_read_word(state, 1802) & 13748c2ecf20Sopenharmony_ci ~(0x7 | (0x7 << 6) | (0x7 << 12)); 13758c2ecf20Sopenharmony_ci reg |= (drive<<12) | (drive<<6) | drive; 13768c2ecf20Sopenharmony_ci dib8000_write_word(state, 1802, reg); 13778c2ecf20Sopenharmony_ci} 13788c2ecf20Sopenharmony_ci 13798c2ecf20Sopenharmony_cistatic u32 dib8096p_calcSyncFreq(u32 P_Kin, u32 P_Kout, 13808c2ecf20Sopenharmony_ci u32 insertExtSynchro, u32 syncSize) 13818c2ecf20Sopenharmony_ci{ 13828c2ecf20Sopenharmony_ci u32 quantif = 3; 13838c2ecf20Sopenharmony_ci u32 nom = (insertExtSynchro * P_Kin+syncSize); 13848c2ecf20Sopenharmony_ci u32 denom = P_Kout; 13858c2ecf20Sopenharmony_ci u32 syncFreq = ((nom << quantif) / denom); 13868c2ecf20Sopenharmony_ci 13878c2ecf20Sopenharmony_ci if ((syncFreq & ((1 << quantif) - 1)) != 0) 13888c2ecf20Sopenharmony_ci syncFreq = (syncFreq >> quantif) + 1; 13898c2ecf20Sopenharmony_ci else 13908c2ecf20Sopenharmony_ci syncFreq = (syncFreq >> quantif); 13918c2ecf20Sopenharmony_ci 13928c2ecf20Sopenharmony_ci if (syncFreq != 0) 13938c2ecf20Sopenharmony_ci syncFreq = syncFreq - 1; 13948c2ecf20Sopenharmony_ci 13958c2ecf20Sopenharmony_ci return syncFreq; 13968c2ecf20Sopenharmony_ci} 13978c2ecf20Sopenharmony_ci 13988c2ecf20Sopenharmony_cistatic void dib8096p_cfg_DibTx(struct dib8000_state *state, u32 P_Kin, 13998c2ecf20Sopenharmony_ci u32 P_Kout, u32 insertExtSynchro, u32 synchroMode, 14008c2ecf20Sopenharmony_ci u32 syncWord, u32 syncSize) 14018c2ecf20Sopenharmony_ci{ 14028c2ecf20Sopenharmony_ci dprintk("Configure DibStream Tx\n"); 14038c2ecf20Sopenharmony_ci 14048c2ecf20Sopenharmony_ci dib8000_write_word(state, 1615, 1); 14058c2ecf20Sopenharmony_ci dib8000_write_word(state, 1603, P_Kin); 14068c2ecf20Sopenharmony_ci dib8000_write_word(state, 1605, P_Kout); 14078c2ecf20Sopenharmony_ci dib8000_write_word(state, 1606, insertExtSynchro); 14088c2ecf20Sopenharmony_ci dib8000_write_word(state, 1608, synchroMode); 14098c2ecf20Sopenharmony_ci dib8000_write_word(state, 1609, (syncWord >> 16) & 0xffff); 14108c2ecf20Sopenharmony_ci dib8000_write_word(state, 1610, syncWord & 0xffff); 14118c2ecf20Sopenharmony_ci dib8000_write_word(state, 1612, syncSize); 14128c2ecf20Sopenharmony_ci dib8000_write_word(state, 1615, 0); 14138c2ecf20Sopenharmony_ci} 14148c2ecf20Sopenharmony_ci 14158c2ecf20Sopenharmony_cistatic void dib8096p_cfg_DibRx(struct dib8000_state *state, u32 P_Kin, 14168c2ecf20Sopenharmony_ci u32 P_Kout, u32 synchroMode, u32 insertExtSynchro, 14178c2ecf20Sopenharmony_ci u32 syncWord, u32 syncSize, u32 dataOutRate) 14188c2ecf20Sopenharmony_ci{ 14198c2ecf20Sopenharmony_ci u32 syncFreq; 14208c2ecf20Sopenharmony_ci 14218c2ecf20Sopenharmony_ci dprintk("Configure DibStream Rx synchroMode = %d\n", synchroMode); 14228c2ecf20Sopenharmony_ci 14238c2ecf20Sopenharmony_ci if ((P_Kin != 0) && (P_Kout != 0)) { 14248c2ecf20Sopenharmony_ci syncFreq = dib8096p_calcSyncFreq(P_Kin, P_Kout, 14258c2ecf20Sopenharmony_ci insertExtSynchro, syncSize); 14268c2ecf20Sopenharmony_ci dib8000_write_word(state, 1542, syncFreq); 14278c2ecf20Sopenharmony_ci } 14288c2ecf20Sopenharmony_ci 14298c2ecf20Sopenharmony_ci dib8000_write_word(state, 1554, 1); 14308c2ecf20Sopenharmony_ci dib8000_write_word(state, 1536, P_Kin); 14318c2ecf20Sopenharmony_ci dib8000_write_word(state, 1537, P_Kout); 14328c2ecf20Sopenharmony_ci dib8000_write_word(state, 1539, synchroMode); 14338c2ecf20Sopenharmony_ci dib8000_write_word(state, 1540, (syncWord >> 16) & 0xffff); 14348c2ecf20Sopenharmony_ci dib8000_write_word(state, 1541, syncWord & 0xffff); 14358c2ecf20Sopenharmony_ci dib8000_write_word(state, 1543, syncSize); 14368c2ecf20Sopenharmony_ci dib8000_write_word(state, 1544, dataOutRate); 14378c2ecf20Sopenharmony_ci dib8000_write_word(state, 1554, 0); 14388c2ecf20Sopenharmony_ci} 14398c2ecf20Sopenharmony_ci 14408c2ecf20Sopenharmony_cistatic void dib8096p_enMpegMux(struct dib8000_state *state, int onoff) 14418c2ecf20Sopenharmony_ci{ 14428c2ecf20Sopenharmony_ci u16 reg_1287; 14438c2ecf20Sopenharmony_ci 14448c2ecf20Sopenharmony_ci reg_1287 = dib8000_read_word(state, 1287); 14458c2ecf20Sopenharmony_ci 14468c2ecf20Sopenharmony_ci switch (onoff) { 14478c2ecf20Sopenharmony_ci case 1: 14488c2ecf20Sopenharmony_ci reg_1287 &= ~(1 << 8); 14498c2ecf20Sopenharmony_ci break; 14508c2ecf20Sopenharmony_ci case 0: 14518c2ecf20Sopenharmony_ci reg_1287 |= (1 << 8); 14528c2ecf20Sopenharmony_ci break; 14538c2ecf20Sopenharmony_ci } 14548c2ecf20Sopenharmony_ci 14558c2ecf20Sopenharmony_ci dib8000_write_word(state, 1287, reg_1287); 14568c2ecf20Sopenharmony_ci} 14578c2ecf20Sopenharmony_ci 14588c2ecf20Sopenharmony_cistatic void dib8096p_configMpegMux(struct dib8000_state *state, 14598c2ecf20Sopenharmony_ci u16 pulseWidth, u16 enSerialMode, u16 enSerialClkDiv2) 14608c2ecf20Sopenharmony_ci{ 14618c2ecf20Sopenharmony_ci u16 reg_1287; 14628c2ecf20Sopenharmony_ci 14638c2ecf20Sopenharmony_ci dprintk("Enable Mpeg mux\n"); 14648c2ecf20Sopenharmony_ci 14658c2ecf20Sopenharmony_ci dib8096p_enMpegMux(state, 0); 14668c2ecf20Sopenharmony_ci 14678c2ecf20Sopenharmony_ci /* If the input mode is MPEG do not divide the serial clock */ 14688c2ecf20Sopenharmony_ci if ((enSerialMode == 1) && (state->input_mode_mpeg == 1)) 14698c2ecf20Sopenharmony_ci enSerialClkDiv2 = 0; 14708c2ecf20Sopenharmony_ci 14718c2ecf20Sopenharmony_ci reg_1287 = ((pulseWidth & 0x1f) << 3) | 14728c2ecf20Sopenharmony_ci ((enSerialMode & 0x1) << 2) | (enSerialClkDiv2 & 0x1); 14738c2ecf20Sopenharmony_ci dib8000_write_word(state, 1287, reg_1287); 14748c2ecf20Sopenharmony_ci 14758c2ecf20Sopenharmony_ci dib8096p_enMpegMux(state, 1); 14768c2ecf20Sopenharmony_ci} 14778c2ecf20Sopenharmony_ci 14788c2ecf20Sopenharmony_cistatic void dib8096p_setDibTxMux(struct dib8000_state *state, int mode) 14798c2ecf20Sopenharmony_ci{ 14808c2ecf20Sopenharmony_ci u16 reg_1288 = dib8000_read_word(state, 1288) & ~(0x7 << 7); 14818c2ecf20Sopenharmony_ci 14828c2ecf20Sopenharmony_ci switch (mode) { 14838c2ecf20Sopenharmony_ci case MPEG_ON_DIBTX: 14848c2ecf20Sopenharmony_ci dprintk("SET MPEG ON DIBSTREAM TX\n"); 14858c2ecf20Sopenharmony_ci dib8096p_cfg_DibTx(state, 8, 5, 0, 0, 0, 0); 14868c2ecf20Sopenharmony_ci reg_1288 |= (1 << 9); break; 14878c2ecf20Sopenharmony_ci case DIV_ON_DIBTX: 14888c2ecf20Sopenharmony_ci dprintk("SET DIV_OUT ON DIBSTREAM TX\n"); 14898c2ecf20Sopenharmony_ci dib8096p_cfg_DibTx(state, 5, 5, 0, 0, 0, 0); 14908c2ecf20Sopenharmony_ci reg_1288 |= (1 << 8); break; 14918c2ecf20Sopenharmony_ci case ADC_ON_DIBTX: 14928c2ecf20Sopenharmony_ci dprintk("SET ADC_OUT ON DIBSTREAM TX\n"); 14938c2ecf20Sopenharmony_ci dib8096p_cfg_DibTx(state, 20, 5, 10, 0, 0, 0); 14948c2ecf20Sopenharmony_ci reg_1288 |= (1 << 7); break; 14958c2ecf20Sopenharmony_ci default: 14968c2ecf20Sopenharmony_ci break; 14978c2ecf20Sopenharmony_ci } 14988c2ecf20Sopenharmony_ci dib8000_write_word(state, 1288, reg_1288); 14998c2ecf20Sopenharmony_ci} 15008c2ecf20Sopenharmony_ci 15018c2ecf20Sopenharmony_cistatic void dib8096p_setHostBusMux(struct dib8000_state *state, int mode) 15028c2ecf20Sopenharmony_ci{ 15038c2ecf20Sopenharmony_ci u16 reg_1288 = dib8000_read_word(state, 1288) & ~(0x7 << 4); 15048c2ecf20Sopenharmony_ci 15058c2ecf20Sopenharmony_ci switch (mode) { 15068c2ecf20Sopenharmony_ci case DEMOUT_ON_HOSTBUS: 15078c2ecf20Sopenharmony_ci dprintk("SET DEM OUT OLD INTERF ON HOST BUS\n"); 15088c2ecf20Sopenharmony_ci dib8096p_enMpegMux(state, 0); 15098c2ecf20Sopenharmony_ci reg_1288 |= (1 << 6); 15108c2ecf20Sopenharmony_ci break; 15118c2ecf20Sopenharmony_ci case DIBTX_ON_HOSTBUS: 15128c2ecf20Sopenharmony_ci dprintk("SET DIBSTREAM TX ON HOST BUS\n"); 15138c2ecf20Sopenharmony_ci dib8096p_enMpegMux(state, 0); 15148c2ecf20Sopenharmony_ci reg_1288 |= (1 << 5); 15158c2ecf20Sopenharmony_ci break; 15168c2ecf20Sopenharmony_ci case MPEG_ON_HOSTBUS: 15178c2ecf20Sopenharmony_ci dprintk("SET MPEG MUX ON HOST BUS\n"); 15188c2ecf20Sopenharmony_ci reg_1288 |= (1 << 4); 15198c2ecf20Sopenharmony_ci break; 15208c2ecf20Sopenharmony_ci default: 15218c2ecf20Sopenharmony_ci break; 15228c2ecf20Sopenharmony_ci } 15238c2ecf20Sopenharmony_ci dib8000_write_word(state, 1288, reg_1288); 15248c2ecf20Sopenharmony_ci} 15258c2ecf20Sopenharmony_ci 15268c2ecf20Sopenharmony_cistatic int dib8096p_set_diversity_in(struct dvb_frontend *fe, int onoff) 15278c2ecf20Sopenharmony_ci{ 15288c2ecf20Sopenharmony_ci struct dib8000_state *state = fe->demodulator_priv; 15298c2ecf20Sopenharmony_ci u16 reg_1287; 15308c2ecf20Sopenharmony_ci 15318c2ecf20Sopenharmony_ci switch (onoff) { 15328c2ecf20Sopenharmony_ci case 0: /* only use the internal way - not the diversity input */ 15338c2ecf20Sopenharmony_ci dprintk("%s mode OFF : by default Enable Mpeg INPUT\n", 15348c2ecf20Sopenharmony_ci __func__); 15358c2ecf20Sopenharmony_ci /* outputRate = 8 */ 15368c2ecf20Sopenharmony_ci dib8096p_cfg_DibRx(state, 8, 5, 0, 0, 0, 8, 0); 15378c2ecf20Sopenharmony_ci 15388c2ecf20Sopenharmony_ci /* Do not divide the serial clock of MPEG MUX in 15398c2ecf20Sopenharmony_ci SERIAL MODE in case input mode MPEG is used */ 15408c2ecf20Sopenharmony_ci reg_1287 = dib8000_read_word(state, 1287); 15418c2ecf20Sopenharmony_ci /* enSerialClkDiv2 == 1 ? */ 15428c2ecf20Sopenharmony_ci if ((reg_1287 & 0x1) == 1) { 15438c2ecf20Sopenharmony_ci /* force enSerialClkDiv2 = 0 */ 15448c2ecf20Sopenharmony_ci reg_1287 &= ~0x1; 15458c2ecf20Sopenharmony_ci dib8000_write_word(state, 1287, reg_1287); 15468c2ecf20Sopenharmony_ci } 15478c2ecf20Sopenharmony_ci state->input_mode_mpeg = 1; 15488c2ecf20Sopenharmony_ci break; 15498c2ecf20Sopenharmony_ci case 1: /* both ways */ 15508c2ecf20Sopenharmony_ci case 2: /* only the diversity input */ 15518c2ecf20Sopenharmony_ci dprintk("%s ON : Enable diversity INPUT\n", __func__); 15528c2ecf20Sopenharmony_ci dib8096p_cfg_DibRx(state, 5, 5, 0, 0, 0, 0, 0); 15538c2ecf20Sopenharmony_ci state->input_mode_mpeg = 0; 15548c2ecf20Sopenharmony_ci break; 15558c2ecf20Sopenharmony_ci } 15568c2ecf20Sopenharmony_ci 15578c2ecf20Sopenharmony_ci dib8000_set_diversity_in(state->fe[0], onoff); 15588c2ecf20Sopenharmony_ci return 0; 15598c2ecf20Sopenharmony_ci} 15608c2ecf20Sopenharmony_ci 15618c2ecf20Sopenharmony_cistatic int dib8096p_set_output_mode(struct dvb_frontend *fe, int mode) 15628c2ecf20Sopenharmony_ci{ 15638c2ecf20Sopenharmony_ci struct dib8000_state *state = fe->demodulator_priv; 15648c2ecf20Sopenharmony_ci u16 outreg, smo_mode, fifo_threshold; 15658c2ecf20Sopenharmony_ci u8 prefer_mpeg_mux_use = 1; 15668c2ecf20Sopenharmony_ci int ret = 0; 15678c2ecf20Sopenharmony_ci 15688c2ecf20Sopenharmony_ci state->output_mode = mode; 15698c2ecf20Sopenharmony_ci dib8096p_host_bus_drive(state, 1); 15708c2ecf20Sopenharmony_ci 15718c2ecf20Sopenharmony_ci fifo_threshold = 1792; 15728c2ecf20Sopenharmony_ci smo_mode = (dib8000_read_word(state, 299) & 0x0050) | (1 << 1); 15738c2ecf20Sopenharmony_ci outreg = dib8000_read_word(state, 1286) & 15748c2ecf20Sopenharmony_ci ~((1 << 10) | (0x7 << 6) | (1 << 1)); 15758c2ecf20Sopenharmony_ci 15768c2ecf20Sopenharmony_ci switch (mode) { 15778c2ecf20Sopenharmony_ci case OUTMODE_HIGH_Z: 15788c2ecf20Sopenharmony_ci outreg = 0; 15798c2ecf20Sopenharmony_ci break; 15808c2ecf20Sopenharmony_ci 15818c2ecf20Sopenharmony_ci case OUTMODE_MPEG2_SERIAL: 15828c2ecf20Sopenharmony_ci if (prefer_mpeg_mux_use) { 15838c2ecf20Sopenharmony_ci dprintk("dib8096P setting output mode TS_SERIAL using Mpeg Mux\n"); 15848c2ecf20Sopenharmony_ci dib8096p_configMpegMux(state, 3, 1, 1); 15858c2ecf20Sopenharmony_ci dib8096p_setHostBusMux(state, MPEG_ON_HOSTBUS); 15868c2ecf20Sopenharmony_ci } else {/* Use Smooth block */ 15878c2ecf20Sopenharmony_ci dprintk("dib8096P setting output mode TS_SERIAL using Smooth bloc\n"); 15888c2ecf20Sopenharmony_ci dib8096p_setHostBusMux(state, 15898c2ecf20Sopenharmony_ci DEMOUT_ON_HOSTBUS); 15908c2ecf20Sopenharmony_ci outreg |= (2 << 6) | (0 << 1); 15918c2ecf20Sopenharmony_ci } 15928c2ecf20Sopenharmony_ci break; 15938c2ecf20Sopenharmony_ci 15948c2ecf20Sopenharmony_ci case OUTMODE_MPEG2_PAR_GATED_CLK: 15958c2ecf20Sopenharmony_ci if (prefer_mpeg_mux_use) { 15968c2ecf20Sopenharmony_ci dprintk("dib8096P setting output mode TS_PARALLEL_GATED using Mpeg Mux\n"); 15978c2ecf20Sopenharmony_ci dib8096p_configMpegMux(state, 2, 0, 0); 15988c2ecf20Sopenharmony_ci dib8096p_setHostBusMux(state, MPEG_ON_HOSTBUS); 15998c2ecf20Sopenharmony_ci } else { /* Use Smooth block */ 16008c2ecf20Sopenharmony_ci dprintk("dib8096P setting output mode TS_PARALLEL_GATED using Smooth block\n"); 16018c2ecf20Sopenharmony_ci dib8096p_setHostBusMux(state, 16028c2ecf20Sopenharmony_ci DEMOUT_ON_HOSTBUS); 16038c2ecf20Sopenharmony_ci outreg |= (0 << 6); 16048c2ecf20Sopenharmony_ci } 16058c2ecf20Sopenharmony_ci break; 16068c2ecf20Sopenharmony_ci 16078c2ecf20Sopenharmony_ci case OUTMODE_MPEG2_PAR_CONT_CLK: /* Using Smooth block only */ 16088c2ecf20Sopenharmony_ci dprintk("dib8096P setting output mode TS_PARALLEL_CONT using Smooth block\n"); 16098c2ecf20Sopenharmony_ci dib8096p_setHostBusMux(state, DEMOUT_ON_HOSTBUS); 16108c2ecf20Sopenharmony_ci outreg |= (1 << 6); 16118c2ecf20Sopenharmony_ci break; 16128c2ecf20Sopenharmony_ci 16138c2ecf20Sopenharmony_ci case OUTMODE_MPEG2_FIFO: 16148c2ecf20Sopenharmony_ci /* Using Smooth block because not supported 16158c2ecf20Sopenharmony_ci by new Mpeg Mux bloc */ 16168c2ecf20Sopenharmony_ci dprintk("dib8096P setting output mode TS_FIFO using Smooth block\n"); 16178c2ecf20Sopenharmony_ci dib8096p_setHostBusMux(state, DEMOUT_ON_HOSTBUS); 16188c2ecf20Sopenharmony_ci outreg |= (5 << 6); 16198c2ecf20Sopenharmony_ci smo_mode |= (3 << 1); 16208c2ecf20Sopenharmony_ci fifo_threshold = 512; 16218c2ecf20Sopenharmony_ci break; 16228c2ecf20Sopenharmony_ci 16238c2ecf20Sopenharmony_ci case OUTMODE_DIVERSITY: 16248c2ecf20Sopenharmony_ci dprintk("dib8096P setting output mode MODE_DIVERSITY\n"); 16258c2ecf20Sopenharmony_ci dib8096p_setDibTxMux(state, DIV_ON_DIBTX); 16268c2ecf20Sopenharmony_ci dib8096p_setHostBusMux(state, DIBTX_ON_HOSTBUS); 16278c2ecf20Sopenharmony_ci break; 16288c2ecf20Sopenharmony_ci 16298c2ecf20Sopenharmony_ci case OUTMODE_ANALOG_ADC: 16308c2ecf20Sopenharmony_ci dprintk("dib8096P setting output mode MODE_ANALOG_ADC\n"); 16318c2ecf20Sopenharmony_ci dib8096p_setDibTxMux(state, ADC_ON_DIBTX); 16328c2ecf20Sopenharmony_ci dib8096p_setHostBusMux(state, DIBTX_ON_HOSTBUS); 16338c2ecf20Sopenharmony_ci break; 16348c2ecf20Sopenharmony_ci } 16358c2ecf20Sopenharmony_ci 16368c2ecf20Sopenharmony_ci if (mode != OUTMODE_HIGH_Z) 16378c2ecf20Sopenharmony_ci outreg |= (1<<10); 16388c2ecf20Sopenharmony_ci 16398c2ecf20Sopenharmony_ci dprintk("output_mpeg2_in_188_bytes = %d\n", 16408c2ecf20Sopenharmony_ci state->cfg.output_mpeg2_in_188_bytes); 16418c2ecf20Sopenharmony_ci if (state->cfg.output_mpeg2_in_188_bytes) 16428c2ecf20Sopenharmony_ci smo_mode |= (1 << 5); 16438c2ecf20Sopenharmony_ci 16448c2ecf20Sopenharmony_ci ret |= dib8000_write_word(state, 299, smo_mode); 16458c2ecf20Sopenharmony_ci /* synchronous fread */ 16468c2ecf20Sopenharmony_ci ret |= dib8000_write_word(state, 299 + 1, fifo_threshold); 16478c2ecf20Sopenharmony_ci ret |= dib8000_write_word(state, 1286, outreg); 16488c2ecf20Sopenharmony_ci 16498c2ecf20Sopenharmony_ci return ret; 16508c2ecf20Sopenharmony_ci} 16518c2ecf20Sopenharmony_ci 16528c2ecf20Sopenharmony_cistatic int map_addr_to_serpar_number(struct i2c_msg *msg) 16538c2ecf20Sopenharmony_ci{ 16548c2ecf20Sopenharmony_ci if (msg->buf[0] <= 15) 16558c2ecf20Sopenharmony_ci msg->buf[0] -= 1; 16568c2ecf20Sopenharmony_ci else if (msg->buf[0] == 17) 16578c2ecf20Sopenharmony_ci msg->buf[0] = 15; 16588c2ecf20Sopenharmony_ci else if (msg->buf[0] == 16) 16598c2ecf20Sopenharmony_ci msg->buf[0] = 17; 16608c2ecf20Sopenharmony_ci else if (msg->buf[0] == 19) 16618c2ecf20Sopenharmony_ci msg->buf[0] = 16; 16628c2ecf20Sopenharmony_ci else if (msg->buf[0] >= 21 && msg->buf[0] <= 25) 16638c2ecf20Sopenharmony_ci msg->buf[0] -= 3; 16648c2ecf20Sopenharmony_ci else if (msg->buf[0] == 28) 16658c2ecf20Sopenharmony_ci msg->buf[0] = 23; 16668c2ecf20Sopenharmony_ci else if (msg->buf[0] == 99) 16678c2ecf20Sopenharmony_ci msg->buf[0] = 99; 16688c2ecf20Sopenharmony_ci else 16698c2ecf20Sopenharmony_ci return -EINVAL; 16708c2ecf20Sopenharmony_ci return 0; 16718c2ecf20Sopenharmony_ci} 16728c2ecf20Sopenharmony_ci 16738c2ecf20Sopenharmony_cistatic int dib8096p_tuner_write_serpar(struct i2c_adapter *i2c_adap, 16748c2ecf20Sopenharmony_ci struct i2c_msg msg[], int num) 16758c2ecf20Sopenharmony_ci{ 16768c2ecf20Sopenharmony_ci struct dib8000_state *state = i2c_get_adapdata(i2c_adap); 16778c2ecf20Sopenharmony_ci u8 n_overflow = 1; 16788c2ecf20Sopenharmony_ci u16 i = 1000; 16798c2ecf20Sopenharmony_ci u16 serpar_num = msg[0].buf[0]; 16808c2ecf20Sopenharmony_ci 16818c2ecf20Sopenharmony_ci while (n_overflow == 1 && i) { 16828c2ecf20Sopenharmony_ci n_overflow = (dib8000_read_word(state, 1984) >> 1) & 0x1; 16838c2ecf20Sopenharmony_ci i--; 16848c2ecf20Sopenharmony_ci if (i == 0) 16858c2ecf20Sopenharmony_ci dprintk("Tuner ITF: write busy (overflow)\n"); 16868c2ecf20Sopenharmony_ci } 16878c2ecf20Sopenharmony_ci dib8000_write_word(state, 1985, (1 << 6) | (serpar_num & 0x3f)); 16888c2ecf20Sopenharmony_ci dib8000_write_word(state, 1986, (msg[0].buf[1] << 8) | msg[0].buf[2]); 16898c2ecf20Sopenharmony_ci 16908c2ecf20Sopenharmony_ci return num; 16918c2ecf20Sopenharmony_ci} 16928c2ecf20Sopenharmony_ci 16938c2ecf20Sopenharmony_cistatic int dib8096p_tuner_read_serpar(struct i2c_adapter *i2c_adap, 16948c2ecf20Sopenharmony_ci struct i2c_msg msg[], int num) 16958c2ecf20Sopenharmony_ci{ 16968c2ecf20Sopenharmony_ci struct dib8000_state *state = i2c_get_adapdata(i2c_adap); 16978c2ecf20Sopenharmony_ci u8 n_overflow = 1, n_empty = 1; 16988c2ecf20Sopenharmony_ci u16 i = 1000; 16998c2ecf20Sopenharmony_ci u16 serpar_num = msg[0].buf[0]; 17008c2ecf20Sopenharmony_ci u16 read_word; 17018c2ecf20Sopenharmony_ci 17028c2ecf20Sopenharmony_ci while (n_overflow == 1 && i) { 17038c2ecf20Sopenharmony_ci n_overflow = (dib8000_read_word(state, 1984) >> 1) & 0x1; 17048c2ecf20Sopenharmony_ci i--; 17058c2ecf20Sopenharmony_ci if (i == 0) 17068c2ecf20Sopenharmony_ci dprintk("TunerITF: read busy (overflow)\n"); 17078c2ecf20Sopenharmony_ci } 17088c2ecf20Sopenharmony_ci dib8000_write_word(state, 1985, (0<<6) | (serpar_num&0x3f)); 17098c2ecf20Sopenharmony_ci 17108c2ecf20Sopenharmony_ci i = 1000; 17118c2ecf20Sopenharmony_ci while (n_empty == 1 && i) { 17128c2ecf20Sopenharmony_ci n_empty = dib8000_read_word(state, 1984)&0x1; 17138c2ecf20Sopenharmony_ci i--; 17148c2ecf20Sopenharmony_ci if (i == 0) 17158c2ecf20Sopenharmony_ci dprintk("TunerITF: read busy (empty)\n"); 17168c2ecf20Sopenharmony_ci } 17178c2ecf20Sopenharmony_ci 17188c2ecf20Sopenharmony_ci read_word = dib8000_read_word(state, 1987); 17198c2ecf20Sopenharmony_ci msg[1].buf[0] = (read_word >> 8) & 0xff; 17208c2ecf20Sopenharmony_ci msg[1].buf[1] = (read_word) & 0xff; 17218c2ecf20Sopenharmony_ci 17228c2ecf20Sopenharmony_ci return num; 17238c2ecf20Sopenharmony_ci} 17248c2ecf20Sopenharmony_ci 17258c2ecf20Sopenharmony_cistatic int dib8096p_tuner_rw_serpar(struct i2c_adapter *i2c_adap, 17268c2ecf20Sopenharmony_ci struct i2c_msg msg[], int num) 17278c2ecf20Sopenharmony_ci{ 17288c2ecf20Sopenharmony_ci if (map_addr_to_serpar_number(&msg[0]) == 0) { 17298c2ecf20Sopenharmony_ci if (num == 1) /* write */ 17308c2ecf20Sopenharmony_ci return dib8096p_tuner_write_serpar(i2c_adap, msg, 1); 17318c2ecf20Sopenharmony_ci else /* read */ 17328c2ecf20Sopenharmony_ci return dib8096p_tuner_read_serpar(i2c_adap, msg, 2); 17338c2ecf20Sopenharmony_ci } 17348c2ecf20Sopenharmony_ci return num; 17358c2ecf20Sopenharmony_ci} 17368c2ecf20Sopenharmony_ci 17378c2ecf20Sopenharmony_cistatic int dib8096p_rw_on_apb(struct i2c_adapter *i2c_adap, 17388c2ecf20Sopenharmony_ci struct i2c_msg msg[], int num, u16 apb_address) 17398c2ecf20Sopenharmony_ci{ 17408c2ecf20Sopenharmony_ci struct dib8000_state *state = i2c_get_adapdata(i2c_adap); 17418c2ecf20Sopenharmony_ci u16 word; 17428c2ecf20Sopenharmony_ci 17438c2ecf20Sopenharmony_ci if (num == 1) { /* write */ 17448c2ecf20Sopenharmony_ci dib8000_write_word(state, apb_address, 17458c2ecf20Sopenharmony_ci ((msg[0].buf[1] << 8) | (msg[0].buf[2]))); 17468c2ecf20Sopenharmony_ci } else { 17478c2ecf20Sopenharmony_ci word = dib8000_read_word(state, apb_address); 17488c2ecf20Sopenharmony_ci msg[1].buf[0] = (word >> 8) & 0xff; 17498c2ecf20Sopenharmony_ci msg[1].buf[1] = (word) & 0xff; 17508c2ecf20Sopenharmony_ci } 17518c2ecf20Sopenharmony_ci return num; 17528c2ecf20Sopenharmony_ci} 17538c2ecf20Sopenharmony_ci 17548c2ecf20Sopenharmony_cistatic int dib8096p_tuner_xfer(struct i2c_adapter *i2c_adap, 17558c2ecf20Sopenharmony_ci struct i2c_msg msg[], int num) 17568c2ecf20Sopenharmony_ci{ 17578c2ecf20Sopenharmony_ci struct dib8000_state *state = i2c_get_adapdata(i2c_adap); 17588c2ecf20Sopenharmony_ci u16 apb_address = 0, word; 17598c2ecf20Sopenharmony_ci int i = 0; 17608c2ecf20Sopenharmony_ci 17618c2ecf20Sopenharmony_ci switch (msg[0].buf[0]) { 17628c2ecf20Sopenharmony_ci case 0x12: 17638c2ecf20Sopenharmony_ci apb_address = 1920; 17648c2ecf20Sopenharmony_ci break; 17658c2ecf20Sopenharmony_ci case 0x14: 17668c2ecf20Sopenharmony_ci apb_address = 1921; 17678c2ecf20Sopenharmony_ci break; 17688c2ecf20Sopenharmony_ci case 0x24: 17698c2ecf20Sopenharmony_ci apb_address = 1922; 17708c2ecf20Sopenharmony_ci break; 17718c2ecf20Sopenharmony_ci case 0x1a: 17728c2ecf20Sopenharmony_ci apb_address = 1923; 17738c2ecf20Sopenharmony_ci break; 17748c2ecf20Sopenharmony_ci case 0x22: 17758c2ecf20Sopenharmony_ci apb_address = 1924; 17768c2ecf20Sopenharmony_ci break; 17778c2ecf20Sopenharmony_ci case 0x33: 17788c2ecf20Sopenharmony_ci apb_address = 1926; 17798c2ecf20Sopenharmony_ci break; 17808c2ecf20Sopenharmony_ci case 0x34: 17818c2ecf20Sopenharmony_ci apb_address = 1927; 17828c2ecf20Sopenharmony_ci break; 17838c2ecf20Sopenharmony_ci case 0x35: 17848c2ecf20Sopenharmony_ci apb_address = 1928; 17858c2ecf20Sopenharmony_ci break; 17868c2ecf20Sopenharmony_ci case 0x36: 17878c2ecf20Sopenharmony_ci apb_address = 1929; 17888c2ecf20Sopenharmony_ci break; 17898c2ecf20Sopenharmony_ci case 0x37: 17908c2ecf20Sopenharmony_ci apb_address = 1930; 17918c2ecf20Sopenharmony_ci break; 17928c2ecf20Sopenharmony_ci case 0x38: 17938c2ecf20Sopenharmony_ci apb_address = 1931; 17948c2ecf20Sopenharmony_ci break; 17958c2ecf20Sopenharmony_ci case 0x39: 17968c2ecf20Sopenharmony_ci apb_address = 1932; 17978c2ecf20Sopenharmony_ci break; 17988c2ecf20Sopenharmony_ci case 0x2a: 17998c2ecf20Sopenharmony_ci apb_address = 1935; 18008c2ecf20Sopenharmony_ci break; 18018c2ecf20Sopenharmony_ci case 0x2b: 18028c2ecf20Sopenharmony_ci apb_address = 1936; 18038c2ecf20Sopenharmony_ci break; 18048c2ecf20Sopenharmony_ci case 0x2c: 18058c2ecf20Sopenharmony_ci apb_address = 1937; 18068c2ecf20Sopenharmony_ci break; 18078c2ecf20Sopenharmony_ci case 0x2d: 18088c2ecf20Sopenharmony_ci apb_address = 1938; 18098c2ecf20Sopenharmony_ci break; 18108c2ecf20Sopenharmony_ci case 0x2e: 18118c2ecf20Sopenharmony_ci apb_address = 1939; 18128c2ecf20Sopenharmony_ci break; 18138c2ecf20Sopenharmony_ci case 0x2f: 18148c2ecf20Sopenharmony_ci apb_address = 1940; 18158c2ecf20Sopenharmony_ci break; 18168c2ecf20Sopenharmony_ci case 0x30: 18178c2ecf20Sopenharmony_ci apb_address = 1941; 18188c2ecf20Sopenharmony_ci break; 18198c2ecf20Sopenharmony_ci case 0x31: 18208c2ecf20Sopenharmony_ci apb_address = 1942; 18218c2ecf20Sopenharmony_ci break; 18228c2ecf20Sopenharmony_ci case 0x32: 18238c2ecf20Sopenharmony_ci apb_address = 1943; 18248c2ecf20Sopenharmony_ci break; 18258c2ecf20Sopenharmony_ci case 0x3e: 18268c2ecf20Sopenharmony_ci apb_address = 1944; 18278c2ecf20Sopenharmony_ci break; 18288c2ecf20Sopenharmony_ci case 0x3f: 18298c2ecf20Sopenharmony_ci apb_address = 1945; 18308c2ecf20Sopenharmony_ci break; 18318c2ecf20Sopenharmony_ci case 0x40: 18328c2ecf20Sopenharmony_ci apb_address = 1948; 18338c2ecf20Sopenharmony_ci break; 18348c2ecf20Sopenharmony_ci case 0x25: 18358c2ecf20Sopenharmony_ci apb_address = 936; 18368c2ecf20Sopenharmony_ci break; 18378c2ecf20Sopenharmony_ci case 0x26: 18388c2ecf20Sopenharmony_ci apb_address = 937; 18398c2ecf20Sopenharmony_ci break; 18408c2ecf20Sopenharmony_ci case 0x27: 18418c2ecf20Sopenharmony_ci apb_address = 938; 18428c2ecf20Sopenharmony_ci break; 18438c2ecf20Sopenharmony_ci case 0x28: 18448c2ecf20Sopenharmony_ci apb_address = 939; 18458c2ecf20Sopenharmony_ci break; 18468c2ecf20Sopenharmony_ci case 0x1d: 18478c2ecf20Sopenharmony_ci /* get sad sel request */ 18488c2ecf20Sopenharmony_ci i = ((dib8000_read_word(state, 921) >> 12)&0x3); 18498c2ecf20Sopenharmony_ci word = dib8000_read_word(state, 924+i); 18508c2ecf20Sopenharmony_ci msg[1].buf[0] = (word >> 8) & 0xff; 18518c2ecf20Sopenharmony_ci msg[1].buf[1] = (word) & 0xff; 18528c2ecf20Sopenharmony_ci return num; 18538c2ecf20Sopenharmony_ci case 0x1f: 18548c2ecf20Sopenharmony_ci if (num == 1) { /* write */ 18558c2ecf20Sopenharmony_ci word = (u16) ((msg[0].buf[1] << 8) | 18568c2ecf20Sopenharmony_ci msg[0].buf[2]); 18578c2ecf20Sopenharmony_ci /* in the VGAMODE Sel are located on bit 0/1 */ 18588c2ecf20Sopenharmony_ci word &= 0x3; 18598c2ecf20Sopenharmony_ci word = (dib8000_read_word(state, 921) & 18608c2ecf20Sopenharmony_ci ~(3<<12)) | (word<<12); 18618c2ecf20Sopenharmony_ci /* Set the proper input */ 18628c2ecf20Sopenharmony_ci dib8000_write_word(state, 921, word); 18638c2ecf20Sopenharmony_ci return num; 18648c2ecf20Sopenharmony_ci } 18658c2ecf20Sopenharmony_ci } 18668c2ecf20Sopenharmony_ci 18678c2ecf20Sopenharmony_ci if (apb_address != 0) /* R/W access via APB */ 18688c2ecf20Sopenharmony_ci return dib8096p_rw_on_apb(i2c_adap, msg, num, apb_address); 18698c2ecf20Sopenharmony_ci else /* R/W access via SERPAR */ 18708c2ecf20Sopenharmony_ci return dib8096p_tuner_rw_serpar(i2c_adap, msg, num); 18718c2ecf20Sopenharmony_ci 18728c2ecf20Sopenharmony_ci return 0; 18738c2ecf20Sopenharmony_ci} 18748c2ecf20Sopenharmony_ci 18758c2ecf20Sopenharmony_cistatic u32 dib8096p_i2c_func(struct i2c_adapter *adapter) 18768c2ecf20Sopenharmony_ci{ 18778c2ecf20Sopenharmony_ci return I2C_FUNC_I2C; 18788c2ecf20Sopenharmony_ci} 18798c2ecf20Sopenharmony_ci 18808c2ecf20Sopenharmony_cistatic const struct i2c_algorithm dib8096p_tuner_xfer_algo = { 18818c2ecf20Sopenharmony_ci .master_xfer = dib8096p_tuner_xfer, 18828c2ecf20Sopenharmony_ci .functionality = dib8096p_i2c_func, 18838c2ecf20Sopenharmony_ci}; 18848c2ecf20Sopenharmony_ci 18858c2ecf20Sopenharmony_cistatic struct i2c_adapter *dib8096p_get_i2c_tuner(struct dvb_frontend *fe) 18868c2ecf20Sopenharmony_ci{ 18878c2ecf20Sopenharmony_ci struct dib8000_state *st = fe->demodulator_priv; 18888c2ecf20Sopenharmony_ci return &st->dib8096p_tuner_adap; 18898c2ecf20Sopenharmony_ci} 18908c2ecf20Sopenharmony_ci 18918c2ecf20Sopenharmony_cistatic int dib8096p_tuner_sleep(struct dvb_frontend *fe, int onoff) 18928c2ecf20Sopenharmony_ci{ 18938c2ecf20Sopenharmony_ci struct dib8000_state *state = fe->demodulator_priv; 18948c2ecf20Sopenharmony_ci u16 en_cur_state; 18958c2ecf20Sopenharmony_ci 18968c2ecf20Sopenharmony_ci dprintk("sleep dib8096p: %d\n", onoff); 18978c2ecf20Sopenharmony_ci 18988c2ecf20Sopenharmony_ci en_cur_state = dib8000_read_word(state, 1922); 18998c2ecf20Sopenharmony_ci 19008c2ecf20Sopenharmony_ci /* LNAs and MIX are ON and therefore it is a valid configuration */ 19018c2ecf20Sopenharmony_ci if (en_cur_state > 0xff) 19028c2ecf20Sopenharmony_ci state->tuner_enable = en_cur_state ; 19038c2ecf20Sopenharmony_ci 19048c2ecf20Sopenharmony_ci if (onoff) 19058c2ecf20Sopenharmony_ci en_cur_state &= 0x00ff; 19068c2ecf20Sopenharmony_ci else { 19078c2ecf20Sopenharmony_ci if (state->tuner_enable != 0) 19088c2ecf20Sopenharmony_ci en_cur_state = state->tuner_enable; 19098c2ecf20Sopenharmony_ci } 19108c2ecf20Sopenharmony_ci 19118c2ecf20Sopenharmony_ci dib8000_write_word(state, 1922, en_cur_state); 19128c2ecf20Sopenharmony_ci 19138c2ecf20Sopenharmony_ci return 0; 19148c2ecf20Sopenharmony_ci} 19158c2ecf20Sopenharmony_ci 19168c2ecf20Sopenharmony_cistatic const s32 lut_1000ln_mant[] = 19178c2ecf20Sopenharmony_ci{ 19188c2ecf20Sopenharmony_ci 908, 7003, 7090, 7170, 7244, 7313, 7377, 7438, 7495, 7549, 7600 19198c2ecf20Sopenharmony_ci}; 19208c2ecf20Sopenharmony_ci 19218c2ecf20Sopenharmony_cistatic s32 dib8000_get_adc_power(struct dvb_frontend *fe, u8 mode) 19228c2ecf20Sopenharmony_ci{ 19238c2ecf20Sopenharmony_ci struct dib8000_state *state = fe->demodulator_priv; 19248c2ecf20Sopenharmony_ci u32 ix = 0, tmp_val = 0, exp = 0, mant = 0; 19258c2ecf20Sopenharmony_ci s32 val; 19268c2ecf20Sopenharmony_ci 19278c2ecf20Sopenharmony_ci val = dib8000_read32(state, 384); 19288c2ecf20Sopenharmony_ci if (mode) { 19298c2ecf20Sopenharmony_ci tmp_val = val; 19308c2ecf20Sopenharmony_ci while (tmp_val >>= 1) 19318c2ecf20Sopenharmony_ci exp++; 19328c2ecf20Sopenharmony_ci mant = (val * 1000 / (1<<exp)); 19338c2ecf20Sopenharmony_ci ix = (u8)((mant-1000)/100); /* index of the LUT */ 19348c2ecf20Sopenharmony_ci val = (lut_1000ln_mant[ix] + 693*(exp-20) - 6908); 19358c2ecf20Sopenharmony_ci val = (val*256)/1000; 19368c2ecf20Sopenharmony_ci } 19378c2ecf20Sopenharmony_ci return val; 19388c2ecf20Sopenharmony_ci} 19398c2ecf20Sopenharmony_ci 19408c2ecf20Sopenharmony_cistatic int dib8090p_get_dc_power(struct dvb_frontend *fe, u8 IQ) 19418c2ecf20Sopenharmony_ci{ 19428c2ecf20Sopenharmony_ci struct dib8000_state *state = fe->demodulator_priv; 19438c2ecf20Sopenharmony_ci int val = 0; 19448c2ecf20Sopenharmony_ci 19458c2ecf20Sopenharmony_ci switch (IQ) { 19468c2ecf20Sopenharmony_ci case 1: 19478c2ecf20Sopenharmony_ci val = dib8000_read_word(state, 403); 19488c2ecf20Sopenharmony_ci break; 19498c2ecf20Sopenharmony_ci case 0: 19508c2ecf20Sopenharmony_ci val = dib8000_read_word(state, 404); 19518c2ecf20Sopenharmony_ci break; 19528c2ecf20Sopenharmony_ci } 19538c2ecf20Sopenharmony_ci if (val & 0x200) 19548c2ecf20Sopenharmony_ci val -= 1024; 19558c2ecf20Sopenharmony_ci 19568c2ecf20Sopenharmony_ci return val; 19578c2ecf20Sopenharmony_ci} 19588c2ecf20Sopenharmony_ci 19598c2ecf20Sopenharmony_cistatic void dib8000_update_timf(struct dib8000_state *state) 19608c2ecf20Sopenharmony_ci{ 19618c2ecf20Sopenharmony_ci u32 timf = state->timf = dib8000_read32(state, 435); 19628c2ecf20Sopenharmony_ci 19638c2ecf20Sopenharmony_ci dib8000_write_word(state, 29, (u16) (timf >> 16)); 19648c2ecf20Sopenharmony_ci dib8000_write_word(state, 30, (u16) (timf & 0xffff)); 19658c2ecf20Sopenharmony_ci dprintk("Updated timing frequency: %d (default: %d)\n", state->timf, state->timf_default); 19668c2ecf20Sopenharmony_ci} 19678c2ecf20Sopenharmony_ci 19688c2ecf20Sopenharmony_cistatic u32 dib8000_ctrl_timf(struct dvb_frontend *fe, uint8_t op, uint32_t timf) 19698c2ecf20Sopenharmony_ci{ 19708c2ecf20Sopenharmony_ci struct dib8000_state *state = fe->demodulator_priv; 19718c2ecf20Sopenharmony_ci 19728c2ecf20Sopenharmony_ci switch (op) { 19738c2ecf20Sopenharmony_ci case DEMOD_TIMF_SET: 19748c2ecf20Sopenharmony_ci state->timf = timf; 19758c2ecf20Sopenharmony_ci break; 19768c2ecf20Sopenharmony_ci case DEMOD_TIMF_UPDATE: 19778c2ecf20Sopenharmony_ci dib8000_update_timf(state); 19788c2ecf20Sopenharmony_ci break; 19798c2ecf20Sopenharmony_ci case DEMOD_TIMF_GET: 19808c2ecf20Sopenharmony_ci break; 19818c2ecf20Sopenharmony_ci } 19828c2ecf20Sopenharmony_ci dib8000_set_bandwidth(state->fe[0], 6000); 19838c2ecf20Sopenharmony_ci 19848c2ecf20Sopenharmony_ci return state->timf; 19858c2ecf20Sopenharmony_ci} 19868c2ecf20Sopenharmony_ci 19878c2ecf20Sopenharmony_cistatic const u16 adc_target_16dB[11] = { 19888c2ecf20Sopenharmony_ci 7250, 7238, 7264, 7309, 7338, 7382, 7427, 7456, 7500, 7544, 7574 19898c2ecf20Sopenharmony_ci}; 19908c2ecf20Sopenharmony_ci 19918c2ecf20Sopenharmony_cistatic const u8 permu_seg[] = { 6, 5, 7, 4, 8, 3, 9, 2, 10, 1, 11, 0, 12 }; 19928c2ecf20Sopenharmony_ci 19938c2ecf20Sopenharmony_cistatic u16 dib8000_set_layer(struct dib8000_state *state, u8 layer_index, u16 max_constellation) 19948c2ecf20Sopenharmony_ci{ 19958c2ecf20Sopenharmony_ci u8 cr, constellation, time_intlv; 19968c2ecf20Sopenharmony_ci struct dtv_frontend_properties *c = &state->fe[0]->dtv_property_cache; 19978c2ecf20Sopenharmony_ci 19988c2ecf20Sopenharmony_ci switch (c->layer[layer_index].modulation) { 19998c2ecf20Sopenharmony_ci case DQPSK: 20008c2ecf20Sopenharmony_ci constellation = 0; 20018c2ecf20Sopenharmony_ci break; 20028c2ecf20Sopenharmony_ci case QPSK: 20038c2ecf20Sopenharmony_ci constellation = 1; 20048c2ecf20Sopenharmony_ci break; 20058c2ecf20Sopenharmony_ci case QAM_16: 20068c2ecf20Sopenharmony_ci constellation = 2; 20078c2ecf20Sopenharmony_ci break; 20088c2ecf20Sopenharmony_ci case QAM_64: 20098c2ecf20Sopenharmony_ci default: 20108c2ecf20Sopenharmony_ci constellation = 3; 20118c2ecf20Sopenharmony_ci break; 20128c2ecf20Sopenharmony_ci } 20138c2ecf20Sopenharmony_ci 20148c2ecf20Sopenharmony_ci switch (c->layer[layer_index].fec) { 20158c2ecf20Sopenharmony_ci case FEC_1_2: 20168c2ecf20Sopenharmony_ci cr = 1; 20178c2ecf20Sopenharmony_ci break; 20188c2ecf20Sopenharmony_ci case FEC_2_3: 20198c2ecf20Sopenharmony_ci cr = 2; 20208c2ecf20Sopenharmony_ci break; 20218c2ecf20Sopenharmony_ci case FEC_3_4: 20228c2ecf20Sopenharmony_ci cr = 3; 20238c2ecf20Sopenharmony_ci break; 20248c2ecf20Sopenharmony_ci case FEC_5_6: 20258c2ecf20Sopenharmony_ci cr = 5; 20268c2ecf20Sopenharmony_ci break; 20278c2ecf20Sopenharmony_ci case FEC_7_8: 20288c2ecf20Sopenharmony_ci default: 20298c2ecf20Sopenharmony_ci cr = 7; 20308c2ecf20Sopenharmony_ci break; 20318c2ecf20Sopenharmony_ci } 20328c2ecf20Sopenharmony_ci 20338c2ecf20Sopenharmony_ci time_intlv = fls(c->layer[layer_index].interleaving); 20348c2ecf20Sopenharmony_ci if (time_intlv > 3 && !(time_intlv == 4 && c->isdbt_sb_mode == 1)) 20358c2ecf20Sopenharmony_ci time_intlv = 0; 20368c2ecf20Sopenharmony_ci 20378c2ecf20Sopenharmony_ci dib8000_write_word(state, 2 + layer_index, (constellation << 10) | ((c->layer[layer_index].segment_count & 0xf) << 6) | (cr << 3) | time_intlv); 20388c2ecf20Sopenharmony_ci if (c->layer[layer_index].segment_count > 0) { 20398c2ecf20Sopenharmony_ci switch (max_constellation) { 20408c2ecf20Sopenharmony_ci case DQPSK: 20418c2ecf20Sopenharmony_ci case QPSK: 20428c2ecf20Sopenharmony_ci if (c->layer[layer_index].modulation == QAM_16 || c->layer[layer_index].modulation == QAM_64) 20438c2ecf20Sopenharmony_ci max_constellation = c->layer[layer_index].modulation; 20448c2ecf20Sopenharmony_ci break; 20458c2ecf20Sopenharmony_ci case QAM_16: 20468c2ecf20Sopenharmony_ci if (c->layer[layer_index].modulation == QAM_64) 20478c2ecf20Sopenharmony_ci max_constellation = c->layer[layer_index].modulation; 20488c2ecf20Sopenharmony_ci break; 20498c2ecf20Sopenharmony_ci } 20508c2ecf20Sopenharmony_ci } 20518c2ecf20Sopenharmony_ci 20528c2ecf20Sopenharmony_ci return max_constellation; 20538c2ecf20Sopenharmony_ci} 20548c2ecf20Sopenharmony_ci 20558c2ecf20Sopenharmony_cistatic const u16 adp_Q64[4] = {0x0148, 0xfff0, 0x00a4, 0xfff8}; /* P_adp_regul_cnt 0.04, P_adp_noise_cnt -0.002, P_adp_regul_ext 0.02, P_adp_noise_ext -0.001 */ 20568c2ecf20Sopenharmony_cistatic const u16 adp_Q16[4] = {0x023d, 0xffdf, 0x00a4, 0xfff0}; /* P_adp_regul_cnt 0.07, P_adp_noise_cnt -0.004, P_adp_regul_ext 0.02, P_adp_noise_ext -0.002 */ 20578c2ecf20Sopenharmony_cistatic const u16 adp_Qdefault[4] = {0x099a, 0xffae, 0x0333, 0xfff8}; /* P_adp_regul_cnt 0.3, P_adp_noise_cnt -0.01, P_adp_regul_ext 0.1, P_adp_noise_ext -0.002 */ 20588c2ecf20Sopenharmony_cistatic u16 dib8000_adp_fine_tune(struct dib8000_state *state, u16 max_constellation) 20598c2ecf20Sopenharmony_ci{ 20608c2ecf20Sopenharmony_ci u16 i, ana_gain = 0; 20618c2ecf20Sopenharmony_ci const u16 *adp; 20628c2ecf20Sopenharmony_ci 20638c2ecf20Sopenharmony_ci /* channel estimation fine configuration */ 20648c2ecf20Sopenharmony_ci switch (max_constellation) { 20658c2ecf20Sopenharmony_ci case QAM_64: 20668c2ecf20Sopenharmony_ci ana_gain = 0x7; 20678c2ecf20Sopenharmony_ci adp = &adp_Q64[0]; 20688c2ecf20Sopenharmony_ci break; 20698c2ecf20Sopenharmony_ci case QAM_16: 20708c2ecf20Sopenharmony_ci ana_gain = 0x7; 20718c2ecf20Sopenharmony_ci adp = &adp_Q16[0]; 20728c2ecf20Sopenharmony_ci break; 20738c2ecf20Sopenharmony_ci default: 20748c2ecf20Sopenharmony_ci ana_gain = 0; 20758c2ecf20Sopenharmony_ci adp = &adp_Qdefault[0]; 20768c2ecf20Sopenharmony_ci break; 20778c2ecf20Sopenharmony_ci } 20788c2ecf20Sopenharmony_ci 20798c2ecf20Sopenharmony_ci for (i = 0; i < 4; i++) 20808c2ecf20Sopenharmony_ci dib8000_write_word(state, 215 + i, adp[i]); 20818c2ecf20Sopenharmony_ci 20828c2ecf20Sopenharmony_ci return ana_gain; 20838c2ecf20Sopenharmony_ci} 20848c2ecf20Sopenharmony_ci 20858c2ecf20Sopenharmony_cistatic void dib8000_update_ana_gain(struct dib8000_state *state, u16 ana_gain) 20868c2ecf20Sopenharmony_ci{ 20878c2ecf20Sopenharmony_ci u16 i; 20888c2ecf20Sopenharmony_ci 20898c2ecf20Sopenharmony_ci dib8000_write_word(state, 116, ana_gain); 20908c2ecf20Sopenharmony_ci 20918c2ecf20Sopenharmony_ci /* update ADC target depending on ana_gain */ 20928c2ecf20Sopenharmony_ci if (ana_gain) { /* set -16dB ADC target for ana_gain=-1 */ 20938c2ecf20Sopenharmony_ci for (i = 0; i < 10; i++) 20948c2ecf20Sopenharmony_ci dib8000_write_word(state, 80 + i, adc_target_16dB[i]); 20958c2ecf20Sopenharmony_ci } else { /* set -22dB ADC target for ana_gain=0 */ 20968c2ecf20Sopenharmony_ci for (i = 0; i < 10; i++) 20978c2ecf20Sopenharmony_ci dib8000_write_word(state, 80 + i, adc_target_16dB[i] - 355); 20988c2ecf20Sopenharmony_ci } 20998c2ecf20Sopenharmony_ci} 21008c2ecf20Sopenharmony_ci 21018c2ecf20Sopenharmony_cistatic void dib8000_load_ana_fe_coefs(struct dib8000_state *state, const s16 *ana_fe) 21028c2ecf20Sopenharmony_ci{ 21038c2ecf20Sopenharmony_ci u16 mode = 0; 21048c2ecf20Sopenharmony_ci 21058c2ecf20Sopenharmony_ci if (state->isdbt_cfg_loaded == 0) 21068c2ecf20Sopenharmony_ci for (mode = 0; mode < 24; mode++) 21078c2ecf20Sopenharmony_ci dib8000_write_word(state, 117 + mode, ana_fe[mode]); 21088c2ecf20Sopenharmony_ci} 21098c2ecf20Sopenharmony_ci 21108c2ecf20Sopenharmony_cistatic const u16 lut_prbs_2k[13] = { 21118c2ecf20Sopenharmony_ci 0x423, 0x009, 0x5C7, 21128c2ecf20Sopenharmony_ci 0x7A6, 0x3D8, 0x527, 21138c2ecf20Sopenharmony_ci 0x7FF, 0x79B, 0x3D6, 21148c2ecf20Sopenharmony_ci 0x3A2, 0x53B, 0x2F4, 21158c2ecf20Sopenharmony_ci 0x213 21168c2ecf20Sopenharmony_ci}; 21178c2ecf20Sopenharmony_ci 21188c2ecf20Sopenharmony_cistatic const u16 lut_prbs_4k[13] = { 21198c2ecf20Sopenharmony_ci 0x208, 0x0C3, 0x7B9, 21208c2ecf20Sopenharmony_ci 0x423, 0x5C7, 0x3D8, 21218c2ecf20Sopenharmony_ci 0x7FF, 0x3D6, 0x53B, 21228c2ecf20Sopenharmony_ci 0x213, 0x029, 0x0D0, 21238c2ecf20Sopenharmony_ci 0x48E 21248c2ecf20Sopenharmony_ci}; 21258c2ecf20Sopenharmony_ci 21268c2ecf20Sopenharmony_cistatic const u16 lut_prbs_8k[13] = { 21278c2ecf20Sopenharmony_ci 0x740, 0x069, 0x7DD, 21288c2ecf20Sopenharmony_ci 0x208, 0x7B9, 0x5C7, 21298c2ecf20Sopenharmony_ci 0x7FF, 0x53B, 0x029, 21308c2ecf20Sopenharmony_ci 0x48E, 0x4C4, 0x367, 21318c2ecf20Sopenharmony_ci 0x684 21328c2ecf20Sopenharmony_ci}; 21338c2ecf20Sopenharmony_ci 21348c2ecf20Sopenharmony_cistatic u16 dib8000_get_init_prbs(struct dib8000_state *state, u16 subchannel) 21358c2ecf20Sopenharmony_ci{ 21368c2ecf20Sopenharmony_ci int sub_channel_prbs_group = 0; 21378c2ecf20Sopenharmony_ci int prbs_group; 21388c2ecf20Sopenharmony_ci 21398c2ecf20Sopenharmony_ci sub_channel_prbs_group = subchannel / 3; 21408c2ecf20Sopenharmony_ci if (sub_channel_prbs_group >= ARRAY_SIZE(lut_prbs_2k)) 21418c2ecf20Sopenharmony_ci return 0; 21428c2ecf20Sopenharmony_ci 21438c2ecf20Sopenharmony_ci switch (state->fe[0]->dtv_property_cache.transmission_mode) { 21448c2ecf20Sopenharmony_ci case TRANSMISSION_MODE_2K: 21458c2ecf20Sopenharmony_ci prbs_group = lut_prbs_2k[sub_channel_prbs_group]; 21468c2ecf20Sopenharmony_ci break; 21478c2ecf20Sopenharmony_ci case TRANSMISSION_MODE_4K: 21488c2ecf20Sopenharmony_ci prbs_group = lut_prbs_4k[sub_channel_prbs_group]; 21498c2ecf20Sopenharmony_ci break; 21508c2ecf20Sopenharmony_ci default: 21518c2ecf20Sopenharmony_ci case TRANSMISSION_MODE_8K: 21528c2ecf20Sopenharmony_ci prbs_group = lut_prbs_8k[sub_channel_prbs_group]; 21538c2ecf20Sopenharmony_ci } 21548c2ecf20Sopenharmony_ci 21558c2ecf20Sopenharmony_ci dprintk("sub_channel_prbs_group = %d , subchannel =%d prbs = 0x%04x\n", 21568c2ecf20Sopenharmony_ci sub_channel_prbs_group, subchannel, prbs_group); 21578c2ecf20Sopenharmony_ci 21588c2ecf20Sopenharmony_ci return prbs_group; 21598c2ecf20Sopenharmony_ci} 21608c2ecf20Sopenharmony_ci 21618c2ecf20Sopenharmony_cistatic void dib8000_set_13seg_channel(struct dib8000_state *state) 21628c2ecf20Sopenharmony_ci{ 21638c2ecf20Sopenharmony_ci u16 i; 21648c2ecf20Sopenharmony_ci u16 coff_pow = 0x2800; 21658c2ecf20Sopenharmony_ci 21668c2ecf20Sopenharmony_ci state->seg_mask = 0x1fff; /* All 13 segments enabled */ 21678c2ecf20Sopenharmony_ci 21688c2ecf20Sopenharmony_ci /* ---- COFF ---- Carloff, the most robust --- */ 21698c2ecf20Sopenharmony_ci if (state->isdbt_cfg_loaded == 0) { /* if not Sound Broadcasting mode : put default values for 13 segments */ 21708c2ecf20Sopenharmony_ci dib8000_write_word(state, 180, (16 << 6) | 9); 21718c2ecf20Sopenharmony_ci dib8000_write_word(state, 187, (4 << 12) | (8 << 5) | 0x2); 21728c2ecf20Sopenharmony_ci coff_pow = 0x2800; 21738c2ecf20Sopenharmony_ci for (i = 0; i < 6; i++) 21748c2ecf20Sopenharmony_ci dib8000_write_word(state, 181+i, coff_pow); 21758c2ecf20Sopenharmony_ci 21768c2ecf20Sopenharmony_ci /* P_ctrl_corm_thres4pre_freq_inh=1, P_ctrl_pre_freq_mode_sat=1 */ 21778c2ecf20Sopenharmony_ci /* P_ctrl_pre_freq_mode_sat=1, P_ctrl_pre_freq_inh=0, P_ctrl_pre_freq_step = 3, P_pre_freq_win_len=1 */ 21788c2ecf20Sopenharmony_ci dib8000_write_word(state, 338, (1 << 12) | (1 << 10) | (0 << 9) | (3 << 5) | 1); 21798c2ecf20Sopenharmony_ci 21808c2ecf20Sopenharmony_ci /* P_ctrl_pre_freq_win_len=8, P_ctrl_pre_freq_thres_lockin=6 */ 21818c2ecf20Sopenharmony_ci dib8000_write_word(state, 340, (8 << 6) | (6 << 0)); 21828c2ecf20Sopenharmony_ci /* P_ctrl_pre_freq_thres_lockout=4, P_small_use_tmcc/ac/cp=1 */ 21838c2ecf20Sopenharmony_ci dib8000_write_word(state, 341, (4 << 3) | (1 << 2) | (1 << 1) | (1 << 0)); 21848c2ecf20Sopenharmony_ci 21858c2ecf20Sopenharmony_ci dib8000_write_word(state, 228, 0); /* default value */ 21868c2ecf20Sopenharmony_ci dib8000_write_word(state, 265, 31); /* default value */ 21878c2ecf20Sopenharmony_ci dib8000_write_word(state, 205, 0x200f); /* init value */ 21888c2ecf20Sopenharmony_ci } 21898c2ecf20Sopenharmony_ci 21908c2ecf20Sopenharmony_ci /* 21918c2ecf20Sopenharmony_ci * make the cpil_coff_lock more robust but slower p_coff_winlen 21928c2ecf20Sopenharmony_ci * 6bits; p_coff_thres_lock 6bits (for coff lock if needed) 21938c2ecf20Sopenharmony_ci */ 21948c2ecf20Sopenharmony_ci 21958c2ecf20Sopenharmony_ci if (state->cfg.pll->ifreq == 0) 21968c2ecf20Sopenharmony_ci dib8000_write_word(state, 266, ~state->seg_mask | state->seg_diff_mask | 0x40); /* P_equal_noise_seg_inh */ 21978c2ecf20Sopenharmony_ci 21988c2ecf20Sopenharmony_ci dib8000_load_ana_fe_coefs(state, ana_fe_coeff_13seg); 21998c2ecf20Sopenharmony_ci} 22008c2ecf20Sopenharmony_ci 22018c2ecf20Sopenharmony_cistatic void dib8000_set_subchannel_prbs(struct dib8000_state *state, u16 init_prbs) 22028c2ecf20Sopenharmony_ci{ 22038c2ecf20Sopenharmony_ci u16 reg_1; 22048c2ecf20Sopenharmony_ci 22058c2ecf20Sopenharmony_ci reg_1 = dib8000_read_word(state, 1); 22068c2ecf20Sopenharmony_ci dib8000_write_word(state, 1, (init_prbs << 2) | (reg_1 & 0x3)); /* ADDR 1 */ 22078c2ecf20Sopenharmony_ci} 22088c2ecf20Sopenharmony_ci 22098c2ecf20Sopenharmony_cistatic void dib8000_small_fine_tune(struct dib8000_state *state) 22108c2ecf20Sopenharmony_ci{ 22118c2ecf20Sopenharmony_ci u16 i; 22128c2ecf20Sopenharmony_ci const s16 *ncoeff; 22138c2ecf20Sopenharmony_ci struct dtv_frontend_properties *c = &state->fe[0]->dtv_property_cache; 22148c2ecf20Sopenharmony_ci 22158c2ecf20Sopenharmony_ci dib8000_write_word(state, 352, state->seg_diff_mask); 22168c2ecf20Sopenharmony_ci dib8000_write_word(state, 353, state->seg_mask); 22178c2ecf20Sopenharmony_ci 22188c2ecf20Sopenharmony_ci /* P_small_coef_ext_enable=ISDB-Tsb, P_small_narrow_band=ISDB-Tsb, P_small_last_seg=13, P_small_offset_num_car=5 */ 22198c2ecf20Sopenharmony_ci dib8000_write_word(state, 351, (c->isdbt_sb_mode << 9) | (c->isdbt_sb_mode << 8) | (13 << 4) | 5); 22208c2ecf20Sopenharmony_ci 22218c2ecf20Sopenharmony_ci if (c->isdbt_sb_mode) { 22228c2ecf20Sopenharmony_ci /* ---- SMALL ---- */ 22238c2ecf20Sopenharmony_ci switch (c->transmission_mode) { 22248c2ecf20Sopenharmony_ci case TRANSMISSION_MODE_2K: 22258c2ecf20Sopenharmony_ci if (c->isdbt_partial_reception == 0) { /* 1-seg */ 22268c2ecf20Sopenharmony_ci if (c->layer[0].modulation == DQPSK) /* DQPSK */ 22278c2ecf20Sopenharmony_ci ncoeff = coeff_2k_sb_1seg_dqpsk; 22288c2ecf20Sopenharmony_ci else /* QPSK or QAM */ 22298c2ecf20Sopenharmony_ci ncoeff = coeff_2k_sb_1seg; 22308c2ecf20Sopenharmony_ci } else { /* 3-segments */ 22318c2ecf20Sopenharmony_ci if (c->layer[0].modulation == DQPSK) { /* DQPSK on central segment */ 22328c2ecf20Sopenharmony_ci if (c->layer[1].modulation == DQPSK) /* DQPSK on external segments */ 22338c2ecf20Sopenharmony_ci ncoeff = coeff_2k_sb_3seg_0dqpsk_1dqpsk; 22348c2ecf20Sopenharmony_ci else /* QPSK or QAM on external segments */ 22358c2ecf20Sopenharmony_ci ncoeff = coeff_2k_sb_3seg_0dqpsk; 22368c2ecf20Sopenharmony_ci } else { /* QPSK or QAM on central segment */ 22378c2ecf20Sopenharmony_ci if (c->layer[1].modulation == DQPSK) /* DQPSK on external segments */ 22388c2ecf20Sopenharmony_ci ncoeff = coeff_2k_sb_3seg_1dqpsk; 22398c2ecf20Sopenharmony_ci else /* QPSK or QAM on external segments */ 22408c2ecf20Sopenharmony_ci ncoeff = coeff_2k_sb_3seg; 22418c2ecf20Sopenharmony_ci } 22428c2ecf20Sopenharmony_ci } 22438c2ecf20Sopenharmony_ci break; 22448c2ecf20Sopenharmony_ci case TRANSMISSION_MODE_4K: 22458c2ecf20Sopenharmony_ci if (c->isdbt_partial_reception == 0) { /* 1-seg */ 22468c2ecf20Sopenharmony_ci if (c->layer[0].modulation == DQPSK) /* DQPSK */ 22478c2ecf20Sopenharmony_ci ncoeff = coeff_4k_sb_1seg_dqpsk; 22488c2ecf20Sopenharmony_ci else /* QPSK or QAM */ 22498c2ecf20Sopenharmony_ci ncoeff = coeff_4k_sb_1seg; 22508c2ecf20Sopenharmony_ci } else { /* 3-segments */ 22518c2ecf20Sopenharmony_ci if (c->layer[0].modulation == DQPSK) { /* DQPSK on central segment */ 22528c2ecf20Sopenharmony_ci if (c->layer[1].modulation == DQPSK) /* DQPSK on external segments */ 22538c2ecf20Sopenharmony_ci ncoeff = coeff_4k_sb_3seg_0dqpsk_1dqpsk; 22548c2ecf20Sopenharmony_ci else /* QPSK or QAM on external segments */ 22558c2ecf20Sopenharmony_ci ncoeff = coeff_4k_sb_3seg_0dqpsk; 22568c2ecf20Sopenharmony_ci } else { /* QPSK or QAM on central segment */ 22578c2ecf20Sopenharmony_ci if (c->layer[1].modulation == DQPSK) /* DQPSK on external segments */ 22588c2ecf20Sopenharmony_ci ncoeff = coeff_4k_sb_3seg_1dqpsk; 22598c2ecf20Sopenharmony_ci else /* QPSK or QAM on external segments */ 22608c2ecf20Sopenharmony_ci ncoeff = coeff_4k_sb_3seg; 22618c2ecf20Sopenharmony_ci } 22628c2ecf20Sopenharmony_ci } 22638c2ecf20Sopenharmony_ci break; 22648c2ecf20Sopenharmony_ci case TRANSMISSION_MODE_AUTO: 22658c2ecf20Sopenharmony_ci case TRANSMISSION_MODE_8K: 22668c2ecf20Sopenharmony_ci default: 22678c2ecf20Sopenharmony_ci if (c->isdbt_partial_reception == 0) { /* 1-seg */ 22688c2ecf20Sopenharmony_ci if (c->layer[0].modulation == DQPSK) /* DQPSK */ 22698c2ecf20Sopenharmony_ci ncoeff = coeff_8k_sb_1seg_dqpsk; 22708c2ecf20Sopenharmony_ci else /* QPSK or QAM */ 22718c2ecf20Sopenharmony_ci ncoeff = coeff_8k_sb_1seg; 22728c2ecf20Sopenharmony_ci } else { /* 3-segments */ 22738c2ecf20Sopenharmony_ci if (c->layer[0].modulation == DQPSK) { /* DQPSK on central segment */ 22748c2ecf20Sopenharmony_ci if (c->layer[1].modulation == DQPSK) /* DQPSK on external segments */ 22758c2ecf20Sopenharmony_ci ncoeff = coeff_8k_sb_3seg_0dqpsk_1dqpsk; 22768c2ecf20Sopenharmony_ci else /* QPSK or QAM on external segments */ 22778c2ecf20Sopenharmony_ci ncoeff = coeff_8k_sb_3seg_0dqpsk; 22788c2ecf20Sopenharmony_ci } else { /* QPSK or QAM on central segment */ 22798c2ecf20Sopenharmony_ci if (c->layer[1].modulation == DQPSK) /* DQPSK on external segments */ 22808c2ecf20Sopenharmony_ci ncoeff = coeff_8k_sb_3seg_1dqpsk; 22818c2ecf20Sopenharmony_ci else /* QPSK or QAM on external segments */ 22828c2ecf20Sopenharmony_ci ncoeff = coeff_8k_sb_3seg; 22838c2ecf20Sopenharmony_ci } 22848c2ecf20Sopenharmony_ci } 22858c2ecf20Sopenharmony_ci break; 22868c2ecf20Sopenharmony_ci } 22878c2ecf20Sopenharmony_ci 22888c2ecf20Sopenharmony_ci for (i = 0; i < 8; i++) 22898c2ecf20Sopenharmony_ci dib8000_write_word(state, 343 + i, ncoeff[i]); 22908c2ecf20Sopenharmony_ci } 22918c2ecf20Sopenharmony_ci} 22928c2ecf20Sopenharmony_ci 22938c2ecf20Sopenharmony_cistatic const u16 coff_thres_1seg[3] = {300, 150, 80}; 22948c2ecf20Sopenharmony_cistatic const u16 coff_thres_3seg[3] = {350, 300, 250}; 22958c2ecf20Sopenharmony_cistatic void dib8000_set_sb_channel(struct dib8000_state *state) 22968c2ecf20Sopenharmony_ci{ 22978c2ecf20Sopenharmony_ci struct dtv_frontend_properties *c = &state->fe[0]->dtv_property_cache; 22988c2ecf20Sopenharmony_ci const u16 *coff; 22998c2ecf20Sopenharmony_ci u16 i; 23008c2ecf20Sopenharmony_ci 23018c2ecf20Sopenharmony_ci if (c->transmission_mode == TRANSMISSION_MODE_2K || c->transmission_mode == TRANSMISSION_MODE_4K) { 23028c2ecf20Sopenharmony_ci dib8000_write_word(state, 219, dib8000_read_word(state, 219) | 0x1); /* adp_pass =1 */ 23038c2ecf20Sopenharmony_ci dib8000_write_word(state, 190, dib8000_read_word(state, 190) | (0x1 << 14)); /* pha3_force_pha_shift = 1 */ 23048c2ecf20Sopenharmony_ci } else { 23058c2ecf20Sopenharmony_ci dib8000_write_word(state, 219, dib8000_read_word(state, 219) & 0xfffe); /* adp_pass =0 */ 23068c2ecf20Sopenharmony_ci dib8000_write_word(state, 190, dib8000_read_word(state, 190) & 0xbfff); /* pha3_force_pha_shift = 0 */ 23078c2ecf20Sopenharmony_ci } 23088c2ecf20Sopenharmony_ci 23098c2ecf20Sopenharmony_ci if (c->isdbt_partial_reception == 1) /* 3-segments */ 23108c2ecf20Sopenharmony_ci state->seg_mask = 0x00E0; 23118c2ecf20Sopenharmony_ci else /* 1-segment */ 23128c2ecf20Sopenharmony_ci state->seg_mask = 0x0040; 23138c2ecf20Sopenharmony_ci 23148c2ecf20Sopenharmony_ci dib8000_write_word(state, 268, (dib8000_read_word(state, 268) & 0xF9FF) | 0x0200); 23158c2ecf20Sopenharmony_ci 23168c2ecf20Sopenharmony_ci /* ---- COFF ---- Carloff, the most robust --- */ 23178c2ecf20Sopenharmony_ci /* P_coff_cpil_alpha=4, P_coff_inh=0, P_coff_cpil_winlen=64, P_coff_narrow_band=1, P_coff_square_val=1, P_coff_one_seg=~partial_rcpt, P_coff_use_tmcc=1, P_coff_use_ac=1 */ 23188c2ecf20Sopenharmony_ci dib8000_write_word(state, 187, (4 << 12) | (0 << 11) | (63 << 5) | (0x3 << 3) | ((~c->isdbt_partial_reception & 1) << 2) | 0x3); 23198c2ecf20Sopenharmony_ci 23208c2ecf20Sopenharmony_ci dib8000_write_word(state, 340, (16 << 6) | (8 << 0)); /* P_ctrl_pre_freq_win_len=16, P_ctrl_pre_freq_thres_lockin=8 */ 23218c2ecf20Sopenharmony_ci dib8000_write_word(state, 341, (6 << 3) | (1 << 2) | (1 << 1) | (1 << 0));/* P_ctrl_pre_freq_thres_lockout=6, P_small_use_tmcc/ac/cp=1 */ 23228c2ecf20Sopenharmony_ci 23238c2ecf20Sopenharmony_ci /* Sound Broadcasting mode 1 seg */ 23248c2ecf20Sopenharmony_ci if (c->isdbt_partial_reception == 0) { 23258c2ecf20Sopenharmony_ci /* P_coff_winlen=63, P_coff_thres_lock=15, P_coff_one_seg_width = (P_mode == 3) , P_coff_one_seg_sym = (P_mode-1) */ 23268c2ecf20Sopenharmony_ci if (state->mode == 3) 23278c2ecf20Sopenharmony_ci dib8000_write_word(state, 180, 0x1fcf | ((state->mode - 1) << 14)); 23288c2ecf20Sopenharmony_ci else 23298c2ecf20Sopenharmony_ci dib8000_write_word(state, 180, 0x0fcf | ((state->mode - 1) << 14)); 23308c2ecf20Sopenharmony_ci 23318c2ecf20Sopenharmony_ci /* P_ctrl_corm_thres4pre_freq_inh=1,P_ctrl_pre_freq_mode_sat=1, P_ctrl_pre_freq_inh=0, P_ctrl_pre_freq_step = 5, P_pre_freq_win_len=4 */ 23328c2ecf20Sopenharmony_ci dib8000_write_word(state, 338, (1 << 12) | (1 << 10) | (0 << 9) | (5 << 5) | 4); 23338c2ecf20Sopenharmony_ci coff = &coff_thres_1seg[0]; 23348c2ecf20Sopenharmony_ci } else { /* Sound Broadcasting mode 3 seg */ 23358c2ecf20Sopenharmony_ci dib8000_write_word(state, 180, 0x1fcf | (1 << 14)); 23368c2ecf20Sopenharmony_ci /* P_ctrl_corm_thres4pre_freq_inh = 1, P_ctrl_pre_freq_mode_sat=1, P_ctrl_pre_freq_inh=0, P_ctrl_pre_freq_step = 4, P_pre_freq_win_len=4 */ 23378c2ecf20Sopenharmony_ci dib8000_write_word(state, 338, (1 << 12) | (1 << 10) | (0 << 9) | (4 << 5) | 4); 23388c2ecf20Sopenharmony_ci coff = &coff_thres_3seg[0]; 23398c2ecf20Sopenharmony_ci } 23408c2ecf20Sopenharmony_ci 23418c2ecf20Sopenharmony_ci dib8000_write_word(state, 228, 1); /* P_2d_mode_byp=1 */ 23428c2ecf20Sopenharmony_ci dib8000_write_word(state, 205, dib8000_read_word(state, 205) & 0xfff0); /* P_cspu_win_cut = 0 */ 23438c2ecf20Sopenharmony_ci 23448c2ecf20Sopenharmony_ci if (c->isdbt_partial_reception == 0 && c->transmission_mode == TRANSMISSION_MODE_2K) 23458c2ecf20Sopenharmony_ci dib8000_write_word(state, 265, 15); /* P_equal_noise_sel = 15 */ 23468c2ecf20Sopenharmony_ci 23478c2ecf20Sopenharmony_ci /* Write COFF thres */ 23488c2ecf20Sopenharmony_ci for (i = 0 ; i < 3; i++) { 23498c2ecf20Sopenharmony_ci dib8000_write_word(state, 181+i, coff[i]); 23508c2ecf20Sopenharmony_ci dib8000_write_word(state, 184+i, coff[i]); 23518c2ecf20Sopenharmony_ci } 23528c2ecf20Sopenharmony_ci 23538c2ecf20Sopenharmony_ci /* 23548c2ecf20Sopenharmony_ci * make the cpil_coff_lock more robust but slower p_coff_winlen 23558c2ecf20Sopenharmony_ci * 6bits; p_coff_thres_lock 6bits (for coff lock if needed) 23568c2ecf20Sopenharmony_ci */ 23578c2ecf20Sopenharmony_ci 23588c2ecf20Sopenharmony_ci dib8000_write_word(state, 266, ~state->seg_mask | state->seg_diff_mask); /* P_equal_noise_seg_inh */ 23598c2ecf20Sopenharmony_ci 23608c2ecf20Sopenharmony_ci if (c->isdbt_partial_reception == 0) 23618c2ecf20Sopenharmony_ci dib8000_write_word(state, 178, 64); /* P_fft_powrange = 64 */ 23628c2ecf20Sopenharmony_ci else 23638c2ecf20Sopenharmony_ci dib8000_write_word(state, 178, 32); /* P_fft_powrange = 32 */ 23648c2ecf20Sopenharmony_ci} 23658c2ecf20Sopenharmony_ci 23668c2ecf20Sopenharmony_cistatic void dib8000_set_isdbt_common_channel(struct dib8000_state *state, u8 seq, u8 autosearching) 23678c2ecf20Sopenharmony_ci{ 23688c2ecf20Sopenharmony_ci u16 p_cfr_left_edge = 0, p_cfr_right_edge = 0; 23698c2ecf20Sopenharmony_ci u16 tmcc_pow = 0, ana_gain = 0, tmp = 0, i = 0, nbseg_diff = 0 ; 23708c2ecf20Sopenharmony_ci u16 max_constellation = DQPSK; 23718c2ecf20Sopenharmony_ci int init_prbs; 23728c2ecf20Sopenharmony_ci struct dtv_frontend_properties *c = &state->fe[0]->dtv_property_cache; 23738c2ecf20Sopenharmony_ci 23748c2ecf20Sopenharmony_ci if (autosearching) 23758c2ecf20Sopenharmony_ci c->isdbt_partial_reception = 1; 23768c2ecf20Sopenharmony_ci 23778c2ecf20Sopenharmony_ci /* P_mode */ 23788c2ecf20Sopenharmony_ci dib8000_write_word(state, 10, (seq << 4)); 23798c2ecf20Sopenharmony_ci 23808c2ecf20Sopenharmony_ci /* init mode */ 23818c2ecf20Sopenharmony_ci state->mode = fft_to_mode(state); 23828c2ecf20Sopenharmony_ci 23838c2ecf20Sopenharmony_ci /* set guard */ 23848c2ecf20Sopenharmony_ci tmp = dib8000_read_word(state, 1); 23858c2ecf20Sopenharmony_ci dib8000_write_word(state, 1, (tmp&0xfffc) | (c->guard_interval & 0x3)); 23868c2ecf20Sopenharmony_ci 23878c2ecf20Sopenharmony_ci dib8000_write_word(state, 274, (dib8000_read_word(state, 274) & 0xffcf) | ((c->isdbt_partial_reception & 1) << 5) | ((c->isdbt_sb_mode & 1) << 4)); 23888c2ecf20Sopenharmony_ci 23898c2ecf20Sopenharmony_ci /* signal optimization parameter */ 23908c2ecf20Sopenharmony_ci if (c->isdbt_partial_reception) { 23918c2ecf20Sopenharmony_ci state->seg_diff_mask = (c->layer[0].modulation == DQPSK) << permu_seg[0]; 23928c2ecf20Sopenharmony_ci for (i = 1; i < 3; i++) 23938c2ecf20Sopenharmony_ci nbseg_diff += (c->layer[i].modulation == DQPSK) * c->layer[i].segment_count; 23948c2ecf20Sopenharmony_ci for (i = 0; i < nbseg_diff; i++) 23958c2ecf20Sopenharmony_ci state->seg_diff_mask |= 1 << permu_seg[i+1]; 23968c2ecf20Sopenharmony_ci } else { 23978c2ecf20Sopenharmony_ci for (i = 0; i < 3; i++) 23988c2ecf20Sopenharmony_ci nbseg_diff += (c->layer[i].modulation == DQPSK) * c->layer[i].segment_count; 23998c2ecf20Sopenharmony_ci for (i = 0; i < nbseg_diff; i++) 24008c2ecf20Sopenharmony_ci state->seg_diff_mask |= 1 << permu_seg[i]; 24018c2ecf20Sopenharmony_ci } 24028c2ecf20Sopenharmony_ci 24038c2ecf20Sopenharmony_ci if (state->seg_diff_mask) 24048c2ecf20Sopenharmony_ci dib8000_write_word(state, 268, (dib8000_read_word(state, 268) & 0xF9FF) | 0x0200); 24058c2ecf20Sopenharmony_ci else 24068c2ecf20Sopenharmony_ci dib8000_write_word(state, 268, (2 << 9) | 39); /*init value */ 24078c2ecf20Sopenharmony_ci 24088c2ecf20Sopenharmony_ci for (i = 0; i < 3; i++) 24098c2ecf20Sopenharmony_ci max_constellation = dib8000_set_layer(state, i, max_constellation); 24108c2ecf20Sopenharmony_ci if (autosearching == 0) { 24118c2ecf20Sopenharmony_ci state->layer_b_nb_seg = c->layer[1].segment_count; 24128c2ecf20Sopenharmony_ci state->layer_c_nb_seg = c->layer[2].segment_count; 24138c2ecf20Sopenharmony_ci } 24148c2ecf20Sopenharmony_ci 24158c2ecf20Sopenharmony_ci /* WRITE: Mode & Diff mask */ 24168c2ecf20Sopenharmony_ci dib8000_write_word(state, 0, (state->mode << 13) | state->seg_diff_mask); 24178c2ecf20Sopenharmony_ci 24188c2ecf20Sopenharmony_ci state->differential_constellation = (state->seg_diff_mask != 0); 24198c2ecf20Sopenharmony_ci 24208c2ecf20Sopenharmony_ci /* channel estimation fine configuration */ 24218c2ecf20Sopenharmony_ci ana_gain = dib8000_adp_fine_tune(state, max_constellation); 24228c2ecf20Sopenharmony_ci 24238c2ecf20Sopenharmony_ci /* update ana_gain depending on max constellation */ 24248c2ecf20Sopenharmony_ci dib8000_update_ana_gain(state, ana_gain); 24258c2ecf20Sopenharmony_ci 24268c2ecf20Sopenharmony_ci /* ---- ANA_FE ---- */ 24278c2ecf20Sopenharmony_ci if (c->isdbt_partial_reception) /* 3-segments */ 24288c2ecf20Sopenharmony_ci dib8000_load_ana_fe_coefs(state, ana_fe_coeff_3seg); 24298c2ecf20Sopenharmony_ci else 24308c2ecf20Sopenharmony_ci dib8000_load_ana_fe_coefs(state, ana_fe_coeff_1seg); /* 1-segment */ 24318c2ecf20Sopenharmony_ci 24328c2ecf20Sopenharmony_ci /* TSB or ISDBT ? apply it now */ 24338c2ecf20Sopenharmony_ci if (c->isdbt_sb_mode) { 24348c2ecf20Sopenharmony_ci dib8000_set_sb_channel(state); 24358c2ecf20Sopenharmony_ci init_prbs = dib8000_get_init_prbs(state, 24368c2ecf20Sopenharmony_ci c->isdbt_sb_subchannel); 24378c2ecf20Sopenharmony_ci } else { 24388c2ecf20Sopenharmony_ci dib8000_set_13seg_channel(state); 24398c2ecf20Sopenharmony_ci init_prbs = 0xfff; 24408c2ecf20Sopenharmony_ci } 24418c2ecf20Sopenharmony_ci 24428c2ecf20Sopenharmony_ci /* SMALL */ 24438c2ecf20Sopenharmony_ci dib8000_small_fine_tune(state); 24448c2ecf20Sopenharmony_ci 24458c2ecf20Sopenharmony_ci dib8000_set_subchannel_prbs(state, init_prbs); 24468c2ecf20Sopenharmony_ci 24478c2ecf20Sopenharmony_ci /* ---- CHAN_BLK ---- */ 24488c2ecf20Sopenharmony_ci for (i = 0; i < 13; i++) { 24498c2ecf20Sopenharmony_ci if ((((~state->seg_diff_mask) >> i) & 1) == 1) { 24508c2ecf20Sopenharmony_ci p_cfr_left_edge += (1 << i) * ((i == 0) || ((((state->seg_mask & (~state->seg_diff_mask)) >> (i - 1)) & 1) == 0)); 24518c2ecf20Sopenharmony_ci p_cfr_right_edge += (1 << i) * ((i == 12) || ((((state->seg_mask & (~state->seg_diff_mask)) >> (i + 1)) & 1) == 0)); 24528c2ecf20Sopenharmony_ci } 24538c2ecf20Sopenharmony_ci } 24548c2ecf20Sopenharmony_ci dib8000_write_word(state, 222, p_cfr_left_edge); /* p_cfr_left_edge */ 24558c2ecf20Sopenharmony_ci dib8000_write_word(state, 223, p_cfr_right_edge); /* p_cfr_right_edge */ 24568c2ecf20Sopenharmony_ci /* "P_cspu_left_edge" & "P_cspu_right_edge" not used => do not care */ 24578c2ecf20Sopenharmony_ci 24588c2ecf20Sopenharmony_ci dib8000_write_word(state, 189, ~state->seg_mask | state->seg_diff_mask); /* P_lmod4_seg_inh */ 24598c2ecf20Sopenharmony_ci dib8000_write_word(state, 192, ~state->seg_mask | state->seg_diff_mask); /* P_pha3_seg_inh */ 24608c2ecf20Sopenharmony_ci dib8000_write_word(state, 225, ~state->seg_mask | state->seg_diff_mask); /* P_tac_seg_inh */ 24618c2ecf20Sopenharmony_ci 24628c2ecf20Sopenharmony_ci if (!autosearching) 24638c2ecf20Sopenharmony_ci dib8000_write_word(state, 288, (~state->seg_mask | state->seg_diff_mask) & 0x1fff); /* P_tmcc_seg_eq_inh */ 24648c2ecf20Sopenharmony_ci else 24658c2ecf20Sopenharmony_ci dib8000_write_word(state, 288, 0x1fff); /*disable equalisation of the tmcc when autosearch to be able to find the DQPSK channels. */ 24668c2ecf20Sopenharmony_ci 24678c2ecf20Sopenharmony_ci dib8000_write_word(state, 211, state->seg_mask & (~state->seg_diff_mask)); /* P_des_seg_enabled */ 24688c2ecf20Sopenharmony_ci dib8000_write_word(state, 287, ~state->seg_mask | 0x1000); /* P_tmcc_seg_inh */ 24698c2ecf20Sopenharmony_ci 24708c2ecf20Sopenharmony_ci dib8000_write_word(state, 178, 32); /* P_fft_powrange = 32 */ 24718c2ecf20Sopenharmony_ci 24728c2ecf20Sopenharmony_ci /* ---- TMCC ---- */ 24738c2ecf20Sopenharmony_ci for (i = 0; i < 3; i++) 24748c2ecf20Sopenharmony_ci tmcc_pow += (((c->layer[i].modulation == DQPSK) * 4 + 1) * c->layer[i].segment_count) ; 24758c2ecf20Sopenharmony_ci 24768c2ecf20Sopenharmony_ci /* Quantif of "P_tmcc_dec_thres_?k" is (0, 5+mode, 9); */ 24778c2ecf20Sopenharmony_ci /* Threshold is set at 1/4 of max power. */ 24788c2ecf20Sopenharmony_ci tmcc_pow *= (1 << (9-2)); 24798c2ecf20Sopenharmony_ci dib8000_write_word(state, 290, tmcc_pow); /* P_tmcc_dec_thres_2k */ 24808c2ecf20Sopenharmony_ci dib8000_write_word(state, 291, tmcc_pow); /* P_tmcc_dec_thres_4k */ 24818c2ecf20Sopenharmony_ci dib8000_write_word(state, 292, tmcc_pow); /* P_tmcc_dec_thres_8k */ 24828c2ecf20Sopenharmony_ci /*dib8000_write_word(state, 287, (1 << 13) | 0x1000 ); */ 24838c2ecf20Sopenharmony_ci 24848c2ecf20Sopenharmony_ci /* ---- PHA3 ---- */ 24858c2ecf20Sopenharmony_ci if (state->isdbt_cfg_loaded == 0) 24868c2ecf20Sopenharmony_ci dib8000_write_word(state, 250, 3285); /* p_2d_hspeed_thr0 */ 24878c2ecf20Sopenharmony_ci 24888c2ecf20Sopenharmony_ci state->isdbt_cfg_loaded = 0; 24898c2ecf20Sopenharmony_ci} 24908c2ecf20Sopenharmony_ci 24918c2ecf20Sopenharmony_cistatic u32 dib8000_wait_lock(struct dib8000_state *state, u32 internal, 24928c2ecf20Sopenharmony_ci u32 wait0_ms, u32 wait1_ms, u32 wait2_ms) 24938c2ecf20Sopenharmony_ci{ 24948c2ecf20Sopenharmony_ci u32 value = 0; /* P_search_end0 wait time */ 24958c2ecf20Sopenharmony_ci u16 reg = 11; /* P_search_end0 start addr */ 24968c2ecf20Sopenharmony_ci 24978c2ecf20Sopenharmony_ci for (reg = 11; reg < 16; reg += 2) { 24988c2ecf20Sopenharmony_ci if (reg == 11) { 24998c2ecf20Sopenharmony_ci if (state->revision == 0x8090) 25008c2ecf20Sopenharmony_ci value = internal * wait1_ms; 25018c2ecf20Sopenharmony_ci else 25028c2ecf20Sopenharmony_ci value = internal * wait0_ms; 25038c2ecf20Sopenharmony_ci } else if (reg == 13) 25048c2ecf20Sopenharmony_ci value = internal * wait1_ms; 25058c2ecf20Sopenharmony_ci else if (reg == 15) 25068c2ecf20Sopenharmony_ci value = internal * wait2_ms; 25078c2ecf20Sopenharmony_ci dib8000_write_word(state, reg, (u16)((value >> 16) & 0xffff)); 25088c2ecf20Sopenharmony_ci dib8000_write_word(state, (reg + 1), (u16)(value & 0xffff)); 25098c2ecf20Sopenharmony_ci } 25108c2ecf20Sopenharmony_ci return value; 25118c2ecf20Sopenharmony_ci} 25128c2ecf20Sopenharmony_ci 25138c2ecf20Sopenharmony_cistatic int dib8000_autosearch_start(struct dvb_frontend *fe) 25148c2ecf20Sopenharmony_ci{ 25158c2ecf20Sopenharmony_ci struct dib8000_state *state = fe->demodulator_priv; 25168c2ecf20Sopenharmony_ci struct dtv_frontend_properties *c = &state->fe[0]->dtv_property_cache; 25178c2ecf20Sopenharmony_ci u8 slist = 0; 25188c2ecf20Sopenharmony_ci u32 value, internal = state->cfg.pll->internal; 25198c2ecf20Sopenharmony_ci 25208c2ecf20Sopenharmony_ci if (state->revision == 0x8090) 25218c2ecf20Sopenharmony_ci internal = dib8000_read32(state, 23) / 1000; 25228c2ecf20Sopenharmony_ci 25238c2ecf20Sopenharmony_ci if ((state->revision >= 0x8002) && 25248c2ecf20Sopenharmony_ci (state->autosearch_state == AS_SEARCHING_FFT)) { 25258c2ecf20Sopenharmony_ci dib8000_write_word(state, 37, 0x0065); /* P_ctrl_pha_off_max default values */ 25268c2ecf20Sopenharmony_ci dib8000_write_word(state, 116, 0x0000); /* P_ana_gain to 0 */ 25278c2ecf20Sopenharmony_ci 25288c2ecf20Sopenharmony_ci dib8000_write_word(state, 0, (dib8000_read_word(state, 0) & 0x1fff) | (0 << 13) | (1 << 15)); /* P_mode = 0, P_restart_search=1 */ 25298c2ecf20Sopenharmony_ci dib8000_write_word(state, 1, (dib8000_read_word(state, 1) & 0xfffc) | 0); /* P_guard = 0 */ 25308c2ecf20Sopenharmony_ci dib8000_write_word(state, 6, 0); /* P_lock0_mask = 0 */ 25318c2ecf20Sopenharmony_ci dib8000_write_word(state, 7, 0); /* P_lock1_mask = 0 */ 25328c2ecf20Sopenharmony_ci dib8000_write_word(state, 8, 0); /* P_lock2_mask = 0 */ 25338c2ecf20Sopenharmony_ci dib8000_write_word(state, 10, (dib8000_read_word(state, 10) & 0x200) | (16 << 4) | (0 << 0)); /* P_search_list=16, P_search_maxtrial=0 */ 25348c2ecf20Sopenharmony_ci 25358c2ecf20Sopenharmony_ci if (state->revision == 0x8090) 25368c2ecf20Sopenharmony_ci value = dib8000_wait_lock(state, internal, 10, 10, 10); /* time in ms configure P_search_end0 P_search_end1 P_search_end2 */ 25378c2ecf20Sopenharmony_ci else 25388c2ecf20Sopenharmony_ci value = dib8000_wait_lock(state, internal, 20, 20, 20); /* time in ms configure P_search_end0 P_search_end1 P_search_end2 */ 25398c2ecf20Sopenharmony_ci 25408c2ecf20Sopenharmony_ci dib8000_write_word(state, 17, 0); 25418c2ecf20Sopenharmony_ci dib8000_write_word(state, 18, 200); /* P_search_rstst = 200 */ 25428c2ecf20Sopenharmony_ci dib8000_write_word(state, 19, 0); 25438c2ecf20Sopenharmony_ci dib8000_write_word(state, 20, 400); /* P_search_rstend = 400 */ 25448c2ecf20Sopenharmony_ci dib8000_write_word(state, 21, (value >> 16) & 0xffff); /* P_search_checkst */ 25458c2ecf20Sopenharmony_ci dib8000_write_word(state, 22, value & 0xffff); 25468c2ecf20Sopenharmony_ci 25478c2ecf20Sopenharmony_ci if (state->revision == 0x8090) 25488c2ecf20Sopenharmony_ci dib8000_write_word(state, 32, (dib8000_read_word(state, 32) & 0xf0ff) | (0 << 8)); /* P_corm_alpha = 0 */ 25498c2ecf20Sopenharmony_ci else 25508c2ecf20Sopenharmony_ci dib8000_write_word(state, 32, (dib8000_read_word(state, 32) & 0xf0ff) | (9 << 8)); /* P_corm_alpha = 3 */ 25518c2ecf20Sopenharmony_ci dib8000_write_word(state, 355, 2); /* P_search_param_max = 2 */ 25528c2ecf20Sopenharmony_ci 25538c2ecf20Sopenharmony_ci /* P_search_param_select = (1 | 1<<4 | 1 << 8) */ 25548c2ecf20Sopenharmony_ci dib8000_write_word(state, 356, 0); 25558c2ecf20Sopenharmony_ci dib8000_write_word(state, 357, 0x111); 25568c2ecf20Sopenharmony_ci 25578c2ecf20Sopenharmony_ci dib8000_write_word(state, 770, (dib8000_read_word(state, 770) & 0xdfff) | (1 << 13)); /* P_restart_ccg = 1 */ 25588c2ecf20Sopenharmony_ci dib8000_write_word(state, 770, (dib8000_read_word(state, 770) & 0xdfff) | (0 << 13)); /* P_restart_ccg = 0 */ 25598c2ecf20Sopenharmony_ci dib8000_write_word(state, 0, (dib8000_read_word(state, 0) & 0x7ff) | (0 << 15) | (1 << 13)); /* P_restart_search = 0; */ 25608c2ecf20Sopenharmony_ci } else if ((state->revision >= 0x8002) && 25618c2ecf20Sopenharmony_ci (state->autosearch_state == AS_SEARCHING_GUARD)) { 25628c2ecf20Sopenharmony_ci c->transmission_mode = TRANSMISSION_MODE_8K; 25638c2ecf20Sopenharmony_ci c->guard_interval = GUARD_INTERVAL_1_8; 25648c2ecf20Sopenharmony_ci c->inversion = 0; 25658c2ecf20Sopenharmony_ci c->layer[0].modulation = QAM_64; 25668c2ecf20Sopenharmony_ci c->layer[0].fec = FEC_2_3; 25678c2ecf20Sopenharmony_ci c->layer[0].interleaving = 0; 25688c2ecf20Sopenharmony_ci c->layer[0].segment_count = 13; 25698c2ecf20Sopenharmony_ci 25708c2ecf20Sopenharmony_ci slist = 16; 25718c2ecf20Sopenharmony_ci c->transmission_mode = state->found_nfft; 25728c2ecf20Sopenharmony_ci 25738c2ecf20Sopenharmony_ci dib8000_set_isdbt_common_channel(state, slist, 1); 25748c2ecf20Sopenharmony_ci 25758c2ecf20Sopenharmony_ci /* set lock_mask values */ 25768c2ecf20Sopenharmony_ci dib8000_write_word(state, 6, 0x4); 25778c2ecf20Sopenharmony_ci if (state->revision == 0x8090) 25788c2ecf20Sopenharmony_ci dib8000_write_word(state, 7, ((1 << 12) | (1 << 11) | (1 << 10)));/* tmcc_dec_lock, tmcc_sync_lock, tmcc_data_lock, tmcc_bch_uncor */ 25798c2ecf20Sopenharmony_ci else 25808c2ecf20Sopenharmony_ci dib8000_write_word(state, 7, 0x8); 25818c2ecf20Sopenharmony_ci dib8000_write_word(state, 8, 0x1000); 25828c2ecf20Sopenharmony_ci 25838c2ecf20Sopenharmony_ci /* set lock_mask wait time values */ 25848c2ecf20Sopenharmony_ci if (state->revision == 0x8090) 25858c2ecf20Sopenharmony_ci dib8000_wait_lock(state, internal, 50, 100, 1000); /* time in ms configure P_search_end0 P_search_end1 P_search_end2 */ 25868c2ecf20Sopenharmony_ci else 25878c2ecf20Sopenharmony_ci dib8000_wait_lock(state, internal, 50, 200, 1000); /* time in ms configure P_search_end0 P_search_end1 P_search_end2 */ 25888c2ecf20Sopenharmony_ci 25898c2ecf20Sopenharmony_ci dib8000_write_word(state, 355, 3); /* P_search_param_max = 3 */ 25908c2ecf20Sopenharmony_ci 25918c2ecf20Sopenharmony_ci /* P_search_param_select = 0xf; look for the 4 different guard intervals */ 25928c2ecf20Sopenharmony_ci dib8000_write_word(state, 356, 0); 25938c2ecf20Sopenharmony_ci dib8000_write_word(state, 357, 0xf); 25948c2ecf20Sopenharmony_ci 25958c2ecf20Sopenharmony_ci value = dib8000_read_word(state, 0); 25968c2ecf20Sopenharmony_ci dib8000_write_word(state, 0, (u16)((1 << 15) | value)); 25978c2ecf20Sopenharmony_ci dib8000_read_word(state, 1284); /* reset the INT. n_irq_pending */ 25988c2ecf20Sopenharmony_ci dib8000_write_word(state, 0, (u16)value); 25998c2ecf20Sopenharmony_ci } else { 26008c2ecf20Sopenharmony_ci c->inversion = 0; 26018c2ecf20Sopenharmony_ci c->layer[0].modulation = QAM_64; 26028c2ecf20Sopenharmony_ci c->layer[0].fec = FEC_2_3; 26038c2ecf20Sopenharmony_ci c->layer[0].interleaving = 0; 26048c2ecf20Sopenharmony_ci c->layer[0].segment_count = 13; 26058c2ecf20Sopenharmony_ci if (!c->isdbt_sb_mode) 26068c2ecf20Sopenharmony_ci c->layer[0].segment_count = 13; 26078c2ecf20Sopenharmony_ci 26088c2ecf20Sopenharmony_ci /* choose the right list, in sb, always do everything */ 26098c2ecf20Sopenharmony_ci if (c->isdbt_sb_mode) { 26108c2ecf20Sopenharmony_ci slist = 7; 26118c2ecf20Sopenharmony_ci dib8000_write_word(state, 0, (dib8000_read_word(state, 0) & 0x9fff) | (1 << 13)); 26128c2ecf20Sopenharmony_ci } else { 26138c2ecf20Sopenharmony_ci if (c->guard_interval == GUARD_INTERVAL_AUTO) { 26148c2ecf20Sopenharmony_ci if (c->transmission_mode == TRANSMISSION_MODE_AUTO) { 26158c2ecf20Sopenharmony_ci c->transmission_mode = TRANSMISSION_MODE_8K; 26168c2ecf20Sopenharmony_ci c->guard_interval = GUARD_INTERVAL_1_8; 26178c2ecf20Sopenharmony_ci slist = 7; 26188c2ecf20Sopenharmony_ci dib8000_write_word(state, 0, (dib8000_read_word(state, 0) & 0x9fff) | (1 << 13)); /* P_mode = 1 to have autosearch start ok with mode2 */ 26198c2ecf20Sopenharmony_ci } else { 26208c2ecf20Sopenharmony_ci c->guard_interval = GUARD_INTERVAL_1_8; 26218c2ecf20Sopenharmony_ci slist = 3; 26228c2ecf20Sopenharmony_ci } 26238c2ecf20Sopenharmony_ci } else { 26248c2ecf20Sopenharmony_ci if (c->transmission_mode == TRANSMISSION_MODE_AUTO) { 26258c2ecf20Sopenharmony_ci c->transmission_mode = TRANSMISSION_MODE_8K; 26268c2ecf20Sopenharmony_ci slist = 2; 26278c2ecf20Sopenharmony_ci dib8000_write_word(state, 0, (dib8000_read_word(state, 0) & 0x9fff) | (1 << 13)); /* P_mode = 1 */ 26288c2ecf20Sopenharmony_ci } else 26298c2ecf20Sopenharmony_ci slist = 0; 26308c2ecf20Sopenharmony_ci } 26318c2ecf20Sopenharmony_ci } 26328c2ecf20Sopenharmony_ci dprintk("Using list for autosearch : %d\n", slist); 26338c2ecf20Sopenharmony_ci 26348c2ecf20Sopenharmony_ci dib8000_set_isdbt_common_channel(state, slist, 1); 26358c2ecf20Sopenharmony_ci 26368c2ecf20Sopenharmony_ci /* set lock_mask values */ 26378c2ecf20Sopenharmony_ci dib8000_write_word(state, 6, 0x4); 26388c2ecf20Sopenharmony_ci if (state->revision == 0x8090) 26398c2ecf20Sopenharmony_ci dib8000_write_word(state, 7, (1 << 12) | (1 << 11) | (1 << 10)); 26408c2ecf20Sopenharmony_ci else 26418c2ecf20Sopenharmony_ci dib8000_write_word(state, 7, 0x8); 26428c2ecf20Sopenharmony_ci dib8000_write_word(state, 8, 0x1000); 26438c2ecf20Sopenharmony_ci 26448c2ecf20Sopenharmony_ci /* set lock_mask wait time values */ 26458c2ecf20Sopenharmony_ci if (state->revision == 0x8090) 26468c2ecf20Sopenharmony_ci dib8000_wait_lock(state, internal, 50, 200, 1000); /* time in ms configure P_search_end0 P_search_end1 P_search_end2 */ 26478c2ecf20Sopenharmony_ci else 26488c2ecf20Sopenharmony_ci dib8000_wait_lock(state, internal, 50, 100, 1000); /* time in ms configure P_search_end0 P_search_end1 P_search_end2 */ 26498c2ecf20Sopenharmony_ci 26508c2ecf20Sopenharmony_ci value = dib8000_read_word(state, 0); 26518c2ecf20Sopenharmony_ci dib8000_write_word(state, 0, (u16)((1 << 15) | value)); 26528c2ecf20Sopenharmony_ci dib8000_read_word(state, 1284); /* reset the INT. n_irq_pending */ 26538c2ecf20Sopenharmony_ci dib8000_write_word(state, 0, (u16)value); 26548c2ecf20Sopenharmony_ci } 26558c2ecf20Sopenharmony_ci return 0; 26568c2ecf20Sopenharmony_ci} 26578c2ecf20Sopenharmony_ci 26588c2ecf20Sopenharmony_cistatic int dib8000_autosearch_irq(struct dvb_frontend *fe) 26598c2ecf20Sopenharmony_ci{ 26608c2ecf20Sopenharmony_ci struct dib8000_state *state = fe->demodulator_priv; 26618c2ecf20Sopenharmony_ci u16 irq_pending = dib8000_read_word(state, 1284); 26628c2ecf20Sopenharmony_ci 26638c2ecf20Sopenharmony_ci if ((state->revision >= 0x8002) && 26648c2ecf20Sopenharmony_ci (state->autosearch_state == AS_SEARCHING_FFT)) { 26658c2ecf20Sopenharmony_ci if (irq_pending & 0x1) { 26668c2ecf20Sopenharmony_ci dprintk("dib8000_autosearch_irq: max correlation result available\n"); 26678c2ecf20Sopenharmony_ci return 3; 26688c2ecf20Sopenharmony_ci } 26698c2ecf20Sopenharmony_ci } else { 26708c2ecf20Sopenharmony_ci if (irq_pending & 0x1) { /* failed */ 26718c2ecf20Sopenharmony_ci dprintk("dib8000_autosearch_irq failed\n"); 26728c2ecf20Sopenharmony_ci return 1; 26738c2ecf20Sopenharmony_ci } 26748c2ecf20Sopenharmony_ci 26758c2ecf20Sopenharmony_ci if (irq_pending & 0x2) { /* succeeded */ 26768c2ecf20Sopenharmony_ci dprintk("dib8000_autosearch_irq succeeded\n"); 26778c2ecf20Sopenharmony_ci return 2; 26788c2ecf20Sopenharmony_ci } 26798c2ecf20Sopenharmony_ci } 26808c2ecf20Sopenharmony_ci 26818c2ecf20Sopenharmony_ci return 0; // still pending 26828c2ecf20Sopenharmony_ci} 26838c2ecf20Sopenharmony_ci 26848c2ecf20Sopenharmony_cistatic void dib8000_viterbi_state(struct dib8000_state *state, u8 onoff) 26858c2ecf20Sopenharmony_ci{ 26868c2ecf20Sopenharmony_ci u16 tmp; 26878c2ecf20Sopenharmony_ci 26888c2ecf20Sopenharmony_ci tmp = dib8000_read_word(state, 771); 26898c2ecf20Sopenharmony_ci if (onoff) /* start P_restart_chd : channel_decoder */ 26908c2ecf20Sopenharmony_ci dib8000_write_word(state, 771, tmp & 0xfffd); 26918c2ecf20Sopenharmony_ci else /* stop P_restart_chd : channel_decoder */ 26928c2ecf20Sopenharmony_ci dib8000_write_word(state, 771, tmp | (1<<1)); 26938c2ecf20Sopenharmony_ci} 26948c2ecf20Sopenharmony_ci 26958c2ecf20Sopenharmony_cistatic void dib8000_set_dds(struct dib8000_state *state, s32 offset_khz) 26968c2ecf20Sopenharmony_ci{ 26978c2ecf20Sopenharmony_ci s16 unit_khz_dds_val; 26988c2ecf20Sopenharmony_ci u32 abs_offset_khz = abs(offset_khz); 26998c2ecf20Sopenharmony_ci u32 dds = state->cfg.pll->ifreq & 0x1ffffff; 27008c2ecf20Sopenharmony_ci u8 invert = !!(state->cfg.pll->ifreq & (1 << 25)); 27018c2ecf20Sopenharmony_ci u8 ratio; 27028c2ecf20Sopenharmony_ci 27038c2ecf20Sopenharmony_ci if (state->revision == 0x8090) { 27048c2ecf20Sopenharmony_ci ratio = 4; 27058c2ecf20Sopenharmony_ci unit_khz_dds_val = (1<<26) / (dib8000_read32(state, 23) / 1000); 27068c2ecf20Sopenharmony_ci if (offset_khz < 0) 27078c2ecf20Sopenharmony_ci dds = (1 << 26) - (abs_offset_khz * unit_khz_dds_val); 27088c2ecf20Sopenharmony_ci else 27098c2ecf20Sopenharmony_ci dds = (abs_offset_khz * unit_khz_dds_val); 27108c2ecf20Sopenharmony_ci 27118c2ecf20Sopenharmony_ci if (invert) 27128c2ecf20Sopenharmony_ci dds = (1<<26) - dds; 27138c2ecf20Sopenharmony_ci } else { 27148c2ecf20Sopenharmony_ci ratio = 2; 27158c2ecf20Sopenharmony_ci unit_khz_dds_val = (u16) (67108864 / state->cfg.pll->internal); 27168c2ecf20Sopenharmony_ci 27178c2ecf20Sopenharmony_ci if (offset_khz < 0) 27188c2ecf20Sopenharmony_ci unit_khz_dds_val *= -1; 27198c2ecf20Sopenharmony_ci 27208c2ecf20Sopenharmony_ci /* IF tuner */ 27218c2ecf20Sopenharmony_ci if (invert) 27228c2ecf20Sopenharmony_ci dds -= abs_offset_khz * unit_khz_dds_val; 27238c2ecf20Sopenharmony_ci else 27248c2ecf20Sopenharmony_ci dds += abs_offset_khz * unit_khz_dds_val; 27258c2ecf20Sopenharmony_ci } 27268c2ecf20Sopenharmony_ci 27278c2ecf20Sopenharmony_ci dprintk("setting a DDS frequency offset of %c%dkHz\n", invert ? '-' : ' ', dds / unit_khz_dds_val); 27288c2ecf20Sopenharmony_ci 27298c2ecf20Sopenharmony_ci if (abs_offset_khz <= (state->cfg.pll->internal / ratio)) { 27308c2ecf20Sopenharmony_ci /* Max dds offset is the half of the demod freq */ 27318c2ecf20Sopenharmony_ci dib8000_write_word(state, 26, invert); 27328c2ecf20Sopenharmony_ci dib8000_write_word(state, 27, (u16)(dds >> 16) & 0x1ff); 27338c2ecf20Sopenharmony_ci dib8000_write_word(state, 28, (u16)(dds & 0xffff)); 27348c2ecf20Sopenharmony_ci } 27358c2ecf20Sopenharmony_ci} 27368c2ecf20Sopenharmony_ci 27378c2ecf20Sopenharmony_cistatic void dib8000_set_frequency_offset(struct dib8000_state *state) 27388c2ecf20Sopenharmony_ci{ 27398c2ecf20Sopenharmony_ci struct dtv_frontend_properties *c = &state->fe[0]->dtv_property_cache; 27408c2ecf20Sopenharmony_ci int i; 27418c2ecf20Sopenharmony_ci u32 current_rf; 27428c2ecf20Sopenharmony_ci int total_dds_offset_khz; 27438c2ecf20Sopenharmony_ci 27448c2ecf20Sopenharmony_ci if (state->fe[0]->ops.tuner_ops.get_frequency) 27458c2ecf20Sopenharmony_ci state->fe[0]->ops.tuner_ops.get_frequency(state->fe[0], ¤t_rf); 27468c2ecf20Sopenharmony_ci else 27478c2ecf20Sopenharmony_ci current_rf = c->frequency; 27488c2ecf20Sopenharmony_ci current_rf /= 1000; 27498c2ecf20Sopenharmony_ci total_dds_offset_khz = (int)current_rf - (int)c->frequency / 1000; 27508c2ecf20Sopenharmony_ci 27518c2ecf20Sopenharmony_ci if (c->isdbt_sb_mode) { 27528c2ecf20Sopenharmony_ci state->subchannel = c->isdbt_sb_subchannel; 27538c2ecf20Sopenharmony_ci 27548c2ecf20Sopenharmony_ci i = dib8000_read_word(state, 26) & 1; /* P_dds_invspec */ 27558c2ecf20Sopenharmony_ci dib8000_write_word(state, 26, c->inversion ^ i); 27568c2ecf20Sopenharmony_ci 27578c2ecf20Sopenharmony_ci if (state->cfg.pll->ifreq == 0) { /* low if tuner */ 27588c2ecf20Sopenharmony_ci if ((c->inversion ^ i) == 0) 27598c2ecf20Sopenharmony_ci dib8000_write_word(state, 26, dib8000_read_word(state, 26) | 1); 27608c2ecf20Sopenharmony_ci } else { 27618c2ecf20Sopenharmony_ci if ((c->inversion ^ i) == 0) 27628c2ecf20Sopenharmony_ci total_dds_offset_khz *= -1; 27638c2ecf20Sopenharmony_ci } 27648c2ecf20Sopenharmony_ci } 27658c2ecf20Sopenharmony_ci 27668c2ecf20Sopenharmony_ci dprintk("%dkhz tuner offset (frequency = %dHz & current_rf = %dHz) total_dds_offset_hz = %d\n", c->frequency - current_rf, c->frequency, current_rf, total_dds_offset_khz); 27678c2ecf20Sopenharmony_ci 27688c2ecf20Sopenharmony_ci /* apply dds offset now */ 27698c2ecf20Sopenharmony_ci dib8000_set_dds(state, total_dds_offset_khz); 27708c2ecf20Sopenharmony_ci} 27718c2ecf20Sopenharmony_ci 27728c2ecf20Sopenharmony_cistatic u16 LUT_isdbt_symbol_duration[4] = { 26, 101, 63 }; 27738c2ecf20Sopenharmony_ci 27748c2ecf20Sopenharmony_cistatic u32 dib8000_get_symbol_duration(struct dib8000_state *state) 27758c2ecf20Sopenharmony_ci{ 27768c2ecf20Sopenharmony_ci struct dtv_frontend_properties *c = &state->fe[0]->dtv_property_cache; 27778c2ecf20Sopenharmony_ci u16 i; 27788c2ecf20Sopenharmony_ci 27798c2ecf20Sopenharmony_ci switch (c->transmission_mode) { 27808c2ecf20Sopenharmony_ci case TRANSMISSION_MODE_2K: 27818c2ecf20Sopenharmony_ci i = 0; 27828c2ecf20Sopenharmony_ci break; 27838c2ecf20Sopenharmony_ci case TRANSMISSION_MODE_4K: 27848c2ecf20Sopenharmony_ci i = 2; 27858c2ecf20Sopenharmony_ci break; 27868c2ecf20Sopenharmony_ci default: 27878c2ecf20Sopenharmony_ci case TRANSMISSION_MODE_AUTO: 27888c2ecf20Sopenharmony_ci case TRANSMISSION_MODE_8K: 27898c2ecf20Sopenharmony_ci i = 1; 27908c2ecf20Sopenharmony_ci break; 27918c2ecf20Sopenharmony_ci } 27928c2ecf20Sopenharmony_ci 27938c2ecf20Sopenharmony_ci return (LUT_isdbt_symbol_duration[i] / (c->bandwidth_hz / 1000)) + 1; 27948c2ecf20Sopenharmony_ci} 27958c2ecf20Sopenharmony_ci 27968c2ecf20Sopenharmony_cistatic void dib8000_set_isdbt_loop_params(struct dib8000_state *state, enum param_loop_step loop_step) 27978c2ecf20Sopenharmony_ci{ 27988c2ecf20Sopenharmony_ci struct dtv_frontend_properties *c = &state->fe[0]->dtv_property_cache; 27998c2ecf20Sopenharmony_ci u16 reg_32 = 0, reg_37 = 0; 28008c2ecf20Sopenharmony_ci 28018c2ecf20Sopenharmony_ci switch (loop_step) { 28028c2ecf20Sopenharmony_ci case LOOP_TUNE_1: 28038c2ecf20Sopenharmony_ci if (c->isdbt_sb_mode) { 28048c2ecf20Sopenharmony_ci if (c->isdbt_partial_reception == 0) { 28058c2ecf20Sopenharmony_ci reg_32 = ((11 - state->mode) << 12) | (6 << 8) | 0x40; /* P_timf_alpha = (11-P_mode), P_corm_alpha=6, P_corm_thres=0x40 */ 28068c2ecf20Sopenharmony_ci reg_37 = (3 << 5) | (0 << 4) | (10 - state->mode); /* P_ctrl_pha_off_max=3 P_ctrl_sfreq_inh =0 P_ctrl_sfreq_step = (10-P_mode) */ 28078c2ecf20Sopenharmony_ci } else { /* Sound Broadcasting mode 3 seg */ 28088c2ecf20Sopenharmony_ci reg_32 = ((10 - state->mode) << 12) | (6 << 8) | 0x60; /* P_timf_alpha = (10-P_mode), P_corm_alpha=6, P_corm_thres=0x60 */ 28098c2ecf20Sopenharmony_ci reg_37 = (3 << 5) | (0 << 4) | (9 - state->mode); /* P_ctrl_pha_off_max=3 P_ctrl_sfreq_inh =0 P_ctrl_sfreq_step = (9-P_mode) */ 28108c2ecf20Sopenharmony_ci } 28118c2ecf20Sopenharmony_ci } else { /* 13-seg start conf offset loop parameters */ 28128c2ecf20Sopenharmony_ci reg_32 = ((9 - state->mode) << 12) | (6 << 8) | 0x80; /* P_timf_alpha = (9-P_mode, P_corm_alpha=6, P_corm_thres=0x80 */ 28138c2ecf20Sopenharmony_ci reg_37 = (3 << 5) | (0 << 4) | (8 - state->mode); /* P_ctrl_pha_off_max=3 P_ctrl_sfreq_inh =0 P_ctrl_sfreq_step = 9 */ 28148c2ecf20Sopenharmony_ci } 28158c2ecf20Sopenharmony_ci break; 28168c2ecf20Sopenharmony_ci case LOOP_TUNE_2: 28178c2ecf20Sopenharmony_ci if (c->isdbt_sb_mode) { 28188c2ecf20Sopenharmony_ci if (c->isdbt_partial_reception == 0) { /* Sound Broadcasting mode 1 seg */ 28198c2ecf20Sopenharmony_ci reg_32 = ((13-state->mode) << 12) | (6 << 8) | 0x40; /* P_timf_alpha = (13-P_mode) , P_corm_alpha=6, P_corm_thres=0x40*/ 28208c2ecf20Sopenharmony_ci reg_37 = (12-state->mode) | ((5 + state->mode) << 5); 28218c2ecf20Sopenharmony_ci } else { /* Sound Broadcasting mode 3 seg */ 28228c2ecf20Sopenharmony_ci reg_32 = ((12-state->mode) << 12) | (6 << 8) | 0x60; /* P_timf_alpha = (12-P_mode) , P_corm_alpha=6, P_corm_thres=0x60 */ 28238c2ecf20Sopenharmony_ci reg_37 = (11-state->mode) | ((5 + state->mode) << 5); 28248c2ecf20Sopenharmony_ci } 28258c2ecf20Sopenharmony_ci } else { /* 13 seg */ 28268c2ecf20Sopenharmony_ci reg_32 = ((11-state->mode) << 12) | (6 << 8) | 0x80; /* P_timf_alpha = 8 , P_corm_alpha=6, P_corm_thres=0x80 */ 28278c2ecf20Sopenharmony_ci reg_37 = ((5+state->mode) << 5) | (10 - state->mode); 28288c2ecf20Sopenharmony_ci } 28298c2ecf20Sopenharmony_ci break; 28308c2ecf20Sopenharmony_ci } 28318c2ecf20Sopenharmony_ci dib8000_write_word(state, 32, reg_32); 28328c2ecf20Sopenharmony_ci dib8000_write_word(state, 37, reg_37); 28338c2ecf20Sopenharmony_ci} 28348c2ecf20Sopenharmony_ci 28358c2ecf20Sopenharmony_cistatic void dib8000_demod_restart(struct dib8000_state *state) 28368c2ecf20Sopenharmony_ci{ 28378c2ecf20Sopenharmony_ci dib8000_write_word(state, 770, 0x4000); 28388c2ecf20Sopenharmony_ci dib8000_write_word(state, 770, 0x0000); 28398c2ecf20Sopenharmony_ci return; 28408c2ecf20Sopenharmony_ci} 28418c2ecf20Sopenharmony_ci 28428c2ecf20Sopenharmony_cistatic void dib8000_set_sync_wait(struct dib8000_state *state) 28438c2ecf20Sopenharmony_ci{ 28448c2ecf20Sopenharmony_ci struct dtv_frontend_properties *c = &state->fe[0]->dtv_property_cache; 28458c2ecf20Sopenharmony_ci u16 sync_wait = 64; 28468c2ecf20Sopenharmony_ci 28478c2ecf20Sopenharmony_ci /* P_dvsy_sync_wait - reuse mode */ 28488c2ecf20Sopenharmony_ci switch (c->transmission_mode) { 28498c2ecf20Sopenharmony_ci case TRANSMISSION_MODE_8K: 28508c2ecf20Sopenharmony_ci sync_wait = 256; 28518c2ecf20Sopenharmony_ci break; 28528c2ecf20Sopenharmony_ci case TRANSMISSION_MODE_4K: 28538c2ecf20Sopenharmony_ci sync_wait = 128; 28548c2ecf20Sopenharmony_ci break; 28558c2ecf20Sopenharmony_ci default: 28568c2ecf20Sopenharmony_ci case TRANSMISSION_MODE_2K: 28578c2ecf20Sopenharmony_ci sync_wait = 64; 28588c2ecf20Sopenharmony_ci break; 28598c2ecf20Sopenharmony_ci } 28608c2ecf20Sopenharmony_ci 28618c2ecf20Sopenharmony_ci if (state->cfg.diversity_delay == 0) 28628c2ecf20Sopenharmony_ci sync_wait = (sync_wait * (1 << (c->guard_interval)) * 3) / 2 + 48; /* add 50% SFN margin + compensate for one DVSY-fifo */ 28638c2ecf20Sopenharmony_ci else 28648c2ecf20Sopenharmony_ci sync_wait = (sync_wait * (1 << (c->guard_interval)) * 3) / 2 + state->cfg.diversity_delay; /* add 50% SFN margin + compensate for DVSY-fifo */ 28658c2ecf20Sopenharmony_ci 28668c2ecf20Sopenharmony_ci dib8000_write_word(state, 273, (dib8000_read_word(state, 273) & 0x000f) | (sync_wait << 4)); 28678c2ecf20Sopenharmony_ci} 28688c2ecf20Sopenharmony_ci 28698c2ecf20Sopenharmony_cistatic unsigned long dib8000_get_timeout(struct dib8000_state *state, u32 delay, enum timeout_mode mode) 28708c2ecf20Sopenharmony_ci{ 28718c2ecf20Sopenharmony_ci if (mode == SYMBOL_DEPENDENT_ON) 28728c2ecf20Sopenharmony_ci delay *= state->symbol_duration; 28738c2ecf20Sopenharmony_ci 28748c2ecf20Sopenharmony_ci return jiffies + usecs_to_jiffies(delay * 100); 28758c2ecf20Sopenharmony_ci} 28768c2ecf20Sopenharmony_ci 28778c2ecf20Sopenharmony_cistatic s32 dib8000_get_status(struct dvb_frontend *fe) 28788c2ecf20Sopenharmony_ci{ 28798c2ecf20Sopenharmony_ci struct dib8000_state *state = fe->demodulator_priv; 28808c2ecf20Sopenharmony_ci return state->status; 28818c2ecf20Sopenharmony_ci} 28828c2ecf20Sopenharmony_ci 28838c2ecf20Sopenharmony_cistatic enum frontend_tune_state dib8000_get_tune_state(struct dvb_frontend *fe) 28848c2ecf20Sopenharmony_ci{ 28858c2ecf20Sopenharmony_ci struct dib8000_state *state = fe->demodulator_priv; 28868c2ecf20Sopenharmony_ci return state->tune_state; 28878c2ecf20Sopenharmony_ci} 28888c2ecf20Sopenharmony_ci 28898c2ecf20Sopenharmony_cistatic int dib8000_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state) 28908c2ecf20Sopenharmony_ci{ 28918c2ecf20Sopenharmony_ci struct dib8000_state *state = fe->demodulator_priv; 28928c2ecf20Sopenharmony_ci 28938c2ecf20Sopenharmony_ci state->tune_state = tune_state; 28948c2ecf20Sopenharmony_ci return 0; 28958c2ecf20Sopenharmony_ci} 28968c2ecf20Sopenharmony_ci 28978c2ecf20Sopenharmony_cistatic int dib8000_tune_restart_from_demod(struct dvb_frontend *fe) 28988c2ecf20Sopenharmony_ci{ 28998c2ecf20Sopenharmony_ci struct dib8000_state *state = fe->demodulator_priv; 29008c2ecf20Sopenharmony_ci 29018c2ecf20Sopenharmony_ci state->status = FE_STATUS_TUNE_PENDING; 29028c2ecf20Sopenharmony_ci state->tune_state = CT_DEMOD_START; 29038c2ecf20Sopenharmony_ci return 0; 29048c2ecf20Sopenharmony_ci} 29058c2ecf20Sopenharmony_ci 29068c2ecf20Sopenharmony_cistatic u16 dib8000_read_lock(struct dvb_frontend *fe) 29078c2ecf20Sopenharmony_ci{ 29088c2ecf20Sopenharmony_ci struct dib8000_state *state = fe->demodulator_priv; 29098c2ecf20Sopenharmony_ci 29108c2ecf20Sopenharmony_ci if (state->revision == 0x8090) 29118c2ecf20Sopenharmony_ci return dib8000_read_word(state, 570); 29128c2ecf20Sopenharmony_ci return dib8000_read_word(state, 568); 29138c2ecf20Sopenharmony_ci} 29148c2ecf20Sopenharmony_ci 29158c2ecf20Sopenharmony_cistatic int dib8090p_init_sdram(struct dib8000_state *state) 29168c2ecf20Sopenharmony_ci{ 29178c2ecf20Sopenharmony_ci u16 reg = 0; 29188c2ecf20Sopenharmony_ci dprintk("init sdram\n"); 29198c2ecf20Sopenharmony_ci 29208c2ecf20Sopenharmony_ci reg = dib8000_read_word(state, 274) & 0xfff0; 29218c2ecf20Sopenharmony_ci dib8000_write_word(state, 274, reg | 0x7); /* P_dintlv_delay_ram = 7 because of MobileSdram */ 29228c2ecf20Sopenharmony_ci 29238c2ecf20Sopenharmony_ci dib8000_write_word(state, 1803, (7 << 2)); 29248c2ecf20Sopenharmony_ci 29258c2ecf20Sopenharmony_ci reg = dib8000_read_word(state, 1280); 29268c2ecf20Sopenharmony_ci dib8000_write_word(state, 1280, reg | (1 << 2)); /* force restart P_restart_sdram */ 29278c2ecf20Sopenharmony_ci dib8000_write_word(state, 1280, reg); /* release restart P_restart_sdram */ 29288c2ecf20Sopenharmony_ci 29298c2ecf20Sopenharmony_ci return 0; 29308c2ecf20Sopenharmony_ci} 29318c2ecf20Sopenharmony_ci 29328c2ecf20Sopenharmony_ci/** 29338c2ecf20Sopenharmony_ci * is_manual_mode - Check if TMCC should be used for parameters settings 29348c2ecf20Sopenharmony_ci * @c: struct dvb_frontend_properties 29358c2ecf20Sopenharmony_ci * 29368c2ecf20Sopenharmony_ci * By default, TMCC table should be used for parameter settings on most 29378c2ecf20Sopenharmony_ci * usercases. However, sometimes it is desirable to lock the demod to 29388c2ecf20Sopenharmony_ci * use the manual parameters. 29398c2ecf20Sopenharmony_ci * 29408c2ecf20Sopenharmony_ci * On manual mode, the current dib8000_tune state machine is very restrict: 29418c2ecf20Sopenharmony_ci * It requires that both per-layer and per-transponder parameters to be 29428c2ecf20Sopenharmony_ci * properly specified, otherwise the device won't lock. 29438c2ecf20Sopenharmony_ci * 29448c2ecf20Sopenharmony_ci * Check if all those conditions are properly satisfied before allowing 29458c2ecf20Sopenharmony_ci * the device to use the manual frequency lock mode. 29468c2ecf20Sopenharmony_ci */ 29478c2ecf20Sopenharmony_cistatic int is_manual_mode(struct dtv_frontend_properties *c) 29488c2ecf20Sopenharmony_ci{ 29498c2ecf20Sopenharmony_ci int i, n_segs = 0; 29508c2ecf20Sopenharmony_ci 29518c2ecf20Sopenharmony_ci /* Use auto mode on DVB-T compat mode */ 29528c2ecf20Sopenharmony_ci if (c->delivery_system != SYS_ISDBT) 29538c2ecf20Sopenharmony_ci return 0; 29548c2ecf20Sopenharmony_ci 29558c2ecf20Sopenharmony_ci /* 29568c2ecf20Sopenharmony_ci * Transmission mode is only detected on auto mode, currently 29578c2ecf20Sopenharmony_ci */ 29588c2ecf20Sopenharmony_ci if (c->transmission_mode == TRANSMISSION_MODE_AUTO) { 29598c2ecf20Sopenharmony_ci dprintk("transmission mode auto\n"); 29608c2ecf20Sopenharmony_ci return 0; 29618c2ecf20Sopenharmony_ci } 29628c2ecf20Sopenharmony_ci 29638c2ecf20Sopenharmony_ci /* 29648c2ecf20Sopenharmony_ci * Guard interval is only detected on auto mode, currently 29658c2ecf20Sopenharmony_ci */ 29668c2ecf20Sopenharmony_ci if (c->guard_interval == GUARD_INTERVAL_AUTO) { 29678c2ecf20Sopenharmony_ci dprintk("guard interval auto\n"); 29688c2ecf20Sopenharmony_ci return 0; 29698c2ecf20Sopenharmony_ci } 29708c2ecf20Sopenharmony_ci 29718c2ecf20Sopenharmony_ci /* 29728c2ecf20Sopenharmony_ci * If no layer is enabled, assume auto mode, as at least one 29738c2ecf20Sopenharmony_ci * layer should be enabled 29748c2ecf20Sopenharmony_ci */ 29758c2ecf20Sopenharmony_ci if (!c->isdbt_layer_enabled) { 29768c2ecf20Sopenharmony_ci dprintk("no layer modulation specified\n"); 29778c2ecf20Sopenharmony_ci return 0; 29788c2ecf20Sopenharmony_ci } 29798c2ecf20Sopenharmony_ci 29808c2ecf20Sopenharmony_ci /* 29818c2ecf20Sopenharmony_ci * Check if the per-layer parameters aren't auto and 29828c2ecf20Sopenharmony_ci * disable a layer if segment count is 0 or invalid. 29838c2ecf20Sopenharmony_ci */ 29848c2ecf20Sopenharmony_ci for (i = 0; i < 3; i++) { 29858c2ecf20Sopenharmony_ci if (!(c->isdbt_layer_enabled & 1 << i)) 29868c2ecf20Sopenharmony_ci continue; 29878c2ecf20Sopenharmony_ci 29888c2ecf20Sopenharmony_ci if ((c->layer[i].segment_count > 13) || 29898c2ecf20Sopenharmony_ci (c->layer[i].segment_count == 0)) { 29908c2ecf20Sopenharmony_ci c->isdbt_layer_enabled &= ~(1 << i); 29918c2ecf20Sopenharmony_ci continue; 29928c2ecf20Sopenharmony_ci } 29938c2ecf20Sopenharmony_ci 29948c2ecf20Sopenharmony_ci n_segs += c->layer[i].segment_count; 29958c2ecf20Sopenharmony_ci 29968c2ecf20Sopenharmony_ci if ((c->layer[i].modulation == QAM_AUTO) || 29978c2ecf20Sopenharmony_ci (c->layer[i].fec == FEC_AUTO)) { 29988c2ecf20Sopenharmony_ci dprintk("layer %c has either modulation or FEC auto\n", 29998c2ecf20Sopenharmony_ci 'A' + i); 30008c2ecf20Sopenharmony_ci return 0; 30018c2ecf20Sopenharmony_ci } 30028c2ecf20Sopenharmony_ci } 30038c2ecf20Sopenharmony_ci 30048c2ecf20Sopenharmony_ci /* 30058c2ecf20Sopenharmony_ci * Userspace specified a wrong number of segments. 30068c2ecf20Sopenharmony_ci * fallback to auto mode. 30078c2ecf20Sopenharmony_ci */ 30088c2ecf20Sopenharmony_ci if (n_segs == 0 || n_segs > 13) { 30098c2ecf20Sopenharmony_ci dprintk("number of segments is invalid\n"); 30108c2ecf20Sopenharmony_ci return 0; 30118c2ecf20Sopenharmony_ci } 30128c2ecf20Sopenharmony_ci 30138c2ecf20Sopenharmony_ci /* Everything looks ok for manual mode */ 30148c2ecf20Sopenharmony_ci return 1; 30158c2ecf20Sopenharmony_ci} 30168c2ecf20Sopenharmony_ci 30178c2ecf20Sopenharmony_cistatic int dib8000_tune(struct dvb_frontend *fe) 30188c2ecf20Sopenharmony_ci{ 30198c2ecf20Sopenharmony_ci struct dib8000_state *state = fe->demodulator_priv; 30208c2ecf20Sopenharmony_ci struct dtv_frontend_properties *c = &state->fe[0]->dtv_property_cache; 30218c2ecf20Sopenharmony_ci enum frontend_tune_state *tune_state = &state->tune_state; 30228c2ecf20Sopenharmony_ci 30238c2ecf20Sopenharmony_ci u16 locks, deeper_interleaver = 0, i; 30248c2ecf20Sopenharmony_ci int ret = 1; /* 1 symbol duration (in 100us unit) delay most of the time */ 30258c2ecf20Sopenharmony_ci 30268c2ecf20Sopenharmony_ci unsigned long *timeout = &state->timeout; 30278c2ecf20Sopenharmony_ci unsigned long now = jiffies; 30288c2ecf20Sopenharmony_ci u16 init_prbs; 30298c2ecf20Sopenharmony_ci#ifdef DIB8000_AGC_FREEZE 30308c2ecf20Sopenharmony_ci u16 agc1, agc2; 30318c2ecf20Sopenharmony_ci#endif 30328c2ecf20Sopenharmony_ci 30338c2ecf20Sopenharmony_ci u32 corm[4] = {0, 0, 0, 0}; 30348c2ecf20Sopenharmony_ci u8 find_index, max_value; 30358c2ecf20Sopenharmony_ci 30368c2ecf20Sopenharmony_ci#if 0 30378c2ecf20Sopenharmony_ci if (*tune_state < CT_DEMOD_STOP) 30388c2ecf20Sopenharmony_ci dprintk("IN: context status = %d, TUNE_STATE %d autosearch step = %u jiffies = %lu\n", 30398c2ecf20Sopenharmony_ci state->channel_parameters_set, *tune_state, state->autosearch_state, now); 30408c2ecf20Sopenharmony_ci#endif 30418c2ecf20Sopenharmony_ci 30428c2ecf20Sopenharmony_ci switch (*tune_state) { 30438c2ecf20Sopenharmony_ci case CT_DEMOD_START: /* 30 */ 30448c2ecf20Sopenharmony_ci dib8000_reset_stats(fe); 30458c2ecf20Sopenharmony_ci 30468c2ecf20Sopenharmony_ci if (state->revision == 0x8090) 30478c2ecf20Sopenharmony_ci dib8090p_init_sdram(state); 30488c2ecf20Sopenharmony_ci state->status = FE_STATUS_TUNE_PENDING; 30498c2ecf20Sopenharmony_ci state->channel_parameters_set = is_manual_mode(c); 30508c2ecf20Sopenharmony_ci 30518c2ecf20Sopenharmony_ci dprintk("Tuning channel on %s search mode\n", 30528c2ecf20Sopenharmony_ci state->channel_parameters_set ? "manual" : "auto"); 30538c2ecf20Sopenharmony_ci 30548c2ecf20Sopenharmony_ci dib8000_viterbi_state(state, 0); /* force chan dec in restart */ 30558c2ecf20Sopenharmony_ci 30568c2ecf20Sopenharmony_ci /* Layer monitor */ 30578c2ecf20Sopenharmony_ci dib8000_write_word(state, 285, dib8000_read_word(state, 285) & 0x60); 30588c2ecf20Sopenharmony_ci 30598c2ecf20Sopenharmony_ci dib8000_set_frequency_offset(state); 30608c2ecf20Sopenharmony_ci dib8000_set_bandwidth(fe, c->bandwidth_hz / 1000); 30618c2ecf20Sopenharmony_ci 30628c2ecf20Sopenharmony_ci if (state->channel_parameters_set == 0) { /* The channel struct is unknown, search it ! */ 30638c2ecf20Sopenharmony_ci#ifdef DIB8000_AGC_FREEZE 30648c2ecf20Sopenharmony_ci if (state->revision != 0x8090) { 30658c2ecf20Sopenharmony_ci state->agc1_max = dib8000_read_word(state, 108); 30668c2ecf20Sopenharmony_ci state->agc1_min = dib8000_read_word(state, 109); 30678c2ecf20Sopenharmony_ci state->agc2_max = dib8000_read_word(state, 110); 30688c2ecf20Sopenharmony_ci state->agc2_min = dib8000_read_word(state, 111); 30698c2ecf20Sopenharmony_ci agc1 = dib8000_read_word(state, 388); 30708c2ecf20Sopenharmony_ci agc2 = dib8000_read_word(state, 389); 30718c2ecf20Sopenharmony_ci dib8000_write_word(state, 108, agc1); 30728c2ecf20Sopenharmony_ci dib8000_write_word(state, 109, agc1); 30738c2ecf20Sopenharmony_ci dib8000_write_word(state, 110, agc2); 30748c2ecf20Sopenharmony_ci dib8000_write_word(state, 111, agc2); 30758c2ecf20Sopenharmony_ci } 30768c2ecf20Sopenharmony_ci#endif 30778c2ecf20Sopenharmony_ci state->autosearch_state = AS_SEARCHING_FFT; 30788c2ecf20Sopenharmony_ci state->found_nfft = TRANSMISSION_MODE_AUTO; 30798c2ecf20Sopenharmony_ci state->found_guard = GUARD_INTERVAL_AUTO; 30808c2ecf20Sopenharmony_ci *tune_state = CT_DEMOD_SEARCH_NEXT; 30818c2ecf20Sopenharmony_ci } else { /* we already know the channel struct so TUNE only ! */ 30828c2ecf20Sopenharmony_ci state->autosearch_state = AS_DONE; 30838c2ecf20Sopenharmony_ci *tune_state = CT_DEMOD_STEP_3; 30848c2ecf20Sopenharmony_ci } 30858c2ecf20Sopenharmony_ci state->symbol_duration = dib8000_get_symbol_duration(state); 30868c2ecf20Sopenharmony_ci break; 30878c2ecf20Sopenharmony_ci 30888c2ecf20Sopenharmony_ci case CT_DEMOD_SEARCH_NEXT: /* 51 */ 30898c2ecf20Sopenharmony_ci dib8000_autosearch_start(fe); 30908c2ecf20Sopenharmony_ci if (state->revision == 0x8090) 30918c2ecf20Sopenharmony_ci ret = 50; 30928c2ecf20Sopenharmony_ci else 30938c2ecf20Sopenharmony_ci ret = 15; 30948c2ecf20Sopenharmony_ci *tune_state = CT_DEMOD_STEP_1; 30958c2ecf20Sopenharmony_ci break; 30968c2ecf20Sopenharmony_ci 30978c2ecf20Sopenharmony_ci case CT_DEMOD_STEP_1: /* 31 */ 30988c2ecf20Sopenharmony_ci switch (dib8000_autosearch_irq(fe)) { 30998c2ecf20Sopenharmony_ci case 1: /* fail */ 31008c2ecf20Sopenharmony_ci state->status = FE_STATUS_TUNE_FAILED; 31018c2ecf20Sopenharmony_ci state->autosearch_state = AS_DONE; 31028c2ecf20Sopenharmony_ci *tune_state = CT_DEMOD_STOP; /* else we are done here */ 31038c2ecf20Sopenharmony_ci break; 31048c2ecf20Sopenharmony_ci case 2: /* Success */ 31058c2ecf20Sopenharmony_ci state->status = FE_STATUS_FFT_SUCCESS; /* signal to the upper layer, that there was a channel found and the parameters can be read */ 31068c2ecf20Sopenharmony_ci *tune_state = CT_DEMOD_STEP_3; 31078c2ecf20Sopenharmony_ci if (state->autosearch_state == AS_SEARCHING_GUARD) 31088c2ecf20Sopenharmony_ci *tune_state = CT_DEMOD_STEP_2; 31098c2ecf20Sopenharmony_ci else 31108c2ecf20Sopenharmony_ci state->autosearch_state = AS_DONE; 31118c2ecf20Sopenharmony_ci break; 31128c2ecf20Sopenharmony_ci case 3: /* Autosearch FFT max correlation endded */ 31138c2ecf20Sopenharmony_ci *tune_state = CT_DEMOD_STEP_2; 31148c2ecf20Sopenharmony_ci break; 31158c2ecf20Sopenharmony_ci } 31168c2ecf20Sopenharmony_ci break; 31178c2ecf20Sopenharmony_ci 31188c2ecf20Sopenharmony_ci case CT_DEMOD_STEP_2: 31198c2ecf20Sopenharmony_ci switch (state->autosearch_state) { 31208c2ecf20Sopenharmony_ci case AS_SEARCHING_FFT: 31218c2ecf20Sopenharmony_ci /* searching for the correct FFT */ 31228c2ecf20Sopenharmony_ci if (state->revision == 0x8090) { 31238c2ecf20Sopenharmony_ci corm[2] = (dib8000_read_word(state, 596) << 16) | (dib8000_read_word(state, 597)); 31248c2ecf20Sopenharmony_ci corm[1] = (dib8000_read_word(state, 598) << 16) | (dib8000_read_word(state, 599)); 31258c2ecf20Sopenharmony_ci corm[0] = (dib8000_read_word(state, 600) << 16) | (dib8000_read_word(state, 601)); 31268c2ecf20Sopenharmony_ci } else { 31278c2ecf20Sopenharmony_ci corm[2] = (dib8000_read_word(state, 594) << 16) | (dib8000_read_word(state, 595)); 31288c2ecf20Sopenharmony_ci corm[1] = (dib8000_read_word(state, 596) << 16) | (dib8000_read_word(state, 597)); 31298c2ecf20Sopenharmony_ci corm[0] = (dib8000_read_word(state, 598) << 16) | (dib8000_read_word(state, 599)); 31308c2ecf20Sopenharmony_ci } 31318c2ecf20Sopenharmony_ci /* dprintk("corm fft: %u %u %u\n", corm[0], corm[1], corm[2]); */ 31328c2ecf20Sopenharmony_ci 31338c2ecf20Sopenharmony_ci max_value = 0; 31348c2ecf20Sopenharmony_ci for (find_index = 1 ; find_index < 3 ; find_index++) { 31358c2ecf20Sopenharmony_ci if (corm[max_value] < corm[find_index]) 31368c2ecf20Sopenharmony_ci max_value = find_index ; 31378c2ecf20Sopenharmony_ci } 31388c2ecf20Sopenharmony_ci 31398c2ecf20Sopenharmony_ci switch (max_value) { 31408c2ecf20Sopenharmony_ci case 0: 31418c2ecf20Sopenharmony_ci state->found_nfft = TRANSMISSION_MODE_2K; 31428c2ecf20Sopenharmony_ci break; 31438c2ecf20Sopenharmony_ci case 1: 31448c2ecf20Sopenharmony_ci state->found_nfft = TRANSMISSION_MODE_4K; 31458c2ecf20Sopenharmony_ci break; 31468c2ecf20Sopenharmony_ci case 2: 31478c2ecf20Sopenharmony_ci default: 31488c2ecf20Sopenharmony_ci state->found_nfft = TRANSMISSION_MODE_8K; 31498c2ecf20Sopenharmony_ci break; 31508c2ecf20Sopenharmony_ci } 31518c2ecf20Sopenharmony_ci /* dprintk("Autosearch FFT has found Mode %d\n", max_value + 1); */ 31528c2ecf20Sopenharmony_ci 31538c2ecf20Sopenharmony_ci *tune_state = CT_DEMOD_SEARCH_NEXT; 31548c2ecf20Sopenharmony_ci state->autosearch_state = AS_SEARCHING_GUARD; 31558c2ecf20Sopenharmony_ci if (state->revision == 0x8090) 31568c2ecf20Sopenharmony_ci ret = 50; 31578c2ecf20Sopenharmony_ci else 31588c2ecf20Sopenharmony_ci ret = 10; 31598c2ecf20Sopenharmony_ci break; 31608c2ecf20Sopenharmony_ci case AS_SEARCHING_GUARD: 31618c2ecf20Sopenharmony_ci /* searching for the correct guard interval */ 31628c2ecf20Sopenharmony_ci if (state->revision == 0x8090) 31638c2ecf20Sopenharmony_ci state->found_guard = dib8000_read_word(state, 572) & 0x3; 31648c2ecf20Sopenharmony_ci else 31658c2ecf20Sopenharmony_ci state->found_guard = dib8000_read_word(state, 570) & 0x3; 31668c2ecf20Sopenharmony_ci /* dprintk("guard interval found=%i\n", state->found_guard); */ 31678c2ecf20Sopenharmony_ci 31688c2ecf20Sopenharmony_ci *tune_state = CT_DEMOD_STEP_3; 31698c2ecf20Sopenharmony_ci break; 31708c2ecf20Sopenharmony_ci default: 31718c2ecf20Sopenharmony_ci /* the demod should never be in this state */ 31728c2ecf20Sopenharmony_ci state->status = FE_STATUS_TUNE_FAILED; 31738c2ecf20Sopenharmony_ci state->autosearch_state = AS_DONE; 31748c2ecf20Sopenharmony_ci *tune_state = CT_DEMOD_STOP; /* else we are done here */ 31758c2ecf20Sopenharmony_ci break; 31768c2ecf20Sopenharmony_ci } 31778c2ecf20Sopenharmony_ci break; 31788c2ecf20Sopenharmony_ci 31798c2ecf20Sopenharmony_ci case CT_DEMOD_STEP_3: /* 33 */ 31808c2ecf20Sopenharmony_ci dib8000_set_isdbt_loop_params(state, LOOP_TUNE_1); 31818c2ecf20Sopenharmony_ci dib8000_set_isdbt_common_channel(state, 0, 0);/* setting the known channel parameters here */ 31828c2ecf20Sopenharmony_ci *tune_state = CT_DEMOD_STEP_4; 31838c2ecf20Sopenharmony_ci break; 31848c2ecf20Sopenharmony_ci 31858c2ecf20Sopenharmony_ci case CT_DEMOD_STEP_4: /* (34) */ 31868c2ecf20Sopenharmony_ci dib8000_demod_restart(state); 31878c2ecf20Sopenharmony_ci 31888c2ecf20Sopenharmony_ci dib8000_set_sync_wait(state); 31898c2ecf20Sopenharmony_ci dib8000_set_diversity_in(state->fe[0], state->diversity_onoff); 31908c2ecf20Sopenharmony_ci 31918c2ecf20Sopenharmony_ci locks = (dib8000_read_word(state, 180) >> 6) & 0x3f; /* P_coff_winlen ? */ 31928c2ecf20Sopenharmony_ci /* coff should lock over P_coff_winlen ofdm symbols : give 3 times this length to lock */ 31938c2ecf20Sopenharmony_ci *timeout = dib8000_get_timeout(state, 2 * locks, SYMBOL_DEPENDENT_ON); 31948c2ecf20Sopenharmony_ci *tune_state = CT_DEMOD_STEP_5; 31958c2ecf20Sopenharmony_ci break; 31968c2ecf20Sopenharmony_ci 31978c2ecf20Sopenharmony_ci case CT_DEMOD_STEP_5: /* (35) */ 31988c2ecf20Sopenharmony_ci locks = dib8000_read_lock(fe); 31998c2ecf20Sopenharmony_ci if (locks & (0x3 << 11)) { /* coff-lock and off_cpil_lock achieved */ 32008c2ecf20Sopenharmony_ci dib8000_update_timf(state); /* we achieved a coff_cpil_lock - it's time to update the timf */ 32018c2ecf20Sopenharmony_ci if (!state->differential_constellation) { 32028c2ecf20Sopenharmony_ci /* 2 times lmod4_win_len + 10 symbols (pipe delay after coff + nb to compute a 1st correlation) */ 32038c2ecf20Sopenharmony_ci *timeout = dib8000_get_timeout(state, (20 * ((dib8000_read_word(state, 188)>>5)&0x1f)), SYMBOL_DEPENDENT_ON); 32048c2ecf20Sopenharmony_ci *tune_state = CT_DEMOD_STEP_7; 32058c2ecf20Sopenharmony_ci } else { 32068c2ecf20Sopenharmony_ci *tune_state = CT_DEMOD_STEP_8; 32078c2ecf20Sopenharmony_ci } 32088c2ecf20Sopenharmony_ci } else if (time_after(now, *timeout)) { 32098c2ecf20Sopenharmony_ci *tune_state = CT_DEMOD_STEP_6; /* goto check for diversity input connection */ 32108c2ecf20Sopenharmony_ci } 32118c2ecf20Sopenharmony_ci break; 32128c2ecf20Sopenharmony_ci 32138c2ecf20Sopenharmony_ci case CT_DEMOD_STEP_6: /* (36) if there is an input (diversity) */ 32148c2ecf20Sopenharmony_ci if ((state->fe[1] != NULL) && (state->output_mode != OUTMODE_DIVERSITY)) { 32158c2ecf20Sopenharmony_ci /* if there is a diversity fe in input and this fe is has not already failed : wait here until this this fe has succedeed or failed */ 32168c2ecf20Sopenharmony_ci if (dib8000_get_status(state->fe[1]) <= FE_STATUS_STD_SUCCESS) /* Something is locked on the input fe */ 32178c2ecf20Sopenharmony_ci *tune_state = CT_DEMOD_STEP_8; /* go for mpeg */ 32188c2ecf20Sopenharmony_ci else if (dib8000_get_status(state->fe[1]) >= FE_STATUS_TUNE_TIME_TOO_SHORT) { /* fe in input failed also, break the current one */ 32198c2ecf20Sopenharmony_ci *tune_state = CT_DEMOD_STOP; /* else we are done here ; step 8 will close the loops and exit */ 32208c2ecf20Sopenharmony_ci dib8000_viterbi_state(state, 1); /* start viterbi chandec */ 32218c2ecf20Sopenharmony_ci dib8000_set_isdbt_loop_params(state, LOOP_TUNE_2); 32228c2ecf20Sopenharmony_ci state->status = FE_STATUS_TUNE_FAILED; 32238c2ecf20Sopenharmony_ci } 32248c2ecf20Sopenharmony_ci } else { 32258c2ecf20Sopenharmony_ci dib8000_viterbi_state(state, 1); /* start viterbi chandec */ 32268c2ecf20Sopenharmony_ci dib8000_set_isdbt_loop_params(state, LOOP_TUNE_2); 32278c2ecf20Sopenharmony_ci *tune_state = CT_DEMOD_STOP; /* else we are done here ; step 8 will close the loops and exit */ 32288c2ecf20Sopenharmony_ci state->status = FE_STATUS_TUNE_FAILED; 32298c2ecf20Sopenharmony_ci } 32308c2ecf20Sopenharmony_ci break; 32318c2ecf20Sopenharmony_ci 32328c2ecf20Sopenharmony_ci case CT_DEMOD_STEP_7: /* 37 */ 32338c2ecf20Sopenharmony_ci locks = dib8000_read_lock(fe); 32348c2ecf20Sopenharmony_ci if (locks & (1<<10)) { /* lmod4_lock */ 32358c2ecf20Sopenharmony_ci ret = 14; /* wait for 14 symbols */ 32368c2ecf20Sopenharmony_ci *tune_state = CT_DEMOD_STEP_8; 32378c2ecf20Sopenharmony_ci } else if (time_after(now, *timeout)) 32388c2ecf20Sopenharmony_ci *tune_state = CT_DEMOD_STEP_6; /* goto check for diversity input connection */ 32398c2ecf20Sopenharmony_ci break; 32408c2ecf20Sopenharmony_ci 32418c2ecf20Sopenharmony_ci case CT_DEMOD_STEP_8: /* 38 */ 32428c2ecf20Sopenharmony_ci dib8000_viterbi_state(state, 1); /* start viterbi chandec */ 32438c2ecf20Sopenharmony_ci dib8000_set_isdbt_loop_params(state, LOOP_TUNE_2); 32448c2ecf20Sopenharmony_ci 32458c2ecf20Sopenharmony_ci /* mpeg will never lock on this condition because init_prbs is not set : search for it !*/ 32468c2ecf20Sopenharmony_ci if (c->isdbt_sb_mode 32478c2ecf20Sopenharmony_ci && c->isdbt_sb_subchannel < 14 32488c2ecf20Sopenharmony_ci && !state->differential_constellation) { 32498c2ecf20Sopenharmony_ci state->subchannel = 0; 32508c2ecf20Sopenharmony_ci *tune_state = CT_DEMOD_STEP_11; 32518c2ecf20Sopenharmony_ci } else { 32528c2ecf20Sopenharmony_ci *tune_state = CT_DEMOD_STEP_9; 32538c2ecf20Sopenharmony_ci state->status = FE_STATUS_LOCKED; 32548c2ecf20Sopenharmony_ci } 32558c2ecf20Sopenharmony_ci break; 32568c2ecf20Sopenharmony_ci 32578c2ecf20Sopenharmony_ci case CT_DEMOD_STEP_9: /* 39 */ 32588c2ecf20Sopenharmony_ci if ((state->revision == 0x8090) || ((dib8000_read_word(state, 1291) >> 9) & 0x1)) { /* fe capable of deinterleaving : esram */ 32598c2ecf20Sopenharmony_ci /* defines timeout for mpeg lock depending on interleaver length of longest layer */ 32608c2ecf20Sopenharmony_ci for (i = 0; i < 3; i++) { 32618c2ecf20Sopenharmony_ci if (c->layer[i].interleaving >= deeper_interleaver) { 32628c2ecf20Sopenharmony_ci dprintk("layer%i: time interleaver = %d\n", i, c->layer[i].interleaving); 32638c2ecf20Sopenharmony_ci if (c->layer[i].segment_count > 0) { /* valid layer */ 32648c2ecf20Sopenharmony_ci deeper_interleaver = c->layer[0].interleaving; 32658c2ecf20Sopenharmony_ci state->longest_intlv_layer = i; 32668c2ecf20Sopenharmony_ci } 32678c2ecf20Sopenharmony_ci } 32688c2ecf20Sopenharmony_ci } 32698c2ecf20Sopenharmony_ci 32708c2ecf20Sopenharmony_ci if (deeper_interleaver == 0) 32718c2ecf20Sopenharmony_ci locks = 2; /* locks is the tmp local variable name */ 32728c2ecf20Sopenharmony_ci else if (deeper_interleaver == 3) 32738c2ecf20Sopenharmony_ci locks = 8; 32748c2ecf20Sopenharmony_ci else 32758c2ecf20Sopenharmony_ci locks = 2 * deeper_interleaver; 32768c2ecf20Sopenharmony_ci 32778c2ecf20Sopenharmony_ci if (state->diversity_onoff != 0) /* because of diversity sync */ 32788c2ecf20Sopenharmony_ci locks *= 2; 32798c2ecf20Sopenharmony_ci 32808c2ecf20Sopenharmony_ci *timeout = now + msecs_to_jiffies(200 * locks); /* give the mpeg lock 800ms if sram is present */ 32818c2ecf20Sopenharmony_ci dprintk("Deeper interleaver mode = %d on layer %d : timeout mult factor = %d => will use timeout = %ld\n", 32828c2ecf20Sopenharmony_ci deeper_interleaver, state->longest_intlv_layer, locks, *timeout); 32838c2ecf20Sopenharmony_ci 32848c2ecf20Sopenharmony_ci *tune_state = CT_DEMOD_STEP_10; 32858c2ecf20Sopenharmony_ci } else 32868c2ecf20Sopenharmony_ci *tune_state = CT_DEMOD_STOP; 32878c2ecf20Sopenharmony_ci break; 32888c2ecf20Sopenharmony_ci 32898c2ecf20Sopenharmony_ci case CT_DEMOD_STEP_10: /* 40 */ 32908c2ecf20Sopenharmony_ci locks = dib8000_read_lock(fe); 32918c2ecf20Sopenharmony_ci if (locks&(1<<(7-state->longest_intlv_layer))) { /* mpeg lock : check the longest one */ 32928c2ecf20Sopenharmony_ci dprintk("ISDB-T layer locks: Layer A %s, Layer B %s, Layer C %s\n", 32938c2ecf20Sopenharmony_ci c->layer[0].segment_count ? (locks >> 7) & 0x1 ? "locked" : "NOT LOCKED" : "not enabled", 32948c2ecf20Sopenharmony_ci c->layer[1].segment_count ? (locks >> 6) & 0x1 ? "locked" : "NOT LOCKED" : "not enabled", 32958c2ecf20Sopenharmony_ci c->layer[2].segment_count ? (locks >> 5) & 0x1 ? "locked" : "NOT LOCKED" : "not enabled"); 32968c2ecf20Sopenharmony_ci if (c->isdbt_sb_mode 32978c2ecf20Sopenharmony_ci && c->isdbt_sb_subchannel < 14 32988c2ecf20Sopenharmony_ci && !state->differential_constellation) 32998c2ecf20Sopenharmony_ci /* signal to the upper layer, that there was a channel found and the parameters can be read */ 33008c2ecf20Sopenharmony_ci state->status = FE_STATUS_DEMOD_SUCCESS; 33018c2ecf20Sopenharmony_ci else 33028c2ecf20Sopenharmony_ci state->status = FE_STATUS_DATA_LOCKED; 33038c2ecf20Sopenharmony_ci *tune_state = CT_DEMOD_STOP; 33048c2ecf20Sopenharmony_ci } else if (time_after(now, *timeout)) { 33058c2ecf20Sopenharmony_ci if (c->isdbt_sb_mode 33068c2ecf20Sopenharmony_ci && c->isdbt_sb_subchannel < 14 33078c2ecf20Sopenharmony_ci && !state->differential_constellation) { /* continue to try init prbs autosearch */ 33088c2ecf20Sopenharmony_ci state->subchannel += 3; 33098c2ecf20Sopenharmony_ci *tune_state = CT_DEMOD_STEP_11; 33108c2ecf20Sopenharmony_ci } else { /* we are done mpeg of the longest interleaver xas not locking but let's try if an other layer has locked in the same time */ 33118c2ecf20Sopenharmony_ci if (locks & (0x7 << 5)) { 33128c2ecf20Sopenharmony_ci dprintk("Not all ISDB-T layers locked in %d ms: Layer A %s, Layer B %s, Layer C %s\n", 33138c2ecf20Sopenharmony_ci jiffies_to_msecs(now - *timeout), 33148c2ecf20Sopenharmony_ci c->layer[0].segment_count ? (locks >> 7) & 0x1 ? "locked" : "NOT LOCKED" : "not enabled", 33158c2ecf20Sopenharmony_ci c->layer[1].segment_count ? (locks >> 6) & 0x1 ? "locked" : "NOT LOCKED" : "not enabled", 33168c2ecf20Sopenharmony_ci c->layer[2].segment_count ? (locks >> 5) & 0x1 ? "locked" : "NOT LOCKED" : "not enabled"); 33178c2ecf20Sopenharmony_ci 33188c2ecf20Sopenharmony_ci state->status = FE_STATUS_DATA_LOCKED; 33198c2ecf20Sopenharmony_ci } else 33208c2ecf20Sopenharmony_ci state->status = FE_STATUS_TUNE_FAILED; 33218c2ecf20Sopenharmony_ci *tune_state = CT_DEMOD_STOP; 33228c2ecf20Sopenharmony_ci } 33238c2ecf20Sopenharmony_ci } 33248c2ecf20Sopenharmony_ci break; 33258c2ecf20Sopenharmony_ci 33268c2ecf20Sopenharmony_ci case CT_DEMOD_STEP_11: /* 41 : init prbs autosearch */ 33278c2ecf20Sopenharmony_ci init_prbs = dib8000_get_init_prbs(state, state->subchannel); 33288c2ecf20Sopenharmony_ci 33298c2ecf20Sopenharmony_ci if (init_prbs) { 33308c2ecf20Sopenharmony_ci dib8000_set_subchannel_prbs(state, init_prbs); 33318c2ecf20Sopenharmony_ci *tune_state = CT_DEMOD_STEP_9; 33328c2ecf20Sopenharmony_ci } else { 33338c2ecf20Sopenharmony_ci *tune_state = CT_DEMOD_STOP; 33348c2ecf20Sopenharmony_ci state->status = FE_STATUS_TUNE_FAILED; 33358c2ecf20Sopenharmony_ci } 33368c2ecf20Sopenharmony_ci break; 33378c2ecf20Sopenharmony_ci 33388c2ecf20Sopenharmony_ci default: 33398c2ecf20Sopenharmony_ci break; 33408c2ecf20Sopenharmony_ci } 33418c2ecf20Sopenharmony_ci 33428c2ecf20Sopenharmony_ci /* tuning is finished - cleanup the demod */ 33438c2ecf20Sopenharmony_ci switch (*tune_state) { 33448c2ecf20Sopenharmony_ci case CT_DEMOD_STOP: /* (42) */ 33458c2ecf20Sopenharmony_ci#ifdef DIB8000_AGC_FREEZE 33468c2ecf20Sopenharmony_ci if ((state->revision != 0x8090) && (state->agc1_max != 0)) { 33478c2ecf20Sopenharmony_ci dib8000_write_word(state, 108, state->agc1_max); 33488c2ecf20Sopenharmony_ci dib8000_write_word(state, 109, state->agc1_min); 33498c2ecf20Sopenharmony_ci dib8000_write_word(state, 110, state->agc2_max); 33508c2ecf20Sopenharmony_ci dib8000_write_word(state, 111, state->agc2_min); 33518c2ecf20Sopenharmony_ci state->agc1_max = 0; 33528c2ecf20Sopenharmony_ci state->agc1_min = 0; 33538c2ecf20Sopenharmony_ci state->agc2_max = 0; 33548c2ecf20Sopenharmony_ci state->agc2_min = 0; 33558c2ecf20Sopenharmony_ci } 33568c2ecf20Sopenharmony_ci#endif 33578c2ecf20Sopenharmony_ci ret = 0; 33588c2ecf20Sopenharmony_ci break; 33598c2ecf20Sopenharmony_ci default: 33608c2ecf20Sopenharmony_ci break; 33618c2ecf20Sopenharmony_ci } 33628c2ecf20Sopenharmony_ci 33638c2ecf20Sopenharmony_ci if ((ret > 0) && (*tune_state > CT_DEMOD_STEP_3)) 33648c2ecf20Sopenharmony_ci return ret * state->symbol_duration; 33658c2ecf20Sopenharmony_ci if ((ret > 0) && (ret < state->symbol_duration)) 33668c2ecf20Sopenharmony_ci return state->symbol_duration; /* at least one symbol */ 33678c2ecf20Sopenharmony_ci return ret; 33688c2ecf20Sopenharmony_ci} 33698c2ecf20Sopenharmony_ci 33708c2ecf20Sopenharmony_cistatic int dib8000_wakeup(struct dvb_frontend *fe) 33718c2ecf20Sopenharmony_ci{ 33728c2ecf20Sopenharmony_ci struct dib8000_state *state = fe->demodulator_priv; 33738c2ecf20Sopenharmony_ci u8 index_frontend; 33748c2ecf20Sopenharmony_ci int ret; 33758c2ecf20Sopenharmony_ci 33768c2ecf20Sopenharmony_ci dib8000_set_power_mode(state, DIB8000_POWER_ALL); 33778c2ecf20Sopenharmony_ci dib8000_set_adc_state(state, DIBX000_ADC_ON); 33788c2ecf20Sopenharmony_ci if (dib8000_set_adc_state(state, DIBX000_SLOW_ADC_ON) != 0) 33798c2ecf20Sopenharmony_ci dprintk("could not start Slow ADC\n"); 33808c2ecf20Sopenharmony_ci 33818c2ecf20Sopenharmony_ci if (state->revision == 0x8090) 33828c2ecf20Sopenharmony_ci dib8000_sad_calib(state); 33838c2ecf20Sopenharmony_ci 33848c2ecf20Sopenharmony_ci for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) { 33858c2ecf20Sopenharmony_ci ret = state->fe[index_frontend]->ops.init(state->fe[index_frontend]); 33868c2ecf20Sopenharmony_ci if (ret < 0) 33878c2ecf20Sopenharmony_ci return ret; 33888c2ecf20Sopenharmony_ci } 33898c2ecf20Sopenharmony_ci 33908c2ecf20Sopenharmony_ci return 0; 33918c2ecf20Sopenharmony_ci} 33928c2ecf20Sopenharmony_ci 33938c2ecf20Sopenharmony_cistatic int dib8000_sleep(struct dvb_frontend *fe) 33948c2ecf20Sopenharmony_ci{ 33958c2ecf20Sopenharmony_ci struct dib8000_state *state = fe->demodulator_priv; 33968c2ecf20Sopenharmony_ci u8 index_frontend; 33978c2ecf20Sopenharmony_ci int ret; 33988c2ecf20Sopenharmony_ci 33998c2ecf20Sopenharmony_ci for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) { 34008c2ecf20Sopenharmony_ci ret = state->fe[index_frontend]->ops.sleep(state->fe[index_frontend]); 34018c2ecf20Sopenharmony_ci if (ret < 0) 34028c2ecf20Sopenharmony_ci return ret; 34038c2ecf20Sopenharmony_ci } 34048c2ecf20Sopenharmony_ci 34058c2ecf20Sopenharmony_ci if (state->revision != 0x8090) 34068c2ecf20Sopenharmony_ci dib8000_set_output_mode(fe, OUTMODE_HIGH_Z); 34078c2ecf20Sopenharmony_ci dib8000_set_power_mode(state, DIB8000_POWER_INTERFACE_ONLY); 34088c2ecf20Sopenharmony_ci return dib8000_set_adc_state(state, DIBX000_SLOW_ADC_OFF) | dib8000_set_adc_state(state, DIBX000_ADC_OFF); 34098c2ecf20Sopenharmony_ci} 34108c2ecf20Sopenharmony_ci 34118c2ecf20Sopenharmony_cistatic int dib8000_read_status(struct dvb_frontend *fe, enum fe_status *stat); 34128c2ecf20Sopenharmony_ci 34138c2ecf20Sopenharmony_cistatic int dib8000_get_frontend(struct dvb_frontend *fe, 34148c2ecf20Sopenharmony_ci struct dtv_frontend_properties *c) 34158c2ecf20Sopenharmony_ci{ 34168c2ecf20Sopenharmony_ci struct dib8000_state *state = fe->demodulator_priv; 34178c2ecf20Sopenharmony_ci u16 i, val = 0; 34188c2ecf20Sopenharmony_ci enum fe_status stat = 0; 34198c2ecf20Sopenharmony_ci u8 index_frontend, sub_index_frontend; 34208c2ecf20Sopenharmony_ci 34218c2ecf20Sopenharmony_ci c->bandwidth_hz = 6000000; 34228c2ecf20Sopenharmony_ci 34238c2ecf20Sopenharmony_ci /* 34248c2ecf20Sopenharmony_ci * If called to early, get_frontend makes dib8000_tune to either 34258c2ecf20Sopenharmony_ci * not lock or not sync. This causes dvbv5-scan/dvbv5-zap to fail. 34268c2ecf20Sopenharmony_ci * So, let's just return if frontend 0 has not locked. 34278c2ecf20Sopenharmony_ci */ 34288c2ecf20Sopenharmony_ci dib8000_read_status(fe, &stat); 34298c2ecf20Sopenharmony_ci if (!(stat & FE_HAS_SYNC)) 34308c2ecf20Sopenharmony_ci return 0; 34318c2ecf20Sopenharmony_ci 34328c2ecf20Sopenharmony_ci dprintk("dib8000_get_frontend: TMCC lock\n"); 34338c2ecf20Sopenharmony_ci for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) { 34348c2ecf20Sopenharmony_ci state->fe[index_frontend]->ops.read_status(state->fe[index_frontend], &stat); 34358c2ecf20Sopenharmony_ci if (stat&FE_HAS_SYNC) { 34368c2ecf20Sopenharmony_ci dprintk("TMCC lock on the slave%i\n", index_frontend); 34378c2ecf20Sopenharmony_ci /* synchronize the cache with the other frontends */ 34388c2ecf20Sopenharmony_ci state->fe[index_frontend]->ops.get_frontend(state->fe[index_frontend], c); 34398c2ecf20Sopenharmony_ci for (sub_index_frontend = 0; (sub_index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[sub_index_frontend] != NULL); sub_index_frontend++) { 34408c2ecf20Sopenharmony_ci if (sub_index_frontend != index_frontend) { 34418c2ecf20Sopenharmony_ci state->fe[sub_index_frontend]->dtv_property_cache.isdbt_sb_mode = state->fe[index_frontend]->dtv_property_cache.isdbt_sb_mode; 34428c2ecf20Sopenharmony_ci state->fe[sub_index_frontend]->dtv_property_cache.inversion = state->fe[index_frontend]->dtv_property_cache.inversion; 34438c2ecf20Sopenharmony_ci state->fe[sub_index_frontend]->dtv_property_cache.transmission_mode = state->fe[index_frontend]->dtv_property_cache.transmission_mode; 34448c2ecf20Sopenharmony_ci state->fe[sub_index_frontend]->dtv_property_cache.guard_interval = state->fe[index_frontend]->dtv_property_cache.guard_interval; 34458c2ecf20Sopenharmony_ci state->fe[sub_index_frontend]->dtv_property_cache.isdbt_partial_reception = state->fe[index_frontend]->dtv_property_cache.isdbt_partial_reception; 34468c2ecf20Sopenharmony_ci for (i = 0; i < 3; i++) { 34478c2ecf20Sopenharmony_ci state->fe[sub_index_frontend]->dtv_property_cache.layer[i].segment_count = state->fe[index_frontend]->dtv_property_cache.layer[i].segment_count; 34488c2ecf20Sopenharmony_ci state->fe[sub_index_frontend]->dtv_property_cache.layer[i].interleaving = state->fe[index_frontend]->dtv_property_cache.layer[i].interleaving; 34498c2ecf20Sopenharmony_ci state->fe[sub_index_frontend]->dtv_property_cache.layer[i].fec = state->fe[index_frontend]->dtv_property_cache.layer[i].fec; 34508c2ecf20Sopenharmony_ci state->fe[sub_index_frontend]->dtv_property_cache.layer[i].modulation = state->fe[index_frontend]->dtv_property_cache.layer[i].modulation; 34518c2ecf20Sopenharmony_ci } 34528c2ecf20Sopenharmony_ci } 34538c2ecf20Sopenharmony_ci } 34548c2ecf20Sopenharmony_ci return 0; 34558c2ecf20Sopenharmony_ci } 34568c2ecf20Sopenharmony_ci } 34578c2ecf20Sopenharmony_ci 34588c2ecf20Sopenharmony_ci c->isdbt_sb_mode = dib8000_read_word(state, 508) & 0x1; 34598c2ecf20Sopenharmony_ci 34608c2ecf20Sopenharmony_ci if (state->revision == 0x8090) 34618c2ecf20Sopenharmony_ci val = dib8000_read_word(state, 572); 34628c2ecf20Sopenharmony_ci else 34638c2ecf20Sopenharmony_ci val = dib8000_read_word(state, 570); 34648c2ecf20Sopenharmony_ci c->inversion = (val & 0x40) >> 6; 34658c2ecf20Sopenharmony_ci switch ((val & 0x30) >> 4) { 34668c2ecf20Sopenharmony_ci case 1: 34678c2ecf20Sopenharmony_ci c->transmission_mode = TRANSMISSION_MODE_2K; 34688c2ecf20Sopenharmony_ci dprintk("dib8000_get_frontend: transmission mode 2K\n"); 34698c2ecf20Sopenharmony_ci break; 34708c2ecf20Sopenharmony_ci case 2: 34718c2ecf20Sopenharmony_ci c->transmission_mode = TRANSMISSION_MODE_4K; 34728c2ecf20Sopenharmony_ci dprintk("dib8000_get_frontend: transmission mode 4K\n"); 34738c2ecf20Sopenharmony_ci break; 34748c2ecf20Sopenharmony_ci case 3: 34758c2ecf20Sopenharmony_ci default: 34768c2ecf20Sopenharmony_ci c->transmission_mode = TRANSMISSION_MODE_8K; 34778c2ecf20Sopenharmony_ci dprintk("dib8000_get_frontend: transmission mode 8K\n"); 34788c2ecf20Sopenharmony_ci break; 34798c2ecf20Sopenharmony_ci } 34808c2ecf20Sopenharmony_ci 34818c2ecf20Sopenharmony_ci switch (val & 0x3) { 34828c2ecf20Sopenharmony_ci case 0: 34838c2ecf20Sopenharmony_ci c->guard_interval = GUARD_INTERVAL_1_32; 34848c2ecf20Sopenharmony_ci dprintk("dib8000_get_frontend: Guard Interval = 1/32\n"); 34858c2ecf20Sopenharmony_ci break; 34868c2ecf20Sopenharmony_ci case 1: 34878c2ecf20Sopenharmony_ci c->guard_interval = GUARD_INTERVAL_1_16; 34888c2ecf20Sopenharmony_ci dprintk("dib8000_get_frontend: Guard Interval = 1/16\n"); 34898c2ecf20Sopenharmony_ci break; 34908c2ecf20Sopenharmony_ci case 2: 34918c2ecf20Sopenharmony_ci dprintk("dib8000_get_frontend: Guard Interval = 1/8\n"); 34928c2ecf20Sopenharmony_ci c->guard_interval = GUARD_INTERVAL_1_8; 34938c2ecf20Sopenharmony_ci break; 34948c2ecf20Sopenharmony_ci case 3: 34958c2ecf20Sopenharmony_ci dprintk("dib8000_get_frontend: Guard Interval = 1/4\n"); 34968c2ecf20Sopenharmony_ci c->guard_interval = GUARD_INTERVAL_1_4; 34978c2ecf20Sopenharmony_ci break; 34988c2ecf20Sopenharmony_ci } 34998c2ecf20Sopenharmony_ci 35008c2ecf20Sopenharmony_ci val = dib8000_read_word(state, 505); 35018c2ecf20Sopenharmony_ci c->isdbt_partial_reception = val & 1; 35028c2ecf20Sopenharmony_ci dprintk("dib8000_get_frontend: partial_reception = %d\n", c->isdbt_partial_reception); 35038c2ecf20Sopenharmony_ci 35048c2ecf20Sopenharmony_ci for (i = 0; i < 3; i++) { 35058c2ecf20Sopenharmony_ci int show; 35068c2ecf20Sopenharmony_ci 35078c2ecf20Sopenharmony_ci val = dib8000_read_word(state, 493 + i) & 0x0f; 35088c2ecf20Sopenharmony_ci c->layer[i].segment_count = val; 35098c2ecf20Sopenharmony_ci 35108c2ecf20Sopenharmony_ci if (val == 0 || val > 13) 35118c2ecf20Sopenharmony_ci show = 0; 35128c2ecf20Sopenharmony_ci else 35138c2ecf20Sopenharmony_ci show = 1; 35148c2ecf20Sopenharmony_ci 35158c2ecf20Sopenharmony_ci if (show) 35168c2ecf20Sopenharmony_ci dprintk("dib8000_get_frontend: Layer %d segments = %d\n", 35178c2ecf20Sopenharmony_ci i, c->layer[i].segment_count); 35188c2ecf20Sopenharmony_ci 35198c2ecf20Sopenharmony_ci val = dib8000_read_word(state, 499 + i) & 0x3; 35208c2ecf20Sopenharmony_ci /* Interleaving can be 0, 1, 2 or 4 */ 35218c2ecf20Sopenharmony_ci if (val == 3) 35228c2ecf20Sopenharmony_ci val = 4; 35238c2ecf20Sopenharmony_ci c->layer[i].interleaving = val; 35248c2ecf20Sopenharmony_ci if (show) 35258c2ecf20Sopenharmony_ci dprintk("dib8000_get_frontend: Layer %d time_intlv = %d\n", 35268c2ecf20Sopenharmony_ci i, c->layer[i].interleaving); 35278c2ecf20Sopenharmony_ci 35288c2ecf20Sopenharmony_ci val = dib8000_read_word(state, 481 + i); 35298c2ecf20Sopenharmony_ci switch (val & 0x7) { 35308c2ecf20Sopenharmony_ci case 1: 35318c2ecf20Sopenharmony_ci c->layer[i].fec = FEC_1_2; 35328c2ecf20Sopenharmony_ci if (show) 35338c2ecf20Sopenharmony_ci dprintk("dib8000_get_frontend: Layer %d Code Rate = 1/2\n", i); 35348c2ecf20Sopenharmony_ci break; 35358c2ecf20Sopenharmony_ci case 2: 35368c2ecf20Sopenharmony_ci c->layer[i].fec = FEC_2_3; 35378c2ecf20Sopenharmony_ci if (show) 35388c2ecf20Sopenharmony_ci dprintk("dib8000_get_frontend: Layer %d Code Rate = 2/3\n", i); 35398c2ecf20Sopenharmony_ci break; 35408c2ecf20Sopenharmony_ci case 3: 35418c2ecf20Sopenharmony_ci c->layer[i].fec = FEC_3_4; 35428c2ecf20Sopenharmony_ci if (show) 35438c2ecf20Sopenharmony_ci dprintk("dib8000_get_frontend: Layer %d Code Rate = 3/4\n", i); 35448c2ecf20Sopenharmony_ci break; 35458c2ecf20Sopenharmony_ci case 5: 35468c2ecf20Sopenharmony_ci c->layer[i].fec = FEC_5_6; 35478c2ecf20Sopenharmony_ci if (show) 35488c2ecf20Sopenharmony_ci dprintk("dib8000_get_frontend: Layer %d Code Rate = 5/6\n", i); 35498c2ecf20Sopenharmony_ci break; 35508c2ecf20Sopenharmony_ci default: 35518c2ecf20Sopenharmony_ci c->layer[i].fec = FEC_7_8; 35528c2ecf20Sopenharmony_ci if (show) 35538c2ecf20Sopenharmony_ci dprintk("dib8000_get_frontend: Layer %d Code Rate = 7/8\n", i); 35548c2ecf20Sopenharmony_ci break; 35558c2ecf20Sopenharmony_ci } 35568c2ecf20Sopenharmony_ci 35578c2ecf20Sopenharmony_ci val = dib8000_read_word(state, 487 + i); 35588c2ecf20Sopenharmony_ci switch (val & 0x3) { 35598c2ecf20Sopenharmony_ci case 0: 35608c2ecf20Sopenharmony_ci c->layer[i].modulation = DQPSK; 35618c2ecf20Sopenharmony_ci if (show) 35628c2ecf20Sopenharmony_ci dprintk("dib8000_get_frontend: Layer %d DQPSK\n", i); 35638c2ecf20Sopenharmony_ci break; 35648c2ecf20Sopenharmony_ci case 1: 35658c2ecf20Sopenharmony_ci c->layer[i].modulation = QPSK; 35668c2ecf20Sopenharmony_ci if (show) 35678c2ecf20Sopenharmony_ci dprintk("dib8000_get_frontend: Layer %d QPSK\n", i); 35688c2ecf20Sopenharmony_ci break; 35698c2ecf20Sopenharmony_ci case 2: 35708c2ecf20Sopenharmony_ci c->layer[i].modulation = QAM_16; 35718c2ecf20Sopenharmony_ci if (show) 35728c2ecf20Sopenharmony_ci dprintk("dib8000_get_frontend: Layer %d QAM16\n", i); 35738c2ecf20Sopenharmony_ci break; 35748c2ecf20Sopenharmony_ci case 3: 35758c2ecf20Sopenharmony_ci default: 35768c2ecf20Sopenharmony_ci c->layer[i].modulation = QAM_64; 35778c2ecf20Sopenharmony_ci if (show) 35788c2ecf20Sopenharmony_ci dprintk("dib8000_get_frontend: Layer %d QAM64\n", i); 35798c2ecf20Sopenharmony_ci break; 35808c2ecf20Sopenharmony_ci } 35818c2ecf20Sopenharmony_ci } 35828c2ecf20Sopenharmony_ci 35838c2ecf20Sopenharmony_ci /* synchronize the cache with the other frontends */ 35848c2ecf20Sopenharmony_ci for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) { 35858c2ecf20Sopenharmony_ci state->fe[index_frontend]->dtv_property_cache.isdbt_sb_mode = c->isdbt_sb_mode; 35868c2ecf20Sopenharmony_ci state->fe[index_frontend]->dtv_property_cache.inversion = c->inversion; 35878c2ecf20Sopenharmony_ci state->fe[index_frontend]->dtv_property_cache.transmission_mode = c->transmission_mode; 35888c2ecf20Sopenharmony_ci state->fe[index_frontend]->dtv_property_cache.guard_interval = c->guard_interval; 35898c2ecf20Sopenharmony_ci state->fe[index_frontend]->dtv_property_cache.isdbt_partial_reception = c->isdbt_partial_reception; 35908c2ecf20Sopenharmony_ci for (i = 0; i < 3; i++) { 35918c2ecf20Sopenharmony_ci state->fe[index_frontend]->dtv_property_cache.layer[i].segment_count = c->layer[i].segment_count; 35928c2ecf20Sopenharmony_ci state->fe[index_frontend]->dtv_property_cache.layer[i].interleaving = c->layer[i].interleaving; 35938c2ecf20Sopenharmony_ci state->fe[index_frontend]->dtv_property_cache.layer[i].fec = c->layer[i].fec; 35948c2ecf20Sopenharmony_ci state->fe[index_frontend]->dtv_property_cache.layer[i].modulation = c->layer[i].modulation; 35958c2ecf20Sopenharmony_ci } 35968c2ecf20Sopenharmony_ci } 35978c2ecf20Sopenharmony_ci return 0; 35988c2ecf20Sopenharmony_ci} 35998c2ecf20Sopenharmony_ci 36008c2ecf20Sopenharmony_cistatic int dib8000_set_frontend(struct dvb_frontend *fe) 36018c2ecf20Sopenharmony_ci{ 36028c2ecf20Sopenharmony_ci struct dib8000_state *state = fe->demodulator_priv; 36038c2ecf20Sopenharmony_ci struct dtv_frontend_properties *c = &state->fe[0]->dtv_property_cache; 36048c2ecf20Sopenharmony_ci int l, i, active, time, time_slave = 0; 36058c2ecf20Sopenharmony_ci u8 exit_condition, index_frontend; 36068c2ecf20Sopenharmony_ci unsigned long delay, callback_time; 36078c2ecf20Sopenharmony_ci 36088c2ecf20Sopenharmony_ci if (c->frequency == 0) { 36098c2ecf20Sopenharmony_ci dprintk("dib8000: must at least specify frequency\n"); 36108c2ecf20Sopenharmony_ci return 0; 36118c2ecf20Sopenharmony_ci } 36128c2ecf20Sopenharmony_ci 36138c2ecf20Sopenharmony_ci if (c->bandwidth_hz == 0) { 36148c2ecf20Sopenharmony_ci dprintk("dib8000: no bandwidth specified, set to default\n"); 36158c2ecf20Sopenharmony_ci c->bandwidth_hz = 6000000; 36168c2ecf20Sopenharmony_ci } 36178c2ecf20Sopenharmony_ci 36188c2ecf20Sopenharmony_ci for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) { 36198c2ecf20Sopenharmony_ci /* synchronization of the cache */ 36208c2ecf20Sopenharmony_ci state->fe[index_frontend]->dtv_property_cache.delivery_system = SYS_ISDBT; 36218c2ecf20Sopenharmony_ci memcpy(&state->fe[index_frontend]->dtv_property_cache, &fe->dtv_property_cache, sizeof(struct dtv_frontend_properties)); 36228c2ecf20Sopenharmony_ci 36238c2ecf20Sopenharmony_ci /* set output mode and diversity input */ 36248c2ecf20Sopenharmony_ci if (state->revision != 0x8090) { 36258c2ecf20Sopenharmony_ci dib8000_set_diversity_in(state->fe[index_frontend], 1); 36268c2ecf20Sopenharmony_ci if (index_frontend != 0) 36278c2ecf20Sopenharmony_ci dib8000_set_output_mode(state->fe[index_frontend], 36288c2ecf20Sopenharmony_ci OUTMODE_DIVERSITY); 36298c2ecf20Sopenharmony_ci else 36308c2ecf20Sopenharmony_ci dib8000_set_output_mode(state->fe[0], OUTMODE_HIGH_Z); 36318c2ecf20Sopenharmony_ci } else { 36328c2ecf20Sopenharmony_ci dib8096p_set_diversity_in(state->fe[index_frontend], 1); 36338c2ecf20Sopenharmony_ci if (index_frontend != 0) 36348c2ecf20Sopenharmony_ci dib8096p_set_output_mode(state->fe[index_frontend], 36358c2ecf20Sopenharmony_ci OUTMODE_DIVERSITY); 36368c2ecf20Sopenharmony_ci else 36378c2ecf20Sopenharmony_ci dib8096p_set_output_mode(state->fe[0], OUTMODE_HIGH_Z); 36388c2ecf20Sopenharmony_ci } 36398c2ecf20Sopenharmony_ci 36408c2ecf20Sopenharmony_ci /* tune the tuner */ 36418c2ecf20Sopenharmony_ci if (state->fe[index_frontend]->ops.tuner_ops.set_params) 36428c2ecf20Sopenharmony_ci state->fe[index_frontend]->ops.tuner_ops.set_params(state->fe[index_frontend]); 36438c2ecf20Sopenharmony_ci 36448c2ecf20Sopenharmony_ci dib8000_set_tune_state(state->fe[index_frontend], CT_AGC_START); 36458c2ecf20Sopenharmony_ci } 36468c2ecf20Sopenharmony_ci 36478c2ecf20Sopenharmony_ci /* turn off the diversity of the last chip */ 36488c2ecf20Sopenharmony_ci if (state->revision != 0x8090) 36498c2ecf20Sopenharmony_ci dib8000_set_diversity_in(state->fe[index_frontend - 1], 0); 36508c2ecf20Sopenharmony_ci else 36518c2ecf20Sopenharmony_ci dib8096p_set_diversity_in(state->fe[index_frontend - 1], 0); 36528c2ecf20Sopenharmony_ci 36538c2ecf20Sopenharmony_ci /* start up the AGC */ 36548c2ecf20Sopenharmony_ci do { 36558c2ecf20Sopenharmony_ci time = dib8000_agc_startup(state->fe[0]); 36568c2ecf20Sopenharmony_ci for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) { 36578c2ecf20Sopenharmony_ci time_slave = dib8000_agc_startup(state->fe[index_frontend]); 36588c2ecf20Sopenharmony_ci if (time == 0) 36598c2ecf20Sopenharmony_ci time = time_slave; 36608c2ecf20Sopenharmony_ci else if ((time_slave != 0) && (time_slave > time)) 36618c2ecf20Sopenharmony_ci time = time_slave; 36628c2ecf20Sopenharmony_ci } 36638c2ecf20Sopenharmony_ci if (time == 0) 36648c2ecf20Sopenharmony_ci break; 36658c2ecf20Sopenharmony_ci 36668c2ecf20Sopenharmony_ci /* 36678c2ecf20Sopenharmony_ci * Despite dib8000_agc_startup returns time at a 0.1 ms range, 36688c2ecf20Sopenharmony_ci * the actual sleep time depends on CONFIG_HZ. The worse case 36698c2ecf20Sopenharmony_ci * is when CONFIG_HZ=100. In such case, the minimum granularity 36708c2ecf20Sopenharmony_ci * is 10ms. On some real field tests, the tuner sometimes don't 36718c2ecf20Sopenharmony_ci * lock when this timer is lower than 10ms. So, enforce a 10ms 36728c2ecf20Sopenharmony_ci * granularity. 36738c2ecf20Sopenharmony_ci */ 36748c2ecf20Sopenharmony_ci time = 10 * (time + 99)/100; 36758c2ecf20Sopenharmony_ci usleep_range(time * 1000, (time + 1) * 1000); 36768c2ecf20Sopenharmony_ci exit_condition = 1; 36778c2ecf20Sopenharmony_ci for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) { 36788c2ecf20Sopenharmony_ci if (dib8000_get_tune_state(state->fe[index_frontend]) != CT_AGC_STOP) { 36798c2ecf20Sopenharmony_ci exit_condition = 0; 36808c2ecf20Sopenharmony_ci break; 36818c2ecf20Sopenharmony_ci } 36828c2ecf20Sopenharmony_ci } 36838c2ecf20Sopenharmony_ci } while (exit_condition == 0); 36848c2ecf20Sopenharmony_ci 36858c2ecf20Sopenharmony_ci for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) 36868c2ecf20Sopenharmony_ci dib8000_set_tune_state(state->fe[index_frontend], CT_DEMOD_START); 36878c2ecf20Sopenharmony_ci 36888c2ecf20Sopenharmony_ci active = 1; 36898c2ecf20Sopenharmony_ci do { 36908c2ecf20Sopenharmony_ci callback_time = 0; 36918c2ecf20Sopenharmony_ci for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) { 36928c2ecf20Sopenharmony_ci delay = dib8000_tune(state->fe[index_frontend]); 36938c2ecf20Sopenharmony_ci if (delay != 0) { 36948c2ecf20Sopenharmony_ci delay = jiffies + usecs_to_jiffies(100 * delay); 36958c2ecf20Sopenharmony_ci if (!callback_time || delay < callback_time) 36968c2ecf20Sopenharmony_ci callback_time = delay; 36978c2ecf20Sopenharmony_ci } 36988c2ecf20Sopenharmony_ci 36998c2ecf20Sopenharmony_ci /* we are in autosearch */ 37008c2ecf20Sopenharmony_ci if (state->channel_parameters_set == 0) { /* searching */ 37018c2ecf20Sopenharmony_ci if ((dib8000_get_status(state->fe[index_frontend]) == FE_STATUS_DEMOD_SUCCESS) || (dib8000_get_status(state->fe[index_frontend]) == FE_STATUS_FFT_SUCCESS)) { 37028c2ecf20Sopenharmony_ci dprintk("autosearch succeeded on fe%i\n", index_frontend); 37038c2ecf20Sopenharmony_ci dib8000_get_frontend(state->fe[index_frontend], c); /* we read the channel parameters from the frontend which was successful */ 37048c2ecf20Sopenharmony_ci state->channel_parameters_set = 1; 37058c2ecf20Sopenharmony_ci 37068c2ecf20Sopenharmony_ci for (l = 0; (l < MAX_NUMBER_OF_FRONTENDS) && (state->fe[l] != NULL); l++) { 37078c2ecf20Sopenharmony_ci if (l != index_frontend) { /* and for all frontend except the successful one */ 37088c2ecf20Sopenharmony_ci dprintk("Restarting frontend %d\n", l); 37098c2ecf20Sopenharmony_ci dib8000_tune_restart_from_demod(state->fe[l]); 37108c2ecf20Sopenharmony_ci 37118c2ecf20Sopenharmony_ci state->fe[l]->dtv_property_cache.isdbt_sb_mode = state->fe[index_frontend]->dtv_property_cache.isdbt_sb_mode; 37128c2ecf20Sopenharmony_ci state->fe[l]->dtv_property_cache.inversion = state->fe[index_frontend]->dtv_property_cache.inversion; 37138c2ecf20Sopenharmony_ci state->fe[l]->dtv_property_cache.transmission_mode = state->fe[index_frontend]->dtv_property_cache.transmission_mode; 37148c2ecf20Sopenharmony_ci state->fe[l]->dtv_property_cache.guard_interval = state->fe[index_frontend]->dtv_property_cache.guard_interval; 37158c2ecf20Sopenharmony_ci state->fe[l]->dtv_property_cache.isdbt_partial_reception = state->fe[index_frontend]->dtv_property_cache.isdbt_partial_reception; 37168c2ecf20Sopenharmony_ci for (i = 0; i < 3; i++) { 37178c2ecf20Sopenharmony_ci state->fe[l]->dtv_property_cache.layer[i].segment_count = state->fe[index_frontend]->dtv_property_cache.layer[i].segment_count; 37188c2ecf20Sopenharmony_ci state->fe[l]->dtv_property_cache.layer[i].interleaving = state->fe[index_frontend]->dtv_property_cache.layer[i].interleaving; 37198c2ecf20Sopenharmony_ci state->fe[l]->dtv_property_cache.layer[i].fec = state->fe[index_frontend]->dtv_property_cache.layer[i].fec; 37208c2ecf20Sopenharmony_ci state->fe[l]->dtv_property_cache.layer[i].modulation = state->fe[index_frontend]->dtv_property_cache.layer[i].modulation; 37218c2ecf20Sopenharmony_ci } 37228c2ecf20Sopenharmony_ci 37238c2ecf20Sopenharmony_ci } 37248c2ecf20Sopenharmony_ci } 37258c2ecf20Sopenharmony_ci } 37268c2ecf20Sopenharmony_ci } 37278c2ecf20Sopenharmony_ci } 37288c2ecf20Sopenharmony_ci /* tuning is done when the master frontend is done (failed or success) */ 37298c2ecf20Sopenharmony_ci if (dib8000_get_status(state->fe[0]) == FE_STATUS_TUNE_FAILED || 37308c2ecf20Sopenharmony_ci dib8000_get_status(state->fe[0]) == FE_STATUS_LOCKED || 37318c2ecf20Sopenharmony_ci dib8000_get_status(state->fe[0]) == FE_STATUS_DATA_LOCKED) { 37328c2ecf20Sopenharmony_ci active = 0; 37338c2ecf20Sopenharmony_ci /* we need to wait for all frontends to be finished */ 37348c2ecf20Sopenharmony_ci for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) { 37358c2ecf20Sopenharmony_ci if (dib8000_get_tune_state(state->fe[index_frontend]) != CT_DEMOD_STOP) 37368c2ecf20Sopenharmony_ci active = 1; 37378c2ecf20Sopenharmony_ci } 37388c2ecf20Sopenharmony_ci if (active == 0) 37398c2ecf20Sopenharmony_ci dprintk("tuning done with status %d\n", dib8000_get_status(state->fe[0])); 37408c2ecf20Sopenharmony_ci } 37418c2ecf20Sopenharmony_ci 37428c2ecf20Sopenharmony_ci if ((active == 1) && (callback_time == 0)) { 37438c2ecf20Sopenharmony_ci dprintk("strange callback time something went wrong\n"); 37448c2ecf20Sopenharmony_ci active = 0; 37458c2ecf20Sopenharmony_ci } 37468c2ecf20Sopenharmony_ci 37478c2ecf20Sopenharmony_ci while ((active == 1) && (time_before(jiffies, callback_time))) 37488c2ecf20Sopenharmony_ci msleep(100); 37498c2ecf20Sopenharmony_ci } while (active); 37508c2ecf20Sopenharmony_ci 37518c2ecf20Sopenharmony_ci /* set output mode */ 37528c2ecf20Sopenharmony_ci if (state->revision != 0x8090) 37538c2ecf20Sopenharmony_ci dib8000_set_output_mode(state->fe[0], state->cfg.output_mode); 37548c2ecf20Sopenharmony_ci else { 37558c2ecf20Sopenharmony_ci dib8096p_set_output_mode(state->fe[0], state->cfg.output_mode); 37568c2ecf20Sopenharmony_ci if (state->cfg.enMpegOutput == 0) { 37578c2ecf20Sopenharmony_ci dib8096p_setDibTxMux(state, MPEG_ON_DIBTX); 37588c2ecf20Sopenharmony_ci dib8096p_setHostBusMux(state, DIBTX_ON_HOSTBUS); 37598c2ecf20Sopenharmony_ci } 37608c2ecf20Sopenharmony_ci } 37618c2ecf20Sopenharmony_ci 37628c2ecf20Sopenharmony_ci return 0; 37638c2ecf20Sopenharmony_ci} 37648c2ecf20Sopenharmony_ci 37658c2ecf20Sopenharmony_cistatic int dib8000_get_stats(struct dvb_frontend *fe, enum fe_status stat); 37668c2ecf20Sopenharmony_ci 37678c2ecf20Sopenharmony_cistatic int dib8000_read_status(struct dvb_frontend *fe, enum fe_status *stat) 37688c2ecf20Sopenharmony_ci{ 37698c2ecf20Sopenharmony_ci struct dib8000_state *state = fe->demodulator_priv; 37708c2ecf20Sopenharmony_ci u16 lock_slave = 0, lock; 37718c2ecf20Sopenharmony_ci u8 index_frontend; 37728c2ecf20Sopenharmony_ci 37738c2ecf20Sopenharmony_ci lock = dib8000_read_lock(fe); 37748c2ecf20Sopenharmony_ci for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) 37758c2ecf20Sopenharmony_ci lock_slave |= dib8000_read_lock(state->fe[index_frontend]); 37768c2ecf20Sopenharmony_ci 37778c2ecf20Sopenharmony_ci *stat = 0; 37788c2ecf20Sopenharmony_ci 37798c2ecf20Sopenharmony_ci if (((lock >> 13) & 1) || ((lock_slave >> 13) & 1)) 37808c2ecf20Sopenharmony_ci *stat |= FE_HAS_SIGNAL; 37818c2ecf20Sopenharmony_ci 37828c2ecf20Sopenharmony_ci if (((lock >> 8) & 1) || ((lock_slave >> 8) & 1)) /* Equal */ 37838c2ecf20Sopenharmony_ci *stat |= FE_HAS_CARRIER; 37848c2ecf20Sopenharmony_ci 37858c2ecf20Sopenharmony_ci if ((((lock >> 1) & 0xf) == 0xf) || (((lock_slave >> 1) & 0xf) == 0xf)) /* TMCC_SYNC */ 37868c2ecf20Sopenharmony_ci *stat |= FE_HAS_SYNC; 37878c2ecf20Sopenharmony_ci 37888c2ecf20Sopenharmony_ci if ((((lock >> 12) & 1) || ((lock_slave >> 12) & 1)) && ((lock >> 5) & 7)) /* FEC MPEG */ 37898c2ecf20Sopenharmony_ci *stat |= FE_HAS_LOCK; 37908c2ecf20Sopenharmony_ci 37918c2ecf20Sopenharmony_ci if (((lock >> 12) & 1) || ((lock_slave >> 12) & 1)) { 37928c2ecf20Sopenharmony_ci lock = dib8000_read_word(state, 554); /* Viterbi Layer A */ 37938c2ecf20Sopenharmony_ci if (lock & 0x01) 37948c2ecf20Sopenharmony_ci *stat |= FE_HAS_VITERBI; 37958c2ecf20Sopenharmony_ci 37968c2ecf20Sopenharmony_ci lock = dib8000_read_word(state, 555); /* Viterbi Layer B */ 37978c2ecf20Sopenharmony_ci if (lock & 0x01) 37988c2ecf20Sopenharmony_ci *stat |= FE_HAS_VITERBI; 37998c2ecf20Sopenharmony_ci 38008c2ecf20Sopenharmony_ci lock = dib8000_read_word(state, 556); /* Viterbi Layer C */ 38018c2ecf20Sopenharmony_ci if (lock & 0x01) 38028c2ecf20Sopenharmony_ci *stat |= FE_HAS_VITERBI; 38038c2ecf20Sopenharmony_ci } 38048c2ecf20Sopenharmony_ci dib8000_get_stats(fe, *stat); 38058c2ecf20Sopenharmony_ci 38068c2ecf20Sopenharmony_ci return 0; 38078c2ecf20Sopenharmony_ci} 38088c2ecf20Sopenharmony_ci 38098c2ecf20Sopenharmony_cistatic int dib8000_read_ber(struct dvb_frontend *fe, u32 * ber) 38108c2ecf20Sopenharmony_ci{ 38118c2ecf20Sopenharmony_ci struct dib8000_state *state = fe->demodulator_priv; 38128c2ecf20Sopenharmony_ci 38138c2ecf20Sopenharmony_ci /* 13 segments */ 38148c2ecf20Sopenharmony_ci if (state->revision == 0x8090) 38158c2ecf20Sopenharmony_ci *ber = (dib8000_read_word(state, 562) << 16) | 38168c2ecf20Sopenharmony_ci dib8000_read_word(state, 563); 38178c2ecf20Sopenharmony_ci else 38188c2ecf20Sopenharmony_ci *ber = (dib8000_read_word(state, 560) << 16) | 38198c2ecf20Sopenharmony_ci dib8000_read_word(state, 561); 38208c2ecf20Sopenharmony_ci return 0; 38218c2ecf20Sopenharmony_ci} 38228c2ecf20Sopenharmony_ci 38238c2ecf20Sopenharmony_cistatic int dib8000_read_unc_blocks(struct dvb_frontend *fe, u32 * unc) 38248c2ecf20Sopenharmony_ci{ 38258c2ecf20Sopenharmony_ci struct dib8000_state *state = fe->demodulator_priv; 38268c2ecf20Sopenharmony_ci 38278c2ecf20Sopenharmony_ci /* packet error on 13 seg */ 38288c2ecf20Sopenharmony_ci if (state->revision == 0x8090) 38298c2ecf20Sopenharmony_ci *unc = dib8000_read_word(state, 567); 38308c2ecf20Sopenharmony_ci else 38318c2ecf20Sopenharmony_ci *unc = dib8000_read_word(state, 565); 38328c2ecf20Sopenharmony_ci return 0; 38338c2ecf20Sopenharmony_ci} 38348c2ecf20Sopenharmony_ci 38358c2ecf20Sopenharmony_cistatic int dib8000_read_signal_strength(struct dvb_frontend *fe, u16 * strength) 38368c2ecf20Sopenharmony_ci{ 38378c2ecf20Sopenharmony_ci struct dib8000_state *state = fe->demodulator_priv; 38388c2ecf20Sopenharmony_ci u8 index_frontend; 38398c2ecf20Sopenharmony_ci u16 val; 38408c2ecf20Sopenharmony_ci 38418c2ecf20Sopenharmony_ci *strength = 0; 38428c2ecf20Sopenharmony_ci for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) { 38438c2ecf20Sopenharmony_ci state->fe[index_frontend]->ops.read_signal_strength(state->fe[index_frontend], &val); 38448c2ecf20Sopenharmony_ci if (val > 65535 - *strength) 38458c2ecf20Sopenharmony_ci *strength = 65535; 38468c2ecf20Sopenharmony_ci else 38478c2ecf20Sopenharmony_ci *strength += val; 38488c2ecf20Sopenharmony_ci } 38498c2ecf20Sopenharmony_ci 38508c2ecf20Sopenharmony_ci val = 65535 - dib8000_read_word(state, 390); 38518c2ecf20Sopenharmony_ci if (val > 65535 - *strength) 38528c2ecf20Sopenharmony_ci *strength = 65535; 38538c2ecf20Sopenharmony_ci else 38548c2ecf20Sopenharmony_ci *strength += val; 38558c2ecf20Sopenharmony_ci return 0; 38568c2ecf20Sopenharmony_ci} 38578c2ecf20Sopenharmony_ci 38588c2ecf20Sopenharmony_cistatic u32 dib8000_get_snr(struct dvb_frontend *fe) 38598c2ecf20Sopenharmony_ci{ 38608c2ecf20Sopenharmony_ci struct dib8000_state *state = fe->demodulator_priv; 38618c2ecf20Sopenharmony_ci u32 n, s, exp; 38628c2ecf20Sopenharmony_ci u16 val; 38638c2ecf20Sopenharmony_ci 38648c2ecf20Sopenharmony_ci if (state->revision != 0x8090) 38658c2ecf20Sopenharmony_ci val = dib8000_read_word(state, 542); 38668c2ecf20Sopenharmony_ci else 38678c2ecf20Sopenharmony_ci val = dib8000_read_word(state, 544); 38688c2ecf20Sopenharmony_ci n = (val >> 6) & 0xff; 38698c2ecf20Sopenharmony_ci exp = (val & 0x3f); 38708c2ecf20Sopenharmony_ci if ((exp & 0x20) != 0) 38718c2ecf20Sopenharmony_ci exp -= 0x40; 38728c2ecf20Sopenharmony_ci n <<= exp+16; 38738c2ecf20Sopenharmony_ci 38748c2ecf20Sopenharmony_ci if (state->revision != 0x8090) 38758c2ecf20Sopenharmony_ci val = dib8000_read_word(state, 543); 38768c2ecf20Sopenharmony_ci else 38778c2ecf20Sopenharmony_ci val = dib8000_read_word(state, 545); 38788c2ecf20Sopenharmony_ci s = (val >> 6) & 0xff; 38798c2ecf20Sopenharmony_ci exp = (val & 0x3f); 38808c2ecf20Sopenharmony_ci if ((exp & 0x20) != 0) 38818c2ecf20Sopenharmony_ci exp -= 0x40; 38828c2ecf20Sopenharmony_ci s <<= exp+16; 38838c2ecf20Sopenharmony_ci 38848c2ecf20Sopenharmony_ci if (n > 0) { 38858c2ecf20Sopenharmony_ci u32 t = (s/n) << 16; 38868c2ecf20Sopenharmony_ci return t + ((s << 16) - n*t) / n; 38878c2ecf20Sopenharmony_ci } 38888c2ecf20Sopenharmony_ci return 0xffffffff; 38898c2ecf20Sopenharmony_ci} 38908c2ecf20Sopenharmony_ci 38918c2ecf20Sopenharmony_cistatic int dib8000_read_snr(struct dvb_frontend *fe, u16 * snr) 38928c2ecf20Sopenharmony_ci{ 38938c2ecf20Sopenharmony_ci struct dib8000_state *state = fe->demodulator_priv; 38948c2ecf20Sopenharmony_ci u8 index_frontend; 38958c2ecf20Sopenharmony_ci u32 snr_master; 38968c2ecf20Sopenharmony_ci 38978c2ecf20Sopenharmony_ci snr_master = dib8000_get_snr(fe); 38988c2ecf20Sopenharmony_ci for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) 38998c2ecf20Sopenharmony_ci snr_master += dib8000_get_snr(state->fe[index_frontend]); 39008c2ecf20Sopenharmony_ci 39018c2ecf20Sopenharmony_ci if ((snr_master >> 16) != 0) { 39028c2ecf20Sopenharmony_ci snr_master = 10*intlog10(snr_master>>16); 39038c2ecf20Sopenharmony_ci *snr = snr_master / ((1 << 24) / 10); 39048c2ecf20Sopenharmony_ci } 39058c2ecf20Sopenharmony_ci else 39068c2ecf20Sopenharmony_ci *snr = 0; 39078c2ecf20Sopenharmony_ci 39088c2ecf20Sopenharmony_ci return 0; 39098c2ecf20Sopenharmony_ci} 39108c2ecf20Sopenharmony_ci 39118c2ecf20Sopenharmony_cistruct per_layer_regs { 39128c2ecf20Sopenharmony_ci u16 lock, ber, per; 39138c2ecf20Sopenharmony_ci}; 39148c2ecf20Sopenharmony_ci 39158c2ecf20Sopenharmony_cistatic const struct per_layer_regs per_layer_regs[] = { 39168c2ecf20Sopenharmony_ci { 554, 560, 562 }, 39178c2ecf20Sopenharmony_ci { 555, 576, 578 }, 39188c2ecf20Sopenharmony_ci { 556, 581, 583 }, 39198c2ecf20Sopenharmony_ci}; 39208c2ecf20Sopenharmony_ci 39218c2ecf20Sopenharmony_cistruct linear_segments { 39228c2ecf20Sopenharmony_ci unsigned x; 39238c2ecf20Sopenharmony_ci signed y; 39248c2ecf20Sopenharmony_ci}; 39258c2ecf20Sopenharmony_ci 39268c2ecf20Sopenharmony_ci/* 39278c2ecf20Sopenharmony_ci * Table to estimate signal strength in dBm. 39288c2ecf20Sopenharmony_ci * This table was empirically determinated by measuring the signal 39298c2ecf20Sopenharmony_ci * strength generated by a DTA-2111 RF generator directly connected into 39308c2ecf20Sopenharmony_ci * a dib8076 device (a PixelView PV-D231U stick), using a good quality 39318c2ecf20Sopenharmony_ci * 3 meters RC6 cable and good RC6 connectors. 39328c2ecf20Sopenharmony_ci * The real value can actually be different on other devices, depending 39338c2ecf20Sopenharmony_ci * on several factors, like if LNA is enabled or not, if diversity is 39348c2ecf20Sopenharmony_ci * enabled, type of connectors, etc. 39358c2ecf20Sopenharmony_ci * Yet, it is better to use this measure in dB than a random non-linear 39368c2ecf20Sopenharmony_ci * percentage value, especially for antenna adjustments. 39378c2ecf20Sopenharmony_ci * On my tests, the precision of the measure using this table is about 39388c2ecf20Sopenharmony_ci * 0.5 dB, with sounds reasonable enough. 39398c2ecf20Sopenharmony_ci */ 39408c2ecf20Sopenharmony_cistatic struct linear_segments strength_to_db_table[] = { 39418c2ecf20Sopenharmony_ci { 55953, 108500 }, /* -22.5 dBm */ 39428c2ecf20Sopenharmony_ci { 55394, 108000 }, 39438c2ecf20Sopenharmony_ci { 53834, 107000 }, 39448c2ecf20Sopenharmony_ci { 52863, 106000 }, 39458c2ecf20Sopenharmony_ci { 52239, 105000 }, 39468c2ecf20Sopenharmony_ci { 52012, 104000 }, 39478c2ecf20Sopenharmony_ci { 51803, 103000 }, 39488c2ecf20Sopenharmony_ci { 51566, 102000 }, 39498c2ecf20Sopenharmony_ci { 51356, 101000 }, 39508c2ecf20Sopenharmony_ci { 51112, 100000 }, 39518c2ecf20Sopenharmony_ci { 50869, 99000 }, 39528c2ecf20Sopenharmony_ci { 50600, 98000 }, 39538c2ecf20Sopenharmony_ci { 50363, 97000 }, 39548c2ecf20Sopenharmony_ci { 50117, 96000 }, /* -35 dBm */ 39558c2ecf20Sopenharmony_ci { 49889, 95000 }, 39568c2ecf20Sopenharmony_ci { 49680, 94000 }, 39578c2ecf20Sopenharmony_ci { 49493, 93000 }, 39588c2ecf20Sopenharmony_ci { 49302, 92000 }, 39598c2ecf20Sopenharmony_ci { 48929, 91000 }, 39608c2ecf20Sopenharmony_ci { 48416, 90000 }, 39618c2ecf20Sopenharmony_ci { 48035, 89000 }, 39628c2ecf20Sopenharmony_ci { 47593, 88000 }, 39638c2ecf20Sopenharmony_ci { 47282, 87000 }, 39648c2ecf20Sopenharmony_ci { 46953, 86000 }, 39658c2ecf20Sopenharmony_ci { 46698, 85000 }, 39668c2ecf20Sopenharmony_ci { 45617, 84000 }, 39678c2ecf20Sopenharmony_ci { 44773, 83000 }, 39688c2ecf20Sopenharmony_ci { 43845, 82000 }, 39698c2ecf20Sopenharmony_ci { 43020, 81000 }, 39708c2ecf20Sopenharmony_ci { 42010, 80000 }, /* -51 dBm */ 39718c2ecf20Sopenharmony_ci { 0, 0 }, 39728c2ecf20Sopenharmony_ci}; 39738c2ecf20Sopenharmony_ci 39748c2ecf20Sopenharmony_cistatic u32 interpolate_value(u32 value, struct linear_segments *segments, 39758c2ecf20Sopenharmony_ci unsigned len) 39768c2ecf20Sopenharmony_ci{ 39778c2ecf20Sopenharmony_ci u64 tmp64; 39788c2ecf20Sopenharmony_ci u32 dx; 39798c2ecf20Sopenharmony_ci s32 dy; 39808c2ecf20Sopenharmony_ci int i, ret; 39818c2ecf20Sopenharmony_ci 39828c2ecf20Sopenharmony_ci if (value >= segments[0].x) 39838c2ecf20Sopenharmony_ci return segments[0].y; 39848c2ecf20Sopenharmony_ci if (value < segments[len-1].x) 39858c2ecf20Sopenharmony_ci return segments[len-1].y; 39868c2ecf20Sopenharmony_ci 39878c2ecf20Sopenharmony_ci for (i = 1; i < len - 1; i++) { 39888c2ecf20Sopenharmony_ci /* If value is identical, no need to interpolate */ 39898c2ecf20Sopenharmony_ci if (value == segments[i].x) 39908c2ecf20Sopenharmony_ci return segments[i].y; 39918c2ecf20Sopenharmony_ci if (value > segments[i].x) 39928c2ecf20Sopenharmony_ci break; 39938c2ecf20Sopenharmony_ci } 39948c2ecf20Sopenharmony_ci 39958c2ecf20Sopenharmony_ci /* Linear interpolation between the two (x,y) points */ 39968c2ecf20Sopenharmony_ci dy = segments[i - 1].y - segments[i].y; 39978c2ecf20Sopenharmony_ci dx = segments[i - 1].x - segments[i].x; 39988c2ecf20Sopenharmony_ci 39998c2ecf20Sopenharmony_ci tmp64 = value - segments[i].x; 40008c2ecf20Sopenharmony_ci tmp64 *= dy; 40018c2ecf20Sopenharmony_ci do_div(tmp64, dx); 40028c2ecf20Sopenharmony_ci ret = segments[i].y + tmp64; 40038c2ecf20Sopenharmony_ci 40048c2ecf20Sopenharmony_ci return ret; 40058c2ecf20Sopenharmony_ci} 40068c2ecf20Sopenharmony_ci 40078c2ecf20Sopenharmony_cistatic u32 dib8000_get_time_us(struct dvb_frontend *fe, int layer) 40088c2ecf20Sopenharmony_ci{ 40098c2ecf20Sopenharmony_ci struct dib8000_state *state = fe->demodulator_priv; 40108c2ecf20Sopenharmony_ci struct dtv_frontend_properties *c = &state->fe[0]->dtv_property_cache; 40118c2ecf20Sopenharmony_ci int ini_layer, end_layer, i; 40128c2ecf20Sopenharmony_ci u64 time_us, tmp64; 40138c2ecf20Sopenharmony_ci u32 tmp, denom; 40148c2ecf20Sopenharmony_ci int guard, rate_num, rate_denum = 1, bits_per_symbol, nsegs; 40158c2ecf20Sopenharmony_ci int interleaving = 0, fft_div; 40168c2ecf20Sopenharmony_ci 40178c2ecf20Sopenharmony_ci if (layer >= 0) { 40188c2ecf20Sopenharmony_ci ini_layer = layer; 40198c2ecf20Sopenharmony_ci end_layer = layer + 1; 40208c2ecf20Sopenharmony_ci } else { 40218c2ecf20Sopenharmony_ci ini_layer = 0; 40228c2ecf20Sopenharmony_ci end_layer = 3; 40238c2ecf20Sopenharmony_ci } 40248c2ecf20Sopenharmony_ci 40258c2ecf20Sopenharmony_ci switch (c->guard_interval) { 40268c2ecf20Sopenharmony_ci case GUARD_INTERVAL_1_4: 40278c2ecf20Sopenharmony_ci guard = 4; 40288c2ecf20Sopenharmony_ci break; 40298c2ecf20Sopenharmony_ci case GUARD_INTERVAL_1_8: 40308c2ecf20Sopenharmony_ci guard = 8; 40318c2ecf20Sopenharmony_ci break; 40328c2ecf20Sopenharmony_ci case GUARD_INTERVAL_1_16: 40338c2ecf20Sopenharmony_ci guard = 16; 40348c2ecf20Sopenharmony_ci break; 40358c2ecf20Sopenharmony_ci default: 40368c2ecf20Sopenharmony_ci case GUARD_INTERVAL_1_32: 40378c2ecf20Sopenharmony_ci guard = 32; 40388c2ecf20Sopenharmony_ci break; 40398c2ecf20Sopenharmony_ci } 40408c2ecf20Sopenharmony_ci 40418c2ecf20Sopenharmony_ci switch (c->transmission_mode) { 40428c2ecf20Sopenharmony_ci case TRANSMISSION_MODE_2K: 40438c2ecf20Sopenharmony_ci fft_div = 4; 40448c2ecf20Sopenharmony_ci break; 40458c2ecf20Sopenharmony_ci case TRANSMISSION_MODE_4K: 40468c2ecf20Sopenharmony_ci fft_div = 2; 40478c2ecf20Sopenharmony_ci break; 40488c2ecf20Sopenharmony_ci default: 40498c2ecf20Sopenharmony_ci case TRANSMISSION_MODE_8K: 40508c2ecf20Sopenharmony_ci fft_div = 1; 40518c2ecf20Sopenharmony_ci break; 40528c2ecf20Sopenharmony_ci } 40538c2ecf20Sopenharmony_ci 40548c2ecf20Sopenharmony_ci denom = 0; 40558c2ecf20Sopenharmony_ci for (i = ini_layer; i < end_layer; i++) { 40568c2ecf20Sopenharmony_ci nsegs = c->layer[i].segment_count; 40578c2ecf20Sopenharmony_ci if (nsegs == 0 || nsegs > 13) 40588c2ecf20Sopenharmony_ci continue; 40598c2ecf20Sopenharmony_ci 40608c2ecf20Sopenharmony_ci switch (c->layer[i].modulation) { 40618c2ecf20Sopenharmony_ci case DQPSK: 40628c2ecf20Sopenharmony_ci case QPSK: 40638c2ecf20Sopenharmony_ci bits_per_symbol = 2; 40648c2ecf20Sopenharmony_ci break; 40658c2ecf20Sopenharmony_ci case QAM_16: 40668c2ecf20Sopenharmony_ci bits_per_symbol = 4; 40678c2ecf20Sopenharmony_ci break; 40688c2ecf20Sopenharmony_ci default: 40698c2ecf20Sopenharmony_ci case QAM_64: 40708c2ecf20Sopenharmony_ci bits_per_symbol = 6; 40718c2ecf20Sopenharmony_ci break; 40728c2ecf20Sopenharmony_ci } 40738c2ecf20Sopenharmony_ci 40748c2ecf20Sopenharmony_ci switch (c->layer[i].fec) { 40758c2ecf20Sopenharmony_ci case FEC_1_2: 40768c2ecf20Sopenharmony_ci rate_num = 1; 40778c2ecf20Sopenharmony_ci rate_denum = 2; 40788c2ecf20Sopenharmony_ci break; 40798c2ecf20Sopenharmony_ci case FEC_2_3: 40808c2ecf20Sopenharmony_ci rate_num = 2; 40818c2ecf20Sopenharmony_ci rate_denum = 3; 40828c2ecf20Sopenharmony_ci break; 40838c2ecf20Sopenharmony_ci case FEC_3_4: 40848c2ecf20Sopenharmony_ci rate_num = 3; 40858c2ecf20Sopenharmony_ci rate_denum = 4; 40868c2ecf20Sopenharmony_ci break; 40878c2ecf20Sopenharmony_ci case FEC_5_6: 40888c2ecf20Sopenharmony_ci rate_num = 5; 40898c2ecf20Sopenharmony_ci rate_denum = 6; 40908c2ecf20Sopenharmony_ci break; 40918c2ecf20Sopenharmony_ci default: 40928c2ecf20Sopenharmony_ci case FEC_7_8: 40938c2ecf20Sopenharmony_ci rate_num = 7; 40948c2ecf20Sopenharmony_ci rate_denum = 8; 40958c2ecf20Sopenharmony_ci break; 40968c2ecf20Sopenharmony_ci } 40978c2ecf20Sopenharmony_ci 40988c2ecf20Sopenharmony_ci interleaving = c->layer[i].interleaving; 40998c2ecf20Sopenharmony_ci 41008c2ecf20Sopenharmony_ci denom += bits_per_symbol * rate_num * fft_div * nsegs * 384; 41018c2ecf20Sopenharmony_ci } 41028c2ecf20Sopenharmony_ci 41038c2ecf20Sopenharmony_ci /* If all goes wrong, wait for 1s for the next stats */ 41048c2ecf20Sopenharmony_ci if (!denom) 41058c2ecf20Sopenharmony_ci return 0; 41068c2ecf20Sopenharmony_ci 41078c2ecf20Sopenharmony_ci /* Estimate the period for the total bit rate */ 41088c2ecf20Sopenharmony_ci time_us = rate_denum * (1008 * 1562500L); 41098c2ecf20Sopenharmony_ci tmp64 = time_us; 41108c2ecf20Sopenharmony_ci do_div(tmp64, guard); 41118c2ecf20Sopenharmony_ci time_us = time_us + tmp64; 41128c2ecf20Sopenharmony_ci time_us += denom / 2; 41138c2ecf20Sopenharmony_ci do_div(time_us, denom); 41148c2ecf20Sopenharmony_ci 41158c2ecf20Sopenharmony_ci tmp = 1008 * 96 * interleaving; 41168c2ecf20Sopenharmony_ci time_us += tmp + tmp / guard; 41178c2ecf20Sopenharmony_ci 41188c2ecf20Sopenharmony_ci return time_us; 41198c2ecf20Sopenharmony_ci} 41208c2ecf20Sopenharmony_ci 41218c2ecf20Sopenharmony_cistatic int dib8000_get_stats(struct dvb_frontend *fe, enum fe_status stat) 41228c2ecf20Sopenharmony_ci{ 41238c2ecf20Sopenharmony_ci struct dib8000_state *state = fe->demodulator_priv; 41248c2ecf20Sopenharmony_ci struct dtv_frontend_properties *c = &state->fe[0]->dtv_property_cache; 41258c2ecf20Sopenharmony_ci int i; 41268c2ecf20Sopenharmony_ci int show_per_stats = 0; 41278c2ecf20Sopenharmony_ci u32 time_us = 0, snr, val; 41288c2ecf20Sopenharmony_ci u64 blocks; 41298c2ecf20Sopenharmony_ci s32 db; 41308c2ecf20Sopenharmony_ci u16 strength; 41318c2ecf20Sopenharmony_ci 41328c2ecf20Sopenharmony_ci /* Get Signal strength */ 41338c2ecf20Sopenharmony_ci dib8000_read_signal_strength(fe, &strength); 41348c2ecf20Sopenharmony_ci val = strength; 41358c2ecf20Sopenharmony_ci db = interpolate_value(val, 41368c2ecf20Sopenharmony_ci strength_to_db_table, 41378c2ecf20Sopenharmony_ci ARRAY_SIZE(strength_to_db_table)) - 131000; 41388c2ecf20Sopenharmony_ci c->strength.stat[0].svalue = db; 41398c2ecf20Sopenharmony_ci 41408c2ecf20Sopenharmony_ci /* UCB/BER/CNR measures require lock */ 41418c2ecf20Sopenharmony_ci if (!(stat & FE_HAS_LOCK)) { 41428c2ecf20Sopenharmony_ci c->cnr.len = 1; 41438c2ecf20Sopenharmony_ci c->block_count.len = 1; 41448c2ecf20Sopenharmony_ci c->block_error.len = 1; 41458c2ecf20Sopenharmony_ci c->post_bit_error.len = 1; 41468c2ecf20Sopenharmony_ci c->post_bit_count.len = 1; 41478c2ecf20Sopenharmony_ci c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 41488c2ecf20Sopenharmony_ci c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 41498c2ecf20Sopenharmony_ci c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 41508c2ecf20Sopenharmony_ci c->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 41518c2ecf20Sopenharmony_ci c->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 41528c2ecf20Sopenharmony_ci return 0; 41538c2ecf20Sopenharmony_ci } 41548c2ecf20Sopenharmony_ci 41558c2ecf20Sopenharmony_ci /* Check if time for stats was elapsed */ 41568c2ecf20Sopenharmony_ci if (time_after(jiffies, state->per_jiffies_stats)) { 41578c2ecf20Sopenharmony_ci state->per_jiffies_stats = jiffies + msecs_to_jiffies(1000); 41588c2ecf20Sopenharmony_ci 41598c2ecf20Sopenharmony_ci /* Get SNR */ 41608c2ecf20Sopenharmony_ci snr = dib8000_get_snr(fe); 41618c2ecf20Sopenharmony_ci for (i = 1; i < MAX_NUMBER_OF_FRONTENDS; i++) { 41628c2ecf20Sopenharmony_ci if (state->fe[i]) 41638c2ecf20Sopenharmony_ci snr += dib8000_get_snr(state->fe[i]); 41648c2ecf20Sopenharmony_ci } 41658c2ecf20Sopenharmony_ci snr = snr >> 16; 41668c2ecf20Sopenharmony_ci 41678c2ecf20Sopenharmony_ci if (snr) { 41688c2ecf20Sopenharmony_ci snr = 10 * intlog10(snr); 41698c2ecf20Sopenharmony_ci snr = (1000L * snr) >> 24; 41708c2ecf20Sopenharmony_ci } else { 41718c2ecf20Sopenharmony_ci snr = 0; 41728c2ecf20Sopenharmony_ci } 41738c2ecf20Sopenharmony_ci c->cnr.stat[0].svalue = snr; 41748c2ecf20Sopenharmony_ci c->cnr.stat[0].scale = FE_SCALE_DECIBEL; 41758c2ecf20Sopenharmony_ci 41768c2ecf20Sopenharmony_ci /* Get UCB measures */ 41778c2ecf20Sopenharmony_ci dib8000_read_unc_blocks(fe, &val); 41788c2ecf20Sopenharmony_ci if (val < state->init_ucb) 41798c2ecf20Sopenharmony_ci state->init_ucb += 0x100000000LL; 41808c2ecf20Sopenharmony_ci 41818c2ecf20Sopenharmony_ci c->block_error.stat[0].scale = FE_SCALE_COUNTER; 41828c2ecf20Sopenharmony_ci c->block_error.stat[0].uvalue = val + state->init_ucb; 41838c2ecf20Sopenharmony_ci 41848c2ecf20Sopenharmony_ci /* Estimate the number of packets based on bitrate */ 41858c2ecf20Sopenharmony_ci if (!time_us) 41868c2ecf20Sopenharmony_ci time_us = dib8000_get_time_us(fe, -1); 41878c2ecf20Sopenharmony_ci 41888c2ecf20Sopenharmony_ci if (time_us) { 41898c2ecf20Sopenharmony_ci blocks = 1250000ULL * 1000000ULL; 41908c2ecf20Sopenharmony_ci do_div(blocks, time_us * 8 * 204); 41918c2ecf20Sopenharmony_ci c->block_count.stat[0].scale = FE_SCALE_COUNTER; 41928c2ecf20Sopenharmony_ci c->block_count.stat[0].uvalue += blocks; 41938c2ecf20Sopenharmony_ci } 41948c2ecf20Sopenharmony_ci 41958c2ecf20Sopenharmony_ci show_per_stats = 1; 41968c2ecf20Sopenharmony_ci } 41978c2ecf20Sopenharmony_ci 41988c2ecf20Sopenharmony_ci /* Get post-BER measures */ 41998c2ecf20Sopenharmony_ci if (time_after(jiffies, state->ber_jiffies_stats)) { 42008c2ecf20Sopenharmony_ci time_us = dib8000_get_time_us(fe, -1); 42018c2ecf20Sopenharmony_ci state->ber_jiffies_stats = jiffies + msecs_to_jiffies((time_us + 500) / 1000); 42028c2ecf20Sopenharmony_ci 42038c2ecf20Sopenharmony_ci dprintk("Next all layers stats available in %u us.\n", time_us); 42048c2ecf20Sopenharmony_ci 42058c2ecf20Sopenharmony_ci dib8000_read_ber(fe, &val); 42068c2ecf20Sopenharmony_ci c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER; 42078c2ecf20Sopenharmony_ci c->post_bit_error.stat[0].uvalue += val; 42088c2ecf20Sopenharmony_ci 42098c2ecf20Sopenharmony_ci c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER; 42108c2ecf20Sopenharmony_ci c->post_bit_count.stat[0].uvalue += 100000000; 42118c2ecf20Sopenharmony_ci } 42128c2ecf20Sopenharmony_ci 42138c2ecf20Sopenharmony_ci if (state->revision < 0x8002) 42148c2ecf20Sopenharmony_ci return 0; 42158c2ecf20Sopenharmony_ci 42168c2ecf20Sopenharmony_ci c->block_error.len = 4; 42178c2ecf20Sopenharmony_ci c->post_bit_error.len = 4; 42188c2ecf20Sopenharmony_ci c->post_bit_count.len = 4; 42198c2ecf20Sopenharmony_ci 42208c2ecf20Sopenharmony_ci for (i = 0; i < 3; i++) { 42218c2ecf20Sopenharmony_ci unsigned nsegs = c->layer[i].segment_count; 42228c2ecf20Sopenharmony_ci 42238c2ecf20Sopenharmony_ci if (nsegs == 0 || nsegs > 13) 42248c2ecf20Sopenharmony_ci continue; 42258c2ecf20Sopenharmony_ci 42268c2ecf20Sopenharmony_ci time_us = 0; 42278c2ecf20Sopenharmony_ci 42288c2ecf20Sopenharmony_ci if (time_after(jiffies, state->ber_jiffies_stats_layer[i])) { 42298c2ecf20Sopenharmony_ci time_us = dib8000_get_time_us(fe, i); 42308c2ecf20Sopenharmony_ci 42318c2ecf20Sopenharmony_ci state->ber_jiffies_stats_layer[i] = jiffies + msecs_to_jiffies((time_us + 500) / 1000); 42328c2ecf20Sopenharmony_ci dprintk("Next layer %c stats will be available in %u us\n", 42338c2ecf20Sopenharmony_ci 'A' + i, time_us); 42348c2ecf20Sopenharmony_ci 42358c2ecf20Sopenharmony_ci val = dib8000_read_word(state, per_layer_regs[i].ber); 42368c2ecf20Sopenharmony_ci c->post_bit_error.stat[1 + i].scale = FE_SCALE_COUNTER; 42378c2ecf20Sopenharmony_ci c->post_bit_error.stat[1 + i].uvalue += val; 42388c2ecf20Sopenharmony_ci 42398c2ecf20Sopenharmony_ci c->post_bit_count.stat[1 + i].scale = FE_SCALE_COUNTER; 42408c2ecf20Sopenharmony_ci c->post_bit_count.stat[1 + i].uvalue += 100000000; 42418c2ecf20Sopenharmony_ci } 42428c2ecf20Sopenharmony_ci 42438c2ecf20Sopenharmony_ci if (show_per_stats) { 42448c2ecf20Sopenharmony_ci val = dib8000_read_word(state, per_layer_regs[i].per); 42458c2ecf20Sopenharmony_ci 42468c2ecf20Sopenharmony_ci c->block_error.stat[1 + i].scale = FE_SCALE_COUNTER; 42478c2ecf20Sopenharmony_ci c->block_error.stat[1 + i].uvalue += val; 42488c2ecf20Sopenharmony_ci 42498c2ecf20Sopenharmony_ci if (!time_us) 42508c2ecf20Sopenharmony_ci time_us = dib8000_get_time_us(fe, i); 42518c2ecf20Sopenharmony_ci if (time_us) { 42528c2ecf20Sopenharmony_ci blocks = 1250000ULL * 1000000ULL; 42538c2ecf20Sopenharmony_ci do_div(blocks, time_us * 8 * 204); 42548c2ecf20Sopenharmony_ci c->block_count.stat[0].scale = FE_SCALE_COUNTER; 42558c2ecf20Sopenharmony_ci c->block_count.stat[0].uvalue += blocks; 42568c2ecf20Sopenharmony_ci } 42578c2ecf20Sopenharmony_ci } 42588c2ecf20Sopenharmony_ci } 42598c2ecf20Sopenharmony_ci return 0; 42608c2ecf20Sopenharmony_ci} 42618c2ecf20Sopenharmony_ci 42628c2ecf20Sopenharmony_cistatic int dib8000_set_slave_frontend(struct dvb_frontend *fe, struct dvb_frontend *fe_slave) 42638c2ecf20Sopenharmony_ci{ 42648c2ecf20Sopenharmony_ci struct dib8000_state *state = fe->demodulator_priv; 42658c2ecf20Sopenharmony_ci u8 index_frontend = 1; 42668c2ecf20Sopenharmony_ci 42678c2ecf20Sopenharmony_ci while ((index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL)) 42688c2ecf20Sopenharmony_ci index_frontend++; 42698c2ecf20Sopenharmony_ci if (index_frontend < MAX_NUMBER_OF_FRONTENDS) { 42708c2ecf20Sopenharmony_ci dprintk("set slave fe %p to index %i\n", fe_slave, index_frontend); 42718c2ecf20Sopenharmony_ci state->fe[index_frontend] = fe_slave; 42728c2ecf20Sopenharmony_ci return 0; 42738c2ecf20Sopenharmony_ci } 42748c2ecf20Sopenharmony_ci 42758c2ecf20Sopenharmony_ci dprintk("too many slave frontend\n"); 42768c2ecf20Sopenharmony_ci return -ENOMEM; 42778c2ecf20Sopenharmony_ci} 42788c2ecf20Sopenharmony_ci 42798c2ecf20Sopenharmony_cistatic struct dvb_frontend *dib8000_get_slave_frontend(struct dvb_frontend *fe, int slave_index) 42808c2ecf20Sopenharmony_ci{ 42818c2ecf20Sopenharmony_ci struct dib8000_state *state = fe->demodulator_priv; 42828c2ecf20Sopenharmony_ci 42838c2ecf20Sopenharmony_ci if (slave_index >= MAX_NUMBER_OF_FRONTENDS) 42848c2ecf20Sopenharmony_ci return NULL; 42858c2ecf20Sopenharmony_ci return state->fe[slave_index]; 42868c2ecf20Sopenharmony_ci} 42878c2ecf20Sopenharmony_ci 42888c2ecf20Sopenharmony_cistatic int dib8000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods, 42898c2ecf20Sopenharmony_ci u8 default_addr, u8 first_addr, u8 is_dib8096p) 42908c2ecf20Sopenharmony_ci{ 42918c2ecf20Sopenharmony_ci int k = 0, ret = 0; 42928c2ecf20Sopenharmony_ci u8 new_addr = 0; 42938c2ecf20Sopenharmony_ci struct i2c_device client = {.adap = host }; 42948c2ecf20Sopenharmony_ci 42958c2ecf20Sopenharmony_ci client.i2c_write_buffer = kzalloc(4, GFP_KERNEL); 42968c2ecf20Sopenharmony_ci if (!client.i2c_write_buffer) { 42978c2ecf20Sopenharmony_ci dprintk("%s: not enough memory\n", __func__); 42988c2ecf20Sopenharmony_ci return -ENOMEM; 42998c2ecf20Sopenharmony_ci } 43008c2ecf20Sopenharmony_ci client.i2c_read_buffer = kzalloc(4, GFP_KERNEL); 43018c2ecf20Sopenharmony_ci if (!client.i2c_read_buffer) { 43028c2ecf20Sopenharmony_ci dprintk("%s: not enough memory\n", __func__); 43038c2ecf20Sopenharmony_ci ret = -ENOMEM; 43048c2ecf20Sopenharmony_ci goto error_memory_read; 43058c2ecf20Sopenharmony_ci } 43068c2ecf20Sopenharmony_ci client.i2c_buffer_lock = kzalloc(sizeof(struct mutex), GFP_KERNEL); 43078c2ecf20Sopenharmony_ci if (!client.i2c_buffer_lock) { 43088c2ecf20Sopenharmony_ci dprintk("%s: not enough memory\n", __func__); 43098c2ecf20Sopenharmony_ci ret = -ENOMEM; 43108c2ecf20Sopenharmony_ci goto error_memory_lock; 43118c2ecf20Sopenharmony_ci } 43128c2ecf20Sopenharmony_ci mutex_init(client.i2c_buffer_lock); 43138c2ecf20Sopenharmony_ci 43148c2ecf20Sopenharmony_ci for (k = no_of_demods - 1; k >= 0; k--) { 43158c2ecf20Sopenharmony_ci /* designated i2c address */ 43168c2ecf20Sopenharmony_ci new_addr = first_addr + (k << 1); 43178c2ecf20Sopenharmony_ci 43188c2ecf20Sopenharmony_ci client.addr = new_addr; 43198c2ecf20Sopenharmony_ci if (!is_dib8096p) 43208c2ecf20Sopenharmony_ci dib8000_i2c_write16(&client, 1287, 0x0003); /* sram lead in, rdy */ 43218c2ecf20Sopenharmony_ci if (dib8000_identify(&client) == 0) { 43228c2ecf20Sopenharmony_ci /* sram lead in, rdy */ 43238c2ecf20Sopenharmony_ci if (!is_dib8096p) 43248c2ecf20Sopenharmony_ci dib8000_i2c_write16(&client, 1287, 0x0003); 43258c2ecf20Sopenharmony_ci client.addr = default_addr; 43268c2ecf20Sopenharmony_ci if (dib8000_identify(&client) == 0) { 43278c2ecf20Sopenharmony_ci dprintk("#%d: not identified\n", k); 43288c2ecf20Sopenharmony_ci ret = -EINVAL; 43298c2ecf20Sopenharmony_ci goto error; 43308c2ecf20Sopenharmony_ci } 43318c2ecf20Sopenharmony_ci } 43328c2ecf20Sopenharmony_ci 43338c2ecf20Sopenharmony_ci /* start diversity to pull_down div_str - just for i2c-enumeration */ 43348c2ecf20Sopenharmony_ci dib8000_i2c_write16(&client, 1286, (1 << 10) | (4 << 6)); 43358c2ecf20Sopenharmony_ci 43368c2ecf20Sopenharmony_ci /* set new i2c address and force divstart */ 43378c2ecf20Sopenharmony_ci dib8000_i2c_write16(&client, 1285, (new_addr << 2) | 0x2); 43388c2ecf20Sopenharmony_ci client.addr = new_addr; 43398c2ecf20Sopenharmony_ci dib8000_identify(&client); 43408c2ecf20Sopenharmony_ci 43418c2ecf20Sopenharmony_ci dprintk("IC %d initialized (to i2c_address 0x%x)\n", k, new_addr); 43428c2ecf20Sopenharmony_ci } 43438c2ecf20Sopenharmony_ci 43448c2ecf20Sopenharmony_ci for (k = 0; k < no_of_demods; k++) { 43458c2ecf20Sopenharmony_ci new_addr = first_addr | (k << 1); 43468c2ecf20Sopenharmony_ci client.addr = new_addr; 43478c2ecf20Sopenharmony_ci 43488c2ecf20Sopenharmony_ci // unforce divstr 43498c2ecf20Sopenharmony_ci dib8000_i2c_write16(&client, 1285, new_addr << 2); 43508c2ecf20Sopenharmony_ci 43518c2ecf20Sopenharmony_ci /* deactivate div - it was just for i2c-enumeration */ 43528c2ecf20Sopenharmony_ci dib8000_i2c_write16(&client, 1286, 0); 43538c2ecf20Sopenharmony_ci } 43548c2ecf20Sopenharmony_ci 43558c2ecf20Sopenharmony_cierror: 43568c2ecf20Sopenharmony_ci kfree(client.i2c_buffer_lock); 43578c2ecf20Sopenharmony_cierror_memory_lock: 43588c2ecf20Sopenharmony_ci kfree(client.i2c_read_buffer); 43598c2ecf20Sopenharmony_cierror_memory_read: 43608c2ecf20Sopenharmony_ci kfree(client.i2c_write_buffer); 43618c2ecf20Sopenharmony_ci 43628c2ecf20Sopenharmony_ci return ret; 43638c2ecf20Sopenharmony_ci} 43648c2ecf20Sopenharmony_ci 43658c2ecf20Sopenharmony_cistatic int dib8000_fe_get_tune_settings(struct dvb_frontend *fe, struct dvb_frontend_tune_settings *tune) 43668c2ecf20Sopenharmony_ci{ 43678c2ecf20Sopenharmony_ci tune->min_delay_ms = 1000; 43688c2ecf20Sopenharmony_ci tune->step_size = 0; 43698c2ecf20Sopenharmony_ci tune->max_drift = 0; 43708c2ecf20Sopenharmony_ci return 0; 43718c2ecf20Sopenharmony_ci} 43728c2ecf20Sopenharmony_ci 43738c2ecf20Sopenharmony_cistatic void dib8000_release(struct dvb_frontend *fe) 43748c2ecf20Sopenharmony_ci{ 43758c2ecf20Sopenharmony_ci struct dib8000_state *st = fe->demodulator_priv; 43768c2ecf20Sopenharmony_ci u8 index_frontend; 43778c2ecf20Sopenharmony_ci 43788c2ecf20Sopenharmony_ci for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (st->fe[index_frontend] != NULL); index_frontend++) 43798c2ecf20Sopenharmony_ci dvb_frontend_detach(st->fe[index_frontend]); 43808c2ecf20Sopenharmony_ci 43818c2ecf20Sopenharmony_ci dibx000_exit_i2c_master(&st->i2c_master); 43828c2ecf20Sopenharmony_ci i2c_del_adapter(&st->dib8096p_tuner_adap); 43838c2ecf20Sopenharmony_ci kfree(st->fe[0]); 43848c2ecf20Sopenharmony_ci kfree(st); 43858c2ecf20Sopenharmony_ci} 43868c2ecf20Sopenharmony_ci 43878c2ecf20Sopenharmony_cistatic struct i2c_adapter *dib8000_get_i2c_master(struct dvb_frontend *fe, enum dibx000_i2c_interface intf, int gating) 43888c2ecf20Sopenharmony_ci{ 43898c2ecf20Sopenharmony_ci struct dib8000_state *st = fe->demodulator_priv; 43908c2ecf20Sopenharmony_ci return dibx000_get_i2c_adapter(&st->i2c_master, intf, gating); 43918c2ecf20Sopenharmony_ci} 43928c2ecf20Sopenharmony_ci 43938c2ecf20Sopenharmony_cistatic int dib8000_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff) 43948c2ecf20Sopenharmony_ci{ 43958c2ecf20Sopenharmony_ci struct dib8000_state *st = fe->demodulator_priv; 43968c2ecf20Sopenharmony_ci u16 val = dib8000_read_word(st, 299) & 0xffef; 43978c2ecf20Sopenharmony_ci val |= (onoff & 0x1) << 4; 43988c2ecf20Sopenharmony_ci 43998c2ecf20Sopenharmony_ci dprintk("pid filter enabled %d\n", onoff); 44008c2ecf20Sopenharmony_ci return dib8000_write_word(st, 299, val); 44018c2ecf20Sopenharmony_ci} 44028c2ecf20Sopenharmony_ci 44038c2ecf20Sopenharmony_cistatic int dib8000_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff) 44048c2ecf20Sopenharmony_ci{ 44058c2ecf20Sopenharmony_ci struct dib8000_state *st = fe->demodulator_priv; 44068c2ecf20Sopenharmony_ci dprintk("Index %x, PID %d, OnOff %d\n", id, pid, onoff); 44078c2ecf20Sopenharmony_ci return dib8000_write_word(st, 305 + id, onoff ? (1 << 13) | pid : 0); 44088c2ecf20Sopenharmony_ci} 44098c2ecf20Sopenharmony_ci 44108c2ecf20Sopenharmony_cistatic const struct dvb_frontend_ops dib8000_ops = { 44118c2ecf20Sopenharmony_ci .delsys = { SYS_ISDBT }, 44128c2ecf20Sopenharmony_ci .info = { 44138c2ecf20Sopenharmony_ci .name = "DiBcom 8000 ISDB-T", 44148c2ecf20Sopenharmony_ci .frequency_min_hz = 44250 * kHz, 44158c2ecf20Sopenharmony_ci .frequency_max_hz = 867250 * kHz, 44168c2ecf20Sopenharmony_ci .frequency_stepsize_hz = 62500, 44178c2ecf20Sopenharmony_ci .caps = FE_CAN_INVERSION_AUTO | 44188c2ecf20Sopenharmony_ci FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | 44198c2ecf20Sopenharmony_ci FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | 44208c2ecf20Sopenharmony_ci FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | 44218c2ecf20Sopenharmony_ci FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_RECOVER | FE_CAN_HIERARCHY_AUTO, 44228c2ecf20Sopenharmony_ci }, 44238c2ecf20Sopenharmony_ci 44248c2ecf20Sopenharmony_ci .release = dib8000_release, 44258c2ecf20Sopenharmony_ci 44268c2ecf20Sopenharmony_ci .init = dib8000_wakeup, 44278c2ecf20Sopenharmony_ci .sleep = dib8000_sleep, 44288c2ecf20Sopenharmony_ci 44298c2ecf20Sopenharmony_ci .set_frontend = dib8000_set_frontend, 44308c2ecf20Sopenharmony_ci .get_tune_settings = dib8000_fe_get_tune_settings, 44318c2ecf20Sopenharmony_ci .get_frontend = dib8000_get_frontend, 44328c2ecf20Sopenharmony_ci 44338c2ecf20Sopenharmony_ci .read_status = dib8000_read_status, 44348c2ecf20Sopenharmony_ci .read_ber = dib8000_read_ber, 44358c2ecf20Sopenharmony_ci .read_signal_strength = dib8000_read_signal_strength, 44368c2ecf20Sopenharmony_ci .read_snr = dib8000_read_snr, 44378c2ecf20Sopenharmony_ci .read_ucblocks = dib8000_read_unc_blocks, 44388c2ecf20Sopenharmony_ci}; 44398c2ecf20Sopenharmony_ci 44408c2ecf20Sopenharmony_cistatic struct dvb_frontend *dib8000_init(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib8000_config *cfg) 44418c2ecf20Sopenharmony_ci{ 44428c2ecf20Sopenharmony_ci struct dvb_frontend *fe; 44438c2ecf20Sopenharmony_ci struct dib8000_state *state; 44448c2ecf20Sopenharmony_ci 44458c2ecf20Sopenharmony_ci dprintk("dib8000_init\n"); 44468c2ecf20Sopenharmony_ci 44478c2ecf20Sopenharmony_ci state = kzalloc(sizeof(struct dib8000_state), GFP_KERNEL); 44488c2ecf20Sopenharmony_ci if (state == NULL) 44498c2ecf20Sopenharmony_ci return NULL; 44508c2ecf20Sopenharmony_ci fe = kzalloc(sizeof(struct dvb_frontend), GFP_KERNEL); 44518c2ecf20Sopenharmony_ci if (fe == NULL) 44528c2ecf20Sopenharmony_ci goto error; 44538c2ecf20Sopenharmony_ci 44548c2ecf20Sopenharmony_ci memcpy(&state->cfg, cfg, sizeof(struct dib8000_config)); 44558c2ecf20Sopenharmony_ci state->i2c.adap = i2c_adap; 44568c2ecf20Sopenharmony_ci state->i2c.addr = i2c_addr; 44578c2ecf20Sopenharmony_ci state->i2c.i2c_write_buffer = state->i2c_write_buffer; 44588c2ecf20Sopenharmony_ci state->i2c.i2c_read_buffer = state->i2c_read_buffer; 44598c2ecf20Sopenharmony_ci mutex_init(&state->i2c_buffer_lock); 44608c2ecf20Sopenharmony_ci state->i2c.i2c_buffer_lock = &state->i2c_buffer_lock; 44618c2ecf20Sopenharmony_ci state->gpio_val = cfg->gpio_val; 44628c2ecf20Sopenharmony_ci state->gpio_dir = cfg->gpio_dir; 44638c2ecf20Sopenharmony_ci 44648c2ecf20Sopenharmony_ci /* Ensure the output mode remains at the previous default if it's 44658c2ecf20Sopenharmony_ci * not specifically set by the caller. 44668c2ecf20Sopenharmony_ci */ 44678c2ecf20Sopenharmony_ci if ((state->cfg.output_mode != OUTMODE_MPEG2_SERIAL) && (state->cfg.output_mode != OUTMODE_MPEG2_PAR_GATED_CLK)) 44688c2ecf20Sopenharmony_ci state->cfg.output_mode = OUTMODE_MPEG2_FIFO; 44698c2ecf20Sopenharmony_ci 44708c2ecf20Sopenharmony_ci state->fe[0] = fe; 44718c2ecf20Sopenharmony_ci fe->demodulator_priv = state; 44728c2ecf20Sopenharmony_ci memcpy(&state->fe[0]->ops, &dib8000_ops, sizeof(struct dvb_frontend_ops)); 44738c2ecf20Sopenharmony_ci 44748c2ecf20Sopenharmony_ci state->timf_default = cfg->pll->timf; 44758c2ecf20Sopenharmony_ci 44768c2ecf20Sopenharmony_ci if (dib8000_identify(&state->i2c) == 0) { 44778c2ecf20Sopenharmony_ci kfree(fe); 44788c2ecf20Sopenharmony_ci goto error; 44798c2ecf20Sopenharmony_ci } 44808c2ecf20Sopenharmony_ci 44818c2ecf20Sopenharmony_ci dibx000_init_i2c_master(&state->i2c_master, DIB8000, state->i2c.adap, state->i2c.addr); 44828c2ecf20Sopenharmony_ci 44838c2ecf20Sopenharmony_ci /* init 8096p tuner adapter */ 44848c2ecf20Sopenharmony_ci strscpy(state->dib8096p_tuner_adap.name, "DiB8096P tuner interface", 44858c2ecf20Sopenharmony_ci sizeof(state->dib8096p_tuner_adap.name)); 44868c2ecf20Sopenharmony_ci state->dib8096p_tuner_adap.algo = &dib8096p_tuner_xfer_algo; 44878c2ecf20Sopenharmony_ci state->dib8096p_tuner_adap.algo_data = NULL; 44888c2ecf20Sopenharmony_ci state->dib8096p_tuner_adap.dev.parent = state->i2c.adap->dev.parent; 44898c2ecf20Sopenharmony_ci i2c_set_adapdata(&state->dib8096p_tuner_adap, state); 44908c2ecf20Sopenharmony_ci i2c_add_adapter(&state->dib8096p_tuner_adap); 44918c2ecf20Sopenharmony_ci 44928c2ecf20Sopenharmony_ci dib8000_reset(fe); 44938c2ecf20Sopenharmony_ci 44948c2ecf20Sopenharmony_ci dib8000_write_word(state, 285, (dib8000_read_word(state, 285) & ~0x60) | (3 << 5)); /* ber_rs_len = 3 */ 44958c2ecf20Sopenharmony_ci state->current_demod_bw = 6000; 44968c2ecf20Sopenharmony_ci 44978c2ecf20Sopenharmony_ci return fe; 44988c2ecf20Sopenharmony_ci 44998c2ecf20Sopenharmony_cierror: 45008c2ecf20Sopenharmony_ci kfree(state); 45018c2ecf20Sopenharmony_ci return NULL; 45028c2ecf20Sopenharmony_ci} 45038c2ecf20Sopenharmony_ci 45048c2ecf20Sopenharmony_civoid *dib8000_attach(struct dib8000_ops *ops) 45058c2ecf20Sopenharmony_ci{ 45068c2ecf20Sopenharmony_ci if (!ops) 45078c2ecf20Sopenharmony_ci return NULL; 45088c2ecf20Sopenharmony_ci 45098c2ecf20Sopenharmony_ci ops->pwm_agc_reset = dib8000_pwm_agc_reset; 45108c2ecf20Sopenharmony_ci ops->get_dc_power = dib8090p_get_dc_power; 45118c2ecf20Sopenharmony_ci ops->set_gpio = dib8000_set_gpio; 45128c2ecf20Sopenharmony_ci ops->get_slave_frontend = dib8000_get_slave_frontend; 45138c2ecf20Sopenharmony_ci ops->set_tune_state = dib8000_set_tune_state; 45148c2ecf20Sopenharmony_ci ops->pid_filter_ctrl = dib8000_pid_filter_ctrl; 45158c2ecf20Sopenharmony_ci ops->get_adc_power = dib8000_get_adc_power; 45168c2ecf20Sopenharmony_ci ops->update_pll = dib8000_update_pll; 45178c2ecf20Sopenharmony_ci ops->tuner_sleep = dib8096p_tuner_sleep; 45188c2ecf20Sopenharmony_ci ops->get_tune_state = dib8000_get_tune_state; 45198c2ecf20Sopenharmony_ci ops->get_i2c_tuner = dib8096p_get_i2c_tuner; 45208c2ecf20Sopenharmony_ci ops->set_slave_frontend = dib8000_set_slave_frontend; 45218c2ecf20Sopenharmony_ci ops->pid_filter = dib8000_pid_filter; 45228c2ecf20Sopenharmony_ci ops->ctrl_timf = dib8000_ctrl_timf; 45238c2ecf20Sopenharmony_ci ops->init = dib8000_init; 45248c2ecf20Sopenharmony_ci ops->get_i2c_master = dib8000_get_i2c_master; 45258c2ecf20Sopenharmony_ci ops->i2c_enumeration = dib8000_i2c_enumeration; 45268c2ecf20Sopenharmony_ci ops->set_wbd_ref = dib8000_set_wbd_ref; 45278c2ecf20Sopenharmony_ci 45288c2ecf20Sopenharmony_ci return ops; 45298c2ecf20Sopenharmony_ci} 45308c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(dib8000_attach); 45318c2ecf20Sopenharmony_ci 45328c2ecf20Sopenharmony_ciMODULE_AUTHOR("Olivier Grenie <Olivier.Grenie@parrot.com, Patrick Boettcher <patrick.boettcher@posteo.de>"); 45338c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Driver for the DiBcom 8000 ISDB-T demodulator"); 45348c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 4535