diff options
author | Antti Palosaari <crope@iki.fi> | 2011-05-04 03:31:36 +0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2011-05-20 16:30:19 +0400 |
commit | e47b78f036bf1c30a5263ccdf1f638d1612b0586 (patch) | |
tree | f0d9d08aeae766dfd3408150dd4ed3ea2615ab21 | |
parent | 2e1ea06e9cc7aacdd6e77939e51743405299c9c2 (diff) | |
download | linux-e47b78f036bf1c30a5263ccdf1f638d1612b0586.tar.xz |
[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>
-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; 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, 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 { u8 gpio[3]; fe_delivery_system_t delivery_system; + int last_tune_failed:1; /* for switch between T and T2 tune */ }; /* cxd2820r_core.c */ |