1b63b36faSFred Richter /* 2b63b36faSFred Richter * Support for LGDT3306A - 8VSB/QAM-B 3b63b36faSFred Richter * 4b63b36faSFred Richter * Copyright (C) 2013 Fred Richter <frichter@hauppauge.com> 5b63b36faSFred Richter * - driver structure based on lgdt3305.[ch] by Michael Krufky 6b63b36faSFred Richter * - code based on LG3306_V0.35 API by LG Electronics Inc. 7b63b36faSFred Richter * 8b63b36faSFred Richter * This program is free software; you can redistribute it and/or modify 9b63b36faSFred Richter * it under the terms of the GNU General Public License as published by 10b63b36faSFred Richter * the Free Software Foundation; either version 2 of the License, or 11b63b36faSFred Richter * (at your option) any later version. 12b63b36faSFred Richter * 13b63b36faSFred Richter * This program is distributed in the hope that it will be useful, 14b63b36faSFred Richter * but WITHOUT ANY WARRANTY; without even the implied warranty of 15b63b36faSFred Richter * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16b63b36faSFred Richter * GNU General Public License for more details. 17b63b36faSFred Richter * 18b63b36faSFred Richter * You should have received a copy of the GNU General Public License 19b63b36faSFred Richter * along with this program; if not, write to the Free Software 20b63b36faSFred Richter * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 21b63b36faSFred Richter * 22b63b36faSFred Richter */ 23b63b36faSFred Richter 24b63b36faSFred Richter #include <asm/div64.h> 25b63b36faSFred Richter #include <linux/dvb/frontend.h> 26b63b36faSFred Richter #include "dvb_math.h" 27b63b36faSFred Richter #include "lgdt3306a.h" 28b63b36faSFred Richter 29b63b36faSFred Richter 30b63b36faSFred Richter static int debug; 31b63b36faSFred Richter module_param(debug, int, 0644); 32b63b36faSFred Richter MODULE_PARM_DESC(debug, "set debug level (info=1, reg=2 (or-able))"); 33b63b36faSFred Richter 34b63b36faSFred Richter #define DBG_INFO 1 35b63b36faSFred Richter #define DBG_REG 2 368e8cd34eSMichael Ira Krufky #define DBG_DUMP 4 /* FGR - comment out to remove dump code */ 37b63b36faSFred Richter 38b63b36faSFred Richter #define lg_printk(kern, fmt, arg...) \ 39b63b36faSFred Richter printk(kern "%s(): " fmt, __func__, ##arg) 40b63b36faSFred Richter 41b63b36faSFred Richter #define lg_info(fmt, arg...) printk(KERN_INFO "lgdt3306a: " fmt, ##arg) 42b63b36faSFred Richter #define lg_warn(fmt, arg...) lg_printk(KERN_WARNING, fmt, ##arg) 43b63b36faSFred Richter #define lg_err(fmt, arg...) lg_printk(KERN_ERR, fmt, ##arg) 44b63b36faSFred Richter #define lg_dbg(fmt, arg...) if (debug & DBG_INFO) \ 45b63b36faSFred Richter lg_printk(KERN_DEBUG, fmt, ##arg) 46b63b36faSFred Richter #define lg_reg(fmt, arg...) if (debug & DBG_REG) \ 47b63b36faSFred Richter lg_printk(KERN_DEBUG, fmt, ##arg) 48b63b36faSFred Richter 49b63b36faSFred Richter #define lg_chkerr(ret) \ 50b63b36faSFred Richter ({ \ 51b63b36faSFred Richter int __ret; \ 52b63b36faSFred Richter __ret = (ret < 0); \ 53b63b36faSFred Richter if (__ret) \ 54b63b36faSFred Richter lg_err("error %d on line %d\n", ret, __LINE__); \ 55b63b36faSFred Richter __ret; \ 56b63b36faSFred Richter }) 57b63b36faSFred Richter 58b63b36faSFred Richter struct lgdt3306a_state { 59b63b36faSFred Richter struct i2c_adapter *i2c_adap; 60b63b36faSFred Richter const struct lgdt3306a_config *cfg; 61b63b36faSFred Richter 62b63b36faSFred Richter struct dvb_frontend frontend; 63b63b36faSFred Richter 64b63b36faSFred Richter fe_modulation_t current_modulation; 65b63b36faSFred Richter u32 current_frequency; 66b63b36faSFred Richter u32 snr; 67b63b36faSFred Richter }; 68b63b36faSFred Richter 69b63b36faSFred Richter /* ----------------------------------------------- 70b63b36faSFred Richter LG3306A Register Usage 71b63b36faSFred Richter (LG does not really name the registers, so this code does not either) 72b63b36faSFred Richter 0000 -> 00FF Common control and status 73b63b36faSFred Richter 1000 -> 10FF Synchronizer control and status 74b63b36faSFred Richter 1F00 -> 1FFF Smart Antenna control and status 75b63b36faSFred Richter 2100 -> 21FF VSB Equalizer control and status 76b63b36faSFred Richter 2800 -> 28FF QAM Equalizer control and status 77b63b36faSFred Richter 3000 -> 30FF FEC control and status 78b63b36faSFred Richter ---------------------------------------------- */ 79b63b36faSFred Richter 80f883d603SMichael Ira Krufky enum lgdt3306a_lock_status { 81b63b36faSFred Richter LG3306_UNLOCK = 0x00, 82b63b36faSFred Richter LG3306_LOCK = 0x01, 834937ba94SMauro Carvalho Chehab LG3306_UNKNOWN_LOCK = 0xff 84f883d603SMichael Ira Krufky }; 85b63b36faSFred Richter 86f883d603SMichael Ira Krufky enum lgdt3306a_neverlock_status { 87b63b36faSFred Richter LG3306_NL_INIT = 0x00, 88b63b36faSFred Richter LG3306_NL_PROCESS = 0x01, 89b63b36faSFred Richter LG3306_NL_LOCK = 0x02, 90b63b36faSFred Richter LG3306_NL_FAIL = 0x03, 914937ba94SMauro Carvalho Chehab LG3306_NL_UNKNOWN = 0xff 92f883d603SMichael Ira Krufky }; 93b63b36faSFred Richter 94f883d603SMichael Ira Krufky enum lgdt3306a_modulation { 95b63b36faSFred Richter LG3306_VSB = 0x00, 96b63b36faSFred Richter LG3306_QAM64 = 0x01, 97b63b36faSFred Richter LG3306_QAM256 = 0x02, 984937ba94SMauro Carvalho Chehab LG3306_UNKNOWN_MODE = 0xff 99f883d603SMichael Ira Krufky }; 100b63b36faSFred Richter 101f883d603SMichael Ira Krufky enum lgdt3306a_lock_check { 102b63b36faSFred Richter LG3306_SYNC_LOCK, 103b63b36faSFred Richter LG3306_FEC_LOCK, 104b63b36faSFred Richter LG3306_TR_LOCK, 105b63b36faSFred Richter LG3306_AGC_LOCK, 106f883d603SMichael Ira Krufky }; 107b63b36faSFred Richter 108b63b36faSFred Richter 109b63b36faSFred Richter #ifdef DBG_DUMP 110b63b36faSFred Richter static void lgdt3306a_DumpAllRegs(struct lgdt3306a_state *state); 111b63b36faSFred Richter static void lgdt3306a_DumpRegs(struct lgdt3306a_state *state); 112b63b36faSFred Richter #endif 113b63b36faSFred Richter 114b63b36faSFred Richter 115b63b36faSFred Richter static int lgdt3306a_write_reg(struct lgdt3306a_state *state, u16 reg, u8 val) 116b63b36faSFred Richter { 117b63b36faSFred Richter int ret; 118b63b36faSFred Richter u8 buf[] = { reg >> 8, reg & 0xff, val }; 119b63b36faSFred Richter struct i2c_msg msg = { 120b63b36faSFred Richter .addr = state->cfg->i2c_addr, .flags = 0, 121b63b36faSFred Richter .buf = buf, .len = 3, 122b63b36faSFred Richter }; 123b63b36faSFred Richter 124b63b36faSFred Richter lg_reg("reg: 0x%04x, val: 0x%02x\n", reg, val); 125b63b36faSFred Richter 126b63b36faSFred Richter ret = i2c_transfer(state->i2c_adap, &msg, 1); 127b63b36faSFred Richter 128b63b36faSFred Richter if (ret != 1) { 129b63b36faSFred Richter lg_err("error (addr %02x %02x <- %02x, err = %i)\n", 130b63b36faSFred Richter msg.buf[0], msg.buf[1], msg.buf[2], ret); 131b63b36faSFred Richter if (ret < 0) 132b63b36faSFred Richter return ret; 133b63b36faSFred Richter else 134b63b36faSFred Richter return -EREMOTEIO; 135b63b36faSFred Richter } 136b63b36faSFred Richter return 0; 137b63b36faSFred Richter } 138b63b36faSFred Richter 139b63b36faSFred Richter static int lgdt3306a_read_reg(struct lgdt3306a_state *state, u16 reg, u8 *val) 140b63b36faSFred Richter { 141b63b36faSFred Richter int ret; 142b63b36faSFred Richter u8 reg_buf[] = { reg >> 8, reg & 0xff }; 143b63b36faSFred Richter struct i2c_msg msg[] = { 144b63b36faSFred Richter { .addr = state->cfg->i2c_addr, 145b63b36faSFred Richter .flags = 0, .buf = reg_buf, .len = 2 }, 146b63b36faSFred Richter { .addr = state->cfg->i2c_addr, 147b63b36faSFred Richter .flags = I2C_M_RD, .buf = val, .len = 1 }, 148b63b36faSFred Richter }; 149b63b36faSFred Richter 150b63b36faSFred Richter ret = i2c_transfer(state->i2c_adap, msg, 2); 151b63b36faSFred Richter 152b63b36faSFred Richter if (ret != 2) { 153b63b36faSFred Richter lg_err("error (addr %02x reg %04x error (ret == %i)\n", 154b63b36faSFred Richter state->cfg->i2c_addr, reg, ret); 155b63b36faSFred Richter if (ret < 0) 156b63b36faSFred Richter return ret; 157b63b36faSFred Richter else 158b63b36faSFred Richter return -EREMOTEIO; 159b63b36faSFred Richter } 160b63b36faSFred Richter lg_reg("reg: 0x%04x, val: 0x%02x\n", reg, *val); 161b63b36faSFred Richter 162b63b36faSFred Richter return 0; 163b63b36faSFred Richter } 164b63b36faSFred Richter 165b63b36faSFred Richter #define read_reg(state, reg) \ 166b63b36faSFred Richter ({ \ 167b63b36faSFred Richter u8 __val; \ 168b63b36faSFred Richter int ret = lgdt3306a_read_reg(state, reg, &__val); \ 169b63b36faSFred Richter if (lg_chkerr(ret)) \ 170b63b36faSFred Richter __val = 0; \ 171b63b36faSFred Richter __val; \ 172b63b36faSFred Richter }) 173b63b36faSFred Richter 174b63b36faSFred Richter static int lgdt3306a_set_reg_bit(struct lgdt3306a_state *state, 175b63b36faSFred Richter u16 reg, int bit, int onoff) 176b63b36faSFred Richter { 177b63b36faSFred Richter u8 val; 178b63b36faSFred Richter int ret; 179b63b36faSFred Richter 180b63b36faSFred Richter lg_reg("reg: 0x%04x, bit: %d, level: %d\n", reg, bit, onoff); 181b63b36faSFred Richter 182b63b36faSFred Richter ret = lgdt3306a_read_reg(state, reg, &val); 183b63b36faSFred Richter if (lg_chkerr(ret)) 184b63b36faSFred Richter goto fail; 185b63b36faSFred Richter 186b63b36faSFred Richter val &= ~(1 << bit); 187b63b36faSFred Richter val |= (onoff & 1) << bit; 188b63b36faSFred Richter 189b63b36faSFred Richter ret = lgdt3306a_write_reg(state, reg, val); 190b63b36faSFred Richter lg_chkerr(ret); 191b63b36faSFred Richter fail: 192b63b36faSFred Richter return ret; 193b63b36faSFred Richter } 194b63b36faSFred Richter 195b63b36faSFred Richter /* ------------------------------------------------------------------------ */ 196b63b36faSFred Richter 197b63b36faSFred Richter static int lgdt3306a_soft_reset(struct lgdt3306a_state *state) 198b63b36faSFred Richter { 199b63b36faSFred Richter int ret; 200b63b36faSFred Richter 201b63b36faSFred Richter lg_dbg("\n"); 202b63b36faSFred Richter 203b63b36faSFred Richter ret = lgdt3306a_set_reg_bit(state, 0x0000, 7, 0); 204b63b36faSFred Richter if (lg_chkerr(ret)) 205b63b36faSFred Richter goto fail; 206b63b36faSFred Richter 207b63b36faSFred Richter msleep(20); 208b63b36faSFred Richter ret = lgdt3306a_set_reg_bit(state, 0x0000, 7, 1); 209b63b36faSFred Richter lg_chkerr(ret); 210b63b36faSFred Richter 211b63b36faSFred Richter fail: 212b63b36faSFred Richter return ret; 213b63b36faSFred Richter } 214b63b36faSFred Richter 215b63b36faSFred Richter static int lgdt3306a_mpeg_mode(struct lgdt3306a_state *state, 216b63b36faSFred Richter enum lgdt3306a_mpeg_mode mode) 217b63b36faSFred Richter { 218b63b36faSFred Richter u8 val; 219b63b36faSFred Richter int ret; 220b63b36faSFred Richter 221b63b36faSFred Richter lg_dbg("(%d)\n", mode); 2228e8cd34eSMichael Ira Krufky /* transport packet format */ 2238e8cd34eSMichael Ira Krufky ret = lgdt3306a_set_reg_bit(state, 0x0071, 7, mode == LGDT3306A_MPEG_PARALLEL?1:0); /* TPSENB=0x80 */ 224b63b36faSFred Richter if (lg_chkerr(ret)) 225b63b36faSFred Richter goto fail; 226b63b36faSFred Richter 2278e8cd34eSMichael Ira Krufky /* start of packet signal duration */ 2288e8cd34eSMichael Ira Krufky ret = lgdt3306a_set_reg_bit(state, 0x0071, 6, 0); /* TPSSOPBITEN=0x40; 0=byte duration, 1=bit duration */ 229b63b36faSFred Richter if (lg_chkerr(ret)) 230b63b36faSFred Richter goto fail; 231b63b36faSFred Richter 232b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x0070, &val); 233b63b36faSFred Richter if (lg_chkerr(ret)) 234b63b36faSFred Richter goto fail; 235b63b36faSFred Richter 2368e8cd34eSMichael Ira Krufky val |= 0x10; /* TPCLKSUPB=0x10 */ 237b63b36faSFred Richter 238b63b36faSFred Richter if (mode == LGDT3306A_MPEG_PARALLEL) 239b63b36faSFred Richter val &= ~0x10; 240b63b36faSFred Richter 241b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0070, val); 242b63b36faSFred Richter lg_chkerr(ret); 243b63b36faSFred Richter 244b63b36faSFred Richter fail: 245b63b36faSFred Richter return ret; 246b63b36faSFred Richter } 247b63b36faSFred Richter 248b63b36faSFred Richter static int lgdt3306a_mpeg_mode_polarity(struct lgdt3306a_state *state, 249b63b36faSFred Richter enum lgdt3306a_tp_clock_edge edge, 250b63b36faSFred Richter enum lgdt3306a_tp_valid_polarity valid) 251b63b36faSFred Richter { 252b63b36faSFred Richter u8 val; 253b63b36faSFred Richter int ret; 254b63b36faSFred Richter 255b63b36faSFred Richter lg_dbg("edge=%d, valid=%d\n", edge, valid); 256b63b36faSFred Richter 257b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x0070, &val); 258b63b36faSFred Richter if (lg_chkerr(ret)) 259b63b36faSFred Richter goto fail; 260b63b36faSFred Richter 2618e8cd34eSMichael Ira Krufky val &= ~0x06; /* TPCLKPOL=0x04, TPVALPOL=0x02 */ 262b63b36faSFred Richter 263b63b36faSFred Richter if (edge == LGDT3306A_TPCLK_RISING_EDGE) 264b63b36faSFred Richter val |= 0x04; 265b63b36faSFred Richter if (valid == LGDT3306A_TP_VALID_HIGH) 266b63b36faSFred Richter val |= 0x02; 267b63b36faSFred Richter 268b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0070, val); 269b63b36faSFred Richter lg_chkerr(ret); 270b63b36faSFred Richter 271b63b36faSFred Richter fail: 272b63b36faSFred Richter return ret; 273b63b36faSFred Richter } 274b63b36faSFred Richter 275b63b36faSFred Richter static int lgdt3306a_mpeg_tristate(struct lgdt3306a_state *state, 276b63b36faSFred Richter int mode) 277b63b36faSFred Richter { 278b63b36faSFred Richter u8 val; 279b63b36faSFred Richter int ret; 280b63b36faSFred Richter 281b63b36faSFred Richter lg_dbg("(%d)\n", mode); 282b63b36faSFred Richter 283b63b36faSFred Richter if (mode) { 284b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x0070, &val); 285b63b36faSFred Richter if (lg_chkerr(ret)) 286b63b36faSFred Richter goto fail; 2874937ba94SMauro Carvalho Chehab val &= ~0xa8; /* Tristate bus; TPOUTEN=0x80, TPCLKOUTEN=0x20, TPDATAOUTEN=0x08 */ 288b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0070, val); 289b63b36faSFred Richter if (lg_chkerr(ret)) 290b63b36faSFred Richter goto fail; 291b63b36faSFred Richter 2928e8cd34eSMichael Ira Krufky ret = lgdt3306a_set_reg_bit(state, 0x0003, 6, 1); /* AGCIFOUTENB=0x40; 1=Disable IFAGC pin */ 293b63b36faSFred Richter if (lg_chkerr(ret)) 294b63b36faSFred Richter goto fail; 295b63b36faSFred Richter 296b63b36faSFred Richter } else { 2978e8cd34eSMichael Ira Krufky ret = lgdt3306a_set_reg_bit(state, 0x0003, 6, 0); /* enable IFAGC pin */ 298b63b36faSFred Richter if (lg_chkerr(ret)) 299b63b36faSFred Richter goto fail; 300b63b36faSFred Richter 301b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x0070, &val); 302b63b36faSFred Richter if (lg_chkerr(ret)) 303b63b36faSFred Richter goto fail; 304b63b36faSFred Richter 3054937ba94SMauro Carvalho Chehab val |= 0xa8; /* enable bus */ 306b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0070, val); 307b63b36faSFred Richter if (lg_chkerr(ret)) 308b63b36faSFred Richter goto fail; 309b63b36faSFred Richter } 310b63b36faSFred Richter 311b63b36faSFred Richter fail: 312b63b36faSFred Richter return ret; 313b63b36faSFred Richter } 314b63b36faSFred Richter 315b63b36faSFred Richter static int lgdt3306a_ts_bus_ctrl(struct dvb_frontend *fe, int acquire) 316b63b36faSFred Richter { 317b63b36faSFred Richter struct lgdt3306a_state *state = fe->demodulator_priv; 318b63b36faSFred Richter 319b63b36faSFred Richter lg_dbg("acquire=%d\n", acquire); 320b63b36faSFred Richter 321b63b36faSFred Richter return lgdt3306a_mpeg_tristate(state, acquire ? 0 : 1); 322b63b36faSFred Richter 323b63b36faSFred Richter } 324b63b36faSFred Richter 325b63b36faSFred Richter static int lgdt3306a_power(struct lgdt3306a_state *state, 326b63b36faSFred Richter int mode) 327b63b36faSFred Richter { 328b63b36faSFred Richter int ret; 329b63b36faSFred Richter 330b63b36faSFred Richter lg_dbg("(%d)\n", mode); 331b63b36faSFred Richter 332b63b36faSFred Richter if (mode == 0) { 3338e8cd34eSMichael Ira Krufky ret = lgdt3306a_set_reg_bit(state, 0x0000, 7, 0); /* into reset */ 334b63b36faSFred Richter if (lg_chkerr(ret)) 335b63b36faSFred Richter goto fail; 336b63b36faSFred Richter 3378e8cd34eSMichael Ira Krufky ret = lgdt3306a_set_reg_bit(state, 0x0000, 0, 0); /* power down */ 338b63b36faSFred Richter if (lg_chkerr(ret)) 339b63b36faSFred Richter goto fail; 340b63b36faSFred Richter 341b63b36faSFred Richter } else { 3428e8cd34eSMichael Ira Krufky ret = lgdt3306a_set_reg_bit(state, 0x0000, 7, 1); /* out of reset */ 343b63b36faSFred Richter if (lg_chkerr(ret)) 344b63b36faSFred Richter goto fail; 345b63b36faSFred Richter 3468e8cd34eSMichael Ira Krufky ret = lgdt3306a_set_reg_bit(state, 0x0000, 0, 1); /* power up */ 347b63b36faSFred Richter if (lg_chkerr(ret)) 348b63b36faSFred Richter goto fail; 349b63b36faSFred Richter } 350b63b36faSFred Richter 351b63b36faSFred Richter #ifdef DBG_DUMP 352b63b36faSFred Richter lgdt3306a_DumpAllRegs(state); 353b63b36faSFred Richter #endif 354b63b36faSFred Richter fail: 355b63b36faSFred Richter return ret; 356b63b36faSFred Richter } 357b63b36faSFred Richter 358b63b36faSFred Richter 359b63b36faSFred Richter static int lgdt3306a_set_vsb(struct lgdt3306a_state *state) 360b63b36faSFred Richter { 361b63b36faSFred Richter u8 val; 362b63b36faSFred Richter int ret; 363b63b36faSFred Richter 364b63b36faSFred Richter lg_dbg("\n"); 365b63b36faSFred Richter 3668e8cd34eSMichael Ira Krufky /* 0. Spectrum inversion detection manual; spectrum inverted */ 367b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x0002, &val); 3684937ba94SMauro Carvalho Chehab val &= 0xf7; /* SPECINVAUTO Off */ 3698e8cd34eSMichael Ira Krufky val |= 0x04; /* SPECINV On */ 370b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0002, val); 371b63b36faSFred Richter if (lg_chkerr(ret)) 372b63b36faSFred Richter goto fail; 373b63b36faSFred Richter 3748e8cd34eSMichael Ira Krufky /* 1. Selection of standard mode(0x08=QAM, 0x80=VSB) */ 375b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0008, 0x80); 376b63b36faSFred Richter if (lg_chkerr(ret)) 377b63b36faSFred Richter goto fail; 378b63b36faSFred Richter 3798e8cd34eSMichael Ira Krufky /* 2. Bandwidth mode for VSB(6MHz) */ 380b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x0009, &val); 3814937ba94SMauro Carvalho Chehab val &= 0xe3; 3824937ba94SMauro Carvalho Chehab val |= 0x0c; /* STDOPDETTMODE[2:0]=3 */ 383b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0009, val); 384b63b36faSFred Richter if (lg_chkerr(ret)) 385b63b36faSFred Richter goto fail; 386b63b36faSFred Richter 3878e8cd34eSMichael Ira Krufky /* 3. QAM mode detection mode(None) */ 388b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x0009, &val); 3894937ba94SMauro Carvalho Chehab val &= 0xfc; /* STDOPDETCMODE[1:0]=0 */ 390b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0009, val); 391b63b36faSFred Richter if (lg_chkerr(ret)) 392b63b36faSFred Richter goto fail; 393b63b36faSFred Richter 3948e8cd34eSMichael Ira Krufky /* 4. ADC sampling frequency rate(2x sampling) */ 3954937ba94SMauro Carvalho Chehab ret = lgdt3306a_read_reg(state, 0x000d, &val); 3964937ba94SMauro Carvalho Chehab val &= 0xbf; /* SAMPLING4XFEN=0 */ 3974937ba94SMauro Carvalho Chehab ret = lgdt3306a_write_reg(state, 0x000d, val); 398b63b36faSFred Richter if (lg_chkerr(ret)) 399b63b36faSFred Richter goto fail; 400b63b36faSFred Richter 4018e8cd34eSMichael Ira Krufky #if 0 4028e8cd34eSMichael Ira Krufky /* FGR - disable any AICC filtering, testing only */ 4038e8cd34eSMichael Ira Krufky 404b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0024, 0x00); 405b63b36faSFred Richter if (lg_chkerr(ret)) 406b63b36faSFred Richter goto fail; 407b63b36faSFred Richter 4088e8cd34eSMichael Ira Krufky /* AICCFIXFREQ0 NT N-1(Video rejection) */ 4094937ba94SMauro Carvalho Chehab ret = lgdt3306a_write_reg(state, 0x002e, 0x00); 4104937ba94SMauro Carvalho Chehab ret = lgdt3306a_write_reg(state, 0x002f, 0x00); 411b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0030, 0x00); 412b63b36faSFred Richter 4138e8cd34eSMichael Ira Krufky /* AICCFIXFREQ1 NT N-1(Audio rejection) */ 4144937ba94SMauro Carvalho Chehab ret = lgdt3306a_write_reg(state, 0x002b, 0x00); 4154937ba94SMauro Carvalho Chehab ret = lgdt3306a_write_reg(state, 0x002c, 0x00); 4164937ba94SMauro Carvalho Chehab ret = lgdt3306a_write_reg(state, 0x002d, 0x00); 417b63b36faSFred Richter 4188e8cd34eSMichael Ira Krufky /* AICCFIXFREQ2 NT Co-Channel(Video rejection) */ 419b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0028, 0x00); 420b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0029, 0x00); 4214937ba94SMauro Carvalho Chehab ret = lgdt3306a_write_reg(state, 0x002a, 0x00); 422b63b36faSFred Richter 4238e8cd34eSMichael Ira Krufky /* AICCFIXFREQ3 NT Co-Channel(Audio rejection) */ 424b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0025, 0x00); 425b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0026, 0x00); 426b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0027, 0x00); 427b63b36faSFred Richter 4288e8cd34eSMichael Ira Krufky #else 4298e8cd34eSMichael Ira Krufky /* FGR - this works well for HVR-1955,1975 */ 4308e8cd34eSMichael Ira Krufky 4318e8cd34eSMichael Ira Krufky /* 5. AICCOPMODE NT N-1 Adj. */ 432b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0024, 0x5A); 433b63b36faSFred Richter if (lg_chkerr(ret)) 434b63b36faSFred Richter goto fail; 435b63b36faSFred Richter 4368e8cd34eSMichael Ira Krufky /* AICCFIXFREQ0 NT N-1(Video rejection) */ 4374937ba94SMauro Carvalho Chehab ret = lgdt3306a_write_reg(state, 0x002e, 0x5A); 4384937ba94SMauro Carvalho Chehab ret = lgdt3306a_write_reg(state, 0x002f, 0x00); 439b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0030, 0x00); 440b63b36faSFred Richter 4418e8cd34eSMichael Ira Krufky /* AICCFIXFREQ1 NT N-1(Audio rejection) */ 4424937ba94SMauro Carvalho Chehab ret = lgdt3306a_write_reg(state, 0x002b, 0x36); 4434937ba94SMauro Carvalho Chehab ret = lgdt3306a_write_reg(state, 0x002c, 0x00); 4444937ba94SMauro Carvalho Chehab ret = lgdt3306a_write_reg(state, 0x002d, 0x00); 445b63b36faSFred Richter 4468e8cd34eSMichael Ira Krufky /* AICCFIXFREQ2 NT Co-Channel(Video rejection) */ 447b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0028, 0x2A); 448b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0029, 0x00); 4494937ba94SMauro Carvalho Chehab ret = lgdt3306a_write_reg(state, 0x002a, 0x00); 450b63b36faSFred Richter 4518e8cd34eSMichael Ira Krufky /* AICCFIXFREQ3 NT Co-Channel(Audio rejection) */ 452b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0025, 0x06); 453b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0026, 0x00); 454b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0027, 0x00); 455b63b36faSFred Richter #endif 456b63b36faSFred Richter 4574937ba94SMauro Carvalho Chehab ret = lgdt3306a_read_reg(state, 0x001e, &val); 4584937ba94SMauro Carvalho Chehab val &= 0x0f; 4594937ba94SMauro Carvalho Chehab val |= 0xa0; 4604937ba94SMauro Carvalho Chehab ret = lgdt3306a_write_reg(state, 0x001e, val); 461b63b36faSFred Richter 462b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0022, 0x08); 463b63b36faSFred Richter 464b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0023, 0xFF); 465b63b36faSFred Richter 4664937ba94SMauro Carvalho Chehab ret = lgdt3306a_read_reg(state, 0x211f, &val); 4674937ba94SMauro Carvalho Chehab val &= 0xef; 4684937ba94SMauro Carvalho Chehab ret = lgdt3306a_write_reg(state, 0x211f, val); 469b63b36faSFred Richter 470b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x2173, 0x01); 471b63b36faSFred Richter 472b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x1061, &val); 4734937ba94SMauro Carvalho Chehab val &= 0xf8; 474b63b36faSFred Richter val |= 0x04; 475b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x1061, val); 476b63b36faSFred Richter 4774937ba94SMauro Carvalho Chehab ret = lgdt3306a_read_reg(state, 0x103d, &val); 4784937ba94SMauro Carvalho Chehab val &= 0xcf; 4794937ba94SMauro Carvalho Chehab ret = lgdt3306a_write_reg(state, 0x103d, val); 480b63b36faSFred Richter 481b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x2122, 0x40); 482b63b36faSFred Richter 483b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x2141, &val); 4844937ba94SMauro Carvalho Chehab val &= 0x3f; 485b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x2141, val); 486b63b36faSFred Richter 487b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x2135, &val); 4884937ba94SMauro Carvalho Chehab val &= 0x0f; 489b63b36faSFred Richter val |= 0x70; 490b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x2135, val); 491b63b36faSFred Richter 492b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x0003, &val); 4934937ba94SMauro Carvalho Chehab val &= 0xf7; 494b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0003, val); 495b63b36faSFred Richter 4964937ba94SMauro Carvalho Chehab ret = lgdt3306a_read_reg(state, 0x001c, &val); 4974937ba94SMauro Carvalho Chehab val &= 0x7f; 4984937ba94SMauro Carvalho Chehab ret = lgdt3306a_write_reg(state, 0x001c, val); 499b63b36faSFred Richter 5008e8cd34eSMichael Ira Krufky /* 6. EQ step size */ 501b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x2179, &val); 5024937ba94SMauro Carvalho Chehab val &= 0xf8; 503b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x2179, val); 504b63b36faSFred Richter 5054937ba94SMauro Carvalho Chehab ret = lgdt3306a_read_reg(state, 0x217a, &val); 5064937ba94SMauro Carvalho Chehab val &= 0xf8; 5074937ba94SMauro Carvalho Chehab ret = lgdt3306a_write_reg(state, 0x217a, val); 508b63b36faSFred Richter 5098e8cd34eSMichael Ira Krufky /* 7. Reset */ 510b63b36faSFred Richter ret = lgdt3306a_soft_reset(state); 511b63b36faSFred Richter if (lg_chkerr(ret)) 512b63b36faSFred Richter goto fail; 513b63b36faSFred Richter 514b63b36faSFred Richter lg_dbg("complete\n"); 515b63b36faSFred Richter fail: 516b63b36faSFred Richter return ret; 517b63b36faSFred Richter } 518b63b36faSFred Richter 519b63b36faSFred Richter static int lgdt3306a_set_qam(struct lgdt3306a_state *state, int modulation) 520b63b36faSFred Richter { 521b63b36faSFred Richter u8 val; 522b63b36faSFred Richter int ret; 523b63b36faSFred Richter 524b63b36faSFred Richter lg_dbg("modulation=%d\n", modulation); 525b63b36faSFred Richter 5268e8cd34eSMichael Ira Krufky /* 1. Selection of standard mode(0x08=QAM, 0x80=VSB) */ 527b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0008, 0x08); 528b63b36faSFred Richter if (lg_chkerr(ret)) 529b63b36faSFred Richter goto fail; 530b63b36faSFred Richter 5318e8cd34eSMichael Ira Krufky /* 1a. Spectrum inversion detection to Auto */ 532b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x0002, &val); 5334937ba94SMauro Carvalho Chehab val &= 0xfb; /* SPECINV Off */ 5348e8cd34eSMichael Ira Krufky val |= 0x08; /* SPECINVAUTO On */ 535b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0002, val); 536b63b36faSFred Richter if (lg_chkerr(ret)) 537b63b36faSFred Richter goto fail; 538b63b36faSFred Richter 5398e8cd34eSMichael Ira Krufky /* 2. Bandwidth mode for QAM */ 540b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x0009, &val); 5414937ba94SMauro Carvalho Chehab val &= 0xe3; /* STDOPDETTMODE[2:0]=0 VSB Off */ 542b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0009, val); 543b63b36faSFred Richter if (lg_chkerr(ret)) 544b63b36faSFred Richter goto fail; 545b63b36faSFred Richter 5468e8cd34eSMichael Ira Krufky /* 3. : 64QAM/256QAM detection(manual, auto) */ 547b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x0009, &val); 5484937ba94SMauro Carvalho Chehab val &= 0xfc; 5498e8cd34eSMichael Ira Krufky val |= 0x02; /* STDOPDETCMODE[1:0]=1=Manual 2=Auto */ 550b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0009, val); 551b63b36faSFred Richter if (lg_chkerr(ret)) 552b63b36faSFred Richter goto fail; 553b63b36faSFred Richter 5548e8cd34eSMichael Ira Krufky /* 3a. : 64QAM/256QAM selection for manual */ 555b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x101a, &val); 5564937ba94SMauro Carvalho Chehab val &= 0xf8; 5578e8cd34eSMichael Ira Krufky if (modulation == QAM_64) 5588e8cd34eSMichael Ira Krufky val |= 0x02; /* QMDQMODE[2:0]=2=QAM64 */ 5598e8cd34eSMichael Ira Krufky else 5608e8cd34eSMichael Ira Krufky val |= 0x04; /* QMDQMODE[2:0]=4=QAM256 */ 5618e8cd34eSMichael Ira Krufky 562b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x101a, val); 563b63b36faSFred Richter if (lg_chkerr(ret)) 564b63b36faSFred Richter goto fail; 565b63b36faSFred Richter 5668e8cd34eSMichael Ira Krufky /* 4. ADC sampling frequency rate(4x sampling) */ 5674937ba94SMauro Carvalho Chehab ret = lgdt3306a_read_reg(state, 0x000d, &val); 5684937ba94SMauro Carvalho Chehab val &= 0xbf; 5698e8cd34eSMichael Ira Krufky val |= 0x40; /* SAMPLING4XFEN=1 */ 5704937ba94SMauro Carvalho Chehab ret = lgdt3306a_write_reg(state, 0x000d, val); 571b63b36faSFred Richter if (lg_chkerr(ret)) 572b63b36faSFred Richter goto fail; 573b63b36faSFred Richter 5748e8cd34eSMichael Ira Krufky /* 5. No AICC operation in QAM mode */ 575b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x0024, &val); 576b63b36faSFred Richter val &= 0x00; 577b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0024, val); 578b63b36faSFred Richter if (lg_chkerr(ret)) 579b63b36faSFred Richter goto fail; 580b63b36faSFred Richter 5818e8cd34eSMichael Ira Krufky /* 6. Reset */ 582b63b36faSFred Richter ret = lgdt3306a_soft_reset(state); 583b63b36faSFred Richter if (lg_chkerr(ret)) 584b63b36faSFred Richter goto fail; 585b63b36faSFred Richter 586b63b36faSFred Richter lg_dbg("complete\n"); 587b63b36faSFred Richter fail: 588b63b36faSFred Richter return ret; 589b63b36faSFred Richter } 590b63b36faSFred Richter 591b63b36faSFred Richter static int lgdt3306a_set_modulation(struct lgdt3306a_state *state, 592b63b36faSFred Richter struct dtv_frontend_properties *p) 593b63b36faSFred Richter { 594b63b36faSFred Richter int ret; 595b63b36faSFred Richter 596b63b36faSFred Richter lg_dbg("\n"); 597b63b36faSFred Richter 598b63b36faSFred Richter switch (p->modulation) { 599b63b36faSFred Richter case VSB_8: 600b63b36faSFred Richter ret = lgdt3306a_set_vsb(state); 601b63b36faSFred Richter break; 602b63b36faSFred Richter case QAM_64: 603b63b36faSFred Richter ret = lgdt3306a_set_qam(state, QAM_64); 604b63b36faSFred Richter break; 605b63b36faSFred Richter case QAM_256: 606b63b36faSFred Richter ret = lgdt3306a_set_qam(state, QAM_256); 607b63b36faSFred Richter break; 608b63b36faSFred Richter default: 609b63b36faSFred Richter return -EINVAL; 610b63b36faSFred Richter } 611b63b36faSFred Richter if (lg_chkerr(ret)) 612b63b36faSFred Richter goto fail; 613b63b36faSFred Richter 614b63b36faSFred Richter state->current_modulation = p->modulation; 615b63b36faSFred Richter 616b63b36faSFred Richter fail: 617b63b36faSFred Richter return ret; 618b63b36faSFred Richter } 619b63b36faSFred Richter 620b63b36faSFred Richter /* ------------------------------------------------------------------------ */ 621b63b36faSFred Richter 622b63b36faSFred Richter static int lgdt3306a_agc_setup(struct lgdt3306a_state *state, 623b63b36faSFred Richter struct dtv_frontend_properties *p) 624b63b36faSFred Richter { 6258e8cd34eSMichael Ira Krufky /* TODO: anything we want to do here??? */ 626b63b36faSFred Richter lg_dbg("\n"); 627b63b36faSFred Richter 628b63b36faSFred Richter switch (p->modulation) { 629b63b36faSFred Richter case VSB_8: 630b63b36faSFred Richter break; 631b63b36faSFred Richter case QAM_64: 632b63b36faSFred Richter case QAM_256: 633b63b36faSFred Richter break; 634b63b36faSFred Richter default: 635b63b36faSFred Richter return -EINVAL; 636b63b36faSFred Richter } 637b63b36faSFred Richter return 0; 638b63b36faSFred Richter } 639b63b36faSFred Richter 640b63b36faSFred Richter /* ------------------------------------------------------------------------ */ 641b63b36faSFred Richter 642b63b36faSFred Richter static int lgdt3306a_set_inversion(struct lgdt3306a_state *state, 643b63b36faSFred Richter int inversion) 644b63b36faSFred Richter { 645b63b36faSFred Richter int ret; 646b63b36faSFred Richter 647b63b36faSFred Richter lg_dbg("(%d)\n", inversion); 648b63b36faSFred Richter 649b63b36faSFred Richter ret = lgdt3306a_set_reg_bit(state, 0x0002, 2, inversion ? 1 : 0); 650b63b36faSFred Richter return ret; 651b63b36faSFred Richter } 652b63b36faSFred Richter 653b63b36faSFred Richter static int lgdt3306a_set_inversion_auto(struct lgdt3306a_state *state, 654b63b36faSFred Richter int enabled) 655b63b36faSFred Richter { 656b63b36faSFred Richter int ret; 657b63b36faSFred Richter 658b63b36faSFred Richter lg_dbg("(%d)\n", enabled); 659b63b36faSFred Richter 6608e8cd34eSMichael Ira Krufky /* 0=Manual 1=Auto(QAM only) */ 6618e8cd34eSMichael Ira Krufky ret = lgdt3306a_set_reg_bit(state, 0x0002, 3, enabled);/* SPECINVAUTO=0x04 */ 662b63b36faSFred Richter return ret; 663b63b36faSFred Richter } 664b63b36faSFred Richter 665b63b36faSFred Richter static int lgdt3306a_spectral_inversion(struct lgdt3306a_state *state, 666b63b36faSFred Richter struct dtv_frontend_properties *p, 667b63b36faSFred Richter int inversion) 668b63b36faSFred Richter { 669b63b36faSFred Richter int ret = 0; 670b63b36faSFred Richter 671b63b36faSFred Richter lg_dbg("(%d)\n", inversion); 6728e8cd34eSMichael Ira Krufky #if 0 6738e8cd34eSMichael Ira Krufky /* FGR - spectral_inversion defaults already set for VSB and QAM; can enable later if desired */ 674b63b36faSFred Richter 675b63b36faSFred Richter ret = lgdt3306a_set_inversion(state, inversion); 676b63b36faSFred Richter 677b63b36faSFred Richter switch (p->modulation) { 678b63b36faSFred Richter case VSB_8: 6798e8cd34eSMichael Ira Krufky ret = lgdt3306a_set_inversion_auto(state, 0); /* Manual only for VSB */ 680b63b36faSFred Richter break; 681b63b36faSFred Richter case QAM_64: 682b63b36faSFred Richter case QAM_256: 6838e8cd34eSMichael Ira Krufky ret = lgdt3306a_set_inversion_auto(state, 1); /* Auto ok for QAM */ 684b63b36faSFred Richter break; 685b63b36faSFred Richter default: 686b63b36faSFred Richter ret = -EINVAL; 687b63b36faSFred Richter } 688b63b36faSFred Richter #endif 689b63b36faSFred Richter return ret; 690b63b36faSFred Richter } 691b63b36faSFred Richter 692b63b36faSFred Richter static int lgdt3306a_set_if(struct lgdt3306a_state *state, 693b63b36faSFred Richter struct dtv_frontend_properties *p) 694b63b36faSFred Richter { 695b63b36faSFred Richter int ret; 696b63b36faSFred Richter u16 if_freq_khz; 697b63b36faSFred Richter u8 nco1, nco2; 698b63b36faSFred Richter 699b63b36faSFred Richter switch (p->modulation) { 700b63b36faSFred Richter case VSB_8: 701b63b36faSFred Richter if_freq_khz = state->cfg->vsb_if_khz; 702b63b36faSFred Richter break; 703b63b36faSFred Richter case QAM_64: 704b63b36faSFred Richter case QAM_256: 705b63b36faSFred Richter if_freq_khz = state->cfg->qam_if_khz; 706b63b36faSFred Richter break; 707b63b36faSFred Richter default: 708b63b36faSFred Richter return -EINVAL; 709b63b36faSFred Richter } 710b63b36faSFred Richter 711b63b36faSFred Richter switch (if_freq_khz) { 712b63b36faSFred Richter default: 713b63b36faSFred Richter lg_warn("IF=%d KHz is not supportted, 3250 assumed\n", if_freq_khz); 7148e8cd34eSMichael Ira Krufky /* fallthrough */ 7158e8cd34eSMichael Ira Krufky case 3250: /* 3.25Mhz */ 716b63b36faSFred Richter nco1 = 0x34; 717b63b36faSFred Richter nco2 = 0x00; 718b63b36faSFred Richter break; 7198e8cd34eSMichael Ira Krufky case 3500: /* 3.50Mhz */ 720b63b36faSFred Richter nco1 = 0x38; 721b63b36faSFred Richter nco2 = 0x00; 722b63b36faSFred Richter break; 7238e8cd34eSMichael Ira Krufky case 4000: /* 4.00Mhz */ 724b63b36faSFred Richter nco1 = 0x40; 725b63b36faSFred Richter nco2 = 0x00; 726b63b36faSFred Richter break; 7278e8cd34eSMichael Ira Krufky case 5000: /* 5.00Mhz */ 728b63b36faSFred Richter nco1 = 0x50; 729b63b36faSFred Richter nco2 = 0x00; 730b63b36faSFred Richter break; 7318e8cd34eSMichael Ira Krufky case 5380: /* 5.38Mhz */ 732b63b36faSFred Richter nco1 = 0x56; 733b63b36faSFred Richter nco2 = 0x14; 734b63b36faSFred Richter break; 735b63b36faSFred Richter } 736b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0010, nco1); 737b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0011, nco2); 738b63b36faSFred Richter 739b63b36faSFred Richter lg_dbg("if_freq=%d KHz->[%04x]\n", if_freq_khz, nco1<<8 | nco2); 740b63b36faSFred Richter 741b63b36faSFred Richter return 0; 742b63b36faSFred Richter } 743b63b36faSFred Richter 744b63b36faSFred Richter /* ------------------------------------------------------------------------ */ 745b63b36faSFred Richter 746b63b36faSFred Richter static int lgdt3306a_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) 747b63b36faSFred Richter { 748b63b36faSFred Richter struct lgdt3306a_state *state = fe->demodulator_priv; 749b63b36faSFred Richter 750b63b36faSFred Richter if (state->cfg->deny_i2c_rptr) { 751b63b36faSFred Richter lg_dbg("deny_i2c_rptr=%d\n", state->cfg->deny_i2c_rptr); 752b63b36faSFred Richter return 0; 753b63b36faSFred Richter } 754b63b36faSFred Richter lg_dbg("(%d)\n", enable); 755b63b36faSFred Richter 7568e8cd34eSMichael Ira Krufky return lgdt3306a_set_reg_bit(state, 0x0002, 7, enable ? 0 : 1); /* NI2CRPTEN=0x80 */ 757b63b36faSFred Richter } 758b63b36faSFred Richter 759b63b36faSFred Richter static int lgdt3306a_sleep(struct lgdt3306a_state *state) 760b63b36faSFred Richter { 761b63b36faSFred Richter int ret; 762b63b36faSFred Richter 763b63b36faSFred Richter lg_dbg("\n"); 7648e8cd34eSMichael Ira Krufky state->current_frequency = -1; /* force re-tune, when we wake */ 765b63b36faSFred Richter 7668e8cd34eSMichael Ira Krufky ret = lgdt3306a_mpeg_tristate(state, 1); /* disable data bus */ 767b63b36faSFred Richter if (lg_chkerr(ret)) 768b63b36faSFred Richter goto fail; 769b63b36faSFred Richter 7708e8cd34eSMichael Ira Krufky ret = lgdt3306a_power(state, 0); /* power down */ 771b63b36faSFred Richter lg_chkerr(ret); 772b63b36faSFred Richter 773b63b36faSFred Richter fail: 774b63b36faSFred Richter return 0; 775b63b36faSFred Richter } 776b63b36faSFred Richter 777b63b36faSFred Richter static int lgdt3306a_fe_sleep(struct dvb_frontend *fe) 778b63b36faSFred Richter { 779b63b36faSFred Richter struct lgdt3306a_state *state = fe->demodulator_priv; 780b63b36faSFred Richter 781b63b36faSFred Richter return lgdt3306a_sleep(state); 782b63b36faSFred Richter } 783b63b36faSFred Richter 784b63b36faSFred Richter static int lgdt3306a_init(struct dvb_frontend *fe) 785b63b36faSFred Richter { 786b63b36faSFred Richter struct lgdt3306a_state *state = fe->demodulator_priv; 787b63b36faSFred Richter u8 val; 788b63b36faSFred Richter int ret; 789b63b36faSFred Richter 790b63b36faSFred Richter lg_dbg("\n"); 791b63b36faSFred Richter 7928e8cd34eSMichael Ira Krufky /* 1. Normal operation mode */ 7938e8cd34eSMichael Ira Krufky ret = lgdt3306a_set_reg_bit(state, 0x0001, 0, 1); /* SIMFASTENB=0x01 */ 794b63b36faSFred Richter if (lg_chkerr(ret)) 795b63b36faSFred Richter goto fail; 796b63b36faSFred Richter 7978e8cd34eSMichael Ira Krufky /* 2. Spectrum inversion auto detection (Not valid for VSB) */ 798b63b36faSFred Richter ret = lgdt3306a_set_inversion_auto(state, 0); 799b63b36faSFred Richter if (lg_chkerr(ret)) 800b63b36faSFred Richter goto fail; 801b63b36faSFred Richter 8028e8cd34eSMichael Ira Krufky /* 3. Spectrum inversion(According to the tuner configuration) */ 803b63b36faSFred Richter ret = lgdt3306a_set_inversion(state, 1); 804b63b36faSFred Richter if (lg_chkerr(ret)) 805b63b36faSFred Richter goto fail; 806b63b36faSFred Richter 8078e8cd34eSMichael Ira Krufky /* 4. Peak-to-peak voltage of ADC input signal */ 8088e8cd34eSMichael Ira Krufky ret = lgdt3306a_set_reg_bit(state, 0x0004, 7, 1); /* ADCSEL1V=0x80=1Vpp; 0x00=2Vpp */ 809b63b36faSFred Richter if (lg_chkerr(ret)) 810b63b36faSFred Richter goto fail; 811b63b36faSFred Richter 8128e8cd34eSMichael Ira Krufky /* 5. ADC output data capture clock phase */ 8138e8cd34eSMichael Ira Krufky ret = lgdt3306a_set_reg_bit(state, 0x0004, 2, 0); /* 0=same phase as ADC clock */ 814b63b36faSFred Richter if (lg_chkerr(ret)) 815b63b36faSFred Richter goto fail; 816b63b36faSFred Richter 8178e8cd34eSMichael Ira Krufky /* 5a. ADC sampling clock source */ 8188e8cd34eSMichael Ira Krufky ret = lgdt3306a_set_reg_bit(state, 0x0004, 3, 0); /* ADCCLKPLLSEL=0x08; 0=use ext clock, not PLL */ 819b63b36faSFred Richter if (lg_chkerr(ret)) 820b63b36faSFred Richter goto fail; 821b63b36faSFred Richter 8228e8cd34eSMichael Ira Krufky /* 6. Automatic PLL set */ 8238e8cd34eSMichael Ira Krufky ret = lgdt3306a_set_reg_bit(state, 0x0005, 6, 0); /* PLLSETAUTO=0x40; 0=off */ 824b63b36faSFred Richter if (lg_chkerr(ret)) 825b63b36faSFred Richter goto fail; 826b63b36faSFred Richter 8278e8cd34eSMichael Ira Krufky if (state->cfg->xtalMHz == 24) { /* 24MHz */ 8288e8cd34eSMichael Ira Krufky /* 7. Frequency for PLL output(0x2564 for 192MHz for 24MHz) */ 829b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x0005, &val); 830b63b36faSFred Richter if (lg_chkerr(ret)) 831b63b36faSFred Richter goto fail; 8324937ba94SMauro Carvalho Chehab val &= 0xc0; 833b63b36faSFred Richter val |= 0x25; 834b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0005, val); 835b63b36faSFred Richter if (lg_chkerr(ret)) 836b63b36faSFred Richter goto fail; 837b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0006, 0x64); 838b63b36faSFred Richter if (lg_chkerr(ret)) 839b63b36faSFred Richter goto fail; 840b63b36faSFred Richter 8418e8cd34eSMichael Ira Krufky /* 8. ADC sampling frequency(0x180000 for 24MHz sampling) */ 8424937ba94SMauro Carvalho Chehab ret = lgdt3306a_read_reg(state, 0x000d, &val); 843b63b36faSFred Richter if (lg_chkerr(ret)) 844b63b36faSFred Richter goto fail; 8454937ba94SMauro Carvalho Chehab val &= 0xc0; 846b63b36faSFred Richter val |= 0x18; 8474937ba94SMauro Carvalho Chehab ret = lgdt3306a_write_reg(state, 0x000d, val); 848b63b36faSFred Richter if (lg_chkerr(ret)) 849b63b36faSFred Richter goto fail; 850b63b36faSFred Richter 8518e8cd34eSMichael Ira Krufky } else if (state->cfg->xtalMHz == 25) { /* 25MHz */ 8528e8cd34eSMichael Ira Krufky /* 7. Frequency for PLL output */ 853b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x0005, &val); 854b63b36faSFred Richter if (lg_chkerr(ret)) 855b63b36faSFred Richter goto fail; 8564937ba94SMauro Carvalho Chehab val &= 0xc0; 857b63b36faSFred Richter val |= 0x25; 858b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0005, val); 859b63b36faSFred Richter if (lg_chkerr(ret)) 860b63b36faSFred Richter goto fail; 861b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0006, 0x64); 862b63b36faSFred Richter if (lg_chkerr(ret)) 863b63b36faSFred Richter goto fail; 864b63b36faSFred Richter 8658e8cd34eSMichael Ira Krufky /* 8. ADC sampling frequency(0x190000 for 25MHz sampling) */ 8664937ba94SMauro Carvalho Chehab ret = lgdt3306a_read_reg(state, 0x000d, &val); 867b63b36faSFred Richter if (lg_chkerr(ret)) 868b63b36faSFred Richter goto fail; 8694937ba94SMauro Carvalho Chehab val &= 0xc0; 870b63b36faSFred Richter val |= 0x19; 8714937ba94SMauro Carvalho Chehab ret = lgdt3306a_write_reg(state, 0x000d, val); 872b63b36faSFred Richter if (lg_chkerr(ret)) 873b63b36faSFred Richter goto fail; 874b63b36faSFred Richter } else { 875b63b36faSFred Richter lg_err("Bad xtalMHz=%d\n", state->cfg->xtalMHz); 876b63b36faSFred Richter } 8778e8cd34eSMichael Ira Krufky #if 0 8784937ba94SMauro Carvalho Chehab ret = lgdt3306a_write_reg(state, 0x000e, 0x00); 8794937ba94SMauro Carvalho Chehab ret = lgdt3306a_write_reg(state, 0x000f, 0x00); 8808e8cd34eSMichael Ira Krufky #endif 881b63b36faSFred Richter 8828e8cd34eSMichael Ira Krufky /* 9. Center frequency of input signal of ADC */ 8838e8cd34eSMichael Ira Krufky ret = lgdt3306a_write_reg(state, 0x0010, 0x34); /* 3.25MHz */ 884b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0011, 0x00); 885b63b36faSFred Richter 8868e8cd34eSMichael Ira Krufky /* 10. Fixed gain error value */ 8878e8cd34eSMichael Ira Krufky ret = lgdt3306a_write_reg(state, 0x0014, 0); /* gain error=0 */ 888b63b36faSFred Richter 8898e8cd34eSMichael Ira Krufky /* 10a. VSB TR BW gear shift initial step */ 8904937ba94SMauro Carvalho Chehab ret = lgdt3306a_read_reg(state, 0x103c, &val); 8914937ba94SMauro Carvalho Chehab val &= 0x0f; 8928e8cd34eSMichael Ira Krufky val |= 0x20; /* SAMGSAUTOSTL_V[3:0] = 2 */ 8934937ba94SMauro Carvalho Chehab ret = lgdt3306a_write_reg(state, 0x103c, val); 894b63b36faSFred Richter 8958e8cd34eSMichael Ira Krufky /* 10b. Timing offset calibration in low temperature for VSB */ 8964937ba94SMauro Carvalho Chehab ret = lgdt3306a_read_reg(state, 0x103d, &val); 8974937ba94SMauro Carvalho Chehab val &= 0xfc; 898b63b36faSFred Richter val |= 0x03; 8994937ba94SMauro Carvalho Chehab ret = lgdt3306a_write_reg(state, 0x103d, val); 900b63b36faSFred Richter 9018e8cd34eSMichael Ira Krufky /* 10c. Timing offset calibration in low temperature for QAM */ 902b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x1036, &val); 9034937ba94SMauro Carvalho Chehab val &= 0xf0; 9044937ba94SMauro Carvalho Chehab val |= 0x0c; 905b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x1036, val); 906b63b36faSFred Richter 9078e8cd34eSMichael Ira Krufky /* 11. Using the imaginary part of CIR in CIR loading */ 9084937ba94SMauro Carvalho Chehab ret = lgdt3306a_read_reg(state, 0x211f, &val); 9094937ba94SMauro Carvalho Chehab val &= 0xef; /* do not use imaginary of CIR */ 9104937ba94SMauro Carvalho Chehab ret = lgdt3306a_write_reg(state, 0x211f, val); 911b63b36faSFred Richter 9128e8cd34eSMichael Ira Krufky /* 12. Control of no signal detector function */ 913b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x2849, &val); 9144937ba94SMauro Carvalho Chehab val &= 0xef; /* NOUSENOSIGDET=0, enable no signal detector */ 915b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x2849, val); 916b63b36faSFred Richter 9178e8cd34eSMichael Ira Krufky /* FGR - put demod in some known mode */ 918b63b36faSFred Richter ret = lgdt3306a_set_vsb(state); 919b63b36faSFred Richter 9208e8cd34eSMichael Ira Krufky /* 13. TP stream format */ 921b63b36faSFred Richter ret = lgdt3306a_mpeg_mode(state, state->cfg->mpeg_mode); 922b63b36faSFred Richter 9238e8cd34eSMichael Ira Krufky /* 14. disable output buses */ 924b63b36faSFred Richter ret = lgdt3306a_mpeg_tristate(state, 1); 925b63b36faSFred Richter 9268e8cd34eSMichael Ira Krufky /* 15. Sleep (in reset) */ 927b63b36faSFred Richter ret = lgdt3306a_sleep(state); 928b63b36faSFred Richter lg_chkerr(ret); 929b63b36faSFred Richter 930b63b36faSFred Richter fail: 931b63b36faSFred Richter return ret; 932b63b36faSFred Richter } 933b63b36faSFred Richter 934b63b36faSFred Richter static int lgdt3306a_set_parameters(struct dvb_frontend *fe) 935b63b36faSFred Richter { 936b63b36faSFred Richter struct dtv_frontend_properties *p = &fe->dtv_property_cache; 937b63b36faSFred Richter struct lgdt3306a_state *state = fe->demodulator_priv; 938b63b36faSFred Richter int ret; 939b63b36faSFred Richter 940b63b36faSFred Richter lg_dbg("(%d, %d)\n", p->frequency, p->modulation); 941b63b36faSFred Richter 942b63b36faSFred Richter if (state->current_frequency == p->frequency && 943b63b36faSFred Richter state->current_modulation == p->modulation) { 944b63b36faSFred Richter lg_dbg(" (already set, skipping ...)\n"); 945b63b36faSFred Richter return 0; 946b63b36faSFred Richter } 947b63b36faSFred Richter state->current_frequency = -1; 948b63b36faSFred Richter state->current_modulation = -1; 949b63b36faSFred Richter 9508e8cd34eSMichael Ira Krufky ret = lgdt3306a_power(state, 1); /* power up */ 951b63b36faSFred Richter if (lg_chkerr(ret)) 952b63b36faSFred Richter goto fail; 953b63b36faSFred Richter 954b63b36faSFred Richter if (fe->ops.tuner_ops.set_params) { 955b63b36faSFred Richter ret = fe->ops.tuner_ops.set_params(fe); 956b63b36faSFred Richter if (fe->ops.i2c_gate_ctrl) 957b63b36faSFred Richter fe->ops.i2c_gate_ctrl(fe, 0); 9588e8cd34eSMichael Ira Krufky #if 0 9598e8cd34eSMichael Ira Krufky if (lg_chkerr(ret)) 9608e8cd34eSMichael Ira Krufky goto fail; 9618e8cd34eSMichael Ira Krufky state->current_frequency = p->frequency; 9628e8cd34eSMichael Ira Krufky #endif 963b63b36faSFred Richter } 964b63b36faSFred Richter 965b63b36faSFred Richter ret = lgdt3306a_set_modulation(state, p); 966b63b36faSFred Richter if (lg_chkerr(ret)) 967b63b36faSFred Richter goto fail; 968b63b36faSFred Richter 969b63b36faSFred Richter ret = lgdt3306a_agc_setup(state, p); 970b63b36faSFred Richter if (lg_chkerr(ret)) 971b63b36faSFred Richter goto fail; 972b63b36faSFred Richter 973b63b36faSFred Richter ret = lgdt3306a_set_if(state, p); 974b63b36faSFred Richter if (lg_chkerr(ret)) 975b63b36faSFred Richter goto fail; 976b63b36faSFred Richter 977b63b36faSFred Richter ret = lgdt3306a_spectral_inversion(state, p, 978b63b36faSFred Richter state->cfg->spectral_inversion ? 1 : 0); 979b63b36faSFred Richter if (lg_chkerr(ret)) 980b63b36faSFred Richter goto fail; 981b63b36faSFred Richter 982b63b36faSFred Richter ret = lgdt3306a_mpeg_mode(state, state->cfg->mpeg_mode); 983b63b36faSFred Richter if (lg_chkerr(ret)) 984b63b36faSFred Richter goto fail; 985b63b36faSFred Richter 986b63b36faSFred Richter ret = lgdt3306a_mpeg_mode_polarity(state, 987b63b36faSFred Richter state->cfg->tpclk_edge, 988b63b36faSFred Richter state->cfg->tpvalid_polarity); 989b63b36faSFred Richter if (lg_chkerr(ret)) 990b63b36faSFred Richter goto fail; 991b63b36faSFred Richter 9928e8cd34eSMichael Ira Krufky ret = lgdt3306a_mpeg_tristate(state, 0); /* enable data bus */ 993b63b36faSFred Richter if (lg_chkerr(ret)) 994b63b36faSFred Richter goto fail; 995b63b36faSFred Richter 996b63b36faSFred Richter ret = lgdt3306a_soft_reset(state); 997b63b36faSFred Richter if (lg_chkerr(ret)) 998b63b36faSFred Richter goto fail; 999b63b36faSFred Richter 1000b63b36faSFred Richter #ifdef DBG_DUMP 1001b63b36faSFred Richter lgdt3306a_DumpAllRegs(state); 1002b63b36faSFred Richter #endif 1003b63b36faSFred Richter state->current_frequency = p->frequency; 1004b63b36faSFred Richter fail: 1005b63b36faSFred Richter return ret; 1006b63b36faSFred Richter } 1007b63b36faSFred Richter 1008b63b36faSFred Richter static int lgdt3306a_get_frontend(struct dvb_frontend *fe) 1009b63b36faSFred Richter { 1010b63b36faSFred Richter struct lgdt3306a_state *state = fe->demodulator_priv; 1011b63b36faSFred Richter struct dtv_frontend_properties *p = &fe->dtv_property_cache; 1012b63b36faSFred Richter 1013b63b36faSFred Richter lg_dbg("(%u, %d)\n", state->current_frequency, state->current_modulation); 1014b63b36faSFred Richter 1015b63b36faSFred Richter p->modulation = state->current_modulation; 1016b63b36faSFred Richter p->frequency = state->current_frequency; 1017b63b36faSFred Richter return 0; 1018b63b36faSFred Richter } 1019b63b36faSFred Richter 1020b63b36faSFred Richter static enum dvbfe_algo lgdt3306a_get_frontend_algo(struct dvb_frontend *fe) 1021b63b36faSFred Richter { 1022b63b36faSFred Richter #if 1 1023b63b36faSFred Richter return DVBFE_ALGO_CUSTOM; 1024b63b36faSFred Richter #else 1025b63b36faSFred Richter return DVBFE_ALGO_HW; 1026b63b36faSFred Richter #endif 1027b63b36faSFred Richter } 1028b63b36faSFred Richter 1029b63b36faSFred Richter /* ------------------------------------------------------------------------ */ 1030b63b36faSFred Richter static void lgdt3306a_monitor_vsb(struct lgdt3306a_state *state) 1031b63b36faSFred Richter { 1032b63b36faSFred Richter u8 val; 1033b63b36faSFred Richter int ret; 1034b63b36faSFred Richter u8 snrRef, maxPowerMan, nCombDet; 1035b63b36faSFred Richter u16 fbDlyCir; 1036b63b36faSFred Richter 10374937ba94SMauro Carvalho Chehab ret = lgdt3306a_read_reg(state, 0x21a1, &val); 10384937ba94SMauro Carvalho Chehab snrRef = val & 0x3f; 1039b63b36faSFred Richter 1040b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x2185, &maxPowerMan); 1041b63b36faSFred Richter 1042b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x2191, &val); 1043b63b36faSFred Richter nCombDet = (val & 0x80) >> 7; 1044b63b36faSFred Richter 1045b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x2180, &val); 1046b63b36faSFred Richter fbDlyCir = (val & 0x03) << 8; 1047b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x2181, &val); 1048b63b36faSFred Richter fbDlyCir |= val; 1049b63b36faSFred Richter 1050b63b36faSFred Richter lg_dbg("snrRef=%d maxPowerMan=0x%x nCombDet=%d fbDlyCir=0x%x\n", 1051b63b36faSFred Richter snrRef, maxPowerMan, nCombDet, fbDlyCir); 1052b63b36faSFred Richter 10538e8cd34eSMichael Ira Krufky /* Carrier offset sub loop bandwidth */ 1054b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x1061, &val); 10554937ba94SMauro Carvalho Chehab val &= 0xf8; 1056b63b36faSFred Richter if ((snrRef > 18) && (maxPowerMan > 0x68) && (nCombDet == 0x01) && ((fbDlyCir == 0x03FF) || (fbDlyCir < 0x6C))) { 10578e8cd34eSMichael Ira Krufky /* SNR is over 18dB and no ghosting */ 10588e8cd34eSMichael Ira Krufky val |= 0x00; /* final bandwidth = 0 */ 1059b63b36faSFred Richter } else { 10608e8cd34eSMichael Ira Krufky val |= 0x04; /* final bandwidth = 4 */ 1061b63b36faSFred Richter } 1062b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x1061, val); 1063b63b36faSFred Richter 10648e8cd34eSMichael Ira Krufky /* Adjust Notch Filter */ 1065b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x0024, &val); 10664937ba94SMauro Carvalho Chehab val &= 0x0f; 10678e8cd34eSMichael Ira Krufky if (nCombDet == 0) { /* Turn on the Notch Filter */ 1068b63b36faSFred Richter val |= 0x50; 1069b63b36faSFred Richter } 1070b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x0024, val); 1071b63b36faSFred Richter 10728e8cd34eSMichael Ira Krufky /* VSB Timing Recovery output normalization */ 10734937ba94SMauro Carvalho Chehab ret = lgdt3306a_read_reg(state, 0x103d, &val); 10744937ba94SMauro Carvalho Chehab val &= 0xcf; 1075b63b36faSFred Richter val |= 0x20; 10764937ba94SMauro Carvalho Chehab ret = lgdt3306a_write_reg(state, 0x103d, val); 1077b63b36faSFred Richter } 1078b63b36faSFred Richter 1079f883d603SMichael Ira Krufky static enum lgdt3306a_modulation lgdt3306a_check_oper_mode(struct lgdt3306a_state *state) 1080b63b36faSFred Richter { 1081b63b36faSFred Richter u8 val = 0; 1082b63b36faSFred Richter int ret; 1083b63b36faSFred Richter 1084b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x0081, &val); 1085b63b36faSFred Richter 1086b63b36faSFred Richter if (val & 0x80) { 1087b63b36faSFred Richter lg_dbg("VSB\n"); 10888e8cd34eSMichael Ira Krufky return LG3306_VSB; 1089b63b36faSFred Richter } 1090c714efe4SMichael Ira Krufky if (val & 0x08) { 10914937ba94SMauro Carvalho Chehab ret = lgdt3306a_read_reg(state, 0x00a6, &val); 1092b63b36faSFred Richter val = val >> 2; 1093b63b36faSFred Richter if (val & 0x01) { 1094b63b36faSFred Richter lg_dbg("QAM256\n"); 10958e8cd34eSMichael Ira Krufky return LG3306_QAM256; 1096b63b36faSFred Richter } else { 1097b63b36faSFred Richter lg_dbg("QAM64\n"); 10988e8cd34eSMichael Ira Krufky return LG3306_QAM64; 1099b63b36faSFred Richter } 1100b63b36faSFred Richter } 1101b63b36faSFred Richter lg_warn("UNKNOWN\n"); 11028e8cd34eSMichael Ira Krufky return LG3306_UNKNOWN_MODE; 1103b63b36faSFred Richter } 1104b63b36faSFred Richter 1105f883d603SMichael Ira Krufky static enum lgdt3306a_lock_status lgdt3306a_check_lock_status(struct lgdt3306a_state *state, 1106f883d603SMichael Ira Krufky enum lgdt3306a_lock_check whatLock) 1107b63b36faSFred Richter { 1108b63b36faSFred Richter u8 val = 0; 1109b63b36faSFred Richter int ret; 1110f883d603SMichael Ira Krufky enum lgdt3306a_modulation modeOper; 1111f883d603SMichael Ira Krufky enum lgdt3306a_lock_status lockStatus; 1112b63b36faSFred Richter 1113b63b36faSFred Richter modeOper = LG3306_UNKNOWN_MODE; 1114b63b36faSFred Richter 11158e8cd34eSMichael Ira Krufky switch (whatLock) { 1116b63b36faSFred Richter case LG3306_SYNC_LOCK: 1117b63b36faSFred Richter { 11184937ba94SMauro Carvalho Chehab ret = lgdt3306a_read_reg(state, 0x00a6, &val); 1119b63b36faSFred Richter 1120b63b36faSFred Richter if ((val & 0x80) == 0x80) 1121b63b36faSFred Richter lockStatus = LG3306_LOCK; 1122b63b36faSFred Richter else 1123b63b36faSFred Richter lockStatus = LG3306_UNLOCK; 1124b63b36faSFred Richter 1125b63b36faSFred Richter lg_dbg("SYNC_LOCK=%x\n", lockStatus); 1126b63b36faSFred Richter break; 1127b63b36faSFred Richter } 1128b63b36faSFred Richter case LG3306_AGC_LOCK: 1129b63b36faSFred Richter { 1130b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x0080, &val); 1131b63b36faSFred Richter 1132b63b36faSFred Richter if ((val & 0x40) == 0x40) 1133b63b36faSFred Richter lockStatus = LG3306_LOCK; 1134b63b36faSFred Richter else 1135b63b36faSFred Richter lockStatus = LG3306_UNLOCK; 1136b63b36faSFred Richter 1137b63b36faSFred Richter lg_dbg("AGC_LOCK=%x\n", lockStatus); 1138b63b36faSFred Richter break; 1139b63b36faSFred Richter } 1140b63b36faSFred Richter case LG3306_TR_LOCK: 1141b63b36faSFred Richter { 1142b63b36faSFred Richter modeOper = lgdt3306a_check_oper_mode(state); 11438e8cd34eSMichael Ira Krufky if ((modeOper == LG3306_QAM64) || (modeOper == LG3306_QAM256)) { 1144b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x1094, &val); 1145b63b36faSFred Richter 1146b63b36faSFred Richter if ((val & 0x80) == 0x80) 1147b63b36faSFred Richter lockStatus = LG3306_LOCK; 1148b63b36faSFred Richter else 1149b63b36faSFred Richter lockStatus = LG3306_UNLOCK; 11508e8cd34eSMichael Ira Krufky } else 1151b63b36faSFred Richter lockStatus = LG3306_UNKNOWN_LOCK; 1152b63b36faSFred Richter 1153b63b36faSFred Richter lg_dbg("TR_LOCK=%x\n", lockStatus); 1154b63b36faSFred Richter break; 1155b63b36faSFred Richter } 1156b63b36faSFred Richter case LG3306_FEC_LOCK: 1157b63b36faSFred Richter { 1158b63b36faSFred Richter modeOper = lgdt3306a_check_oper_mode(state); 11598e8cd34eSMichael Ira Krufky if ((modeOper == LG3306_QAM64) || (modeOper == LG3306_QAM256)) { 1160b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x0080, &val); 1161b63b36faSFred Richter 1162b63b36faSFred Richter if ((val & 0x10) == 0x10) 1163b63b36faSFred Richter lockStatus = LG3306_LOCK; 1164b63b36faSFred Richter else 1165b63b36faSFred Richter lockStatus = LG3306_UNLOCK; 11668e8cd34eSMichael Ira Krufky } else 1167b63b36faSFred Richter lockStatus = LG3306_UNKNOWN_LOCK; 1168b63b36faSFred Richter 1169b63b36faSFred Richter lg_dbg("FEC_LOCK=%x\n", lockStatus); 1170b63b36faSFred Richter break; 1171b63b36faSFred Richter } 1172b63b36faSFred Richter 1173b63b36faSFred Richter default: 1174b63b36faSFred Richter lockStatus = LG3306_UNKNOWN_LOCK; 1175b63b36faSFred Richter lg_warn("UNKNOWN whatLock=%d\n", whatLock); 1176b63b36faSFred Richter break; 1177b63b36faSFred Richter } 1178b63b36faSFred Richter 11798e8cd34eSMichael Ira Krufky return lockStatus; 1180b63b36faSFred Richter } 1181b63b36faSFred Richter 1182f883d603SMichael Ira Krufky static enum lgdt3306a_neverlock_status lgdt3306a_check_neverlock_status(struct lgdt3306a_state *state) 1183b63b36faSFred Richter { 1184b63b36faSFred Richter u8 val = 0; 1185b63b36faSFred Richter int ret; 1186f883d603SMichael Ira Krufky enum lgdt3306a_neverlock_status lockStatus; 1187b63b36faSFred Richter 1188b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x0080, &val); 1189f883d603SMichael Ira Krufky lockStatus = (enum lgdt3306a_neverlock_status)(val & 0x03); 1190b63b36faSFred Richter 1191b63b36faSFred Richter lg_dbg("NeverLock=%d", lockStatus); 1192b63b36faSFred Richter 11938e8cd34eSMichael Ira Krufky return lockStatus; 1194b63b36faSFred Richter } 1195b63b36faSFred Richter 1196b63b36faSFred Richter static void lgdt3306a_pre_monitoring(struct lgdt3306a_state *state) 1197b63b36faSFred Richter { 1198b63b36faSFred Richter u8 val = 0; 1199b63b36faSFred Richter int ret; 1200b63b36faSFred Richter u8 currChDiffACQ, snrRef, mainStrong, aiccrejStatus; 1201b63b36faSFred Richter 12028e8cd34eSMichael Ira Krufky /* Channel variation */ 12034937ba94SMauro Carvalho Chehab ret = lgdt3306a_read_reg(state, 0x21bc, &currChDiffACQ); 1204b63b36faSFred Richter 12058e8cd34eSMichael Ira Krufky /* SNR of Frame sync */ 12064937ba94SMauro Carvalho Chehab ret = lgdt3306a_read_reg(state, 0x21a1, &val); 12074937ba94SMauro Carvalho Chehab snrRef = val & 0x3f; 1208b63b36faSFred Richter 12098e8cd34eSMichael Ira Krufky /* Strong Main CIR */ 1210b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x2199, &val); 1211b63b36faSFred Richter mainStrong = (val & 0x40) >> 6; 1212b63b36faSFred Richter 1213b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x0090, &val); 12144937ba94SMauro Carvalho Chehab aiccrejStatus = (val & 0xf0) >> 4; 1215b63b36faSFred Richter 1216b63b36faSFred Richter lg_dbg("snrRef=%d mainStrong=%d aiccrejStatus=%d currChDiffACQ=0x%x\n", 1217b63b36faSFred Richter snrRef, mainStrong, aiccrejStatus, currChDiffACQ); 1218b63b36faSFred Richter 12198e8cd34eSMichael Ira Krufky #if 0 12208e8cd34eSMichael Ira Krufky if ((mainStrong == 0) && (currChDiffACQ > 0x70)) /* Dynamic ghost exists */ 12218e8cd34eSMichael Ira Krufky #endif 12228e8cd34eSMichael Ira Krufky if (mainStrong == 0) { 1223b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x2135, &val); 12244937ba94SMauro Carvalho Chehab val &= 0x0f; 12254937ba94SMauro Carvalho Chehab val |= 0xa0; 1226b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x2135, val); 1227b63b36faSFred Richter 1228b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x2141, &val); 12294937ba94SMauro Carvalho Chehab val &= 0x3f; 1230b63b36faSFred Richter val |= 0x80; 1231b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x2141, val); 1232b63b36faSFred Richter 1233b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x2122, 0x70); 12348e8cd34eSMichael Ira Krufky } else { /* Weak ghost or static channel */ 1235b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x2135, &val); 12364937ba94SMauro Carvalho Chehab val &= 0x0f; 1237b63b36faSFred Richter val |= 0x70; 1238b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x2135, val); 1239b63b36faSFred Richter 1240b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x2141, &val); 12414937ba94SMauro Carvalho Chehab val &= 0x3f; 1242b63b36faSFred Richter val |= 0x40; 1243b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x2141, val); 1244b63b36faSFred Richter 1245b63b36faSFred Richter ret = lgdt3306a_write_reg(state, 0x2122, 0x40); 1246b63b36faSFred Richter } 1247b63b36faSFred Richter 1248b63b36faSFred Richter } 1249b63b36faSFred Richter 1250f883d603SMichael Ira Krufky static enum lgdt3306a_lock_status lgdt3306a_sync_lock_poll(struct lgdt3306a_state *state) 1251b63b36faSFred Richter { 1252f883d603SMichael Ira Krufky enum lgdt3306a_lock_status syncLockStatus = LG3306_UNLOCK; 1253b63b36faSFred Richter int i; 1254b63b36faSFred Richter 1255b63b36faSFred Richter for (i = 0; i < 2; i++) { 1256b63b36faSFred Richter msleep(30); 1257b63b36faSFred Richter 1258b63b36faSFred Richter syncLockStatus = lgdt3306a_check_lock_status(state, LG3306_SYNC_LOCK); 1259b63b36faSFred Richter 1260b63b36faSFred Richter if (syncLockStatus == LG3306_LOCK) { 1261b63b36faSFred Richter lg_dbg("locked(%d)\n", i); 12628e8cd34eSMichael Ira Krufky return LG3306_LOCK; 1263b63b36faSFred Richter } 1264b63b36faSFred Richter } 1265b63b36faSFred Richter lg_dbg("not locked\n"); 12668e8cd34eSMichael Ira Krufky return LG3306_UNLOCK; 1267b63b36faSFred Richter } 1268b63b36faSFred Richter 1269f883d603SMichael Ira Krufky static enum lgdt3306a_lock_status lgdt3306a_fec_lock_poll(struct lgdt3306a_state *state) 1270b63b36faSFred Richter { 1271f883d603SMichael Ira Krufky enum lgdt3306a_lock_status FECLockStatus = LG3306_UNLOCK; 1272b63b36faSFred Richter int i; 1273b63b36faSFred Richter 1274b63b36faSFred Richter for (i = 0; i < 2; i++) { 1275b63b36faSFred Richter msleep(30); 1276b63b36faSFred Richter 1277b63b36faSFred Richter FECLockStatus = lgdt3306a_check_lock_status(state, LG3306_FEC_LOCK); 1278b63b36faSFred Richter 1279b63b36faSFred Richter if (FECLockStatus == LG3306_LOCK) { 1280b63b36faSFred Richter lg_dbg("locked(%d)\n", i); 12818e8cd34eSMichael Ira Krufky return FECLockStatus; 1282b63b36faSFred Richter } 1283b63b36faSFred Richter } 1284b63b36faSFred Richter lg_dbg("not locked\n"); 12858e8cd34eSMichael Ira Krufky return FECLockStatus; 1286b63b36faSFred Richter } 1287b63b36faSFred Richter 1288f883d603SMichael Ira Krufky static enum lgdt3306a_neverlock_status lgdt3306a_neverlock_poll(struct lgdt3306a_state *state) 1289b63b36faSFred Richter { 1290f883d603SMichael Ira Krufky enum lgdt3306a_neverlock_status NLLockStatus = LG3306_NL_FAIL; 1291b63b36faSFred Richter int i; 1292b63b36faSFred Richter 1293b63b36faSFred Richter for (i = 0; i < 5; i++) { 1294b63b36faSFred Richter msleep(30); 1295b63b36faSFred Richter 1296b63b36faSFred Richter NLLockStatus = lgdt3306a_check_neverlock_status(state); 1297b63b36faSFred Richter 1298b63b36faSFred Richter if (NLLockStatus == LG3306_NL_LOCK) { 1299b63b36faSFred Richter lg_dbg("NL_LOCK(%d)\n", i); 13008e8cd34eSMichael Ira Krufky return NLLockStatus; 1301b63b36faSFred Richter } 1302b63b36faSFred Richter } 1303b63b36faSFred Richter lg_dbg("NLLockStatus=%d\n", NLLockStatus); 13048e8cd34eSMichael Ira Krufky return NLLockStatus; 1305b63b36faSFred Richter } 1306b63b36faSFred Richter 1307b63b36faSFred Richter static u8 lgdt3306a_get_packet_error(struct lgdt3306a_state *state) 1308b63b36faSFred Richter { 1309b63b36faSFred Richter u8 val; 1310b63b36faSFred Richter int ret; 1311b63b36faSFred Richter 13124937ba94SMauro Carvalho Chehab ret = lgdt3306a_read_reg(state, 0x00fa, &val); 1313b63b36faSFred Richter 13148e8cd34eSMichael Ira Krufky return val; 1315b63b36faSFred Richter } 1316b63b36faSFred Richter 1317b63b36faSFred Richter static u32 log10_x1000(u32 x) 1318b63b36faSFred Richter { 1319b63b36faSFred Richter static u32 valx_x10[] = { 10, 11, 13, 15, 17, 20, 25, 33, 41, 50, 59, 73, 87, 100 }; 1320b63b36faSFred Richter static u32 log10x_x1000[] = { 0, 41, 114, 176, 230, 301, 398, 518, 613, 699, 771, 863, 939, 1000 }; 1321b63b36faSFred Richter static u32 nelems = sizeof(valx_x10)/sizeof(valx_x10[0]); 1322*a132fef8SMauro Carvalho Chehab u32 diff_val, step_val, step_log10; 1323b63b36faSFred Richter u32 log_val = 0; 1324b63b36faSFred Richter u32 i; 1325b63b36faSFred Richter 1326b63b36faSFred Richter if (x <= 0) 13278e8cd34eSMichael Ira Krufky return -1000000; /* signal error */ 1328b63b36faSFred Richter 1329b63b36faSFred Richter if (x < 10) { 1330b63b36faSFred Richter while (x < 10) { 1331b63b36faSFred Richter x = x * 10; 1332b63b36faSFred Richter log_val--; 1333b63b36faSFred Richter } 1334b63b36faSFred Richter } else if (x == 10) { 13358e8cd34eSMichael Ira Krufky return 0; /* log(1)=0 */ 1336b63b36faSFred Richter } else { 1337b63b36faSFred Richter while (x >= 100) { 1338b63b36faSFred Richter x = x / 10; 1339b63b36faSFred Richter log_val++; 1340b63b36faSFred Richter } 1341b63b36faSFred Richter } 1342b63b36faSFred Richter log_val *= 1000; 1343b63b36faSFred Richter 13448e8cd34eSMichael Ira Krufky if (x == 10) /* was our input an exact multiple of 10 */ 13458e8cd34eSMichael Ira Krufky return log_val; /* don't need to interpolate */ 1346b63b36faSFred Richter 13478e8cd34eSMichael Ira Krufky /* find our place on the log curve */ 1348b63b36faSFred Richter for (i = 1; i < nelems; i++) { 13498e8cd34eSMichael Ira Krufky if (valx_x10[i] >= x) 13508e8cd34eSMichael Ira Krufky break; 1351b63b36faSFred Richter } 1352*a132fef8SMauro Carvalho Chehab if (i == nelems) 1353*a132fef8SMauro Carvalho Chehab return log_val + log10x_x1000[i - 1]; 1354b63b36faSFred Richter 1355*a132fef8SMauro Carvalho Chehab diff_val = x - valx_x10[i-1]; 1356*a132fef8SMauro Carvalho Chehab step_val = valx_x10[i] - valx_x10[i - 1]; 1357*a132fef8SMauro Carvalho Chehab step_log10 = log10x_x1000[i] - log10x_x1000[i - 1]; 1358*a132fef8SMauro Carvalho Chehab 13598e8cd34eSMichael Ira Krufky /* do a linear interpolation to get in-between values */ 13608e8cd34eSMichael Ira Krufky return log_val + log10x_x1000[i - 1] + 13618e8cd34eSMichael Ira Krufky ((diff_val*step_log10) / step_val); 1362b63b36faSFred Richter } 1363b63b36faSFred Richter 1364b63b36faSFred Richter static u32 lgdt3306a_calculate_snr_x100(struct lgdt3306a_state *state) 1365b63b36faSFred Richter { 1366b63b36faSFred Richter u32 mse; /* Mean-Square Error */ 1367b63b36faSFred Richter u32 pwr; /* Constelation power */ 1368b63b36faSFred Richter u32 snr_x100; 1369b63b36faSFred Richter 13704937ba94SMauro Carvalho Chehab mse = (read_reg(state, 0x00ec) << 8) | 13714937ba94SMauro Carvalho Chehab (read_reg(state, 0x00ed)); 13724937ba94SMauro Carvalho Chehab pwr = (read_reg(state, 0x00e8) << 8) | 13734937ba94SMauro Carvalho Chehab (read_reg(state, 0x00e9)); 1374b63b36faSFred Richter 1375b63b36faSFred Richter if (mse == 0) /* no signal */ 1376b63b36faSFred Richter return 0; 1377b63b36faSFred Richter 1378b63b36faSFred Richter snr_x100 = log10_x1000((pwr * 10000) / mse) - 3000; 1379b63b36faSFred Richter lg_dbg("mse=%u, pwr=%u, snr_x100=%d\n", mse, pwr, snr_x100); 1380b63b36faSFred Richter 1381b63b36faSFred Richter return snr_x100; 1382b63b36faSFred Richter } 1383b63b36faSFred Richter 1384f883d603SMichael Ira Krufky static enum lgdt3306a_lock_status lgdt3306a_vsb_lock_poll(struct lgdt3306a_state *state) 1385b63b36faSFred Richter { 1386b63b36faSFred Richter u8 cnt = 0; 1387b63b36faSFred Richter u8 packet_error; 1388b63b36faSFred Richter u32 snr; 1389b63b36faSFred Richter 1390b63b36faSFred Richter while (1) { 1391b63b36faSFred Richter if (lgdt3306a_sync_lock_poll(state) == LG3306_UNLOCK) { 1392b63b36faSFred Richter lg_dbg("no sync lock!\n"); 13938e8cd34eSMichael Ira Krufky return LG3306_UNLOCK; 1394b63b36faSFred Richter } else { 1395b63b36faSFred Richter msleep(20); 1396b63b36faSFred Richter lgdt3306a_pre_monitoring(state); 1397b63b36faSFred Richter 1398b63b36faSFred Richter packet_error = lgdt3306a_get_packet_error(state); 1399b63b36faSFred Richter snr = lgdt3306a_calculate_snr_x100(state); 14008e8cd34eSMichael Ira Krufky lg_dbg("cnt=%d errors=%d snr=%d\n", 14018e8cd34eSMichael Ira Krufky cnt, packet_error, snr); 1402b63b36faSFred Richter 14038e8cd34eSMichael Ira Krufky if ((snr < 1500) || (packet_error >= 0xff)) 1404b63b36faSFred Richter cnt++; 14058e8cd34eSMichael Ira Krufky else 14068e8cd34eSMichael Ira Krufky return LG3306_LOCK; 1407b63b36faSFred Richter 1408b63b36faSFred Richter if (cnt >= 10) { 1409b63b36faSFred Richter lg_dbg("not locked!\n"); 14108e8cd34eSMichael Ira Krufky return LG3306_UNLOCK; 1411b63b36faSFred Richter } 1412b63b36faSFred Richter } 1413b63b36faSFred Richter } 14148e8cd34eSMichael Ira Krufky return LG3306_UNLOCK; 1415b63b36faSFred Richter } 1416b63b36faSFred Richter 1417f883d603SMichael Ira Krufky static enum lgdt3306a_lock_status lgdt3306a_qam_lock_poll(struct lgdt3306a_state *state) 1418b63b36faSFred Richter { 1419b63b36faSFred Richter u8 cnt = 0; 1420b63b36faSFred Richter u8 packet_error; 1421b63b36faSFred Richter u32 snr; 1422b63b36faSFred Richter 1423b63b36faSFred Richter while (1) { 1424b63b36faSFred Richter if (lgdt3306a_fec_lock_poll(state) == LG3306_UNLOCK) { 1425b63b36faSFred Richter lg_dbg("no fec lock!\n"); 14268e8cd34eSMichael Ira Krufky return LG3306_UNLOCK; 1427b63b36faSFred Richter } else { 1428b63b36faSFred Richter msleep(20); 1429b63b36faSFred Richter 1430b63b36faSFred Richter packet_error = lgdt3306a_get_packet_error(state); 1431b63b36faSFred Richter snr = lgdt3306a_calculate_snr_x100(state); 14328e8cd34eSMichael Ira Krufky lg_dbg("cnt=%d errors=%d snr=%d\n", 14338e8cd34eSMichael Ira Krufky cnt, packet_error, snr); 1434b63b36faSFred Richter 14358e8cd34eSMichael Ira Krufky if ((snr < 1500) || (packet_error >= 0xff)) 1436b63b36faSFred Richter cnt++; 14378e8cd34eSMichael Ira Krufky else 14388e8cd34eSMichael Ira Krufky return LG3306_LOCK; 1439b63b36faSFred Richter 1440b63b36faSFred Richter if (cnt >= 10) { 1441b63b36faSFred Richter lg_dbg("not locked!\n"); 14428e8cd34eSMichael Ira Krufky return LG3306_UNLOCK; 1443b63b36faSFred Richter } 1444b63b36faSFred Richter } 1445b63b36faSFred Richter } 14468e8cd34eSMichael Ira Krufky return LG3306_UNLOCK; 1447b63b36faSFred Richter } 1448b63b36faSFred Richter 1449b63b36faSFred Richter static int lgdt3306a_read_status(struct dvb_frontend *fe, fe_status_t *status) 1450b63b36faSFred Richter { 1451b63b36faSFred Richter struct lgdt3306a_state *state = fe->demodulator_priv; 1452b63b36faSFred Richter u16 strength = 0; 14538e8cd34eSMichael Ira Krufky int ret = 0; 14548e8cd34eSMichael Ira Krufky 1455b63b36faSFred Richter if (fe->ops.tuner_ops.get_rf_strength) { 1456b63b36faSFred Richter ret = fe->ops.tuner_ops.get_rf_strength(fe, &strength); 1457b63b36faSFred Richter if (ret == 0) { 1458b63b36faSFred Richter lg_dbg("strength=%d\n", strength); 1459b63b36faSFred Richter } else { 1460b63b36faSFred Richter lg_dbg("fe->ops.tuner_ops.get_rf_strength() failed\n"); 1461b63b36faSFred Richter } 1462b63b36faSFred Richter } 1463b63b36faSFred Richter 1464b63b36faSFred Richter *status = 0; 1465b63b36faSFred Richter if (lgdt3306a_neverlock_poll(state) == LG3306_NL_LOCK) { 1466b63b36faSFred Richter *status |= FE_HAS_SIGNAL; 1467b63b36faSFred Richter *status |= FE_HAS_CARRIER; 1468b63b36faSFred Richter 1469b63b36faSFred Richter switch (state->current_modulation) { 1470b63b36faSFred Richter case QAM_256: 1471b63b36faSFred Richter case QAM_64: 1472b63b36faSFred Richter if (lgdt3306a_qam_lock_poll(state) == LG3306_LOCK) { 1473b63b36faSFred Richter *status |= FE_HAS_VITERBI; 1474b63b36faSFred Richter *status |= FE_HAS_SYNC; 1475b63b36faSFred Richter 1476b63b36faSFred Richter *status |= FE_HAS_LOCK; 1477b63b36faSFred Richter } 1478b63b36faSFred Richter break; 1479b63b36faSFred Richter case VSB_8: 1480b63b36faSFred Richter if (lgdt3306a_vsb_lock_poll(state) == LG3306_LOCK) { 1481b63b36faSFred Richter *status |= FE_HAS_VITERBI; 1482b63b36faSFred Richter *status |= FE_HAS_SYNC; 1483b63b36faSFred Richter 1484b63b36faSFred Richter *status |= FE_HAS_LOCK; 1485b63b36faSFred Richter 1486b63b36faSFred Richter lgdt3306a_monitor_vsb(state); 1487b63b36faSFred Richter } 1488b63b36faSFred Richter break; 1489b63b36faSFred Richter default: 1490b63b36faSFred Richter ret = -EINVAL; 1491b63b36faSFred Richter } 1492b63b36faSFred Richter } 1493b63b36faSFred Richter return ret; 1494b63b36faSFred Richter } 1495b63b36faSFred Richter 1496b63b36faSFred Richter 1497b63b36faSFred Richter static int lgdt3306a_read_snr(struct dvb_frontend *fe, u16 *snr) 1498b63b36faSFred Richter { 1499b63b36faSFred Richter struct lgdt3306a_state *state = fe->demodulator_priv; 1500b63b36faSFred Richter 1501b63b36faSFred Richter state->snr = lgdt3306a_calculate_snr_x100(state); 1502b63b36faSFred Richter /* report SNR in dB * 10 */ 1503b63b36faSFred Richter *snr = state->snr/10; 1504b63b36faSFred Richter 1505b63b36faSFred Richter return 0; 1506b63b36faSFred Richter } 1507b63b36faSFred Richter 1508b63b36faSFred Richter static int lgdt3306a_read_signal_strength(struct dvb_frontend *fe, 1509b63b36faSFred Richter u16 *strength) 1510b63b36faSFred Richter { 1511b63b36faSFred Richter /* 1512b63b36faSFred Richter * Calculate some sort of "strength" from SNR 1513b63b36faSFred Richter */ 1514b63b36faSFred Richter struct lgdt3306a_state *state = fe->demodulator_priv; 15158e8cd34eSMichael Ira Krufky u16 snr; /* snr_x10 */ 1516b63b36faSFred Richter int ret; 15178e8cd34eSMichael Ira Krufky u32 ref_snr; /* snr*100 */ 1518b63b36faSFred Richter u32 str; 1519b63b36faSFred Richter 1520b63b36faSFred Richter *strength = 0; 1521b63b36faSFred Richter 1522b63b36faSFred Richter switch (state->current_modulation) { 1523b63b36faSFred Richter case VSB_8: 15248e8cd34eSMichael Ira Krufky ref_snr = 1600; /* 16dB */ 1525b63b36faSFred Richter break; 1526b63b36faSFred Richter case QAM_64: 15278e8cd34eSMichael Ira Krufky ref_snr = 2200; /* 22dB */ 1528b63b36faSFred Richter break; 1529b63b36faSFred Richter case QAM_256: 15308e8cd34eSMichael Ira Krufky ref_snr = 2800; /* 28dB */ 1531b63b36faSFred Richter break; 1532b63b36faSFred Richter default: 1533b63b36faSFred Richter return -EINVAL; 1534b63b36faSFred Richter } 1535b63b36faSFred Richter 1536b63b36faSFred Richter ret = fe->ops.read_snr(fe, &snr); 1537b63b36faSFred Richter if (lg_chkerr(ret)) 1538b63b36faSFred Richter goto fail; 1539b63b36faSFred Richter 1540b63b36faSFred Richter if (state->snr <= (ref_snr - 100)) 1541b63b36faSFred Richter str = 0; 1542b63b36faSFred Richter else if (state->snr <= ref_snr) 15438e8cd34eSMichael Ira Krufky str = (0xffff * 65) / 100; /* 65% */ 1544b63b36faSFred Richter else { 1545b63b36faSFred Richter str = state->snr - ref_snr; 1546b63b36faSFred Richter str /= 50; 15478e8cd34eSMichael Ira Krufky str += 78; /* 78%-100% */ 1548b63b36faSFred Richter if (str > 100) 1549b63b36faSFred Richter str = 100; 1550b63b36faSFred Richter str = (0xffff * str) / 100; 1551b63b36faSFred Richter } 1552b63b36faSFred Richter *strength = (u16)str; 1553b63b36faSFred Richter lg_dbg("strength=%u\n", *strength); 1554b63b36faSFred Richter 1555b63b36faSFred Richter fail: 1556b63b36faSFred Richter return ret; 1557b63b36faSFred Richter } 1558b63b36faSFred Richter 1559b63b36faSFred Richter /* ------------------------------------------------------------------------ */ 1560b63b36faSFred Richter 1561b63b36faSFred Richter static int lgdt3306a_read_ber(struct dvb_frontend *fe, u32 *ber) 1562b63b36faSFred Richter { 1563b63b36faSFred Richter struct lgdt3306a_state *state = fe->demodulator_priv; 1564b63b36faSFred Richter u32 tmp; 1565b63b36faSFred Richter 1566b63b36faSFred Richter *ber = 0; 1567b63b36faSFred Richter #if 1 15688e8cd34eSMichael Ira Krufky /* FGR - BUGBUG - I don't know what value is expected by dvb_core 15698e8cd34eSMichael Ira Krufky * what is the scale of the value?? */ 15704937ba94SMauro Carvalho Chehab tmp = read_reg(state, 0x00fc); /* NBERVALUE[24-31] */ 15714937ba94SMauro Carvalho Chehab tmp = (tmp << 8) | read_reg(state, 0x00fd); /* NBERVALUE[16-23] */ 15724937ba94SMauro Carvalho Chehab tmp = (tmp << 8) | read_reg(state, 0x00fe); /* NBERVALUE[8-15] */ 15734937ba94SMauro Carvalho Chehab tmp = (tmp << 8) | read_reg(state, 0x00ff); /* NBERVALUE[0-7] */ 1574b63b36faSFred Richter *ber = tmp; 1575b63b36faSFred Richter lg_dbg("ber=%u\n", tmp); 1576b63b36faSFred Richter #endif 1577b63b36faSFred Richter return 0; 1578b63b36faSFred Richter } 1579b63b36faSFred Richter 1580b63b36faSFred Richter static int lgdt3306a_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) 1581b63b36faSFred Richter { 1582b63b36faSFred Richter struct lgdt3306a_state *state = fe->demodulator_priv; 1583b63b36faSFred Richter 1584b63b36faSFred Richter *ucblocks = 0; 1585b63b36faSFred Richter #if 1 15868e8cd34eSMichael Ira Krufky /* FGR - BUGBUG - I don't know what value is expected by dvb_core 15878e8cd34eSMichael Ira Krufky * what happens when value wraps? */ 15884937ba94SMauro Carvalho Chehab *ucblocks = read_reg(state, 0x00f4); /* TPIFTPERRCNT[0-7] */ 1589b63b36faSFred Richter lg_dbg("ucblocks=%u\n", *ucblocks); 1590b63b36faSFred Richter #endif 1591b63b36faSFred Richter 1592b63b36faSFred Richter return 0; 1593b63b36faSFred Richter } 1594b63b36faSFred Richter 1595b63b36faSFred Richter static int lgdt3306a_tune(struct dvb_frontend *fe, bool re_tune, unsigned int mode_flags, unsigned int *delay, fe_status_t *status) 1596b63b36faSFred Richter { 1597b63b36faSFred Richter int ret = 0; 1598b63b36faSFred Richter struct lgdt3306a_state *state = fe->demodulator_priv; 1599b63b36faSFred Richter 1600b63b36faSFred Richter lg_dbg("re_tune=%u\n", re_tune); 1601b63b36faSFred Richter 1602b63b36faSFred Richter if (re_tune) { 16038e8cd34eSMichael Ira Krufky state->current_frequency = -1; /* force re-tune */ 1604ae21e447SMichael Ira Krufky ret = lgdt3306a_set_parameters(fe); 1605ae21e447SMichael Ira Krufky if (ret != 0) 1606b63b36faSFred Richter return ret; 1607b63b36faSFred Richter } 1608b63b36faSFred Richter *delay = 125; 1609b63b36faSFred Richter ret = lgdt3306a_read_status(fe, status); 1610b63b36faSFred Richter 1611b63b36faSFred Richter return ret; 1612b63b36faSFred Richter } 1613b63b36faSFred Richter 1614b63b36faSFred Richter static int lgdt3306a_get_tune_settings(struct dvb_frontend *fe, 1615b63b36faSFred Richter struct dvb_frontend_tune_settings 1616b63b36faSFred Richter *fe_tune_settings) 1617b63b36faSFred Richter { 1618b63b36faSFred Richter fe_tune_settings->min_delay_ms = 100; 1619b63b36faSFred Richter lg_dbg("\n"); 1620b63b36faSFred Richter return 0; 1621b63b36faSFred Richter } 1622b63b36faSFred Richter 1623b63b36faSFred Richter static int lgdt3306a_search(struct dvb_frontend *fe) 1624b63b36faSFred Richter { 1625b63b36faSFred Richter fe_status_t status = 0; 1626b63b36faSFred Richter int i, ret; 1627b63b36faSFred Richter 1628b63b36faSFred Richter /* set frontend */ 1629b63b36faSFred Richter ret = lgdt3306a_set_parameters(fe); 1630b63b36faSFred Richter if (ret) 1631b63b36faSFred Richter goto error; 1632b63b36faSFred Richter 1633b63b36faSFred Richter /* wait frontend lock */ 1634b63b36faSFred Richter for (i = 20; i > 0; i--) { 1635b63b36faSFred Richter lg_dbg(": loop=%d\n", i); 1636b63b36faSFred Richter msleep(50); 1637b63b36faSFred Richter ret = lgdt3306a_read_status(fe, &status); 1638b63b36faSFred Richter if (ret) 1639b63b36faSFred Richter goto error; 1640b63b36faSFred Richter 1641b63b36faSFred Richter if (status & FE_HAS_LOCK) 1642b63b36faSFred Richter break; 1643b63b36faSFred Richter } 1644b63b36faSFred Richter 1645b63b36faSFred Richter /* check if we have a valid signal */ 16468e8cd34eSMichael Ira Krufky if (status & FE_HAS_LOCK) 1647b63b36faSFred Richter return DVBFE_ALGO_SEARCH_SUCCESS; 16488e8cd34eSMichael Ira Krufky else 1649b63b36faSFred Richter return DVBFE_ALGO_SEARCH_AGAIN; 1650b63b36faSFred Richter 1651b63b36faSFred Richter error: 1652b63b36faSFred Richter lg_dbg("failed (%d)\n", ret); 1653b63b36faSFred Richter return DVBFE_ALGO_SEARCH_ERROR; 1654b63b36faSFred Richter } 1655b63b36faSFred Richter 1656b63b36faSFred Richter static void lgdt3306a_release(struct dvb_frontend *fe) 1657b63b36faSFred Richter { 1658b63b36faSFred Richter struct lgdt3306a_state *state = fe->demodulator_priv; 16598e8cd34eSMichael Ira Krufky 1660b63b36faSFred Richter lg_dbg("\n"); 1661b63b36faSFred Richter kfree(state); 1662b63b36faSFred Richter } 1663b63b36faSFred Richter 1664b63b36faSFred Richter static struct dvb_frontend_ops lgdt3306a_ops; 1665b63b36faSFred Richter 1666b63b36faSFred Richter struct dvb_frontend *lgdt3306a_attach(const struct lgdt3306a_config *config, 1667b63b36faSFred Richter struct i2c_adapter *i2c_adap) 1668b63b36faSFred Richter { 1669b63b36faSFred Richter struct lgdt3306a_state *state = NULL; 1670b63b36faSFred Richter int ret; 1671b63b36faSFred Richter u8 val; 1672b63b36faSFred Richter 1673b63b36faSFred Richter lg_dbg("(%d-%04x)\n", 1674b63b36faSFred Richter i2c_adap ? i2c_adapter_id(i2c_adap) : 0, 1675b63b36faSFred Richter config ? config->i2c_addr : 0); 1676b63b36faSFred Richter 1677b63b36faSFred Richter state = kzalloc(sizeof(struct lgdt3306a_state), GFP_KERNEL); 1678b63b36faSFred Richter if (state == NULL) 1679b63b36faSFred Richter goto fail; 1680b63b36faSFred Richter 1681b63b36faSFred Richter state->cfg = config; 1682b63b36faSFred Richter state->i2c_adap = i2c_adap; 1683b63b36faSFred Richter 1684b63b36faSFred Richter memcpy(&state->frontend.ops, &lgdt3306a_ops, 1685b63b36faSFred Richter sizeof(struct dvb_frontend_ops)); 1686b63b36faSFred Richter state->frontend.demodulator_priv = state; 1687b63b36faSFred Richter 1688b63b36faSFred Richter /* verify that we're talking to a lg3306a */ 16898e8cd34eSMichael Ira Krufky /* FGR - NOTE - there is no obvious ChipId to check; we check 16908e8cd34eSMichael Ira Krufky * some "known" bits after reset, but it's still just a guess */ 1691b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x0000, &val); 1692b63b36faSFred Richter if (lg_chkerr(ret)) 1693b63b36faSFred Richter goto fail; 1694b63b36faSFred Richter if ((val & 0x74) != 0x74) { 1695b63b36faSFred Richter lg_warn("expected 0x74, got 0x%x\n", (val & 0x74)); 16968e8cd34eSMichael Ira Krufky #if 0 16978e8cd34eSMichael Ira Krufky goto fail; /* BUGBUG - re-enable when we know this is right */ 16988e8cd34eSMichael Ira Krufky #endif 1699b63b36faSFred Richter } 1700b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x0001, &val); 1701b63b36faSFred Richter if (lg_chkerr(ret)) 1702b63b36faSFred Richter goto fail; 17034937ba94SMauro Carvalho Chehab if ((val & 0xf6) != 0xc6) { 17044937ba94SMauro Carvalho Chehab lg_warn("expected 0xc6, got 0x%x\n", (val & 0xf6)); 17058e8cd34eSMichael Ira Krufky #if 0 17068e8cd34eSMichael Ira Krufky goto fail; /* BUGBUG - re-enable when we know this is right */ 17078e8cd34eSMichael Ira Krufky #endif 1708b63b36faSFred Richter } 1709b63b36faSFred Richter ret = lgdt3306a_read_reg(state, 0x0002, &val); 1710b63b36faSFred Richter if (lg_chkerr(ret)) 1711b63b36faSFred Richter goto fail; 1712b63b36faSFred Richter if ((val & 0x73) != 0x03) { 1713b63b36faSFred Richter lg_warn("expected 0x03, got 0x%x\n", (val & 0x73)); 17148e8cd34eSMichael Ira Krufky #if 0 17158e8cd34eSMichael Ira Krufky goto fail; /* BUGBUG - re-enable when we know this is right */ 17168e8cd34eSMichael Ira Krufky #endif 1717b63b36faSFred Richter } 1718b63b36faSFred Richter 1719b63b36faSFred Richter state->current_frequency = -1; 1720b63b36faSFred Richter state->current_modulation = -1; 1721b63b36faSFred Richter 1722b63b36faSFred Richter lgdt3306a_sleep(state); 1723b63b36faSFred Richter 1724b63b36faSFred Richter return &state->frontend; 1725b63b36faSFred Richter 1726b63b36faSFred Richter fail: 1727b63b36faSFred Richter lg_warn("unable to detect LGDT3306A hardware\n"); 1728b63b36faSFred Richter kfree(state); 1729b63b36faSFred Richter return NULL; 1730b63b36faSFred Richter } 1731ebd9175eSMichael Ira Krufky EXPORT_SYMBOL(lgdt3306a_attach); 1732b63b36faSFred Richter 1733b63b36faSFred Richter #ifdef DBG_DUMP 1734b63b36faSFred Richter 1735b63b36faSFred Richter static const short regtab[] = { 17366da7ac98SMichael Ira Krufky 0x0000, /* SOFTRSTB 1'b1 1'b1 1'b1 ADCPDB 1'b1 PLLPDB GBBPDB 11111111 */ 17376da7ac98SMichael Ira Krufky 0x0001, /* 1'b1 1'b1 1'b0 1'b0 AUTORPTRS */ 17386da7ac98SMichael Ira Krufky 0x0002, /* NI2CRPTEN 1'b0 1'b0 1'b0 SPECINVAUT */ 17396da7ac98SMichael Ira Krufky 0x0003, /* AGCRFOUT */ 17406da7ac98SMichael Ira Krufky 0x0004, /* ADCSEL1V ADCCNT ADCCNF ADCCNS ADCCLKPLL */ 17416da7ac98SMichael Ira Krufky 0x0005, /* PLLINDIVSE */ 17426da7ac98SMichael Ira Krufky 0x0006, /* PLLCTRL[7:0] 11100001 */ 17436da7ac98SMichael Ira Krufky 0x0007, /* SYSINITWAITTIME[7:0] (msec) 00001000 */ 17446da7ac98SMichael Ira Krufky 0x0008, /* STDOPMODE[7:0] 10000000 */ 17456da7ac98SMichael Ira Krufky 0x0009, /* 1'b0 1'b0 1'b0 STDOPDETTMODE[2:0] STDOPDETCMODE[1:0] 00011110 */ 17464937ba94SMauro Carvalho Chehab 0x000a, /* DAFTEN 1'b1 x x SCSYSLOCK */ 17474937ba94SMauro Carvalho Chehab 0x000b, /* SCSYSLOCKCHKTIME[7:0] (10msec) 01100100 */ 17484937ba94SMauro Carvalho Chehab 0x000d, /* x SAMPLING4 */ 17494937ba94SMauro Carvalho Chehab 0x000e, /* SAMFREQ[15:8] 00000000 */ 17504937ba94SMauro Carvalho Chehab 0x000f, /* SAMFREQ[7:0] 00000000 */ 17516da7ac98SMichael Ira Krufky 0x0010, /* IFFREQ[15:8] 01100000 */ 17526da7ac98SMichael Ira Krufky 0x0011, /* IFFREQ[7:0] 00000000 */ 17536da7ac98SMichael Ira Krufky 0x0012, /* AGCEN AGCREFMO */ 17546da7ac98SMichael Ira Krufky 0x0013, /* AGCRFFIXB AGCIFFIXB AGCLOCKDETRNGSEL[1:0] 1'b1 1'b0 1'b0 1'b0 11101000 */ 17556da7ac98SMichael Ira Krufky 0x0014, /* AGCFIXVALUE[7:0] 01111111 */ 17566da7ac98SMichael Ira Krufky 0x0015, /* AGCREF[15:8] 00001010 */ 17576da7ac98SMichael Ira Krufky 0x0016, /* AGCREF[7:0] 11100100 */ 17586da7ac98SMichael Ira Krufky 0x0017, /* AGCDELAY[7:0] 00100000 */ 17596da7ac98SMichael Ira Krufky 0x0018, /* AGCRFBW[3:0] AGCIFBW[3:0] 10001000 */ 17606da7ac98SMichael Ira Krufky 0x0019, /* AGCUDOUTMODE[1:0] AGCUDCTRLLEN[1:0] AGCUDCTRL */ 17614937ba94SMauro Carvalho Chehab 0x001c, /* 1'b1 PFEN MFEN AICCVSYNC */ 17624937ba94SMauro Carvalho Chehab 0x001d, /* 1'b0 1'b1 1'b0 1'b1 AICCVSYNC */ 17634937ba94SMauro Carvalho Chehab 0x001e, /* AICCALPHA[3:0] 1'b1 1'b0 1'b1 1'b0 01111010 */ 17644937ba94SMauro Carvalho Chehab 0x001f, /* AICCDETTH[19:16] AICCOFFTH[19:16] 00000000 */ 17656da7ac98SMichael Ira Krufky 0x0020, /* AICCDETTH[15:8] 01111100 */ 17666da7ac98SMichael Ira Krufky 0x0021, /* AICCDETTH[7:0] 00000000 */ 17676da7ac98SMichael Ira Krufky 0x0022, /* AICCOFFTH[15:8] 00000101 */ 17686da7ac98SMichael Ira Krufky 0x0023, /* AICCOFFTH[7:0] 11100000 */ 17696da7ac98SMichael Ira Krufky 0x0024, /* AICCOPMODE3[1:0] AICCOPMODE2[1:0] AICCOPMODE1[1:0] AICCOPMODE0[1:0] 00000000 */ 17706da7ac98SMichael Ira Krufky 0x0025, /* AICCFIXFREQ3[23:16] 00000000 */ 17716da7ac98SMichael Ira Krufky 0x0026, /* AICCFIXFREQ3[15:8] 00000000 */ 17726da7ac98SMichael Ira Krufky 0x0027, /* AICCFIXFREQ3[7:0] 00000000 */ 17736da7ac98SMichael Ira Krufky 0x0028, /* AICCFIXFREQ2[23:16] 00000000 */ 17746da7ac98SMichael Ira Krufky 0x0029, /* AICCFIXFREQ2[15:8] 00000000 */ 17754937ba94SMauro Carvalho Chehab 0x002a, /* AICCFIXFREQ2[7:0] 00000000 */ 17764937ba94SMauro Carvalho Chehab 0x002b, /* AICCFIXFREQ1[23:16] 00000000 */ 17774937ba94SMauro Carvalho Chehab 0x002c, /* AICCFIXFREQ1[15:8] 00000000 */ 17784937ba94SMauro Carvalho Chehab 0x002d, /* AICCFIXFREQ1[7:0] 00000000 */ 17794937ba94SMauro Carvalho Chehab 0x002e, /* AICCFIXFREQ0[23:16] 00000000 */ 17804937ba94SMauro Carvalho Chehab 0x002f, /* AICCFIXFREQ0[15:8] 00000000 */ 17816da7ac98SMichael Ira Krufky 0x0030, /* AICCFIXFREQ0[7:0] 00000000 */ 17826da7ac98SMichael Ira Krufky 0x0031, /* 1'b0 1'b1 1'b0 1'b0 x DAGC1STER */ 17836da7ac98SMichael Ira Krufky 0x0032, /* DAGC1STEN DAGC1STER */ 17846da7ac98SMichael Ira Krufky 0x0033, /* DAGC1STREF[15:8] 00001010 */ 17856da7ac98SMichael Ira Krufky 0x0034, /* DAGC1STREF[7:0] 11100100 */ 17866da7ac98SMichael Ira Krufky 0x0035, /* DAGC2NDE */ 17876da7ac98SMichael Ira Krufky 0x0036, /* DAGC2NDREF[15:8] 00001010 */ 17886da7ac98SMichael Ira Krufky 0x0037, /* DAGC2NDREF[7:0] 10000000 */ 17896da7ac98SMichael Ira Krufky 0x0038, /* DAGC2NDLOCKDETRNGSEL[1:0] */ 17904937ba94SMauro Carvalho Chehab 0x003d, /* 1'b1 SAMGEARS */ 17916da7ac98SMichael Ira Krufky 0x0040, /* SAMLFGMA */ 17926da7ac98SMichael Ira Krufky 0x0041, /* SAMLFBWM */ 17936da7ac98SMichael Ira Krufky 0x0044, /* 1'b1 CRGEARSHE */ 17946da7ac98SMichael Ira Krufky 0x0045, /* CRLFGMAN */ 17956da7ac98SMichael Ira Krufky 0x0046, /* CFLFBWMA */ 17966da7ac98SMichael Ira Krufky 0x0047, /* CRLFGMAN */ 17976da7ac98SMichael Ira Krufky 0x0048, /* x x x x CRLFGSTEP_VS[3:0] xxxx1001 */ 17986da7ac98SMichael Ira Krufky 0x0049, /* CRLFBWMA */ 17994937ba94SMauro Carvalho Chehab 0x004a, /* CRLFBWMA */ 18006da7ac98SMichael Ira Krufky 0x0050, /* 1'b0 1'b1 1'b1 1'b0 MSECALCDA */ 18016da7ac98SMichael Ira Krufky 0x0070, /* TPOUTEN TPIFEN TPCLKOUTE */ 18026da7ac98SMichael Ira Krufky 0x0071, /* TPSENB TPSSOPBITE */ 18036da7ac98SMichael Ira Krufky 0x0073, /* TP47HINS x x CHBERINT PERMODE[1:0] PERINT[1:0] 1xx11100 */ 18046da7ac98SMichael Ira Krufky 0x0075, /* x x x x x IQSWAPCTRL[2:0] xxxxx000 */ 18056da7ac98SMichael Ira Krufky 0x0076, /* NBERCON NBERST NBERPOL NBERWSYN */ 18066da7ac98SMichael Ira Krufky 0x0077, /* x NBERLOSTTH[2:0] NBERACQTH[3:0] x0000000 */ 18076da7ac98SMichael Ira Krufky 0x0078, /* NBERPOLY[31:24] 00000000 */ 18086da7ac98SMichael Ira Krufky 0x0079, /* NBERPOLY[23:16] 00000000 */ 18094937ba94SMauro Carvalho Chehab 0x007a, /* NBERPOLY[15:8] 00000000 */ 18104937ba94SMauro Carvalho Chehab 0x007b, /* NBERPOLY[7:0] 00000000 */ 18114937ba94SMauro Carvalho Chehab 0x007c, /* NBERPED[31:24] 00000000 */ 18124937ba94SMauro Carvalho Chehab 0x007d, /* NBERPED[23:16] 00000000 */ 18134937ba94SMauro Carvalho Chehab 0x007e, /* NBERPED[15:8] 00000000 */ 18144937ba94SMauro Carvalho Chehab 0x007f, /* NBERPED[7:0] 00000000 */ 18156da7ac98SMichael Ira Krufky 0x0080, /* x AGCLOCK DAGCLOCK SYSLOCK x x NEVERLOCK[1:0] */ 18166da7ac98SMichael Ira Krufky 0x0085, /* SPECINVST */ 18176da7ac98SMichael Ira Krufky 0x0088, /* SYSLOCKTIME[15:8] */ 18186da7ac98SMichael Ira Krufky 0x0089, /* SYSLOCKTIME[7:0] */ 18194937ba94SMauro Carvalho Chehab 0x008c, /* FECLOCKTIME[15:8] */ 18204937ba94SMauro Carvalho Chehab 0x008d, /* FECLOCKTIME[7:0] */ 18214937ba94SMauro Carvalho Chehab 0x008e, /* AGCACCOUT[15:8] */ 18224937ba94SMauro Carvalho Chehab 0x008f, /* AGCACCOUT[7:0] */ 18236da7ac98SMichael Ira Krufky 0x0090, /* AICCREJSTATUS[3:0] AICCREJBUSY[3:0] */ 18246da7ac98SMichael Ira Krufky 0x0091, /* AICCVSYNC */ 18254937ba94SMauro Carvalho Chehab 0x009c, /* CARRFREQOFFSET[15:8] */ 18264937ba94SMauro Carvalho Chehab 0x009d, /* CARRFREQOFFSET[7:0] */ 18274937ba94SMauro Carvalho Chehab 0x00a1, /* SAMFREQOFFSET[23:16] */ 18284937ba94SMauro Carvalho Chehab 0x00a2, /* SAMFREQOFFSET[15:8] */ 18294937ba94SMauro Carvalho Chehab 0x00a3, /* SAMFREQOFFSET[7:0] */ 18304937ba94SMauro Carvalho Chehab 0x00a6, /* SYNCLOCK SYNCLOCKH */ 18316da7ac98SMichael Ira Krufky #if 0 /* covered elsewhere */ 18324937ba94SMauro Carvalho Chehab 0x00e8, /* CONSTPWR[15:8] */ 18334937ba94SMauro Carvalho Chehab 0x00e9, /* CONSTPWR[7:0] */ 18344937ba94SMauro Carvalho Chehab 0x00ea, /* BMSE[15:8] */ 18354937ba94SMauro Carvalho Chehab 0x00eb, /* BMSE[7:0] */ 18364937ba94SMauro Carvalho Chehab 0x00ec, /* MSE[15:8] */ 18374937ba94SMauro Carvalho Chehab 0x00ed, /* MSE[7:0] */ 18384937ba94SMauro Carvalho Chehab 0x00ee, /* CONSTI[7:0] */ 18394937ba94SMauro Carvalho Chehab 0x00ef, /* CONSTQ[7:0] */ 1840b63b36faSFred Richter #endif 18414937ba94SMauro Carvalho Chehab 0x00f4, /* TPIFTPERRCNT[7:0] */ 18424937ba94SMauro Carvalho Chehab 0x00f5, /* TPCORREC */ 18434937ba94SMauro Carvalho Chehab 0x00f6, /* VBBER[15:8] */ 18444937ba94SMauro Carvalho Chehab 0x00f7, /* VBBER[7:0] */ 18454937ba94SMauro Carvalho Chehab 0x00f8, /* VABER[15:8] */ 18464937ba94SMauro Carvalho Chehab 0x00f9, /* VABER[7:0] */ 18474937ba94SMauro Carvalho Chehab 0x00fa, /* TPERRCNT[7:0] */ 18484937ba94SMauro Carvalho Chehab 0x00fb, /* NBERLOCK x x x x x x x */ 18494937ba94SMauro Carvalho Chehab 0x00fc, /* NBERVALUE[31:24] */ 18504937ba94SMauro Carvalho Chehab 0x00fd, /* NBERVALUE[23:16] */ 18514937ba94SMauro Carvalho Chehab 0x00fe, /* NBERVALUE[15:8] */ 18524937ba94SMauro Carvalho Chehab 0x00ff, /* NBERVALUE[7:0] */ 18536da7ac98SMichael Ira Krufky 0x1000, /* 1'b0 WODAGCOU */ 18546da7ac98SMichael Ira Krufky 0x1005, /* x x 1'b1 1'b1 x SRD_Q_QM */ 18556da7ac98SMichael Ira Krufky 0x1009, /* SRDWAITTIME[7:0] (10msec) 00100011 */ 18564937ba94SMauro Carvalho Chehab 0x100a, /* SRDWAITTIME_CQS[7:0] (msec) 01100100 */ 18574937ba94SMauro Carvalho Chehab 0x101a, /* x 1'b1 1'b0 1'b0 x QMDQAMMODE[2:0] x100x010 */ 18586da7ac98SMichael Ira Krufky 0x1036, /* 1'b0 1'b1 1'b0 1'b0 SAMGSEND_CQS[3:0] 01001110 */ 18594937ba94SMauro Carvalho Chehab 0x103c, /* SAMGSAUTOSTL_V[3:0] SAMGSAUTOEDL_V[3:0] 01000110 */ 18604937ba94SMauro Carvalho Chehab 0x103d, /* 1'b1 1'b1 SAMCNORMBP_V[1:0] 1'b0 1'b0 SAMMODESEL_V[1:0] 11100001 */ 18614937ba94SMauro Carvalho Chehab 0x103f, /* SAMZTEDSE */ 18624937ba94SMauro Carvalho Chehab 0x105d, /* EQSTATUSE */ 18634937ba94SMauro Carvalho Chehab 0x105f, /* x PMAPG2_V[2:0] x DMAPG2_V[2:0] x001x011 */ 18646da7ac98SMichael Ira Krufky 0x1060, /* 1'b1 EQSTATUSE */ 18656da7ac98SMichael Ira Krufky 0x1061, /* CRMAPBWSTL_V[3:0] CRMAPBWEDL_V[3:0] 00000100 */ 18666da7ac98SMichael Ira Krufky 0x1065, /* 1'b0 x CRMODE_V[1:0] 1'b1 x 1'b1 x 0x111x1x */ 18676da7ac98SMichael Ira Krufky 0x1066, /* 1'b0 1'b0 1'b1 1'b0 1'b1 PNBOOSTSE */ 18686da7ac98SMichael Ira Krufky 0x1068, /* CREPHNGAIN2_V[3:0] CREPHNPBW_V[3:0] 10010001 */ 18694937ba94SMauro Carvalho Chehab 0x106e, /* x x x x x CREPHNEN_ */ 18704937ba94SMauro Carvalho Chehab 0x106f, /* CREPHNTH_V[7:0] 00010101 */ 18716da7ac98SMichael Ira Krufky 0x1072, /* CRSWEEPN */ 18726da7ac98SMichael Ira Krufky 0x1073, /* CRPGAIN_V[3:0] x x 1'b1 1'b1 1001xx11 */ 18736da7ac98SMichael Ira Krufky 0x1074, /* CRPBW_V[3:0] x x 1'b1 1'b1 0001xx11 */ 18746da7ac98SMichael Ira Krufky 0x1080, /* DAFTSTATUS[1:0] x x x x x x */ 18756da7ac98SMichael Ira Krufky 0x1081, /* SRDSTATUS[1:0] x x x x x SRDLOCK */ 18764937ba94SMauro Carvalho Chehab 0x10a9, /* EQSTATUS_CQS[1:0] x x x x x x */ 18774937ba94SMauro Carvalho Chehab 0x10b7, /* EQSTATUS_V[1:0] x x x x x x */ 18786da7ac98SMichael Ira Krufky #if 0 /* SMART_ANT */ 18794937ba94SMauro Carvalho Chehab 0x1f00, /* MODEDETE */ 18804937ba94SMauro Carvalho Chehab 0x1f01, /* x x x x x x x SFNRST xxxxxxx0 */ 18814937ba94SMauro Carvalho Chehab 0x1f03, /* NUMOFANT[7:0] 10000000 */ 18824937ba94SMauro Carvalho Chehab 0x1f04, /* x SELMASK[6:0] x0000000 */ 18834937ba94SMauro Carvalho Chehab 0x1f05, /* x SETMASK[6:0] x0000000 */ 18844937ba94SMauro Carvalho Chehab 0x1f06, /* x TXDATA[6:0] x0000000 */ 18854937ba94SMauro Carvalho Chehab 0x1f07, /* x CHNUMBER[6:0] x0000000 */ 18864937ba94SMauro Carvalho Chehab 0x1f09, /* AGCTIME[23:16] 10011000 */ 18874937ba94SMauro Carvalho Chehab 0x1f0a, /* AGCTIME[15:8] 10010110 */ 18884937ba94SMauro Carvalho Chehab 0x1f0b, /* AGCTIME[7:0] 10000000 */ 18894937ba94SMauro Carvalho Chehab 0x1f0c, /* ANTTIME[31:24] 00000000 */ 18904937ba94SMauro Carvalho Chehab 0x1f0d, /* ANTTIME[23:16] 00000011 */ 18914937ba94SMauro Carvalho Chehab 0x1f0e, /* ANTTIME[15:8] 10010000 */ 18924937ba94SMauro Carvalho Chehab 0x1f0f, /* ANTTIME[7:0] 10010000 */ 18934937ba94SMauro Carvalho Chehab 0x1f11, /* SYNCTIME[23:16] 10011000 */ 18944937ba94SMauro Carvalho Chehab 0x1f12, /* SYNCTIME[15:8] 10010110 */ 18954937ba94SMauro Carvalho Chehab 0x1f13, /* SYNCTIME[7:0] 10000000 */ 18964937ba94SMauro Carvalho Chehab 0x1f14, /* SNRTIME[31:24] 00000001 */ 18974937ba94SMauro Carvalho Chehab 0x1f15, /* SNRTIME[23:16] 01111101 */ 18984937ba94SMauro Carvalho Chehab 0x1f16, /* SNRTIME[15:8] 01111000 */ 18994937ba94SMauro Carvalho Chehab 0x1f17, /* SNRTIME[7:0] 01000000 */ 19004937ba94SMauro Carvalho Chehab 0x1f19, /* FECTIME[23:16] 00000000 */ 19014937ba94SMauro Carvalho Chehab 0x1f1a, /* FECTIME[15:8] 01110010 */ 19024937ba94SMauro Carvalho Chehab 0x1f1b, /* FECTIME[7:0] 01110000 */ 19034937ba94SMauro Carvalho Chehab 0x1f1d, /* FECTHD[7:0] 00000011 */ 19044937ba94SMauro Carvalho Chehab 0x1f1f, /* SNRTHD[23:16] 00001000 */ 19054937ba94SMauro Carvalho Chehab 0x1f20, /* SNRTHD[15:8] 01111111 */ 19064937ba94SMauro Carvalho Chehab 0x1f21, /* SNRTHD[7:0] 10000101 */ 19074937ba94SMauro Carvalho Chehab 0x1f80, /* IRQFLG x x SFSDRFLG MODEBFLG SAVEFLG SCANFLG TRACKFLG */ 19084937ba94SMauro Carvalho Chehab 0x1f81, /* x SYNCCON SNRCON FECCON x STDBUSY SYNCRST AGCFZCO */ 19094937ba94SMauro Carvalho Chehab 0x1f82, /* x x x SCANOPCD[4:0] */ 19104937ba94SMauro Carvalho Chehab 0x1f83, /* x x x x MAINOPCD[3:0] */ 19114937ba94SMauro Carvalho Chehab 0x1f84, /* x x RXDATA[13:8] */ 19124937ba94SMauro Carvalho Chehab 0x1f85, /* RXDATA[7:0] */ 19134937ba94SMauro Carvalho Chehab 0x1f86, /* x x SDTDATA[13:8] */ 19144937ba94SMauro Carvalho Chehab 0x1f87, /* SDTDATA[7:0] */ 19154937ba94SMauro Carvalho Chehab 0x1f89, /* ANTSNR[23:16] */ 19164937ba94SMauro Carvalho Chehab 0x1f8a, /* ANTSNR[15:8] */ 19174937ba94SMauro Carvalho Chehab 0x1f8b, /* ANTSNR[7:0] */ 19184937ba94SMauro Carvalho Chehab 0x1f8c, /* x x x x ANTFEC[13:8] */ 19194937ba94SMauro Carvalho Chehab 0x1f8d, /* ANTFEC[7:0] */ 19204937ba94SMauro Carvalho Chehab 0x1f8e, /* MAXCNT[7:0] */ 19214937ba94SMauro Carvalho Chehab 0x1f8f, /* SCANCNT[7:0] */ 19224937ba94SMauro Carvalho Chehab 0x1f91, /* MAXPW[23:16] */ 19234937ba94SMauro Carvalho Chehab 0x1f92, /* MAXPW[15:8] */ 19244937ba94SMauro Carvalho Chehab 0x1f93, /* MAXPW[7:0] */ 19254937ba94SMauro Carvalho Chehab 0x1f95, /* CURPWMSE[23:16] */ 19264937ba94SMauro Carvalho Chehab 0x1f96, /* CURPWMSE[15:8] */ 19274937ba94SMauro Carvalho Chehab 0x1f97, /* CURPWMSE[7:0] */ 19286da7ac98SMichael Ira Krufky #endif /* SMART_ANT */ 19294937ba94SMauro Carvalho Chehab 0x211f, /* 1'b1 1'b1 1'b1 CIRQEN x x 1'b0 1'b0 1111xx00 */ 19304937ba94SMauro Carvalho Chehab 0x212a, /* EQAUTOST */ 19316da7ac98SMichael Ira Krufky 0x2122, /* CHFAST[7:0] 01100000 */ 19324937ba94SMauro Carvalho Chehab 0x212b, /* FFFSTEP_V[3:0] x FBFSTEP_V[2:0] 0001x001 */ 19334937ba94SMauro Carvalho Chehab 0x212c, /* PHDEROTBWSEL[3:0] 1'b1 1'b1 1'b1 1'b0 10001110 */ 19344937ba94SMauro Carvalho Chehab 0x212d, /* 1'b1 1'b1 1'b1 1'b1 x x TPIFLOCKS */ 19356da7ac98SMichael Ira Krufky 0x2135, /* DYNTRACKFDEQ[3:0] x 1'b0 1'b0 1'b0 1010x000 */ 19366da7ac98SMichael Ira Krufky 0x2141, /* TRMODE[1:0] 1'b1 1'b1 1'b0 1'b1 1'b1 1'b1 01110111 */ 19376da7ac98SMichael Ira Krufky 0x2162, /* AICCCTRLE */ 19386da7ac98SMichael Ira Krufky 0x2173, /* PHNCNFCNT[7:0] 00000100 */ 19396da7ac98SMichael Ira Krufky 0x2179, /* 1'b0 1'b0 1'b0 1'b1 x BADSINGLEDYNTRACKFBF[2:0] 0001x001 */ 19404937ba94SMauro Carvalho Chehab 0x217a, /* 1'b0 1'b0 1'b0 1'b1 x BADSLOWSINGLEDYNTRACKFBF[2:0] 0001x001 */ 19414937ba94SMauro Carvalho Chehab 0x217e, /* CNFCNTTPIF[7:0] 00001000 */ 19424937ba94SMauro Carvalho Chehab 0x217f, /* TPERRCNTTPIF[7:0] 00000001 */ 19436da7ac98SMichael Ira Krufky 0x2180, /* x x x x x x FBDLYCIR[9:8] */ 19446da7ac98SMichael Ira Krufky 0x2181, /* FBDLYCIR[7:0] */ 19456da7ac98SMichael Ira Krufky 0x2185, /* MAXPWRMAIN[7:0] */ 19466da7ac98SMichael Ira Krufky 0x2191, /* NCOMBDET x x x x x x x */ 19476da7ac98SMichael Ira Krufky 0x2199, /* x MAINSTRON */ 19484937ba94SMauro Carvalho Chehab 0x219a, /* FFFEQSTEPOUT_V[3:0] FBFSTEPOUT_V[2:0] */ 19494937ba94SMauro Carvalho Chehab 0x21a1, /* x x SNRREF[5:0] */ 19506da7ac98SMichael Ira Krufky 0x2845, /* 1'b0 1'b1 x x FFFSTEP_CQS[1:0] FFFCENTERTAP[1:0] 01xx1110 */ 19516da7ac98SMichael Ira Krufky 0x2846, /* 1'b0 x 1'b0 1'b1 FBFSTEP_CQS[1:0] 1'b1 1'b0 0x011110 */ 19526da7ac98SMichael Ira Krufky 0x2847, /* ENNOSIGDE */ 19536da7ac98SMichael Ira Krufky 0x2849, /* 1'b1 1'b1 NOUSENOSI */ 19544937ba94SMauro Carvalho Chehab 0x284a, /* EQINITWAITTIME[7:0] 01100100 */ 19556da7ac98SMichael Ira Krufky 0x3000, /* 1'b1 1'b1 1'b1 x x x 1'b0 RPTRSTM */ 19566da7ac98SMichael Ira Krufky 0x3001, /* RPTRSTWAITTIME[7:0] (100msec) 00110010 */ 19576da7ac98SMichael Ira Krufky 0x3031, /* FRAMELOC */ 19586da7ac98SMichael Ira Krufky 0x3032, /* 1'b1 1'b0 1'b0 1'b0 x x FRAMELOCKMODE_CQS[1:0] 1000xx11 */ 19594937ba94SMauro Carvalho Chehab 0x30a9, /* VDLOCK_Q FRAMELOCK */ 19604937ba94SMauro Carvalho Chehab 0x30aa, /* MPEGLOCK */ 1961b63b36faSFred Richter }; 1962b63b36faSFred Richter 1963b63b36faSFred Richter #define numDumpRegs (sizeof(regtab)/sizeof(regtab[0])) 1964b63b36faSFred Richter static u8 regval1[numDumpRegs] = {0, }; 1965b63b36faSFred Richter static u8 regval2[numDumpRegs] = {0, }; 1966b63b36faSFred Richter 1967b63b36faSFred Richter static void lgdt3306a_DumpAllRegs(struct lgdt3306a_state *state) 1968b63b36faSFred Richter { 1969b63b36faSFred Richter memset(regval2, 0xff, sizeof(regval2)); 1970b63b36faSFred Richter lgdt3306a_DumpRegs(state); 1971b63b36faSFred Richter } 1972b63b36faSFred Richter 1973b63b36faSFred Richter static void lgdt3306a_DumpRegs(struct lgdt3306a_state *state) 1974b63b36faSFred Richter { 1975b63b36faSFred Richter int i; 1976b63b36faSFred Richter int sav_debug = debug; 19778e8cd34eSMichael Ira Krufky 1978b63b36faSFred Richter if ((debug & DBG_DUMP) == 0) 1979b63b36faSFred Richter return; 1980831a9112SMichael Ira Krufky debug &= ~DBG_REG; /* suppress DBG_REG during reg dump */ 1981b63b36faSFred Richter 1982b63b36faSFred Richter lg_info("\n"); 1983b63b36faSFred Richter 1984b63b36faSFred Richter for (i = 0; i < numDumpRegs; i++) { 1985b63b36faSFred Richter lgdt3306a_read_reg(state, regtab[i], ®val1[i]); 1986b63b36faSFred Richter if (regval1[i] != regval2[i]) { 1987b63b36faSFred Richter lg_info(" %04X = %02X\n", regtab[i], regval1[i]); 1988b63b36faSFred Richter regval2[i] = regval1[i]; 1989b63b36faSFred Richter } 1990b63b36faSFred Richter } 1991b63b36faSFred Richter debug = sav_debug; 1992b63b36faSFred Richter } 19938e8cd34eSMichael Ira Krufky #endif /* DBG_DUMP */ 1994b63b36faSFred Richter 1995b63b36faSFred Richter 1996b63b36faSFred Richter 1997b63b36faSFred Richter static struct dvb_frontend_ops lgdt3306a_ops = { 1998b63b36faSFred Richter .delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B }, 1999b63b36faSFred Richter .info = { 2000b63b36faSFred Richter .name = "LG Electronics LGDT3306A VSB/QAM Frontend", 20018e8cd34eSMichael Ira Krufky #if 0 20028e8cd34eSMichael Ira Krufky .type = FE_ATSC, 20038e8cd34eSMichael Ira Krufky #endif 2004b63b36faSFred Richter .frequency_min = 54000000, 20058e8cd34eSMichael Ira Krufky .frequency_max = 858000000, 2006b63b36faSFred Richter .frequency_stepsize = 62500, 2007b63b36faSFred Richter .caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB 2008b63b36faSFred Richter }, 2009b63b36faSFred Richter .i2c_gate_ctrl = lgdt3306a_i2c_gate_ctrl, 2010b63b36faSFred Richter .init = lgdt3306a_init, 2011b63b36faSFred Richter .sleep = lgdt3306a_fe_sleep, 2012b63b36faSFred Richter /* if this is set, it overrides the default swzigzag */ 2013b63b36faSFred Richter .tune = lgdt3306a_tune, 2014b63b36faSFred Richter .set_frontend = lgdt3306a_set_parameters, 2015b63b36faSFred Richter .get_frontend = lgdt3306a_get_frontend, 2016b63b36faSFred Richter .get_frontend_algo = lgdt3306a_get_frontend_algo, 2017b63b36faSFred Richter .get_tune_settings = lgdt3306a_get_tune_settings, 2018b63b36faSFred Richter .read_status = lgdt3306a_read_status, 2019b63b36faSFred Richter .read_ber = lgdt3306a_read_ber, 2020b63b36faSFred Richter .read_signal_strength = lgdt3306a_read_signal_strength, 2021b63b36faSFred Richter .read_snr = lgdt3306a_read_snr, 2022b63b36faSFred Richter .read_ucblocks = lgdt3306a_read_ucblocks, 2023b63b36faSFred Richter .release = lgdt3306a_release, 2024b63b36faSFred Richter .ts_bus_ctrl = lgdt3306a_ts_bus_ctrl, 2025b63b36faSFred Richter .search = lgdt3306a_search, 2026b63b36faSFred Richter }; 2027b63b36faSFred Richter 2028b63b36faSFred Richter MODULE_DESCRIPTION("LG Electronics LGDT3306A ATSC/QAM-B Demodulator Driver"); 2029b63b36faSFred Richter MODULE_AUTHOR("Fred Richter <frichter@hauppauge.com>"); 2030b63b36faSFred Richter MODULE_LICENSE("GPL"); 2031b63b36faSFred Richter MODULE_VERSION("0.2"); 2032b63b36faSFred Richter 2033b63b36faSFred Richter /* 2034b63b36faSFred Richter * Local variables: 2035b63b36faSFred Richter * c-basic-offset: 8 2036b63b36faSFred Richter * End: 2037b63b36faSFred Richter */ 2038