aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@redhat.com>2013-04-10 14:55:48 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2013-04-16 20:33:11 -0400
commit25cf4d462abd6d78d224b564de82dcdab7973673 (patch)
tree2ebbc629fdadcdb92f4817a95587b26f5b9109bc
parentd75d538899da00bdf8f152c65a99eda1ab59daa3 (diff)
[media] r820t: add IMR calibrate code
This code seems to calibrate I/Q phase and gain during the device initialization. This is done only once, and it doesn't seem to be needed to happen after resuming. Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com> Tested-by: Antti Palosaari <crope@iki.fi>
-rw-r--r--drivers/media/tuners/r820t.c702
1 files changed, 681 insertions, 21 deletions
diff --git a/drivers/media/tuners/r820t.c b/drivers/media/tuners/r820t.c
index 07d032350c1b..fa2e9ae48c98 100644
--- a/drivers/media/tuners/r820t.c
+++ b/drivers/media/tuners/r820t.c
@@ -47,6 +47,8 @@
47 */ 47 */
48#define REG_SHADOW_START 5 48#define REG_SHADOW_START 5
49#define NUM_REGS 27 49#define NUM_REGS 27
50#define NUM_IMR 5
51#define IMR_TRIAL 9
50 52
51#define VER_NUM 49 53#define VER_NUM 49
52 54
@@ -66,6 +68,12 @@ enum xtal_cap_value {
66 XTAL_HIGH_CAP_0P 68 XTAL_HIGH_CAP_0P
67}; 69};
68 70
71struct r820t_sect_type {
72 u8 phase_y;
73 u8 gain_x;
74 u16 value;
75};
76
69struct r820t_priv { 77struct r820t_priv {
70 struct list_head hybrid_tuner_instance_list; 78 struct list_head hybrid_tuner_instance_list;
71 const struct r820t_config *cfg; 79 const struct r820t_config *cfg;
@@ -80,6 +88,8 @@ struct r820t_priv {
80 u8 fil_cal_code; 88 u8 fil_cal_code;
81 bool imr_done; 89 bool imr_done;
82 90
91 struct r820t_sect_type imr_data[NUM_IMR];
92
83 /* Store current mode */ 93 /* Store current mode */
84 u32 delsys; 94 u32 delsys;
85 enum v4l2_tuner_type type; 95 enum v4l2_tuner_type type;
@@ -459,7 +469,7 @@ static int r820t_set_mux(struct r820t_priv *priv, u32 freq)
459{ 469{
460 const struct r820t_freq_range *range; 470 const struct r820t_freq_range *range;
461 int i, rc; 471 int i, rc;
462 u8 val; 472 u8 val, reg08, reg09;
463 473
464 /* Get the proper frequency range */ 474 /* Get the proper frequency range */
465 freq = freq / 1000000; 475 freq = freq / 1000000;
@@ -507,17 +517,18 @@ static int r820t_set_mux(struct r820t_priv *priv, u32 freq)
507 if (rc < 0) 517 if (rc < 0)
508 return rc; 518 return rc;
509 519
510 /* 520 if (priv->imr_done) {
511 * FIXME: the original driver has a logic there with preserves 521 reg08 = priv->imr_data[range->imr_mem].gain_x;
512 * gain/phase from registers 8 and 9 reading the data from the 522 reg09 = priv->imr_data[range->imr_mem].phase_y;
513 * registers before writing, if "IMF done". That code was sort of 523 } else {
514 * commented there, as the flag is always false. 524 reg08 = 0;
515 */ 525 reg09 = 0;
516 rc = r820t_write_reg_mask(priv, 0x08, 0, 0x3f); 526 }
527 rc = r820t_write_reg_mask(priv, 0x08, reg08, 0x3f);
517 if (rc < 0) 528 if (rc < 0)
518 return rc; 529 return rc;
519 530
520 rc = r820t_write_reg_mask(priv, 0x09, 0, 0x3f); 531 rc = r820t_write_reg_mask(priv, 0x09, reg09, 0x3f);
521 532
522 return rc; 533 return rc;
523} 534}
@@ -1383,24 +1394,621 @@ static int r820t_xtal_check(struct r820t_priv *priv)
1383 return r820t_xtal_capacitor[i][1]; 1394 return r820t_xtal_capacitor[i][1];
1384} 1395}
1385 1396
1386/* 1397static int r820t_imr_prepare(struct r820t_priv *priv)
1387 * r820t frontend operations and tuner attach code 1398{
1388 * 1399 int rc;
1389 * All driver locks and i2c control are only in this part of the code
1390 */
1391 1400
1392static int r820t_init(struct dvb_frontend *fe) 1401 /* Initialize the shadow registers */
1402 memcpy(priv->regs, r820t_init_array, sizeof(r820t_init_array));
1403
1404 /* lna off (air-in off) */
1405 rc = r820t_write_reg_mask(priv, 0x05, 0x20, 0x20);
1406 if (rc < 0)
1407 return rc;
1408
1409 /* mixer gain mode = manual */
1410 rc = r820t_write_reg_mask(priv, 0x07, 0, 0x10);
1411 if (rc < 0)
1412 return rc;
1413
1414 /* filter corner = lowest */
1415 rc = r820t_write_reg_mask(priv, 0x0a, 0x0f, 0x0f);
1416 if (rc < 0)
1417 return rc;
1418
1419 /* filter bw=+2cap, hp=5M */
1420 rc = r820t_write_reg_mask(priv, 0x0b, 0x60, 0x6f);
1421 if (rc < 0)
1422 return rc;
1423
1424 /* adc=on, vga code mode, gain = 26.5dB */
1425 rc = r820t_write_reg_mask(priv, 0x0c, 0x0b, 0x9f);
1426 if (rc < 0)
1427 return rc;
1428
1429 /* ring clk = on */
1430 rc = r820t_write_reg_mask(priv, 0x0f, 0, 0x08);
1431 if (rc < 0)
1432 return rc;
1433
1434 /* ring power = on */
1435 rc = r820t_write_reg_mask(priv, 0x18, 0x10, 0x10);
1436 if (rc < 0)
1437 return rc;
1438
1439 /* from ring = ring pll in */
1440 rc = r820t_write_reg_mask(priv, 0x1c, 0x02, 0x02);
1441 if (rc < 0)
1442 return rc;
1443
1444 /* sw_pdect = det3 */
1445 rc = r820t_write_reg_mask(priv, 0x1e, 0x80, 0x80);
1446 if (rc < 0)
1447 return rc;
1448
1449 /* Set filt_3dB */
1450 rc = r820t_write_reg_mask(priv, 0x06, 0x20, 0x20);
1451
1452 return rc;
1453}
1454
1455static int r820t_multi_read(struct r820t_priv *priv)
1456{
1457 int rc, i;
1458 u8 data[2], min = 0, max = 255, sum = 0;
1459
1460 usleep_range(5000, 6000);
1461
1462 for (i = 0; i < 6; i++) {
1463 rc = r820t_read(priv, 0x00, data, sizeof(data));
1464 if (rc < 0)
1465 return rc;
1466
1467 sum += data[1];
1468
1469 if (data[1] < min)
1470 min = data[1];
1471
1472 if (data[1] > max)
1473 max = data[1];
1474 }
1475 rc = sum - max - min;
1476
1477 return rc;
1478}
1479
1480static int r820t_imr_cross(struct r820t_priv *priv,
1481 struct r820t_sect_type iq_point[3],
1482 u8 *x_direct)
1483{
1484 struct r820t_sect_type cross[5]; /* (0,0)(0,Q-1)(0,I-1)(Q-1,0)(I-1,0) */
1485 struct r820t_sect_type tmp;
1486 int i, rc;
1487 u8 reg08, reg09;
1488
1489 reg08 = r820t_read_cache_reg(priv, 8) & 0xc0;
1490 reg09 = r820t_read_cache_reg(priv, 9) & 0xc0;
1491
1492 tmp.gain_x = 0;
1493 tmp.phase_y = 0;
1494 tmp.value = 255;
1495
1496 for (i = 0; i < 5; i++) {
1497 switch (i) {
1498 case 0:
1499 cross[i].gain_x = reg08;
1500 cross[i].phase_y = reg09;
1501 break;
1502 case 1:
1503 cross[i].gain_x = reg08; /* 0 */
1504 cross[i].phase_y = reg09 + 1; /* Q-1 */
1505 break;
1506 case 2:
1507 cross[i].gain_x = reg08; /* 0 */
1508 cross[i].phase_y = (reg09 | 0x20) + 1; /* I-1 */
1509 break;
1510 case 3:
1511 cross[i].gain_x = reg08 + 1; /* Q-1 */
1512 cross[i].phase_y = reg09;
1513 break;
1514 default:
1515 cross[i].gain_x = (reg08 | 0x20) + 1; /* I-1 */
1516 cross[i].phase_y = reg09;
1517 }
1518
1519 rc = r820t_write_reg(priv, 0x08, cross[i].gain_x);
1520 if (rc < 0)
1521 return rc;
1522
1523 rc = r820t_write_reg(priv, 0x09, cross[i].phase_y);
1524 if (rc < 0)
1525 return rc;
1526
1527 rc = r820t_multi_read(priv);
1528 if (rc < 0)
1529 return rc;
1530
1531 cross[i].value = rc;
1532
1533 if (cross[i].value < tmp.value)
1534 memcpy(&tmp, &cross[i], sizeof(tmp));
1535 }
1536
1537 if ((tmp.phase_y & 0x1f) == 1) { /* y-direction */
1538 *x_direct = 0;
1539
1540 iq_point[0] = cross[0];
1541 iq_point[1] = cross[1];
1542 iq_point[2] = cross[2];
1543 } else { /* (0,0) or x-direction */
1544 *x_direct = 1;
1545
1546 iq_point[0] = cross[0];
1547 iq_point[1] = cross[3];
1548 iq_point[2] = cross[4];
1549 }
1550 return 0;
1551}
1552
1553static void r820t_compre_cor(struct r820t_sect_type iq[3])
1554{
1555 int i;
1556
1557 for (i = 3; i > 0; i--) {
1558 if (iq[0].value > iq[i - 1].value)
1559 swap(iq[0], iq[i - 1]);
1560 }
1561}
1562
1563static int r820t_compre_step(struct r820t_priv *priv,
1564 struct r820t_sect_type iq[3], u8 reg)
1565{
1566 int rc;
1567 struct r820t_sect_type tmp;
1568
1569 /*
1570 * Purpose: if (Gain<9 or Phase<9), Gain+1 or Phase+1 and compare
1571 * with min value:
1572 * new < min => update to min and continue
1573 * new > min => Exit
1574 */
1575
1576 /* min value already saved in iq[0] */
1577 tmp.phase_y = iq[0].phase_y;
1578 tmp.gain_x = iq[0].gain_x;
1579
1580 while (((tmp.gain_x & 0x1f) < IMR_TRIAL) &&
1581 ((tmp.phase_y & 0x1f) < IMR_TRIAL)) {
1582 if (reg == 0x08)
1583 tmp.gain_x++;
1584 else
1585 tmp.phase_y++;
1586
1587 rc = r820t_write_reg(priv, 0x08, tmp.gain_x);
1588 if (rc < 0)
1589 return rc;
1590
1591 rc = r820t_write_reg(priv, 0x09, tmp.phase_y);
1592 if (rc < 0)
1593 return rc;
1594
1595 rc = r820t_multi_read(priv);
1596 if (rc < 0)
1597 return rc;
1598 tmp.value = rc;
1599
1600 if (tmp.value <= iq[0].value) {
1601 iq[0].gain_x = tmp.gain_x;
1602 iq[0].phase_y = tmp.phase_y;
1603 iq[0].value = tmp.value;
1604 } else {
1605 return 0;
1606 }
1607
1608 }
1609
1610 return 0;
1611}
1612
1613static int r820t_iq_tree(struct r820t_priv *priv,
1614 struct r820t_sect_type iq[3],
1615 u8 fix_val, u8 var_val, u8 fix_reg)
1616{
1617 int rc, i;
1618 u8 tmp, var_reg;
1619
1620 /*
1621 * record IMC results by input gain/phase location then adjust
1622 * gain or phase positive 1 step and negtive 1 step,
1623 * both record results
1624 */
1625
1626 if (fix_reg == 0x08)
1627 var_reg = 0x09;
1628 else
1629 var_reg = 0x08;
1630
1631 for (i = 0; i < 3; i++) {
1632 rc = r820t_write_reg(priv, fix_reg, fix_val);
1633 if (rc < 0)
1634 return rc;
1635
1636 rc = r820t_write_reg(priv, var_reg, var_val);
1637 if (rc < 0)
1638 return rc;
1639
1640 rc = r820t_multi_read(priv);
1641 if (rc < 0)
1642 return rc;
1643 iq[i].value = rc;
1644
1645 if (fix_reg == 0x08) {
1646 iq[i].gain_x = fix_val;
1647 iq[i].phase_y = var_val;
1648 } else {
1649 iq[i].phase_y = fix_val;
1650 iq[i].gain_x = var_val;
1651 }
1652
1653 if (i == 0) { /* try right-side point */
1654 var_val++;
1655 } else if (i == 1) { /* try left-side point */
1656 /* if absolute location is 1, change I/Q direction */
1657 if ((var_val & 0x1f) < 0x02) {
1658 tmp = 2 - (var_val & 0x1f);
1659
1660 /* b[5]:I/Q selection. 0:Q-path, 1:I-path */
1661 if (var_val & 0x20) {
1662 var_val &= 0xc0;
1663 var_val |= tmp;
1664 } else {
1665 var_val |= 0x20 | tmp;
1666 }
1667 } else {
1668 var_val -= 2;
1669 }
1670 }
1671 }
1672
1673 return 0;
1674}
1675
1676static int r820t_section(struct r820t_priv *priv,
1677 struct r820t_sect_type *iq_point)
1678{
1679 int rc;
1680 struct r820t_sect_type compare_iq[3], compare_bet[3];
1681
1682 /* Try X-1 column and save min result to compare_bet[0] */
1683 if (!(iq_point->gain_x & 0x1f))
1684 compare_iq[0].gain_x = ((iq_point->gain_x) & 0xdf) + 1; /* Q-path, Gain=1 */
1685 else
1686 compare_iq[0].gain_x = iq_point->gain_x - 1; /* left point */
1687 compare_iq[0].phase_y = iq_point->phase_y;
1688
1689 /* y-direction */
1690 rc = r820t_iq_tree(priv, compare_iq, compare_iq[0].gain_x,
1691 compare_iq[0].phase_y, 0x08);
1692 if (rc < 0)
1693 return rc;
1694
1695 r820t_compre_cor(compare_iq);
1696
1697 compare_bet[0] = compare_iq[0];
1698
1699 /* Try X column and save min result to compare_bet[1] */
1700 compare_iq[0].gain_x = iq_point->gain_x;
1701 compare_iq[0].phase_y = iq_point->phase_y;
1702
1703 rc = r820t_iq_tree(priv, compare_iq, compare_iq[0].gain_x,
1704 compare_iq[0].phase_y, 0x08);
1705 if (rc < 0)
1706 return rc;
1707
1708 r820t_compre_cor(compare_iq);
1709
1710 compare_bet[1] = compare_iq[0];
1711
1712 /* Try X+1 column and save min result to compare_bet[2] */
1713 if ((iq_point->gain_x & 0x1f) == 0x00)
1714 compare_iq[0].gain_x = ((iq_point->gain_x) | 0x20) + 1; /* I-path, Gain=1 */
1715 else
1716 compare_iq[0].gain_x = iq_point->gain_x + 1;
1717 compare_iq[0].phase_y = iq_point->phase_y;
1718
1719 rc = r820t_iq_tree(priv, compare_iq, compare_iq[0].gain_x,
1720 compare_iq[0].phase_y, 0x08);
1721 if (rc < 0)
1722 return rc;
1723
1724 r820t_compre_cor(compare_iq);
1725
1726 compare_bet[2] = compare_iq[0];
1727
1728 r820t_compre_cor(compare_bet);
1729
1730 *iq_point = compare_bet[0];
1731
1732 return 0;
1733}
1734
1735static int r820t_vga_adjust(struct r820t_priv *priv)
1736{
1737 int rc;
1738 u8 vga_count;
1739
1740 /* increase vga power to let image significant */
1741 for (vga_count = 12; vga_count < 16; vga_count++) {
1742 rc = r820t_write_reg_mask(priv, 0x0c, vga_count, 0x0f);
1743 if (rc < 0)
1744 return rc;
1745
1746 usleep_range(10000, 11000);
1747
1748 rc = r820t_multi_read(priv);
1749 if (rc < 0)
1750 return rc;
1751
1752 if (rc > 40 * 4)
1753 break;
1754 }
1755
1756 return 0;
1757}
1758
1759static int r820t_iq(struct r820t_priv *priv, struct r820t_sect_type *iq_pont)
1760{
1761 struct r820t_sect_type compare_iq[3];
1762 int rc;
1763 u8 x_direction = 0; /* 1:x, 0:y */
1764 u8 dir_reg, other_reg;
1765
1766 r820t_vga_adjust(priv);
1767
1768 rc = r820t_imr_cross(priv, compare_iq, &x_direction);
1769 if (rc < 0)
1770 return rc;
1771
1772 if (x_direction == 1) {
1773 dir_reg = 0x08;
1774 other_reg = 0x09;
1775 } else {
1776 dir_reg = 0x09;
1777 other_reg = 0x08;
1778 }
1779
1780 /* compare and find min of 3 points. determine i/q direction */
1781 r820t_compre_cor(compare_iq);
1782
1783 /* increase step to find min value of this direction */
1784 rc = r820t_compre_step(priv, compare_iq, dir_reg);
1785 if (rc < 0)
1786 return rc;
1787
1788 /* the other direction */
1789 rc = r820t_iq_tree(priv, compare_iq, compare_iq[0].gain_x,
1790 compare_iq[0].phase_y, dir_reg);
1791 if (rc < 0)
1792 return rc;
1793
1794 /* compare and find min of 3 points. determine i/q direction */
1795 r820t_compre_cor(compare_iq);
1796
1797 /* increase step to find min value on this direction */
1798 rc = r820t_compre_step(priv, compare_iq, other_reg);
1799 if (rc < 0)
1800 return rc;
1801
1802 /* check 3 points again */
1803 rc = r820t_iq_tree(priv, compare_iq, compare_iq[0].gain_x,
1804 compare_iq[0].phase_y, other_reg);
1805 if (rc < 0)
1806 return rc;
1807
1808 r820t_compre_cor(compare_iq);
1809
1810 /* section-9 check */
1811 rc = r820t_section(priv, compare_iq);
1812
1813 *iq_pont = compare_iq[0];
1814
1815 /* reset gain/phase control setting */
1816 rc = r820t_write_reg_mask(priv, 0x08, 0, 0x3f);
1817 if (rc < 0)
1818 return rc;
1819
1820 rc = r820t_write_reg_mask(priv, 0x09, 0, 0x3f);
1821
1822 return rc;
1823}
1824
1825static int r820t_f_imr(struct r820t_priv *priv, struct r820t_sect_type *iq_pont)
1826{
1827 int rc;
1828
1829 r820t_vga_adjust(priv);
1830
1831 /*
1832 * search surrounding points from previous point
1833 * try (x-1), (x), (x+1) columns, and find min IMR result point
1834 */
1835 rc = r820t_section(priv, iq_pont);
1836 if (rc < 0)
1837 return rc;
1838
1839 return 0;
1840}
1841
1842static int r820t_imr(struct r820t_priv *priv, unsigned imr_mem, bool im_flag)
1843{
1844 struct r820t_sect_type imr_point;
1845 int rc;
1846 u32 ring_vco, ring_freq, ring_ref;
1847 u8 n_ring, n;
1848 int reg18, reg19, reg1f;
1849
1850 if (priv->cfg->xtal > 24000000)
1851 ring_ref = priv->cfg->xtal / 2;
1852 else
1853 ring_ref = priv->cfg->xtal;
1854
1855 for (n = 0; n < 16; n++) {
1856 if ((16 + n) * 8 * ring_ref >= 3100000) {
1857 n_ring = n;
1858 break;
1859 }
1860
1861 /* n_ring not found */
1862 if (n == 15)
1863 n_ring = n;
1864 }
1865
1866 reg18 = r820t_read_cache_reg(priv, 0x18);
1867 reg19 = r820t_read_cache_reg(priv, 0x19);
1868 reg1f = r820t_read_cache_reg(priv, 0x1f);
1869
1870 reg18 &= 0xf0; /* set ring[3:0] */
1871 reg18 |= n_ring;
1872
1873 ring_vco = (16 + n_ring) * 8 * ring_ref;
1874
1875 reg18 &= 0xdf; /* clear ring_se23 */
1876 reg19 &= 0xfc; /* clear ring_seldiv */
1877 reg1f &= 0xfc; /* clear ring_att */
1878
1879 switch (imr_mem) {
1880 case 0:
1881 ring_freq = ring_vco / 48;
1882 reg18 |= 0x20; /* ring_se23 = 1 */
1883 reg19 |= 0x03; /* ring_seldiv = 3 */
1884 reg1f |= 0x02; /* ring_att 10 */
1885 break;
1886 case 1:
1887 ring_freq = ring_vco / 16;
1888 reg18 |= 0x00; /* ring_se23 = 0 */
1889 reg19 |= 0x02; /* ring_seldiv = 2 */
1890 reg1f |= 0x00; /* pw_ring 00 */
1891 break;
1892 case 2:
1893 ring_freq = ring_vco / 8;
1894 reg18 |= 0x00; /* ring_se23 = 0 */
1895 reg19 |= 0x01; /* ring_seldiv = 1 */
1896 reg1f |= 0x03; /* pw_ring 11 */
1897 break;
1898 case 3:
1899 ring_freq = ring_vco / 6;
1900 reg18 |= 0x20; /* ring_se23 = 1 */
1901 reg19 |= 0x00; /* ring_seldiv = 0 */
1902 reg1f |= 0x03; /* pw_ring 11 */
1903 break;
1904 case 4:
1905 ring_freq = ring_vco / 4;
1906 reg18 |= 0x00; /* ring_se23 = 0 */
1907 reg19 |= 0x00; /* ring_seldiv = 0 */
1908 reg1f |= 0x01; /* pw_ring 01 */
1909 break;
1910 default:
1911 ring_freq = ring_vco / 4;
1912 reg18 |= 0x00; /* ring_se23 = 0 */
1913 reg19 |= 0x00; /* ring_seldiv = 0 */
1914 reg1f |= 0x01; /* pw_ring 01 */
1915 break;
1916 }
1917
1918
1919 /* write pw_ring, n_ring, ringdiv2 registers */
1920
1921 /* n_ring, ring_se23 */
1922 rc = r820t_write_reg(priv, 0x18, reg18);
1923 if (rc < 0)
1924 return rc;
1925
1926 /* ring_sediv */
1927 rc = r820t_write_reg(priv, 0x19, reg19);
1928 if (rc < 0)
1929 return rc;
1930
1931 /* pw_ring */
1932 rc = r820t_write_reg(priv, 0x1f, reg1f);
1933 if (rc < 0)
1934 return rc;
1935
1936 /* mux input freq ~ rf_in freq */
1937 rc = r820t_set_mux(priv, (ring_freq - 5300) * 1000);
1938 if (rc < 0)
1939 return rc;
1940
1941 rc = r820t_set_pll(priv, V4L2_TUNER_DIGITAL_TV,
1942 (ring_freq - 5300) * 1000);
1943 if (!priv->has_lock)
1944 rc = -EINVAL;
1945 if (rc < 0)
1946 return rc;
1947
1948 if (im_flag) {
1949 rc = r820t_iq(priv, &imr_point);
1950 } else {
1951 imr_point.gain_x = priv->imr_data[3].gain_x;
1952 imr_point.phase_y = priv->imr_data[3].phase_y;
1953 imr_point.value = priv->imr_data[3].value;
1954
1955 rc = r820t_f_imr(priv, &imr_point);
1956 }
1957 if (rc < 0)
1958 return rc;
1959
1960 /* save IMR value */
1961 switch (imr_mem) {
1962 case 0:
1963 priv->imr_data[0].gain_x = imr_point.gain_x;
1964 priv->imr_data[0].phase_y = imr_point.phase_y;
1965 priv->imr_data[0].value = imr_point.value;
1966 break;
1967 case 1:
1968 priv->imr_data[1].gain_x = imr_point.gain_x;
1969 priv->imr_data[1].phase_y = imr_point.phase_y;
1970 priv->imr_data[1].value = imr_point.value;
1971 break;
1972 case 2:
1973 priv->imr_data[2].gain_x = imr_point.gain_x;
1974 priv->imr_data[2].phase_y = imr_point.phase_y;
1975 priv->imr_data[2].value = imr_point.value;
1976 break;
1977 case 3:
1978 priv->imr_data[3].gain_x = imr_point.gain_x;
1979 priv->imr_data[3].phase_y = imr_point.phase_y;
1980 priv->imr_data[3].value = imr_point.value;
1981 break;
1982 case 4:
1983 priv->imr_data[4].gain_x = imr_point.gain_x;
1984 priv->imr_data[4].phase_y = imr_point.phase_y;
1985 priv->imr_data[4].value = imr_point.value;
1986 break;
1987 default:
1988 priv->imr_data[4].gain_x = imr_point.gain_x;
1989 priv->imr_data[4].phase_y = imr_point.phase_y;
1990 priv->imr_data[4].value = imr_point.value;
1991 break;
1992 }
1993
1994 return 0;
1995}
1996
1997static int r820t_imr_callibrate(struct r820t_priv *priv)
1393{ 1998{
1394 struct r820t_priv *priv = fe->tuner_priv;
1395 int rc, i; 1999 int rc, i;
1396 int xtal_cap = 0; 2000 int xtal_cap = 0;
1397 2001
1398 tuner_dbg("%s:\n", __func__); 2002 if (priv->imr_done)
2003 return 0;
1399 2004
1400 mutex_lock(&priv->lock); 2005 /* Initialize registers */
1401 if (fe->ops.i2c_gate_ctrl) 2006 rc = r820t_write(priv, 0x05,
1402 fe->ops.i2c_gate_ctrl(fe, 1); 2007 r820t_init_array, sizeof(r820t_init_array));
2008 if (rc < 0)
2009 return rc;
1403 2010
2011 /* Detect Xtal capacitance */
1404 if ((priv->cfg->rafael_chip == CHIP_R820T) || 2012 if ((priv->cfg->rafael_chip == CHIP_R820T) ||
1405 (priv->cfg->rafael_chip == CHIP_R828S) || 2013 (priv->cfg->rafael_chip == CHIP_R828S) ||
1406 (priv->cfg->rafael_chip == CHIP_R820C)) { 2014 (priv->cfg->rafael_chip == CHIP_R820C)) {
@@ -1409,7 +2017,7 @@ static int r820t_init(struct dvb_frontend *fe)
1409 for (i = 0; i < 3; i++) { 2017 for (i = 0; i < 3; i++) {
1410 rc = r820t_xtal_check(priv); 2018 rc = r820t_xtal_check(priv);
1411 if (rc < 0) 2019 if (rc < 0)
1412 goto err; 2020 return rc;
1413 if (!i || rc > xtal_cap) 2021 if (!i || rc > xtal_cap)
1414 xtal_cap = rc; 2022 xtal_cap = rc;
1415 } 2023 }
@@ -1419,6 +2027,58 @@ static int r820t_init(struct dvb_frontend *fe)
1419 /* Initialize registers */ 2027 /* Initialize registers */
1420 rc = r820t_write(priv, 0x05, 2028 rc = r820t_write(priv, 0x05,
1421 r820t_init_array, sizeof(r820t_init_array)); 2029 r820t_init_array, sizeof(r820t_init_array));
2030 if (rc < 0)
2031 return rc;
2032
2033 rc = r820t_imr_prepare(priv);
2034 if (rc < 0)
2035 return rc;
2036
2037 rc = r820t_imr(priv, 3, true);
2038 if (rc < 0)
2039 return rc;
2040 rc = r820t_imr(priv, 1, false);
2041 if (rc < 0)
2042 return rc;
2043 rc = r820t_imr(priv, 0, false);
2044 if (rc < 0)
2045 return rc;
2046 rc = r820t_imr(priv, 2, false);
2047 if (rc < 0)
2048 return rc;
2049 rc = r820t_imr(priv, 4, false);
2050 if (rc < 0)
2051 return rc;
2052
2053 priv->imr_done = true;
2054
2055 return 0;
2056}
2057
2058/*
2059 * r820t frontend operations and tuner attach code
2060 *
2061 * All driver locks and i2c control are only in this part of the code
2062 */
2063
2064static int r820t_init(struct dvb_frontend *fe)
2065{
2066 struct r820t_priv *priv = fe->tuner_priv;
2067 int rc;
2068
2069 tuner_dbg("%s:\n", __func__);
2070
2071 mutex_lock(&priv->lock);
2072 if (fe->ops.i2c_gate_ctrl)
2073 fe->ops.i2c_gate_ctrl(fe, 1);
2074
2075 rc = r820t_imr_callibrate(priv);
2076 if (rc < 0)
2077 goto err;
2078
2079 /* Initialize registers */
2080 rc = r820t_write(priv, 0x05,
2081 r820t_init_array, sizeof(r820t_init_array));
1422 2082
1423err: 2083err:
1424 if (fe->ops.i2c_gate_ctrl) 2084 if (fe->ops.i2c_gate_ctrl)