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,
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;
}
......
......@@ -26,6 +26,7 @@
#include "af9033.h"
#include <linux/math64.h>
#include <linux/regmap.h>
#include <linux/kernel.h>
struct reg_val {
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