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