1203 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Support for LG Electronics LGDT3304 and LGDT3305 - VSB/QAM4 *5 * Copyright (C) 2008, 2009, 2010 Michael Krufky <mkrufky@linuxtv.org>6 *7 * LGDT3304 support by Jarod Wilson <jarod@redhat.com>8 */9 10#include <asm/div64.h>11#include <linux/dvb/frontend.h>12#include <linux/slab.h>13#include <linux/int_log.h>14#include "lgdt3305.h"15 16static int debug;17module_param(debug, int, 0644);18MODULE_PARM_DESC(debug, "set debug level (info=1, reg=2 (or-able))");19 20#define DBG_INFO 121#define DBG_REG 222 23#define lg_printk(kern, fmt, arg...) \24 printk(kern "%s: " fmt, __func__, ##arg)25 26#define lg_info(fmt, arg...) printk(KERN_INFO "lgdt3305: " fmt, ##arg)27#define lg_warn(fmt, arg...) lg_printk(KERN_WARNING, fmt, ##arg)28#define lg_err(fmt, arg...) lg_printk(KERN_ERR, fmt, ##arg)29#define lg_dbg(fmt, arg...) if (debug & DBG_INFO) \30 lg_printk(KERN_DEBUG, fmt, ##arg)31#define lg_reg(fmt, arg...) if (debug & DBG_REG) \32 lg_printk(KERN_DEBUG, fmt, ##arg)33 34#define lg_fail(ret) \35({ \36 int __ret; \37 __ret = (ret < 0); \38 if (__ret) \39 lg_err("error %d on line %d\n", ret, __LINE__); \40 __ret; \41})42 43struct lgdt3305_state {44 struct i2c_adapter *i2c_adap;45 const struct lgdt3305_config *cfg;46 47 struct dvb_frontend frontend;48 49 enum fe_modulation current_modulation;50 u32 current_frequency;51 u32 snr;52};53 54/* ------------------------------------------------------------------------ */55 56/* FIXME: verify & document the LGDT3304 registers */57 58#define LGDT3305_GEN_CTRL_1 0x000059#define LGDT3305_GEN_CTRL_2 0x000160#define LGDT3305_GEN_CTRL_3 0x000261#define LGDT3305_GEN_STATUS 0x000362#define LGDT3305_GEN_CONTROL 0x000763#define LGDT3305_GEN_CTRL_4 0x000a64#define LGDT3305_DGTL_AGC_REF_1 0x001265#define LGDT3305_DGTL_AGC_REF_2 0x001366#define LGDT3305_CR_CTR_FREQ_1 0x010667#define LGDT3305_CR_CTR_FREQ_2 0x010768#define LGDT3305_CR_CTR_FREQ_3 0x010869#define LGDT3305_CR_CTR_FREQ_4 0x010970#define LGDT3305_CR_MSE_1 0x011b71#define LGDT3305_CR_MSE_2 0x011c72#define LGDT3305_CR_LOCK_STATUS 0x011d73#define LGDT3305_CR_CTRL_7 0x012674#define LGDT3305_AGC_POWER_REF_1 0x030075#define LGDT3305_AGC_POWER_REF_2 0x030176#define LGDT3305_AGC_DELAY_PT_1 0x030277#define LGDT3305_AGC_DELAY_PT_2 0x030378#define LGDT3305_RFAGC_LOOP_FLTR_BW_1 0x030679#define LGDT3305_RFAGC_LOOP_FLTR_BW_2 0x030780#define LGDT3305_IFBW_1 0x030881#define LGDT3305_IFBW_2 0x030982#define LGDT3305_AGC_CTRL_1 0x030c83#define LGDT3305_AGC_CTRL_4 0x031484#define LGDT3305_EQ_MSE_1 0x041385#define LGDT3305_EQ_MSE_2 0x041486#define LGDT3305_EQ_MSE_3 0x041587#define LGDT3305_PT_MSE_1 0x041788#define LGDT3305_PT_MSE_2 0x041889#define LGDT3305_PT_MSE_3 0x041990#define LGDT3305_FEC_BLOCK_CTRL 0x050491#define LGDT3305_FEC_LOCK_STATUS 0x050a92#define LGDT3305_FEC_PKT_ERR_1 0x050c93#define LGDT3305_FEC_PKT_ERR_2 0x050d94#define LGDT3305_TP_CTRL_1 0x050e95#define LGDT3305_BERT_PERIOD 0x080196#define LGDT3305_BERT_ERROR_COUNT_1 0x080a97#define LGDT3305_BERT_ERROR_COUNT_2 0x080b98#define LGDT3305_BERT_ERROR_COUNT_3 0x080c99#define LGDT3305_BERT_ERROR_COUNT_4 0x080d100 101static int lgdt3305_write_reg(struct lgdt3305_state *state, u16 reg, u8 val)102{103 int ret;104 u8 buf[] = { reg >> 8, reg & 0xff, val };105 struct i2c_msg msg = {106 .addr = state->cfg->i2c_addr, .flags = 0,107 .buf = buf, .len = 3,108 };109 110 lg_reg("reg: 0x%04x, val: 0x%02x\n", reg, val);111 112 ret = i2c_transfer(state->i2c_adap, &msg, 1);113 114 if (ret != 1) {115 lg_err("error (addr %02x %02x <- %02x, err = %i)\n",116 msg.buf[0], msg.buf[1], msg.buf[2], ret);117 if (ret < 0)118 return ret;119 else120 return -EREMOTEIO;121 }122 return 0;123}124 125static int lgdt3305_read_reg(struct lgdt3305_state *state, u16 reg, u8 *val)126{127 int ret;128 u8 reg_buf[] = { reg >> 8, reg & 0xff };129 struct i2c_msg msg[] = {130 { .addr = state->cfg->i2c_addr,131 .flags = 0, .buf = reg_buf, .len = 2 },132 { .addr = state->cfg->i2c_addr,133 .flags = I2C_M_RD, .buf = val, .len = 1 },134 };135 136 lg_reg("reg: 0x%04x\n", reg);137 138 ret = i2c_transfer(state->i2c_adap, msg, 2);139 140 if (ret != 2) {141 lg_err("error (addr %02x reg %04x error (ret == %i)\n",142 state->cfg->i2c_addr, reg, ret);143 if (ret < 0)144 return ret;145 else146 return -EREMOTEIO;147 }148 return 0;149}150 151#define read_reg(state, reg) \152({ \153 u8 __val; \154 int ret = lgdt3305_read_reg(state, reg, &__val); \155 if (lg_fail(ret)) \156 __val = 0; \157 __val; \158})159 160static int lgdt3305_set_reg_bit(struct lgdt3305_state *state,161 u16 reg, int bit, int onoff)162{163 u8 val;164 int ret;165 166 lg_reg("reg: 0x%04x, bit: %d, level: %d\n", reg, bit, onoff);167 168 ret = lgdt3305_read_reg(state, reg, &val);169 if (lg_fail(ret))170 goto fail;171 172 val &= ~(1 << bit);173 val |= (onoff & 1) << bit;174 175 ret = lgdt3305_write_reg(state, reg, val);176fail:177 return ret;178}179 180struct lgdt3305_reg {181 u16 reg;182 u8 val;183};184 185static int lgdt3305_write_regs(struct lgdt3305_state *state,186 struct lgdt3305_reg *regs, int len)187{188 int i, ret;189 190 lg_reg("writing %d registers...\n", len);191 192 for (i = 0; i < len - 1; i++) {193 ret = lgdt3305_write_reg(state, regs[i].reg, regs[i].val);194 if (lg_fail(ret))195 return ret;196 }197 return 0;198}199 200/* ------------------------------------------------------------------------ */201 202static int lgdt3305_soft_reset(struct lgdt3305_state *state)203{204 int ret;205 206 lg_dbg("\n");207 208 ret = lgdt3305_set_reg_bit(state, LGDT3305_GEN_CTRL_3, 0, 0);209 if (lg_fail(ret))210 goto fail;211 212 msleep(20);213 ret = lgdt3305_set_reg_bit(state, LGDT3305_GEN_CTRL_3, 0, 1);214fail:215 return ret;216}217 218static inline int lgdt3305_mpeg_mode(struct lgdt3305_state *state,219 enum lgdt3305_mpeg_mode mode)220{221 lg_dbg("(%d)\n", mode);222 return lgdt3305_set_reg_bit(state, LGDT3305_TP_CTRL_1, 5, mode);223}224 225static int lgdt3305_mpeg_mode_polarity(struct lgdt3305_state *state)226{227 u8 val;228 int ret;229 enum lgdt3305_tp_clock_edge edge = state->cfg->tpclk_edge;230 enum lgdt3305_tp_clock_mode mode = state->cfg->tpclk_mode;231 enum lgdt3305_tp_valid_polarity valid = state->cfg->tpvalid_polarity;232 233 lg_dbg("edge = %d, valid = %d\n", edge, valid);234 235 ret = lgdt3305_read_reg(state, LGDT3305_TP_CTRL_1, &val);236 if (lg_fail(ret))237 goto fail;238 239 val &= ~0x09;240 241 if (edge)242 val |= 0x08;243 if (mode)244 val |= 0x40;245 if (valid)246 val |= 0x01;247 248 ret = lgdt3305_write_reg(state, LGDT3305_TP_CTRL_1, val);249 if (lg_fail(ret))250 goto fail;251 252 ret = lgdt3305_soft_reset(state);253fail:254 return ret;255}256 257static int lgdt3305_set_modulation(struct lgdt3305_state *state,258 struct dtv_frontend_properties *p)259{260 u8 opermode;261 int ret;262 263 lg_dbg("\n");264 265 ret = lgdt3305_read_reg(state, LGDT3305_GEN_CTRL_1, &opermode);266 if (lg_fail(ret))267 goto fail;268 269 opermode &= ~0x03;270 271 switch (p->modulation) {272 case VSB_8:273 opermode |= 0x03;274 break;275 case QAM_64:276 opermode |= 0x00;277 break;278 case QAM_256:279 opermode |= 0x01;280 break;281 default:282 return -EINVAL;283 }284 ret = lgdt3305_write_reg(state, LGDT3305_GEN_CTRL_1, opermode);285fail:286 return ret;287}288 289static int lgdt3305_set_filter_extension(struct lgdt3305_state *state,290 struct dtv_frontend_properties *p)291{292 int val;293 294 switch (p->modulation) {295 case VSB_8:296 val = 0;297 break;298 case QAM_64:299 case QAM_256:300 val = 1;301 break;302 default:303 return -EINVAL;304 }305 lg_dbg("val = %d\n", val);306 307 return lgdt3305_set_reg_bit(state, 0x043f, 2, val);308}309 310/* ------------------------------------------------------------------------ */311 312static int lgdt3305_passband_digital_agc(struct lgdt3305_state *state,313 struct dtv_frontend_properties *p)314{315 u16 agc_ref;316 317 switch (p->modulation) {318 case VSB_8:319 agc_ref = 0x32c4;320 break;321 case QAM_64:322 agc_ref = 0x2a00;323 break;324 case QAM_256:325 agc_ref = 0x2a80;326 break;327 default:328 return -EINVAL;329 }330 331 lg_dbg("agc ref: 0x%04x\n", agc_ref);332 333 lgdt3305_write_reg(state, LGDT3305_DGTL_AGC_REF_1, agc_ref >> 8);334 lgdt3305_write_reg(state, LGDT3305_DGTL_AGC_REF_2, agc_ref & 0xff);335 336 return 0;337}338 339static int lgdt3305_rfagc_loop(struct lgdt3305_state *state,340 struct dtv_frontend_properties *p)341{342 u16 ifbw, rfbw, agcdelay;343 344 switch (p->modulation) {345 case VSB_8:346 agcdelay = 0x04c0;347 rfbw = 0x8000;348 ifbw = 0x8000;349 break;350 case QAM_64:351 case QAM_256:352 agcdelay = 0x046b;353 rfbw = 0x8889;354 /* FIXME: investigate optimal ifbw & rfbw values for the355 * DT3304 and re-write this switch..case block */356 if (state->cfg->demod_chip == LGDT3304)357 ifbw = 0x6666;358 else /* (state->cfg->demod_chip == LGDT3305) */359 ifbw = 0x8888;360 break;361 default:362 return -EINVAL;363 }364 365 if (state->cfg->rf_agc_loop) {366 lg_dbg("agcdelay: 0x%04x, rfbw: 0x%04x\n", agcdelay, rfbw);367 368 /* rf agc loop filter bandwidth */369 lgdt3305_write_reg(state, LGDT3305_AGC_DELAY_PT_1,370 agcdelay >> 8);371 lgdt3305_write_reg(state, LGDT3305_AGC_DELAY_PT_2,372 agcdelay & 0xff);373 374 lgdt3305_write_reg(state, LGDT3305_RFAGC_LOOP_FLTR_BW_1,375 rfbw >> 8);376 lgdt3305_write_reg(state, LGDT3305_RFAGC_LOOP_FLTR_BW_2,377 rfbw & 0xff);378 } else {379 lg_dbg("ifbw: 0x%04x\n", ifbw);380 381 /* if agc loop filter bandwidth */382 lgdt3305_write_reg(state, LGDT3305_IFBW_1, ifbw >> 8);383 lgdt3305_write_reg(state, LGDT3305_IFBW_2, ifbw & 0xff);384 }385 386 return 0;387}388 389static int lgdt3305_agc_setup(struct lgdt3305_state *state,390 struct dtv_frontend_properties *p)391{392 int lockdten, acqen;393 394 switch (p->modulation) {395 case VSB_8:396 lockdten = 0;397 acqen = 0;398 break;399 case QAM_64:400 case QAM_256:401 lockdten = 1;402 acqen = 1;403 break;404 default:405 return -EINVAL;406 }407 408 lg_dbg("lockdten = %d, acqen = %d\n", lockdten, acqen);409 410 /* control agc function */411 switch (state->cfg->demod_chip) {412 case LGDT3304:413 lgdt3305_write_reg(state, 0x0314, 0xe1 | lockdten << 1);414 lgdt3305_set_reg_bit(state, 0x030e, 2, acqen);415 break;416 case LGDT3305:417 lgdt3305_write_reg(state, LGDT3305_AGC_CTRL_4, 0xe1 | lockdten << 1);418 lgdt3305_set_reg_bit(state, LGDT3305_AGC_CTRL_1, 2, acqen);419 break;420 default:421 return -EINVAL;422 }423 424 return lgdt3305_rfagc_loop(state, p);425}426 427static int lgdt3305_set_agc_power_ref(struct lgdt3305_state *state,428 struct dtv_frontend_properties *p)429{430 u16 usref = 0;431 432 switch (p->modulation) {433 case VSB_8:434 if (state->cfg->usref_8vsb)435 usref = state->cfg->usref_8vsb;436 break;437 case QAM_64:438 if (state->cfg->usref_qam64)439 usref = state->cfg->usref_qam64;440 break;441 case QAM_256:442 if (state->cfg->usref_qam256)443 usref = state->cfg->usref_qam256;444 break;445 default:446 return -EINVAL;447 }448 449 if (usref) {450 lg_dbg("set manual mode: 0x%04x\n", usref);451 452 lgdt3305_set_reg_bit(state, LGDT3305_AGC_CTRL_1, 3, 1);453 454 lgdt3305_write_reg(state, LGDT3305_AGC_POWER_REF_1,455 0xff & (usref >> 8));456 lgdt3305_write_reg(state, LGDT3305_AGC_POWER_REF_2,457 0xff & (usref >> 0));458 }459 return 0;460}461 462/* ------------------------------------------------------------------------ */463 464static int lgdt3305_spectral_inversion(struct lgdt3305_state *state,465 struct dtv_frontend_properties *p,466 int inversion)467{468 int ret;469 470 lg_dbg("(%d)\n", inversion);471 472 switch (p->modulation) {473 case VSB_8:474 ret = lgdt3305_write_reg(state, LGDT3305_CR_CTRL_7,475 inversion ? 0xf9 : 0x79);476 break;477 case QAM_64:478 case QAM_256:479 ret = lgdt3305_write_reg(state, LGDT3305_FEC_BLOCK_CTRL,480 inversion ? 0xfd : 0xff);481 break;482 default:483 ret = -EINVAL;484 }485 return ret;486}487 488static int lgdt3305_set_if(struct lgdt3305_state *state,489 struct dtv_frontend_properties *p)490{491 u16 if_freq_khz;492 u8 nco1, nco2, nco3, nco4;493 u64 nco;494 495 switch (p->modulation) {496 case VSB_8:497 if_freq_khz = state->cfg->vsb_if_khz;498 break;499 case QAM_64:500 case QAM_256:501 if_freq_khz = state->cfg->qam_if_khz;502 break;503 default:504 return -EINVAL;505 }506 507 nco = if_freq_khz / 10;508 509 switch (p->modulation) {510 case VSB_8:511 nco <<= 24;512 do_div(nco, 625);513 break;514 case QAM_64:515 case QAM_256:516 nco <<= 28;517 do_div(nco, 625);518 break;519 default:520 return -EINVAL;521 }522 523 nco1 = (nco >> 24) & 0x3f;524 nco1 |= 0x40;525 nco2 = (nco >> 16) & 0xff;526 nco3 = (nco >> 8) & 0xff;527 nco4 = nco & 0xff;528 529 lgdt3305_write_reg(state, LGDT3305_CR_CTR_FREQ_1, nco1);530 lgdt3305_write_reg(state, LGDT3305_CR_CTR_FREQ_2, nco2);531 lgdt3305_write_reg(state, LGDT3305_CR_CTR_FREQ_3, nco3);532 lgdt3305_write_reg(state, LGDT3305_CR_CTR_FREQ_4, nco4);533 534 lg_dbg("%d KHz -> [%02x%02x%02x%02x]\n",535 if_freq_khz, nco1, nco2, nco3, nco4);536 537 return 0;538}539 540/* ------------------------------------------------------------------------ */541 542static int lgdt3305_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)543{544 struct lgdt3305_state *state = fe->demodulator_priv;545 546 if (state->cfg->deny_i2c_rptr)547 return 0;548 549 lg_dbg("(%d)\n", enable);550 551 return lgdt3305_set_reg_bit(state, LGDT3305_GEN_CTRL_2, 5,552 enable ? 0 : 1);553}554 555static int lgdt3305_sleep(struct dvb_frontend *fe)556{557 struct lgdt3305_state *state = fe->demodulator_priv;558 u8 gen_ctrl_3, gen_ctrl_4;559 560 lg_dbg("\n");561 562 gen_ctrl_3 = read_reg(state, LGDT3305_GEN_CTRL_3);563 gen_ctrl_4 = read_reg(state, LGDT3305_GEN_CTRL_4);564 565 /* hold in software reset while sleeping */566 gen_ctrl_3 &= ~0x01;567 /* tristate the IF-AGC pin */568 gen_ctrl_3 |= 0x02;569 /* tristate the RF-AGC pin */570 gen_ctrl_3 |= 0x04;571 572 /* disable vsb/qam module */573 gen_ctrl_4 &= ~0x01;574 /* disable adc module */575 gen_ctrl_4 &= ~0x02;576 577 lgdt3305_write_reg(state, LGDT3305_GEN_CTRL_3, gen_ctrl_3);578 lgdt3305_write_reg(state, LGDT3305_GEN_CTRL_4, gen_ctrl_4);579 580 return 0;581}582 583static int lgdt3305_init(struct dvb_frontend *fe)584{585 struct lgdt3305_state *state = fe->demodulator_priv;586 int ret;587 588 static struct lgdt3305_reg lgdt3304_init_data[] = {589 { .reg = LGDT3305_GEN_CTRL_1, .val = 0x03, },590 { .reg = 0x000d, .val = 0x02, },591 { .reg = 0x000e, .val = 0x02, },592 { .reg = LGDT3305_DGTL_AGC_REF_1, .val = 0x32, },593 { .reg = LGDT3305_DGTL_AGC_REF_2, .val = 0xc4, },594 { .reg = LGDT3305_CR_CTR_FREQ_1, .val = 0x00, },595 { .reg = LGDT3305_CR_CTR_FREQ_2, .val = 0x00, },596 { .reg = LGDT3305_CR_CTR_FREQ_3, .val = 0x00, },597 { .reg = LGDT3305_CR_CTR_FREQ_4, .val = 0x00, },598 { .reg = LGDT3305_CR_CTRL_7, .val = 0xf9, },599 { .reg = 0x0112, .val = 0x17, },600 { .reg = 0x0113, .val = 0x15, },601 { .reg = 0x0114, .val = 0x18, },602 { .reg = 0x0115, .val = 0xff, },603 { .reg = 0x0116, .val = 0x3c, },604 { .reg = 0x0214, .val = 0x67, },605 { .reg = 0x0424, .val = 0x8d, },606 { .reg = 0x0427, .val = 0x12, },607 { .reg = 0x0428, .val = 0x4f, },608 { .reg = LGDT3305_IFBW_1, .val = 0x80, },609 { .reg = LGDT3305_IFBW_2, .val = 0x00, },610 { .reg = 0x030a, .val = 0x08, },611 { .reg = 0x030b, .val = 0x9b, },612 { .reg = 0x030d, .val = 0x00, },613 { .reg = 0x030e, .val = 0x1c, },614 { .reg = 0x0314, .val = 0xe1, },615 { .reg = 0x000d, .val = 0x82, },616 { .reg = LGDT3305_TP_CTRL_1, .val = 0x5b, },617 { .reg = LGDT3305_TP_CTRL_1, .val = 0x5b, },618 };619 620 static struct lgdt3305_reg lgdt3305_init_data[] = {621 { .reg = LGDT3305_GEN_CTRL_1, .val = 0x03, },622 { .reg = LGDT3305_GEN_CTRL_2, .val = 0xb0, },623 { .reg = LGDT3305_GEN_CTRL_3, .val = 0x01, },624 { .reg = LGDT3305_GEN_CONTROL, .val = 0x6f, },625 { .reg = LGDT3305_GEN_CTRL_4, .val = 0x03, },626 { .reg = LGDT3305_DGTL_AGC_REF_1, .val = 0x32, },627 { .reg = LGDT3305_DGTL_AGC_REF_2, .val = 0xc4, },628 { .reg = LGDT3305_CR_CTR_FREQ_1, .val = 0x00, },629 { .reg = LGDT3305_CR_CTR_FREQ_2, .val = 0x00, },630 { .reg = LGDT3305_CR_CTR_FREQ_3, .val = 0x00, },631 { .reg = LGDT3305_CR_CTR_FREQ_4, .val = 0x00, },632 { .reg = LGDT3305_CR_CTRL_7, .val = 0x79, },633 { .reg = LGDT3305_AGC_POWER_REF_1, .val = 0x32, },634 { .reg = LGDT3305_AGC_POWER_REF_2, .val = 0xc4, },635 { .reg = LGDT3305_AGC_DELAY_PT_1, .val = 0x0d, },636 { .reg = LGDT3305_AGC_DELAY_PT_2, .val = 0x30, },637 { .reg = LGDT3305_RFAGC_LOOP_FLTR_BW_1, .val = 0x80, },638 { .reg = LGDT3305_RFAGC_LOOP_FLTR_BW_2, .val = 0x00, },639 { .reg = LGDT3305_IFBW_1, .val = 0x80, },640 { .reg = LGDT3305_IFBW_2, .val = 0x00, },641 { .reg = LGDT3305_AGC_CTRL_1, .val = 0x30, },642 { .reg = LGDT3305_AGC_CTRL_4, .val = 0x61, },643 { .reg = LGDT3305_FEC_BLOCK_CTRL, .val = 0xff, },644 { .reg = LGDT3305_TP_CTRL_1, .val = 0x1b, },645 };646 647 lg_dbg("\n");648 649 switch (state->cfg->demod_chip) {650 case LGDT3304:651 ret = lgdt3305_write_regs(state, lgdt3304_init_data,652 ARRAY_SIZE(lgdt3304_init_data));653 break;654 case LGDT3305:655 ret = lgdt3305_write_regs(state, lgdt3305_init_data,656 ARRAY_SIZE(lgdt3305_init_data));657 break;658 default:659 ret = -EINVAL;660 }661 if (lg_fail(ret))662 goto fail;663 664 ret = lgdt3305_soft_reset(state);665fail:666 return ret;667}668 669static int lgdt3304_set_parameters(struct dvb_frontend *fe)670{671 struct dtv_frontend_properties *p = &fe->dtv_property_cache;672 struct lgdt3305_state *state = fe->demodulator_priv;673 int ret;674 675 lg_dbg("(%d, %d)\n", p->frequency, p->modulation);676 677 if (fe->ops.tuner_ops.set_params) {678 ret = fe->ops.tuner_ops.set_params(fe);679 if (fe->ops.i2c_gate_ctrl)680 fe->ops.i2c_gate_ctrl(fe, 0);681 if (lg_fail(ret))682 goto fail;683 state->current_frequency = p->frequency;684 }685 686 ret = lgdt3305_set_modulation(state, p);687 if (lg_fail(ret))688 goto fail;689 690 ret = lgdt3305_passband_digital_agc(state, p);691 if (lg_fail(ret))692 goto fail;693 694 ret = lgdt3305_agc_setup(state, p);695 if (lg_fail(ret))696 goto fail;697 698 /* reg 0x030d is 3304-only... seen in vsb and qam usbsnoops... */699 switch (p->modulation) {700 case VSB_8:701 lgdt3305_write_reg(state, 0x030d, 0x00);702 lgdt3305_write_reg(state, LGDT3305_CR_CTR_FREQ_1, 0x4f);703 lgdt3305_write_reg(state, LGDT3305_CR_CTR_FREQ_2, 0x0c);704 lgdt3305_write_reg(state, LGDT3305_CR_CTR_FREQ_3, 0xac);705 lgdt3305_write_reg(state, LGDT3305_CR_CTR_FREQ_4, 0xba);706 break;707 case QAM_64:708 case QAM_256:709 lgdt3305_write_reg(state, 0x030d, 0x14);710 ret = lgdt3305_set_if(state, p);711 if (lg_fail(ret))712 goto fail;713 break;714 default:715 return -EINVAL;716 }717 718 719 ret = lgdt3305_spectral_inversion(state, p,720 state->cfg->spectral_inversion721 ? 1 : 0);722 if (lg_fail(ret))723 goto fail;724 725 state->current_modulation = p->modulation;726 727 ret = lgdt3305_mpeg_mode(state, state->cfg->mpeg_mode);728 if (lg_fail(ret))729 goto fail;730 731 /* lgdt3305_mpeg_mode_polarity calls lgdt3305_soft_reset */732 ret = lgdt3305_mpeg_mode_polarity(state);733fail:734 return ret;735}736 737static int lgdt3305_set_parameters(struct dvb_frontend *fe)738{739 struct dtv_frontend_properties *p = &fe->dtv_property_cache;740 struct lgdt3305_state *state = fe->demodulator_priv;741 int ret;742 743 lg_dbg("(%d, %d)\n", p->frequency, p->modulation);744 745 if (fe->ops.tuner_ops.set_params) {746 ret = fe->ops.tuner_ops.set_params(fe);747 if (fe->ops.i2c_gate_ctrl)748 fe->ops.i2c_gate_ctrl(fe, 0);749 if (lg_fail(ret))750 goto fail;751 state->current_frequency = p->frequency;752 }753 754 ret = lgdt3305_set_modulation(state, p);755 if (lg_fail(ret))756 goto fail;757 758 ret = lgdt3305_passband_digital_agc(state, p);759 if (lg_fail(ret))760 goto fail;761 ret = lgdt3305_set_agc_power_ref(state, p);762 if (lg_fail(ret))763 goto fail;764 ret = lgdt3305_agc_setup(state, p);765 if (lg_fail(ret))766 goto fail;767 768 /* low if */769 ret = lgdt3305_write_reg(state, LGDT3305_GEN_CONTROL, 0x2f);770 if (lg_fail(ret))771 goto fail;772 ret = lgdt3305_set_reg_bit(state, LGDT3305_CR_CTR_FREQ_1, 6, 1);773 if (lg_fail(ret))774 goto fail;775 776 ret = lgdt3305_set_if(state, p);777 if (lg_fail(ret))778 goto fail;779 ret = lgdt3305_spectral_inversion(state, p,780 state->cfg->spectral_inversion781 ? 1 : 0);782 if (lg_fail(ret))783 goto fail;784 785 ret = lgdt3305_set_filter_extension(state, p);786 if (lg_fail(ret))787 goto fail;788 789 state->current_modulation = p->modulation;790 791 ret = lgdt3305_mpeg_mode(state, state->cfg->mpeg_mode);792 if (lg_fail(ret))793 goto fail;794 795 /* lgdt3305_mpeg_mode_polarity calls lgdt3305_soft_reset */796 ret = lgdt3305_mpeg_mode_polarity(state);797fail:798 return ret;799}800 801static int lgdt3305_get_frontend(struct dvb_frontend *fe,802 struct dtv_frontend_properties *p)803{804 struct lgdt3305_state *state = fe->demodulator_priv;805 806 lg_dbg("\n");807 808 p->modulation = state->current_modulation;809 p->frequency = state->current_frequency;810 return 0;811}812 813/* ------------------------------------------------------------------------ */814 815static int lgdt3305_read_cr_lock_status(struct lgdt3305_state *state,816 int *locked)817{818 u8 val;819 int ret;820 char *cr_lock_state = "";821 822 *locked = 0;823 824 ret = lgdt3305_read_reg(state, LGDT3305_CR_LOCK_STATUS, &val);825 if (lg_fail(ret))826 goto fail;827 828 switch (state->current_modulation) {829 case QAM_256:830 case QAM_64:831 if (val & (1 << 1))832 *locked = 1;833 834 switch (val & 0x07) {835 case 0:836 cr_lock_state = "QAM UNLOCK";837 break;838 case 4:839 cr_lock_state = "QAM 1stLock";840 break;841 case 6:842 cr_lock_state = "QAM 2ndLock";843 break;844 case 7:845 cr_lock_state = "QAM FinalLock";846 break;847 default:848 cr_lock_state = "CLOCKQAM-INVALID!";849 break;850 }851 break;852 case VSB_8:853 if (val & (1 << 7)) {854 *locked = 1;855 cr_lock_state = "CLOCKVSB";856 }857 break;858 default:859 ret = -EINVAL;860 }861 lg_dbg("(%d) %s\n", *locked, cr_lock_state);862fail:863 return ret;864}865 866static int lgdt3305_read_fec_lock_status(struct lgdt3305_state *state,867 int *locked)868{869 u8 val;870 int ret, mpeg_lock, fec_lock, viterbi_lock;871 872 *locked = 0;873 874 switch (state->current_modulation) {875 case QAM_256:876 case QAM_64:877 ret = lgdt3305_read_reg(state,878 LGDT3305_FEC_LOCK_STATUS, &val);879 if (lg_fail(ret))880 goto fail;881 882 mpeg_lock = (val & (1 << 0)) ? 1 : 0;883 fec_lock = (val & (1 << 2)) ? 1 : 0;884 viterbi_lock = (val & (1 << 3)) ? 1 : 0;885 886 *locked = mpeg_lock && fec_lock && viterbi_lock;887 888 lg_dbg("(%d) %s%s%s\n", *locked,889 mpeg_lock ? "mpeg lock " : "",890 fec_lock ? "fec lock " : "",891 viterbi_lock ? "viterbi lock" : "");892 break;893 case VSB_8:894 default:895 ret = -EINVAL;896 }897fail:898 return ret;899}900 901static int lgdt3305_read_status(struct dvb_frontend *fe, enum fe_status *status)902{903 struct lgdt3305_state *state = fe->demodulator_priv;904 u8 val;905 int ret, signal, inlock, nofecerr, snrgood,906 cr_lock, fec_lock, sync_lock;907 908 *status = 0;909 910 ret = lgdt3305_read_reg(state, LGDT3305_GEN_STATUS, &val);911 if (lg_fail(ret))912 goto fail;913 914 signal = (val & (1 << 4)) ? 1 : 0;915 inlock = (val & (1 << 3)) ? 0 : 1;916 sync_lock = (val & (1 << 2)) ? 1 : 0;917 nofecerr = (val & (1 << 1)) ? 1 : 0;918 snrgood = (val & (1 << 0)) ? 1 : 0;919 920 lg_dbg("%s%s%s%s%s\n",921 signal ? "SIGNALEXIST " : "",922 inlock ? "INLOCK " : "",923 sync_lock ? "SYNCLOCK " : "",924 nofecerr ? "NOFECERR " : "",925 snrgood ? "SNRGOOD " : "");926 927 ret = lgdt3305_read_cr_lock_status(state, &cr_lock);928 if (lg_fail(ret))929 goto fail;930 931 if (signal)932 *status |= FE_HAS_SIGNAL;933 if (cr_lock)934 *status |= FE_HAS_CARRIER;935 if (nofecerr)936 *status |= FE_HAS_VITERBI;937 if (sync_lock)938 *status |= FE_HAS_SYNC;939 940 switch (state->current_modulation) {941 case QAM_256:942 case QAM_64:943 /* signal bit is unreliable on the DT3304 in QAM mode */944 if (((LGDT3304 == state->cfg->demod_chip)) && (cr_lock))945 *status |= FE_HAS_SIGNAL;946 947 ret = lgdt3305_read_fec_lock_status(state, &fec_lock);948 if (lg_fail(ret))949 goto fail;950 951 if (fec_lock)952 *status |= FE_HAS_LOCK;953 break;954 case VSB_8:955 if (inlock)956 *status |= FE_HAS_LOCK;957 break;958 default:959 ret = -EINVAL;960 }961fail:962 return ret;963}964 965/* ------------------------------------------------------------------------ */966 967/* borrowed from lgdt330x.c */968static u32 calculate_snr(u32 mse, u32 c)969{970 if (mse == 0) /* no signal */971 return 0;972 973 mse = intlog10(mse);974 if (mse > c) {975 /* Negative SNR, which is possible, but realisticly the976 demod will lose lock before the signal gets this bad. The977 API only allows for unsigned values, so just return 0 */978 return 0;979 }980 return 10*(c - mse);981}982 983static int lgdt3305_read_snr(struct dvb_frontend *fe, u16 *snr)984{985 struct lgdt3305_state *state = fe->demodulator_priv;986 u32 noise; /* noise value */987 u32 c; /* per-modulation SNR calculation constant */988 989 switch (state->current_modulation) {990 case VSB_8:991#ifdef USE_PTMSE992 /* Use Phase Tracker Mean-Square Error Register */993 /* SNR for ranges from -13.11 to +44.08 */994 noise = ((read_reg(state, LGDT3305_PT_MSE_1) & 0x07) << 16) |995 (read_reg(state, LGDT3305_PT_MSE_2) << 8) |996 (read_reg(state, LGDT3305_PT_MSE_3) & 0xff);997 c = 73957994; /* log10(25*32^2)*2^24 */998#else999 /* Use Equalizer Mean-Square Error Register */1000 /* SNR for ranges from -16.12 to +44.08 */1001 noise = ((read_reg(state, LGDT3305_EQ_MSE_1) & 0x0f) << 16) |1002 (read_reg(state, LGDT3305_EQ_MSE_2) << 8) |1003 (read_reg(state, LGDT3305_EQ_MSE_3) & 0xff);1004 c = 73957994; /* log10(25*32^2)*2^24 */1005#endif1006 break;1007 case QAM_64:1008 case QAM_256:1009 noise = (read_reg(state, LGDT3305_CR_MSE_1) << 8) |1010 (read_reg(state, LGDT3305_CR_MSE_2) & 0xff);1011 1012 c = (state->current_modulation == QAM_64) ?1013 97939837 : 98026066;1014 /* log10(688128)*2^24 and log10(696320)*2^24 */1015 break;1016 default:1017 return -EINVAL;1018 }1019 state->snr = calculate_snr(noise, c);1020 /* report SNR in dB * 10 */1021 *snr = (state->snr / ((1 << 24) / 10));1022 lg_dbg("noise = 0x%08x, snr = %d.%02d dB\n", noise,1023 state->snr >> 24, (((state->snr >> 8) & 0xffff) * 100) >> 16);1024 1025 return 0;1026}1027 1028static int lgdt3305_read_signal_strength(struct dvb_frontend *fe,1029 u16 *strength)1030{1031 /* borrowed from lgdt330x.c1032 *1033 * Calculate strength from SNR up to 35dB1034 * Even though the SNR can go higher than 35dB,1035 * there is some comfort factor in having a range of1036 * strong signals that can show at 100%1037 */1038 struct lgdt3305_state *state = fe->demodulator_priv;1039 u16 snr;1040 int ret;1041 1042 *strength = 0;1043 1044 ret = fe->ops.read_snr(fe, &snr);1045 if (lg_fail(ret))1046 goto fail;1047 /* Rather than use the 8.8 value snr, use state->snr which is 8.24 */1048 /* scale the range 0 - 35*2^24 into 0 - 65535 */1049 if (state->snr >= 8960 * 0x10000)1050 *strength = 0xffff;1051 else1052 *strength = state->snr / 8960;1053fail:1054 return ret;1055}1056 1057/* ------------------------------------------------------------------------ */1058 1059static int lgdt3305_read_ber(struct dvb_frontend *fe, u32 *ber)1060{1061 *ber = 0;1062 return 0;1063}1064 1065static int lgdt3305_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)1066{1067 struct lgdt3305_state *state = fe->demodulator_priv;1068 1069 *ucblocks =1070 (read_reg(state, LGDT3305_FEC_PKT_ERR_1) << 8) |1071 (read_reg(state, LGDT3305_FEC_PKT_ERR_2) & 0xff);1072 1073 return 0;1074}1075 1076static int lgdt3305_get_tune_settings(struct dvb_frontend *fe,1077 struct dvb_frontend_tune_settings1078 *fe_tune_settings)1079{1080 fe_tune_settings->min_delay_ms = 500;1081 lg_dbg("\n");1082 return 0;1083}1084 1085static void lgdt3305_release(struct dvb_frontend *fe)1086{1087 struct lgdt3305_state *state = fe->demodulator_priv;1088 lg_dbg("\n");1089 kfree(state);1090}1091 1092static const struct dvb_frontend_ops lgdt3304_ops;1093static const struct dvb_frontend_ops lgdt3305_ops;1094 1095struct dvb_frontend *lgdt3305_attach(const struct lgdt3305_config *config,1096 struct i2c_adapter *i2c_adap)1097{1098 struct lgdt3305_state *state = NULL;1099 int ret;1100 u8 val;1101 1102 lg_dbg("(%d-%04x)\n",1103 i2c_adap ? i2c_adapter_id(i2c_adap) : 0,1104 config ? config->i2c_addr : 0);1105 1106 state = kzalloc(sizeof(struct lgdt3305_state), GFP_KERNEL);1107 if (state == NULL)1108 goto fail;1109 1110 state->cfg = config;1111 state->i2c_adap = i2c_adap;1112 1113 switch (config->demod_chip) {1114 case LGDT3304:1115 memcpy(&state->frontend.ops, &lgdt3304_ops,1116 sizeof(struct dvb_frontend_ops));1117 break;1118 case LGDT3305:1119 memcpy(&state->frontend.ops, &lgdt3305_ops,1120 sizeof(struct dvb_frontend_ops));1121 break;1122 default:1123 goto fail;1124 }1125 state->frontend.demodulator_priv = state;1126 1127 /* verify that we're talking to a lg dt3304/5 */1128 ret = lgdt3305_read_reg(state, LGDT3305_GEN_CTRL_2, &val);1129 if ((lg_fail(ret)) | (val == 0))1130 goto fail;1131 ret = lgdt3305_write_reg(state, 0x0808, 0x80);1132 if (lg_fail(ret))1133 goto fail;1134 ret = lgdt3305_read_reg(state, 0x0808, &val);1135 if ((lg_fail(ret)) | (val != 0x80))1136 goto fail;1137 ret = lgdt3305_write_reg(state, 0x0808, 0x00);1138 if (lg_fail(ret))1139 goto fail;1140 1141 state->current_frequency = -1;1142 state->current_modulation = -1;1143 1144 return &state->frontend;1145fail:1146 lg_warn("unable to detect %s hardware\n",1147 config->demod_chip ? "LGDT3304" : "LGDT3305");1148 kfree(state);1149 return NULL;1150}1151EXPORT_SYMBOL_GPL(lgdt3305_attach);1152 1153static const struct dvb_frontend_ops lgdt3304_ops = {1154 .delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B },1155 .info = {1156 .name = "LG Electronics LGDT3304 VSB/QAM Frontend",1157 .frequency_min_hz = 54 * MHz,1158 .frequency_max_hz = 858 * MHz,1159 .frequency_stepsize_hz = 62500,1160 .caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB1161 },1162 .i2c_gate_ctrl = lgdt3305_i2c_gate_ctrl,1163 .init = lgdt3305_init,1164 .sleep = lgdt3305_sleep,1165 .set_frontend = lgdt3304_set_parameters,1166 .get_frontend = lgdt3305_get_frontend,1167 .get_tune_settings = lgdt3305_get_tune_settings,1168 .read_status = lgdt3305_read_status,1169 .read_ber = lgdt3305_read_ber,1170 .read_signal_strength = lgdt3305_read_signal_strength,1171 .read_snr = lgdt3305_read_snr,1172 .read_ucblocks = lgdt3305_read_ucblocks,1173 .release = lgdt3305_release,1174};1175 1176static const struct dvb_frontend_ops lgdt3305_ops = {1177 .delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B },1178 .info = {1179 .name = "LG Electronics LGDT3305 VSB/QAM Frontend",1180 .frequency_min_hz = 54 * MHz,1181 .frequency_max_hz = 858 * MHz,1182 .frequency_stepsize_hz = 62500,1183 .caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB1184 },1185 .i2c_gate_ctrl = lgdt3305_i2c_gate_ctrl,1186 .init = lgdt3305_init,1187 .sleep = lgdt3305_sleep,1188 .set_frontend = lgdt3305_set_parameters,1189 .get_frontend = lgdt3305_get_frontend,1190 .get_tune_settings = lgdt3305_get_tune_settings,1191 .read_status = lgdt3305_read_status,1192 .read_ber = lgdt3305_read_ber,1193 .read_signal_strength = lgdt3305_read_signal_strength,1194 .read_snr = lgdt3305_read_snr,1195 .read_ucblocks = lgdt3305_read_ucblocks,1196 .release = lgdt3305_release,1197};1198 1199MODULE_DESCRIPTION("LG Electronics LGDT3304/5 ATSC/QAM-B Demodulator Driver");1200MODULE_AUTHOR("Michael Krufky <mkrufky@linuxtv.org>");1201MODULE_LICENSE("GPL");1202MODULE_VERSION("0.2");1203