[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: Antti Palosaari <crope@iki.fi>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
This commit is contained in:
Antti Palosaari 2016-08-08 15:54:10 -03:00 committed by Mauro Carvalho Chehab
parent 7d4b64028c
commit fcd09f6592
4 changed files with 43 additions and 45 deletions

View file

@ -26,10 +26,9 @@ int cxd2820r_set_frontend_c(struct dvb_frontend *fe)
struct cxd2820r_priv *priv = fe->demodulator_priv; struct cxd2820r_priv *priv = fe->demodulator_priv;
struct dtv_frontend_properties *c = &fe->dtv_property_cache; struct dtv_frontend_properties *c = &fe->dtv_property_cache;
int ret, i; int ret, i;
unsigned int utmp;
u8 buf[2]; u8 buf[2];
u32 if_freq; u32 if_frequency;
u16 if_ctl;
u64 num;
struct reg_val_mask tab[] = { struct reg_val_mask tab[] = {
{ 0x00080, 0x01, 0xff }, { 0x00080, 0x01, 0xff },
{ 0x00081, 0x05, 0xff }, { 0x00081, 0x05, 0xff },
@ -69,20 +68,19 @@ int cxd2820r_set_frontend_c(struct dvb_frontend *fe)
/* program IF frequency */ /* program IF frequency */
if (fe->ops.tuner_ops.get_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) if (ret)
goto error; goto error;
} else dev_dbg(&priv->i2c->dev, "%s: if_frequency=%u\n", __func__,
if_freq = 0; if_frequency);
} else {
dev_dbg(&priv->i2c->dev, "%s: if_freq=%d\n", __func__, if_freq); ret = -EINVAL;
goto error;
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;
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); ret = cxd2820r_wr_regs(priv, 0x10042, buf, 2);
if (ret) if (ret)
goto error; goto error;

View file

@ -34,6 +34,8 @@ struct reg_val_mask {
u8 mask; u8 mask;
}; };
#define CXD2820R_CLK 41000000
struct cxd2820r_priv { struct cxd2820r_priv {
struct i2c_adapter *i2c; struct i2c_adapter *i2c;
struct dvb_frontend fe; struct dvb_frontend fe;

View file

@ -26,8 +26,8 @@ int cxd2820r_set_frontend_t(struct dvb_frontend *fe)
struct cxd2820r_priv *priv = fe->demodulator_priv; struct cxd2820r_priv *priv = fe->demodulator_priv;
struct dtv_frontend_properties *c = &fe->dtv_property_cache; struct dtv_frontend_properties *c = &fe->dtv_property_cache;
int ret, i, bw_i; int ret, i, bw_i;
u32 if_freq, if_ctl; unsigned int utmp;
u64 num; u32 if_frequency;
u8 buf[3], bw_param; u8 buf[3], bw_param;
u8 bw_params1[][5] = { u8 bw_params1[][5] = {
{ 0x17, 0xea, 0xaa, 0xaa, 0xaa }, /* 6 MHz */ { 0x17, 0xea, 0xaa, 0xaa, 0xaa }, /* 6 MHz */
@ -93,21 +93,20 @@ int cxd2820r_set_frontend_t(struct dvb_frontend *fe)
/* program IF frequency */ /* program IF frequency */
if (fe->ops.tuner_ops.get_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) if (ret)
goto error; goto error;
} else dev_dbg(&priv->i2c->dev, "%s: if_frequency=%u\n", __func__,
if_freq = 0; if_frequency);
} else {
dev_dbg(&priv->i2c->dev, "%s: if_freq=%d\n", __func__, if_freq); 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, 0x000b6, buf, 3); ret = cxd2820r_wr_regs(priv, 0x000b6, buf, 3);
if (ret) if (ret)
goto error; goto error;

View file

@ -26,8 +26,8 @@ int cxd2820r_set_frontend_t2(struct dvb_frontend *fe)
struct dtv_frontend_properties *c = &fe->dtv_property_cache; struct dtv_frontend_properties *c = &fe->dtv_property_cache;
struct cxd2820r_priv *priv = fe->demodulator_priv; struct cxd2820r_priv *priv = fe->demodulator_priv;
int ret, i, bw_i; int ret, i, bw_i;
u32 if_freq, if_ctl; unsigned int utmp;
u64 num; u32 if_frequency;
u8 buf[3], bw_param; u8 buf[3], bw_param;
u8 bw_params1[][5] = { u8 bw_params1[][5] = {
{ 0x1c, 0xb3, 0x33, 0x33, 0x33 }, /* 5 MHz */ { 0x1c, 0xb3, 0x33, 0x33, 0x33 }, /* 5 MHz */
@ -110,20 +110,23 @@ int cxd2820r_set_frontend_t2(struct dvb_frontend *fe)
/* program IF frequency */ /* program IF frequency */
if (fe->ops.tuner_ops.get_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) if (ret)
goto error; goto error;
} else dev_dbg(&priv->i2c->dev, "%s: if_frequency=%u\n", __func__,
if_freq = 0; if_frequency);
} else {
ret = -EINVAL;
goto error;
}
dev_dbg(&priv->i2c->dev, "%s: if_freq=%d\n", __func__, if_freq); utmp = DIV_ROUND_CLOSEST_ULL((u64)if_frequency * 0x1000000, CXD2820R_CLK);
buf[0] = (utmp >> 16) & 0xff;
num = if_freq / 1000; /* Hz => kHz */ buf[1] = (utmp >> 8) & 0xff;
num *= 0x1000000; buf[2] = (utmp >> 0) & 0xff;
if_ctl = DIV_ROUND_CLOSEST_ULL(num, 41000); ret = cxd2820r_wr_regs(priv, 0x020b6, buf, 3);
buf[0] = ((if_ctl >> 16) & 0xff); if (ret)
buf[1] = ((if_ctl >> 8) & 0xff); goto error;
buf[2] = ((if_ctl >> 0) & 0xff);
/* PLP filtering */ /* PLP filtering */
if (c->stream_id > 255) { if (c->stream_id > 255) {
@ -142,10 +145,6 @@ int cxd2820r_set_frontend_t2(struct dvb_frontend *fe)
goto error; 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); ret = cxd2820r_wr_regs(priv, 0x0209f, bw_params1[bw_i], 5);
if (ret) if (ret)
goto error; goto error;