Commit e47b78f0 authored by Antti Palosaari's avatar Antti Palosaari Committed by Mauro Carvalho Chehab
Browse files

[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: default avatarAntti Palosaari <crope@iki.fi>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 2e1ea06e
Loading
Loading
Loading
Loading
+72 −39
Original line number Diff line number Diff line
@@ -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,
+1 −0
Original line number Diff line number Diff line
@@ -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 */