Commit c2feb9ff authored by Antti Palosaari's avatar Antti Palosaari Committed by Mauro Carvalho Chehab

[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: default avatarAntti Palosaari <crope@iki.fi>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@s-opensource.com>
parent bc85d5e2
...@@ -79,40 +79,14 @@ static int af9033_wr_reg_val_tab(struct af9033_dev *dev, ...@@ -79,40 +79,14 @@ static int af9033_wr_reg_val_tab(struct af9033_dev *dev,
return ret; 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) static int af9033_init(struct dvb_frontend *fe)
{ {
struct af9033_dev *dev = fe->demodulator_priv; struct af9033_dev *dev = fe->demodulator_priv;
struct dtv_frontend_properties *c = &fe->dtv_property_cache; struct dtv_frontend_properties *c = &fe->dtv_property_cache;
int ret, i, len; int ret, i, len;
unsigned int utmp;
const struct reg_val *init; const struct reg_val *init;
u8 buf[4]; u8 buf[4];
u32 adc_cw, clock_cw;
struct reg_val_mask tab[] = { struct reg_val_mask tab[] = {
{ 0x80fb24, 0x00, 0x08 }, { 0x80fb24, 0x00, 0x08 },
{ 0x80004c, 0x00, 0xff }, { 0x80004c, 0x00, 0xff },
...@@ -143,19 +117,18 @@ static int af9033_init(struct dvb_frontend *fe) ...@@ -143,19 +117,18 @@ static int af9033_init(struct dvb_frontend *fe)
}; };
/* program clock control */ /* program clock control */
clock_cw = af9033_div(dev, dev->cfg.clock, 1000000ul, 19ul); utmp = div_u64((u64)dev->cfg.clock * 0x80000, 1000000);
buf[0] = (clock_cw >> 0) & 0xff; buf[0] = (utmp >> 0) & 0xff;
buf[1] = (clock_cw >> 8) & 0xff; buf[1] = (utmp >> 8) & 0xff;
buf[2] = (clock_cw >> 16) & 0xff; buf[2] = (utmp >> 16) & 0xff;
buf[3] = (clock_cw >> 24) & 0xff; buf[3] = (utmp >> 24) & 0xff;
dev_dbg(&dev->client->dev, "clock=%d clock_cw=%08x\n",
dev->cfg.clock, clock_cw);
ret = regmap_bulk_write(dev->regmap, 0x800025, buf, 4); ret = regmap_bulk_write(dev->regmap, 0x800025, buf, 4);
if (ret) if (ret)
goto err; goto err;
dev_dbg(&dev->client->dev, "clk=%u clk_cw=%08x\n",
dev->cfg.clock, utmp);
/* program ADC control */ /* program ADC control */
for (i = 0; i < ARRAY_SIZE(clock_adc_lut); i++) { for (i = 0; i < ARRAY_SIZE(clock_adc_lut); i++) {
if (clock_adc_lut[i].clock == dev->cfg.clock) if (clock_adc_lut[i].clock == dev->cfg.clock)
...@@ -168,18 +141,17 @@ static int af9033_init(struct dvb_frontend *fe) ...@@ -168,18 +141,17 @@ static int af9033_init(struct dvb_frontend *fe)
goto err; goto err;
} }
adc_cw = af9033_div(dev, clock_adc_lut[i].adc, 1000000ul, 19ul); utmp = div_u64((u64)clock_adc_lut[i].adc * 0x80000, 1000000);
buf[0] = (adc_cw >> 0) & 0xff; buf[0] = (utmp >> 0) & 0xff;
buf[1] = (adc_cw >> 8) & 0xff; buf[1] = (utmp >> 8) & 0xff;
buf[2] = (adc_cw >> 16) & 0xff; buf[2] = (utmp >> 16) & 0xff;
dev_dbg(&dev->client->dev, "adc=%d adc_cw=%06x\n",
clock_adc_lut[i].adc, adc_cw);
ret = regmap_bulk_write(dev->regmap, 0x80f1cd, buf, 3); ret = regmap_bulk_write(dev->regmap, 0x80f1cd, buf, 3);
if (ret) if (ret)
goto err; goto err;
dev_dbg(&dev->client->dev, "adc=%u adc_cw=%06x\n",
clock_adc_lut[i].adc, utmp);
/* program register table */ /* program register table */
for (i = 0; i < ARRAY_SIZE(tab); i++) { for (i = 0; i < ARRAY_SIZE(tab); i++) {
ret = regmap_update_bits(dev->regmap, tab[i].reg, tab[i].mask, 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) ...@@ -397,9 +369,10 @@ static int af9033_set_frontend(struct dvb_frontend *fe)
{ {
struct af9033_dev *dev = fe->demodulator_priv; struct af9033_dev *dev = fe->demodulator_priv;
struct dtv_frontend_properties *c = &fe->dtv_property_cache; 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; 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", dev_dbg(&dev->client->dev, "frequency=%d bandwidth_hz=%d\n",
c->frequency, c->bandwidth_hz); c->frequency, c->bandwidth_hz);
...@@ -449,8 +422,6 @@ static int af9033_set_frontend(struct dvb_frontend *fe) ...@@ -449,8 +422,6 @@ static int af9033_set_frontend(struct dvb_frontend *fe)
/* program frequency control */ /* program frequency control */
if (c->bandwidth_hz != dev->bandwidth_hz) { 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++) { for (i = 0; i < ARRAY_SIZE(clock_adc_lut); i++) {
if (clock_adc_lut[i].clock == dev->cfg.clock) if (clock_adc_lut[i].clock == dev->cfg.clock)
break; break;
...@@ -464,42 +435,30 @@ static int af9033_set_frontend(struct dvb_frontend *fe) ...@@ -464,42 +435,30 @@ static int af9033_set_frontend(struct dvb_frontend *fe)
} }
adc_freq = clock_adc_lut[i].adc; 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 */ /* get used IF frequency */
if (fe->ops.tuner_ops.get_if_frequency) if (fe->ops.tuner_ops.get_if_frequency)
fe->ops.tuner_ops.get_if_frequency(fe, &if_frequency); fe->ops.tuner_ops.get_if_frequency(fe, &if_frequency);
else else
if_frequency = 0; if_frequency = 0;
sampling_freq = if_frequency; utmp = DIV_ROUND_CLOSEST_ULL((u64)if_frequency * 0x800000,
adc_freq);
while (sampling_freq > (adc_freq / 2)) if (!dev->cfg.spec_inv && if_frequency)
sampling_freq -= adc_freq; utmp = 0x800000 - utmp;
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;
buf[0] = (utmp >> 0) & 0xff;
buf[1] = (utmp >> 8) & 0xff;
buf[2] = (utmp >> 16) & 0xff;
ret = regmap_bulk_write(dev->regmap, 0x800029, buf, 3); ret = regmap_bulk_write(dev->regmap, 0x800029, buf, 3);
if (ret) if (ret)
goto err; goto err;
dev_dbg(&dev->client->dev, "if_frequency_cw=%06x\n", utmp);
dev->bandwidth_hz = c->bandwidth_hz; dev->bandwidth_hz = c->bandwidth_hz;
} }
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include "af9033.h" #include "af9033.h"
#include <linux/math64.h> #include <linux/math64.h>
#include <linux/regmap.h> #include <linux/regmap.h>
#include <linux/kernel.h>
struct reg_val { struct reg_val {
u32 reg; u32 reg;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment