1c942fddfSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 2b63b36faSFred Richter /* 3b63b36faSFred Richter * Support for LGDT3306A - 8VSB/QAM-B 4b63b36faSFred Richter * 5b63b36faSFred Richter * Copyright (C) 2013 Fred Richter <frichter@hauppauge.com> 6b63b36faSFred Richter * - driver structure based on lgdt3305.[ch] by Michael Krufky 7b63b36faSFred Richter * - code based on LG3306_V0.35 API by LG Electronics Inc. 8b63b36faSFred Richter */ 9b63b36faSFred Richter 10097117caSMauro Carvalho Chehab #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 11097117caSMauro Carvalho Chehab 12b63b36faSFred Richter #include <asm/div64.h> 131f679ff6SThomas Meyer #include <linux/kernel.h> 14b63b36faSFred Richter #include <linux/dvb/frontend.h> 15fada1935SMauro Carvalho Chehab #include <media/dvb_math.h> 16b63b36faSFred Richter #include "lgdt3306a.h" 174f751890SKevin Cheng #include <linux/i2c-mux.h> 18b63b36faSFred Richter 19b63b36faSFred Richter 20b63b36faSFred Richter static int debug; 21b63b36faSFred Richter module_param(debug, int, 0644); 22b63b36faSFred Richter MODULE_PARM_DESC(debug, "set debug level (info=1, reg=2 (or-able))"); 23b63b36faSFred Richter 244966c0c5SBrad Love /* 254966c0c5SBrad Love * Older drivers treated QAM64 and QAM256 the same; that is the HW always 264966c0c5SBrad Love * used "Auto" mode during detection. Setting "forced_manual"=1 allows 274966c0c5SBrad Love * the user to treat these modes as separate. For backwards compatibility, 284966c0c5SBrad Love * it's off by default. QAM_AUTO can now be specified to achive that 294966c0c5SBrad Love * effect even if "forced_manual"=1 304966c0c5SBrad Love */ 314966c0c5SBrad Love static int forced_manual; 324966c0c5SBrad Love module_param(forced_manual, int, 0644); 334966c0c5SBrad Love MODULE_PARM_DESC(forced_manual, "if set, QAM64 and QAM256 will only lock to modulation specified"); 344966c0c5SBrad Love 35b63b36faSFred Richter #define DBG_INFO 1 36b63b36faSFred Richter #define DBG_REG 2 378e8cd34eSMichael Ira Krufky #define DBG_DUMP 4 /* FGR - comment out to remove dump code */ 38b63b36faSFred Richter 39097117caSMauro Carvalho Chehab #define lg_debug(fmt, arg...) \ 40097117caSMauro Carvalho Chehab printk(KERN_DEBUG pr_fmt(fmt), ## arg) 41b63b36faSFred Richter 42097117caSMauro Carvalho Chehab #define dbg_info(fmt, arg...) \ 43097117caSMauro Carvalho Chehab do { \ 44097117caSMauro Carvalho Chehab if (debug & DBG_INFO) \ 45097117caSMauro Carvalho Chehab lg_debug(fmt, ## arg); \ 46097117caSMauro Carvalho Chehab } while (0) 47097117caSMauro Carvalho Chehab 48097117caSMauro Carvalho Chehab #define dbg_reg(fmt, arg...) \ 49097117caSMauro Carvalho Chehab do { \ 50097117caSMauro Carvalho Chehab if (debug & DBG_REG) \ 51097117caSMauro Carvalho Chehab lg_debug(fmt, ## arg); \ 52097117caSMauro Carvalho Chehab } while (0) 53b63b36faSFred Richter 54b63b36faSFred Richter #define lg_chkerr(ret) \ 55b63b36faSFred Richter ({ \ 56b63b36faSFred Richter int __ret; \ 57b63b36faSFred Richter __ret = (ret < 0); \ 58b63b36faSFred Richter if (__ret) \ 59097117caSMauro Carvalho Chehab pr_err("error %d on line %d\n", ret, __LINE__); \ 60b63b36faSFred Richter __ret; \ 61b63b36faSFred Richter }) 62b63b36faSFred Richter 63b63b36faSFred Richter struct lgdt3306a_state { 64b63b36faSFred Richter struct i2c_adapter *i2c_adap; 65b63b36faSFred Richter const struct lgdt3306a_config *cfg; 66b63b36faSFred Richter 67b63b36faSFred Richter struct dvb_frontend frontend; 68b63b36faSFred Richter 690df289a2SMauro Carvalho Chehab enum fe_modulation current_modulation; 70b63b36faSFred Richter u32 current_frequency; 71b63b36faSFred Richter u32 snr; 724f751890SKevin Cheng 734f751890SKevin Cheng struct i2c_mux_core *muxc; 74b63b36faSFred Richter }; 75b63b36faSFred Richter 7695f22c5aSMauro Carvalho Chehab /* 7795f22c5aSMauro Carvalho Chehab * LG3306A Register Usage 7895f22c5aSMauro Carvalho Chehab * (LG does not really name the registers, so this code does not either) 7995f22c5aSMauro Carvalho Chehab * 8095f22c5aSMauro Carvalho Chehab * 0000 -> 00FF Common control and status 8195f22c5aSMauro Carvalho Chehab * 1000 -> 10FF Synchronizer control and status 8295f22c5aSMauro Carvalho Chehab * 1F00 -> 1FFF Smart Antenna control and status 8395f22c5aSMauro Carvalho Chehab * 2100 -> 21FF VSB Equalizer control and status 8495f22c5aSMauro Carvalho Chehab * 2800 -> 28FF QAM Equalizer control and status 8595f22c5aSMauro Carvalho Chehab * 3000 -> 30FF FEC control and status 8695f22c5aSMauro Carvalho Chehab */ 87b63b36faSFred Richter 88f883d603SMichael Ira Krufky enum lgdt3306a_lock_status { 89b63b36faSFred Richter LG3306_UNLOCK = 0x00, 90b63b36faSFred Richter LG3306_LOCK = 0x01, 914937ba94SMauro Carvalho Chehab LG3306_UNKNOWN_LOCK = 0xff 92f883d603SMichael Ira Krufky }; 93b63b36faSFred Richter 94f883d603SMichael Ira Krufky enum lgdt3306a_neverlock_status { 95b63b36faSFred Richter LG3306_NL_INIT = 0x00, 96b63b36faSFred Richter LG3306_NL_PROCESS = 0x01, 97b63b36faSFred Richter LG3306_NL_LOCK = 0x02, 98b63b36faSFred Richter LG3306_NL_FAIL = 0x03, 994937ba94SMauro Carvalho Chehab LG3306_NL_UNKNOWN = 0xff 100f883d603SMichael Ira Krufky }; 101b63b36faSFred Richter 102f883d603SMichael Ira Krufky enum lgdt3306a_modulation { 103b63b36faSFred Richter LG3306_VSB = 0x00, 104b63b36faSFred Richter LG3306_QAM64 = 0x01, 105b63b36faSFred Richter LG3306_QAM256 = 0x02, 1064937ba94SMauro Carvalho Chehab LG3306_UNKNOWN_MODE = 0xff 107f883d603SMichael Ira Krufky }; 108b63b36faSFred Richter 109f883d603SMichael Ira Krufky enum lgdt3306a_lock_check { 110b63b36faSFred Richter LG3306_SYNC_LOCK, 111b63b36faSFred Richter LG3306_FEC_LOCK, 112b63b36faSFred Richter LG3306_TR_LOCK, 113b63b36faSFred Richter LG3306_AGC_LOCK, 114f883d603SMichael Ira Krufky }; 115b63b36faSFred Richter 116b63b36faSFred Richter 117b63b36faSFred Richter #ifdef DBG_DUMP 118b63b36faSFred Richter static void lgdt3306a_DumpAllRegs(struct lgdt3306a_state *state); 119b63b36faSFred Richter static void lgdt3306a_DumpRegs(struct lgdt3306a_state *state); 120b63b36faSFred Richter #endif 121b63b36faSFred Richter 122b63b36faSFred Richter 123b63b36faSFred Richter static int lgdt3306a_write_reg(struct lgdt3306a_state *state, u16 reg, u8 val) 124b63b36faSFred Richter { 125b63b36faSFred Richter int ret; 126b63b36faSFred Richter u8 buf[] = { reg >> 8, reg & 0xff, val }; 127b63b36faSFred Richter struct i2c_msg msg = { 128b63b36faSFred Richter .addr = state->cfg->i2c_addr, .flags = 0, 129b63b36faSFred Richter .buf = buf, .len = 3, 130b63b36faSFred Richter }; 131b63b36faSFred Richter 132097117caSMauro Carvalho Chehab dbg_reg("reg: 0x%04x, val: 0x%02x\n", reg, val); 133b63b36faSFred Richter 134b63b36faSFred Richter ret = i2c_transfer(state->i2c_adap, &msg, 1); 135b63b36faSFred Richter 136b63b36faSFred Richter if (ret != 1) { 137097117caSMauro Carvalho Chehab pr_err("error (addr %02x %02x <- %02x, err = %i)\n", 138b63b36faSFred Richter msg.buf[0], msg.buf[1], msg.buf[2], ret); 139b63b36faSFred Richter if (ret < 0) 140b63b36faSFred Richter return ret; 141b63b36faSFred Richter else 142b63b36faSFred Richter return -EREMOTEIO; 143b63b36faSFred Richter } 144b63b36faSFred Richter return 0; 145b63b36faSFred Richter } 146b63b36faSFred Richter 147b63b36faSFred Richter static int lgdt3306a_read_reg(struct lgdt3306a_state *state, u16 reg, u8 *val) 148b63b36faSFred Richter { 149b63b36faSFred Richter int ret; 150b63b36faSFred Richter u8 reg_buf[] = { reg >> 8, reg & 0xff }; 151b63b36faSFred Richter struct i2c_msg msg[] = { 152b63b36faSFred Richter { .addr = state->cfg->i2c_addr, 153b63b36faSFred Richter .flags = 0, .buf = reg_buf, .len = 2 }, 154b63b36faSFred Richter { .addr = state->cfg->i2c_addr, 155b63b36faSFred Richter .flags = I2C_M_RD, .buf = val, .len = 1 }, 156b63b36faSFred Richter }; 157b63b36faSFred Richter 158b63b36faSFred Richter ret = i2c_transfer(state->i2c_adap, msg, 2); 159b63b36faSFred Richter 160b63b36faSFred Richter if (ret != 2) { 161097117caSMauro Carvalho Chehab pr_err("error (addr %02x reg %04x error (ret == %i)\n", 162b63b36faSFred Richter state->cfg->i2c_addr, reg, ret); 163b63b36faSFred Richter if (ret < 0) 164b63b36faSFred Richter return ret; 165b63b36faSFred Richter else 166b63b36faSFred Richter return -EREMOTEIO; 167b63b36faSFred Richter } 168097117caSMauro Carvalho Chehab dbg_reg("reg: 0x%04x, val: 0x%02x\n", reg, *val); 169b63b36faSFred Richter 170b63b36faSFred Richter return 0; 171b63b36faSFred Richter } 172b63b36faSFred Richter 173b63b36faSFred Richter #define read_reg(state, reg) \ 174b63b36faSFred Richter ({ \ 175b63b36faSFred Richter u8 __val; \ 176b63b36faSFred Richter int ret = lgdt3306a_read_reg(state, reg, &__val); \ 177b63b36faSFred Richter if (lg_chkerr(ret)) \ 178b63b36faSFred Richter __val = 0; \ 179b63b36faSFred Richter __val; \ 180b63b36faSFred Richter }) 181b63b36faSFred Richter 182b63b36faSFred Richter static int lgdt3306a_set_reg_bit(struct lgdt3306a_state *state, 183b63b36faSFred Richter u16 reg, int bit, int onoff) 184b63b36faSFred Richter { 185b63b36faSFred Richter u8 val; 186b63b36faSFred Richter int ret; 187b63b36faSFred Richter 188097117caSMauro Carvalho Chehab dbg_reg("reg: 0x%04x, bit: %d, level: %d\n", reg, bit, onoff); 189b63b36faSFred Richter 190b63b36faSFred Richter ret = lgdt3306a_read_reg(state, reg, &val); 191b63b36faSFred Richter if (lg_chkerr(ret)) 192b63b36faSFred Richter goto fail; 193b63b36faSFred Richter 194b63b36faSFred Richter val &= ~(1 << bit); 195b63b36faSFred Richter val |= (onoff & 1) << bit; 196b63b36faSFred Richter 197b63b36faSFred Richter ret = lgdt3306a_write_reg(state, reg, val); 198b63b36faSFred Richter lg_chkerr(ret); 199b63b36faSFred Richter fail: 200b63b36faSFred Richter return ret; 201b63b36faSFred Richter } 202b63b36faSFred Richter 203b63b36faSFred Richter /* ------------------------------------------------------------------------ */ 204b63b36faSFred Richter 205b63b36faSFred Richter static int lgdt3306a_soft_reset(struct lgdt3306a_state *state) 206b63b36faSFred Richter { 207b63b36faSFred Richter int ret; 208b63b36faSFred Richter 209097117caSMauro Carvalho Chehab dbg_info("\n"); 210b63b36faSFred Richter 211b63b36faSFred Richter ret = lgdt3306a_set_reg_bit(state, 0x0000, 7, 0); 212b63b36faSFred Richter if (lg_chkerr(ret)) 213b63b36faSFred Richter goto fail; 214b63b36faSFred Richter 215b63b36faSFred Richter msleep(20); 216b63b36faSFred Richter ret = lgdt3306a_set_reg_bit(state, 0x0000, 7, 1); 217b63b36faSFred Richter lg_chkerr(ret); 218b63b36faSFred Richter 219b63b36faSFred Richter fail: 220b63b36faSFred Richter return ret; 221b63b36faSFred Richter } 222b63b36faSFred Richter 223b63b36faSFred Richter static int lgdt3306a_mpeg_mode(struct lgdt3306a_state *state, 224b63b36faSFred Richter enum lgdt3306a_mpeg_mode mode) 225b63b36faSFred Richter { 226b63b36faSFred Richter u8 val; 227b63b36faSFred Richter int ret; 228b63b36faSFred Richter 229097117caSMauro Carvalho Chehab dbg_info("(%d)\n", mode); 230534f4364SMauro Carvalho Chehab /* transport packet format - TPSENB=0x80 */ 231534f4364SMauro Carvalho Chehab ret = lgdt3306a_set_reg_bit(state, 0x0071, 7, 232534f4364SMauro Carvalho Chehab mode == LGDT3306A_MPEG_PARALLEL ? 1 : 0); 233b63b36faSFred Richter if (lg_chkerr(ret)) 234b63b36faSFred Richter goto fail; 235b63b36faSFred Richter 236534f4364SMauro Carvalho Chehab /* 237534f4364SMauro Carvalho Chehab * start of packet signal duration 238534f4364SMauro Carvalho Chehab * TPSSOPBITEN=0x40; 0=byte duration, 1=bit duration 239534f4364SMauro Carvalho Chehab */ 240534f4364SMauro Carvalho Chehab ret = lgdt3306a_set_reg_bit(state, 0x0071, 6, 0); 241b63b36faSFred Richter if (lg_chkerr(ret)) 242b63b36faSFred Richter goto fail; 243b63b36faSFred Richter 244b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x0070, &val); 245b63b36faSFred Richter if (lg_chkerr(ret)) 246b63b36faSFred Richter goto fail; 247b63b36faSFred Richter 2488e8cd34eSMichael Ira Krufky val |= 0x10; /* TPCLKSUPB=0x10 */ 249b63b36faSFred Richter 250b63b36faSFred Richter if (mode == LGDT3306A_MPEG_PARALLEL) 251b63b36faSFred Richter val &= ~0x10; 252b63b36faSFred Richter 253b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0070, val); 254b63b36faSFred Richter lg_chkerr(ret); 255b63b36faSFred Richter 256b63b36faSFred Richter fail: 257b63b36faSFred Richter return ret; 258b63b36faSFred Richter } 259b63b36faSFred Richter 260b63b36faSFred Richter static int lgdt3306a_mpeg_mode_polarity(struct lgdt3306a_state *state, 261b63b36faSFred Richter enum lgdt3306a_tp_clock_edge edge, 262b63b36faSFred Richter enum lgdt3306a_tp_valid_polarity valid) 263b63b36faSFred Richter { 264b63b36faSFred Richter u8 val; 265b63b36faSFred Richter int ret; 266b63b36faSFred Richter 267097117caSMauro Carvalho Chehab dbg_info("edge=%d, valid=%d\n", edge, valid); 268b63b36faSFred Richter 269b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x0070, &val); 270b63b36faSFred Richter if (lg_chkerr(ret)) 271b63b36faSFred Richter goto fail; 272b63b36faSFred Richter 2738e8cd34eSMichael Ira Krufky val &= ~0x06; /* TPCLKPOL=0x04, TPVALPOL=0x02 */ 274b63b36faSFred Richter 275b63b36faSFred Richter if (edge == LGDT3306A_TPCLK_RISING_EDGE) 276b63b36faSFred Richter val |= 0x04; 277b63b36faSFred Richter if (valid == LGDT3306A_TP_VALID_HIGH) 278b63b36faSFred Richter val |= 0x02; 279b63b36faSFred Richter 280b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0070, val); 281b63b36faSFred Richter lg_chkerr(ret); 282b63b36faSFred Richter 283b63b36faSFred Richter fail: 284b63b36faSFred Richter return ret; 285b63b36faSFred Richter } 286b63b36faSFred Richter 287b63b36faSFred Richter static int lgdt3306a_mpeg_tristate(struct lgdt3306a_state *state, 288b63b36faSFred Richter int mode) 289b63b36faSFred Richter { 290b63b36faSFred Richter u8 val; 291b63b36faSFred Richter int ret; 292b63b36faSFred Richter 293097117caSMauro Carvalho Chehab dbg_info("(%d)\n", mode); 294b63b36faSFred Richter 295b63b36faSFred Richter if (mode) { 296b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x0070, &val); 297b63b36faSFred Richter if (lg_chkerr(ret)) 298b63b36faSFred Richter goto fail; 299534f4364SMauro Carvalho Chehab /* 300534f4364SMauro Carvalho Chehab * Tristate bus; TPOUTEN=0x80, TPCLKOUTEN=0x20, 301534f4364SMauro Carvalho Chehab * TPDATAOUTEN=0x08 302534f4364SMauro Carvalho Chehab */ 303534f4364SMauro Carvalho Chehab val &= ~0xa8; 304b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0070, val); 305b63b36faSFred Richter if (lg_chkerr(ret)) 306b63b36faSFred Richter goto fail; 307b63b36faSFred Richter 308534f4364SMauro Carvalho Chehab /* AGCIFOUTENB=0x40; 1=Disable IFAGC pin */ 309534f4364SMauro Carvalho Chehab ret = lgdt3306a_set_reg_bit(state, 0x0003, 6, 1); 310b63b36faSFred Richter if (lg_chkerr(ret)) 311b63b36faSFred Richter goto fail; 312b63b36faSFred Richter 313b63b36faSFred Richter } else { 314534f4364SMauro Carvalho Chehab /* enable IFAGC pin */ 315534f4364SMauro Carvalho Chehab ret = lgdt3306a_set_reg_bit(state, 0x0003, 6, 0); 316b63b36faSFred Richter if (lg_chkerr(ret)) 317b63b36faSFred Richter goto fail; 318b63b36faSFred Richter 319b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x0070, &val); 320b63b36faSFred Richter if (lg_chkerr(ret)) 321b63b36faSFred Richter goto fail; 322b63b36faSFred Richter 3234937ba94SMauro Carvalho Chehab val |= 0xa8; /* enable bus */ 324b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0070, val); 325b63b36faSFred Richter if (lg_chkerr(ret)) 326b63b36faSFred Richter goto fail; 327b63b36faSFred Richter } 328b63b36faSFred Richter 329b63b36faSFred Richter fail: 330b63b36faSFred Richter return ret; 331b63b36faSFred Richter } 332b63b36faSFred Richter 333b63b36faSFred Richter static int lgdt3306a_ts_bus_ctrl(struct dvb_frontend *fe, int acquire) 334b63b36faSFred Richter { 335b63b36faSFred Richter struct lgdt3306a_state *state = fe->demodulator_priv; 336b63b36faSFred Richter 337097117caSMauro Carvalho Chehab dbg_info("acquire=%d\n", acquire); 338b63b36faSFred Richter 339b63b36faSFred Richter return lgdt3306a_mpeg_tristate(state, acquire ? 0 : 1); 340b63b36faSFred Richter 341b63b36faSFred Richter } 342b63b36faSFred Richter 343b63b36faSFred Richter static int lgdt3306a_power(struct lgdt3306a_state *state, 344b63b36faSFred Richter int mode) 345b63b36faSFred Richter { 346b63b36faSFred Richter int ret; 347b63b36faSFred Richter 348097117caSMauro Carvalho Chehab dbg_info("(%d)\n", mode); 349b63b36faSFred Richter 350b63b36faSFred Richter if (mode == 0) { 351534f4364SMauro Carvalho Chehab /* into reset */ 352534f4364SMauro Carvalho Chehab ret = lgdt3306a_set_reg_bit(state, 0x0000, 7, 0); 353b63b36faSFred Richter if (lg_chkerr(ret)) 354b63b36faSFred Richter goto fail; 355b63b36faSFred Richter 356534f4364SMauro Carvalho Chehab /* power down */ 357534f4364SMauro Carvalho Chehab ret = lgdt3306a_set_reg_bit(state, 0x0000, 0, 0); 358b63b36faSFred Richter if (lg_chkerr(ret)) 359b63b36faSFred Richter goto fail; 360b63b36faSFred Richter 361b63b36faSFred Richter } else { 362534f4364SMauro Carvalho Chehab /* out of reset */ 363534f4364SMauro Carvalho Chehab ret = lgdt3306a_set_reg_bit(state, 0x0000, 7, 1); 364b63b36faSFred Richter if (lg_chkerr(ret)) 365b63b36faSFred Richter goto fail; 366b63b36faSFred Richter 367534f4364SMauro Carvalho Chehab /* power up */ 368534f4364SMauro Carvalho Chehab ret = lgdt3306a_set_reg_bit(state, 0x0000, 0, 1); 369b63b36faSFred Richter if (lg_chkerr(ret)) 370b63b36faSFred Richter goto fail; 371b63b36faSFred Richter } 372b63b36faSFred Richter 373b63b36faSFred Richter #ifdef DBG_DUMP 374b63b36faSFred Richter lgdt3306a_DumpAllRegs(state); 375b63b36faSFred Richter #endif 376b63b36faSFred Richter fail: 377b63b36faSFred Richter return ret; 378b63b36faSFred Richter } 379b63b36faSFred Richter 380b63b36faSFred Richter 381b63b36faSFred Richter static int lgdt3306a_set_vsb(struct lgdt3306a_state *state) 382b63b36faSFred Richter { 383b63b36faSFred Richter u8 val; 384b63b36faSFred Richter int ret; 385b63b36faSFred Richter 386097117caSMauro Carvalho Chehab dbg_info("\n"); 387b63b36faSFred Richter 3888e8cd34eSMichael Ira Krufky /* 0. Spectrum inversion detection manual; spectrum inverted */ 389b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x0002, &val); 3904937ba94SMauro Carvalho Chehab val &= 0xf7; /* SPECINVAUTO Off */ 3918e8cd34eSMichael Ira Krufky val |= 0x04; /* SPECINV On */ 392b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0002, val); 393b63b36faSFred Richter if (lg_chkerr(ret)) 394b63b36faSFred Richter goto fail; 395b63b36faSFred Richter 3968e8cd34eSMichael Ira Krufky /* 1. Selection of standard mode(0x08=QAM, 0x80=VSB) */ 397b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0008, 0x80); 398b63b36faSFred Richter if (lg_chkerr(ret)) 399b63b36faSFred Richter goto fail; 400b63b36faSFred Richter 4018e8cd34eSMichael Ira Krufky /* 2. Bandwidth mode for VSB(6MHz) */ 402b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x0009, &val); 4034937ba94SMauro Carvalho Chehab val &= 0xe3; 4044937ba94SMauro Carvalho Chehab val |= 0x0c; /* STDOPDETTMODE[2:0]=3 */ 405b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0009, val); 406b63b36faSFred Richter if (lg_chkerr(ret)) 407b63b36faSFred Richter goto fail; 408b63b36faSFred Richter 4098e8cd34eSMichael Ira Krufky /* 3. QAM mode detection mode(None) */ 410b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x0009, &val); 4114937ba94SMauro Carvalho Chehab val &= 0xfc; /* STDOPDETCMODE[1:0]=0 */ 412b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0009, val); 413b63b36faSFred Richter if (lg_chkerr(ret)) 414b63b36faSFred Richter goto fail; 415b63b36faSFred Richter 4168e8cd34eSMichael Ira Krufky /* 4. ADC sampling frequency rate(2x sampling) */ 4174937ba94SMauro Carvalho Chehab ret = lgdt3306a_read_reg(state, 0x000d, &val); 4184937ba94SMauro Carvalho Chehab val &= 0xbf; /* SAMPLING4XFEN=0 */ 4194937ba94SMauro Carvalho Chehab ret = lgdt3306a_write_reg(state, 0x000d, val); 420b63b36faSFred Richter if (lg_chkerr(ret)) 421b63b36faSFred Richter goto fail; 422b63b36faSFred Richter 4238e8cd34eSMichael Ira Krufky #if 0 4248e8cd34eSMichael Ira Krufky /* FGR - disable any AICC filtering, testing only */ 4258e8cd34eSMichael Ira Krufky 426b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0024, 0x00); 427b63b36faSFred Richter if (lg_chkerr(ret)) 428b63b36faSFred Richter goto fail; 429b63b36faSFred Richter 4308e8cd34eSMichael Ira Krufky /* AICCFIXFREQ0 NT N-1(Video rejection) */ 4314937ba94SMauro Carvalho Chehab ret = lgdt3306a_write_reg(state, 0x002e, 0x00); 4324937ba94SMauro Carvalho Chehab ret = lgdt3306a_write_reg(state, 0x002f, 0x00); 433b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0030, 0x00); 434b63b36faSFred Richter 4358e8cd34eSMichael Ira Krufky /* AICCFIXFREQ1 NT N-1(Audio rejection) */ 4364937ba94SMauro Carvalho Chehab ret = lgdt3306a_write_reg(state, 0x002b, 0x00); 4374937ba94SMauro Carvalho Chehab ret = lgdt3306a_write_reg(state, 0x002c, 0x00); 4384937ba94SMauro Carvalho Chehab ret = lgdt3306a_write_reg(state, 0x002d, 0x00); 439b63b36faSFred Richter 4408e8cd34eSMichael Ira Krufky /* AICCFIXFREQ2 NT Co-Channel(Video rejection) */ 441b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0028, 0x00); 442b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0029, 0x00); 4434937ba94SMauro Carvalho Chehab ret = lgdt3306a_write_reg(state, 0x002a, 0x00); 444b63b36faSFred Richter 4458e8cd34eSMichael Ira Krufky /* AICCFIXFREQ3 NT Co-Channel(Audio rejection) */ 446b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0025, 0x00); 447b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0026, 0x00); 448b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0027, 0x00); 449b63b36faSFred Richter 4508e8cd34eSMichael Ira Krufky #else 4518e8cd34eSMichael Ira Krufky /* FGR - this works well for HVR-1955,1975 */ 4528e8cd34eSMichael Ira Krufky 4538e8cd34eSMichael Ira Krufky /* 5. AICCOPMODE NT N-1 Adj. */ 454b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0024, 0x5A); 455b63b36faSFred Richter if (lg_chkerr(ret)) 456b63b36faSFred Richter goto fail; 457b63b36faSFred Richter 4588e8cd34eSMichael Ira Krufky /* AICCFIXFREQ0 NT N-1(Video rejection) */ 4594937ba94SMauro Carvalho Chehab ret = lgdt3306a_write_reg(state, 0x002e, 0x5A); 4604937ba94SMauro Carvalho Chehab ret = lgdt3306a_write_reg(state, 0x002f, 0x00); 461b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0030, 0x00); 462b63b36faSFred Richter 4638e8cd34eSMichael Ira Krufky /* AICCFIXFREQ1 NT N-1(Audio rejection) */ 4644937ba94SMauro Carvalho Chehab ret = lgdt3306a_write_reg(state, 0x002b, 0x36); 4654937ba94SMauro Carvalho Chehab ret = lgdt3306a_write_reg(state, 0x002c, 0x00); 4664937ba94SMauro Carvalho Chehab ret = lgdt3306a_write_reg(state, 0x002d, 0x00); 467b63b36faSFred Richter 4688e8cd34eSMichael Ira Krufky /* AICCFIXFREQ2 NT Co-Channel(Video rejection) */ 469b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0028, 0x2A); 470b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0029, 0x00); 4714937ba94SMauro Carvalho Chehab ret = lgdt3306a_write_reg(state, 0x002a, 0x00); 472b63b36faSFred Richter 4738e8cd34eSMichael Ira Krufky /* AICCFIXFREQ3 NT Co-Channel(Audio rejection) */ 474b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0025, 0x06); 475b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0026, 0x00); 476b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0027, 0x00); 477b63b36faSFred Richter #endif 478b63b36faSFred Richter 4794937ba94SMauro Carvalho Chehab ret = lgdt3306a_read_reg(state, 0x001e, &val); 4804937ba94SMauro Carvalho Chehab val &= 0x0f; 4814937ba94SMauro Carvalho Chehab val |= 0xa0; 4824937ba94SMauro Carvalho Chehab ret = lgdt3306a_write_reg(state, 0x001e, val); 483b63b36faSFred Richter 484b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0022, 0x08); 485b63b36faSFred Richter 486b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0023, 0xFF); 487b63b36faSFred Richter 4884937ba94SMauro Carvalho Chehab ret = lgdt3306a_read_reg(state, 0x211f, &val); 4894937ba94SMauro Carvalho Chehab val &= 0xef; 4904937ba94SMauro Carvalho Chehab ret = lgdt3306a_write_reg(state, 0x211f, val); 491b63b36faSFred Richter 492b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x2173, 0x01); 493b63b36faSFred Richter 494b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x1061, &val); 4954937ba94SMauro Carvalho Chehab val &= 0xf8; 496b63b36faSFred Richter val |= 0x04; 497b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x1061, val); 498b63b36faSFred Richter 4994937ba94SMauro Carvalho Chehab ret = lgdt3306a_read_reg(state, 0x103d, &val); 5004937ba94SMauro Carvalho Chehab val &= 0xcf; 5014937ba94SMauro Carvalho Chehab ret = lgdt3306a_write_reg(state, 0x103d, val); 502b63b36faSFred Richter 503b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x2122, 0x40); 504b63b36faSFred Richter 505b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x2141, &val); 5064937ba94SMauro Carvalho Chehab val &= 0x3f; 507b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x2141, val); 508b63b36faSFred Richter 509b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x2135, &val); 5104937ba94SMauro Carvalho Chehab val &= 0x0f; 511b63b36faSFred Richter val |= 0x70; 512b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x2135, val); 513b63b36faSFred Richter 514b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x0003, &val); 5154937ba94SMauro Carvalho Chehab val &= 0xf7; 516b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0003, val); 517b63b36faSFred Richter 5184937ba94SMauro Carvalho Chehab ret = lgdt3306a_read_reg(state, 0x001c, &val); 5194937ba94SMauro Carvalho Chehab val &= 0x7f; 5204937ba94SMauro Carvalho Chehab ret = lgdt3306a_write_reg(state, 0x001c, val); 521b63b36faSFred Richter 5228e8cd34eSMichael Ira Krufky /* 6. EQ step size */ 523b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x2179, &val); 5244937ba94SMauro Carvalho Chehab val &= 0xf8; 525b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x2179, val); 526b63b36faSFred Richter 5274937ba94SMauro Carvalho Chehab ret = lgdt3306a_read_reg(state, 0x217a, &val); 5284937ba94SMauro Carvalho Chehab val &= 0xf8; 5294937ba94SMauro Carvalho Chehab ret = lgdt3306a_write_reg(state, 0x217a, val); 530b63b36faSFred Richter 5318e8cd34eSMichael Ira Krufky /* 7. Reset */ 532b63b36faSFred Richter ret = lgdt3306a_soft_reset(state); 533b63b36faSFred Richter if (lg_chkerr(ret)) 534b63b36faSFred Richter goto fail; 535b63b36faSFred Richter 536097117caSMauro Carvalho Chehab dbg_info("complete\n"); 537b63b36faSFred Richter fail: 538b63b36faSFred Richter return ret; 539b63b36faSFred Richter } 540b63b36faSFred Richter 541b63b36faSFred Richter static int lgdt3306a_set_qam(struct lgdt3306a_state *state, int modulation) 542b63b36faSFred Richter { 543b63b36faSFred Richter u8 val; 544b63b36faSFred Richter int ret; 545b63b36faSFred Richter 546097117caSMauro Carvalho Chehab dbg_info("modulation=%d\n", modulation); 547b63b36faSFred Richter 5488e8cd34eSMichael Ira Krufky /* 1. Selection of standard mode(0x08=QAM, 0x80=VSB) */ 549b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0008, 0x08); 550b63b36faSFred Richter if (lg_chkerr(ret)) 551b63b36faSFred Richter goto fail; 552b63b36faSFred Richter 5538e8cd34eSMichael Ira Krufky /* 1a. Spectrum inversion detection to Auto */ 554b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x0002, &val); 5554937ba94SMauro Carvalho Chehab val &= 0xfb; /* SPECINV Off */ 5568e8cd34eSMichael Ira Krufky val |= 0x08; /* SPECINVAUTO On */ 557b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0002, val); 558b63b36faSFred Richter if (lg_chkerr(ret)) 559b63b36faSFred Richter goto fail; 560b63b36faSFred Richter 5618e8cd34eSMichael Ira Krufky /* 2. Bandwidth mode for QAM */ 562b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x0009, &val); 5634937ba94SMauro Carvalho Chehab val &= 0xe3; /* STDOPDETTMODE[2:0]=0 VSB Off */ 564b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0009, val); 565b63b36faSFred Richter if (lg_chkerr(ret)) 566b63b36faSFred Richter goto fail; 567b63b36faSFred Richter 5688e8cd34eSMichael Ira Krufky /* 3. : 64QAM/256QAM detection(manual, auto) */ 569b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x0009, &val); 5704937ba94SMauro Carvalho Chehab val &= 0xfc; 5714966c0c5SBrad Love /* Check for forced Manual modulation modes; otherwise always "auto" */ 5724966c0c5SBrad Love if(forced_manual && (modulation != QAM_AUTO)){ 5734966c0c5SBrad Love val |= 0x01; /* STDOPDETCMODE[1:0]= 1=Manual */ 5744966c0c5SBrad Love } else { 5754966c0c5SBrad Love val |= 0x02; /* STDOPDETCMODE[1:0]= 2=Auto */ 5764966c0c5SBrad Love } 577b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0009, val); 578b63b36faSFred Richter if (lg_chkerr(ret)) 579b63b36faSFred Richter goto fail; 580b63b36faSFred Richter 5818e8cd34eSMichael Ira Krufky /* 3a. : 64QAM/256QAM selection for manual */ 582b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x101a, &val); 5834937ba94SMauro Carvalho Chehab val &= 0xf8; 5848e8cd34eSMichael Ira Krufky if (modulation == QAM_64) 5858e8cd34eSMichael Ira Krufky val |= 0x02; /* QMDQMODE[2:0]=2=QAM64 */ 5868e8cd34eSMichael Ira Krufky else 5878e8cd34eSMichael Ira Krufky val |= 0x04; /* QMDQMODE[2:0]=4=QAM256 */ 5888e8cd34eSMichael Ira Krufky 589b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x101a, val); 590b63b36faSFred Richter if (lg_chkerr(ret)) 591b63b36faSFred Richter goto fail; 592b63b36faSFred Richter 5938e8cd34eSMichael Ira Krufky /* 4. ADC sampling frequency rate(4x sampling) */ 5944937ba94SMauro Carvalho Chehab ret = lgdt3306a_read_reg(state, 0x000d, &val); 5954937ba94SMauro Carvalho Chehab val &= 0xbf; 5968e8cd34eSMichael Ira Krufky val |= 0x40; /* SAMPLING4XFEN=1 */ 5974937ba94SMauro Carvalho Chehab ret = lgdt3306a_write_reg(state, 0x000d, val); 598b63b36faSFred Richter if (lg_chkerr(ret)) 599b63b36faSFred Richter goto fail; 600b63b36faSFred Richter 6018e8cd34eSMichael Ira Krufky /* 5. No AICC operation in QAM mode */ 602b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x0024, &val); 603b63b36faSFred Richter val &= 0x00; 604b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0024, val); 605b63b36faSFred Richter if (lg_chkerr(ret)) 606b63b36faSFred Richter goto fail; 607b63b36faSFred Richter 6084c7c3f9bSBrad Love /* 5.1 V0.36 SRDCHKALWAYS : For better QAM detection */ 6094c7c3f9bSBrad Love ret = lgdt3306a_read_reg(state, 0x000a, &val); 6104c7c3f9bSBrad Love val &= 0xfd; 6114c7c3f9bSBrad Love val |= 0x02; 6124c7c3f9bSBrad Love ret = lgdt3306a_write_reg(state, 0x000a, val); 6134c7c3f9bSBrad Love if (lg_chkerr(ret)) 6144c7c3f9bSBrad Love goto fail; 6154c7c3f9bSBrad Love 6164c7c3f9bSBrad Love /* 5.2 V0.36 Control of "no signal" detector function */ 6174c7c3f9bSBrad Love ret = lgdt3306a_read_reg(state, 0x2849, &val); 6184c7c3f9bSBrad Love val &= 0xdf; 6194c7c3f9bSBrad Love ret = lgdt3306a_write_reg(state, 0x2849, val); 6204c7c3f9bSBrad Love if (lg_chkerr(ret)) 6214c7c3f9bSBrad Love goto fail; 6224c7c3f9bSBrad Love 6234c7c3f9bSBrad Love /* 5.3 Fix for Blonder Tongue HDE-2H-QAM and AQM modulators */ 6244c7c3f9bSBrad Love ret = lgdt3306a_read_reg(state, 0x302b, &val); 6254c7c3f9bSBrad Love val &= 0x7f; /* SELFSYNCFINDEN_CQS=0; disable auto reset */ 6264c7c3f9bSBrad Love ret = lgdt3306a_write_reg(state, 0x302b, val); 6274c7c3f9bSBrad Love if (lg_chkerr(ret)) 6284c7c3f9bSBrad Love goto fail; 6294c7c3f9bSBrad Love 6308e8cd34eSMichael Ira Krufky /* 6. Reset */ 631b63b36faSFred Richter ret = lgdt3306a_soft_reset(state); 632b63b36faSFred Richter if (lg_chkerr(ret)) 633b63b36faSFred Richter goto fail; 634b63b36faSFred Richter 635097117caSMauro Carvalho Chehab dbg_info("complete\n"); 636b63b36faSFred Richter fail: 637b63b36faSFred Richter return ret; 638b63b36faSFred Richter } 639b63b36faSFred Richter 640b63b36faSFred Richter static int lgdt3306a_set_modulation(struct lgdt3306a_state *state, 641b63b36faSFred Richter struct dtv_frontend_properties *p) 642b63b36faSFred Richter { 643b63b36faSFred Richter int ret; 644b63b36faSFred Richter 645097117caSMauro Carvalho Chehab dbg_info("\n"); 646b63b36faSFred Richter 647b63b36faSFred Richter switch (p->modulation) { 648b63b36faSFred Richter case VSB_8: 649b63b36faSFred Richter ret = lgdt3306a_set_vsb(state); 650b63b36faSFred Richter break; 651b63b36faSFred Richter case QAM_64: 652b63b36faSFred Richter case QAM_256: 6534966c0c5SBrad Love case QAM_AUTO: 6544966c0c5SBrad Love ret = lgdt3306a_set_qam(state, p->modulation); 655b63b36faSFred Richter break; 656b63b36faSFred Richter default: 657b63b36faSFred Richter return -EINVAL; 658b63b36faSFred Richter } 659b63b36faSFred Richter if (lg_chkerr(ret)) 660b63b36faSFred Richter goto fail; 661b63b36faSFred Richter 662b63b36faSFred Richter state->current_modulation = p->modulation; 663b63b36faSFred Richter 664b63b36faSFred Richter fail: 665b63b36faSFred Richter return ret; 666b63b36faSFred Richter } 667b63b36faSFred Richter 668b63b36faSFred Richter /* ------------------------------------------------------------------------ */ 669b63b36faSFred Richter 670b63b36faSFred Richter static int lgdt3306a_agc_setup(struct lgdt3306a_state *state, 671b63b36faSFred Richter struct dtv_frontend_properties *p) 672b63b36faSFred Richter { 6738e8cd34eSMichael Ira Krufky /* TODO: anything we want to do here??? */ 674097117caSMauro Carvalho Chehab dbg_info("\n"); 675b63b36faSFred Richter 676b63b36faSFred Richter switch (p->modulation) { 677b63b36faSFred Richter case VSB_8: 678b63b36faSFred Richter break; 679b63b36faSFred Richter case QAM_64: 680b63b36faSFred Richter case QAM_256: 6814966c0c5SBrad Love case QAM_AUTO: 682b63b36faSFred Richter break; 683b63b36faSFred Richter default: 684b63b36faSFred Richter return -EINVAL; 685b63b36faSFred Richter } 686b63b36faSFred Richter return 0; 687b63b36faSFred Richter } 688b63b36faSFred Richter 689b63b36faSFred Richter /* ------------------------------------------------------------------------ */ 690b63b36faSFred Richter 691b63b36faSFred Richter static int lgdt3306a_set_inversion(struct lgdt3306a_state *state, 692b63b36faSFred Richter int inversion) 693b63b36faSFred Richter { 694b63b36faSFred Richter int ret; 695b63b36faSFred Richter 696097117caSMauro Carvalho Chehab dbg_info("(%d)\n", inversion); 697b63b36faSFred Richter 698b63b36faSFred Richter ret = lgdt3306a_set_reg_bit(state, 0x0002, 2, inversion ? 1 : 0); 699b63b36faSFred Richter return ret; 700b63b36faSFred Richter } 701b63b36faSFred Richter 702b63b36faSFred Richter static int lgdt3306a_set_inversion_auto(struct lgdt3306a_state *state, 703b63b36faSFred Richter int enabled) 704b63b36faSFred Richter { 705b63b36faSFred Richter int ret; 706b63b36faSFred Richter 707097117caSMauro Carvalho Chehab dbg_info("(%d)\n", enabled); 708b63b36faSFred Richter 709534f4364SMauro Carvalho Chehab /* 0=Manual 1=Auto(QAM only) - SPECINVAUTO=0x04 */ 710534f4364SMauro Carvalho Chehab ret = lgdt3306a_set_reg_bit(state, 0x0002, 3, enabled); 711b63b36faSFred Richter return ret; 712b63b36faSFred Richter } 713b63b36faSFred Richter 714b63b36faSFred Richter static int lgdt3306a_set_if(struct lgdt3306a_state *state, 715b63b36faSFred Richter struct dtv_frontend_properties *p) 716b63b36faSFred Richter { 717b63b36faSFred Richter int ret; 718b63b36faSFred Richter u16 if_freq_khz; 719b63b36faSFred Richter u8 nco1, nco2; 720b63b36faSFred Richter 721b63b36faSFred Richter switch (p->modulation) { 722b63b36faSFred Richter case VSB_8: 723b63b36faSFred Richter if_freq_khz = state->cfg->vsb_if_khz; 724b63b36faSFred Richter break; 725b63b36faSFred Richter case QAM_64: 726b63b36faSFred Richter case QAM_256: 7274966c0c5SBrad Love case QAM_AUTO: 728b63b36faSFred Richter if_freq_khz = state->cfg->qam_if_khz; 729b63b36faSFred Richter break; 730b63b36faSFred Richter default: 731b63b36faSFred Richter return -EINVAL; 732b63b36faSFred Richter } 733b63b36faSFred Richter 734b63b36faSFred Richter switch (if_freq_khz) { 735b63b36faSFred Richter default: 736f86548cfSColin Ian King pr_warn("IF=%d KHz is not supported, 3250 assumed\n", 737534f4364SMauro Carvalho Chehab if_freq_khz); 738df561f66SGustavo A. R. Silva fallthrough; 7398e8cd34eSMichael Ira Krufky case 3250: /* 3.25Mhz */ 740b63b36faSFred Richter nco1 = 0x34; 741b63b36faSFred Richter nco2 = 0x00; 742b63b36faSFred Richter break; 7438e8cd34eSMichael Ira Krufky case 3500: /* 3.50Mhz */ 744b63b36faSFred Richter nco1 = 0x38; 745b63b36faSFred Richter nco2 = 0x00; 746b63b36faSFred Richter break; 7478e8cd34eSMichael Ira Krufky case 4000: /* 4.00Mhz */ 748b63b36faSFred Richter nco1 = 0x40; 749b63b36faSFred Richter nco2 = 0x00; 750b63b36faSFred Richter break; 7518e8cd34eSMichael Ira Krufky case 5000: /* 5.00Mhz */ 752b63b36faSFred Richter nco1 = 0x50; 753b63b36faSFred Richter nco2 = 0x00; 754b63b36faSFred Richter break; 7558e8cd34eSMichael Ira Krufky case 5380: /* 5.38Mhz */ 756b63b36faSFred Richter nco1 = 0x56; 757b63b36faSFred Richter nco2 = 0x14; 758b63b36faSFred Richter break; 759b63b36faSFred Richter } 760b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0010, nco1); 761ee0133eeSMauro Carvalho Chehab if (ret) 762ee0133eeSMauro Carvalho Chehab return ret; 763b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0011, nco2); 764ee0133eeSMauro Carvalho Chehab if (ret) 765ee0133eeSMauro Carvalho Chehab return ret; 766b63b36faSFred Richter 767097117caSMauro Carvalho Chehab dbg_info("if_freq=%d KHz->[%04x]\n", if_freq_khz, nco1<<8 | nco2); 768b63b36faSFred Richter 769b63b36faSFred Richter return 0; 770b63b36faSFred Richter } 771b63b36faSFred Richter 772b63b36faSFred Richter /* ------------------------------------------------------------------------ */ 773b63b36faSFred Richter 774b63b36faSFred Richter static int lgdt3306a_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) 775b63b36faSFred Richter { 776b63b36faSFred Richter struct lgdt3306a_state *state = fe->demodulator_priv; 777b63b36faSFred Richter 778b63b36faSFred Richter if (state->cfg->deny_i2c_rptr) { 779097117caSMauro Carvalho Chehab dbg_info("deny_i2c_rptr=%d\n", state->cfg->deny_i2c_rptr); 780b63b36faSFred Richter return 0; 781b63b36faSFred Richter } 782097117caSMauro Carvalho Chehab dbg_info("(%d)\n", enable); 783b63b36faSFred Richter 784534f4364SMauro Carvalho Chehab /* NI2CRPTEN=0x80 */ 785534f4364SMauro Carvalho Chehab return lgdt3306a_set_reg_bit(state, 0x0002, 7, enable ? 0 : 1); 786b63b36faSFred Richter } 787b63b36faSFred Richter 788b63b36faSFred Richter static int lgdt3306a_sleep(struct lgdt3306a_state *state) 789b63b36faSFred Richter { 790b63b36faSFred Richter int ret; 791b63b36faSFred Richter 792097117caSMauro Carvalho Chehab dbg_info("\n"); 7938e8cd34eSMichael Ira Krufky state->current_frequency = -1; /* force re-tune, when we wake */ 794b63b36faSFred Richter 7958e8cd34eSMichael Ira Krufky ret = lgdt3306a_mpeg_tristate(state, 1); /* disable data bus */ 796b63b36faSFred Richter if (lg_chkerr(ret)) 797b63b36faSFred Richter goto fail; 798b63b36faSFred Richter 7998e8cd34eSMichael Ira Krufky ret = lgdt3306a_power(state, 0); /* power down */ 800b63b36faSFred Richter lg_chkerr(ret); 801b63b36faSFred Richter 802b63b36faSFred Richter fail: 803b63b36faSFred Richter return 0; 804b63b36faSFred Richter } 805b63b36faSFred Richter 806b63b36faSFred Richter static int lgdt3306a_fe_sleep(struct dvb_frontend *fe) 807b63b36faSFred Richter { 808b63b36faSFred Richter struct lgdt3306a_state *state = fe->demodulator_priv; 809b63b36faSFred Richter 810b63b36faSFred Richter return lgdt3306a_sleep(state); 811b63b36faSFred Richter } 812b63b36faSFred Richter 813b63b36faSFred Richter static int lgdt3306a_init(struct dvb_frontend *fe) 814b63b36faSFred Richter { 815b63b36faSFred Richter struct lgdt3306a_state *state = fe->demodulator_priv; 816722b3c14SBrad Love struct dtv_frontend_properties *c = &fe->dtv_property_cache; 817b63b36faSFred Richter u8 val; 818b63b36faSFred Richter int ret; 819b63b36faSFred Richter 820097117caSMauro Carvalho Chehab dbg_info("\n"); 821b63b36faSFred Richter 8228e8cd34eSMichael Ira Krufky /* 1. Normal operation mode */ 8238e8cd34eSMichael Ira Krufky ret = lgdt3306a_set_reg_bit(state, 0x0001, 0, 1); /* SIMFASTENB=0x01 */ 824b63b36faSFred Richter if (lg_chkerr(ret)) 825b63b36faSFred Richter goto fail; 826b63b36faSFred Richter 8278e8cd34eSMichael Ira Krufky /* 2. Spectrum inversion auto detection (Not valid for VSB) */ 828b63b36faSFred Richter ret = lgdt3306a_set_inversion_auto(state, 0); 829b63b36faSFred Richter if (lg_chkerr(ret)) 830b63b36faSFred Richter goto fail; 831b63b36faSFred Richter 8328e8cd34eSMichael Ira Krufky /* 3. Spectrum inversion(According to the tuner configuration) */ 833b63b36faSFred Richter ret = lgdt3306a_set_inversion(state, 1); 834b63b36faSFred Richter if (lg_chkerr(ret)) 835b63b36faSFred Richter goto fail; 836b63b36faSFred Richter 8378e8cd34eSMichael Ira Krufky /* 4. Peak-to-peak voltage of ADC input signal */ 838534f4364SMauro Carvalho Chehab 839534f4364SMauro Carvalho Chehab /* ADCSEL1V=0x80=1Vpp; 0x00=2Vpp */ 840534f4364SMauro Carvalho Chehab ret = lgdt3306a_set_reg_bit(state, 0x0004, 7, 1); 841b63b36faSFred Richter if (lg_chkerr(ret)) 842b63b36faSFred Richter goto fail; 843b63b36faSFred Richter 8448e8cd34eSMichael Ira Krufky /* 5. ADC output data capture clock phase */ 845534f4364SMauro Carvalho Chehab 846534f4364SMauro Carvalho Chehab /* 0=same phase as ADC clock */ 847534f4364SMauro Carvalho Chehab ret = lgdt3306a_set_reg_bit(state, 0x0004, 2, 0); 848b63b36faSFred Richter if (lg_chkerr(ret)) 849b63b36faSFred Richter goto fail; 850b63b36faSFred Richter 8518e8cd34eSMichael Ira Krufky /* 5a. ADC sampling clock source */ 852534f4364SMauro Carvalho Chehab 853534f4364SMauro Carvalho Chehab /* ADCCLKPLLSEL=0x08; 0=use ext clock, not PLL */ 854534f4364SMauro Carvalho Chehab ret = lgdt3306a_set_reg_bit(state, 0x0004, 3, 0); 855b63b36faSFred Richter if (lg_chkerr(ret)) 856b63b36faSFred Richter goto fail; 857b63b36faSFred Richter 8588e8cd34eSMichael Ira Krufky /* 6. Automatic PLL set */ 859534f4364SMauro Carvalho Chehab 860534f4364SMauro Carvalho Chehab /* PLLSETAUTO=0x40; 0=off */ 861534f4364SMauro Carvalho Chehab ret = lgdt3306a_set_reg_bit(state, 0x0005, 6, 0); 862b63b36faSFred Richter if (lg_chkerr(ret)) 863b63b36faSFred Richter goto fail; 864b63b36faSFred Richter 8658e8cd34eSMichael Ira Krufky if (state->cfg->xtalMHz == 24) { /* 24MHz */ 8668e8cd34eSMichael Ira Krufky /* 7. Frequency for PLL output(0x2564 for 192MHz for 24MHz) */ 867b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x0005, &val); 868b63b36faSFred Richter if (lg_chkerr(ret)) 869b63b36faSFred Richter goto fail; 8704937ba94SMauro Carvalho Chehab val &= 0xc0; 871b63b36faSFred Richter val |= 0x25; 872b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0005, val); 873b63b36faSFred Richter if (lg_chkerr(ret)) 874b63b36faSFred Richter goto fail; 875b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0006, 0x64); 876b63b36faSFred Richter if (lg_chkerr(ret)) 877b63b36faSFred Richter goto fail; 878b63b36faSFred Richter 8798e8cd34eSMichael Ira Krufky /* 8. ADC sampling frequency(0x180000 for 24MHz sampling) */ 8804937ba94SMauro Carvalho Chehab ret = lgdt3306a_read_reg(state, 0x000d, &val); 881b63b36faSFred Richter if (lg_chkerr(ret)) 882b63b36faSFred Richter goto fail; 8834937ba94SMauro Carvalho Chehab val &= 0xc0; 884b63b36faSFred Richter val |= 0x18; 8854937ba94SMauro Carvalho Chehab ret = lgdt3306a_write_reg(state, 0x000d, val); 886b63b36faSFred Richter if (lg_chkerr(ret)) 887b63b36faSFred Richter goto fail; 888b63b36faSFred Richter 8898e8cd34eSMichael Ira Krufky } else if (state->cfg->xtalMHz == 25) { /* 25MHz */ 8908e8cd34eSMichael Ira Krufky /* 7. Frequency for PLL output */ 891b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x0005, &val); 892b63b36faSFred Richter if (lg_chkerr(ret)) 893b63b36faSFred Richter goto fail; 8944937ba94SMauro Carvalho Chehab val &= 0xc0; 895b63b36faSFred Richter val |= 0x25; 896b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0005, val); 897b63b36faSFred Richter if (lg_chkerr(ret)) 898b63b36faSFred Richter goto fail; 899b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0006, 0x64); 900b63b36faSFred Richter if (lg_chkerr(ret)) 901b63b36faSFred Richter goto fail; 902b63b36faSFred Richter 9038e8cd34eSMichael Ira Krufky /* 8. ADC sampling frequency(0x190000 for 25MHz sampling) */ 9044937ba94SMauro Carvalho Chehab ret = lgdt3306a_read_reg(state, 0x000d, &val); 905b63b36faSFred Richter if (lg_chkerr(ret)) 906b63b36faSFred Richter goto fail; 9074937ba94SMauro Carvalho Chehab val &= 0xc0; 908b63b36faSFred Richter val |= 0x19; 9094937ba94SMauro Carvalho Chehab ret = lgdt3306a_write_reg(state, 0x000d, val); 910b63b36faSFred Richter if (lg_chkerr(ret)) 911b63b36faSFred Richter goto fail; 912b63b36faSFred Richter } else { 913097117caSMauro Carvalho Chehab pr_err("Bad xtalMHz=%d\n", state->cfg->xtalMHz); 914b63b36faSFred Richter } 9158e8cd34eSMichael Ira Krufky #if 0 9164937ba94SMauro Carvalho Chehab ret = lgdt3306a_write_reg(state, 0x000e, 0x00); 9174937ba94SMauro Carvalho Chehab ret = lgdt3306a_write_reg(state, 0x000f, 0x00); 9188e8cd34eSMichael Ira Krufky #endif 919b63b36faSFred Richter 9208e8cd34eSMichael Ira Krufky /* 9. Center frequency of input signal of ADC */ 9218e8cd34eSMichael Ira Krufky ret = lgdt3306a_write_reg(state, 0x0010, 0x34); /* 3.25MHz */ 922b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0011, 0x00); 923b63b36faSFred Richter 9248e8cd34eSMichael Ira Krufky /* 10. Fixed gain error value */ 9258e8cd34eSMichael Ira Krufky ret = lgdt3306a_write_reg(state, 0x0014, 0); /* gain error=0 */ 926b63b36faSFred Richter 9278e8cd34eSMichael Ira Krufky /* 10a. VSB TR BW gear shift initial step */ 9284937ba94SMauro Carvalho Chehab ret = lgdt3306a_read_reg(state, 0x103c, &val); 9294937ba94SMauro Carvalho Chehab val &= 0x0f; 9308e8cd34eSMichael Ira Krufky val |= 0x20; /* SAMGSAUTOSTL_V[3:0] = 2 */ 9314937ba94SMauro Carvalho Chehab ret = lgdt3306a_write_reg(state, 0x103c, val); 932b63b36faSFred Richter 9338e8cd34eSMichael Ira Krufky /* 10b. Timing offset calibration in low temperature for VSB */ 9344937ba94SMauro Carvalho Chehab ret = lgdt3306a_read_reg(state, 0x103d, &val); 9354937ba94SMauro Carvalho Chehab val &= 0xfc; 936b63b36faSFred Richter val |= 0x03; 9374937ba94SMauro Carvalho Chehab ret = lgdt3306a_write_reg(state, 0x103d, val); 938b63b36faSFred Richter 9398e8cd34eSMichael Ira Krufky /* 10c. Timing offset calibration in low temperature for QAM */ 940b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x1036, &val); 9414937ba94SMauro Carvalho Chehab val &= 0xf0; 9424937ba94SMauro Carvalho Chehab val |= 0x0c; 943b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x1036, val); 944b63b36faSFred Richter 9458e8cd34eSMichael Ira Krufky /* 11. Using the imaginary part of CIR in CIR loading */ 9464937ba94SMauro Carvalho Chehab ret = lgdt3306a_read_reg(state, 0x211f, &val); 9474937ba94SMauro Carvalho Chehab val &= 0xef; /* do not use imaginary of CIR */ 9484937ba94SMauro Carvalho Chehab ret = lgdt3306a_write_reg(state, 0x211f, val); 949b63b36faSFred Richter 9508e8cd34eSMichael Ira Krufky /* 12. Control of no signal detector function */ 951b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x2849, &val); 9524937ba94SMauro Carvalho Chehab val &= 0xef; /* NOUSENOSIGDET=0, enable no signal detector */ 953b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x2849, val); 954b63b36faSFred Richter 9558e8cd34eSMichael Ira Krufky /* FGR - put demod in some known mode */ 956b63b36faSFred Richter ret = lgdt3306a_set_vsb(state); 957b63b36faSFred Richter 9588e8cd34eSMichael Ira Krufky /* 13. TP stream format */ 959b63b36faSFred Richter ret = lgdt3306a_mpeg_mode(state, state->cfg->mpeg_mode); 960b63b36faSFred Richter 9618e8cd34eSMichael Ira Krufky /* 14. disable output buses */ 962b63b36faSFred Richter ret = lgdt3306a_mpeg_tristate(state, 1); 963b63b36faSFred Richter 9648e8cd34eSMichael Ira Krufky /* 15. Sleep (in reset) */ 965b63b36faSFred Richter ret = lgdt3306a_sleep(state); 966b63b36faSFred Richter lg_chkerr(ret); 967b63b36faSFred Richter 968722b3c14SBrad Love c->cnr.len = 1; 969722b3c14SBrad Love c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 970722b3c14SBrad Love 971b63b36faSFred Richter fail: 972b63b36faSFred Richter return ret; 973b63b36faSFred Richter } 974b63b36faSFred Richter 975b63b36faSFred Richter static int lgdt3306a_set_parameters(struct dvb_frontend *fe) 976b63b36faSFred Richter { 977b63b36faSFred Richter struct dtv_frontend_properties *p = &fe->dtv_property_cache; 978b63b36faSFred Richter struct lgdt3306a_state *state = fe->demodulator_priv; 979b63b36faSFred Richter int ret; 980b63b36faSFred Richter 981097117caSMauro Carvalho Chehab dbg_info("(%d, %d)\n", p->frequency, p->modulation); 982b63b36faSFred Richter 983b63b36faSFred Richter if (state->current_frequency == p->frequency && 984b63b36faSFred Richter state->current_modulation == p->modulation) { 985097117caSMauro Carvalho Chehab dbg_info(" (already set, skipping ...)\n"); 986b63b36faSFred Richter return 0; 987b63b36faSFred Richter } 988b63b36faSFred Richter state->current_frequency = -1; 989b63b36faSFred Richter state->current_modulation = -1; 990b63b36faSFred Richter 9918e8cd34eSMichael Ira Krufky ret = lgdt3306a_power(state, 1); /* power up */ 992b63b36faSFred Richter if (lg_chkerr(ret)) 993b63b36faSFred Richter goto fail; 994b63b36faSFred Richter 995b63b36faSFred Richter if (fe->ops.tuner_ops.set_params) { 996b63b36faSFred Richter ret = fe->ops.tuner_ops.set_params(fe); 997b63b36faSFred Richter if (fe->ops.i2c_gate_ctrl) 998b63b36faSFred Richter fe->ops.i2c_gate_ctrl(fe, 0); 9998e8cd34eSMichael Ira Krufky #if 0 10008e8cd34eSMichael Ira Krufky if (lg_chkerr(ret)) 10018e8cd34eSMichael Ira Krufky goto fail; 10028e8cd34eSMichael Ira Krufky state->current_frequency = p->frequency; 10038e8cd34eSMichael Ira Krufky #endif 1004b63b36faSFred Richter } 1005b63b36faSFred Richter 1006b63b36faSFred Richter ret = lgdt3306a_set_modulation(state, p); 1007b63b36faSFred Richter if (lg_chkerr(ret)) 1008b63b36faSFred Richter goto fail; 1009b63b36faSFred Richter 1010b63b36faSFred Richter ret = lgdt3306a_agc_setup(state, p); 1011b63b36faSFred Richter if (lg_chkerr(ret)) 1012b63b36faSFred Richter goto fail; 1013b63b36faSFred Richter 1014b63b36faSFred Richter ret = lgdt3306a_set_if(state, p); 1015b63b36faSFred Richter if (lg_chkerr(ret)) 1016b63b36faSFred Richter goto fail; 1017b63b36faSFred Richter 1018*d4a3fa66SDaniel W. S. Almeida /* spectral_inversion defaults already set for VSB and QAM */ 1019*d4a3fa66SDaniel W. S. Almeida 1020b63b36faSFred Richter if (lg_chkerr(ret)) 1021b63b36faSFred Richter goto fail; 1022b63b36faSFred Richter 1023b63b36faSFred Richter ret = lgdt3306a_mpeg_mode(state, state->cfg->mpeg_mode); 1024b63b36faSFred Richter if (lg_chkerr(ret)) 1025b63b36faSFred Richter goto fail; 1026b63b36faSFred Richter 1027b63b36faSFred Richter ret = lgdt3306a_mpeg_mode_polarity(state, 1028b63b36faSFred Richter state->cfg->tpclk_edge, 1029b63b36faSFred Richter state->cfg->tpvalid_polarity); 1030b63b36faSFred Richter if (lg_chkerr(ret)) 1031b63b36faSFred Richter goto fail; 1032b63b36faSFred Richter 10338e8cd34eSMichael Ira Krufky ret = lgdt3306a_mpeg_tristate(state, 0); /* enable data bus */ 1034b63b36faSFred Richter if (lg_chkerr(ret)) 1035b63b36faSFred Richter goto fail; 1036b63b36faSFred Richter 1037b63b36faSFred Richter ret = lgdt3306a_soft_reset(state); 1038b63b36faSFred Richter if (lg_chkerr(ret)) 1039b63b36faSFred Richter goto fail; 1040b63b36faSFred Richter 1041b63b36faSFred Richter #ifdef DBG_DUMP 1042b63b36faSFred Richter lgdt3306a_DumpAllRegs(state); 1043b63b36faSFred Richter #endif 1044b63b36faSFred Richter state->current_frequency = p->frequency; 1045b63b36faSFred Richter fail: 1046b63b36faSFred Richter return ret; 1047b63b36faSFred Richter } 1048b63b36faSFred Richter 10497e3e68bcSMauro Carvalho Chehab static int lgdt3306a_get_frontend(struct dvb_frontend *fe, 10507e3e68bcSMauro Carvalho Chehab struct dtv_frontend_properties *p) 1051b63b36faSFred Richter { 1052b63b36faSFred Richter struct lgdt3306a_state *state = fe->demodulator_priv; 1053b63b36faSFred Richter 1054534f4364SMauro Carvalho Chehab dbg_info("(%u, %d)\n", 1055534f4364SMauro Carvalho Chehab state->current_frequency, state->current_modulation); 1056b63b36faSFred Richter 1057b63b36faSFred Richter p->modulation = state->current_modulation; 1058b63b36faSFred Richter p->frequency = state->current_frequency; 1059b63b36faSFred Richter return 0; 1060b63b36faSFred Richter } 1061b63b36faSFred Richter 1062b63b36faSFred Richter static enum dvbfe_algo lgdt3306a_get_frontend_algo(struct dvb_frontend *fe) 1063b63b36faSFred Richter { 1064b63b36faSFred Richter #if 1 1065b63b36faSFred Richter return DVBFE_ALGO_CUSTOM; 1066b63b36faSFred Richter #else 1067b63b36faSFred Richter return DVBFE_ALGO_HW; 1068b63b36faSFred Richter #endif 1069b63b36faSFred Richter } 1070b63b36faSFred Richter 1071b63b36faSFred Richter /* ------------------------------------------------------------------------ */ 1072ee0133eeSMauro Carvalho Chehab static int lgdt3306a_monitor_vsb(struct lgdt3306a_state *state) 1073b63b36faSFred Richter { 1074b63b36faSFred Richter u8 val; 1075b63b36faSFred Richter int ret; 1076b63b36faSFred Richter u8 snrRef, maxPowerMan, nCombDet; 1077b63b36faSFred Richter u16 fbDlyCir; 1078b63b36faSFred Richter 10794937ba94SMauro Carvalho Chehab ret = lgdt3306a_read_reg(state, 0x21a1, &val); 1080ee0133eeSMauro Carvalho Chehab if (ret) 1081ee0133eeSMauro Carvalho Chehab return ret; 10824937ba94SMauro Carvalho Chehab snrRef = val & 0x3f; 1083b63b36faSFred Richter 1084b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x2185, &maxPowerMan); 1085ee0133eeSMauro Carvalho Chehab if (ret) 1086ee0133eeSMauro Carvalho Chehab return ret; 1087b63b36faSFred Richter 1088b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x2191, &val); 1089ee0133eeSMauro Carvalho Chehab if (ret) 1090ee0133eeSMauro Carvalho Chehab return ret; 1091b63b36faSFred Richter nCombDet = (val & 0x80) >> 7; 1092b63b36faSFred Richter 1093b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x2180, &val); 1094ee0133eeSMauro Carvalho Chehab if (ret) 1095ee0133eeSMauro Carvalho Chehab return ret; 1096b63b36faSFred Richter fbDlyCir = (val & 0x03) << 8; 1097ee0133eeSMauro Carvalho Chehab 1098b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x2181, &val); 1099ee0133eeSMauro Carvalho Chehab if (ret) 1100ee0133eeSMauro Carvalho Chehab return ret; 1101b63b36faSFred Richter fbDlyCir |= val; 1102b63b36faSFred Richter 1103097117caSMauro Carvalho Chehab dbg_info("snrRef=%d maxPowerMan=0x%x nCombDet=%d fbDlyCir=0x%x\n", 1104b63b36faSFred Richter snrRef, maxPowerMan, nCombDet, fbDlyCir); 1105b63b36faSFred Richter 11068e8cd34eSMichael Ira Krufky /* Carrier offset sub loop bandwidth */ 1107b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x1061, &val); 1108ee0133eeSMauro Carvalho Chehab if (ret) 1109ee0133eeSMauro Carvalho Chehab return ret; 11104937ba94SMauro Carvalho Chehab val &= 0xf8; 1111534f4364SMauro Carvalho Chehab if ((snrRef > 18) && (maxPowerMan > 0x68) 1112534f4364SMauro Carvalho Chehab && (nCombDet == 0x01) 1113534f4364SMauro Carvalho Chehab && ((fbDlyCir == 0x03FF) || (fbDlyCir < 0x6C))) { 11148e8cd34eSMichael Ira Krufky /* SNR is over 18dB and no ghosting */ 11158e8cd34eSMichael Ira Krufky val |= 0x00; /* final bandwidth = 0 */ 1116b63b36faSFred Richter } else { 11178e8cd34eSMichael Ira Krufky val |= 0x04; /* final bandwidth = 4 */ 1118b63b36faSFred Richter } 1119b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x1061, val); 1120ee0133eeSMauro Carvalho Chehab if (ret) 1121ee0133eeSMauro Carvalho Chehab return ret; 1122b63b36faSFred Richter 11238e8cd34eSMichael Ira Krufky /* Adjust Notch Filter */ 1124b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x0024, &val); 1125ee0133eeSMauro Carvalho Chehab if (ret) 1126ee0133eeSMauro Carvalho Chehab return ret; 11274937ba94SMauro Carvalho Chehab val &= 0x0f; 11288e8cd34eSMichael Ira Krufky if (nCombDet == 0) { /* Turn on the Notch Filter */ 1129b63b36faSFred Richter val |= 0x50; 1130b63b36faSFred Richter } 1131b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0024, val); 1132ee0133eeSMauro Carvalho Chehab if (ret) 1133ee0133eeSMauro Carvalho Chehab return ret; 1134b63b36faSFred Richter 11358e8cd34eSMichael Ira Krufky /* VSB Timing Recovery output normalization */ 11364937ba94SMauro Carvalho Chehab ret = lgdt3306a_read_reg(state, 0x103d, &val); 1137ee0133eeSMauro Carvalho Chehab if (ret) 1138ee0133eeSMauro Carvalho Chehab return ret; 11394937ba94SMauro Carvalho Chehab val &= 0xcf; 1140b63b36faSFred Richter val |= 0x20; 11414937ba94SMauro Carvalho Chehab ret = lgdt3306a_write_reg(state, 0x103d, val); 1142ee0133eeSMauro Carvalho Chehab 1143ee0133eeSMauro Carvalho Chehab return ret; 1144b63b36faSFred Richter } 1145b63b36faSFred Richter 1146534f4364SMauro Carvalho Chehab static enum lgdt3306a_modulation 1147534f4364SMauro Carvalho Chehab lgdt3306a_check_oper_mode(struct lgdt3306a_state *state) 1148b63b36faSFred Richter { 1149b63b36faSFred Richter u8 val = 0; 1150b63b36faSFred Richter int ret; 1151b63b36faSFred Richter 1152b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x0081, &val); 1153ee0133eeSMauro Carvalho Chehab if (ret) 1154ee0133eeSMauro Carvalho Chehab goto err; 1155b63b36faSFred Richter 1156b63b36faSFred Richter if (val & 0x80) { 1157097117caSMauro Carvalho Chehab dbg_info("VSB\n"); 11588e8cd34eSMichael Ira Krufky return LG3306_VSB; 1159b63b36faSFred Richter } 1160c714efe4SMichael Ira Krufky if (val & 0x08) { 11614937ba94SMauro Carvalho Chehab ret = lgdt3306a_read_reg(state, 0x00a6, &val); 1162ee0133eeSMauro Carvalho Chehab if (ret) 1163ee0133eeSMauro Carvalho Chehab goto err; 1164b63b36faSFred Richter val = val >> 2; 1165b63b36faSFred Richter if (val & 0x01) { 1166097117caSMauro Carvalho Chehab dbg_info("QAM256\n"); 11678e8cd34eSMichael Ira Krufky return LG3306_QAM256; 1168b4e43e95SMauro Carvalho Chehab } 1169097117caSMauro Carvalho Chehab dbg_info("QAM64\n"); 11708e8cd34eSMichael Ira Krufky return LG3306_QAM64; 1171b63b36faSFred Richter } 1172ee0133eeSMauro Carvalho Chehab err: 1173097117caSMauro Carvalho Chehab pr_warn("UNKNOWN\n"); 11748e8cd34eSMichael Ira Krufky return LG3306_UNKNOWN_MODE; 1175b63b36faSFred Richter } 1176b63b36faSFred Richter 1177534f4364SMauro Carvalho Chehab static enum lgdt3306a_lock_status 1178534f4364SMauro Carvalho Chehab lgdt3306a_check_lock_status(struct lgdt3306a_state *state, 1179f883d603SMichael Ira Krufky enum lgdt3306a_lock_check whatLock) 1180b63b36faSFred Richter { 1181b63b36faSFred Richter u8 val = 0; 1182b63b36faSFred Richter int ret; 1183f883d603SMichael Ira Krufky enum lgdt3306a_modulation modeOper; 1184f883d603SMichael Ira Krufky enum lgdt3306a_lock_status lockStatus; 1185b63b36faSFred Richter 1186b63b36faSFred Richter modeOper = LG3306_UNKNOWN_MODE; 1187b63b36faSFred Richter 11888e8cd34eSMichael Ira Krufky switch (whatLock) { 1189b63b36faSFred Richter case LG3306_SYNC_LOCK: 1190b63b36faSFred Richter { 11914937ba94SMauro Carvalho Chehab ret = lgdt3306a_read_reg(state, 0x00a6, &val); 1192ee0133eeSMauro Carvalho Chehab if (ret) 1193ee0133eeSMauro Carvalho Chehab return ret; 1194b63b36faSFred Richter 1195b63b36faSFred Richter if ((val & 0x80) == 0x80) 1196b63b36faSFred Richter lockStatus = LG3306_LOCK; 1197b63b36faSFred Richter else 1198b63b36faSFred Richter lockStatus = LG3306_UNLOCK; 1199b63b36faSFred Richter 1200097117caSMauro Carvalho Chehab dbg_info("SYNC_LOCK=%x\n", lockStatus); 1201b63b36faSFred Richter break; 1202b63b36faSFred Richter } 1203b63b36faSFred Richter case LG3306_AGC_LOCK: 1204b63b36faSFred Richter { 1205b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x0080, &val); 1206ee0133eeSMauro Carvalho Chehab if (ret) 1207ee0133eeSMauro Carvalho Chehab return ret; 1208b63b36faSFred Richter 1209b63b36faSFred Richter if ((val & 0x40) == 0x40) 1210b63b36faSFred Richter lockStatus = LG3306_LOCK; 1211b63b36faSFred Richter else 1212b63b36faSFred Richter lockStatus = LG3306_UNLOCK; 1213b63b36faSFred Richter 1214097117caSMauro Carvalho Chehab dbg_info("AGC_LOCK=%x\n", lockStatus); 1215b63b36faSFred Richter break; 1216b63b36faSFred Richter } 1217b63b36faSFred Richter case LG3306_TR_LOCK: 1218b63b36faSFred Richter { 1219b63b36faSFred Richter modeOper = lgdt3306a_check_oper_mode(state); 12208e8cd34eSMichael Ira Krufky if ((modeOper == LG3306_QAM64) || (modeOper == LG3306_QAM256)) { 1221b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x1094, &val); 1222ee0133eeSMauro Carvalho Chehab if (ret) 1223ee0133eeSMauro Carvalho Chehab return ret; 1224b63b36faSFred Richter 1225b63b36faSFred Richter if ((val & 0x80) == 0x80) 1226b63b36faSFred Richter lockStatus = LG3306_LOCK; 1227b63b36faSFred Richter else 1228b63b36faSFred Richter lockStatus = LG3306_UNLOCK; 12298e8cd34eSMichael Ira Krufky } else 1230b63b36faSFred Richter lockStatus = LG3306_UNKNOWN_LOCK; 1231b63b36faSFred Richter 1232097117caSMauro Carvalho Chehab dbg_info("TR_LOCK=%x\n", lockStatus); 1233b63b36faSFred Richter break; 1234b63b36faSFred Richter } 1235b63b36faSFred Richter case LG3306_FEC_LOCK: 1236b63b36faSFred Richter { 1237b63b36faSFred Richter modeOper = lgdt3306a_check_oper_mode(state); 12388e8cd34eSMichael Ira Krufky if ((modeOper == LG3306_QAM64) || (modeOper == LG3306_QAM256)) { 1239b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x0080, &val); 1240ee0133eeSMauro Carvalho Chehab if (ret) 1241ee0133eeSMauro Carvalho Chehab return ret; 1242b63b36faSFred Richter 1243b63b36faSFred Richter if ((val & 0x10) == 0x10) 1244b63b36faSFred Richter lockStatus = LG3306_LOCK; 1245b63b36faSFred Richter else 1246b63b36faSFred Richter lockStatus = LG3306_UNLOCK; 12478e8cd34eSMichael Ira Krufky } else 1248b63b36faSFred Richter lockStatus = LG3306_UNKNOWN_LOCK; 1249b63b36faSFred Richter 1250097117caSMauro Carvalho Chehab dbg_info("FEC_LOCK=%x\n", lockStatus); 1251b63b36faSFred Richter break; 1252b63b36faSFred Richter } 1253b63b36faSFred Richter 1254b63b36faSFred Richter default: 1255b63b36faSFred Richter lockStatus = LG3306_UNKNOWN_LOCK; 1256097117caSMauro Carvalho Chehab pr_warn("UNKNOWN whatLock=%d\n", whatLock); 1257b63b36faSFred Richter break; 1258b63b36faSFred Richter } 1259b63b36faSFred Richter 12608e8cd34eSMichael Ira Krufky return lockStatus; 1261b63b36faSFred Richter } 1262b63b36faSFred Richter 1263534f4364SMauro Carvalho Chehab static enum lgdt3306a_neverlock_status 1264534f4364SMauro Carvalho Chehab lgdt3306a_check_neverlock_status(struct lgdt3306a_state *state) 1265b63b36faSFred Richter { 1266b63b36faSFred Richter u8 val = 0; 1267b63b36faSFred Richter int ret; 1268f883d603SMichael Ira Krufky enum lgdt3306a_neverlock_status lockStatus; 1269b63b36faSFred Richter 1270b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x0080, &val); 1271ee0133eeSMauro Carvalho Chehab if (ret) 1272ee0133eeSMauro Carvalho Chehab return ret; 1273f883d603SMichael Ira Krufky lockStatus = (enum lgdt3306a_neverlock_status)(val & 0x03); 1274b63b36faSFred Richter 1275097117caSMauro Carvalho Chehab dbg_info("NeverLock=%d", lockStatus); 1276b63b36faSFred Richter 12778e8cd34eSMichael Ira Krufky return lockStatus; 1278b63b36faSFred Richter } 1279b63b36faSFred Richter 1280ee0133eeSMauro Carvalho Chehab static int lgdt3306a_pre_monitoring(struct lgdt3306a_state *state) 1281b63b36faSFred Richter { 1282b63b36faSFred Richter u8 val = 0; 1283b63b36faSFred Richter int ret; 1284b63b36faSFred Richter u8 currChDiffACQ, snrRef, mainStrong, aiccrejStatus; 1285b63b36faSFred Richter 12868e8cd34eSMichael Ira Krufky /* Channel variation */ 12874937ba94SMauro Carvalho Chehab ret = lgdt3306a_read_reg(state, 0x21bc, &currChDiffACQ); 1288ee0133eeSMauro Carvalho Chehab if (ret) 1289ee0133eeSMauro Carvalho Chehab return ret; 1290b63b36faSFred Richter 12918e8cd34eSMichael Ira Krufky /* SNR of Frame sync */ 12924937ba94SMauro Carvalho Chehab ret = lgdt3306a_read_reg(state, 0x21a1, &val); 1293ee0133eeSMauro Carvalho Chehab if (ret) 1294ee0133eeSMauro Carvalho Chehab return ret; 12954937ba94SMauro Carvalho Chehab snrRef = val & 0x3f; 1296b63b36faSFred Richter 12978e8cd34eSMichael Ira Krufky /* Strong Main CIR */ 1298b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x2199, &val); 1299ee0133eeSMauro Carvalho Chehab if (ret) 1300ee0133eeSMauro Carvalho Chehab return ret; 1301b63b36faSFred Richter mainStrong = (val & 0x40) >> 6; 1302b63b36faSFred Richter 1303b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x0090, &val); 1304ee0133eeSMauro Carvalho Chehab if (ret) 1305ee0133eeSMauro Carvalho Chehab return ret; 13064937ba94SMauro Carvalho Chehab aiccrejStatus = (val & 0xf0) >> 4; 1307b63b36faSFred Richter 1308097117caSMauro Carvalho Chehab dbg_info("snrRef=%d mainStrong=%d aiccrejStatus=%d currChDiffACQ=0x%x\n", 1309b63b36faSFred Richter snrRef, mainStrong, aiccrejStatus, currChDiffACQ); 1310b63b36faSFred Richter 13118e8cd34eSMichael Ira Krufky #if 0 1312534f4364SMauro Carvalho Chehab /* Dynamic ghost exists */ 1313534f4364SMauro Carvalho Chehab if ((mainStrong == 0) && (currChDiffACQ > 0x70)) 13148e8cd34eSMichael Ira Krufky #endif 13158e8cd34eSMichael Ira Krufky if (mainStrong == 0) { 1316b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x2135, &val); 1317ee0133eeSMauro Carvalho Chehab if (ret) 1318ee0133eeSMauro Carvalho Chehab return ret; 13194937ba94SMauro Carvalho Chehab val &= 0x0f; 13204937ba94SMauro Carvalho Chehab val |= 0xa0; 1321b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x2135, val); 1322ee0133eeSMauro Carvalho Chehab if (ret) 1323ee0133eeSMauro Carvalho Chehab return ret; 1324b63b36faSFred Richter 1325b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x2141, &val); 1326ee0133eeSMauro Carvalho Chehab if (ret) 1327ee0133eeSMauro Carvalho Chehab return ret; 13284937ba94SMauro Carvalho Chehab val &= 0x3f; 1329b63b36faSFred Richter val |= 0x80; 1330b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x2141, val); 1331ee0133eeSMauro Carvalho Chehab if (ret) 1332ee0133eeSMauro Carvalho Chehab return ret; 1333b63b36faSFred Richter 1334b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x2122, 0x70); 1335ee0133eeSMauro Carvalho Chehab if (ret) 1336ee0133eeSMauro Carvalho Chehab return ret; 13378e8cd34eSMichael Ira Krufky } else { /* Weak ghost or static channel */ 1338b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x2135, &val); 1339ee0133eeSMauro Carvalho Chehab if (ret) 1340ee0133eeSMauro Carvalho Chehab return ret; 13414937ba94SMauro Carvalho Chehab val &= 0x0f; 1342b63b36faSFred Richter val |= 0x70; 1343b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x2135, val); 1344ee0133eeSMauro Carvalho Chehab if (ret) 1345ee0133eeSMauro Carvalho Chehab return ret; 1346b63b36faSFred Richter 1347b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x2141, &val); 1348ee0133eeSMauro Carvalho Chehab if (ret) 1349ee0133eeSMauro Carvalho Chehab return ret; 13504937ba94SMauro Carvalho Chehab val &= 0x3f; 1351b63b36faSFred Richter val |= 0x40; 1352b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x2141, val); 1353ee0133eeSMauro Carvalho Chehab if (ret) 1354ee0133eeSMauro Carvalho Chehab return ret; 1355b63b36faSFred Richter 1356b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x2122, 0x40); 1357ee0133eeSMauro Carvalho Chehab if (ret) 1358ee0133eeSMauro Carvalho Chehab return ret; 1359b63b36faSFred Richter } 1360ee0133eeSMauro Carvalho Chehab return 0; 1361b63b36faSFred Richter } 1362b63b36faSFred Richter 1363534f4364SMauro Carvalho Chehab static enum lgdt3306a_lock_status 1364534f4364SMauro Carvalho Chehab lgdt3306a_sync_lock_poll(struct lgdt3306a_state *state) 1365b63b36faSFred Richter { 1366f883d603SMichael Ira Krufky enum lgdt3306a_lock_status syncLockStatus = LG3306_UNLOCK; 1367b63b36faSFred Richter int i; 1368b63b36faSFred Richter 1369b63b36faSFred Richter for (i = 0; i < 2; i++) { 1370b63b36faSFred Richter msleep(30); 1371b63b36faSFred Richter 1372534f4364SMauro Carvalho Chehab syncLockStatus = lgdt3306a_check_lock_status(state, 1373534f4364SMauro Carvalho Chehab LG3306_SYNC_LOCK); 1374b63b36faSFred Richter 1375b63b36faSFred Richter if (syncLockStatus == LG3306_LOCK) { 1376097117caSMauro Carvalho Chehab dbg_info("locked(%d)\n", i); 13778e8cd34eSMichael Ira Krufky return LG3306_LOCK; 1378b63b36faSFred Richter } 1379b63b36faSFred Richter } 1380097117caSMauro Carvalho Chehab dbg_info("not locked\n"); 13818e8cd34eSMichael Ira Krufky return LG3306_UNLOCK; 1382b63b36faSFred Richter } 1383b63b36faSFred Richter 1384534f4364SMauro Carvalho Chehab static enum lgdt3306a_lock_status 1385534f4364SMauro Carvalho Chehab lgdt3306a_fec_lock_poll(struct lgdt3306a_state *state) 1386b63b36faSFred Richter { 1387f883d603SMichael Ira Krufky enum lgdt3306a_lock_status FECLockStatus = LG3306_UNLOCK; 1388b63b36faSFred Richter int i; 1389b63b36faSFred Richter 1390b63b36faSFred Richter for (i = 0; i < 2; i++) { 1391b63b36faSFred Richter msleep(30); 1392b63b36faSFred Richter 1393534f4364SMauro Carvalho Chehab FECLockStatus = lgdt3306a_check_lock_status(state, 1394534f4364SMauro Carvalho Chehab LG3306_FEC_LOCK); 1395b63b36faSFred Richter 1396b63b36faSFred Richter if (FECLockStatus == LG3306_LOCK) { 1397097117caSMauro Carvalho Chehab dbg_info("locked(%d)\n", i); 13988e8cd34eSMichael Ira Krufky return FECLockStatus; 1399b63b36faSFred Richter } 1400b63b36faSFred Richter } 1401097117caSMauro Carvalho Chehab dbg_info("not locked\n"); 14028e8cd34eSMichael Ira Krufky return FECLockStatus; 1403b63b36faSFred Richter } 1404b63b36faSFred Richter 1405534f4364SMauro Carvalho Chehab static enum lgdt3306a_neverlock_status 1406534f4364SMauro Carvalho Chehab lgdt3306a_neverlock_poll(struct lgdt3306a_state *state) 1407b63b36faSFred Richter { 1408f883d603SMichael Ira Krufky enum lgdt3306a_neverlock_status NLLockStatus = LG3306_NL_FAIL; 1409b63b36faSFred Richter int i; 1410b63b36faSFred Richter 1411b63b36faSFred Richter for (i = 0; i < 5; i++) { 1412b63b36faSFred Richter msleep(30); 1413b63b36faSFred Richter 1414b63b36faSFred Richter NLLockStatus = lgdt3306a_check_neverlock_status(state); 1415b63b36faSFred Richter 1416b63b36faSFred Richter if (NLLockStatus == LG3306_NL_LOCK) { 1417097117caSMauro Carvalho Chehab dbg_info("NL_LOCK(%d)\n", i); 14188e8cd34eSMichael Ira Krufky return NLLockStatus; 1419b63b36faSFred Richter } 1420b63b36faSFred Richter } 1421097117caSMauro Carvalho Chehab dbg_info("NLLockStatus=%d\n", NLLockStatus); 14228e8cd34eSMichael Ira Krufky return NLLockStatus; 1423b63b36faSFred Richter } 1424b63b36faSFred Richter 1425b63b36faSFred Richter static u8 lgdt3306a_get_packet_error(struct lgdt3306a_state *state) 1426b63b36faSFred Richter { 1427b63b36faSFred Richter u8 val; 1428b63b36faSFred Richter int ret; 1429b63b36faSFred Richter 14304937ba94SMauro Carvalho Chehab ret = lgdt3306a_read_reg(state, 0x00fa, &val); 1431ee0133eeSMauro Carvalho Chehab if (ret) 1432ee0133eeSMauro Carvalho Chehab return ret; 1433b63b36faSFred Richter 14348e8cd34eSMichael Ira Krufky return val; 1435b63b36faSFred Richter } 1436b63b36faSFred Richter 14379369fe01SMauro Carvalho Chehab static const u32 valx_x10[] = { 14389369fe01SMauro Carvalho Chehab 10, 11, 13, 15, 17, 20, 25, 33, 41, 50, 59, 73, 87, 100 14399369fe01SMauro Carvalho Chehab }; 14409369fe01SMauro Carvalho Chehab static const u32 log10x_x1000[] = { 14419369fe01SMauro Carvalho Chehab 0, 41, 114, 176, 230, 301, 398, 518, 613, 699, 771, 863, 939, 1000 14429369fe01SMauro Carvalho Chehab }; 14439369fe01SMauro Carvalho Chehab 1444b63b36faSFred Richter static u32 log10_x1000(u32 x) 1445b63b36faSFred Richter { 1446a132fef8SMauro Carvalho Chehab u32 diff_val, step_val, step_log10; 1447b63b36faSFred Richter u32 log_val = 0; 1448b63b36faSFred Richter u32 i; 1449b63b36faSFred Richter 1450b63b36faSFred Richter if (x <= 0) 14518e8cd34eSMichael Ira Krufky return -1000000; /* signal error */ 1452b63b36faSFred Richter 1453b4e43e95SMauro Carvalho Chehab if (x == 10) 1454b4e43e95SMauro Carvalho Chehab return 0; /* log(1)=0 */ 1455b4e43e95SMauro Carvalho Chehab 1456b63b36faSFred Richter if (x < 10) { 1457b63b36faSFred Richter while (x < 10) { 1458b63b36faSFred Richter x = x * 10; 1459b63b36faSFred Richter log_val--; 1460b63b36faSFred Richter } 1461b4e43e95SMauro Carvalho Chehab } else { /* x > 10 */ 1462b63b36faSFred Richter while (x >= 100) { 1463b63b36faSFred Richter x = x / 10; 1464b63b36faSFred Richter log_val++; 1465b63b36faSFred Richter } 1466b63b36faSFred Richter } 1467b63b36faSFred Richter log_val *= 1000; 1468b63b36faSFred Richter 14698e8cd34eSMichael Ira Krufky if (x == 10) /* was our input an exact multiple of 10 */ 14708e8cd34eSMichael Ira Krufky return log_val; /* don't need to interpolate */ 1471b63b36faSFred Richter 14728e8cd34eSMichael Ira Krufky /* find our place on the log curve */ 14739369fe01SMauro Carvalho Chehab for (i = 1; i < ARRAY_SIZE(valx_x10); i++) { 14748e8cd34eSMichael Ira Krufky if (valx_x10[i] >= x) 14758e8cd34eSMichael Ira Krufky break; 1476b63b36faSFred Richter } 14779369fe01SMauro Carvalho Chehab if (i == ARRAY_SIZE(valx_x10)) 1478a132fef8SMauro Carvalho Chehab return log_val + log10x_x1000[i - 1]; 1479b63b36faSFred Richter 1480a132fef8SMauro Carvalho Chehab diff_val = x - valx_x10[i-1]; 1481a132fef8SMauro Carvalho Chehab step_val = valx_x10[i] - valx_x10[i - 1]; 1482a132fef8SMauro Carvalho Chehab step_log10 = log10x_x1000[i] - log10x_x1000[i - 1]; 1483a132fef8SMauro Carvalho Chehab 14848e8cd34eSMichael Ira Krufky /* do a linear interpolation to get in-between values */ 14858e8cd34eSMichael Ira Krufky return log_val + log10x_x1000[i - 1] + 14868e8cd34eSMichael Ira Krufky ((diff_val*step_log10) / step_val); 1487b63b36faSFred Richter } 1488b63b36faSFred Richter 1489b63b36faSFred Richter static u32 lgdt3306a_calculate_snr_x100(struct lgdt3306a_state *state) 1490b63b36faSFred Richter { 1491b63b36faSFred Richter u32 mse; /* Mean-Square Error */ 1492b63b36faSFred Richter u32 pwr; /* Constelation power */ 1493b63b36faSFred Richter u32 snr_x100; 1494b63b36faSFred Richter 14954937ba94SMauro Carvalho Chehab mse = (read_reg(state, 0x00ec) << 8) | 14964937ba94SMauro Carvalho Chehab (read_reg(state, 0x00ed)); 14974937ba94SMauro Carvalho Chehab pwr = (read_reg(state, 0x00e8) << 8) | 14984937ba94SMauro Carvalho Chehab (read_reg(state, 0x00e9)); 1499b63b36faSFred Richter 1500b63b36faSFred Richter if (mse == 0) /* no signal */ 1501b63b36faSFred Richter return 0; 1502b63b36faSFred Richter 1503b63b36faSFred Richter snr_x100 = log10_x1000((pwr * 10000) / mse) - 3000; 1504097117caSMauro Carvalho Chehab dbg_info("mse=%u, pwr=%u, snr_x100=%d\n", mse, pwr, snr_x100); 1505b63b36faSFred Richter 1506b63b36faSFred Richter return snr_x100; 1507b63b36faSFred Richter } 1508b63b36faSFred Richter 1509534f4364SMauro Carvalho Chehab static enum lgdt3306a_lock_status 1510534f4364SMauro Carvalho Chehab lgdt3306a_vsb_lock_poll(struct lgdt3306a_state *state) 1511b63b36faSFred Richter { 1512e2c47fa7SMauro Carvalho Chehab int ret; 1513b63b36faSFred Richter u8 cnt = 0; 1514b63b36faSFred Richter u8 packet_error; 1515b63b36faSFred Richter u32 snr; 1516b63b36faSFred Richter 1517b1a88c71SMauro Carvalho Chehab for (cnt = 0; cnt < 10; cnt++) { 1518b63b36faSFred Richter if (lgdt3306a_sync_lock_poll(state) == LG3306_UNLOCK) { 1519097117caSMauro Carvalho Chehab dbg_info("no sync lock!\n"); 15208e8cd34eSMichael Ira Krufky return LG3306_UNLOCK; 1521b1a88c71SMauro Carvalho Chehab } 1522b1a88c71SMauro Carvalho Chehab 1523b63b36faSFred Richter msleep(20); 1524ee0133eeSMauro Carvalho Chehab ret = lgdt3306a_pre_monitoring(state); 1525ee0133eeSMauro Carvalho Chehab if (ret) 1526b1a88c71SMauro Carvalho Chehab break; 1527b63b36faSFred Richter 1528b63b36faSFred Richter packet_error = lgdt3306a_get_packet_error(state); 1529b63b36faSFred Richter snr = lgdt3306a_calculate_snr_x100(state); 1530b1a88c71SMauro Carvalho Chehab dbg_info("cnt=%d errors=%d snr=%d\n", cnt, packet_error, snr); 1531b63b36faSFred Richter 1532b1a88c71SMauro Carvalho Chehab if ((snr >= 1500) && (packet_error < 0xff)) 15338e8cd34eSMichael Ira Krufky return LG3306_LOCK; 1534b1a88c71SMauro Carvalho Chehab } 1535b63b36faSFred Richter 1536097117caSMauro Carvalho Chehab dbg_info("not locked!\n"); 15378e8cd34eSMichael Ira Krufky return LG3306_UNLOCK; 1538b63b36faSFred Richter } 1539b63b36faSFred Richter 1540534f4364SMauro Carvalho Chehab static enum lgdt3306a_lock_status 1541534f4364SMauro Carvalho Chehab lgdt3306a_qam_lock_poll(struct lgdt3306a_state *state) 1542b63b36faSFred Richter { 1543b1a88c71SMauro Carvalho Chehab u8 cnt; 1544b63b36faSFred Richter u8 packet_error; 1545b63b36faSFred Richter u32 snr; 1546b63b36faSFred Richter 1547b1a88c71SMauro Carvalho Chehab for (cnt = 0; cnt < 10; cnt++) { 1548b63b36faSFred Richter if (lgdt3306a_fec_lock_poll(state) == LG3306_UNLOCK) { 1549097117caSMauro Carvalho Chehab dbg_info("no fec lock!\n"); 15508e8cd34eSMichael Ira Krufky return LG3306_UNLOCK; 1551b1a88c71SMauro Carvalho Chehab } 1552b1a88c71SMauro Carvalho Chehab 1553b63b36faSFred Richter msleep(20); 1554b63b36faSFred Richter 1555b63b36faSFred Richter packet_error = lgdt3306a_get_packet_error(state); 1556b63b36faSFred Richter snr = lgdt3306a_calculate_snr_x100(state); 1557b1a88c71SMauro Carvalho Chehab dbg_info("cnt=%d errors=%d snr=%d\n", cnt, packet_error, snr); 1558b63b36faSFred Richter 1559b1a88c71SMauro Carvalho Chehab if ((snr >= 1500) && (packet_error < 0xff)) 15608e8cd34eSMichael Ira Krufky return LG3306_LOCK; 1561b1a88c71SMauro Carvalho Chehab } 1562b63b36faSFred Richter 1563097117caSMauro Carvalho Chehab dbg_info("not locked!\n"); 15648e8cd34eSMichael Ira Krufky return LG3306_UNLOCK; 1565b63b36faSFred Richter } 1566b63b36faSFred Richter 15670df289a2SMauro Carvalho Chehab static int lgdt3306a_read_status(struct dvb_frontend *fe, 15680df289a2SMauro Carvalho Chehab enum fe_status *status) 1569b63b36faSFred Richter { 1570b63b36faSFred Richter struct lgdt3306a_state *state = fe->demodulator_priv; 1571722b3c14SBrad Love struct dtv_frontend_properties *c = &fe->dtv_property_cache; 1572b63b36faSFred Richter u16 strength = 0; 15738e8cd34eSMichael Ira Krufky int ret = 0; 15748e8cd34eSMichael Ira Krufky 1575b63b36faSFred Richter if (fe->ops.tuner_ops.get_rf_strength) { 1576b63b36faSFred Richter ret = fe->ops.tuner_ops.get_rf_strength(fe, &strength); 1577c9897649SMauro Carvalho Chehab if (ret == 0) 1578097117caSMauro Carvalho Chehab dbg_info("strength=%d\n", strength); 1579c9897649SMauro Carvalho Chehab else 1580097117caSMauro Carvalho Chehab dbg_info("fe->ops.tuner_ops.get_rf_strength() failed\n"); 1581b63b36faSFred Richter } 1582b63b36faSFred Richter 1583b63b36faSFred Richter *status = 0; 1584b63b36faSFred Richter if (lgdt3306a_neverlock_poll(state) == LG3306_NL_LOCK) { 1585b63b36faSFred Richter *status |= FE_HAS_SIGNAL; 1586b63b36faSFred Richter *status |= FE_HAS_CARRIER; 1587b63b36faSFred Richter 1588b63b36faSFred Richter switch (state->current_modulation) { 1589b63b36faSFred Richter case QAM_256: 1590b63b36faSFred Richter case QAM_64: 15914966c0c5SBrad Love case QAM_AUTO: 1592b63b36faSFred Richter if (lgdt3306a_qam_lock_poll(state) == LG3306_LOCK) { 1593b63b36faSFred Richter *status |= FE_HAS_VITERBI; 1594b63b36faSFred Richter *status |= FE_HAS_SYNC; 1595b63b36faSFred Richter 1596b63b36faSFred Richter *status |= FE_HAS_LOCK; 1597b63b36faSFred Richter } 1598b63b36faSFred Richter break; 1599b63b36faSFred Richter case VSB_8: 1600b63b36faSFred Richter if (lgdt3306a_vsb_lock_poll(state) == LG3306_LOCK) { 1601b63b36faSFred Richter *status |= FE_HAS_VITERBI; 1602b63b36faSFred Richter *status |= FE_HAS_SYNC; 1603b63b36faSFred Richter 1604b63b36faSFred Richter *status |= FE_HAS_LOCK; 1605b63b36faSFred Richter 1606ee0133eeSMauro Carvalho Chehab ret = lgdt3306a_monitor_vsb(state); 1607b63b36faSFred Richter } 1608b63b36faSFred Richter break; 1609b63b36faSFred Richter default: 1610b63b36faSFred Richter ret = -EINVAL; 1611b63b36faSFred Richter } 1612722b3c14SBrad Love 1613722b3c14SBrad Love if (*status & FE_HAS_SYNC) { 1614722b3c14SBrad Love c->cnr.len = 1; 1615722b3c14SBrad Love c->cnr.stat[0].scale = FE_SCALE_DECIBEL; 1616722b3c14SBrad Love c->cnr.stat[0].svalue = lgdt3306a_calculate_snr_x100(state) * 10; 1617722b3c14SBrad Love } else { 1618722b3c14SBrad Love c->cnr.len = 1; 1619722b3c14SBrad Love c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 1620722b3c14SBrad Love } 1621b63b36faSFred Richter } 1622b63b36faSFred Richter return ret; 1623b63b36faSFred Richter } 1624b63b36faSFred Richter 1625b63b36faSFred Richter 1626b63b36faSFred Richter static int lgdt3306a_read_snr(struct dvb_frontend *fe, u16 *snr) 1627b63b36faSFred Richter { 1628b63b36faSFred Richter struct lgdt3306a_state *state = fe->demodulator_priv; 1629b63b36faSFred Richter 1630b63b36faSFred Richter state->snr = lgdt3306a_calculate_snr_x100(state); 1631b63b36faSFred Richter /* report SNR in dB * 10 */ 1632b63b36faSFred Richter *snr = state->snr/10; 1633b63b36faSFred Richter 1634b63b36faSFred Richter return 0; 1635b63b36faSFred Richter } 1636b63b36faSFred Richter 1637b63b36faSFred Richter static int lgdt3306a_read_signal_strength(struct dvb_frontend *fe, 1638b63b36faSFred Richter u16 *strength) 1639b63b36faSFred Richter { 1640b63b36faSFred Richter /* 1641b63b36faSFred Richter * Calculate some sort of "strength" from SNR 1642b63b36faSFred Richter */ 1643b63b36faSFred Richter struct lgdt3306a_state *state = fe->demodulator_priv; 16444966c0c5SBrad Love u8 val; 16458e8cd34eSMichael Ira Krufky u16 snr; /* snr_x10 */ 1646b63b36faSFred Richter int ret; 16478e8cd34eSMichael Ira Krufky u32 ref_snr; /* snr*100 */ 1648b63b36faSFred Richter u32 str; 1649b63b36faSFred Richter 1650b63b36faSFred Richter *strength = 0; 1651b63b36faSFred Richter 1652b63b36faSFred Richter switch (state->current_modulation) { 1653b63b36faSFred Richter case VSB_8: 16548e8cd34eSMichael Ira Krufky ref_snr = 1600; /* 16dB */ 1655b63b36faSFred Richter break; 1656b63b36faSFred Richter case QAM_64: 1657b63b36faSFred Richter case QAM_256: 16584966c0c5SBrad Love case QAM_AUTO: 16594966c0c5SBrad Love /* need to know actual modulation to set proper SNR baseline */ 1660c9b7d8f2SKangjie Lu ret = lgdt3306a_read_reg(state, 0x00a6, &val); 1661c9b7d8f2SKangjie Lu if (lg_chkerr(ret)) 1662c9b7d8f2SKangjie Lu goto fail; 1663c9b7d8f2SKangjie Lu 16644966c0c5SBrad Love if(val & 0x04) 16654966c0c5SBrad Love ref_snr = 2800; /* QAM-256 28dB */ 16664966c0c5SBrad Love else 16674966c0c5SBrad Love ref_snr = 2200; /* QAM-64 22dB */ 1668b63b36faSFred Richter break; 1669b63b36faSFred Richter default: 1670b63b36faSFred Richter return -EINVAL; 1671b63b36faSFred Richter } 1672b63b36faSFred Richter 1673b63b36faSFred Richter ret = fe->ops.read_snr(fe, &snr); 1674b63b36faSFred Richter if (lg_chkerr(ret)) 1675b63b36faSFred Richter goto fail; 1676b63b36faSFred Richter 1677b63b36faSFred Richter if (state->snr <= (ref_snr - 100)) 1678b63b36faSFred Richter str = 0; 1679b63b36faSFred Richter else if (state->snr <= ref_snr) 16808e8cd34eSMichael Ira Krufky str = (0xffff * 65) / 100; /* 65% */ 1681b63b36faSFred Richter else { 1682b63b36faSFred Richter str = state->snr - ref_snr; 1683b63b36faSFred Richter str /= 50; 16848e8cd34eSMichael Ira Krufky str += 78; /* 78%-100% */ 1685b63b36faSFred Richter if (str > 100) 1686b63b36faSFred Richter str = 100; 1687b63b36faSFred Richter str = (0xffff * str) / 100; 1688b63b36faSFred Richter } 1689b63b36faSFred Richter *strength = (u16)str; 1690097117caSMauro Carvalho Chehab dbg_info("strength=%u\n", *strength); 1691b63b36faSFred Richter 1692b63b36faSFred Richter fail: 1693b63b36faSFred Richter return ret; 1694b63b36faSFred Richter } 1695b63b36faSFred Richter 1696b63b36faSFred Richter /* ------------------------------------------------------------------------ */ 1697b63b36faSFred Richter 1698b63b36faSFred Richter static int lgdt3306a_read_ber(struct dvb_frontend *fe, u32 *ber) 1699b63b36faSFred Richter { 1700b63b36faSFred Richter struct lgdt3306a_state *state = fe->demodulator_priv; 1701b63b36faSFred Richter u32 tmp; 1702b63b36faSFred Richter 1703b63b36faSFred Richter *ber = 0; 1704b63b36faSFred Richter #if 1 1705534f4364SMauro Carvalho Chehab /* FGR - FIXME - I don't know what value is expected by dvb_core 17068e8cd34eSMichael Ira Krufky * what is the scale of the value?? */ 17074937ba94SMauro Carvalho Chehab tmp = read_reg(state, 0x00fc); /* NBERVALUE[24-31] */ 17084937ba94SMauro Carvalho Chehab tmp = (tmp << 8) | read_reg(state, 0x00fd); /* NBERVALUE[16-23] */ 17094937ba94SMauro Carvalho Chehab tmp = (tmp << 8) | read_reg(state, 0x00fe); /* NBERVALUE[8-15] */ 17104937ba94SMauro Carvalho Chehab tmp = (tmp << 8) | read_reg(state, 0x00ff); /* NBERVALUE[0-7] */ 1711b63b36faSFred Richter *ber = tmp; 1712097117caSMauro Carvalho Chehab dbg_info("ber=%u\n", tmp); 1713b63b36faSFred Richter #endif 1714b63b36faSFred Richter return 0; 1715b63b36faSFred Richter } 1716b63b36faSFred Richter 1717b63b36faSFred Richter static int lgdt3306a_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) 1718b63b36faSFred Richter { 1719b63b36faSFred Richter struct lgdt3306a_state *state = fe->demodulator_priv; 1720b63b36faSFred Richter 1721b63b36faSFred Richter *ucblocks = 0; 1722b63b36faSFred Richter #if 1 1723534f4364SMauro Carvalho Chehab /* FGR - FIXME - I don't know what value is expected by dvb_core 17248e8cd34eSMichael Ira Krufky * what happens when value wraps? */ 17254937ba94SMauro Carvalho Chehab *ucblocks = read_reg(state, 0x00f4); /* TPIFTPERRCNT[0-7] */ 1726097117caSMauro Carvalho Chehab dbg_info("ucblocks=%u\n", *ucblocks); 1727b63b36faSFred Richter #endif 1728b63b36faSFred Richter 1729b63b36faSFred Richter return 0; 1730b63b36faSFred Richter } 1731b63b36faSFred Richter 1732534f4364SMauro Carvalho Chehab static int lgdt3306a_tune(struct dvb_frontend *fe, bool re_tune, 1733534f4364SMauro Carvalho Chehab unsigned int mode_flags, unsigned int *delay, 17340df289a2SMauro Carvalho Chehab enum fe_status *status) 1735b63b36faSFred Richter { 1736b63b36faSFred Richter int ret = 0; 1737b63b36faSFred Richter struct lgdt3306a_state *state = fe->demodulator_priv; 1738b63b36faSFred Richter 1739097117caSMauro Carvalho Chehab dbg_info("re_tune=%u\n", re_tune); 1740b63b36faSFred Richter 1741b63b36faSFred Richter if (re_tune) { 17428e8cd34eSMichael Ira Krufky state->current_frequency = -1; /* force re-tune */ 1743ae21e447SMichael Ira Krufky ret = lgdt3306a_set_parameters(fe); 1744ae21e447SMichael Ira Krufky if (ret != 0) 1745b63b36faSFred Richter return ret; 1746b63b36faSFred Richter } 1747b63b36faSFred Richter *delay = 125; 1748b63b36faSFred Richter ret = lgdt3306a_read_status(fe, status); 1749b63b36faSFred Richter 1750b63b36faSFred Richter return ret; 1751b63b36faSFred Richter } 1752b63b36faSFred Richter 1753b63b36faSFred Richter static int lgdt3306a_get_tune_settings(struct dvb_frontend *fe, 1754b63b36faSFred Richter struct dvb_frontend_tune_settings 1755b63b36faSFred Richter *fe_tune_settings) 1756b63b36faSFred Richter { 1757b63b36faSFred Richter fe_tune_settings->min_delay_ms = 100; 1758097117caSMauro Carvalho Chehab dbg_info("\n"); 1759b63b36faSFred Richter return 0; 1760b63b36faSFred Richter } 1761b63b36faSFred Richter 1762f172fe9fSLuc Van Oostenryck static enum dvbfe_search lgdt3306a_search(struct dvb_frontend *fe) 1763b63b36faSFred Richter { 17640df289a2SMauro Carvalho Chehab enum fe_status status = 0; 1765dd14523aSAbylay Ospan int ret; 1766b63b36faSFred Richter 1767b63b36faSFred Richter /* set frontend */ 1768b63b36faSFred Richter ret = lgdt3306a_set_parameters(fe); 1769b63b36faSFred Richter if (ret) 1770b63b36faSFred Richter goto error; 1771b63b36faSFred Richter 1772b63b36faSFred Richter ret = lgdt3306a_read_status(fe, &status); 1773b63b36faSFred Richter if (ret) 1774b63b36faSFred Richter goto error; 1775b63b36faSFred Richter 1776b63b36faSFred Richter /* check if we have a valid signal */ 17778e8cd34eSMichael Ira Krufky if (status & FE_HAS_LOCK) 1778b63b36faSFred Richter return DVBFE_ALGO_SEARCH_SUCCESS; 17798e8cd34eSMichael Ira Krufky else 1780b63b36faSFred Richter return DVBFE_ALGO_SEARCH_AGAIN; 1781b63b36faSFred Richter 1782b63b36faSFred Richter error: 1783097117caSMauro Carvalho Chehab dbg_info("failed (%d)\n", ret); 1784b63b36faSFred Richter return DVBFE_ALGO_SEARCH_ERROR; 1785b63b36faSFred Richter } 1786b63b36faSFred Richter 1787b63b36faSFred Richter static void lgdt3306a_release(struct dvb_frontend *fe) 1788b63b36faSFred Richter { 1789b63b36faSFred Richter struct lgdt3306a_state *state = fe->demodulator_priv; 17908e8cd34eSMichael Ira Krufky 1791097117caSMauro Carvalho Chehab dbg_info("\n"); 1792b63b36faSFred Richter kfree(state); 1793b63b36faSFred Richter } 1794b63b36faSFred Richter 1795bd336e63SMax Kellermann static const struct dvb_frontend_ops lgdt3306a_ops; 1796b63b36faSFred Richter 1797b63b36faSFred Richter struct dvb_frontend *lgdt3306a_attach(const struct lgdt3306a_config *config, 1798b63b36faSFred Richter struct i2c_adapter *i2c_adap) 1799b63b36faSFred Richter { 1800b63b36faSFred Richter struct lgdt3306a_state *state = NULL; 1801b63b36faSFred Richter int ret; 1802b63b36faSFred Richter u8 val; 1803b63b36faSFred Richter 1804097117caSMauro Carvalho Chehab dbg_info("(%d-%04x)\n", 1805b63b36faSFred Richter i2c_adap ? i2c_adapter_id(i2c_adap) : 0, 1806b63b36faSFred Richter config ? config->i2c_addr : 0); 1807b63b36faSFred Richter 1808b63b36faSFred Richter state = kzalloc(sizeof(struct lgdt3306a_state), GFP_KERNEL); 1809b63b36faSFred Richter if (state == NULL) 1810b63b36faSFred Richter goto fail; 1811b63b36faSFred Richter 1812b63b36faSFred Richter state->cfg = config; 1813b63b36faSFred Richter state->i2c_adap = i2c_adap; 1814b63b36faSFred Richter 1815b63b36faSFred Richter memcpy(&state->frontend.ops, &lgdt3306a_ops, 1816b63b36faSFred Richter sizeof(struct dvb_frontend_ops)); 1817b63b36faSFred Richter state->frontend.demodulator_priv = state; 1818b63b36faSFred Richter 1819b63b36faSFred Richter /* verify that we're talking to a lg3306a */ 18208e8cd34eSMichael Ira Krufky /* FGR - NOTE - there is no obvious ChipId to check; we check 18218e8cd34eSMichael Ira Krufky * some "known" bits after reset, but it's still just a guess */ 1822b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x0000, &val); 1823b63b36faSFred Richter if (lg_chkerr(ret)) 1824b63b36faSFred Richter goto fail; 1825b63b36faSFred Richter if ((val & 0x74) != 0x74) { 1826097117caSMauro Carvalho Chehab pr_warn("expected 0x74, got 0x%x\n", (val & 0x74)); 18278e8cd34eSMichael Ira Krufky #if 0 1828534f4364SMauro Carvalho Chehab /* FIXME - re-enable when we know this is right */ 1829534f4364SMauro Carvalho Chehab goto fail; 18308e8cd34eSMichael Ira Krufky #endif 1831b63b36faSFred Richter } 1832b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x0001, &val); 1833b63b36faSFred Richter if (lg_chkerr(ret)) 1834b63b36faSFred Richter goto fail; 18354937ba94SMauro Carvalho Chehab if ((val & 0xf6) != 0xc6) { 1836097117caSMauro Carvalho Chehab pr_warn("expected 0xc6, got 0x%x\n", (val & 0xf6)); 18378e8cd34eSMichael Ira Krufky #if 0 1838534f4364SMauro Carvalho Chehab /* FIXME - re-enable when we know this is right */ 1839534f4364SMauro Carvalho Chehab goto fail; 18408e8cd34eSMichael Ira Krufky #endif 1841b63b36faSFred Richter } 1842b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x0002, &val); 1843b63b36faSFred Richter if (lg_chkerr(ret)) 1844b63b36faSFred Richter goto fail; 1845b63b36faSFred Richter if ((val & 0x73) != 0x03) { 1846097117caSMauro Carvalho Chehab pr_warn("expected 0x03, got 0x%x\n", (val & 0x73)); 18478e8cd34eSMichael Ira Krufky #if 0 1848534f4364SMauro Carvalho Chehab /* FIXME - re-enable when we know this is right */ 1849534f4364SMauro Carvalho Chehab goto fail; 18508e8cd34eSMichael Ira Krufky #endif 1851b63b36faSFred Richter } 1852b63b36faSFred Richter 1853b63b36faSFred Richter state->current_frequency = -1; 1854b63b36faSFred Richter state->current_modulation = -1; 1855b63b36faSFred Richter 1856b63b36faSFred Richter lgdt3306a_sleep(state); 1857b63b36faSFred Richter 1858b63b36faSFred Richter return &state->frontend; 1859b63b36faSFred Richter 1860b63b36faSFred Richter fail: 1861097117caSMauro Carvalho Chehab pr_warn("unable to detect LGDT3306A hardware\n"); 1862b63b36faSFred Richter kfree(state); 1863b63b36faSFred Richter return NULL; 1864b63b36faSFred Richter } 1865ebd9175eSMichael Ira Krufky EXPORT_SYMBOL(lgdt3306a_attach); 1866b63b36faSFred Richter 1867b63b36faSFred Richter #ifdef DBG_DUMP 1868b63b36faSFred Richter 1869b63b36faSFred Richter static const short regtab[] = { 18706da7ac98SMichael Ira Krufky 0x0000, /* SOFTRSTB 1'b1 1'b1 1'b1 ADCPDB 1'b1 PLLPDB GBBPDB 11111111 */ 18716da7ac98SMichael Ira Krufky 0x0001, /* 1'b1 1'b1 1'b0 1'b0 AUTORPTRS */ 18726da7ac98SMichael Ira Krufky 0x0002, /* NI2CRPTEN 1'b0 1'b0 1'b0 SPECINVAUT */ 18736da7ac98SMichael Ira Krufky 0x0003, /* AGCRFOUT */ 18746da7ac98SMichael Ira Krufky 0x0004, /* ADCSEL1V ADCCNT ADCCNF ADCCNS ADCCLKPLL */ 18756da7ac98SMichael Ira Krufky 0x0005, /* PLLINDIVSE */ 18766da7ac98SMichael Ira Krufky 0x0006, /* PLLCTRL[7:0] 11100001 */ 18776da7ac98SMichael Ira Krufky 0x0007, /* SYSINITWAITTIME[7:0] (msec) 00001000 */ 18786da7ac98SMichael Ira Krufky 0x0008, /* STDOPMODE[7:0] 10000000 */ 18796da7ac98SMichael Ira Krufky 0x0009, /* 1'b0 1'b0 1'b0 STDOPDETTMODE[2:0] STDOPDETCMODE[1:0] 00011110 */ 18804937ba94SMauro Carvalho Chehab 0x000a, /* DAFTEN 1'b1 x x SCSYSLOCK */ 18814937ba94SMauro Carvalho Chehab 0x000b, /* SCSYSLOCKCHKTIME[7:0] (10msec) 01100100 */ 18824937ba94SMauro Carvalho Chehab 0x000d, /* x SAMPLING4 */ 18834937ba94SMauro Carvalho Chehab 0x000e, /* SAMFREQ[15:8] 00000000 */ 18844937ba94SMauro Carvalho Chehab 0x000f, /* SAMFREQ[7:0] 00000000 */ 18856da7ac98SMichael Ira Krufky 0x0010, /* IFFREQ[15:8] 01100000 */ 18866da7ac98SMichael Ira Krufky 0x0011, /* IFFREQ[7:0] 00000000 */ 18876da7ac98SMichael Ira Krufky 0x0012, /* AGCEN AGCREFMO */ 18886da7ac98SMichael Ira Krufky 0x0013, /* AGCRFFIXB AGCIFFIXB AGCLOCKDETRNGSEL[1:0] 1'b1 1'b0 1'b0 1'b0 11101000 */ 18896da7ac98SMichael Ira Krufky 0x0014, /* AGCFIXVALUE[7:0] 01111111 */ 18906da7ac98SMichael Ira Krufky 0x0015, /* AGCREF[15:8] 00001010 */ 18916da7ac98SMichael Ira Krufky 0x0016, /* AGCREF[7:0] 11100100 */ 18926da7ac98SMichael Ira Krufky 0x0017, /* AGCDELAY[7:0] 00100000 */ 18936da7ac98SMichael Ira Krufky 0x0018, /* AGCRFBW[3:0] AGCIFBW[3:0] 10001000 */ 18946da7ac98SMichael Ira Krufky 0x0019, /* AGCUDOUTMODE[1:0] AGCUDCTRLLEN[1:0] AGCUDCTRL */ 18954937ba94SMauro Carvalho Chehab 0x001c, /* 1'b1 PFEN MFEN AICCVSYNC */ 18964937ba94SMauro Carvalho Chehab 0x001d, /* 1'b0 1'b1 1'b0 1'b1 AICCVSYNC */ 18974937ba94SMauro Carvalho Chehab 0x001e, /* AICCALPHA[3:0] 1'b1 1'b0 1'b1 1'b0 01111010 */ 18984937ba94SMauro Carvalho Chehab 0x001f, /* AICCDETTH[19:16] AICCOFFTH[19:16] 00000000 */ 18996da7ac98SMichael Ira Krufky 0x0020, /* AICCDETTH[15:8] 01111100 */ 19006da7ac98SMichael Ira Krufky 0x0021, /* AICCDETTH[7:0] 00000000 */ 19016da7ac98SMichael Ira Krufky 0x0022, /* AICCOFFTH[15:8] 00000101 */ 19026da7ac98SMichael Ira Krufky 0x0023, /* AICCOFFTH[7:0] 11100000 */ 19036da7ac98SMichael Ira Krufky 0x0024, /* AICCOPMODE3[1:0] AICCOPMODE2[1:0] AICCOPMODE1[1:0] AICCOPMODE0[1:0] 00000000 */ 19046da7ac98SMichael Ira Krufky 0x0025, /* AICCFIXFREQ3[23:16] 00000000 */ 19056da7ac98SMichael Ira Krufky 0x0026, /* AICCFIXFREQ3[15:8] 00000000 */ 19066da7ac98SMichael Ira Krufky 0x0027, /* AICCFIXFREQ3[7:0] 00000000 */ 19076da7ac98SMichael Ira Krufky 0x0028, /* AICCFIXFREQ2[23:16] 00000000 */ 19086da7ac98SMichael Ira Krufky 0x0029, /* AICCFIXFREQ2[15:8] 00000000 */ 19094937ba94SMauro Carvalho Chehab 0x002a, /* AICCFIXFREQ2[7:0] 00000000 */ 19104937ba94SMauro Carvalho Chehab 0x002b, /* AICCFIXFREQ1[23:16] 00000000 */ 19114937ba94SMauro Carvalho Chehab 0x002c, /* AICCFIXFREQ1[15:8] 00000000 */ 19124937ba94SMauro Carvalho Chehab 0x002d, /* AICCFIXFREQ1[7:0] 00000000 */ 19134937ba94SMauro Carvalho Chehab 0x002e, /* AICCFIXFREQ0[23:16] 00000000 */ 19144937ba94SMauro Carvalho Chehab 0x002f, /* AICCFIXFREQ0[15:8] 00000000 */ 19156da7ac98SMichael Ira Krufky 0x0030, /* AICCFIXFREQ0[7:0] 00000000 */ 19166da7ac98SMichael Ira Krufky 0x0031, /* 1'b0 1'b1 1'b0 1'b0 x DAGC1STER */ 19176da7ac98SMichael Ira Krufky 0x0032, /* DAGC1STEN DAGC1STER */ 19186da7ac98SMichael Ira Krufky 0x0033, /* DAGC1STREF[15:8] 00001010 */ 19196da7ac98SMichael Ira Krufky 0x0034, /* DAGC1STREF[7:0] 11100100 */ 19206da7ac98SMichael Ira Krufky 0x0035, /* DAGC2NDE */ 19216da7ac98SMichael Ira Krufky 0x0036, /* DAGC2NDREF[15:8] 00001010 */ 19226da7ac98SMichael Ira Krufky 0x0037, /* DAGC2NDREF[7:0] 10000000 */ 19236da7ac98SMichael Ira Krufky 0x0038, /* DAGC2NDLOCKDETRNGSEL[1:0] */ 19244937ba94SMauro Carvalho Chehab 0x003d, /* 1'b1 SAMGEARS */ 19256da7ac98SMichael Ira Krufky 0x0040, /* SAMLFGMA */ 19266da7ac98SMichael Ira Krufky 0x0041, /* SAMLFBWM */ 19276da7ac98SMichael Ira Krufky 0x0044, /* 1'b1 CRGEARSHE */ 19286da7ac98SMichael Ira Krufky 0x0045, /* CRLFGMAN */ 19296da7ac98SMichael Ira Krufky 0x0046, /* CFLFBWMA */ 19306da7ac98SMichael Ira Krufky 0x0047, /* CRLFGMAN */ 19316da7ac98SMichael Ira Krufky 0x0048, /* x x x x CRLFGSTEP_VS[3:0] xxxx1001 */ 19326da7ac98SMichael Ira Krufky 0x0049, /* CRLFBWMA */ 19334937ba94SMauro Carvalho Chehab 0x004a, /* CRLFBWMA */ 19346da7ac98SMichael Ira Krufky 0x0050, /* 1'b0 1'b1 1'b1 1'b0 MSECALCDA */ 19356da7ac98SMichael Ira Krufky 0x0070, /* TPOUTEN TPIFEN TPCLKOUTE */ 19366da7ac98SMichael Ira Krufky 0x0071, /* TPSENB TPSSOPBITE */ 19376da7ac98SMichael Ira Krufky 0x0073, /* TP47HINS x x CHBERINT PERMODE[1:0] PERINT[1:0] 1xx11100 */ 19386da7ac98SMichael Ira Krufky 0x0075, /* x x x x x IQSWAPCTRL[2:0] xxxxx000 */ 19396da7ac98SMichael Ira Krufky 0x0076, /* NBERCON NBERST NBERPOL NBERWSYN */ 19406da7ac98SMichael Ira Krufky 0x0077, /* x NBERLOSTTH[2:0] NBERACQTH[3:0] x0000000 */ 19416da7ac98SMichael Ira Krufky 0x0078, /* NBERPOLY[31:24] 00000000 */ 19426da7ac98SMichael Ira Krufky 0x0079, /* NBERPOLY[23:16] 00000000 */ 19434937ba94SMauro Carvalho Chehab 0x007a, /* NBERPOLY[15:8] 00000000 */ 19444937ba94SMauro Carvalho Chehab 0x007b, /* NBERPOLY[7:0] 00000000 */ 19454937ba94SMauro Carvalho Chehab 0x007c, /* NBERPED[31:24] 00000000 */ 19464937ba94SMauro Carvalho Chehab 0x007d, /* NBERPED[23:16] 00000000 */ 19474937ba94SMauro Carvalho Chehab 0x007e, /* NBERPED[15:8] 00000000 */ 19484937ba94SMauro Carvalho Chehab 0x007f, /* NBERPED[7:0] 00000000 */ 19496da7ac98SMichael Ira Krufky 0x0080, /* x AGCLOCK DAGCLOCK SYSLOCK x x NEVERLOCK[1:0] */ 19506da7ac98SMichael Ira Krufky 0x0085, /* SPECINVST */ 19516da7ac98SMichael Ira Krufky 0x0088, /* SYSLOCKTIME[15:8] */ 19526da7ac98SMichael Ira Krufky 0x0089, /* SYSLOCKTIME[7:0] */ 19534937ba94SMauro Carvalho Chehab 0x008c, /* FECLOCKTIME[15:8] */ 19544937ba94SMauro Carvalho Chehab 0x008d, /* FECLOCKTIME[7:0] */ 19554937ba94SMauro Carvalho Chehab 0x008e, /* AGCACCOUT[15:8] */ 19564937ba94SMauro Carvalho Chehab 0x008f, /* AGCACCOUT[7:0] */ 19576da7ac98SMichael Ira Krufky 0x0090, /* AICCREJSTATUS[3:0] AICCREJBUSY[3:0] */ 19586da7ac98SMichael Ira Krufky 0x0091, /* AICCVSYNC */ 19594937ba94SMauro Carvalho Chehab 0x009c, /* CARRFREQOFFSET[15:8] */ 19604937ba94SMauro Carvalho Chehab 0x009d, /* CARRFREQOFFSET[7:0] */ 19614937ba94SMauro Carvalho Chehab 0x00a1, /* SAMFREQOFFSET[23:16] */ 19624937ba94SMauro Carvalho Chehab 0x00a2, /* SAMFREQOFFSET[15:8] */ 19634937ba94SMauro Carvalho Chehab 0x00a3, /* SAMFREQOFFSET[7:0] */ 19644937ba94SMauro Carvalho Chehab 0x00a6, /* SYNCLOCK SYNCLOCKH */ 19656da7ac98SMichael Ira Krufky #if 0 /* covered elsewhere */ 19664937ba94SMauro Carvalho Chehab 0x00e8, /* CONSTPWR[15:8] */ 19674937ba94SMauro Carvalho Chehab 0x00e9, /* CONSTPWR[7:0] */ 19684937ba94SMauro Carvalho Chehab 0x00ea, /* BMSE[15:8] */ 19694937ba94SMauro Carvalho Chehab 0x00eb, /* BMSE[7:0] */ 19704937ba94SMauro Carvalho Chehab 0x00ec, /* MSE[15:8] */ 19714937ba94SMauro Carvalho Chehab 0x00ed, /* MSE[7:0] */ 19724937ba94SMauro Carvalho Chehab 0x00ee, /* CONSTI[7:0] */ 19734937ba94SMauro Carvalho Chehab 0x00ef, /* CONSTQ[7:0] */ 1974b63b36faSFred Richter #endif 19754937ba94SMauro Carvalho Chehab 0x00f4, /* TPIFTPERRCNT[7:0] */ 19764937ba94SMauro Carvalho Chehab 0x00f5, /* TPCORREC */ 19774937ba94SMauro Carvalho Chehab 0x00f6, /* VBBER[15:8] */ 19784937ba94SMauro Carvalho Chehab 0x00f7, /* VBBER[7:0] */ 19794937ba94SMauro Carvalho Chehab 0x00f8, /* VABER[15:8] */ 19804937ba94SMauro Carvalho Chehab 0x00f9, /* VABER[7:0] */ 19814937ba94SMauro Carvalho Chehab 0x00fa, /* TPERRCNT[7:0] */ 19824937ba94SMauro Carvalho Chehab 0x00fb, /* NBERLOCK x x x x x x x */ 19834937ba94SMauro Carvalho Chehab 0x00fc, /* NBERVALUE[31:24] */ 19844937ba94SMauro Carvalho Chehab 0x00fd, /* NBERVALUE[23:16] */ 19854937ba94SMauro Carvalho Chehab 0x00fe, /* NBERVALUE[15:8] */ 19864937ba94SMauro Carvalho Chehab 0x00ff, /* NBERVALUE[7:0] */ 19876da7ac98SMichael Ira Krufky 0x1000, /* 1'b0 WODAGCOU */ 19886da7ac98SMichael Ira Krufky 0x1005, /* x x 1'b1 1'b1 x SRD_Q_QM */ 19896da7ac98SMichael Ira Krufky 0x1009, /* SRDWAITTIME[7:0] (10msec) 00100011 */ 19904937ba94SMauro Carvalho Chehab 0x100a, /* SRDWAITTIME_CQS[7:0] (msec) 01100100 */ 19914937ba94SMauro Carvalho Chehab 0x101a, /* x 1'b1 1'b0 1'b0 x QMDQAMMODE[2:0] x100x010 */ 19926da7ac98SMichael Ira Krufky 0x1036, /* 1'b0 1'b1 1'b0 1'b0 SAMGSEND_CQS[3:0] 01001110 */ 19934937ba94SMauro Carvalho Chehab 0x103c, /* SAMGSAUTOSTL_V[3:0] SAMGSAUTOEDL_V[3:0] 01000110 */ 19944937ba94SMauro Carvalho Chehab 0x103d, /* 1'b1 1'b1 SAMCNORMBP_V[1:0] 1'b0 1'b0 SAMMODESEL_V[1:0] 11100001 */ 19954937ba94SMauro Carvalho Chehab 0x103f, /* SAMZTEDSE */ 19964937ba94SMauro Carvalho Chehab 0x105d, /* EQSTATUSE */ 19974937ba94SMauro Carvalho Chehab 0x105f, /* x PMAPG2_V[2:0] x DMAPG2_V[2:0] x001x011 */ 19986da7ac98SMichael Ira Krufky 0x1060, /* 1'b1 EQSTATUSE */ 19996da7ac98SMichael Ira Krufky 0x1061, /* CRMAPBWSTL_V[3:0] CRMAPBWEDL_V[3:0] 00000100 */ 20006da7ac98SMichael Ira Krufky 0x1065, /* 1'b0 x CRMODE_V[1:0] 1'b1 x 1'b1 x 0x111x1x */ 20016da7ac98SMichael Ira Krufky 0x1066, /* 1'b0 1'b0 1'b1 1'b0 1'b1 PNBOOSTSE */ 20026da7ac98SMichael Ira Krufky 0x1068, /* CREPHNGAIN2_V[3:0] CREPHNPBW_V[3:0] 10010001 */ 20034937ba94SMauro Carvalho Chehab 0x106e, /* x x x x x CREPHNEN_ */ 20044937ba94SMauro Carvalho Chehab 0x106f, /* CREPHNTH_V[7:0] 00010101 */ 20056da7ac98SMichael Ira Krufky 0x1072, /* CRSWEEPN */ 20066da7ac98SMichael Ira Krufky 0x1073, /* CRPGAIN_V[3:0] x x 1'b1 1'b1 1001xx11 */ 20076da7ac98SMichael Ira Krufky 0x1074, /* CRPBW_V[3:0] x x 1'b1 1'b1 0001xx11 */ 20086da7ac98SMichael Ira Krufky 0x1080, /* DAFTSTATUS[1:0] x x x x x x */ 20096da7ac98SMichael Ira Krufky 0x1081, /* SRDSTATUS[1:0] x x x x x SRDLOCK */ 20104937ba94SMauro Carvalho Chehab 0x10a9, /* EQSTATUS_CQS[1:0] x x x x x x */ 20114937ba94SMauro Carvalho Chehab 0x10b7, /* EQSTATUS_V[1:0] x x x x x x */ 20126da7ac98SMichael Ira Krufky #if 0 /* SMART_ANT */ 20134937ba94SMauro Carvalho Chehab 0x1f00, /* MODEDETE */ 20144937ba94SMauro Carvalho Chehab 0x1f01, /* x x x x x x x SFNRST xxxxxxx0 */ 20154937ba94SMauro Carvalho Chehab 0x1f03, /* NUMOFANT[7:0] 10000000 */ 20164937ba94SMauro Carvalho Chehab 0x1f04, /* x SELMASK[6:0] x0000000 */ 20174937ba94SMauro Carvalho Chehab 0x1f05, /* x SETMASK[6:0] x0000000 */ 20184937ba94SMauro Carvalho Chehab 0x1f06, /* x TXDATA[6:0] x0000000 */ 20194937ba94SMauro Carvalho Chehab 0x1f07, /* x CHNUMBER[6:0] x0000000 */ 20204937ba94SMauro Carvalho Chehab 0x1f09, /* AGCTIME[23:16] 10011000 */ 20214937ba94SMauro Carvalho Chehab 0x1f0a, /* AGCTIME[15:8] 10010110 */ 20224937ba94SMauro Carvalho Chehab 0x1f0b, /* AGCTIME[7:0] 10000000 */ 20234937ba94SMauro Carvalho Chehab 0x1f0c, /* ANTTIME[31:24] 00000000 */ 20244937ba94SMauro Carvalho Chehab 0x1f0d, /* ANTTIME[23:16] 00000011 */ 20254937ba94SMauro Carvalho Chehab 0x1f0e, /* ANTTIME[15:8] 10010000 */ 20264937ba94SMauro Carvalho Chehab 0x1f0f, /* ANTTIME[7:0] 10010000 */ 20274937ba94SMauro Carvalho Chehab 0x1f11, /* SYNCTIME[23:16] 10011000 */ 20284937ba94SMauro Carvalho Chehab 0x1f12, /* SYNCTIME[15:8] 10010110 */ 20294937ba94SMauro Carvalho Chehab 0x1f13, /* SYNCTIME[7:0] 10000000 */ 20304937ba94SMauro Carvalho Chehab 0x1f14, /* SNRTIME[31:24] 00000001 */ 20314937ba94SMauro Carvalho Chehab 0x1f15, /* SNRTIME[23:16] 01111101 */ 20324937ba94SMauro Carvalho Chehab 0x1f16, /* SNRTIME[15:8] 01111000 */ 20334937ba94SMauro Carvalho Chehab 0x1f17, /* SNRTIME[7:0] 01000000 */ 20344937ba94SMauro Carvalho Chehab 0x1f19, /* FECTIME[23:16] 00000000 */ 20354937ba94SMauro Carvalho Chehab 0x1f1a, /* FECTIME[15:8] 01110010 */ 20364937ba94SMauro Carvalho Chehab 0x1f1b, /* FECTIME[7:0] 01110000 */ 20374937ba94SMauro Carvalho Chehab 0x1f1d, /* FECTHD[7:0] 00000011 */ 20384937ba94SMauro Carvalho Chehab 0x1f1f, /* SNRTHD[23:16] 00001000 */ 20394937ba94SMauro Carvalho Chehab 0x1f20, /* SNRTHD[15:8] 01111111 */ 20404937ba94SMauro Carvalho Chehab 0x1f21, /* SNRTHD[7:0] 10000101 */ 20414937ba94SMauro Carvalho Chehab 0x1f80, /* IRQFLG x x SFSDRFLG MODEBFLG SAVEFLG SCANFLG TRACKFLG */ 20424937ba94SMauro Carvalho Chehab 0x1f81, /* x SYNCCON SNRCON FECCON x STDBUSY SYNCRST AGCFZCO */ 20434937ba94SMauro Carvalho Chehab 0x1f82, /* x x x SCANOPCD[4:0] */ 20444937ba94SMauro Carvalho Chehab 0x1f83, /* x x x x MAINOPCD[3:0] */ 20454937ba94SMauro Carvalho Chehab 0x1f84, /* x x RXDATA[13:8] */ 20464937ba94SMauro Carvalho Chehab 0x1f85, /* RXDATA[7:0] */ 20474937ba94SMauro Carvalho Chehab 0x1f86, /* x x SDTDATA[13:8] */ 20484937ba94SMauro Carvalho Chehab 0x1f87, /* SDTDATA[7:0] */ 20494937ba94SMauro Carvalho Chehab 0x1f89, /* ANTSNR[23:16] */ 20504937ba94SMauro Carvalho Chehab 0x1f8a, /* ANTSNR[15:8] */ 20514937ba94SMauro Carvalho Chehab 0x1f8b, /* ANTSNR[7:0] */ 20524937ba94SMauro Carvalho Chehab 0x1f8c, /* x x x x ANTFEC[13:8] */ 20534937ba94SMauro Carvalho Chehab 0x1f8d, /* ANTFEC[7:0] */ 20544937ba94SMauro Carvalho Chehab 0x1f8e, /* MAXCNT[7:0] */ 20554937ba94SMauro Carvalho Chehab 0x1f8f, /* SCANCNT[7:0] */ 20564937ba94SMauro Carvalho Chehab 0x1f91, /* MAXPW[23:16] */ 20574937ba94SMauro Carvalho Chehab 0x1f92, /* MAXPW[15:8] */ 20584937ba94SMauro Carvalho Chehab 0x1f93, /* MAXPW[7:0] */ 20594937ba94SMauro Carvalho Chehab 0x1f95, /* CURPWMSE[23:16] */ 20604937ba94SMauro Carvalho Chehab 0x1f96, /* CURPWMSE[15:8] */ 20614937ba94SMauro Carvalho Chehab 0x1f97, /* CURPWMSE[7:0] */ 20626da7ac98SMichael Ira Krufky #endif /* SMART_ANT */ 20634937ba94SMauro Carvalho Chehab 0x211f, /* 1'b1 1'b1 1'b1 CIRQEN x x 1'b0 1'b0 1111xx00 */ 20644937ba94SMauro Carvalho Chehab 0x212a, /* EQAUTOST */ 20656da7ac98SMichael Ira Krufky 0x2122, /* CHFAST[7:0] 01100000 */ 20664937ba94SMauro Carvalho Chehab 0x212b, /* FFFSTEP_V[3:0] x FBFSTEP_V[2:0] 0001x001 */ 20674937ba94SMauro Carvalho Chehab 0x212c, /* PHDEROTBWSEL[3:0] 1'b1 1'b1 1'b1 1'b0 10001110 */ 20684937ba94SMauro Carvalho Chehab 0x212d, /* 1'b1 1'b1 1'b1 1'b1 x x TPIFLOCKS */ 20696da7ac98SMichael Ira Krufky 0x2135, /* DYNTRACKFDEQ[3:0] x 1'b0 1'b0 1'b0 1010x000 */ 20706da7ac98SMichael Ira Krufky 0x2141, /* TRMODE[1:0] 1'b1 1'b1 1'b0 1'b1 1'b1 1'b1 01110111 */ 20716da7ac98SMichael Ira Krufky 0x2162, /* AICCCTRLE */ 20726da7ac98SMichael Ira Krufky 0x2173, /* PHNCNFCNT[7:0] 00000100 */ 20736da7ac98SMichael Ira Krufky 0x2179, /* 1'b0 1'b0 1'b0 1'b1 x BADSINGLEDYNTRACKFBF[2:0] 0001x001 */ 20744937ba94SMauro Carvalho Chehab 0x217a, /* 1'b0 1'b0 1'b0 1'b1 x BADSLOWSINGLEDYNTRACKFBF[2:0] 0001x001 */ 20754937ba94SMauro Carvalho Chehab 0x217e, /* CNFCNTTPIF[7:0] 00001000 */ 20764937ba94SMauro Carvalho Chehab 0x217f, /* TPERRCNTTPIF[7:0] 00000001 */ 20776da7ac98SMichael Ira Krufky 0x2180, /* x x x x x x FBDLYCIR[9:8] */ 20786da7ac98SMichael Ira Krufky 0x2181, /* FBDLYCIR[7:0] */ 20796da7ac98SMichael Ira Krufky 0x2185, /* MAXPWRMAIN[7:0] */ 20806da7ac98SMichael Ira Krufky 0x2191, /* NCOMBDET x x x x x x x */ 20816da7ac98SMichael Ira Krufky 0x2199, /* x MAINSTRON */ 20824937ba94SMauro Carvalho Chehab 0x219a, /* FFFEQSTEPOUT_V[3:0] FBFSTEPOUT_V[2:0] */ 20834937ba94SMauro Carvalho Chehab 0x21a1, /* x x SNRREF[5:0] */ 20846da7ac98SMichael Ira Krufky 0x2845, /* 1'b0 1'b1 x x FFFSTEP_CQS[1:0] FFFCENTERTAP[1:0] 01xx1110 */ 20856da7ac98SMichael Ira Krufky 0x2846, /* 1'b0 x 1'b0 1'b1 FBFSTEP_CQS[1:0] 1'b1 1'b0 0x011110 */ 20866da7ac98SMichael Ira Krufky 0x2847, /* ENNOSIGDE */ 20876da7ac98SMichael Ira Krufky 0x2849, /* 1'b1 1'b1 NOUSENOSI */ 20884937ba94SMauro Carvalho Chehab 0x284a, /* EQINITWAITTIME[7:0] 01100100 */ 20896da7ac98SMichael Ira Krufky 0x3000, /* 1'b1 1'b1 1'b1 x x x 1'b0 RPTRSTM */ 20906da7ac98SMichael Ira Krufky 0x3001, /* RPTRSTWAITTIME[7:0] (100msec) 00110010 */ 20916da7ac98SMichael Ira Krufky 0x3031, /* FRAMELOC */ 20926da7ac98SMichael Ira Krufky 0x3032, /* 1'b1 1'b0 1'b0 1'b0 x x FRAMELOCKMODE_CQS[1:0] 1000xx11 */ 20934937ba94SMauro Carvalho Chehab 0x30a9, /* VDLOCK_Q FRAMELOCK */ 20944937ba94SMauro Carvalho Chehab 0x30aa, /* MPEGLOCK */ 2095b63b36faSFred Richter }; 2096b63b36faSFred Richter 20971f679ff6SThomas Meyer #define numDumpRegs (ARRAY_SIZE(regtab)) 2098b63b36faSFred Richter static u8 regval1[numDumpRegs] = {0, }; 2099b63b36faSFred Richter static u8 regval2[numDumpRegs] = {0, }; 2100b63b36faSFred Richter 2101b63b36faSFred Richter static void lgdt3306a_DumpAllRegs(struct lgdt3306a_state *state) 2102b63b36faSFred Richter { 2103b63b36faSFred Richter memset(regval2, 0xff, sizeof(regval2)); 2104b63b36faSFred Richter lgdt3306a_DumpRegs(state); 2105b63b36faSFred Richter } 2106b63b36faSFred Richter 2107b63b36faSFred Richter static void lgdt3306a_DumpRegs(struct lgdt3306a_state *state) 2108b63b36faSFred Richter { 2109b63b36faSFred Richter int i; 2110b63b36faSFred Richter int sav_debug = debug; 21118e8cd34eSMichael Ira Krufky 2112b63b36faSFred Richter if ((debug & DBG_DUMP) == 0) 2113b63b36faSFred Richter return; 2114831a9112SMichael Ira Krufky debug &= ~DBG_REG; /* suppress DBG_REG during reg dump */ 2115b63b36faSFred Richter 2116097117caSMauro Carvalho Chehab lg_debug("\n"); 2117b63b36faSFred Richter 2118b63b36faSFred Richter for (i = 0; i < numDumpRegs; i++) { 2119b63b36faSFred Richter lgdt3306a_read_reg(state, regtab[i], ®val1[i]); 2120b63b36faSFred Richter if (regval1[i] != regval2[i]) { 2121097117caSMauro Carvalho Chehab lg_debug(" %04X = %02X\n", regtab[i], regval1[i]); 2122b63b36faSFred Richter regval2[i] = regval1[i]; 2123b63b36faSFred Richter } 2124b63b36faSFred Richter } 2125b63b36faSFred Richter debug = sav_debug; 2126b63b36faSFred Richter } 21278e8cd34eSMichael Ira Krufky #endif /* DBG_DUMP */ 2128b63b36faSFred Richter 2129b63b36faSFred Richter 2130b63b36faSFred Richter 2131bd336e63SMax Kellermann static const struct dvb_frontend_ops lgdt3306a_ops = { 2132b63b36faSFred Richter .delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B }, 2133b63b36faSFred Richter .info = { 2134b63b36faSFred Richter .name = "LG Electronics LGDT3306A VSB/QAM Frontend", 2135f1b1eabfSMauro Carvalho Chehab .frequency_min_hz = 54 * MHz, 2136f1b1eabfSMauro Carvalho Chehab .frequency_max_hz = 858 * MHz, 2137f1b1eabfSMauro Carvalho Chehab .frequency_stepsize_hz = 62500, 21384966c0c5SBrad Love .caps = FE_CAN_QAM_AUTO | FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB 2139b63b36faSFred Richter }, 2140b63b36faSFred Richter .i2c_gate_ctrl = lgdt3306a_i2c_gate_ctrl, 2141b63b36faSFred Richter .init = lgdt3306a_init, 2142b63b36faSFred Richter .sleep = lgdt3306a_fe_sleep, 2143b63b36faSFred Richter /* if this is set, it overrides the default swzigzag */ 2144b63b36faSFred Richter .tune = lgdt3306a_tune, 2145b63b36faSFred Richter .set_frontend = lgdt3306a_set_parameters, 2146b63b36faSFred Richter .get_frontend = lgdt3306a_get_frontend, 2147b63b36faSFred Richter .get_frontend_algo = lgdt3306a_get_frontend_algo, 2148b63b36faSFred Richter .get_tune_settings = lgdt3306a_get_tune_settings, 2149b63b36faSFred Richter .read_status = lgdt3306a_read_status, 2150b63b36faSFred Richter .read_ber = lgdt3306a_read_ber, 2151b63b36faSFred Richter .read_signal_strength = lgdt3306a_read_signal_strength, 2152b63b36faSFred Richter .read_snr = lgdt3306a_read_snr, 2153b63b36faSFred Richter .read_ucblocks = lgdt3306a_read_ucblocks, 2154b63b36faSFred Richter .release = lgdt3306a_release, 2155b63b36faSFred Richter .ts_bus_ctrl = lgdt3306a_ts_bus_ctrl, 2156b63b36faSFred Richter .search = lgdt3306a_search, 2157b63b36faSFred Richter }; 2158b63b36faSFred Richter 21594f751890SKevin Cheng static int lgdt3306a_select(struct i2c_mux_core *muxc, u32 chan) 21604f751890SKevin Cheng { 21614f751890SKevin Cheng struct i2c_client *client = i2c_mux_priv(muxc); 21624f751890SKevin Cheng struct lgdt3306a_state *state = i2c_get_clientdata(client); 21634f751890SKevin Cheng 21644f751890SKevin Cheng return lgdt3306a_i2c_gate_ctrl(&state->frontend, 1); 21654f751890SKevin Cheng } 21664f751890SKevin Cheng 21674f751890SKevin Cheng static int lgdt3306a_deselect(struct i2c_mux_core *muxc, u32 chan) 21684f751890SKevin Cheng { 21694f751890SKevin Cheng struct i2c_client *client = i2c_mux_priv(muxc); 21704f751890SKevin Cheng struct lgdt3306a_state *state = i2c_get_clientdata(client); 21714f751890SKevin Cheng 21724f751890SKevin Cheng return lgdt3306a_i2c_gate_ctrl(&state->frontend, 0); 21734f751890SKevin Cheng } 21744f751890SKevin Cheng 21754f751890SKevin Cheng static int lgdt3306a_probe(struct i2c_client *client, 21764f751890SKevin Cheng const struct i2c_device_id *id) 21774f751890SKevin Cheng { 21784f751890SKevin Cheng struct lgdt3306a_config *config; 21794f751890SKevin Cheng struct lgdt3306a_state *state; 21804f751890SKevin Cheng struct dvb_frontend *fe; 21814f751890SKevin Cheng int ret; 21824f751890SKevin Cheng 21832c4746cfSzhong jiang config = kmemdup(client->dev.platform_data, 21842c4746cfSzhong jiang sizeof(struct lgdt3306a_config), GFP_KERNEL); 21854f751890SKevin Cheng if (config == NULL) { 21864f751890SKevin Cheng ret = -ENOMEM; 21874f751890SKevin Cheng goto fail; 21884f751890SKevin Cheng } 21894f751890SKevin Cheng 21904f751890SKevin Cheng config->i2c_addr = client->addr; 2191f6618cc8SBrad Love fe = lgdt3306a_attach(config, client->adapter); 21924f751890SKevin Cheng if (fe == NULL) { 21934f751890SKevin Cheng ret = -ENODEV; 21944f751890SKevin Cheng goto err_fe; 21954f751890SKevin Cheng } 21964f751890SKevin Cheng 21974f751890SKevin Cheng i2c_set_clientdata(client, fe->demodulator_priv); 21984f751890SKevin Cheng state = fe->demodulator_priv; 21995b3a8e90SBrad Love state->frontend.ops.release = NULL; 22004f751890SKevin Cheng 22014f751890SKevin Cheng /* create mux i2c adapter for tuner */ 22024f751890SKevin Cheng state->muxc = i2c_mux_alloc(client->adapter, &client->dev, 22034f751890SKevin Cheng 1, 0, I2C_MUX_LOCKED, 22044f751890SKevin Cheng lgdt3306a_select, lgdt3306a_deselect); 22054f751890SKevin Cheng if (!state->muxc) { 22064f751890SKevin Cheng ret = -ENOMEM; 22074f751890SKevin Cheng goto err_kfree; 22084f751890SKevin Cheng } 22094f751890SKevin Cheng state->muxc->priv = client; 22104f751890SKevin Cheng ret = i2c_mux_add_adapter(state->muxc, 0, 0, 0); 22114f751890SKevin Cheng if (ret) 22124f751890SKevin Cheng goto err_kfree; 22134f751890SKevin Cheng 22144f751890SKevin Cheng /* create dvb_frontend */ 22154f751890SKevin Cheng fe->ops.i2c_gate_ctrl = NULL; 22164f751890SKevin Cheng *config->i2c_adapter = state->muxc->adapter[0]; 22174f751890SKevin Cheng *config->fe = fe; 22184f751890SKevin Cheng 2219e7f4d751SBrad Love dev_info(&client->dev, "LG Electronics LGDT3306A successfully identified\n"); 2220e7f4d751SBrad Love 22214f751890SKevin Cheng return 0; 22224f751890SKevin Cheng 22234f751890SKevin Cheng err_kfree: 22244f751890SKevin Cheng kfree(state); 22254f751890SKevin Cheng err_fe: 22264f751890SKevin Cheng kfree(config); 22274f751890SKevin Cheng fail: 2228e7f4d751SBrad Love dev_warn(&client->dev, "probe failed = %d\n", ret); 22294f751890SKevin Cheng return ret; 22304f751890SKevin Cheng } 22314f751890SKevin Cheng 22324f751890SKevin Cheng static int lgdt3306a_remove(struct i2c_client *client) 22334f751890SKevin Cheng { 22344f751890SKevin Cheng struct lgdt3306a_state *state = i2c_get_clientdata(client); 22354f751890SKevin Cheng 22364f751890SKevin Cheng i2c_mux_del_adapters(state->muxc); 22374f751890SKevin Cheng 22384f751890SKevin Cheng state->frontend.ops.release = NULL; 22394f751890SKevin Cheng state->frontend.demodulator_priv = NULL; 22404f751890SKevin Cheng 22414f751890SKevin Cheng kfree(state->cfg); 22424f751890SKevin Cheng kfree(state); 22434f751890SKevin Cheng 22444f751890SKevin Cheng return 0; 22454f751890SKevin Cheng } 22464f751890SKevin Cheng 22474f751890SKevin Cheng static const struct i2c_device_id lgdt3306a_id_table[] = { 22484f751890SKevin Cheng {"lgdt3306a", 0}, 22494f751890SKevin Cheng {} 22504f751890SKevin Cheng }; 22514f751890SKevin Cheng MODULE_DEVICE_TABLE(i2c, lgdt3306a_id_table); 22524f751890SKevin Cheng 22534f751890SKevin Cheng static struct i2c_driver lgdt3306a_driver = { 22544f751890SKevin Cheng .driver = { 22554f751890SKevin Cheng .name = "lgdt3306a", 22564f751890SKevin Cheng .suppress_bind_attrs = true, 22574f751890SKevin Cheng }, 22584f751890SKevin Cheng .probe = lgdt3306a_probe, 22594f751890SKevin Cheng .remove = lgdt3306a_remove, 22604f751890SKevin Cheng .id_table = lgdt3306a_id_table, 22614f751890SKevin Cheng }; 22624f751890SKevin Cheng 22634f751890SKevin Cheng module_i2c_driver(lgdt3306a_driver); 22644f751890SKevin Cheng 2265b63b36faSFred Richter MODULE_DESCRIPTION("LG Electronics LGDT3306A ATSC/QAM-B Demodulator Driver"); 2266b63b36faSFred Richter MODULE_AUTHOR("Fred Richter <frichter@hauppauge.com>"); 2267b63b36faSFred Richter MODULE_LICENSE("GPL"); 2268b63b36faSFred Richter MODULE_VERSION("0.2"); 2269