diff options
author | Antti Palosaari <crope@iki.fi> | 2011-05-03 19:31:36 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2011-05-20 08:30:19 -0400 |
commit | e47b78f036bf1c30a5263ccdf1f638d1612b0586 (patch) | |
tree | f0d9d08aeae766dfd3408150dd4ed3ea2615ab21 /drivers/media/dvb | |
parent | 2e1ea06e9cc7aacdd6e77939e51743405299c9c2 (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.c | 111 | ||||
-rw-r--r-- | drivers/media/dvb/frontends/cxd2820r_priv.h | 1 |
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; | |||
25 | module_param_named(debug, cxd2820r_debug, int, 0644); | 25 | module_param_named(debug, cxd2820r_debug, int, 0644); |
26 | MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); | 26 | MODULE_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 */ | ||
29 | unsigned int cxd2820r_dvbt2_freq[5]; | ||
30 | int cxd2820r_dvbt2_count; | ||
31 | module_param_array_named(dvbt2_freq, cxd2820r_dvbt2_freq, int, | ||
32 | &cxd2820r_dvbt2_count, 0644); | ||
33 | MODULE_PARM_DESC(dvbt2_freq, "RF frequencies forced to DVB-T2 (unit Hz)"); | ||
34 | |||
35 | /* write multiple registers */ | 28 | /* write multiple registers */ |
36 | static int cxd2820r_wr_regs_i2c(struct cxd2820r_priv *priv, u8 i2c, u8 reg, | 29 | static 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 | ||
653 | static 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 | |||
711 | error: | ||
712 | dbg("%s: failed:%d", __func__, ret); | ||
713 | return DVBFE_ALGO_SEARCH_ERROR; | ||
714 | } | ||
715 | |||
716 | static int cxd2820r_get_frontend_algo(struct dvb_frontend *fe) | ||
717 | { | ||
718 | return DVBFE_ALGO_CUSTOM; | ||
719 | } | ||
720 | |||
690 | static void cxd2820r_release(struct dvb_frontend *fe) | 721 | static 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 */ |