Skip to content

Commit 5e9c85d

Browse files
Olivier GrenieMauro Carvalho Chehab
authored andcommitted
[media] dib8096: enhancement
The intend of this patch is to improve the support of the dib8096. The PLL parameters are not automatically computed. The limit to set/unset external diode for attenuation has been updated. The TFE8096P board is using the new I2C API. Signed-off-by: Olivier Grenie <olivier.grenie@parrot.com> Signed-off-by: Patrick Boettcher <patrick.boettcher@parrot.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
1 parent aedabf7 commit 5e9c85d

File tree

1 file changed

+175
-33
lines changed

1 file changed

+175
-33
lines changed

drivers/media/usb/dvb-usb/dib0700_devices.c

Lines changed: 175 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1431,13 +1431,22 @@ static int dib8090_get_adc_power(struct dvb_frontend *fe)
14311431
return dib8000_get_adc_power(fe, 1);
14321432
}
14331433

1434+
static void dib8090_agc_control(struct dvb_frontend *fe, u8 restart)
1435+
{
1436+
deb_info("AGC control callback: %i\n", restart);
1437+
dib0090_dcc_freq(fe, restart);
1438+
1439+
if (restart == 0) /* before AGC startup */
1440+
dib0090_set_dc_servo(fe, 1);
1441+
}
1442+
14341443
static struct dib8000_config dib809x_dib8000_config[2] = {
14351444
{
14361445
.output_mpeg2_in_188_bytes = 1,
14371446

14381447
.agc_config_count = 2,
14391448
.agc = dib8090_agc_config,
1440-
.agc_control = dib0090_dcc_freq,
1449+
.agc_control = dib8090_agc_control,
14411450
.pll = &dib8090_pll_config_12mhz,
14421451
.tuner_is_baseband = 1,
14431452

@@ -1456,7 +1465,7 @@ static struct dib8000_config dib809x_dib8000_config[2] = {
14561465

14571466
.agc_config_count = 2,
14581467
.agc = dib8090_agc_config,
1459-
.agc_control = dib0090_dcc_freq,
1468+
.agc_control = dib8090_agc_control,
14601469
.pll = &dib8090_pll_config_12mhz,
14611470
.tuner_is_baseband = 1,
14621471

@@ -1504,28 +1513,89 @@ static struct dib0090_config dib809x_dib0090_config = {
15041513
.fref_clock_ratio = 6,
15051514
};
15061515

1516+
static u8 dib8090_compute_pll_parameters(struct dvb_frontend *fe)
1517+
{
1518+
u8 optimal_pll_ratio = 20;
1519+
u32 freq_adc, ratio, rest, max = 0;
1520+
u8 pll_ratio;
1521+
1522+
for (pll_ratio = 17; pll_ratio <= 20; pll_ratio++) {
1523+
freq_adc = 12 * pll_ratio * (1 << 8) / 16;
1524+
ratio = ((fe->dtv_property_cache.frequency / 1000) * (1 << 8) / 1000) / freq_adc;
1525+
rest = ((fe->dtv_property_cache.frequency / 1000) * (1 << 8) / 1000) - ratio * freq_adc;
1526+
1527+
if (rest > freq_adc / 2)
1528+
rest = freq_adc - rest;
1529+
deb_info("PLL ratio=%i rest=%i\n", pll_ratio, rest);
1530+
if ((rest > max) && (rest > 717)) {
1531+
optimal_pll_ratio = pll_ratio;
1532+
max = rest;
1533+
}
1534+
}
1535+
deb_info("optimal PLL ratio=%i\n", optimal_pll_ratio);
1536+
1537+
return optimal_pll_ratio;
1538+
}
1539+
15071540
static int dib8096_set_param_override(struct dvb_frontend *fe)
15081541
{
1509-
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
15101542
struct dvb_usb_adapter *adap = fe->dvb->priv;
15111543
struct dib0700_adapter_state *state = adap->priv;
1512-
u8 band = BAND_OF_FREQUENCY(p->frequency/1000);
1513-
u16 target;
1544+
u8 pll_ratio, band = BAND_OF_FREQUENCY(fe->dtv_property_cache.frequency / 1000);
1545+
u16 target, ltgain, rf_gain_limit;
1546+
u32 timf;
15141547
int ret = 0;
15151548
enum frontend_tune_state tune_state = CT_SHUTDOWN;
1516-
u16 ltgain, rf_gain_limit;
1549+
1550+
switch (band) {
1551+
default:
1552+
deb_info("Warning : Rf frequency (%iHz) is not in the supported range, using VHF switch ", fe->dtv_property_cache.frequency);
1553+
case BAND_VHF:
1554+
dib8000_set_gpio(fe, 3, 0, 1);
1555+
break;
1556+
case BAND_UHF:
1557+
dib8000_set_gpio(fe, 3, 0, 0);
1558+
break;
1559+
}
15171560

15181561
ret = state->set_param_save(fe);
15191562
if (ret < 0)
15201563
return ret;
15211564

1522-
target = (dib0090_get_wbd_target(fe) * 8 * 18 / 33 + 1) / 2;
1523-
dib8000_set_wbd_ref(fe, target);
1565+
if (fe->dtv_property_cache.bandwidth_hz != 6000000) {
1566+
deb_info("only 6MHz bandwidth is supported\n");
1567+
return -EINVAL;
1568+
}
15241569

1570+
/** Update PLL if needed ratio **/
1571+
dib8000_update_pll(fe, &dib8090_pll_config_12mhz, fe->dtv_property_cache.bandwidth_hz / 1000, 0);
1572+
1573+
/** Get optimize PLL ratio to remove spurious **/
1574+
pll_ratio = dib8090_compute_pll_parameters(fe);
1575+
if (pll_ratio == 17)
1576+
timf = 21387946;
1577+
else if (pll_ratio == 18)
1578+
timf = 20199727;
1579+
else if (pll_ratio == 19)
1580+
timf = 19136583;
1581+
else
1582+
timf = 18179756;
1583+
1584+
/** Update ratio **/
1585+
dib8000_update_pll(fe, &dib8090_pll_config_12mhz, fe->dtv_property_cache.bandwidth_hz / 1000, pll_ratio);
1586+
1587+
dib8000_ctrl_timf(fe, DEMOD_TIMF_SET, timf);
1588+
1589+
if (band != BAND_CBAND) {
1590+
/* dib0090_get_wbd_target is returning any possible temperature compensated wbd-target */
1591+
target = (dib0090_get_wbd_target(fe) * 8 * 18 / 33 + 1) / 2;
1592+
dib8000_set_wbd_ref(fe, target);
1593+
}
15251594

15261595
if (band == BAND_CBAND) {
15271596
deb_info("tuning in CBAND - soft-AGC startup\n");
15281597
dib0090_set_tune_state(fe, CT_AGC_START);
1598+
15291599
do {
15301600
ret = dib0090_gain_control(fe);
15311601
msleep(ret);
@@ -1534,14 +1604,17 @@ static int dib8096_set_param_override(struct dvb_frontend *fe)
15341604
dib8000_set_gpio(fe, 6, 0, 1);
15351605
else if (tune_state == CT_AGC_STEP_1) {
15361606
dib0090_get_current_gain(fe, NULL, NULL, &rf_gain_limit, &ltgain);
1537-
if (rf_gain_limit == 0)
1607+
if (rf_gain_limit < 2000) /* activate the external attenuator in case of very high input power */
15381608
dib8000_set_gpio(fe, 6, 0, 0);
15391609
}
15401610
} while (tune_state < CT_AGC_STOP);
1611+
1612+
deb_info("switching to PWM AGC\n");
15411613
dib0090_pwm_gain_reset(fe);
15421614
dib8000_pwm_agc_reset(fe);
15431615
dib8000_set_tune_state(fe, CT_DEMOD_START);
15441616
} else {
1617+
/* for everything else than CBAND we are using standard AGC */
15451618
deb_info("not tuning in CBAND - standard AGC startup\n");
15461619
dib0090_pwm_gain_reset(fe);
15471620
}
@@ -1814,21 +1887,92 @@ struct dibx090p_adc {
18141887
u32 pll_prediv; /* New loopdiv */
18151888
};
18161889

1817-
struct dibx090p_adc dib8090p_adc_tab[] = {
1818-
{ 50000, 17043521, 16, 3}, /* 64 MHz */
1819-
{878000, 20199729, 9, 1}, /* 60 MHz */
1820-
{0xffffffff, 0, 0, 0}, /* 60 MHz */
1890+
struct dibx090p_best_adc {
1891+
u32 timf;
1892+
u32 pll_loopdiv;
1893+
u32 pll_prediv;
18211894
};
18221895

1896+
static int dib8096p_get_best_sampling(struct dvb_frontend *fe, struct dibx090p_best_adc *adc)
1897+
{
1898+
u8 spur = 0, prediv = 0, loopdiv = 0, min_prediv = 1, max_prediv = 1;
1899+
u16 xtal = 12000;
1900+
u16 fcp_min = 1900; /* PLL, Minimum Frequency of phase comparator (KHz) */
1901+
u16 fcp_max = 20000; /* PLL, Maximum Frequency of phase comparator (KHz) */
1902+
u32 fmem_max = 140000; /* 140MHz max SDRAM freq */
1903+
u32 fdem_min = 66000;
1904+
u32 fcp = 0, fs = 0, fdem = 0, fmem = 0;
1905+
u32 harmonic_id = 0;
1906+
1907+
adc->timf = 0;
1908+
adc->pll_loopdiv = loopdiv;
1909+
adc->pll_prediv = prediv;
1910+
1911+
deb_info("bandwidth = %d", fe->dtv_property_cache.bandwidth_hz);
1912+
1913+
/* Find Min and Max prediv */
1914+
while ((xtal / max_prediv) >= fcp_min)
1915+
max_prediv++;
1916+
1917+
max_prediv--;
1918+
min_prediv = max_prediv;
1919+
while ((xtal / min_prediv) <= fcp_max) {
1920+
min_prediv--;
1921+
if (min_prediv == 1)
1922+
break;
1923+
}
1924+
deb_info("MIN prediv = %d : MAX prediv = %d", min_prediv, max_prediv);
1925+
1926+
min_prediv = 1;
1927+
1928+
for (prediv = min_prediv; prediv < max_prediv; prediv++) {
1929+
fcp = xtal / prediv;
1930+
if (fcp > fcp_min && fcp < fcp_max) {
1931+
for (loopdiv = 1; loopdiv < 64; loopdiv++) {
1932+
fmem = ((xtal/prediv) * loopdiv);
1933+
fdem = fmem / 2;
1934+
fs = fdem / 4;
1935+
1936+
/* test min/max system restrictions */
1937+
if ((fdem >= fdem_min) && (fmem <= fmem_max) && (fs >= fe->dtv_property_cache.bandwidth_hz / 1000)) {
1938+
spur = 0;
1939+
/* test fs harmonics positions */
1940+
for (harmonic_id = (fe->dtv_property_cache.frequency / (1000 * fs)); harmonic_id <= ((fe->dtv_property_cache.frequency / (1000 * fs)) + 1); harmonic_id++) {
1941+
if (((fs * harmonic_id) >= (fe->dtv_property_cache.frequency / 1000 - (fe->dtv_property_cache.bandwidth_hz / 2000))) && ((fs * harmonic_id) <= (fe->dtv_property_cache.frequency / 1000 + (fe->dtv_property_cache.bandwidth_hz / 2000)))) {
1942+
spur = 1;
1943+
break;
1944+
}
1945+
}
1946+
1947+
if (!spur) {
1948+
adc->pll_loopdiv = loopdiv;
1949+
adc->pll_prediv = prediv;
1950+
adc->timf = (4260880253U / fdem) * (1 << 8);
1951+
adc->timf += ((4260880253U % fdem) << 8) / fdem;
1952+
1953+
deb_info("RF %6d; BW %6d; Xtal %6d; Fmem %6d; Fdem %6d; Fs %6d; Prediv %2d; Loopdiv %2d; Timf %8d;", fe->dtv_property_cache.frequency, fe->dtv_property_cache.bandwidth_hz, xtal, fmem, fdem, fs, prediv, loopdiv, adc->timf);
1954+
break;
1955+
}
1956+
}
1957+
}
1958+
}
1959+
if (!spur)
1960+
break;
1961+
}
1962+
1963+
if (adc->pll_loopdiv == 0 && adc->pll_prediv == 0)
1964+
return -EINVAL;
1965+
return 0;
1966+
}
1967+
18231968
static int dib8096p_agc_startup(struct dvb_frontend *fe)
18241969
{
1825-
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
18261970
struct dvb_usb_adapter *adap = fe->dvb->priv;
18271971
struct dib0700_adapter_state *state = adap->priv;
18281972
struct dibx000_bandwidth_config pll;
1973+
struct dibx090p_best_adc adc;
18291974
u16 target;
1830-
int better_sampling_freq = 0, ret;
1831-
struct dibx090p_adc *adc_table = &dib8090p_adc_tab[0];
1975+
int ret;
18321976

18331977
ret = state->set_param_save(fe);
18341978
if (ret < 0)
@@ -1841,23 +1985,27 @@ static int dib8096p_agc_startup(struct dvb_frontend *fe)
18411985
target = (dib0090_get_wbd_target(fe) * 8 + 1) / 2;
18421986
dib8000_set_wbd_ref(fe, target);
18431987

1988+
if (dib8096p_get_best_sampling(fe, &adc) == 0) {
1989+
pll.pll_ratio = adc.pll_loopdiv;
1990+
pll.pll_prediv = adc.pll_prediv;
18441991

1845-
while (p->frequency / 1000 > adc_table->freq) {
1846-
better_sampling_freq = 1;
1847-
adc_table++;
1848-
}
1849-
1850-
if ((adc_table->freq != 0xffffffff) && better_sampling_freq) {
1851-
pll.pll_ratio = adc_table->pll_loopdiv;
1852-
pll.pll_prediv = adc_table->pll_prediv;
1992+
dib0700_set_i2c_speed(adap->dev, 200);
18531993
dib8000_update_pll(fe, &pll, fe->dtv_property_cache.bandwidth_hz / 1000, 0);
1854-
dib8000_ctrl_timf(fe, DEMOD_TIMF_SET, adc_table->timf);
1994+
dib8000_ctrl_timf(fe, DEMOD_TIMF_SET, adc.timf);
1995+
dib0700_set_i2c_speed(adap->dev, 1000);
18551996
}
18561997
return 0;
18571998
}
18581999

18592000
static int tfe8096p_frontend_attach(struct dvb_usb_adapter *adap)
18602001
{
2002+
struct dib0700_state *st = adap->dev->priv;
2003+
u32 fw_version;
2004+
2005+
dib0700_get_version(adap->dev, NULL, NULL, &fw_version, NULL);
2006+
if (fw_version >= 0x10200)
2007+
st->fw_use_new_i2c_api = 1;
2008+
18612009
dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
18622010
msleep(20);
18632011
dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1);
@@ -2242,13 +2390,7 @@ static int nim9090md_tuner_attach(struct dvb_usb_adapter *adap)
22422390
}
22432391

22442392
/* NIM7090 */
2245-
struct dib7090p_best_adc {
2246-
u32 timf;
2247-
u32 pll_loopdiv;
2248-
u32 pll_prediv;
2249-
};
2250-
2251-
static int dib7090p_get_best_sampling(struct dvb_frontend *fe , struct dib7090p_best_adc *adc)
2393+
static int dib7090p_get_best_sampling(struct dvb_frontend *fe , struct dibx090p_best_adc *adc)
22522394
{
22532395
u8 spur = 0, prediv = 0, loopdiv = 0, min_prediv = 1, max_prediv = 1;
22542396

@@ -2327,7 +2469,7 @@ static int dib7090_agc_startup(struct dvb_frontend *fe)
23272469
struct dib0700_adapter_state *state = adap->priv;
23282470
struct dibx000_bandwidth_config pll;
23292471
u16 target;
2330-
struct dib7090p_best_adc adc;
2472+
struct dibx090p_best_adc adc;
23312473
int ret;
23322474

23332475
ret = state->set_param_save(fe);

0 commit comments

Comments
 (0)