summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAntti Palosaari <crope@iki.fi>2016-11-06 15:27:16 -0200
committerMauro Carvalho Chehab <mchehab@s-opensource.com>2017-01-31 10:43:40 -0200
commitc2feb9ffce1e29463eedee8bebc30016d533b25f (patch)
treebcd2ddff6f94666fd67ea04ee22772fc25ccdb71
parentbc85d5e2fa730fd3deb0ccf825dc9af8d237a283 (diff)
[media] af9033: use 64-bit div macro where possible
Replace Booth's binary division algo with 64-bit multiply and division. Fix related IF calculations. Signed-off-by: Antti Palosaari <crope@iki.fi> Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
-rw-r--r--drivers/media/dvb-frontends/af9033.c103
-rw-r--r--drivers/media/dvb-frontends/af9033_priv.h1
2 files changed, 32 insertions, 72 deletions
diff --git a/drivers/media/dvb-frontends/af9033.c b/drivers/media/dvb-frontends/af9033.c
index c61d879db96c..765d05a4f478 100644
--- a/drivers/media/dvb-frontends/af9033.c
+++ b/drivers/media/dvb-frontends/af9033.c
@@ -79,40 +79,14 @@ err:
return ret;
}
-static u32 af9033_div(struct af9033_dev *dev, u32 a, u32 b, u32 x)
-{
- u32 r = 0, c = 0, i;
-
- dev_dbg(&dev->client->dev, "a=%d b=%d x=%d\n", a, b, x);
-
- if (a > b) {
- c = a / b;
- a = a - c * b;
- }
-
- for (i = 0; i < x; i++) {
- if (a >= b) {
- r += 1;
- a -= b;
- }
- a <<= 1;
- r <<= 1;
- }
- r = (c << (u32)x) + r;
-
- dev_dbg(&dev->client->dev, "a=%d b=%d x=%d r=%d r=%x\n", a, b, x, r, r);
-
- return r;
-}
-
static int af9033_init(struct dvb_frontend *fe)
{
struct af9033_dev *dev = fe->demodulator_priv;
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
int ret, i, len;
+ unsigned int utmp;
const struct reg_val *init;
u8 buf[4];
- u32 adc_cw, clock_cw;
struct reg_val_mask tab[] = {
{ 0x80fb24, 0x00, 0x08 },
{ 0x80004c, 0x00, 0xff },
@@ -143,19 +117,18 @@ static int af9033_init(struct dvb_frontend *fe)
};
/* program clock control */
- clock_cw = af9033_div(dev, dev->cfg.clock, 1000000ul, 19ul);
- buf[0] = (clock_cw >> 0) & 0xff;
- buf[1] = (clock_cw >> 8) & 0xff;
- buf[2] = (clock_cw >> 16) & 0xff;
- buf[3] = (clock_cw >> 24) & 0xff;
-
- dev_dbg(&dev->client->dev, "clock=%d clock_cw=%08x\n",
- dev->cfg.clock, clock_cw);
-
+ utmp = div_u64((u64)dev->cfg.clock * 0x80000, 1000000);
+ buf[0] = (utmp >> 0) & 0xff;
+ buf[1] = (utmp >> 8) & 0xff;
+ buf[2] = (utmp >> 16) & 0xff;
+ buf[3] = (utmp >> 24) & 0xff;
ret = regmap_bulk_write(dev->regmap, 0x800025, buf, 4);
if (ret)
goto err;
+ dev_dbg(&dev->client->dev, "clk=%u clk_cw=%08x\n",
+ dev->cfg.clock, utmp);
+
/* program ADC control */
for (i = 0; i < ARRAY_SIZE(clock_adc_lut); i++) {
if (clock_adc_lut[i].clock == dev->cfg.clock)
@@ -168,18 +141,17 @@ static int af9033_init(struct dvb_frontend *fe)
goto err;
}
- adc_cw = af9033_div(dev, clock_adc_lut[i].adc, 1000000ul, 19ul);
- buf[0] = (adc_cw >> 0) & 0xff;
- buf[1] = (adc_cw >> 8) & 0xff;
- buf[2] = (adc_cw >> 16) & 0xff;
-
- dev_dbg(&dev->client->dev, "adc=%d adc_cw=%06x\n",
- clock_adc_lut[i].adc, adc_cw);
-
+ utmp = div_u64((u64)clock_adc_lut[i].adc * 0x80000, 1000000);
+ buf[0] = (utmp >> 0) & 0xff;
+ buf[1] = (utmp >> 8) & 0xff;
+ buf[2] = (utmp >> 16) & 0xff;
ret = regmap_bulk_write(dev->regmap, 0x80f1cd, buf, 3);
if (ret)
goto err;
+ dev_dbg(&dev->client->dev, "adc=%u adc_cw=%06x\n",
+ clock_adc_lut[i].adc, utmp);
+
/* program register table */
for (i = 0; i < ARRAY_SIZE(tab); i++) {
ret = regmap_update_bits(dev->regmap, tab[i].reg, tab[i].mask,
@@ -397,9 +369,10 @@ static int af9033_set_frontend(struct dvb_frontend *fe)
{
struct af9033_dev *dev = fe->demodulator_priv;
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
- int ret, i, spec_inv, sampling_freq;
+ int ret, i;
+ unsigned int utmp, adc_freq;
u8 tmp, buf[3], bandwidth_reg_val;
- u32 if_frequency, freq_cw, adc_freq;
+ u32 if_frequency;
dev_dbg(&dev->client->dev, "frequency=%d bandwidth_hz=%d\n",
c->frequency, c->bandwidth_hz);
@@ -449,8 +422,6 @@ static int af9033_set_frontend(struct dvb_frontend *fe)
/* program frequency control */
if (c->bandwidth_hz != dev->bandwidth_hz) {
- spec_inv = dev->cfg.spec_inv ? -1 : 1;
-
for (i = 0; i < ARRAY_SIZE(clock_adc_lut); i++) {
if (clock_adc_lut[i].clock == dev->cfg.clock)
break;
@@ -464,42 +435,30 @@ static int af9033_set_frontend(struct dvb_frontend *fe)
}
adc_freq = clock_adc_lut[i].adc;
+ if (dev->cfg.adc_multiplier == AF9033_ADC_MULTIPLIER_2X)
+ adc_freq = 2 * adc_freq;
+
/* get used IF frequency */
if (fe->ops.tuner_ops.get_if_frequency)
fe->ops.tuner_ops.get_if_frequency(fe, &if_frequency);
else
if_frequency = 0;
- sampling_freq = if_frequency;
+ utmp = DIV_ROUND_CLOSEST_ULL((u64)if_frequency * 0x800000,
+ adc_freq);
- while (sampling_freq > (adc_freq / 2))
- sampling_freq -= adc_freq;
-
- if (sampling_freq >= 0)
- spec_inv *= -1;
- else
- sampling_freq *= -1;
-
- freq_cw = af9033_div(dev, sampling_freq, adc_freq, 23ul);
-
- if (spec_inv == -1)
- freq_cw = 0x800000 - freq_cw;
-
- if (dev->cfg.adc_multiplier == AF9033_ADC_MULTIPLIER_2X)
- freq_cw /= 2;
-
- buf[0] = (freq_cw >> 0) & 0xff;
- buf[1] = (freq_cw >> 8) & 0xff;
- buf[2] = (freq_cw >> 16) & 0x7f;
-
- /* FIXME: there seems to be calculation error here... */
- if (if_frequency == 0)
- buf[2] = 0;
+ if (!dev->cfg.spec_inv && if_frequency)
+ utmp = 0x800000 - utmp;
+ buf[0] = (utmp >> 0) & 0xff;
+ buf[1] = (utmp >> 8) & 0xff;
+ buf[2] = (utmp >> 16) & 0xff;
ret = regmap_bulk_write(dev->regmap, 0x800029, buf, 3);
if (ret)
goto err;
+ dev_dbg(&dev->client->dev, "if_frequency_cw=%06x\n", utmp);
+
dev->bandwidth_hz = c->bandwidth_hz;
}
diff --git a/drivers/media/dvb-frontends/af9033_priv.h b/drivers/media/dvb-frontends/af9033_priv.h
index 701c5085fdd2..28d14dc5ceea 100644
--- a/drivers/media/dvb-frontends/af9033_priv.h
+++ b/drivers/media/dvb-frontends/af9033_priv.h
@@ -26,6 +26,7 @@
#include "af9033.h"
#include <linux/math64.h>
#include <linux/regmap.h>
+#include <linux/kernel.h>
struct reg_val {
u32 reg;