From fcd09f6592cc1d55dea1571297ad88b9024de80c Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Mon, 8 Aug 2016 15:54:10 -0300 Subject: [PATCH] [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 Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/cxd2820r_c.c | 26 ++++++++-------- drivers/media/dvb-frontends/cxd2820r_priv.h | 2 ++ drivers/media/dvb-frontends/cxd2820r_t.c | 27 ++++++++--------- drivers/media/dvb-frontends/cxd2820r_t2.c | 33 ++++++++++----------- 4 files changed, 43 insertions(+), 45 deletions(-) diff --git a/drivers/media/dvb-frontends/cxd2820r_c.c b/drivers/media/dvb-frontends/cxd2820r_c.c index a674a6312c38..957ec94c7243 100644 --- a/drivers/media/dvb-frontends/cxd2820r_c.c +++ b/drivers/media/dvb-frontends/cxd2820r_c.c @@ -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; diff --git a/drivers/media/dvb-frontends/cxd2820r_priv.h b/drivers/media/dvb-frontends/cxd2820r_priv.h index e31c48e53097..acfae17991e3 100644 --- a/drivers/media/dvb-frontends/cxd2820r_priv.h +++ b/drivers/media/dvb-frontends/cxd2820r_priv.h @@ -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; diff --git a/drivers/media/dvb-frontends/cxd2820r_t.c b/drivers/media/dvb-frontends/cxd2820r_t.c index 75ce7d8ded00..67cc33bc3c35 100644 --- a/drivers/media/dvb-frontends/cxd2820r_t.c +++ b/drivers/media/dvb-frontends/cxd2820r_t.c @@ -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; diff --git a/drivers/media/dvb-frontends/cxd2820r_t2.c b/drivers/media/dvb-frontends/cxd2820r_t2.c index 704475676234..14c9a26502ed 100644 --- a/drivers/media/dvb-frontends/cxd2820r_t2.c +++ b/drivers/media/dvb-frontends/cxd2820r_t2.c @@ -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; -- 2.30.2