diff options
author | Olivier Grenie <olivier.grenie@parrot.com> | 2012-12-31 08:17:44 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2013-04-22 16:15:07 -0400 |
commit | 5e9c85d983375fd84a4ba98b34f8fc38d4ec8766 (patch) | |
tree | 3af7bc434e572f2bccf33b71509207bd99a0a723 /drivers/media/usb/dvb-usb | |
parent | aedabf7a5402cd46df6ca33e87d77762c08599b0 (diff) |
[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>
Diffstat (limited to 'drivers/media/usb/dvb-usb')
-rw-r--r-- | drivers/media/usb/dvb-usb/dib0700_devices.c | 208 |
1 files changed, 175 insertions, 33 deletions
diff --git a/drivers/media/usb/dvb-usb/dib0700_devices.c b/drivers/media/usb/dvb-usb/dib0700_devices.c index 5a4175ef3524..d0916c88d9c1 100644 --- a/drivers/media/usb/dvb-usb/dib0700_devices.c +++ b/drivers/media/usb/dvb-usb/dib0700_devices.c | |||
@@ -1431,13 +1431,22 @@ static int dib8090_get_adc_power(struct dvb_frontend *fe) | |||
1431 | return dib8000_get_adc_power(fe, 1); | 1431 | return dib8000_get_adc_power(fe, 1); |
1432 | } | 1432 | } |
1433 | 1433 | ||
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 | |||
1434 | static struct dib8000_config dib809x_dib8000_config[2] = { | 1443 | static struct dib8000_config dib809x_dib8000_config[2] = { |
1435 | { | 1444 | { |
1436 | .output_mpeg2_in_188_bytes = 1, | 1445 | .output_mpeg2_in_188_bytes = 1, |
1437 | 1446 | ||
1438 | .agc_config_count = 2, | 1447 | .agc_config_count = 2, |
1439 | .agc = dib8090_agc_config, | 1448 | .agc = dib8090_agc_config, |
1440 | .agc_control = dib0090_dcc_freq, | 1449 | .agc_control = dib8090_agc_control, |
1441 | .pll = &dib8090_pll_config_12mhz, | 1450 | .pll = &dib8090_pll_config_12mhz, |
1442 | .tuner_is_baseband = 1, | 1451 | .tuner_is_baseband = 1, |
1443 | 1452 | ||
@@ -1456,7 +1465,7 @@ static struct dib8000_config dib809x_dib8000_config[2] = { | |||
1456 | 1465 | ||
1457 | .agc_config_count = 2, | 1466 | .agc_config_count = 2, |
1458 | .agc = dib8090_agc_config, | 1467 | .agc = dib8090_agc_config, |
1459 | .agc_control = dib0090_dcc_freq, | 1468 | .agc_control = dib8090_agc_control, |
1460 | .pll = &dib8090_pll_config_12mhz, | 1469 | .pll = &dib8090_pll_config_12mhz, |
1461 | .tuner_is_baseband = 1, | 1470 | .tuner_is_baseband = 1, |
1462 | 1471 | ||
@@ -1504,28 +1513,89 @@ static struct dib0090_config dib809x_dib0090_config = { | |||
1504 | .fref_clock_ratio = 6, | 1513 | .fref_clock_ratio = 6, |
1505 | }; | 1514 | }; |
1506 | 1515 | ||
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 | |||
1507 | static int dib8096_set_param_override(struct dvb_frontend *fe) | 1540 | static int dib8096_set_param_override(struct dvb_frontend *fe) |
1508 | { | 1541 | { |
1509 | struct dtv_frontend_properties *p = &fe->dtv_property_cache; | ||
1510 | struct dvb_usb_adapter *adap = fe->dvb->priv; | 1542 | struct dvb_usb_adapter *adap = fe->dvb->priv; |
1511 | struct dib0700_adapter_state *state = adap->priv; | 1543 | struct dib0700_adapter_state *state = adap->priv; |
1512 | u8 band = BAND_OF_FREQUENCY(p->frequency/1000); | 1544 | u8 pll_ratio, band = BAND_OF_FREQUENCY(fe->dtv_property_cache.frequency / 1000); |
1513 | u16 target; | 1545 | u16 target, ltgain, rf_gain_limit; |
1546 | u32 timf; | ||
1514 | int ret = 0; | 1547 | int ret = 0; |
1515 | enum frontend_tune_state tune_state = CT_SHUTDOWN; | 1548 | 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 | } | ||
1517 | 1560 | ||
1518 | ret = state->set_param_save(fe); | 1561 | ret = state->set_param_save(fe); |
1519 | if (ret < 0) | 1562 | if (ret < 0) |
1520 | return ret; | 1563 | return ret; |
1521 | 1564 | ||
1522 | target = (dib0090_get_wbd_target(fe) * 8 * 18 / 33 + 1) / 2; | 1565 | if (fe->dtv_property_cache.bandwidth_hz != 6000000) { |
1523 | dib8000_set_wbd_ref(fe, target); | 1566 | deb_info("only 6MHz bandwidth is supported\n"); |
1567 | return -EINVAL; | ||
1568 | } | ||
1524 | 1569 | ||
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 | } | ||
1525 | 1594 | ||
1526 | if (band == BAND_CBAND) { | 1595 | if (band == BAND_CBAND) { |
1527 | deb_info("tuning in CBAND - soft-AGC startup\n"); | 1596 | deb_info("tuning in CBAND - soft-AGC startup\n"); |
1528 | dib0090_set_tune_state(fe, CT_AGC_START); | 1597 | dib0090_set_tune_state(fe, CT_AGC_START); |
1598 | |||
1529 | do { | 1599 | do { |
1530 | ret = dib0090_gain_control(fe); | 1600 | ret = dib0090_gain_control(fe); |
1531 | msleep(ret); | 1601 | msleep(ret); |
@@ -1534,14 +1604,17 @@ static int dib8096_set_param_override(struct dvb_frontend *fe) | |||
1534 | dib8000_set_gpio(fe, 6, 0, 1); | 1604 | dib8000_set_gpio(fe, 6, 0, 1); |
1535 | else if (tune_state == CT_AGC_STEP_1) { | 1605 | else if (tune_state == CT_AGC_STEP_1) { |
1536 | dib0090_get_current_gain(fe, NULL, NULL, &rf_gain_limit, <gain); | 1606 | dib0090_get_current_gain(fe, NULL, NULL, &rf_gain_limit, <gain); |
1537 | if (rf_gain_limit == 0) | 1607 | if (rf_gain_limit < 2000) /* activate the external attenuator in case of very high input power */ |
1538 | dib8000_set_gpio(fe, 6, 0, 0); | 1608 | dib8000_set_gpio(fe, 6, 0, 0); |
1539 | } | 1609 | } |
1540 | } while (tune_state < CT_AGC_STOP); | 1610 | } while (tune_state < CT_AGC_STOP); |
1611 | |||
1612 | deb_info("switching to PWM AGC\n"); | ||
1541 | dib0090_pwm_gain_reset(fe); | 1613 | dib0090_pwm_gain_reset(fe); |
1542 | dib8000_pwm_agc_reset(fe); | 1614 | dib8000_pwm_agc_reset(fe); |
1543 | dib8000_set_tune_state(fe, CT_DEMOD_START); | 1615 | dib8000_set_tune_state(fe, CT_DEMOD_START); |
1544 | } else { | 1616 | } else { |
1617 | /* for everything else than CBAND we are using standard AGC */ | ||
1545 | deb_info("not tuning in CBAND - standard AGC startup\n"); | 1618 | deb_info("not tuning in CBAND - standard AGC startup\n"); |
1546 | dib0090_pwm_gain_reset(fe); | 1619 | dib0090_pwm_gain_reset(fe); |
1547 | } | 1620 | } |
@@ -1814,21 +1887,92 @@ struct dibx090p_adc { | |||
1814 | u32 pll_prediv; /* New loopdiv */ | 1887 | u32 pll_prediv; /* New loopdiv */ |
1815 | }; | 1888 | }; |
1816 | 1889 | ||
1817 | struct dibx090p_adc dib8090p_adc_tab[] = { | 1890 | struct dibx090p_best_adc { |
1818 | { 50000, 17043521, 16, 3}, /* 64 MHz */ | 1891 | u32 timf; |
1819 | {878000, 20199729, 9, 1}, /* 60 MHz */ | 1892 | u32 pll_loopdiv; |
1820 | {0xffffffff, 0, 0, 0}, /* 60 MHz */ | 1893 | u32 pll_prediv; |
1821 | }; | 1894 | }; |
1822 | 1895 | ||
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 | |||
1823 | static int dib8096p_agc_startup(struct dvb_frontend *fe) | 1968 | static int dib8096p_agc_startup(struct dvb_frontend *fe) |
1824 | { | 1969 | { |
1825 | struct dtv_frontend_properties *p = &fe->dtv_property_cache; | ||
1826 | struct dvb_usb_adapter *adap = fe->dvb->priv; | 1970 | struct dvb_usb_adapter *adap = fe->dvb->priv; |
1827 | struct dib0700_adapter_state *state = adap->priv; | 1971 | struct dib0700_adapter_state *state = adap->priv; |
1828 | struct dibx000_bandwidth_config pll; | 1972 | struct dibx000_bandwidth_config pll; |
1973 | struct dibx090p_best_adc adc; | ||
1829 | u16 target; | 1974 | u16 target; |
1830 | int better_sampling_freq = 0, ret; | 1975 | int ret; |
1831 | struct dibx090p_adc *adc_table = &dib8090p_adc_tab[0]; | ||
1832 | 1976 | ||
1833 | ret = state->set_param_save(fe); | 1977 | ret = state->set_param_save(fe); |
1834 | if (ret < 0) | 1978 | if (ret < 0) |
@@ -1841,23 +1985,27 @@ static int dib8096p_agc_startup(struct dvb_frontend *fe) | |||
1841 | target = (dib0090_get_wbd_target(fe) * 8 + 1) / 2; | 1985 | target = (dib0090_get_wbd_target(fe) * 8 + 1) / 2; |
1842 | dib8000_set_wbd_ref(fe, target); | 1986 | dib8000_set_wbd_ref(fe, target); |
1843 | 1987 | ||
1988 | if (dib8096p_get_best_sampling(fe, &adc) == 0) { | ||
1989 | pll.pll_ratio = adc.pll_loopdiv; | ||
1990 | pll.pll_prediv = adc.pll_prediv; | ||
1844 | 1991 | ||
1845 | while (p->frequency / 1000 > adc_table->freq) { | 1992 | dib0700_set_i2c_speed(adap->dev, 200); |
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; | ||
1853 | dib8000_update_pll(fe, &pll, fe->dtv_property_cache.bandwidth_hz / 1000, 0); | 1993 | 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); | ||
1855 | } | 1996 | } |
1856 | return 0; | 1997 | return 0; |
1857 | } | 1998 | } |
1858 | 1999 | ||
1859 | static int tfe8096p_frontend_attach(struct dvb_usb_adapter *adap) | 2000 | static int tfe8096p_frontend_attach(struct dvb_usb_adapter *adap) |
1860 | { | 2001 | { |
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 | |||
1861 | dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1); | 2009 | dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1); |
1862 | msleep(20); | 2010 | msleep(20); |
1863 | dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1); | 2011 | dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1); |
@@ -2242,13 +2390,7 @@ static int nim9090md_tuner_attach(struct dvb_usb_adapter *adap) | |||
2242 | } | 2390 | } |
2243 | 2391 | ||
2244 | /* NIM7090 */ | 2392 | /* NIM7090 */ |
2245 | struct dib7090p_best_adc { | 2393 | static int dib7090p_get_best_sampling(struct dvb_frontend *fe , struct dibx090p_best_adc *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) | ||
2252 | { | 2394 | { |
2253 | u8 spur = 0, prediv = 0, loopdiv = 0, min_prediv = 1, max_prediv = 1; | 2395 | u8 spur = 0, prediv = 0, loopdiv = 0, min_prediv = 1, max_prediv = 1; |
2254 | 2396 | ||
@@ -2327,7 +2469,7 @@ static int dib7090_agc_startup(struct dvb_frontend *fe) | |||
2327 | struct dib0700_adapter_state *state = adap->priv; | 2469 | struct dib0700_adapter_state *state = adap->priv; |
2328 | struct dibx000_bandwidth_config pll; | 2470 | struct dibx000_bandwidth_config pll; |
2329 | u16 target; | 2471 | u16 target; |
2330 | struct dib7090p_best_adc adc; | 2472 | struct dibx090p_best_adc adc; |
2331 | int ret; | 2473 | int ret; |
2332 | 2474 | ||
2333 | ret = state->set_param_save(fe); | 2475 | ret = state->set_param_save(fe); |