1c942fddfSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 2e26f2ae4SMichael Krufky /* 3e26f2ae4SMichael Krufky * Support for LG2160 - ATSC/MH 4e26f2ae4SMichael Krufky * 5e26f2ae4SMichael Krufky * Copyright (C) 2010 Michael Krufky <mkrufky@linuxtv.org> 6e26f2ae4SMichael Krufky */ 7e26f2ae4SMichael Krufky 8e26f2ae4SMichael Krufky #include <linux/jiffies.h> 9e26f2ae4SMichael Krufky #include <linux/dvb/frontend.h> 10e26f2ae4SMichael Krufky #include "lg2160.h" 11e26f2ae4SMichael Krufky 12e26f2ae4SMichael Krufky static int debug; 13e26f2ae4SMichael Krufky module_param(debug, int, 0644); 14e26f2ae4SMichael Krufky MODULE_PARM_DESC(debug, "set debug level (info=1, reg=2 (or-able))"); 15e26f2ae4SMichael Krufky 16e26f2ae4SMichael Krufky #define DBG_INFO 1 17e26f2ae4SMichael Krufky #define DBG_REG 2 18e26f2ae4SMichael Krufky 19e26f2ae4SMichael Krufky #define lg_printk(kern, fmt, arg...) \ 20e26f2ae4SMichael Krufky printk(kern "%s: " fmt, __func__, ##arg) 21e26f2ae4SMichael Krufky 22e26f2ae4SMichael Krufky #define lg_info(fmt, arg...) printk(KERN_INFO "lg2160: " fmt, ##arg) 23e26f2ae4SMichael Krufky #define lg_warn(fmt, arg...) lg_printk(KERN_WARNING, fmt, ##arg) 24e26f2ae4SMichael Krufky #define lg_err(fmt, arg...) lg_printk(KERN_ERR, fmt, ##arg) 25e26f2ae4SMichael Krufky #define lg_dbg(fmt, arg...) if (debug & DBG_INFO) \ 26e26f2ae4SMichael Krufky lg_printk(KERN_DEBUG, fmt, ##arg) 27e26f2ae4SMichael Krufky #define lg_reg(fmt, arg...) if (debug & DBG_REG) \ 28e26f2ae4SMichael Krufky lg_printk(KERN_DEBUG, fmt, ##arg) 29e26f2ae4SMichael Krufky 30e26f2ae4SMichael Krufky #define lg_fail(ret) \ 31e26f2ae4SMichael Krufky ({ \ 32e26f2ae4SMichael Krufky int __ret; \ 33e26f2ae4SMichael Krufky __ret = (ret < 0); \ 34e26f2ae4SMichael Krufky if (__ret) \ 35e26f2ae4SMichael Krufky lg_err("error %d on line %d\n", ret, __LINE__); \ 36e26f2ae4SMichael Krufky __ret; \ 37e26f2ae4SMichael Krufky }) 38e26f2ae4SMichael Krufky 39e26f2ae4SMichael Krufky struct lg216x_state { 40e26f2ae4SMichael Krufky struct i2c_adapter *i2c_adap; 41e26f2ae4SMichael Krufky const struct lg2160_config *cfg; 42e26f2ae4SMichael Krufky 43e26f2ae4SMichael Krufky struct dvb_frontend frontend; 44e26f2ae4SMichael Krufky 45e26f2ae4SMichael Krufky u32 current_frequency; 46e26f2ae4SMichael Krufky u8 parade_id; 47e26f2ae4SMichael Krufky u8 fic_ver; 48e26f2ae4SMichael Krufky unsigned int last_reset; 49e26f2ae4SMichael Krufky }; 50e26f2ae4SMichael Krufky 51e26f2ae4SMichael Krufky /* ------------------------------------------------------------------------ */ 52e26f2ae4SMichael Krufky 53e26f2ae4SMichael Krufky static int lg216x_write_reg(struct lg216x_state *state, u16 reg, u8 val) 54e26f2ae4SMichael Krufky { 55e26f2ae4SMichael Krufky int ret; 56e26f2ae4SMichael Krufky u8 buf[] = { reg >> 8, reg & 0xff, val }; 57e26f2ae4SMichael Krufky struct i2c_msg msg = { 58e26f2ae4SMichael Krufky .addr = state->cfg->i2c_addr, .flags = 0, 59e26f2ae4SMichael Krufky .buf = buf, .len = 3, 60e26f2ae4SMichael Krufky }; 61e26f2ae4SMichael Krufky 62e26f2ae4SMichael Krufky lg_reg("reg: 0x%04x, val: 0x%02x\n", reg, val); 63e26f2ae4SMichael Krufky 64e26f2ae4SMichael Krufky ret = i2c_transfer(state->i2c_adap, &msg, 1); 65e26f2ae4SMichael Krufky 66e26f2ae4SMichael Krufky if (ret != 1) { 67e26f2ae4SMichael Krufky lg_err("error (addr %02x %02x <- %02x, err = %i)\n", 68e26f2ae4SMichael Krufky msg.buf[0], msg.buf[1], msg.buf[2], ret); 69e26f2ae4SMichael Krufky if (ret < 0) 70e26f2ae4SMichael Krufky return ret; 71e26f2ae4SMichael Krufky else 72e26f2ae4SMichael Krufky return -EREMOTEIO; 73e26f2ae4SMichael Krufky } 74e26f2ae4SMichael Krufky return 0; 75e26f2ae4SMichael Krufky } 76e26f2ae4SMichael Krufky 77e26f2ae4SMichael Krufky static int lg216x_read_reg(struct lg216x_state *state, u16 reg, u8 *val) 78e26f2ae4SMichael Krufky { 79e26f2ae4SMichael Krufky int ret; 80e26f2ae4SMichael Krufky u8 reg_buf[] = { reg >> 8, reg & 0xff }; 81e26f2ae4SMichael Krufky struct i2c_msg msg[] = { 82e26f2ae4SMichael Krufky { .addr = state->cfg->i2c_addr, 83e26f2ae4SMichael Krufky .flags = 0, .buf = reg_buf, .len = 2 }, 84e26f2ae4SMichael Krufky { .addr = state->cfg->i2c_addr, 85e26f2ae4SMichael Krufky .flags = I2C_M_RD, .buf = val, .len = 1 }, 86e26f2ae4SMichael Krufky }; 87e26f2ae4SMichael Krufky 88e26f2ae4SMichael Krufky lg_reg("reg: 0x%04x\n", reg); 89e26f2ae4SMichael Krufky 90e26f2ae4SMichael Krufky ret = i2c_transfer(state->i2c_adap, msg, 2); 91e26f2ae4SMichael Krufky 92e26f2ae4SMichael Krufky if (ret != 2) { 93e26f2ae4SMichael Krufky lg_err("error (addr %02x reg %04x error (ret == %i)\n", 94e26f2ae4SMichael Krufky state->cfg->i2c_addr, reg, ret); 95e26f2ae4SMichael Krufky if (ret < 0) 96e26f2ae4SMichael Krufky return ret; 97e26f2ae4SMichael Krufky else 98e26f2ae4SMichael Krufky return -EREMOTEIO; 99e26f2ae4SMichael Krufky } 100e26f2ae4SMichael Krufky return 0; 101e26f2ae4SMichael Krufky } 102e26f2ae4SMichael Krufky 103e26f2ae4SMichael Krufky struct lg216x_reg { 104e26f2ae4SMichael Krufky u16 reg; 105e26f2ae4SMichael Krufky u8 val; 106e26f2ae4SMichael Krufky }; 107e26f2ae4SMichael Krufky 108e26f2ae4SMichael Krufky static int lg216x_write_regs(struct lg216x_state *state, 109e26f2ae4SMichael Krufky struct lg216x_reg *regs, int len) 110e26f2ae4SMichael Krufky { 111e26f2ae4SMichael Krufky int i, ret; 112e26f2ae4SMichael Krufky 113e26f2ae4SMichael Krufky lg_reg("writing %d registers...\n", len); 114e26f2ae4SMichael Krufky 115bffaecc7SMichael Krufky for (i = 0; i < len; i++) { 116e26f2ae4SMichael Krufky ret = lg216x_write_reg(state, regs[i].reg, regs[i].val); 117e26f2ae4SMichael Krufky if (lg_fail(ret)) 118e26f2ae4SMichael Krufky return ret; 119e26f2ae4SMichael Krufky } 120e26f2ae4SMichael Krufky return 0; 121e26f2ae4SMichael Krufky } 122e26f2ae4SMichael Krufky 123e26f2ae4SMichael Krufky static int lg216x_set_reg_bit(struct lg216x_state *state, 124e26f2ae4SMichael Krufky u16 reg, int bit, int onoff) 125e26f2ae4SMichael Krufky { 126e26f2ae4SMichael Krufky u8 val; 127e26f2ae4SMichael Krufky int ret; 128e26f2ae4SMichael Krufky 129e26f2ae4SMichael Krufky lg_reg("reg: 0x%04x, bit: %d, level: %d\n", reg, bit, onoff); 130e26f2ae4SMichael Krufky 131e26f2ae4SMichael Krufky ret = lg216x_read_reg(state, reg, &val); 132e26f2ae4SMichael Krufky if (lg_fail(ret)) 133e26f2ae4SMichael Krufky goto fail; 134e26f2ae4SMichael Krufky 135e26f2ae4SMichael Krufky val &= ~(1 << bit); 136e26f2ae4SMichael Krufky val |= (onoff & 1) << bit; 137e26f2ae4SMichael Krufky 138e26f2ae4SMichael Krufky ret = lg216x_write_reg(state, reg, val); 139e26f2ae4SMichael Krufky lg_fail(ret); 140e26f2ae4SMichael Krufky fail: 141e26f2ae4SMichael Krufky return ret; 142e26f2ae4SMichael Krufky } 143e26f2ae4SMichael Krufky 144e26f2ae4SMichael Krufky /* ------------------------------------------------------------------------ */ 145e26f2ae4SMichael Krufky 146e26f2ae4SMichael Krufky static int lg216x_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) 147e26f2ae4SMichael Krufky { 148e26f2ae4SMichael Krufky struct lg216x_state *state = fe->demodulator_priv; 149e26f2ae4SMichael Krufky int ret; 150e26f2ae4SMichael Krufky 151e26f2ae4SMichael Krufky if (state->cfg->deny_i2c_rptr) 152e26f2ae4SMichael Krufky return 0; 153e26f2ae4SMichael Krufky 154e26f2ae4SMichael Krufky lg_dbg("(%d)\n", enable); 155e26f2ae4SMichael Krufky 156e26f2ae4SMichael Krufky ret = lg216x_set_reg_bit(state, 0x0000, 0, enable ? 0 : 1); 157e26f2ae4SMichael Krufky 158e26f2ae4SMichael Krufky msleep(1); 159e26f2ae4SMichael Krufky 160e26f2ae4SMichael Krufky return ret; 161e26f2ae4SMichael Krufky } 162e26f2ae4SMichael Krufky 163e26f2ae4SMichael Krufky static int lg216x_soft_reset(struct lg216x_state *state) 164e26f2ae4SMichael Krufky { 165e26f2ae4SMichael Krufky int ret; 166e26f2ae4SMichael Krufky 167e26f2ae4SMichael Krufky lg_dbg("\n"); 168e26f2ae4SMichael Krufky 169e26f2ae4SMichael Krufky ret = lg216x_write_reg(state, 0x0002, 0x00); 170e26f2ae4SMichael Krufky if (lg_fail(ret)) 171e26f2ae4SMichael Krufky goto fail; 172e26f2ae4SMichael Krufky 173e26f2ae4SMichael Krufky msleep(20); 174e26f2ae4SMichael Krufky ret = lg216x_write_reg(state, 0x0002, 0x01); 175e26f2ae4SMichael Krufky if (lg_fail(ret)) 176e26f2ae4SMichael Krufky goto fail; 177e26f2ae4SMichael Krufky 178e26f2ae4SMichael Krufky state->last_reset = jiffies_to_msecs(jiffies); 179e26f2ae4SMichael Krufky fail: 180e26f2ae4SMichael Krufky return ret; 181e26f2ae4SMichael Krufky } 182e26f2ae4SMichael Krufky 183e26f2ae4SMichael Krufky static int lg216x_initialize(struct lg216x_state *state) 184e26f2ae4SMichael Krufky { 185e26f2ae4SMichael Krufky int ret; 186e26f2ae4SMichael Krufky 187e26f2ae4SMichael Krufky static struct lg216x_reg lg2160_init[] = { 188e26f2ae4SMichael Krufky #if 0 189e26f2ae4SMichael Krufky { .reg = 0x0015, .val = 0xe6 }, 190e26f2ae4SMichael Krufky #else 191e26f2ae4SMichael Krufky { .reg = 0x0015, .val = 0xf7 }, 192e26f2ae4SMichael Krufky { .reg = 0x001b, .val = 0x52 }, 193e26f2ae4SMichael Krufky { .reg = 0x0208, .val = 0x00 }, 194e26f2ae4SMichael Krufky { .reg = 0x0209, .val = 0x82 }, 195e26f2ae4SMichael Krufky { .reg = 0x0210, .val = 0xf9 }, 196e26f2ae4SMichael Krufky { .reg = 0x020a, .val = 0x00 }, 197e26f2ae4SMichael Krufky { .reg = 0x020b, .val = 0x82 }, 198e26f2ae4SMichael Krufky { .reg = 0x020d, .val = 0x28 }, 199e26f2ae4SMichael Krufky { .reg = 0x020f, .val = 0x14 }, 200e26f2ae4SMichael Krufky #endif 201e26f2ae4SMichael Krufky }; 202e26f2ae4SMichael Krufky 203e26f2ae4SMichael Krufky static struct lg216x_reg lg2161_init[] = { 204e26f2ae4SMichael Krufky { .reg = 0x0000, .val = 0x41 }, 205e26f2ae4SMichael Krufky { .reg = 0x0001, .val = 0xfb }, 206e26f2ae4SMichael Krufky { .reg = 0x0216, .val = 0x00 }, 207e26f2ae4SMichael Krufky { .reg = 0x0219, .val = 0x00 }, 208e26f2ae4SMichael Krufky { .reg = 0x021b, .val = 0x55 }, 209e26f2ae4SMichael Krufky { .reg = 0x0606, .val = 0x0a }, 210e26f2ae4SMichael Krufky }; 211e26f2ae4SMichael Krufky 212e26f2ae4SMichael Krufky switch (state->cfg->lg_chip) { 213e26f2ae4SMichael Krufky case LG2160: 214e26f2ae4SMichael Krufky ret = lg216x_write_regs(state, 215e26f2ae4SMichael Krufky lg2160_init, ARRAY_SIZE(lg2160_init)); 216e26f2ae4SMichael Krufky break; 217e26f2ae4SMichael Krufky case LG2161: 218e26f2ae4SMichael Krufky ret = lg216x_write_regs(state, 219e26f2ae4SMichael Krufky lg2161_init, ARRAY_SIZE(lg2161_init)); 220e26f2ae4SMichael Krufky break; 221e26f2ae4SMichael Krufky default: 222e26f2ae4SMichael Krufky ret = -EINVAL; 223e26f2ae4SMichael Krufky break; 224e26f2ae4SMichael Krufky } 225e26f2ae4SMichael Krufky if (lg_fail(ret)) 226e26f2ae4SMichael Krufky goto fail; 227e26f2ae4SMichael Krufky 228e26f2ae4SMichael Krufky ret = lg216x_soft_reset(state); 229e26f2ae4SMichael Krufky lg_fail(ret); 230e26f2ae4SMichael Krufky fail: 231e26f2ae4SMichael Krufky return ret; 232e26f2ae4SMichael Krufky } 233e26f2ae4SMichael Krufky 234e26f2ae4SMichael Krufky /* ------------------------------------------------------------------------ */ 235e26f2ae4SMichael Krufky 236e26f2ae4SMichael Krufky static int lg216x_set_if(struct lg216x_state *state) 237e26f2ae4SMichael Krufky { 238e26f2ae4SMichael Krufky u8 val; 239e26f2ae4SMichael Krufky int ret; 240e26f2ae4SMichael Krufky 241e26f2ae4SMichael Krufky lg_dbg("%d KHz\n", state->cfg->if_khz); 242e26f2ae4SMichael Krufky 243e26f2ae4SMichael Krufky ret = lg216x_read_reg(state, 0x0132, &val); 244e26f2ae4SMichael Krufky if (lg_fail(ret)) 245e26f2ae4SMichael Krufky goto fail; 246e26f2ae4SMichael Krufky 247e26f2ae4SMichael Krufky val &= 0xfb; 248e26f2ae4SMichael Krufky val |= (0 == state->cfg->if_khz) ? 0x04 : 0x00; 249e26f2ae4SMichael Krufky 250e26f2ae4SMichael Krufky ret = lg216x_write_reg(state, 0x0132, val); 251e26f2ae4SMichael Krufky lg_fail(ret); 252e26f2ae4SMichael Krufky 253e26f2ae4SMichael Krufky /* if NOT zero IF, 6 MHz is the default */ 254e26f2ae4SMichael Krufky fail: 255e26f2ae4SMichael Krufky return ret; 256e26f2ae4SMichael Krufky } 257e26f2ae4SMichael Krufky 258e26f2ae4SMichael Krufky /* ------------------------------------------------------------------------ */ 259e26f2ae4SMichael Krufky 260e26f2ae4SMichael Krufky static int lg2160_agc_fix(struct lg216x_state *state, 261e26f2ae4SMichael Krufky int if_agc_fix, int rf_agc_fix) 262e26f2ae4SMichael Krufky { 263e26f2ae4SMichael Krufky u8 val; 264e26f2ae4SMichael Krufky int ret; 265e26f2ae4SMichael Krufky 266e26f2ae4SMichael Krufky ret = lg216x_read_reg(state, 0x0100, &val); 267e26f2ae4SMichael Krufky if (lg_fail(ret)) 268e26f2ae4SMichael Krufky goto fail; 269e26f2ae4SMichael Krufky 270e26f2ae4SMichael Krufky val &= 0xf3; 271e26f2ae4SMichael Krufky val |= (if_agc_fix) ? 0x08 : 0x00; 272e26f2ae4SMichael Krufky val |= (rf_agc_fix) ? 0x04 : 0x00; 273e26f2ae4SMichael Krufky 274e26f2ae4SMichael Krufky ret = lg216x_write_reg(state, 0x0100, val); 275e26f2ae4SMichael Krufky lg_fail(ret); 276e26f2ae4SMichael Krufky fail: 277e26f2ae4SMichael Krufky return ret; 278e26f2ae4SMichael Krufky } 279e26f2ae4SMichael Krufky 280e26f2ae4SMichael Krufky #if 0 281e26f2ae4SMichael Krufky static int lg2160_agc_freeze(struct lg216x_state *state, 282e26f2ae4SMichael Krufky int if_agc_freeze, int rf_agc_freeze) 283e26f2ae4SMichael Krufky { 284e26f2ae4SMichael Krufky u8 val; 285e26f2ae4SMichael Krufky int ret; 286e26f2ae4SMichael Krufky 287e26f2ae4SMichael Krufky ret = lg216x_read_reg(state, 0x0100, &val); 288e26f2ae4SMichael Krufky if (lg_fail(ret)) 289e26f2ae4SMichael Krufky goto fail; 290e26f2ae4SMichael Krufky 291e26f2ae4SMichael Krufky val &= 0xcf; 292e26f2ae4SMichael Krufky val |= (if_agc_freeze) ? 0x20 : 0x00; 293e26f2ae4SMichael Krufky val |= (rf_agc_freeze) ? 0x10 : 0x00; 294e26f2ae4SMichael Krufky 295e26f2ae4SMichael Krufky ret = lg216x_write_reg(state, 0x0100, val); 296e26f2ae4SMichael Krufky lg_fail(ret); 297e26f2ae4SMichael Krufky fail: 298e26f2ae4SMichael Krufky return ret; 299e26f2ae4SMichael Krufky } 300e26f2ae4SMichael Krufky #endif 301e26f2ae4SMichael Krufky 302e26f2ae4SMichael Krufky static int lg2160_agc_polarity(struct lg216x_state *state, 303e26f2ae4SMichael Krufky int if_agc_polarity, int rf_agc_polarity) 304e26f2ae4SMichael Krufky { 305e26f2ae4SMichael Krufky u8 val; 306e26f2ae4SMichael Krufky int ret; 307e26f2ae4SMichael Krufky 308e26f2ae4SMichael Krufky ret = lg216x_read_reg(state, 0x0100, &val); 309e26f2ae4SMichael Krufky if (lg_fail(ret)) 310e26f2ae4SMichael Krufky goto fail; 311e26f2ae4SMichael Krufky 312e26f2ae4SMichael Krufky val &= 0xfc; 313e26f2ae4SMichael Krufky val |= (if_agc_polarity) ? 0x02 : 0x00; 314e26f2ae4SMichael Krufky val |= (rf_agc_polarity) ? 0x01 : 0x00; 315e26f2ae4SMichael Krufky 316e26f2ae4SMichael Krufky ret = lg216x_write_reg(state, 0x0100, val); 317e26f2ae4SMichael Krufky lg_fail(ret); 318e26f2ae4SMichael Krufky fail: 319e26f2ae4SMichael Krufky return ret; 320e26f2ae4SMichael Krufky } 321e26f2ae4SMichael Krufky 322e26f2ae4SMichael Krufky static int lg2160_tuner_pwr_save_polarity(struct lg216x_state *state, 323e26f2ae4SMichael Krufky int polarity) 324e26f2ae4SMichael Krufky { 325e26f2ae4SMichael Krufky u8 val; 326e26f2ae4SMichael Krufky int ret; 327e26f2ae4SMichael Krufky 328e26f2ae4SMichael Krufky ret = lg216x_read_reg(state, 0x0008, &val); 329e26f2ae4SMichael Krufky if (lg_fail(ret)) 330e26f2ae4SMichael Krufky goto fail; 331e26f2ae4SMichael Krufky 332e26f2ae4SMichael Krufky val &= 0xfe; 333e26f2ae4SMichael Krufky val |= (polarity) ? 0x01 : 0x00; 334e26f2ae4SMichael Krufky 335e26f2ae4SMichael Krufky ret = lg216x_write_reg(state, 0x0008, val); 336e26f2ae4SMichael Krufky lg_fail(ret); 337e26f2ae4SMichael Krufky fail: 338e26f2ae4SMichael Krufky return ret; 339e26f2ae4SMichael Krufky } 340e26f2ae4SMichael Krufky 341e26f2ae4SMichael Krufky static int lg2160_spectrum_polarity(struct lg216x_state *state, 342e26f2ae4SMichael Krufky int inverted) 343e26f2ae4SMichael Krufky { 344e26f2ae4SMichael Krufky u8 val; 345e26f2ae4SMichael Krufky int ret; 346e26f2ae4SMichael Krufky 347e26f2ae4SMichael Krufky ret = lg216x_read_reg(state, 0x0132, &val); 348e26f2ae4SMichael Krufky if (lg_fail(ret)) 349e26f2ae4SMichael Krufky goto fail; 350e26f2ae4SMichael Krufky 351e26f2ae4SMichael Krufky val &= 0xfd; 352e26f2ae4SMichael Krufky val |= (inverted) ? 0x02 : 0x00; 353e26f2ae4SMichael Krufky 354e26f2ae4SMichael Krufky ret = lg216x_write_reg(state, 0x0132, val); 355e26f2ae4SMichael Krufky lg_fail(ret); 356e26f2ae4SMichael Krufky fail: 357e26f2ae4SMichael Krufky return lg216x_soft_reset(state); 358e26f2ae4SMichael Krufky } 359e26f2ae4SMichael Krufky 360e26f2ae4SMichael Krufky static int lg2160_tuner_pwr_save(struct lg216x_state *state, int onoff) 361e26f2ae4SMichael Krufky { 362e26f2ae4SMichael Krufky u8 val; 363e26f2ae4SMichael Krufky int ret; 364e26f2ae4SMichael Krufky 365e26f2ae4SMichael Krufky ret = lg216x_read_reg(state, 0x0007, &val); 366e26f2ae4SMichael Krufky if (lg_fail(ret)) 367e26f2ae4SMichael Krufky goto fail; 368e26f2ae4SMichael Krufky 369e26f2ae4SMichael Krufky val &= 0xbf; 370e26f2ae4SMichael Krufky val |= (onoff) ? 0x40 : 0x00; 371e26f2ae4SMichael Krufky 372e26f2ae4SMichael Krufky ret = lg216x_write_reg(state, 0x0007, val); 373e26f2ae4SMichael Krufky lg_fail(ret); 374e26f2ae4SMichael Krufky fail: 375e26f2ae4SMichael Krufky return ret; 376e26f2ae4SMichael Krufky } 377e26f2ae4SMichael Krufky 378e26f2ae4SMichael Krufky static int lg216x_set_parade(struct lg216x_state *state, int id) 379e26f2ae4SMichael Krufky { 380e26f2ae4SMichael Krufky int ret; 381e26f2ae4SMichael Krufky 382e26f2ae4SMichael Krufky ret = lg216x_write_reg(state, 0x013e, id & 0x7f); 383e26f2ae4SMichael Krufky if (lg_fail(ret)) 384e26f2ae4SMichael Krufky goto fail; 385e26f2ae4SMichael Krufky 386e26f2ae4SMichael Krufky state->parade_id = id & 0x7f; 387e26f2ae4SMichael Krufky fail: 388e26f2ae4SMichael Krufky return ret; 389e26f2ae4SMichael Krufky } 390e26f2ae4SMichael Krufky 391e26f2ae4SMichael Krufky static int lg216x_set_ensemble(struct lg216x_state *state, int id) 392e26f2ae4SMichael Krufky { 393e26f2ae4SMichael Krufky int ret; 394e26f2ae4SMichael Krufky u16 reg; 395e26f2ae4SMichael Krufky u8 val; 396e26f2ae4SMichael Krufky 397e26f2ae4SMichael Krufky switch (state->cfg->lg_chip) { 398e26f2ae4SMichael Krufky case LG2160: 399e26f2ae4SMichael Krufky reg = 0x0400; 400e26f2ae4SMichael Krufky break; 401e26f2ae4SMichael Krufky case LG2161: 4025444a1b7SMauro Carvalho Chehab default: 403e26f2ae4SMichael Krufky reg = 0x0500; 404e26f2ae4SMichael Krufky break; 405e26f2ae4SMichael Krufky } 406e26f2ae4SMichael Krufky 407e26f2ae4SMichael Krufky ret = lg216x_read_reg(state, reg, &val); 408e26f2ae4SMichael Krufky if (lg_fail(ret)) 409e26f2ae4SMichael Krufky goto fail; 410e26f2ae4SMichael Krufky 411e26f2ae4SMichael Krufky val &= 0xfe; 412e26f2ae4SMichael Krufky val |= (id) ? 0x01 : 0x00; 413e26f2ae4SMichael Krufky 414e26f2ae4SMichael Krufky ret = lg216x_write_reg(state, reg, val); 415e26f2ae4SMichael Krufky lg_fail(ret); 416e26f2ae4SMichael Krufky fail: 417e26f2ae4SMichael Krufky return ret; 418e26f2ae4SMichael Krufky } 419e26f2ae4SMichael Krufky 420e26f2ae4SMichael Krufky static int lg2160_set_spi_clock(struct lg216x_state *state) 421e26f2ae4SMichael Krufky { 422e26f2ae4SMichael Krufky u8 val; 423e26f2ae4SMichael Krufky int ret; 424e26f2ae4SMichael Krufky 425e26f2ae4SMichael Krufky ret = lg216x_read_reg(state, 0x0014, &val); 426e26f2ae4SMichael Krufky if (lg_fail(ret)) 427e26f2ae4SMichael Krufky goto fail; 428e26f2ae4SMichael Krufky 429e26f2ae4SMichael Krufky val &= 0xf3; 430e26f2ae4SMichael Krufky val |= (state->cfg->spi_clock << 2); 431e26f2ae4SMichael Krufky 432e26f2ae4SMichael Krufky ret = lg216x_write_reg(state, 0x0014, val); 433e26f2ae4SMichael Krufky lg_fail(ret); 434e26f2ae4SMichael Krufky fail: 435e26f2ae4SMichael Krufky return ret; 436e26f2ae4SMichael Krufky } 437e26f2ae4SMichael Krufky 438e26f2ae4SMichael Krufky static int lg2161_set_output_interface(struct lg216x_state *state) 439e26f2ae4SMichael Krufky { 440e26f2ae4SMichael Krufky u8 val; 441e26f2ae4SMichael Krufky int ret; 442e26f2ae4SMichael Krufky 443e26f2ae4SMichael Krufky ret = lg216x_read_reg(state, 0x0014, &val); 444e26f2ae4SMichael Krufky if (lg_fail(ret)) 445e26f2ae4SMichael Krufky goto fail; 446e26f2ae4SMichael Krufky 447e26f2ae4SMichael Krufky val &= ~0x07; 448e26f2ae4SMichael Krufky val |= state->cfg->output_if; /* FIXME: needs sanity check */ 449e26f2ae4SMichael Krufky 450e26f2ae4SMichael Krufky ret = lg216x_write_reg(state, 0x0014, val); 451e26f2ae4SMichael Krufky lg_fail(ret); 452e26f2ae4SMichael Krufky fail: 453e26f2ae4SMichael Krufky return ret; 454e26f2ae4SMichael Krufky } 455e26f2ae4SMichael Krufky 456e26f2ae4SMichael Krufky static int lg216x_enable_fic(struct lg216x_state *state, int onoff) 457e26f2ae4SMichael Krufky { 458e26f2ae4SMichael Krufky int ret; 459e26f2ae4SMichael Krufky 460e26f2ae4SMichael Krufky ret = lg216x_write_reg(state, 0x0017, 0x23); 461e26f2ae4SMichael Krufky if (lg_fail(ret)) 462e26f2ae4SMichael Krufky goto fail; 463e26f2ae4SMichael Krufky 464e26f2ae4SMichael Krufky ret = lg216x_write_reg(state, 0x0016, 0xfc); 465e26f2ae4SMichael Krufky if (lg_fail(ret)) 466e26f2ae4SMichael Krufky goto fail; 467e26f2ae4SMichael Krufky 468e26f2ae4SMichael Krufky switch (state->cfg->lg_chip) { 469e26f2ae4SMichael Krufky case LG2160: 470e26f2ae4SMichael Krufky ret = lg216x_write_reg(state, 0x0016, 471e26f2ae4SMichael Krufky 0xfc | ((onoff) ? 0x02 : 0x00)); 472e26f2ae4SMichael Krufky break; 473e26f2ae4SMichael Krufky case LG2161: 474e26f2ae4SMichael Krufky ret = lg216x_write_reg(state, 0x0016, (onoff) ? 0x10 : 0x00); 475e26f2ae4SMichael Krufky break; 476e26f2ae4SMichael Krufky } 477e26f2ae4SMichael Krufky if (lg_fail(ret)) 478e26f2ae4SMichael Krufky goto fail; 479e26f2ae4SMichael Krufky 480e26f2ae4SMichael Krufky ret = lg216x_initialize(state); 481e26f2ae4SMichael Krufky if (lg_fail(ret)) 482e26f2ae4SMichael Krufky goto fail; 483e26f2ae4SMichael Krufky 484e26f2ae4SMichael Krufky if (onoff) { 485e26f2ae4SMichael Krufky ret = lg216x_write_reg(state, 0x0017, 0x03); 486e26f2ae4SMichael Krufky lg_fail(ret); 487e26f2ae4SMichael Krufky } 488e26f2ae4SMichael Krufky fail: 489e26f2ae4SMichael Krufky return ret; 490e26f2ae4SMichael Krufky } 491e26f2ae4SMichael Krufky 492e26f2ae4SMichael Krufky /* ------------------------------------------------------------------------ */ 493e26f2ae4SMichael Krufky 494e26f2ae4SMichael Krufky static int lg216x_get_fic_version(struct lg216x_state *state, u8 *ficver) 495e26f2ae4SMichael Krufky { 496e26f2ae4SMichael Krufky u8 val; 497e26f2ae4SMichael Krufky int ret; 498e26f2ae4SMichael Krufky 499e26f2ae4SMichael Krufky *ficver = 0xff; /* invalid value */ 500e26f2ae4SMichael Krufky 501e26f2ae4SMichael Krufky ret = lg216x_read_reg(state, 0x0128, &val); 502e26f2ae4SMichael Krufky if (lg_fail(ret)) 503e26f2ae4SMichael Krufky goto fail; 504e26f2ae4SMichael Krufky 505e26f2ae4SMichael Krufky *ficver = (val >> 3) & 0x1f; 506e26f2ae4SMichael Krufky fail: 507e26f2ae4SMichael Krufky return ret; 508e26f2ae4SMichael Krufky } 509e26f2ae4SMichael Krufky 510e26f2ae4SMichael Krufky #if 0 511e26f2ae4SMichael Krufky static int lg2160_get_parade_id(struct lg216x_state *state, u8 *id) 512e26f2ae4SMichael Krufky { 513e26f2ae4SMichael Krufky u8 val; 514e26f2ae4SMichael Krufky int ret; 515e26f2ae4SMichael Krufky 516e26f2ae4SMichael Krufky *id = 0xff; /* invalid value */ 517e26f2ae4SMichael Krufky 518e26f2ae4SMichael Krufky ret = lg216x_read_reg(state, 0x0123, &val); 519e26f2ae4SMichael Krufky if (lg_fail(ret)) 520e26f2ae4SMichael Krufky goto fail; 521e26f2ae4SMichael Krufky 522e26f2ae4SMichael Krufky *id = val & 0x7f; 523e26f2ae4SMichael Krufky fail: 524e26f2ae4SMichael Krufky return ret; 525e26f2ae4SMichael Krufky } 526e26f2ae4SMichael Krufky #endif 527e26f2ae4SMichael Krufky 528e26f2ae4SMichael Krufky static int lg216x_get_nog(struct lg216x_state *state, u8 *nog) 529e26f2ae4SMichael Krufky { 530e26f2ae4SMichael Krufky u8 val; 531e26f2ae4SMichael Krufky int ret; 532e26f2ae4SMichael Krufky 533e26f2ae4SMichael Krufky *nog = 0xff; /* invalid value */ 534e26f2ae4SMichael Krufky 535e26f2ae4SMichael Krufky ret = lg216x_read_reg(state, 0x0124, &val); 536e26f2ae4SMichael Krufky if (lg_fail(ret)) 537e26f2ae4SMichael Krufky goto fail; 538e26f2ae4SMichael Krufky 539e26f2ae4SMichael Krufky *nog = ((val >> 4) & 0x07) + 1; 540e26f2ae4SMichael Krufky fail: 541e26f2ae4SMichael Krufky return ret; 542e26f2ae4SMichael Krufky } 543e26f2ae4SMichael Krufky 544e26f2ae4SMichael Krufky static int lg216x_get_tnog(struct lg216x_state *state, u8 *tnog) 545e26f2ae4SMichael Krufky { 546e26f2ae4SMichael Krufky u8 val; 547e26f2ae4SMichael Krufky int ret; 548e26f2ae4SMichael Krufky 549e26f2ae4SMichael Krufky *tnog = 0xff; /* invalid value */ 550e26f2ae4SMichael Krufky 551e26f2ae4SMichael Krufky ret = lg216x_read_reg(state, 0x0125, &val); 552e26f2ae4SMichael Krufky if (lg_fail(ret)) 553e26f2ae4SMichael Krufky goto fail; 554e26f2ae4SMichael Krufky 555e26f2ae4SMichael Krufky *tnog = val & 0x1f; 556e26f2ae4SMichael Krufky fail: 557e26f2ae4SMichael Krufky return ret; 558e26f2ae4SMichael Krufky } 559e26f2ae4SMichael Krufky 560e26f2ae4SMichael Krufky static int lg216x_get_sgn(struct lg216x_state *state, u8 *sgn) 561e26f2ae4SMichael Krufky { 562e26f2ae4SMichael Krufky u8 val; 563e26f2ae4SMichael Krufky int ret; 564e26f2ae4SMichael Krufky 565e26f2ae4SMichael Krufky *sgn = 0xff; /* invalid value */ 566e26f2ae4SMichael Krufky 567e26f2ae4SMichael Krufky ret = lg216x_read_reg(state, 0x0124, &val); 568e26f2ae4SMichael Krufky if (lg_fail(ret)) 569e26f2ae4SMichael Krufky goto fail; 570e26f2ae4SMichael Krufky 571e26f2ae4SMichael Krufky *sgn = val & 0x0f; 572e26f2ae4SMichael Krufky fail: 573e26f2ae4SMichael Krufky return ret; 574e26f2ae4SMichael Krufky } 575e26f2ae4SMichael Krufky 576e26f2ae4SMichael Krufky static int lg216x_get_prc(struct lg216x_state *state, u8 *prc) 577e26f2ae4SMichael Krufky { 578e26f2ae4SMichael Krufky u8 val; 579e26f2ae4SMichael Krufky int ret; 580e26f2ae4SMichael Krufky 581e26f2ae4SMichael Krufky *prc = 0xff; /* invalid value */ 582e26f2ae4SMichael Krufky 583e26f2ae4SMichael Krufky ret = lg216x_read_reg(state, 0x0125, &val); 584e26f2ae4SMichael Krufky if (lg_fail(ret)) 585e26f2ae4SMichael Krufky goto fail; 586e26f2ae4SMichael Krufky 587e26f2ae4SMichael Krufky *prc = ((val >> 5) & 0x07) + 1; 588e26f2ae4SMichael Krufky fail: 589e26f2ae4SMichael Krufky return ret; 590e26f2ae4SMichael Krufky } 591e26f2ae4SMichael Krufky 592e26f2ae4SMichael Krufky /* ------------------------------------------------------------------------ */ 593e26f2ae4SMichael Krufky 594e26f2ae4SMichael Krufky static int lg216x_get_rs_frame_mode(struct lg216x_state *state, 595e26f2ae4SMichael Krufky enum atscmh_rs_frame_mode *rs_framemode) 596e26f2ae4SMichael Krufky { 597e26f2ae4SMichael Krufky u8 val; 598e26f2ae4SMichael Krufky int ret; 599e26f2ae4SMichael Krufky 600e26f2ae4SMichael Krufky switch (state->cfg->lg_chip) { 601e26f2ae4SMichael Krufky case LG2160: 602e26f2ae4SMichael Krufky ret = lg216x_read_reg(state, 0x0410, &val); 603e26f2ae4SMichael Krufky break; 604e26f2ae4SMichael Krufky case LG2161: 605e26f2ae4SMichael Krufky ret = lg216x_read_reg(state, 0x0513, &val); 606e26f2ae4SMichael Krufky break; 607e26f2ae4SMichael Krufky default: 608e26f2ae4SMichael Krufky ret = -EINVAL; 609e26f2ae4SMichael Krufky } 610e26f2ae4SMichael Krufky if (lg_fail(ret)) 611e26f2ae4SMichael Krufky goto fail; 612e26f2ae4SMichael Krufky 613e26f2ae4SMichael Krufky switch ((val >> 4) & 0x03) { 614e26f2ae4SMichael Krufky #if 1 615e26f2ae4SMichael Krufky default: 616e26f2ae4SMichael Krufky #endif 617e26f2ae4SMichael Krufky case 0x00: 618e26f2ae4SMichael Krufky *rs_framemode = ATSCMH_RSFRAME_PRI_ONLY; 619e26f2ae4SMichael Krufky break; 620e26f2ae4SMichael Krufky case 0x01: 621e26f2ae4SMichael Krufky *rs_framemode = ATSCMH_RSFRAME_PRI_SEC; 622e26f2ae4SMichael Krufky break; 623e26f2ae4SMichael Krufky #if 0 624e26f2ae4SMichael Krufky default: 625e26f2ae4SMichael Krufky *rs_framemode = ATSCMH_RSFRAME_RES; 626e26f2ae4SMichael Krufky break; 627e26f2ae4SMichael Krufky #endif 628e26f2ae4SMichael Krufky } 629e26f2ae4SMichael Krufky fail: 630e26f2ae4SMichael Krufky return ret; 631e26f2ae4SMichael Krufky } 632e26f2ae4SMichael Krufky 633e26f2ae4SMichael Krufky static 634e26f2ae4SMichael Krufky int lg216x_get_rs_frame_ensemble(struct lg216x_state *state, 635e26f2ae4SMichael Krufky enum atscmh_rs_frame_ensemble *rs_frame_ens) 636e26f2ae4SMichael Krufky { 637e26f2ae4SMichael Krufky u8 val; 638e26f2ae4SMichael Krufky int ret; 639e26f2ae4SMichael Krufky 640e26f2ae4SMichael Krufky switch (state->cfg->lg_chip) { 641e26f2ae4SMichael Krufky case LG2160: 642e26f2ae4SMichael Krufky ret = lg216x_read_reg(state, 0x0400, &val); 643e26f2ae4SMichael Krufky break; 644e26f2ae4SMichael Krufky case LG2161: 645e26f2ae4SMichael Krufky ret = lg216x_read_reg(state, 0x0500, &val); 646e26f2ae4SMichael Krufky break; 647e26f2ae4SMichael Krufky default: 648e26f2ae4SMichael Krufky ret = -EINVAL; 649e26f2ae4SMichael Krufky } 650e26f2ae4SMichael Krufky if (lg_fail(ret)) 651e26f2ae4SMichael Krufky goto fail; 652e26f2ae4SMichael Krufky 653e26f2ae4SMichael Krufky val &= 0x01; 654e26f2ae4SMichael Krufky *rs_frame_ens = (enum atscmh_rs_frame_ensemble) val; 655e26f2ae4SMichael Krufky fail: 656e26f2ae4SMichael Krufky return ret; 657e26f2ae4SMichael Krufky } 658e26f2ae4SMichael Krufky 659e26f2ae4SMichael Krufky static int lg216x_get_rs_code_mode(struct lg216x_state *state, 660e26f2ae4SMichael Krufky enum atscmh_rs_code_mode *rs_code_pri, 661e26f2ae4SMichael Krufky enum atscmh_rs_code_mode *rs_code_sec) 662e26f2ae4SMichael Krufky { 663e26f2ae4SMichael Krufky u8 val; 664e26f2ae4SMichael Krufky int ret; 665e26f2ae4SMichael Krufky 666e26f2ae4SMichael Krufky switch (state->cfg->lg_chip) { 667e26f2ae4SMichael Krufky case LG2160: 668e26f2ae4SMichael Krufky ret = lg216x_read_reg(state, 0x0410, &val); 669e26f2ae4SMichael Krufky break; 670e26f2ae4SMichael Krufky case LG2161: 671e26f2ae4SMichael Krufky ret = lg216x_read_reg(state, 0x0513, &val); 672e26f2ae4SMichael Krufky break; 673e26f2ae4SMichael Krufky default: 674e26f2ae4SMichael Krufky ret = -EINVAL; 675e26f2ae4SMichael Krufky } 676e26f2ae4SMichael Krufky if (lg_fail(ret)) 677e26f2ae4SMichael Krufky goto fail; 678e26f2ae4SMichael Krufky 679e26f2ae4SMichael Krufky *rs_code_pri = (enum atscmh_rs_code_mode) ((val >> 2) & 0x03); 680e26f2ae4SMichael Krufky *rs_code_sec = (enum atscmh_rs_code_mode) (val & 0x03); 681e26f2ae4SMichael Krufky fail: 682e26f2ae4SMichael Krufky return ret; 683e26f2ae4SMichael Krufky } 684e26f2ae4SMichael Krufky 685e26f2ae4SMichael Krufky static int lg216x_get_sccc_block_mode(struct lg216x_state *state, 686e26f2ae4SMichael Krufky enum atscmh_sccc_block_mode *sccc_block) 687e26f2ae4SMichael Krufky { 688e26f2ae4SMichael Krufky u8 val; 689e26f2ae4SMichael Krufky int ret; 690e26f2ae4SMichael Krufky 691e26f2ae4SMichael Krufky switch (state->cfg->lg_chip) { 692e26f2ae4SMichael Krufky case LG2160: 693e26f2ae4SMichael Krufky ret = lg216x_read_reg(state, 0x0315, &val); 694e26f2ae4SMichael Krufky break; 695e26f2ae4SMichael Krufky case LG2161: 696e26f2ae4SMichael Krufky ret = lg216x_read_reg(state, 0x0511, &val); 697e26f2ae4SMichael Krufky break; 698e26f2ae4SMichael Krufky default: 699e26f2ae4SMichael Krufky ret = -EINVAL; 700e26f2ae4SMichael Krufky } 701e26f2ae4SMichael Krufky if (lg_fail(ret)) 702e26f2ae4SMichael Krufky goto fail; 703e26f2ae4SMichael Krufky 704e26f2ae4SMichael Krufky switch (val & 0x03) { 705e26f2ae4SMichael Krufky case 0x00: 706e26f2ae4SMichael Krufky *sccc_block = ATSCMH_SCCC_BLK_SEP; 707e26f2ae4SMichael Krufky break; 708e26f2ae4SMichael Krufky case 0x01: 709e26f2ae4SMichael Krufky *sccc_block = ATSCMH_SCCC_BLK_COMB; 710e26f2ae4SMichael Krufky break; 711e26f2ae4SMichael Krufky default: 712e26f2ae4SMichael Krufky *sccc_block = ATSCMH_SCCC_BLK_RES; 713e26f2ae4SMichael Krufky break; 714e26f2ae4SMichael Krufky } 715e26f2ae4SMichael Krufky fail: 716e26f2ae4SMichael Krufky return ret; 717e26f2ae4SMichael Krufky } 718e26f2ae4SMichael Krufky 719e26f2ae4SMichael Krufky static int lg216x_get_sccc_code_mode(struct lg216x_state *state, 720e26f2ae4SMichael Krufky enum atscmh_sccc_code_mode *mode_a, 721e26f2ae4SMichael Krufky enum atscmh_sccc_code_mode *mode_b, 722e26f2ae4SMichael Krufky enum atscmh_sccc_code_mode *mode_c, 723e26f2ae4SMichael Krufky enum atscmh_sccc_code_mode *mode_d) 724e26f2ae4SMichael Krufky { 725e26f2ae4SMichael Krufky u8 val; 726e26f2ae4SMichael Krufky int ret; 727e26f2ae4SMichael Krufky 728e26f2ae4SMichael Krufky switch (state->cfg->lg_chip) { 729e26f2ae4SMichael Krufky case LG2160: 730e26f2ae4SMichael Krufky ret = lg216x_read_reg(state, 0x0316, &val); 731e26f2ae4SMichael Krufky break; 732e26f2ae4SMichael Krufky case LG2161: 733e26f2ae4SMichael Krufky ret = lg216x_read_reg(state, 0x0512, &val); 734e26f2ae4SMichael Krufky break; 735e26f2ae4SMichael Krufky default: 736e26f2ae4SMichael Krufky ret = -EINVAL; 737e26f2ae4SMichael Krufky } 738e26f2ae4SMichael Krufky if (lg_fail(ret)) 739e26f2ae4SMichael Krufky goto fail; 740e26f2ae4SMichael Krufky 741e26f2ae4SMichael Krufky switch ((val >> 6) & 0x03) { 742e26f2ae4SMichael Krufky case 0x00: 743e26f2ae4SMichael Krufky *mode_a = ATSCMH_SCCC_CODE_HLF; 744e26f2ae4SMichael Krufky break; 745e26f2ae4SMichael Krufky case 0x01: 746e26f2ae4SMichael Krufky *mode_a = ATSCMH_SCCC_CODE_QTR; 747e26f2ae4SMichael Krufky break; 748e26f2ae4SMichael Krufky default: 749e26f2ae4SMichael Krufky *mode_a = ATSCMH_SCCC_CODE_RES; 750e26f2ae4SMichael Krufky break; 751e26f2ae4SMichael Krufky } 752e26f2ae4SMichael Krufky 753e26f2ae4SMichael Krufky switch ((val >> 4) & 0x03) { 754e26f2ae4SMichael Krufky case 0x00: 755e26f2ae4SMichael Krufky *mode_b = ATSCMH_SCCC_CODE_HLF; 756e26f2ae4SMichael Krufky break; 757e26f2ae4SMichael Krufky case 0x01: 758e26f2ae4SMichael Krufky *mode_b = ATSCMH_SCCC_CODE_QTR; 759e26f2ae4SMichael Krufky break; 760e26f2ae4SMichael Krufky default: 761e26f2ae4SMichael Krufky *mode_b = ATSCMH_SCCC_CODE_RES; 762e26f2ae4SMichael Krufky break; 763e26f2ae4SMichael Krufky } 764e26f2ae4SMichael Krufky 765e26f2ae4SMichael Krufky switch ((val >> 2) & 0x03) { 766e26f2ae4SMichael Krufky case 0x00: 767e26f2ae4SMichael Krufky *mode_c = ATSCMH_SCCC_CODE_HLF; 768e26f2ae4SMichael Krufky break; 769e26f2ae4SMichael Krufky case 0x01: 770e26f2ae4SMichael Krufky *mode_c = ATSCMH_SCCC_CODE_QTR; 771e26f2ae4SMichael Krufky break; 772e26f2ae4SMichael Krufky default: 773e26f2ae4SMichael Krufky *mode_c = ATSCMH_SCCC_CODE_RES; 774e26f2ae4SMichael Krufky break; 775e26f2ae4SMichael Krufky } 776e26f2ae4SMichael Krufky 777e26f2ae4SMichael Krufky switch (val & 0x03) { 778e26f2ae4SMichael Krufky case 0x00: 779e26f2ae4SMichael Krufky *mode_d = ATSCMH_SCCC_CODE_HLF; 780e26f2ae4SMichael Krufky break; 781e26f2ae4SMichael Krufky case 0x01: 782e26f2ae4SMichael Krufky *mode_d = ATSCMH_SCCC_CODE_QTR; 783e26f2ae4SMichael Krufky break; 784e26f2ae4SMichael Krufky default: 785e26f2ae4SMichael Krufky *mode_d = ATSCMH_SCCC_CODE_RES; 786e26f2ae4SMichael Krufky break; 787e26f2ae4SMichael Krufky } 788e26f2ae4SMichael Krufky fail: 789e26f2ae4SMichael Krufky return ret; 790e26f2ae4SMichael Krufky } 791e26f2ae4SMichael Krufky 792e26f2ae4SMichael Krufky /* ------------------------------------------------------------------------ */ 793e26f2ae4SMichael Krufky 79410d67371SMichael Krufky #if 0 795e26f2ae4SMichael Krufky static int lg216x_read_fic_err_count(struct lg216x_state *state, u8 *err) 796e26f2ae4SMichael Krufky { 797e26f2ae4SMichael Krufky u8 fic_err; 798e26f2ae4SMichael Krufky int ret; 799e26f2ae4SMichael Krufky 800e26f2ae4SMichael Krufky *err = 0; 801e26f2ae4SMichael Krufky 802e26f2ae4SMichael Krufky switch (state->cfg->lg_chip) { 803e26f2ae4SMichael Krufky case LG2160: 804e26f2ae4SMichael Krufky ret = lg216x_read_reg(state, 0x0012, &fic_err); 805e26f2ae4SMichael Krufky break; 806e26f2ae4SMichael Krufky case LG2161: 807e26f2ae4SMichael Krufky ret = lg216x_read_reg(state, 0x001e, &fic_err); 808e26f2ae4SMichael Krufky break; 809e26f2ae4SMichael Krufky } 810e26f2ae4SMichael Krufky if (lg_fail(ret)) 811e26f2ae4SMichael Krufky goto fail; 812e26f2ae4SMichael Krufky 813e26f2ae4SMichael Krufky *err = fic_err; 814e26f2ae4SMichael Krufky fail: 815e26f2ae4SMichael Krufky return ret; 816e26f2ae4SMichael Krufky } 817e26f2ae4SMichael Krufky 818e26f2ae4SMichael Krufky static int lg2160_read_crc_err_count(struct lg216x_state *state, u16 *err) 819e26f2ae4SMichael Krufky { 820e26f2ae4SMichael Krufky u8 crc_err1, crc_err2; 821e26f2ae4SMichael Krufky int ret; 822e26f2ae4SMichael Krufky 823e26f2ae4SMichael Krufky *err = 0; 824e26f2ae4SMichael Krufky 825e26f2ae4SMichael Krufky ret = lg216x_read_reg(state, 0x0411, &crc_err1); 826e26f2ae4SMichael Krufky if (lg_fail(ret)) 827e26f2ae4SMichael Krufky goto fail; 828e26f2ae4SMichael Krufky 829e26f2ae4SMichael Krufky ret = lg216x_read_reg(state, 0x0412, &crc_err2); 830e26f2ae4SMichael Krufky if (lg_fail(ret)) 831e26f2ae4SMichael Krufky goto fail; 832e26f2ae4SMichael Krufky 833e26f2ae4SMichael Krufky *err = (u16)(((crc_err2 & 0x0f) << 8) | crc_err1); 834e26f2ae4SMichael Krufky fail: 835e26f2ae4SMichael Krufky return ret; 836e26f2ae4SMichael Krufky } 837e26f2ae4SMichael Krufky 838e26f2ae4SMichael Krufky static int lg2161_read_crc_err_count(struct lg216x_state *state, u16 *err) 839e26f2ae4SMichael Krufky { 840e26f2ae4SMichael Krufky u8 crc_err; 841e26f2ae4SMichael Krufky int ret; 842e26f2ae4SMichael Krufky 843e26f2ae4SMichael Krufky *err = 0; 844e26f2ae4SMichael Krufky 845e26f2ae4SMichael Krufky ret = lg216x_read_reg(state, 0x0612, &crc_err); 846e26f2ae4SMichael Krufky if (lg_fail(ret)) 847e26f2ae4SMichael Krufky goto fail; 848e26f2ae4SMichael Krufky 849e26f2ae4SMichael Krufky *err = (u16)crc_err; 850e26f2ae4SMichael Krufky fail: 851e26f2ae4SMichael Krufky return ret; 852e26f2ae4SMichael Krufky } 853e26f2ae4SMichael Krufky 854e26f2ae4SMichael Krufky static int lg216x_read_crc_err_count(struct lg216x_state *state, u16 *err) 855e26f2ae4SMichael Krufky { 856e26f2ae4SMichael Krufky int ret; 857e26f2ae4SMichael Krufky switch (state->cfg->lg_chip) { 858e26f2ae4SMichael Krufky case LG2160: 859e26f2ae4SMichael Krufky ret = lg2160_read_crc_err_count(state, err); 860e26f2ae4SMichael Krufky break; 861e26f2ae4SMichael Krufky case LG2161: 862e26f2ae4SMichael Krufky ret = lg2161_read_crc_err_count(state, err); 863e26f2ae4SMichael Krufky break; 864e26f2ae4SMichael Krufky default: 865e26f2ae4SMichael Krufky ret = -EINVAL; 866e26f2ae4SMichael Krufky break; 867e26f2ae4SMichael Krufky } 868e26f2ae4SMichael Krufky return ret; 869e26f2ae4SMichael Krufky } 870e26f2ae4SMichael Krufky 871e26f2ae4SMichael Krufky static int lg2160_read_rs_err_count(struct lg216x_state *state, u16 *err) 872e26f2ae4SMichael Krufky { 873e26f2ae4SMichael Krufky u8 rs_err1, rs_err2; 874e26f2ae4SMichael Krufky int ret; 875e26f2ae4SMichael Krufky 876e26f2ae4SMichael Krufky *err = 0; 877e26f2ae4SMichael Krufky 878e26f2ae4SMichael Krufky ret = lg216x_read_reg(state, 0x0413, &rs_err1); 879e26f2ae4SMichael Krufky if (lg_fail(ret)) 880e26f2ae4SMichael Krufky goto fail; 881e26f2ae4SMichael Krufky 882e26f2ae4SMichael Krufky ret = lg216x_read_reg(state, 0x0414, &rs_err2); 883e26f2ae4SMichael Krufky if (lg_fail(ret)) 884e26f2ae4SMichael Krufky goto fail; 885e26f2ae4SMichael Krufky 886e26f2ae4SMichael Krufky *err = (u16)(((rs_err2 & 0x0f) << 8) | rs_err1); 887e26f2ae4SMichael Krufky fail: 888e26f2ae4SMichael Krufky return ret; 889e26f2ae4SMichael Krufky } 890e26f2ae4SMichael Krufky 891e26f2ae4SMichael Krufky static int lg2161_read_rs_err_count(struct lg216x_state *state, u16 *err) 892e26f2ae4SMichael Krufky { 893e26f2ae4SMichael Krufky u8 rs_err1, rs_err2; 894e26f2ae4SMichael Krufky int ret; 895e26f2ae4SMichael Krufky 896e26f2ae4SMichael Krufky *err = 0; 897e26f2ae4SMichael Krufky 898e26f2ae4SMichael Krufky ret = lg216x_read_reg(state, 0x0613, &rs_err1); 899e26f2ae4SMichael Krufky if (lg_fail(ret)) 900e26f2ae4SMichael Krufky goto fail; 901e26f2ae4SMichael Krufky 902e26f2ae4SMichael Krufky ret = lg216x_read_reg(state, 0x0614, &rs_err2); 903e26f2ae4SMichael Krufky if (lg_fail(ret)) 904e26f2ae4SMichael Krufky goto fail; 905e26f2ae4SMichael Krufky 906e26f2ae4SMichael Krufky *err = (u16)((rs_err1 << 8) | rs_err2); 907e26f2ae4SMichael Krufky fail: 908e26f2ae4SMichael Krufky return ret; 909e26f2ae4SMichael Krufky } 910e26f2ae4SMichael Krufky 911e26f2ae4SMichael Krufky static int lg216x_read_rs_err_count(struct lg216x_state *state, u16 *err) 912e26f2ae4SMichael Krufky { 913e26f2ae4SMichael Krufky int ret; 914e26f2ae4SMichael Krufky switch (state->cfg->lg_chip) { 915e26f2ae4SMichael Krufky case LG2160: 916e26f2ae4SMichael Krufky ret = lg2160_read_rs_err_count(state, err); 917e26f2ae4SMichael Krufky break; 918e26f2ae4SMichael Krufky case LG2161: 919e26f2ae4SMichael Krufky ret = lg2161_read_rs_err_count(state, err); 920e26f2ae4SMichael Krufky break; 921e26f2ae4SMichael Krufky default: 922e26f2ae4SMichael Krufky ret = -EINVAL; 923e26f2ae4SMichael Krufky break; 924e26f2ae4SMichael Krufky } 925e26f2ae4SMichael Krufky return ret; 926e26f2ae4SMichael Krufky } 92710d67371SMichael Krufky #endif 928e26f2ae4SMichael Krufky 929e26f2ae4SMichael Krufky /* ------------------------------------------------------------------------ */ 930e26f2ae4SMichael Krufky 9317e3e68bcSMauro Carvalho Chehab static int lg216x_get_frontend(struct dvb_frontend *fe, 9327e3e68bcSMauro Carvalho Chehab struct dtv_frontend_properties *c) 933e26f2ae4SMichael Krufky { 934e26f2ae4SMichael Krufky struct lg216x_state *state = fe->demodulator_priv; 935e26f2ae4SMichael Krufky int ret; 936e26f2ae4SMichael Krufky 937e26f2ae4SMichael Krufky lg_dbg("\n"); 938e26f2ae4SMichael Krufky 9397e3e68bcSMauro Carvalho Chehab c->modulation = VSB_8; 9407e3e68bcSMauro Carvalho Chehab c->frequency = state->current_frequency; 9417e3e68bcSMauro Carvalho Chehab c->delivery_system = SYS_ATSCMH; 942e26f2ae4SMichael Krufky 943e26f2ae4SMichael Krufky ret = lg216x_get_fic_version(state, 9447e3e68bcSMauro Carvalho Chehab &c->atscmh_fic_ver); 945e26f2ae4SMichael Krufky if (lg_fail(ret)) 946e26f2ae4SMichael Krufky goto fail; 9477e3e68bcSMauro Carvalho Chehab if (state->fic_ver != c->atscmh_fic_ver) { 9487e3e68bcSMauro Carvalho Chehab state->fic_ver = c->atscmh_fic_ver; 949e26f2ae4SMichael Krufky 950e26f2ae4SMichael Krufky #if 0 951e26f2ae4SMichael Krufky ret = lg2160_get_parade_id(state, 9527e3e68bcSMauro Carvalho Chehab &c->atscmh_parade_id); 953e26f2ae4SMichael Krufky if (lg_fail(ret)) 954e26f2ae4SMichael Krufky goto fail; 955e26f2ae4SMichael Krufky /* #else */ 9567e3e68bcSMauro Carvalho Chehab c->atscmh_parade_id = state->parade_id; 957e26f2ae4SMichael Krufky #endif 958e26f2ae4SMichael Krufky ret = lg216x_get_nog(state, 9597e3e68bcSMauro Carvalho Chehab &c->atscmh_nog); 960e26f2ae4SMichael Krufky if (lg_fail(ret)) 961e26f2ae4SMichael Krufky goto fail; 962e26f2ae4SMichael Krufky ret = lg216x_get_tnog(state, 9637e3e68bcSMauro Carvalho Chehab &c->atscmh_tnog); 964e26f2ae4SMichael Krufky if (lg_fail(ret)) 965e26f2ae4SMichael Krufky goto fail; 966e26f2ae4SMichael Krufky ret = lg216x_get_sgn(state, 9677e3e68bcSMauro Carvalho Chehab &c->atscmh_sgn); 968e26f2ae4SMichael Krufky if (lg_fail(ret)) 969e26f2ae4SMichael Krufky goto fail; 970e26f2ae4SMichael Krufky ret = lg216x_get_prc(state, 9717e3e68bcSMauro Carvalho Chehab &c->atscmh_prc); 972e26f2ae4SMichael Krufky if (lg_fail(ret)) 973e26f2ae4SMichael Krufky goto fail; 974e26f2ae4SMichael Krufky 975e26f2ae4SMichael Krufky ret = lg216x_get_rs_frame_mode(state, 976e26f2ae4SMichael Krufky (enum atscmh_rs_frame_mode *) 9777e3e68bcSMauro Carvalho Chehab &c->atscmh_rs_frame_mode); 978e26f2ae4SMichael Krufky if (lg_fail(ret)) 979e26f2ae4SMichael Krufky goto fail; 980e26f2ae4SMichael Krufky ret = lg216x_get_rs_frame_ensemble(state, 981e26f2ae4SMichael Krufky (enum atscmh_rs_frame_ensemble *) 9827e3e68bcSMauro Carvalho Chehab &c->atscmh_rs_frame_ensemble); 983e26f2ae4SMichael Krufky if (lg_fail(ret)) 984e26f2ae4SMichael Krufky goto fail; 985e26f2ae4SMichael Krufky ret = lg216x_get_rs_code_mode(state, 986e26f2ae4SMichael Krufky (enum atscmh_rs_code_mode *) 9877e3e68bcSMauro Carvalho Chehab &c->atscmh_rs_code_mode_pri, 988e26f2ae4SMichael Krufky (enum atscmh_rs_code_mode *) 9897e3e68bcSMauro Carvalho Chehab &c->atscmh_rs_code_mode_sec); 990e26f2ae4SMichael Krufky if (lg_fail(ret)) 991e26f2ae4SMichael Krufky goto fail; 992e26f2ae4SMichael Krufky ret = lg216x_get_sccc_block_mode(state, 993e26f2ae4SMichael Krufky (enum atscmh_sccc_block_mode *) 9947e3e68bcSMauro Carvalho Chehab &c->atscmh_sccc_block_mode); 995e26f2ae4SMichael Krufky if (lg_fail(ret)) 996e26f2ae4SMichael Krufky goto fail; 997e26f2ae4SMichael Krufky ret = lg216x_get_sccc_code_mode(state, 998e26f2ae4SMichael Krufky (enum atscmh_sccc_code_mode *) 9997e3e68bcSMauro Carvalho Chehab &c->atscmh_sccc_code_mode_a, 1000e26f2ae4SMichael Krufky (enum atscmh_sccc_code_mode *) 10017e3e68bcSMauro Carvalho Chehab &c->atscmh_sccc_code_mode_b, 1002e26f2ae4SMichael Krufky (enum atscmh_sccc_code_mode *) 10037e3e68bcSMauro Carvalho Chehab &c->atscmh_sccc_code_mode_c, 1004e26f2ae4SMichael Krufky (enum atscmh_sccc_code_mode *) 10057e3e68bcSMauro Carvalho Chehab &c->atscmh_sccc_code_mode_d); 1006e26f2ae4SMichael Krufky if (lg_fail(ret)) 1007e26f2ae4SMichael Krufky goto fail; 1008e26f2ae4SMichael Krufky } 100910d67371SMichael Krufky #if 0 1010e26f2ae4SMichael Krufky ret = lg216x_read_fic_err_count(state, 10117e3e68bcSMauro Carvalho Chehab (u8 *)&c->atscmh_fic_err); 1012e26f2ae4SMichael Krufky if (lg_fail(ret)) 1013e26f2ae4SMichael Krufky goto fail; 1014e26f2ae4SMichael Krufky ret = lg216x_read_crc_err_count(state, 10157e3e68bcSMauro Carvalho Chehab &c->atscmh_crc_err); 1016e26f2ae4SMichael Krufky if (lg_fail(ret)) 1017e26f2ae4SMichael Krufky goto fail; 1018e26f2ae4SMichael Krufky ret = lg216x_read_rs_err_count(state, 10197e3e68bcSMauro Carvalho Chehab &c->atscmh_rs_err); 1020e26f2ae4SMichael Krufky if (lg_fail(ret)) 1021e26f2ae4SMichael Krufky goto fail; 1022e26f2ae4SMichael Krufky 1023e26f2ae4SMichael Krufky switch (state->cfg->lg_chip) { 1024e26f2ae4SMichael Krufky case LG2160: 10257e3e68bcSMauro Carvalho Chehab if (((c->atscmh_rs_err >= 240) && 10267e3e68bcSMauro Carvalho Chehab (c->atscmh_crc_err >= 240)) && 1027e26f2ae4SMichael Krufky ((jiffies_to_msecs(jiffies) - state->last_reset) > 6000)) 1028e26f2ae4SMichael Krufky ret = lg216x_soft_reset(state); 1029e26f2ae4SMichael Krufky break; 1030e26f2ae4SMichael Krufky case LG2161: 1031e26f2ae4SMichael Krufky /* no fix needed here (as far as we know) */ 1032e26f2ae4SMichael Krufky ret = 0; 1033e26f2ae4SMichael Krufky break; 1034e26f2ae4SMichael Krufky } 1035e26f2ae4SMichael Krufky lg_fail(ret); 103610d67371SMichael Krufky #endif 1037e26f2ae4SMichael Krufky fail: 1038e26f2ae4SMichael Krufky return ret; 1039e26f2ae4SMichael Krufky } 1040e26f2ae4SMichael Krufky 1041e26f2ae4SMichael Krufky static int lg2160_set_frontend(struct dvb_frontend *fe) 1042e26f2ae4SMichael Krufky { 1043e26f2ae4SMichael Krufky struct lg216x_state *state = fe->demodulator_priv; 10447e3e68bcSMauro Carvalho Chehab struct dtv_frontend_properties *c = &fe->dtv_property_cache; 1045e26f2ae4SMichael Krufky int ret; 1046e26f2ae4SMichael Krufky 1047e26f2ae4SMichael Krufky lg_dbg("(%d)\n", fe->dtv_property_cache.frequency); 1048e26f2ae4SMichael Krufky 1049e26f2ae4SMichael Krufky if (fe->ops.tuner_ops.set_params) { 1050e26f2ae4SMichael Krufky ret = fe->ops.tuner_ops.set_params(fe); 1051e26f2ae4SMichael Krufky if (fe->ops.i2c_gate_ctrl) 1052e26f2ae4SMichael Krufky fe->ops.i2c_gate_ctrl(fe, 0); 1053e26f2ae4SMichael Krufky if (lg_fail(ret)) 1054e26f2ae4SMichael Krufky goto fail; 1055e26f2ae4SMichael Krufky state->current_frequency = fe->dtv_property_cache.frequency; 1056e26f2ae4SMichael Krufky } 1057e26f2ae4SMichael Krufky 1058e26f2ae4SMichael Krufky ret = lg2160_agc_fix(state, 0, 0); 1059e26f2ae4SMichael Krufky if (lg_fail(ret)) 1060e26f2ae4SMichael Krufky goto fail; 1061e26f2ae4SMichael Krufky ret = lg2160_agc_polarity(state, 0, 0); 1062e26f2ae4SMichael Krufky if (lg_fail(ret)) 1063e26f2ae4SMichael Krufky goto fail; 1064e26f2ae4SMichael Krufky ret = lg2160_tuner_pwr_save_polarity(state, 1); 1065e26f2ae4SMichael Krufky if (lg_fail(ret)) 1066e26f2ae4SMichael Krufky goto fail; 1067e26f2ae4SMichael Krufky ret = lg216x_set_if(state); 1068e26f2ae4SMichael Krufky if (lg_fail(ret)) 1069e26f2ae4SMichael Krufky goto fail; 1070e26f2ae4SMichael Krufky ret = lg2160_spectrum_polarity(state, state->cfg->spectral_inversion); 1071e26f2ae4SMichael Krufky if (lg_fail(ret)) 1072e26f2ae4SMichael Krufky goto fail; 1073e26f2ae4SMichael Krufky 1074e26f2ae4SMichael Krufky /* be tuned before this point */ 1075e26f2ae4SMichael Krufky ret = lg216x_soft_reset(state); 1076e26f2ae4SMichael Krufky if (lg_fail(ret)) 1077e26f2ae4SMichael Krufky goto fail; 1078e26f2ae4SMichael Krufky 1079e26f2ae4SMichael Krufky ret = lg2160_tuner_pwr_save(state, 0); 1080e26f2ae4SMichael Krufky if (lg_fail(ret)) 1081e26f2ae4SMichael Krufky goto fail; 1082e26f2ae4SMichael Krufky 1083e26f2ae4SMichael Krufky switch (state->cfg->lg_chip) { 1084e26f2ae4SMichael Krufky case LG2160: 1085e26f2ae4SMichael Krufky ret = lg2160_set_spi_clock(state); 1086e26f2ae4SMichael Krufky if (lg_fail(ret)) 1087e26f2ae4SMichael Krufky goto fail; 1088e26f2ae4SMichael Krufky break; 1089e26f2ae4SMichael Krufky case LG2161: 1090e26f2ae4SMichael Krufky ret = lg2161_set_output_interface(state); 1091e26f2ae4SMichael Krufky if (lg_fail(ret)) 1092e26f2ae4SMichael Krufky goto fail; 1093e26f2ae4SMichael Krufky break; 1094e26f2ae4SMichael Krufky } 1095e26f2ae4SMichael Krufky 1096e26f2ae4SMichael Krufky ret = lg216x_set_parade(state, fe->dtv_property_cache.atscmh_parade_id); 1097e26f2ae4SMichael Krufky if (lg_fail(ret)) 1098e26f2ae4SMichael Krufky goto fail; 1099e26f2ae4SMichael Krufky 1100e26f2ae4SMichael Krufky ret = lg216x_set_ensemble(state, 1101e26f2ae4SMichael Krufky fe->dtv_property_cache.atscmh_rs_frame_ensemble); 1102e26f2ae4SMichael Krufky if (lg_fail(ret)) 1103e26f2ae4SMichael Krufky goto fail; 1104e26f2ae4SMichael Krufky 1105e26f2ae4SMichael Krufky ret = lg216x_initialize(state); 1106e26f2ae4SMichael Krufky if (lg_fail(ret)) 1107e26f2ae4SMichael Krufky goto fail; 1108e26f2ae4SMichael Krufky 1109e26f2ae4SMichael Krufky ret = lg216x_enable_fic(state, 1); 1110e26f2ae4SMichael Krufky lg_fail(ret); 1111e26f2ae4SMichael Krufky 11127e3e68bcSMauro Carvalho Chehab lg216x_get_frontend(fe, c); 1113e26f2ae4SMichael Krufky fail: 1114e26f2ae4SMichael Krufky return ret; 1115e26f2ae4SMichael Krufky } 1116e26f2ae4SMichael Krufky 1117e26f2ae4SMichael Krufky /* ------------------------------------------------------------------------ */ 1118e26f2ae4SMichael Krufky 1119e26f2ae4SMichael Krufky static int lg2160_read_lock_status(struct lg216x_state *state, 1120e26f2ae4SMichael Krufky int *acq_lock, int *sync_lock) 1121e26f2ae4SMichael Krufky { 1122e26f2ae4SMichael Krufky u8 val; 1123e26f2ae4SMichael Krufky int ret; 1124e26f2ae4SMichael Krufky 1125e26f2ae4SMichael Krufky *acq_lock = 0; 1126e26f2ae4SMichael Krufky *sync_lock = 0; 1127e26f2ae4SMichael Krufky 1128e26f2ae4SMichael Krufky ret = lg216x_read_reg(state, 0x011b, &val); 1129e26f2ae4SMichael Krufky if (lg_fail(ret)) 1130e26f2ae4SMichael Krufky goto fail; 1131e26f2ae4SMichael Krufky 1132e26f2ae4SMichael Krufky *sync_lock = (val & 0x20) ? 0 : 1; 1133e26f2ae4SMichael Krufky *acq_lock = (val & 0x40) ? 0 : 1; 1134e26f2ae4SMichael Krufky fail: 1135e26f2ae4SMichael Krufky return ret; 1136e26f2ae4SMichael Krufky } 1137e26f2ae4SMichael Krufky 1138e26f2ae4SMichael Krufky #ifdef USE_LG2161_LOCK_BITS 1139e26f2ae4SMichael Krufky static int lg2161_read_lock_status(struct lg216x_state *state, 1140e26f2ae4SMichael Krufky int *acq_lock, int *sync_lock) 1141e26f2ae4SMichael Krufky { 1142e26f2ae4SMichael Krufky u8 val; 1143e26f2ae4SMichael Krufky int ret; 1144e26f2ae4SMichael Krufky 1145e26f2ae4SMichael Krufky *acq_lock = 0; 1146e26f2ae4SMichael Krufky *sync_lock = 0; 1147e26f2ae4SMichael Krufky 1148e26f2ae4SMichael Krufky ret = lg216x_read_reg(state, 0x0304, &val); 1149e26f2ae4SMichael Krufky if (lg_fail(ret)) 1150e26f2ae4SMichael Krufky goto fail; 1151e26f2ae4SMichael Krufky 1152e26f2ae4SMichael Krufky *sync_lock = (val & 0x80) ? 0 : 1; 1153e26f2ae4SMichael Krufky 1154e26f2ae4SMichael Krufky ret = lg216x_read_reg(state, 0x011b, &val); 1155e26f2ae4SMichael Krufky if (lg_fail(ret)) 1156e26f2ae4SMichael Krufky goto fail; 1157e26f2ae4SMichael Krufky 1158e26f2ae4SMichael Krufky *acq_lock = (val & 0x40) ? 0 : 1; 1159e26f2ae4SMichael Krufky fail: 1160e26f2ae4SMichael Krufky return ret; 1161e26f2ae4SMichael Krufky } 1162e26f2ae4SMichael Krufky #endif 1163e26f2ae4SMichael Krufky 1164e26f2ae4SMichael Krufky static int lg216x_read_lock_status(struct lg216x_state *state, 1165e26f2ae4SMichael Krufky int *acq_lock, int *sync_lock) 1166e26f2ae4SMichael Krufky { 1167e26f2ae4SMichael Krufky #ifdef USE_LG2161_LOCK_BITS 1168e26f2ae4SMichael Krufky int ret; 1169e26f2ae4SMichael Krufky switch (state->cfg->lg_chip) { 1170e26f2ae4SMichael Krufky case LG2160: 1171e26f2ae4SMichael Krufky ret = lg2160_read_lock_status(state, acq_lock, sync_lock); 1172e26f2ae4SMichael Krufky break; 1173e26f2ae4SMichael Krufky case LG2161: 1174e26f2ae4SMichael Krufky ret = lg2161_read_lock_status(state, acq_lock, sync_lock); 1175e26f2ae4SMichael Krufky break; 1176e26f2ae4SMichael Krufky default: 1177e26f2ae4SMichael Krufky ret = -EINVAL; 1178e26f2ae4SMichael Krufky break; 1179e26f2ae4SMichael Krufky } 1180e26f2ae4SMichael Krufky return ret; 1181e26f2ae4SMichael Krufky #else 1182e26f2ae4SMichael Krufky return lg2160_read_lock_status(state, acq_lock, sync_lock); 1183e26f2ae4SMichael Krufky #endif 1184e26f2ae4SMichael Krufky } 1185e26f2ae4SMichael Krufky 11860df289a2SMauro Carvalho Chehab static int lg216x_read_status(struct dvb_frontend *fe, enum fe_status *status) 1187e26f2ae4SMichael Krufky { 1188e26f2ae4SMichael Krufky struct lg216x_state *state = fe->demodulator_priv; 1189e26f2ae4SMichael Krufky int ret, acq_lock, sync_lock; 1190e26f2ae4SMichael Krufky 1191e26f2ae4SMichael Krufky *status = 0; 1192e26f2ae4SMichael Krufky 1193e26f2ae4SMichael Krufky ret = lg216x_read_lock_status(state, &acq_lock, &sync_lock); 1194e26f2ae4SMichael Krufky if (lg_fail(ret)) 1195e26f2ae4SMichael Krufky goto fail; 1196e26f2ae4SMichael Krufky 1197e26f2ae4SMichael Krufky lg_dbg("%s%s\n", 1198e26f2ae4SMichael Krufky acq_lock ? "SIGNALEXIST " : "", 1199e26f2ae4SMichael Krufky sync_lock ? "SYNCLOCK" : ""); 1200e26f2ae4SMichael Krufky 1201e26f2ae4SMichael Krufky if (acq_lock) 1202e26f2ae4SMichael Krufky *status |= FE_HAS_SIGNAL; 1203e26f2ae4SMichael Krufky if (sync_lock) 1204e26f2ae4SMichael Krufky *status |= FE_HAS_SYNC; 1205e26f2ae4SMichael Krufky 1206e26f2ae4SMichael Krufky if (*status) 1207e26f2ae4SMichael Krufky *status |= FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_LOCK; 1208e26f2ae4SMichael Krufky 1209e26f2ae4SMichael Krufky fail: 1210e26f2ae4SMichael Krufky return ret; 1211e26f2ae4SMichael Krufky } 1212e26f2ae4SMichael Krufky 1213e26f2ae4SMichael Krufky /* ------------------------------------------------------------------------ */ 1214e26f2ae4SMichael Krufky 1215e26f2ae4SMichael Krufky static int lg2160_read_snr(struct dvb_frontend *fe, u16 *snr) 1216e26f2ae4SMichael Krufky { 1217e26f2ae4SMichael Krufky struct lg216x_state *state = fe->demodulator_priv; 1218e26f2ae4SMichael Krufky u8 snr1, snr2; 1219e26f2ae4SMichael Krufky int ret; 1220e26f2ae4SMichael Krufky 1221e26f2ae4SMichael Krufky *snr = 0; 1222e26f2ae4SMichael Krufky 1223e26f2ae4SMichael Krufky ret = lg216x_read_reg(state, 0x0202, &snr1); 1224e26f2ae4SMichael Krufky if (lg_fail(ret)) 1225e26f2ae4SMichael Krufky goto fail; 1226e26f2ae4SMichael Krufky 1227e26f2ae4SMichael Krufky ret = lg216x_read_reg(state, 0x0203, &snr2); 1228e26f2ae4SMichael Krufky if (lg_fail(ret)) 1229e26f2ae4SMichael Krufky goto fail; 1230e26f2ae4SMichael Krufky 1231e26f2ae4SMichael Krufky if ((snr1 == 0xba) || (snr2 == 0xdf)) 1232e26f2ae4SMichael Krufky *snr = 0; 1233e26f2ae4SMichael Krufky else 1234e26f2ae4SMichael Krufky #if 1 1235e26f2ae4SMichael Krufky *snr = ((snr1 >> 4) * 100) + ((snr1 & 0x0f) * 10) + (snr2 >> 4); 1236e26f2ae4SMichael Krufky #else /* BCD */ 1237e26f2ae4SMichael Krufky *snr = (snr2 | (snr1 << 8)); 1238e26f2ae4SMichael Krufky #endif 1239e26f2ae4SMichael Krufky fail: 1240e26f2ae4SMichael Krufky return ret; 1241e26f2ae4SMichael Krufky } 1242e26f2ae4SMichael Krufky 1243e26f2ae4SMichael Krufky static int lg2161_read_snr(struct dvb_frontend *fe, u16 *snr) 1244e26f2ae4SMichael Krufky { 1245e26f2ae4SMichael Krufky struct lg216x_state *state = fe->demodulator_priv; 1246e26f2ae4SMichael Krufky u8 snr1, snr2; 1247e26f2ae4SMichael Krufky int ret; 1248e26f2ae4SMichael Krufky 1249e26f2ae4SMichael Krufky *snr = 0; 1250e26f2ae4SMichael Krufky 1251e26f2ae4SMichael Krufky ret = lg216x_read_reg(state, 0x0302, &snr1); 1252e26f2ae4SMichael Krufky if (lg_fail(ret)) 1253e26f2ae4SMichael Krufky goto fail; 1254e26f2ae4SMichael Krufky 1255e26f2ae4SMichael Krufky ret = lg216x_read_reg(state, 0x0303, &snr2); 1256e26f2ae4SMichael Krufky if (lg_fail(ret)) 1257e26f2ae4SMichael Krufky goto fail; 1258e26f2ae4SMichael Krufky 1259e26f2ae4SMichael Krufky if ((snr1 == 0xba) || (snr2 == 0xfd)) 1260e26f2ae4SMichael Krufky *snr = 0; 1261e26f2ae4SMichael Krufky else 1262e26f2ae4SMichael Krufky 1263e26f2ae4SMichael Krufky *snr = ((snr1 >> 4) * 100) + ((snr1 & 0x0f) * 10) + (snr2 & 0x0f); 1264e26f2ae4SMichael Krufky fail: 1265e26f2ae4SMichael Krufky return ret; 1266e26f2ae4SMichael Krufky } 1267e26f2ae4SMichael Krufky 1268e26f2ae4SMichael Krufky static int lg216x_read_signal_strength(struct dvb_frontend *fe, 1269e26f2ae4SMichael Krufky u16 *strength) 1270e26f2ae4SMichael Krufky { 1271e26f2ae4SMichael Krufky #if 0 1272e26f2ae4SMichael Krufky /* borrowed from lgdt330x.c 1273e26f2ae4SMichael Krufky * 1274e26f2ae4SMichael Krufky * Calculate strength from SNR up to 35dB 1275e26f2ae4SMichael Krufky * Even though the SNR can go higher than 35dB, 1276e26f2ae4SMichael Krufky * there is some comfort factor in having a range of 1277e26f2ae4SMichael Krufky * strong signals that can show at 100% 1278e26f2ae4SMichael Krufky */ 1279e26f2ae4SMichael Krufky struct lg216x_state *state = fe->demodulator_priv; 1280e26f2ae4SMichael Krufky u16 snr; 1281e26f2ae4SMichael Krufky int ret; 1282e26f2ae4SMichael Krufky #endif 1283e26f2ae4SMichael Krufky *strength = 0; 1284e26f2ae4SMichael Krufky #if 0 1285e26f2ae4SMichael Krufky ret = fe->ops.read_snr(fe, &snr); 1286e26f2ae4SMichael Krufky if (lg_fail(ret)) 1287e26f2ae4SMichael Krufky goto fail; 1288e26f2ae4SMichael Krufky /* Rather than use the 8.8 value snr, use state->snr which is 8.24 */ 1289e26f2ae4SMichael Krufky /* scale the range 0 - 35*2^24 into 0 - 65535 */ 1290e26f2ae4SMichael Krufky if (state->snr >= 8960 * 0x10000) 1291e26f2ae4SMichael Krufky *strength = 0xffff; 1292e26f2ae4SMichael Krufky else 1293e26f2ae4SMichael Krufky *strength = state->snr / 8960; 1294e26f2ae4SMichael Krufky fail: 1295e26f2ae4SMichael Krufky return ret; 1296e26f2ae4SMichael Krufky #else 1297e26f2ae4SMichael Krufky return 0; 1298e26f2ae4SMichael Krufky #endif 1299e26f2ae4SMichael Krufky } 1300e26f2ae4SMichael Krufky 1301e26f2ae4SMichael Krufky /* ------------------------------------------------------------------------ */ 1302e26f2ae4SMichael Krufky 1303e26f2ae4SMichael Krufky static int lg216x_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) 1304e26f2ae4SMichael Krufky { 13055444a1b7SMauro Carvalho Chehab #if 0 1306e26f2ae4SMichael Krufky struct lg216x_state *state = fe->demodulator_priv; 1307e26f2ae4SMichael Krufky int ret; 13085444a1b7SMauro Carvalho Chehab 1309e26f2ae4SMichael Krufky ret = lg216x_read_rs_err_count(state, 1310e26f2ae4SMichael Krufky &fe->dtv_property_cache.atscmh_rs_err); 1311e26f2ae4SMichael Krufky if (lg_fail(ret)) 1312e26f2ae4SMichael Krufky goto fail; 1313e26f2ae4SMichael Krufky 1314e26f2ae4SMichael Krufky *ucblocks = fe->dtv_property_cache.atscmh_rs_err; 13155444a1b7SMauro Carvalho Chehab fail: 131610d67371SMichael Krufky #else 131710d67371SMichael Krufky *ucblocks = 0; 131810d67371SMichael Krufky #endif 1319e26f2ae4SMichael Krufky return 0; 1320e26f2ae4SMichael Krufky } 1321e26f2ae4SMichael Krufky 1322e26f2ae4SMichael Krufky static int lg216x_get_tune_settings(struct dvb_frontend *fe, 1323e26f2ae4SMichael Krufky struct dvb_frontend_tune_settings 1324e26f2ae4SMichael Krufky *fe_tune_settings) 1325e26f2ae4SMichael Krufky { 1326e26f2ae4SMichael Krufky fe_tune_settings->min_delay_ms = 500; 1327e26f2ae4SMichael Krufky lg_dbg("\n"); 1328e26f2ae4SMichael Krufky return 0; 1329e26f2ae4SMichael Krufky } 1330e26f2ae4SMichael Krufky 1331e26f2ae4SMichael Krufky static void lg216x_release(struct dvb_frontend *fe) 1332e26f2ae4SMichael Krufky { 1333e26f2ae4SMichael Krufky struct lg216x_state *state = fe->demodulator_priv; 1334e26f2ae4SMichael Krufky lg_dbg("\n"); 1335e26f2ae4SMichael Krufky kfree(state); 1336e26f2ae4SMichael Krufky } 1337e26f2ae4SMichael Krufky 1338bd336e63SMax Kellermann static const struct dvb_frontend_ops lg2160_ops = { 1339e26f2ae4SMichael Krufky .delsys = { SYS_ATSCMH }, 1340e26f2ae4SMichael Krufky .info = { 1341e26f2ae4SMichael Krufky .name = "LG Electronics LG2160 ATSC/MH Frontend", 1342f1b1eabfSMauro Carvalho Chehab .frequency_min_hz = 54 * MHz, 1343f1b1eabfSMauro Carvalho Chehab .frequency_max_hz = 858 * MHz, 1344f1b1eabfSMauro Carvalho Chehab .frequency_stepsize_hz = 62500, 1345e26f2ae4SMichael Krufky }, 1346e26f2ae4SMichael Krufky .i2c_gate_ctrl = lg216x_i2c_gate_ctrl, 1347e26f2ae4SMichael Krufky #if 0 1348e26f2ae4SMichael Krufky .init = lg216x_init, 1349e26f2ae4SMichael Krufky .sleep = lg216x_sleep, 1350e26f2ae4SMichael Krufky #endif 1351e26f2ae4SMichael Krufky .set_frontend = lg2160_set_frontend, 1352e26f2ae4SMichael Krufky .get_frontend = lg216x_get_frontend, 1353e26f2ae4SMichael Krufky .get_tune_settings = lg216x_get_tune_settings, 1354e26f2ae4SMichael Krufky .read_status = lg216x_read_status, 1355e26f2ae4SMichael Krufky #if 0 1356e26f2ae4SMichael Krufky .read_ber = lg216x_read_ber, 1357e26f2ae4SMichael Krufky #endif 1358e26f2ae4SMichael Krufky .read_signal_strength = lg216x_read_signal_strength, 1359e26f2ae4SMichael Krufky .read_snr = lg2160_read_snr, 1360e26f2ae4SMichael Krufky .read_ucblocks = lg216x_read_ucblocks, 1361e26f2ae4SMichael Krufky .release = lg216x_release, 1362e26f2ae4SMichael Krufky }; 1363e26f2ae4SMichael Krufky 1364bd336e63SMax Kellermann static const struct dvb_frontend_ops lg2161_ops = { 1365e26f2ae4SMichael Krufky .delsys = { SYS_ATSCMH }, 1366e26f2ae4SMichael Krufky .info = { 1367e26f2ae4SMichael Krufky .name = "LG Electronics LG2161 ATSC/MH Frontend", 1368f1b1eabfSMauro Carvalho Chehab .frequency_min_hz = 54 * MHz, 1369f1b1eabfSMauro Carvalho Chehab .frequency_max_hz = 858 * MHz, 1370f1b1eabfSMauro Carvalho Chehab .frequency_stepsize_hz = 62500, 1371e26f2ae4SMichael Krufky }, 1372e26f2ae4SMichael Krufky .i2c_gate_ctrl = lg216x_i2c_gate_ctrl, 1373e26f2ae4SMichael Krufky #if 0 1374e26f2ae4SMichael Krufky .init = lg216x_init, 1375e26f2ae4SMichael Krufky .sleep = lg216x_sleep, 1376e26f2ae4SMichael Krufky #endif 1377e26f2ae4SMichael Krufky .set_frontend = lg2160_set_frontend, 1378e26f2ae4SMichael Krufky .get_frontend = lg216x_get_frontend, 1379e26f2ae4SMichael Krufky .get_tune_settings = lg216x_get_tune_settings, 1380e26f2ae4SMichael Krufky .read_status = lg216x_read_status, 1381e26f2ae4SMichael Krufky #if 0 1382e26f2ae4SMichael Krufky .read_ber = lg216x_read_ber, 1383e26f2ae4SMichael Krufky #endif 1384e26f2ae4SMichael Krufky .read_signal_strength = lg216x_read_signal_strength, 1385e26f2ae4SMichael Krufky .read_snr = lg2161_read_snr, 1386e26f2ae4SMichael Krufky .read_ucblocks = lg216x_read_ucblocks, 1387e26f2ae4SMichael Krufky .release = lg216x_release, 1388e26f2ae4SMichael Krufky }; 1389e26f2ae4SMichael Krufky 1390e26f2ae4SMichael Krufky struct dvb_frontend *lg2160_attach(const struct lg2160_config *config, 1391e26f2ae4SMichael Krufky struct i2c_adapter *i2c_adap) 1392e26f2ae4SMichael Krufky { 1393e26f2ae4SMichael Krufky struct lg216x_state *state = NULL; 1394e26f2ae4SMichael Krufky 1395e26f2ae4SMichael Krufky lg_dbg("(%d-%04x)\n", 1396e26f2ae4SMichael Krufky i2c_adap ? i2c_adapter_id(i2c_adap) : 0, 1397e26f2ae4SMichael Krufky config ? config->i2c_addr : 0); 1398e26f2ae4SMichael Krufky 1399e26f2ae4SMichael Krufky state = kzalloc(sizeof(struct lg216x_state), GFP_KERNEL); 14001a5d2da1SPeter Senna Tschudin if (!state) 14011a5d2da1SPeter Senna Tschudin return NULL; 1402e26f2ae4SMichael Krufky 1403e26f2ae4SMichael Krufky state->cfg = config; 1404e26f2ae4SMichael Krufky state->i2c_adap = i2c_adap; 1405e26f2ae4SMichael Krufky state->fic_ver = 0xff; 1406e26f2ae4SMichael Krufky state->parade_id = 0xff; 1407e26f2ae4SMichael Krufky 1408e26f2ae4SMichael Krufky switch (config->lg_chip) { 1409e26f2ae4SMichael Krufky default: 1410e26f2ae4SMichael Krufky lg_warn("invalid chip requested, defaulting to LG2160"); 1411*1771e9fbSGustavo A. R. Silva fallthrough; 1412e26f2ae4SMichael Krufky case LG2160: 1413e26f2ae4SMichael Krufky memcpy(&state->frontend.ops, &lg2160_ops, 1414e26f2ae4SMichael Krufky sizeof(struct dvb_frontend_ops)); 1415e26f2ae4SMichael Krufky break; 1416e26f2ae4SMichael Krufky case LG2161: 1417e26f2ae4SMichael Krufky memcpy(&state->frontend.ops, &lg2161_ops, 1418e26f2ae4SMichael Krufky sizeof(struct dvb_frontend_ops)); 1419e26f2ae4SMichael Krufky break; 1420e26f2ae4SMichael Krufky } 1421e26f2ae4SMichael Krufky 1422e26f2ae4SMichael Krufky state->frontend.demodulator_priv = state; 1423e26f2ae4SMichael Krufky state->current_frequency = -1; 1424e26f2ae4SMichael Krufky /* parade 1 by default */ 1425e26f2ae4SMichael Krufky state->frontend.dtv_property_cache.atscmh_parade_id = 1; 1426e26f2ae4SMichael Krufky 1427e26f2ae4SMichael Krufky return &state->frontend; 1428e26f2ae4SMichael Krufky } 1429e26f2ae4SMichael Krufky EXPORT_SYMBOL(lg2160_attach); 1430e26f2ae4SMichael Krufky 1431e26f2ae4SMichael Krufky MODULE_DESCRIPTION("LG Electronics LG216x ATSC/MH Demodulator Driver"); 1432e26f2ae4SMichael Krufky MODULE_AUTHOR("Michael Krufky <mkrufky@linuxtv.org>"); 1433e26f2ae4SMichael Krufky MODULE_LICENSE("GPL"); 1434e26f2ae4SMichael Krufky MODULE_VERSION("0.3"); 1435