[media] cxd2820r: switch automatically between DVB-T and DVB-T2
authorAntti Palosaari <crope@iki.fi>
Tue, 3 May 2011 23:31:36 +0000 (20:31 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Fri, 20 May 2011 12:30:19 +0000 (09:30 -0300)
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>
drivers/media/dvb/frontends/cxd2820r_core.c
drivers/media/dvb/frontends/cxd2820r_priv.h

index 59d302f..e900c4c 100644 (file)
@@ -25,13 +25,6 @@ int cxd2820r_debug;
 module_param_named(debug, cxd2820r_debug, int, 0644);
 MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
 
-/* TODO: temporary hack, will be removed later when there is app support */
-unsigned int cxd2820r_dvbt2_freq[5];
-int cxd2820r_dvbt2_count;
-module_param_array_named(dvbt2_freq, cxd2820r_dvbt2_freq, int,
-       &cxd2820r_dvbt2_count, 0644);
-MODULE_PARM_DESC(dvbt2_freq, "RF frequencies forced to DVB-T2 (unit Hz)");
-
 /* write multiple registers */
 static int cxd2820r_wr_regs_i2c(struct cxd2820r_priv *priv, u8 i2c, u8 reg,
        u8 *val, int len)
@@ -626,8 +619,7 @@ static int cxd2820r_get_tune_settings(struct dvb_frontend *fe,
        struct dvb_frontend_tune_settings *s)
 {
        struct cxd2820r_priv *priv = fe->demodulator_priv;
-       int ret, i;
-       unsigned int rf1, rf2;
+       int ret;
        dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
 
        if (fe->ops.info.type == FE_OFDM) {
@@ -636,35 +628,6 @@ static int cxd2820r_get_tune_settings(struct dvb_frontend *fe,
                if (ret)
                        return ret;
 
-               /* TODO: hack! This will be removed later when there is better
-                * app support for DVB-T2... */
-
-               /* Hz => MHz */
-               rf1 = DIV_ROUND_CLOSEST(fe->dtv_property_cache.frequency,
-                       1000000);
-               for (i = 0; i < cxd2820r_dvbt2_count; i++) {
-                       if (cxd2820r_dvbt2_freq[i] > 100000000) {
-                               /* Hz => MHz */
-                               rf2 = DIV_ROUND_CLOSEST(cxd2820r_dvbt2_freq[i],
-                                       1000000);
-                       } else if (cxd2820r_dvbt2_freq[i] > 100000) {
-                               /* kHz => MHz */
-                               rf2 = DIV_ROUND_CLOSEST(cxd2820r_dvbt2_freq[i],
-                                       1000);
-                       } else {
-                               rf2 = cxd2820r_dvbt2_freq[i];
-                       }
-
-                       dbg("%s: rf1=%d rf2=%d", __func__, rf1, rf2);
-
-                       if (rf1 == rf2) {
-                               dbg("%s: forcing DVB-T2, frequency=%d",
-                               __func__, fe->dtv_property_cache.frequency);
-                               fe->dtv_property_cache.delivery_system =
-                                       SYS_DVBT2;
-                       }
-               }
-
                switch (fe->dtv_property_cache.delivery_system) {
                case SYS_DVBT:
                        ret = cxd2820r_get_tune_settings_t(fe, s);
@@ -687,6 +650,74 @@ static int cxd2820r_get_tune_settings(struct dvb_frontend *fe,
        return ret;
 }
 
+static enum dvbfe_search cxd2820r_search(struct dvb_frontend *fe,
+       struct dvb_frontend_parameters *p)
+{
+       struct cxd2820r_priv *priv = fe->demodulator_priv;
+       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+       int ret, i;
+       fe_status_t status = 0;
+       dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
+
+       /* switch between DVB-T and DVB-T2 when tune fails */
+       if (priv->last_tune_failed) {
+               if (priv->delivery_system == SYS_DVBT)
+                       c->delivery_system = SYS_DVBT2;
+               else
+                       c->delivery_system = SYS_DVBT;
+       }
+
+       /* set frontend */
+       ret = cxd2820r_set_frontend(fe, p);
+       if (ret)
+               goto error;
+
+
+       /* frontend lock wait loop count */
+       switch (priv->delivery_system) {
+       case SYS_DVBT:
+               i = 20;
+               break;
+       case SYS_DVBT2:
+               i = 40;
+               break;
+       case SYS_UNDEFINED:
+       default:
+               i = 0;
+               break;
+       }
+
+       /* wait frontend lock */
+       for (; i > 0; i--) {
+               dbg("%s: LOOP=%d", __func__, i);
+               msleep(50);
+               ret = cxd2820r_read_status(fe, &status);
+               if (ret)
+                       goto error;
+
+               if (status & FE_HAS_SIGNAL)
+                       break;
+       }
+
+       /* check if we have a valid signal */
+       if (status) {
+               priv->last_tune_failed = 0;
+               return DVBFE_ALGO_SEARCH_SUCCESS;
+       } else {
+               priv->last_tune_failed = 1;
+               return DVBFE_ALGO_SEARCH_AGAIN;
+       }
+
+error:
+       dbg("%s: failed:%d", __func__, ret);
+       return DVBFE_ALGO_SEARCH_ERROR;
+}
+
+static int cxd2820r_get_frontend_algo(struct dvb_frontend *fe)
+{
+       return DVBFE_ALGO_CUSTOM;
+}
+
 static void cxd2820r_release(struct dvb_frontend *fe)
 {
        struct cxd2820r_priv *priv = fe->demodulator_priv;
@@ -838,9 +869,11 @@ static struct dvb_frontend_ops cxd2820r_ops[2] = {
 
                .get_tune_settings = cxd2820r_get_tune_settings,
 
-               .set_frontend = cxd2820r_set_frontend,
                .get_frontend = cxd2820r_get_frontend,
 
+               .get_frontend_algo = cxd2820r_get_frontend_algo,
+               .search = cxd2820r_search,
+
                .read_status = cxd2820r_read_status,
                .read_snr = cxd2820r_read_snr,
                .read_ber = cxd2820r_read_ber,
index 835e37b..d4e2e0b 100644 (file)
@@ -73,6 +73,7 @@ struct cxd2820r_priv {
        u8 gpio[3];
 
        fe_delivery_system_t delivery_system;
+       int last_tune_failed:1; /* for switch between T and T2 tune */
 };
 
 /* cxd2820r_core.c */