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