18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci	STV0900/0903 Multistandard Broadcast Frontend driver
48c2ecf20Sopenharmony_ci	Copyright (C) Manu Abraham <abraham.manu@gmail.com>
58c2ecf20Sopenharmony_ci
68c2ecf20Sopenharmony_ci	Copyright (C) ST Microelectronics
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci*/
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_ci#include <linux/init.h>
118c2ecf20Sopenharmony_ci#include <linux/kernel.h>
128c2ecf20Sopenharmony_ci#include <linux/module.h>
138c2ecf20Sopenharmony_ci#include <linux/string.h>
148c2ecf20Sopenharmony_ci#include <linux/slab.h>
158c2ecf20Sopenharmony_ci#include <linux/mutex.h>
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_ci#include <linux/dvb/frontend.h>
188c2ecf20Sopenharmony_ci#include <media/dvb_frontend.h>
198c2ecf20Sopenharmony_ci
208c2ecf20Sopenharmony_ci#include "stv6110x.h" /* for demodulator internal modes */
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_ci#include "stv090x_reg.h"
238c2ecf20Sopenharmony_ci#include "stv090x.h"
248c2ecf20Sopenharmony_ci#include "stv090x_priv.h"
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_ci/* Max transfer size done by I2C transfer functions */
278c2ecf20Sopenharmony_ci#define MAX_XFER_SIZE  64
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_cistatic unsigned int verbose;
308c2ecf20Sopenharmony_cimodule_param(verbose, int, 0644);
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_ci/* internal params node */
338c2ecf20Sopenharmony_cistruct stv090x_dev {
348c2ecf20Sopenharmony_ci	/* pointer for internal params, one for each pair of demods */
358c2ecf20Sopenharmony_ci	struct stv090x_internal		*internal;
368c2ecf20Sopenharmony_ci	struct stv090x_dev		*next_dev;
378c2ecf20Sopenharmony_ci};
388c2ecf20Sopenharmony_ci
398c2ecf20Sopenharmony_ci/* first internal params */
408c2ecf20Sopenharmony_cistatic struct stv090x_dev *stv090x_first_dev;
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_ci/* find chip by i2c adapter and i2c address */
438c2ecf20Sopenharmony_cistatic struct stv090x_dev *find_dev(struct i2c_adapter *i2c_adap,
448c2ecf20Sopenharmony_ci					u8 i2c_addr)
458c2ecf20Sopenharmony_ci{
468c2ecf20Sopenharmony_ci	struct stv090x_dev *temp_dev = stv090x_first_dev;
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_ci	/*
498c2ecf20Sopenharmony_ci	 Search of the last stv0900 chip or
508c2ecf20Sopenharmony_ci	 find it by i2c adapter and i2c address */
518c2ecf20Sopenharmony_ci	while ((temp_dev != NULL) &&
528c2ecf20Sopenharmony_ci		((temp_dev->internal->i2c_adap != i2c_adap) ||
538c2ecf20Sopenharmony_ci		(temp_dev->internal->i2c_addr != i2c_addr))) {
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_ci		temp_dev = temp_dev->next_dev;
568c2ecf20Sopenharmony_ci	}
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_ci	return temp_dev;
598c2ecf20Sopenharmony_ci}
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_ci/* deallocating chip */
628c2ecf20Sopenharmony_cistatic void remove_dev(struct stv090x_internal *internal)
638c2ecf20Sopenharmony_ci{
648c2ecf20Sopenharmony_ci	struct stv090x_dev *prev_dev = stv090x_first_dev;
658c2ecf20Sopenharmony_ci	struct stv090x_dev *del_dev = find_dev(internal->i2c_adap,
668c2ecf20Sopenharmony_ci						internal->i2c_addr);
678c2ecf20Sopenharmony_ci
688c2ecf20Sopenharmony_ci	if (del_dev != NULL) {
698c2ecf20Sopenharmony_ci		if (del_dev == stv090x_first_dev) {
708c2ecf20Sopenharmony_ci			stv090x_first_dev = del_dev->next_dev;
718c2ecf20Sopenharmony_ci		} else {
728c2ecf20Sopenharmony_ci			while (prev_dev->next_dev != del_dev)
738c2ecf20Sopenharmony_ci				prev_dev = prev_dev->next_dev;
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_ci			prev_dev->next_dev = del_dev->next_dev;
768c2ecf20Sopenharmony_ci		}
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_ci		kfree(del_dev);
798c2ecf20Sopenharmony_ci	}
808c2ecf20Sopenharmony_ci}
818c2ecf20Sopenharmony_ci
828c2ecf20Sopenharmony_ci/* allocating new chip */
838c2ecf20Sopenharmony_cistatic struct stv090x_dev *append_internal(struct stv090x_internal *internal)
848c2ecf20Sopenharmony_ci{
858c2ecf20Sopenharmony_ci	struct stv090x_dev *new_dev;
868c2ecf20Sopenharmony_ci	struct stv090x_dev *temp_dev;
878c2ecf20Sopenharmony_ci
888c2ecf20Sopenharmony_ci	new_dev = kmalloc(sizeof(struct stv090x_dev), GFP_KERNEL);
898c2ecf20Sopenharmony_ci	if (new_dev != NULL) {
908c2ecf20Sopenharmony_ci		new_dev->internal = internal;
918c2ecf20Sopenharmony_ci		new_dev->next_dev = NULL;
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_ci		/* append to list */
948c2ecf20Sopenharmony_ci		if (stv090x_first_dev == NULL) {
958c2ecf20Sopenharmony_ci			stv090x_first_dev = new_dev;
968c2ecf20Sopenharmony_ci		} else {
978c2ecf20Sopenharmony_ci			temp_dev = stv090x_first_dev;
988c2ecf20Sopenharmony_ci			while (temp_dev->next_dev != NULL)
998c2ecf20Sopenharmony_ci				temp_dev = temp_dev->next_dev;
1008c2ecf20Sopenharmony_ci
1018c2ecf20Sopenharmony_ci			temp_dev->next_dev = new_dev;
1028c2ecf20Sopenharmony_ci		}
1038c2ecf20Sopenharmony_ci	}
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_ci	return new_dev;
1068c2ecf20Sopenharmony_ci}
1078c2ecf20Sopenharmony_ci
1088c2ecf20Sopenharmony_ci
1098c2ecf20Sopenharmony_ci/* DVBS1 and DSS C/N Lookup table */
1108c2ecf20Sopenharmony_cistatic const struct stv090x_tab stv090x_s1cn_tab[] = {
1118c2ecf20Sopenharmony_ci	{   0, 8917 }, /*  0.0dB */
1128c2ecf20Sopenharmony_ci	{   5, 8801 }, /*  0.5dB */
1138c2ecf20Sopenharmony_ci	{  10, 8667 }, /*  1.0dB */
1148c2ecf20Sopenharmony_ci	{  15, 8522 }, /*  1.5dB */
1158c2ecf20Sopenharmony_ci	{  20, 8355 }, /*  2.0dB */
1168c2ecf20Sopenharmony_ci	{  25, 8175 }, /*  2.5dB */
1178c2ecf20Sopenharmony_ci	{  30, 7979 }, /*  3.0dB */
1188c2ecf20Sopenharmony_ci	{  35, 7763 }, /*  3.5dB */
1198c2ecf20Sopenharmony_ci	{  40, 7530 }, /*  4.0dB */
1208c2ecf20Sopenharmony_ci	{  45, 7282 }, /*  4.5dB */
1218c2ecf20Sopenharmony_ci	{  50, 7026 }, /*  5.0dB */
1228c2ecf20Sopenharmony_ci	{  55, 6781 }, /*  5.5dB */
1238c2ecf20Sopenharmony_ci	{  60, 6514 }, /*  6.0dB */
1248c2ecf20Sopenharmony_ci	{  65, 6241 }, /*  6.5dB */
1258c2ecf20Sopenharmony_ci	{  70, 5965 }, /*  7.0dB */
1268c2ecf20Sopenharmony_ci	{  75, 5690 }, /*  7.5dB */
1278c2ecf20Sopenharmony_ci	{  80, 5424 }, /*  8.0dB */
1288c2ecf20Sopenharmony_ci	{  85, 5161 }, /*  8.5dB */
1298c2ecf20Sopenharmony_ci	{  90, 4902 }, /*  9.0dB */
1308c2ecf20Sopenharmony_ci	{  95, 4654 }, /*  9.5dB */
1318c2ecf20Sopenharmony_ci	{ 100, 4417 }, /* 10.0dB */
1328c2ecf20Sopenharmony_ci	{ 105, 4186 }, /* 10.5dB */
1338c2ecf20Sopenharmony_ci	{ 110, 3968 }, /* 11.0dB */
1348c2ecf20Sopenharmony_ci	{ 115, 3757 }, /* 11.5dB */
1358c2ecf20Sopenharmony_ci	{ 120, 3558 }, /* 12.0dB */
1368c2ecf20Sopenharmony_ci	{ 125, 3366 }, /* 12.5dB */
1378c2ecf20Sopenharmony_ci	{ 130, 3185 }, /* 13.0dB */
1388c2ecf20Sopenharmony_ci	{ 135, 3012 }, /* 13.5dB */
1398c2ecf20Sopenharmony_ci	{ 140, 2850 }, /* 14.0dB */
1408c2ecf20Sopenharmony_ci	{ 145, 2698 }, /* 14.5dB */
1418c2ecf20Sopenharmony_ci	{ 150, 2550 }, /* 15.0dB */
1428c2ecf20Sopenharmony_ci	{ 160, 2283 }, /* 16.0dB */
1438c2ecf20Sopenharmony_ci	{ 170, 2042 }, /* 17.0dB */
1448c2ecf20Sopenharmony_ci	{ 180, 1827 }, /* 18.0dB */
1458c2ecf20Sopenharmony_ci	{ 190, 1636 }, /* 19.0dB */
1468c2ecf20Sopenharmony_ci	{ 200, 1466 }, /* 20.0dB */
1478c2ecf20Sopenharmony_ci	{ 210, 1315 }, /* 21.0dB */
1488c2ecf20Sopenharmony_ci	{ 220, 1181 }, /* 22.0dB */
1498c2ecf20Sopenharmony_ci	{ 230, 1064 }, /* 23.0dB */
1508c2ecf20Sopenharmony_ci	{ 240,	960 }, /* 24.0dB */
1518c2ecf20Sopenharmony_ci	{ 250,	869 }, /* 25.0dB */
1528c2ecf20Sopenharmony_ci	{ 260,	792 }, /* 26.0dB */
1538c2ecf20Sopenharmony_ci	{ 270,	724 }, /* 27.0dB */
1548c2ecf20Sopenharmony_ci	{ 280,	665 }, /* 28.0dB */
1558c2ecf20Sopenharmony_ci	{ 290,	616 }, /* 29.0dB */
1568c2ecf20Sopenharmony_ci	{ 300,	573 }, /* 30.0dB */
1578c2ecf20Sopenharmony_ci	{ 310,	537 }, /* 31.0dB */
1588c2ecf20Sopenharmony_ci	{ 320,	507 }, /* 32.0dB */
1598c2ecf20Sopenharmony_ci	{ 330,	483 }, /* 33.0dB */
1608c2ecf20Sopenharmony_ci	{ 400,	398 }, /* 40.0dB */
1618c2ecf20Sopenharmony_ci	{ 450,	381 }, /* 45.0dB */
1628c2ecf20Sopenharmony_ci	{ 500,	377 }  /* 50.0dB */
1638c2ecf20Sopenharmony_ci};
1648c2ecf20Sopenharmony_ci
1658c2ecf20Sopenharmony_ci/* DVBS2 C/N Lookup table */
1668c2ecf20Sopenharmony_cistatic const struct stv090x_tab stv090x_s2cn_tab[] = {
1678c2ecf20Sopenharmony_ci	{ -30, 13348 }, /* -3.0dB */
1688c2ecf20Sopenharmony_ci	{ -20, 12640 }, /* -2d.0B */
1698c2ecf20Sopenharmony_ci	{ -10, 11883 }, /* -1.0dB */
1708c2ecf20Sopenharmony_ci	{   0, 11101 }, /* -0.0dB */
1718c2ecf20Sopenharmony_ci	{   5, 10718 }, /*  0.5dB */
1728c2ecf20Sopenharmony_ci	{  10, 10339 }, /*  1.0dB */
1738c2ecf20Sopenharmony_ci	{  15,  9947 }, /*  1.5dB */
1748c2ecf20Sopenharmony_ci	{  20,  9552 }, /*  2.0dB */
1758c2ecf20Sopenharmony_ci	{  25,  9183 }, /*  2.5dB */
1768c2ecf20Sopenharmony_ci	{  30,  8799 }, /*  3.0dB */
1778c2ecf20Sopenharmony_ci	{  35,  8422 }, /*  3.5dB */
1788c2ecf20Sopenharmony_ci	{  40,  8062 }, /*  4.0dB */
1798c2ecf20Sopenharmony_ci	{  45,  7707 }, /*  4.5dB */
1808c2ecf20Sopenharmony_ci	{  50,  7353 }, /*  5.0dB */
1818c2ecf20Sopenharmony_ci	{  55,  7025 }, /*  5.5dB */
1828c2ecf20Sopenharmony_ci	{  60,  6684 }, /*  6.0dB */
1838c2ecf20Sopenharmony_ci	{  65,  6331 }, /*  6.5dB */
1848c2ecf20Sopenharmony_ci	{  70,  6036 }, /*  7.0dB */
1858c2ecf20Sopenharmony_ci	{  75,  5727 }, /*  7.5dB */
1868c2ecf20Sopenharmony_ci	{  80,  5437 }, /*  8.0dB */
1878c2ecf20Sopenharmony_ci	{  85,  5164 }, /*  8.5dB */
1888c2ecf20Sopenharmony_ci	{  90,  4902 }, /*  9.0dB */
1898c2ecf20Sopenharmony_ci	{  95,  4653 }, /*  9.5dB */
1908c2ecf20Sopenharmony_ci	{ 100,  4408 }, /* 10.0dB */
1918c2ecf20Sopenharmony_ci	{ 105,  4187 }, /* 10.5dB */
1928c2ecf20Sopenharmony_ci	{ 110,  3961 }, /* 11.0dB */
1938c2ecf20Sopenharmony_ci	{ 115,  3751 }, /* 11.5dB */
1948c2ecf20Sopenharmony_ci	{ 120,  3558 }, /* 12.0dB */
1958c2ecf20Sopenharmony_ci	{ 125,  3368 }, /* 12.5dB */
1968c2ecf20Sopenharmony_ci	{ 130,  3191 }, /* 13.0dB */
1978c2ecf20Sopenharmony_ci	{ 135,  3017 }, /* 13.5dB */
1988c2ecf20Sopenharmony_ci	{ 140,  2862 }, /* 14.0dB */
1998c2ecf20Sopenharmony_ci	{ 145,  2710 }, /* 14.5dB */
2008c2ecf20Sopenharmony_ci	{ 150,  2565 }, /* 15.0dB */
2018c2ecf20Sopenharmony_ci	{ 160,  2300 }, /* 16.0dB */
2028c2ecf20Sopenharmony_ci	{ 170,  2058 }, /* 17.0dB */
2038c2ecf20Sopenharmony_ci	{ 180,  1849 }, /* 18.0dB */
2048c2ecf20Sopenharmony_ci	{ 190,  1663 }, /* 19.0dB */
2058c2ecf20Sopenharmony_ci	{ 200,  1495 }, /* 20.0dB */
2068c2ecf20Sopenharmony_ci	{ 210,  1349 }, /* 21.0dB */
2078c2ecf20Sopenharmony_ci	{ 220,  1222 }, /* 22.0dB */
2088c2ecf20Sopenharmony_ci	{ 230,  1110 }, /* 23.0dB */
2098c2ecf20Sopenharmony_ci	{ 240,  1011 }, /* 24.0dB */
2108c2ecf20Sopenharmony_ci	{ 250,   925 }, /* 25.0dB */
2118c2ecf20Sopenharmony_ci	{ 260,   853 }, /* 26.0dB */
2128c2ecf20Sopenharmony_ci	{ 270,   789 }, /* 27.0dB */
2138c2ecf20Sopenharmony_ci	{ 280,   734 }, /* 28.0dB */
2148c2ecf20Sopenharmony_ci	{ 290,   690 }, /* 29.0dB */
2158c2ecf20Sopenharmony_ci	{ 300,   650 }, /* 30.0dB */
2168c2ecf20Sopenharmony_ci	{ 310,   619 }, /* 31.0dB */
2178c2ecf20Sopenharmony_ci	{ 320,   593 }, /* 32.0dB */
2188c2ecf20Sopenharmony_ci	{ 330,   571 }, /* 33.0dB */
2198c2ecf20Sopenharmony_ci	{ 400,   498 }, /* 40.0dB */
2208c2ecf20Sopenharmony_ci	{ 450,	 484 }, /* 45.0dB */
2218c2ecf20Sopenharmony_ci	{ 500,	 481 }	/* 50.0dB */
2228c2ecf20Sopenharmony_ci};
2238c2ecf20Sopenharmony_ci
2248c2ecf20Sopenharmony_ci/* RF level C/N lookup table */
2258c2ecf20Sopenharmony_cistatic const struct stv090x_tab stv090x_rf_tab[] = {
2268c2ecf20Sopenharmony_ci	{  -5, 0xcaa1 }, /*  -5dBm */
2278c2ecf20Sopenharmony_ci	{ -10, 0xc229 }, /* -10dBm */
2288c2ecf20Sopenharmony_ci	{ -15, 0xbb08 }, /* -15dBm */
2298c2ecf20Sopenharmony_ci	{ -20, 0xb4bc }, /* -20dBm */
2308c2ecf20Sopenharmony_ci	{ -25, 0xad5a }, /* -25dBm */
2318c2ecf20Sopenharmony_ci	{ -30, 0xa298 }, /* -30dBm */
2328c2ecf20Sopenharmony_ci	{ -35, 0x98a8 }, /* -35dBm */
2338c2ecf20Sopenharmony_ci	{ -40, 0x8389 }, /* -40dBm */
2348c2ecf20Sopenharmony_ci	{ -45, 0x59be }, /* -45dBm */
2358c2ecf20Sopenharmony_ci	{ -50, 0x3a14 }, /* -50dBm */
2368c2ecf20Sopenharmony_ci	{ -55, 0x2d11 }, /* -55dBm */
2378c2ecf20Sopenharmony_ci	{ -60, 0x210d }, /* -60dBm */
2388c2ecf20Sopenharmony_ci	{ -65, 0xa14f }, /* -65dBm */
2398c2ecf20Sopenharmony_ci	{ -70, 0x07aa }	 /* -70dBm */
2408c2ecf20Sopenharmony_ci};
2418c2ecf20Sopenharmony_ci
2428c2ecf20Sopenharmony_ci
2438c2ecf20Sopenharmony_cistatic struct stv090x_reg stv0900_initval[] = {
2448c2ecf20Sopenharmony_ci
2458c2ecf20Sopenharmony_ci	{ STV090x_OUTCFG,		0x00 },
2468c2ecf20Sopenharmony_ci	{ STV090x_MODECFG,		0xff },
2478c2ecf20Sopenharmony_ci	{ STV090x_AGCRF1CFG,		0x11 },
2488c2ecf20Sopenharmony_ci	{ STV090x_AGCRF2CFG,		0x13 },
2498c2ecf20Sopenharmony_ci	{ STV090x_TSGENERAL1X,		0x14 },
2508c2ecf20Sopenharmony_ci	{ STV090x_TSTTNR2,		0x21 },
2518c2ecf20Sopenharmony_ci	{ STV090x_TSTTNR4,		0x21 },
2528c2ecf20Sopenharmony_ci	{ STV090x_P2_DISTXCTL,		0x22 },
2538c2ecf20Sopenharmony_ci	{ STV090x_P2_F22TX,		0xc0 },
2548c2ecf20Sopenharmony_ci	{ STV090x_P2_F22RX,		0xc0 },
2558c2ecf20Sopenharmony_ci	{ STV090x_P2_DISRXCTL,		0x00 },
2568c2ecf20Sopenharmony_ci	{ STV090x_P2_DMDCFGMD,		0xF9 },
2578c2ecf20Sopenharmony_ci	{ STV090x_P2_DEMOD,		0x08 },
2588c2ecf20Sopenharmony_ci	{ STV090x_P2_DMDCFG3,		0xc4 },
2598c2ecf20Sopenharmony_ci	{ STV090x_P2_CARFREQ,		0xed },
2608c2ecf20Sopenharmony_ci	{ STV090x_P2_LDT,		0xd0 },
2618c2ecf20Sopenharmony_ci	{ STV090x_P2_LDT2,		0xb8 },
2628c2ecf20Sopenharmony_ci	{ STV090x_P2_TMGCFG,		0xd2 },
2638c2ecf20Sopenharmony_ci	{ STV090x_P2_TMGTHRISE,		0x20 },
2648c2ecf20Sopenharmony_ci	{ STV090x_P1_TMGCFG,		0xd2 },
2658c2ecf20Sopenharmony_ci
2668c2ecf20Sopenharmony_ci	{ STV090x_P2_TMGTHFALL,		0x00 },
2678c2ecf20Sopenharmony_ci	{ STV090x_P2_FECSPY,		0x88 },
2688c2ecf20Sopenharmony_ci	{ STV090x_P2_FSPYDATA,		0x3a },
2698c2ecf20Sopenharmony_ci	{ STV090x_P2_FBERCPT4,		0x00 },
2708c2ecf20Sopenharmony_ci	{ STV090x_P2_FSPYBER,		0x10 },
2718c2ecf20Sopenharmony_ci	{ STV090x_P2_ERRCTRL1,		0x35 },
2728c2ecf20Sopenharmony_ci	{ STV090x_P2_ERRCTRL2,		0xc1 },
2738c2ecf20Sopenharmony_ci	{ STV090x_P2_CFRICFG,		0xf8 },
2748c2ecf20Sopenharmony_ci	{ STV090x_P2_NOSCFG,		0x1c },
2758c2ecf20Sopenharmony_ci	{ STV090x_P2_DMDTOM,		0x20 },
2768c2ecf20Sopenharmony_ci	{ STV090x_P2_CORRELMANT,	0x70 },
2778c2ecf20Sopenharmony_ci	{ STV090x_P2_CORRELABS,		0x88 },
2788c2ecf20Sopenharmony_ci	{ STV090x_P2_AGC2O,		0x5b },
2798c2ecf20Sopenharmony_ci	{ STV090x_P2_AGC2REF,		0x38 },
2808c2ecf20Sopenharmony_ci	{ STV090x_P2_CARCFG,		0xe4 },
2818c2ecf20Sopenharmony_ci	{ STV090x_P2_ACLC,		0x1A },
2828c2ecf20Sopenharmony_ci	{ STV090x_P2_BCLC,		0x09 },
2838c2ecf20Sopenharmony_ci	{ STV090x_P2_CARHDR,		0x08 },
2848c2ecf20Sopenharmony_ci	{ STV090x_P2_KREFTMG,		0xc1 },
2858c2ecf20Sopenharmony_ci	{ STV090x_P2_SFRUPRATIO,	0xf0 },
2868c2ecf20Sopenharmony_ci	{ STV090x_P2_SFRLOWRATIO,	0x70 },
2878c2ecf20Sopenharmony_ci	{ STV090x_P2_SFRSTEP,		0x58 },
2888c2ecf20Sopenharmony_ci	{ STV090x_P2_TMGCFG2,		0x01 },
2898c2ecf20Sopenharmony_ci	{ STV090x_P2_CAR2CFG,		0x26 },
2908c2ecf20Sopenharmony_ci	{ STV090x_P2_BCLC2S2Q,		0x86 },
2918c2ecf20Sopenharmony_ci	{ STV090x_P2_BCLC2S28,		0x86 },
2928c2ecf20Sopenharmony_ci	{ STV090x_P2_SMAPCOEF7,		0x77 },
2938c2ecf20Sopenharmony_ci	{ STV090x_P2_SMAPCOEF6,		0x85 },
2948c2ecf20Sopenharmony_ci	{ STV090x_P2_SMAPCOEF5,		0x77 },
2958c2ecf20Sopenharmony_ci	{ STV090x_P2_TSCFGL,		0x20 },
2968c2ecf20Sopenharmony_ci	{ STV090x_P2_DMDCFG2,		0x3b },
2978c2ecf20Sopenharmony_ci	{ STV090x_P2_MODCODLST0,	0xff },
2988c2ecf20Sopenharmony_ci	{ STV090x_P2_MODCODLST1,	0xff },
2998c2ecf20Sopenharmony_ci	{ STV090x_P2_MODCODLST2,	0xff },
3008c2ecf20Sopenharmony_ci	{ STV090x_P2_MODCODLST3,	0xff },
3018c2ecf20Sopenharmony_ci	{ STV090x_P2_MODCODLST4,	0xff },
3028c2ecf20Sopenharmony_ci	{ STV090x_P2_MODCODLST5,	0xff },
3038c2ecf20Sopenharmony_ci	{ STV090x_P2_MODCODLST6,	0xff },
3048c2ecf20Sopenharmony_ci	{ STV090x_P2_MODCODLST7,	0xcc },
3058c2ecf20Sopenharmony_ci	{ STV090x_P2_MODCODLST8,	0xcc },
3068c2ecf20Sopenharmony_ci	{ STV090x_P2_MODCODLST9,	0xcc },
3078c2ecf20Sopenharmony_ci	{ STV090x_P2_MODCODLSTA,	0xcc },
3088c2ecf20Sopenharmony_ci	{ STV090x_P2_MODCODLSTB,	0xcc },
3098c2ecf20Sopenharmony_ci	{ STV090x_P2_MODCODLSTC,	0xcc },
3108c2ecf20Sopenharmony_ci	{ STV090x_P2_MODCODLSTD,	0xcc },
3118c2ecf20Sopenharmony_ci	{ STV090x_P2_MODCODLSTE,	0xcc },
3128c2ecf20Sopenharmony_ci	{ STV090x_P2_MODCODLSTF,	0xcf },
3138c2ecf20Sopenharmony_ci	{ STV090x_P1_DISTXCTL,		0x22 },
3148c2ecf20Sopenharmony_ci	{ STV090x_P1_F22TX,		0xc0 },
3158c2ecf20Sopenharmony_ci	{ STV090x_P1_F22RX,		0xc0 },
3168c2ecf20Sopenharmony_ci	{ STV090x_P1_DISRXCTL,		0x00 },
3178c2ecf20Sopenharmony_ci	{ STV090x_P1_DMDCFGMD,		0xf9 },
3188c2ecf20Sopenharmony_ci	{ STV090x_P1_DEMOD,		0x08 },
3198c2ecf20Sopenharmony_ci	{ STV090x_P1_DMDCFG3,		0xc4 },
3208c2ecf20Sopenharmony_ci	{ STV090x_P1_DMDTOM,		0x20 },
3218c2ecf20Sopenharmony_ci	{ STV090x_P1_CARFREQ,		0xed },
3228c2ecf20Sopenharmony_ci	{ STV090x_P1_LDT,		0xd0 },
3238c2ecf20Sopenharmony_ci	{ STV090x_P1_LDT2,		0xb8 },
3248c2ecf20Sopenharmony_ci	{ STV090x_P1_TMGCFG,		0xd2 },
3258c2ecf20Sopenharmony_ci	{ STV090x_P1_TMGTHRISE,		0x20 },
3268c2ecf20Sopenharmony_ci	{ STV090x_P1_TMGTHFALL,		0x00 },
3278c2ecf20Sopenharmony_ci	{ STV090x_P1_SFRUPRATIO,	0xf0 },
3288c2ecf20Sopenharmony_ci	{ STV090x_P1_SFRLOWRATIO,	0x70 },
3298c2ecf20Sopenharmony_ci	{ STV090x_P1_TSCFGL,		0x20 },
3308c2ecf20Sopenharmony_ci	{ STV090x_P1_FECSPY,		0x88 },
3318c2ecf20Sopenharmony_ci	{ STV090x_P1_FSPYDATA,		0x3a },
3328c2ecf20Sopenharmony_ci	{ STV090x_P1_FBERCPT4,		0x00 },
3338c2ecf20Sopenharmony_ci	{ STV090x_P1_FSPYBER,		0x10 },
3348c2ecf20Sopenharmony_ci	{ STV090x_P1_ERRCTRL1,		0x35 },
3358c2ecf20Sopenharmony_ci	{ STV090x_P1_ERRCTRL2,		0xc1 },
3368c2ecf20Sopenharmony_ci	{ STV090x_P1_CFRICFG,		0xf8 },
3378c2ecf20Sopenharmony_ci	{ STV090x_P1_NOSCFG,		0x1c },
3388c2ecf20Sopenharmony_ci	{ STV090x_P1_CORRELMANT,	0x70 },
3398c2ecf20Sopenharmony_ci	{ STV090x_P1_CORRELABS,		0x88 },
3408c2ecf20Sopenharmony_ci	{ STV090x_P1_AGC2O,		0x5b },
3418c2ecf20Sopenharmony_ci	{ STV090x_P1_AGC2REF,		0x38 },
3428c2ecf20Sopenharmony_ci	{ STV090x_P1_CARCFG,		0xe4 },
3438c2ecf20Sopenharmony_ci	{ STV090x_P1_ACLC,		0x1A },
3448c2ecf20Sopenharmony_ci	{ STV090x_P1_BCLC,		0x09 },
3458c2ecf20Sopenharmony_ci	{ STV090x_P1_CARHDR,		0x08 },
3468c2ecf20Sopenharmony_ci	{ STV090x_P1_KREFTMG,		0xc1 },
3478c2ecf20Sopenharmony_ci	{ STV090x_P1_SFRSTEP,		0x58 },
3488c2ecf20Sopenharmony_ci	{ STV090x_P1_TMGCFG2,		0x01 },
3498c2ecf20Sopenharmony_ci	{ STV090x_P1_CAR2CFG,		0x26 },
3508c2ecf20Sopenharmony_ci	{ STV090x_P1_BCLC2S2Q,		0x86 },
3518c2ecf20Sopenharmony_ci	{ STV090x_P1_BCLC2S28,		0x86 },
3528c2ecf20Sopenharmony_ci	{ STV090x_P1_SMAPCOEF7,		0x77 },
3538c2ecf20Sopenharmony_ci	{ STV090x_P1_SMAPCOEF6,		0x85 },
3548c2ecf20Sopenharmony_ci	{ STV090x_P1_SMAPCOEF5,		0x77 },
3558c2ecf20Sopenharmony_ci	{ STV090x_P1_DMDCFG2,		0x3b },
3568c2ecf20Sopenharmony_ci	{ STV090x_P1_MODCODLST0,	0xff },
3578c2ecf20Sopenharmony_ci	{ STV090x_P1_MODCODLST1,	0xff },
3588c2ecf20Sopenharmony_ci	{ STV090x_P1_MODCODLST2,	0xff },
3598c2ecf20Sopenharmony_ci	{ STV090x_P1_MODCODLST3,	0xff },
3608c2ecf20Sopenharmony_ci	{ STV090x_P1_MODCODLST4,	0xff },
3618c2ecf20Sopenharmony_ci	{ STV090x_P1_MODCODLST5,	0xff },
3628c2ecf20Sopenharmony_ci	{ STV090x_P1_MODCODLST6,	0xff },
3638c2ecf20Sopenharmony_ci	{ STV090x_P1_MODCODLST7,	0xcc },
3648c2ecf20Sopenharmony_ci	{ STV090x_P1_MODCODLST8,	0xcc },
3658c2ecf20Sopenharmony_ci	{ STV090x_P1_MODCODLST9,	0xcc },
3668c2ecf20Sopenharmony_ci	{ STV090x_P1_MODCODLSTA,	0xcc },
3678c2ecf20Sopenharmony_ci	{ STV090x_P1_MODCODLSTB,	0xcc },
3688c2ecf20Sopenharmony_ci	{ STV090x_P1_MODCODLSTC,	0xcc },
3698c2ecf20Sopenharmony_ci	{ STV090x_P1_MODCODLSTD,	0xcc },
3708c2ecf20Sopenharmony_ci	{ STV090x_P1_MODCODLSTE,	0xcc },
3718c2ecf20Sopenharmony_ci	{ STV090x_P1_MODCODLSTF,	0xcf },
3728c2ecf20Sopenharmony_ci	{ STV090x_GENCFG,		0x1d },
3738c2ecf20Sopenharmony_ci	{ STV090x_NBITER_NF4,		0x37 },
3748c2ecf20Sopenharmony_ci	{ STV090x_NBITER_NF5,		0x29 },
3758c2ecf20Sopenharmony_ci	{ STV090x_NBITER_NF6,		0x37 },
3768c2ecf20Sopenharmony_ci	{ STV090x_NBITER_NF7,		0x33 },
3778c2ecf20Sopenharmony_ci	{ STV090x_NBITER_NF8,		0x31 },
3788c2ecf20Sopenharmony_ci	{ STV090x_NBITER_NF9,		0x2f },
3798c2ecf20Sopenharmony_ci	{ STV090x_NBITER_NF10,		0x39 },
3808c2ecf20Sopenharmony_ci	{ STV090x_NBITER_NF11,		0x3a },
3818c2ecf20Sopenharmony_ci	{ STV090x_NBITER_NF12,		0x29 },
3828c2ecf20Sopenharmony_ci	{ STV090x_NBITER_NF13,		0x37 },
3838c2ecf20Sopenharmony_ci	{ STV090x_NBITER_NF14,		0x33 },
3848c2ecf20Sopenharmony_ci	{ STV090x_NBITER_NF15,		0x2f },
3858c2ecf20Sopenharmony_ci	{ STV090x_NBITER_NF16,		0x39 },
3868c2ecf20Sopenharmony_ci	{ STV090x_NBITER_NF17,		0x3a },
3878c2ecf20Sopenharmony_ci	{ STV090x_NBITERNOERR,		0x04 },
3888c2ecf20Sopenharmony_ci	{ STV090x_GAINLLR_NF4,		0x0C },
3898c2ecf20Sopenharmony_ci	{ STV090x_GAINLLR_NF5,		0x0F },
3908c2ecf20Sopenharmony_ci	{ STV090x_GAINLLR_NF6,		0x11 },
3918c2ecf20Sopenharmony_ci	{ STV090x_GAINLLR_NF7,		0x14 },
3928c2ecf20Sopenharmony_ci	{ STV090x_GAINLLR_NF8,		0x17 },
3938c2ecf20Sopenharmony_ci	{ STV090x_GAINLLR_NF9,		0x19 },
3948c2ecf20Sopenharmony_ci	{ STV090x_GAINLLR_NF10,		0x20 },
3958c2ecf20Sopenharmony_ci	{ STV090x_GAINLLR_NF11,		0x21 },
3968c2ecf20Sopenharmony_ci	{ STV090x_GAINLLR_NF12,		0x0D },
3978c2ecf20Sopenharmony_ci	{ STV090x_GAINLLR_NF13,		0x0F },
3988c2ecf20Sopenharmony_ci	{ STV090x_GAINLLR_NF14,		0x13 },
3998c2ecf20Sopenharmony_ci	{ STV090x_GAINLLR_NF15,		0x1A },
4008c2ecf20Sopenharmony_ci	{ STV090x_GAINLLR_NF16,		0x1F },
4018c2ecf20Sopenharmony_ci	{ STV090x_GAINLLR_NF17,		0x21 },
4028c2ecf20Sopenharmony_ci	{ STV090x_RCCFGH,		0x20 },
4038c2ecf20Sopenharmony_ci	{ STV090x_P1_FECM,		0x01 }, /* disable DSS modes */
4048c2ecf20Sopenharmony_ci	{ STV090x_P2_FECM,		0x01 }, /* disable DSS modes */
4058c2ecf20Sopenharmony_ci	{ STV090x_P1_PRVIT,		0x2F }, /* disable PR 6/7 */
4068c2ecf20Sopenharmony_ci	{ STV090x_P2_PRVIT,		0x2F }, /* disable PR 6/7 */
4078c2ecf20Sopenharmony_ci};
4088c2ecf20Sopenharmony_ci
4098c2ecf20Sopenharmony_cistatic struct stv090x_reg stv0903_initval[] = {
4108c2ecf20Sopenharmony_ci	{ STV090x_OUTCFG,		0x00 },
4118c2ecf20Sopenharmony_ci	{ STV090x_AGCRF1CFG,		0x11 },
4128c2ecf20Sopenharmony_ci	{ STV090x_STOPCLK1,		0x48 },
4138c2ecf20Sopenharmony_ci	{ STV090x_STOPCLK2,		0x14 },
4148c2ecf20Sopenharmony_ci	{ STV090x_TSTTNR1,		0x27 },
4158c2ecf20Sopenharmony_ci	{ STV090x_TSTTNR2,		0x21 },
4168c2ecf20Sopenharmony_ci	{ STV090x_P1_DISTXCTL,		0x22 },
4178c2ecf20Sopenharmony_ci	{ STV090x_P1_F22TX,		0xc0 },
4188c2ecf20Sopenharmony_ci	{ STV090x_P1_F22RX,		0xc0 },
4198c2ecf20Sopenharmony_ci	{ STV090x_P1_DISRXCTL,		0x00 },
4208c2ecf20Sopenharmony_ci	{ STV090x_P1_DMDCFGMD,		0xF9 },
4218c2ecf20Sopenharmony_ci	{ STV090x_P1_DEMOD,		0x08 },
4228c2ecf20Sopenharmony_ci	{ STV090x_P1_DMDCFG3,		0xc4 },
4238c2ecf20Sopenharmony_ci	{ STV090x_P1_CARFREQ,		0xed },
4248c2ecf20Sopenharmony_ci	{ STV090x_P1_TNRCFG2,		0x82 },
4258c2ecf20Sopenharmony_ci	{ STV090x_P1_LDT,		0xd0 },
4268c2ecf20Sopenharmony_ci	{ STV090x_P1_LDT2,		0xb8 },
4278c2ecf20Sopenharmony_ci	{ STV090x_P1_TMGCFG,		0xd2 },
4288c2ecf20Sopenharmony_ci	{ STV090x_P1_TMGTHRISE,		0x20 },
4298c2ecf20Sopenharmony_ci	{ STV090x_P1_TMGTHFALL,		0x00 },
4308c2ecf20Sopenharmony_ci	{ STV090x_P1_SFRUPRATIO,	0xf0 },
4318c2ecf20Sopenharmony_ci	{ STV090x_P1_SFRLOWRATIO,	0x70 },
4328c2ecf20Sopenharmony_ci	{ STV090x_P1_TSCFGL,		0x20 },
4338c2ecf20Sopenharmony_ci	{ STV090x_P1_FECSPY,		0x88 },
4348c2ecf20Sopenharmony_ci	{ STV090x_P1_FSPYDATA,		0x3a },
4358c2ecf20Sopenharmony_ci	{ STV090x_P1_FBERCPT4,		0x00 },
4368c2ecf20Sopenharmony_ci	{ STV090x_P1_FSPYBER,		0x10 },
4378c2ecf20Sopenharmony_ci	{ STV090x_P1_ERRCTRL1,		0x35 },
4388c2ecf20Sopenharmony_ci	{ STV090x_P1_ERRCTRL2,		0xc1 },
4398c2ecf20Sopenharmony_ci	{ STV090x_P1_CFRICFG,		0xf8 },
4408c2ecf20Sopenharmony_ci	{ STV090x_P1_NOSCFG,		0x1c },
4418c2ecf20Sopenharmony_ci	{ STV090x_P1_DMDTOM,		0x20 },
4428c2ecf20Sopenharmony_ci	{ STV090x_P1_CORRELMANT,	0x70 },
4438c2ecf20Sopenharmony_ci	{ STV090x_P1_CORRELABS,		0x88 },
4448c2ecf20Sopenharmony_ci	{ STV090x_P1_AGC2O,		0x5b },
4458c2ecf20Sopenharmony_ci	{ STV090x_P1_AGC2REF,		0x38 },
4468c2ecf20Sopenharmony_ci	{ STV090x_P1_CARCFG,		0xe4 },
4478c2ecf20Sopenharmony_ci	{ STV090x_P1_ACLC,		0x1A },
4488c2ecf20Sopenharmony_ci	{ STV090x_P1_BCLC,		0x09 },
4498c2ecf20Sopenharmony_ci	{ STV090x_P1_CARHDR,		0x08 },
4508c2ecf20Sopenharmony_ci	{ STV090x_P1_KREFTMG,		0xc1 },
4518c2ecf20Sopenharmony_ci	{ STV090x_P1_SFRSTEP,		0x58 },
4528c2ecf20Sopenharmony_ci	{ STV090x_P1_TMGCFG2,		0x01 },
4538c2ecf20Sopenharmony_ci	{ STV090x_P1_CAR2CFG,		0x26 },
4548c2ecf20Sopenharmony_ci	{ STV090x_P1_BCLC2S2Q,		0x86 },
4558c2ecf20Sopenharmony_ci	{ STV090x_P1_BCLC2S28,		0x86 },
4568c2ecf20Sopenharmony_ci	{ STV090x_P1_SMAPCOEF7,		0x77 },
4578c2ecf20Sopenharmony_ci	{ STV090x_P1_SMAPCOEF6,		0x85 },
4588c2ecf20Sopenharmony_ci	{ STV090x_P1_SMAPCOEF5,		0x77 },
4598c2ecf20Sopenharmony_ci	{ STV090x_P1_DMDCFG2,		0x3b },
4608c2ecf20Sopenharmony_ci	{ STV090x_P1_MODCODLST0,	0xff },
4618c2ecf20Sopenharmony_ci	{ STV090x_P1_MODCODLST1,	0xff },
4628c2ecf20Sopenharmony_ci	{ STV090x_P1_MODCODLST2,	0xff },
4638c2ecf20Sopenharmony_ci	{ STV090x_P1_MODCODLST3,	0xff },
4648c2ecf20Sopenharmony_ci	{ STV090x_P1_MODCODLST4,	0xff },
4658c2ecf20Sopenharmony_ci	{ STV090x_P1_MODCODLST5,	0xff },
4668c2ecf20Sopenharmony_ci	{ STV090x_P1_MODCODLST6,	0xff },
4678c2ecf20Sopenharmony_ci	{ STV090x_P1_MODCODLST7,	0xcc },
4688c2ecf20Sopenharmony_ci	{ STV090x_P1_MODCODLST8,	0xcc },
4698c2ecf20Sopenharmony_ci	{ STV090x_P1_MODCODLST9,	0xcc },
4708c2ecf20Sopenharmony_ci	{ STV090x_P1_MODCODLSTA,	0xcc },
4718c2ecf20Sopenharmony_ci	{ STV090x_P1_MODCODLSTB,	0xcc },
4728c2ecf20Sopenharmony_ci	{ STV090x_P1_MODCODLSTC,	0xcc },
4738c2ecf20Sopenharmony_ci	{ STV090x_P1_MODCODLSTD,	0xcc },
4748c2ecf20Sopenharmony_ci	{ STV090x_P1_MODCODLSTE,	0xcc },
4758c2ecf20Sopenharmony_ci	{ STV090x_P1_MODCODLSTF,	0xcf },
4768c2ecf20Sopenharmony_ci	{ STV090x_GENCFG,		0x1c },
4778c2ecf20Sopenharmony_ci	{ STV090x_NBITER_NF4,		0x37 },
4788c2ecf20Sopenharmony_ci	{ STV090x_NBITER_NF5,		0x29 },
4798c2ecf20Sopenharmony_ci	{ STV090x_NBITER_NF6,		0x37 },
4808c2ecf20Sopenharmony_ci	{ STV090x_NBITER_NF7,		0x33 },
4818c2ecf20Sopenharmony_ci	{ STV090x_NBITER_NF8,		0x31 },
4828c2ecf20Sopenharmony_ci	{ STV090x_NBITER_NF9,		0x2f },
4838c2ecf20Sopenharmony_ci	{ STV090x_NBITER_NF10,		0x39 },
4848c2ecf20Sopenharmony_ci	{ STV090x_NBITER_NF11,		0x3a },
4858c2ecf20Sopenharmony_ci	{ STV090x_NBITER_NF12,		0x29 },
4868c2ecf20Sopenharmony_ci	{ STV090x_NBITER_NF13,		0x37 },
4878c2ecf20Sopenharmony_ci	{ STV090x_NBITER_NF14,		0x33 },
4888c2ecf20Sopenharmony_ci	{ STV090x_NBITER_NF15,		0x2f },
4898c2ecf20Sopenharmony_ci	{ STV090x_NBITER_NF16,		0x39 },
4908c2ecf20Sopenharmony_ci	{ STV090x_NBITER_NF17,		0x3a },
4918c2ecf20Sopenharmony_ci	{ STV090x_NBITERNOERR,		0x04 },
4928c2ecf20Sopenharmony_ci	{ STV090x_GAINLLR_NF4,		0x0C },
4938c2ecf20Sopenharmony_ci	{ STV090x_GAINLLR_NF5,		0x0F },
4948c2ecf20Sopenharmony_ci	{ STV090x_GAINLLR_NF6,		0x11 },
4958c2ecf20Sopenharmony_ci	{ STV090x_GAINLLR_NF7,		0x14 },
4968c2ecf20Sopenharmony_ci	{ STV090x_GAINLLR_NF8,		0x17 },
4978c2ecf20Sopenharmony_ci	{ STV090x_GAINLLR_NF9,		0x19 },
4988c2ecf20Sopenharmony_ci	{ STV090x_GAINLLR_NF10,		0x20 },
4998c2ecf20Sopenharmony_ci	{ STV090x_GAINLLR_NF11,		0x21 },
5008c2ecf20Sopenharmony_ci	{ STV090x_GAINLLR_NF12,		0x0D },
5018c2ecf20Sopenharmony_ci	{ STV090x_GAINLLR_NF13,		0x0F },
5028c2ecf20Sopenharmony_ci	{ STV090x_GAINLLR_NF14,		0x13 },
5038c2ecf20Sopenharmony_ci	{ STV090x_GAINLLR_NF15,		0x1A },
5048c2ecf20Sopenharmony_ci	{ STV090x_GAINLLR_NF16,		0x1F },
5058c2ecf20Sopenharmony_ci	{ STV090x_GAINLLR_NF17,		0x21 },
5068c2ecf20Sopenharmony_ci	{ STV090x_RCCFGH,		0x20 },
5078c2ecf20Sopenharmony_ci	{ STV090x_P1_FECM,		0x01 }, /*disable the DSS mode */
5088c2ecf20Sopenharmony_ci	{ STV090x_P1_PRVIT,		0x2f }  /*disable puncture rate 6/7*/
5098c2ecf20Sopenharmony_ci};
5108c2ecf20Sopenharmony_ci
5118c2ecf20Sopenharmony_cistatic struct stv090x_reg stv0900_cut20_val[] = {
5128c2ecf20Sopenharmony_ci
5138c2ecf20Sopenharmony_ci	{ STV090x_P2_DMDCFG3,		0xe8 },
5148c2ecf20Sopenharmony_ci	{ STV090x_P2_DMDCFG4,		0x10 },
5158c2ecf20Sopenharmony_ci	{ STV090x_P2_CARFREQ,		0x38 },
5168c2ecf20Sopenharmony_ci	{ STV090x_P2_CARHDR,		0x20 },
5178c2ecf20Sopenharmony_ci	{ STV090x_P2_KREFTMG,		0x5a },
5188c2ecf20Sopenharmony_ci	{ STV090x_P2_SMAPCOEF7,		0x06 },
5198c2ecf20Sopenharmony_ci	{ STV090x_P2_SMAPCOEF6,		0x00 },
5208c2ecf20Sopenharmony_ci	{ STV090x_P2_SMAPCOEF5,		0x04 },
5218c2ecf20Sopenharmony_ci	{ STV090x_P2_NOSCFG,		0x0c },
5228c2ecf20Sopenharmony_ci	{ STV090x_P1_DMDCFG3,		0xe8 },
5238c2ecf20Sopenharmony_ci	{ STV090x_P1_DMDCFG4,		0x10 },
5248c2ecf20Sopenharmony_ci	{ STV090x_P1_CARFREQ,		0x38 },
5258c2ecf20Sopenharmony_ci	{ STV090x_P1_CARHDR,		0x20 },
5268c2ecf20Sopenharmony_ci	{ STV090x_P1_KREFTMG,		0x5a },
5278c2ecf20Sopenharmony_ci	{ STV090x_P1_SMAPCOEF7,		0x06 },
5288c2ecf20Sopenharmony_ci	{ STV090x_P1_SMAPCOEF6,		0x00 },
5298c2ecf20Sopenharmony_ci	{ STV090x_P1_SMAPCOEF5,		0x04 },
5308c2ecf20Sopenharmony_ci	{ STV090x_P1_NOSCFG,		0x0c },
5318c2ecf20Sopenharmony_ci	{ STV090x_GAINLLR_NF4,		0x21 },
5328c2ecf20Sopenharmony_ci	{ STV090x_GAINLLR_NF5,		0x21 },
5338c2ecf20Sopenharmony_ci	{ STV090x_GAINLLR_NF6,		0x20 },
5348c2ecf20Sopenharmony_ci	{ STV090x_GAINLLR_NF7,		0x1F },
5358c2ecf20Sopenharmony_ci	{ STV090x_GAINLLR_NF8,		0x1E },
5368c2ecf20Sopenharmony_ci	{ STV090x_GAINLLR_NF9,		0x1E },
5378c2ecf20Sopenharmony_ci	{ STV090x_GAINLLR_NF10,		0x1D },
5388c2ecf20Sopenharmony_ci	{ STV090x_GAINLLR_NF11,		0x1B },
5398c2ecf20Sopenharmony_ci	{ STV090x_GAINLLR_NF12,		0x20 },
5408c2ecf20Sopenharmony_ci	{ STV090x_GAINLLR_NF13,		0x20 },
5418c2ecf20Sopenharmony_ci	{ STV090x_GAINLLR_NF14,		0x20 },
5428c2ecf20Sopenharmony_ci	{ STV090x_GAINLLR_NF15,		0x20 },
5438c2ecf20Sopenharmony_ci	{ STV090x_GAINLLR_NF16,		0x20 },
5448c2ecf20Sopenharmony_ci	{ STV090x_GAINLLR_NF17,		0x21 },
5458c2ecf20Sopenharmony_ci};
5468c2ecf20Sopenharmony_ci
5478c2ecf20Sopenharmony_cistatic struct stv090x_reg stv0903_cut20_val[] = {
5488c2ecf20Sopenharmony_ci	{ STV090x_P1_DMDCFG3,		0xe8 },
5498c2ecf20Sopenharmony_ci	{ STV090x_P1_DMDCFG4,		0x10 },
5508c2ecf20Sopenharmony_ci	{ STV090x_P1_CARFREQ,		0x38 },
5518c2ecf20Sopenharmony_ci	{ STV090x_P1_CARHDR,		0x20 },
5528c2ecf20Sopenharmony_ci	{ STV090x_P1_KREFTMG,		0x5a },
5538c2ecf20Sopenharmony_ci	{ STV090x_P1_SMAPCOEF7,		0x06 },
5548c2ecf20Sopenharmony_ci	{ STV090x_P1_SMAPCOEF6,		0x00 },
5558c2ecf20Sopenharmony_ci	{ STV090x_P1_SMAPCOEF5,		0x04 },
5568c2ecf20Sopenharmony_ci	{ STV090x_P1_NOSCFG,		0x0c },
5578c2ecf20Sopenharmony_ci	{ STV090x_GAINLLR_NF4,		0x21 },
5588c2ecf20Sopenharmony_ci	{ STV090x_GAINLLR_NF5,		0x21 },
5598c2ecf20Sopenharmony_ci	{ STV090x_GAINLLR_NF6,		0x20 },
5608c2ecf20Sopenharmony_ci	{ STV090x_GAINLLR_NF7,		0x1F },
5618c2ecf20Sopenharmony_ci	{ STV090x_GAINLLR_NF8,		0x1E },
5628c2ecf20Sopenharmony_ci	{ STV090x_GAINLLR_NF9,		0x1E },
5638c2ecf20Sopenharmony_ci	{ STV090x_GAINLLR_NF10,		0x1D },
5648c2ecf20Sopenharmony_ci	{ STV090x_GAINLLR_NF11,		0x1B },
5658c2ecf20Sopenharmony_ci	{ STV090x_GAINLLR_NF12,		0x20 },
5668c2ecf20Sopenharmony_ci	{ STV090x_GAINLLR_NF13,		0x20 },
5678c2ecf20Sopenharmony_ci	{ STV090x_GAINLLR_NF14,		0x20 },
5688c2ecf20Sopenharmony_ci	{ STV090x_GAINLLR_NF15,		0x20 },
5698c2ecf20Sopenharmony_ci	{ STV090x_GAINLLR_NF16,		0x20 },
5708c2ecf20Sopenharmony_ci	{ STV090x_GAINLLR_NF17,		0x21 }
5718c2ecf20Sopenharmony_ci};
5728c2ecf20Sopenharmony_ci
5738c2ecf20Sopenharmony_ci/* Cut 2.0 Long Frame Tracking CR loop */
5748c2ecf20Sopenharmony_cistatic struct stv090x_long_frame_crloop stv090x_s2_crl_cut20[] = {
5758c2ecf20Sopenharmony_ci	/* MODCOD  2MPon 2MPoff 5MPon 5MPoff 10MPon 10MPoff 20MPon 20MPoff 30MPon 30MPoff */
5768c2ecf20Sopenharmony_ci	{ STV090x_QPSK_12,  0x1f, 0x3f, 0x1e, 0x3f, 0x3d, 0x1f, 0x3d, 0x3e, 0x3d, 0x1e },
5778c2ecf20Sopenharmony_ci	{ STV090x_QPSK_35,  0x2f, 0x3f, 0x2e, 0x2f, 0x3d, 0x0f, 0x0e, 0x2e, 0x3d, 0x0e },
5788c2ecf20Sopenharmony_ci	{ STV090x_QPSK_23,  0x2f, 0x3f, 0x2e, 0x2f, 0x0e, 0x0f, 0x0e, 0x1e, 0x3d, 0x3d },
5798c2ecf20Sopenharmony_ci	{ STV090x_QPSK_34,  0x3f, 0x3f, 0x3e, 0x1f, 0x0e, 0x3e, 0x0e, 0x1e, 0x3d, 0x3d },
5808c2ecf20Sopenharmony_ci	{ STV090x_QPSK_45,  0x3f, 0x3f, 0x3e, 0x1f, 0x0e, 0x3e, 0x0e, 0x1e, 0x3d, 0x3d },
5818c2ecf20Sopenharmony_ci	{ STV090x_QPSK_56,  0x3f, 0x3f, 0x3e, 0x1f, 0x0e, 0x3e, 0x0e, 0x1e, 0x3d, 0x3d },
5828c2ecf20Sopenharmony_ci	{ STV090x_QPSK_89,  0x3f, 0x3f, 0x3e, 0x1f, 0x1e, 0x3e, 0x0e, 0x1e, 0x3d, 0x3d },
5838c2ecf20Sopenharmony_ci	{ STV090x_QPSK_910, 0x3f, 0x3f, 0x3e, 0x1f, 0x1e, 0x3e, 0x0e, 0x1e, 0x3d, 0x3d },
5848c2ecf20Sopenharmony_ci	{ STV090x_8PSK_35,  0x3c, 0x3e, 0x1c, 0x2e, 0x0c, 0x1e, 0x2b, 0x2d, 0x1b, 0x1d },
5858c2ecf20Sopenharmony_ci	{ STV090x_8PSK_23,  0x1d, 0x3e, 0x3c, 0x2e, 0x2c, 0x1e, 0x0c, 0x2d, 0x2b, 0x1d },
5868c2ecf20Sopenharmony_ci	{ STV090x_8PSK_34,  0x0e, 0x3e, 0x3d, 0x2e, 0x0d, 0x1e, 0x2c, 0x2d, 0x0c, 0x1d },
5878c2ecf20Sopenharmony_ci	{ STV090x_8PSK_56,  0x2e, 0x3e, 0x1e, 0x2e, 0x2d, 0x1e, 0x3c, 0x2d, 0x2c, 0x1d },
5888c2ecf20Sopenharmony_ci	{ STV090x_8PSK_89,  0x3e, 0x3e, 0x1e, 0x2e, 0x3d, 0x1e, 0x0d, 0x2d, 0x3c, 0x1d },
5898c2ecf20Sopenharmony_ci	{ STV090x_8PSK_910, 0x3e, 0x3e, 0x1e, 0x2e, 0x3d, 0x1e, 0x1d, 0x2d, 0x0d, 0x1d }
5908c2ecf20Sopenharmony_ci};
5918c2ecf20Sopenharmony_ci
5928c2ecf20Sopenharmony_ci/* Cut 3.0 Long Frame Tracking CR loop */
5938c2ecf20Sopenharmony_cistatic	struct stv090x_long_frame_crloop stv090x_s2_crl_cut30[] = {
5948c2ecf20Sopenharmony_ci	/* MODCOD  2MPon 2MPoff 5MPon 5MPoff 10MPon 10MPoff 20MPon 20MPoff 30MPon 30MPoff */
5958c2ecf20Sopenharmony_ci	{ STV090x_QPSK_12,  0x3c, 0x2c, 0x0c, 0x2c, 0x1b, 0x2c, 0x1b, 0x1c, 0x0b, 0x3b },
5968c2ecf20Sopenharmony_ci	{ STV090x_QPSK_35,  0x0d, 0x0d, 0x0c, 0x0d, 0x1b, 0x3c, 0x1b, 0x1c, 0x0b, 0x3b },
5978c2ecf20Sopenharmony_ci	{ STV090x_QPSK_23,  0x1d, 0x0d, 0x0c, 0x1d, 0x2b, 0x3c, 0x1b, 0x1c, 0x0b, 0x3b },
5988c2ecf20Sopenharmony_ci	{ STV090x_QPSK_34,  0x1d, 0x1d, 0x0c, 0x1d, 0x2b, 0x3c, 0x1b, 0x1c, 0x0b, 0x3b },
5998c2ecf20Sopenharmony_ci	{ STV090x_QPSK_45,  0x2d, 0x1d, 0x1c, 0x1d, 0x2b, 0x3c, 0x2b, 0x0c, 0x1b, 0x3b },
6008c2ecf20Sopenharmony_ci	{ STV090x_QPSK_56,  0x2d, 0x1d, 0x1c, 0x1d, 0x2b, 0x3c, 0x2b, 0x0c, 0x1b, 0x3b },
6018c2ecf20Sopenharmony_ci	{ STV090x_QPSK_89,  0x3d, 0x2d, 0x1c, 0x1d, 0x3b, 0x3c, 0x2b, 0x0c, 0x1b, 0x3b },
6028c2ecf20Sopenharmony_ci	{ STV090x_QPSK_910, 0x3d, 0x2d, 0x1c, 0x1d, 0x3b, 0x3c, 0x2b, 0x0c, 0x1b, 0x3b },
6038c2ecf20Sopenharmony_ci	{ STV090x_8PSK_35,  0x39, 0x29, 0x39, 0x19, 0x19, 0x19, 0x19, 0x19, 0x09, 0x19 },
6048c2ecf20Sopenharmony_ci	{ STV090x_8PSK_23,  0x2a, 0x39, 0x1a, 0x0a, 0x39, 0x0a, 0x29, 0x39, 0x29, 0x0a },
6058c2ecf20Sopenharmony_ci	{ STV090x_8PSK_34,  0x2b, 0x3a, 0x1b, 0x1b, 0x3a, 0x1b, 0x1a, 0x0b, 0x1a, 0x3a },
6068c2ecf20Sopenharmony_ci	{ STV090x_8PSK_56,  0x0c, 0x1b, 0x3b, 0x3b, 0x1b, 0x3b, 0x3a, 0x3b, 0x3a, 0x1b },
6078c2ecf20Sopenharmony_ci	{ STV090x_8PSK_89,  0x0d, 0x3c, 0x2c, 0x2c, 0x2b, 0x0c, 0x0b, 0x3b, 0x0b, 0x1b },
6088c2ecf20Sopenharmony_ci	{ STV090x_8PSK_910, 0x0d, 0x0d, 0x2c, 0x3c, 0x3b, 0x1c, 0x0b, 0x3b, 0x0b, 0x1b }
6098c2ecf20Sopenharmony_ci};
6108c2ecf20Sopenharmony_ci
6118c2ecf20Sopenharmony_ci/* Cut 2.0 Long Frame Tracking CR Loop */
6128c2ecf20Sopenharmony_cistatic struct stv090x_long_frame_crloop stv090x_s2_apsk_crl_cut20[] = {
6138c2ecf20Sopenharmony_ci	/* MODCOD  2MPon 2MPoff 5MPon 5MPoff 10MPon 10MPoff 20MPon 20MPoff 30MPon 30MPoff */
6148c2ecf20Sopenharmony_ci	{ STV090x_16APSK_23,  0x0c, 0x0c, 0x0c, 0x0c, 0x1d, 0x0c, 0x3c, 0x0c, 0x2c, 0x0c },
6158c2ecf20Sopenharmony_ci	{ STV090x_16APSK_34,  0x0c, 0x0c, 0x0c, 0x0c, 0x0e, 0x0c, 0x2d, 0x0c, 0x1d, 0x0c },
6168c2ecf20Sopenharmony_ci	{ STV090x_16APSK_45,  0x0c, 0x0c, 0x0c, 0x0c, 0x1e, 0x0c, 0x3d, 0x0c, 0x2d, 0x0c },
6178c2ecf20Sopenharmony_ci	{ STV090x_16APSK_56,  0x0c, 0x0c, 0x0c, 0x0c, 0x1e, 0x0c, 0x3d, 0x0c, 0x2d, 0x0c },
6188c2ecf20Sopenharmony_ci	{ STV090x_16APSK_89,  0x0c, 0x0c, 0x0c, 0x0c, 0x2e, 0x0c, 0x0e, 0x0c, 0x3d, 0x0c },
6198c2ecf20Sopenharmony_ci	{ STV090x_16APSK_910, 0x0c, 0x0c, 0x0c, 0x0c, 0x2e, 0x0c, 0x0e, 0x0c, 0x3d, 0x0c },
6208c2ecf20Sopenharmony_ci	{ STV090x_32APSK_34,  0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c },
6218c2ecf20Sopenharmony_ci	{ STV090x_32APSK_45,  0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c },
6228c2ecf20Sopenharmony_ci	{ STV090x_32APSK_56,  0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c },
6238c2ecf20Sopenharmony_ci	{ STV090x_32APSK_89,  0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c },
6248c2ecf20Sopenharmony_ci	{ STV090x_32APSK_910, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c }
6258c2ecf20Sopenharmony_ci};
6268c2ecf20Sopenharmony_ci
6278c2ecf20Sopenharmony_ci/* Cut 3.0 Long Frame Tracking CR Loop */
6288c2ecf20Sopenharmony_cistatic struct stv090x_long_frame_crloop	stv090x_s2_apsk_crl_cut30[] = {
6298c2ecf20Sopenharmony_ci	/* MODCOD  2MPon 2MPoff 5MPon 5MPoff 10MPon 10MPoff 20MPon 20MPoff 30MPon 30MPoff */
6308c2ecf20Sopenharmony_ci	{ STV090x_16APSK_23,  0x0a, 0x0a, 0x0a, 0x0a, 0x1a, 0x0a, 0x3a, 0x0a, 0x2a, 0x0a },
6318c2ecf20Sopenharmony_ci	{ STV090x_16APSK_34,  0x0a, 0x0a, 0x0a, 0x0a, 0x0b, 0x0a, 0x3b, 0x0a, 0x1b, 0x0a },
6328c2ecf20Sopenharmony_ci	{ STV090x_16APSK_45,  0x0a, 0x0a, 0x0a, 0x0a, 0x1b, 0x0a, 0x3b, 0x0a, 0x2b, 0x0a },
6338c2ecf20Sopenharmony_ci	{ STV090x_16APSK_56,  0x0a, 0x0a, 0x0a, 0x0a, 0x1b, 0x0a, 0x3b, 0x0a, 0x2b, 0x0a },
6348c2ecf20Sopenharmony_ci	{ STV090x_16APSK_89,  0x0a, 0x0a, 0x0a, 0x0a, 0x2b, 0x0a, 0x0c, 0x0a, 0x3b, 0x0a },
6358c2ecf20Sopenharmony_ci	{ STV090x_16APSK_910, 0x0a, 0x0a, 0x0a, 0x0a, 0x2b, 0x0a, 0x0c, 0x0a, 0x3b, 0x0a },
6368c2ecf20Sopenharmony_ci	{ STV090x_32APSK_34,  0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a },
6378c2ecf20Sopenharmony_ci	{ STV090x_32APSK_45,  0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a },
6388c2ecf20Sopenharmony_ci	{ STV090x_32APSK_56,  0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a },
6398c2ecf20Sopenharmony_ci	{ STV090x_32APSK_89,  0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a },
6408c2ecf20Sopenharmony_ci	{ STV090x_32APSK_910, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a }
6418c2ecf20Sopenharmony_ci};
6428c2ecf20Sopenharmony_ci
6438c2ecf20Sopenharmony_cistatic struct stv090x_long_frame_crloop stv090x_s2_lowqpsk_crl_cut20[] = {
6448c2ecf20Sopenharmony_ci	/* MODCOD  2MPon 2MPoff 5MPon 5MPoff 10MPon 10MPoff 20MPon 20MPoff 30MPon 30MPoff */
6458c2ecf20Sopenharmony_ci	{ STV090x_QPSK_14,  0x0f, 0x3f, 0x0e, 0x3f, 0x2d, 0x2f, 0x2d, 0x1f, 0x3d, 0x3e },
6468c2ecf20Sopenharmony_ci	{ STV090x_QPSK_13,  0x0f, 0x3f, 0x0e, 0x3f, 0x2d, 0x2f, 0x3d, 0x0f, 0x3d, 0x2e },
6478c2ecf20Sopenharmony_ci	{ STV090x_QPSK_25,  0x1f, 0x3f, 0x1e, 0x3f, 0x3d, 0x1f, 0x3d, 0x3e, 0x3d, 0x2e }
6488c2ecf20Sopenharmony_ci};
6498c2ecf20Sopenharmony_ci
6508c2ecf20Sopenharmony_cistatic struct stv090x_long_frame_crloop	stv090x_s2_lowqpsk_crl_cut30[] = {
6518c2ecf20Sopenharmony_ci	/* MODCOD  2MPon 2MPoff 5MPon 5MPoff 10MPon 10MPoff 20MPon 20MPoff 30MPon 30MPoff */
6528c2ecf20Sopenharmony_ci	{ STV090x_QPSK_14,  0x0c, 0x3c, 0x0b, 0x3c, 0x2a, 0x2c, 0x2a, 0x1c, 0x3a, 0x3b },
6538c2ecf20Sopenharmony_ci	{ STV090x_QPSK_13,  0x0c, 0x3c, 0x0b, 0x3c, 0x2a, 0x2c, 0x3a, 0x0c, 0x3a, 0x2b },
6548c2ecf20Sopenharmony_ci	{ STV090x_QPSK_25,  0x1c, 0x3c, 0x1b, 0x3c, 0x3a, 0x1c, 0x3a, 0x3b, 0x3a, 0x2b }
6558c2ecf20Sopenharmony_ci};
6568c2ecf20Sopenharmony_ci
6578c2ecf20Sopenharmony_ci/* Cut 2.0 Short Frame Tracking CR Loop */
6588c2ecf20Sopenharmony_cistatic struct stv090x_short_frame_crloop stv090x_s2_short_crl_cut20[] = {
6598c2ecf20Sopenharmony_ci	/* MODCOD	  2M    5M    10M   20M   30M */
6608c2ecf20Sopenharmony_ci	{ STV090x_QPSK,   0x2f, 0x2e, 0x0e, 0x0e, 0x3d },
6618c2ecf20Sopenharmony_ci	{ STV090x_8PSK,   0x3e, 0x0e, 0x2d, 0x0d, 0x3c },
6628c2ecf20Sopenharmony_ci	{ STV090x_16APSK, 0x1e, 0x1e, 0x1e, 0x3d, 0x2d },
6638c2ecf20Sopenharmony_ci	{ STV090x_32APSK, 0x1e, 0x1e, 0x1e, 0x3d, 0x2d }
6648c2ecf20Sopenharmony_ci};
6658c2ecf20Sopenharmony_ci
6668c2ecf20Sopenharmony_ci/* Cut 3.0 Short Frame Tracking CR Loop */
6678c2ecf20Sopenharmony_cistatic struct stv090x_short_frame_crloop stv090x_s2_short_crl_cut30[] = {
6688c2ecf20Sopenharmony_ci	/* MODCOD	  2M	5M    10M   20M	  30M */
6698c2ecf20Sopenharmony_ci	{ STV090x_QPSK,   0x2C, 0x2B, 0x0B, 0x0B, 0x3A },
6708c2ecf20Sopenharmony_ci	{ STV090x_8PSK,   0x3B, 0x0B, 0x2A, 0x0A, 0x39 },
6718c2ecf20Sopenharmony_ci	{ STV090x_16APSK, 0x1B, 0x1B, 0x1B, 0x3A, 0x2A },
6728c2ecf20Sopenharmony_ci	{ STV090x_32APSK, 0x1B, 0x1B, 0x1B, 0x3A, 0x2A }
6738c2ecf20Sopenharmony_ci};
6748c2ecf20Sopenharmony_ci
6758c2ecf20Sopenharmony_cistatic inline s32 comp2(s32 __x, s32 __width)
6768c2ecf20Sopenharmony_ci{
6778c2ecf20Sopenharmony_ci	if (__width == 32)
6788c2ecf20Sopenharmony_ci		return __x;
6798c2ecf20Sopenharmony_ci	else
6808c2ecf20Sopenharmony_ci		return (__x >= (1 << (__width - 1))) ? (__x - (1 << __width)) : __x;
6818c2ecf20Sopenharmony_ci}
6828c2ecf20Sopenharmony_ci
6838c2ecf20Sopenharmony_cistatic int stv090x_read_reg(struct stv090x_state *state, unsigned int reg)
6848c2ecf20Sopenharmony_ci{
6858c2ecf20Sopenharmony_ci	const struct stv090x_config *config = state->config;
6868c2ecf20Sopenharmony_ci	int ret;
6878c2ecf20Sopenharmony_ci
6888c2ecf20Sopenharmony_ci	u8 b0[] = { reg >> 8, reg & 0xff };
6898c2ecf20Sopenharmony_ci	u8 buf;
6908c2ecf20Sopenharmony_ci
6918c2ecf20Sopenharmony_ci	struct i2c_msg msg[] = {
6928c2ecf20Sopenharmony_ci		{ .addr	= config->address, .flags	= 0,		.buf = b0,   .len = 2 },
6938c2ecf20Sopenharmony_ci		{ .addr	= config->address, .flags	= I2C_M_RD,	.buf = &buf, .len = 1 }
6948c2ecf20Sopenharmony_ci	};
6958c2ecf20Sopenharmony_ci
6968c2ecf20Sopenharmony_ci	ret = i2c_transfer(state->i2c, msg, 2);
6978c2ecf20Sopenharmony_ci	if (ret != 2) {
6988c2ecf20Sopenharmony_ci		if (ret != -ERESTARTSYS)
6998c2ecf20Sopenharmony_ci			dprintk(FE_ERROR, 1,
7008c2ecf20Sopenharmony_ci				"Read error, Reg=[0x%02x], Status=%d",
7018c2ecf20Sopenharmony_ci				reg, ret);
7028c2ecf20Sopenharmony_ci
7038c2ecf20Sopenharmony_ci		return ret < 0 ? ret : -EREMOTEIO;
7048c2ecf20Sopenharmony_ci	}
7058c2ecf20Sopenharmony_ci	if (unlikely(*state->verbose >= FE_DEBUGREG))
7068c2ecf20Sopenharmony_ci		dprintk(FE_ERROR, 1, "Reg=[0x%02x], data=%02x",
7078c2ecf20Sopenharmony_ci			reg, buf);
7088c2ecf20Sopenharmony_ci
7098c2ecf20Sopenharmony_ci	return (unsigned int) buf;
7108c2ecf20Sopenharmony_ci}
7118c2ecf20Sopenharmony_ci
7128c2ecf20Sopenharmony_cistatic int stv090x_write_regs(struct stv090x_state *state, unsigned int reg, u8 *data, u32 count)
7138c2ecf20Sopenharmony_ci{
7148c2ecf20Sopenharmony_ci	const struct stv090x_config *config = state->config;
7158c2ecf20Sopenharmony_ci	int ret;
7168c2ecf20Sopenharmony_ci	u8 buf[MAX_XFER_SIZE];
7178c2ecf20Sopenharmony_ci	struct i2c_msg i2c_msg = { .addr = config->address, .flags = 0, .buf = buf, .len = 2 + count };
7188c2ecf20Sopenharmony_ci
7198c2ecf20Sopenharmony_ci	if (2 + count > sizeof(buf)) {
7208c2ecf20Sopenharmony_ci		printk(KERN_WARNING
7218c2ecf20Sopenharmony_ci		       "%s: i2c wr reg=%04x: len=%d is too big!\n",
7228c2ecf20Sopenharmony_ci		       KBUILD_MODNAME, reg, count);
7238c2ecf20Sopenharmony_ci		return -EINVAL;
7248c2ecf20Sopenharmony_ci	}
7258c2ecf20Sopenharmony_ci
7268c2ecf20Sopenharmony_ci	buf[0] = reg >> 8;
7278c2ecf20Sopenharmony_ci	buf[1] = reg & 0xff;
7288c2ecf20Sopenharmony_ci	memcpy(&buf[2], data, count);
7298c2ecf20Sopenharmony_ci
7308c2ecf20Sopenharmony_ci	dprintk(FE_DEBUGREG, 1, "%s [0x%04x]: %*ph",
7318c2ecf20Sopenharmony_ci		__func__, reg, count, data);
7328c2ecf20Sopenharmony_ci
7338c2ecf20Sopenharmony_ci	ret = i2c_transfer(state->i2c, &i2c_msg, 1);
7348c2ecf20Sopenharmony_ci	if (ret != 1) {
7358c2ecf20Sopenharmony_ci		if (ret != -ERESTARTSYS)
7368c2ecf20Sopenharmony_ci			dprintk(FE_ERROR, 1, "Reg=[0x%04x], Data=[0x%02x ...], Count=%u, Status=%d",
7378c2ecf20Sopenharmony_ci				reg, data[0], count, ret);
7388c2ecf20Sopenharmony_ci		return ret < 0 ? ret : -EREMOTEIO;
7398c2ecf20Sopenharmony_ci	}
7408c2ecf20Sopenharmony_ci
7418c2ecf20Sopenharmony_ci	return 0;
7428c2ecf20Sopenharmony_ci}
7438c2ecf20Sopenharmony_ci
7448c2ecf20Sopenharmony_cistatic int stv090x_write_reg(struct stv090x_state *state, unsigned int reg, u8 data)
7458c2ecf20Sopenharmony_ci{
7468c2ecf20Sopenharmony_ci	u8 tmp = data; /* see gcc.gnu.org/bugzilla/show_bug.cgi?id=81715 */
7478c2ecf20Sopenharmony_ci
7488c2ecf20Sopenharmony_ci	return stv090x_write_regs(state, reg, &tmp, 1);
7498c2ecf20Sopenharmony_ci}
7508c2ecf20Sopenharmony_ci
7518c2ecf20Sopenharmony_cistatic int stv090x_i2c_gate_ctrl(struct stv090x_state *state, int enable)
7528c2ecf20Sopenharmony_ci{
7538c2ecf20Sopenharmony_ci	u32 reg;
7548c2ecf20Sopenharmony_ci
7558c2ecf20Sopenharmony_ci	/*
7568c2ecf20Sopenharmony_ci	 * NOTE! A lock is used as a FSM to control the state in which
7578c2ecf20Sopenharmony_ci	 * access is serialized between two tuners on the same demod.
7588c2ecf20Sopenharmony_ci	 * This has nothing to do with a lock to protect a critical section
7598c2ecf20Sopenharmony_ci	 * which may in some other cases be confused with protecting I/O
7608c2ecf20Sopenharmony_ci	 * access to the demodulator gate.
7618c2ecf20Sopenharmony_ci	 * In case of any error, the lock is unlocked and exit within the
7628c2ecf20Sopenharmony_ci	 * relevant operations themselves.
7638c2ecf20Sopenharmony_ci	 */
7648c2ecf20Sopenharmony_ci	if (enable) {
7658c2ecf20Sopenharmony_ci		if (state->config->tuner_i2c_lock)
7668c2ecf20Sopenharmony_ci			state->config->tuner_i2c_lock(&state->frontend, 1);
7678c2ecf20Sopenharmony_ci		else
7688c2ecf20Sopenharmony_ci			mutex_lock(&state->internal->tuner_lock);
7698c2ecf20Sopenharmony_ci	}
7708c2ecf20Sopenharmony_ci
7718c2ecf20Sopenharmony_ci	reg = STV090x_READ_DEMOD(state, I2CRPT);
7728c2ecf20Sopenharmony_ci	if (enable) {
7738c2ecf20Sopenharmony_ci		dprintk(FE_DEBUG, 1, "Enable Gate");
7748c2ecf20Sopenharmony_ci		STV090x_SETFIELD_Px(reg, I2CT_ON_FIELD, 1);
7758c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, I2CRPT, reg) < 0)
7768c2ecf20Sopenharmony_ci			goto err;
7778c2ecf20Sopenharmony_ci
7788c2ecf20Sopenharmony_ci	} else {
7798c2ecf20Sopenharmony_ci		dprintk(FE_DEBUG, 1, "Disable Gate");
7808c2ecf20Sopenharmony_ci		STV090x_SETFIELD_Px(reg, I2CT_ON_FIELD, 0);
7818c2ecf20Sopenharmony_ci		if ((STV090x_WRITE_DEMOD(state, I2CRPT, reg)) < 0)
7828c2ecf20Sopenharmony_ci			goto err;
7838c2ecf20Sopenharmony_ci	}
7848c2ecf20Sopenharmony_ci
7858c2ecf20Sopenharmony_ci	if (!enable) {
7868c2ecf20Sopenharmony_ci		if (state->config->tuner_i2c_lock)
7878c2ecf20Sopenharmony_ci			state->config->tuner_i2c_lock(&state->frontend, 0);
7888c2ecf20Sopenharmony_ci		else
7898c2ecf20Sopenharmony_ci			mutex_unlock(&state->internal->tuner_lock);
7908c2ecf20Sopenharmony_ci	}
7918c2ecf20Sopenharmony_ci
7928c2ecf20Sopenharmony_ci	return 0;
7938c2ecf20Sopenharmony_cierr:
7948c2ecf20Sopenharmony_ci	dprintk(FE_ERROR, 1, "I/O error");
7958c2ecf20Sopenharmony_ci	if (state->config->tuner_i2c_lock)
7968c2ecf20Sopenharmony_ci		state->config->tuner_i2c_lock(&state->frontend, 0);
7978c2ecf20Sopenharmony_ci	else
7988c2ecf20Sopenharmony_ci		mutex_unlock(&state->internal->tuner_lock);
7998c2ecf20Sopenharmony_ci	return -1;
8008c2ecf20Sopenharmony_ci}
8018c2ecf20Sopenharmony_ci
8028c2ecf20Sopenharmony_cistatic void stv090x_get_lock_tmg(struct stv090x_state *state)
8038c2ecf20Sopenharmony_ci{
8048c2ecf20Sopenharmony_ci	switch (state->algo) {
8058c2ecf20Sopenharmony_ci	case STV090x_BLIND_SEARCH:
8068c2ecf20Sopenharmony_ci		dprintk(FE_DEBUG, 1, "Blind Search");
8078c2ecf20Sopenharmony_ci		if (state->srate <= 1500000) {  /*10Msps< SR <=15Msps*/
8088c2ecf20Sopenharmony_ci			state->DemodTimeout = 1500;
8098c2ecf20Sopenharmony_ci			state->FecTimeout = 400;
8108c2ecf20Sopenharmony_ci		} else if (state->srate <= 5000000) {  /*10Msps< SR <=15Msps*/
8118c2ecf20Sopenharmony_ci			state->DemodTimeout = 1000;
8128c2ecf20Sopenharmony_ci			state->FecTimeout = 300;
8138c2ecf20Sopenharmony_ci		} else {  /*SR >20Msps*/
8148c2ecf20Sopenharmony_ci			state->DemodTimeout = 700;
8158c2ecf20Sopenharmony_ci			state->FecTimeout = 100;
8168c2ecf20Sopenharmony_ci		}
8178c2ecf20Sopenharmony_ci		break;
8188c2ecf20Sopenharmony_ci
8198c2ecf20Sopenharmony_ci	case STV090x_COLD_SEARCH:
8208c2ecf20Sopenharmony_ci	case STV090x_WARM_SEARCH:
8218c2ecf20Sopenharmony_ci	default:
8228c2ecf20Sopenharmony_ci		dprintk(FE_DEBUG, 1, "Normal Search");
8238c2ecf20Sopenharmony_ci		if (state->srate <= 1000000) {  /*SR <=1Msps*/
8248c2ecf20Sopenharmony_ci			state->DemodTimeout = 4500;
8258c2ecf20Sopenharmony_ci			state->FecTimeout = 1700;
8268c2ecf20Sopenharmony_ci		} else if (state->srate <= 2000000) { /*1Msps < SR <= 2Msps */
8278c2ecf20Sopenharmony_ci			state->DemodTimeout = 2500;
8288c2ecf20Sopenharmony_ci			state->FecTimeout = 1100;
8298c2ecf20Sopenharmony_ci		} else if (state->srate <= 5000000) { /*2Msps < SR <= 5Msps */
8308c2ecf20Sopenharmony_ci			state->DemodTimeout = 1000;
8318c2ecf20Sopenharmony_ci			state->FecTimeout = 550;
8328c2ecf20Sopenharmony_ci		} else if (state->srate <= 10000000) { /*5Msps < SR <= 10Msps */
8338c2ecf20Sopenharmony_ci			state->DemodTimeout = 700;
8348c2ecf20Sopenharmony_ci			state->FecTimeout = 250;
8358c2ecf20Sopenharmony_ci		} else if (state->srate <= 20000000) { /*10Msps < SR <= 20Msps */
8368c2ecf20Sopenharmony_ci			state->DemodTimeout = 400;
8378c2ecf20Sopenharmony_ci			state->FecTimeout = 130;
8388c2ecf20Sopenharmony_ci		} else {   /*SR >20Msps*/
8398c2ecf20Sopenharmony_ci			state->DemodTimeout = 300;
8408c2ecf20Sopenharmony_ci			state->FecTimeout = 100;
8418c2ecf20Sopenharmony_ci		}
8428c2ecf20Sopenharmony_ci		break;
8438c2ecf20Sopenharmony_ci	}
8448c2ecf20Sopenharmony_ci
8458c2ecf20Sopenharmony_ci	if (state->algo == STV090x_WARM_SEARCH)
8468c2ecf20Sopenharmony_ci		state->DemodTimeout /= 2;
8478c2ecf20Sopenharmony_ci}
8488c2ecf20Sopenharmony_ci
8498c2ecf20Sopenharmony_cistatic int stv090x_set_srate(struct stv090x_state *state, u32 srate)
8508c2ecf20Sopenharmony_ci{
8518c2ecf20Sopenharmony_ci	u32 sym;
8528c2ecf20Sopenharmony_ci
8538c2ecf20Sopenharmony_ci	if (srate > 60000000) {
8548c2ecf20Sopenharmony_ci		sym  = (srate << 4); /* SR * 2^16 / master_clk */
8558c2ecf20Sopenharmony_ci		sym /= (state->internal->mclk >> 12);
8568c2ecf20Sopenharmony_ci	} else if (srate > 6000000) {
8578c2ecf20Sopenharmony_ci		sym  = (srate << 6);
8588c2ecf20Sopenharmony_ci		sym /= (state->internal->mclk >> 10);
8598c2ecf20Sopenharmony_ci	} else {
8608c2ecf20Sopenharmony_ci		sym  = (srate << 9);
8618c2ecf20Sopenharmony_ci		sym /= (state->internal->mclk >> 7);
8628c2ecf20Sopenharmony_ci	}
8638c2ecf20Sopenharmony_ci
8648c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, SFRINIT1, (sym >> 8) & 0x7f) < 0) /* MSB */
8658c2ecf20Sopenharmony_ci		goto err;
8668c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, SFRINIT0, (sym & 0xff)) < 0) /* LSB */
8678c2ecf20Sopenharmony_ci		goto err;
8688c2ecf20Sopenharmony_ci
8698c2ecf20Sopenharmony_ci	return 0;
8708c2ecf20Sopenharmony_cierr:
8718c2ecf20Sopenharmony_ci	dprintk(FE_ERROR, 1, "I/O error");
8728c2ecf20Sopenharmony_ci	return -1;
8738c2ecf20Sopenharmony_ci}
8748c2ecf20Sopenharmony_ci
8758c2ecf20Sopenharmony_cistatic int stv090x_set_max_srate(struct stv090x_state *state, u32 clk, u32 srate)
8768c2ecf20Sopenharmony_ci{
8778c2ecf20Sopenharmony_ci	u32 sym;
8788c2ecf20Sopenharmony_ci
8798c2ecf20Sopenharmony_ci	srate = 105 * (srate / 100);
8808c2ecf20Sopenharmony_ci	if (srate > 60000000) {
8818c2ecf20Sopenharmony_ci		sym  = (srate << 4); /* SR * 2^16 / master_clk */
8828c2ecf20Sopenharmony_ci		sym /= (state->internal->mclk >> 12);
8838c2ecf20Sopenharmony_ci	} else if (srate > 6000000) {
8848c2ecf20Sopenharmony_ci		sym  = (srate << 6);
8858c2ecf20Sopenharmony_ci		sym /= (state->internal->mclk >> 10);
8868c2ecf20Sopenharmony_ci	} else {
8878c2ecf20Sopenharmony_ci		sym  = (srate << 9);
8888c2ecf20Sopenharmony_ci		sym /= (state->internal->mclk >> 7);
8898c2ecf20Sopenharmony_ci	}
8908c2ecf20Sopenharmony_ci
8918c2ecf20Sopenharmony_ci	if (sym < 0x7fff) {
8928c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, SFRUP1, (sym >> 8) & 0x7f) < 0) /* MSB */
8938c2ecf20Sopenharmony_ci			goto err;
8948c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, SFRUP0, sym & 0xff) < 0) /* LSB */
8958c2ecf20Sopenharmony_ci			goto err;
8968c2ecf20Sopenharmony_ci	} else {
8978c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, SFRUP1, 0x7f) < 0) /* MSB */
8988c2ecf20Sopenharmony_ci			goto err;
8998c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, SFRUP0, 0xff) < 0) /* LSB */
9008c2ecf20Sopenharmony_ci			goto err;
9018c2ecf20Sopenharmony_ci	}
9028c2ecf20Sopenharmony_ci
9038c2ecf20Sopenharmony_ci	return 0;
9048c2ecf20Sopenharmony_cierr:
9058c2ecf20Sopenharmony_ci	dprintk(FE_ERROR, 1, "I/O error");
9068c2ecf20Sopenharmony_ci	return -1;
9078c2ecf20Sopenharmony_ci}
9088c2ecf20Sopenharmony_ci
9098c2ecf20Sopenharmony_cistatic int stv090x_set_min_srate(struct stv090x_state *state, u32 clk, u32 srate)
9108c2ecf20Sopenharmony_ci{
9118c2ecf20Sopenharmony_ci	u32 sym;
9128c2ecf20Sopenharmony_ci
9138c2ecf20Sopenharmony_ci	srate = 95 * (srate / 100);
9148c2ecf20Sopenharmony_ci	if (srate > 60000000) {
9158c2ecf20Sopenharmony_ci		sym  = (srate << 4); /* SR * 2^16 / master_clk */
9168c2ecf20Sopenharmony_ci		sym /= (state->internal->mclk >> 12);
9178c2ecf20Sopenharmony_ci	} else if (srate > 6000000) {
9188c2ecf20Sopenharmony_ci		sym  = (srate << 6);
9198c2ecf20Sopenharmony_ci		sym /= (state->internal->mclk >> 10);
9208c2ecf20Sopenharmony_ci	} else {
9218c2ecf20Sopenharmony_ci		sym  = (srate << 9);
9228c2ecf20Sopenharmony_ci		sym /= (state->internal->mclk >> 7);
9238c2ecf20Sopenharmony_ci	}
9248c2ecf20Sopenharmony_ci
9258c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, SFRLOW1, ((sym >> 8) & 0x7f)) < 0) /* MSB */
9268c2ecf20Sopenharmony_ci		goto err;
9278c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, SFRLOW0, (sym & 0xff)) < 0) /* LSB */
9288c2ecf20Sopenharmony_ci		goto err;
9298c2ecf20Sopenharmony_ci	return 0;
9308c2ecf20Sopenharmony_cierr:
9318c2ecf20Sopenharmony_ci	dprintk(FE_ERROR, 1, "I/O error");
9328c2ecf20Sopenharmony_ci	return -1;
9338c2ecf20Sopenharmony_ci}
9348c2ecf20Sopenharmony_ci
9358c2ecf20Sopenharmony_cistatic u32 stv090x_car_width(u32 srate, enum stv090x_rolloff rolloff)
9368c2ecf20Sopenharmony_ci{
9378c2ecf20Sopenharmony_ci	u32 ro;
9388c2ecf20Sopenharmony_ci
9398c2ecf20Sopenharmony_ci	switch (rolloff) {
9408c2ecf20Sopenharmony_ci	case STV090x_RO_20:
9418c2ecf20Sopenharmony_ci		ro = 20;
9428c2ecf20Sopenharmony_ci		break;
9438c2ecf20Sopenharmony_ci	case STV090x_RO_25:
9448c2ecf20Sopenharmony_ci		ro = 25;
9458c2ecf20Sopenharmony_ci		break;
9468c2ecf20Sopenharmony_ci	case STV090x_RO_35:
9478c2ecf20Sopenharmony_ci	default:
9488c2ecf20Sopenharmony_ci		ro = 35;
9498c2ecf20Sopenharmony_ci		break;
9508c2ecf20Sopenharmony_ci	}
9518c2ecf20Sopenharmony_ci
9528c2ecf20Sopenharmony_ci	return srate + (srate * ro) / 100;
9538c2ecf20Sopenharmony_ci}
9548c2ecf20Sopenharmony_ci
9558c2ecf20Sopenharmony_cistatic int stv090x_set_vit_thacq(struct stv090x_state *state)
9568c2ecf20Sopenharmony_ci{
9578c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, VTH12, 0x96) < 0)
9588c2ecf20Sopenharmony_ci		goto err;
9598c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, VTH23, 0x64) < 0)
9608c2ecf20Sopenharmony_ci		goto err;
9618c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, VTH34, 0x36) < 0)
9628c2ecf20Sopenharmony_ci		goto err;
9638c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, VTH56, 0x23) < 0)
9648c2ecf20Sopenharmony_ci		goto err;
9658c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, VTH67, 0x1e) < 0)
9668c2ecf20Sopenharmony_ci		goto err;
9678c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, VTH78, 0x19) < 0)
9688c2ecf20Sopenharmony_ci		goto err;
9698c2ecf20Sopenharmony_ci	return 0;
9708c2ecf20Sopenharmony_cierr:
9718c2ecf20Sopenharmony_ci	dprintk(FE_ERROR, 1, "I/O error");
9728c2ecf20Sopenharmony_ci	return -1;
9738c2ecf20Sopenharmony_ci}
9748c2ecf20Sopenharmony_ci
9758c2ecf20Sopenharmony_cistatic int stv090x_set_vit_thtracq(struct stv090x_state *state)
9768c2ecf20Sopenharmony_ci{
9778c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, VTH12, 0xd0) < 0)
9788c2ecf20Sopenharmony_ci		goto err;
9798c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, VTH23, 0x7d) < 0)
9808c2ecf20Sopenharmony_ci		goto err;
9818c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, VTH34, 0x53) < 0)
9828c2ecf20Sopenharmony_ci		goto err;
9838c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, VTH56, 0x2f) < 0)
9848c2ecf20Sopenharmony_ci		goto err;
9858c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, VTH67, 0x24) < 0)
9868c2ecf20Sopenharmony_ci		goto err;
9878c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, VTH78, 0x1f) < 0)
9888c2ecf20Sopenharmony_ci		goto err;
9898c2ecf20Sopenharmony_ci	return 0;
9908c2ecf20Sopenharmony_cierr:
9918c2ecf20Sopenharmony_ci	dprintk(FE_ERROR, 1, "I/O error");
9928c2ecf20Sopenharmony_ci	return -1;
9938c2ecf20Sopenharmony_ci}
9948c2ecf20Sopenharmony_ci
9958c2ecf20Sopenharmony_cistatic int stv090x_set_viterbi(struct stv090x_state *state)
9968c2ecf20Sopenharmony_ci{
9978c2ecf20Sopenharmony_ci	switch (state->search_mode) {
9988c2ecf20Sopenharmony_ci	case STV090x_SEARCH_AUTO:
9998c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, FECM, 0x10) < 0) /* DVB-S and DVB-S2 */
10008c2ecf20Sopenharmony_ci			goto err;
10018c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, PRVIT, 0x3f) < 0) /* all puncture rate */
10028c2ecf20Sopenharmony_ci			goto err;
10038c2ecf20Sopenharmony_ci		break;
10048c2ecf20Sopenharmony_ci	case STV090x_SEARCH_DVBS1:
10058c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, FECM, 0x00) < 0) /* disable DSS */
10068c2ecf20Sopenharmony_ci			goto err;
10078c2ecf20Sopenharmony_ci		switch (state->fec) {
10088c2ecf20Sopenharmony_ci		case STV090x_PR12:
10098c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, PRVIT, 0x01) < 0)
10108c2ecf20Sopenharmony_ci				goto err;
10118c2ecf20Sopenharmony_ci			break;
10128c2ecf20Sopenharmony_ci
10138c2ecf20Sopenharmony_ci		case STV090x_PR23:
10148c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, PRVIT, 0x02) < 0)
10158c2ecf20Sopenharmony_ci				goto err;
10168c2ecf20Sopenharmony_ci			break;
10178c2ecf20Sopenharmony_ci
10188c2ecf20Sopenharmony_ci		case STV090x_PR34:
10198c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, PRVIT, 0x04) < 0)
10208c2ecf20Sopenharmony_ci				goto err;
10218c2ecf20Sopenharmony_ci			break;
10228c2ecf20Sopenharmony_ci
10238c2ecf20Sopenharmony_ci		case STV090x_PR56:
10248c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, PRVIT, 0x08) < 0)
10258c2ecf20Sopenharmony_ci				goto err;
10268c2ecf20Sopenharmony_ci			break;
10278c2ecf20Sopenharmony_ci
10288c2ecf20Sopenharmony_ci		case STV090x_PR78:
10298c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, PRVIT, 0x20) < 0)
10308c2ecf20Sopenharmony_ci				goto err;
10318c2ecf20Sopenharmony_ci			break;
10328c2ecf20Sopenharmony_ci
10338c2ecf20Sopenharmony_ci		default:
10348c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, PRVIT, 0x2f) < 0) /* all */
10358c2ecf20Sopenharmony_ci				goto err;
10368c2ecf20Sopenharmony_ci			break;
10378c2ecf20Sopenharmony_ci		}
10388c2ecf20Sopenharmony_ci		break;
10398c2ecf20Sopenharmony_ci	case STV090x_SEARCH_DSS:
10408c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, FECM, 0x80) < 0)
10418c2ecf20Sopenharmony_ci			goto err;
10428c2ecf20Sopenharmony_ci		switch (state->fec) {
10438c2ecf20Sopenharmony_ci		case STV090x_PR12:
10448c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, PRVIT, 0x01) < 0)
10458c2ecf20Sopenharmony_ci				goto err;
10468c2ecf20Sopenharmony_ci			break;
10478c2ecf20Sopenharmony_ci
10488c2ecf20Sopenharmony_ci		case STV090x_PR23:
10498c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, PRVIT, 0x02) < 0)
10508c2ecf20Sopenharmony_ci				goto err;
10518c2ecf20Sopenharmony_ci			break;
10528c2ecf20Sopenharmony_ci
10538c2ecf20Sopenharmony_ci		case STV090x_PR67:
10548c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, PRVIT, 0x10) < 0)
10558c2ecf20Sopenharmony_ci				goto err;
10568c2ecf20Sopenharmony_ci			break;
10578c2ecf20Sopenharmony_ci
10588c2ecf20Sopenharmony_ci		default:
10598c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, PRVIT, 0x13) < 0) /* 1/2, 2/3, 6/7 */
10608c2ecf20Sopenharmony_ci				goto err;
10618c2ecf20Sopenharmony_ci			break;
10628c2ecf20Sopenharmony_ci		}
10638c2ecf20Sopenharmony_ci		break;
10648c2ecf20Sopenharmony_ci	default:
10658c2ecf20Sopenharmony_ci		break;
10668c2ecf20Sopenharmony_ci	}
10678c2ecf20Sopenharmony_ci	return 0;
10688c2ecf20Sopenharmony_cierr:
10698c2ecf20Sopenharmony_ci	dprintk(FE_ERROR, 1, "I/O error");
10708c2ecf20Sopenharmony_ci	return -1;
10718c2ecf20Sopenharmony_ci}
10728c2ecf20Sopenharmony_ci
10738c2ecf20Sopenharmony_cistatic int stv090x_stop_modcod(struct stv090x_state *state)
10748c2ecf20Sopenharmony_ci{
10758c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, MODCODLST0, 0xff) < 0)
10768c2ecf20Sopenharmony_ci		goto err;
10778c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, MODCODLST1, 0xff) < 0)
10788c2ecf20Sopenharmony_ci		goto err;
10798c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, MODCODLST2, 0xff) < 0)
10808c2ecf20Sopenharmony_ci		goto err;
10818c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, MODCODLST3, 0xff) < 0)
10828c2ecf20Sopenharmony_ci		goto err;
10838c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, MODCODLST4, 0xff) < 0)
10848c2ecf20Sopenharmony_ci		goto err;
10858c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, MODCODLST5, 0xff) < 0)
10868c2ecf20Sopenharmony_ci		goto err;
10878c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, MODCODLST6, 0xff) < 0)
10888c2ecf20Sopenharmony_ci		goto err;
10898c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, MODCODLST7, 0xff) < 0)
10908c2ecf20Sopenharmony_ci		goto err;
10918c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, MODCODLST8, 0xff) < 0)
10928c2ecf20Sopenharmony_ci		goto err;
10938c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, MODCODLST9, 0xff) < 0)
10948c2ecf20Sopenharmony_ci		goto err;
10958c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, MODCODLSTA, 0xff) < 0)
10968c2ecf20Sopenharmony_ci		goto err;
10978c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, MODCODLSTB, 0xff) < 0)
10988c2ecf20Sopenharmony_ci		goto err;
10998c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, MODCODLSTC, 0xff) < 0)
11008c2ecf20Sopenharmony_ci		goto err;
11018c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, MODCODLSTD, 0xff) < 0)
11028c2ecf20Sopenharmony_ci		goto err;
11038c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, MODCODLSTE, 0xff) < 0)
11048c2ecf20Sopenharmony_ci		goto err;
11058c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, MODCODLSTF, 0xff) < 0)
11068c2ecf20Sopenharmony_ci		goto err;
11078c2ecf20Sopenharmony_ci	return 0;
11088c2ecf20Sopenharmony_cierr:
11098c2ecf20Sopenharmony_ci	dprintk(FE_ERROR, 1, "I/O error");
11108c2ecf20Sopenharmony_ci	return -1;
11118c2ecf20Sopenharmony_ci}
11128c2ecf20Sopenharmony_ci
11138c2ecf20Sopenharmony_cistatic int stv090x_activate_modcod(struct stv090x_state *state)
11148c2ecf20Sopenharmony_ci{
11158c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, MODCODLST0, 0xff) < 0)
11168c2ecf20Sopenharmony_ci		goto err;
11178c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, MODCODLST1, 0xfc) < 0)
11188c2ecf20Sopenharmony_ci		goto err;
11198c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, MODCODLST2, 0xcc) < 0)
11208c2ecf20Sopenharmony_ci		goto err;
11218c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, MODCODLST3, 0xcc) < 0)
11228c2ecf20Sopenharmony_ci		goto err;
11238c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, MODCODLST4, 0xcc) < 0)
11248c2ecf20Sopenharmony_ci		goto err;
11258c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, MODCODLST5, 0xcc) < 0)
11268c2ecf20Sopenharmony_ci		goto err;
11278c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, MODCODLST6, 0xcc) < 0)
11288c2ecf20Sopenharmony_ci		goto err;
11298c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, MODCODLST7, 0xcc) < 0)
11308c2ecf20Sopenharmony_ci		goto err;
11318c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, MODCODLST8, 0xcc) < 0)
11328c2ecf20Sopenharmony_ci		goto err;
11338c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, MODCODLST9, 0xcc) < 0)
11348c2ecf20Sopenharmony_ci		goto err;
11358c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, MODCODLSTA, 0xcc) < 0)
11368c2ecf20Sopenharmony_ci		goto err;
11378c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, MODCODLSTB, 0xcc) < 0)
11388c2ecf20Sopenharmony_ci		goto err;
11398c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, MODCODLSTC, 0xcc) < 0)
11408c2ecf20Sopenharmony_ci		goto err;
11418c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, MODCODLSTD, 0xcc) < 0)
11428c2ecf20Sopenharmony_ci		goto err;
11438c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, MODCODLSTE, 0xcc) < 0)
11448c2ecf20Sopenharmony_ci		goto err;
11458c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, MODCODLSTF, 0xcf) < 0)
11468c2ecf20Sopenharmony_ci		goto err;
11478c2ecf20Sopenharmony_ci
11488c2ecf20Sopenharmony_ci	return 0;
11498c2ecf20Sopenharmony_cierr:
11508c2ecf20Sopenharmony_ci	dprintk(FE_ERROR, 1, "I/O error");
11518c2ecf20Sopenharmony_ci	return -1;
11528c2ecf20Sopenharmony_ci}
11538c2ecf20Sopenharmony_ci
11548c2ecf20Sopenharmony_cistatic int stv090x_activate_modcod_single(struct stv090x_state *state)
11558c2ecf20Sopenharmony_ci{
11568c2ecf20Sopenharmony_ci
11578c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, MODCODLST0, 0xff) < 0)
11588c2ecf20Sopenharmony_ci		goto err;
11598c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, MODCODLST1, 0xf0) < 0)
11608c2ecf20Sopenharmony_ci		goto err;
11618c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, MODCODLST2, 0x00) < 0)
11628c2ecf20Sopenharmony_ci		goto err;
11638c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, MODCODLST3, 0x00) < 0)
11648c2ecf20Sopenharmony_ci		goto err;
11658c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, MODCODLST4, 0x00) < 0)
11668c2ecf20Sopenharmony_ci		goto err;
11678c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, MODCODLST5, 0x00) < 0)
11688c2ecf20Sopenharmony_ci		goto err;
11698c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, MODCODLST6, 0x00) < 0)
11708c2ecf20Sopenharmony_ci		goto err;
11718c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, MODCODLST7, 0x00) < 0)
11728c2ecf20Sopenharmony_ci		goto err;
11738c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, MODCODLST8, 0x00) < 0)
11748c2ecf20Sopenharmony_ci		goto err;
11758c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, MODCODLST9, 0x00) < 0)
11768c2ecf20Sopenharmony_ci		goto err;
11778c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, MODCODLSTA, 0x00) < 0)
11788c2ecf20Sopenharmony_ci		goto err;
11798c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, MODCODLSTB, 0x00) < 0)
11808c2ecf20Sopenharmony_ci		goto err;
11818c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, MODCODLSTC, 0x00) < 0)
11828c2ecf20Sopenharmony_ci		goto err;
11838c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, MODCODLSTD, 0x00) < 0)
11848c2ecf20Sopenharmony_ci		goto err;
11858c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, MODCODLSTE, 0x00) < 0)
11868c2ecf20Sopenharmony_ci		goto err;
11878c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, MODCODLSTF, 0x0f) < 0)
11888c2ecf20Sopenharmony_ci		goto err;
11898c2ecf20Sopenharmony_ci
11908c2ecf20Sopenharmony_ci	return 0;
11918c2ecf20Sopenharmony_ci
11928c2ecf20Sopenharmony_cierr:
11938c2ecf20Sopenharmony_ci	dprintk(FE_ERROR, 1, "I/O error");
11948c2ecf20Sopenharmony_ci	return -1;
11958c2ecf20Sopenharmony_ci}
11968c2ecf20Sopenharmony_ci
11978c2ecf20Sopenharmony_cistatic int stv090x_vitclk_ctl(struct stv090x_state *state, int enable)
11988c2ecf20Sopenharmony_ci{
11998c2ecf20Sopenharmony_ci	u32 reg;
12008c2ecf20Sopenharmony_ci
12018c2ecf20Sopenharmony_ci	switch (state->demod) {
12028c2ecf20Sopenharmony_ci	case STV090x_DEMODULATOR_0:
12038c2ecf20Sopenharmony_ci		mutex_lock(&state->internal->demod_lock);
12048c2ecf20Sopenharmony_ci		reg = stv090x_read_reg(state, STV090x_STOPCLK2);
12058c2ecf20Sopenharmony_ci		STV090x_SETFIELD(reg, STOP_CLKVIT1_FIELD, enable);
12068c2ecf20Sopenharmony_ci		if (stv090x_write_reg(state, STV090x_STOPCLK2, reg) < 0)
12078c2ecf20Sopenharmony_ci			goto err;
12088c2ecf20Sopenharmony_ci		mutex_unlock(&state->internal->demod_lock);
12098c2ecf20Sopenharmony_ci		break;
12108c2ecf20Sopenharmony_ci
12118c2ecf20Sopenharmony_ci	case STV090x_DEMODULATOR_1:
12128c2ecf20Sopenharmony_ci		mutex_lock(&state->internal->demod_lock);
12138c2ecf20Sopenharmony_ci		reg = stv090x_read_reg(state, STV090x_STOPCLK2);
12148c2ecf20Sopenharmony_ci		STV090x_SETFIELD(reg, STOP_CLKVIT2_FIELD, enable);
12158c2ecf20Sopenharmony_ci		if (stv090x_write_reg(state, STV090x_STOPCLK2, reg) < 0)
12168c2ecf20Sopenharmony_ci			goto err;
12178c2ecf20Sopenharmony_ci		mutex_unlock(&state->internal->demod_lock);
12188c2ecf20Sopenharmony_ci		break;
12198c2ecf20Sopenharmony_ci
12208c2ecf20Sopenharmony_ci	default:
12218c2ecf20Sopenharmony_ci		dprintk(FE_ERROR, 1, "Wrong demodulator!");
12228c2ecf20Sopenharmony_ci		break;
12238c2ecf20Sopenharmony_ci	}
12248c2ecf20Sopenharmony_ci	return 0;
12258c2ecf20Sopenharmony_cierr:
12268c2ecf20Sopenharmony_ci	mutex_unlock(&state->internal->demod_lock);
12278c2ecf20Sopenharmony_ci	dprintk(FE_ERROR, 1, "I/O error");
12288c2ecf20Sopenharmony_ci	return -1;
12298c2ecf20Sopenharmony_ci}
12308c2ecf20Sopenharmony_ci
12318c2ecf20Sopenharmony_cistatic int stv090x_dvbs_track_crl(struct stv090x_state *state)
12328c2ecf20Sopenharmony_ci{
12338c2ecf20Sopenharmony_ci	if (state->internal->dev_ver >= 0x30) {
12348c2ecf20Sopenharmony_ci		/* Set ACLC BCLC optimised value vs SR */
12358c2ecf20Sopenharmony_ci		if (state->srate >= 15000000) {
12368c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, ACLC, 0x2b) < 0)
12378c2ecf20Sopenharmony_ci				goto err;
12388c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, BCLC, 0x1a) < 0)
12398c2ecf20Sopenharmony_ci				goto err;
12408c2ecf20Sopenharmony_ci		} else if ((state->srate >= 7000000) && (15000000 > state->srate)) {
12418c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, ACLC, 0x0c) < 0)
12428c2ecf20Sopenharmony_ci				goto err;
12438c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, BCLC, 0x1b) < 0)
12448c2ecf20Sopenharmony_ci				goto err;
12458c2ecf20Sopenharmony_ci		} else if (state->srate < 7000000) {
12468c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, ACLC, 0x2c) < 0)
12478c2ecf20Sopenharmony_ci				goto err;
12488c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, BCLC, 0x1c) < 0)
12498c2ecf20Sopenharmony_ci				goto err;
12508c2ecf20Sopenharmony_ci		}
12518c2ecf20Sopenharmony_ci
12528c2ecf20Sopenharmony_ci	} else {
12538c2ecf20Sopenharmony_ci		/* Cut 2.0 */
12548c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, ACLC, 0x1a) < 0)
12558c2ecf20Sopenharmony_ci			goto err;
12568c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, BCLC, 0x09) < 0)
12578c2ecf20Sopenharmony_ci			goto err;
12588c2ecf20Sopenharmony_ci	}
12598c2ecf20Sopenharmony_ci	return 0;
12608c2ecf20Sopenharmony_cierr:
12618c2ecf20Sopenharmony_ci	dprintk(FE_ERROR, 1, "I/O error");
12628c2ecf20Sopenharmony_ci	return -1;
12638c2ecf20Sopenharmony_ci}
12648c2ecf20Sopenharmony_ci
12658c2ecf20Sopenharmony_cistatic int stv090x_delivery_search(struct stv090x_state *state)
12668c2ecf20Sopenharmony_ci{
12678c2ecf20Sopenharmony_ci	u32 reg;
12688c2ecf20Sopenharmony_ci
12698c2ecf20Sopenharmony_ci	switch (state->search_mode) {
12708c2ecf20Sopenharmony_ci	case STV090x_SEARCH_DVBS1:
12718c2ecf20Sopenharmony_ci	case STV090x_SEARCH_DSS:
12728c2ecf20Sopenharmony_ci		reg = STV090x_READ_DEMOD(state, DMDCFGMD);
12738c2ecf20Sopenharmony_ci		STV090x_SETFIELD_Px(reg, DVBS1_ENABLE_FIELD, 1);
12748c2ecf20Sopenharmony_ci		STV090x_SETFIELD_Px(reg, DVBS2_ENABLE_FIELD, 0);
12758c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0)
12768c2ecf20Sopenharmony_ci			goto err;
12778c2ecf20Sopenharmony_ci
12788c2ecf20Sopenharmony_ci		/* Activate Viterbi decoder in legacy search,
12798c2ecf20Sopenharmony_ci		 * do not use FRESVIT1, might impact VITERBI2
12808c2ecf20Sopenharmony_ci		 */
12818c2ecf20Sopenharmony_ci		if (stv090x_vitclk_ctl(state, 0) < 0)
12828c2ecf20Sopenharmony_ci			goto err;
12838c2ecf20Sopenharmony_ci
12848c2ecf20Sopenharmony_ci		if (stv090x_dvbs_track_crl(state) < 0)
12858c2ecf20Sopenharmony_ci			goto err;
12868c2ecf20Sopenharmony_ci
12878c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, CAR2CFG, 0x22) < 0) /* disable DVB-S2 */
12888c2ecf20Sopenharmony_ci			goto err;
12898c2ecf20Sopenharmony_ci
12908c2ecf20Sopenharmony_ci		if (stv090x_set_vit_thacq(state) < 0)
12918c2ecf20Sopenharmony_ci			goto err;
12928c2ecf20Sopenharmony_ci		if (stv090x_set_viterbi(state) < 0)
12938c2ecf20Sopenharmony_ci			goto err;
12948c2ecf20Sopenharmony_ci		break;
12958c2ecf20Sopenharmony_ci
12968c2ecf20Sopenharmony_ci	case STV090x_SEARCH_DVBS2:
12978c2ecf20Sopenharmony_ci		reg = STV090x_READ_DEMOD(state, DMDCFGMD);
12988c2ecf20Sopenharmony_ci		STV090x_SETFIELD_Px(reg, DVBS1_ENABLE_FIELD, 0);
12998c2ecf20Sopenharmony_ci		STV090x_SETFIELD_Px(reg, DVBS2_ENABLE_FIELD, 0);
13008c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0)
13018c2ecf20Sopenharmony_ci			goto err;
13028c2ecf20Sopenharmony_ci		STV090x_SETFIELD_Px(reg, DVBS1_ENABLE_FIELD, 1);
13038c2ecf20Sopenharmony_ci		STV090x_SETFIELD_Px(reg, DVBS2_ENABLE_FIELD, 1);
13048c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0)
13058c2ecf20Sopenharmony_ci			goto err;
13068c2ecf20Sopenharmony_ci
13078c2ecf20Sopenharmony_ci		if (stv090x_vitclk_ctl(state, 1) < 0)
13088c2ecf20Sopenharmony_ci			goto err;
13098c2ecf20Sopenharmony_ci
13108c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, ACLC, 0x1a) < 0) /* stop DVB-S CR loop */
13118c2ecf20Sopenharmony_ci			goto err;
13128c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, BCLC, 0x09) < 0)
13138c2ecf20Sopenharmony_ci			goto err;
13148c2ecf20Sopenharmony_ci
13158c2ecf20Sopenharmony_ci		if (state->internal->dev_ver <= 0x20) {
13168c2ecf20Sopenharmony_ci			/* enable S2 carrier loop */
13178c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, CAR2CFG, 0x26) < 0)
13188c2ecf20Sopenharmony_ci				goto err;
13198c2ecf20Sopenharmony_ci		} else {
13208c2ecf20Sopenharmony_ci			/* > Cut 3: Stop carrier 3 */
13218c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, CAR2CFG, 0x66) < 0)
13228c2ecf20Sopenharmony_ci				goto err;
13238c2ecf20Sopenharmony_ci		}
13248c2ecf20Sopenharmony_ci
13258c2ecf20Sopenharmony_ci		if (state->demod_mode != STV090x_SINGLE) {
13268c2ecf20Sopenharmony_ci			/* Cut 2: enable link during search */
13278c2ecf20Sopenharmony_ci			if (stv090x_activate_modcod(state) < 0)
13288c2ecf20Sopenharmony_ci				goto err;
13298c2ecf20Sopenharmony_ci		} else {
13308c2ecf20Sopenharmony_ci			/* Single demodulator
13318c2ecf20Sopenharmony_ci			 * Authorize SHORT and LONG frames,
13328c2ecf20Sopenharmony_ci			 * QPSK, 8PSK, 16APSK and 32APSK
13338c2ecf20Sopenharmony_ci			 */
13348c2ecf20Sopenharmony_ci			if (stv090x_activate_modcod_single(state) < 0)
13358c2ecf20Sopenharmony_ci				goto err;
13368c2ecf20Sopenharmony_ci		}
13378c2ecf20Sopenharmony_ci
13388c2ecf20Sopenharmony_ci		if (stv090x_set_vit_thtracq(state) < 0)
13398c2ecf20Sopenharmony_ci			goto err;
13408c2ecf20Sopenharmony_ci		break;
13418c2ecf20Sopenharmony_ci
13428c2ecf20Sopenharmony_ci	case STV090x_SEARCH_AUTO:
13438c2ecf20Sopenharmony_ci	default:
13448c2ecf20Sopenharmony_ci		/* enable DVB-S2 and DVB-S2 in Auto MODE */
13458c2ecf20Sopenharmony_ci		reg = STV090x_READ_DEMOD(state, DMDCFGMD);
13468c2ecf20Sopenharmony_ci		STV090x_SETFIELD_Px(reg, DVBS1_ENABLE_FIELD, 0);
13478c2ecf20Sopenharmony_ci		STV090x_SETFIELD_Px(reg, DVBS2_ENABLE_FIELD, 0);
13488c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0)
13498c2ecf20Sopenharmony_ci			goto err;
13508c2ecf20Sopenharmony_ci		STV090x_SETFIELD_Px(reg, DVBS1_ENABLE_FIELD, 1);
13518c2ecf20Sopenharmony_ci		STV090x_SETFIELD_Px(reg, DVBS2_ENABLE_FIELD, 1);
13528c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0)
13538c2ecf20Sopenharmony_ci			goto err;
13548c2ecf20Sopenharmony_ci
13558c2ecf20Sopenharmony_ci		if (stv090x_vitclk_ctl(state, 0) < 0)
13568c2ecf20Sopenharmony_ci			goto err;
13578c2ecf20Sopenharmony_ci
13588c2ecf20Sopenharmony_ci		if (stv090x_dvbs_track_crl(state) < 0)
13598c2ecf20Sopenharmony_ci			goto err;
13608c2ecf20Sopenharmony_ci
13618c2ecf20Sopenharmony_ci		if (state->internal->dev_ver <= 0x20) {
13628c2ecf20Sopenharmony_ci			/* enable S2 carrier loop */
13638c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, CAR2CFG, 0x26) < 0)
13648c2ecf20Sopenharmony_ci				goto err;
13658c2ecf20Sopenharmony_ci		} else {
13668c2ecf20Sopenharmony_ci			/* > Cut 3: Stop carrier 3 */
13678c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, CAR2CFG, 0x66) < 0)
13688c2ecf20Sopenharmony_ci				goto err;
13698c2ecf20Sopenharmony_ci		}
13708c2ecf20Sopenharmony_ci
13718c2ecf20Sopenharmony_ci		if (state->demod_mode != STV090x_SINGLE) {
13728c2ecf20Sopenharmony_ci			/* Cut 2: enable link during search */
13738c2ecf20Sopenharmony_ci			if (stv090x_activate_modcod(state) < 0)
13748c2ecf20Sopenharmony_ci				goto err;
13758c2ecf20Sopenharmony_ci		} else {
13768c2ecf20Sopenharmony_ci			/* Single demodulator
13778c2ecf20Sopenharmony_ci			 * Authorize SHORT and LONG frames,
13788c2ecf20Sopenharmony_ci			 * QPSK, 8PSK, 16APSK and 32APSK
13798c2ecf20Sopenharmony_ci			 */
13808c2ecf20Sopenharmony_ci			if (stv090x_activate_modcod_single(state) < 0)
13818c2ecf20Sopenharmony_ci				goto err;
13828c2ecf20Sopenharmony_ci		}
13838c2ecf20Sopenharmony_ci
13848c2ecf20Sopenharmony_ci		if (stv090x_set_vit_thacq(state) < 0)
13858c2ecf20Sopenharmony_ci			goto err;
13868c2ecf20Sopenharmony_ci
13878c2ecf20Sopenharmony_ci		if (stv090x_set_viterbi(state) < 0)
13888c2ecf20Sopenharmony_ci			goto err;
13898c2ecf20Sopenharmony_ci		break;
13908c2ecf20Sopenharmony_ci	}
13918c2ecf20Sopenharmony_ci	return 0;
13928c2ecf20Sopenharmony_cierr:
13938c2ecf20Sopenharmony_ci	dprintk(FE_ERROR, 1, "I/O error");
13948c2ecf20Sopenharmony_ci	return -1;
13958c2ecf20Sopenharmony_ci}
13968c2ecf20Sopenharmony_ci
13978c2ecf20Sopenharmony_cistatic int stv090x_start_search(struct stv090x_state *state)
13988c2ecf20Sopenharmony_ci{
13998c2ecf20Sopenharmony_ci	u32 reg, freq_abs;
14008c2ecf20Sopenharmony_ci	s16 freq;
14018c2ecf20Sopenharmony_ci
14028c2ecf20Sopenharmony_ci	/* Reset demodulator */
14038c2ecf20Sopenharmony_ci	reg = STV090x_READ_DEMOD(state, DMDISTATE);
14048c2ecf20Sopenharmony_ci	STV090x_SETFIELD_Px(reg, I2C_DEMOD_MODE_FIELD, 0x1f);
14058c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, DMDISTATE, reg) < 0)
14068c2ecf20Sopenharmony_ci		goto err;
14078c2ecf20Sopenharmony_ci
14088c2ecf20Sopenharmony_ci	if (state->internal->dev_ver <= 0x20) {
14098c2ecf20Sopenharmony_ci		if (state->srate <= 5000000) {
14108c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, CARCFG, 0x44) < 0)
14118c2ecf20Sopenharmony_ci				goto err;
14128c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, CFRUP1, 0x0f) < 0)
14138c2ecf20Sopenharmony_ci				goto err;
14148c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, CFRUP0, 0xff) < 0)
14158c2ecf20Sopenharmony_ci				goto err;
14168c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, CFRLOW1, 0xf0) < 0)
14178c2ecf20Sopenharmony_ci				goto err;
14188c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, CFRLOW0, 0x00) < 0)
14198c2ecf20Sopenharmony_ci				goto err;
14208c2ecf20Sopenharmony_ci
14218c2ecf20Sopenharmony_ci			/*enlarge the timing bandwidth for Low SR*/
14228c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, RTCS2, 0x68) < 0)
14238c2ecf20Sopenharmony_ci				goto err;
14248c2ecf20Sopenharmony_ci		} else {
14258c2ecf20Sopenharmony_ci			/* If the symbol rate is >5 Msps
14268c2ecf20Sopenharmony_ci			Set The carrier search up and low to auto mode */
14278c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, CARCFG, 0xc4) < 0)
14288c2ecf20Sopenharmony_ci				goto err;
14298c2ecf20Sopenharmony_ci			/*reduce the timing bandwidth for high SR*/
14308c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, RTCS2, 0x44) < 0)
14318c2ecf20Sopenharmony_ci				goto err;
14328c2ecf20Sopenharmony_ci		}
14338c2ecf20Sopenharmony_ci	} else {
14348c2ecf20Sopenharmony_ci		/* >= Cut 3 */
14358c2ecf20Sopenharmony_ci		if (state->srate <= 5000000) {
14368c2ecf20Sopenharmony_ci			/* enlarge the timing bandwidth for Low SR */
14378c2ecf20Sopenharmony_ci			STV090x_WRITE_DEMOD(state, RTCS2, 0x68);
14388c2ecf20Sopenharmony_ci		} else {
14398c2ecf20Sopenharmony_ci			/* reduce timing bandwidth for high SR */
14408c2ecf20Sopenharmony_ci			STV090x_WRITE_DEMOD(state, RTCS2, 0x44);
14418c2ecf20Sopenharmony_ci		}
14428c2ecf20Sopenharmony_ci
14438c2ecf20Sopenharmony_ci		/* Set CFR min and max to manual mode */
14448c2ecf20Sopenharmony_ci		STV090x_WRITE_DEMOD(state, CARCFG, 0x46);
14458c2ecf20Sopenharmony_ci
14468c2ecf20Sopenharmony_ci		if (state->algo == STV090x_WARM_SEARCH) {
14478c2ecf20Sopenharmony_ci			/* WARM Start
14488c2ecf20Sopenharmony_ci			 * CFR min = -1MHz,
14498c2ecf20Sopenharmony_ci			 * CFR max = +1MHz
14508c2ecf20Sopenharmony_ci			 */
14518c2ecf20Sopenharmony_ci			freq_abs  = 1000 << 16;
14528c2ecf20Sopenharmony_ci			freq_abs /= (state->internal->mclk / 1000);
14538c2ecf20Sopenharmony_ci			freq      = (s16) freq_abs;
14548c2ecf20Sopenharmony_ci		} else {
14558c2ecf20Sopenharmony_ci			/* COLD Start
14568c2ecf20Sopenharmony_ci			 * CFR min =- (SearchRange / 2 + 600KHz)
14578c2ecf20Sopenharmony_ci			 * CFR max = +(SearchRange / 2 + 600KHz)
14588c2ecf20Sopenharmony_ci			 * (600KHz for the tuner step size)
14598c2ecf20Sopenharmony_ci			 */
14608c2ecf20Sopenharmony_ci			freq_abs  = (state->search_range / 2000) + 600;
14618c2ecf20Sopenharmony_ci			freq_abs  = freq_abs << 16;
14628c2ecf20Sopenharmony_ci			freq_abs /= (state->internal->mclk / 1000);
14638c2ecf20Sopenharmony_ci			freq      = (s16) freq_abs;
14648c2ecf20Sopenharmony_ci		}
14658c2ecf20Sopenharmony_ci
14668c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, CFRUP1, MSB(freq)) < 0)
14678c2ecf20Sopenharmony_ci			goto err;
14688c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, CFRUP0, LSB(freq)) < 0)
14698c2ecf20Sopenharmony_ci			goto err;
14708c2ecf20Sopenharmony_ci
14718c2ecf20Sopenharmony_ci		freq *= -1;
14728c2ecf20Sopenharmony_ci
14738c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, CFRLOW1, MSB(freq)) < 0)
14748c2ecf20Sopenharmony_ci			goto err;
14758c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, CFRLOW0, LSB(freq)) < 0)
14768c2ecf20Sopenharmony_ci			goto err;
14778c2ecf20Sopenharmony_ci
14788c2ecf20Sopenharmony_ci	}
14798c2ecf20Sopenharmony_ci
14808c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, CFRINIT1, 0) < 0)
14818c2ecf20Sopenharmony_ci		goto err;
14828c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, CFRINIT0, 0) < 0)
14838c2ecf20Sopenharmony_ci		goto err;
14848c2ecf20Sopenharmony_ci
14858c2ecf20Sopenharmony_ci	if (state->internal->dev_ver >= 0x20) {
14868c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, EQUALCFG, 0x41) < 0)
14878c2ecf20Sopenharmony_ci			goto err;
14888c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, FFECFG, 0x41) < 0)
14898c2ecf20Sopenharmony_ci			goto err;
14908c2ecf20Sopenharmony_ci
14918c2ecf20Sopenharmony_ci		if ((state->search_mode == STV090x_SEARCH_DVBS1)	||
14928c2ecf20Sopenharmony_ci			(state->search_mode == STV090x_SEARCH_DSS)	||
14938c2ecf20Sopenharmony_ci			(state->search_mode == STV090x_SEARCH_AUTO)) {
14948c2ecf20Sopenharmony_ci
14958c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, VITSCALE, 0x82) < 0)
14968c2ecf20Sopenharmony_ci				goto err;
14978c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, VAVSRVIT, 0x00) < 0)
14988c2ecf20Sopenharmony_ci				goto err;
14998c2ecf20Sopenharmony_ci		}
15008c2ecf20Sopenharmony_ci	}
15018c2ecf20Sopenharmony_ci
15028c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, SFRSTEP, 0x00) < 0)
15038c2ecf20Sopenharmony_ci		goto err;
15048c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, TMGTHRISE, 0xe0) < 0)
15058c2ecf20Sopenharmony_ci		goto err;
15068c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, TMGTHFALL, 0xc0) < 0)
15078c2ecf20Sopenharmony_ci		goto err;
15088c2ecf20Sopenharmony_ci
15098c2ecf20Sopenharmony_ci	reg = STV090x_READ_DEMOD(state, DMDCFGMD);
15108c2ecf20Sopenharmony_ci	STV090x_SETFIELD_Px(reg, SCAN_ENABLE_FIELD, 0);
15118c2ecf20Sopenharmony_ci	STV090x_SETFIELD_Px(reg, CFR_AUTOSCAN_FIELD, 0);
15128c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0)
15138c2ecf20Sopenharmony_ci		goto err;
15148c2ecf20Sopenharmony_ci	reg = STV090x_READ_DEMOD(state, DMDCFG2);
15158c2ecf20Sopenharmony_ci	STV090x_SETFIELD_Px(reg, S1S2_SEQUENTIAL_FIELD, 0x0);
15168c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, DMDCFG2, reg) < 0)
15178c2ecf20Sopenharmony_ci		goto err;
15188c2ecf20Sopenharmony_ci
15198c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, RTC, 0x88) < 0)
15208c2ecf20Sopenharmony_ci		goto err;
15218c2ecf20Sopenharmony_ci
15228c2ecf20Sopenharmony_ci	if (state->internal->dev_ver >= 0x20) {
15238c2ecf20Sopenharmony_ci		/*Frequency offset detector setting*/
15248c2ecf20Sopenharmony_ci		if (state->srate < 2000000) {
15258c2ecf20Sopenharmony_ci			if (state->internal->dev_ver <= 0x20) {
15268c2ecf20Sopenharmony_ci				/* Cut 2 */
15278c2ecf20Sopenharmony_ci				if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x39) < 0)
15288c2ecf20Sopenharmony_ci					goto err;
15298c2ecf20Sopenharmony_ci			} else {
15308c2ecf20Sopenharmony_ci				/* Cut 3 */
15318c2ecf20Sopenharmony_ci				if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x89) < 0)
15328c2ecf20Sopenharmony_ci					goto err;
15338c2ecf20Sopenharmony_ci			}
15348c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, CARHDR, 0x40) < 0)
15358c2ecf20Sopenharmony_ci				goto err;
15368c2ecf20Sopenharmony_ci		} else if (state->srate < 10000000) {
15378c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x4c) < 0)
15388c2ecf20Sopenharmony_ci				goto err;
15398c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, CARHDR, 0x20) < 0)
15408c2ecf20Sopenharmony_ci				goto err;
15418c2ecf20Sopenharmony_ci		} else {
15428c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x4b) < 0)
15438c2ecf20Sopenharmony_ci				goto err;
15448c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, CARHDR, 0x20) < 0)
15458c2ecf20Sopenharmony_ci				goto err;
15468c2ecf20Sopenharmony_ci		}
15478c2ecf20Sopenharmony_ci	} else {
15488c2ecf20Sopenharmony_ci		if (state->srate < 10000000) {
15498c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, CARFREQ, 0xef) < 0)
15508c2ecf20Sopenharmony_ci				goto err;
15518c2ecf20Sopenharmony_ci		} else {
15528c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, CARFREQ, 0xed) < 0)
15538c2ecf20Sopenharmony_ci				goto err;
15548c2ecf20Sopenharmony_ci		}
15558c2ecf20Sopenharmony_ci	}
15568c2ecf20Sopenharmony_ci
15578c2ecf20Sopenharmony_ci	switch (state->algo) {
15588c2ecf20Sopenharmony_ci	case STV090x_WARM_SEARCH:
15598c2ecf20Sopenharmony_ci		/* The symbol rate and the exact
15608c2ecf20Sopenharmony_ci		 * carrier Frequency are known
15618c2ecf20Sopenharmony_ci		 */
15628c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1f) < 0)
15638c2ecf20Sopenharmony_ci			goto err;
15648c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x18) < 0)
15658c2ecf20Sopenharmony_ci			goto err;
15668c2ecf20Sopenharmony_ci		break;
15678c2ecf20Sopenharmony_ci
15688c2ecf20Sopenharmony_ci	case STV090x_COLD_SEARCH:
15698c2ecf20Sopenharmony_ci		/* The symbol rate is known */
15708c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1f) < 0)
15718c2ecf20Sopenharmony_ci			goto err;
15728c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x15) < 0)
15738c2ecf20Sopenharmony_ci			goto err;
15748c2ecf20Sopenharmony_ci		break;
15758c2ecf20Sopenharmony_ci
15768c2ecf20Sopenharmony_ci	default:
15778c2ecf20Sopenharmony_ci		break;
15788c2ecf20Sopenharmony_ci	}
15798c2ecf20Sopenharmony_ci	return 0;
15808c2ecf20Sopenharmony_cierr:
15818c2ecf20Sopenharmony_ci	dprintk(FE_ERROR, 1, "I/O error");
15828c2ecf20Sopenharmony_ci	return -1;
15838c2ecf20Sopenharmony_ci}
15848c2ecf20Sopenharmony_ci
15858c2ecf20Sopenharmony_cistatic int stv090x_get_agc2_min_level(struct stv090x_state *state)
15868c2ecf20Sopenharmony_ci{
15878c2ecf20Sopenharmony_ci	u32 agc2_min = 0xffff, agc2 = 0, freq_init, freq_step, reg;
15888c2ecf20Sopenharmony_ci	s32 i, j, steps, dir;
15898c2ecf20Sopenharmony_ci
15908c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, AGC2REF, 0x38) < 0)
15918c2ecf20Sopenharmony_ci		goto err;
15928c2ecf20Sopenharmony_ci	reg = STV090x_READ_DEMOD(state, DMDCFGMD);
15938c2ecf20Sopenharmony_ci	STV090x_SETFIELD_Px(reg, SCAN_ENABLE_FIELD, 0);
15948c2ecf20Sopenharmony_ci	STV090x_SETFIELD_Px(reg, CFR_AUTOSCAN_FIELD, 0);
15958c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0)
15968c2ecf20Sopenharmony_ci		goto err;
15978c2ecf20Sopenharmony_ci
15988c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, SFRUP1, 0x83) < 0) /* SR = 65 Msps Max */
15998c2ecf20Sopenharmony_ci		goto err;
16008c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, SFRUP0, 0xc0) < 0)
16018c2ecf20Sopenharmony_ci		goto err;
16028c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, SFRLOW1, 0x82) < 0) /* SR= 400 ksps Min */
16038c2ecf20Sopenharmony_ci		goto err;
16048c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, SFRLOW0, 0xa0) < 0)
16058c2ecf20Sopenharmony_ci		goto err;
16068c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, DMDTOM, 0x00) < 0) /* stop acq @ coarse carrier state */
16078c2ecf20Sopenharmony_ci		goto err;
16088c2ecf20Sopenharmony_ci	if (stv090x_set_srate(state, 1000000) < 0)
16098c2ecf20Sopenharmony_ci		goto err;
16108c2ecf20Sopenharmony_ci
16118c2ecf20Sopenharmony_ci	steps  = state->search_range / 1000000;
16128c2ecf20Sopenharmony_ci	if (steps <= 0)
16138c2ecf20Sopenharmony_ci		steps = 1;
16148c2ecf20Sopenharmony_ci
16158c2ecf20Sopenharmony_ci	dir = 1;
16168c2ecf20Sopenharmony_ci	freq_step = (1000000 * 256) / (state->internal->mclk / 256);
16178c2ecf20Sopenharmony_ci	freq_init = 0;
16188c2ecf20Sopenharmony_ci
16198c2ecf20Sopenharmony_ci	for (i = 0; i < steps; i++) {
16208c2ecf20Sopenharmony_ci		if (dir > 0)
16218c2ecf20Sopenharmony_ci			freq_init = freq_init + (freq_step * i);
16228c2ecf20Sopenharmony_ci		else
16238c2ecf20Sopenharmony_ci			freq_init = freq_init - (freq_step * i);
16248c2ecf20Sopenharmony_ci
16258c2ecf20Sopenharmony_ci		dir *= -1;
16268c2ecf20Sopenharmony_ci
16278c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x5c) < 0) /* Demod RESET */
16288c2ecf20Sopenharmony_ci			goto err;
16298c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, CFRINIT1, (freq_init >> 8) & 0xff) < 0)
16308c2ecf20Sopenharmony_ci			goto err;
16318c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, CFRINIT0, freq_init & 0xff) < 0)
16328c2ecf20Sopenharmony_ci			goto err;
16338c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x58) < 0) /* Demod RESET */
16348c2ecf20Sopenharmony_ci			goto err;
16358c2ecf20Sopenharmony_ci		msleep(10);
16368c2ecf20Sopenharmony_ci
16378c2ecf20Sopenharmony_ci		agc2 = 0;
16388c2ecf20Sopenharmony_ci		for (j = 0; j < 10; j++) {
16398c2ecf20Sopenharmony_ci			agc2 += (STV090x_READ_DEMOD(state, AGC2I1) << 8) |
16408c2ecf20Sopenharmony_ci				STV090x_READ_DEMOD(state, AGC2I0);
16418c2ecf20Sopenharmony_ci		}
16428c2ecf20Sopenharmony_ci		agc2 /= 10;
16438c2ecf20Sopenharmony_ci		if (agc2 < agc2_min)
16448c2ecf20Sopenharmony_ci			agc2_min = agc2;
16458c2ecf20Sopenharmony_ci	}
16468c2ecf20Sopenharmony_ci
16478c2ecf20Sopenharmony_ci	return agc2_min;
16488c2ecf20Sopenharmony_cierr:
16498c2ecf20Sopenharmony_ci	dprintk(FE_ERROR, 1, "I/O error");
16508c2ecf20Sopenharmony_ci	return -1;
16518c2ecf20Sopenharmony_ci}
16528c2ecf20Sopenharmony_ci
16538c2ecf20Sopenharmony_cistatic u32 stv090x_get_srate(struct stv090x_state *state, u32 clk)
16548c2ecf20Sopenharmony_ci{
16558c2ecf20Sopenharmony_ci	u8 r3, r2, r1, r0;
16568c2ecf20Sopenharmony_ci	s32 srate, int_1, int_2, tmp_1, tmp_2;
16578c2ecf20Sopenharmony_ci
16588c2ecf20Sopenharmony_ci	r3 = STV090x_READ_DEMOD(state, SFR3);
16598c2ecf20Sopenharmony_ci	r2 = STV090x_READ_DEMOD(state, SFR2);
16608c2ecf20Sopenharmony_ci	r1 = STV090x_READ_DEMOD(state, SFR1);
16618c2ecf20Sopenharmony_ci	r0 = STV090x_READ_DEMOD(state, SFR0);
16628c2ecf20Sopenharmony_ci
16638c2ecf20Sopenharmony_ci	srate = ((r3 << 24) | (r2 << 16) | (r1 <<  8) | r0);
16648c2ecf20Sopenharmony_ci
16658c2ecf20Sopenharmony_ci	int_1 = clk >> 16;
16668c2ecf20Sopenharmony_ci	int_2 = srate >> 16;
16678c2ecf20Sopenharmony_ci
16688c2ecf20Sopenharmony_ci	tmp_1 = clk % 0x10000;
16698c2ecf20Sopenharmony_ci	tmp_2 = srate % 0x10000;
16708c2ecf20Sopenharmony_ci
16718c2ecf20Sopenharmony_ci	srate = (int_1 * int_2) +
16728c2ecf20Sopenharmony_ci		((int_1 * tmp_2) >> 16) +
16738c2ecf20Sopenharmony_ci		((int_2 * tmp_1) >> 16);
16748c2ecf20Sopenharmony_ci
16758c2ecf20Sopenharmony_ci	return srate;
16768c2ecf20Sopenharmony_ci}
16778c2ecf20Sopenharmony_ci
16788c2ecf20Sopenharmony_cistatic u32 stv090x_srate_srch_coarse(struct stv090x_state *state)
16798c2ecf20Sopenharmony_ci{
16808c2ecf20Sopenharmony_ci	struct dvb_frontend *fe = &state->frontend;
16818c2ecf20Sopenharmony_ci
16828c2ecf20Sopenharmony_ci	int tmg_lock = 0, i;
16838c2ecf20Sopenharmony_ci	s32 tmg_cpt = 0, dir = 1, steps, cur_step = 0, freq;
16848c2ecf20Sopenharmony_ci	u32 srate_coarse = 0, agc2 = 0, car_step = 1200, reg;
16858c2ecf20Sopenharmony_ci	u32 agc2th;
16868c2ecf20Sopenharmony_ci
16878c2ecf20Sopenharmony_ci	if (state->internal->dev_ver >= 0x30)
16888c2ecf20Sopenharmony_ci		agc2th = 0x2e00;
16898c2ecf20Sopenharmony_ci	else
16908c2ecf20Sopenharmony_ci		agc2th = 0x1f00;
16918c2ecf20Sopenharmony_ci
16928c2ecf20Sopenharmony_ci	reg = STV090x_READ_DEMOD(state, DMDISTATE);
16938c2ecf20Sopenharmony_ci	STV090x_SETFIELD_Px(reg, I2C_DEMOD_MODE_FIELD, 0x1f); /* Demod RESET */
16948c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, DMDISTATE, reg) < 0)
16958c2ecf20Sopenharmony_ci		goto err;
16968c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, TMGCFG, 0x12) < 0)
16978c2ecf20Sopenharmony_ci		goto err;
16988c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, TMGCFG2, 0xc0) < 0)
16998c2ecf20Sopenharmony_ci		goto err;
17008c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, TMGTHRISE, 0xf0) < 0)
17018c2ecf20Sopenharmony_ci		goto err;
17028c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, TMGTHFALL, 0xe0) < 0)
17038c2ecf20Sopenharmony_ci		goto err;
17048c2ecf20Sopenharmony_ci	reg = STV090x_READ_DEMOD(state, DMDCFGMD);
17058c2ecf20Sopenharmony_ci	STV090x_SETFIELD_Px(reg, SCAN_ENABLE_FIELD, 1);
17068c2ecf20Sopenharmony_ci	STV090x_SETFIELD_Px(reg, CFR_AUTOSCAN_FIELD, 0);
17078c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0)
17088c2ecf20Sopenharmony_ci		goto err;
17098c2ecf20Sopenharmony_ci
17108c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, SFRUP1, 0x83) < 0)
17118c2ecf20Sopenharmony_ci		goto err;
17128c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, SFRUP0, 0xc0) < 0)
17138c2ecf20Sopenharmony_ci		goto err;
17148c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, SFRLOW1, 0x82) < 0)
17158c2ecf20Sopenharmony_ci		goto err;
17168c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, SFRLOW0, 0xa0) < 0)
17178c2ecf20Sopenharmony_ci		goto err;
17188c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, DMDTOM, 0x00) < 0)
17198c2ecf20Sopenharmony_ci		goto err;
17208c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, AGC2REF, 0x50) < 0)
17218c2ecf20Sopenharmony_ci		goto err;
17228c2ecf20Sopenharmony_ci
17238c2ecf20Sopenharmony_ci	if (state->internal->dev_ver >= 0x30) {
17248c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x99) < 0)
17258c2ecf20Sopenharmony_ci			goto err;
17268c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, SFRSTEP, 0x98) < 0)
17278c2ecf20Sopenharmony_ci			goto err;
17288c2ecf20Sopenharmony_ci
17298c2ecf20Sopenharmony_ci	} else if (state->internal->dev_ver >= 0x20) {
17308c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x6a) < 0)
17318c2ecf20Sopenharmony_ci			goto err;
17328c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, SFRSTEP, 0x95) < 0)
17338c2ecf20Sopenharmony_ci			goto err;
17348c2ecf20Sopenharmony_ci	}
17358c2ecf20Sopenharmony_ci
17368c2ecf20Sopenharmony_ci	if (state->srate <= 2000000)
17378c2ecf20Sopenharmony_ci		car_step = 1000;
17388c2ecf20Sopenharmony_ci	else if (state->srate <= 5000000)
17398c2ecf20Sopenharmony_ci		car_step = 2000;
17408c2ecf20Sopenharmony_ci	else if (state->srate <= 12000000)
17418c2ecf20Sopenharmony_ci		car_step = 3000;
17428c2ecf20Sopenharmony_ci	else
17438c2ecf20Sopenharmony_ci		car_step = 5000;
17448c2ecf20Sopenharmony_ci
17458c2ecf20Sopenharmony_ci	steps  = -1 + ((state->search_range / 1000) / car_step);
17468c2ecf20Sopenharmony_ci	steps /= 2;
17478c2ecf20Sopenharmony_ci	steps  = (2 * steps) + 1;
17488c2ecf20Sopenharmony_ci	if (steps < 0)
17498c2ecf20Sopenharmony_ci		steps = 1;
17508c2ecf20Sopenharmony_ci	else if (steps > 10) {
17518c2ecf20Sopenharmony_ci		steps = 11;
17528c2ecf20Sopenharmony_ci		car_step = (state->search_range / 1000) / 10;
17538c2ecf20Sopenharmony_ci	}
17548c2ecf20Sopenharmony_ci	cur_step = 0;
17558c2ecf20Sopenharmony_ci	dir = 1;
17568c2ecf20Sopenharmony_ci	freq = state->frequency;
17578c2ecf20Sopenharmony_ci
17588c2ecf20Sopenharmony_ci	while ((!tmg_lock) && (cur_step < steps)) {
17598c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x5f) < 0) /* Demod RESET */
17608c2ecf20Sopenharmony_ci			goto err;
17618c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, CFRINIT1, 0x00) < 0)
17628c2ecf20Sopenharmony_ci			goto err;
17638c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, CFRINIT0, 0x00) < 0)
17648c2ecf20Sopenharmony_ci			goto err;
17658c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, SFRINIT1, 0x00) < 0)
17668c2ecf20Sopenharmony_ci			goto err;
17678c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, SFRINIT0, 0x00) < 0)
17688c2ecf20Sopenharmony_ci			goto err;
17698c2ecf20Sopenharmony_ci		/* trigger acquisition */
17708c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x40) < 0)
17718c2ecf20Sopenharmony_ci			goto err;
17728c2ecf20Sopenharmony_ci		msleep(50);
17738c2ecf20Sopenharmony_ci		for (i = 0; i < 10; i++) {
17748c2ecf20Sopenharmony_ci			reg = STV090x_READ_DEMOD(state, DSTATUS);
17758c2ecf20Sopenharmony_ci			if (STV090x_GETFIELD_Px(reg, TMGLOCK_QUALITY_FIELD) >= 2)
17768c2ecf20Sopenharmony_ci				tmg_cpt++;
17778c2ecf20Sopenharmony_ci			agc2 += (STV090x_READ_DEMOD(state, AGC2I1) << 8) |
17788c2ecf20Sopenharmony_ci				STV090x_READ_DEMOD(state, AGC2I0);
17798c2ecf20Sopenharmony_ci		}
17808c2ecf20Sopenharmony_ci		agc2 /= 10;
17818c2ecf20Sopenharmony_ci		srate_coarse = stv090x_get_srate(state, state->internal->mclk);
17828c2ecf20Sopenharmony_ci		cur_step++;
17838c2ecf20Sopenharmony_ci		dir *= -1;
17848c2ecf20Sopenharmony_ci		if ((tmg_cpt >= 5) && (agc2 < agc2th) &&
17858c2ecf20Sopenharmony_ci		    (srate_coarse < 50000000) && (srate_coarse > 850000))
17868c2ecf20Sopenharmony_ci			tmg_lock = 1;
17878c2ecf20Sopenharmony_ci		else if (cur_step < steps) {
17888c2ecf20Sopenharmony_ci			if (dir > 0)
17898c2ecf20Sopenharmony_ci				freq += cur_step * car_step;
17908c2ecf20Sopenharmony_ci			else
17918c2ecf20Sopenharmony_ci				freq -= cur_step * car_step;
17928c2ecf20Sopenharmony_ci
17938c2ecf20Sopenharmony_ci			/* Setup tuner */
17948c2ecf20Sopenharmony_ci			if (stv090x_i2c_gate_ctrl(state, 1) < 0)
17958c2ecf20Sopenharmony_ci				goto err;
17968c2ecf20Sopenharmony_ci
17978c2ecf20Sopenharmony_ci			if (state->config->tuner_set_frequency) {
17988c2ecf20Sopenharmony_ci				if (state->config->tuner_set_frequency(fe, freq) < 0)
17998c2ecf20Sopenharmony_ci					goto err_gateoff;
18008c2ecf20Sopenharmony_ci			}
18018c2ecf20Sopenharmony_ci
18028c2ecf20Sopenharmony_ci			if (state->config->tuner_set_bandwidth) {
18038c2ecf20Sopenharmony_ci				if (state->config->tuner_set_bandwidth(fe, state->tuner_bw) < 0)
18048c2ecf20Sopenharmony_ci					goto err_gateoff;
18058c2ecf20Sopenharmony_ci			}
18068c2ecf20Sopenharmony_ci
18078c2ecf20Sopenharmony_ci			if (stv090x_i2c_gate_ctrl(state, 0) < 0)
18088c2ecf20Sopenharmony_ci				goto err;
18098c2ecf20Sopenharmony_ci
18108c2ecf20Sopenharmony_ci			msleep(50);
18118c2ecf20Sopenharmony_ci
18128c2ecf20Sopenharmony_ci			if (stv090x_i2c_gate_ctrl(state, 1) < 0)
18138c2ecf20Sopenharmony_ci				goto err;
18148c2ecf20Sopenharmony_ci
18158c2ecf20Sopenharmony_ci			if (state->config->tuner_get_status) {
18168c2ecf20Sopenharmony_ci				if (state->config->tuner_get_status(fe, &reg) < 0)
18178c2ecf20Sopenharmony_ci					goto err_gateoff;
18188c2ecf20Sopenharmony_ci			}
18198c2ecf20Sopenharmony_ci
18208c2ecf20Sopenharmony_ci			if (reg)
18218c2ecf20Sopenharmony_ci				dprintk(FE_DEBUG, 1, "Tuner phase locked");
18228c2ecf20Sopenharmony_ci			else
18238c2ecf20Sopenharmony_ci				dprintk(FE_DEBUG, 1, "Tuner unlocked");
18248c2ecf20Sopenharmony_ci
18258c2ecf20Sopenharmony_ci			if (stv090x_i2c_gate_ctrl(state, 0) < 0)
18268c2ecf20Sopenharmony_ci				goto err;
18278c2ecf20Sopenharmony_ci
18288c2ecf20Sopenharmony_ci		}
18298c2ecf20Sopenharmony_ci	}
18308c2ecf20Sopenharmony_ci	if (!tmg_lock)
18318c2ecf20Sopenharmony_ci		srate_coarse = 0;
18328c2ecf20Sopenharmony_ci	else
18338c2ecf20Sopenharmony_ci		srate_coarse = stv090x_get_srate(state, state->internal->mclk);
18348c2ecf20Sopenharmony_ci
18358c2ecf20Sopenharmony_ci	return srate_coarse;
18368c2ecf20Sopenharmony_ci
18378c2ecf20Sopenharmony_cierr_gateoff:
18388c2ecf20Sopenharmony_ci	stv090x_i2c_gate_ctrl(state, 0);
18398c2ecf20Sopenharmony_cierr:
18408c2ecf20Sopenharmony_ci	dprintk(FE_ERROR, 1, "I/O error");
18418c2ecf20Sopenharmony_ci	return -1;
18428c2ecf20Sopenharmony_ci}
18438c2ecf20Sopenharmony_ci
18448c2ecf20Sopenharmony_cistatic u32 stv090x_srate_srch_fine(struct stv090x_state *state)
18458c2ecf20Sopenharmony_ci{
18468c2ecf20Sopenharmony_ci	u32 srate_coarse, freq_coarse, sym, reg;
18478c2ecf20Sopenharmony_ci
18488c2ecf20Sopenharmony_ci	srate_coarse = stv090x_get_srate(state, state->internal->mclk);
18498c2ecf20Sopenharmony_ci	freq_coarse  = STV090x_READ_DEMOD(state, CFR2) << 8;
18508c2ecf20Sopenharmony_ci	freq_coarse |= STV090x_READ_DEMOD(state, CFR1);
18518c2ecf20Sopenharmony_ci	sym = 13 * (srate_coarse / 10); /* SFRUP = SFR + 30% */
18528c2ecf20Sopenharmony_ci
18538c2ecf20Sopenharmony_ci	if (sym < state->srate)
18548c2ecf20Sopenharmony_ci		srate_coarse = 0;
18558c2ecf20Sopenharmony_ci	else {
18568c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1f) < 0) /* Demod RESET */
18578c2ecf20Sopenharmony_ci			goto err;
18588c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, TMGCFG2, 0xc1) < 0)
18598c2ecf20Sopenharmony_ci			goto err;
18608c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, TMGTHRISE, 0x20) < 0)
18618c2ecf20Sopenharmony_ci			goto err;
18628c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, TMGTHFALL, 0x00) < 0)
18638c2ecf20Sopenharmony_ci			goto err;
18648c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, TMGCFG, 0xd2) < 0)
18658c2ecf20Sopenharmony_ci			goto err;
18668c2ecf20Sopenharmony_ci		reg = STV090x_READ_DEMOD(state, DMDCFGMD);
18678c2ecf20Sopenharmony_ci		STV090x_SETFIELD_Px(reg, CFR_AUTOSCAN_FIELD, 0x00);
18688c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0)
18698c2ecf20Sopenharmony_ci			goto err;
18708c2ecf20Sopenharmony_ci
18718c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, AGC2REF, 0x38) < 0)
18728c2ecf20Sopenharmony_ci			goto err;
18738c2ecf20Sopenharmony_ci
18748c2ecf20Sopenharmony_ci		if (state->internal->dev_ver >= 0x30) {
18758c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x79) < 0)
18768c2ecf20Sopenharmony_ci				goto err;
18778c2ecf20Sopenharmony_ci		} else if (state->internal->dev_ver >= 0x20) {
18788c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x49) < 0)
18798c2ecf20Sopenharmony_ci				goto err;
18808c2ecf20Sopenharmony_ci		}
18818c2ecf20Sopenharmony_ci
18828c2ecf20Sopenharmony_ci		if (srate_coarse > 3000000) {
18838c2ecf20Sopenharmony_ci			sym  = 13 * (srate_coarse / 10); /* SFRUP = SFR + 30% */
18848c2ecf20Sopenharmony_ci			sym  = (sym / 1000) * 65536;
18858c2ecf20Sopenharmony_ci			sym /= (state->internal->mclk / 1000);
18868c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, SFRUP1, (sym >> 8) & 0x7f) < 0)
18878c2ecf20Sopenharmony_ci				goto err;
18888c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, SFRUP0, sym & 0xff) < 0)
18898c2ecf20Sopenharmony_ci				goto err;
18908c2ecf20Sopenharmony_ci			sym  = 10 * (srate_coarse / 13); /* SFRLOW = SFR - 30% */
18918c2ecf20Sopenharmony_ci			sym  = (sym / 1000) * 65536;
18928c2ecf20Sopenharmony_ci			sym /= (state->internal->mclk / 1000);
18938c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, SFRLOW1, (sym >> 8) & 0x7f) < 0)
18948c2ecf20Sopenharmony_ci				goto err;
18958c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, SFRLOW0, sym & 0xff) < 0)
18968c2ecf20Sopenharmony_ci				goto err;
18978c2ecf20Sopenharmony_ci			sym  = (srate_coarse / 1000) * 65536;
18988c2ecf20Sopenharmony_ci			sym /= (state->internal->mclk / 1000);
18998c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, SFRINIT1, (sym >> 8) & 0xff) < 0)
19008c2ecf20Sopenharmony_ci				goto err;
19018c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, SFRINIT0, sym & 0xff) < 0)
19028c2ecf20Sopenharmony_ci				goto err;
19038c2ecf20Sopenharmony_ci		} else {
19048c2ecf20Sopenharmony_ci			sym  = 13 * (srate_coarse / 10); /* SFRUP = SFR + 30% */
19058c2ecf20Sopenharmony_ci			sym  = (sym / 100) * 65536;
19068c2ecf20Sopenharmony_ci			sym /= (state->internal->mclk / 100);
19078c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, SFRUP1, (sym >> 8) & 0x7f) < 0)
19088c2ecf20Sopenharmony_ci				goto err;
19098c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, SFRUP0, sym & 0xff) < 0)
19108c2ecf20Sopenharmony_ci				goto err;
19118c2ecf20Sopenharmony_ci			sym  = 10 * (srate_coarse / 14); /* SFRLOW = SFR - 30% */
19128c2ecf20Sopenharmony_ci			sym  = (sym / 100) * 65536;
19138c2ecf20Sopenharmony_ci			sym /= (state->internal->mclk / 100);
19148c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, SFRLOW1, (sym >> 8) & 0x7f) < 0)
19158c2ecf20Sopenharmony_ci				goto err;
19168c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, SFRLOW0, sym & 0xff) < 0)
19178c2ecf20Sopenharmony_ci				goto err;
19188c2ecf20Sopenharmony_ci			sym  = (srate_coarse / 100) * 65536;
19198c2ecf20Sopenharmony_ci			sym /= (state->internal->mclk / 100);
19208c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, SFRINIT1, (sym >> 8) & 0xff) < 0)
19218c2ecf20Sopenharmony_ci				goto err;
19228c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, SFRINIT0, sym & 0xff) < 0)
19238c2ecf20Sopenharmony_ci				goto err;
19248c2ecf20Sopenharmony_ci		}
19258c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, DMDTOM, 0x20) < 0)
19268c2ecf20Sopenharmony_ci			goto err;
19278c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, CFRINIT1, (freq_coarse >> 8) & 0xff) < 0)
19288c2ecf20Sopenharmony_ci			goto err;
19298c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, CFRINIT0, freq_coarse & 0xff) < 0)
19308c2ecf20Sopenharmony_ci			goto err;
19318c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x15) < 0) /* trigger acquisition */
19328c2ecf20Sopenharmony_ci			goto err;
19338c2ecf20Sopenharmony_ci	}
19348c2ecf20Sopenharmony_ci
19358c2ecf20Sopenharmony_ci	return srate_coarse;
19368c2ecf20Sopenharmony_ci
19378c2ecf20Sopenharmony_cierr:
19388c2ecf20Sopenharmony_ci	dprintk(FE_ERROR, 1, "I/O error");
19398c2ecf20Sopenharmony_ci	return -1;
19408c2ecf20Sopenharmony_ci}
19418c2ecf20Sopenharmony_ci
19428c2ecf20Sopenharmony_cistatic int stv090x_get_dmdlock(struct stv090x_state *state, s32 timeout)
19438c2ecf20Sopenharmony_ci{
19448c2ecf20Sopenharmony_ci	s32 timer = 0, lock = 0;
19458c2ecf20Sopenharmony_ci	u32 reg;
19468c2ecf20Sopenharmony_ci	u8 stat;
19478c2ecf20Sopenharmony_ci
19488c2ecf20Sopenharmony_ci	while ((timer < timeout) && (!lock)) {
19498c2ecf20Sopenharmony_ci		reg = STV090x_READ_DEMOD(state, DMDSTATE);
19508c2ecf20Sopenharmony_ci		stat = STV090x_GETFIELD_Px(reg, HEADER_MODE_FIELD);
19518c2ecf20Sopenharmony_ci
19528c2ecf20Sopenharmony_ci		switch (stat) {
19538c2ecf20Sopenharmony_ci		case 0: /* searching */
19548c2ecf20Sopenharmony_ci		case 1: /* first PLH detected */
19558c2ecf20Sopenharmony_ci		default:
19568c2ecf20Sopenharmony_ci			dprintk(FE_DEBUG, 1, "Demodulator searching ..");
19578c2ecf20Sopenharmony_ci			lock = 0;
19588c2ecf20Sopenharmony_ci			break;
19598c2ecf20Sopenharmony_ci		case 2: /* DVB-S2 mode */
19608c2ecf20Sopenharmony_ci		case 3: /* DVB-S1/legacy mode */
19618c2ecf20Sopenharmony_ci			reg = STV090x_READ_DEMOD(state, DSTATUS);
19628c2ecf20Sopenharmony_ci			lock = STV090x_GETFIELD_Px(reg, LOCK_DEFINITIF_FIELD);
19638c2ecf20Sopenharmony_ci			break;
19648c2ecf20Sopenharmony_ci		}
19658c2ecf20Sopenharmony_ci
19668c2ecf20Sopenharmony_ci		if (!lock)
19678c2ecf20Sopenharmony_ci			msleep(10);
19688c2ecf20Sopenharmony_ci		else
19698c2ecf20Sopenharmony_ci			dprintk(FE_DEBUG, 1, "Demodulator acquired LOCK");
19708c2ecf20Sopenharmony_ci
19718c2ecf20Sopenharmony_ci		timer += 10;
19728c2ecf20Sopenharmony_ci	}
19738c2ecf20Sopenharmony_ci	return lock;
19748c2ecf20Sopenharmony_ci}
19758c2ecf20Sopenharmony_ci
19768c2ecf20Sopenharmony_cistatic int stv090x_blind_search(struct stv090x_state *state)
19778c2ecf20Sopenharmony_ci{
19788c2ecf20Sopenharmony_ci	u32 agc2, reg, srate_coarse;
19798c2ecf20Sopenharmony_ci	s32 cpt_fail, agc2_ovflw, i;
19808c2ecf20Sopenharmony_ci	u8 k_ref, k_max, k_min;
19818c2ecf20Sopenharmony_ci	int coarse_fail = 0;
19828c2ecf20Sopenharmony_ci	int lock;
19838c2ecf20Sopenharmony_ci
19848c2ecf20Sopenharmony_ci	k_max = 110;
19858c2ecf20Sopenharmony_ci	k_min = 10;
19868c2ecf20Sopenharmony_ci
19878c2ecf20Sopenharmony_ci	agc2 = stv090x_get_agc2_min_level(state);
19888c2ecf20Sopenharmony_ci
19898c2ecf20Sopenharmony_ci	if (agc2 > STV090x_SEARCH_AGC2_TH(state->internal->dev_ver)) {
19908c2ecf20Sopenharmony_ci		lock = 0;
19918c2ecf20Sopenharmony_ci	} else {
19928c2ecf20Sopenharmony_ci
19938c2ecf20Sopenharmony_ci		if (state->internal->dev_ver <= 0x20) {
19948c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, CARCFG, 0xc4) < 0)
19958c2ecf20Sopenharmony_ci				goto err;
19968c2ecf20Sopenharmony_ci		} else {
19978c2ecf20Sopenharmony_ci			/* > Cut 3 */
19988c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, CARCFG, 0x06) < 0)
19998c2ecf20Sopenharmony_ci				goto err;
20008c2ecf20Sopenharmony_ci		}
20018c2ecf20Sopenharmony_ci
20028c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, RTCS2, 0x44) < 0)
20038c2ecf20Sopenharmony_ci			goto err;
20048c2ecf20Sopenharmony_ci
20058c2ecf20Sopenharmony_ci		if (state->internal->dev_ver >= 0x20) {
20068c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, EQUALCFG, 0x41) < 0)
20078c2ecf20Sopenharmony_ci				goto err;
20088c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, FFECFG, 0x41) < 0)
20098c2ecf20Sopenharmony_ci				goto err;
20108c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, VITSCALE, 0x82) < 0)
20118c2ecf20Sopenharmony_ci				goto err;
20128c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, VAVSRVIT, 0x00) < 0) /* set viterbi hysteresis */
20138c2ecf20Sopenharmony_ci				goto err;
20148c2ecf20Sopenharmony_ci		}
20158c2ecf20Sopenharmony_ci
20168c2ecf20Sopenharmony_ci		k_ref = k_max;
20178c2ecf20Sopenharmony_ci		do {
20188c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, KREFTMG, k_ref) < 0)
20198c2ecf20Sopenharmony_ci				goto err;
20208c2ecf20Sopenharmony_ci			if (stv090x_srate_srch_coarse(state) != 0) {
20218c2ecf20Sopenharmony_ci				srate_coarse = stv090x_srate_srch_fine(state);
20228c2ecf20Sopenharmony_ci				if (srate_coarse != 0) {
20238c2ecf20Sopenharmony_ci					stv090x_get_lock_tmg(state);
20248c2ecf20Sopenharmony_ci					lock = stv090x_get_dmdlock(state,
20258c2ecf20Sopenharmony_ci							state->DemodTimeout);
20268c2ecf20Sopenharmony_ci				} else {
20278c2ecf20Sopenharmony_ci					lock = 0;
20288c2ecf20Sopenharmony_ci				}
20298c2ecf20Sopenharmony_ci			} else {
20308c2ecf20Sopenharmony_ci				cpt_fail = 0;
20318c2ecf20Sopenharmony_ci				agc2_ovflw = 0;
20328c2ecf20Sopenharmony_ci				for (i = 0; i < 10; i++) {
20338c2ecf20Sopenharmony_ci					agc2 += (STV090x_READ_DEMOD(state, AGC2I1) << 8) |
20348c2ecf20Sopenharmony_ci						STV090x_READ_DEMOD(state, AGC2I0);
20358c2ecf20Sopenharmony_ci					if (agc2 >= 0xff00)
20368c2ecf20Sopenharmony_ci						agc2_ovflw++;
20378c2ecf20Sopenharmony_ci					reg = STV090x_READ_DEMOD(state, DSTATUS2);
20388c2ecf20Sopenharmony_ci					if ((STV090x_GETFIELD_Px(reg, CFR_OVERFLOW_FIELD) == 0x01) &&
20398c2ecf20Sopenharmony_ci					    (STV090x_GETFIELD_Px(reg, DEMOD_DELOCK_FIELD) == 0x01))
20408c2ecf20Sopenharmony_ci
20418c2ecf20Sopenharmony_ci						cpt_fail++;
20428c2ecf20Sopenharmony_ci				}
20438c2ecf20Sopenharmony_ci				if ((cpt_fail > 7) || (agc2_ovflw > 7))
20448c2ecf20Sopenharmony_ci					coarse_fail = 1;
20458c2ecf20Sopenharmony_ci
20468c2ecf20Sopenharmony_ci				lock = 0;
20478c2ecf20Sopenharmony_ci			}
20488c2ecf20Sopenharmony_ci			k_ref -= 20;
20498c2ecf20Sopenharmony_ci		} while ((k_ref >= k_min) && (!lock) && (!coarse_fail));
20508c2ecf20Sopenharmony_ci	}
20518c2ecf20Sopenharmony_ci
20528c2ecf20Sopenharmony_ci	return lock;
20538c2ecf20Sopenharmony_ci
20548c2ecf20Sopenharmony_cierr:
20558c2ecf20Sopenharmony_ci	dprintk(FE_ERROR, 1, "I/O error");
20568c2ecf20Sopenharmony_ci	return -1;
20578c2ecf20Sopenharmony_ci}
20588c2ecf20Sopenharmony_ci
20598c2ecf20Sopenharmony_cistatic int stv090x_chk_tmg(struct stv090x_state *state)
20608c2ecf20Sopenharmony_ci{
20618c2ecf20Sopenharmony_ci	u32 reg;
20628c2ecf20Sopenharmony_ci	s32 tmg_cpt = 0, i;
20638c2ecf20Sopenharmony_ci	u8 freq, tmg_thh, tmg_thl;
20648c2ecf20Sopenharmony_ci	int tmg_lock = 0;
20658c2ecf20Sopenharmony_ci
20668c2ecf20Sopenharmony_ci	freq = STV090x_READ_DEMOD(state, CARFREQ);
20678c2ecf20Sopenharmony_ci	tmg_thh = STV090x_READ_DEMOD(state, TMGTHRISE);
20688c2ecf20Sopenharmony_ci	tmg_thl = STV090x_READ_DEMOD(state, TMGTHFALL);
20698c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, TMGTHRISE, 0x20) < 0)
20708c2ecf20Sopenharmony_ci		goto err;
20718c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, TMGTHFALL, 0x00) < 0)
20728c2ecf20Sopenharmony_ci		goto err;
20738c2ecf20Sopenharmony_ci
20748c2ecf20Sopenharmony_ci	reg = STV090x_READ_DEMOD(state, DMDCFGMD);
20758c2ecf20Sopenharmony_ci	STV090x_SETFIELD_Px(reg, CFR_AUTOSCAN_FIELD, 0x00); /* stop carrier offset search */
20768c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0)
20778c2ecf20Sopenharmony_ci		goto err;
20788c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, RTC, 0x80) < 0)
20798c2ecf20Sopenharmony_ci		goto err;
20808c2ecf20Sopenharmony_ci
20818c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, RTCS2, 0x40) < 0)
20828c2ecf20Sopenharmony_ci		goto err;
20838c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x00) < 0)
20848c2ecf20Sopenharmony_ci		goto err;
20858c2ecf20Sopenharmony_ci
20868c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, CFRINIT1, 0x00) < 0) /* set car ofset to 0 */
20878c2ecf20Sopenharmony_ci		goto err;
20888c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, CFRINIT0, 0x00) < 0)
20898c2ecf20Sopenharmony_ci		goto err;
20908c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, AGC2REF, 0x65) < 0)
20918c2ecf20Sopenharmony_ci		goto err;
20928c2ecf20Sopenharmony_ci
20938c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x18) < 0) /* trigger acquisition */
20948c2ecf20Sopenharmony_ci		goto err;
20958c2ecf20Sopenharmony_ci	msleep(10);
20968c2ecf20Sopenharmony_ci
20978c2ecf20Sopenharmony_ci	for (i = 0; i < 10; i++) {
20988c2ecf20Sopenharmony_ci		reg = STV090x_READ_DEMOD(state, DSTATUS);
20998c2ecf20Sopenharmony_ci		if (STV090x_GETFIELD_Px(reg, TMGLOCK_QUALITY_FIELD) >= 2)
21008c2ecf20Sopenharmony_ci			tmg_cpt++;
21018c2ecf20Sopenharmony_ci		msleep(1);
21028c2ecf20Sopenharmony_ci	}
21038c2ecf20Sopenharmony_ci	if (tmg_cpt >= 3)
21048c2ecf20Sopenharmony_ci		tmg_lock = 1;
21058c2ecf20Sopenharmony_ci
21068c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, AGC2REF, 0x38) < 0)
21078c2ecf20Sopenharmony_ci		goto err;
21088c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, RTC, 0x88) < 0) /* DVB-S1 timing */
21098c2ecf20Sopenharmony_ci		goto err;
21108c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, RTCS2, 0x68) < 0) /* DVB-S2 timing */
21118c2ecf20Sopenharmony_ci		goto err;
21128c2ecf20Sopenharmony_ci
21138c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, CARFREQ, freq) < 0)
21148c2ecf20Sopenharmony_ci		goto err;
21158c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, TMGTHRISE, tmg_thh) < 0)
21168c2ecf20Sopenharmony_ci		goto err;
21178c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, TMGTHFALL, tmg_thl) < 0)
21188c2ecf20Sopenharmony_ci		goto err;
21198c2ecf20Sopenharmony_ci
21208c2ecf20Sopenharmony_ci	return	tmg_lock;
21218c2ecf20Sopenharmony_ci
21228c2ecf20Sopenharmony_cierr:
21238c2ecf20Sopenharmony_ci	dprintk(FE_ERROR, 1, "I/O error");
21248c2ecf20Sopenharmony_ci	return -1;
21258c2ecf20Sopenharmony_ci}
21268c2ecf20Sopenharmony_ci
21278c2ecf20Sopenharmony_cistatic int stv090x_get_coldlock(struct stv090x_state *state, s32 timeout_dmd)
21288c2ecf20Sopenharmony_ci{
21298c2ecf20Sopenharmony_ci	struct dvb_frontend *fe = &state->frontend;
21308c2ecf20Sopenharmony_ci
21318c2ecf20Sopenharmony_ci	u32 reg;
21328c2ecf20Sopenharmony_ci	s32 car_step, steps, cur_step, dir, freq, timeout_lock;
21338c2ecf20Sopenharmony_ci	int lock;
21348c2ecf20Sopenharmony_ci
21358c2ecf20Sopenharmony_ci	if (state->srate >= 10000000)
21368c2ecf20Sopenharmony_ci		timeout_lock = timeout_dmd / 3;
21378c2ecf20Sopenharmony_ci	else
21388c2ecf20Sopenharmony_ci		timeout_lock = timeout_dmd / 2;
21398c2ecf20Sopenharmony_ci
21408c2ecf20Sopenharmony_ci	lock = stv090x_get_dmdlock(state, timeout_lock); /* cold start wait */
21418c2ecf20Sopenharmony_ci	if (lock)
21428c2ecf20Sopenharmony_ci		return lock;
21438c2ecf20Sopenharmony_ci
21448c2ecf20Sopenharmony_ci	if (state->srate >= 10000000) {
21458c2ecf20Sopenharmony_ci		if (stv090x_chk_tmg(state)) {
21468c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1f) < 0)
21478c2ecf20Sopenharmony_ci				goto err;
21488c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x15) < 0)
21498c2ecf20Sopenharmony_ci				goto err;
21508c2ecf20Sopenharmony_ci			return stv090x_get_dmdlock(state, timeout_dmd);
21518c2ecf20Sopenharmony_ci		}
21528c2ecf20Sopenharmony_ci		return 0;
21538c2ecf20Sopenharmony_ci	}
21548c2ecf20Sopenharmony_ci
21558c2ecf20Sopenharmony_ci	if (state->srate <= 4000000)
21568c2ecf20Sopenharmony_ci		car_step = 1000;
21578c2ecf20Sopenharmony_ci	else if (state->srate <= 7000000)
21588c2ecf20Sopenharmony_ci		car_step = 2000;
21598c2ecf20Sopenharmony_ci	else if (state->srate <= 10000000)
21608c2ecf20Sopenharmony_ci		car_step = 3000;
21618c2ecf20Sopenharmony_ci	else
21628c2ecf20Sopenharmony_ci		car_step = 5000;
21638c2ecf20Sopenharmony_ci
21648c2ecf20Sopenharmony_ci	steps  = (state->search_range / 1000) / car_step;
21658c2ecf20Sopenharmony_ci	steps /= 2;
21668c2ecf20Sopenharmony_ci	steps  = 2 * (steps + 1);
21678c2ecf20Sopenharmony_ci	if (steps < 0)
21688c2ecf20Sopenharmony_ci		steps = 2;
21698c2ecf20Sopenharmony_ci	else if (steps > 12)
21708c2ecf20Sopenharmony_ci		steps = 12;
21718c2ecf20Sopenharmony_ci
21728c2ecf20Sopenharmony_ci	cur_step = 1;
21738c2ecf20Sopenharmony_ci	dir = 1;
21748c2ecf20Sopenharmony_ci
21758c2ecf20Sopenharmony_ci	freq = state->frequency;
21768c2ecf20Sopenharmony_ci	state->tuner_bw = stv090x_car_width(state->srate, state->rolloff) + state->srate;
21778c2ecf20Sopenharmony_ci	while ((cur_step <= steps) && (!lock)) {
21788c2ecf20Sopenharmony_ci		if (dir > 0)
21798c2ecf20Sopenharmony_ci			freq += cur_step * car_step;
21808c2ecf20Sopenharmony_ci		else
21818c2ecf20Sopenharmony_ci			freq -= cur_step * car_step;
21828c2ecf20Sopenharmony_ci
21838c2ecf20Sopenharmony_ci		/* Setup tuner */
21848c2ecf20Sopenharmony_ci		if (stv090x_i2c_gate_ctrl(state, 1) < 0)
21858c2ecf20Sopenharmony_ci			goto err;
21868c2ecf20Sopenharmony_ci
21878c2ecf20Sopenharmony_ci		if (state->config->tuner_set_frequency) {
21888c2ecf20Sopenharmony_ci			if (state->config->tuner_set_frequency(fe, freq) < 0)
21898c2ecf20Sopenharmony_ci				goto err_gateoff;
21908c2ecf20Sopenharmony_ci		}
21918c2ecf20Sopenharmony_ci
21928c2ecf20Sopenharmony_ci		if (state->config->tuner_set_bandwidth) {
21938c2ecf20Sopenharmony_ci			if (state->config->tuner_set_bandwidth(fe, state->tuner_bw) < 0)
21948c2ecf20Sopenharmony_ci				goto err_gateoff;
21958c2ecf20Sopenharmony_ci		}
21968c2ecf20Sopenharmony_ci
21978c2ecf20Sopenharmony_ci		if (stv090x_i2c_gate_ctrl(state, 0) < 0)
21988c2ecf20Sopenharmony_ci			goto err;
21998c2ecf20Sopenharmony_ci
22008c2ecf20Sopenharmony_ci		msleep(50);
22018c2ecf20Sopenharmony_ci
22028c2ecf20Sopenharmony_ci		if (stv090x_i2c_gate_ctrl(state, 1) < 0)
22038c2ecf20Sopenharmony_ci			goto err;
22048c2ecf20Sopenharmony_ci
22058c2ecf20Sopenharmony_ci		if (state->config->tuner_get_status) {
22068c2ecf20Sopenharmony_ci			if (state->config->tuner_get_status(fe, &reg) < 0)
22078c2ecf20Sopenharmony_ci				goto err_gateoff;
22088c2ecf20Sopenharmony_ci			if (reg)
22098c2ecf20Sopenharmony_ci				dprintk(FE_DEBUG, 1, "Tuner phase locked");
22108c2ecf20Sopenharmony_ci			else
22118c2ecf20Sopenharmony_ci				dprintk(FE_DEBUG, 1, "Tuner unlocked");
22128c2ecf20Sopenharmony_ci		}
22138c2ecf20Sopenharmony_ci
22148c2ecf20Sopenharmony_ci		if (stv090x_i2c_gate_ctrl(state, 0) < 0)
22158c2ecf20Sopenharmony_ci			goto err;
22168c2ecf20Sopenharmony_ci
22178c2ecf20Sopenharmony_ci		STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1c);
22188c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, CFRINIT1, 0x00) < 0)
22198c2ecf20Sopenharmony_ci			goto err;
22208c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, CFRINIT0, 0x00) < 0)
22218c2ecf20Sopenharmony_ci			goto err;
22228c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1f) < 0)
22238c2ecf20Sopenharmony_ci			goto err;
22248c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x15) < 0)
22258c2ecf20Sopenharmony_ci			goto err;
22268c2ecf20Sopenharmony_ci		lock = stv090x_get_dmdlock(state, (timeout_dmd / 3));
22278c2ecf20Sopenharmony_ci
22288c2ecf20Sopenharmony_ci		dir *= -1;
22298c2ecf20Sopenharmony_ci		cur_step++;
22308c2ecf20Sopenharmony_ci	}
22318c2ecf20Sopenharmony_ci
22328c2ecf20Sopenharmony_ci	return lock;
22338c2ecf20Sopenharmony_ci
22348c2ecf20Sopenharmony_cierr_gateoff:
22358c2ecf20Sopenharmony_ci	stv090x_i2c_gate_ctrl(state, 0);
22368c2ecf20Sopenharmony_cierr:
22378c2ecf20Sopenharmony_ci	dprintk(FE_ERROR, 1, "I/O error");
22388c2ecf20Sopenharmony_ci	return -1;
22398c2ecf20Sopenharmony_ci}
22408c2ecf20Sopenharmony_ci
22418c2ecf20Sopenharmony_cistatic int stv090x_get_loop_params(struct stv090x_state *state, s32 *freq_inc, s32 *timeout_sw, s32 *steps)
22428c2ecf20Sopenharmony_ci{
22438c2ecf20Sopenharmony_ci	s32 timeout, inc, steps_max, srate, car_max;
22448c2ecf20Sopenharmony_ci
22458c2ecf20Sopenharmony_ci	srate = state->srate;
22468c2ecf20Sopenharmony_ci	car_max = state->search_range / 1000;
22478c2ecf20Sopenharmony_ci	car_max += car_max / 10;
22488c2ecf20Sopenharmony_ci	car_max  = 65536 * (car_max / 2);
22498c2ecf20Sopenharmony_ci	car_max /= (state->internal->mclk / 1000);
22508c2ecf20Sopenharmony_ci
22518c2ecf20Sopenharmony_ci	if (car_max > 0x4000)
22528c2ecf20Sopenharmony_ci		car_max = 0x4000 ; /* maxcarrier should be<= +-1/4 Mclk */
22538c2ecf20Sopenharmony_ci
22548c2ecf20Sopenharmony_ci	inc  = srate;
22558c2ecf20Sopenharmony_ci	inc /= state->internal->mclk / 1000;
22568c2ecf20Sopenharmony_ci	inc *= 256;
22578c2ecf20Sopenharmony_ci	inc *= 256;
22588c2ecf20Sopenharmony_ci	inc /= 1000;
22598c2ecf20Sopenharmony_ci
22608c2ecf20Sopenharmony_ci	switch (state->search_mode) {
22618c2ecf20Sopenharmony_ci	case STV090x_SEARCH_DVBS1:
22628c2ecf20Sopenharmony_ci	case STV090x_SEARCH_DSS:
22638c2ecf20Sopenharmony_ci		inc *= 3; /* freq step = 3% of srate */
22648c2ecf20Sopenharmony_ci		timeout = 20;
22658c2ecf20Sopenharmony_ci		break;
22668c2ecf20Sopenharmony_ci
22678c2ecf20Sopenharmony_ci	case STV090x_SEARCH_DVBS2:
22688c2ecf20Sopenharmony_ci		inc *= 4;
22698c2ecf20Sopenharmony_ci		timeout = 25;
22708c2ecf20Sopenharmony_ci		break;
22718c2ecf20Sopenharmony_ci
22728c2ecf20Sopenharmony_ci	case STV090x_SEARCH_AUTO:
22738c2ecf20Sopenharmony_ci	default:
22748c2ecf20Sopenharmony_ci		inc *= 3;
22758c2ecf20Sopenharmony_ci		timeout = 25;
22768c2ecf20Sopenharmony_ci		break;
22778c2ecf20Sopenharmony_ci	}
22788c2ecf20Sopenharmony_ci	inc /= 100;
22798c2ecf20Sopenharmony_ci	if ((inc > car_max) || (inc < 0))
22808c2ecf20Sopenharmony_ci		inc = car_max / 2; /* increment <= 1/8 Mclk */
22818c2ecf20Sopenharmony_ci
22828c2ecf20Sopenharmony_ci	timeout *= 27500; /* 27.5 Msps reference */
22838c2ecf20Sopenharmony_ci	if (srate > 0)
22848c2ecf20Sopenharmony_ci		timeout /= (srate / 1000);
22858c2ecf20Sopenharmony_ci
22868c2ecf20Sopenharmony_ci	if ((timeout > 100) || (timeout < 0))
22878c2ecf20Sopenharmony_ci		timeout = 100;
22888c2ecf20Sopenharmony_ci
22898c2ecf20Sopenharmony_ci	steps_max = (car_max / inc) + 1; /* min steps = 3 */
22908c2ecf20Sopenharmony_ci	if ((steps_max > 100) || (steps_max < 0)) {
22918c2ecf20Sopenharmony_ci		steps_max = 100; /* max steps <= 100 */
22928c2ecf20Sopenharmony_ci		inc = car_max / steps_max;
22938c2ecf20Sopenharmony_ci	}
22948c2ecf20Sopenharmony_ci	*freq_inc = inc;
22958c2ecf20Sopenharmony_ci	*timeout_sw = timeout;
22968c2ecf20Sopenharmony_ci	*steps = steps_max;
22978c2ecf20Sopenharmony_ci
22988c2ecf20Sopenharmony_ci	return 0;
22998c2ecf20Sopenharmony_ci}
23008c2ecf20Sopenharmony_ci
23018c2ecf20Sopenharmony_cistatic int stv090x_chk_signal(struct stv090x_state *state)
23028c2ecf20Sopenharmony_ci{
23038c2ecf20Sopenharmony_ci	s32 offst_car, agc2, car_max;
23048c2ecf20Sopenharmony_ci	int no_signal;
23058c2ecf20Sopenharmony_ci
23068c2ecf20Sopenharmony_ci	offst_car  = STV090x_READ_DEMOD(state, CFR2) << 8;
23078c2ecf20Sopenharmony_ci	offst_car |= STV090x_READ_DEMOD(state, CFR1);
23088c2ecf20Sopenharmony_ci	offst_car = comp2(offst_car, 16);
23098c2ecf20Sopenharmony_ci
23108c2ecf20Sopenharmony_ci	agc2  = STV090x_READ_DEMOD(state, AGC2I1) << 8;
23118c2ecf20Sopenharmony_ci	agc2 |= STV090x_READ_DEMOD(state, AGC2I0);
23128c2ecf20Sopenharmony_ci	car_max = state->search_range / 1000;
23138c2ecf20Sopenharmony_ci
23148c2ecf20Sopenharmony_ci	car_max += (car_max / 10); /* 10% margin */
23158c2ecf20Sopenharmony_ci	car_max  = (65536 * car_max / 2);
23168c2ecf20Sopenharmony_ci	car_max /= state->internal->mclk / 1000;
23178c2ecf20Sopenharmony_ci
23188c2ecf20Sopenharmony_ci	if (car_max > 0x4000)
23198c2ecf20Sopenharmony_ci		car_max = 0x4000;
23208c2ecf20Sopenharmony_ci
23218c2ecf20Sopenharmony_ci	if ((agc2 > 0x2000) || (offst_car > 2 * car_max) || (offst_car < -2 * car_max)) {
23228c2ecf20Sopenharmony_ci		no_signal = 1;
23238c2ecf20Sopenharmony_ci		dprintk(FE_DEBUG, 1, "No Signal");
23248c2ecf20Sopenharmony_ci	} else {
23258c2ecf20Sopenharmony_ci		no_signal = 0;
23268c2ecf20Sopenharmony_ci		dprintk(FE_DEBUG, 1, "Found Signal");
23278c2ecf20Sopenharmony_ci	}
23288c2ecf20Sopenharmony_ci
23298c2ecf20Sopenharmony_ci	return no_signal;
23308c2ecf20Sopenharmony_ci}
23318c2ecf20Sopenharmony_ci
23328c2ecf20Sopenharmony_cistatic int stv090x_search_car_loop(struct stv090x_state *state, s32 inc, s32 timeout, int zigzag, s32 steps_max)
23338c2ecf20Sopenharmony_ci{
23348c2ecf20Sopenharmony_ci	int no_signal, lock = 0;
23358c2ecf20Sopenharmony_ci	s32 cpt_step = 0, offst_freq, car_max;
23368c2ecf20Sopenharmony_ci	u32 reg;
23378c2ecf20Sopenharmony_ci
23388c2ecf20Sopenharmony_ci	car_max  = state->search_range / 1000;
23398c2ecf20Sopenharmony_ci	car_max += (car_max / 10);
23408c2ecf20Sopenharmony_ci	car_max  = (65536 * car_max / 2);
23418c2ecf20Sopenharmony_ci	car_max /= (state->internal->mclk / 1000);
23428c2ecf20Sopenharmony_ci	if (car_max > 0x4000)
23438c2ecf20Sopenharmony_ci		car_max = 0x4000;
23448c2ecf20Sopenharmony_ci
23458c2ecf20Sopenharmony_ci	if (zigzag)
23468c2ecf20Sopenharmony_ci		offst_freq = 0;
23478c2ecf20Sopenharmony_ci	else
23488c2ecf20Sopenharmony_ci		offst_freq = -car_max + inc;
23498c2ecf20Sopenharmony_ci
23508c2ecf20Sopenharmony_ci	do {
23518c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1c) < 0)
23528c2ecf20Sopenharmony_ci			goto err;
23538c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, CFRINIT1, ((offst_freq / 256) & 0xff)) < 0)
23548c2ecf20Sopenharmony_ci			goto err;
23558c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, CFRINIT0, offst_freq & 0xff) < 0)
23568c2ecf20Sopenharmony_ci			goto err;
23578c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x18) < 0)
23588c2ecf20Sopenharmony_ci			goto err;
23598c2ecf20Sopenharmony_ci
23608c2ecf20Sopenharmony_ci		reg = STV090x_READ_DEMOD(state, PDELCTRL1);
23618c2ecf20Sopenharmony_ci		STV090x_SETFIELD_Px(reg, ALGOSWRST_FIELD, 0x1); /* stop DVB-S2 packet delin */
23628c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, PDELCTRL1, reg) < 0)
23638c2ecf20Sopenharmony_ci			goto err;
23648c2ecf20Sopenharmony_ci
23658c2ecf20Sopenharmony_ci		if (zigzag) {
23668c2ecf20Sopenharmony_ci			if (offst_freq >= 0)
23678c2ecf20Sopenharmony_ci				offst_freq = -offst_freq - 2 * inc;
23688c2ecf20Sopenharmony_ci			else
23698c2ecf20Sopenharmony_ci				offst_freq = -offst_freq;
23708c2ecf20Sopenharmony_ci		} else {
23718c2ecf20Sopenharmony_ci			offst_freq += 2 * inc;
23728c2ecf20Sopenharmony_ci		}
23738c2ecf20Sopenharmony_ci
23748c2ecf20Sopenharmony_ci		cpt_step++;
23758c2ecf20Sopenharmony_ci
23768c2ecf20Sopenharmony_ci		lock = stv090x_get_dmdlock(state, timeout);
23778c2ecf20Sopenharmony_ci		no_signal = stv090x_chk_signal(state);
23788c2ecf20Sopenharmony_ci
23798c2ecf20Sopenharmony_ci	} while ((!lock) &&
23808c2ecf20Sopenharmony_ci		 (!no_signal) &&
23818c2ecf20Sopenharmony_ci		  ((offst_freq - inc) < car_max) &&
23828c2ecf20Sopenharmony_ci		  ((offst_freq + inc) > -car_max) &&
23838c2ecf20Sopenharmony_ci		  (cpt_step < steps_max));
23848c2ecf20Sopenharmony_ci
23858c2ecf20Sopenharmony_ci	reg = STV090x_READ_DEMOD(state, PDELCTRL1);
23868c2ecf20Sopenharmony_ci	STV090x_SETFIELD_Px(reg, ALGOSWRST_FIELD, 0);
23878c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, PDELCTRL1, reg) < 0)
23888c2ecf20Sopenharmony_ci			goto err;
23898c2ecf20Sopenharmony_ci
23908c2ecf20Sopenharmony_ci	return lock;
23918c2ecf20Sopenharmony_cierr:
23928c2ecf20Sopenharmony_ci	dprintk(FE_ERROR, 1, "I/O error");
23938c2ecf20Sopenharmony_ci	return -1;
23948c2ecf20Sopenharmony_ci}
23958c2ecf20Sopenharmony_ci
23968c2ecf20Sopenharmony_cistatic int stv090x_sw_algo(struct stv090x_state *state)
23978c2ecf20Sopenharmony_ci{
23988c2ecf20Sopenharmony_ci	int no_signal, zigzag, lock = 0;
23998c2ecf20Sopenharmony_ci	u32 reg;
24008c2ecf20Sopenharmony_ci
24018c2ecf20Sopenharmony_ci	s32 dvbs2_fly_wheel;
24028c2ecf20Sopenharmony_ci	s32 inc, timeout_step, trials, steps_max;
24038c2ecf20Sopenharmony_ci
24048c2ecf20Sopenharmony_ci	/* get params */
24058c2ecf20Sopenharmony_ci	stv090x_get_loop_params(state, &inc, &timeout_step, &steps_max);
24068c2ecf20Sopenharmony_ci
24078c2ecf20Sopenharmony_ci	switch (state->search_mode) {
24088c2ecf20Sopenharmony_ci	case STV090x_SEARCH_DVBS1:
24098c2ecf20Sopenharmony_ci	case STV090x_SEARCH_DSS:
24108c2ecf20Sopenharmony_ci		/* accelerate the frequency detector */
24118c2ecf20Sopenharmony_ci		if (state->internal->dev_ver >= 0x20) {
24128c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x3B) < 0)
24138c2ecf20Sopenharmony_ci				goto err;
24148c2ecf20Sopenharmony_ci		}
24158c2ecf20Sopenharmony_ci
24168c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, DMDCFGMD, 0x49) < 0)
24178c2ecf20Sopenharmony_ci			goto err;
24188c2ecf20Sopenharmony_ci		zigzag = 0;
24198c2ecf20Sopenharmony_ci		break;
24208c2ecf20Sopenharmony_ci
24218c2ecf20Sopenharmony_ci	case STV090x_SEARCH_DVBS2:
24228c2ecf20Sopenharmony_ci		if (state->internal->dev_ver >= 0x20) {
24238c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, CORRELABS, 0x79) < 0)
24248c2ecf20Sopenharmony_ci				goto err;
24258c2ecf20Sopenharmony_ci		}
24268c2ecf20Sopenharmony_ci
24278c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, DMDCFGMD, 0x89) < 0)
24288c2ecf20Sopenharmony_ci			goto err;
24298c2ecf20Sopenharmony_ci		zigzag = 1;
24308c2ecf20Sopenharmony_ci		break;
24318c2ecf20Sopenharmony_ci
24328c2ecf20Sopenharmony_ci	case STV090x_SEARCH_AUTO:
24338c2ecf20Sopenharmony_ci	default:
24348c2ecf20Sopenharmony_ci		/* accelerate the frequency detector */
24358c2ecf20Sopenharmony_ci		if (state->internal->dev_ver >= 0x20) {
24368c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x3b) < 0)
24378c2ecf20Sopenharmony_ci				goto err;
24388c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, CORRELABS, 0x79) < 0)
24398c2ecf20Sopenharmony_ci				goto err;
24408c2ecf20Sopenharmony_ci		}
24418c2ecf20Sopenharmony_ci
24428c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, DMDCFGMD, 0xc9) < 0)
24438c2ecf20Sopenharmony_ci			goto err;
24448c2ecf20Sopenharmony_ci		zigzag = 0;
24458c2ecf20Sopenharmony_ci		break;
24468c2ecf20Sopenharmony_ci	}
24478c2ecf20Sopenharmony_ci
24488c2ecf20Sopenharmony_ci	trials = 0;
24498c2ecf20Sopenharmony_ci	do {
24508c2ecf20Sopenharmony_ci		lock = stv090x_search_car_loop(state, inc, timeout_step, zigzag, steps_max);
24518c2ecf20Sopenharmony_ci		no_signal = stv090x_chk_signal(state);
24528c2ecf20Sopenharmony_ci		trials++;
24538c2ecf20Sopenharmony_ci
24548c2ecf20Sopenharmony_ci		/*run the SW search 2 times maximum*/
24558c2ecf20Sopenharmony_ci		if (lock || no_signal || (trials == 2)) {
24568c2ecf20Sopenharmony_ci			/*Check if the demod is not losing lock in DVBS2*/
24578c2ecf20Sopenharmony_ci			if (state->internal->dev_ver >= 0x20) {
24588c2ecf20Sopenharmony_ci				if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x49) < 0)
24598c2ecf20Sopenharmony_ci					goto err;
24608c2ecf20Sopenharmony_ci				if (STV090x_WRITE_DEMOD(state, CORRELABS, 0x9e) < 0)
24618c2ecf20Sopenharmony_ci					goto err;
24628c2ecf20Sopenharmony_ci			}
24638c2ecf20Sopenharmony_ci
24648c2ecf20Sopenharmony_ci			reg = STV090x_READ_DEMOD(state, DMDSTATE);
24658c2ecf20Sopenharmony_ci			if ((lock) && (STV090x_GETFIELD_Px(reg, HEADER_MODE_FIELD) == STV090x_DVBS2)) {
24668c2ecf20Sopenharmony_ci				/*Check if the demod is not losing lock in DVBS2*/
24678c2ecf20Sopenharmony_ci				msleep(timeout_step);
24688c2ecf20Sopenharmony_ci				reg = STV090x_READ_DEMOD(state, DMDFLYW);
24698c2ecf20Sopenharmony_ci				dvbs2_fly_wheel = STV090x_GETFIELD_Px(reg, FLYWHEEL_CPT_FIELD);
24708c2ecf20Sopenharmony_ci				if (dvbs2_fly_wheel < 0xd) {	 /*if correct frames is decrementing */
24718c2ecf20Sopenharmony_ci					msleep(timeout_step);
24728c2ecf20Sopenharmony_ci					reg = STV090x_READ_DEMOD(state, DMDFLYW);
24738c2ecf20Sopenharmony_ci					dvbs2_fly_wheel = STV090x_GETFIELD_Px(reg, FLYWHEEL_CPT_FIELD);
24748c2ecf20Sopenharmony_ci				}
24758c2ecf20Sopenharmony_ci				if (dvbs2_fly_wheel < 0xd) {
24768c2ecf20Sopenharmony_ci					/*FALSE lock, The demod is losing lock */
24778c2ecf20Sopenharmony_ci					lock = 0;
24788c2ecf20Sopenharmony_ci					if (trials < 2) {
24798c2ecf20Sopenharmony_ci						if (state->internal->dev_ver >= 0x20) {
24808c2ecf20Sopenharmony_ci							if (STV090x_WRITE_DEMOD(state, CORRELABS, 0x79) < 0)
24818c2ecf20Sopenharmony_ci								goto err;
24828c2ecf20Sopenharmony_ci						}
24838c2ecf20Sopenharmony_ci
24848c2ecf20Sopenharmony_ci						if (STV090x_WRITE_DEMOD(state, DMDCFGMD, 0x89) < 0)
24858c2ecf20Sopenharmony_ci							goto err;
24868c2ecf20Sopenharmony_ci					}
24878c2ecf20Sopenharmony_ci				}
24888c2ecf20Sopenharmony_ci			}
24898c2ecf20Sopenharmony_ci		}
24908c2ecf20Sopenharmony_ci	} while ((!lock) && (trials < 2) && (!no_signal));
24918c2ecf20Sopenharmony_ci
24928c2ecf20Sopenharmony_ci	return lock;
24938c2ecf20Sopenharmony_cierr:
24948c2ecf20Sopenharmony_ci	dprintk(FE_ERROR, 1, "I/O error");
24958c2ecf20Sopenharmony_ci	return -1;
24968c2ecf20Sopenharmony_ci}
24978c2ecf20Sopenharmony_ci
24988c2ecf20Sopenharmony_cistatic enum stv090x_delsys stv090x_get_std(struct stv090x_state *state)
24998c2ecf20Sopenharmony_ci{
25008c2ecf20Sopenharmony_ci	u32 reg;
25018c2ecf20Sopenharmony_ci	enum stv090x_delsys delsys;
25028c2ecf20Sopenharmony_ci
25038c2ecf20Sopenharmony_ci	reg = STV090x_READ_DEMOD(state, DMDSTATE);
25048c2ecf20Sopenharmony_ci	if (STV090x_GETFIELD_Px(reg, HEADER_MODE_FIELD) == 2)
25058c2ecf20Sopenharmony_ci		delsys = STV090x_DVBS2;
25068c2ecf20Sopenharmony_ci	else if (STV090x_GETFIELD_Px(reg, HEADER_MODE_FIELD) == 3) {
25078c2ecf20Sopenharmony_ci		reg = STV090x_READ_DEMOD(state, FECM);
25088c2ecf20Sopenharmony_ci		if (STV090x_GETFIELD_Px(reg, DSS_DVB_FIELD) == 1)
25098c2ecf20Sopenharmony_ci			delsys = STV090x_DSS;
25108c2ecf20Sopenharmony_ci		else
25118c2ecf20Sopenharmony_ci			delsys = STV090x_DVBS1;
25128c2ecf20Sopenharmony_ci	} else {
25138c2ecf20Sopenharmony_ci		delsys = STV090x_ERROR;
25148c2ecf20Sopenharmony_ci	}
25158c2ecf20Sopenharmony_ci
25168c2ecf20Sopenharmony_ci	return delsys;
25178c2ecf20Sopenharmony_ci}
25188c2ecf20Sopenharmony_ci
25198c2ecf20Sopenharmony_ci/* in Hz */
25208c2ecf20Sopenharmony_cistatic s32 stv090x_get_car_freq(struct stv090x_state *state, u32 mclk)
25218c2ecf20Sopenharmony_ci{
25228c2ecf20Sopenharmony_ci	s32 derot, int_1, int_2, tmp_1, tmp_2;
25238c2ecf20Sopenharmony_ci
25248c2ecf20Sopenharmony_ci	derot  = STV090x_READ_DEMOD(state, CFR2) << 16;
25258c2ecf20Sopenharmony_ci	derot |= STV090x_READ_DEMOD(state, CFR1) <<  8;
25268c2ecf20Sopenharmony_ci	derot |= STV090x_READ_DEMOD(state, CFR0);
25278c2ecf20Sopenharmony_ci
25288c2ecf20Sopenharmony_ci	derot = comp2(derot, 24);
25298c2ecf20Sopenharmony_ci	int_1 = mclk >> 12;
25308c2ecf20Sopenharmony_ci	int_2 = derot >> 12;
25318c2ecf20Sopenharmony_ci
25328c2ecf20Sopenharmony_ci	/* carrier_frequency = MasterClock * Reg / 2^24 */
25338c2ecf20Sopenharmony_ci	tmp_1 = mclk % 0x1000;
25348c2ecf20Sopenharmony_ci	tmp_2 = derot % 0x1000;
25358c2ecf20Sopenharmony_ci
25368c2ecf20Sopenharmony_ci	derot = (int_1 * int_2) +
25378c2ecf20Sopenharmony_ci		((int_1 * tmp_2) >> 12) +
25388c2ecf20Sopenharmony_ci		((int_2 * tmp_1) >> 12);
25398c2ecf20Sopenharmony_ci
25408c2ecf20Sopenharmony_ci	return derot;
25418c2ecf20Sopenharmony_ci}
25428c2ecf20Sopenharmony_ci
25438c2ecf20Sopenharmony_cistatic int stv090x_get_viterbi(struct stv090x_state *state)
25448c2ecf20Sopenharmony_ci{
25458c2ecf20Sopenharmony_ci	u32 reg, rate;
25468c2ecf20Sopenharmony_ci
25478c2ecf20Sopenharmony_ci	reg = STV090x_READ_DEMOD(state, VITCURPUN);
25488c2ecf20Sopenharmony_ci	rate = STV090x_GETFIELD_Px(reg, VIT_CURPUN_FIELD);
25498c2ecf20Sopenharmony_ci
25508c2ecf20Sopenharmony_ci	switch (rate) {
25518c2ecf20Sopenharmony_ci	case 13:
25528c2ecf20Sopenharmony_ci		state->fec = STV090x_PR12;
25538c2ecf20Sopenharmony_ci		break;
25548c2ecf20Sopenharmony_ci
25558c2ecf20Sopenharmony_ci	case 18:
25568c2ecf20Sopenharmony_ci		state->fec = STV090x_PR23;
25578c2ecf20Sopenharmony_ci		break;
25588c2ecf20Sopenharmony_ci
25598c2ecf20Sopenharmony_ci	case 21:
25608c2ecf20Sopenharmony_ci		state->fec = STV090x_PR34;
25618c2ecf20Sopenharmony_ci		break;
25628c2ecf20Sopenharmony_ci
25638c2ecf20Sopenharmony_ci	case 24:
25648c2ecf20Sopenharmony_ci		state->fec = STV090x_PR56;
25658c2ecf20Sopenharmony_ci		break;
25668c2ecf20Sopenharmony_ci
25678c2ecf20Sopenharmony_ci	case 25:
25688c2ecf20Sopenharmony_ci		state->fec = STV090x_PR67;
25698c2ecf20Sopenharmony_ci		break;
25708c2ecf20Sopenharmony_ci
25718c2ecf20Sopenharmony_ci	case 26:
25728c2ecf20Sopenharmony_ci		state->fec = STV090x_PR78;
25738c2ecf20Sopenharmony_ci		break;
25748c2ecf20Sopenharmony_ci
25758c2ecf20Sopenharmony_ci	default:
25768c2ecf20Sopenharmony_ci		state->fec = STV090x_PRERR;
25778c2ecf20Sopenharmony_ci		break;
25788c2ecf20Sopenharmony_ci	}
25798c2ecf20Sopenharmony_ci
25808c2ecf20Sopenharmony_ci	return 0;
25818c2ecf20Sopenharmony_ci}
25828c2ecf20Sopenharmony_ci
25838c2ecf20Sopenharmony_cistatic enum stv090x_signal_state stv090x_get_sig_params(struct stv090x_state *state)
25848c2ecf20Sopenharmony_ci{
25858c2ecf20Sopenharmony_ci	struct dvb_frontend *fe = &state->frontend;
25868c2ecf20Sopenharmony_ci
25878c2ecf20Sopenharmony_ci	u8 tmg;
25888c2ecf20Sopenharmony_ci	u32 reg;
25898c2ecf20Sopenharmony_ci	s32 i = 0, offst_freq;
25908c2ecf20Sopenharmony_ci
25918c2ecf20Sopenharmony_ci	msleep(5);
25928c2ecf20Sopenharmony_ci
25938c2ecf20Sopenharmony_ci	if (state->algo == STV090x_BLIND_SEARCH) {
25948c2ecf20Sopenharmony_ci		tmg = STV090x_READ_DEMOD(state, TMGREG2);
25958c2ecf20Sopenharmony_ci		STV090x_WRITE_DEMOD(state, SFRSTEP, 0x5c);
25968c2ecf20Sopenharmony_ci		while ((i <= 50) && (tmg != 0) && (tmg != 0xff)) {
25978c2ecf20Sopenharmony_ci			tmg = STV090x_READ_DEMOD(state, TMGREG2);
25988c2ecf20Sopenharmony_ci			msleep(5);
25998c2ecf20Sopenharmony_ci			i += 5;
26008c2ecf20Sopenharmony_ci		}
26018c2ecf20Sopenharmony_ci	}
26028c2ecf20Sopenharmony_ci	state->delsys = stv090x_get_std(state);
26038c2ecf20Sopenharmony_ci
26048c2ecf20Sopenharmony_ci	if (stv090x_i2c_gate_ctrl(state, 1) < 0)
26058c2ecf20Sopenharmony_ci		goto err;
26068c2ecf20Sopenharmony_ci
26078c2ecf20Sopenharmony_ci	if (state->config->tuner_get_frequency) {
26088c2ecf20Sopenharmony_ci		if (state->config->tuner_get_frequency(fe, &state->frequency) < 0)
26098c2ecf20Sopenharmony_ci			goto err_gateoff;
26108c2ecf20Sopenharmony_ci	}
26118c2ecf20Sopenharmony_ci
26128c2ecf20Sopenharmony_ci	if (stv090x_i2c_gate_ctrl(state, 0) < 0)
26138c2ecf20Sopenharmony_ci		goto err;
26148c2ecf20Sopenharmony_ci
26158c2ecf20Sopenharmony_ci	offst_freq = stv090x_get_car_freq(state, state->internal->mclk) / 1000;
26168c2ecf20Sopenharmony_ci	state->frequency += offst_freq;
26178c2ecf20Sopenharmony_ci
26188c2ecf20Sopenharmony_ci	if (stv090x_get_viterbi(state) < 0)
26198c2ecf20Sopenharmony_ci		goto err;
26208c2ecf20Sopenharmony_ci
26218c2ecf20Sopenharmony_ci	reg = STV090x_READ_DEMOD(state, DMDMODCOD);
26228c2ecf20Sopenharmony_ci	state->modcod = STV090x_GETFIELD_Px(reg, DEMOD_MODCOD_FIELD);
26238c2ecf20Sopenharmony_ci	state->pilots = STV090x_GETFIELD_Px(reg, DEMOD_TYPE_FIELD) & 0x01;
26248c2ecf20Sopenharmony_ci	state->frame_len = STV090x_GETFIELD_Px(reg, DEMOD_TYPE_FIELD) >> 1;
26258c2ecf20Sopenharmony_ci	reg = STV090x_READ_DEMOD(state, TMGOBS);
26268c2ecf20Sopenharmony_ci	state->rolloff = STV090x_GETFIELD_Px(reg, ROLLOFF_STATUS_FIELD);
26278c2ecf20Sopenharmony_ci	reg = STV090x_READ_DEMOD(state, FECM);
26288c2ecf20Sopenharmony_ci	state->inversion = STV090x_GETFIELD_Px(reg, IQINV_FIELD);
26298c2ecf20Sopenharmony_ci
26308c2ecf20Sopenharmony_ci	if ((state->algo == STV090x_BLIND_SEARCH) || (state->srate < 10000000)) {
26318c2ecf20Sopenharmony_ci
26328c2ecf20Sopenharmony_ci		if (stv090x_i2c_gate_ctrl(state, 1) < 0)
26338c2ecf20Sopenharmony_ci			goto err;
26348c2ecf20Sopenharmony_ci
26358c2ecf20Sopenharmony_ci		if (state->config->tuner_get_frequency) {
26368c2ecf20Sopenharmony_ci			if (state->config->tuner_get_frequency(fe, &state->frequency) < 0)
26378c2ecf20Sopenharmony_ci				goto err_gateoff;
26388c2ecf20Sopenharmony_ci		}
26398c2ecf20Sopenharmony_ci
26408c2ecf20Sopenharmony_ci		if (stv090x_i2c_gate_ctrl(state, 0) < 0)
26418c2ecf20Sopenharmony_ci			goto err;
26428c2ecf20Sopenharmony_ci
26438c2ecf20Sopenharmony_ci		if (abs(offst_freq) <= ((state->search_range / 2000) + 500))
26448c2ecf20Sopenharmony_ci			return STV090x_RANGEOK;
26458c2ecf20Sopenharmony_ci		else if (abs(offst_freq) <= (stv090x_car_width(state->srate, state->rolloff) / 2000))
26468c2ecf20Sopenharmony_ci			return STV090x_RANGEOK;
26478c2ecf20Sopenharmony_ci	} else {
26488c2ecf20Sopenharmony_ci		if (abs(offst_freq) <= ((state->search_range / 2000) + 500))
26498c2ecf20Sopenharmony_ci			return STV090x_RANGEOK;
26508c2ecf20Sopenharmony_ci	}
26518c2ecf20Sopenharmony_ci
26528c2ecf20Sopenharmony_ci	return STV090x_OUTOFRANGE;
26538c2ecf20Sopenharmony_ci
26548c2ecf20Sopenharmony_cierr_gateoff:
26558c2ecf20Sopenharmony_ci	stv090x_i2c_gate_ctrl(state, 0);
26568c2ecf20Sopenharmony_cierr:
26578c2ecf20Sopenharmony_ci	dprintk(FE_ERROR, 1, "I/O error");
26588c2ecf20Sopenharmony_ci	return -1;
26598c2ecf20Sopenharmony_ci}
26608c2ecf20Sopenharmony_ci
26618c2ecf20Sopenharmony_cistatic u32 stv090x_get_tmgoffst(struct stv090x_state *state, u32 srate)
26628c2ecf20Sopenharmony_ci{
26638c2ecf20Sopenharmony_ci	s32 offst_tmg;
26648c2ecf20Sopenharmony_ci
26658c2ecf20Sopenharmony_ci	offst_tmg  = STV090x_READ_DEMOD(state, TMGREG2) << 16;
26668c2ecf20Sopenharmony_ci	offst_tmg |= STV090x_READ_DEMOD(state, TMGREG1) <<  8;
26678c2ecf20Sopenharmony_ci	offst_tmg |= STV090x_READ_DEMOD(state, TMGREG0);
26688c2ecf20Sopenharmony_ci
26698c2ecf20Sopenharmony_ci	offst_tmg = comp2(offst_tmg, 24); /* 2's complement */
26708c2ecf20Sopenharmony_ci	if (!offst_tmg)
26718c2ecf20Sopenharmony_ci		offst_tmg = 1;
26728c2ecf20Sopenharmony_ci
26738c2ecf20Sopenharmony_ci	offst_tmg  = ((s32) srate * 10) / ((s32) 0x1000000 / offst_tmg);
26748c2ecf20Sopenharmony_ci	offst_tmg /= 320;
26758c2ecf20Sopenharmony_ci
26768c2ecf20Sopenharmony_ci	return offst_tmg;
26778c2ecf20Sopenharmony_ci}
26788c2ecf20Sopenharmony_ci
26798c2ecf20Sopenharmony_cistatic u8 stv090x_optimize_carloop(struct stv090x_state *state, enum stv090x_modcod modcod, s32 pilots)
26808c2ecf20Sopenharmony_ci{
26818c2ecf20Sopenharmony_ci	u8 aclc = 0x29;
26828c2ecf20Sopenharmony_ci	s32 i;
26838c2ecf20Sopenharmony_ci	struct stv090x_long_frame_crloop *car_loop, *car_loop_qpsk_low, *car_loop_apsk_low;
26848c2ecf20Sopenharmony_ci
26858c2ecf20Sopenharmony_ci	if (state->internal->dev_ver == 0x20) {
26868c2ecf20Sopenharmony_ci		car_loop		= stv090x_s2_crl_cut20;
26878c2ecf20Sopenharmony_ci		car_loop_qpsk_low	= stv090x_s2_lowqpsk_crl_cut20;
26888c2ecf20Sopenharmony_ci		car_loop_apsk_low	= stv090x_s2_apsk_crl_cut20;
26898c2ecf20Sopenharmony_ci	} else {
26908c2ecf20Sopenharmony_ci		/* >= Cut 3 */
26918c2ecf20Sopenharmony_ci		car_loop		= stv090x_s2_crl_cut30;
26928c2ecf20Sopenharmony_ci		car_loop_qpsk_low	= stv090x_s2_lowqpsk_crl_cut30;
26938c2ecf20Sopenharmony_ci		car_loop_apsk_low	= stv090x_s2_apsk_crl_cut30;
26948c2ecf20Sopenharmony_ci	}
26958c2ecf20Sopenharmony_ci
26968c2ecf20Sopenharmony_ci	if (modcod < STV090x_QPSK_12) {
26978c2ecf20Sopenharmony_ci		i = 0;
26988c2ecf20Sopenharmony_ci		while ((i < 3) && (modcod != car_loop_qpsk_low[i].modcod))
26998c2ecf20Sopenharmony_ci			i++;
27008c2ecf20Sopenharmony_ci
27018c2ecf20Sopenharmony_ci		if (i >= 3)
27028c2ecf20Sopenharmony_ci			i = 2;
27038c2ecf20Sopenharmony_ci
27048c2ecf20Sopenharmony_ci	} else {
27058c2ecf20Sopenharmony_ci		i = 0;
27068c2ecf20Sopenharmony_ci		while ((i < 14) && (modcod != car_loop[i].modcod))
27078c2ecf20Sopenharmony_ci			i++;
27088c2ecf20Sopenharmony_ci
27098c2ecf20Sopenharmony_ci		if (i >= 14) {
27108c2ecf20Sopenharmony_ci			i = 0;
27118c2ecf20Sopenharmony_ci			while ((i < 11) && (modcod != car_loop_apsk_low[i].modcod))
27128c2ecf20Sopenharmony_ci				i++;
27138c2ecf20Sopenharmony_ci
27148c2ecf20Sopenharmony_ci			if (i >= 11)
27158c2ecf20Sopenharmony_ci				i = 10;
27168c2ecf20Sopenharmony_ci		}
27178c2ecf20Sopenharmony_ci	}
27188c2ecf20Sopenharmony_ci
27198c2ecf20Sopenharmony_ci	if (modcod <= STV090x_QPSK_25) {
27208c2ecf20Sopenharmony_ci		if (pilots) {
27218c2ecf20Sopenharmony_ci			if (state->srate <= 3000000)
27228c2ecf20Sopenharmony_ci				aclc = car_loop_qpsk_low[i].crl_pilots_on_2;
27238c2ecf20Sopenharmony_ci			else if (state->srate <= 7000000)
27248c2ecf20Sopenharmony_ci				aclc = car_loop_qpsk_low[i].crl_pilots_on_5;
27258c2ecf20Sopenharmony_ci			else if (state->srate <= 15000000)
27268c2ecf20Sopenharmony_ci				aclc = car_loop_qpsk_low[i].crl_pilots_on_10;
27278c2ecf20Sopenharmony_ci			else if (state->srate <= 25000000)
27288c2ecf20Sopenharmony_ci				aclc = car_loop_qpsk_low[i].crl_pilots_on_20;
27298c2ecf20Sopenharmony_ci			else
27308c2ecf20Sopenharmony_ci				aclc = car_loop_qpsk_low[i].crl_pilots_on_30;
27318c2ecf20Sopenharmony_ci		} else {
27328c2ecf20Sopenharmony_ci			if (state->srate <= 3000000)
27338c2ecf20Sopenharmony_ci				aclc = car_loop_qpsk_low[i].crl_pilots_off_2;
27348c2ecf20Sopenharmony_ci			else if (state->srate <= 7000000)
27358c2ecf20Sopenharmony_ci				aclc = car_loop_qpsk_low[i].crl_pilots_off_5;
27368c2ecf20Sopenharmony_ci			else if (state->srate <= 15000000)
27378c2ecf20Sopenharmony_ci				aclc = car_loop_qpsk_low[i].crl_pilots_off_10;
27388c2ecf20Sopenharmony_ci			else if (state->srate <= 25000000)
27398c2ecf20Sopenharmony_ci				aclc = car_loop_qpsk_low[i].crl_pilots_off_20;
27408c2ecf20Sopenharmony_ci			else
27418c2ecf20Sopenharmony_ci				aclc = car_loop_qpsk_low[i].crl_pilots_off_30;
27428c2ecf20Sopenharmony_ci		}
27438c2ecf20Sopenharmony_ci
27448c2ecf20Sopenharmony_ci	} else if (modcod <= STV090x_8PSK_910) {
27458c2ecf20Sopenharmony_ci		if (pilots) {
27468c2ecf20Sopenharmony_ci			if (state->srate <= 3000000)
27478c2ecf20Sopenharmony_ci				aclc = car_loop[i].crl_pilots_on_2;
27488c2ecf20Sopenharmony_ci			else if (state->srate <= 7000000)
27498c2ecf20Sopenharmony_ci				aclc = car_loop[i].crl_pilots_on_5;
27508c2ecf20Sopenharmony_ci			else if (state->srate <= 15000000)
27518c2ecf20Sopenharmony_ci				aclc = car_loop[i].crl_pilots_on_10;
27528c2ecf20Sopenharmony_ci			else if (state->srate <= 25000000)
27538c2ecf20Sopenharmony_ci				aclc = car_loop[i].crl_pilots_on_20;
27548c2ecf20Sopenharmony_ci			else
27558c2ecf20Sopenharmony_ci				aclc = car_loop[i].crl_pilots_on_30;
27568c2ecf20Sopenharmony_ci		} else {
27578c2ecf20Sopenharmony_ci			if (state->srate <= 3000000)
27588c2ecf20Sopenharmony_ci				aclc = car_loop[i].crl_pilots_off_2;
27598c2ecf20Sopenharmony_ci			else if (state->srate <= 7000000)
27608c2ecf20Sopenharmony_ci				aclc = car_loop[i].crl_pilots_off_5;
27618c2ecf20Sopenharmony_ci			else if (state->srate <= 15000000)
27628c2ecf20Sopenharmony_ci				aclc = car_loop[i].crl_pilots_off_10;
27638c2ecf20Sopenharmony_ci			else if (state->srate <= 25000000)
27648c2ecf20Sopenharmony_ci				aclc = car_loop[i].crl_pilots_off_20;
27658c2ecf20Sopenharmony_ci			else
27668c2ecf20Sopenharmony_ci				aclc = car_loop[i].crl_pilots_off_30;
27678c2ecf20Sopenharmony_ci		}
27688c2ecf20Sopenharmony_ci	} else { /* 16APSK and 32APSK */
27698c2ecf20Sopenharmony_ci		/*
27708c2ecf20Sopenharmony_ci		 * This should never happen in practice, except if
27718c2ecf20Sopenharmony_ci		 * something is really wrong at the car_loop table.
27728c2ecf20Sopenharmony_ci		 */
27738c2ecf20Sopenharmony_ci		if (i >= 11)
27748c2ecf20Sopenharmony_ci			i = 10;
27758c2ecf20Sopenharmony_ci		if (state->srate <= 3000000)
27768c2ecf20Sopenharmony_ci			aclc = car_loop_apsk_low[i].crl_pilots_on_2;
27778c2ecf20Sopenharmony_ci		else if (state->srate <= 7000000)
27788c2ecf20Sopenharmony_ci			aclc = car_loop_apsk_low[i].crl_pilots_on_5;
27798c2ecf20Sopenharmony_ci		else if (state->srate <= 15000000)
27808c2ecf20Sopenharmony_ci			aclc = car_loop_apsk_low[i].crl_pilots_on_10;
27818c2ecf20Sopenharmony_ci		else if (state->srate <= 25000000)
27828c2ecf20Sopenharmony_ci			aclc = car_loop_apsk_low[i].crl_pilots_on_20;
27838c2ecf20Sopenharmony_ci		else
27848c2ecf20Sopenharmony_ci			aclc = car_loop_apsk_low[i].crl_pilots_on_30;
27858c2ecf20Sopenharmony_ci	}
27868c2ecf20Sopenharmony_ci
27878c2ecf20Sopenharmony_ci	return aclc;
27888c2ecf20Sopenharmony_ci}
27898c2ecf20Sopenharmony_ci
27908c2ecf20Sopenharmony_cistatic u8 stv090x_optimize_carloop_short(struct stv090x_state *state)
27918c2ecf20Sopenharmony_ci{
27928c2ecf20Sopenharmony_ci	struct stv090x_short_frame_crloop *short_crl = NULL;
27938c2ecf20Sopenharmony_ci	s32 index = 0;
27948c2ecf20Sopenharmony_ci	u8 aclc = 0x0b;
27958c2ecf20Sopenharmony_ci
27968c2ecf20Sopenharmony_ci	switch (state->modulation) {
27978c2ecf20Sopenharmony_ci	case STV090x_QPSK:
27988c2ecf20Sopenharmony_ci	default:
27998c2ecf20Sopenharmony_ci		index = 0;
28008c2ecf20Sopenharmony_ci		break;
28018c2ecf20Sopenharmony_ci	case STV090x_8PSK:
28028c2ecf20Sopenharmony_ci		index = 1;
28038c2ecf20Sopenharmony_ci		break;
28048c2ecf20Sopenharmony_ci	case STV090x_16APSK:
28058c2ecf20Sopenharmony_ci		index = 2;
28068c2ecf20Sopenharmony_ci		break;
28078c2ecf20Sopenharmony_ci	case STV090x_32APSK:
28088c2ecf20Sopenharmony_ci		index = 3;
28098c2ecf20Sopenharmony_ci		break;
28108c2ecf20Sopenharmony_ci	}
28118c2ecf20Sopenharmony_ci
28128c2ecf20Sopenharmony_ci	if (state->internal->dev_ver >= 0x30) {
28138c2ecf20Sopenharmony_ci		/* Cut 3.0 and up */
28148c2ecf20Sopenharmony_ci		short_crl = stv090x_s2_short_crl_cut30;
28158c2ecf20Sopenharmony_ci	} else {
28168c2ecf20Sopenharmony_ci		/* Cut 2.0 and up: we don't support cuts older than 2.0 */
28178c2ecf20Sopenharmony_ci		short_crl = stv090x_s2_short_crl_cut20;
28188c2ecf20Sopenharmony_ci	}
28198c2ecf20Sopenharmony_ci
28208c2ecf20Sopenharmony_ci	if (state->srate <= 3000000)
28218c2ecf20Sopenharmony_ci		aclc = short_crl[index].crl_2;
28228c2ecf20Sopenharmony_ci	else if (state->srate <= 7000000)
28238c2ecf20Sopenharmony_ci		aclc = short_crl[index].crl_5;
28248c2ecf20Sopenharmony_ci	else if (state->srate <= 15000000)
28258c2ecf20Sopenharmony_ci		aclc = short_crl[index].crl_10;
28268c2ecf20Sopenharmony_ci	else if (state->srate <= 25000000)
28278c2ecf20Sopenharmony_ci		aclc = short_crl[index].crl_20;
28288c2ecf20Sopenharmony_ci	else
28298c2ecf20Sopenharmony_ci		aclc = short_crl[index].crl_30;
28308c2ecf20Sopenharmony_ci
28318c2ecf20Sopenharmony_ci	return aclc;
28328c2ecf20Sopenharmony_ci}
28338c2ecf20Sopenharmony_ci
28348c2ecf20Sopenharmony_cistatic int stv090x_optimize_track(struct stv090x_state *state)
28358c2ecf20Sopenharmony_ci{
28368c2ecf20Sopenharmony_ci	struct dvb_frontend *fe = &state->frontend;
28378c2ecf20Sopenharmony_ci
28388c2ecf20Sopenharmony_ci	enum stv090x_modcod modcod;
28398c2ecf20Sopenharmony_ci
28408c2ecf20Sopenharmony_ci	s32 srate, pilots, aclc, f_1, f_0, i = 0, blind_tune = 0;
28418c2ecf20Sopenharmony_ci	u32 reg;
28428c2ecf20Sopenharmony_ci
28438c2ecf20Sopenharmony_ci	srate  = stv090x_get_srate(state, state->internal->mclk);
28448c2ecf20Sopenharmony_ci	srate += stv090x_get_tmgoffst(state, srate);
28458c2ecf20Sopenharmony_ci
28468c2ecf20Sopenharmony_ci	switch (state->delsys) {
28478c2ecf20Sopenharmony_ci	case STV090x_DVBS1:
28488c2ecf20Sopenharmony_ci	case STV090x_DSS:
28498c2ecf20Sopenharmony_ci		if (state->search_mode == STV090x_SEARCH_AUTO) {
28508c2ecf20Sopenharmony_ci			reg = STV090x_READ_DEMOD(state, DMDCFGMD);
28518c2ecf20Sopenharmony_ci			STV090x_SETFIELD_Px(reg, DVBS1_ENABLE_FIELD, 1);
28528c2ecf20Sopenharmony_ci			STV090x_SETFIELD_Px(reg, DVBS2_ENABLE_FIELD, 0);
28538c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0)
28548c2ecf20Sopenharmony_ci				goto err;
28558c2ecf20Sopenharmony_ci		}
28568c2ecf20Sopenharmony_ci		reg = STV090x_READ_DEMOD(state, DEMOD);
28578c2ecf20Sopenharmony_ci		STV090x_SETFIELD_Px(reg, ROLLOFF_CONTROL_FIELD, state->rolloff);
28588c2ecf20Sopenharmony_ci		STV090x_SETFIELD_Px(reg, MANUAL_SXROLLOFF_FIELD, 0x01);
28598c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, DEMOD, reg) < 0)
28608c2ecf20Sopenharmony_ci			goto err;
28618c2ecf20Sopenharmony_ci
28628c2ecf20Sopenharmony_ci		if (state->internal->dev_ver >= 0x30) {
28638c2ecf20Sopenharmony_ci			if (stv090x_get_viterbi(state) < 0)
28648c2ecf20Sopenharmony_ci				goto err;
28658c2ecf20Sopenharmony_ci
28668c2ecf20Sopenharmony_ci			if (state->fec == STV090x_PR12) {
28678c2ecf20Sopenharmony_ci				if (STV090x_WRITE_DEMOD(state, GAUSSR0, 0x98) < 0)
28688c2ecf20Sopenharmony_ci					goto err;
28698c2ecf20Sopenharmony_ci				if (STV090x_WRITE_DEMOD(state, CCIR0, 0x18) < 0)
28708c2ecf20Sopenharmony_ci					goto err;
28718c2ecf20Sopenharmony_ci			} else {
28728c2ecf20Sopenharmony_ci				if (STV090x_WRITE_DEMOD(state, GAUSSR0, 0x18) < 0)
28738c2ecf20Sopenharmony_ci					goto err;
28748c2ecf20Sopenharmony_ci				if (STV090x_WRITE_DEMOD(state, CCIR0, 0x18) < 0)
28758c2ecf20Sopenharmony_ci					goto err;
28768c2ecf20Sopenharmony_ci			}
28778c2ecf20Sopenharmony_ci		}
28788c2ecf20Sopenharmony_ci
28798c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, ERRCTRL1, 0x75) < 0)
28808c2ecf20Sopenharmony_ci			goto err;
28818c2ecf20Sopenharmony_ci		break;
28828c2ecf20Sopenharmony_ci
28838c2ecf20Sopenharmony_ci	case STV090x_DVBS2:
28848c2ecf20Sopenharmony_ci		reg = STV090x_READ_DEMOD(state, DMDCFGMD);
28858c2ecf20Sopenharmony_ci		STV090x_SETFIELD_Px(reg, DVBS1_ENABLE_FIELD, 0);
28868c2ecf20Sopenharmony_ci		STV090x_SETFIELD_Px(reg, DVBS2_ENABLE_FIELD, 1);
28878c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0)
28888c2ecf20Sopenharmony_ci			goto err;
28898c2ecf20Sopenharmony_ci		if (state->internal->dev_ver >= 0x30) {
28908c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, ACLC, 0) < 0)
28918c2ecf20Sopenharmony_ci				goto err;
28928c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, BCLC, 0) < 0)
28938c2ecf20Sopenharmony_ci				goto err;
28948c2ecf20Sopenharmony_ci		}
28958c2ecf20Sopenharmony_ci		if (state->frame_len == STV090x_LONG_FRAME) {
28968c2ecf20Sopenharmony_ci			reg = STV090x_READ_DEMOD(state, DMDMODCOD);
28978c2ecf20Sopenharmony_ci			modcod = STV090x_GETFIELD_Px(reg, DEMOD_MODCOD_FIELD);
28988c2ecf20Sopenharmony_ci			pilots = STV090x_GETFIELD_Px(reg, DEMOD_TYPE_FIELD) & 0x01;
28998c2ecf20Sopenharmony_ci			aclc = stv090x_optimize_carloop(state, modcod, pilots);
29008c2ecf20Sopenharmony_ci			if (modcod <= STV090x_QPSK_910) {
29018c2ecf20Sopenharmony_ci				STV090x_WRITE_DEMOD(state, ACLC2S2Q, aclc);
29028c2ecf20Sopenharmony_ci			} else if (modcod <= STV090x_8PSK_910) {
29038c2ecf20Sopenharmony_ci				if (STV090x_WRITE_DEMOD(state, ACLC2S2Q, 0x2a) < 0)
29048c2ecf20Sopenharmony_ci					goto err;
29058c2ecf20Sopenharmony_ci				if (STV090x_WRITE_DEMOD(state, ACLC2S28, aclc) < 0)
29068c2ecf20Sopenharmony_ci					goto err;
29078c2ecf20Sopenharmony_ci			}
29088c2ecf20Sopenharmony_ci			if ((state->demod_mode == STV090x_SINGLE) && (modcod > STV090x_8PSK_910)) {
29098c2ecf20Sopenharmony_ci				if (modcod <= STV090x_16APSK_910) {
29108c2ecf20Sopenharmony_ci					if (STV090x_WRITE_DEMOD(state, ACLC2S2Q, 0x2a) < 0)
29118c2ecf20Sopenharmony_ci						goto err;
29128c2ecf20Sopenharmony_ci					if (STV090x_WRITE_DEMOD(state, ACLC2S216A, aclc) < 0)
29138c2ecf20Sopenharmony_ci						goto err;
29148c2ecf20Sopenharmony_ci				} else {
29158c2ecf20Sopenharmony_ci					if (STV090x_WRITE_DEMOD(state, ACLC2S2Q, 0x2a) < 0)
29168c2ecf20Sopenharmony_ci						goto err;
29178c2ecf20Sopenharmony_ci					if (STV090x_WRITE_DEMOD(state, ACLC2S232A, aclc) < 0)
29188c2ecf20Sopenharmony_ci						goto err;
29198c2ecf20Sopenharmony_ci				}
29208c2ecf20Sopenharmony_ci			}
29218c2ecf20Sopenharmony_ci		} else {
29228c2ecf20Sopenharmony_ci			/*Carrier loop setting for short frame*/
29238c2ecf20Sopenharmony_ci			aclc = stv090x_optimize_carloop_short(state);
29248c2ecf20Sopenharmony_ci			if (state->modulation == STV090x_QPSK) {
29258c2ecf20Sopenharmony_ci				if (STV090x_WRITE_DEMOD(state, ACLC2S2Q, aclc) < 0)
29268c2ecf20Sopenharmony_ci					goto err;
29278c2ecf20Sopenharmony_ci			} else if (state->modulation == STV090x_8PSK) {
29288c2ecf20Sopenharmony_ci				if (STV090x_WRITE_DEMOD(state, ACLC2S2Q, 0x2a) < 0)
29298c2ecf20Sopenharmony_ci					goto err;
29308c2ecf20Sopenharmony_ci				if (STV090x_WRITE_DEMOD(state, ACLC2S28, aclc) < 0)
29318c2ecf20Sopenharmony_ci					goto err;
29328c2ecf20Sopenharmony_ci			} else if (state->modulation == STV090x_16APSK) {
29338c2ecf20Sopenharmony_ci				if (STV090x_WRITE_DEMOD(state, ACLC2S2Q, 0x2a) < 0)
29348c2ecf20Sopenharmony_ci					goto err;
29358c2ecf20Sopenharmony_ci				if (STV090x_WRITE_DEMOD(state, ACLC2S216A, aclc) < 0)
29368c2ecf20Sopenharmony_ci					goto err;
29378c2ecf20Sopenharmony_ci			} else if (state->modulation == STV090x_32APSK)  {
29388c2ecf20Sopenharmony_ci				if (STV090x_WRITE_DEMOD(state, ACLC2S2Q, 0x2a) < 0)
29398c2ecf20Sopenharmony_ci					goto err;
29408c2ecf20Sopenharmony_ci				if (STV090x_WRITE_DEMOD(state, ACLC2S232A, aclc) < 0)
29418c2ecf20Sopenharmony_ci					goto err;
29428c2ecf20Sopenharmony_ci			}
29438c2ecf20Sopenharmony_ci		}
29448c2ecf20Sopenharmony_ci
29458c2ecf20Sopenharmony_ci		STV090x_WRITE_DEMOD(state, ERRCTRL1, 0x67); /* PER */
29468c2ecf20Sopenharmony_ci		break;
29478c2ecf20Sopenharmony_ci
29488c2ecf20Sopenharmony_ci	case STV090x_ERROR:
29498c2ecf20Sopenharmony_ci	default:
29508c2ecf20Sopenharmony_ci		reg = STV090x_READ_DEMOD(state, DMDCFGMD);
29518c2ecf20Sopenharmony_ci		STV090x_SETFIELD_Px(reg, DVBS1_ENABLE_FIELD, 1);
29528c2ecf20Sopenharmony_ci		STV090x_SETFIELD_Px(reg, DVBS2_ENABLE_FIELD, 1);
29538c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0)
29548c2ecf20Sopenharmony_ci			goto err;
29558c2ecf20Sopenharmony_ci		break;
29568c2ecf20Sopenharmony_ci	}
29578c2ecf20Sopenharmony_ci
29588c2ecf20Sopenharmony_ci	f_1 = STV090x_READ_DEMOD(state, CFR2);
29598c2ecf20Sopenharmony_ci	f_0 = STV090x_READ_DEMOD(state, CFR1);
29608c2ecf20Sopenharmony_ci	reg = STV090x_READ_DEMOD(state, TMGOBS);
29618c2ecf20Sopenharmony_ci
29628c2ecf20Sopenharmony_ci	if (state->algo == STV090x_BLIND_SEARCH) {
29638c2ecf20Sopenharmony_ci		STV090x_WRITE_DEMOD(state, SFRSTEP, 0x00);
29648c2ecf20Sopenharmony_ci		reg = STV090x_READ_DEMOD(state, DMDCFGMD);
29658c2ecf20Sopenharmony_ci		STV090x_SETFIELD_Px(reg, SCAN_ENABLE_FIELD, 0x00);
29668c2ecf20Sopenharmony_ci		STV090x_SETFIELD_Px(reg, CFR_AUTOSCAN_FIELD, 0x00);
29678c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0)
29688c2ecf20Sopenharmony_ci			goto err;
29698c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, TMGCFG2, 0xc1) < 0)
29708c2ecf20Sopenharmony_ci			goto err;
29718c2ecf20Sopenharmony_ci
29728c2ecf20Sopenharmony_ci		if (stv090x_set_srate(state, srate) < 0)
29738c2ecf20Sopenharmony_ci			goto err;
29748c2ecf20Sopenharmony_ci		blind_tune = 1;
29758c2ecf20Sopenharmony_ci
29768c2ecf20Sopenharmony_ci		if (stv090x_dvbs_track_crl(state) < 0)
29778c2ecf20Sopenharmony_ci			goto err;
29788c2ecf20Sopenharmony_ci	}
29798c2ecf20Sopenharmony_ci
29808c2ecf20Sopenharmony_ci	if (state->internal->dev_ver >= 0x20) {
29818c2ecf20Sopenharmony_ci		if ((state->search_mode == STV090x_SEARCH_DVBS1)	||
29828c2ecf20Sopenharmony_ci		    (state->search_mode == STV090x_SEARCH_DSS)		||
29838c2ecf20Sopenharmony_ci		    (state->search_mode == STV090x_SEARCH_AUTO)) {
29848c2ecf20Sopenharmony_ci
29858c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, VAVSRVIT, 0x0a) < 0)
29868c2ecf20Sopenharmony_ci				goto err;
29878c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, VITSCALE, 0x00) < 0)
29888c2ecf20Sopenharmony_ci				goto err;
29898c2ecf20Sopenharmony_ci		}
29908c2ecf20Sopenharmony_ci	}
29918c2ecf20Sopenharmony_ci
29928c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, AGC2REF, 0x38) < 0)
29938c2ecf20Sopenharmony_ci		goto err;
29948c2ecf20Sopenharmony_ci
29958c2ecf20Sopenharmony_ci	/* AUTO tracking MODE */
29968c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, SFRUP1, 0x80) < 0)
29978c2ecf20Sopenharmony_ci		goto err;
29988c2ecf20Sopenharmony_ci	/* AUTO tracking MODE */
29998c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, SFRLOW1, 0x80) < 0)
30008c2ecf20Sopenharmony_ci		goto err;
30018c2ecf20Sopenharmony_ci
30028c2ecf20Sopenharmony_ci	if ((state->internal->dev_ver >= 0x20) || (blind_tune == 1) ||
30038c2ecf20Sopenharmony_ci	    (state->srate < 10000000)) {
30048c2ecf20Sopenharmony_ci		/* update initial carrier freq with the found freq offset */
30058c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, CFRINIT1, f_1) < 0)
30068c2ecf20Sopenharmony_ci			goto err;
30078c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, CFRINIT0, f_0) < 0)
30088c2ecf20Sopenharmony_ci			goto err;
30098c2ecf20Sopenharmony_ci		state->tuner_bw = stv090x_car_width(srate, state->rolloff) + 10000000;
30108c2ecf20Sopenharmony_ci
30118c2ecf20Sopenharmony_ci		if ((state->internal->dev_ver >= 0x20) || (blind_tune == 1)) {
30128c2ecf20Sopenharmony_ci
30138c2ecf20Sopenharmony_ci			if (state->algo != STV090x_WARM_SEARCH) {
30148c2ecf20Sopenharmony_ci
30158c2ecf20Sopenharmony_ci				if (stv090x_i2c_gate_ctrl(state, 1) < 0)
30168c2ecf20Sopenharmony_ci					goto err;
30178c2ecf20Sopenharmony_ci
30188c2ecf20Sopenharmony_ci				if (state->config->tuner_set_bandwidth) {
30198c2ecf20Sopenharmony_ci					if (state->config->tuner_set_bandwidth(fe, state->tuner_bw) < 0)
30208c2ecf20Sopenharmony_ci						goto err_gateoff;
30218c2ecf20Sopenharmony_ci				}
30228c2ecf20Sopenharmony_ci
30238c2ecf20Sopenharmony_ci				if (stv090x_i2c_gate_ctrl(state, 0) < 0)
30248c2ecf20Sopenharmony_ci					goto err;
30258c2ecf20Sopenharmony_ci
30268c2ecf20Sopenharmony_ci			}
30278c2ecf20Sopenharmony_ci		}
30288c2ecf20Sopenharmony_ci		if ((state->algo == STV090x_BLIND_SEARCH) || (state->srate < 10000000))
30298c2ecf20Sopenharmony_ci			msleep(50); /* blind search: wait 50ms for SR stabilization */
30308c2ecf20Sopenharmony_ci		else
30318c2ecf20Sopenharmony_ci			msleep(5);
30328c2ecf20Sopenharmony_ci
30338c2ecf20Sopenharmony_ci		stv090x_get_lock_tmg(state);
30348c2ecf20Sopenharmony_ci
30358c2ecf20Sopenharmony_ci		if (!(stv090x_get_dmdlock(state, (state->DemodTimeout / 2)))) {
30368c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1f) < 0)
30378c2ecf20Sopenharmony_ci				goto err;
30388c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, CFRINIT1, f_1) < 0)
30398c2ecf20Sopenharmony_ci				goto err;
30408c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, CFRINIT0, f_0) < 0)
30418c2ecf20Sopenharmony_ci				goto err;
30428c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x18) < 0)
30438c2ecf20Sopenharmony_ci				goto err;
30448c2ecf20Sopenharmony_ci
30458c2ecf20Sopenharmony_ci			i = 0;
30468c2ecf20Sopenharmony_ci
30478c2ecf20Sopenharmony_ci			while ((!(stv090x_get_dmdlock(state, (state->DemodTimeout / 2)))) && (i <= 2)) {
30488c2ecf20Sopenharmony_ci
30498c2ecf20Sopenharmony_ci				if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1f) < 0)
30508c2ecf20Sopenharmony_ci					goto err;
30518c2ecf20Sopenharmony_ci				if (STV090x_WRITE_DEMOD(state, CFRINIT1, f_1) < 0)
30528c2ecf20Sopenharmony_ci					goto err;
30538c2ecf20Sopenharmony_ci				if (STV090x_WRITE_DEMOD(state, CFRINIT0, f_0) < 0)
30548c2ecf20Sopenharmony_ci					goto err;
30558c2ecf20Sopenharmony_ci				if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x18) < 0)
30568c2ecf20Sopenharmony_ci					goto err;
30578c2ecf20Sopenharmony_ci				i++;
30588c2ecf20Sopenharmony_ci			}
30598c2ecf20Sopenharmony_ci		}
30608c2ecf20Sopenharmony_ci
30618c2ecf20Sopenharmony_ci	}
30628c2ecf20Sopenharmony_ci
30638c2ecf20Sopenharmony_ci	if (state->internal->dev_ver >= 0x20) {
30648c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x49) < 0)
30658c2ecf20Sopenharmony_ci			goto err;
30668c2ecf20Sopenharmony_ci	}
30678c2ecf20Sopenharmony_ci
30688c2ecf20Sopenharmony_ci	if ((state->delsys == STV090x_DVBS1) || (state->delsys == STV090x_DSS))
30698c2ecf20Sopenharmony_ci		stv090x_set_vit_thtracq(state);
30708c2ecf20Sopenharmony_ci
30718c2ecf20Sopenharmony_ci	return 0;
30728c2ecf20Sopenharmony_ci
30738c2ecf20Sopenharmony_cierr_gateoff:
30748c2ecf20Sopenharmony_ci	stv090x_i2c_gate_ctrl(state, 0);
30758c2ecf20Sopenharmony_cierr:
30768c2ecf20Sopenharmony_ci	dprintk(FE_ERROR, 1, "I/O error");
30778c2ecf20Sopenharmony_ci	return -1;
30788c2ecf20Sopenharmony_ci}
30798c2ecf20Sopenharmony_ci
30808c2ecf20Sopenharmony_cistatic int stv090x_get_feclock(struct stv090x_state *state, s32 timeout)
30818c2ecf20Sopenharmony_ci{
30828c2ecf20Sopenharmony_ci	s32 timer = 0, lock = 0, stat;
30838c2ecf20Sopenharmony_ci	u32 reg;
30848c2ecf20Sopenharmony_ci
30858c2ecf20Sopenharmony_ci	while ((timer < timeout) && (!lock)) {
30868c2ecf20Sopenharmony_ci		reg = STV090x_READ_DEMOD(state, DMDSTATE);
30878c2ecf20Sopenharmony_ci		stat = STV090x_GETFIELD_Px(reg, HEADER_MODE_FIELD);
30888c2ecf20Sopenharmony_ci
30898c2ecf20Sopenharmony_ci		switch (stat) {
30908c2ecf20Sopenharmony_ci		case 0: /* searching */
30918c2ecf20Sopenharmony_ci		case 1: /* first PLH detected */
30928c2ecf20Sopenharmony_ci		default:
30938c2ecf20Sopenharmony_ci			lock = 0;
30948c2ecf20Sopenharmony_ci			break;
30958c2ecf20Sopenharmony_ci
30968c2ecf20Sopenharmony_ci		case 2: /* DVB-S2 mode */
30978c2ecf20Sopenharmony_ci			reg = STV090x_READ_DEMOD(state, PDELSTATUS1);
30988c2ecf20Sopenharmony_ci			lock = STV090x_GETFIELD_Px(reg, PKTDELIN_LOCK_FIELD);
30998c2ecf20Sopenharmony_ci			break;
31008c2ecf20Sopenharmony_ci
31018c2ecf20Sopenharmony_ci		case 3: /* DVB-S1/legacy mode */
31028c2ecf20Sopenharmony_ci			reg = STV090x_READ_DEMOD(state, VSTATUSVIT);
31038c2ecf20Sopenharmony_ci			lock = STV090x_GETFIELD_Px(reg, LOCKEDVIT_FIELD);
31048c2ecf20Sopenharmony_ci			break;
31058c2ecf20Sopenharmony_ci		}
31068c2ecf20Sopenharmony_ci		if (!lock) {
31078c2ecf20Sopenharmony_ci			msleep(10);
31088c2ecf20Sopenharmony_ci			timer += 10;
31098c2ecf20Sopenharmony_ci		}
31108c2ecf20Sopenharmony_ci	}
31118c2ecf20Sopenharmony_ci	return lock;
31128c2ecf20Sopenharmony_ci}
31138c2ecf20Sopenharmony_ci
31148c2ecf20Sopenharmony_cistatic int stv090x_get_lock(struct stv090x_state *state, s32 timeout_dmd, s32 timeout_fec)
31158c2ecf20Sopenharmony_ci{
31168c2ecf20Sopenharmony_ci	u32 reg;
31178c2ecf20Sopenharmony_ci	s32 timer = 0;
31188c2ecf20Sopenharmony_ci	int lock;
31198c2ecf20Sopenharmony_ci
31208c2ecf20Sopenharmony_ci	lock = stv090x_get_dmdlock(state, timeout_dmd);
31218c2ecf20Sopenharmony_ci	if (lock)
31228c2ecf20Sopenharmony_ci		lock = stv090x_get_feclock(state, timeout_fec);
31238c2ecf20Sopenharmony_ci
31248c2ecf20Sopenharmony_ci	if (lock) {
31258c2ecf20Sopenharmony_ci		lock = 0;
31268c2ecf20Sopenharmony_ci
31278c2ecf20Sopenharmony_ci		while ((timer < timeout_fec) && (!lock)) {
31288c2ecf20Sopenharmony_ci			reg = STV090x_READ_DEMOD(state, TSSTATUS);
31298c2ecf20Sopenharmony_ci			lock = STV090x_GETFIELD_Px(reg, TSFIFO_LINEOK_FIELD);
31308c2ecf20Sopenharmony_ci			msleep(1);
31318c2ecf20Sopenharmony_ci			timer++;
31328c2ecf20Sopenharmony_ci		}
31338c2ecf20Sopenharmony_ci	}
31348c2ecf20Sopenharmony_ci
31358c2ecf20Sopenharmony_ci	return lock;
31368c2ecf20Sopenharmony_ci}
31378c2ecf20Sopenharmony_ci
31388c2ecf20Sopenharmony_cistatic int stv090x_set_s2rolloff(struct stv090x_state *state)
31398c2ecf20Sopenharmony_ci{
31408c2ecf20Sopenharmony_ci	u32 reg;
31418c2ecf20Sopenharmony_ci
31428c2ecf20Sopenharmony_ci	if (state->internal->dev_ver <= 0x20) {
31438c2ecf20Sopenharmony_ci		/* rolloff to auto mode if DVBS2 */
31448c2ecf20Sopenharmony_ci		reg = STV090x_READ_DEMOD(state, DEMOD);
31458c2ecf20Sopenharmony_ci		STV090x_SETFIELD_Px(reg, MANUAL_SXROLLOFF_FIELD, 0x00);
31468c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, DEMOD, reg) < 0)
31478c2ecf20Sopenharmony_ci			goto err;
31488c2ecf20Sopenharmony_ci	} else {
31498c2ecf20Sopenharmony_ci		/* DVB-S2 rolloff to auto mode if DVBS2 */
31508c2ecf20Sopenharmony_ci		reg = STV090x_READ_DEMOD(state, DEMOD);
31518c2ecf20Sopenharmony_ci		STV090x_SETFIELD_Px(reg, MANUAL_S2ROLLOFF_FIELD, 0x00);
31528c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, DEMOD, reg) < 0)
31538c2ecf20Sopenharmony_ci			goto err;
31548c2ecf20Sopenharmony_ci	}
31558c2ecf20Sopenharmony_ci	return 0;
31568c2ecf20Sopenharmony_cierr:
31578c2ecf20Sopenharmony_ci	dprintk(FE_ERROR, 1, "I/O error");
31588c2ecf20Sopenharmony_ci	return -1;
31598c2ecf20Sopenharmony_ci}
31608c2ecf20Sopenharmony_ci
31618c2ecf20Sopenharmony_ci
31628c2ecf20Sopenharmony_cistatic enum stv090x_signal_state stv090x_algo(struct stv090x_state *state)
31638c2ecf20Sopenharmony_ci{
31648c2ecf20Sopenharmony_ci	struct dvb_frontend *fe = &state->frontend;
31658c2ecf20Sopenharmony_ci	enum stv090x_signal_state signal_state = STV090x_NOCARRIER;
31668c2ecf20Sopenharmony_ci	u32 reg;
31678c2ecf20Sopenharmony_ci	s32 agc1_power, power_iq = 0, i;
31688c2ecf20Sopenharmony_ci	int lock = 0, low_sr = 0;
31698c2ecf20Sopenharmony_ci
31708c2ecf20Sopenharmony_ci	reg = STV090x_READ_DEMOD(state, TSCFGH);
31718c2ecf20Sopenharmony_ci	STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 1); /* Stop path 1 stream merger */
31728c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, TSCFGH, reg) < 0)
31738c2ecf20Sopenharmony_ci		goto err;
31748c2ecf20Sopenharmony_ci
31758c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x5c) < 0) /* Demod stop */
31768c2ecf20Sopenharmony_ci		goto err;
31778c2ecf20Sopenharmony_ci
31788c2ecf20Sopenharmony_ci	if (state->internal->dev_ver >= 0x20) {
31798c2ecf20Sopenharmony_ci		if (state->srate > 5000000) {
31808c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, CORRELABS, 0x9e) < 0)
31818c2ecf20Sopenharmony_ci				goto err;
31828c2ecf20Sopenharmony_ci		} else {
31838c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, CORRELABS, 0x82) < 0)
31848c2ecf20Sopenharmony_ci				goto err;
31858c2ecf20Sopenharmony_ci		}
31868c2ecf20Sopenharmony_ci	}
31878c2ecf20Sopenharmony_ci
31888c2ecf20Sopenharmony_ci	stv090x_get_lock_tmg(state);
31898c2ecf20Sopenharmony_ci
31908c2ecf20Sopenharmony_ci	if (state->algo == STV090x_BLIND_SEARCH) {
31918c2ecf20Sopenharmony_ci		state->tuner_bw = 2 * 36000000; /* wide bw for unknown srate */
31928c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, TMGCFG2, 0xc0) < 0) /* wider srate scan */
31938c2ecf20Sopenharmony_ci			goto err;
31948c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, CORRELMANT, 0x70) < 0)
31958c2ecf20Sopenharmony_ci			goto err;
31968c2ecf20Sopenharmony_ci		if (stv090x_set_srate(state, 1000000) < 0) /* initial srate = 1Msps */
31978c2ecf20Sopenharmony_ci			goto err;
31988c2ecf20Sopenharmony_ci	} else {
31998c2ecf20Sopenharmony_ci		/* known srate */
32008c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, DMDTOM, 0x20) < 0)
32018c2ecf20Sopenharmony_ci			goto err;
32028c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, TMGCFG, 0xd2) < 0)
32038c2ecf20Sopenharmony_ci			goto err;
32048c2ecf20Sopenharmony_ci
32058c2ecf20Sopenharmony_ci		if (state->srate < 2000000) {
32068c2ecf20Sopenharmony_ci			/* SR < 2MSPS */
32078c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, CORRELMANT, 0x63) < 0)
32088c2ecf20Sopenharmony_ci				goto err;
32098c2ecf20Sopenharmony_ci		} else {
32108c2ecf20Sopenharmony_ci			/* SR >= 2Msps */
32118c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, CORRELMANT, 0x70) < 0)
32128c2ecf20Sopenharmony_ci				goto err;
32138c2ecf20Sopenharmony_ci		}
32148c2ecf20Sopenharmony_ci
32158c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, AGC2REF, 0x38) < 0)
32168c2ecf20Sopenharmony_ci			goto err;
32178c2ecf20Sopenharmony_ci
32188c2ecf20Sopenharmony_ci		if (state->internal->dev_ver >= 0x20) {
32198c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, KREFTMG, 0x5a) < 0)
32208c2ecf20Sopenharmony_ci				goto err;
32218c2ecf20Sopenharmony_ci			if (state->algo == STV090x_COLD_SEARCH)
32228c2ecf20Sopenharmony_ci				state->tuner_bw = (15 * (stv090x_car_width(state->srate, state->rolloff) + 10000000)) / 10;
32238c2ecf20Sopenharmony_ci			else if (state->algo == STV090x_WARM_SEARCH)
32248c2ecf20Sopenharmony_ci				state->tuner_bw = stv090x_car_width(state->srate, state->rolloff) + 10000000;
32258c2ecf20Sopenharmony_ci		}
32268c2ecf20Sopenharmony_ci
32278c2ecf20Sopenharmony_ci		/* if cold start or warm  (Symbolrate is known)
32288c2ecf20Sopenharmony_ci		 * use a Narrow symbol rate scan range
32298c2ecf20Sopenharmony_ci		 */
32308c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, TMGCFG2, 0xc1) < 0) /* narrow srate scan */
32318c2ecf20Sopenharmony_ci			goto err;
32328c2ecf20Sopenharmony_ci
32338c2ecf20Sopenharmony_ci		if (stv090x_set_srate(state, state->srate) < 0)
32348c2ecf20Sopenharmony_ci			goto err;
32358c2ecf20Sopenharmony_ci
32368c2ecf20Sopenharmony_ci		if (stv090x_set_max_srate(state, state->internal->mclk,
32378c2ecf20Sopenharmony_ci					  state->srate) < 0)
32388c2ecf20Sopenharmony_ci			goto err;
32398c2ecf20Sopenharmony_ci		if (stv090x_set_min_srate(state, state->internal->mclk,
32408c2ecf20Sopenharmony_ci					  state->srate) < 0)
32418c2ecf20Sopenharmony_ci			goto err;
32428c2ecf20Sopenharmony_ci
32438c2ecf20Sopenharmony_ci		if (state->srate >= 10000000)
32448c2ecf20Sopenharmony_ci			low_sr = 0;
32458c2ecf20Sopenharmony_ci		else
32468c2ecf20Sopenharmony_ci			low_sr = 1;
32478c2ecf20Sopenharmony_ci	}
32488c2ecf20Sopenharmony_ci
32498c2ecf20Sopenharmony_ci	/* Setup tuner */
32508c2ecf20Sopenharmony_ci	if (stv090x_i2c_gate_ctrl(state, 1) < 0)
32518c2ecf20Sopenharmony_ci		goto err;
32528c2ecf20Sopenharmony_ci
32538c2ecf20Sopenharmony_ci	if (state->config->tuner_set_bbgain) {
32548c2ecf20Sopenharmony_ci		reg = state->config->tuner_bbgain;
32558c2ecf20Sopenharmony_ci		if (reg == 0)
32568c2ecf20Sopenharmony_ci			reg = 10; /* default: 10dB */
32578c2ecf20Sopenharmony_ci		if (state->config->tuner_set_bbgain(fe, reg) < 0)
32588c2ecf20Sopenharmony_ci			goto err_gateoff;
32598c2ecf20Sopenharmony_ci	}
32608c2ecf20Sopenharmony_ci
32618c2ecf20Sopenharmony_ci	if (state->config->tuner_set_frequency) {
32628c2ecf20Sopenharmony_ci		if (state->config->tuner_set_frequency(fe, state->frequency) < 0)
32638c2ecf20Sopenharmony_ci			goto err_gateoff;
32648c2ecf20Sopenharmony_ci	}
32658c2ecf20Sopenharmony_ci
32668c2ecf20Sopenharmony_ci	if (state->config->tuner_set_bandwidth) {
32678c2ecf20Sopenharmony_ci		if (state->config->tuner_set_bandwidth(fe, state->tuner_bw) < 0)
32688c2ecf20Sopenharmony_ci			goto err_gateoff;
32698c2ecf20Sopenharmony_ci	}
32708c2ecf20Sopenharmony_ci
32718c2ecf20Sopenharmony_ci	if (stv090x_i2c_gate_ctrl(state, 0) < 0)
32728c2ecf20Sopenharmony_ci		goto err;
32738c2ecf20Sopenharmony_ci
32748c2ecf20Sopenharmony_ci	msleep(50);
32758c2ecf20Sopenharmony_ci
32768c2ecf20Sopenharmony_ci	if (state->config->tuner_get_status) {
32778c2ecf20Sopenharmony_ci		if (stv090x_i2c_gate_ctrl(state, 1) < 0)
32788c2ecf20Sopenharmony_ci			goto err;
32798c2ecf20Sopenharmony_ci		if (state->config->tuner_get_status(fe, &reg) < 0)
32808c2ecf20Sopenharmony_ci			goto err_gateoff;
32818c2ecf20Sopenharmony_ci		if (stv090x_i2c_gate_ctrl(state, 0) < 0)
32828c2ecf20Sopenharmony_ci			goto err;
32838c2ecf20Sopenharmony_ci
32848c2ecf20Sopenharmony_ci		if (reg)
32858c2ecf20Sopenharmony_ci			dprintk(FE_DEBUG, 1, "Tuner phase locked");
32868c2ecf20Sopenharmony_ci		else {
32878c2ecf20Sopenharmony_ci			dprintk(FE_DEBUG, 1, "Tuner unlocked");
32888c2ecf20Sopenharmony_ci			return STV090x_NOCARRIER;
32898c2ecf20Sopenharmony_ci		}
32908c2ecf20Sopenharmony_ci	}
32918c2ecf20Sopenharmony_ci
32928c2ecf20Sopenharmony_ci	msleep(10);
32938c2ecf20Sopenharmony_ci	agc1_power = MAKEWORD16(STV090x_READ_DEMOD(state, AGCIQIN1),
32948c2ecf20Sopenharmony_ci				STV090x_READ_DEMOD(state, AGCIQIN0));
32958c2ecf20Sopenharmony_ci
32968c2ecf20Sopenharmony_ci	if (agc1_power == 0) {
32978c2ecf20Sopenharmony_ci		/* If AGC1 integrator value is 0
32988c2ecf20Sopenharmony_ci		 * then read POWERI, POWERQ
32998c2ecf20Sopenharmony_ci		 */
33008c2ecf20Sopenharmony_ci		for (i = 0; i < 5; i++) {
33018c2ecf20Sopenharmony_ci			power_iq += (STV090x_READ_DEMOD(state, POWERI) +
33028c2ecf20Sopenharmony_ci				     STV090x_READ_DEMOD(state, POWERQ)) >> 1;
33038c2ecf20Sopenharmony_ci		}
33048c2ecf20Sopenharmony_ci		power_iq /= 5;
33058c2ecf20Sopenharmony_ci	}
33068c2ecf20Sopenharmony_ci
33078c2ecf20Sopenharmony_ci	if ((agc1_power == 0) && (power_iq < STV090x_IQPOWER_THRESHOLD)) {
33088c2ecf20Sopenharmony_ci		dprintk(FE_ERROR, 1, "No Signal: POWER_IQ=0x%02x", power_iq);
33098c2ecf20Sopenharmony_ci		lock = 0;
33108c2ecf20Sopenharmony_ci		signal_state = STV090x_NOAGC1;
33118c2ecf20Sopenharmony_ci	} else {
33128c2ecf20Sopenharmony_ci		reg = STV090x_READ_DEMOD(state, DEMOD);
33138c2ecf20Sopenharmony_ci		STV090x_SETFIELD_Px(reg, SPECINV_CONTROL_FIELD, state->inversion);
33148c2ecf20Sopenharmony_ci
33158c2ecf20Sopenharmony_ci		if (state->internal->dev_ver <= 0x20) {
33168c2ecf20Sopenharmony_ci			/* rolloff to auto mode if DVBS2 */
33178c2ecf20Sopenharmony_ci			STV090x_SETFIELD_Px(reg, MANUAL_SXROLLOFF_FIELD, 1);
33188c2ecf20Sopenharmony_ci		} else {
33198c2ecf20Sopenharmony_ci			/* DVB-S2 rolloff to auto mode if DVBS2 */
33208c2ecf20Sopenharmony_ci			STV090x_SETFIELD_Px(reg, MANUAL_S2ROLLOFF_FIELD, 1);
33218c2ecf20Sopenharmony_ci		}
33228c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, DEMOD, reg) < 0)
33238c2ecf20Sopenharmony_ci			goto err;
33248c2ecf20Sopenharmony_ci
33258c2ecf20Sopenharmony_ci		if (stv090x_delivery_search(state) < 0)
33268c2ecf20Sopenharmony_ci			goto err;
33278c2ecf20Sopenharmony_ci
33288c2ecf20Sopenharmony_ci		if (state->algo != STV090x_BLIND_SEARCH) {
33298c2ecf20Sopenharmony_ci			if (stv090x_start_search(state) < 0)
33308c2ecf20Sopenharmony_ci				goto err;
33318c2ecf20Sopenharmony_ci		}
33328c2ecf20Sopenharmony_ci	}
33338c2ecf20Sopenharmony_ci
33348c2ecf20Sopenharmony_ci	if (signal_state == STV090x_NOAGC1)
33358c2ecf20Sopenharmony_ci		return signal_state;
33368c2ecf20Sopenharmony_ci
33378c2ecf20Sopenharmony_ci	if (state->algo == STV090x_BLIND_SEARCH)
33388c2ecf20Sopenharmony_ci		lock = stv090x_blind_search(state);
33398c2ecf20Sopenharmony_ci
33408c2ecf20Sopenharmony_ci	else if (state->algo == STV090x_COLD_SEARCH)
33418c2ecf20Sopenharmony_ci		lock = stv090x_get_coldlock(state, state->DemodTimeout);
33428c2ecf20Sopenharmony_ci
33438c2ecf20Sopenharmony_ci	else if (state->algo == STV090x_WARM_SEARCH)
33448c2ecf20Sopenharmony_ci		lock = stv090x_get_dmdlock(state, state->DemodTimeout);
33458c2ecf20Sopenharmony_ci
33468c2ecf20Sopenharmony_ci	if ((!lock) && (state->algo == STV090x_COLD_SEARCH)) {
33478c2ecf20Sopenharmony_ci		if (!low_sr) {
33488c2ecf20Sopenharmony_ci			if (stv090x_chk_tmg(state))
33498c2ecf20Sopenharmony_ci				lock = stv090x_sw_algo(state);
33508c2ecf20Sopenharmony_ci		}
33518c2ecf20Sopenharmony_ci	}
33528c2ecf20Sopenharmony_ci
33538c2ecf20Sopenharmony_ci	if (lock)
33548c2ecf20Sopenharmony_ci		signal_state = stv090x_get_sig_params(state);
33558c2ecf20Sopenharmony_ci
33568c2ecf20Sopenharmony_ci	if ((lock) && (signal_state == STV090x_RANGEOK)) { /* signal within Range */
33578c2ecf20Sopenharmony_ci		stv090x_optimize_track(state);
33588c2ecf20Sopenharmony_ci
33598c2ecf20Sopenharmony_ci		if (state->internal->dev_ver >= 0x20) {
33608c2ecf20Sopenharmony_ci			/* >= Cut 2.0 :release TS reset after
33618c2ecf20Sopenharmony_ci			 * demod lock and optimized Tracking
33628c2ecf20Sopenharmony_ci			 */
33638c2ecf20Sopenharmony_ci			reg = STV090x_READ_DEMOD(state, TSCFGH);
33648c2ecf20Sopenharmony_ci			STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 0); /* release merger reset */
33658c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, TSCFGH, reg) < 0)
33668c2ecf20Sopenharmony_ci				goto err;
33678c2ecf20Sopenharmony_ci
33688c2ecf20Sopenharmony_ci			msleep(3);
33698c2ecf20Sopenharmony_ci
33708c2ecf20Sopenharmony_ci			STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 1); /* merger reset */
33718c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, TSCFGH, reg) < 0)
33728c2ecf20Sopenharmony_ci				goto err;
33738c2ecf20Sopenharmony_ci
33748c2ecf20Sopenharmony_ci			STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 0); /* release merger reset */
33758c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, TSCFGH, reg) < 0)
33768c2ecf20Sopenharmony_ci				goto err;
33778c2ecf20Sopenharmony_ci		}
33788c2ecf20Sopenharmony_ci
33798c2ecf20Sopenharmony_ci		lock = stv090x_get_lock(state, state->FecTimeout,
33808c2ecf20Sopenharmony_ci				state->FecTimeout);
33818c2ecf20Sopenharmony_ci		if (lock) {
33828c2ecf20Sopenharmony_ci			if (state->delsys == STV090x_DVBS2) {
33838c2ecf20Sopenharmony_ci				stv090x_set_s2rolloff(state);
33848c2ecf20Sopenharmony_ci
33858c2ecf20Sopenharmony_ci				reg = STV090x_READ_DEMOD(state, PDELCTRL2);
33868c2ecf20Sopenharmony_ci				STV090x_SETFIELD_Px(reg, RESET_UPKO_COUNT, 1);
33878c2ecf20Sopenharmony_ci				if (STV090x_WRITE_DEMOD(state, PDELCTRL2, reg) < 0)
33888c2ecf20Sopenharmony_ci					goto err;
33898c2ecf20Sopenharmony_ci				/* Reset DVBS2 packet delinator error counter */
33908c2ecf20Sopenharmony_ci				reg = STV090x_READ_DEMOD(state, PDELCTRL2);
33918c2ecf20Sopenharmony_ci				STV090x_SETFIELD_Px(reg, RESET_UPKO_COUNT, 0);
33928c2ecf20Sopenharmony_ci				if (STV090x_WRITE_DEMOD(state, PDELCTRL2, reg) < 0)
33938c2ecf20Sopenharmony_ci					goto err;
33948c2ecf20Sopenharmony_ci
33958c2ecf20Sopenharmony_ci				if (STV090x_WRITE_DEMOD(state, ERRCTRL1, 0x67) < 0) /* PER */
33968c2ecf20Sopenharmony_ci					goto err;
33978c2ecf20Sopenharmony_ci			} else {
33988c2ecf20Sopenharmony_ci				if (STV090x_WRITE_DEMOD(state, ERRCTRL1, 0x75) < 0)
33998c2ecf20Sopenharmony_ci					goto err;
34008c2ecf20Sopenharmony_ci			}
34018c2ecf20Sopenharmony_ci			/* Reset the Total packet counter */
34028c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, FBERCPT4, 0x00) < 0)
34038c2ecf20Sopenharmony_ci				goto err;
34048c2ecf20Sopenharmony_ci			/* Reset the packet Error counter2 */
34058c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, ERRCTRL2, 0xc1) < 0)
34068c2ecf20Sopenharmony_ci				goto err;
34078c2ecf20Sopenharmony_ci		} else {
34088c2ecf20Sopenharmony_ci			signal_state = STV090x_NODATA;
34098c2ecf20Sopenharmony_ci			stv090x_chk_signal(state);
34108c2ecf20Sopenharmony_ci		}
34118c2ecf20Sopenharmony_ci	}
34128c2ecf20Sopenharmony_ci	return signal_state;
34138c2ecf20Sopenharmony_ci
34148c2ecf20Sopenharmony_cierr_gateoff:
34158c2ecf20Sopenharmony_ci	stv090x_i2c_gate_ctrl(state, 0);
34168c2ecf20Sopenharmony_cierr:
34178c2ecf20Sopenharmony_ci	dprintk(FE_ERROR, 1, "I/O error");
34188c2ecf20Sopenharmony_ci	return -1;
34198c2ecf20Sopenharmony_ci}
34208c2ecf20Sopenharmony_ci
34218c2ecf20Sopenharmony_cistatic int stv090x_set_pls(struct stv090x_state *state, u32 pls_code)
34228c2ecf20Sopenharmony_ci{
34238c2ecf20Sopenharmony_ci	dprintk(FE_DEBUG, 1, "Set Gold PLS code %d", pls_code);
34248c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, PLROOT0, pls_code & 0xff) < 0)
34258c2ecf20Sopenharmony_ci		goto err;
34268c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, PLROOT1, (pls_code >> 8) & 0xff) < 0)
34278c2ecf20Sopenharmony_ci		goto err;
34288c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, PLROOT2, 0x04 | (pls_code >> 16)) < 0)
34298c2ecf20Sopenharmony_ci		goto err;
34308c2ecf20Sopenharmony_ci	return 0;
34318c2ecf20Sopenharmony_cierr:
34328c2ecf20Sopenharmony_ci	dprintk(FE_ERROR, 1, "I/O error");
34338c2ecf20Sopenharmony_ci	return -1;
34348c2ecf20Sopenharmony_ci}
34358c2ecf20Sopenharmony_ci
34368c2ecf20Sopenharmony_cistatic int stv090x_set_mis(struct stv090x_state *state, int mis)
34378c2ecf20Sopenharmony_ci{
34388c2ecf20Sopenharmony_ci	u32 reg;
34398c2ecf20Sopenharmony_ci
34408c2ecf20Sopenharmony_ci	if (mis < 0 || mis > 255) {
34418c2ecf20Sopenharmony_ci		dprintk(FE_DEBUG, 1, "Disable MIS filtering");
34428c2ecf20Sopenharmony_ci		reg = STV090x_READ_DEMOD(state, PDELCTRL1);
34438c2ecf20Sopenharmony_ci		STV090x_SETFIELD_Px(reg, FILTER_EN_FIELD, 0x00);
34448c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, PDELCTRL1, reg) < 0)
34458c2ecf20Sopenharmony_ci			goto err;
34468c2ecf20Sopenharmony_ci	} else {
34478c2ecf20Sopenharmony_ci		dprintk(FE_DEBUG, 1, "Enable MIS filtering - %d", mis);
34488c2ecf20Sopenharmony_ci		reg = STV090x_READ_DEMOD(state, PDELCTRL1);
34498c2ecf20Sopenharmony_ci		STV090x_SETFIELD_Px(reg, FILTER_EN_FIELD, 0x01);
34508c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, PDELCTRL1, reg) < 0)
34518c2ecf20Sopenharmony_ci			goto err;
34528c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, ISIENTRY, mis) < 0)
34538c2ecf20Sopenharmony_ci			goto err;
34548c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, ISIBITENA, 0xff) < 0)
34558c2ecf20Sopenharmony_ci			goto err;
34568c2ecf20Sopenharmony_ci	}
34578c2ecf20Sopenharmony_ci	return 0;
34588c2ecf20Sopenharmony_cierr:
34598c2ecf20Sopenharmony_ci	dprintk(FE_ERROR, 1, "I/O error");
34608c2ecf20Sopenharmony_ci	return -1;
34618c2ecf20Sopenharmony_ci}
34628c2ecf20Sopenharmony_ci
34638c2ecf20Sopenharmony_cistatic enum dvbfe_search stv090x_search(struct dvb_frontend *fe)
34648c2ecf20Sopenharmony_ci{
34658c2ecf20Sopenharmony_ci	struct stv090x_state *state = fe->demodulator_priv;
34668c2ecf20Sopenharmony_ci	struct dtv_frontend_properties *props = &fe->dtv_property_cache;
34678c2ecf20Sopenharmony_ci
34688c2ecf20Sopenharmony_ci	if (props->frequency == 0)
34698c2ecf20Sopenharmony_ci		return DVBFE_ALGO_SEARCH_INVALID;
34708c2ecf20Sopenharmony_ci
34718c2ecf20Sopenharmony_ci	switch (props->delivery_system) {
34728c2ecf20Sopenharmony_ci	case SYS_DSS:
34738c2ecf20Sopenharmony_ci		state->delsys = STV090x_DSS;
34748c2ecf20Sopenharmony_ci		break;
34758c2ecf20Sopenharmony_ci	case SYS_DVBS:
34768c2ecf20Sopenharmony_ci		state->delsys = STV090x_DVBS1;
34778c2ecf20Sopenharmony_ci		break;
34788c2ecf20Sopenharmony_ci	case SYS_DVBS2:
34798c2ecf20Sopenharmony_ci		state->delsys = STV090x_DVBS2;
34808c2ecf20Sopenharmony_ci		break;
34818c2ecf20Sopenharmony_ci	default:
34828c2ecf20Sopenharmony_ci		return DVBFE_ALGO_SEARCH_INVALID;
34838c2ecf20Sopenharmony_ci	}
34848c2ecf20Sopenharmony_ci
34858c2ecf20Sopenharmony_ci	state->frequency = props->frequency;
34868c2ecf20Sopenharmony_ci	state->srate = props->symbol_rate;
34878c2ecf20Sopenharmony_ci	state->search_mode = STV090x_SEARCH_AUTO;
34888c2ecf20Sopenharmony_ci	state->algo = STV090x_COLD_SEARCH;
34898c2ecf20Sopenharmony_ci	state->fec = STV090x_PRERR;
34908c2ecf20Sopenharmony_ci	if (state->srate > 10000000) {
34918c2ecf20Sopenharmony_ci		dprintk(FE_DEBUG, 1, "Search range: 10 MHz");
34928c2ecf20Sopenharmony_ci		state->search_range = 10000000;
34938c2ecf20Sopenharmony_ci	} else {
34948c2ecf20Sopenharmony_ci		dprintk(FE_DEBUG, 1, "Search range: 5 MHz");
34958c2ecf20Sopenharmony_ci		state->search_range = 5000000;
34968c2ecf20Sopenharmony_ci	}
34978c2ecf20Sopenharmony_ci
34988c2ecf20Sopenharmony_ci	stv090x_set_pls(state, props->scrambling_sequence_index);
34998c2ecf20Sopenharmony_ci	stv090x_set_mis(state, props->stream_id);
35008c2ecf20Sopenharmony_ci
35018c2ecf20Sopenharmony_ci	if (stv090x_algo(state) == STV090x_RANGEOK) {
35028c2ecf20Sopenharmony_ci		dprintk(FE_DEBUG, 1, "Search success!");
35038c2ecf20Sopenharmony_ci		return DVBFE_ALGO_SEARCH_SUCCESS;
35048c2ecf20Sopenharmony_ci	} else {
35058c2ecf20Sopenharmony_ci		dprintk(FE_DEBUG, 1, "Search failed!");
35068c2ecf20Sopenharmony_ci		return DVBFE_ALGO_SEARCH_FAILED;
35078c2ecf20Sopenharmony_ci	}
35088c2ecf20Sopenharmony_ci
35098c2ecf20Sopenharmony_ci	return DVBFE_ALGO_SEARCH_ERROR;
35108c2ecf20Sopenharmony_ci}
35118c2ecf20Sopenharmony_ci
35128c2ecf20Sopenharmony_cistatic int stv090x_read_status(struct dvb_frontend *fe, enum fe_status *status)
35138c2ecf20Sopenharmony_ci{
35148c2ecf20Sopenharmony_ci	struct stv090x_state *state = fe->demodulator_priv;
35158c2ecf20Sopenharmony_ci	u32 reg, dstatus;
35168c2ecf20Sopenharmony_ci	u8 search_state;
35178c2ecf20Sopenharmony_ci
35188c2ecf20Sopenharmony_ci	*status = 0;
35198c2ecf20Sopenharmony_ci
35208c2ecf20Sopenharmony_ci	dstatus = STV090x_READ_DEMOD(state, DSTATUS);
35218c2ecf20Sopenharmony_ci	if (STV090x_GETFIELD_Px(dstatus, CAR_LOCK_FIELD))
35228c2ecf20Sopenharmony_ci		*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER;
35238c2ecf20Sopenharmony_ci
35248c2ecf20Sopenharmony_ci	reg = STV090x_READ_DEMOD(state, DMDSTATE);
35258c2ecf20Sopenharmony_ci	search_state = STV090x_GETFIELD_Px(reg, HEADER_MODE_FIELD);
35268c2ecf20Sopenharmony_ci
35278c2ecf20Sopenharmony_ci	switch (search_state) {
35288c2ecf20Sopenharmony_ci	case 0: /* searching */
35298c2ecf20Sopenharmony_ci	case 1: /* first PLH detected */
35308c2ecf20Sopenharmony_ci	default:
35318c2ecf20Sopenharmony_ci		dprintk(FE_DEBUG, 1, "Status: Unlocked (Searching ..)");
35328c2ecf20Sopenharmony_ci		break;
35338c2ecf20Sopenharmony_ci
35348c2ecf20Sopenharmony_ci	case 2: /* DVB-S2 mode */
35358c2ecf20Sopenharmony_ci		dprintk(FE_DEBUG, 1, "Delivery system: DVB-S2");
35368c2ecf20Sopenharmony_ci		if (STV090x_GETFIELD_Px(dstatus, LOCK_DEFINITIF_FIELD)) {
35378c2ecf20Sopenharmony_ci			reg = STV090x_READ_DEMOD(state, PDELSTATUS1);
35388c2ecf20Sopenharmony_ci			if (STV090x_GETFIELD_Px(reg, PKTDELIN_LOCK_FIELD)) {
35398c2ecf20Sopenharmony_ci				*status |= FE_HAS_VITERBI;
35408c2ecf20Sopenharmony_ci				reg = STV090x_READ_DEMOD(state, TSSTATUS);
35418c2ecf20Sopenharmony_ci				if (STV090x_GETFIELD_Px(reg, TSFIFO_LINEOK_FIELD))
35428c2ecf20Sopenharmony_ci					*status |= FE_HAS_SYNC | FE_HAS_LOCK;
35438c2ecf20Sopenharmony_ci			}
35448c2ecf20Sopenharmony_ci		}
35458c2ecf20Sopenharmony_ci		break;
35468c2ecf20Sopenharmony_ci
35478c2ecf20Sopenharmony_ci	case 3: /* DVB-S1/legacy mode */
35488c2ecf20Sopenharmony_ci		dprintk(FE_DEBUG, 1, "Delivery system: DVB-S");
35498c2ecf20Sopenharmony_ci		if (STV090x_GETFIELD_Px(dstatus, LOCK_DEFINITIF_FIELD)) {
35508c2ecf20Sopenharmony_ci			reg = STV090x_READ_DEMOD(state, VSTATUSVIT);
35518c2ecf20Sopenharmony_ci			if (STV090x_GETFIELD_Px(reg, LOCKEDVIT_FIELD)) {
35528c2ecf20Sopenharmony_ci				*status |= FE_HAS_VITERBI;
35538c2ecf20Sopenharmony_ci				reg = STV090x_READ_DEMOD(state, TSSTATUS);
35548c2ecf20Sopenharmony_ci				if (STV090x_GETFIELD_Px(reg, TSFIFO_LINEOK_FIELD))
35558c2ecf20Sopenharmony_ci					*status |= FE_HAS_SYNC | FE_HAS_LOCK;
35568c2ecf20Sopenharmony_ci			}
35578c2ecf20Sopenharmony_ci		}
35588c2ecf20Sopenharmony_ci		break;
35598c2ecf20Sopenharmony_ci	}
35608c2ecf20Sopenharmony_ci
35618c2ecf20Sopenharmony_ci	return 0;
35628c2ecf20Sopenharmony_ci}
35638c2ecf20Sopenharmony_ci
35648c2ecf20Sopenharmony_cistatic int stv090x_read_per(struct dvb_frontend *fe, u32 *per)
35658c2ecf20Sopenharmony_ci{
35668c2ecf20Sopenharmony_ci	struct stv090x_state *state = fe->demodulator_priv;
35678c2ecf20Sopenharmony_ci
35688c2ecf20Sopenharmony_ci	s32 count_4, count_3, count_2, count_1, count_0, count;
35698c2ecf20Sopenharmony_ci	u32 reg, h, m, l;
35708c2ecf20Sopenharmony_ci	enum fe_status status;
35718c2ecf20Sopenharmony_ci
35728c2ecf20Sopenharmony_ci	stv090x_read_status(fe, &status);
35738c2ecf20Sopenharmony_ci	if (!(status & FE_HAS_LOCK)) {
35748c2ecf20Sopenharmony_ci		*per = 1 << 23; /* Max PER */
35758c2ecf20Sopenharmony_ci	} else {
35768c2ecf20Sopenharmony_ci		/* Counter 2 */
35778c2ecf20Sopenharmony_ci		reg = STV090x_READ_DEMOD(state, ERRCNT22);
35788c2ecf20Sopenharmony_ci		h = STV090x_GETFIELD_Px(reg, ERR_CNT2_FIELD);
35798c2ecf20Sopenharmony_ci
35808c2ecf20Sopenharmony_ci		reg = STV090x_READ_DEMOD(state, ERRCNT21);
35818c2ecf20Sopenharmony_ci		m = STV090x_GETFIELD_Px(reg, ERR_CNT21_FIELD);
35828c2ecf20Sopenharmony_ci
35838c2ecf20Sopenharmony_ci		reg = STV090x_READ_DEMOD(state, ERRCNT20);
35848c2ecf20Sopenharmony_ci		l = STV090x_GETFIELD_Px(reg, ERR_CNT20_FIELD);
35858c2ecf20Sopenharmony_ci
35868c2ecf20Sopenharmony_ci		*per = ((h << 16) | (m << 8) | l);
35878c2ecf20Sopenharmony_ci
35888c2ecf20Sopenharmony_ci		count_4 = STV090x_READ_DEMOD(state, FBERCPT4);
35898c2ecf20Sopenharmony_ci		count_3 = STV090x_READ_DEMOD(state, FBERCPT3);
35908c2ecf20Sopenharmony_ci		count_2 = STV090x_READ_DEMOD(state, FBERCPT2);
35918c2ecf20Sopenharmony_ci		count_1 = STV090x_READ_DEMOD(state, FBERCPT1);
35928c2ecf20Sopenharmony_ci		count_0 = STV090x_READ_DEMOD(state, FBERCPT0);
35938c2ecf20Sopenharmony_ci
35948c2ecf20Sopenharmony_ci		if ((!count_4) && (!count_3)) {
35958c2ecf20Sopenharmony_ci			count  = (count_2 & 0xff) << 16;
35968c2ecf20Sopenharmony_ci			count |= (count_1 & 0xff) <<  8;
35978c2ecf20Sopenharmony_ci			count |=  count_0 & 0xff;
35988c2ecf20Sopenharmony_ci		} else {
35998c2ecf20Sopenharmony_ci			count = 1 << 24;
36008c2ecf20Sopenharmony_ci		}
36018c2ecf20Sopenharmony_ci		if (count == 0)
36028c2ecf20Sopenharmony_ci			*per = 1;
36038c2ecf20Sopenharmony_ci	}
36048c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, FBERCPT4, 0) < 0)
36058c2ecf20Sopenharmony_ci		goto err;
36068c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, ERRCTRL2, 0xc1) < 0)
36078c2ecf20Sopenharmony_ci		goto err;
36088c2ecf20Sopenharmony_ci
36098c2ecf20Sopenharmony_ci	return 0;
36108c2ecf20Sopenharmony_cierr:
36118c2ecf20Sopenharmony_ci	dprintk(FE_ERROR, 1, "I/O error");
36128c2ecf20Sopenharmony_ci	return -1;
36138c2ecf20Sopenharmony_ci}
36148c2ecf20Sopenharmony_ci
36158c2ecf20Sopenharmony_cistatic int stv090x_table_lookup(const struct stv090x_tab *tab, int max, int val)
36168c2ecf20Sopenharmony_ci{
36178c2ecf20Sopenharmony_ci	int res = 0;
36188c2ecf20Sopenharmony_ci	int min = 0, med;
36198c2ecf20Sopenharmony_ci
36208c2ecf20Sopenharmony_ci	if ((val >= tab[min].read && val < tab[max].read) ||
36218c2ecf20Sopenharmony_ci	    (val >= tab[max].read && val < tab[min].read)) {
36228c2ecf20Sopenharmony_ci		while ((max - min) > 1) {
36238c2ecf20Sopenharmony_ci			med = (max + min) / 2;
36248c2ecf20Sopenharmony_ci			if ((val >= tab[min].read && val < tab[med].read) ||
36258c2ecf20Sopenharmony_ci			    (val >= tab[med].read && val < tab[min].read))
36268c2ecf20Sopenharmony_ci				max = med;
36278c2ecf20Sopenharmony_ci			else
36288c2ecf20Sopenharmony_ci				min = med;
36298c2ecf20Sopenharmony_ci		}
36308c2ecf20Sopenharmony_ci		res = ((val - tab[min].read) *
36318c2ecf20Sopenharmony_ci		       (tab[max].real - tab[min].real) /
36328c2ecf20Sopenharmony_ci		       (tab[max].read - tab[min].read)) +
36338c2ecf20Sopenharmony_ci			tab[min].real;
36348c2ecf20Sopenharmony_ci	} else {
36358c2ecf20Sopenharmony_ci		if (tab[min].read < tab[max].read) {
36368c2ecf20Sopenharmony_ci			if (val < tab[min].read)
36378c2ecf20Sopenharmony_ci				res = tab[min].real;
36388c2ecf20Sopenharmony_ci			else if (val >= tab[max].read)
36398c2ecf20Sopenharmony_ci				res = tab[max].real;
36408c2ecf20Sopenharmony_ci		} else {
36418c2ecf20Sopenharmony_ci			if (val >= tab[min].read)
36428c2ecf20Sopenharmony_ci				res = tab[min].real;
36438c2ecf20Sopenharmony_ci			else if (val < tab[max].read)
36448c2ecf20Sopenharmony_ci				res = tab[max].real;
36458c2ecf20Sopenharmony_ci		}
36468c2ecf20Sopenharmony_ci	}
36478c2ecf20Sopenharmony_ci
36488c2ecf20Sopenharmony_ci	return res;
36498c2ecf20Sopenharmony_ci}
36508c2ecf20Sopenharmony_ci
36518c2ecf20Sopenharmony_cistatic int stv090x_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
36528c2ecf20Sopenharmony_ci{
36538c2ecf20Sopenharmony_ci	struct stv090x_state *state = fe->demodulator_priv;
36548c2ecf20Sopenharmony_ci	u32 reg;
36558c2ecf20Sopenharmony_ci	s32 agc_0, agc_1, agc;
36568c2ecf20Sopenharmony_ci	s32 str;
36578c2ecf20Sopenharmony_ci
36588c2ecf20Sopenharmony_ci	reg = STV090x_READ_DEMOD(state, AGCIQIN1);
36598c2ecf20Sopenharmony_ci	agc_1 = STV090x_GETFIELD_Px(reg, AGCIQ_VALUE_FIELD);
36608c2ecf20Sopenharmony_ci	reg = STV090x_READ_DEMOD(state, AGCIQIN0);
36618c2ecf20Sopenharmony_ci	agc_0 = STV090x_GETFIELD_Px(reg, AGCIQ_VALUE_FIELD);
36628c2ecf20Sopenharmony_ci	agc = MAKEWORD16(agc_1, agc_0);
36638c2ecf20Sopenharmony_ci
36648c2ecf20Sopenharmony_ci	str = stv090x_table_lookup(stv090x_rf_tab,
36658c2ecf20Sopenharmony_ci		ARRAY_SIZE(stv090x_rf_tab) - 1, agc);
36668c2ecf20Sopenharmony_ci	if (agc > stv090x_rf_tab[0].read)
36678c2ecf20Sopenharmony_ci		str = 0;
36688c2ecf20Sopenharmony_ci	else if (agc < stv090x_rf_tab[ARRAY_SIZE(stv090x_rf_tab) - 1].read)
36698c2ecf20Sopenharmony_ci		str = -100;
36708c2ecf20Sopenharmony_ci	*strength = (str + 100) * 0xFFFF / 100;
36718c2ecf20Sopenharmony_ci
36728c2ecf20Sopenharmony_ci	return 0;
36738c2ecf20Sopenharmony_ci}
36748c2ecf20Sopenharmony_ci
36758c2ecf20Sopenharmony_cistatic int stv090x_read_cnr(struct dvb_frontend *fe, u16 *cnr)
36768c2ecf20Sopenharmony_ci{
36778c2ecf20Sopenharmony_ci	struct stv090x_state *state = fe->demodulator_priv;
36788c2ecf20Sopenharmony_ci	u32 reg_0, reg_1, reg, i;
36798c2ecf20Sopenharmony_ci	s32 val_0, val_1, val = 0;
36808c2ecf20Sopenharmony_ci	u8 lock_f;
36818c2ecf20Sopenharmony_ci	s32 div;
36828c2ecf20Sopenharmony_ci	u32 last;
36838c2ecf20Sopenharmony_ci
36848c2ecf20Sopenharmony_ci	switch (state->delsys) {
36858c2ecf20Sopenharmony_ci	case STV090x_DVBS2:
36868c2ecf20Sopenharmony_ci		reg = STV090x_READ_DEMOD(state, DSTATUS);
36878c2ecf20Sopenharmony_ci		lock_f = STV090x_GETFIELD_Px(reg, LOCK_DEFINITIF_FIELD);
36888c2ecf20Sopenharmony_ci		if (lock_f) {
36898c2ecf20Sopenharmony_ci			msleep(5);
36908c2ecf20Sopenharmony_ci			for (i = 0; i < 16; i++) {
36918c2ecf20Sopenharmony_ci				reg_1 = STV090x_READ_DEMOD(state, NNOSPLHT1);
36928c2ecf20Sopenharmony_ci				val_1 = STV090x_GETFIELD_Px(reg_1, NOSPLHT_NORMED_FIELD);
36938c2ecf20Sopenharmony_ci				reg_0 = STV090x_READ_DEMOD(state, NNOSPLHT0);
36948c2ecf20Sopenharmony_ci				val_0 = STV090x_GETFIELD_Px(reg_0, NOSPLHT_NORMED_FIELD);
36958c2ecf20Sopenharmony_ci				val  += MAKEWORD16(val_1, val_0);
36968c2ecf20Sopenharmony_ci				msleep(1);
36978c2ecf20Sopenharmony_ci			}
36988c2ecf20Sopenharmony_ci			val /= 16;
36998c2ecf20Sopenharmony_ci			last = ARRAY_SIZE(stv090x_s2cn_tab) - 1;
37008c2ecf20Sopenharmony_ci			div = stv090x_s2cn_tab[last].real -
37018c2ecf20Sopenharmony_ci			      stv090x_s2cn_tab[3].real;
37028c2ecf20Sopenharmony_ci			val = stv090x_table_lookup(stv090x_s2cn_tab, last, val);
37038c2ecf20Sopenharmony_ci			if (val < 0)
37048c2ecf20Sopenharmony_ci				val = 0;
37058c2ecf20Sopenharmony_ci			*cnr = val * 0xFFFF / div;
37068c2ecf20Sopenharmony_ci		}
37078c2ecf20Sopenharmony_ci		break;
37088c2ecf20Sopenharmony_ci
37098c2ecf20Sopenharmony_ci	case STV090x_DVBS1:
37108c2ecf20Sopenharmony_ci	case STV090x_DSS:
37118c2ecf20Sopenharmony_ci		reg = STV090x_READ_DEMOD(state, DSTATUS);
37128c2ecf20Sopenharmony_ci		lock_f = STV090x_GETFIELD_Px(reg, LOCK_DEFINITIF_FIELD);
37138c2ecf20Sopenharmony_ci		if (lock_f) {
37148c2ecf20Sopenharmony_ci			msleep(5);
37158c2ecf20Sopenharmony_ci			for (i = 0; i < 16; i++) {
37168c2ecf20Sopenharmony_ci				reg_1 = STV090x_READ_DEMOD(state, NOSDATAT1);
37178c2ecf20Sopenharmony_ci				val_1 = STV090x_GETFIELD_Px(reg_1, NOSDATAT_UNNORMED_FIELD);
37188c2ecf20Sopenharmony_ci				reg_0 = STV090x_READ_DEMOD(state, NOSDATAT0);
37198c2ecf20Sopenharmony_ci				val_0 = STV090x_GETFIELD_Px(reg_0, NOSDATAT_UNNORMED_FIELD);
37208c2ecf20Sopenharmony_ci				val  += MAKEWORD16(val_1, val_0);
37218c2ecf20Sopenharmony_ci				msleep(1);
37228c2ecf20Sopenharmony_ci			}
37238c2ecf20Sopenharmony_ci			val /= 16;
37248c2ecf20Sopenharmony_ci			last = ARRAY_SIZE(stv090x_s1cn_tab) - 1;
37258c2ecf20Sopenharmony_ci			div = stv090x_s1cn_tab[last].real -
37268c2ecf20Sopenharmony_ci			      stv090x_s1cn_tab[0].real;
37278c2ecf20Sopenharmony_ci			val = stv090x_table_lookup(stv090x_s1cn_tab, last, val);
37288c2ecf20Sopenharmony_ci			*cnr = val * 0xFFFF / div;
37298c2ecf20Sopenharmony_ci		}
37308c2ecf20Sopenharmony_ci		break;
37318c2ecf20Sopenharmony_ci	default:
37328c2ecf20Sopenharmony_ci		break;
37338c2ecf20Sopenharmony_ci	}
37348c2ecf20Sopenharmony_ci
37358c2ecf20Sopenharmony_ci	return 0;
37368c2ecf20Sopenharmony_ci}
37378c2ecf20Sopenharmony_ci
37388c2ecf20Sopenharmony_cistatic int stv090x_set_tone(struct dvb_frontend *fe, enum fe_sec_tone_mode tone)
37398c2ecf20Sopenharmony_ci{
37408c2ecf20Sopenharmony_ci	struct stv090x_state *state = fe->demodulator_priv;
37418c2ecf20Sopenharmony_ci	u32 reg;
37428c2ecf20Sopenharmony_ci
37438c2ecf20Sopenharmony_ci	reg = STV090x_READ_DEMOD(state, DISTXCTL);
37448c2ecf20Sopenharmony_ci	switch (tone) {
37458c2ecf20Sopenharmony_ci	case SEC_TONE_ON:
37468c2ecf20Sopenharmony_ci		STV090x_SETFIELD_Px(reg, DISTX_MODE_FIELD, 0);
37478c2ecf20Sopenharmony_ci		STV090x_SETFIELD_Px(reg, DISEQC_RESET_FIELD, 1);
37488c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0)
37498c2ecf20Sopenharmony_ci			goto err;
37508c2ecf20Sopenharmony_ci		STV090x_SETFIELD_Px(reg, DISEQC_RESET_FIELD, 0);
37518c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0)
37528c2ecf20Sopenharmony_ci			goto err;
37538c2ecf20Sopenharmony_ci		break;
37548c2ecf20Sopenharmony_ci
37558c2ecf20Sopenharmony_ci	case SEC_TONE_OFF:
37568c2ecf20Sopenharmony_ci		STV090x_SETFIELD_Px(reg, DISTX_MODE_FIELD, 0);
37578c2ecf20Sopenharmony_ci		STV090x_SETFIELD_Px(reg, DISEQC_RESET_FIELD, 1);
37588c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0)
37598c2ecf20Sopenharmony_ci			goto err;
37608c2ecf20Sopenharmony_ci		break;
37618c2ecf20Sopenharmony_ci	default:
37628c2ecf20Sopenharmony_ci		return -EINVAL;
37638c2ecf20Sopenharmony_ci	}
37648c2ecf20Sopenharmony_ci
37658c2ecf20Sopenharmony_ci	return 0;
37668c2ecf20Sopenharmony_cierr:
37678c2ecf20Sopenharmony_ci	dprintk(FE_ERROR, 1, "I/O error");
37688c2ecf20Sopenharmony_ci	return -1;
37698c2ecf20Sopenharmony_ci}
37708c2ecf20Sopenharmony_ci
37718c2ecf20Sopenharmony_ci
37728c2ecf20Sopenharmony_cistatic enum dvbfe_algo stv090x_frontend_algo(struct dvb_frontend *fe)
37738c2ecf20Sopenharmony_ci{
37748c2ecf20Sopenharmony_ci	return DVBFE_ALGO_CUSTOM;
37758c2ecf20Sopenharmony_ci}
37768c2ecf20Sopenharmony_ci
37778c2ecf20Sopenharmony_cistatic int stv090x_send_diseqc_msg(struct dvb_frontend *fe, struct dvb_diseqc_master_cmd *cmd)
37788c2ecf20Sopenharmony_ci{
37798c2ecf20Sopenharmony_ci	struct stv090x_state *state = fe->demodulator_priv;
37808c2ecf20Sopenharmony_ci	u32 reg, idle = 0, fifo_full = 1;
37818c2ecf20Sopenharmony_ci	int i;
37828c2ecf20Sopenharmony_ci
37838c2ecf20Sopenharmony_ci	reg = STV090x_READ_DEMOD(state, DISTXCTL);
37848c2ecf20Sopenharmony_ci
37858c2ecf20Sopenharmony_ci	STV090x_SETFIELD_Px(reg, DISTX_MODE_FIELD,
37868c2ecf20Sopenharmony_ci		(state->config->diseqc_envelope_mode) ? 4 : 2);
37878c2ecf20Sopenharmony_ci	STV090x_SETFIELD_Px(reg, DISEQC_RESET_FIELD, 1);
37888c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0)
37898c2ecf20Sopenharmony_ci		goto err;
37908c2ecf20Sopenharmony_ci	STV090x_SETFIELD_Px(reg, DISEQC_RESET_FIELD, 0);
37918c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0)
37928c2ecf20Sopenharmony_ci		goto err;
37938c2ecf20Sopenharmony_ci
37948c2ecf20Sopenharmony_ci	STV090x_SETFIELD_Px(reg, DIS_PRECHARGE_FIELD, 1);
37958c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0)
37968c2ecf20Sopenharmony_ci		goto err;
37978c2ecf20Sopenharmony_ci
37988c2ecf20Sopenharmony_ci	for (i = 0; i < cmd->msg_len; i++) {
37998c2ecf20Sopenharmony_ci
38008c2ecf20Sopenharmony_ci		while (fifo_full) {
38018c2ecf20Sopenharmony_ci			reg = STV090x_READ_DEMOD(state, DISTXSTATUS);
38028c2ecf20Sopenharmony_ci			fifo_full = STV090x_GETFIELD_Px(reg, FIFO_FULL_FIELD);
38038c2ecf20Sopenharmony_ci		}
38048c2ecf20Sopenharmony_ci
38058c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, DISTXDATA, cmd->msg[i]) < 0)
38068c2ecf20Sopenharmony_ci			goto err;
38078c2ecf20Sopenharmony_ci	}
38088c2ecf20Sopenharmony_ci	reg = STV090x_READ_DEMOD(state, DISTXCTL);
38098c2ecf20Sopenharmony_ci	STV090x_SETFIELD_Px(reg, DIS_PRECHARGE_FIELD, 0);
38108c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0)
38118c2ecf20Sopenharmony_ci		goto err;
38128c2ecf20Sopenharmony_ci
38138c2ecf20Sopenharmony_ci	i = 0;
38148c2ecf20Sopenharmony_ci
38158c2ecf20Sopenharmony_ci	while ((!idle) && (i < 10)) {
38168c2ecf20Sopenharmony_ci		reg = STV090x_READ_DEMOD(state, DISTXSTATUS);
38178c2ecf20Sopenharmony_ci		idle = STV090x_GETFIELD_Px(reg, TX_IDLE_FIELD);
38188c2ecf20Sopenharmony_ci		msleep(10);
38198c2ecf20Sopenharmony_ci		i++;
38208c2ecf20Sopenharmony_ci	}
38218c2ecf20Sopenharmony_ci
38228c2ecf20Sopenharmony_ci	return 0;
38238c2ecf20Sopenharmony_cierr:
38248c2ecf20Sopenharmony_ci	dprintk(FE_ERROR, 1, "I/O error");
38258c2ecf20Sopenharmony_ci	return -1;
38268c2ecf20Sopenharmony_ci}
38278c2ecf20Sopenharmony_ci
38288c2ecf20Sopenharmony_cistatic int stv090x_send_diseqc_burst(struct dvb_frontend *fe,
38298c2ecf20Sopenharmony_ci				     enum fe_sec_mini_cmd burst)
38308c2ecf20Sopenharmony_ci{
38318c2ecf20Sopenharmony_ci	struct stv090x_state *state = fe->demodulator_priv;
38328c2ecf20Sopenharmony_ci	u32 reg, idle = 0, fifo_full = 1;
38338c2ecf20Sopenharmony_ci	u8 mode, value;
38348c2ecf20Sopenharmony_ci	int i;
38358c2ecf20Sopenharmony_ci
38368c2ecf20Sopenharmony_ci	reg = STV090x_READ_DEMOD(state, DISTXCTL);
38378c2ecf20Sopenharmony_ci
38388c2ecf20Sopenharmony_ci	if (burst == SEC_MINI_A) {
38398c2ecf20Sopenharmony_ci		mode = (state->config->diseqc_envelope_mode) ? 5 : 3;
38408c2ecf20Sopenharmony_ci		value = 0x00;
38418c2ecf20Sopenharmony_ci	} else {
38428c2ecf20Sopenharmony_ci		mode = (state->config->diseqc_envelope_mode) ? 4 : 2;
38438c2ecf20Sopenharmony_ci		value = 0xFF;
38448c2ecf20Sopenharmony_ci	}
38458c2ecf20Sopenharmony_ci
38468c2ecf20Sopenharmony_ci	STV090x_SETFIELD_Px(reg, DISTX_MODE_FIELD, mode);
38478c2ecf20Sopenharmony_ci	STV090x_SETFIELD_Px(reg, DISEQC_RESET_FIELD, 1);
38488c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0)
38498c2ecf20Sopenharmony_ci		goto err;
38508c2ecf20Sopenharmony_ci	STV090x_SETFIELD_Px(reg, DISEQC_RESET_FIELD, 0);
38518c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0)
38528c2ecf20Sopenharmony_ci		goto err;
38538c2ecf20Sopenharmony_ci
38548c2ecf20Sopenharmony_ci	STV090x_SETFIELD_Px(reg, DIS_PRECHARGE_FIELD, 1);
38558c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0)
38568c2ecf20Sopenharmony_ci		goto err;
38578c2ecf20Sopenharmony_ci
38588c2ecf20Sopenharmony_ci	while (fifo_full) {
38598c2ecf20Sopenharmony_ci		reg = STV090x_READ_DEMOD(state, DISTXSTATUS);
38608c2ecf20Sopenharmony_ci		fifo_full = STV090x_GETFIELD_Px(reg, FIFO_FULL_FIELD);
38618c2ecf20Sopenharmony_ci	}
38628c2ecf20Sopenharmony_ci
38638c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, DISTXDATA, value) < 0)
38648c2ecf20Sopenharmony_ci		goto err;
38658c2ecf20Sopenharmony_ci
38668c2ecf20Sopenharmony_ci	reg = STV090x_READ_DEMOD(state, DISTXCTL);
38678c2ecf20Sopenharmony_ci	STV090x_SETFIELD_Px(reg, DIS_PRECHARGE_FIELD, 0);
38688c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0)
38698c2ecf20Sopenharmony_ci		goto err;
38708c2ecf20Sopenharmony_ci
38718c2ecf20Sopenharmony_ci	i = 0;
38728c2ecf20Sopenharmony_ci
38738c2ecf20Sopenharmony_ci	while ((!idle) && (i < 10)) {
38748c2ecf20Sopenharmony_ci		reg = STV090x_READ_DEMOD(state, DISTXSTATUS);
38758c2ecf20Sopenharmony_ci		idle = STV090x_GETFIELD_Px(reg, TX_IDLE_FIELD);
38768c2ecf20Sopenharmony_ci		msleep(10);
38778c2ecf20Sopenharmony_ci		i++;
38788c2ecf20Sopenharmony_ci	}
38798c2ecf20Sopenharmony_ci
38808c2ecf20Sopenharmony_ci	return 0;
38818c2ecf20Sopenharmony_cierr:
38828c2ecf20Sopenharmony_ci	dprintk(FE_ERROR, 1, "I/O error");
38838c2ecf20Sopenharmony_ci	return -1;
38848c2ecf20Sopenharmony_ci}
38858c2ecf20Sopenharmony_ci
38868c2ecf20Sopenharmony_cistatic int stv090x_recv_slave_reply(struct dvb_frontend *fe, struct dvb_diseqc_slave_reply *reply)
38878c2ecf20Sopenharmony_ci{
38888c2ecf20Sopenharmony_ci	struct stv090x_state *state = fe->demodulator_priv;
38898c2ecf20Sopenharmony_ci	u32 reg = 0, i = 0, rx_end = 0;
38908c2ecf20Sopenharmony_ci
38918c2ecf20Sopenharmony_ci	while ((rx_end != 1) && (i < 10)) {
38928c2ecf20Sopenharmony_ci		msleep(10);
38938c2ecf20Sopenharmony_ci		i++;
38948c2ecf20Sopenharmony_ci		reg = STV090x_READ_DEMOD(state, DISRX_ST0);
38958c2ecf20Sopenharmony_ci		rx_end = STV090x_GETFIELD_Px(reg, RX_END_FIELD);
38968c2ecf20Sopenharmony_ci	}
38978c2ecf20Sopenharmony_ci
38988c2ecf20Sopenharmony_ci	if (rx_end) {
38998c2ecf20Sopenharmony_ci		reply->msg_len = STV090x_GETFIELD_Px(reg, FIFO_BYTENBR_FIELD);
39008c2ecf20Sopenharmony_ci		for (i = 0; i < reply->msg_len; i++)
39018c2ecf20Sopenharmony_ci			reply->msg[i] = STV090x_READ_DEMOD(state, DISRXDATA);
39028c2ecf20Sopenharmony_ci	}
39038c2ecf20Sopenharmony_ci
39048c2ecf20Sopenharmony_ci	return 0;
39058c2ecf20Sopenharmony_ci}
39068c2ecf20Sopenharmony_ci
39078c2ecf20Sopenharmony_cistatic int stv090x_sleep(struct dvb_frontend *fe)
39088c2ecf20Sopenharmony_ci{
39098c2ecf20Sopenharmony_ci	struct stv090x_state *state = fe->demodulator_priv;
39108c2ecf20Sopenharmony_ci	u32 reg;
39118c2ecf20Sopenharmony_ci	u8 full_standby = 0;
39128c2ecf20Sopenharmony_ci
39138c2ecf20Sopenharmony_ci	if (stv090x_i2c_gate_ctrl(state, 1) < 0)
39148c2ecf20Sopenharmony_ci		goto err;
39158c2ecf20Sopenharmony_ci
39168c2ecf20Sopenharmony_ci	if (state->config->tuner_sleep) {
39178c2ecf20Sopenharmony_ci		if (state->config->tuner_sleep(fe) < 0)
39188c2ecf20Sopenharmony_ci			goto err_gateoff;
39198c2ecf20Sopenharmony_ci	}
39208c2ecf20Sopenharmony_ci
39218c2ecf20Sopenharmony_ci	if (stv090x_i2c_gate_ctrl(state, 0) < 0)
39228c2ecf20Sopenharmony_ci		goto err;
39238c2ecf20Sopenharmony_ci
39248c2ecf20Sopenharmony_ci	dprintk(FE_DEBUG, 1, "Set %s(%d) to sleep",
39258c2ecf20Sopenharmony_ci		state->device == STV0900 ? "STV0900" : "STV0903",
39268c2ecf20Sopenharmony_ci		state->demod);
39278c2ecf20Sopenharmony_ci
39288c2ecf20Sopenharmony_ci	mutex_lock(&state->internal->demod_lock);
39298c2ecf20Sopenharmony_ci
39308c2ecf20Sopenharmony_ci	switch (state->demod) {
39318c2ecf20Sopenharmony_ci	case STV090x_DEMODULATOR_0:
39328c2ecf20Sopenharmony_ci		/* power off ADC 1 */
39338c2ecf20Sopenharmony_ci		reg = stv090x_read_reg(state, STV090x_TSTTNR1);
39348c2ecf20Sopenharmony_ci		STV090x_SETFIELD(reg, ADC1_PON_FIELD, 0);
39358c2ecf20Sopenharmony_ci		if (stv090x_write_reg(state, STV090x_TSTTNR1, reg) < 0)
39368c2ecf20Sopenharmony_ci			goto err_unlock;
39378c2ecf20Sopenharmony_ci		/* power off DiSEqC 1 */
39388c2ecf20Sopenharmony_ci		reg = stv090x_read_reg(state, STV090x_TSTTNR2);
39398c2ecf20Sopenharmony_ci		STV090x_SETFIELD(reg, DISEQC1_PON_FIELD, 0);
39408c2ecf20Sopenharmony_ci		if (stv090x_write_reg(state, STV090x_TSTTNR2, reg) < 0)
39418c2ecf20Sopenharmony_ci			goto err_unlock;
39428c2ecf20Sopenharmony_ci
39438c2ecf20Sopenharmony_ci		/* check whether path 2 is already sleeping, that is when
39448c2ecf20Sopenharmony_ci		   ADC2 is off */
39458c2ecf20Sopenharmony_ci		reg = stv090x_read_reg(state, STV090x_TSTTNR3);
39468c2ecf20Sopenharmony_ci		if (STV090x_GETFIELD(reg, ADC2_PON_FIELD) == 0)
39478c2ecf20Sopenharmony_ci			full_standby = 1;
39488c2ecf20Sopenharmony_ci
39498c2ecf20Sopenharmony_ci		/* stop clocks */
39508c2ecf20Sopenharmony_ci		reg = stv090x_read_reg(state, STV090x_STOPCLK1);
39518c2ecf20Sopenharmony_ci		/* packet delineator 1 clock */
39528c2ecf20Sopenharmony_ci		STV090x_SETFIELD(reg, STOP_CLKPKDT1_FIELD, 1);
39538c2ecf20Sopenharmony_ci		/* ADC 1 clock */
39548c2ecf20Sopenharmony_ci		STV090x_SETFIELD(reg, STOP_CLKADCI1_FIELD, 1);
39558c2ecf20Sopenharmony_ci		/* FEC clock is shared between the two paths, only stop it
39568c2ecf20Sopenharmony_ci		   when full standby is possible */
39578c2ecf20Sopenharmony_ci		if (full_standby)
39588c2ecf20Sopenharmony_ci			STV090x_SETFIELD(reg, STOP_CLKFEC_FIELD, 1);
39598c2ecf20Sopenharmony_ci		if (stv090x_write_reg(state, STV090x_STOPCLK1, reg) < 0)
39608c2ecf20Sopenharmony_ci			goto err_unlock;
39618c2ecf20Sopenharmony_ci		reg = stv090x_read_reg(state, STV090x_STOPCLK2);
39628c2ecf20Sopenharmony_ci		/* sampling 1 clock */
39638c2ecf20Sopenharmony_ci		STV090x_SETFIELD(reg, STOP_CLKSAMP1_FIELD, 1);
39648c2ecf20Sopenharmony_ci		/* viterbi 1 clock */
39658c2ecf20Sopenharmony_ci		STV090x_SETFIELD(reg, STOP_CLKVIT1_FIELD, 1);
39668c2ecf20Sopenharmony_ci		/* TS clock is shared between the two paths, only stop it
39678c2ecf20Sopenharmony_ci		   when full standby is possible */
39688c2ecf20Sopenharmony_ci		if (full_standby)
39698c2ecf20Sopenharmony_ci			STV090x_SETFIELD(reg, STOP_CLKTS_FIELD, 1);
39708c2ecf20Sopenharmony_ci		if (stv090x_write_reg(state, STV090x_STOPCLK2, reg) < 0)
39718c2ecf20Sopenharmony_ci			goto err_unlock;
39728c2ecf20Sopenharmony_ci		break;
39738c2ecf20Sopenharmony_ci
39748c2ecf20Sopenharmony_ci	case STV090x_DEMODULATOR_1:
39758c2ecf20Sopenharmony_ci		/* power off ADC 2 */
39768c2ecf20Sopenharmony_ci		reg = stv090x_read_reg(state, STV090x_TSTTNR3);
39778c2ecf20Sopenharmony_ci		STV090x_SETFIELD(reg, ADC2_PON_FIELD, 0);
39788c2ecf20Sopenharmony_ci		if (stv090x_write_reg(state, STV090x_TSTTNR3, reg) < 0)
39798c2ecf20Sopenharmony_ci			goto err_unlock;
39808c2ecf20Sopenharmony_ci		/* power off DiSEqC 2 */
39818c2ecf20Sopenharmony_ci		reg = stv090x_read_reg(state, STV090x_TSTTNR4);
39828c2ecf20Sopenharmony_ci		STV090x_SETFIELD(reg, DISEQC2_PON_FIELD, 0);
39838c2ecf20Sopenharmony_ci		if (stv090x_write_reg(state, STV090x_TSTTNR4, reg) < 0)
39848c2ecf20Sopenharmony_ci			goto err_unlock;
39858c2ecf20Sopenharmony_ci
39868c2ecf20Sopenharmony_ci		/* check whether path 1 is already sleeping, that is when
39878c2ecf20Sopenharmony_ci		   ADC1 is off */
39888c2ecf20Sopenharmony_ci		reg = stv090x_read_reg(state, STV090x_TSTTNR1);
39898c2ecf20Sopenharmony_ci		if (STV090x_GETFIELD(reg, ADC1_PON_FIELD) == 0)
39908c2ecf20Sopenharmony_ci			full_standby = 1;
39918c2ecf20Sopenharmony_ci
39928c2ecf20Sopenharmony_ci		/* stop clocks */
39938c2ecf20Sopenharmony_ci		reg = stv090x_read_reg(state, STV090x_STOPCLK1);
39948c2ecf20Sopenharmony_ci		/* packet delineator 2 clock */
39958c2ecf20Sopenharmony_ci		STV090x_SETFIELD(reg, STOP_CLKPKDT2_FIELD, 1);
39968c2ecf20Sopenharmony_ci		/* ADC 2 clock */
39978c2ecf20Sopenharmony_ci		STV090x_SETFIELD(reg, STOP_CLKADCI2_FIELD, 1);
39988c2ecf20Sopenharmony_ci		/* FEC clock is shared between the two paths, only stop it
39998c2ecf20Sopenharmony_ci		   when full standby is possible */
40008c2ecf20Sopenharmony_ci		if (full_standby)
40018c2ecf20Sopenharmony_ci			STV090x_SETFIELD(reg, STOP_CLKFEC_FIELD, 1);
40028c2ecf20Sopenharmony_ci		if (stv090x_write_reg(state, STV090x_STOPCLK1, reg) < 0)
40038c2ecf20Sopenharmony_ci			goto err_unlock;
40048c2ecf20Sopenharmony_ci		reg = stv090x_read_reg(state, STV090x_STOPCLK2);
40058c2ecf20Sopenharmony_ci		/* sampling 2 clock */
40068c2ecf20Sopenharmony_ci		STV090x_SETFIELD(reg, STOP_CLKSAMP2_FIELD, 1);
40078c2ecf20Sopenharmony_ci		/* viterbi 2 clock */
40088c2ecf20Sopenharmony_ci		STV090x_SETFIELD(reg, STOP_CLKVIT2_FIELD, 1);
40098c2ecf20Sopenharmony_ci		/* TS clock is shared between the two paths, only stop it
40108c2ecf20Sopenharmony_ci		   when full standby is possible */
40118c2ecf20Sopenharmony_ci		if (full_standby)
40128c2ecf20Sopenharmony_ci			STV090x_SETFIELD(reg, STOP_CLKTS_FIELD, 1);
40138c2ecf20Sopenharmony_ci		if (stv090x_write_reg(state, STV090x_STOPCLK2, reg) < 0)
40148c2ecf20Sopenharmony_ci			goto err_unlock;
40158c2ecf20Sopenharmony_ci		break;
40168c2ecf20Sopenharmony_ci
40178c2ecf20Sopenharmony_ci	default:
40188c2ecf20Sopenharmony_ci		dprintk(FE_ERROR, 1, "Wrong demodulator!");
40198c2ecf20Sopenharmony_ci		break;
40208c2ecf20Sopenharmony_ci	}
40218c2ecf20Sopenharmony_ci
40228c2ecf20Sopenharmony_ci	if (full_standby) {
40238c2ecf20Sopenharmony_ci		/* general power off */
40248c2ecf20Sopenharmony_ci		reg = stv090x_read_reg(state, STV090x_SYNTCTRL);
40258c2ecf20Sopenharmony_ci		STV090x_SETFIELD(reg, STANDBY_FIELD, 0x01);
40268c2ecf20Sopenharmony_ci		if (stv090x_write_reg(state, STV090x_SYNTCTRL, reg) < 0)
40278c2ecf20Sopenharmony_ci			goto err_unlock;
40288c2ecf20Sopenharmony_ci	}
40298c2ecf20Sopenharmony_ci
40308c2ecf20Sopenharmony_ci	mutex_unlock(&state->internal->demod_lock);
40318c2ecf20Sopenharmony_ci	return 0;
40328c2ecf20Sopenharmony_ci
40338c2ecf20Sopenharmony_cierr_gateoff:
40348c2ecf20Sopenharmony_ci	stv090x_i2c_gate_ctrl(state, 0);
40358c2ecf20Sopenharmony_ci	goto err;
40368c2ecf20Sopenharmony_cierr_unlock:
40378c2ecf20Sopenharmony_ci	mutex_unlock(&state->internal->demod_lock);
40388c2ecf20Sopenharmony_cierr:
40398c2ecf20Sopenharmony_ci	dprintk(FE_ERROR, 1, "I/O error");
40408c2ecf20Sopenharmony_ci	return -1;
40418c2ecf20Sopenharmony_ci}
40428c2ecf20Sopenharmony_ci
40438c2ecf20Sopenharmony_cistatic int stv090x_wakeup(struct dvb_frontend *fe)
40448c2ecf20Sopenharmony_ci{
40458c2ecf20Sopenharmony_ci	struct stv090x_state *state = fe->demodulator_priv;
40468c2ecf20Sopenharmony_ci	u32 reg;
40478c2ecf20Sopenharmony_ci
40488c2ecf20Sopenharmony_ci	dprintk(FE_DEBUG, 1, "Wake %s(%d) from standby",
40498c2ecf20Sopenharmony_ci		state->device == STV0900 ? "STV0900" : "STV0903",
40508c2ecf20Sopenharmony_ci		state->demod);
40518c2ecf20Sopenharmony_ci
40528c2ecf20Sopenharmony_ci	mutex_lock(&state->internal->demod_lock);
40538c2ecf20Sopenharmony_ci
40548c2ecf20Sopenharmony_ci	/* general power on */
40558c2ecf20Sopenharmony_ci	reg = stv090x_read_reg(state, STV090x_SYNTCTRL);
40568c2ecf20Sopenharmony_ci	STV090x_SETFIELD(reg, STANDBY_FIELD, 0x00);
40578c2ecf20Sopenharmony_ci	if (stv090x_write_reg(state, STV090x_SYNTCTRL, reg) < 0)
40588c2ecf20Sopenharmony_ci		goto err;
40598c2ecf20Sopenharmony_ci
40608c2ecf20Sopenharmony_ci	switch (state->demod) {
40618c2ecf20Sopenharmony_ci	case STV090x_DEMODULATOR_0:
40628c2ecf20Sopenharmony_ci		/* power on ADC 1 */
40638c2ecf20Sopenharmony_ci		reg = stv090x_read_reg(state, STV090x_TSTTNR1);
40648c2ecf20Sopenharmony_ci		STV090x_SETFIELD(reg, ADC1_PON_FIELD, 1);
40658c2ecf20Sopenharmony_ci		if (stv090x_write_reg(state, STV090x_TSTTNR1, reg) < 0)
40668c2ecf20Sopenharmony_ci			goto err;
40678c2ecf20Sopenharmony_ci		/* power on DiSEqC 1 */
40688c2ecf20Sopenharmony_ci		reg = stv090x_read_reg(state, STV090x_TSTTNR2);
40698c2ecf20Sopenharmony_ci		STV090x_SETFIELD(reg, DISEQC1_PON_FIELD, 1);
40708c2ecf20Sopenharmony_ci		if (stv090x_write_reg(state, STV090x_TSTTNR2, reg) < 0)
40718c2ecf20Sopenharmony_ci			goto err;
40728c2ecf20Sopenharmony_ci
40738c2ecf20Sopenharmony_ci		/* activate clocks */
40748c2ecf20Sopenharmony_ci		reg = stv090x_read_reg(state, STV090x_STOPCLK1);
40758c2ecf20Sopenharmony_ci		/* packet delineator 1 clock */
40768c2ecf20Sopenharmony_ci		STV090x_SETFIELD(reg, STOP_CLKPKDT1_FIELD, 0);
40778c2ecf20Sopenharmony_ci		/* ADC 1 clock */
40788c2ecf20Sopenharmony_ci		STV090x_SETFIELD(reg, STOP_CLKADCI1_FIELD, 0);
40798c2ecf20Sopenharmony_ci		/* FEC clock */
40808c2ecf20Sopenharmony_ci		STV090x_SETFIELD(reg, STOP_CLKFEC_FIELD, 0);
40818c2ecf20Sopenharmony_ci		if (stv090x_write_reg(state, STV090x_STOPCLK1, reg) < 0)
40828c2ecf20Sopenharmony_ci			goto err;
40838c2ecf20Sopenharmony_ci		reg = stv090x_read_reg(state, STV090x_STOPCLK2);
40848c2ecf20Sopenharmony_ci		/* sampling 1 clock */
40858c2ecf20Sopenharmony_ci		STV090x_SETFIELD(reg, STOP_CLKSAMP1_FIELD, 0);
40868c2ecf20Sopenharmony_ci		/* viterbi 1 clock */
40878c2ecf20Sopenharmony_ci		STV090x_SETFIELD(reg, STOP_CLKVIT1_FIELD, 0);
40888c2ecf20Sopenharmony_ci		/* TS clock */
40898c2ecf20Sopenharmony_ci		STV090x_SETFIELD(reg, STOP_CLKTS_FIELD, 0);
40908c2ecf20Sopenharmony_ci		if (stv090x_write_reg(state, STV090x_STOPCLK2, reg) < 0)
40918c2ecf20Sopenharmony_ci			goto err;
40928c2ecf20Sopenharmony_ci		break;
40938c2ecf20Sopenharmony_ci
40948c2ecf20Sopenharmony_ci	case STV090x_DEMODULATOR_1:
40958c2ecf20Sopenharmony_ci		/* power on ADC 2 */
40968c2ecf20Sopenharmony_ci		reg = stv090x_read_reg(state, STV090x_TSTTNR3);
40978c2ecf20Sopenharmony_ci		STV090x_SETFIELD(reg, ADC2_PON_FIELD, 1);
40988c2ecf20Sopenharmony_ci		if (stv090x_write_reg(state, STV090x_TSTTNR3, reg) < 0)
40998c2ecf20Sopenharmony_ci			goto err;
41008c2ecf20Sopenharmony_ci		/* power on DiSEqC 2 */
41018c2ecf20Sopenharmony_ci		reg = stv090x_read_reg(state, STV090x_TSTTNR4);
41028c2ecf20Sopenharmony_ci		STV090x_SETFIELD(reg, DISEQC2_PON_FIELD, 1);
41038c2ecf20Sopenharmony_ci		if (stv090x_write_reg(state, STV090x_TSTTNR4, reg) < 0)
41048c2ecf20Sopenharmony_ci			goto err;
41058c2ecf20Sopenharmony_ci
41068c2ecf20Sopenharmony_ci		/* activate clocks */
41078c2ecf20Sopenharmony_ci		reg = stv090x_read_reg(state, STV090x_STOPCLK1);
41088c2ecf20Sopenharmony_ci		/* packet delineator 2 clock */
41098c2ecf20Sopenharmony_ci		STV090x_SETFIELD(reg, STOP_CLKPKDT2_FIELD, 0);
41108c2ecf20Sopenharmony_ci		/* ADC 2 clock */
41118c2ecf20Sopenharmony_ci		STV090x_SETFIELD(reg, STOP_CLKADCI2_FIELD, 0);
41128c2ecf20Sopenharmony_ci		/* FEC clock */
41138c2ecf20Sopenharmony_ci		STV090x_SETFIELD(reg, STOP_CLKFEC_FIELD, 0);
41148c2ecf20Sopenharmony_ci		if (stv090x_write_reg(state, STV090x_STOPCLK1, reg) < 0)
41158c2ecf20Sopenharmony_ci			goto err;
41168c2ecf20Sopenharmony_ci		reg = stv090x_read_reg(state, STV090x_STOPCLK2);
41178c2ecf20Sopenharmony_ci		/* sampling 2 clock */
41188c2ecf20Sopenharmony_ci		STV090x_SETFIELD(reg, STOP_CLKSAMP2_FIELD, 0);
41198c2ecf20Sopenharmony_ci		/* viterbi 2 clock */
41208c2ecf20Sopenharmony_ci		STV090x_SETFIELD(reg, STOP_CLKVIT2_FIELD, 0);
41218c2ecf20Sopenharmony_ci		/* TS clock */
41228c2ecf20Sopenharmony_ci		STV090x_SETFIELD(reg, STOP_CLKTS_FIELD, 0);
41238c2ecf20Sopenharmony_ci		if (stv090x_write_reg(state, STV090x_STOPCLK2, reg) < 0)
41248c2ecf20Sopenharmony_ci			goto err;
41258c2ecf20Sopenharmony_ci		break;
41268c2ecf20Sopenharmony_ci
41278c2ecf20Sopenharmony_ci	default:
41288c2ecf20Sopenharmony_ci		dprintk(FE_ERROR, 1, "Wrong demodulator!");
41298c2ecf20Sopenharmony_ci		break;
41308c2ecf20Sopenharmony_ci	}
41318c2ecf20Sopenharmony_ci
41328c2ecf20Sopenharmony_ci	mutex_unlock(&state->internal->demod_lock);
41338c2ecf20Sopenharmony_ci	return 0;
41348c2ecf20Sopenharmony_cierr:
41358c2ecf20Sopenharmony_ci	mutex_unlock(&state->internal->demod_lock);
41368c2ecf20Sopenharmony_ci	dprintk(FE_ERROR, 1, "I/O error");
41378c2ecf20Sopenharmony_ci	return -1;
41388c2ecf20Sopenharmony_ci}
41398c2ecf20Sopenharmony_ci
41408c2ecf20Sopenharmony_cistatic void stv090x_release(struct dvb_frontend *fe)
41418c2ecf20Sopenharmony_ci{
41428c2ecf20Sopenharmony_ci	struct stv090x_state *state = fe->demodulator_priv;
41438c2ecf20Sopenharmony_ci
41448c2ecf20Sopenharmony_ci	state->internal->num_used--;
41458c2ecf20Sopenharmony_ci	if (state->internal->num_used <= 0) {
41468c2ecf20Sopenharmony_ci
41478c2ecf20Sopenharmony_ci		dprintk(FE_ERROR, 1, "Actually removing");
41488c2ecf20Sopenharmony_ci
41498c2ecf20Sopenharmony_ci		remove_dev(state->internal);
41508c2ecf20Sopenharmony_ci		kfree(state->internal);
41518c2ecf20Sopenharmony_ci	}
41528c2ecf20Sopenharmony_ci
41538c2ecf20Sopenharmony_ci	kfree(state);
41548c2ecf20Sopenharmony_ci}
41558c2ecf20Sopenharmony_ci
41568c2ecf20Sopenharmony_cistatic int stv090x_ldpc_mode(struct stv090x_state *state, enum stv090x_mode ldpc_mode)
41578c2ecf20Sopenharmony_ci{
41588c2ecf20Sopenharmony_ci	u32 reg = 0;
41598c2ecf20Sopenharmony_ci
41608c2ecf20Sopenharmony_ci	reg = stv090x_read_reg(state, STV090x_GENCFG);
41618c2ecf20Sopenharmony_ci
41628c2ecf20Sopenharmony_ci	switch (ldpc_mode) {
41638c2ecf20Sopenharmony_ci	case STV090x_DUAL:
41648c2ecf20Sopenharmony_ci	default:
41658c2ecf20Sopenharmony_ci		if ((state->demod_mode != STV090x_DUAL) || (STV090x_GETFIELD(reg, DDEMOD_FIELD) != 1)) {
41668c2ecf20Sopenharmony_ci			/* set LDPC to dual mode */
41678c2ecf20Sopenharmony_ci			if (stv090x_write_reg(state, STV090x_GENCFG, 0x1d) < 0)
41688c2ecf20Sopenharmony_ci				goto err;
41698c2ecf20Sopenharmony_ci
41708c2ecf20Sopenharmony_ci			state->demod_mode = STV090x_DUAL;
41718c2ecf20Sopenharmony_ci
41728c2ecf20Sopenharmony_ci			reg = stv090x_read_reg(state, STV090x_TSTRES0);
41738c2ecf20Sopenharmony_ci			STV090x_SETFIELD(reg, FRESFEC_FIELD, 0x1);
41748c2ecf20Sopenharmony_ci			if (stv090x_write_reg(state, STV090x_TSTRES0, reg) < 0)
41758c2ecf20Sopenharmony_ci				goto err;
41768c2ecf20Sopenharmony_ci			STV090x_SETFIELD(reg, FRESFEC_FIELD, 0x0);
41778c2ecf20Sopenharmony_ci			if (stv090x_write_reg(state, STV090x_TSTRES0, reg) < 0)
41788c2ecf20Sopenharmony_ci				goto err;
41798c2ecf20Sopenharmony_ci
41808c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, MODCODLST0, 0xff) < 0)
41818c2ecf20Sopenharmony_ci				goto err;
41828c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, MODCODLST1, 0xff) < 0)
41838c2ecf20Sopenharmony_ci				goto err;
41848c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, MODCODLST2, 0xff) < 0)
41858c2ecf20Sopenharmony_ci				goto err;
41868c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, MODCODLST3, 0xff) < 0)
41878c2ecf20Sopenharmony_ci				goto err;
41888c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, MODCODLST4, 0xff) < 0)
41898c2ecf20Sopenharmony_ci				goto err;
41908c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, MODCODLST5, 0xff) < 0)
41918c2ecf20Sopenharmony_ci				goto err;
41928c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, MODCODLST6, 0xff) < 0)
41938c2ecf20Sopenharmony_ci				goto err;
41948c2ecf20Sopenharmony_ci
41958c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, MODCODLST7, 0xcc) < 0)
41968c2ecf20Sopenharmony_ci				goto err;
41978c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, MODCODLST8, 0xcc) < 0)
41988c2ecf20Sopenharmony_ci				goto err;
41998c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, MODCODLST9, 0xcc) < 0)
42008c2ecf20Sopenharmony_ci				goto err;
42018c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, MODCODLSTA, 0xcc) < 0)
42028c2ecf20Sopenharmony_ci				goto err;
42038c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, MODCODLSTB, 0xcc) < 0)
42048c2ecf20Sopenharmony_ci				goto err;
42058c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, MODCODLSTC, 0xcc) < 0)
42068c2ecf20Sopenharmony_ci				goto err;
42078c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, MODCODLSTD, 0xcc) < 0)
42088c2ecf20Sopenharmony_ci				goto err;
42098c2ecf20Sopenharmony_ci
42108c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, MODCODLSTE, 0xff) < 0)
42118c2ecf20Sopenharmony_ci				goto err;
42128c2ecf20Sopenharmony_ci			if (STV090x_WRITE_DEMOD(state, MODCODLSTF, 0xcf) < 0)
42138c2ecf20Sopenharmony_ci				goto err;
42148c2ecf20Sopenharmony_ci		}
42158c2ecf20Sopenharmony_ci		break;
42168c2ecf20Sopenharmony_ci
42178c2ecf20Sopenharmony_ci	case STV090x_SINGLE:
42188c2ecf20Sopenharmony_ci		if (stv090x_stop_modcod(state) < 0)
42198c2ecf20Sopenharmony_ci			goto err;
42208c2ecf20Sopenharmony_ci		if (stv090x_activate_modcod_single(state) < 0)
42218c2ecf20Sopenharmony_ci			goto err;
42228c2ecf20Sopenharmony_ci
42238c2ecf20Sopenharmony_ci		if (state->demod == STV090x_DEMODULATOR_1) {
42248c2ecf20Sopenharmony_ci			if (stv090x_write_reg(state, STV090x_GENCFG, 0x06) < 0) /* path 2 */
42258c2ecf20Sopenharmony_ci				goto err;
42268c2ecf20Sopenharmony_ci		} else {
42278c2ecf20Sopenharmony_ci			if (stv090x_write_reg(state, STV090x_GENCFG, 0x04) < 0) /* path 1 */
42288c2ecf20Sopenharmony_ci				goto err;
42298c2ecf20Sopenharmony_ci		}
42308c2ecf20Sopenharmony_ci
42318c2ecf20Sopenharmony_ci		reg = stv090x_read_reg(state, STV090x_TSTRES0);
42328c2ecf20Sopenharmony_ci		STV090x_SETFIELD(reg, FRESFEC_FIELD, 0x1);
42338c2ecf20Sopenharmony_ci		if (stv090x_write_reg(state, STV090x_TSTRES0, reg) < 0)
42348c2ecf20Sopenharmony_ci			goto err;
42358c2ecf20Sopenharmony_ci		STV090x_SETFIELD(reg, FRESFEC_FIELD, 0x0);
42368c2ecf20Sopenharmony_ci		if (stv090x_write_reg(state, STV090x_TSTRES0, reg) < 0)
42378c2ecf20Sopenharmony_ci			goto err;
42388c2ecf20Sopenharmony_ci
42398c2ecf20Sopenharmony_ci		reg = STV090x_READ_DEMOD(state, PDELCTRL1);
42408c2ecf20Sopenharmony_ci		STV090x_SETFIELD_Px(reg, ALGOSWRST_FIELD, 0x01);
42418c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, PDELCTRL1, reg) < 0)
42428c2ecf20Sopenharmony_ci			goto err;
42438c2ecf20Sopenharmony_ci		STV090x_SETFIELD_Px(reg, ALGOSWRST_FIELD, 0x00);
42448c2ecf20Sopenharmony_ci		if (STV090x_WRITE_DEMOD(state, PDELCTRL1, reg) < 0)
42458c2ecf20Sopenharmony_ci			goto err;
42468c2ecf20Sopenharmony_ci		break;
42478c2ecf20Sopenharmony_ci	}
42488c2ecf20Sopenharmony_ci
42498c2ecf20Sopenharmony_ci	return 0;
42508c2ecf20Sopenharmony_cierr:
42518c2ecf20Sopenharmony_ci	dprintk(FE_ERROR, 1, "I/O error");
42528c2ecf20Sopenharmony_ci	return -1;
42538c2ecf20Sopenharmony_ci}
42548c2ecf20Sopenharmony_ci
42558c2ecf20Sopenharmony_ci/* return (Hz), clk in Hz*/
42568c2ecf20Sopenharmony_cistatic u32 stv090x_get_mclk(struct stv090x_state *state)
42578c2ecf20Sopenharmony_ci{
42588c2ecf20Sopenharmony_ci	const struct stv090x_config *config = state->config;
42598c2ecf20Sopenharmony_ci	u32 div, reg;
42608c2ecf20Sopenharmony_ci	u8 ratio;
42618c2ecf20Sopenharmony_ci
42628c2ecf20Sopenharmony_ci	div = stv090x_read_reg(state, STV090x_NCOARSE);
42638c2ecf20Sopenharmony_ci	reg = stv090x_read_reg(state, STV090x_SYNTCTRL);
42648c2ecf20Sopenharmony_ci	ratio = STV090x_GETFIELD(reg, SELX1RATIO_FIELD) ? 4 : 6;
42658c2ecf20Sopenharmony_ci
42668c2ecf20Sopenharmony_ci	return (div + 1) * config->xtal / ratio; /* kHz */
42678c2ecf20Sopenharmony_ci}
42688c2ecf20Sopenharmony_ci
42698c2ecf20Sopenharmony_cistatic int stv090x_set_mclk(struct stv090x_state *state, u32 mclk, u32 clk)
42708c2ecf20Sopenharmony_ci{
42718c2ecf20Sopenharmony_ci	const struct stv090x_config *config = state->config;
42728c2ecf20Sopenharmony_ci	u32 reg, div, clk_sel;
42738c2ecf20Sopenharmony_ci
42748c2ecf20Sopenharmony_ci	reg = stv090x_read_reg(state, STV090x_SYNTCTRL);
42758c2ecf20Sopenharmony_ci	clk_sel = ((STV090x_GETFIELD(reg, SELX1RATIO_FIELD) == 1) ? 4 : 6);
42768c2ecf20Sopenharmony_ci
42778c2ecf20Sopenharmony_ci	div = ((clk_sel * mclk) / config->xtal) - 1;
42788c2ecf20Sopenharmony_ci
42798c2ecf20Sopenharmony_ci	reg = stv090x_read_reg(state, STV090x_NCOARSE);
42808c2ecf20Sopenharmony_ci	STV090x_SETFIELD(reg, M_DIV_FIELD, div);
42818c2ecf20Sopenharmony_ci	if (stv090x_write_reg(state, STV090x_NCOARSE, reg) < 0)
42828c2ecf20Sopenharmony_ci		goto err;
42838c2ecf20Sopenharmony_ci
42848c2ecf20Sopenharmony_ci	state->internal->mclk = stv090x_get_mclk(state);
42858c2ecf20Sopenharmony_ci
42868c2ecf20Sopenharmony_ci	/*Set the DiseqC frequency to 22KHz */
42878c2ecf20Sopenharmony_ci	div = state->internal->mclk / 704000;
42888c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, F22TX, div) < 0)
42898c2ecf20Sopenharmony_ci		goto err;
42908c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, F22RX, div) < 0)
42918c2ecf20Sopenharmony_ci		goto err;
42928c2ecf20Sopenharmony_ci
42938c2ecf20Sopenharmony_ci	return 0;
42948c2ecf20Sopenharmony_cierr:
42958c2ecf20Sopenharmony_ci	dprintk(FE_ERROR, 1, "I/O error");
42968c2ecf20Sopenharmony_ci	return -1;
42978c2ecf20Sopenharmony_ci}
42988c2ecf20Sopenharmony_ci
42998c2ecf20Sopenharmony_cistatic int stv0900_set_tspath(struct stv090x_state *state)
43008c2ecf20Sopenharmony_ci{
43018c2ecf20Sopenharmony_ci	u32 reg;
43028c2ecf20Sopenharmony_ci
43038c2ecf20Sopenharmony_ci	if (state->internal->dev_ver >= 0x20) {
43048c2ecf20Sopenharmony_ci		switch (state->config->ts1_mode) {
43058c2ecf20Sopenharmony_ci		case STV090x_TSMODE_PARALLEL_PUNCTURED:
43068c2ecf20Sopenharmony_ci		case STV090x_TSMODE_DVBCI:
43078c2ecf20Sopenharmony_ci			switch (state->config->ts2_mode) {
43088c2ecf20Sopenharmony_ci			case STV090x_TSMODE_SERIAL_PUNCTURED:
43098c2ecf20Sopenharmony_ci			case STV090x_TSMODE_SERIAL_CONTINUOUS:
43108c2ecf20Sopenharmony_ci			default:
43118c2ecf20Sopenharmony_ci				stv090x_write_reg(state, STV090x_TSGENERAL, 0x00);
43128c2ecf20Sopenharmony_ci				break;
43138c2ecf20Sopenharmony_ci
43148c2ecf20Sopenharmony_ci			case STV090x_TSMODE_PARALLEL_PUNCTURED:
43158c2ecf20Sopenharmony_ci			case STV090x_TSMODE_DVBCI:
43168c2ecf20Sopenharmony_ci				if (stv090x_write_reg(state, STV090x_TSGENERAL, 0x06) < 0) /* Mux'd stream mode */
43178c2ecf20Sopenharmony_ci					goto err;
43188c2ecf20Sopenharmony_ci				reg = stv090x_read_reg(state, STV090x_P1_TSCFGM);
43198c2ecf20Sopenharmony_ci				STV090x_SETFIELD_Px(reg, TSFIFO_MANSPEED_FIELD, 3);
43208c2ecf20Sopenharmony_ci				if (stv090x_write_reg(state, STV090x_P1_TSCFGM, reg) < 0)
43218c2ecf20Sopenharmony_ci					goto err;
43228c2ecf20Sopenharmony_ci				reg = stv090x_read_reg(state, STV090x_P2_TSCFGM);
43238c2ecf20Sopenharmony_ci				STV090x_SETFIELD_Px(reg, TSFIFO_MANSPEED_FIELD, 3);
43248c2ecf20Sopenharmony_ci				if (stv090x_write_reg(state, STV090x_P2_TSCFGM, reg) < 0)
43258c2ecf20Sopenharmony_ci					goto err;
43268c2ecf20Sopenharmony_ci				if (stv090x_write_reg(state, STV090x_P1_TSSPEED, 0x14) < 0)
43278c2ecf20Sopenharmony_ci					goto err;
43288c2ecf20Sopenharmony_ci				if (stv090x_write_reg(state, STV090x_P2_TSSPEED, 0x28) < 0)
43298c2ecf20Sopenharmony_ci					goto err;
43308c2ecf20Sopenharmony_ci				break;
43318c2ecf20Sopenharmony_ci			}
43328c2ecf20Sopenharmony_ci			break;
43338c2ecf20Sopenharmony_ci
43348c2ecf20Sopenharmony_ci		case STV090x_TSMODE_SERIAL_PUNCTURED:
43358c2ecf20Sopenharmony_ci		case STV090x_TSMODE_SERIAL_CONTINUOUS:
43368c2ecf20Sopenharmony_ci		default:
43378c2ecf20Sopenharmony_ci			switch (state->config->ts2_mode) {
43388c2ecf20Sopenharmony_ci			case STV090x_TSMODE_SERIAL_PUNCTURED:
43398c2ecf20Sopenharmony_ci			case STV090x_TSMODE_SERIAL_CONTINUOUS:
43408c2ecf20Sopenharmony_ci			default:
43418c2ecf20Sopenharmony_ci				if (stv090x_write_reg(state, STV090x_TSGENERAL, 0x0c) < 0)
43428c2ecf20Sopenharmony_ci					goto err;
43438c2ecf20Sopenharmony_ci				break;
43448c2ecf20Sopenharmony_ci
43458c2ecf20Sopenharmony_ci			case STV090x_TSMODE_PARALLEL_PUNCTURED:
43468c2ecf20Sopenharmony_ci			case STV090x_TSMODE_DVBCI:
43478c2ecf20Sopenharmony_ci				if (stv090x_write_reg(state, STV090x_TSGENERAL, 0x0a) < 0)
43488c2ecf20Sopenharmony_ci					goto err;
43498c2ecf20Sopenharmony_ci				break;
43508c2ecf20Sopenharmony_ci			}
43518c2ecf20Sopenharmony_ci			break;
43528c2ecf20Sopenharmony_ci		}
43538c2ecf20Sopenharmony_ci	} else {
43548c2ecf20Sopenharmony_ci		switch (state->config->ts1_mode) {
43558c2ecf20Sopenharmony_ci		case STV090x_TSMODE_PARALLEL_PUNCTURED:
43568c2ecf20Sopenharmony_ci		case STV090x_TSMODE_DVBCI:
43578c2ecf20Sopenharmony_ci			switch (state->config->ts2_mode) {
43588c2ecf20Sopenharmony_ci			case STV090x_TSMODE_SERIAL_PUNCTURED:
43598c2ecf20Sopenharmony_ci			case STV090x_TSMODE_SERIAL_CONTINUOUS:
43608c2ecf20Sopenharmony_ci			default:
43618c2ecf20Sopenharmony_ci				stv090x_write_reg(state, STV090x_TSGENERAL1X, 0x10);
43628c2ecf20Sopenharmony_ci				break;
43638c2ecf20Sopenharmony_ci
43648c2ecf20Sopenharmony_ci			case STV090x_TSMODE_PARALLEL_PUNCTURED:
43658c2ecf20Sopenharmony_ci			case STV090x_TSMODE_DVBCI:
43668c2ecf20Sopenharmony_ci				stv090x_write_reg(state, STV090x_TSGENERAL1X, 0x16);
43678c2ecf20Sopenharmony_ci				reg = stv090x_read_reg(state, STV090x_P1_TSCFGM);
43688c2ecf20Sopenharmony_ci				STV090x_SETFIELD_Px(reg, TSFIFO_MANSPEED_FIELD, 3);
43698c2ecf20Sopenharmony_ci				if (stv090x_write_reg(state, STV090x_P1_TSCFGM, reg) < 0)
43708c2ecf20Sopenharmony_ci					goto err;
43718c2ecf20Sopenharmony_ci				reg = stv090x_read_reg(state, STV090x_P1_TSCFGM);
43728c2ecf20Sopenharmony_ci				STV090x_SETFIELD_Px(reg, TSFIFO_MANSPEED_FIELD, 0);
43738c2ecf20Sopenharmony_ci				if (stv090x_write_reg(state, STV090x_P1_TSCFGM, reg) < 0)
43748c2ecf20Sopenharmony_ci					goto err;
43758c2ecf20Sopenharmony_ci				if (stv090x_write_reg(state, STV090x_P1_TSSPEED, 0x14) < 0)
43768c2ecf20Sopenharmony_ci					goto err;
43778c2ecf20Sopenharmony_ci				if (stv090x_write_reg(state, STV090x_P2_TSSPEED, 0x28) < 0)
43788c2ecf20Sopenharmony_ci					goto err;
43798c2ecf20Sopenharmony_ci				break;
43808c2ecf20Sopenharmony_ci			}
43818c2ecf20Sopenharmony_ci			break;
43828c2ecf20Sopenharmony_ci
43838c2ecf20Sopenharmony_ci		case STV090x_TSMODE_SERIAL_PUNCTURED:
43848c2ecf20Sopenharmony_ci		case STV090x_TSMODE_SERIAL_CONTINUOUS:
43858c2ecf20Sopenharmony_ci		default:
43868c2ecf20Sopenharmony_ci			switch (state->config->ts2_mode) {
43878c2ecf20Sopenharmony_ci			case STV090x_TSMODE_SERIAL_PUNCTURED:
43888c2ecf20Sopenharmony_ci			case STV090x_TSMODE_SERIAL_CONTINUOUS:
43898c2ecf20Sopenharmony_ci			default:
43908c2ecf20Sopenharmony_ci				stv090x_write_reg(state, STV090x_TSGENERAL1X, 0x14);
43918c2ecf20Sopenharmony_ci				break;
43928c2ecf20Sopenharmony_ci
43938c2ecf20Sopenharmony_ci			case STV090x_TSMODE_PARALLEL_PUNCTURED:
43948c2ecf20Sopenharmony_ci			case STV090x_TSMODE_DVBCI:
43958c2ecf20Sopenharmony_ci				stv090x_write_reg(state, STV090x_TSGENERAL1X, 0x12);
43968c2ecf20Sopenharmony_ci				break;
43978c2ecf20Sopenharmony_ci			}
43988c2ecf20Sopenharmony_ci			break;
43998c2ecf20Sopenharmony_ci		}
44008c2ecf20Sopenharmony_ci	}
44018c2ecf20Sopenharmony_ci
44028c2ecf20Sopenharmony_ci	switch (state->config->ts1_mode) {
44038c2ecf20Sopenharmony_ci	case STV090x_TSMODE_PARALLEL_PUNCTURED:
44048c2ecf20Sopenharmony_ci		reg = stv090x_read_reg(state, STV090x_P1_TSCFGH);
44058c2ecf20Sopenharmony_ci		STV090x_SETFIELD_Px(reg, TSFIFO_TEIUPDATE_FIELD, state->config->ts1_tei);
44068c2ecf20Sopenharmony_ci		STV090x_SETFIELD_Px(reg, TSFIFO_SERIAL_FIELD, 0x00);
44078c2ecf20Sopenharmony_ci		STV090x_SETFIELD_Px(reg, TSFIFO_DVBCI_FIELD, 0x00);
44088c2ecf20Sopenharmony_ci		if (stv090x_write_reg(state, STV090x_P1_TSCFGH, reg) < 0)
44098c2ecf20Sopenharmony_ci			goto err;
44108c2ecf20Sopenharmony_ci		break;
44118c2ecf20Sopenharmony_ci
44128c2ecf20Sopenharmony_ci	case STV090x_TSMODE_DVBCI:
44138c2ecf20Sopenharmony_ci		reg = stv090x_read_reg(state, STV090x_P1_TSCFGH);
44148c2ecf20Sopenharmony_ci		STV090x_SETFIELD_Px(reg, TSFIFO_TEIUPDATE_FIELD, state->config->ts1_tei);
44158c2ecf20Sopenharmony_ci		STV090x_SETFIELD_Px(reg, TSFIFO_SERIAL_FIELD, 0x00);
44168c2ecf20Sopenharmony_ci		STV090x_SETFIELD_Px(reg, TSFIFO_DVBCI_FIELD, 0x01);
44178c2ecf20Sopenharmony_ci		if (stv090x_write_reg(state, STV090x_P1_TSCFGH, reg) < 0)
44188c2ecf20Sopenharmony_ci			goto err;
44198c2ecf20Sopenharmony_ci		break;
44208c2ecf20Sopenharmony_ci
44218c2ecf20Sopenharmony_ci	case STV090x_TSMODE_SERIAL_PUNCTURED:
44228c2ecf20Sopenharmony_ci		reg = stv090x_read_reg(state, STV090x_P1_TSCFGH);
44238c2ecf20Sopenharmony_ci		STV090x_SETFIELD_Px(reg, TSFIFO_TEIUPDATE_FIELD, state->config->ts1_tei);
44248c2ecf20Sopenharmony_ci		STV090x_SETFIELD_Px(reg, TSFIFO_SERIAL_FIELD, 0x01);
44258c2ecf20Sopenharmony_ci		STV090x_SETFIELD_Px(reg, TSFIFO_DVBCI_FIELD, 0x00);
44268c2ecf20Sopenharmony_ci		if (stv090x_write_reg(state, STV090x_P1_TSCFGH, reg) < 0)
44278c2ecf20Sopenharmony_ci			goto err;
44288c2ecf20Sopenharmony_ci		break;
44298c2ecf20Sopenharmony_ci
44308c2ecf20Sopenharmony_ci	case STV090x_TSMODE_SERIAL_CONTINUOUS:
44318c2ecf20Sopenharmony_ci		reg = stv090x_read_reg(state, STV090x_P1_TSCFGH);
44328c2ecf20Sopenharmony_ci		STV090x_SETFIELD_Px(reg, TSFIFO_TEIUPDATE_FIELD, state->config->ts1_tei);
44338c2ecf20Sopenharmony_ci		STV090x_SETFIELD_Px(reg, TSFIFO_SERIAL_FIELD, 0x01);
44348c2ecf20Sopenharmony_ci		STV090x_SETFIELD_Px(reg, TSFIFO_DVBCI_FIELD, 0x01);
44358c2ecf20Sopenharmony_ci		if (stv090x_write_reg(state, STV090x_P1_TSCFGH, reg) < 0)
44368c2ecf20Sopenharmony_ci			goto err;
44378c2ecf20Sopenharmony_ci		break;
44388c2ecf20Sopenharmony_ci
44398c2ecf20Sopenharmony_ci	default:
44408c2ecf20Sopenharmony_ci		break;
44418c2ecf20Sopenharmony_ci	}
44428c2ecf20Sopenharmony_ci
44438c2ecf20Sopenharmony_ci	switch (state->config->ts2_mode) {
44448c2ecf20Sopenharmony_ci	case STV090x_TSMODE_PARALLEL_PUNCTURED:
44458c2ecf20Sopenharmony_ci		reg = stv090x_read_reg(state, STV090x_P2_TSCFGH);
44468c2ecf20Sopenharmony_ci		STV090x_SETFIELD_Px(reg, TSFIFO_TEIUPDATE_FIELD, state->config->ts2_tei);
44478c2ecf20Sopenharmony_ci		STV090x_SETFIELD_Px(reg, TSFIFO_SERIAL_FIELD, 0x00);
44488c2ecf20Sopenharmony_ci		STV090x_SETFIELD_Px(reg, TSFIFO_DVBCI_FIELD, 0x00);
44498c2ecf20Sopenharmony_ci		if (stv090x_write_reg(state, STV090x_P2_TSCFGH, reg) < 0)
44508c2ecf20Sopenharmony_ci			goto err;
44518c2ecf20Sopenharmony_ci		break;
44528c2ecf20Sopenharmony_ci
44538c2ecf20Sopenharmony_ci	case STV090x_TSMODE_DVBCI:
44548c2ecf20Sopenharmony_ci		reg = stv090x_read_reg(state, STV090x_P2_TSCFGH);
44558c2ecf20Sopenharmony_ci		STV090x_SETFIELD_Px(reg, TSFIFO_TEIUPDATE_FIELD, state->config->ts2_tei);
44568c2ecf20Sopenharmony_ci		STV090x_SETFIELD_Px(reg, TSFIFO_SERIAL_FIELD, 0x00);
44578c2ecf20Sopenharmony_ci		STV090x_SETFIELD_Px(reg, TSFIFO_DVBCI_FIELD, 0x01);
44588c2ecf20Sopenharmony_ci		if (stv090x_write_reg(state, STV090x_P2_TSCFGH, reg) < 0)
44598c2ecf20Sopenharmony_ci			goto err;
44608c2ecf20Sopenharmony_ci		break;
44618c2ecf20Sopenharmony_ci
44628c2ecf20Sopenharmony_ci	case STV090x_TSMODE_SERIAL_PUNCTURED:
44638c2ecf20Sopenharmony_ci		reg = stv090x_read_reg(state, STV090x_P2_TSCFGH);
44648c2ecf20Sopenharmony_ci		STV090x_SETFIELD_Px(reg, TSFIFO_TEIUPDATE_FIELD, state->config->ts2_tei);
44658c2ecf20Sopenharmony_ci		STV090x_SETFIELD_Px(reg, TSFIFO_SERIAL_FIELD, 0x01);
44668c2ecf20Sopenharmony_ci		STV090x_SETFIELD_Px(reg, TSFIFO_DVBCI_FIELD, 0x00);
44678c2ecf20Sopenharmony_ci		if (stv090x_write_reg(state, STV090x_P2_TSCFGH, reg) < 0)
44688c2ecf20Sopenharmony_ci			goto err;
44698c2ecf20Sopenharmony_ci		break;
44708c2ecf20Sopenharmony_ci
44718c2ecf20Sopenharmony_ci	case STV090x_TSMODE_SERIAL_CONTINUOUS:
44728c2ecf20Sopenharmony_ci		reg = stv090x_read_reg(state, STV090x_P2_TSCFGH);
44738c2ecf20Sopenharmony_ci		STV090x_SETFIELD_Px(reg, TSFIFO_TEIUPDATE_FIELD, state->config->ts2_tei);
44748c2ecf20Sopenharmony_ci		STV090x_SETFIELD_Px(reg, TSFIFO_SERIAL_FIELD, 0x01);
44758c2ecf20Sopenharmony_ci		STV090x_SETFIELD_Px(reg, TSFIFO_DVBCI_FIELD, 0x01);
44768c2ecf20Sopenharmony_ci		if (stv090x_write_reg(state, STV090x_P2_TSCFGH, reg) < 0)
44778c2ecf20Sopenharmony_ci			goto err;
44788c2ecf20Sopenharmony_ci		break;
44798c2ecf20Sopenharmony_ci
44808c2ecf20Sopenharmony_ci	default:
44818c2ecf20Sopenharmony_ci		break;
44828c2ecf20Sopenharmony_ci	}
44838c2ecf20Sopenharmony_ci
44848c2ecf20Sopenharmony_ci	if (state->config->ts1_clk > 0) {
44858c2ecf20Sopenharmony_ci		u32 speed;
44868c2ecf20Sopenharmony_ci
44878c2ecf20Sopenharmony_ci		switch (state->config->ts1_mode) {
44888c2ecf20Sopenharmony_ci		case STV090x_TSMODE_PARALLEL_PUNCTURED:
44898c2ecf20Sopenharmony_ci		case STV090x_TSMODE_DVBCI:
44908c2ecf20Sopenharmony_ci		default:
44918c2ecf20Sopenharmony_ci			speed = state->internal->mclk /
44928c2ecf20Sopenharmony_ci				(state->config->ts1_clk / 4);
44938c2ecf20Sopenharmony_ci			if (speed < 0x08)
44948c2ecf20Sopenharmony_ci				speed = 0x08;
44958c2ecf20Sopenharmony_ci			if (speed > 0xFF)
44968c2ecf20Sopenharmony_ci				speed = 0xFF;
44978c2ecf20Sopenharmony_ci			break;
44988c2ecf20Sopenharmony_ci		case STV090x_TSMODE_SERIAL_PUNCTURED:
44998c2ecf20Sopenharmony_ci		case STV090x_TSMODE_SERIAL_CONTINUOUS:
45008c2ecf20Sopenharmony_ci			speed = state->internal->mclk /
45018c2ecf20Sopenharmony_ci				(state->config->ts1_clk / 32);
45028c2ecf20Sopenharmony_ci			if (speed < 0x20)
45038c2ecf20Sopenharmony_ci				speed = 0x20;
45048c2ecf20Sopenharmony_ci			if (speed > 0xFF)
45058c2ecf20Sopenharmony_ci				speed = 0xFF;
45068c2ecf20Sopenharmony_ci			break;
45078c2ecf20Sopenharmony_ci		}
45088c2ecf20Sopenharmony_ci		reg = stv090x_read_reg(state, STV090x_P1_TSCFGM);
45098c2ecf20Sopenharmony_ci		STV090x_SETFIELD_Px(reg, TSFIFO_MANSPEED_FIELD, 3);
45108c2ecf20Sopenharmony_ci		if (stv090x_write_reg(state, STV090x_P1_TSCFGM, reg) < 0)
45118c2ecf20Sopenharmony_ci			goto err;
45128c2ecf20Sopenharmony_ci		if (stv090x_write_reg(state, STV090x_P1_TSSPEED, speed) < 0)
45138c2ecf20Sopenharmony_ci			goto err;
45148c2ecf20Sopenharmony_ci	}
45158c2ecf20Sopenharmony_ci
45168c2ecf20Sopenharmony_ci	if (state->config->ts2_clk > 0) {
45178c2ecf20Sopenharmony_ci		u32 speed;
45188c2ecf20Sopenharmony_ci
45198c2ecf20Sopenharmony_ci		switch (state->config->ts2_mode) {
45208c2ecf20Sopenharmony_ci		case STV090x_TSMODE_PARALLEL_PUNCTURED:
45218c2ecf20Sopenharmony_ci		case STV090x_TSMODE_DVBCI:
45228c2ecf20Sopenharmony_ci		default:
45238c2ecf20Sopenharmony_ci			speed = state->internal->mclk /
45248c2ecf20Sopenharmony_ci				(state->config->ts2_clk / 4);
45258c2ecf20Sopenharmony_ci			if (speed < 0x08)
45268c2ecf20Sopenharmony_ci				speed = 0x08;
45278c2ecf20Sopenharmony_ci			if (speed > 0xFF)
45288c2ecf20Sopenharmony_ci				speed = 0xFF;
45298c2ecf20Sopenharmony_ci			break;
45308c2ecf20Sopenharmony_ci		case STV090x_TSMODE_SERIAL_PUNCTURED:
45318c2ecf20Sopenharmony_ci		case STV090x_TSMODE_SERIAL_CONTINUOUS:
45328c2ecf20Sopenharmony_ci			speed = state->internal->mclk /
45338c2ecf20Sopenharmony_ci				(state->config->ts2_clk / 32);
45348c2ecf20Sopenharmony_ci			if (speed < 0x20)
45358c2ecf20Sopenharmony_ci				speed = 0x20;
45368c2ecf20Sopenharmony_ci			if (speed > 0xFF)
45378c2ecf20Sopenharmony_ci				speed = 0xFF;
45388c2ecf20Sopenharmony_ci			break;
45398c2ecf20Sopenharmony_ci		}
45408c2ecf20Sopenharmony_ci		reg = stv090x_read_reg(state, STV090x_P2_TSCFGM);
45418c2ecf20Sopenharmony_ci		STV090x_SETFIELD_Px(reg, TSFIFO_MANSPEED_FIELD, 3);
45428c2ecf20Sopenharmony_ci		if (stv090x_write_reg(state, STV090x_P2_TSCFGM, reg) < 0)
45438c2ecf20Sopenharmony_ci			goto err;
45448c2ecf20Sopenharmony_ci		if (stv090x_write_reg(state, STV090x_P2_TSSPEED, speed) < 0)
45458c2ecf20Sopenharmony_ci			goto err;
45468c2ecf20Sopenharmony_ci	}
45478c2ecf20Sopenharmony_ci
45488c2ecf20Sopenharmony_ci	reg = stv090x_read_reg(state, STV090x_P2_TSCFGH);
45498c2ecf20Sopenharmony_ci	STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 0x01);
45508c2ecf20Sopenharmony_ci	if (stv090x_write_reg(state, STV090x_P2_TSCFGH, reg) < 0)
45518c2ecf20Sopenharmony_ci		goto err;
45528c2ecf20Sopenharmony_ci	STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 0x00);
45538c2ecf20Sopenharmony_ci	if (stv090x_write_reg(state, STV090x_P2_TSCFGH, reg) < 0)
45548c2ecf20Sopenharmony_ci		goto err;
45558c2ecf20Sopenharmony_ci
45568c2ecf20Sopenharmony_ci	reg = stv090x_read_reg(state, STV090x_P1_TSCFGH);
45578c2ecf20Sopenharmony_ci	STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 0x01);
45588c2ecf20Sopenharmony_ci	if (stv090x_write_reg(state, STV090x_P1_TSCFGH, reg) < 0)
45598c2ecf20Sopenharmony_ci		goto err;
45608c2ecf20Sopenharmony_ci	STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 0x00);
45618c2ecf20Sopenharmony_ci	if (stv090x_write_reg(state, STV090x_P1_TSCFGH, reg) < 0)
45628c2ecf20Sopenharmony_ci		goto err;
45638c2ecf20Sopenharmony_ci
45648c2ecf20Sopenharmony_ci	return 0;
45658c2ecf20Sopenharmony_cierr:
45668c2ecf20Sopenharmony_ci	dprintk(FE_ERROR, 1, "I/O error");
45678c2ecf20Sopenharmony_ci	return -1;
45688c2ecf20Sopenharmony_ci}
45698c2ecf20Sopenharmony_ci
45708c2ecf20Sopenharmony_cistatic int stv0903_set_tspath(struct stv090x_state *state)
45718c2ecf20Sopenharmony_ci{
45728c2ecf20Sopenharmony_ci	u32 reg;
45738c2ecf20Sopenharmony_ci
45748c2ecf20Sopenharmony_ci	if (state->internal->dev_ver >= 0x20) {
45758c2ecf20Sopenharmony_ci		switch (state->config->ts1_mode) {
45768c2ecf20Sopenharmony_ci		case STV090x_TSMODE_PARALLEL_PUNCTURED:
45778c2ecf20Sopenharmony_ci		case STV090x_TSMODE_DVBCI:
45788c2ecf20Sopenharmony_ci			stv090x_write_reg(state, STV090x_TSGENERAL, 0x00);
45798c2ecf20Sopenharmony_ci			break;
45808c2ecf20Sopenharmony_ci
45818c2ecf20Sopenharmony_ci		case STV090x_TSMODE_SERIAL_PUNCTURED:
45828c2ecf20Sopenharmony_ci		case STV090x_TSMODE_SERIAL_CONTINUOUS:
45838c2ecf20Sopenharmony_ci		default:
45848c2ecf20Sopenharmony_ci			stv090x_write_reg(state, STV090x_TSGENERAL, 0x0c);
45858c2ecf20Sopenharmony_ci			break;
45868c2ecf20Sopenharmony_ci		}
45878c2ecf20Sopenharmony_ci	} else {
45888c2ecf20Sopenharmony_ci		switch (state->config->ts1_mode) {
45898c2ecf20Sopenharmony_ci		case STV090x_TSMODE_PARALLEL_PUNCTURED:
45908c2ecf20Sopenharmony_ci		case STV090x_TSMODE_DVBCI:
45918c2ecf20Sopenharmony_ci			stv090x_write_reg(state, STV090x_TSGENERAL1X, 0x10);
45928c2ecf20Sopenharmony_ci			break;
45938c2ecf20Sopenharmony_ci
45948c2ecf20Sopenharmony_ci		case STV090x_TSMODE_SERIAL_PUNCTURED:
45958c2ecf20Sopenharmony_ci		case STV090x_TSMODE_SERIAL_CONTINUOUS:
45968c2ecf20Sopenharmony_ci		default:
45978c2ecf20Sopenharmony_ci			stv090x_write_reg(state, STV090x_TSGENERAL1X, 0x14);
45988c2ecf20Sopenharmony_ci			break;
45998c2ecf20Sopenharmony_ci		}
46008c2ecf20Sopenharmony_ci	}
46018c2ecf20Sopenharmony_ci
46028c2ecf20Sopenharmony_ci	switch (state->config->ts1_mode) {
46038c2ecf20Sopenharmony_ci	case STV090x_TSMODE_PARALLEL_PUNCTURED:
46048c2ecf20Sopenharmony_ci		reg = stv090x_read_reg(state, STV090x_P1_TSCFGH);
46058c2ecf20Sopenharmony_ci		STV090x_SETFIELD_Px(reg, TSFIFO_SERIAL_FIELD, 0x00);
46068c2ecf20Sopenharmony_ci		STV090x_SETFIELD_Px(reg, TSFIFO_DVBCI_FIELD, 0x00);
46078c2ecf20Sopenharmony_ci		if (stv090x_write_reg(state, STV090x_P1_TSCFGH, reg) < 0)
46088c2ecf20Sopenharmony_ci			goto err;
46098c2ecf20Sopenharmony_ci		break;
46108c2ecf20Sopenharmony_ci
46118c2ecf20Sopenharmony_ci	case STV090x_TSMODE_DVBCI:
46128c2ecf20Sopenharmony_ci		reg = stv090x_read_reg(state, STV090x_P1_TSCFGH);
46138c2ecf20Sopenharmony_ci		STV090x_SETFIELD_Px(reg, TSFIFO_SERIAL_FIELD, 0x00);
46148c2ecf20Sopenharmony_ci		STV090x_SETFIELD_Px(reg, TSFIFO_DVBCI_FIELD, 0x01);
46158c2ecf20Sopenharmony_ci		if (stv090x_write_reg(state, STV090x_P1_TSCFGH, reg) < 0)
46168c2ecf20Sopenharmony_ci			goto err;
46178c2ecf20Sopenharmony_ci		break;
46188c2ecf20Sopenharmony_ci
46198c2ecf20Sopenharmony_ci	case STV090x_TSMODE_SERIAL_PUNCTURED:
46208c2ecf20Sopenharmony_ci		reg = stv090x_read_reg(state, STV090x_P1_TSCFGH);
46218c2ecf20Sopenharmony_ci		STV090x_SETFIELD_Px(reg, TSFIFO_SERIAL_FIELD, 0x01);
46228c2ecf20Sopenharmony_ci		STV090x_SETFIELD_Px(reg, TSFIFO_DVBCI_FIELD, 0x00);
46238c2ecf20Sopenharmony_ci		if (stv090x_write_reg(state, STV090x_P1_TSCFGH, reg) < 0)
46248c2ecf20Sopenharmony_ci			goto err;
46258c2ecf20Sopenharmony_ci		break;
46268c2ecf20Sopenharmony_ci
46278c2ecf20Sopenharmony_ci	case STV090x_TSMODE_SERIAL_CONTINUOUS:
46288c2ecf20Sopenharmony_ci		reg = stv090x_read_reg(state, STV090x_P1_TSCFGH);
46298c2ecf20Sopenharmony_ci		STV090x_SETFIELD_Px(reg, TSFIFO_SERIAL_FIELD, 0x01);
46308c2ecf20Sopenharmony_ci		STV090x_SETFIELD_Px(reg, TSFIFO_DVBCI_FIELD, 0x01);
46318c2ecf20Sopenharmony_ci		if (stv090x_write_reg(state, STV090x_P1_TSCFGH, reg) < 0)
46328c2ecf20Sopenharmony_ci			goto err;
46338c2ecf20Sopenharmony_ci		break;
46348c2ecf20Sopenharmony_ci
46358c2ecf20Sopenharmony_ci	default:
46368c2ecf20Sopenharmony_ci		break;
46378c2ecf20Sopenharmony_ci	}
46388c2ecf20Sopenharmony_ci
46398c2ecf20Sopenharmony_ci	if (state->config->ts1_clk > 0) {
46408c2ecf20Sopenharmony_ci		u32 speed;
46418c2ecf20Sopenharmony_ci
46428c2ecf20Sopenharmony_ci		switch (state->config->ts1_mode) {
46438c2ecf20Sopenharmony_ci		case STV090x_TSMODE_PARALLEL_PUNCTURED:
46448c2ecf20Sopenharmony_ci		case STV090x_TSMODE_DVBCI:
46458c2ecf20Sopenharmony_ci		default:
46468c2ecf20Sopenharmony_ci			speed = state->internal->mclk /
46478c2ecf20Sopenharmony_ci				(state->config->ts1_clk / 4);
46488c2ecf20Sopenharmony_ci			if (speed < 0x08)
46498c2ecf20Sopenharmony_ci				speed = 0x08;
46508c2ecf20Sopenharmony_ci			if (speed > 0xFF)
46518c2ecf20Sopenharmony_ci				speed = 0xFF;
46528c2ecf20Sopenharmony_ci			break;
46538c2ecf20Sopenharmony_ci		case STV090x_TSMODE_SERIAL_PUNCTURED:
46548c2ecf20Sopenharmony_ci		case STV090x_TSMODE_SERIAL_CONTINUOUS:
46558c2ecf20Sopenharmony_ci			speed = state->internal->mclk /
46568c2ecf20Sopenharmony_ci				(state->config->ts1_clk / 32);
46578c2ecf20Sopenharmony_ci			if (speed < 0x20)
46588c2ecf20Sopenharmony_ci				speed = 0x20;
46598c2ecf20Sopenharmony_ci			if (speed > 0xFF)
46608c2ecf20Sopenharmony_ci				speed = 0xFF;
46618c2ecf20Sopenharmony_ci			break;
46628c2ecf20Sopenharmony_ci		}
46638c2ecf20Sopenharmony_ci		reg = stv090x_read_reg(state, STV090x_P1_TSCFGM);
46648c2ecf20Sopenharmony_ci		STV090x_SETFIELD_Px(reg, TSFIFO_MANSPEED_FIELD, 3);
46658c2ecf20Sopenharmony_ci		if (stv090x_write_reg(state, STV090x_P1_TSCFGM, reg) < 0)
46668c2ecf20Sopenharmony_ci			goto err;
46678c2ecf20Sopenharmony_ci		if (stv090x_write_reg(state, STV090x_P1_TSSPEED, speed) < 0)
46688c2ecf20Sopenharmony_ci			goto err;
46698c2ecf20Sopenharmony_ci	}
46708c2ecf20Sopenharmony_ci
46718c2ecf20Sopenharmony_ci	reg = stv090x_read_reg(state, STV090x_P1_TSCFGH);
46728c2ecf20Sopenharmony_ci	STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 0x01);
46738c2ecf20Sopenharmony_ci	if (stv090x_write_reg(state, STV090x_P1_TSCFGH, reg) < 0)
46748c2ecf20Sopenharmony_ci		goto err;
46758c2ecf20Sopenharmony_ci	STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 0x00);
46768c2ecf20Sopenharmony_ci	if (stv090x_write_reg(state, STV090x_P1_TSCFGH, reg) < 0)
46778c2ecf20Sopenharmony_ci		goto err;
46788c2ecf20Sopenharmony_ci
46798c2ecf20Sopenharmony_ci	return 0;
46808c2ecf20Sopenharmony_cierr:
46818c2ecf20Sopenharmony_ci	dprintk(FE_ERROR, 1, "I/O error");
46828c2ecf20Sopenharmony_ci	return -1;
46838c2ecf20Sopenharmony_ci}
46848c2ecf20Sopenharmony_ci
46858c2ecf20Sopenharmony_cistatic int stv090x_init(struct dvb_frontend *fe)
46868c2ecf20Sopenharmony_ci{
46878c2ecf20Sopenharmony_ci	struct stv090x_state *state = fe->demodulator_priv;
46888c2ecf20Sopenharmony_ci	const struct stv090x_config *config = state->config;
46898c2ecf20Sopenharmony_ci	u32 reg;
46908c2ecf20Sopenharmony_ci
46918c2ecf20Sopenharmony_ci	if (state->internal->mclk == 0) {
46928c2ecf20Sopenharmony_ci		/* call tuner init to configure the tuner's clock output
46938c2ecf20Sopenharmony_ci		   divider directly before setting up the master clock of
46948c2ecf20Sopenharmony_ci		   the stv090x. */
46958c2ecf20Sopenharmony_ci		if (stv090x_i2c_gate_ctrl(state, 1) < 0)
46968c2ecf20Sopenharmony_ci			goto err;
46978c2ecf20Sopenharmony_ci
46988c2ecf20Sopenharmony_ci		if (config->tuner_init) {
46998c2ecf20Sopenharmony_ci			if (config->tuner_init(fe) < 0)
47008c2ecf20Sopenharmony_ci				goto err_gateoff;
47018c2ecf20Sopenharmony_ci		}
47028c2ecf20Sopenharmony_ci
47038c2ecf20Sopenharmony_ci		if (stv090x_i2c_gate_ctrl(state, 0) < 0)
47048c2ecf20Sopenharmony_ci			goto err;
47058c2ecf20Sopenharmony_ci
47068c2ecf20Sopenharmony_ci		stv090x_set_mclk(state, 135000000, config->xtal); /* 135 Mhz */
47078c2ecf20Sopenharmony_ci		msleep(5);
47088c2ecf20Sopenharmony_ci		if (stv090x_write_reg(state, STV090x_SYNTCTRL,
47098c2ecf20Sopenharmony_ci				      0x20 | config->clk_mode) < 0)
47108c2ecf20Sopenharmony_ci			goto err;
47118c2ecf20Sopenharmony_ci		stv090x_get_mclk(state);
47128c2ecf20Sopenharmony_ci	}
47138c2ecf20Sopenharmony_ci
47148c2ecf20Sopenharmony_ci	if (stv090x_wakeup(fe) < 0) {
47158c2ecf20Sopenharmony_ci		dprintk(FE_ERROR, 1, "Error waking device");
47168c2ecf20Sopenharmony_ci		goto err;
47178c2ecf20Sopenharmony_ci	}
47188c2ecf20Sopenharmony_ci
47198c2ecf20Sopenharmony_ci	if (stv090x_ldpc_mode(state, state->demod_mode) < 0)
47208c2ecf20Sopenharmony_ci		goto err;
47218c2ecf20Sopenharmony_ci
47228c2ecf20Sopenharmony_ci	reg = STV090x_READ_DEMOD(state, TNRCFG2);
47238c2ecf20Sopenharmony_ci	STV090x_SETFIELD_Px(reg, TUN_IQSWAP_FIELD, state->inversion);
47248c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, TNRCFG2, reg) < 0)
47258c2ecf20Sopenharmony_ci		goto err;
47268c2ecf20Sopenharmony_ci	reg = STV090x_READ_DEMOD(state, DEMOD);
47278c2ecf20Sopenharmony_ci	STV090x_SETFIELD_Px(reg, ROLLOFF_CONTROL_FIELD, state->rolloff);
47288c2ecf20Sopenharmony_ci	if (STV090x_WRITE_DEMOD(state, DEMOD, reg) < 0)
47298c2ecf20Sopenharmony_ci		goto err;
47308c2ecf20Sopenharmony_ci
47318c2ecf20Sopenharmony_ci	if (stv090x_i2c_gate_ctrl(state, 1) < 0)
47328c2ecf20Sopenharmony_ci		goto err;
47338c2ecf20Sopenharmony_ci
47348c2ecf20Sopenharmony_ci	if (config->tuner_set_mode) {
47358c2ecf20Sopenharmony_ci		if (config->tuner_set_mode(fe, TUNER_WAKE) < 0)
47368c2ecf20Sopenharmony_ci			goto err_gateoff;
47378c2ecf20Sopenharmony_ci	}
47388c2ecf20Sopenharmony_ci
47398c2ecf20Sopenharmony_ci	if (config->tuner_init) {
47408c2ecf20Sopenharmony_ci		if (config->tuner_init(fe) < 0)
47418c2ecf20Sopenharmony_ci			goto err_gateoff;
47428c2ecf20Sopenharmony_ci	}
47438c2ecf20Sopenharmony_ci
47448c2ecf20Sopenharmony_ci	if (stv090x_i2c_gate_ctrl(state, 0) < 0)
47458c2ecf20Sopenharmony_ci		goto err;
47468c2ecf20Sopenharmony_ci
47478c2ecf20Sopenharmony_ci	if (state->device == STV0900) {
47488c2ecf20Sopenharmony_ci		if (stv0900_set_tspath(state) < 0)
47498c2ecf20Sopenharmony_ci			goto err;
47508c2ecf20Sopenharmony_ci	} else {
47518c2ecf20Sopenharmony_ci		if (stv0903_set_tspath(state) < 0)
47528c2ecf20Sopenharmony_ci			goto err;
47538c2ecf20Sopenharmony_ci	}
47548c2ecf20Sopenharmony_ci
47558c2ecf20Sopenharmony_ci	return 0;
47568c2ecf20Sopenharmony_ci
47578c2ecf20Sopenharmony_cierr_gateoff:
47588c2ecf20Sopenharmony_ci	stv090x_i2c_gate_ctrl(state, 0);
47598c2ecf20Sopenharmony_cierr:
47608c2ecf20Sopenharmony_ci	dprintk(FE_ERROR, 1, "I/O error");
47618c2ecf20Sopenharmony_ci	return -1;
47628c2ecf20Sopenharmony_ci}
47638c2ecf20Sopenharmony_ci
47648c2ecf20Sopenharmony_cistatic int stv090x_setup(struct dvb_frontend *fe)
47658c2ecf20Sopenharmony_ci{
47668c2ecf20Sopenharmony_ci	struct stv090x_state *state = fe->demodulator_priv;
47678c2ecf20Sopenharmony_ci	const struct stv090x_config *config = state->config;
47688c2ecf20Sopenharmony_ci	const struct stv090x_reg *stv090x_initval = NULL;
47698c2ecf20Sopenharmony_ci	const struct stv090x_reg *stv090x_cut20_val = NULL;
47708c2ecf20Sopenharmony_ci	unsigned long t1_size = 0, t2_size = 0;
47718c2ecf20Sopenharmony_ci	u32 reg = 0;
47728c2ecf20Sopenharmony_ci
47738c2ecf20Sopenharmony_ci	int i;
47748c2ecf20Sopenharmony_ci
47758c2ecf20Sopenharmony_ci	if (state->device == STV0900) {
47768c2ecf20Sopenharmony_ci		dprintk(FE_DEBUG, 1, "Initializing STV0900");
47778c2ecf20Sopenharmony_ci		stv090x_initval = stv0900_initval;
47788c2ecf20Sopenharmony_ci		t1_size = ARRAY_SIZE(stv0900_initval);
47798c2ecf20Sopenharmony_ci		stv090x_cut20_val = stv0900_cut20_val;
47808c2ecf20Sopenharmony_ci		t2_size = ARRAY_SIZE(stv0900_cut20_val);
47818c2ecf20Sopenharmony_ci	} else if (state->device == STV0903) {
47828c2ecf20Sopenharmony_ci		dprintk(FE_DEBUG, 1, "Initializing STV0903");
47838c2ecf20Sopenharmony_ci		stv090x_initval = stv0903_initval;
47848c2ecf20Sopenharmony_ci		t1_size = ARRAY_SIZE(stv0903_initval);
47858c2ecf20Sopenharmony_ci		stv090x_cut20_val = stv0903_cut20_val;
47868c2ecf20Sopenharmony_ci		t2_size = ARRAY_SIZE(stv0903_cut20_val);
47878c2ecf20Sopenharmony_ci	}
47888c2ecf20Sopenharmony_ci
47898c2ecf20Sopenharmony_ci	/* STV090x init */
47908c2ecf20Sopenharmony_ci
47918c2ecf20Sopenharmony_ci	/* Stop Demod */
47928c2ecf20Sopenharmony_ci	if (stv090x_write_reg(state, STV090x_P1_DMDISTATE, 0x5c) < 0)
47938c2ecf20Sopenharmony_ci		goto err;
47948c2ecf20Sopenharmony_ci	if (state->device == STV0900)
47958c2ecf20Sopenharmony_ci		if (stv090x_write_reg(state, STV090x_P2_DMDISTATE, 0x5c) < 0)
47968c2ecf20Sopenharmony_ci			goto err;
47978c2ecf20Sopenharmony_ci
47988c2ecf20Sopenharmony_ci	msleep(5);
47998c2ecf20Sopenharmony_ci
48008c2ecf20Sopenharmony_ci	/* Set No Tuner Mode */
48018c2ecf20Sopenharmony_ci	if (stv090x_write_reg(state, STV090x_P1_TNRCFG, 0x6c) < 0)
48028c2ecf20Sopenharmony_ci		goto err;
48038c2ecf20Sopenharmony_ci	if (state->device == STV0900)
48048c2ecf20Sopenharmony_ci		if (stv090x_write_reg(state, STV090x_P2_TNRCFG, 0x6c) < 0)
48058c2ecf20Sopenharmony_ci			goto err;
48068c2ecf20Sopenharmony_ci
48078c2ecf20Sopenharmony_ci	/* I2C repeater OFF */
48088c2ecf20Sopenharmony_ci	STV090x_SETFIELD_Px(reg, ENARPT_LEVEL_FIELD, config->repeater_level);
48098c2ecf20Sopenharmony_ci	if (stv090x_write_reg(state, STV090x_P1_I2CRPT, reg) < 0)
48108c2ecf20Sopenharmony_ci		goto err;
48118c2ecf20Sopenharmony_ci	if (state->device == STV0900)
48128c2ecf20Sopenharmony_ci		if (stv090x_write_reg(state, STV090x_P2_I2CRPT, reg) < 0)
48138c2ecf20Sopenharmony_ci			goto err;
48148c2ecf20Sopenharmony_ci
48158c2ecf20Sopenharmony_ci	if (stv090x_write_reg(state, STV090x_NCOARSE, 0x13) < 0) /* set PLL divider */
48168c2ecf20Sopenharmony_ci		goto err;
48178c2ecf20Sopenharmony_ci	msleep(5);
48188c2ecf20Sopenharmony_ci	if (stv090x_write_reg(state, STV090x_I2CCFG, 0x08) < 0) /* 1/41 oversampling */
48198c2ecf20Sopenharmony_ci		goto err;
48208c2ecf20Sopenharmony_ci	if (stv090x_write_reg(state, STV090x_SYNTCTRL, 0x20 | config->clk_mode) < 0) /* enable PLL */
48218c2ecf20Sopenharmony_ci		goto err;
48228c2ecf20Sopenharmony_ci	msleep(5);
48238c2ecf20Sopenharmony_ci
48248c2ecf20Sopenharmony_ci	/* write initval */
48258c2ecf20Sopenharmony_ci	dprintk(FE_DEBUG, 1, "Setting up initial values");
48268c2ecf20Sopenharmony_ci	for (i = 0; i < t1_size; i++) {
48278c2ecf20Sopenharmony_ci		if (stv090x_write_reg(state, stv090x_initval[i].addr, stv090x_initval[i].data) < 0)
48288c2ecf20Sopenharmony_ci			goto err;
48298c2ecf20Sopenharmony_ci	}
48308c2ecf20Sopenharmony_ci
48318c2ecf20Sopenharmony_ci	state->internal->dev_ver = stv090x_read_reg(state, STV090x_MID);
48328c2ecf20Sopenharmony_ci	if (state->internal->dev_ver >= 0x20) {
48338c2ecf20Sopenharmony_ci		if (stv090x_write_reg(state, STV090x_TSGENERAL, 0x0c) < 0)
48348c2ecf20Sopenharmony_ci			goto err;
48358c2ecf20Sopenharmony_ci
48368c2ecf20Sopenharmony_ci		/* write cut20_val*/
48378c2ecf20Sopenharmony_ci		dprintk(FE_DEBUG, 1, "Setting up Cut 2.0 initial values");
48388c2ecf20Sopenharmony_ci		for (i = 0; i < t2_size; i++) {
48398c2ecf20Sopenharmony_ci			if (stv090x_write_reg(state, stv090x_cut20_val[i].addr, stv090x_cut20_val[i].data) < 0)
48408c2ecf20Sopenharmony_ci				goto err;
48418c2ecf20Sopenharmony_ci		}
48428c2ecf20Sopenharmony_ci
48438c2ecf20Sopenharmony_ci	} else if (state->internal->dev_ver < 0x20) {
48448c2ecf20Sopenharmony_ci		dprintk(FE_ERROR, 1, "ERROR: Unsupported Cut: 0x%02x!",
48458c2ecf20Sopenharmony_ci			state->internal->dev_ver);
48468c2ecf20Sopenharmony_ci
48478c2ecf20Sopenharmony_ci		goto err;
48488c2ecf20Sopenharmony_ci	} else if (state->internal->dev_ver > 0x30) {
48498c2ecf20Sopenharmony_ci		/* we shouldn't bail out from here */
48508c2ecf20Sopenharmony_ci		dprintk(FE_ERROR, 1, "INFO: Cut: 0x%02x probably incomplete support!",
48518c2ecf20Sopenharmony_ci			state->internal->dev_ver);
48528c2ecf20Sopenharmony_ci	}
48538c2ecf20Sopenharmony_ci
48548c2ecf20Sopenharmony_ci	/* ADC1 range */
48558c2ecf20Sopenharmony_ci	reg = stv090x_read_reg(state, STV090x_TSTTNR1);
48568c2ecf20Sopenharmony_ci	STV090x_SETFIELD(reg, ADC1_INMODE_FIELD,
48578c2ecf20Sopenharmony_ci		(config->adc1_range == STV090x_ADC_1Vpp) ? 0 : 1);
48588c2ecf20Sopenharmony_ci	if (stv090x_write_reg(state, STV090x_TSTTNR1, reg) < 0)
48598c2ecf20Sopenharmony_ci		goto err;
48608c2ecf20Sopenharmony_ci
48618c2ecf20Sopenharmony_ci	/* ADC2 range */
48628c2ecf20Sopenharmony_ci	reg = stv090x_read_reg(state, STV090x_TSTTNR3);
48638c2ecf20Sopenharmony_ci	STV090x_SETFIELD(reg, ADC2_INMODE_FIELD,
48648c2ecf20Sopenharmony_ci		(config->adc2_range == STV090x_ADC_1Vpp) ? 0 : 1);
48658c2ecf20Sopenharmony_ci	if (stv090x_write_reg(state, STV090x_TSTTNR3, reg) < 0)
48668c2ecf20Sopenharmony_ci		goto err;
48678c2ecf20Sopenharmony_ci
48688c2ecf20Sopenharmony_ci	if (stv090x_write_reg(state, STV090x_TSTRES0, 0x80) < 0)
48698c2ecf20Sopenharmony_ci		goto err;
48708c2ecf20Sopenharmony_ci	if (stv090x_write_reg(state, STV090x_TSTRES0, 0x00) < 0)
48718c2ecf20Sopenharmony_ci		goto err;
48728c2ecf20Sopenharmony_ci
48738c2ecf20Sopenharmony_ci	return 0;
48748c2ecf20Sopenharmony_cierr:
48758c2ecf20Sopenharmony_ci	dprintk(FE_ERROR, 1, "I/O error");
48768c2ecf20Sopenharmony_ci	return -1;
48778c2ecf20Sopenharmony_ci}
48788c2ecf20Sopenharmony_ci
48798c2ecf20Sopenharmony_cistatic int stv090x_set_gpio(struct dvb_frontend *fe, u8 gpio, u8 dir,
48808c2ecf20Sopenharmony_ci			    u8 value, u8 xor_value)
48818c2ecf20Sopenharmony_ci{
48828c2ecf20Sopenharmony_ci	struct stv090x_state *state = fe->demodulator_priv;
48838c2ecf20Sopenharmony_ci	u8 reg = 0;
48848c2ecf20Sopenharmony_ci
48858c2ecf20Sopenharmony_ci	STV090x_SETFIELD(reg, GPIOx_OPD_FIELD, dir);
48868c2ecf20Sopenharmony_ci	STV090x_SETFIELD(reg, GPIOx_CONFIG_FIELD, value);
48878c2ecf20Sopenharmony_ci	STV090x_SETFIELD(reg, GPIOx_XOR_FIELD, xor_value);
48888c2ecf20Sopenharmony_ci
48898c2ecf20Sopenharmony_ci	return stv090x_write_reg(state, STV090x_GPIOxCFG(gpio), reg);
48908c2ecf20Sopenharmony_ci}
48918c2ecf20Sopenharmony_ci
48928c2ecf20Sopenharmony_cistatic int stv090x_setup_compound(struct stv090x_state *state)
48938c2ecf20Sopenharmony_ci{
48948c2ecf20Sopenharmony_ci	struct stv090x_dev *temp_int;
48958c2ecf20Sopenharmony_ci
48968c2ecf20Sopenharmony_ci	temp_int = find_dev(state->i2c,
48978c2ecf20Sopenharmony_ci			    state->config->address);
48988c2ecf20Sopenharmony_ci
48998c2ecf20Sopenharmony_ci	if (temp_int && state->demod_mode == STV090x_DUAL) {
49008c2ecf20Sopenharmony_ci		state->internal = temp_int->internal;
49018c2ecf20Sopenharmony_ci		state->internal->num_used++;
49028c2ecf20Sopenharmony_ci		dprintk(FE_INFO, 1, "Found Internal Structure!");
49038c2ecf20Sopenharmony_ci	} else {
49048c2ecf20Sopenharmony_ci		state->internal = kmalloc(sizeof(*state->internal), GFP_KERNEL);
49058c2ecf20Sopenharmony_ci		if (!state->internal)
49068c2ecf20Sopenharmony_ci			goto error;
49078c2ecf20Sopenharmony_ci		temp_int = append_internal(state->internal);
49088c2ecf20Sopenharmony_ci		if (!temp_int) {
49098c2ecf20Sopenharmony_ci			kfree(state->internal);
49108c2ecf20Sopenharmony_ci			goto error;
49118c2ecf20Sopenharmony_ci		}
49128c2ecf20Sopenharmony_ci		state->internal->num_used = 1;
49138c2ecf20Sopenharmony_ci		state->internal->mclk = 0;
49148c2ecf20Sopenharmony_ci		state->internal->dev_ver = 0;
49158c2ecf20Sopenharmony_ci		state->internal->i2c_adap = state->i2c;
49168c2ecf20Sopenharmony_ci		state->internal->i2c_addr = state->config->address;
49178c2ecf20Sopenharmony_ci		dprintk(FE_INFO, 1, "Create New Internal Structure!");
49188c2ecf20Sopenharmony_ci
49198c2ecf20Sopenharmony_ci		mutex_init(&state->internal->demod_lock);
49208c2ecf20Sopenharmony_ci		mutex_init(&state->internal->tuner_lock);
49218c2ecf20Sopenharmony_ci
49228c2ecf20Sopenharmony_ci		if (stv090x_setup(&state->frontend) < 0) {
49238c2ecf20Sopenharmony_ci			dprintk(FE_ERROR, 1, "Error setting up device");
49248c2ecf20Sopenharmony_ci			goto err_remove;
49258c2ecf20Sopenharmony_ci		}
49268c2ecf20Sopenharmony_ci	}
49278c2ecf20Sopenharmony_ci
49288c2ecf20Sopenharmony_ci	if (state->internal->dev_ver >= 0x30)
49298c2ecf20Sopenharmony_ci		state->frontend.ops.info.caps |= FE_CAN_MULTISTREAM;
49308c2ecf20Sopenharmony_ci
49318c2ecf20Sopenharmony_ci	/* workaround for stuck DiSEqC output */
49328c2ecf20Sopenharmony_ci	if (state->config->diseqc_envelope_mode)
49338c2ecf20Sopenharmony_ci		stv090x_send_diseqc_burst(&state->frontend, SEC_MINI_A);
49348c2ecf20Sopenharmony_ci
49358c2ecf20Sopenharmony_ci	state->config->set_gpio = stv090x_set_gpio;
49368c2ecf20Sopenharmony_ci
49378c2ecf20Sopenharmony_ci	dprintk(FE_ERROR, 1, "Probing %s demodulator(%d) Cut=0x%02x",
49388c2ecf20Sopenharmony_ci		state->device == STV0900 ? "STV0900" : "STV0903",
49398c2ecf20Sopenharmony_ci		state->config->demod,
49408c2ecf20Sopenharmony_ci		state->internal->dev_ver);
49418c2ecf20Sopenharmony_ci
49428c2ecf20Sopenharmony_ci	return 0;
49438c2ecf20Sopenharmony_ci
49448c2ecf20Sopenharmony_cierror:
49458c2ecf20Sopenharmony_ci	return -ENOMEM;
49468c2ecf20Sopenharmony_cierr_remove:
49478c2ecf20Sopenharmony_ci	remove_dev(state->internal);
49488c2ecf20Sopenharmony_ci	kfree(state->internal);
49498c2ecf20Sopenharmony_ci	return -ENODEV;
49508c2ecf20Sopenharmony_ci}
49518c2ecf20Sopenharmony_ci
49528c2ecf20Sopenharmony_cistatic const struct dvb_frontend_ops stv090x_ops = {
49538c2ecf20Sopenharmony_ci	.delsys = { SYS_DVBS, SYS_DVBS2, SYS_DSS },
49548c2ecf20Sopenharmony_ci	.info = {
49558c2ecf20Sopenharmony_ci		.name			= "STV090x Multistandard",
49568c2ecf20Sopenharmony_ci		.frequency_min_hz	=  950 * MHz,
49578c2ecf20Sopenharmony_ci		.frequency_max_hz	= 2150 * MHz,
49588c2ecf20Sopenharmony_ci		.symbol_rate_min	= 1000000,
49598c2ecf20Sopenharmony_ci		.symbol_rate_max	= 45000000,
49608c2ecf20Sopenharmony_ci		.caps			= FE_CAN_INVERSION_AUTO |
49618c2ecf20Sopenharmony_ci					  FE_CAN_FEC_AUTO       |
49628c2ecf20Sopenharmony_ci					  FE_CAN_QPSK           |
49638c2ecf20Sopenharmony_ci					  FE_CAN_2G_MODULATION
49648c2ecf20Sopenharmony_ci	},
49658c2ecf20Sopenharmony_ci
49668c2ecf20Sopenharmony_ci	.release			= stv090x_release,
49678c2ecf20Sopenharmony_ci	.init				= stv090x_init,
49688c2ecf20Sopenharmony_ci
49698c2ecf20Sopenharmony_ci	.sleep				= stv090x_sleep,
49708c2ecf20Sopenharmony_ci	.get_frontend_algo		= stv090x_frontend_algo,
49718c2ecf20Sopenharmony_ci
49728c2ecf20Sopenharmony_ci	.diseqc_send_master_cmd		= stv090x_send_diseqc_msg,
49738c2ecf20Sopenharmony_ci	.diseqc_send_burst		= stv090x_send_diseqc_burst,
49748c2ecf20Sopenharmony_ci	.diseqc_recv_slave_reply	= stv090x_recv_slave_reply,
49758c2ecf20Sopenharmony_ci	.set_tone			= stv090x_set_tone,
49768c2ecf20Sopenharmony_ci
49778c2ecf20Sopenharmony_ci	.search				= stv090x_search,
49788c2ecf20Sopenharmony_ci	.read_status			= stv090x_read_status,
49798c2ecf20Sopenharmony_ci	.read_ber			= stv090x_read_per,
49808c2ecf20Sopenharmony_ci	.read_signal_strength		= stv090x_read_signal_strength,
49818c2ecf20Sopenharmony_ci	.read_snr			= stv090x_read_cnr,
49828c2ecf20Sopenharmony_ci};
49838c2ecf20Sopenharmony_ci
49848c2ecf20Sopenharmony_cistatic struct dvb_frontend *stv090x_get_dvb_frontend(struct i2c_client *client)
49858c2ecf20Sopenharmony_ci{
49868c2ecf20Sopenharmony_ci	struct stv090x_state *state = i2c_get_clientdata(client);
49878c2ecf20Sopenharmony_ci
49888c2ecf20Sopenharmony_ci	dev_dbg(&client->dev, "\n");
49898c2ecf20Sopenharmony_ci
49908c2ecf20Sopenharmony_ci	return &state->frontend;
49918c2ecf20Sopenharmony_ci}
49928c2ecf20Sopenharmony_ci
49938c2ecf20Sopenharmony_cistatic int stv090x_probe(struct i2c_client *client,
49948c2ecf20Sopenharmony_ci			 const struct i2c_device_id *id)
49958c2ecf20Sopenharmony_ci{
49968c2ecf20Sopenharmony_ci	int ret = 0;
49978c2ecf20Sopenharmony_ci	struct stv090x_config *config = client->dev.platform_data;
49988c2ecf20Sopenharmony_ci
49998c2ecf20Sopenharmony_ci	struct stv090x_state *state = NULL;
50008c2ecf20Sopenharmony_ci
50018c2ecf20Sopenharmony_ci	state = kzalloc(sizeof(*state), GFP_KERNEL);
50028c2ecf20Sopenharmony_ci	if (!state) {
50038c2ecf20Sopenharmony_ci		ret = -ENOMEM;
50048c2ecf20Sopenharmony_ci		goto error;
50058c2ecf20Sopenharmony_ci	}
50068c2ecf20Sopenharmony_ci
50078c2ecf20Sopenharmony_ci	state->verbose				= &verbose;
50088c2ecf20Sopenharmony_ci	state->config				= config;
50098c2ecf20Sopenharmony_ci	state->i2c				= client->adapter;
50108c2ecf20Sopenharmony_ci	state->frontend.ops			= stv090x_ops;
50118c2ecf20Sopenharmony_ci	state->frontend.demodulator_priv	= state;
50128c2ecf20Sopenharmony_ci	state->demod				= config->demod;
50138c2ecf20Sopenharmony_ci						/* Single or Dual mode */
50148c2ecf20Sopenharmony_ci	state->demod_mode			= config->demod_mode;
50158c2ecf20Sopenharmony_ci	state->device				= config->device;
50168c2ecf20Sopenharmony_ci						/* default */
50178c2ecf20Sopenharmony_ci	state->rolloff				= STV090x_RO_35;
50188c2ecf20Sopenharmony_ci
50198c2ecf20Sopenharmony_ci	ret = stv090x_setup_compound(state);
50208c2ecf20Sopenharmony_ci	if (ret)
50218c2ecf20Sopenharmony_ci		goto error;
50228c2ecf20Sopenharmony_ci
50238c2ecf20Sopenharmony_ci	i2c_set_clientdata(client, state);
50248c2ecf20Sopenharmony_ci
50258c2ecf20Sopenharmony_ci	/* setup callbacks */
50268c2ecf20Sopenharmony_ci	config->get_dvb_frontend = stv090x_get_dvb_frontend;
50278c2ecf20Sopenharmony_ci
50288c2ecf20Sopenharmony_ci	return 0;
50298c2ecf20Sopenharmony_ci
50308c2ecf20Sopenharmony_cierror:
50318c2ecf20Sopenharmony_ci	kfree(state);
50328c2ecf20Sopenharmony_ci	return ret;
50338c2ecf20Sopenharmony_ci}
50348c2ecf20Sopenharmony_ci
50358c2ecf20Sopenharmony_cistatic int stv090x_remove(struct i2c_client *client)
50368c2ecf20Sopenharmony_ci{
50378c2ecf20Sopenharmony_ci	struct stv090x_state *state = i2c_get_clientdata(client);
50388c2ecf20Sopenharmony_ci
50398c2ecf20Sopenharmony_ci	stv090x_release(&state->frontend);
50408c2ecf20Sopenharmony_ci	return 0;
50418c2ecf20Sopenharmony_ci}
50428c2ecf20Sopenharmony_ci
50438c2ecf20Sopenharmony_cistruct dvb_frontend *stv090x_attach(struct stv090x_config *config,
50448c2ecf20Sopenharmony_ci				    struct i2c_adapter *i2c,
50458c2ecf20Sopenharmony_ci				    enum stv090x_demodulator demod)
50468c2ecf20Sopenharmony_ci{
50478c2ecf20Sopenharmony_ci	int ret = 0;
50488c2ecf20Sopenharmony_ci	struct stv090x_state *state = NULL;
50498c2ecf20Sopenharmony_ci
50508c2ecf20Sopenharmony_ci	state = kzalloc(sizeof(*state), GFP_KERNEL);
50518c2ecf20Sopenharmony_ci	if (!state)
50528c2ecf20Sopenharmony_ci		goto error;
50538c2ecf20Sopenharmony_ci
50548c2ecf20Sopenharmony_ci	state->verbose				= &verbose;
50558c2ecf20Sopenharmony_ci	state->config				= config;
50568c2ecf20Sopenharmony_ci	state->i2c				= i2c;
50578c2ecf20Sopenharmony_ci	state->frontend.ops			= stv090x_ops;
50588c2ecf20Sopenharmony_ci	state->frontend.demodulator_priv	= state;
50598c2ecf20Sopenharmony_ci	state->demod				= demod;
50608c2ecf20Sopenharmony_ci						/* Single or Dual mode */
50618c2ecf20Sopenharmony_ci	state->demod_mode			= config->demod_mode;
50628c2ecf20Sopenharmony_ci	state->device				= config->device;
50638c2ecf20Sopenharmony_ci						/* default */
50648c2ecf20Sopenharmony_ci	state->rolloff				= STV090x_RO_35;
50658c2ecf20Sopenharmony_ci
50668c2ecf20Sopenharmony_ci	ret = stv090x_setup_compound(state);
50678c2ecf20Sopenharmony_ci	if (ret)
50688c2ecf20Sopenharmony_ci		goto error;
50698c2ecf20Sopenharmony_ci
50708c2ecf20Sopenharmony_ci	return &state->frontend;
50718c2ecf20Sopenharmony_ci
50728c2ecf20Sopenharmony_cierror:
50738c2ecf20Sopenharmony_ci	kfree(state);
50748c2ecf20Sopenharmony_ci	return NULL;
50758c2ecf20Sopenharmony_ci}
50768c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(stv090x_attach);
50778c2ecf20Sopenharmony_ci
50788c2ecf20Sopenharmony_cistatic const struct i2c_device_id stv090x_id_table[] = {
50798c2ecf20Sopenharmony_ci	{"stv090x", 0},
50808c2ecf20Sopenharmony_ci	{}
50818c2ecf20Sopenharmony_ci};
50828c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(i2c, stv090x_id_table);
50838c2ecf20Sopenharmony_ci
50848c2ecf20Sopenharmony_cistatic struct i2c_driver stv090x_driver = {
50858c2ecf20Sopenharmony_ci	.driver = {
50868c2ecf20Sopenharmony_ci		.name	= "stv090x",
50878c2ecf20Sopenharmony_ci		.suppress_bind_attrs = true,
50888c2ecf20Sopenharmony_ci	},
50898c2ecf20Sopenharmony_ci	.probe		= stv090x_probe,
50908c2ecf20Sopenharmony_ci	.remove		= stv090x_remove,
50918c2ecf20Sopenharmony_ci	.id_table	= stv090x_id_table,
50928c2ecf20Sopenharmony_ci};
50938c2ecf20Sopenharmony_ci
50948c2ecf20Sopenharmony_cimodule_i2c_driver(stv090x_driver);
50958c2ecf20Sopenharmony_ci
50968c2ecf20Sopenharmony_ciMODULE_PARM_DESC(verbose, "Set Verbosity level");
50978c2ecf20Sopenharmony_ciMODULE_AUTHOR("Manu Abraham");
50988c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("STV090x Multi-Std Broadcast frontend");
50998c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL");
5100