aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJarod Wilson <jarod@redhat.com>2010-03-07 15:20:03 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2010-08-02 13:45:34 -0400
commit804258c95f9b782b1916eeb4fe280b119ad5b152 (patch)
tree8bce57b91383c9f192ecef3410d8c0d97db1289a
parent5b0ff8c43afefbd42a1aa3cd89808eec829bbbb7 (diff)
V4L/DVB: dvb: add lgdt3304 support to lgdt3305 driver
There's a currently-unused lgdt3304 demod driver, which leaves a lot to be desired as far as functionality. The 3304 is unsurprisingly quite similar to the 3305, and empirical testing yeilds far better results and more complete functionality by merging 3304 support into the 3305 driver. (For example, the current lgdt3304 driver lacks support for signal strength, snr, ucblocks, etc., which we get w/the lgdt3305). For the moment, not dropping the lgdt3304 driver, and its still up to a given device's config setup to choose which demod driver to use, but I'd suggest dropping the 3304 driver entirely. As a follow-up to this patch, I've got another patch that adds support for the KWorld PlusTV 340U (ATSC) em2870-based tuner stick, driving its lgdt3304 demod via this lgdt3305 driver, which is what I used to successfully test this patch with both VSB_8 and QAM_256 signals. A few pieces are still a touch crude, but I think its a solid start, as well as much cleaner and more feature-complete than the existing lgdt3304 driver. Signed-off-by: Jarod Wilson <jarod@redhat.com> Signed-off-by: Michael Krufky <mkrufky@kernellabs.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r--drivers/media/dvb/frontends/lgdt3305.c190
-rw-r--r--drivers/media/dvb/frontends/lgdt3305.h6
2 files changed, 187 insertions, 9 deletions
diff --git a/drivers/media/dvb/frontends/lgdt3305.c b/drivers/media/dvb/frontends/lgdt3305.c
index d69c775f864..d329d6abef8 100644
--- a/drivers/media/dvb/frontends/lgdt3305.c
+++ b/drivers/media/dvb/frontends/lgdt3305.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Support for LGDT3305 - VSB/QAM 2 * Support for LG Electronics LGDT3304 and LGDT3305 - VSB/QAM
3 * 3 *
4 * Copyright (C) 2008, 2009 Michael Krufky <mkrufky@linuxtv.org> 4 * Copyright (C) 2008, 2009 Michael Krufky <mkrufky@linuxtv.org>
5 * 5 *
@@ -358,7 +358,10 @@ static int lgdt3305_rfagc_loop(struct lgdt3305_state *state,
358 case QAM_256: 358 case QAM_256:
359 agcdelay = 0x046b; 359 agcdelay = 0x046b;
360 rfbw = 0x8889; 360 rfbw = 0x8889;
361 ifbw = 0x8888; 361 if (state->cfg->demod_chip == LGDT3305)
362 ifbw = 0x8888;
363 else
364 ifbw = 0x6666;
362 break; 365 break;
363 default: 366 default:
364 return -EINVAL; 367 return -EINVAL;
@@ -410,8 +413,18 @@ static int lgdt3305_agc_setup(struct lgdt3305_state *state,
410 lg_dbg("lockdten = %d, acqen = %d\n", lockdten, acqen); 413 lg_dbg("lockdten = %d, acqen = %d\n", lockdten, acqen);
411 414
412 /* control agc function */ 415 /* control agc function */
413 lgdt3305_write_reg(state, LGDT3305_AGC_CTRL_4, 0xe1 | lockdten << 1); 416 switch (state->cfg->demod_chip) {
414 lgdt3305_set_reg_bit(state, LGDT3305_AGC_CTRL_1, 2, acqen); 417 case LGDT3304:
418 lgdt3305_write_reg(state, 0x0314, 0xe1 | lockdten << 1);
419 lgdt3305_set_reg_bit(state, 0x030e, 2, acqen);
420 break;
421 case LGDT3305:
422 lgdt3305_write_reg(state, LGDT3305_AGC_CTRL_4, 0xe1 | lockdten << 1);
423 lgdt3305_set_reg_bit(state, LGDT3305_AGC_CTRL_1, 2, acqen);
424 break;
425 default:
426 return -EINVAL;
427 }
415 428
416 return lgdt3305_rfagc_loop(state, param); 429 return lgdt3305_rfagc_loop(state, param);
417} 430}
@@ -544,6 +557,11 @@ static int lgdt3305_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
544 enable ? 0 : 1); 557 enable ? 0 : 1);
545} 558}
546 559
560static int lgdt3304_sleep(struct dvb_frontend *fe)
561{
562 return 0;
563}
564
547static int lgdt3305_sleep(struct dvb_frontend *fe) 565static int lgdt3305_sleep(struct dvb_frontend *fe)
548{ 566{
549 struct lgdt3305_state *state = fe->demodulator_priv; 567 struct lgdt3305_state *state = fe->demodulator_priv;
@@ -572,6 +590,55 @@ static int lgdt3305_sleep(struct dvb_frontend *fe)
572 return 0; 590 return 0;
573} 591}
574 592
593static int lgdt3304_init(struct dvb_frontend *fe)
594{
595 struct lgdt3305_state *state = fe->demodulator_priv;
596 int ret;
597
598 static struct lgdt3305_reg lgdt3304_init_data[] = {
599 { .reg = LGDT3305_GEN_CTRL_1, .val = 0x03, },
600 { .reg = 0x000d, .val = 0x02, },
601 { .reg = 0x000e, .val = 0x02, },
602 { .reg = LGDT3305_DGTL_AGC_REF_1, .val = 0x32, },
603 { .reg = LGDT3305_DGTL_AGC_REF_2, .val = 0xc4, },
604 { .reg = LGDT3305_CR_CTR_FREQ_1, .val = 0x00, },
605 { .reg = LGDT3305_CR_CTR_FREQ_2, .val = 0x00, },
606 { .reg = LGDT3305_CR_CTR_FREQ_3, .val = 0x00, },
607 { .reg = LGDT3305_CR_CTR_FREQ_4, .val = 0x00, },
608 { .reg = LGDT3305_CR_CTRL_7, .val = 0xf9, },
609 { .reg = 0x0112, .val = 0x17, },
610 { .reg = 0x0113, .val = 0x15, },
611 { .reg = 0x0114, .val = 0x18, },
612 { .reg = 0x0115, .val = 0xff, },
613 { .reg = 0x0116, .val = 0x3c, },
614 { .reg = 0x0214, .val = 0x67, },
615 { .reg = 0x0424, .val = 0x8d, },
616 { .reg = 0x0427, .val = 0x12, },
617 { .reg = 0x0428, .val = 0x4f, },
618 { .reg = LGDT3305_IFBW_1, .val = 0x80, },
619 { .reg = LGDT3305_IFBW_2, .val = 0x00, },
620 { .reg = 0x030a, .val = 0x08, },
621 { .reg = 0x030b, .val = 0x9b, },
622 { .reg = 0x030d, .val = 0x00, },
623 { .reg = 0x030e, .val = 0x1c, },
624 { .reg = 0x0314, .val = 0xe1, },
625 { .reg = 0x000d, .val = 0x82, },
626 { .reg = LGDT3305_TP_CTRL_1, .val = 0x5b, },
627 { .reg = LGDT3305_TP_CTRL_1, .val = 0x5b, },
628 };
629
630 lg_dbg("\n");
631
632 ret = lgdt3305_write_regs(state, lgdt3304_init_data,
633 ARRAY_SIZE(lgdt3304_init_data));
634 if (lg_fail(ret))
635 goto fail;
636
637 ret = lgdt3305_soft_reset(state);
638fail:
639 return ret;
640}
641
575static int lgdt3305_init(struct dvb_frontend *fe) 642static int lgdt3305_init(struct dvb_frontend *fe)
576{ 643{
577 struct lgdt3305_state *state = fe->demodulator_priv; 644 struct lgdt3305_state *state = fe->demodulator_priv;
@@ -640,6 +707,76 @@ fail:
640 return ret; 707 return ret;
641} 708}
642 709
710static int lgdt3304_set_parameters(struct dvb_frontend *fe,
711 struct dvb_frontend_parameters *param)
712{
713 struct lgdt3305_state *state = fe->demodulator_priv;
714 int ret;
715
716 lg_dbg("(%d, %d)\n", param->frequency, param->u.vsb.modulation);
717
718 if (fe->ops.tuner_ops.set_params) {
719 ret = fe->ops.tuner_ops.set_params(fe, param);
720 if (fe->ops.i2c_gate_ctrl)
721 fe->ops.i2c_gate_ctrl(fe, 0);
722 if (lg_fail(ret))
723 goto fail;
724 state->current_frequency = param->frequency;
725 }
726
727 ret = lgdt3305_set_modulation(state, param);
728 if (lg_fail(ret))
729 goto fail;
730
731 ret = lgdt3305_passband_digital_agc(state, param);
732 if (lg_fail(ret))
733 goto fail;
734
735 ret = lgdt3305_agc_setup(state, param);
736 if (lg_fail(ret))
737 goto fail;
738
739 /* reg 0x030d is 3304-only... seen in vsb and qam usbsnoops... */
740 switch (param->u.vsb.modulation) {
741 case VSB_8:
742 lgdt3305_write_reg(state, 0x030d, 0x00);
743 lgdt3305_write_reg(state, LGDT3305_CR_CTR_FREQ_1, 0x4f);
744 lgdt3305_write_reg(state, LGDT3305_CR_CTR_FREQ_2, 0x0c);
745 lgdt3305_write_reg(state, LGDT3305_CR_CTR_FREQ_3, 0xac);
746 lgdt3305_write_reg(state, LGDT3305_CR_CTR_FREQ_4, 0xba);
747 break;
748 case QAM_64:
749 case QAM_256:
750 lgdt3305_write_reg(state, 0x030d, 0x14);
751 ret = lgdt3305_set_if(state, param);
752 if (lg_fail(ret))
753 goto fail;
754 break;
755 default:
756 return -EINVAL;
757 }
758
759
760 ret = lgdt3305_spectral_inversion(state, param,
761 state->cfg->spectral_inversion
762 ? 1 : 0);
763 if (lg_fail(ret))
764 goto fail;
765
766 state->current_modulation = param->u.vsb.modulation;
767
768 ret = lgdt3305_mpeg_mode(state, state->cfg->mpeg_mode);
769 if (lg_fail(ret))
770 goto fail;
771
772 /* lgdt3305_mpeg_mode_polarity calls lgdt3305_soft_reset */
773 ret = lgdt3305_mpeg_mode_polarity(state,
774 state->cfg->tpclk_edge,
775 state->cfg->tpvalid_polarity);
776fail:
777 return ret;
778}
779
643static int lgdt3305_set_parameters(struct dvb_frontend *fe, 780static int lgdt3305_set_parameters(struct dvb_frontend *fe,
644 struct dvb_frontend_parameters *param) 781 struct dvb_frontend_parameters *param)
645{ 782{
@@ -993,6 +1130,7 @@ static void lgdt3305_release(struct dvb_frontend *fe)
993 kfree(state); 1130 kfree(state);
994} 1131}
995 1132
1133static struct dvb_frontend_ops lgdt3304_ops;
996static struct dvb_frontend_ops lgdt3305_ops; 1134static struct dvb_frontend_ops lgdt3305_ops;
997 1135
998struct dvb_frontend *lgdt3305_attach(const struct lgdt3305_config *config, 1136struct dvb_frontend *lgdt3305_attach(const struct lgdt3305_config *config,
@@ -1013,11 +1151,21 @@ struct dvb_frontend *lgdt3305_attach(const struct lgdt3305_config *config,
1013 state->cfg = config; 1151 state->cfg = config;
1014 state->i2c_adap = i2c_adap; 1152 state->i2c_adap = i2c_adap;
1015 1153
1016 memcpy(&state->frontend.ops, &lgdt3305_ops, 1154 switch (config->demod_chip) {
1017 sizeof(struct dvb_frontend_ops)); 1155 case LGDT3304:
1156 memcpy(&state->frontend.ops, &lgdt3304_ops,
1157 sizeof(struct dvb_frontend_ops));
1158 break;
1159 case LGDT3305:
1160 memcpy(&state->frontend.ops, &lgdt3305_ops,
1161 sizeof(struct dvb_frontend_ops));
1162 break;
1163 default:
1164 goto fail;
1165 }
1018 state->frontend.demodulator_priv = state; 1166 state->frontend.demodulator_priv = state;
1019 1167
1020 /* verify that we're talking to a lg dt3305 */ 1168 /* verify that we're talking to a lg dt3304/5 */
1021 ret = lgdt3305_read_reg(state, LGDT3305_GEN_CTRL_2, &val); 1169 ret = lgdt3305_read_reg(state, LGDT3305_GEN_CTRL_2, &val);
1022 if ((lg_fail(ret)) | (val == 0)) 1170 if ((lg_fail(ret)) | (val == 0))
1023 goto fail; 1171 goto fail;
@@ -1036,12 +1184,36 @@ struct dvb_frontend *lgdt3305_attach(const struct lgdt3305_config *config,
1036 1184
1037 return &state->frontend; 1185 return &state->frontend;
1038fail: 1186fail:
1039 lg_warn("unable to detect LGDT3305 hardware\n"); 1187 lg_warn("unable to detect %s hardware\n",
1188 config->demod_chip ? "LGDT3304" : "LGDT3305");
1040 kfree(state); 1189 kfree(state);
1041 return NULL; 1190 return NULL;
1042} 1191}
1043EXPORT_SYMBOL(lgdt3305_attach); 1192EXPORT_SYMBOL(lgdt3305_attach);
1044 1193
1194static struct dvb_frontend_ops lgdt3304_ops = {
1195 .info = {
1196 .name = "LG Electronics LGDT3304 VSB/QAM Frontend",
1197 .type = FE_ATSC,
1198 .frequency_min = 54000000,
1199 .frequency_max = 858000000,
1200 .frequency_stepsize = 62500,
1201 .caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB
1202 },
1203 .i2c_gate_ctrl = lgdt3305_i2c_gate_ctrl,
1204 .init = lgdt3304_init,
1205 .sleep = lgdt3304_sleep,
1206 .set_frontend = lgdt3304_set_parameters,
1207 .get_frontend = lgdt3305_get_frontend,
1208 .get_tune_settings = lgdt3305_get_tune_settings,
1209 .read_status = lgdt3305_read_status,
1210 .read_ber = lgdt3305_read_ber,
1211 .read_signal_strength = lgdt3305_read_signal_strength,
1212 .read_snr = lgdt3305_read_snr,
1213 .read_ucblocks = lgdt3305_read_ucblocks,
1214 .release = lgdt3305_release,
1215};
1216
1045static struct dvb_frontend_ops lgdt3305_ops = { 1217static struct dvb_frontend_ops lgdt3305_ops = {
1046 .info = { 1218 .info = {
1047 .name = "LG Electronics LGDT3305 VSB/QAM Frontend", 1219 .name = "LG Electronics LGDT3305 VSB/QAM Frontend",
@@ -1065,7 +1237,7 @@ static struct dvb_frontend_ops lgdt3305_ops = {
1065 .release = lgdt3305_release, 1237 .release = lgdt3305_release,
1066}; 1238};
1067 1239
1068MODULE_DESCRIPTION("LG Electronics LGDT3305 ATSC/QAM-B Demodulator Driver"); 1240MODULE_DESCRIPTION("LG Electronics LGDT3304/5 ATSC/QAM-B Demodulator Driver");
1069MODULE_AUTHOR("Michael Krufky <mkrufky@linuxtv.org>"); 1241MODULE_AUTHOR("Michael Krufky <mkrufky@linuxtv.org>");
1070MODULE_LICENSE("GPL"); 1242MODULE_LICENSE("GPL");
1071MODULE_VERSION("0.1"); 1243MODULE_VERSION("0.1");
diff --git a/drivers/media/dvb/frontends/lgdt3305.h b/drivers/media/dvb/frontends/lgdt3305.h
index 9cb11c9cae5..a7f30c2ed14 100644
--- a/drivers/media/dvb/frontends/lgdt3305.h
+++ b/drivers/media/dvb/frontends/lgdt3305.h
@@ -41,6 +41,11 @@ enum lgdt3305_tp_valid_polarity {
41 LGDT3305_TP_VALID_HIGH = 1, 41 LGDT3305_TP_VALID_HIGH = 1,
42}; 42};
43 43
44enum lgdt_demod_chip_type {
45 LGDT3305 = 0,
46 LGDT3304 = 1,
47};
48
44struct lgdt3305_config { 49struct lgdt3305_config {
45 u8 i2c_addr; 50 u8 i2c_addr;
46 51
@@ -65,6 +70,7 @@ struct lgdt3305_config {
65 enum lgdt3305_mpeg_mode mpeg_mode; 70 enum lgdt3305_mpeg_mode mpeg_mode;
66 enum lgdt3305_tp_clock_edge tpclk_edge; 71 enum lgdt3305_tp_clock_edge tpclk_edge;
67 enum lgdt3305_tp_valid_polarity tpvalid_polarity; 72 enum lgdt3305_tp_valid_polarity tpvalid_polarity;
73 enum lgdt_demod_chip_type demod_chip;
68}; 74};
69 75
70#if defined(CONFIG_DVB_LGDT3305) || (defined(CONFIG_DVB_LGDT3305_MODULE) && \ 76#if defined(CONFIG_DVB_LGDT3305) || (defined(CONFIG_DVB_LGDT3305_MODULE) && \