aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/dvb
diff options
context:
space:
mode:
authorAntti Palosaari <crope@iki.fi>2011-05-03 19:31:36 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2011-05-20 08:30:19 -0400
commite47b78f036bf1c30a5263ccdf1f638d1612b0586 (patch)
treef0d9d08aeae766dfd3408150dd4ed3ea2615ab21 /drivers/media/dvb
parent2e1ea06e9cc7aacdd6e77939e51743405299c9c2 (diff)
[media] cxd2820r: switch automatically between DVB-T and DVB-T2
Remove old DVB-T2 freq module param and detect DVB-T/T2 automatically. Implementation is trial and error, if DVB-T does not lock try DVB-T2 and vice versa. That's done by replacing normal DVBFE_ALGO_SW with DVBFE_ALGO_CUSTOM which gives better control for tuning process. DVB-C still uses normal software ZigZag, DVBFE_ALGO_SW. Signed-off-by: Antti Palosaari <crope@iki.fi> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/dvb')
-rw-r--r--drivers/media/dvb/frontends/cxd2820r_core.c111
-rw-r--r--drivers/media/dvb/frontends/cxd2820r_priv.h1
2 files changed, 73 insertions, 39 deletions
diff --git a/drivers/media/dvb/frontends/cxd2820r_core.c b/drivers/media/dvb/frontends/cxd2820r_core.c
index 59d302f7a8f1..e900c4cad7fd 100644
--- a/drivers/media/dvb/frontends/cxd2820r_core.c
+++ b/drivers/media/dvb/frontends/cxd2820r_core.c
@@ -25,13 +25,6 @@ int cxd2820r_debug;
25module_param_named(debug, cxd2820r_debug, int, 0644); 25module_param_named(debug, cxd2820r_debug, int, 0644);
26MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); 26MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
27 27
28/* TODO: temporary hack, will be removed later when there is app support */
29unsigned int cxd2820r_dvbt2_freq[5];
30int cxd2820r_dvbt2_count;
31module_param_array_named(dvbt2_freq, cxd2820r_dvbt2_freq, int,
32 &cxd2820r_dvbt2_count, 0644);
33MODULE_PARM_DESC(dvbt2_freq, "RF frequencies forced to DVB-T2 (unit Hz)");
34
35/* write multiple registers */ 28/* write multiple registers */
36static int cxd2820r_wr_regs_i2c(struct cxd2820r_priv *priv, u8 i2c, u8 reg, 29static int cxd2820r_wr_regs_i2c(struct cxd2820r_priv *priv, u8 i2c, u8 reg,
37 u8 *val, int len) 30 u8 *val, int len)
@@ -626,8 +619,7 @@ static int cxd2820r_get_tune_settings(struct dvb_frontend *fe,
626 struct dvb_frontend_tune_settings *s) 619 struct dvb_frontend_tune_settings *s)
627{ 620{
628 struct cxd2820r_priv *priv = fe->demodulator_priv; 621 struct cxd2820r_priv *priv = fe->demodulator_priv;
629 int ret, i; 622 int ret;
630 unsigned int rf1, rf2;
631 dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system); 623 dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
632 624
633 if (fe->ops.info.type == FE_OFDM) { 625 if (fe->ops.info.type == FE_OFDM) {
@@ -636,35 +628,6 @@ static int cxd2820r_get_tune_settings(struct dvb_frontend *fe,
636 if (ret) 628 if (ret)
637 return ret; 629 return ret;
638 630
639 /* TODO: hack! This will be removed later when there is better
640 * app support for DVB-T2... */
641
642 /* Hz => MHz */
643 rf1 = DIV_ROUND_CLOSEST(fe->dtv_property_cache.frequency,
644 1000000);
645 for (i = 0; i < cxd2820r_dvbt2_count; i++) {
646 if (cxd2820r_dvbt2_freq[i] > 100000000) {
647 /* Hz => MHz */
648 rf2 = DIV_ROUND_CLOSEST(cxd2820r_dvbt2_freq[i],
649 1000000);
650 } else if (cxd2820r_dvbt2_freq[i] > 100000) {
651 /* kHz => MHz */
652 rf2 = DIV_ROUND_CLOSEST(cxd2820r_dvbt2_freq[i],
653 1000);
654 } else {
655 rf2 = cxd2820r_dvbt2_freq[i];
656 }
657
658 dbg("%s: rf1=%d rf2=%d", __func__, rf1, rf2);
659
660 if (rf1 == rf2) {
661 dbg("%s: forcing DVB-T2, frequency=%d",
662 __func__, fe->dtv_property_cache.frequency);
663 fe->dtv_property_cache.delivery_system =
664 SYS_DVBT2;
665 }
666 }
667
668 switch (fe->dtv_property_cache.delivery_system) { 631 switch (fe->dtv_property_cache.delivery_system) {
669 case SYS_DVBT: 632 case SYS_DVBT:
670 ret = cxd2820r_get_tune_settings_t(fe, s); 633 ret = cxd2820r_get_tune_settings_t(fe, s);
@@ -687,6 +650,74 @@ static int cxd2820r_get_tune_settings(struct dvb_frontend *fe,
687 return ret; 650 return ret;
688} 651}
689 652
653static enum dvbfe_search cxd2820r_search(struct dvb_frontend *fe,
654 struct dvb_frontend_parameters *p)
655{
656 struct cxd2820r_priv *priv = fe->demodulator_priv;
657 struct dtv_frontend_properties *c = &fe->dtv_property_cache;
658 int ret, i;
659 fe_status_t status = 0;
660 dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
661
662 /* switch between DVB-T and DVB-T2 when tune fails */
663 if (priv->last_tune_failed) {
664 if (priv->delivery_system == SYS_DVBT)
665 c->delivery_system = SYS_DVBT2;
666 else
667 c->delivery_system = SYS_DVBT;
668 }
669
670 /* set frontend */
671 ret = cxd2820r_set_frontend(fe, p);
672 if (ret)
673 goto error;
674
675
676 /* frontend lock wait loop count */
677 switch (priv->delivery_system) {
678 case SYS_DVBT:
679 i = 20;
680 break;
681 case SYS_DVBT2:
682 i = 40;
683 break;
684 case SYS_UNDEFINED:
685 default:
686 i = 0;
687 break;
688 }
689
690 /* wait frontend lock */
691 for (; i > 0; i--) {
692 dbg("%s: LOOP=%d", __func__, i);
693 msleep(50);
694 ret = cxd2820r_read_status(fe, &status);
695 if (ret)
696 goto error;
697
698 if (status & FE_HAS_SIGNAL)
699 break;
700 }
701
702 /* check if we have a valid signal */
703 if (status) {
704 priv->last_tune_failed = 0;
705 return DVBFE_ALGO_SEARCH_SUCCESS;
706 } else {
707 priv->last_tune_failed = 1;
708 return DVBFE_ALGO_SEARCH_AGAIN;
709 }
710
711error:
712 dbg("%s: failed:%d", __func__, ret);
713 return DVBFE_ALGO_SEARCH_ERROR;
714}
715
716static int cxd2820r_get_frontend_algo(struct dvb_frontend *fe)
717{
718 return DVBFE_ALGO_CUSTOM;
719}
720
690static void cxd2820r_release(struct dvb_frontend *fe) 721static void cxd2820r_release(struct dvb_frontend *fe)
691{ 722{
692 struct cxd2820r_priv *priv = fe->demodulator_priv; 723 struct cxd2820r_priv *priv = fe->demodulator_priv;
@@ -838,9 +869,11 @@ static struct dvb_frontend_ops cxd2820r_ops[2] = {
838 869
839 .get_tune_settings = cxd2820r_get_tune_settings, 870 .get_tune_settings = cxd2820r_get_tune_settings,
840 871
841 .set_frontend = cxd2820r_set_frontend,
842 .get_frontend = cxd2820r_get_frontend, 872 .get_frontend = cxd2820r_get_frontend,
843 873
874 .get_frontend_algo = cxd2820r_get_frontend_algo,
875 .search = cxd2820r_search,
876
844 .read_status = cxd2820r_read_status, 877 .read_status = cxd2820r_read_status,
845 .read_snr = cxd2820r_read_snr, 878 .read_snr = cxd2820r_read_snr,
846 .read_ber = cxd2820r_read_ber, 879 .read_ber = cxd2820r_read_ber,
diff --git a/drivers/media/dvb/frontends/cxd2820r_priv.h b/drivers/media/dvb/frontends/cxd2820r_priv.h
index 835e37b98049..d4e2e0b76c10 100644
--- a/drivers/media/dvb/frontends/cxd2820r_priv.h
+++ b/drivers/media/dvb/frontends/cxd2820r_priv.h
@@ -73,6 +73,7 @@ struct cxd2820r_priv {
73 u8 gpio[3]; 73 u8 gpio[3];
74 74
75 fe_delivery_system_t delivery_system; 75 fe_delivery_system_t delivery_system;
76 int last_tune_failed:1; /* for switch between T and T2 tune */
76}; 77};
77 78
78/* cxd2820r_core.c */ 79/* cxd2820r_core.c */