18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Support for LG2160 - ATSC/MH 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2010 Michael Krufky <mkrufky@linuxtv.org> 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#include <linux/jiffies.h> 98c2ecf20Sopenharmony_ci#include <linux/dvb/frontend.h> 108c2ecf20Sopenharmony_ci#include "lg2160.h" 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_cistatic int debug; 138c2ecf20Sopenharmony_cimodule_param(debug, int, 0644); 148c2ecf20Sopenharmony_ciMODULE_PARM_DESC(debug, "set debug level (info=1, reg=2 (or-able))"); 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci#define DBG_INFO 1 178c2ecf20Sopenharmony_ci#define DBG_REG 2 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci#define lg_printk(kern, fmt, arg...) \ 208c2ecf20Sopenharmony_ci printk(kern "%s: " fmt, __func__, ##arg) 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ci#define lg_info(fmt, arg...) printk(KERN_INFO "lg2160: " fmt, ##arg) 238c2ecf20Sopenharmony_ci#define lg_warn(fmt, arg...) lg_printk(KERN_WARNING, fmt, ##arg) 248c2ecf20Sopenharmony_ci#define lg_err(fmt, arg...) lg_printk(KERN_ERR, fmt, ##arg) 258c2ecf20Sopenharmony_ci#define lg_dbg(fmt, arg...) if (debug & DBG_INFO) \ 268c2ecf20Sopenharmony_ci lg_printk(KERN_DEBUG, fmt, ##arg) 278c2ecf20Sopenharmony_ci#define lg_reg(fmt, arg...) if (debug & DBG_REG) \ 288c2ecf20Sopenharmony_ci lg_printk(KERN_DEBUG, fmt, ##arg) 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci#define lg_fail(ret) \ 318c2ecf20Sopenharmony_ci({ \ 328c2ecf20Sopenharmony_ci int __ret; \ 338c2ecf20Sopenharmony_ci __ret = (ret < 0); \ 348c2ecf20Sopenharmony_ci if (__ret) \ 358c2ecf20Sopenharmony_ci lg_err("error %d on line %d\n", ret, __LINE__); \ 368c2ecf20Sopenharmony_ci __ret; \ 378c2ecf20Sopenharmony_ci}) 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_cistruct lg216x_state { 408c2ecf20Sopenharmony_ci struct i2c_adapter *i2c_adap; 418c2ecf20Sopenharmony_ci const struct lg2160_config *cfg; 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci struct dvb_frontend frontend; 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci u32 current_frequency; 468c2ecf20Sopenharmony_ci u8 parade_id; 478c2ecf20Sopenharmony_ci u8 fic_ver; 488c2ecf20Sopenharmony_ci unsigned int last_reset; 498c2ecf20Sopenharmony_ci}; 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ci/* ------------------------------------------------------------------------ */ 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_cistatic int lg216x_write_reg(struct lg216x_state *state, u16 reg, u8 val) 548c2ecf20Sopenharmony_ci{ 558c2ecf20Sopenharmony_ci int ret; 568c2ecf20Sopenharmony_ci u8 buf[] = { reg >> 8, reg & 0xff, val }; 578c2ecf20Sopenharmony_ci struct i2c_msg msg = { 588c2ecf20Sopenharmony_ci .addr = state->cfg->i2c_addr, .flags = 0, 598c2ecf20Sopenharmony_ci .buf = buf, .len = 3, 608c2ecf20Sopenharmony_ci }; 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci lg_reg("reg: 0x%04x, val: 0x%02x\n", reg, val); 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci ret = i2c_transfer(state->i2c_adap, &msg, 1); 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci if (ret != 1) { 678c2ecf20Sopenharmony_ci lg_err("error (addr %02x %02x <- %02x, err = %i)\n", 688c2ecf20Sopenharmony_ci msg.buf[0], msg.buf[1], msg.buf[2], ret); 698c2ecf20Sopenharmony_ci if (ret < 0) 708c2ecf20Sopenharmony_ci return ret; 718c2ecf20Sopenharmony_ci else 728c2ecf20Sopenharmony_ci return -EREMOTEIO; 738c2ecf20Sopenharmony_ci } 748c2ecf20Sopenharmony_ci return 0; 758c2ecf20Sopenharmony_ci} 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_cistatic int lg216x_read_reg(struct lg216x_state *state, u16 reg, u8 *val) 788c2ecf20Sopenharmony_ci{ 798c2ecf20Sopenharmony_ci int ret; 808c2ecf20Sopenharmony_ci u8 reg_buf[] = { reg >> 8, reg & 0xff }; 818c2ecf20Sopenharmony_ci struct i2c_msg msg[] = { 828c2ecf20Sopenharmony_ci { .addr = state->cfg->i2c_addr, 838c2ecf20Sopenharmony_ci .flags = 0, .buf = reg_buf, .len = 2 }, 848c2ecf20Sopenharmony_ci { .addr = state->cfg->i2c_addr, 858c2ecf20Sopenharmony_ci .flags = I2C_M_RD, .buf = val, .len = 1 }, 868c2ecf20Sopenharmony_ci }; 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci lg_reg("reg: 0x%04x\n", reg); 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ci ret = i2c_transfer(state->i2c_adap, msg, 2); 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ci if (ret != 2) { 938c2ecf20Sopenharmony_ci lg_err("error (addr %02x reg %04x error (ret == %i)\n", 948c2ecf20Sopenharmony_ci state->cfg->i2c_addr, reg, ret); 958c2ecf20Sopenharmony_ci if (ret < 0) 968c2ecf20Sopenharmony_ci return ret; 978c2ecf20Sopenharmony_ci else 988c2ecf20Sopenharmony_ci return -EREMOTEIO; 998c2ecf20Sopenharmony_ci } 1008c2ecf20Sopenharmony_ci return 0; 1018c2ecf20Sopenharmony_ci} 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_cistruct lg216x_reg { 1048c2ecf20Sopenharmony_ci u16 reg; 1058c2ecf20Sopenharmony_ci u8 val; 1068c2ecf20Sopenharmony_ci}; 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_cistatic int lg216x_write_regs(struct lg216x_state *state, 1098c2ecf20Sopenharmony_ci struct lg216x_reg *regs, int len) 1108c2ecf20Sopenharmony_ci{ 1118c2ecf20Sopenharmony_ci int i, ret; 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_ci lg_reg("writing %d registers...\n", len); 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ci for (i = 0; i < len; i++) { 1168c2ecf20Sopenharmony_ci ret = lg216x_write_reg(state, regs[i].reg, regs[i].val); 1178c2ecf20Sopenharmony_ci if (lg_fail(ret)) 1188c2ecf20Sopenharmony_ci return ret; 1198c2ecf20Sopenharmony_ci } 1208c2ecf20Sopenharmony_ci return 0; 1218c2ecf20Sopenharmony_ci} 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_cistatic int lg216x_set_reg_bit(struct lg216x_state *state, 1248c2ecf20Sopenharmony_ci u16 reg, int bit, int onoff) 1258c2ecf20Sopenharmony_ci{ 1268c2ecf20Sopenharmony_ci u8 val; 1278c2ecf20Sopenharmony_ci int ret; 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_ci lg_reg("reg: 0x%04x, bit: %d, level: %d\n", reg, bit, onoff); 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_ci ret = lg216x_read_reg(state, reg, &val); 1328c2ecf20Sopenharmony_ci if (lg_fail(ret)) 1338c2ecf20Sopenharmony_ci goto fail; 1348c2ecf20Sopenharmony_ci 1358c2ecf20Sopenharmony_ci val &= ~(1 << bit); 1368c2ecf20Sopenharmony_ci val |= (onoff & 1) << bit; 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_ci ret = lg216x_write_reg(state, reg, val); 1398c2ecf20Sopenharmony_ci lg_fail(ret); 1408c2ecf20Sopenharmony_cifail: 1418c2ecf20Sopenharmony_ci return ret; 1428c2ecf20Sopenharmony_ci} 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_ci/* ------------------------------------------------------------------------ */ 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_cistatic int lg216x_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) 1478c2ecf20Sopenharmony_ci{ 1488c2ecf20Sopenharmony_ci struct lg216x_state *state = fe->demodulator_priv; 1498c2ecf20Sopenharmony_ci int ret; 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ci if (state->cfg->deny_i2c_rptr) 1528c2ecf20Sopenharmony_ci return 0; 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci lg_dbg("(%d)\n", enable); 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_ci ret = lg216x_set_reg_bit(state, 0x0000, 0, enable ? 0 : 1); 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci msleep(1); 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci return ret; 1618c2ecf20Sopenharmony_ci} 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_cistatic int lg216x_soft_reset(struct lg216x_state *state) 1648c2ecf20Sopenharmony_ci{ 1658c2ecf20Sopenharmony_ci int ret; 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_ci lg_dbg("\n"); 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ci ret = lg216x_write_reg(state, 0x0002, 0x00); 1708c2ecf20Sopenharmony_ci if (lg_fail(ret)) 1718c2ecf20Sopenharmony_ci goto fail; 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_ci msleep(20); 1748c2ecf20Sopenharmony_ci ret = lg216x_write_reg(state, 0x0002, 0x01); 1758c2ecf20Sopenharmony_ci if (lg_fail(ret)) 1768c2ecf20Sopenharmony_ci goto fail; 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ci state->last_reset = jiffies_to_msecs(jiffies); 1798c2ecf20Sopenharmony_cifail: 1808c2ecf20Sopenharmony_ci return ret; 1818c2ecf20Sopenharmony_ci} 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_cistatic int lg216x_initialize(struct lg216x_state *state) 1848c2ecf20Sopenharmony_ci{ 1858c2ecf20Sopenharmony_ci int ret; 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_ci static struct lg216x_reg lg2160_init[] = { 1888c2ecf20Sopenharmony_ci#if 0 1898c2ecf20Sopenharmony_ci { .reg = 0x0015, .val = 0xe6 }, 1908c2ecf20Sopenharmony_ci#else 1918c2ecf20Sopenharmony_ci { .reg = 0x0015, .val = 0xf7 }, 1928c2ecf20Sopenharmony_ci { .reg = 0x001b, .val = 0x52 }, 1938c2ecf20Sopenharmony_ci { .reg = 0x0208, .val = 0x00 }, 1948c2ecf20Sopenharmony_ci { .reg = 0x0209, .val = 0x82 }, 1958c2ecf20Sopenharmony_ci { .reg = 0x0210, .val = 0xf9 }, 1968c2ecf20Sopenharmony_ci { .reg = 0x020a, .val = 0x00 }, 1978c2ecf20Sopenharmony_ci { .reg = 0x020b, .val = 0x82 }, 1988c2ecf20Sopenharmony_ci { .reg = 0x020d, .val = 0x28 }, 1998c2ecf20Sopenharmony_ci { .reg = 0x020f, .val = 0x14 }, 2008c2ecf20Sopenharmony_ci#endif 2018c2ecf20Sopenharmony_ci }; 2028c2ecf20Sopenharmony_ci 2038c2ecf20Sopenharmony_ci static struct lg216x_reg lg2161_init[] = { 2048c2ecf20Sopenharmony_ci { .reg = 0x0000, .val = 0x41 }, 2058c2ecf20Sopenharmony_ci { .reg = 0x0001, .val = 0xfb }, 2068c2ecf20Sopenharmony_ci { .reg = 0x0216, .val = 0x00 }, 2078c2ecf20Sopenharmony_ci { .reg = 0x0219, .val = 0x00 }, 2088c2ecf20Sopenharmony_ci { .reg = 0x021b, .val = 0x55 }, 2098c2ecf20Sopenharmony_ci { .reg = 0x0606, .val = 0x0a }, 2108c2ecf20Sopenharmony_ci }; 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_ci switch (state->cfg->lg_chip) { 2138c2ecf20Sopenharmony_ci case LG2160: 2148c2ecf20Sopenharmony_ci ret = lg216x_write_regs(state, 2158c2ecf20Sopenharmony_ci lg2160_init, ARRAY_SIZE(lg2160_init)); 2168c2ecf20Sopenharmony_ci break; 2178c2ecf20Sopenharmony_ci case LG2161: 2188c2ecf20Sopenharmony_ci ret = lg216x_write_regs(state, 2198c2ecf20Sopenharmony_ci lg2161_init, ARRAY_SIZE(lg2161_init)); 2208c2ecf20Sopenharmony_ci break; 2218c2ecf20Sopenharmony_ci default: 2228c2ecf20Sopenharmony_ci ret = -EINVAL; 2238c2ecf20Sopenharmony_ci break; 2248c2ecf20Sopenharmony_ci } 2258c2ecf20Sopenharmony_ci if (lg_fail(ret)) 2268c2ecf20Sopenharmony_ci goto fail; 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_ci ret = lg216x_soft_reset(state); 2298c2ecf20Sopenharmony_ci lg_fail(ret); 2308c2ecf20Sopenharmony_cifail: 2318c2ecf20Sopenharmony_ci return ret; 2328c2ecf20Sopenharmony_ci} 2338c2ecf20Sopenharmony_ci 2348c2ecf20Sopenharmony_ci/* ------------------------------------------------------------------------ */ 2358c2ecf20Sopenharmony_ci 2368c2ecf20Sopenharmony_cistatic int lg216x_set_if(struct lg216x_state *state) 2378c2ecf20Sopenharmony_ci{ 2388c2ecf20Sopenharmony_ci u8 val; 2398c2ecf20Sopenharmony_ci int ret; 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_ci lg_dbg("%d KHz\n", state->cfg->if_khz); 2428c2ecf20Sopenharmony_ci 2438c2ecf20Sopenharmony_ci ret = lg216x_read_reg(state, 0x0132, &val); 2448c2ecf20Sopenharmony_ci if (lg_fail(ret)) 2458c2ecf20Sopenharmony_ci goto fail; 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_ci val &= 0xfb; 2488c2ecf20Sopenharmony_ci val |= (0 == state->cfg->if_khz) ? 0x04 : 0x00; 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_ci ret = lg216x_write_reg(state, 0x0132, val); 2518c2ecf20Sopenharmony_ci lg_fail(ret); 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_ci /* if NOT zero IF, 6 MHz is the default */ 2548c2ecf20Sopenharmony_cifail: 2558c2ecf20Sopenharmony_ci return ret; 2568c2ecf20Sopenharmony_ci} 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_ci/* ------------------------------------------------------------------------ */ 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_cistatic int lg2160_agc_fix(struct lg216x_state *state, 2618c2ecf20Sopenharmony_ci int if_agc_fix, int rf_agc_fix) 2628c2ecf20Sopenharmony_ci{ 2638c2ecf20Sopenharmony_ci u8 val; 2648c2ecf20Sopenharmony_ci int ret; 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_ci ret = lg216x_read_reg(state, 0x0100, &val); 2678c2ecf20Sopenharmony_ci if (lg_fail(ret)) 2688c2ecf20Sopenharmony_ci goto fail; 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_ci val &= 0xf3; 2718c2ecf20Sopenharmony_ci val |= (if_agc_fix) ? 0x08 : 0x00; 2728c2ecf20Sopenharmony_ci val |= (rf_agc_fix) ? 0x04 : 0x00; 2738c2ecf20Sopenharmony_ci 2748c2ecf20Sopenharmony_ci ret = lg216x_write_reg(state, 0x0100, val); 2758c2ecf20Sopenharmony_ci lg_fail(ret); 2768c2ecf20Sopenharmony_cifail: 2778c2ecf20Sopenharmony_ci return ret; 2788c2ecf20Sopenharmony_ci} 2798c2ecf20Sopenharmony_ci 2808c2ecf20Sopenharmony_ci#if 0 2818c2ecf20Sopenharmony_cistatic int lg2160_agc_freeze(struct lg216x_state *state, 2828c2ecf20Sopenharmony_ci int if_agc_freeze, int rf_agc_freeze) 2838c2ecf20Sopenharmony_ci{ 2848c2ecf20Sopenharmony_ci u8 val; 2858c2ecf20Sopenharmony_ci int ret; 2868c2ecf20Sopenharmony_ci 2878c2ecf20Sopenharmony_ci ret = lg216x_read_reg(state, 0x0100, &val); 2888c2ecf20Sopenharmony_ci if (lg_fail(ret)) 2898c2ecf20Sopenharmony_ci goto fail; 2908c2ecf20Sopenharmony_ci 2918c2ecf20Sopenharmony_ci val &= 0xcf; 2928c2ecf20Sopenharmony_ci val |= (if_agc_freeze) ? 0x20 : 0x00; 2938c2ecf20Sopenharmony_ci val |= (rf_agc_freeze) ? 0x10 : 0x00; 2948c2ecf20Sopenharmony_ci 2958c2ecf20Sopenharmony_ci ret = lg216x_write_reg(state, 0x0100, val); 2968c2ecf20Sopenharmony_ci lg_fail(ret); 2978c2ecf20Sopenharmony_cifail: 2988c2ecf20Sopenharmony_ci return ret; 2998c2ecf20Sopenharmony_ci} 3008c2ecf20Sopenharmony_ci#endif 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_cistatic int lg2160_agc_polarity(struct lg216x_state *state, 3038c2ecf20Sopenharmony_ci int if_agc_polarity, int rf_agc_polarity) 3048c2ecf20Sopenharmony_ci{ 3058c2ecf20Sopenharmony_ci u8 val; 3068c2ecf20Sopenharmony_ci int ret; 3078c2ecf20Sopenharmony_ci 3088c2ecf20Sopenharmony_ci ret = lg216x_read_reg(state, 0x0100, &val); 3098c2ecf20Sopenharmony_ci if (lg_fail(ret)) 3108c2ecf20Sopenharmony_ci goto fail; 3118c2ecf20Sopenharmony_ci 3128c2ecf20Sopenharmony_ci val &= 0xfc; 3138c2ecf20Sopenharmony_ci val |= (if_agc_polarity) ? 0x02 : 0x00; 3148c2ecf20Sopenharmony_ci val |= (rf_agc_polarity) ? 0x01 : 0x00; 3158c2ecf20Sopenharmony_ci 3168c2ecf20Sopenharmony_ci ret = lg216x_write_reg(state, 0x0100, val); 3178c2ecf20Sopenharmony_ci lg_fail(ret); 3188c2ecf20Sopenharmony_cifail: 3198c2ecf20Sopenharmony_ci return ret; 3208c2ecf20Sopenharmony_ci} 3218c2ecf20Sopenharmony_ci 3228c2ecf20Sopenharmony_cistatic int lg2160_tuner_pwr_save_polarity(struct lg216x_state *state, 3238c2ecf20Sopenharmony_ci int polarity) 3248c2ecf20Sopenharmony_ci{ 3258c2ecf20Sopenharmony_ci u8 val; 3268c2ecf20Sopenharmony_ci int ret; 3278c2ecf20Sopenharmony_ci 3288c2ecf20Sopenharmony_ci ret = lg216x_read_reg(state, 0x0008, &val); 3298c2ecf20Sopenharmony_ci if (lg_fail(ret)) 3308c2ecf20Sopenharmony_ci goto fail; 3318c2ecf20Sopenharmony_ci 3328c2ecf20Sopenharmony_ci val &= 0xfe; 3338c2ecf20Sopenharmony_ci val |= (polarity) ? 0x01 : 0x00; 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_ci ret = lg216x_write_reg(state, 0x0008, val); 3368c2ecf20Sopenharmony_ci lg_fail(ret); 3378c2ecf20Sopenharmony_cifail: 3388c2ecf20Sopenharmony_ci return ret; 3398c2ecf20Sopenharmony_ci} 3408c2ecf20Sopenharmony_ci 3418c2ecf20Sopenharmony_cistatic int lg2160_spectrum_polarity(struct lg216x_state *state, 3428c2ecf20Sopenharmony_ci int inverted) 3438c2ecf20Sopenharmony_ci{ 3448c2ecf20Sopenharmony_ci u8 val; 3458c2ecf20Sopenharmony_ci int ret; 3468c2ecf20Sopenharmony_ci 3478c2ecf20Sopenharmony_ci ret = lg216x_read_reg(state, 0x0132, &val); 3488c2ecf20Sopenharmony_ci if (lg_fail(ret)) 3498c2ecf20Sopenharmony_ci goto fail; 3508c2ecf20Sopenharmony_ci 3518c2ecf20Sopenharmony_ci val &= 0xfd; 3528c2ecf20Sopenharmony_ci val |= (inverted) ? 0x02 : 0x00; 3538c2ecf20Sopenharmony_ci 3548c2ecf20Sopenharmony_ci ret = lg216x_write_reg(state, 0x0132, val); 3558c2ecf20Sopenharmony_ci lg_fail(ret); 3568c2ecf20Sopenharmony_cifail: 3578c2ecf20Sopenharmony_ci return lg216x_soft_reset(state); 3588c2ecf20Sopenharmony_ci} 3598c2ecf20Sopenharmony_ci 3608c2ecf20Sopenharmony_cistatic int lg2160_tuner_pwr_save(struct lg216x_state *state, int onoff) 3618c2ecf20Sopenharmony_ci{ 3628c2ecf20Sopenharmony_ci u8 val; 3638c2ecf20Sopenharmony_ci int ret; 3648c2ecf20Sopenharmony_ci 3658c2ecf20Sopenharmony_ci ret = lg216x_read_reg(state, 0x0007, &val); 3668c2ecf20Sopenharmony_ci if (lg_fail(ret)) 3678c2ecf20Sopenharmony_ci goto fail; 3688c2ecf20Sopenharmony_ci 3698c2ecf20Sopenharmony_ci val &= 0xbf; 3708c2ecf20Sopenharmony_ci val |= (onoff) ? 0x40 : 0x00; 3718c2ecf20Sopenharmony_ci 3728c2ecf20Sopenharmony_ci ret = lg216x_write_reg(state, 0x0007, val); 3738c2ecf20Sopenharmony_ci lg_fail(ret); 3748c2ecf20Sopenharmony_cifail: 3758c2ecf20Sopenharmony_ci return ret; 3768c2ecf20Sopenharmony_ci} 3778c2ecf20Sopenharmony_ci 3788c2ecf20Sopenharmony_cistatic int lg216x_set_parade(struct lg216x_state *state, int id) 3798c2ecf20Sopenharmony_ci{ 3808c2ecf20Sopenharmony_ci int ret; 3818c2ecf20Sopenharmony_ci 3828c2ecf20Sopenharmony_ci ret = lg216x_write_reg(state, 0x013e, id & 0x7f); 3838c2ecf20Sopenharmony_ci if (lg_fail(ret)) 3848c2ecf20Sopenharmony_ci goto fail; 3858c2ecf20Sopenharmony_ci 3868c2ecf20Sopenharmony_ci state->parade_id = id & 0x7f; 3878c2ecf20Sopenharmony_cifail: 3888c2ecf20Sopenharmony_ci return ret; 3898c2ecf20Sopenharmony_ci} 3908c2ecf20Sopenharmony_ci 3918c2ecf20Sopenharmony_cistatic int lg216x_set_ensemble(struct lg216x_state *state, int id) 3928c2ecf20Sopenharmony_ci{ 3938c2ecf20Sopenharmony_ci int ret; 3948c2ecf20Sopenharmony_ci u16 reg; 3958c2ecf20Sopenharmony_ci u8 val; 3968c2ecf20Sopenharmony_ci 3978c2ecf20Sopenharmony_ci switch (state->cfg->lg_chip) { 3988c2ecf20Sopenharmony_ci case LG2160: 3998c2ecf20Sopenharmony_ci reg = 0x0400; 4008c2ecf20Sopenharmony_ci break; 4018c2ecf20Sopenharmony_ci case LG2161: 4028c2ecf20Sopenharmony_ci default: 4038c2ecf20Sopenharmony_ci reg = 0x0500; 4048c2ecf20Sopenharmony_ci break; 4058c2ecf20Sopenharmony_ci } 4068c2ecf20Sopenharmony_ci 4078c2ecf20Sopenharmony_ci ret = lg216x_read_reg(state, reg, &val); 4088c2ecf20Sopenharmony_ci if (lg_fail(ret)) 4098c2ecf20Sopenharmony_ci goto fail; 4108c2ecf20Sopenharmony_ci 4118c2ecf20Sopenharmony_ci val &= 0xfe; 4128c2ecf20Sopenharmony_ci val |= (id) ? 0x01 : 0x00; 4138c2ecf20Sopenharmony_ci 4148c2ecf20Sopenharmony_ci ret = lg216x_write_reg(state, reg, val); 4158c2ecf20Sopenharmony_ci lg_fail(ret); 4168c2ecf20Sopenharmony_cifail: 4178c2ecf20Sopenharmony_ci return ret; 4188c2ecf20Sopenharmony_ci} 4198c2ecf20Sopenharmony_ci 4208c2ecf20Sopenharmony_cistatic int lg2160_set_spi_clock(struct lg216x_state *state) 4218c2ecf20Sopenharmony_ci{ 4228c2ecf20Sopenharmony_ci u8 val; 4238c2ecf20Sopenharmony_ci int ret; 4248c2ecf20Sopenharmony_ci 4258c2ecf20Sopenharmony_ci ret = lg216x_read_reg(state, 0x0014, &val); 4268c2ecf20Sopenharmony_ci if (lg_fail(ret)) 4278c2ecf20Sopenharmony_ci goto fail; 4288c2ecf20Sopenharmony_ci 4298c2ecf20Sopenharmony_ci val &= 0xf3; 4308c2ecf20Sopenharmony_ci val |= (state->cfg->spi_clock << 2); 4318c2ecf20Sopenharmony_ci 4328c2ecf20Sopenharmony_ci ret = lg216x_write_reg(state, 0x0014, val); 4338c2ecf20Sopenharmony_ci lg_fail(ret); 4348c2ecf20Sopenharmony_cifail: 4358c2ecf20Sopenharmony_ci return ret; 4368c2ecf20Sopenharmony_ci} 4378c2ecf20Sopenharmony_ci 4388c2ecf20Sopenharmony_cistatic int lg2161_set_output_interface(struct lg216x_state *state) 4398c2ecf20Sopenharmony_ci{ 4408c2ecf20Sopenharmony_ci u8 val; 4418c2ecf20Sopenharmony_ci int ret; 4428c2ecf20Sopenharmony_ci 4438c2ecf20Sopenharmony_ci ret = lg216x_read_reg(state, 0x0014, &val); 4448c2ecf20Sopenharmony_ci if (lg_fail(ret)) 4458c2ecf20Sopenharmony_ci goto fail; 4468c2ecf20Sopenharmony_ci 4478c2ecf20Sopenharmony_ci val &= ~0x07; 4488c2ecf20Sopenharmony_ci val |= state->cfg->output_if; /* FIXME: needs sanity check */ 4498c2ecf20Sopenharmony_ci 4508c2ecf20Sopenharmony_ci ret = lg216x_write_reg(state, 0x0014, val); 4518c2ecf20Sopenharmony_ci lg_fail(ret); 4528c2ecf20Sopenharmony_cifail: 4538c2ecf20Sopenharmony_ci return ret; 4548c2ecf20Sopenharmony_ci} 4558c2ecf20Sopenharmony_ci 4568c2ecf20Sopenharmony_cistatic int lg216x_enable_fic(struct lg216x_state *state, int onoff) 4578c2ecf20Sopenharmony_ci{ 4588c2ecf20Sopenharmony_ci int ret; 4598c2ecf20Sopenharmony_ci 4608c2ecf20Sopenharmony_ci ret = lg216x_write_reg(state, 0x0017, 0x23); 4618c2ecf20Sopenharmony_ci if (lg_fail(ret)) 4628c2ecf20Sopenharmony_ci goto fail; 4638c2ecf20Sopenharmony_ci 4648c2ecf20Sopenharmony_ci ret = lg216x_write_reg(state, 0x0016, 0xfc); 4658c2ecf20Sopenharmony_ci if (lg_fail(ret)) 4668c2ecf20Sopenharmony_ci goto fail; 4678c2ecf20Sopenharmony_ci 4688c2ecf20Sopenharmony_ci switch (state->cfg->lg_chip) { 4698c2ecf20Sopenharmony_ci case LG2160: 4708c2ecf20Sopenharmony_ci ret = lg216x_write_reg(state, 0x0016, 4718c2ecf20Sopenharmony_ci 0xfc | ((onoff) ? 0x02 : 0x00)); 4728c2ecf20Sopenharmony_ci break; 4738c2ecf20Sopenharmony_ci case LG2161: 4748c2ecf20Sopenharmony_ci ret = lg216x_write_reg(state, 0x0016, (onoff) ? 0x10 : 0x00); 4758c2ecf20Sopenharmony_ci break; 4768c2ecf20Sopenharmony_ci } 4778c2ecf20Sopenharmony_ci if (lg_fail(ret)) 4788c2ecf20Sopenharmony_ci goto fail; 4798c2ecf20Sopenharmony_ci 4808c2ecf20Sopenharmony_ci ret = lg216x_initialize(state); 4818c2ecf20Sopenharmony_ci if (lg_fail(ret)) 4828c2ecf20Sopenharmony_ci goto fail; 4838c2ecf20Sopenharmony_ci 4848c2ecf20Sopenharmony_ci if (onoff) { 4858c2ecf20Sopenharmony_ci ret = lg216x_write_reg(state, 0x0017, 0x03); 4868c2ecf20Sopenharmony_ci lg_fail(ret); 4878c2ecf20Sopenharmony_ci } 4888c2ecf20Sopenharmony_cifail: 4898c2ecf20Sopenharmony_ci return ret; 4908c2ecf20Sopenharmony_ci} 4918c2ecf20Sopenharmony_ci 4928c2ecf20Sopenharmony_ci/* ------------------------------------------------------------------------ */ 4938c2ecf20Sopenharmony_ci 4948c2ecf20Sopenharmony_cistatic int lg216x_get_fic_version(struct lg216x_state *state, u8 *ficver) 4958c2ecf20Sopenharmony_ci{ 4968c2ecf20Sopenharmony_ci u8 val; 4978c2ecf20Sopenharmony_ci int ret; 4988c2ecf20Sopenharmony_ci 4998c2ecf20Sopenharmony_ci *ficver = 0xff; /* invalid value */ 5008c2ecf20Sopenharmony_ci 5018c2ecf20Sopenharmony_ci ret = lg216x_read_reg(state, 0x0128, &val); 5028c2ecf20Sopenharmony_ci if (lg_fail(ret)) 5038c2ecf20Sopenharmony_ci goto fail; 5048c2ecf20Sopenharmony_ci 5058c2ecf20Sopenharmony_ci *ficver = (val >> 3) & 0x1f; 5068c2ecf20Sopenharmony_cifail: 5078c2ecf20Sopenharmony_ci return ret; 5088c2ecf20Sopenharmony_ci} 5098c2ecf20Sopenharmony_ci 5108c2ecf20Sopenharmony_ci#if 0 5118c2ecf20Sopenharmony_cistatic int lg2160_get_parade_id(struct lg216x_state *state, u8 *id) 5128c2ecf20Sopenharmony_ci{ 5138c2ecf20Sopenharmony_ci u8 val; 5148c2ecf20Sopenharmony_ci int ret; 5158c2ecf20Sopenharmony_ci 5168c2ecf20Sopenharmony_ci *id = 0xff; /* invalid value */ 5178c2ecf20Sopenharmony_ci 5188c2ecf20Sopenharmony_ci ret = lg216x_read_reg(state, 0x0123, &val); 5198c2ecf20Sopenharmony_ci if (lg_fail(ret)) 5208c2ecf20Sopenharmony_ci goto fail; 5218c2ecf20Sopenharmony_ci 5228c2ecf20Sopenharmony_ci *id = val & 0x7f; 5238c2ecf20Sopenharmony_cifail: 5248c2ecf20Sopenharmony_ci return ret; 5258c2ecf20Sopenharmony_ci} 5268c2ecf20Sopenharmony_ci#endif 5278c2ecf20Sopenharmony_ci 5288c2ecf20Sopenharmony_cistatic int lg216x_get_nog(struct lg216x_state *state, u8 *nog) 5298c2ecf20Sopenharmony_ci{ 5308c2ecf20Sopenharmony_ci u8 val; 5318c2ecf20Sopenharmony_ci int ret; 5328c2ecf20Sopenharmony_ci 5338c2ecf20Sopenharmony_ci *nog = 0xff; /* invalid value */ 5348c2ecf20Sopenharmony_ci 5358c2ecf20Sopenharmony_ci ret = lg216x_read_reg(state, 0x0124, &val); 5368c2ecf20Sopenharmony_ci if (lg_fail(ret)) 5378c2ecf20Sopenharmony_ci goto fail; 5388c2ecf20Sopenharmony_ci 5398c2ecf20Sopenharmony_ci *nog = ((val >> 4) & 0x07) + 1; 5408c2ecf20Sopenharmony_cifail: 5418c2ecf20Sopenharmony_ci return ret; 5428c2ecf20Sopenharmony_ci} 5438c2ecf20Sopenharmony_ci 5448c2ecf20Sopenharmony_cistatic int lg216x_get_tnog(struct lg216x_state *state, u8 *tnog) 5458c2ecf20Sopenharmony_ci{ 5468c2ecf20Sopenharmony_ci u8 val; 5478c2ecf20Sopenharmony_ci int ret; 5488c2ecf20Sopenharmony_ci 5498c2ecf20Sopenharmony_ci *tnog = 0xff; /* invalid value */ 5508c2ecf20Sopenharmony_ci 5518c2ecf20Sopenharmony_ci ret = lg216x_read_reg(state, 0x0125, &val); 5528c2ecf20Sopenharmony_ci if (lg_fail(ret)) 5538c2ecf20Sopenharmony_ci goto fail; 5548c2ecf20Sopenharmony_ci 5558c2ecf20Sopenharmony_ci *tnog = val & 0x1f; 5568c2ecf20Sopenharmony_cifail: 5578c2ecf20Sopenharmony_ci return ret; 5588c2ecf20Sopenharmony_ci} 5598c2ecf20Sopenharmony_ci 5608c2ecf20Sopenharmony_cistatic int lg216x_get_sgn(struct lg216x_state *state, u8 *sgn) 5618c2ecf20Sopenharmony_ci{ 5628c2ecf20Sopenharmony_ci u8 val; 5638c2ecf20Sopenharmony_ci int ret; 5648c2ecf20Sopenharmony_ci 5658c2ecf20Sopenharmony_ci *sgn = 0xff; /* invalid value */ 5668c2ecf20Sopenharmony_ci 5678c2ecf20Sopenharmony_ci ret = lg216x_read_reg(state, 0x0124, &val); 5688c2ecf20Sopenharmony_ci if (lg_fail(ret)) 5698c2ecf20Sopenharmony_ci goto fail; 5708c2ecf20Sopenharmony_ci 5718c2ecf20Sopenharmony_ci *sgn = val & 0x0f; 5728c2ecf20Sopenharmony_cifail: 5738c2ecf20Sopenharmony_ci return ret; 5748c2ecf20Sopenharmony_ci} 5758c2ecf20Sopenharmony_ci 5768c2ecf20Sopenharmony_cistatic int lg216x_get_prc(struct lg216x_state *state, u8 *prc) 5778c2ecf20Sopenharmony_ci{ 5788c2ecf20Sopenharmony_ci u8 val; 5798c2ecf20Sopenharmony_ci int ret; 5808c2ecf20Sopenharmony_ci 5818c2ecf20Sopenharmony_ci *prc = 0xff; /* invalid value */ 5828c2ecf20Sopenharmony_ci 5838c2ecf20Sopenharmony_ci ret = lg216x_read_reg(state, 0x0125, &val); 5848c2ecf20Sopenharmony_ci if (lg_fail(ret)) 5858c2ecf20Sopenharmony_ci goto fail; 5868c2ecf20Sopenharmony_ci 5878c2ecf20Sopenharmony_ci *prc = ((val >> 5) & 0x07) + 1; 5888c2ecf20Sopenharmony_cifail: 5898c2ecf20Sopenharmony_ci return ret; 5908c2ecf20Sopenharmony_ci} 5918c2ecf20Sopenharmony_ci 5928c2ecf20Sopenharmony_ci/* ------------------------------------------------------------------------ */ 5938c2ecf20Sopenharmony_ci 5948c2ecf20Sopenharmony_cistatic int lg216x_get_rs_frame_mode(struct lg216x_state *state, 5958c2ecf20Sopenharmony_ci enum atscmh_rs_frame_mode *rs_framemode) 5968c2ecf20Sopenharmony_ci{ 5978c2ecf20Sopenharmony_ci u8 val; 5988c2ecf20Sopenharmony_ci int ret; 5998c2ecf20Sopenharmony_ci 6008c2ecf20Sopenharmony_ci switch (state->cfg->lg_chip) { 6018c2ecf20Sopenharmony_ci case LG2160: 6028c2ecf20Sopenharmony_ci ret = lg216x_read_reg(state, 0x0410, &val); 6038c2ecf20Sopenharmony_ci break; 6048c2ecf20Sopenharmony_ci case LG2161: 6058c2ecf20Sopenharmony_ci ret = lg216x_read_reg(state, 0x0513, &val); 6068c2ecf20Sopenharmony_ci break; 6078c2ecf20Sopenharmony_ci default: 6088c2ecf20Sopenharmony_ci ret = -EINVAL; 6098c2ecf20Sopenharmony_ci } 6108c2ecf20Sopenharmony_ci if (lg_fail(ret)) 6118c2ecf20Sopenharmony_ci goto fail; 6128c2ecf20Sopenharmony_ci 6138c2ecf20Sopenharmony_ci switch ((val >> 4) & 0x03) { 6148c2ecf20Sopenharmony_ci#if 1 6158c2ecf20Sopenharmony_ci default: 6168c2ecf20Sopenharmony_ci#endif 6178c2ecf20Sopenharmony_ci case 0x00: 6188c2ecf20Sopenharmony_ci *rs_framemode = ATSCMH_RSFRAME_PRI_ONLY; 6198c2ecf20Sopenharmony_ci break; 6208c2ecf20Sopenharmony_ci case 0x01: 6218c2ecf20Sopenharmony_ci *rs_framemode = ATSCMH_RSFRAME_PRI_SEC; 6228c2ecf20Sopenharmony_ci break; 6238c2ecf20Sopenharmony_ci#if 0 6248c2ecf20Sopenharmony_ci default: 6258c2ecf20Sopenharmony_ci *rs_framemode = ATSCMH_RSFRAME_RES; 6268c2ecf20Sopenharmony_ci break; 6278c2ecf20Sopenharmony_ci#endif 6288c2ecf20Sopenharmony_ci } 6298c2ecf20Sopenharmony_cifail: 6308c2ecf20Sopenharmony_ci return ret; 6318c2ecf20Sopenharmony_ci} 6328c2ecf20Sopenharmony_ci 6338c2ecf20Sopenharmony_cistatic 6348c2ecf20Sopenharmony_ciint lg216x_get_rs_frame_ensemble(struct lg216x_state *state, 6358c2ecf20Sopenharmony_ci enum atscmh_rs_frame_ensemble *rs_frame_ens) 6368c2ecf20Sopenharmony_ci{ 6378c2ecf20Sopenharmony_ci u8 val; 6388c2ecf20Sopenharmony_ci int ret; 6398c2ecf20Sopenharmony_ci 6408c2ecf20Sopenharmony_ci switch (state->cfg->lg_chip) { 6418c2ecf20Sopenharmony_ci case LG2160: 6428c2ecf20Sopenharmony_ci ret = lg216x_read_reg(state, 0x0400, &val); 6438c2ecf20Sopenharmony_ci break; 6448c2ecf20Sopenharmony_ci case LG2161: 6458c2ecf20Sopenharmony_ci ret = lg216x_read_reg(state, 0x0500, &val); 6468c2ecf20Sopenharmony_ci break; 6478c2ecf20Sopenharmony_ci default: 6488c2ecf20Sopenharmony_ci ret = -EINVAL; 6498c2ecf20Sopenharmony_ci } 6508c2ecf20Sopenharmony_ci if (lg_fail(ret)) 6518c2ecf20Sopenharmony_ci goto fail; 6528c2ecf20Sopenharmony_ci 6538c2ecf20Sopenharmony_ci val &= 0x01; 6548c2ecf20Sopenharmony_ci *rs_frame_ens = (enum atscmh_rs_frame_ensemble) val; 6558c2ecf20Sopenharmony_cifail: 6568c2ecf20Sopenharmony_ci return ret; 6578c2ecf20Sopenharmony_ci} 6588c2ecf20Sopenharmony_ci 6598c2ecf20Sopenharmony_cistatic int lg216x_get_rs_code_mode(struct lg216x_state *state, 6608c2ecf20Sopenharmony_ci enum atscmh_rs_code_mode *rs_code_pri, 6618c2ecf20Sopenharmony_ci enum atscmh_rs_code_mode *rs_code_sec) 6628c2ecf20Sopenharmony_ci{ 6638c2ecf20Sopenharmony_ci u8 val; 6648c2ecf20Sopenharmony_ci int ret; 6658c2ecf20Sopenharmony_ci 6668c2ecf20Sopenharmony_ci switch (state->cfg->lg_chip) { 6678c2ecf20Sopenharmony_ci case LG2160: 6688c2ecf20Sopenharmony_ci ret = lg216x_read_reg(state, 0x0410, &val); 6698c2ecf20Sopenharmony_ci break; 6708c2ecf20Sopenharmony_ci case LG2161: 6718c2ecf20Sopenharmony_ci ret = lg216x_read_reg(state, 0x0513, &val); 6728c2ecf20Sopenharmony_ci break; 6738c2ecf20Sopenharmony_ci default: 6748c2ecf20Sopenharmony_ci ret = -EINVAL; 6758c2ecf20Sopenharmony_ci } 6768c2ecf20Sopenharmony_ci if (lg_fail(ret)) 6778c2ecf20Sopenharmony_ci goto fail; 6788c2ecf20Sopenharmony_ci 6798c2ecf20Sopenharmony_ci *rs_code_pri = (enum atscmh_rs_code_mode) ((val >> 2) & 0x03); 6808c2ecf20Sopenharmony_ci *rs_code_sec = (enum atscmh_rs_code_mode) (val & 0x03); 6818c2ecf20Sopenharmony_cifail: 6828c2ecf20Sopenharmony_ci return ret; 6838c2ecf20Sopenharmony_ci} 6848c2ecf20Sopenharmony_ci 6858c2ecf20Sopenharmony_cistatic int lg216x_get_sccc_block_mode(struct lg216x_state *state, 6868c2ecf20Sopenharmony_ci enum atscmh_sccc_block_mode *sccc_block) 6878c2ecf20Sopenharmony_ci{ 6888c2ecf20Sopenharmony_ci u8 val; 6898c2ecf20Sopenharmony_ci int ret; 6908c2ecf20Sopenharmony_ci 6918c2ecf20Sopenharmony_ci switch (state->cfg->lg_chip) { 6928c2ecf20Sopenharmony_ci case LG2160: 6938c2ecf20Sopenharmony_ci ret = lg216x_read_reg(state, 0x0315, &val); 6948c2ecf20Sopenharmony_ci break; 6958c2ecf20Sopenharmony_ci case LG2161: 6968c2ecf20Sopenharmony_ci ret = lg216x_read_reg(state, 0x0511, &val); 6978c2ecf20Sopenharmony_ci break; 6988c2ecf20Sopenharmony_ci default: 6998c2ecf20Sopenharmony_ci ret = -EINVAL; 7008c2ecf20Sopenharmony_ci } 7018c2ecf20Sopenharmony_ci if (lg_fail(ret)) 7028c2ecf20Sopenharmony_ci goto fail; 7038c2ecf20Sopenharmony_ci 7048c2ecf20Sopenharmony_ci switch (val & 0x03) { 7058c2ecf20Sopenharmony_ci case 0x00: 7068c2ecf20Sopenharmony_ci *sccc_block = ATSCMH_SCCC_BLK_SEP; 7078c2ecf20Sopenharmony_ci break; 7088c2ecf20Sopenharmony_ci case 0x01: 7098c2ecf20Sopenharmony_ci *sccc_block = ATSCMH_SCCC_BLK_COMB; 7108c2ecf20Sopenharmony_ci break; 7118c2ecf20Sopenharmony_ci default: 7128c2ecf20Sopenharmony_ci *sccc_block = ATSCMH_SCCC_BLK_RES; 7138c2ecf20Sopenharmony_ci break; 7148c2ecf20Sopenharmony_ci } 7158c2ecf20Sopenharmony_cifail: 7168c2ecf20Sopenharmony_ci return ret; 7178c2ecf20Sopenharmony_ci} 7188c2ecf20Sopenharmony_ci 7198c2ecf20Sopenharmony_cistatic int lg216x_get_sccc_code_mode(struct lg216x_state *state, 7208c2ecf20Sopenharmony_ci enum atscmh_sccc_code_mode *mode_a, 7218c2ecf20Sopenharmony_ci enum atscmh_sccc_code_mode *mode_b, 7228c2ecf20Sopenharmony_ci enum atscmh_sccc_code_mode *mode_c, 7238c2ecf20Sopenharmony_ci enum atscmh_sccc_code_mode *mode_d) 7248c2ecf20Sopenharmony_ci{ 7258c2ecf20Sopenharmony_ci u8 val; 7268c2ecf20Sopenharmony_ci int ret; 7278c2ecf20Sopenharmony_ci 7288c2ecf20Sopenharmony_ci switch (state->cfg->lg_chip) { 7298c2ecf20Sopenharmony_ci case LG2160: 7308c2ecf20Sopenharmony_ci ret = lg216x_read_reg(state, 0x0316, &val); 7318c2ecf20Sopenharmony_ci break; 7328c2ecf20Sopenharmony_ci case LG2161: 7338c2ecf20Sopenharmony_ci ret = lg216x_read_reg(state, 0x0512, &val); 7348c2ecf20Sopenharmony_ci break; 7358c2ecf20Sopenharmony_ci default: 7368c2ecf20Sopenharmony_ci ret = -EINVAL; 7378c2ecf20Sopenharmony_ci } 7388c2ecf20Sopenharmony_ci if (lg_fail(ret)) 7398c2ecf20Sopenharmony_ci goto fail; 7408c2ecf20Sopenharmony_ci 7418c2ecf20Sopenharmony_ci switch ((val >> 6) & 0x03) { 7428c2ecf20Sopenharmony_ci case 0x00: 7438c2ecf20Sopenharmony_ci *mode_a = ATSCMH_SCCC_CODE_HLF; 7448c2ecf20Sopenharmony_ci break; 7458c2ecf20Sopenharmony_ci case 0x01: 7468c2ecf20Sopenharmony_ci *mode_a = ATSCMH_SCCC_CODE_QTR; 7478c2ecf20Sopenharmony_ci break; 7488c2ecf20Sopenharmony_ci default: 7498c2ecf20Sopenharmony_ci *mode_a = ATSCMH_SCCC_CODE_RES; 7508c2ecf20Sopenharmony_ci break; 7518c2ecf20Sopenharmony_ci } 7528c2ecf20Sopenharmony_ci 7538c2ecf20Sopenharmony_ci switch ((val >> 4) & 0x03) { 7548c2ecf20Sopenharmony_ci case 0x00: 7558c2ecf20Sopenharmony_ci *mode_b = ATSCMH_SCCC_CODE_HLF; 7568c2ecf20Sopenharmony_ci break; 7578c2ecf20Sopenharmony_ci case 0x01: 7588c2ecf20Sopenharmony_ci *mode_b = ATSCMH_SCCC_CODE_QTR; 7598c2ecf20Sopenharmony_ci break; 7608c2ecf20Sopenharmony_ci default: 7618c2ecf20Sopenharmony_ci *mode_b = ATSCMH_SCCC_CODE_RES; 7628c2ecf20Sopenharmony_ci break; 7638c2ecf20Sopenharmony_ci } 7648c2ecf20Sopenharmony_ci 7658c2ecf20Sopenharmony_ci switch ((val >> 2) & 0x03) { 7668c2ecf20Sopenharmony_ci case 0x00: 7678c2ecf20Sopenharmony_ci *mode_c = ATSCMH_SCCC_CODE_HLF; 7688c2ecf20Sopenharmony_ci break; 7698c2ecf20Sopenharmony_ci case 0x01: 7708c2ecf20Sopenharmony_ci *mode_c = ATSCMH_SCCC_CODE_QTR; 7718c2ecf20Sopenharmony_ci break; 7728c2ecf20Sopenharmony_ci default: 7738c2ecf20Sopenharmony_ci *mode_c = ATSCMH_SCCC_CODE_RES; 7748c2ecf20Sopenharmony_ci break; 7758c2ecf20Sopenharmony_ci } 7768c2ecf20Sopenharmony_ci 7778c2ecf20Sopenharmony_ci switch (val & 0x03) { 7788c2ecf20Sopenharmony_ci case 0x00: 7798c2ecf20Sopenharmony_ci *mode_d = ATSCMH_SCCC_CODE_HLF; 7808c2ecf20Sopenharmony_ci break; 7818c2ecf20Sopenharmony_ci case 0x01: 7828c2ecf20Sopenharmony_ci *mode_d = ATSCMH_SCCC_CODE_QTR; 7838c2ecf20Sopenharmony_ci break; 7848c2ecf20Sopenharmony_ci default: 7858c2ecf20Sopenharmony_ci *mode_d = ATSCMH_SCCC_CODE_RES; 7868c2ecf20Sopenharmony_ci break; 7878c2ecf20Sopenharmony_ci } 7888c2ecf20Sopenharmony_cifail: 7898c2ecf20Sopenharmony_ci return ret; 7908c2ecf20Sopenharmony_ci} 7918c2ecf20Sopenharmony_ci 7928c2ecf20Sopenharmony_ci/* ------------------------------------------------------------------------ */ 7938c2ecf20Sopenharmony_ci 7948c2ecf20Sopenharmony_ci#if 0 7958c2ecf20Sopenharmony_cistatic int lg216x_read_fic_err_count(struct lg216x_state *state, u8 *err) 7968c2ecf20Sopenharmony_ci{ 7978c2ecf20Sopenharmony_ci u8 fic_err; 7988c2ecf20Sopenharmony_ci int ret; 7998c2ecf20Sopenharmony_ci 8008c2ecf20Sopenharmony_ci *err = 0; 8018c2ecf20Sopenharmony_ci 8028c2ecf20Sopenharmony_ci switch (state->cfg->lg_chip) { 8038c2ecf20Sopenharmony_ci case LG2160: 8048c2ecf20Sopenharmony_ci ret = lg216x_read_reg(state, 0x0012, &fic_err); 8058c2ecf20Sopenharmony_ci break; 8068c2ecf20Sopenharmony_ci case LG2161: 8078c2ecf20Sopenharmony_ci ret = lg216x_read_reg(state, 0x001e, &fic_err); 8088c2ecf20Sopenharmony_ci break; 8098c2ecf20Sopenharmony_ci } 8108c2ecf20Sopenharmony_ci if (lg_fail(ret)) 8118c2ecf20Sopenharmony_ci goto fail; 8128c2ecf20Sopenharmony_ci 8138c2ecf20Sopenharmony_ci *err = fic_err; 8148c2ecf20Sopenharmony_cifail: 8158c2ecf20Sopenharmony_ci return ret; 8168c2ecf20Sopenharmony_ci} 8178c2ecf20Sopenharmony_ci 8188c2ecf20Sopenharmony_cistatic int lg2160_read_crc_err_count(struct lg216x_state *state, u16 *err) 8198c2ecf20Sopenharmony_ci{ 8208c2ecf20Sopenharmony_ci u8 crc_err1, crc_err2; 8218c2ecf20Sopenharmony_ci int ret; 8228c2ecf20Sopenharmony_ci 8238c2ecf20Sopenharmony_ci *err = 0; 8248c2ecf20Sopenharmony_ci 8258c2ecf20Sopenharmony_ci ret = lg216x_read_reg(state, 0x0411, &crc_err1); 8268c2ecf20Sopenharmony_ci if (lg_fail(ret)) 8278c2ecf20Sopenharmony_ci goto fail; 8288c2ecf20Sopenharmony_ci 8298c2ecf20Sopenharmony_ci ret = lg216x_read_reg(state, 0x0412, &crc_err2); 8308c2ecf20Sopenharmony_ci if (lg_fail(ret)) 8318c2ecf20Sopenharmony_ci goto fail; 8328c2ecf20Sopenharmony_ci 8338c2ecf20Sopenharmony_ci *err = (u16)(((crc_err2 & 0x0f) << 8) | crc_err1); 8348c2ecf20Sopenharmony_cifail: 8358c2ecf20Sopenharmony_ci return ret; 8368c2ecf20Sopenharmony_ci} 8378c2ecf20Sopenharmony_ci 8388c2ecf20Sopenharmony_cistatic int lg2161_read_crc_err_count(struct lg216x_state *state, u16 *err) 8398c2ecf20Sopenharmony_ci{ 8408c2ecf20Sopenharmony_ci u8 crc_err; 8418c2ecf20Sopenharmony_ci int ret; 8428c2ecf20Sopenharmony_ci 8438c2ecf20Sopenharmony_ci *err = 0; 8448c2ecf20Sopenharmony_ci 8458c2ecf20Sopenharmony_ci ret = lg216x_read_reg(state, 0x0612, &crc_err); 8468c2ecf20Sopenharmony_ci if (lg_fail(ret)) 8478c2ecf20Sopenharmony_ci goto fail; 8488c2ecf20Sopenharmony_ci 8498c2ecf20Sopenharmony_ci *err = (u16)crc_err; 8508c2ecf20Sopenharmony_cifail: 8518c2ecf20Sopenharmony_ci return ret; 8528c2ecf20Sopenharmony_ci} 8538c2ecf20Sopenharmony_ci 8548c2ecf20Sopenharmony_cistatic int lg216x_read_crc_err_count(struct lg216x_state *state, u16 *err) 8558c2ecf20Sopenharmony_ci{ 8568c2ecf20Sopenharmony_ci int ret; 8578c2ecf20Sopenharmony_ci switch (state->cfg->lg_chip) { 8588c2ecf20Sopenharmony_ci case LG2160: 8598c2ecf20Sopenharmony_ci ret = lg2160_read_crc_err_count(state, err); 8608c2ecf20Sopenharmony_ci break; 8618c2ecf20Sopenharmony_ci case LG2161: 8628c2ecf20Sopenharmony_ci ret = lg2161_read_crc_err_count(state, err); 8638c2ecf20Sopenharmony_ci break; 8648c2ecf20Sopenharmony_ci default: 8658c2ecf20Sopenharmony_ci ret = -EINVAL; 8668c2ecf20Sopenharmony_ci break; 8678c2ecf20Sopenharmony_ci } 8688c2ecf20Sopenharmony_ci return ret; 8698c2ecf20Sopenharmony_ci} 8708c2ecf20Sopenharmony_ci 8718c2ecf20Sopenharmony_cistatic int lg2160_read_rs_err_count(struct lg216x_state *state, u16 *err) 8728c2ecf20Sopenharmony_ci{ 8738c2ecf20Sopenharmony_ci u8 rs_err1, rs_err2; 8748c2ecf20Sopenharmony_ci int ret; 8758c2ecf20Sopenharmony_ci 8768c2ecf20Sopenharmony_ci *err = 0; 8778c2ecf20Sopenharmony_ci 8788c2ecf20Sopenharmony_ci ret = lg216x_read_reg(state, 0x0413, &rs_err1); 8798c2ecf20Sopenharmony_ci if (lg_fail(ret)) 8808c2ecf20Sopenharmony_ci goto fail; 8818c2ecf20Sopenharmony_ci 8828c2ecf20Sopenharmony_ci ret = lg216x_read_reg(state, 0x0414, &rs_err2); 8838c2ecf20Sopenharmony_ci if (lg_fail(ret)) 8848c2ecf20Sopenharmony_ci goto fail; 8858c2ecf20Sopenharmony_ci 8868c2ecf20Sopenharmony_ci *err = (u16)(((rs_err2 & 0x0f) << 8) | rs_err1); 8878c2ecf20Sopenharmony_cifail: 8888c2ecf20Sopenharmony_ci return ret; 8898c2ecf20Sopenharmony_ci} 8908c2ecf20Sopenharmony_ci 8918c2ecf20Sopenharmony_cistatic int lg2161_read_rs_err_count(struct lg216x_state *state, u16 *err) 8928c2ecf20Sopenharmony_ci{ 8938c2ecf20Sopenharmony_ci u8 rs_err1, rs_err2; 8948c2ecf20Sopenharmony_ci int ret; 8958c2ecf20Sopenharmony_ci 8968c2ecf20Sopenharmony_ci *err = 0; 8978c2ecf20Sopenharmony_ci 8988c2ecf20Sopenharmony_ci ret = lg216x_read_reg(state, 0x0613, &rs_err1); 8998c2ecf20Sopenharmony_ci if (lg_fail(ret)) 9008c2ecf20Sopenharmony_ci goto fail; 9018c2ecf20Sopenharmony_ci 9028c2ecf20Sopenharmony_ci ret = lg216x_read_reg(state, 0x0614, &rs_err2); 9038c2ecf20Sopenharmony_ci if (lg_fail(ret)) 9048c2ecf20Sopenharmony_ci goto fail; 9058c2ecf20Sopenharmony_ci 9068c2ecf20Sopenharmony_ci *err = (u16)((rs_err1 << 8) | rs_err2); 9078c2ecf20Sopenharmony_cifail: 9088c2ecf20Sopenharmony_ci return ret; 9098c2ecf20Sopenharmony_ci} 9108c2ecf20Sopenharmony_ci 9118c2ecf20Sopenharmony_cistatic int lg216x_read_rs_err_count(struct lg216x_state *state, u16 *err) 9128c2ecf20Sopenharmony_ci{ 9138c2ecf20Sopenharmony_ci int ret; 9148c2ecf20Sopenharmony_ci switch (state->cfg->lg_chip) { 9158c2ecf20Sopenharmony_ci case LG2160: 9168c2ecf20Sopenharmony_ci ret = lg2160_read_rs_err_count(state, err); 9178c2ecf20Sopenharmony_ci break; 9188c2ecf20Sopenharmony_ci case LG2161: 9198c2ecf20Sopenharmony_ci ret = lg2161_read_rs_err_count(state, err); 9208c2ecf20Sopenharmony_ci break; 9218c2ecf20Sopenharmony_ci default: 9228c2ecf20Sopenharmony_ci ret = -EINVAL; 9238c2ecf20Sopenharmony_ci break; 9248c2ecf20Sopenharmony_ci } 9258c2ecf20Sopenharmony_ci return ret; 9268c2ecf20Sopenharmony_ci} 9278c2ecf20Sopenharmony_ci#endif 9288c2ecf20Sopenharmony_ci 9298c2ecf20Sopenharmony_ci/* ------------------------------------------------------------------------ */ 9308c2ecf20Sopenharmony_ci 9318c2ecf20Sopenharmony_cistatic int lg216x_get_frontend(struct dvb_frontend *fe, 9328c2ecf20Sopenharmony_ci struct dtv_frontend_properties *c) 9338c2ecf20Sopenharmony_ci{ 9348c2ecf20Sopenharmony_ci struct lg216x_state *state = fe->demodulator_priv; 9358c2ecf20Sopenharmony_ci int ret; 9368c2ecf20Sopenharmony_ci 9378c2ecf20Sopenharmony_ci lg_dbg("\n"); 9388c2ecf20Sopenharmony_ci 9398c2ecf20Sopenharmony_ci c->modulation = VSB_8; 9408c2ecf20Sopenharmony_ci c->frequency = state->current_frequency; 9418c2ecf20Sopenharmony_ci c->delivery_system = SYS_ATSCMH; 9428c2ecf20Sopenharmony_ci 9438c2ecf20Sopenharmony_ci ret = lg216x_get_fic_version(state, 9448c2ecf20Sopenharmony_ci &c->atscmh_fic_ver); 9458c2ecf20Sopenharmony_ci if (lg_fail(ret)) 9468c2ecf20Sopenharmony_ci goto fail; 9478c2ecf20Sopenharmony_ci if (state->fic_ver != c->atscmh_fic_ver) { 9488c2ecf20Sopenharmony_ci state->fic_ver = c->atscmh_fic_ver; 9498c2ecf20Sopenharmony_ci 9508c2ecf20Sopenharmony_ci#if 0 9518c2ecf20Sopenharmony_ci ret = lg2160_get_parade_id(state, 9528c2ecf20Sopenharmony_ci &c->atscmh_parade_id); 9538c2ecf20Sopenharmony_ci if (lg_fail(ret)) 9548c2ecf20Sopenharmony_ci goto fail; 9558c2ecf20Sopenharmony_ci/* #else */ 9568c2ecf20Sopenharmony_ci c->atscmh_parade_id = state->parade_id; 9578c2ecf20Sopenharmony_ci#endif 9588c2ecf20Sopenharmony_ci ret = lg216x_get_nog(state, 9598c2ecf20Sopenharmony_ci &c->atscmh_nog); 9608c2ecf20Sopenharmony_ci if (lg_fail(ret)) 9618c2ecf20Sopenharmony_ci goto fail; 9628c2ecf20Sopenharmony_ci ret = lg216x_get_tnog(state, 9638c2ecf20Sopenharmony_ci &c->atscmh_tnog); 9648c2ecf20Sopenharmony_ci if (lg_fail(ret)) 9658c2ecf20Sopenharmony_ci goto fail; 9668c2ecf20Sopenharmony_ci ret = lg216x_get_sgn(state, 9678c2ecf20Sopenharmony_ci &c->atscmh_sgn); 9688c2ecf20Sopenharmony_ci if (lg_fail(ret)) 9698c2ecf20Sopenharmony_ci goto fail; 9708c2ecf20Sopenharmony_ci ret = lg216x_get_prc(state, 9718c2ecf20Sopenharmony_ci &c->atscmh_prc); 9728c2ecf20Sopenharmony_ci if (lg_fail(ret)) 9738c2ecf20Sopenharmony_ci goto fail; 9748c2ecf20Sopenharmony_ci 9758c2ecf20Sopenharmony_ci ret = lg216x_get_rs_frame_mode(state, 9768c2ecf20Sopenharmony_ci (enum atscmh_rs_frame_mode *) 9778c2ecf20Sopenharmony_ci &c->atscmh_rs_frame_mode); 9788c2ecf20Sopenharmony_ci if (lg_fail(ret)) 9798c2ecf20Sopenharmony_ci goto fail; 9808c2ecf20Sopenharmony_ci ret = lg216x_get_rs_frame_ensemble(state, 9818c2ecf20Sopenharmony_ci (enum atscmh_rs_frame_ensemble *) 9828c2ecf20Sopenharmony_ci &c->atscmh_rs_frame_ensemble); 9838c2ecf20Sopenharmony_ci if (lg_fail(ret)) 9848c2ecf20Sopenharmony_ci goto fail; 9858c2ecf20Sopenharmony_ci ret = lg216x_get_rs_code_mode(state, 9868c2ecf20Sopenharmony_ci (enum atscmh_rs_code_mode *) 9878c2ecf20Sopenharmony_ci &c->atscmh_rs_code_mode_pri, 9888c2ecf20Sopenharmony_ci (enum atscmh_rs_code_mode *) 9898c2ecf20Sopenharmony_ci &c->atscmh_rs_code_mode_sec); 9908c2ecf20Sopenharmony_ci if (lg_fail(ret)) 9918c2ecf20Sopenharmony_ci goto fail; 9928c2ecf20Sopenharmony_ci ret = lg216x_get_sccc_block_mode(state, 9938c2ecf20Sopenharmony_ci (enum atscmh_sccc_block_mode *) 9948c2ecf20Sopenharmony_ci &c->atscmh_sccc_block_mode); 9958c2ecf20Sopenharmony_ci if (lg_fail(ret)) 9968c2ecf20Sopenharmony_ci goto fail; 9978c2ecf20Sopenharmony_ci ret = lg216x_get_sccc_code_mode(state, 9988c2ecf20Sopenharmony_ci (enum atscmh_sccc_code_mode *) 9998c2ecf20Sopenharmony_ci &c->atscmh_sccc_code_mode_a, 10008c2ecf20Sopenharmony_ci (enum atscmh_sccc_code_mode *) 10018c2ecf20Sopenharmony_ci &c->atscmh_sccc_code_mode_b, 10028c2ecf20Sopenharmony_ci (enum atscmh_sccc_code_mode *) 10038c2ecf20Sopenharmony_ci &c->atscmh_sccc_code_mode_c, 10048c2ecf20Sopenharmony_ci (enum atscmh_sccc_code_mode *) 10058c2ecf20Sopenharmony_ci &c->atscmh_sccc_code_mode_d); 10068c2ecf20Sopenharmony_ci if (lg_fail(ret)) 10078c2ecf20Sopenharmony_ci goto fail; 10088c2ecf20Sopenharmony_ci } 10098c2ecf20Sopenharmony_ci#if 0 10108c2ecf20Sopenharmony_ci ret = lg216x_read_fic_err_count(state, 10118c2ecf20Sopenharmony_ci (u8 *)&c->atscmh_fic_err); 10128c2ecf20Sopenharmony_ci if (lg_fail(ret)) 10138c2ecf20Sopenharmony_ci goto fail; 10148c2ecf20Sopenharmony_ci ret = lg216x_read_crc_err_count(state, 10158c2ecf20Sopenharmony_ci &c->atscmh_crc_err); 10168c2ecf20Sopenharmony_ci if (lg_fail(ret)) 10178c2ecf20Sopenharmony_ci goto fail; 10188c2ecf20Sopenharmony_ci ret = lg216x_read_rs_err_count(state, 10198c2ecf20Sopenharmony_ci &c->atscmh_rs_err); 10208c2ecf20Sopenharmony_ci if (lg_fail(ret)) 10218c2ecf20Sopenharmony_ci goto fail; 10228c2ecf20Sopenharmony_ci 10238c2ecf20Sopenharmony_ci switch (state->cfg->lg_chip) { 10248c2ecf20Sopenharmony_ci case LG2160: 10258c2ecf20Sopenharmony_ci if (((c->atscmh_rs_err >= 240) && 10268c2ecf20Sopenharmony_ci (c->atscmh_crc_err >= 240)) && 10278c2ecf20Sopenharmony_ci ((jiffies_to_msecs(jiffies) - state->last_reset) > 6000)) 10288c2ecf20Sopenharmony_ci ret = lg216x_soft_reset(state); 10298c2ecf20Sopenharmony_ci break; 10308c2ecf20Sopenharmony_ci case LG2161: 10318c2ecf20Sopenharmony_ci /* no fix needed here (as far as we know) */ 10328c2ecf20Sopenharmony_ci ret = 0; 10338c2ecf20Sopenharmony_ci break; 10348c2ecf20Sopenharmony_ci } 10358c2ecf20Sopenharmony_ci lg_fail(ret); 10368c2ecf20Sopenharmony_ci#endif 10378c2ecf20Sopenharmony_cifail: 10388c2ecf20Sopenharmony_ci return ret; 10398c2ecf20Sopenharmony_ci} 10408c2ecf20Sopenharmony_ci 10418c2ecf20Sopenharmony_cistatic int lg2160_set_frontend(struct dvb_frontend *fe) 10428c2ecf20Sopenharmony_ci{ 10438c2ecf20Sopenharmony_ci struct lg216x_state *state = fe->demodulator_priv; 10448c2ecf20Sopenharmony_ci struct dtv_frontend_properties *c = &fe->dtv_property_cache; 10458c2ecf20Sopenharmony_ci int ret; 10468c2ecf20Sopenharmony_ci 10478c2ecf20Sopenharmony_ci lg_dbg("(%d)\n", fe->dtv_property_cache.frequency); 10488c2ecf20Sopenharmony_ci 10498c2ecf20Sopenharmony_ci if (fe->ops.tuner_ops.set_params) { 10508c2ecf20Sopenharmony_ci ret = fe->ops.tuner_ops.set_params(fe); 10518c2ecf20Sopenharmony_ci if (fe->ops.i2c_gate_ctrl) 10528c2ecf20Sopenharmony_ci fe->ops.i2c_gate_ctrl(fe, 0); 10538c2ecf20Sopenharmony_ci if (lg_fail(ret)) 10548c2ecf20Sopenharmony_ci goto fail; 10558c2ecf20Sopenharmony_ci state->current_frequency = fe->dtv_property_cache.frequency; 10568c2ecf20Sopenharmony_ci } 10578c2ecf20Sopenharmony_ci 10588c2ecf20Sopenharmony_ci ret = lg2160_agc_fix(state, 0, 0); 10598c2ecf20Sopenharmony_ci if (lg_fail(ret)) 10608c2ecf20Sopenharmony_ci goto fail; 10618c2ecf20Sopenharmony_ci ret = lg2160_agc_polarity(state, 0, 0); 10628c2ecf20Sopenharmony_ci if (lg_fail(ret)) 10638c2ecf20Sopenharmony_ci goto fail; 10648c2ecf20Sopenharmony_ci ret = lg2160_tuner_pwr_save_polarity(state, 1); 10658c2ecf20Sopenharmony_ci if (lg_fail(ret)) 10668c2ecf20Sopenharmony_ci goto fail; 10678c2ecf20Sopenharmony_ci ret = lg216x_set_if(state); 10688c2ecf20Sopenharmony_ci if (lg_fail(ret)) 10698c2ecf20Sopenharmony_ci goto fail; 10708c2ecf20Sopenharmony_ci ret = lg2160_spectrum_polarity(state, state->cfg->spectral_inversion); 10718c2ecf20Sopenharmony_ci if (lg_fail(ret)) 10728c2ecf20Sopenharmony_ci goto fail; 10738c2ecf20Sopenharmony_ci 10748c2ecf20Sopenharmony_ci /* be tuned before this point */ 10758c2ecf20Sopenharmony_ci ret = lg216x_soft_reset(state); 10768c2ecf20Sopenharmony_ci if (lg_fail(ret)) 10778c2ecf20Sopenharmony_ci goto fail; 10788c2ecf20Sopenharmony_ci 10798c2ecf20Sopenharmony_ci ret = lg2160_tuner_pwr_save(state, 0); 10808c2ecf20Sopenharmony_ci if (lg_fail(ret)) 10818c2ecf20Sopenharmony_ci goto fail; 10828c2ecf20Sopenharmony_ci 10838c2ecf20Sopenharmony_ci switch (state->cfg->lg_chip) { 10848c2ecf20Sopenharmony_ci case LG2160: 10858c2ecf20Sopenharmony_ci ret = lg2160_set_spi_clock(state); 10868c2ecf20Sopenharmony_ci if (lg_fail(ret)) 10878c2ecf20Sopenharmony_ci goto fail; 10888c2ecf20Sopenharmony_ci break; 10898c2ecf20Sopenharmony_ci case LG2161: 10908c2ecf20Sopenharmony_ci ret = lg2161_set_output_interface(state); 10918c2ecf20Sopenharmony_ci if (lg_fail(ret)) 10928c2ecf20Sopenharmony_ci goto fail; 10938c2ecf20Sopenharmony_ci break; 10948c2ecf20Sopenharmony_ci } 10958c2ecf20Sopenharmony_ci 10968c2ecf20Sopenharmony_ci ret = lg216x_set_parade(state, fe->dtv_property_cache.atscmh_parade_id); 10978c2ecf20Sopenharmony_ci if (lg_fail(ret)) 10988c2ecf20Sopenharmony_ci goto fail; 10998c2ecf20Sopenharmony_ci 11008c2ecf20Sopenharmony_ci ret = lg216x_set_ensemble(state, 11018c2ecf20Sopenharmony_ci fe->dtv_property_cache.atscmh_rs_frame_ensemble); 11028c2ecf20Sopenharmony_ci if (lg_fail(ret)) 11038c2ecf20Sopenharmony_ci goto fail; 11048c2ecf20Sopenharmony_ci 11058c2ecf20Sopenharmony_ci ret = lg216x_initialize(state); 11068c2ecf20Sopenharmony_ci if (lg_fail(ret)) 11078c2ecf20Sopenharmony_ci goto fail; 11088c2ecf20Sopenharmony_ci 11098c2ecf20Sopenharmony_ci ret = lg216x_enable_fic(state, 1); 11108c2ecf20Sopenharmony_ci lg_fail(ret); 11118c2ecf20Sopenharmony_ci 11128c2ecf20Sopenharmony_ci lg216x_get_frontend(fe, c); 11138c2ecf20Sopenharmony_cifail: 11148c2ecf20Sopenharmony_ci return ret; 11158c2ecf20Sopenharmony_ci} 11168c2ecf20Sopenharmony_ci 11178c2ecf20Sopenharmony_ci/* ------------------------------------------------------------------------ */ 11188c2ecf20Sopenharmony_ci 11198c2ecf20Sopenharmony_cistatic int lg2160_read_lock_status(struct lg216x_state *state, 11208c2ecf20Sopenharmony_ci int *acq_lock, int *sync_lock) 11218c2ecf20Sopenharmony_ci{ 11228c2ecf20Sopenharmony_ci u8 val; 11238c2ecf20Sopenharmony_ci int ret; 11248c2ecf20Sopenharmony_ci 11258c2ecf20Sopenharmony_ci *acq_lock = 0; 11268c2ecf20Sopenharmony_ci *sync_lock = 0; 11278c2ecf20Sopenharmony_ci 11288c2ecf20Sopenharmony_ci ret = lg216x_read_reg(state, 0x011b, &val); 11298c2ecf20Sopenharmony_ci if (lg_fail(ret)) 11308c2ecf20Sopenharmony_ci goto fail; 11318c2ecf20Sopenharmony_ci 11328c2ecf20Sopenharmony_ci *sync_lock = (val & 0x20) ? 0 : 1; 11338c2ecf20Sopenharmony_ci *acq_lock = (val & 0x40) ? 0 : 1; 11348c2ecf20Sopenharmony_cifail: 11358c2ecf20Sopenharmony_ci return ret; 11368c2ecf20Sopenharmony_ci} 11378c2ecf20Sopenharmony_ci 11388c2ecf20Sopenharmony_ci#ifdef USE_LG2161_LOCK_BITS 11398c2ecf20Sopenharmony_cistatic int lg2161_read_lock_status(struct lg216x_state *state, 11408c2ecf20Sopenharmony_ci int *acq_lock, int *sync_lock) 11418c2ecf20Sopenharmony_ci{ 11428c2ecf20Sopenharmony_ci u8 val; 11438c2ecf20Sopenharmony_ci int ret; 11448c2ecf20Sopenharmony_ci 11458c2ecf20Sopenharmony_ci *acq_lock = 0; 11468c2ecf20Sopenharmony_ci *sync_lock = 0; 11478c2ecf20Sopenharmony_ci 11488c2ecf20Sopenharmony_ci ret = lg216x_read_reg(state, 0x0304, &val); 11498c2ecf20Sopenharmony_ci if (lg_fail(ret)) 11508c2ecf20Sopenharmony_ci goto fail; 11518c2ecf20Sopenharmony_ci 11528c2ecf20Sopenharmony_ci *sync_lock = (val & 0x80) ? 0 : 1; 11538c2ecf20Sopenharmony_ci 11548c2ecf20Sopenharmony_ci ret = lg216x_read_reg(state, 0x011b, &val); 11558c2ecf20Sopenharmony_ci if (lg_fail(ret)) 11568c2ecf20Sopenharmony_ci goto fail; 11578c2ecf20Sopenharmony_ci 11588c2ecf20Sopenharmony_ci *acq_lock = (val & 0x40) ? 0 : 1; 11598c2ecf20Sopenharmony_cifail: 11608c2ecf20Sopenharmony_ci return ret; 11618c2ecf20Sopenharmony_ci} 11628c2ecf20Sopenharmony_ci#endif 11638c2ecf20Sopenharmony_ci 11648c2ecf20Sopenharmony_cistatic int lg216x_read_lock_status(struct lg216x_state *state, 11658c2ecf20Sopenharmony_ci int *acq_lock, int *sync_lock) 11668c2ecf20Sopenharmony_ci{ 11678c2ecf20Sopenharmony_ci#ifdef USE_LG2161_LOCK_BITS 11688c2ecf20Sopenharmony_ci int ret; 11698c2ecf20Sopenharmony_ci switch (state->cfg->lg_chip) { 11708c2ecf20Sopenharmony_ci case LG2160: 11718c2ecf20Sopenharmony_ci ret = lg2160_read_lock_status(state, acq_lock, sync_lock); 11728c2ecf20Sopenharmony_ci break; 11738c2ecf20Sopenharmony_ci case LG2161: 11748c2ecf20Sopenharmony_ci ret = lg2161_read_lock_status(state, acq_lock, sync_lock); 11758c2ecf20Sopenharmony_ci break; 11768c2ecf20Sopenharmony_ci default: 11778c2ecf20Sopenharmony_ci ret = -EINVAL; 11788c2ecf20Sopenharmony_ci break; 11798c2ecf20Sopenharmony_ci } 11808c2ecf20Sopenharmony_ci return ret; 11818c2ecf20Sopenharmony_ci#else 11828c2ecf20Sopenharmony_ci return lg2160_read_lock_status(state, acq_lock, sync_lock); 11838c2ecf20Sopenharmony_ci#endif 11848c2ecf20Sopenharmony_ci} 11858c2ecf20Sopenharmony_ci 11868c2ecf20Sopenharmony_cistatic int lg216x_read_status(struct dvb_frontend *fe, enum fe_status *status) 11878c2ecf20Sopenharmony_ci{ 11888c2ecf20Sopenharmony_ci struct lg216x_state *state = fe->demodulator_priv; 11898c2ecf20Sopenharmony_ci int ret, acq_lock, sync_lock; 11908c2ecf20Sopenharmony_ci 11918c2ecf20Sopenharmony_ci *status = 0; 11928c2ecf20Sopenharmony_ci 11938c2ecf20Sopenharmony_ci ret = lg216x_read_lock_status(state, &acq_lock, &sync_lock); 11948c2ecf20Sopenharmony_ci if (lg_fail(ret)) 11958c2ecf20Sopenharmony_ci goto fail; 11968c2ecf20Sopenharmony_ci 11978c2ecf20Sopenharmony_ci lg_dbg("%s%s\n", 11988c2ecf20Sopenharmony_ci acq_lock ? "SIGNALEXIST " : "", 11998c2ecf20Sopenharmony_ci sync_lock ? "SYNCLOCK" : ""); 12008c2ecf20Sopenharmony_ci 12018c2ecf20Sopenharmony_ci if (acq_lock) 12028c2ecf20Sopenharmony_ci *status |= FE_HAS_SIGNAL; 12038c2ecf20Sopenharmony_ci if (sync_lock) 12048c2ecf20Sopenharmony_ci *status |= FE_HAS_SYNC; 12058c2ecf20Sopenharmony_ci 12068c2ecf20Sopenharmony_ci if (*status) 12078c2ecf20Sopenharmony_ci *status |= FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_LOCK; 12088c2ecf20Sopenharmony_ci 12098c2ecf20Sopenharmony_cifail: 12108c2ecf20Sopenharmony_ci return ret; 12118c2ecf20Sopenharmony_ci} 12128c2ecf20Sopenharmony_ci 12138c2ecf20Sopenharmony_ci/* ------------------------------------------------------------------------ */ 12148c2ecf20Sopenharmony_ci 12158c2ecf20Sopenharmony_cistatic int lg2160_read_snr(struct dvb_frontend *fe, u16 *snr) 12168c2ecf20Sopenharmony_ci{ 12178c2ecf20Sopenharmony_ci struct lg216x_state *state = fe->demodulator_priv; 12188c2ecf20Sopenharmony_ci u8 snr1, snr2; 12198c2ecf20Sopenharmony_ci int ret; 12208c2ecf20Sopenharmony_ci 12218c2ecf20Sopenharmony_ci *snr = 0; 12228c2ecf20Sopenharmony_ci 12238c2ecf20Sopenharmony_ci ret = lg216x_read_reg(state, 0x0202, &snr1); 12248c2ecf20Sopenharmony_ci if (lg_fail(ret)) 12258c2ecf20Sopenharmony_ci goto fail; 12268c2ecf20Sopenharmony_ci 12278c2ecf20Sopenharmony_ci ret = lg216x_read_reg(state, 0x0203, &snr2); 12288c2ecf20Sopenharmony_ci if (lg_fail(ret)) 12298c2ecf20Sopenharmony_ci goto fail; 12308c2ecf20Sopenharmony_ci 12318c2ecf20Sopenharmony_ci if ((snr1 == 0xba) || (snr2 == 0xdf)) 12328c2ecf20Sopenharmony_ci *snr = 0; 12338c2ecf20Sopenharmony_ci else 12348c2ecf20Sopenharmony_ci#if 1 12358c2ecf20Sopenharmony_ci *snr = ((snr1 >> 4) * 100) + ((snr1 & 0x0f) * 10) + (snr2 >> 4); 12368c2ecf20Sopenharmony_ci#else /* BCD */ 12378c2ecf20Sopenharmony_ci *snr = (snr2 | (snr1 << 8)); 12388c2ecf20Sopenharmony_ci#endif 12398c2ecf20Sopenharmony_cifail: 12408c2ecf20Sopenharmony_ci return ret; 12418c2ecf20Sopenharmony_ci} 12428c2ecf20Sopenharmony_ci 12438c2ecf20Sopenharmony_cistatic int lg2161_read_snr(struct dvb_frontend *fe, u16 *snr) 12448c2ecf20Sopenharmony_ci{ 12458c2ecf20Sopenharmony_ci struct lg216x_state *state = fe->demodulator_priv; 12468c2ecf20Sopenharmony_ci u8 snr1, snr2; 12478c2ecf20Sopenharmony_ci int ret; 12488c2ecf20Sopenharmony_ci 12498c2ecf20Sopenharmony_ci *snr = 0; 12508c2ecf20Sopenharmony_ci 12518c2ecf20Sopenharmony_ci ret = lg216x_read_reg(state, 0x0302, &snr1); 12528c2ecf20Sopenharmony_ci if (lg_fail(ret)) 12538c2ecf20Sopenharmony_ci goto fail; 12548c2ecf20Sopenharmony_ci 12558c2ecf20Sopenharmony_ci ret = lg216x_read_reg(state, 0x0303, &snr2); 12568c2ecf20Sopenharmony_ci if (lg_fail(ret)) 12578c2ecf20Sopenharmony_ci goto fail; 12588c2ecf20Sopenharmony_ci 12598c2ecf20Sopenharmony_ci if ((snr1 == 0xba) || (snr2 == 0xfd)) 12608c2ecf20Sopenharmony_ci *snr = 0; 12618c2ecf20Sopenharmony_ci else 12628c2ecf20Sopenharmony_ci 12638c2ecf20Sopenharmony_ci *snr = ((snr1 >> 4) * 100) + ((snr1 & 0x0f) * 10) + (snr2 & 0x0f); 12648c2ecf20Sopenharmony_cifail: 12658c2ecf20Sopenharmony_ci return ret; 12668c2ecf20Sopenharmony_ci} 12678c2ecf20Sopenharmony_ci 12688c2ecf20Sopenharmony_cistatic int lg216x_read_signal_strength(struct dvb_frontend *fe, 12698c2ecf20Sopenharmony_ci u16 *strength) 12708c2ecf20Sopenharmony_ci{ 12718c2ecf20Sopenharmony_ci#if 0 12728c2ecf20Sopenharmony_ci /* borrowed from lgdt330x.c 12738c2ecf20Sopenharmony_ci * 12748c2ecf20Sopenharmony_ci * Calculate strength from SNR up to 35dB 12758c2ecf20Sopenharmony_ci * Even though the SNR can go higher than 35dB, 12768c2ecf20Sopenharmony_ci * there is some comfort factor in having a range of 12778c2ecf20Sopenharmony_ci * strong signals that can show at 100% 12788c2ecf20Sopenharmony_ci */ 12798c2ecf20Sopenharmony_ci struct lg216x_state *state = fe->demodulator_priv; 12808c2ecf20Sopenharmony_ci u16 snr; 12818c2ecf20Sopenharmony_ci int ret; 12828c2ecf20Sopenharmony_ci#endif 12838c2ecf20Sopenharmony_ci *strength = 0; 12848c2ecf20Sopenharmony_ci#if 0 12858c2ecf20Sopenharmony_ci ret = fe->ops.read_snr(fe, &snr); 12868c2ecf20Sopenharmony_ci if (lg_fail(ret)) 12878c2ecf20Sopenharmony_ci goto fail; 12888c2ecf20Sopenharmony_ci /* Rather than use the 8.8 value snr, use state->snr which is 8.24 */ 12898c2ecf20Sopenharmony_ci /* scale the range 0 - 35*2^24 into 0 - 65535 */ 12908c2ecf20Sopenharmony_ci if (state->snr >= 8960 * 0x10000) 12918c2ecf20Sopenharmony_ci *strength = 0xffff; 12928c2ecf20Sopenharmony_ci else 12938c2ecf20Sopenharmony_ci *strength = state->snr / 8960; 12948c2ecf20Sopenharmony_cifail: 12958c2ecf20Sopenharmony_ci return ret; 12968c2ecf20Sopenharmony_ci#else 12978c2ecf20Sopenharmony_ci return 0; 12988c2ecf20Sopenharmony_ci#endif 12998c2ecf20Sopenharmony_ci} 13008c2ecf20Sopenharmony_ci 13018c2ecf20Sopenharmony_ci/* ------------------------------------------------------------------------ */ 13028c2ecf20Sopenharmony_ci 13038c2ecf20Sopenharmony_cistatic int lg216x_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) 13048c2ecf20Sopenharmony_ci{ 13058c2ecf20Sopenharmony_ci#if 0 13068c2ecf20Sopenharmony_ci struct lg216x_state *state = fe->demodulator_priv; 13078c2ecf20Sopenharmony_ci int ret; 13088c2ecf20Sopenharmony_ci 13098c2ecf20Sopenharmony_ci ret = lg216x_read_rs_err_count(state, 13108c2ecf20Sopenharmony_ci &fe->dtv_property_cache.atscmh_rs_err); 13118c2ecf20Sopenharmony_ci if (lg_fail(ret)) 13128c2ecf20Sopenharmony_ci goto fail; 13138c2ecf20Sopenharmony_ci 13148c2ecf20Sopenharmony_ci *ucblocks = fe->dtv_property_cache.atscmh_rs_err; 13158c2ecf20Sopenharmony_cifail: 13168c2ecf20Sopenharmony_ci#else 13178c2ecf20Sopenharmony_ci *ucblocks = 0; 13188c2ecf20Sopenharmony_ci#endif 13198c2ecf20Sopenharmony_ci return 0; 13208c2ecf20Sopenharmony_ci} 13218c2ecf20Sopenharmony_ci 13228c2ecf20Sopenharmony_cistatic int lg216x_get_tune_settings(struct dvb_frontend *fe, 13238c2ecf20Sopenharmony_ci struct dvb_frontend_tune_settings 13248c2ecf20Sopenharmony_ci *fe_tune_settings) 13258c2ecf20Sopenharmony_ci{ 13268c2ecf20Sopenharmony_ci fe_tune_settings->min_delay_ms = 500; 13278c2ecf20Sopenharmony_ci lg_dbg("\n"); 13288c2ecf20Sopenharmony_ci return 0; 13298c2ecf20Sopenharmony_ci} 13308c2ecf20Sopenharmony_ci 13318c2ecf20Sopenharmony_cistatic void lg216x_release(struct dvb_frontend *fe) 13328c2ecf20Sopenharmony_ci{ 13338c2ecf20Sopenharmony_ci struct lg216x_state *state = fe->demodulator_priv; 13348c2ecf20Sopenharmony_ci lg_dbg("\n"); 13358c2ecf20Sopenharmony_ci kfree(state); 13368c2ecf20Sopenharmony_ci} 13378c2ecf20Sopenharmony_ci 13388c2ecf20Sopenharmony_cistatic const struct dvb_frontend_ops lg2160_ops = { 13398c2ecf20Sopenharmony_ci .delsys = { SYS_ATSCMH }, 13408c2ecf20Sopenharmony_ci .info = { 13418c2ecf20Sopenharmony_ci .name = "LG Electronics LG2160 ATSC/MH Frontend", 13428c2ecf20Sopenharmony_ci .frequency_min_hz = 54 * MHz, 13438c2ecf20Sopenharmony_ci .frequency_max_hz = 858 * MHz, 13448c2ecf20Sopenharmony_ci .frequency_stepsize_hz = 62500, 13458c2ecf20Sopenharmony_ci }, 13468c2ecf20Sopenharmony_ci .i2c_gate_ctrl = lg216x_i2c_gate_ctrl, 13478c2ecf20Sopenharmony_ci#if 0 13488c2ecf20Sopenharmony_ci .init = lg216x_init, 13498c2ecf20Sopenharmony_ci .sleep = lg216x_sleep, 13508c2ecf20Sopenharmony_ci#endif 13518c2ecf20Sopenharmony_ci .set_frontend = lg2160_set_frontend, 13528c2ecf20Sopenharmony_ci .get_frontend = lg216x_get_frontend, 13538c2ecf20Sopenharmony_ci .get_tune_settings = lg216x_get_tune_settings, 13548c2ecf20Sopenharmony_ci .read_status = lg216x_read_status, 13558c2ecf20Sopenharmony_ci#if 0 13568c2ecf20Sopenharmony_ci .read_ber = lg216x_read_ber, 13578c2ecf20Sopenharmony_ci#endif 13588c2ecf20Sopenharmony_ci .read_signal_strength = lg216x_read_signal_strength, 13598c2ecf20Sopenharmony_ci .read_snr = lg2160_read_snr, 13608c2ecf20Sopenharmony_ci .read_ucblocks = lg216x_read_ucblocks, 13618c2ecf20Sopenharmony_ci .release = lg216x_release, 13628c2ecf20Sopenharmony_ci}; 13638c2ecf20Sopenharmony_ci 13648c2ecf20Sopenharmony_cistatic const struct dvb_frontend_ops lg2161_ops = { 13658c2ecf20Sopenharmony_ci .delsys = { SYS_ATSCMH }, 13668c2ecf20Sopenharmony_ci .info = { 13678c2ecf20Sopenharmony_ci .name = "LG Electronics LG2161 ATSC/MH Frontend", 13688c2ecf20Sopenharmony_ci .frequency_min_hz = 54 * MHz, 13698c2ecf20Sopenharmony_ci .frequency_max_hz = 858 * MHz, 13708c2ecf20Sopenharmony_ci .frequency_stepsize_hz = 62500, 13718c2ecf20Sopenharmony_ci }, 13728c2ecf20Sopenharmony_ci .i2c_gate_ctrl = lg216x_i2c_gate_ctrl, 13738c2ecf20Sopenharmony_ci#if 0 13748c2ecf20Sopenharmony_ci .init = lg216x_init, 13758c2ecf20Sopenharmony_ci .sleep = lg216x_sleep, 13768c2ecf20Sopenharmony_ci#endif 13778c2ecf20Sopenharmony_ci .set_frontend = lg2160_set_frontend, 13788c2ecf20Sopenharmony_ci .get_frontend = lg216x_get_frontend, 13798c2ecf20Sopenharmony_ci .get_tune_settings = lg216x_get_tune_settings, 13808c2ecf20Sopenharmony_ci .read_status = lg216x_read_status, 13818c2ecf20Sopenharmony_ci#if 0 13828c2ecf20Sopenharmony_ci .read_ber = lg216x_read_ber, 13838c2ecf20Sopenharmony_ci#endif 13848c2ecf20Sopenharmony_ci .read_signal_strength = lg216x_read_signal_strength, 13858c2ecf20Sopenharmony_ci .read_snr = lg2161_read_snr, 13868c2ecf20Sopenharmony_ci .read_ucblocks = lg216x_read_ucblocks, 13878c2ecf20Sopenharmony_ci .release = lg216x_release, 13888c2ecf20Sopenharmony_ci}; 13898c2ecf20Sopenharmony_ci 13908c2ecf20Sopenharmony_cistruct dvb_frontend *lg2160_attach(const struct lg2160_config *config, 13918c2ecf20Sopenharmony_ci struct i2c_adapter *i2c_adap) 13928c2ecf20Sopenharmony_ci{ 13938c2ecf20Sopenharmony_ci struct lg216x_state *state = NULL; 13948c2ecf20Sopenharmony_ci 13958c2ecf20Sopenharmony_ci lg_dbg("(%d-%04x)\n", 13968c2ecf20Sopenharmony_ci i2c_adap ? i2c_adapter_id(i2c_adap) : 0, 13978c2ecf20Sopenharmony_ci config ? config->i2c_addr : 0); 13988c2ecf20Sopenharmony_ci 13998c2ecf20Sopenharmony_ci state = kzalloc(sizeof(struct lg216x_state), GFP_KERNEL); 14008c2ecf20Sopenharmony_ci if (!state) 14018c2ecf20Sopenharmony_ci return NULL; 14028c2ecf20Sopenharmony_ci 14038c2ecf20Sopenharmony_ci state->cfg = config; 14048c2ecf20Sopenharmony_ci state->i2c_adap = i2c_adap; 14058c2ecf20Sopenharmony_ci state->fic_ver = 0xff; 14068c2ecf20Sopenharmony_ci state->parade_id = 0xff; 14078c2ecf20Sopenharmony_ci 14088c2ecf20Sopenharmony_ci switch (config->lg_chip) { 14098c2ecf20Sopenharmony_ci default: 14108c2ecf20Sopenharmony_ci lg_warn("invalid chip requested, defaulting to LG2160"); 14118c2ecf20Sopenharmony_ci fallthrough; 14128c2ecf20Sopenharmony_ci case LG2160: 14138c2ecf20Sopenharmony_ci memcpy(&state->frontend.ops, &lg2160_ops, 14148c2ecf20Sopenharmony_ci sizeof(struct dvb_frontend_ops)); 14158c2ecf20Sopenharmony_ci break; 14168c2ecf20Sopenharmony_ci case LG2161: 14178c2ecf20Sopenharmony_ci memcpy(&state->frontend.ops, &lg2161_ops, 14188c2ecf20Sopenharmony_ci sizeof(struct dvb_frontend_ops)); 14198c2ecf20Sopenharmony_ci break; 14208c2ecf20Sopenharmony_ci } 14218c2ecf20Sopenharmony_ci 14228c2ecf20Sopenharmony_ci state->frontend.demodulator_priv = state; 14238c2ecf20Sopenharmony_ci state->current_frequency = -1; 14248c2ecf20Sopenharmony_ci /* parade 1 by default */ 14258c2ecf20Sopenharmony_ci state->frontend.dtv_property_cache.atscmh_parade_id = 1; 14268c2ecf20Sopenharmony_ci 14278c2ecf20Sopenharmony_ci return &state->frontend; 14288c2ecf20Sopenharmony_ci} 14298c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(lg2160_attach); 14308c2ecf20Sopenharmony_ci 14318c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("LG Electronics LG216x ATSC/MH Demodulator Driver"); 14328c2ecf20Sopenharmony_ciMODULE_AUTHOR("Michael Krufky <mkrufky@linuxtv.org>"); 14338c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 14348c2ecf20Sopenharmony_ciMODULE_VERSION("0.3"); 1435