1b63b36faSFred Richter /* 2b63b36faSFred Richter * Support for LGDT3306A - 8VSB/QAM-B 3b63b36faSFred Richter * 4b63b36faSFred Richter * Copyright (C) 2013 Fred Richter <frichter@hauppauge.com> 5b63b36faSFred Richter * - driver structure based on lgdt3305.[ch] by Michael Krufky 6b63b36faSFred Richter * - code based on LG3306_V0.35 API by LG Electronics Inc. 7b63b36faSFred Richter * 8b63b36faSFred Richter * This program is free software; you can redistribute it and/or modify 9b63b36faSFred Richter * it under the terms of the GNU General Public License as published by 10b63b36faSFred Richter * the Free Software Foundation; either version 2 of the License, or 11b63b36faSFred Richter * (at your option) any later version. 12b63b36faSFred Richter * 13b63b36faSFred Richter * This program is distributed in the hope that it will be useful, 14b63b36faSFred Richter * but WITHOUT ANY WARRANTY; without even the implied warranty of 15b63b36faSFred Richter * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16b63b36faSFred Richter * GNU General Public License for more details. 17b63b36faSFred Richter */ 18b63b36faSFred Richter 19097117caSMauro Carvalho Chehab #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 20097117caSMauro Carvalho Chehab 21b63b36faSFred Richter #include <asm/div64.h> 22b63b36faSFred Richter #include <linux/dvb/frontend.h> 23b63b36faSFred Richter #include "dvb_math.h" 24b63b36faSFred Richter #include "lgdt3306a.h" 25b63b36faSFred Richter 26b63b36faSFred Richter 27b63b36faSFred Richter static int debug; 28b63b36faSFred Richter module_param(debug, int, 0644); 29b63b36faSFred Richter MODULE_PARM_DESC(debug, "set debug level (info=1, reg=2 (or-able))"); 30b63b36faSFred Richter 31b63b36faSFred Richter #define DBG_INFO 1 32b63b36faSFred Richter #define DBG_REG 2 338e8cd34eSMichael Ira Krufky #define DBG_DUMP 4 /* FGR - comment out to remove dump code */ 34b63b36faSFred Richter 35097117caSMauro Carvalho Chehab #define lg_debug(fmt, arg...) \ 36097117caSMauro Carvalho Chehab printk(KERN_DEBUG pr_fmt(fmt), ## arg) 37b63b36faSFred Richter 38097117caSMauro Carvalho Chehab #define dbg_info(fmt, arg...) \ 39097117caSMauro Carvalho Chehab do { \ 40097117caSMauro Carvalho Chehab if (debug & DBG_INFO) \ 41097117caSMauro Carvalho Chehab lg_debug(fmt, ## arg); \ 42097117caSMauro Carvalho Chehab } while (0) 43097117caSMauro Carvalho Chehab 44097117caSMauro Carvalho Chehab #define dbg_reg(fmt, arg...) \ 45097117caSMauro Carvalho Chehab do { \ 46097117caSMauro Carvalho Chehab if (debug & DBG_REG) \ 47097117caSMauro Carvalho Chehab lg_debug(fmt, ## arg); \ 48097117caSMauro Carvalho Chehab } while (0) 49b63b36faSFred Richter 50b63b36faSFred Richter #define lg_chkerr(ret) \ 51b63b36faSFred Richter ({ \ 52b63b36faSFred Richter int __ret; \ 53b63b36faSFred Richter __ret = (ret < 0); \ 54b63b36faSFred Richter if (__ret) \ 55097117caSMauro Carvalho Chehab pr_err("error %d on line %d\n", ret, __LINE__); \ 56b63b36faSFred Richter __ret; \ 57b63b36faSFred Richter }) 58b63b36faSFred Richter 59b63b36faSFred Richter struct lgdt3306a_state { 60b63b36faSFred Richter struct i2c_adapter *i2c_adap; 61b63b36faSFred Richter const struct lgdt3306a_config *cfg; 62b63b36faSFred Richter 63b63b36faSFred Richter struct dvb_frontend frontend; 64b63b36faSFred Richter 65b63b36faSFred Richter fe_modulation_t current_modulation; 66b63b36faSFred Richter u32 current_frequency; 67b63b36faSFred Richter u32 snr; 68b63b36faSFred Richter }; 69b63b36faSFred Richter 70b63b36faSFred Richter /* ----------------------------------------------- 71b63b36faSFred Richter LG3306A Register Usage 72b63b36faSFred Richter (LG does not really name the registers, so this code does not either) 73b63b36faSFred Richter 0000 -> 00FF Common control and status 74b63b36faSFred Richter 1000 -> 10FF Synchronizer control and status 75b63b36faSFred Richter 1F00 -> 1FFF Smart Antenna control and status 76b63b36faSFred Richter 2100 -> 21FF VSB Equalizer control and status 77b63b36faSFred Richter 2800 -> 28FF QAM Equalizer control and status 78b63b36faSFred Richter 3000 -> 30FF FEC control and status 79b63b36faSFred Richter ---------------------------------------------- */ 80b63b36faSFred Richter 81f883d603SMichael Ira Krufky enum lgdt3306a_lock_status { 82b63b36faSFred Richter LG3306_UNLOCK = 0x00, 83b63b36faSFred Richter LG3306_LOCK = 0x01, 844937ba94SMauro Carvalho Chehab LG3306_UNKNOWN_LOCK = 0xff 85f883d603SMichael Ira Krufky }; 86b63b36faSFred Richter 87f883d603SMichael Ira Krufky enum lgdt3306a_neverlock_status { 88b63b36faSFred Richter LG3306_NL_INIT = 0x00, 89b63b36faSFred Richter LG3306_NL_PROCESS = 0x01, 90b63b36faSFred Richter LG3306_NL_LOCK = 0x02, 91b63b36faSFred Richter LG3306_NL_FAIL = 0x03, 924937ba94SMauro Carvalho Chehab LG3306_NL_UNKNOWN = 0xff 93f883d603SMichael Ira Krufky }; 94b63b36faSFred Richter 95f883d603SMichael Ira Krufky enum lgdt3306a_modulation { 96b63b36faSFred Richter LG3306_VSB = 0x00, 97b63b36faSFred Richter LG3306_QAM64 = 0x01, 98b63b36faSFred Richter LG3306_QAM256 = 0x02, 994937ba94SMauro Carvalho Chehab LG3306_UNKNOWN_MODE = 0xff 100f883d603SMichael Ira Krufky }; 101b63b36faSFred Richter 102f883d603SMichael Ira Krufky enum lgdt3306a_lock_check { 103b63b36faSFred Richter LG3306_SYNC_LOCK, 104b63b36faSFred Richter LG3306_FEC_LOCK, 105b63b36faSFred Richter LG3306_TR_LOCK, 106b63b36faSFred Richter LG3306_AGC_LOCK, 107f883d603SMichael Ira Krufky }; 108b63b36faSFred Richter 109b63b36faSFred Richter 110b63b36faSFred Richter #ifdef DBG_DUMP 111b63b36faSFred Richter static void lgdt3306a_DumpAllRegs(struct lgdt3306a_state *state); 112b63b36faSFred Richter static void lgdt3306a_DumpRegs(struct lgdt3306a_state *state); 113b63b36faSFred Richter #endif 114b63b36faSFred Richter 115b63b36faSFred Richter 116b63b36faSFred Richter static int lgdt3306a_write_reg(struct lgdt3306a_state *state, u16 reg, u8 val) 117b63b36faSFred Richter { 118b63b36faSFred Richter int ret; 119b63b36faSFred Richter u8 buf[] = { reg >> 8, reg & 0xff, val }; 120b63b36faSFred Richter struct i2c_msg msg = { 121b63b36faSFred Richter .addr = state->cfg->i2c_addr, .flags = 0, 122b63b36faSFred Richter .buf = buf, .len = 3, 123b63b36faSFred Richter }; 124b63b36faSFred Richter 125097117caSMauro Carvalho Chehab dbg_reg("reg: 0x%04x, val: 0x%02x\n", reg, val); 126b63b36faSFred Richter 127b63b36faSFred Richter ret = i2c_transfer(state->i2c_adap, &msg, 1); 128b63b36faSFred Richter 129b63b36faSFred Richter if (ret != 1) { 130097117caSMauro Carvalho Chehab pr_err("error (addr %02x %02x <- %02x, err = %i)\n", 131b63b36faSFred Richter msg.buf[0], msg.buf[1], msg.buf[2], ret); 132b63b36faSFred Richter if (ret < 0) 133b63b36faSFred Richter return ret; 134b63b36faSFred Richter else 135b63b36faSFred Richter return -EREMOTEIO; 136b63b36faSFred Richter } 137b63b36faSFred Richter return 0; 138b63b36faSFred Richter } 139b63b36faSFred Richter 140b63b36faSFred Richter static int lgdt3306a_read_reg(struct lgdt3306a_state *state, u16 reg, u8 *val) 141b63b36faSFred Richter { 142b63b36faSFred Richter int ret; 143b63b36faSFred Richter u8 reg_buf[] = { reg >> 8, reg & 0xff }; 144b63b36faSFred Richter struct i2c_msg msg[] = { 145b63b36faSFred Richter { .addr = state->cfg->i2c_addr, 146b63b36faSFred Richter .flags = 0, .buf = reg_buf, .len = 2 }, 147b63b36faSFred Richter { .addr = state->cfg->i2c_addr, 148b63b36faSFred Richter .flags = I2C_M_RD, .buf = val, .len = 1 }, 149b63b36faSFred Richter }; 150b63b36faSFred Richter 151b63b36faSFred Richter ret = i2c_transfer(state->i2c_adap, msg, 2); 152b63b36faSFred Richter 153b63b36faSFred Richter if (ret != 2) { 154097117caSMauro Carvalho Chehab pr_err("error (addr %02x reg %04x error (ret == %i)\n", 155b63b36faSFred Richter state->cfg->i2c_addr, reg, ret); 156b63b36faSFred Richter if (ret < 0) 157b63b36faSFred Richter return ret; 158b63b36faSFred Richter else 159b63b36faSFred Richter return -EREMOTEIO; 160b63b36faSFred Richter } 161097117caSMauro Carvalho Chehab dbg_reg("reg: 0x%04x, val: 0x%02x\n", reg, *val); 162b63b36faSFred Richter 163b63b36faSFred Richter return 0; 164b63b36faSFred Richter } 165b63b36faSFred Richter 166b63b36faSFred Richter #define read_reg(state, reg) \ 167b63b36faSFred Richter ({ \ 168b63b36faSFred Richter u8 __val; \ 169b63b36faSFred Richter int ret = lgdt3306a_read_reg(state, reg, &__val); \ 170b63b36faSFred Richter if (lg_chkerr(ret)) \ 171b63b36faSFred Richter __val = 0; \ 172b63b36faSFred Richter __val; \ 173b63b36faSFred Richter }) 174b63b36faSFred Richter 175b63b36faSFred Richter static int lgdt3306a_set_reg_bit(struct lgdt3306a_state *state, 176b63b36faSFred Richter u16 reg, int bit, int onoff) 177b63b36faSFred Richter { 178b63b36faSFred Richter u8 val; 179b63b36faSFred Richter int ret; 180b63b36faSFred Richter 181097117caSMauro Carvalho Chehab dbg_reg("reg: 0x%04x, bit: %d, level: %d\n", reg, bit, onoff); 182b63b36faSFred Richter 183b63b36faSFred Richter ret = lgdt3306a_read_reg(state, reg, &val); 184b63b36faSFred Richter if (lg_chkerr(ret)) 185b63b36faSFred Richter goto fail; 186b63b36faSFred Richter 187b63b36faSFred Richter val &= ~(1 << bit); 188b63b36faSFred Richter val |= (onoff & 1) << bit; 189b63b36faSFred Richter 190b63b36faSFred Richter ret = lgdt3306a_write_reg(state, reg, val); 191b63b36faSFred Richter lg_chkerr(ret); 192b63b36faSFred Richter fail: 193b63b36faSFred Richter return ret; 194b63b36faSFred Richter } 195b63b36faSFred Richter 196b63b36faSFred Richter /* ------------------------------------------------------------------------ */ 197b63b36faSFred Richter 198b63b36faSFred Richter static int lgdt3306a_soft_reset(struct lgdt3306a_state *state) 199b63b36faSFred Richter { 200b63b36faSFred Richter int ret; 201b63b36faSFred Richter 202097117caSMauro Carvalho Chehab dbg_info("\n"); 203b63b36faSFred Richter 204b63b36faSFred Richter ret = lgdt3306a_set_reg_bit(state, 0x0000, 7, 0); 205b63b36faSFred Richter if (lg_chkerr(ret)) 206b63b36faSFred Richter goto fail; 207b63b36faSFred Richter 208b63b36faSFred Richter msleep(20); 209b63b36faSFred Richter ret = lgdt3306a_set_reg_bit(state, 0x0000, 7, 1); 210b63b36faSFred Richter lg_chkerr(ret); 211b63b36faSFred Richter 212b63b36faSFred Richter fail: 213b63b36faSFred Richter return ret; 214b63b36faSFred Richter } 215b63b36faSFred Richter 216b63b36faSFred Richter static int lgdt3306a_mpeg_mode(struct lgdt3306a_state *state, 217b63b36faSFred Richter enum lgdt3306a_mpeg_mode mode) 218b63b36faSFred Richter { 219b63b36faSFred Richter u8 val; 220b63b36faSFred Richter int ret; 221b63b36faSFred Richter 222097117caSMauro Carvalho Chehab dbg_info("(%d)\n", mode); 2238e8cd34eSMichael Ira Krufky /* transport packet format */ 2248e8cd34eSMichael Ira Krufky ret = lgdt3306a_set_reg_bit(state, 0x0071, 7, mode == LGDT3306A_MPEG_PARALLEL?1:0); /* TPSENB=0x80 */ 225b63b36faSFred Richter if (lg_chkerr(ret)) 226b63b36faSFred Richter goto fail; 227b63b36faSFred Richter 2288e8cd34eSMichael Ira Krufky /* start of packet signal duration */ 2298e8cd34eSMichael Ira Krufky ret = lgdt3306a_set_reg_bit(state, 0x0071, 6, 0); /* TPSSOPBITEN=0x40; 0=byte duration, 1=bit duration */ 230b63b36faSFred Richter if (lg_chkerr(ret)) 231b63b36faSFred Richter goto fail; 232b63b36faSFred Richter 233b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x0070, &val); 234b63b36faSFred Richter if (lg_chkerr(ret)) 235b63b36faSFred Richter goto fail; 236b63b36faSFred Richter 2378e8cd34eSMichael Ira Krufky val |= 0x10; /* TPCLKSUPB=0x10 */ 238b63b36faSFred Richter 239b63b36faSFred Richter if (mode == LGDT3306A_MPEG_PARALLEL) 240b63b36faSFred Richter val &= ~0x10; 241b63b36faSFred Richter 242b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0070, val); 243b63b36faSFred Richter lg_chkerr(ret); 244b63b36faSFred Richter 245b63b36faSFred Richter fail: 246b63b36faSFred Richter return ret; 247b63b36faSFred Richter } 248b63b36faSFred Richter 249b63b36faSFred Richter static int lgdt3306a_mpeg_mode_polarity(struct lgdt3306a_state *state, 250b63b36faSFred Richter enum lgdt3306a_tp_clock_edge edge, 251b63b36faSFred Richter enum lgdt3306a_tp_valid_polarity valid) 252b63b36faSFred Richter { 253b63b36faSFred Richter u8 val; 254b63b36faSFred Richter int ret; 255b63b36faSFred Richter 256097117caSMauro Carvalho Chehab dbg_info("edge=%d, valid=%d\n", edge, valid); 257b63b36faSFred Richter 258b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x0070, &val); 259b63b36faSFred Richter if (lg_chkerr(ret)) 260b63b36faSFred Richter goto fail; 261b63b36faSFred Richter 2628e8cd34eSMichael Ira Krufky val &= ~0x06; /* TPCLKPOL=0x04, TPVALPOL=0x02 */ 263b63b36faSFred Richter 264b63b36faSFred Richter if (edge == LGDT3306A_TPCLK_RISING_EDGE) 265b63b36faSFred Richter val |= 0x04; 266b63b36faSFred Richter if (valid == LGDT3306A_TP_VALID_HIGH) 267b63b36faSFred Richter val |= 0x02; 268b63b36faSFred Richter 269b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0070, val); 270b63b36faSFred Richter lg_chkerr(ret); 271b63b36faSFred Richter 272b63b36faSFred Richter fail: 273b63b36faSFred Richter return ret; 274b63b36faSFred Richter } 275b63b36faSFred Richter 276b63b36faSFred Richter static int lgdt3306a_mpeg_tristate(struct lgdt3306a_state *state, 277b63b36faSFred Richter int mode) 278b63b36faSFred Richter { 279b63b36faSFred Richter u8 val; 280b63b36faSFred Richter int ret; 281b63b36faSFred Richter 282097117caSMauro Carvalho Chehab dbg_info("(%d)\n", mode); 283b63b36faSFred Richter 284b63b36faSFred Richter if (mode) { 285b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x0070, &val); 286b63b36faSFred Richter if (lg_chkerr(ret)) 287b63b36faSFred Richter goto fail; 2884937ba94SMauro Carvalho Chehab val &= ~0xa8; /* Tristate bus; TPOUTEN=0x80, TPCLKOUTEN=0x20, TPDATAOUTEN=0x08 */ 289b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0070, val); 290b63b36faSFred Richter if (lg_chkerr(ret)) 291b63b36faSFred Richter goto fail; 292b63b36faSFred Richter 2938e8cd34eSMichael Ira Krufky ret = lgdt3306a_set_reg_bit(state, 0x0003, 6, 1); /* AGCIFOUTENB=0x40; 1=Disable IFAGC pin */ 294b63b36faSFred Richter if (lg_chkerr(ret)) 295b63b36faSFred Richter goto fail; 296b63b36faSFred Richter 297b63b36faSFred Richter } else { 2988e8cd34eSMichael Ira Krufky ret = lgdt3306a_set_reg_bit(state, 0x0003, 6, 0); /* enable IFAGC pin */ 299b63b36faSFred Richter if (lg_chkerr(ret)) 300b63b36faSFred Richter goto fail; 301b63b36faSFred Richter 302b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x0070, &val); 303b63b36faSFred Richter if (lg_chkerr(ret)) 304b63b36faSFred Richter goto fail; 305b63b36faSFred Richter 3064937ba94SMauro Carvalho Chehab val |= 0xa8; /* enable bus */ 307b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0070, val); 308b63b36faSFred Richter if (lg_chkerr(ret)) 309b63b36faSFred Richter goto fail; 310b63b36faSFred Richter } 311b63b36faSFred Richter 312b63b36faSFred Richter fail: 313b63b36faSFred Richter return ret; 314b63b36faSFred Richter } 315b63b36faSFred Richter 316b63b36faSFred Richter static int lgdt3306a_ts_bus_ctrl(struct dvb_frontend *fe, int acquire) 317b63b36faSFred Richter { 318b63b36faSFred Richter struct lgdt3306a_state *state = fe->demodulator_priv; 319b63b36faSFred Richter 320097117caSMauro Carvalho Chehab dbg_info("acquire=%d\n", acquire); 321b63b36faSFred Richter 322b63b36faSFred Richter return lgdt3306a_mpeg_tristate(state, acquire ? 0 : 1); 323b63b36faSFred Richter 324b63b36faSFred Richter } 325b63b36faSFred Richter 326b63b36faSFred Richter static int lgdt3306a_power(struct lgdt3306a_state *state, 327b63b36faSFred Richter int mode) 328b63b36faSFred Richter { 329b63b36faSFred Richter int ret; 330b63b36faSFred Richter 331097117caSMauro Carvalho Chehab dbg_info("(%d)\n", mode); 332b63b36faSFred Richter 333b63b36faSFred Richter if (mode == 0) { 3348e8cd34eSMichael Ira Krufky ret = lgdt3306a_set_reg_bit(state, 0x0000, 7, 0); /* into reset */ 335b63b36faSFred Richter if (lg_chkerr(ret)) 336b63b36faSFred Richter goto fail; 337b63b36faSFred Richter 3388e8cd34eSMichael Ira Krufky ret = lgdt3306a_set_reg_bit(state, 0x0000, 0, 0); /* power down */ 339b63b36faSFred Richter if (lg_chkerr(ret)) 340b63b36faSFred Richter goto fail; 341b63b36faSFred Richter 342b63b36faSFred Richter } else { 3438e8cd34eSMichael Ira Krufky ret = lgdt3306a_set_reg_bit(state, 0x0000, 7, 1); /* out of reset */ 344b63b36faSFred Richter if (lg_chkerr(ret)) 345b63b36faSFred Richter goto fail; 346b63b36faSFred Richter 3478e8cd34eSMichael Ira Krufky ret = lgdt3306a_set_reg_bit(state, 0x0000, 0, 1); /* power up */ 348b63b36faSFred Richter if (lg_chkerr(ret)) 349b63b36faSFred Richter goto fail; 350b63b36faSFred Richter } 351b63b36faSFred Richter 352b63b36faSFred Richter #ifdef DBG_DUMP 353b63b36faSFred Richter lgdt3306a_DumpAllRegs(state); 354b63b36faSFred Richter #endif 355b63b36faSFred Richter fail: 356b63b36faSFred Richter return ret; 357b63b36faSFred Richter } 358b63b36faSFred Richter 359b63b36faSFred Richter 360b63b36faSFred Richter static int lgdt3306a_set_vsb(struct lgdt3306a_state *state) 361b63b36faSFred Richter { 362b63b36faSFred Richter u8 val; 363b63b36faSFred Richter int ret; 364b63b36faSFred Richter 365097117caSMauro Carvalho Chehab dbg_info("\n"); 366b63b36faSFred Richter 3678e8cd34eSMichael Ira Krufky /* 0. Spectrum inversion detection manual; spectrum inverted */ 368b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x0002, &val); 3694937ba94SMauro Carvalho Chehab val &= 0xf7; /* SPECINVAUTO Off */ 3708e8cd34eSMichael Ira Krufky val |= 0x04; /* SPECINV On */ 371b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0002, val); 372b63b36faSFred Richter if (lg_chkerr(ret)) 373b63b36faSFred Richter goto fail; 374b63b36faSFred Richter 3758e8cd34eSMichael Ira Krufky /* 1. Selection of standard mode(0x08=QAM, 0x80=VSB) */ 376b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0008, 0x80); 377b63b36faSFred Richter if (lg_chkerr(ret)) 378b63b36faSFred Richter goto fail; 379b63b36faSFred Richter 3808e8cd34eSMichael Ira Krufky /* 2. Bandwidth mode for VSB(6MHz) */ 381b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x0009, &val); 3824937ba94SMauro Carvalho Chehab val &= 0xe3; 3834937ba94SMauro Carvalho Chehab val |= 0x0c; /* STDOPDETTMODE[2:0]=3 */ 384b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0009, val); 385b63b36faSFred Richter if (lg_chkerr(ret)) 386b63b36faSFred Richter goto fail; 387b63b36faSFred Richter 3888e8cd34eSMichael Ira Krufky /* 3. QAM mode detection mode(None) */ 389b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x0009, &val); 3904937ba94SMauro Carvalho Chehab val &= 0xfc; /* STDOPDETCMODE[1:0]=0 */ 391b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0009, val); 392b63b36faSFred Richter if (lg_chkerr(ret)) 393b63b36faSFred Richter goto fail; 394b63b36faSFred Richter 3958e8cd34eSMichael Ira Krufky /* 4. ADC sampling frequency rate(2x sampling) */ 3964937ba94SMauro Carvalho Chehab ret = lgdt3306a_read_reg(state, 0x000d, &val); 3974937ba94SMauro Carvalho Chehab val &= 0xbf; /* SAMPLING4XFEN=0 */ 3984937ba94SMauro Carvalho Chehab ret = lgdt3306a_write_reg(state, 0x000d, val); 399b63b36faSFred Richter if (lg_chkerr(ret)) 400b63b36faSFred Richter goto fail; 401b63b36faSFred Richter 4028e8cd34eSMichael Ira Krufky #if 0 4038e8cd34eSMichael Ira Krufky /* FGR - disable any AICC filtering, testing only */ 4048e8cd34eSMichael Ira Krufky 405b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0024, 0x00); 406b63b36faSFred Richter if (lg_chkerr(ret)) 407b63b36faSFred Richter goto fail; 408b63b36faSFred Richter 4098e8cd34eSMichael Ira Krufky /* AICCFIXFREQ0 NT N-1(Video rejection) */ 4104937ba94SMauro Carvalho Chehab ret = lgdt3306a_write_reg(state, 0x002e, 0x00); 4114937ba94SMauro Carvalho Chehab ret = lgdt3306a_write_reg(state, 0x002f, 0x00); 412b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0030, 0x00); 413b63b36faSFred Richter 4148e8cd34eSMichael Ira Krufky /* AICCFIXFREQ1 NT N-1(Audio rejection) */ 4154937ba94SMauro Carvalho Chehab ret = lgdt3306a_write_reg(state, 0x002b, 0x00); 4164937ba94SMauro Carvalho Chehab ret = lgdt3306a_write_reg(state, 0x002c, 0x00); 4174937ba94SMauro Carvalho Chehab ret = lgdt3306a_write_reg(state, 0x002d, 0x00); 418b63b36faSFred Richter 4198e8cd34eSMichael Ira Krufky /* AICCFIXFREQ2 NT Co-Channel(Video rejection) */ 420b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0028, 0x00); 421b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0029, 0x00); 4224937ba94SMauro Carvalho Chehab ret = lgdt3306a_write_reg(state, 0x002a, 0x00); 423b63b36faSFred Richter 4248e8cd34eSMichael Ira Krufky /* AICCFIXFREQ3 NT Co-Channel(Audio rejection) */ 425b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0025, 0x00); 426b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0026, 0x00); 427b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0027, 0x00); 428b63b36faSFred Richter 4298e8cd34eSMichael Ira Krufky #else 4308e8cd34eSMichael Ira Krufky /* FGR - this works well for HVR-1955,1975 */ 4318e8cd34eSMichael Ira Krufky 4328e8cd34eSMichael Ira Krufky /* 5. AICCOPMODE NT N-1 Adj. */ 433b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0024, 0x5A); 434b63b36faSFred Richter if (lg_chkerr(ret)) 435b63b36faSFred Richter goto fail; 436b63b36faSFred Richter 4378e8cd34eSMichael Ira Krufky /* AICCFIXFREQ0 NT N-1(Video rejection) */ 4384937ba94SMauro Carvalho Chehab ret = lgdt3306a_write_reg(state, 0x002e, 0x5A); 4394937ba94SMauro Carvalho Chehab ret = lgdt3306a_write_reg(state, 0x002f, 0x00); 440b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0030, 0x00); 441b63b36faSFred Richter 4428e8cd34eSMichael Ira Krufky /* AICCFIXFREQ1 NT N-1(Audio rejection) */ 4434937ba94SMauro Carvalho Chehab ret = lgdt3306a_write_reg(state, 0x002b, 0x36); 4444937ba94SMauro Carvalho Chehab ret = lgdt3306a_write_reg(state, 0x002c, 0x00); 4454937ba94SMauro Carvalho Chehab ret = lgdt3306a_write_reg(state, 0x002d, 0x00); 446b63b36faSFred Richter 4478e8cd34eSMichael Ira Krufky /* AICCFIXFREQ2 NT Co-Channel(Video rejection) */ 448b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0028, 0x2A); 449b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0029, 0x00); 4504937ba94SMauro Carvalho Chehab ret = lgdt3306a_write_reg(state, 0x002a, 0x00); 451b63b36faSFred Richter 4528e8cd34eSMichael Ira Krufky /* AICCFIXFREQ3 NT Co-Channel(Audio rejection) */ 453b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0025, 0x06); 454b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0026, 0x00); 455b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0027, 0x00); 456b63b36faSFred Richter #endif 457b63b36faSFred Richter 4584937ba94SMauro Carvalho Chehab ret = lgdt3306a_read_reg(state, 0x001e, &val); 4594937ba94SMauro Carvalho Chehab val &= 0x0f; 4604937ba94SMauro Carvalho Chehab val |= 0xa0; 4614937ba94SMauro Carvalho Chehab ret = lgdt3306a_write_reg(state, 0x001e, val); 462b63b36faSFred Richter 463b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0022, 0x08); 464b63b36faSFred Richter 465b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0023, 0xFF); 466b63b36faSFred Richter 4674937ba94SMauro Carvalho Chehab ret = lgdt3306a_read_reg(state, 0x211f, &val); 4684937ba94SMauro Carvalho Chehab val &= 0xef; 4694937ba94SMauro Carvalho Chehab ret = lgdt3306a_write_reg(state, 0x211f, val); 470b63b36faSFred Richter 471b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x2173, 0x01); 472b63b36faSFred Richter 473b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x1061, &val); 4744937ba94SMauro Carvalho Chehab val &= 0xf8; 475b63b36faSFred Richter val |= 0x04; 476b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x1061, val); 477b63b36faSFred Richter 4784937ba94SMauro Carvalho Chehab ret = lgdt3306a_read_reg(state, 0x103d, &val); 4794937ba94SMauro Carvalho Chehab val &= 0xcf; 4804937ba94SMauro Carvalho Chehab ret = lgdt3306a_write_reg(state, 0x103d, val); 481b63b36faSFred Richter 482b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x2122, 0x40); 483b63b36faSFred Richter 484b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x2141, &val); 4854937ba94SMauro Carvalho Chehab val &= 0x3f; 486b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x2141, val); 487b63b36faSFred Richter 488b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x2135, &val); 4894937ba94SMauro Carvalho Chehab val &= 0x0f; 490b63b36faSFred Richter val |= 0x70; 491b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x2135, val); 492b63b36faSFred Richter 493b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x0003, &val); 4944937ba94SMauro Carvalho Chehab val &= 0xf7; 495b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0003, val); 496b63b36faSFred Richter 4974937ba94SMauro Carvalho Chehab ret = lgdt3306a_read_reg(state, 0x001c, &val); 4984937ba94SMauro Carvalho Chehab val &= 0x7f; 4994937ba94SMauro Carvalho Chehab ret = lgdt3306a_write_reg(state, 0x001c, val); 500b63b36faSFred Richter 5018e8cd34eSMichael Ira Krufky /* 6. EQ step size */ 502b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x2179, &val); 5034937ba94SMauro Carvalho Chehab val &= 0xf8; 504b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x2179, val); 505b63b36faSFred Richter 5064937ba94SMauro Carvalho Chehab ret = lgdt3306a_read_reg(state, 0x217a, &val); 5074937ba94SMauro Carvalho Chehab val &= 0xf8; 5084937ba94SMauro Carvalho Chehab ret = lgdt3306a_write_reg(state, 0x217a, val); 509b63b36faSFred Richter 5108e8cd34eSMichael Ira Krufky /* 7. Reset */ 511b63b36faSFred Richter ret = lgdt3306a_soft_reset(state); 512b63b36faSFred Richter if (lg_chkerr(ret)) 513b63b36faSFred Richter goto fail; 514b63b36faSFred Richter 515097117caSMauro Carvalho Chehab dbg_info("complete\n"); 516b63b36faSFred Richter fail: 517b63b36faSFred Richter return ret; 518b63b36faSFred Richter } 519b63b36faSFred Richter 520b63b36faSFred Richter static int lgdt3306a_set_qam(struct lgdt3306a_state *state, int modulation) 521b63b36faSFred Richter { 522b63b36faSFred Richter u8 val; 523b63b36faSFred Richter int ret; 524b63b36faSFred Richter 525097117caSMauro Carvalho Chehab dbg_info("modulation=%d\n", modulation); 526b63b36faSFred Richter 5278e8cd34eSMichael Ira Krufky /* 1. Selection of standard mode(0x08=QAM, 0x80=VSB) */ 528b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0008, 0x08); 529b63b36faSFred Richter if (lg_chkerr(ret)) 530b63b36faSFred Richter goto fail; 531b63b36faSFred Richter 5328e8cd34eSMichael Ira Krufky /* 1a. Spectrum inversion detection to Auto */ 533b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x0002, &val); 5344937ba94SMauro Carvalho Chehab val &= 0xfb; /* SPECINV Off */ 5358e8cd34eSMichael Ira Krufky val |= 0x08; /* SPECINVAUTO On */ 536b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0002, val); 537b63b36faSFred Richter if (lg_chkerr(ret)) 538b63b36faSFred Richter goto fail; 539b63b36faSFred Richter 5408e8cd34eSMichael Ira Krufky /* 2. Bandwidth mode for QAM */ 541b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x0009, &val); 5424937ba94SMauro Carvalho Chehab val &= 0xe3; /* STDOPDETTMODE[2:0]=0 VSB Off */ 543b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0009, val); 544b63b36faSFred Richter if (lg_chkerr(ret)) 545b63b36faSFred Richter goto fail; 546b63b36faSFred Richter 5478e8cd34eSMichael Ira Krufky /* 3. : 64QAM/256QAM detection(manual, auto) */ 548b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x0009, &val); 5494937ba94SMauro Carvalho Chehab val &= 0xfc; 5508e8cd34eSMichael Ira Krufky val |= 0x02; /* STDOPDETCMODE[1:0]=1=Manual 2=Auto */ 551b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0009, val); 552b63b36faSFred Richter if (lg_chkerr(ret)) 553b63b36faSFred Richter goto fail; 554b63b36faSFred Richter 5558e8cd34eSMichael Ira Krufky /* 3a. : 64QAM/256QAM selection for manual */ 556b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x101a, &val); 5574937ba94SMauro Carvalho Chehab val &= 0xf8; 5588e8cd34eSMichael Ira Krufky if (modulation == QAM_64) 5598e8cd34eSMichael Ira Krufky val |= 0x02; /* QMDQMODE[2:0]=2=QAM64 */ 5608e8cd34eSMichael Ira Krufky else 5618e8cd34eSMichael Ira Krufky val |= 0x04; /* QMDQMODE[2:0]=4=QAM256 */ 5628e8cd34eSMichael Ira Krufky 563b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x101a, val); 564b63b36faSFred Richter if (lg_chkerr(ret)) 565b63b36faSFred Richter goto fail; 566b63b36faSFred Richter 5678e8cd34eSMichael Ira Krufky /* 4. ADC sampling frequency rate(4x sampling) */ 5684937ba94SMauro Carvalho Chehab ret = lgdt3306a_read_reg(state, 0x000d, &val); 5694937ba94SMauro Carvalho Chehab val &= 0xbf; 5708e8cd34eSMichael Ira Krufky val |= 0x40; /* SAMPLING4XFEN=1 */ 5714937ba94SMauro Carvalho Chehab ret = lgdt3306a_write_reg(state, 0x000d, val); 572b63b36faSFred Richter if (lg_chkerr(ret)) 573b63b36faSFred Richter goto fail; 574b63b36faSFred Richter 5758e8cd34eSMichael Ira Krufky /* 5. No AICC operation in QAM mode */ 576b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x0024, &val); 577b63b36faSFred Richter val &= 0x00; 578b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0024, val); 579b63b36faSFred Richter if (lg_chkerr(ret)) 580b63b36faSFred Richter goto fail; 581b63b36faSFred Richter 5828e8cd34eSMichael Ira Krufky /* 6. Reset */ 583b63b36faSFred Richter ret = lgdt3306a_soft_reset(state); 584b63b36faSFred Richter if (lg_chkerr(ret)) 585b63b36faSFred Richter goto fail; 586b63b36faSFred Richter 587097117caSMauro Carvalho Chehab dbg_info("complete\n"); 588b63b36faSFred Richter fail: 589b63b36faSFred Richter return ret; 590b63b36faSFred Richter } 591b63b36faSFred Richter 592b63b36faSFred Richter static int lgdt3306a_set_modulation(struct lgdt3306a_state *state, 593b63b36faSFred Richter struct dtv_frontend_properties *p) 594b63b36faSFred Richter { 595b63b36faSFred Richter int ret; 596b63b36faSFred Richter 597097117caSMauro Carvalho Chehab dbg_info("\n"); 598b63b36faSFred Richter 599b63b36faSFred Richter switch (p->modulation) { 600b63b36faSFred Richter case VSB_8: 601b63b36faSFred Richter ret = lgdt3306a_set_vsb(state); 602b63b36faSFred Richter break; 603b63b36faSFred Richter case QAM_64: 604b63b36faSFred Richter ret = lgdt3306a_set_qam(state, QAM_64); 605b63b36faSFred Richter break; 606b63b36faSFred Richter case QAM_256: 607b63b36faSFred Richter ret = lgdt3306a_set_qam(state, QAM_256); 608b63b36faSFred Richter break; 609b63b36faSFred Richter default: 610b63b36faSFred Richter return -EINVAL; 611b63b36faSFred Richter } 612b63b36faSFred Richter if (lg_chkerr(ret)) 613b63b36faSFred Richter goto fail; 614b63b36faSFred Richter 615b63b36faSFred Richter state->current_modulation = p->modulation; 616b63b36faSFred Richter 617b63b36faSFred Richter fail: 618b63b36faSFred Richter return ret; 619b63b36faSFred Richter } 620b63b36faSFred Richter 621b63b36faSFred Richter /* ------------------------------------------------------------------------ */ 622b63b36faSFred Richter 623b63b36faSFred Richter static int lgdt3306a_agc_setup(struct lgdt3306a_state *state, 624b63b36faSFred Richter struct dtv_frontend_properties *p) 625b63b36faSFred Richter { 6268e8cd34eSMichael Ira Krufky /* TODO: anything we want to do here??? */ 627097117caSMauro Carvalho Chehab dbg_info("\n"); 628b63b36faSFred Richter 629b63b36faSFred Richter switch (p->modulation) { 630b63b36faSFred Richter case VSB_8: 631b63b36faSFred Richter break; 632b63b36faSFred Richter case QAM_64: 633b63b36faSFred Richter case QAM_256: 634b63b36faSFred Richter break; 635b63b36faSFred Richter default: 636b63b36faSFred Richter return -EINVAL; 637b63b36faSFred Richter } 638b63b36faSFred Richter return 0; 639b63b36faSFred Richter } 640b63b36faSFred Richter 641b63b36faSFred Richter /* ------------------------------------------------------------------------ */ 642b63b36faSFred Richter 643b63b36faSFred Richter static int lgdt3306a_set_inversion(struct lgdt3306a_state *state, 644b63b36faSFred Richter int inversion) 645b63b36faSFred Richter { 646b63b36faSFred Richter int ret; 647b63b36faSFred Richter 648097117caSMauro Carvalho Chehab dbg_info("(%d)\n", inversion); 649b63b36faSFred Richter 650b63b36faSFred Richter ret = lgdt3306a_set_reg_bit(state, 0x0002, 2, inversion ? 1 : 0); 651b63b36faSFred Richter return ret; 652b63b36faSFred Richter } 653b63b36faSFred Richter 654b63b36faSFred Richter static int lgdt3306a_set_inversion_auto(struct lgdt3306a_state *state, 655b63b36faSFred Richter int enabled) 656b63b36faSFred Richter { 657b63b36faSFred Richter int ret; 658b63b36faSFred Richter 659097117caSMauro Carvalho Chehab dbg_info("(%d)\n", enabled); 660b63b36faSFred Richter 6618e8cd34eSMichael Ira Krufky /* 0=Manual 1=Auto(QAM only) */ 6628e8cd34eSMichael Ira Krufky ret = lgdt3306a_set_reg_bit(state, 0x0002, 3, enabled);/* SPECINVAUTO=0x04 */ 663b63b36faSFred Richter return ret; 664b63b36faSFred Richter } 665b63b36faSFred Richter 666b63b36faSFred Richter static int lgdt3306a_spectral_inversion(struct lgdt3306a_state *state, 667b63b36faSFred Richter struct dtv_frontend_properties *p, 668b63b36faSFred Richter int inversion) 669b63b36faSFred Richter { 670b63b36faSFred Richter int ret = 0; 671b63b36faSFred Richter 672097117caSMauro Carvalho Chehab dbg_info("(%d)\n", inversion); 6738e8cd34eSMichael Ira Krufky #if 0 6748e8cd34eSMichael Ira Krufky /* FGR - spectral_inversion defaults already set for VSB and QAM; can enable later if desired */ 675b63b36faSFred Richter 676b63b36faSFred Richter ret = lgdt3306a_set_inversion(state, inversion); 677b63b36faSFred Richter 678b63b36faSFred Richter switch (p->modulation) { 679b63b36faSFred Richter case VSB_8: 6808e8cd34eSMichael Ira Krufky ret = lgdt3306a_set_inversion_auto(state, 0); /* Manual only for VSB */ 681b63b36faSFred Richter break; 682b63b36faSFred Richter case QAM_64: 683b63b36faSFred Richter case QAM_256: 6848e8cd34eSMichael Ira Krufky ret = lgdt3306a_set_inversion_auto(state, 1); /* Auto ok for QAM */ 685b63b36faSFred Richter break; 686b63b36faSFred Richter default: 687b63b36faSFred Richter ret = -EINVAL; 688b63b36faSFred Richter } 689b63b36faSFred Richter #endif 690b63b36faSFred Richter return ret; 691b63b36faSFred Richter } 692b63b36faSFred Richter 693b63b36faSFred Richter static int lgdt3306a_set_if(struct lgdt3306a_state *state, 694b63b36faSFred Richter struct dtv_frontend_properties *p) 695b63b36faSFred Richter { 696b63b36faSFred Richter int ret; 697b63b36faSFred Richter u16 if_freq_khz; 698b63b36faSFred Richter u8 nco1, nco2; 699b63b36faSFred Richter 700b63b36faSFred Richter switch (p->modulation) { 701b63b36faSFred Richter case VSB_8: 702b63b36faSFred Richter if_freq_khz = state->cfg->vsb_if_khz; 703b63b36faSFred Richter break; 704b63b36faSFred Richter case QAM_64: 705b63b36faSFred Richter case QAM_256: 706b63b36faSFred Richter if_freq_khz = state->cfg->qam_if_khz; 707b63b36faSFred Richter break; 708b63b36faSFred Richter default: 709b63b36faSFred Richter return -EINVAL; 710b63b36faSFred Richter } 711b63b36faSFred Richter 712b63b36faSFred Richter switch (if_freq_khz) { 713b63b36faSFred Richter default: 714097117caSMauro Carvalho Chehab pr_warn("IF=%d KHz is not supportted, 3250 assumed\n", if_freq_khz); 7158e8cd34eSMichael Ira Krufky /* fallthrough */ 7168e8cd34eSMichael Ira Krufky case 3250: /* 3.25Mhz */ 717b63b36faSFred Richter nco1 = 0x34; 718b63b36faSFred Richter nco2 = 0x00; 719b63b36faSFred Richter break; 7208e8cd34eSMichael Ira Krufky case 3500: /* 3.50Mhz */ 721b63b36faSFred Richter nco1 = 0x38; 722b63b36faSFred Richter nco2 = 0x00; 723b63b36faSFred Richter break; 7248e8cd34eSMichael Ira Krufky case 4000: /* 4.00Mhz */ 725b63b36faSFred Richter nco1 = 0x40; 726b63b36faSFred Richter nco2 = 0x00; 727b63b36faSFred Richter break; 7288e8cd34eSMichael Ira Krufky case 5000: /* 5.00Mhz */ 729b63b36faSFred Richter nco1 = 0x50; 730b63b36faSFred Richter nco2 = 0x00; 731b63b36faSFred Richter break; 7328e8cd34eSMichael Ira Krufky case 5380: /* 5.38Mhz */ 733b63b36faSFred Richter nco1 = 0x56; 734b63b36faSFred Richter nco2 = 0x14; 735b63b36faSFred Richter break; 736b63b36faSFred Richter } 737b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0010, nco1); 738ee0133eeSMauro Carvalho Chehab if (ret) 739ee0133eeSMauro Carvalho Chehab return ret; 740b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0011, nco2); 741ee0133eeSMauro Carvalho Chehab if (ret) 742ee0133eeSMauro Carvalho Chehab return ret; 743b63b36faSFred Richter 744097117caSMauro Carvalho Chehab dbg_info("if_freq=%d KHz->[%04x]\n", if_freq_khz, nco1<<8 | nco2); 745b63b36faSFred Richter 746b63b36faSFred Richter return 0; 747b63b36faSFred Richter } 748b63b36faSFred Richter 749b63b36faSFred Richter /* ------------------------------------------------------------------------ */ 750b63b36faSFred Richter 751b63b36faSFred Richter static int lgdt3306a_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) 752b63b36faSFred Richter { 753b63b36faSFred Richter struct lgdt3306a_state *state = fe->demodulator_priv; 754b63b36faSFred Richter 755b63b36faSFred Richter if (state->cfg->deny_i2c_rptr) { 756097117caSMauro Carvalho Chehab dbg_info("deny_i2c_rptr=%d\n", state->cfg->deny_i2c_rptr); 757b63b36faSFred Richter return 0; 758b63b36faSFred Richter } 759097117caSMauro Carvalho Chehab dbg_info("(%d)\n", enable); 760b63b36faSFred Richter 7618e8cd34eSMichael Ira Krufky return lgdt3306a_set_reg_bit(state, 0x0002, 7, enable ? 0 : 1); /* NI2CRPTEN=0x80 */ 762b63b36faSFred Richter } 763b63b36faSFred Richter 764b63b36faSFred Richter static int lgdt3306a_sleep(struct lgdt3306a_state *state) 765b63b36faSFred Richter { 766b63b36faSFred Richter int ret; 767b63b36faSFred Richter 768097117caSMauro Carvalho Chehab dbg_info("\n"); 7698e8cd34eSMichael Ira Krufky state->current_frequency = -1; /* force re-tune, when we wake */ 770b63b36faSFred Richter 7718e8cd34eSMichael Ira Krufky ret = lgdt3306a_mpeg_tristate(state, 1); /* disable data bus */ 772b63b36faSFred Richter if (lg_chkerr(ret)) 773b63b36faSFred Richter goto fail; 774b63b36faSFred Richter 7758e8cd34eSMichael Ira Krufky ret = lgdt3306a_power(state, 0); /* power down */ 776b63b36faSFred Richter lg_chkerr(ret); 777b63b36faSFred Richter 778b63b36faSFred Richter fail: 779b63b36faSFred Richter return 0; 780b63b36faSFred Richter } 781b63b36faSFred Richter 782b63b36faSFred Richter static int lgdt3306a_fe_sleep(struct dvb_frontend *fe) 783b63b36faSFred Richter { 784b63b36faSFred Richter struct lgdt3306a_state *state = fe->demodulator_priv; 785b63b36faSFred Richter 786b63b36faSFred Richter return lgdt3306a_sleep(state); 787b63b36faSFred Richter } 788b63b36faSFred Richter 789b63b36faSFred Richter static int lgdt3306a_init(struct dvb_frontend *fe) 790b63b36faSFred Richter { 791b63b36faSFred Richter struct lgdt3306a_state *state = fe->demodulator_priv; 792b63b36faSFred Richter u8 val; 793b63b36faSFred Richter int ret; 794b63b36faSFred Richter 795097117caSMauro Carvalho Chehab dbg_info("\n"); 796b63b36faSFred Richter 7978e8cd34eSMichael Ira Krufky /* 1. Normal operation mode */ 7988e8cd34eSMichael Ira Krufky ret = lgdt3306a_set_reg_bit(state, 0x0001, 0, 1); /* SIMFASTENB=0x01 */ 799b63b36faSFred Richter if (lg_chkerr(ret)) 800b63b36faSFred Richter goto fail; 801b63b36faSFred Richter 8028e8cd34eSMichael Ira Krufky /* 2. Spectrum inversion auto detection (Not valid for VSB) */ 803b63b36faSFred Richter ret = lgdt3306a_set_inversion_auto(state, 0); 804b63b36faSFred Richter if (lg_chkerr(ret)) 805b63b36faSFred Richter goto fail; 806b63b36faSFred Richter 8078e8cd34eSMichael Ira Krufky /* 3. Spectrum inversion(According to the tuner configuration) */ 808b63b36faSFred Richter ret = lgdt3306a_set_inversion(state, 1); 809b63b36faSFred Richter if (lg_chkerr(ret)) 810b63b36faSFred Richter goto fail; 811b63b36faSFred Richter 8128e8cd34eSMichael Ira Krufky /* 4. Peak-to-peak voltage of ADC input signal */ 8138e8cd34eSMichael Ira Krufky ret = lgdt3306a_set_reg_bit(state, 0x0004, 7, 1); /* ADCSEL1V=0x80=1Vpp; 0x00=2Vpp */ 814b63b36faSFred Richter if (lg_chkerr(ret)) 815b63b36faSFred Richter goto fail; 816b63b36faSFred Richter 8178e8cd34eSMichael Ira Krufky /* 5. ADC output data capture clock phase */ 8188e8cd34eSMichael Ira Krufky ret = lgdt3306a_set_reg_bit(state, 0x0004, 2, 0); /* 0=same phase as ADC clock */ 819b63b36faSFred Richter if (lg_chkerr(ret)) 820b63b36faSFred Richter goto fail; 821b63b36faSFred Richter 8228e8cd34eSMichael Ira Krufky /* 5a. ADC sampling clock source */ 8238e8cd34eSMichael Ira Krufky ret = lgdt3306a_set_reg_bit(state, 0x0004, 3, 0); /* ADCCLKPLLSEL=0x08; 0=use ext clock, not PLL */ 824b63b36faSFred Richter if (lg_chkerr(ret)) 825b63b36faSFred Richter goto fail; 826b63b36faSFred Richter 8278e8cd34eSMichael Ira Krufky /* 6. Automatic PLL set */ 8288e8cd34eSMichael Ira Krufky ret = lgdt3306a_set_reg_bit(state, 0x0005, 6, 0); /* PLLSETAUTO=0x40; 0=off */ 829b63b36faSFred Richter if (lg_chkerr(ret)) 830b63b36faSFred Richter goto fail; 831b63b36faSFred Richter 8328e8cd34eSMichael Ira Krufky if (state->cfg->xtalMHz == 24) { /* 24MHz */ 8338e8cd34eSMichael Ira Krufky /* 7. Frequency for PLL output(0x2564 for 192MHz for 24MHz) */ 834b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x0005, &val); 835b63b36faSFred Richter if (lg_chkerr(ret)) 836b63b36faSFred Richter goto fail; 8374937ba94SMauro Carvalho Chehab val &= 0xc0; 838b63b36faSFred Richter val |= 0x25; 839b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0005, val); 840b63b36faSFred Richter if (lg_chkerr(ret)) 841b63b36faSFred Richter goto fail; 842b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0006, 0x64); 843b63b36faSFred Richter if (lg_chkerr(ret)) 844b63b36faSFred Richter goto fail; 845b63b36faSFred Richter 8468e8cd34eSMichael Ira Krufky /* 8. ADC sampling frequency(0x180000 for 24MHz sampling) */ 8474937ba94SMauro Carvalho Chehab ret = lgdt3306a_read_reg(state, 0x000d, &val); 848b63b36faSFred Richter if (lg_chkerr(ret)) 849b63b36faSFred Richter goto fail; 8504937ba94SMauro Carvalho Chehab val &= 0xc0; 851b63b36faSFred Richter val |= 0x18; 8524937ba94SMauro Carvalho Chehab ret = lgdt3306a_write_reg(state, 0x000d, val); 853b63b36faSFred Richter if (lg_chkerr(ret)) 854b63b36faSFred Richter goto fail; 855b63b36faSFred Richter 8568e8cd34eSMichael Ira Krufky } else if (state->cfg->xtalMHz == 25) { /* 25MHz */ 8578e8cd34eSMichael Ira Krufky /* 7. Frequency for PLL output */ 858b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x0005, &val); 859b63b36faSFred Richter if (lg_chkerr(ret)) 860b63b36faSFred Richter goto fail; 8614937ba94SMauro Carvalho Chehab val &= 0xc0; 862b63b36faSFred Richter val |= 0x25; 863b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0005, val); 864b63b36faSFred Richter if (lg_chkerr(ret)) 865b63b36faSFred Richter goto fail; 866b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0006, 0x64); 867b63b36faSFred Richter if (lg_chkerr(ret)) 868b63b36faSFred Richter goto fail; 869b63b36faSFred Richter 8708e8cd34eSMichael Ira Krufky /* 8. ADC sampling frequency(0x190000 for 25MHz sampling) */ 8714937ba94SMauro Carvalho Chehab ret = lgdt3306a_read_reg(state, 0x000d, &val); 872b63b36faSFred Richter if (lg_chkerr(ret)) 873b63b36faSFred Richter goto fail; 8744937ba94SMauro Carvalho Chehab val &= 0xc0; 875b63b36faSFred Richter val |= 0x19; 8764937ba94SMauro Carvalho Chehab ret = lgdt3306a_write_reg(state, 0x000d, val); 877b63b36faSFred Richter if (lg_chkerr(ret)) 878b63b36faSFred Richter goto fail; 879b63b36faSFred Richter } else { 880097117caSMauro Carvalho Chehab pr_err("Bad xtalMHz=%d\n", state->cfg->xtalMHz); 881b63b36faSFred Richter } 8828e8cd34eSMichael Ira Krufky #if 0 8834937ba94SMauro Carvalho Chehab ret = lgdt3306a_write_reg(state, 0x000e, 0x00); 8844937ba94SMauro Carvalho Chehab ret = lgdt3306a_write_reg(state, 0x000f, 0x00); 8858e8cd34eSMichael Ira Krufky #endif 886b63b36faSFred Richter 8878e8cd34eSMichael Ira Krufky /* 9. Center frequency of input signal of ADC */ 8888e8cd34eSMichael Ira Krufky ret = lgdt3306a_write_reg(state, 0x0010, 0x34); /* 3.25MHz */ 889b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0011, 0x00); 890b63b36faSFred Richter 8918e8cd34eSMichael Ira Krufky /* 10. Fixed gain error value */ 8928e8cd34eSMichael Ira Krufky ret = lgdt3306a_write_reg(state, 0x0014, 0); /* gain error=0 */ 893b63b36faSFred Richter 8948e8cd34eSMichael Ira Krufky /* 10a. VSB TR BW gear shift initial step */ 8954937ba94SMauro Carvalho Chehab ret = lgdt3306a_read_reg(state, 0x103c, &val); 8964937ba94SMauro Carvalho Chehab val &= 0x0f; 8978e8cd34eSMichael Ira Krufky val |= 0x20; /* SAMGSAUTOSTL_V[3:0] = 2 */ 8984937ba94SMauro Carvalho Chehab ret = lgdt3306a_write_reg(state, 0x103c, val); 899b63b36faSFred Richter 9008e8cd34eSMichael Ira Krufky /* 10b. Timing offset calibration in low temperature for VSB */ 9014937ba94SMauro Carvalho Chehab ret = lgdt3306a_read_reg(state, 0x103d, &val); 9024937ba94SMauro Carvalho Chehab val &= 0xfc; 903b63b36faSFred Richter val |= 0x03; 9044937ba94SMauro Carvalho Chehab ret = lgdt3306a_write_reg(state, 0x103d, val); 905b63b36faSFred Richter 9068e8cd34eSMichael Ira Krufky /* 10c. Timing offset calibration in low temperature for QAM */ 907b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x1036, &val); 9084937ba94SMauro Carvalho Chehab val &= 0xf0; 9094937ba94SMauro Carvalho Chehab val |= 0x0c; 910b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x1036, val); 911b63b36faSFred Richter 9128e8cd34eSMichael Ira Krufky /* 11. Using the imaginary part of CIR in CIR loading */ 9134937ba94SMauro Carvalho Chehab ret = lgdt3306a_read_reg(state, 0x211f, &val); 9144937ba94SMauro Carvalho Chehab val &= 0xef; /* do not use imaginary of CIR */ 9154937ba94SMauro Carvalho Chehab ret = lgdt3306a_write_reg(state, 0x211f, val); 916b63b36faSFred Richter 9178e8cd34eSMichael Ira Krufky /* 12. Control of no signal detector function */ 918b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x2849, &val); 9194937ba94SMauro Carvalho Chehab val &= 0xef; /* NOUSENOSIGDET=0, enable no signal detector */ 920b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x2849, val); 921b63b36faSFred Richter 9228e8cd34eSMichael Ira Krufky /* FGR - put demod in some known mode */ 923b63b36faSFred Richter ret = lgdt3306a_set_vsb(state); 924b63b36faSFred Richter 9258e8cd34eSMichael Ira Krufky /* 13. TP stream format */ 926b63b36faSFred Richter ret = lgdt3306a_mpeg_mode(state, state->cfg->mpeg_mode); 927b63b36faSFred Richter 9288e8cd34eSMichael Ira Krufky /* 14. disable output buses */ 929b63b36faSFred Richter ret = lgdt3306a_mpeg_tristate(state, 1); 930b63b36faSFred Richter 9318e8cd34eSMichael Ira Krufky /* 15. Sleep (in reset) */ 932b63b36faSFred Richter ret = lgdt3306a_sleep(state); 933b63b36faSFred Richter lg_chkerr(ret); 934b63b36faSFred Richter 935b63b36faSFred Richter fail: 936b63b36faSFred Richter return ret; 937b63b36faSFred Richter } 938b63b36faSFred Richter 939b63b36faSFred Richter static int lgdt3306a_set_parameters(struct dvb_frontend *fe) 940b63b36faSFred Richter { 941b63b36faSFred Richter struct dtv_frontend_properties *p = &fe->dtv_property_cache; 942b63b36faSFred Richter struct lgdt3306a_state *state = fe->demodulator_priv; 943b63b36faSFred Richter int ret; 944b63b36faSFred Richter 945097117caSMauro Carvalho Chehab dbg_info("(%d, %d)\n", p->frequency, p->modulation); 946b63b36faSFred Richter 947b63b36faSFred Richter if (state->current_frequency == p->frequency && 948b63b36faSFred Richter state->current_modulation == p->modulation) { 949097117caSMauro Carvalho Chehab dbg_info(" (already set, skipping ...)\n"); 950b63b36faSFred Richter return 0; 951b63b36faSFred Richter } 952b63b36faSFred Richter state->current_frequency = -1; 953b63b36faSFred Richter state->current_modulation = -1; 954b63b36faSFred Richter 9558e8cd34eSMichael Ira Krufky ret = lgdt3306a_power(state, 1); /* power up */ 956b63b36faSFred Richter if (lg_chkerr(ret)) 957b63b36faSFred Richter goto fail; 958b63b36faSFred Richter 959b63b36faSFred Richter if (fe->ops.tuner_ops.set_params) { 960b63b36faSFred Richter ret = fe->ops.tuner_ops.set_params(fe); 961b63b36faSFred Richter if (fe->ops.i2c_gate_ctrl) 962b63b36faSFred Richter fe->ops.i2c_gate_ctrl(fe, 0); 9638e8cd34eSMichael Ira Krufky #if 0 9648e8cd34eSMichael Ira Krufky if (lg_chkerr(ret)) 9658e8cd34eSMichael Ira Krufky goto fail; 9668e8cd34eSMichael Ira Krufky state->current_frequency = p->frequency; 9678e8cd34eSMichael Ira Krufky #endif 968b63b36faSFred Richter } 969b63b36faSFred Richter 970b63b36faSFred Richter ret = lgdt3306a_set_modulation(state, p); 971b63b36faSFred Richter if (lg_chkerr(ret)) 972b63b36faSFred Richter goto fail; 973b63b36faSFred Richter 974b63b36faSFred Richter ret = lgdt3306a_agc_setup(state, p); 975b63b36faSFred Richter if (lg_chkerr(ret)) 976b63b36faSFred Richter goto fail; 977b63b36faSFred Richter 978b63b36faSFred Richter ret = lgdt3306a_set_if(state, p); 979b63b36faSFred Richter if (lg_chkerr(ret)) 980b63b36faSFred Richter goto fail; 981b63b36faSFred Richter 982b63b36faSFred Richter ret = lgdt3306a_spectral_inversion(state, p, 983b63b36faSFred Richter state->cfg->spectral_inversion ? 1 : 0); 984b63b36faSFred Richter if (lg_chkerr(ret)) 985b63b36faSFred Richter goto fail; 986b63b36faSFred Richter 987b63b36faSFred Richter ret = lgdt3306a_mpeg_mode(state, state->cfg->mpeg_mode); 988b63b36faSFred Richter if (lg_chkerr(ret)) 989b63b36faSFred Richter goto fail; 990b63b36faSFred Richter 991b63b36faSFred Richter ret = lgdt3306a_mpeg_mode_polarity(state, 992b63b36faSFred Richter state->cfg->tpclk_edge, 993b63b36faSFred Richter state->cfg->tpvalid_polarity); 994b63b36faSFred Richter if (lg_chkerr(ret)) 995b63b36faSFred Richter goto fail; 996b63b36faSFred Richter 9978e8cd34eSMichael Ira Krufky ret = lgdt3306a_mpeg_tristate(state, 0); /* enable data bus */ 998b63b36faSFred Richter if (lg_chkerr(ret)) 999b63b36faSFred Richter goto fail; 1000b63b36faSFred Richter 1001b63b36faSFred Richter ret = lgdt3306a_soft_reset(state); 1002b63b36faSFred Richter if (lg_chkerr(ret)) 1003b63b36faSFred Richter goto fail; 1004b63b36faSFred Richter 1005b63b36faSFred Richter #ifdef DBG_DUMP 1006b63b36faSFred Richter lgdt3306a_DumpAllRegs(state); 1007b63b36faSFred Richter #endif 1008b63b36faSFred Richter state->current_frequency = p->frequency; 1009b63b36faSFred Richter fail: 1010b63b36faSFred Richter return ret; 1011b63b36faSFred Richter } 1012b63b36faSFred Richter 1013b63b36faSFred Richter static int lgdt3306a_get_frontend(struct dvb_frontend *fe) 1014b63b36faSFred Richter { 1015b63b36faSFred Richter struct lgdt3306a_state *state = fe->demodulator_priv; 1016b63b36faSFred Richter struct dtv_frontend_properties *p = &fe->dtv_property_cache; 1017b63b36faSFred Richter 1018097117caSMauro Carvalho Chehab dbg_info("(%u, %d)\n", state->current_frequency, state->current_modulation); 1019b63b36faSFred Richter 1020b63b36faSFred Richter p->modulation = state->current_modulation; 1021b63b36faSFred Richter p->frequency = state->current_frequency; 1022b63b36faSFred Richter return 0; 1023b63b36faSFred Richter } 1024b63b36faSFred Richter 1025b63b36faSFred Richter static enum dvbfe_algo lgdt3306a_get_frontend_algo(struct dvb_frontend *fe) 1026b63b36faSFred Richter { 1027b63b36faSFred Richter #if 1 1028b63b36faSFred Richter return DVBFE_ALGO_CUSTOM; 1029b63b36faSFred Richter #else 1030b63b36faSFred Richter return DVBFE_ALGO_HW; 1031b63b36faSFred Richter #endif 1032b63b36faSFred Richter } 1033b63b36faSFred Richter 1034b63b36faSFred Richter /* ------------------------------------------------------------------------ */ 1035ee0133eeSMauro Carvalho Chehab static int lgdt3306a_monitor_vsb(struct lgdt3306a_state *state) 1036b63b36faSFred Richter { 1037b63b36faSFred Richter u8 val; 1038b63b36faSFred Richter int ret; 1039b63b36faSFred Richter u8 snrRef, maxPowerMan, nCombDet; 1040b63b36faSFred Richter u16 fbDlyCir; 1041b63b36faSFred Richter 10424937ba94SMauro Carvalho Chehab ret = lgdt3306a_read_reg(state, 0x21a1, &val); 1043ee0133eeSMauro Carvalho Chehab if (ret) 1044ee0133eeSMauro Carvalho Chehab return ret; 10454937ba94SMauro Carvalho Chehab snrRef = val & 0x3f; 1046b63b36faSFred Richter 1047b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x2185, &maxPowerMan); 1048ee0133eeSMauro Carvalho Chehab if (ret) 1049ee0133eeSMauro Carvalho Chehab return ret; 1050b63b36faSFred Richter 1051b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x2191, &val); 1052ee0133eeSMauro Carvalho Chehab if (ret) 1053ee0133eeSMauro Carvalho Chehab return ret; 1054b63b36faSFred Richter nCombDet = (val & 0x80) >> 7; 1055b63b36faSFred Richter 1056b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x2180, &val); 1057ee0133eeSMauro Carvalho Chehab if (ret) 1058ee0133eeSMauro Carvalho Chehab return ret; 1059b63b36faSFred Richter fbDlyCir = (val & 0x03) << 8; 1060ee0133eeSMauro Carvalho Chehab 1061b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x2181, &val); 1062ee0133eeSMauro Carvalho Chehab if (ret) 1063ee0133eeSMauro Carvalho Chehab return ret; 1064b63b36faSFred Richter fbDlyCir |= val; 1065b63b36faSFred Richter 1066097117caSMauro Carvalho Chehab dbg_info("snrRef=%d maxPowerMan=0x%x nCombDet=%d fbDlyCir=0x%x\n", 1067b63b36faSFred Richter snrRef, maxPowerMan, nCombDet, fbDlyCir); 1068b63b36faSFred Richter 10698e8cd34eSMichael Ira Krufky /* Carrier offset sub loop bandwidth */ 1070b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x1061, &val); 1071ee0133eeSMauro Carvalho Chehab if (ret) 1072ee0133eeSMauro Carvalho Chehab return ret; 10734937ba94SMauro Carvalho Chehab val &= 0xf8; 1074b63b36faSFred Richter if ((snrRef > 18) && (maxPowerMan > 0x68) && (nCombDet == 0x01) && ((fbDlyCir == 0x03FF) || (fbDlyCir < 0x6C))) { 10758e8cd34eSMichael Ira Krufky /* SNR is over 18dB and no ghosting */ 10768e8cd34eSMichael Ira Krufky val |= 0x00; /* final bandwidth = 0 */ 1077b63b36faSFred Richter } else { 10788e8cd34eSMichael Ira Krufky val |= 0x04; /* final bandwidth = 4 */ 1079b63b36faSFred Richter } 1080b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x1061, val); 1081ee0133eeSMauro Carvalho Chehab if (ret) 1082ee0133eeSMauro Carvalho Chehab return ret; 1083b63b36faSFred Richter 10848e8cd34eSMichael Ira Krufky /* Adjust Notch Filter */ 1085b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x0024, &val); 1086ee0133eeSMauro Carvalho Chehab if (ret) 1087ee0133eeSMauro Carvalho Chehab return ret; 10884937ba94SMauro Carvalho Chehab val &= 0x0f; 10898e8cd34eSMichael Ira Krufky if (nCombDet == 0) { /* Turn on the Notch Filter */ 1090b63b36faSFred Richter val |= 0x50; 1091b63b36faSFred Richter } 1092b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0024, val); 1093ee0133eeSMauro Carvalho Chehab if (ret) 1094ee0133eeSMauro Carvalho Chehab return ret; 1095b63b36faSFred Richter 10968e8cd34eSMichael Ira Krufky /* VSB Timing Recovery output normalization */ 10974937ba94SMauro Carvalho Chehab ret = lgdt3306a_read_reg(state, 0x103d, &val); 1098ee0133eeSMauro Carvalho Chehab if (ret) 1099ee0133eeSMauro Carvalho Chehab return ret; 11004937ba94SMauro Carvalho Chehab val &= 0xcf; 1101b63b36faSFred Richter val |= 0x20; 11024937ba94SMauro Carvalho Chehab ret = lgdt3306a_write_reg(state, 0x103d, val); 1103ee0133eeSMauro Carvalho Chehab 1104ee0133eeSMauro Carvalho Chehab return ret; 1105b63b36faSFred Richter } 1106b63b36faSFred Richter 1107f883d603SMichael Ira Krufky static enum lgdt3306a_modulation lgdt3306a_check_oper_mode(struct lgdt3306a_state *state) 1108b63b36faSFred Richter { 1109b63b36faSFred Richter u8 val = 0; 1110b63b36faSFred Richter int ret; 1111b63b36faSFred Richter 1112b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x0081, &val); 1113ee0133eeSMauro Carvalho Chehab if (ret) 1114ee0133eeSMauro Carvalho Chehab goto err; 1115b63b36faSFred Richter 1116b63b36faSFred Richter if (val & 0x80) { 1117097117caSMauro Carvalho Chehab dbg_info("VSB\n"); 11188e8cd34eSMichael Ira Krufky return LG3306_VSB; 1119b63b36faSFred Richter } 1120c714efe4SMichael Ira Krufky if (val & 0x08) { 11214937ba94SMauro Carvalho Chehab ret = lgdt3306a_read_reg(state, 0x00a6, &val); 1122ee0133eeSMauro Carvalho Chehab if (ret) 1123ee0133eeSMauro Carvalho Chehab goto err; 1124b63b36faSFred Richter val = val >> 2; 1125b63b36faSFred Richter if (val & 0x01) { 1126097117caSMauro Carvalho Chehab dbg_info("QAM256\n"); 11278e8cd34eSMichael Ira Krufky return LG3306_QAM256; 1128b4e43e95SMauro Carvalho Chehab } 1129097117caSMauro Carvalho Chehab dbg_info("QAM64\n"); 11308e8cd34eSMichael Ira Krufky return LG3306_QAM64; 1131b63b36faSFred Richter } 1132ee0133eeSMauro Carvalho Chehab err: 1133097117caSMauro Carvalho Chehab pr_warn("UNKNOWN\n"); 11348e8cd34eSMichael Ira Krufky return LG3306_UNKNOWN_MODE; 1135b63b36faSFred Richter } 1136b63b36faSFred Richter 1137f883d603SMichael Ira Krufky static enum lgdt3306a_lock_status lgdt3306a_check_lock_status(struct lgdt3306a_state *state, 1138f883d603SMichael Ira Krufky enum lgdt3306a_lock_check whatLock) 1139b63b36faSFred Richter { 1140b63b36faSFred Richter u8 val = 0; 1141b63b36faSFred Richter int ret; 1142f883d603SMichael Ira Krufky enum lgdt3306a_modulation modeOper; 1143f883d603SMichael Ira Krufky enum lgdt3306a_lock_status lockStatus; 1144b63b36faSFred Richter 1145b63b36faSFred Richter modeOper = LG3306_UNKNOWN_MODE; 1146b63b36faSFred Richter 11478e8cd34eSMichael Ira Krufky switch (whatLock) { 1148b63b36faSFred Richter case LG3306_SYNC_LOCK: 1149b63b36faSFred Richter { 11504937ba94SMauro Carvalho Chehab ret = lgdt3306a_read_reg(state, 0x00a6, &val); 1151ee0133eeSMauro Carvalho Chehab if (ret) 1152ee0133eeSMauro Carvalho Chehab return ret; 1153b63b36faSFred Richter 1154b63b36faSFred Richter if ((val & 0x80) == 0x80) 1155b63b36faSFred Richter lockStatus = LG3306_LOCK; 1156b63b36faSFred Richter else 1157b63b36faSFred Richter lockStatus = LG3306_UNLOCK; 1158b63b36faSFred Richter 1159097117caSMauro Carvalho Chehab dbg_info("SYNC_LOCK=%x\n", lockStatus); 1160b63b36faSFred Richter break; 1161b63b36faSFred Richter } 1162b63b36faSFred Richter case LG3306_AGC_LOCK: 1163b63b36faSFred Richter { 1164b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x0080, &val); 1165ee0133eeSMauro Carvalho Chehab if (ret) 1166ee0133eeSMauro Carvalho Chehab return ret; 1167b63b36faSFred Richter 1168b63b36faSFred Richter if ((val & 0x40) == 0x40) 1169b63b36faSFred Richter lockStatus = LG3306_LOCK; 1170b63b36faSFred Richter else 1171b63b36faSFred Richter lockStatus = LG3306_UNLOCK; 1172b63b36faSFred Richter 1173097117caSMauro Carvalho Chehab dbg_info("AGC_LOCK=%x\n", lockStatus); 1174b63b36faSFred Richter break; 1175b63b36faSFred Richter } 1176b63b36faSFred Richter case LG3306_TR_LOCK: 1177b63b36faSFred Richter { 1178b63b36faSFred Richter modeOper = lgdt3306a_check_oper_mode(state); 11798e8cd34eSMichael Ira Krufky if ((modeOper == LG3306_QAM64) || (modeOper == LG3306_QAM256)) { 1180b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x1094, &val); 1181ee0133eeSMauro Carvalho Chehab if (ret) 1182ee0133eeSMauro Carvalho Chehab return ret; 1183b63b36faSFred Richter 1184b63b36faSFred Richter if ((val & 0x80) == 0x80) 1185b63b36faSFred Richter lockStatus = LG3306_LOCK; 1186b63b36faSFred Richter else 1187b63b36faSFred Richter lockStatus = LG3306_UNLOCK; 11888e8cd34eSMichael Ira Krufky } else 1189b63b36faSFred Richter lockStatus = LG3306_UNKNOWN_LOCK; 1190b63b36faSFred Richter 1191097117caSMauro Carvalho Chehab dbg_info("TR_LOCK=%x\n", lockStatus); 1192b63b36faSFred Richter break; 1193b63b36faSFred Richter } 1194b63b36faSFred Richter case LG3306_FEC_LOCK: 1195b63b36faSFred Richter { 1196b63b36faSFred Richter modeOper = lgdt3306a_check_oper_mode(state); 11978e8cd34eSMichael Ira Krufky if ((modeOper == LG3306_QAM64) || (modeOper == LG3306_QAM256)) { 1198b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x0080, &val); 1199ee0133eeSMauro Carvalho Chehab if (ret) 1200ee0133eeSMauro Carvalho Chehab return ret; 1201b63b36faSFred Richter 1202b63b36faSFred Richter if ((val & 0x10) == 0x10) 1203b63b36faSFred Richter lockStatus = LG3306_LOCK; 1204b63b36faSFred Richter else 1205b63b36faSFred Richter lockStatus = LG3306_UNLOCK; 12068e8cd34eSMichael Ira Krufky } else 1207b63b36faSFred Richter lockStatus = LG3306_UNKNOWN_LOCK; 1208b63b36faSFred Richter 1209097117caSMauro Carvalho Chehab dbg_info("FEC_LOCK=%x\n", lockStatus); 1210b63b36faSFred Richter break; 1211b63b36faSFred Richter } 1212b63b36faSFred Richter 1213b63b36faSFred Richter default: 1214b63b36faSFred Richter lockStatus = LG3306_UNKNOWN_LOCK; 1215097117caSMauro Carvalho Chehab pr_warn("UNKNOWN whatLock=%d\n", whatLock); 1216b63b36faSFred Richter break; 1217b63b36faSFred Richter } 1218b63b36faSFred Richter 12198e8cd34eSMichael Ira Krufky return lockStatus; 1220b63b36faSFred Richter } 1221b63b36faSFred Richter 1222f883d603SMichael Ira Krufky static enum lgdt3306a_neverlock_status lgdt3306a_check_neverlock_status(struct lgdt3306a_state *state) 1223b63b36faSFred Richter { 1224b63b36faSFred Richter u8 val = 0; 1225b63b36faSFred Richter int ret; 1226f883d603SMichael Ira Krufky enum lgdt3306a_neverlock_status lockStatus; 1227b63b36faSFred Richter 1228b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x0080, &val); 1229ee0133eeSMauro Carvalho Chehab if (ret) 1230ee0133eeSMauro Carvalho Chehab return ret; 1231f883d603SMichael Ira Krufky lockStatus = (enum lgdt3306a_neverlock_status)(val & 0x03); 1232b63b36faSFred Richter 1233097117caSMauro Carvalho Chehab dbg_info("NeverLock=%d", lockStatus); 1234b63b36faSFred Richter 12358e8cd34eSMichael Ira Krufky return lockStatus; 1236b63b36faSFred Richter } 1237b63b36faSFred Richter 1238ee0133eeSMauro Carvalho Chehab static int lgdt3306a_pre_monitoring(struct lgdt3306a_state *state) 1239b63b36faSFred Richter { 1240b63b36faSFred Richter u8 val = 0; 1241b63b36faSFred Richter int ret; 1242b63b36faSFred Richter u8 currChDiffACQ, snrRef, mainStrong, aiccrejStatus; 1243b63b36faSFred Richter 12448e8cd34eSMichael Ira Krufky /* Channel variation */ 12454937ba94SMauro Carvalho Chehab ret = lgdt3306a_read_reg(state, 0x21bc, &currChDiffACQ); 1246ee0133eeSMauro Carvalho Chehab if (ret) 1247ee0133eeSMauro Carvalho Chehab return ret; 1248b63b36faSFred Richter 12498e8cd34eSMichael Ira Krufky /* SNR of Frame sync */ 12504937ba94SMauro Carvalho Chehab ret = lgdt3306a_read_reg(state, 0x21a1, &val); 1251ee0133eeSMauro Carvalho Chehab if (ret) 1252ee0133eeSMauro Carvalho Chehab return ret; 12534937ba94SMauro Carvalho Chehab snrRef = val & 0x3f; 1254b63b36faSFred Richter 12558e8cd34eSMichael Ira Krufky /* Strong Main CIR */ 1256b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x2199, &val); 1257ee0133eeSMauro Carvalho Chehab if (ret) 1258ee0133eeSMauro Carvalho Chehab return ret; 1259b63b36faSFred Richter mainStrong = (val & 0x40) >> 6; 1260b63b36faSFred Richter 1261b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x0090, &val); 1262ee0133eeSMauro Carvalho Chehab if (ret) 1263ee0133eeSMauro Carvalho Chehab return ret; 12644937ba94SMauro Carvalho Chehab aiccrejStatus = (val & 0xf0) >> 4; 1265b63b36faSFred Richter 1266097117caSMauro Carvalho Chehab dbg_info("snrRef=%d mainStrong=%d aiccrejStatus=%d currChDiffACQ=0x%x\n", 1267b63b36faSFred Richter snrRef, mainStrong, aiccrejStatus, currChDiffACQ); 1268b63b36faSFred Richter 12698e8cd34eSMichael Ira Krufky #if 0 12708e8cd34eSMichael Ira Krufky if ((mainStrong == 0) && (currChDiffACQ > 0x70)) /* Dynamic ghost exists */ 12718e8cd34eSMichael Ira Krufky #endif 12728e8cd34eSMichael Ira Krufky if (mainStrong == 0) { 1273b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x2135, &val); 1274ee0133eeSMauro Carvalho Chehab if (ret) 1275ee0133eeSMauro Carvalho Chehab return ret; 12764937ba94SMauro Carvalho Chehab val &= 0x0f; 12774937ba94SMauro Carvalho Chehab val |= 0xa0; 1278b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x2135, val); 1279ee0133eeSMauro Carvalho Chehab if (ret) 1280ee0133eeSMauro Carvalho Chehab return ret; 1281b63b36faSFred Richter 1282b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x2141, &val); 1283ee0133eeSMauro Carvalho Chehab if (ret) 1284ee0133eeSMauro Carvalho Chehab return ret; 12854937ba94SMauro Carvalho Chehab val &= 0x3f; 1286b63b36faSFred Richter val |= 0x80; 1287b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x2141, val); 1288ee0133eeSMauro Carvalho Chehab if (ret) 1289ee0133eeSMauro Carvalho Chehab return ret; 1290b63b36faSFred Richter 1291b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x2122, 0x70); 1292ee0133eeSMauro Carvalho Chehab if (ret) 1293ee0133eeSMauro Carvalho Chehab return ret; 12948e8cd34eSMichael Ira Krufky } else { /* Weak ghost or static channel */ 1295b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x2135, &val); 1296ee0133eeSMauro Carvalho Chehab if (ret) 1297ee0133eeSMauro Carvalho Chehab return ret; 12984937ba94SMauro Carvalho Chehab val &= 0x0f; 1299b63b36faSFred Richter val |= 0x70; 1300b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x2135, val); 1301ee0133eeSMauro Carvalho Chehab if (ret) 1302ee0133eeSMauro Carvalho Chehab return ret; 1303b63b36faSFred Richter 1304b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x2141, &val); 1305ee0133eeSMauro Carvalho Chehab if (ret) 1306ee0133eeSMauro Carvalho Chehab return ret; 13074937ba94SMauro Carvalho Chehab val &= 0x3f; 1308b63b36faSFred Richter val |= 0x40; 1309b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x2141, val); 1310ee0133eeSMauro Carvalho Chehab if (ret) 1311ee0133eeSMauro Carvalho Chehab return ret; 1312b63b36faSFred Richter 1313b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x2122, 0x40); 1314ee0133eeSMauro Carvalho Chehab if (ret) 1315ee0133eeSMauro Carvalho Chehab return ret; 1316b63b36faSFred Richter } 1317ee0133eeSMauro Carvalho Chehab return 0; 1318b63b36faSFred Richter } 1319b63b36faSFred Richter 1320f883d603SMichael Ira Krufky static enum lgdt3306a_lock_status lgdt3306a_sync_lock_poll(struct lgdt3306a_state *state) 1321b63b36faSFred Richter { 1322f883d603SMichael Ira Krufky enum lgdt3306a_lock_status syncLockStatus = LG3306_UNLOCK; 1323b63b36faSFred Richter int i; 1324b63b36faSFred Richter 1325b63b36faSFred Richter for (i = 0; i < 2; i++) { 1326b63b36faSFred Richter msleep(30); 1327b63b36faSFred Richter 1328b63b36faSFred Richter syncLockStatus = lgdt3306a_check_lock_status(state, LG3306_SYNC_LOCK); 1329b63b36faSFred Richter 1330b63b36faSFred Richter if (syncLockStatus == LG3306_LOCK) { 1331097117caSMauro Carvalho Chehab dbg_info("locked(%d)\n", i); 13328e8cd34eSMichael Ira Krufky return LG3306_LOCK; 1333b63b36faSFred Richter } 1334b63b36faSFred Richter } 1335097117caSMauro Carvalho Chehab dbg_info("not locked\n"); 13368e8cd34eSMichael Ira Krufky return LG3306_UNLOCK; 1337b63b36faSFred Richter } 1338b63b36faSFred Richter 1339f883d603SMichael Ira Krufky static enum lgdt3306a_lock_status lgdt3306a_fec_lock_poll(struct lgdt3306a_state *state) 1340b63b36faSFred Richter { 1341f883d603SMichael Ira Krufky enum lgdt3306a_lock_status FECLockStatus = LG3306_UNLOCK; 1342b63b36faSFred Richter int i; 1343b63b36faSFred Richter 1344b63b36faSFred Richter for (i = 0; i < 2; i++) { 1345b63b36faSFred Richter msleep(30); 1346b63b36faSFred Richter 1347b63b36faSFred Richter FECLockStatus = lgdt3306a_check_lock_status(state, LG3306_FEC_LOCK); 1348b63b36faSFred Richter 1349b63b36faSFred Richter if (FECLockStatus == LG3306_LOCK) { 1350097117caSMauro Carvalho Chehab dbg_info("locked(%d)\n", i); 13518e8cd34eSMichael Ira Krufky return FECLockStatus; 1352b63b36faSFred Richter } 1353b63b36faSFred Richter } 1354097117caSMauro Carvalho Chehab dbg_info("not locked\n"); 13558e8cd34eSMichael Ira Krufky return FECLockStatus; 1356b63b36faSFred Richter } 1357b63b36faSFred Richter 1358f883d603SMichael Ira Krufky static enum lgdt3306a_neverlock_status lgdt3306a_neverlock_poll(struct lgdt3306a_state *state) 1359b63b36faSFred Richter { 1360f883d603SMichael Ira Krufky enum lgdt3306a_neverlock_status NLLockStatus = LG3306_NL_FAIL; 1361b63b36faSFred Richter int i; 1362b63b36faSFred Richter 1363b63b36faSFred Richter for (i = 0; i < 5; i++) { 1364b63b36faSFred Richter msleep(30); 1365b63b36faSFred Richter 1366b63b36faSFred Richter NLLockStatus = lgdt3306a_check_neverlock_status(state); 1367b63b36faSFred Richter 1368b63b36faSFred Richter if (NLLockStatus == LG3306_NL_LOCK) { 1369097117caSMauro Carvalho Chehab dbg_info("NL_LOCK(%d)\n", i); 13708e8cd34eSMichael Ira Krufky return NLLockStatus; 1371b63b36faSFred Richter } 1372b63b36faSFred Richter } 1373097117caSMauro Carvalho Chehab dbg_info("NLLockStatus=%d\n", NLLockStatus); 13748e8cd34eSMichael Ira Krufky return NLLockStatus; 1375b63b36faSFred Richter } 1376b63b36faSFred Richter 1377b63b36faSFred Richter static u8 lgdt3306a_get_packet_error(struct lgdt3306a_state *state) 1378b63b36faSFred Richter { 1379b63b36faSFred Richter u8 val; 1380b63b36faSFred Richter int ret; 1381b63b36faSFred Richter 13824937ba94SMauro Carvalho Chehab ret = lgdt3306a_read_reg(state, 0x00fa, &val); 1383ee0133eeSMauro Carvalho Chehab if (ret) 1384ee0133eeSMauro Carvalho Chehab return ret; 1385b63b36faSFred Richter 13868e8cd34eSMichael Ira Krufky return val; 1387b63b36faSFred Richter } 1388b63b36faSFred Richter 1389b63b36faSFred Richter static u32 log10_x1000(u32 x) 1390b63b36faSFred Richter { 1391b63b36faSFred Richter static u32 valx_x10[] = { 10, 11, 13, 15, 17, 20, 25, 33, 41, 50, 59, 73, 87, 100 }; 1392b63b36faSFred Richter static u32 log10x_x1000[] = { 0, 41, 114, 176, 230, 301, 398, 518, 613, 699, 771, 863, 939, 1000 }; 1393b63b36faSFred Richter static u32 nelems = sizeof(valx_x10)/sizeof(valx_x10[0]); 1394a132fef8SMauro Carvalho Chehab u32 diff_val, step_val, step_log10; 1395b63b36faSFred Richter u32 log_val = 0; 1396b63b36faSFred Richter u32 i; 1397b63b36faSFred Richter 1398b63b36faSFred Richter if (x <= 0) 13998e8cd34eSMichael Ira Krufky return -1000000; /* signal error */ 1400b63b36faSFred Richter 1401b4e43e95SMauro Carvalho Chehab if (x == 10) 1402b4e43e95SMauro Carvalho Chehab return 0; /* log(1)=0 */ 1403b4e43e95SMauro Carvalho Chehab 1404b63b36faSFred Richter if (x < 10) { 1405b63b36faSFred Richter while (x < 10) { 1406b63b36faSFred Richter x = x * 10; 1407b63b36faSFred Richter log_val--; 1408b63b36faSFred Richter } 1409b4e43e95SMauro Carvalho Chehab } else { /* x > 10 */ 1410b63b36faSFred Richter while (x >= 100) { 1411b63b36faSFred Richter x = x / 10; 1412b63b36faSFred Richter log_val++; 1413b63b36faSFred Richter } 1414b63b36faSFred Richter } 1415b63b36faSFred Richter log_val *= 1000; 1416b63b36faSFred Richter 14178e8cd34eSMichael Ira Krufky if (x == 10) /* was our input an exact multiple of 10 */ 14188e8cd34eSMichael Ira Krufky return log_val; /* don't need to interpolate */ 1419b63b36faSFred Richter 14208e8cd34eSMichael Ira Krufky /* find our place on the log curve */ 1421b63b36faSFred Richter for (i = 1; i < nelems; i++) { 14228e8cd34eSMichael Ira Krufky if (valx_x10[i] >= x) 14238e8cd34eSMichael Ira Krufky break; 1424b63b36faSFred Richter } 1425a132fef8SMauro Carvalho Chehab if (i == nelems) 1426a132fef8SMauro Carvalho Chehab return log_val + log10x_x1000[i - 1]; 1427b63b36faSFred Richter 1428a132fef8SMauro Carvalho Chehab diff_val = x - valx_x10[i-1]; 1429a132fef8SMauro Carvalho Chehab step_val = valx_x10[i] - valx_x10[i - 1]; 1430a132fef8SMauro Carvalho Chehab step_log10 = log10x_x1000[i] - log10x_x1000[i - 1]; 1431a132fef8SMauro Carvalho Chehab 14328e8cd34eSMichael Ira Krufky /* do a linear interpolation to get in-between values */ 14338e8cd34eSMichael Ira Krufky return log_val + log10x_x1000[i - 1] + 14348e8cd34eSMichael Ira Krufky ((diff_val*step_log10) / step_val); 1435b63b36faSFred Richter } 1436b63b36faSFred Richter 1437b63b36faSFred Richter static u32 lgdt3306a_calculate_snr_x100(struct lgdt3306a_state *state) 1438b63b36faSFred Richter { 1439b63b36faSFred Richter u32 mse; /* Mean-Square Error */ 1440b63b36faSFred Richter u32 pwr; /* Constelation power */ 1441b63b36faSFred Richter u32 snr_x100; 1442b63b36faSFred Richter 14434937ba94SMauro Carvalho Chehab mse = (read_reg(state, 0x00ec) << 8) | 14444937ba94SMauro Carvalho Chehab (read_reg(state, 0x00ed)); 14454937ba94SMauro Carvalho Chehab pwr = (read_reg(state, 0x00e8) << 8) | 14464937ba94SMauro Carvalho Chehab (read_reg(state, 0x00e9)); 1447b63b36faSFred Richter 1448b63b36faSFred Richter if (mse == 0) /* no signal */ 1449b63b36faSFred Richter return 0; 1450b63b36faSFred Richter 1451b63b36faSFred Richter snr_x100 = log10_x1000((pwr * 10000) / mse) - 3000; 1452097117caSMauro Carvalho Chehab dbg_info("mse=%u, pwr=%u, snr_x100=%d\n", mse, pwr, snr_x100); 1453b63b36faSFred Richter 1454b63b36faSFred Richter return snr_x100; 1455b63b36faSFred Richter } 1456b63b36faSFred Richter 1457f883d603SMichael Ira Krufky static enum lgdt3306a_lock_status lgdt3306a_vsb_lock_poll(struct lgdt3306a_state *state) 1458b63b36faSFred Richter { 1459e2c47fa7SMauro Carvalho Chehab int ret; 1460b63b36faSFred Richter u8 cnt = 0; 1461b63b36faSFred Richter u8 packet_error; 1462b63b36faSFred Richter u32 snr; 1463b63b36faSFred Richter 1464b1a88c71SMauro Carvalho Chehab for (cnt = 0; cnt < 10; cnt++) { 1465b63b36faSFred Richter if (lgdt3306a_sync_lock_poll(state) == LG3306_UNLOCK) { 1466097117caSMauro Carvalho Chehab dbg_info("no sync lock!\n"); 14678e8cd34eSMichael Ira Krufky return LG3306_UNLOCK; 1468b1a88c71SMauro Carvalho Chehab } 1469b1a88c71SMauro Carvalho Chehab 1470b63b36faSFred Richter msleep(20); 1471ee0133eeSMauro Carvalho Chehab ret = lgdt3306a_pre_monitoring(state); 1472ee0133eeSMauro Carvalho Chehab if (ret) 1473b1a88c71SMauro Carvalho Chehab break; 1474b63b36faSFred Richter 1475b63b36faSFred Richter packet_error = lgdt3306a_get_packet_error(state); 1476b63b36faSFred Richter snr = lgdt3306a_calculate_snr_x100(state); 1477b1a88c71SMauro Carvalho Chehab dbg_info("cnt=%d errors=%d snr=%d\n", cnt, packet_error, snr); 1478b63b36faSFred Richter 1479b1a88c71SMauro Carvalho Chehab if ((snr >= 1500) && (packet_error < 0xff)) 14808e8cd34eSMichael Ira Krufky return LG3306_LOCK; 1481b1a88c71SMauro Carvalho Chehab } 1482b63b36faSFred Richter 1483097117caSMauro Carvalho Chehab dbg_info("not locked!\n"); 14848e8cd34eSMichael Ira Krufky return LG3306_UNLOCK; 1485b63b36faSFred Richter } 1486b63b36faSFred Richter 1487f883d603SMichael Ira Krufky static enum lgdt3306a_lock_status lgdt3306a_qam_lock_poll(struct lgdt3306a_state *state) 1488b63b36faSFred Richter { 1489b1a88c71SMauro Carvalho Chehab u8 cnt; 1490b63b36faSFred Richter u8 packet_error; 1491b63b36faSFred Richter u32 snr; 1492b63b36faSFred Richter 1493b1a88c71SMauro Carvalho Chehab for (cnt = 0; cnt < 10; cnt++) { 1494b63b36faSFred Richter if (lgdt3306a_fec_lock_poll(state) == LG3306_UNLOCK) { 1495097117caSMauro Carvalho Chehab dbg_info("no fec lock!\n"); 14968e8cd34eSMichael Ira Krufky return LG3306_UNLOCK; 1497b1a88c71SMauro Carvalho Chehab } 1498b1a88c71SMauro Carvalho Chehab 1499b63b36faSFred Richter msleep(20); 1500b63b36faSFred Richter 1501b63b36faSFred Richter packet_error = lgdt3306a_get_packet_error(state); 1502b63b36faSFred Richter snr = lgdt3306a_calculate_snr_x100(state); 1503b1a88c71SMauro Carvalho Chehab dbg_info("cnt=%d errors=%d snr=%d\n", cnt, packet_error, snr); 1504b63b36faSFred Richter 1505b1a88c71SMauro Carvalho Chehab if ((snr >= 1500) && (packet_error < 0xff)) 15068e8cd34eSMichael Ira Krufky return LG3306_LOCK; 1507b1a88c71SMauro Carvalho Chehab } 1508b63b36faSFred Richter 1509097117caSMauro Carvalho Chehab dbg_info("not locked!\n"); 15108e8cd34eSMichael Ira Krufky return LG3306_UNLOCK; 1511b63b36faSFred Richter } 1512b63b36faSFred Richter 1513b63b36faSFred Richter static int lgdt3306a_read_status(struct dvb_frontend *fe, fe_status_t *status) 1514b63b36faSFred Richter { 1515b63b36faSFred Richter struct lgdt3306a_state *state = fe->demodulator_priv; 1516b63b36faSFred Richter u16 strength = 0; 15178e8cd34eSMichael Ira Krufky int ret = 0; 15188e8cd34eSMichael Ira Krufky 1519b63b36faSFred Richter if (fe->ops.tuner_ops.get_rf_strength) { 1520b63b36faSFred Richter ret = fe->ops.tuner_ops.get_rf_strength(fe, &strength); 1521*c9897649SMauro Carvalho Chehab if (ret == 0) 1522097117caSMauro Carvalho Chehab dbg_info("strength=%d\n", strength); 1523*c9897649SMauro Carvalho Chehab else 1524097117caSMauro Carvalho Chehab dbg_info("fe->ops.tuner_ops.get_rf_strength() failed\n"); 1525b63b36faSFred Richter } 1526b63b36faSFred Richter 1527b63b36faSFred Richter *status = 0; 1528b63b36faSFred Richter if (lgdt3306a_neverlock_poll(state) == LG3306_NL_LOCK) { 1529b63b36faSFred Richter *status |= FE_HAS_SIGNAL; 1530b63b36faSFred Richter *status |= FE_HAS_CARRIER; 1531b63b36faSFred Richter 1532b63b36faSFred Richter switch (state->current_modulation) { 1533b63b36faSFred Richter case QAM_256: 1534b63b36faSFred Richter case QAM_64: 1535b63b36faSFred Richter if (lgdt3306a_qam_lock_poll(state) == LG3306_LOCK) { 1536b63b36faSFred Richter *status |= FE_HAS_VITERBI; 1537b63b36faSFred Richter *status |= FE_HAS_SYNC; 1538b63b36faSFred Richter 1539b63b36faSFred Richter *status |= FE_HAS_LOCK; 1540b63b36faSFred Richter } 1541b63b36faSFred Richter break; 1542b63b36faSFred Richter case VSB_8: 1543b63b36faSFred Richter if (lgdt3306a_vsb_lock_poll(state) == LG3306_LOCK) { 1544b63b36faSFred Richter *status |= FE_HAS_VITERBI; 1545b63b36faSFred Richter *status |= FE_HAS_SYNC; 1546b63b36faSFred Richter 1547b63b36faSFred Richter *status |= FE_HAS_LOCK; 1548b63b36faSFred Richter 1549ee0133eeSMauro Carvalho Chehab ret = lgdt3306a_monitor_vsb(state); 1550b63b36faSFred Richter } 1551b63b36faSFred Richter break; 1552b63b36faSFred Richter default: 1553b63b36faSFred Richter ret = -EINVAL; 1554b63b36faSFred Richter } 1555b63b36faSFred Richter } 1556b63b36faSFred Richter return ret; 1557b63b36faSFred Richter } 1558b63b36faSFred Richter 1559b63b36faSFred Richter 1560b63b36faSFred Richter static int lgdt3306a_read_snr(struct dvb_frontend *fe, u16 *snr) 1561b63b36faSFred Richter { 1562b63b36faSFred Richter struct lgdt3306a_state *state = fe->demodulator_priv; 1563b63b36faSFred Richter 1564b63b36faSFred Richter state->snr = lgdt3306a_calculate_snr_x100(state); 1565b63b36faSFred Richter /* report SNR in dB * 10 */ 1566b63b36faSFred Richter *snr = state->snr/10; 1567b63b36faSFred Richter 1568b63b36faSFred Richter return 0; 1569b63b36faSFred Richter } 1570b63b36faSFred Richter 1571b63b36faSFred Richter static int lgdt3306a_read_signal_strength(struct dvb_frontend *fe, 1572b63b36faSFred Richter u16 *strength) 1573b63b36faSFred Richter { 1574b63b36faSFred Richter /* 1575b63b36faSFred Richter * Calculate some sort of "strength" from SNR 1576b63b36faSFred Richter */ 1577b63b36faSFred Richter struct lgdt3306a_state *state = fe->demodulator_priv; 15788e8cd34eSMichael Ira Krufky u16 snr; /* snr_x10 */ 1579b63b36faSFred Richter int ret; 15808e8cd34eSMichael Ira Krufky u32 ref_snr; /* snr*100 */ 1581b63b36faSFred Richter u32 str; 1582b63b36faSFred Richter 1583b63b36faSFred Richter *strength = 0; 1584b63b36faSFred Richter 1585b63b36faSFred Richter switch (state->current_modulation) { 1586b63b36faSFred Richter case VSB_8: 15878e8cd34eSMichael Ira Krufky ref_snr = 1600; /* 16dB */ 1588b63b36faSFred Richter break; 1589b63b36faSFred Richter case QAM_64: 15908e8cd34eSMichael Ira Krufky ref_snr = 2200; /* 22dB */ 1591b63b36faSFred Richter break; 1592b63b36faSFred Richter case QAM_256: 15938e8cd34eSMichael Ira Krufky ref_snr = 2800; /* 28dB */ 1594b63b36faSFred Richter break; 1595b63b36faSFred Richter default: 1596b63b36faSFred Richter return -EINVAL; 1597b63b36faSFred Richter } 1598b63b36faSFred Richter 1599b63b36faSFred Richter ret = fe->ops.read_snr(fe, &snr); 1600b63b36faSFred Richter if (lg_chkerr(ret)) 1601b63b36faSFred Richter goto fail; 1602b63b36faSFred Richter 1603b63b36faSFred Richter if (state->snr <= (ref_snr - 100)) 1604b63b36faSFred Richter str = 0; 1605b63b36faSFred Richter else if (state->snr <= ref_snr) 16068e8cd34eSMichael Ira Krufky str = (0xffff * 65) / 100; /* 65% */ 1607b63b36faSFred Richter else { 1608b63b36faSFred Richter str = state->snr - ref_snr; 1609b63b36faSFred Richter str /= 50; 16108e8cd34eSMichael Ira Krufky str += 78; /* 78%-100% */ 1611b63b36faSFred Richter if (str > 100) 1612b63b36faSFred Richter str = 100; 1613b63b36faSFred Richter str = (0xffff * str) / 100; 1614b63b36faSFred Richter } 1615b63b36faSFred Richter *strength = (u16)str; 1616097117caSMauro Carvalho Chehab dbg_info("strength=%u\n", *strength); 1617b63b36faSFred Richter 1618b63b36faSFred Richter fail: 1619b63b36faSFred Richter return ret; 1620b63b36faSFred Richter } 1621b63b36faSFred Richter 1622b63b36faSFred Richter /* ------------------------------------------------------------------------ */ 1623b63b36faSFred Richter 1624b63b36faSFred Richter static int lgdt3306a_read_ber(struct dvb_frontend *fe, u32 *ber) 1625b63b36faSFred Richter { 1626b63b36faSFred Richter struct lgdt3306a_state *state = fe->demodulator_priv; 1627b63b36faSFred Richter u32 tmp; 1628b63b36faSFred Richter 1629b63b36faSFred Richter *ber = 0; 1630b63b36faSFred Richter #if 1 16318e8cd34eSMichael Ira Krufky /* FGR - BUGBUG - I don't know what value is expected by dvb_core 16328e8cd34eSMichael Ira Krufky * what is the scale of the value?? */ 16334937ba94SMauro Carvalho Chehab tmp = read_reg(state, 0x00fc); /* NBERVALUE[24-31] */ 16344937ba94SMauro Carvalho Chehab tmp = (tmp << 8) | read_reg(state, 0x00fd); /* NBERVALUE[16-23] */ 16354937ba94SMauro Carvalho Chehab tmp = (tmp << 8) | read_reg(state, 0x00fe); /* NBERVALUE[8-15] */ 16364937ba94SMauro Carvalho Chehab tmp = (tmp << 8) | read_reg(state, 0x00ff); /* NBERVALUE[0-7] */ 1637b63b36faSFred Richter *ber = tmp; 1638097117caSMauro Carvalho Chehab dbg_info("ber=%u\n", tmp); 1639b63b36faSFred Richter #endif 1640b63b36faSFred Richter return 0; 1641b63b36faSFred Richter } 1642b63b36faSFred Richter 1643b63b36faSFred Richter static int lgdt3306a_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) 1644b63b36faSFred Richter { 1645b63b36faSFred Richter struct lgdt3306a_state *state = fe->demodulator_priv; 1646b63b36faSFred Richter 1647b63b36faSFred Richter *ucblocks = 0; 1648b63b36faSFred Richter #if 1 16498e8cd34eSMichael Ira Krufky /* FGR - BUGBUG - I don't know what value is expected by dvb_core 16508e8cd34eSMichael Ira Krufky * what happens when value wraps? */ 16514937ba94SMauro Carvalho Chehab *ucblocks = read_reg(state, 0x00f4); /* TPIFTPERRCNT[0-7] */ 1652097117caSMauro Carvalho Chehab dbg_info("ucblocks=%u\n", *ucblocks); 1653b63b36faSFred Richter #endif 1654b63b36faSFred Richter 1655b63b36faSFred Richter return 0; 1656b63b36faSFred Richter } 1657b63b36faSFred Richter 1658b63b36faSFred Richter static int lgdt3306a_tune(struct dvb_frontend *fe, bool re_tune, unsigned int mode_flags, unsigned int *delay, fe_status_t *status) 1659b63b36faSFred Richter { 1660b63b36faSFred Richter int ret = 0; 1661b63b36faSFred Richter struct lgdt3306a_state *state = fe->demodulator_priv; 1662b63b36faSFred Richter 1663097117caSMauro Carvalho Chehab dbg_info("re_tune=%u\n", re_tune); 1664b63b36faSFred Richter 1665b63b36faSFred Richter if (re_tune) { 16668e8cd34eSMichael Ira Krufky state->current_frequency = -1; /* force re-tune */ 1667ae21e447SMichael Ira Krufky ret = lgdt3306a_set_parameters(fe); 1668ae21e447SMichael Ira Krufky if (ret != 0) 1669b63b36faSFred Richter return ret; 1670b63b36faSFred Richter } 1671b63b36faSFred Richter *delay = 125; 1672b63b36faSFred Richter ret = lgdt3306a_read_status(fe, status); 1673b63b36faSFred Richter 1674b63b36faSFred Richter return ret; 1675b63b36faSFred Richter } 1676b63b36faSFred Richter 1677b63b36faSFred Richter static int lgdt3306a_get_tune_settings(struct dvb_frontend *fe, 1678b63b36faSFred Richter struct dvb_frontend_tune_settings 1679b63b36faSFred Richter *fe_tune_settings) 1680b63b36faSFred Richter { 1681b63b36faSFred Richter fe_tune_settings->min_delay_ms = 100; 1682097117caSMauro Carvalho Chehab dbg_info("\n"); 1683b63b36faSFred Richter return 0; 1684b63b36faSFred Richter } 1685b63b36faSFred Richter 1686b63b36faSFred Richter static int lgdt3306a_search(struct dvb_frontend *fe) 1687b63b36faSFred Richter { 1688b63b36faSFred Richter fe_status_t status = 0; 1689b63b36faSFred Richter int i, ret; 1690b63b36faSFred Richter 1691b63b36faSFred Richter /* set frontend */ 1692b63b36faSFred Richter ret = lgdt3306a_set_parameters(fe); 1693b63b36faSFred Richter if (ret) 1694b63b36faSFred Richter goto error; 1695b63b36faSFred Richter 1696b63b36faSFred Richter /* wait frontend lock */ 1697b63b36faSFred Richter for (i = 20; i > 0; i--) { 1698097117caSMauro Carvalho Chehab dbg_info(": loop=%d\n", i); 1699b63b36faSFred Richter msleep(50); 1700b63b36faSFred Richter ret = lgdt3306a_read_status(fe, &status); 1701b63b36faSFred Richter if (ret) 1702b63b36faSFred Richter goto error; 1703b63b36faSFred Richter 1704b63b36faSFred Richter if (status & FE_HAS_LOCK) 1705b63b36faSFred Richter break; 1706b63b36faSFred Richter } 1707b63b36faSFred Richter 1708b63b36faSFred Richter /* check if we have a valid signal */ 17098e8cd34eSMichael Ira Krufky if (status & FE_HAS_LOCK) 1710b63b36faSFred Richter return DVBFE_ALGO_SEARCH_SUCCESS; 17118e8cd34eSMichael Ira Krufky else 1712b63b36faSFred Richter return DVBFE_ALGO_SEARCH_AGAIN; 1713b63b36faSFred Richter 1714b63b36faSFred Richter error: 1715097117caSMauro Carvalho Chehab dbg_info("failed (%d)\n", ret); 1716b63b36faSFred Richter return DVBFE_ALGO_SEARCH_ERROR; 1717b63b36faSFred Richter } 1718b63b36faSFred Richter 1719b63b36faSFred Richter static void lgdt3306a_release(struct dvb_frontend *fe) 1720b63b36faSFred Richter { 1721b63b36faSFred Richter struct lgdt3306a_state *state = fe->demodulator_priv; 17228e8cd34eSMichael Ira Krufky 1723097117caSMauro Carvalho Chehab dbg_info("\n"); 1724b63b36faSFred Richter kfree(state); 1725b63b36faSFred Richter } 1726b63b36faSFred Richter 1727b63b36faSFred Richter static struct dvb_frontend_ops lgdt3306a_ops; 1728b63b36faSFred Richter 1729b63b36faSFred Richter struct dvb_frontend *lgdt3306a_attach(const struct lgdt3306a_config *config, 1730b63b36faSFred Richter struct i2c_adapter *i2c_adap) 1731b63b36faSFred Richter { 1732b63b36faSFred Richter struct lgdt3306a_state *state = NULL; 1733b63b36faSFred Richter int ret; 1734b63b36faSFred Richter u8 val; 1735b63b36faSFred Richter 1736097117caSMauro Carvalho Chehab dbg_info("(%d-%04x)\n", 1737b63b36faSFred Richter i2c_adap ? i2c_adapter_id(i2c_adap) : 0, 1738b63b36faSFred Richter config ? config->i2c_addr : 0); 1739b63b36faSFred Richter 1740b63b36faSFred Richter state = kzalloc(sizeof(struct lgdt3306a_state), GFP_KERNEL); 1741b63b36faSFred Richter if (state == NULL) 1742b63b36faSFred Richter goto fail; 1743b63b36faSFred Richter 1744b63b36faSFred Richter state->cfg = config; 1745b63b36faSFred Richter state->i2c_adap = i2c_adap; 1746b63b36faSFred Richter 1747b63b36faSFred Richter memcpy(&state->frontend.ops, &lgdt3306a_ops, 1748b63b36faSFred Richter sizeof(struct dvb_frontend_ops)); 1749b63b36faSFred Richter state->frontend.demodulator_priv = state; 1750b63b36faSFred Richter 1751b63b36faSFred Richter /* verify that we're talking to a lg3306a */ 17528e8cd34eSMichael Ira Krufky /* FGR - NOTE - there is no obvious ChipId to check; we check 17538e8cd34eSMichael Ira Krufky * some "known" bits after reset, but it's still just a guess */ 1754b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x0000, &val); 1755b63b36faSFred Richter if (lg_chkerr(ret)) 1756b63b36faSFred Richter goto fail; 1757b63b36faSFred Richter if ((val & 0x74) != 0x74) { 1758097117caSMauro Carvalho Chehab pr_warn("expected 0x74, got 0x%x\n", (val & 0x74)); 17598e8cd34eSMichael Ira Krufky #if 0 17608e8cd34eSMichael Ira Krufky goto fail; /* BUGBUG - re-enable when we know this is right */ 17618e8cd34eSMichael Ira Krufky #endif 1762b63b36faSFred Richter } 1763b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x0001, &val); 1764b63b36faSFred Richter if (lg_chkerr(ret)) 1765b63b36faSFred Richter goto fail; 17664937ba94SMauro Carvalho Chehab if ((val & 0xf6) != 0xc6) { 1767097117caSMauro Carvalho Chehab pr_warn("expected 0xc6, got 0x%x\n", (val & 0xf6)); 17688e8cd34eSMichael Ira Krufky #if 0 17698e8cd34eSMichael Ira Krufky goto fail; /* BUGBUG - re-enable when we know this is right */ 17708e8cd34eSMichael Ira Krufky #endif 1771b63b36faSFred Richter } 1772b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x0002, &val); 1773b63b36faSFred Richter if (lg_chkerr(ret)) 1774b63b36faSFred Richter goto fail; 1775b63b36faSFred Richter if ((val & 0x73) != 0x03) { 1776097117caSMauro Carvalho Chehab pr_warn("expected 0x03, got 0x%x\n", (val & 0x73)); 17778e8cd34eSMichael Ira Krufky #if 0 17788e8cd34eSMichael Ira Krufky goto fail; /* BUGBUG - re-enable when we know this is right */ 17798e8cd34eSMichael Ira Krufky #endif 1780b63b36faSFred Richter } 1781b63b36faSFred Richter 1782b63b36faSFred Richter state->current_frequency = -1; 1783b63b36faSFred Richter state->current_modulation = -1; 1784b63b36faSFred Richter 1785b63b36faSFred Richter lgdt3306a_sleep(state); 1786b63b36faSFred Richter 1787b63b36faSFred Richter return &state->frontend; 1788b63b36faSFred Richter 1789b63b36faSFred Richter fail: 1790097117caSMauro Carvalho Chehab pr_warn("unable to detect LGDT3306A hardware\n"); 1791b63b36faSFred Richter kfree(state); 1792b63b36faSFred Richter return NULL; 1793b63b36faSFred Richter } 1794ebd9175eSMichael Ira Krufky EXPORT_SYMBOL(lgdt3306a_attach); 1795b63b36faSFred Richter 1796b63b36faSFred Richter #ifdef DBG_DUMP 1797b63b36faSFred Richter 1798b63b36faSFred Richter static const short regtab[] = { 17996da7ac98SMichael Ira Krufky 0x0000, /* SOFTRSTB 1'b1 1'b1 1'b1 ADCPDB 1'b1 PLLPDB GBBPDB 11111111 */ 18006da7ac98SMichael Ira Krufky 0x0001, /* 1'b1 1'b1 1'b0 1'b0 AUTORPTRS */ 18016da7ac98SMichael Ira Krufky 0x0002, /* NI2CRPTEN 1'b0 1'b0 1'b0 SPECINVAUT */ 18026da7ac98SMichael Ira Krufky 0x0003, /* AGCRFOUT */ 18036da7ac98SMichael Ira Krufky 0x0004, /* ADCSEL1V ADCCNT ADCCNF ADCCNS ADCCLKPLL */ 18046da7ac98SMichael Ira Krufky 0x0005, /* PLLINDIVSE */ 18056da7ac98SMichael Ira Krufky 0x0006, /* PLLCTRL[7:0] 11100001 */ 18066da7ac98SMichael Ira Krufky 0x0007, /* SYSINITWAITTIME[7:0] (msec) 00001000 */ 18076da7ac98SMichael Ira Krufky 0x0008, /* STDOPMODE[7:0] 10000000 */ 18086da7ac98SMichael Ira Krufky 0x0009, /* 1'b0 1'b0 1'b0 STDOPDETTMODE[2:0] STDOPDETCMODE[1:0] 00011110 */ 18094937ba94SMauro Carvalho Chehab 0x000a, /* DAFTEN 1'b1 x x SCSYSLOCK */ 18104937ba94SMauro Carvalho Chehab 0x000b, /* SCSYSLOCKCHKTIME[7:0] (10msec) 01100100 */ 18114937ba94SMauro Carvalho Chehab 0x000d, /* x SAMPLING4 */ 18124937ba94SMauro Carvalho Chehab 0x000e, /* SAMFREQ[15:8] 00000000 */ 18134937ba94SMauro Carvalho Chehab 0x000f, /* SAMFREQ[7:0] 00000000 */ 18146da7ac98SMichael Ira Krufky 0x0010, /* IFFREQ[15:8] 01100000 */ 18156da7ac98SMichael Ira Krufky 0x0011, /* IFFREQ[7:0] 00000000 */ 18166da7ac98SMichael Ira Krufky 0x0012, /* AGCEN AGCREFMO */ 18176da7ac98SMichael Ira Krufky 0x0013, /* AGCRFFIXB AGCIFFIXB AGCLOCKDETRNGSEL[1:0] 1'b1 1'b0 1'b0 1'b0 11101000 */ 18186da7ac98SMichael Ira Krufky 0x0014, /* AGCFIXVALUE[7:0] 01111111 */ 18196da7ac98SMichael Ira Krufky 0x0015, /* AGCREF[15:8] 00001010 */ 18206da7ac98SMichael Ira Krufky 0x0016, /* AGCREF[7:0] 11100100 */ 18216da7ac98SMichael Ira Krufky 0x0017, /* AGCDELAY[7:0] 00100000 */ 18226da7ac98SMichael Ira Krufky 0x0018, /* AGCRFBW[3:0] AGCIFBW[3:0] 10001000 */ 18236da7ac98SMichael Ira Krufky 0x0019, /* AGCUDOUTMODE[1:0] AGCUDCTRLLEN[1:0] AGCUDCTRL */ 18244937ba94SMauro Carvalho Chehab 0x001c, /* 1'b1 PFEN MFEN AICCVSYNC */ 18254937ba94SMauro Carvalho Chehab 0x001d, /* 1'b0 1'b1 1'b0 1'b1 AICCVSYNC */ 18264937ba94SMauro Carvalho Chehab 0x001e, /* AICCALPHA[3:0] 1'b1 1'b0 1'b1 1'b0 01111010 */ 18274937ba94SMauro Carvalho Chehab 0x001f, /* AICCDETTH[19:16] AICCOFFTH[19:16] 00000000 */ 18286da7ac98SMichael Ira Krufky 0x0020, /* AICCDETTH[15:8] 01111100 */ 18296da7ac98SMichael Ira Krufky 0x0021, /* AICCDETTH[7:0] 00000000 */ 18306da7ac98SMichael Ira Krufky 0x0022, /* AICCOFFTH[15:8] 00000101 */ 18316da7ac98SMichael Ira Krufky 0x0023, /* AICCOFFTH[7:0] 11100000 */ 18326da7ac98SMichael Ira Krufky 0x0024, /* AICCOPMODE3[1:0] AICCOPMODE2[1:0] AICCOPMODE1[1:0] AICCOPMODE0[1:0] 00000000 */ 18336da7ac98SMichael Ira Krufky 0x0025, /* AICCFIXFREQ3[23:16] 00000000 */ 18346da7ac98SMichael Ira Krufky 0x0026, /* AICCFIXFREQ3[15:8] 00000000 */ 18356da7ac98SMichael Ira Krufky 0x0027, /* AICCFIXFREQ3[7:0] 00000000 */ 18366da7ac98SMichael Ira Krufky 0x0028, /* AICCFIXFREQ2[23:16] 00000000 */ 18376da7ac98SMichael Ira Krufky 0x0029, /* AICCFIXFREQ2[15:8] 00000000 */ 18384937ba94SMauro Carvalho Chehab 0x002a, /* AICCFIXFREQ2[7:0] 00000000 */ 18394937ba94SMauro Carvalho Chehab 0x002b, /* AICCFIXFREQ1[23:16] 00000000 */ 18404937ba94SMauro Carvalho Chehab 0x002c, /* AICCFIXFREQ1[15:8] 00000000 */ 18414937ba94SMauro Carvalho Chehab 0x002d, /* AICCFIXFREQ1[7:0] 00000000 */ 18424937ba94SMauro Carvalho Chehab 0x002e, /* AICCFIXFREQ0[23:16] 00000000 */ 18434937ba94SMauro Carvalho Chehab 0x002f, /* AICCFIXFREQ0[15:8] 00000000 */ 18446da7ac98SMichael Ira Krufky 0x0030, /* AICCFIXFREQ0[7:0] 00000000 */ 18456da7ac98SMichael Ira Krufky 0x0031, /* 1'b0 1'b1 1'b0 1'b0 x DAGC1STER */ 18466da7ac98SMichael Ira Krufky 0x0032, /* DAGC1STEN DAGC1STER */ 18476da7ac98SMichael Ira Krufky 0x0033, /* DAGC1STREF[15:8] 00001010 */ 18486da7ac98SMichael Ira Krufky 0x0034, /* DAGC1STREF[7:0] 11100100 */ 18496da7ac98SMichael Ira Krufky 0x0035, /* DAGC2NDE */ 18506da7ac98SMichael Ira Krufky 0x0036, /* DAGC2NDREF[15:8] 00001010 */ 18516da7ac98SMichael Ira Krufky 0x0037, /* DAGC2NDREF[7:0] 10000000 */ 18526da7ac98SMichael Ira Krufky 0x0038, /* DAGC2NDLOCKDETRNGSEL[1:0] */ 18534937ba94SMauro Carvalho Chehab 0x003d, /* 1'b1 SAMGEARS */ 18546da7ac98SMichael Ira Krufky 0x0040, /* SAMLFGMA */ 18556da7ac98SMichael Ira Krufky 0x0041, /* SAMLFBWM */ 18566da7ac98SMichael Ira Krufky 0x0044, /* 1'b1 CRGEARSHE */ 18576da7ac98SMichael Ira Krufky 0x0045, /* CRLFGMAN */ 18586da7ac98SMichael Ira Krufky 0x0046, /* CFLFBWMA */ 18596da7ac98SMichael Ira Krufky 0x0047, /* CRLFGMAN */ 18606da7ac98SMichael Ira Krufky 0x0048, /* x x x x CRLFGSTEP_VS[3:0] xxxx1001 */ 18616da7ac98SMichael Ira Krufky 0x0049, /* CRLFBWMA */ 18624937ba94SMauro Carvalho Chehab 0x004a, /* CRLFBWMA */ 18636da7ac98SMichael Ira Krufky 0x0050, /* 1'b0 1'b1 1'b1 1'b0 MSECALCDA */ 18646da7ac98SMichael Ira Krufky 0x0070, /* TPOUTEN TPIFEN TPCLKOUTE */ 18656da7ac98SMichael Ira Krufky 0x0071, /* TPSENB TPSSOPBITE */ 18666da7ac98SMichael Ira Krufky 0x0073, /* TP47HINS x x CHBERINT PERMODE[1:0] PERINT[1:0] 1xx11100 */ 18676da7ac98SMichael Ira Krufky 0x0075, /* x x x x x IQSWAPCTRL[2:0] xxxxx000 */ 18686da7ac98SMichael Ira Krufky 0x0076, /* NBERCON NBERST NBERPOL NBERWSYN */ 18696da7ac98SMichael Ira Krufky 0x0077, /* x NBERLOSTTH[2:0] NBERACQTH[3:0] x0000000 */ 18706da7ac98SMichael Ira Krufky 0x0078, /* NBERPOLY[31:24] 00000000 */ 18716da7ac98SMichael Ira Krufky 0x0079, /* NBERPOLY[23:16] 00000000 */ 18724937ba94SMauro Carvalho Chehab 0x007a, /* NBERPOLY[15:8] 00000000 */ 18734937ba94SMauro Carvalho Chehab 0x007b, /* NBERPOLY[7:0] 00000000 */ 18744937ba94SMauro Carvalho Chehab 0x007c, /* NBERPED[31:24] 00000000 */ 18754937ba94SMauro Carvalho Chehab 0x007d, /* NBERPED[23:16] 00000000 */ 18764937ba94SMauro Carvalho Chehab 0x007e, /* NBERPED[15:8] 00000000 */ 18774937ba94SMauro Carvalho Chehab 0x007f, /* NBERPED[7:0] 00000000 */ 18786da7ac98SMichael Ira Krufky 0x0080, /* x AGCLOCK DAGCLOCK SYSLOCK x x NEVERLOCK[1:0] */ 18796da7ac98SMichael Ira Krufky 0x0085, /* SPECINVST */ 18806da7ac98SMichael Ira Krufky 0x0088, /* SYSLOCKTIME[15:8] */ 18816da7ac98SMichael Ira Krufky 0x0089, /* SYSLOCKTIME[7:0] */ 18824937ba94SMauro Carvalho Chehab 0x008c, /* FECLOCKTIME[15:8] */ 18834937ba94SMauro Carvalho Chehab 0x008d, /* FECLOCKTIME[7:0] */ 18844937ba94SMauro Carvalho Chehab 0x008e, /* AGCACCOUT[15:8] */ 18854937ba94SMauro Carvalho Chehab 0x008f, /* AGCACCOUT[7:0] */ 18866da7ac98SMichael Ira Krufky 0x0090, /* AICCREJSTATUS[3:0] AICCREJBUSY[3:0] */ 18876da7ac98SMichael Ira Krufky 0x0091, /* AICCVSYNC */ 18884937ba94SMauro Carvalho Chehab 0x009c, /* CARRFREQOFFSET[15:8] */ 18894937ba94SMauro Carvalho Chehab 0x009d, /* CARRFREQOFFSET[7:0] */ 18904937ba94SMauro Carvalho Chehab 0x00a1, /* SAMFREQOFFSET[23:16] */ 18914937ba94SMauro Carvalho Chehab 0x00a2, /* SAMFREQOFFSET[15:8] */ 18924937ba94SMauro Carvalho Chehab 0x00a3, /* SAMFREQOFFSET[7:0] */ 18934937ba94SMauro Carvalho Chehab 0x00a6, /* SYNCLOCK SYNCLOCKH */ 18946da7ac98SMichael Ira Krufky #if 0 /* covered elsewhere */ 18954937ba94SMauro Carvalho Chehab 0x00e8, /* CONSTPWR[15:8] */ 18964937ba94SMauro Carvalho Chehab 0x00e9, /* CONSTPWR[7:0] */ 18974937ba94SMauro Carvalho Chehab 0x00ea, /* BMSE[15:8] */ 18984937ba94SMauro Carvalho Chehab 0x00eb, /* BMSE[7:0] */ 18994937ba94SMauro Carvalho Chehab 0x00ec, /* MSE[15:8] */ 19004937ba94SMauro Carvalho Chehab 0x00ed, /* MSE[7:0] */ 19014937ba94SMauro Carvalho Chehab 0x00ee, /* CONSTI[7:0] */ 19024937ba94SMauro Carvalho Chehab 0x00ef, /* CONSTQ[7:0] */ 1903b63b36faSFred Richter #endif 19044937ba94SMauro Carvalho Chehab 0x00f4, /* TPIFTPERRCNT[7:0] */ 19054937ba94SMauro Carvalho Chehab 0x00f5, /* TPCORREC */ 19064937ba94SMauro Carvalho Chehab 0x00f6, /* VBBER[15:8] */ 19074937ba94SMauro Carvalho Chehab 0x00f7, /* VBBER[7:0] */ 19084937ba94SMauro Carvalho Chehab 0x00f8, /* VABER[15:8] */ 19094937ba94SMauro Carvalho Chehab 0x00f9, /* VABER[7:0] */ 19104937ba94SMauro Carvalho Chehab 0x00fa, /* TPERRCNT[7:0] */ 19114937ba94SMauro Carvalho Chehab 0x00fb, /* NBERLOCK x x x x x x x */ 19124937ba94SMauro Carvalho Chehab 0x00fc, /* NBERVALUE[31:24] */ 19134937ba94SMauro Carvalho Chehab 0x00fd, /* NBERVALUE[23:16] */ 19144937ba94SMauro Carvalho Chehab 0x00fe, /* NBERVALUE[15:8] */ 19154937ba94SMauro Carvalho Chehab 0x00ff, /* NBERVALUE[7:0] */ 19166da7ac98SMichael Ira Krufky 0x1000, /* 1'b0 WODAGCOU */ 19176da7ac98SMichael Ira Krufky 0x1005, /* x x 1'b1 1'b1 x SRD_Q_QM */ 19186da7ac98SMichael Ira Krufky 0x1009, /* SRDWAITTIME[7:0] (10msec) 00100011 */ 19194937ba94SMauro Carvalho Chehab 0x100a, /* SRDWAITTIME_CQS[7:0] (msec) 01100100 */ 19204937ba94SMauro Carvalho Chehab 0x101a, /* x 1'b1 1'b0 1'b0 x QMDQAMMODE[2:0] x100x010 */ 19216da7ac98SMichael Ira Krufky 0x1036, /* 1'b0 1'b1 1'b0 1'b0 SAMGSEND_CQS[3:0] 01001110 */ 19224937ba94SMauro Carvalho Chehab 0x103c, /* SAMGSAUTOSTL_V[3:0] SAMGSAUTOEDL_V[3:0] 01000110 */ 19234937ba94SMauro Carvalho Chehab 0x103d, /* 1'b1 1'b1 SAMCNORMBP_V[1:0] 1'b0 1'b0 SAMMODESEL_V[1:0] 11100001 */ 19244937ba94SMauro Carvalho Chehab 0x103f, /* SAMZTEDSE */ 19254937ba94SMauro Carvalho Chehab 0x105d, /* EQSTATUSE */ 19264937ba94SMauro Carvalho Chehab 0x105f, /* x PMAPG2_V[2:0] x DMAPG2_V[2:0] x001x011 */ 19276da7ac98SMichael Ira Krufky 0x1060, /* 1'b1 EQSTATUSE */ 19286da7ac98SMichael Ira Krufky 0x1061, /* CRMAPBWSTL_V[3:0] CRMAPBWEDL_V[3:0] 00000100 */ 19296da7ac98SMichael Ira Krufky 0x1065, /* 1'b0 x CRMODE_V[1:0] 1'b1 x 1'b1 x 0x111x1x */ 19306da7ac98SMichael Ira Krufky 0x1066, /* 1'b0 1'b0 1'b1 1'b0 1'b1 PNBOOSTSE */ 19316da7ac98SMichael Ira Krufky 0x1068, /* CREPHNGAIN2_V[3:0] CREPHNPBW_V[3:0] 10010001 */ 19324937ba94SMauro Carvalho Chehab 0x106e, /* x x x x x CREPHNEN_ */ 19334937ba94SMauro Carvalho Chehab 0x106f, /* CREPHNTH_V[7:0] 00010101 */ 19346da7ac98SMichael Ira Krufky 0x1072, /* CRSWEEPN */ 19356da7ac98SMichael Ira Krufky 0x1073, /* CRPGAIN_V[3:0] x x 1'b1 1'b1 1001xx11 */ 19366da7ac98SMichael Ira Krufky 0x1074, /* CRPBW_V[3:0] x x 1'b1 1'b1 0001xx11 */ 19376da7ac98SMichael Ira Krufky 0x1080, /* DAFTSTATUS[1:0] x x x x x x */ 19386da7ac98SMichael Ira Krufky 0x1081, /* SRDSTATUS[1:0] x x x x x SRDLOCK */ 19394937ba94SMauro Carvalho Chehab 0x10a9, /* EQSTATUS_CQS[1:0] x x x x x x */ 19404937ba94SMauro Carvalho Chehab 0x10b7, /* EQSTATUS_V[1:0] x x x x x x */ 19416da7ac98SMichael Ira Krufky #if 0 /* SMART_ANT */ 19424937ba94SMauro Carvalho Chehab 0x1f00, /* MODEDETE */ 19434937ba94SMauro Carvalho Chehab 0x1f01, /* x x x x x x x SFNRST xxxxxxx0 */ 19444937ba94SMauro Carvalho Chehab 0x1f03, /* NUMOFANT[7:0] 10000000 */ 19454937ba94SMauro Carvalho Chehab 0x1f04, /* x SELMASK[6:0] x0000000 */ 19464937ba94SMauro Carvalho Chehab 0x1f05, /* x SETMASK[6:0] x0000000 */ 19474937ba94SMauro Carvalho Chehab 0x1f06, /* x TXDATA[6:0] x0000000 */ 19484937ba94SMauro Carvalho Chehab 0x1f07, /* x CHNUMBER[6:0] x0000000 */ 19494937ba94SMauro Carvalho Chehab 0x1f09, /* AGCTIME[23:16] 10011000 */ 19504937ba94SMauro Carvalho Chehab 0x1f0a, /* AGCTIME[15:8] 10010110 */ 19514937ba94SMauro Carvalho Chehab 0x1f0b, /* AGCTIME[7:0] 10000000 */ 19524937ba94SMauro Carvalho Chehab 0x1f0c, /* ANTTIME[31:24] 00000000 */ 19534937ba94SMauro Carvalho Chehab 0x1f0d, /* ANTTIME[23:16] 00000011 */ 19544937ba94SMauro Carvalho Chehab 0x1f0e, /* ANTTIME[15:8] 10010000 */ 19554937ba94SMauro Carvalho Chehab 0x1f0f, /* ANTTIME[7:0] 10010000 */ 19564937ba94SMauro Carvalho Chehab 0x1f11, /* SYNCTIME[23:16] 10011000 */ 19574937ba94SMauro Carvalho Chehab 0x1f12, /* SYNCTIME[15:8] 10010110 */ 19584937ba94SMauro Carvalho Chehab 0x1f13, /* SYNCTIME[7:0] 10000000 */ 19594937ba94SMauro Carvalho Chehab 0x1f14, /* SNRTIME[31:24] 00000001 */ 19604937ba94SMauro Carvalho Chehab 0x1f15, /* SNRTIME[23:16] 01111101 */ 19614937ba94SMauro Carvalho Chehab 0x1f16, /* SNRTIME[15:8] 01111000 */ 19624937ba94SMauro Carvalho Chehab 0x1f17, /* SNRTIME[7:0] 01000000 */ 19634937ba94SMauro Carvalho Chehab 0x1f19, /* FECTIME[23:16] 00000000 */ 19644937ba94SMauro Carvalho Chehab 0x1f1a, /* FECTIME[15:8] 01110010 */ 19654937ba94SMauro Carvalho Chehab 0x1f1b, /* FECTIME[7:0] 01110000 */ 19664937ba94SMauro Carvalho Chehab 0x1f1d, /* FECTHD[7:0] 00000011 */ 19674937ba94SMauro Carvalho Chehab 0x1f1f, /* SNRTHD[23:16] 00001000 */ 19684937ba94SMauro Carvalho Chehab 0x1f20, /* SNRTHD[15:8] 01111111 */ 19694937ba94SMauro Carvalho Chehab 0x1f21, /* SNRTHD[7:0] 10000101 */ 19704937ba94SMauro Carvalho Chehab 0x1f80, /* IRQFLG x x SFSDRFLG MODEBFLG SAVEFLG SCANFLG TRACKFLG */ 19714937ba94SMauro Carvalho Chehab 0x1f81, /* x SYNCCON SNRCON FECCON x STDBUSY SYNCRST AGCFZCO */ 19724937ba94SMauro Carvalho Chehab 0x1f82, /* x x x SCANOPCD[4:0] */ 19734937ba94SMauro Carvalho Chehab 0x1f83, /* x x x x MAINOPCD[3:0] */ 19744937ba94SMauro Carvalho Chehab 0x1f84, /* x x RXDATA[13:8] */ 19754937ba94SMauro Carvalho Chehab 0x1f85, /* RXDATA[7:0] */ 19764937ba94SMauro Carvalho Chehab 0x1f86, /* x x SDTDATA[13:8] */ 19774937ba94SMauro Carvalho Chehab 0x1f87, /* SDTDATA[7:0] */ 19784937ba94SMauro Carvalho Chehab 0x1f89, /* ANTSNR[23:16] */ 19794937ba94SMauro Carvalho Chehab 0x1f8a, /* ANTSNR[15:8] */ 19804937ba94SMauro Carvalho Chehab 0x1f8b, /* ANTSNR[7:0] */ 19814937ba94SMauro Carvalho Chehab 0x1f8c, /* x x x x ANTFEC[13:8] */ 19824937ba94SMauro Carvalho Chehab 0x1f8d, /* ANTFEC[7:0] */ 19834937ba94SMauro Carvalho Chehab 0x1f8e, /* MAXCNT[7:0] */ 19844937ba94SMauro Carvalho Chehab 0x1f8f, /* SCANCNT[7:0] */ 19854937ba94SMauro Carvalho Chehab 0x1f91, /* MAXPW[23:16] */ 19864937ba94SMauro Carvalho Chehab 0x1f92, /* MAXPW[15:8] */ 19874937ba94SMauro Carvalho Chehab 0x1f93, /* MAXPW[7:0] */ 19884937ba94SMauro Carvalho Chehab 0x1f95, /* CURPWMSE[23:16] */ 19894937ba94SMauro Carvalho Chehab 0x1f96, /* CURPWMSE[15:8] */ 19904937ba94SMauro Carvalho Chehab 0x1f97, /* CURPWMSE[7:0] */ 19916da7ac98SMichael Ira Krufky #endif /* SMART_ANT */ 19924937ba94SMauro Carvalho Chehab 0x211f, /* 1'b1 1'b1 1'b1 CIRQEN x x 1'b0 1'b0 1111xx00 */ 19934937ba94SMauro Carvalho Chehab 0x212a, /* EQAUTOST */ 19946da7ac98SMichael Ira Krufky 0x2122, /* CHFAST[7:0] 01100000 */ 19954937ba94SMauro Carvalho Chehab 0x212b, /* FFFSTEP_V[3:0] x FBFSTEP_V[2:0] 0001x001 */ 19964937ba94SMauro Carvalho Chehab 0x212c, /* PHDEROTBWSEL[3:0] 1'b1 1'b1 1'b1 1'b0 10001110 */ 19974937ba94SMauro Carvalho Chehab 0x212d, /* 1'b1 1'b1 1'b1 1'b1 x x TPIFLOCKS */ 19986da7ac98SMichael Ira Krufky 0x2135, /* DYNTRACKFDEQ[3:0] x 1'b0 1'b0 1'b0 1010x000 */ 19996da7ac98SMichael Ira Krufky 0x2141, /* TRMODE[1:0] 1'b1 1'b1 1'b0 1'b1 1'b1 1'b1 01110111 */ 20006da7ac98SMichael Ira Krufky 0x2162, /* AICCCTRLE */ 20016da7ac98SMichael Ira Krufky 0x2173, /* PHNCNFCNT[7:0] 00000100 */ 20026da7ac98SMichael Ira Krufky 0x2179, /* 1'b0 1'b0 1'b0 1'b1 x BADSINGLEDYNTRACKFBF[2:0] 0001x001 */ 20034937ba94SMauro Carvalho Chehab 0x217a, /* 1'b0 1'b0 1'b0 1'b1 x BADSLOWSINGLEDYNTRACKFBF[2:0] 0001x001 */ 20044937ba94SMauro Carvalho Chehab 0x217e, /* CNFCNTTPIF[7:0] 00001000 */ 20054937ba94SMauro Carvalho Chehab 0x217f, /* TPERRCNTTPIF[7:0] 00000001 */ 20066da7ac98SMichael Ira Krufky 0x2180, /* x x x x x x FBDLYCIR[9:8] */ 20076da7ac98SMichael Ira Krufky 0x2181, /* FBDLYCIR[7:0] */ 20086da7ac98SMichael Ira Krufky 0x2185, /* MAXPWRMAIN[7:0] */ 20096da7ac98SMichael Ira Krufky 0x2191, /* NCOMBDET x x x x x x x */ 20106da7ac98SMichael Ira Krufky 0x2199, /* x MAINSTRON */ 20114937ba94SMauro Carvalho Chehab 0x219a, /* FFFEQSTEPOUT_V[3:0] FBFSTEPOUT_V[2:0] */ 20124937ba94SMauro Carvalho Chehab 0x21a1, /* x x SNRREF[5:0] */ 20136da7ac98SMichael Ira Krufky 0x2845, /* 1'b0 1'b1 x x FFFSTEP_CQS[1:0] FFFCENTERTAP[1:0] 01xx1110 */ 20146da7ac98SMichael Ira Krufky 0x2846, /* 1'b0 x 1'b0 1'b1 FBFSTEP_CQS[1:0] 1'b1 1'b0 0x011110 */ 20156da7ac98SMichael Ira Krufky 0x2847, /* ENNOSIGDE */ 20166da7ac98SMichael Ira Krufky 0x2849, /* 1'b1 1'b1 NOUSENOSI */ 20174937ba94SMauro Carvalho Chehab 0x284a, /* EQINITWAITTIME[7:0] 01100100 */ 20186da7ac98SMichael Ira Krufky 0x3000, /* 1'b1 1'b1 1'b1 x x x 1'b0 RPTRSTM */ 20196da7ac98SMichael Ira Krufky 0x3001, /* RPTRSTWAITTIME[7:0] (100msec) 00110010 */ 20206da7ac98SMichael Ira Krufky 0x3031, /* FRAMELOC */ 20216da7ac98SMichael Ira Krufky 0x3032, /* 1'b1 1'b0 1'b0 1'b0 x x FRAMELOCKMODE_CQS[1:0] 1000xx11 */ 20224937ba94SMauro Carvalho Chehab 0x30a9, /* VDLOCK_Q FRAMELOCK */ 20234937ba94SMauro Carvalho Chehab 0x30aa, /* MPEGLOCK */ 2024b63b36faSFred Richter }; 2025b63b36faSFred Richter 2026b63b36faSFred Richter #define numDumpRegs (sizeof(regtab)/sizeof(regtab[0])) 2027b63b36faSFred Richter static u8 regval1[numDumpRegs] = {0, }; 2028b63b36faSFred Richter static u8 regval2[numDumpRegs] = {0, }; 2029b63b36faSFred Richter 2030b63b36faSFred Richter static void lgdt3306a_DumpAllRegs(struct lgdt3306a_state *state) 2031b63b36faSFred Richter { 2032b63b36faSFred Richter memset(regval2, 0xff, sizeof(regval2)); 2033b63b36faSFred Richter lgdt3306a_DumpRegs(state); 2034b63b36faSFred Richter } 2035b63b36faSFred Richter 2036b63b36faSFred Richter static void lgdt3306a_DumpRegs(struct lgdt3306a_state *state) 2037b63b36faSFred Richter { 2038b63b36faSFred Richter int i; 2039b63b36faSFred Richter int sav_debug = debug; 20408e8cd34eSMichael Ira Krufky 2041b63b36faSFred Richter if ((debug & DBG_DUMP) == 0) 2042b63b36faSFred Richter return; 2043831a9112SMichael Ira Krufky debug &= ~DBG_REG; /* suppress DBG_REG during reg dump */ 2044b63b36faSFred Richter 2045097117caSMauro Carvalho Chehab lg_debug("\n"); 2046b63b36faSFred Richter 2047b63b36faSFred Richter for (i = 0; i < numDumpRegs; i++) { 2048b63b36faSFred Richter lgdt3306a_read_reg(state, regtab[i], ®val1[i]); 2049b63b36faSFred Richter if (regval1[i] != regval2[i]) { 2050097117caSMauro Carvalho Chehab lg_debug(" %04X = %02X\n", regtab[i], regval1[i]); 2051b63b36faSFred Richter regval2[i] = regval1[i]; 2052b63b36faSFred Richter } 2053b63b36faSFred Richter } 2054b63b36faSFred Richter debug = sav_debug; 2055b63b36faSFred Richter } 20568e8cd34eSMichael Ira Krufky #endif /* DBG_DUMP */ 2057b63b36faSFred Richter 2058b63b36faSFred Richter 2059b63b36faSFred Richter 2060b63b36faSFred Richter static struct dvb_frontend_ops lgdt3306a_ops = { 2061b63b36faSFred Richter .delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B }, 2062b63b36faSFred Richter .info = { 2063b63b36faSFred Richter .name = "LG Electronics LGDT3306A VSB/QAM Frontend", 20648e8cd34eSMichael Ira Krufky #if 0 20658e8cd34eSMichael Ira Krufky .type = FE_ATSC, 20668e8cd34eSMichael Ira Krufky #endif 2067b63b36faSFred Richter .frequency_min = 54000000, 20688e8cd34eSMichael Ira Krufky .frequency_max = 858000000, 2069b63b36faSFred Richter .frequency_stepsize = 62500, 2070b63b36faSFred Richter .caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB 2071b63b36faSFred Richter }, 2072b63b36faSFred Richter .i2c_gate_ctrl = lgdt3306a_i2c_gate_ctrl, 2073b63b36faSFred Richter .init = lgdt3306a_init, 2074b63b36faSFred Richter .sleep = lgdt3306a_fe_sleep, 2075b63b36faSFred Richter /* if this is set, it overrides the default swzigzag */ 2076b63b36faSFred Richter .tune = lgdt3306a_tune, 2077b63b36faSFred Richter .set_frontend = lgdt3306a_set_parameters, 2078b63b36faSFred Richter .get_frontend = lgdt3306a_get_frontend, 2079b63b36faSFred Richter .get_frontend_algo = lgdt3306a_get_frontend_algo, 2080b63b36faSFred Richter .get_tune_settings = lgdt3306a_get_tune_settings, 2081b63b36faSFred Richter .read_status = lgdt3306a_read_status, 2082b63b36faSFred Richter .read_ber = lgdt3306a_read_ber, 2083b63b36faSFred Richter .read_signal_strength = lgdt3306a_read_signal_strength, 2084b63b36faSFred Richter .read_snr = lgdt3306a_read_snr, 2085b63b36faSFred Richter .read_ucblocks = lgdt3306a_read_ucblocks, 2086b63b36faSFred Richter .release = lgdt3306a_release, 2087b63b36faSFred Richter .ts_bus_ctrl = lgdt3306a_ts_bus_ctrl, 2088b63b36faSFred Richter .search = lgdt3306a_search, 2089b63b36faSFred Richter }; 2090b63b36faSFred Richter 2091b63b36faSFred Richter MODULE_DESCRIPTION("LG Electronics LGDT3306A ATSC/QAM-B Demodulator Driver"); 2092b63b36faSFred Richter MODULE_AUTHOR("Fred Richter <frichter@hauppauge.com>"); 2093b63b36faSFred Richter MODULE_LICENSE("GPL"); 2094b63b36faSFred Richter MODULE_VERSION("0.2"); 2095b63b36faSFred Richter 2096b63b36faSFred Richter /* 2097b63b36faSFred Richter * Local variables: 2098b63b36faSFred Richter * c-basic-offset: 8 2099b63b36faSFred Richter * End: 2100b63b36faSFred Richter */ 2101