174ba9207SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 29a0bf528SMauro Carvalho Chehab /* 39a0bf528SMauro Carvalho Chehab STV0900/0903 Multistandard Broadcast Frontend driver 49a0bf528SMauro Carvalho Chehab Copyright (C) Manu Abraham <abraham.manu@gmail.com> 59a0bf528SMauro Carvalho Chehab 69a0bf528SMauro Carvalho Chehab Copyright (C) ST Microelectronics 79a0bf528SMauro Carvalho Chehab 89a0bf528SMauro Carvalho Chehab */ 99a0bf528SMauro Carvalho Chehab 109a0bf528SMauro Carvalho Chehab #include <linux/init.h> 119a0bf528SMauro Carvalho Chehab #include <linux/kernel.h> 129a0bf528SMauro Carvalho Chehab #include <linux/module.h> 139a0bf528SMauro Carvalho Chehab #include <linux/string.h> 149a0bf528SMauro Carvalho Chehab #include <linux/slab.h> 159a0bf528SMauro Carvalho Chehab #include <linux/mutex.h> 169a0bf528SMauro Carvalho Chehab 179a0bf528SMauro Carvalho Chehab #include <linux/dvb/frontend.h> 18fada1935SMauro Carvalho Chehab #include <media/dvb_frontend.h> 199a0bf528SMauro Carvalho Chehab 209a0bf528SMauro Carvalho Chehab #include "stv6110x.h" /* for demodulator internal modes */ 219a0bf528SMauro Carvalho Chehab 229a0bf528SMauro Carvalho Chehab #include "stv090x_reg.h" 239a0bf528SMauro Carvalho Chehab #include "stv090x.h" 249a0bf528SMauro Carvalho Chehab #include "stv090x_priv.h" 259a0bf528SMauro Carvalho Chehab 26f7a35df1SMauro Carvalho Chehab /* Max transfer size done by I2C transfer functions */ 27f7a35df1SMauro Carvalho Chehab #define MAX_XFER_SIZE 64 28f7a35df1SMauro Carvalho Chehab 299a0bf528SMauro Carvalho Chehab static unsigned int verbose; 309a0bf528SMauro Carvalho Chehab module_param(verbose, int, 0644); 319a0bf528SMauro Carvalho Chehab 329a0bf528SMauro Carvalho Chehab /* internal params node */ 339a0bf528SMauro Carvalho Chehab struct stv090x_dev { 349a0bf528SMauro Carvalho Chehab /* pointer for internal params, one for each pair of demods */ 359a0bf528SMauro Carvalho Chehab struct stv090x_internal *internal; 369a0bf528SMauro Carvalho Chehab struct stv090x_dev *next_dev; 379a0bf528SMauro Carvalho Chehab }; 389a0bf528SMauro Carvalho Chehab 399a0bf528SMauro Carvalho Chehab /* first internal params */ 409a0bf528SMauro Carvalho Chehab static struct stv090x_dev *stv090x_first_dev; 419a0bf528SMauro Carvalho Chehab 429a0bf528SMauro Carvalho Chehab /* find chip by i2c adapter and i2c address */ 439a0bf528SMauro Carvalho Chehab static struct stv090x_dev *find_dev(struct i2c_adapter *i2c_adap, 449a0bf528SMauro Carvalho Chehab u8 i2c_addr) 459a0bf528SMauro Carvalho Chehab { 469a0bf528SMauro Carvalho Chehab struct stv090x_dev *temp_dev = stv090x_first_dev; 479a0bf528SMauro Carvalho Chehab 489a0bf528SMauro Carvalho Chehab /* 499a0bf528SMauro Carvalho Chehab Search of the last stv0900 chip or 509a0bf528SMauro Carvalho Chehab find it by i2c adapter and i2c address */ 519a0bf528SMauro Carvalho Chehab while ((temp_dev != NULL) && 529a0bf528SMauro Carvalho Chehab ((temp_dev->internal->i2c_adap != i2c_adap) || 539a0bf528SMauro Carvalho Chehab (temp_dev->internal->i2c_addr != i2c_addr))) { 549a0bf528SMauro Carvalho Chehab 559a0bf528SMauro Carvalho Chehab temp_dev = temp_dev->next_dev; 569a0bf528SMauro Carvalho Chehab } 579a0bf528SMauro Carvalho Chehab 589a0bf528SMauro Carvalho Chehab return temp_dev; 599a0bf528SMauro Carvalho Chehab } 609a0bf528SMauro Carvalho Chehab 619a0bf528SMauro Carvalho Chehab /* deallocating chip */ 629a0bf528SMauro Carvalho Chehab static void remove_dev(struct stv090x_internal *internal) 639a0bf528SMauro Carvalho Chehab { 649a0bf528SMauro Carvalho Chehab struct stv090x_dev *prev_dev = stv090x_first_dev; 659a0bf528SMauro Carvalho Chehab struct stv090x_dev *del_dev = find_dev(internal->i2c_adap, 669a0bf528SMauro Carvalho Chehab internal->i2c_addr); 679a0bf528SMauro Carvalho Chehab 689a0bf528SMauro Carvalho Chehab if (del_dev != NULL) { 699a0bf528SMauro Carvalho Chehab if (del_dev == stv090x_first_dev) { 709a0bf528SMauro Carvalho Chehab stv090x_first_dev = del_dev->next_dev; 719a0bf528SMauro Carvalho Chehab } else { 729a0bf528SMauro Carvalho Chehab while (prev_dev->next_dev != del_dev) 739a0bf528SMauro Carvalho Chehab prev_dev = prev_dev->next_dev; 749a0bf528SMauro Carvalho Chehab 759a0bf528SMauro Carvalho Chehab prev_dev->next_dev = del_dev->next_dev; 769a0bf528SMauro Carvalho Chehab } 779a0bf528SMauro Carvalho Chehab 789a0bf528SMauro Carvalho Chehab kfree(del_dev); 799a0bf528SMauro Carvalho Chehab } 809a0bf528SMauro Carvalho Chehab } 819a0bf528SMauro Carvalho Chehab 829a0bf528SMauro Carvalho Chehab /* allocating new chip */ 839a0bf528SMauro Carvalho Chehab static struct stv090x_dev *append_internal(struct stv090x_internal *internal) 849a0bf528SMauro Carvalho Chehab { 859a0bf528SMauro Carvalho Chehab struct stv090x_dev *new_dev; 869a0bf528SMauro Carvalho Chehab struct stv090x_dev *temp_dev; 879a0bf528SMauro Carvalho Chehab 889a0bf528SMauro Carvalho Chehab new_dev = kmalloc(sizeof(struct stv090x_dev), GFP_KERNEL); 899a0bf528SMauro Carvalho Chehab if (new_dev != NULL) { 909a0bf528SMauro Carvalho Chehab new_dev->internal = internal; 919a0bf528SMauro Carvalho Chehab new_dev->next_dev = NULL; 929a0bf528SMauro Carvalho Chehab 939a0bf528SMauro Carvalho Chehab /* append to list */ 949a0bf528SMauro Carvalho Chehab if (stv090x_first_dev == NULL) { 959a0bf528SMauro Carvalho Chehab stv090x_first_dev = new_dev; 969a0bf528SMauro Carvalho Chehab } else { 979a0bf528SMauro Carvalho Chehab temp_dev = stv090x_first_dev; 989a0bf528SMauro Carvalho Chehab while (temp_dev->next_dev != NULL) 999a0bf528SMauro Carvalho Chehab temp_dev = temp_dev->next_dev; 1009a0bf528SMauro Carvalho Chehab 1019a0bf528SMauro Carvalho Chehab temp_dev->next_dev = new_dev; 1029a0bf528SMauro Carvalho Chehab } 1039a0bf528SMauro Carvalho Chehab } 1049a0bf528SMauro Carvalho Chehab 1059a0bf528SMauro Carvalho Chehab return new_dev; 1069a0bf528SMauro Carvalho Chehab } 1079a0bf528SMauro Carvalho Chehab 1089a0bf528SMauro Carvalho Chehab 1099a0bf528SMauro Carvalho Chehab /* DVBS1 and DSS C/N Lookup table */ 1109a0bf528SMauro Carvalho Chehab static const struct stv090x_tab stv090x_s1cn_tab[] = { 1119a0bf528SMauro Carvalho Chehab { 0, 8917 }, /* 0.0dB */ 1129a0bf528SMauro Carvalho Chehab { 5, 8801 }, /* 0.5dB */ 1139a0bf528SMauro Carvalho Chehab { 10, 8667 }, /* 1.0dB */ 1149a0bf528SMauro Carvalho Chehab { 15, 8522 }, /* 1.5dB */ 1159a0bf528SMauro Carvalho Chehab { 20, 8355 }, /* 2.0dB */ 1169a0bf528SMauro Carvalho Chehab { 25, 8175 }, /* 2.5dB */ 1179a0bf528SMauro Carvalho Chehab { 30, 7979 }, /* 3.0dB */ 1189a0bf528SMauro Carvalho Chehab { 35, 7763 }, /* 3.5dB */ 1199a0bf528SMauro Carvalho Chehab { 40, 7530 }, /* 4.0dB */ 1209a0bf528SMauro Carvalho Chehab { 45, 7282 }, /* 4.5dB */ 1219a0bf528SMauro Carvalho Chehab { 50, 7026 }, /* 5.0dB */ 1229a0bf528SMauro Carvalho Chehab { 55, 6781 }, /* 5.5dB */ 1239a0bf528SMauro Carvalho Chehab { 60, 6514 }, /* 6.0dB */ 1249a0bf528SMauro Carvalho Chehab { 65, 6241 }, /* 6.5dB */ 1259a0bf528SMauro Carvalho Chehab { 70, 5965 }, /* 7.0dB */ 1269a0bf528SMauro Carvalho Chehab { 75, 5690 }, /* 7.5dB */ 1279a0bf528SMauro Carvalho Chehab { 80, 5424 }, /* 8.0dB */ 1289a0bf528SMauro Carvalho Chehab { 85, 5161 }, /* 8.5dB */ 1299a0bf528SMauro Carvalho Chehab { 90, 4902 }, /* 9.0dB */ 1309a0bf528SMauro Carvalho Chehab { 95, 4654 }, /* 9.5dB */ 1319a0bf528SMauro Carvalho Chehab { 100, 4417 }, /* 10.0dB */ 1329a0bf528SMauro Carvalho Chehab { 105, 4186 }, /* 10.5dB */ 1339a0bf528SMauro Carvalho Chehab { 110, 3968 }, /* 11.0dB */ 1349a0bf528SMauro Carvalho Chehab { 115, 3757 }, /* 11.5dB */ 1359a0bf528SMauro Carvalho Chehab { 120, 3558 }, /* 12.0dB */ 1369a0bf528SMauro Carvalho Chehab { 125, 3366 }, /* 12.5dB */ 1379a0bf528SMauro Carvalho Chehab { 130, 3185 }, /* 13.0dB */ 1389a0bf528SMauro Carvalho Chehab { 135, 3012 }, /* 13.5dB */ 1399a0bf528SMauro Carvalho Chehab { 140, 2850 }, /* 14.0dB */ 1409a0bf528SMauro Carvalho Chehab { 145, 2698 }, /* 14.5dB */ 1419a0bf528SMauro Carvalho Chehab { 150, 2550 }, /* 15.0dB */ 1429a0bf528SMauro Carvalho Chehab { 160, 2283 }, /* 16.0dB */ 1439a0bf528SMauro Carvalho Chehab { 170, 2042 }, /* 17.0dB */ 1449a0bf528SMauro Carvalho Chehab { 180, 1827 }, /* 18.0dB */ 1459a0bf528SMauro Carvalho Chehab { 190, 1636 }, /* 19.0dB */ 1469a0bf528SMauro Carvalho Chehab { 200, 1466 }, /* 20.0dB */ 1479a0bf528SMauro Carvalho Chehab { 210, 1315 }, /* 21.0dB */ 1489a0bf528SMauro Carvalho Chehab { 220, 1181 }, /* 22.0dB */ 1499a0bf528SMauro Carvalho Chehab { 230, 1064 }, /* 23.0dB */ 1509a0bf528SMauro Carvalho Chehab { 240, 960 }, /* 24.0dB */ 1519a0bf528SMauro Carvalho Chehab { 250, 869 }, /* 25.0dB */ 1529a0bf528SMauro Carvalho Chehab { 260, 792 }, /* 26.0dB */ 1539a0bf528SMauro Carvalho Chehab { 270, 724 }, /* 27.0dB */ 1549a0bf528SMauro Carvalho Chehab { 280, 665 }, /* 28.0dB */ 1559a0bf528SMauro Carvalho Chehab { 290, 616 }, /* 29.0dB */ 1569a0bf528SMauro Carvalho Chehab { 300, 573 }, /* 30.0dB */ 1579a0bf528SMauro Carvalho Chehab { 310, 537 }, /* 31.0dB */ 1589a0bf528SMauro Carvalho Chehab { 320, 507 }, /* 32.0dB */ 1599a0bf528SMauro Carvalho Chehab { 330, 483 }, /* 33.0dB */ 1609a0bf528SMauro Carvalho Chehab { 400, 398 }, /* 40.0dB */ 1619a0bf528SMauro Carvalho Chehab { 450, 381 }, /* 45.0dB */ 1629a0bf528SMauro Carvalho Chehab { 500, 377 } /* 50.0dB */ 1639a0bf528SMauro Carvalho Chehab }; 1649a0bf528SMauro Carvalho Chehab 1659a0bf528SMauro Carvalho Chehab /* DVBS2 C/N Lookup table */ 1669a0bf528SMauro Carvalho Chehab static const struct stv090x_tab stv090x_s2cn_tab[] = { 1679a0bf528SMauro Carvalho Chehab { -30, 13348 }, /* -3.0dB */ 1689a0bf528SMauro Carvalho Chehab { -20, 12640 }, /* -2d.0B */ 1699a0bf528SMauro Carvalho Chehab { -10, 11883 }, /* -1.0dB */ 1709a0bf528SMauro Carvalho Chehab { 0, 11101 }, /* -0.0dB */ 1719a0bf528SMauro Carvalho Chehab { 5, 10718 }, /* 0.5dB */ 1729a0bf528SMauro Carvalho Chehab { 10, 10339 }, /* 1.0dB */ 1739a0bf528SMauro Carvalho Chehab { 15, 9947 }, /* 1.5dB */ 1749a0bf528SMauro Carvalho Chehab { 20, 9552 }, /* 2.0dB */ 1759a0bf528SMauro Carvalho Chehab { 25, 9183 }, /* 2.5dB */ 1769a0bf528SMauro Carvalho Chehab { 30, 8799 }, /* 3.0dB */ 1779a0bf528SMauro Carvalho Chehab { 35, 8422 }, /* 3.5dB */ 1789a0bf528SMauro Carvalho Chehab { 40, 8062 }, /* 4.0dB */ 1799a0bf528SMauro Carvalho Chehab { 45, 7707 }, /* 4.5dB */ 1809a0bf528SMauro Carvalho Chehab { 50, 7353 }, /* 5.0dB */ 1819a0bf528SMauro Carvalho Chehab { 55, 7025 }, /* 5.5dB */ 1829a0bf528SMauro Carvalho Chehab { 60, 6684 }, /* 6.0dB */ 1839a0bf528SMauro Carvalho Chehab { 65, 6331 }, /* 6.5dB */ 1849a0bf528SMauro Carvalho Chehab { 70, 6036 }, /* 7.0dB */ 1859a0bf528SMauro Carvalho Chehab { 75, 5727 }, /* 7.5dB */ 1869a0bf528SMauro Carvalho Chehab { 80, 5437 }, /* 8.0dB */ 1879a0bf528SMauro Carvalho Chehab { 85, 5164 }, /* 8.5dB */ 1889a0bf528SMauro Carvalho Chehab { 90, 4902 }, /* 9.0dB */ 1899a0bf528SMauro Carvalho Chehab { 95, 4653 }, /* 9.5dB */ 1909a0bf528SMauro Carvalho Chehab { 100, 4408 }, /* 10.0dB */ 1919a0bf528SMauro Carvalho Chehab { 105, 4187 }, /* 10.5dB */ 1929a0bf528SMauro Carvalho Chehab { 110, 3961 }, /* 11.0dB */ 1939a0bf528SMauro Carvalho Chehab { 115, 3751 }, /* 11.5dB */ 1949a0bf528SMauro Carvalho Chehab { 120, 3558 }, /* 12.0dB */ 1959a0bf528SMauro Carvalho Chehab { 125, 3368 }, /* 12.5dB */ 1969a0bf528SMauro Carvalho Chehab { 130, 3191 }, /* 13.0dB */ 1979a0bf528SMauro Carvalho Chehab { 135, 3017 }, /* 13.5dB */ 1989a0bf528SMauro Carvalho Chehab { 140, 2862 }, /* 14.0dB */ 1999a0bf528SMauro Carvalho Chehab { 145, 2710 }, /* 14.5dB */ 2009a0bf528SMauro Carvalho Chehab { 150, 2565 }, /* 15.0dB */ 2019a0bf528SMauro Carvalho Chehab { 160, 2300 }, /* 16.0dB */ 2029a0bf528SMauro Carvalho Chehab { 170, 2058 }, /* 17.0dB */ 2039a0bf528SMauro Carvalho Chehab { 180, 1849 }, /* 18.0dB */ 2049a0bf528SMauro Carvalho Chehab { 190, 1663 }, /* 19.0dB */ 2059a0bf528SMauro Carvalho Chehab { 200, 1495 }, /* 20.0dB */ 2069a0bf528SMauro Carvalho Chehab { 210, 1349 }, /* 21.0dB */ 2079a0bf528SMauro Carvalho Chehab { 220, 1222 }, /* 22.0dB */ 2089a0bf528SMauro Carvalho Chehab { 230, 1110 }, /* 23.0dB */ 2099a0bf528SMauro Carvalho Chehab { 240, 1011 }, /* 24.0dB */ 2109a0bf528SMauro Carvalho Chehab { 250, 925 }, /* 25.0dB */ 2119a0bf528SMauro Carvalho Chehab { 260, 853 }, /* 26.0dB */ 2129a0bf528SMauro Carvalho Chehab { 270, 789 }, /* 27.0dB */ 2139a0bf528SMauro Carvalho Chehab { 280, 734 }, /* 28.0dB */ 2149a0bf528SMauro Carvalho Chehab { 290, 690 }, /* 29.0dB */ 2159a0bf528SMauro Carvalho Chehab { 300, 650 }, /* 30.0dB */ 2169a0bf528SMauro Carvalho Chehab { 310, 619 }, /* 31.0dB */ 2179a0bf528SMauro Carvalho Chehab { 320, 593 }, /* 32.0dB */ 2189a0bf528SMauro Carvalho Chehab { 330, 571 }, /* 33.0dB */ 2199a0bf528SMauro Carvalho Chehab { 400, 498 }, /* 40.0dB */ 2209a0bf528SMauro Carvalho Chehab { 450, 484 }, /* 45.0dB */ 2219a0bf528SMauro Carvalho Chehab { 500, 481 } /* 50.0dB */ 2229a0bf528SMauro Carvalho Chehab }; 2239a0bf528SMauro Carvalho Chehab 2249a0bf528SMauro Carvalho Chehab /* RF level C/N lookup table */ 2259a0bf528SMauro Carvalho Chehab static const struct stv090x_tab stv090x_rf_tab[] = { 2269a0bf528SMauro Carvalho Chehab { -5, 0xcaa1 }, /* -5dBm */ 2279a0bf528SMauro Carvalho Chehab { -10, 0xc229 }, /* -10dBm */ 2289a0bf528SMauro Carvalho Chehab { -15, 0xbb08 }, /* -15dBm */ 2299a0bf528SMauro Carvalho Chehab { -20, 0xb4bc }, /* -20dBm */ 2309a0bf528SMauro Carvalho Chehab { -25, 0xad5a }, /* -25dBm */ 2319a0bf528SMauro Carvalho Chehab { -30, 0xa298 }, /* -30dBm */ 2329a0bf528SMauro Carvalho Chehab { -35, 0x98a8 }, /* -35dBm */ 2339a0bf528SMauro Carvalho Chehab { -40, 0x8389 }, /* -40dBm */ 2349a0bf528SMauro Carvalho Chehab { -45, 0x59be }, /* -45dBm */ 2359a0bf528SMauro Carvalho Chehab { -50, 0x3a14 }, /* -50dBm */ 2369a0bf528SMauro Carvalho Chehab { -55, 0x2d11 }, /* -55dBm */ 2379a0bf528SMauro Carvalho Chehab { -60, 0x210d }, /* -60dBm */ 2389a0bf528SMauro Carvalho Chehab { -65, 0xa14f }, /* -65dBm */ 2399a0bf528SMauro Carvalho Chehab { -70, 0x07aa } /* -70dBm */ 2409a0bf528SMauro Carvalho Chehab }; 2419a0bf528SMauro Carvalho Chehab 2429a0bf528SMauro Carvalho Chehab 2439a0bf528SMauro Carvalho Chehab static struct stv090x_reg stv0900_initval[] = { 2449a0bf528SMauro Carvalho Chehab 2459a0bf528SMauro Carvalho Chehab { STV090x_OUTCFG, 0x00 }, 2469a0bf528SMauro Carvalho Chehab { STV090x_MODECFG, 0xff }, 2479a0bf528SMauro Carvalho Chehab { STV090x_AGCRF1CFG, 0x11 }, 2489a0bf528SMauro Carvalho Chehab { STV090x_AGCRF2CFG, 0x13 }, 2499a0bf528SMauro Carvalho Chehab { STV090x_TSGENERAL1X, 0x14 }, 2509a0bf528SMauro Carvalho Chehab { STV090x_TSTTNR2, 0x21 }, 2519a0bf528SMauro Carvalho Chehab { STV090x_TSTTNR4, 0x21 }, 2529a0bf528SMauro Carvalho Chehab { STV090x_P2_DISTXCTL, 0x22 }, 2539a0bf528SMauro Carvalho Chehab { STV090x_P2_F22TX, 0xc0 }, 2549a0bf528SMauro Carvalho Chehab { STV090x_P2_F22RX, 0xc0 }, 2559a0bf528SMauro Carvalho Chehab { STV090x_P2_DISRXCTL, 0x00 }, 2569a0bf528SMauro Carvalho Chehab { STV090x_P2_DMDCFGMD, 0xF9 }, 2579a0bf528SMauro Carvalho Chehab { STV090x_P2_DEMOD, 0x08 }, 2589a0bf528SMauro Carvalho Chehab { STV090x_P2_DMDCFG3, 0xc4 }, 2599a0bf528SMauro Carvalho Chehab { STV090x_P2_CARFREQ, 0xed }, 2609a0bf528SMauro Carvalho Chehab { STV090x_P2_LDT, 0xd0 }, 2619a0bf528SMauro Carvalho Chehab { STV090x_P2_LDT2, 0xb8 }, 2629a0bf528SMauro Carvalho Chehab { STV090x_P2_TMGCFG, 0xd2 }, 2639a0bf528SMauro Carvalho Chehab { STV090x_P2_TMGTHRISE, 0x20 }, 2649a0bf528SMauro Carvalho Chehab { STV090x_P1_TMGCFG, 0xd2 }, 2659a0bf528SMauro Carvalho Chehab 2669a0bf528SMauro Carvalho Chehab { STV090x_P2_TMGTHFALL, 0x00 }, 2679a0bf528SMauro Carvalho Chehab { STV090x_P2_FECSPY, 0x88 }, 2689a0bf528SMauro Carvalho Chehab { STV090x_P2_FSPYDATA, 0x3a }, 2699a0bf528SMauro Carvalho Chehab { STV090x_P2_FBERCPT4, 0x00 }, 2709a0bf528SMauro Carvalho Chehab { STV090x_P2_FSPYBER, 0x10 }, 2719a0bf528SMauro Carvalho Chehab { STV090x_P2_ERRCTRL1, 0x35 }, 2729a0bf528SMauro Carvalho Chehab { STV090x_P2_ERRCTRL2, 0xc1 }, 2739a0bf528SMauro Carvalho Chehab { STV090x_P2_CFRICFG, 0xf8 }, 2749a0bf528SMauro Carvalho Chehab { STV090x_P2_NOSCFG, 0x1c }, 2759a0bf528SMauro Carvalho Chehab { STV090x_P2_DMDTOM, 0x20 }, 2769a0bf528SMauro Carvalho Chehab { STV090x_P2_CORRELMANT, 0x70 }, 2779a0bf528SMauro Carvalho Chehab { STV090x_P2_CORRELABS, 0x88 }, 2789a0bf528SMauro Carvalho Chehab { STV090x_P2_AGC2O, 0x5b }, 2799a0bf528SMauro Carvalho Chehab { STV090x_P2_AGC2REF, 0x38 }, 2809a0bf528SMauro Carvalho Chehab { STV090x_P2_CARCFG, 0xe4 }, 2819a0bf528SMauro Carvalho Chehab { STV090x_P2_ACLC, 0x1A }, 2829a0bf528SMauro Carvalho Chehab { STV090x_P2_BCLC, 0x09 }, 2839a0bf528SMauro Carvalho Chehab { STV090x_P2_CARHDR, 0x08 }, 2849a0bf528SMauro Carvalho Chehab { STV090x_P2_KREFTMG, 0xc1 }, 2859a0bf528SMauro Carvalho Chehab { STV090x_P2_SFRUPRATIO, 0xf0 }, 2869a0bf528SMauro Carvalho Chehab { STV090x_P2_SFRLOWRATIO, 0x70 }, 2879a0bf528SMauro Carvalho Chehab { STV090x_P2_SFRSTEP, 0x58 }, 2889a0bf528SMauro Carvalho Chehab { STV090x_P2_TMGCFG2, 0x01 }, 2899a0bf528SMauro Carvalho Chehab { STV090x_P2_CAR2CFG, 0x26 }, 2909a0bf528SMauro Carvalho Chehab { STV090x_P2_BCLC2S2Q, 0x86 }, 2919a0bf528SMauro Carvalho Chehab { STV090x_P2_BCLC2S28, 0x86 }, 2929a0bf528SMauro Carvalho Chehab { STV090x_P2_SMAPCOEF7, 0x77 }, 2939a0bf528SMauro Carvalho Chehab { STV090x_P2_SMAPCOEF6, 0x85 }, 2949a0bf528SMauro Carvalho Chehab { STV090x_P2_SMAPCOEF5, 0x77 }, 2959a0bf528SMauro Carvalho Chehab { STV090x_P2_TSCFGL, 0x20 }, 2969a0bf528SMauro Carvalho Chehab { STV090x_P2_DMDCFG2, 0x3b }, 2979a0bf528SMauro Carvalho Chehab { STV090x_P2_MODCODLST0, 0xff }, 2989a0bf528SMauro Carvalho Chehab { STV090x_P2_MODCODLST1, 0xff }, 2999a0bf528SMauro Carvalho Chehab { STV090x_P2_MODCODLST2, 0xff }, 3009a0bf528SMauro Carvalho Chehab { STV090x_P2_MODCODLST3, 0xff }, 3019a0bf528SMauro Carvalho Chehab { STV090x_P2_MODCODLST4, 0xff }, 3029a0bf528SMauro Carvalho Chehab { STV090x_P2_MODCODLST5, 0xff }, 3039a0bf528SMauro Carvalho Chehab { STV090x_P2_MODCODLST6, 0xff }, 3049a0bf528SMauro Carvalho Chehab { STV090x_P2_MODCODLST7, 0xcc }, 3059a0bf528SMauro Carvalho Chehab { STV090x_P2_MODCODLST8, 0xcc }, 3069a0bf528SMauro Carvalho Chehab { STV090x_P2_MODCODLST9, 0xcc }, 3079a0bf528SMauro Carvalho Chehab { STV090x_P2_MODCODLSTA, 0xcc }, 3089a0bf528SMauro Carvalho Chehab { STV090x_P2_MODCODLSTB, 0xcc }, 3099a0bf528SMauro Carvalho Chehab { STV090x_P2_MODCODLSTC, 0xcc }, 3109a0bf528SMauro Carvalho Chehab { STV090x_P2_MODCODLSTD, 0xcc }, 3119a0bf528SMauro Carvalho Chehab { STV090x_P2_MODCODLSTE, 0xcc }, 3129a0bf528SMauro Carvalho Chehab { STV090x_P2_MODCODLSTF, 0xcf }, 3139a0bf528SMauro Carvalho Chehab { STV090x_P1_DISTXCTL, 0x22 }, 3149a0bf528SMauro Carvalho Chehab { STV090x_P1_F22TX, 0xc0 }, 3159a0bf528SMauro Carvalho Chehab { STV090x_P1_F22RX, 0xc0 }, 3169a0bf528SMauro Carvalho Chehab { STV090x_P1_DISRXCTL, 0x00 }, 3179a0bf528SMauro Carvalho Chehab { STV090x_P1_DMDCFGMD, 0xf9 }, 3189a0bf528SMauro Carvalho Chehab { STV090x_P1_DEMOD, 0x08 }, 3199a0bf528SMauro Carvalho Chehab { STV090x_P1_DMDCFG3, 0xc4 }, 3209a0bf528SMauro Carvalho Chehab { STV090x_P1_DMDTOM, 0x20 }, 3219a0bf528SMauro Carvalho Chehab { STV090x_P1_CARFREQ, 0xed }, 3229a0bf528SMauro Carvalho Chehab { STV090x_P1_LDT, 0xd0 }, 3239a0bf528SMauro Carvalho Chehab { STV090x_P1_LDT2, 0xb8 }, 3249a0bf528SMauro Carvalho Chehab { STV090x_P1_TMGCFG, 0xd2 }, 3259a0bf528SMauro Carvalho Chehab { STV090x_P1_TMGTHRISE, 0x20 }, 3269a0bf528SMauro Carvalho Chehab { STV090x_P1_TMGTHFALL, 0x00 }, 3279a0bf528SMauro Carvalho Chehab { STV090x_P1_SFRUPRATIO, 0xf0 }, 3289a0bf528SMauro Carvalho Chehab { STV090x_P1_SFRLOWRATIO, 0x70 }, 3299a0bf528SMauro Carvalho Chehab { STV090x_P1_TSCFGL, 0x20 }, 3309a0bf528SMauro Carvalho Chehab { STV090x_P1_FECSPY, 0x88 }, 3319a0bf528SMauro Carvalho Chehab { STV090x_P1_FSPYDATA, 0x3a }, 3329a0bf528SMauro Carvalho Chehab { STV090x_P1_FBERCPT4, 0x00 }, 3339a0bf528SMauro Carvalho Chehab { STV090x_P1_FSPYBER, 0x10 }, 3349a0bf528SMauro Carvalho Chehab { STV090x_P1_ERRCTRL1, 0x35 }, 3359a0bf528SMauro Carvalho Chehab { STV090x_P1_ERRCTRL2, 0xc1 }, 3369a0bf528SMauro Carvalho Chehab { STV090x_P1_CFRICFG, 0xf8 }, 3379a0bf528SMauro Carvalho Chehab { STV090x_P1_NOSCFG, 0x1c }, 3389a0bf528SMauro Carvalho Chehab { STV090x_P1_CORRELMANT, 0x70 }, 3399a0bf528SMauro Carvalho Chehab { STV090x_P1_CORRELABS, 0x88 }, 3409a0bf528SMauro Carvalho Chehab { STV090x_P1_AGC2O, 0x5b }, 3419a0bf528SMauro Carvalho Chehab { STV090x_P1_AGC2REF, 0x38 }, 3429a0bf528SMauro Carvalho Chehab { STV090x_P1_CARCFG, 0xe4 }, 3439a0bf528SMauro Carvalho Chehab { STV090x_P1_ACLC, 0x1A }, 3449a0bf528SMauro Carvalho Chehab { STV090x_P1_BCLC, 0x09 }, 3459a0bf528SMauro Carvalho Chehab { STV090x_P1_CARHDR, 0x08 }, 3469a0bf528SMauro Carvalho Chehab { STV090x_P1_KREFTMG, 0xc1 }, 3479a0bf528SMauro Carvalho Chehab { STV090x_P1_SFRSTEP, 0x58 }, 3489a0bf528SMauro Carvalho Chehab { STV090x_P1_TMGCFG2, 0x01 }, 3499a0bf528SMauro Carvalho Chehab { STV090x_P1_CAR2CFG, 0x26 }, 3509a0bf528SMauro Carvalho Chehab { STV090x_P1_BCLC2S2Q, 0x86 }, 3519a0bf528SMauro Carvalho Chehab { STV090x_P1_BCLC2S28, 0x86 }, 3529a0bf528SMauro Carvalho Chehab { STV090x_P1_SMAPCOEF7, 0x77 }, 3539a0bf528SMauro Carvalho Chehab { STV090x_P1_SMAPCOEF6, 0x85 }, 3549a0bf528SMauro Carvalho Chehab { STV090x_P1_SMAPCOEF5, 0x77 }, 3559a0bf528SMauro Carvalho Chehab { STV090x_P1_DMDCFG2, 0x3b }, 3569a0bf528SMauro Carvalho Chehab { STV090x_P1_MODCODLST0, 0xff }, 3579a0bf528SMauro Carvalho Chehab { STV090x_P1_MODCODLST1, 0xff }, 3589a0bf528SMauro Carvalho Chehab { STV090x_P1_MODCODLST2, 0xff }, 3599a0bf528SMauro Carvalho Chehab { STV090x_P1_MODCODLST3, 0xff }, 3609a0bf528SMauro Carvalho Chehab { STV090x_P1_MODCODLST4, 0xff }, 3619a0bf528SMauro Carvalho Chehab { STV090x_P1_MODCODLST5, 0xff }, 3629a0bf528SMauro Carvalho Chehab { STV090x_P1_MODCODLST6, 0xff }, 3639a0bf528SMauro Carvalho Chehab { STV090x_P1_MODCODLST7, 0xcc }, 3649a0bf528SMauro Carvalho Chehab { STV090x_P1_MODCODLST8, 0xcc }, 3659a0bf528SMauro Carvalho Chehab { STV090x_P1_MODCODLST9, 0xcc }, 3669a0bf528SMauro Carvalho Chehab { STV090x_P1_MODCODLSTA, 0xcc }, 3679a0bf528SMauro Carvalho Chehab { STV090x_P1_MODCODLSTB, 0xcc }, 3689a0bf528SMauro Carvalho Chehab { STV090x_P1_MODCODLSTC, 0xcc }, 3699a0bf528SMauro Carvalho Chehab { STV090x_P1_MODCODLSTD, 0xcc }, 3709a0bf528SMauro Carvalho Chehab { STV090x_P1_MODCODLSTE, 0xcc }, 3719a0bf528SMauro Carvalho Chehab { STV090x_P1_MODCODLSTF, 0xcf }, 3729a0bf528SMauro Carvalho Chehab { STV090x_GENCFG, 0x1d }, 3739a0bf528SMauro Carvalho Chehab { STV090x_NBITER_NF4, 0x37 }, 3749a0bf528SMauro Carvalho Chehab { STV090x_NBITER_NF5, 0x29 }, 3759a0bf528SMauro Carvalho Chehab { STV090x_NBITER_NF6, 0x37 }, 3769a0bf528SMauro Carvalho Chehab { STV090x_NBITER_NF7, 0x33 }, 3779a0bf528SMauro Carvalho Chehab { STV090x_NBITER_NF8, 0x31 }, 3789a0bf528SMauro Carvalho Chehab { STV090x_NBITER_NF9, 0x2f }, 3799a0bf528SMauro Carvalho Chehab { STV090x_NBITER_NF10, 0x39 }, 3809a0bf528SMauro Carvalho Chehab { STV090x_NBITER_NF11, 0x3a }, 3819a0bf528SMauro Carvalho Chehab { STV090x_NBITER_NF12, 0x29 }, 3829a0bf528SMauro Carvalho Chehab { STV090x_NBITER_NF13, 0x37 }, 3839a0bf528SMauro Carvalho Chehab { STV090x_NBITER_NF14, 0x33 }, 3849a0bf528SMauro Carvalho Chehab { STV090x_NBITER_NF15, 0x2f }, 3859a0bf528SMauro Carvalho Chehab { STV090x_NBITER_NF16, 0x39 }, 3869a0bf528SMauro Carvalho Chehab { STV090x_NBITER_NF17, 0x3a }, 3879a0bf528SMauro Carvalho Chehab { STV090x_NBITERNOERR, 0x04 }, 3889a0bf528SMauro Carvalho Chehab { STV090x_GAINLLR_NF4, 0x0C }, 3899a0bf528SMauro Carvalho Chehab { STV090x_GAINLLR_NF5, 0x0F }, 3909a0bf528SMauro Carvalho Chehab { STV090x_GAINLLR_NF6, 0x11 }, 3919a0bf528SMauro Carvalho Chehab { STV090x_GAINLLR_NF7, 0x14 }, 3929a0bf528SMauro Carvalho Chehab { STV090x_GAINLLR_NF8, 0x17 }, 3939a0bf528SMauro Carvalho Chehab { STV090x_GAINLLR_NF9, 0x19 }, 3949a0bf528SMauro Carvalho Chehab { STV090x_GAINLLR_NF10, 0x20 }, 3959a0bf528SMauro Carvalho Chehab { STV090x_GAINLLR_NF11, 0x21 }, 3969a0bf528SMauro Carvalho Chehab { STV090x_GAINLLR_NF12, 0x0D }, 3979a0bf528SMauro Carvalho Chehab { STV090x_GAINLLR_NF13, 0x0F }, 3989a0bf528SMauro Carvalho Chehab { STV090x_GAINLLR_NF14, 0x13 }, 3999a0bf528SMauro Carvalho Chehab { STV090x_GAINLLR_NF15, 0x1A }, 4009a0bf528SMauro Carvalho Chehab { STV090x_GAINLLR_NF16, 0x1F }, 4019a0bf528SMauro Carvalho Chehab { STV090x_GAINLLR_NF17, 0x21 }, 4029a0bf528SMauro Carvalho Chehab { STV090x_RCCFGH, 0x20 }, 4039a0bf528SMauro Carvalho Chehab { STV090x_P1_FECM, 0x01 }, /* disable DSS modes */ 4049a0bf528SMauro Carvalho Chehab { STV090x_P2_FECM, 0x01 }, /* disable DSS modes */ 4059a0bf528SMauro Carvalho Chehab { STV090x_P1_PRVIT, 0x2F }, /* disable PR 6/7 */ 4069a0bf528SMauro Carvalho Chehab { STV090x_P2_PRVIT, 0x2F }, /* disable PR 6/7 */ 4079a0bf528SMauro Carvalho Chehab }; 4089a0bf528SMauro Carvalho Chehab 4099a0bf528SMauro Carvalho Chehab static struct stv090x_reg stv0903_initval[] = { 4109a0bf528SMauro Carvalho Chehab { STV090x_OUTCFG, 0x00 }, 4119a0bf528SMauro Carvalho Chehab { STV090x_AGCRF1CFG, 0x11 }, 4129a0bf528SMauro Carvalho Chehab { STV090x_STOPCLK1, 0x48 }, 4139a0bf528SMauro Carvalho Chehab { STV090x_STOPCLK2, 0x14 }, 4149a0bf528SMauro Carvalho Chehab { STV090x_TSTTNR1, 0x27 }, 4159a0bf528SMauro Carvalho Chehab { STV090x_TSTTNR2, 0x21 }, 4169a0bf528SMauro Carvalho Chehab { STV090x_P1_DISTXCTL, 0x22 }, 4179a0bf528SMauro Carvalho Chehab { STV090x_P1_F22TX, 0xc0 }, 4189a0bf528SMauro Carvalho Chehab { STV090x_P1_F22RX, 0xc0 }, 4199a0bf528SMauro Carvalho Chehab { STV090x_P1_DISRXCTL, 0x00 }, 4209a0bf528SMauro Carvalho Chehab { STV090x_P1_DMDCFGMD, 0xF9 }, 4219a0bf528SMauro Carvalho Chehab { STV090x_P1_DEMOD, 0x08 }, 4229a0bf528SMauro Carvalho Chehab { STV090x_P1_DMDCFG3, 0xc4 }, 4239a0bf528SMauro Carvalho Chehab { STV090x_P1_CARFREQ, 0xed }, 4249a0bf528SMauro Carvalho Chehab { STV090x_P1_TNRCFG2, 0x82 }, 4259a0bf528SMauro Carvalho Chehab { STV090x_P1_LDT, 0xd0 }, 4269a0bf528SMauro Carvalho Chehab { STV090x_P1_LDT2, 0xb8 }, 4279a0bf528SMauro Carvalho Chehab { STV090x_P1_TMGCFG, 0xd2 }, 4289a0bf528SMauro Carvalho Chehab { STV090x_P1_TMGTHRISE, 0x20 }, 4299a0bf528SMauro Carvalho Chehab { STV090x_P1_TMGTHFALL, 0x00 }, 4309a0bf528SMauro Carvalho Chehab { STV090x_P1_SFRUPRATIO, 0xf0 }, 4319a0bf528SMauro Carvalho Chehab { STV090x_P1_SFRLOWRATIO, 0x70 }, 4329a0bf528SMauro Carvalho Chehab { STV090x_P1_TSCFGL, 0x20 }, 4339a0bf528SMauro Carvalho Chehab { STV090x_P1_FECSPY, 0x88 }, 4349a0bf528SMauro Carvalho Chehab { STV090x_P1_FSPYDATA, 0x3a }, 4359a0bf528SMauro Carvalho Chehab { STV090x_P1_FBERCPT4, 0x00 }, 4369a0bf528SMauro Carvalho Chehab { STV090x_P1_FSPYBER, 0x10 }, 4379a0bf528SMauro Carvalho Chehab { STV090x_P1_ERRCTRL1, 0x35 }, 4389a0bf528SMauro Carvalho Chehab { STV090x_P1_ERRCTRL2, 0xc1 }, 4399a0bf528SMauro Carvalho Chehab { STV090x_P1_CFRICFG, 0xf8 }, 4409a0bf528SMauro Carvalho Chehab { STV090x_P1_NOSCFG, 0x1c }, 4419a0bf528SMauro Carvalho Chehab { STV090x_P1_DMDTOM, 0x20 }, 4429a0bf528SMauro Carvalho Chehab { STV090x_P1_CORRELMANT, 0x70 }, 4439a0bf528SMauro Carvalho Chehab { STV090x_P1_CORRELABS, 0x88 }, 4449a0bf528SMauro Carvalho Chehab { STV090x_P1_AGC2O, 0x5b }, 4459a0bf528SMauro Carvalho Chehab { STV090x_P1_AGC2REF, 0x38 }, 4469a0bf528SMauro Carvalho Chehab { STV090x_P1_CARCFG, 0xe4 }, 4479a0bf528SMauro Carvalho Chehab { STV090x_P1_ACLC, 0x1A }, 4489a0bf528SMauro Carvalho Chehab { STV090x_P1_BCLC, 0x09 }, 4499a0bf528SMauro Carvalho Chehab { STV090x_P1_CARHDR, 0x08 }, 4509a0bf528SMauro Carvalho Chehab { STV090x_P1_KREFTMG, 0xc1 }, 4519a0bf528SMauro Carvalho Chehab { STV090x_P1_SFRSTEP, 0x58 }, 4529a0bf528SMauro Carvalho Chehab { STV090x_P1_TMGCFG2, 0x01 }, 4539a0bf528SMauro Carvalho Chehab { STV090x_P1_CAR2CFG, 0x26 }, 4549a0bf528SMauro Carvalho Chehab { STV090x_P1_BCLC2S2Q, 0x86 }, 4559a0bf528SMauro Carvalho Chehab { STV090x_P1_BCLC2S28, 0x86 }, 4569a0bf528SMauro Carvalho Chehab { STV090x_P1_SMAPCOEF7, 0x77 }, 4579a0bf528SMauro Carvalho Chehab { STV090x_P1_SMAPCOEF6, 0x85 }, 4589a0bf528SMauro Carvalho Chehab { STV090x_P1_SMAPCOEF5, 0x77 }, 4599a0bf528SMauro Carvalho Chehab { STV090x_P1_DMDCFG2, 0x3b }, 4609a0bf528SMauro Carvalho Chehab { STV090x_P1_MODCODLST0, 0xff }, 4619a0bf528SMauro Carvalho Chehab { STV090x_P1_MODCODLST1, 0xff }, 4629a0bf528SMauro Carvalho Chehab { STV090x_P1_MODCODLST2, 0xff }, 4639a0bf528SMauro Carvalho Chehab { STV090x_P1_MODCODLST3, 0xff }, 4649a0bf528SMauro Carvalho Chehab { STV090x_P1_MODCODLST4, 0xff }, 4659a0bf528SMauro Carvalho Chehab { STV090x_P1_MODCODLST5, 0xff }, 4669a0bf528SMauro Carvalho Chehab { STV090x_P1_MODCODLST6, 0xff }, 4679a0bf528SMauro Carvalho Chehab { STV090x_P1_MODCODLST7, 0xcc }, 4689a0bf528SMauro Carvalho Chehab { STV090x_P1_MODCODLST8, 0xcc }, 4699a0bf528SMauro Carvalho Chehab { STV090x_P1_MODCODLST9, 0xcc }, 4709a0bf528SMauro Carvalho Chehab { STV090x_P1_MODCODLSTA, 0xcc }, 4719a0bf528SMauro Carvalho Chehab { STV090x_P1_MODCODLSTB, 0xcc }, 4729a0bf528SMauro Carvalho Chehab { STV090x_P1_MODCODLSTC, 0xcc }, 4739a0bf528SMauro Carvalho Chehab { STV090x_P1_MODCODLSTD, 0xcc }, 4749a0bf528SMauro Carvalho Chehab { STV090x_P1_MODCODLSTE, 0xcc }, 4759a0bf528SMauro Carvalho Chehab { STV090x_P1_MODCODLSTF, 0xcf }, 4769a0bf528SMauro Carvalho Chehab { STV090x_GENCFG, 0x1c }, 4779a0bf528SMauro Carvalho Chehab { STV090x_NBITER_NF4, 0x37 }, 4789a0bf528SMauro Carvalho Chehab { STV090x_NBITER_NF5, 0x29 }, 4799a0bf528SMauro Carvalho Chehab { STV090x_NBITER_NF6, 0x37 }, 4809a0bf528SMauro Carvalho Chehab { STV090x_NBITER_NF7, 0x33 }, 4819a0bf528SMauro Carvalho Chehab { STV090x_NBITER_NF8, 0x31 }, 4829a0bf528SMauro Carvalho Chehab { STV090x_NBITER_NF9, 0x2f }, 4839a0bf528SMauro Carvalho Chehab { STV090x_NBITER_NF10, 0x39 }, 4849a0bf528SMauro Carvalho Chehab { STV090x_NBITER_NF11, 0x3a }, 4859a0bf528SMauro Carvalho Chehab { STV090x_NBITER_NF12, 0x29 }, 4869a0bf528SMauro Carvalho Chehab { STV090x_NBITER_NF13, 0x37 }, 4879a0bf528SMauro Carvalho Chehab { STV090x_NBITER_NF14, 0x33 }, 4889a0bf528SMauro Carvalho Chehab { STV090x_NBITER_NF15, 0x2f }, 4899a0bf528SMauro Carvalho Chehab { STV090x_NBITER_NF16, 0x39 }, 4909a0bf528SMauro Carvalho Chehab { STV090x_NBITER_NF17, 0x3a }, 4919a0bf528SMauro Carvalho Chehab { STV090x_NBITERNOERR, 0x04 }, 4929a0bf528SMauro Carvalho Chehab { STV090x_GAINLLR_NF4, 0x0C }, 4939a0bf528SMauro Carvalho Chehab { STV090x_GAINLLR_NF5, 0x0F }, 4949a0bf528SMauro Carvalho Chehab { STV090x_GAINLLR_NF6, 0x11 }, 4959a0bf528SMauro Carvalho Chehab { STV090x_GAINLLR_NF7, 0x14 }, 4969a0bf528SMauro Carvalho Chehab { STV090x_GAINLLR_NF8, 0x17 }, 4979a0bf528SMauro Carvalho Chehab { STV090x_GAINLLR_NF9, 0x19 }, 4989a0bf528SMauro Carvalho Chehab { STV090x_GAINLLR_NF10, 0x20 }, 4999a0bf528SMauro Carvalho Chehab { STV090x_GAINLLR_NF11, 0x21 }, 5009a0bf528SMauro Carvalho Chehab { STV090x_GAINLLR_NF12, 0x0D }, 5019a0bf528SMauro Carvalho Chehab { STV090x_GAINLLR_NF13, 0x0F }, 5029a0bf528SMauro Carvalho Chehab { STV090x_GAINLLR_NF14, 0x13 }, 5039a0bf528SMauro Carvalho Chehab { STV090x_GAINLLR_NF15, 0x1A }, 5049a0bf528SMauro Carvalho Chehab { STV090x_GAINLLR_NF16, 0x1F }, 5059a0bf528SMauro Carvalho Chehab { STV090x_GAINLLR_NF17, 0x21 }, 5069a0bf528SMauro Carvalho Chehab { STV090x_RCCFGH, 0x20 }, 5079a0bf528SMauro Carvalho Chehab { STV090x_P1_FECM, 0x01 }, /*disable the DSS mode */ 5089a0bf528SMauro Carvalho Chehab { STV090x_P1_PRVIT, 0x2f } /*disable puncture rate 6/7*/ 5099a0bf528SMauro Carvalho Chehab }; 5109a0bf528SMauro Carvalho Chehab 5119a0bf528SMauro Carvalho Chehab static struct stv090x_reg stv0900_cut20_val[] = { 5129a0bf528SMauro Carvalho Chehab 5139a0bf528SMauro Carvalho Chehab { STV090x_P2_DMDCFG3, 0xe8 }, 5149a0bf528SMauro Carvalho Chehab { STV090x_P2_DMDCFG4, 0x10 }, 5159a0bf528SMauro Carvalho Chehab { STV090x_P2_CARFREQ, 0x38 }, 5169a0bf528SMauro Carvalho Chehab { STV090x_P2_CARHDR, 0x20 }, 5179a0bf528SMauro Carvalho Chehab { STV090x_P2_KREFTMG, 0x5a }, 5189a0bf528SMauro Carvalho Chehab { STV090x_P2_SMAPCOEF7, 0x06 }, 5199a0bf528SMauro Carvalho Chehab { STV090x_P2_SMAPCOEF6, 0x00 }, 5209a0bf528SMauro Carvalho Chehab { STV090x_P2_SMAPCOEF5, 0x04 }, 5219a0bf528SMauro Carvalho Chehab { STV090x_P2_NOSCFG, 0x0c }, 5229a0bf528SMauro Carvalho Chehab { STV090x_P1_DMDCFG3, 0xe8 }, 5239a0bf528SMauro Carvalho Chehab { STV090x_P1_DMDCFG4, 0x10 }, 5249a0bf528SMauro Carvalho Chehab { STV090x_P1_CARFREQ, 0x38 }, 5259a0bf528SMauro Carvalho Chehab { STV090x_P1_CARHDR, 0x20 }, 5269a0bf528SMauro Carvalho Chehab { STV090x_P1_KREFTMG, 0x5a }, 5279a0bf528SMauro Carvalho Chehab { STV090x_P1_SMAPCOEF7, 0x06 }, 5289a0bf528SMauro Carvalho Chehab { STV090x_P1_SMAPCOEF6, 0x00 }, 5299a0bf528SMauro Carvalho Chehab { STV090x_P1_SMAPCOEF5, 0x04 }, 5309a0bf528SMauro Carvalho Chehab { STV090x_P1_NOSCFG, 0x0c }, 5319a0bf528SMauro Carvalho Chehab { STV090x_GAINLLR_NF4, 0x21 }, 5329a0bf528SMauro Carvalho Chehab { STV090x_GAINLLR_NF5, 0x21 }, 5339a0bf528SMauro Carvalho Chehab { STV090x_GAINLLR_NF6, 0x20 }, 5349a0bf528SMauro Carvalho Chehab { STV090x_GAINLLR_NF7, 0x1F }, 5359a0bf528SMauro Carvalho Chehab { STV090x_GAINLLR_NF8, 0x1E }, 5369a0bf528SMauro Carvalho Chehab { STV090x_GAINLLR_NF9, 0x1E }, 5379a0bf528SMauro Carvalho Chehab { STV090x_GAINLLR_NF10, 0x1D }, 5389a0bf528SMauro Carvalho Chehab { STV090x_GAINLLR_NF11, 0x1B }, 5399a0bf528SMauro Carvalho Chehab { STV090x_GAINLLR_NF12, 0x20 }, 5409a0bf528SMauro Carvalho Chehab { STV090x_GAINLLR_NF13, 0x20 }, 5419a0bf528SMauro Carvalho Chehab { STV090x_GAINLLR_NF14, 0x20 }, 5429a0bf528SMauro Carvalho Chehab { STV090x_GAINLLR_NF15, 0x20 }, 5439a0bf528SMauro Carvalho Chehab { STV090x_GAINLLR_NF16, 0x20 }, 5449a0bf528SMauro Carvalho Chehab { STV090x_GAINLLR_NF17, 0x21 }, 5459a0bf528SMauro Carvalho Chehab }; 5469a0bf528SMauro Carvalho Chehab 5479a0bf528SMauro Carvalho Chehab static struct stv090x_reg stv0903_cut20_val[] = { 5489a0bf528SMauro Carvalho Chehab { STV090x_P1_DMDCFG3, 0xe8 }, 5499a0bf528SMauro Carvalho Chehab { STV090x_P1_DMDCFG4, 0x10 }, 5509a0bf528SMauro Carvalho Chehab { STV090x_P1_CARFREQ, 0x38 }, 5519a0bf528SMauro Carvalho Chehab { STV090x_P1_CARHDR, 0x20 }, 5529a0bf528SMauro Carvalho Chehab { STV090x_P1_KREFTMG, 0x5a }, 5539a0bf528SMauro Carvalho Chehab { STV090x_P1_SMAPCOEF7, 0x06 }, 5549a0bf528SMauro Carvalho Chehab { STV090x_P1_SMAPCOEF6, 0x00 }, 5559a0bf528SMauro Carvalho Chehab { STV090x_P1_SMAPCOEF5, 0x04 }, 5569a0bf528SMauro Carvalho Chehab { STV090x_P1_NOSCFG, 0x0c }, 5579a0bf528SMauro Carvalho Chehab { STV090x_GAINLLR_NF4, 0x21 }, 5589a0bf528SMauro Carvalho Chehab { STV090x_GAINLLR_NF5, 0x21 }, 5599a0bf528SMauro Carvalho Chehab { STV090x_GAINLLR_NF6, 0x20 }, 5609a0bf528SMauro Carvalho Chehab { STV090x_GAINLLR_NF7, 0x1F }, 5619a0bf528SMauro Carvalho Chehab { STV090x_GAINLLR_NF8, 0x1E }, 5629a0bf528SMauro Carvalho Chehab { STV090x_GAINLLR_NF9, 0x1E }, 5639a0bf528SMauro Carvalho Chehab { STV090x_GAINLLR_NF10, 0x1D }, 5649a0bf528SMauro Carvalho Chehab { STV090x_GAINLLR_NF11, 0x1B }, 5659a0bf528SMauro Carvalho Chehab { STV090x_GAINLLR_NF12, 0x20 }, 5669a0bf528SMauro Carvalho Chehab { STV090x_GAINLLR_NF13, 0x20 }, 5679a0bf528SMauro Carvalho Chehab { STV090x_GAINLLR_NF14, 0x20 }, 5689a0bf528SMauro Carvalho Chehab { STV090x_GAINLLR_NF15, 0x20 }, 5699a0bf528SMauro Carvalho Chehab { STV090x_GAINLLR_NF16, 0x20 }, 5709a0bf528SMauro Carvalho Chehab { STV090x_GAINLLR_NF17, 0x21 } 5719a0bf528SMauro Carvalho Chehab }; 5729a0bf528SMauro Carvalho Chehab 5739a0bf528SMauro Carvalho Chehab /* Cut 2.0 Long Frame Tracking CR loop */ 5749a0bf528SMauro Carvalho Chehab static struct stv090x_long_frame_crloop stv090x_s2_crl_cut20[] = { 5759a0bf528SMauro Carvalho Chehab /* MODCOD 2MPon 2MPoff 5MPon 5MPoff 10MPon 10MPoff 20MPon 20MPoff 30MPon 30MPoff */ 5769a0bf528SMauro Carvalho Chehab { STV090x_QPSK_12, 0x1f, 0x3f, 0x1e, 0x3f, 0x3d, 0x1f, 0x3d, 0x3e, 0x3d, 0x1e }, 5779a0bf528SMauro Carvalho Chehab { STV090x_QPSK_35, 0x2f, 0x3f, 0x2e, 0x2f, 0x3d, 0x0f, 0x0e, 0x2e, 0x3d, 0x0e }, 5789a0bf528SMauro Carvalho Chehab { STV090x_QPSK_23, 0x2f, 0x3f, 0x2e, 0x2f, 0x0e, 0x0f, 0x0e, 0x1e, 0x3d, 0x3d }, 5799a0bf528SMauro Carvalho Chehab { STV090x_QPSK_34, 0x3f, 0x3f, 0x3e, 0x1f, 0x0e, 0x3e, 0x0e, 0x1e, 0x3d, 0x3d }, 5809a0bf528SMauro Carvalho Chehab { STV090x_QPSK_45, 0x3f, 0x3f, 0x3e, 0x1f, 0x0e, 0x3e, 0x0e, 0x1e, 0x3d, 0x3d }, 5819a0bf528SMauro Carvalho Chehab { STV090x_QPSK_56, 0x3f, 0x3f, 0x3e, 0x1f, 0x0e, 0x3e, 0x0e, 0x1e, 0x3d, 0x3d }, 5829a0bf528SMauro Carvalho Chehab { STV090x_QPSK_89, 0x3f, 0x3f, 0x3e, 0x1f, 0x1e, 0x3e, 0x0e, 0x1e, 0x3d, 0x3d }, 5839a0bf528SMauro Carvalho Chehab { STV090x_QPSK_910, 0x3f, 0x3f, 0x3e, 0x1f, 0x1e, 0x3e, 0x0e, 0x1e, 0x3d, 0x3d }, 5849a0bf528SMauro Carvalho Chehab { STV090x_8PSK_35, 0x3c, 0x3e, 0x1c, 0x2e, 0x0c, 0x1e, 0x2b, 0x2d, 0x1b, 0x1d }, 5859a0bf528SMauro Carvalho Chehab { STV090x_8PSK_23, 0x1d, 0x3e, 0x3c, 0x2e, 0x2c, 0x1e, 0x0c, 0x2d, 0x2b, 0x1d }, 5869a0bf528SMauro Carvalho Chehab { STV090x_8PSK_34, 0x0e, 0x3e, 0x3d, 0x2e, 0x0d, 0x1e, 0x2c, 0x2d, 0x0c, 0x1d }, 5879a0bf528SMauro Carvalho Chehab { STV090x_8PSK_56, 0x2e, 0x3e, 0x1e, 0x2e, 0x2d, 0x1e, 0x3c, 0x2d, 0x2c, 0x1d }, 5889a0bf528SMauro Carvalho Chehab { STV090x_8PSK_89, 0x3e, 0x3e, 0x1e, 0x2e, 0x3d, 0x1e, 0x0d, 0x2d, 0x3c, 0x1d }, 5899a0bf528SMauro Carvalho Chehab { STV090x_8PSK_910, 0x3e, 0x3e, 0x1e, 0x2e, 0x3d, 0x1e, 0x1d, 0x2d, 0x0d, 0x1d } 5909a0bf528SMauro Carvalho Chehab }; 5919a0bf528SMauro Carvalho Chehab 5929a0bf528SMauro Carvalho Chehab /* Cut 3.0 Long Frame Tracking CR loop */ 5939a0bf528SMauro Carvalho Chehab static struct stv090x_long_frame_crloop stv090x_s2_crl_cut30[] = { 5949a0bf528SMauro Carvalho Chehab /* MODCOD 2MPon 2MPoff 5MPon 5MPoff 10MPon 10MPoff 20MPon 20MPoff 30MPon 30MPoff */ 5959a0bf528SMauro Carvalho Chehab { STV090x_QPSK_12, 0x3c, 0x2c, 0x0c, 0x2c, 0x1b, 0x2c, 0x1b, 0x1c, 0x0b, 0x3b }, 5969a0bf528SMauro Carvalho Chehab { STV090x_QPSK_35, 0x0d, 0x0d, 0x0c, 0x0d, 0x1b, 0x3c, 0x1b, 0x1c, 0x0b, 0x3b }, 5979a0bf528SMauro Carvalho Chehab { STV090x_QPSK_23, 0x1d, 0x0d, 0x0c, 0x1d, 0x2b, 0x3c, 0x1b, 0x1c, 0x0b, 0x3b }, 5989a0bf528SMauro Carvalho Chehab { STV090x_QPSK_34, 0x1d, 0x1d, 0x0c, 0x1d, 0x2b, 0x3c, 0x1b, 0x1c, 0x0b, 0x3b }, 5999a0bf528SMauro Carvalho Chehab { STV090x_QPSK_45, 0x2d, 0x1d, 0x1c, 0x1d, 0x2b, 0x3c, 0x2b, 0x0c, 0x1b, 0x3b }, 6009a0bf528SMauro Carvalho Chehab { STV090x_QPSK_56, 0x2d, 0x1d, 0x1c, 0x1d, 0x2b, 0x3c, 0x2b, 0x0c, 0x1b, 0x3b }, 6019a0bf528SMauro Carvalho Chehab { STV090x_QPSK_89, 0x3d, 0x2d, 0x1c, 0x1d, 0x3b, 0x3c, 0x2b, 0x0c, 0x1b, 0x3b }, 6029a0bf528SMauro Carvalho Chehab { STV090x_QPSK_910, 0x3d, 0x2d, 0x1c, 0x1d, 0x3b, 0x3c, 0x2b, 0x0c, 0x1b, 0x3b }, 6039a0bf528SMauro Carvalho Chehab { STV090x_8PSK_35, 0x39, 0x29, 0x39, 0x19, 0x19, 0x19, 0x19, 0x19, 0x09, 0x19 }, 6049a0bf528SMauro Carvalho Chehab { STV090x_8PSK_23, 0x2a, 0x39, 0x1a, 0x0a, 0x39, 0x0a, 0x29, 0x39, 0x29, 0x0a }, 6059a0bf528SMauro Carvalho Chehab { STV090x_8PSK_34, 0x2b, 0x3a, 0x1b, 0x1b, 0x3a, 0x1b, 0x1a, 0x0b, 0x1a, 0x3a }, 6069a0bf528SMauro Carvalho Chehab { STV090x_8PSK_56, 0x0c, 0x1b, 0x3b, 0x3b, 0x1b, 0x3b, 0x3a, 0x3b, 0x3a, 0x1b }, 6079a0bf528SMauro Carvalho Chehab { STV090x_8PSK_89, 0x0d, 0x3c, 0x2c, 0x2c, 0x2b, 0x0c, 0x0b, 0x3b, 0x0b, 0x1b }, 6089a0bf528SMauro Carvalho Chehab { STV090x_8PSK_910, 0x0d, 0x0d, 0x2c, 0x3c, 0x3b, 0x1c, 0x0b, 0x3b, 0x0b, 0x1b } 6099a0bf528SMauro Carvalho Chehab }; 6109a0bf528SMauro Carvalho Chehab 6119a0bf528SMauro Carvalho Chehab /* Cut 2.0 Long Frame Tracking CR Loop */ 6129a0bf528SMauro Carvalho Chehab static struct stv090x_long_frame_crloop stv090x_s2_apsk_crl_cut20[] = { 6139a0bf528SMauro Carvalho Chehab /* MODCOD 2MPon 2MPoff 5MPon 5MPoff 10MPon 10MPoff 20MPon 20MPoff 30MPon 30MPoff */ 6149a0bf528SMauro Carvalho Chehab { STV090x_16APSK_23, 0x0c, 0x0c, 0x0c, 0x0c, 0x1d, 0x0c, 0x3c, 0x0c, 0x2c, 0x0c }, 6159a0bf528SMauro Carvalho Chehab { STV090x_16APSK_34, 0x0c, 0x0c, 0x0c, 0x0c, 0x0e, 0x0c, 0x2d, 0x0c, 0x1d, 0x0c }, 6169a0bf528SMauro Carvalho Chehab { STV090x_16APSK_45, 0x0c, 0x0c, 0x0c, 0x0c, 0x1e, 0x0c, 0x3d, 0x0c, 0x2d, 0x0c }, 6179a0bf528SMauro Carvalho Chehab { STV090x_16APSK_56, 0x0c, 0x0c, 0x0c, 0x0c, 0x1e, 0x0c, 0x3d, 0x0c, 0x2d, 0x0c }, 6189a0bf528SMauro Carvalho Chehab { STV090x_16APSK_89, 0x0c, 0x0c, 0x0c, 0x0c, 0x2e, 0x0c, 0x0e, 0x0c, 0x3d, 0x0c }, 6199a0bf528SMauro Carvalho Chehab { STV090x_16APSK_910, 0x0c, 0x0c, 0x0c, 0x0c, 0x2e, 0x0c, 0x0e, 0x0c, 0x3d, 0x0c }, 6209a0bf528SMauro Carvalho Chehab { STV090x_32APSK_34, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c }, 6219a0bf528SMauro Carvalho Chehab { STV090x_32APSK_45, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c }, 6229a0bf528SMauro Carvalho Chehab { STV090x_32APSK_56, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c }, 6239a0bf528SMauro Carvalho Chehab { STV090x_32APSK_89, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c }, 6249a0bf528SMauro Carvalho Chehab { STV090x_32APSK_910, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c } 6259a0bf528SMauro Carvalho Chehab }; 6269a0bf528SMauro Carvalho Chehab 6279a0bf528SMauro Carvalho Chehab /* Cut 3.0 Long Frame Tracking CR Loop */ 6289a0bf528SMauro Carvalho Chehab static struct stv090x_long_frame_crloop stv090x_s2_apsk_crl_cut30[] = { 6299a0bf528SMauro Carvalho Chehab /* MODCOD 2MPon 2MPoff 5MPon 5MPoff 10MPon 10MPoff 20MPon 20MPoff 30MPon 30MPoff */ 6309a0bf528SMauro Carvalho Chehab { STV090x_16APSK_23, 0x0a, 0x0a, 0x0a, 0x0a, 0x1a, 0x0a, 0x3a, 0x0a, 0x2a, 0x0a }, 6319a0bf528SMauro Carvalho Chehab { STV090x_16APSK_34, 0x0a, 0x0a, 0x0a, 0x0a, 0x0b, 0x0a, 0x3b, 0x0a, 0x1b, 0x0a }, 6329a0bf528SMauro Carvalho Chehab { STV090x_16APSK_45, 0x0a, 0x0a, 0x0a, 0x0a, 0x1b, 0x0a, 0x3b, 0x0a, 0x2b, 0x0a }, 6339a0bf528SMauro Carvalho Chehab { STV090x_16APSK_56, 0x0a, 0x0a, 0x0a, 0x0a, 0x1b, 0x0a, 0x3b, 0x0a, 0x2b, 0x0a }, 6349a0bf528SMauro Carvalho Chehab { STV090x_16APSK_89, 0x0a, 0x0a, 0x0a, 0x0a, 0x2b, 0x0a, 0x0c, 0x0a, 0x3b, 0x0a }, 6359a0bf528SMauro Carvalho Chehab { STV090x_16APSK_910, 0x0a, 0x0a, 0x0a, 0x0a, 0x2b, 0x0a, 0x0c, 0x0a, 0x3b, 0x0a }, 6369a0bf528SMauro Carvalho Chehab { STV090x_32APSK_34, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a }, 6379a0bf528SMauro Carvalho Chehab { STV090x_32APSK_45, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a }, 6389a0bf528SMauro Carvalho Chehab { STV090x_32APSK_56, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a }, 6399a0bf528SMauro Carvalho Chehab { STV090x_32APSK_89, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a }, 6409a0bf528SMauro Carvalho Chehab { STV090x_32APSK_910, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a } 6419a0bf528SMauro Carvalho Chehab }; 6429a0bf528SMauro Carvalho Chehab 6439a0bf528SMauro Carvalho Chehab static struct stv090x_long_frame_crloop stv090x_s2_lowqpsk_crl_cut20[] = { 6449a0bf528SMauro Carvalho Chehab /* MODCOD 2MPon 2MPoff 5MPon 5MPoff 10MPon 10MPoff 20MPon 20MPoff 30MPon 30MPoff */ 6459a0bf528SMauro Carvalho Chehab { STV090x_QPSK_14, 0x0f, 0x3f, 0x0e, 0x3f, 0x2d, 0x2f, 0x2d, 0x1f, 0x3d, 0x3e }, 6469a0bf528SMauro Carvalho Chehab { STV090x_QPSK_13, 0x0f, 0x3f, 0x0e, 0x3f, 0x2d, 0x2f, 0x3d, 0x0f, 0x3d, 0x2e }, 6479a0bf528SMauro Carvalho Chehab { STV090x_QPSK_25, 0x1f, 0x3f, 0x1e, 0x3f, 0x3d, 0x1f, 0x3d, 0x3e, 0x3d, 0x2e } 6489a0bf528SMauro Carvalho Chehab }; 6499a0bf528SMauro Carvalho Chehab 6509a0bf528SMauro Carvalho Chehab static struct stv090x_long_frame_crloop stv090x_s2_lowqpsk_crl_cut30[] = { 6519a0bf528SMauro Carvalho Chehab /* MODCOD 2MPon 2MPoff 5MPon 5MPoff 10MPon 10MPoff 20MPon 20MPoff 30MPon 30MPoff */ 6529a0bf528SMauro Carvalho Chehab { STV090x_QPSK_14, 0x0c, 0x3c, 0x0b, 0x3c, 0x2a, 0x2c, 0x2a, 0x1c, 0x3a, 0x3b }, 6539a0bf528SMauro Carvalho Chehab { STV090x_QPSK_13, 0x0c, 0x3c, 0x0b, 0x3c, 0x2a, 0x2c, 0x3a, 0x0c, 0x3a, 0x2b }, 6549a0bf528SMauro Carvalho Chehab { STV090x_QPSK_25, 0x1c, 0x3c, 0x1b, 0x3c, 0x3a, 0x1c, 0x3a, 0x3b, 0x3a, 0x2b } 6559a0bf528SMauro Carvalho Chehab }; 6569a0bf528SMauro Carvalho Chehab 6579a0bf528SMauro Carvalho Chehab /* Cut 2.0 Short Frame Tracking CR Loop */ 6589a0bf528SMauro Carvalho Chehab static struct stv090x_short_frame_crloop stv090x_s2_short_crl_cut20[] = { 6599a0bf528SMauro Carvalho Chehab /* MODCOD 2M 5M 10M 20M 30M */ 6609a0bf528SMauro Carvalho Chehab { STV090x_QPSK, 0x2f, 0x2e, 0x0e, 0x0e, 0x3d }, 6619a0bf528SMauro Carvalho Chehab { STV090x_8PSK, 0x3e, 0x0e, 0x2d, 0x0d, 0x3c }, 6629a0bf528SMauro Carvalho Chehab { STV090x_16APSK, 0x1e, 0x1e, 0x1e, 0x3d, 0x2d }, 6639a0bf528SMauro Carvalho Chehab { STV090x_32APSK, 0x1e, 0x1e, 0x1e, 0x3d, 0x2d } 6649a0bf528SMauro Carvalho Chehab }; 6659a0bf528SMauro Carvalho Chehab 6669a0bf528SMauro Carvalho Chehab /* Cut 3.0 Short Frame Tracking CR Loop */ 6679a0bf528SMauro Carvalho Chehab static struct stv090x_short_frame_crloop stv090x_s2_short_crl_cut30[] = { 6689a0bf528SMauro Carvalho Chehab /* MODCOD 2M 5M 10M 20M 30M */ 6699a0bf528SMauro Carvalho Chehab { STV090x_QPSK, 0x2C, 0x2B, 0x0B, 0x0B, 0x3A }, 6709a0bf528SMauro Carvalho Chehab { STV090x_8PSK, 0x3B, 0x0B, 0x2A, 0x0A, 0x39 }, 6719a0bf528SMauro Carvalho Chehab { STV090x_16APSK, 0x1B, 0x1B, 0x1B, 0x3A, 0x2A }, 6729a0bf528SMauro Carvalho Chehab { STV090x_32APSK, 0x1B, 0x1B, 0x1B, 0x3A, 0x2A } 6739a0bf528SMauro Carvalho Chehab }; 6749a0bf528SMauro Carvalho Chehab 6759a0bf528SMauro Carvalho Chehab static inline s32 comp2(s32 __x, s32 __width) 6769a0bf528SMauro Carvalho Chehab { 6779a0bf528SMauro Carvalho Chehab if (__width == 32) 6789a0bf528SMauro Carvalho Chehab return __x; 6799a0bf528SMauro Carvalho Chehab else 6809a0bf528SMauro Carvalho Chehab return (__x >= (1 << (__width - 1))) ? (__x - (1 << __width)) : __x; 6819a0bf528SMauro Carvalho Chehab } 6829a0bf528SMauro Carvalho Chehab 6839a0bf528SMauro Carvalho Chehab static int stv090x_read_reg(struct stv090x_state *state, unsigned int reg) 6849a0bf528SMauro Carvalho Chehab { 6859a0bf528SMauro Carvalho Chehab const struct stv090x_config *config = state->config; 6869a0bf528SMauro Carvalho Chehab int ret; 6879a0bf528SMauro Carvalho Chehab 6889a0bf528SMauro Carvalho Chehab u8 b0[] = { reg >> 8, reg & 0xff }; 6899a0bf528SMauro Carvalho Chehab u8 buf; 6909a0bf528SMauro Carvalho Chehab 6919a0bf528SMauro Carvalho Chehab struct i2c_msg msg[] = { 6929a0bf528SMauro Carvalho Chehab { .addr = config->address, .flags = 0, .buf = b0, .len = 2 }, 6939a0bf528SMauro Carvalho Chehab { .addr = config->address, .flags = I2C_M_RD, .buf = &buf, .len = 1 } 6949a0bf528SMauro Carvalho Chehab }; 6959a0bf528SMauro Carvalho Chehab 6969a0bf528SMauro Carvalho Chehab ret = i2c_transfer(state->i2c, msg, 2); 6979a0bf528SMauro Carvalho Chehab if (ret != 2) { 6989a0bf528SMauro Carvalho Chehab if (ret != -ERESTARTSYS) 6999a0bf528SMauro Carvalho Chehab dprintk(FE_ERROR, 1, 7009a0bf528SMauro Carvalho Chehab "Read error, Reg=[0x%02x], Status=%d", 7019a0bf528SMauro Carvalho Chehab reg, ret); 7029a0bf528SMauro Carvalho Chehab 7039a0bf528SMauro Carvalho Chehab return ret < 0 ? ret : -EREMOTEIO; 7049a0bf528SMauro Carvalho Chehab } 7059a0bf528SMauro Carvalho Chehab if (unlikely(*state->verbose >= FE_DEBUGREG)) 7069a0bf528SMauro Carvalho Chehab dprintk(FE_ERROR, 1, "Reg=[0x%02x], data=%02x", 7079a0bf528SMauro Carvalho Chehab reg, buf); 7089a0bf528SMauro Carvalho Chehab 7099a0bf528SMauro Carvalho Chehab return (unsigned int) buf; 7109a0bf528SMauro Carvalho Chehab } 7119a0bf528SMauro Carvalho Chehab 7129a0bf528SMauro Carvalho Chehab static int stv090x_write_regs(struct stv090x_state *state, unsigned int reg, u8 *data, u32 count) 7139a0bf528SMauro Carvalho Chehab { 7149a0bf528SMauro Carvalho Chehab const struct stv090x_config *config = state->config; 7159a0bf528SMauro Carvalho Chehab int ret; 716f7a35df1SMauro Carvalho Chehab u8 buf[MAX_XFER_SIZE]; 7179a0bf528SMauro Carvalho Chehab struct i2c_msg i2c_msg = { .addr = config->address, .flags = 0, .buf = buf, .len = 2 + count }; 7189a0bf528SMauro Carvalho Chehab 719f7a35df1SMauro Carvalho Chehab if (2 + count > sizeof(buf)) { 720f7a35df1SMauro Carvalho Chehab printk(KERN_WARNING 721f7a35df1SMauro Carvalho Chehab "%s: i2c wr reg=%04x: len=%d is too big!\n", 722f7a35df1SMauro Carvalho Chehab KBUILD_MODNAME, reg, count); 723f7a35df1SMauro Carvalho Chehab return -EINVAL; 724f7a35df1SMauro Carvalho Chehab } 725f7a35df1SMauro Carvalho Chehab 7269a0bf528SMauro Carvalho Chehab buf[0] = reg >> 8; 7279a0bf528SMauro Carvalho Chehab buf[1] = reg & 0xff; 7289a0bf528SMauro Carvalho Chehab memcpy(&buf[2], data, count); 7299a0bf528SMauro Carvalho Chehab 730fed9d8f3SMauro Carvalho Chehab dprintk(FE_DEBUGREG, 1, "%s [0x%04x]: %*ph", 731fed9d8f3SMauro Carvalho Chehab __func__, reg, count, data); 7329a0bf528SMauro Carvalho Chehab 7339a0bf528SMauro Carvalho Chehab ret = i2c_transfer(state->i2c, &i2c_msg, 1); 7349a0bf528SMauro Carvalho Chehab if (ret != 1) { 7359a0bf528SMauro Carvalho Chehab if (ret != -ERESTARTSYS) 7369a0bf528SMauro Carvalho Chehab dprintk(FE_ERROR, 1, "Reg=[0x%04x], Data=[0x%02x ...], Count=%u, Status=%d", 7379a0bf528SMauro Carvalho Chehab reg, data[0], count, ret); 7389a0bf528SMauro Carvalho Chehab return ret < 0 ? ret : -EREMOTEIO; 7399a0bf528SMauro Carvalho Chehab } 7409a0bf528SMauro Carvalho Chehab 7419a0bf528SMauro Carvalho Chehab return 0; 7429a0bf528SMauro Carvalho Chehab } 7439a0bf528SMauro Carvalho Chehab 7449a0bf528SMauro Carvalho Chehab static int stv090x_write_reg(struct stv090x_state *state, unsigned int reg, u8 data) 7459a0bf528SMauro Carvalho Chehab { 7463cd890dbSArnd Bergmann u8 tmp = data; /* see gcc.gnu.org/bugzilla/show_bug.cgi?id=81715 */ 7473cd890dbSArnd Bergmann 7483cd890dbSArnd Bergmann return stv090x_write_regs(state, reg, &tmp, 1); 7499a0bf528SMauro Carvalho Chehab } 7509a0bf528SMauro Carvalho Chehab 7519a0bf528SMauro Carvalho Chehab static int stv090x_i2c_gate_ctrl(struct stv090x_state *state, int enable) 7529a0bf528SMauro Carvalho Chehab { 7539a0bf528SMauro Carvalho Chehab u32 reg; 7549a0bf528SMauro Carvalho Chehab 7559a0bf528SMauro Carvalho Chehab /* 7569a0bf528SMauro Carvalho Chehab * NOTE! A lock is used as a FSM to control the state in which 7579a0bf528SMauro Carvalho Chehab * access is serialized between two tuners on the same demod. 7589a0bf528SMauro Carvalho Chehab * This has nothing to do with a lock to protect a critical section 7599a0bf528SMauro Carvalho Chehab * which may in some other cases be confused with protecting I/O 7609a0bf528SMauro Carvalho Chehab * access to the demodulator gate. 7619a0bf528SMauro Carvalho Chehab * In case of any error, the lock is unlocked and exit within the 7629a0bf528SMauro Carvalho Chehab * relevant operations themselves. 7639a0bf528SMauro Carvalho Chehab */ 7649a0bf528SMauro Carvalho Chehab if (enable) { 7659a0bf528SMauro Carvalho Chehab if (state->config->tuner_i2c_lock) 7669a0bf528SMauro Carvalho Chehab state->config->tuner_i2c_lock(&state->frontend, 1); 7679a0bf528SMauro Carvalho Chehab else 7689a0bf528SMauro Carvalho Chehab mutex_lock(&state->internal->tuner_lock); 7699a0bf528SMauro Carvalho Chehab } 7709a0bf528SMauro Carvalho Chehab 7719a0bf528SMauro Carvalho Chehab reg = STV090x_READ_DEMOD(state, I2CRPT); 7729a0bf528SMauro Carvalho Chehab if (enable) { 7739a0bf528SMauro Carvalho Chehab dprintk(FE_DEBUG, 1, "Enable Gate"); 7749a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, I2CT_ON_FIELD, 1); 7759a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, I2CRPT, reg) < 0) 7769a0bf528SMauro Carvalho Chehab goto err; 7779a0bf528SMauro Carvalho Chehab 7789a0bf528SMauro Carvalho Chehab } else { 7799a0bf528SMauro Carvalho Chehab dprintk(FE_DEBUG, 1, "Disable Gate"); 7809a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, I2CT_ON_FIELD, 0); 7819a0bf528SMauro Carvalho Chehab if ((STV090x_WRITE_DEMOD(state, I2CRPT, reg)) < 0) 7829a0bf528SMauro Carvalho Chehab goto err; 7839a0bf528SMauro Carvalho Chehab } 7849a0bf528SMauro Carvalho Chehab 7859a0bf528SMauro Carvalho Chehab if (!enable) { 7869a0bf528SMauro Carvalho Chehab if (state->config->tuner_i2c_lock) 7879a0bf528SMauro Carvalho Chehab state->config->tuner_i2c_lock(&state->frontend, 0); 7889a0bf528SMauro Carvalho Chehab else 7899a0bf528SMauro Carvalho Chehab mutex_unlock(&state->internal->tuner_lock); 7909a0bf528SMauro Carvalho Chehab } 7919a0bf528SMauro Carvalho Chehab 7929a0bf528SMauro Carvalho Chehab return 0; 7939a0bf528SMauro Carvalho Chehab err: 7949a0bf528SMauro Carvalho Chehab dprintk(FE_ERROR, 1, "I/O error"); 7959a0bf528SMauro Carvalho Chehab if (state->config->tuner_i2c_lock) 7969a0bf528SMauro Carvalho Chehab state->config->tuner_i2c_lock(&state->frontend, 0); 7979a0bf528SMauro Carvalho Chehab else 7989a0bf528SMauro Carvalho Chehab mutex_unlock(&state->internal->tuner_lock); 7999a0bf528SMauro Carvalho Chehab return -1; 8009a0bf528SMauro Carvalho Chehab } 8019a0bf528SMauro Carvalho Chehab 8029a0bf528SMauro Carvalho Chehab static void stv090x_get_lock_tmg(struct stv090x_state *state) 8039a0bf528SMauro Carvalho Chehab { 8049a0bf528SMauro Carvalho Chehab switch (state->algo) { 8059a0bf528SMauro Carvalho Chehab case STV090x_BLIND_SEARCH: 8069a0bf528SMauro Carvalho Chehab dprintk(FE_DEBUG, 1, "Blind Search"); 8079a0bf528SMauro Carvalho Chehab if (state->srate <= 1500000) { /*10Msps< SR <=15Msps*/ 8089a0bf528SMauro Carvalho Chehab state->DemodTimeout = 1500; 8099a0bf528SMauro Carvalho Chehab state->FecTimeout = 400; 8109a0bf528SMauro Carvalho Chehab } else if (state->srate <= 5000000) { /*10Msps< SR <=15Msps*/ 8119a0bf528SMauro Carvalho Chehab state->DemodTimeout = 1000; 8129a0bf528SMauro Carvalho Chehab state->FecTimeout = 300; 8139a0bf528SMauro Carvalho Chehab } else { /*SR >20Msps*/ 8149a0bf528SMauro Carvalho Chehab state->DemodTimeout = 700; 8159a0bf528SMauro Carvalho Chehab state->FecTimeout = 100; 8169a0bf528SMauro Carvalho Chehab } 8179a0bf528SMauro Carvalho Chehab break; 8189a0bf528SMauro Carvalho Chehab 8199a0bf528SMauro Carvalho Chehab case STV090x_COLD_SEARCH: 8209a0bf528SMauro Carvalho Chehab case STV090x_WARM_SEARCH: 8219a0bf528SMauro Carvalho Chehab default: 8229a0bf528SMauro Carvalho Chehab dprintk(FE_DEBUG, 1, "Normal Search"); 8239a0bf528SMauro Carvalho Chehab if (state->srate <= 1000000) { /*SR <=1Msps*/ 8249a0bf528SMauro Carvalho Chehab state->DemodTimeout = 4500; 8259a0bf528SMauro Carvalho Chehab state->FecTimeout = 1700; 8269a0bf528SMauro Carvalho Chehab } else if (state->srate <= 2000000) { /*1Msps < SR <= 2Msps */ 8279a0bf528SMauro Carvalho Chehab state->DemodTimeout = 2500; 8289a0bf528SMauro Carvalho Chehab state->FecTimeout = 1100; 8299a0bf528SMauro Carvalho Chehab } else if (state->srate <= 5000000) { /*2Msps < SR <= 5Msps */ 8309a0bf528SMauro Carvalho Chehab state->DemodTimeout = 1000; 8319a0bf528SMauro Carvalho Chehab state->FecTimeout = 550; 8329a0bf528SMauro Carvalho Chehab } else if (state->srate <= 10000000) { /*5Msps < SR <= 10Msps */ 8339a0bf528SMauro Carvalho Chehab state->DemodTimeout = 700; 8349a0bf528SMauro Carvalho Chehab state->FecTimeout = 250; 8359a0bf528SMauro Carvalho Chehab } else if (state->srate <= 20000000) { /*10Msps < SR <= 20Msps */ 8369a0bf528SMauro Carvalho Chehab state->DemodTimeout = 400; 8379a0bf528SMauro Carvalho Chehab state->FecTimeout = 130; 8389a0bf528SMauro Carvalho Chehab } else { /*SR >20Msps*/ 8399a0bf528SMauro Carvalho Chehab state->DemodTimeout = 300; 8409a0bf528SMauro Carvalho Chehab state->FecTimeout = 100; 8419a0bf528SMauro Carvalho Chehab } 8429a0bf528SMauro Carvalho Chehab break; 8439a0bf528SMauro Carvalho Chehab } 8449a0bf528SMauro Carvalho Chehab 8459a0bf528SMauro Carvalho Chehab if (state->algo == STV090x_WARM_SEARCH) 8469a0bf528SMauro Carvalho Chehab state->DemodTimeout /= 2; 8479a0bf528SMauro Carvalho Chehab } 8489a0bf528SMauro Carvalho Chehab 8499a0bf528SMauro Carvalho Chehab static int stv090x_set_srate(struct stv090x_state *state, u32 srate) 8509a0bf528SMauro Carvalho Chehab { 8519a0bf528SMauro Carvalho Chehab u32 sym; 8529a0bf528SMauro Carvalho Chehab 8539a0bf528SMauro Carvalho Chehab if (srate > 60000000) { 8549a0bf528SMauro Carvalho Chehab sym = (srate << 4); /* SR * 2^16 / master_clk */ 8559a0bf528SMauro Carvalho Chehab sym /= (state->internal->mclk >> 12); 8569a0bf528SMauro Carvalho Chehab } else if (srate > 6000000) { 8579a0bf528SMauro Carvalho Chehab sym = (srate << 6); 8589a0bf528SMauro Carvalho Chehab sym /= (state->internal->mclk >> 10); 8599a0bf528SMauro Carvalho Chehab } else { 8609a0bf528SMauro Carvalho Chehab sym = (srate << 9); 8619a0bf528SMauro Carvalho Chehab sym /= (state->internal->mclk >> 7); 8629a0bf528SMauro Carvalho Chehab } 8639a0bf528SMauro Carvalho Chehab 8649a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, SFRINIT1, (sym >> 8) & 0x7f) < 0) /* MSB */ 8659a0bf528SMauro Carvalho Chehab goto err; 8669a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, SFRINIT0, (sym & 0xff)) < 0) /* LSB */ 8679a0bf528SMauro Carvalho Chehab goto err; 8689a0bf528SMauro Carvalho Chehab 8699a0bf528SMauro Carvalho Chehab return 0; 8709a0bf528SMauro Carvalho Chehab err: 8719a0bf528SMauro Carvalho Chehab dprintk(FE_ERROR, 1, "I/O error"); 8729a0bf528SMauro Carvalho Chehab return -1; 8739a0bf528SMauro Carvalho Chehab } 8749a0bf528SMauro Carvalho Chehab 8759a0bf528SMauro Carvalho Chehab static int stv090x_set_max_srate(struct stv090x_state *state, u32 clk, u32 srate) 8769a0bf528SMauro Carvalho Chehab { 8779a0bf528SMauro Carvalho Chehab u32 sym; 8789a0bf528SMauro Carvalho Chehab 8799a0bf528SMauro Carvalho Chehab srate = 105 * (srate / 100); 8809a0bf528SMauro Carvalho Chehab if (srate > 60000000) { 8819a0bf528SMauro Carvalho Chehab sym = (srate << 4); /* SR * 2^16 / master_clk */ 8829a0bf528SMauro Carvalho Chehab sym /= (state->internal->mclk >> 12); 8839a0bf528SMauro Carvalho Chehab } else if (srate > 6000000) { 8849a0bf528SMauro Carvalho Chehab sym = (srate << 6); 8859a0bf528SMauro Carvalho Chehab sym /= (state->internal->mclk >> 10); 8869a0bf528SMauro Carvalho Chehab } else { 8879a0bf528SMauro Carvalho Chehab sym = (srate << 9); 8889a0bf528SMauro Carvalho Chehab sym /= (state->internal->mclk >> 7); 8899a0bf528SMauro Carvalho Chehab } 8909a0bf528SMauro Carvalho Chehab 8919a0bf528SMauro Carvalho Chehab if (sym < 0x7fff) { 8929a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, SFRUP1, (sym >> 8) & 0x7f) < 0) /* MSB */ 8939a0bf528SMauro Carvalho Chehab goto err; 8949a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, SFRUP0, sym & 0xff) < 0) /* LSB */ 8959a0bf528SMauro Carvalho Chehab goto err; 8969a0bf528SMauro Carvalho Chehab } else { 8979a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, SFRUP1, 0x7f) < 0) /* MSB */ 8989a0bf528SMauro Carvalho Chehab goto err; 8999a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, SFRUP0, 0xff) < 0) /* LSB */ 9009a0bf528SMauro Carvalho Chehab goto err; 9019a0bf528SMauro Carvalho Chehab } 9029a0bf528SMauro Carvalho Chehab 9039a0bf528SMauro Carvalho Chehab return 0; 9049a0bf528SMauro Carvalho Chehab err: 9059a0bf528SMauro Carvalho Chehab dprintk(FE_ERROR, 1, "I/O error"); 9069a0bf528SMauro Carvalho Chehab return -1; 9079a0bf528SMauro Carvalho Chehab } 9089a0bf528SMauro Carvalho Chehab 9099a0bf528SMauro Carvalho Chehab static int stv090x_set_min_srate(struct stv090x_state *state, u32 clk, u32 srate) 9109a0bf528SMauro Carvalho Chehab { 9119a0bf528SMauro Carvalho Chehab u32 sym; 9129a0bf528SMauro Carvalho Chehab 9139a0bf528SMauro Carvalho Chehab srate = 95 * (srate / 100); 9149a0bf528SMauro Carvalho Chehab if (srate > 60000000) { 9159a0bf528SMauro Carvalho Chehab sym = (srate << 4); /* SR * 2^16 / master_clk */ 9169a0bf528SMauro Carvalho Chehab sym /= (state->internal->mclk >> 12); 9179a0bf528SMauro Carvalho Chehab } else if (srate > 6000000) { 9189a0bf528SMauro Carvalho Chehab sym = (srate << 6); 9199a0bf528SMauro Carvalho Chehab sym /= (state->internal->mclk >> 10); 9209a0bf528SMauro Carvalho Chehab } else { 9219a0bf528SMauro Carvalho Chehab sym = (srate << 9); 9229a0bf528SMauro Carvalho Chehab sym /= (state->internal->mclk >> 7); 9239a0bf528SMauro Carvalho Chehab } 9249a0bf528SMauro Carvalho Chehab 9259a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, SFRLOW1, ((sym >> 8) & 0x7f)) < 0) /* MSB */ 9269a0bf528SMauro Carvalho Chehab goto err; 9279a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, SFRLOW0, (sym & 0xff)) < 0) /* LSB */ 9289a0bf528SMauro Carvalho Chehab goto err; 9299a0bf528SMauro Carvalho Chehab return 0; 9309a0bf528SMauro Carvalho Chehab err: 9319a0bf528SMauro Carvalho Chehab dprintk(FE_ERROR, 1, "I/O error"); 9329a0bf528SMauro Carvalho Chehab return -1; 9339a0bf528SMauro Carvalho Chehab } 9349a0bf528SMauro Carvalho Chehab 9359a0bf528SMauro Carvalho Chehab static u32 stv090x_car_width(u32 srate, enum stv090x_rolloff rolloff) 9369a0bf528SMauro Carvalho Chehab { 9379a0bf528SMauro Carvalho Chehab u32 ro; 9389a0bf528SMauro Carvalho Chehab 9399a0bf528SMauro Carvalho Chehab switch (rolloff) { 9409a0bf528SMauro Carvalho Chehab case STV090x_RO_20: 9419a0bf528SMauro Carvalho Chehab ro = 20; 9429a0bf528SMauro Carvalho Chehab break; 9439a0bf528SMauro Carvalho Chehab case STV090x_RO_25: 9449a0bf528SMauro Carvalho Chehab ro = 25; 9459a0bf528SMauro Carvalho Chehab break; 9469a0bf528SMauro Carvalho Chehab case STV090x_RO_35: 9479a0bf528SMauro Carvalho Chehab default: 9489a0bf528SMauro Carvalho Chehab ro = 35; 9499a0bf528SMauro Carvalho Chehab break; 9509a0bf528SMauro Carvalho Chehab } 9519a0bf528SMauro Carvalho Chehab 9529a0bf528SMauro Carvalho Chehab return srate + (srate * ro) / 100; 9539a0bf528SMauro Carvalho Chehab } 9549a0bf528SMauro Carvalho Chehab 9559a0bf528SMauro Carvalho Chehab static int stv090x_set_vit_thacq(struct stv090x_state *state) 9569a0bf528SMauro Carvalho Chehab { 9579a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, VTH12, 0x96) < 0) 9589a0bf528SMauro Carvalho Chehab goto err; 9599a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, VTH23, 0x64) < 0) 9609a0bf528SMauro Carvalho Chehab goto err; 9619a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, VTH34, 0x36) < 0) 9629a0bf528SMauro Carvalho Chehab goto err; 9639a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, VTH56, 0x23) < 0) 9649a0bf528SMauro Carvalho Chehab goto err; 9659a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, VTH67, 0x1e) < 0) 9669a0bf528SMauro Carvalho Chehab goto err; 9679a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, VTH78, 0x19) < 0) 9689a0bf528SMauro Carvalho Chehab goto err; 9699a0bf528SMauro Carvalho Chehab return 0; 9709a0bf528SMauro Carvalho Chehab err: 9719a0bf528SMauro Carvalho Chehab dprintk(FE_ERROR, 1, "I/O error"); 9729a0bf528SMauro Carvalho Chehab return -1; 9739a0bf528SMauro Carvalho Chehab } 9749a0bf528SMauro Carvalho Chehab 9759a0bf528SMauro Carvalho Chehab static int stv090x_set_vit_thtracq(struct stv090x_state *state) 9769a0bf528SMauro Carvalho Chehab { 9779a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, VTH12, 0xd0) < 0) 9789a0bf528SMauro Carvalho Chehab goto err; 9799a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, VTH23, 0x7d) < 0) 9809a0bf528SMauro Carvalho Chehab goto err; 9819a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, VTH34, 0x53) < 0) 9829a0bf528SMauro Carvalho Chehab goto err; 9839a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, VTH56, 0x2f) < 0) 9849a0bf528SMauro Carvalho Chehab goto err; 9859a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, VTH67, 0x24) < 0) 9869a0bf528SMauro Carvalho Chehab goto err; 9879a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, VTH78, 0x1f) < 0) 9889a0bf528SMauro Carvalho Chehab goto err; 9899a0bf528SMauro Carvalho Chehab return 0; 9909a0bf528SMauro Carvalho Chehab err: 9919a0bf528SMauro Carvalho Chehab dprintk(FE_ERROR, 1, "I/O error"); 9929a0bf528SMauro Carvalho Chehab return -1; 9939a0bf528SMauro Carvalho Chehab } 9949a0bf528SMauro Carvalho Chehab 9959a0bf528SMauro Carvalho Chehab static int stv090x_set_viterbi(struct stv090x_state *state) 9969a0bf528SMauro Carvalho Chehab { 9979a0bf528SMauro Carvalho Chehab switch (state->search_mode) { 9989a0bf528SMauro Carvalho Chehab case STV090x_SEARCH_AUTO: 9999a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, FECM, 0x10) < 0) /* DVB-S and DVB-S2 */ 10009a0bf528SMauro Carvalho Chehab goto err; 10019a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, PRVIT, 0x3f) < 0) /* all puncture rate */ 10029a0bf528SMauro Carvalho Chehab goto err; 10039a0bf528SMauro Carvalho Chehab break; 10049a0bf528SMauro Carvalho Chehab case STV090x_SEARCH_DVBS1: 10059a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, FECM, 0x00) < 0) /* disable DSS */ 10069a0bf528SMauro Carvalho Chehab goto err; 10079a0bf528SMauro Carvalho Chehab switch (state->fec) { 10089a0bf528SMauro Carvalho Chehab case STV090x_PR12: 10099a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, PRVIT, 0x01) < 0) 10109a0bf528SMauro Carvalho Chehab goto err; 10119a0bf528SMauro Carvalho Chehab break; 10129a0bf528SMauro Carvalho Chehab 10139a0bf528SMauro Carvalho Chehab case STV090x_PR23: 10149a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, PRVIT, 0x02) < 0) 10159a0bf528SMauro Carvalho Chehab goto err; 10169a0bf528SMauro Carvalho Chehab break; 10179a0bf528SMauro Carvalho Chehab 10189a0bf528SMauro Carvalho Chehab case STV090x_PR34: 10199a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, PRVIT, 0x04) < 0) 10209a0bf528SMauro Carvalho Chehab goto err; 10219a0bf528SMauro Carvalho Chehab break; 10229a0bf528SMauro Carvalho Chehab 10239a0bf528SMauro Carvalho Chehab case STV090x_PR56: 10249a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, PRVIT, 0x08) < 0) 10259a0bf528SMauro Carvalho Chehab goto err; 10269a0bf528SMauro Carvalho Chehab break; 10279a0bf528SMauro Carvalho Chehab 10289a0bf528SMauro Carvalho Chehab case STV090x_PR78: 10299a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, PRVIT, 0x20) < 0) 10309a0bf528SMauro Carvalho Chehab goto err; 10319a0bf528SMauro Carvalho Chehab break; 10329a0bf528SMauro Carvalho Chehab 10339a0bf528SMauro Carvalho Chehab default: 10349a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, PRVIT, 0x2f) < 0) /* all */ 10359a0bf528SMauro Carvalho Chehab goto err; 10369a0bf528SMauro Carvalho Chehab break; 10379a0bf528SMauro Carvalho Chehab } 10389a0bf528SMauro Carvalho Chehab break; 10399a0bf528SMauro Carvalho Chehab case STV090x_SEARCH_DSS: 10409a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, FECM, 0x80) < 0) 10419a0bf528SMauro Carvalho Chehab goto err; 10429a0bf528SMauro Carvalho Chehab switch (state->fec) { 10439a0bf528SMauro Carvalho Chehab case STV090x_PR12: 10449a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, PRVIT, 0x01) < 0) 10459a0bf528SMauro Carvalho Chehab goto err; 10469a0bf528SMauro Carvalho Chehab break; 10479a0bf528SMauro Carvalho Chehab 10489a0bf528SMauro Carvalho Chehab case STV090x_PR23: 10499a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, PRVIT, 0x02) < 0) 10509a0bf528SMauro Carvalho Chehab goto err; 10519a0bf528SMauro Carvalho Chehab break; 10529a0bf528SMauro Carvalho Chehab 10539a0bf528SMauro Carvalho Chehab case STV090x_PR67: 10549a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, PRVIT, 0x10) < 0) 10559a0bf528SMauro Carvalho Chehab goto err; 10569a0bf528SMauro Carvalho Chehab break; 10579a0bf528SMauro Carvalho Chehab 10589a0bf528SMauro Carvalho Chehab default: 10599a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, PRVIT, 0x13) < 0) /* 1/2, 2/3, 6/7 */ 10609a0bf528SMauro Carvalho Chehab goto err; 10619a0bf528SMauro Carvalho Chehab break; 10629a0bf528SMauro Carvalho Chehab } 10639a0bf528SMauro Carvalho Chehab break; 10649a0bf528SMauro Carvalho Chehab default: 10659a0bf528SMauro Carvalho Chehab break; 10669a0bf528SMauro Carvalho Chehab } 10679a0bf528SMauro Carvalho Chehab return 0; 10689a0bf528SMauro Carvalho Chehab err: 10699a0bf528SMauro Carvalho Chehab dprintk(FE_ERROR, 1, "I/O error"); 10709a0bf528SMauro Carvalho Chehab return -1; 10719a0bf528SMauro Carvalho Chehab } 10729a0bf528SMauro Carvalho Chehab 10739a0bf528SMauro Carvalho Chehab static int stv090x_stop_modcod(struct stv090x_state *state) 10749a0bf528SMauro Carvalho Chehab { 10759a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, MODCODLST0, 0xff) < 0) 10769a0bf528SMauro Carvalho Chehab goto err; 10779a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, MODCODLST1, 0xff) < 0) 10789a0bf528SMauro Carvalho Chehab goto err; 10799a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, MODCODLST2, 0xff) < 0) 10809a0bf528SMauro Carvalho Chehab goto err; 10819a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, MODCODLST3, 0xff) < 0) 10829a0bf528SMauro Carvalho Chehab goto err; 10839a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, MODCODLST4, 0xff) < 0) 10849a0bf528SMauro Carvalho Chehab goto err; 10859a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, MODCODLST5, 0xff) < 0) 10869a0bf528SMauro Carvalho Chehab goto err; 10879a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, MODCODLST6, 0xff) < 0) 10889a0bf528SMauro Carvalho Chehab goto err; 10899a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, MODCODLST7, 0xff) < 0) 10909a0bf528SMauro Carvalho Chehab goto err; 10919a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, MODCODLST8, 0xff) < 0) 10929a0bf528SMauro Carvalho Chehab goto err; 10939a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, MODCODLST9, 0xff) < 0) 10949a0bf528SMauro Carvalho Chehab goto err; 10959a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, MODCODLSTA, 0xff) < 0) 10969a0bf528SMauro Carvalho Chehab goto err; 10979a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, MODCODLSTB, 0xff) < 0) 10989a0bf528SMauro Carvalho Chehab goto err; 10999a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, MODCODLSTC, 0xff) < 0) 11009a0bf528SMauro Carvalho Chehab goto err; 11019a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, MODCODLSTD, 0xff) < 0) 11029a0bf528SMauro Carvalho Chehab goto err; 11039a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, MODCODLSTE, 0xff) < 0) 11049a0bf528SMauro Carvalho Chehab goto err; 11059a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, MODCODLSTF, 0xff) < 0) 11069a0bf528SMauro Carvalho Chehab goto err; 11079a0bf528SMauro Carvalho Chehab return 0; 11089a0bf528SMauro Carvalho Chehab err: 11099a0bf528SMauro Carvalho Chehab dprintk(FE_ERROR, 1, "I/O error"); 11109a0bf528SMauro Carvalho Chehab return -1; 11119a0bf528SMauro Carvalho Chehab } 11129a0bf528SMauro Carvalho Chehab 11139a0bf528SMauro Carvalho Chehab static int stv090x_activate_modcod(struct stv090x_state *state) 11149a0bf528SMauro Carvalho Chehab { 11159a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, MODCODLST0, 0xff) < 0) 11169a0bf528SMauro Carvalho Chehab goto err; 11179a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, MODCODLST1, 0xfc) < 0) 11189a0bf528SMauro Carvalho Chehab goto err; 11199a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, MODCODLST2, 0xcc) < 0) 11209a0bf528SMauro Carvalho Chehab goto err; 11219a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, MODCODLST3, 0xcc) < 0) 11229a0bf528SMauro Carvalho Chehab goto err; 11239a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, MODCODLST4, 0xcc) < 0) 11249a0bf528SMauro Carvalho Chehab goto err; 11259a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, MODCODLST5, 0xcc) < 0) 11269a0bf528SMauro Carvalho Chehab goto err; 11279a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, MODCODLST6, 0xcc) < 0) 11289a0bf528SMauro Carvalho Chehab goto err; 11299a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, MODCODLST7, 0xcc) < 0) 11309a0bf528SMauro Carvalho Chehab goto err; 11319a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, MODCODLST8, 0xcc) < 0) 11329a0bf528SMauro Carvalho Chehab goto err; 11339a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, MODCODLST9, 0xcc) < 0) 11349a0bf528SMauro Carvalho Chehab goto err; 11359a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, MODCODLSTA, 0xcc) < 0) 11369a0bf528SMauro Carvalho Chehab goto err; 11379a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, MODCODLSTB, 0xcc) < 0) 11389a0bf528SMauro Carvalho Chehab goto err; 11399a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, MODCODLSTC, 0xcc) < 0) 11409a0bf528SMauro Carvalho Chehab goto err; 11419a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, MODCODLSTD, 0xcc) < 0) 11429a0bf528SMauro Carvalho Chehab goto err; 11439a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, MODCODLSTE, 0xcc) < 0) 11449a0bf528SMauro Carvalho Chehab goto err; 11459a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, MODCODLSTF, 0xcf) < 0) 11469a0bf528SMauro Carvalho Chehab goto err; 11479a0bf528SMauro Carvalho Chehab 11489a0bf528SMauro Carvalho Chehab return 0; 11499a0bf528SMauro Carvalho Chehab err: 11509a0bf528SMauro Carvalho Chehab dprintk(FE_ERROR, 1, "I/O error"); 11519a0bf528SMauro Carvalho Chehab return -1; 11529a0bf528SMauro Carvalho Chehab } 11539a0bf528SMauro Carvalho Chehab 11549a0bf528SMauro Carvalho Chehab static int stv090x_activate_modcod_single(struct stv090x_state *state) 11559a0bf528SMauro Carvalho Chehab { 11569a0bf528SMauro Carvalho Chehab 11579a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, MODCODLST0, 0xff) < 0) 11589a0bf528SMauro Carvalho Chehab goto err; 11599a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, MODCODLST1, 0xf0) < 0) 11609a0bf528SMauro Carvalho Chehab goto err; 11619a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, MODCODLST2, 0x00) < 0) 11629a0bf528SMauro Carvalho Chehab goto err; 11639a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, MODCODLST3, 0x00) < 0) 11649a0bf528SMauro Carvalho Chehab goto err; 11659a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, MODCODLST4, 0x00) < 0) 11669a0bf528SMauro Carvalho Chehab goto err; 11679a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, MODCODLST5, 0x00) < 0) 11689a0bf528SMauro Carvalho Chehab goto err; 11699a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, MODCODLST6, 0x00) < 0) 11709a0bf528SMauro Carvalho Chehab goto err; 11719a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, MODCODLST7, 0x00) < 0) 11729a0bf528SMauro Carvalho Chehab goto err; 11739a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, MODCODLST8, 0x00) < 0) 11749a0bf528SMauro Carvalho Chehab goto err; 11759a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, MODCODLST9, 0x00) < 0) 11769a0bf528SMauro Carvalho Chehab goto err; 11779a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, MODCODLSTA, 0x00) < 0) 11789a0bf528SMauro Carvalho Chehab goto err; 11799a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, MODCODLSTB, 0x00) < 0) 11809a0bf528SMauro Carvalho Chehab goto err; 11819a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, MODCODLSTC, 0x00) < 0) 11829a0bf528SMauro Carvalho Chehab goto err; 11839a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, MODCODLSTD, 0x00) < 0) 11849a0bf528SMauro Carvalho Chehab goto err; 11859a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, MODCODLSTE, 0x00) < 0) 11869a0bf528SMauro Carvalho Chehab goto err; 11879a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, MODCODLSTF, 0x0f) < 0) 11889a0bf528SMauro Carvalho Chehab goto err; 11899a0bf528SMauro Carvalho Chehab 11909a0bf528SMauro Carvalho Chehab return 0; 11919a0bf528SMauro Carvalho Chehab 11929a0bf528SMauro Carvalho Chehab err: 11939a0bf528SMauro Carvalho Chehab dprintk(FE_ERROR, 1, "I/O error"); 11949a0bf528SMauro Carvalho Chehab return -1; 11959a0bf528SMauro Carvalho Chehab } 11969a0bf528SMauro Carvalho Chehab 11979a0bf528SMauro Carvalho Chehab static int stv090x_vitclk_ctl(struct stv090x_state *state, int enable) 11989a0bf528SMauro Carvalho Chehab { 11999a0bf528SMauro Carvalho Chehab u32 reg; 12009a0bf528SMauro Carvalho Chehab 12019a0bf528SMauro Carvalho Chehab switch (state->demod) { 12029a0bf528SMauro Carvalho Chehab case STV090x_DEMODULATOR_0: 12039a0bf528SMauro Carvalho Chehab mutex_lock(&state->internal->demod_lock); 12049a0bf528SMauro Carvalho Chehab reg = stv090x_read_reg(state, STV090x_STOPCLK2); 12059a0bf528SMauro Carvalho Chehab STV090x_SETFIELD(reg, STOP_CLKVIT1_FIELD, enable); 12069a0bf528SMauro Carvalho Chehab if (stv090x_write_reg(state, STV090x_STOPCLK2, reg) < 0) 12079a0bf528SMauro Carvalho Chehab goto err; 12089a0bf528SMauro Carvalho Chehab mutex_unlock(&state->internal->demod_lock); 12099a0bf528SMauro Carvalho Chehab break; 12109a0bf528SMauro Carvalho Chehab 12119a0bf528SMauro Carvalho Chehab case STV090x_DEMODULATOR_1: 12129a0bf528SMauro Carvalho Chehab mutex_lock(&state->internal->demod_lock); 12139a0bf528SMauro Carvalho Chehab reg = stv090x_read_reg(state, STV090x_STOPCLK2); 12149a0bf528SMauro Carvalho Chehab STV090x_SETFIELD(reg, STOP_CLKVIT2_FIELD, enable); 12159a0bf528SMauro Carvalho Chehab if (stv090x_write_reg(state, STV090x_STOPCLK2, reg) < 0) 12169a0bf528SMauro Carvalho Chehab goto err; 12179a0bf528SMauro Carvalho Chehab mutex_unlock(&state->internal->demod_lock); 12189a0bf528SMauro Carvalho Chehab break; 12199a0bf528SMauro Carvalho Chehab 12209a0bf528SMauro Carvalho Chehab default: 12219a0bf528SMauro Carvalho Chehab dprintk(FE_ERROR, 1, "Wrong demodulator!"); 12229a0bf528SMauro Carvalho Chehab break; 12239a0bf528SMauro Carvalho Chehab } 12249a0bf528SMauro Carvalho Chehab return 0; 12259a0bf528SMauro Carvalho Chehab err: 12269a0bf528SMauro Carvalho Chehab mutex_unlock(&state->internal->demod_lock); 12279a0bf528SMauro Carvalho Chehab dprintk(FE_ERROR, 1, "I/O error"); 12289a0bf528SMauro Carvalho Chehab return -1; 12299a0bf528SMauro Carvalho Chehab } 12309a0bf528SMauro Carvalho Chehab 12319a0bf528SMauro Carvalho Chehab static int stv090x_dvbs_track_crl(struct stv090x_state *state) 12329a0bf528SMauro Carvalho Chehab { 12339a0bf528SMauro Carvalho Chehab if (state->internal->dev_ver >= 0x30) { 12349a0bf528SMauro Carvalho Chehab /* Set ACLC BCLC optimised value vs SR */ 12359a0bf528SMauro Carvalho Chehab if (state->srate >= 15000000) { 12369a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, ACLC, 0x2b) < 0) 12379a0bf528SMauro Carvalho Chehab goto err; 12389a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, BCLC, 0x1a) < 0) 12399a0bf528SMauro Carvalho Chehab goto err; 12409a0bf528SMauro Carvalho Chehab } else if ((state->srate >= 7000000) && (15000000 > state->srate)) { 12419a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, ACLC, 0x0c) < 0) 12429a0bf528SMauro Carvalho Chehab goto err; 12439a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, BCLC, 0x1b) < 0) 12449a0bf528SMauro Carvalho Chehab goto err; 12459a0bf528SMauro Carvalho Chehab } else if (state->srate < 7000000) { 12469a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, ACLC, 0x2c) < 0) 12479a0bf528SMauro Carvalho Chehab goto err; 12489a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, BCLC, 0x1c) < 0) 12499a0bf528SMauro Carvalho Chehab goto err; 12509a0bf528SMauro Carvalho Chehab } 12519a0bf528SMauro Carvalho Chehab 12529a0bf528SMauro Carvalho Chehab } else { 12539a0bf528SMauro Carvalho Chehab /* Cut 2.0 */ 12549a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, ACLC, 0x1a) < 0) 12559a0bf528SMauro Carvalho Chehab goto err; 12569a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, BCLC, 0x09) < 0) 12579a0bf528SMauro Carvalho Chehab goto err; 12589a0bf528SMauro Carvalho Chehab } 12599a0bf528SMauro Carvalho Chehab return 0; 12609a0bf528SMauro Carvalho Chehab err: 12619a0bf528SMauro Carvalho Chehab dprintk(FE_ERROR, 1, "I/O error"); 12629a0bf528SMauro Carvalho Chehab return -1; 12639a0bf528SMauro Carvalho Chehab } 12649a0bf528SMauro Carvalho Chehab 12659a0bf528SMauro Carvalho Chehab static int stv090x_delivery_search(struct stv090x_state *state) 12669a0bf528SMauro Carvalho Chehab { 12679a0bf528SMauro Carvalho Chehab u32 reg; 12689a0bf528SMauro Carvalho Chehab 12699a0bf528SMauro Carvalho Chehab switch (state->search_mode) { 12709a0bf528SMauro Carvalho Chehab case STV090x_SEARCH_DVBS1: 12719a0bf528SMauro Carvalho Chehab case STV090x_SEARCH_DSS: 12729a0bf528SMauro Carvalho Chehab reg = STV090x_READ_DEMOD(state, DMDCFGMD); 12739a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, DVBS1_ENABLE_FIELD, 1); 12749a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, DVBS2_ENABLE_FIELD, 0); 12759a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0) 12769a0bf528SMauro Carvalho Chehab goto err; 12779a0bf528SMauro Carvalho Chehab 12789a0bf528SMauro Carvalho Chehab /* Activate Viterbi decoder in legacy search, 12799a0bf528SMauro Carvalho Chehab * do not use FRESVIT1, might impact VITERBI2 12809a0bf528SMauro Carvalho Chehab */ 12819a0bf528SMauro Carvalho Chehab if (stv090x_vitclk_ctl(state, 0) < 0) 12829a0bf528SMauro Carvalho Chehab goto err; 12839a0bf528SMauro Carvalho Chehab 12849a0bf528SMauro Carvalho Chehab if (stv090x_dvbs_track_crl(state) < 0) 12859a0bf528SMauro Carvalho Chehab goto err; 12869a0bf528SMauro Carvalho Chehab 12879a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, CAR2CFG, 0x22) < 0) /* disable DVB-S2 */ 12889a0bf528SMauro Carvalho Chehab goto err; 12899a0bf528SMauro Carvalho Chehab 12909a0bf528SMauro Carvalho Chehab if (stv090x_set_vit_thacq(state) < 0) 12919a0bf528SMauro Carvalho Chehab goto err; 12929a0bf528SMauro Carvalho Chehab if (stv090x_set_viterbi(state) < 0) 12939a0bf528SMauro Carvalho Chehab goto err; 12949a0bf528SMauro Carvalho Chehab break; 12959a0bf528SMauro Carvalho Chehab 12969a0bf528SMauro Carvalho Chehab case STV090x_SEARCH_DVBS2: 12979a0bf528SMauro Carvalho Chehab reg = STV090x_READ_DEMOD(state, DMDCFGMD); 12989a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, DVBS1_ENABLE_FIELD, 0); 12999a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, DVBS2_ENABLE_FIELD, 0); 13009a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0) 13019a0bf528SMauro Carvalho Chehab goto err; 13029a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, DVBS1_ENABLE_FIELD, 1); 13039a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, DVBS2_ENABLE_FIELD, 1); 13049a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0) 13059a0bf528SMauro Carvalho Chehab goto err; 13069a0bf528SMauro Carvalho Chehab 13079a0bf528SMauro Carvalho Chehab if (stv090x_vitclk_ctl(state, 1) < 0) 13089a0bf528SMauro Carvalho Chehab goto err; 13099a0bf528SMauro Carvalho Chehab 13109a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, ACLC, 0x1a) < 0) /* stop DVB-S CR loop */ 13119a0bf528SMauro Carvalho Chehab goto err; 13129a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, BCLC, 0x09) < 0) 13139a0bf528SMauro Carvalho Chehab goto err; 13149a0bf528SMauro Carvalho Chehab 13159a0bf528SMauro Carvalho Chehab if (state->internal->dev_ver <= 0x20) { 13169a0bf528SMauro Carvalho Chehab /* enable S2 carrier loop */ 13179a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, CAR2CFG, 0x26) < 0) 13189a0bf528SMauro Carvalho Chehab goto err; 13199a0bf528SMauro Carvalho Chehab } else { 13209a0bf528SMauro Carvalho Chehab /* > Cut 3: Stop carrier 3 */ 13219a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, CAR2CFG, 0x66) < 0) 13229a0bf528SMauro Carvalho Chehab goto err; 13239a0bf528SMauro Carvalho Chehab } 13249a0bf528SMauro Carvalho Chehab 13259a0bf528SMauro Carvalho Chehab if (state->demod_mode != STV090x_SINGLE) { 13269a0bf528SMauro Carvalho Chehab /* Cut 2: enable link during search */ 13279a0bf528SMauro Carvalho Chehab if (stv090x_activate_modcod(state) < 0) 13289a0bf528SMauro Carvalho Chehab goto err; 13299a0bf528SMauro Carvalho Chehab } else { 13309a0bf528SMauro Carvalho Chehab /* Single demodulator 13319a0bf528SMauro Carvalho Chehab * Authorize SHORT and LONG frames, 13329a0bf528SMauro Carvalho Chehab * QPSK, 8PSK, 16APSK and 32APSK 13339a0bf528SMauro Carvalho Chehab */ 13349a0bf528SMauro Carvalho Chehab if (stv090x_activate_modcod_single(state) < 0) 13359a0bf528SMauro Carvalho Chehab goto err; 13369a0bf528SMauro Carvalho Chehab } 13379a0bf528SMauro Carvalho Chehab 13389a0bf528SMauro Carvalho Chehab if (stv090x_set_vit_thtracq(state) < 0) 13399a0bf528SMauro Carvalho Chehab goto err; 13409a0bf528SMauro Carvalho Chehab break; 13419a0bf528SMauro Carvalho Chehab 13429a0bf528SMauro Carvalho Chehab case STV090x_SEARCH_AUTO: 13439a0bf528SMauro Carvalho Chehab default: 13449a0bf528SMauro Carvalho Chehab /* enable DVB-S2 and DVB-S2 in Auto MODE */ 13459a0bf528SMauro Carvalho Chehab reg = STV090x_READ_DEMOD(state, DMDCFGMD); 13469a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, DVBS1_ENABLE_FIELD, 0); 13479a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, DVBS2_ENABLE_FIELD, 0); 13489a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0) 13499a0bf528SMauro Carvalho Chehab goto err; 13509a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, DVBS1_ENABLE_FIELD, 1); 13519a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, DVBS2_ENABLE_FIELD, 1); 13529a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0) 13539a0bf528SMauro Carvalho Chehab goto err; 13549a0bf528SMauro Carvalho Chehab 13559a0bf528SMauro Carvalho Chehab if (stv090x_vitclk_ctl(state, 0) < 0) 13569a0bf528SMauro Carvalho Chehab goto err; 13579a0bf528SMauro Carvalho Chehab 13589a0bf528SMauro Carvalho Chehab if (stv090x_dvbs_track_crl(state) < 0) 13599a0bf528SMauro Carvalho Chehab goto err; 13609a0bf528SMauro Carvalho Chehab 13619a0bf528SMauro Carvalho Chehab if (state->internal->dev_ver <= 0x20) { 13629a0bf528SMauro Carvalho Chehab /* enable S2 carrier loop */ 13639a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, CAR2CFG, 0x26) < 0) 13649a0bf528SMauro Carvalho Chehab goto err; 13659a0bf528SMauro Carvalho Chehab } else { 13669a0bf528SMauro Carvalho Chehab /* > Cut 3: Stop carrier 3 */ 13679a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, CAR2CFG, 0x66) < 0) 13689a0bf528SMauro Carvalho Chehab goto err; 13699a0bf528SMauro Carvalho Chehab } 13709a0bf528SMauro Carvalho Chehab 13719a0bf528SMauro Carvalho Chehab if (state->demod_mode != STV090x_SINGLE) { 13729a0bf528SMauro Carvalho Chehab /* Cut 2: enable link during search */ 13739a0bf528SMauro Carvalho Chehab if (stv090x_activate_modcod(state) < 0) 13749a0bf528SMauro Carvalho Chehab goto err; 13759a0bf528SMauro Carvalho Chehab } else { 13769a0bf528SMauro Carvalho Chehab /* Single demodulator 13779a0bf528SMauro Carvalho Chehab * Authorize SHORT and LONG frames, 13789a0bf528SMauro Carvalho Chehab * QPSK, 8PSK, 16APSK and 32APSK 13799a0bf528SMauro Carvalho Chehab */ 13809a0bf528SMauro Carvalho Chehab if (stv090x_activate_modcod_single(state) < 0) 13819a0bf528SMauro Carvalho Chehab goto err; 13829a0bf528SMauro Carvalho Chehab } 13839a0bf528SMauro Carvalho Chehab 13849a0bf528SMauro Carvalho Chehab if (stv090x_set_vit_thacq(state) < 0) 13859a0bf528SMauro Carvalho Chehab goto err; 13869a0bf528SMauro Carvalho Chehab 13879a0bf528SMauro Carvalho Chehab if (stv090x_set_viterbi(state) < 0) 13889a0bf528SMauro Carvalho Chehab goto err; 13899a0bf528SMauro Carvalho Chehab break; 13909a0bf528SMauro Carvalho Chehab } 13919a0bf528SMauro Carvalho Chehab return 0; 13929a0bf528SMauro Carvalho Chehab err: 13939a0bf528SMauro Carvalho Chehab dprintk(FE_ERROR, 1, "I/O error"); 13949a0bf528SMauro Carvalho Chehab return -1; 13959a0bf528SMauro Carvalho Chehab } 13969a0bf528SMauro Carvalho Chehab 13979a0bf528SMauro Carvalho Chehab static int stv090x_start_search(struct stv090x_state *state) 13989a0bf528SMauro Carvalho Chehab { 13999a0bf528SMauro Carvalho Chehab u32 reg, freq_abs; 14009a0bf528SMauro Carvalho Chehab s16 freq; 14019a0bf528SMauro Carvalho Chehab 14029a0bf528SMauro Carvalho Chehab /* Reset demodulator */ 14039a0bf528SMauro Carvalho Chehab reg = STV090x_READ_DEMOD(state, DMDISTATE); 14049a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, I2C_DEMOD_MODE_FIELD, 0x1f); 14059a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, DMDISTATE, reg) < 0) 14069a0bf528SMauro Carvalho Chehab goto err; 14079a0bf528SMauro Carvalho Chehab 14089a0bf528SMauro Carvalho Chehab if (state->internal->dev_ver <= 0x20) { 14099a0bf528SMauro Carvalho Chehab if (state->srate <= 5000000) { 14109a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, CARCFG, 0x44) < 0) 14119a0bf528SMauro Carvalho Chehab goto err; 14129a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, CFRUP1, 0x0f) < 0) 14139a0bf528SMauro Carvalho Chehab goto err; 14149a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, CFRUP0, 0xff) < 0) 14159a0bf528SMauro Carvalho Chehab goto err; 14169a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, CFRLOW1, 0xf0) < 0) 14179a0bf528SMauro Carvalho Chehab goto err; 14189a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, CFRLOW0, 0x00) < 0) 14199a0bf528SMauro Carvalho Chehab goto err; 14209a0bf528SMauro Carvalho Chehab 14219a0bf528SMauro Carvalho Chehab /*enlarge the timing bandwidth for Low SR*/ 14229a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, RTCS2, 0x68) < 0) 14239a0bf528SMauro Carvalho Chehab goto err; 14249a0bf528SMauro Carvalho Chehab } else { 14259a0bf528SMauro Carvalho Chehab /* If the symbol rate is >5 Msps 14269a0bf528SMauro Carvalho Chehab Set The carrier search up and low to auto mode */ 14279a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, CARCFG, 0xc4) < 0) 14289a0bf528SMauro Carvalho Chehab goto err; 14299a0bf528SMauro Carvalho Chehab /*reduce the timing bandwidth for high SR*/ 14309a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, RTCS2, 0x44) < 0) 14319a0bf528SMauro Carvalho Chehab goto err; 14329a0bf528SMauro Carvalho Chehab } 14339a0bf528SMauro Carvalho Chehab } else { 14349a0bf528SMauro Carvalho Chehab /* >= Cut 3 */ 14359a0bf528SMauro Carvalho Chehab if (state->srate <= 5000000) { 14369a0bf528SMauro Carvalho Chehab /* enlarge the timing bandwidth for Low SR */ 14379a0bf528SMauro Carvalho Chehab STV090x_WRITE_DEMOD(state, RTCS2, 0x68); 14389a0bf528SMauro Carvalho Chehab } else { 14399a0bf528SMauro Carvalho Chehab /* reduce timing bandwidth for high SR */ 14409a0bf528SMauro Carvalho Chehab STV090x_WRITE_DEMOD(state, RTCS2, 0x44); 14419a0bf528SMauro Carvalho Chehab } 14429a0bf528SMauro Carvalho Chehab 14439a0bf528SMauro Carvalho Chehab /* Set CFR min and max to manual mode */ 14449a0bf528SMauro Carvalho Chehab STV090x_WRITE_DEMOD(state, CARCFG, 0x46); 14459a0bf528SMauro Carvalho Chehab 14469a0bf528SMauro Carvalho Chehab if (state->algo == STV090x_WARM_SEARCH) { 14479a0bf528SMauro Carvalho Chehab /* WARM Start 14489a0bf528SMauro Carvalho Chehab * CFR min = -1MHz, 14499a0bf528SMauro Carvalho Chehab * CFR max = +1MHz 14509a0bf528SMauro Carvalho Chehab */ 14519a0bf528SMauro Carvalho Chehab freq_abs = 1000 << 16; 14529a0bf528SMauro Carvalho Chehab freq_abs /= (state->internal->mclk / 1000); 14539a0bf528SMauro Carvalho Chehab freq = (s16) freq_abs; 14549a0bf528SMauro Carvalho Chehab } else { 14559a0bf528SMauro Carvalho Chehab /* COLD Start 14569a0bf528SMauro Carvalho Chehab * CFR min =- (SearchRange / 2 + 600KHz) 14579a0bf528SMauro Carvalho Chehab * CFR max = +(SearchRange / 2 + 600KHz) 14589a0bf528SMauro Carvalho Chehab * (600KHz for the tuner step size) 14599a0bf528SMauro Carvalho Chehab */ 14609a0bf528SMauro Carvalho Chehab freq_abs = (state->search_range / 2000) + 600; 14619a0bf528SMauro Carvalho Chehab freq_abs = freq_abs << 16; 14629a0bf528SMauro Carvalho Chehab freq_abs /= (state->internal->mclk / 1000); 14639a0bf528SMauro Carvalho Chehab freq = (s16) freq_abs; 14649a0bf528SMauro Carvalho Chehab } 14659a0bf528SMauro Carvalho Chehab 14669a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, CFRUP1, MSB(freq)) < 0) 14679a0bf528SMauro Carvalho Chehab goto err; 14689a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, CFRUP0, LSB(freq)) < 0) 14699a0bf528SMauro Carvalho Chehab goto err; 14709a0bf528SMauro Carvalho Chehab 14719a0bf528SMauro Carvalho Chehab freq *= -1; 14729a0bf528SMauro Carvalho Chehab 14739a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, CFRLOW1, MSB(freq)) < 0) 14749a0bf528SMauro Carvalho Chehab goto err; 14759a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, CFRLOW0, LSB(freq)) < 0) 14769a0bf528SMauro Carvalho Chehab goto err; 14779a0bf528SMauro Carvalho Chehab 14789a0bf528SMauro Carvalho Chehab } 14799a0bf528SMauro Carvalho Chehab 14809a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, CFRINIT1, 0) < 0) 14819a0bf528SMauro Carvalho Chehab goto err; 14829a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, CFRINIT0, 0) < 0) 14839a0bf528SMauro Carvalho Chehab goto err; 14849a0bf528SMauro Carvalho Chehab 14859a0bf528SMauro Carvalho Chehab if (state->internal->dev_ver >= 0x20) { 14869a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, EQUALCFG, 0x41) < 0) 14879a0bf528SMauro Carvalho Chehab goto err; 14889a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, FFECFG, 0x41) < 0) 14899a0bf528SMauro Carvalho Chehab goto err; 14909a0bf528SMauro Carvalho Chehab 14919a0bf528SMauro Carvalho Chehab if ((state->search_mode == STV090x_SEARCH_DVBS1) || 14929a0bf528SMauro Carvalho Chehab (state->search_mode == STV090x_SEARCH_DSS) || 14939a0bf528SMauro Carvalho Chehab (state->search_mode == STV090x_SEARCH_AUTO)) { 14949a0bf528SMauro Carvalho Chehab 14959a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, VITSCALE, 0x82) < 0) 14969a0bf528SMauro Carvalho Chehab goto err; 14979a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, VAVSRVIT, 0x00) < 0) 14989a0bf528SMauro Carvalho Chehab goto err; 14999a0bf528SMauro Carvalho Chehab } 15009a0bf528SMauro Carvalho Chehab } 15019a0bf528SMauro Carvalho Chehab 15029a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, SFRSTEP, 0x00) < 0) 15039a0bf528SMauro Carvalho Chehab goto err; 15049a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, TMGTHRISE, 0xe0) < 0) 15059a0bf528SMauro Carvalho Chehab goto err; 15069a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, TMGTHFALL, 0xc0) < 0) 15079a0bf528SMauro Carvalho Chehab goto err; 15089a0bf528SMauro Carvalho Chehab 15099a0bf528SMauro Carvalho Chehab reg = STV090x_READ_DEMOD(state, DMDCFGMD); 15109a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, SCAN_ENABLE_FIELD, 0); 15119a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, CFR_AUTOSCAN_FIELD, 0); 15129a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0) 15139a0bf528SMauro Carvalho Chehab goto err; 15149a0bf528SMauro Carvalho Chehab reg = STV090x_READ_DEMOD(state, DMDCFG2); 15159a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, S1S2_SEQUENTIAL_FIELD, 0x0); 15169a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, DMDCFG2, reg) < 0) 15179a0bf528SMauro Carvalho Chehab goto err; 15189a0bf528SMauro Carvalho Chehab 15199a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, RTC, 0x88) < 0) 15209a0bf528SMauro Carvalho Chehab goto err; 15219a0bf528SMauro Carvalho Chehab 15229a0bf528SMauro Carvalho Chehab if (state->internal->dev_ver >= 0x20) { 15239a0bf528SMauro Carvalho Chehab /*Frequency offset detector setting*/ 15249a0bf528SMauro Carvalho Chehab if (state->srate < 2000000) { 15259a0bf528SMauro Carvalho Chehab if (state->internal->dev_ver <= 0x20) { 15269a0bf528SMauro Carvalho Chehab /* Cut 2 */ 15279a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x39) < 0) 15289a0bf528SMauro Carvalho Chehab goto err; 15299a0bf528SMauro Carvalho Chehab } else { 15309a0bf528SMauro Carvalho Chehab /* Cut 3 */ 15319a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x89) < 0) 15329a0bf528SMauro Carvalho Chehab goto err; 15339a0bf528SMauro Carvalho Chehab } 15349a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, CARHDR, 0x40) < 0) 15359a0bf528SMauro Carvalho Chehab goto err; 15369a0bf528SMauro Carvalho Chehab } else if (state->srate < 10000000) { 15379a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x4c) < 0) 15389a0bf528SMauro Carvalho Chehab goto err; 15399a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, CARHDR, 0x20) < 0) 15409a0bf528SMauro Carvalho Chehab goto err; 15419a0bf528SMauro Carvalho Chehab } else { 15429a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x4b) < 0) 15439a0bf528SMauro Carvalho Chehab goto err; 15449a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, CARHDR, 0x20) < 0) 15459a0bf528SMauro Carvalho Chehab goto err; 15469a0bf528SMauro Carvalho Chehab } 15479a0bf528SMauro Carvalho Chehab } else { 15489a0bf528SMauro Carvalho Chehab if (state->srate < 10000000) { 15499a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, CARFREQ, 0xef) < 0) 15509a0bf528SMauro Carvalho Chehab goto err; 15519a0bf528SMauro Carvalho Chehab } else { 15529a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, CARFREQ, 0xed) < 0) 15539a0bf528SMauro Carvalho Chehab goto err; 15549a0bf528SMauro Carvalho Chehab } 15559a0bf528SMauro Carvalho Chehab } 15569a0bf528SMauro Carvalho Chehab 15579a0bf528SMauro Carvalho Chehab switch (state->algo) { 15589a0bf528SMauro Carvalho Chehab case STV090x_WARM_SEARCH: 15599a0bf528SMauro Carvalho Chehab /* The symbol rate and the exact 15609a0bf528SMauro Carvalho Chehab * carrier Frequency are known 15619a0bf528SMauro Carvalho Chehab */ 15629a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1f) < 0) 15639a0bf528SMauro Carvalho Chehab goto err; 15649a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x18) < 0) 15659a0bf528SMauro Carvalho Chehab goto err; 15669a0bf528SMauro Carvalho Chehab break; 15679a0bf528SMauro Carvalho Chehab 15689a0bf528SMauro Carvalho Chehab case STV090x_COLD_SEARCH: 15699a0bf528SMauro Carvalho Chehab /* The symbol rate is known */ 15709a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1f) < 0) 15719a0bf528SMauro Carvalho Chehab goto err; 15729a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x15) < 0) 15739a0bf528SMauro Carvalho Chehab goto err; 15749a0bf528SMauro Carvalho Chehab break; 15759a0bf528SMauro Carvalho Chehab 15769a0bf528SMauro Carvalho Chehab default: 15779a0bf528SMauro Carvalho Chehab break; 15789a0bf528SMauro Carvalho Chehab } 15799a0bf528SMauro Carvalho Chehab return 0; 15809a0bf528SMauro Carvalho Chehab err: 15819a0bf528SMauro Carvalho Chehab dprintk(FE_ERROR, 1, "I/O error"); 15829a0bf528SMauro Carvalho Chehab return -1; 15839a0bf528SMauro Carvalho Chehab } 15849a0bf528SMauro Carvalho Chehab 15859a0bf528SMauro Carvalho Chehab static int stv090x_get_agc2_min_level(struct stv090x_state *state) 15869a0bf528SMauro Carvalho Chehab { 15879a0bf528SMauro Carvalho Chehab u32 agc2_min = 0xffff, agc2 = 0, freq_init, freq_step, reg; 15889a0bf528SMauro Carvalho Chehab s32 i, j, steps, dir; 15899a0bf528SMauro Carvalho Chehab 15909a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, AGC2REF, 0x38) < 0) 15919a0bf528SMauro Carvalho Chehab goto err; 15929a0bf528SMauro Carvalho Chehab reg = STV090x_READ_DEMOD(state, DMDCFGMD); 15939a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, SCAN_ENABLE_FIELD, 0); 15949a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, CFR_AUTOSCAN_FIELD, 0); 15959a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0) 15969a0bf528SMauro Carvalho Chehab goto err; 15979a0bf528SMauro Carvalho Chehab 15989a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, SFRUP1, 0x83) < 0) /* SR = 65 Msps Max */ 15999a0bf528SMauro Carvalho Chehab goto err; 16009a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, SFRUP0, 0xc0) < 0) 16019a0bf528SMauro Carvalho Chehab goto err; 16029a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, SFRLOW1, 0x82) < 0) /* SR= 400 ksps Min */ 16039a0bf528SMauro Carvalho Chehab goto err; 16049a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, SFRLOW0, 0xa0) < 0) 16059a0bf528SMauro Carvalho Chehab goto err; 16069a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, DMDTOM, 0x00) < 0) /* stop acq @ coarse carrier state */ 16079a0bf528SMauro Carvalho Chehab goto err; 16089a0bf528SMauro Carvalho Chehab if (stv090x_set_srate(state, 1000000) < 0) 16099a0bf528SMauro Carvalho Chehab goto err; 16109a0bf528SMauro Carvalho Chehab 16119a0bf528SMauro Carvalho Chehab steps = state->search_range / 1000000; 16129a0bf528SMauro Carvalho Chehab if (steps <= 0) 16139a0bf528SMauro Carvalho Chehab steps = 1; 16149a0bf528SMauro Carvalho Chehab 16159a0bf528SMauro Carvalho Chehab dir = 1; 16169a0bf528SMauro Carvalho Chehab freq_step = (1000000 * 256) / (state->internal->mclk / 256); 16179a0bf528SMauro Carvalho Chehab freq_init = 0; 16189a0bf528SMauro Carvalho Chehab 16199a0bf528SMauro Carvalho Chehab for (i = 0; i < steps; i++) { 16209a0bf528SMauro Carvalho Chehab if (dir > 0) 16219a0bf528SMauro Carvalho Chehab freq_init = freq_init + (freq_step * i); 16229a0bf528SMauro Carvalho Chehab else 16239a0bf528SMauro Carvalho Chehab freq_init = freq_init - (freq_step * i); 16249a0bf528SMauro Carvalho Chehab 16259a0bf528SMauro Carvalho Chehab dir *= -1; 16269a0bf528SMauro Carvalho Chehab 16279a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x5c) < 0) /* Demod RESET */ 16289a0bf528SMauro Carvalho Chehab goto err; 16299a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, CFRINIT1, (freq_init >> 8) & 0xff) < 0) 16309a0bf528SMauro Carvalho Chehab goto err; 16319a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, CFRINIT0, freq_init & 0xff) < 0) 16329a0bf528SMauro Carvalho Chehab goto err; 16339a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x58) < 0) /* Demod RESET */ 16349a0bf528SMauro Carvalho Chehab goto err; 16359a0bf528SMauro Carvalho Chehab msleep(10); 16369a0bf528SMauro Carvalho Chehab 16379a0bf528SMauro Carvalho Chehab agc2 = 0; 16389a0bf528SMauro Carvalho Chehab for (j = 0; j < 10; j++) { 16399a0bf528SMauro Carvalho Chehab agc2 += (STV090x_READ_DEMOD(state, AGC2I1) << 8) | 16409a0bf528SMauro Carvalho Chehab STV090x_READ_DEMOD(state, AGC2I0); 16419a0bf528SMauro Carvalho Chehab } 16429a0bf528SMauro Carvalho Chehab agc2 /= 10; 16439a0bf528SMauro Carvalho Chehab if (agc2 < agc2_min) 16449a0bf528SMauro Carvalho Chehab agc2_min = agc2; 16459a0bf528SMauro Carvalho Chehab } 16469a0bf528SMauro Carvalho Chehab 16479a0bf528SMauro Carvalho Chehab return agc2_min; 16489a0bf528SMauro Carvalho Chehab err: 16499a0bf528SMauro Carvalho Chehab dprintk(FE_ERROR, 1, "I/O error"); 16509a0bf528SMauro Carvalho Chehab return -1; 16519a0bf528SMauro Carvalho Chehab } 16529a0bf528SMauro Carvalho Chehab 16539a0bf528SMauro Carvalho Chehab static u32 stv090x_get_srate(struct stv090x_state *state, u32 clk) 16549a0bf528SMauro Carvalho Chehab { 16559a0bf528SMauro Carvalho Chehab u8 r3, r2, r1, r0; 16569a0bf528SMauro Carvalho Chehab s32 srate, int_1, int_2, tmp_1, tmp_2; 16579a0bf528SMauro Carvalho Chehab 16589a0bf528SMauro Carvalho Chehab r3 = STV090x_READ_DEMOD(state, SFR3); 16599a0bf528SMauro Carvalho Chehab r2 = STV090x_READ_DEMOD(state, SFR2); 16609a0bf528SMauro Carvalho Chehab r1 = STV090x_READ_DEMOD(state, SFR1); 16619a0bf528SMauro Carvalho Chehab r0 = STV090x_READ_DEMOD(state, SFR0); 16629a0bf528SMauro Carvalho Chehab 16639a0bf528SMauro Carvalho Chehab srate = ((r3 << 24) | (r2 << 16) | (r1 << 8) | r0); 16649a0bf528SMauro Carvalho Chehab 16659a0bf528SMauro Carvalho Chehab int_1 = clk >> 16; 16669a0bf528SMauro Carvalho Chehab int_2 = srate >> 16; 16679a0bf528SMauro Carvalho Chehab 16689a0bf528SMauro Carvalho Chehab tmp_1 = clk % 0x10000; 16699a0bf528SMauro Carvalho Chehab tmp_2 = srate % 0x10000; 16709a0bf528SMauro Carvalho Chehab 16719a0bf528SMauro Carvalho Chehab srate = (int_1 * int_2) + 16729a0bf528SMauro Carvalho Chehab ((int_1 * tmp_2) >> 16) + 16739a0bf528SMauro Carvalho Chehab ((int_2 * tmp_1) >> 16); 16749a0bf528SMauro Carvalho Chehab 16759a0bf528SMauro Carvalho Chehab return srate; 16769a0bf528SMauro Carvalho Chehab } 16779a0bf528SMauro Carvalho Chehab 16789a0bf528SMauro Carvalho Chehab static u32 stv090x_srate_srch_coarse(struct stv090x_state *state) 16799a0bf528SMauro Carvalho Chehab { 16809a0bf528SMauro Carvalho Chehab struct dvb_frontend *fe = &state->frontend; 16819a0bf528SMauro Carvalho Chehab 16829a0bf528SMauro Carvalho Chehab int tmg_lock = 0, i; 16839a0bf528SMauro Carvalho Chehab s32 tmg_cpt = 0, dir = 1, steps, cur_step = 0, freq; 16849a0bf528SMauro Carvalho Chehab u32 srate_coarse = 0, agc2 = 0, car_step = 1200, reg; 16859a0bf528SMauro Carvalho Chehab u32 agc2th; 16869a0bf528SMauro Carvalho Chehab 16879a0bf528SMauro Carvalho Chehab if (state->internal->dev_ver >= 0x30) 16889a0bf528SMauro Carvalho Chehab agc2th = 0x2e00; 16899a0bf528SMauro Carvalho Chehab else 16909a0bf528SMauro Carvalho Chehab agc2th = 0x1f00; 16919a0bf528SMauro Carvalho Chehab 16929a0bf528SMauro Carvalho Chehab reg = STV090x_READ_DEMOD(state, DMDISTATE); 16939a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, I2C_DEMOD_MODE_FIELD, 0x1f); /* Demod RESET */ 16949a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, DMDISTATE, reg) < 0) 16959a0bf528SMauro Carvalho Chehab goto err; 16969a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, TMGCFG, 0x12) < 0) 16979a0bf528SMauro Carvalho Chehab goto err; 16989a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, TMGCFG2, 0xc0) < 0) 16999a0bf528SMauro Carvalho Chehab goto err; 17009a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, TMGTHRISE, 0xf0) < 0) 17019a0bf528SMauro Carvalho Chehab goto err; 17029a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, TMGTHFALL, 0xe0) < 0) 17039a0bf528SMauro Carvalho Chehab goto err; 17049a0bf528SMauro Carvalho Chehab reg = STV090x_READ_DEMOD(state, DMDCFGMD); 17059a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, SCAN_ENABLE_FIELD, 1); 17069a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, CFR_AUTOSCAN_FIELD, 0); 17079a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0) 17089a0bf528SMauro Carvalho Chehab goto err; 17099a0bf528SMauro Carvalho Chehab 17109a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, SFRUP1, 0x83) < 0) 17119a0bf528SMauro Carvalho Chehab goto err; 17129a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, SFRUP0, 0xc0) < 0) 17139a0bf528SMauro Carvalho Chehab goto err; 17149a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, SFRLOW1, 0x82) < 0) 17159a0bf528SMauro Carvalho Chehab goto err; 17169a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, SFRLOW0, 0xa0) < 0) 17179a0bf528SMauro Carvalho Chehab goto err; 17189a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, DMDTOM, 0x00) < 0) 17199a0bf528SMauro Carvalho Chehab goto err; 17209a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, AGC2REF, 0x50) < 0) 17219a0bf528SMauro Carvalho Chehab goto err; 17229a0bf528SMauro Carvalho Chehab 17239a0bf528SMauro Carvalho Chehab if (state->internal->dev_ver >= 0x30) { 17249a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x99) < 0) 17259a0bf528SMauro Carvalho Chehab goto err; 17269a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, SFRSTEP, 0x98) < 0) 17279a0bf528SMauro Carvalho Chehab goto err; 17289a0bf528SMauro Carvalho Chehab 17299a0bf528SMauro Carvalho Chehab } else if (state->internal->dev_ver >= 0x20) { 17309a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x6a) < 0) 17319a0bf528SMauro Carvalho Chehab goto err; 17329a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, SFRSTEP, 0x95) < 0) 17339a0bf528SMauro Carvalho Chehab goto err; 17349a0bf528SMauro Carvalho Chehab } 17359a0bf528SMauro Carvalho Chehab 17369a0bf528SMauro Carvalho Chehab if (state->srate <= 2000000) 17379a0bf528SMauro Carvalho Chehab car_step = 1000; 17389a0bf528SMauro Carvalho Chehab else if (state->srate <= 5000000) 17399a0bf528SMauro Carvalho Chehab car_step = 2000; 17409a0bf528SMauro Carvalho Chehab else if (state->srate <= 12000000) 17419a0bf528SMauro Carvalho Chehab car_step = 3000; 17429a0bf528SMauro Carvalho Chehab else 17439a0bf528SMauro Carvalho Chehab car_step = 5000; 17449a0bf528SMauro Carvalho Chehab 17459a0bf528SMauro Carvalho Chehab steps = -1 + ((state->search_range / 1000) / car_step); 17469a0bf528SMauro Carvalho Chehab steps /= 2; 17479a0bf528SMauro Carvalho Chehab steps = (2 * steps) + 1; 17489a0bf528SMauro Carvalho Chehab if (steps < 0) 17499a0bf528SMauro Carvalho Chehab steps = 1; 17509a0bf528SMauro Carvalho Chehab else if (steps > 10) { 17519a0bf528SMauro Carvalho Chehab steps = 11; 17529a0bf528SMauro Carvalho Chehab car_step = (state->search_range / 1000) / 10; 17539a0bf528SMauro Carvalho Chehab } 17549a0bf528SMauro Carvalho Chehab cur_step = 0; 17559a0bf528SMauro Carvalho Chehab dir = 1; 17569a0bf528SMauro Carvalho Chehab freq = state->frequency; 17579a0bf528SMauro Carvalho Chehab 17589a0bf528SMauro Carvalho Chehab while ((!tmg_lock) && (cur_step < steps)) { 17599a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x5f) < 0) /* Demod RESET */ 17609a0bf528SMauro Carvalho Chehab goto err; 17619a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, CFRINIT1, 0x00) < 0) 17629a0bf528SMauro Carvalho Chehab goto err; 17639a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, CFRINIT0, 0x00) < 0) 17649a0bf528SMauro Carvalho Chehab goto err; 17659a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, SFRINIT1, 0x00) < 0) 17669a0bf528SMauro Carvalho Chehab goto err; 17679a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, SFRINIT0, 0x00) < 0) 17689a0bf528SMauro Carvalho Chehab goto err; 17699a0bf528SMauro Carvalho Chehab /* trigger acquisition */ 17709a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x40) < 0) 17719a0bf528SMauro Carvalho Chehab goto err; 17729a0bf528SMauro Carvalho Chehab msleep(50); 17739a0bf528SMauro Carvalho Chehab for (i = 0; i < 10; i++) { 17749a0bf528SMauro Carvalho Chehab reg = STV090x_READ_DEMOD(state, DSTATUS); 17759a0bf528SMauro Carvalho Chehab if (STV090x_GETFIELD_Px(reg, TMGLOCK_QUALITY_FIELD) >= 2) 17769a0bf528SMauro Carvalho Chehab tmg_cpt++; 17779a0bf528SMauro Carvalho Chehab agc2 += (STV090x_READ_DEMOD(state, AGC2I1) << 8) | 17789a0bf528SMauro Carvalho Chehab STV090x_READ_DEMOD(state, AGC2I0); 17799a0bf528SMauro Carvalho Chehab } 17809a0bf528SMauro Carvalho Chehab agc2 /= 10; 17819a0bf528SMauro Carvalho Chehab srate_coarse = stv090x_get_srate(state, state->internal->mclk); 17829a0bf528SMauro Carvalho Chehab cur_step++; 17839a0bf528SMauro Carvalho Chehab dir *= -1; 17849a0bf528SMauro Carvalho Chehab if ((tmg_cpt >= 5) && (agc2 < agc2th) && 17859a0bf528SMauro Carvalho Chehab (srate_coarse < 50000000) && (srate_coarse > 850000)) 17869a0bf528SMauro Carvalho Chehab tmg_lock = 1; 17879a0bf528SMauro Carvalho Chehab else if (cur_step < steps) { 17889a0bf528SMauro Carvalho Chehab if (dir > 0) 17899a0bf528SMauro Carvalho Chehab freq += cur_step * car_step; 17909a0bf528SMauro Carvalho Chehab else 17919a0bf528SMauro Carvalho Chehab freq -= cur_step * car_step; 17929a0bf528SMauro Carvalho Chehab 17939a0bf528SMauro Carvalho Chehab /* Setup tuner */ 17949a0bf528SMauro Carvalho Chehab if (stv090x_i2c_gate_ctrl(state, 1) < 0) 17959a0bf528SMauro Carvalho Chehab goto err; 17969a0bf528SMauro Carvalho Chehab 17979a0bf528SMauro Carvalho Chehab if (state->config->tuner_set_frequency) { 17989a0bf528SMauro Carvalho Chehab if (state->config->tuner_set_frequency(fe, freq) < 0) 17999a0bf528SMauro Carvalho Chehab goto err_gateoff; 18009a0bf528SMauro Carvalho Chehab } 18019a0bf528SMauro Carvalho Chehab 18029a0bf528SMauro Carvalho Chehab if (state->config->tuner_set_bandwidth) { 18039a0bf528SMauro Carvalho Chehab if (state->config->tuner_set_bandwidth(fe, state->tuner_bw) < 0) 18049a0bf528SMauro Carvalho Chehab goto err_gateoff; 18059a0bf528SMauro Carvalho Chehab } 18069a0bf528SMauro Carvalho Chehab 18079a0bf528SMauro Carvalho Chehab if (stv090x_i2c_gate_ctrl(state, 0) < 0) 18089a0bf528SMauro Carvalho Chehab goto err; 18099a0bf528SMauro Carvalho Chehab 18109a0bf528SMauro Carvalho Chehab msleep(50); 18119a0bf528SMauro Carvalho Chehab 18129a0bf528SMauro Carvalho Chehab if (stv090x_i2c_gate_ctrl(state, 1) < 0) 18139a0bf528SMauro Carvalho Chehab goto err; 18149a0bf528SMauro Carvalho Chehab 18159a0bf528SMauro Carvalho Chehab if (state->config->tuner_get_status) { 18169a0bf528SMauro Carvalho Chehab if (state->config->tuner_get_status(fe, ®) < 0) 18179a0bf528SMauro Carvalho Chehab goto err_gateoff; 18189a0bf528SMauro Carvalho Chehab } 18199a0bf528SMauro Carvalho Chehab 18209a0bf528SMauro Carvalho Chehab if (reg) 18219a0bf528SMauro Carvalho Chehab dprintk(FE_DEBUG, 1, "Tuner phase locked"); 18229a0bf528SMauro Carvalho Chehab else 18239a0bf528SMauro Carvalho Chehab dprintk(FE_DEBUG, 1, "Tuner unlocked"); 18249a0bf528SMauro Carvalho Chehab 18259a0bf528SMauro Carvalho Chehab if (stv090x_i2c_gate_ctrl(state, 0) < 0) 18269a0bf528SMauro Carvalho Chehab goto err; 18279a0bf528SMauro Carvalho Chehab 18289a0bf528SMauro Carvalho Chehab } 18299a0bf528SMauro Carvalho Chehab } 18309a0bf528SMauro Carvalho Chehab if (!tmg_lock) 18319a0bf528SMauro Carvalho Chehab srate_coarse = 0; 18329a0bf528SMauro Carvalho Chehab else 18339a0bf528SMauro Carvalho Chehab srate_coarse = stv090x_get_srate(state, state->internal->mclk); 18349a0bf528SMauro Carvalho Chehab 18359a0bf528SMauro Carvalho Chehab return srate_coarse; 18369a0bf528SMauro Carvalho Chehab 18379a0bf528SMauro Carvalho Chehab err_gateoff: 18389a0bf528SMauro Carvalho Chehab stv090x_i2c_gate_ctrl(state, 0); 18399a0bf528SMauro Carvalho Chehab err: 18409a0bf528SMauro Carvalho Chehab dprintk(FE_ERROR, 1, "I/O error"); 18419a0bf528SMauro Carvalho Chehab return -1; 18429a0bf528SMauro Carvalho Chehab } 18439a0bf528SMauro Carvalho Chehab 18449a0bf528SMauro Carvalho Chehab static u32 stv090x_srate_srch_fine(struct stv090x_state *state) 18459a0bf528SMauro Carvalho Chehab { 18469a0bf528SMauro Carvalho Chehab u32 srate_coarse, freq_coarse, sym, reg; 18479a0bf528SMauro Carvalho Chehab 18489a0bf528SMauro Carvalho Chehab srate_coarse = stv090x_get_srate(state, state->internal->mclk); 18499a0bf528SMauro Carvalho Chehab freq_coarse = STV090x_READ_DEMOD(state, CFR2) << 8; 18509a0bf528SMauro Carvalho Chehab freq_coarse |= STV090x_READ_DEMOD(state, CFR1); 18519a0bf528SMauro Carvalho Chehab sym = 13 * (srate_coarse / 10); /* SFRUP = SFR + 30% */ 18529a0bf528SMauro Carvalho Chehab 18539a0bf528SMauro Carvalho Chehab if (sym < state->srate) 18549a0bf528SMauro Carvalho Chehab srate_coarse = 0; 18559a0bf528SMauro Carvalho Chehab else { 18569a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1f) < 0) /* Demod RESET */ 18579a0bf528SMauro Carvalho Chehab goto err; 18589a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, TMGCFG2, 0xc1) < 0) 18599a0bf528SMauro Carvalho Chehab goto err; 18609a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, TMGTHRISE, 0x20) < 0) 18619a0bf528SMauro Carvalho Chehab goto err; 18629a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, TMGTHFALL, 0x00) < 0) 18639a0bf528SMauro Carvalho Chehab goto err; 18649a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, TMGCFG, 0xd2) < 0) 18659a0bf528SMauro Carvalho Chehab goto err; 18669a0bf528SMauro Carvalho Chehab reg = STV090x_READ_DEMOD(state, DMDCFGMD); 18679a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, CFR_AUTOSCAN_FIELD, 0x00); 18689a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0) 18699a0bf528SMauro Carvalho Chehab goto err; 18709a0bf528SMauro Carvalho Chehab 18719a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, AGC2REF, 0x38) < 0) 18729a0bf528SMauro Carvalho Chehab goto err; 18739a0bf528SMauro Carvalho Chehab 18749a0bf528SMauro Carvalho Chehab if (state->internal->dev_ver >= 0x30) { 18759a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x79) < 0) 18769a0bf528SMauro Carvalho Chehab goto err; 18779a0bf528SMauro Carvalho Chehab } else if (state->internal->dev_ver >= 0x20) { 18789a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x49) < 0) 18799a0bf528SMauro Carvalho Chehab goto err; 18809a0bf528SMauro Carvalho Chehab } 18819a0bf528SMauro Carvalho Chehab 18829a0bf528SMauro Carvalho Chehab if (srate_coarse > 3000000) { 18839a0bf528SMauro Carvalho Chehab sym = 13 * (srate_coarse / 10); /* SFRUP = SFR + 30% */ 18849a0bf528SMauro Carvalho Chehab sym = (sym / 1000) * 65536; 18859a0bf528SMauro Carvalho Chehab sym /= (state->internal->mclk / 1000); 18869a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, SFRUP1, (sym >> 8) & 0x7f) < 0) 18879a0bf528SMauro Carvalho Chehab goto err; 18889a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, SFRUP0, sym & 0xff) < 0) 18899a0bf528SMauro Carvalho Chehab goto err; 18909a0bf528SMauro Carvalho Chehab sym = 10 * (srate_coarse / 13); /* SFRLOW = SFR - 30% */ 18919a0bf528SMauro Carvalho Chehab sym = (sym / 1000) * 65536; 18929a0bf528SMauro Carvalho Chehab sym /= (state->internal->mclk / 1000); 18939a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, SFRLOW1, (sym >> 8) & 0x7f) < 0) 18949a0bf528SMauro Carvalho Chehab goto err; 18959a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, SFRLOW0, sym & 0xff) < 0) 18969a0bf528SMauro Carvalho Chehab goto err; 18979a0bf528SMauro Carvalho Chehab sym = (srate_coarse / 1000) * 65536; 18989a0bf528SMauro Carvalho Chehab sym /= (state->internal->mclk / 1000); 18999a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, SFRINIT1, (sym >> 8) & 0xff) < 0) 19009a0bf528SMauro Carvalho Chehab goto err; 19019a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, SFRINIT0, sym & 0xff) < 0) 19029a0bf528SMauro Carvalho Chehab goto err; 19039a0bf528SMauro Carvalho Chehab } else { 19049a0bf528SMauro Carvalho Chehab sym = 13 * (srate_coarse / 10); /* SFRUP = SFR + 30% */ 19059a0bf528SMauro Carvalho Chehab sym = (sym / 100) * 65536; 19069a0bf528SMauro Carvalho Chehab sym /= (state->internal->mclk / 100); 19079a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, SFRUP1, (sym >> 8) & 0x7f) < 0) 19089a0bf528SMauro Carvalho Chehab goto err; 19099a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, SFRUP0, sym & 0xff) < 0) 19109a0bf528SMauro Carvalho Chehab goto err; 19119a0bf528SMauro Carvalho Chehab sym = 10 * (srate_coarse / 14); /* SFRLOW = SFR - 30% */ 19129a0bf528SMauro Carvalho Chehab sym = (sym / 100) * 65536; 19139a0bf528SMauro Carvalho Chehab sym /= (state->internal->mclk / 100); 19149a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, SFRLOW1, (sym >> 8) & 0x7f) < 0) 19159a0bf528SMauro Carvalho Chehab goto err; 19169a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, SFRLOW0, sym & 0xff) < 0) 19179a0bf528SMauro Carvalho Chehab goto err; 19189a0bf528SMauro Carvalho Chehab sym = (srate_coarse / 100) * 65536; 19199a0bf528SMauro Carvalho Chehab sym /= (state->internal->mclk / 100); 19209a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, SFRINIT1, (sym >> 8) & 0xff) < 0) 19219a0bf528SMauro Carvalho Chehab goto err; 19229a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, SFRINIT0, sym & 0xff) < 0) 19239a0bf528SMauro Carvalho Chehab goto err; 19249a0bf528SMauro Carvalho Chehab } 19259a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, DMDTOM, 0x20) < 0) 19269a0bf528SMauro Carvalho Chehab goto err; 19279a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, CFRINIT1, (freq_coarse >> 8) & 0xff) < 0) 19289a0bf528SMauro Carvalho Chehab goto err; 19299a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, CFRINIT0, freq_coarse & 0xff) < 0) 19309a0bf528SMauro Carvalho Chehab goto err; 19319a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x15) < 0) /* trigger acquisition */ 19329a0bf528SMauro Carvalho Chehab goto err; 19339a0bf528SMauro Carvalho Chehab } 19349a0bf528SMauro Carvalho Chehab 19359a0bf528SMauro Carvalho Chehab return srate_coarse; 19369a0bf528SMauro Carvalho Chehab 19379a0bf528SMauro Carvalho Chehab err: 19389a0bf528SMauro Carvalho Chehab dprintk(FE_ERROR, 1, "I/O error"); 19399a0bf528SMauro Carvalho Chehab return -1; 19409a0bf528SMauro Carvalho Chehab } 19419a0bf528SMauro Carvalho Chehab 19429a0bf528SMauro Carvalho Chehab static int stv090x_get_dmdlock(struct stv090x_state *state, s32 timeout) 19439a0bf528SMauro Carvalho Chehab { 19449a0bf528SMauro Carvalho Chehab s32 timer = 0, lock = 0; 19459a0bf528SMauro Carvalho Chehab u32 reg; 19469a0bf528SMauro Carvalho Chehab u8 stat; 19479a0bf528SMauro Carvalho Chehab 19489a0bf528SMauro Carvalho Chehab while ((timer < timeout) && (!lock)) { 19499a0bf528SMauro Carvalho Chehab reg = STV090x_READ_DEMOD(state, DMDSTATE); 19509a0bf528SMauro Carvalho Chehab stat = STV090x_GETFIELD_Px(reg, HEADER_MODE_FIELD); 19519a0bf528SMauro Carvalho Chehab 19529a0bf528SMauro Carvalho Chehab switch (stat) { 19539a0bf528SMauro Carvalho Chehab case 0: /* searching */ 19549a0bf528SMauro Carvalho Chehab case 1: /* first PLH detected */ 19559a0bf528SMauro Carvalho Chehab default: 19569a0bf528SMauro Carvalho Chehab dprintk(FE_DEBUG, 1, "Demodulator searching .."); 19579a0bf528SMauro Carvalho Chehab lock = 0; 19589a0bf528SMauro Carvalho Chehab break; 19599a0bf528SMauro Carvalho Chehab case 2: /* DVB-S2 mode */ 19609a0bf528SMauro Carvalho Chehab case 3: /* DVB-S1/legacy mode */ 19619a0bf528SMauro Carvalho Chehab reg = STV090x_READ_DEMOD(state, DSTATUS); 19629a0bf528SMauro Carvalho Chehab lock = STV090x_GETFIELD_Px(reg, LOCK_DEFINITIF_FIELD); 19639a0bf528SMauro Carvalho Chehab break; 19649a0bf528SMauro Carvalho Chehab } 19659a0bf528SMauro Carvalho Chehab 19669a0bf528SMauro Carvalho Chehab if (!lock) 19679a0bf528SMauro Carvalho Chehab msleep(10); 19689a0bf528SMauro Carvalho Chehab else 19699a0bf528SMauro Carvalho Chehab dprintk(FE_DEBUG, 1, "Demodulator acquired LOCK"); 19709a0bf528SMauro Carvalho Chehab 19719a0bf528SMauro Carvalho Chehab timer += 10; 19729a0bf528SMauro Carvalho Chehab } 19739a0bf528SMauro Carvalho Chehab return lock; 19749a0bf528SMauro Carvalho Chehab } 19759a0bf528SMauro Carvalho Chehab 19769a0bf528SMauro Carvalho Chehab static int stv090x_blind_search(struct stv090x_state *state) 19779a0bf528SMauro Carvalho Chehab { 19789a0bf528SMauro Carvalho Chehab u32 agc2, reg, srate_coarse; 19799a0bf528SMauro Carvalho Chehab s32 cpt_fail, agc2_ovflw, i; 19809a0bf528SMauro Carvalho Chehab u8 k_ref, k_max, k_min; 19819a0bf528SMauro Carvalho Chehab int coarse_fail = 0; 19829a0bf528SMauro Carvalho Chehab int lock; 19839a0bf528SMauro Carvalho Chehab 19849a0bf528SMauro Carvalho Chehab k_max = 110; 19859a0bf528SMauro Carvalho Chehab k_min = 10; 19869a0bf528SMauro Carvalho Chehab 19879a0bf528SMauro Carvalho Chehab agc2 = stv090x_get_agc2_min_level(state); 19889a0bf528SMauro Carvalho Chehab 19899a0bf528SMauro Carvalho Chehab if (agc2 > STV090x_SEARCH_AGC2_TH(state->internal->dev_ver)) { 19909a0bf528SMauro Carvalho Chehab lock = 0; 19919a0bf528SMauro Carvalho Chehab } else { 19929a0bf528SMauro Carvalho Chehab 19939a0bf528SMauro Carvalho Chehab if (state->internal->dev_ver <= 0x20) { 19949a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, CARCFG, 0xc4) < 0) 19959a0bf528SMauro Carvalho Chehab goto err; 19969a0bf528SMauro Carvalho Chehab } else { 19979a0bf528SMauro Carvalho Chehab /* > Cut 3 */ 19989a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, CARCFG, 0x06) < 0) 19999a0bf528SMauro Carvalho Chehab goto err; 20009a0bf528SMauro Carvalho Chehab } 20019a0bf528SMauro Carvalho Chehab 20029a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, RTCS2, 0x44) < 0) 20039a0bf528SMauro Carvalho Chehab goto err; 20049a0bf528SMauro Carvalho Chehab 20059a0bf528SMauro Carvalho Chehab if (state->internal->dev_ver >= 0x20) { 20069a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, EQUALCFG, 0x41) < 0) 20079a0bf528SMauro Carvalho Chehab goto err; 20089a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, FFECFG, 0x41) < 0) 20099a0bf528SMauro Carvalho Chehab goto err; 20109a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, VITSCALE, 0x82) < 0) 20119a0bf528SMauro Carvalho Chehab goto err; 20129a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, VAVSRVIT, 0x00) < 0) /* set viterbi hysteresis */ 20139a0bf528SMauro Carvalho Chehab goto err; 20149a0bf528SMauro Carvalho Chehab } 20159a0bf528SMauro Carvalho Chehab 20169a0bf528SMauro Carvalho Chehab k_ref = k_max; 20179a0bf528SMauro Carvalho Chehab do { 20189a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, KREFTMG, k_ref) < 0) 20199a0bf528SMauro Carvalho Chehab goto err; 20209a0bf528SMauro Carvalho Chehab if (stv090x_srate_srch_coarse(state) != 0) { 20219a0bf528SMauro Carvalho Chehab srate_coarse = stv090x_srate_srch_fine(state); 20229a0bf528SMauro Carvalho Chehab if (srate_coarse != 0) { 20239a0bf528SMauro Carvalho Chehab stv090x_get_lock_tmg(state); 20249a0bf528SMauro Carvalho Chehab lock = stv090x_get_dmdlock(state, 20259a0bf528SMauro Carvalho Chehab state->DemodTimeout); 20269a0bf528SMauro Carvalho Chehab } else { 20279a0bf528SMauro Carvalho Chehab lock = 0; 20289a0bf528SMauro Carvalho Chehab } 20299a0bf528SMauro Carvalho Chehab } else { 20309a0bf528SMauro Carvalho Chehab cpt_fail = 0; 20319a0bf528SMauro Carvalho Chehab agc2_ovflw = 0; 20329a0bf528SMauro Carvalho Chehab for (i = 0; i < 10; i++) { 20339a0bf528SMauro Carvalho Chehab agc2 += (STV090x_READ_DEMOD(state, AGC2I1) << 8) | 20349a0bf528SMauro Carvalho Chehab STV090x_READ_DEMOD(state, AGC2I0); 20359a0bf528SMauro Carvalho Chehab if (agc2 >= 0xff00) 20369a0bf528SMauro Carvalho Chehab agc2_ovflw++; 20379a0bf528SMauro Carvalho Chehab reg = STV090x_READ_DEMOD(state, DSTATUS2); 20389a0bf528SMauro Carvalho Chehab if ((STV090x_GETFIELD_Px(reg, CFR_OVERFLOW_FIELD) == 0x01) && 20399a0bf528SMauro Carvalho Chehab (STV090x_GETFIELD_Px(reg, DEMOD_DELOCK_FIELD) == 0x01)) 20409a0bf528SMauro Carvalho Chehab 20419a0bf528SMauro Carvalho Chehab cpt_fail++; 20429a0bf528SMauro Carvalho Chehab } 20439a0bf528SMauro Carvalho Chehab if ((cpt_fail > 7) || (agc2_ovflw > 7)) 20449a0bf528SMauro Carvalho Chehab coarse_fail = 1; 20459a0bf528SMauro Carvalho Chehab 20469a0bf528SMauro Carvalho Chehab lock = 0; 20479a0bf528SMauro Carvalho Chehab } 20489a0bf528SMauro Carvalho Chehab k_ref -= 20; 20499a0bf528SMauro Carvalho Chehab } while ((k_ref >= k_min) && (!lock) && (!coarse_fail)); 20509a0bf528SMauro Carvalho Chehab } 20519a0bf528SMauro Carvalho Chehab 20529a0bf528SMauro Carvalho Chehab return lock; 20539a0bf528SMauro Carvalho Chehab 20549a0bf528SMauro Carvalho Chehab err: 20559a0bf528SMauro Carvalho Chehab dprintk(FE_ERROR, 1, "I/O error"); 20569a0bf528SMauro Carvalho Chehab return -1; 20579a0bf528SMauro Carvalho Chehab } 20589a0bf528SMauro Carvalho Chehab 20599a0bf528SMauro Carvalho Chehab static int stv090x_chk_tmg(struct stv090x_state *state) 20609a0bf528SMauro Carvalho Chehab { 20619a0bf528SMauro Carvalho Chehab u32 reg; 20629a0bf528SMauro Carvalho Chehab s32 tmg_cpt = 0, i; 20639a0bf528SMauro Carvalho Chehab u8 freq, tmg_thh, tmg_thl; 20649a0bf528SMauro Carvalho Chehab int tmg_lock = 0; 20659a0bf528SMauro Carvalho Chehab 20669a0bf528SMauro Carvalho Chehab freq = STV090x_READ_DEMOD(state, CARFREQ); 20679a0bf528SMauro Carvalho Chehab tmg_thh = STV090x_READ_DEMOD(state, TMGTHRISE); 20689a0bf528SMauro Carvalho Chehab tmg_thl = STV090x_READ_DEMOD(state, TMGTHFALL); 20699a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, TMGTHRISE, 0x20) < 0) 20709a0bf528SMauro Carvalho Chehab goto err; 20719a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, TMGTHFALL, 0x00) < 0) 20729a0bf528SMauro Carvalho Chehab goto err; 20739a0bf528SMauro Carvalho Chehab 20749a0bf528SMauro Carvalho Chehab reg = STV090x_READ_DEMOD(state, DMDCFGMD); 20759a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, CFR_AUTOSCAN_FIELD, 0x00); /* stop carrier offset search */ 20769a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0) 20779a0bf528SMauro Carvalho Chehab goto err; 20789a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, RTC, 0x80) < 0) 20799a0bf528SMauro Carvalho Chehab goto err; 20809a0bf528SMauro Carvalho Chehab 20819a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, RTCS2, 0x40) < 0) 20829a0bf528SMauro Carvalho Chehab goto err; 20839a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x00) < 0) 20849a0bf528SMauro Carvalho Chehab goto err; 20859a0bf528SMauro Carvalho Chehab 20869a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, CFRINIT1, 0x00) < 0) /* set car ofset to 0 */ 20879a0bf528SMauro Carvalho Chehab goto err; 20889a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, CFRINIT0, 0x00) < 0) 20899a0bf528SMauro Carvalho Chehab goto err; 20909a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, AGC2REF, 0x65) < 0) 20919a0bf528SMauro Carvalho Chehab goto err; 20929a0bf528SMauro Carvalho Chehab 20939a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x18) < 0) /* trigger acquisition */ 20949a0bf528SMauro Carvalho Chehab goto err; 20959a0bf528SMauro Carvalho Chehab msleep(10); 20969a0bf528SMauro Carvalho Chehab 20979a0bf528SMauro Carvalho Chehab for (i = 0; i < 10; i++) { 20989a0bf528SMauro Carvalho Chehab reg = STV090x_READ_DEMOD(state, DSTATUS); 20999a0bf528SMauro Carvalho Chehab if (STV090x_GETFIELD_Px(reg, TMGLOCK_QUALITY_FIELD) >= 2) 21009a0bf528SMauro Carvalho Chehab tmg_cpt++; 21019a0bf528SMauro Carvalho Chehab msleep(1); 21029a0bf528SMauro Carvalho Chehab } 21039a0bf528SMauro Carvalho Chehab if (tmg_cpt >= 3) 21049a0bf528SMauro Carvalho Chehab tmg_lock = 1; 21059a0bf528SMauro Carvalho Chehab 21069a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, AGC2REF, 0x38) < 0) 21079a0bf528SMauro Carvalho Chehab goto err; 21089a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, RTC, 0x88) < 0) /* DVB-S1 timing */ 21099a0bf528SMauro Carvalho Chehab goto err; 21109a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, RTCS2, 0x68) < 0) /* DVB-S2 timing */ 21119a0bf528SMauro Carvalho Chehab goto err; 21129a0bf528SMauro Carvalho Chehab 21139a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, CARFREQ, freq) < 0) 21149a0bf528SMauro Carvalho Chehab goto err; 21159a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, TMGTHRISE, tmg_thh) < 0) 21169a0bf528SMauro Carvalho Chehab goto err; 21179a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, TMGTHFALL, tmg_thl) < 0) 21189a0bf528SMauro Carvalho Chehab goto err; 21199a0bf528SMauro Carvalho Chehab 21209a0bf528SMauro Carvalho Chehab return tmg_lock; 21219a0bf528SMauro Carvalho Chehab 21229a0bf528SMauro Carvalho Chehab err: 21239a0bf528SMauro Carvalho Chehab dprintk(FE_ERROR, 1, "I/O error"); 21249a0bf528SMauro Carvalho Chehab return -1; 21259a0bf528SMauro Carvalho Chehab } 21269a0bf528SMauro Carvalho Chehab 21279a0bf528SMauro Carvalho Chehab static int stv090x_get_coldlock(struct stv090x_state *state, s32 timeout_dmd) 21289a0bf528SMauro Carvalho Chehab { 21299a0bf528SMauro Carvalho Chehab struct dvb_frontend *fe = &state->frontend; 21309a0bf528SMauro Carvalho Chehab 21319a0bf528SMauro Carvalho Chehab u32 reg; 21329a0bf528SMauro Carvalho Chehab s32 car_step, steps, cur_step, dir, freq, timeout_lock; 213366ae9fc2SDan Carpenter int lock; 21349a0bf528SMauro Carvalho Chehab 21359a0bf528SMauro Carvalho Chehab if (state->srate >= 10000000) 21369a0bf528SMauro Carvalho Chehab timeout_lock = timeout_dmd / 3; 21379a0bf528SMauro Carvalho Chehab else 21389a0bf528SMauro Carvalho Chehab timeout_lock = timeout_dmd / 2; 21399a0bf528SMauro Carvalho Chehab 21409a0bf528SMauro Carvalho Chehab lock = stv090x_get_dmdlock(state, timeout_lock); /* cold start wait */ 214166ae9fc2SDan Carpenter if (lock) 214266ae9fc2SDan Carpenter return lock; 214366ae9fc2SDan Carpenter 21449a0bf528SMauro Carvalho Chehab if (state->srate >= 10000000) { 21459a0bf528SMauro Carvalho Chehab if (stv090x_chk_tmg(state)) { 21469a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1f) < 0) 21479a0bf528SMauro Carvalho Chehab goto err; 21489a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x15) < 0) 21499a0bf528SMauro Carvalho Chehab goto err; 215066ae9fc2SDan Carpenter return stv090x_get_dmdlock(state, timeout_dmd); 21519a0bf528SMauro Carvalho Chehab } 215266ae9fc2SDan Carpenter return 0; 215366ae9fc2SDan Carpenter } 215466ae9fc2SDan Carpenter 21559a0bf528SMauro Carvalho Chehab if (state->srate <= 4000000) 21569a0bf528SMauro Carvalho Chehab car_step = 1000; 21579a0bf528SMauro Carvalho Chehab else if (state->srate <= 7000000) 21589a0bf528SMauro Carvalho Chehab car_step = 2000; 21599a0bf528SMauro Carvalho Chehab else if (state->srate <= 10000000) 21609a0bf528SMauro Carvalho Chehab car_step = 3000; 21619a0bf528SMauro Carvalho Chehab else 21629a0bf528SMauro Carvalho Chehab car_step = 5000; 21639a0bf528SMauro Carvalho Chehab 21649a0bf528SMauro Carvalho Chehab steps = (state->search_range / 1000) / car_step; 21659a0bf528SMauro Carvalho Chehab steps /= 2; 21669a0bf528SMauro Carvalho Chehab steps = 2 * (steps + 1); 21679a0bf528SMauro Carvalho Chehab if (steps < 0) 21689a0bf528SMauro Carvalho Chehab steps = 2; 21699a0bf528SMauro Carvalho Chehab else if (steps > 12) 21709a0bf528SMauro Carvalho Chehab steps = 12; 21719a0bf528SMauro Carvalho Chehab 21729a0bf528SMauro Carvalho Chehab cur_step = 1; 21739a0bf528SMauro Carvalho Chehab dir = 1; 21749a0bf528SMauro Carvalho Chehab 21759a0bf528SMauro Carvalho Chehab freq = state->frequency; 21769a0bf528SMauro Carvalho Chehab state->tuner_bw = stv090x_car_width(state->srate, state->rolloff) + state->srate; 21779a0bf528SMauro Carvalho Chehab while ((cur_step <= steps) && (!lock)) { 21789a0bf528SMauro Carvalho Chehab if (dir > 0) 21799a0bf528SMauro Carvalho Chehab freq += cur_step * car_step; 21809a0bf528SMauro Carvalho Chehab else 21819a0bf528SMauro Carvalho Chehab freq -= cur_step * car_step; 21829a0bf528SMauro Carvalho Chehab 21839a0bf528SMauro Carvalho Chehab /* Setup tuner */ 21849a0bf528SMauro Carvalho Chehab if (stv090x_i2c_gate_ctrl(state, 1) < 0) 21859a0bf528SMauro Carvalho Chehab goto err; 21869a0bf528SMauro Carvalho Chehab 21879a0bf528SMauro Carvalho Chehab if (state->config->tuner_set_frequency) { 21889a0bf528SMauro Carvalho Chehab if (state->config->tuner_set_frequency(fe, freq) < 0) 21899a0bf528SMauro Carvalho Chehab goto err_gateoff; 21909a0bf528SMauro Carvalho Chehab } 21919a0bf528SMauro Carvalho Chehab 21929a0bf528SMauro Carvalho Chehab if (state->config->tuner_set_bandwidth) { 21939a0bf528SMauro Carvalho Chehab if (state->config->tuner_set_bandwidth(fe, state->tuner_bw) < 0) 21949a0bf528SMauro Carvalho Chehab goto err_gateoff; 21959a0bf528SMauro Carvalho Chehab } 21969a0bf528SMauro Carvalho Chehab 21979a0bf528SMauro Carvalho Chehab if (stv090x_i2c_gate_ctrl(state, 0) < 0) 21989a0bf528SMauro Carvalho Chehab goto err; 21999a0bf528SMauro Carvalho Chehab 22009a0bf528SMauro Carvalho Chehab msleep(50); 22019a0bf528SMauro Carvalho Chehab 22029a0bf528SMauro Carvalho Chehab if (stv090x_i2c_gate_ctrl(state, 1) < 0) 22039a0bf528SMauro Carvalho Chehab goto err; 22049a0bf528SMauro Carvalho Chehab 22059a0bf528SMauro Carvalho Chehab if (state->config->tuner_get_status) { 22069a0bf528SMauro Carvalho Chehab if (state->config->tuner_get_status(fe, ®) < 0) 22079a0bf528SMauro Carvalho Chehab goto err_gateoff; 22089a0bf528SMauro Carvalho Chehab if (reg) 22099a0bf528SMauro Carvalho Chehab dprintk(FE_DEBUG, 1, "Tuner phase locked"); 22109a0bf528SMauro Carvalho Chehab else 22119a0bf528SMauro Carvalho Chehab dprintk(FE_DEBUG, 1, "Tuner unlocked"); 2212ab0625f0SMauro Carvalho Chehab } 22139a0bf528SMauro Carvalho Chehab 22149a0bf528SMauro Carvalho Chehab if (stv090x_i2c_gate_ctrl(state, 0) < 0) 22159a0bf528SMauro Carvalho Chehab goto err; 22169a0bf528SMauro Carvalho Chehab 22179a0bf528SMauro Carvalho Chehab STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1c); 22189a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, CFRINIT1, 0x00) < 0) 22199a0bf528SMauro Carvalho Chehab goto err; 22209a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, CFRINIT0, 0x00) < 0) 22219a0bf528SMauro Carvalho Chehab goto err; 22229a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1f) < 0) 22239a0bf528SMauro Carvalho Chehab goto err; 22249a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x15) < 0) 22259a0bf528SMauro Carvalho Chehab goto err; 22269a0bf528SMauro Carvalho Chehab lock = stv090x_get_dmdlock(state, (timeout_dmd / 3)); 22279a0bf528SMauro Carvalho Chehab 22289a0bf528SMauro Carvalho Chehab dir *= -1; 22299a0bf528SMauro Carvalho Chehab cur_step++; 22309a0bf528SMauro Carvalho Chehab } 22319a0bf528SMauro Carvalho Chehab 22329a0bf528SMauro Carvalho Chehab return lock; 22339a0bf528SMauro Carvalho Chehab 22349a0bf528SMauro Carvalho Chehab err_gateoff: 22359a0bf528SMauro Carvalho Chehab stv090x_i2c_gate_ctrl(state, 0); 22369a0bf528SMauro Carvalho Chehab err: 22379a0bf528SMauro Carvalho Chehab dprintk(FE_ERROR, 1, "I/O error"); 22389a0bf528SMauro Carvalho Chehab return -1; 22399a0bf528SMauro Carvalho Chehab } 22409a0bf528SMauro Carvalho Chehab 22419a0bf528SMauro Carvalho Chehab static int stv090x_get_loop_params(struct stv090x_state *state, s32 *freq_inc, s32 *timeout_sw, s32 *steps) 22429a0bf528SMauro Carvalho Chehab { 22439a0bf528SMauro Carvalho Chehab s32 timeout, inc, steps_max, srate, car_max; 22449a0bf528SMauro Carvalho Chehab 22459a0bf528SMauro Carvalho Chehab srate = state->srate; 22469a0bf528SMauro Carvalho Chehab car_max = state->search_range / 1000; 22479a0bf528SMauro Carvalho Chehab car_max += car_max / 10; 22489a0bf528SMauro Carvalho Chehab car_max = 65536 * (car_max / 2); 22499a0bf528SMauro Carvalho Chehab car_max /= (state->internal->mclk / 1000); 22509a0bf528SMauro Carvalho Chehab 22519a0bf528SMauro Carvalho Chehab if (car_max > 0x4000) 22529a0bf528SMauro Carvalho Chehab car_max = 0x4000 ; /* maxcarrier should be<= +-1/4 Mclk */ 22539a0bf528SMauro Carvalho Chehab 22549a0bf528SMauro Carvalho Chehab inc = srate; 22559a0bf528SMauro Carvalho Chehab inc /= state->internal->mclk / 1000; 22569a0bf528SMauro Carvalho Chehab inc *= 256; 22579a0bf528SMauro Carvalho Chehab inc *= 256; 22589a0bf528SMauro Carvalho Chehab inc /= 1000; 22599a0bf528SMauro Carvalho Chehab 22609a0bf528SMauro Carvalho Chehab switch (state->search_mode) { 22619a0bf528SMauro Carvalho Chehab case STV090x_SEARCH_DVBS1: 22629a0bf528SMauro Carvalho Chehab case STV090x_SEARCH_DSS: 22639a0bf528SMauro Carvalho Chehab inc *= 3; /* freq step = 3% of srate */ 22649a0bf528SMauro Carvalho Chehab timeout = 20; 22659a0bf528SMauro Carvalho Chehab break; 22669a0bf528SMauro Carvalho Chehab 22679a0bf528SMauro Carvalho Chehab case STV090x_SEARCH_DVBS2: 22689a0bf528SMauro Carvalho Chehab inc *= 4; 22699a0bf528SMauro Carvalho Chehab timeout = 25; 22709a0bf528SMauro Carvalho Chehab break; 22719a0bf528SMauro Carvalho Chehab 22729a0bf528SMauro Carvalho Chehab case STV090x_SEARCH_AUTO: 22739a0bf528SMauro Carvalho Chehab default: 22749a0bf528SMauro Carvalho Chehab inc *= 3; 22759a0bf528SMauro Carvalho Chehab timeout = 25; 22769a0bf528SMauro Carvalho Chehab break; 22779a0bf528SMauro Carvalho Chehab } 22789a0bf528SMauro Carvalho Chehab inc /= 100; 22799a0bf528SMauro Carvalho Chehab if ((inc > car_max) || (inc < 0)) 22809a0bf528SMauro Carvalho Chehab inc = car_max / 2; /* increment <= 1/8 Mclk */ 22819a0bf528SMauro Carvalho Chehab 22829a0bf528SMauro Carvalho Chehab timeout *= 27500; /* 27.5 Msps reference */ 22839a0bf528SMauro Carvalho Chehab if (srate > 0) 22849a0bf528SMauro Carvalho Chehab timeout /= (srate / 1000); 22859a0bf528SMauro Carvalho Chehab 22869a0bf528SMauro Carvalho Chehab if ((timeout > 100) || (timeout < 0)) 22879a0bf528SMauro Carvalho Chehab timeout = 100; 22889a0bf528SMauro Carvalho Chehab 22899a0bf528SMauro Carvalho Chehab steps_max = (car_max / inc) + 1; /* min steps = 3 */ 22909a0bf528SMauro Carvalho Chehab if ((steps_max > 100) || (steps_max < 0)) { 22919a0bf528SMauro Carvalho Chehab steps_max = 100; /* max steps <= 100 */ 22929a0bf528SMauro Carvalho Chehab inc = car_max / steps_max; 22939a0bf528SMauro Carvalho Chehab } 22949a0bf528SMauro Carvalho Chehab *freq_inc = inc; 22959a0bf528SMauro Carvalho Chehab *timeout_sw = timeout; 22969a0bf528SMauro Carvalho Chehab *steps = steps_max; 22979a0bf528SMauro Carvalho Chehab 22989a0bf528SMauro Carvalho Chehab return 0; 22999a0bf528SMauro Carvalho Chehab } 23009a0bf528SMauro Carvalho Chehab 23019a0bf528SMauro Carvalho Chehab static int stv090x_chk_signal(struct stv090x_state *state) 23029a0bf528SMauro Carvalho Chehab { 23039a0bf528SMauro Carvalho Chehab s32 offst_car, agc2, car_max; 23049a0bf528SMauro Carvalho Chehab int no_signal; 23059a0bf528SMauro Carvalho Chehab 23069a0bf528SMauro Carvalho Chehab offst_car = STV090x_READ_DEMOD(state, CFR2) << 8; 23079a0bf528SMauro Carvalho Chehab offst_car |= STV090x_READ_DEMOD(state, CFR1); 23089a0bf528SMauro Carvalho Chehab offst_car = comp2(offst_car, 16); 23099a0bf528SMauro Carvalho Chehab 23109a0bf528SMauro Carvalho Chehab agc2 = STV090x_READ_DEMOD(state, AGC2I1) << 8; 23119a0bf528SMauro Carvalho Chehab agc2 |= STV090x_READ_DEMOD(state, AGC2I0); 23129a0bf528SMauro Carvalho Chehab car_max = state->search_range / 1000; 23139a0bf528SMauro Carvalho Chehab 23149a0bf528SMauro Carvalho Chehab car_max += (car_max / 10); /* 10% margin */ 23159a0bf528SMauro Carvalho Chehab car_max = (65536 * car_max / 2); 23169a0bf528SMauro Carvalho Chehab car_max /= state->internal->mclk / 1000; 23179a0bf528SMauro Carvalho Chehab 23189a0bf528SMauro Carvalho Chehab if (car_max > 0x4000) 23199a0bf528SMauro Carvalho Chehab car_max = 0x4000; 23209a0bf528SMauro Carvalho Chehab 23219a0bf528SMauro Carvalho Chehab if ((agc2 > 0x2000) || (offst_car > 2 * car_max) || (offst_car < -2 * car_max)) { 23229a0bf528SMauro Carvalho Chehab no_signal = 1; 23239a0bf528SMauro Carvalho Chehab dprintk(FE_DEBUG, 1, "No Signal"); 23249a0bf528SMauro Carvalho Chehab } else { 23259a0bf528SMauro Carvalho Chehab no_signal = 0; 23269a0bf528SMauro Carvalho Chehab dprintk(FE_DEBUG, 1, "Found Signal"); 23279a0bf528SMauro Carvalho Chehab } 23289a0bf528SMauro Carvalho Chehab 23299a0bf528SMauro Carvalho Chehab return no_signal; 23309a0bf528SMauro Carvalho Chehab } 23319a0bf528SMauro Carvalho Chehab 23329a0bf528SMauro Carvalho Chehab static int stv090x_search_car_loop(struct stv090x_state *state, s32 inc, s32 timeout, int zigzag, s32 steps_max) 23339a0bf528SMauro Carvalho Chehab { 23349a0bf528SMauro Carvalho Chehab int no_signal, lock = 0; 23359a0bf528SMauro Carvalho Chehab s32 cpt_step = 0, offst_freq, car_max; 23369a0bf528SMauro Carvalho Chehab u32 reg; 23379a0bf528SMauro Carvalho Chehab 23389a0bf528SMauro Carvalho Chehab car_max = state->search_range / 1000; 23399a0bf528SMauro Carvalho Chehab car_max += (car_max / 10); 23409a0bf528SMauro Carvalho Chehab car_max = (65536 * car_max / 2); 23419a0bf528SMauro Carvalho Chehab car_max /= (state->internal->mclk / 1000); 23429a0bf528SMauro Carvalho Chehab if (car_max > 0x4000) 23439a0bf528SMauro Carvalho Chehab car_max = 0x4000; 23449a0bf528SMauro Carvalho Chehab 23459a0bf528SMauro Carvalho Chehab if (zigzag) 23469a0bf528SMauro Carvalho Chehab offst_freq = 0; 23479a0bf528SMauro Carvalho Chehab else 23489a0bf528SMauro Carvalho Chehab offst_freq = -car_max + inc; 23499a0bf528SMauro Carvalho Chehab 23509a0bf528SMauro Carvalho Chehab do { 23519a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1c) < 0) 23529a0bf528SMauro Carvalho Chehab goto err; 23539a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, CFRINIT1, ((offst_freq / 256) & 0xff)) < 0) 23549a0bf528SMauro Carvalho Chehab goto err; 23559a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, CFRINIT0, offst_freq & 0xff) < 0) 23569a0bf528SMauro Carvalho Chehab goto err; 23579a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x18) < 0) 23589a0bf528SMauro Carvalho Chehab goto err; 23599a0bf528SMauro Carvalho Chehab 23609a0bf528SMauro Carvalho Chehab reg = STV090x_READ_DEMOD(state, PDELCTRL1); 23619a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, ALGOSWRST_FIELD, 0x1); /* stop DVB-S2 packet delin */ 23629a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, PDELCTRL1, reg) < 0) 23639a0bf528SMauro Carvalho Chehab goto err; 23649a0bf528SMauro Carvalho Chehab 23659a0bf528SMauro Carvalho Chehab if (zigzag) { 23669a0bf528SMauro Carvalho Chehab if (offst_freq >= 0) 23679a0bf528SMauro Carvalho Chehab offst_freq = -offst_freq - 2 * inc; 23689a0bf528SMauro Carvalho Chehab else 23699a0bf528SMauro Carvalho Chehab offst_freq = -offst_freq; 23709a0bf528SMauro Carvalho Chehab } else { 23719a0bf528SMauro Carvalho Chehab offst_freq += 2 * inc; 23729a0bf528SMauro Carvalho Chehab } 23739a0bf528SMauro Carvalho Chehab 23749a0bf528SMauro Carvalho Chehab cpt_step++; 23759a0bf528SMauro Carvalho Chehab 23769a0bf528SMauro Carvalho Chehab lock = stv090x_get_dmdlock(state, timeout); 23779a0bf528SMauro Carvalho Chehab no_signal = stv090x_chk_signal(state); 23789a0bf528SMauro Carvalho Chehab 23799a0bf528SMauro Carvalho Chehab } while ((!lock) && 23809a0bf528SMauro Carvalho Chehab (!no_signal) && 23819a0bf528SMauro Carvalho Chehab ((offst_freq - inc) < car_max) && 23829a0bf528SMauro Carvalho Chehab ((offst_freq + inc) > -car_max) && 23839a0bf528SMauro Carvalho Chehab (cpt_step < steps_max)); 23849a0bf528SMauro Carvalho Chehab 23859a0bf528SMauro Carvalho Chehab reg = STV090x_READ_DEMOD(state, PDELCTRL1); 23869a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, ALGOSWRST_FIELD, 0); 23879a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, PDELCTRL1, reg) < 0) 23889a0bf528SMauro Carvalho Chehab goto err; 23899a0bf528SMauro Carvalho Chehab 23909a0bf528SMauro Carvalho Chehab return lock; 23919a0bf528SMauro Carvalho Chehab err: 23929a0bf528SMauro Carvalho Chehab dprintk(FE_ERROR, 1, "I/O error"); 23939a0bf528SMauro Carvalho Chehab return -1; 23949a0bf528SMauro Carvalho Chehab } 23959a0bf528SMauro Carvalho Chehab 23969a0bf528SMauro Carvalho Chehab static int stv090x_sw_algo(struct stv090x_state *state) 23979a0bf528SMauro Carvalho Chehab { 23989a0bf528SMauro Carvalho Chehab int no_signal, zigzag, lock = 0; 23999a0bf528SMauro Carvalho Chehab u32 reg; 24009a0bf528SMauro Carvalho Chehab 24019a0bf528SMauro Carvalho Chehab s32 dvbs2_fly_wheel; 24029a0bf528SMauro Carvalho Chehab s32 inc, timeout_step, trials, steps_max; 24039a0bf528SMauro Carvalho Chehab 24049a0bf528SMauro Carvalho Chehab /* get params */ 24059a0bf528SMauro Carvalho Chehab stv090x_get_loop_params(state, &inc, &timeout_step, &steps_max); 24069a0bf528SMauro Carvalho Chehab 24079a0bf528SMauro Carvalho Chehab switch (state->search_mode) { 24089a0bf528SMauro Carvalho Chehab case STV090x_SEARCH_DVBS1: 24099a0bf528SMauro Carvalho Chehab case STV090x_SEARCH_DSS: 24109a0bf528SMauro Carvalho Chehab /* accelerate the frequency detector */ 24119a0bf528SMauro Carvalho Chehab if (state->internal->dev_ver >= 0x20) { 24129a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x3B) < 0) 24139a0bf528SMauro Carvalho Chehab goto err; 24149a0bf528SMauro Carvalho Chehab } 24159a0bf528SMauro Carvalho Chehab 24169a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, DMDCFGMD, 0x49) < 0) 24179a0bf528SMauro Carvalho Chehab goto err; 24189a0bf528SMauro Carvalho Chehab zigzag = 0; 24199a0bf528SMauro Carvalho Chehab break; 24209a0bf528SMauro Carvalho Chehab 24219a0bf528SMauro Carvalho Chehab case STV090x_SEARCH_DVBS2: 24229a0bf528SMauro Carvalho Chehab if (state->internal->dev_ver >= 0x20) { 24239a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, CORRELABS, 0x79) < 0) 24249a0bf528SMauro Carvalho Chehab goto err; 24259a0bf528SMauro Carvalho Chehab } 24269a0bf528SMauro Carvalho Chehab 24279a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, DMDCFGMD, 0x89) < 0) 24289a0bf528SMauro Carvalho Chehab goto err; 24299a0bf528SMauro Carvalho Chehab zigzag = 1; 24309a0bf528SMauro Carvalho Chehab break; 24319a0bf528SMauro Carvalho Chehab 24329a0bf528SMauro Carvalho Chehab case STV090x_SEARCH_AUTO: 24339a0bf528SMauro Carvalho Chehab default: 24349a0bf528SMauro Carvalho Chehab /* accelerate the frequency detector */ 24359a0bf528SMauro Carvalho Chehab if (state->internal->dev_ver >= 0x20) { 24369a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x3b) < 0) 24379a0bf528SMauro Carvalho Chehab goto err; 24389a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, CORRELABS, 0x79) < 0) 24399a0bf528SMauro Carvalho Chehab goto err; 24409a0bf528SMauro Carvalho Chehab } 24419a0bf528SMauro Carvalho Chehab 24429a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, DMDCFGMD, 0xc9) < 0) 24439a0bf528SMauro Carvalho Chehab goto err; 24449a0bf528SMauro Carvalho Chehab zigzag = 0; 24459a0bf528SMauro Carvalho Chehab break; 24469a0bf528SMauro Carvalho Chehab } 24479a0bf528SMauro Carvalho Chehab 24489a0bf528SMauro Carvalho Chehab trials = 0; 24499a0bf528SMauro Carvalho Chehab do { 24509a0bf528SMauro Carvalho Chehab lock = stv090x_search_car_loop(state, inc, timeout_step, zigzag, steps_max); 24519a0bf528SMauro Carvalho Chehab no_signal = stv090x_chk_signal(state); 24529a0bf528SMauro Carvalho Chehab trials++; 24539a0bf528SMauro Carvalho Chehab 24549a0bf528SMauro Carvalho Chehab /*run the SW search 2 times maximum*/ 24559a0bf528SMauro Carvalho Chehab if (lock || no_signal || (trials == 2)) { 24569a0bf528SMauro Carvalho Chehab /*Check if the demod is not losing lock in DVBS2*/ 24579a0bf528SMauro Carvalho Chehab if (state->internal->dev_ver >= 0x20) { 24589a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x49) < 0) 24599a0bf528SMauro Carvalho Chehab goto err; 24609a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, CORRELABS, 0x9e) < 0) 24619a0bf528SMauro Carvalho Chehab goto err; 24629a0bf528SMauro Carvalho Chehab } 24639a0bf528SMauro Carvalho Chehab 24649a0bf528SMauro Carvalho Chehab reg = STV090x_READ_DEMOD(state, DMDSTATE); 24659a0bf528SMauro Carvalho Chehab if ((lock) && (STV090x_GETFIELD_Px(reg, HEADER_MODE_FIELD) == STV090x_DVBS2)) { 24669a0bf528SMauro Carvalho Chehab /*Check if the demod is not losing lock in DVBS2*/ 24679a0bf528SMauro Carvalho Chehab msleep(timeout_step); 24689a0bf528SMauro Carvalho Chehab reg = STV090x_READ_DEMOD(state, DMDFLYW); 24699a0bf528SMauro Carvalho Chehab dvbs2_fly_wheel = STV090x_GETFIELD_Px(reg, FLYWHEEL_CPT_FIELD); 24709a0bf528SMauro Carvalho Chehab if (dvbs2_fly_wheel < 0xd) { /*if correct frames is decrementing */ 24719a0bf528SMauro Carvalho Chehab msleep(timeout_step); 24729a0bf528SMauro Carvalho Chehab reg = STV090x_READ_DEMOD(state, DMDFLYW); 24739a0bf528SMauro Carvalho Chehab dvbs2_fly_wheel = STV090x_GETFIELD_Px(reg, FLYWHEEL_CPT_FIELD); 24749a0bf528SMauro Carvalho Chehab } 24759a0bf528SMauro Carvalho Chehab if (dvbs2_fly_wheel < 0xd) { 24769a0bf528SMauro Carvalho Chehab /*FALSE lock, The demod is losing lock */ 24779a0bf528SMauro Carvalho Chehab lock = 0; 24789a0bf528SMauro Carvalho Chehab if (trials < 2) { 24799a0bf528SMauro Carvalho Chehab if (state->internal->dev_ver >= 0x20) { 24809a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, CORRELABS, 0x79) < 0) 24819a0bf528SMauro Carvalho Chehab goto err; 24829a0bf528SMauro Carvalho Chehab } 24839a0bf528SMauro Carvalho Chehab 24849a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, DMDCFGMD, 0x89) < 0) 24859a0bf528SMauro Carvalho Chehab goto err; 24869a0bf528SMauro Carvalho Chehab } 24879a0bf528SMauro Carvalho Chehab } 24889a0bf528SMauro Carvalho Chehab } 24899a0bf528SMauro Carvalho Chehab } 24909a0bf528SMauro Carvalho Chehab } while ((!lock) && (trials < 2) && (!no_signal)); 24919a0bf528SMauro Carvalho Chehab 24929a0bf528SMauro Carvalho Chehab return lock; 24939a0bf528SMauro Carvalho Chehab err: 24949a0bf528SMauro Carvalho Chehab dprintk(FE_ERROR, 1, "I/O error"); 24959a0bf528SMauro Carvalho Chehab return -1; 24969a0bf528SMauro Carvalho Chehab } 24979a0bf528SMauro Carvalho Chehab 24989a0bf528SMauro Carvalho Chehab static enum stv090x_delsys stv090x_get_std(struct stv090x_state *state) 24999a0bf528SMauro Carvalho Chehab { 25009a0bf528SMauro Carvalho Chehab u32 reg; 25019a0bf528SMauro Carvalho Chehab enum stv090x_delsys delsys; 25029a0bf528SMauro Carvalho Chehab 25039a0bf528SMauro Carvalho Chehab reg = STV090x_READ_DEMOD(state, DMDSTATE); 25049a0bf528SMauro Carvalho Chehab if (STV090x_GETFIELD_Px(reg, HEADER_MODE_FIELD) == 2) 25059a0bf528SMauro Carvalho Chehab delsys = STV090x_DVBS2; 25069a0bf528SMauro Carvalho Chehab else if (STV090x_GETFIELD_Px(reg, HEADER_MODE_FIELD) == 3) { 25079a0bf528SMauro Carvalho Chehab reg = STV090x_READ_DEMOD(state, FECM); 25089a0bf528SMauro Carvalho Chehab if (STV090x_GETFIELD_Px(reg, DSS_DVB_FIELD) == 1) 25099a0bf528SMauro Carvalho Chehab delsys = STV090x_DSS; 25109a0bf528SMauro Carvalho Chehab else 25119a0bf528SMauro Carvalho Chehab delsys = STV090x_DVBS1; 25129a0bf528SMauro Carvalho Chehab } else { 25139a0bf528SMauro Carvalho Chehab delsys = STV090x_ERROR; 25149a0bf528SMauro Carvalho Chehab } 25159a0bf528SMauro Carvalho Chehab 25169a0bf528SMauro Carvalho Chehab return delsys; 25179a0bf528SMauro Carvalho Chehab } 25189a0bf528SMauro Carvalho Chehab 25199a0bf528SMauro Carvalho Chehab /* in Hz */ 25209a0bf528SMauro Carvalho Chehab static s32 stv090x_get_car_freq(struct stv090x_state *state, u32 mclk) 25219a0bf528SMauro Carvalho Chehab { 25229a0bf528SMauro Carvalho Chehab s32 derot, int_1, int_2, tmp_1, tmp_2; 25239a0bf528SMauro Carvalho Chehab 25249a0bf528SMauro Carvalho Chehab derot = STV090x_READ_DEMOD(state, CFR2) << 16; 25259a0bf528SMauro Carvalho Chehab derot |= STV090x_READ_DEMOD(state, CFR1) << 8; 25269a0bf528SMauro Carvalho Chehab derot |= STV090x_READ_DEMOD(state, CFR0); 25279a0bf528SMauro Carvalho Chehab 25289a0bf528SMauro Carvalho Chehab derot = comp2(derot, 24); 25299a0bf528SMauro Carvalho Chehab int_1 = mclk >> 12; 25309a0bf528SMauro Carvalho Chehab int_2 = derot >> 12; 25319a0bf528SMauro Carvalho Chehab 25329a0bf528SMauro Carvalho Chehab /* carrier_frequency = MasterClock * Reg / 2^24 */ 25339a0bf528SMauro Carvalho Chehab tmp_1 = mclk % 0x1000; 25349a0bf528SMauro Carvalho Chehab tmp_2 = derot % 0x1000; 25359a0bf528SMauro Carvalho Chehab 25369a0bf528SMauro Carvalho Chehab derot = (int_1 * int_2) + 25379a0bf528SMauro Carvalho Chehab ((int_1 * tmp_2) >> 12) + 25389a0bf528SMauro Carvalho Chehab ((int_2 * tmp_1) >> 12); 25399a0bf528SMauro Carvalho Chehab 25409a0bf528SMauro Carvalho Chehab return derot; 25419a0bf528SMauro Carvalho Chehab } 25429a0bf528SMauro Carvalho Chehab 25439a0bf528SMauro Carvalho Chehab static int stv090x_get_viterbi(struct stv090x_state *state) 25449a0bf528SMauro Carvalho Chehab { 25459a0bf528SMauro Carvalho Chehab u32 reg, rate; 25469a0bf528SMauro Carvalho Chehab 25479a0bf528SMauro Carvalho Chehab reg = STV090x_READ_DEMOD(state, VITCURPUN); 25489a0bf528SMauro Carvalho Chehab rate = STV090x_GETFIELD_Px(reg, VIT_CURPUN_FIELD); 25499a0bf528SMauro Carvalho Chehab 25509a0bf528SMauro Carvalho Chehab switch (rate) { 25519a0bf528SMauro Carvalho Chehab case 13: 25529a0bf528SMauro Carvalho Chehab state->fec = STV090x_PR12; 25539a0bf528SMauro Carvalho Chehab break; 25549a0bf528SMauro Carvalho Chehab 25559a0bf528SMauro Carvalho Chehab case 18: 25569a0bf528SMauro Carvalho Chehab state->fec = STV090x_PR23; 25579a0bf528SMauro Carvalho Chehab break; 25589a0bf528SMauro Carvalho Chehab 25599a0bf528SMauro Carvalho Chehab case 21: 25609a0bf528SMauro Carvalho Chehab state->fec = STV090x_PR34; 25619a0bf528SMauro Carvalho Chehab break; 25629a0bf528SMauro Carvalho Chehab 25639a0bf528SMauro Carvalho Chehab case 24: 25649a0bf528SMauro Carvalho Chehab state->fec = STV090x_PR56; 25659a0bf528SMauro Carvalho Chehab break; 25669a0bf528SMauro Carvalho Chehab 25679a0bf528SMauro Carvalho Chehab case 25: 25689a0bf528SMauro Carvalho Chehab state->fec = STV090x_PR67; 25699a0bf528SMauro Carvalho Chehab break; 25709a0bf528SMauro Carvalho Chehab 25719a0bf528SMauro Carvalho Chehab case 26: 25729a0bf528SMauro Carvalho Chehab state->fec = STV090x_PR78; 25739a0bf528SMauro Carvalho Chehab break; 25749a0bf528SMauro Carvalho Chehab 25759a0bf528SMauro Carvalho Chehab default: 25769a0bf528SMauro Carvalho Chehab state->fec = STV090x_PRERR; 25779a0bf528SMauro Carvalho Chehab break; 25789a0bf528SMauro Carvalho Chehab } 25799a0bf528SMauro Carvalho Chehab 25809a0bf528SMauro Carvalho Chehab return 0; 25819a0bf528SMauro Carvalho Chehab } 25829a0bf528SMauro Carvalho Chehab 25839a0bf528SMauro Carvalho Chehab static enum stv090x_signal_state stv090x_get_sig_params(struct stv090x_state *state) 25849a0bf528SMauro Carvalho Chehab { 25859a0bf528SMauro Carvalho Chehab struct dvb_frontend *fe = &state->frontend; 25869a0bf528SMauro Carvalho Chehab 25879a0bf528SMauro Carvalho Chehab u8 tmg; 25889a0bf528SMauro Carvalho Chehab u32 reg; 25899a0bf528SMauro Carvalho Chehab s32 i = 0, offst_freq; 25909a0bf528SMauro Carvalho Chehab 25919a0bf528SMauro Carvalho Chehab msleep(5); 25929a0bf528SMauro Carvalho Chehab 25939a0bf528SMauro Carvalho Chehab if (state->algo == STV090x_BLIND_SEARCH) { 25949a0bf528SMauro Carvalho Chehab tmg = STV090x_READ_DEMOD(state, TMGREG2); 25959a0bf528SMauro Carvalho Chehab STV090x_WRITE_DEMOD(state, SFRSTEP, 0x5c); 25969a0bf528SMauro Carvalho Chehab while ((i <= 50) && (tmg != 0) && (tmg != 0xff)) { 25979a0bf528SMauro Carvalho Chehab tmg = STV090x_READ_DEMOD(state, TMGREG2); 25989a0bf528SMauro Carvalho Chehab msleep(5); 25999a0bf528SMauro Carvalho Chehab i += 5; 26009a0bf528SMauro Carvalho Chehab } 26019a0bf528SMauro Carvalho Chehab } 26029a0bf528SMauro Carvalho Chehab state->delsys = stv090x_get_std(state); 26039a0bf528SMauro Carvalho Chehab 26049a0bf528SMauro Carvalho Chehab if (stv090x_i2c_gate_ctrl(state, 1) < 0) 26059a0bf528SMauro Carvalho Chehab goto err; 26069a0bf528SMauro Carvalho Chehab 26079a0bf528SMauro Carvalho Chehab if (state->config->tuner_get_frequency) { 26089a0bf528SMauro Carvalho Chehab if (state->config->tuner_get_frequency(fe, &state->frequency) < 0) 26099a0bf528SMauro Carvalho Chehab goto err_gateoff; 26109a0bf528SMauro Carvalho Chehab } 26119a0bf528SMauro Carvalho Chehab 26129a0bf528SMauro Carvalho Chehab if (stv090x_i2c_gate_ctrl(state, 0) < 0) 26139a0bf528SMauro Carvalho Chehab goto err; 26149a0bf528SMauro Carvalho Chehab 26159a0bf528SMauro Carvalho Chehab offst_freq = stv090x_get_car_freq(state, state->internal->mclk) / 1000; 26169a0bf528SMauro Carvalho Chehab state->frequency += offst_freq; 26179a0bf528SMauro Carvalho Chehab 26189a0bf528SMauro Carvalho Chehab if (stv090x_get_viterbi(state) < 0) 26199a0bf528SMauro Carvalho Chehab goto err; 26209a0bf528SMauro Carvalho Chehab 26219a0bf528SMauro Carvalho Chehab reg = STV090x_READ_DEMOD(state, DMDMODCOD); 26229a0bf528SMauro Carvalho Chehab state->modcod = STV090x_GETFIELD_Px(reg, DEMOD_MODCOD_FIELD); 26239a0bf528SMauro Carvalho Chehab state->pilots = STV090x_GETFIELD_Px(reg, DEMOD_TYPE_FIELD) & 0x01; 26249a0bf528SMauro Carvalho Chehab state->frame_len = STV090x_GETFIELD_Px(reg, DEMOD_TYPE_FIELD) >> 1; 26259a0bf528SMauro Carvalho Chehab reg = STV090x_READ_DEMOD(state, TMGOBS); 26269a0bf528SMauro Carvalho Chehab state->rolloff = STV090x_GETFIELD_Px(reg, ROLLOFF_STATUS_FIELD); 26279a0bf528SMauro Carvalho Chehab reg = STV090x_READ_DEMOD(state, FECM); 26289a0bf528SMauro Carvalho Chehab state->inversion = STV090x_GETFIELD_Px(reg, IQINV_FIELD); 26299a0bf528SMauro Carvalho Chehab 26309a0bf528SMauro Carvalho Chehab if ((state->algo == STV090x_BLIND_SEARCH) || (state->srate < 10000000)) { 26319a0bf528SMauro Carvalho Chehab 26329a0bf528SMauro Carvalho Chehab if (stv090x_i2c_gate_ctrl(state, 1) < 0) 26339a0bf528SMauro Carvalho Chehab goto err; 26349a0bf528SMauro Carvalho Chehab 26359a0bf528SMauro Carvalho Chehab if (state->config->tuner_get_frequency) { 26369a0bf528SMauro Carvalho Chehab if (state->config->tuner_get_frequency(fe, &state->frequency) < 0) 26379a0bf528SMauro Carvalho Chehab goto err_gateoff; 26389a0bf528SMauro Carvalho Chehab } 26399a0bf528SMauro Carvalho Chehab 26409a0bf528SMauro Carvalho Chehab if (stv090x_i2c_gate_ctrl(state, 0) < 0) 26419a0bf528SMauro Carvalho Chehab goto err; 26429a0bf528SMauro Carvalho Chehab 26439a0bf528SMauro Carvalho Chehab if (abs(offst_freq) <= ((state->search_range / 2000) + 500)) 26449a0bf528SMauro Carvalho Chehab return STV090x_RANGEOK; 26459a0bf528SMauro Carvalho Chehab else if (abs(offst_freq) <= (stv090x_car_width(state->srate, state->rolloff) / 2000)) 26469a0bf528SMauro Carvalho Chehab return STV090x_RANGEOK; 26479a0bf528SMauro Carvalho Chehab } else { 26489a0bf528SMauro Carvalho Chehab if (abs(offst_freq) <= ((state->search_range / 2000) + 500)) 26499a0bf528SMauro Carvalho Chehab return STV090x_RANGEOK; 26509a0bf528SMauro Carvalho Chehab } 26519a0bf528SMauro Carvalho Chehab 26529a0bf528SMauro Carvalho Chehab return STV090x_OUTOFRANGE; 26539a0bf528SMauro Carvalho Chehab 26549a0bf528SMauro Carvalho Chehab err_gateoff: 26559a0bf528SMauro Carvalho Chehab stv090x_i2c_gate_ctrl(state, 0); 26569a0bf528SMauro Carvalho Chehab err: 26579a0bf528SMauro Carvalho Chehab dprintk(FE_ERROR, 1, "I/O error"); 26589a0bf528SMauro Carvalho Chehab return -1; 26599a0bf528SMauro Carvalho Chehab } 26609a0bf528SMauro Carvalho Chehab 26619a0bf528SMauro Carvalho Chehab static u32 stv090x_get_tmgoffst(struct stv090x_state *state, u32 srate) 26629a0bf528SMauro Carvalho Chehab { 26639a0bf528SMauro Carvalho Chehab s32 offst_tmg; 26649a0bf528SMauro Carvalho Chehab 26659a0bf528SMauro Carvalho Chehab offst_tmg = STV090x_READ_DEMOD(state, TMGREG2) << 16; 26669a0bf528SMauro Carvalho Chehab offst_tmg |= STV090x_READ_DEMOD(state, TMGREG1) << 8; 26679a0bf528SMauro Carvalho Chehab offst_tmg |= STV090x_READ_DEMOD(state, TMGREG0); 26689a0bf528SMauro Carvalho Chehab 26699a0bf528SMauro Carvalho Chehab offst_tmg = comp2(offst_tmg, 24); /* 2's complement */ 26709a0bf528SMauro Carvalho Chehab if (!offst_tmg) 26719a0bf528SMauro Carvalho Chehab offst_tmg = 1; 26729a0bf528SMauro Carvalho Chehab 26739a0bf528SMauro Carvalho Chehab offst_tmg = ((s32) srate * 10) / ((s32) 0x1000000 / offst_tmg); 26749a0bf528SMauro Carvalho Chehab offst_tmg /= 320; 26759a0bf528SMauro Carvalho Chehab 26769a0bf528SMauro Carvalho Chehab return offst_tmg; 26779a0bf528SMauro Carvalho Chehab } 26789a0bf528SMauro Carvalho Chehab 26799a0bf528SMauro Carvalho Chehab static u8 stv090x_optimize_carloop(struct stv090x_state *state, enum stv090x_modcod modcod, s32 pilots) 26809a0bf528SMauro Carvalho Chehab { 26819a0bf528SMauro Carvalho Chehab u8 aclc = 0x29; 26829a0bf528SMauro Carvalho Chehab s32 i; 26839a0bf528SMauro Carvalho Chehab struct stv090x_long_frame_crloop *car_loop, *car_loop_qpsk_low, *car_loop_apsk_low; 26849a0bf528SMauro Carvalho Chehab 26859a0bf528SMauro Carvalho Chehab if (state->internal->dev_ver == 0x20) { 26869a0bf528SMauro Carvalho Chehab car_loop = stv090x_s2_crl_cut20; 26879a0bf528SMauro Carvalho Chehab car_loop_qpsk_low = stv090x_s2_lowqpsk_crl_cut20; 26889a0bf528SMauro Carvalho Chehab car_loop_apsk_low = stv090x_s2_apsk_crl_cut20; 26899a0bf528SMauro Carvalho Chehab } else { 26909a0bf528SMauro Carvalho Chehab /* >= Cut 3 */ 26919a0bf528SMauro Carvalho Chehab car_loop = stv090x_s2_crl_cut30; 26929a0bf528SMauro Carvalho Chehab car_loop_qpsk_low = stv090x_s2_lowqpsk_crl_cut30; 26939a0bf528SMauro Carvalho Chehab car_loop_apsk_low = stv090x_s2_apsk_crl_cut30; 26949a0bf528SMauro Carvalho Chehab } 26959a0bf528SMauro Carvalho Chehab 26969a0bf528SMauro Carvalho Chehab if (modcod < STV090x_QPSK_12) { 26979a0bf528SMauro Carvalho Chehab i = 0; 26989a0bf528SMauro Carvalho Chehab while ((i < 3) && (modcod != car_loop_qpsk_low[i].modcod)) 26999a0bf528SMauro Carvalho Chehab i++; 27009a0bf528SMauro Carvalho Chehab 27019a0bf528SMauro Carvalho Chehab if (i >= 3) 27029a0bf528SMauro Carvalho Chehab i = 2; 27039a0bf528SMauro Carvalho Chehab 27049a0bf528SMauro Carvalho Chehab } else { 27059a0bf528SMauro Carvalho Chehab i = 0; 27069a0bf528SMauro Carvalho Chehab while ((i < 14) && (modcod != car_loop[i].modcod)) 27079a0bf528SMauro Carvalho Chehab i++; 27089a0bf528SMauro Carvalho Chehab 27099a0bf528SMauro Carvalho Chehab if (i >= 14) { 27109a0bf528SMauro Carvalho Chehab i = 0; 27119a0bf528SMauro Carvalho Chehab while ((i < 11) && (modcod != car_loop_apsk_low[i].modcod)) 27129a0bf528SMauro Carvalho Chehab i++; 27139a0bf528SMauro Carvalho Chehab 27149a0bf528SMauro Carvalho Chehab if (i >= 11) 27159a0bf528SMauro Carvalho Chehab i = 10; 27169a0bf528SMauro Carvalho Chehab } 27179a0bf528SMauro Carvalho Chehab } 27189a0bf528SMauro Carvalho Chehab 27199a0bf528SMauro Carvalho Chehab if (modcod <= STV090x_QPSK_25) { 27209a0bf528SMauro Carvalho Chehab if (pilots) { 27219a0bf528SMauro Carvalho Chehab if (state->srate <= 3000000) 27229a0bf528SMauro Carvalho Chehab aclc = car_loop_qpsk_low[i].crl_pilots_on_2; 27239a0bf528SMauro Carvalho Chehab else if (state->srate <= 7000000) 27249a0bf528SMauro Carvalho Chehab aclc = car_loop_qpsk_low[i].crl_pilots_on_5; 27259a0bf528SMauro Carvalho Chehab else if (state->srate <= 15000000) 27269a0bf528SMauro Carvalho Chehab aclc = car_loop_qpsk_low[i].crl_pilots_on_10; 27279a0bf528SMauro Carvalho Chehab else if (state->srate <= 25000000) 27289a0bf528SMauro Carvalho Chehab aclc = car_loop_qpsk_low[i].crl_pilots_on_20; 27299a0bf528SMauro Carvalho Chehab else 27309a0bf528SMauro Carvalho Chehab aclc = car_loop_qpsk_low[i].crl_pilots_on_30; 27319a0bf528SMauro Carvalho Chehab } else { 27329a0bf528SMauro Carvalho Chehab if (state->srate <= 3000000) 27339a0bf528SMauro Carvalho Chehab aclc = car_loop_qpsk_low[i].crl_pilots_off_2; 27349a0bf528SMauro Carvalho Chehab else if (state->srate <= 7000000) 27359a0bf528SMauro Carvalho Chehab aclc = car_loop_qpsk_low[i].crl_pilots_off_5; 27369a0bf528SMauro Carvalho Chehab else if (state->srate <= 15000000) 27379a0bf528SMauro Carvalho Chehab aclc = car_loop_qpsk_low[i].crl_pilots_off_10; 27389a0bf528SMauro Carvalho Chehab else if (state->srate <= 25000000) 27399a0bf528SMauro Carvalho Chehab aclc = car_loop_qpsk_low[i].crl_pilots_off_20; 27409a0bf528SMauro Carvalho Chehab else 27419a0bf528SMauro Carvalho Chehab aclc = car_loop_qpsk_low[i].crl_pilots_off_30; 27429a0bf528SMauro Carvalho Chehab } 27439a0bf528SMauro Carvalho Chehab 27449a0bf528SMauro Carvalho Chehab } else if (modcod <= STV090x_8PSK_910) { 27459a0bf528SMauro Carvalho Chehab if (pilots) { 27469a0bf528SMauro Carvalho Chehab if (state->srate <= 3000000) 27479a0bf528SMauro Carvalho Chehab aclc = car_loop[i].crl_pilots_on_2; 27489a0bf528SMauro Carvalho Chehab else if (state->srate <= 7000000) 27499a0bf528SMauro Carvalho Chehab aclc = car_loop[i].crl_pilots_on_5; 27509a0bf528SMauro Carvalho Chehab else if (state->srate <= 15000000) 27519a0bf528SMauro Carvalho Chehab aclc = car_loop[i].crl_pilots_on_10; 27529a0bf528SMauro Carvalho Chehab else if (state->srate <= 25000000) 27539a0bf528SMauro Carvalho Chehab aclc = car_loop[i].crl_pilots_on_20; 27549a0bf528SMauro Carvalho Chehab else 27559a0bf528SMauro Carvalho Chehab aclc = car_loop[i].crl_pilots_on_30; 27569a0bf528SMauro Carvalho Chehab } else { 27579a0bf528SMauro Carvalho Chehab if (state->srate <= 3000000) 27589a0bf528SMauro Carvalho Chehab aclc = car_loop[i].crl_pilots_off_2; 27599a0bf528SMauro Carvalho Chehab else if (state->srate <= 7000000) 27609a0bf528SMauro Carvalho Chehab aclc = car_loop[i].crl_pilots_off_5; 27619a0bf528SMauro Carvalho Chehab else if (state->srate <= 15000000) 27629a0bf528SMauro Carvalho Chehab aclc = car_loop[i].crl_pilots_off_10; 27639a0bf528SMauro Carvalho Chehab else if (state->srate <= 25000000) 27649a0bf528SMauro Carvalho Chehab aclc = car_loop[i].crl_pilots_off_20; 27659a0bf528SMauro Carvalho Chehab else 27669a0bf528SMauro Carvalho Chehab aclc = car_loop[i].crl_pilots_off_30; 27679a0bf528SMauro Carvalho Chehab } 27689a0bf528SMauro Carvalho Chehab } else { /* 16APSK and 32APSK */ 2769ffe30010SMauro Carvalho Chehab /* 2770ffe30010SMauro Carvalho Chehab * This should never happen in practice, except if 2771ffe30010SMauro Carvalho Chehab * something is really wrong at the car_loop table. 2772ffe30010SMauro Carvalho Chehab */ 2773ffe30010SMauro Carvalho Chehab if (i >= 11) 2774ffe30010SMauro Carvalho Chehab i = 10; 27759a0bf528SMauro Carvalho Chehab if (state->srate <= 3000000) 27769a0bf528SMauro Carvalho Chehab aclc = car_loop_apsk_low[i].crl_pilots_on_2; 27779a0bf528SMauro Carvalho Chehab else if (state->srate <= 7000000) 27789a0bf528SMauro Carvalho Chehab aclc = car_loop_apsk_low[i].crl_pilots_on_5; 27799a0bf528SMauro Carvalho Chehab else if (state->srate <= 15000000) 27809a0bf528SMauro Carvalho Chehab aclc = car_loop_apsk_low[i].crl_pilots_on_10; 27819a0bf528SMauro Carvalho Chehab else if (state->srate <= 25000000) 27829a0bf528SMauro Carvalho Chehab aclc = car_loop_apsk_low[i].crl_pilots_on_20; 27839a0bf528SMauro Carvalho Chehab else 27849a0bf528SMauro Carvalho Chehab aclc = car_loop_apsk_low[i].crl_pilots_on_30; 27859a0bf528SMauro Carvalho Chehab } 27869a0bf528SMauro Carvalho Chehab 27879a0bf528SMauro Carvalho Chehab return aclc; 27889a0bf528SMauro Carvalho Chehab } 27899a0bf528SMauro Carvalho Chehab 27909a0bf528SMauro Carvalho Chehab static u8 stv090x_optimize_carloop_short(struct stv090x_state *state) 27919a0bf528SMauro Carvalho Chehab { 27929a0bf528SMauro Carvalho Chehab struct stv090x_short_frame_crloop *short_crl = NULL; 27939a0bf528SMauro Carvalho Chehab s32 index = 0; 27949a0bf528SMauro Carvalho Chehab u8 aclc = 0x0b; 27959a0bf528SMauro Carvalho Chehab 27969a0bf528SMauro Carvalho Chehab switch (state->modulation) { 27979a0bf528SMauro Carvalho Chehab case STV090x_QPSK: 27989a0bf528SMauro Carvalho Chehab default: 27999a0bf528SMauro Carvalho Chehab index = 0; 28009a0bf528SMauro Carvalho Chehab break; 28019a0bf528SMauro Carvalho Chehab case STV090x_8PSK: 28029a0bf528SMauro Carvalho Chehab index = 1; 28039a0bf528SMauro Carvalho Chehab break; 28049a0bf528SMauro Carvalho Chehab case STV090x_16APSK: 28059a0bf528SMauro Carvalho Chehab index = 2; 28069a0bf528SMauro Carvalho Chehab break; 28079a0bf528SMauro Carvalho Chehab case STV090x_32APSK: 28089a0bf528SMauro Carvalho Chehab index = 3; 28099a0bf528SMauro Carvalho Chehab break; 28109a0bf528SMauro Carvalho Chehab } 28119a0bf528SMauro Carvalho Chehab 28129a0bf528SMauro Carvalho Chehab if (state->internal->dev_ver >= 0x30) { 28139a0bf528SMauro Carvalho Chehab /* Cut 3.0 and up */ 28149a0bf528SMauro Carvalho Chehab short_crl = stv090x_s2_short_crl_cut30; 28159a0bf528SMauro Carvalho Chehab } else { 28169a0bf528SMauro Carvalho Chehab /* Cut 2.0 and up: we don't support cuts older than 2.0 */ 28179a0bf528SMauro Carvalho Chehab short_crl = stv090x_s2_short_crl_cut20; 28189a0bf528SMauro Carvalho Chehab } 28199a0bf528SMauro Carvalho Chehab 28209a0bf528SMauro Carvalho Chehab if (state->srate <= 3000000) 28219a0bf528SMauro Carvalho Chehab aclc = short_crl[index].crl_2; 28229a0bf528SMauro Carvalho Chehab else if (state->srate <= 7000000) 28239a0bf528SMauro Carvalho Chehab aclc = short_crl[index].crl_5; 28249a0bf528SMauro Carvalho Chehab else if (state->srate <= 15000000) 28259a0bf528SMauro Carvalho Chehab aclc = short_crl[index].crl_10; 28269a0bf528SMauro Carvalho Chehab else if (state->srate <= 25000000) 28279a0bf528SMauro Carvalho Chehab aclc = short_crl[index].crl_20; 28289a0bf528SMauro Carvalho Chehab else 28299a0bf528SMauro Carvalho Chehab aclc = short_crl[index].crl_30; 28309a0bf528SMauro Carvalho Chehab 28319a0bf528SMauro Carvalho Chehab return aclc; 28329a0bf528SMauro Carvalho Chehab } 28339a0bf528SMauro Carvalho Chehab 28349a0bf528SMauro Carvalho Chehab static int stv090x_optimize_track(struct stv090x_state *state) 28359a0bf528SMauro Carvalho Chehab { 28369a0bf528SMauro Carvalho Chehab struct dvb_frontend *fe = &state->frontend; 28379a0bf528SMauro Carvalho Chehab 28389a0bf528SMauro Carvalho Chehab enum stv090x_modcod modcod; 28399a0bf528SMauro Carvalho Chehab 28409a0bf528SMauro Carvalho Chehab s32 srate, pilots, aclc, f_1, f_0, i = 0, blind_tune = 0; 28419a0bf528SMauro Carvalho Chehab u32 reg; 28429a0bf528SMauro Carvalho Chehab 28439a0bf528SMauro Carvalho Chehab srate = stv090x_get_srate(state, state->internal->mclk); 28449a0bf528SMauro Carvalho Chehab srate += stv090x_get_tmgoffst(state, srate); 28459a0bf528SMauro Carvalho Chehab 28469a0bf528SMauro Carvalho Chehab switch (state->delsys) { 28479a0bf528SMauro Carvalho Chehab case STV090x_DVBS1: 28489a0bf528SMauro Carvalho Chehab case STV090x_DSS: 28499a0bf528SMauro Carvalho Chehab if (state->search_mode == STV090x_SEARCH_AUTO) { 28509a0bf528SMauro Carvalho Chehab reg = STV090x_READ_DEMOD(state, DMDCFGMD); 28519a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, DVBS1_ENABLE_FIELD, 1); 28529a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, DVBS2_ENABLE_FIELD, 0); 28539a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0) 28549a0bf528SMauro Carvalho Chehab goto err; 28559a0bf528SMauro Carvalho Chehab } 28569a0bf528SMauro Carvalho Chehab reg = STV090x_READ_DEMOD(state, DEMOD); 28579a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, ROLLOFF_CONTROL_FIELD, state->rolloff); 28589a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, MANUAL_SXROLLOFF_FIELD, 0x01); 28599a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, DEMOD, reg) < 0) 28609a0bf528SMauro Carvalho Chehab goto err; 28619a0bf528SMauro Carvalho Chehab 28629a0bf528SMauro Carvalho Chehab if (state->internal->dev_ver >= 0x30) { 28639a0bf528SMauro Carvalho Chehab if (stv090x_get_viterbi(state) < 0) 28649a0bf528SMauro Carvalho Chehab goto err; 28659a0bf528SMauro Carvalho Chehab 28669a0bf528SMauro Carvalho Chehab if (state->fec == STV090x_PR12) { 28679a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, GAUSSR0, 0x98) < 0) 28689a0bf528SMauro Carvalho Chehab goto err; 28699a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, CCIR0, 0x18) < 0) 28709a0bf528SMauro Carvalho Chehab goto err; 28719a0bf528SMauro Carvalho Chehab } else { 28729a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, GAUSSR0, 0x18) < 0) 28739a0bf528SMauro Carvalho Chehab goto err; 28749a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, CCIR0, 0x18) < 0) 28759a0bf528SMauro Carvalho Chehab goto err; 28769a0bf528SMauro Carvalho Chehab } 28779a0bf528SMauro Carvalho Chehab } 28789a0bf528SMauro Carvalho Chehab 28799a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, ERRCTRL1, 0x75) < 0) 28809a0bf528SMauro Carvalho Chehab goto err; 28819a0bf528SMauro Carvalho Chehab break; 28829a0bf528SMauro Carvalho Chehab 28839a0bf528SMauro Carvalho Chehab case STV090x_DVBS2: 28849a0bf528SMauro Carvalho Chehab reg = STV090x_READ_DEMOD(state, DMDCFGMD); 28859a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, DVBS1_ENABLE_FIELD, 0); 28869a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, DVBS2_ENABLE_FIELD, 1); 28879a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0) 28889a0bf528SMauro Carvalho Chehab goto err; 28899a0bf528SMauro Carvalho Chehab if (state->internal->dev_ver >= 0x30) { 28909a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, ACLC, 0) < 0) 28919a0bf528SMauro Carvalho Chehab goto err; 28929a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, BCLC, 0) < 0) 28939a0bf528SMauro Carvalho Chehab goto err; 28949a0bf528SMauro Carvalho Chehab } 28959a0bf528SMauro Carvalho Chehab if (state->frame_len == STV090x_LONG_FRAME) { 28969a0bf528SMauro Carvalho Chehab reg = STV090x_READ_DEMOD(state, DMDMODCOD); 28979a0bf528SMauro Carvalho Chehab modcod = STV090x_GETFIELD_Px(reg, DEMOD_MODCOD_FIELD); 28989a0bf528SMauro Carvalho Chehab pilots = STV090x_GETFIELD_Px(reg, DEMOD_TYPE_FIELD) & 0x01; 28999a0bf528SMauro Carvalho Chehab aclc = stv090x_optimize_carloop(state, modcod, pilots); 29009a0bf528SMauro Carvalho Chehab if (modcod <= STV090x_QPSK_910) { 29019a0bf528SMauro Carvalho Chehab STV090x_WRITE_DEMOD(state, ACLC2S2Q, aclc); 29029a0bf528SMauro Carvalho Chehab } else if (modcod <= STV090x_8PSK_910) { 29039a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, ACLC2S2Q, 0x2a) < 0) 29049a0bf528SMauro Carvalho Chehab goto err; 29059a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, ACLC2S28, aclc) < 0) 29069a0bf528SMauro Carvalho Chehab goto err; 29079a0bf528SMauro Carvalho Chehab } 29089a0bf528SMauro Carvalho Chehab if ((state->demod_mode == STV090x_SINGLE) && (modcod > STV090x_8PSK_910)) { 29099a0bf528SMauro Carvalho Chehab if (modcod <= STV090x_16APSK_910) { 29109a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, ACLC2S2Q, 0x2a) < 0) 29119a0bf528SMauro Carvalho Chehab goto err; 29129a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, ACLC2S216A, aclc) < 0) 29139a0bf528SMauro Carvalho Chehab goto err; 29149a0bf528SMauro Carvalho Chehab } else { 29159a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, ACLC2S2Q, 0x2a) < 0) 29169a0bf528SMauro Carvalho Chehab goto err; 29179a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, ACLC2S232A, aclc) < 0) 29189a0bf528SMauro Carvalho Chehab goto err; 29199a0bf528SMauro Carvalho Chehab } 29209a0bf528SMauro Carvalho Chehab } 29219a0bf528SMauro Carvalho Chehab } else { 29229a0bf528SMauro Carvalho Chehab /*Carrier loop setting for short frame*/ 29239a0bf528SMauro Carvalho Chehab aclc = stv090x_optimize_carloop_short(state); 29249a0bf528SMauro Carvalho Chehab if (state->modulation == STV090x_QPSK) { 29259a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, ACLC2S2Q, aclc) < 0) 29269a0bf528SMauro Carvalho Chehab goto err; 29279a0bf528SMauro Carvalho Chehab } else if (state->modulation == STV090x_8PSK) { 29289a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, ACLC2S2Q, 0x2a) < 0) 29299a0bf528SMauro Carvalho Chehab goto err; 29309a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, ACLC2S28, aclc) < 0) 29319a0bf528SMauro Carvalho Chehab goto err; 29329a0bf528SMauro Carvalho Chehab } else if (state->modulation == STV090x_16APSK) { 29339a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, ACLC2S2Q, 0x2a) < 0) 29349a0bf528SMauro Carvalho Chehab goto err; 29359a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, ACLC2S216A, aclc) < 0) 29369a0bf528SMauro Carvalho Chehab goto err; 29379a0bf528SMauro Carvalho Chehab } else if (state->modulation == STV090x_32APSK) { 29389a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, ACLC2S2Q, 0x2a) < 0) 29399a0bf528SMauro Carvalho Chehab goto err; 29409a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, ACLC2S232A, aclc) < 0) 29419a0bf528SMauro Carvalho Chehab goto err; 29429a0bf528SMauro Carvalho Chehab } 29439a0bf528SMauro Carvalho Chehab } 29449a0bf528SMauro Carvalho Chehab 29459a0bf528SMauro Carvalho Chehab STV090x_WRITE_DEMOD(state, ERRCTRL1, 0x67); /* PER */ 29469a0bf528SMauro Carvalho Chehab break; 29479a0bf528SMauro Carvalho Chehab 29489a0bf528SMauro Carvalho Chehab case STV090x_ERROR: 29499a0bf528SMauro Carvalho Chehab default: 29509a0bf528SMauro Carvalho Chehab reg = STV090x_READ_DEMOD(state, DMDCFGMD); 29519a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, DVBS1_ENABLE_FIELD, 1); 29529a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, DVBS2_ENABLE_FIELD, 1); 29539a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0) 29549a0bf528SMauro Carvalho Chehab goto err; 29559a0bf528SMauro Carvalho Chehab break; 29569a0bf528SMauro Carvalho Chehab } 29579a0bf528SMauro Carvalho Chehab 29589a0bf528SMauro Carvalho Chehab f_1 = STV090x_READ_DEMOD(state, CFR2); 29599a0bf528SMauro Carvalho Chehab f_0 = STV090x_READ_DEMOD(state, CFR1); 29609a0bf528SMauro Carvalho Chehab reg = STV090x_READ_DEMOD(state, TMGOBS); 29619a0bf528SMauro Carvalho Chehab 29629a0bf528SMauro Carvalho Chehab if (state->algo == STV090x_BLIND_SEARCH) { 29639a0bf528SMauro Carvalho Chehab STV090x_WRITE_DEMOD(state, SFRSTEP, 0x00); 29649a0bf528SMauro Carvalho Chehab reg = STV090x_READ_DEMOD(state, DMDCFGMD); 29659a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, SCAN_ENABLE_FIELD, 0x00); 29669a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, CFR_AUTOSCAN_FIELD, 0x00); 29679a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0) 29689a0bf528SMauro Carvalho Chehab goto err; 29699a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, TMGCFG2, 0xc1) < 0) 29709a0bf528SMauro Carvalho Chehab goto err; 29719a0bf528SMauro Carvalho Chehab 29729a0bf528SMauro Carvalho Chehab if (stv090x_set_srate(state, srate) < 0) 29739a0bf528SMauro Carvalho Chehab goto err; 29749a0bf528SMauro Carvalho Chehab blind_tune = 1; 29759a0bf528SMauro Carvalho Chehab 29769a0bf528SMauro Carvalho Chehab if (stv090x_dvbs_track_crl(state) < 0) 29779a0bf528SMauro Carvalho Chehab goto err; 29789a0bf528SMauro Carvalho Chehab } 29799a0bf528SMauro Carvalho Chehab 29809a0bf528SMauro Carvalho Chehab if (state->internal->dev_ver >= 0x20) { 29819a0bf528SMauro Carvalho Chehab if ((state->search_mode == STV090x_SEARCH_DVBS1) || 29829a0bf528SMauro Carvalho Chehab (state->search_mode == STV090x_SEARCH_DSS) || 29839a0bf528SMauro Carvalho Chehab (state->search_mode == STV090x_SEARCH_AUTO)) { 29849a0bf528SMauro Carvalho Chehab 29859a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, VAVSRVIT, 0x0a) < 0) 29869a0bf528SMauro Carvalho Chehab goto err; 29879a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, VITSCALE, 0x00) < 0) 29889a0bf528SMauro Carvalho Chehab goto err; 29899a0bf528SMauro Carvalho Chehab } 29909a0bf528SMauro Carvalho Chehab } 29919a0bf528SMauro Carvalho Chehab 29929a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, AGC2REF, 0x38) < 0) 29939a0bf528SMauro Carvalho Chehab goto err; 29949a0bf528SMauro Carvalho Chehab 29959a0bf528SMauro Carvalho Chehab /* AUTO tracking MODE */ 29969a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, SFRUP1, 0x80) < 0) 29979a0bf528SMauro Carvalho Chehab goto err; 29989a0bf528SMauro Carvalho Chehab /* AUTO tracking MODE */ 29999a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, SFRLOW1, 0x80) < 0) 30009a0bf528SMauro Carvalho Chehab goto err; 30019a0bf528SMauro Carvalho Chehab 30029a0bf528SMauro Carvalho Chehab if ((state->internal->dev_ver >= 0x20) || (blind_tune == 1) || 30039a0bf528SMauro Carvalho Chehab (state->srate < 10000000)) { 30049a0bf528SMauro Carvalho Chehab /* update initial carrier freq with the found freq offset */ 30059a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, CFRINIT1, f_1) < 0) 30069a0bf528SMauro Carvalho Chehab goto err; 30079a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, CFRINIT0, f_0) < 0) 30089a0bf528SMauro Carvalho Chehab goto err; 30099a0bf528SMauro Carvalho Chehab state->tuner_bw = stv090x_car_width(srate, state->rolloff) + 10000000; 30109a0bf528SMauro Carvalho Chehab 30119a0bf528SMauro Carvalho Chehab if ((state->internal->dev_ver >= 0x20) || (blind_tune == 1)) { 30129a0bf528SMauro Carvalho Chehab 30139a0bf528SMauro Carvalho Chehab if (state->algo != STV090x_WARM_SEARCH) { 30149a0bf528SMauro Carvalho Chehab 30159a0bf528SMauro Carvalho Chehab if (stv090x_i2c_gate_ctrl(state, 1) < 0) 30169a0bf528SMauro Carvalho Chehab goto err; 30179a0bf528SMauro Carvalho Chehab 30189a0bf528SMauro Carvalho Chehab if (state->config->tuner_set_bandwidth) { 30199a0bf528SMauro Carvalho Chehab if (state->config->tuner_set_bandwidth(fe, state->tuner_bw) < 0) 30209a0bf528SMauro Carvalho Chehab goto err_gateoff; 30219a0bf528SMauro Carvalho Chehab } 30229a0bf528SMauro Carvalho Chehab 30239a0bf528SMauro Carvalho Chehab if (stv090x_i2c_gate_ctrl(state, 0) < 0) 30249a0bf528SMauro Carvalho Chehab goto err; 30259a0bf528SMauro Carvalho Chehab 30269a0bf528SMauro Carvalho Chehab } 30279a0bf528SMauro Carvalho Chehab } 30289a0bf528SMauro Carvalho Chehab if ((state->algo == STV090x_BLIND_SEARCH) || (state->srate < 10000000)) 30299a0bf528SMauro Carvalho Chehab msleep(50); /* blind search: wait 50ms for SR stabilization */ 30309a0bf528SMauro Carvalho Chehab else 30319a0bf528SMauro Carvalho Chehab msleep(5); 30329a0bf528SMauro Carvalho Chehab 30339a0bf528SMauro Carvalho Chehab stv090x_get_lock_tmg(state); 30349a0bf528SMauro Carvalho Chehab 30359a0bf528SMauro Carvalho Chehab if (!(stv090x_get_dmdlock(state, (state->DemodTimeout / 2)))) { 30369a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1f) < 0) 30379a0bf528SMauro Carvalho Chehab goto err; 30389a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, CFRINIT1, f_1) < 0) 30399a0bf528SMauro Carvalho Chehab goto err; 30409a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, CFRINIT0, f_0) < 0) 30419a0bf528SMauro Carvalho Chehab goto err; 30429a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x18) < 0) 30439a0bf528SMauro Carvalho Chehab goto err; 30449a0bf528SMauro Carvalho Chehab 30459a0bf528SMauro Carvalho Chehab i = 0; 30469a0bf528SMauro Carvalho Chehab 30479a0bf528SMauro Carvalho Chehab while ((!(stv090x_get_dmdlock(state, (state->DemodTimeout / 2)))) && (i <= 2)) { 30489a0bf528SMauro Carvalho Chehab 30499a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1f) < 0) 30509a0bf528SMauro Carvalho Chehab goto err; 30519a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, CFRINIT1, f_1) < 0) 30529a0bf528SMauro Carvalho Chehab goto err; 30539a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, CFRINIT0, f_0) < 0) 30549a0bf528SMauro Carvalho Chehab goto err; 30559a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x18) < 0) 30569a0bf528SMauro Carvalho Chehab goto err; 30579a0bf528SMauro Carvalho Chehab i++; 30589a0bf528SMauro Carvalho Chehab } 30599a0bf528SMauro Carvalho Chehab } 30609a0bf528SMauro Carvalho Chehab 30619a0bf528SMauro Carvalho Chehab } 30629a0bf528SMauro Carvalho Chehab 30639a0bf528SMauro Carvalho Chehab if (state->internal->dev_ver >= 0x20) { 30649a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x49) < 0) 30659a0bf528SMauro Carvalho Chehab goto err; 30669a0bf528SMauro Carvalho Chehab } 30679a0bf528SMauro Carvalho Chehab 30689a0bf528SMauro Carvalho Chehab if ((state->delsys == STV090x_DVBS1) || (state->delsys == STV090x_DSS)) 30699a0bf528SMauro Carvalho Chehab stv090x_set_vit_thtracq(state); 30709a0bf528SMauro Carvalho Chehab 30719a0bf528SMauro Carvalho Chehab return 0; 30729a0bf528SMauro Carvalho Chehab 30739a0bf528SMauro Carvalho Chehab err_gateoff: 30749a0bf528SMauro Carvalho Chehab stv090x_i2c_gate_ctrl(state, 0); 30759a0bf528SMauro Carvalho Chehab err: 30769a0bf528SMauro Carvalho Chehab dprintk(FE_ERROR, 1, "I/O error"); 30779a0bf528SMauro Carvalho Chehab return -1; 30789a0bf528SMauro Carvalho Chehab } 30799a0bf528SMauro Carvalho Chehab 30809a0bf528SMauro Carvalho Chehab static int stv090x_get_feclock(struct stv090x_state *state, s32 timeout) 30819a0bf528SMauro Carvalho Chehab { 30829a0bf528SMauro Carvalho Chehab s32 timer = 0, lock = 0, stat; 30839a0bf528SMauro Carvalho Chehab u32 reg; 30849a0bf528SMauro Carvalho Chehab 30859a0bf528SMauro Carvalho Chehab while ((timer < timeout) && (!lock)) { 30869a0bf528SMauro Carvalho Chehab reg = STV090x_READ_DEMOD(state, DMDSTATE); 30879a0bf528SMauro Carvalho Chehab stat = STV090x_GETFIELD_Px(reg, HEADER_MODE_FIELD); 30889a0bf528SMauro Carvalho Chehab 30899a0bf528SMauro Carvalho Chehab switch (stat) { 30909a0bf528SMauro Carvalho Chehab case 0: /* searching */ 30919a0bf528SMauro Carvalho Chehab case 1: /* first PLH detected */ 30929a0bf528SMauro Carvalho Chehab default: 30939a0bf528SMauro Carvalho Chehab lock = 0; 30949a0bf528SMauro Carvalho Chehab break; 30959a0bf528SMauro Carvalho Chehab 30969a0bf528SMauro Carvalho Chehab case 2: /* DVB-S2 mode */ 30979a0bf528SMauro Carvalho Chehab reg = STV090x_READ_DEMOD(state, PDELSTATUS1); 30989a0bf528SMauro Carvalho Chehab lock = STV090x_GETFIELD_Px(reg, PKTDELIN_LOCK_FIELD); 30999a0bf528SMauro Carvalho Chehab break; 31009a0bf528SMauro Carvalho Chehab 31019a0bf528SMauro Carvalho Chehab case 3: /* DVB-S1/legacy mode */ 31029a0bf528SMauro Carvalho Chehab reg = STV090x_READ_DEMOD(state, VSTATUSVIT); 31039a0bf528SMauro Carvalho Chehab lock = STV090x_GETFIELD_Px(reg, LOCKEDVIT_FIELD); 31049a0bf528SMauro Carvalho Chehab break; 31059a0bf528SMauro Carvalho Chehab } 31069a0bf528SMauro Carvalho Chehab if (!lock) { 31079a0bf528SMauro Carvalho Chehab msleep(10); 31089a0bf528SMauro Carvalho Chehab timer += 10; 31099a0bf528SMauro Carvalho Chehab } 31109a0bf528SMauro Carvalho Chehab } 31119a0bf528SMauro Carvalho Chehab return lock; 31129a0bf528SMauro Carvalho Chehab } 31139a0bf528SMauro Carvalho Chehab 31149a0bf528SMauro Carvalho Chehab static int stv090x_get_lock(struct stv090x_state *state, s32 timeout_dmd, s32 timeout_fec) 31159a0bf528SMauro Carvalho Chehab { 31169a0bf528SMauro Carvalho Chehab u32 reg; 31179a0bf528SMauro Carvalho Chehab s32 timer = 0; 31189a0bf528SMauro Carvalho Chehab int lock; 31199a0bf528SMauro Carvalho Chehab 31209a0bf528SMauro Carvalho Chehab lock = stv090x_get_dmdlock(state, timeout_dmd); 31219a0bf528SMauro Carvalho Chehab if (lock) 31229a0bf528SMauro Carvalho Chehab lock = stv090x_get_feclock(state, timeout_fec); 31239a0bf528SMauro Carvalho Chehab 31249a0bf528SMauro Carvalho Chehab if (lock) { 31259a0bf528SMauro Carvalho Chehab lock = 0; 31269a0bf528SMauro Carvalho Chehab 31279a0bf528SMauro Carvalho Chehab while ((timer < timeout_fec) && (!lock)) { 31289a0bf528SMauro Carvalho Chehab reg = STV090x_READ_DEMOD(state, TSSTATUS); 31299a0bf528SMauro Carvalho Chehab lock = STV090x_GETFIELD_Px(reg, TSFIFO_LINEOK_FIELD); 31309a0bf528SMauro Carvalho Chehab msleep(1); 31319a0bf528SMauro Carvalho Chehab timer++; 31329a0bf528SMauro Carvalho Chehab } 31339a0bf528SMauro Carvalho Chehab } 31349a0bf528SMauro Carvalho Chehab 31359a0bf528SMauro Carvalho Chehab return lock; 31369a0bf528SMauro Carvalho Chehab } 31379a0bf528SMauro Carvalho Chehab 31389a0bf528SMauro Carvalho Chehab static int stv090x_set_s2rolloff(struct stv090x_state *state) 31399a0bf528SMauro Carvalho Chehab { 31409a0bf528SMauro Carvalho Chehab u32 reg; 31419a0bf528SMauro Carvalho Chehab 31429a0bf528SMauro Carvalho Chehab if (state->internal->dev_ver <= 0x20) { 31439a0bf528SMauro Carvalho Chehab /* rolloff to auto mode if DVBS2 */ 31449a0bf528SMauro Carvalho Chehab reg = STV090x_READ_DEMOD(state, DEMOD); 31459a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, MANUAL_SXROLLOFF_FIELD, 0x00); 31469a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, DEMOD, reg) < 0) 31479a0bf528SMauro Carvalho Chehab goto err; 31489a0bf528SMauro Carvalho Chehab } else { 31499a0bf528SMauro Carvalho Chehab /* DVB-S2 rolloff to auto mode if DVBS2 */ 31509a0bf528SMauro Carvalho Chehab reg = STV090x_READ_DEMOD(state, DEMOD); 31519a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, MANUAL_S2ROLLOFF_FIELD, 0x00); 31529a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, DEMOD, reg) < 0) 31539a0bf528SMauro Carvalho Chehab goto err; 31549a0bf528SMauro Carvalho Chehab } 31559a0bf528SMauro Carvalho Chehab return 0; 31569a0bf528SMauro Carvalho Chehab err: 31579a0bf528SMauro Carvalho Chehab dprintk(FE_ERROR, 1, "I/O error"); 31589a0bf528SMauro Carvalho Chehab return -1; 31599a0bf528SMauro Carvalho Chehab } 31609a0bf528SMauro Carvalho Chehab 31619a0bf528SMauro Carvalho Chehab 31629a0bf528SMauro Carvalho Chehab static enum stv090x_signal_state stv090x_algo(struct stv090x_state *state) 31639a0bf528SMauro Carvalho Chehab { 31649a0bf528SMauro Carvalho Chehab struct dvb_frontend *fe = &state->frontend; 31659a0bf528SMauro Carvalho Chehab enum stv090x_signal_state signal_state = STV090x_NOCARRIER; 31669a0bf528SMauro Carvalho Chehab u32 reg; 31679a0bf528SMauro Carvalho Chehab s32 agc1_power, power_iq = 0, i; 31689a0bf528SMauro Carvalho Chehab int lock = 0, low_sr = 0; 31699a0bf528SMauro Carvalho Chehab 31709a0bf528SMauro Carvalho Chehab reg = STV090x_READ_DEMOD(state, TSCFGH); 31719a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 1); /* Stop path 1 stream merger */ 31729a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, TSCFGH, reg) < 0) 31739a0bf528SMauro Carvalho Chehab goto err; 31749a0bf528SMauro Carvalho Chehab 31759a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x5c) < 0) /* Demod stop */ 31769a0bf528SMauro Carvalho Chehab goto err; 31779a0bf528SMauro Carvalho Chehab 31789a0bf528SMauro Carvalho Chehab if (state->internal->dev_ver >= 0x20) { 31799a0bf528SMauro Carvalho Chehab if (state->srate > 5000000) { 31809a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, CORRELABS, 0x9e) < 0) 31819a0bf528SMauro Carvalho Chehab goto err; 31829a0bf528SMauro Carvalho Chehab } else { 31839a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, CORRELABS, 0x82) < 0) 31849a0bf528SMauro Carvalho Chehab goto err; 31859a0bf528SMauro Carvalho Chehab } 31869a0bf528SMauro Carvalho Chehab } 31879a0bf528SMauro Carvalho Chehab 31889a0bf528SMauro Carvalho Chehab stv090x_get_lock_tmg(state); 31899a0bf528SMauro Carvalho Chehab 31909a0bf528SMauro Carvalho Chehab if (state->algo == STV090x_BLIND_SEARCH) { 31919a0bf528SMauro Carvalho Chehab state->tuner_bw = 2 * 36000000; /* wide bw for unknown srate */ 31929a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, TMGCFG2, 0xc0) < 0) /* wider srate scan */ 31939a0bf528SMauro Carvalho Chehab goto err; 31949a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, CORRELMANT, 0x70) < 0) 31959a0bf528SMauro Carvalho Chehab goto err; 31969a0bf528SMauro Carvalho Chehab if (stv090x_set_srate(state, 1000000) < 0) /* initial srate = 1Msps */ 31979a0bf528SMauro Carvalho Chehab goto err; 31989a0bf528SMauro Carvalho Chehab } else { 31999a0bf528SMauro Carvalho Chehab /* known srate */ 32009a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, DMDTOM, 0x20) < 0) 32019a0bf528SMauro Carvalho Chehab goto err; 32029a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, TMGCFG, 0xd2) < 0) 32039a0bf528SMauro Carvalho Chehab goto err; 32049a0bf528SMauro Carvalho Chehab 32059a0bf528SMauro Carvalho Chehab if (state->srate < 2000000) { 32069a0bf528SMauro Carvalho Chehab /* SR < 2MSPS */ 32079a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, CORRELMANT, 0x63) < 0) 32089a0bf528SMauro Carvalho Chehab goto err; 32099a0bf528SMauro Carvalho Chehab } else { 32109a0bf528SMauro Carvalho Chehab /* SR >= 2Msps */ 32119a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, CORRELMANT, 0x70) < 0) 32129a0bf528SMauro Carvalho Chehab goto err; 32139a0bf528SMauro Carvalho Chehab } 32149a0bf528SMauro Carvalho Chehab 32159a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, AGC2REF, 0x38) < 0) 32169a0bf528SMauro Carvalho Chehab goto err; 32179a0bf528SMauro Carvalho Chehab 32189a0bf528SMauro Carvalho Chehab if (state->internal->dev_ver >= 0x20) { 32199a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, KREFTMG, 0x5a) < 0) 32209a0bf528SMauro Carvalho Chehab goto err; 32219a0bf528SMauro Carvalho Chehab if (state->algo == STV090x_COLD_SEARCH) 32229a0bf528SMauro Carvalho Chehab state->tuner_bw = (15 * (stv090x_car_width(state->srate, state->rolloff) + 10000000)) / 10; 32239a0bf528SMauro Carvalho Chehab else if (state->algo == STV090x_WARM_SEARCH) 32249a0bf528SMauro Carvalho Chehab state->tuner_bw = stv090x_car_width(state->srate, state->rolloff) + 10000000; 32259a0bf528SMauro Carvalho Chehab } 32269a0bf528SMauro Carvalho Chehab 32279a0bf528SMauro Carvalho Chehab /* if cold start or warm (Symbolrate is known) 32289a0bf528SMauro Carvalho Chehab * use a Narrow symbol rate scan range 32299a0bf528SMauro Carvalho Chehab */ 32309a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, TMGCFG2, 0xc1) < 0) /* narrow srate scan */ 32319a0bf528SMauro Carvalho Chehab goto err; 32329a0bf528SMauro Carvalho Chehab 32339a0bf528SMauro Carvalho Chehab if (stv090x_set_srate(state, state->srate) < 0) 32349a0bf528SMauro Carvalho Chehab goto err; 32359a0bf528SMauro Carvalho Chehab 32369a0bf528SMauro Carvalho Chehab if (stv090x_set_max_srate(state, state->internal->mclk, 32379a0bf528SMauro Carvalho Chehab state->srate) < 0) 32389a0bf528SMauro Carvalho Chehab goto err; 32399a0bf528SMauro Carvalho Chehab if (stv090x_set_min_srate(state, state->internal->mclk, 32409a0bf528SMauro Carvalho Chehab state->srate) < 0) 32419a0bf528SMauro Carvalho Chehab goto err; 32429a0bf528SMauro Carvalho Chehab 32439a0bf528SMauro Carvalho Chehab if (state->srate >= 10000000) 32449a0bf528SMauro Carvalho Chehab low_sr = 0; 32459a0bf528SMauro Carvalho Chehab else 32469a0bf528SMauro Carvalho Chehab low_sr = 1; 32479a0bf528SMauro Carvalho Chehab } 32489a0bf528SMauro Carvalho Chehab 32499a0bf528SMauro Carvalho Chehab /* Setup tuner */ 32509a0bf528SMauro Carvalho Chehab if (stv090x_i2c_gate_ctrl(state, 1) < 0) 32519a0bf528SMauro Carvalho Chehab goto err; 32529a0bf528SMauro Carvalho Chehab 32539a0bf528SMauro Carvalho Chehab if (state->config->tuner_set_bbgain) { 32549a0bf528SMauro Carvalho Chehab reg = state->config->tuner_bbgain; 32559a0bf528SMauro Carvalho Chehab if (reg == 0) 32569a0bf528SMauro Carvalho Chehab reg = 10; /* default: 10dB */ 32579a0bf528SMauro Carvalho Chehab if (state->config->tuner_set_bbgain(fe, reg) < 0) 32589a0bf528SMauro Carvalho Chehab goto err_gateoff; 32599a0bf528SMauro Carvalho Chehab } 32609a0bf528SMauro Carvalho Chehab 32619a0bf528SMauro Carvalho Chehab if (state->config->tuner_set_frequency) { 32629a0bf528SMauro Carvalho Chehab if (state->config->tuner_set_frequency(fe, state->frequency) < 0) 32639a0bf528SMauro Carvalho Chehab goto err_gateoff; 32649a0bf528SMauro Carvalho Chehab } 32659a0bf528SMauro Carvalho Chehab 32669a0bf528SMauro Carvalho Chehab if (state->config->tuner_set_bandwidth) { 32679a0bf528SMauro Carvalho Chehab if (state->config->tuner_set_bandwidth(fe, state->tuner_bw) < 0) 32689a0bf528SMauro Carvalho Chehab goto err_gateoff; 32699a0bf528SMauro Carvalho Chehab } 32709a0bf528SMauro Carvalho Chehab 32719a0bf528SMauro Carvalho Chehab if (stv090x_i2c_gate_ctrl(state, 0) < 0) 32729a0bf528SMauro Carvalho Chehab goto err; 32739a0bf528SMauro Carvalho Chehab 32749a0bf528SMauro Carvalho Chehab msleep(50); 32759a0bf528SMauro Carvalho Chehab 32769a0bf528SMauro Carvalho Chehab if (state->config->tuner_get_status) { 32779a0bf528SMauro Carvalho Chehab if (stv090x_i2c_gate_ctrl(state, 1) < 0) 32789a0bf528SMauro Carvalho Chehab goto err; 32799a0bf528SMauro Carvalho Chehab if (state->config->tuner_get_status(fe, ®) < 0) 32809a0bf528SMauro Carvalho Chehab goto err_gateoff; 32819a0bf528SMauro Carvalho Chehab if (stv090x_i2c_gate_ctrl(state, 0) < 0) 32829a0bf528SMauro Carvalho Chehab goto err; 32839a0bf528SMauro Carvalho Chehab 32849a0bf528SMauro Carvalho Chehab if (reg) 32859a0bf528SMauro Carvalho Chehab dprintk(FE_DEBUG, 1, "Tuner phase locked"); 32869a0bf528SMauro Carvalho Chehab else { 32879a0bf528SMauro Carvalho Chehab dprintk(FE_DEBUG, 1, "Tuner unlocked"); 32889a0bf528SMauro Carvalho Chehab return STV090x_NOCARRIER; 32899a0bf528SMauro Carvalho Chehab } 32909a0bf528SMauro Carvalho Chehab } 32919a0bf528SMauro Carvalho Chehab 32929a0bf528SMauro Carvalho Chehab msleep(10); 32939a0bf528SMauro Carvalho Chehab agc1_power = MAKEWORD16(STV090x_READ_DEMOD(state, AGCIQIN1), 32949a0bf528SMauro Carvalho Chehab STV090x_READ_DEMOD(state, AGCIQIN0)); 32959a0bf528SMauro Carvalho Chehab 32969a0bf528SMauro Carvalho Chehab if (agc1_power == 0) { 32979a0bf528SMauro Carvalho Chehab /* If AGC1 integrator value is 0 32989a0bf528SMauro Carvalho Chehab * then read POWERI, POWERQ 32999a0bf528SMauro Carvalho Chehab */ 33009a0bf528SMauro Carvalho Chehab for (i = 0; i < 5; i++) { 33019a0bf528SMauro Carvalho Chehab power_iq += (STV090x_READ_DEMOD(state, POWERI) + 33029a0bf528SMauro Carvalho Chehab STV090x_READ_DEMOD(state, POWERQ)) >> 1; 33039a0bf528SMauro Carvalho Chehab } 33049a0bf528SMauro Carvalho Chehab power_iq /= 5; 33059a0bf528SMauro Carvalho Chehab } 33069a0bf528SMauro Carvalho Chehab 33079a0bf528SMauro Carvalho Chehab if ((agc1_power == 0) && (power_iq < STV090x_IQPOWER_THRESHOLD)) { 33089a0bf528SMauro Carvalho Chehab dprintk(FE_ERROR, 1, "No Signal: POWER_IQ=0x%02x", power_iq); 33099a0bf528SMauro Carvalho Chehab lock = 0; 33109a0bf528SMauro Carvalho Chehab signal_state = STV090x_NOAGC1; 33119a0bf528SMauro Carvalho Chehab } else { 33129a0bf528SMauro Carvalho Chehab reg = STV090x_READ_DEMOD(state, DEMOD); 33139a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, SPECINV_CONTROL_FIELD, state->inversion); 33149a0bf528SMauro Carvalho Chehab 33159a0bf528SMauro Carvalho Chehab if (state->internal->dev_ver <= 0x20) { 33169a0bf528SMauro Carvalho Chehab /* rolloff to auto mode if DVBS2 */ 33179a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, MANUAL_SXROLLOFF_FIELD, 1); 33189a0bf528SMauro Carvalho Chehab } else { 33199a0bf528SMauro Carvalho Chehab /* DVB-S2 rolloff to auto mode if DVBS2 */ 33209a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, MANUAL_S2ROLLOFF_FIELD, 1); 33219a0bf528SMauro Carvalho Chehab } 33229a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, DEMOD, reg) < 0) 33239a0bf528SMauro Carvalho Chehab goto err; 33249a0bf528SMauro Carvalho Chehab 33259a0bf528SMauro Carvalho Chehab if (stv090x_delivery_search(state) < 0) 33269a0bf528SMauro Carvalho Chehab goto err; 33279a0bf528SMauro Carvalho Chehab 33289a0bf528SMauro Carvalho Chehab if (state->algo != STV090x_BLIND_SEARCH) { 33299a0bf528SMauro Carvalho Chehab if (stv090x_start_search(state) < 0) 33309a0bf528SMauro Carvalho Chehab goto err; 33319a0bf528SMauro Carvalho Chehab } 33329a0bf528SMauro Carvalho Chehab } 33339a0bf528SMauro Carvalho Chehab 33349a0bf528SMauro Carvalho Chehab if (signal_state == STV090x_NOAGC1) 33359a0bf528SMauro Carvalho Chehab return signal_state; 33369a0bf528SMauro Carvalho Chehab 33379a0bf528SMauro Carvalho Chehab if (state->algo == STV090x_BLIND_SEARCH) 33389a0bf528SMauro Carvalho Chehab lock = stv090x_blind_search(state); 33399a0bf528SMauro Carvalho Chehab 33409a0bf528SMauro Carvalho Chehab else if (state->algo == STV090x_COLD_SEARCH) 33419a0bf528SMauro Carvalho Chehab lock = stv090x_get_coldlock(state, state->DemodTimeout); 33429a0bf528SMauro Carvalho Chehab 33439a0bf528SMauro Carvalho Chehab else if (state->algo == STV090x_WARM_SEARCH) 33449a0bf528SMauro Carvalho Chehab lock = stv090x_get_dmdlock(state, state->DemodTimeout); 33459a0bf528SMauro Carvalho Chehab 33469a0bf528SMauro Carvalho Chehab if ((!lock) && (state->algo == STV090x_COLD_SEARCH)) { 33479a0bf528SMauro Carvalho Chehab if (!low_sr) { 33489a0bf528SMauro Carvalho Chehab if (stv090x_chk_tmg(state)) 33499a0bf528SMauro Carvalho Chehab lock = stv090x_sw_algo(state); 33509a0bf528SMauro Carvalho Chehab } 33519a0bf528SMauro Carvalho Chehab } 33529a0bf528SMauro Carvalho Chehab 33539a0bf528SMauro Carvalho Chehab if (lock) 33549a0bf528SMauro Carvalho Chehab signal_state = stv090x_get_sig_params(state); 33559a0bf528SMauro Carvalho Chehab 33569a0bf528SMauro Carvalho Chehab if ((lock) && (signal_state == STV090x_RANGEOK)) { /* signal within Range */ 33579a0bf528SMauro Carvalho Chehab stv090x_optimize_track(state); 33589a0bf528SMauro Carvalho Chehab 33599a0bf528SMauro Carvalho Chehab if (state->internal->dev_ver >= 0x20) { 33609a0bf528SMauro Carvalho Chehab /* >= Cut 2.0 :release TS reset after 33619a0bf528SMauro Carvalho Chehab * demod lock and optimized Tracking 33629a0bf528SMauro Carvalho Chehab */ 33639a0bf528SMauro Carvalho Chehab reg = STV090x_READ_DEMOD(state, TSCFGH); 33649a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 0); /* release merger reset */ 33659a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, TSCFGH, reg) < 0) 33669a0bf528SMauro Carvalho Chehab goto err; 33679a0bf528SMauro Carvalho Chehab 33689a0bf528SMauro Carvalho Chehab msleep(3); 33699a0bf528SMauro Carvalho Chehab 33709a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 1); /* merger reset */ 33719a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, TSCFGH, reg) < 0) 33729a0bf528SMauro Carvalho Chehab goto err; 33739a0bf528SMauro Carvalho Chehab 33749a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 0); /* release merger reset */ 33759a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, TSCFGH, reg) < 0) 33769a0bf528SMauro Carvalho Chehab goto err; 33779a0bf528SMauro Carvalho Chehab } 33789a0bf528SMauro Carvalho Chehab 33799a0bf528SMauro Carvalho Chehab lock = stv090x_get_lock(state, state->FecTimeout, 33809a0bf528SMauro Carvalho Chehab state->FecTimeout); 33819a0bf528SMauro Carvalho Chehab if (lock) { 33829a0bf528SMauro Carvalho Chehab if (state->delsys == STV090x_DVBS2) { 33839a0bf528SMauro Carvalho Chehab stv090x_set_s2rolloff(state); 33849a0bf528SMauro Carvalho Chehab 33859a0bf528SMauro Carvalho Chehab reg = STV090x_READ_DEMOD(state, PDELCTRL2); 33869a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, RESET_UPKO_COUNT, 1); 33879a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, PDELCTRL2, reg) < 0) 33889a0bf528SMauro Carvalho Chehab goto err; 33899a0bf528SMauro Carvalho Chehab /* Reset DVBS2 packet delinator error counter */ 33909a0bf528SMauro Carvalho Chehab reg = STV090x_READ_DEMOD(state, PDELCTRL2); 33919a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, RESET_UPKO_COUNT, 0); 33929a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, PDELCTRL2, reg) < 0) 33939a0bf528SMauro Carvalho Chehab goto err; 33949a0bf528SMauro Carvalho Chehab 33959a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, ERRCTRL1, 0x67) < 0) /* PER */ 33969a0bf528SMauro Carvalho Chehab goto err; 33979a0bf528SMauro Carvalho Chehab } else { 33989a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, ERRCTRL1, 0x75) < 0) 33999a0bf528SMauro Carvalho Chehab goto err; 34009a0bf528SMauro Carvalho Chehab } 34019a0bf528SMauro Carvalho Chehab /* Reset the Total packet counter */ 34029a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, FBERCPT4, 0x00) < 0) 34039a0bf528SMauro Carvalho Chehab goto err; 34049a0bf528SMauro Carvalho Chehab /* Reset the packet Error counter2 */ 34059a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, ERRCTRL2, 0xc1) < 0) 34069a0bf528SMauro Carvalho Chehab goto err; 34079a0bf528SMauro Carvalho Chehab } else { 34089a0bf528SMauro Carvalho Chehab signal_state = STV090x_NODATA; 34099a0bf528SMauro Carvalho Chehab stv090x_chk_signal(state); 34109a0bf528SMauro Carvalho Chehab } 34119a0bf528SMauro Carvalho Chehab } 34129a0bf528SMauro Carvalho Chehab return signal_state; 34139a0bf528SMauro Carvalho Chehab 34149a0bf528SMauro Carvalho Chehab err_gateoff: 34159a0bf528SMauro Carvalho Chehab stv090x_i2c_gate_ctrl(state, 0); 34169a0bf528SMauro Carvalho Chehab err: 34179a0bf528SMauro Carvalho Chehab dprintk(FE_ERROR, 1, "I/O error"); 34189a0bf528SMauro Carvalho Chehab return -1; 34199a0bf528SMauro Carvalho Chehab } 34209a0bf528SMauro Carvalho Chehab 342193314453SAthanasios Oikonomou static int stv090x_set_pls(struct stv090x_state *state, u32 pls_code) 342293314453SAthanasios Oikonomou { 342393314453SAthanasios Oikonomou dprintk(FE_DEBUG, 1, "Set Gold PLS code %d", pls_code); 342493314453SAthanasios Oikonomou if (STV090x_WRITE_DEMOD(state, PLROOT0, pls_code & 0xff) < 0) 342593314453SAthanasios Oikonomou goto err; 342693314453SAthanasios Oikonomou if (STV090x_WRITE_DEMOD(state, PLROOT1, (pls_code >> 8) & 0xff) < 0) 342793314453SAthanasios Oikonomou goto err; 342893314453SAthanasios Oikonomou if (STV090x_WRITE_DEMOD(state, PLROOT2, 0x04 | (pls_code >> 16)) < 0) 342993314453SAthanasios Oikonomou goto err; 343093314453SAthanasios Oikonomou return 0; 343193314453SAthanasios Oikonomou err: 343293314453SAthanasios Oikonomou dprintk(FE_ERROR, 1, "I/O error"); 343393314453SAthanasios Oikonomou return -1; 343493314453SAthanasios Oikonomou } 343593314453SAthanasios Oikonomou 3436f9040ef3SEvgeny Plehov static int stv090x_set_mis(struct stv090x_state *state, int mis) 3437f9040ef3SEvgeny Plehov { 3438f9040ef3SEvgeny Plehov u32 reg; 3439f9040ef3SEvgeny Plehov 3440f9040ef3SEvgeny Plehov if (mis < 0 || mis > 255) { 3441f9040ef3SEvgeny Plehov dprintk(FE_DEBUG, 1, "Disable MIS filtering"); 3442f9040ef3SEvgeny Plehov reg = STV090x_READ_DEMOD(state, PDELCTRL1); 3443f9040ef3SEvgeny Plehov STV090x_SETFIELD_Px(reg, FILTER_EN_FIELD, 0x00); 3444f9040ef3SEvgeny Plehov if (STV090x_WRITE_DEMOD(state, PDELCTRL1, reg) < 0) 3445f9040ef3SEvgeny Plehov goto err; 3446f9040ef3SEvgeny Plehov } else { 3447f9040ef3SEvgeny Plehov dprintk(FE_DEBUG, 1, "Enable MIS filtering - %d", mis); 3448f9040ef3SEvgeny Plehov reg = STV090x_READ_DEMOD(state, PDELCTRL1); 3449f9040ef3SEvgeny Plehov STV090x_SETFIELD_Px(reg, FILTER_EN_FIELD, 0x01); 3450f9040ef3SEvgeny Plehov if (STV090x_WRITE_DEMOD(state, PDELCTRL1, reg) < 0) 3451f9040ef3SEvgeny Plehov goto err; 3452f9040ef3SEvgeny Plehov if (STV090x_WRITE_DEMOD(state, ISIENTRY, mis) < 0) 3453f9040ef3SEvgeny Plehov goto err; 3454f9040ef3SEvgeny Plehov if (STV090x_WRITE_DEMOD(state, ISIBITENA, 0xff) < 0) 3455f9040ef3SEvgeny Plehov goto err; 3456f9040ef3SEvgeny Plehov } 3457f9040ef3SEvgeny Plehov return 0; 3458f9040ef3SEvgeny Plehov err: 3459f9040ef3SEvgeny Plehov dprintk(FE_ERROR, 1, "I/O error"); 3460f9040ef3SEvgeny Plehov return -1; 3461f9040ef3SEvgeny Plehov } 3462f9040ef3SEvgeny Plehov 34639a0bf528SMauro Carvalho Chehab static enum dvbfe_search stv090x_search(struct dvb_frontend *fe) 34649a0bf528SMauro Carvalho Chehab { 34659a0bf528SMauro Carvalho Chehab struct stv090x_state *state = fe->demodulator_priv; 34669a0bf528SMauro Carvalho Chehab struct dtv_frontend_properties *props = &fe->dtv_property_cache; 34679a0bf528SMauro Carvalho Chehab 34689a0bf528SMauro Carvalho Chehab if (props->frequency == 0) 34699a0bf528SMauro Carvalho Chehab return DVBFE_ALGO_SEARCH_INVALID; 34709a0bf528SMauro Carvalho Chehab 34711011d24aSMauro Carvalho Chehab switch (props->delivery_system) { 34721011d24aSMauro Carvalho Chehab case SYS_DSS: 34731011d24aSMauro Carvalho Chehab state->delsys = STV090x_DSS; 34741011d24aSMauro Carvalho Chehab break; 34751011d24aSMauro Carvalho Chehab case SYS_DVBS: 34761011d24aSMauro Carvalho Chehab state->delsys = STV090x_DVBS1; 34771011d24aSMauro Carvalho Chehab break; 34781011d24aSMauro Carvalho Chehab case SYS_DVBS2: 34791011d24aSMauro Carvalho Chehab state->delsys = STV090x_DVBS2; 34801011d24aSMauro Carvalho Chehab break; 34811011d24aSMauro Carvalho Chehab default: 34821011d24aSMauro Carvalho Chehab return DVBFE_ALGO_SEARCH_INVALID; 34831011d24aSMauro Carvalho Chehab } 34841011d24aSMauro Carvalho Chehab 34859a0bf528SMauro Carvalho Chehab state->frequency = props->frequency; 34869a0bf528SMauro Carvalho Chehab state->srate = props->symbol_rate; 34879a0bf528SMauro Carvalho Chehab state->search_mode = STV090x_SEARCH_AUTO; 34889a0bf528SMauro Carvalho Chehab state->algo = STV090x_COLD_SEARCH; 34899a0bf528SMauro Carvalho Chehab state->fec = STV090x_PRERR; 34909a0bf528SMauro Carvalho Chehab if (state->srate > 10000000) { 34919a0bf528SMauro Carvalho Chehab dprintk(FE_DEBUG, 1, "Search range: 10 MHz"); 34929a0bf528SMauro Carvalho Chehab state->search_range = 10000000; 34939a0bf528SMauro Carvalho Chehab } else { 34949a0bf528SMauro Carvalho Chehab dprintk(FE_DEBUG, 1, "Search range: 5 MHz"); 34959a0bf528SMauro Carvalho Chehab state->search_range = 5000000; 34969a0bf528SMauro Carvalho Chehab } 34979a0bf528SMauro Carvalho Chehab 349893314453SAthanasios Oikonomou stv090x_set_pls(state, props->scrambling_sequence_index); 3499f9040ef3SEvgeny Plehov stv090x_set_mis(state, props->stream_id); 3500f9040ef3SEvgeny Plehov 35019a0bf528SMauro Carvalho Chehab if (stv090x_algo(state) == STV090x_RANGEOK) { 35029a0bf528SMauro Carvalho Chehab dprintk(FE_DEBUG, 1, "Search success!"); 35039a0bf528SMauro Carvalho Chehab return DVBFE_ALGO_SEARCH_SUCCESS; 35049a0bf528SMauro Carvalho Chehab } else { 35059a0bf528SMauro Carvalho Chehab dprintk(FE_DEBUG, 1, "Search failed!"); 35069a0bf528SMauro Carvalho Chehab return DVBFE_ALGO_SEARCH_FAILED; 35079a0bf528SMauro Carvalho Chehab } 35089a0bf528SMauro Carvalho Chehab 35099a0bf528SMauro Carvalho Chehab return DVBFE_ALGO_SEARCH_ERROR; 35109a0bf528SMauro Carvalho Chehab } 35119a0bf528SMauro Carvalho Chehab 35129a0bf528SMauro Carvalho Chehab static int stv090x_read_status(struct dvb_frontend *fe, enum fe_status *status) 35139a0bf528SMauro Carvalho Chehab { 35149a0bf528SMauro Carvalho Chehab struct stv090x_state *state = fe->demodulator_priv; 35159a0bf528SMauro Carvalho Chehab u32 reg, dstatus; 35169a0bf528SMauro Carvalho Chehab u8 search_state; 35179a0bf528SMauro Carvalho Chehab 35189a0bf528SMauro Carvalho Chehab *status = 0; 35199a0bf528SMauro Carvalho Chehab 35209a0bf528SMauro Carvalho Chehab dstatus = STV090x_READ_DEMOD(state, DSTATUS); 35219a0bf528SMauro Carvalho Chehab if (STV090x_GETFIELD_Px(dstatus, CAR_LOCK_FIELD)) 35229a0bf528SMauro Carvalho Chehab *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER; 35239a0bf528SMauro Carvalho Chehab 35249a0bf528SMauro Carvalho Chehab reg = STV090x_READ_DEMOD(state, DMDSTATE); 35259a0bf528SMauro Carvalho Chehab search_state = STV090x_GETFIELD_Px(reg, HEADER_MODE_FIELD); 35269a0bf528SMauro Carvalho Chehab 35279a0bf528SMauro Carvalho Chehab switch (search_state) { 35289a0bf528SMauro Carvalho Chehab case 0: /* searching */ 35299a0bf528SMauro Carvalho Chehab case 1: /* first PLH detected */ 35309a0bf528SMauro Carvalho Chehab default: 35319a0bf528SMauro Carvalho Chehab dprintk(FE_DEBUG, 1, "Status: Unlocked (Searching ..)"); 35329a0bf528SMauro Carvalho Chehab break; 35339a0bf528SMauro Carvalho Chehab 35349a0bf528SMauro Carvalho Chehab case 2: /* DVB-S2 mode */ 35359a0bf528SMauro Carvalho Chehab dprintk(FE_DEBUG, 1, "Delivery system: DVB-S2"); 35369a0bf528SMauro Carvalho Chehab if (STV090x_GETFIELD_Px(dstatus, LOCK_DEFINITIF_FIELD)) { 35379a0bf528SMauro Carvalho Chehab reg = STV090x_READ_DEMOD(state, PDELSTATUS1); 35389a0bf528SMauro Carvalho Chehab if (STV090x_GETFIELD_Px(reg, PKTDELIN_LOCK_FIELD)) { 35399a0bf528SMauro Carvalho Chehab *status |= FE_HAS_VITERBI; 35409a0bf528SMauro Carvalho Chehab reg = STV090x_READ_DEMOD(state, TSSTATUS); 35419a0bf528SMauro Carvalho Chehab if (STV090x_GETFIELD_Px(reg, TSFIFO_LINEOK_FIELD)) 35429a0bf528SMauro Carvalho Chehab *status |= FE_HAS_SYNC | FE_HAS_LOCK; 35439a0bf528SMauro Carvalho Chehab } 35449a0bf528SMauro Carvalho Chehab } 35459a0bf528SMauro Carvalho Chehab break; 35469a0bf528SMauro Carvalho Chehab 35479a0bf528SMauro Carvalho Chehab case 3: /* DVB-S1/legacy mode */ 35489a0bf528SMauro Carvalho Chehab dprintk(FE_DEBUG, 1, "Delivery system: DVB-S"); 35499a0bf528SMauro Carvalho Chehab if (STV090x_GETFIELD_Px(dstatus, LOCK_DEFINITIF_FIELD)) { 35509a0bf528SMauro Carvalho Chehab reg = STV090x_READ_DEMOD(state, VSTATUSVIT); 35519a0bf528SMauro Carvalho Chehab if (STV090x_GETFIELD_Px(reg, LOCKEDVIT_FIELD)) { 35529a0bf528SMauro Carvalho Chehab *status |= FE_HAS_VITERBI; 35539a0bf528SMauro Carvalho Chehab reg = STV090x_READ_DEMOD(state, TSSTATUS); 35549a0bf528SMauro Carvalho Chehab if (STV090x_GETFIELD_Px(reg, TSFIFO_LINEOK_FIELD)) 35559a0bf528SMauro Carvalho Chehab *status |= FE_HAS_SYNC | FE_HAS_LOCK; 35569a0bf528SMauro Carvalho Chehab } 35579a0bf528SMauro Carvalho Chehab } 35589a0bf528SMauro Carvalho Chehab break; 35599a0bf528SMauro Carvalho Chehab } 35609a0bf528SMauro Carvalho Chehab 35619a0bf528SMauro Carvalho Chehab return 0; 35629a0bf528SMauro Carvalho Chehab } 35639a0bf528SMauro Carvalho Chehab 35649a0bf528SMauro Carvalho Chehab static int stv090x_read_per(struct dvb_frontend *fe, u32 *per) 35659a0bf528SMauro Carvalho Chehab { 35669a0bf528SMauro Carvalho Chehab struct stv090x_state *state = fe->demodulator_priv; 35679a0bf528SMauro Carvalho Chehab 35689a0bf528SMauro Carvalho Chehab s32 count_4, count_3, count_2, count_1, count_0, count; 35699a0bf528SMauro Carvalho Chehab u32 reg, h, m, l; 35709a0bf528SMauro Carvalho Chehab enum fe_status status; 35719a0bf528SMauro Carvalho Chehab 35729a0bf528SMauro Carvalho Chehab stv090x_read_status(fe, &status); 35739a0bf528SMauro Carvalho Chehab if (!(status & FE_HAS_LOCK)) { 35749a0bf528SMauro Carvalho Chehab *per = 1 << 23; /* Max PER */ 35759a0bf528SMauro Carvalho Chehab } else { 35769a0bf528SMauro Carvalho Chehab /* Counter 2 */ 35779a0bf528SMauro Carvalho Chehab reg = STV090x_READ_DEMOD(state, ERRCNT22); 35789a0bf528SMauro Carvalho Chehab h = STV090x_GETFIELD_Px(reg, ERR_CNT2_FIELD); 35799a0bf528SMauro Carvalho Chehab 35809a0bf528SMauro Carvalho Chehab reg = STV090x_READ_DEMOD(state, ERRCNT21); 35819a0bf528SMauro Carvalho Chehab m = STV090x_GETFIELD_Px(reg, ERR_CNT21_FIELD); 35829a0bf528SMauro Carvalho Chehab 35839a0bf528SMauro Carvalho Chehab reg = STV090x_READ_DEMOD(state, ERRCNT20); 35849a0bf528SMauro Carvalho Chehab l = STV090x_GETFIELD_Px(reg, ERR_CNT20_FIELD); 35859a0bf528SMauro Carvalho Chehab 35869a0bf528SMauro Carvalho Chehab *per = ((h << 16) | (m << 8) | l); 35879a0bf528SMauro Carvalho Chehab 35889a0bf528SMauro Carvalho Chehab count_4 = STV090x_READ_DEMOD(state, FBERCPT4); 35899a0bf528SMauro Carvalho Chehab count_3 = STV090x_READ_DEMOD(state, FBERCPT3); 35909a0bf528SMauro Carvalho Chehab count_2 = STV090x_READ_DEMOD(state, FBERCPT2); 35919a0bf528SMauro Carvalho Chehab count_1 = STV090x_READ_DEMOD(state, FBERCPT1); 35929a0bf528SMauro Carvalho Chehab count_0 = STV090x_READ_DEMOD(state, FBERCPT0); 35939a0bf528SMauro Carvalho Chehab 35949a0bf528SMauro Carvalho Chehab if ((!count_4) && (!count_3)) { 35959a0bf528SMauro Carvalho Chehab count = (count_2 & 0xff) << 16; 35969a0bf528SMauro Carvalho Chehab count |= (count_1 & 0xff) << 8; 35979a0bf528SMauro Carvalho Chehab count |= count_0 & 0xff; 35989a0bf528SMauro Carvalho Chehab } else { 35999a0bf528SMauro Carvalho Chehab count = 1 << 24; 36009a0bf528SMauro Carvalho Chehab } 36019a0bf528SMauro Carvalho Chehab if (count == 0) 36029a0bf528SMauro Carvalho Chehab *per = 1; 36039a0bf528SMauro Carvalho Chehab } 36049a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, FBERCPT4, 0) < 0) 36059a0bf528SMauro Carvalho Chehab goto err; 36069a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, ERRCTRL2, 0xc1) < 0) 36079a0bf528SMauro Carvalho Chehab goto err; 36089a0bf528SMauro Carvalho Chehab 36099a0bf528SMauro Carvalho Chehab return 0; 36109a0bf528SMauro Carvalho Chehab err: 36119a0bf528SMauro Carvalho Chehab dprintk(FE_ERROR, 1, "I/O error"); 36129a0bf528SMauro Carvalho Chehab return -1; 36139a0bf528SMauro Carvalho Chehab } 36149a0bf528SMauro Carvalho Chehab 36159a0bf528SMauro Carvalho Chehab static int stv090x_table_lookup(const struct stv090x_tab *tab, int max, int val) 36169a0bf528SMauro Carvalho Chehab { 36179a0bf528SMauro Carvalho Chehab int res = 0; 36189a0bf528SMauro Carvalho Chehab int min = 0, med; 36199a0bf528SMauro Carvalho Chehab 36209a0bf528SMauro Carvalho Chehab if ((val >= tab[min].read && val < tab[max].read) || 36219a0bf528SMauro Carvalho Chehab (val >= tab[max].read && val < tab[min].read)) { 36229a0bf528SMauro Carvalho Chehab while ((max - min) > 1) { 36239a0bf528SMauro Carvalho Chehab med = (max + min) / 2; 36249a0bf528SMauro Carvalho Chehab if ((val >= tab[min].read && val < tab[med].read) || 36259a0bf528SMauro Carvalho Chehab (val >= tab[med].read && val < tab[min].read)) 36269a0bf528SMauro Carvalho Chehab max = med; 36279a0bf528SMauro Carvalho Chehab else 36289a0bf528SMauro Carvalho Chehab min = med; 36299a0bf528SMauro Carvalho Chehab } 36309a0bf528SMauro Carvalho Chehab res = ((val - tab[min].read) * 36319a0bf528SMauro Carvalho Chehab (tab[max].real - tab[min].real) / 36329a0bf528SMauro Carvalho Chehab (tab[max].read - tab[min].read)) + 36339a0bf528SMauro Carvalho Chehab tab[min].real; 36349a0bf528SMauro Carvalho Chehab } else { 36359a0bf528SMauro Carvalho Chehab if (tab[min].read < tab[max].read) { 36369a0bf528SMauro Carvalho Chehab if (val < tab[min].read) 36379a0bf528SMauro Carvalho Chehab res = tab[min].real; 36389a0bf528SMauro Carvalho Chehab else if (val >= tab[max].read) 36399a0bf528SMauro Carvalho Chehab res = tab[max].real; 36409a0bf528SMauro Carvalho Chehab } else { 36419a0bf528SMauro Carvalho Chehab if (val >= tab[min].read) 36429a0bf528SMauro Carvalho Chehab res = tab[min].real; 36439a0bf528SMauro Carvalho Chehab else if (val < tab[max].read) 36449a0bf528SMauro Carvalho Chehab res = tab[max].real; 36459a0bf528SMauro Carvalho Chehab } 36469a0bf528SMauro Carvalho Chehab } 36479a0bf528SMauro Carvalho Chehab 36489a0bf528SMauro Carvalho Chehab return res; 36499a0bf528SMauro Carvalho Chehab } 36509a0bf528SMauro Carvalho Chehab 36519a0bf528SMauro Carvalho Chehab static int stv090x_read_signal_strength(struct dvb_frontend *fe, u16 *strength) 36529a0bf528SMauro Carvalho Chehab { 36539a0bf528SMauro Carvalho Chehab struct stv090x_state *state = fe->demodulator_priv; 36549a0bf528SMauro Carvalho Chehab u32 reg; 36559a0bf528SMauro Carvalho Chehab s32 agc_0, agc_1, agc; 36569a0bf528SMauro Carvalho Chehab s32 str; 36579a0bf528SMauro Carvalho Chehab 36589a0bf528SMauro Carvalho Chehab reg = STV090x_READ_DEMOD(state, AGCIQIN1); 36599a0bf528SMauro Carvalho Chehab agc_1 = STV090x_GETFIELD_Px(reg, AGCIQ_VALUE_FIELD); 36609a0bf528SMauro Carvalho Chehab reg = STV090x_READ_DEMOD(state, AGCIQIN0); 36619a0bf528SMauro Carvalho Chehab agc_0 = STV090x_GETFIELD_Px(reg, AGCIQ_VALUE_FIELD); 36629a0bf528SMauro Carvalho Chehab agc = MAKEWORD16(agc_1, agc_0); 36639a0bf528SMauro Carvalho Chehab 36649a0bf528SMauro Carvalho Chehab str = stv090x_table_lookup(stv090x_rf_tab, 36659a0bf528SMauro Carvalho Chehab ARRAY_SIZE(stv090x_rf_tab) - 1, agc); 36669a0bf528SMauro Carvalho Chehab if (agc > stv090x_rf_tab[0].read) 36679a0bf528SMauro Carvalho Chehab str = 0; 36689a0bf528SMauro Carvalho Chehab else if (agc < stv090x_rf_tab[ARRAY_SIZE(stv090x_rf_tab) - 1].read) 36699a0bf528SMauro Carvalho Chehab str = -100; 36709a0bf528SMauro Carvalho Chehab *strength = (str + 100) * 0xFFFF / 100; 36719a0bf528SMauro Carvalho Chehab 36729a0bf528SMauro Carvalho Chehab return 0; 36739a0bf528SMauro Carvalho Chehab } 36749a0bf528SMauro Carvalho Chehab 36759a0bf528SMauro Carvalho Chehab static int stv090x_read_cnr(struct dvb_frontend *fe, u16 *cnr) 36769a0bf528SMauro Carvalho Chehab { 36779a0bf528SMauro Carvalho Chehab struct stv090x_state *state = fe->demodulator_priv; 36789a0bf528SMauro Carvalho Chehab u32 reg_0, reg_1, reg, i; 36799a0bf528SMauro Carvalho Chehab s32 val_0, val_1, val = 0; 36809a0bf528SMauro Carvalho Chehab u8 lock_f; 36819a0bf528SMauro Carvalho Chehab s32 div; 36829a0bf528SMauro Carvalho Chehab u32 last; 36839a0bf528SMauro Carvalho Chehab 36849a0bf528SMauro Carvalho Chehab switch (state->delsys) { 36859a0bf528SMauro Carvalho Chehab case STV090x_DVBS2: 36869a0bf528SMauro Carvalho Chehab reg = STV090x_READ_DEMOD(state, DSTATUS); 36879a0bf528SMauro Carvalho Chehab lock_f = STV090x_GETFIELD_Px(reg, LOCK_DEFINITIF_FIELD); 36889a0bf528SMauro Carvalho Chehab if (lock_f) { 36899a0bf528SMauro Carvalho Chehab msleep(5); 36909a0bf528SMauro Carvalho Chehab for (i = 0; i < 16; i++) { 36919a0bf528SMauro Carvalho Chehab reg_1 = STV090x_READ_DEMOD(state, NNOSPLHT1); 36929a0bf528SMauro Carvalho Chehab val_1 = STV090x_GETFIELD_Px(reg_1, NOSPLHT_NORMED_FIELD); 36939a0bf528SMauro Carvalho Chehab reg_0 = STV090x_READ_DEMOD(state, NNOSPLHT0); 36949a0bf528SMauro Carvalho Chehab val_0 = STV090x_GETFIELD_Px(reg_0, NOSPLHT_NORMED_FIELD); 36959a0bf528SMauro Carvalho Chehab val += MAKEWORD16(val_1, val_0); 36969a0bf528SMauro Carvalho Chehab msleep(1); 36979a0bf528SMauro Carvalho Chehab } 36989a0bf528SMauro Carvalho Chehab val /= 16; 36999a0bf528SMauro Carvalho Chehab last = ARRAY_SIZE(stv090x_s2cn_tab) - 1; 370038670189SJoerg Riechardt div = stv090x_s2cn_tab[last].real - 370138670189SJoerg Riechardt stv090x_s2cn_tab[3].real; 370238670189SJoerg Riechardt val = stv090x_table_lookup(stv090x_s2cn_tab, last, val); 370338670189SJoerg Riechardt if (val < 0) 370438670189SJoerg Riechardt val = 0; 370538670189SJoerg Riechardt *cnr = val * 0xFFFF / div; 37069a0bf528SMauro Carvalho Chehab } 37079a0bf528SMauro Carvalho Chehab break; 37089a0bf528SMauro Carvalho Chehab 37099a0bf528SMauro Carvalho Chehab case STV090x_DVBS1: 37109a0bf528SMauro Carvalho Chehab case STV090x_DSS: 37119a0bf528SMauro Carvalho Chehab reg = STV090x_READ_DEMOD(state, DSTATUS); 37129a0bf528SMauro Carvalho Chehab lock_f = STV090x_GETFIELD_Px(reg, LOCK_DEFINITIF_FIELD); 37139a0bf528SMauro Carvalho Chehab if (lock_f) { 37149a0bf528SMauro Carvalho Chehab msleep(5); 37159a0bf528SMauro Carvalho Chehab for (i = 0; i < 16; i++) { 37169a0bf528SMauro Carvalho Chehab reg_1 = STV090x_READ_DEMOD(state, NOSDATAT1); 37179a0bf528SMauro Carvalho Chehab val_1 = STV090x_GETFIELD_Px(reg_1, NOSDATAT_UNNORMED_FIELD); 37189a0bf528SMauro Carvalho Chehab reg_0 = STV090x_READ_DEMOD(state, NOSDATAT0); 37199a0bf528SMauro Carvalho Chehab val_0 = STV090x_GETFIELD_Px(reg_0, NOSDATAT_UNNORMED_FIELD); 37209a0bf528SMauro Carvalho Chehab val += MAKEWORD16(val_1, val_0); 37219a0bf528SMauro Carvalho Chehab msleep(1); 37229a0bf528SMauro Carvalho Chehab } 37239a0bf528SMauro Carvalho Chehab val /= 16; 37249a0bf528SMauro Carvalho Chehab last = ARRAY_SIZE(stv090x_s1cn_tab) - 1; 372538670189SJoerg Riechardt div = stv090x_s1cn_tab[last].real - 372638670189SJoerg Riechardt stv090x_s1cn_tab[0].real; 372738670189SJoerg Riechardt val = stv090x_table_lookup(stv090x_s1cn_tab, last, val); 372838670189SJoerg Riechardt *cnr = val * 0xFFFF / div; 37299a0bf528SMauro Carvalho Chehab } 37309a0bf528SMauro Carvalho Chehab break; 37319a0bf528SMauro Carvalho Chehab default: 37329a0bf528SMauro Carvalho Chehab break; 37339a0bf528SMauro Carvalho Chehab } 37349a0bf528SMauro Carvalho Chehab 37359a0bf528SMauro Carvalho Chehab return 0; 37369a0bf528SMauro Carvalho Chehab } 37379a0bf528SMauro Carvalho Chehab 37380df289a2SMauro Carvalho Chehab static int stv090x_set_tone(struct dvb_frontend *fe, enum fe_sec_tone_mode tone) 37399a0bf528SMauro Carvalho Chehab { 37409a0bf528SMauro Carvalho Chehab struct stv090x_state *state = fe->demodulator_priv; 37419a0bf528SMauro Carvalho Chehab u32 reg; 37429a0bf528SMauro Carvalho Chehab 37439a0bf528SMauro Carvalho Chehab reg = STV090x_READ_DEMOD(state, DISTXCTL); 37449a0bf528SMauro Carvalho Chehab switch (tone) { 37459a0bf528SMauro Carvalho Chehab case SEC_TONE_ON: 37469a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, DISTX_MODE_FIELD, 0); 37479a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, DISEQC_RESET_FIELD, 1); 37489a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0) 37499a0bf528SMauro Carvalho Chehab goto err; 37509a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, DISEQC_RESET_FIELD, 0); 37519a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0) 37529a0bf528SMauro Carvalho Chehab goto err; 37539a0bf528SMauro Carvalho Chehab break; 37549a0bf528SMauro Carvalho Chehab 37559a0bf528SMauro Carvalho Chehab case SEC_TONE_OFF: 37569a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, DISTX_MODE_FIELD, 0); 37579a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, DISEQC_RESET_FIELD, 1); 37589a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0) 37599a0bf528SMauro Carvalho Chehab goto err; 37609a0bf528SMauro Carvalho Chehab break; 37619a0bf528SMauro Carvalho Chehab default: 37629a0bf528SMauro Carvalho Chehab return -EINVAL; 37639a0bf528SMauro Carvalho Chehab } 37649a0bf528SMauro Carvalho Chehab 37659a0bf528SMauro Carvalho Chehab return 0; 37669a0bf528SMauro Carvalho Chehab err: 37679a0bf528SMauro Carvalho Chehab dprintk(FE_ERROR, 1, "I/O error"); 37689a0bf528SMauro Carvalho Chehab return -1; 37699a0bf528SMauro Carvalho Chehab } 37709a0bf528SMauro Carvalho Chehab 37719a0bf528SMauro Carvalho Chehab 37729a0bf528SMauro Carvalho Chehab static enum dvbfe_algo stv090x_frontend_algo(struct dvb_frontend *fe) 37739a0bf528SMauro Carvalho Chehab { 37749a0bf528SMauro Carvalho Chehab return DVBFE_ALGO_CUSTOM; 37759a0bf528SMauro Carvalho Chehab } 37769a0bf528SMauro Carvalho Chehab 37779a0bf528SMauro Carvalho Chehab static int stv090x_send_diseqc_msg(struct dvb_frontend *fe, struct dvb_diseqc_master_cmd *cmd) 37789a0bf528SMauro Carvalho Chehab { 37799a0bf528SMauro Carvalho Chehab struct stv090x_state *state = fe->demodulator_priv; 37809a0bf528SMauro Carvalho Chehab u32 reg, idle = 0, fifo_full = 1; 37819a0bf528SMauro Carvalho Chehab int i; 37829a0bf528SMauro Carvalho Chehab 37839a0bf528SMauro Carvalho Chehab reg = STV090x_READ_DEMOD(state, DISTXCTL); 37849a0bf528SMauro Carvalho Chehab 37859a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, DISTX_MODE_FIELD, 37869a0bf528SMauro Carvalho Chehab (state->config->diseqc_envelope_mode) ? 4 : 2); 37879a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, DISEQC_RESET_FIELD, 1); 37889a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0) 37899a0bf528SMauro Carvalho Chehab goto err; 37909a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, DISEQC_RESET_FIELD, 0); 37919a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0) 37929a0bf528SMauro Carvalho Chehab goto err; 37939a0bf528SMauro Carvalho Chehab 37949a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, DIS_PRECHARGE_FIELD, 1); 37959a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0) 37969a0bf528SMauro Carvalho Chehab goto err; 37979a0bf528SMauro Carvalho Chehab 37989a0bf528SMauro Carvalho Chehab for (i = 0; i < cmd->msg_len; i++) { 37999a0bf528SMauro Carvalho Chehab 38009a0bf528SMauro Carvalho Chehab while (fifo_full) { 38019a0bf528SMauro Carvalho Chehab reg = STV090x_READ_DEMOD(state, DISTXSTATUS); 38029a0bf528SMauro Carvalho Chehab fifo_full = STV090x_GETFIELD_Px(reg, FIFO_FULL_FIELD); 38039a0bf528SMauro Carvalho Chehab } 38049a0bf528SMauro Carvalho Chehab 38059a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, DISTXDATA, cmd->msg[i]) < 0) 38069a0bf528SMauro Carvalho Chehab goto err; 38079a0bf528SMauro Carvalho Chehab } 38089a0bf528SMauro Carvalho Chehab reg = STV090x_READ_DEMOD(state, DISTXCTL); 38099a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, DIS_PRECHARGE_FIELD, 0); 38109a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0) 38119a0bf528SMauro Carvalho Chehab goto err; 38129a0bf528SMauro Carvalho Chehab 38139a0bf528SMauro Carvalho Chehab i = 0; 38149a0bf528SMauro Carvalho Chehab 38159a0bf528SMauro Carvalho Chehab while ((!idle) && (i < 10)) { 38169a0bf528SMauro Carvalho Chehab reg = STV090x_READ_DEMOD(state, DISTXSTATUS); 38179a0bf528SMauro Carvalho Chehab idle = STV090x_GETFIELD_Px(reg, TX_IDLE_FIELD); 38189a0bf528SMauro Carvalho Chehab msleep(10); 38199a0bf528SMauro Carvalho Chehab i++; 38209a0bf528SMauro Carvalho Chehab } 38219a0bf528SMauro Carvalho Chehab 38229a0bf528SMauro Carvalho Chehab return 0; 38239a0bf528SMauro Carvalho Chehab err: 38249a0bf528SMauro Carvalho Chehab dprintk(FE_ERROR, 1, "I/O error"); 38259a0bf528SMauro Carvalho Chehab return -1; 38269a0bf528SMauro Carvalho Chehab } 38279a0bf528SMauro Carvalho Chehab 38280df289a2SMauro Carvalho Chehab static int stv090x_send_diseqc_burst(struct dvb_frontend *fe, 38290df289a2SMauro Carvalho Chehab enum fe_sec_mini_cmd burst) 38309a0bf528SMauro Carvalho Chehab { 38319a0bf528SMauro Carvalho Chehab struct stv090x_state *state = fe->demodulator_priv; 38329a0bf528SMauro Carvalho Chehab u32 reg, idle = 0, fifo_full = 1; 38339a0bf528SMauro Carvalho Chehab u8 mode, value; 38349a0bf528SMauro Carvalho Chehab int i; 38359a0bf528SMauro Carvalho Chehab 38369a0bf528SMauro Carvalho Chehab reg = STV090x_READ_DEMOD(state, DISTXCTL); 38379a0bf528SMauro Carvalho Chehab 38389a0bf528SMauro Carvalho Chehab if (burst == SEC_MINI_A) { 38399a0bf528SMauro Carvalho Chehab mode = (state->config->diseqc_envelope_mode) ? 5 : 3; 38409a0bf528SMauro Carvalho Chehab value = 0x00; 38419a0bf528SMauro Carvalho Chehab } else { 38429a0bf528SMauro Carvalho Chehab mode = (state->config->diseqc_envelope_mode) ? 4 : 2; 38439a0bf528SMauro Carvalho Chehab value = 0xFF; 38449a0bf528SMauro Carvalho Chehab } 38459a0bf528SMauro Carvalho Chehab 38469a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, DISTX_MODE_FIELD, mode); 38479a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, DISEQC_RESET_FIELD, 1); 38489a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0) 38499a0bf528SMauro Carvalho Chehab goto err; 38509a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, DISEQC_RESET_FIELD, 0); 38519a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0) 38529a0bf528SMauro Carvalho Chehab goto err; 38539a0bf528SMauro Carvalho Chehab 38549a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, DIS_PRECHARGE_FIELD, 1); 38559a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0) 38569a0bf528SMauro Carvalho Chehab goto err; 38579a0bf528SMauro Carvalho Chehab 38589a0bf528SMauro Carvalho Chehab while (fifo_full) { 38599a0bf528SMauro Carvalho Chehab reg = STV090x_READ_DEMOD(state, DISTXSTATUS); 38609a0bf528SMauro Carvalho Chehab fifo_full = STV090x_GETFIELD_Px(reg, FIFO_FULL_FIELD); 38619a0bf528SMauro Carvalho Chehab } 38629a0bf528SMauro Carvalho Chehab 38639a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, DISTXDATA, value) < 0) 38649a0bf528SMauro Carvalho Chehab goto err; 38659a0bf528SMauro Carvalho Chehab 38669a0bf528SMauro Carvalho Chehab reg = STV090x_READ_DEMOD(state, DISTXCTL); 38679a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, DIS_PRECHARGE_FIELD, 0); 38689a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0) 38699a0bf528SMauro Carvalho Chehab goto err; 38709a0bf528SMauro Carvalho Chehab 38719a0bf528SMauro Carvalho Chehab i = 0; 38729a0bf528SMauro Carvalho Chehab 38739a0bf528SMauro Carvalho Chehab while ((!idle) && (i < 10)) { 38749a0bf528SMauro Carvalho Chehab reg = STV090x_READ_DEMOD(state, DISTXSTATUS); 38759a0bf528SMauro Carvalho Chehab idle = STV090x_GETFIELD_Px(reg, TX_IDLE_FIELD); 38769a0bf528SMauro Carvalho Chehab msleep(10); 38779a0bf528SMauro Carvalho Chehab i++; 38789a0bf528SMauro Carvalho Chehab } 38799a0bf528SMauro Carvalho Chehab 38809a0bf528SMauro Carvalho Chehab return 0; 38819a0bf528SMauro Carvalho Chehab err: 38829a0bf528SMauro Carvalho Chehab dprintk(FE_ERROR, 1, "I/O error"); 38839a0bf528SMauro Carvalho Chehab return -1; 38849a0bf528SMauro Carvalho Chehab } 38859a0bf528SMauro Carvalho Chehab 38869a0bf528SMauro Carvalho Chehab static int stv090x_recv_slave_reply(struct dvb_frontend *fe, struct dvb_diseqc_slave_reply *reply) 38879a0bf528SMauro Carvalho Chehab { 38889a0bf528SMauro Carvalho Chehab struct stv090x_state *state = fe->demodulator_priv; 38899a0bf528SMauro Carvalho Chehab u32 reg = 0, i = 0, rx_end = 0; 38909a0bf528SMauro Carvalho Chehab 38919a0bf528SMauro Carvalho Chehab while ((rx_end != 1) && (i < 10)) { 38929a0bf528SMauro Carvalho Chehab msleep(10); 38939a0bf528SMauro Carvalho Chehab i++; 38949a0bf528SMauro Carvalho Chehab reg = STV090x_READ_DEMOD(state, DISRX_ST0); 38959a0bf528SMauro Carvalho Chehab rx_end = STV090x_GETFIELD_Px(reg, RX_END_FIELD); 38969a0bf528SMauro Carvalho Chehab } 38979a0bf528SMauro Carvalho Chehab 38989a0bf528SMauro Carvalho Chehab if (rx_end) { 38999a0bf528SMauro Carvalho Chehab reply->msg_len = STV090x_GETFIELD_Px(reg, FIFO_BYTENBR_FIELD); 39009a0bf528SMauro Carvalho Chehab for (i = 0; i < reply->msg_len; i++) 39019a0bf528SMauro Carvalho Chehab reply->msg[i] = STV090x_READ_DEMOD(state, DISRXDATA); 39029a0bf528SMauro Carvalho Chehab } 39039a0bf528SMauro Carvalho Chehab 39049a0bf528SMauro Carvalho Chehab return 0; 39059a0bf528SMauro Carvalho Chehab } 39069a0bf528SMauro Carvalho Chehab 39079a0bf528SMauro Carvalho Chehab static int stv090x_sleep(struct dvb_frontend *fe) 39089a0bf528SMauro Carvalho Chehab { 39099a0bf528SMauro Carvalho Chehab struct stv090x_state *state = fe->demodulator_priv; 39109a0bf528SMauro Carvalho Chehab u32 reg; 39119a0bf528SMauro Carvalho Chehab u8 full_standby = 0; 39129a0bf528SMauro Carvalho Chehab 39139a0bf528SMauro Carvalho Chehab if (stv090x_i2c_gate_ctrl(state, 1) < 0) 39149a0bf528SMauro Carvalho Chehab goto err; 39159a0bf528SMauro Carvalho Chehab 39169a0bf528SMauro Carvalho Chehab if (state->config->tuner_sleep) { 39179a0bf528SMauro Carvalho Chehab if (state->config->tuner_sleep(fe) < 0) 39189a0bf528SMauro Carvalho Chehab goto err_gateoff; 39199a0bf528SMauro Carvalho Chehab } 39209a0bf528SMauro Carvalho Chehab 39219a0bf528SMauro Carvalho Chehab if (stv090x_i2c_gate_ctrl(state, 0) < 0) 39229a0bf528SMauro Carvalho Chehab goto err; 39239a0bf528SMauro Carvalho Chehab 39249a0bf528SMauro Carvalho Chehab dprintk(FE_DEBUG, 1, "Set %s(%d) to sleep", 39259a0bf528SMauro Carvalho Chehab state->device == STV0900 ? "STV0900" : "STV0903", 39269a0bf528SMauro Carvalho Chehab state->demod); 39279a0bf528SMauro Carvalho Chehab 39289a0bf528SMauro Carvalho Chehab mutex_lock(&state->internal->demod_lock); 39299a0bf528SMauro Carvalho Chehab 39309a0bf528SMauro Carvalho Chehab switch (state->demod) { 39319a0bf528SMauro Carvalho Chehab case STV090x_DEMODULATOR_0: 39329a0bf528SMauro Carvalho Chehab /* power off ADC 1 */ 39339a0bf528SMauro Carvalho Chehab reg = stv090x_read_reg(state, STV090x_TSTTNR1); 39349a0bf528SMauro Carvalho Chehab STV090x_SETFIELD(reg, ADC1_PON_FIELD, 0); 39359a0bf528SMauro Carvalho Chehab if (stv090x_write_reg(state, STV090x_TSTTNR1, reg) < 0) 3936c67d2f07SAlexey Khoroshilov goto err_unlock; 39379a0bf528SMauro Carvalho Chehab /* power off DiSEqC 1 */ 39389a0bf528SMauro Carvalho Chehab reg = stv090x_read_reg(state, STV090x_TSTTNR2); 39399a0bf528SMauro Carvalho Chehab STV090x_SETFIELD(reg, DISEQC1_PON_FIELD, 0); 39409a0bf528SMauro Carvalho Chehab if (stv090x_write_reg(state, STV090x_TSTTNR2, reg) < 0) 3941c67d2f07SAlexey Khoroshilov goto err_unlock; 39429a0bf528SMauro Carvalho Chehab 39439a0bf528SMauro Carvalho Chehab /* check whether path 2 is already sleeping, that is when 39449a0bf528SMauro Carvalho Chehab ADC2 is off */ 39459a0bf528SMauro Carvalho Chehab reg = stv090x_read_reg(state, STV090x_TSTTNR3); 39469a0bf528SMauro Carvalho Chehab if (STV090x_GETFIELD(reg, ADC2_PON_FIELD) == 0) 39479a0bf528SMauro Carvalho Chehab full_standby = 1; 39489a0bf528SMauro Carvalho Chehab 39499a0bf528SMauro Carvalho Chehab /* stop clocks */ 39509a0bf528SMauro Carvalho Chehab reg = stv090x_read_reg(state, STV090x_STOPCLK1); 39519a0bf528SMauro Carvalho Chehab /* packet delineator 1 clock */ 39529a0bf528SMauro Carvalho Chehab STV090x_SETFIELD(reg, STOP_CLKPKDT1_FIELD, 1); 39539a0bf528SMauro Carvalho Chehab /* ADC 1 clock */ 39549a0bf528SMauro Carvalho Chehab STV090x_SETFIELD(reg, STOP_CLKADCI1_FIELD, 1); 39559a0bf528SMauro Carvalho Chehab /* FEC clock is shared between the two paths, only stop it 39569a0bf528SMauro Carvalho Chehab when full standby is possible */ 39579a0bf528SMauro Carvalho Chehab if (full_standby) 39589a0bf528SMauro Carvalho Chehab STV090x_SETFIELD(reg, STOP_CLKFEC_FIELD, 1); 39599a0bf528SMauro Carvalho Chehab if (stv090x_write_reg(state, STV090x_STOPCLK1, reg) < 0) 3960c67d2f07SAlexey Khoroshilov goto err_unlock; 39619a0bf528SMauro Carvalho Chehab reg = stv090x_read_reg(state, STV090x_STOPCLK2); 39629a0bf528SMauro Carvalho Chehab /* sampling 1 clock */ 39639a0bf528SMauro Carvalho Chehab STV090x_SETFIELD(reg, STOP_CLKSAMP1_FIELD, 1); 39649a0bf528SMauro Carvalho Chehab /* viterbi 1 clock */ 39659a0bf528SMauro Carvalho Chehab STV090x_SETFIELD(reg, STOP_CLKVIT1_FIELD, 1); 39669a0bf528SMauro Carvalho Chehab /* TS clock is shared between the two paths, only stop it 39679a0bf528SMauro Carvalho Chehab when full standby is possible */ 39689a0bf528SMauro Carvalho Chehab if (full_standby) 39699a0bf528SMauro Carvalho Chehab STV090x_SETFIELD(reg, STOP_CLKTS_FIELD, 1); 39709a0bf528SMauro Carvalho Chehab if (stv090x_write_reg(state, STV090x_STOPCLK2, reg) < 0) 3971c67d2f07SAlexey Khoroshilov goto err_unlock; 39729a0bf528SMauro Carvalho Chehab break; 39739a0bf528SMauro Carvalho Chehab 39749a0bf528SMauro Carvalho Chehab case STV090x_DEMODULATOR_1: 39759a0bf528SMauro Carvalho Chehab /* power off ADC 2 */ 39769a0bf528SMauro Carvalho Chehab reg = stv090x_read_reg(state, STV090x_TSTTNR3); 39779a0bf528SMauro Carvalho Chehab STV090x_SETFIELD(reg, ADC2_PON_FIELD, 0); 39789a0bf528SMauro Carvalho Chehab if (stv090x_write_reg(state, STV090x_TSTTNR3, reg) < 0) 3979c67d2f07SAlexey Khoroshilov goto err_unlock; 39809a0bf528SMauro Carvalho Chehab /* power off DiSEqC 2 */ 39819a0bf528SMauro Carvalho Chehab reg = stv090x_read_reg(state, STV090x_TSTTNR4); 39829a0bf528SMauro Carvalho Chehab STV090x_SETFIELD(reg, DISEQC2_PON_FIELD, 0); 39839a0bf528SMauro Carvalho Chehab if (stv090x_write_reg(state, STV090x_TSTTNR4, reg) < 0) 3984c67d2f07SAlexey Khoroshilov goto err_unlock; 39859a0bf528SMauro Carvalho Chehab 39869a0bf528SMauro Carvalho Chehab /* check whether path 1 is already sleeping, that is when 39879a0bf528SMauro Carvalho Chehab ADC1 is off */ 39889a0bf528SMauro Carvalho Chehab reg = stv090x_read_reg(state, STV090x_TSTTNR1); 39899a0bf528SMauro Carvalho Chehab if (STV090x_GETFIELD(reg, ADC1_PON_FIELD) == 0) 39909a0bf528SMauro Carvalho Chehab full_standby = 1; 39919a0bf528SMauro Carvalho Chehab 39929a0bf528SMauro Carvalho Chehab /* stop clocks */ 39939a0bf528SMauro Carvalho Chehab reg = stv090x_read_reg(state, STV090x_STOPCLK1); 39949a0bf528SMauro Carvalho Chehab /* packet delineator 2 clock */ 39959a0bf528SMauro Carvalho Chehab STV090x_SETFIELD(reg, STOP_CLKPKDT2_FIELD, 1); 39969a0bf528SMauro Carvalho Chehab /* ADC 2 clock */ 39979a0bf528SMauro Carvalho Chehab STV090x_SETFIELD(reg, STOP_CLKADCI2_FIELD, 1); 39989a0bf528SMauro Carvalho Chehab /* FEC clock is shared between the two paths, only stop it 39999a0bf528SMauro Carvalho Chehab when full standby is possible */ 40009a0bf528SMauro Carvalho Chehab if (full_standby) 40019a0bf528SMauro Carvalho Chehab STV090x_SETFIELD(reg, STOP_CLKFEC_FIELD, 1); 40029a0bf528SMauro Carvalho Chehab if (stv090x_write_reg(state, STV090x_STOPCLK1, reg) < 0) 4003c67d2f07SAlexey Khoroshilov goto err_unlock; 40049a0bf528SMauro Carvalho Chehab reg = stv090x_read_reg(state, STV090x_STOPCLK2); 40059a0bf528SMauro Carvalho Chehab /* sampling 2 clock */ 40069a0bf528SMauro Carvalho Chehab STV090x_SETFIELD(reg, STOP_CLKSAMP2_FIELD, 1); 40079a0bf528SMauro Carvalho Chehab /* viterbi 2 clock */ 40089a0bf528SMauro Carvalho Chehab STV090x_SETFIELD(reg, STOP_CLKVIT2_FIELD, 1); 40099a0bf528SMauro Carvalho Chehab /* TS clock is shared between the two paths, only stop it 40109a0bf528SMauro Carvalho Chehab when full standby is possible */ 40119a0bf528SMauro Carvalho Chehab if (full_standby) 40129a0bf528SMauro Carvalho Chehab STV090x_SETFIELD(reg, STOP_CLKTS_FIELD, 1); 40139a0bf528SMauro Carvalho Chehab if (stv090x_write_reg(state, STV090x_STOPCLK2, reg) < 0) 4014c67d2f07SAlexey Khoroshilov goto err_unlock; 40159a0bf528SMauro Carvalho Chehab break; 40169a0bf528SMauro Carvalho Chehab 40179a0bf528SMauro Carvalho Chehab default: 40189a0bf528SMauro Carvalho Chehab dprintk(FE_ERROR, 1, "Wrong demodulator!"); 40199a0bf528SMauro Carvalho Chehab break; 40209a0bf528SMauro Carvalho Chehab } 40219a0bf528SMauro Carvalho Chehab 40229a0bf528SMauro Carvalho Chehab if (full_standby) { 40239a0bf528SMauro Carvalho Chehab /* general power off */ 40249a0bf528SMauro Carvalho Chehab reg = stv090x_read_reg(state, STV090x_SYNTCTRL); 40259a0bf528SMauro Carvalho Chehab STV090x_SETFIELD(reg, STANDBY_FIELD, 0x01); 40269a0bf528SMauro Carvalho Chehab if (stv090x_write_reg(state, STV090x_SYNTCTRL, reg) < 0) 4027c67d2f07SAlexey Khoroshilov goto err_unlock; 40289a0bf528SMauro Carvalho Chehab } 40299a0bf528SMauro Carvalho Chehab 40309a0bf528SMauro Carvalho Chehab mutex_unlock(&state->internal->demod_lock); 40319a0bf528SMauro Carvalho Chehab return 0; 40329a0bf528SMauro Carvalho Chehab 40339a0bf528SMauro Carvalho Chehab err_gateoff: 40349a0bf528SMauro Carvalho Chehab stv090x_i2c_gate_ctrl(state, 0); 4035c67d2f07SAlexey Khoroshilov goto err; 4036c67d2f07SAlexey Khoroshilov err_unlock: 40379a0bf528SMauro Carvalho Chehab mutex_unlock(&state->internal->demod_lock); 4038c67d2f07SAlexey Khoroshilov err: 40399a0bf528SMauro Carvalho Chehab dprintk(FE_ERROR, 1, "I/O error"); 40409a0bf528SMauro Carvalho Chehab return -1; 40419a0bf528SMauro Carvalho Chehab } 40429a0bf528SMauro Carvalho Chehab 40439a0bf528SMauro Carvalho Chehab static int stv090x_wakeup(struct dvb_frontend *fe) 40449a0bf528SMauro Carvalho Chehab { 40459a0bf528SMauro Carvalho Chehab struct stv090x_state *state = fe->demodulator_priv; 40469a0bf528SMauro Carvalho Chehab u32 reg; 40479a0bf528SMauro Carvalho Chehab 40489a0bf528SMauro Carvalho Chehab dprintk(FE_DEBUG, 1, "Wake %s(%d) from standby", 40499a0bf528SMauro Carvalho Chehab state->device == STV0900 ? "STV0900" : "STV0903", 40509a0bf528SMauro Carvalho Chehab state->demod); 40519a0bf528SMauro Carvalho Chehab 40529a0bf528SMauro Carvalho Chehab mutex_lock(&state->internal->demod_lock); 40539a0bf528SMauro Carvalho Chehab 40549a0bf528SMauro Carvalho Chehab /* general power on */ 40559a0bf528SMauro Carvalho Chehab reg = stv090x_read_reg(state, STV090x_SYNTCTRL); 40569a0bf528SMauro Carvalho Chehab STV090x_SETFIELD(reg, STANDBY_FIELD, 0x00); 40579a0bf528SMauro Carvalho Chehab if (stv090x_write_reg(state, STV090x_SYNTCTRL, reg) < 0) 40589a0bf528SMauro Carvalho Chehab goto err; 40599a0bf528SMauro Carvalho Chehab 40609a0bf528SMauro Carvalho Chehab switch (state->demod) { 40619a0bf528SMauro Carvalho Chehab case STV090x_DEMODULATOR_0: 40629a0bf528SMauro Carvalho Chehab /* power on ADC 1 */ 40639a0bf528SMauro Carvalho Chehab reg = stv090x_read_reg(state, STV090x_TSTTNR1); 40649a0bf528SMauro Carvalho Chehab STV090x_SETFIELD(reg, ADC1_PON_FIELD, 1); 40659a0bf528SMauro Carvalho Chehab if (stv090x_write_reg(state, STV090x_TSTTNR1, reg) < 0) 40669a0bf528SMauro Carvalho Chehab goto err; 40679a0bf528SMauro Carvalho Chehab /* power on DiSEqC 1 */ 40689a0bf528SMauro Carvalho Chehab reg = stv090x_read_reg(state, STV090x_TSTTNR2); 40699a0bf528SMauro Carvalho Chehab STV090x_SETFIELD(reg, DISEQC1_PON_FIELD, 1); 40709a0bf528SMauro Carvalho Chehab if (stv090x_write_reg(state, STV090x_TSTTNR2, reg) < 0) 40719a0bf528SMauro Carvalho Chehab goto err; 40729a0bf528SMauro Carvalho Chehab 40739a0bf528SMauro Carvalho Chehab /* activate clocks */ 40749a0bf528SMauro Carvalho Chehab reg = stv090x_read_reg(state, STV090x_STOPCLK1); 40759a0bf528SMauro Carvalho Chehab /* packet delineator 1 clock */ 40769a0bf528SMauro Carvalho Chehab STV090x_SETFIELD(reg, STOP_CLKPKDT1_FIELD, 0); 40779a0bf528SMauro Carvalho Chehab /* ADC 1 clock */ 40789a0bf528SMauro Carvalho Chehab STV090x_SETFIELD(reg, STOP_CLKADCI1_FIELD, 0); 40799a0bf528SMauro Carvalho Chehab /* FEC clock */ 40809a0bf528SMauro Carvalho Chehab STV090x_SETFIELD(reg, STOP_CLKFEC_FIELD, 0); 40819a0bf528SMauro Carvalho Chehab if (stv090x_write_reg(state, STV090x_STOPCLK1, reg) < 0) 40829a0bf528SMauro Carvalho Chehab goto err; 40839a0bf528SMauro Carvalho Chehab reg = stv090x_read_reg(state, STV090x_STOPCLK2); 40849a0bf528SMauro Carvalho Chehab /* sampling 1 clock */ 40859a0bf528SMauro Carvalho Chehab STV090x_SETFIELD(reg, STOP_CLKSAMP1_FIELD, 0); 40869a0bf528SMauro Carvalho Chehab /* viterbi 1 clock */ 40879a0bf528SMauro Carvalho Chehab STV090x_SETFIELD(reg, STOP_CLKVIT1_FIELD, 0); 40889a0bf528SMauro Carvalho Chehab /* TS clock */ 40899a0bf528SMauro Carvalho Chehab STV090x_SETFIELD(reg, STOP_CLKTS_FIELD, 0); 40909a0bf528SMauro Carvalho Chehab if (stv090x_write_reg(state, STV090x_STOPCLK2, reg) < 0) 40919a0bf528SMauro Carvalho Chehab goto err; 40929a0bf528SMauro Carvalho Chehab break; 40939a0bf528SMauro Carvalho Chehab 40949a0bf528SMauro Carvalho Chehab case STV090x_DEMODULATOR_1: 40959a0bf528SMauro Carvalho Chehab /* power on ADC 2 */ 40969a0bf528SMauro Carvalho Chehab reg = stv090x_read_reg(state, STV090x_TSTTNR3); 40979a0bf528SMauro Carvalho Chehab STV090x_SETFIELD(reg, ADC2_PON_FIELD, 1); 40989a0bf528SMauro Carvalho Chehab if (stv090x_write_reg(state, STV090x_TSTTNR3, reg) < 0) 40999a0bf528SMauro Carvalho Chehab goto err; 41009a0bf528SMauro Carvalho Chehab /* power on DiSEqC 2 */ 41019a0bf528SMauro Carvalho Chehab reg = stv090x_read_reg(state, STV090x_TSTTNR4); 41029a0bf528SMauro Carvalho Chehab STV090x_SETFIELD(reg, DISEQC2_PON_FIELD, 1); 41039a0bf528SMauro Carvalho Chehab if (stv090x_write_reg(state, STV090x_TSTTNR4, reg) < 0) 41049a0bf528SMauro Carvalho Chehab goto err; 41059a0bf528SMauro Carvalho Chehab 41069a0bf528SMauro Carvalho Chehab /* activate clocks */ 41079a0bf528SMauro Carvalho Chehab reg = stv090x_read_reg(state, STV090x_STOPCLK1); 41089a0bf528SMauro Carvalho Chehab /* packet delineator 2 clock */ 41099a0bf528SMauro Carvalho Chehab STV090x_SETFIELD(reg, STOP_CLKPKDT2_FIELD, 0); 41109a0bf528SMauro Carvalho Chehab /* ADC 2 clock */ 41119a0bf528SMauro Carvalho Chehab STV090x_SETFIELD(reg, STOP_CLKADCI2_FIELD, 0); 41129a0bf528SMauro Carvalho Chehab /* FEC clock */ 41139a0bf528SMauro Carvalho Chehab STV090x_SETFIELD(reg, STOP_CLKFEC_FIELD, 0); 41149a0bf528SMauro Carvalho Chehab if (stv090x_write_reg(state, STV090x_STOPCLK1, reg) < 0) 41159a0bf528SMauro Carvalho Chehab goto err; 41169a0bf528SMauro Carvalho Chehab reg = stv090x_read_reg(state, STV090x_STOPCLK2); 41179a0bf528SMauro Carvalho Chehab /* sampling 2 clock */ 41189a0bf528SMauro Carvalho Chehab STV090x_SETFIELD(reg, STOP_CLKSAMP2_FIELD, 0); 41199a0bf528SMauro Carvalho Chehab /* viterbi 2 clock */ 41209a0bf528SMauro Carvalho Chehab STV090x_SETFIELD(reg, STOP_CLKVIT2_FIELD, 0); 41219a0bf528SMauro Carvalho Chehab /* TS clock */ 41229a0bf528SMauro Carvalho Chehab STV090x_SETFIELD(reg, STOP_CLKTS_FIELD, 0); 41239a0bf528SMauro Carvalho Chehab if (stv090x_write_reg(state, STV090x_STOPCLK2, reg) < 0) 41249a0bf528SMauro Carvalho Chehab goto err; 41259a0bf528SMauro Carvalho Chehab break; 41269a0bf528SMauro Carvalho Chehab 41279a0bf528SMauro Carvalho Chehab default: 41289a0bf528SMauro Carvalho Chehab dprintk(FE_ERROR, 1, "Wrong demodulator!"); 41299a0bf528SMauro Carvalho Chehab break; 41309a0bf528SMauro Carvalho Chehab } 41319a0bf528SMauro Carvalho Chehab 41329a0bf528SMauro Carvalho Chehab mutex_unlock(&state->internal->demod_lock); 41339a0bf528SMauro Carvalho Chehab return 0; 41349a0bf528SMauro Carvalho Chehab err: 41359a0bf528SMauro Carvalho Chehab mutex_unlock(&state->internal->demod_lock); 41369a0bf528SMauro Carvalho Chehab dprintk(FE_ERROR, 1, "I/O error"); 41379a0bf528SMauro Carvalho Chehab return -1; 41389a0bf528SMauro Carvalho Chehab } 41399a0bf528SMauro Carvalho Chehab 41409a0bf528SMauro Carvalho Chehab static void stv090x_release(struct dvb_frontend *fe) 41419a0bf528SMauro Carvalho Chehab { 41429a0bf528SMauro Carvalho Chehab struct stv090x_state *state = fe->demodulator_priv; 41439a0bf528SMauro Carvalho Chehab 41449a0bf528SMauro Carvalho Chehab state->internal->num_used--; 41459a0bf528SMauro Carvalho Chehab if (state->internal->num_used <= 0) { 41469a0bf528SMauro Carvalho Chehab 41479a0bf528SMauro Carvalho Chehab dprintk(FE_ERROR, 1, "Actually removing"); 41489a0bf528SMauro Carvalho Chehab 41499a0bf528SMauro Carvalho Chehab remove_dev(state->internal); 41509a0bf528SMauro Carvalho Chehab kfree(state->internal); 41519a0bf528SMauro Carvalho Chehab } 41529a0bf528SMauro Carvalho Chehab 41539a0bf528SMauro Carvalho Chehab kfree(state); 41549a0bf528SMauro Carvalho Chehab } 41559a0bf528SMauro Carvalho Chehab 41569a0bf528SMauro Carvalho Chehab static int stv090x_ldpc_mode(struct stv090x_state *state, enum stv090x_mode ldpc_mode) 41579a0bf528SMauro Carvalho Chehab { 41589a0bf528SMauro Carvalho Chehab u32 reg = 0; 41599a0bf528SMauro Carvalho Chehab 41609a0bf528SMauro Carvalho Chehab reg = stv090x_read_reg(state, STV090x_GENCFG); 41619a0bf528SMauro Carvalho Chehab 41629a0bf528SMauro Carvalho Chehab switch (ldpc_mode) { 41639a0bf528SMauro Carvalho Chehab case STV090x_DUAL: 41649a0bf528SMauro Carvalho Chehab default: 41659a0bf528SMauro Carvalho Chehab if ((state->demod_mode != STV090x_DUAL) || (STV090x_GETFIELD(reg, DDEMOD_FIELD) != 1)) { 41669a0bf528SMauro Carvalho Chehab /* set LDPC to dual mode */ 41679a0bf528SMauro Carvalho Chehab if (stv090x_write_reg(state, STV090x_GENCFG, 0x1d) < 0) 41689a0bf528SMauro Carvalho Chehab goto err; 41699a0bf528SMauro Carvalho Chehab 41709a0bf528SMauro Carvalho Chehab state->demod_mode = STV090x_DUAL; 41719a0bf528SMauro Carvalho Chehab 41729a0bf528SMauro Carvalho Chehab reg = stv090x_read_reg(state, STV090x_TSTRES0); 41739a0bf528SMauro Carvalho Chehab STV090x_SETFIELD(reg, FRESFEC_FIELD, 0x1); 41749a0bf528SMauro Carvalho Chehab if (stv090x_write_reg(state, STV090x_TSTRES0, reg) < 0) 41759a0bf528SMauro Carvalho Chehab goto err; 41769a0bf528SMauro Carvalho Chehab STV090x_SETFIELD(reg, FRESFEC_FIELD, 0x0); 41779a0bf528SMauro Carvalho Chehab if (stv090x_write_reg(state, STV090x_TSTRES0, reg) < 0) 41789a0bf528SMauro Carvalho Chehab goto err; 41799a0bf528SMauro Carvalho Chehab 41809a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, MODCODLST0, 0xff) < 0) 41819a0bf528SMauro Carvalho Chehab goto err; 41829a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, MODCODLST1, 0xff) < 0) 41839a0bf528SMauro Carvalho Chehab goto err; 41849a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, MODCODLST2, 0xff) < 0) 41859a0bf528SMauro Carvalho Chehab goto err; 41869a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, MODCODLST3, 0xff) < 0) 41879a0bf528SMauro Carvalho Chehab goto err; 41889a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, MODCODLST4, 0xff) < 0) 41899a0bf528SMauro Carvalho Chehab goto err; 41909a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, MODCODLST5, 0xff) < 0) 41919a0bf528SMauro Carvalho Chehab goto err; 41929a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, MODCODLST6, 0xff) < 0) 41939a0bf528SMauro Carvalho Chehab goto err; 41949a0bf528SMauro Carvalho Chehab 41959a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, MODCODLST7, 0xcc) < 0) 41969a0bf528SMauro Carvalho Chehab goto err; 41979a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, MODCODLST8, 0xcc) < 0) 41989a0bf528SMauro Carvalho Chehab goto err; 41999a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, MODCODLST9, 0xcc) < 0) 42009a0bf528SMauro Carvalho Chehab goto err; 42019a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, MODCODLSTA, 0xcc) < 0) 42029a0bf528SMauro Carvalho Chehab goto err; 42039a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, MODCODLSTB, 0xcc) < 0) 42049a0bf528SMauro Carvalho Chehab goto err; 42059a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, MODCODLSTC, 0xcc) < 0) 42069a0bf528SMauro Carvalho Chehab goto err; 42079a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, MODCODLSTD, 0xcc) < 0) 42089a0bf528SMauro Carvalho Chehab goto err; 42099a0bf528SMauro Carvalho Chehab 42109a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, MODCODLSTE, 0xff) < 0) 42119a0bf528SMauro Carvalho Chehab goto err; 42129a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, MODCODLSTF, 0xcf) < 0) 42139a0bf528SMauro Carvalho Chehab goto err; 42149a0bf528SMauro Carvalho Chehab } 42159a0bf528SMauro Carvalho Chehab break; 42169a0bf528SMauro Carvalho Chehab 42179a0bf528SMauro Carvalho Chehab case STV090x_SINGLE: 42189a0bf528SMauro Carvalho Chehab if (stv090x_stop_modcod(state) < 0) 42199a0bf528SMauro Carvalho Chehab goto err; 42209a0bf528SMauro Carvalho Chehab if (stv090x_activate_modcod_single(state) < 0) 42219a0bf528SMauro Carvalho Chehab goto err; 42229a0bf528SMauro Carvalho Chehab 42239a0bf528SMauro Carvalho Chehab if (state->demod == STV090x_DEMODULATOR_1) { 42249a0bf528SMauro Carvalho Chehab if (stv090x_write_reg(state, STV090x_GENCFG, 0x06) < 0) /* path 2 */ 42259a0bf528SMauro Carvalho Chehab goto err; 42269a0bf528SMauro Carvalho Chehab } else { 42279a0bf528SMauro Carvalho Chehab if (stv090x_write_reg(state, STV090x_GENCFG, 0x04) < 0) /* path 1 */ 42289a0bf528SMauro Carvalho Chehab goto err; 42299a0bf528SMauro Carvalho Chehab } 42309a0bf528SMauro Carvalho Chehab 42319a0bf528SMauro Carvalho Chehab reg = stv090x_read_reg(state, STV090x_TSTRES0); 42329a0bf528SMauro Carvalho Chehab STV090x_SETFIELD(reg, FRESFEC_FIELD, 0x1); 42339a0bf528SMauro Carvalho Chehab if (stv090x_write_reg(state, STV090x_TSTRES0, reg) < 0) 42349a0bf528SMauro Carvalho Chehab goto err; 42359a0bf528SMauro Carvalho Chehab STV090x_SETFIELD(reg, FRESFEC_FIELD, 0x0); 42369a0bf528SMauro Carvalho Chehab if (stv090x_write_reg(state, STV090x_TSTRES0, reg) < 0) 42379a0bf528SMauro Carvalho Chehab goto err; 42389a0bf528SMauro Carvalho Chehab 42399a0bf528SMauro Carvalho Chehab reg = STV090x_READ_DEMOD(state, PDELCTRL1); 42409a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, ALGOSWRST_FIELD, 0x01); 42419a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, PDELCTRL1, reg) < 0) 42429a0bf528SMauro Carvalho Chehab goto err; 42439a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, ALGOSWRST_FIELD, 0x00); 42449a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, PDELCTRL1, reg) < 0) 42459a0bf528SMauro Carvalho Chehab goto err; 42469a0bf528SMauro Carvalho Chehab break; 42479a0bf528SMauro Carvalho Chehab } 42489a0bf528SMauro Carvalho Chehab 42499a0bf528SMauro Carvalho Chehab return 0; 42509a0bf528SMauro Carvalho Chehab err: 42519a0bf528SMauro Carvalho Chehab dprintk(FE_ERROR, 1, "I/O error"); 42529a0bf528SMauro Carvalho Chehab return -1; 42539a0bf528SMauro Carvalho Chehab } 42549a0bf528SMauro Carvalho Chehab 42559a0bf528SMauro Carvalho Chehab /* return (Hz), clk in Hz*/ 42569a0bf528SMauro Carvalho Chehab static u32 stv090x_get_mclk(struct stv090x_state *state) 42579a0bf528SMauro Carvalho Chehab { 42589a0bf528SMauro Carvalho Chehab const struct stv090x_config *config = state->config; 42599a0bf528SMauro Carvalho Chehab u32 div, reg; 42609a0bf528SMauro Carvalho Chehab u8 ratio; 42619a0bf528SMauro Carvalho Chehab 42629a0bf528SMauro Carvalho Chehab div = stv090x_read_reg(state, STV090x_NCOARSE); 42639a0bf528SMauro Carvalho Chehab reg = stv090x_read_reg(state, STV090x_SYNTCTRL); 42649a0bf528SMauro Carvalho Chehab ratio = STV090x_GETFIELD(reg, SELX1RATIO_FIELD) ? 4 : 6; 42659a0bf528SMauro Carvalho Chehab 42669a0bf528SMauro Carvalho Chehab return (div + 1) * config->xtal / ratio; /* kHz */ 42679a0bf528SMauro Carvalho Chehab } 42689a0bf528SMauro Carvalho Chehab 42699a0bf528SMauro Carvalho Chehab static int stv090x_set_mclk(struct stv090x_state *state, u32 mclk, u32 clk) 42709a0bf528SMauro Carvalho Chehab { 42719a0bf528SMauro Carvalho Chehab const struct stv090x_config *config = state->config; 42729a0bf528SMauro Carvalho Chehab u32 reg, div, clk_sel; 42739a0bf528SMauro Carvalho Chehab 42749a0bf528SMauro Carvalho Chehab reg = stv090x_read_reg(state, STV090x_SYNTCTRL); 42759a0bf528SMauro Carvalho Chehab clk_sel = ((STV090x_GETFIELD(reg, SELX1RATIO_FIELD) == 1) ? 4 : 6); 42769a0bf528SMauro Carvalho Chehab 42779a0bf528SMauro Carvalho Chehab div = ((clk_sel * mclk) / config->xtal) - 1; 42789a0bf528SMauro Carvalho Chehab 42799a0bf528SMauro Carvalho Chehab reg = stv090x_read_reg(state, STV090x_NCOARSE); 42809a0bf528SMauro Carvalho Chehab STV090x_SETFIELD(reg, M_DIV_FIELD, div); 42819a0bf528SMauro Carvalho Chehab if (stv090x_write_reg(state, STV090x_NCOARSE, reg) < 0) 42829a0bf528SMauro Carvalho Chehab goto err; 42839a0bf528SMauro Carvalho Chehab 42849a0bf528SMauro Carvalho Chehab state->internal->mclk = stv090x_get_mclk(state); 42859a0bf528SMauro Carvalho Chehab 42869a0bf528SMauro Carvalho Chehab /*Set the DiseqC frequency to 22KHz */ 42879a0bf528SMauro Carvalho Chehab div = state->internal->mclk / 704000; 42889a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, F22TX, div) < 0) 42899a0bf528SMauro Carvalho Chehab goto err; 42909a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, F22RX, div) < 0) 42919a0bf528SMauro Carvalho Chehab goto err; 42929a0bf528SMauro Carvalho Chehab 42939a0bf528SMauro Carvalho Chehab return 0; 42949a0bf528SMauro Carvalho Chehab err: 42959a0bf528SMauro Carvalho Chehab dprintk(FE_ERROR, 1, "I/O error"); 42969a0bf528SMauro Carvalho Chehab return -1; 42979a0bf528SMauro Carvalho Chehab } 42989a0bf528SMauro Carvalho Chehab 42996b9e50c4SAndreas Regel static int stv0900_set_tspath(struct stv090x_state *state) 43009a0bf528SMauro Carvalho Chehab { 43019a0bf528SMauro Carvalho Chehab u32 reg; 43029a0bf528SMauro Carvalho Chehab 43039a0bf528SMauro Carvalho Chehab if (state->internal->dev_ver >= 0x20) { 43049a0bf528SMauro Carvalho Chehab switch (state->config->ts1_mode) { 43059a0bf528SMauro Carvalho Chehab case STV090x_TSMODE_PARALLEL_PUNCTURED: 43069a0bf528SMauro Carvalho Chehab case STV090x_TSMODE_DVBCI: 43079a0bf528SMauro Carvalho Chehab switch (state->config->ts2_mode) { 43089a0bf528SMauro Carvalho Chehab case STV090x_TSMODE_SERIAL_PUNCTURED: 43099a0bf528SMauro Carvalho Chehab case STV090x_TSMODE_SERIAL_CONTINUOUS: 43109a0bf528SMauro Carvalho Chehab default: 43119a0bf528SMauro Carvalho Chehab stv090x_write_reg(state, STV090x_TSGENERAL, 0x00); 43129a0bf528SMauro Carvalho Chehab break; 43139a0bf528SMauro Carvalho Chehab 43149a0bf528SMauro Carvalho Chehab case STV090x_TSMODE_PARALLEL_PUNCTURED: 43159a0bf528SMauro Carvalho Chehab case STV090x_TSMODE_DVBCI: 43169a0bf528SMauro Carvalho Chehab if (stv090x_write_reg(state, STV090x_TSGENERAL, 0x06) < 0) /* Mux'd stream mode */ 43179a0bf528SMauro Carvalho Chehab goto err; 43189a0bf528SMauro Carvalho Chehab reg = stv090x_read_reg(state, STV090x_P1_TSCFGM); 43199a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, TSFIFO_MANSPEED_FIELD, 3); 43209a0bf528SMauro Carvalho Chehab if (stv090x_write_reg(state, STV090x_P1_TSCFGM, reg) < 0) 43219a0bf528SMauro Carvalho Chehab goto err; 43229a0bf528SMauro Carvalho Chehab reg = stv090x_read_reg(state, STV090x_P2_TSCFGM); 43239a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, TSFIFO_MANSPEED_FIELD, 3); 43249a0bf528SMauro Carvalho Chehab if (stv090x_write_reg(state, STV090x_P2_TSCFGM, reg) < 0) 43259a0bf528SMauro Carvalho Chehab goto err; 43269a0bf528SMauro Carvalho Chehab if (stv090x_write_reg(state, STV090x_P1_TSSPEED, 0x14) < 0) 43279a0bf528SMauro Carvalho Chehab goto err; 43289a0bf528SMauro Carvalho Chehab if (stv090x_write_reg(state, STV090x_P2_TSSPEED, 0x28) < 0) 43299a0bf528SMauro Carvalho Chehab goto err; 43309a0bf528SMauro Carvalho Chehab break; 43319a0bf528SMauro Carvalho Chehab } 43329a0bf528SMauro Carvalho Chehab break; 43339a0bf528SMauro Carvalho Chehab 43349a0bf528SMauro Carvalho Chehab case STV090x_TSMODE_SERIAL_PUNCTURED: 43359a0bf528SMauro Carvalho Chehab case STV090x_TSMODE_SERIAL_CONTINUOUS: 43369a0bf528SMauro Carvalho Chehab default: 43379a0bf528SMauro Carvalho Chehab switch (state->config->ts2_mode) { 43389a0bf528SMauro Carvalho Chehab case STV090x_TSMODE_SERIAL_PUNCTURED: 43399a0bf528SMauro Carvalho Chehab case STV090x_TSMODE_SERIAL_CONTINUOUS: 43409a0bf528SMauro Carvalho Chehab default: 43419a0bf528SMauro Carvalho Chehab if (stv090x_write_reg(state, STV090x_TSGENERAL, 0x0c) < 0) 43429a0bf528SMauro Carvalho Chehab goto err; 43439a0bf528SMauro Carvalho Chehab break; 43449a0bf528SMauro Carvalho Chehab 43459a0bf528SMauro Carvalho Chehab case STV090x_TSMODE_PARALLEL_PUNCTURED: 43469a0bf528SMauro Carvalho Chehab case STV090x_TSMODE_DVBCI: 43479a0bf528SMauro Carvalho Chehab if (stv090x_write_reg(state, STV090x_TSGENERAL, 0x0a) < 0) 43489a0bf528SMauro Carvalho Chehab goto err; 43499a0bf528SMauro Carvalho Chehab break; 43509a0bf528SMauro Carvalho Chehab } 43519a0bf528SMauro Carvalho Chehab break; 43529a0bf528SMauro Carvalho Chehab } 43539a0bf528SMauro Carvalho Chehab } else { 43549a0bf528SMauro Carvalho Chehab switch (state->config->ts1_mode) { 43559a0bf528SMauro Carvalho Chehab case STV090x_TSMODE_PARALLEL_PUNCTURED: 43569a0bf528SMauro Carvalho Chehab case STV090x_TSMODE_DVBCI: 43579a0bf528SMauro Carvalho Chehab switch (state->config->ts2_mode) { 43589a0bf528SMauro Carvalho Chehab case STV090x_TSMODE_SERIAL_PUNCTURED: 43599a0bf528SMauro Carvalho Chehab case STV090x_TSMODE_SERIAL_CONTINUOUS: 43609a0bf528SMauro Carvalho Chehab default: 43619a0bf528SMauro Carvalho Chehab stv090x_write_reg(state, STV090x_TSGENERAL1X, 0x10); 43629a0bf528SMauro Carvalho Chehab break; 43639a0bf528SMauro Carvalho Chehab 43649a0bf528SMauro Carvalho Chehab case STV090x_TSMODE_PARALLEL_PUNCTURED: 43659a0bf528SMauro Carvalho Chehab case STV090x_TSMODE_DVBCI: 43669a0bf528SMauro Carvalho Chehab stv090x_write_reg(state, STV090x_TSGENERAL1X, 0x16); 43679a0bf528SMauro Carvalho Chehab reg = stv090x_read_reg(state, STV090x_P1_TSCFGM); 43689a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, TSFIFO_MANSPEED_FIELD, 3); 43699a0bf528SMauro Carvalho Chehab if (stv090x_write_reg(state, STV090x_P1_TSCFGM, reg) < 0) 43709a0bf528SMauro Carvalho Chehab goto err; 43719a0bf528SMauro Carvalho Chehab reg = stv090x_read_reg(state, STV090x_P1_TSCFGM); 43729a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, TSFIFO_MANSPEED_FIELD, 0); 43739a0bf528SMauro Carvalho Chehab if (stv090x_write_reg(state, STV090x_P1_TSCFGM, reg) < 0) 43749a0bf528SMauro Carvalho Chehab goto err; 43759a0bf528SMauro Carvalho Chehab if (stv090x_write_reg(state, STV090x_P1_TSSPEED, 0x14) < 0) 43769a0bf528SMauro Carvalho Chehab goto err; 43779a0bf528SMauro Carvalho Chehab if (stv090x_write_reg(state, STV090x_P2_TSSPEED, 0x28) < 0) 43789a0bf528SMauro Carvalho Chehab goto err; 43799a0bf528SMauro Carvalho Chehab break; 43809a0bf528SMauro Carvalho Chehab } 43819a0bf528SMauro Carvalho Chehab break; 43829a0bf528SMauro Carvalho Chehab 43839a0bf528SMauro Carvalho Chehab case STV090x_TSMODE_SERIAL_PUNCTURED: 43849a0bf528SMauro Carvalho Chehab case STV090x_TSMODE_SERIAL_CONTINUOUS: 43859a0bf528SMauro Carvalho Chehab default: 43869a0bf528SMauro Carvalho Chehab switch (state->config->ts2_mode) { 43879a0bf528SMauro Carvalho Chehab case STV090x_TSMODE_SERIAL_PUNCTURED: 43889a0bf528SMauro Carvalho Chehab case STV090x_TSMODE_SERIAL_CONTINUOUS: 43899a0bf528SMauro Carvalho Chehab default: 43909a0bf528SMauro Carvalho Chehab stv090x_write_reg(state, STV090x_TSGENERAL1X, 0x14); 43919a0bf528SMauro Carvalho Chehab break; 43929a0bf528SMauro Carvalho Chehab 43939a0bf528SMauro Carvalho Chehab case STV090x_TSMODE_PARALLEL_PUNCTURED: 43949a0bf528SMauro Carvalho Chehab case STV090x_TSMODE_DVBCI: 43959a0bf528SMauro Carvalho Chehab stv090x_write_reg(state, STV090x_TSGENERAL1X, 0x12); 43969a0bf528SMauro Carvalho Chehab break; 43979a0bf528SMauro Carvalho Chehab } 43989a0bf528SMauro Carvalho Chehab break; 43999a0bf528SMauro Carvalho Chehab } 44009a0bf528SMauro Carvalho Chehab } 44019a0bf528SMauro Carvalho Chehab 44029a0bf528SMauro Carvalho Chehab switch (state->config->ts1_mode) { 44039a0bf528SMauro Carvalho Chehab case STV090x_TSMODE_PARALLEL_PUNCTURED: 44049a0bf528SMauro Carvalho Chehab reg = stv090x_read_reg(state, STV090x_P1_TSCFGH); 44059a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, TSFIFO_TEIUPDATE_FIELD, state->config->ts1_tei); 44069a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, TSFIFO_SERIAL_FIELD, 0x00); 44079a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, TSFIFO_DVBCI_FIELD, 0x00); 44089a0bf528SMauro Carvalho Chehab if (stv090x_write_reg(state, STV090x_P1_TSCFGH, reg) < 0) 44099a0bf528SMauro Carvalho Chehab goto err; 44109a0bf528SMauro Carvalho Chehab break; 44119a0bf528SMauro Carvalho Chehab 44129a0bf528SMauro Carvalho Chehab case STV090x_TSMODE_DVBCI: 44139a0bf528SMauro Carvalho Chehab reg = stv090x_read_reg(state, STV090x_P1_TSCFGH); 44149a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, TSFIFO_TEIUPDATE_FIELD, state->config->ts1_tei); 44159a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, TSFIFO_SERIAL_FIELD, 0x00); 44169a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, TSFIFO_DVBCI_FIELD, 0x01); 44179a0bf528SMauro Carvalho Chehab if (stv090x_write_reg(state, STV090x_P1_TSCFGH, reg) < 0) 44189a0bf528SMauro Carvalho Chehab goto err; 44199a0bf528SMauro Carvalho Chehab break; 44209a0bf528SMauro Carvalho Chehab 44219a0bf528SMauro Carvalho Chehab case STV090x_TSMODE_SERIAL_PUNCTURED: 44229a0bf528SMauro Carvalho Chehab reg = stv090x_read_reg(state, STV090x_P1_TSCFGH); 44239a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, TSFIFO_TEIUPDATE_FIELD, state->config->ts1_tei); 44249a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, TSFIFO_SERIAL_FIELD, 0x01); 44259a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, TSFIFO_DVBCI_FIELD, 0x00); 44269a0bf528SMauro Carvalho Chehab if (stv090x_write_reg(state, STV090x_P1_TSCFGH, reg) < 0) 44279a0bf528SMauro Carvalho Chehab goto err; 44289a0bf528SMauro Carvalho Chehab break; 44299a0bf528SMauro Carvalho Chehab 44309a0bf528SMauro Carvalho Chehab case STV090x_TSMODE_SERIAL_CONTINUOUS: 44319a0bf528SMauro Carvalho Chehab reg = stv090x_read_reg(state, STV090x_P1_TSCFGH); 44329a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, TSFIFO_TEIUPDATE_FIELD, state->config->ts1_tei); 44339a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, TSFIFO_SERIAL_FIELD, 0x01); 44349a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, TSFIFO_DVBCI_FIELD, 0x01); 44359a0bf528SMauro Carvalho Chehab if (stv090x_write_reg(state, STV090x_P1_TSCFGH, reg) < 0) 44369a0bf528SMauro Carvalho Chehab goto err; 44379a0bf528SMauro Carvalho Chehab break; 44389a0bf528SMauro Carvalho Chehab 44399a0bf528SMauro Carvalho Chehab default: 44409a0bf528SMauro Carvalho Chehab break; 44419a0bf528SMauro Carvalho Chehab } 44429a0bf528SMauro Carvalho Chehab 44439a0bf528SMauro Carvalho Chehab switch (state->config->ts2_mode) { 44449a0bf528SMauro Carvalho Chehab case STV090x_TSMODE_PARALLEL_PUNCTURED: 44459a0bf528SMauro Carvalho Chehab reg = stv090x_read_reg(state, STV090x_P2_TSCFGH); 44469a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, TSFIFO_TEIUPDATE_FIELD, state->config->ts2_tei); 44479a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, TSFIFO_SERIAL_FIELD, 0x00); 44489a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, TSFIFO_DVBCI_FIELD, 0x00); 44499a0bf528SMauro Carvalho Chehab if (stv090x_write_reg(state, STV090x_P2_TSCFGH, reg) < 0) 44509a0bf528SMauro Carvalho Chehab goto err; 44519a0bf528SMauro Carvalho Chehab break; 44529a0bf528SMauro Carvalho Chehab 44539a0bf528SMauro Carvalho Chehab case STV090x_TSMODE_DVBCI: 44549a0bf528SMauro Carvalho Chehab reg = stv090x_read_reg(state, STV090x_P2_TSCFGH); 44559a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, TSFIFO_TEIUPDATE_FIELD, state->config->ts2_tei); 44569a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, TSFIFO_SERIAL_FIELD, 0x00); 44579a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, TSFIFO_DVBCI_FIELD, 0x01); 44589a0bf528SMauro Carvalho Chehab if (stv090x_write_reg(state, STV090x_P2_TSCFGH, reg) < 0) 44599a0bf528SMauro Carvalho Chehab goto err; 44609a0bf528SMauro Carvalho Chehab break; 44619a0bf528SMauro Carvalho Chehab 44629a0bf528SMauro Carvalho Chehab case STV090x_TSMODE_SERIAL_PUNCTURED: 44639a0bf528SMauro Carvalho Chehab reg = stv090x_read_reg(state, STV090x_P2_TSCFGH); 44649a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, TSFIFO_TEIUPDATE_FIELD, state->config->ts2_tei); 44659a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, TSFIFO_SERIAL_FIELD, 0x01); 44669a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, TSFIFO_DVBCI_FIELD, 0x00); 44679a0bf528SMauro Carvalho Chehab if (stv090x_write_reg(state, STV090x_P2_TSCFGH, reg) < 0) 44689a0bf528SMauro Carvalho Chehab goto err; 44699a0bf528SMauro Carvalho Chehab break; 44709a0bf528SMauro Carvalho Chehab 44719a0bf528SMauro Carvalho Chehab case STV090x_TSMODE_SERIAL_CONTINUOUS: 44729a0bf528SMauro Carvalho Chehab reg = stv090x_read_reg(state, STV090x_P2_TSCFGH); 44739a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, TSFIFO_TEIUPDATE_FIELD, state->config->ts2_tei); 44749a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, TSFIFO_SERIAL_FIELD, 0x01); 44759a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, TSFIFO_DVBCI_FIELD, 0x01); 44769a0bf528SMauro Carvalho Chehab if (stv090x_write_reg(state, STV090x_P2_TSCFGH, reg) < 0) 44779a0bf528SMauro Carvalho Chehab goto err; 44789a0bf528SMauro Carvalho Chehab break; 44799a0bf528SMauro Carvalho Chehab 44809a0bf528SMauro Carvalho Chehab default: 44819a0bf528SMauro Carvalho Chehab break; 44829a0bf528SMauro Carvalho Chehab } 44839a0bf528SMauro Carvalho Chehab 44849a0bf528SMauro Carvalho Chehab if (state->config->ts1_clk > 0) { 44859a0bf528SMauro Carvalho Chehab u32 speed; 44869a0bf528SMauro Carvalho Chehab 44879a0bf528SMauro Carvalho Chehab switch (state->config->ts1_mode) { 44889a0bf528SMauro Carvalho Chehab case STV090x_TSMODE_PARALLEL_PUNCTURED: 44899a0bf528SMauro Carvalho Chehab case STV090x_TSMODE_DVBCI: 44909a0bf528SMauro Carvalho Chehab default: 44919a0bf528SMauro Carvalho Chehab speed = state->internal->mclk / 44929a0bf528SMauro Carvalho Chehab (state->config->ts1_clk / 4); 44939a0bf528SMauro Carvalho Chehab if (speed < 0x08) 44949a0bf528SMauro Carvalho Chehab speed = 0x08; 44959a0bf528SMauro Carvalho Chehab if (speed > 0xFF) 44969a0bf528SMauro Carvalho Chehab speed = 0xFF; 44979a0bf528SMauro Carvalho Chehab break; 44989a0bf528SMauro Carvalho Chehab case STV090x_TSMODE_SERIAL_PUNCTURED: 44999a0bf528SMauro Carvalho Chehab case STV090x_TSMODE_SERIAL_CONTINUOUS: 45009a0bf528SMauro Carvalho Chehab speed = state->internal->mclk / 45019a0bf528SMauro Carvalho Chehab (state->config->ts1_clk / 32); 45029a0bf528SMauro Carvalho Chehab if (speed < 0x20) 45039a0bf528SMauro Carvalho Chehab speed = 0x20; 45049a0bf528SMauro Carvalho Chehab if (speed > 0xFF) 45059a0bf528SMauro Carvalho Chehab speed = 0xFF; 45069a0bf528SMauro Carvalho Chehab break; 45079a0bf528SMauro Carvalho Chehab } 45089a0bf528SMauro Carvalho Chehab reg = stv090x_read_reg(state, STV090x_P1_TSCFGM); 45099a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, TSFIFO_MANSPEED_FIELD, 3); 45109a0bf528SMauro Carvalho Chehab if (stv090x_write_reg(state, STV090x_P1_TSCFGM, reg) < 0) 45119a0bf528SMauro Carvalho Chehab goto err; 45129a0bf528SMauro Carvalho Chehab if (stv090x_write_reg(state, STV090x_P1_TSSPEED, speed) < 0) 45139a0bf528SMauro Carvalho Chehab goto err; 45149a0bf528SMauro Carvalho Chehab } 45159a0bf528SMauro Carvalho Chehab 45169a0bf528SMauro Carvalho Chehab if (state->config->ts2_clk > 0) { 45179a0bf528SMauro Carvalho Chehab u32 speed; 45189a0bf528SMauro Carvalho Chehab 45199a0bf528SMauro Carvalho Chehab switch (state->config->ts2_mode) { 45209a0bf528SMauro Carvalho Chehab case STV090x_TSMODE_PARALLEL_PUNCTURED: 45219a0bf528SMauro Carvalho Chehab case STV090x_TSMODE_DVBCI: 45229a0bf528SMauro Carvalho Chehab default: 45239a0bf528SMauro Carvalho Chehab speed = state->internal->mclk / 45249a0bf528SMauro Carvalho Chehab (state->config->ts2_clk / 4); 45259a0bf528SMauro Carvalho Chehab if (speed < 0x08) 45269a0bf528SMauro Carvalho Chehab speed = 0x08; 45279a0bf528SMauro Carvalho Chehab if (speed > 0xFF) 45289a0bf528SMauro Carvalho Chehab speed = 0xFF; 45299a0bf528SMauro Carvalho Chehab break; 45309a0bf528SMauro Carvalho Chehab case STV090x_TSMODE_SERIAL_PUNCTURED: 45319a0bf528SMauro Carvalho Chehab case STV090x_TSMODE_SERIAL_CONTINUOUS: 45329a0bf528SMauro Carvalho Chehab speed = state->internal->mclk / 45339a0bf528SMauro Carvalho Chehab (state->config->ts2_clk / 32); 45349a0bf528SMauro Carvalho Chehab if (speed < 0x20) 45359a0bf528SMauro Carvalho Chehab speed = 0x20; 45369a0bf528SMauro Carvalho Chehab if (speed > 0xFF) 45379a0bf528SMauro Carvalho Chehab speed = 0xFF; 45389a0bf528SMauro Carvalho Chehab break; 45399a0bf528SMauro Carvalho Chehab } 45409a0bf528SMauro Carvalho Chehab reg = stv090x_read_reg(state, STV090x_P2_TSCFGM); 45419a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, TSFIFO_MANSPEED_FIELD, 3); 45429a0bf528SMauro Carvalho Chehab if (stv090x_write_reg(state, STV090x_P2_TSCFGM, reg) < 0) 45439a0bf528SMauro Carvalho Chehab goto err; 45449a0bf528SMauro Carvalho Chehab if (stv090x_write_reg(state, STV090x_P2_TSSPEED, speed) < 0) 45459a0bf528SMauro Carvalho Chehab goto err; 45469a0bf528SMauro Carvalho Chehab } 45479a0bf528SMauro Carvalho Chehab 45489a0bf528SMauro Carvalho Chehab reg = stv090x_read_reg(state, STV090x_P2_TSCFGH); 45499a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 0x01); 45509a0bf528SMauro Carvalho Chehab if (stv090x_write_reg(state, STV090x_P2_TSCFGH, reg) < 0) 45519a0bf528SMauro Carvalho Chehab goto err; 45529a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 0x00); 45539a0bf528SMauro Carvalho Chehab if (stv090x_write_reg(state, STV090x_P2_TSCFGH, reg) < 0) 45549a0bf528SMauro Carvalho Chehab goto err; 45559a0bf528SMauro Carvalho Chehab 45569a0bf528SMauro Carvalho Chehab reg = stv090x_read_reg(state, STV090x_P1_TSCFGH); 45579a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 0x01); 45589a0bf528SMauro Carvalho Chehab if (stv090x_write_reg(state, STV090x_P1_TSCFGH, reg) < 0) 45599a0bf528SMauro Carvalho Chehab goto err; 45609a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 0x00); 45619a0bf528SMauro Carvalho Chehab if (stv090x_write_reg(state, STV090x_P1_TSCFGH, reg) < 0) 45629a0bf528SMauro Carvalho Chehab goto err; 45639a0bf528SMauro Carvalho Chehab 45649a0bf528SMauro Carvalho Chehab return 0; 45659a0bf528SMauro Carvalho Chehab err: 45669a0bf528SMauro Carvalho Chehab dprintk(FE_ERROR, 1, "I/O error"); 45679a0bf528SMauro Carvalho Chehab return -1; 45689a0bf528SMauro Carvalho Chehab } 45699a0bf528SMauro Carvalho Chehab 45706b9e50c4SAndreas Regel static int stv0903_set_tspath(struct stv090x_state *state) 45716b9e50c4SAndreas Regel { 45726b9e50c4SAndreas Regel u32 reg; 45736b9e50c4SAndreas Regel 45746b9e50c4SAndreas Regel if (state->internal->dev_ver >= 0x20) { 45756b9e50c4SAndreas Regel switch (state->config->ts1_mode) { 45766b9e50c4SAndreas Regel case STV090x_TSMODE_PARALLEL_PUNCTURED: 45776b9e50c4SAndreas Regel case STV090x_TSMODE_DVBCI: 45786b9e50c4SAndreas Regel stv090x_write_reg(state, STV090x_TSGENERAL, 0x00); 45796b9e50c4SAndreas Regel break; 45806b9e50c4SAndreas Regel 45816b9e50c4SAndreas Regel case STV090x_TSMODE_SERIAL_PUNCTURED: 45826b9e50c4SAndreas Regel case STV090x_TSMODE_SERIAL_CONTINUOUS: 45836b9e50c4SAndreas Regel default: 45846b9e50c4SAndreas Regel stv090x_write_reg(state, STV090x_TSGENERAL, 0x0c); 45856b9e50c4SAndreas Regel break; 45866b9e50c4SAndreas Regel } 45876b9e50c4SAndreas Regel } else { 45886b9e50c4SAndreas Regel switch (state->config->ts1_mode) { 45896b9e50c4SAndreas Regel case STV090x_TSMODE_PARALLEL_PUNCTURED: 45906b9e50c4SAndreas Regel case STV090x_TSMODE_DVBCI: 45916b9e50c4SAndreas Regel stv090x_write_reg(state, STV090x_TSGENERAL1X, 0x10); 45926b9e50c4SAndreas Regel break; 45936b9e50c4SAndreas Regel 45946b9e50c4SAndreas Regel case STV090x_TSMODE_SERIAL_PUNCTURED: 45956b9e50c4SAndreas Regel case STV090x_TSMODE_SERIAL_CONTINUOUS: 45966b9e50c4SAndreas Regel default: 45976b9e50c4SAndreas Regel stv090x_write_reg(state, STV090x_TSGENERAL1X, 0x14); 45986b9e50c4SAndreas Regel break; 45996b9e50c4SAndreas Regel } 46006b9e50c4SAndreas Regel } 46016b9e50c4SAndreas Regel 46026b9e50c4SAndreas Regel switch (state->config->ts1_mode) { 46036b9e50c4SAndreas Regel case STV090x_TSMODE_PARALLEL_PUNCTURED: 46046b9e50c4SAndreas Regel reg = stv090x_read_reg(state, STV090x_P1_TSCFGH); 46056b9e50c4SAndreas Regel STV090x_SETFIELD_Px(reg, TSFIFO_SERIAL_FIELD, 0x00); 46066b9e50c4SAndreas Regel STV090x_SETFIELD_Px(reg, TSFIFO_DVBCI_FIELD, 0x00); 46076b9e50c4SAndreas Regel if (stv090x_write_reg(state, STV090x_P1_TSCFGH, reg) < 0) 46086b9e50c4SAndreas Regel goto err; 46096b9e50c4SAndreas Regel break; 46106b9e50c4SAndreas Regel 46116b9e50c4SAndreas Regel case STV090x_TSMODE_DVBCI: 46126b9e50c4SAndreas Regel reg = stv090x_read_reg(state, STV090x_P1_TSCFGH); 46136b9e50c4SAndreas Regel STV090x_SETFIELD_Px(reg, TSFIFO_SERIAL_FIELD, 0x00); 46146b9e50c4SAndreas Regel STV090x_SETFIELD_Px(reg, TSFIFO_DVBCI_FIELD, 0x01); 46156b9e50c4SAndreas Regel if (stv090x_write_reg(state, STV090x_P1_TSCFGH, reg) < 0) 46166b9e50c4SAndreas Regel goto err; 46176b9e50c4SAndreas Regel break; 46186b9e50c4SAndreas Regel 46196b9e50c4SAndreas Regel case STV090x_TSMODE_SERIAL_PUNCTURED: 46206b9e50c4SAndreas Regel reg = stv090x_read_reg(state, STV090x_P1_TSCFGH); 46216b9e50c4SAndreas Regel STV090x_SETFIELD_Px(reg, TSFIFO_SERIAL_FIELD, 0x01); 46226b9e50c4SAndreas Regel STV090x_SETFIELD_Px(reg, TSFIFO_DVBCI_FIELD, 0x00); 46236b9e50c4SAndreas Regel if (stv090x_write_reg(state, STV090x_P1_TSCFGH, reg) < 0) 46246b9e50c4SAndreas Regel goto err; 46256b9e50c4SAndreas Regel break; 46266b9e50c4SAndreas Regel 46276b9e50c4SAndreas Regel case STV090x_TSMODE_SERIAL_CONTINUOUS: 46286b9e50c4SAndreas Regel reg = stv090x_read_reg(state, STV090x_P1_TSCFGH); 46296b9e50c4SAndreas Regel STV090x_SETFIELD_Px(reg, TSFIFO_SERIAL_FIELD, 0x01); 46306b9e50c4SAndreas Regel STV090x_SETFIELD_Px(reg, TSFIFO_DVBCI_FIELD, 0x01); 46316b9e50c4SAndreas Regel if (stv090x_write_reg(state, STV090x_P1_TSCFGH, reg) < 0) 46326b9e50c4SAndreas Regel goto err; 46336b9e50c4SAndreas Regel break; 46346b9e50c4SAndreas Regel 46356b9e50c4SAndreas Regel default: 46366b9e50c4SAndreas Regel break; 46376b9e50c4SAndreas Regel } 46386b9e50c4SAndreas Regel 46396b9e50c4SAndreas Regel if (state->config->ts1_clk > 0) { 46406b9e50c4SAndreas Regel u32 speed; 46416b9e50c4SAndreas Regel 46426b9e50c4SAndreas Regel switch (state->config->ts1_mode) { 46436b9e50c4SAndreas Regel case STV090x_TSMODE_PARALLEL_PUNCTURED: 46446b9e50c4SAndreas Regel case STV090x_TSMODE_DVBCI: 46456b9e50c4SAndreas Regel default: 46466b9e50c4SAndreas Regel speed = state->internal->mclk / 46476b9e50c4SAndreas Regel (state->config->ts1_clk / 4); 46486b9e50c4SAndreas Regel if (speed < 0x08) 46496b9e50c4SAndreas Regel speed = 0x08; 46506b9e50c4SAndreas Regel if (speed > 0xFF) 46516b9e50c4SAndreas Regel speed = 0xFF; 46526b9e50c4SAndreas Regel break; 46536b9e50c4SAndreas Regel case STV090x_TSMODE_SERIAL_PUNCTURED: 46546b9e50c4SAndreas Regel case STV090x_TSMODE_SERIAL_CONTINUOUS: 46556b9e50c4SAndreas Regel speed = state->internal->mclk / 46566b9e50c4SAndreas Regel (state->config->ts1_clk / 32); 46576b9e50c4SAndreas Regel if (speed < 0x20) 46586b9e50c4SAndreas Regel speed = 0x20; 46596b9e50c4SAndreas Regel if (speed > 0xFF) 46606b9e50c4SAndreas Regel speed = 0xFF; 46616b9e50c4SAndreas Regel break; 46626b9e50c4SAndreas Regel } 46636b9e50c4SAndreas Regel reg = stv090x_read_reg(state, STV090x_P1_TSCFGM); 46646b9e50c4SAndreas Regel STV090x_SETFIELD_Px(reg, TSFIFO_MANSPEED_FIELD, 3); 46656b9e50c4SAndreas Regel if (stv090x_write_reg(state, STV090x_P1_TSCFGM, reg) < 0) 46666b9e50c4SAndreas Regel goto err; 46676b9e50c4SAndreas Regel if (stv090x_write_reg(state, STV090x_P1_TSSPEED, speed) < 0) 46686b9e50c4SAndreas Regel goto err; 46696b9e50c4SAndreas Regel } 46706b9e50c4SAndreas Regel 46716b9e50c4SAndreas Regel reg = stv090x_read_reg(state, STV090x_P1_TSCFGH); 46726b9e50c4SAndreas Regel STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 0x01); 46736b9e50c4SAndreas Regel if (stv090x_write_reg(state, STV090x_P1_TSCFGH, reg) < 0) 46746b9e50c4SAndreas Regel goto err; 46756b9e50c4SAndreas Regel STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 0x00); 46766b9e50c4SAndreas Regel if (stv090x_write_reg(state, STV090x_P1_TSCFGH, reg) < 0) 46776b9e50c4SAndreas Regel goto err; 46786b9e50c4SAndreas Regel 46796b9e50c4SAndreas Regel return 0; 46806b9e50c4SAndreas Regel err: 46816b9e50c4SAndreas Regel dprintk(FE_ERROR, 1, "I/O error"); 46826b9e50c4SAndreas Regel return -1; 46836b9e50c4SAndreas Regel } 46846b9e50c4SAndreas Regel 46859a0bf528SMauro Carvalho Chehab static int stv090x_init(struct dvb_frontend *fe) 46869a0bf528SMauro Carvalho Chehab { 46879a0bf528SMauro Carvalho Chehab struct stv090x_state *state = fe->demodulator_priv; 46889a0bf528SMauro Carvalho Chehab const struct stv090x_config *config = state->config; 46899a0bf528SMauro Carvalho Chehab u32 reg; 46909a0bf528SMauro Carvalho Chehab 46919a0bf528SMauro Carvalho Chehab if (state->internal->mclk == 0) { 46929a0bf528SMauro Carvalho Chehab /* call tuner init to configure the tuner's clock output 46939a0bf528SMauro Carvalho Chehab divider directly before setting up the master clock of 46949a0bf528SMauro Carvalho Chehab the stv090x. */ 46959a0bf528SMauro Carvalho Chehab if (stv090x_i2c_gate_ctrl(state, 1) < 0) 46969a0bf528SMauro Carvalho Chehab goto err; 46979a0bf528SMauro Carvalho Chehab 46989a0bf528SMauro Carvalho Chehab if (config->tuner_init) { 46999a0bf528SMauro Carvalho Chehab if (config->tuner_init(fe) < 0) 47009a0bf528SMauro Carvalho Chehab goto err_gateoff; 47019a0bf528SMauro Carvalho Chehab } 47029a0bf528SMauro Carvalho Chehab 47039a0bf528SMauro Carvalho Chehab if (stv090x_i2c_gate_ctrl(state, 0) < 0) 47049a0bf528SMauro Carvalho Chehab goto err; 47059a0bf528SMauro Carvalho Chehab 47069a0bf528SMauro Carvalho Chehab stv090x_set_mclk(state, 135000000, config->xtal); /* 135 Mhz */ 47079a0bf528SMauro Carvalho Chehab msleep(5); 47089a0bf528SMauro Carvalho Chehab if (stv090x_write_reg(state, STV090x_SYNTCTRL, 47099a0bf528SMauro Carvalho Chehab 0x20 | config->clk_mode) < 0) 47109a0bf528SMauro Carvalho Chehab goto err; 47119a0bf528SMauro Carvalho Chehab stv090x_get_mclk(state); 47129a0bf528SMauro Carvalho Chehab } 47139a0bf528SMauro Carvalho Chehab 47149a0bf528SMauro Carvalho Chehab if (stv090x_wakeup(fe) < 0) { 47159a0bf528SMauro Carvalho Chehab dprintk(FE_ERROR, 1, "Error waking device"); 47169a0bf528SMauro Carvalho Chehab goto err; 47179a0bf528SMauro Carvalho Chehab } 47189a0bf528SMauro Carvalho Chehab 47199a0bf528SMauro Carvalho Chehab if (stv090x_ldpc_mode(state, state->demod_mode) < 0) 47209a0bf528SMauro Carvalho Chehab goto err; 47219a0bf528SMauro Carvalho Chehab 47229a0bf528SMauro Carvalho Chehab reg = STV090x_READ_DEMOD(state, TNRCFG2); 47239a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, TUN_IQSWAP_FIELD, state->inversion); 47249a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, TNRCFG2, reg) < 0) 47259a0bf528SMauro Carvalho Chehab goto err; 47269a0bf528SMauro Carvalho Chehab reg = STV090x_READ_DEMOD(state, DEMOD); 47279a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, ROLLOFF_CONTROL_FIELD, state->rolloff); 47289a0bf528SMauro Carvalho Chehab if (STV090x_WRITE_DEMOD(state, DEMOD, reg) < 0) 47299a0bf528SMauro Carvalho Chehab goto err; 47309a0bf528SMauro Carvalho Chehab 47319a0bf528SMauro Carvalho Chehab if (stv090x_i2c_gate_ctrl(state, 1) < 0) 47329a0bf528SMauro Carvalho Chehab goto err; 47339a0bf528SMauro Carvalho Chehab 47349a0bf528SMauro Carvalho Chehab if (config->tuner_set_mode) { 47359a0bf528SMauro Carvalho Chehab if (config->tuner_set_mode(fe, TUNER_WAKE) < 0) 47369a0bf528SMauro Carvalho Chehab goto err_gateoff; 47379a0bf528SMauro Carvalho Chehab } 47389a0bf528SMauro Carvalho Chehab 47399a0bf528SMauro Carvalho Chehab if (config->tuner_init) { 47409a0bf528SMauro Carvalho Chehab if (config->tuner_init(fe) < 0) 47419a0bf528SMauro Carvalho Chehab goto err_gateoff; 47429a0bf528SMauro Carvalho Chehab } 47439a0bf528SMauro Carvalho Chehab 47449a0bf528SMauro Carvalho Chehab if (stv090x_i2c_gate_ctrl(state, 0) < 0) 47459a0bf528SMauro Carvalho Chehab goto err; 47469a0bf528SMauro Carvalho Chehab 47476b9e50c4SAndreas Regel if (state->device == STV0900) { 47486b9e50c4SAndreas Regel if (stv0900_set_tspath(state) < 0) 47499a0bf528SMauro Carvalho Chehab goto err; 47506b9e50c4SAndreas Regel } else { 47516b9e50c4SAndreas Regel if (stv0903_set_tspath(state) < 0) 47526b9e50c4SAndreas Regel goto err; 47536b9e50c4SAndreas Regel } 47549a0bf528SMauro Carvalho Chehab 47559a0bf528SMauro Carvalho Chehab return 0; 47569a0bf528SMauro Carvalho Chehab 47579a0bf528SMauro Carvalho Chehab err_gateoff: 47589a0bf528SMauro Carvalho Chehab stv090x_i2c_gate_ctrl(state, 0); 47599a0bf528SMauro Carvalho Chehab err: 47609a0bf528SMauro Carvalho Chehab dprintk(FE_ERROR, 1, "I/O error"); 47619a0bf528SMauro Carvalho Chehab return -1; 47629a0bf528SMauro Carvalho Chehab } 47639a0bf528SMauro Carvalho Chehab 47649a0bf528SMauro Carvalho Chehab static int stv090x_setup(struct dvb_frontend *fe) 47659a0bf528SMauro Carvalho Chehab { 47669a0bf528SMauro Carvalho Chehab struct stv090x_state *state = fe->demodulator_priv; 47679a0bf528SMauro Carvalho Chehab const struct stv090x_config *config = state->config; 47689a0bf528SMauro Carvalho Chehab const struct stv090x_reg *stv090x_initval = NULL; 47699a0bf528SMauro Carvalho Chehab const struct stv090x_reg *stv090x_cut20_val = NULL; 47709a0bf528SMauro Carvalho Chehab unsigned long t1_size = 0, t2_size = 0; 47719a0bf528SMauro Carvalho Chehab u32 reg = 0; 47729a0bf528SMauro Carvalho Chehab 47739a0bf528SMauro Carvalho Chehab int i; 47749a0bf528SMauro Carvalho Chehab 47759a0bf528SMauro Carvalho Chehab if (state->device == STV0900) { 47769a0bf528SMauro Carvalho Chehab dprintk(FE_DEBUG, 1, "Initializing STV0900"); 47779a0bf528SMauro Carvalho Chehab stv090x_initval = stv0900_initval; 47789a0bf528SMauro Carvalho Chehab t1_size = ARRAY_SIZE(stv0900_initval); 47799a0bf528SMauro Carvalho Chehab stv090x_cut20_val = stv0900_cut20_val; 47809a0bf528SMauro Carvalho Chehab t2_size = ARRAY_SIZE(stv0900_cut20_val); 47819a0bf528SMauro Carvalho Chehab } else if (state->device == STV0903) { 47829a0bf528SMauro Carvalho Chehab dprintk(FE_DEBUG, 1, "Initializing STV0903"); 47839a0bf528SMauro Carvalho Chehab stv090x_initval = stv0903_initval; 47849a0bf528SMauro Carvalho Chehab t1_size = ARRAY_SIZE(stv0903_initval); 47859a0bf528SMauro Carvalho Chehab stv090x_cut20_val = stv0903_cut20_val; 47869a0bf528SMauro Carvalho Chehab t2_size = ARRAY_SIZE(stv0903_cut20_val); 47879a0bf528SMauro Carvalho Chehab } 47889a0bf528SMauro Carvalho Chehab 47899a0bf528SMauro Carvalho Chehab /* STV090x init */ 47909a0bf528SMauro Carvalho Chehab 47919a0bf528SMauro Carvalho Chehab /* Stop Demod */ 47929a0bf528SMauro Carvalho Chehab if (stv090x_write_reg(state, STV090x_P1_DMDISTATE, 0x5c) < 0) 47939a0bf528SMauro Carvalho Chehab goto err; 47946b9e50c4SAndreas Regel if (state->device == STV0900) 47959a0bf528SMauro Carvalho Chehab if (stv090x_write_reg(state, STV090x_P2_DMDISTATE, 0x5c) < 0) 47969a0bf528SMauro Carvalho Chehab goto err; 47979a0bf528SMauro Carvalho Chehab 47989a0bf528SMauro Carvalho Chehab msleep(5); 47999a0bf528SMauro Carvalho Chehab 48009a0bf528SMauro Carvalho Chehab /* Set No Tuner Mode */ 48019a0bf528SMauro Carvalho Chehab if (stv090x_write_reg(state, STV090x_P1_TNRCFG, 0x6c) < 0) 48029a0bf528SMauro Carvalho Chehab goto err; 48036b9e50c4SAndreas Regel if (state->device == STV0900) 48049a0bf528SMauro Carvalho Chehab if (stv090x_write_reg(state, STV090x_P2_TNRCFG, 0x6c) < 0) 48059a0bf528SMauro Carvalho Chehab goto err; 48069a0bf528SMauro Carvalho Chehab 48079a0bf528SMauro Carvalho Chehab /* I2C repeater OFF */ 48089a0bf528SMauro Carvalho Chehab STV090x_SETFIELD_Px(reg, ENARPT_LEVEL_FIELD, config->repeater_level); 48099a0bf528SMauro Carvalho Chehab if (stv090x_write_reg(state, STV090x_P1_I2CRPT, reg) < 0) 48109a0bf528SMauro Carvalho Chehab goto err; 48116b9e50c4SAndreas Regel if (state->device == STV0900) 48129a0bf528SMauro Carvalho Chehab if (stv090x_write_reg(state, STV090x_P2_I2CRPT, reg) < 0) 48139a0bf528SMauro Carvalho Chehab goto err; 48149a0bf528SMauro Carvalho Chehab 48159a0bf528SMauro Carvalho Chehab if (stv090x_write_reg(state, STV090x_NCOARSE, 0x13) < 0) /* set PLL divider */ 48169a0bf528SMauro Carvalho Chehab goto err; 48179a0bf528SMauro Carvalho Chehab msleep(5); 48189a0bf528SMauro Carvalho Chehab if (stv090x_write_reg(state, STV090x_I2CCFG, 0x08) < 0) /* 1/41 oversampling */ 48199a0bf528SMauro Carvalho Chehab goto err; 48209a0bf528SMauro Carvalho Chehab if (stv090x_write_reg(state, STV090x_SYNTCTRL, 0x20 | config->clk_mode) < 0) /* enable PLL */ 48219a0bf528SMauro Carvalho Chehab goto err; 48229a0bf528SMauro Carvalho Chehab msleep(5); 48239a0bf528SMauro Carvalho Chehab 48249a0bf528SMauro Carvalho Chehab /* write initval */ 48259a0bf528SMauro Carvalho Chehab dprintk(FE_DEBUG, 1, "Setting up initial values"); 48269a0bf528SMauro Carvalho Chehab for (i = 0; i < t1_size; i++) { 48279a0bf528SMauro Carvalho Chehab if (stv090x_write_reg(state, stv090x_initval[i].addr, stv090x_initval[i].data) < 0) 48289a0bf528SMauro Carvalho Chehab goto err; 48299a0bf528SMauro Carvalho Chehab } 48309a0bf528SMauro Carvalho Chehab 48319a0bf528SMauro Carvalho Chehab state->internal->dev_ver = stv090x_read_reg(state, STV090x_MID); 48329a0bf528SMauro Carvalho Chehab if (state->internal->dev_ver >= 0x20) { 48339a0bf528SMauro Carvalho Chehab if (stv090x_write_reg(state, STV090x_TSGENERAL, 0x0c) < 0) 48349a0bf528SMauro Carvalho Chehab goto err; 48359a0bf528SMauro Carvalho Chehab 48369a0bf528SMauro Carvalho Chehab /* write cut20_val*/ 48379a0bf528SMauro Carvalho Chehab dprintk(FE_DEBUG, 1, "Setting up Cut 2.0 initial values"); 48389a0bf528SMauro Carvalho Chehab for (i = 0; i < t2_size; i++) { 48399a0bf528SMauro Carvalho Chehab if (stv090x_write_reg(state, stv090x_cut20_val[i].addr, stv090x_cut20_val[i].data) < 0) 48409a0bf528SMauro Carvalho Chehab goto err; 48419a0bf528SMauro Carvalho Chehab } 48429a0bf528SMauro Carvalho Chehab 48439a0bf528SMauro Carvalho Chehab } else if (state->internal->dev_ver < 0x20) { 48449a0bf528SMauro Carvalho Chehab dprintk(FE_ERROR, 1, "ERROR: Unsupported Cut: 0x%02x!", 48459a0bf528SMauro Carvalho Chehab state->internal->dev_ver); 48469a0bf528SMauro Carvalho Chehab 48479a0bf528SMauro Carvalho Chehab goto err; 48489a0bf528SMauro Carvalho Chehab } else if (state->internal->dev_ver > 0x30) { 48499a0bf528SMauro Carvalho Chehab /* we shouldn't bail out from here */ 48509a0bf528SMauro Carvalho Chehab dprintk(FE_ERROR, 1, "INFO: Cut: 0x%02x probably incomplete support!", 48519a0bf528SMauro Carvalho Chehab state->internal->dev_ver); 48529a0bf528SMauro Carvalho Chehab } 48539a0bf528SMauro Carvalho Chehab 48549a0bf528SMauro Carvalho Chehab /* ADC1 range */ 48559a0bf528SMauro Carvalho Chehab reg = stv090x_read_reg(state, STV090x_TSTTNR1); 48569a0bf528SMauro Carvalho Chehab STV090x_SETFIELD(reg, ADC1_INMODE_FIELD, 48579a0bf528SMauro Carvalho Chehab (config->adc1_range == STV090x_ADC_1Vpp) ? 0 : 1); 48589a0bf528SMauro Carvalho Chehab if (stv090x_write_reg(state, STV090x_TSTTNR1, reg) < 0) 48599a0bf528SMauro Carvalho Chehab goto err; 48609a0bf528SMauro Carvalho Chehab 48619a0bf528SMauro Carvalho Chehab /* ADC2 range */ 48629a0bf528SMauro Carvalho Chehab reg = stv090x_read_reg(state, STV090x_TSTTNR3); 48639a0bf528SMauro Carvalho Chehab STV090x_SETFIELD(reg, ADC2_INMODE_FIELD, 48649a0bf528SMauro Carvalho Chehab (config->adc2_range == STV090x_ADC_1Vpp) ? 0 : 1); 48659a0bf528SMauro Carvalho Chehab if (stv090x_write_reg(state, STV090x_TSTTNR3, reg) < 0) 48669a0bf528SMauro Carvalho Chehab goto err; 48679a0bf528SMauro Carvalho Chehab 48689a0bf528SMauro Carvalho Chehab if (stv090x_write_reg(state, STV090x_TSTRES0, 0x80) < 0) 48699a0bf528SMauro Carvalho Chehab goto err; 48709a0bf528SMauro Carvalho Chehab if (stv090x_write_reg(state, STV090x_TSTRES0, 0x00) < 0) 48719a0bf528SMauro Carvalho Chehab goto err; 48729a0bf528SMauro Carvalho Chehab 48739a0bf528SMauro Carvalho Chehab return 0; 48749a0bf528SMauro Carvalho Chehab err: 48759a0bf528SMauro Carvalho Chehab dprintk(FE_ERROR, 1, "I/O error"); 48769a0bf528SMauro Carvalho Chehab return -1; 48779a0bf528SMauro Carvalho Chehab } 48789a0bf528SMauro Carvalho Chehab 4879a2ea5561SMauro Carvalho Chehab static int stv090x_set_gpio(struct dvb_frontend *fe, u8 gpio, u8 dir, 4880a2ea5561SMauro Carvalho Chehab u8 value, u8 xor_value) 48819a0bf528SMauro Carvalho Chehab { 48829a0bf528SMauro Carvalho Chehab struct stv090x_state *state = fe->demodulator_priv; 48839a0bf528SMauro Carvalho Chehab u8 reg = 0; 48849a0bf528SMauro Carvalho Chehab 48859a0bf528SMauro Carvalho Chehab STV090x_SETFIELD(reg, GPIOx_OPD_FIELD, dir); 48869a0bf528SMauro Carvalho Chehab STV090x_SETFIELD(reg, GPIOx_CONFIG_FIELD, value); 48879a0bf528SMauro Carvalho Chehab STV090x_SETFIELD(reg, GPIOx_XOR_FIELD, xor_value); 48889a0bf528SMauro Carvalho Chehab 48899a0bf528SMauro Carvalho Chehab return stv090x_write_reg(state, STV090x_GPIOxCFG(gpio), reg); 48909a0bf528SMauro Carvalho Chehab } 48919a0bf528SMauro Carvalho Chehab 4892eb5005dfSTobias Klausmann static int stv090x_setup_compound(struct stv090x_state *state) 4893eb5005dfSTobias Klausmann { 4894eb5005dfSTobias Klausmann struct stv090x_dev *temp_int; 4895eb5005dfSTobias Klausmann 4896eb5005dfSTobias Klausmann temp_int = find_dev(state->i2c, 4897eb5005dfSTobias Klausmann state->config->address); 4898eb5005dfSTobias Klausmann 4899eb5005dfSTobias Klausmann if (temp_int && state->demod_mode == STV090x_DUAL) { 4900eb5005dfSTobias Klausmann state->internal = temp_int->internal; 4901eb5005dfSTobias Klausmann state->internal->num_used++; 4902eb5005dfSTobias Klausmann dprintk(FE_INFO, 1, "Found Internal Structure!"); 4903eb5005dfSTobias Klausmann } else { 4904eb5005dfSTobias Klausmann state->internal = kmalloc(sizeof(*state->internal), GFP_KERNEL); 4905eb5005dfSTobias Klausmann if (!state->internal) 4906eb5005dfSTobias Klausmann goto error; 4907eb5005dfSTobias Klausmann temp_int = append_internal(state->internal); 4908eb5005dfSTobias Klausmann if (!temp_int) { 4909eb5005dfSTobias Klausmann kfree(state->internal); 4910eb5005dfSTobias Klausmann goto error; 4911eb5005dfSTobias Klausmann } 4912eb5005dfSTobias Klausmann state->internal->num_used = 1; 4913eb5005dfSTobias Klausmann state->internal->mclk = 0; 4914eb5005dfSTobias Klausmann state->internal->dev_ver = 0; 4915eb5005dfSTobias Klausmann state->internal->i2c_adap = state->i2c; 4916eb5005dfSTobias Klausmann state->internal->i2c_addr = state->config->address; 4917eb5005dfSTobias Klausmann dprintk(FE_INFO, 1, "Create New Internal Structure!"); 4918eb5005dfSTobias Klausmann 4919eb5005dfSTobias Klausmann mutex_init(&state->internal->demod_lock); 4920eb5005dfSTobias Klausmann mutex_init(&state->internal->tuner_lock); 4921eb5005dfSTobias Klausmann 4922eb5005dfSTobias Klausmann if (stv090x_setup(&state->frontend) < 0) { 4923eb5005dfSTobias Klausmann dprintk(FE_ERROR, 1, "Error setting up device"); 4924eb5005dfSTobias Klausmann goto err_remove; 4925eb5005dfSTobias Klausmann } 4926eb5005dfSTobias Klausmann } 4927eb5005dfSTobias Klausmann 4928eb5005dfSTobias Klausmann if (state->internal->dev_ver >= 0x30) 4929eb5005dfSTobias Klausmann state->frontend.ops.info.caps |= FE_CAN_MULTISTREAM; 4930eb5005dfSTobias Klausmann 4931eb5005dfSTobias Klausmann /* workaround for stuck DiSEqC output */ 4932eb5005dfSTobias Klausmann if (state->config->diseqc_envelope_mode) 4933eb5005dfSTobias Klausmann stv090x_send_diseqc_burst(&state->frontend, SEC_MINI_A); 4934eb5005dfSTobias Klausmann 4935eb5005dfSTobias Klausmann state->config->set_gpio = stv090x_set_gpio; 4936eb5005dfSTobias Klausmann 4937eb5005dfSTobias Klausmann dprintk(FE_ERROR, 1, "Probing %s demodulator(%d) Cut=0x%02x", 4938eb5005dfSTobias Klausmann state->device == STV0900 ? "STV0900" : "STV0903", 4939eb5005dfSTobias Klausmann state->config->demod, 4940eb5005dfSTobias Klausmann state->internal->dev_ver); 4941eb5005dfSTobias Klausmann 4942eb5005dfSTobias Klausmann return 0; 4943eb5005dfSTobias Klausmann 4944eb5005dfSTobias Klausmann error: 4945eb5005dfSTobias Klausmann return -ENOMEM; 4946eb5005dfSTobias Klausmann err_remove: 4947eb5005dfSTobias Klausmann remove_dev(state->internal); 4948eb5005dfSTobias Klausmann kfree(state->internal); 4949eb5005dfSTobias Klausmann return -ENODEV; 4950eb5005dfSTobias Klausmann } 4951eb5005dfSTobias Klausmann 4952bd336e63SMax Kellermann static const struct dvb_frontend_ops stv090x_ops = { 49539a0bf528SMauro Carvalho Chehab .delsys = { SYS_DVBS, SYS_DVBS2, SYS_DSS }, 49549a0bf528SMauro Carvalho Chehab .info = { 49559a0bf528SMauro Carvalho Chehab .name = "STV090x Multistandard", 4956f1b1eabfSMauro Carvalho Chehab .frequency_min_hz = 950 * MHz, 4957f1b1eabfSMauro Carvalho Chehab .frequency_max_hz = 2150 * MHz, 49589a0bf528SMauro Carvalho Chehab .symbol_rate_min = 1000000, 49599a0bf528SMauro Carvalho Chehab .symbol_rate_max = 45000000, 49609a0bf528SMauro Carvalho Chehab .caps = FE_CAN_INVERSION_AUTO | 49619a0bf528SMauro Carvalho Chehab FE_CAN_FEC_AUTO | 49629a0bf528SMauro Carvalho Chehab FE_CAN_QPSK | 49639a0bf528SMauro Carvalho Chehab FE_CAN_2G_MODULATION 49649a0bf528SMauro Carvalho Chehab }, 49659a0bf528SMauro Carvalho Chehab 49669a0bf528SMauro Carvalho Chehab .release = stv090x_release, 49679a0bf528SMauro Carvalho Chehab .init = stv090x_init, 49689a0bf528SMauro Carvalho Chehab 49699a0bf528SMauro Carvalho Chehab .sleep = stv090x_sleep, 49709a0bf528SMauro Carvalho Chehab .get_frontend_algo = stv090x_frontend_algo, 49719a0bf528SMauro Carvalho Chehab 49729a0bf528SMauro Carvalho Chehab .diseqc_send_master_cmd = stv090x_send_diseqc_msg, 49739a0bf528SMauro Carvalho Chehab .diseqc_send_burst = stv090x_send_diseqc_burst, 49749a0bf528SMauro Carvalho Chehab .diseqc_recv_slave_reply = stv090x_recv_slave_reply, 49759a0bf528SMauro Carvalho Chehab .set_tone = stv090x_set_tone, 49769a0bf528SMauro Carvalho Chehab 49779a0bf528SMauro Carvalho Chehab .search = stv090x_search, 49789a0bf528SMauro Carvalho Chehab .read_status = stv090x_read_status, 49799a0bf528SMauro Carvalho Chehab .read_ber = stv090x_read_per, 49809a0bf528SMauro Carvalho Chehab .read_signal_strength = stv090x_read_signal_strength, 49819a0bf528SMauro Carvalho Chehab .read_snr = stv090x_read_cnr, 49829a0bf528SMauro Carvalho Chehab }; 49839a0bf528SMauro Carvalho Chehab 4984eb5005dfSTobias Klausmann static struct dvb_frontend *stv090x_get_dvb_frontend(struct i2c_client *client) 4985eb5005dfSTobias Klausmann { 4986eb5005dfSTobias Klausmann struct stv090x_state *state = i2c_get_clientdata(client); 4987eb5005dfSTobias Klausmann 4988eb5005dfSTobias Klausmann dev_dbg(&client->dev, "\n"); 4989eb5005dfSTobias Klausmann 4990eb5005dfSTobias Klausmann return &state->frontend; 4991eb5005dfSTobias Klausmann } 4992eb5005dfSTobias Klausmann 4993be95f69cSUwe Kleine-König static int stv090x_probe(struct i2c_client *client) 4994eb5005dfSTobias Klausmann { 4995eb5005dfSTobias Klausmann int ret = 0; 4996eb5005dfSTobias Klausmann struct stv090x_config *config = client->dev.platform_data; 4997eb5005dfSTobias Klausmann 4998eb5005dfSTobias Klausmann struct stv090x_state *state = NULL; 4999eb5005dfSTobias Klausmann 5000eb5005dfSTobias Klausmann state = kzalloc(sizeof(*state), GFP_KERNEL); 5001eb5005dfSTobias Klausmann if (!state) { 5002eb5005dfSTobias Klausmann ret = -ENOMEM; 5003eb5005dfSTobias Klausmann goto error; 5004eb5005dfSTobias Klausmann } 5005eb5005dfSTobias Klausmann 5006eb5005dfSTobias Klausmann state->verbose = &verbose; 5007eb5005dfSTobias Klausmann state->config = config; 5008eb5005dfSTobias Klausmann state->i2c = client->adapter; 5009eb5005dfSTobias Klausmann state->frontend.ops = stv090x_ops; 5010eb5005dfSTobias Klausmann state->frontend.demodulator_priv = state; 5011eb5005dfSTobias Klausmann state->demod = config->demod; 5012eb5005dfSTobias Klausmann /* Single or Dual mode */ 5013eb5005dfSTobias Klausmann state->demod_mode = config->demod_mode; 5014eb5005dfSTobias Klausmann state->device = config->device; 5015eb5005dfSTobias Klausmann /* default */ 5016eb5005dfSTobias Klausmann state->rolloff = STV090x_RO_35; 5017eb5005dfSTobias Klausmann 5018eb5005dfSTobias Klausmann ret = stv090x_setup_compound(state); 5019eb5005dfSTobias Klausmann if (ret) 5020eb5005dfSTobias Klausmann goto error; 5021eb5005dfSTobias Klausmann 5022eb5005dfSTobias Klausmann i2c_set_clientdata(client, state); 5023eb5005dfSTobias Klausmann 5024eb5005dfSTobias Klausmann /* setup callbacks */ 5025eb5005dfSTobias Klausmann config->get_dvb_frontend = stv090x_get_dvb_frontend; 5026eb5005dfSTobias Klausmann 5027eb5005dfSTobias Klausmann return 0; 5028eb5005dfSTobias Klausmann 5029eb5005dfSTobias Klausmann error: 5030eb5005dfSTobias Klausmann kfree(state); 5031eb5005dfSTobias Klausmann return ret; 5032eb5005dfSTobias Klausmann } 5033eb5005dfSTobias Klausmann 5034ed5c2f5fSUwe Kleine-König static void stv090x_remove(struct i2c_client *client) 5035eb5005dfSTobias Klausmann { 5036eb5005dfSTobias Klausmann struct stv090x_state *state = i2c_get_clientdata(client); 5037eb5005dfSTobias Klausmann 5038eb5005dfSTobias Klausmann stv090x_release(&state->frontend); 5039eb5005dfSTobias Klausmann } 50409a0bf528SMauro Carvalho Chehab 5041a2ea5561SMauro Carvalho Chehab struct dvb_frontend *stv090x_attach(struct stv090x_config *config, 50429a0bf528SMauro Carvalho Chehab struct i2c_adapter *i2c, 50439a0bf528SMauro Carvalho Chehab enum stv090x_demodulator demod) 50449a0bf528SMauro Carvalho Chehab { 5045eb5005dfSTobias Klausmann int ret = 0; 50469a0bf528SMauro Carvalho Chehab struct stv090x_state *state = NULL; 50479a0bf528SMauro Carvalho Chehab 5048eb5005dfSTobias Klausmann state = kzalloc(sizeof(*state), GFP_KERNEL); 5049eb5005dfSTobias Klausmann if (!state) 50509a0bf528SMauro Carvalho Chehab goto error; 50519a0bf528SMauro Carvalho Chehab 50529a0bf528SMauro Carvalho Chehab state->verbose = &verbose; 50539a0bf528SMauro Carvalho Chehab state->config = config; 50549a0bf528SMauro Carvalho Chehab state->i2c = i2c; 50559a0bf528SMauro Carvalho Chehab state->frontend.ops = stv090x_ops; 50569a0bf528SMauro Carvalho Chehab state->frontend.demodulator_priv = state; 50579a0bf528SMauro Carvalho Chehab state->demod = demod; 5058eb5005dfSTobias Klausmann /* Single or Dual mode */ 5059eb5005dfSTobias Klausmann state->demod_mode = config->demod_mode; 50609a0bf528SMauro Carvalho Chehab state->device = config->device; 5061eb5005dfSTobias Klausmann /* default */ 5062eb5005dfSTobias Klausmann state->rolloff = STV090x_RO_35; 50639a0bf528SMauro Carvalho Chehab 5064eb5005dfSTobias Klausmann ret = stv090x_setup_compound(state); 5065eb5005dfSTobias Klausmann if (ret) 50669a0bf528SMauro Carvalho Chehab goto error; 50679a0bf528SMauro Carvalho Chehab 50689a0bf528SMauro Carvalho Chehab return &state->frontend; 50699a0bf528SMauro Carvalho Chehab 50709a0bf528SMauro Carvalho Chehab error: 50719a0bf528SMauro Carvalho Chehab kfree(state); 50729a0bf528SMauro Carvalho Chehab return NULL; 50739a0bf528SMauro Carvalho Chehab } 50749a0bf528SMauro Carvalho Chehab EXPORT_SYMBOL(stv090x_attach); 5075eb5005dfSTobias Klausmann 5076eb5005dfSTobias Klausmann static const struct i2c_device_id stv090x_id_table[] = { 5077eb5005dfSTobias Klausmann {"stv090x", 0}, 5078eb5005dfSTobias Klausmann {} 5079eb5005dfSTobias Klausmann }; 5080eb5005dfSTobias Klausmann MODULE_DEVICE_TABLE(i2c, stv090x_id_table); 5081eb5005dfSTobias Klausmann 5082eb5005dfSTobias Klausmann static struct i2c_driver stv090x_driver = { 5083eb5005dfSTobias Klausmann .driver = { 5084eb5005dfSTobias Klausmann .name = "stv090x", 5085eb5005dfSTobias Klausmann .suppress_bind_attrs = true, 5086eb5005dfSTobias Klausmann }, 5087*aaeb31c0SUwe Kleine-König .probe = stv090x_probe, 5088eb5005dfSTobias Klausmann .remove = stv090x_remove, 5089eb5005dfSTobias Klausmann .id_table = stv090x_id_table, 5090eb5005dfSTobias Klausmann }; 5091eb5005dfSTobias Klausmann 5092eb5005dfSTobias Klausmann module_i2c_driver(stv090x_driver); 5093eb5005dfSTobias Klausmann 50949a0bf528SMauro Carvalho Chehab MODULE_PARM_DESC(verbose, "Set Verbosity level"); 50959a0bf528SMauro Carvalho Chehab MODULE_AUTHOR("Manu Abraham"); 50969a0bf528SMauro Carvalho Chehab MODULE_DESCRIPTION("STV090x Multi-Std Broadcast frontend"); 50979a0bf528SMauro Carvalho Chehab MODULE_LICENSE("GPL"); 5098