19a0bf528SMauro Carvalho Chehab /*
29a0bf528SMauro Carvalho Chehab  * drxk_hard: DRX-K DVB-C/T demodulator driver
39a0bf528SMauro Carvalho Chehab  *
49a0bf528SMauro Carvalho Chehab  * Copyright (C) 2010-2011 Digital Devices GmbH
59a0bf528SMauro Carvalho Chehab  *
69a0bf528SMauro Carvalho Chehab  * This program is free software; you can redistribute it and/or
79a0bf528SMauro Carvalho Chehab  * modify it under the terms of the GNU General Public License
89a0bf528SMauro Carvalho Chehab  * version 2 only, as published by the Free Software Foundation.
99a0bf528SMauro Carvalho Chehab  *
109a0bf528SMauro Carvalho Chehab  *
119a0bf528SMauro Carvalho Chehab  * This program is distributed in the hope that it will be useful,
129a0bf528SMauro Carvalho Chehab  * but WITHOUT ANY WARRANTY; without even the implied warranty of
139a0bf528SMauro Carvalho Chehab  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
149a0bf528SMauro Carvalho Chehab  * GNU General Public License for more details.
159a0bf528SMauro Carvalho Chehab  *
169a0bf528SMauro Carvalho Chehab  *
179a0bf528SMauro Carvalho Chehab  * You should have received a copy of the GNU General Public License
189a0bf528SMauro Carvalho Chehab  * along with this program; if not, write to the Free Software
199a0bf528SMauro Carvalho Chehab  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
209a0bf528SMauro Carvalho Chehab  * 02110-1301, USA
219a0bf528SMauro Carvalho Chehab  * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
229a0bf528SMauro Carvalho Chehab  */
239a0bf528SMauro Carvalho Chehab 
243a4398f5SMauro Carvalho Chehab #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
253a4398f5SMauro Carvalho Chehab 
269a0bf528SMauro Carvalho Chehab #include <linux/kernel.h>
279a0bf528SMauro Carvalho Chehab #include <linux/module.h>
289a0bf528SMauro Carvalho Chehab #include <linux/moduleparam.h>
299a0bf528SMauro Carvalho Chehab #include <linux/init.h>
309a0bf528SMauro Carvalho Chehab #include <linux/delay.h>
319a0bf528SMauro Carvalho Chehab #include <linux/firmware.h>
329a0bf528SMauro Carvalho Chehab #include <linux/i2c.h>
339a0bf528SMauro Carvalho Chehab #include <linux/hardirq.h>
349a0bf528SMauro Carvalho Chehab #include <asm/div64.h>
359a0bf528SMauro Carvalho Chehab 
369a0bf528SMauro Carvalho Chehab #include "dvb_frontend.h"
379a0bf528SMauro Carvalho Chehab #include "drxk.h"
389a0bf528SMauro Carvalho Chehab #include "drxk_hard.h"
39b5e9eb6fSMauro Carvalho Chehab #include "dvb_math.h"
409a0bf528SMauro Carvalho Chehab 
41cd7a67a4SMauro Carvalho Chehab static int power_down_dvbt(struct drxk_state *state, bool set_power_mode);
42cd7a67a4SMauro Carvalho Chehab static int power_down_qam(struct drxk_state *state);
43cd7a67a4SMauro Carvalho Chehab static int set_dvbt_standard(struct drxk_state *state,
44cd7a67a4SMauro Carvalho Chehab 			   enum operation_mode o_mode);
45cd7a67a4SMauro Carvalho Chehab static int set_qam_standard(struct drxk_state *state,
46cd7a67a4SMauro Carvalho Chehab 			  enum operation_mode o_mode);
47cd7a67a4SMauro Carvalho Chehab static int set_qam(struct drxk_state *state, u16 intermediate_freqk_hz,
48cd7a67a4SMauro Carvalho Chehab 		  s32 tuner_freq_offset);
49cd7a67a4SMauro Carvalho Chehab static int set_dvbt_standard(struct drxk_state *state,
50cd7a67a4SMauro Carvalho Chehab 			   enum operation_mode o_mode);
51cd7a67a4SMauro Carvalho Chehab static int dvbt_start(struct drxk_state *state);
52cd7a67a4SMauro Carvalho Chehab static int set_dvbt(struct drxk_state *state, u16 intermediate_freqk_hz,
53cd7a67a4SMauro Carvalho Chehab 		   s32 tuner_freq_offset);
54cd7a67a4SMauro Carvalho Chehab static int get_qam_lock_status(struct drxk_state *state, u32 *p_lock_status);
55cd7a67a4SMauro Carvalho Chehab static int get_dvbt_lock_status(struct drxk_state *state, u32 *p_lock_status);
56cd7a67a4SMauro Carvalho Chehab static int switch_antenna_to_qam(struct drxk_state *state);
57cd7a67a4SMauro Carvalho Chehab static int switch_antenna_to_dvbt(struct drxk_state *state);
589a0bf528SMauro Carvalho Chehab 
59cd7a67a4SMauro Carvalho Chehab static bool is_dvbt(struct drxk_state *state)
609a0bf528SMauro Carvalho Chehab {
61cd7a67a4SMauro Carvalho Chehab 	return state->m_operation_mode == OM_DVBT;
629a0bf528SMauro Carvalho Chehab }
639a0bf528SMauro Carvalho Chehab 
64cd7a67a4SMauro Carvalho Chehab static bool is_qam(struct drxk_state *state)
659a0bf528SMauro Carvalho Chehab {
66cd7a67a4SMauro Carvalho Chehab 	return state->m_operation_mode == OM_QAM_ITU_A ||
67cd7a67a4SMauro Carvalho Chehab 	    state->m_operation_mode == OM_QAM_ITU_B ||
68cd7a67a4SMauro Carvalho Chehab 	    state->m_operation_mode == OM_QAM_ITU_C;
699a0bf528SMauro Carvalho Chehab }
709a0bf528SMauro Carvalho Chehab 
719a0bf528SMauro Carvalho Chehab #define NOA1ROM 0
729a0bf528SMauro Carvalho Chehab 
739a0bf528SMauro Carvalho Chehab #define DRXDAP_FASI_SHORT_FORMAT(addr) (((addr) & 0xFC30FF80) == 0)
749a0bf528SMauro Carvalho Chehab #define DRXDAP_FASI_LONG_FORMAT(addr)  (((addr) & 0xFC30FF80) != 0)
759a0bf528SMauro Carvalho Chehab 
769a0bf528SMauro Carvalho Chehab #define DEFAULT_MER_83  165
779a0bf528SMauro Carvalho Chehab #define DEFAULT_MER_93  250
789a0bf528SMauro Carvalho Chehab 
799a0bf528SMauro Carvalho Chehab #ifndef DRXK_MPEG_SERIAL_OUTPUT_PIN_DRIVE_STRENGTH
809a0bf528SMauro Carvalho Chehab #define DRXK_MPEG_SERIAL_OUTPUT_PIN_DRIVE_STRENGTH (0x02)
819a0bf528SMauro Carvalho Chehab #endif
829a0bf528SMauro Carvalho Chehab 
839a0bf528SMauro Carvalho Chehab #ifndef DRXK_MPEG_PARALLEL_OUTPUT_PIN_DRIVE_STRENGTH
849a0bf528SMauro Carvalho Chehab #define DRXK_MPEG_PARALLEL_OUTPUT_PIN_DRIVE_STRENGTH (0x03)
859a0bf528SMauro Carvalho Chehab #endif
869a0bf528SMauro Carvalho Chehab 
879a0bf528SMauro Carvalho Chehab #define DEFAULT_DRXK_MPEG_LOCK_TIMEOUT 700
889a0bf528SMauro Carvalho Chehab #define DEFAULT_DRXK_DEMOD_LOCK_TIMEOUT 500
899a0bf528SMauro Carvalho Chehab 
909a0bf528SMauro Carvalho Chehab #ifndef DRXK_KI_RAGC_ATV
919a0bf528SMauro Carvalho Chehab #define DRXK_KI_RAGC_ATV   4
929a0bf528SMauro Carvalho Chehab #endif
939a0bf528SMauro Carvalho Chehab #ifndef DRXK_KI_IAGC_ATV
949a0bf528SMauro Carvalho Chehab #define DRXK_KI_IAGC_ATV   6
959a0bf528SMauro Carvalho Chehab #endif
969a0bf528SMauro Carvalho Chehab #ifndef DRXK_KI_DAGC_ATV
979a0bf528SMauro Carvalho Chehab #define DRXK_KI_DAGC_ATV   7
989a0bf528SMauro Carvalho Chehab #endif
999a0bf528SMauro Carvalho Chehab 
1009a0bf528SMauro Carvalho Chehab #ifndef DRXK_KI_RAGC_QAM
1019a0bf528SMauro Carvalho Chehab #define DRXK_KI_RAGC_QAM   3
1029a0bf528SMauro Carvalho Chehab #endif
1039a0bf528SMauro Carvalho Chehab #ifndef DRXK_KI_IAGC_QAM
1049a0bf528SMauro Carvalho Chehab #define DRXK_KI_IAGC_QAM   4
1059a0bf528SMauro Carvalho Chehab #endif
1069a0bf528SMauro Carvalho Chehab #ifndef DRXK_KI_DAGC_QAM
1079a0bf528SMauro Carvalho Chehab #define DRXK_KI_DAGC_QAM   7
1089a0bf528SMauro Carvalho Chehab #endif
1099a0bf528SMauro Carvalho Chehab #ifndef DRXK_KI_RAGC_DVBT
1109a0bf528SMauro Carvalho Chehab #define DRXK_KI_RAGC_DVBT  (IsA1WithPatchCode(state) ? 3 : 2)
1119a0bf528SMauro Carvalho Chehab #endif
1129a0bf528SMauro Carvalho Chehab #ifndef DRXK_KI_IAGC_DVBT
1139a0bf528SMauro Carvalho Chehab #define DRXK_KI_IAGC_DVBT  (IsA1WithPatchCode(state) ? 4 : 2)
1149a0bf528SMauro Carvalho Chehab #endif
1159a0bf528SMauro Carvalho Chehab #ifndef DRXK_KI_DAGC_DVBT
1169a0bf528SMauro Carvalho Chehab #define DRXK_KI_DAGC_DVBT  (IsA1WithPatchCode(state) ? 10 : 7)
1179a0bf528SMauro Carvalho Chehab #endif
1189a0bf528SMauro Carvalho Chehab 
1199a0bf528SMauro Carvalho Chehab #ifndef DRXK_AGC_DAC_OFFSET
1209a0bf528SMauro Carvalho Chehab #define DRXK_AGC_DAC_OFFSET (0x800)
1219a0bf528SMauro Carvalho Chehab #endif
1229a0bf528SMauro Carvalho Chehab 
1239a0bf528SMauro Carvalho Chehab #ifndef DRXK_BANDWIDTH_8MHZ_IN_HZ
1249a0bf528SMauro Carvalho Chehab #define DRXK_BANDWIDTH_8MHZ_IN_HZ  (0x8B8249L)
1259a0bf528SMauro Carvalho Chehab #endif
1269a0bf528SMauro Carvalho Chehab 
1279a0bf528SMauro Carvalho Chehab #ifndef DRXK_BANDWIDTH_7MHZ_IN_HZ
1289a0bf528SMauro Carvalho Chehab #define DRXK_BANDWIDTH_7MHZ_IN_HZ  (0x7A1200L)
1299a0bf528SMauro Carvalho Chehab #endif
1309a0bf528SMauro Carvalho Chehab 
1319a0bf528SMauro Carvalho Chehab #ifndef DRXK_BANDWIDTH_6MHZ_IN_HZ
1329a0bf528SMauro Carvalho Chehab #define DRXK_BANDWIDTH_6MHZ_IN_HZ  (0x68A1B6L)
1339a0bf528SMauro Carvalho Chehab #endif
1349a0bf528SMauro Carvalho Chehab 
1359a0bf528SMauro Carvalho Chehab #ifndef DRXK_QAM_SYMBOLRATE_MAX
1369a0bf528SMauro Carvalho Chehab #define DRXK_QAM_SYMBOLRATE_MAX         (7233000)
1379a0bf528SMauro Carvalho Chehab #endif
1389a0bf528SMauro Carvalho Chehab 
1399a0bf528SMauro Carvalho Chehab #define DRXK_BL_ROM_OFFSET_TAPS_DVBT    56
1409a0bf528SMauro Carvalho Chehab #define DRXK_BL_ROM_OFFSET_TAPS_ITU_A   64
1419a0bf528SMauro Carvalho Chehab #define DRXK_BL_ROM_OFFSET_TAPS_ITU_C   0x5FE0
1429a0bf528SMauro Carvalho Chehab #define DRXK_BL_ROM_OFFSET_TAPS_BG      24
1439a0bf528SMauro Carvalho Chehab #define DRXK_BL_ROM_OFFSET_TAPS_DKILLP  32
1449a0bf528SMauro Carvalho Chehab #define DRXK_BL_ROM_OFFSET_TAPS_NTSC    40
1459a0bf528SMauro Carvalho Chehab #define DRXK_BL_ROM_OFFSET_TAPS_FM      48
1469a0bf528SMauro Carvalho Chehab #define DRXK_BL_ROM_OFFSET_UCODE        0
1479a0bf528SMauro Carvalho Chehab 
1489a0bf528SMauro Carvalho Chehab #define DRXK_BLC_TIMEOUT                100
1499a0bf528SMauro Carvalho Chehab 
1509a0bf528SMauro Carvalho Chehab #define DRXK_BLCC_NR_ELEMENTS_TAPS      2
1519a0bf528SMauro Carvalho Chehab #define DRXK_BLCC_NR_ELEMENTS_UCODE     6
1529a0bf528SMauro Carvalho Chehab 
1539a0bf528SMauro Carvalho Chehab #define DRXK_BLDC_NR_ELEMENTS_TAPS      28
1549a0bf528SMauro Carvalho Chehab 
1559a0bf528SMauro Carvalho Chehab #ifndef DRXK_OFDM_NE_NOTCH_WIDTH
1569a0bf528SMauro Carvalho Chehab #define DRXK_OFDM_NE_NOTCH_WIDTH             (4)
1579a0bf528SMauro Carvalho Chehab #endif
1589a0bf528SMauro Carvalho Chehab 
1599a0bf528SMauro Carvalho Chehab #define DRXK_QAM_SL_SIG_POWER_QAM16       (40960)
1609a0bf528SMauro Carvalho Chehab #define DRXK_QAM_SL_SIG_POWER_QAM32       (20480)
1619a0bf528SMauro Carvalho Chehab #define DRXK_QAM_SL_SIG_POWER_QAM64       (43008)
1629a0bf528SMauro Carvalho Chehab #define DRXK_QAM_SL_SIG_POWER_QAM128      (20992)
1639a0bf528SMauro Carvalho Chehab #define DRXK_QAM_SL_SIG_POWER_QAM256      (43520)
1649a0bf528SMauro Carvalho Chehab 
1659a0bf528SMauro Carvalho Chehab static unsigned int debug;
1669a0bf528SMauro Carvalho Chehab module_param(debug, int, 0644);
1679a0bf528SMauro Carvalho Chehab MODULE_PARM_DESC(debug, "enable debug messages");
1689a0bf528SMauro Carvalho Chehab 
1699a0bf528SMauro Carvalho Chehab #define dprintk(level, fmt, arg...) do {			\
1709a0bf528SMauro Carvalho Chehab if (debug >= level)						\
1719a0bf528SMauro Carvalho Chehab 	printk(KERN_DEBUG "drxk: %s" fmt, __func__, ## arg);	\
1729a0bf528SMauro Carvalho Chehab } while (0)
1739a0bf528SMauro Carvalho Chehab 
1749a0bf528SMauro Carvalho Chehab 
1759a0bf528SMauro Carvalho Chehab static inline u32 MulDiv32(u32 a, u32 b, u32 c)
1769a0bf528SMauro Carvalho Chehab {
1779a0bf528SMauro Carvalho Chehab 	u64 tmp64;
1789a0bf528SMauro Carvalho Chehab 
1799a0bf528SMauro Carvalho Chehab 	tmp64 = (u64) a * (u64) b;
1809a0bf528SMauro Carvalho Chehab 	do_div(tmp64, c);
1819a0bf528SMauro Carvalho Chehab 
1829a0bf528SMauro Carvalho Chehab 	return (u32) tmp64;
1839a0bf528SMauro Carvalho Chehab }
1849a0bf528SMauro Carvalho Chehab 
185ff38c216SMauro Carvalho Chehab static inline u32 Frac28a(u32 a, u32 c)
1869a0bf528SMauro Carvalho Chehab {
1879a0bf528SMauro Carvalho Chehab 	int i = 0;
1889a0bf528SMauro Carvalho Chehab 	u32 Q1 = 0;
1899a0bf528SMauro Carvalho Chehab 	u32 R0 = 0;
1909a0bf528SMauro Carvalho Chehab 
1919a0bf528SMauro Carvalho Chehab 	R0 = (a % c) << 4;	/* 32-28 == 4 shifts possible at max */
1929a0bf528SMauro Carvalho Chehab 	Q1 = a / c;		/* integer part, only the 4 least significant bits
1939a0bf528SMauro Carvalho Chehab 				   will be visible in the result */
1949a0bf528SMauro Carvalho Chehab 
1959a0bf528SMauro Carvalho Chehab 	/* division using radix 16, 7 nibbles in the result */
1969a0bf528SMauro Carvalho Chehab 	for (i = 0; i < 7; i++) {
1979a0bf528SMauro Carvalho Chehab 		Q1 = (Q1 << 4) | (R0 / c);
1989a0bf528SMauro Carvalho Chehab 		R0 = (R0 % c) << 4;
1999a0bf528SMauro Carvalho Chehab 	}
2009a0bf528SMauro Carvalho Chehab 	/* rounding */
2019a0bf528SMauro Carvalho Chehab 	if ((R0 >> 3) >= c)
2029a0bf528SMauro Carvalho Chehab 		Q1++;
2039a0bf528SMauro Carvalho Chehab 
2049a0bf528SMauro Carvalho Chehab 	return Q1;
2059a0bf528SMauro Carvalho Chehab }
2069a0bf528SMauro Carvalho Chehab 
207b5e9eb6fSMauro Carvalho Chehab static inline u32 log10times100(u32 value)
2089a0bf528SMauro Carvalho Chehab {
209b5e9eb6fSMauro Carvalho Chehab 	return (100L * intlog10(value)) >> 24;
2109a0bf528SMauro Carvalho Chehab }
2119a0bf528SMauro Carvalho Chehab 
2129a0bf528SMauro Carvalho Chehab /****************************************************************************/
2139a0bf528SMauro Carvalho Chehab /* I2C **********************************************************************/
2149a0bf528SMauro Carvalho Chehab /****************************************************************************/
2159a0bf528SMauro Carvalho Chehab 
2169a0bf528SMauro Carvalho Chehab static int drxk_i2c_lock(struct drxk_state *state)
2179a0bf528SMauro Carvalho Chehab {
2189a0bf528SMauro Carvalho Chehab 	i2c_lock_adapter(state->i2c);
2199a0bf528SMauro Carvalho Chehab 	state->drxk_i2c_exclusive_lock = true;
2209a0bf528SMauro Carvalho Chehab 
2219a0bf528SMauro Carvalho Chehab 	return 0;
2229a0bf528SMauro Carvalho Chehab }
2239a0bf528SMauro Carvalho Chehab 
2249a0bf528SMauro Carvalho Chehab static void drxk_i2c_unlock(struct drxk_state *state)
2259a0bf528SMauro Carvalho Chehab {
2269a0bf528SMauro Carvalho Chehab 	if (!state->drxk_i2c_exclusive_lock)
2279a0bf528SMauro Carvalho Chehab 		return;
2289a0bf528SMauro Carvalho Chehab 
2299a0bf528SMauro Carvalho Chehab 	i2c_unlock_adapter(state->i2c);
2309a0bf528SMauro Carvalho Chehab 	state->drxk_i2c_exclusive_lock = false;
2319a0bf528SMauro Carvalho Chehab }
2329a0bf528SMauro Carvalho Chehab 
2339a0bf528SMauro Carvalho Chehab static int drxk_i2c_transfer(struct drxk_state *state, struct i2c_msg *msgs,
2349a0bf528SMauro Carvalho Chehab 			     unsigned len)
2359a0bf528SMauro Carvalho Chehab {
2369a0bf528SMauro Carvalho Chehab 	if (state->drxk_i2c_exclusive_lock)
2379a0bf528SMauro Carvalho Chehab 		return __i2c_transfer(state->i2c, msgs, len);
2389a0bf528SMauro Carvalho Chehab 	else
2399a0bf528SMauro Carvalho Chehab 		return i2c_transfer(state->i2c, msgs, len);
2409a0bf528SMauro Carvalho Chehab }
2419a0bf528SMauro Carvalho Chehab 
2429a0bf528SMauro Carvalho Chehab static int i2c_read1(struct drxk_state *state, u8 adr, u8 *val)
2439a0bf528SMauro Carvalho Chehab {
2449a0bf528SMauro Carvalho Chehab 	struct i2c_msg msgs[1] = { {.addr = adr, .flags = I2C_M_RD,
2459a0bf528SMauro Carvalho Chehab 				    .buf = val, .len = 1}
2469a0bf528SMauro Carvalho Chehab 	};
2479a0bf528SMauro Carvalho Chehab 
2489a0bf528SMauro Carvalho Chehab 	return drxk_i2c_transfer(state, msgs, 1);
2499a0bf528SMauro Carvalho Chehab }
2509a0bf528SMauro Carvalho Chehab 
2519a0bf528SMauro Carvalho Chehab static int i2c_write(struct drxk_state *state, u8 adr, u8 *data, int len)
2529a0bf528SMauro Carvalho Chehab {
2539a0bf528SMauro Carvalho Chehab 	int status;
2549a0bf528SMauro Carvalho Chehab 	struct i2c_msg msg = {
2559a0bf528SMauro Carvalho Chehab 	    .addr = adr, .flags = 0, .buf = data, .len = len };
2569a0bf528SMauro Carvalho Chehab 
2579a0bf528SMauro Carvalho Chehab 	dprintk(3, ":");
2589a0bf528SMauro Carvalho Chehab 	if (debug > 2) {
2599a0bf528SMauro Carvalho Chehab 		int i;
2609a0bf528SMauro Carvalho Chehab 		for (i = 0; i < len; i++)
2619a0bf528SMauro Carvalho Chehab 			printk(KERN_CONT " %02x", data[i]);
2629a0bf528SMauro Carvalho Chehab 		printk(KERN_CONT "\n");
2639a0bf528SMauro Carvalho Chehab 	}
2649a0bf528SMauro Carvalho Chehab 	status = drxk_i2c_transfer(state, &msg, 1);
2659a0bf528SMauro Carvalho Chehab 	if (status >= 0 && status != 1)
2669a0bf528SMauro Carvalho Chehab 		status = -EIO;
2679a0bf528SMauro Carvalho Chehab 
2689a0bf528SMauro Carvalho Chehab 	if (status < 0)
2693a4398f5SMauro Carvalho Chehab 		pr_err("i2c write error at addr 0x%02x\n", adr);
2709a0bf528SMauro Carvalho Chehab 
2719a0bf528SMauro Carvalho Chehab 	return status;
2729a0bf528SMauro Carvalho Chehab }
2739a0bf528SMauro Carvalho Chehab 
2749a0bf528SMauro Carvalho Chehab static int i2c_read(struct drxk_state *state,
2759a0bf528SMauro Carvalho Chehab 		    u8 adr, u8 *msg, int len, u8 *answ, int alen)
2769a0bf528SMauro Carvalho Chehab {
2779a0bf528SMauro Carvalho Chehab 	int status;
2789a0bf528SMauro Carvalho Chehab 	struct i2c_msg msgs[2] = {
2799a0bf528SMauro Carvalho Chehab 		{.addr = adr, .flags = 0,
2809a0bf528SMauro Carvalho Chehab 				    .buf = msg, .len = len},
2819a0bf528SMauro Carvalho Chehab 		{.addr = adr, .flags = I2C_M_RD,
2829a0bf528SMauro Carvalho Chehab 		 .buf = answ, .len = alen}
2839a0bf528SMauro Carvalho Chehab 	};
2849a0bf528SMauro Carvalho Chehab 
2859a0bf528SMauro Carvalho Chehab 	status = drxk_i2c_transfer(state, msgs, 2);
2869a0bf528SMauro Carvalho Chehab 	if (status != 2) {
2879a0bf528SMauro Carvalho Chehab 		if (debug > 2)
2889a0bf528SMauro Carvalho Chehab 			printk(KERN_CONT ": ERROR!\n");
2899a0bf528SMauro Carvalho Chehab 		if (status >= 0)
2909a0bf528SMauro Carvalho Chehab 			status = -EIO;
2919a0bf528SMauro Carvalho Chehab 
2923a4398f5SMauro Carvalho Chehab 		pr_err("i2c read error at addr 0x%02x\n", adr);
2939a0bf528SMauro Carvalho Chehab 		return status;
2949a0bf528SMauro Carvalho Chehab 	}
2959a0bf528SMauro Carvalho Chehab 	if (debug > 2) {
2969a0bf528SMauro Carvalho Chehab 		int i;
2979a0bf528SMauro Carvalho Chehab 		dprintk(2, ": read from");
2989a0bf528SMauro Carvalho Chehab 		for (i = 0; i < len; i++)
2999a0bf528SMauro Carvalho Chehab 			printk(KERN_CONT " %02x", msg[i]);
3009a0bf528SMauro Carvalho Chehab 		printk(KERN_CONT ", value = ");
3019a0bf528SMauro Carvalho Chehab 		for (i = 0; i < alen; i++)
3029a0bf528SMauro Carvalho Chehab 			printk(KERN_CONT " %02x", answ[i]);
3039a0bf528SMauro Carvalho Chehab 		printk(KERN_CONT "\n");
3049a0bf528SMauro Carvalho Chehab 	}
3059a0bf528SMauro Carvalho Chehab 	return 0;
3069a0bf528SMauro Carvalho Chehab }
3079a0bf528SMauro Carvalho Chehab 
3089a0bf528SMauro Carvalho Chehab static int read16_flags(struct drxk_state *state, u32 reg, u16 *data, u8 flags)
3099a0bf528SMauro Carvalho Chehab {
3109a0bf528SMauro Carvalho Chehab 	int status;
3119a0bf528SMauro Carvalho Chehab 	u8 adr = state->demod_address, mm1[4], mm2[2], len;
3129a0bf528SMauro Carvalho Chehab 
3139a0bf528SMauro Carvalho Chehab 	if (state->single_master)
3149a0bf528SMauro Carvalho Chehab 		flags |= 0xC0;
3159a0bf528SMauro Carvalho Chehab 
3169a0bf528SMauro Carvalho Chehab 	if (DRXDAP_FASI_LONG_FORMAT(reg) || (flags != 0)) {
3179a0bf528SMauro Carvalho Chehab 		mm1[0] = (((reg << 1) & 0xFF) | 0x01);
3189a0bf528SMauro Carvalho Chehab 		mm1[1] = ((reg >> 16) & 0xFF);
3199a0bf528SMauro Carvalho Chehab 		mm1[2] = ((reg >> 24) & 0xFF) | flags;
3209a0bf528SMauro Carvalho Chehab 		mm1[3] = ((reg >> 7) & 0xFF);
3219a0bf528SMauro Carvalho Chehab 		len = 4;
3229a0bf528SMauro Carvalho Chehab 	} else {
3239a0bf528SMauro Carvalho Chehab 		mm1[0] = ((reg << 1) & 0xFF);
3249a0bf528SMauro Carvalho Chehab 		mm1[1] = (((reg >> 16) & 0x0F) | ((reg >> 18) & 0xF0));
3259a0bf528SMauro Carvalho Chehab 		len = 2;
3269a0bf528SMauro Carvalho Chehab 	}
3279a0bf528SMauro Carvalho Chehab 	dprintk(2, "(0x%08x, 0x%02x)\n", reg, flags);
3289a0bf528SMauro Carvalho Chehab 	status = i2c_read(state, adr, mm1, len, mm2, 2);
3299a0bf528SMauro Carvalho Chehab 	if (status < 0)
3309a0bf528SMauro Carvalho Chehab 		return status;
3319a0bf528SMauro Carvalho Chehab 	if (data)
3329a0bf528SMauro Carvalho Chehab 		*data = mm2[0] | (mm2[1] << 8);
3339a0bf528SMauro Carvalho Chehab 
3349a0bf528SMauro Carvalho Chehab 	return 0;
3359a0bf528SMauro Carvalho Chehab }
3369a0bf528SMauro Carvalho Chehab 
3379a0bf528SMauro Carvalho Chehab static int read16(struct drxk_state *state, u32 reg, u16 *data)
3389a0bf528SMauro Carvalho Chehab {
3399a0bf528SMauro Carvalho Chehab 	return read16_flags(state, reg, data, 0);
3409a0bf528SMauro Carvalho Chehab }
3419a0bf528SMauro Carvalho Chehab 
3429a0bf528SMauro Carvalho Chehab static int read32_flags(struct drxk_state *state, u32 reg, u32 *data, u8 flags)
3439a0bf528SMauro Carvalho Chehab {
3449a0bf528SMauro Carvalho Chehab 	int status;
3459a0bf528SMauro Carvalho Chehab 	u8 adr = state->demod_address, mm1[4], mm2[4], len;
3469a0bf528SMauro Carvalho Chehab 
3479a0bf528SMauro Carvalho Chehab 	if (state->single_master)
3489a0bf528SMauro Carvalho Chehab 		flags |= 0xC0;
3499a0bf528SMauro Carvalho Chehab 
3509a0bf528SMauro Carvalho Chehab 	if (DRXDAP_FASI_LONG_FORMAT(reg) || (flags != 0)) {
3519a0bf528SMauro Carvalho Chehab 		mm1[0] = (((reg << 1) & 0xFF) | 0x01);
3529a0bf528SMauro Carvalho Chehab 		mm1[1] = ((reg >> 16) & 0xFF);
3539a0bf528SMauro Carvalho Chehab 		mm1[2] = ((reg >> 24) & 0xFF) | flags;
3549a0bf528SMauro Carvalho Chehab 		mm1[3] = ((reg >> 7) & 0xFF);
3559a0bf528SMauro Carvalho Chehab 		len = 4;
3569a0bf528SMauro Carvalho Chehab 	} else {
3579a0bf528SMauro Carvalho Chehab 		mm1[0] = ((reg << 1) & 0xFF);
3589a0bf528SMauro Carvalho Chehab 		mm1[1] = (((reg >> 16) & 0x0F) | ((reg >> 18) & 0xF0));
3599a0bf528SMauro Carvalho Chehab 		len = 2;
3609a0bf528SMauro Carvalho Chehab 	}
3619a0bf528SMauro Carvalho Chehab 	dprintk(2, "(0x%08x, 0x%02x)\n", reg, flags);
3629a0bf528SMauro Carvalho Chehab 	status = i2c_read(state, adr, mm1, len, mm2, 4);
3639a0bf528SMauro Carvalho Chehab 	if (status < 0)
3649a0bf528SMauro Carvalho Chehab 		return status;
3659a0bf528SMauro Carvalho Chehab 	if (data)
3669a0bf528SMauro Carvalho Chehab 		*data = mm2[0] | (mm2[1] << 8) |
3679a0bf528SMauro Carvalho Chehab 		    (mm2[2] << 16) | (mm2[3] << 24);
3689a0bf528SMauro Carvalho Chehab 
3699a0bf528SMauro Carvalho Chehab 	return 0;
3709a0bf528SMauro Carvalho Chehab }
3719a0bf528SMauro Carvalho Chehab 
3729a0bf528SMauro Carvalho Chehab static int read32(struct drxk_state *state, u32 reg, u32 *data)
3739a0bf528SMauro Carvalho Chehab {
3749a0bf528SMauro Carvalho Chehab 	return read32_flags(state, reg, data, 0);
3759a0bf528SMauro Carvalho Chehab }
3769a0bf528SMauro Carvalho Chehab 
3779a0bf528SMauro Carvalho Chehab static int write16_flags(struct drxk_state *state, u32 reg, u16 data, u8 flags)
3789a0bf528SMauro Carvalho Chehab {
3799a0bf528SMauro Carvalho Chehab 	u8 adr = state->demod_address, mm[6], len;
3809a0bf528SMauro Carvalho Chehab 
3819a0bf528SMauro Carvalho Chehab 	if (state->single_master)
3829a0bf528SMauro Carvalho Chehab 		flags |= 0xC0;
3839a0bf528SMauro Carvalho Chehab 	if (DRXDAP_FASI_LONG_FORMAT(reg) || (flags != 0)) {
3849a0bf528SMauro Carvalho Chehab 		mm[0] = (((reg << 1) & 0xFF) | 0x01);
3859a0bf528SMauro Carvalho Chehab 		mm[1] = ((reg >> 16) & 0xFF);
3869a0bf528SMauro Carvalho Chehab 		mm[2] = ((reg >> 24) & 0xFF) | flags;
3879a0bf528SMauro Carvalho Chehab 		mm[3] = ((reg >> 7) & 0xFF);
3889a0bf528SMauro Carvalho Chehab 		len = 4;
3899a0bf528SMauro Carvalho Chehab 	} else {
3909a0bf528SMauro Carvalho Chehab 		mm[0] = ((reg << 1) & 0xFF);
3919a0bf528SMauro Carvalho Chehab 		mm[1] = (((reg >> 16) & 0x0F) | ((reg >> 18) & 0xF0));
3929a0bf528SMauro Carvalho Chehab 		len = 2;
3939a0bf528SMauro Carvalho Chehab 	}
3949a0bf528SMauro Carvalho Chehab 	mm[len] = data & 0xff;
3959a0bf528SMauro Carvalho Chehab 	mm[len + 1] = (data >> 8) & 0xff;
3969a0bf528SMauro Carvalho Chehab 
3979a0bf528SMauro Carvalho Chehab 	dprintk(2, "(0x%08x, 0x%04x, 0x%02x)\n", reg, data, flags);
3989a0bf528SMauro Carvalho Chehab 	return i2c_write(state, adr, mm, len + 2);
3999a0bf528SMauro Carvalho Chehab }
4009a0bf528SMauro Carvalho Chehab 
4019a0bf528SMauro Carvalho Chehab static int write16(struct drxk_state *state, u32 reg, u16 data)
4029a0bf528SMauro Carvalho Chehab {
4039a0bf528SMauro Carvalho Chehab 	return write16_flags(state, reg, data, 0);
4049a0bf528SMauro Carvalho Chehab }
4059a0bf528SMauro Carvalho Chehab 
4069a0bf528SMauro Carvalho Chehab static int write32_flags(struct drxk_state *state, u32 reg, u32 data, u8 flags)
4079a0bf528SMauro Carvalho Chehab {
4089a0bf528SMauro Carvalho Chehab 	u8 adr = state->demod_address, mm[8], len;
4099a0bf528SMauro Carvalho Chehab 
4109a0bf528SMauro Carvalho Chehab 	if (state->single_master)
4119a0bf528SMauro Carvalho Chehab 		flags |= 0xC0;
4129a0bf528SMauro Carvalho Chehab 	if (DRXDAP_FASI_LONG_FORMAT(reg) || (flags != 0)) {
4139a0bf528SMauro Carvalho Chehab 		mm[0] = (((reg << 1) & 0xFF) | 0x01);
4149a0bf528SMauro Carvalho Chehab 		mm[1] = ((reg >> 16) & 0xFF);
4159a0bf528SMauro Carvalho Chehab 		mm[2] = ((reg >> 24) & 0xFF) | flags;
4169a0bf528SMauro Carvalho Chehab 		mm[3] = ((reg >> 7) & 0xFF);
4179a0bf528SMauro Carvalho Chehab 		len = 4;
4189a0bf528SMauro Carvalho Chehab 	} else {
4199a0bf528SMauro Carvalho Chehab 		mm[0] = ((reg << 1) & 0xFF);
4209a0bf528SMauro Carvalho Chehab 		mm[1] = (((reg >> 16) & 0x0F) | ((reg >> 18) & 0xF0));
4219a0bf528SMauro Carvalho Chehab 		len = 2;
4229a0bf528SMauro Carvalho Chehab 	}
4239a0bf528SMauro Carvalho Chehab 	mm[len] = data & 0xff;
4249a0bf528SMauro Carvalho Chehab 	mm[len + 1] = (data >> 8) & 0xff;
4259a0bf528SMauro Carvalho Chehab 	mm[len + 2] = (data >> 16) & 0xff;
4269a0bf528SMauro Carvalho Chehab 	mm[len + 3] = (data >> 24) & 0xff;
4279a0bf528SMauro Carvalho Chehab 	dprintk(2, "(0x%08x, 0x%08x, 0x%02x)\n", reg, data, flags);
4289a0bf528SMauro Carvalho Chehab 
4299a0bf528SMauro Carvalho Chehab 	return i2c_write(state, adr, mm, len + 4);
4309a0bf528SMauro Carvalho Chehab }
4319a0bf528SMauro Carvalho Chehab 
4329a0bf528SMauro Carvalho Chehab static int write32(struct drxk_state *state, u32 reg, u32 data)
4339a0bf528SMauro Carvalho Chehab {
4349a0bf528SMauro Carvalho Chehab 	return write32_flags(state, reg, data, 0);
4359a0bf528SMauro Carvalho Chehab }
4369a0bf528SMauro Carvalho Chehab 
437cd7a67a4SMauro Carvalho Chehab static int write_block(struct drxk_state *state, u32 address,
438cd7a67a4SMauro Carvalho Chehab 		      const int block_size, const u8 p_block[])
4399a0bf528SMauro Carvalho Chehab {
440cd7a67a4SMauro Carvalho Chehab 	int status = 0, blk_size = block_size;
441cd7a67a4SMauro Carvalho Chehab 	u8 flags = 0;
4429a0bf528SMauro Carvalho Chehab 
4439a0bf528SMauro Carvalho Chehab 	if (state->single_master)
444cd7a67a4SMauro Carvalho Chehab 		flags |= 0xC0;
4459a0bf528SMauro Carvalho Chehab 
446cd7a67a4SMauro Carvalho Chehab 	while (blk_size > 0) {
447cd7a67a4SMauro Carvalho Chehab 		int chunk = blk_size > state->m_chunk_size ?
448cd7a67a4SMauro Carvalho Chehab 		    state->m_chunk_size : blk_size;
449cd7a67a4SMauro Carvalho Chehab 		u8 *adr_buf = &state->chunk[0];
450cd7a67a4SMauro Carvalho Chehab 		u32 adr_length = 0;
4519a0bf528SMauro Carvalho Chehab 
452cd7a67a4SMauro Carvalho Chehab 		if (DRXDAP_FASI_LONG_FORMAT(address) || (flags != 0)) {
453cd7a67a4SMauro Carvalho Chehab 			adr_buf[0] = (((address << 1) & 0xFF) | 0x01);
454cd7a67a4SMauro Carvalho Chehab 			adr_buf[1] = ((address >> 16) & 0xFF);
455cd7a67a4SMauro Carvalho Chehab 			adr_buf[2] = ((address >> 24) & 0xFF);
456cd7a67a4SMauro Carvalho Chehab 			adr_buf[3] = ((address >> 7) & 0xFF);
457cd7a67a4SMauro Carvalho Chehab 			adr_buf[2] |= flags;
458cd7a67a4SMauro Carvalho Chehab 			adr_length = 4;
459cd7a67a4SMauro Carvalho Chehab 			if (chunk == state->m_chunk_size)
460cd7a67a4SMauro Carvalho Chehab 				chunk -= 2;
4619a0bf528SMauro Carvalho Chehab 		} else {
462cd7a67a4SMauro Carvalho Chehab 			adr_buf[0] = ((address << 1) & 0xFF);
463cd7a67a4SMauro Carvalho Chehab 			adr_buf[1] = (((address >> 16) & 0x0F) |
464cd7a67a4SMauro Carvalho Chehab 				     ((address >> 18) & 0xF0));
465cd7a67a4SMauro Carvalho Chehab 			adr_length = 2;
4669a0bf528SMauro Carvalho Chehab 		}
467cd7a67a4SMauro Carvalho Chehab 		memcpy(&state->chunk[adr_length], p_block, chunk);
468cd7a67a4SMauro Carvalho Chehab 		dprintk(2, "(0x%08x, 0x%02x)\n", address, flags);
4699a0bf528SMauro Carvalho Chehab 		if (debug > 1) {
4709a0bf528SMauro Carvalho Chehab 			int i;
471cd7a67a4SMauro Carvalho Chehab 			if (p_block)
472cd7a67a4SMauro Carvalho Chehab 				for (i = 0; i < chunk; i++)
473cd7a67a4SMauro Carvalho Chehab 					printk(KERN_CONT " %02x", p_block[i]);
4749a0bf528SMauro Carvalho Chehab 			printk(KERN_CONT "\n");
4759a0bf528SMauro Carvalho Chehab 		}
4769a0bf528SMauro Carvalho Chehab 		status = i2c_write(state, state->demod_address,
477cd7a67a4SMauro Carvalho Chehab 				   &state->chunk[0], chunk + adr_length);
4789a0bf528SMauro Carvalho Chehab 		if (status < 0) {
4793a4398f5SMauro Carvalho Chehab 			pr_err("%s: i2c write error at addr 0x%02x\n",
480cd7a67a4SMauro Carvalho Chehab 			       __func__, address);
4819a0bf528SMauro Carvalho Chehab 			break;
4829a0bf528SMauro Carvalho Chehab 		}
483cd7a67a4SMauro Carvalho Chehab 		p_block += chunk;
484cd7a67a4SMauro Carvalho Chehab 		address += (chunk >> 1);
485cd7a67a4SMauro Carvalho Chehab 		blk_size -= chunk;
4869a0bf528SMauro Carvalho Chehab 	}
4879a0bf528SMauro Carvalho Chehab 	return status;
4889a0bf528SMauro Carvalho Chehab }
4899a0bf528SMauro Carvalho Chehab 
4909a0bf528SMauro Carvalho Chehab #ifndef DRXK_MAX_RETRIES_POWERUP
4919a0bf528SMauro Carvalho Chehab #define DRXK_MAX_RETRIES_POWERUP 20
4929a0bf528SMauro Carvalho Chehab #endif
4939a0bf528SMauro Carvalho Chehab 
494cd7a67a4SMauro Carvalho Chehab static int power_up_device(struct drxk_state *state)
4959a0bf528SMauro Carvalho Chehab {
4969a0bf528SMauro Carvalho Chehab 	int status;
4979a0bf528SMauro Carvalho Chehab 	u8 data = 0;
498cd7a67a4SMauro Carvalho Chehab 	u16 retry_count = 0;
4999a0bf528SMauro Carvalho Chehab 
5009a0bf528SMauro Carvalho Chehab 	dprintk(1, "\n");
5019a0bf528SMauro Carvalho Chehab 
5029a0bf528SMauro Carvalho Chehab 	status = i2c_read1(state, state->demod_address, &data);
5039a0bf528SMauro Carvalho Chehab 	if (status < 0) {
5049a0bf528SMauro Carvalho Chehab 		do {
5059a0bf528SMauro Carvalho Chehab 			data = 0;
5069a0bf528SMauro Carvalho Chehab 			status = i2c_write(state, state->demod_address,
5079a0bf528SMauro Carvalho Chehab 					   &data, 1);
5089a0bf528SMauro Carvalho Chehab 			msleep(10);
509cd7a67a4SMauro Carvalho Chehab 			retry_count++;
5109a0bf528SMauro Carvalho Chehab 			if (status < 0)
5119a0bf528SMauro Carvalho Chehab 				continue;
5129a0bf528SMauro Carvalho Chehab 			status = i2c_read1(state, state->demod_address,
5139a0bf528SMauro Carvalho Chehab 					   &data);
5149a0bf528SMauro Carvalho Chehab 		} while (status < 0 &&
515cd7a67a4SMauro Carvalho Chehab 			 (retry_count < DRXK_MAX_RETRIES_POWERUP));
516cd7a67a4SMauro Carvalho Chehab 		if (status < 0 && retry_count >= DRXK_MAX_RETRIES_POWERUP)
5179a0bf528SMauro Carvalho Chehab 			goto error;
5189a0bf528SMauro Carvalho Chehab 	}
5199a0bf528SMauro Carvalho Chehab 
5209a0bf528SMauro Carvalho Chehab 	/* Make sure all clk domains are active */
5219a0bf528SMauro Carvalho Chehab 	status = write16(state, SIO_CC_PWD_MODE__A, SIO_CC_PWD_MODE_LEVEL_NONE);
5229a0bf528SMauro Carvalho Chehab 	if (status < 0)
5239a0bf528SMauro Carvalho Chehab 		goto error;
5249a0bf528SMauro Carvalho Chehab 	status = write16(state, SIO_CC_UPDATE__A, SIO_CC_UPDATE_KEY);
5259a0bf528SMauro Carvalho Chehab 	if (status < 0)
5269a0bf528SMauro Carvalho Chehab 		goto error;
5279a0bf528SMauro Carvalho Chehab 	/* Enable pll lock tests */
5289a0bf528SMauro Carvalho Chehab 	status = write16(state, SIO_CC_PLL_LOCK__A, 1);
5299a0bf528SMauro Carvalho Chehab 	if (status < 0)
5309a0bf528SMauro Carvalho Chehab 		goto error;
5319a0bf528SMauro Carvalho Chehab 
532cd7a67a4SMauro Carvalho Chehab 	state->m_current_power_mode = DRX_POWER_UP;
5339a0bf528SMauro Carvalho Chehab 
5349a0bf528SMauro Carvalho Chehab error:
5359a0bf528SMauro Carvalho Chehab 	if (status < 0)
5363a4398f5SMauro Carvalho Chehab 		pr_err("Error %d on %s\n", status, __func__);
5379a0bf528SMauro Carvalho Chehab 
5389a0bf528SMauro Carvalho Chehab 	return status;
5399a0bf528SMauro Carvalho Chehab }
5409a0bf528SMauro Carvalho Chehab 
5419a0bf528SMauro Carvalho Chehab 
5429a0bf528SMauro Carvalho Chehab static int init_state(struct drxk_state *state)
5439a0bf528SMauro Carvalho Chehab {
5449a0bf528SMauro Carvalho Chehab 	/*
5459a0bf528SMauro Carvalho Chehab 	 * FIXME: most (all?) of the values bellow should be moved into
5469a0bf528SMauro Carvalho Chehab 	 * struct drxk_config, as they are probably board-specific
5479a0bf528SMauro Carvalho Chehab 	 */
548cd7a67a4SMauro Carvalho Chehab 	u32 ul_vsb_if_agc_mode = DRXK_AGC_CTRL_AUTO;
549cd7a67a4SMauro Carvalho Chehab 	u32 ul_vsb_if_agc_output_level = 0;
550cd7a67a4SMauro Carvalho Chehab 	u32 ul_vsb_if_agc_min_level = 0;
551cd7a67a4SMauro Carvalho Chehab 	u32 ul_vsb_if_agc_max_level = 0x7FFF;
552cd7a67a4SMauro Carvalho Chehab 	u32 ul_vsb_if_agc_speed = 3;
5539a0bf528SMauro Carvalho Chehab 
554cd7a67a4SMauro Carvalho Chehab 	u32 ul_vsb_rf_agc_mode = DRXK_AGC_CTRL_AUTO;
555cd7a67a4SMauro Carvalho Chehab 	u32 ul_vsb_rf_agc_output_level = 0;
556cd7a67a4SMauro Carvalho Chehab 	u32 ul_vsb_rf_agc_min_level = 0;
557cd7a67a4SMauro Carvalho Chehab 	u32 ul_vsb_rf_agc_max_level = 0x7FFF;
558cd7a67a4SMauro Carvalho Chehab 	u32 ul_vsb_rf_agc_speed = 3;
559cd7a67a4SMauro Carvalho Chehab 	u32 ul_vsb_rf_agc_top = 9500;
560cd7a67a4SMauro Carvalho Chehab 	u32 ul_vsb_rf_agc_cut_off_current = 4000;
5619a0bf528SMauro Carvalho Chehab 
562cd7a67a4SMauro Carvalho Chehab 	u32 ul_atv_if_agc_mode = DRXK_AGC_CTRL_AUTO;
563cd7a67a4SMauro Carvalho Chehab 	u32 ul_atv_if_agc_output_level = 0;
564cd7a67a4SMauro Carvalho Chehab 	u32 ul_atv_if_agc_min_level = 0;
565cd7a67a4SMauro Carvalho Chehab 	u32 ul_atv_if_agc_max_level = 0;
566cd7a67a4SMauro Carvalho Chehab 	u32 ul_atv_if_agc_speed = 3;
5679a0bf528SMauro Carvalho Chehab 
568cd7a67a4SMauro Carvalho Chehab 	u32 ul_atv_rf_agc_mode = DRXK_AGC_CTRL_OFF;
569cd7a67a4SMauro Carvalho Chehab 	u32 ul_atv_rf_agc_output_level = 0;
570cd7a67a4SMauro Carvalho Chehab 	u32 ul_atv_rf_agc_min_level = 0;
571cd7a67a4SMauro Carvalho Chehab 	u32 ul_atv_rf_agc_max_level = 0;
572cd7a67a4SMauro Carvalho Chehab 	u32 ul_atv_rf_agc_top = 9500;
573cd7a67a4SMauro Carvalho Chehab 	u32 ul_atv_rf_agc_cut_off_current = 4000;
574cd7a67a4SMauro Carvalho Chehab 	u32 ul_atv_rf_agc_speed = 3;
5759a0bf528SMauro Carvalho Chehab 
5769a0bf528SMauro Carvalho Chehab 	u32 ulQual83 = DEFAULT_MER_83;
5779a0bf528SMauro Carvalho Chehab 	u32 ulQual93 = DEFAULT_MER_93;
5789a0bf528SMauro Carvalho Chehab 
579cd7a67a4SMauro Carvalho Chehab 	u32 ul_mpeg_lock_time_out = DEFAULT_DRXK_MPEG_LOCK_TIMEOUT;
580cd7a67a4SMauro Carvalho Chehab 	u32 ul_demod_lock_time_out = DEFAULT_DRXK_DEMOD_LOCK_TIMEOUT;
5819a0bf528SMauro Carvalho Chehab 
5829a0bf528SMauro Carvalho Chehab 	/* io_pad_cfg register (8 bit reg.) MSB bit is 1 (default value) */
5839a0bf528SMauro Carvalho Chehab 	/* io_pad_cfg_mode output mode is drive always */
5849a0bf528SMauro Carvalho Chehab 	/* io_pad_cfg_drive is set to power 2 (23 mA) */
585cd7a67a4SMauro Carvalho Chehab 	u32 ul_gpio_cfg = 0x0113;
586cd7a67a4SMauro Carvalho Chehab 	u32 ul_invert_ts_clock = 0;
587cd7a67a4SMauro Carvalho Chehab 	u32 ul_ts_data_strength = DRXK_MPEG_SERIAL_OUTPUT_PIN_DRIVE_STRENGTH;
588cd7a67a4SMauro Carvalho Chehab 	u32 ul_dvbt_bitrate = 50000000;
589cd7a67a4SMauro Carvalho Chehab 	u32 ul_dvbc_bitrate = DRXK_QAM_SYMBOLRATE_MAX * 8;
5909a0bf528SMauro Carvalho Chehab 
591cd7a67a4SMauro Carvalho Chehab 	u32 ul_insert_rs_byte = 0;
5929a0bf528SMauro Carvalho Chehab 
593cd7a67a4SMauro Carvalho Chehab 	u32 ul_rf_mirror = 1;
594cd7a67a4SMauro Carvalho Chehab 	u32 ul_power_down = 0;
5959a0bf528SMauro Carvalho Chehab 
5969a0bf528SMauro Carvalho Chehab 	dprintk(1, "\n");
5979a0bf528SMauro Carvalho Chehab 
598cd7a67a4SMauro Carvalho Chehab 	state->m_has_lna = false;
599cd7a67a4SMauro Carvalho Chehab 	state->m_has_dvbt = false;
600cd7a67a4SMauro Carvalho Chehab 	state->m_has_dvbc = false;
601cd7a67a4SMauro Carvalho Chehab 	state->m_has_atv = false;
602cd7a67a4SMauro Carvalho Chehab 	state->m_has_oob = false;
603cd7a67a4SMauro Carvalho Chehab 	state->m_has_audio = false;
6049a0bf528SMauro Carvalho Chehab 
605cd7a67a4SMauro Carvalho Chehab 	if (!state->m_chunk_size)
606cd7a67a4SMauro Carvalho Chehab 		state->m_chunk_size = 124;
6079a0bf528SMauro Carvalho Chehab 
608cd7a67a4SMauro Carvalho Chehab 	state->m_osc_clock_freq = 0;
609cd7a67a4SMauro Carvalho Chehab 	state->m_smart_ant_inverted = false;
610cd7a67a4SMauro Carvalho Chehab 	state->m_b_p_down_open_bridge = false;
6119a0bf528SMauro Carvalho Chehab 
6129a0bf528SMauro Carvalho Chehab 	/* real system clock frequency in kHz */
613cd7a67a4SMauro Carvalho Chehab 	state->m_sys_clock_freq = 151875;
6149a0bf528SMauro Carvalho Chehab 	/* Timing div, 250ns/Psys */
6159a0bf528SMauro Carvalho Chehab 	/* Timing div, = (delay (nano seconds) * sysclk (kHz))/ 1000 */
616cd7a67a4SMauro Carvalho Chehab 	state->m_hi_cfg_timing_div = ((state->m_sys_clock_freq / 1000) *
6179a0bf528SMauro Carvalho Chehab 				   HI_I2C_DELAY) / 1000;
6189a0bf528SMauro Carvalho Chehab 	/* Clipping */
619cd7a67a4SMauro Carvalho Chehab 	if (state->m_hi_cfg_timing_div > SIO_HI_RA_RAM_PAR_2_CFG_DIV__M)
620cd7a67a4SMauro Carvalho Chehab 		state->m_hi_cfg_timing_div = SIO_HI_RA_RAM_PAR_2_CFG_DIV__M;
621cd7a67a4SMauro Carvalho Chehab 	state->m_hi_cfg_wake_up_key = (state->demod_address << 1);
6229a0bf528SMauro Carvalho Chehab 	/* port/bridge/power down ctrl */
623cd7a67a4SMauro Carvalho Chehab 	state->m_hi_cfg_ctrl = SIO_HI_RA_RAM_PAR_5_CFG_SLV0_SLAVE;
6249a0bf528SMauro Carvalho Chehab 
625cd7a67a4SMauro Carvalho Chehab 	state->m_b_power_down = (ul_power_down != 0);
6269a0bf528SMauro Carvalho Chehab 
627cd7a67a4SMauro Carvalho Chehab 	state->m_drxk_a3_patch_code = false;
6289a0bf528SMauro Carvalho Chehab 
6299a0bf528SMauro Carvalho Chehab 	/* Init AGC and PGA parameters */
6309a0bf528SMauro Carvalho Chehab 	/* VSB IF */
631cd7a67a4SMauro Carvalho Chehab 	state->m_vsb_if_agc_cfg.ctrl_mode = (ul_vsb_if_agc_mode);
632cd7a67a4SMauro Carvalho Chehab 	state->m_vsb_if_agc_cfg.output_level = (ul_vsb_if_agc_output_level);
633cd7a67a4SMauro Carvalho Chehab 	state->m_vsb_if_agc_cfg.min_output_level = (ul_vsb_if_agc_min_level);
634cd7a67a4SMauro Carvalho Chehab 	state->m_vsb_if_agc_cfg.max_output_level = (ul_vsb_if_agc_max_level);
635cd7a67a4SMauro Carvalho Chehab 	state->m_vsb_if_agc_cfg.speed = (ul_vsb_if_agc_speed);
636cd7a67a4SMauro Carvalho Chehab 	state->m_vsb_pga_cfg = 140;
6379a0bf528SMauro Carvalho Chehab 
6389a0bf528SMauro Carvalho Chehab 	/* VSB RF */
639cd7a67a4SMauro Carvalho Chehab 	state->m_vsb_rf_agc_cfg.ctrl_mode = (ul_vsb_rf_agc_mode);
640cd7a67a4SMauro Carvalho Chehab 	state->m_vsb_rf_agc_cfg.output_level = (ul_vsb_rf_agc_output_level);
641cd7a67a4SMauro Carvalho Chehab 	state->m_vsb_rf_agc_cfg.min_output_level = (ul_vsb_rf_agc_min_level);
642cd7a67a4SMauro Carvalho Chehab 	state->m_vsb_rf_agc_cfg.max_output_level = (ul_vsb_rf_agc_max_level);
643cd7a67a4SMauro Carvalho Chehab 	state->m_vsb_rf_agc_cfg.speed = (ul_vsb_rf_agc_speed);
644cd7a67a4SMauro Carvalho Chehab 	state->m_vsb_rf_agc_cfg.top = (ul_vsb_rf_agc_top);
645cd7a67a4SMauro Carvalho Chehab 	state->m_vsb_rf_agc_cfg.cut_off_current = (ul_vsb_rf_agc_cut_off_current);
646cd7a67a4SMauro Carvalho Chehab 	state->m_vsb_pre_saw_cfg.reference = 0x07;
647cd7a67a4SMauro Carvalho Chehab 	state->m_vsb_pre_saw_cfg.use_pre_saw = true;
6489a0bf528SMauro Carvalho Chehab 
6499a0bf528SMauro Carvalho Chehab 	state->m_Quality83percent = DEFAULT_MER_83;
6509a0bf528SMauro Carvalho Chehab 	state->m_Quality93percent = DEFAULT_MER_93;
6519a0bf528SMauro Carvalho Chehab 	if (ulQual93 <= 500 && ulQual83 < ulQual93) {
6529a0bf528SMauro Carvalho Chehab 		state->m_Quality83percent = ulQual83;
6539a0bf528SMauro Carvalho Chehab 		state->m_Quality93percent = ulQual93;
6549a0bf528SMauro Carvalho Chehab 	}
6559a0bf528SMauro Carvalho Chehab 
6569a0bf528SMauro Carvalho Chehab 	/* ATV IF */
657cd7a67a4SMauro Carvalho Chehab 	state->m_atv_if_agc_cfg.ctrl_mode = (ul_atv_if_agc_mode);
658cd7a67a4SMauro Carvalho Chehab 	state->m_atv_if_agc_cfg.output_level = (ul_atv_if_agc_output_level);
659cd7a67a4SMauro Carvalho Chehab 	state->m_atv_if_agc_cfg.min_output_level = (ul_atv_if_agc_min_level);
660cd7a67a4SMauro Carvalho Chehab 	state->m_atv_if_agc_cfg.max_output_level = (ul_atv_if_agc_max_level);
661cd7a67a4SMauro Carvalho Chehab 	state->m_atv_if_agc_cfg.speed = (ul_atv_if_agc_speed);
6629a0bf528SMauro Carvalho Chehab 
6639a0bf528SMauro Carvalho Chehab 	/* ATV RF */
664cd7a67a4SMauro Carvalho Chehab 	state->m_atv_rf_agc_cfg.ctrl_mode = (ul_atv_rf_agc_mode);
665cd7a67a4SMauro Carvalho Chehab 	state->m_atv_rf_agc_cfg.output_level = (ul_atv_rf_agc_output_level);
666cd7a67a4SMauro Carvalho Chehab 	state->m_atv_rf_agc_cfg.min_output_level = (ul_atv_rf_agc_min_level);
667cd7a67a4SMauro Carvalho Chehab 	state->m_atv_rf_agc_cfg.max_output_level = (ul_atv_rf_agc_max_level);
668cd7a67a4SMauro Carvalho Chehab 	state->m_atv_rf_agc_cfg.speed = (ul_atv_rf_agc_speed);
669cd7a67a4SMauro Carvalho Chehab 	state->m_atv_rf_agc_cfg.top = (ul_atv_rf_agc_top);
670cd7a67a4SMauro Carvalho Chehab 	state->m_atv_rf_agc_cfg.cut_off_current = (ul_atv_rf_agc_cut_off_current);
671cd7a67a4SMauro Carvalho Chehab 	state->m_atv_pre_saw_cfg.reference = 0x04;
672cd7a67a4SMauro Carvalho Chehab 	state->m_atv_pre_saw_cfg.use_pre_saw = true;
6739a0bf528SMauro Carvalho Chehab 
6749a0bf528SMauro Carvalho Chehab 
6759a0bf528SMauro Carvalho Chehab 	/* DVBT RF */
676cd7a67a4SMauro Carvalho Chehab 	state->m_dvbt_rf_agc_cfg.ctrl_mode = DRXK_AGC_CTRL_OFF;
677cd7a67a4SMauro Carvalho Chehab 	state->m_dvbt_rf_agc_cfg.output_level = 0;
678cd7a67a4SMauro Carvalho Chehab 	state->m_dvbt_rf_agc_cfg.min_output_level = 0;
679cd7a67a4SMauro Carvalho Chehab 	state->m_dvbt_rf_agc_cfg.max_output_level = 0xFFFF;
680cd7a67a4SMauro Carvalho Chehab 	state->m_dvbt_rf_agc_cfg.top = 0x2100;
681cd7a67a4SMauro Carvalho Chehab 	state->m_dvbt_rf_agc_cfg.cut_off_current = 4000;
682cd7a67a4SMauro Carvalho Chehab 	state->m_dvbt_rf_agc_cfg.speed = 1;
6839a0bf528SMauro Carvalho Chehab 
6849a0bf528SMauro Carvalho Chehab 
6859a0bf528SMauro Carvalho Chehab 	/* DVBT IF */
686cd7a67a4SMauro Carvalho Chehab 	state->m_dvbt_if_agc_cfg.ctrl_mode = DRXK_AGC_CTRL_AUTO;
687cd7a67a4SMauro Carvalho Chehab 	state->m_dvbt_if_agc_cfg.output_level = 0;
688cd7a67a4SMauro Carvalho Chehab 	state->m_dvbt_if_agc_cfg.min_output_level = 0;
689cd7a67a4SMauro Carvalho Chehab 	state->m_dvbt_if_agc_cfg.max_output_level = 9000;
690cd7a67a4SMauro Carvalho Chehab 	state->m_dvbt_if_agc_cfg.top = 13424;
691cd7a67a4SMauro Carvalho Chehab 	state->m_dvbt_if_agc_cfg.cut_off_current = 0;
692cd7a67a4SMauro Carvalho Chehab 	state->m_dvbt_if_agc_cfg.speed = 3;
693cd7a67a4SMauro Carvalho Chehab 	state->m_dvbt_if_agc_cfg.fast_clip_ctrl_delay = 30;
694cd7a67a4SMauro Carvalho Chehab 	state->m_dvbt_if_agc_cfg.ingain_tgt_max = 30000;
6959a0bf528SMauro Carvalho Chehab 	/* state->m_dvbtPgaCfg = 140; */
6969a0bf528SMauro Carvalho Chehab 
697cd7a67a4SMauro Carvalho Chehab 	state->m_dvbt_pre_saw_cfg.reference = 4;
698cd7a67a4SMauro Carvalho Chehab 	state->m_dvbt_pre_saw_cfg.use_pre_saw = false;
6999a0bf528SMauro Carvalho Chehab 
7009a0bf528SMauro Carvalho Chehab 	/* QAM RF */
701cd7a67a4SMauro Carvalho Chehab 	state->m_qam_rf_agc_cfg.ctrl_mode = DRXK_AGC_CTRL_OFF;
702cd7a67a4SMauro Carvalho Chehab 	state->m_qam_rf_agc_cfg.output_level = 0;
703cd7a67a4SMauro Carvalho Chehab 	state->m_qam_rf_agc_cfg.min_output_level = 6023;
704cd7a67a4SMauro Carvalho Chehab 	state->m_qam_rf_agc_cfg.max_output_level = 27000;
705cd7a67a4SMauro Carvalho Chehab 	state->m_qam_rf_agc_cfg.top = 0x2380;
706cd7a67a4SMauro Carvalho Chehab 	state->m_qam_rf_agc_cfg.cut_off_current = 4000;
707cd7a67a4SMauro Carvalho Chehab 	state->m_qam_rf_agc_cfg.speed = 3;
7089a0bf528SMauro Carvalho Chehab 
7099a0bf528SMauro Carvalho Chehab 	/* QAM IF */
710cd7a67a4SMauro Carvalho Chehab 	state->m_qam_if_agc_cfg.ctrl_mode = DRXK_AGC_CTRL_AUTO;
711cd7a67a4SMauro Carvalho Chehab 	state->m_qam_if_agc_cfg.output_level = 0;
712cd7a67a4SMauro Carvalho Chehab 	state->m_qam_if_agc_cfg.min_output_level = 0;
713cd7a67a4SMauro Carvalho Chehab 	state->m_qam_if_agc_cfg.max_output_level = 9000;
714cd7a67a4SMauro Carvalho Chehab 	state->m_qam_if_agc_cfg.top = 0x0511;
715cd7a67a4SMauro Carvalho Chehab 	state->m_qam_if_agc_cfg.cut_off_current = 0;
716cd7a67a4SMauro Carvalho Chehab 	state->m_qam_if_agc_cfg.speed = 3;
717cd7a67a4SMauro Carvalho Chehab 	state->m_qam_if_agc_cfg.ingain_tgt_max = 5119;
718cd7a67a4SMauro Carvalho Chehab 	state->m_qam_if_agc_cfg.fast_clip_ctrl_delay = 50;
7199a0bf528SMauro Carvalho Chehab 
720cd7a67a4SMauro Carvalho Chehab 	state->m_qam_pga_cfg = 140;
721cd7a67a4SMauro Carvalho Chehab 	state->m_qam_pre_saw_cfg.reference = 4;
722cd7a67a4SMauro Carvalho Chehab 	state->m_qam_pre_saw_cfg.use_pre_saw = false;
7239a0bf528SMauro Carvalho Chehab 
724cd7a67a4SMauro Carvalho Chehab 	state->m_operation_mode = OM_NONE;
725cd7a67a4SMauro Carvalho Chehab 	state->m_drxk_state = DRXK_UNINITIALIZED;
7269a0bf528SMauro Carvalho Chehab 
7279a0bf528SMauro Carvalho Chehab 	/* MPEG output configuration */
728cd7a67a4SMauro Carvalho Chehab 	state->m_enable_mpeg_output = true;	/* If TRUE; enable MPEG ouput */
729cd7a67a4SMauro Carvalho Chehab 	state->m_insert_rs_byte = false;	/* If TRUE; insert RS byte */
730cd7a67a4SMauro Carvalho Chehab 	state->m_invert_data = false;	/* If TRUE; invert DATA signals */
731cd7a67a4SMauro Carvalho Chehab 	state->m_invert_err = false;	/* If TRUE; invert ERR signal */
732cd7a67a4SMauro Carvalho Chehab 	state->m_invert_str = false;	/* If TRUE; invert STR signals */
733cd7a67a4SMauro Carvalho Chehab 	state->m_invert_val = false;	/* If TRUE; invert VAL signals */
734cd7a67a4SMauro Carvalho Chehab 	state->m_invert_clk = (ul_invert_ts_clock != 0);	/* If TRUE; invert CLK signals */
7359a0bf528SMauro Carvalho Chehab 
7369a0bf528SMauro Carvalho Chehab 	/* If TRUE; static MPEG clockrate will be used;
7379a0bf528SMauro Carvalho Chehab 	   otherwise clockrate will adapt to the bitrate of the TS */
7389a0bf528SMauro Carvalho Chehab 
739cd7a67a4SMauro Carvalho Chehab 	state->m_dvbt_bitrate = ul_dvbt_bitrate;
740cd7a67a4SMauro Carvalho Chehab 	state->m_dvbc_bitrate = ul_dvbc_bitrate;
7419a0bf528SMauro Carvalho Chehab 
742cd7a67a4SMauro Carvalho Chehab 	state->m_ts_data_strength = (ul_ts_data_strength & 0x07);
7439a0bf528SMauro Carvalho Chehab 
7449a0bf528SMauro Carvalho Chehab 	/* Maximum bitrate in b/s in case static clockrate is selected */
745cd7a67a4SMauro Carvalho Chehab 	state->m_mpeg_ts_static_bitrate = 19392658;
746cd7a67a4SMauro Carvalho Chehab 	state->m_disable_te_ihandling = false;
7479a0bf528SMauro Carvalho Chehab 
748cd7a67a4SMauro Carvalho Chehab 	if (ul_insert_rs_byte)
749cd7a67a4SMauro Carvalho Chehab 		state->m_insert_rs_byte = true;
7509a0bf528SMauro Carvalho Chehab 
751cd7a67a4SMauro Carvalho Chehab 	state->m_mpeg_lock_time_out = DEFAULT_DRXK_MPEG_LOCK_TIMEOUT;
752cd7a67a4SMauro Carvalho Chehab 	if (ul_mpeg_lock_time_out < 10000)
753cd7a67a4SMauro Carvalho Chehab 		state->m_mpeg_lock_time_out = ul_mpeg_lock_time_out;
754cd7a67a4SMauro Carvalho Chehab 	state->m_demod_lock_time_out = DEFAULT_DRXK_DEMOD_LOCK_TIMEOUT;
755cd7a67a4SMauro Carvalho Chehab 	if (ul_demod_lock_time_out < 10000)
756cd7a67a4SMauro Carvalho Chehab 		state->m_demod_lock_time_out = ul_demod_lock_time_out;
7579a0bf528SMauro Carvalho Chehab 
7589a0bf528SMauro Carvalho Chehab 	/* QAM defaults */
759cd7a67a4SMauro Carvalho Chehab 	state->m_constellation = DRX_CONSTELLATION_AUTO;
760cd7a67a4SMauro Carvalho Chehab 	state->m_qam_interleave_mode = DRXK_QAM_I12_J17;
761cd7a67a4SMauro Carvalho Chehab 	state->m_fec_rs_plen = 204 * 8;	/* fecRsPlen  annex A */
762cd7a67a4SMauro Carvalho Chehab 	state->m_fec_rs_prescale = 1;
7639a0bf528SMauro Carvalho Chehab 
764cd7a67a4SMauro Carvalho Chehab 	state->m_sqi_speed = DRXK_DVBT_SQI_SPEED_MEDIUM;
765cd7a67a4SMauro Carvalho Chehab 	state->m_agcfast_clip_ctrl_delay = 0;
7669a0bf528SMauro Carvalho Chehab 
767cd7a67a4SMauro Carvalho Chehab 	state->m_gpio_cfg = (ul_gpio_cfg);
7689a0bf528SMauro Carvalho Chehab 
769cd7a67a4SMauro Carvalho Chehab 	state->m_b_power_down = false;
770cd7a67a4SMauro Carvalho Chehab 	state->m_current_power_mode = DRX_POWER_DOWN;
7719a0bf528SMauro Carvalho Chehab 
772cd7a67a4SMauro Carvalho Chehab 	state->m_rfmirror = (ul_rf_mirror == 0);
773cd7a67a4SMauro Carvalho Chehab 	state->m_if_agc_pol = false;
7749a0bf528SMauro Carvalho Chehab 	return 0;
7759a0bf528SMauro Carvalho Chehab }
7769a0bf528SMauro Carvalho Chehab 
777cd7a67a4SMauro Carvalho Chehab static int drxx_open(struct drxk_state *state)
7789a0bf528SMauro Carvalho Chehab {
7799a0bf528SMauro Carvalho Chehab 	int status = 0;
7809a0bf528SMauro Carvalho Chehab 	u32 jtag = 0;
7819a0bf528SMauro Carvalho Chehab 	u16 bid = 0;
7829a0bf528SMauro Carvalho Chehab 	u16 key = 0;
7839a0bf528SMauro Carvalho Chehab 
7849a0bf528SMauro Carvalho Chehab 	dprintk(1, "\n");
7859a0bf528SMauro Carvalho Chehab 	/* stop lock indicator process */
7869a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_GPIO__A, SCU_RAM_GPIO_HW_LOCK_IND_DISABLE);
7879a0bf528SMauro Carvalho Chehab 	if (status < 0)
7889a0bf528SMauro Carvalho Chehab 		goto error;
7899a0bf528SMauro Carvalho Chehab 	/* Check device id */
7909a0bf528SMauro Carvalho Chehab 	status = read16(state, SIO_TOP_COMM_KEY__A, &key);
7919a0bf528SMauro Carvalho Chehab 	if (status < 0)
7929a0bf528SMauro Carvalho Chehab 		goto error;
7939a0bf528SMauro Carvalho Chehab 	status = write16(state, SIO_TOP_COMM_KEY__A, SIO_TOP_COMM_KEY_KEY);
7949a0bf528SMauro Carvalho Chehab 	if (status < 0)
7959a0bf528SMauro Carvalho Chehab 		goto error;
7969a0bf528SMauro Carvalho Chehab 	status = read32(state, SIO_TOP_JTAGID_LO__A, &jtag);
7979a0bf528SMauro Carvalho Chehab 	if (status < 0)
7989a0bf528SMauro Carvalho Chehab 		goto error;
7999a0bf528SMauro Carvalho Chehab 	status = read16(state, SIO_PDR_UIO_IN_HI__A, &bid);
8009a0bf528SMauro Carvalho Chehab 	if (status < 0)
8019a0bf528SMauro Carvalho Chehab 		goto error;
8029a0bf528SMauro Carvalho Chehab 	status = write16(state, SIO_TOP_COMM_KEY__A, key);
8039a0bf528SMauro Carvalho Chehab error:
8049a0bf528SMauro Carvalho Chehab 	if (status < 0)
8053a4398f5SMauro Carvalho Chehab 		pr_err("Error %d on %s\n", status, __func__);
8069a0bf528SMauro Carvalho Chehab 	return status;
8079a0bf528SMauro Carvalho Chehab }
8089a0bf528SMauro Carvalho Chehab 
809cd7a67a4SMauro Carvalho Chehab static int get_device_capabilities(struct drxk_state *state)
8109a0bf528SMauro Carvalho Chehab {
811cd7a67a4SMauro Carvalho Chehab 	u16 sio_pdr_ohw_cfg = 0;
812cd7a67a4SMauro Carvalho Chehab 	u32 sio_top_jtagid_lo = 0;
8139a0bf528SMauro Carvalho Chehab 	int status;
8149a0bf528SMauro Carvalho Chehab 	const char *spin = "";
8159a0bf528SMauro Carvalho Chehab 
8169a0bf528SMauro Carvalho Chehab 	dprintk(1, "\n");
8179a0bf528SMauro Carvalho Chehab 
8189a0bf528SMauro Carvalho Chehab 	/* driver 0.9.0 */
8199a0bf528SMauro Carvalho Chehab 	/* stop lock indicator process */
8209a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_GPIO__A, SCU_RAM_GPIO_HW_LOCK_IND_DISABLE);
8219a0bf528SMauro Carvalho Chehab 	if (status < 0)
8229a0bf528SMauro Carvalho Chehab 		goto error;
8238418366dSMartin Blumenstingl 	status = write16(state, SIO_TOP_COMM_KEY__A, SIO_TOP_COMM_KEY_KEY);
8249a0bf528SMauro Carvalho Chehab 	if (status < 0)
8259a0bf528SMauro Carvalho Chehab 		goto error;
826cd7a67a4SMauro Carvalho Chehab 	status = read16(state, SIO_PDR_OHW_CFG__A, &sio_pdr_ohw_cfg);
8279a0bf528SMauro Carvalho Chehab 	if (status < 0)
8289a0bf528SMauro Carvalho Chehab 		goto error;
8299a0bf528SMauro Carvalho Chehab 	status = write16(state, SIO_TOP_COMM_KEY__A, 0x0000);
8309a0bf528SMauro Carvalho Chehab 	if (status < 0)
8319a0bf528SMauro Carvalho Chehab 		goto error;
8329a0bf528SMauro Carvalho Chehab 
833cd7a67a4SMauro Carvalho Chehab 	switch ((sio_pdr_ohw_cfg & SIO_PDR_OHW_CFG_FREF_SEL__M)) {
8349a0bf528SMauro Carvalho Chehab 	case 0:
8359a0bf528SMauro Carvalho Chehab 		/* ignore (bypass ?) */
8369a0bf528SMauro Carvalho Chehab 		break;
8379a0bf528SMauro Carvalho Chehab 	case 1:
8389a0bf528SMauro Carvalho Chehab 		/* 27 MHz */
839cd7a67a4SMauro Carvalho Chehab 		state->m_osc_clock_freq = 27000;
8409a0bf528SMauro Carvalho Chehab 		break;
8419a0bf528SMauro Carvalho Chehab 	case 2:
8429a0bf528SMauro Carvalho Chehab 		/* 20.25 MHz */
843cd7a67a4SMauro Carvalho Chehab 		state->m_osc_clock_freq = 20250;
8449a0bf528SMauro Carvalho Chehab 		break;
8459a0bf528SMauro Carvalho Chehab 	case 3:
8469a0bf528SMauro Carvalho Chehab 		/* 4 MHz */
847cd7a67a4SMauro Carvalho Chehab 		state->m_osc_clock_freq = 20250;
8489a0bf528SMauro Carvalho Chehab 		break;
8499a0bf528SMauro Carvalho Chehab 	default:
8503a4398f5SMauro Carvalho Chehab 		pr_err("Clock Frequency is unknown\n");
8519a0bf528SMauro Carvalho Chehab 		return -EINVAL;
8529a0bf528SMauro Carvalho Chehab 	}
8539a0bf528SMauro Carvalho Chehab 	/*
8549a0bf528SMauro Carvalho Chehab 		Determine device capabilities
8559a0bf528SMauro Carvalho Chehab 		Based on pinning v14
8569a0bf528SMauro Carvalho Chehab 		*/
857cd7a67a4SMauro Carvalho Chehab 	status = read32(state, SIO_TOP_JTAGID_LO__A, &sio_top_jtagid_lo);
8589a0bf528SMauro Carvalho Chehab 	if (status < 0)
8599a0bf528SMauro Carvalho Chehab 		goto error;
8609a0bf528SMauro Carvalho Chehab 
8613a4398f5SMauro Carvalho Chehab 	pr_info("status = 0x%08x\n", sio_top_jtagid_lo);
8629a0bf528SMauro Carvalho Chehab 
8639a0bf528SMauro Carvalho Chehab 	/* driver 0.9.0 */
864cd7a67a4SMauro Carvalho Chehab 	switch ((sio_top_jtagid_lo >> 29) & 0xF) {
8659a0bf528SMauro Carvalho Chehab 	case 0:
866cd7a67a4SMauro Carvalho Chehab 		state->m_device_spin = DRXK_SPIN_A1;
8679a0bf528SMauro Carvalho Chehab 		spin = "A1";
8689a0bf528SMauro Carvalho Chehab 		break;
8699a0bf528SMauro Carvalho Chehab 	case 2:
870cd7a67a4SMauro Carvalho Chehab 		state->m_device_spin = DRXK_SPIN_A2;
8719a0bf528SMauro Carvalho Chehab 		spin = "A2";
8729a0bf528SMauro Carvalho Chehab 		break;
8739a0bf528SMauro Carvalho Chehab 	case 3:
874cd7a67a4SMauro Carvalho Chehab 		state->m_device_spin = DRXK_SPIN_A3;
8759a0bf528SMauro Carvalho Chehab 		spin = "A3";
8769a0bf528SMauro Carvalho Chehab 		break;
8779a0bf528SMauro Carvalho Chehab 	default:
878cd7a67a4SMauro Carvalho Chehab 		state->m_device_spin = DRXK_SPIN_UNKNOWN;
8799a0bf528SMauro Carvalho Chehab 		status = -EINVAL;
8803a4398f5SMauro Carvalho Chehab 		pr_err("Spin %d unknown\n", (sio_top_jtagid_lo >> 29) & 0xF);
8819a0bf528SMauro Carvalho Chehab 		goto error2;
8829a0bf528SMauro Carvalho Chehab 	}
883cd7a67a4SMauro Carvalho Chehab 	switch ((sio_top_jtagid_lo >> 12) & 0xFF) {
8849a0bf528SMauro Carvalho Chehab 	case 0x13:
8859a0bf528SMauro Carvalho Chehab 		/* typeId = DRX3913K_TYPE_ID */
886cd7a67a4SMauro Carvalho Chehab 		state->m_has_lna = false;
887cd7a67a4SMauro Carvalho Chehab 		state->m_has_oob = false;
888cd7a67a4SMauro Carvalho Chehab 		state->m_has_atv = false;
889cd7a67a4SMauro Carvalho Chehab 		state->m_has_audio = false;
890cd7a67a4SMauro Carvalho Chehab 		state->m_has_dvbt = true;
891cd7a67a4SMauro Carvalho Chehab 		state->m_has_dvbc = true;
892cd7a67a4SMauro Carvalho Chehab 		state->m_has_sawsw = true;
893cd7a67a4SMauro Carvalho Chehab 		state->m_has_gpio2 = false;
894cd7a67a4SMauro Carvalho Chehab 		state->m_has_gpio1 = false;
895cd7a67a4SMauro Carvalho Chehab 		state->m_has_irqn = false;
8969a0bf528SMauro Carvalho Chehab 		break;
8979a0bf528SMauro Carvalho Chehab 	case 0x15:
8989a0bf528SMauro Carvalho Chehab 		/* typeId = DRX3915K_TYPE_ID */
899cd7a67a4SMauro Carvalho Chehab 		state->m_has_lna = false;
900cd7a67a4SMauro Carvalho Chehab 		state->m_has_oob = false;
901cd7a67a4SMauro Carvalho Chehab 		state->m_has_atv = true;
902cd7a67a4SMauro Carvalho Chehab 		state->m_has_audio = false;
903cd7a67a4SMauro Carvalho Chehab 		state->m_has_dvbt = true;
904cd7a67a4SMauro Carvalho Chehab 		state->m_has_dvbc = false;
905cd7a67a4SMauro Carvalho Chehab 		state->m_has_sawsw = true;
906cd7a67a4SMauro Carvalho Chehab 		state->m_has_gpio2 = true;
907cd7a67a4SMauro Carvalho Chehab 		state->m_has_gpio1 = true;
908cd7a67a4SMauro Carvalho Chehab 		state->m_has_irqn = false;
9099a0bf528SMauro Carvalho Chehab 		break;
9109a0bf528SMauro Carvalho Chehab 	case 0x16:
9119a0bf528SMauro Carvalho Chehab 		/* typeId = DRX3916K_TYPE_ID */
912cd7a67a4SMauro Carvalho Chehab 		state->m_has_lna = false;
913cd7a67a4SMauro Carvalho Chehab 		state->m_has_oob = false;
914cd7a67a4SMauro Carvalho Chehab 		state->m_has_atv = true;
915cd7a67a4SMauro Carvalho Chehab 		state->m_has_audio = false;
916cd7a67a4SMauro Carvalho Chehab 		state->m_has_dvbt = true;
917cd7a67a4SMauro Carvalho Chehab 		state->m_has_dvbc = false;
918cd7a67a4SMauro Carvalho Chehab 		state->m_has_sawsw = true;
919cd7a67a4SMauro Carvalho Chehab 		state->m_has_gpio2 = true;
920cd7a67a4SMauro Carvalho Chehab 		state->m_has_gpio1 = true;
921cd7a67a4SMauro Carvalho Chehab 		state->m_has_irqn = false;
9229a0bf528SMauro Carvalho Chehab 		break;
9239a0bf528SMauro Carvalho Chehab 	case 0x18:
9249a0bf528SMauro Carvalho Chehab 		/* typeId = DRX3918K_TYPE_ID */
925cd7a67a4SMauro Carvalho Chehab 		state->m_has_lna = false;
926cd7a67a4SMauro Carvalho Chehab 		state->m_has_oob = false;
927cd7a67a4SMauro Carvalho Chehab 		state->m_has_atv = true;
928cd7a67a4SMauro Carvalho Chehab 		state->m_has_audio = true;
929cd7a67a4SMauro Carvalho Chehab 		state->m_has_dvbt = true;
930cd7a67a4SMauro Carvalho Chehab 		state->m_has_dvbc = false;
931cd7a67a4SMauro Carvalho Chehab 		state->m_has_sawsw = true;
932cd7a67a4SMauro Carvalho Chehab 		state->m_has_gpio2 = true;
933cd7a67a4SMauro Carvalho Chehab 		state->m_has_gpio1 = true;
934cd7a67a4SMauro Carvalho Chehab 		state->m_has_irqn = false;
9359a0bf528SMauro Carvalho Chehab 		break;
9369a0bf528SMauro Carvalho Chehab 	case 0x21:
9379a0bf528SMauro Carvalho Chehab 		/* typeId = DRX3921K_TYPE_ID */
938cd7a67a4SMauro Carvalho Chehab 		state->m_has_lna = false;
939cd7a67a4SMauro Carvalho Chehab 		state->m_has_oob = false;
940cd7a67a4SMauro Carvalho Chehab 		state->m_has_atv = true;
941cd7a67a4SMauro Carvalho Chehab 		state->m_has_audio = true;
942cd7a67a4SMauro Carvalho Chehab 		state->m_has_dvbt = true;
943cd7a67a4SMauro Carvalho Chehab 		state->m_has_dvbc = true;
944cd7a67a4SMauro Carvalho Chehab 		state->m_has_sawsw = true;
945cd7a67a4SMauro Carvalho Chehab 		state->m_has_gpio2 = true;
946cd7a67a4SMauro Carvalho Chehab 		state->m_has_gpio1 = true;
947cd7a67a4SMauro Carvalho Chehab 		state->m_has_irqn = false;
9489a0bf528SMauro Carvalho Chehab 		break;
9499a0bf528SMauro Carvalho Chehab 	case 0x23:
9509a0bf528SMauro Carvalho Chehab 		/* typeId = DRX3923K_TYPE_ID */
951cd7a67a4SMauro Carvalho Chehab 		state->m_has_lna = false;
952cd7a67a4SMauro Carvalho Chehab 		state->m_has_oob = false;
953cd7a67a4SMauro Carvalho Chehab 		state->m_has_atv = true;
954cd7a67a4SMauro Carvalho Chehab 		state->m_has_audio = true;
955cd7a67a4SMauro Carvalho Chehab 		state->m_has_dvbt = true;
956cd7a67a4SMauro Carvalho Chehab 		state->m_has_dvbc = true;
957cd7a67a4SMauro Carvalho Chehab 		state->m_has_sawsw = true;
958cd7a67a4SMauro Carvalho Chehab 		state->m_has_gpio2 = true;
959cd7a67a4SMauro Carvalho Chehab 		state->m_has_gpio1 = true;
960cd7a67a4SMauro Carvalho Chehab 		state->m_has_irqn = false;
9619a0bf528SMauro Carvalho Chehab 		break;
9629a0bf528SMauro Carvalho Chehab 	case 0x25:
9639a0bf528SMauro Carvalho Chehab 		/* typeId = DRX3925K_TYPE_ID */
964cd7a67a4SMauro Carvalho Chehab 		state->m_has_lna = false;
965cd7a67a4SMauro Carvalho Chehab 		state->m_has_oob = false;
966cd7a67a4SMauro Carvalho Chehab 		state->m_has_atv = true;
967cd7a67a4SMauro Carvalho Chehab 		state->m_has_audio = true;
968cd7a67a4SMauro Carvalho Chehab 		state->m_has_dvbt = true;
969cd7a67a4SMauro Carvalho Chehab 		state->m_has_dvbc = true;
970cd7a67a4SMauro Carvalho Chehab 		state->m_has_sawsw = true;
971cd7a67a4SMauro Carvalho Chehab 		state->m_has_gpio2 = true;
972cd7a67a4SMauro Carvalho Chehab 		state->m_has_gpio1 = true;
973cd7a67a4SMauro Carvalho Chehab 		state->m_has_irqn = false;
9749a0bf528SMauro Carvalho Chehab 		break;
9759a0bf528SMauro Carvalho Chehab 	case 0x26:
9769a0bf528SMauro Carvalho Chehab 		/* typeId = DRX3926K_TYPE_ID */
977cd7a67a4SMauro Carvalho Chehab 		state->m_has_lna = false;
978cd7a67a4SMauro Carvalho Chehab 		state->m_has_oob = false;
979cd7a67a4SMauro Carvalho Chehab 		state->m_has_atv = true;
980cd7a67a4SMauro Carvalho Chehab 		state->m_has_audio = false;
981cd7a67a4SMauro Carvalho Chehab 		state->m_has_dvbt = true;
982cd7a67a4SMauro Carvalho Chehab 		state->m_has_dvbc = true;
983cd7a67a4SMauro Carvalho Chehab 		state->m_has_sawsw = true;
984cd7a67a4SMauro Carvalho Chehab 		state->m_has_gpio2 = true;
985cd7a67a4SMauro Carvalho Chehab 		state->m_has_gpio1 = true;
986cd7a67a4SMauro Carvalho Chehab 		state->m_has_irqn = false;
9879a0bf528SMauro Carvalho Chehab 		break;
9889a0bf528SMauro Carvalho Chehab 	default:
9893a4398f5SMauro Carvalho Chehab 		pr_err("DeviceID 0x%02x not supported\n",
990cd7a67a4SMauro Carvalho Chehab 			((sio_top_jtagid_lo >> 12) & 0xFF));
9919a0bf528SMauro Carvalho Chehab 		status = -EINVAL;
9929a0bf528SMauro Carvalho Chehab 		goto error2;
9939a0bf528SMauro Carvalho Chehab 	}
9949a0bf528SMauro Carvalho Chehab 
9953a4398f5SMauro Carvalho Chehab 	pr_info("detected a drx-39%02xk, spin %s, xtal %d.%03d MHz\n",
996cd7a67a4SMauro Carvalho Chehab 	       ((sio_top_jtagid_lo >> 12) & 0xFF), spin,
997cd7a67a4SMauro Carvalho Chehab 	       state->m_osc_clock_freq / 1000,
998cd7a67a4SMauro Carvalho Chehab 	       state->m_osc_clock_freq % 1000);
9999a0bf528SMauro Carvalho Chehab 
10009a0bf528SMauro Carvalho Chehab error:
10019a0bf528SMauro Carvalho Chehab 	if (status < 0)
10023a4398f5SMauro Carvalho Chehab 		pr_err("Error %d on %s\n", status, __func__);
10039a0bf528SMauro Carvalho Chehab 
10049a0bf528SMauro Carvalho Chehab error2:
10059a0bf528SMauro Carvalho Chehab 	return status;
10069a0bf528SMauro Carvalho Chehab }
10079a0bf528SMauro Carvalho Chehab 
1008cd7a67a4SMauro Carvalho Chehab static int hi_command(struct drxk_state *state, u16 cmd, u16 *p_result)
10099a0bf528SMauro Carvalho Chehab {
10109a0bf528SMauro Carvalho Chehab 	int status;
10119a0bf528SMauro Carvalho Chehab 	bool powerdown_cmd;
10129a0bf528SMauro Carvalho Chehab 
10139a0bf528SMauro Carvalho Chehab 	dprintk(1, "\n");
10149a0bf528SMauro Carvalho Chehab 
10159a0bf528SMauro Carvalho Chehab 	/* Write command */
10169a0bf528SMauro Carvalho Chehab 	status = write16(state, SIO_HI_RA_RAM_CMD__A, cmd);
10179a0bf528SMauro Carvalho Chehab 	if (status < 0)
10189a0bf528SMauro Carvalho Chehab 		goto error;
10199a0bf528SMauro Carvalho Chehab 	if (cmd == SIO_HI_RA_RAM_CMD_RESET)
10209a0bf528SMauro Carvalho Chehab 		msleep(1);
10219a0bf528SMauro Carvalho Chehab 
10229a0bf528SMauro Carvalho Chehab 	powerdown_cmd =
10239a0bf528SMauro Carvalho Chehab 	    (bool) ((cmd == SIO_HI_RA_RAM_CMD_CONFIG) &&
1024cd7a67a4SMauro Carvalho Chehab 		    ((state->m_hi_cfg_ctrl) &
10259a0bf528SMauro Carvalho Chehab 		     SIO_HI_RA_RAM_PAR_5_CFG_SLEEP__M) ==
10269a0bf528SMauro Carvalho Chehab 		    SIO_HI_RA_RAM_PAR_5_CFG_SLEEP_ZZZ);
10279a0bf528SMauro Carvalho Chehab 	if (powerdown_cmd == false) {
10289a0bf528SMauro Carvalho Chehab 		/* Wait until command rdy */
1029cd7a67a4SMauro Carvalho Chehab 		u32 retry_count = 0;
1030cd7a67a4SMauro Carvalho Chehab 		u16 wait_cmd;
10319a0bf528SMauro Carvalho Chehab 
10329a0bf528SMauro Carvalho Chehab 		do {
10339a0bf528SMauro Carvalho Chehab 			msleep(1);
1034cd7a67a4SMauro Carvalho Chehab 			retry_count += 1;
10359a0bf528SMauro Carvalho Chehab 			status = read16(state, SIO_HI_RA_RAM_CMD__A,
1036cd7a67a4SMauro Carvalho Chehab 					  &wait_cmd);
1037cd7a67a4SMauro Carvalho Chehab 		} while ((status < 0) && (retry_count < DRXK_MAX_RETRIES)
1038cd7a67a4SMauro Carvalho Chehab 			 && (wait_cmd != 0));
10399a0bf528SMauro Carvalho Chehab 		if (status < 0)
10409a0bf528SMauro Carvalho Chehab 			goto error;
1041cd7a67a4SMauro Carvalho Chehab 		status = read16(state, SIO_HI_RA_RAM_RES__A, p_result);
10429a0bf528SMauro Carvalho Chehab 	}
10439a0bf528SMauro Carvalho Chehab error:
10449a0bf528SMauro Carvalho Chehab 	if (status < 0)
10453a4398f5SMauro Carvalho Chehab 		pr_err("Error %d on %s\n", status, __func__);
10469a0bf528SMauro Carvalho Chehab 
10479a0bf528SMauro Carvalho Chehab 	return status;
10489a0bf528SMauro Carvalho Chehab }
10499a0bf528SMauro Carvalho Chehab 
1050cd7a67a4SMauro Carvalho Chehab static int hi_cfg_command(struct drxk_state *state)
10519a0bf528SMauro Carvalho Chehab {
10529a0bf528SMauro Carvalho Chehab 	int status;
10539a0bf528SMauro Carvalho Chehab 
10549a0bf528SMauro Carvalho Chehab 	dprintk(1, "\n");
10559a0bf528SMauro Carvalho Chehab 
10569a0bf528SMauro Carvalho Chehab 	mutex_lock(&state->mutex);
10579a0bf528SMauro Carvalho Chehab 
1058cd7a67a4SMauro Carvalho Chehab 	status = write16(state, SIO_HI_RA_RAM_PAR_6__A, state->m_hi_cfg_timeout);
10599a0bf528SMauro Carvalho Chehab 	if (status < 0)
10609a0bf528SMauro Carvalho Chehab 		goto error;
1061cd7a67a4SMauro Carvalho Chehab 	status = write16(state, SIO_HI_RA_RAM_PAR_5__A, state->m_hi_cfg_ctrl);
10629a0bf528SMauro Carvalho Chehab 	if (status < 0)
10639a0bf528SMauro Carvalho Chehab 		goto error;
1064cd7a67a4SMauro Carvalho Chehab 	status = write16(state, SIO_HI_RA_RAM_PAR_4__A, state->m_hi_cfg_wake_up_key);
10659a0bf528SMauro Carvalho Chehab 	if (status < 0)
10669a0bf528SMauro Carvalho Chehab 		goto error;
1067cd7a67a4SMauro Carvalho Chehab 	status = write16(state, SIO_HI_RA_RAM_PAR_3__A, state->m_hi_cfg_bridge_delay);
10689a0bf528SMauro Carvalho Chehab 	if (status < 0)
10699a0bf528SMauro Carvalho Chehab 		goto error;
1070cd7a67a4SMauro Carvalho Chehab 	status = write16(state, SIO_HI_RA_RAM_PAR_2__A, state->m_hi_cfg_timing_div);
10719a0bf528SMauro Carvalho Chehab 	if (status < 0)
10729a0bf528SMauro Carvalho Chehab 		goto error;
10739a0bf528SMauro Carvalho Chehab 	status = write16(state, SIO_HI_RA_RAM_PAR_1__A, SIO_HI_RA_RAM_PAR_1_PAR1_SEC_KEY);
10749a0bf528SMauro Carvalho Chehab 	if (status < 0)
10759a0bf528SMauro Carvalho Chehab 		goto error;
1076cd7a67a4SMauro Carvalho Chehab 	status = hi_command(state, SIO_HI_RA_RAM_CMD_CONFIG, 0);
10779a0bf528SMauro Carvalho Chehab 	if (status < 0)
10789a0bf528SMauro Carvalho Chehab 		goto error;
10799a0bf528SMauro Carvalho Chehab 
1080cd7a67a4SMauro Carvalho Chehab 	state->m_hi_cfg_ctrl &= ~SIO_HI_RA_RAM_PAR_5_CFG_SLEEP_ZZZ;
10819a0bf528SMauro Carvalho Chehab error:
10829a0bf528SMauro Carvalho Chehab 	mutex_unlock(&state->mutex);
10839a0bf528SMauro Carvalho Chehab 	if (status < 0)
10843a4398f5SMauro Carvalho Chehab 		pr_err("Error %d on %s\n", status, __func__);
10859a0bf528SMauro Carvalho Chehab 	return status;
10869a0bf528SMauro Carvalho Chehab }
10879a0bf528SMauro Carvalho Chehab 
1088cd7a67a4SMauro Carvalho Chehab static int init_hi(struct drxk_state *state)
10899a0bf528SMauro Carvalho Chehab {
10909a0bf528SMauro Carvalho Chehab 	dprintk(1, "\n");
10919a0bf528SMauro Carvalho Chehab 
1092cd7a67a4SMauro Carvalho Chehab 	state->m_hi_cfg_wake_up_key = (state->demod_address << 1);
1093cd7a67a4SMauro Carvalho Chehab 	state->m_hi_cfg_timeout = 0x96FF;
10949a0bf528SMauro Carvalho Chehab 	/* port/bridge/power down ctrl */
1095cd7a67a4SMauro Carvalho Chehab 	state->m_hi_cfg_ctrl = SIO_HI_RA_RAM_PAR_5_CFG_SLV0_SLAVE;
10969a0bf528SMauro Carvalho Chehab 
1097cd7a67a4SMauro Carvalho Chehab 	return hi_cfg_command(state);
10989a0bf528SMauro Carvalho Chehab }
10999a0bf528SMauro Carvalho Chehab 
1100cd7a67a4SMauro Carvalho Chehab static int mpegts_configure_pins(struct drxk_state *state, bool mpeg_enable)
11019a0bf528SMauro Carvalho Chehab {
11029a0bf528SMauro Carvalho Chehab 	int status = -1;
1103cd7a67a4SMauro Carvalho Chehab 	u16 sio_pdr_mclk_cfg = 0;
1104cd7a67a4SMauro Carvalho Chehab 	u16 sio_pdr_mdx_cfg = 0;
11059a0bf528SMauro Carvalho Chehab 	u16 err_cfg = 0;
11069a0bf528SMauro Carvalho Chehab 
11079a0bf528SMauro Carvalho Chehab 	dprintk(1, ": mpeg %s, %s mode\n",
1108cd7a67a4SMauro Carvalho Chehab 		mpeg_enable ? "enable" : "disable",
1109cd7a67a4SMauro Carvalho Chehab 		state->m_enable_parallel ? "parallel" : "serial");
11109a0bf528SMauro Carvalho Chehab 
11119a0bf528SMauro Carvalho Chehab 	/* stop lock indicator process */
11129a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_GPIO__A, SCU_RAM_GPIO_HW_LOCK_IND_DISABLE);
11139a0bf528SMauro Carvalho Chehab 	if (status < 0)
11149a0bf528SMauro Carvalho Chehab 		goto error;
11159a0bf528SMauro Carvalho Chehab 
11169a0bf528SMauro Carvalho Chehab 	/*  MPEG TS pad configuration */
11178418366dSMartin Blumenstingl 	status = write16(state, SIO_TOP_COMM_KEY__A, SIO_TOP_COMM_KEY_KEY);
11189a0bf528SMauro Carvalho Chehab 	if (status < 0)
11199a0bf528SMauro Carvalho Chehab 		goto error;
11209a0bf528SMauro Carvalho Chehab 
1121cd7a67a4SMauro Carvalho Chehab 	if (mpeg_enable == false) {
11229a0bf528SMauro Carvalho Chehab 		/*  Set MPEG TS pads to inputmode */
11239a0bf528SMauro Carvalho Chehab 		status = write16(state, SIO_PDR_MSTRT_CFG__A, 0x0000);
11249a0bf528SMauro Carvalho Chehab 		if (status < 0)
11259a0bf528SMauro Carvalho Chehab 			goto error;
11269a0bf528SMauro Carvalho Chehab 		status = write16(state, SIO_PDR_MERR_CFG__A, 0x0000);
11279a0bf528SMauro Carvalho Chehab 		if (status < 0)
11289a0bf528SMauro Carvalho Chehab 			goto error;
11299a0bf528SMauro Carvalho Chehab 		status = write16(state, SIO_PDR_MCLK_CFG__A, 0x0000);
11309a0bf528SMauro Carvalho Chehab 		if (status < 0)
11319a0bf528SMauro Carvalho Chehab 			goto error;
11329a0bf528SMauro Carvalho Chehab 		status = write16(state, SIO_PDR_MVAL_CFG__A, 0x0000);
11339a0bf528SMauro Carvalho Chehab 		if (status < 0)
11349a0bf528SMauro Carvalho Chehab 			goto error;
11359a0bf528SMauro Carvalho Chehab 		status = write16(state, SIO_PDR_MD0_CFG__A, 0x0000);
11369a0bf528SMauro Carvalho Chehab 		if (status < 0)
11379a0bf528SMauro Carvalho Chehab 			goto error;
11389a0bf528SMauro Carvalho Chehab 		status = write16(state, SIO_PDR_MD1_CFG__A, 0x0000);
11399a0bf528SMauro Carvalho Chehab 		if (status < 0)
11409a0bf528SMauro Carvalho Chehab 			goto error;
11419a0bf528SMauro Carvalho Chehab 		status = write16(state, SIO_PDR_MD2_CFG__A, 0x0000);
11429a0bf528SMauro Carvalho Chehab 		if (status < 0)
11439a0bf528SMauro Carvalho Chehab 			goto error;
11449a0bf528SMauro Carvalho Chehab 		status = write16(state, SIO_PDR_MD3_CFG__A, 0x0000);
11459a0bf528SMauro Carvalho Chehab 		if (status < 0)
11469a0bf528SMauro Carvalho Chehab 			goto error;
11479a0bf528SMauro Carvalho Chehab 		status = write16(state, SIO_PDR_MD4_CFG__A, 0x0000);
11489a0bf528SMauro Carvalho Chehab 		if (status < 0)
11499a0bf528SMauro Carvalho Chehab 			goto error;
11509a0bf528SMauro Carvalho Chehab 		status = write16(state, SIO_PDR_MD5_CFG__A, 0x0000);
11519a0bf528SMauro Carvalho Chehab 		if (status < 0)
11529a0bf528SMauro Carvalho Chehab 			goto error;
11539a0bf528SMauro Carvalho Chehab 		status = write16(state, SIO_PDR_MD6_CFG__A, 0x0000);
11549a0bf528SMauro Carvalho Chehab 		if (status < 0)
11559a0bf528SMauro Carvalho Chehab 			goto error;
11569a0bf528SMauro Carvalho Chehab 		status = write16(state, SIO_PDR_MD7_CFG__A, 0x0000);
11579a0bf528SMauro Carvalho Chehab 		if (status < 0)
11589a0bf528SMauro Carvalho Chehab 			goto error;
11599a0bf528SMauro Carvalho Chehab 	} else {
11609a0bf528SMauro Carvalho Chehab 		/* Enable MPEG output */
1161cd7a67a4SMauro Carvalho Chehab 		sio_pdr_mdx_cfg =
1162cd7a67a4SMauro Carvalho Chehab 			((state->m_ts_data_strength <<
11639a0bf528SMauro Carvalho Chehab 			SIO_PDR_MD0_CFG_DRIVE__B) | 0x0003);
1164cd7a67a4SMauro Carvalho Chehab 		sio_pdr_mclk_cfg = ((state->m_ts_clockk_strength <<
11659a0bf528SMauro Carvalho Chehab 					SIO_PDR_MCLK_CFG_DRIVE__B) |
11669a0bf528SMauro Carvalho Chehab 					0x0003);
11679a0bf528SMauro Carvalho Chehab 
1168cd7a67a4SMauro Carvalho Chehab 		status = write16(state, SIO_PDR_MSTRT_CFG__A, sio_pdr_mdx_cfg);
11699a0bf528SMauro Carvalho Chehab 		if (status < 0)
11709a0bf528SMauro Carvalho Chehab 			goto error;
11719a0bf528SMauro Carvalho Chehab 
11729a0bf528SMauro Carvalho Chehab 		if (state->enable_merr_cfg)
1173cd7a67a4SMauro Carvalho Chehab 			err_cfg = sio_pdr_mdx_cfg;
11749a0bf528SMauro Carvalho Chehab 
11759a0bf528SMauro Carvalho Chehab 		status = write16(state, SIO_PDR_MERR_CFG__A, err_cfg);
11769a0bf528SMauro Carvalho Chehab 		if (status < 0)
11779a0bf528SMauro Carvalho Chehab 			goto error;
11789a0bf528SMauro Carvalho Chehab 		status = write16(state, SIO_PDR_MVAL_CFG__A, err_cfg);
11799a0bf528SMauro Carvalho Chehab 		if (status < 0)
11809a0bf528SMauro Carvalho Chehab 			goto error;
11819a0bf528SMauro Carvalho Chehab 
1182cd7a67a4SMauro Carvalho Chehab 		if (state->m_enable_parallel == true) {
11839a0bf528SMauro Carvalho Chehab 			/* paralel -> enable MD1 to MD7 */
1184cd7a67a4SMauro Carvalho Chehab 			status = write16(state, SIO_PDR_MD1_CFG__A, sio_pdr_mdx_cfg);
11859a0bf528SMauro Carvalho Chehab 			if (status < 0)
11869a0bf528SMauro Carvalho Chehab 				goto error;
1187cd7a67a4SMauro Carvalho Chehab 			status = write16(state, SIO_PDR_MD2_CFG__A, sio_pdr_mdx_cfg);
11889a0bf528SMauro Carvalho Chehab 			if (status < 0)
11899a0bf528SMauro Carvalho Chehab 				goto error;
1190cd7a67a4SMauro Carvalho Chehab 			status = write16(state, SIO_PDR_MD3_CFG__A, sio_pdr_mdx_cfg);
11919a0bf528SMauro Carvalho Chehab 			if (status < 0)
11929a0bf528SMauro Carvalho Chehab 				goto error;
1193cd7a67a4SMauro Carvalho Chehab 			status = write16(state, SIO_PDR_MD4_CFG__A, sio_pdr_mdx_cfg);
11949a0bf528SMauro Carvalho Chehab 			if (status < 0)
11959a0bf528SMauro Carvalho Chehab 				goto error;
1196cd7a67a4SMauro Carvalho Chehab 			status = write16(state, SIO_PDR_MD5_CFG__A, sio_pdr_mdx_cfg);
11979a0bf528SMauro Carvalho Chehab 			if (status < 0)
11989a0bf528SMauro Carvalho Chehab 				goto error;
1199cd7a67a4SMauro Carvalho Chehab 			status = write16(state, SIO_PDR_MD6_CFG__A, sio_pdr_mdx_cfg);
12009a0bf528SMauro Carvalho Chehab 			if (status < 0)
12019a0bf528SMauro Carvalho Chehab 				goto error;
1202cd7a67a4SMauro Carvalho Chehab 			status = write16(state, SIO_PDR_MD7_CFG__A, sio_pdr_mdx_cfg);
12039a0bf528SMauro Carvalho Chehab 			if (status < 0)
12049a0bf528SMauro Carvalho Chehab 				goto error;
12059a0bf528SMauro Carvalho Chehab 		} else {
1206cd7a67a4SMauro Carvalho Chehab 			sio_pdr_mdx_cfg = ((state->m_ts_data_strength <<
12079a0bf528SMauro Carvalho Chehab 						SIO_PDR_MD0_CFG_DRIVE__B)
12089a0bf528SMauro Carvalho Chehab 					| 0x0003);
12099a0bf528SMauro Carvalho Chehab 			/* serial -> disable MD1 to MD7 */
12109a0bf528SMauro Carvalho Chehab 			status = write16(state, SIO_PDR_MD1_CFG__A, 0x0000);
12119a0bf528SMauro Carvalho Chehab 			if (status < 0)
12129a0bf528SMauro Carvalho Chehab 				goto error;
12139a0bf528SMauro Carvalho Chehab 			status = write16(state, SIO_PDR_MD2_CFG__A, 0x0000);
12149a0bf528SMauro Carvalho Chehab 			if (status < 0)
12159a0bf528SMauro Carvalho Chehab 				goto error;
12169a0bf528SMauro Carvalho Chehab 			status = write16(state, SIO_PDR_MD3_CFG__A, 0x0000);
12179a0bf528SMauro Carvalho Chehab 			if (status < 0)
12189a0bf528SMauro Carvalho Chehab 				goto error;
12199a0bf528SMauro Carvalho Chehab 			status = write16(state, SIO_PDR_MD4_CFG__A, 0x0000);
12209a0bf528SMauro Carvalho Chehab 			if (status < 0)
12219a0bf528SMauro Carvalho Chehab 				goto error;
12229a0bf528SMauro Carvalho Chehab 			status = write16(state, SIO_PDR_MD5_CFG__A, 0x0000);
12239a0bf528SMauro Carvalho Chehab 			if (status < 0)
12249a0bf528SMauro Carvalho Chehab 				goto error;
12259a0bf528SMauro Carvalho Chehab 			status = write16(state, SIO_PDR_MD6_CFG__A, 0x0000);
12269a0bf528SMauro Carvalho Chehab 			if (status < 0)
12279a0bf528SMauro Carvalho Chehab 				goto error;
12289a0bf528SMauro Carvalho Chehab 			status = write16(state, SIO_PDR_MD7_CFG__A, 0x0000);
12299a0bf528SMauro Carvalho Chehab 			if (status < 0)
12309a0bf528SMauro Carvalho Chehab 				goto error;
12319a0bf528SMauro Carvalho Chehab 		}
1232cd7a67a4SMauro Carvalho Chehab 		status = write16(state, SIO_PDR_MCLK_CFG__A, sio_pdr_mclk_cfg);
12339a0bf528SMauro Carvalho Chehab 		if (status < 0)
12349a0bf528SMauro Carvalho Chehab 			goto error;
1235cd7a67a4SMauro Carvalho Chehab 		status = write16(state, SIO_PDR_MD0_CFG__A, sio_pdr_mdx_cfg);
12369a0bf528SMauro Carvalho Chehab 		if (status < 0)
12379a0bf528SMauro Carvalho Chehab 			goto error;
12389a0bf528SMauro Carvalho Chehab 	}
12399a0bf528SMauro Carvalho Chehab 	/*  Enable MB output over MPEG pads and ctl input */
12409a0bf528SMauro Carvalho Chehab 	status = write16(state, SIO_PDR_MON_CFG__A, 0x0000);
12419a0bf528SMauro Carvalho Chehab 	if (status < 0)
12429a0bf528SMauro Carvalho Chehab 		goto error;
12439a0bf528SMauro Carvalho Chehab 	/*  Write nomagic word to enable pdr reg write */
12449a0bf528SMauro Carvalho Chehab 	status = write16(state, SIO_TOP_COMM_KEY__A, 0x0000);
12459a0bf528SMauro Carvalho Chehab error:
12469a0bf528SMauro Carvalho Chehab 	if (status < 0)
12473a4398f5SMauro Carvalho Chehab 		pr_err("Error %d on %s\n", status, __func__);
12489a0bf528SMauro Carvalho Chehab 	return status;
12499a0bf528SMauro Carvalho Chehab }
12509a0bf528SMauro Carvalho Chehab 
1251cd7a67a4SMauro Carvalho Chehab static int mpegts_disable(struct drxk_state *state)
12529a0bf528SMauro Carvalho Chehab {
12539a0bf528SMauro Carvalho Chehab 	dprintk(1, "\n");
12549a0bf528SMauro Carvalho Chehab 
1255cd7a67a4SMauro Carvalho Chehab 	return mpegts_configure_pins(state, false);
12569a0bf528SMauro Carvalho Chehab }
12579a0bf528SMauro Carvalho Chehab 
1258cd7a67a4SMauro Carvalho Chehab static int bl_chain_cmd(struct drxk_state *state,
1259cd7a67a4SMauro Carvalho Chehab 		      u16 rom_offset, u16 nr_of_elements, u32 time_out)
12609a0bf528SMauro Carvalho Chehab {
1261cd7a67a4SMauro Carvalho Chehab 	u16 bl_status = 0;
12629a0bf528SMauro Carvalho Chehab 	int status;
12639a0bf528SMauro Carvalho Chehab 	unsigned long end;
12649a0bf528SMauro Carvalho Chehab 
12659a0bf528SMauro Carvalho Chehab 	dprintk(1, "\n");
12669a0bf528SMauro Carvalho Chehab 	mutex_lock(&state->mutex);
12679a0bf528SMauro Carvalho Chehab 	status = write16(state, SIO_BL_MODE__A, SIO_BL_MODE_CHAIN);
12689a0bf528SMauro Carvalho Chehab 	if (status < 0)
12699a0bf528SMauro Carvalho Chehab 		goto error;
1270cd7a67a4SMauro Carvalho Chehab 	status = write16(state, SIO_BL_CHAIN_ADDR__A, rom_offset);
12719a0bf528SMauro Carvalho Chehab 	if (status < 0)
12729a0bf528SMauro Carvalho Chehab 		goto error;
1273cd7a67a4SMauro Carvalho Chehab 	status = write16(state, SIO_BL_CHAIN_LEN__A, nr_of_elements);
12749a0bf528SMauro Carvalho Chehab 	if (status < 0)
12759a0bf528SMauro Carvalho Chehab 		goto error;
12769a0bf528SMauro Carvalho Chehab 	status = write16(state, SIO_BL_ENABLE__A, SIO_BL_ENABLE_ON);
12779a0bf528SMauro Carvalho Chehab 	if (status < 0)
12789a0bf528SMauro Carvalho Chehab 		goto error;
12799a0bf528SMauro Carvalho Chehab 
1280cd7a67a4SMauro Carvalho Chehab 	end = jiffies + msecs_to_jiffies(time_out);
12819a0bf528SMauro Carvalho Chehab 	do {
12829a0bf528SMauro Carvalho Chehab 		msleep(1);
1283cd7a67a4SMauro Carvalho Chehab 		status = read16(state, SIO_BL_STATUS__A, &bl_status);
12849a0bf528SMauro Carvalho Chehab 		if (status < 0)
12859a0bf528SMauro Carvalho Chehab 			goto error;
1286cd7a67a4SMauro Carvalho Chehab 	} while ((bl_status == 0x1) &&
12879a0bf528SMauro Carvalho Chehab 			((time_is_after_jiffies(end))));
12889a0bf528SMauro Carvalho Chehab 
1289cd7a67a4SMauro Carvalho Chehab 	if (bl_status == 0x1) {
12903a4398f5SMauro Carvalho Chehab 		pr_err("SIO not ready\n");
12919a0bf528SMauro Carvalho Chehab 		status = -EINVAL;
12929a0bf528SMauro Carvalho Chehab 		goto error2;
12939a0bf528SMauro Carvalho Chehab 	}
12949a0bf528SMauro Carvalho Chehab error:
12959a0bf528SMauro Carvalho Chehab 	if (status < 0)
12963a4398f5SMauro Carvalho Chehab 		pr_err("Error %d on %s\n", status, __func__);
12979a0bf528SMauro Carvalho Chehab error2:
12989a0bf528SMauro Carvalho Chehab 	mutex_unlock(&state->mutex);
12999a0bf528SMauro Carvalho Chehab 	return status;
13009a0bf528SMauro Carvalho Chehab }
13019a0bf528SMauro Carvalho Chehab 
13029a0bf528SMauro Carvalho Chehab 
1303cd7a67a4SMauro Carvalho Chehab static int download_microcode(struct drxk_state *state,
1304cd7a67a4SMauro Carvalho Chehab 			     const u8 p_mc_image[], u32 length)
13059a0bf528SMauro Carvalho Chehab {
1306cd7a67a4SMauro Carvalho Chehab 	const u8 *p_src = p_mc_image;
1307cd7a67a4SMauro Carvalho Chehab 	u32 address;
1308cd7a67a4SMauro Carvalho Chehab 	u16 n_blocks;
1309cd7a67a4SMauro Carvalho Chehab 	u16 block_size;
13109a0bf528SMauro Carvalho Chehab 	u32 offset = 0;
13119a0bf528SMauro Carvalho Chehab 	u32 i;
13129a0bf528SMauro Carvalho Chehab 	int status = 0;
13139a0bf528SMauro Carvalho Chehab 
13149a0bf528SMauro Carvalho Chehab 	dprintk(1, "\n");
13159a0bf528SMauro Carvalho Chehab 
13169a0bf528SMauro Carvalho Chehab 	/* down the drain (we don't care about MAGIC_WORD) */
13179a0bf528SMauro Carvalho Chehab #if 0
13189a0bf528SMauro Carvalho Chehab 	/* For future reference */
1319cd7a67a4SMauro Carvalho Chehab 	drain = (p_src[0] << 8) | p_src[1];
13209a0bf528SMauro Carvalho Chehab #endif
1321cd7a67a4SMauro Carvalho Chehab 	p_src += sizeof(u16);
13229a0bf528SMauro Carvalho Chehab 	offset += sizeof(u16);
1323cd7a67a4SMauro Carvalho Chehab 	n_blocks = (p_src[0] << 8) | p_src[1];
1324cd7a67a4SMauro Carvalho Chehab 	p_src += sizeof(u16);
13259a0bf528SMauro Carvalho Chehab 	offset += sizeof(u16);
13269a0bf528SMauro Carvalho Chehab 
1327cd7a67a4SMauro Carvalho Chehab 	for (i = 0; i < n_blocks; i += 1) {
1328cd7a67a4SMauro Carvalho Chehab 		address = (p_src[0] << 24) | (p_src[1] << 16) |
1329cd7a67a4SMauro Carvalho Chehab 		    (p_src[2] << 8) | p_src[3];
1330cd7a67a4SMauro Carvalho Chehab 		p_src += sizeof(u32);
13319a0bf528SMauro Carvalho Chehab 		offset += sizeof(u32);
13329a0bf528SMauro Carvalho Chehab 
1333cd7a67a4SMauro Carvalho Chehab 		block_size = ((p_src[0] << 8) | p_src[1]) * sizeof(u16);
1334cd7a67a4SMauro Carvalho Chehab 		p_src += sizeof(u16);
13359a0bf528SMauro Carvalho Chehab 		offset += sizeof(u16);
13369a0bf528SMauro Carvalho Chehab 
13379a0bf528SMauro Carvalho Chehab #if 0
13389a0bf528SMauro Carvalho Chehab 		/* For future reference */
1339cd7a67a4SMauro Carvalho Chehab 		flags = (p_src[0] << 8) | p_src[1];
13409a0bf528SMauro Carvalho Chehab #endif
1341cd7a67a4SMauro Carvalho Chehab 		p_src += sizeof(u16);
13429a0bf528SMauro Carvalho Chehab 		offset += sizeof(u16);
13439a0bf528SMauro Carvalho Chehab 
13449a0bf528SMauro Carvalho Chehab #if 0
13459a0bf528SMauro Carvalho Chehab 		/* For future reference */
1346cd7a67a4SMauro Carvalho Chehab 		block_crc = (p_src[0] << 8) | p_src[1];
13479a0bf528SMauro Carvalho Chehab #endif
1348cd7a67a4SMauro Carvalho Chehab 		p_src += sizeof(u16);
13499a0bf528SMauro Carvalho Chehab 		offset += sizeof(u16);
13509a0bf528SMauro Carvalho Chehab 
1351cd7a67a4SMauro Carvalho Chehab 		if (offset + block_size > length) {
13523a4398f5SMauro Carvalho Chehab 			pr_err("Firmware is corrupted.\n");
13539a0bf528SMauro Carvalho Chehab 			return -EINVAL;
13549a0bf528SMauro Carvalho Chehab 		}
13559a0bf528SMauro Carvalho Chehab 
1356cd7a67a4SMauro Carvalho Chehab 		status = write_block(state, address, block_size, p_src);
13579a0bf528SMauro Carvalho Chehab 		if (status < 0) {
13583a4398f5SMauro Carvalho Chehab 			pr_err("Error %d while loading firmware\n", status);
13599a0bf528SMauro Carvalho Chehab 			break;
13609a0bf528SMauro Carvalho Chehab 		}
1361cd7a67a4SMauro Carvalho Chehab 		p_src += block_size;
1362cd7a67a4SMauro Carvalho Chehab 		offset += block_size;
13639a0bf528SMauro Carvalho Chehab 	}
13649a0bf528SMauro Carvalho Chehab 	return status;
13659a0bf528SMauro Carvalho Chehab }
13669a0bf528SMauro Carvalho Chehab 
1367cd7a67a4SMauro Carvalho Chehab static int dvbt_enable_ofdm_token_ring(struct drxk_state *state, bool enable)
13689a0bf528SMauro Carvalho Chehab {
13699a0bf528SMauro Carvalho Chehab 	int status;
13709a0bf528SMauro Carvalho Chehab 	u16 data = 0;
1371cd7a67a4SMauro Carvalho Chehab 	u16 desired_ctrl = SIO_OFDM_SH_OFDM_RING_ENABLE_ON;
1372cd7a67a4SMauro Carvalho Chehab 	u16 desired_status = SIO_OFDM_SH_OFDM_RING_STATUS_ENABLED;
13739a0bf528SMauro Carvalho Chehab 	unsigned long end;
13749a0bf528SMauro Carvalho Chehab 
13759a0bf528SMauro Carvalho Chehab 	dprintk(1, "\n");
13769a0bf528SMauro Carvalho Chehab 
13779a0bf528SMauro Carvalho Chehab 	if (enable == false) {
1378cd7a67a4SMauro Carvalho Chehab 		desired_ctrl = SIO_OFDM_SH_OFDM_RING_ENABLE_OFF;
1379cd7a67a4SMauro Carvalho Chehab 		desired_status = SIO_OFDM_SH_OFDM_RING_STATUS_DOWN;
13809a0bf528SMauro Carvalho Chehab 	}
13819a0bf528SMauro Carvalho Chehab 
13829a0bf528SMauro Carvalho Chehab 	status = read16(state, SIO_OFDM_SH_OFDM_RING_STATUS__A, &data);
1383cd7a67a4SMauro Carvalho Chehab 	if (status >= 0 && data == desired_status) {
13849a0bf528SMauro Carvalho Chehab 		/* tokenring already has correct status */
13859a0bf528SMauro Carvalho Chehab 		return status;
13869a0bf528SMauro Carvalho Chehab 	}
13879a0bf528SMauro Carvalho Chehab 	/* Disable/enable dvbt tokenring bridge   */
1388cd7a67a4SMauro Carvalho Chehab 	status = write16(state, SIO_OFDM_SH_OFDM_RING_ENABLE__A, desired_ctrl);
13899a0bf528SMauro Carvalho Chehab 
13909a0bf528SMauro Carvalho Chehab 	end = jiffies + msecs_to_jiffies(DRXK_OFDM_TR_SHUTDOWN_TIMEOUT);
13919a0bf528SMauro Carvalho Chehab 	do {
13929a0bf528SMauro Carvalho Chehab 		status = read16(state, SIO_OFDM_SH_OFDM_RING_STATUS__A, &data);
1393cd7a67a4SMauro Carvalho Chehab 		if ((status >= 0 && data == desired_status) || time_is_after_jiffies(end))
13949a0bf528SMauro Carvalho Chehab 			break;
13959a0bf528SMauro Carvalho Chehab 		msleep(1);
13969a0bf528SMauro Carvalho Chehab 	} while (1);
1397cd7a67a4SMauro Carvalho Chehab 	if (data != desired_status) {
13983a4398f5SMauro Carvalho Chehab 		pr_err("SIO not ready\n");
13999a0bf528SMauro Carvalho Chehab 		return -EINVAL;
14009a0bf528SMauro Carvalho Chehab 	}
14019a0bf528SMauro Carvalho Chehab 	return status;
14029a0bf528SMauro Carvalho Chehab }
14039a0bf528SMauro Carvalho Chehab 
1404cd7a67a4SMauro Carvalho Chehab static int mpegts_stop(struct drxk_state *state)
14059a0bf528SMauro Carvalho Chehab {
14069a0bf528SMauro Carvalho Chehab 	int status = 0;
1407cd7a67a4SMauro Carvalho Chehab 	u16 fec_oc_snc_mode = 0;
1408cd7a67a4SMauro Carvalho Chehab 	u16 fec_oc_ipr_mode = 0;
14099a0bf528SMauro Carvalho Chehab 
14109a0bf528SMauro Carvalho Chehab 	dprintk(1, "\n");
14119a0bf528SMauro Carvalho Chehab 
14129a0bf528SMauro Carvalho Chehab 	/* Gracefull shutdown (byte boundaries) */
1413cd7a67a4SMauro Carvalho Chehab 	status = read16(state, FEC_OC_SNC_MODE__A, &fec_oc_snc_mode);
14149a0bf528SMauro Carvalho Chehab 	if (status < 0)
14159a0bf528SMauro Carvalho Chehab 		goto error;
1416cd7a67a4SMauro Carvalho Chehab 	fec_oc_snc_mode |= FEC_OC_SNC_MODE_SHUTDOWN__M;
1417cd7a67a4SMauro Carvalho Chehab 	status = write16(state, FEC_OC_SNC_MODE__A, fec_oc_snc_mode);
14189a0bf528SMauro Carvalho Chehab 	if (status < 0)
14199a0bf528SMauro Carvalho Chehab 		goto error;
14209a0bf528SMauro Carvalho Chehab 
14219a0bf528SMauro Carvalho Chehab 	/* Suppress MCLK during absence of data */
1422cd7a67a4SMauro Carvalho Chehab 	status = read16(state, FEC_OC_IPR_MODE__A, &fec_oc_ipr_mode);
14239a0bf528SMauro Carvalho Chehab 	if (status < 0)
14249a0bf528SMauro Carvalho Chehab 		goto error;
1425cd7a67a4SMauro Carvalho Chehab 	fec_oc_ipr_mode |= FEC_OC_IPR_MODE_MCLK_DIS_DAT_ABS__M;
1426cd7a67a4SMauro Carvalho Chehab 	status = write16(state, FEC_OC_IPR_MODE__A, fec_oc_ipr_mode);
14279a0bf528SMauro Carvalho Chehab 
14289a0bf528SMauro Carvalho Chehab error:
14299a0bf528SMauro Carvalho Chehab 	if (status < 0)
14303a4398f5SMauro Carvalho Chehab 		pr_err("Error %d on %s\n", status, __func__);
14319a0bf528SMauro Carvalho Chehab 
14329a0bf528SMauro Carvalho Chehab 	return status;
14339a0bf528SMauro Carvalho Chehab }
14349a0bf528SMauro Carvalho Chehab 
14359a0bf528SMauro Carvalho Chehab static int scu_command(struct drxk_state *state,
1436cd7a67a4SMauro Carvalho Chehab 		       u16 cmd, u8 parameter_len,
1437cd7a67a4SMauro Carvalho Chehab 		       u16 *parameter, u8 result_len, u16 *result)
14389a0bf528SMauro Carvalho Chehab {
14399a0bf528SMauro Carvalho Chehab #if (SCU_RAM_PARAM_0__A - SCU_RAM_PARAM_15__A) != 15
14409a0bf528SMauro Carvalho Chehab #error DRXK register mapping no longer compatible with this routine!
14419a0bf528SMauro Carvalho Chehab #endif
1442cd7a67a4SMauro Carvalho Chehab 	u16 cur_cmd = 0;
14439a0bf528SMauro Carvalho Chehab 	int status = -EINVAL;
14449a0bf528SMauro Carvalho Chehab 	unsigned long end;
14459a0bf528SMauro Carvalho Chehab 	u8 buffer[34];
14469a0bf528SMauro Carvalho Chehab 	int cnt = 0, ii;
14479a0bf528SMauro Carvalho Chehab 	const char *p;
14489a0bf528SMauro Carvalho Chehab 	char errname[30];
14499a0bf528SMauro Carvalho Chehab 
14509a0bf528SMauro Carvalho Chehab 	dprintk(1, "\n");
14519a0bf528SMauro Carvalho Chehab 
1452cd7a67a4SMauro Carvalho Chehab 	if ((cmd == 0) || ((parameter_len > 0) && (parameter == NULL)) ||
1453cd7a67a4SMauro Carvalho Chehab 	    ((result_len > 0) && (result == NULL))) {
14543a4398f5SMauro Carvalho Chehab 		pr_err("Error %d on %s\n", status, __func__);
14559a0bf528SMauro Carvalho Chehab 		return status;
14569a0bf528SMauro Carvalho Chehab 	}
14579a0bf528SMauro Carvalho Chehab 
14589a0bf528SMauro Carvalho Chehab 	mutex_lock(&state->mutex);
14599a0bf528SMauro Carvalho Chehab 
14609a0bf528SMauro Carvalho Chehab 	/* assume that the command register is ready
14619a0bf528SMauro Carvalho Chehab 		since it is checked afterwards */
1462cd7a67a4SMauro Carvalho Chehab 	for (ii = parameter_len - 1; ii >= 0; ii -= 1) {
14639a0bf528SMauro Carvalho Chehab 		buffer[cnt++] = (parameter[ii] & 0xFF);
14649a0bf528SMauro Carvalho Chehab 		buffer[cnt++] = ((parameter[ii] >> 8) & 0xFF);
14659a0bf528SMauro Carvalho Chehab 	}
14669a0bf528SMauro Carvalho Chehab 	buffer[cnt++] = (cmd & 0xFF);
14679a0bf528SMauro Carvalho Chehab 	buffer[cnt++] = ((cmd >> 8) & 0xFF);
14689a0bf528SMauro Carvalho Chehab 
14699a0bf528SMauro Carvalho Chehab 	write_block(state, SCU_RAM_PARAM_0__A -
1470cd7a67a4SMauro Carvalho Chehab 			(parameter_len - 1), cnt, buffer);
14719a0bf528SMauro Carvalho Chehab 	/* Wait until SCU has processed command */
14729a0bf528SMauro Carvalho Chehab 	end = jiffies + msecs_to_jiffies(DRXK_MAX_WAITTIME);
14739a0bf528SMauro Carvalho Chehab 	do {
14749a0bf528SMauro Carvalho Chehab 		msleep(1);
1475cd7a67a4SMauro Carvalho Chehab 		status = read16(state, SCU_RAM_COMMAND__A, &cur_cmd);
14769a0bf528SMauro Carvalho Chehab 		if (status < 0)
14779a0bf528SMauro Carvalho Chehab 			goto error;
1478cd7a67a4SMauro Carvalho Chehab 	} while (!(cur_cmd == DRX_SCU_READY) && (time_is_after_jiffies(end)));
1479cd7a67a4SMauro Carvalho Chehab 	if (cur_cmd != DRX_SCU_READY) {
14803a4398f5SMauro Carvalho Chehab 		pr_err("SCU not ready\n");
14819a0bf528SMauro Carvalho Chehab 		status = -EIO;
14829a0bf528SMauro Carvalho Chehab 		goto error2;
14839a0bf528SMauro Carvalho Chehab 	}
14849a0bf528SMauro Carvalho Chehab 	/* read results */
1485cd7a67a4SMauro Carvalho Chehab 	if ((result_len > 0) && (result != NULL)) {
14869a0bf528SMauro Carvalho Chehab 		s16 err;
14879a0bf528SMauro Carvalho Chehab 		int ii;
14889a0bf528SMauro Carvalho Chehab 
1489cd7a67a4SMauro Carvalho Chehab 		for (ii = result_len - 1; ii >= 0; ii -= 1) {
14909a0bf528SMauro Carvalho Chehab 			status = read16(state, SCU_RAM_PARAM_0__A - ii, &result[ii]);
14919a0bf528SMauro Carvalho Chehab 			if (status < 0)
14929a0bf528SMauro Carvalho Chehab 				goto error;
14939a0bf528SMauro Carvalho Chehab 		}
14949a0bf528SMauro Carvalho Chehab 
14959a0bf528SMauro Carvalho Chehab 		/* Check if an error was reported by SCU */
14969a0bf528SMauro Carvalho Chehab 		err = (s16)result[0];
14979a0bf528SMauro Carvalho Chehab 		if (err >= 0)
14989a0bf528SMauro Carvalho Chehab 			goto error;
14999a0bf528SMauro Carvalho Chehab 
15009a0bf528SMauro Carvalho Chehab 		/* check for the known error codes */
15019a0bf528SMauro Carvalho Chehab 		switch (err) {
15029a0bf528SMauro Carvalho Chehab 		case SCU_RESULT_UNKCMD:
15039a0bf528SMauro Carvalho Chehab 			p = "SCU_RESULT_UNKCMD";
15049a0bf528SMauro Carvalho Chehab 			break;
15059a0bf528SMauro Carvalho Chehab 		case SCU_RESULT_UNKSTD:
15069a0bf528SMauro Carvalho Chehab 			p = "SCU_RESULT_UNKSTD";
15079a0bf528SMauro Carvalho Chehab 			break;
15089a0bf528SMauro Carvalho Chehab 		case SCU_RESULT_SIZE:
15099a0bf528SMauro Carvalho Chehab 			p = "SCU_RESULT_SIZE";
15109a0bf528SMauro Carvalho Chehab 			break;
15119a0bf528SMauro Carvalho Chehab 		case SCU_RESULT_INVPAR:
15129a0bf528SMauro Carvalho Chehab 			p = "SCU_RESULT_INVPAR";
15139a0bf528SMauro Carvalho Chehab 			break;
15149a0bf528SMauro Carvalho Chehab 		default: /* Other negative values are errors */
15159a0bf528SMauro Carvalho Chehab 			sprintf(errname, "ERROR: %d\n", err);
15169a0bf528SMauro Carvalho Chehab 			p = errname;
15179a0bf528SMauro Carvalho Chehab 		}
15183a4398f5SMauro Carvalho Chehab 		pr_err("%s while sending cmd 0x%04x with params:", p, cmd);
15199a0bf528SMauro Carvalho Chehab 		print_hex_dump_bytes("drxk: ", DUMP_PREFIX_NONE, buffer, cnt);
15209a0bf528SMauro Carvalho Chehab 		status = -EINVAL;
15219a0bf528SMauro Carvalho Chehab 		goto error2;
15229a0bf528SMauro Carvalho Chehab 	}
15239a0bf528SMauro Carvalho Chehab 
15249a0bf528SMauro Carvalho Chehab error:
15259a0bf528SMauro Carvalho Chehab 	if (status < 0)
15263a4398f5SMauro Carvalho Chehab 		pr_err("Error %d on %s\n", status, __func__);
15279a0bf528SMauro Carvalho Chehab error2:
15289a0bf528SMauro Carvalho Chehab 	mutex_unlock(&state->mutex);
15299a0bf528SMauro Carvalho Chehab 	return status;
15309a0bf528SMauro Carvalho Chehab }
15319a0bf528SMauro Carvalho Chehab 
1532cd7a67a4SMauro Carvalho Chehab static int set_iqm_af(struct drxk_state *state, bool active)
15339a0bf528SMauro Carvalho Chehab {
15349a0bf528SMauro Carvalho Chehab 	u16 data = 0;
15359a0bf528SMauro Carvalho Chehab 	int status;
15369a0bf528SMauro Carvalho Chehab 
15379a0bf528SMauro Carvalho Chehab 	dprintk(1, "\n");
15389a0bf528SMauro Carvalho Chehab 
15399a0bf528SMauro Carvalho Chehab 	/* Configure IQM */
15409a0bf528SMauro Carvalho Chehab 	status = read16(state, IQM_AF_STDBY__A, &data);
15419a0bf528SMauro Carvalho Chehab 	if (status < 0)
15429a0bf528SMauro Carvalho Chehab 		goto error;
15439a0bf528SMauro Carvalho Chehab 
15449a0bf528SMauro Carvalho Chehab 	if (!active) {
15459a0bf528SMauro Carvalho Chehab 		data |= (IQM_AF_STDBY_STDBY_ADC_STANDBY
15469a0bf528SMauro Carvalho Chehab 				| IQM_AF_STDBY_STDBY_AMP_STANDBY
15479a0bf528SMauro Carvalho Chehab 				| IQM_AF_STDBY_STDBY_PD_STANDBY
15489a0bf528SMauro Carvalho Chehab 				| IQM_AF_STDBY_STDBY_TAGC_IF_STANDBY
15499a0bf528SMauro Carvalho Chehab 				| IQM_AF_STDBY_STDBY_TAGC_RF_STANDBY);
15509a0bf528SMauro Carvalho Chehab 	} else {
15519a0bf528SMauro Carvalho Chehab 		data &= ((~IQM_AF_STDBY_STDBY_ADC_STANDBY)
15529a0bf528SMauro Carvalho Chehab 				& (~IQM_AF_STDBY_STDBY_AMP_STANDBY)
15539a0bf528SMauro Carvalho Chehab 				& (~IQM_AF_STDBY_STDBY_PD_STANDBY)
15549a0bf528SMauro Carvalho Chehab 				& (~IQM_AF_STDBY_STDBY_TAGC_IF_STANDBY)
15559a0bf528SMauro Carvalho Chehab 				& (~IQM_AF_STDBY_STDBY_TAGC_RF_STANDBY)
15569a0bf528SMauro Carvalho Chehab 			);
15579a0bf528SMauro Carvalho Chehab 	}
15589a0bf528SMauro Carvalho Chehab 	status = write16(state, IQM_AF_STDBY__A, data);
15599a0bf528SMauro Carvalho Chehab 
15609a0bf528SMauro Carvalho Chehab error:
15619a0bf528SMauro Carvalho Chehab 	if (status < 0)
15623a4398f5SMauro Carvalho Chehab 		pr_err("Error %d on %s\n", status, __func__);
15639a0bf528SMauro Carvalho Chehab 	return status;
15649a0bf528SMauro Carvalho Chehab }
15659a0bf528SMauro Carvalho Chehab 
1566cd7a67a4SMauro Carvalho Chehab static int ctrl_power_mode(struct drxk_state *state, enum drx_power_mode *mode)
15679a0bf528SMauro Carvalho Chehab {
15689a0bf528SMauro Carvalho Chehab 	int status = 0;
1569cd7a67a4SMauro Carvalho Chehab 	u16 sio_cc_pwd_mode = 0;
15709a0bf528SMauro Carvalho Chehab 
15719a0bf528SMauro Carvalho Chehab 	dprintk(1, "\n");
15729a0bf528SMauro Carvalho Chehab 
15739a0bf528SMauro Carvalho Chehab 	/* Check arguments */
15749a0bf528SMauro Carvalho Chehab 	if (mode == NULL)
15759a0bf528SMauro Carvalho Chehab 		return -EINVAL;
15769a0bf528SMauro Carvalho Chehab 
15779a0bf528SMauro Carvalho Chehab 	switch (*mode) {
15789a0bf528SMauro Carvalho Chehab 	case DRX_POWER_UP:
1579cd7a67a4SMauro Carvalho Chehab 		sio_cc_pwd_mode = SIO_CC_PWD_MODE_LEVEL_NONE;
15809a0bf528SMauro Carvalho Chehab 		break;
15819a0bf528SMauro Carvalho Chehab 	case DRXK_POWER_DOWN_OFDM:
1582cd7a67a4SMauro Carvalho Chehab 		sio_cc_pwd_mode = SIO_CC_PWD_MODE_LEVEL_OFDM;
15839a0bf528SMauro Carvalho Chehab 		break;
15849a0bf528SMauro Carvalho Chehab 	case DRXK_POWER_DOWN_CORE:
1585cd7a67a4SMauro Carvalho Chehab 		sio_cc_pwd_mode = SIO_CC_PWD_MODE_LEVEL_CLOCK;
15869a0bf528SMauro Carvalho Chehab 		break;
15879a0bf528SMauro Carvalho Chehab 	case DRXK_POWER_DOWN_PLL:
1588cd7a67a4SMauro Carvalho Chehab 		sio_cc_pwd_mode = SIO_CC_PWD_MODE_LEVEL_PLL;
15899a0bf528SMauro Carvalho Chehab 		break;
15909a0bf528SMauro Carvalho Chehab 	case DRX_POWER_DOWN:
1591cd7a67a4SMauro Carvalho Chehab 		sio_cc_pwd_mode = SIO_CC_PWD_MODE_LEVEL_OSC;
15929a0bf528SMauro Carvalho Chehab 		break;
15939a0bf528SMauro Carvalho Chehab 	default:
15949a0bf528SMauro Carvalho Chehab 		/* Unknow sleep mode */
15959a0bf528SMauro Carvalho Chehab 		return -EINVAL;
15969a0bf528SMauro Carvalho Chehab 	}
15979a0bf528SMauro Carvalho Chehab 
15989a0bf528SMauro Carvalho Chehab 	/* If already in requested power mode, do nothing */
1599cd7a67a4SMauro Carvalho Chehab 	if (state->m_current_power_mode == *mode)
16009a0bf528SMauro Carvalho Chehab 		return 0;
16019a0bf528SMauro Carvalho Chehab 
16029a0bf528SMauro Carvalho Chehab 	/* For next steps make sure to start from DRX_POWER_UP mode */
1603cd7a67a4SMauro Carvalho Chehab 	if (state->m_current_power_mode != DRX_POWER_UP) {
1604cd7a67a4SMauro Carvalho Chehab 		status = power_up_device(state);
16059a0bf528SMauro Carvalho Chehab 		if (status < 0)
16069a0bf528SMauro Carvalho Chehab 			goto error;
1607cd7a67a4SMauro Carvalho Chehab 		status = dvbt_enable_ofdm_token_ring(state, true);
16089a0bf528SMauro Carvalho Chehab 		if (status < 0)
16099a0bf528SMauro Carvalho Chehab 			goto error;
16109a0bf528SMauro Carvalho Chehab 	}
16119a0bf528SMauro Carvalho Chehab 
16129a0bf528SMauro Carvalho Chehab 	if (*mode == DRX_POWER_UP) {
16139a0bf528SMauro Carvalho Chehab 		/* Restore analog & pin configuartion */
16149a0bf528SMauro Carvalho Chehab 	} else {
16159a0bf528SMauro Carvalho Chehab 		/* Power down to requested mode */
16169a0bf528SMauro Carvalho Chehab 		/* Backup some register settings */
16179a0bf528SMauro Carvalho Chehab 		/* Set pins with possible pull-ups connected
16189a0bf528SMauro Carvalho Chehab 		   to them in input mode */
16199a0bf528SMauro Carvalho Chehab 		/* Analog power down */
16209a0bf528SMauro Carvalho Chehab 		/* ADC power down */
16219a0bf528SMauro Carvalho Chehab 		/* Power down device */
16229a0bf528SMauro Carvalho Chehab 		/* stop all comm_exec */
16239a0bf528SMauro Carvalho Chehab 		/* Stop and power down previous standard */
1624cd7a67a4SMauro Carvalho Chehab 		switch (state->m_operation_mode) {
16259a0bf528SMauro Carvalho Chehab 		case OM_DVBT:
1626cd7a67a4SMauro Carvalho Chehab 			status = mpegts_stop(state);
16279a0bf528SMauro Carvalho Chehab 			if (status < 0)
16289a0bf528SMauro Carvalho Chehab 				goto error;
1629cd7a67a4SMauro Carvalho Chehab 			status = power_down_dvbt(state, false);
16309a0bf528SMauro Carvalho Chehab 			if (status < 0)
16319a0bf528SMauro Carvalho Chehab 				goto error;
16329a0bf528SMauro Carvalho Chehab 			break;
16339a0bf528SMauro Carvalho Chehab 		case OM_QAM_ITU_A:
16349a0bf528SMauro Carvalho Chehab 		case OM_QAM_ITU_C:
1635cd7a67a4SMauro Carvalho Chehab 			status = mpegts_stop(state);
16369a0bf528SMauro Carvalho Chehab 			if (status < 0)
16379a0bf528SMauro Carvalho Chehab 				goto error;
1638cd7a67a4SMauro Carvalho Chehab 			status = power_down_qam(state);
16399a0bf528SMauro Carvalho Chehab 			if (status < 0)
16409a0bf528SMauro Carvalho Chehab 				goto error;
16419a0bf528SMauro Carvalho Chehab 			break;
16429a0bf528SMauro Carvalho Chehab 		default:
16439a0bf528SMauro Carvalho Chehab 			break;
16449a0bf528SMauro Carvalho Chehab 		}
1645cd7a67a4SMauro Carvalho Chehab 		status = dvbt_enable_ofdm_token_ring(state, false);
16469a0bf528SMauro Carvalho Chehab 		if (status < 0)
16479a0bf528SMauro Carvalho Chehab 			goto error;
1648cd7a67a4SMauro Carvalho Chehab 		status = write16(state, SIO_CC_PWD_MODE__A, sio_cc_pwd_mode);
16499a0bf528SMauro Carvalho Chehab 		if (status < 0)
16509a0bf528SMauro Carvalho Chehab 			goto error;
16519a0bf528SMauro Carvalho Chehab 		status = write16(state, SIO_CC_UPDATE__A, SIO_CC_UPDATE_KEY);
16529a0bf528SMauro Carvalho Chehab 		if (status < 0)
16539a0bf528SMauro Carvalho Chehab 			goto error;
16549a0bf528SMauro Carvalho Chehab 
16559a0bf528SMauro Carvalho Chehab 		if (*mode != DRXK_POWER_DOWN_OFDM) {
1656cd7a67a4SMauro Carvalho Chehab 			state->m_hi_cfg_ctrl |=
16579a0bf528SMauro Carvalho Chehab 				SIO_HI_RA_RAM_PAR_5_CFG_SLEEP_ZZZ;
1658cd7a67a4SMauro Carvalho Chehab 			status = hi_cfg_command(state);
16599a0bf528SMauro Carvalho Chehab 			if (status < 0)
16609a0bf528SMauro Carvalho Chehab 				goto error;
16619a0bf528SMauro Carvalho Chehab 		}
16629a0bf528SMauro Carvalho Chehab 	}
1663cd7a67a4SMauro Carvalho Chehab 	state->m_current_power_mode = *mode;
16649a0bf528SMauro Carvalho Chehab 
16659a0bf528SMauro Carvalho Chehab error:
16669a0bf528SMauro Carvalho Chehab 	if (status < 0)
16673a4398f5SMauro Carvalho Chehab 		pr_err("Error %d on %s\n", status, __func__);
16689a0bf528SMauro Carvalho Chehab 
16699a0bf528SMauro Carvalho Chehab 	return status;
16709a0bf528SMauro Carvalho Chehab }
16719a0bf528SMauro Carvalho Chehab 
1672cd7a67a4SMauro Carvalho Chehab static int power_down_dvbt(struct drxk_state *state, bool set_power_mode)
16739a0bf528SMauro Carvalho Chehab {
1674cd7a67a4SMauro Carvalho Chehab 	enum drx_power_mode power_mode = DRXK_POWER_DOWN_OFDM;
1675cd7a67a4SMauro Carvalho Chehab 	u16 cmd_result = 0;
16769a0bf528SMauro Carvalho Chehab 	u16 data = 0;
16779a0bf528SMauro Carvalho Chehab 	int status;
16789a0bf528SMauro Carvalho Chehab 
16799a0bf528SMauro Carvalho Chehab 	dprintk(1, "\n");
16809a0bf528SMauro Carvalho Chehab 
16819a0bf528SMauro Carvalho Chehab 	status = read16(state, SCU_COMM_EXEC__A, &data);
16829a0bf528SMauro Carvalho Chehab 	if (status < 0)
16839a0bf528SMauro Carvalho Chehab 		goto error;
16849a0bf528SMauro Carvalho Chehab 	if (data == SCU_COMM_EXEC_ACTIVE) {
16859a0bf528SMauro Carvalho Chehab 		/* Send OFDM stop command */
1686cd7a67a4SMauro Carvalho Chehab 		status = scu_command(state, SCU_RAM_COMMAND_STANDARD_OFDM | SCU_RAM_COMMAND_CMD_DEMOD_STOP, 0, NULL, 1, &cmd_result);
16879a0bf528SMauro Carvalho Chehab 		if (status < 0)
16889a0bf528SMauro Carvalho Chehab 			goto error;
16899a0bf528SMauro Carvalho Chehab 		/* Send OFDM reset command */
1690cd7a67a4SMauro Carvalho Chehab 		status = scu_command(state, SCU_RAM_COMMAND_STANDARD_OFDM | SCU_RAM_COMMAND_CMD_DEMOD_RESET, 0, NULL, 1, &cmd_result);
16919a0bf528SMauro Carvalho Chehab 		if (status < 0)
16929a0bf528SMauro Carvalho Chehab 			goto error;
16939a0bf528SMauro Carvalho Chehab 	}
16949a0bf528SMauro Carvalho Chehab 
16959a0bf528SMauro Carvalho Chehab 	/* Reset datapath for OFDM, processors first */
16969a0bf528SMauro Carvalho Chehab 	status = write16(state, OFDM_SC_COMM_EXEC__A, OFDM_SC_COMM_EXEC_STOP);
16979a0bf528SMauro Carvalho Chehab 	if (status < 0)
16989a0bf528SMauro Carvalho Chehab 		goto error;
16999a0bf528SMauro Carvalho Chehab 	status = write16(state, OFDM_LC_COMM_EXEC__A, OFDM_LC_COMM_EXEC_STOP);
17009a0bf528SMauro Carvalho Chehab 	if (status < 0)
17019a0bf528SMauro Carvalho Chehab 		goto error;
17029a0bf528SMauro Carvalho Chehab 	status = write16(state, IQM_COMM_EXEC__A, IQM_COMM_EXEC_B_STOP);
17039a0bf528SMauro Carvalho Chehab 	if (status < 0)
17049a0bf528SMauro Carvalho Chehab 		goto error;
17059a0bf528SMauro Carvalho Chehab 
17069a0bf528SMauro Carvalho Chehab 	/* powerdown AFE                   */
1707cd7a67a4SMauro Carvalho Chehab 	status = set_iqm_af(state, false);
17089a0bf528SMauro Carvalho Chehab 	if (status < 0)
17099a0bf528SMauro Carvalho Chehab 		goto error;
17109a0bf528SMauro Carvalho Chehab 
17119a0bf528SMauro Carvalho Chehab 	/* powerdown to OFDM mode          */
1712cd7a67a4SMauro Carvalho Chehab 	if (set_power_mode) {
1713cd7a67a4SMauro Carvalho Chehab 		status = ctrl_power_mode(state, &power_mode);
17149a0bf528SMauro Carvalho Chehab 		if (status < 0)
17159a0bf528SMauro Carvalho Chehab 			goto error;
17169a0bf528SMauro Carvalho Chehab 	}
17179a0bf528SMauro Carvalho Chehab error:
17189a0bf528SMauro Carvalho Chehab 	if (status < 0)
17193a4398f5SMauro Carvalho Chehab 		pr_err("Error %d on %s\n", status, __func__);
17209a0bf528SMauro Carvalho Chehab 	return status;
17219a0bf528SMauro Carvalho Chehab }
17229a0bf528SMauro Carvalho Chehab 
1723cd7a67a4SMauro Carvalho Chehab static int setoperation_mode(struct drxk_state *state,
1724cd7a67a4SMauro Carvalho Chehab 			    enum operation_mode o_mode)
17259a0bf528SMauro Carvalho Chehab {
17269a0bf528SMauro Carvalho Chehab 	int status = 0;
17279a0bf528SMauro Carvalho Chehab 
17289a0bf528SMauro Carvalho Chehab 	dprintk(1, "\n");
17299a0bf528SMauro Carvalho Chehab 	/*
17309a0bf528SMauro Carvalho Chehab 	   Stop and power down previous standard
17319a0bf528SMauro Carvalho Chehab 	   TODO investigate total power down instead of partial
17329a0bf528SMauro Carvalho Chehab 	   power down depending on "previous" standard.
17339a0bf528SMauro Carvalho Chehab 	 */
17349a0bf528SMauro Carvalho Chehab 
17359a0bf528SMauro Carvalho Chehab 	/* disable HW lock indicator */
17369a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_GPIO__A, SCU_RAM_GPIO_HW_LOCK_IND_DISABLE);
17379a0bf528SMauro Carvalho Chehab 	if (status < 0)
17389a0bf528SMauro Carvalho Chehab 		goto error;
17399a0bf528SMauro Carvalho Chehab 
17409a0bf528SMauro Carvalho Chehab 	/* Device is already at the required mode */
1741cd7a67a4SMauro Carvalho Chehab 	if (state->m_operation_mode == o_mode)
17429a0bf528SMauro Carvalho Chehab 		return 0;
17439a0bf528SMauro Carvalho Chehab 
1744cd7a67a4SMauro Carvalho Chehab 	switch (state->m_operation_mode) {
17459a0bf528SMauro Carvalho Chehab 		/* OM_NONE was added for start up */
17469a0bf528SMauro Carvalho Chehab 	case OM_NONE:
17479a0bf528SMauro Carvalho Chehab 		break;
17489a0bf528SMauro Carvalho Chehab 	case OM_DVBT:
1749cd7a67a4SMauro Carvalho Chehab 		status = mpegts_stop(state);
17509a0bf528SMauro Carvalho Chehab 		if (status < 0)
17519a0bf528SMauro Carvalho Chehab 			goto error;
1752cd7a67a4SMauro Carvalho Chehab 		status = power_down_dvbt(state, true);
17539a0bf528SMauro Carvalho Chehab 		if (status < 0)
17549a0bf528SMauro Carvalho Chehab 			goto error;
1755cd7a67a4SMauro Carvalho Chehab 		state->m_operation_mode = OM_NONE;
17569a0bf528SMauro Carvalho Chehab 		break;
17579a0bf528SMauro Carvalho Chehab 	case OM_QAM_ITU_A:	/* fallthrough */
17589a0bf528SMauro Carvalho Chehab 	case OM_QAM_ITU_C:
1759cd7a67a4SMauro Carvalho Chehab 		status = mpegts_stop(state);
17609a0bf528SMauro Carvalho Chehab 		if (status < 0)
17619a0bf528SMauro Carvalho Chehab 			goto error;
1762cd7a67a4SMauro Carvalho Chehab 		status = power_down_qam(state);
17639a0bf528SMauro Carvalho Chehab 		if (status < 0)
17649a0bf528SMauro Carvalho Chehab 			goto error;
1765cd7a67a4SMauro Carvalho Chehab 		state->m_operation_mode = OM_NONE;
17669a0bf528SMauro Carvalho Chehab 		break;
17679a0bf528SMauro Carvalho Chehab 	case OM_QAM_ITU_B:
17689a0bf528SMauro Carvalho Chehab 	default:
17699a0bf528SMauro Carvalho Chehab 		status = -EINVAL;
17709a0bf528SMauro Carvalho Chehab 		goto error;
17719a0bf528SMauro Carvalho Chehab 	}
17729a0bf528SMauro Carvalho Chehab 
17739a0bf528SMauro Carvalho Chehab 	/*
17749a0bf528SMauro Carvalho Chehab 		Power up new standard
17759a0bf528SMauro Carvalho Chehab 		*/
1776cd7a67a4SMauro Carvalho Chehab 	switch (o_mode) {
17779a0bf528SMauro Carvalho Chehab 	case OM_DVBT:
17789a0bf528SMauro Carvalho Chehab 		dprintk(1, ": DVB-T\n");
1779cd7a67a4SMauro Carvalho Chehab 		state->m_operation_mode = o_mode;
1780cd7a67a4SMauro Carvalho Chehab 		status = set_dvbt_standard(state, o_mode);
17819a0bf528SMauro Carvalho Chehab 		if (status < 0)
17829a0bf528SMauro Carvalho Chehab 			goto error;
17839a0bf528SMauro Carvalho Chehab 		break;
17849a0bf528SMauro Carvalho Chehab 	case OM_QAM_ITU_A:	/* fallthrough */
17859a0bf528SMauro Carvalho Chehab 	case OM_QAM_ITU_C:
17869a0bf528SMauro Carvalho Chehab 		dprintk(1, ": DVB-C Annex %c\n",
1787cd7a67a4SMauro Carvalho Chehab 			(state->m_operation_mode == OM_QAM_ITU_A) ? 'A' : 'C');
1788cd7a67a4SMauro Carvalho Chehab 		state->m_operation_mode = o_mode;
1789cd7a67a4SMauro Carvalho Chehab 		status = set_qam_standard(state, o_mode);
17909a0bf528SMauro Carvalho Chehab 		if (status < 0)
17919a0bf528SMauro Carvalho Chehab 			goto error;
17929a0bf528SMauro Carvalho Chehab 		break;
17939a0bf528SMauro Carvalho Chehab 	case OM_QAM_ITU_B:
17949a0bf528SMauro Carvalho Chehab 	default:
17959a0bf528SMauro Carvalho Chehab 		status = -EINVAL;
17969a0bf528SMauro Carvalho Chehab 	}
17979a0bf528SMauro Carvalho Chehab error:
17989a0bf528SMauro Carvalho Chehab 	if (status < 0)
17993a4398f5SMauro Carvalho Chehab 		pr_err("Error %d on %s\n", status, __func__);
18009a0bf528SMauro Carvalho Chehab 	return status;
18019a0bf528SMauro Carvalho Chehab }
18029a0bf528SMauro Carvalho Chehab 
1803cd7a67a4SMauro Carvalho Chehab static int start(struct drxk_state *state, s32 offset_freq,
1804cd7a67a4SMauro Carvalho Chehab 		 s32 intermediate_frequency)
18059a0bf528SMauro Carvalho Chehab {
18069a0bf528SMauro Carvalho Chehab 	int status = -EINVAL;
18079a0bf528SMauro Carvalho Chehab 
1808cd7a67a4SMauro Carvalho Chehab 	u16 i_freqk_hz;
1809cd7a67a4SMauro Carvalho Chehab 	s32 offsetk_hz = offset_freq / 1000;
18109a0bf528SMauro Carvalho Chehab 
18119a0bf528SMauro Carvalho Chehab 	dprintk(1, "\n");
1812cd7a67a4SMauro Carvalho Chehab 	if (state->m_drxk_state != DRXK_STOPPED &&
1813cd7a67a4SMauro Carvalho Chehab 		state->m_drxk_state != DRXK_DTV_STARTED)
18149a0bf528SMauro Carvalho Chehab 		goto error;
18159a0bf528SMauro Carvalho Chehab 
1816cd7a67a4SMauro Carvalho Chehab 	state->m_b_mirror_freq_spect = (state->props.inversion == INVERSION_ON);
18179a0bf528SMauro Carvalho Chehab 
1818cd7a67a4SMauro Carvalho Chehab 	if (intermediate_frequency < 0) {
1819cd7a67a4SMauro Carvalho Chehab 		state->m_b_mirror_freq_spect = !state->m_b_mirror_freq_spect;
1820cd7a67a4SMauro Carvalho Chehab 		intermediate_frequency = -intermediate_frequency;
18219a0bf528SMauro Carvalho Chehab 	}
18229a0bf528SMauro Carvalho Chehab 
1823cd7a67a4SMauro Carvalho Chehab 	switch (state->m_operation_mode) {
18249a0bf528SMauro Carvalho Chehab 	case OM_QAM_ITU_A:
18259a0bf528SMauro Carvalho Chehab 	case OM_QAM_ITU_C:
1826cd7a67a4SMauro Carvalho Chehab 		i_freqk_hz = (intermediate_frequency / 1000);
1827cd7a67a4SMauro Carvalho Chehab 		status = set_qam(state, i_freqk_hz, offsetk_hz);
18289a0bf528SMauro Carvalho Chehab 		if (status < 0)
18299a0bf528SMauro Carvalho Chehab 			goto error;
1830cd7a67a4SMauro Carvalho Chehab 		state->m_drxk_state = DRXK_DTV_STARTED;
18319a0bf528SMauro Carvalho Chehab 		break;
18329a0bf528SMauro Carvalho Chehab 	case OM_DVBT:
1833cd7a67a4SMauro Carvalho Chehab 		i_freqk_hz = (intermediate_frequency / 1000);
1834cd7a67a4SMauro Carvalho Chehab 		status = mpegts_stop(state);
18359a0bf528SMauro Carvalho Chehab 		if (status < 0)
18369a0bf528SMauro Carvalho Chehab 			goto error;
1837cd7a67a4SMauro Carvalho Chehab 		status = set_dvbt(state, i_freqk_hz, offsetk_hz);
18389a0bf528SMauro Carvalho Chehab 		if (status < 0)
18399a0bf528SMauro Carvalho Chehab 			goto error;
1840cd7a67a4SMauro Carvalho Chehab 		status = dvbt_start(state);
18419a0bf528SMauro Carvalho Chehab 		if (status < 0)
18429a0bf528SMauro Carvalho Chehab 			goto error;
1843cd7a67a4SMauro Carvalho Chehab 		state->m_drxk_state = DRXK_DTV_STARTED;
18449a0bf528SMauro Carvalho Chehab 		break;
18459a0bf528SMauro Carvalho Chehab 	default:
18469a0bf528SMauro Carvalho Chehab 		break;
18479a0bf528SMauro Carvalho Chehab 	}
18489a0bf528SMauro Carvalho Chehab error:
18499a0bf528SMauro Carvalho Chehab 	if (status < 0)
18503a4398f5SMauro Carvalho Chehab 		pr_err("Error %d on %s\n", status, __func__);
18519a0bf528SMauro Carvalho Chehab 	return status;
18529a0bf528SMauro Carvalho Chehab }
18539a0bf528SMauro Carvalho Chehab 
1854cd7a67a4SMauro Carvalho Chehab static int shut_down(struct drxk_state *state)
18559a0bf528SMauro Carvalho Chehab {
18569a0bf528SMauro Carvalho Chehab 	dprintk(1, "\n");
18579a0bf528SMauro Carvalho Chehab 
1858cd7a67a4SMauro Carvalho Chehab 	mpegts_stop(state);
18599a0bf528SMauro Carvalho Chehab 	return 0;
18609a0bf528SMauro Carvalho Chehab }
18619a0bf528SMauro Carvalho Chehab 
1862cd7a67a4SMauro Carvalho Chehab static int get_lock_status(struct drxk_state *state, u32 *p_lock_status)
18639a0bf528SMauro Carvalho Chehab {
18649a0bf528SMauro Carvalho Chehab 	int status = -EINVAL;
18659a0bf528SMauro Carvalho Chehab 
18669a0bf528SMauro Carvalho Chehab 	dprintk(1, "\n");
18679a0bf528SMauro Carvalho Chehab 
1868cd7a67a4SMauro Carvalho Chehab 	if (p_lock_status == NULL)
18699a0bf528SMauro Carvalho Chehab 		goto error;
18709a0bf528SMauro Carvalho Chehab 
1871cd7a67a4SMauro Carvalho Chehab 	*p_lock_status = NOT_LOCKED;
18729a0bf528SMauro Carvalho Chehab 
18739a0bf528SMauro Carvalho Chehab 	/* define the SCU command code */
1874cd7a67a4SMauro Carvalho Chehab 	switch (state->m_operation_mode) {
18759a0bf528SMauro Carvalho Chehab 	case OM_QAM_ITU_A:
18769a0bf528SMauro Carvalho Chehab 	case OM_QAM_ITU_B:
18779a0bf528SMauro Carvalho Chehab 	case OM_QAM_ITU_C:
1878cd7a67a4SMauro Carvalho Chehab 		status = get_qam_lock_status(state, p_lock_status);
18799a0bf528SMauro Carvalho Chehab 		break;
18809a0bf528SMauro Carvalho Chehab 	case OM_DVBT:
1881cd7a67a4SMauro Carvalho Chehab 		status = get_dvbt_lock_status(state, p_lock_status);
18829a0bf528SMauro Carvalho Chehab 		break;
18839a0bf528SMauro Carvalho Chehab 	default:
18849a0bf528SMauro Carvalho Chehab 		break;
18859a0bf528SMauro Carvalho Chehab 	}
18869a0bf528SMauro Carvalho Chehab error:
18879a0bf528SMauro Carvalho Chehab 	if (status < 0)
18883a4398f5SMauro Carvalho Chehab 		pr_err("Error %d on %s\n", status, __func__);
18899a0bf528SMauro Carvalho Chehab 	return status;
18909a0bf528SMauro Carvalho Chehab }
18919a0bf528SMauro Carvalho Chehab 
1892cd7a67a4SMauro Carvalho Chehab static int mpegts_start(struct drxk_state *state)
18939a0bf528SMauro Carvalho Chehab {
18949a0bf528SMauro Carvalho Chehab 	int status;
18959a0bf528SMauro Carvalho Chehab 
1896cd7a67a4SMauro Carvalho Chehab 	u16 fec_oc_snc_mode = 0;
18979a0bf528SMauro Carvalho Chehab 
18989a0bf528SMauro Carvalho Chehab 	/* Allow OC to sync again */
1899cd7a67a4SMauro Carvalho Chehab 	status = read16(state, FEC_OC_SNC_MODE__A, &fec_oc_snc_mode);
19009a0bf528SMauro Carvalho Chehab 	if (status < 0)
19019a0bf528SMauro Carvalho Chehab 		goto error;
1902cd7a67a4SMauro Carvalho Chehab 	fec_oc_snc_mode &= ~FEC_OC_SNC_MODE_SHUTDOWN__M;
1903cd7a67a4SMauro Carvalho Chehab 	status = write16(state, FEC_OC_SNC_MODE__A, fec_oc_snc_mode);
19049a0bf528SMauro Carvalho Chehab 	if (status < 0)
19059a0bf528SMauro Carvalho Chehab 		goto error;
19069a0bf528SMauro Carvalho Chehab 	status = write16(state, FEC_OC_SNC_UNLOCK__A, 1);
19079a0bf528SMauro Carvalho Chehab error:
19089a0bf528SMauro Carvalho Chehab 	if (status < 0)
19093a4398f5SMauro Carvalho Chehab 		pr_err("Error %d on %s\n", status, __func__);
19109a0bf528SMauro Carvalho Chehab 	return status;
19119a0bf528SMauro Carvalho Chehab }
19129a0bf528SMauro Carvalho Chehab 
1913cd7a67a4SMauro Carvalho Chehab static int mpegts_dto_init(struct drxk_state *state)
19149a0bf528SMauro Carvalho Chehab {
19159a0bf528SMauro Carvalho Chehab 	int status;
19169a0bf528SMauro Carvalho Chehab 
19179a0bf528SMauro Carvalho Chehab 	dprintk(1, "\n");
19189a0bf528SMauro Carvalho Chehab 
19199a0bf528SMauro Carvalho Chehab 	/* Rate integration settings */
19209a0bf528SMauro Carvalho Chehab 	status = write16(state, FEC_OC_RCN_CTL_STEP_LO__A, 0x0000);
19219a0bf528SMauro Carvalho Chehab 	if (status < 0)
19229a0bf528SMauro Carvalho Chehab 		goto error;
19239a0bf528SMauro Carvalho Chehab 	status = write16(state, FEC_OC_RCN_CTL_STEP_HI__A, 0x000C);
19249a0bf528SMauro Carvalho Chehab 	if (status < 0)
19259a0bf528SMauro Carvalho Chehab 		goto error;
19269a0bf528SMauro Carvalho Chehab 	status = write16(state, FEC_OC_RCN_GAIN__A, 0x000A);
19279a0bf528SMauro Carvalho Chehab 	if (status < 0)
19289a0bf528SMauro Carvalho Chehab 		goto error;
19299a0bf528SMauro Carvalho Chehab 	status = write16(state, FEC_OC_AVR_PARM_A__A, 0x0008);
19309a0bf528SMauro Carvalho Chehab 	if (status < 0)
19319a0bf528SMauro Carvalho Chehab 		goto error;
19329a0bf528SMauro Carvalho Chehab 	status = write16(state, FEC_OC_AVR_PARM_B__A, 0x0006);
19339a0bf528SMauro Carvalho Chehab 	if (status < 0)
19349a0bf528SMauro Carvalho Chehab 		goto error;
19359a0bf528SMauro Carvalho Chehab 	status = write16(state, FEC_OC_TMD_HI_MARGIN__A, 0x0680);
19369a0bf528SMauro Carvalho Chehab 	if (status < 0)
19379a0bf528SMauro Carvalho Chehab 		goto error;
19389a0bf528SMauro Carvalho Chehab 	status = write16(state, FEC_OC_TMD_LO_MARGIN__A, 0x0080);
19399a0bf528SMauro Carvalho Chehab 	if (status < 0)
19409a0bf528SMauro Carvalho Chehab 		goto error;
19419a0bf528SMauro Carvalho Chehab 	status = write16(state, FEC_OC_TMD_COUNT__A, 0x03F4);
19429a0bf528SMauro Carvalho Chehab 	if (status < 0)
19439a0bf528SMauro Carvalho Chehab 		goto error;
19449a0bf528SMauro Carvalho Chehab 
19459a0bf528SMauro Carvalho Chehab 	/* Additional configuration */
19469a0bf528SMauro Carvalho Chehab 	status = write16(state, FEC_OC_OCR_INVERT__A, 0);
19479a0bf528SMauro Carvalho Chehab 	if (status < 0)
19489a0bf528SMauro Carvalho Chehab 		goto error;
19499a0bf528SMauro Carvalho Chehab 	status = write16(state, FEC_OC_SNC_LWM__A, 2);
19509a0bf528SMauro Carvalho Chehab 	if (status < 0)
19519a0bf528SMauro Carvalho Chehab 		goto error;
19529a0bf528SMauro Carvalho Chehab 	status = write16(state, FEC_OC_SNC_HWM__A, 12);
19539a0bf528SMauro Carvalho Chehab error:
19549a0bf528SMauro Carvalho Chehab 	if (status < 0)
19553a4398f5SMauro Carvalho Chehab 		pr_err("Error %d on %s\n", status, __func__);
19569a0bf528SMauro Carvalho Chehab 
19579a0bf528SMauro Carvalho Chehab 	return status;
19589a0bf528SMauro Carvalho Chehab }
19599a0bf528SMauro Carvalho Chehab 
1960cd7a67a4SMauro Carvalho Chehab static int mpegts_dto_setup(struct drxk_state *state,
1961cd7a67a4SMauro Carvalho Chehab 			  enum operation_mode o_mode)
19629a0bf528SMauro Carvalho Chehab {
19639a0bf528SMauro Carvalho Chehab 	int status;
19649a0bf528SMauro Carvalho Chehab 
1965cd7a67a4SMauro Carvalho Chehab 	u16 fec_oc_reg_mode = 0;	/* FEC_OC_MODE       register value */
1966cd7a67a4SMauro Carvalho Chehab 	u16 fec_oc_reg_ipr_mode = 0;	/* FEC_OC_IPR_MODE   register value */
1967cd7a67a4SMauro Carvalho Chehab 	u16 fec_oc_dto_mode = 0;	/* FEC_OC_IPR_INVERT register value */
1968cd7a67a4SMauro Carvalho Chehab 	u16 fec_oc_fct_mode = 0;	/* FEC_OC_IPR_INVERT register value */
1969cd7a67a4SMauro Carvalho Chehab 	u16 fec_oc_dto_period = 2;	/* FEC_OC_IPR_INVERT register value */
1970cd7a67a4SMauro Carvalho Chehab 	u16 fec_oc_dto_burst_len = 188;	/* FEC_OC_IPR_INVERT register value */
1971cd7a67a4SMauro Carvalho Chehab 	u32 fec_oc_rcn_ctl_rate = 0;	/* FEC_OC_IPR_INVERT register value */
1972cd7a67a4SMauro Carvalho Chehab 	u16 fec_oc_tmd_mode = 0;
1973cd7a67a4SMauro Carvalho Chehab 	u16 fec_oc_tmd_int_upd_rate = 0;
1974cd7a67a4SMauro Carvalho Chehab 	u32 max_bit_rate = 0;
1975cd7a67a4SMauro Carvalho Chehab 	bool static_clk = false;
19769a0bf528SMauro Carvalho Chehab 
19779a0bf528SMauro Carvalho Chehab 	dprintk(1, "\n");
19789a0bf528SMauro Carvalho Chehab 
19799a0bf528SMauro Carvalho Chehab 	/* Check insertion of the Reed-Solomon parity bytes */
1980cd7a67a4SMauro Carvalho Chehab 	status = read16(state, FEC_OC_MODE__A, &fec_oc_reg_mode);
19819a0bf528SMauro Carvalho Chehab 	if (status < 0)
19829a0bf528SMauro Carvalho Chehab 		goto error;
1983cd7a67a4SMauro Carvalho Chehab 	status = read16(state, FEC_OC_IPR_MODE__A, &fec_oc_reg_ipr_mode);
19849a0bf528SMauro Carvalho Chehab 	if (status < 0)
19859a0bf528SMauro Carvalho Chehab 		goto error;
1986cd7a67a4SMauro Carvalho Chehab 	fec_oc_reg_mode &= (~FEC_OC_MODE_PARITY__M);
1987cd7a67a4SMauro Carvalho Chehab 	fec_oc_reg_ipr_mode &= (~FEC_OC_IPR_MODE_MVAL_DIS_PAR__M);
1988cd7a67a4SMauro Carvalho Chehab 	if (state->m_insert_rs_byte == true) {
19899a0bf528SMauro Carvalho Chehab 		/* enable parity symbol forward */
1990cd7a67a4SMauro Carvalho Chehab 		fec_oc_reg_mode |= FEC_OC_MODE_PARITY__M;
19919a0bf528SMauro Carvalho Chehab 		/* MVAL disable during parity bytes */
1992cd7a67a4SMauro Carvalho Chehab 		fec_oc_reg_ipr_mode |= FEC_OC_IPR_MODE_MVAL_DIS_PAR__M;
19939a0bf528SMauro Carvalho Chehab 		/* TS burst length to 204 */
1994cd7a67a4SMauro Carvalho Chehab 		fec_oc_dto_burst_len = 204;
19959a0bf528SMauro Carvalho Chehab 	}
19969a0bf528SMauro Carvalho Chehab 
19979a0bf528SMauro Carvalho Chehab 	/* Check serial or parrallel output */
1998cd7a67a4SMauro Carvalho Chehab 	fec_oc_reg_ipr_mode &= (~(FEC_OC_IPR_MODE_SERIAL__M));
1999cd7a67a4SMauro Carvalho Chehab 	if (state->m_enable_parallel == false) {
20009a0bf528SMauro Carvalho Chehab 		/* MPEG data output is serial -> set ipr_mode[0] */
2001cd7a67a4SMauro Carvalho Chehab 		fec_oc_reg_ipr_mode |= FEC_OC_IPR_MODE_SERIAL__M;
20029a0bf528SMauro Carvalho Chehab 	}
20039a0bf528SMauro Carvalho Chehab 
2004cd7a67a4SMauro Carvalho Chehab 	switch (o_mode) {
20059a0bf528SMauro Carvalho Chehab 	case OM_DVBT:
2006cd7a67a4SMauro Carvalho Chehab 		max_bit_rate = state->m_dvbt_bitrate;
2007cd7a67a4SMauro Carvalho Chehab 		fec_oc_tmd_mode = 3;
2008cd7a67a4SMauro Carvalho Chehab 		fec_oc_rcn_ctl_rate = 0xC00000;
2009cd7a67a4SMauro Carvalho Chehab 		static_clk = state->m_dvbt_static_clk;
20109a0bf528SMauro Carvalho Chehab 		break;
20119a0bf528SMauro Carvalho Chehab 	case OM_QAM_ITU_A:	/* fallthrough */
20129a0bf528SMauro Carvalho Chehab 	case OM_QAM_ITU_C:
2013cd7a67a4SMauro Carvalho Chehab 		fec_oc_tmd_mode = 0x0004;
2014cd7a67a4SMauro Carvalho Chehab 		fec_oc_rcn_ctl_rate = 0xD2B4EE;	/* good for >63 Mb/s */
2015cd7a67a4SMauro Carvalho Chehab 		max_bit_rate = state->m_dvbc_bitrate;
2016cd7a67a4SMauro Carvalho Chehab 		static_clk = state->m_dvbc_static_clk;
20179a0bf528SMauro Carvalho Chehab 		break;
20189a0bf528SMauro Carvalho Chehab 	default:
20199a0bf528SMauro Carvalho Chehab 		status = -EINVAL;
20209a0bf528SMauro Carvalho Chehab 	}		/* switch (standard) */
20219a0bf528SMauro Carvalho Chehab 	if (status < 0)
20229a0bf528SMauro Carvalho Chehab 		goto error;
20239a0bf528SMauro Carvalho Chehab 
20249a0bf528SMauro Carvalho Chehab 	/* Configure DTO's */
2025cd7a67a4SMauro Carvalho Chehab 	if (static_clk) {
2026cd7a67a4SMauro Carvalho Chehab 		u32 bit_rate = 0;
20279a0bf528SMauro Carvalho Chehab 
20289a0bf528SMauro Carvalho Chehab 		/* Rational DTO for MCLK source (static MCLK rate),
20299a0bf528SMauro Carvalho Chehab 			Dynamic DTO for optimal grouping
20309a0bf528SMauro Carvalho Chehab 			(avoid intra-packet gaps),
20319a0bf528SMauro Carvalho Chehab 			DTO offset enable to sync TS burst with MSTRT */
2032cd7a67a4SMauro Carvalho Chehab 		fec_oc_dto_mode = (FEC_OC_DTO_MODE_DYNAMIC__M |
20339a0bf528SMauro Carvalho Chehab 				FEC_OC_DTO_MODE_OFFSET_ENABLE__M);
2034cd7a67a4SMauro Carvalho Chehab 		fec_oc_fct_mode = (FEC_OC_FCT_MODE_RAT_ENA__M |
20359a0bf528SMauro Carvalho Chehab 				FEC_OC_FCT_MODE_VIRT_ENA__M);
20369a0bf528SMauro Carvalho Chehab 
20379a0bf528SMauro Carvalho Chehab 		/* Check user defined bitrate */
2038cd7a67a4SMauro Carvalho Chehab 		bit_rate = max_bit_rate;
2039cd7a67a4SMauro Carvalho Chehab 		if (bit_rate > 75900000UL) {	/* max is 75.9 Mb/s */
2040cd7a67a4SMauro Carvalho Chehab 			bit_rate = 75900000UL;
20419a0bf528SMauro Carvalho Chehab 		}
20429a0bf528SMauro Carvalho Chehab 		/* Rational DTO period:
20439a0bf528SMauro Carvalho Chehab 			dto_period = (Fsys / bitrate) - 2
20449a0bf528SMauro Carvalho Chehab 
2045cd7a67a4SMauro Carvalho Chehab 			result should be floored,
20469a0bf528SMauro Carvalho Chehab 			to make sure >= requested bitrate
20479a0bf528SMauro Carvalho Chehab 			*/
2048cd7a67a4SMauro Carvalho Chehab 		fec_oc_dto_period = (u16) (((state->m_sys_clock_freq)
2049cd7a67a4SMauro Carvalho Chehab 						* 1000) / bit_rate);
2050cd7a67a4SMauro Carvalho Chehab 		if (fec_oc_dto_period <= 2)
2051cd7a67a4SMauro Carvalho Chehab 			fec_oc_dto_period = 0;
20529a0bf528SMauro Carvalho Chehab 		else
2053cd7a67a4SMauro Carvalho Chehab 			fec_oc_dto_period -= 2;
2054cd7a67a4SMauro Carvalho Chehab 		fec_oc_tmd_int_upd_rate = 8;
20559a0bf528SMauro Carvalho Chehab 	} else {
2056cd7a67a4SMauro Carvalho Chehab 		/* (commonAttr->static_clk == false) => dynamic mode */
2057cd7a67a4SMauro Carvalho Chehab 		fec_oc_dto_mode = FEC_OC_DTO_MODE_DYNAMIC__M;
2058cd7a67a4SMauro Carvalho Chehab 		fec_oc_fct_mode = FEC_OC_FCT_MODE__PRE;
2059cd7a67a4SMauro Carvalho Chehab 		fec_oc_tmd_int_upd_rate = 5;
20609a0bf528SMauro Carvalho Chehab 	}
20619a0bf528SMauro Carvalho Chehab 
20629a0bf528SMauro Carvalho Chehab 	/* Write appropriate registers with requested configuration */
2063cd7a67a4SMauro Carvalho Chehab 	status = write16(state, FEC_OC_DTO_BURST_LEN__A, fec_oc_dto_burst_len);
20649a0bf528SMauro Carvalho Chehab 	if (status < 0)
20659a0bf528SMauro Carvalho Chehab 		goto error;
2066cd7a67a4SMauro Carvalho Chehab 	status = write16(state, FEC_OC_DTO_PERIOD__A, fec_oc_dto_period);
20679a0bf528SMauro Carvalho Chehab 	if (status < 0)
20689a0bf528SMauro Carvalho Chehab 		goto error;
2069cd7a67a4SMauro Carvalho Chehab 	status = write16(state, FEC_OC_DTO_MODE__A, fec_oc_dto_mode);
20709a0bf528SMauro Carvalho Chehab 	if (status < 0)
20719a0bf528SMauro Carvalho Chehab 		goto error;
2072cd7a67a4SMauro Carvalho Chehab 	status = write16(state, FEC_OC_FCT_MODE__A, fec_oc_fct_mode);
20739a0bf528SMauro Carvalho Chehab 	if (status < 0)
20749a0bf528SMauro Carvalho Chehab 		goto error;
2075cd7a67a4SMauro Carvalho Chehab 	status = write16(state, FEC_OC_MODE__A, fec_oc_reg_mode);
20769a0bf528SMauro Carvalho Chehab 	if (status < 0)
20779a0bf528SMauro Carvalho Chehab 		goto error;
2078cd7a67a4SMauro Carvalho Chehab 	status = write16(state, FEC_OC_IPR_MODE__A, fec_oc_reg_ipr_mode);
20799a0bf528SMauro Carvalho Chehab 	if (status < 0)
20809a0bf528SMauro Carvalho Chehab 		goto error;
20819a0bf528SMauro Carvalho Chehab 
20829a0bf528SMauro Carvalho Chehab 	/* Rate integration settings */
2083cd7a67a4SMauro Carvalho Chehab 	status = write32(state, FEC_OC_RCN_CTL_RATE_LO__A, fec_oc_rcn_ctl_rate);
20849a0bf528SMauro Carvalho Chehab 	if (status < 0)
20859a0bf528SMauro Carvalho Chehab 		goto error;
2086cd7a67a4SMauro Carvalho Chehab 	status = write16(state, FEC_OC_TMD_INT_UPD_RATE__A, fec_oc_tmd_int_upd_rate);
20879a0bf528SMauro Carvalho Chehab 	if (status < 0)
20889a0bf528SMauro Carvalho Chehab 		goto error;
2089cd7a67a4SMauro Carvalho Chehab 	status = write16(state, FEC_OC_TMD_MODE__A, fec_oc_tmd_mode);
20909a0bf528SMauro Carvalho Chehab error:
20919a0bf528SMauro Carvalho Chehab 	if (status < 0)
20923a4398f5SMauro Carvalho Chehab 		pr_err("Error %d on %s\n", status, __func__);
20939a0bf528SMauro Carvalho Chehab 	return status;
20949a0bf528SMauro Carvalho Chehab }
20959a0bf528SMauro Carvalho Chehab 
2096cd7a67a4SMauro Carvalho Chehab static int mpegts_configure_polarity(struct drxk_state *state)
20979a0bf528SMauro Carvalho Chehab {
2098cd7a67a4SMauro Carvalho Chehab 	u16 fec_oc_reg_ipr_invert = 0;
20999a0bf528SMauro Carvalho Chehab 
21009a0bf528SMauro Carvalho Chehab 	/* Data mask for the output data byte */
2101cd7a67a4SMauro Carvalho Chehab 	u16 invert_data_mask =
21029a0bf528SMauro Carvalho Chehab 	    FEC_OC_IPR_INVERT_MD7__M | FEC_OC_IPR_INVERT_MD6__M |
21039a0bf528SMauro Carvalho Chehab 	    FEC_OC_IPR_INVERT_MD5__M | FEC_OC_IPR_INVERT_MD4__M |
21049a0bf528SMauro Carvalho Chehab 	    FEC_OC_IPR_INVERT_MD3__M | FEC_OC_IPR_INVERT_MD2__M |
21059a0bf528SMauro Carvalho Chehab 	    FEC_OC_IPR_INVERT_MD1__M | FEC_OC_IPR_INVERT_MD0__M;
21069a0bf528SMauro Carvalho Chehab 
21079a0bf528SMauro Carvalho Chehab 	dprintk(1, "\n");
21089a0bf528SMauro Carvalho Chehab 
21099a0bf528SMauro Carvalho Chehab 	/* Control selective inversion of output bits */
2110cd7a67a4SMauro Carvalho Chehab 	fec_oc_reg_ipr_invert &= (~(invert_data_mask));
2111cd7a67a4SMauro Carvalho Chehab 	if (state->m_invert_data == true)
2112cd7a67a4SMauro Carvalho Chehab 		fec_oc_reg_ipr_invert |= invert_data_mask;
2113cd7a67a4SMauro Carvalho Chehab 	fec_oc_reg_ipr_invert &= (~(FEC_OC_IPR_INVERT_MERR__M));
2114cd7a67a4SMauro Carvalho Chehab 	if (state->m_invert_err == true)
2115cd7a67a4SMauro Carvalho Chehab 		fec_oc_reg_ipr_invert |= FEC_OC_IPR_INVERT_MERR__M;
2116cd7a67a4SMauro Carvalho Chehab 	fec_oc_reg_ipr_invert &= (~(FEC_OC_IPR_INVERT_MSTRT__M));
2117cd7a67a4SMauro Carvalho Chehab 	if (state->m_invert_str == true)
2118cd7a67a4SMauro Carvalho Chehab 		fec_oc_reg_ipr_invert |= FEC_OC_IPR_INVERT_MSTRT__M;
2119cd7a67a4SMauro Carvalho Chehab 	fec_oc_reg_ipr_invert &= (~(FEC_OC_IPR_INVERT_MVAL__M));
2120cd7a67a4SMauro Carvalho Chehab 	if (state->m_invert_val == true)
2121cd7a67a4SMauro Carvalho Chehab 		fec_oc_reg_ipr_invert |= FEC_OC_IPR_INVERT_MVAL__M;
2122cd7a67a4SMauro Carvalho Chehab 	fec_oc_reg_ipr_invert &= (~(FEC_OC_IPR_INVERT_MCLK__M));
2123cd7a67a4SMauro Carvalho Chehab 	if (state->m_invert_clk == true)
2124cd7a67a4SMauro Carvalho Chehab 		fec_oc_reg_ipr_invert |= FEC_OC_IPR_INVERT_MCLK__M;
21259a0bf528SMauro Carvalho Chehab 
2126cd7a67a4SMauro Carvalho Chehab 	return write16(state, FEC_OC_IPR_INVERT__A, fec_oc_reg_ipr_invert);
21279a0bf528SMauro Carvalho Chehab }
21289a0bf528SMauro Carvalho Chehab 
21299a0bf528SMauro Carvalho Chehab #define   SCU_RAM_AGC_KI_INV_RF_POL__M 0x4000
21309a0bf528SMauro Carvalho Chehab 
2131cd7a67a4SMauro Carvalho Chehab static int set_agc_rf(struct drxk_state *state,
2132cd7a67a4SMauro Carvalho Chehab 		    struct s_cfg_agc *p_agc_cfg, bool is_dtv)
21339a0bf528SMauro Carvalho Chehab {
21349a0bf528SMauro Carvalho Chehab 	int status = -EINVAL;
21359a0bf528SMauro Carvalho Chehab 	u16 data = 0;
2136cd7a67a4SMauro Carvalho Chehab 	struct s_cfg_agc *p_if_agc_settings;
21379a0bf528SMauro Carvalho Chehab 
21389a0bf528SMauro Carvalho Chehab 	dprintk(1, "\n");
21399a0bf528SMauro Carvalho Chehab 
2140cd7a67a4SMauro Carvalho Chehab 	if (p_agc_cfg == NULL)
21419a0bf528SMauro Carvalho Chehab 		goto error;
21429a0bf528SMauro Carvalho Chehab 
2143cd7a67a4SMauro Carvalho Chehab 	switch (p_agc_cfg->ctrl_mode) {
21449a0bf528SMauro Carvalho Chehab 	case DRXK_AGC_CTRL_AUTO:
21459a0bf528SMauro Carvalho Chehab 		/* Enable RF AGC DAC */
21469a0bf528SMauro Carvalho Chehab 		status = read16(state, IQM_AF_STDBY__A, &data);
21479a0bf528SMauro Carvalho Chehab 		if (status < 0)
21489a0bf528SMauro Carvalho Chehab 			goto error;
21499a0bf528SMauro Carvalho Chehab 		data &= ~IQM_AF_STDBY_STDBY_TAGC_RF_STANDBY;
21509a0bf528SMauro Carvalho Chehab 		status = write16(state, IQM_AF_STDBY__A, data);
21519a0bf528SMauro Carvalho Chehab 		if (status < 0)
21529a0bf528SMauro Carvalho Chehab 			goto error;
21539a0bf528SMauro Carvalho Chehab 		status = read16(state, SCU_RAM_AGC_CONFIG__A, &data);
21549a0bf528SMauro Carvalho Chehab 		if (status < 0)
21559a0bf528SMauro Carvalho Chehab 			goto error;
21569a0bf528SMauro Carvalho Chehab 
21579a0bf528SMauro Carvalho Chehab 		/* Enable SCU RF AGC loop */
21589a0bf528SMauro Carvalho Chehab 		data &= ~SCU_RAM_AGC_CONFIG_DISABLE_RF_AGC__M;
21599a0bf528SMauro Carvalho Chehab 
21609a0bf528SMauro Carvalho Chehab 		/* Polarity */
2161cd7a67a4SMauro Carvalho Chehab 		if (state->m_rf_agc_pol)
21629a0bf528SMauro Carvalho Chehab 			data |= SCU_RAM_AGC_CONFIG_INV_RF_POL__M;
21639a0bf528SMauro Carvalho Chehab 		else
21649a0bf528SMauro Carvalho Chehab 			data &= ~SCU_RAM_AGC_CONFIG_INV_RF_POL__M;
21659a0bf528SMauro Carvalho Chehab 		status = write16(state, SCU_RAM_AGC_CONFIG__A, data);
21669a0bf528SMauro Carvalho Chehab 		if (status < 0)
21679a0bf528SMauro Carvalho Chehab 			goto error;
21689a0bf528SMauro Carvalho Chehab 
21699a0bf528SMauro Carvalho Chehab 		/* Set speed (using complementary reduction value) */
21709a0bf528SMauro Carvalho Chehab 		status = read16(state, SCU_RAM_AGC_KI_RED__A, &data);
21719a0bf528SMauro Carvalho Chehab 		if (status < 0)
21729a0bf528SMauro Carvalho Chehab 			goto error;
21739a0bf528SMauro Carvalho Chehab 
21749a0bf528SMauro Carvalho Chehab 		data &= ~SCU_RAM_AGC_KI_RED_RAGC_RED__M;
2175cd7a67a4SMauro Carvalho Chehab 		data |= (~(p_agc_cfg->speed <<
21769a0bf528SMauro Carvalho Chehab 				SCU_RAM_AGC_KI_RED_RAGC_RED__B)
21779a0bf528SMauro Carvalho Chehab 				& SCU_RAM_AGC_KI_RED_RAGC_RED__M);
21789a0bf528SMauro Carvalho Chehab 
21799a0bf528SMauro Carvalho Chehab 		status = write16(state, SCU_RAM_AGC_KI_RED__A, data);
21809a0bf528SMauro Carvalho Chehab 		if (status < 0)
21819a0bf528SMauro Carvalho Chehab 			goto error;
21829a0bf528SMauro Carvalho Chehab 
2183cd7a67a4SMauro Carvalho Chehab 		if (is_dvbt(state))
2184cd7a67a4SMauro Carvalho Chehab 			p_if_agc_settings = &state->m_dvbt_if_agc_cfg;
2185cd7a67a4SMauro Carvalho Chehab 		else if (is_qam(state))
2186cd7a67a4SMauro Carvalho Chehab 			p_if_agc_settings = &state->m_qam_if_agc_cfg;
21879a0bf528SMauro Carvalho Chehab 		else
2188cd7a67a4SMauro Carvalho Chehab 			p_if_agc_settings = &state->m_atv_if_agc_cfg;
2189cd7a67a4SMauro Carvalho Chehab 		if (p_if_agc_settings == NULL) {
21909a0bf528SMauro Carvalho Chehab 			status = -EINVAL;
21919a0bf528SMauro Carvalho Chehab 			goto error;
21929a0bf528SMauro Carvalho Chehab 		}
21939a0bf528SMauro Carvalho Chehab 
21949a0bf528SMauro Carvalho Chehab 		/* Set TOP, only if IF-AGC is in AUTO mode */
2195cd7a67a4SMauro Carvalho Chehab 		if (p_if_agc_settings->ctrl_mode == DRXK_AGC_CTRL_AUTO)
2196cd7a67a4SMauro Carvalho Chehab 			status = write16(state, SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A, p_agc_cfg->top);
21979a0bf528SMauro Carvalho Chehab 			if (status < 0)
21989a0bf528SMauro Carvalho Chehab 				goto error;
21999a0bf528SMauro Carvalho Chehab 
22009a0bf528SMauro Carvalho Chehab 		/* Cut-Off current */
2201cd7a67a4SMauro Carvalho Chehab 		status = write16(state, SCU_RAM_AGC_RF_IACCU_HI_CO__A, p_agc_cfg->cut_off_current);
22029a0bf528SMauro Carvalho Chehab 		if (status < 0)
22039a0bf528SMauro Carvalho Chehab 			goto error;
22049a0bf528SMauro Carvalho Chehab 
22059a0bf528SMauro Carvalho Chehab 		/* Max. output level */
2206cd7a67a4SMauro Carvalho Chehab 		status = write16(state, SCU_RAM_AGC_RF_MAX__A, p_agc_cfg->max_output_level);
22079a0bf528SMauro Carvalho Chehab 		if (status < 0)
22089a0bf528SMauro Carvalho Chehab 			goto error;
22099a0bf528SMauro Carvalho Chehab 
22109a0bf528SMauro Carvalho Chehab 		break;
22119a0bf528SMauro Carvalho Chehab 
22129a0bf528SMauro Carvalho Chehab 	case DRXK_AGC_CTRL_USER:
22139a0bf528SMauro Carvalho Chehab 		/* Enable RF AGC DAC */
22149a0bf528SMauro Carvalho Chehab 		status = read16(state, IQM_AF_STDBY__A, &data);
22159a0bf528SMauro Carvalho Chehab 		if (status < 0)
22169a0bf528SMauro Carvalho Chehab 			goto error;
22179a0bf528SMauro Carvalho Chehab 		data &= ~IQM_AF_STDBY_STDBY_TAGC_RF_STANDBY;
22189a0bf528SMauro Carvalho Chehab 		status = write16(state, IQM_AF_STDBY__A, data);
22199a0bf528SMauro Carvalho Chehab 		if (status < 0)
22209a0bf528SMauro Carvalho Chehab 			goto error;
22219a0bf528SMauro Carvalho Chehab 
22229a0bf528SMauro Carvalho Chehab 		/* Disable SCU RF AGC loop */
22239a0bf528SMauro Carvalho Chehab 		status = read16(state, SCU_RAM_AGC_CONFIG__A, &data);
22249a0bf528SMauro Carvalho Chehab 		if (status < 0)
22259a0bf528SMauro Carvalho Chehab 			goto error;
22269a0bf528SMauro Carvalho Chehab 		data |= SCU_RAM_AGC_CONFIG_DISABLE_RF_AGC__M;
2227cd7a67a4SMauro Carvalho Chehab 		if (state->m_rf_agc_pol)
22289a0bf528SMauro Carvalho Chehab 			data |= SCU_RAM_AGC_CONFIG_INV_RF_POL__M;
22299a0bf528SMauro Carvalho Chehab 		else
22309a0bf528SMauro Carvalho Chehab 			data &= ~SCU_RAM_AGC_CONFIG_INV_RF_POL__M;
22319a0bf528SMauro Carvalho Chehab 		status = write16(state, SCU_RAM_AGC_CONFIG__A, data);
22329a0bf528SMauro Carvalho Chehab 		if (status < 0)
22339a0bf528SMauro Carvalho Chehab 			goto error;
22349a0bf528SMauro Carvalho Chehab 
22359a0bf528SMauro Carvalho Chehab 		/* SCU c.o.c. to 0, enabling full control range */
22369a0bf528SMauro Carvalho Chehab 		status = write16(state, SCU_RAM_AGC_RF_IACCU_HI_CO__A, 0);
22379a0bf528SMauro Carvalho Chehab 		if (status < 0)
22389a0bf528SMauro Carvalho Chehab 			goto error;
22399a0bf528SMauro Carvalho Chehab 
22409a0bf528SMauro Carvalho Chehab 		/* Write value to output pin */
2241cd7a67a4SMauro Carvalho Chehab 		status = write16(state, SCU_RAM_AGC_RF_IACCU_HI__A, p_agc_cfg->output_level);
22429a0bf528SMauro Carvalho Chehab 		if (status < 0)
22439a0bf528SMauro Carvalho Chehab 			goto error;
22449a0bf528SMauro Carvalho Chehab 		break;
22459a0bf528SMauro Carvalho Chehab 
22469a0bf528SMauro Carvalho Chehab 	case DRXK_AGC_CTRL_OFF:
22479a0bf528SMauro Carvalho Chehab 		/* Disable RF AGC DAC */
22489a0bf528SMauro Carvalho Chehab 		status = read16(state, IQM_AF_STDBY__A, &data);
22499a0bf528SMauro Carvalho Chehab 		if (status < 0)
22509a0bf528SMauro Carvalho Chehab 			goto error;
22519a0bf528SMauro Carvalho Chehab 		data |= IQM_AF_STDBY_STDBY_TAGC_RF_STANDBY;
22529a0bf528SMauro Carvalho Chehab 		status = write16(state, IQM_AF_STDBY__A, data);
22539a0bf528SMauro Carvalho Chehab 		if (status < 0)
22549a0bf528SMauro Carvalho Chehab 			goto error;
22559a0bf528SMauro Carvalho Chehab 
22569a0bf528SMauro Carvalho Chehab 		/* Disable SCU RF AGC loop */
22579a0bf528SMauro Carvalho Chehab 		status = read16(state, SCU_RAM_AGC_CONFIG__A, &data);
22589a0bf528SMauro Carvalho Chehab 		if (status < 0)
22599a0bf528SMauro Carvalho Chehab 			goto error;
22609a0bf528SMauro Carvalho Chehab 		data |= SCU_RAM_AGC_CONFIG_DISABLE_RF_AGC__M;
22619a0bf528SMauro Carvalho Chehab 		status = write16(state, SCU_RAM_AGC_CONFIG__A, data);
22629a0bf528SMauro Carvalho Chehab 		if (status < 0)
22639a0bf528SMauro Carvalho Chehab 			goto error;
22649a0bf528SMauro Carvalho Chehab 		break;
22659a0bf528SMauro Carvalho Chehab 
22669a0bf528SMauro Carvalho Chehab 	default:
22679a0bf528SMauro Carvalho Chehab 		status = -EINVAL;
22689a0bf528SMauro Carvalho Chehab 
22699a0bf528SMauro Carvalho Chehab 	}
22709a0bf528SMauro Carvalho Chehab error:
22719a0bf528SMauro Carvalho Chehab 	if (status < 0)
22723a4398f5SMauro Carvalho Chehab 		pr_err("Error %d on %s\n", status, __func__);
22739a0bf528SMauro Carvalho Chehab 	return status;
22749a0bf528SMauro Carvalho Chehab }
22759a0bf528SMauro Carvalho Chehab 
22769a0bf528SMauro Carvalho Chehab #define SCU_RAM_AGC_KI_INV_IF_POL__M 0x2000
22779a0bf528SMauro Carvalho Chehab 
2278cd7a67a4SMauro Carvalho Chehab static int set_agc_if(struct drxk_state *state,
2279cd7a67a4SMauro Carvalho Chehab 		    struct s_cfg_agc *p_agc_cfg, bool is_dtv)
22809a0bf528SMauro Carvalho Chehab {
22819a0bf528SMauro Carvalho Chehab 	u16 data = 0;
22829a0bf528SMauro Carvalho Chehab 	int status = 0;
2283cd7a67a4SMauro Carvalho Chehab 	struct s_cfg_agc *p_rf_agc_settings;
22849a0bf528SMauro Carvalho Chehab 
22859a0bf528SMauro Carvalho Chehab 	dprintk(1, "\n");
22869a0bf528SMauro Carvalho Chehab 
2287cd7a67a4SMauro Carvalho Chehab 	switch (p_agc_cfg->ctrl_mode) {
22889a0bf528SMauro Carvalho Chehab 	case DRXK_AGC_CTRL_AUTO:
22899a0bf528SMauro Carvalho Chehab 
22909a0bf528SMauro Carvalho Chehab 		/* Enable IF AGC DAC */
22919a0bf528SMauro Carvalho Chehab 		status = read16(state, IQM_AF_STDBY__A, &data);
22929a0bf528SMauro Carvalho Chehab 		if (status < 0)
22939a0bf528SMauro Carvalho Chehab 			goto error;
22949a0bf528SMauro Carvalho Chehab 		data &= ~IQM_AF_STDBY_STDBY_TAGC_IF_STANDBY;
22959a0bf528SMauro Carvalho Chehab 		status = write16(state, IQM_AF_STDBY__A, data);
22969a0bf528SMauro Carvalho Chehab 		if (status < 0)
22979a0bf528SMauro Carvalho Chehab 			goto error;
22989a0bf528SMauro Carvalho Chehab 
22999a0bf528SMauro Carvalho Chehab 		status = read16(state, SCU_RAM_AGC_CONFIG__A, &data);
23009a0bf528SMauro Carvalho Chehab 		if (status < 0)
23019a0bf528SMauro Carvalho Chehab 			goto error;
23029a0bf528SMauro Carvalho Chehab 
23039a0bf528SMauro Carvalho Chehab 		/* Enable SCU IF AGC loop */
23049a0bf528SMauro Carvalho Chehab 		data &= ~SCU_RAM_AGC_CONFIG_DISABLE_IF_AGC__M;
23059a0bf528SMauro Carvalho Chehab 
23069a0bf528SMauro Carvalho Chehab 		/* Polarity */
2307cd7a67a4SMauro Carvalho Chehab 		if (state->m_if_agc_pol)
23089a0bf528SMauro Carvalho Chehab 			data |= SCU_RAM_AGC_CONFIG_INV_IF_POL__M;
23099a0bf528SMauro Carvalho Chehab 		else
23109a0bf528SMauro Carvalho Chehab 			data &= ~SCU_RAM_AGC_CONFIG_INV_IF_POL__M;
23119a0bf528SMauro Carvalho Chehab 		status = write16(state, SCU_RAM_AGC_CONFIG__A, data);
23129a0bf528SMauro Carvalho Chehab 		if (status < 0)
23139a0bf528SMauro Carvalho Chehab 			goto error;
23149a0bf528SMauro Carvalho Chehab 
23159a0bf528SMauro Carvalho Chehab 		/* Set speed (using complementary reduction value) */
23169a0bf528SMauro Carvalho Chehab 		status = read16(state, SCU_RAM_AGC_KI_RED__A, &data);
23179a0bf528SMauro Carvalho Chehab 		if (status < 0)
23189a0bf528SMauro Carvalho Chehab 			goto error;
23199a0bf528SMauro Carvalho Chehab 		data &= ~SCU_RAM_AGC_KI_RED_IAGC_RED__M;
2320cd7a67a4SMauro Carvalho Chehab 		data |= (~(p_agc_cfg->speed <<
23219a0bf528SMauro Carvalho Chehab 				SCU_RAM_AGC_KI_RED_IAGC_RED__B)
23229a0bf528SMauro Carvalho Chehab 				& SCU_RAM_AGC_KI_RED_IAGC_RED__M);
23239a0bf528SMauro Carvalho Chehab 
23249a0bf528SMauro Carvalho Chehab 		status = write16(state, SCU_RAM_AGC_KI_RED__A, data);
23259a0bf528SMauro Carvalho Chehab 		if (status < 0)
23269a0bf528SMauro Carvalho Chehab 			goto error;
23279a0bf528SMauro Carvalho Chehab 
2328cd7a67a4SMauro Carvalho Chehab 		if (is_qam(state))
2329cd7a67a4SMauro Carvalho Chehab 			p_rf_agc_settings = &state->m_qam_rf_agc_cfg;
23309a0bf528SMauro Carvalho Chehab 		else
2331cd7a67a4SMauro Carvalho Chehab 			p_rf_agc_settings = &state->m_atv_rf_agc_cfg;
2332cd7a67a4SMauro Carvalho Chehab 		if (p_rf_agc_settings == NULL)
23339a0bf528SMauro Carvalho Chehab 			return -1;
23349a0bf528SMauro Carvalho Chehab 		/* Restore TOP */
2335cd7a67a4SMauro Carvalho Chehab 		status = write16(state, SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A, p_rf_agc_settings->top);
23369a0bf528SMauro Carvalho Chehab 		if (status < 0)
23379a0bf528SMauro Carvalho Chehab 			goto error;
23389a0bf528SMauro Carvalho Chehab 		break;
23399a0bf528SMauro Carvalho Chehab 
23409a0bf528SMauro Carvalho Chehab 	case DRXK_AGC_CTRL_USER:
23419a0bf528SMauro Carvalho Chehab 
23429a0bf528SMauro Carvalho Chehab 		/* Enable IF AGC DAC */
23439a0bf528SMauro Carvalho Chehab 		status = read16(state, IQM_AF_STDBY__A, &data);
23449a0bf528SMauro Carvalho Chehab 		if (status < 0)
23459a0bf528SMauro Carvalho Chehab 			goto error;
23469a0bf528SMauro Carvalho Chehab 		data &= ~IQM_AF_STDBY_STDBY_TAGC_IF_STANDBY;
23479a0bf528SMauro Carvalho Chehab 		status = write16(state, IQM_AF_STDBY__A, data);
23489a0bf528SMauro Carvalho Chehab 		if (status < 0)
23499a0bf528SMauro Carvalho Chehab 			goto error;
23509a0bf528SMauro Carvalho Chehab 
23519a0bf528SMauro Carvalho Chehab 		status = read16(state, SCU_RAM_AGC_CONFIG__A, &data);
23529a0bf528SMauro Carvalho Chehab 		if (status < 0)
23539a0bf528SMauro Carvalho Chehab 			goto error;
23549a0bf528SMauro Carvalho Chehab 
23559a0bf528SMauro Carvalho Chehab 		/* Disable SCU IF AGC loop */
23569a0bf528SMauro Carvalho Chehab 		data |= SCU_RAM_AGC_CONFIG_DISABLE_IF_AGC__M;
23579a0bf528SMauro Carvalho Chehab 
23589a0bf528SMauro Carvalho Chehab 		/* Polarity */
2359cd7a67a4SMauro Carvalho Chehab 		if (state->m_if_agc_pol)
23609a0bf528SMauro Carvalho Chehab 			data |= SCU_RAM_AGC_CONFIG_INV_IF_POL__M;
23619a0bf528SMauro Carvalho Chehab 		else
23629a0bf528SMauro Carvalho Chehab 			data &= ~SCU_RAM_AGC_CONFIG_INV_IF_POL__M;
23639a0bf528SMauro Carvalho Chehab 		status = write16(state, SCU_RAM_AGC_CONFIG__A, data);
23649a0bf528SMauro Carvalho Chehab 		if (status < 0)
23659a0bf528SMauro Carvalho Chehab 			goto error;
23669a0bf528SMauro Carvalho Chehab 
23679a0bf528SMauro Carvalho Chehab 		/* Write value to output pin */
2368cd7a67a4SMauro Carvalho Chehab 		status = write16(state, SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A, p_agc_cfg->output_level);
23699a0bf528SMauro Carvalho Chehab 		if (status < 0)
23709a0bf528SMauro Carvalho Chehab 			goto error;
23719a0bf528SMauro Carvalho Chehab 		break;
23729a0bf528SMauro Carvalho Chehab 
23739a0bf528SMauro Carvalho Chehab 	case DRXK_AGC_CTRL_OFF:
23749a0bf528SMauro Carvalho Chehab 
23759a0bf528SMauro Carvalho Chehab 		/* Disable If AGC DAC */
23769a0bf528SMauro Carvalho Chehab 		status = read16(state, IQM_AF_STDBY__A, &data);
23779a0bf528SMauro Carvalho Chehab 		if (status < 0)
23789a0bf528SMauro Carvalho Chehab 			goto error;
23799a0bf528SMauro Carvalho Chehab 		data |= IQM_AF_STDBY_STDBY_TAGC_IF_STANDBY;
23809a0bf528SMauro Carvalho Chehab 		status = write16(state, IQM_AF_STDBY__A, data);
23819a0bf528SMauro Carvalho Chehab 		if (status < 0)
23829a0bf528SMauro Carvalho Chehab 			goto error;
23839a0bf528SMauro Carvalho Chehab 
23849a0bf528SMauro Carvalho Chehab 		/* Disable SCU IF AGC loop */
23859a0bf528SMauro Carvalho Chehab 		status = read16(state, SCU_RAM_AGC_CONFIG__A, &data);
23869a0bf528SMauro Carvalho Chehab 		if (status < 0)
23879a0bf528SMauro Carvalho Chehab 			goto error;
23889a0bf528SMauro Carvalho Chehab 		data |= SCU_RAM_AGC_CONFIG_DISABLE_IF_AGC__M;
23899a0bf528SMauro Carvalho Chehab 		status = write16(state, SCU_RAM_AGC_CONFIG__A, data);
23909a0bf528SMauro Carvalho Chehab 		if (status < 0)
23919a0bf528SMauro Carvalho Chehab 			goto error;
23929a0bf528SMauro Carvalho Chehab 		break;
2393cd7a67a4SMauro Carvalho Chehab 	}		/* switch (agcSettingsIf->ctrl_mode) */
23949a0bf528SMauro Carvalho Chehab 
23959a0bf528SMauro Carvalho Chehab 	/* always set the top to support
23969a0bf528SMauro Carvalho Chehab 		configurations without if-loop */
2397cd7a67a4SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_AGC_INGAIN_TGT_MIN__A, p_agc_cfg->top);
23989a0bf528SMauro Carvalho Chehab error:
23999a0bf528SMauro Carvalho Chehab 	if (status < 0)
24003a4398f5SMauro Carvalho Chehab 		pr_err("Error %d on %s\n", status, __func__);
24019a0bf528SMauro Carvalho Chehab 	return status;
24029a0bf528SMauro Carvalho Chehab }
24039a0bf528SMauro Carvalho Chehab 
2404cd7a67a4SMauro Carvalho Chehab static int get_qam_signal_to_noise(struct drxk_state *state,
2405cd7a67a4SMauro Carvalho Chehab 			       s32 *p_signal_to_noise)
24069a0bf528SMauro Carvalho Chehab {
24079a0bf528SMauro Carvalho Chehab 	int status = 0;
2408cd7a67a4SMauro Carvalho Chehab 	u16 qam_sl_err_power = 0;	/* accum. error between
24099a0bf528SMauro Carvalho Chehab 					raw and sliced symbols */
2410cd7a67a4SMauro Carvalho Chehab 	u32 qam_sl_sig_power = 0;	/* used for MER, depends of
24119a0bf528SMauro Carvalho Chehab 					QAM modulation */
2412cd7a67a4SMauro Carvalho Chehab 	u32 qam_sl_mer = 0;	/* QAM MER */
24139a0bf528SMauro Carvalho Chehab 
24149a0bf528SMauro Carvalho Chehab 	dprintk(1, "\n");
24159a0bf528SMauro Carvalho Chehab 
24169a0bf528SMauro Carvalho Chehab 	/* MER calculation */
24179a0bf528SMauro Carvalho Chehab 
24189a0bf528SMauro Carvalho Chehab 	/* get the register value needed for MER */
2419cd7a67a4SMauro Carvalho Chehab 	status = read16(state, QAM_SL_ERR_POWER__A, &qam_sl_err_power);
24209a0bf528SMauro Carvalho Chehab 	if (status < 0) {
24213a4398f5SMauro Carvalho Chehab 		pr_err("Error %d on %s\n", status, __func__);
24229a0bf528SMauro Carvalho Chehab 		return -EINVAL;
24239a0bf528SMauro Carvalho Chehab 	}
24249a0bf528SMauro Carvalho Chehab 
24259a0bf528SMauro Carvalho Chehab 	switch (state->props.modulation) {
24269a0bf528SMauro Carvalho Chehab 	case QAM_16:
2427cd7a67a4SMauro Carvalho Chehab 		qam_sl_sig_power = DRXK_QAM_SL_SIG_POWER_QAM16 << 2;
24289a0bf528SMauro Carvalho Chehab 		break;
24299a0bf528SMauro Carvalho Chehab 	case QAM_32:
2430cd7a67a4SMauro Carvalho Chehab 		qam_sl_sig_power = DRXK_QAM_SL_SIG_POWER_QAM32 << 2;
24319a0bf528SMauro Carvalho Chehab 		break;
24329a0bf528SMauro Carvalho Chehab 	case QAM_64:
2433cd7a67a4SMauro Carvalho Chehab 		qam_sl_sig_power = DRXK_QAM_SL_SIG_POWER_QAM64 << 2;
24349a0bf528SMauro Carvalho Chehab 		break;
24359a0bf528SMauro Carvalho Chehab 	case QAM_128:
2436cd7a67a4SMauro Carvalho Chehab 		qam_sl_sig_power = DRXK_QAM_SL_SIG_POWER_QAM128 << 2;
24379a0bf528SMauro Carvalho Chehab 		break;
24389a0bf528SMauro Carvalho Chehab 	default:
24399a0bf528SMauro Carvalho Chehab 	case QAM_256:
2440cd7a67a4SMauro Carvalho Chehab 		qam_sl_sig_power = DRXK_QAM_SL_SIG_POWER_QAM256 << 2;
24419a0bf528SMauro Carvalho Chehab 		break;
24429a0bf528SMauro Carvalho Chehab 	}
24439a0bf528SMauro Carvalho Chehab 
2444cd7a67a4SMauro Carvalho Chehab 	if (qam_sl_err_power > 0) {
2445cd7a67a4SMauro Carvalho Chehab 		qam_sl_mer = log10times100(qam_sl_sig_power) -
2446cd7a67a4SMauro Carvalho Chehab 			log10times100((u32) qam_sl_err_power);
24479a0bf528SMauro Carvalho Chehab 	}
2448cd7a67a4SMauro Carvalho Chehab 	*p_signal_to_noise = qam_sl_mer;
24499a0bf528SMauro Carvalho Chehab 
24509a0bf528SMauro Carvalho Chehab 	return status;
24519a0bf528SMauro Carvalho Chehab }
24529a0bf528SMauro Carvalho Chehab 
2453cd7a67a4SMauro Carvalho Chehab static int get_dvbt_signal_to_noise(struct drxk_state *state,
2454cd7a67a4SMauro Carvalho Chehab 				s32 *p_signal_to_noise)
24559a0bf528SMauro Carvalho Chehab {
24569a0bf528SMauro Carvalho Chehab 	int status;
2457cd7a67a4SMauro Carvalho Chehab 	u16 reg_data = 0;
2458cd7a67a4SMauro Carvalho Chehab 	u32 eq_reg_td_sqr_err_i = 0;
2459cd7a67a4SMauro Carvalho Chehab 	u32 eq_reg_td_sqr_err_q = 0;
2460cd7a67a4SMauro Carvalho Chehab 	u16 eq_reg_td_sqr_err_exp = 0;
2461cd7a67a4SMauro Carvalho Chehab 	u16 eq_reg_td_tps_pwr_ofs = 0;
2462cd7a67a4SMauro Carvalho Chehab 	u16 eq_reg_td_req_smb_cnt = 0;
2463cd7a67a4SMauro Carvalho Chehab 	u32 tps_cnt = 0;
2464cd7a67a4SMauro Carvalho Chehab 	u32 sqr_err_iq = 0;
24659a0bf528SMauro Carvalho Chehab 	u32 a = 0;
24669a0bf528SMauro Carvalho Chehab 	u32 b = 0;
24679a0bf528SMauro Carvalho Chehab 	u32 c = 0;
2468cd7a67a4SMauro Carvalho Chehab 	u32 i_mer = 0;
2469cd7a67a4SMauro Carvalho Chehab 	u16 transmission_params = 0;
24709a0bf528SMauro Carvalho Chehab 
24719a0bf528SMauro Carvalho Chehab 	dprintk(1, "\n");
24729a0bf528SMauro Carvalho Chehab 
2473cd7a67a4SMauro Carvalho Chehab 	status = read16(state, OFDM_EQ_TOP_TD_TPS_PWR_OFS__A, &eq_reg_td_tps_pwr_ofs);
24749a0bf528SMauro Carvalho Chehab 	if (status < 0)
24759a0bf528SMauro Carvalho Chehab 		goto error;
2476cd7a67a4SMauro Carvalho Chehab 	status = read16(state, OFDM_EQ_TOP_TD_REQ_SMB_CNT__A, &eq_reg_td_req_smb_cnt);
24779a0bf528SMauro Carvalho Chehab 	if (status < 0)
24789a0bf528SMauro Carvalho Chehab 		goto error;
2479cd7a67a4SMauro Carvalho Chehab 	status = read16(state, OFDM_EQ_TOP_TD_SQR_ERR_EXP__A, &eq_reg_td_sqr_err_exp);
24809a0bf528SMauro Carvalho Chehab 	if (status < 0)
24819a0bf528SMauro Carvalho Chehab 		goto error;
2482cd7a67a4SMauro Carvalho Chehab 	status = read16(state, OFDM_EQ_TOP_TD_SQR_ERR_I__A, &reg_data);
24839a0bf528SMauro Carvalho Chehab 	if (status < 0)
24849a0bf528SMauro Carvalho Chehab 		goto error;
24859a0bf528SMauro Carvalho Chehab 	/* Extend SQR_ERR_I operational range */
2486cd7a67a4SMauro Carvalho Chehab 	eq_reg_td_sqr_err_i = (u32) reg_data;
2487cd7a67a4SMauro Carvalho Chehab 	if ((eq_reg_td_sqr_err_exp > 11) &&
2488cd7a67a4SMauro Carvalho Chehab 		(eq_reg_td_sqr_err_i < 0x00000FFFUL)) {
2489cd7a67a4SMauro Carvalho Chehab 		eq_reg_td_sqr_err_i += 0x00010000UL;
24909a0bf528SMauro Carvalho Chehab 	}
2491cd7a67a4SMauro Carvalho Chehab 	status = read16(state, OFDM_EQ_TOP_TD_SQR_ERR_Q__A, &reg_data);
24929a0bf528SMauro Carvalho Chehab 	if (status < 0)
24939a0bf528SMauro Carvalho Chehab 		goto error;
24949a0bf528SMauro Carvalho Chehab 	/* Extend SQR_ERR_Q operational range */
2495cd7a67a4SMauro Carvalho Chehab 	eq_reg_td_sqr_err_q = (u32) reg_data;
2496cd7a67a4SMauro Carvalho Chehab 	if ((eq_reg_td_sqr_err_exp > 11) &&
2497cd7a67a4SMauro Carvalho Chehab 		(eq_reg_td_sqr_err_q < 0x00000FFFUL))
2498cd7a67a4SMauro Carvalho Chehab 		eq_reg_td_sqr_err_q += 0x00010000UL;
24999a0bf528SMauro Carvalho Chehab 
2500cd7a67a4SMauro Carvalho Chehab 	status = read16(state, OFDM_SC_RA_RAM_OP_PARAM__A, &transmission_params);
25019a0bf528SMauro Carvalho Chehab 	if (status < 0)
25029a0bf528SMauro Carvalho Chehab 		goto error;
25039a0bf528SMauro Carvalho Chehab 
25049a0bf528SMauro Carvalho Chehab 	/* Check input data for MER */
25059a0bf528SMauro Carvalho Chehab 
25069a0bf528SMauro Carvalho Chehab 	/* MER calculation (in 0.1 dB) without math.h */
2507cd7a67a4SMauro Carvalho Chehab 	if ((eq_reg_td_tps_pwr_ofs == 0) || (eq_reg_td_req_smb_cnt == 0))
2508cd7a67a4SMauro Carvalho Chehab 		i_mer = 0;
2509cd7a67a4SMauro Carvalho Chehab 	else if ((eq_reg_td_sqr_err_i + eq_reg_td_sqr_err_q) == 0) {
25109a0bf528SMauro Carvalho Chehab 		/* No error at all, this must be the HW reset value
25119a0bf528SMauro Carvalho Chehab 			* Apparently no first measurement yet
25129a0bf528SMauro Carvalho Chehab 			* Set MER to 0.0 */
2513cd7a67a4SMauro Carvalho Chehab 		i_mer = 0;
25149a0bf528SMauro Carvalho Chehab 	} else {
2515cd7a67a4SMauro Carvalho Chehab 		sqr_err_iq = (eq_reg_td_sqr_err_i + eq_reg_td_sqr_err_q) <<
2516cd7a67a4SMauro Carvalho Chehab 			eq_reg_td_sqr_err_exp;
2517cd7a67a4SMauro Carvalho Chehab 		if ((transmission_params &
25189a0bf528SMauro Carvalho Chehab 			OFDM_SC_RA_RAM_OP_PARAM_MODE__M)
25199a0bf528SMauro Carvalho Chehab 			== OFDM_SC_RA_RAM_OP_PARAM_MODE_2K)
2520cd7a67a4SMauro Carvalho Chehab 			tps_cnt = 17;
25219a0bf528SMauro Carvalho Chehab 		else
2522cd7a67a4SMauro Carvalho Chehab 			tps_cnt = 68;
25239a0bf528SMauro Carvalho Chehab 
25249a0bf528SMauro Carvalho Chehab 		/* IMER = 100 * log10 (x)
2525cd7a67a4SMauro Carvalho Chehab 			where x = (eq_reg_td_tps_pwr_ofs^2 *
2526cd7a67a4SMauro Carvalho Chehab 			eq_reg_td_req_smb_cnt * tps_cnt)/sqr_err_iq
25279a0bf528SMauro Carvalho Chehab 
25289a0bf528SMauro Carvalho Chehab 			=> IMER = a + b -c
2529cd7a67a4SMauro Carvalho Chehab 			where a = 100 * log10 (eq_reg_td_tps_pwr_ofs^2)
2530cd7a67a4SMauro Carvalho Chehab 			b = 100 * log10 (eq_reg_td_req_smb_cnt * tps_cnt)
2531cd7a67a4SMauro Carvalho Chehab 			c = 100 * log10 (sqr_err_iq)
25329a0bf528SMauro Carvalho Chehab 			*/
25339a0bf528SMauro Carvalho Chehab 
25349a0bf528SMauro Carvalho Chehab 		/* log(x) x = 9bits * 9bits->18 bits  */
2535cd7a67a4SMauro Carvalho Chehab 		a = log10times100(eq_reg_td_tps_pwr_ofs *
2536cd7a67a4SMauro Carvalho Chehab 					eq_reg_td_tps_pwr_ofs);
25379a0bf528SMauro Carvalho Chehab 		/* log(x) x = 16bits * 7bits->23 bits  */
2538cd7a67a4SMauro Carvalho Chehab 		b = log10times100(eq_reg_td_req_smb_cnt * tps_cnt);
25399a0bf528SMauro Carvalho Chehab 		/* log(x) x = (16bits + 16bits) << 15 ->32 bits  */
2540cd7a67a4SMauro Carvalho Chehab 		c = log10times100(sqr_err_iq);
25419a0bf528SMauro Carvalho Chehab 
2542cd7a67a4SMauro Carvalho Chehab 		i_mer = a + b - c;
25439a0bf528SMauro Carvalho Chehab 	}
2544cd7a67a4SMauro Carvalho Chehab 	*p_signal_to_noise = i_mer;
25459a0bf528SMauro Carvalho Chehab 
25469a0bf528SMauro Carvalho Chehab error:
25479a0bf528SMauro Carvalho Chehab 	if (status < 0)
25483a4398f5SMauro Carvalho Chehab 		pr_err("Error %d on %s\n", status, __func__);
25499a0bf528SMauro Carvalho Chehab 	return status;
25509a0bf528SMauro Carvalho Chehab }
25519a0bf528SMauro Carvalho Chehab 
2552cd7a67a4SMauro Carvalho Chehab static int get_signal_to_noise(struct drxk_state *state, s32 *p_signal_to_noise)
25539a0bf528SMauro Carvalho Chehab {
25549a0bf528SMauro Carvalho Chehab 	dprintk(1, "\n");
25559a0bf528SMauro Carvalho Chehab 
2556cd7a67a4SMauro Carvalho Chehab 	*p_signal_to_noise = 0;
2557cd7a67a4SMauro Carvalho Chehab 	switch (state->m_operation_mode) {
25589a0bf528SMauro Carvalho Chehab 	case OM_DVBT:
2559cd7a67a4SMauro Carvalho Chehab 		return get_dvbt_signal_to_noise(state, p_signal_to_noise);
25609a0bf528SMauro Carvalho Chehab 	case OM_QAM_ITU_A:
25619a0bf528SMauro Carvalho Chehab 	case OM_QAM_ITU_C:
2562cd7a67a4SMauro Carvalho Chehab 		return get_qam_signal_to_noise(state, p_signal_to_noise);
25639a0bf528SMauro Carvalho Chehab 	default:
25649a0bf528SMauro Carvalho Chehab 		break;
25659a0bf528SMauro Carvalho Chehab 	}
25669a0bf528SMauro Carvalho Chehab 	return 0;
25679a0bf528SMauro Carvalho Chehab }
25689a0bf528SMauro Carvalho Chehab 
25699a0bf528SMauro Carvalho Chehab #if 0
2570cd7a67a4SMauro Carvalho Chehab static int get_dvbt_quality(struct drxk_state *state, s32 *p_quality)
25719a0bf528SMauro Carvalho Chehab {
25729a0bf528SMauro Carvalho Chehab 	/* SNR Values for quasi errorfree reception rom Nordig 2.2 */
25739a0bf528SMauro Carvalho Chehab 	int status = 0;
25749a0bf528SMauro Carvalho Chehab 
25759a0bf528SMauro Carvalho Chehab 	dprintk(1, "\n");
25769a0bf528SMauro Carvalho Chehab 
25779a0bf528SMauro Carvalho Chehab 	static s32 QE_SN[] = {
25789a0bf528SMauro Carvalho Chehab 		51,		/* QPSK 1/2 */
25799a0bf528SMauro Carvalho Chehab 		69,		/* QPSK 2/3 */
25809a0bf528SMauro Carvalho Chehab 		79,		/* QPSK 3/4 */
25819a0bf528SMauro Carvalho Chehab 		89,		/* QPSK 5/6 */
25829a0bf528SMauro Carvalho Chehab 		97,		/* QPSK 7/8 */
25839a0bf528SMauro Carvalho Chehab 		108,		/* 16-QAM 1/2 */
25849a0bf528SMauro Carvalho Chehab 		131,		/* 16-QAM 2/3 */
25859a0bf528SMauro Carvalho Chehab 		146,		/* 16-QAM 3/4 */
25869a0bf528SMauro Carvalho Chehab 		156,		/* 16-QAM 5/6 */
25879a0bf528SMauro Carvalho Chehab 		160,		/* 16-QAM 7/8 */
25889a0bf528SMauro Carvalho Chehab 		165,		/* 64-QAM 1/2 */
25899a0bf528SMauro Carvalho Chehab 		187,		/* 64-QAM 2/3 */
25909a0bf528SMauro Carvalho Chehab 		202,		/* 64-QAM 3/4 */
25919a0bf528SMauro Carvalho Chehab 		216,		/* 64-QAM 5/6 */
25929a0bf528SMauro Carvalho Chehab 		225,		/* 64-QAM 7/8 */
25939a0bf528SMauro Carvalho Chehab 	};
25949a0bf528SMauro Carvalho Chehab 
2595cd7a67a4SMauro Carvalho Chehab 	*p_quality = 0;
25969a0bf528SMauro Carvalho Chehab 
25979a0bf528SMauro Carvalho Chehab 	do {
2598cd7a67a4SMauro Carvalho Chehab 		s32 signal_to_noise = 0;
2599cd7a67a4SMauro Carvalho Chehab 		u16 constellation = 0;
2600cd7a67a4SMauro Carvalho Chehab 		u16 code_rate = 0;
2601cd7a67a4SMauro Carvalho Chehab 		u32 signal_to_noise_rel;
2602cd7a67a4SMauro Carvalho Chehab 		u32 ber_quality;
26039a0bf528SMauro Carvalho Chehab 
2604cd7a67a4SMauro Carvalho Chehab 		status = get_dvbt_signal_to_noise(state, &signal_to_noise);
26059a0bf528SMauro Carvalho Chehab 		if (status < 0)
26069a0bf528SMauro Carvalho Chehab 			break;
2607cd7a67a4SMauro Carvalho Chehab 		status = read16(state, OFDM_EQ_TOP_TD_TPS_CONST__A, &constellation);
26089a0bf528SMauro Carvalho Chehab 		if (status < 0)
26099a0bf528SMauro Carvalho Chehab 			break;
2610cd7a67a4SMauro Carvalho Chehab 		constellation &= OFDM_EQ_TOP_TD_TPS_CONST__M;
26119a0bf528SMauro Carvalho Chehab 
2612cd7a67a4SMauro Carvalho Chehab 		status = read16(state, OFDM_EQ_TOP_TD_TPS_CODE_HP__A, &code_rate);
26139a0bf528SMauro Carvalho Chehab 		if (status < 0)
26149a0bf528SMauro Carvalho Chehab 			break;
2615cd7a67a4SMauro Carvalho Chehab 		code_rate &= OFDM_EQ_TOP_TD_TPS_CODE_HP__M;
26169a0bf528SMauro Carvalho Chehab 
2617cd7a67a4SMauro Carvalho Chehab 		if (constellation > OFDM_EQ_TOP_TD_TPS_CONST_64QAM ||
2618cd7a67a4SMauro Carvalho Chehab 		    code_rate > OFDM_EQ_TOP_TD_TPS_CODE_LP_7_8)
26199a0bf528SMauro Carvalho Chehab 			break;
2620cd7a67a4SMauro Carvalho Chehab 		signal_to_noise_rel = signal_to_noise -
2621cd7a67a4SMauro Carvalho Chehab 		    QE_SN[constellation * 5 + code_rate];
2622cd7a67a4SMauro Carvalho Chehab 		ber_quality = 100;
26239a0bf528SMauro Carvalho Chehab 
2624cd7a67a4SMauro Carvalho Chehab 		if (signal_to_noise_rel < -70)
2625cd7a67a4SMauro Carvalho Chehab 			*p_quality = 0;
2626cd7a67a4SMauro Carvalho Chehab 		else if (signal_to_noise_rel < 30)
2627cd7a67a4SMauro Carvalho Chehab 			*p_quality = ((signal_to_noise_rel + 70) *
2628cd7a67a4SMauro Carvalho Chehab 				     ber_quality) / 100;
26299a0bf528SMauro Carvalho Chehab 		else
2630cd7a67a4SMauro Carvalho Chehab 			*p_quality = ber_quality;
26319a0bf528SMauro Carvalho Chehab 	} while (0);
26329a0bf528SMauro Carvalho Chehab 	return 0;
26339a0bf528SMauro Carvalho Chehab };
26349a0bf528SMauro Carvalho Chehab 
2635cd7a67a4SMauro Carvalho Chehab static int get_dvbc_quality(struct drxk_state *state, s32 *p_quality)
26369a0bf528SMauro Carvalho Chehab {
26379a0bf528SMauro Carvalho Chehab 	int status = 0;
2638cd7a67a4SMauro Carvalho Chehab 	*p_quality = 0;
26399a0bf528SMauro Carvalho Chehab 
26409a0bf528SMauro Carvalho Chehab 	dprintk(1, "\n");
26419a0bf528SMauro Carvalho Chehab 
26429a0bf528SMauro Carvalho Chehab 	do {
2643cd7a67a4SMauro Carvalho Chehab 		u32 signal_to_noise = 0;
2644cd7a67a4SMauro Carvalho Chehab 		u32 ber_quality = 100;
2645cd7a67a4SMauro Carvalho Chehab 		u32 signal_to_noise_rel = 0;
26469a0bf528SMauro Carvalho Chehab 
2647cd7a67a4SMauro Carvalho Chehab 		status = get_qam_signal_to_noise(state, &signal_to_noise);
26489a0bf528SMauro Carvalho Chehab 		if (status < 0)
26499a0bf528SMauro Carvalho Chehab 			break;
26509a0bf528SMauro Carvalho Chehab 
26519a0bf528SMauro Carvalho Chehab 		switch (state->props.modulation) {
26529a0bf528SMauro Carvalho Chehab 		case QAM_16:
2653cd7a67a4SMauro Carvalho Chehab 			signal_to_noise_rel = signal_to_noise - 200;
26549a0bf528SMauro Carvalho Chehab 			break;
26559a0bf528SMauro Carvalho Chehab 		case QAM_32:
2656cd7a67a4SMauro Carvalho Chehab 			signal_to_noise_rel = signal_to_noise - 230;
26579a0bf528SMauro Carvalho Chehab 			break;	/* Not in NorDig */
26589a0bf528SMauro Carvalho Chehab 		case QAM_64:
2659cd7a67a4SMauro Carvalho Chehab 			signal_to_noise_rel = signal_to_noise - 260;
26609a0bf528SMauro Carvalho Chehab 			break;
26619a0bf528SMauro Carvalho Chehab 		case QAM_128:
2662cd7a67a4SMauro Carvalho Chehab 			signal_to_noise_rel = signal_to_noise - 290;
26639a0bf528SMauro Carvalho Chehab 			break;
26649a0bf528SMauro Carvalho Chehab 		default:
26659a0bf528SMauro Carvalho Chehab 		case QAM_256:
2666cd7a67a4SMauro Carvalho Chehab 			signal_to_noise_rel = signal_to_noise - 320;
26679a0bf528SMauro Carvalho Chehab 			break;
26689a0bf528SMauro Carvalho Chehab 		}
26699a0bf528SMauro Carvalho Chehab 
2670cd7a67a4SMauro Carvalho Chehab 		if (signal_to_noise_rel < -70)
2671cd7a67a4SMauro Carvalho Chehab 			*p_quality = 0;
2672cd7a67a4SMauro Carvalho Chehab 		else if (signal_to_noise_rel < 30)
2673cd7a67a4SMauro Carvalho Chehab 			*p_quality = ((signal_to_noise_rel + 70) *
2674cd7a67a4SMauro Carvalho Chehab 				     ber_quality) / 100;
26759a0bf528SMauro Carvalho Chehab 		else
2676cd7a67a4SMauro Carvalho Chehab 			*p_quality = ber_quality;
26779a0bf528SMauro Carvalho Chehab 	} while (0);
26789a0bf528SMauro Carvalho Chehab 
26799a0bf528SMauro Carvalho Chehab 	return status;
26809a0bf528SMauro Carvalho Chehab }
26819a0bf528SMauro Carvalho Chehab 
2682cd7a67a4SMauro Carvalho Chehab static int get_quality(struct drxk_state *state, s32 *p_quality)
26839a0bf528SMauro Carvalho Chehab {
26849a0bf528SMauro Carvalho Chehab 	dprintk(1, "\n");
26859a0bf528SMauro Carvalho Chehab 
2686cd7a67a4SMauro Carvalho Chehab 	switch (state->m_operation_mode) {
26879a0bf528SMauro Carvalho Chehab 	case OM_DVBT:
2688cd7a67a4SMauro Carvalho Chehab 		return get_dvbt_quality(state, p_quality);
26899a0bf528SMauro Carvalho Chehab 	case OM_QAM_ITU_A:
2690cd7a67a4SMauro Carvalho Chehab 		return get_dvbc_quality(state, p_quality);
26919a0bf528SMauro Carvalho Chehab 	default:
26929a0bf528SMauro Carvalho Chehab 		break;
26939a0bf528SMauro Carvalho Chehab 	}
26949a0bf528SMauro Carvalho Chehab 
26959a0bf528SMauro Carvalho Chehab 	return 0;
26969a0bf528SMauro Carvalho Chehab }
26979a0bf528SMauro Carvalho Chehab #endif
26989a0bf528SMauro Carvalho Chehab 
26999a0bf528SMauro Carvalho Chehab /* Free data ram in SIO HI */
27009a0bf528SMauro Carvalho Chehab #define SIO_HI_RA_RAM_USR_BEGIN__A 0x420040
27019a0bf528SMauro Carvalho Chehab #define SIO_HI_RA_RAM_USR_END__A   0x420060
27029a0bf528SMauro Carvalho Chehab 
27039a0bf528SMauro Carvalho Chehab #define DRXK_HI_ATOMIC_BUF_START (SIO_HI_RA_RAM_USR_BEGIN__A)
27049a0bf528SMauro Carvalho Chehab #define DRXK_HI_ATOMIC_BUF_END   (SIO_HI_RA_RAM_USR_BEGIN__A + 7)
27059a0bf528SMauro Carvalho Chehab #define DRXK_HI_ATOMIC_READ      SIO_HI_RA_RAM_PAR_3_ACP_RW_READ
27069a0bf528SMauro Carvalho Chehab #define DRXK_HI_ATOMIC_WRITE     SIO_HI_RA_RAM_PAR_3_ACP_RW_WRITE
27079a0bf528SMauro Carvalho Chehab 
27089a0bf528SMauro Carvalho Chehab #define DRXDAP_FASI_ADDR2BLOCK(addr)  (((addr) >> 22) & 0x3F)
27099a0bf528SMauro Carvalho Chehab #define DRXDAP_FASI_ADDR2BANK(addr)   (((addr) >> 16) & 0x3F)
27109a0bf528SMauro Carvalho Chehab #define DRXDAP_FASI_ADDR2OFFSET(addr) ((addr) & 0x7FFF)
27119a0bf528SMauro Carvalho Chehab 
2712cd7a67a4SMauro Carvalho Chehab static int ConfigureI2CBridge(struct drxk_state *state, bool b_enable_bridge)
27139a0bf528SMauro Carvalho Chehab {
27149a0bf528SMauro Carvalho Chehab 	int status = -EINVAL;
27159a0bf528SMauro Carvalho Chehab 
27169a0bf528SMauro Carvalho Chehab 	dprintk(1, "\n");
27179a0bf528SMauro Carvalho Chehab 
2718cd7a67a4SMauro Carvalho Chehab 	if (state->m_drxk_state == DRXK_UNINITIALIZED)
27199a0bf528SMauro Carvalho Chehab 		return 0;
2720cd7a67a4SMauro Carvalho Chehab 	if (state->m_drxk_state == DRXK_POWERED_DOWN)
27219a0bf528SMauro Carvalho Chehab 		goto error;
27229a0bf528SMauro Carvalho Chehab 
27239a0bf528SMauro Carvalho Chehab 	if (state->no_i2c_bridge)
27249a0bf528SMauro Carvalho Chehab 		return 0;
27259a0bf528SMauro Carvalho Chehab 
27269a0bf528SMauro Carvalho Chehab 	status = write16(state, SIO_HI_RA_RAM_PAR_1__A, SIO_HI_RA_RAM_PAR_1_PAR1_SEC_KEY);
27279a0bf528SMauro Carvalho Chehab 	if (status < 0)
27289a0bf528SMauro Carvalho Chehab 		goto error;
2729cd7a67a4SMauro Carvalho Chehab 	if (b_enable_bridge) {
27309a0bf528SMauro Carvalho Chehab 		status = write16(state, SIO_HI_RA_RAM_PAR_2__A, SIO_HI_RA_RAM_PAR_2_BRD_CFG_CLOSED);
27319a0bf528SMauro Carvalho Chehab 		if (status < 0)
27329a0bf528SMauro Carvalho Chehab 			goto error;
27339a0bf528SMauro Carvalho Chehab 	} else {
27349a0bf528SMauro Carvalho Chehab 		status = write16(state, SIO_HI_RA_RAM_PAR_2__A, SIO_HI_RA_RAM_PAR_2_BRD_CFG_OPEN);
27359a0bf528SMauro Carvalho Chehab 		if (status < 0)
27369a0bf528SMauro Carvalho Chehab 			goto error;
27379a0bf528SMauro Carvalho Chehab 	}
27389a0bf528SMauro Carvalho Chehab 
2739cd7a67a4SMauro Carvalho Chehab 	status = hi_command(state, SIO_HI_RA_RAM_CMD_BRDCTRL, 0);
27409a0bf528SMauro Carvalho Chehab 
27419a0bf528SMauro Carvalho Chehab error:
27429a0bf528SMauro Carvalho Chehab 	if (status < 0)
27433a4398f5SMauro Carvalho Chehab 		pr_err("Error %d on %s\n", status, __func__);
27449a0bf528SMauro Carvalho Chehab 	return status;
27459a0bf528SMauro Carvalho Chehab }
27469a0bf528SMauro Carvalho Chehab 
2747cd7a67a4SMauro Carvalho Chehab static int set_pre_saw(struct drxk_state *state,
2748cd7a67a4SMauro Carvalho Chehab 		     struct s_cfg_pre_saw *p_pre_saw_cfg)
27499a0bf528SMauro Carvalho Chehab {
27509a0bf528SMauro Carvalho Chehab 	int status = -EINVAL;
27519a0bf528SMauro Carvalho Chehab 
27529a0bf528SMauro Carvalho Chehab 	dprintk(1, "\n");
27539a0bf528SMauro Carvalho Chehab 
2754cd7a67a4SMauro Carvalho Chehab 	if ((p_pre_saw_cfg == NULL)
2755cd7a67a4SMauro Carvalho Chehab 	    || (p_pre_saw_cfg->reference > IQM_AF_PDREF__M))
27569a0bf528SMauro Carvalho Chehab 		goto error;
27579a0bf528SMauro Carvalho Chehab 
2758cd7a67a4SMauro Carvalho Chehab 	status = write16(state, IQM_AF_PDREF__A, p_pre_saw_cfg->reference);
27599a0bf528SMauro Carvalho Chehab error:
27609a0bf528SMauro Carvalho Chehab 	if (status < 0)
27613a4398f5SMauro Carvalho Chehab 		pr_err("Error %d on %s\n", status, __func__);
27629a0bf528SMauro Carvalho Chehab 	return status;
27639a0bf528SMauro Carvalho Chehab }
27649a0bf528SMauro Carvalho Chehab 
2765cd7a67a4SMauro Carvalho Chehab static int bl_direct_cmd(struct drxk_state *state, u32 target_addr,
2766cd7a67a4SMauro Carvalho Chehab 		       u16 rom_offset, u16 nr_of_elements, u32 time_out)
27679a0bf528SMauro Carvalho Chehab {
2768cd7a67a4SMauro Carvalho Chehab 	u16 bl_status = 0;
2769cd7a67a4SMauro Carvalho Chehab 	u16 offset = (u16) ((target_addr >> 0) & 0x00FFFF);
2770cd7a67a4SMauro Carvalho Chehab 	u16 blockbank = (u16) ((target_addr >> 16) & 0x000FFF);
27719a0bf528SMauro Carvalho Chehab 	int status;
27729a0bf528SMauro Carvalho Chehab 	unsigned long end;
27739a0bf528SMauro Carvalho Chehab 
27749a0bf528SMauro Carvalho Chehab 	dprintk(1, "\n");
27759a0bf528SMauro Carvalho Chehab 
27769a0bf528SMauro Carvalho Chehab 	mutex_lock(&state->mutex);
27779a0bf528SMauro Carvalho Chehab 	status = write16(state, SIO_BL_MODE__A, SIO_BL_MODE_DIRECT);
27789a0bf528SMauro Carvalho Chehab 	if (status < 0)
27799a0bf528SMauro Carvalho Chehab 		goto error;
27809a0bf528SMauro Carvalho Chehab 	status = write16(state, SIO_BL_TGT_HDR__A, blockbank);
27819a0bf528SMauro Carvalho Chehab 	if (status < 0)
27829a0bf528SMauro Carvalho Chehab 		goto error;
27839a0bf528SMauro Carvalho Chehab 	status = write16(state, SIO_BL_TGT_ADDR__A, offset);
27849a0bf528SMauro Carvalho Chehab 	if (status < 0)
27859a0bf528SMauro Carvalho Chehab 		goto error;
2786cd7a67a4SMauro Carvalho Chehab 	status = write16(state, SIO_BL_SRC_ADDR__A, rom_offset);
27879a0bf528SMauro Carvalho Chehab 	if (status < 0)
27889a0bf528SMauro Carvalho Chehab 		goto error;
2789cd7a67a4SMauro Carvalho Chehab 	status = write16(state, SIO_BL_SRC_LEN__A, nr_of_elements);
27909a0bf528SMauro Carvalho Chehab 	if (status < 0)
27919a0bf528SMauro Carvalho Chehab 		goto error;
27929a0bf528SMauro Carvalho Chehab 	status = write16(state, SIO_BL_ENABLE__A, SIO_BL_ENABLE_ON);
27939a0bf528SMauro Carvalho Chehab 	if (status < 0)
27949a0bf528SMauro Carvalho Chehab 		goto error;
27959a0bf528SMauro Carvalho Chehab 
2796cd7a67a4SMauro Carvalho Chehab 	end = jiffies + msecs_to_jiffies(time_out);
27979a0bf528SMauro Carvalho Chehab 	do {
2798cd7a67a4SMauro Carvalho Chehab 		status = read16(state, SIO_BL_STATUS__A, &bl_status);
27999a0bf528SMauro Carvalho Chehab 		if (status < 0)
28009a0bf528SMauro Carvalho Chehab 			goto error;
2801cd7a67a4SMauro Carvalho Chehab 	} while ((bl_status == 0x1) && time_is_after_jiffies(end));
2802cd7a67a4SMauro Carvalho Chehab 	if (bl_status == 0x1) {
28033a4398f5SMauro Carvalho Chehab 		pr_err("SIO not ready\n");
28049a0bf528SMauro Carvalho Chehab 		status = -EINVAL;
28059a0bf528SMauro Carvalho Chehab 		goto error2;
28069a0bf528SMauro Carvalho Chehab 	}
28079a0bf528SMauro Carvalho Chehab error:
28089a0bf528SMauro Carvalho Chehab 	if (status < 0)
28093a4398f5SMauro Carvalho Chehab 		pr_err("Error %d on %s\n", status, __func__);
28109a0bf528SMauro Carvalho Chehab error2:
28119a0bf528SMauro Carvalho Chehab 	mutex_unlock(&state->mutex);
28129a0bf528SMauro Carvalho Chehab 	return status;
28139a0bf528SMauro Carvalho Chehab 
28149a0bf528SMauro Carvalho Chehab }
28159a0bf528SMauro Carvalho Chehab 
2816cd7a67a4SMauro Carvalho Chehab static int adc_sync_measurement(struct drxk_state *state, u16 *count)
28179a0bf528SMauro Carvalho Chehab {
28189a0bf528SMauro Carvalho Chehab 	u16 data = 0;
28199a0bf528SMauro Carvalho Chehab 	int status;
28209a0bf528SMauro Carvalho Chehab 
28219a0bf528SMauro Carvalho Chehab 	dprintk(1, "\n");
28229a0bf528SMauro Carvalho Chehab 
2823cd7a67a4SMauro Carvalho Chehab 	/* start measurement */
28249a0bf528SMauro Carvalho Chehab 	status = write16(state, IQM_AF_COMM_EXEC__A, IQM_AF_COMM_EXEC_ACTIVE);
28259a0bf528SMauro Carvalho Chehab 	if (status < 0)
28269a0bf528SMauro Carvalho Chehab 		goto error;
28279a0bf528SMauro Carvalho Chehab 	status = write16(state, IQM_AF_START_LOCK__A, 1);
28289a0bf528SMauro Carvalho Chehab 	if (status < 0)
28299a0bf528SMauro Carvalho Chehab 		goto error;
28309a0bf528SMauro Carvalho Chehab 
28319a0bf528SMauro Carvalho Chehab 	*count = 0;
28329a0bf528SMauro Carvalho Chehab 	status = read16(state, IQM_AF_PHASE0__A, &data);
28339a0bf528SMauro Carvalho Chehab 	if (status < 0)
28349a0bf528SMauro Carvalho Chehab 		goto error;
28359a0bf528SMauro Carvalho Chehab 	if (data == 127)
28369a0bf528SMauro Carvalho Chehab 		*count = *count + 1;
28379a0bf528SMauro Carvalho Chehab 	status = read16(state, IQM_AF_PHASE1__A, &data);
28389a0bf528SMauro Carvalho Chehab 	if (status < 0)
28399a0bf528SMauro Carvalho Chehab 		goto error;
28409a0bf528SMauro Carvalho Chehab 	if (data == 127)
28419a0bf528SMauro Carvalho Chehab 		*count = *count + 1;
28429a0bf528SMauro Carvalho Chehab 	status = read16(state, IQM_AF_PHASE2__A, &data);
28439a0bf528SMauro Carvalho Chehab 	if (status < 0)
28449a0bf528SMauro Carvalho Chehab 		goto error;
28459a0bf528SMauro Carvalho Chehab 	if (data == 127)
28469a0bf528SMauro Carvalho Chehab 		*count = *count + 1;
28479a0bf528SMauro Carvalho Chehab 
28489a0bf528SMauro Carvalho Chehab error:
28499a0bf528SMauro Carvalho Chehab 	if (status < 0)
28503a4398f5SMauro Carvalho Chehab 		pr_err("Error %d on %s\n", status, __func__);
28519a0bf528SMauro Carvalho Chehab 	return status;
28529a0bf528SMauro Carvalho Chehab }
28539a0bf528SMauro Carvalho Chehab 
2854cd7a67a4SMauro Carvalho Chehab static int adc_synchronization(struct drxk_state *state)
28559a0bf528SMauro Carvalho Chehab {
28569a0bf528SMauro Carvalho Chehab 	u16 count = 0;
28579a0bf528SMauro Carvalho Chehab 	int status;
28589a0bf528SMauro Carvalho Chehab 
28599a0bf528SMauro Carvalho Chehab 	dprintk(1, "\n");
28609a0bf528SMauro Carvalho Chehab 
2861cd7a67a4SMauro Carvalho Chehab 	status = adc_sync_measurement(state, &count);
28629a0bf528SMauro Carvalho Chehab 	if (status < 0)
28639a0bf528SMauro Carvalho Chehab 		goto error;
28649a0bf528SMauro Carvalho Chehab 
28659a0bf528SMauro Carvalho Chehab 	if (count == 1) {
28669a0bf528SMauro Carvalho Chehab 		/* Try sampling on a diffrent edge */
2867cd7a67a4SMauro Carvalho Chehab 		u16 clk_neg = 0;
28689a0bf528SMauro Carvalho Chehab 
2869cd7a67a4SMauro Carvalho Chehab 		status = read16(state, IQM_AF_CLKNEG__A, &clk_neg);
28709a0bf528SMauro Carvalho Chehab 		if (status < 0)
28719a0bf528SMauro Carvalho Chehab 			goto error;
2872cd7a67a4SMauro Carvalho Chehab 		if ((clk_neg & IQM_AF_CLKNEG_CLKNEGDATA__M) ==
28739a0bf528SMauro Carvalho Chehab 			IQM_AF_CLKNEG_CLKNEGDATA_CLK_ADC_DATA_POS) {
2874cd7a67a4SMauro Carvalho Chehab 			clk_neg &= (~(IQM_AF_CLKNEG_CLKNEGDATA__M));
2875cd7a67a4SMauro Carvalho Chehab 			clk_neg |=
28769a0bf528SMauro Carvalho Chehab 				IQM_AF_CLKNEG_CLKNEGDATA_CLK_ADC_DATA_NEG;
28779a0bf528SMauro Carvalho Chehab 		} else {
2878cd7a67a4SMauro Carvalho Chehab 			clk_neg &= (~(IQM_AF_CLKNEG_CLKNEGDATA__M));
2879cd7a67a4SMauro Carvalho Chehab 			clk_neg |=
28809a0bf528SMauro Carvalho Chehab 				IQM_AF_CLKNEG_CLKNEGDATA_CLK_ADC_DATA_POS;
28819a0bf528SMauro Carvalho Chehab 		}
2882cd7a67a4SMauro Carvalho Chehab 		status = write16(state, IQM_AF_CLKNEG__A, clk_neg);
28839a0bf528SMauro Carvalho Chehab 		if (status < 0)
28849a0bf528SMauro Carvalho Chehab 			goto error;
2885cd7a67a4SMauro Carvalho Chehab 		status = adc_sync_measurement(state, &count);
28869a0bf528SMauro Carvalho Chehab 		if (status < 0)
28879a0bf528SMauro Carvalho Chehab 			goto error;
28889a0bf528SMauro Carvalho Chehab 	}
28899a0bf528SMauro Carvalho Chehab 
28909a0bf528SMauro Carvalho Chehab 	if (count < 2)
28919a0bf528SMauro Carvalho Chehab 		status = -EINVAL;
28929a0bf528SMauro Carvalho Chehab error:
28939a0bf528SMauro Carvalho Chehab 	if (status < 0)
28943a4398f5SMauro Carvalho Chehab 		pr_err("Error %d on %s\n", status, __func__);
28959a0bf528SMauro Carvalho Chehab 	return status;
28969a0bf528SMauro Carvalho Chehab }
28979a0bf528SMauro Carvalho Chehab 
2898cd7a67a4SMauro Carvalho Chehab static int set_frequency_shifter(struct drxk_state *state,
2899cd7a67a4SMauro Carvalho Chehab 			       u16 intermediate_freqk_hz,
2900cd7a67a4SMauro Carvalho Chehab 			       s32 tuner_freq_offset, bool is_dtv)
29019a0bf528SMauro Carvalho Chehab {
2902cd7a67a4SMauro Carvalho Chehab 	bool select_pos_image = false;
2903cd7a67a4SMauro Carvalho Chehab 	u32 rf_freq_residual = tuner_freq_offset;
2904cd7a67a4SMauro Carvalho Chehab 	u32 fm_frequency_shift = 0;
2905cd7a67a4SMauro Carvalho Chehab 	bool tuner_mirror = !state->m_b_mirror_freq_spect;
2906cd7a67a4SMauro Carvalho Chehab 	u32 adc_freq;
2907cd7a67a4SMauro Carvalho Chehab 	bool adc_flip;
29089a0bf528SMauro Carvalho Chehab 	int status;
2909cd7a67a4SMauro Carvalho Chehab 	u32 if_freq_actual;
2910cd7a67a4SMauro Carvalho Chehab 	u32 sampling_frequency = (u32) (state->m_sys_clock_freq / 3);
2911cd7a67a4SMauro Carvalho Chehab 	u32 frequency_shift;
2912cd7a67a4SMauro Carvalho Chehab 	bool image_to_select;
29139a0bf528SMauro Carvalho Chehab 
29149a0bf528SMauro Carvalho Chehab 	dprintk(1, "\n");
29159a0bf528SMauro Carvalho Chehab 
29169a0bf528SMauro Carvalho Chehab 	/*
29179a0bf528SMauro Carvalho Chehab 	   Program frequency shifter
29189a0bf528SMauro Carvalho Chehab 	   No need to account for mirroring on RF
29199a0bf528SMauro Carvalho Chehab 	 */
2920cd7a67a4SMauro Carvalho Chehab 	if (is_dtv) {
2921cd7a67a4SMauro Carvalho Chehab 		if ((state->m_operation_mode == OM_QAM_ITU_A) ||
2922cd7a67a4SMauro Carvalho Chehab 		    (state->m_operation_mode == OM_QAM_ITU_C) ||
2923cd7a67a4SMauro Carvalho Chehab 		    (state->m_operation_mode == OM_DVBT))
2924cd7a67a4SMauro Carvalho Chehab 			select_pos_image = true;
29259a0bf528SMauro Carvalho Chehab 		else
2926cd7a67a4SMauro Carvalho Chehab 			select_pos_image = false;
29279a0bf528SMauro Carvalho Chehab 	}
2928cd7a67a4SMauro Carvalho Chehab 	if (tuner_mirror)
29299a0bf528SMauro Carvalho Chehab 		/* tuner doesn't mirror */
2930cd7a67a4SMauro Carvalho Chehab 		if_freq_actual = intermediate_freqk_hz +
2931cd7a67a4SMauro Carvalho Chehab 		    rf_freq_residual + fm_frequency_shift;
29329a0bf528SMauro Carvalho Chehab 	else
29339a0bf528SMauro Carvalho Chehab 		/* tuner mirrors */
2934cd7a67a4SMauro Carvalho Chehab 		if_freq_actual = intermediate_freqk_hz -
2935cd7a67a4SMauro Carvalho Chehab 		    rf_freq_residual - fm_frequency_shift;
2936cd7a67a4SMauro Carvalho Chehab 	if (if_freq_actual > sampling_frequency / 2) {
29379a0bf528SMauro Carvalho Chehab 		/* adc mirrors */
2938cd7a67a4SMauro Carvalho Chehab 		adc_freq = sampling_frequency - if_freq_actual;
2939cd7a67a4SMauro Carvalho Chehab 		adc_flip = true;
29409a0bf528SMauro Carvalho Chehab 	} else {
29419a0bf528SMauro Carvalho Chehab 		/* adc doesn't mirror */
2942cd7a67a4SMauro Carvalho Chehab 		adc_freq = if_freq_actual;
2943cd7a67a4SMauro Carvalho Chehab 		adc_flip = false;
29449a0bf528SMauro Carvalho Chehab 	}
29459a0bf528SMauro Carvalho Chehab 
2946cd7a67a4SMauro Carvalho Chehab 	frequency_shift = adc_freq;
2947cd7a67a4SMauro Carvalho Chehab 	image_to_select = state->m_rfmirror ^ tuner_mirror ^
2948cd7a67a4SMauro Carvalho Chehab 	    adc_flip ^ select_pos_image;
2949cd7a67a4SMauro Carvalho Chehab 	state->m_iqm_fs_rate_ofs =
2950cd7a67a4SMauro Carvalho Chehab 	    Frac28a((frequency_shift), sampling_frequency);
29519a0bf528SMauro Carvalho Chehab 
2952cd7a67a4SMauro Carvalho Chehab 	if (image_to_select)
2953cd7a67a4SMauro Carvalho Chehab 		state->m_iqm_fs_rate_ofs = ~state->m_iqm_fs_rate_ofs + 1;
29549a0bf528SMauro Carvalho Chehab 
29559a0bf528SMauro Carvalho Chehab 	/* Program frequency shifter with tuner offset compensation */
2956cd7a67a4SMauro Carvalho Chehab 	/* frequency_shift += tuner_freq_offset; TODO */
29579a0bf528SMauro Carvalho Chehab 	status = write32(state, IQM_FS_RATE_OFS_LO__A,
2958cd7a67a4SMauro Carvalho Chehab 			 state->m_iqm_fs_rate_ofs);
29599a0bf528SMauro Carvalho Chehab 	if (status < 0)
29603a4398f5SMauro Carvalho Chehab 		pr_err("Error %d on %s\n", status, __func__);
29619a0bf528SMauro Carvalho Chehab 	return status;
29629a0bf528SMauro Carvalho Chehab }
29639a0bf528SMauro Carvalho Chehab 
2964cd7a67a4SMauro Carvalho Chehab static int init_agc(struct drxk_state *state, bool is_dtv)
29659a0bf528SMauro Carvalho Chehab {
2966cd7a67a4SMauro Carvalho Chehab 	u16 ingain_tgt = 0;
2967cd7a67a4SMauro Carvalho Chehab 	u16 ingain_tgt_min = 0;
2968cd7a67a4SMauro Carvalho Chehab 	u16 ingain_tgt_max = 0;
2969cd7a67a4SMauro Carvalho Chehab 	u16 clp_cyclen = 0;
2970cd7a67a4SMauro Carvalho Chehab 	u16 clp_sum_min = 0;
2971cd7a67a4SMauro Carvalho Chehab 	u16 clp_dir_to = 0;
2972cd7a67a4SMauro Carvalho Chehab 	u16 sns_sum_min = 0;
2973cd7a67a4SMauro Carvalho Chehab 	u16 sns_sum_max = 0;
2974cd7a67a4SMauro Carvalho Chehab 	u16 clp_sum_max = 0;
2975cd7a67a4SMauro Carvalho Chehab 	u16 sns_dir_to = 0;
2976cd7a67a4SMauro Carvalho Chehab 	u16 ki_innergain_min = 0;
2977cd7a67a4SMauro Carvalho Chehab 	u16 if_iaccu_hi_tgt = 0;
2978cd7a67a4SMauro Carvalho Chehab 	u16 if_iaccu_hi_tgt_min = 0;
2979cd7a67a4SMauro Carvalho Chehab 	u16 if_iaccu_hi_tgt_max = 0;
29809a0bf528SMauro Carvalho Chehab 	u16 data = 0;
2981cd7a67a4SMauro Carvalho Chehab 	u16 fast_clp_ctrl_delay = 0;
2982cd7a67a4SMauro Carvalho Chehab 	u16 clp_ctrl_mode = 0;
29839a0bf528SMauro Carvalho Chehab 	int status = 0;
29849a0bf528SMauro Carvalho Chehab 
29859a0bf528SMauro Carvalho Chehab 	dprintk(1, "\n");
29869a0bf528SMauro Carvalho Chehab 
29879a0bf528SMauro Carvalho Chehab 	/* Common settings */
2988cd7a67a4SMauro Carvalho Chehab 	sns_sum_max = 1023;
2989cd7a67a4SMauro Carvalho Chehab 	if_iaccu_hi_tgt_min = 2047;
2990cd7a67a4SMauro Carvalho Chehab 	clp_cyclen = 500;
2991cd7a67a4SMauro Carvalho Chehab 	clp_sum_max = 1023;
29929a0bf528SMauro Carvalho Chehab 
29939a0bf528SMauro Carvalho Chehab 	/* AGCInit() not available for DVBT; init done in microcode */
2994cd7a67a4SMauro Carvalho Chehab 	if (!is_qam(state)) {
29953a4398f5SMauro Carvalho Chehab 		pr_err("%s: mode %d is not DVB-C\n",
29963a4398f5SMauro Carvalho Chehab 		       __func__, state->m_operation_mode);
29979a0bf528SMauro Carvalho Chehab 		return -EINVAL;
29989a0bf528SMauro Carvalho Chehab 	}
29999a0bf528SMauro Carvalho Chehab 
30009a0bf528SMauro Carvalho Chehab 	/* FIXME: Analog TV AGC require different settings */
30019a0bf528SMauro Carvalho Chehab 
30029a0bf528SMauro Carvalho Chehab 	/* Standard specific settings */
3003cd7a67a4SMauro Carvalho Chehab 	clp_sum_min = 8;
3004cd7a67a4SMauro Carvalho Chehab 	clp_dir_to = (u16) -9;
3005cd7a67a4SMauro Carvalho Chehab 	clp_ctrl_mode = 0;
3006cd7a67a4SMauro Carvalho Chehab 	sns_sum_min = 8;
3007cd7a67a4SMauro Carvalho Chehab 	sns_dir_to = (u16) -9;
3008cd7a67a4SMauro Carvalho Chehab 	ki_innergain_min = (u16) -1030;
3009cd7a67a4SMauro Carvalho Chehab 	if_iaccu_hi_tgt_max = 0x2380;
3010cd7a67a4SMauro Carvalho Chehab 	if_iaccu_hi_tgt = 0x2380;
3011cd7a67a4SMauro Carvalho Chehab 	ingain_tgt_min = 0x0511;
3012cd7a67a4SMauro Carvalho Chehab 	ingain_tgt = 0x0511;
3013cd7a67a4SMauro Carvalho Chehab 	ingain_tgt_max = 5119;
3014cd7a67a4SMauro Carvalho Chehab 	fast_clp_ctrl_delay = state->m_qam_if_agc_cfg.fast_clip_ctrl_delay;
30159a0bf528SMauro Carvalho Chehab 
3016cd7a67a4SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_AGC_FAST_CLP_CTRL_DELAY__A, fast_clp_ctrl_delay);
30179a0bf528SMauro Carvalho Chehab 	if (status < 0)
30189a0bf528SMauro Carvalho Chehab 		goto error;
30199a0bf528SMauro Carvalho Chehab 
3020cd7a67a4SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_AGC_CLP_CTRL_MODE__A, clp_ctrl_mode);
30219a0bf528SMauro Carvalho Chehab 	if (status < 0)
30229a0bf528SMauro Carvalho Chehab 		goto error;
3023cd7a67a4SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_AGC_INGAIN_TGT__A, ingain_tgt);
30249a0bf528SMauro Carvalho Chehab 	if (status < 0)
30259a0bf528SMauro Carvalho Chehab 		goto error;
3026cd7a67a4SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_AGC_INGAIN_TGT_MIN__A, ingain_tgt_min);
30279a0bf528SMauro Carvalho Chehab 	if (status < 0)
30289a0bf528SMauro Carvalho Chehab 		goto error;
3029cd7a67a4SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_AGC_INGAIN_TGT_MAX__A, ingain_tgt_max);
30309a0bf528SMauro Carvalho Chehab 	if (status < 0)
30319a0bf528SMauro Carvalho Chehab 		goto error;
3032cd7a67a4SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_AGC_IF_IACCU_HI_TGT_MIN__A, if_iaccu_hi_tgt_min);
30339a0bf528SMauro Carvalho Chehab 	if (status < 0)
30349a0bf528SMauro Carvalho Chehab 		goto error;
3035cd7a67a4SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A, if_iaccu_hi_tgt_max);
30369a0bf528SMauro Carvalho Chehab 	if (status < 0)
30379a0bf528SMauro Carvalho Chehab 		goto error;
30389a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_AGC_IF_IACCU_HI__A, 0);
30399a0bf528SMauro Carvalho Chehab 	if (status < 0)
30409a0bf528SMauro Carvalho Chehab 		goto error;
30419a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_AGC_IF_IACCU_LO__A, 0);
30429a0bf528SMauro Carvalho Chehab 	if (status < 0)
30439a0bf528SMauro Carvalho Chehab 		goto error;
30449a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_AGC_RF_IACCU_HI__A, 0);
30459a0bf528SMauro Carvalho Chehab 	if (status < 0)
30469a0bf528SMauro Carvalho Chehab 		goto error;
30479a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_AGC_RF_IACCU_LO__A, 0);
30489a0bf528SMauro Carvalho Chehab 	if (status < 0)
30499a0bf528SMauro Carvalho Chehab 		goto error;
3050cd7a67a4SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_AGC_CLP_SUM_MAX__A, clp_sum_max);
30519a0bf528SMauro Carvalho Chehab 	if (status < 0)
30529a0bf528SMauro Carvalho Chehab 		goto error;
3053cd7a67a4SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_AGC_SNS_SUM_MAX__A, sns_sum_max);
30549a0bf528SMauro Carvalho Chehab 	if (status < 0)
30559a0bf528SMauro Carvalho Chehab 		goto error;
30569a0bf528SMauro Carvalho Chehab 
3057cd7a67a4SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_AGC_KI_INNERGAIN_MIN__A, ki_innergain_min);
30589a0bf528SMauro Carvalho Chehab 	if (status < 0)
30599a0bf528SMauro Carvalho Chehab 		goto error;
3060cd7a67a4SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_AGC_IF_IACCU_HI_TGT__A, if_iaccu_hi_tgt);
30619a0bf528SMauro Carvalho Chehab 	if (status < 0)
30629a0bf528SMauro Carvalho Chehab 		goto error;
3063cd7a67a4SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_AGC_CLP_CYCLEN__A, clp_cyclen);
30649a0bf528SMauro Carvalho Chehab 	if (status < 0)
30659a0bf528SMauro Carvalho Chehab 		goto error;
30669a0bf528SMauro Carvalho Chehab 
30679a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_AGC_RF_SNS_DEV_MAX__A, 1023);
30689a0bf528SMauro Carvalho Chehab 	if (status < 0)
30699a0bf528SMauro Carvalho Chehab 		goto error;
30709a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_AGC_RF_SNS_DEV_MIN__A, (u16) -1023);
30719a0bf528SMauro Carvalho Chehab 	if (status < 0)
30729a0bf528SMauro Carvalho Chehab 		goto error;
30739a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_AGC_FAST_SNS_CTRL_DELAY__A, 50);
30749a0bf528SMauro Carvalho Chehab 	if (status < 0)
30759a0bf528SMauro Carvalho Chehab 		goto error;
30769a0bf528SMauro Carvalho Chehab 
30779a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_AGC_KI_MAXMINGAIN_TH__A, 20);
30789a0bf528SMauro Carvalho Chehab 	if (status < 0)
30799a0bf528SMauro Carvalho Chehab 		goto error;
3080cd7a67a4SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_AGC_CLP_SUM_MIN__A, clp_sum_min);
30819a0bf528SMauro Carvalho Chehab 	if (status < 0)
30829a0bf528SMauro Carvalho Chehab 		goto error;
3083cd7a67a4SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_AGC_SNS_SUM_MIN__A, sns_sum_min);
30849a0bf528SMauro Carvalho Chehab 	if (status < 0)
30859a0bf528SMauro Carvalho Chehab 		goto error;
3086cd7a67a4SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_AGC_CLP_DIR_TO__A, clp_dir_to);
30879a0bf528SMauro Carvalho Chehab 	if (status < 0)
30889a0bf528SMauro Carvalho Chehab 		goto error;
3089cd7a67a4SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_AGC_SNS_DIR_TO__A, sns_dir_to);
30909a0bf528SMauro Carvalho Chehab 	if (status < 0)
30919a0bf528SMauro Carvalho Chehab 		goto error;
30929a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_AGC_KI_MINGAIN__A, 0x7fff);
30939a0bf528SMauro Carvalho Chehab 	if (status < 0)
30949a0bf528SMauro Carvalho Chehab 		goto error;
30959a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_AGC_KI_MAXGAIN__A, 0x0);
30969a0bf528SMauro Carvalho Chehab 	if (status < 0)
30979a0bf528SMauro Carvalho Chehab 		goto error;
30989a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_AGC_KI_MIN__A, 0x0117);
30999a0bf528SMauro Carvalho Chehab 	if (status < 0)
31009a0bf528SMauro Carvalho Chehab 		goto error;
31019a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_AGC_KI_MAX__A, 0x0657);
31029a0bf528SMauro Carvalho Chehab 	if (status < 0)
31039a0bf528SMauro Carvalho Chehab 		goto error;
31049a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_AGC_CLP_SUM__A, 0);
31059a0bf528SMauro Carvalho Chehab 	if (status < 0)
31069a0bf528SMauro Carvalho Chehab 		goto error;
31079a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_AGC_CLP_CYCCNT__A, 0);
31089a0bf528SMauro Carvalho Chehab 	if (status < 0)
31099a0bf528SMauro Carvalho Chehab 		goto error;
31109a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_AGC_CLP_DIR_WD__A, 0);
31119a0bf528SMauro Carvalho Chehab 	if (status < 0)
31129a0bf528SMauro Carvalho Chehab 		goto error;
31139a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_AGC_CLP_DIR_STP__A, 1);
31149a0bf528SMauro Carvalho Chehab 	if (status < 0)
31159a0bf528SMauro Carvalho Chehab 		goto error;
31169a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_AGC_SNS_SUM__A, 0);
31179a0bf528SMauro Carvalho Chehab 	if (status < 0)
31189a0bf528SMauro Carvalho Chehab 		goto error;
31199a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_AGC_SNS_CYCCNT__A, 0);
31209a0bf528SMauro Carvalho Chehab 	if (status < 0)
31219a0bf528SMauro Carvalho Chehab 		goto error;
31229a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_AGC_SNS_DIR_WD__A, 0);
31239a0bf528SMauro Carvalho Chehab 	if (status < 0)
31249a0bf528SMauro Carvalho Chehab 		goto error;
31259a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_AGC_SNS_DIR_STP__A, 1);
31269a0bf528SMauro Carvalho Chehab 	if (status < 0)
31279a0bf528SMauro Carvalho Chehab 		goto error;
31289a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_AGC_SNS_CYCLEN__A, 500);
31299a0bf528SMauro Carvalho Chehab 	if (status < 0)
31309a0bf528SMauro Carvalho Chehab 		goto error;
31319a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_AGC_KI_CYCLEN__A, 500);
31329a0bf528SMauro Carvalho Chehab 	if (status < 0)
31339a0bf528SMauro Carvalho Chehab 		goto error;
31349a0bf528SMauro Carvalho Chehab 
31359a0bf528SMauro Carvalho Chehab 	/* Initialize inner-loop KI gain factors */
31369a0bf528SMauro Carvalho Chehab 	status = read16(state, SCU_RAM_AGC_KI__A, &data);
31379a0bf528SMauro Carvalho Chehab 	if (status < 0)
31389a0bf528SMauro Carvalho Chehab 		goto error;
31399a0bf528SMauro Carvalho Chehab 
31409a0bf528SMauro Carvalho Chehab 	data = 0x0657;
31419a0bf528SMauro Carvalho Chehab 	data &= ~SCU_RAM_AGC_KI_RF__M;
31429a0bf528SMauro Carvalho Chehab 	data |= (DRXK_KI_RAGC_QAM << SCU_RAM_AGC_KI_RF__B);
31439a0bf528SMauro Carvalho Chehab 	data &= ~SCU_RAM_AGC_KI_IF__M;
31449a0bf528SMauro Carvalho Chehab 	data |= (DRXK_KI_IAGC_QAM << SCU_RAM_AGC_KI_IF__B);
31459a0bf528SMauro Carvalho Chehab 
31469a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_AGC_KI__A, data);
31479a0bf528SMauro Carvalho Chehab error:
31489a0bf528SMauro Carvalho Chehab 	if (status < 0)
31493a4398f5SMauro Carvalho Chehab 		pr_err("Error %d on %s\n", status, __func__);
31509a0bf528SMauro Carvalho Chehab 	return status;
31519a0bf528SMauro Carvalho Chehab }
31529a0bf528SMauro Carvalho Chehab 
3153cd7a67a4SMauro Carvalho Chehab static int dvbtqam_get_acc_pkt_err(struct drxk_state *state, u16 *packet_err)
31549a0bf528SMauro Carvalho Chehab {
31559a0bf528SMauro Carvalho Chehab 	int status;
31569a0bf528SMauro Carvalho Chehab 
31579a0bf528SMauro Carvalho Chehab 	dprintk(1, "\n");
3158cd7a67a4SMauro Carvalho Chehab 	if (packet_err == NULL)
31599a0bf528SMauro Carvalho Chehab 		status = write16(state, SCU_RAM_FEC_ACCUM_PKT_FAILURES__A, 0);
31609a0bf528SMauro Carvalho Chehab 	else
3161cd7a67a4SMauro Carvalho Chehab 		status = read16(state, SCU_RAM_FEC_ACCUM_PKT_FAILURES__A, packet_err);
31629a0bf528SMauro Carvalho Chehab 	if (status < 0)
31633a4398f5SMauro Carvalho Chehab 		pr_err("Error %d on %s\n", status, __func__);
31649a0bf528SMauro Carvalho Chehab 	return status;
31659a0bf528SMauro Carvalho Chehab }
31669a0bf528SMauro Carvalho Chehab 
3167cd7a67a4SMauro Carvalho Chehab static int dvbt_sc_command(struct drxk_state *state,
31689a0bf528SMauro Carvalho Chehab 			 u16 cmd, u16 subcmd,
31699a0bf528SMauro Carvalho Chehab 			 u16 param0, u16 param1, u16 param2,
31709a0bf528SMauro Carvalho Chehab 			 u16 param3, u16 param4)
31719a0bf528SMauro Carvalho Chehab {
3172cd7a67a4SMauro Carvalho Chehab 	u16 cur_cmd = 0;
3173cd7a67a4SMauro Carvalho Chehab 	u16 err_code = 0;
3174cd7a67a4SMauro Carvalho Chehab 	u16 retry_cnt = 0;
3175cd7a67a4SMauro Carvalho Chehab 	u16 sc_exec = 0;
31769a0bf528SMauro Carvalho Chehab 	int status;
31779a0bf528SMauro Carvalho Chehab 
31789a0bf528SMauro Carvalho Chehab 	dprintk(1, "\n");
3179cd7a67a4SMauro Carvalho Chehab 	status = read16(state, OFDM_SC_COMM_EXEC__A, &sc_exec);
3180cd7a67a4SMauro Carvalho Chehab 	if (sc_exec != 1) {
31819a0bf528SMauro Carvalho Chehab 		/* SC is not running */
31829a0bf528SMauro Carvalho Chehab 		status = -EINVAL;
31839a0bf528SMauro Carvalho Chehab 	}
31849a0bf528SMauro Carvalho Chehab 	if (status < 0)
31859a0bf528SMauro Carvalho Chehab 		goto error;
31869a0bf528SMauro Carvalho Chehab 
31879a0bf528SMauro Carvalho Chehab 	/* Wait until sc is ready to receive command */
3188cd7a67a4SMauro Carvalho Chehab 	retry_cnt = 0;
31899a0bf528SMauro Carvalho Chehab 	do {
31909a0bf528SMauro Carvalho Chehab 		msleep(1);
3191cd7a67a4SMauro Carvalho Chehab 		status = read16(state, OFDM_SC_RA_RAM_CMD__A, &cur_cmd);
3192cd7a67a4SMauro Carvalho Chehab 		retry_cnt++;
3193cd7a67a4SMauro Carvalho Chehab 	} while ((cur_cmd != 0) && (retry_cnt < DRXK_MAX_RETRIES));
3194cd7a67a4SMauro Carvalho Chehab 	if (retry_cnt >= DRXK_MAX_RETRIES && (status < 0))
31959a0bf528SMauro Carvalho Chehab 		goto error;
31969a0bf528SMauro Carvalho Chehab 
31979a0bf528SMauro Carvalho Chehab 	/* Write sub-command */
31989a0bf528SMauro Carvalho Chehab 	switch (cmd) {
31999a0bf528SMauro Carvalho Chehab 		/* All commands using sub-cmd */
32009a0bf528SMauro Carvalho Chehab 	case OFDM_SC_RA_RAM_CMD_PROC_START:
32019a0bf528SMauro Carvalho Chehab 	case OFDM_SC_RA_RAM_CMD_SET_PREF_PARAM:
32029a0bf528SMauro Carvalho Chehab 	case OFDM_SC_RA_RAM_CMD_PROGRAM_PARAM:
32039a0bf528SMauro Carvalho Chehab 		status = write16(state, OFDM_SC_RA_RAM_CMD_ADDR__A, subcmd);
32049a0bf528SMauro Carvalho Chehab 		if (status < 0)
32059a0bf528SMauro Carvalho Chehab 			goto error;
32069a0bf528SMauro Carvalho Chehab 		break;
32079a0bf528SMauro Carvalho Chehab 	default:
32089a0bf528SMauro Carvalho Chehab 		/* Do nothing */
32099a0bf528SMauro Carvalho Chehab 		break;
32109a0bf528SMauro Carvalho Chehab 	}
32119a0bf528SMauro Carvalho Chehab 
32129a0bf528SMauro Carvalho Chehab 	/* Write needed parameters and the command */
32139a0bf528SMauro Carvalho Chehab 	switch (cmd) {
32149a0bf528SMauro Carvalho Chehab 		/* All commands using 5 parameters */
32159a0bf528SMauro Carvalho Chehab 		/* All commands using 4 parameters */
32169a0bf528SMauro Carvalho Chehab 		/* All commands using 3 parameters */
32179a0bf528SMauro Carvalho Chehab 		/* All commands using 2 parameters */
32189a0bf528SMauro Carvalho Chehab 	case OFDM_SC_RA_RAM_CMD_PROC_START:
32199a0bf528SMauro Carvalho Chehab 	case OFDM_SC_RA_RAM_CMD_SET_PREF_PARAM:
32209a0bf528SMauro Carvalho Chehab 	case OFDM_SC_RA_RAM_CMD_PROGRAM_PARAM:
32219a0bf528SMauro Carvalho Chehab 		status = write16(state, OFDM_SC_RA_RAM_PARAM1__A, param1);
32229a0bf528SMauro Carvalho Chehab 		/* All commands using 1 parameters */
32239a0bf528SMauro Carvalho Chehab 	case OFDM_SC_RA_RAM_CMD_SET_ECHO_TIMING:
32249a0bf528SMauro Carvalho Chehab 	case OFDM_SC_RA_RAM_CMD_USER_IO:
32259a0bf528SMauro Carvalho Chehab 		status = write16(state, OFDM_SC_RA_RAM_PARAM0__A, param0);
32269a0bf528SMauro Carvalho Chehab 		/* All commands using 0 parameters */
32279a0bf528SMauro Carvalho Chehab 	case OFDM_SC_RA_RAM_CMD_GET_OP_PARAM:
32289a0bf528SMauro Carvalho Chehab 	case OFDM_SC_RA_RAM_CMD_NULL:
32299a0bf528SMauro Carvalho Chehab 		/* Write command */
32309a0bf528SMauro Carvalho Chehab 		status = write16(state, OFDM_SC_RA_RAM_CMD__A, cmd);
32319a0bf528SMauro Carvalho Chehab 		break;
32329a0bf528SMauro Carvalho Chehab 	default:
32339a0bf528SMauro Carvalho Chehab 		/* Unknown command */
32349a0bf528SMauro Carvalho Chehab 		status = -EINVAL;
32359a0bf528SMauro Carvalho Chehab 	}
32369a0bf528SMauro Carvalho Chehab 	if (status < 0)
32379a0bf528SMauro Carvalho Chehab 		goto error;
32389a0bf528SMauro Carvalho Chehab 
32399a0bf528SMauro Carvalho Chehab 	/* Wait until sc is ready processing command */
3240cd7a67a4SMauro Carvalho Chehab 	retry_cnt = 0;
32419a0bf528SMauro Carvalho Chehab 	do {
32429a0bf528SMauro Carvalho Chehab 		msleep(1);
3243cd7a67a4SMauro Carvalho Chehab 		status = read16(state, OFDM_SC_RA_RAM_CMD__A, &cur_cmd);
3244cd7a67a4SMauro Carvalho Chehab 		retry_cnt++;
3245cd7a67a4SMauro Carvalho Chehab 	} while ((cur_cmd != 0) && (retry_cnt < DRXK_MAX_RETRIES));
3246cd7a67a4SMauro Carvalho Chehab 	if (retry_cnt >= DRXK_MAX_RETRIES && (status < 0))
32479a0bf528SMauro Carvalho Chehab 		goto error;
32489a0bf528SMauro Carvalho Chehab 
32499a0bf528SMauro Carvalho Chehab 	/* Check for illegal cmd */
3250cd7a67a4SMauro Carvalho Chehab 	status = read16(state, OFDM_SC_RA_RAM_CMD_ADDR__A, &err_code);
3251cd7a67a4SMauro Carvalho Chehab 	if (err_code == 0xFFFF) {
32529a0bf528SMauro Carvalho Chehab 		/* illegal command */
32539a0bf528SMauro Carvalho Chehab 		status = -EINVAL;
32549a0bf528SMauro Carvalho Chehab 	}
32559a0bf528SMauro Carvalho Chehab 	if (status < 0)
32569a0bf528SMauro Carvalho Chehab 		goto error;
32579a0bf528SMauro Carvalho Chehab 
32589a0bf528SMauro Carvalho Chehab 	/* Retreive results parameters from SC */
32599a0bf528SMauro Carvalho Chehab 	switch (cmd) {
32609a0bf528SMauro Carvalho Chehab 		/* All commands yielding 5 results */
32619a0bf528SMauro Carvalho Chehab 		/* All commands yielding 4 results */
32629a0bf528SMauro Carvalho Chehab 		/* All commands yielding 3 results */
32639a0bf528SMauro Carvalho Chehab 		/* All commands yielding 2 results */
32649a0bf528SMauro Carvalho Chehab 		/* All commands yielding 1 result */
32659a0bf528SMauro Carvalho Chehab 	case OFDM_SC_RA_RAM_CMD_USER_IO:
32669a0bf528SMauro Carvalho Chehab 	case OFDM_SC_RA_RAM_CMD_GET_OP_PARAM:
32679a0bf528SMauro Carvalho Chehab 		status = read16(state, OFDM_SC_RA_RAM_PARAM0__A, &(param0));
32689a0bf528SMauro Carvalho Chehab 		/* All commands yielding 0 results */
32699a0bf528SMauro Carvalho Chehab 	case OFDM_SC_RA_RAM_CMD_SET_ECHO_TIMING:
32709a0bf528SMauro Carvalho Chehab 	case OFDM_SC_RA_RAM_CMD_SET_TIMER:
32719a0bf528SMauro Carvalho Chehab 	case OFDM_SC_RA_RAM_CMD_PROC_START:
32729a0bf528SMauro Carvalho Chehab 	case OFDM_SC_RA_RAM_CMD_SET_PREF_PARAM:
32739a0bf528SMauro Carvalho Chehab 	case OFDM_SC_RA_RAM_CMD_PROGRAM_PARAM:
32749a0bf528SMauro Carvalho Chehab 	case OFDM_SC_RA_RAM_CMD_NULL:
32759a0bf528SMauro Carvalho Chehab 		break;
32769a0bf528SMauro Carvalho Chehab 	default:
32779a0bf528SMauro Carvalho Chehab 		/* Unknown command */
32789a0bf528SMauro Carvalho Chehab 		status = -EINVAL;
32799a0bf528SMauro Carvalho Chehab 		break;
32809a0bf528SMauro Carvalho Chehab 	}			/* switch (cmd->cmd) */
32819a0bf528SMauro Carvalho Chehab error:
32829a0bf528SMauro Carvalho Chehab 	if (status < 0)
32833a4398f5SMauro Carvalho Chehab 		pr_err("Error %d on %s\n", status, __func__);
32849a0bf528SMauro Carvalho Chehab 	return status;
32859a0bf528SMauro Carvalho Chehab }
32869a0bf528SMauro Carvalho Chehab 
3287cd7a67a4SMauro Carvalho Chehab static int power_up_dvbt(struct drxk_state *state)
32889a0bf528SMauro Carvalho Chehab {
3289cd7a67a4SMauro Carvalho Chehab 	enum drx_power_mode power_mode = DRX_POWER_UP;
32909a0bf528SMauro Carvalho Chehab 	int status;
32919a0bf528SMauro Carvalho Chehab 
32929a0bf528SMauro Carvalho Chehab 	dprintk(1, "\n");
3293cd7a67a4SMauro Carvalho Chehab 	status = ctrl_power_mode(state, &power_mode);
32949a0bf528SMauro Carvalho Chehab 	if (status < 0)
32953a4398f5SMauro Carvalho Chehab 		pr_err("Error %d on %s\n", status, __func__);
32969a0bf528SMauro Carvalho Chehab 	return status;
32979a0bf528SMauro Carvalho Chehab }
32989a0bf528SMauro Carvalho Chehab 
3299cd7a67a4SMauro Carvalho Chehab static int dvbt_ctrl_set_inc_enable(struct drxk_state *state, bool *enabled)
33009a0bf528SMauro Carvalho Chehab {
33019a0bf528SMauro Carvalho Chehab 	int status;
33029a0bf528SMauro Carvalho Chehab 
33039a0bf528SMauro Carvalho Chehab 	dprintk(1, "\n");
33049a0bf528SMauro Carvalho Chehab 	if (*enabled == true)
33059a0bf528SMauro Carvalho Chehab 		status = write16(state, IQM_CF_BYPASSDET__A, 0);
33069a0bf528SMauro Carvalho Chehab 	else
33079a0bf528SMauro Carvalho Chehab 		status = write16(state, IQM_CF_BYPASSDET__A, 1);
33089a0bf528SMauro Carvalho Chehab 	if (status < 0)
33093a4398f5SMauro Carvalho Chehab 		pr_err("Error %d on %s\n", status, __func__);
33109a0bf528SMauro Carvalho Chehab 	return status;
33119a0bf528SMauro Carvalho Chehab }
33129a0bf528SMauro Carvalho Chehab 
33139a0bf528SMauro Carvalho Chehab #define DEFAULT_FR_THRES_8K     4000
3314cd7a67a4SMauro Carvalho Chehab static int dvbt_ctrl_set_fr_enable(struct drxk_state *state, bool *enabled)
33159a0bf528SMauro Carvalho Chehab {
33169a0bf528SMauro Carvalho Chehab 
33179a0bf528SMauro Carvalho Chehab 	int status;
33189a0bf528SMauro Carvalho Chehab 
33199a0bf528SMauro Carvalho Chehab 	dprintk(1, "\n");
33209a0bf528SMauro Carvalho Chehab 	if (*enabled == true) {
33219a0bf528SMauro Carvalho Chehab 		/* write mask to 1 */
33229a0bf528SMauro Carvalho Chehab 		status = write16(state, OFDM_SC_RA_RAM_FR_THRES_8K__A,
33239a0bf528SMauro Carvalho Chehab 				   DEFAULT_FR_THRES_8K);
33249a0bf528SMauro Carvalho Chehab 	} else {
33259a0bf528SMauro Carvalho Chehab 		/* write mask to 0 */
33269a0bf528SMauro Carvalho Chehab 		status = write16(state, OFDM_SC_RA_RAM_FR_THRES_8K__A, 0);
33279a0bf528SMauro Carvalho Chehab 	}
33289a0bf528SMauro Carvalho Chehab 	if (status < 0)
33293a4398f5SMauro Carvalho Chehab 		pr_err("Error %d on %s\n", status, __func__);
33309a0bf528SMauro Carvalho Chehab 
33319a0bf528SMauro Carvalho Chehab 	return status;
33329a0bf528SMauro Carvalho Chehab }
33339a0bf528SMauro Carvalho Chehab 
3334cd7a67a4SMauro Carvalho Chehab static int dvbt_ctrl_set_echo_threshold(struct drxk_state *state,
3335cd7a67a4SMauro Carvalho Chehab 				    struct drxk_cfg_dvbt_echo_thres_t *echo_thres)
33369a0bf528SMauro Carvalho Chehab {
33379a0bf528SMauro Carvalho Chehab 	u16 data = 0;
33389a0bf528SMauro Carvalho Chehab 	int status;
33399a0bf528SMauro Carvalho Chehab 
33409a0bf528SMauro Carvalho Chehab 	dprintk(1, "\n");
33419a0bf528SMauro Carvalho Chehab 	status = read16(state, OFDM_SC_RA_RAM_ECHO_THRES__A, &data);
33429a0bf528SMauro Carvalho Chehab 	if (status < 0)
33439a0bf528SMauro Carvalho Chehab 		goto error;
33449a0bf528SMauro Carvalho Chehab 
3345cd7a67a4SMauro Carvalho Chehab 	switch (echo_thres->fft_mode) {
33469a0bf528SMauro Carvalho Chehab 	case DRX_FFTMODE_2K:
33479a0bf528SMauro Carvalho Chehab 		data &= ~OFDM_SC_RA_RAM_ECHO_THRES_2K__M;
3348cd7a67a4SMauro Carvalho Chehab 		data |= ((echo_thres->threshold <<
33499a0bf528SMauro Carvalho Chehab 			OFDM_SC_RA_RAM_ECHO_THRES_2K__B)
33509a0bf528SMauro Carvalho Chehab 			& (OFDM_SC_RA_RAM_ECHO_THRES_2K__M));
33519a0bf528SMauro Carvalho Chehab 		break;
33529a0bf528SMauro Carvalho Chehab 	case DRX_FFTMODE_8K:
33539a0bf528SMauro Carvalho Chehab 		data &= ~OFDM_SC_RA_RAM_ECHO_THRES_8K__M;
3354cd7a67a4SMauro Carvalho Chehab 		data |= ((echo_thres->threshold <<
33559a0bf528SMauro Carvalho Chehab 			OFDM_SC_RA_RAM_ECHO_THRES_8K__B)
33569a0bf528SMauro Carvalho Chehab 			& (OFDM_SC_RA_RAM_ECHO_THRES_8K__M));
33579a0bf528SMauro Carvalho Chehab 		break;
33589a0bf528SMauro Carvalho Chehab 	default:
33599a0bf528SMauro Carvalho Chehab 		return -EINVAL;
33609a0bf528SMauro Carvalho Chehab 	}
33619a0bf528SMauro Carvalho Chehab 
33629a0bf528SMauro Carvalho Chehab 	status = write16(state, OFDM_SC_RA_RAM_ECHO_THRES__A, data);
33639a0bf528SMauro Carvalho Chehab error:
33649a0bf528SMauro Carvalho Chehab 	if (status < 0)
33653a4398f5SMauro Carvalho Chehab 		pr_err("Error %d on %s\n", status, __func__);
33669a0bf528SMauro Carvalho Chehab 	return status;
33679a0bf528SMauro Carvalho Chehab }
33689a0bf528SMauro Carvalho Chehab 
3369cd7a67a4SMauro Carvalho Chehab static int dvbt_ctrl_set_sqi_speed(struct drxk_state *state,
3370cd7a67a4SMauro Carvalho Chehab 			       enum drxk_cfg_dvbt_sqi_speed *speed)
33719a0bf528SMauro Carvalho Chehab {
33729a0bf528SMauro Carvalho Chehab 	int status = -EINVAL;
33739a0bf528SMauro Carvalho Chehab 
33749a0bf528SMauro Carvalho Chehab 	dprintk(1, "\n");
33759a0bf528SMauro Carvalho Chehab 
33769a0bf528SMauro Carvalho Chehab 	switch (*speed) {
33779a0bf528SMauro Carvalho Chehab 	case DRXK_DVBT_SQI_SPEED_FAST:
33789a0bf528SMauro Carvalho Chehab 	case DRXK_DVBT_SQI_SPEED_MEDIUM:
33799a0bf528SMauro Carvalho Chehab 	case DRXK_DVBT_SQI_SPEED_SLOW:
33809a0bf528SMauro Carvalho Chehab 		break;
33819a0bf528SMauro Carvalho Chehab 	default:
33829a0bf528SMauro Carvalho Chehab 		goto error;
33839a0bf528SMauro Carvalho Chehab 	}
33849a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_FEC_PRE_RS_BER_FILTER_SH__A,
33859a0bf528SMauro Carvalho Chehab 			   (u16) *speed);
33869a0bf528SMauro Carvalho Chehab error:
33879a0bf528SMauro Carvalho Chehab 	if (status < 0)
33883a4398f5SMauro Carvalho Chehab 		pr_err("Error %d on %s\n", status, __func__);
33899a0bf528SMauro Carvalho Chehab 	return status;
33909a0bf528SMauro Carvalho Chehab }
33919a0bf528SMauro Carvalho Chehab 
33929a0bf528SMauro Carvalho Chehab /*============================================================================*/
33939a0bf528SMauro Carvalho Chehab 
33949a0bf528SMauro Carvalho Chehab /**
33959a0bf528SMauro Carvalho Chehab * \brief Activate DVBT specific presets
33969a0bf528SMauro Carvalho Chehab * \param demod instance of demodulator.
33979a0bf528SMauro Carvalho Chehab * \return DRXStatus_t.
33989a0bf528SMauro Carvalho Chehab *
33999a0bf528SMauro Carvalho Chehab * Called in DVBTSetStandard
34009a0bf528SMauro Carvalho Chehab *
34019a0bf528SMauro Carvalho Chehab */
3402cd7a67a4SMauro Carvalho Chehab static int dvbt_activate_presets(struct drxk_state *state)
34039a0bf528SMauro Carvalho Chehab {
34049a0bf528SMauro Carvalho Chehab 	int status;
34059a0bf528SMauro Carvalho Chehab 	bool setincenable = false;
34069a0bf528SMauro Carvalho Chehab 	bool setfrenable = true;
34079a0bf528SMauro Carvalho Chehab 
3408cd7a67a4SMauro Carvalho Chehab 	struct drxk_cfg_dvbt_echo_thres_t echo_thres2k = { 0, DRX_FFTMODE_2K };
3409cd7a67a4SMauro Carvalho Chehab 	struct drxk_cfg_dvbt_echo_thres_t echo_thres8k = { 0, DRX_FFTMODE_8K };
34109a0bf528SMauro Carvalho Chehab 
34119a0bf528SMauro Carvalho Chehab 	dprintk(1, "\n");
3412cd7a67a4SMauro Carvalho Chehab 	status = dvbt_ctrl_set_inc_enable(state, &setincenable);
34139a0bf528SMauro Carvalho Chehab 	if (status < 0)
34149a0bf528SMauro Carvalho Chehab 		goto error;
3415cd7a67a4SMauro Carvalho Chehab 	status = dvbt_ctrl_set_fr_enable(state, &setfrenable);
34169a0bf528SMauro Carvalho Chehab 	if (status < 0)
34179a0bf528SMauro Carvalho Chehab 		goto error;
3418cd7a67a4SMauro Carvalho Chehab 	status = dvbt_ctrl_set_echo_threshold(state, &echo_thres2k);
34199a0bf528SMauro Carvalho Chehab 	if (status < 0)
34209a0bf528SMauro Carvalho Chehab 		goto error;
3421cd7a67a4SMauro Carvalho Chehab 	status = dvbt_ctrl_set_echo_threshold(state, &echo_thres8k);
34229a0bf528SMauro Carvalho Chehab 	if (status < 0)
34239a0bf528SMauro Carvalho Chehab 		goto error;
3424cd7a67a4SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_AGC_INGAIN_TGT_MAX__A, state->m_dvbt_if_agc_cfg.ingain_tgt_max);
34259a0bf528SMauro Carvalho Chehab error:
34269a0bf528SMauro Carvalho Chehab 	if (status < 0)
34273a4398f5SMauro Carvalho Chehab 		pr_err("Error %d on %s\n", status, __func__);
34289a0bf528SMauro Carvalho Chehab 	return status;
34299a0bf528SMauro Carvalho Chehab }
34309a0bf528SMauro Carvalho Chehab 
34319a0bf528SMauro Carvalho Chehab /*============================================================================*/
34329a0bf528SMauro Carvalho Chehab 
34339a0bf528SMauro Carvalho Chehab /**
34349a0bf528SMauro Carvalho Chehab * \brief Initialize channelswitch-independent settings for DVBT.
34359a0bf528SMauro Carvalho Chehab * \param demod instance of demodulator.
34369a0bf528SMauro Carvalho Chehab * \return DRXStatus_t.
34379a0bf528SMauro Carvalho Chehab *
34389a0bf528SMauro Carvalho Chehab * For ROM code channel filter taps are loaded from the bootloader. For microcode
34399a0bf528SMauro Carvalho Chehab * the DVB-T taps from the drxk_filters.h are used.
34409a0bf528SMauro Carvalho Chehab */
3441cd7a67a4SMauro Carvalho Chehab static int set_dvbt_standard(struct drxk_state *state,
3442cd7a67a4SMauro Carvalho Chehab 			   enum operation_mode o_mode)
34439a0bf528SMauro Carvalho Chehab {
3444cd7a67a4SMauro Carvalho Chehab 	u16 cmd_result = 0;
34459a0bf528SMauro Carvalho Chehab 	u16 data = 0;
34469a0bf528SMauro Carvalho Chehab 	int status;
34479a0bf528SMauro Carvalho Chehab 
34489a0bf528SMauro Carvalho Chehab 	dprintk(1, "\n");
34499a0bf528SMauro Carvalho Chehab 
3450cd7a67a4SMauro Carvalho Chehab 	power_up_dvbt(state);
34519a0bf528SMauro Carvalho Chehab 	/* added antenna switch */
3452cd7a67a4SMauro Carvalho Chehab 	switch_antenna_to_dvbt(state);
34539a0bf528SMauro Carvalho Chehab 	/* send OFDM reset command */
3454cd7a67a4SMauro Carvalho Chehab 	status = scu_command(state, SCU_RAM_COMMAND_STANDARD_OFDM | SCU_RAM_COMMAND_CMD_DEMOD_RESET, 0, NULL, 1, &cmd_result);
34559a0bf528SMauro Carvalho Chehab 	if (status < 0)
34569a0bf528SMauro Carvalho Chehab 		goto error;
34579a0bf528SMauro Carvalho Chehab 
34589a0bf528SMauro Carvalho Chehab 	/* send OFDM setenv command */
3459cd7a67a4SMauro Carvalho Chehab 	status = scu_command(state, SCU_RAM_COMMAND_STANDARD_OFDM | SCU_RAM_COMMAND_CMD_DEMOD_SET_ENV, 0, NULL, 1, &cmd_result);
34609a0bf528SMauro Carvalho Chehab 	if (status < 0)
34619a0bf528SMauro Carvalho Chehab 		goto error;
34629a0bf528SMauro Carvalho Chehab 
34639a0bf528SMauro Carvalho Chehab 	/* reset datapath for OFDM, processors first */
34649a0bf528SMauro Carvalho Chehab 	status = write16(state, OFDM_SC_COMM_EXEC__A, OFDM_SC_COMM_EXEC_STOP);
34659a0bf528SMauro Carvalho Chehab 	if (status < 0)
34669a0bf528SMauro Carvalho Chehab 		goto error;
34679a0bf528SMauro Carvalho Chehab 	status = write16(state, OFDM_LC_COMM_EXEC__A, OFDM_LC_COMM_EXEC_STOP);
34689a0bf528SMauro Carvalho Chehab 	if (status < 0)
34699a0bf528SMauro Carvalho Chehab 		goto error;
34709a0bf528SMauro Carvalho Chehab 	status = write16(state, IQM_COMM_EXEC__A, IQM_COMM_EXEC_B_STOP);
34719a0bf528SMauro Carvalho Chehab 	if (status < 0)
34729a0bf528SMauro Carvalho Chehab 		goto error;
34739a0bf528SMauro Carvalho Chehab 
34749a0bf528SMauro Carvalho Chehab 	/* IQM setup */
34759a0bf528SMauro Carvalho Chehab 	/* synchronize on ofdstate->m_festart */
34769a0bf528SMauro Carvalho Chehab 	status = write16(state, IQM_AF_UPD_SEL__A, 1);
34779a0bf528SMauro Carvalho Chehab 	if (status < 0)
34789a0bf528SMauro Carvalho Chehab 		goto error;
34799a0bf528SMauro Carvalho Chehab 	/* window size for clipping ADC detection */
34809a0bf528SMauro Carvalho Chehab 	status = write16(state, IQM_AF_CLP_LEN__A, 0);
34819a0bf528SMauro Carvalho Chehab 	if (status < 0)
34829a0bf528SMauro Carvalho Chehab 		goto error;
34839a0bf528SMauro Carvalho Chehab 	/* window size for for sense pre-SAW detection */
34849a0bf528SMauro Carvalho Chehab 	status = write16(state, IQM_AF_SNS_LEN__A, 0);
34859a0bf528SMauro Carvalho Chehab 	if (status < 0)
34869a0bf528SMauro Carvalho Chehab 		goto error;
34879a0bf528SMauro Carvalho Chehab 	/* sense threshold for sense pre-SAW detection */
34889a0bf528SMauro Carvalho Chehab 	status = write16(state, IQM_AF_AMUX__A, IQM_AF_AMUX_SIGNAL2ADC);
34899a0bf528SMauro Carvalho Chehab 	if (status < 0)
34909a0bf528SMauro Carvalho Chehab 		goto error;
3491cd7a67a4SMauro Carvalho Chehab 	status = set_iqm_af(state, true);
34929a0bf528SMauro Carvalho Chehab 	if (status < 0)
34939a0bf528SMauro Carvalho Chehab 		goto error;
34949a0bf528SMauro Carvalho Chehab 
34959a0bf528SMauro Carvalho Chehab 	status = write16(state, IQM_AF_AGC_RF__A, 0);
34969a0bf528SMauro Carvalho Chehab 	if (status < 0)
34979a0bf528SMauro Carvalho Chehab 		goto error;
34989a0bf528SMauro Carvalho Chehab 
34999a0bf528SMauro Carvalho Chehab 	/* Impulse noise cruncher setup */
35009a0bf528SMauro Carvalho Chehab 	status = write16(state, IQM_AF_INC_LCT__A, 0);	/* crunch in IQM_CF */
35019a0bf528SMauro Carvalho Chehab 	if (status < 0)
35029a0bf528SMauro Carvalho Chehab 		goto error;
35039a0bf528SMauro Carvalho Chehab 	status = write16(state, IQM_CF_DET_LCT__A, 0);	/* detect in IQM_CF */
35049a0bf528SMauro Carvalho Chehab 	if (status < 0)
35059a0bf528SMauro Carvalho Chehab 		goto error;
35069a0bf528SMauro Carvalho Chehab 	status = write16(state, IQM_CF_WND_LEN__A, 3);	/* peak detector window length */
35079a0bf528SMauro Carvalho Chehab 	if (status < 0)
35089a0bf528SMauro Carvalho Chehab 		goto error;
35099a0bf528SMauro Carvalho Chehab 
35109a0bf528SMauro Carvalho Chehab 	status = write16(state, IQM_RC_STRETCH__A, 16);
35119a0bf528SMauro Carvalho Chehab 	if (status < 0)
35129a0bf528SMauro Carvalho Chehab 		goto error;
35139a0bf528SMauro Carvalho Chehab 	status = write16(state, IQM_CF_OUT_ENA__A, 0x4);	/* enable output 2 */
35149a0bf528SMauro Carvalho Chehab 	if (status < 0)
35159a0bf528SMauro Carvalho Chehab 		goto error;
35169a0bf528SMauro Carvalho Chehab 	status = write16(state, IQM_CF_DS_ENA__A, 0x4);	/* decimate output 2 */
35179a0bf528SMauro Carvalho Chehab 	if (status < 0)
35189a0bf528SMauro Carvalho Chehab 		goto error;
35199a0bf528SMauro Carvalho Chehab 	status = write16(state, IQM_CF_SCALE__A, 1600);
35209a0bf528SMauro Carvalho Chehab 	if (status < 0)
35219a0bf528SMauro Carvalho Chehab 		goto error;
35229a0bf528SMauro Carvalho Chehab 	status = write16(state, IQM_CF_SCALE_SH__A, 0);
35239a0bf528SMauro Carvalho Chehab 	if (status < 0)
35249a0bf528SMauro Carvalho Chehab 		goto error;
35259a0bf528SMauro Carvalho Chehab 
35269a0bf528SMauro Carvalho Chehab 	/* virtual clipping threshold for clipping ADC detection */
35279a0bf528SMauro Carvalho Chehab 	status = write16(state, IQM_AF_CLP_TH__A, 448);
35289a0bf528SMauro Carvalho Chehab 	if (status < 0)
35299a0bf528SMauro Carvalho Chehab 		goto error;
35309a0bf528SMauro Carvalho Chehab 	status = write16(state, IQM_CF_DATATH__A, 495);	/* crunching threshold */
35319a0bf528SMauro Carvalho Chehab 	if (status < 0)
35329a0bf528SMauro Carvalho Chehab 		goto error;
35339a0bf528SMauro Carvalho Chehab 
3534cd7a67a4SMauro Carvalho Chehab 	status = bl_chain_cmd(state, DRXK_BL_ROM_OFFSET_TAPS_DVBT, DRXK_BLCC_NR_ELEMENTS_TAPS, DRXK_BLC_TIMEOUT);
35359a0bf528SMauro Carvalho Chehab 	if (status < 0)
35369a0bf528SMauro Carvalho Chehab 		goto error;
35379a0bf528SMauro Carvalho Chehab 
35389a0bf528SMauro Carvalho Chehab 	status = write16(state, IQM_CF_PKDTH__A, 2);	/* peak detector threshold */
35399a0bf528SMauro Carvalho Chehab 	if (status < 0)
35409a0bf528SMauro Carvalho Chehab 		goto error;
35419a0bf528SMauro Carvalho Chehab 	status = write16(state, IQM_CF_POW_MEAS_LEN__A, 2);
35429a0bf528SMauro Carvalho Chehab 	if (status < 0)
35439a0bf528SMauro Carvalho Chehab 		goto error;
35449a0bf528SMauro Carvalho Chehab 	/* enable power measurement interrupt */
35459a0bf528SMauro Carvalho Chehab 	status = write16(state, IQM_CF_COMM_INT_MSK__A, 1);
35469a0bf528SMauro Carvalho Chehab 	if (status < 0)
35479a0bf528SMauro Carvalho Chehab 		goto error;
35489a0bf528SMauro Carvalho Chehab 	status = write16(state, IQM_COMM_EXEC__A, IQM_COMM_EXEC_B_ACTIVE);
35499a0bf528SMauro Carvalho Chehab 	if (status < 0)
35509a0bf528SMauro Carvalho Chehab 		goto error;
35519a0bf528SMauro Carvalho Chehab 
35529a0bf528SMauro Carvalho Chehab 	/* IQM will not be reset from here, sync ADC and update/init AGC */
3553cd7a67a4SMauro Carvalho Chehab 	status = adc_synchronization(state);
35549a0bf528SMauro Carvalho Chehab 	if (status < 0)
35559a0bf528SMauro Carvalho Chehab 		goto error;
3556cd7a67a4SMauro Carvalho Chehab 	status = set_pre_saw(state, &state->m_dvbt_pre_saw_cfg);
35579a0bf528SMauro Carvalho Chehab 	if (status < 0)
35589a0bf528SMauro Carvalho Chehab 		goto error;
35599a0bf528SMauro Carvalho Chehab 
35609a0bf528SMauro Carvalho Chehab 	/* Halt SCU to enable safe non-atomic accesses */
35619a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_COMM_EXEC__A, SCU_COMM_EXEC_HOLD);
35629a0bf528SMauro Carvalho Chehab 	if (status < 0)
35639a0bf528SMauro Carvalho Chehab 		goto error;
35649a0bf528SMauro Carvalho Chehab 
3565cd7a67a4SMauro Carvalho Chehab 	status = set_agc_rf(state, &state->m_dvbt_rf_agc_cfg, true);
35669a0bf528SMauro Carvalho Chehab 	if (status < 0)
35679a0bf528SMauro Carvalho Chehab 		goto error;
3568cd7a67a4SMauro Carvalho Chehab 	status = set_agc_if(state, &state->m_dvbt_if_agc_cfg, true);
35699a0bf528SMauro Carvalho Chehab 	if (status < 0)
35709a0bf528SMauro Carvalho Chehab 		goto error;
35719a0bf528SMauro Carvalho Chehab 
35729a0bf528SMauro Carvalho Chehab 	/* Set Noise Estimation notch width and enable DC fix */
35739a0bf528SMauro Carvalho Chehab 	status = read16(state, OFDM_SC_RA_RAM_CONFIG__A, &data);
35749a0bf528SMauro Carvalho Chehab 	if (status < 0)
35759a0bf528SMauro Carvalho Chehab 		goto error;
35769a0bf528SMauro Carvalho Chehab 	data |= OFDM_SC_RA_RAM_CONFIG_NE_FIX_ENABLE__M;
35779a0bf528SMauro Carvalho Chehab 	status = write16(state, OFDM_SC_RA_RAM_CONFIG__A, data);
35789a0bf528SMauro Carvalho Chehab 	if (status < 0)
35799a0bf528SMauro Carvalho Chehab 		goto error;
35809a0bf528SMauro Carvalho Chehab 
35819a0bf528SMauro Carvalho Chehab 	/* Activate SCU to enable SCU commands */
35829a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_COMM_EXEC__A, SCU_COMM_EXEC_ACTIVE);
35839a0bf528SMauro Carvalho Chehab 	if (status < 0)
35849a0bf528SMauro Carvalho Chehab 		goto error;
35859a0bf528SMauro Carvalho Chehab 
3586cd7a67a4SMauro Carvalho Chehab 	if (!state->m_drxk_a3_rom_code) {
3587cd7a67a4SMauro Carvalho Chehab 		/* AGCInit() is not done for DVBT, so set agcfast_clip_ctrl_delay  */
3588cd7a67a4SMauro Carvalho Chehab 		status = write16(state, SCU_RAM_AGC_FAST_CLP_CTRL_DELAY__A, state->m_dvbt_if_agc_cfg.fast_clip_ctrl_delay);
35899a0bf528SMauro Carvalho Chehab 		if (status < 0)
35909a0bf528SMauro Carvalho Chehab 			goto error;
35919a0bf528SMauro Carvalho Chehab 	}
35929a0bf528SMauro Carvalho Chehab 
35939a0bf528SMauro Carvalho Chehab 	/* OFDM_SC setup */
35949a0bf528SMauro Carvalho Chehab #ifdef COMPILE_FOR_NONRT
35959a0bf528SMauro Carvalho Chehab 	status = write16(state, OFDM_SC_RA_RAM_BE_OPT_DELAY__A, 1);
35969a0bf528SMauro Carvalho Chehab 	if (status < 0)
35979a0bf528SMauro Carvalho Chehab 		goto error;
35989a0bf528SMauro Carvalho Chehab 	status = write16(state, OFDM_SC_RA_RAM_BE_OPT_INIT_DELAY__A, 2);
35999a0bf528SMauro Carvalho Chehab 	if (status < 0)
36009a0bf528SMauro Carvalho Chehab 		goto error;
36019a0bf528SMauro Carvalho Chehab #endif
36029a0bf528SMauro Carvalho Chehab 
36039a0bf528SMauro Carvalho Chehab 	/* FEC setup */
36049a0bf528SMauro Carvalho Chehab 	status = write16(state, FEC_DI_INPUT_CTL__A, 1);	/* OFDM input */
36059a0bf528SMauro Carvalho Chehab 	if (status < 0)
36069a0bf528SMauro Carvalho Chehab 		goto error;
36079a0bf528SMauro Carvalho Chehab 
36089a0bf528SMauro Carvalho Chehab 
36099a0bf528SMauro Carvalho Chehab #ifdef COMPILE_FOR_NONRT
36109a0bf528SMauro Carvalho Chehab 	status = write16(state, FEC_RS_MEASUREMENT_PERIOD__A, 0x400);
36119a0bf528SMauro Carvalho Chehab 	if (status < 0)
36129a0bf528SMauro Carvalho Chehab 		goto error;
36139a0bf528SMauro Carvalho Chehab #else
36149a0bf528SMauro Carvalho Chehab 	status = write16(state, FEC_RS_MEASUREMENT_PERIOD__A, 0x1000);
36159a0bf528SMauro Carvalho Chehab 	if (status < 0)
36169a0bf528SMauro Carvalho Chehab 		goto error;
36179a0bf528SMauro Carvalho Chehab #endif
36189a0bf528SMauro Carvalho Chehab 	status = write16(state, FEC_RS_MEASUREMENT_PRESCALE__A, 0x0001);
36199a0bf528SMauro Carvalho Chehab 	if (status < 0)
36209a0bf528SMauro Carvalho Chehab 		goto error;
36219a0bf528SMauro Carvalho Chehab 
36229a0bf528SMauro Carvalho Chehab 	/* Setup MPEG bus */
3623cd7a67a4SMauro Carvalho Chehab 	status = mpegts_dto_setup(state, OM_DVBT);
36249a0bf528SMauro Carvalho Chehab 	if (status < 0)
36259a0bf528SMauro Carvalho Chehab 		goto error;
36269a0bf528SMauro Carvalho Chehab 	/* Set DVBT Presets */
3627cd7a67a4SMauro Carvalho Chehab 	status = dvbt_activate_presets(state);
36289a0bf528SMauro Carvalho Chehab 	if (status < 0)
36299a0bf528SMauro Carvalho Chehab 		goto error;
36309a0bf528SMauro Carvalho Chehab 
36319a0bf528SMauro Carvalho Chehab error:
36329a0bf528SMauro Carvalho Chehab 	if (status < 0)
36333a4398f5SMauro Carvalho Chehab 		pr_err("Error %d on %s\n", status, __func__);
36349a0bf528SMauro Carvalho Chehab 	return status;
36359a0bf528SMauro Carvalho Chehab }
36369a0bf528SMauro Carvalho Chehab 
36379a0bf528SMauro Carvalho Chehab /*============================================================================*/
36389a0bf528SMauro Carvalho Chehab /**
3639cd7a67a4SMauro Carvalho Chehab * \brief start dvbt demodulating for channel.
36409a0bf528SMauro Carvalho Chehab * \param demod instance of demodulator.
36419a0bf528SMauro Carvalho Chehab * \return DRXStatus_t.
36429a0bf528SMauro Carvalho Chehab */
3643cd7a67a4SMauro Carvalho Chehab static int dvbt_start(struct drxk_state *state)
36449a0bf528SMauro Carvalho Chehab {
36459a0bf528SMauro Carvalho Chehab 	u16 param1;
36469a0bf528SMauro Carvalho Chehab 	int status;
3647cd7a67a4SMauro Carvalho Chehab 	/* drxk_ofdm_sc_cmd_t scCmd; */
36489a0bf528SMauro Carvalho Chehab 
36499a0bf528SMauro Carvalho Chehab 	dprintk(1, "\n");
3650cd7a67a4SMauro Carvalho Chehab 	/* start correct processes to get in lock */
36519a0bf528SMauro Carvalho Chehab 	/* DRXK: OFDM_SC_RA_RAM_PROC_LOCKTRACK is no longer in mapfile! */
36529a0bf528SMauro Carvalho Chehab 	param1 = OFDM_SC_RA_RAM_LOCKTRACK_MIN;
3653cd7a67a4SMauro Carvalho Chehab 	status = dvbt_sc_command(state, OFDM_SC_RA_RAM_CMD_PROC_START, 0, OFDM_SC_RA_RAM_SW_EVENT_RUN_NMASK__M, param1, 0, 0, 0);
36549a0bf528SMauro Carvalho Chehab 	if (status < 0)
36559a0bf528SMauro Carvalho Chehab 		goto error;
3656cd7a67a4SMauro Carvalho Chehab 	/* start FEC OC */
3657cd7a67a4SMauro Carvalho Chehab 	status = mpegts_start(state);
36589a0bf528SMauro Carvalho Chehab 	if (status < 0)
36599a0bf528SMauro Carvalho Chehab 		goto error;
36609a0bf528SMauro Carvalho Chehab 	status = write16(state, FEC_COMM_EXEC__A, FEC_COMM_EXEC_ACTIVE);
36619a0bf528SMauro Carvalho Chehab 	if (status < 0)
36629a0bf528SMauro Carvalho Chehab 		goto error;
36639a0bf528SMauro Carvalho Chehab error:
36649a0bf528SMauro Carvalho Chehab 	if (status < 0)
36653a4398f5SMauro Carvalho Chehab 		pr_err("Error %d on %s\n", status, __func__);
36669a0bf528SMauro Carvalho Chehab 	return status;
36679a0bf528SMauro Carvalho Chehab }
36689a0bf528SMauro Carvalho Chehab 
36699a0bf528SMauro Carvalho Chehab 
36709a0bf528SMauro Carvalho Chehab /*============================================================================*/
36719a0bf528SMauro Carvalho Chehab 
36729a0bf528SMauro Carvalho Chehab /**
36739a0bf528SMauro Carvalho Chehab * \brief Set up dvbt demodulator for channel.
36749a0bf528SMauro Carvalho Chehab * \param demod instance of demodulator.
36759a0bf528SMauro Carvalho Chehab * \return DRXStatus_t.
36769a0bf528SMauro Carvalho Chehab * // original DVBTSetChannel()
36779a0bf528SMauro Carvalho Chehab */
3678cd7a67a4SMauro Carvalho Chehab static int set_dvbt(struct drxk_state *state, u16 intermediate_freqk_hz,
3679cd7a67a4SMauro Carvalho Chehab 		   s32 tuner_freq_offset)
36809a0bf528SMauro Carvalho Chehab {
3681cd7a67a4SMauro Carvalho Chehab 	u16 cmd_result = 0;
3682cd7a67a4SMauro Carvalho Chehab 	u16 transmission_params = 0;
3683cd7a67a4SMauro Carvalho Chehab 	u16 operation_mode = 0;
3684cd7a67a4SMauro Carvalho Chehab 	u32 iqm_rc_rate_ofs = 0;
36859a0bf528SMauro Carvalho Chehab 	u32 bandwidth = 0;
36869a0bf528SMauro Carvalho Chehab 	u16 param1;
36879a0bf528SMauro Carvalho Chehab 	int status;
36889a0bf528SMauro Carvalho Chehab 
3689cd7a67a4SMauro Carvalho Chehab 	dprintk(1, "IF =%d, TFO = %d\n", intermediate_freqk_hz, tuner_freq_offset);
36909a0bf528SMauro Carvalho Chehab 
3691cd7a67a4SMauro Carvalho Chehab 	status = scu_command(state, SCU_RAM_COMMAND_STANDARD_OFDM | SCU_RAM_COMMAND_CMD_DEMOD_STOP, 0, NULL, 1, &cmd_result);
36929a0bf528SMauro Carvalho Chehab 	if (status < 0)
36939a0bf528SMauro Carvalho Chehab 		goto error;
36949a0bf528SMauro Carvalho Chehab 
36959a0bf528SMauro Carvalho Chehab 	/* Halt SCU to enable safe non-atomic accesses */
36969a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_COMM_EXEC__A, SCU_COMM_EXEC_HOLD);
36979a0bf528SMauro Carvalho Chehab 	if (status < 0)
36989a0bf528SMauro Carvalho Chehab 		goto error;
36999a0bf528SMauro Carvalho Chehab 
37009a0bf528SMauro Carvalho Chehab 	/* Stop processors */
37019a0bf528SMauro Carvalho Chehab 	status = write16(state, OFDM_SC_COMM_EXEC__A, OFDM_SC_COMM_EXEC_STOP);
37029a0bf528SMauro Carvalho Chehab 	if (status < 0)
37039a0bf528SMauro Carvalho Chehab 		goto error;
37049a0bf528SMauro Carvalho Chehab 	status = write16(state, OFDM_LC_COMM_EXEC__A, OFDM_LC_COMM_EXEC_STOP);
37059a0bf528SMauro Carvalho Chehab 	if (status < 0)
37069a0bf528SMauro Carvalho Chehab 		goto error;
37079a0bf528SMauro Carvalho Chehab 
37089a0bf528SMauro Carvalho Chehab 	/* Mandatory fix, always stop CP, required to set spl offset back to
37099a0bf528SMauro Carvalho Chehab 		hardware default (is set to 0 by ucode during pilot detection */
37109a0bf528SMauro Carvalho Chehab 	status = write16(state, OFDM_CP_COMM_EXEC__A, OFDM_CP_COMM_EXEC_STOP);
37119a0bf528SMauro Carvalho Chehab 	if (status < 0)
37129a0bf528SMauro Carvalho Chehab 		goto error;
37139a0bf528SMauro Carvalho Chehab 
37149a0bf528SMauro Carvalho Chehab 	/*== Write channel settings to device =====================================*/
37159a0bf528SMauro Carvalho Chehab 
37169a0bf528SMauro Carvalho Chehab 	/* mode */
37179a0bf528SMauro Carvalho Chehab 	switch (state->props.transmission_mode) {
37189a0bf528SMauro Carvalho Chehab 	case TRANSMISSION_MODE_AUTO:
37199a0bf528SMauro Carvalho Chehab 	default:
3720cd7a67a4SMauro Carvalho Chehab 		operation_mode |= OFDM_SC_RA_RAM_OP_AUTO_MODE__M;
37219a0bf528SMauro Carvalho Chehab 		/* fall through , try first guess DRX_FFTMODE_8K */
37229a0bf528SMauro Carvalho Chehab 	case TRANSMISSION_MODE_8K:
3723cd7a67a4SMauro Carvalho Chehab 		transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_MODE_8K;
37249a0bf528SMauro Carvalho Chehab 		break;
37259a0bf528SMauro Carvalho Chehab 	case TRANSMISSION_MODE_2K:
3726cd7a67a4SMauro Carvalho Chehab 		transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_MODE_2K;
37279a0bf528SMauro Carvalho Chehab 		break;
37289a0bf528SMauro Carvalho Chehab 	}
37299a0bf528SMauro Carvalho Chehab 
37309a0bf528SMauro Carvalho Chehab 	/* guard */
37319a0bf528SMauro Carvalho Chehab 	switch (state->props.guard_interval) {
37329a0bf528SMauro Carvalho Chehab 	default:
37339a0bf528SMauro Carvalho Chehab 	case GUARD_INTERVAL_AUTO:
3734cd7a67a4SMauro Carvalho Chehab 		operation_mode |= OFDM_SC_RA_RAM_OP_AUTO_GUARD__M;
37359a0bf528SMauro Carvalho Chehab 		/* fall through , try first guess DRX_GUARD_1DIV4 */
37369a0bf528SMauro Carvalho Chehab 	case GUARD_INTERVAL_1_4:
3737cd7a67a4SMauro Carvalho Chehab 		transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_GUARD_4;
37389a0bf528SMauro Carvalho Chehab 		break;
37399a0bf528SMauro Carvalho Chehab 	case GUARD_INTERVAL_1_32:
3740cd7a67a4SMauro Carvalho Chehab 		transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_GUARD_32;
37419a0bf528SMauro Carvalho Chehab 		break;
37429a0bf528SMauro Carvalho Chehab 	case GUARD_INTERVAL_1_16:
3743cd7a67a4SMauro Carvalho Chehab 		transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_GUARD_16;
37449a0bf528SMauro Carvalho Chehab 		break;
37459a0bf528SMauro Carvalho Chehab 	case GUARD_INTERVAL_1_8:
3746cd7a67a4SMauro Carvalho Chehab 		transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_GUARD_8;
37479a0bf528SMauro Carvalho Chehab 		break;
37489a0bf528SMauro Carvalho Chehab 	}
37499a0bf528SMauro Carvalho Chehab 
37509a0bf528SMauro Carvalho Chehab 	/* hierarchy */
37519a0bf528SMauro Carvalho Chehab 	switch (state->props.hierarchy) {
37529a0bf528SMauro Carvalho Chehab 	case HIERARCHY_AUTO:
37539a0bf528SMauro Carvalho Chehab 	case HIERARCHY_NONE:
37549a0bf528SMauro Carvalho Chehab 	default:
3755cd7a67a4SMauro Carvalho Chehab 		operation_mode |= OFDM_SC_RA_RAM_OP_AUTO_HIER__M;
37569a0bf528SMauro Carvalho Chehab 		/* fall through , try first guess SC_RA_RAM_OP_PARAM_HIER_NO */
3757cd7a67a4SMauro Carvalho Chehab 		/* transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_HIER_NO; */
37589a0bf528SMauro Carvalho Chehab 		/* break; */
37599a0bf528SMauro Carvalho Chehab 	case HIERARCHY_1:
3760cd7a67a4SMauro Carvalho Chehab 		transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_HIER_A1;
37619a0bf528SMauro Carvalho Chehab 		break;
37629a0bf528SMauro Carvalho Chehab 	case HIERARCHY_2:
3763cd7a67a4SMauro Carvalho Chehab 		transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_HIER_A2;
37649a0bf528SMauro Carvalho Chehab 		break;
37659a0bf528SMauro Carvalho Chehab 	case HIERARCHY_4:
3766cd7a67a4SMauro Carvalho Chehab 		transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_HIER_A4;
37679a0bf528SMauro Carvalho Chehab 		break;
37689a0bf528SMauro Carvalho Chehab 	}
37699a0bf528SMauro Carvalho Chehab 
37709a0bf528SMauro Carvalho Chehab 
37719a0bf528SMauro Carvalho Chehab 	/* modulation */
37729a0bf528SMauro Carvalho Chehab 	switch (state->props.modulation) {
37739a0bf528SMauro Carvalho Chehab 	case QAM_AUTO:
37749a0bf528SMauro Carvalho Chehab 	default:
3775cd7a67a4SMauro Carvalho Chehab 		operation_mode |= OFDM_SC_RA_RAM_OP_AUTO_CONST__M;
37769a0bf528SMauro Carvalho Chehab 		/* fall through , try first guess DRX_CONSTELLATION_QAM64 */
37779a0bf528SMauro Carvalho Chehab 	case QAM_64:
3778cd7a67a4SMauro Carvalho Chehab 		transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_CONST_QAM64;
37799a0bf528SMauro Carvalho Chehab 		break;
37809a0bf528SMauro Carvalho Chehab 	case QPSK:
3781cd7a67a4SMauro Carvalho Chehab 		transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_CONST_QPSK;
37829a0bf528SMauro Carvalho Chehab 		break;
37839a0bf528SMauro Carvalho Chehab 	case QAM_16:
3784cd7a67a4SMauro Carvalho Chehab 		transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_CONST_QAM16;
37859a0bf528SMauro Carvalho Chehab 		break;
37869a0bf528SMauro Carvalho Chehab 	}
37879a0bf528SMauro Carvalho Chehab #if 0
37889a0bf528SMauro Carvalho Chehab 	/* No hierachical channels support in BDA */
37899a0bf528SMauro Carvalho Chehab 	/* Priority (only for hierarchical channels) */
37909a0bf528SMauro Carvalho Chehab 	switch (channel->priority) {
37919a0bf528SMauro Carvalho Chehab 	case DRX_PRIORITY_LOW:
3792cd7a67a4SMauro Carvalho Chehab 		transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_PRIO_LO;
3793cd7a67a4SMauro Carvalho Chehab 		WR16(dev_addr, OFDM_EC_SB_PRIOR__A,
37949a0bf528SMauro Carvalho Chehab 			OFDM_EC_SB_PRIOR_LO);
37959a0bf528SMauro Carvalho Chehab 		break;
37969a0bf528SMauro Carvalho Chehab 	case DRX_PRIORITY_HIGH:
3797cd7a67a4SMauro Carvalho Chehab 		transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_PRIO_HI;
3798cd7a67a4SMauro Carvalho Chehab 		WR16(dev_addr, OFDM_EC_SB_PRIOR__A,
37999a0bf528SMauro Carvalho Chehab 			OFDM_EC_SB_PRIOR_HI));
38009a0bf528SMauro Carvalho Chehab 		break;
38019a0bf528SMauro Carvalho Chehab 	case DRX_PRIORITY_UNKNOWN:	/* fall through */
38029a0bf528SMauro Carvalho Chehab 	default:
38039a0bf528SMauro Carvalho Chehab 		status = -EINVAL;
38049a0bf528SMauro Carvalho Chehab 		goto error;
38059a0bf528SMauro Carvalho Chehab 	}
38069a0bf528SMauro Carvalho Chehab #else
38079a0bf528SMauro Carvalho Chehab 	/* Set Priorty high */
3808cd7a67a4SMauro Carvalho Chehab 	transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_PRIO_HI;
38099a0bf528SMauro Carvalho Chehab 	status = write16(state, OFDM_EC_SB_PRIOR__A, OFDM_EC_SB_PRIOR_HI);
38109a0bf528SMauro Carvalho Chehab 	if (status < 0)
38119a0bf528SMauro Carvalho Chehab 		goto error;
38129a0bf528SMauro Carvalho Chehab #endif
38139a0bf528SMauro Carvalho Chehab 
38149a0bf528SMauro Carvalho Chehab 	/* coderate */
38159a0bf528SMauro Carvalho Chehab 	switch (state->props.code_rate_HP) {
38169a0bf528SMauro Carvalho Chehab 	case FEC_AUTO:
38179a0bf528SMauro Carvalho Chehab 	default:
3818cd7a67a4SMauro Carvalho Chehab 		operation_mode |= OFDM_SC_RA_RAM_OP_AUTO_RATE__M;
38199a0bf528SMauro Carvalho Chehab 		/* fall through , try first guess DRX_CODERATE_2DIV3 */
38209a0bf528SMauro Carvalho Chehab 	case FEC_2_3:
3821cd7a67a4SMauro Carvalho Chehab 		transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_RATE_2_3;
38229a0bf528SMauro Carvalho Chehab 		break;
38239a0bf528SMauro Carvalho Chehab 	case FEC_1_2:
3824cd7a67a4SMauro Carvalho Chehab 		transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_RATE_1_2;
38259a0bf528SMauro Carvalho Chehab 		break;
38269a0bf528SMauro Carvalho Chehab 	case FEC_3_4:
3827cd7a67a4SMauro Carvalho Chehab 		transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_RATE_3_4;
38289a0bf528SMauro Carvalho Chehab 		break;
38299a0bf528SMauro Carvalho Chehab 	case FEC_5_6:
3830cd7a67a4SMauro Carvalho Chehab 		transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_RATE_5_6;
38319a0bf528SMauro Carvalho Chehab 		break;
38329a0bf528SMauro Carvalho Chehab 	case FEC_7_8:
3833cd7a67a4SMauro Carvalho Chehab 		transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_RATE_7_8;
38349a0bf528SMauro Carvalho Chehab 		break;
38359a0bf528SMauro Carvalho Chehab 	}
38369a0bf528SMauro Carvalho Chehab 
38379a0bf528SMauro Carvalho Chehab 	/* SAW filter selection: normaly not necesarry, but if wanted
38389a0bf528SMauro Carvalho Chehab 		the application can select a SAW filter via the driver by using UIOs */
38399a0bf528SMauro Carvalho Chehab 	/* First determine real bandwidth (Hz) */
38409a0bf528SMauro Carvalho Chehab 	/* Also set delay for impulse noise cruncher */
38419a0bf528SMauro Carvalho Chehab 	/* Also set parameters for EC_OC fix, note EC_OC_REG_TMD_HIL_MAR is changed
38429a0bf528SMauro Carvalho Chehab 		by SC for fix for some 8K,1/8 guard but is restored by InitEC and ResetEC
38439a0bf528SMauro Carvalho Chehab 		functions */
38449a0bf528SMauro Carvalho Chehab 	switch (state->props.bandwidth_hz) {
38459a0bf528SMauro Carvalho Chehab 	case 0:
38469a0bf528SMauro Carvalho Chehab 		state->props.bandwidth_hz = 8000000;
38479a0bf528SMauro Carvalho Chehab 		/* fall though */
38489a0bf528SMauro Carvalho Chehab 	case 8000000:
38499a0bf528SMauro Carvalho Chehab 		bandwidth = DRXK_BANDWIDTH_8MHZ_IN_HZ;
38509a0bf528SMauro Carvalho Chehab 		status = write16(state, OFDM_SC_RA_RAM_SRMM_FIX_FACT_8K__A, 3052);
38519a0bf528SMauro Carvalho Chehab 		if (status < 0)
38529a0bf528SMauro Carvalho Chehab 			goto error;
38539a0bf528SMauro Carvalho Chehab 		/* cochannel protection for PAL 8 MHz */
38549a0bf528SMauro Carvalho Chehab 		status = write16(state, OFDM_SC_RA_RAM_NI_INIT_8K_PER_LEFT__A, 7);
38559a0bf528SMauro Carvalho Chehab 		if (status < 0)
38569a0bf528SMauro Carvalho Chehab 			goto error;
38579a0bf528SMauro Carvalho Chehab 		status = write16(state, OFDM_SC_RA_RAM_NI_INIT_8K_PER_RIGHT__A, 7);
38589a0bf528SMauro Carvalho Chehab 		if (status < 0)
38599a0bf528SMauro Carvalho Chehab 			goto error;
38609a0bf528SMauro Carvalho Chehab 		status = write16(state, OFDM_SC_RA_RAM_NI_INIT_2K_PER_LEFT__A, 7);
38619a0bf528SMauro Carvalho Chehab 		if (status < 0)
38629a0bf528SMauro Carvalho Chehab 			goto error;
38639a0bf528SMauro Carvalho Chehab 		status = write16(state, OFDM_SC_RA_RAM_NI_INIT_2K_PER_RIGHT__A, 1);
38649a0bf528SMauro Carvalho Chehab 		if (status < 0)
38659a0bf528SMauro Carvalho Chehab 			goto error;
38669a0bf528SMauro Carvalho Chehab 		break;
38679a0bf528SMauro Carvalho Chehab 	case 7000000:
38689a0bf528SMauro Carvalho Chehab 		bandwidth = DRXK_BANDWIDTH_7MHZ_IN_HZ;
38699a0bf528SMauro Carvalho Chehab 		status = write16(state, OFDM_SC_RA_RAM_SRMM_FIX_FACT_8K__A, 3491);
38709a0bf528SMauro Carvalho Chehab 		if (status < 0)
38719a0bf528SMauro Carvalho Chehab 			goto error;
38729a0bf528SMauro Carvalho Chehab 		/* cochannel protection for PAL 7 MHz */
38739a0bf528SMauro Carvalho Chehab 		status = write16(state, OFDM_SC_RA_RAM_NI_INIT_8K_PER_LEFT__A, 8);
38749a0bf528SMauro Carvalho Chehab 		if (status < 0)
38759a0bf528SMauro Carvalho Chehab 			goto error;
38769a0bf528SMauro Carvalho Chehab 		status = write16(state, OFDM_SC_RA_RAM_NI_INIT_8K_PER_RIGHT__A, 8);
38779a0bf528SMauro Carvalho Chehab 		if (status < 0)
38789a0bf528SMauro Carvalho Chehab 			goto error;
38799a0bf528SMauro Carvalho Chehab 		status = write16(state, OFDM_SC_RA_RAM_NI_INIT_2K_PER_LEFT__A, 4);
38809a0bf528SMauro Carvalho Chehab 		if (status < 0)
38819a0bf528SMauro Carvalho Chehab 			goto error;
38829a0bf528SMauro Carvalho Chehab 		status = write16(state, OFDM_SC_RA_RAM_NI_INIT_2K_PER_RIGHT__A, 1);
38839a0bf528SMauro Carvalho Chehab 		if (status < 0)
38849a0bf528SMauro Carvalho Chehab 			goto error;
38859a0bf528SMauro Carvalho Chehab 		break;
38869a0bf528SMauro Carvalho Chehab 	case 6000000:
38879a0bf528SMauro Carvalho Chehab 		bandwidth = DRXK_BANDWIDTH_6MHZ_IN_HZ;
38889a0bf528SMauro Carvalho Chehab 		status = write16(state, OFDM_SC_RA_RAM_SRMM_FIX_FACT_8K__A, 4073);
38899a0bf528SMauro Carvalho Chehab 		if (status < 0)
38909a0bf528SMauro Carvalho Chehab 			goto error;
38919a0bf528SMauro Carvalho Chehab 		/* cochannel protection for NTSC 6 MHz */
38929a0bf528SMauro Carvalho Chehab 		status = write16(state, OFDM_SC_RA_RAM_NI_INIT_8K_PER_LEFT__A, 19);
38939a0bf528SMauro Carvalho Chehab 		if (status < 0)
38949a0bf528SMauro Carvalho Chehab 			goto error;
38959a0bf528SMauro Carvalho Chehab 		status = write16(state, OFDM_SC_RA_RAM_NI_INIT_8K_PER_RIGHT__A, 19);
38969a0bf528SMauro Carvalho Chehab 		if (status < 0)
38979a0bf528SMauro Carvalho Chehab 			goto error;
38989a0bf528SMauro Carvalho Chehab 		status = write16(state, OFDM_SC_RA_RAM_NI_INIT_2K_PER_LEFT__A, 14);
38999a0bf528SMauro Carvalho Chehab 		if (status < 0)
39009a0bf528SMauro Carvalho Chehab 			goto error;
39019a0bf528SMauro Carvalho Chehab 		status = write16(state, OFDM_SC_RA_RAM_NI_INIT_2K_PER_RIGHT__A, 1);
39029a0bf528SMauro Carvalho Chehab 		if (status < 0)
39039a0bf528SMauro Carvalho Chehab 			goto error;
39049a0bf528SMauro Carvalho Chehab 		break;
39059a0bf528SMauro Carvalho Chehab 	default:
39069a0bf528SMauro Carvalho Chehab 		status = -EINVAL;
39079a0bf528SMauro Carvalho Chehab 		goto error;
39089a0bf528SMauro Carvalho Chehab 	}
39099a0bf528SMauro Carvalho Chehab 
3910cd7a67a4SMauro Carvalho Chehab 	if (iqm_rc_rate_ofs == 0) {
39119a0bf528SMauro Carvalho Chehab 		/* Now compute IQM_RC_RATE_OFS
39129a0bf528SMauro Carvalho Chehab 			(((SysFreq/BandWidth)/2)/2) -1) * 2^23)
39139a0bf528SMauro Carvalho Chehab 			=>
39149a0bf528SMauro Carvalho Chehab 			((SysFreq / BandWidth) * (2^21)) - (2^23)
39159a0bf528SMauro Carvalho Chehab 			*/
39169a0bf528SMauro Carvalho Chehab 		/* (SysFreq / BandWidth) * (2^28)  */
39179a0bf528SMauro Carvalho Chehab 		/* assert (MAX(sysClk)/MIN(bandwidth) < 16)
39189a0bf528SMauro Carvalho Chehab 			=> assert(MAX(sysClk) < 16*MIN(bandwidth))
39199a0bf528SMauro Carvalho Chehab 			=> assert(109714272 > 48000000) = true so Frac 28 can be used  */
3920cd7a67a4SMauro Carvalho Chehab 		iqm_rc_rate_ofs = Frac28a((u32)
3921cd7a67a4SMauro Carvalho Chehab 					((state->m_sys_clock_freq *
39229a0bf528SMauro Carvalho Chehab 						1000) / 3), bandwidth);
39239a0bf528SMauro Carvalho Chehab 		/* (SysFreq / BandWidth) * (2^21), rounding before truncating  */
3924cd7a67a4SMauro Carvalho Chehab 		if ((iqm_rc_rate_ofs & 0x7fL) >= 0x40)
3925cd7a67a4SMauro Carvalho Chehab 			iqm_rc_rate_ofs += 0x80L;
3926cd7a67a4SMauro Carvalho Chehab 		iqm_rc_rate_ofs = iqm_rc_rate_ofs >> 7;
39279a0bf528SMauro Carvalho Chehab 		/* ((SysFreq / BandWidth) * (2^21)) - (2^23)  */
3928cd7a67a4SMauro Carvalho Chehab 		iqm_rc_rate_ofs = iqm_rc_rate_ofs - (1 << 23);
39299a0bf528SMauro Carvalho Chehab 	}
39309a0bf528SMauro Carvalho Chehab 
3931cd7a67a4SMauro Carvalho Chehab 	iqm_rc_rate_ofs &=
39329a0bf528SMauro Carvalho Chehab 		((((u32) IQM_RC_RATE_OFS_HI__M) <<
39339a0bf528SMauro Carvalho Chehab 		IQM_RC_RATE_OFS_LO__W) | IQM_RC_RATE_OFS_LO__M);
3934cd7a67a4SMauro Carvalho Chehab 	status = write32(state, IQM_RC_RATE_OFS_LO__A, iqm_rc_rate_ofs);
39359a0bf528SMauro Carvalho Chehab 	if (status < 0)
39369a0bf528SMauro Carvalho Chehab 		goto error;
39379a0bf528SMauro Carvalho Chehab 
39389a0bf528SMauro Carvalho Chehab 	/* Bandwidth setting done */
39399a0bf528SMauro Carvalho Chehab 
39409a0bf528SMauro Carvalho Chehab #if 0
3941cd7a67a4SMauro Carvalho Chehab 	status = dvbt_set_frequency_shift(demod, channel, tuner_offset);
39429a0bf528SMauro Carvalho Chehab 	if (status < 0)
39439a0bf528SMauro Carvalho Chehab 		goto error;
39449a0bf528SMauro Carvalho Chehab #endif
3945cd7a67a4SMauro Carvalho Chehab 	status = set_frequency_shifter(state, intermediate_freqk_hz, tuner_freq_offset, true);
39469a0bf528SMauro Carvalho Chehab 	if (status < 0)
39479a0bf528SMauro Carvalho Chehab 		goto error;
39489a0bf528SMauro Carvalho Chehab 
3949cd7a67a4SMauro Carvalho Chehab 	/*== start SC, write channel settings to SC ===============================*/
39509a0bf528SMauro Carvalho Chehab 
39519a0bf528SMauro Carvalho Chehab 	/* Activate SCU to enable SCU commands */
39529a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_COMM_EXEC__A, SCU_COMM_EXEC_ACTIVE);
39539a0bf528SMauro Carvalho Chehab 	if (status < 0)
39549a0bf528SMauro Carvalho Chehab 		goto error;
39559a0bf528SMauro Carvalho Chehab 
39569a0bf528SMauro Carvalho Chehab 	/* Enable SC after setting all other parameters */
39579a0bf528SMauro Carvalho Chehab 	status = write16(state, OFDM_SC_COMM_STATE__A, 0);
39589a0bf528SMauro Carvalho Chehab 	if (status < 0)
39599a0bf528SMauro Carvalho Chehab 		goto error;
39609a0bf528SMauro Carvalho Chehab 	status = write16(state, OFDM_SC_COMM_EXEC__A, 1);
39619a0bf528SMauro Carvalho Chehab 	if (status < 0)
39629a0bf528SMauro Carvalho Chehab 		goto error;
39639a0bf528SMauro Carvalho Chehab 
39649a0bf528SMauro Carvalho Chehab 
3965cd7a67a4SMauro Carvalho Chehab 	status = scu_command(state, SCU_RAM_COMMAND_STANDARD_OFDM | SCU_RAM_COMMAND_CMD_DEMOD_START, 0, NULL, 1, &cmd_result);
39669a0bf528SMauro Carvalho Chehab 	if (status < 0)
39679a0bf528SMauro Carvalho Chehab 		goto error;
39689a0bf528SMauro Carvalho Chehab 
39699a0bf528SMauro Carvalho Chehab 	/* Write SC parameter registers, set all AUTO flags in operation mode */
39709a0bf528SMauro Carvalho Chehab 	param1 = (OFDM_SC_RA_RAM_OP_AUTO_MODE__M |
39719a0bf528SMauro Carvalho Chehab 			OFDM_SC_RA_RAM_OP_AUTO_GUARD__M |
39729a0bf528SMauro Carvalho Chehab 			OFDM_SC_RA_RAM_OP_AUTO_CONST__M |
39739a0bf528SMauro Carvalho Chehab 			OFDM_SC_RA_RAM_OP_AUTO_HIER__M |
39749a0bf528SMauro Carvalho Chehab 			OFDM_SC_RA_RAM_OP_AUTO_RATE__M);
3975cd7a67a4SMauro Carvalho Chehab 	status = dvbt_sc_command(state, OFDM_SC_RA_RAM_CMD_SET_PREF_PARAM,
3976cd7a67a4SMauro Carvalho Chehab 				0, transmission_params, param1, 0, 0, 0);
39779a0bf528SMauro Carvalho Chehab 	if (status < 0)
39789a0bf528SMauro Carvalho Chehab 		goto error;
39799a0bf528SMauro Carvalho Chehab 
3980cd7a67a4SMauro Carvalho Chehab 	if (!state->m_drxk_a3_rom_code)
3981cd7a67a4SMauro Carvalho Chehab 		status = dvbt_ctrl_set_sqi_speed(state, &state->m_sqi_speed);
39829a0bf528SMauro Carvalho Chehab error:
39839a0bf528SMauro Carvalho Chehab 	if (status < 0)
39843a4398f5SMauro Carvalho Chehab 		pr_err("Error %d on %s\n", status, __func__);
39859a0bf528SMauro Carvalho Chehab 
39869a0bf528SMauro Carvalho Chehab 	return status;
39879a0bf528SMauro Carvalho Chehab }
39889a0bf528SMauro Carvalho Chehab 
39899a0bf528SMauro Carvalho Chehab 
39909a0bf528SMauro Carvalho Chehab /*============================================================================*/
39919a0bf528SMauro Carvalho Chehab 
39929a0bf528SMauro Carvalho Chehab /**
39939a0bf528SMauro Carvalho Chehab * \brief Retreive lock status .
39949a0bf528SMauro Carvalho Chehab * \param demod    Pointer to demodulator instance.
39959a0bf528SMauro Carvalho Chehab * \param lockStat Pointer to lock status structure.
39969a0bf528SMauro Carvalho Chehab * \return DRXStatus_t.
39979a0bf528SMauro Carvalho Chehab *
39989a0bf528SMauro Carvalho Chehab */
3999cd7a67a4SMauro Carvalho Chehab static int get_dvbt_lock_status(struct drxk_state *state, u32 *p_lock_status)
40009a0bf528SMauro Carvalho Chehab {
40019a0bf528SMauro Carvalho Chehab 	int status;
40029a0bf528SMauro Carvalho Chehab 	const u16 mpeg_lock_mask = (OFDM_SC_RA_RAM_LOCK_MPEG__M |
40039a0bf528SMauro Carvalho Chehab 				    OFDM_SC_RA_RAM_LOCK_FEC__M);
40049a0bf528SMauro Carvalho Chehab 	const u16 fec_lock_mask = (OFDM_SC_RA_RAM_LOCK_FEC__M);
40059a0bf528SMauro Carvalho Chehab 	const u16 demod_lock_mask = OFDM_SC_RA_RAM_LOCK_DEMOD__M;
40069a0bf528SMauro Carvalho Chehab 
4007cd7a67a4SMauro Carvalho Chehab 	u16 sc_ra_ram_lock = 0;
4008cd7a67a4SMauro Carvalho Chehab 	u16 sc_comm_exec = 0;
40099a0bf528SMauro Carvalho Chehab 
40109a0bf528SMauro Carvalho Chehab 	dprintk(1, "\n");
40119a0bf528SMauro Carvalho Chehab 
4012cd7a67a4SMauro Carvalho Chehab 	*p_lock_status = NOT_LOCKED;
40139a0bf528SMauro Carvalho Chehab 	/* driver 0.9.0 */
40149a0bf528SMauro Carvalho Chehab 	/* Check if SC is running */
4015cd7a67a4SMauro Carvalho Chehab 	status = read16(state, OFDM_SC_COMM_EXEC__A, &sc_comm_exec);
40169a0bf528SMauro Carvalho Chehab 	if (status < 0)
40179a0bf528SMauro Carvalho Chehab 		goto end;
4018cd7a67a4SMauro Carvalho Chehab 	if (sc_comm_exec == OFDM_SC_COMM_EXEC_STOP)
40199a0bf528SMauro Carvalho Chehab 		goto end;
40209a0bf528SMauro Carvalho Chehab 
4021cd7a67a4SMauro Carvalho Chehab 	status = read16(state, OFDM_SC_RA_RAM_LOCK__A, &sc_ra_ram_lock);
40229a0bf528SMauro Carvalho Chehab 	if (status < 0)
40239a0bf528SMauro Carvalho Chehab 		goto end;
40249a0bf528SMauro Carvalho Chehab 
4025cd7a67a4SMauro Carvalho Chehab 	if ((sc_ra_ram_lock & mpeg_lock_mask) == mpeg_lock_mask)
4026cd7a67a4SMauro Carvalho Chehab 		*p_lock_status = MPEG_LOCK;
4027cd7a67a4SMauro Carvalho Chehab 	else if ((sc_ra_ram_lock & fec_lock_mask) == fec_lock_mask)
4028cd7a67a4SMauro Carvalho Chehab 		*p_lock_status = FEC_LOCK;
4029cd7a67a4SMauro Carvalho Chehab 	else if ((sc_ra_ram_lock & demod_lock_mask) == demod_lock_mask)
4030cd7a67a4SMauro Carvalho Chehab 		*p_lock_status = DEMOD_LOCK;
4031cd7a67a4SMauro Carvalho Chehab 	else if (sc_ra_ram_lock & OFDM_SC_RA_RAM_LOCK_NODVBT__M)
4032cd7a67a4SMauro Carvalho Chehab 		*p_lock_status = NEVER_LOCK;
40339a0bf528SMauro Carvalho Chehab end:
40349a0bf528SMauro Carvalho Chehab 	if (status < 0)
40353a4398f5SMauro Carvalho Chehab 		pr_err("Error %d on %s\n", status, __func__);
40369a0bf528SMauro Carvalho Chehab 
40379a0bf528SMauro Carvalho Chehab 	return status;
40389a0bf528SMauro Carvalho Chehab }
40399a0bf528SMauro Carvalho Chehab 
4040cd7a67a4SMauro Carvalho Chehab static int power_up_qam(struct drxk_state *state)
40419a0bf528SMauro Carvalho Chehab {
4042cd7a67a4SMauro Carvalho Chehab 	enum drx_power_mode power_mode = DRXK_POWER_DOWN_OFDM;
40439a0bf528SMauro Carvalho Chehab 	int status;
40449a0bf528SMauro Carvalho Chehab 
40459a0bf528SMauro Carvalho Chehab 	dprintk(1, "\n");
4046cd7a67a4SMauro Carvalho Chehab 	status = ctrl_power_mode(state, &power_mode);
40479a0bf528SMauro Carvalho Chehab 	if (status < 0)
40483a4398f5SMauro Carvalho Chehab 		pr_err("Error %d on %s\n", status, __func__);
40499a0bf528SMauro Carvalho Chehab 
40509a0bf528SMauro Carvalho Chehab 	return status;
40519a0bf528SMauro Carvalho Chehab }
40529a0bf528SMauro Carvalho Chehab 
40539a0bf528SMauro Carvalho Chehab 
40549a0bf528SMauro Carvalho Chehab /** Power Down QAM */
4055cd7a67a4SMauro Carvalho Chehab static int power_down_qam(struct drxk_state *state)
40569a0bf528SMauro Carvalho Chehab {
40579a0bf528SMauro Carvalho Chehab 	u16 data = 0;
4058cd7a67a4SMauro Carvalho Chehab 	u16 cmd_result;
40599a0bf528SMauro Carvalho Chehab 	int status = 0;
40609a0bf528SMauro Carvalho Chehab 
40619a0bf528SMauro Carvalho Chehab 	dprintk(1, "\n");
40629a0bf528SMauro Carvalho Chehab 	status = read16(state, SCU_COMM_EXEC__A, &data);
40639a0bf528SMauro Carvalho Chehab 	if (status < 0)
40649a0bf528SMauro Carvalho Chehab 		goto error;
40659a0bf528SMauro Carvalho Chehab 	if (data == SCU_COMM_EXEC_ACTIVE) {
40669a0bf528SMauro Carvalho Chehab 		/*
40679a0bf528SMauro Carvalho Chehab 			STOP demodulator
40689a0bf528SMauro Carvalho Chehab 			QAM and HW blocks
40699a0bf528SMauro Carvalho Chehab 			*/
40709a0bf528SMauro Carvalho Chehab 		/* stop all comstate->m_exec */
40719a0bf528SMauro Carvalho Chehab 		status = write16(state, QAM_COMM_EXEC__A, QAM_COMM_EXEC_STOP);
40729a0bf528SMauro Carvalho Chehab 		if (status < 0)
40739a0bf528SMauro Carvalho Chehab 			goto error;
4074cd7a67a4SMauro Carvalho Chehab 		status = scu_command(state, SCU_RAM_COMMAND_STANDARD_QAM | SCU_RAM_COMMAND_CMD_DEMOD_STOP, 0, NULL, 1, &cmd_result);
40759a0bf528SMauro Carvalho Chehab 		if (status < 0)
40769a0bf528SMauro Carvalho Chehab 			goto error;
40779a0bf528SMauro Carvalho Chehab 	}
40789a0bf528SMauro Carvalho Chehab 	/* powerdown AFE                   */
4079cd7a67a4SMauro Carvalho Chehab 	status = set_iqm_af(state, false);
40809a0bf528SMauro Carvalho Chehab 
40819a0bf528SMauro Carvalho Chehab error:
40829a0bf528SMauro Carvalho Chehab 	if (status < 0)
40833a4398f5SMauro Carvalho Chehab 		pr_err("Error %d on %s\n", status, __func__);
40849a0bf528SMauro Carvalho Chehab 
40859a0bf528SMauro Carvalho Chehab 	return status;
40869a0bf528SMauro Carvalho Chehab }
40879a0bf528SMauro Carvalho Chehab 
40889a0bf528SMauro Carvalho Chehab /*============================================================================*/
40899a0bf528SMauro Carvalho Chehab 
40909a0bf528SMauro Carvalho Chehab /**
40919a0bf528SMauro Carvalho Chehab * \brief Setup of the QAM Measurement intervals for signal quality
40929a0bf528SMauro Carvalho Chehab * \param demod instance of demod.
40939a0bf528SMauro Carvalho Chehab * \param modulation current modulation.
40949a0bf528SMauro Carvalho Chehab * \return DRXStatus_t.
40959a0bf528SMauro Carvalho Chehab *
40969a0bf528SMauro Carvalho Chehab *  NOTE:
40979a0bf528SMauro Carvalho Chehab *  Take into account that for certain settings the errorcounters can overflow.
40989a0bf528SMauro Carvalho Chehab *  The implementation does not check this.
40999a0bf528SMauro Carvalho Chehab *
41009a0bf528SMauro Carvalho Chehab */
4101cd7a67a4SMauro Carvalho Chehab static int set_qam_measurement(struct drxk_state *state,
4102cd7a67a4SMauro Carvalho Chehab 			     enum e_drxk_constellation modulation,
4103cd7a67a4SMauro Carvalho Chehab 			     u32 symbol_rate)
41049a0bf528SMauro Carvalho Chehab {
4105cd7a67a4SMauro Carvalho Chehab 	u32 fec_bits_desired = 0;	/* BER accounting period */
4106cd7a67a4SMauro Carvalho Chehab 	u32 fec_rs_period_total = 0;	/* Total period */
4107cd7a67a4SMauro Carvalho Chehab 	u16 fec_rs_prescale = 0;	/* ReedSolomon Measurement Prescale */
4108cd7a67a4SMauro Carvalho Chehab 	u16 fec_rs_period = 0;	/* Value for corresponding I2C register */
41099a0bf528SMauro Carvalho Chehab 	int status = 0;
41109a0bf528SMauro Carvalho Chehab 
41119a0bf528SMauro Carvalho Chehab 	dprintk(1, "\n");
41129a0bf528SMauro Carvalho Chehab 
4113cd7a67a4SMauro Carvalho Chehab 	fec_rs_prescale = 1;
4114cd7a67a4SMauro Carvalho Chehab 	/* fec_bits_desired = symbol_rate [kHz] *
41159a0bf528SMauro Carvalho Chehab 		FrameLenght [ms] *
41169a0bf528SMauro Carvalho Chehab 		(modulation + 1) *
41179a0bf528SMauro Carvalho Chehab 		SyncLoss (== 1) *
41189a0bf528SMauro Carvalho Chehab 		ViterbiLoss (==1)
41199a0bf528SMauro Carvalho Chehab 		*/
41209a0bf528SMauro Carvalho Chehab 	switch (modulation) {
41219a0bf528SMauro Carvalho Chehab 	case DRX_CONSTELLATION_QAM16:
4122cd7a67a4SMauro Carvalho Chehab 		fec_bits_desired = 4 * symbol_rate;
41239a0bf528SMauro Carvalho Chehab 		break;
41249a0bf528SMauro Carvalho Chehab 	case DRX_CONSTELLATION_QAM32:
4125cd7a67a4SMauro Carvalho Chehab 		fec_bits_desired = 5 * symbol_rate;
41269a0bf528SMauro Carvalho Chehab 		break;
41279a0bf528SMauro Carvalho Chehab 	case DRX_CONSTELLATION_QAM64:
4128cd7a67a4SMauro Carvalho Chehab 		fec_bits_desired = 6 * symbol_rate;
41299a0bf528SMauro Carvalho Chehab 		break;
41309a0bf528SMauro Carvalho Chehab 	case DRX_CONSTELLATION_QAM128:
4131cd7a67a4SMauro Carvalho Chehab 		fec_bits_desired = 7 * symbol_rate;
41329a0bf528SMauro Carvalho Chehab 		break;
41339a0bf528SMauro Carvalho Chehab 	case DRX_CONSTELLATION_QAM256:
4134cd7a67a4SMauro Carvalho Chehab 		fec_bits_desired = 8 * symbol_rate;
41359a0bf528SMauro Carvalho Chehab 		break;
41369a0bf528SMauro Carvalho Chehab 	default:
41379a0bf528SMauro Carvalho Chehab 		status = -EINVAL;
41389a0bf528SMauro Carvalho Chehab 	}
41399a0bf528SMauro Carvalho Chehab 	if (status < 0)
41409a0bf528SMauro Carvalho Chehab 		goto error;
41419a0bf528SMauro Carvalho Chehab 
4142cd7a67a4SMauro Carvalho Chehab 	fec_bits_desired /= 1000;	/* symbol_rate [Hz] -> symbol_rate [kHz]  */
4143cd7a67a4SMauro Carvalho Chehab 	fec_bits_desired *= 500;	/* meas. period [ms] */
41449a0bf528SMauro Carvalho Chehab 
41459a0bf528SMauro Carvalho Chehab 	/* Annex A/C: bits/RsPeriod = 204 * 8 = 1632 */
4146cd7a67a4SMauro Carvalho Chehab 	/* fec_rs_period_total = fec_bits_desired / 1632 */
4147cd7a67a4SMauro Carvalho Chehab 	fec_rs_period_total = (fec_bits_desired / 1632UL) + 1;	/* roughly ceil */
41489a0bf528SMauro Carvalho Chehab 
4149cd7a67a4SMauro Carvalho Chehab 	/* fec_rs_period_total =  fec_rs_prescale * fec_rs_period  */
4150cd7a67a4SMauro Carvalho Chehab 	fec_rs_prescale = 1 + (u16) (fec_rs_period_total >> 16);
4151cd7a67a4SMauro Carvalho Chehab 	if (fec_rs_prescale == 0) {
41529a0bf528SMauro Carvalho Chehab 		/* Divide by zero (though impossible) */
41539a0bf528SMauro Carvalho Chehab 		status = -EINVAL;
41549a0bf528SMauro Carvalho Chehab 		if (status < 0)
41559a0bf528SMauro Carvalho Chehab 			goto error;
41569a0bf528SMauro Carvalho Chehab 	}
4157cd7a67a4SMauro Carvalho Chehab 	fec_rs_period =
4158cd7a67a4SMauro Carvalho Chehab 		((u16) fec_rs_period_total +
4159cd7a67a4SMauro Carvalho Chehab 		(fec_rs_prescale >> 1)) / fec_rs_prescale;
41609a0bf528SMauro Carvalho Chehab 
41619a0bf528SMauro Carvalho Chehab 	/* write corresponding registers */
4162cd7a67a4SMauro Carvalho Chehab 	status = write16(state, FEC_RS_MEASUREMENT_PERIOD__A, fec_rs_period);
41639a0bf528SMauro Carvalho Chehab 	if (status < 0)
41649a0bf528SMauro Carvalho Chehab 		goto error;
4165cd7a67a4SMauro Carvalho Chehab 	status = write16(state, FEC_RS_MEASUREMENT_PRESCALE__A, fec_rs_prescale);
41669a0bf528SMauro Carvalho Chehab 	if (status < 0)
41679a0bf528SMauro Carvalho Chehab 		goto error;
4168cd7a67a4SMauro Carvalho Chehab 	status = write16(state, FEC_OC_SNC_FAIL_PERIOD__A, fec_rs_period);
41699a0bf528SMauro Carvalho Chehab error:
41709a0bf528SMauro Carvalho Chehab 	if (status < 0)
41713a4398f5SMauro Carvalho Chehab 		pr_err("Error %d on %s\n", status, __func__);
41729a0bf528SMauro Carvalho Chehab 	return status;
41739a0bf528SMauro Carvalho Chehab }
41749a0bf528SMauro Carvalho Chehab 
4175cd7a67a4SMauro Carvalho Chehab static int set_qam16(struct drxk_state *state)
41769a0bf528SMauro Carvalho Chehab {
41779a0bf528SMauro Carvalho Chehab 	int status = 0;
41789a0bf528SMauro Carvalho Chehab 
41799a0bf528SMauro Carvalho Chehab 	dprintk(1, "\n");
41809a0bf528SMauro Carvalho Chehab 	/* QAM Equalizer Setup */
41819a0bf528SMauro Carvalho Chehab 	/* Equalizer */
41829a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD0__A, 13517);
41839a0bf528SMauro Carvalho Chehab 	if (status < 0)
41849a0bf528SMauro Carvalho Chehab 		goto error;
41859a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD1__A, 13517);
41869a0bf528SMauro Carvalho Chehab 	if (status < 0)
41879a0bf528SMauro Carvalho Chehab 		goto error;
41889a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD2__A, 13517);
41899a0bf528SMauro Carvalho Chehab 	if (status < 0)
41909a0bf528SMauro Carvalho Chehab 		goto error;
41919a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD3__A, 13517);
41929a0bf528SMauro Carvalho Chehab 	if (status < 0)
41939a0bf528SMauro Carvalho Chehab 		goto error;
41949a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD4__A, 13517);
41959a0bf528SMauro Carvalho Chehab 	if (status < 0)
41969a0bf528SMauro Carvalho Chehab 		goto error;
41979a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD5__A, 13517);
41989a0bf528SMauro Carvalho Chehab 	if (status < 0)
41999a0bf528SMauro Carvalho Chehab 		goto error;
42009a0bf528SMauro Carvalho Chehab 	/* Decision Feedback Equalizer */
42019a0bf528SMauro Carvalho Chehab 	status = write16(state, QAM_DQ_QUAL_FUN0__A, 2);
42029a0bf528SMauro Carvalho Chehab 	if (status < 0)
42039a0bf528SMauro Carvalho Chehab 		goto error;
42049a0bf528SMauro Carvalho Chehab 	status = write16(state, QAM_DQ_QUAL_FUN1__A, 2);
42059a0bf528SMauro Carvalho Chehab 	if (status < 0)
42069a0bf528SMauro Carvalho Chehab 		goto error;
42079a0bf528SMauro Carvalho Chehab 	status = write16(state, QAM_DQ_QUAL_FUN2__A, 2);
42089a0bf528SMauro Carvalho Chehab 	if (status < 0)
42099a0bf528SMauro Carvalho Chehab 		goto error;
42109a0bf528SMauro Carvalho Chehab 	status = write16(state, QAM_DQ_QUAL_FUN3__A, 2);
42119a0bf528SMauro Carvalho Chehab 	if (status < 0)
42129a0bf528SMauro Carvalho Chehab 		goto error;
42139a0bf528SMauro Carvalho Chehab 	status = write16(state, QAM_DQ_QUAL_FUN4__A, 2);
42149a0bf528SMauro Carvalho Chehab 	if (status < 0)
42159a0bf528SMauro Carvalho Chehab 		goto error;
42169a0bf528SMauro Carvalho Chehab 	status = write16(state, QAM_DQ_QUAL_FUN5__A, 0);
42179a0bf528SMauro Carvalho Chehab 	if (status < 0)
42189a0bf528SMauro Carvalho Chehab 		goto error;
42199a0bf528SMauro Carvalho Chehab 
42209a0bf528SMauro Carvalho Chehab 	status = write16(state, QAM_SY_SYNC_HWM__A, 5);
42219a0bf528SMauro Carvalho Chehab 	if (status < 0)
42229a0bf528SMauro Carvalho Chehab 		goto error;
42239a0bf528SMauro Carvalho Chehab 	status = write16(state, QAM_SY_SYNC_AWM__A, 4);
42249a0bf528SMauro Carvalho Chehab 	if (status < 0)
42259a0bf528SMauro Carvalho Chehab 		goto error;
42269a0bf528SMauro Carvalho Chehab 	status = write16(state, QAM_SY_SYNC_LWM__A, 3);
42279a0bf528SMauro Carvalho Chehab 	if (status < 0)
42289a0bf528SMauro Carvalho Chehab 		goto error;
42299a0bf528SMauro Carvalho Chehab 
42309a0bf528SMauro Carvalho Chehab 	/* QAM Slicer Settings */
42319a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_SL_SIG_POWER__A, DRXK_QAM_SL_SIG_POWER_QAM16);
42329a0bf528SMauro Carvalho Chehab 	if (status < 0)
42339a0bf528SMauro Carvalho Chehab 		goto error;
42349a0bf528SMauro Carvalho Chehab 
42359a0bf528SMauro Carvalho Chehab 	/* QAM Loop Controller Coeficients */
42369a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_CA_FINE__A, 15);
42379a0bf528SMauro Carvalho Chehab 	if (status < 0)
42389a0bf528SMauro Carvalho Chehab 		goto error;
42399a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_CA_COARSE__A, 40);
42409a0bf528SMauro Carvalho Chehab 	if (status < 0)
42419a0bf528SMauro Carvalho Chehab 		goto error;
42429a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_EP_FINE__A, 12);
42439a0bf528SMauro Carvalho Chehab 	if (status < 0)
42449a0bf528SMauro Carvalho Chehab 		goto error;
42459a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_EP_MEDIUM__A, 24);
42469a0bf528SMauro Carvalho Chehab 	if (status < 0)
42479a0bf528SMauro Carvalho Chehab 		goto error;
42489a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_EP_COARSE__A, 24);
42499a0bf528SMauro Carvalho Chehab 	if (status < 0)
42509a0bf528SMauro Carvalho Chehab 		goto error;
42519a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_EI_FINE__A, 12);
42529a0bf528SMauro Carvalho Chehab 	if (status < 0)
42539a0bf528SMauro Carvalho Chehab 		goto error;
42549a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_EI_MEDIUM__A, 16);
42559a0bf528SMauro Carvalho Chehab 	if (status < 0)
42569a0bf528SMauro Carvalho Chehab 		goto error;
42579a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_EI_COARSE__A, 16);
42589a0bf528SMauro Carvalho Chehab 	if (status < 0)
42599a0bf528SMauro Carvalho Chehab 		goto error;
42609a0bf528SMauro Carvalho Chehab 
42619a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_CP_FINE__A, 5);
42629a0bf528SMauro Carvalho Chehab 	if (status < 0)
42639a0bf528SMauro Carvalho Chehab 		goto error;
42649a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_CP_MEDIUM__A, 20);
42659a0bf528SMauro Carvalho Chehab 	if (status < 0)
42669a0bf528SMauro Carvalho Chehab 		goto error;
42679a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_CP_COARSE__A, 80);
42689a0bf528SMauro Carvalho Chehab 	if (status < 0)
42699a0bf528SMauro Carvalho Chehab 		goto error;
42709a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_CI_FINE__A, 5);
42719a0bf528SMauro Carvalho Chehab 	if (status < 0)
42729a0bf528SMauro Carvalho Chehab 		goto error;
42739a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_CI_MEDIUM__A, 20);
42749a0bf528SMauro Carvalho Chehab 	if (status < 0)
42759a0bf528SMauro Carvalho Chehab 		goto error;
42769a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_CI_COARSE__A, 50);
42779a0bf528SMauro Carvalho Chehab 	if (status < 0)
42789a0bf528SMauro Carvalho Chehab 		goto error;
42799a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_CF_FINE__A, 16);
42809a0bf528SMauro Carvalho Chehab 	if (status < 0)
42819a0bf528SMauro Carvalho Chehab 		goto error;
42829a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_CF_MEDIUM__A, 16);
42839a0bf528SMauro Carvalho Chehab 	if (status < 0)
42849a0bf528SMauro Carvalho Chehab 		goto error;
42859a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_CF_COARSE__A, 32);
42869a0bf528SMauro Carvalho Chehab 	if (status < 0)
42879a0bf528SMauro Carvalho Chehab 		goto error;
42889a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_CF1_FINE__A, 5);
42899a0bf528SMauro Carvalho Chehab 	if (status < 0)
42909a0bf528SMauro Carvalho Chehab 		goto error;
42919a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_CF1_MEDIUM__A, 10);
42929a0bf528SMauro Carvalho Chehab 	if (status < 0)
42939a0bf528SMauro Carvalho Chehab 		goto error;
42949a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_CF1_COARSE__A, 10);
42959a0bf528SMauro Carvalho Chehab 	if (status < 0)
42969a0bf528SMauro Carvalho Chehab 		goto error;
42979a0bf528SMauro Carvalho Chehab 
42989a0bf528SMauro Carvalho Chehab 
42999a0bf528SMauro Carvalho Chehab 	/* QAM State Machine (FSM) Thresholds */
43009a0bf528SMauro Carvalho Chehab 
43019a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_FSM_RTH__A, 140);
43029a0bf528SMauro Carvalho Chehab 	if (status < 0)
43039a0bf528SMauro Carvalho Chehab 		goto error;
43049a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_FSM_FTH__A, 50);
43059a0bf528SMauro Carvalho Chehab 	if (status < 0)
43069a0bf528SMauro Carvalho Chehab 		goto error;
43079a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_FSM_CTH__A, 95);
43089a0bf528SMauro Carvalho Chehab 	if (status < 0)
43099a0bf528SMauro Carvalho Chehab 		goto error;
43109a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_FSM_PTH__A, 120);
43119a0bf528SMauro Carvalho Chehab 	if (status < 0)
43129a0bf528SMauro Carvalho Chehab 		goto error;
43139a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_FSM_QTH__A, 230);
43149a0bf528SMauro Carvalho Chehab 	if (status < 0)
43159a0bf528SMauro Carvalho Chehab 		goto error;
43169a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_FSM_MTH__A, 105);
43179a0bf528SMauro Carvalho Chehab 	if (status < 0)
43189a0bf528SMauro Carvalho Chehab 		goto error;
43199a0bf528SMauro Carvalho Chehab 
43209a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_FSM_RATE_LIM__A, 40);
43219a0bf528SMauro Carvalho Chehab 	if (status < 0)
43229a0bf528SMauro Carvalho Chehab 		goto error;
43239a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_FSM_COUNT_LIM__A, 4);
43249a0bf528SMauro Carvalho Chehab 	if (status < 0)
43259a0bf528SMauro Carvalho Chehab 		goto error;
43269a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_FSM_FREQ_LIM__A, 24);
43279a0bf528SMauro Carvalho Chehab 	if (status < 0)
43289a0bf528SMauro Carvalho Chehab 		goto error;
43299a0bf528SMauro Carvalho Chehab 
43309a0bf528SMauro Carvalho Chehab 
43319a0bf528SMauro Carvalho Chehab 	/* QAM FSM Tracking Parameters */
43329a0bf528SMauro Carvalho Chehab 
43339a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_FSM_MEDIAN_AV_MULT__A, (u16) 16);
43349a0bf528SMauro Carvalho Chehab 	if (status < 0)
43359a0bf528SMauro Carvalho Chehab 		goto error;
43369a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_FSM_RADIUS_AV_LIMIT__A, (u16) 220);
43379a0bf528SMauro Carvalho Chehab 	if (status < 0)
43389a0bf528SMauro Carvalho Chehab 		goto error;
43399a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET1__A, (u16) 25);
43409a0bf528SMauro Carvalho Chehab 	if (status < 0)
43419a0bf528SMauro Carvalho Chehab 		goto error;
43429a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET2__A, (u16) 6);
43439a0bf528SMauro Carvalho Chehab 	if (status < 0)
43449a0bf528SMauro Carvalho Chehab 		goto error;
43459a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET3__A, (u16) -24);
43469a0bf528SMauro Carvalho Chehab 	if (status < 0)
43479a0bf528SMauro Carvalho Chehab 		goto error;
43489a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET4__A, (u16) -65);
43499a0bf528SMauro Carvalho Chehab 	if (status < 0)
43509a0bf528SMauro Carvalho Chehab 		goto error;
43519a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET5__A, (u16) -127);
43529a0bf528SMauro Carvalho Chehab 	if (status < 0)
43539a0bf528SMauro Carvalho Chehab 		goto error;
43549a0bf528SMauro Carvalho Chehab 
43559a0bf528SMauro Carvalho Chehab error:
43569a0bf528SMauro Carvalho Chehab 	if (status < 0)
43573a4398f5SMauro Carvalho Chehab 		pr_err("Error %d on %s\n", status, __func__);
43589a0bf528SMauro Carvalho Chehab 	return status;
43599a0bf528SMauro Carvalho Chehab }
43609a0bf528SMauro Carvalho Chehab 
43619a0bf528SMauro Carvalho Chehab /*============================================================================*/
43629a0bf528SMauro Carvalho Chehab 
43639a0bf528SMauro Carvalho Chehab /**
43649a0bf528SMauro Carvalho Chehab * \brief QAM32 specific setup
43659a0bf528SMauro Carvalho Chehab * \param demod instance of demod.
43669a0bf528SMauro Carvalho Chehab * \return DRXStatus_t.
43679a0bf528SMauro Carvalho Chehab */
4368cd7a67a4SMauro Carvalho Chehab static int set_qam32(struct drxk_state *state)
43699a0bf528SMauro Carvalho Chehab {
43709a0bf528SMauro Carvalho Chehab 	int status = 0;
43719a0bf528SMauro Carvalho Chehab 
43729a0bf528SMauro Carvalho Chehab 	dprintk(1, "\n");
43739a0bf528SMauro Carvalho Chehab 
43749a0bf528SMauro Carvalho Chehab 	/* QAM Equalizer Setup */
43759a0bf528SMauro Carvalho Chehab 	/* Equalizer */
43769a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD0__A, 6707);
43779a0bf528SMauro Carvalho Chehab 	if (status < 0)
43789a0bf528SMauro Carvalho Chehab 		goto error;
43799a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD1__A, 6707);
43809a0bf528SMauro Carvalho Chehab 	if (status < 0)
43819a0bf528SMauro Carvalho Chehab 		goto error;
43829a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD2__A, 6707);
43839a0bf528SMauro Carvalho Chehab 	if (status < 0)
43849a0bf528SMauro Carvalho Chehab 		goto error;
43859a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD3__A, 6707);
43869a0bf528SMauro Carvalho Chehab 	if (status < 0)
43879a0bf528SMauro Carvalho Chehab 		goto error;
43889a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD4__A, 6707);
43899a0bf528SMauro Carvalho Chehab 	if (status < 0)
43909a0bf528SMauro Carvalho Chehab 		goto error;
43919a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD5__A, 6707);
43929a0bf528SMauro Carvalho Chehab 	if (status < 0)
43939a0bf528SMauro Carvalho Chehab 		goto error;
43949a0bf528SMauro Carvalho Chehab 
43959a0bf528SMauro Carvalho Chehab 	/* Decision Feedback Equalizer */
43969a0bf528SMauro Carvalho Chehab 	status = write16(state, QAM_DQ_QUAL_FUN0__A, 3);
43979a0bf528SMauro Carvalho Chehab 	if (status < 0)
43989a0bf528SMauro Carvalho Chehab 		goto error;
43999a0bf528SMauro Carvalho Chehab 	status = write16(state, QAM_DQ_QUAL_FUN1__A, 3);
44009a0bf528SMauro Carvalho Chehab 	if (status < 0)
44019a0bf528SMauro Carvalho Chehab 		goto error;
44029a0bf528SMauro Carvalho Chehab 	status = write16(state, QAM_DQ_QUAL_FUN2__A, 3);
44039a0bf528SMauro Carvalho Chehab 	if (status < 0)
44049a0bf528SMauro Carvalho Chehab 		goto error;
44059a0bf528SMauro Carvalho Chehab 	status = write16(state, QAM_DQ_QUAL_FUN3__A, 3);
44069a0bf528SMauro Carvalho Chehab 	if (status < 0)
44079a0bf528SMauro Carvalho Chehab 		goto error;
44089a0bf528SMauro Carvalho Chehab 	status = write16(state, QAM_DQ_QUAL_FUN4__A, 3);
44099a0bf528SMauro Carvalho Chehab 	if (status < 0)
44109a0bf528SMauro Carvalho Chehab 		goto error;
44119a0bf528SMauro Carvalho Chehab 	status = write16(state, QAM_DQ_QUAL_FUN5__A, 0);
44129a0bf528SMauro Carvalho Chehab 	if (status < 0)
44139a0bf528SMauro Carvalho Chehab 		goto error;
44149a0bf528SMauro Carvalho Chehab 
44159a0bf528SMauro Carvalho Chehab 	status = write16(state, QAM_SY_SYNC_HWM__A, 6);
44169a0bf528SMauro Carvalho Chehab 	if (status < 0)
44179a0bf528SMauro Carvalho Chehab 		goto error;
44189a0bf528SMauro Carvalho Chehab 	status = write16(state, QAM_SY_SYNC_AWM__A, 5);
44199a0bf528SMauro Carvalho Chehab 	if (status < 0)
44209a0bf528SMauro Carvalho Chehab 		goto error;
44219a0bf528SMauro Carvalho Chehab 	status = write16(state, QAM_SY_SYNC_LWM__A, 3);
44229a0bf528SMauro Carvalho Chehab 	if (status < 0)
44239a0bf528SMauro Carvalho Chehab 		goto error;
44249a0bf528SMauro Carvalho Chehab 
44259a0bf528SMauro Carvalho Chehab 	/* QAM Slicer Settings */
44269a0bf528SMauro Carvalho Chehab 
44279a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_SL_SIG_POWER__A, DRXK_QAM_SL_SIG_POWER_QAM32);
44289a0bf528SMauro Carvalho Chehab 	if (status < 0)
44299a0bf528SMauro Carvalho Chehab 		goto error;
44309a0bf528SMauro Carvalho Chehab 
44319a0bf528SMauro Carvalho Chehab 
44329a0bf528SMauro Carvalho Chehab 	/* QAM Loop Controller Coeficients */
44339a0bf528SMauro Carvalho Chehab 
44349a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_CA_FINE__A, 15);
44359a0bf528SMauro Carvalho Chehab 	if (status < 0)
44369a0bf528SMauro Carvalho Chehab 		goto error;
44379a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_CA_COARSE__A, 40);
44389a0bf528SMauro Carvalho Chehab 	if (status < 0)
44399a0bf528SMauro Carvalho Chehab 		goto error;
44409a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_EP_FINE__A, 12);
44419a0bf528SMauro Carvalho Chehab 	if (status < 0)
44429a0bf528SMauro Carvalho Chehab 		goto error;
44439a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_EP_MEDIUM__A, 24);
44449a0bf528SMauro Carvalho Chehab 	if (status < 0)
44459a0bf528SMauro Carvalho Chehab 		goto error;
44469a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_EP_COARSE__A, 24);
44479a0bf528SMauro Carvalho Chehab 	if (status < 0)
44489a0bf528SMauro Carvalho Chehab 		goto error;
44499a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_EI_FINE__A, 12);
44509a0bf528SMauro Carvalho Chehab 	if (status < 0)
44519a0bf528SMauro Carvalho Chehab 		goto error;
44529a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_EI_MEDIUM__A, 16);
44539a0bf528SMauro Carvalho Chehab 	if (status < 0)
44549a0bf528SMauro Carvalho Chehab 		goto error;
44559a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_EI_COARSE__A, 16);
44569a0bf528SMauro Carvalho Chehab 	if (status < 0)
44579a0bf528SMauro Carvalho Chehab 		goto error;
44589a0bf528SMauro Carvalho Chehab 
44599a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_CP_FINE__A, 5);
44609a0bf528SMauro Carvalho Chehab 	if (status < 0)
44619a0bf528SMauro Carvalho Chehab 		goto error;
44629a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_CP_MEDIUM__A, 20);
44639a0bf528SMauro Carvalho Chehab 	if (status < 0)
44649a0bf528SMauro Carvalho Chehab 		goto error;
44659a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_CP_COARSE__A, 80);
44669a0bf528SMauro Carvalho Chehab 	if (status < 0)
44679a0bf528SMauro Carvalho Chehab 		goto error;
44689a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_CI_FINE__A, 5);
44699a0bf528SMauro Carvalho Chehab 	if (status < 0)
44709a0bf528SMauro Carvalho Chehab 		goto error;
44719a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_CI_MEDIUM__A, 20);
44729a0bf528SMauro Carvalho Chehab 	if (status < 0)
44739a0bf528SMauro Carvalho Chehab 		goto error;
44749a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_CI_COARSE__A, 50);
44759a0bf528SMauro Carvalho Chehab 	if (status < 0)
44769a0bf528SMauro Carvalho Chehab 		goto error;
44779a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_CF_FINE__A, 16);
44789a0bf528SMauro Carvalho Chehab 	if (status < 0)
44799a0bf528SMauro Carvalho Chehab 		goto error;
44809a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_CF_MEDIUM__A, 16);
44819a0bf528SMauro Carvalho Chehab 	if (status < 0)
44829a0bf528SMauro Carvalho Chehab 		goto error;
44839a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_CF_COARSE__A, 16);
44849a0bf528SMauro Carvalho Chehab 	if (status < 0)
44859a0bf528SMauro Carvalho Chehab 		goto error;
44869a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_CF1_FINE__A, 5);
44879a0bf528SMauro Carvalho Chehab 	if (status < 0)
44889a0bf528SMauro Carvalho Chehab 		goto error;
44899a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_CF1_MEDIUM__A, 10);
44909a0bf528SMauro Carvalho Chehab 	if (status < 0)
44919a0bf528SMauro Carvalho Chehab 		goto error;
44929a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_CF1_COARSE__A, 0);
44939a0bf528SMauro Carvalho Chehab 	if (status < 0)
44949a0bf528SMauro Carvalho Chehab 		goto error;
44959a0bf528SMauro Carvalho Chehab 
44969a0bf528SMauro Carvalho Chehab 
44979a0bf528SMauro Carvalho Chehab 	/* QAM State Machine (FSM) Thresholds */
44989a0bf528SMauro Carvalho Chehab 
44999a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_FSM_RTH__A, 90);
45009a0bf528SMauro Carvalho Chehab 	if (status < 0)
45019a0bf528SMauro Carvalho Chehab 		goto error;
45029a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_FSM_FTH__A, 50);
45039a0bf528SMauro Carvalho Chehab 	if (status < 0)
45049a0bf528SMauro Carvalho Chehab 		goto error;
45059a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_FSM_CTH__A, 80);
45069a0bf528SMauro Carvalho Chehab 	if (status < 0)
45079a0bf528SMauro Carvalho Chehab 		goto error;
45089a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_FSM_PTH__A, 100);
45099a0bf528SMauro Carvalho Chehab 	if (status < 0)
45109a0bf528SMauro Carvalho Chehab 		goto error;
45119a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_FSM_QTH__A, 170);
45129a0bf528SMauro Carvalho Chehab 	if (status < 0)
45139a0bf528SMauro Carvalho Chehab 		goto error;
45149a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_FSM_MTH__A, 100);
45159a0bf528SMauro Carvalho Chehab 	if (status < 0)
45169a0bf528SMauro Carvalho Chehab 		goto error;
45179a0bf528SMauro Carvalho Chehab 
45189a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_FSM_RATE_LIM__A, 40);
45199a0bf528SMauro Carvalho Chehab 	if (status < 0)
45209a0bf528SMauro Carvalho Chehab 		goto error;
45219a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_FSM_COUNT_LIM__A, 4);
45229a0bf528SMauro Carvalho Chehab 	if (status < 0)
45239a0bf528SMauro Carvalho Chehab 		goto error;
45249a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_FSM_FREQ_LIM__A, 10);
45259a0bf528SMauro Carvalho Chehab 	if (status < 0)
45269a0bf528SMauro Carvalho Chehab 		goto error;
45279a0bf528SMauro Carvalho Chehab 
45289a0bf528SMauro Carvalho Chehab 
45299a0bf528SMauro Carvalho Chehab 	/* QAM FSM Tracking Parameters */
45309a0bf528SMauro Carvalho Chehab 
45319a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_FSM_MEDIAN_AV_MULT__A, (u16) 12);
45329a0bf528SMauro Carvalho Chehab 	if (status < 0)
45339a0bf528SMauro Carvalho Chehab 		goto error;
45349a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_FSM_RADIUS_AV_LIMIT__A, (u16) 140);
45359a0bf528SMauro Carvalho Chehab 	if (status < 0)
45369a0bf528SMauro Carvalho Chehab 		goto error;
45379a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET1__A, (u16) -8);
45389a0bf528SMauro Carvalho Chehab 	if (status < 0)
45399a0bf528SMauro Carvalho Chehab 		goto error;
45409a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET2__A, (u16) -16);
45419a0bf528SMauro Carvalho Chehab 	if (status < 0)
45429a0bf528SMauro Carvalho Chehab 		goto error;
45439a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET3__A, (u16) -26);
45449a0bf528SMauro Carvalho Chehab 	if (status < 0)
45459a0bf528SMauro Carvalho Chehab 		goto error;
45469a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET4__A, (u16) -56);
45479a0bf528SMauro Carvalho Chehab 	if (status < 0)
45489a0bf528SMauro Carvalho Chehab 		goto error;
45499a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET5__A, (u16) -86);
45509a0bf528SMauro Carvalho Chehab error:
45519a0bf528SMauro Carvalho Chehab 	if (status < 0)
45523a4398f5SMauro Carvalho Chehab 		pr_err("Error %d on %s\n", status, __func__);
45539a0bf528SMauro Carvalho Chehab 	return status;
45549a0bf528SMauro Carvalho Chehab }
45559a0bf528SMauro Carvalho Chehab 
45569a0bf528SMauro Carvalho Chehab /*============================================================================*/
45579a0bf528SMauro Carvalho Chehab 
45589a0bf528SMauro Carvalho Chehab /**
45599a0bf528SMauro Carvalho Chehab * \brief QAM64 specific setup
45609a0bf528SMauro Carvalho Chehab * \param demod instance of demod.
45619a0bf528SMauro Carvalho Chehab * \return DRXStatus_t.
45629a0bf528SMauro Carvalho Chehab */
4563cd7a67a4SMauro Carvalho Chehab static int set_qam64(struct drxk_state *state)
45649a0bf528SMauro Carvalho Chehab {
45659a0bf528SMauro Carvalho Chehab 	int status = 0;
45669a0bf528SMauro Carvalho Chehab 
45679a0bf528SMauro Carvalho Chehab 	dprintk(1, "\n");
45689a0bf528SMauro Carvalho Chehab 	/* QAM Equalizer Setup */
45699a0bf528SMauro Carvalho Chehab 	/* Equalizer */
45709a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD0__A, 13336);
45719a0bf528SMauro Carvalho Chehab 	if (status < 0)
45729a0bf528SMauro Carvalho Chehab 		goto error;
45739a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD1__A, 12618);
45749a0bf528SMauro Carvalho Chehab 	if (status < 0)
45759a0bf528SMauro Carvalho Chehab 		goto error;
45769a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD2__A, 11988);
45779a0bf528SMauro Carvalho Chehab 	if (status < 0)
45789a0bf528SMauro Carvalho Chehab 		goto error;
45799a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD3__A, 13809);
45809a0bf528SMauro Carvalho Chehab 	if (status < 0)
45819a0bf528SMauro Carvalho Chehab 		goto error;
45829a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD4__A, 13809);
45839a0bf528SMauro Carvalho Chehab 	if (status < 0)
45849a0bf528SMauro Carvalho Chehab 		goto error;
45859a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD5__A, 15609);
45869a0bf528SMauro Carvalho Chehab 	if (status < 0)
45879a0bf528SMauro Carvalho Chehab 		goto error;
45889a0bf528SMauro Carvalho Chehab 
45899a0bf528SMauro Carvalho Chehab 	/* Decision Feedback Equalizer */
45909a0bf528SMauro Carvalho Chehab 	status = write16(state, QAM_DQ_QUAL_FUN0__A, 4);
45919a0bf528SMauro Carvalho Chehab 	if (status < 0)
45929a0bf528SMauro Carvalho Chehab 		goto error;
45939a0bf528SMauro Carvalho Chehab 	status = write16(state, QAM_DQ_QUAL_FUN1__A, 4);
45949a0bf528SMauro Carvalho Chehab 	if (status < 0)
45959a0bf528SMauro Carvalho Chehab 		goto error;
45969a0bf528SMauro Carvalho Chehab 	status = write16(state, QAM_DQ_QUAL_FUN2__A, 4);
45979a0bf528SMauro Carvalho Chehab 	if (status < 0)
45989a0bf528SMauro Carvalho Chehab 		goto error;
45999a0bf528SMauro Carvalho Chehab 	status = write16(state, QAM_DQ_QUAL_FUN3__A, 4);
46009a0bf528SMauro Carvalho Chehab 	if (status < 0)
46019a0bf528SMauro Carvalho Chehab 		goto error;
46029a0bf528SMauro Carvalho Chehab 	status = write16(state, QAM_DQ_QUAL_FUN4__A, 3);
46039a0bf528SMauro Carvalho Chehab 	if (status < 0)
46049a0bf528SMauro Carvalho Chehab 		goto error;
46059a0bf528SMauro Carvalho Chehab 	status = write16(state, QAM_DQ_QUAL_FUN5__A, 0);
46069a0bf528SMauro Carvalho Chehab 	if (status < 0)
46079a0bf528SMauro Carvalho Chehab 		goto error;
46089a0bf528SMauro Carvalho Chehab 
46099a0bf528SMauro Carvalho Chehab 	status = write16(state, QAM_SY_SYNC_HWM__A, 5);
46109a0bf528SMauro Carvalho Chehab 	if (status < 0)
46119a0bf528SMauro Carvalho Chehab 		goto error;
46129a0bf528SMauro Carvalho Chehab 	status = write16(state, QAM_SY_SYNC_AWM__A, 4);
46139a0bf528SMauro Carvalho Chehab 	if (status < 0)
46149a0bf528SMauro Carvalho Chehab 		goto error;
46159a0bf528SMauro Carvalho Chehab 	status = write16(state, QAM_SY_SYNC_LWM__A, 3);
46169a0bf528SMauro Carvalho Chehab 	if (status < 0)
46179a0bf528SMauro Carvalho Chehab 		goto error;
46189a0bf528SMauro Carvalho Chehab 
46199a0bf528SMauro Carvalho Chehab 	/* QAM Slicer Settings */
46209a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_SL_SIG_POWER__A, DRXK_QAM_SL_SIG_POWER_QAM64);
46219a0bf528SMauro Carvalho Chehab 	if (status < 0)
46229a0bf528SMauro Carvalho Chehab 		goto error;
46239a0bf528SMauro Carvalho Chehab 
46249a0bf528SMauro Carvalho Chehab 
46259a0bf528SMauro Carvalho Chehab 	/* QAM Loop Controller Coeficients */
46269a0bf528SMauro Carvalho Chehab 
46279a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_CA_FINE__A, 15);
46289a0bf528SMauro Carvalho Chehab 	if (status < 0)
46299a0bf528SMauro Carvalho Chehab 		goto error;
46309a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_CA_COARSE__A, 40);
46319a0bf528SMauro Carvalho Chehab 	if (status < 0)
46329a0bf528SMauro Carvalho Chehab 		goto error;
46339a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_EP_FINE__A, 12);
46349a0bf528SMauro Carvalho Chehab 	if (status < 0)
46359a0bf528SMauro Carvalho Chehab 		goto error;
46369a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_EP_MEDIUM__A, 24);
46379a0bf528SMauro Carvalho Chehab 	if (status < 0)
46389a0bf528SMauro Carvalho Chehab 		goto error;
46399a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_EP_COARSE__A, 24);
46409a0bf528SMauro Carvalho Chehab 	if (status < 0)
46419a0bf528SMauro Carvalho Chehab 		goto error;
46429a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_EI_FINE__A, 12);
46439a0bf528SMauro Carvalho Chehab 	if (status < 0)
46449a0bf528SMauro Carvalho Chehab 		goto error;
46459a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_EI_MEDIUM__A, 16);
46469a0bf528SMauro Carvalho Chehab 	if (status < 0)
46479a0bf528SMauro Carvalho Chehab 		goto error;
46489a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_EI_COARSE__A, 16);
46499a0bf528SMauro Carvalho Chehab 	if (status < 0)
46509a0bf528SMauro Carvalho Chehab 		goto error;
46519a0bf528SMauro Carvalho Chehab 
46529a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_CP_FINE__A, 5);
46539a0bf528SMauro Carvalho Chehab 	if (status < 0)
46549a0bf528SMauro Carvalho Chehab 		goto error;
46559a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_CP_MEDIUM__A, 30);
46569a0bf528SMauro Carvalho Chehab 	if (status < 0)
46579a0bf528SMauro Carvalho Chehab 		goto error;
46589a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_CP_COARSE__A, 100);
46599a0bf528SMauro Carvalho Chehab 	if (status < 0)
46609a0bf528SMauro Carvalho Chehab 		goto error;
46619a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_CI_FINE__A, 5);
46629a0bf528SMauro Carvalho Chehab 	if (status < 0)
46639a0bf528SMauro Carvalho Chehab 		goto error;
46649a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_CI_MEDIUM__A, 30);
46659a0bf528SMauro Carvalho Chehab 	if (status < 0)
46669a0bf528SMauro Carvalho Chehab 		goto error;
46679a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_CI_COARSE__A, 50);
46689a0bf528SMauro Carvalho Chehab 	if (status < 0)
46699a0bf528SMauro Carvalho Chehab 		goto error;
46709a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_CF_FINE__A, 16);
46719a0bf528SMauro Carvalho Chehab 	if (status < 0)
46729a0bf528SMauro Carvalho Chehab 		goto error;
46739a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_CF_MEDIUM__A, 25);
46749a0bf528SMauro Carvalho Chehab 	if (status < 0)
46759a0bf528SMauro Carvalho Chehab 		goto error;
46769a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_CF_COARSE__A, 48);
46779a0bf528SMauro Carvalho Chehab 	if (status < 0)
46789a0bf528SMauro Carvalho Chehab 		goto error;
46799a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_CF1_FINE__A, 5);
46809a0bf528SMauro Carvalho Chehab 	if (status < 0)
46819a0bf528SMauro Carvalho Chehab 		goto error;
46829a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_CF1_MEDIUM__A, 10);
46839a0bf528SMauro Carvalho Chehab 	if (status < 0)
46849a0bf528SMauro Carvalho Chehab 		goto error;
46859a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_CF1_COARSE__A, 10);
46869a0bf528SMauro Carvalho Chehab 	if (status < 0)
46879a0bf528SMauro Carvalho Chehab 		goto error;
46889a0bf528SMauro Carvalho Chehab 
46899a0bf528SMauro Carvalho Chehab 
46909a0bf528SMauro Carvalho Chehab 	/* QAM State Machine (FSM) Thresholds */
46919a0bf528SMauro Carvalho Chehab 
46929a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_FSM_RTH__A, 100);
46939a0bf528SMauro Carvalho Chehab 	if (status < 0)
46949a0bf528SMauro Carvalho Chehab 		goto error;
46959a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_FSM_FTH__A, 60);
46969a0bf528SMauro Carvalho Chehab 	if (status < 0)
46979a0bf528SMauro Carvalho Chehab 		goto error;
46989a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_FSM_CTH__A, 80);
46999a0bf528SMauro Carvalho Chehab 	if (status < 0)
47009a0bf528SMauro Carvalho Chehab 		goto error;
47019a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_FSM_PTH__A, 110);
47029a0bf528SMauro Carvalho Chehab 	if (status < 0)
47039a0bf528SMauro Carvalho Chehab 		goto error;
47049a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_FSM_QTH__A, 200);
47059a0bf528SMauro Carvalho Chehab 	if (status < 0)
47069a0bf528SMauro Carvalho Chehab 		goto error;
47079a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_FSM_MTH__A, 95);
47089a0bf528SMauro Carvalho Chehab 	if (status < 0)
47099a0bf528SMauro Carvalho Chehab 		goto error;
47109a0bf528SMauro Carvalho Chehab 
47119a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_FSM_RATE_LIM__A, 40);
47129a0bf528SMauro Carvalho Chehab 	if (status < 0)
47139a0bf528SMauro Carvalho Chehab 		goto error;
47149a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_FSM_COUNT_LIM__A, 4);
47159a0bf528SMauro Carvalho Chehab 	if (status < 0)
47169a0bf528SMauro Carvalho Chehab 		goto error;
47179a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_FSM_FREQ_LIM__A, 15);
47189a0bf528SMauro Carvalho Chehab 	if (status < 0)
47199a0bf528SMauro Carvalho Chehab 		goto error;
47209a0bf528SMauro Carvalho Chehab 
47219a0bf528SMauro Carvalho Chehab 
47229a0bf528SMauro Carvalho Chehab 	/* QAM FSM Tracking Parameters */
47239a0bf528SMauro Carvalho Chehab 
47249a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_FSM_MEDIAN_AV_MULT__A, (u16) 12);
47259a0bf528SMauro Carvalho Chehab 	if (status < 0)
47269a0bf528SMauro Carvalho Chehab 		goto error;
47279a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_FSM_RADIUS_AV_LIMIT__A, (u16) 141);
47289a0bf528SMauro Carvalho Chehab 	if (status < 0)
47299a0bf528SMauro Carvalho Chehab 		goto error;
47309a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET1__A, (u16) 7);
47319a0bf528SMauro Carvalho Chehab 	if (status < 0)
47329a0bf528SMauro Carvalho Chehab 		goto error;
47339a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET2__A, (u16) 0);
47349a0bf528SMauro Carvalho Chehab 	if (status < 0)
47359a0bf528SMauro Carvalho Chehab 		goto error;
47369a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET3__A, (u16) -15);
47379a0bf528SMauro Carvalho Chehab 	if (status < 0)
47389a0bf528SMauro Carvalho Chehab 		goto error;
47399a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET4__A, (u16) -45);
47409a0bf528SMauro Carvalho Chehab 	if (status < 0)
47419a0bf528SMauro Carvalho Chehab 		goto error;
47429a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET5__A, (u16) -80);
47439a0bf528SMauro Carvalho Chehab error:
47449a0bf528SMauro Carvalho Chehab 	if (status < 0)
47453a4398f5SMauro Carvalho Chehab 		pr_err("Error %d on %s\n", status, __func__);
47469a0bf528SMauro Carvalho Chehab 
47479a0bf528SMauro Carvalho Chehab 	return status;
47489a0bf528SMauro Carvalho Chehab }
47499a0bf528SMauro Carvalho Chehab 
47509a0bf528SMauro Carvalho Chehab /*============================================================================*/
47519a0bf528SMauro Carvalho Chehab 
47529a0bf528SMauro Carvalho Chehab /**
47539a0bf528SMauro Carvalho Chehab * \brief QAM128 specific setup
47549a0bf528SMauro Carvalho Chehab * \param demod: instance of demod.
47559a0bf528SMauro Carvalho Chehab * \return DRXStatus_t.
47569a0bf528SMauro Carvalho Chehab */
4757cd7a67a4SMauro Carvalho Chehab static int set_qam128(struct drxk_state *state)
47589a0bf528SMauro Carvalho Chehab {
47599a0bf528SMauro Carvalho Chehab 	int status = 0;
47609a0bf528SMauro Carvalho Chehab 
47619a0bf528SMauro Carvalho Chehab 	dprintk(1, "\n");
47629a0bf528SMauro Carvalho Chehab 	/* QAM Equalizer Setup */
47639a0bf528SMauro Carvalho Chehab 	/* Equalizer */
47649a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD0__A, 6564);
47659a0bf528SMauro Carvalho Chehab 	if (status < 0)
47669a0bf528SMauro Carvalho Chehab 		goto error;
47679a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD1__A, 6598);
47689a0bf528SMauro Carvalho Chehab 	if (status < 0)
47699a0bf528SMauro Carvalho Chehab 		goto error;
47709a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD2__A, 6394);
47719a0bf528SMauro Carvalho Chehab 	if (status < 0)
47729a0bf528SMauro Carvalho Chehab 		goto error;
47739a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD3__A, 6409);
47749a0bf528SMauro Carvalho Chehab 	if (status < 0)
47759a0bf528SMauro Carvalho Chehab 		goto error;
47769a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD4__A, 6656);
47779a0bf528SMauro Carvalho Chehab 	if (status < 0)
47789a0bf528SMauro Carvalho Chehab 		goto error;
47799a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD5__A, 7238);
47809a0bf528SMauro Carvalho Chehab 	if (status < 0)
47819a0bf528SMauro Carvalho Chehab 		goto error;
47829a0bf528SMauro Carvalho Chehab 
47839a0bf528SMauro Carvalho Chehab 	/* Decision Feedback Equalizer */
47849a0bf528SMauro Carvalho Chehab 	status = write16(state, QAM_DQ_QUAL_FUN0__A, 6);
47859a0bf528SMauro Carvalho Chehab 	if (status < 0)
47869a0bf528SMauro Carvalho Chehab 		goto error;
47879a0bf528SMauro Carvalho Chehab 	status = write16(state, QAM_DQ_QUAL_FUN1__A, 6);
47889a0bf528SMauro Carvalho Chehab 	if (status < 0)
47899a0bf528SMauro Carvalho Chehab 		goto error;
47909a0bf528SMauro Carvalho Chehab 	status = write16(state, QAM_DQ_QUAL_FUN2__A, 6);
47919a0bf528SMauro Carvalho Chehab 	if (status < 0)
47929a0bf528SMauro Carvalho Chehab 		goto error;
47939a0bf528SMauro Carvalho Chehab 	status = write16(state, QAM_DQ_QUAL_FUN3__A, 6);
47949a0bf528SMauro Carvalho Chehab 	if (status < 0)
47959a0bf528SMauro Carvalho Chehab 		goto error;
47969a0bf528SMauro Carvalho Chehab 	status = write16(state, QAM_DQ_QUAL_FUN4__A, 5);
47979a0bf528SMauro Carvalho Chehab 	if (status < 0)
47989a0bf528SMauro Carvalho Chehab 		goto error;
47999a0bf528SMauro Carvalho Chehab 	status = write16(state, QAM_DQ_QUAL_FUN5__A, 0);
48009a0bf528SMauro Carvalho Chehab 	if (status < 0)
48019a0bf528SMauro Carvalho Chehab 		goto error;
48029a0bf528SMauro Carvalho Chehab 
48039a0bf528SMauro Carvalho Chehab 	status = write16(state, QAM_SY_SYNC_HWM__A, 6);
48049a0bf528SMauro Carvalho Chehab 	if (status < 0)
48059a0bf528SMauro Carvalho Chehab 		goto error;
48069a0bf528SMauro Carvalho Chehab 	status = write16(state, QAM_SY_SYNC_AWM__A, 5);
48079a0bf528SMauro Carvalho Chehab 	if (status < 0)
48089a0bf528SMauro Carvalho Chehab 		goto error;
48099a0bf528SMauro Carvalho Chehab 	status = write16(state, QAM_SY_SYNC_LWM__A, 3);
48109a0bf528SMauro Carvalho Chehab 	if (status < 0)
48119a0bf528SMauro Carvalho Chehab 		goto error;
48129a0bf528SMauro Carvalho Chehab 
48139a0bf528SMauro Carvalho Chehab 
48149a0bf528SMauro Carvalho Chehab 	/* QAM Slicer Settings */
48159a0bf528SMauro Carvalho Chehab 
48169a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_SL_SIG_POWER__A, DRXK_QAM_SL_SIG_POWER_QAM128);
48179a0bf528SMauro Carvalho Chehab 	if (status < 0)
48189a0bf528SMauro Carvalho Chehab 		goto error;
48199a0bf528SMauro Carvalho Chehab 
48209a0bf528SMauro Carvalho Chehab 
48219a0bf528SMauro Carvalho Chehab 	/* QAM Loop Controller Coeficients */
48229a0bf528SMauro Carvalho Chehab 
48239a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_CA_FINE__A, 15);
48249a0bf528SMauro Carvalho Chehab 	if (status < 0)
48259a0bf528SMauro Carvalho Chehab 		goto error;
48269a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_CA_COARSE__A, 40);
48279a0bf528SMauro Carvalho Chehab 	if (status < 0)
48289a0bf528SMauro Carvalho Chehab 		goto error;
48299a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_EP_FINE__A, 12);
48309a0bf528SMauro Carvalho Chehab 	if (status < 0)
48319a0bf528SMauro Carvalho Chehab 		goto error;
48329a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_EP_MEDIUM__A, 24);
48339a0bf528SMauro Carvalho Chehab 	if (status < 0)
48349a0bf528SMauro Carvalho Chehab 		goto error;
48359a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_EP_COARSE__A, 24);
48369a0bf528SMauro Carvalho Chehab 	if (status < 0)
48379a0bf528SMauro Carvalho Chehab 		goto error;
48389a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_EI_FINE__A, 12);
48399a0bf528SMauro Carvalho Chehab 	if (status < 0)
48409a0bf528SMauro Carvalho Chehab 		goto error;
48419a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_EI_MEDIUM__A, 16);
48429a0bf528SMauro Carvalho Chehab 	if (status < 0)
48439a0bf528SMauro Carvalho Chehab 		goto error;
48449a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_EI_COARSE__A, 16);
48459a0bf528SMauro Carvalho Chehab 	if (status < 0)
48469a0bf528SMauro Carvalho Chehab 		goto error;
48479a0bf528SMauro Carvalho Chehab 
48489a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_CP_FINE__A, 5);
48499a0bf528SMauro Carvalho Chehab 	if (status < 0)
48509a0bf528SMauro Carvalho Chehab 		goto error;
48519a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_CP_MEDIUM__A, 40);
48529a0bf528SMauro Carvalho Chehab 	if (status < 0)
48539a0bf528SMauro Carvalho Chehab 		goto error;
48549a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_CP_COARSE__A, 120);
48559a0bf528SMauro Carvalho Chehab 	if (status < 0)
48569a0bf528SMauro Carvalho Chehab 		goto error;
48579a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_CI_FINE__A, 5);
48589a0bf528SMauro Carvalho Chehab 	if (status < 0)
48599a0bf528SMauro Carvalho Chehab 		goto error;
48609a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_CI_MEDIUM__A, 40);
48619a0bf528SMauro Carvalho Chehab 	if (status < 0)
48629a0bf528SMauro Carvalho Chehab 		goto error;
48639a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_CI_COARSE__A, 60);
48649a0bf528SMauro Carvalho Chehab 	if (status < 0)
48659a0bf528SMauro Carvalho Chehab 		goto error;
48669a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_CF_FINE__A, 16);
48679a0bf528SMauro Carvalho Chehab 	if (status < 0)
48689a0bf528SMauro Carvalho Chehab 		goto error;
48699a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_CF_MEDIUM__A, 25);
48709a0bf528SMauro Carvalho Chehab 	if (status < 0)
48719a0bf528SMauro Carvalho Chehab 		goto error;
48729a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_CF_COARSE__A, 64);
48739a0bf528SMauro Carvalho Chehab 	if (status < 0)
48749a0bf528SMauro Carvalho Chehab 		goto error;
48759a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_CF1_FINE__A, 5);
48769a0bf528SMauro Carvalho Chehab 	if (status < 0)
48779a0bf528SMauro Carvalho Chehab 		goto error;
48789a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_CF1_MEDIUM__A, 10);
48799a0bf528SMauro Carvalho Chehab 	if (status < 0)
48809a0bf528SMauro Carvalho Chehab 		goto error;
48819a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_CF1_COARSE__A, 0);
48829a0bf528SMauro Carvalho Chehab 	if (status < 0)
48839a0bf528SMauro Carvalho Chehab 		goto error;
48849a0bf528SMauro Carvalho Chehab 
48859a0bf528SMauro Carvalho Chehab 
48869a0bf528SMauro Carvalho Chehab 	/* QAM State Machine (FSM) Thresholds */
48879a0bf528SMauro Carvalho Chehab 
48889a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_FSM_RTH__A, 50);
48899a0bf528SMauro Carvalho Chehab 	if (status < 0)
48909a0bf528SMauro Carvalho Chehab 		goto error;
48919a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_FSM_FTH__A, 60);
48929a0bf528SMauro Carvalho Chehab 	if (status < 0)
48939a0bf528SMauro Carvalho Chehab 		goto error;
48949a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_FSM_CTH__A, 80);
48959a0bf528SMauro Carvalho Chehab 	if (status < 0)
48969a0bf528SMauro Carvalho Chehab 		goto error;
48979a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_FSM_PTH__A, 100);
48989a0bf528SMauro Carvalho Chehab 	if (status < 0)
48999a0bf528SMauro Carvalho Chehab 		goto error;
49009a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_FSM_QTH__A, 140);
49019a0bf528SMauro Carvalho Chehab 	if (status < 0)
49029a0bf528SMauro Carvalho Chehab 		goto error;
49039a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_FSM_MTH__A, 100);
49049a0bf528SMauro Carvalho Chehab 	if (status < 0)
49059a0bf528SMauro Carvalho Chehab 		goto error;
49069a0bf528SMauro Carvalho Chehab 
49079a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_FSM_RATE_LIM__A, 40);
49089a0bf528SMauro Carvalho Chehab 	if (status < 0)
49099a0bf528SMauro Carvalho Chehab 		goto error;
49109a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_FSM_COUNT_LIM__A, 5);
49119a0bf528SMauro Carvalho Chehab 	if (status < 0)
49129a0bf528SMauro Carvalho Chehab 		goto error;
49139a0bf528SMauro Carvalho Chehab 
49149a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_FSM_FREQ_LIM__A, 12);
49159a0bf528SMauro Carvalho Chehab 	if (status < 0)
49169a0bf528SMauro Carvalho Chehab 		goto error;
49179a0bf528SMauro Carvalho Chehab 
49189a0bf528SMauro Carvalho Chehab 	/* QAM FSM Tracking Parameters */
49199a0bf528SMauro Carvalho Chehab 
49209a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_FSM_MEDIAN_AV_MULT__A, (u16) 8);
49219a0bf528SMauro Carvalho Chehab 	if (status < 0)
49229a0bf528SMauro Carvalho Chehab 		goto error;
49239a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_FSM_RADIUS_AV_LIMIT__A, (u16) 65);
49249a0bf528SMauro Carvalho Chehab 	if (status < 0)
49259a0bf528SMauro Carvalho Chehab 		goto error;
49269a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET1__A, (u16) 5);
49279a0bf528SMauro Carvalho Chehab 	if (status < 0)
49289a0bf528SMauro Carvalho Chehab 		goto error;
49299a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET2__A, (u16) 3);
49309a0bf528SMauro Carvalho Chehab 	if (status < 0)
49319a0bf528SMauro Carvalho Chehab 		goto error;
49329a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET3__A, (u16) -1);
49339a0bf528SMauro Carvalho Chehab 	if (status < 0)
49349a0bf528SMauro Carvalho Chehab 		goto error;
49359a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET4__A, (u16) -12);
49369a0bf528SMauro Carvalho Chehab 	if (status < 0)
49379a0bf528SMauro Carvalho Chehab 		goto error;
49389a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET5__A, (u16) -23);
49399a0bf528SMauro Carvalho Chehab error:
49409a0bf528SMauro Carvalho Chehab 	if (status < 0)
49413a4398f5SMauro Carvalho Chehab 		pr_err("Error %d on %s\n", status, __func__);
49429a0bf528SMauro Carvalho Chehab 
49439a0bf528SMauro Carvalho Chehab 	return status;
49449a0bf528SMauro Carvalho Chehab }
49459a0bf528SMauro Carvalho Chehab 
49469a0bf528SMauro Carvalho Chehab /*============================================================================*/
49479a0bf528SMauro Carvalho Chehab 
49489a0bf528SMauro Carvalho Chehab /**
49499a0bf528SMauro Carvalho Chehab * \brief QAM256 specific setup
49509a0bf528SMauro Carvalho Chehab * \param demod: instance of demod.
49519a0bf528SMauro Carvalho Chehab * \return DRXStatus_t.
49529a0bf528SMauro Carvalho Chehab */
4953cd7a67a4SMauro Carvalho Chehab static int set_qam256(struct drxk_state *state)
49549a0bf528SMauro Carvalho Chehab {
49559a0bf528SMauro Carvalho Chehab 	int status = 0;
49569a0bf528SMauro Carvalho Chehab 
49579a0bf528SMauro Carvalho Chehab 	dprintk(1, "\n");
49589a0bf528SMauro Carvalho Chehab 	/* QAM Equalizer Setup */
49599a0bf528SMauro Carvalho Chehab 	/* Equalizer */
49609a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD0__A, 11502);
49619a0bf528SMauro Carvalho Chehab 	if (status < 0)
49629a0bf528SMauro Carvalho Chehab 		goto error;
49639a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD1__A, 12084);
49649a0bf528SMauro Carvalho Chehab 	if (status < 0)
49659a0bf528SMauro Carvalho Chehab 		goto error;
49669a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD2__A, 12543);
49679a0bf528SMauro Carvalho Chehab 	if (status < 0)
49689a0bf528SMauro Carvalho Chehab 		goto error;
49699a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD3__A, 12931);
49709a0bf528SMauro Carvalho Chehab 	if (status < 0)
49719a0bf528SMauro Carvalho Chehab 		goto error;
49729a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD4__A, 13629);
49739a0bf528SMauro Carvalho Chehab 	if (status < 0)
49749a0bf528SMauro Carvalho Chehab 		goto error;
49759a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD5__A, 15385);
49769a0bf528SMauro Carvalho Chehab 	if (status < 0)
49779a0bf528SMauro Carvalho Chehab 		goto error;
49789a0bf528SMauro Carvalho Chehab 
49799a0bf528SMauro Carvalho Chehab 	/* Decision Feedback Equalizer */
49809a0bf528SMauro Carvalho Chehab 	status = write16(state, QAM_DQ_QUAL_FUN0__A, 8);
49819a0bf528SMauro Carvalho Chehab 	if (status < 0)
49829a0bf528SMauro Carvalho Chehab 		goto error;
49839a0bf528SMauro Carvalho Chehab 	status = write16(state, QAM_DQ_QUAL_FUN1__A, 8);
49849a0bf528SMauro Carvalho Chehab 	if (status < 0)
49859a0bf528SMauro Carvalho Chehab 		goto error;
49869a0bf528SMauro Carvalho Chehab 	status = write16(state, QAM_DQ_QUAL_FUN2__A, 8);
49879a0bf528SMauro Carvalho Chehab 	if (status < 0)
49889a0bf528SMauro Carvalho Chehab 		goto error;
49899a0bf528SMauro Carvalho Chehab 	status = write16(state, QAM_DQ_QUAL_FUN3__A, 8);
49909a0bf528SMauro Carvalho Chehab 	if (status < 0)
49919a0bf528SMauro Carvalho Chehab 		goto error;
49929a0bf528SMauro Carvalho Chehab 	status = write16(state, QAM_DQ_QUAL_FUN4__A, 6);
49939a0bf528SMauro Carvalho Chehab 	if (status < 0)
49949a0bf528SMauro Carvalho Chehab 		goto error;
49959a0bf528SMauro Carvalho Chehab 	status = write16(state, QAM_DQ_QUAL_FUN5__A, 0);
49969a0bf528SMauro Carvalho Chehab 	if (status < 0)
49979a0bf528SMauro Carvalho Chehab 		goto error;
49989a0bf528SMauro Carvalho Chehab 
49999a0bf528SMauro Carvalho Chehab 	status = write16(state, QAM_SY_SYNC_HWM__A, 5);
50009a0bf528SMauro Carvalho Chehab 	if (status < 0)
50019a0bf528SMauro Carvalho Chehab 		goto error;
50029a0bf528SMauro Carvalho Chehab 	status = write16(state, QAM_SY_SYNC_AWM__A, 4);
50039a0bf528SMauro Carvalho Chehab 	if (status < 0)
50049a0bf528SMauro Carvalho Chehab 		goto error;
50059a0bf528SMauro Carvalho Chehab 	status = write16(state, QAM_SY_SYNC_LWM__A, 3);
50069a0bf528SMauro Carvalho Chehab 	if (status < 0)
50079a0bf528SMauro Carvalho Chehab 		goto error;
50089a0bf528SMauro Carvalho Chehab 
50099a0bf528SMauro Carvalho Chehab 	/* QAM Slicer Settings */
50109a0bf528SMauro Carvalho Chehab 
50119a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_SL_SIG_POWER__A, DRXK_QAM_SL_SIG_POWER_QAM256);
50129a0bf528SMauro Carvalho Chehab 	if (status < 0)
50139a0bf528SMauro Carvalho Chehab 		goto error;
50149a0bf528SMauro Carvalho Chehab 
50159a0bf528SMauro Carvalho Chehab 
50169a0bf528SMauro Carvalho Chehab 	/* QAM Loop Controller Coeficients */
50179a0bf528SMauro Carvalho Chehab 
50189a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_CA_FINE__A, 15);
50199a0bf528SMauro Carvalho Chehab 	if (status < 0)
50209a0bf528SMauro Carvalho Chehab 		goto error;
50219a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_CA_COARSE__A, 40);
50229a0bf528SMauro Carvalho Chehab 	if (status < 0)
50239a0bf528SMauro Carvalho Chehab 		goto error;
50249a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_EP_FINE__A, 12);
50259a0bf528SMauro Carvalho Chehab 	if (status < 0)
50269a0bf528SMauro Carvalho Chehab 		goto error;
50279a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_EP_MEDIUM__A, 24);
50289a0bf528SMauro Carvalho Chehab 	if (status < 0)
50299a0bf528SMauro Carvalho Chehab 		goto error;
50309a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_EP_COARSE__A, 24);
50319a0bf528SMauro Carvalho Chehab 	if (status < 0)
50329a0bf528SMauro Carvalho Chehab 		goto error;
50339a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_EI_FINE__A, 12);
50349a0bf528SMauro Carvalho Chehab 	if (status < 0)
50359a0bf528SMauro Carvalho Chehab 		goto error;
50369a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_EI_MEDIUM__A, 16);
50379a0bf528SMauro Carvalho Chehab 	if (status < 0)
50389a0bf528SMauro Carvalho Chehab 		goto error;
50399a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_EI_COARSE__A, 16);
50409a0bf528SMauro Carvalho Chehab 	if (status < 0)
50419a0bf528SMauro Carvalho Chehab 		goto error;
50429a0bf528SMauro Carvalho Chehab 
50439a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_CP_FINE__A, 5);
50449a0bf528SMauro Carvalho Chehab 	if (status < 0)
50459a0bf528SMauro Carvalho Chehab 		goto error;
50469a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_CP_MEDIUM__A, 50);
50479a0bf528SMauro Carvalho Chehab 	if (status < 0)
50489a0bf528SMauro Carvalho Chehab 		goto error;
50499a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_CP_COARSE__A, 250);
50509a0bf528SMauro Carvalho Chehab 	if (status < 0)
50519a0bf528SMauro Carvalho Chehab 		goto error;
50529a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_CI_FINE__A, 5);
50539a0bf528SMauro Carvalho Chehab 	if (status < 0)
50549a0bf528SMauro Carvalho Chehab 		goto error;
50559a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_CI_MEDIUM__A, 50);
50569a0bf528SMauro Carvalho Chehab 	if (status < 0)
50579a0bf528SMauro Carvalho Chehab 		goto error;
50589a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_CI_COARSE__A, 125);
50599a0bf528SMauro Carvalho Chehab 	if (status < 0)
50609a0bf528SMauro Carvalho Chehab 		goto error;
50619a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_CF_FINE__A, 16);
50629a0bf528SMauro Carvalho Chehab 	if (status < 0)
50639a0bf528SMauro Carvalho Chehab 		goto error;
50649a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_CF_MEDIUM__A, 25);
50659a0bf528SMauro Carvalho Chehab 	if (status < 0)
50669a0bf528SMauro Carvalho Chehab 		goto error;
50679a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_CF_COARSE__A, 48);
50689a0bf528SMauro Carvalho Chehab 	if (status < 0)
50699a0bf528SMauro Carvalho Chehab 		goto error;
50709a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_CF1_FINE__A, 5);
50719a0bf528SMauro Carvalho Chehab 	if (status < 0)
50729a0bf528SMauro Carvalho Chehab 		goto error;
50739a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_CF1_MEDIUM__A, 10);
50749a0bf528SMauro Carvalho Chehab 	if (status < 0)
50759a0bf528SMauro Carvalho Chehab 		goto error;
50769a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_LC_CF1_COARSE__A, 10);
50779a0bf528SMauro Carvalho Chehab 	if (status < 0)
50789a0bf528SMauro Carvalho Chehab 		goto error;
50799a0bf528SMauro Carvalho Chehab 
50809a0bf528SMauro Carvalho Chehab 
50819a0bf528SMauro Carvalho Chehab 	/* QAM State Machine (FSM) Thresholds */
50829a0bf528SMauro Carvalho Chehab 
50839a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_FSM_RTH__A, 50);
50849a0bf528SMauro Carvalho Chehab 	if (status < 0)
50859a0bf528SMauro Carvalho Chehab 		goto error;
50869a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_FSM_FTH__A, 60);
50879a0bf528SMauro Carvalho Chehab 	if (status < 0)
50889a0bf528SMauro Carvalho Chehab 		goto error;
50899a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_FSM_CTH__A, 80);
50909a0bf528SMauro Carvalho Chehab 	if (status < 0)
50919a0bf528SMauro Carvalho Chehab 		goto error;
50929a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_FSM_PTH__A, 100);
50939a0bf528SMauro Carvalho Chehab 	if (status < 0)
50949a0bf528SMauro Carvalho Chehab 		goto error;
50959a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_FSM_QTH__A, 150);
50969a0bf528SMauro Carvalho Chehab 	if (status < 0)
50979a0bf528SMauro Carvalho Chehab 		goto error;
50989a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_FSM_MTH__A, 110);
50999a0bf528SMauro Carvalho Chehab 	if (status < 0)
51009a0bf528SMauro Carvalho Chehab 		goto error;
51019a0bf528SMauro Carvalho Chehab 
51029a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_FSM_RATE_LIM__A, 40);
51039a0bf528SMauro Carvalho Chehab 	if (status < 0)
51049a0bf528SMauro Carvalho Chehab 		goto error;
51059a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_FSM_COUNT_LIM__A, 4);
51069a0bf528SMauro Carvalho Chehab 	if (status < 0)
51079a0bf528SMauro Carvalho Chehab 		goto error;
51089a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_FSM_FREQ_LIM__A, 12);
51099a0bf528SMauro Carvalho Chehab 	if (status < 0)
51109a0bf528SMauro Carvalho Chehab 		goto error;
51119a0bf528SMauro Carvalho Chehab 
51129a0bf528SMauro Carvalho Chehab 
51139a0bf528SMauro Carvalho Chehab 	/* QAM FSM Tracking Parameters */
51149a0bf528SMauro Carvalho Chehab 
51159a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_FSM_MEDIAN_AV_MULT__A, (u16) 8);
51169a0bf528SMauro Carvalho Chehab 	if (status < 0)
51179a0bf528SMauro Carvalho Chehab 		goto error;
51189a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_FSM_RADIUS_AV_LIMIT__A, (u16) 74);
51199a0bf528SMauro Carvalho Chehab 	if (status < 0)
51209a0bf528SMauro Carvalho Chehab 		goto error;
51219a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET1__A, (u16) 18);
51229a0bf528SMauro Carvalho Chehab 	if (status < 0)
51239a0bf528SMauro Carvalho Chehab 		goto error;
51249a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET2__A, (u16) 13);
51259a0bf528SMauro Carvalho Chehab 	if (status < 0)
51269a0bf528SMauro Carvalho Chehab 		goto error;
51279a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET3__A, (u16) 7);
51289a0bf528SMauro Carvalho Chehab 	if (status < 0)
51299a0bf528SMauro Carvalho Chehab 		goto error;
51309a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET4__A, (u16) 0);
51319a0bf528SMauro Carvalho Chehab 	if (status < 0)
51329a0bf528SMauro Carvalho Chehab 		goto error;
51339a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET5__A, (u16) -8);
51349a0bf528SMauro Carvalho Chehab error:
51359a0bf528SMauro Carvalho Chehab 	if (status < 0)
51363a4398f5SMauro Carvalho Chehab 		pr_err("Error %d on %s\n", status, __func__);
51379a0bf528SMauro Carvalho Chehab 	return status;
51389a0bf528SMauro Carvalho Chehab }
51399a0bf528SMauro Carvalho Chehab 
51409a0bf528SMauro Carvalho Chehab 
51419a0bf528SMauro Carvalho Chehab /*============================================================================*/
51429a0bf528SMauro Carvalho Chehab /**
51439a0bf528SMauro Carvalho Chehab * \brief Reset QAM block.
51449a0bf528SMauro Carvalho Chehab * \param demod:   instance of demod.
51459a0bf528SMauro Carvalho Chehab * \param channel: pointer to channel data.
51469a0bf528SMauro Carvalho Chehab * \return DRXStatus_t.
51479a0bf528SMauro Carvalho Chehab */
5148cd7a67a4SMauro Carvalho Chehab static int qam_reset_qam(struct drxk_state *state)
51499a0bf528SMauro Carvalho Chehab {
51509a0bf528SMauro Carvalho Chehab 	int status;
5151cd7a67a4SMauro Carvalho Chehab 	u16 cmd_result;
51529a0bf528SMauro Carvalho Chehab 
51539a0bf528SMauro Carvalho Chehab 	dprintk(1, "\n");
51549a0bf528SMauro Carvalho Chehab 	/* Stop QAM comstate->m_exec */
51559a0bf528SMauro Carvalho Chehab 	status = write16(state, QAM_COMM_EXEC__A, QAM_COMM_EXEC_STOP);
51569a0bf528SMauro Carvalho Chehab 	if (status < 0)
51579a0bf528SMauro Carvalho Chehab 		goto error;
51589a0bf528SMauro Carvalho Chehab 
5159cd7a67a4SMauro Carvalho Chehab 	status = scu_command(state, SCU_RAM_COMMAND_STANDARD_QAM | SCU_RAM_COMMAND_CMD_DEMOD_RESET, 0, NULL, 1, &cmd_result);
51609a0bf528SMauro Carvalho Chehab error:
51619a0bf528SMauro Carvalho Chehab 	if (status < 0)
51623a4398f5SMauro Carvalho Chehab 		pr_err("Error %d on %s\n", status, __func__);
51639a0bf528SMauro Carvalho Chehab 	return status;
51649a0bf528SMauro Carvalho Chehab }
51659a0bf528SMauro Carvalho Chehab 
51669a0bf528SMauro Carvalho Chehab /*============================================================================*/
51679a0bf528SMauro Carvalho Chehab 
51689a0bf528SMauro Carvalho Chehab /**
51699a0bf528SMauro Carvalho Chehab * \brief Set QAM symbolrate.
51709a0bf528SMauro Carvalho Chehab * \param demod:   instance of demod.
51719a0bf528SMauro Carvalho Chehab * \param channel: pointer to channel data.
51729a0bf528SMauro Carvalho Chehab * \return DRXStatus_t.
51739a0bf528SMauro Carvalho Chehab */
5174cd7a67a4SMauro Carvalho Chehab static int qam_set_symbolrate(struct drxk_state *state)
51759a0bf528SMauro Carvalho Chehab {
5176cd7a67a4SMauro Carvalho Chehab 	u32 adc_frequency = 0;
5177cd7a67a4SMauro Carvalho Chehab 	u32 symb_freq = 0;
5178cd7a67a4SMauro Carvalho Chehab 	u32 iqm_rc_rate = 0;
51799a0bf528SMauro Carvalho Chehab 	u16 ratesel = 0;
5180cd7a67a4SMauro Carvalho Chehab 	u32 lc_symb_rate = 0;
51819a0bf528SMauro Carvalho Chehab 	int status;
51829a0bf528SMauro Carvalho Chehab 
51839a0bf528SMauro Carvalho Chehab 	dprintk(1, "\n");
51849a0bf528SMauro Carvalho Chehab 	/* Select & calculate correct IQM rate */
5185cd7a67a4SMauro Carvalho Chehab 	adc_frequency = (state->m_sys_clock_freq * 1000) / 3;
51869a0bf528SMauro Carvalho Chehab 	ratesel = 0;
51879a0bf528SMauro Carvalho Chehab 	/* printk(KERN_DEBUG "drxk: SR %d\n", state->props.symbol_rate); */
51889a0bf528SMauro Carvalho Chehab 	if (state->props.symbol_rate <= 1188750)
51899a0bf528SMauro Carvalho Chehab 		ratesel = 3;
51909a0bf528SMauro Carvalho Chehab 	else if (state->props.symbol_rate <= 2377500)
51919a0bf528SMauro Carvalho Chehab 		ratesel = 2;
51929a0bf528SMauro Carvalho Chehab 	else if (state->props.symbol_rate <= 4755000)
51939a0bf528SMauro Carvalho Chehab 		ratesel = 1;
51949a0bf528SMauro Carvalho Chehab 	status = write16(state, IQM_FD_RATESEL__A, ratesel);
51959a0bf528SMauro Carvalho Chehab 	if (status < 0)
51969a0bf528SMauro Carvalho Chehab 		goto error;
51979a0bf528SMauro Carvalho Chehab 
51989a0bf528SMauro Carvalho Chehab 	/*
51999a0bf528SMauro Carvalho Chehab 		IqmRcRate = ((Fadc / (symbolrate * (4<<ratesel))) - 1) * (1<<23)
52009a0bf528SMauro Carvalho Chehab 		*/
5201cd7a67a4SMauro Carvalho Chehab 	symb_freq = state->props.symbol_rate * (1 << ratesel);
5202cd7a67a4SMauro Carvalho Chehab 	if (symb_freq == 0) {
52039a0bf528SMauro Carvalho Chehab 		/* Divide by zero */
52049a0bf528SMauro Carvalho Chehab 		status = -EINVAL;
52059a0bf528SMauro Carvalho Chehab 		goto error;
52069a0bf528SMauro Carvalho Chehab 	}
5207cd7a67a4SMauro Carvalho Chehab 	iqm_rc_rate = (adc_frequency / symb_freq) * (1 << 21) +
5208cd7a67a4SMauro Carvalho Chehab 		(Frac28a((adc_frequency % symb_freq), symb_freq) >> 7) -
52099a0bf528SMauro Carvalho Chehab 		(1 << 23);
5210cd7a67a4SMauro Carvalho Chehab 	status = write32(state, IQM_RC_RATE_OFS_LO__A, iqm_rc_rate);
52119a0bf528SMauro Carvalho Chehab 	if (status < 0)
52129a0bf528SMauro Carvalho Chehab 		goto error;
5213cd7a67a4SMauro Carvalho Chehab 	state->m_iqm_rc_rate = iqm_rc_rate;
52149a0bf528SMauro Carvalho Chehab 	/*
5215cd7a67a4SMauro Carvalho Chehab 		LcSymbFreq = round (.125 *  symbolrate / adc_freq * (1<<15))
52169a0bf528SMauro Carvalho Chehab 		*/
5217cd7a67a4SMauro Carvalho Chehab 	symb_freq = state->props.symbol_rate;
5218cd7a67a4SMauro Carvalho Chehab 	if (adc_frequency == 0) {
52199a0bf528SMauro Carvalho Chehab 		/* Divide by zero */
52209a0bf528SMauro Carvalho Chehab 		status = -EINVAL;
52219a0bf528SMauro Carvalho Chehab 		goto error;
52229a0bf528SMauro Carvalho Chehab 	}
5223cd7a67a4SMauro Carvalho Chehab 	lc_symb_rate = (symb_freq / adc_frequency) * (1 << 12) +
5224cd7a67a4SMauro Carvalho Chehab 		(Frac28a((symb_freq % adc_frequency), adc_frequency) >>
52259a0bf528SMauro Carvalho Chehab 		16);
5226cd7a67a4SMauro Carvalho Chehab 	if (lc_symb_rate > 511)
5227cd7a67a4SMauro Carvalho Chehab 		lc_symb_rate = 511;
5228cd7a67a4SMauro Carvalho Chehab 	status = write16(state, QAM_LC_SYMBOL_FREQ__A, (u16) lc_symb_rate);
52299a0bf528SMauro Carvalho Chehab 
52309a0bf528SMauro Carvalho Chehab error:
52319a0bf528SMauro Carvalho Chehab 	if (status < 0)
52323a4398f5SMauro Carvalho Chehab 		pr_err("Error %d on %s\n", status, __func__);
52339a0bf528SMauro Carvalho Chehab 	return status;
52349a0bf528SMauro Carvalho Chehab }
52359a0bf528SMauro Carvalho Chehab 
52369a0bf528SMauro Carvalho Chehab /*============================================================================*/
52379a0bf528SMauro Carvalho Chehab 
52389a0bf528SMauro Carvalho Chehab /**
52399a0bf528SMauro Carvalho Chehab * \brief Get QAM lock status.
52409a0bf528SMauro Carvalho Chehab * \param demod:   instance of demod.
52419a0bf528SMauro Carvalho Chehab * \param channel: pointer to channel data.
52429a0bf528SMauro Carvalho Chehab * \return DRXStatus_t.
52439a0bf528SMauro Carvalho Chehab */
52449a0bf528SMauro Carvalho Chehab 
5245cd7a67a4SMauro Carvalho Chehab static int get_qam_lock_status(struct drxk_state *state, u32 *p_lock_status)
52469a0bf528SMauro Carvalho Chehab {
52479a0bf528SMauro Carvalho Chehab 	int status;
5248cd7a67a4SMauro Carvalho Chehab 	u16 result[2] = { 0, 0 };
52499a0bf528SMauro Carvalho Chehab 
52509a0bf528SMauro Carvalho Chehab 	dprintk(1, "\n");
5251cd7a67a4SMauro Carvalho Chehab 	*p_lock_status = NOT_LOCKED;
52529a0bf528SMauro Carvalho Chehab 	status = scu_command(state,
52539a0bf528SMauro Carvalho Chehab 			SCU_RAM_COMMAND_STANDARD_QAM |
52549a0bf528SMauro Carvalho Chehab 			SCU_RAM_COMMAND_CMD_DEMOD_GET_LOCK, 0, NULL, 2,
5255cd7a67a4SMauro Carvalho Chehab 			result);
52569a0bf528SMauro Carvalho Chehab 	if (status < 0)
52573a4398f5SMauro Carvalho Chehab 		pr_err("Error %d on %s\n", status, __func__);
52589a0bf528SMauro Carvalho Chehab 
5259cd7a67a4SMauro Carvalho Chehab 	if (result[1] < SCU_RAM_QAM_LOCKED_LOCKED_DEMOD_LOCKED) {
52609a0bf528SMauro Carvalho Chehab 		/* 0x0000 NOT LOCKED */
5261cd7a67a4SMauro Carvalho Chehab 	} else if (result[1] < SCU_RAM_QAM_LOCKED_LOCKED_LOCKED) {
52629a0bf528SMauro Carvalho Chehab 		/* 0x4000 DEMOD LOCKED */
5263cd7a67a4SMauro Carvalho Chehab 		*p_lock_status = DEMOD_LOCK;
5264cd7a67a4SMauro Carvalho Chehab 	} else if (result[1] < SCU_RAM_QAM_LOCKED_LOCKED_NEVER_LOCK) {
52659a0bf528SMauro Carvalho Chehab 		/* 0x8000 DEMOD + FEC LOCKED (system lock) */
5266cd7a67a4SMauro Carvalho Chehab 		*p_lock_status = MPEG_LOCK;
52679a0bf528SMauro Carvalho Chehab 	} else {
52689a0bf528SMauro Carvalho Chehab 		/* 0xC000 NEVER LOCKED */
52699a0bf528SMauro Carvalho Chehab 		/* (system will never be able to lock to the signal) */
52709a0bf528SMauro Carvalho Chehab 		/* TODO: check this, intermediate & standard specific lock states are not
52719a0bf528SMauro Carvalho Chehab 		   taken into account here */
5272cd7a67a4SMauro Carvalho Chehab 		*p_lock_status = NEVER_LOCK;
52739a0bf528SMauro Carvalho Chehab 	}
52749a0bf528SMauro Carvalho Chehab 	return status;
52759a0bf528SMauro Carvalho Chehab }
52769a0bf528SMauro Carvalho Chehab 
52779a0bf528SMauro Carvalho Chehab #define QAM_MIRROR__M         0x03
52789a0bf528SMauro Carvalho Chehab #define QAM_MIRROR_NORMAL     0x00
52799a0bf528SMauro Carvalho Chehab #define QAM_MIRRORED          0x01
52809a0bf528SMauro Carvalho Chehab #define QAM_MIRROR_AUTO_ON    0x02
52819a0bf528SMauro Carvalho Chehab #define QAM_LOCKRANGE__M      0x10
52829a0bf528SMauro Carvalho Chehab #define QAM_LOCKRANGE_NORMAL  0x10
52839a0bf528SMauro Carvalho Chehab 
5284cd7a67a4SMauro Carvalho Chehab static int qam_demodulator_command(struct drxk_state *state,
5285cd7a67a4SMauro Carvalho Chehab 				 int number_of_parameters)
52869a0bf528SMauro Carvalho Chehab {
52879a0bf528SMauro Carvalho Chehab 	int status;
5288cd7a67a4SMauro Carvalho Chehab 	u16 cmd_result;
5289cd7a67a4SMauro Carvalho Chehab 	u16 set_param_parameters[4] = { 0, 0, 0, 0 };
52909a0bf528SMauro Carvalho Chehab 
5291cd7a67a4SMauro Carvalho Chehab 	set_param_parameters[0] = state->m_constellation;	/* modulation     */
5292cd7a67a4SMauro Carvalho Chehab 	set_param_parameters[1] = DRXK_QAM_I12_J17;	/* interleave mode   */
52939a0bf528SMauro Carvalho Chehab 
5294cd7a67a4SMauro Carvalho Chehab 	if (number_of_parameters == 2) {
5295cd7a67a4SMauro Carvalho Chehab 		u16 set_env_parameters[1] = { 0 };
52969a0bf528SMauro Carvalho Chehab 
5297cd7a67a4SMauro Carvalho Chehab 		if (state->m_operation_mode == OM_QAM_ITU_C)
5298cd7a67a4SMauro Carvalho Chehab 			set_env_parameters[0] = QAM_TOP_ANNEX_C;
52999a0bf528SMauro Carvalho Chehab 		else
5300cd7a67a4SMauro Carvalho Chehab 			set_env_parameters[0] = QAM_TOP_ANNEX_A;
53019a0bf528SMauro Carvalho Chehab 
53029a0bf528SMauro Carvalho Chehab 		status = scu_command(state,
53039a0bf528SMauro Carvalho Chehab 				     SCU_RAM_COMMAND_STANDARD_QAM | SCU_RAM_COMMAND_CMD_DEMOD_SET_ENV,
5304cd7a67a4SMauro Carvalho Chehab 				     1, set_env_parameters, 1, &cmd_result);
53059a0bf528SMauro Carvalho Chehab 		if (status < 0)
53069a0bf528SMauro Carvalho Chehab 			goto error;
53079a0bf528SMauro Carvalho Chehab 
53089a0bf528SMauro Carvalho Chehab 		status = scu_command(state,
53099a0bf528SMauro Carvalho Chehab 				     SCU_RAM_COMMAND_STANDARD_QAM | SCU_RAM_COMMAND_CMD_DEMOD_SET_PARAM,
5310cd7a67a4SMauro Carvalho Chehab 				     number_of_parameters, set_param_parameters,
5311cd7a67a4SMauro Carvalho Chehab 				     1, &cmd_result);
5312cd7a67a4SMauro Carvalho Chehab 	} else if (number_of_parameters == 4) {
5313cd7a67a4SMauro Carvalho Chehab 		if (state->m_operation_mode == OM_QAM_ITU_C)
5314cd7a67a4SMauro Carvalho Chehab 			set_param_parameters[2] = QAM_TOP_ANNEX_C;
53159a0bf528SMauro Carvalho Chehab 		else
5316cd7a67a4SMauro Carvalho Chehab 			set_param_parameters[2] = QAM_TOP_ANNEX_A;
53179a0bf528SMauro Carvalho Chehab 
5318cd7a67a4SMauro Carvalho Chehab 		set_param_parameters[3] |= (QAM_MIRROR_AUTO_ON);
53199a0bf528SMauro Carvalho Chehab 		/* Env parameters */
53209a0bf528SMauro Carvalho Chehab 		/* check for LOCKRANGE Extented */
5321cd7a67a4SMauro Carvalho Chehab 		/* set_param_parameters[3] |= QAM_LOCKRANGE_NORMAL; */
53229a0bf528SMauro Carvalho Chehab 
53239a0bf528SMauro Carvalho Chehab 		status = scu_command(state,
53249a0bf528SMauro Carvalho Chehab 				     SCU_RAM_COMMAND_STANDARD_QAM | SCU_RAM_COMMAND_CMD_DEMOD_SET_PARAM,
5325cd7a67a4SMauro Carvalho Chehab 				     number_of_parameters, set_param_parameters,
5326cd7a67a4SMauro Carvalho Chehab 				     1, &cmd_result);
53279a0bf528SMauro Carvalho Chehab 	} else {
53283a4398f5SMauro Carvalho Chehab 		pr_warn("Unknown QAM demodulator parameter count %d\n",
53293a4398f5SMauro Carvalho Chehab 			number_of_parameters);
533094af1b63SMauro Carvalho Chehab 		status = -EINVAL;
53319a0bf528SMauro Carvalho Chehab 	}
53329a0bf528SMauro Carvalho Chehab 
53339a0bf528SMauro Carvalho Chehab error:
53349a0bf528SMauro Carvalho Chehab 	if (status < 0)
53353a4398f5SMauro Carvalho Chehab 		pr_warn("Warning %d on %s\n", status, __func__);
53369a0bf528SMauro Carvalho Chehab 	return status;
53379a0bf528SMauro Carvalho Chehab }
53389a0bf528SMauro Carvalho Chehab 
5339cd7a67a4SMauro Carvalho Chehab static int set_qam(struct drxk_state *state, u16 intermediate_freqk_hz,
5340cd7a67a4SMauro Carvalho Chehab 		  s32 tuner_freq_offset)
53419a0bf528SMauro Carvalho Chehab {
53429a0bf528SMauro Carvalho Chehab 	int status;
5343cd7a67a4SMauro Carvalho Chehab 	u16 cmd_result;
5344cd7a67a4SMauro Carvalho Chehab 	int qam_demod_param_count = state->qam_demod_parameter_count;
53459a0bf528SMauro Carvalho Chehab 
53469a0bf528SMauro Carvalho Chehab 	dprintk(1, "\n");
53479a0bf528SMauro Carvalho Chehab 	/*
53489a0bf528SMauro Carvalho Chehab 	 * STEP 1: reset demodulator
53499a0bf528SMauro Carvalho Chehab 	 *	resets FEC DI and FEC RS
53509a0bf528SMauro Carvalho Chehab 	 *	resets QAM block
53519a0bf528SMauro Carvalho Chehab 	 *	resets SCU variables
53529a0bf528SMauro Carvalho Chehab 	 */
53539a0bf528SMauro Carvalho Chehab 	status = write16(state, FEC_DI_COMM_EXEC__A, FEC_DI_COMM_EXEC_STOP);
53549a0bf528SMauro Carvalho Chehab 	if (status < 0)
53559a0bf528SMauro Carvalho Chehab 		goto error;
53569a0bf528SMauro Carvalho Chehab 	status = write16(state, FEC_RS_COMM_EXEC__A, FEC_RS_COMM_EXEC_STOP);
53579a0bf528SMauro Carvalho Chehab 	if (status < 0)
53589a0bf528SMauro Carvalho Chehab 		goto error;
5359cd7a67a4SMauro Carvalho Chehab 	status = qam_reset_qam(state);
53609a0bf528SMauro Carvalho Chehab 	if (status < 0)
53619a0bf528SMauro Carvalho Chehab 		goto error;
53629a0bf528SMauro Carvalho Chehab 
53639a0bf528SMauro Carvalho Chehab 	/*
53649a0bf528SMauro Carvalho Chehab 	 * STEP 2: configure demodulator
53659a0bf528SMauro Carvalho Chehab 	 *	-set params; resets IQM,QAM,FEC HW; initializes some
53669a0bf528SMauro Carvalho Chehab 	 *       SCU variables
53679a0bf528SMauro Carvalho Chehab 	 */
5368cd7a67a4SMauro Carvalho Chehab 	status = qam_set_symbolrate(state);
53699a0bf528SMauro Carvalho Chehab 	if (status < 0)
53709a0bf528SMauro Carvalho Chehab 		goto error;
53719a0bf528SMauro Carvalho Chehab 
53729a0bf528SMauro Carvalho Chehab 	/* Set params */
53739a0bf528SMauro Carvalho Chehab 	switch (state->props.modulation) {
53749a0bf528SMauro Carvalho Chehab 	case QAM_256:
5375cd7a67a4SMauro Carvalho Chehab 		state->m_constellation = DRX_CONSTELLATION_QAM256;
53769a0bf528SMauro Carvalho Chehab 		break;
53779a0bf528SMauro Carvalho Chehab 	case QAM_AUTO:
53789a0bf528SMauro Carvalho Chehab 	case QAM_64:
5379cd7a67a4SMauro Carvalho Chehab 		state->m_constellation = DRX_CONSTELLATION_QAM64;
53809a0bf528SMauro Carvalho Chehab 		break;
53819a0bf528SMauro Carvalho Chehab 	case QAM_16:
5382cd7a67a4SMauro Carvalho Chehab 		state->m_constellation = DRX_CONSTELLATION_QAM16;
53839a0bf528SMauro Carvalho Chehab 		break;
53849a0bf528SMauro Carvalho Chehab 	case QAM_32:
5385cd7a67a4SMauro Carvalho Chehab 		state->m_constellation = DRX_CONSTELLATION_QAM32;
53869a0bf528SMauro Carvalho Chehab 		break;
53879a0bf528SMauro Carvalho Chehab 	case QAM_128:
5388cd7a67a4SMauro Carvalho Chehab 		state->m_constellation = DRX_CONSTELLATION_QAM128;
53899a0bf528SMauro Carvalho Chehab 		break;
53909a0bf528SMauro Carvalho Chehab 	default:
53919a0bf528SMauro Carvalho Chehab 		status = -EINVAL;
53929a0bf528SMauro Carvalho Chehab 		break;
53939a0bf528SMauro Carvalho Chehab 	}
53949a0bf528SMauro Carvalho Chehab 	if (status < 0)
53959a0bf528SMauro Carvalho Chehab 		goto error;
53969a0bf528SMauro Carvalho Chehab 
53979a0bf528SMauro Carvalho Chehab 	/* Use the 4-parameter if it's requested or we're probing for
53989a0bf528SMauro Carvalho Chehab 	 * the correct command. */
53999a0bf528SMauro Carvalho Chehab 	if (state->qam_demod_parameter_count == 4
54009a0bf528SMauro Carvalho Chehab 		|| !state->qam_demod_parameter_count) {
5401cd7a67a4SMauro Carvalho Chehab 		qam_demod_param_count = 4;
5402cd7a67a4SMauro Carvalho Chehab 		status = qam_demodulator_command(state, qam_demod_param_count);
54039a0bf528SMauro Carvalho Chehab 	}
54049a0bf528SMauro Carvalho Chehab 
54059a0bf528SMauro Carvalho Chehab 	/* Use the 2-parameter command if it was requested or if we're
54069a0bf528SMauro Carvalho Chehab 	 * probing for the correct command and the 4-parameter command
54079a0bf528SMauro Carvalho Chehab 	 * failed. */
54089a0bf528SMauro Carvalho Chehab 	if (state->qam_demod_parameter_count == 2
54099a0bf528SMauro Carvalho Chehab 		|| (!state->qam_demod_parameter_count && status < 0)) {
5410cd7a67a4SMauro Carvalho Chehab 		qam_demod_param_count = 2;
5411cd7a67a4SMauro Carvalho Chehab 		status = qam_demodulator_command(state, qam_demod_param_count);
54129a0bf528SMauro Carvalho Chehab 	}
54139a0bf528SMauro Carvalho Chehab 
54149a0bf528SMauro Carvalho Chehab 	if (status < 0) {
54159a0bf528SMauro Carvalho Chehab 		dprintk(1, "Could not set demodulator parameters. Make "
54169a0bf528SMauro Carvalho Chehab 			"sure qam_demod_parameter_count (%d) is correct for "
54179a0bf528SMauro Carvalho Chehab 			"your firmware (%s).\n",
54189a0bf528SMauro Carvalho Chehab 			state->qam_demod_parameter_count,
54199a0bf528SMauro Carvalho Chehab 			state->microcode_name);
54209a0bf528SMauro Carvalho Chehab 		goto error;
54219a0bf528SMauro Carvalho Chehab 	} else if (!state->qam_demod_parameter_count) {
54229a0bf528SMauro Carvalho Chehab 		dprintk(1, "Auto-probing the correct QAM demodulator command "
54239a0bf528SMauro Carvalho Chehab 			"parameters was successful - using %d parameters.\n",
5424cd7a67a4SMauro Carvalho Chehab 			qam_demod_param_count);
54259a0bf528SMauro Carvalho Chehab 
54269a0bf528SMauro Carvalho Chehab 		/*
54279a0bf528SMauro Carvalho Chehab 		 * One of our commands was successful. We don't need to
54289a0bf528SMauro Carvalho Chehab 		 * auto-probe anymore, now that we got the correct command.
54299a0bf528SMauro Carvalho Chehab 		 */
5430cd7a67a4SMauro Carvalho Chehab 		state->qam_demod_parameter_count = qam_demod_param_count;
54319a0bf528SMauro Carvalho Chehab 	}
54329a0bf528SMauro Carvalho Chehab 
54339a0bf528SMauro Carvalho Chehab 	/*
54349a0bf528SMauro Carvalho Chehab 	 * STEP 3: enable the system in a mode where the ADC provides valid
54359a0bf528SMauro Carvalho Chehab 	 * signal setup modulation independent registers
54369a0bf528SMauro Carvalho Chehab 	 */
54379a0bf528SMauro Carvalho Chehab #if 0
5438cd7a67a4SMauro Carvalho Chehab 	status = set_frequency(channel, tuner_freq_offset));
54399a0bf528SMauro Carvalho Chehab 	if (status < 0)
54409a0bf528SMauro Carvalho Chehab 		goto error;
54419a0bf528SMauro Carvalho Chehab #endif
5442cd7a67a4SMauro Carvalho Chehab 	status = set_frequency_shifter(state, intermediate_freqk_hz, tuner_freq_offset, true);
54439a0bf528SMauro Carvalho Chehab 	if (status < 0)
54449a0bf528SMauro Carvalho Chehab 		goto error;
54459a0bf528SMauro Carvalho Chehab 
54469a0bf528SMauro Carvalho Chehab 	/* Setup BER measurement */
5447cd7a67a4SMauro Carvalho Chehab 	status = set_qam_measurement(state, state->m_constellation, state->props.symbol_rate);
54489a0bf528SMauro Carvalho Chehab 	if (status < 0)
54499a0bf528SMauro Carvalho Chehab 		goto error;
54509a0bf528SMauro Carvalho Chehab 
54519a0bf528SMauro Carvalho Chehab 	/* Reset default values */
54529a0bf528SMauro Carvalho Chehab 	status = write16(state, IQM_CF_SCALE_SH__A, IQM_CF_SCALE_SH__PRE);
54539a0bf528SMauro Carvalho Chehab 	if (status < 0)
54549a0bf528SMauro Carvalho Chehab 		goto error;
54559a0bf528SMauro Carvalho Chehab 	status = write16(state, QAM_SY_TIMEOUT__A, QAM_SY_TIMEOUT__PRE);
54569a0bf528SMauro Carvalho Chehab 	if (status < 0)
54579a0bf528SMauro Carvalho Chehab 		goto error;
54589a0bf528SMauro Carvalho Chehab 
54599a0bf528SMauro Carvalho Chehab 	/* Reset default LC values */
54609a0bf528SMauro Carvalho Chehab 	status = write16(state, QAM_LC_RATE_LIMIT__A, 3);
54619a0bf528SMauro Carvalho Chehab 	if (status < 0)
54629a0bf528SMauro Carvalho Chehab 		goto error;
54639a0bf528SMauro Carvalho Chehab 	status = write16(state, QAM_LC_LPF_FACTORP__A, 4);
54649a0bf528SMauro Carvalho Chehab 	if (status < 0)
54659a0bf528SMauro Carvalho Chehab 		goto error;
54669a0bf528SMauro Carvalho Chehab 	status = write16(state, QAM_LC_LPF_FACTORI__A, 4);
54679a0bf528SMauro Carvalho Chehab 	if (status < 0)
54689a0bf528SMauro Carvalho Chehab 		goto error;
54699a0bf528SMauro Carvalho Chehab 	status = write16(state, QAM_LC_MODE__A, 7);
54709a0bf528SMauro Carvalho Chehab 	if (status < 0)
54719a0bf528SMauro Carvalho Chehab 		goto error;
54729a0bf528SMauro Carvalho Chehab 
54739a0bf528SMauro Carvalho Chehab 	status = write16(state, QAM_LC_QUAL_TAB0__A, 1);
54749a0bf528SMauro Carvalho Chehab 	if (status < 0)
54759a0bf528SMauro Carvalho Chehab 		goto error;
54769a0bf528SMauro Carvalho Chehab 	status = write16(state, QAM_LC_QUAL_TAB1__A, 1);
54779a0bf528SMauro Carvalho Chehab 	if (status < 0)
54789a0bf528SMauro Carvalho Chehab 		goto error;
54799a0bf528SMauro Carvalho Chehab 	status = write16(state, QAM_LC_QUAL_TAB2__A, 1);
54809a0bf528SMauro Carvalho Chehab 	if (status < 0)
54819a0bf528SMauro Carvalho Chehab 		goto error;
54829a0bf528SMauro Carvalho Chehab 	status = write16(state, QAM_LC_QUAL_TAB3__A, 1);
54839a0bf528SMauro Carvalho Chehab 	if (status < 0)
54849a0bf528SMauro Carvalho Chehab 		goto error;
54859a0bf528SMauro Carvalho Chehab 	status = write16(state, QAM_LC_QUAL_TAB4__A, 2);
54869a0bf528SMauro Carvalho Chehab 	if (status < 0)
54879a0bf528SMauro Carvalho Chehab 		goto error;
54889a0bf528SMauro Carvalho Chehab 	status = write16(state, QAM_LC_QUAL_TAB5__A, 2);
54899a0bf528SMauro Carvalho Chehab 	if (status < 0)
54909a0bf528SMauro Carvalho Chehab 		goto error;
54919a0bf528SMauro Carvalho Chehab 	status = write16(state, QAM_LC_QUAL_TAB6__A, 2);
54929a0bf528SMauro Carvalho Chehab 	if (status < 0)
54939a0bf528SMauro Carvalho Chehab 		goto error;
54949a0bf528SMauro Carvalho Chehab 	status = write16(state, QAM_LC_QUAL_TAB8__A, 2);
54959a0bf528SMauro Carvalho Chehab 	if (status < 0)
54969a0bf528SMauro Carvalho Chehab 		goto error;
54979a0bf528SMauro Carvalho Chehab 	status = write16(state, QAM_LC_QUAL_TAB9__A, 2);
54989a0bf528SMauro Carvalho Chehab 	if (status < 0)
54999a0bf528SMauro Carvalho Chehab 		goto error;
55009a0bf528SMauro Carvalho Chehab 	status = write16(state, QAM_LC_QUAL_TAB10__A, 2);
55019a0bf528SMauro Carvalho Chehab 	if (status < 0)
55029a0bf528SMauro Carvalho Chehab 		goto error;
55039a0bf528SMauro Carvalho Chehab 	status = write16(state, QAM_LC_QUAL_TAB12__A, 2);
55049a0bf528SMauro Carvalho Chehab 	if (status < 0)
55059a0bf528SMauro Carvalho Chehab 		goto error;
55069a0bf528SMauro Carvalho Chehab 	status = write16(state, QAM_LC_QUAL_TAB15__A, 3);
55079a0bf528SMauro Carvalho Chehab 	if (status < 0)
55089a0bf528SMauro Carvalho Chehab 		goto error;
55099a0bf528SMauro Carvalho Chehab 	status = write16(state, QAM_LC_QUAL_TAB16__A, 3);
55109a0bf528SMauro Carvalho Chehab 	if (status < 0)
55119a0bf528SMauro Carvalho Chehab 		goto error;
55129a0bf528SMauro Carvalho Chehab 	status = write16(state, QAM_LC_QUAL_TAB20__A, 4);
55139a0bf528SMauro Carvalho Chehab 	if (status < 0)
55149a0bf528SMauro Carvalho Chehab 		goto error;
55159a0bf528SMauro Carvalho Chehab 	status = write16(state, QAM_LC_QUAL_TAB25__A, 4);
55169a0bf528SMauro Carvalho Chehab 	if (status < 0)
55179a0bf528SMauro Carvalho Chehab 		goto error;
55189a0bf528SMauro Carvalho Chehab 
55199a0bf528SMauro Carvalho Chehab 	/* Mirroring, QAM-block starting point not inverted */
55209a0bf528SMauro Carvalho Chehab 	status = write16(state, QAM_SY_SP_INV__A, QAM_SY_SP_INV_SPECTRUM_INV_DIS);
55219a0bf528SMauro Carvalho Chehab 	if (status < 0)
55229a0bf528SMauro Carvalho Chehab 		goto error;
55239a0bf528SMauro Carvalho Chehab 
55249a0bf528SMauro Carvalho Chehab 	/* Halt SCU to enable safe non-atomic accesses */
55259a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_COMM_EXEC__A, SCU_COMM_EXEC_HOLD);
55269a0bf528SMauro Carvalho Chehab 	if (status < 0)
55279a0bf528SMauro Carvalho Chehab 		goto error;
55289a0bf528SMauro Carvalho Chehab 
55299a0bf528SMauro Carvalho Chehab 	/* STEP 4: modulation specific setup */
55309a0bf528SMauro Carvalho Chehab 	switch (state->props.modulation) {
55319a0bf528SMauro Carvalho Chehab 	case QAM_16:
5532cd7a67a4SMauro Carvalho Chehab 		status = set_qam16(state);
55339a0bf528SMauro Carvalho Chehab 		break;
55349a0bf528SMauro Carvalho Chehab 	case QAM_32:
5535cd7a67a4SMauro Carvalho Chehab 		status = set_qam32(state);
55369a0bf528SMauro Carvalho Chehab 		break;
55379a0bf528SMauro Carvalho Chehab 	case QAM_AUTO:
55389a0bf528SMauro Carvalho Chehab 	case QAM_64:
5539cd7a67a4SMauro Carvalho Chehab 		status = set_qam64(state);
55409a0bf528SMauro Carvalho Chehab 		break;
55419a0bf528SMauro Carvalho Chehab 	case QAM_128:
5542cd7a67a4SMauro Carvalho Chehab 		status = set_qam128(state);
55439a0bf528SMauro Carvalho Chehab 		break;
55449a0bf528SMauro Carvalho Chehab 	case QAM_256:
5545cd7a67a4SMauro Carvalho Chehab 		status = set_qam256(state);
55469a0bf528SMauro Carvalho Chehab 		break;
55479a0bf528SMauro Carvalho Chehab 	default:
55489a0bf528SMauro Carvalho Chehab 		status = -EINVAL;
55499a0bf528SMauro Carvalho Chehab 		break;
55509a0bf528SMauro Carvalho Chehab 	}
55519a0bf528SMauro Carvalho Chehab 	if (status < 0)
55529a0bf528SMauro Carvalho Chehab 		goto error;
55539a0bf528SMauro Carvalho Chehab 
55549a0bf528SMauro Carvalho Chehab 	/* Activate SCU to enable SCU commands */
55559a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_COMM_EXEC__A, SCU_COMM_EXEC_ACTIVE);
55569a0bf528SMauro Carvalho Chehab 	if (status < 0)
55579a0bf528SMauro Carvalho Chehab 		goto error;
55589a0bf528SMauro Carvalho Chehab 
55599a0bf528SMauro Carvalho Chehab 	/* Re-configure MPEG output, requires knowledge of channel bitrate */
55609a0bf528SMauro Carvalho Chehab 	/* extAttr->currentChannel.modulation = channel->modulation; */
55619a0bf528SMauro Carvalho Chehab 	/* extAttr->currentChannel.symbolrate    = channel->symbolrate; */
5562cd7a67a4SMauro Carvalho Chehab 	status = mpegts_dto_setup(state, state->m_operation_mode);
55639a0bf528SMauro Carvalho Chehab 	if (status < 0)
55649a0bf528SMauro Carvalho Chehab 		goto error;
55659a0bf528SMauro Carvalho Chehab 
5566cd7a67a4SMauro Carvalho Chehab 	/* start processes */
5567cd7a67a4SMauro Carvalho Chehab 	status = mpegts_start(state);
55689a0bf528SMauro Carvalho Chehab 	if (status < 0)
55699a0bf528SMauro Carvalho Chehab 		goto error;
55709a0bf528SMauro Carvalho Chehab 	status = write16(state, FEC_COMM_EXEC__A, FEC_COMM_EXEC_ACTIVE);
55719a0bf528SMauro Carvalho Chehab 	if (status < 0)
55729a0bf528SMauro Carvalho Chehab 		goto error;
55739a0bf528SMauro Carvalho Chehab 	status = write16(state, QAM_COMM_EXEC__A, QAM_COMM_EXEC_ACTIVE);
55749a0bf528SMauro Carvalho Chehab 	if (status < 0)
55759a0bf528SMauro Carvalho Chehab 		goto error;
55769a0bf528SMauro Carvalho Chehab 	status = write16(state, IQM_COMM_EXEC__A, IQM_COMM_EXEC_B_ACTIVE);
55779a0bf528SMauro Carvalho Chehab 	if (status < 0)
55789a0bf528SMauro Carvalho Chehab 		goto error;
55799a0bf528SMauro Carvalho Chehab 
55809a0bf528SMauro Carvalho Chehab 	/* STEP 5: start QAM demodulator (starts FEC, QAM and IQM HW) */
5581cd7a67a4SMauro Carvalho Chehab 	status = scu_command(state, SCU_RAM_COMMAND_STANDARD_QAM | SCU_RAM_COMMAND_CMD_DEMOD_START, 0, NULL, 1, &cmd_result);
55829a0bf528SMauro Carvalho Chehab 	if (status < 0)
55839a0bf528SMauro Carvalho Chehab 		goto error;
55849a0bf528SMauro Carvalho Chehab 
55859a0bf528SMauro Carvalho Chehab 	/* update global DRXK data container */
55869a0bf528SMauro Carvalho Chehab /*?     extAttr->qamInterleaveMode = DRXK_QAM_I12_J17; */
55879a0bf528SMauro Carvalho Chehab 
55889a0bf528SMauro Carvalho Chehab error:
55899a0bf528SMauro Carvalho Chehab 	if (status < 0)
55903a4398f5SMauro Carvalho Chehab 		pr_err("Error %d on %s\n", status, __func__);
55919a0bf528SMauro Carvalho Chehab 	return status;
55929a0bf528SMauro Carvalho Chehab }
55939a0bf528SMauro Carvalho Chehab 
5594cd7a67a4SMauro Carvalho Chehab static int set_qam_standard(struct drxk_state *state,
5595cd7a67a4SMauro Carvalho Chehab 			  enum operation_mode o_mode)
55969a0bf528SMauro Carvalho Chehab {
55979a0bf528SMauro Carvalho Chehab 	int status;
55989a0bf528SMauro Carvalho Chehab #ifdef DRXK_QAM_TAPS
55999a0bf528SMauro Carvalho Chehab #define DRXK_QAMA_TAPS_SELECT
56009a0bf528SMauro Carvalho Chehab #include "drxk_filters.h"
56019a0bf528SMauro Carvalho Chehab #undef DRXK_QAMA_TAPS_SELECT
56029a0bf528SMauro Carvalho Chehab #endif
56039a0bf528SMauro Carvalho Chehab 
56049a0bf528SMauro Carvalho Chehab 	dprintk(1, "\n");
56059a0bf528SMauro Carvalho Chehab 
56069a0bf528SMauro Carvalho Chehab 	/* added antenna switch */
5607cd7a67a4SMauro Carvalho Chehab 	switch_antenna_to_qam(state);
56089a0bf528SMauro Carvalho Chehab 
56099a0bf528SMauro Carvalho Chehab 	/* Ensure correct power-up mode */
5610cd7a67a4SMauro Carvalho Chehab 	status = power_up_qam(state);
56119a0bf528SMauro Carvalho Chehab 	if (status < 0)
56129a0bf528SMauro Carvalho Chehab 		goto error;
56139a0bf528SMauro Carvalho Chehab 	/* Reset QAM block */
5614cd7a67a4SMauro Carvalho Chehab 	status = qam_reset_qam(state);
56159a0bf528SMauro Carvalho Chehab 	if (status < 0)
56169a0bf528SMauro Carvalho Chehab 		goto error;
56179a0bf528SMauro Carvalho Chehab 
56189a0bf528SMauro Carvalho Chehab 	/* Setup IQM */
56199a0bf528SMauro Carvalho Chehab 
56209a0bf528SMauro Carvalho Chehab 	status = write16(state, IQM_COMM_EXEC__A, IQM_COMM_EXEC_B_STOP);
56219a0bf528SMauro Carvalho Chehab 	if (status < 0)
56229a0bf528SMauro Carvalho Chehab 		goto error;
56239a0bf528SMauro Carvalho Chehab 	status = write16(state, IQM_AF_AMUX__A, IQM_AF_AMUX_SIGNAL2ADC);
56249a0bf528SMauro Carvalho Chehab 	if (status < 0)
56259a0bf528SMauro Carvalho Chehab 		goto error;
56269a0bf528SMauro Carvalho Chehab 
56279a0bf528SMauro Carvalho Chehab 	/* Upload IQM Channel Filter settings by
56289a0bf528SMauro Carvalho Chehab 		boot loader from ROM table */
5629cd7a67a4SMauro Carvalho Chehab 	switch (o_mode) {
56309a0bf528SMauro Carvalho Chehab 	case OM_QAM_ITU_A:
5631cd7a67a4SMauro Carvalho Chehab 		status = bl_chain_cmd(state, DRXK_BL_ROM_OFFSET_TAPS_ITU_A, DRXK_BLCC_NR_ELEMENTS_TAPS, DRXK_BLC_TIMEOUT);
56329a0bf528SMauro Carvalho Chehab 		break;
56339a0bf528SMauro Carvalho Chehab 	case OM_QAM_ITU_C:
5634cd7a67a4SMauro Carvalho Chehab 		status = bl_direct_cmd(state, IQM_CF_TAP_RE0__A, DRXK_BL_ROM_OFFSET_TAPS_ITU_C, DRXK_BLDC_NR_ELEMENTS_TAPS, DRXK_BLC_TIMEOUT);
56359a0bf528SMauro Carvalho Chehab 		if (status < 0)
56369a0bf528SMauro Carvalho Chehab 			goto error;
5637cd7a67a4SMauro Carvalho Chehab 		status = bl_direct_cmd(state, IQM_CF_TAP_IM0__A, DRXK_BL_ROM_OFFSET_TAPS_ITU_C, DRXK_BLDC_NR_ELEMENTS_TAPS, DRXK_BLC_TIMEOUT);
56389a0bf528SMauro Carvalho Chehab 		break;
56399a0bf528SMauro Carvalho Chehab 	default:
56409a0bf528SMauro Carvalho Chehab 		status = -EINVAL;
56419a0bf528SMauro Carvalho Chehab 	}
56429a0bf528SMauro Carvalho Chehab 	if (status < 0)
56439a0bf528SMauro Carvalho Chehab 		goto error;
56449a0bf528SMauro Carvalho Chehab 
56459a0bf528SMauro Carvalho Chehab 	status = write16(state, IQM_CF_OUT_ENA__A, (1 << IQM_CF_OUT_ENA_QAM__B));
56469a0bf528SMauro Carvalho Chehab 	if (status < 0)
56479a0bf528SMauro Carvalho Chehab 		goto error;
56489a0bf528SMauro Carvalho Chehab 	status = write16(state, IQM_CF_SYMMETRIC__A, 0);
56499a0bf528SMauro Carvalho Chehab 	if (status < 0)
56509a0bf528SMauro Carvalho Chehab 		goto error;
56519a0bf528SMauro Carvalho Chehab 	status = write16(state, IQM_CF_MIDTAP__A, ((1 << IQM_CF_MIDTAP_RE__B) | (1 << IQM_CF_MIDTAP_IM__B)));
56529a0bf528SMauro Carvalho Chehab 	if (status < 0)
56539a0bf528SMauro Carvalho Chehab 		goto error;
56549a0bf528SMauro Carvalho Chehab 
56559a0bf528SMauro Carvalho Chehab 	status = write16(state, IQM_RC_STRETCH__A, 21);
56569a0bf528SMauro Carvalho Chehab 	if (status < 0)
56579a0bf528SMauro Carvalho Chehab 		goto error;
56589a0bf528SMauro Carvalho Chehab 	status = write16(state, IQM_AF_CLP_LEN__A, 0);
56599a0bf528SMauro Carvalho Chehab 	if (status < 0)
56609a0bf528SMauro Carvalho Chehab 		goto error;
56619a0bf528SMauro Carvalho Chehab 	status = write16(state, IQM_AF_CLP_TH__A, 448);
56629a0bf528SMauro Carvalho Chehab 	if (status < 0)
56639a0bf528SMauro Carvalho Chehab 		goto error;
56649a0bf528SMauro Carvalho Chehab 	status = write16(state, IQM_AF_SNS_LEN__A, 0);
56659a0bf528SMauro Carvalho Chehab 	if (status < 0)
56669a0bf528SMauro Carvalho Chehab 		goto error;
56679a0bf528SMauro Carvalho Chehab 	status = write16(state, IQM_CF_POW_MEAS_LEN__A, 0);
56689a0bf528SMauro Carvalho Chehab 	if (status < 0)
56699a0bf528SMauro Carvalho Chehab 		goto error;
56709a0bf528SMauro Carvalho Chehab 
56719a0bf528SMauro Carvalho Chehab 	status = write16(state, IQM_FS_ADJ_SEL__A, 1);
56729a0bf528SMauro Carvalho Chehab 	if (status < 0)
56739a0bf528SMauro Carvalho Chehab 		goto error;
56749a0bf528SMauro Carvalho Chehab 	status = write16(state, IQM_RC_ADJ_SEL__A, 1);
56759a0bf528SMauro Carvalho Chehab 	if (status < 0)
56769a0bf528SMauro Carvalho Chehab 		goto error;
56779a0bf528SMauro Carvalho Chehab 	status = write16(state, IQM_CF_ADJ_SEL__A, 1);
56789a0bf528SMauro Carvalho Chehab 	if (status < 0)
56799a0bf528SMauro Carvalho Chehab 		goto error;
56809a0bf528SMauro Carvalho Chehab 	status = write16(state, IQM_AF_UPD_SEL__A, 0);
56819a0bf528SMauro Carvalho Chehab 	if (status < 0)
56829a0bf528SMauro Carvalho Chehab 		goto error;
56839a0bf528SMauro Carvalho Chehab 
56849a0bf528SMauro Carvalho Chehab 	/* IQM Impulse Noise Processing Unit */
56859a0bf528SMauro Carvalho Chehab 	status = write16(state, IQM_CF_CLP_VAL__A, 500);
56869a0bf528SMauro Carvalho Chehab 	if (status < 0)
56879a0bf528SMauro Carvalho Chehab 		goto error;
56889a0bf528SMauro Carvalho Chehab 	status = write16(state, IQM_CF_DATATH__A, 1000);
56899a0bf528SMauro Carvalho Chehab 	if (status < 0)
56909a0bf528SMauro Carvalho Chehab 		goto error;
56919a0bf528SMauro Carvalho Chehab 	status = write16(state, IQM_CF_BYPASSDET__A, 1);
56929a0bf528SMauro Carvalho Chehab 	if (status < 0)
56939a0bf528SMauro Carvalho Chehab 		goto error;
56949a0bf528SMauro Carvalho Chehab 	status = write16(state, IQM_CF_DET_LCT__A, 0);
56959a0bf528SMauro Carvalho Chehab 	if (status < 0)
56969a0bf528SMauro Carvalho Chehab 		goto error;
56979a0bf528SMauro Carvalho Chehab 	status = write16(state, IQM_CF_WND_LEN__A, 1);
56989a0bf528SMauro Carvalho Chehab 	if (status < 0)
56999a0bf528SMauro Carvalho Chehab 		goto error;
57009a0bf528SMauro Carvalho Chehab 	status = write16(state, IQM_CF_PKDTH__A, 1);
57019a0bf528SMauro Carvalho Chehab 	if (status < 0)
57029a0bf528SMauro Carvalho Chehab 		goto error;
57039a0bf528SMauro Carvalho Chehab 	status = write16(state, IQM_AF_INC_BYPASS__A, 1);
57049a0bf528SMauro Carvalho Chehab 	if (status < 0)
57059a0bf528SMauro Carvalho Chehab 		goto error;
57069a0bf528SMauro Carvalho Chehab 
57079a0bf528SMauro Carvalho Chehab 	/* turn on IQMAF. Must be done before setAgc**() */
5708cd7a67a4SMauro Carvalho Chehab 	status = set_iqm_af(state, true);
57099a0bf528SMauro Carvalho Chehab 	if (status < 0)
57109a0bf528SMauro Carvalho Chehab 		goto error;
57119a0bf528SMauro Carvalho Chehab 	status = write16(state, IQM_AF_START_LOCK__A, 0x01);
57129a0bf528SMauro Carvalho Chehab 	if (status < 0)
57139a0bf528SMauro Carvalho Chehab 		goto error;
57149a0bf528SMauro Carvalho Chehab 
57159a0bf528SMauro Carvalho Chehab 	/* IQM will not be reset from here, sync ADC and update/init AGC */
5716cd7a67a4SMauro Carvalho Chehab 	status = adc_synchronization(state);
57179a0bf528SMauro Carvalho Chehab 	if (status < 0)
57189a0bf528SMauro Carvalho Chehab 		goto error;
57199a0bf528SMauro Carvalho Chehab 
57209a0bf528SMauro Carvalho Chehab 	/* Set the FSM step period */
57219a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_QAM_FSM_STEP_PERIOD__A, 2000);
57229a0bf528SMauro Carvalho Chehab 	if (status < 0)
57239a0bf528SMauro Carvalho Chehab 		goto error;
57249a0bf528SMauro Carvalho Chehab 
57259a0bf528SMauro Carvalho Chehab 	/* Halt SCU to enable safe non-atomic accesses */
57269a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_COMM_EXEC__A, SCU_COMM_EXEC_HOLD);
57279a0bf528SMauro Carvalho Chehab 	if (status < 0)
57289a0bf528SMauro Carvalho Chehab 		goto error;
57299a0bf528SMauro Carvalho Chehab 
57309a0bf528SMauro Carvalho Chehab 	/* No more resets of the IQM, current standard correctly set =>
57319a0bf528SMauro Carvalho Chehab 		now AGCs can be configured. */
57329a0bf528SMauro Carvalho Chehab 
5733cd7a67a4SMauro Carvalho Chehab 	status = init_agc(state, true);
57349a0bf528SMauro Carvalho Chehab 	if (status < 0)
57359a0bf528SMauro Carvalho Chehab 		goto error;
5736cd7a67a4SMauro Carvalho Chehab 	status = set_pre_saw(state, &(state->m_qam_pre_saw_cfg));
57379a0bf528SMauro Carvalho Chehab 	if (status < 0)
57389a0bf528SMauro Carvalho Chehab 		goto error;
57399a0bf528SMauro Carvalho Chehab 
57409a0bf528SMauro Carvalho Chehab 	/* Configure AGC's */
5741cd7a67a4SMauro Carvalho Chehab 	status = set_agc_rf(state, &(state->m_qam_rf_agc_cfg), true);
57429a0bf528SMauro Carvalho Chehab 	if (status < 0)
57439a0bf528SMauro Carvalho Chehab 		goto error;
5744cd7a67a4SMauro Carvalho Chehab 	status = set_agc_if(state, &(state->m_qam_if_agc_cfg), true);
57459a0bf528SMauro Carvalho Chehab 	if (status < 0)
57469a0bf528SMauro Carvalho Chehab 		goto error;
57479a0bf528SMauro Carvalho Chehab 
57489a0bf528SMauro Carvalho Chehab 	/* Activate SCU to enable SCU commands */
57499a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_COMM_EXEC__A, SCU_COMM_EXEC_ACTIVE);
57509a0bf528SMauro Carvalho Chehab error:
57519a0bf528SMauro Carvalho Chehab 	if (status < 0)
57523a4398f5SMauro Carvalho Chehab 		pr_err("Error %d on %s\n", status, __func__);
57539a0bf528SMauro Carvalho Chehab 	return status;
57549a0bf528SMauro Carvalho Chehab }
57559a0bf528SMauro Carvalho Chehab 
5756cd7a67a4SMauro Carvalho Chehab static int write_gpio(struct drxk_state *state)
57579a0bf528SMauro Carvalho Chehab {
57589a0bf528SMauro Carvalho Chehab 	int status;
57599a0bf528SMauro Carvalho Chehab 	u16 value = 0;
57609a0bf528SMauro Carvalho Chehab 
57619a0bf528SMauro Carvalho Chehab 	dprintk(1, "\n");
57629a0bf528SMauro Carvalho Chehab 	/* stop lock indicator process */
57639a0bf528SMauro Carvalho Chehab 	status = write16(state, SCU_RAM_GPIO__A, SCU_RAM_GPIO_HW_LOCK_IND_DISABLE);
57649a0bf528SMauro Carvalho Chehab 	if (status < 0)
57659a0bf528SMauro Carvalho Chehab 		goto error;
57669a0bf528SMauro Carvalho Chehab 
57679a0bf528SMauro Carvalho Chehab 	/*  Write magic word to enable pdr reg write               */
57689a0bf528SMauro Carvalho Chehab 	status = write16(state, SIO_TOP_COMM_KEY__A, SIO_TOP_COMM_KEY_KEY);
57699a0bf528SMauro Carvalho Chehab 	if (status < 0)
57709a0bf528SMauro Carvalho Chehab 		goto error;
57719a0bf528SMauro Carvalho Chehab 
5772cd7a67a4SMauro Carvalho Chehab 	if (state->m_has_sawsw) {
5773cd7a67a4SMauro Carvalho Chehab 		if (state->uio_mask & 0x0001) { /* UIO-1 */
57749a0bf528SMauro Carvalho Chehab 			/* write to io pad configuration register - output mode */
5775cd7a67a4SMauro Carvalho Chehab 			status = write16(state, SIO_PDR_SMA_TX_CFG__A, state->m_gpio_cfg);
57769a0bf528SMauro Carvalho Chehab 			if (status < 0)
57779a0bf528SMauro Carvalho Chehab 				goto error;
57789a0bf528SMauro Carvalho Chehab 
57799a0bf528SMauro Carvalho Chehab 			/* use corresponding bit in io data output registar */
57809a0bf528SMauro Carvalho Chehab 			status = read16(state, SIO_PDR_UIO_OUT_LO__A, &value);
57819a0bf528SMauro Carvalho Chehab 			if (status < 0)
57829a0bf528SMauro Carvalho Chehab 				goto error;
5783cd7a67a4SMauro Carvalho Chehab 			if ((state->m_gpio & 0x0001) == 0)
57849a0bf528SMauro Carvalho Chehab 				value &= 0x7FFF;	/* write zero to 15th bit - 1st UIO */
57859a0bf528SMauro Carvalho Chehab 			else
57869a0bf528SMauro Carvalho Chehab 				value |= 0x8000;	/* write one to 15th bit - 1st UIO */
57879a0bf528SMauro Carvalho Chehab 			/* write back to io data output register */
57889a0bf528SMauro Carvalho Chehab 			status = write16(state, SIO_PDR_UIO_OUT_LO__A, value);
57899a0bf528SMauro Carvalho Chehab 			if (status < 0)
57909a0bf528SMauro Carvalho Chehab 				goto error;
57919a0bf528SMauro Carvalho Chehab 		}
5792cd7a67a4SMauro Carvalho Chehab 		if (state->uio_mask & 0x0002) { /* UIO-2 */
57939a0bf528SMauro Carvalho Chehab 			/* write to io pad configuration register - output mode */
5794cd7a67a4SMauro Carvalho Chehab 			status = write16(state, SIO_PDR_SMA_RX_CFG__A, state->m_gpio_cfg);
57959a0bf528SMauro Carvalho Chehab 			if (status < 0)
57969a0bf528SMauro Carvalho Chehab 				goto error;
57979a0bf528SMauro Carvalho Chehab 
57989a0bf528SMauro Carvalho Chehab 			/* use corresponding bit in io data output registar */
57999a0bf528SMauro Carvalho Chehab 			status = read16(state, SIO_PDR_UIO_OUT_LO__A, &value);
58009a0bf528SMauro Carvalho Chehab 			if (status < 0)
58019a0bf528SMauro Carvalho Chehab 				goto error;
5802cd7a67a4SMauro Carvalho Chehab 			if ((state->m_gpio & 0x0002) == 0)
58039a0bf528SMauro Carvalho Chehab 				value &= 0xBFFF;	/* write zero to 14th bit - 2st UIO */
58049a0bf528SMauro Carvalho Chehab 			else
58059a0bf528SMauro Carvalho Chehab 				value |= 0x4000;	/* write one to 14th bit - 2st UIO */
58069a0bf528SMauro Carvalho Chehab 			/* write back to io data output register */
58079a0bf528SMauro Carvalho Chehab 			status = write16(state, SIO_PDR_UIO_OUT_LO__A, value);
58089a0bf528SMauro Carvalho Chehab 			if (status < 0)
58099a0bf528SMauro Carvalho Chehab 				goto error;
58109a0bf528SMauro Carvalho Chehab 		}
5811cd7a67a4SMauro Carvalho Chehab 		if (state->uio_mask & 0x0004) { /* UIO-3 */
58129a0bf528SMauro Carvalho Chehab 			/* write to io pad configuration register - output mode */
5813cd7a67a4SMauro Carvalho Chehab 			status = write16(state, SIO_PDR_GPIO_CFG__A, state->m_gpio_cfg);
58149a0bf528SMauro Carvalho Chehab 			if (status < 0)
58159a0bf528SMauro Carvalho Chehab 				goto error;
58169a0bf528SMauro Carvalho Chehab 
58179a0bf528SMauro Carvalho Chehab 			/* use corresponding bit in io data output registar */
58189a0bf528SMauro Carvalho Chehab 			status = read16(state, SIO_PDR_UIO_OUT_LO__A, &value);
58199a0bf528SMauro Carvalho Chehab 			if (status < 0)
58209a0bf528SMauro Carvalho Chehab 				goto error;
5821cd7a67a4SMauro Carvalho Chehab 			if ((state->m_gpio & 0x0004) == 0)
58229a0bf528SMauro Carvalho Chehab 				value &= 0xFFFB;            /* write zero to 2nd bit - 3rd UIO */
58239a0bf528SMauro Carvalho Chehab 			else
58249a0bf528SMauro Carvalho Chehab 				value |= 0x0004;            /* write one to 2nd bit - 3rd UIO */
58259a0bf528SMauro Carvalho Chehab 			/* write back to io data output register */
58269a0bf528SMauro Carvalho Chehab 			status = write16(state, SIO_PDR_UIO_OUT_LO__A, value);
58279a0bf528SMauro Carvalho Chehab 			if (status < 0)
58289a0bf528SMauro Carvalho Chehab 				goto error;
58299a0bf528SMauro Carvalho Chehab 		}
58309a0bf528SMauro Carvalho Chehab 	}
58319a0bf528SMauro Carvalho Chehab 	/*  Write magic word to disable pdr reg write               */
58329a0bf528SMauro Carvalho Chehab 	status = write16(state, SIO_TOP_COMM_KEY__A, 0x0000);
58339a0bf528SMauro Carvalho Chehab error:
58349a0bf528SMauro Carvalho Chehab 	if (status < 0)
58353a4398f5SMauro Carvalho Chehab 		pr_err("Error %d on %s\n", status, __func__);
58369a0bf528SMauro Carvalho Chehab 	return status;
58379a0bf528SMauro Carvalho Chehab }
58389a0bf528SMauro Carvalho Chehab 
5839cd7a67a4SMauro Carvalho Chehab static int switch_antenna_to_qam(struct drxk_state *state)
58409a0bf528SMauro Carvalho Chehab {
58419a0bf528SMauro Carvalho Chehab 	int status = 0;
58429a0bf528SMauro Carvalho Chehab 	bool gpio_state;
58439a0bf528SMauro Carvalho Chehab 
58449a0bf528SMauro Carvalho Chehab 	dprintk(1, "\n");
58459a0bf528SMauro Carvalho Chehab 
58469a0bf528SMauro Carvalho Chehab 	if (!state->antenna_gpio)
58479a0bf528SMauro Carvalho Chehab 		return 0;
58489a0bf528SMauro Carvalho Chehab 
5849cd7a67a4SMauro Carvalho Chehab 	gpio_state = state->m_gpio & state->antenna_gpio;
58509a0bf528SMauro Carvalho Chehab 
58519a0bf528SMauro Carvalho Chehab 	if (state->antenna_dvbt ^ gpio_state) {
58529a0bf528SMauro Carvalho Chehab 		/* Antenna is on DVB-T mode. Switch */
58539a0bf528SMauro Carvalho Chehab 		if (state->antenna_dvbt)
5854cd7a67a4SMauro Carvalho Chehab 			state->m_gpio &= ~state->antenna_gpio;
58559a0bf528SMauro Carvalho Chehab 		else
5856cd7a67a4SMauro Carvalho Chehab 			state->m_gpio |= state->antenna_gpio;
5857cd7a67a4SMauro Carvalho Chehab 		status = write_gpio(state);
58589a0bf528SMauro Carvalho Chehab 	}
58599a0bf528SMauro Carvalho Chehab 	if (status < 0)
58603a4398f5SMauro Carvalho Chehab 		pr_err("Error %d on %s\n", status, __func__);
58619a0bf528SMauro Carvalho Chehab 	return status;
58629a0bf528SMauro Carvalho Chehab }
58639a0bf528SMauro Carvalho Chehab 
5864cd7a67a4SMauro Carvalho Chehab static int switch_antenna_to_dvbt(struct drxk_state *state)
58659a0bf528SMauro Carvalho Chehab {
58669a0bf528SMauro Carvalho Chehab 	int status = 0;
58679a0bf528SMauro Carvalho Chehab 	bool gpio_state;
58689a0bf528SMauro Carvalho Chehab 
58699a0bf528SMauro Carvalho Chehab 	dprintk(1, "\n");
58709a0bf528SMauro Carvalho Chehab 
58719a0bf528SMauro Carvalho Chehab 	if (!state->antenna_gpio)
58729a0bf528SMauro Carvalho Chehab 		return 0;
58739a0bf528SMauro Carvalho Chehab 
5874cd7a67a4SMauro Carvalho Chehab 	gpio_state = state->m_gpio & state->antenna_gpio;
58759a0bf528SMauro Carvalho Chehab 
58769a0bf528SMauro Carvalho Chehab 	if (!(state->antenna_dvbt ^ gpio_state)) {
58779a0bf528SMauro Carvalho Chehab 		/* Antenna is on DVB-C mode. Switch */
58789a0bf528SMauro Carvalho Chehab 		if (state->antenna_dvbt)
5879cd7a67a4SMauro Carvalho Chehab 			state->m_gpio |= state->antenna_gpio;
58809a0bf528SMauro Carvalho Chehab 		else
5881cd7a67a4SMauro Carvalho Chehab 			state->m_gpio &= ~state->antenna_gpio;
5882cd7a67a4SMauro Carvalho Chehab 		status = write_gpio(state);
58839a0bf528SMauro Carvalho Chehab 	}
58849a0bf528SMauro Carvalho Chehab 	if (status < 0)
58853a4398f5SMauro Carvalho Chehab 		pr_err("Error %d on %s\n", status, __func__);
58869a0bf528SMauro Carvalho Chehab 	return status;
58879a0bf528SMauro Carvalho Chehab }
58889a0bf528SMauro Carvalho Chehab 
58899a0bf528SMauro Carvalho Chehab 
5890cd7a67a4SMauro Carvalho Chehab static int power_down_device(struct drxk_state *state)
58919a0bf528SMauro Carvalho Chehab {
58929a0bf528SMauro Carvalho Chehab 	/* Power down to requested mode */
58939a0bf528SMauro Carvalho Chehab 	/* Backup some register settings */
58949a0bf528SMauro Carvalho Chehab 	/* Set pins with possible pull-ups connected to them in input mode */
58959a0bf528SMauro Carvalho Chehab 	/* Analog power down */
58969a0bf528SMauro Carvalho Chehab 	/* ADC power down */
58979a0bf528SMauro Carvalho Chehab 	/* Power down device */
58989a0bf528SMauro Carvalho Chehab 	int status;
58999a0bf528SMauro Carvalho Chehab 
59009a0bf528SMauro Carvalho Chehab 	dprintk(1, "\n");
5901cd7a67a4SMauro Carvalho Chehab 	if (state->m_b_p_down_open_bridge) {
59029a0bf528SMauro Carvalho Chehab 		/* Open I2C bridge before power down of DRXK */
59039a0bf528SMauro Carvalho Chehab 		status = ConfigureI2CBridge(state, true);
59049a0bf528SMauro Carvalho Chehab 		if (status < 0)
59059a0bf528SMauro Carvalho Chehab 			goto error;
59069a0bf528SMauro Carvalho Chehab 	}
59079a0bf528SMauro Carvalho Chehab 	/* driver 0.9.0 */
5908cd7a67a4SMauro Carvalho Chehab 	status = dvbt_enable_ofdm_token_ring(state, false);
59099a0bf528SMauro Carvalho Chehab 	if (status < 0)
59109a0bf528SMauro Carvalho Chehab 		goto error;
59119a0bf528SMauro Carvalho Chehab 
59129a0bf528SMauro Carvalho Chehab 	status = write16(state, SIO_CC_PWD_MODE__A, SIO_CC_PWD_MODE_LEVEL_CLOCK);
59139a0bf528SMauro Carvalho Chehab 	if (status < 0)
59149a0bf528SMauro Carvalho Chehab 		goto error;
59159a0bf528SMauro Carvalho Chehab 	status = write16(state, SIO_CC_UPDATE__A, SIO_CC_UPDATE_KEY);
59169a0bf528SMauro Carvalho Chehab 	if (status < 0)
59179a0bf528SMauro Carvalho Chehab 		goto error;
5918cd7a67a4SMauro Carvalho Chehab 	state->m_hi_cfg_ctrl |= SIO_HI_RA_RAM_PAR_5_CFG_SLEEP_ZZZ;
5919cd7a67a4SMauro Carvalho Chehab 	status = hi_cfg_command(state);
59209a0bf528SMauro Carvalho Chehab error:
59219a0bf528SMauro Carvalho Chehab 	if (status < 0)
59223a4398f5SMauro Carvalho Chehab 		pr_err("Error %d on %s\n", status, __func__);
59239a0bf528SMauro Carvalho Chehab 
59249a0bf528SMauro Carvalho Chehab 	return status;
59259a0bf528SMauro Carvalho Chehab }
59269a0bf528SMauro Carvalho Chehab 
59279a0bf528SMauro Carvalho Chehab static int init_drxk(struct drxk_state *state)
59289a0bf528SMauro Carvalho Chehab {
59299a0bf528SMauro Carvalho Chehab 	int status = 0, n = 0;
5930cd7a67a4SMauro Carvalho Chehab 	enum drx_power_mode power_mode = DRXK_POWER_DOWN_OFDM;
5931cd7a67a4SMauro Carvalho Chehab 	u16 driver_version;
59329a0bf528SMauro Carvalho Chehab 
59339a0bf528SMauro Carvalho Chehab 	dprintk(1, "\n");
5934cd7a67a4SMauro Carvalho Chehab 	if ((state->m_drxk_state == DRXK_UNINITIALIZED)) {
59359a0bf528SMauro Carvalho Chehab 		drxk_i2c_lock(state);
5936cd7a67a4SMauro Carvalho Chehab 		status = power_up_device(state);
59379a0bf528SMauro Carvalho Chehab 		if (status < 0)
59389a0bf528SMauro Carvalho Chehab 			goto error;
5939cd7a67a4SMauro Carvalho Chehab 		status = drxx_open(state);
59409a0bf528SMauro Carvalho Chehab 		if (status < 0)
59419a0bf528SMauro Carvalho Chehab 			goto error;
59429a0bf528SMauro Carvalho Chehab 		/* Soft reset of OFDM-, sys- and osc-clockdomain */
59439a0bf528SMauro Carvalho Chehab 		status = write16(state, SIO_CC_SOFT_RST__A, SIO_CC_SOFT_RST_OFDM__M | SIO_CC_SOFT_RST_SYS__M | SIO_CC_SOFT_RST_OSC__M);
59449a0bf528SMauro Carvalho Chehab 		if (status < 0)
59459a0bf528SMauro Carvalho Chehab 			goto error;
59469a0bf528SMauro Carvalho Chehab 		status = write16(state, SIO_CC_UPDATE__A, SIO_CC_UPDATE_KEY);
59479a0bf528SMauro Carvalho Chehab 		if (status < 0)
59489a0bf528SMauro Carvalho Chehab 			goto error;
59499a0bf528SMauro Carvalho Chehab 		/* TODO is this needed, if yes how much delay in worst case scenario */
59509a0bf528SMauro Carvalho Chehab 		msleep(1);
5951cd7a67a4SMauro Carvalho Chehab 		state->m_drxk_a3_patch_code = true;
5952cd7a67a4SMauro Carvalho Chehab 		status = get_device_capabilities(state);
59539a0bf528SMauro Carvalho Chehab 		if (status < 0)
59549a0bf528SMauro Carvalho Chehab 			goto error;
59559a0bf528SMauro Carvalho Chehab 
59569a0bf528SMauro Carvalho Chehab 		/* Bridge delay, uses oscilator clock */
59579a0bf528SMauro Carvalho Chehab 		/* Delay = (delay (nano seconds) * oscclk (kHz))/ 1000 */
59589a0bf528SMauro Carvalho Chehab 		/* SDA brdige delay */
5959cd7a67a4SMauro Carvalho Chehab 		state->m_hi_cfg_bridge_delay =
5960cd7a67a4SMauro Carvalho Chehab 			(u16) ((state->m_osc_clock_freq / 1000) *
59619a0bf528SMauro Carvalho Chehab 				HI_I2C_BRIDGE_DELAY) / 1000;
59629a0bf528SMauro Carvalho Chehab 		/* Clipping */
5963cd7a67a4SMauro Carvalho Chehab 		if (state->m_hi_cfg_bridge_delay >
59649a0bf528SMauro Carvalho Chehab 			SIO_HI_RA_RAM_PAR_3_CFG_DBL_SDA__M) {
5965cd7a67a4SMauro Carvalho Chehab 			state->m_hi_cfg_bridge_delay =
59669a0bf528SMauro Carvalho Chehab 				SIO_HI_RA_RAM_PAR_3_CFG_DBL_SDA__M;
59679a0bf528SMauro Carvalho Chehab 		}
59689a0bf528SMauro Carvalho Chehab 		/* SCL bridge delay, same as SDA for now */
5969cd7a67a4SMauro Carvalho Chehab 		state->m_hi_cfg_bridge_delay +=
5970cd7a67a4SMauro Carvalho Chehab 			state->m_hi_cfg_bridge_delay <<
59719a0bf528SMauro Carvalho Chehab 			SIO_HI_RA_RAM_PAR_3_CFG_DBL_SCL__B;
59729a0bf528SMauro Carvalho Chehab 
5973cd7a67a4SMauro Carvalho Chehab 		status = init_hi(state);
59749a0bf528SMauro Carvalho Chehab 		if (status < 0)
59759a0bf528SMauro Carvalho Chehab 			goto error;
59769a0bf528SMauro Carvalho Chehab 		/* disable various processes */
59779a0bf528SMauro Carvalho Chehab #if NOA1ROM
59789a0bf528SMauro Carvalho Chehab 		if (!(state->m_DRXK_A1_ROM_CODE)
59799a0bf528SMauro Carvalho Chehab 			&& !(state->m_DRXK_A2_ROM_CODE))
59809a0bf528SMauro Carvalho Chehab #endif
59819a0bf528SMauro Carvalho Chehab 		{
59829a0bf528SMauro Carvalho Chehab 			status = write16(state, SCU_RAM_GPIO__A, SCU_RAM_GPIO_HW_LOCK_IND_DISABLE);
59839a0bf528SMauro Carvalho Chehab 			if (status < 0)
59849a0bf528SMauro Carvalho Chehab 				goto error;
59859a0bf528SMauro Carvalho Chehab 		}
59869a0bf528SMauro Carvalho Chehab 
59879a0bf528SMauro Carvalho Chehab 		/* disable MPEG port */
5988cd7a67a4SMauro Carvalho Chehab 		status = mpegts_disable(state);
59899a0bf528SMauro Carvalho Chehab 		if (status < 0)
59909a0bf528SMauro Carvalho Chehab 			goto error;
59919a0bf528SMauro Carvalho Chehab 
59929a0bf528SMauro Carvalho Chehab 		/* Stop AUD and SCU */
59939a0bf528SMauro Carvalho Chehab 		status = write16(state, AUD_COMM_EXEC__A, AUD_COMM_EXEC_STOP);
59949a0bf528SMauro Carvalho Chehab 		if (status < 0)
59959a0bf528SMauro Carvalho Chehab 			goto error;
59969a0bf528SMauro Carvalho Chehab 		status = write16(state, SCU_COMM_EXEC__A, SCU_COMM_EXEC_STOP);
59979a0bf528SMauro Carvalho Chehab 		if (status < 0)
59989a0bf528SMauro Carvalho Chehab 			goto error;
59999a0bf528SMauro Carvalho Chehab 
60009a0bf528SMauro Carvalho Chehab 		/* enable token-ring bus through OFDM block for possible ucode upload */
60019a0bf528SMauro Carvalho Chehab 		status = write16(state, SIO_OFDM_SH_OFDM_RING_ENABLE__A, SIO_OFDM_SH_OFDM_RING_ENABLE_ON);
60029a0bf528SMauro Carvalho Chehab 		if (status < 0)
60039a0bf528SMauro Carvalho Chehab 			goto error;
60049a0bf528SMauro Carvalho Chehab 
60059a0bf528SMauro Carvalho Chehab 		/* include boot loader section */
60069a0bf528SMauro Carvalho Chehab 		status = write16(state, SIO_BL_COMM_EXEC__A, SIO_BL_COMM_EXEC_ACTIVE);
60079a0bf528SMauro Carvalho Chehab 		if (status < 0)
60089a0bf528SMauro Carvalho Chehab 			goto error;
6009cd7a67a4SMauro Carvalho Chehab 		status = bl_chain_cmd(state, 0, 6, 100);
60109a0bf528SMauro Carvalho Chehab 		if (status < 0)
60119a0bf528SMauro Carvalho Chehab 			goto error;
60129a0bf528SMauro Carvalho Chehab 
60139a0bf528SMauro Carvalho Chehab 		if (state->fw) {
6014cd7a67a4SMauro Carvalho Chehab 			status = download_microcode(state, state->fw->data,
60159a0bf528SMauro Carvalho Chehab 						   state->fw->size);
60169a0bf528SMauro Carvalho Chehab 			if (status < 0)
60179a0bf528SMauro Carvalho Chehab 				goto error;
60189a0bf528SMauro Carvalho Chehab 		}
60199a0bf528SMauro Carvalho Chehab 
60209a0bf528SMauro Carvalho Chehab 		/* disable token-ring bus through OFDM block for possible ucode upload */
60219a0bf528SMauro Carvalho Chehab 		status = write16(state, SIO_OFDM_SH_OFDM_RING_ENABLE__A, SIO_OFDM_SH_OFDM_RING_ENABLE_OFF);
60229a0bf528SMauro Carvalho Chehab 		if (status < 0)
60239a0bf528SMauro Carvalho Chehab 			goto error;
60249a0bf528SMauro Carvalho Chehab 
60259a0bf528SMauro Carvalho Chehab 		/* Run SCU for a little while to initialize microcode version numbers */
60269a0bf528SMauro Carvalho Chehab 		status = write16(state, SCU_COMM_EXEC__A, SCU_COMM_EXEC_ACTIVE);
60279a0bf528SMauro Carvalho Chehab 		if (status < 0)
60289a0bf528SMauro Carvalho Chehab 			goto error;
6029cd7a67a4SMauro Carvalho Chehab 		status = drxx_open(state);
60309a0bf528SMauro Carvalho Chehab 		if (status < 0)
60319a0bf528SMauro Carvalho Chehab 			goto error;
60329a0bf528SMauro Carvalho Chehab 		/* added for test */
60339a0bf528SMauro Carvalho Chehab 		msleep(30);
60349a0bf528SMauro Carvalho Chehab 
6035cd7a67a4SMauro Carvalho Chehab 		power_mode = DRXK_POWER_DOWN_OFDM;
6036cd7a67a4SMauro Carvalho Chehab 		status = ctrl_power_mode(state, &power_mode);
60379a0bf528SMauro Carvalho Chehab 		if (status < 0)
60389a0bf528SMauro Carvalho Chehab 			goto error;
60399a0bf528SMauro Carvalho Chehab 
60409a0bf528SMauro Carvalho Chehab 		/* Stamp driver version number in SCU data RAM in BCD code
60419a0bf528SMauro Carvalho Chehab 			Done to enable field application engineers to retreive drxdriver version
60429a0bf528SMauro Carvalho Chehab 			via I2C from SCU RAM.
60439a0bf528SMauro Carvalho Chehab 			Not using SCU command interface for SCU register access since no
60449a0bf528SMauro Carvalho Chehab 			microcode may be present.
60459a0bf528SMauro Carvalho Chehab 			*/
6046cd7a67a4SMauro Carvalho Chehab 		driver_version =
60479a0bf528SMauro Carvalho Chehab 			(((DRXK_VERSION_MAJOR / 100) % 10) << 12) +
60489a0bf528SMauro Carvalho Chehab 			(((DRXK_VERSION_MAJOR / 10) % 10) << 8) +
60499a0bf528SMauro Carvalho Chehab 			((DRXK_VERSION_MAJOR % 10) << 4) +
60509a0bf528SMauro Carvalho Chehab 			(DRXK_VERSION_MINOR % 10);
6051cd7a67a4SMauro Carvalho Chehab 		status = write16(state, SCU_RAM_DRIVER_VER_HI__A, driver_version);
60529a0bf528SMauro Carvalho Chehab 		if (status < 0)
60539a0bf528SMauro Carvalho Chehab 			goto error;
6054cd7a67a4SMauro Carvalho Chehab 		driver_version =
60559a0bf528SMauro Carvalho Chehab 			(((DRXK_VERSION_PATCH / 1000) % 10) << 12) +
60569a0bf528SMauro Carvalho Chehab 			(((DRXK_VERSION_PATCH / 100) % 10) << 8) +
60579a0bf528SMauro Carvalho Chehab 			(((DRXK_VERSION_PATCH / 10) % 10) << 4) +
60589a0bf528SMauro Carvalho Chehab 			(DRXK_VERSION_PATCH % 10);
6059cd7a67a4SMauro Carvalho Chehab 		status = write16(state, SCU_RAM_DRIVER_VER_LO__A, driver_version);
60609a0bf528SMauro Carvalho Chehab 		if (status < 0)
60619a0bf528SMauro Carvalho Chehab 			goto error;
60629a0bf528SMauro Carvalho Chehab 
60633a4398f5SMauro Carvalho Chehab 		pr_info("DRXK driver version %d.%d.%d\n",
60649a0bf528SMauro Carvalho Chehab 			DRXK_VERSION_MAJOR, DRXK_VERSION_MINOR,
60659a0bf528SMauro Carvalho Chehab 			DRXK_VERSION_PATCH);
60669a0bf528SMauro Carvalho Chehab 
60679a0bf528SMauro Carvalho Chehab 		/* Dirty fix of default values for ROM/PATCH microcode
60689a0bf528SMauro Carvalho Chehab 			Dirty because this fix makes it impossible to setup suitable values
60699a0bf528SMauro Carvalho Chehab 			before calling DRX_Open. This solution requires changes to RF AGC speed
60709a0bf528SMauro Carvalho Chehab 			to be done via the CTRL function after calling DRX_Open */
60719a0bf528SMauro Carvalho Chehab 
6072cd7a67a4SMauro Carvalho Chehab 		/* m_dvbt_rf_agc_cfg.speed = 3; */
60739a0bf528SMauro Carvalho Chehab 
60749a0bf528SMauro Carvalho Chehab 		/* Reset driver debug flags to 0 */
60759a0bf528SMauro Carvalho Chehab 		status = write16(state, SCU_RAM_DRIVER_DEBUG__A, 0);
60769a0bf528SMauro Carvalho Chehab 		if (status < 0)
60779a0bf528SMauro Carvalho Chehab 			goto error;
60789a0bf528SMauro Carvalho Chehab 		/* driver 0.9.0 */
60799a0bf528SMauro Carvalho Chehab 		/* Setup FEC OC:
60809a0bf528SMauro Carvalho Chehab 			NOTE: No more full FEC resets allowed afterwards!! */
60819a0bf528SMauro Carvalho Chehab 		status = write16(state, FEC_COMM_EXEC__A, FEC_COMM_EXEC_STOP);
60829a0bf528SMauro Carvalho Chehab 		if (status < 0)
60839a0bf528SMauro Carvalho Chehab 			goto error;
60849a0bf528SMauro Carvalho Chehab 		/* MPEGTS functions are still the same */
6085cd7a67a4SMauro Carvalho Chehab 		status = mpegts_dto_init(state);
60869a0bf528SMauro Carvalho Chehab 		if (status < 0)
60879a0bf528SMauro Carvalho Chehab 			goto error;
6088cd7a67a4SMauro Carvalho Chehab 		status = mpegts_stop(state);
60899a0bf528SMauro Carvalho Chehab 		if (status < 0)
60909a0bf528SMauro Carvalho Chehab 			goto error;
6091cd7a67a4SMauro Carvalho Chehab 		status = mpegts_configure_polarity(state);
60929a0bf528SMauro Carvalho Chehab 		if (status < 0)
60939a0bf528SMauro Carvalho Chehab 			goto error;
6094cd7a67a4SMauro Carvalho Chehab 		status = mpegts_configure_pins(state, state->m_enable_mpeg_output);
60959a0bf528SMauro Carvalho Chehab 		if (status < 0)
60969a0bf528SMauro Carvalho Chehab 			goto error;
60979a0bf528SMauro Carvalho Chehab 		/* added: configure GPIO */
6098cd7a67a4SMauro Carvalho Chehab 		status = write_gpio(state);
60999a0bf528SMauro Carvalho Chehab 		if (status < 0)
61009a0bf528SMauro Carvalho Chehab 			goto error;
61019a0bf528SMauro Carvalho Chehab 
6102cd7a67a4SMauro Carvalho Chehab 		state->m_drxk_state = DRXK_STOPPED;
61039a0bf528SMauro Carvalho Chehab 
6104cd7a67a4SMauro Carvalho Chehab 		if (state->m_b_power_down) {
6105cd7a67a4SMauro Carvalho Chehab 			status = power_down_device(state);
61069a0bf528SMauro Carvalho Chehab 			if (status < 0)
61079a0bf528SMauro Carvalho Chehab 				goto error;
6108cd7a67a4SMauro Carvalho Chehab 			state->m_drxk_state = DRXK_POWERED_DOWN;
61099a0bf528SMauro Carvalho Chehab 		} else
6110cd7a67a4SMauro Carvalho Chehab 			state->m_drxk_state = DRXK_STOPPED;
61119a0bf528SMauro Carvalho Chehab 
61129a0bf528SMauro Carvalho Chehab 		/* Initialize the supported delivery systems */
61139a0bf528SMauro Carvalho Chehab 		n = 0;
6114cd7a67a4SMauro Carvalho Chehab 		if (state->m_has_dvbc) {
61159a0bf528SMauro Carvalho Chehab 			state->frontend.ops.delsys[n++] = SYS_DVBC_ANNEX_A;
61169a0bf528SMauro Carvalho Chehab 			state->frontend.ops.delsys[n++] = SYS_DVBC_ANNEX_C;
61179a0bf528SMauro Carvalho Chehab 			strlcat(state->frontend.ops.info.name, " DVB-C",
61189a0bf528SMauro Carvalho Chehab 				sizeof(state->frontend.ops.info.name));
61199a0bf528SMauro Carvalho Chehab 		}
6120cd7a67a4SMauro Carvalho Chehab 		if (state->m_has_dvbt) {
61219a0bf528SMauro Carvalho Chehab 			state->frontend.ops.delsys[n++] = SYS_DVBT;
61229a0bf528SMauro Carvalho Chehab 			strlcat(state->frontend.ops.info.name, " DVB-T",
61239a0bf528SMauro Carvalho Chehab 				sizeof(state->frontend.ops.info.name));
61249a0bf528SMauro Carvalho Chehab 		}
61259a0bf528SMauro Carvalho Chehab 		drxk_i2c_unlock(state);
61269a0bf528SMauro Carvalho Chehab 	}
61279a0bf528SMauro Carvalho Chehab error:
61289a0bf528SMauro Carvalho Chehab 	if (status < 0) {
6129cd7a67a4SMauro Carvalho Chehab 		state->m_drxk_state = DRXK_NO_DEV;
61309a0bf528SMauro Carvalho Chehab 		drxk_i2c_unlock(state);
61313a4398f5SMauro Carvalho Chehab 		pr_err("Error %d on %s\n", status, __func__);
61329a0bf528SMauro Carvalho Chehab 	}
61339a0bf528SMauro Carvalho Chehab 
61349a0bf528SMauro Carvalho Chehab 	return status;
61359a0bf528SMauro Carvalho Chehab }
61369a0bf528SMauro Carvalho Chehab 
61379a0bf528SMauro Carvalho Chehab static void load_firmware_cb(const struct firmware *fw,
61389a0bf528SMauro Carvalho Chehab 			     void *context)
61399a0bf528SMauro Carvalho Chehab {
61409a0bf528SMauro Carvalho Chehab 	struct drxk_state *state = context;
61419a0bf528SMauro Carvalho Chehab 
61429a0bf528SMauro Carvalho Chehab 	dprintk(1, ": %s\n", fw ? "firmware loaded" : "firmware not loaded");
61439a0bf528SMauro Carvalho Chehab 	if (!fw) {
61443a4398f5SMauro Carvalho Chehab 		pr_err("Could not load firmware file %s.\n",
61459a0bf528SMauro Carvalho Chehab 			state->microcode_name);
61463a4398f5SMauro Carvalho Chehab 		pr_info("Copy %s to your hotplug directory!\n",
61479a0bf528SMauro Carvalho Chehab 			state->microcode_name);
61489a0bf528SMauro Carvalho Chehab 		state->microcode_name = NULL;
61499a0bf528SMauro Carvalho Chehab 
61509a0bf528SMauro Carvalho Chehab 		/*
61519a0bf528SMauro Carvalho Chehab 		 * As firmware is now load asynchronous, it is not possible
61529a0bf528SMauro Carvalho Chehab 		 * anymore to fail at frontend attach. We might silently
61539a0bf528SMauro Carvalho Chehab 		 * return here, and hope that the driver won't crash.
61549a0bf528SMauro Carvalho Chehab 		 * We might also change all DVB callbacks to return -ENODEV
61559a0bf528SMauro Carvalho Chehab 		 * if the device is not initialized.
61569a0bf528SMauro Carvalho Chehab 		 * As the DRX-K devices have their own internal firmware,
61579a0bf528SMauro Carvalho Chehab 		 * let's just hope that it will match a firmware revision
61589a0bf528SMauro Carvalho Chehab 		 * compatible with this driver and proceed.
61599a0bf528SMauro Carvalho Chehab 		 */
61609a0bf528SMauro Carvalho Chehab 	}
61619a0bf528SMauro Carvalho Chehab 	state->fw = fw;
61629a0bf528SMauro Carvalho Chehab 
61639a0bf528SMauro Carvalho Chehab 	init_drxk(state);
61649a0bf528SMauro Carvalho Chehab }
61659a0bf528SMauro Carvalho Chehab 
61669a0bf528SMauro Carvalho Chehab static void drxk_release(struct dvb_frontend *fe)
61679a0bf528SMauro Carvalho Chehab {
61689a0bf528SMauro Carvalho Chehab 	struct drxk_state *state = fe->demodulator_priv;
61699a0bf528SMauro Carvalho Chehab 
61709a0bf528SMauro Carvalho Chehab 	dprintk(1, "\n");
61719a0bf528SMauro Carvalho Chehab 	if (state->fw)
61729a0bf528SMauro Carvalho Chehab 		release_firmware(state->fw);
61739a0bf528SMauro Carvalho Chehab 
61749a0bf528SMauro Carvalho Chehab 	kfree(state);
61759a0bf528SMauro Carvalho Chehab }
61769a0bf528SMauro Carvalho Chehab 
61779a0bf528SMauro Carvalho Chehab static int drxk_sleep(struct dvb_frontend *fe)
61789a0bf528SMauro Carvalho Chehab {
61799a0bf528SMauro Carvalho Chehab 	struct drxk_state *state = fe->demodulator_priv;
61809a0bf528SMauro Carvalho Chehab 
61819a0bf528SMauro Carvalho Chehab 	dprintk(1, "\n");
61829a0bf528SMauro Carvalho Chehab 
6183cd7a67a4SMauro Carvalho Chehab 	if (state->m_drxk_state == DRXK_NO_DEV)
61849a0bf528SMauro Carvalho Chehab 		return -ENODEV;
6185cd7a67a4SMauro Carvalho Chehab 	if (state->m_drxk_state == DRXK_UNINITIALIZED)
61869a0bf528SMauro Carvalho Chehab 		return 0;
61879a0bf528SMauro Carvalho Chehab 
6188cd7a67a4SMauro Carvalho Chehab 	shut_down(state);
61899a0bf528SMauro Carvalho Chehab 	return 0;
61909a0bf528SMauro Carvalho Chehab }
61919a0bf528SMauro Carvalho Chehab 
61929a0bf528SMauro Carvalho Chehab static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable)
61939a0bf528SMauro Carvalho Chehab {
61949a0bf528SMauro Carvalho Chehab 	struct drxk_state *state = fe->demodulator_priv;
61959a0bf528SMauro Carvalho Chehab 
61969a0bf528SMauro Carvalho Chehab 	dprintk(1, ": %s\n", enable ? "enable" : "disable");
61979a0bf528SMauro Carvalho Chehab 
6198cd7a67a4SMauro Carvalho Chehab 	if (state->m_drxk_state == DRXK_NO_DEV)
61999a0bf528SMauro Carvalho Chehab 		return -ENODEV;
62009a0bf528SMauro Carvalho Chehab 
62019a0bf528SMauro Carvalho Chehab 	return ConfigureI2CBridge(state, enable ? true : false);
62029a0bf528SMauro Carvalho Chehab }
62039a0bf528SMauro Carvalho Chehab 
62049a0bf528SMauro Carvalho Chehab static int drxk_set_parameters(struct dvb_frontend *fe)
62059a0bf528SMauro Carvalho Chehab {
62069a0bf528SMauro Carvalho Chehab 	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
62079a0bf528SMauro Carvalho Chehab 	u32 delsys  = p->delivery_system, old_delsys;
62089a0bf528SMauro Carvalho Chehab 	struct drxk_state *state = fe->demodulator_priv;
62099a0bf528SMauro Carvalho Chehab 	u32 IF;
62109a0bf528SMauro Carvalho Chehab 
62119a0bf528SMauro Carvalho Chehab 	dprintk(1, "\n");
62129a0bf528SMauro Carvalho Chehab 
6213cd7a67a4SMauro Carvalho Chehab 	if (state->m_drxk_state == DRXK_NO_DEV)
62149a0bf528SMauro Carvalho Chehab 		return -ENODEV;
62159a0bf528SMauro Carvalho Chehab 
6216cd7a67a4SMauro Carvalho Chehab 	if (state->m_drxk_state == DRXK_UNINITIALIZED)
62179a0bf528SMauro Carvalho Chehab 		return -EAGAIN;
62189a0bf528SMauro Carvalho Chehab 
62199a0bf528SMauro Carvalho Chehab 	if (!fe->ops.tuner_ops.get_if_frequency) {
62203a4398f5SMauro Carvalho Chehab 		pr_err("Error: get_if_frequency() not defined at tuner. Can't work without it!\n");
62219a0bf528SMauro Carvalho Chehab 		return -EINVAL;
62229a0bf528SMauro Carvalho Chehab 	}
62239a0bf528SMauro Carvalho Chehab 
62249a0bf528SMauro Carvalho Chehab 	if (fe->ops.i2c_gate_ctrl)
62259a0bf528SMauro Carvalho Chehab 		fe->ops.i2c_gate_ctrl(fe, 1);
62269a0bf528SMauro Carvalho Chehab 	if (fe->ops.tuner_ops.set_params)
62279a0bf528SMauro Carvalho Chehab 		fe->ops.tuner_ops.set_params(fe);
62289a0bf528SMauro Carvalho Chehab 	if (fe->ops.i2c_gate_ctrl)
62299a0bf528SMauro Carvalho Chehab 		fe->ops.i2c_gate_ctrl(fe, 0);
62309a0bf528SMauro Carvalho Chehab 
62319a0bf528SMauro Carvalho Chehab 	old_delsys = state->props.delivery_system;
62329a0bf528SMauro Carvalho Chehab 	state->props = *p;
62339a0bf528SMauro Carvalho Chehab 
62349a0bf528SMauro Carvalho Chehab 	if (old_delsys != delsys) {
6235cd7a67a4SMauro Carvalho Chehab 		shut_down(state);
62369a0bf528SMauro Carvalho Chehab 		switch (delsys) {
62379a0bf528SMauro Carvalho Chehab 		case SYS_DVBC_ANNEX_A:
62389a0bf528SMauro Carvalho Chehab 		case SYS_DVBC_ANNEX_C:
6239cd7a67a4SMauro Carvalho Chehab 			if (!state->m_has_dvbc)
62409a0bf528SMauro Carvalho Chehab 				return -EINVAL;
62419a0bf528SMauro Carvalho Chehab 			state->m_itut_annex_c = (delsys == SYS_DVBC_ANNEX_C) ? true : false;
62429a0bf528SMauro Carvalho Chehab 			if (state->m_itut_annex_c)
6243cd7a67a4SMauro Carvalho Chehab 				setoperation_mode(state, OM_QAM_ITU_C);
62449a0bf528SMauro Carvalho Chehab 			else
6245cd7a67a4SMauro Carvalho Chehab 				setoperation_mode(state, OM_QAM_ITU_A);
62469a0bf528SMauro Carvalho Chehab 			break;
62479a0bf528SMauro Carvalho Chehab 		case SYS_DVBT:
6248cd7a67a4SMauro Carvalho Chehab 			if (!state->m_has_dvbt)
62499a0bf528SMauro Carvalho Chehab 				return -EINVAL;
6250cd7a67a4SMauro Carvalho Chehab 			setoperation_mode(state, OM_DVBT);
62519a0bf528SMauro Carvalho Chehab 			break;
62529a0bf528SMauro Carvalho Chehab 		default:
62539a0bf528SMauro Carvalho Chehab 			return -EINVAL;
62549a0bf528SMauro Carvalho Chehab 		}
62559a0bf528SMauro Carvalho Chehab 	}
62569a0bf528SMauro Carvalho Chehab 
62579a0bf528SMauro Carvalho Chehab 	fe->ops.tuner_ops.get_if_frequency(fe, &IF);
6258cd7a67a4SMauro Carvalho Chehab 	start(state, 0, IF);
62599a0bf528SMauro Carvalho Chehab 
62608f3741e0SMauro Carvalho Chehab 	/* After set_frontend, stats aren't avaliable */
62618f3741e0SMauro Carvalho Chehab 	p->strength.stat[0].scale = FE_SCALE_RELATIVE;
62628f3741e0SMauro Carvalho Chehab 	p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
62638f3741e0SMauro Carvalho Chehab 	p->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
62648f3741e0SMauro Carvalho Chehab 	p->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
62658f3741e0SMauro Carvalho Chehab 	p->pre_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
62668f3741e0SMauro Carvalho Chehab 	p->pre_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
62678f3741e0SMauro Carvalho Chehab 	p->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
62688f3741e0SMauro Carvalho Chehab 	p->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
62698f3741e0SMauro Carvalho Chehab 
62709a0bf528SMauro Carvalho Chehab 	/* printk(KERN_DEBUG "drxk: %s IF=%d done\n", __func__, IF); */
62719a0bf528SMauro Carvalho Chehab 
62729a0bf528SMauro Carvalho Chehab 	return 0;
62739a0bf528SMauro Carvalho Chehab }
62749a0bf528SMauro Carvalho Chehab 
627559a7a23cSMauro Carvalho Chehab static int get_strength(struct drxk_state *state, u64 *strength)
627659a7a23cSMauro Carvalho Chehab {
627759a7a23cSMauro Carvalho Chehab 	int status;
6278cd7a67a4SMauro Carvalho Chehab 	struct s_cfg_agc   rf_agc, if_agc;
6279cd7a67a4SMauro Carvalho Chehab 	u32          total_gain  = 0;
628059a7a23cSMauro Carvalho Chehab 	u32          atten      = 0;
6281cd7a67a4SMauro Carvalho Chehab 	u32          agc_range   = 0;
628259a7a23cSMauro Carvalho Chehab 	u16            scu_lvl  = 0;
628359a7a23cSMauro Carvalho Chehab 	u16            scu_coc  = 0;
628459a7a23cSMauro Carvalho Chehab 	/* FIXME: those are part of the tuner presets */
6285cd7a67a4SMauro Carvalho Chehab 	u16 tuner_rf_gain         = 50; /* Default value on az6007 driver */
6286cd7a67a4SMauro Carvalho Chehab 	u16 tuner_if_gain         = 40; /* Default value on az6007 driver */
628759a7a23cSMauro Carvalho Chehab 
628859a7a23cSMauro Carvalho Chehab 	*strength = 0;
628959a7a23cSMauro Carvalho Chehab 
6290cd7a67a4SMauro Carvalho Chehab 	if (is_dvbt(state)) {
6291cd7a67a4SMauro Carvalho Chehab 		rf_agc = state->m_dvbt_rf_agc_cfg;
6292cd7a67a4SMauro Carvalho Chehab 		if_agc = state->m_dvbt_if_agc_cfg;
6293cd7a67a4SMauro Carvalho Chehab 	} else if (is_qam(state)) {
6294cd7a67a4SMauro Carvalho Chehab 		rf_agc = state->m_qam_rf_agc_cfg;
6295cd7a67a4SMauro Carvalho Chehab 		if_agc = state->m_qam_if_agc_cfg;
629659a7a23cSMauro Carvalho Chehab 	} else {
6297cd7a67a4SMauro Carvalho Chehab 		rf_agc = state->m_atv_rf_agc_cfg;
6298cd7a67a4SMauro Carvalho Chehab 		if_agc = state->m_atv_if_agc_cfg;
629959a7a23cSMauro Carvalho Chehab 	}
630059a7a23cSMauro Carvalho Chehab 
6301cd7a67a4SMauro Carvalho Chehab 	if (rf_agc.ctrl_mode == DRXK_AGC_CTRL_AUTO) {
6302cd7a67a4SMauro Carvalho Chehab 		/* SCU output_level */
630359a7a23cSMauro Carvalho Chehab 		status = read16(state, SCU_RAM_AGC_RF_IACCU_HI__A, &scu_lvl);
630459a7a23cSMauro Carvalho Chehab 		if (status < 0)
630559a7a23cSMauro Carvalho Chehab 			return status;
630659a7a23cSMauro Carvalho Chehab 
630759a7a23cSMauro Carvalho Chehab 		/* SCU c.o.c. */
630859a7a23cSMauro Carvalho Chehab 		read16(state, SCU_RAM_AGC_RF_IACCU_HI_CO__A, &scu_coc);
630959a7a23cSMauro Carvalho Chehab 		if (status < 0)
631059a7a23cSMauro Carvalho Chehab 			return status;
631159a7a23cSMauro Carvalho Chehab 
631259a7a23cSMauro Carvalho Chehab 		if (((u32) scu_lvl + (u32) scu_coc) < 0xffff)
6313cd7a67a4SMauro Carvalho Chehab 			rf_agc.output_level = scu_lvl + scu_coc;
631459a7a23cSMauro Carvalho Chehab 		else
6315cd7a67a4SMauro Carvalho Chehab 			rf_agc.output_level = 0xffff;
631659a7a23cSMauro Carvalho Chehab 
631759a7a23cSMauro Carvalho Chehab 		/* Take RF gain into account */
6318cd7a67a4SMauro Carvalho Chehab 		total_gain += tuner_rf_gain;
631959a7a23cSMauro Carvalho Chehab 
632059a7a23cSMauro Carvalho Chehab 		/* clip output value */
6321cd7a67a4SMauro Carvalho Chehab 		if (rf_agc.output_level < rf_agc.min_output_level)
6322cd7a67a4SMauro Carvalho Chehab 			rf_agc.output_level = rf_agc.min_output_level;
6323cd7a67a4SMauro Carvalho Chehab 		if (rf_agc.output_level > rf_agc.max_output_level)
6324cd7a67a4SMauro Carvalho Chehab 			rf_agc.output_level = rf_agc.max_output_level;
632559a7a23cSMauro Carvalho Chehab 
6326cd7a67a4SMauro Carvalho Chehab 		agc_range = (u32) (rf_agc.max_output_level - rf_agc.min_output_level);
6327cd7a67a4SMauro Carvalho Chehab 		if (agc_range > 0) {
632859a7a23cSMauro Carvalho Chehab 			atten += 100UL *
6329cd7a67a4SMauro Carvalho Chehab 				((u32)(tuner_rf_gain)) *
6330cd7a67a4SMauro Carvalho Chehab 				((u32)(rf_agc.output_level - rf_agc.min_output_level))
6331cd7a67a4SMauro Carvalho Chehab 				/ agc_range;
633259a7a23cSMauro Carvalho Chehab 		}
633359a7a23cSMauro Carvalho Chehab 	}
633459a7a23cSMauro Carvalho Chehab 
6335cd7a67a4SMauro Carvalho Chehab 	if (if_agc.ctrl_mode == DRXK_AGC_CTRL_AUTO) {
633659a7a23cSMauro Carvalho Chehab 		status = read16(state, SCU_RAM_AGC_IF_IACCU_HI__A,
6337cd7a67a4SMauro Carvalho Chehab 				&if_agc.output_level);
633859a7a23cSMauro Carvalho Chehab 		if (status < 0)
633959a7a23cSMauro Carvalho Chehab 			return status;
634059a7a23cSMauro Carvalho Chehab 
634159a7a23cSMauro Carvalho Chehab 		status = read16(state, SCU_RAM_AGC_INGAIN_TGT_MIN__A,
6342cd7a67a4SMauro Carvalho Chehab 				&if_agc.top);
634359a7a23cSMauro Carvalho Chehab 		if (status < 0)
634459a7a23cSMauro Carvalho Chehab 			return status;
634559a7a23cSMauro Carvalho Chehab 
634659a7a23cSMauro Carvalho Chehab 		/* Take IF gain into account */
6347cd7a67a4SMauro Carvalho Chehab 		total_gain += (u32) tuner_if_gain;
634859a7a23cSMauro Carvalho Chehab 
634959a7a23cSMauro Carvalho Chehab 		/* clip output value */
6350cd7a67a4SMauro Carvalho Chehab 		if (if_agc.output_level < if_agc.min_output_level)
6351cd7a67a4SMauro Carvalho Chehab 			if_agc.output_level = if_agc.min_output_level;
6352cd7a67a4SMauro Carvalho Chehab 		if (if_agc.output_level > if_agc.max_output_level)
6353cd7a67a4SMauro Carvalho Chehab 			if_agc.output_level = if_agc.max_output_level;
635459a7a23cSMauro Carvalho Chehab 
6355cd7a67a4SMauro Carvalho Chehab 		agc_range  = (u32) (if_agc.max_output_level - if_agc.min_output_level);
6356cd7a67a4SMauro Carvalho Chehab 		if (agc_range > 0) {
635759a7a23cSMauro Carvalho Chehab 			atten += 100UL *
6358cd7a67a4SMauro Carvalho Chehab 				((u32)(tuner_if_gain)) *
6359cd7a67a4SMauro Carvalho Chehab 				((u32)(if_agc.output_level - if_agc.min_output_level))
6360cd7a67a4SMauro Carvalho Chehab 				/ agc_range;
636159a7a23cSMauro Carvalho Chehab 		}
636259a7a23cSMauro Carvalho Chehab 	}
636359a7a23cSMauro Carvalho Chehab 
636459a7a23cSMauro Carvalho Chehab 	/*
636559a7a23cSMauro Carvalho Chehab 	 * Convert to 0..65535 scale.
636659a7a23cSMauro Carvalho Chehab 	 * If it can't be measured (AGC is disabled), just show 100%.
636759a7a23cSMauro Carvalho Chehab 	 */
6368cd7a67a4SMauro Carvalho Chehab 	if (total_gain > 0)
6369cd7a67a4SMauro Carvalho Chehab 		*strength = (65535UL * atten / total_gain / 100);
637059a7a23cSMauro Carvalho Chehab 	else
637159a7a23cSMauro Carvalho Chehab 		*strength = 65535;
637259a7a23cSMauro Carvalho Chehab 
637359a7a23cSMauro Carvalho Chehab 	return 0;
637459a7a23cSMauro Carvalho Chehab }
637559a7a23cSMauro Carvalho Chehab 
63768f3741e0SMauro Carvalho Chehab static int drxk_get_stats(struct dvb_frontend *fe)
63779a0bf528SMauro Carvalho Chehab {
63788f3741e0SMauro Carvalho Chehab 	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
63799a0bf528SMauro Carvalho Chehab 	struct drxk_state *state = fe->demodulator_priv;
63808f3741e0SMauro Carvalho Chehab 	int status;
63819a0bf528SMauro Carvalho Chehab 	u32 stat;
63828f3741e0SMauro Carvalho Chehab 	u16 reg16;
63838f3741e0SMauro Carvalho Chehab 	u32 post_bit_count;
63848f3741e0SMauro Carvalho Chehab 	u32 post_bit_err_count;
63858f3741e0SMauro Carvalho Chehab 	u32 post_bit_error_scale;
63868f3741e0SMauro Carvalho Chehab 	u32 pre_bit_err_count;
63878f3741e0SMauro Carvalho Chehab 	u32 pre_bit_count;
63888f3741e0SMauro Carvalho Chehab 	u32 pkt_count;
63898f3741e0SMauro Carvalho Chehab 	u32 pkt_error_count;
639059a7a23cSMauro Carvalho Chehab 	s32 cnr;
63919a0bf528SMauro Carvalho Chehab 
6392cd7a67a4SMauro Carvalho Chehab 	if (state->m_drxk_state == DRXK_NO_DEV)
63939a0bf528SMauro Carvalho Chehab 		return -ENODEV;
6394cd7a67a4SMauro Carvalho Chehab 	if (state->m_drxk_state == DRXK_UNINITIALIZED)
63959a0bf528SMauro Carvalho Chehab 		return -EAGAIN;
63969a0bf528SMauro Carvalho Chehab 
63978f3741e0SMauro Carvalho Chehab 	/* get status */
63988f3741e0SMauro Carvalho Chehab 	state->fe_status = 0;
6399cd7a67a4SMauro Carvalho Chehab 	get_lock_status(state, &stat);
64009a0bf528SMauro Carvalho Chehab 	if (stat == MPEG_LOCK)
64018f3741e0SMauro Carvalho Chehab 		state->fe_status |= 0x1f;
64029a0bf528SMauro Carvalho Chehab 	if (stat == FEC_LOCK)
64038f3741e0SMauro Carvalho Chehab 		state->fe_status |= 0x0f;
64049a0bf528SMauro Carvalho Chehab 	if (stat == DEMOD_LOCK)
64058f3741e0SMauro Carvalho Chehab 		state->fe_status |= 0x07;
64068f3741e0SMauro Carvalho Chehab 
640759a7a23cSMauro Carvalho Chehab 	/*
640859a7a23cSMauro Carvalho Chehab 	 * Estimate signal strength from AGC
640959a7a23cSMauro Carvalho Chehab 	 */
641059a7a23cSMauro Carvalho Chehab 	get_strength(state, &c->strength.stat[0].uvalue);
641159a7a23cSMauro Carvalho Chehab 	c->strength.stat[0].scale = FE_SCALE_RELATIVE;
641259a7a23cSMauro Carvalho Chehab 
641359a7a23cSMauro Carvalho Chehab 
64148f3741e0SMauro Carvalho Chehab 	if (stat >= DEMOD_LOCK) {
6415cd7a67a4SMauro Carvalho Chehab 		get_signal_to_noise(state, &cnr);
64168f3741e0SMauro Carvalho Chehab 		c->cnr.stat[0].svalue = cnr * 100;
64178f3741e0SMauro Carvalho Chehab 		c->cnr.stat[0].scale = FE_SCALE_DECIBEL;
64188f3741e0SMauro Carvalho Chehab 	} else {
64198f3741e0SMauro Carvalho Chehab 		c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
64208f3741e0SMauro Carvalho Chehab 	}
64218f3741e0SMauro Carvalho Chehab 
64228f3741e0SMauro Carvalho Chehab 	if (stat < FEC_LOCK) {
64238f3741e0SMauro Carvalho Chehab 		c->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
64248f3741e0SMauro Carvalho Chehab 		c->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
64258f3741e0SMauro Carvalho Chehab 		c->pre_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
64268f3741e0SMauro Carvalho Chehab 		c->pre_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
64278f3741e0SMauro Carvalho Chehab 		c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
64288f3741e0SMauro Carvalho Chehab 		c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
64298f3741e0SMauro Carvalho Chehab 		return 0;
64308f3741e0SMauro Carvalho Chehab 	}
64318f3741e0SMauro Carvalho Chehab 
64328f3741e0SMauro Carvalho Chehab 	/* Get post BER */
64338f3741e0SMauro Carvalho Chehab 
64348f3741e0SMauro Carvalho Chehab 	/* BER measurement is valid if at least FEC lock is achieved */
64358f3741e0SMauro Carvalho Chehab 
64368f3741e0SMauro Carvalho Chehab 	/* OFDM_EC_VD_REQ_SMB_CNT__A and/or OFDM_EC_VD_REQ_BIT_CNT can be written
64378f3741e0SMauro Carvalho Chehab 		to set nr of symbols or bits over which
64388f3741e0SMauro Carvalho Chehab 		to measure EC_VD_REG_ERR_BIT_CNT__A . See CtrlSetCfg(). */
64398f3741e0SMauro Carvalho Chehab 
64408f3741e0SMauro Carvalho Chehab 	/* Read registers for post/preViterbi BER calculation */
64418f3741e0SMauro Carvalho Chehab 	status = read16(state, OFDM_EC_VD_ERR_BIT_CNT__A, &reg16);
64428f3741e0SMauro Carvalho Chehab 	if (status < 0)
64438f3741e0SMauro Carvalho Chehab 		goto error;
64448f3741e0SMauro Carvalho Chehab 	pre_bit_err_count = reg16;
64458f3741e0SMauro Carvalho Chehab 
64468f3741e0SMauro Carvalho Chehab 	status = read16(state, OFDM_EC_VD_IN_BIT_CNT__A , &reg16);
64478f3741e0SMauro Carvalho Chehab 	if (status < 0)
64488f3741e0SMauro Carvalho Chehab 		goto error;
64498f3741e0SMauro Carvalho Chehab 	pre_bit_count = reg16;
64508f3741e0SMauro Carvalho Chehab 
64518f3741e0SMauro Carvalho Chehab 	/* Number of bit-errors */
64528f3741e0SMauro Carvalho Chehab 	status = read16(state, FEC_RS_NR_BIT_ERRORS__A, &reg16);
64538f3741e0SMauro Carvalho Chehab 	if (status < 0)
64548f3741e0SMauro Carvalho Chehab 		goto error;
64558f3741e0SMauro Carvalho Chehab 	post_bit_err_count = reg16;
64568f3741e0SMauro Carvalho Chehab 
64578f3741e0SMauro Carvalho Chehab 	status = read16(state, FEC_RS_MEASUREMENT_PRESCALE__A, &reg16);
64588f3741e0SMauro Carvalho Chehab 	if (status < 0)
64598f3741e0SMauro Carvalho Chehab 		goto error;
64608f3741e0SMauro Carvalho Chehab 	post_bit_error_scale = reg16;
64618f3741e0SMauro Carvalho Chehab 
64628f3741e0SMauro Carvalho Chehab 	status = read16(state, FEC_RS_MEASUREMENT_PERIOD__A, &reg16);
64638f3741e0SMauro Carvalho Chehab 	if (status < 0)
64648f3741e0SMauro Carvalho Chehab 		goto error;
64658f3741e0SMauro Carvalho Chehab 	pkt_count = reg16;
64668f3741e0SMauro Carvalho Chehab 
64678f3741e0SMauro Carvalho Chehab 	status = read16(state, SCU_RAM_FEC_ACCUM_PKT_FAILURES__A, &reg16);
64688f3741e0SMauro Carvalho Chehab 	if (status < 0)
64698f3741e0SMauro Carvalho Chehab 		goto error;
64708f3741e0SMauro Carvalho Chehab 	pkt_error_count = reg16;
64718f3741e0SMauro Carvalho Chehab 	write16(state, SCU_RAM_FEC_ACCUM_PKT_FAILURES__A, 0);
64728f3741e0SMauro Carvalho Chehab 
64738f3741e0SMauro Carvalho Chehab 	post_bit_err_count *= post_bit_error_scale;
64748f3741e0SMauro Carvalho Chehab 
64758f3741e0SMauro Carvalho Chehab 	post_bit_count = pkt_count * 204 * 8;
64768f3741e0SMauro Carvalho Chehab 
64778f3741e0SMauro Carvalho Chehab 	/* Store the results */
64788f3741e0SMauro Carvalho Chehab 	c->block_error.stat[0].scale = FE_SCALE_COUNTER;
64798f3741e0SMauro Carvalho Chehab 	c->block_error.stat[0].uvalue += pkt_error_count;
64808f3741e0SMauro Carvalho Chehab 	c->block_count.stat[0].scale = FE_SCALE_COUNTER;
64818f3741e0SMauro Carvalho Chehab 	c->block_count.stat[0].uvalue += pkt_count;
64828f3741e0SMauro Carvalho Chehab 
64838f3741e0SMauro Carvalho Chehab 	c->pre_bit_error.stat[0].scale = FE_SCALE_COUNTER;
64848f3741e0SMauro Carvalho Chehab 	c->pre_bit_error.stat[0].uvalue += pre_bit_err_count;
64858f3741e0SMauro Carvalho Chehab 	c->pre_bit_count.stat[0].scale = FE_SCALE_COUNTER;
64868f3741e0SMauro Carvalho Chehab 	c->pre_bit_count.stat[0].uvalue += pre_bit_count;
64878f3741e0SMauro Carvalho Chehab 
64888f3741e0SMauro Carvalho Chehab 	c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER;
64898f3741e0SMauro Carvalho Chehab 	c->post_bit_error.stat[0].uvalue += post_bit_err_count;
64908f3741e0SMauro Carvalho Chehab 	c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER;
64918f3741e0SMauro Carvalho Chehab 	c->post_bit_count.stat[0].uvalue += post_bit_count;
64928f3741e0SMauro Carvalho Chehab 
64938f3741e0SMauro Carvalho Chehab error:
64948f3741e0SMauro Carvalho Chehab 	return status;
64958f3741e0SMauro Carvalho Chehab }
64968f3741e0SMauro Carvalho Chehab 
64978f3741e0SMauro Carvalho Chehab 
64988f3741e0SMauro Carvalho Chehab static int drxk_read_status(struct dvb_frontend *fe, fe_status_t *status)
64998f3741e0SMauro Carvalho Chehab {
65008f3741e0SMauro Carvalho Chehab 	struct drxk_state *state = fe->demodulator_priv;
65018f3741e0SMauro Carvalho Chehab 	int rc;
65028f3741e0SMauro Carvalho Chehab 
65038f3741e0SMauro Carvalho Chehab 	dprintk(1, "\n");
65048f3741e0SMauro Carvalho Chehab 
65058f3741e0SMauro Carvalho Chehab 	rc = drxk_get_stats(fe);
65068f3741e0SMauro Carvalho Chehab 	if (rc < 0)
65078f3741e0SMauro Carvalho Chehab 		return rc;
65088f3741e0SMauro Carvalho Chehab 
65098f3741e0SMauro Carvalho Chehab 	*status = state->fe_status;
65108f3741e0SMauro Carvalho Chehab 
65119a0bf528SMauro Carvalho Chehab 	return 0;
65129a0bf528SMauro Carvalho Chehab }
65139a0bf528SMauro Carvalho Chehab 
65149a0bf528SMauro Carvalho Chehab static int drxk_read_signal_strength(struct dvb_frontend *fe,
65159a0bf528SMauro Carvalho Chehab 				     u16 *strength)
65169a0bf528SMauro Carvalho Chehab {
65179a0bf528SMauro Carvalho Chehab 	struct drxk_state *state = fe->demodulator_priv;
6518340e7696SMauro Carvalho Chehab 	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
65199a0bf528SMauro Carvalho Chehab 
65209a0bf528SMauro Carvalho Chehab 	dprintk(1, "\n");
65219a0bf528SMauro Carvalho Chehab 
6522cd7a67a4SMauro Carvalho Chehab 	if (state->m_drxk_state == DRXK_NO_DEV)
65239a0bf528SMauro Carvalho Chehab 		return -ENODEV;
6524cd7a67a4SMauro Carvalho Chehab 	if (state->m_drxk_state == DRXK_UNINITIALIZED)
65259a0bf528SMauro Carvalho Chehab 		return -EAGAIN;
65269a0bf528SMauro Carvalho Chehab 
6527340e7696SMauro Carvalho Chehab 	*strength = c->strength.stat[0].uvalue;
65289a0bf528SMauro Carvalho Chehab 	return 0;
65299a0bf528SMauro Carvalho Chehab }
65309a0bf528SMauro Carvalho Chehab 
65319a0bf528SMauro Carvalho Chehab static int drxk_read_snr(struct dvb_frontend *fe, u16 *snr)
65329a0bf528SMauro Carvalho Chehab {
65339a0bf528SMauro Carvalho Chehab 	struct drxk_state *state = fe->demodulator_priv;
65349a0bf528SMauro Carvalho Chehab 	s32 snr2;
65359a0bf528SMauro Carvalho Chehab 
65369a0bf528SMauro Carvalho Chehab 	dprintk(1, "\n");
65379a0bf528SMauro Carvalho Chehab 
6538cd7a67a4SMauro Carvalho Chehab 	if (state->m_drxk_state == DRXK_NO_DEV)
65399a0bf528SMauro Carvalho Chehab 		return -ENODEV;
6540cd7a67a4SMauro Carvalho Chehab 	if (state->m_drxk_state == DRXK_UNINITIALIZED)
65419a0bf528SMauro Carvalho Chehab 		return -EAGAIN;
65429a0bf528SMauro Carvalho Chehab 
6543cd7a67a4SMauro Carvalho Chehab 	get_signal_to_noise(state, &snr2);
65448f3741e0SMauro Carvalho Chehab 
65458f3741e0SMauro Carvalho Chehab 	/* No negative SNR, clip to zero */
65468f3741e0SMauro Carvalho Chehab 	if (snr2 < 0)
65478f3741e0SMauro Carvalho Chehab 		snr2 = 0;
65489a0bf528SMauro Carvalho Chehab 	*snr = snr2 & 0xffff;
65499a0bf528SMauro Carvalho Chehab 	return 0;
65509a0bf528SMauro Carvalho Chehab }
65519a0bf528SMauro Carvalho Chehab 
65529a0bf528SMauro Carvalho Chehab static int drxk_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
65539a0bf528SMauro Carvalho Chehab {
65549a0bf528SMauro Carvalho Chehab 	struct drxk_state *state = fe->demodulator_priv;
65559a0bf528SMauro Carvalho Chehab 	u16 err;
65569a0bf528SMauro Carvalho Chehab 
65579a0bf528SMauro Carvalho Chehab 	dprintk(1, "\n");
65589a0bf528SMauro Carvalho Chehab 
6559cd7a67a4SMauro Carvalho Chehab 	if (state->m_drxk_state == DRXK_NO_DEV)
65609a0bf528SMauro Carvalho Chehab 		return -ENODEV;
6561cd7a67a4SMauro Carvalho Chehab 	if (state->m_drxk_state == DRXK_UNINITIALIZED)
65629a0bf528SMauro Carvalho Chehab 		return -EAGAIN;
65639a0bf528SMauro Carvalho Chehab 
6564cd7a67a4SMauro Carvalho Chehab 	dvbtqam_get_acc_pkt_err(state, &err);
65659a0bf528SMauro Carvalho Chehab 	*ucblocks = (u32) err;
65669a0bf528SMauro Carvalho Chehab 	return 0;
65679a0bf528SMauro Carvalho Chehab }
65689a0bf528SMauro Carvalho Chehab 
65699a0bf528SMauro Carvalho Chehab static int drxk_get_tune_settings(struct dvb_frontend *fe, struct dvb_frontend_tune_settings
65709a0bf528SMauro Carvalho Chehab 				    *sets)
65719a0bf528SMauro Carvalho Chehab {
65729a0bf528SMauro Carvalho Chehab 	struct drxk_state *state = fe->demodulator_priv;
65739a0bf528SMauro Carvalho Chehab 	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
65749a0bf528SMauro Carvalho Chehab 
65759a0bf528SMauro Carvalho Chehab 	dprintk(1, "\n");
65769a0bf528SMauro Carvalho Chehab 
6577cd7a67a4SMauro Carvalho Chehab 	if (state->m_drxk_state == DRXK_NO_DEV)
65789a0bf528SMauro Carvalho Chehab 		return -ENODEV;
6579cd7a67a4SMauro Carvalho Chehab 	if (state->m_drxk_state == DRXK_UNINITIALIZED)
65809a0bf528SMauro Carvalho Chehab 		return -EAGAIN;
65819a0bf528SMauro Carvalho Chehab 
65829a0bf528SMauro Carvalho Chehab 	switch (p->delivery_system) {
65839a0bf528SMauro Carvalho Chehab 	case SYS_DVBC_ANNEX_A:
65849a0bf528SMauro Carvalho Chehab 	case SYS_DVBC_ANNEX_C:
65859a0bf528SMauro Carvalho Chehab 	case SYS_DVBT:
65869a0bf528SMauro Carvalho Chehab 		sets->min_delay_ms = 3000;
65879a0bf528SMauro Carvalho Chehab 		sets->max_drift = 0;
65889a0bf528SMauro Carvalho Chehab 		sets->step_size = 0;
65899a0bf528SMauro Carvalho Chehab 		return 0;
65909a0bf528SMauro Carvalho Chehab 	default:
65919a0bf528SMauro Carvalho Chehab 		return -EINVAL;
65929a0bf528SMauro Carvalho Chehab 	}
65939a0bf528SMauro Carvalho Chehab }
65949a0bf528SMauro Carvalho Chehab 
65959a0bf528SMauro Carvalho Chehab static struct dvb_frontend_ops drxk_ops = {
65969a0bf528SMauro Carvalho Chehab 	/* .delsys will be filled dynamically */
65979a0bf528SMauro Carvalho Chehab 	.info = {
65989a0bf528SMauro Carvalho Chehab 		.name = "DRXK",
65999a0bf528SMauro Carvalho Chehab 		.frequency_min = 47000000,
66009a0bf528SMauro Carvalho Chehab 		.frequency_max = 865000000,
66019a0bf528SMauro Carvalho Chehab 		 /* For DVB-C */
66029a0bf528SMauro Carvalho Chehab 		.symbol_rate_min = 870000,
66039a0bf528SMauro Carvalho Chehab 		.symbol_rate_max = 11700000,
66049a0bf528SMauro Carvalho Chehab 		/* For DVB-T */
66059a0bf528SMauro Carvalho Chehab 		.frequency_stepsize = 166667,
66069a0bf528SMauro Carvalho Chehab 
66079a0bf528SMauro Carvalho Chehab 		.caps = FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 |
66089a0bf528SMauro Carvalho Chehab 			FE_CAN_QAM_128 | FE_CAN_QAM_256 | FE_CAN_FEC_AUTO |
66099a0bf528SMauro Carvalho Chehab 			FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
66109a0bf528SMauro Carvalho Chehab 			FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_MUTE_TS |
66119a0bf528SMauro Carvalho Chehab 			FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_RECOVER |
66129a0bf528SMauro Carvalho Chehab 			FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO
66139a0bf528SMauro Carvalho Chehab 	},
66149a0bf528SMauro Carvalho Chehab 
66159a0bf528SMauro Carvalho Chehab 	.release = drxk_release,
66169a0bf528SMauro Carvalho Chehab 	.sleep = drxk_sleep,
66179a0bf528SMauro Carvalho Chehab 	.i2c_gate_ctrl = drxk_gate_ctrl,
66189a0bf528SMauro Carvalho Chehab 
66199a0bf528SMauro Carvalho Chehab 	.set_frontend = drxk_set_parameters,
66209a0bf528SMauro Carvalho Chehab 	.get_tune_settings = drxk_get_tune_settings,
66219a0bf528SMauro Carvalho Chehab 
66229a0bf528SMauro Carvalho Chehab 	.read_status = drxk_read_status,
66239a0bf528SMauro Carvalho Chehab 	.read_signal_strength = drxk_read_signal_strength,
66249a0bf528SMauro Carvalho Chehab 	.read_snr = drxk_read_snr,
66259a0bf528SMauro Carvalho Chehab 	.read_ucblocks = drxk_read_ucblocks,
66269a0bf528SMauro Carvalho Chehab };
66279a0bf528SMauro Carvalho Chehab 
66289a0bf528SMauro Carvalho Chehab struct dvb_frontend *drxk_attach(const struct drxk_config *config,
66299a0bf528SMauro Carvalho Chehab 				 struct i2c_adapter *i2c)
66309a0bf528SMauro Carvalho Chehab {
66318f3741e0SMauro Carvalho Chehab 	struct dtv_frontend_properties *p;
66329a0bf528SMauro Carvalho Chehab 	struct drxk_state *state = NULL;
66339a0bf528SMauro Carvalho Chehab 	u8 adr = config->adr;
66349a0bf528SMauro Carvalho Chehab 	int status;
66359a0bf528SMauro Carvalho Chehab 
66369a0bf528SMauro Carvalho Chehab 	dprintk(1, "\n");
66379a0bf528SMauro Carvalho Chehab 	state = kzalloc(sizeof(struct drxk_state), GFP_KERNEL);
66389a0bf528SMauro Carvalho Chehab 	if (!state)
66399a0bf528SMauro Carvalho Chehab 		return NULL;
66409a0bf528SMauro Carvalho Chehab 
66419a0bf528SMauro Carvalho Chehab 	state->i2c = i2c;
66429a0bf528SMauro Carvalho Chehab 	state->demod_address = adr;
66439a0bf528SMauro Carvalho Chehab 	state->single_master = config->single_master;
66449a0bf528SMauro Carvalho Chehab 	state->microcode_name = config->microcode_name;
66459a0bf528SMauro Carvalho Chehab 	state->qam_demod_parameter_count = config->qam_demod_parameter_count;
66469a0bf528SMauro Carvalho Chehab 	state->no_i2c_bridge = config->no_i2c_bridge;
66479a0bf528SMauro Carvalho Chehab 	state->antenna_gpio = config->antenna_gpio;
66489a0bf528SMauro Carvalho Chehab 	state->antenna_dvbt = config->antenna_dvbt;
6649cd7a67a4SMauro Carvalho Chehab 	state->m_chunk_size = config->chunk_size;
66509a0bf528SMauro Carvalho Chehab 	state->enable_merr_cfg = config->enable_merr_cfg;
66519a0bf528SMauro Carvalho Chehab 
66529a0bf528SMauro Carvalho Chehab 	if (config->dynamic_clk) {
6653cd7a67a4SMauro Carvalho Chehab 		state->m_dvbt_static_clk = 0;
6654cd7a67a4SMauro Carvalho Chehab 		state->m_dvbc_static_clk = 0;
66559a0bf528SMauro Carvalho Chehab 	} else {
6656cd7a67a4SMauro Carvalho Chehab 		state->m_dvbt_static_clk = 1;
6657cd7a67a4SMauro Carvalho Chehab 		state->m_dvbc_static_clk = 1;
66589a0bf528SMauro Carvalho Chehab 	}
66599a0bf528SMauro Carvalho Chehab 
66609a0bf528SMauro Carvalho Chehab 
66619a0bf528SMauro Carvalho Chehab 	if (config->mpeg_out_clk_strength)
6662cd7a67a4SMauro Carvalho Chehab 		state->m_ts_clockk_strength = config->mpeg_out_clk_strength & 0x07;
66639a0bf528SMauro Carvalho Chehab 	else
6664cd7a67a4SMauro Carvalho Chehab 		state->m_ts_clockk_strength = 0x06;
66659a0bf528SMauro Carvalho Chehab 
66669a0bf528SMauro Carvalho Chehab 	if (config->parallel_ts)
6667cd7a67a4SMauro Carvalho Chehab 		state->m_enable_parallel = true;
66689a0bf528SMauro Carvalho Chehab 	else
6669cd7a67a4SMauro Carvalho Chehab 		state->m_enable_parallel = false;
66709a0bf528SMauro Carvalho Chehab 
66719a0bf528SMauro Carvalho Chehab 	/* NOTE: as more UIO bits will be used, add them to the mask */
6672cd7a67a4SMauro Carvalho Chehab 	state->uio_mask = config->antenna_gpio;
66739a0bf528SMauro Carvalho Chehab 
66749a0bf528SMauro Carvalho Chehab 	/* Default gpio to DVB-C */
66759a0bf528SMauro Carvalho Chehab 	if (!state->antenna_dvbt && state->antenna_gpio)
6676cd7a67a4SMauro Carvalho Chehab 		state->m_gpio |= state->antenna_gpio;
66779a0bf528SMauro Carvalho Chehab 	else
6678cd7a67a4SMauro Carvalho Chehab 		state->m_gpio &= ~state->antenna_gpio;
66799a0bf528SMauro Carvalho Chehab 
66809a0bf528SMauro Carvalho Chehab 	mutex_init(&state->mutex);
66819a0bf528SMauro Carvalho Chehab 
66829a0bf528SMauro Carvalho Chehab 	memcpy(&state->frontend.ops, &drxk_ops, sizeof(drxk_ops));
66839a0bf528SMauro Carvalho Chehab 	state->frontend.demodulator_priv = state;
66849a0bf528SMauro Carvalho Chehab 
66859a0bf528SMauro Carvalho Chehab 	init_state(state);
66869a0bf528SMauro Carvalho Chehab 
66879a0bf528SMauro Carvalho Chehab 	/* Load firmware and initialize DRX-K */
66889a0bf528SMauro Carvalho Chehab 	if (state->microcode_name) {
66898e30783bSMauro Carvalho Chehab 		if (config->load_firmware_sync) {
66908e30783bSMauro Carvalho Chehab 			const struct firmware *fw = NULL;
66918e30783bSMauro Carvalho Chehab 
66928e30783bSMauro Carvalho Chehab 			status = request_firmware(&fw, state->microcode_name,
66938e30783bSMauro Carvalho Chehab 						  state->i2c->dev.parent);
66948e30783bSMauro Carvalho Chehab 			if (status < 0)
66958e30783bSMauro Carvalho Chehab 				fw = NULL;
66968e30783bSMauro Carvalho Chehab 			load_firmware_cb(fw, state);
66978e30783bSMauro Carvalho Chehab 		} else {
66989a0bf528SMauro Carvalho Chehab 			status = request_firmware_nowait(THIS_MODULE, 1,
66999a0bf528SMauro Carvalho Chehab 					      state->microcode_name,
67009a0bf528SMauro Carvalho Chehab 					      state->i2c->dev.parent,
67019a0bf528SMauro Carvalho Chehab 					      GFP_KERNEL,
67029a0bf528SMauro Carvalho Chehab 					      state, load_firmware_cb);
67039a0bf528SMauro Carvalho Chehab 			if (status < 0) {
67043a4398f5SMauro Carvalho Chehab 				pr_err("failed to request a firmware\n");
67059a0bf528SMauro Carvalho Chehab 				return NULL;
67069a0bf528SMauro Carvalho Chehab 			}
67078e30783bSMauro Carvalho Chehab 		}
67089a0bf528SMauro Carvalho Chehab 	} else if (init_drxk(state) < 0)
67099a0bf528SMauro Carvalho Chehab 		goto error;
67109a0bf528SMauro Carvalho Chehab 
67118f3741e0SMauro Carvalho Chehab 
67128f3741e0SMauro Carvalho Chehab 	/* Initialize stats */
67138f3741e0SMauro Carvalho Chehab 	p = &state->frontend.dtv_property_cache;
67148f3741e0SMauro Carvalho Chehab 	p->strength.len = 1;
67158f3741e0SMauro Carvalho Chehab 	p->cnr.len = 1;
67168f3741e0SMauro Carvalho Chehab 	p->block_error.len = 1;
67178f3741e0SMauro Carvalho Chehab 	p->block_count.len = 1;
67188f3741e0SMauro Carvalho Chehab 	p->pre_bit_error.len = 1;
67198f3741e0SMauro Carvalho Chehab 	p->pre_bit_count.len = 1;
67208f3741e0SMauro Carvalho Chehab 	p->post_bit_error.len = 1;
67218f3741e0SMauro Carvalho Chehab 	p->post_bit_count.len = 1;
67228f3741e0SMauro Carvalho Chehab 
67238f3741e0SMauro Carvalho Chehab 	p->strength.stat[0].scale = FE_SCALE_RELATIVE;
67248f3741e0SMauro Carvalho Chehab 	p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
67258f3741e0SMauro Carvalho Chehab 	p->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
67268f3741e0SMauro Carvalho Chehab 	p->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
67278f3741e0SMauro Carvalho Chehab 	p->pre_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
67288f3741e0SMauro Carvalho Chehab 	p->pre_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
67298f3741e0SMauro Carvalho Chehab 	p->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
67308f3741e0SMauro Carvalho Chehab 	p->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
67318f3741e0SMauro Carvalho Chehab 
67323a4398f5SMauro Carvalho Chehab 	pr_info("frontend initialized.\n");
67339a0bf528SMauro Carvalho Chehab 	return &state->frontend;
67349a0bf528SMauro Carvalho Chehab 
67359a0bf528SMauro Carvalho Chehab error:
67363a4398f5SMauro Carvalho Chehab 	pr_err("not found\n");
67379a0bf528SMauro Carvalho Chehab 	kfree(state);
67389a0bf528SMauro Carvalho Chehab 	return NULL;
67399a0bf528SMauro Carvalho Chehab }
67409a0bf528SMauro Carvalho Chehab EXPORT_SYMBOL(drxk_attach);
67419a0bf528SMauro Carvalho Chehab 
67429a0bf528SMauro Carvalho Chehab MODULE_DESCRIPTION("DRX-K driver");
67439a0bf528SMauro Carvalho Chehab MODULE_AUTHOR("Ralph Metzler");
67449a0bf528SMauro Carvalho Chehab MODULE_LICENSE("GPL");
6745