Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

[media] cxd2820r: improve IF frequency setting



Use 64-bit calculation.

Return error if tuner does not provide get_if_frequency() callback.
All currently used tuners has it.

Signed-off-by: default avatarAntti Palosaari <crope@iki.fi>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@s-opensource.com>
parent 7d4b6402
Loading
Loading
Loading
Loading
+12 −14
Original line number Diff line number Diff line
@@ -26,10 +26,9 @@ int cxd2820r_set_frontend_c(struct dvb_frontend *fe)
	struct cxd2820r_priv *priv = fe->demodulator_priv;
	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
	int ret, i;
	unsigned int utmp;
	u8 buf[2];
	u32 if_freq;
	u16 if_ctl;
	u64 num;
	u32 if_frequency;
	struct reg_val_mask tab[] = {
		{ 0x00080, 0x01, 0xff },
		{ 0x00081, 0x05, 0xff },
@@ -69,20 +68,19 @@ int cxd2820r_set_frontend_c(struct dvb_frontend *fe)

	/* program IF frequency */
	if (fe->ops.tuner_ops.get_if_frequency) {
		ret = fe->ops.tuner_ops.get_if_frequency(fe, &if_freq);
		ret = fe->ops.tuner_ops.get_if_frequency(fe, &if_frequency);
		if (ret)
			goto error;
	} else
		if_freq = 0;

	dev_dbg(&priv->i2c->dev, "%s: if_freq=%d\n", __func__, if_freq);

	num = if_freq / 1000; /* Hz => kHz */
	num *= 0x4000;
	if_ctl = 0x4000 - DIV_ROUND_CLOSEST_ULL(num, 41000);
	buf[0] = (if_ctl >> 8) & 0x3f;
	buf[1] = (if_ctl >> 0) & 0xff;
		dev_dbg(&priv->i2c->dev, "%s: if_frequency=%u\n", __func__,
			if_frequency);
	} else {
		ret = -EINVAL;
		goto error;
	}

	utmp = 0x4000 - DIV_ROUND_CLOSEST_ULL((u64)if_frequency * 0x4000, CXD2820R_CLK);
	buf[0] = (utmp >> 8) & 0xff;
	buf[1] = (utmp >> 0) & 0xff;
	ret = cxd2820r_wr_regs(priv, 0x10042, buf, 2);
	if (ret)
		goto error;
+2 −0
Original line number Diff line number Diff line
@@ -34,6 +34,8 @@ struct reg_val_mask {
	u8  mask;
};

#define CXD2820R_CLK 41000000

struct cxd2820r_priv {
	struct i2c_adapter *i2c;
	struct dvb_frontend fe;
+13 −14
Original line number Diff line number Diff line
@@ -26,8 +26,8 @@ int cxd2820r_set_frontend_t(struct dvb_frontend *fe)
	struct cxd2820r_priv *priv = fe->demodulator_priv;
	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
	int ret, i, bw_i;
	u32 if_freq, if_ctl;
	u64 num;
	unsigned int utmp;
	u32 if_frequency;
	u8 buf[3], bw_param;
	u8 bw_params1[][5] = {
		{ 0x17, 0xea, 0xaa, 0xaa, 0xaa }, /* 6 MHz */
@@ -93,21 +93,20 @@ int cxd2820r_set_frontend_t(struct dvb_frontend *fe)

	/* program IF frequency */
	if (fe->ops.tuner_ops.get_if_frequency) {
		ret = fe->ops.tuner_ops.get_if_frequency(fe, &if_freq);
		ret = fe->ops.tuner_ops.get_if_frequency(fe, &if_frequency);
		if (ret)
			goto error;
	} else
		if_freq = 0;

	dev_dbg(&priv->i2c->dev, "%s: if_freq=%d\n", __func__, if_freq);

	num = if_freq / 1000; /* Hz => kHz */
	num *= 0x1000000;
	if_ctl = DIV_ROUND_CLOSEST_ULL(num, 41000);
	buf[0] = ((if_ctl >> 16) & 0xff);
	buf[1] = ((if_ctl >>  8) & 0xff);
	buf[2] = ((if_ctl >>  0) & 0xff);
		dev_dbg(&priv->i2c->dev, "%s: if_frequency=%u\n", __func__,
			if_frequency);
	} else {
		ret = -EINVAL;
		goto error;
	}

	utmp = DIV_ROUND_CLOSEST_ULL((u64)if_frequency * 0x1000000, CXD2820R_CLK);
	buf[0] = (utmp >> 16) & 0xff;
	buf[1] = (utmp >>  8) & 0xff;
	buf[2] = (utmp >>  0) & 0xff;
	ret = cxd2820r_wr_regs(priv, 0x000b6, buf, 3);
	if (ret)
		goto error;
+16 −17
Original line number Diff line number Diff line
@@ -26,8 +26,8 @@ int cxd2820r_set_frontend_t2(struct dvb_frontend *fe)
	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
	struct cxd2820r_priv *priv = fe->demodulator_priv;
	int ret, i, bw_i;
	u32 if_freq, if_ctl;
	u64 num;
	unsigned int utmp;
	u32 if_frequency;
	u8 buf[3], bw_param;
	u8 bw_params1[][5] = {
		{ 0x1c, 0xb3, 0x33, 0x33, 0x33 }, /* 5 MHz */
@@ -110,20 +110,23 @@ int cxd2820r_set_frontend_t2(struct dvb_frontend *fe)

	/* program IF frequency */
	if (fe->ops.tuner_ops.get_if_frequency) {
		ret = fe->ops.tuner_ops.get_if_frequency(fe, &if_freq);
		ret = fe->ops.tuner_ops.get_if_frequency(fe, &if_frequency);
		if (ret)
			goto error;
	} else
		if_freq = 0;

	dev_dbg(&priv->i2c->dev, "%s: if_freq=%d\n", __func__, if_freq);
		dev_dbg(&priv->i2c->dev, "%s: if_frequency=%u\n", __func__,
			if_frequency);
	} else {
		ret = -EINVAL;
		goto error;
	}

	num = if_freq / 1000; /* Hz => kHz */
	num *= 0x1000000;
	if_ctl = DIV_ROUND_CLOSEST_ULL(num, 41000);
	buf[0] = ((if_ctl >> 16) & 0xff);
	buf[1] = ((if_ctl >>  8) & 0xff);
	buf[2] = ((if_ctl >>  0) & 0xff);
	utmp = DIV_ROUND_CLOSEST_ULL((u64)if_frequency * 0x1000000, CXD2820R_CLK);
	buf[0] = (utmp >> 16) & 0xff;
	buf[1] = (utmp >>  8) & 0xff;
	buf[2] = (utmp >>  0) & 0xff;
	ret = cxd2820r_wr_regs(priv, 0x020b6, buf, 3);
	if (ret)
		goto error;

	/* PLP filtering */
	if (c->stream_id > 255) {
@@ -142,10 +145,6 @@ int cxd2820r_set_frontend_t2(struct dvb_frontend *fe)
			goto error;
	}

	ret = cxd2820r_wr_regs(priv, 0x020b6, buf, 3);
	if (ret)
		goto error;

	ret = cxd2820r_wr_regs(priv, 0x0209f, bw_params1[bw_i], 5);
	if (ret)
		goto error;