xref: /OK3568_Linux_fs/kernel/drivers/media/dvb-frontends/drxk_hard.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * drxk_hard: DRX-K DVB-C/T demodulator driver
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Copyright (C) 2010-2011 Digital Devices GmbH
6*4882a593Smuzhiyun  */
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
9*4882a593Smuzhiyun 
10*4882a593Smuzhiyun #include <linux/kernel.h>
11*4882a593Smuzhiyun #include <linux/module.h>
12*4882a593Smuzhiyun #include <linux/moduleparam.h>
13*4882a593Smuzhiyun #include <linux/init.h>
14*4882a593Smuzhiyun #include <linux/delay.h>
15*4882a593Smuzhiyun #include <linux/firmware.h>
16*4882a593Smuzhiyun #include <linux/i2c.h>
17*4882a593Smuzhiyun #include <linux/hardirq.h>
18*4882a593Smuzhiyun #include <asm/div64.h>
19*4882a593Smuzhiyun 
20*4882a593Smuzhiyun #include <media/dvb_frontend.h>
21*4882a593Smuzhiyun #include "drxk.h"
22*4882a593Smuzhiyun #include "drxk_hard.h"
23*4882a593Smuzhiyun #include <media/dvb_math.h>
24*4882a593Smuzhiyun 
25*4882a593Smuzhiyun static int power_down_dvbt(struct drxk_state *state, bool set_power_mode);
26*4882a593Smuzhiyun static int power_down_qam(struct drxk_state *state);
27*4882a593Smuzhiyun static int set_dvbt_standard(struct drxk_state *state,
28*4882a593Smuzhiyun 			   enum operation_mode o_mode);
29*4882a593Smuzhiyun static int set_qam_standard(struct drxk_state *state,
30*4882a593Smuzhiyun 			  enum operation_mode o_mode);
31*4882a593Smuzhiyun static int set_qam(struct drxk_state *state, u16 intermediate_freqk_hz,
32*4882a593Smuzhiyun 		  s32 tuner_freq_offset);
33*4882a593Smuzhiyun static int set_dvbt_standard(struct drxk_state *state,
34*4882a593Smuzhiyun 			   enum operation_mode o_mode);
35*4882a593Smuzhiyun static int dvbt_start(struct drxk_state *state);
36*4882a593Smuzhiyun static int set_dvbt(struct drxk_state *state, u16 intermediate_freqk_hz,
37*4882a593Smuzhiyun 		   s32 tuner_freq_offset);
38*4882a593Smuzhiyun static int get_qam_lock_status(struct drxk_state *state, u32 *p_lock_status);
39*4882a593Smuzhiyun static int get_dvbt_lock_status(struct drxk_state *state, u32 *p_lock_status);
40*4882a593Smuzhiyun static int switch_antenna_to_qam(struct drxk_state *state);
41*4882a593Smuzhiyun static int switch_antenna_to_dvbt(struct drxk_state *state);
42*4882a593Smuzhiyun 
is_dvbt(struct drxk_state * state)43*4882a593Smuzhiyun static bool is_dvbt(struct drxk_state *state)
44*4882a593Smuzhiyun {
45*4882a593Smuzhiyun 	return state->m_operation_mode == OM_DVBT;
46*4882a593Smuzhiyun }
47*4882a593Smuzhiyun 
is_qam(struct drxk_state * state)48*4882a593Smuzhiyun static bool is_qam(struct drxk_state *state)
49*4882a593Smuzhiyun {
50*4882a593Smuzhiyun 	return state->m_operation_mode == OM_QAM_ITU_A ||
51*4882a593Smuzhiyun 	    state->m_operation_mode == OM_QAM_ITU_B ||
52*4882a593Smuzhiyun 	    state->m_operation_mode == OM_QAM_ITU_C;
53*4882a593Smuzhiyun }
54*4882a593Smuzhiyun 
55*4882a593Smuzhiyun #define NOA1ROM 0
56*4882a593Smuzhiyun 
57*4882a593Smuzhiyun #define DRXDAP_FASI_SHORT_FORMAT(addr) (((addr) & 0xFC30FF80) == 0)
58*4882a593Smuzhiyun #define DRXDAP_FASI_LONG_FORMAT(addr)  (((addr) & 0xFC30FF80) != 0)
59*4882a593Smuzhiyun 
60*4882a593Smuzhiyun #define DEFAULT_MER_83  165
61*4882a593Smuzhiyun #define DEFAULT_MER_93  250
62*4882a593Smuzhiyun 
63*4882a593Smuzhiyun #ifndef DRXK_MPEG_SERIAL_OUTPUT_PIN_DRIVE_STRENGTH
64*4882a593Smuzhiyun #define DRXK_MPEG_SERIAL_OUTPUT_PIN_DRIVE_STRENGTH (0x02)
65*4882a593Smuzhiyun #endif
66*4882a593Smuzhiyun 
67*4882a593Smuzhiyun #ifndef DRXK_MPEG_PARALLEL_OUTPUT_PIN_DRIVE_STRENGTH
68*4882a593Smuzhiyun #define DRXK_MPEG_PARALLEL_OUTPUT_PIN_DRIVE_STRENGTH (0x03)
69*4882a593Smuzhiyun #endif
70*4882a593Smuzhiyun 
71*4882a593Smuzhiyun #define DEFAULT_DRXK_MPEG_LOCK_TIMEOUT 700
72*4882a593Smuzhiyun #define DEFAULT_DRXK_DEMOD_LOCK_TIMEOUT 500
73*4882a593Smuzhiyun 
74*4882a593Smuzhiyun #ifndef DRXK_KI_RAGC_ATV
75*4882a593Smuzhiyun #define DRXK_KI_RAGC_ATV   4
76*4882a593Smuzhiyun #endif
77*4882a593Smuzhiyun #ifndef DRXK_KI_IAGC_ATV
78*4882a593Smuzhiyun #define DRXK_KI_IAGC_ATV   6
79*4882a593Smuzhiyun #endif
80*4882a593Smuzhiyun #ifndef DRXK_KI_DAGC_ATV
81*4882a593Smuzhiyun #define DRXK_KI_DAGC_ATV   7
82*4882a593Smuzhiyun #endif
83*4882a593Smuzhiyun 
84*4882a593Smuzhiyun #ifndef DRXK_KI_RAGC_QAM
85*4882a593Smuzhiyun #define DRXK_KI_RAGC_QAM   3
86*4882a593Smuzhiyun #endif
87*4882a593Smuzhiyun #ifndef DRXK_KI_IAGC_QAM
88*4882a593Smuzhiyun #define DRXK_KI_IAGC_QAM   4
89*4882a593Smuzhiyun #endif
90*4882a593Smuzhiyun #ifndef DRXK_KI_DAGC_QAM
91*4882a593Smuzhiyun #define DRXK_KI_DAGC_QAM   7
92*4882a593Smuzhiyun #endif
93*4882a593Smuzhiyun #ifndef DRXK_KI_RAGC_DVBT
94*4882a593Smuzhiyun #define DRXK_KI_RAGC_DVBT  (IsA1WithPatchCode(state) ? 3 : 2)
95*4882a593Smuzhiyun #endif
96*4882a593Smuzhiyun #ifndef DRXK_KI_IAGC_DVBT
97*4882a593Smuzhiyun #define DRXK_KI_IAGC_DVBT  (IsA1WithPatchCode(state) ? 4 : 2)
98*4882a593Smuzhiyun #endif
99*4882a593Smuzhiyun #ifndef DRXK_KI_DAGC_DVBT
100*4882a593Smuzhiyun #define DRXK_KI_DAGC_DVBT  (IsA1WithPatchCode(state) ? 10 : 7)
101*4882a593Smuzhiyun #endif
102*4882a593Smuzhiyun 
103*4882a593Smuzhiyun #ifndef DRXK_AGC_DAC_OFFSET
104*4882a593Smuzhiyun #define DRXK_AGC_DAC_OFFSET (0x800)
105*4882a593Smuzhiyun #endif
106*4882a593Smuzhiyun 
107*4882a593Smuzhiyun #ifndef DRXK_BANDWIDTH_8MHZ_IN_HZ
108*4882a593Smuzhiyun #define DRXK_BANDWIDTH_8MHZ_IN_HZ  (0x8B8249L)
109*4882a593Smuzhiyun #endif
110*4882a593Smuzhiyun 
111*4882a593Smuzhiyun #ifndef DRXK_BANDWIDTH_7MHZ_IN_HZ
112*4882a593Smuzhiyun #define DRXK_BANDWIDTH_7MHZ_IN_HZ  (0x7A1200L)
113*4882a593Smuzhiyun #endif
114*4882a593Smuzhiyun 
115*4882a593Smuzhiyun #ifndef DRXK_BANDWIDTH_6MHZ_IN_HZ
116*4882a593Smuzhiyun #define DRXK_BANDWIDTH_6MHZ_IN_HZ  (0x68A1B6L)
117*4882a593Smuzhiyun #endif
118*4882a593Smuzhiyun 
119*4882a593Smuzhiyun #ifndef DRXK_QAM_SYMBOLRATE_MAX
120*4882a593Smuzhiyun #define DRXK_QAM_SYMBOLRATE_MAX         (7233000)
121*4882a593Smuzhiyun #endif
122*4882a593Smuzhiyun 
123*4882a593Smuzhiyun #define DRXK_BL_ROM_OFFSET_TAPS_DVBT    56
124*4882a593Smuzhiyun #define DRXK_BL_ROM_OFFSET_TAPS_ITU_A   64
125*4882a593Smuzhiyun #define DRXK_BL_ROM_OFFSET_TAPS_ITU_C   0x5FE0
126*4882a593Smuzhiyun #define DRXK_BL_ROM_OFFSET_TAPS_BG      24
127*4882a593Smuzhiyun #define DRXK_BL_ROM_OFFSET_TAPS_DKILLP  32
128*4882a593Smuzhiyun #define DRXK_BL_ROM_OFFSET_TAPS_NTSC    40
129*4882a593Smuzhiyun #define DRXK_BL_ROM_OFFSET_TAPS_FM      48
130*4882a593Smuzhiyun #define DRXK_BL_ROM_OFFSET_UCODE        0
131*4882a593Smuzhiyun 
132*4882a593Smuzhiyun #define DRXK_BLC_TIMEOUT                100
133*4882a593Smuzhiyun 
134*4882a593Smuzhiyun #define DRXK_BLCC_NR_ELEMENTS_TAPS      2
135*4882a593Smuzhiyun #define DRXK_BLCC_NR_ELEMENTS_UCODE     6
136*4882a593Smuzhiyun 
137*4882a593Smuzhiyun #define DRXK_BLDC_NR_ELEMENTS_TAPS      28
138*4882a593Smuzhiyun 
139*4882a593Smuzhiyun #ifndef DRXK_OFDM_NE_NOTCH_WIDTH
140*4882a593Smuzhiyun #define DRXK_OFDM_NE_NOTCH_WIDTH             (4)
141*4882a593Smuzhiyun #endif
142*4882a593Smuzhiyun 
143*4882a593Smuzhiyun #define DRXK_QAM_SL_SIG_POWER_QAM16       (40960)
144*4882a593Smuzhiyun #define DRXK_QAM_SL_SIG_POWER_QAM32       (20480)
145*4882a593Smuzhiyun #define DRXK_QAM_SL_SIG_POWER_QAM64       (43008)
146*4882a593Smuzhiyun #define DRXK_QAM_SL_SIG_POWER_QAM128      (20992)
147*4882a593Smuzhiyun #define DRXK_QAM_SL_SIG_POWER_QAM256      (43520)
148*4882a593Smuzhiyun 
149*4882a593Smuzhiyun static unsigned int debug;
150*4882a593Smuzhiyun module_param(debug, int, 0644);
151*4882a593Smuzhiyun MODULE_PARM_DESC(debug, "enable debug messages");
152*4882a593Smuzhiyun 
153*4882a593Smuzhiyun #define dprintk(level, fmt, arg...) do {				\
154*4882a593Smuzhiyun if (debug >= level)							\
155*4882a593Smuzhiyun 	printk(KERN_DEBUG KBUILD_MODNAME ": %s " fmt, __func__, ##arg);	\
156*4882a593Smuzhiyun } while (0)
157*4882a593Smuzhiyun 
Frac28a(u32 a,u32 c)158*4882a593Smuzhiyun static inline u32 Frac28a(u32 a, u32 c)
159*4882a593Smuzhiyun {
160*4882a593Smuzhiyun 	int i = 0;
161*4882a593Smuzhiyun 	u32 Q1 = 0;
162*4882a593Smuzhiyun 	u32 R0 = 0;
163*4882a593Smuzhiyun 
164*4882a593Smuzhiyun 	R0 = (a % c) << 4;	/* 32-28 == 4 shifts possible at max */
165*4882a593Smuzhiyun 	Q1 = a / c;		/*
166*4882a593Smuzhiyun 				 * integer part, only the 4 least significant
167*4882a593Smuzhiyun 				 * bits will be visible in the result
168*4882a593Smuzhiyun 				 */
169*4882a593Smuzhiyun 
170*4882a593Smuzhiyun 	/* division using radix 16, 7 nibbles in the result */
171*4882a593Smuzhiyun 	for (i = 0; i < 7; i++) {
172*4882a593Smuzhiyun 		Q1 = (Q1 << 4) | (R0 / c);
173*4882a593Smuzhiyun 		R0 = (R0 % c) << 4;
174*4882a593Smuzhiyun 	}
175*4882a593Smuzhiyun 	/* rounding */
176*4882a593Smuzhiyun 	if ((R0 >> 3) >= c)
177*4882a593Smuzhiyun 		Q1++;
178*4882a593Smuzhiyun 
179*4882a593Smuzhiyun 	return Q1;
180*4882a593Smuzhiyun }
181*4882a593Smuzhiyun 
log10times100(u32 value)182*4882a593Smuzhiyun static inline u32 log10times100(u32 value)
183*4882a593Smuzhiyun {
184*4882a593Smuzhiyun 	return (100L * intlog10(value)) >> 24;
185*4882a593Smuzhiyun }
186*4882a593Smuzhiyun 
187*4882a593Smuzhiyun /***************************************************************************/
188*4882a593Smuzhiyun /* I2C **********************************************************************/
189*4882a593Smuzhiyun /***************************************************************************/
190*4882a593Smuzhiyun 
drxk_i2c_lock(struct drxk_state * state)191*4882a593Smuzhiyun static int drxk_i2c_lock(struct drxk_state *state)
192*4882a593Smuzhiyun {
193*4882a593Smuzhiyun 	i2c_lock_bus(state->i2c, I2C_LOCK_SEGMENT);
194*4882a593Smuzhiyun 	state->drxk_i2c_exclusive_lock = true;
195*4882a593Smuzhiyun 
196*4882a593Smuzhiyun 	return 0;
197*4882a593Smuzhiyun }
198*4882a593Smuzhiyun 
drxk_i2c_unlock(struct drxk_state * state)199*4882a593Smuzhiyun static void drxk_i2c_unlock(struct drxk_state *state)
200*4882a593Smuzhiyun {
201*4882a593Smuzhiyun 	if (!state->drxk_i2c_exclusive_lock)
202*4882a593Smuzhiyun 		return;
203*4882a593Smuzhiyun 
204*4882a593Smuzhiyun 	i2c_unlock_bus(state->i2c, I2C_LOCK_SEGMENT);
205*4882a593Smuzhiyun 	state->drxk_i2c_exclusive_lock = false;
206*4882a593Smuzhiyun }
207*4882a593Smuzhiyun 
drxk_i2c_transfer(struct drxk_state * state,struct i2c_msg * msgs,unsigned len)208*4882a593Smuzhiyun static int drxk_i2c_transfer(struct drxk_state *state, struct i2c_msg *msgs,
209*4882a593Smuzhiyun 			     unsigned len)
210*4882a593Smuzhiyun {
211*4882a593Smuzhiyun 	if (state->drxk_i2c_exclusive_lock)
212*4882a593Smuzhiyun 		return __i2c_transfer(state->i2c, msgs, len);
213*4882a593Smuzhiyun 	else
214*4882a593Smuzhiyun 		return i2c_transfer(state->i2c, msgs, len);
215*4882a593Smuzhiyun }
216*4882a593Smuzhiyun 
i2c_read1(struct drxk_state * state,u8 adr,u8 * val)217*4882a593Smuzhiyun static int i2c_read1(struct drxk_state *state, u8 adr, u8 *val)
218*4882a593Smuzhiyun {
219*4882a593Smuzhiyun 	struct i2c_msg msgs[1] = { {.addr = adr, .flags = I2C_M_RD,
220*4882a593Smuzhiyun 				    .buf = val, .len = 1}
221*4882a593Smuzhiyun 	};
222*4882a593Smuzhiyun 
223*4882a593Smuzhiyun 	return drxk_i2c_transfer(state, msgs, 1);
224*4882a593Smuzhiyun }
225*4882a593Smuzhiyun 
i2c_write(struct drxk_state * state,u8 adr,u8 * data,int len)226*4882a593Smuzhiyun static int i2c_write(struct drxk_state *state, u8 adr, u8 *data, int len)
227*4882a593Smuzhiyun {
228*4882a593Smuzhiyun 	int status;
229*4882a593Smuzhiyun 	struct i2c_msg msg = {
230*4882a593Smuzhiyun 	    .addr = adr, .flags = 0, .buf = data, .len = len };
231*4882a593Smuzhiyun 
232*4882a593Smuzhiyun 	dprintk(3, ":");
233*4882a593Smuzhiyun 	if (debug > 2) {
234*4882a593Smuzhiyun 		int i;
235*4882a593Smuzhiyun 		for (i = 0; i < len; i++)
236*4882a593Smuzhiyun 			pr_cont(" %02x", data[i]);
237*4882a593Smuzhiyun 		pr_cont("\n");
238*4882a593Smuzhiyun 	}
239*4882a593Smuzhiyun 	status = drxk_i2c_transfer(state, &msg, 1);
240*4882a593Smuzhiyun 	if (status >= 0 && status != 1)
241*4882a593Smuzhiyun 		status = -EIO;
242*4882a593Smuzhiyun 
243*4882a593Smuzhiyun 	if (status < 0)
244*4882a593Smuzhiyun 		pr_err("i2c write error at addr 0x%02x\n", adr);
245*4882a593Smuzhiyun 
246*4882a593Smuzhiyun 	return status;
247*4882a593Smuzhiyun }
248*4882a593Smuzhiyun 
i2c_read(struct drxk_state * state,u8 adr,u8 * msg,int len,u8 * answ,int alen)249*4882a593Smuzhiyun static int i2c_read(struct drxk_state *state,
250*4882a593Smuzhiyun 		    u8 adr, u8 *msg, int len, u8 *answ, int alen)
251*4882a593Smuzhiyun {
252*4882a593Smuzhiyun 	int status;
253*4882a593Smuzhiyun 	struct i2c_msg msgs[2] = {
254*4882a593Smuzhiyun 		{.addr = adr, .flags = 0,
255*4882a593Smuzhiyun 				    .buf = msg, .len = len},
256*4882a593Smuzhiyun 		{.addr = adr, .flags = I2C_M_RD,
257*4882a593Smuzhiyun 		 .buf = answ, .len = alen}
258*4882a593Smuzhiyun 	};
259*4882a593Smuzhiyun 
260*4882a593Smuzhiyun 	status = drxk_i2c_transfer(state, msgs, 2);
261*4882a593Smuzhiyun 	if (status != 2) {
262*4882a593Smuzhiyun 		if (debug > 2)
263*4882a593Smuzhiyun 			pr_cont(": ERROR!\n");
264*4882a593Smuzhiyun 		if (status >= 0)
265*4882a593Smuzhiyun 			status = -EIO;
266*4882a593Smuzhiyun 
267*4882a593Smuzhiyun 		pr_err("i2c read error at addr 0x%02x\n", adr);
268*4882a593Smuzhiyun 		return status;
269*4882a593Smuzhiyun 	}
270*4882a593Smuzhiyun 	if (debug > 2) {
271*4882a593Smuzhiyun 		int i;
272*4882a593Smuzhiyun 		dprintk(2, ": read from");
273*4882a593Smuzhiyun 		for (i = 0; i < len; i++)
274*4882a593Smuzhiyun 			pr_cont(" %02x", msg[i]);
275*4882a593Smuzhiyun 		pr_cont(", value = ");
276*4882a593Smuzhiyun 		for (i = 0; i < alen; i++)
277*4882a593Smuzhiyun 			pr_cont(" %02x", answ[i]);
278*4882a593Smuzhiyun 		pr_cont("\n");
279*4882a593Smuzhiyun 	}
280*4882a593Smuzhiyun 	return 0;
281*4882a593Smuzhiyun }
282*4882a593Smuzhiyun 
read16_flags(struct drxk_state * state,u32 reg,u16 * data,u8 flags)283*4882a593Smuzhiyun static int read16_flags(struct drxk_state *state, u32 reg, u16 *data, u8 flags)
284*4882a593Smuzhiyun {
285*4882a593Smuzhiyun 	int status;
286*4882a593Smuzhiyun 	u8 adr = state->demod_address, mm1[4], mm2[2], len;
287*4882a593Smuzhiyun 
288*4882a593Smuzhiyun 	if (state->single_master)
289*4882a593Smuzhiyun 		flags |= 0xC0;
290*4882a593Smuzhiyun 
291*4882a593Smuzhiyun 	if (DRXDAP_FASI_LONG_FORMAT(reg) || (flags != 0)) {
292*4882a593Smuzhiyun 		mm1[0] = (((reg << 1) & 0xFF) | 0x01);
293*4882a593Smuzhiyun 		mm1[1] = ((reg >> 16) & 0xFF);
294*4882a593Smuzhiyun 		mm1[2] = ((reg >> 24) & 0xFF) | flags;
295*4882a593Smuzhiyun 		mm1[3] = ((reg >> 7) & 0xFF);
296*4882a593Smuzhiyun 		len = 4;
297*4882a593Smuzhiyun 	} else {
298*4882a593Smuzhiyun 		mm1[0] = ((reg << 1) & 0xFF);
299*4882a593Smuzhiyun 		mm1[1] = (((reg >> 16) & 0x0F) | ((reg >> 18) & 0xF0));
300*4882a593Smuzhiyun 		len = 2;
301*4882a593Smuzhiyun 	}
302*4882a593Smuzhiyun 	dprintk(2, "(0x%08x, 0x%02x)\n", reg, flags);
303*4882a593Smuzhiyun 	status = i2c_read(state, adr, mm1, len, mm2, 2);
304*4882a593Smuzhiyun 	if (status < 0)
305*4882a593Smuzhiyun 		return status;
306*4882a593Smuzhiyun 	if (data)
307*4882a593Smuzhiyun 		*data = mm2[0] | (mm2[1] << 8);
308*4882a593Smuzhiyun 
309*4882a593Smuzhiyun 	return 0;
310*4882a593Smuzhiyun }
311*4882a593Smuzhiyun 
read16(struct drxk_state * state,u32 reg,u16 * data)312*4882a593Smuzhiyun static int read16(struct drxk_state *state, u32 reg, u16 *data)
313*4882a593Smuzhiyun {
314*4882a593Smuzhiyun 	return read16_flags(state, reg, data, 0);
315*4882a593Smuzhiyun }
316*4882a593Smuzhiyun 
read32_flags(struct drxk_state * state,u32 reg,u32 * data,u8 flags)317*4882a593Smuzhiyun static int read32_flags(struct drxk_state *state, u32 reg, u32 *data, u8 flags)
318*4882a593Smuzhiyun {
319*4882a593Smuzhiyun 	int status;
320*4882a593Smuzhiyun 	u8 adr = state->demod_address, mm1[4], mm2[4], len;
321*4882a593Smuzhiyun 
322*4882a593Smuzhiyun 	if (state->single_master)
323*4882a593Smuzhiyun 		flags |= 0xC0;
324*4882a593Smuzhiyun 
325*4882a593Smuzhiyun 	if (DRXDAP_FASI_LONG_FORMAT(reg) || (flags != 0)) {
326*4882a593Smuzhiyun 		mm1[0] = (((reg << 1) & 0xFF) | 0x01);
327*4882a593Smuzhiyun 		mm1[1] = ((reg >> 16) & 0xFF);
328*4882a593Smuzhiyun 		mm1[2] = ((reg >> 24) & 0xFF) | flags;
329*4882a593Smuzhiyun 		mm1[3] = ((reg >> 7) & 0xFF);
330*4882a593Smuzhiyun 		len = 4;
331*4882a593Smuzhiyun 	} else {
332*4882a593Smuzhiyun 		mm1[0] = ((reg << 1) & 0xFF);
333*4882a593Smuzhiyun 		mm1[1] = (((reg >> 16) & 0x0F) | ((reg >> 18) & 0xF0));
334*4882a593Smuzhiyun 		len = 2;
335*4882a593Smuzhiyun 	}
336*4882a593Smuzhiyun 	dprintk(2, "(0x%08x, 0x%02x)\n", reg, flags);
337*4882a593Smuzhiyun 	status = i2c_read(state, adr, mm1, len, mm2, 4);
338*4882a593Smuzhiyun 	if (status < 0)
339*4882a593Smuzhiyun 		return status;
340*4882a593Smuzhiyun 	if (data)
341*4882a593Smuzhiyun 		*data = mm2[0] | (mm2[1] << 8) |
342*4882a593Smuzhiyun 		    (mm2[2] << 16) | (mm2[3] << 24);
343*4882a593Smuzhiyun 
344*4882a593Smuzhiyun 	return 0;
345*4882a593Smuzhiyun }
346*4882a593Smuzhiyun 
read32(struct drxk_state * state,u32 reg,u32 * data)347*4882a593Smuzhiyun static int read32(struct drxk_state *state, u32 reg, u32 *data)
348*4882a593Smuzhiyun {
349*4882a593Smuzhiyun 	return read32_flags(state, reg, data, 0);
350*4882a593Smuzhiyun }
351*4882a593Smuzhiyun 
write16_flags(struct drxk_state * state,u32 reg,u16 data,u8 flags)352*4882a593Smuzhiyun static int write16_flags(struct drxk_state *state, u32 reg, u16 data, u8 flags)
353*4882a593Smuzhiyun {
354*4882a593Smuzhiyun 	u8 adr = state->demod_address, mm[6], len;
355*4882a593Smuzhiyun 
356*4882a593Smuzhiyun 	if (state->single_master)
357*4882a593Smuzhiyun 		flags |= 0xC0;
358*4882a593Smuzhiyun 	if (DRXDAP_FASI_LONG_FORMAT(reg) || (flags != 0)) {
359*4882a593Smuzhiyun 		mm[0] = (((reg << 1) & 0xFF) | 0x01);
360*4882a593Smuzhiyun 		mm[1] = ((reg >> 16) & 0xFF);
361*4882a593Smuzhiyun 		mm[2] = ((reg >> 24) & 0xFF) | flags;
362*4882a593Smuzhiyun 		mm[3] = ((reg >> 7) & 0xFF);
363*4882a593Smuzhiyun 		len = 4;
364*4882a593Smuzhiyun 	} else {
365*4882a593Smuzhiyun 		mm[0] = ((reg << 1) & 0xFF);
366*4882a593Smuzhiyun 		mm[1] = (((reg >> 16) & 0x0F) | ((reg >> 18) & 0xF0));
367*4882a593Smuzhiyun 		len = 2;
368*4882a593Smuzhiyun 	}
369*4882a593Smuzhiyun 	mm[len] = data & 0xff;
370*4882a593Smuzhiyun 	mm[len + 1] = (data >> 8) & 0xff;
371*4882a593Smuzhiyun 
372*4882a593Smuzhiyun 	dprintk(2, "(0x%08x, 0x%04x, 0x%02x)\n", reg, data, flags);
373*4882a593Smuzhiyun 	return i2c_write(state, adr, mm, len + 2);
374*4882a593Smuzhiyun }
375*4882a593Smuzhiyun 
write16(struct drxk_state * state,u32 reg,u16 data)376*4882a593Smuzhiyun static int write16(struct drxk_state *state, u32 reg, u16 data)
377*4882a593Smuzhiyun {
378*4882a593Smuzhiyun 	return write16_flags(state, reg, data, 0);
379*4882a593Smuzhiyun }
380*4882a593Smuzhiyun 
write32_flags(struct drxk_state * state,u32 reg,u32 data,u8 flags)381*4882a593Smuzhiyun static int write32_flags(struct drxk_state *state, u32 reg, u32 data, u8 flags)
382*4882a593Smuzhiyun {
383*4882a593Smuzhiyun 	u8 adr = state->demod_address, mm[8], len;
384*4882a593Smuzhiyun 
385*4882a593Smuzhiyun 	if (state->single_master)
386*4882a593Smuzhiyun 		flags |= 0xC0;
387*4882a593Smuzhiyun 	if (DRXDAP_FASI_LONG_FORMAT(reg) || (flags != 0)) {
388*4882a593Smuzhiyun 		mm[0] = (((reg << 1) & 0xFF) | 0x01);
389*4882a593Smuzhiyun 		mm[1] = ((reg >> 16) & 0xFF);
390*4882a593Smuzhiyun 		mm[2] = ((reg >> 24) & 0xFF) | flags;
391*4882a593Smuzhiyun 		mm[3] = ((reg >> 7) & 0xFF);
392*4882a593Smuzhiyun 		len = 4;
393*4882a593Smuzhiyun 	} else {
394*4882a593Smuzhiyun 		mm[0] = ((reg << 1) & 0xFF);
395*4882a593Smuzhiyun 		mm[1] = (((reg >> 16) & 0x0F) | ((reg >> 18) & 0xF0));
396*4882a593Smuzhiyun 		len = 2;
397*4882a593Smuzhiyun 	}
398*4882a593Smuzhiyun 	mm[len] = data & 0xff;
399*4882a593Smuzhiyun 	mm[len + 1] = (data >> 8) & 0xff;
400*4882a593Smuzhiyun 	mm[len + 2] = (data >> 16) & 0xff;
401*4882a593Smuzhiyun 	mm[len + 3] = (data >> 24) & 0xff;
402*4882a593Smuzhiyun 	dprintk(2, "(0x%08x, 0x%08x, 0x%02x)\n", reg, data, flags);
403*4882a593Smuzhiyun 
404*4882a593Smuzhiyun 	return i2c_write(state, adr, mm, len + 4);
405*4882a593Smuzhiyun }
406*4882a593Smuzhiyun 
write32(struct drxk_state * state,u32 reg,u32 data)407*4882a593Smuzhiyun static int write32(struct drxk_state *state, u32 reg, u32 data)
408*4882a593Smuzhiyun {
409*4882a593Smuzhiyun 	return write32_flags(state, reg, data, 0);
410*4882a593Smuzhiyun }
411*4882a593Smuzhiyun 
write_block(struct drxk_state * state,u32 address,const int block_size,const u8 p_block[])412*4882a593Smuzhiyun static int write_block(struct drxk_state *state, u32 address,
413*4882a593Smuzhiyun 		      const int block_size, const u8 p_block[])
414*4882a593Smuzhiyun {
415*4882a593Smuzhiyun 	int status = 0, blk_size = block_size;
416*4882a593Smuzhiyun 	u8 flags = 0;
417*4882a593Smuzhiyun 
418*4882a593Smuzhiyun 	if (state->single_master)
419*4882a593Smuzhiyun 		flags |= 0xC0;
420*4882a593Smuzhiyun 
421*4882a593Smuzhiyun 	while (blk_size > 0) {
422*4882a593Smuzhiyun 		int chunk = blk_size > state->m_chunk_size ?
423*4882a593Smuzhiyun 		    state->m_chunk_size : blk_size;
424*4882a593Smuzhiyun 		u8 *adr_buf = &state->chunk[0];
425*4882a593Smuzhiyun 		u32 adr_length = 0;
426*4882a593Smuzhiyun 
427*4882a593Smuzhiyun 		if (DRXDAP_FASI_LONG_FORMAT(address) || (flags != 0)) {
428*4882a593Smuzhiyun 			adr_buf[0] = (((address << 1) & 0xFF) | 0x01);
429*4882a593Smuzhiyun 			adr_buf[1] = ((address >> 16) & 0xFF);
430*4882a593Smuzhiyun 			adr_buf[2] = ((address >> 24) & 0xFF);
431*4882a593Smuzhiyun 			adr_buf[3] = ((address >> 7) & 0xFF);
432*4882a593Smuzhiyun 			adr_buf[2] |= flags;
433*4882a593Smuzhiyun 			adr_length = 4;
434*4882a593Smuzhiyun 			if (chunk == state->m_chunk_size)
435*4882a593Smuzhiyun 				chunk -= 2;
436*4882a593Smuzhiyun 		} else {
437*4882a593Smuzhiyun 			adr_buf[0] = ((address << 1) & 0xFF);
438*4882a593Smuzhiyun 			adr_buf[1] = (((address >> 16) & 0x0F) |
439*4882a593Smuzhiyun 				     ((address >> 18) & 0xF0));
440*4882a593Smuzhiyun 			adr_length = 2;
441*4882a593Smuzhiyun 		}
442*4882a593Smuzhiyun 		memcpy(&state->chunk[adr_length], p_block, chunk);
443*4882a593Smuzhiyun 		dprintk(2, "(0x%08x, 0x%02x)\n", address, flags);
444*4882a593Smuzhiyun 		if (debug > 1) {
445*4882a593Smuzhiyun 			int i;
446*4882a593Smuzhiyun 			if (p_block)
447*4882a593Smuzhiyun 				for (i = 0; i < chunk; i++)
448*4882a593Smuzhiyun 					pr_cont(" %02x", p_block[i]);
449*4882a593Smuzhiyun 			pr_cont("\n");
450*4882a593Smuzhiyun 		}
451*4882a593Smuzhiyun 		status = i2c_write(state, state->demod_address,
452*4882a593Smuzhiyun 				   &state->chunk[0], chunk + adr_length);
453*4882a593Smuzhiyun 		if (status < 0) {
454*4882a593Smuzhiyun 			pr_err("%s: i2c write error at addr 0x%02x\n",
455*4882a593Smuzhiyun 			       __func__, address);
456*4882a593Smuzhiyun 			break;
457*4882a593Smuzhiyun 		}
458*4882a593Smuzhiyun 		p_block += chunk;
459*4882a593Smuzhiyun 		address += (chunk >> 1);
460*4882a593Smuzhiyun 		blk_size -= chunk;
461*4882a593Smuzhiyun 	}
462*4882a593Smuzhiyun 	return status;
463*4882a593Smuzhiyun }
464*4882a593Smuzhiyun 
465*4882a593Smuzhiyun #ifndef DRXK_MAX_RETRIES_POWERUP
466*4882a593Smuzhiyun #define DRXK_MAX_RETRIES_POWERUP 20
467*4882a593Smuzhiyun #endif
468*4882a593Smuzhiyun 
power_up_device(struct drxk_state * state)469*4882a593Smuzhiyun static int power_up_device(struct drxk_state *state)
470*4882a593Smuzhiyun {
471*4882a593Smuzhiyun 	int status;
472*4882a593Smuzhiyun 	u8 data = 0;
473*4882a593Smuzhiyun 	u16 retry_count = 0;
474*4882a593Smuzhiyun 
475*4882a593Smuzhiyun 	dprintk(1, "\n");
476*4882a593Smuzhiyun 
477*4882a593Smuzhiyun 	status = i2c_read1(state, state->demod_address, &data);
478*4882a593Smuzhiyun 	if (status < 0) {
479*4882a593Smuzhiyun 		do {
480*4882a593Smuzhiyun 			data = 0;
481*4882a593Smuzhiyun 			status = i2c_write(state, state->demod_address,
482*4882a593Smuzhiyun 					   &data, 1);
483*4882a593Smuzhiyun 			usleep_range(10000, 11000);
484*4882a593Smuzhiyun 			retry_count++;
485*4882a593Smuzhiyun 			if (status < 0)
486*4882a593Smuzhiyun 				continue;
487*4882a593Smuzhiyun 			status = i2c_read1(state, state->demod_address,
488*4882a593Smuzhiyun 					   &data);
489*4882a593Smuzhiyun 		} while (status < 0 &&
490*4882a593Smuzhiyun 			 (retry_count < DRXK_MAX_RETRIES_POWERUP));
491*4882a593Smuzhiyun 		if (status < 0 && retry_count >= DRXK_MAX_RETRIES_POWERUP)
492*4882a593Smuzhiyun 			goto error;
493*4882a593Smuzhiyun 	}
494*4882a593Smuzhiyun 
495*4882a593Smuzhiyun 	/* Make sure all clk domains are active */
496*4882a593Smuzhiyun 	status = write16(state, SIO_CC_PWD_MODE__A, SIO_CC_PWD_MODE_LEVEL_NONE);
497*4882a593Smuzhiyun 	if (status < 0)
498*4882a593Smuzhiyun 		goto error;
499*4882a593Smuzhiyun 	status = write16(state, SIO_CC_UPDATE__A, SIO_CC_UPDATE_KEY);
500*4882a593Smuzhiyun 	if (status < 0)
501*4882a593Smuzhiyun 		goto error;
502*4882a593Smuzhiyun 	/* Enable pll lock tests */
503*4882a593Smuzhiyun 	status = write16(state, SIO_CC_PLL_LOCK__A, 1);
504*4882a593Smuzhiyun 	if (status < 0)
505*4882a593Smuzhiyun 		goto error;
506*4882a593Smuzhiyun 
507*4882a593Smuzhiyun 	state->m_current_power_mode = DRX_POWER_UP;
508*4882a593Smuzhiyun 
509*4882a593Smuzhiyun error:
510*4882a593Smuzhiyun 	if (status < 0)
511*4882a593Smuzhiyun 		pr_err("Error %d on %s\n", status, __func__);
512*4882a593Smuzhiyun 
513*4882a593Smuzhiyun 	return status;
514*4882a593Smuzhiyun }
515*4882a593Smuzhiyun 
516*4882a593Smuzhiyun 
init_state(struct drxk_state * state)517*4882a593Smuzhiyun static int init_state(struct drxk_state *state)
518*4882a593Smuzhiyun {
519*4882a593Smuzhiyun 	/*
520*4882a593Smuzhiyun 	 * FIXME: most (all?) of the values below should be moved into
521*4882a593Smuzhiyun 	 * struct drxk_config, as they are probably board-specific
522*4882a593Smuzhiyun 	 */
523*4882a593Smuzhiyun 	u32 ul_vsb_if_agc_mode = DRXK_AGC_CTRL_AUTO;
524*4882a593Smuzhiyun 	u32 ul_vsb_if_agc_output_level = 0;
525*4882a593Smuzhiyun 	u32 ul_vsb_if_agc_min_level = 0;
526*4882a593Smuzhiyun 	u32 ul_vsb_if_agc_max_level = 0x7FFF;
527*4882a593Smuzhiyun 	u32 ul_vsb_if_agc_speed = 3;
528*4882a593Smuzhiyun 
529*4882a593Smuzhiyun 	u32 ul_vsb_rf_agc_mode = DRXK_AGC_CTRL_AUTO;
530*4882a593Smuzhiyun 	u32 ul_vsb_rf_agc_output_level = 0;
531*4882a593Smuzhiyun 	u32 ul_vsb_rf_agc_min_level = 0;
532*4882a593Smuzhiyun 	u32 ul_vsb_rf_agc_max_level = 0x7FFF;
533*4882a593Smuzhiyun 	u32 ul_vsb_rf_agc_speed = 3;
534*4882a593Smuzhiyun 	u32 ul_vsb_rf_agc_top = 9500;
535*4882a593Smuzhiyun 	u32 ul_vsb_rf_agc_cut_off_current = 4000;
536*4882a593Smuzhiyun 
537*4882a593Smuzhiyun 	u32 ul_atv_if_agc_mode = DRXK_AGC_CTRL_AUTO;
538*4882a593Smuzhiyun 	u32 ul_atv_if_agc_output_level = 0;
539*4882a593Smuzhiyun 	u32 ul_atv_if_agc_min_level = 0;
540*4882a593Smuzhiyun 	u32 ul_atv_if_agc_max_level = 0;
541*4882a593Smuzhiyun 	u32 ul_atv_if_agc_speed = 3;
542*4882a593Smuzhiyun 
543*4882a593Smuzhiyun 	u32 ul_atv_rf_agc_mode = DRXK_AGC_CTRL_OFF;
544*4882a593Smuzhiyun 	u32 ul_atv_rf_agc_output_level = 0;
545*4882a593Smuzhiyun 	u32 ul_atv_rf_agc_min_level = 0;
546*4882a593Smuzhiyun 	u32 ul_atv_rf_agc_max_level = 0;
547*4882a593Smuzhiyun 	u32 ul_atv_rf_agc_top = 9500;
548*4882a593Smuzhiyun 	u32 ul_atv_rf_agc_cut_off_current = 4000;
549*4882a593Smuzhiyun 	u32 ul_atv_rf_agc_speed = 3;
550*4882a593Smuzhiyun 
551*4882a593Smuzhiyun 	u32 ulQual83 = DEFAULT_MER_83;
552*4882a593Smuzhiyun 	u32 ulQual93 = DEFAULT_MER_93;
553*4882a593Smuzhiyun 
554*4882a593Smuzhiyun 	u32 ul_mpeg_lock_time_out = DEFAULT_DRXK_MPEG_LOCK_TIMEOUT;
555*4882a593Smuzhiyun 	u32 ul_demod_lock_time_out = DEFAULT_DRXK_DEMOD_LOCK_TIMEOUT;
556*4882a593Smuzhiyun 
557*4882a593Smuzhiyun 	/* io_pad_cfg register (8 bit reg.) MSB bit is 1 (default value) */
558*4882a593Smuzhiyun 	/* io_pad_cfg_mode output mode is drive always */
559*4882a593Smuzhiyun 	/* io_pad_cfg_drive is set to power 2 (23 mA) */
560*4882a593Smuzhiyun 	u32 ul_gpio_cfg = 0x0113;
561*4882a593Smuzhiyun 	u32 ul_invert_ts_clock = 0;
562*4882a593Smuzhiyun 	u32 ul_ts_data_strength = DRXK_MPEG_SERIAL_OUTPUT_PIN_DRIVE_STRENGTH;
563*4882a593Smuzhiyun 	u32 ul_dvbt_bitrate = 50000000;
564*4882a593Smuzhiyun 	u32 ul_dvbc_bitrate = DRXK_QAM_SYMBOLRATE_MAX * 8;
565*4882a593Smuzhiyun 
566*4882a593Smuzhiyun 	u32 ul_insert_rs_byte = 0;
567*4882a593Smuzhiyun 
568*4882a593Smuzhiyun 	u32 ul_rf_mirror = 1;
569*4882a593Smuzhiyun 	u32 ul_power_down = 0;
570*4882a593Smuzhiyun 
571*4882a593Smuzhiyun 	dprintk(1, "\n");
572*4882a593Smuzhiyun 
573*4882a593Smuzhiyun 	state->m_has_lna = false;
574*4882a593Smuzhiyun 	state->m_has_dvbt = false;
575*4882a593Smuzhiyun 	state->m_has_dvbc = false;
576*4882a593Smuzhiyun 	state->m_has_atv = false;
577*4882a593Smuzhiyun 	state->m_has_oob = false;
578*4882a593Smuzhiyun 	state->m_has_audio = false;
579*4882a593Smuzhiyun 
580*4882a593Smuzhiyun 	if (!state->m_chunk_size)
581*4882a593Smuzhiyun 		state->m_chunk_size = 124;
582*4882a593Smuzhiyun 
583*4882a593Smuzhiyun 	state->m_osc_clock_freq = 0;
584*4882a593Smuzhiyun 	state->m_smart_ant_inverted = false;
585*4882a593Smuzhiyun 	state->m_b_p_down_open_bridge = false;
586*4882a593Smuzhiyun 
587*4882a593Smuzhiyun 	/* real system clock frequency in kHz */
588*4882a593Smuzhiyun 	state->m_sys_clock_freq = 151875;
589*4882a593Smuzhiyun 	/* Timing div, 250ns/Psys */
590*4882a593Smuzhiyun 	/* Timing div, = (delay (nano seconds) * sysclk (kHz))/ 1000 */
591*4882a593Smuzhiyun 	state->m_hi_cfg_timing_div = ((state->m_sys_clock_freq / 1000) *
592*4882a593Smuzhiyun 				   HI_I2C_DELAY) / 1000;
593*4882a593Smuzhiyun 	/* Clipping */
594*4882a593Smuzhiyun 	if (state->m_hi_cfg_timing_div > SIO_HI_RA_RAM_PAR_2_CFG_DIV__M)
595*4882a593Smuzhiyun 		state->m_hi_cfg_timing_div = SIO_HI_RA_RAM_PAR_2_CFG_DIV__M;
596*4882a593Smuzhiyun 	state->m_hi_cfg_wake_up_key = (state->demod_address << 1);
597*4882a593Smuzhiyun 	/* port/bridge/power down ctrl */
598*4882a593Smuzhiyun 	state->m_hi_cfg_ctrl = SIO_HI_RA_RAM_PAR_5_CFG_SLV0_SLAVE;
599*4882a593Smuzhiyun 
600*4882a593Smuzhiyun 	state->m_b_power_down = (ul_power_down != 0);
601*4882a593Smuzhiyun 
602*4882a593Smuzhiyun 	state->m_drxk_a3_patch_code = false;
603*4882a593Smuzhiyun 
604*4882a593Smuzhiyun 	/* Init AGC and PGA parameters */
605*4882a593Smuzhiyun 	/* VSB IF */
606*4882a593Smuzhiyun 	state->m_vsb_if_agc_cfg.ctrl_mode = ul_vsb_if_agc_mode;
607*4882a593Smuzhiyun 	state->m_vsb_if_agc_cfg.output_level = ul_vsb_if_agc_output_level;
608*4882a593Smuzhiyun 	state->m_vsb_if_agc_cfg.min_output_level = ul_vsb_if_agc_min_level;
609*4882a593Smuzhiyun 	state->m_vsb_if_agc_cfg.max_output_level = ul_vsb_if_agc_max_level;
610*4882a593Smuzhiyun 	state->m_vsb_if_agc_cfg.speed = ul_vsb_if_agc_speed;
611*4882a593Smuzhiyun 	state->m_vsb_pga_cfg = 140;
612*4882a593Smuzhiyun 
613*4882a593Smuzhiyun 	/* VSB RF */
614*4882a593Smuzhiyun 	state->m_vsb_rf_agc_cfg.ctrl_mode = ul_vsb_rf_agc_mode;
615*4882a593Smuzhiyun 	state->m_vsb_rf_agc_cfg.output_level = ul_vsb_rf_agc_output_level;
616*4882a593Smuzhiyun 	state->m_vsb_rf_agc_cfg.min_output_level = ul_vsb_rf_agc_min_level;
617*4882a593Smuzhiyun 	state->m_vsb_rf_agc_cfg.max_output_level = ul_vsb_rf_agc_max_level;
618*4882a593Smuzhiyun 	state->m_vsb_rf_agc_cfg.speed = ul_vsb_rf_agc_speed;
619*4882a593Smuzhiyun 	state->m_vsb_rf_agc_cfg.top = ul_vsb_rf_agc_top;
620*4882a593Smuzhiyun 	state->m_vsb_rf_agc_cfg.cut_off_current = ul_vsb_rf_agc_cut_off_current;
621*4882a593Smuzhiyun 	state->m_vsb_pre_saw_cfg.reference = 0x07;
622*4882a593Smuzhiyun 	state->m_vsb_pre_saw_cfg.use_pre_saw = true;
623*4882a593Smuzhiyun 
624*4882a593Smuzhiyun 	state->m_Quality83percent = DEFAULT_MER_83;
625*4882a593Smuzhiyun 	state->m_Quality93percent = DEFAULT_MER_93;
626*4882a593Smuzhiyun 	if (ulQual93 <= 500 && ulQual83 < ulQual93) {
627*4882a593Smuzhiyun 		state->m_Quality83percent = ulQual83;
628*4882a593Smuzhiyun 		state->m_Quality93percent = ulQual93;
629*4882a593Smuzhiyun 	}
630*4882a593Smuzhiyun 
631*4882a593Smuzhiyun 	/* ATV IF */
632*4882a593Smuzhiyun 	state->m_atv_if_agc_cfg.ctrl_mode = ul_atv_if_agc_mode;
633*4882a593Smuzhiyun 	state->m_atv_if_agc_cfg.output_level = ul_atv_if_agc_output_level;
634*4882a593Smuzhiyun 	state->m_atv_if_agc_cfg.min_output_level = ul_atv_if_agc_min_level;
635*4882a593Smuzhiyun 	state->m_atv_if_agc_cfg.max_output_level = ul_atv_if_agc_max_level;
636*4882a593Smuzhiyun 	state->m_atv_if_agc_cfg.speed = ul_atv_if_agc_speed;
637*4882a593Smuzhiyun 
638*4882a593Smuzhiyun 	/* ATV RF */
639*4882a593Smuzhiyun 	state->m_atv_rf_agc_cfg.ctrl_mode = ul_atv_rf_agc_mode;
640*4882a593Smuzhiyun 	state->m_atv_rf_agc_cfg.output_level = ul_atv_rf_agc_output_level;
641*4882a593Smuzhiyun 	state->m_atv_rf_agc_cfg.min_output_level = ul_atv_rf_agc_min_level;
642*4882a593Smuzhiyun 	state->m_atv_rf_agc_cfg.max_output_level = ul_atv_rf_agc_max_level;
643*4882a593Smuzhiyun 	state->m_atv_rf_agc_cfg.speed = ul_atv_rf_agc_speed;
644*4882a593Smuzhiyun 	state->m_atv_rf_agc_cfg.top = ul_atv_rf_agc_top;
645*4882a593Smuzhiyun 	state->m_atv_rf_agc_cfg.cut_off_current = ul_atv_rf_agc_cut_off_current;
646*4882a593Smuzhiyun 	state->m_atv_pre_saw_cfg.reference = 0x04;
647*4882a593Smuzhiyun 	state->m_atv_pre_saw_cfg.use_pre_saw = true;
648*4882a593Smuzhiyun 
649*4882a593Smuzhiyun 
650*4882a593Smuzhiyun 	/* DVBT RF */
651*4882a593Smuzhiyun 	state->m_dvbt_rf_agc_cfg.ctrl_mode = DRXK_AGC_CTRL_OFF;
652*4882a593Smuzhiyun 	state->m_dvbt_rf_agc_cfg.output_level = 0;
653*4882a593Smuzhiyun 	state->m_dvbt_rf_agc_cfg.min_output_level = 0;
654*4882a593Smuzhiyun 	state->m_dvbt_rf_agc_cfg.max_output_level = 0xFFFF;
655*4882a593Smuzhiyun 	state->m_dvbt_rf_agc_cfg.top = 0x2100;
656*4882a593Smuzhiyun 	state->m_dvbt_rf_agc_cfg.cut_off_current = 4000;
657*4882a593Smuzhiyun 	state->m_dvbt_rf_agc_cfg.speed = 1;
658*4882a593Smuzhiyun 
659*4882a593Smuzhiyun 
660*4882a593Smuzhiyun 	/* DVBT IF */
661*4882a593Smuzhiyun 	state->m_dvbt_if_agc_cfg.ctrl_mode = DRXK_AGC_CTRL_AUTO;
662*4882a593Smuzhiyun 	state->m_dvbt_if_agc_cfg.output_level = 0;
663*4882a593Smuzhiyun 	state->m_dvbt_if_agc_cfg.min_output_level = 0;
664*4882a593Smuzhiyun 	state->m_dvbt_if_agc_cfg.max_output_level = 9000;
665*4882a593Smuzhiyun 	state->m_dvbt_if_agc_cfg.top = 13424;
666*4882a593Smuzhiyun 	state->m_dvbt_if_agc_cfg.cut_off_current = 0;
667*4882a593Smuzhiyun 	state->m_dvbt_if_agc_cfg.speed = 3;
668*4882a593Smuzhiyun 	state->m_dvbt_if_agc_cfg.fast_clip_ctrl_delay = 30;
669*4882a593Smuzhiyun 	state->m_dvbt_if_agc_cfg.ingain_tgt_max = 30000;
670*4882a593Smuzhiyun 	/* state->m_dvbtPgaCfg = 140; */
671*4882a593Smuzhiyun 
672*4882a593Smuzhiyun 	state->m_dvbt_pre_saw_cfg.reference = 4;
673*4882a593Smuzhiyun 	state->m_dvbt_pre_saw_cfg.use_pre_saw = false;
674*4882a593Smuzhiyun 
675*4882a593Smuzhiyun 	/* QAM RF */
676*4882a593Smuzhiyun 	state->m_qam_rf_agc_cfg.ctrl_mode = DRXK_AGC_CTRL_OFF;
677*4882a593Smuzhiyun 	state->m_qam_rf_agc_cfg.output_level = 0;
678*4882a593Smuzhiyun 	state->m_qam_rf_agc_cfg.min_output_level = 6023;
679*4882a593Smuzhiyun 	state->m_qam_rf_agc_cfg.max_output_level = 27000;
680*4882a593Smuzhiyun 	state->m_qam_rf_agc_cfg.top = 0x2380;
681*4882a593Smuzhiyun 	state->m_qam_rf_agc_cfg.cut_off_current = 4000;
682*4882a593Smuzhiyun 	state->m_qam_rf_agc_cfg.speed = 3;
683*4882a593Smuzhiyun 
684*4882a593Smuzhiyun 	/* QAM IF */
685*4882a593Smuzhiyun 	state->m_qam_if_agc_cfg.ctrl_mode = DRXK_AGC_CTRL_AUTO;
686*4882a593Smuzhiyun 	state->m_qam_if_agc_cfg.output_level = 0;
687*4882a593Smuzhiyun 	state->m_qam_if_agc_cfg.min_output_level = 0;
688*4882a593Smuzhiyun 	state->m_qam_if_agc_cfg.max_output_level = 9000;
689*4882a593Smuzhiyun 	state->m_qam_if_agc_cfg.top = 0x0511;
690*4882a593Smuzhiyun 	state->m_qam_if_agc_cfg.cut_off_current = 0;
691*4882a593Smuzhiyun 	state->m_qam_if_agc_cfg.speed = 3;
692*4882a593Smuzhiyun 	state->m_qam_if_agc_cfg.ingain_tgt_max = 5119;
693*4882a593Smuzhiyun 	state->m_qam_if_agc_cfg.fast_clip_ctrl_delay = 50;
694*4882a593Smuzhiyun 
695*4882a593Smuzhiyun 	state->m_qam_pga_cfg = 140;
696*4882a593Smuzhiyun 	state->m_qam_pre_saw_cfg.reference = 4;
697*4882a593Smuzhiyun 	state->m_qam_pre_saw_cfg.use_pre_saw = false;
698*4882a593Smuzhiyun 
699*4882a593Smuzhiyun 	state->m_operation_mode = OM_NONE;
700*4882a593Smuzhiyun 	state->m_drxk_state = DRXK_UNINITIALIZED;
701*4882a593Smuzhiyun 
702*4882a593Smuzhiyun 	/* MPEG output configuration */
703*4882a593Smuzhiyun 	state->m_enable_mpeg_output = true;	/* If TRUE; enable MPEG output */
704*4882a593Smuzhiyun 	state->m_insert_rs_byte = false;	/* If TRUE; insert RS byte */
705*4882a593Smuzhiyun 	state->m_invert_data = false;	/* If TRUE; invert DATA signals */
706*4882a593Smuzhiyun 	state->m_invert_err = false;	/* If TRUE; invert ERR signal */
707*4882a593Smuzhiyun 	state->m_invert_str = false;	/* If TRUE; invert STR signals */
708*4882a593Smuzhiyun 	state->m_invert_val = false;	/* If TRUE; invert VAL signals */
709*4882a593Smuzhiyun 	state->m_invert_clk = (ul_invert_ts_clock != 0);	/* If TRUE; invert CLK signals */
710*4882a593Smuzhiyun 
711*4882a593Smuzhiyun 	/* If TRUE; static MPEG clockrate will be used;
712*4882a593Smuzhiyun 	   otherwise clockrate will adapt to the bitrate of the TS */
713*4882a593Smuzhiyun 
714*4882a593Smuzhiyun 	state->m_dvbt_bitrate = ul_dvbt_bitrate;
715*4882a593Smuzhiyun 	state->m_dvbc_bitrate = ul_dvbc_bitrate;
716*4882a593Smuzhiyun 
717*4882a593Smuzhiyun 	state->m_ts_data_strength = (ul_ts_data_strength & 0x07);
718*4882a593Smuzhiyun 
719*4882a593Smuzhiyun 	/* Maximum bitrate in b/s in case static clockrate is selected */
720*4882a593Smuzhiyun 	state->m_mpeg_ts_static_bitrate = 19392658;
721*4882a593Smuzhiyun 	state->m_disable_te_ihandling = false;
722*4882a593Smuzhiyun 
723*4882a593Smuzhiyun 	if (ul_insert_rs_byte)
724*4882a593Smuzhiyun 		state->m_insert_rs_byte = true;
725*4882a593Smuzhiyun 
726*4882a593Smuzhiyun 	state->m_mpeg_lock_time_out = DEFAULT_DRXK_MPEG_LOCK_TIMEOUT;
727*4882a593Smuzhiyun 	if (ul_mpeg_lock_time_out < 10000)
728*4882a593Smuzhiyun 		state->m_mpeg_lock_time_out = ul_mpeg_lock_time_out;
729*4882a593Smuzhiyun 	state->m_demod_lock_time_out = DEFAULT_DRXK_DEMOD_LOCK_TIMEOUT;
730*4882a593Smuzhiyun 	if (ul_demod_lock_time_out < 10000)
731*4882a593Smuzhiyun 		state->m_demod_lock_time_out = ul_demod_lock_time_out;
732*4882a593Smuzhiyun 
733*4882a593Smuzhiyun 	/* QAM defaults */
734*4882a593Smuzhiyun 	state->m_constellation = DRX_CONSTELLATION_AUTO;
735*4882a593Smuzhiyun 	state->m_qam_interleave_mode = DRXK_QAM_I12_J17;
736*4882a593Smuzhiyun 	state->m_fec_rs_plen = 204 * 8;	/* fecRsPlen  annex A */
737*4882a593Smuzhiyun 	state->m_fec_rs_prescale = 1;
738*4882a593Smuzhiyun 
739*4882a593Smuzhiyun 	state->m_sqi_speed = DRXK_DVBT_SQI_SPEED_MEDIUM;
740*4882a593Smuzhiyun 	state->m_agcfast_clip_ctrl_delay = 0;
741*4882a593Smuzhiyun 
742*4882a593Smuzhiyun 	state->m_gpio_cfg = ul_gpio_cfg;
743*4882a593Smuzhiyun 
744*4882a593Smuzhiyun 	state->m_b_power_down = false;
745*4882a593Smuzhiyun 	state->m_current_power_mode = DRX_POWER_DOWN;
746*4882a593Smuzhiyun 
747*4882a593Smuzhiyun 	state->m_rfmirror = (ul_rf_mirror == 0);
748*4882a593Smuzhiyun 	state->m_if_agc_pol = false;
749*4882a593Smuzhiyun 	return 0;
750*4882a593Smuzhiyun }
751*4882a593Smuzhiyun 
drxx_open(struct drxk_state * state)752*4882a593Smuzhiyun static int drxx_open(struct drxk_state *state)
753*4882a593Smuzhiyun {
754*4882a593Smuzhiyun 	int status = 0;
755*4882a593Smuzhiyun 	u32 jtag = 0;
756*4882a593Smuzhiyun 	u16 bid = 0;
757*4882a593Smuzhiyun 	u16 key = 0;
758*4882a593Smuzhiyun 
759*4882a593Smuzhiyun 	dprintk(1, "\n");
760*4882a593Smuzhiyun 	/* stop lock indicator process */
761*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_GPIO__A,
762*4882a593Smuzhiyun 			 SCU_RAM_GPIO_HW_LOCK_IND_DISABLE);
763*4882a593Smuzhiyun 	if (status < 0)
764*4882a593Smuzhiyun 		goto error;
765*4882a593Smuzhiyun 	/* Check device id */
766*4882a593Smuzhiyun 	status = read16(state, SIO_TOP_COMM_KEY__A, &key);
767*4882a593Smuzhiyun 	if (status < 0)
768*4882a593Smuzhiyun 		goto error;
769*4882a593Smuzhiyun 	status = write16(state, SIO_TOP_COMM_KEY__A, SIO_TOP_COMM_KEY_KEY);
770*4882a593Smuzhiyun 	if (status < 0)
771*4882a593Smuzhiyun 		goto error;
772*4882a593Smuzhiyun 	status = read32(state, SIO_TOP_JTAGID_LO__A, &jtag);
773*4882a593Smuzhiyun 	if (status < 0)
774*4882a593Smuzhiyun 		goto error;
775*4882a593Smuzhiyun 	status = read16(state, SIO_PDR_UIO_IN_HI__A, &bid);
776*4882a593Smuzhiyun 	if (status < 0)
777*4882a593Smuzhiyun 		goto error;
778*4882a593Smuzhiyun 	status = write16(state, SIO_TOP_COMM_KEY__A, key);
779*4882a593Smuzhiyun error:
780*4882a593Smuzhiyun 	if (status < 0)
781*4882a593Smuzhiyun 		pr_err("Error %d on %s\n", status, __func__);
782*4882a593Smuzhiyun 	return status;
783*4882a593Smuzhiyun }
784*4882a593Smuzhiyun 
get_device_capabilities(struct drxk_state * state)785*4882a593Smuzhiyun static int get_device_capabilities(struct drxk_state *state)
786*4882a593Smuzhiyun {
787*4882a593Smuzhiyun 	u16 sio_pdr_ohw_cfg = 0;
788*4882a593Smuzhiyun 	u32 sio_top_jtagid_lo = 0;
789*4882a593Smuzhiyun 	int status;
790*4882a593Smuzhiyun 	const char *spin = "";
791*4882a593Smuzhiyun 
792*4882a593Smuzhiyun 	dprintk(1, "\n");
793*4882a593Smuzhiyun 
794*4882a593Smuzhiyun 	/* driver 0.9.0 */
795*4882a593Smuzhiyun 	/* stop lock indicator process */
796*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_GPIO__A,
797*4882a593Smuzhiyun 			 SCU_RAM_GPIO_HW_LOCK_IND_DISABLE);
798*4882a593Smuzhiyun 	if (status < 0)
799*4882a593Smuzhiyun 		goto error;
800*4882a593Smuzhiyun 	status = write16(state, SIO_TOP_COMM_KEY__A, SIO_TOP_COMM_KEY_KEY);
801*4882a593Smuzhiyun 	if (status < 0)
802*4882a593Smuzhiyun 		goto error;
803*4882a593Smuzhiyun 	status = read16(state, SIO_PDR_OHW_CFG__A, &sio_pdr_ohw_cfg);
804*4882a593Smuzhiyun 	if (status < 0)
805*4882a593Smuzhiyun 		goto error;
806*4882a593Smuzhiyun 	status = write16(state, SIO_TOP_COMM_KEY__A, 0x0000);
807*4882a593Smuzhiyun 	if (status < 0)
808*4882a593Smuzhiyun 		goto error;
809*4882a593Smuzhiyun 
810*4882a593Smuzhiyun 	switch ((sio_pdr_ohw_cfg & SIO_PDR_OHW_CFG_FREF_SEL__M)) {
811*4882a593Smuzhiyun 	case 0:
812*4882a593Smuzhiyun 		/* ignore (bypass ?) */
813*4882a593Smuzhiyun 		break;
814*4882a593Smuzhiyun 	case 1:
815*4882a593Smuzhiyun 		/* 27 MHz */
816*4882a593Smuzhiyun 		state->m_osc_clock_freq = 27000;
817*4882a593Smuzhiyun 		break;
818*4882a593Smuzhiyun 	case 2:
819*4882a593Smuzhiyun 		/* 20.25 MHz */
820*4882a593Smuzhiyun 		state->m_osc_clock_freq = 20250;
821*4882a593Smuzhiyun 		break;
822*4882a593Smuzhiyun 	case 3:
823*4882a593Smuzhiyun 		/* 4 MHz */
824*4882a593Smuzhiyun 		state->m_osc_clock_freq = 20250;
825*4882a593Smuzhiyun 		break;
826*4882a593Smuzhiyun 	default:
827*4882a593Smuzhiyun 		pr_err("Clock Frequency is unknown\n");
828*4882a593Smuzhiyun 		return -EINVAL;
829*4882a593Smuzhiyun 	}
830*4882a593Smuzhiyun 	/*
831*4882a593Smuzhiyun 		Determine device capabilities
832*4882a593Smuzhiyun 		Based on pinning v14
833*4882a593Smuzhiyun 		*/
834*4882a593Smuzhiyun 	status = read32(state, SIO_TOP_JTAGID_LO__A, &sio_top_jtagid_lo);
835*4882a593Smuzhiyun 	if (status < 0)
836*4882a593Smuzhiyun 		goto error;
837*4882a593Smuzhiyun 
838*4882a593Smuzhiyun 	pr_info("status = 0x%08x\n", sio_top_jtagid_lo);
839*4882a593Smuzhiyun 
840*4882a593Smuzhiyun 	/* driver 0.9.0 */
841*4882a593Smuzhiyun 	switch ((sio_top_jtagid_lo >> 29) & 0xF) {
842*4882a593Smuzhiyun 	case 0:
843*4882a593Smuzhiyun 		state->m_device_spin = DRXK_SPIN_A1;
844*4882a593Smuzhiyun 		spin = "A1";
845*4882a593Smuzhiyun 		break;
846*4882a593Smuzhiyun 	case 2:
847*4882a593Smuzhiyun 		state->m_device_spin = DRXK_SPIN_A2;
848*4882a593Smuzhiyun 		spin = "A2";
849*4882a593Smuzhiyun 		break;
850*4882a593Smuzhiyun 	case 3:
851*4882a593Smuzhiyun 		state->m_device_spin = DRXK_SPIN_A3;
852*4882a593Smuzhiyun 		spin = "A3";
853*4882a593Smuzhiyun 		break;
854*4882a593Smuzhiyun 	default:
855*4882a593Smuzhiyun 		state->m_device_spin = DRXK_SPIN_UNKNOWN;
856*4882a593Smuzhiyun 		status = -EINVAL;
857*4882a593Smuzhiyun 		pr_err("Spin %d unknown\n", (sio_top_jtagid_lo >> 29) & 0xF);
858*4882a593Smuzhiyun 		goto error2;
859*4882a593Smuzhiyun 	}
860*4882a593Smuzhiyun 	switch ((sio_top_jtagid_lo >> 12) & 0xFF) {
861*4882a593Smuzhiyun 	case 0x13:
862*4882a593Smuzhiyun 		/* typeId = DRX3913K_TYPE_ID */
863*4882a593Smuzhiyun 		state->m_has_lna = false;
864*4882a593Smuzhiyun 		state->m_has_oob = false;
865*4882a593Smuzhiyun 		state->m_has_atv = false;
866*4882a593Smuzhiyun 		state->m_has_audio = false;
867*4882a593Smuzhiyun 		state->m_has_dvbt = true;
868*4882a593Smuzhiyun 		state->m_has_dvbc = true;
869*4882a593Smuzhiyun 		state->m_has_sawsw = true;
870*4882a593Smuzhiyun 		state->m_has_gpio2 = false;
871*4882a593Smuzhiyun 		state->m_has_gpio1 = false;
872*4882a593Smuzhiyun 		state->m_has_irqn = false;
873*4882a593Smuzhiyun 		break;
874*4882a593Smuzhiyun 	case 0x15:
875*4882a593Smuzhiyun 		/* typeId = DRX3915K_TYPE_ID */
876*4882a593Smuzhiyun 		state->m_has_lna = false;
877*4882a593Smuzhiyun 		state->m_has_oob = false;
878*4882a593Smuzhiyun 		state->m_has_atv = true;
879*4882a593Smuzhiyun 		state->m_has_audio = false;
880*4882a593Smuzhiyun 		state->m_has_dvbt = true;
881*4882a593Smuzhiyun 		state->m_has_dvbc = false;
882*4882a593Smuzhiyun 		state->m_has_sawsw = true;
883*4882a593Smuzhiyun 		state->m_has_gpio2 = true;
884*4882a593Smuzhiyun 		state->m_has_gpio1 = true;
885*4882a593Smuzhiyun 		state->m_has_irqn = false;
886*4882a593Smuzhiyun 		break;
887*4882a593Smuzhiyun 	case 0x16:
888*4882a593Smuzhiyun 		/* typeId = DRX3916K_TYPE_ID */
889*4882a593Smuzhiyun 		state->m_has_lna = false;
890*4882a593Smuzhiyun 		state->m_has_oob = false;
891*4882a593Smuzhiyun 		state->m_has_atv = true;
892*4882a593Smuzhiyun 		state->m_has_audio = false;
893*4882a593Smuzhiyun 		state->m_has_dvbt = true;
894*4882a593Smuzhiyun 		state->m_has_dvbc = false;
895*4882a593Smuzhiyun 		state->m_has_sawsw = true;
896*4882a593Smuzhiyun 		state->m_has_gpio2 = true;
897*4882a593Smuzhiyun 		state->m_has_gpio1 = true;
898*4882a593Smuzhiyun 		state->m_has_irqn = false;
899*4882a593Smuzhiyun 		break;
900*4882a593Smuzhiyun 	case 0x18:
901*4882a593Smuzhiyun 		/* typeId = DRX3918K_TYPE_ID */
902*4882a593Smuzhiyun 		state->m_has_lna = false;
903*4882a593Smuzhiyun 		state->m_has_oob = false;
904*4882a593Smuzhiyun 		state->m_has_atv = true;
905*4882a593Smuzhiyun 		state->m_has_audio = true;
906*4882a593Smuzhiyun 		state->m_has_dvbt = true;
907*4882a593Smuzhiyun 		state->m_has_dvbc = false;
908*4882a593Smuzhiyun 		state->m_has_sawsw = true;
909*4882a593Smuzhiyun 		state->m_has_gpio2 = true;
910*4882a593Smuzhiyun 		state->m_has_gpio1 = true;
911*4882a593Smuzhiyun 		state->m_has_irqn = false;
912*4882a593Smuzhiyun 		break;
913*4882a593Smuzhiyun 	case 0x21:
914*4882a593Smuzhiyun 		/* typeId = DRX3921K_TYPE_ID */
915*4882a593Smuzhiyun 		state->m_has_lna = false;
916*4882a593Smuzhiyun 		state->m_has_oob = false;
917*4882a593Smuzhiyun 		state->m_has_atv = true;
918*4882a593Smuzhiyun 		state->m_has_audio = true;
919*4882a593Smuzhiyun 		state->m_has_dvbt = true;
920*4882a593Smuzhiyun 		state->m_has_dvbc = true;
921*4882a593Smuzhiyun 		state->m_has_sawsw = true;
922*4882a593Smuzhiyun 		state->m_has_gpio2 = true;
923*4882a593Smuzhiyun 		state->m_has_gpio1 = true;
924*4882a593Smuzhiyun 		state->m_has_irqn = false;
925*4882a593Smuzhiyun 		break;
926*4882a593Smuzhiyun 	case 0x23:
927*4882a593Smuzhiyun 		/* typeId = DRX3923K_TYPE_ID */
928*4882a593Smuzhiyun 		state->m_has_lna = false;
929*4882a593Smuzhiyun 		state->m_has_oob = false;
930*4882a593Smuzhiyun 		state->m_has_atv = true;
931*4882a593Smuzhiyun 		state->m_has_audio = true;
932*4882a593Smuzhiyun 		state->m_has_dvbt = true;
933*4882a593Smuzhiyun 		state->m_has_dvbc = true;
934*4882a593Smuzhiyun 		state->m_has_sawsw = true;
935*4882a593Smuzhiyun 		state->m_has_gpio2 = true;
936*4882a593Smuzhiyun 		state->m_has_gpio1 = true;
937*4882a593Smuzhiyun 		state->m_has_irqn = false;
938*4882a593Smuzhiyun 		break;
939*4882a593Smuzhiyun 	case 0x25:
940*4882a593Smuzhiyun 		/* typeId = DRX3925K_TYPE_ID */
941*4882a593Smuzhiyun 		state->m_has_lna = false;
942*4882a593Smuzhiyun 		state->m_has_oob = false;
943*4882a593Smuzhiyun 		state->m_has_atv = true;
944*4882a593Smuzhiyun 		state->m_has_audio = true;
945*4882a593Smuzhiyun 		state->m_has_dvbt = true;
946*4882a593Smuzhiyun 		state->m_has_dvbc = true;
947*4882a593Smuzhiyun 		state->m_has_sawsw = true;
948*4882a593Smuzhiyun 		state->m_has_gpio2 = true;
949*4882a593Smuzhiyun 		state->m_has_gpio1 = true;
950*4882a593Smuzhiyun 		state->m_has_irqn = false;
951*4882a593Smuzhiyun 		break;
952*4882a593Smuzhiyun 	case 0x26:
953*4882a593Smuzhiyun 		/* typeId = DRX3926K_TYPE_ID */
954*4882a593Smuzhiyun 		state->m_has_lna = false;
955*4882a593Smuzhiyun 		state->m_has_oob = false;
956*4882a593Smuzhiyun 		state->m_has_atv = true;
957*4882a593Smuzhiyun 		state->m_has_audio = false;
958*4882a593Smuzhiyun 		state->m_has_dvbt = true;
959*4882a593Smuzhiyun 		state->m_has_dvbc = true;
960*4882a593Smuzhiyun 		state->m_has_sawsw = true;
961*4882a593Smuzhiyun 		state->m_has_gpio2 = true;
962*4882a593Smuzhiyun 		state->m_has_gpio1 = true;
963*4882a593Smuzhiyun 		state->m_has_irqn = false;
964*4882a593Smuzhiyun 		break;
965*4882a593Smuzhiyun 	default:
966*4882a593Smuzhiyun 		pr_err("DeviceID 0x%02x not supported\n",
967*4882a593Smuzhiyun 			((sio_top_jtagid_lo >> 12) & 0xFF));
968*4882a593Smuzhiyun 		status = -EINVAL;
969*4882a593Smuzhiyun 		goto error2;
970*4882a593Smuzhiyun 	}
971*4882a593Smuzhiyun 
972*4882a593Smuzhiyun 	pr_info("detected a drx-39%02xk, spin %s, xtal %d.%03d MHz\n",
973*4882a593Smuzhiyun 	       ((sio_top_jtagid_lo >> 12) & 0xFF), spin,
974*4882a593Smuzhiyun 	       state->m_osc_clock_freq / 1000,
975*4882a593Smuzhiyun 	       state->m_osc_clock_freq % 1000);
976*4882a593Smuzhiyun 
977*4882a593Smuzhiyun error:
978*4882a593Smuzhiyun 	if (status < 0)
979*4882a593Smuzhiyun 		pr_err("Error %d on %s\n", status, __func__);
980*4882a593Smuzhiyun 
981*4882a593Smuzhiyun error2:
982*4882a593Smuzhiyun 	return status;
983*4882a593Smuzhiyun }
984*4882a593Smuzhiyun 
hi_command(struct drxk_state * state,u16 cmd,u16 * p_result)985*4882a593Smuzhiyun static int hi_command(struct drxk_state *state, u16 cmd, u16 *p_result)
986*4882a593Smuzhiyun {
987*4882a593Smuzhiyun 	int status;
988*4882a593Smuzhiyun 	bool powerdown_cmd;
989*4882a593Smuzhiyun 
990*4882a593Smuzhiyun 	dprintk(1, "\n");
991*4882a593Smuzhiyun 
992*4882a593Smuzhiyun 	/* Write command */
993*4882a593Smuzhiyun 	status = write16(state, SIO_HI_RA_RAM_CMD__A, cmd);
994*4882a593Smuzhiyun 	if (status < 0)
995*4882a593Smuzhiyun 		goto error;
996*4882a593Smuzhiyun 	if (cmd == SIO_HI_RA_RAM_CMD_RESET)
997*4882a593Smuzhiyun 		usleep_range(1000, 2000);
998*4882a593Smuzhiyun 
999*4882a593Smuzhiyun 	powerdown_cmd =
1000*4882a593Smuzhiyun 	    (bool) ((cmd == SIO_HI_RA_RAM_CMD_CONFIG) &&
1001*4882a593Smuzhiyun 		    ((state->m_hi_cfg_ctrl) &
1002*4882a593Smuzhiyun 		     SIO_HI_RA_RAM_PAR_5_CFG_SLEEP__M) ==
1003*4882a593Smuzhiyun 		    SIO_HI_RA_RAM_PAR_5_CFG_SLEEP_ZZZ);
1004*4882a593Smuzhiyun 	if (!powerdown_cmd) {
1005*4882a593Smuzhiyun 		/* Wait until command rdy */
1006*4882a593Smuzhiyun 		u32 retry_count = 0;
1007*4882a593Smuzhiyun 		u16 wait_cmd;
1008*4882a593Smuzhiyun 
1009*4882a593Smuzhiyun 		do {
1010*4882a593Smuzhiyun 			usleep_range(1000, 2000);
1011*4882a593Smuzhiyun 			retry_count += 1;
1012*4882a593Smuzhiyun 			status = read16(state, SIO_HI_RA_RAM_CMD__A,
1013*4882a593Smuzhiyun 					  &wait_cmd);
1014*4882a593Smuzhiyun 		} while ((status < 0 || wait_cmd) && (retry_count < DRXK_MAX_RETRIES));
1015*4882a593Smuzhiyun 		if (status < 0)
1016*4882a593Smuzhiyun 			goto error;
1017*4882a593Smuzhiyun 		status = read16(state, SIO_HI_RA_RAM_RES__A, p_result);
1018*4882a593Smuzhiyun 	}
1019*4882a593Smuzhiyun error:
1020*4882a593Smuzhiyun 	if (status < 0)
1021*4882a593Smuzhiyun 		pr_err("Error %d on %s\n", status, __func__);
1022*4882a593Smuzhiyun 
1023*4882a593Smuzhiyun 	return status;
1024*4882a593Smuzhiyun }
1025*4882a593Smuzhiyun 
hi_cfg_command(struct drxk_state * state)1026*4882a593Smuzhiyun static int hi_cfg_command(struct drxk_state *state)
1027*4882a593Smuzhiyun {
1028*4882a593Smuzhiyun 	int status;
1029*4882a593Smuzhiyun 
1030*4882a593Smuzhiyun 	dprintk(1, "\n");
1031*4882a593Smuzhiyun 
1032*4882a593Smuzhiyun 	mutex_lock(&state->mutex);
1033*4882a593Smuzhiyun 
1034*4882a593Smuzhiyun 	status = write16(state, SIO_HI_RA_RAM_PAR_6__A,
1035*4882a593Smuzhiyun 			 state->m_hi_cfg_timeout);
1036*4882a593Smuzhiyun 	if (status < 0)
1037*4882a593Smuzhiyun 		goto error;
1038*4882a593Smuzhiyun 	status = write16(state, SIO_HI_RA_RAM_PAR_5__A,
1039*4882a593Smuzhiyun 			 state->m_hi_cfg_ctrl);
1040*4882a593Smuzhiyun 	if (status < 0)
1041*4882a593Smuzhiyun 		goto error;
1042*4882a593Smuzhiyun 	status = write16(state, SIO_HI_RA_RAM_PAR_4__A,
1043*4882a593Smuzhiyun 			 state->m_hi_cfg_wake_up_key);
1044*4882a593Smuzhiyun 	if (status < 0)
1045*4882a593Smuzhiyun 		goto error;
1046*4882a593Smuzhiyun 	status = write16(state, SIO_HI_RA_RAM_PAR_3__A,
1047*4882a593Smuzhiyun 			 state->m_hi_cfg_bridge_delay);
1048*4882a593Smuzhiyun 	if (status < 0)
1049*4882a593Smuzhiyun 		goto error;
1050*4882a593Smuzhiyun 	status = write16(state, SIO_HI_RA_RAM_PAR_2__A,
1051*4882a593Smuzhiyun 			 state->m_hi_cfg_timing_div);
1052*4882a593Smuzhiyun 	if (status < 0)
1053*4882a593Smuzhiyun 		goto error;
1054*4882a593Smuzhiyun 	status = write16(state, SIO_HI_RA_RAM_PAR_1__A,
1055*4882a593Smuzhiyun 			 SIO_HI_RA_RAM_PAR_1_PAR1_SEC_KEY);
1056*4882a593Smuzhiyun 	if (status < 0)
1057*4882a593Smuzhiyun 		goto error;
1058*4882a593Smuzhiyun 	status = hi_command(state, SIO_HI_RA_RAM_CMD_CONFIG, NULL);
1059*4882a593Smuzhiyun 	if (status < 0)
1060*4882a593Smuzhiyun 		goto error;
1061*4882a593Smuzhiyun 
1062*4882a593Smuzhiyun 	state->m_hi_cfg_ctrl &= ~SIO_HI_RA_RAM_PAR_5_CFG_SLEEP_ZZZ;
1063*4882a593Smuzhiyun error:
1064*4882a593Smuzhiyun 	mutex_unlock(&state->mutex);
1065*4882a593Smuzhiyun 	if (status < 0)
1066*4882a593Smuzhiyun 		pr_err("Error %d on %s\n", status, __func__);
1067*4882a593Smuzhiyun 	return status;
1068*4882a593Smuzhiyun }
1069*4882a593Smuzhiyun 
init_hi(struct drxk_state * state)1070*4882a593Smuzhiyun static int init_hi(struct drxk_state *state)
1071*4882a593Smuzhiyun {
1072*4882a593Smuzhiyun 	dprintk(1, "\n");
1073*4882a593Smuzhiyun 
1074*4882a593Smuzhiyun 	state->m_hi_cfg_wake_up_key = (state->demod_address << 1);
1075*4882a593Smuzhiyun 	state->m_hi_cfg_timeout = 0x96FF;
1076*4882a593Smuzhiyun 	/* port/bridge/power down ctrl */
1077*4882a593Smuzhiyun 	state->m_hi_cfg_ctrl = SIO_HI_RA_RAM_PAR_5_CFG_SLV0_SLAVE;
1078*4882a593Smuzhiyun 
1079*4882a593Smuzhiyun 	return hi_cfg_command(state);
1080*4882a593Smuzhiyun }
1081*4882a593Smuzhiyun 
mpegts_configure_pins(struct drxk_state * state,bool mpeg_enable)1082*4882a593Smuzhiyun static int mpegts_configure_pins(struct drxk_state *state, bool mpeg_enable)
1083*4882a593Smuzhiyun {
1084*4882a593Smuzhiyun 	int status;
1085*4882a593Smuzhiyun 	u16 sio_pdr_mclk_cfg = 0;
1086*4882a593Smuzhiyun 	u16 sio_pdr_mdx_cfg = 0;
1087*4882a593Smuzhiyun 	u16 err_cfg = 0;
1088*4882a593Smuzhiyun 
1089*4882a593Smuzhiyun 	dprintk(1, ": mpeg %s, %s mode\n",
1090*4882a593Smuzhiyun 		mpeg_enable ? "enable" : "disable",
1091*4882a593Smuzhiyun 		state->m_enable_parallel ? "parallel" : "serial");
1092*4882a593Smuzhiyun 
1093*4882a593Smuzhiyun 	/* stop lock indicator process */
1094*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_GPIO__A,
1095*4882a593Smuzhiyun 			 SCU_RAM_GPIO_HW_LOCK_IND_DISABLE);
1096*4882a593Smuzhiyun 	if (status < 0)
1097*4882a593Smuzhiyun 		goto error;
1098*4882a593Smuzhiyun 
1099*4882a593Smuzhiyun 	/*  MPEG TS pad configuration */
1100*4882a593Smuzhiyun 	status = write16(state, SIO_TOP_COMM_KEY__A, SIO_TOP_COMM_KEY_KEY);
1101*4882a593Smuzhiyun 	if (status < 0)
1102*4882a593Smuzhiyun 		goto error;
1103*4882a593Smuzhiyun 
1104*4882a593Smuzhiyun 	if (!mpeg_enable) {
1105*4882a593Smuzhiyun 		/*  Set MPEG TS pads to inputmode */
1106*4882a593Smuzhiyun 		status = write16(state, SIO_PDR_MSTRT_CFG__A, 0x0000);
1107*4882a593Smuzhiyun 		if (status < 0)
1108*4882a593Smuzhiyun 			goto error;
1109*4882a593Smuzhiyun 		status = write16(state, SIO_PDR_MERR_CFG__A, 0x0000);
1110*4882a593Smuzhiyun 		if (status < 0)
1111*4882a593Smuzhiyun 			goto error;
1112*4882a593Smuzhiyun 		status = write16(state, SIO_PDR_MCLK_CFG__A, 0x0000);
1113*4882a593Smuzhiyun 		if (status < 0)
1114*4882a593Smuzhiyun 			goto error;
1115*4882a593Smuzhiyun 		status = write16(state, SIO_PDR_MVAL_CFG__A, 0x0000);
1116*4882a593Smuzhiyun 		if (status < 0)
1117*4882a593Smuzhiyun 			goto error;
1118*4882a593Smuzhiyun 		status = write16(state, SIO_PDR_MD0_CFG__A, 0x0000);
1119*4882a593Smuzhiyun 		if (status < 0)
1120*4882a593Smuzhiyun 			goto error;
1121*4882a593Smuzhiyun 		status = write16(state, SIO_PDR_MD1_CFG__A, 0x0000);
1122*4882a593Smuzhiyun 		if (status < 0)
1123*4882a593Smuzhiyun 			goto error;
1124*4882a593Smuzhiyun 		status = write16(state, SIO_PDR_MD2_CFG__A, 0x0000);
1125*4882a593Smuzhiyun 		if (status < 0)
1126*4882a593Smuzhiyun 			goto error;
1127*4882a593Smuzhiyun 		status = write16(state, SIO_PDR_MD3_CFG__A, 0x0000);
1128*4882a593Smuzhiyun 		if (status < 0)
1129*4882a593Smuzhiyun 			goto error;
1130*4882a593Smuzhiyun 		status = write16(state, SIO_PDR_MD4_CFG__A, 0x0000);
1131*4882a593Smuzhiyun 		if (status < 0)
1132*4882a593Smuzhiyun 			goto error;
1133*4882a593Smuzhiyun 		status = write16(state, SIO_PDR_MD5_CFG__A, 0x0000);
1134*4882a593Smuzhiyun 		if (status < 0)
1135*4882a593Smuzhiyun 			goto error;
1136*4882a593Smuzhiyun 		status = write16(state, SIO_PDR_MD6_CFG__A, 0x0000);
1137*4882a593Smuzhiyun 		if (status < 0)
1138*4882a593Smuzhiyun 			goto error;
1139*4882a593Smuzhiyun 		status = write16(state, SIO_PDR_MD7_CFG__A, 0x0000);
1140*4882a593Smuzhiyun 		if (status < 0)
1141*4882a593Smuzhiyun 			goto error;
1142*4882a593Smuzhiyun 	} else {
1143*4882a593Smuzhiyun 		/* Enable MPEG output */
1144*4882a593Smuzhiyun 		sio_pdr_mdx_cfg =
1145*4882a593Smuzhiyun 			((state->m_ts_data_strength <<
1146*4882a593Smuzhiyun 			SIO_PDR_MD0_CFG_DRIVE__B) | 0x0003);
1147*4882a593Smuzhiyun 		sio_pdr_mclk_cfg = ((state->m_ts_clockk_strength <<
1148*4882a593Smuzhiyun 					SIO_PDR_MCLK_CFG_DRIVE__B) |
1149*4882a593Smuzhiyun 					0x0003);
1150*4882a593Smuzhiyun 
1151*4882a593Smuzhiyun 		status = write16(state, SIO_PDR_MSTRT_CFG__A, sio_pdr_mdx_cfg);
1152*4882a593Smuzhiyun 		if (status < 0)
1153*4882a593Smuzhiyun 			goto error;
1154*4882a593Smuzhiyun 
1155*4882a593Smuzhiyun 		if (state->enable_merr_cfg)
1156*4882a593Smuzhiyun 			err_cfg = sio_pdr_mdx_cfg;
1157*4882a593Smuzhiyun 
1158*4882a593Smuzhiyun 		status = write16(state, SIO_PDR_MERR_CFG__A, err_cfg);
1159*4882a593Smuzhiyun 		if (status < 0)
1160*4882a593Smuzhiyun 			goto error;
1161*4882a593Smuzhiyun 		status = write16(state, SIO_PDR_MVAL_CFG__A, err_cfg);
1162*4882a593Smuzhiyun 		if (status < 0)
1163*4882a593Smuzhiyun 			goto error;
1164*4882a593Smuzhiyun 
1165*4882a593Smuzhiyun 		if (state->m_enable_parallel) {
1166*4882a593Smuzhiyun 			/* parallel -> enable MD1 to MD7 */
1167*4882a593Smuzhiyun 			status = write16(state, SIO_PDR_MD1_CFG__A,
1168*4882a593Smuzhiyun 					 sio_pdr_mdx_cfg);
1169*4882a593Smuzhiyun 			if (status < 0)
1170*4882a593Smuzhiyun 				goto error;
1171*4882a593Smuzhiyun 			status = write16(state, SIO_PDR_MD2_CFG__A,
1172*4882a593Smuzhiyun 					 sio_pdr_mdx_cfg);
1173*4882a593Smuzhiyun 			if (status < 0)
1174*4882a593Smuzhiyun 				goto error;
1175*4882a593Smuzhiyun 			status = write16(state, SIO_PDR_MD3_CFG__A,
1176*4882a593Smuzhiyun 					 sio_pdr_mdx_cfg);
1177*4882a593Smuzhiyun 			if (status < 0)
1178*4882a593Smuzhiyun 				goto error;
1179*4882a593Smuzhiyun 			status = write16(state, SIO_PDR_MD4_CFG__A,
1180*4882a593Smuzhiyun 					 sio_pdr_mdx_cfg);
1181*4882a593Smuzhiyun 			if (status < 0)
1182*4882a593Smuzhiyun 				goto error;
1183*4882a593Smuzhiyun 			status = write16(state, SIO_PDR_MD5_CFG__A,
1184*4882a593Smuzhiyun 					 sio_pdr_mdx_cfg);
1185*4882a593Smuzhiyun 			if (status < 0)
1186*4882a593Smuzhiyun 				goto error;
1187*4882a593Smuzhiyun 			status = write16(state, SIO_PDR_MD6_CFG__A,
1188*4882a593Smuzhiyun 					 sio_pdr_mdx_cfg);
1189*4882a593Smuzhiyun 			if (status < 0)
1190*4882a593Smuzhiyun 				goto error;
1191*4882a593Smuzhiyun 			status = write16(state, SIO_PDR_MD7_CFG__A,
1192*4882a593Smuzhiyun 					 sio_pdr_mdx_cfg);
1193*4882a593Smuzhiyun 			if (status < 0)
1194*4882a593Smuzhiyun 				goto error;
1195*4882a593Smuzhiyun 		} else {
1196*4882a593Smuzhiyun 			sio_pdr_mdx_cfg = ((state->m_ts_data_strength <<
1197*4882a593Smuzhiyun 						SIO_PDR_MD0_CFG_DRIVE__B)
1198*4882a593Smuzhiyun 					| 0x0003);
1199*4882a593Smuzhiyun 			/* serial -> disable MD1 to MD7 */
1200*4882a593Smuzhiyun 			status = write16(state, SIO_PDR_MD1_CFG__A, 0x0000);
1201*4882a593Smuzhiyun 			if (status < 0)
1202*4882a593Smuzhiyun 				goto error;
1203*4882a593Smuzhiyun 			status = write16(state, SIO_PDR_MD2_CFG__A, 0x0000);
1204*4882a593Smuzhiyun 			if (status < 0)
1205*4882a593Smuzhiyun 				goto error;
1206*4882a593Smuzhiyun 			status = write16(state, SIO_PDR_MD3_CFG__A, 0x0000);
1207*4882a593Smuzhiyun 			if (status < 0)
1208*4882a593Smuzhiyun 				goto error;
1209*4882a593Smuzhiyun 			status = write16(state, SIO_PDR_MD4_CFG__A, 0x0000);
1210*4882a593Smuzhiyun 			if (status < 0)
1211*4882a593Smuzhiyun 				goto error;
1212*4882a593Smuzhiyun 			status = write16(state, SIO_PDR_MD5_CFG__A, 0x0000);
1213*4882a593Smuzhiyun 			if (status < 0)
1214*4882a593Smuzhiyun 				goto error;
1215*4882a593Smuzhiyun 			status = write16(state, SIO_PDR_MD6_CFG__A, 0x0000);
1216*4882a593Smuzhiyun 			if (status < 0)
1217*4882a593Smuzhiyun 				goto error;
1218*4882a593Smuzhiyun 			status = write16(state, SIO_PDR_MD7_CFG__A, 0x0000);
1219*4882a593Smuzhiyun 			if (status < 0)
1220*4882a593Smuzhiyun 				goto error;
1221*4882a593Smuzhiyun 		}
1222*4882a593Smuzhiyun 		status = write16(state, SIO_PDR_MCLK_CFG__A, sio_pdr_mclk_cfg);
1223*4882a593Smuzhiyun 		if (status < 0)
1224*4882a593Smuzhiyun 			goto error;
1225*4882a593Smuzhiyun 		status = write16(state, SIO_PDR_MD0_CFG__A, sio_pdr_mdx_cfg);
1226*4882a593Smuzhiyun 		if (status < 0)
1227*4882a593Smuzhiyun 			goto error;
1228*4882a593Smuzhiyun 	}
1229*4882a593Smuzhiyun 	/*  Enable MB output over MPEG pads and ctl input */
1230*4882a593Smuzhiyun 	status = write16(state, SIO_PDR_MON_CFG__A, 0x0000);
1231*4882a593Smuzhiyun 	if (status < 0)
1232*4882a593Smuzhiyun 		goto error;
1233*4882a593Smuzhiyun 	/*  Write nomagic word to enable pdr reg write */
1234*4882a593Smuzhiyun 	status = write16(state, SIO_TOP_COMM_KEY__A, 0x0000);
1235*4882a593Smuzhiyun error:
1236*4882a593Smuzhiyun 	if (status < 0)
1237*4882a593Smuzhiyun 		pr_err("Error %d on %s\n", status, __func__);
1238*4882a593Smuzhiyun 	return status;
1239*4882a593Smuzhiyun }
1240*4882a593Smuzhiyun 
mpegts_disable(struct drxk_state * state)1241*4882a593Smuzhiyun static int mpegts_disable(struct drxk_state *state)
1242*4882a593Smuzhiyun {
1243*4882a593Smuzhiyun 	dprintk(1, "\n");
1244*4882a593Smuzhiyun 
1245*4882a593Smuzhiyun 	return mpegts_configure_pins(state, false);
1246*4882a593Smuzhiyun }
1247*4882a593Smuzhiyun 
bl_chain_cmd(struct drxk_state * state,u16 rom_offset,u16 nr_of_elements,u32 time_out)1248*4882a593Smuzhiyun static int bl_chain_cmd(struct drxk_state *state,
1249*4882a593Smuzhiyun 		      u16 rom_offset, u16 nr_of_elements, u32 time_out)
1250*4882a593Smuzhiyun {
1251*4882a593Smuzhiyun 	u16 bl_status = 0;
1252*4882a593Smuzhiyun 	int status;
1253*4882a593Smuzhiyun 	unsigned long end;
1254*4882a593Smuzhiyun 
1255*4882a593Smuzhiyun 	dprintk(1, "\n");
1256*4882a593Smuzhiyun 	mutex_lock(&state->mutex);
1257*4882a593Smuzhiyun 	status = write16(state, SIO_BL_MODE__A, SIO_BL_MODE_CHAIN);
1258*4882a593Smuzhiyun 	if (status < 0)
1259*4882a593Smuzhiyun 		goto error;
1260*4882a593Smuzhiyun 	status = write16(state, SIO_BL_CHAIN_ADDR__A, rom_offset);
1261*4882a593Smuzhiyun 	if (status < 0)
1262*4882a593Smuzhiyun 		goto error;
1263*4882a593Smuzhiyun 	status = write16(state, SIO_BL_CHAIN_LEN__A, nr_of_elements);
1264*4882a593Smuzhiyun 	if (status < 0)
1265*4882a593Smuzhiyun 		goto error;
1266*4882a593Smuzhiyun 	status = write16(state, SIO_BL_ENABLE__A, SIO_BL_ENABLE_ON);
1267*4882a593Smuzhiyun 	if (status < 0)
1268*4882a593Smuzhiyun 		goto error;
1269*4882a593Smuzhiyun 
1270*4882a593Smuzhiyun 	end = jiffies + msecs_to_jiffies(time_out);
1271*4882a593Smuzhiyun 	do {
1272*4882a593Smuzhiyun 		usleep_range(1000, 2000);
1273*4882a593Smuzhiyun 		status = read16(state, SIO_BL_STATUS__A, &bl_status);
1274*4882a593Smuzhiyun 		if (status < 0)
1275*4882a593Smuzhiyun 			goto error;
1276*4882a593Smuzhiyun 	} while ((bl_status == 0x1) &&
1277*4882a593Smuzhiyun 			((time_is_after_jiffies(end))));
1278*4882a593Smuzhiyun 
1279*4882a593Smuzhiyun 	if (bl_status == 0x1) {
1280*4882a593Smuzhiyun 		pr_err("SIO not ready\n");
1281*4882a593Smuzhiyun 		status = -EINVAL;
1282*4882a593Smuzhiyun 		goto error2;
1283*4882a593Smuzhiyun 	}
1284*4882a593Smuzhiyun error:
1285*4882a593Smuzhiyun 	if (status < 0)
1286*4882a593Smuzhiyun 		pr_err("Error %d on %s\n", status, __func__);
1287*4882a593Smuzhiyun error2:
1288*4882a593Smuzhiyun 	mutex_unlock(&state->mutex);
1289*4882a593Smuzhiyun 	return status;
1290*4882a593Smuzhiyun }
1291*4882a593Smuzhiyun 
1292*4882a593Smuzhiyun 
download_microcode(struct drxk_state * state,const u8 p_mc_image[],u32 length)1293*4882a593Smuzhiyun static int download_microcode(struct drxk_state *state,
1294*4882a593Smuzhiyun 			     const u8 p_mc_image[], u32 length)
1295*4882a593Smuzhiyun {
1296*4882a593Smuzhiyun 	const u8 *p_src = p_mc_image;
1297*4882a593Smuzhiyun 	u32 address;
1298*4882a593Smuzhiyun 	u16 n_blocks;
1299*4882a593Smuzhiyun 	u16 block_size;
1300*4882a593Smuzhiyun 	u32 offset = 0;
1301*4882a593Smuzhiyun 	u32 i;
1302*4882a593Smuzhiyun 	int status = 0;
1303*4882a593Smuzhiyun 
1304*4882a593Smuzhiyun 	dprintk(1, "\n");
1305*4882a593Smuzhiyun 
1306*4882a593Smuzhiyun 	/* down the drain (we don't care about MAGIC_WORD) */
1307*4882a593Smuzhiyun #if 0
1308*4882a593Smuzhiyun 	/* For future reference */
1309*4882a593Smuzhiyun 	drain = (p_src[0] << 8) | p_src[1];
1310*4882a593Smuzhiyun #endif
1311*4882a593Smuzhiyun 	p_src += sizeof(u16);
1312*4882a593Smuzhiyun 	offset += sizeof(u16);
1313*4882a593Smuzhiyun 	n_blocks = (p_src[0] << 8) | p_src[1];
1314*4882a593Smuzhiyun 	p_src += sizeof(u16);
1315*4882a593Smuzhiyun 	offset += sizeof(u16);
1316*4882a593Smuzhiyun 
1317*4882a593Smuzhiyun 	for (i = 0; i < n_blocks; i += 1) {
1318*4882a593Smuzhiyun 		address = (p_src[0] << 24) | (p_src[1] << 16) |
1319*4882a593Smuzhiyun 		    (p_src[2] << 8) | p_src[3];
1320*4882a593Smuzhiyun 		p_src += sizeof(u32);
1321*4882a593Smuzhiyun 		offset += sizeof(u32);
1322*4882a593Smuzhiyun 
1323*4882a593Smuzhiyun 		block_size = ((p_src[0] << 8) | p_src[1]) * sizeof(u16);
1324*4882a593Smuzhiyun 		p_src += sizeof(u16);
1325*4882a593Smuzhiyun 		offset += sizeof(u16);
1326*4882a593Smuzhiyun 
1327*4882a593Smuzhiyun #if 0
1328*4882a593Smuzhiyun 		/* For future reference */
1329*4882a593Smuzhiyun 		flags = (p_src[0] << 8) | p_src[1];
1330*4882a593Smuzhiyun #endif
1331*4882a593Smuzhiyun 		p_src += sizeof(u16);
1332*4882a593Smuzhiyun 		offset += sizeof(u16);
1333*4882a593Smuzhiyun 
1334*4882a593Smuzhiyun #if 0
1335*4882a593Smuzhiyun 		/* For future reference */
1336*4882a593Smuzhiyun 		block_crc = (p_src[0] << 8) | p_src[1];
1337*4882a593Smuzhiyun #endif
1338*4882a593Smuzhiyun 		p_src += sizeof(u16);
1339*4882a593Smuzhiyun 		offset += sizeof(u16);
1340*4882a593Smuzhiyun 
1341*4882a593Smuzhiyun 		if (offset + block_size > length) {
1342*4882a593Smuzhiyun 			pr_err("Firmware is corrupted.\n");
1343*4882a593Smuzhiyun 			return -EINVAL;
1344*4882a593Smuzhiyun 		}
1345*4882a593Smuzhiyun 
1346*4882a593Smuzhiyun 		status = write_block(state, address, block_size, p_src);
1347*4882a593Smuzhiyun 		if (status < 0) {
1348*4882a593Smuzhiyun 			pr_err("Error %d while loading firmware\n", status);
1349*4882a593Smuzhiyun 			break;
1350*4882a593Smuzhiyun 		}
1351*4882a593Smuzhiyun 		p_src += block_size;
1352*4882a593Smuzhiyun 		offset += block_size;
1353*4882a593Smuzhiyun 	}
1354*4882a593Smuzhiyun 	return status;
1355*4882a593Smuzhiyun }
1356*4882a593Smuzhiyun 
dvbt_enable_ofdm_token_ring(struct drxk_state * state,bool enable)1357*4882a593Smuzhiyun static int dvbt_enable_ofdm_token_ring(struct drxk_state *state, bool enable)
1358*4882a593Smuzhiyun {
1359*4882a593Smuzhiyun 	int status;
1360*4882a593Smuzhiyun 	u16 data = 0;
1361*4882a593Smuzhiyun 	u16 desired_ctrl = SIO_OFDM_SH_OFDM_RING_ENABLE_ON;
1362*4882a593Smuzhiyun 	u16 desired_status = SIO_OFDM_SH_OFDM_RING_STATUS_ENABLED;
1363*4882a593Smuzhiyun 	unsigned long end;
1364*4882a593Smuzhiyun 
1365*4882a593Smuzhiyun 	dprintk(1, "\n");
1366*4882a593Smuzhiyun 
1367*4882a593Smuzhiyun 	if (!enable) {
1368*4882a593Smuzhiyun 		desired_ctrl = SIO_OFDM_SH_OFDM_RING_ENABLE_OFF;
1369*4882a593Smuzhiyun 		desired_status = SIO_OFDM_SH_OFDM_RING_STATUS_DOWN;
1370*4882a593Smuzhiyun 	}
1371*4882a593Smuzhiyun 
1372*4882a593Smuzhiyun 	status = read16(state, SIO_OFDM_SH_OFDM_RING_STATUS__A, &data);
1373*4882a593Smuzhiyun 	if (status >= 0 && data == desired_status) {
1374*4882a593Smuzhiyun 		/* tokenring already has correct status */
1375*4882a593Smuzhiyun 		return status;
1376*4882a593Smuzhiyun 	}
1377*4882a593Smuzhiyun 	/* Disable/enable dvbt tokenring bridge   */
1378*4882a593Smuzhiyun 	status = write16(state, SIO_OFDM_SH_OFDM_RING_ENABLE__A, desired_ctrl);
1379*4882a593Smuzhiyun 
1380*4882a593Smuzhiyun 	end = jiffies + msecs_to_jiffies(DRXK_OFDM_TR_SHUTDOWN_TIMEOUT);
1381*4882a593Smuzhiyun 	do {
1382*4882a593Smuzhiyun 		status = read16(state, SIO_OFDM_SH_OFDM_RING_STATUS__A, &data);
1383*4882a593Smuzhiyun 		if ((status >= 0 && data == desired_status)
1384*4882a593Smuzhiyun 		    || time_is_after_jiffies(end))
1385*4882a593Smuzhiyun 			break;
1386*4882a593Smuzhiyun 		usleep_range(1000, 2000);
1387*4882a593Smuzhiyun 	} while (1);
1388*4882a593Smuzhiyun 	if (data != desired_status) {
1389*4882a593Smuzhiyun 		pr_err("SIO not ready\n");
1390*4882a593Smuzhiyun 		return -EINVAL;
1391*4882a593Smuzhiyun 	}
1392*4882a593Smuzhiyun 	return status;
1393*4882a593Smuzhiyun }
1394*4882a593Smuzhiyun 
mpegts_stop(struct drxk_state * state)1395*4882a593Smuzhiyun static int mpegts_stop(struct drxk_state *state)
1396*4882a593Smuzhiyun {
1397*4882a593Smuzhiyun 	int status = 0;
1398*4882a593Smuzhiyun 	u16 fec_oc_snc_mode = 0;
1399*4882a593Smuzhiyun 	u16 fec_oc_ipr_mode = 0;
1400*4882a593Smuzhiyun 
1401*4882a593Smuzhiyun 	dprintk(1, "\n");
1402*4882a593Smuzhiyun 
1403*4882a593Smuzhiyun 	/* Graceful shutdown (byte boundaries) */
1404*4882a593Smuzhiyun 	status = read16(state, FEC_OC_SNC_MODE__A, &fec_oc_snc_mode);
1405*4882a593Smuzhiyun 	if (status < 0)
1406*4882a593Smuzhiyun 		goto error;
1407*4882a593Smuzhiyun 	fec_oc_snc_mode |= FEC_OC_SNC_MODE_SHUTDOWN__M;
1408*4882a593Smuzhiyun 	status = write16(state, FEC_OC_SNC_MODE__A, fec_oc_snc_mode);
1409*4882a593Smuzhiyun 	if (status < 0)
1410*4882a593Smuzhiyun 		goto error;
1411*4882a593Smuzhiyun 
1412*4882a593Smuzhiyun 	/* Suppress MCLK during absence of data */
1413*4882a593Smuzhiyun 	status = read16(state, FEC_OC_IPR_MODE__A, &fec_oc_ipr_mode);
1414*4882a593Smuzhiyun 	if (status < 0)
1415*4882a593Smuzhiyun 		goto error;
1416*4882a593Smuzhiyun 	fec_oc_ipr_mode |= FEC_OC_IPR_MODE_MCLK_DIS_DAT_ABS__M;
1417*4882a593Smuzhiyun 	status = write16(state, FEC_OC_IPR_MODE__A, fec_oc_ipr_mode);
1418*4882a593Smuzhiyun 
1419*4882a593Smuzhiyun error:
1420*4882a593Smuzhiyun 	if (status < 0)
1421*4882a593Smuzhiyun 		pr_err("Error %d on %s\n", status, __func__);
1422*4882a593Smuzhiyun 
1423*4882a593Smuzhiyun 	return status;
1424*4882a593Smuzhiyun }
1425*4882a593Smuzhiyun 
scu_command(struct drxk_state * state,u16 cmd,u8 parameter_len,u16 * parameter,u8 result_len,u16 * result)1426*4882a593Smuzhiyun static int scu_command(struct drxk_state *state,
1427*4882a593Smuzhiyun 		       u16 cmd, u8 parameter_len,
1428*4882a593Smuzhiyun 		       u16 *parameter, u8 result_len, u16 *result)
1429*4882a593Smuzhiyun {
1430*4882a593Smuzhiyun #if (SCU_RAM_PARAM_0__A - SCU_RAM_PARAM_15__A) != 15
1431*4882a593Smuzhiyun #error DRXK register mapping no longer compatible with this routine!
1432*4882a593Smuzhiyun #endif
1433*4882a593Smuzhiyun 	u16 cur_cmd = 0;
1434*4882a593Smuzhiyun 	int status = -EINVAL;
1435*4882a593Smuzhiyun 	unsigned long end;
1436*4882a593Smuzhiyun 	u8 buffer[34];
1437*4882a593Smuzhiyun 	int cnt = 0, ii;
1438*4882a593Smuzhiyun 	const char *p;
1439*4882a593Smuzhiyun 	char errname[30];
1440*4882a593Smuzhiyun 
1441*4882a593Smuzhiyun 	dprintk(1, "\n");
1442*4882a593Smuzhiyun 
1443*4882a593Smuzhiyun 	if ((cmd == 0) || ((parameter_len > 0) && (parameter == NULL)) ||
1444*4882a593Smuzhiyun 	    ((result_len > 0) && (result == NULL))) {
1445*4882a593Smuzhiyun 		pr_err("Error %d on %s\n", status, __func__);
1446*4882a593Smuzhiyun 		return status;
1447*4882a593Smuzhiyun 	}
1448*4882a593Smuzhiyun 
1449*4882a593Smuzhiyun 	mutex_lock(&state->mutex);
1450*4882a593Smuzhiyun 
1451*4882a593Smuzhiyun 	/* assume that the command register is ready
1452*4882a593Smuzhiyun 		since it is checked afterwards */
1453*4882a593Smuzhiyun 	if (parameter) {
1454*4882a593Smuzhiyun 		for (ii = parameter_len - 1; ii >= 0; ii -= 1) {
1455*4882a593Smuzhiyun 			buffer[cnt++] = (parameter[ii] & 0xFF);
1456*4882a593Smuzhiyun 			buffer[cnt++] = ((parameter[ii] >> 8) & 0xFF);
1457*4882a593Smuzhiyun 		}
1458*4882a593Smuzhiyun 	}
1459*4882a593Smuzhiyun 	buffer[cnt++] = (cmd & 0xFF);
1460*4882a593Smuzhiyun 	buffer[cnt++] = ((cmd >> 8) & 0xFF);
1461*4882a593Smuzhiyun 
1462*4882a593Smuzhiyun 	write_block(state, SCU_RAM_PARAM_0__A -
1463*4882a593Smuzhiyun 			(parameter_len - 1), cnt, buffer);
1464*4882a593Smuzhiyun 	/* Wait until SCU has processed command */
1465*4882a593Smuzhiyun 	end = jiffies + msecs_to_jiffies(DRXK_MAX_WAITTIME);
1466*4882a593Smuzhiyun 	do {
1467*4882a593Smuzhiyun 		usleep_range(1000, 2000);
1468*4882a593Smuzhiyun 		status = read16(state, SCU_RAM_COMMAND__A, &cur_cmd);
1469*4882a593Smuzhiyun 		if (status < 0)
1470*4882a593Smuzhiyun 			goto error;
1471*4882a593Smuzhiyun 	} while (!(cur_cmd == DRX_SCU_READY) && (time_is_after_jiffies(end)));
1472*4882a593Smuzhiyun 	if (cur_cmd != DRX_SCU_READY) {
1473*4882a593Smuzhiyun 		pr_err("SCU not ready\n");
1474*4882a593Smuzhiyun 		status = -EIO;
1475*4882a593Smuzhiyun 		goto error2;
1476*4882a593Smuzhiyun 	}
1477*4882a593Smuzhiyun 	/* read results */
1478*4882a593Smuzhiyun 	if ((result_len > 0) && (result != NULL)) {
1479*4882a593Smuzhiyun 		s16 err;
1480*4882a593Smuzhiyun 		int ii;
1481*4882a593Smuzhiyun 
1482*4882a593Smuzhiyun 		for (ii = result_len - 1; ii >= 0; ii -= 1) {
1483*4882a593Smuzhiyun 			status = read16(state, SCU_RAM_PARAM_0__A - ii,
1484*4882a593Smuzhiyun 					&result[ii]);
1485*4882a593Smuzhiyun 			if (status < 0)
1486*4882a593Smuzhiyun 				goto error;
1487*4882a593Smuzhiyun 		}
1488*4882a593Smuzhiyun 
1489*4882a593Smuzhiyun 		/* Check if an error was reported by SCU */
1490*4882a593Smuzhiyun 		err = (s16)result[0];
1491*4882a593Smuzhiyun 		if (err >= 0)
1492*4882a593Smuzhiyun 			goto error;
1493*4882a593Smuzhiyun 
1494*4882a593Smuzhiyun 		/* check for the known error codes */
1495*4882a593Smuzhiyun 		switch (err) {
1496*4882a593Smuzhiyun 		case SCU_RESULT_UNKCMD:
1497*4882a593Smuzhiyun 			p = "SCU_RESULT_UNKCMD";
1498*4882a593Smuzhiyun 			break;
1499*4882a593Smuzhiyun 		case SCU_RESULT_UNKSTD:
1500*4882a593Smuzhiyun 			p = "SCU_RESULT_UNKSTD";
1501*4882a593Smuzhiyun 			break;
1502*4882a593Smuzhiyun 		case SCU_RESULT_SIZE:
1503*4882a593Smuzhiyun 			p = "SCU_RESULT_SIZE";
1504*4882a593Smuzhiyun 			break;
1505*4882a593Smuzhiyun 		case SCU_RESULT_INVPAR:
1506*4882a593Smuzhiyun 			p = "SCU_RESULT_INVPAR";
1507*4882a593Smuzhiyun 			break;
1508*4882a593Smuzhiyun 		default: /* Other negative values are errors */
1509*4882a593Smuzhiyun 			sprintf(errname, "ERROR: %d\n", err);
1510*4882a593Smuzhiyun 			p = errname;
1511*4882a593Smuzhiyun 		}
1512*4882a593Smuzhiyun 		pr_err("%s while sending cmd 0x%04x with params:", p, cmd);
1513*4882a593Smuzhiyun 		print_hex_dump_bytes("drxk: ", DUMP_PREFIX_NONE, buffer, cnt);
1514*4882a593Smuzhiyun 		status = -EINVAL;
1515*4882a593Smuzhiyun 		goto error2;
1516*4882a593Smuzhiyun 	}
1517*4882a593Smuzhiyun 
1518*4882a593Smuzhiyun error:
1519*4882a593Smuzhiyun 	if (status < 0)
1520*4882a593Smuzhiyun 		pr_err("Error %d on %s\n", status, __func__);
1521*4882a593Smuzhiyun error2:
1522*4882a593Smuzhiyun 	mutex_unlock(&state->mutex);
1523*4882a593Smuzhiyun 	return status;
1524*4882a593Smuzhiyun }
1525*4882a593Smuzhiyun 
set_iqm_af(struct drxk_state * state,bool active)1526*4882a593Smuzhiyun static int set_iqm_af(struct drxk_state *state, bool active)
1527*4882a593Smuzhiyun {
1528*4882a593Smuzhiyun 	u16 data = 0;
1529*4882a593Smuzhiyun 	int status;
1530*4882a593Smuzhiyun 
1531*4882a593Smuzhiyun 	dprintk(1, "\n");
1532*4882a593Smuzhiyun 
1533*4882a593Smuzhiyun 	/* Configure IQM */
1534*4882a593Smuzhiyun 	status = read16(state, IQM_AF_STDBY__A, &data);
1535*4882a593Smuzhiyun 	if (status < 0)
1536*4882a593Smuzhiyun 		goto error;
1537*4882a593Smuzhiyun 
1538*4882a593Smuzhiyun 	if (!active) {
1539*4882a593Smuzhiyun 		data |= (IQM_AF_STDBY_STDBY_ADC_STANDBY
1540*4882a593Smuzhiyun 				| IQM_AF_STDBY_STDBY_AMP_STANDBY
1541*4882a593Smuzhiyun 				| IQM_AF_STDBY_STDBY_PD_STANDBY
1542*4882a593Smuzhiyun 				| IQM_AF_STDBY_STDBY_TAGC_IF_STANDBY
1543*4882a593Smuzhiyun 				| IQM_AF_STDBY_STDBY_TAGC_RF_STANDBY);
1544*4882a593Smuzhiyun 	} else {
1545*4882a593Smuzhiyun 		data &= ((~IQM_AF_STDBY_STDBY_ADC_STANDBY)
1546*4882a593Smuzhiyun 				& (~IQM_AF_STDBY_STDBY_AMP_STANDBY)
1547*4882a593Smuzhiyun 				& (~IQM_AF_STDBY_STDBY_PD_STANDBY)
1548*4882a593Smuzhiyun 				& (~IQM_AF_STDBY_STDBY_TAGC_IF_STANDBY)
1549*4882a593Smuzhiyun 				& (~IQM_AF_STDBY_STDBY_TAGC_RF_STANDBY)
1550*4882a593Smuzhiyun 			);
1551*4882a593Smuzhiyun 	}
1552*4882a593Smuzhiyun 	status = write16(state, IQM_AF_STDBY__A, data);
1553*4882a593Smuzhiyun 
1554*4882a593Smuzhiyun error:
1555*4882a593Smuzhiyun 	if (status < 0)
1556*4882a593Smuzhiyun 		pr_err("Error %d on %s\n", status, __func__);
1557*4882a593Smuzhiyun 	return status;
1558*4882a593Smuzhiyun }
1559*4882a593Smuzhiyun 
ctrl_power_mode(struct drxk_state * state,enum drx_power_mode * mode)1560*4882a593Smuzhiyun static int ctrl_power_mode(struct drxk_state *state, enum drx_power_mode *mode)
1561*4882a593Smuzhiyun {
1562*4882a593Smuzhiyun 	int status = 0;
1563*4882a593Smuzhiyun 	u16 sio_cc_pwd_mode = 0;
1564*4882a593Smuzhiyun 
1565*4882a593Smuzhiyun 	dprintk(1, "\n");
1566*4882a593Smuzhiyun 
1567*4882a593Smuzhiyun 	/* Check arguments */
1568*4882a593Smuzhiyun 	if (mode == NULL)
1569*4882a593Smuzhiyun 		return -EINVAL;
1570*4882a593Smuzhiyun 
1571*4882a593Smuzhiyun 	switch (*mode) {
1572*4882a593Smuzhiyun 	case DRX_POWER_UP:
1573*4882a593Smuzhiyun 		sio_cc_pwd_mode = SIO_CC_PWD_MODE_LEVEL_NONE;
1574*4882a593Smuzhiyun 		break;
1575*4882a593Smuzhiyun 	case DRXK_POWER_DOWN_OFDM:
1576*4882a593Smuzhiyun 		sio_cc_pwd_mode = SIO_CC_PWD_MODE_LEVEL_OFDM;
1577*4882a593Smuzhiyun 		break;
1578*4882a593Smuzhiyun 	case DRXK_POWER_DOWN_CORE:
1579*4882a593Smuzhiyun 		sio_cc_pwd_mode = SIO_CC_PWD_MODE_LEVEL_CLOCK;
1580*4882a593Smuzhiyun 		break;
1581*4882a593Smuzhiyun 	case DRXK_POWER_DOWN_PLL:
1582*4882a593Smuzhiyun 		sio_cc_pwd_mode = SIO_CC_PWD_MODE_LEVEL_PLL;
1583*4882a593Smuzhiyun 		break;
1584*4882a593Smuzhiyun 	case DRX_POWER_DOWN:
1585*4882a593Smuzhiyun 		sio_cc_pwd_mode = SIO_CC_PWD_MODE_LEVEL_OSC;
1586*4882a593Smuzhiyun 		break;
1587*4882a593Smuzhiyun 	default:
1588*4882a593Smuzhiyun 		/* Unknow sleep mode */
1589*4882a593Smuzhiyun 		return -EINVAL;
1590*4882a593Smuzhiyun 	}
1591*4882a593Smuzhiyun 
1592*4882a593Smuzhiyun 	/* If already in requested power mode, do nothing */
1593*4882a593Smuzhiyun 	if (state->m_current_power_mode == *mode)
1594*4882a593Smuzhiyun 		return 0;
1595*4882a593Smuzhiyun 
1596*4882a593Smuzhiyun 	/* For next steps make sure to start from DRX_POWER_UP mode */
1597*4882a593Smuzhiyun 	if (state->m_current_power_mode != DRX_POWER_UP) {
1598*4882a593Smuzhiyun 		status = power_up_device(state);
1599*4882a593Smuzhiyun 		if (status < 0)
1600*4882a593Smuzhiyun 			goto error;
1601*4882a593Smuzhiyun 		status = dvbt_enable_ofdm_token_ring(state, true);
1602*4882a593Smuzhiyun 		if (status < 0)
1603*4882a593Smuzhiyun 			goto error;
1604*4882a593Smuzhiyun 	}
1605*4882a593Smuzhiyun 
1606*4882a593Smuzhiyun 	if (*mode == DRX_POWER_UP) {
1607*4882a593Smuzhiyun 		/* Restore analog & pin configuration */
1608*4882a593Smuzhiyun 	} else {
1609*4882a593Smuzhiyun 		/* Power down to requested mode */
1610*4882a593Smuzhiyun 		/* Backup some register settings */
1611*4882a593Smuzhiyun 		/* Set pins with possible pull-ups connected
1612*4882a593Smuzhiyun 		   to them in input mode */
1613*4882a593Smuzhiyun 		/* Analog power down */
1614*4882a593Smuzhiyun 		/* ADC power down */
1615*4882a593Smuzhiyun 		/* Power down device */
1616*4882a593Smuzhiyun 		/* stop all comm_exec */
1617*4882a593Smuzhiyun 		/* Stop and power down previous standard */
1618*4882a593Smuzhiyun 		switch (state->m_operation_mode) {
1619*4882a593Smuzhiyun 		case OM_DVBT:
1620*4882a593Smuzhiyun 			status = mpegts_stop(state);
1621*4882a593Smuzhiyun 			if (status < 0)
1622*4882a593Smuzhiyun 				goto error;
1623*4882a593Smuzhiyun 			status = power_down_dvbt(state, false);
1624*4882a593Smuzhiyun 			if (status < 0)
1625*4882a593Smuzhiyun 				goto error;
1626*4882a593Smuzhiyun 			break;
1627*4882a593Smuzhiyun 		case OM_QAM_ITU_A:
1628*4882a593Smuzhiyun 		case OM_QAM_ITU_C:
1629*4882a593Smuzhiyun 			status = mpegts_stop(state);
1630*4882a593Smuzhiyun 			if (status < 0)
1631*4882a593Smuzhiyun 				goto error;
1632*4882a593Smuzhiyun 			status = power_down_qam(state);
1633*4882a593Smuzhiyun 			if (status < 0)
1634*4882a593Smuzhiyun 				goto error;
1635*4882a593Smuzhiyun 			break;
1636*4882a593Smuzhiyun 		default:
1637*4882a593Smuzhiyun 			break;
1638*4882a593Smuzhiyun 		}
1639*4882a593Smuzhiyun 		status = dvbt_enable_ofdm_token_ring(state, false);
1640*4882a593Smuzhiyun 		if (status < 0)
1641*4882a593Smuzhiyun 			goto error;
1642*4882a593Smuzhiyun 		status = write16(state, SIO_CC_PWD_MODE__A, sio_cc_pwd_mode);
1643*4882a593Smuzhiyun 		if (status < 0)
1644*4882a593Smuzhiyun 			goto error;
1645*4882a593Smuzhiyun 		status = write16(state, SIO_CC_UPDATE__A, SIO_CC_UPDATE_KEY);
1646*4882a593Smuzhiyun 		if (status < 0)
1647*4882a593Smuzhiyun 			goto error;
1648*4882a593Smuzhiyun 
1649*4882a593Smuzhiyun 		if (*mode != DRXK_POWER_DOWN_OFDM) {
1650*4882a593Smuzhiyun 			state->m_hi_cfg_ctrl |=
1651*4882a593Smuzhiyun 				SIO_HI_RA_RAM_PAR_5_CFG_SLEEP_ZZZ;
1652*4882a593Smuzhiyun 			status = hi_cfg_command(state);
1653*4882a593Smuzhiyun 			if (status < 0)
1654*4882a593Smuzhiyun 				goto error;
1655*4882a593Smuzhiyun 		}
1656*4882a593Smuzhiyun 	}
1657*4882a593Smuzhiyun 	state->m_current_power_mode = *mode;
1658*4882a593Smuzhiyun 
1659*4882a593Smuzhiyun error:
1660*4882a593Smuzhiyun 	if (status < 0)
1661*4882a593Smuzhiyun 		pr_err("Error %d on %s\n", status, __func__);
1662*4882a593Smuzhiyun 
1663*4882a593Smuzhiyun 	return status;
1664*4882a593Smuzhiyun }
1665*4882a593Smuzhiyun 
power_down_dvbt(struct drxk_state * state,bool set_power_mode)1666*4882a593Smuzhiyun static int power_down_dvbt(struct drxk_state *state, bool set_power_mode)
1667*4882a593Smuzhiyun {
1668*4882a593Smuzhiyun 	enum drx_power_mode power_mode = DRXK_POWER_DOWN_OFDM;
1669*4882a593Smuzhiyun 	u16 cmd_result = 0;
1670*4882a593Smuzhiyun 	u16 data = 0;
1671*4882a593Smuzhiyun 	int status;
1672*4882a593Smuzhiyun 
1673*4882a593Smuzhiyun 	dprintk(1, "\n");
1674*4882a593Smuzhiyun 
1675*4882a593Smuzhiyun 	status = read16(state, SCU_COMM_EXEC__A, &data);
1676*4882a593Smuzhiyun 	if (status < 0)
1677*4882a593Smuzhiyun 		goto error;
1678*4882a593Smuzhiyun 	if (data == SCU_COMM_EXEC_ACTIVE) {
1679*4882a593Smuzhiyun 		/* Send OFDM stop command */
1680*4882a593Smuzhiyun 		status = scu_command(state,
1681*4882a593Smuzhiyun 				     SCU_RAM_COMMAND_STANDARD_OFDM
1682*4882a593Smuzhiyun 				     | SCU_RAM_COMMAND_CMD_DEMOD_STOP,
1683*4882a593Smuzhiyun 				     0, NULL, 1, &cmd_result);
1684*4882a593Smuzhiyun 		if (status < 0)
1685*4882a593Smuzhiyun 			goto error;
1686*4882a593Smuzhiyun 		/* Send OFDM reset command */
1687*4882a593Smuzhiyun 		status = scu_command(state,
1688*4882a593Smuzhiyun 				     SCU_RAM_COMMAND_STANDARD_OFDM
1689*4882a593Smuzhiyun 				     | SCU_RAM_COMMAND_CMD_DEMOD_RESET,
1690*4882a593Smuzhiyun 				     0, NULL, 1, &cmd_result);
1691*4882a593Smuzhiyun 		if (status < 0)
1692*4882a593Smuzhiyun 			goto error;
1693*4882a593Smuzhiyun 	}
1694*4882a593Smuzhiyun 
1695*4882a593Smuzhiyun 	/* Reset datapath for OFDM, processors first */
1696*4882a593Smuzhiyun 	status = write16(state, OFDM_SC_COMM_EXEC__A, OFDM_SC_COMM_EXEC_STOP);
1697*4882a593Smuzhiyun 	if (status < 0)
1698*4882a593Smuzhiyun 		goto error;
1699*4882a593Smuzhiyun 	status = write16(state, OFDM_LC_COMM_EXEC__A, OFDM_LC_COMM_EXEC_STOP);
1700*4882a593Smuzhiyun 	if (status < 0)
1701*4882a593Smuzhiyun 		goto error;
1702*4882a593Smuzhiyun 	status = write16(state, IQM_COMM_EXEC__A, IQM_COMM_EXEC_B_STOP);
1703*4882a593Smuzhiyun 	if (status < 0)
1704*4882a593Smuzhiyun 		goto error;
1705*4882a593Smuzhiyun 
1706*4882a593Smuzhiyun 	/* powerdown AFE                   */
1707*4882a593Smuzhiyun 	status = set_iqm_af(state, false);
1708*4882a593Smuzhiyun 	if (status < 0)
1709*4882a593Smuzhiyun 		goto error;
1710*4882a593Smuzhiyun 
1711*4882a593Smuzhiyun 	/* powerdown to OFDM mode          */
1712*4882a593Smuzhiyun 	if (set_power_mode) {
1713*4882a593Smuzhiyun 		status = ctrl_power_mode(state, &power_mode);
1714*4882a593Smuzhiyun 		if (status < 0)
1715*4882a593Smuzhiyun 			goto error;
1716*4882a593Smuzhiyun 	}
1717*4882a593Smuzhiyun error:
1718*4882a593Smuzhiyun 	if (status < 0)
1719*4882a593Smuzhiyun 		pr_err("Error %d on %s\n", status, __func__);
1720*4882a593Smuzhiyun 	return status;
1721*4882a593Smuzhiyun }
1722*4882a593Smuzhiyun 
setoperation_mode(struct drxk_state * state,enum operation_mode o_mode)1723*4882a593Smuzhiyun static int setoperation_mode(struct drxk_state *state,
1724*4882a593Smuzhiyun 			    enum operation_mode o_mode)
1725*4882a593Smuzhiyun {
1726*4882a593Smuzhiyun 	int status = 0;
1727*4882a593Smuzhiyun 
1728*4882a593Smuzhiyun 	dprintk(1, "\n");
1729*4882a593Smuzhiyun 	/*
1730*4882a593Smuzhiyun 	   Stop and power down previous standard
1731*4882a593Smuzhiyun 	   TODO investigate total power down instead of partial
1732*4882a593Smuzhiyun 	   power down depending on "previous" standard.
1733*4882a593Smuzhiyun 	 */
1734*4882a593Smuzhiyun 
1735*4882a593Smuzhiyun 	/* disable HW lock indicator */
1736*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_GPIO__A,
1737*4882a593Smuzhiyun 			 SCU_RAM_GPIO_HW_LOCK_IND_DISABLE);
1738*4882a593Smuzhiyun 	if (status < 0)
1739*4882a593Smuzhiyun 		goto error;
1740*4882a593Smuzhiyun 
1741*4882a593Smuzhiyun 	/* Device is already at the required mode */
1742*4882a593Smuzhiyun 	if (state->m_operation_mode == o_mode)
1743*4882a593Smuzhiyun 		return 0;
1744*4882a593Smuzhiyun 
1745*4882a593Smuzhiyun 	switch (state->m_operation_mode) {
1746*4882a593Smuzhiyun 		/* OM_NONE was added for start up */
1747*4882a593Smuzhiyun 	case OM_NONE:
1748*4882a593Smuzhiyun 		break;
1749*4882a593Smuzhiyun 	case OM_DVBT:
1750*4882a593Smuzhiyun 		status = mpegts_stop(state);
1751*4882a593Smuzhiyun 		if (status < 0)
1752*4882a593Smuzhiyun 			goto error;
1753*4882a593Smuzhiyun 		status = power_down_dvbt(state, true);
1754*4882a593Smuzhiyun 		if (status < 0)
1755*4882a593Smuzhiyun 			goto error;
1756*4882a593Smuzhiyun 		state->m_operation_mode = OM_NONE;
1757*4882a593Smuzhiyun 		break;
1758*4882a593Smuzhiyun 	case OM_QAM_ITU_A:
1759*4882a593Smuzhiyun 	case OM_QAM_ITU_C:
1760*4882a593Smuzhiyun 		status = mpegts_stop(state);
1761*4882a593Smuzhiyun 		if (status < 0)
1762*4882a593Smuzhiyun 			goto error;
1763*4882a593Smuzhiyun 		status = power_down_qam(state);
1764*4882a593Smuzhiyun 		if (status < 0)
1765*4882a593Smuzhiyun 			goto error;
1766*4882a593Smuzhiyun 		state->m_operation_mode = OM_NONE;
1767*4882a593Smuzhiyun 		break;
1768*4882a593Smuzhiyun 	case OM_QAM_ITU_B:
1769*4882a593Smuzhiyun 	default:
1770*4882a593Smuzhiyun 		status = -EINVAL;
1771*4882a593Smuzhiyun 		goto error;
1772*4882a593Smuzhiyun 	}
1773*4882a593Smuzhiyun 
1774*4882a593Smuzhiyun 	/*
1775*4882a593Smuzhiyun 		Power up new standard
1776*4882a593Smuzhiyun 		*/
1777*4882a593Smuzhiyun 	switch (o_mode) {
1778*4882a593Smuzhiyun 	case OM_DVBT:
1779*4882a593Smuzhiyun 		dprintk(1, ": DVB-T\n");
1780*4882a593Smuzhiyun 		state->m_operation_mode = o_mode;
1781*4882a593Smuzhiyun 		status = set_dvbt_standard(state, o_mode);
1782*4882a593Smuzhiyun 		if (status < 0)
1783*4882a593Smuzhiyun 			goto error;
1784*4882a593Smuzhiyun 		break;
1785*4882a593Smuzhiyun 	case OM_QAM_ITU_A:
1786*4882a593Smuzhiyun 	case OM_QAM_ITU_C:
1787*4882a593Smuzhiyun 		dprintk(1, ": DVB-C Annex %c\n",
1788*4882a593Smuzhiyun 			(state->m_operation_mode == OM_QAM_ITU_A) ? 'A' : 'C');
1789*4882a593Smuzhiyun 		state->m_operation_mode = o_mode;
1790*4882a593Smuzhiyun 		status = set_qam_standard(state, o_mode);
1791*4882a593Smuzhiyun 		if (status < 0)
1792*4882a593Smuzhiyun 			goto error;
1793*4882a593Smuzhiyun 		break;
1794*4882a593Smuzhiyun 	case OM_QAM_ITU_B:
1795*4882a593Smuzhiyun 	default:
1796*4882a593Smuzhiyun 		status = -EINVAL;
1797*4882a593Smuzhiyun 	}
1798*4882a593Smuzhiyun error:
1799*4882a593Smuzhiyun 	if (status < 0)
1800*4882a593Smuzhiyun 		pr_err("Error %d on %s\n", status, __func__);
1801*4882a593Smuzhiyun 	return status;
1802*4882a593Smuzhiyun }
1803*4882a593Smuzhiyun 
start(struct drxk_state * state,s32 offset_freq,s32 intermediate_frequency)1804*4882a593Smuzhiyun static int start(struct drxk_state *state, s32 offset_freq,
1805*4882a593Smuzhiyun 		 s32 intermediate_frequency)
1806*4882a593Smuzhiyun {
1807*4882a593Smuzhiyun 	int status = -EINVAL;
1808*4882a593Smuzhiyun 
1809*4882a593Smuzhiyun 	u16 i_freqk_hz;
1810*4882a593Smuzhiyun 	s32 offsetk_hz = offset_freq / 1000;
1811*4882a593Smuzhiyun 
1812*4882a593Smuzhiyun 	dprintk(1, "\n");
1813*4882a593Smuzhiyun 	if (state->m_drxk_state != DRXK_STOPPED &&
1814*4882a593Smuzhiyun 		state->m_drxk_state != DRXK_DTV_STARTED)
1815*4882a593Smuzhiyun 		goto error;
1816*4882a593Smuzhiyun 
1817*4882a593Smuzhiyun 	state->m_b_mirror_freq_spect = (state->props.inversion == INVERSION_ON);
1818*4882a593Smuzhiyun 
1819*4882a593Smuzhiyun 	if (intermediate_frequency < 0) {
1820*4882a593Smuzhiyun 		state->m_b_mirror_freq_spect = !state->m_b_mirror_freq_spect;
1821*4882a593Smuzhiyun 		intermediate_frequency = -intermediate_frequency;
1822*4882a593Smuzhiyun 	}
1823*4882a593Smuzhiyun 
1824*4882a593Smuzhiyun 	switch (state->m_operation_mode) {
1825*4882a593Smuzhiyun 	case OM_QAM_ITU_A:
1826*4882a593Smuzhiyun 	case OM_QAM_ITU_C:
1827*4882a593Smuzhiyun 		i_freqk_hz = (intermediate_frequency / 1000);
1828*4882a593Smuzhiyun 		status = set_qam(state, i_freqk_hz, offsetk_hz);
1829*4882a593Smuzhiyun 		if (status < 0)
1830*4882a593Smuzhiyun 			goto error;
1831*4882a593Smuzhiyun 		state->m_drxk_state = DRXK_DTV_STARTED;
1832*4882a593Smuzhiyun 		break;
1833*4882a593Smuzhiyun 	case OM_DVBT:
1834*4882a593Smuzhiyun 		i_freqk_hz = (intermediate_frequency / 1000);
1835*4882a593Smuzhiyun 		status = mpegts_stop(state);
1836*4882a593Smuzhiyun 		if (status < 0)
1837*4882a593Smuzhiyun 			goto error;
1838*4882a593Smuzhiyun 		status = set_dvbt(state, i_freqk_hz, offsetk_hz);
1839*4882a593Smuzhiyun 		if (status < 0)
1840*4882a593Smuzhiyun 			goto error;
1841*4882a593Smuzhiyun 		status = dvbt_start(state);
1842*4882a593Smuzhiyun 		if (status < 0)
1843*4882a593Smuzhiyun 			goto error;
1844*4882a593Smuzhiyun 		state->m_drxk_state = DRXK_DTV_STARTED;
1845*4882a593Smuzhiyun 		break;
1846*4882a593Smuzhiyun 	default:
1847*4882a593Smuzhiyun 		break;
1848*4882a593Smuzhiyun 	}
1849*4882a593Smuzhiyun error:
1850*4882a593Smuzhiyun 	if (status < 0)
1851*4882a593Smuzhiyun 		pr_err("Error %d on %s\n", status, __func__);
1852*4882a593Smuzhiyun 	return status;
1853*4882a593Smuzhiyun }
1854*4882a593Smuzhiyun 
shut_down(struct drxk_state * state)1855*4882a593Smuzhiyun static int shut_down(struct drxk_state *state)
1856*4882a593Smuzhiyun {
1857*4882a593Smuzhiyun 	dprintk(1, "\n");
1858*4882a593Smuzhiyun 
1859*4882a593Smuzhiyun 	mpegts_stop(state);
1860*4882a593Smuzhiyun 	return 0;
1861*4882a593Smuzhiyun }
1862*4882a593Smuzhiyun 
get_lock_status(struct drxk_state * state,u32 * p_lock_status)1863*4882a593Smuzhiyun static int get_lock_status(struct drxk_state *state, u32 *p_lock_status)
1864*4882a593Smuzhiyun {
1865*4882a593Smuzhiyun 	int status = -EINVAL;
1866*4882a593Smuzhiyun 
1867*4882a593Smuzhiyun 	dprintk(1, "\n");
1868*4882a593Smuzhiyun 
1869*4882a593Smuzhiyun 	if (p_lock_status == NULL)
1870*4882a593Smuzhiyun 		goto error;
1871*4882a593Smuzhiyun 
1872*4882a593Smuzhiyun 	*p_lock_status = NOT_LOCKED;
1873*4882a593Smuzhiyun 
1874*4882a593Smuzhiyun 	/* define the SCU command code */
1875*4882a593Smuzhiyun 	switch (state->m_operation_mode) {
1876*4882a593Smuzhiyun 	case OM_QAM_ITU_A:
1877*4882a593Smuzhiyun 	case OM_QAM_ITU_B:
1878*4882a593Smuzhiyun 	case OM_QAM_ITU_C:
1879*4882a593Smuzhiyun 		status = get_qam_lock_status(state, p_lock_status);
1880*4882a593Smuzhiyun 		break;
1881*4882a593Smuzhiyun 	case OM_DVBT:
1882*4882a593Smuzhiyun 		status = get_dvbt_lock_status(state, p_lock_status);
1883*4882a593Smuzhiyun 		break;
1884*4882a593Smuzhiyun 	default:
1885*4882a593Smuzhiyun 		pr_debug("Unsupported operation mode %d in %s\n",
1886*4882a593Smuzhiyun 			state->m_operation_mode, __func__);
1887*4882a593Smuzhiyun 		return 0;
1888*4882a593Smuzhiyun 	}
1889*4882a593Smuzhiyun error:
1890*4882a593Smuzhiyun 	if (status < 0)
1891*4882a593Smuzhiyun 		pr_err("Error %d on %s\n", status, __func__);
1892*4882a593Smuzhiyun 	return status;
1893*4882a593Smuzhiyun }
1894*4882a593Smuzhiyun 
mpegts_start(struct drxk_state * state)1895*4882a593Smuzhiyun static int mpegts_start(struct drxk_state *state)
1896*4882a593Smuzhiyun {
1897*4882a593Smuzhiyun 	int status;
1898*4882a593Smuzhiyun 
1899*4882a593Smuzhiyun 	u16 fec_oc_snc_mode = 0;
1900*4882a593Smuzhiyun 
1901*4882a593Smuzhiyun 	/* Allow OC to sync again */
1902*4882a593Smuzhiyun 	status = read16(state, FEC_OC_SNC_MODE__A, &fec_oc_snc_mode);
1903*4882a593Smuzhiyun 	if (status < 0)
1904*4882a593Smuzhiyun 		goto error;
1905*4882a593Smuzhiyun 	fec_oc_snc_mode &= ~FEC_OC_SNC_MODE_SHUTDOWN__M;
1906*4882a593Smuzhiyun 	status = write16(state, FEC_OC_SNC_MODE__A, fec_oc_snc_mode);
1907*4882a593Smuzhiyun 	if (status < 0)
1908*4882a593Smuzhiyun 		goto error;
1909*4882a593Smuzhiyun 	status = write16(state, FEC_OC_SNC_UNLOCK__A, 1);
1910*4882a593Smuzhiyun error:
1911*4882a593Smuzhiyun 	if (status < 0)
1912*4882a593Smuzhiyun 		pr_err("Error %d on %s\n", status, __func__);
1913*4882a593Smuzhiyun 	return status;
1914*4882a593Smuzhiyun }
1915*4882a593Smuzhiyun 
mpegts_dto_init(struct drxk_state * state)1916*4882a593Smuzhiyun static int mpegts_dto_init(struct drxk_state *state)
1917*4882a593Smuzhiyun {
1918*4882a593Smuzhiyun 	int status;
1919*4882a593Smuzhiyun 
1920*4882a593Smuzhiyun 	dprintk(1, "\n");
1921*4882a593Smuzhiyun 
1922*4882a593Smuzhiyun 	/* Rate integration settings */
1923*4882a593Smuzhiyun 	status = write16(state, FEC_OC_RCN_CTL_STEP_LO__A, 0x0000);
1924*4882a593Smuzhiyun 	if (status < 0)
1925*4882a593Smuzhiyun 		goto error;
1926*4882a593Smuzhiyun 	status = write16(state, FEC_OC_RCN_CTL_STEP_HI__A, 0x000C);
1927*4882a593Smuzhiyun 	if (status < 0)
1928*4882a593Smuzhiyun 		goto error;
1929*4882a593Smuzhiyun 	status = write16(state, FEC_OC_RCN_GAIN__A, 0x000A);
1930*4882a593Smuzhiyun 	if (status < 0)
1931*4882a593Smuzhiyun 		goto error;
1932*4882a593Smuzhiyun 	status = write16(state, FEC_OC_AVR_PARM_A__A, 0x0008);
1933*4882a593Smuzhiyun 	if (status < 0)
1934*4882a593Smuzhiyun 		goto error;
1935*4882a593Smuzhiyun 	status = write16(state, FEC_OC_AVR_PARM_B__A, 0x0006);
1936*4882a593Smuzhiyun 	if (status < 0)
1937*4882a593Smuzhiyun 		goto error;
1938*4882a593Smuzhiyun 	status = write16(state, FEC_OC_TMD_HI_MARGIN__A, 0x0680);
1939*4882a593Smuzhiyun 	if (status < 0)
1940*4882a593Smuzhiyun 		goto error;
1941*4882a593Smuzhiyun 	status = write16(state, FEC_OC_TMD_LO_MARGIN__A, 0x0080);
1942*4882a593Smuzhiyun 	if (status < 0)
1943*4882a593Smuzhiyun 		goto error;
1944*4882a593Smuzhiyun 	status = write16(state, FEC_OC_TMD_COUNT__A, 0x03F4);
1945*4882a593Smuzhiyun 	if (status < 0)
1946*4882a593Smuzhiyun 		goto error;
1947*4882a593Smuzhiyun 
1948*4882a593Smuzhiyun 	/* Additional configuration */
1949*4882a593Smuzhiyun 	status = write16(state, FEC_OC_OCR_INVERT__A, 0);
1950*4882a593Smuzhiyun 	if (status < 0)
1951*4882a593Smuzhiyun 		goto error;
1952*4882a593Smuzhiyun 	status = write16(state, FEC_OC_SNC_LWM__A, 2);
1953*4882a593Smuzhiyun 	if (status < 0)
1954*4882a593Smuzhiyun 		goto error;
1955*4882a593Smuzhiyun 	status = write16(state, FEC_OC_SNC_HWM__A, 12);
1956*4882a593Smuzhiyun error:
1957*4882a593Smuzhiyun 	if (status < 0)
1958*4882a593Smuzhiyun 		pr_err("Error %d on %s\n", status, __func__);
1959*4882a593Smuzhiyun 
1960*4882a593Smuzhiyun 	return status;
1961*4882a593Smuzhiyun }
1962*4882a593Smuzhiyun 
mpegts_dto_setup(struct drxk_state * state,enum operation_mode o_mode)1963*4882a593Smuzhiyun static int mpegts_dto_setup(struct drxk_state *state,
1964*4882a593Smuzhiyun 			  enum operation_mode o_mode)
1965*4882a593Smuzhiyun {
1966*4882a593Smuzhiyun 	int status;
1967*4882a593Smuzhiyun 
1968*4882a593Smuzhiyun 	u16 fec_oc_reg_mode = 0;	/* FEC_OC_MODE       register value */
1969*4882a593Smuzhiyun 	u16 fec_oc_reg_ipr_mode = 0;	/* FEC_OC_IPR_MODE   register value */
1970*4882a593Smuzhiyun 	u16 fec_oc_dto_mode = 0;	/* FEC_OC_IPR_INVERT register value */
1971*4882a593Smuzhiyun 	u16 fec_oc_fct_mode = 0;	/* FEC_OC_IPR_INVERT register value */
1972*4882a593Smuzhiyun 	u16 fec_oc_dto_period = 2;	/* FEC_OC_IPR_INVERT register value */
1973*4882a593Smuzhiyun 	u16 fec_oc_dto_burst_len = 188;	/* FEC_OC_IPR_INVERT register value */
1974*4882a593Smuzhiyun 	u32 fec_oc_rcn_ctl_rate = 0;	/* FEC_OC_IPR_INVERT register value */
1975*4882a593Smuzhiyun 	u16 fec_oc_tmd_mode = 0;
1976*4882a593Smuzhiyun 	u16 fec_oc_tmd_int_upd_rate = 0;
1977*4882a593Smuzhiyun 	u32 max_bit_rate = 0;
1978*4882a593Smuzhiyun 	bool static_clk = false;
1979*4882a593Smuzhiyun 
1980*4882a593Smuzhiyun 	dprintk(1, "\n");
1981*4882a593Smuzhiyun 
1982*4882a593Smuzhiyun 	/* Check insertion of the Reed-Solomon parity bytes */
1983*4882a593Smuzhiyun 	status = read16(state, FEC_OC_MODE__A, &fec_oc_reg_mode);
1984*4882a593Smuzhiyun 	if (status < 0)
1985*4882a593Smuzhiyun 		goto error;
1986*4882a593Smuzhiyun 	status = read16(state, FEC_OC_IPR_MODE__A, &fec_oc_reg_ipr_mode);
1987*4882a593Smuzhiyun 	if (status < 0)
1988*4882a593Smuzhiyun 		goto error;
1989*4882a593Smuzhiyun 	fec_oc_reg_mode &= (~FEC_OC_MODE_PARITY__M);
1990*4882a593Smuzhiyun 	fec_oc_reg_ipr_mode &= (~FEC_OC_IPR_MODE_MVAL_DIS_PAR__M);
1991*4882a593Smuzhiyun 	if (state->m_insert_rs_byte) {
1992*4882a593Smuzhiyun 		/* enable parity symbol forward */
1993*4882a593Smuzhiyun 		fec_oc_reg_mode |= FEC_OC_MODE_PARITY__M;
1994*4882a593Smuzhiyun 		/* MVAL disable during parity bytes */
1995*4882a593Smuzhiyun 		fec_oc_reg_ipr_mode |= FEC_OC_IPR_MODE_MVAL_DIS_PAR__M;
1996*4882a593Smuzhiyun 		/* TS burst length to 204 */
1997*4882a593Smuzhiyun 		fec_oc_dto_burst_len = 204;
1998*4882a593Smuzhiyun 	}
1999*4882a593Smuzhiyun 
2000*4882a593Smuzhiyun 	/* Check serial or parallel output */
2001*4882a593Smuzhiyun 	fec_oc_reg_ipr_mode &= (~(FEC_OC_IPR_MODE_SERIAL__M));
2002*4882a593Smuzhiyun 	if (!state->m_enable_parallel) {
2003*4882a593Smuzhiyun 		/* MPEG data output is serial -> set ipr_mode[0] */
2004*4882a593Smuzhiyun 		fec_oc_reg_ipr_mode |= FEC_OC_IPR_MODE_SERIAL__M;
2005*4882a593Smuzhiyun 	}
2006*4882a593Smuzhiyun 
2007*4882a593Smuzhiyun 	switch (o_mode) {
2008*4882a593Smuzhiyun 	case OM_DVBT:
2009*4882a593Smuzhiyun 		max_bit_rate = state->m_dvbt_bitrate;
2010*4882a593Smuzhiyun 		fec_oc_tmd_mode = 3;
2011*4882a593Smuzhiyun 		fec_oc_rcn_ctl_rate = 0xC00000;
2012*4882a593Smuzhiyun 		static_clk = state->m_dvbt_static_clk;
2013*4882a593Smuzhiyun 		break;
2014*4882a593Smuzhiyun 	case OM_QAM_ITU_A:
2015*4882a593Smuzhiyun 	case OM_QAM_ITU_C:
2016*4882a593Smuzhiyun 		fec_oc_tmd_mode = 0x0004;
2017*4882a593Smuzhiyun 		fec_oc_rcn_ctl_rate = 0xD2B4EE;	/* good for >63 Mb/s */
2018*4882a593Smuzhiyun 		max_bit_rate = state->m_dvbc_bitrate;
2019*4882a593Smuzhiyun 		static_clk = state->m_dvbc_static_clk;
2020*4882a593Smuzhiyun 		break;
2021*4882a593Smuzhiyun 	default:
2022*4882a593Smuzhiyun 		status = -EINVAL;
2023*4882a593Smuzhiyun 	}		/* switch (standard) */
2024*4882a593Smuzhiyun 	if (status < 0)
2025*4882a593Smuzhiyun 		goto error;
2026*4882a593Smuzhiyun 
2027*4882a593Smuzhiyun 	/* Configure DTO's */
2028*4882a593Smuzhiyun 	if (static_clk) {
2029*4882a593Smuzhiyun 		u32 bit_rate = 0;
2030*4882a593Smuzhiyun 
2031*4882a593Smuzhiyun 		/* Rational DTO for MCLK source (static MCLK rate),
2032*4882a593Smuzhiyun 			Dynamic DTO for optimal grouping
2033*4882a593Smuzhiyun 			(avoid intra-packet gaps),
2034*4882a593Smuzhiyun 			DTO offset enable to sync TS burst with MSTRT */
2035*4882a593Smuzhiyun 		fec_oc_dto_mode = (FEC_OC_DTO_MODE_DYNAMIC__M |
2036*4882a593Smuzhiyun 				FEC_OC_DTO_MODE_OFFSET_ENABLE__M);
2037*4882a593Smuzhiyun 		fec_oc_fct_mode = (FEC_OC_FCT_MODE_RAT_ENA__M |
2038*4882a593Smuzhiyun 				FEC_OC_FCT_MODE_VIRT_ENA__M);
2039*4882a593Smuzhiyun 
2040*4882a593Smuzhiyun 		/* Check user defined bitrate */
2041*4882a593Smuzhiyun 		bit_rate = max_bit_rate;
2042*4882a593Smuzhiyun 		if (bit_rate > 75900000UL) {	/* max is 75.9 Mb/s */
2043*4882a593Smuzhiyun 			bit_rate = 75900000UL;
2044*4882a593Smuzhiyun 		}
2045*4882a593Smuzhiyun 		/* Rational DTO period:
2046*4882a593Smuzhiyun 			dto_period = (Fsys / bitrate) - 2
2047*4882a593Smuzhiyun 
2048*4882a593Smuzhiyun 			result should be floored,
2049*4882a593Smuzhiyun 			to make sure >= requested bitrate
2050*4882a593Smuzhiyun 			*/
2051*4882a593Smuzhiyun 		fec_oc_dto_period = (u16) (((state->m_sys_clock_freq)
2052*4882a593Smuzhiyun 						* 1000) / bit_rate);
2053*4882a593Smuzhiyun 		if (fec_oc_dto_period <= 2)
2054*4882a593Smuzhiyun 			fec_oc_dto_period = 0;
2055*4882a593Smuzhiyun 		else
2056*4882a593Smuzhiyun 			fec_oc_dto_period -= 2;
2057*4882a593Smuzhiyun 		fec_oc_tmd_int_upd_rate = 8;
2058*4882a593Smuzhiyun 	} else {
2059*4882a593Smuzhiyun 		/* (commonAttr->static_clk == false) => dynamic mode */
2060*4882a593Smuzhiyun 		fec_oc_dto_mode = FEC_OC_DTO_MODE_DYNAMIC__M;
2061*4882a593Smuzhiyun 		fec_oc_fct_mode = FEC_OC_FCT_MODE__PRE;
2062*4882a593Smuzhiyun 		fec_oc_tmd_int_upd_rate = 5;
2063*4882a593Smuzhiyun 	}
2064*4882a593Smuzhiyun 
2065*4882a593Smuzhiyun 	/* Write appropriate registers with requested configuration */
2066*4882a593Smuzhiyun 	status = write16(state, FEC_OC_DTO_BURST_LEN__A, fec_oc_dto_burst_len);
2067*4882a593Smuzhiyun 	if (status < 0)
2068*4882a593Smuzhiyun 		goto error;
2069*4882a593Smuzhiyun 	status = write16(state, FEC_OC_DTO_PERIOD__A, fec_oc_dto_period);
2070*4882a593Smuzhiyun 	if (status < 0)
2071*4882a593Smuzhiyun 		goto error;
2072*4882a593Smuzhiyun 	status = write16(state, FEC_OC_DTO_MODE__A, fec_oc_dto_mode);
2073*4882a593Smuzhiyun 	if (status < 0)
2074*4882a593Smuzhiyun 		goto error;
2075*4882a593Smuzhiyun 	status = write16(state, FEC_OC_FCT_MODE__A, fec_oc_fct_mode);
2076*4882a593Smuzhiyun 	if (status < 0)
2077*4882a593Smuzhiyun 		goto error;
2078*4882a593Smuzhiyun 	status = write16(state, FEC_OC_MODE__A, fec_oc_reg_mode);
2079*4882a593Smuzhiyun 	if (status < 0)
2080*4882a593Smuzhiyun 		goto error;
2081*4882a593Smuzhiyun 	status = write16(state, FEC_OC_IPR_MODE__A, fec_oc_reg_ipr_mode);
2082*4882a593Smuzhiyun 	if (status < 0)
2083*4882a593Smuzhiyun 		goto error;
2084*4882a593Smuzhiyun 
2085*4882a593Smuzhiyun 	/* Rate integration settings */
2086*4882a593Smuzhiyun 	status = write32(state, FEC_OC_RCN_CTL_RATE_LO__A, fec_oc_rcn_ctl_rate);
2087*4882a593Smuzhiyun 	if (status < 0)
2088*4882a593Smuzhiyun 		goto error;
2089*4882a593Smuzhiyun 	status = write16(state, FEC_OC_TMD_INT_UPD_RATE__A,
2090*4882a593Smuzhiyun 			 fec_oc_tmd_int_upd_rate);
2091*4882a593Smuzhiyun 	if (status < 0)
2092*4882a593Smuzhiyun 		goto error;
2093*4882a593Smuzhiyun 	status = write16(state, FEC_OC_TMD_MODE__A, fec_oc_tmd_mode);
2094*4882a593Smuzhiyun error:
2095*4882a593Smuzhiyun 	if (status < 0)
2096*4882a593Smuzhiyun 		pr_err("Error %d on %s\n", status, __func__);
2097*4882a593Smuzhiyun 	return status;
2098*4882a593Smuzhiyun }
2099*4882a593Smuzhiyun 
mpegts_configure_polarity(struct drxk_state * state)2100*4882a593Smuzhiyun static int mpegts_configure_polarity(struct drxk_state *state)
2101*4882a593Smuzhiyun {
2102*4882a593Smuzhiyun 	u16 fec_oc_reg_ipr_invert = 0;
2103*4882a593Smuzhiyun 
2104*4882a593Smuzhiyun 	/* Data mask for the output data byte */
2105*4882a593Smuzhiyun 	u16 invert_data_mask =
2106*4882a593Smuzhiyun 	    FEC_OC_IPR_INVERT_MD7__M | FEC_OC_IPR_INVERT_MD6__M |
2107*4882a593Smuzhiyun 	    FEC_OC_IPR_INVERT_MD5__M | FEC_OC_IPR_INVERT_MD4__M |
2108*4882a593Smuzhiyun 	    FEC_OC_IPR_INVERT_MD3__M | FEC_OC_IPR_INVERT_MD2__M |
2109*4882a593Smuzhiyun 	    FEC_OC_IPR_INVERT_MD1__M | FEC_OC_IPR_INVERT_MD0__M;
2110*4882a593Smuzhiyun 
2111*4882a593Smuzhiyun 	dprintk(1, "\n");
2112*4882a593Smuzhiyun 
2113*4882a593Smuzhiyun 	/* Control selective inversion of output bits */
2114*4882a593Smuzhiyun 	fec_oc_reg_ipr_invert &= (~(invert_data_mask));
2115*4882a593Smuzhiyun 	if (state->m_invert_data)
2116*4882a593Smuzhiyun 		fec_oc_reg_ipr_invert |= invert_data_mask;
2117*4882a593Smuzhiyun 	fec_oc_reg_ipr_invert &= (~(FEC_OC_IPR_INVERT_MERR__M));
2118*4882a593Smuzhiyun 	if (state->m_invert_err)
2119*4882a593Smuzhiyun 		fec_oc_reg_ipr_invert |= FEC_OC_IPR_INVERT_MERR__M;
2120*4882a593Smuzhiyun 	fec_oc_reg_ipr_invert &= (~(FEC_OC_IPR_INVERT_MSTRT__M));
2121*4882a593Smuzhiyun 	if (state->m_invert_str)
2122*4882a593Smuzhiyun 		fec_oc_reg_ipr_invert |= FEC_OC_IPR_INVERT_MSTRT__M;
2123*4882a593Smuzhiyun 	fec_oc_reg_ipr_invert &= (~(FEC_OC_IPR_INVERT_MVAL__M));
2124*4882a593Smuzhiyun 	if (state->m_invert_val)
2125*4882a593Smuzhiyun 		fec_oc_reg_ipr_invert |= FEC_OC_IPR_INVERT_MVAL__M;
2126*4882a593Smuzhiyun 	fec_oc_reg_ipr_invert &= (~(FEC_OC_IPR_INVERT_MCLK__M));
2127*4882a593Smuzhiyun 	if (state->m_invert_clk)
2128*4882a593Smuzhiyun 		fec_oc_reg_ipr_invert |= FEC_OC_IPR_INVERT_MCLK__M;
2129*4882a593Smuzhiyun 
2130*4882a593Smuzhiyun 	return write16(state, FEC_OC_IPR_INVERT__A, fec_oc_reg_ipr_invert);
2131*4882a593Smuzhiyun }
2132*4882a593Smuzhiyun 
2133*4882a593Smuzhiyun #define   SCU_RAM_AGC_KI_INV_RF_POL__M 0x4000
2134*4882a593Smuzhiyun 
set_agc_rf(struct drxk_state * state,struct s_cfg_agc * p_agc_cfg,bool is_dtv)2135*4882a593Smuzhiyun static int set_agc_rf(struct drxk_state *state,
2136*4882a593Smuzhiyun 		    struct s_cfg_agc *p_agc_cfg, bool is_dtv)
2137*4882a593Smuzhiyun {
2138*4882a593Smuzhiyun 	int status = -EINVAL;
2139*4882a593Smuzhiyun 	u16 data = 0;
2140*4882a593Smuzhiyun 	struct s_cfg_agc *p_if_agc_settings;
2141*4882a593Smuzhiyun 
2142*4882a593Smuzhiyun 	dprintk(1, "\n");
2143*4882a593Smuzhiyun 
2144*4882a593Smuzhiyun 	if (p_agc_cfg == NULL)
2145*4882a593Smuzhiyun 		goto error;
2146*4882a593Smuzhiyun 
2147*4882a593Smuzhiyun 	switch (p_agc_cfg->ctrl_mode) {
2148*4882a593Smuzhiyun 	case DRXK_AGC_CTRL_AUTO:
2149*4882a593Smuzhiyun 		/* Enable RF AGC DAC */
2150*4882a593Smuzhiyun 		status = read16(state, IQM_AF_STDBY__A, &data);
2151*4882a593Smuzhiyun 		if (status < 0)
2152*4882a593Smuzhiyun 			goto error;
2153*4882a593Smuzhiyun 		data &= ~IQM_AF_STDBY_STDBY_TAGC_RF_STANDBY;
2154*4882a593Smuzhiyun 		status = write16(state, IQM_AF_STDBY__A, data);
2155*4882a593Smuzhiyun 		if (status < 0)
2156*4882a593Smuzhiyun 			goto error;
2157*4882a593Smuzhiyun 		status = read16(state, SCU_RAM_AGC_CONFIG__A, &data);
2158*4882a593Smuzhiyun 		if (status < 0)
2159*4882a593Smuzhiyun 			goto error;
2160*4882a593Smuzhiyun 
2161*4882a593Smuzhiyun 		/* Enable SCU RF AGC loop */
2162*4882a593Smuzhiyun 		data &= ~SCU_RAM_AGC_CONFIG_DISABLE_RF_AGC__M;
2163*4882a593Smuzhiyun 
2164*4882a593Smuzhiyun 		/* Polarity */
2165*4882a593Smuzhiyun 		if (state->m_rf_agc_pol)
2166*4882a593Smuzhiyun 			data |= SCU_RAM_AGC_CONFIG_INV_RF_POL__M;
2167*4882a593Smuzhiyun 		else
2168*4882a593Smuzhiyun 			data &= ~SCU_RAM_AGC_CONFIG_INV_RF_POL__M;
2169*4882a593Smuzhiyun 		status = write16(state, SCU_RAM_AGC_CONFIG__A, data);
2170*4882a593Smuzhiyun 		if (status < 0)
2171*4882a593Smuzhiyun 			goto error;
2172*4882a593Smuzhiyun 
2173*4882a593Smuzhiyun 		/* Set speed (using complementary reduction value) */
2174*4882a593Smuzhiyun 		status = read16(state, SCU_RAM_AGC_KI_RED__A, &data);
2175*4882a593Smuzhiyun 		if (status < 0)
2176*4882a593Smuzhiyun 			goto error;
2177*4882a593Smuzhiyun 
2178*4882a593Smuzhiyun 		data &= ~SCU_RAM_AGC_KI_RED_RAGC_RED__M;
2179*4882a593Smuzhiyun 		data |= (~(p_agc_cfg->speed <<
2180*4882a593Smuzhiyun 				SCU_RAM_AGC_KI_RED_RAGC_RED__B)
2181*4882a593Smuzhiyun 				& SCU_RAM_AGC_KI_RED_RAGC_RED__M);
2182*4882a593Smuzhiyun 
2183*4882a593Smuzhiyun 		status = write16(state, SCU_RAM_AGC_KI_RED__A, data);
2184*4882a593Smuzhiyun 		if (status < 0)
2185*4882a593Smuzhiyun 			goto error;
2186*4882a593Smuzhiyun 
2187*4882a593Smuzhiyun 		if (is_dvbt(state))
2188*4882a593Smuzhiyun 			p_if_agc_settings = &state->m_dvbt_if_agc_cfg;
2189*4882a593Smuzhiyun 		else if (is_qam(state))
2190*4882a593Smuzhiyun 			p_if_agc_settings = &state->m_qam_if_agc_cfg;
2191*4882a593Smuzhiyun 		else
2192*4882a593Smuzhiyun 			p_if_agc_settings = &state->m_atv_if_agc_cfg;
2193*4882a593Smuzhiyun 		if (p_if_agc_settings == NULL) {
2194*4882a593Smuzhiyun 			status = -EINVAL;
2195*4882a593Smuzhiyun 			goto error;
2196*4882a593Smuzhiyun 		}
2197*4882a593Smuzhiyun 
2198*4882a593Smuzhiyun 		/* Set TOP, only if IF-AGC is in AUTO mode */
2199*4882a593Smuzhiyun 		if (p_if_agc_settings->ctrl_mode == DRXK_AGC_CTRL_AUTO) {
2200*4882a593Smuzhiyun 			status = write16(state,
2201*4882a593Smuzhiyun 					 SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A,
2202*4882a593Smuzhiyun 					 p_agc_cfg->top);
2203*4882a593Smuzhiyun 			if (status < 0)
2204*4882a593Smuzhiyun 				goto error;
2205*4882a593Smuzhiyun 		}
2206*4882a593Smuzhiyun 
2207*4882a593Smuzhiyun 		/* Cut-Off current */
2208*4882a593Smuzhiyun 		status = write16(state, SCU_RAM_AGC_RF_IACCU_HI_CO__A,
2209*4882a593Smuzhiyun 				 p_agc_cfg->cut_off_current);
2210*4882a593Smuzhiyun 		if (status < 0)
2211*4882a593Smuzhiyun 			goto error;
2212*4882a593Smuzhiyun 
2213*4882a593Smuzhiyun 		/* Max. output level */
2214*4882a593Smuzhiyun 		status = write16(state, SCU_RAM_AGC_RF_MAX__A,
2215*4882a593Smuzhiyun 				 p_agc_cfg->max_output_level);
2216*4882a593Smuzhiyun 		if (status < 0)
2217*4882a593Smuzhiyun 			goto error;
2218*4882a593Smuzhiyun 
2219*4882a593Smuzhiyun 		break;
2220*4882a593Smuzhiyun 
2221*4882a593Smuzhiyun 	case DRXK_AGC_CTRL_USER:
2222*4882a593Smuzhiyun 		/* Enable RF AGC DAC */
2223*4882a593Smuzhiyun 		status = read16(state, IQM_AF_STDBY__A, &data);
2224*4882a593Smuzhiyun 		if (status < 0)
2225*4882a593Smuzhiyun 			goto error;
2226*4882a593Smuzhiyun 		data &= ~IQM_AF_STDBY_STDBY_TAGC_RF_STANDBY;
2227*4882a593Smuzhiyun 		status = write16(state, IQM_AF_STDBY__A, data);
2228*4882a593Smuzhiyun 		if (status < 0)
2229*4882a593Smuzhiyun 			goto error;
2230*4882a593Smuzhiyun 
2231*4882a593Smuzhiyun 		/* Disable SCU RF AGC loop */
2232*4882a593Smuzhiyun 		status = read16(state, SCU_RAM_AGC_CONFIG__A, &data);
2233*4882a593Smuzhiyun 		if (status < 0)
2234*4882a593Smuzhiyun 			goto error;
2235*4882a593Smuzhiyun 		data |= SCU_RAM_AGC_CONFIG_DISABLE_RF_AGC__M;
2236*4882a593Smuzhiyun 		if (state->m_rf_agc_pol)
2237*4882a593Smuzhiyun 			data |= SCU_RAM_AGC_CONFIG_INV_RF_POL__M;
2238*4882a593Smuzhiyun 		else
2239*4882a593Smuzhiyun 			data &= ~SCU_RAM_AGC_CONFIG_INV_RF_POL__M;
2240*4882a593Smuzhiyun 		status = write16(state, SCU_RAM_AGC_CONFIG__A, data);
2241*4882a593Smuzhiyun 		if (status < 0)
2242*4882a593Smuzhiyun 			goto error;
2243*4882a593Smuzhiyun 
2244*4882a593Smuzhiyun 		/* SCU c.o.c. to 0, enabling full control range */
2245*4882a593Smuzhiyun 		status = write16(state, SCU_RAM_AGC_RF_IACCU_HI_CO__A, 0);
2246*4882a593Smuzhiyun 		if (status < 0)
2247*4882a593Smuzhiyun 			goto error;
2248*4882a593Smuzhiyun 
2249*4882a593Smuzhiyun 		/* Write value to output pin */
2250*4882a593Smuzhiyun 		status = write16(state, SCU_RAM_AGC_RF_IACCU_HI__A,
2251*4882a593Smuzhiyun 				 p_agc_cfg->output_level);
2252*4882a593Smuzhiyun 		if (status < 0)
2253*4882a593Smuzhiyun 			goto error;
2254*4882a593Smuzhiyun 		break;
2255*4882a593Smuzhiyun 
2256*4882a593Smuzhiyun 	case DRXK_AGC_CTRL_OFF:
2257*4882a593Smuzhiyun 		/* Disable RF AGC DAC */
2258*4882a593Smuzhiyun 		status = read16(state, IQM_AF_STDBY__A, &data);
2259*4882a593Smuzhiyun 		if (status < 0)
2260*4882a593Smuzhiyun 			goto error;
2261*4882a593Smuzhiyun 		data |= IQM_AF_STDBY_STDBY_TAGC_RF_STANDBY;
2262*4882a593Smuzhiyun 		status = write16(state, IQM_AF_STDBY__A, data);
2263*4882a593Smuzhiyun 		if (status < 0)
2264*4882a593Smuzhiyun 			goto error;
2265*4882a593Smuzhiyun 
2266*4882a593Smuzhiyun 		/* Disable SCU RF AGC loop */
2267*4882a593Smuzhiyun 		status = read16(state, SCU_RAM_AGC_CONFIG__A, &data);
2268*4882a593Smuzhiyun 		if (status < 0)
2269*4882a593Smuzhiyun 			goto error;
2270*4882a593Smuzhiyun 		data |= SCU_RAM_AGC_CONFIG_DISABLE_RF_AGC__M;
2271*4882a593Smuzhiyun 		status = write16(state, SCU_RAM_AGC_CONFIG__A, data);
2272*4882a593Smuzhiyun 		if (status < 0)
2273*4882a593Smuzhiyun 			goto error;
2274*4882a593Smuzhiyun 		break;
2275*4882a593Smuzhiyun 
2276*4882a593Smuzhiyun 	default:
2277*4882a593Smuzhiyun 		status = -EINVAL;
2278*4882a593Smuzhiyun 
2279*4882a593Smuzhiyun 	}
2280*4882a593Smuzhiyun error:
2281*4882a593Smuzhiyun 	if (status < 0)
2282*4882a593Smuzhiyun 		pr_err("Error %d on %s\n", status, __func__);
2283*4882a593Smuzhiyun 	return status;
2284*4882a593Smuzhiyun }
2285*4882a593Smuzhiyun 
2286*4882a593Smuzhiyun #define SCU_RAM_AGC_KI_INV_IF_POL__M 0x2000
2287*4882a593Smuzhiyun 
set_agc_if(struct drxk_state * state,struct s_cfg_agc * p_agc_cfg,bool is_dtv)2288*4882a593Smuzhiyun static int set_agc_if(struct drxk_state *state,
2289*4882a593Smuzhiyun 		    struct s_cfg_agc *p_agc_cfg, bool is_dtv)
2290*4882a593Smuzhiyun {
2291*4882a593Smuzhiyun 	u16 data = 0;
2292*4882a593Smuzhiyun 	int status = 0;
2293*4882a593Smuzhiyun 	struct s_cfg_agc *p_rf_agc_settings;
2294*4882a593Smuzhiyun 
2295*4882a593Smuzhiyun 	dprintk(1, "\n");
2296*4882a593Smuzhiyun 
2297*4882a593Smuzhiyun 	switch (p_agc_cfg->ctrl_mode) {
2298*4882a593Smuzhiyun 	case DRXK_AGC_CTRL_AUTO:
2299*4882a593Smuzhiyun 
2300*4882a593Smuzhiyun 		/* Enable IF AGC DAC */
2301*4882a593Smuzhiyun 		status = read16(state, IQM_AF_STDBY__A, &data);
2302*4882a593Smuzhiyun 		if (status < 0)
2303*4882a593Smuzhiyun 			goto error;
2304*4882a593Smuzhiyun 		data &= ~IQM_AF_STDBY_STDBY_TAGC_IF_STANDBY;
2305*4882a593Smuzhiyun 		status = write16(state, IQM_AF_STDBY__A, data);
2306*4882a593Smuzhiyun 		if (status < 0)
2307*4882a593Smuzhiyun 			goto error;
2308*4882a593Smuzhiyun 
2309*4882a593Smuzhiyun 		status = read16(state, SCU_RAM_AGC_CONFIG__A, &data);
2310*4882a593Smuzhiyun 		if (status < 0)
2311*4882a593Smuzhiyun 			goto error;
2312*4882a593Smuzhiyun 
2313*4882a593Smuzhiyun 		/* Enable SCU IF AGC loop */
2314*4882a593Smuzhiyun 		data &= ~SCU_RAM_AGC_CONFIG_DISABLE_IF_AGC__M;
2315*4882a593Smuzhiyun 
2316*4882a593Smuzhiyun 		/* Polarity */
2317*4882a593Smuzhiyun 		if (state->m_if_agc_pol)
2318*4882a593Smuzhiyun 			data |= SCU_RAM_AGC_CONFIG_INV_IF_POL__M;
2319*4882a593Smuzhiyun 		else
2320*4882a593Smuzhiyun 			data &= ~SCU_RAM_AGC_CONFIG_INV_IF_POL__M;
2321*4882a593Smuzhiyun 		status = write16(state, SCU_RAM_AGC_CONFIG__A, data);
2322*4882a593Smuzhiyun 		if (status < 0)
2323*4882a593Smuzhiyun 			goto error;
2324*4882a593Smuzhiyun 
2325*4882a593Smuzhiyun 		/* Set speed (using complementary reduction value) */
2326*4882a593Smuzhiyun 		status = read16(state, SCU_RAM_AGC_KI_RED__A, &data);
2327*4882a593Smuzhiyun 		if (status < 0)
2328*4882a593Smuzhiyun 			goto error;
2329*4882a593Smuzhiyun 		data &= ~SCU_RAM_AGC_KI_RED_IAGC_RED__M;
2330*4882a593Smuzhiyun 		data |= (~(p_agc_cfg->speed <<
2331*4882a593Smuzhiyun 				SCU_RAM_AGC_KI_RED_IAGC_RED__B)
2332*4882a593Smuzhiyun 				& SCU_RAM_AGC_KI_RED_IAGC_RED__M);
2333*4882a593Smuzhiyun 
2334*4882a593Smuzhiyun 		status = write16(state, SCU_RAM_AGC_KI_RED__A, data);
2335*4882a593Smuzhiyun 		if (status < 0)
2336*4882a593Smuzhiyun 			goto error;
2337*4882a593Smuzhiyun 
2338*4882a593Smuzhiyun 		if (is_qam(state))
2339*4882a593Smuzhiyun 			p_rf_agc_settings = &state->m_qam_rf_agc_cfg;
2340*4882a593Smuzhiyun 		else
2341*4882a593Smuzhiyun 			p_rf_agc_settings = &state->m_atv_rf_agc_cfg;
2342*4882a593Smuzhiyun 		if (p_rf_agc_settings == NULL)
2343*4882a593Smuzhiyun 			return -1;
2344*4882a593Smuzhiyun 		/* Restore TOP */
2345*4882a593Smuzhiyun 		status = write16(state, SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A,
2346*4882a593Smuzhiyun 				 p_rf_agc_settings->top);
2347*4882a593Smuzhiyun 		if (status < 0)
2348*4882a593Smuzhiyun 			goto error;
2349*4882a593Smuzhiyun 		break;
2350*4882a593Smuzhiyun 
2351*4882a593Smuzhiyun 	case DRXK_AGC_CTRL_USER:
2352*4882a593Smuzhiyun 
2353*4882a593Smuzhiyun 		/* Enable IF AGC DAC */
2354*4882a593Smuzhiyun 		status = read16(state, IQM_AF_STDBY__A, &data);
2355*4882a593Smuzhiyun 		if (status < 0)
2356*4882a593Smuzhiyun 			goto error;
2357*4882a593Smuzhiyun 		data &= ~IQM_AF_STDBY_STDBY_TAGC_IF_STANDBY;
2358*4882a593Smuzhiyun 		status = write16(state, IQM_AF_STDBY__A, data);
2359*4882a593Smuzhiyun 		if (status < 0)
2360*4882a593Smuzhiyun 			goto error;
2361*4882a593Smuzhiyun 
2362*4882a593Smuzhiyun 		status = read16(state, SCU_RAM_AGC_CONFIG__A, &data);
2363*4882a593Smuzhiyun 		if (status < 0)
2364*4882a593Smuzhiyun 			goto error;
2365*4882a593Smuzhiyun 
2366*4882a593Smuzhiyun 		/* Disable SCU IF AGC loop */
2367*4882a593Smuzhiyun 		data |= SCU_RAM_AGC_CONFIG_DISABLE_IF_AGC__M;
2368*4882a593Smuzhiyun 
2369*4882a593Smuzhiyun 		/* Polarity */
2370*4882a593Smuzhiyun 		if (state->m_if_agc_pol)
2371*4882a593Smuzhiyun 			data |= SCU_RAM_AGC_CONFIG_INV_IF_POL__M;
2372*4882a593Smuzhiyun 		else
2373*4882a593Smuzhiyun 			data &= ~SCU_RAM_AGC_CONFIG_INV_IF_POL__M;
2374*4882a593Smuzhiyun 		status = write16(state, SCU_RAM_AGC_CONFIG__A, data);
2375*4882a593Smuzhiyun 		if (status < 0)
2376*4882a593Smuzhiyun 			goto error;
2377*4882a593Smuzhiyun 
2378*4882a593Smuzhiyun 		/* Write value to output pin */
2379*4882a593Smuzhiyun 		status = write16(state, SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A,
2380*4882a593Smuzhiyun 				 p_agc_cfg->output_level);
2381*4882a593Smuzhiyun 		if (status < 0)
2382*4882a593Smuzhiyun 			goto error;
2383*4882a593Smuzhiyun 		break;
2384*4882a593Smuzhiyun 
2385*4882a593Smuzhiyun 	case DRXK_AGC_CTRL_OFF:
2386*4882a593Smuzhiyun 
2387*4882a593Smuzhiyun 		/* Disable If AGC DAC */
2388*4882a593Smuzhiyun 		status = read16(state, IQM_AF_STDBY__A, &data);
2389*4882a593Smuzhiyun 		if (status < 0)
2390*4882a593Smuzhiyun 			goto error;
2391*4882a593Smuzhiyun 		data |= IQM_AF_STDBY_STDBY_TAGC_IF_STANDBY;
2392*4882a593Smuzhiyun 		status = write16(state, IQM_AF_STDBY__A, data);
2393*4882a593Smuzhiyun 		if (status < 0)
2394*4882a593Smuzhiyun 			goto error;
2395*4882a593Smuzhiyun 
2396*4882a593Smuzhiyun 		/* Disable SCU IF AGC loop */
2397*4882a593Smuzhiyun 		status = read16(state, SCU_RAM_AGC_CONFIG__A, &data);
2398*4882a593Smuzhiyun 		if (status < 0)
2399*4882a593Smuzhiyun 			goto error;
2400*4882a593Smuzhiyun 		data |= SCU_RAM_AGC_CONFIG_DISABLE_IF_AGC__M;
2401*4882a593Smuzhiyun 		status = write16(state, SCU_RAM_AGC_CONFIG__A, data);
2402*4882a593Smuzhiyun 		if (status < 0)
2403*4882a593Smuzhiyun 			goto error;
2404*4882a593Smuzhiyun 		break;
2405*4882a593Smuzhiyun 	}		/* switch (agcSettingsIf->ctrl_mode) */
2406*4882a593Smuzhiyun 
2407*4882a593Smuzhiyun 	/* always set the top to support
2408*4882a593Smuzhiyun 		configurations without if-loop */
2409*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_AGC_INGAIN_TGT_MIN__A, p_agc_cfg->top);
2410*4882a593Smuzhiyun error:
2411*4882a593Smuzhiyun 	if (status < 0)
2412*4882a593Smuzhiyun 		pr_err("Error %d on %s\n", status, __func__);
2413*4882a593Smuzhiyun 	return status;
2414*4882a593Smuzhiyun }
2415*4882a593Smuzhiyun 
get_qam_signal_to_noise(struct drxk_state * state,s32 * p_signal_to_noise)2416*4882a593Smuzhiyun static int get_qam_signal_to_noise(struct drxk_state *state,
2417*4882a593Smuzhiyun 			       s32 *p_signal_to_noise)
2418*4882a593Smuzhiyun {
2419*4882a593Smuzhiyun 	int status = 0;
2420*4882a593Smuzhiyun 	u16 qam_sl_err_power = 0;	/* accum. error between
2421*4882a593Smuzhiyun 					raw and sliced symbols */
2422*4882a593Smuzhiyun 	u32 qam_sl_sig_power = 0;	/* used for MER, depends of
2423*4882a593Smuzhiyun 					QAM modulation */
2424*4882a593Smuzhiyun 	u32 qam_sl_mer = 0;	/* QAM MER */
2425*4882a593Smuzhiyun 
2426*4882a593Smuzhiyun 	dprintk(1, "\n");
2427*4882a593Smuzhiyun 
2428*4882a593Smuzhiyun 	/* MER calculation */
2429*4882a593Smuzhiyun 
2430*4882a593Smuzhiyun 	/* get the register value needed for MER */
2431*4882a593Smuzhiyun 	status = read16(state, QAM_SL_ERR_POWER__A, &qam_sl_err_power);
2432*4882a593Smuzhiyun 	if (status < 0) {
2433*4882a593Smuzhiyun 		pr_err("Error %d on %s\n", status, __func__);
2434*4882a593Smuzhiyun 		return -EINVAL;
2435*4882a593Smuzhiyun 	}
2436*4882a593Smuzhiyun 
2437*4882a593Smuzhiyun 	switch (state->props.modulation) {
2438*4882a593Smuzhiyun 	case QAM_16:
2439*4882a593Smuzhiyun 		qam_sl_sig_power = DRXK_QAM_SL_SIG_POWER_QAM16 << 2;
2440*4882a593Smuzhiyun 		break;
2441*4882a593Smuzhiyun 	case QAM_32:
2442*4882a593Smuzhiyun 		qam_sl_sig_power = DRXK_QAM_SL_SIG_POWER_QAM32 << 2;
2443*4882a593Smuzhiyun 		break;
2444*4882a593Smuzhiyun 	case QAM_64:
2445*4882a593Smuzhiyun 		qam_sl_sig_power = DRXK_QAM_SL_SIG_POWER_QAM64 << 2;
2446*4882a593Smuzhiyun 		break;
2447*4882a593Smuzhiyun 	case QAM_128:
2448*4882a593Smuzhiyun 		qam_sl_sig_power = DRXK_QAM_SL_SIG_POWER_QAM128 << 2;
2449*4882a593Smuzhiyun 		break;
2450*4882a593Smuzhiyun 	default:
2451*4882a593Smuzhiyun 	case QAM_256:
2452*4882a593Smuzhiyun 		qam_sl_sig_power = DRXK_QAM_SL_SIG_POWER_QAM256 << 2;
2453*4882a593Smuzhiyun 		break;
2454*4882a593Smuzhiyun 	}
2455*4882a593Smuzhiyun 
2456*4882a593Smuzhiyun 	if (qam_sl_err_power > 0) {
2457*4882a593Smuzhiyun 		qam_sl_mer = log10times100(qam_sl_sig_power) -
2458*4882a593Smuzhiyun 			log10times100((u32) qam_sl_err_power);
2459*4882a593Smuzhiyun 	}
2460*4882a593Smuzhiyun 	*p_signal_to_noise = qam_sl_mer;
2461*4882a593Smuzhiyun 
2462*4882a593Smuzhiyun 	return status;
2463*4882a593Smuzhiyun }
2464*4882a593Smuzhiyun 
get_dvbt_signal_to_noise(struct drxk_state * state,s32 * p_signal_to_noise)2465*4882a593Smuzhiyun static int get_dvbt_signal_to_noise(struct drxk_state *state,
2466*4882a593Smuzhiyun 				s32 *p_signal_to_noise)
2467*4882a593Smuzhiyun {
2468*4882a593Smuzhiyun 	int status;
2469*4882a593Smuzhiyun 	u16 reg_data = 0;
2470*4882a593Smuzhiyun 	u32 eq_reg_td_sqr_err_i = 0;
2471*4882a593Smuzhiyun 	u32 eq_reg_td_sqr_err_q = 0;
2472*4882a593Smuzhiyun 	u16 eq_reg_td_sqr_err_exp = 0;
2473*4882a593Smuzhiyun 	u16 eq_reg_td_tps_pwr_ofs = 0;
2474*4882a593Smuzhiyun 	u16 eq_reg_td_req_smb_cnt = 0;
2475*4882a593Smuzhiyun 	u32 tps_cnt = 0;
2476*4882a593Smuzhiyun 	u32 sqr_err_iq = 0;
2477*4882a593Smuzhiyun 	u32 a = 0;
2478*4882a593Smuzhiyun 	u32 b = 0;
2479*4882a593Smuzhiyun 	u32 c = 0;
2480*4882a593Smuzhiyun 	u32 i_mer = 0;
2481*4882a593Smuzhiyun 	u16 transmission_params = 0;
2482*4882a593Smuzhiyun 
2483*4882a593Smuzhiyun 	dprintk(1, "\n");
2484*4882a593Smuzhiyun 
2485*4882a593Smuzhiyun 	status = read16(state, OFDM_EQ_TOP_TD_TPS_PWR_OFS__A,
2486*4882a593Smuzhiyun 			&eq_reg_td_tps_pwr_ofs);
2487*4882a593Smuzhiyun 	if (status < 0)
2488*4882a593Smuzhiyun 		goto error;
2489*4882a593Smuzhiyun 	status = read16(state, OFDM_EQ_TOP_TD_REQ_SMB_CNT__A,
2490*4882a593Smuzhiyun 			&eq_reg_td_req_smb_cnt);
2491*4882a593Smuzhiyun 	if (status < 0)
2492*4882a593Smuzhiyun 		goto error;
2493*4882a593Smuzhiyun 	status = read16(state, OFDM_EQ_TOP_TD_SQR_ERR_EXP__A,
2494*4882a593Smuzhiyun 			&eq_reg_td_sqr_err_exp);
2495*4882a593Smuzhiyun 	if (status < 0)
2496*4882a593Smuzhiyun 		goto error;
2497*4882a593Smuzhiyun 	status = read16(state, OFDM_EQ_TOP_TD_SQR_ERR_I__A,
2498*4882a593Smuzhiyun 			&reg_data);
2499*4882a593Smuzhiyun 	if (status < 0)
2500*4882a593Smuzhiyun 		goto error;
2501*4882a593Smuzhiyun 	/* Extend SQR_ERR_I operational range */
2502*4882a593Smuzhiyun 	eq_reg_td_sqr_err_i = (u32) reg_data;
2503*4882a593Smuzhiyun 	if ((eq_reg_td_sqr_err_exp > 11) &&
2504*4882a593Smuzhiyun 		(eq_reg_td_sqr_err_i < 0x00000FFFUL)) {
2505*4882a593Smuzhiyun 		eq_reg_td_sqr_err_i += 0x00010000UL;
2506*4882a593Smuzhiyun 	}
2507*4882a593Smuzhiyun 	status = read16(state, OFDM_EQ_TOP_TD_SQR_ERR_Q__A, &reg_data);
2508*4882a593Smuzhiyun 	if (status < 0)
2509*4882a593Smuzhiyun 		goto error;
2510*4882a593Smuzhiyun 	/* Extend SQR_ERR_Q operational range */
2511*4882a593Smuzhiyun 	eq_reg_td_sqr_err_q = (u32) reg_data;
2512*4882a593Smuzhiyun 	if ((eq_reg_td_sqr_err_exp > 11) &&
2513*4882a593Smuzhiyun 		(eq_reg_td_sqr_err_q < 0x00000FFFUL))
2514*4882a593Smuzhiyun 		eq_reg_td_sqr_err_q += 0x00010000UL;
2515*4882a593Smuzhiyun 
2516*4882a593Smuzhiyun 	status = read16(state, OFDM_SC_RA_RAM_OP_PARAM__A,
2517*4882a593Smuzhiyun 			&transmission_params);
2518*4882a593Smuzhiyun 	if (status < 0)
2519*4882a593Smuzhiyun 		goto error;
2520*4882a593Smuzhiyun 
2521*4882a593Smuzhiyun 	/* Check input data for MER */
2522*4882a593Smuzhiyun 
2523*4882a593Smuzhiyun 	/* MER calculation (in 0.1 dB) without math.h */
2524*4882a593Smuzhiyun 	if ((eq_reg_td_tps_pwr_ofs == 0) || (eq_reg_td_req_smb_cnt == 0))
2525*4882a593Smuzhiyun 		i_mer = 0;
2526*4882a593Smuzhiyun 	else if ((eq_reg_td_sqr_err_i + eq_reg_td_sqr_err_q) == 0) {
2527*4882a593Smuzhiyun 		/* No error at all, this must be the HW reset value
2528*4882a593Smuzhiyun 			* Apparently no first measurement yet
2529*4882a593Smuzhiyun 			* Set MER to 0.0 */
2530*4882a593Smuzhiyun 		i_mer = 0;
2531*4882a593Smuzhiyun 	} else {
2532*4882a593Smuzhiyun 		sqr_err_iq = (eq_reg_td_sqr_err_i + eq_reg_td_sqr_err_q) <<
2533*4882a593Smuzhiyun 			eq_reg_td_sqr_err_exp;
2534*4882a593Smuzhiyun 		if ((transmission_params &
2535*4882a593Smuzhiyun 			OFDM_SC_RA_RAM_OP_PARAM_MODE__M)
2536*4882a593Smuzhiyun 			== OFDM_SC_RA_RAM_OP_PARAM_MODE_2K)
2537*4882a593Smuzhiyun 			tps_cnt = 17;
2538*4882a593Smuzhiyun 		else
2539*4882a593Smuzhiyun 			tps_cnt = 68;
2540*4882a593Smuzhiyun 
2541*4882a593Smuzhiyun 		/* IMER = 100 * log10 (x)
2542*4882a593Smuzhiyun 			where x = (eq_reg_td_tps_pwr_ofs^2 *
2543*4882a593Smuzhiyun 			eq_reg_td_req_smb_cnt * tps_cnt)/sqr_err_iq
2544*4882a593Smuzhiyun 
2545*4882a593Smuzhiyun 			=> IMER = a + b -c
2546*4882a593Smuzhiyun 			where a = 100 * log10 (eq_reg_td_tps_pwr_ofs^2)
2547*4882a593Smuzhiyun 			b = 100 * log10 (eq_reg_td_req_smb_cnt * tps_cnt)
2548*4882a593Smuzhiyun 			c = 100 * log10 (sqr_err_iq)
2549*4882a593Smuzhiyun 			*/
2550*4882a593Smuzhiyun 
2551*4882a593Smuzhiyun 		/* log(x) x = 9bits * 9bits->18 bits  */
2552*4882a593Smuzhiyun 		a = log10times100(eq_reg_td_tps_pwr_ofs *
2553*4882a593Smuzhiyun 					eq_reg_td_tps_pwr_ofs);
2554*4882a593Smuzhiyun 		/* log(x) x = 16bits * 7bits->23 bits  */
2555*4882a593Smuzhiyun 		b = log10times100(eq_reg_td_req_smb_cnt * tps_cnt);
2556*4882a593Smuzhiyun 		/* log(x) x = (16bits + 16bits) << 15 ->32 bits  */
2557*4882a593Smuzhiyun 		c = log10times100(sqr_err_iq);
2558*4882a593Smuzhiyun 
2559*4882a593Smuzhiyun 		i_mer = a + b - c;
2560*4882a593Smuzhiyun 	}
2561*4882a593Smuzhiyun 	*p_signal_to_noise = i_mer;
2562*4882a593Smuzhiyun 
2563*4882a593Smuzhiyun error:
2564*4882a593Smuzhiyun 	if (status < 0)
2565*4882a593Smuzhiyun 		pr_err("Error %d on %s\n", status, __func__);
2566*4882a593Smuzhiyun 	return status;
2567*4882a593Smuzhiyun }
2568*4882a593Smuzhiyun 
get_signal_to_noise(struct drxk_state * state,s32 * p_signal_to_noise)2569*4882a593Smuzhiyun static int get_signal_to_noise(struct drxk_state *state, s32 *p_signal_to_noise)
2570*4882a593Smuzhiyun {
2571*4882a593Smuzhiyun 	dprintk(1, "\n");
2572*4882a593Smuzhiyun 
2573*4882a593Smuzhiyun 	*p_signal_to_noise = 0;
2574*4882a593Smuzhiyun 	switch (state->m_operation_mode) {
2575*4882a593Smuzhiyun 	case OM_DVBT:
2576*4882a593Smuzhiyun 		return get_dvbt_signal_to_noise(state, p_signal_to_noise);
2577*4882a593Smuzhiyun 	case OM_QAM_ITU_A:
2578*4882a593Smuzhiyun 	case OM_QAM_ITU_C:
2579*4882a593Smuzhiyun 		return get_qam_signal_to_noise(state, p_signal_to_noise);
2580*4882a593Smuzhiyun 	default:
2581*4882a593Smuzhiyun 		break;
2582*4882a593Smuzhiyun 	}
2583*4882a593Smuzhiyun 	return 0;
2584*4882a593Smuzhiyun }
2585*4882a593Smuzhiyun 
2586*4882a593Smuzhiyun #if 0
2587*4882a593Smuzhiyun static int get_dvbt_quality(struct drxk_state *state, s32 *p_quality)
2588*4882a593Smuzhiyun {
2589*4882a593Smuzhiyun 	/* SNR Values for quasi errorfree reception rom Nordig 2.2 */
2590*4882a593Smuzhiyun 	int status = 0;
2591*4882a593Smuzhiyun 
2592*4882a593Smuzhiyun 	dprintk(1, "\n");
2593*4882a593Smuzhiyun 
2594*4882a593Smuzhiyun 	static s32 QE_SN[] = {
2595*4882a593Smuzhiyun 		51,		/* QPSK 1/2 */
2596*4882a593Smuzhiyun 		69,		/* QPSK 2/3 */
2597*4882a593Smuzhiyun 		79,		/* QPSK 3/4 */
2598*4882a593Smuzhiyun 		89,		/* QPSK 5/6 */
2599*4882a593Smuzhiyun 		97,		/* QPSK 7/8 */
2600*4882a593Smuzhiyun 		108,		/* 16-QAM 1/2 */
2601*4882a593Smuzhiyun 		131,		/* 16-QAM 2/3 */
2602*4882a593Smuzhiyun 		146,		/* 16-QAM 3/4 */
2603*4882a593Smuzhiyun 		156,		/* 16-QAM 5/6 */
2604*4882a593Smuzhiyun 		160,		/* 16-QAM 7/8 */
2605*4882a593Smuzhiyun 		165,		/* 64-QAM 1/2 */
2606*4882a593Smuzhiyun 		187,		/* 64-QAM 2/3 */
2607*4882a593Smuzhiyun 		202,		/* 64-QAM 3/4 */
2608*4882a593Smuzhiyun 		216,		/* 64-QAM 5/6 */
2609*4882a593Smuzhiyun 		225,		/* 64-QAM 7/8 */
2610*4882a593Smuzhiyun 	};
2611*4882a593Smuzhiyun 
2612*4882a593Smuzhiyun 	*p_quality = 0;
2613*4882a593Smuzhiyun 
2614*4882a593Smuzhiyun 	do {
2615*4882a593Smuzhiyun 		s32 signal_to_noise = 0;
2616*4882a593Smuzhiyun 		u16 constellation = 0;
2617*4882a593Smuzhiyun 		u16 code_rate = 0;
2618*4882a593Smuzhiyun 		u32 signal_to_noise_rel;
2619*4882a593Smuzhiyun 		u32 ber_quality;
2620*4882a593Smuzhiyun 
2621*4882a593Smuzhiyun 		status = get_dvbt_signal_to_noise(state, &signal_to_noise);
2622*4882a593Smuzhiyun 		if (status < 0)
2623*4882a593Smuzhiyun 			break;
2624*4882a593Smuzhiyun 		status = read16(state, OFDM_EQ_TOP_TD_TPS_CONST__A,
2625*4882a593Smuzhiyun 				&constellation);
2626*4882a593Smuzhiyun 		if (status < 0)
2627*4882a593Smuzhiyun 			break;
2628*4882a593Smuzhiyun 		constellation &= OFDM_EQ_TOP_TD_TPS_CONST__M;
2629*4882a593Smuzhiyun 
2630*4882a593Smuzhiyun 		status = read16(state, OFDM_EQ_TOP_TD_TPS_CODE_HP__A,
2631*4882a593Smuzhiyun 				&code_rate);
2632*4882a593Smuzhiyun 		if (status < 0)
2633*4882a593Smuzhiyun 			break;
2634*4882a593Smuzhiyun 		code_rate &= OFDM_EQ_TOP_TD_TPS_CODE_HP__M;
2635*4882a593Smuzhiyun 
2636*4882a593Smuzhiyun 		if (constellation > OFDM_EQ_TOP_TD_TPS_CONST_64QAM ||
2637*4882a593Smuzhiyun 		    code_rate > OFDM_EQ_TOP_TD_TPS_CODE_LP_7_8)
2638*4882a593Smuzhiyun 			break;
2639*4882a593Smuzhiyun 		signal_to_noise_rel = signal_to_noise -
2640*4882a593Smuzhiyun 		    QE_SN[constellation * 5 + code_rate];
2641*4882a593Smuzhiyun 		ber_quality = 100;
2642*4882a593Smuzhiyun 
2643*4882a593Smuzhiyun 		if (signal_to_noise_rel < -70)
2644*4882a593Smuzhiyun 			*p_quality = 0;
2645*4882a593Smuzhiyun 		else if (signal_to_noise_rel < 30)
2646*4882a593Smuzhiyun 			*p_quality = ((signal_to_noise_rel + 70) *
2647*4882a593Smuzhiyun 				     ber_quality) / 100;
2648*4882a593Smuzhiyun 		else
2649*4882a593Smuzhiyun 			*p_quality = ber_quality;
2650*4882a593Smuzhiyun 	} while (0);
2651*4882a593Smuzhiyun 	return 0;
2652*4882a593Smuzhiyun };
2653*4882a593Smuzhiyun 
2654*4882a593Smuzhiyun static int get_dvbc_quality(struct drxk_state *state, s32 *p_quality)
2655*4882a593Smuzhiyun {
2656*4882a593Smuzhiyun 	int status = 0;
2657*4882a593Smuzhiyun 	*p_quality = 0;
2658*4882a593Smuzhiyun 
2659*4882a593Smuzhiyun 	dprintk(1, "\n");
2660*4882a593Smuzhiyun 
2661*4882a593Smuzhiyun 	do {
2662*4882a593Smuzhiyun 		u32 signal_to_noise = 0;
2663*4882a593Smuzhiyun 		u32 ber_quality = 100;
2664*4882a593Smuzhiyun 		u32 signal_to_noise_rel = 0;
2665*4882a593Smuzhiyun 
2666*4882a593Smuzhiyun 		status = get_qam_signal_to_noise(state, &signal_to_noise);
2667*4882a593Smuzhiyun 		if (status < 0)
2668*4882a593Smuzhiyun 			break;
2669*4882a593Smuzhiyun 
2670*4882a593Smuzhiyun 		switch (state->props.modulation) {
2671*4882a593Smuzhiyun 		case QAM_16:
2672*4882a593Smuzhiyun 			signal_to_noise_rel = signal_to_noise - 200;
2673*4882a593Smuzhiyun 			break;
2674*4882a593Smuzhiyun 		case QAM_32:
2675*4882a593Smuzhiyun 			signal_to_noise_rel = signal_to_noise - 230;
2676*4882a593Smuzhiyun 			break;	/* Not in NorDig */
2677*4882a593Smuzhiyun 		case QAM_64:
2678*4882a593Smuzhiyun 			signal_to_noise_rel = signal_to_noise - 260;
2679*4882a593Smuzhiyun 			break;
2680*4882a593Smuzhiyun 		case QAM_128:
2681*4882a593Smuzhiyun 			signal_to_noise_rel = signal_to_noise - 290;
2682*4882a593Smuzhiyun 			break;
2683*4882a593Smuzhiyun 		default:
2684*4882a593Smuzhiyun 		case QAM_256:
2685*4882a593Smuzhiyun 			signal_to_noise_rel = signal_to_noise - 320;
2686*4882a593Smuzhiyun 			break;
2687*4882a593Smuzhiyun 		}
2688*4882a593Smuzhiyun 
2689*4882a593Smuzhiyun 		if (signal_to_noise_rel < -70)
2690*4882a593Smuzhiyun 			*p_quality = 0;
2691*4882a593Smuzhiyun 		else if (signal_to_noise_rel < 30)
2692*4882a593Smuzhiyun 			*p_quality = ((signal_to_noise_rel + 70) *
2693*4882a593Smuzhiyun 				     ber_quality) / 100;
2694*4882a593Smuzhiyun 		else
2695*4882a593Smuzhiyun 			*p_quality = ber_quality;
2696*4882a593Smuzhiyun 	} while (0);
2697*4882a593Smuzhiyun 
2698*4882a593Smuzhiyun 	return status;
2699*4882a593Smuzhiyun }
2700*4882a593Smuzhiyun 
2701*4882a593Smuzhiyun static int get_quality(struct drxk_state *state, s32 *p_quality)
2702*4882a593Smuzhiyun {
2703*4882a593Smuzhiyun 	dprintk(1, "\n");
2704*4882a593Smuzhiyun 
2705*4882a593Smuzhiyun 	switch (state->m_operation_mode) {
2706*4882a593Smuzhiyun 	case OM_DVBT:
2707*4882a593Smuzhiyun 		return get_dvbt_quality(state, p_quality);
2708*4882a593Smuzhiyun 	case OM_QAM_ITU_A:
2709*4882a593Smuzhiyun 		return get_dvbc_quality(state, p_quality);
2710*4882a593Smuzhiyun 	default:
2711*4882a593Smuzhiyun 		break;
2712*4882a593Smuzhiyun 	}
2713*4882a593Smuzhiyun 
2714*4882a593Smuzhiyun 	return 0;
2715*4882a593Smuzhiyun }
2716*4882a593Smuzhiyun #endif
2717*4882a593Smuzhiyun 
2718*4882a593Smuzhiyun /* Free data ram in SIO HI */
2719*4882a593Smuzhiyun #define SIO_HI_RA_RAM_USR_BEGIN__A 0x420040
2720*4882a593Smuzhiyun #define SIO_HI_RA_RAM_USR_END__A   0x420060
2721*4882a593Smuzhiyun 
2722*4882a593Smuzhiyun #define DRXK_HI_ATOMIC_BUF_START (SIO_HI_RA_RAM_USR_BEGIN__A)
2723*4882a593Smuzhiyun #define DRXK_HI_ATOMIC_BUF_END   (SIO_HI_RA_RAM_USR_BEGIN__A + 7)
2724*4882a593Smuzhiyun #define DRXK_HI_ATOMIC_READ      SIO_HI_RA_RAM_PAR_3_ACP_RW_READ
2725*4882a593Smuzhiyun #define DRXK_HI_ATOMIC_WRITE     SIO_HI_RA_RAM_PAR_3_ACP_RW_WRITE
2726*4882a593Smuzhiyun 
2727*4882a593Smuzhiyun #define DRXDAP_FASI_ADDR2BLOCK(addr)  (((addr) >> 22) & 0x3F)
2728*4882a593Smuzhiyun #define DRXDAP_FASI_ADDR2BANK(addr)   (((addr) >> 16) & 0x3F)
2729*4882a593Smuzhiyun #define DRXDAP_FASI_ADDR2OFFSET(addr) ((addr) & 0x7FFF)
2730*4882a593Smuzhiyun 
ConfigureI2CBridge(struct drxk_state * state,bool b_enable_bridge)2731*4882a593Smuzhiyun static int ConfigureI2CBridge(struct drxk_state *state, bool b_enable_bridge)
2732*4882a593Smuzhiyun {
2733*4882a593Smuzhiyun 	int status = -EINVAL;
2734*4882a593Smuzhiyun 
2735*4882a593Smuzhiyun 	dprintk(1, "\n");
2736*4882a593Smuzhiyun 
2737*4882a593Smuzhiyun 	if (state->m_drxk_state == DRXK_UNINITIALIZED)
2738*4882a593Smuzhiyun 		return 0;
2739*4882a593Smuzhiyun 	if (state->m_drxk_state == DRXK_POWERED_DOWN)
2740*4882a593Smuzhiyun 		goto error;
2741*4882a593Smuzhiyun 
2742*4882a593Smuzhiyun 	if (state->no_i2c_bridge)
2743*4882a593Smuzhiyun 		return 0;
2744*4882a593Smuzhiyun 
2745*4882a593Smuzhiyun 	status = write16(state, SIO_HI_RA_RAM_PAR_1__A,
2746*4882a593Smuzhiyun 			 SIO_HI_RA_RAM_PAR_1_PAR1_SEC_KEY);
2747*4882a593Smuzhiyun 	if (status < 0)
2748*4882a593Smuzhiyun 		goto error;
2749*4882a593Smuzhiyun 	if (b_enable_bridge) {
2750*4882a593Smuzhiyun 		status = write16(state, SIO_HI_RA_RAM_PAR_2__A,
2751*4882a593Smuzhiyun 				 SIO_HI_RA_RAM_PAR_2_BRD_CFG_CLOSED);
2752*4882a593Smuzhiyun 		if (status < 0)
2753*4882a593Smuzhiyun 			goto error;
2754*4882a593Smuzhiyun 	} else {
2755*4882a593Smuzhiyun 		status = write16(state, SIO_HI_RA_RAM_PAR_2__A,
2756*4882a593Smuzhiyun 				 SIO_HI_RA_RAM_PAR_2_BRD_CFG_OPEN);
2757*4882a593Smuzhiyun 		if (status < 0)
2758*4882a593Smuzhiyun 			goto error;
2759*4882a593Smuzhiyun 	}
2760*4882a593Smuzhiyun 
2761*4882a593Smuzhiyun 	status = hi_command(state, SIO_HI_RA_RAM_CMD_BRDCTRL, NULL);
2762*4882a593Smuzhiyun 
2763*4882a593Smuzhiyun error:
2764*4882a593Smuzhiyun 	if (status < 0)
2765*4882a593Smuzhiyun 		pr_err("Error %d on %s\n", status, __func__);
2766*4882a593Smuzhiyun 	return status;
2767*4882a593Smuzhiyun }
2768*4882a593Smuzhiyun 
set_pre_saw(struct drxk_state * state,struct s_cfg_pre_saw * p_pre_saw_cfg)2769*4882a593Smuzhiyun static int set_pre_saw(struct drxk_state *state,
2770*4882a593Smuzhiyun 		     struct s_cfg_pre_saw *p_pre_saw_cfg)
2771*4882a593Smuzhiyun {
2772*4882a593Smuzhiyun 	int status = -EINVAL;
2773*4882a593Smuzhiyun 
2774*4882a593Smuzhiyun 	dprintk(1, "\n");
2775*4882a593Smuzhiyun 
2776*4882a593Smuzhiyun 	if ((p_pre_saw_cfg == NULL)
2777*4882a593Smuzhiyun 	    || (p_pre_saw_cfg->reference > IQM_AF_PDREF__M))
2778*4882a593Smuzhiyun 		goto error;
2779*4882a593Smuzhiyun 
2780*4882a593Smuzhiyun 	status = write16(state, IQM_AF_PDREF__A, p_pre_saw_cfg->reference);
2781*4882a593Smuzhiyun error:
2782*4882a593Smuzhiyun 	if (status < 0)
2783*4882a593Smuzhiyun 		pr_err("Error %d on %s\n", status, __func__);
2784*4882a593Smuzhiyun 	return status;
2785*4882a593Smuzhiyun }
2786*4882a593Smuzhiyun 
bl_direct_cmd(struct drxk_state * state,u32 target_addr,u16 rom_offset,u16 nr_of_elements,u32 time_out)2787*4882a593Smuzhiyun static int bl_direct_cmd(struct drxk_state *state, u32 target_addr,
2788*4882a593Smuzhiyun 		       u16 rom_offset, u16 nr_of_elements, u32 time_out)
2789*4882a593Smuzhiyun {
2790*4882a593Smuzhiyun 	u16 bl_status = 0;
2791*4882a593Smuzhiyun 	u16 offset = (u16) ((target_addr >> 0) & 0x00FFFF);
2792*4882a593Smuzhiyun 	u16 blockbank = (u16) ((target_addr >> 16) & 0x000FFF);
2793*4882a593Smuzhiyun 	int status;
2794*4882a593Smuzhiyun 	unsigned long end;
2795*4882a593Smuzhiyun 
2796*4882a593Smuzhiyun 	dprintk(1, "\n");
2797*4882a593Smuzhiyun 
2798*4882a593Smuzhiyun 	mutex_lock(&state->mutex);
2799*4882a593Smuzhiyun 	status = write16(state, SIO_BL_MODE__A, SIO_BL_MODE_DIRECT);
2800*4882a593Smuzhiyun 	if (status < 0)
2801*4882a593Smuzhiyun 		goto error;
2802*4882a593Smuzhiyun 	status = write16(state, SIO_BL_TGT_HDR__A, blockbank);
2803*4882a593Smuzhiyun 	if (status < 0)
2804*4882a593Smuzhiyun 		goto error;
2805*4882a593Smuzhiyun 	status = write16(state, SIO_BL_TGT_ADDR__A, offset);
2806*4882a593Smuzhiyun 	if (status < 0)
2807*4882a593Smuzhiyun 		goto error;
2808*4882a593Smuzhiyun 	status = write16(state, SIO_BL_SRC_ADDR__A, rom_offset);
2809*4882a593Smuzhiyun 	if (status < 0)
2810*4882a593Smuzhiyun 		goto error;
2811*4882a593Smuzhiyun 	status = write16(state, SIO_BL_SRC_LEN__A, nr_of_elements);
2812*4882a593Smuzhiyun 	if (status < 0)
2813*4882a593Smuzhiyun 		goto error;
2814*4882a593Smuzhiyun 	status = write16(state, SIO_BL_ENABLE__A, SIO_BL_ENABLE_ON);
2815*4882a593Smuzhiyun 	if (status < 0)
2816*4882a593Smuzhiyun 		goto error;
2817*4882a593Smuzhiyun 
2818*4882a593Smuzhiyun 	end = jiffies + msecs_to_jiffies(time_out);
2819*4882a593Smuzhiyun 	do {
2820*4882a593Smuzhiyun 		status = read16(state, SIO_BL_STATUS__A, &bl_status);
2821*4882a593Smuzhiyun 		if (status < 0)
2822*4882a593Smuzhiyun 			goto error;
2823*4882a593Smuzhiyun 	} while ((bl_status == 0x1) && time_is_after_jiffies(end));
2824*4882a593Smuzhiyun 	if (bl_status == 0x1) {
2825*4882a593Smuzhiyun 		pr_err("SIO not ready\n");
2826*4882a593Smuzhiyun 		status = -EINVAL;
2827*4882a593Smuzhiyun 		goto error2;
2828*4882a593Smuzhiyun 	}
2829*4882a593Smuzhiyun error:
2830*4882a593Smuzhiyun 	if (status < 0)
2831*4882a593Smuzhiyun 		pr_err("Error %d on %s\n", status, __func__);
2832*4882a593Smuzhiyun error2:
2833*4882a593Smuzhiyun 	mutex_unlock(&state->mutex);
2834*4882a593Smuzhiyun 	return status;
2835*4882a593Smuzhiyun 
2836*4882a593Smuzhiyun }
2837*4882a593Smuzhiyun 
adc_sync_measurement(struct drxk_state * state,u16 * count)2838*4882a593Smuzhiyun static int adc_sync_measurement(struct drxk_state *state, u16 *count)
2839*4882a593Smuzhiyun {
2840*4882a593Smuzhiyun 	u16 data = 0;
2841*4882a593Smuzhiyun 	int status;
2842*4882a593Smuzhiyun 
2843*4882a593Smuzhiyun 	dprintk(1, "\n");
2844*4882a593Smuzhiyun 
2845*4882a593Smuzhiyun 	/* start measurement */
2846*4882a593Smuzhiyun 	status = write16(state, IQM_AF_COMM_EXEC__A, IQM_AF_COMM_EXEC_ACTIVE);
2847*4882a593Smuzhiyun 	if (status < 0)
2848*4882a593Smuzhiyun 		goto error;
2849*4882a593Smuzhiyun 	status = write16(state, IQM_AF_START_LOCK__A, 1);
2850*4882a593Smuzhiyun 	if (status < 0)
2851*4882a593Smuzhiyun 		goto error;
2852*4882a593Smuzhiyun 
2853*4882a593Smuzhiyun 	*count = 0;
2854*4882a593Smuzhiyun 	status = read16(state, IQM_AF_PHASE0__A, &data);
2855*4882a593Smuzhiyun 	if (status < 0)
2856*4882a593Smuzhiyun 		goto error;
2857*4882a593Smuzhiyun 	if (data == 127)
2858*4882a593Smuzhiyun 		*count = *count + 1;
2859*4882a593Smuzhiyun 	status = read16(state, IQM_AF_PHASE1__A, &data);
2860*4882a593Smuzhiyun 	if (status < 0)
2861*4882a593Smuzhiyun 		goto error;
2862*4882a593Smuzhiyun 	if (data == 127)
2863*4882a593Smuzhiyun 		*count = *count + 1;
2864*4882a593Smuzhiyun 	status = read16(state, IQM_AF_PHASE2__A, &data);
2865*4882a593Smuzhiyun 	if (status < 0)
2866*4882a593Smuzhiyun 		goto error;
2867*4882a593Smuzhiyun 	if (data == 127)
2868*4882a593Smuzhiyun 		*count = *count + 1;
2869*4882a593Smuzhiyun 
2870*4882a593Smuzhiyun error:
2871*4882a593Smuzhiyun 	if (status < 0)
2872*4882a593Smuzhiyun 		pr_err("Error %d on %s\n", status, __func__);
2873*4882a593Smuzhiyun 	return status;
2874*4882a593Smuzhiyun }
2875*4882a593Smuzhiyun 
adc_synchronization(struct drxk_state * state)2876*4882a593Smuzhiyun static int adc_synchronization(struct drxk_state *state)
2877*4882a593Smuzhiyun {
2878*4882a593Smuzhiyun 	u16 count = 0;
2879*4882a593Smuzhiyun 	int status;
2880*4882a593Smuzhiyun 
2881*4882a593Smuzhiyun 	dprintk(1, "\n");
2882*4882a593Smuzhiyun 
2883*4882a593Smuzhiyun 	status = adc_sync_measurement(state, &count);
2884*4882a593Smuzhiyun 	if (status < 0)
2885*4882a593Smuzhiyun 		goto error;
2886*4882a593Smuzhiyun 
2887*4882a593Smuzhiyun 	if (count == 1) {
2888*4882a593Smuzhiyun 		/* Try sampling on a different edge */
2889*4882a593Smuzhiyun 		u16 clk_neg = 0;
2890*4882a593Smuzhiyun 
2891*4882a593Smuzhiyun 		status = read16(state, IQM_AF_CLKNEG__A, &clk_neg);
2892*4882a593Smuzhiyun 		if (status < 0)
2893*4882a593Smuzhiyun 			goto error;
2894*4882a593Smuzhiyun 		if ((clk_neg & IQM_AF_CLKNEG_CLKNEGDATA__M) ==
2895*4882a593Smuzhiyun 			IQM_AF_CLKNEG_CLKNEGDATA_CLK_ADC_DATA_POS) {
2896*4882a593Smuzhiyun 			clk_neg &= (~(IQM_AF_CLKNEG_CLKNEGDATA__M));
2897*4882a593Smuzhiyun 			clk_neg |=
2898*4882a593Smuzhiyun 				IQM_AF_CLKNEG_CLKNEGDATA_CLK_ADC_DATA_NEG;
2899*4882a593Smuzhiyun 		} else {
2900*4882a593Smuzhiyun 			clk_neg &= (~(IQM_AF_CLKNEG_CLKNEGDATA__M));
2901*4882a593Smuzhiyun 			clk_neg |=
2902*4882a593Smuzhiyun 				IQM_AF_CLKNEG_CLKNEGDATA_CLK_ADC_DATA_POS;
2903*4882a593Smuzhiyun 		}
2904*4882a593Smuzhiyun 		status = write16(state, IQM_AF_CLKNEG__A, clk_neg);
2905*4882a593Smuzhiyun 		if (status < 0)
2906*4882a593Smuzhiyun 			goto error;
2907*4882a593Smuzhiyun 		status = adc_sync_measurement(state, &count);
2908*4882a593Smuzhiyun 		if (status < 0)
2909*4882a593Smuzhiyun 			goto error;
2910*4882a593Smuzhiyun 	}
2911*4882a593Smuzhiyun 
2912*4882a593Smuzhiyun 	if (count < 2)
2913*4882a593Smuzhiyun 		status = -EINVAL;
2914*4882a593Smuzhiyun error:
2915*4882a593Smuzhiyun 	if (status < 0)
2916*4882a593Smuzhiyun 		pr_err("Error %d on %s\n", status, __func__);
2917*4882a593Smuzhiyun 	return status;
2918*4882a593Smuzhiyun }
2919*4882a593Smuzhiyun 
set_frequency_shifter(struct drxk_state * state,u16 intermediate_freqk_hz,s32 tuner_freq_offset,bool is_dtv)2920*4882a593Smuzhiyun static int set_frequency_shifter(struct drxk_state *state,
2921*4882a593Smuzhiyun 			       u16 intermediate_freqk_hz,
2922*4882a593Smuzhiyun 			       s32 tuner_freq_offset, bool is_dtv)
2923*4882a593Smuzhiyun {
2924*4882a593Smuzhiyun 	bool select_pos_image = false;
2925*4882a593Smuzhiyun 	u32 rf_freq_residual = tuner_freq_offset;
2926*4882a593Smuzhiyun 	u32 fm_frequency_shift = 0;
2927*4882a593Smuzhiyun 	bool tuner_mirror = !state->m_b_mirror_freq_spect;
2928*4882a593Smuzhiyun 	u32 adc_freq;
2929*4882a593Smuzhiyun 	bool adc_flip;
2930*4882a593Smuzhiyun 	int status;
2931*4882a593Smuzhiyun 	u32 if_freq_actual;
2932*4882a593Smuzhiyun 	u32 sampling_frequency = (u32) (state->m_sys_clock_freq / 3);
2933*4882a593Smuzhiyun 	u32 frequency_shift;
2934*4882a593Smuzhiyun 	bool image_to_select;
2935*4882a593Smuzhiyun 
2936*4882a593Smuzhiyun 	dprintk(1, "\n");
2937*4882a593Smuzhiyun 
2938*4882a593Smuzhiyun 	/*
2939*4882a593Smuzhiyun 	   Program frequency shifter
2940*4882a593Smuzhiyun 	   No need to account for mirroring on RF
2941*4882a593Smuzhiyun 	 */
2942*4882a593Smuzhiyun 	if (is_dtv) {
2943*4882a593Smuzhiyun 		if ((state->m_operation_mode == OM_QAM_ITU_A) ||
2944*4882a593Smuzhiyun 		    (state->m_operation_mode == OM_QAM_ITU_C) ||
2945*4882a593Smuzhiyun 		    (state->m_operation_mode == OM_DVBT))
2946*4882a593Smuzhiyun 			select_pos_image = true;
2947*4882a593Smuzhiyun 		else
2948*4882a593Smuzhiyun 			select_pos_image = false;
2949*4882a593Smuzhiyun 	}
2950*4882a593Smuzhiyun 	if (tuner_mirror)
2951*4882a593Smuzhiyun 		/* tuner doesn't mirror */
2952*4882a593Smuzhiyun 		if_freq_actual = intermediate_freqk_hz +
2953*4882a593Smuzhiyun 		    rf_freq_residual + fm_frequency_shift;
2954*4882a593Smuzhiyun 	else
2955*4882a593Smuzhiyun 		/* tuner mirrors */
2956*4882a593Smuzhiyun 		if_freq_actual = intermediate_freqk_hz -
2957*4882a593Smuzhiyun 		    rf_freq_residual - fm_frequency_shift;
2958*4882a593Smuzhiyun 	if (if_freq_actual > sampling_frequency / 2) {
2959*4882a593Smuzhiyun 		/* adc mirrors */
2960*4882a593Smuzhiyun 		adc_freq = sampling_frequency - if_freq_actual;
2961*4882a593Smuzhiyun 		adc_flip = true;
2962*4882a593Smuzhiyun 	} else {
2963*4882a593Smuzhiyun 		/* adc doesn't mirror */
2964*4882a593Smuzhiyun 		adc_freq = if_freq_actual;
2965*4882a593Smuzhiyun 		adc_flip = false;
2966*4882a593Smuzhiyun 	}
2967*4882a593Smuzhiyun 
2968*4882a593Smuzhiyun 	frequency_shift = adc_freq;
2969*4882a593Smuzhiyun 	image_to_select = state->m_rfmirror ^ tuner_mirror ^
2970*4882a593Smuzhiyun 	    adc_flip ^ select_pos_image;
2971*4882a593Smuzhiyun 	state->m_iqm_fs_rate_ofs =
2972*4882a593Smuzhiyun 	    Frac28a((frequency_shift), sampling_frequency);
2973*4882a593Smuzhiyun 
2974*4882a593Smuzhiyun 	if (image_to_select)
2975*4882a593Smuzhiyun 		state->m_iqm_fs_rate_ofs = ~state->m_iqm_fs_rate_ofs + 1;
2976*4882a593Smuzhiyun 
2977*4882a593Smuzhiyun 	/* Program frequency shifter with tuner offset compensation */
2978*4882a593Smuzhiyun 	/* frequency_shift += tuner_freq_offset; TODO */
2979*4882a593Smuzhiyun 	status = write32(state, IQM_FS_RATE_OFS_LO__A,
2980*4882a593Smuzhiyun 			 state->m_iqm_fs_rate_ofs);
2981*4882a593Smuzhiyun 	if (status < 0)
2982*4882a593Smuzhiyun 		pr_err("Error %d on %s\n", status, __func__);
2983*4882a593Smuzhiyun 	return status;
2984*4882a593Smuzhiyun }
2985*4882a593Smuzhiyun 
init_agc(struct drxk_state * state,bool is_dtv)2986*4882a593Smuzhiyun static int init_agc(struct drxk_state *state, bool is_dtv)
2987*4882a593Smuzhiyun {
2988*4882a593Smuzhiyun 	u16 ingain_tgt = 0;
2989*4882a593Smuzhiyun 	u16 ingain_tgt_min = 0;
2990*4882a593Smuzhiyun 	u16 ingain_tgt_max = 0;
2991*4882a593Smuzhiyun 	u16 clp_cyclen = 0;
2992*4882a593Smuzhiyun 	u16 clp_sum_min = 0;
2993*4882a593Smuzhiyun 	u16 clp_dir_to = 0;
2994*4882a593Smuzhiyun 	u16 sns_sum_min = 0;
2995*4882a593Smuzhiyun 	u16 sns_sum_max = 0;
2996*4882a593Smuzhiyun 	u16 clp_sum_max = 0;
2997*4882a593Smuzhiyun 	u16 sns_dir_to = 0;
2998*4882a593Smuzhiyun 	u16 ki_innergain_min = 0;
2999*4882a593Smuzhiyun 	u16 if_iaccu_hi_tgt = 0;
3000*4882a593Smuzhiyun 	u16 if_iaccu_hi_tgt_min = 0;
3001*4882a593Smuzhiyun 	u16 if_iaccu_hi_tgt_max = 0;
3002*4882a593Smuzhiyun 	u16 data = 0;
3003*4882a593Smuzhiyun 	u16 fast_clp_ctrl_delay = 0;
3004*4882a593Smuzhiyun 	u16 clp_ctrl_mode = 0;
3005*4882a593Smuzhiyun 	int status = 0;
3006*4882a593Smuzhiyun 
3007*4882a593Smuzhiyun 	dprintk(1, "\n");
3008*4882a593Smuzhiyun 
3009*4882a593Smuzhiyun 	/* Common settings */
3010*4882a593Smuzhiyun 	sns_sum_max = 1023;
3011*4882a593Smuzhiyun 	if_iaccu_hi_tgt_min = 2047;
3012*4882a593Smuzhiyun 	clp_cyclen = 500;
3013*4882a593Smuzhiyun 	clp_sum_max = 1023;
3014*4882a593Smuzhiyun 
3015*4882a593Smuzhiyun 	/* AGCInit() not available for DVBT; init done in microcode */
3016*4882a593Smuzhiyun 	if (!is_qam(state)) {
3017*4882a593Smuzhiyun 		pr_err("%s: mode %d is not DVB-C\n",
3018*4882a593Smuzhiyun 		       __func__, state->m_operation_mode);
3019*4882a593Smuzhiyun 		return -EINVAL;
3020*4882a593Smuzhiyun 	}
3021*4882a593Smuzhiyun 
3022*4882a593Smuzhiyun 	/* FIXME: Analog TV AGC require different settings */
3023*4882a593Smuzhiyun 
3024*4882a593Smuzhiyun 	/* Standard specific settings */
3025*4882a593Smuzhiyun 	clp_sum_min = 8;
3026*4882a593Smuzhiyun 	clp_dir_to = (u16) -9;
3027*4882a593Smuzhiyun 	clp_ctrl_mode = 0;
3028*4882a593Smuzhiyun 	sns_sum_min = 8;
3029*4882a593Smuzhiyun 	sns_dir_to = (u16) -9;
3030*4882a593Smuzhiyun 	ki_innergain_min = (u16) -1030;
3031*4882a593Smuzhiyun 	if_iaccu_hi_tgt_max = 0x2380;
3032*4882a593Smuzhiyun 	if_iaccu_hi_tgt = 0x2380;
3033*4882a593Smuzhiyun 	ingain_tgt_min = 0x0511;
3034*4882a593Smuzhiyun 	ingain_tgt = 0x0511;
3035*4882a593Smuzhiyun 	ingain_tgt_max = 5119;
3036*4882a593Smuzhiyun 	fast_clp_ctrl_delay = state->m_qam_if_agc_cfg.fast_clip_ctrl_delay;
3037*4882a593Smuzhiyun 
3038*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_AGC_FAST_CLP_CTRL_DELAY__A,
3039*4882a593Smuzhiyun 			 fast_clp_ctrl_delay);
3040*4882a593Smuzhiyun 	if (status < 0)
3041*4882a593Smuzhiyun 		goto error;
3042*4882a593Smuzhiyun 
3043*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_AGC_CLP_CTRL_MODE__A, clp_ctrl_mode);
3044*4882a593Smuzhiyun 	if (status < 0)
3045*4882a593Smuzhiyun 		goto error;
3046*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_AGC_INGAIN_TGT__A, ingain_tgt);
3047*4882a593Smuzhiyun 	if (status < 0)
3048*4882a593Smuzhiyun 		goto error;
3049*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_AGC_INGAIN_TGT_MIN__A, ingain_tgt_min);
3050*4882a593Smuzhiyun 	if (status < 0)
3051*4882a593Smuzhiyun 		goto error;
3052*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_AGC_INGAIN_TGT_MAX__A, ingain_tgt_max);
3053*4882a593Smuzhiyun 	if (status < 0)
3054*4882a593Smuzhiyun 		goto error;
3055*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_AGC_IF_IACCU_HI_TGT_MIN__A,
3056*4882a593Smuzhiyun 			 if_iaccu_hi_tgt_min);
3057*4882a593Smuzhiyun 	if (status < 0)
3058*4882a593Smuzhiyun 		goto error;
3059*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A,
3060*4882a593Smuzhiyun 			 if_iaccu_hi_tgt_max);
3061*4882a593Smuzhiyun 	if (status < 0)
3062*4882a593Smuzhiyun 		goto error;
3063*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_AGC_IF_IACCU_HI__A, 0);
3064*4882a593Smuzhiyun 	if (status < 0)
3065*4882a593Smuzhiyun 		goto error;
3066*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_AGC_IF_IACCU_LO__A, 0);
3067*4882a593Smuzhiyun 	if (status < 0)
3068*4882a593Smuzhiyun 		goto error;
3069*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_AGC_RF_IACCU_HI__A, 0);
3070*4882a593Smuzhiyun 	if (status < 0)
3071*4882a593Smuzhiyun 		goto error;
3072*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_AGC_RF_IACCU_LO__A, 0);
3073*4882a593Smuzhiyun 	if (status < 0)
3074*4882a593Smuzhiyun 		goto error;
3075*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_AGC_CLP_SUM_MAX__A, clp_sum_max);
3076*4882a593Smuzhiyun 	if (status < 0)
3077*4882a593Smuzhiyun 		goto error;
3078*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_AGC_SNS_SUM_MAX__A, sns_sum_max);
3079*4882a593Smuzhiyun 	if (status < 0)
3080*4882a593Smuzhiyun 		goto error;
3081*4882a593Smuzhiyun 
3082*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_AGC_KI_INNERGAIN_MIN__A,
3083*4882a593Smuzhiyun 			 ki_innergain_min);
3084*4882a593Smuzhiyun 	if (status < 0)
3085*4882a593Smuzhiyun 		goto error;
3086*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_AGC_IF_IACCU_HI_TGT__A,
3087*4882a593Smuzhiyun 			 if_iaccu_hi_tgt);
3088*4882a593Smuzhiyun 	if (status < 0)
3089*4882a593Smuzhiyun 		goto error;
3090*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_AGC_CLP_CYCLEN__A, clp_cyclen);
3091*4882a593Smuzhiyun 	if (status < 0)
3092*4882a593Smuzhiyun 		goto error;
3093*4882a593Smuzhiyun 
3094*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_AGC_RF_SNS_DEV_MAX__A, 1023);
3095*4882a593Smuzhiyun 	if (status < 0)
3096*4882a593Smuzhiyun 		goto error;
3097*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_AGC_RF_SNS_DEV_MIN__A, (u16) -1023);
3098*4882a593Smuzhiyun 	if (status < 0)
3099*4882a593Smuzhiyun 		goto error;
3100*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_AGC_FAST_SNS_CTRL_DELAY__A, 50);
3101*4882a593Smuzhiyun 	if (status < 0)
3102*4882a593Smuzhiyun 		goto error;
3103*4882a593Smuzhiyun 
3104*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_AGC_KI_MAXMINGAIN_TH__A, 20);
3105*4882a593Smuzhiyun 	if (status < 0)
3106*4882a593Smuzhiyun 		goto error;
3107*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_AGC_CLP_SUM_MIN__A, clp_sum_min);
3108*4882a593Smuzhiyun 	if (status < 0)
3109*4882a593Smuzhiyun 		goto error;
3110*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_AGC_SNS_SUM_MIN__A, sns_sum_min);
3111*4882a593Smuzhiyun 	if (status < 0)
3112*4882a593Smuzhiyun 		goto error;
3113*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_AGC_CLP_DIR_TO__A, clp_dir_to);
3114*4882a593Smuzhiyun 	if (status < 0)
3115*4882a593Smuzhiyun 		goto error;
3116*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_AGC_SNS_DIR_TO__A, sns_dir_to);
3117*4882a593Smuzhiyun 	if (status < 0)
3118*4882a593Smuzhiyun 		goto error;
3119*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_AGC_KI_MINGAIN__A, 0x7fff);
3120*4882a593Smuzhiyun 	if (status < 0)
3121*4882a593Smuzhiyun 		goto error;
3122*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_AGC_KI_MAXGAIN__A, 0x0);
3123*4882a593Smuzhiyun 	if (status < 0)
3124*4882a593Smuzhiyun 		goto error;
3125*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_AGC_KI_MIN__A, 0x0117);
3126*4882a593Smuzhiyun 	if (status < 0)
3127*4882a593Smuzhiyun 		goto error;
3128*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_AGC_KI_MAX__A, 0x0657);
3129*4882a593Smuzhiyun 	if (status < 0)
3130*4882a593Smuzhiyun 		goto error;
3131*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_AGC_CLP_SUM__A, 0);
3132*4882a593Smuzhiyun 	if (status < 0)
3133*4882a593Smuzhiyun 		goto error;
3134*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_AGC_CLP_CYCCNT__A, 0);
3135*4882a593Smuzhiyun 	if (status < 0)
3136*4882a593Smuzhiyun 		goto error;
3137*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_AGC_CLP_DIR_WD__A, 0);
3138*4882a593Smuzhiyun 	if (status < 0)
3139*4882a593Smuzhiyun 		goto error;
3140*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_AGC_CLP_DIR_STP__A, 1);
3141*4882a593Smuzhiyun 	if (status < 0)
3142*4882a593Smuzhiyun 		goto error;
3143*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_AGC_SNS_SUM__A, 0);
3144*4882a593Smuzhiyun 	if (status < 0)
3145*4882a593Smuzhiyun 		goto error;
3146*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_AGC_SNS_CYCCNT__A, 0);
3147*4882a593Smuzhiyun 	if (status < 0)
3148*4882a593Smuzhiyun 		goto error;
3149*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_AGC_SNS_DIR_WD__A, 0);
3150*4882a593Smuzhiyun 	if (status < 0)
3151*4882a593Smuzhiyun 		goto error;
3152*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_AGC_SNS_DIR_STP__A, 1);
3153*4882a593Smuzhiyun 	if (status < 0)
3154*4882a593Smuzhiyun 		goto error;
3155*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_AGC_SNS_CYCLEN__A, 500);
3156*4882a593Smuzhiyun 	if (status < 0)
3157*4882a593Smuzhiyun 		goto error;
3158*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_AGC_KI_CYCLEN__A, 500);
3159*4882a593Smuzhiyun 	if (status < 0)
3160*4882a593Smuzhiyun 		goto error;
3161*4882a593Smuzhiyun 
3162*4882a593Smuzhiyun 	/* Initialize inner-loop KI gain factors */
3163*4882a593Smuzhiyun 	status = read16(state, SCU_RAM_AGC_KI__A, &data);
3164*4882a593Smuzhiyun 	if (status < 0)
3165*4882a593Smuzhiyun 		goto error;
3166*4882a593Smuzhiyun 
3167*4882a593Smuzhiyun 	data = 0x0657;
3168*4882a593Smuzhiyun 	data &= ~SCU_RAM_AGC_KI_RF__M;
3169*4882a593Smuzhiyun 	data |= (DRXK_KI_RAGC_QAM << SCU_RAM_AGC_KI_RF__B);
3170*4882a593Smuzhiyun 	data &= ~SCU_RAM_AGC_KI_IF__M;
3171*4882a593Smuzhiyun 	data |= (DRXK_KI_IAGC_QAM << SCU_RAM_AGC_KI_IF__B);
3172*4882a593Smuzhiyun 
3173*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_AGC_KI__A, data);
3174*4882a593Smuzhiyun error:
3175*4882a593Smuzhiyun 	if (status < 0)
3176*4882a593Smuzhiyun 		pr_err("Error %d on %s\n", status, __func__);
3177*4882a593Smuzhiyun 	return status;
3178*4882a593Smuzhiyun }
3179*4882a593Smuzhiyun 
dvbtqam_get_acc_pkt_err(struct drxk_state * state,u16 * packet_err)3180*4882a593Smuzhiyun static int dvbtqam_get_acc_pkt_err(struct drxk_state *state, u16 *packet_err)
3181*4882a593Smuzhiyun {
3182*4882a593Smuzhiyun 	int status;
3183*4882a593Smuzhiyun 
3184*4882a593Smuzhiyun 	dprintk(1, "\n");
3185*4882a593Smuzhiyun 	if (packet_err == NULL)
3186*4882a593Smuzhiyun 		status = write16(state, SCU_RAM_FEC_ACCUM_PKT_FAILURES__A, 0);
3187*4882a593Smuzhiyun 	else
3188*4882a593Smuzhiyun 		status = read16(state, SCU_RAM_FEC_ACCUM_PKT_FAILURES__A,
3189*4882a593Smuzhiyun 				packet_err);
3190*4882a593Smuzhiyun 	if (status < 0)
3191*4882a593Smuzhiyun 		pr_err("Error %d on %s\n", status, __func__);
3192*4882a593Smuzhiyun 	return status;
3193*4882a593Smuzhiyun }
3194*4882a593Smuzhiyun 
dvbt_sc_command(struct drxk_state * state,u16 cmd,u16 subcmd,u16 param0,u16 param1,u16 param2,u16 param3,u16 param4)3195*4882a593Smuzhiyun static int dvbt_sc_command(struct drxk_state *state,
3196*4882a593Smuzhiyun 			 u16 cmd, u16 subcmd,
3197*4882a593Smuzhiyun 			 u16 param0, u16 param1, u16 param2,
3198*4882a593Smuzhiyun 			 u16 param3, u16 param4)
3199*4882a593Smuzhiyun {
3200*4882a593Smuzhiyun 	u16 cur_cmd = 0;
3201*4882a593Smuzhiyun 	u16 err_code = 0;
3202*4882a593Smuzhiyun 	u16 retry_cnt = 0;
3203*4882a593Smuzhiyun 	u16 sc_exec = 0;
3204*4882a593Smuzhiyun 	int status;
3205*4882a593Smuzhiyun 
3206*4882a593Smuzhiyun 	dprintk(1, "\n");
3207*4882a593Smuzhiyun 	status = read16(state, OFDM_SC_COMM_EXEC__A, &sc_exec);
3208*4882a593Smuzhiyun 	if (sc_exec != 1) {
3209*4882a593Smuzhiyun 		/* SC is not running */
3210*4882a593Smuzhiyun 		status = -EINVAL;
3211*4882a593Smuzhiyun 	}
3212*4882a593Smuzhiyun 	if (status < 0)
3213*4882a593Smuzhiyun 		goto error;
3214*4882a593Smuzhiyun 
3215*4882a593Smuzhiyun 	/* Wait until sc is ready to receive command */
3216*4882a593Smuzhiyun 	retry_cnt = 0;
3217*4882a593Smuzhiyun 	do {
3218*4882a593Smuzhiyun 		usleep_range(1000, 2000);
3219*4882a593Smuzhiyun 		status = read16(state, OFDM_SC_RA_RAM_CMD__A, &cur_cmd);
3220*4882a593Smuzhiyun 		retry_cnt++;
3221*4882a593Smuzhiyun 	} while ((cur_cmd != 0) && (retry_cnt < DRXK_MAX_RETRIES));
3222*4882a593Smuzhiyun 	if (retry_cnt >= DRXK_MAX_RETRIES && (status < 0))
3223*4882a593Smuzhiyun 		goto error;
3224*4882a593Smuzhiyun 
3225*4882a593Smuzhiyun 	/* Write sub-command */
3226*4882a593Smuzhiyun 	switch (cmd) {
3227*4882a593Smuzhiyun 		/* All commands using sub-cmd */
3228*4882a593Smuzhiyun 	case OFDM_SC_RA_RAM_CMD_PROC_START:
3229*4882a593Smuzhiyun 	case OFDM_SC_RA_RAM_CMD_SET_PREF_PARAM:
3230*4882a593Smuzhiyun 	case OFDM_SC_RA_RAM_CMD_PROGRAM_PARAM:
3231*4882a593Smuzhiyun 		status = write16(state, OFDM_SC_RA_RAM_CMD_ADDR__A, subcmd);
3232*4882a593Smuzhiyun 		if (status < 0)
3233*4882a593Smuzhiyun 			goto error;
3234*4882a593Smuzhiyun 		break;
3235*4882a593Smuzhiyun 	default:
3236*4882a593Smuzhiyun 		/* Do nothing */
3237*4882a593Smuzhiyun 		break;
3238*4882a593Smuzhiyun 	}
3239*4882a593Smuzhiyun 
3240*4882a593Smuzhiyun 	/* Write needed parameters and the command */
3241*4882a593Smuzhiyun 	status = 0;
3242*4882a593Smuzhiyun 	switch (cmd) {
3243*4882a593Smuzhiyun 		/* All commands using 5 parameters */
3244*4882a593Smuzhiyun 		/* All commands using 4 parameters */
3245*4882a593Smuzhiyun 		/* All commands using 3 parameters */
3246*4882a593Smuzhiyun 		/* All commands using 2 parameters */
3247*4882a593Smuzhiyun 	case OFDM_SC_RA_RAM_CMD_PROC_START:
3248*4882a593Smuzhiyun 	case OFDM_SC_RA_RAM_CMD_SET_PREF_PARAM:
3249*4882a593Smuzhiyun 	case OFDM_SC_RA_RAM_CMD_PROGRAM_PARAM:
3250*4882a593Smuzhiyun 		status |= write16(state, OFDM_SC_RA_RAM_PARAM1__A, param1);
3251*4882a593Smuzhiyun 		fallthrough;	/* All commands using 1 parameters */
3252*4882a593Smuzhiyun 	case OFDM_SC_RA_RAM_CMD_SET_ECHO_TIMING:
3253*4882a593Smuzhiyun 	case OFDM_SC_RA_RAM_CMD_USER_IO:
3254*4882a593Smuzhiyun 		status |= write16(state, OFDM_SC_RA_RAM_PARAM0__A, param0);
3255*4882a593Smuzhiyun 		fallthrough;	/* All commands using 0 parameters */
3256*4882a593Smuzhiyun 	case OFDM_SC_RA_RAM_CMD_GET_OP_PARAM:
3257*4882a593Smuzhiyun 	case OFDM_SC_RA_RAM_CMD_NULL:
3258*4882a593Smuzhiyun 		/* Write command */
3259*4882a593Smuzhiyun 		status |= write16(state, OFDM_SC_RA_RAM_CMD__A, cmd);
3260*4882a593Smuzhiyun 		break;
3261*4882a593Smuzhiyun 	default:
3262*4882a593Smuzhiyun 		/* Unknown command */
3263*4882a593Smuzhiyun 		status = -EINVAL;
3264*4882a593Smuzhiyun 	}
3265*4882a593Smuzhiyun 	if (status < 0)
3266*4882a593Smuzhiyun 		goto error;
3267*4882a593Smuzhiyun 
3268*4882a593Smuzhiyun 	/* Wait until sc is ready processing command */
3269*4882a593Smuzhiyun 	retry_cnt = 0;
3270*4882a593Smuzhiyun 	do {
3271*4882a593Smuzhiyun 		usleep_range(1000, 2000);
3272*4882a593Smuzhiyun 		status = read16(state, OFDM_SC_RA_RAM_CMD__A, &cur_cmd);
3273*4882a593Smuzhiyun 		retry_cnt++;
3274*4882a593Smuzhiyun 	} while ((cur_cmd != 0) && (retry_cnt < DRXK_MAX_RETRIES));
3275*4882a593Smuzhiyun 	if (retry_cnt >= DRXK_MAX_RETRIES && (status < 0))
3276*4882a593Smuzhiyun 		goto error;
3277*4882a593Smuzhiyun 
3278*4882a593Smuzhiyun 	/* Check for illegal cmd */
3279*4882a593Smuzhiyun 	status = read16(state, OFDM_SC_RA_RAM_CMD_ADDR__A, &err_code);
3280*4882a593Smuzhiyun 	if (err_code == 0xFFFF) {
3281*4882a593Smuzhiyun 		/* illegal command */
3282*4882a593Smuzhiyun 		status = -EINVAL;
3283*4882a593Smuzhiyun 	}
3284*4882a593Smuzhiyun 	if (status < 0)
3285*4882a593Smuzhiyun 		goto error;
3286*4882a593Smuzhiyun 
3287*4882a593Smuzhiyun 	/* Retrieve results parameters from SC */
3288*4882a593Smuzhiyun 	switch (cmd) {
3289*4882a593Smuzhiyun 		/* All commands yielding 5 results */
3290*4882a593Smuzhiyun 		/* All commands yielding 4 results */
3291*4882a593Smuzhiyun 		/* All commands yielding 3 results */
3292*4882a593Smuzhiyun 		/* All commands yielding 2 results */
3293*4882a593Smuzhiyun 		/* All commands yielding 1 result */
3294*4882a593Smuzhiyun 	case OFDM_SC_RA_RAM_CMD_USER_IO:
3295*4882a593Smuzhiyun 	case OFDM_SC_RA_RAM_CMD_GET_OP_PARAM:
3296*4882a593Smuzhiyun 		status = read16(state, OFDM_SC_RA_RAM_PARAM0__A, &(param0));
3297*4882a593Smuzhiyun 		/* All commands yielding 0 results */
3298*4882a593Smuzhiyun 	case OFDM_SC_RA_RAM_CMD_SET_ECHO_TIMING:
3299*4882a593Smuzhiyun 	case OFDM_SC_RA_RAM_CMD_SET_TIMER:
3300*4882a593Smuzhiyun 	case OFDM_SC_RA_RAM_CMD_PROC_START:
3301*4882a593Smuzhiyun 	case OFDM_SC_RA_RAM_CMD_SET_PREF_PARAM:
3302*4882a593Smuzhiyun 	case OFDM_SC_RA_RAM_CMD_PROGRAM_PARAM:
3303*4882a593Smuzhiyun 	case OFDM_SC_RA_RAM_CMD_NULL:
3304*4882a593Smuzhiyun 		break;
3305*4882a593Smuzhiyun 	default:
3306*4882a593Smuzhiyun 		/* Unknown command */
3307*4882a593Smuzhiyun 		status = -EINVAL;
3308*4882a593Smuzhiyun 		break;
3309*4882a593Smuzhiyun 	}			/* switch (cmd->cmd) */
3310*4882a593Smuzhiyun error:
3311*4882a593Smuzhiyun 	if (status < 0)
3312*4882a593Smuzhiyun 		pr_err("Error %d on %s\n", status, __func__);
3313*4882a593Smuzhiyun 	return status;
3314*4882a593Smuzhiyun }
3315*4882a593Smuzhiyun 
power_up_dvbt(struct drxk_state * state)3316*4882a593Smuzhiyun static int power_up_dvbt(struct drxk_state *state)
3317*4882a593Smuzhiyun {
3318*4882a593Smuzhiyun 	enum drx_power_mode power_mode = DRX_POWER_UP;
3319*4882a593Smuzhiyun 	int status;
3320*4882a593Smuzhiyun 
3321*4882a593Smuzhiyun 	dprintk(1, "\n");
3322*4882a593Smuzhiyun 	status = ctrl_power_mode(state, &power_mode);
3323*4882a593Smuzhiyun 	if (status < 0)
3324*4882a593Smuzhiyun 		pr_err("Error %d on %s\n", status, __func__);
3325*4882a593Smuzhiyun 	return status;
3326*4882a593Smuzhiyun }
3327*4882a593Smuzhiyun 
dvbt_ctrl_set_inc_enable(struct drxk_state * state,bool * enabled)3328*4882a593Smuzhiyun static int dvbt_ctrl_set_inc_enable(struct drxk_state *state, bool *enabled)
3329*4882a593Smuzhiyun {
3330*4882a593Smuzhiyun 	int status;
3331*4882a593Smuzhiyun 
3332*4882a593Smuzhiyun 	dprintk(1, "\n");
3333*4882a593Smuzhiyun 	if (*enabled)
3334*4882a593Smuzhiyun 		status = write16(state, IQM_CF_BYPASSDET__A, 0);
3335*4882a593Smuzhiyun 	else
3336*4882a593Smuzhiyun 		status = write16(state, IQM_CF_BYPASSDET__A, 1);
3337*4882a593Smuzhiyun 	if (status < 0)
3338*4882a593Smuzhiyun 		pr_err("Error %d on %s\n", status, __func__);
3339*4882a593Smuzhiyun 	return status;
3340*4882a593Smuzhiyun }
3341*4882a593Smuzhiyun 
3342*4882a593Smuzhiyun #define DEFAULT_FR_THRES_8K     4000
dvbt_ctrl_set_fr_enable(struct drxk_state * state,bool * enabled)3343*4882a593Smuzhiyun static int dvbt_ctrl_set_fr_enable(struct drxk_state *state, bool *enabled)
3344*4882a593Smuzhiyun {
3345*4882a593Smuzhiyun 
3346*4882a593Smuzhiyun 	int status;
3347*4882a593Smuzhiyun 
3348*4882a593Smuzhiyun 	dprintk(1, "\n");
3349*4882a593Smuzhiyun 	if (*enabled) {
3350*4882a593Smuzhiyun 		/* write mask to 1 */
3351*4882a593Smuzhiyun 		status = write16(state, OFDM_SC_RA_RAM_FR_THRES_8K__A,
3352*4882a593Smuzhiyun 				   DEFAULT_FR_THRES_8K);
3353*4882a593Smuzhiyun 	} else {
3354*4882a593Smuzhiyun 		/* write mask to 0 */
3355*4882a593Smuzhiyun 		status = write16(state, OFDM_SC_RA_RAM_FR_THRES_8K__A, 0);
3356*4882a593Smuzhiyun 	}
3357*4882a593Smuzhiyun 	if (status < 0)
3358*4882a593Smuzhiyun 		pr_err("Error %d on %s\n", status, __func__);
3359*4882a593Smuzhiyun 
3360*4882a593Smuzhiyun 	return status;
3361*4882a593Smuzhiyun }
3362*4882a593Smuzhiyun 
dvbt_ctrl_set_echo_threshold(struct drxk_state * state,struct drxk_cfg_dvbt_echo_thres_t * echo_thres)3363*4882a593Smuzhiyun static int dvbt_ctrl_set_echo_threshold(struct drxk_state *state,
3364*4882a593Smuzhiyun 				struct drxk_cfg_dvbt_echo_thres_t *echo_thres)
3365*4882a593Smuzhiyun {
3366*4882a593Smuzhiyun 	u16 data = 0;
3367*4882a593Smuzhiyun 	int status;
3368*4882a593Smuzhiyun 
3369*4882a593Smuzhiyun 	dprintk(1, "\n");
3370*4882a593Smuzhiyun 	status = read16(state, OFDM_SC_RA_RAM_ECHO_THRES__A, &data);
3371*4882a593Smuzhiyun 	if (status < 0)
3372*4882a593Smuzhiyun 		goto error;
3373*4882a593Smuzhiyun 
3374*4882a593Smuzhiyun 	switch (echo_thres->fft_mode) {
3375*4882a593Smuzhiyun 	case DRX_FFTMODE_2K:
3376*4882a593Smuzhiyun 		data &= ~OFDM_SC_RA_RAM_ECHO_THRES_2K__M;
3377*4882a593Smuzhiyun 		data |= ((echo_thres->threshold <<
3378*4882a593Smuzhiyun 			OFDM_SC_RA_RAM_ECHO_THRES_2K__B)
3379*4882a593Smuzhiyun 			& (OFDM_SC_RA_RAM_ECHO_THRES_2K__M));
3380*4882a593Smuzhiyun 		break;
3381*4882a593Smuzhiyun 	case DRX_FFTMODE_8K:
3382*4882a593Smuzhiyun 		data &= ~OFDM_SC_RA_RAM_ECHO_THRES_8K__M;
3383*4882a593Smuzhiyun 		data |= ((echo_thres->threshold <<
3384*4882a593Smuzhiyun 			OFDM_SC_RA_RAM_ECHO_THRES_8K__B)
3385*4882a593Smuzhiyun 			& (OFDM_SC_RA_RAM_ECHO_THRES_8K__M));
3386*4882a593Smuzhiyun 		break;
3387*4882a593Smuzhiyun 	default:
3388*4882a593Smuzhiyun 		return -EINVAL;
3389*4882a593Smuzhiyun 	}
3390*4882a593Smuzhiyun 
3391*4882a593Smuzhiyun 	status = write16(state, OFDM_SC_RA_RAM_ECHO_THRES__A, data);
3392*4882a593Smuzhiyun error:
3393*4882a593Smuzhiyun 	if (status < 0)
3394*4882a593Smuzhiyun 		pr_err("Error %d on %s\n", status, __func__);
3395*4882a593Smuzhiyun 	return status;
3396*4882a593Smuzhiyun }
3397*4882a593Smuzhiyun 
dvbt_ctrl_set_sqi_speed(struct drxk_state * state,enum drxk_cfg_dvbt_sqi_speed * speed)3398*4882a593Smuzhiyun static int dvbt_ctrl_set_sqi_speed(struct drxk_state *state,
3399*4882a593Smuzhiyun 			       enum drxk_cfg_dvbt_sqi_speed *speed)
3400*4882a593Smuzhiyun {
3401*4882a593Smuzhiyun 	int status = -EINVAL;
3402*4882a593Smuzhiyun 
3403*4882a593Smuzhiyun 	dprintk(1, "\n");
3404*4882a593Smuzhiyun 
3405*4882a593Smuzhiyun 	switch (*speed) {
3406*4882a593Smuzhiyun 	case DRXK_DVBT_SQI_SPEED_FAST:
3407*4882a593Smuzhiyun 	case DRXK_DVBT_SQI_SPEED_MEDIUM:
3408*4882a593Smuzhiyun 	case DRXK_DVBT_SQI_SPEED_SLOW:
3409*4882a593Smuzhiyun 		break;
3410*4882a593Smuzhiyun 	default:
3411*4882a593Smuzhiyun 		goto error;
3412*4882a593Smuzhiyun 	}
3413*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_FEC_PRE_RS_BER_FILTER_SH__A,
3414*4882a593Smuzhiyun 			   (u16) *speed);
3415*4882a593Smuzhiyun error:
3416*4882a593Smuzhiyun 	if (status < 0)
3417*4882a593Smuzhiyun 		pr_err("Error %d on %s\n", status, __func__);
3418*4882a593Smuzhiyun 	return status;
3419*4882a593Smuzhiyun }
3420*4882a593Smuzhiyun 
3421*4882a593Smuzhiyun /*============================================================================*/
3422*4882a593Smuzhiyun 
3423*4882a593Smuzhiyun /*
3424*4882a593Smuzhiyun * \brief Activate DVBT specific presets
3425*4882a593Smuzhiyun * \param demod instance of demodulator.
3426*4882a593Smuzhiyun * \return DRXStatus_t.
3427*4882a593Smuzhiyun *
3428*4882a593Smuzhiyun * Called in DVBTSetStandard
3429*4882a593Smuzhiyun *
3430*4882a593Smuzhiyun */
dvbt_activate_presets(struct drxk_state * state)3431*4882a593Smuzhiyun static int dvbt_activate_presets(struct drxk_state *state)
3432*4882a593Smuzhiyun {
3433*4882a593Smuzhiyun 	int status;
3434*4882a593Smuzhiyun 	bool setincenable = false;
3435*4882a593Smuzhiyun 	bool setfrenable = true;
3436*4882a593Smuzhiyun 
3437*4882a593Smuzhiyun 	struct drxk_cfg_dvbt_echo_thres_t echo_thres2k = { 0, DRX_FFTMODE_2K };
3438*4882a593Smuzhiyun 	struct drxk_cfg_dvbt_echo_thres_t echo_thres8k = { 0, DRX_FFTMODE_8K };
3439*4882a593Smuzhiyun 
3440*4882a593Smuzhiyun 	dprintk(1, "\n");
3441*4882a593Smuzhiyun 	status = dvbt_ctrl_set_inc_enable(state, &setincenable);
3442*4882a593Smuzhiyun 	if (status < 0)
3443*4882a593Smuzhiyun 		goto error;
3444*4882a593Smuzhiyun 	status = dvbt_ctrl_set_fr_enable(state, &setfrenable);
3445*4882a593Smuzhiyun 	if (status < 0)
3446*4882a593Smuzhiyun 		goto error;
3447*4882a593Smuzhiyun 	status = dvbt_ctrl_set_echo_threshold(state, &echo_thres2k);
3448*4882a593Smuzhiyun 	if (status < 0)
3449*4882a593Smuzhiyun 		goto error;
3450*4882a593Smuzhiyun 	status = dvbt_ctrl_set_echo_threshold(state, &echo_thres8k);
3451*4882a593Smuzhiyun 	if (status < 0)
3452*4882a593Smuzhiyun 		goto error;
3453*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_AGC_INGAIN_TGT_MAX__A,
3454*4882a593Smuzhiyun 			 state->m_dvbt_if_agc_cfg.ingain_tgt_max);
3455*4882a593Smuzhiyun error:
3456*4882a593Smuzhiyun 	if (status < 0)
3457*4882a593Smuzhiyun 		pr_err("Error %d on %s\n", status, __func__);
3458*4882a593Smuzhiyun 	return status;
3459*4882a593Smuzhiyun }
3460*4882a593Smuzhiyun 
3461*4882a593Smuzhiyun /*============================================================================*/
3462*4882a593Smuzhiyun 
3463*4882a593Smuzhiyun /*
3464*4882a593Smuzhiyun * \brief Initialize channelswitch-independent settings for DVBT.
3465*4882a593Smuzhiyun * \param demod instance of demodulator.
3466*4882a593Smuzhiyun * \return DRXStatus_t.
3467*4882a593Smuzhiyun *
3468*4882a593Smuzhiyun * For ROM code channel filter taps are loaded from the bootloader. For microcode
3469*4882a593Smuzhiyun * the DVB-T taps from the drxk_filters.h are used.
3470*4882a593Smuzhiyun */
set_dvbt_standard(struct drxk_state * state,enum operation_mode o_mode)3471*4882a593Smuzhiyun static int set_dvbt_standard(struct drxk_state *state,
3472*4882a593Smuzhiyun 			   enum operation_mode o_mode)
3473*4882a593Smuzhiyun {
3474*4882a593Smuzhiyun 	u16 cmd_result = 0;
3475*4882a593Smuzhiyun 	u16 data = 0;
3476*4882a593Smuzhiyun 	int status;
3477*4882a593Smuzhiyun 
3478*4882a593Smuzhiyun 	dprintk(1, "\n");
3479*4882a593Smuzhiyun 
3480*4882a593Smuzhiyun 	power_up_dvbt(state);
3481*4882a593Smuzhiyun 	/* added antenna switch */
3482*4882a593Smuzhiyun 	switch_antenna_to_dvbt(state);
3483*4882a593Smuzhiyun 	/* send OFDM reset command */
3484*4882a593Smuzhiyun 	status = scu_command(state,
3485*4882a593Smuzhiyun 			     SCU_RAM_COMMAND_STANDARD_OFDM
3486*4882a593Smuzhiyun 			     | SCU_RAM_COMMAND_CMD_DEMOD_RESET,
3487*4882a593Smuzhiyun 			     0, NULL, 1, &cmd_result);
3488*4882a593Smuzhiyun 	if (status < 0)
3489*4882a593Smuzhiyun 		goto error;
3490*4882a593Smuzhiyun 
3491*4882a593Smuzhiyun 	/* send OFDM setenv command */
3492*4882a593Smuzhiyun 	status = scu_command(state, SCU_RAM_COMMAND_STANDARD_OFDM
3493*4882a593Smuzhiyun 			     | SCU_RAM_COMMAND_CMD_DEMOD_SET_ENV,
3494*4882a593Smuzhiyun 			     0, NULL, 1, &cmd_result);
3495*4882a593Smuzhiyun 	if (status < 0)
3496*4882a593Smuzhiyun 		goto error;
3497*4882a593Smuzhiyun 
3498*4882a593Smuzhiyun 	/* reset datapath for OFDM, processors first */
3499*4882a593Smuzhiyun 	status = write16(state, OFDM_SC_COMM_EXEC__A, OFDM_SC_COMM_EXEC_STOP);
3500*4882a593Smuzhiyun 	if (status < 0)
3501*4882a593Smuzhiyun 		goto error;
3502*4882a593Smuzhiyun 	status = write16(state, OFDM_LC_COMM_EXEC__A, OFDM_LC_COMM_EXEC_STOP);
3503*4882a593Smuzhiyun 	if (status < 0)
3504*4882a593Smuzhiyun 		goto error;
3505*4882a593Smuzhiyun 	status = write16(state, IQM_COMM_EXEC__A, IQM_COMM_EXEC_B_STOP);
3506*4882a593Smuzhiyun 	if (status < 0)
3507*4882a593Smuzhiyun 		goto error;
3508*4882a593Smuzhiyun 
3509*4882a593Smuzhiyun 	/* IQM setup */
3510*4882a593Smuzhiyun 	/* synchronize on ofdstate->m_festart */
3511*4882a593Smuzhiyun 	status = write16(state, IQM_AF_UPD_SEL__A, 1);
3512*4882a593Smuzhiyun 	if (status < 0)
3513*4882a593Smuzhiyun 		goto error;
3514*4882a593Smuzhiyun 	/* window size for clipping ADC detection */
3515*4882a593Smuzhiyun 	status = write16(state, IQM_AF_CLP_LEN__A, 0);
3516*4882a593Smuzhiyun 	if (status < 0)
3517*4882a593Smuzhiyun 		goto error;
3518*4882a593Smuzhiyun 	/* window size for for sense pre-SAW detection */
3519*4882a593Smuzhiyun 	status = write16(state, IQM_AF_SNS_LEN__A, 0);
3520*4882a593Smuzhiyun 	if (status < 0)
3521*4882a593Smuzhiyun 		goto error;
3522*4882a593Smuzhiyun 	/* sense threshold for sense pre-SAW detection */
3523*4882a593Smuzhiyun 	status = write16(state, IQM_AF_AMUX__A, IQM_AF_AMUX_SIGNAL2ADC);
3524*4882a593Smuzhiyun 	if (status < 0)
3525*4882a593Smuzhiyun 		goto error;
3526*4882a593Smuzhiyun 	status = set_iqm_af(state, true);
3527*4882a593Smuzhiyun 	if (status < 0)
3528*4882a593Smuzhiyun 		goto error;
3529*4882a593Smuzhiyun 
3530*4882a593Smuzhiyun 	status = write16(state, IQM_AF_AGC_RF__A, 0);
3531*4882a593Smuzhiyun 	if (status < 0)
3532*4882a593Smuzhiyun 		goto error;
3533*4882a593Smuzhiyun 
3534*4882a593Smuzhiyun 	/* Impulse noise cruncher setup */
3535*4882a593Smuzhiyun 	status = write16(state, IQM_AF_INC_LCT__A, 0);	/* crunch in IQM_CF */
3536*4882a593Smuzhiyun 	if (status < 0)
3537*4882a593Smuzhiyun 		goto error;
3538*4882a593Smuzhiyun 	status = write16(state, IQM_CF_DET_LCT__A, 0);	/* detect in IQM_CF */
3539*4882a593Smuzhiyun 	if (status < 0)
3540*4882a593Smuzhiyun 		goto error;
3541*4882a593Smuzhiyun 	status = write16(state, IQM_CF_WND_LEN__A, 3);	/* peak detector window length */
3542*4882a593Smuzhiyun 	if (status < 0)
3543*4882a593Smuzhiyun 		goto error;
3544*4882a593Smuzhiyun 
3545*4882a593Smuzhiyun 	status = write16(state, IQM_RC_STRETCH__A, 16);
3546*4882a593Smuzhiyun 	if (status < 0)
3547*4882a593Smuzhiyun 		goto error;
3548*4882a593Smuzhiyun 	status = write16(state, IQM_CF_OUT_ENA__A, 0x4); /* enable output 2 */
3549*4882a593Smuzhiyun 	if (status < 0)
3550*4882a593Smuzhiyun 		goto error;
3551*4882a593Smuzhiyun 	status = write16(state, IQM_CF_DS_ENA__A, 0x4);	/* decimate output 2 */
3552*4882a593Smuzhiyun 	if (status < 0)
3553*4882a593Smuzhiyun 		goto error;
3554*4882a593Smuzhiyun 	status = write16(state, IQM_CF_SCALE__A, 1600);
3555*4882a593Smuzhiyun 	if (status < 0)
3556*4882a593Smuzhiyun 		goto error;
3557*4882a593Smuzhiyun 	status = write16(state, IQM_CF_SCALE_SH__A, 0);
3558*4882a593Smuzhiyun 	if (status < 0)
3559*4882a593Smuzhiyun 		goto error;
3560*4882a593Smuzhiyun 
3561*4882a593Smuzhiyun 	/* virtual clipping threshold for clipping ADC detection */
3562*4882a593Smuzhiyun 	status = write16(state, IQM_AF_CLP_TH__A, 448);
3563*4882a593Smuzhiyun 	if (status < 0)
3564*4882a593Smuzhiyun 		goto error;
3565*4882a593Smuzhiyun 	status = write16(state, IQM_CF_DATATH__A, 495);	/* crunching threshold */
3566*4882a593Smuzhiyun 	if (status < 0)
3567*4882a593Smuzhiyun 		goto error;
3568*4882a593Smuzhiyun 
3569*4882a593Smuzhiyun 	status = bl_chain_cmd(state, DRXK_BL_ROM_OFFSET_TAPS_DVBT,
3570*4882a593Smuzhiyun 			      DRXK_BLCC_NR_ELEMENTS_TAPS, DRXK_BLC_TIMEOUT);
3571*4882a593Smuzhiyun 	if (status < 0)
3572*4882a593Smuzhiyun 		goto error;
3573*4882a593Smuzhiyun 
3574*4882a593Smuzhiyun 	status = write16(state, IQM_CF_PKDTH__A, 2);	/* peak detector threshold */
3575*4882a593Smuzhiyun 	if (status < 0)
3576*4882a593Smuzhiyun 		goto error;
3577*4882a593Smuzhiyun 	status = write16(state, IQM_CF_POW_MEAS_LEN__A, 2);
3578*4882a593Smuzhiyun 	if (status < 0)
3579*4882a593Smuzhiyun 		goto error;
3580*4882a593Smuzhiyun 	/* enable power measurement interrupt */
3581*4882a593Smuzhiyun 	status = write16(state, IQM_CF_COMM_INT_MSK__A, 1);
3582*4882a593Smuzhiyun 	if (status < 0)
3583*4882a593Smuzhiyun 		goto error;
3584*4882a593Smuzhiyun 	status = write16(state, IQM_COMM_EXEC__A, IQM_COMM_EXEC_B_ACTIVE);
3585*4882a593Smuzhiyun 	if (status < 0)
3586*4882a593Smuzhiyun 		goto error;
3587*4882a593Smuzhiyun 
3588*4882a593Smuzhiyun 	/* IQM will not be reset from here, sync ADC and update/init AGC */
3589*4882a593Smuzhiyun 	status = adc_synchronization(state);
3590*4882a593Smuzhiyun 	if (status < 0)
3591*4882a593Smuzhiyun 		goto error;
3592*4882a593Smuzhiyun 	status = set_pre_saw(state, &state->m_dvbt_pre_saw_cfg);
3593*4882a593Smuzhiyun 	if (status < 0)
3594*4882a593Smuzhiyun 		goto error;
3595*4882a593Smuzhiyun 
3596*4882a593Smuzhiyun 	/* Halt SCU to enable safe non-atomic accesses */
3597*4882a593Smuzhiyun 	status = write16(state, SCU_COMM_EXEC__A, SCU_COMM_EXEC_HOLD);
3598*4882a593Smuzhiyun 	if (status < 0)
3599*4882a593Smuzhiyun 		goto error;
3600*4882a593Smuzhiyun 
3601*4882a593Smuzhiyun 	status = set_agc_rf(state, &state->m_dvbt_rf_agc_cfg, true);
3602*4882a593Smuzhiyun 	if (status < 0)
3603*4882a593Smuzhiyun 		goto error;
3604*4882a593Smuzhiyun 	status = set_agc_if(state, &state->m_dvbt_if_agc_cfg, true);
3605*4882a593Smuzhiyun 	if (status < 0)
3606*4882a593Smuzhiyun 		goto error;
3607*4882a593Smuzhiyun 
3608*4882a593Smuzhiyun 	/* Set Noise Estimation notch width and enable DC fix */
3609*4882a593Smuzhiyun 	status = read16(state, OFDM_SC_RA_RAM_CONFIG__A, &data);
3610*4882a593Smuzhiyun 	if (status < 0)
3611*4882a593Smuzhiyun 		goto error;
3612*4882a593Smuzhiyun 	data |= OFDM_SC_RA_RAM_CONFIG_NE_FIX_ENABLE__M;
3613*4882a593Smuzhiyun 	status = write16(state, OFDM_SC_RA_RAM_CONFIG__A, data);
3614*4882a593Smuzhiyun 	if (status < 0)
3615*4882a593Smuzhiyun 		goto error;
3616*4882a593Smuzhiyun 
3617*4882a593Smuzhiyun 	/* Activate SCU to enable SCU commands */
3618*4882a593Smuzhiyun 	status = write16(state, SCU_COMM_EXEC__A, SCU_COMM_EXEC_ACTIVE);
3619*4882a593Smuzhiyun 	if (status < 0)
3620*4882a593Smuzhiyun 		goto error;
3621*4882a593Smuzhiyun 
3622*4882a593Smuzhiyun 	if (!state->m_drxk_a3_rom_code) {
3623*4882a593Smuzhiyun 		/* AGCInit() is not done for DVBT, so set agcfast_clip_ctrl_delay  */
3624*4882a593Smuzhiyun 		status = write16(state, SCU_RAM_AGC_FAST_CLP_CTRL_DELAY__A,
3625*4882a593Smuzhiyun 				 state->m_dvbt_if_agc_cfg.fast_clip_ctrl_delay);
3626*4882a593Smuzhiyun 		if (status < 0)
3627*4882a593Smuzhiyun 			goto error;
3628*4882a593Smuzhiyun 	}
3629*4882a593Smuzhiyun 
3630*4882a593Smuzhiyun 	/* OFDM_SC setup */
3631*4882a593Smuzhiyun #ifdef COMPILE_FOR_NONRT
3632*4882a593Smuzhiyun 	status = write16(state, OFDM_SC_RA_RAM_BE_OPT_DELAY__A, 1);
3633*4882a593Smuzhiyun 	if (status < 0)
3634*4882a593Smuzhiyun 		goto error;
3635*4882a593Smuzhiyun 	status = write16(state, OFDM_SC_RA_RAM_BE_OPT_INIT_DELAY__A, 2);
3636*4882a593Smuzhiyun 	if (status < 0)
3637*4882a593Smuzhiyun 		goto error;
3638*4882a593Smuzhiyun #endif
3639*4882a593Smuzhiyun 
3640*4882a593Smuzhiyun 	/* FEC setup */
3641*4882a593Smuzhiyun 	status = write16(state, FEC_DI_INPUT_CTL__A, 1);	/* OFDM input */
3642*4882a593Smuzhiyun 	if (status < 0)
3643*4882a593Smuzhiyun 		goto error;
3644*4882a593Smuzhiyun 
3645*4882a593Smuzhiyun 
3646*4882a593Smuzhiyun #ifdef COMPILE_FOR_NONRT
3647*4882a593Smuzhiyun 	status = write16(state, FEC_RS_MEASUREMENT_PERIOD__A, 0x400);
3648*4882a593Smuzhiyun 	if (status < 0)
3649*4882a593Smuzhiyun 		goto error;
3650*4882a593Smuzhiyun #else
3651*4882a593Smuzhiyun 	status = write16(state, FEC_RS_MEASUREMENT_PERIOD__A, 0x1000);
3652*4882a593Smuzhiyun 	if (status < 0)
3653*4882a593Smuzhiyun 		goto error;
3654*4882a593Smuzhiyun #endif
3655*4882a593Smuzhiyun 	status = write16(state, FEC_RS_MEASUREMENT_PRESCALE__A, 0x0001);
3656*4882a593Smuzhiyun 	if (status < 0)
3657*4882a593Smuzhiyun 		goto error;
3658*4882a593Smuzhiyun 
3659*4882a593Smuzhiyun 	/* Setup MPEG bus */
3660*4882a593Smuzhiyun 	status = mpegts_dto_setup(state, OM_DVBT);
3661*4882a593Smuzhiyun 	if (status < 0)
3662*4882a593Smuzhiyun 		goto error;
3663*4882a593Smuzhiyun 	/* Set DVBT Presets */
3664*4882a593Smuzhiyun 	status = dvbt_activate_presets(state);
3665*4882a593Smuzhiyun 	if (status < 0)
3666*4882a593Smuzhiyun 		goto error;
3667*4882a593Smuzhiyun 
3668*4882a593Smuzhiyun error:
3669*4882a593Smuzhiyun 	if (status < 0)
3670*4882a593Smuzhiyun 		pr_err("Error %d on %s\n", status, __func__);
3671*4882a593Smuzhiyun 	return status;
3672*4882a593Smuzhiyun }
3673*4882a593Smuzhiyun 
3674*4882a593Smuzhiyun /*============================================================================*/
3675*4882a593Smuzhiyun /*
3676*4882a593Smuzhiyun * \brief start dvbt demodulating for channel.
3677*4882a593Smuzhiyun * \param demod instance of demodulator.
3678*4882a593Smuzhiyun * \return DRXStatus_t.
3679*4882a593Smuzhiyun */
dvbt_start(struct drxk_state * state)3680*4882a593Smuzhiyun static int dvbt_start(struct drxk_state *state)
3681*4882a593Smuzhiyun {
3682*4882a593Smuzhiyun 	u16 param1;
3683*4882a593Smuzhiyun 	int status;
3684*4882a593Smuzhiyun 	/* drxk_ofdm_sc_cmd_t scCmd; */
3685*4882a593Smuzhiyun 
3686*4882a593Smuzhiyun 	dprintk(1, "\n");
3687*4882a593Smuzhiyun 	/* start correct processes to get in lock */
3688*4882a593Smuzhiyun 	/* DRXK: OFDM_SC_RA_RAM_PROC_LOCKTRACK is no longer in mapfile! */
3689*4882a593Smuzhiyun 	param1 = OFDM_SC_RA_RAM_LOCKTRACK_MIN;
3690*4882a593Smuzhiyun 	status = dvbt_sc_command(state, OFDM_SC_RA_RAM_CMD_PROC_START, 0,
3691*4882a593Smuzhiyun 				 OFDM_SC_RA_RAM_SW_EVENT_RUN_NMASK__M, param1,
3692*4882a593Smuzhiyun 				 0, 0, 0);
3693*4882a593Smuzhiyun 	if (status < 0)
3694*4882a593Smuzhiyun 		goto error;
3695*4882a593Smuzhiyun 	/* start FEC OC */
3696*4882a593Smuzhiyun 	status = mpegts_start(state);
3697*4882a593Smuzhiyun 	if (status < 0)
3698*4882a593Smuzhiyun 		goto error;
3699*4882a593Smuzhiyun 	status = write16(state, FEC_COMM_EXEC__A, FEC_COMM_EXEC_ACTIVE);
3700*4882a593Smuzhiyun 	if (status < 0)
3701*4882a593Smuzhiyun 		goto error;
3702*4882a593Smuzhiyun error:
3703*4882a593Smuzhiyun 	if (status < 0)
3704*4882a593Smuzhiyun 		pr_err("Error %d on %s\n", status, __func__);
3705*4882a593Smuzhiyun 	return status;
3706*4882a593Smuzhiyun }
3707*4882a593Smuzhiyun 
3708*4882a593Smuzhiyun 
3709*4882a593Smuzhiyun /*============================================================================*/
3710*4882a593Smuzhiyun 
3711*4882a593Smuzhiyun /*
3712*4882a593Smuzhiyun * \brief Set up dvbt demodulator for channel.
3713*4882a593Smuzhiyun * \param demod instance of demodulator.
3714*4882a593Smuzhiyun * \return DRXStatus_t.
3715*4882a593Smuzhiyun * // original DVBTSetChannel()
3716*4882a593Smuzhiyun */
set_dvbt(struct drxk_state * state,u16 intermediate_freqk_hz,s32 tuner_freq_offset)3717*4882a593Smuzhiyun static int set_dvbt(struct drxk_state *state, u16 intermediate_freqk_hz,
3718*4882a593Smuzhiyun 		   s32 tuner_freq_offset)
3719*4882a593Smuzhiyun {
3720*4882a593Smuzhiyun 	u16 cmd_result = 0;
3721*4882a593Smuzhiyun 	u16 transmission_params = 0;
3722*4882a593Smuzhiyun 	u16 operation_mode = 0;
3723*4882a593Smuzhiyun 	u32 iqm_rc_rate_ofs = 0;
3724*4882a593Smuzhiyun 	u32 bandwidth = 0;
3725*4882a593Smuzhiyun 	u16 param1;
3726*4882a593Smuzhiyun 	int status;
3727*4882a593Smuzhiyun 
3728*4882a593Smuzhiyun 	dprintk(1, "IF =%d, TFO = %d\n",
3729*4882a593Smuzhiyun 		intermediate_freqk_hz, tuner_freq_offset);
3730*4882a593Smuzhiyun 
3731*4882a593Smuzhiyun 	status = scu_command(state, SCU_RAM_COMMAND_STANDARD_OFDM
3732*4882a593Smuzhiyun 			    | SCU_RAM_COMMAND_CMD_DEMOD_STOP,
3733*4882a593Smuzhiyun 			    0, NULL, 1, &cmd_result);
3734*4882a593Smuzhiyun 	if (status < 0)
3735*4882a593Smuzhiyun 		goto error;
3736*4882a593Smuzhiyun 
3737*4882a593Smuzhiyun 	/* Halt SCU to enable safe non-atomic accesses */
3738*4882a593Smuzhiyun 	status = write16(state, SCU_COMM_EXEC__A, SCU_COMM_EXEC_HOLD);
3739*4882a593Smuzhiyun 	if (status < 0)
3740*4882a593Smuzhiyun 		goto error;
3741*4882a593Smuzhiyun 
3742*4882a593Smuzhiyun 	/* Stop processors */
3743*4882a593Smuzhiyun 	status = write16(state, OFDM_SC_COMM_EXEC__A, OFDM_SC_COMM_EXEC_STOP);
3744*4882a593Smuzhiyun 	if (status < 0)
3745*4882a593Smuzhiyun 		goto error;
3746*4882a593Smuzhiyun 	status = write16(state, OFDM_LC_COMM_EXEC__A, OFDM_LC_COMM_EXEC_STOP);
3747*4882a593Smuzhiyun 	if (status < 0)
3748*4882a593Smuzhiyun 		goto error;
3749*4882a593Smuzhiyun 
3750*4882a593Smuzhiyun 	/* Mandatory fix, always stop CP, required to set spl offset back to
3751*4882a593Smuzhiyun 		hardware default (is set to 0 by ucode during pilot detection */
3752*4882a593Smuzhiyun 	status = write16(state, OFDM_CP_COMM_EXEC__A, OFDM_CP_COMM_EXEC_STOP);
3753*4882a593Smuzhiyun 	if (status < 0)
3754*4882a593Smuzhiyun 		goto error;
3755*4882a593Smuzhiyun 
3756*4882a593Smuzhiyun 	/*== Write channel settings to device ================================*/
3757*4882a593Smuzhiyun 
3758*4882a593Smuzhiyun 	/* mode */
3759*4882a593Smuzhiyun 	switch (state->props.transmission_mode) {
3760*4882a593Smuzhiyun 	case TRANSMISSION_MODE_AUTO:
3761*4882a593Smuzhiyun 	default:
3762*4882a593Smuzhiyun 		operation_mode |= OFDM_SC_RA_RAM_OP_AUTO_MODE__M;
3763*4882a593Smuzhiyun 		fallthrough;	/* try first guess DRX_FFTMODE_8K */
3764*4882a593Smuzhiyun 	case TRANSMISSION_MODE_8K:
3765*4882a593Smuzhiyun 		transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_MODE_8K;
3766*4882a593Smuzhiyun 		break;
3767*4882a593Smuzhiyun 	case TRANSMISSION_MODE_2K:
3768*4882a593Smuzhiyun 		transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_MODE_2K;
3769*4882a593Smuzhiyun 		break;
3770*4882a593Smuzhiyun 	}
3771*4882a593Smuzhiyun 
3772*4882a593Smuzhiyun 	/* guard */
3773*4882a593Smuzhiyun 	switch (state->props.guard_interval) {
3774*4882a593Smuzhiyun 	default:
3775*4882a593Smuzhiyun 	case GUARD_INTERVAL_AUTO:
3776*4882a593Smuzhiyun 		operation_mode |= OFDM_SC_RA_RAM_OP_AUTO_GUARD__M;
3777*4882a593Smuzhiyun 		fallthrough;	/* try first guess DRX_GUARD_1DIV4 */
3778*4882a593Smuzhiyun 	case GUARD_INTERVAL_1_4:
3779*4882a593Smuzhiyun 		transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_GUARD_4;
3780*4882a593Smuzhiyun 		break;
3781*4882a593Smuzhiyun 	case GUARD_INTERVAL_1_32:
3782*4882a593Smuzhiyun 		transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_GUARD_32;
3783*4882a593Smuzhiyun 		break;
3784*4882a593Smuzhiyun 	case GUARD_INTERVAL_1_16:
3785*4882a593Smuzhiyun 		transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_GUARD_16;
3786*4882a593Smuzhiyun 		break;
3787*4882a593Smuzhiyun 	case GUARD_INTERVAL_1_8:
3788*4882a593Smuzhiyun 		transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_GUARD_8;
3789*4882a593Smuzhiyun 		break;
3790*4882a593Smuzhiyun 	}
3791*4882a593Smuzhiyun 
3792*4882a593Smuzhiyun 	/* hierarchy */
3793*4882a593Smuzhiyun 	switch (state->props.hierarchy) {
3794*4882a593Smuzhiyun 	case HIERARCHY_AUTO:
3795*4882a593Smuzhiyun 	case HIERARCHY_NONE:
3796*4882a593Smuzhiyun 	default:
3797*4882a593Smuzhiyun 		operation_mode |= OFDM_SC_RA_RAM_OP_AUTO_HIER__M;
3798*4882a593Smuzhiyun 		/* try first guess SC_RA_RAM_OP_PARAM_HIER_NO */
3799*4882a593Smuzhiyun 		/* transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_HIER_NO; */
3800*4882a593Smuzhiyun 		fallthrough;
3801*4882a593Smuzhiyun 	case HIERARCHY_1:
3802*4882a593Smuzhiyun 		transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_HIER_A1;
3803*4882a593Smuzhiyun 		break;
3804*4882a593Smuzhiyun 	case HIERARCHY_2:
3805*4882a593Smuzhiyun 		transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_HIER_A2;
3806*4882a593Smuzhiyun 		break;
3807*4882a593Smuzhiyun 	case HIERARCHY_4:
3808*4882a593Smuzhiyun 		transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_HIER_A4;
3809*4882a593Smuzhiyun 		break;
3810*4882a593Smuzhiyun 	}
3811*4882a593Smuzhiyun 
3812*4882a593Smuzhiyun 
3813*4882a593Smuzhiyun 	/* modulation */
3814*4882a593Smuzhiyun 	switch (state->props.modulation) {
3815*4882a593Smuzhiyun 	case QAM_AUTO:
3816*4882a593Smuzhiyun 	default:
3817*4882a593Smuzhiyun 		operation_mode |= OFDM_SC_RA_RAM_OP_AUTO_CONST__M;
3818*4882a593Smuzhiyun 		fallthrough;	/* try first guess DRX_CONSTELLATION_QAM64 */
3819*4882a593Smuzhiyun 	case QAM_64:
3820*4882a593Smuzhiyun 		transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_CONST_QAM64;
3821*4882a593Smuzhiyun 		break;
3822*4882a593Smuzhiyun 	case QPSK:
3823*4882a593Smuzhiyun 		transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_CONST_QPSK;
3824*4882a593Smuzhiyun 		break;
3825*4882a593Smuzhiyun 	case QAM_16:
3826*4882a593Smuzhiyun 		transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_CONST_QAM16;
3827*4882a593Smuzhiyun 		break;
3828*4882a593Smuzhiyun 	}
3829*4882a593Smuzhiyun #if 0
3830*4882a593Smuzhiyun 	/* No hierarchical channels support in BDA */
3831*4882a593Smuzhiyun 	/* Priority (only for hierarchical channels) */
3832*4882a593Smuzhiyun 	switch (channel->priority) {
3833*4882a593Smuzhiyun 	case DRX_PRIORITY_LOW:
3834*4882a593Smuzhiyun 		transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_PRIO_LO;
3835*4882a593Smuzhiyun 		WR16(dev_addr, OFDM_EC_SB_PRIOR__A,
3836*4882a593Smuzhiyun 			OFDM_EC_SB_PRIOR_LO);
3837*4882a593Smuzhiyun 		break;
3838*4882a593Smuzhiyun 	case DRX_PRIORITY_HIGH:
3839*4882a593Smuzhiyun 		transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_PRIO_HI;
3840*4882a593Smuzhiyun 		WR16(dev_addr, OFDM_EC_SB_PRIOR__A,
3841*4882a593Smuzhiyun 			OFDM_EC_SB_PRIOR_HI));
3842*4882a593Smuzhiyun 		break;
3843*4882a593Smuzhiyun 	case DRX_PRIORITY_UNKNOWN:
3844*4882a593Smuzhiyun 	default:
3845*4882a593Smuzhiyun 		status = -EINVAL;
3846*4882a593Smuzhiyun 		goto error;
3847*4882a593Smuzhiyun 	}
3848*4882a593Smuzhiyun #else
3849*4882a593Smuzhiyun 	/* Set Priority high */
3850*4882a593Smuzhiyun 	transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_PRIO_HI;
3851*4882a593Smuzhiyun 	status = write16(state, OFDM_EC_SB_PRIOR__A, OFDM_EC_SB_PRIOR_HI);
3852*4882a593Smuzhiyun 	if (status < 0)
3853*4882a593Smuzhiyun 		goto error;
3854*4882a593Smuzhiyun #endif
3855*4882a593Smuzhiyun 
3856*4882a593Smuzhiyun 	/* coderate */
3857*4882a593Smuzhiyun 	switch (state->props.code_rate_HP) {
3858*4882a593Smuzhiyun 	case FEC_AUTO:
3859*4882a593Smuzhiyun 	default:
3860*4882a593Smuzhiyun 		operation_mode |= OFDM_SC_RA_RAM_OP_AUTO_RATE__M;
3861*4882a593Smuzhiyun 		fallthrough;	/* try first guess DRX_CODERATE_2DIV3 */
3862*4882a593Smuzhiyun 	case FEC_2_3:
3863*4882a593Smuzhiyun 		transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_RATE_2_3;
3864*4882a593Smuzhiyun 		break;
3865*4882a593Smuzhiyun 	case FEC_1_2:
3866*4882a593Smuzhiyun 		transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_RATE_1_2;
3867*4882a593Smuzhiyun 		break;
3868*4882a593Smuzhiyun 	case FEC_3_4:
3869*4882a593Smuzhiyun 		transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_RATE_3_4;
3870*4882a593Smuzhiyun 		break;
3871*4882a593Smuzhiyun 	case FEC_5_6:
3872*4882a593Smuzhiyun 		transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_RATE_5_6;
3873*4882a593Smuzhiyun 		break;
3874*4882a593Smuzhiyun 	case FEC_7_8:
3875*4882a593Smuzhiyun 		transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_RATE_7_8;
3876*4882a593Smuzhiyun 		break;
3877*4882a593Smuzhiyun 	}
3878*4882a593Smuzhiyun 
3879*4882a593Smuzhiyun 	/*
3880*4882a593Smuzhiyun 	 * SAW filter selection: normally not necessary, but if wanted
3881*4882a593Smuzhiyun 	 * the application can select a SAW filter via the driver by
3882*4882a593Smuzhiyun 	 * using UIOs
3883*4882a593Smuzhiyun 	 */
3884*4882a593Smuzhiyun 
3885*4882a593Smuzhiyun 	/* First determine real bandwidth (Hz) */
3886*4882a593Smuzhiyun 	/* Also set delay for impulse noise cruncher */
3887*4882a593Smuzhiyun 	/*
3888*4882a593Smuzhiyun 	 * Also set parameters for EC_OC fix, note EC_OC_REG_TMD_HIL_MAR is
3889*4882a593Smuzhiyun 	 * changed by SC for fix for some 8K,1/8 guard but is restored by
3890*4882a593Smuzhiyun 	 * InitEC and ResetEC functions
3891*4882a593Smuzhiyun 	 */
3892*4882a593Smuzhiyun 	switch (state->props.bandwidth_hz) {
3893*4882a593Smuzhiyun 	case 0:
3894*4882a593Smuzhiyun 		state->props.bandwidth_hz = 8000000;
3895*4882a593Smuzhiyun 		fallthrough;
3896*4882a593Smuzhiyun 	case 8000000:
3897*4882a593Smuzhiyun 		bandwidth = DRXK_BANDWIDTH_8MHZ_IN_HZ;
3898*4882a593Smuzhiyun 		status = write16(state, OFDM_SC_RA_RAM_SRMM_FIX_FACT_8K__A,
3899*4882a593Smuzhiyun 				 3052);
3900*4882a593Smuzhiyun 		if (status < 0)
3901*4882a593Smuzhiyun 			goto error;
3902*4882a593Smuzhiyun 		/* cochannel protection for PAL 8 MHz */
3903*4882a593Smuzhiyun 		status = write16(state, OFDM_SC_RA_RAM_NI_INIT_8K_PER_LEFT__A,
3904*4882a593Smuzhiyun 				 7);
3905*4882a593Smuzhiyun 		if (status < 0)
3906*4882a593Smuzhiyun 			goto error;
3907*4882a593Smuzhiyun 		status = write16(state, OFDM_SC_RA_RAM_NI_INIT_8K_PER_RIGHT__A,
3908*4882a593Smuzhiyun 				 7);
3909*4882a593Smuzhiyun 		if (status < 0)
3910*4882a593Smuzhiyun 			goto error;
3911*4882a593Smuzhiyun 		status = write16(state, OFDM_SC_RA_RAM_NI_INIT_2K_PER_LEFT__A,
3912*4882a593Smuzhiyun 				 7);
3913*4882a593Smuzhiyun 		if (status < 0)
3914*4882a593Smuzhiyun 			goto error;
3915*4882a593Smuzhiyun 		status = write16(state, OFDM_SC_RA_RAM_NI_INIT_2K_PER_RIGHT__A,
3916*4882a593Smuzhiyun 				 1);
3917*4882a593Smuzhiyun 		if (status < 0)
3918*4882a593Smuzhiyun 			goto error;
3919*4882a593Smuzhiyun 		break;
3920*4882a593Smuzhiyun 	case 7000000:
3921*4882a593Smuzhiyun 		bandwidth = DRXK_BANDWIDTH_7MHZ_IN_HZ;
3922*4882a593Smuzhiyun 		status = write16(state, OFDM_SC_RA_RAM_SRMM_FIX_FACT_8K__A,
3923*4882a593Smuzhiyun 				 3491);
3924*4882a593Smuzhiyun 		if (status < 0)
3925*4882a593Smuzhiyun 			goto error;
3926*4882a593Smuzhiyun 		/* cochannel protection for PAL 7 MHz */
3927*4882a593Smuzhiyun 		status = write16(state, OFDM_SC_RA_RAM_NI_INIT_8K_PER_LEFT__A,
3928*4882a593Smuzhiyun 				 8);
3929*4882a593Smuzhiyun 		if (status < 0)
3930*4882a593Smuzhiyun 			goto error;
3931*4882a593Smuzhiyun 		status = write16(state, OFDM_SC_RA_RAM_NI_INIT_8K_PER_RIGHT__A,
3932*4882a593Smuzhiyun 				 8);
3933*4882a593Smuzhiyun 		if (status < 0)
3934*4882a593Smuzhiyun 			goto error;
3935*4882a593Smuzhiyun 		status = write16(state, OFDM_SC_RA_RAM_NI_INIT_2K_PER_LEFT__A,
3936*4882a593Smuzhiyun 				 4);
3937*4882a593Smuzhiyun 		if (status < 0)
3938*4882a593Smuzhiyun 			goto error;
3939*4882a593Smuzhiyun 		status = write16(state, OFDM_SC_RA_RAM_NI_INIT_2K_PER_RIGHT__A,
3940*4882a593Smuzhiyun 				 1);
3941*4882a593Smuzhiyun 		if (status < 0)
3942*4882a593Smuzhiyun 			goto error;
3943*4882a593Smuzhiyun 		break;
3944*4882a593Smuzhiyun 	case 6000000:
3945*4882a593Smuzhiyun 		bandwidth = DRXK_BANDWIDTH_6MHZ_IN_HZ;
3946*4882a593Smuzhiyun 		status = write16(state, OFDM_SC_RA_RAM_SRMM_FIX_FACT_8K__A,
3947*4882a593Smuzhiyun 				 4073);
3948*4882a593Smuzhiyun 		if (status < 0)
3949*4882a593Smuzhiyun 			goto error;
3950*4882a593Smuzhiyun 		/* cochannel protection for NTSC 6 MHz */
3951*4882a593Smuzhiyun 		status = write16(state, OFDM_SC_RA_RAM_NI_INIT_8K_PER_LEFT__A,
3952*4882a593Smuzhiyun 				 19);
3953*4882a593Smuzhiyun 		if (status < 0)
3954*4882a593Smuzhiyun 			goto error;
3955*4882a593Smuzhiyun 		status = write16(state, OFDM_SC_RA_RAM_NI_INIT_8K_PER_RIGHT__A,
3956*4882a593Smuzhiyun 				 19);
3957*4882a593Smuzhiyun 		if (status < 0)
3958*4882a593Smuzhiyun 			goto error;
3959*4882a593Smuzhiyun 		status = write16(state, OFDM_SC_RA_RAM_NI_INIT_2K_PER_LEFT__A,
3960*4882a593Smuzhiyun 				 14);
3961*4882a593Smuzhiyun 		if (status < 0)
3962*4882a593Smuzhiyun 			goto error;
3963*4882a593Smuzhiyun 		status = write16(state, OFDM_SC_RA_RAM_NI_INIT_2K_PER_RIGHT__A,
3964*4882a593Smuzhiyun 				 1);
3965*4882a593Smuzhiyun 		if (status < 0)
3966*4882a593Smuzhiyun 			goto error;
3967*4882a593Smuzhiyun 		break;
3968*4882a593Smuzhiyun 	default:
3969*4882a593Smuzhiyun 		status = -EINVAL;
3970*4882a593Smuzhiyun 		goto error;
3971*4882a593Smuzhiyun 	}
3972*4882a593Smuzhiyun 
3973*4882a593Smuzhiyun 	if (iqm_rc_rate_ofs == 0) {
3974*4882a593Smuzhiyun 		/* Now compute IQM_RC_RATE_OFS
3975*4882a593Smuzhiyun 			(((SysFreq/BandWidth)/2)/2) -1) * 2^23)
3976*4882a593Smuzhiyun 			=>
3977*4882a593Smuzhiyun 			((SysFreq / BandWidth) * (2^21)) - (2^23)
3978*4882a593Smuzhiyun 			*/
3979*4882a593Smuzhiyun 		/* (SysFreq / BandWidth) * (2^28)  */
3980*4882a593Smuzhiyun 		/*
3981*4882a593Smuzhiyun 		 * assert (MAX(sysClk)/MIN(bandwidth) < 16)
3982*4882a593Smuzhiyun 		 *	=> assert(MAX(sysClk) < 16*MIN(bandwidth))
3983*4882a593Smuzhiyun 		 *	=> assert(109714272 > 48000000) = true
3984*4882a593Smuzhiyun 		 * so Frac 28 can be used
3985*4882a593Smuzhiyun 		 */
3986*4882a593Smuzhiyun 		iqm_rc_rate_ofs = Frac28a((u32)
3987*4882a593Smuzhiyun 					((state->m_sys_clock_freq *
3988*4882a593Smuzhiyun 						1000) / 3), bandwidth);
3989*4882a593Smuzhiyun 		/* (SysFreq / BandWidth) * (2^21), rounding before truncating */
3990*4882a593Smuzhiyun 		if ((iqm_rc_rate_ofs & 0x7fL) >= 0x40)
3991*4882a593Smuzhiyun 			iqm_rc_rate_ofs += 0x80L;
3992*4882a593Smuzhiyun 		iqm_rc_rate_ofs = iqm_rc_rate_ofs >> 7;
3993*4882a593Smuzhiyun 		/* ((SysFreq / BandWidth) * (2^21)) - (2^23)  */
3994*4882a593Smuzhiyun 		iqm_rc_rate_ofs = iqm_rc_rate_ofs - (1 << 23);
3995*4882a593Smuzhiyun 	}
3996*4882a593Smuzhiyun 
3997*4882a593Smuzhiyun 	iqm_rc_rate_ofs &=
3998*4882a593Smuzhiyun 		((((u32) IQM_RC_RATE_OFS_HI__M) <<
3999*4882a593Smuzhiyun 		IQM_RC_RATE_OFS_LO__W) | IQM_RC_RATE_OFS_LO__M);
4000*4882a593Smuzhiyun 	status = write32(state, IQM_RC_RATE_OFS_LO__A, iqm_rc_rate_ofs);
4001*4882a593Smuzhiyun 	if (status < 0)
4002*4882a593Smuzhiyun 		goto error;
4003*4882a593Smuzhiyun 
4004*4882a593Smuzhiyun 	/* Bandwidth setting done */
4005*4882a593Smuzhiyun 
4006*4882a593Smuzhiyun #if 0
4007*4882a593Smuzhiyun 	status = dvbt_set_frequency_shift(demod, channel, tuner_offset);
4008*4882a593Smuzhiyun 	if (status < 0)
4009*4882a593Smuzhiyun 		goto error;
4010*4882a593Smuzhiyun #endif
4011*4882a593Smuzhiyun 	status = set_frequency_shifter(state, intermediate_freqk_hz,
4012*4882a593Smuzhiyun 				       tuner_freq_offset, true);
4013*4882a593Smuzhiyun 	if (status < 0)
4014*4882a593Smuzhiyun 		goto error;
4015*4882a593Smuzhiyun 
4016*4882a593Smuzhiyun 	/*== start SC, write channel settings to SC ==========================*/
4017*4882a593Smuzhiyun 
4018*4882a593Smuzhiyun 	/* Activate SCU to enable SCU commands */
4019*4882a593Smuzhiyun 	status = write16(state, SCU_COMM_EXEC__A, SCU_COMM_EXEC_ACTIVE);
4020*4882a593Smuzhiyun 	if (status < 0)
4021*4882a593Smuzhiyun 		goto error;
4022*4882a593Smuzhiyun 
4023*4882a593Smuzhiyun 	/* Enable SC after setting all other parameters */
4024*4882a593Smuzhiyun 	status = write16(state, OFDM_SC_COMM_STATE__A, 0);
4025*4882a593Smuzhiyun 	if (status < 0)
4026*4882a593Smuzhiyun 		goto error;
4027*4882a593Smuzhiyun 	status = write16(state, OFDM_SC_COMM_EXEC__A, 1);
4028*4882a593Smuzhiyun 	if (status < 0)
4029*4882a593Smuzhiyun 		goto error;
4030*4882a593Smuzhiyun 
4031*4882a593Smuzhiyun 
4032*4882a593Smuzhiyun 	status = scu_command(state, SCU_RAM_COMMAND_STANDARD_OFDM
4033*4882a593Smuzhiyun 			     | SCU_RAM_COMMAND_CMD_DEMOD_START,
4034*4882a593Smuzhiyun 			     0, NULL, 1, &cmd_result);
4035*4882a593Smuzhiyun 	if (status < 0)
4036*4882a593Smuzhiyun 		goto error;
4037*4882a593Smuzhiyun 
4038*4882a593Smuzhiyun 	/* Write SC parameter registers, set all AUTO flags in operation mode */
4039*4882a593Smuzhiyun 	param1 = (OFDM_SC_RA_RAM_OP_AUTO_MODE__M |
4040*4882a593Smuzhiyun 			OFDM_SC_RA_RAM_OP_AUTO_GUARD__M |
4041*4882a593Smuzhiyun 			OFDM_SC_RA_RAM_OP_AUTO_CONST__M |
4042*4882a593Smuzhiyun 			OFDM_SC_RA_RAM_OP_AUTO_HIER__M |
4043*4882a593Smuzhiyun 			OFDM_SC_RA_RAM_OP_AUTO_RATE__M);
4044*4882a593Smuzhiyun 	status = dvbt_sc_command(state, OFDM_SC_RA_RAM_CMD_SET_PREF_PARAM,
4045*4882a593Smuzhiyun 				0, transmission_params, param1, 0, 0, 0);
4046*4882a593Smuzhiyun 	if (status < 0)
4047*4882a593Smuzhiyun 		goto error;
4048*4882a593Smuzhiyun 
4049*4882a593Smuzhiyun 	if (!state->m_drxk_a3_rom_code)
4050*4882a593Smuzhiyun 		status = dvbt_ctrl_set_sqi_speed(state, &state->m_sqi_speed);
4051*4882a593Smuzhiyun error:
4052*4882a593Smuzhiyun 	if (status < 0)
4053*4882a593Smuzhiyun 		pr_err("Error %d on %s\n", status, __func__);
4054*4882a593Smuzhiyun 
4055*4882a593Smuzhiyun 	return status;
4056*4882a593Smuzhiyun }
4057*4882a593Smuzhiyun 
4058*4882a593Smuzhiyun 
4059*4882a593Smuzhiyun /*============================================================================*/
4060*4882a593Smuzhiyun 
4061*4882a593Smuzhiyun /*
4062*4882a593Smuzhiyun * \brief Retrieve lock status .
4063*4882a593Smuzhiyun * \param demod    Pointer to demodulator instance.
4064*4882a593Smuzhiyun * \param lockStat Pointer to lock status structure.
4065*4882a593Smuzhiyun * \return DRXStatus_t.
4066*4882a593Smuzhiyun *
4067*4882a593Smuzhiyun */
get_dvbt_lock_status(struct drxk_state * state,u32 * p_lock_status)4068*4882a593Smuzhiyun static int get_dvbt_lock_status(struct drxk_state *state, u32 *p_lock_status)
4069*4882a593Smuzhiyun {
4070*4882a593Smuzhiyun 	int status;
4071*4882a593Smuzhiyun 	const u16 mpeg_lock_mask = (OFDM_SC_RA_RAM_LOCK_MPEG__M |
4072*4882a593Smuzhiyun 				    OFDM_SC_RA_RAM_LOCK_FEC__M);
4073*4882a593Smuzhiyun 	const u16 fec_lock_mask = (OFDM_SC_RA_RAM_LOCK_FEC__M);
4074*4882a593Smuzhiyun 	const u16 demod_lock_mask = OFDM_SC_RA_RAM_LOCK_DEMOD__M;
4075*4882a593Smuzhiyun 
4076*4882a593Smuzhiyun 	u16 sc_ra_ram_lock = 0;
4077*4882a593Smuzhiyun 	u16 sc_comm_exec = 0;
4078*4882a593Smuzhiyun 
4079*4882a593Smuzhiyun 	dprintk(1, "\n");
4080*4882a593Smuzhiyun 
4081*4882a593Smuzhiyun 	*p_lock_status = NOT_LOCKED;
4082*4882a593Smuzhiyun 	/* driver 0.9.0 */
4083*4882a593Smuzhiyun 	/* Check if SC is running */
4084*4882a593Smuzhiyun 	status = read16(state, OFDM_SC_COMM_EXEC__A, &sc_comm_exec);
4085*4882a593Smuzhiyun 	if (status < 0)
4086*4882a593Smuzhiyun 		goto end;
4087*4882a593Smuzhiyun 	if (sc_comm_exec == OFDM_SC_COMM_EXEC_STOP)
4088*4882a593Smuzhiyun 		goto end;
4089*4882a593Smuzhiyun 
4090*4882a593Smuzhiyun 	status = read16(state, OFDM_SC_RA_RAM_LOCK__A, &sc_ra_ram_lock);
4091*4882a593Smuzhiyun 	if (status < 0)
4092*4882a593Smuzhiyun 		goto end;
4093*4882a593Smuzhiyun 
4094*4882a593Smuzhiyun 	if ((sc_ra_ram_lock & mpeg_lock_mask) == mpeg_lock_mask)
4095*4882a593Smuzhiyun 		*p_lock_status = MPEG_LOCK;
4096*4882a593Smuzhiyun 	else if ((sc_ra_ram_lock & fec_lock_mask) == fec_lock_mask)
4097*4882a593Smuzhiyun 		*p_lock_status = FEC_LOCK;
4098*4882a593Smuzhiyun 	else if ((sc_ra_ram_lock & demod_lock_mask) == demod_lock_mask)
4099*4882a593Smuzhiyun 		*p_lock_status = DEMOD_LOCK;
4100*4882a593Smuzhiyun 	else if (sc_ra_ram_lock & OFDM_SC_RA_RAM_LOCK_NODVBT__M)
4101*4882a593Smuzhiyun 		*p_lock_status = NEVER_LOCK;
4102*4882a593Smuzhiyun end:
4103*4882a593Smuzhiyun 	if (status < 0)
4104*4882a593Smuzhiyun 		pr_err("Error %d on %s\n", status, __func__);
4105*4882a593Smuzhiyun 
4106*4882a593Smuzhiyun 	return status;
4107*4882a593Smuzhiyun }
4108*4882a593Smuzhiyun 
power_up_qam(struct drxk_state * state)4109*4882a593Smuzhiyun static int power_up_qam(struct drxk_state *state)
4110*4882a593Smuzhiyun {
4111*4882a593Smuzhiyun 	enum drx_power_mode power_mode = DRXK_POWER_DOWN_OFDM;
4112*4882a593Smuzhiyun 	int status;
4113*4882a593Smuzhiyun 
4114*4882a593Smuzhiyun 	dprintk(1, "\n");
4115*4882a593Smuzhiyun 	status = ctrl_power_mode(state, &power_mode);
4116*4882a593Smuzhiyun 	if (status < 0)
4117*4882a593Smuzhiyun 		pr_err("Error %d on %s\n", status, __func__);
4118*4882a593Smuzhiyun 
4119*4882a593Smuzhiyun 	return status;
4120*4882a593Smuzhiyun }
4121*4882a593Smuzhiyun 
4122*4882a593Smuzhiyun 
4123*4882a593Smuzhiyun /* Power Down QAM */
power_down_qam(struct drxk_state * state)4124*4882a593Smuzhiyun static int power_down_qam(struct drxk_state *state)
4125*4882a593Smuzhiyun {
4126*4882a593Smuzhiyun 	u16 data = 0;
4127*4882a593Smuzhiyun 	u16 cmd_result;
4128*4882a593Smuzhiyun 	int status = 0;
4129*4882a593Smuzhiyun 
4130*4882a593Smuzhiyun 	dprintk(1, "\n");
4131*4882a593Smuzhiyun 	status = read16(state, SCU_COMM_EXEC__A, &data);
4132*4882a593Smuzhiyun 	if (status < 0)
4133*4882a593Smuzhiyun 		goto error;
4134*4882a593Smuzhiyun 	if (data == SCU_COMM_EXEC_ACTIVE) {
4135*4882a593Smuzhiyun 		/*
4136*4882a593Smuzhiyun 			STOP demodulator
4137*4882a593Smuzhiyun 			QAM and HW blocks
4138*4882a593Smuzhiyun 			*/
4139*4882a593Smuzhiyun 		/* stop all comstate->m_exec */
4140*4882a593Smuzhiyun 		status = write16(state, QAM_COMM_EXEC__A, QAM_COMM_EXEC_STOP);
4141*4882a593Smuzhiyun 		if (status < 0)
4142*4882a593Smuzhiyun 			goto error;
4143*4882a593Smuzhiyun 		status = scu_command(state, SCU_RAM_COMMAND_STANDARD_QAM
4144*4882a593Smuzhiyun 				     | SCU_RAM_COMMAND_CMD_DEMOD_STOP,
4145*4882a593Smuzhiyun 				     0, NULL, 1, &cmd_result);
4146*4882a593Smuzhiyun 		if (status < 0)
4147*4882a593Smuzhiyun 			goto error;
4148*4882a593Smuzhiyun 	}
4149*4882a593Smuzhiyun 	/* powerdown AFE                   */
4150*4882a593Smuzhiyun 	status = set_iqm_af(state, false);
4151*4882a593Smuzhiyun 
4152*4882a593Smuzhiyun error:
4153*4882a593Smuzhiyun 	if (status < 0)
4154*4882a593Smuzhiyun 		pr_err("Error %d on %s\n", status, __func__);
4155*4882a593Smuzhiyun 
4156*4882a593Smuzhiyun 	return status;
4157*4882a593Smuzhiyun }
4158*4882a593Smuzhiyun 
4159*4882a593Smuzhiyun /*============================================================================*/
4160*4882a593Smuzhiyun 
4161*4882a593Smuzhiyun /*
4162*4882a593Smuzhiyun * \brief Setup of the QAM Measurement intervals for signal quality
4163*4882a593Smuzhiyun * \param demod instance of demod.
4164*4882a593Smuzhiyun * \param modulation current modulation.
4165*4882a593Smuzhiyun * \return DRXStatus_t.
4166*4882a593Smuzhiyun *
4167*4882a593Smuzhiyun *  NOTE:
4168*4882a593Smuzhiyun *  Take into account that for certain settings the errorcounters can overflow.
4169*4882a593Smuzhiyun *  The implementation does not check this.
4170*4882a593Smuzhiyun *
4171*4882a593Smuzhiyun */
set_qam_measurement(struct drxk_state * state,enum e_drxk_constellation modulation,u32 symbol_rate)4172*4882a593Smuzhiyun static int set_qam_measurement(struct drxk_state *state,
4173*4882a593Smuzhiyun 			     enum e_drxk_constellation modulation,
4174*4882a593Smuzhiyun 			     u32 symbol_rate)
4175*4882a593Smuzhiyun {
4176*4882a593Smuzhiyun 	u32 fec_bits_desired = 0;	/* BER accounting period */
4177*4882a593Smuzhiyun 	u32 fec_rs_period_total = 0;	/* Total period */
4178*4882a593Smuzhiyun 	u16 fec_rs_prescale = 0;	/* ReedSolomon Measurement Prescale */
4179*4882a593Smuzhiyun 	u16 fec_rs_period = 0;	/* Value for corresponding I2C register */
4180*4882a593Smuzhiyun 	int status = 0;
4181*4882a593Smuzhiyun 
4182*4882a593Smuzhiyun 	dprintk(1, "\n");
4183*4882a593Smuzhiyun 
4184*4882a593Smuzhiyun 	fec_rs_prescale = 1;
4185*4882a593Smuzhiyun 	/* fec_bits_desired = symbol_rate [kHz] *
4186*4882a593Smuzhiyun 		FrameLenght [ms] *
4187*4882a593Smuzhiyun 		(modulation + 1) *
4188*4882a593Smuzhiyun 		SyncLoss (== 1) *
4189*4882a593Smuzhiyun 		ViterbiLoss (==1)
4190*4882a593Smuzhiyun 		*/
4191*4882a593Smuzhiyun 	switch (modulation) {
4192*4882a593Smuzhiyun 	case DRX_CONSTELLATION_QAM16:
4193*4882a593Smuzhiyun 		fec_bits_desired = 4 * symbol_rate;
4194*4882a593Smuzhiyun 		break;
4195*4882a593Smuzhiyun 	case DRX_CONSTELLATION_QAM32:
4196*4882a593Smuzhiyun 		fec_bits_desired = 5 * symbol_rate;
4197*4882a593Smuzhiyun 		break;
4198*4882a593Smuzhiyun 	case DRX_CONSTELLATION_QAM64:
4199*4882a593Smuzhiyun 		fec_bits_desired = 6 * symbol_rate;
4200*4882a593Smuzhiyun 		break;
4201*4882a593Smuzhiyun 	case DRX_CONSTELLATION_QAM128:
4202*4882a593Smuzhiyun 		fec_bits_desired = 7 * symbol_rate;
4203*4882a593Smuzhiyun 		break;
4204*4882a593Smuzhiyun 	case DRX_CONSTELLATION_QAM256:
4205*4882a593Smuzhiyun 		fec_bits_desired = 8 * symbol_rate;
4206*4882a593Smuzhiyun 		break;
4207*4882a593Smuzhiyun 	default:
4208*4882a593Smuzhiyun 		status = -EINVAL;
4209*4882a593Smuzhiyun 	}
4210*4882a593Smuzhiyun 	if (status < 0)
4211*4882a593Smuzhiyun 		goto error;
4212*4882a593Smuzhiyun 
4213*4882a593Smuzhiyun 	fec_bits_desired /= 1000;	/* symbol_rate [Hz] -> symbol_rate [kHz] */
4214*4882a593Smuzhiyun 	fec_bits_desired *= 500;	/* meas. period [ms] */
4215*4882a593Smuzhiyun 
4216*4882a593Smuzhiyun 	/* Annex A/C: bits/RsPeriod = 204 * 8 = 1632 */
4217*4882a593Smuzhiyun 	/* fec_rs_period_total = fec_bits_desired / 1632 */
4218*4882a593Smuzhiyun 	fec_rs_period_total = (fec_bits_desired / 1632UL) + 1;	/* roughly ceil */
4219*4882a593Smuzhiyun 
4220*4882a593Smuzhiyun 	/* fec_rs_period_total =  fec_rs_prescale * fec_rs_period  */
4221*4882a593Smuzhiyun 	fec_rs_prescale = 1 + (u16) (fec_rs_period_total >> 16);
4222*4882a593Smuzhiyun 	if (fec_rs_prescale == 0) {
4223*4882a593Smuzhiyun 		/* Divide by zero (though impossible) */
4224*4882a593Smuzhiyun 		status = -EINVAL;
4225*4882a593Smuzhiyun 		if (status < 0)
4226*4882a593Smuzhiyun 			goto error;
4227*4882a593Smuzhiyun 	}
4228*4882a593Smuzhiyun 	fec_rs_period =
4229*4882a593Smuzhiyun 		((u16) fec_rs_period_total +
4230*4882a593Smuzhiyun 		(fec_rs_prescale >> 1)) / fec_rs_prescale;
4231*4882a593Smuzhiyun 
4232*4882a593Smuzhiyun 	/* write corresponding registers */
4233*4882a593Smuzhiyun 	status = write16(state, FEC_RS_MEASUREMENT_PERIOD__A, fec_rs_period);
4234*4882a593Smuzhiyun 	if (status < 0)
4235*4882a593Smuzhiyun 		goto error;
4236*4882a593Smuzhiyun 	status = write16(state, FEC_RS_MEASUREMENT_PRESCALE__A,
4237*4882a593Smuzhiyun 			 fec_rs_prescale);
4238*4882a593Smuzhiyun 	if (status < 0)
4239*4882a593Smuzhiyun 		goto error;
4240*4882a593Smuzhiyun 	status = write16(state, FEC_OC_SNC_FAIL_PERIOD__A, fec_rs_period);
4241*4882a593Smuzhiyun error:
4242*4882a593Smuzhiyun 	if (status < 0)
4243*4882a593Smuzhiyun 		pr_err("Error %d on %s\n", status, __func__);
4244*4882a593Smuzhiyun 	return status;
4245*4882a593Smuzhiyun }
4246*4882a593Smuzhiyun 
set_qam16(struct drxk_state * state)4247*4882a593Smuzhiyun static int set_qam16(struct drxk_state *state)
4248*4882a593Smuzhiyun {
4249*4882a593Smuzhiyun 	int status = 0;
4250*4882a593Smuzhiyun 
4251*4882a593Smuzhiyun 	dprintk(1, "\n");
4252*4882a593Smuzhiyun 	/* QAM Equalizer Setup */
4253*4882a593Smuzhiyun 	/* Equalizer */
4254*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD0__A, 13517);
4255*4882a593Smuzhiyun 	if (status < 0)
4256*4882a593Smuzhiyun 		goto error;
4257*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD1__A, 13517);
4258*4882a593Smuzhiyun 	if (status < 0)
4259*4882a593Smuzhiyun 		goto error;
4260*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD2__A, 13517);
4261*4882a593Smuzhiyun 	if (status < 0)
4262*4882a593Smuzhiyun 		goto error;
4263*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD3__A, 13517);
4264*4882a593Smuzhiyun 	if (status < 0)
4265*4882a593Smuzhiyun 		goto error;
4266*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD4__A, 13517);
4267*4882a593Smuzhiyun 	if (status < 0)
4268*4882a593Smuzhiyun 		goto error;
4269*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD5__A, 13517);
4270*4882a593Smuzhiyun 	if (status < 0)
4271*4882a593Smuzhiyun 		goto error;
4272*4882a593Smuzhiyun 	/* Decision Feedback Equalizer */
4273*4882a593Smuzhiyun 	status = write16(state, QAM_DQ_QUAL_FUN0__A, 2);
4274*4882a593Smuzhiyun 	if (status < 0)
4275*4882a593Smuzhiyun 		goto error;
4276*4882a593Smuzhiyun 	status = write16(state, QAM_DQ_QUAL_FUN1__A, 2);
4277*4882a593Smuzhiyun 	if (status < 0)
4278*4882a593Smuzhiyun 		goto error;
4279*4882a593Smuzhiyun 	status = write16(state, QAM_DQ_QUAL_FUN2__A, 2);
4280*4882a593Smuzhiyun 	if (status < 0)
4281*4882a593Smuzhiyun 		goto error;
4282*4882a593Smuzhiyun 	status = write16(state, QAM_DQ_QUAL_FUN3__A, 2);
4283*4882a593Smuzhiyun 	if (status < 0)
4284*4882a593Smuzhiyun 		goto error;
4285*4882a593Smuzhiyun 	status = write16(state, QAM_DQ_QUAL_FUN4__A, 2);
4286*4882a593Smuzhiyun 	if (status < 0)
4287*4882a593Smuzhiyun 		goto error;
4288*4882a593Smuzhiyun 	status = write16(state, QAM_DQ_QUAL_FUN5__A, 0);
4289*4882a593Smuzhiyun 	if (status < 0)
4290*4882a593Smuzhiyun 		goto error;
4291*4882a593Smuzhiyun 
4292*4882a593Smuzhiyun 	status = write16(state, QAM_SY_SYNC_HWM__A, 5);
4293*4882a593Smuzhiyun 	if (status < 0)
4294*4882a593Smuzhiyun 		goto error;
4295*4882a593Smuzhiyun 	status = write16(state, QAM_SY_SYNC_AWM__A, 4);
4296*4882a593Smuzhiyun 	if (status < 0)
4297*4882a593Smuzhiyun 		goto error;
4298*4882a593Smuzhiyun 	status = write16(state, QAM_SY_SYNC_LWM__A, 3);
4299*4882a593Smuzhiyun 	if (status < 0)
4300*4882a593Smuzhiyun 		goto error;
4301*4882a593Smuzhiyun 
4302*4882a593Smuzhiyun 	/* QAM Slicer Settings */
4303*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_SL_SIG_POWER__A,
4304*4882a593Smuzhiyun 			 DRXK_QAM_SL_SIG_POWER_QAM16);
4305*4882a593Smuzhiyun 	if (status < 0)
4306*4882a593Smuzhiyun 		goto error;
4307*4882a593Smuzhiyun 
4308*4882a593Smuzhiyun 	/* QAM Loop Controller Coeficients */
4309*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_CA_FINE__A, 15);
4310*4882a593Smuzhiyun 	if (status < 0)
4311*4882a593Smuzhiyun 		goto error;
4312*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_CA_COARSE__A, 40);
4313*4882a593Smuzhiyun 	if (status < 0)
4314*4882a593Smuzhiyun 		goto error;
4315*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_EP_FINE__A, 12);
4316*4882a593Smuzhiyun 	if (status < 0)
4317*4882a593Smuzhiyun 		goto error;
4318*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_EP_MEDIUM__A, 24);
4319*4882a593Smuzhiyun 	if (status < 0)
4320*4882a593Smuzhiyun 		goto error;
4321*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_EP_COARSE__A, 24);
4322*4882a593Smuzhiyun 	if (status < 0)
4323*4882a593Smuzhiyun 		goto error;
4324*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_EI_FINE__A, 12);
4325*4882a593Smuzhiyun 	if (status < 0)
4326*4882a593Smuzhiyun 		goto error;
4327*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_EI_MEDIUM__A, 16);
4328*4882a593Smuzhiyun 	if (status < 0)
4329*4882a593Smuzhiyun 		goto error;
4330*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_EI_COARSE__A, 16);
4331*4882a593Smuzhiyun 	if (status < 0)
4332*4882a593Smuzhiyun 		goto error;
4333*4882a593Smuzhiyun 
4334*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_CP_FINE__A, 5);
4335*4882a593Smuzhiyun 	if (status < 0)
4336*4882a593Smuzhiyun 		goto error;
4337*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_CP_MEDIUM__A, 20);
4338*4882a593Smuzhiyun 	if (status < 0)
4339*4882a593Smuzhiyun 		goto error;
4340*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_CP_COARSE__A, 80);
4341*4882a593Smuzhiyun 	if (status < 0)
4342*4882a593Smuzhiyun 		goto error;
4343*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_CI_FINE__A, 5);
4344*4882a593Smuzhiyun 	if (status < 0)
4345*4882a593Smuzhiyun 		goto error;
4346*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_CI_MEDIUM__A, 20);
4347*4882a593Smuzhiyun 	if (status < 0)
4348*4882a593Smuzhiyun 		goto error;
4349*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_CI_COARSE__A, 50);
4350*4882a593Smuzhiyun 	if (status < 0)
4351*4882a593Smuzhiyun 		goto error;
4352*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_CF_FINE__A, 16);
4353*4882a593Smuzhiyun 	if (status < 0)
4354*4882a593Smuzhiyun 		goto error;
4355*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_CF_MEDIUM__A, 16);
4356*4882a593Smuzhiyun 	if (status < 0)
4357*4882a593Smuzhiyun 		goto error;
4358*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_CF_COARSE__A, 32);
4359*4882a593Smuzhiyun 	if (status < 0)
4360*4882a593Smuzhiyun 		goto error;
4361*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_CF1_FINE__A, 5);
4362*4882a593Smuzhiyun 	if (status < 0)
4363*4882a593Smuzhiyun 		goto error;
4364*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_CF1_MEDIUM__A, 10);
4365*4882a593Smuzhiyun 	if (status < 0)
4366*4882a593Smuzhiyun 		goto error;
4367*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_CF1_COARSE__A, 10);
4368*4882a593Smuzhiyun 	if (status < 0)
4369*4882a593Smuzhiyun 		goto error;
4370*4882a593Smuzhiyun 
4371*4882a593Smuzhiyun 
4372*4882a593Smuzhiyun 	/* QAM State Machine (FSM) Thresholds */
4373*4882a593Smuzhiyun 
4374*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_FSM_RTH__A, 140);
4375*4882a593Smuzhiyun 	if (status < 0)
4376*4882a593Smuzhiyun 		goto error;
4377*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_FSM_FTH__A, 50);
4378*4882a593Smuzhiyun 	if (status < 0)
4379*4882a593Smuzhiyun 		goto error;
4380*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_FSM_CTH__A, 95);
4381*4882a593Smuzhiyun 	if (status < 0)
4382*4882a593Smuzhiyun 		goto error;
4383*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_FSM_PTH__A, 120);
4384*4882a593Smuzhiyun 	if (status < 0)
4385*4882a593Smuzhiyun 		goto error;
4386*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_FSM_QTH__A, 230);
4387*4882a593Smuzhiyun 	if (status < 0)
4388*4882a593Smuzhiyun 		goto error;
4389*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_FSM_MTH__A, 105);
4390*4882a593Smuzhiyun 	if (status < 0)
4391*4882a593Smuzhiyun 		goto error;
4392*4882a593Smuzhiyun 
4393*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_FSM_RATE_LIM__A, 40);
4394*4882a593Smuzhiyun 	if (status < 0)
4395*4882a593Smuzhiyun 		goto error;
4396*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_FSM_COUNT_LIM__A, 4);
4397*4882a593Smuzhiyun 	if (status < 0)
4398*4882a593Smuzhiyun 		goto error;
4399*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_FSM_FREQ_LIM__A, 24);
4400*4882a593Smuzhiyun 	if (status < 0)
4401*4882a593Smuzhiyun 		goto error;
4402*4882a593Smuzhiyun 
4403*4882a593Smuzhiyun 
4404*4882a593Smuzhiyun 	/* QAM FSM Tracking Parameters */
4405*4882a593Smuzhiyun 
4406*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_FSM_MEDIAN_AV_MULT__A, (u16) 16);
4407*4882a593Smuzhiyun 	if (status < 0)
4408*4882a593Smuzhiyun 		goto error;
4409*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_FSM_RADIUS_AV_LIMIT__A, (u16) 220);
4410*4882a593Smuzhiyun 	if (status < 0)
4411*4882a593Smuzhiyun 		goto error;
4412*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET1__A, (u16) 25);
4413*4882a593Smuzhiyun 	if (status < 0)
4414*4882a593Smuzhiyun 		goto error;
4415*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET2__A, (u16) 6);
4416*4882a593Smuzhiyun 	if (status < 0)
4417*4882a593Smuzhiyun 		goto error;
4418*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET3__A, (u16) -24);
4419*4882a593Smuzhiyun 	if (status < 0)
4420*4882a593Smuzhiyun 		goto error;
4421*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET4__A, (u16) -65);
4422*4882a593Smuzhiyun 	if (status < 0)
4423*4882a593Smuzhiyun 		goto error;
4424*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET5__A, (u16) -127);
4425*4882a593Smuzhiyun 	if (status < 0)
4426*4882a593Smuzhiyun 		goto error;
4427*4882a593Smuzhiyun 
4428*4882a593Smuzhiyun error:
4429*4882a593Smuzhiyun 	if (status < 0)
4430*4882a593Smuzhiyun 		pr_err("Error %d on %s\n", status, __func__);
4431*4882a593Smuzhiyun 	return status;
4432*4882a593Smuzhiyun }
4433*4882a593Smuzhiyun 
4434*4882a593Smuzhiyun /*============================================================================*/
4435*4882a593Smuzhiyun 
4436*4882a593Smuzhiyun /*
4437*4882a593Smuzhiyun * \brief QAM32 specific setup
4438*4882a593Smuzhiyun * \param demod instance of demod.
4439*4882a593Smuzhiyun * \return DRXStatus_t.
4440*4882a593Smuzhiyun */
set_qam32(struct drxk_state * state)4441*4882a593Smuzhiyun static int set_qam32(struct drxk_state *state)
4442*4882a593Smuzhiyun {
4443*4882a593Smuzhiyun 	int status = 0;
4444*4882a593Smuzhiyun 
4445*4882a593Smuzhiyun 	dprintk(1, "\n");
4446*4882a593Smuzhiyun 
4447*4882a593Smuzhiyun 	/* QAM Equalizer Setup */
4448*4882a593Smuzhiyun 	/* Equalizer */
4449*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD0__A, 6707);
4450*4882a593Smuzhiyun 	if (status < 0)
4451*4882a593Smuzhiyun 		goto error;
4452*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD1__A, 6707);
4453*4882a593Smuzhiyun 	if (status < 0)
4454*4882a593Smuzhiyun 		goto error;
4455*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD2__A, 6707);
4456*4882a593Smuzhiyun 	if (status < 0)
4457*4882a593Smuzhiyun 		goto error;
4458*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD3__A, 6707);
4459*4882a593Smuzhiyun 	if (status < 0)
4460*4882a593Smuzhiyun 		goto error;
4461*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD4__A, 6707);
4462*4882a593Smuzhiyun 	if (status < 0)
4463*4882a593Smuzhiyun 		goto error;
4464*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD5__A, 6707);
4465*4882a593Smuzhiyun 	if (status < 0)
4466*4882a593Smuzhiyun 		goto error;
4467*4882a593Smuzhiyun 
4468*4882a593Smuzhiyun 	/* Decision Feedback Equalizer */
4469*4882a593Smuzhiyun 	status = write16(state, QAM_DQ_QUAL_FUN0__A, 3);
4470*4882a593Smuzhiyun 	if (status < 0)
4471*4882a593Smuzhiyun 		goto error;
4472*4882a593Smuzhiyun 	status = write16(state, QAM_DQ_QUAL_FUN1__A, 3);
4473*4882a593Smuzhiyun 	if (status < 0)
4474*4882a593Smuzhiyun 		goto error;
4475*4882a593Smuzhiyun 	status = write16(state, QAM_DQ_QUAL_FUN2__A, 3);
4476*4882a593Smuzhiyun 	if (status < 0)
4477*4882a593Smuzhiyun 		goto error;
4478*4882a593Smuzhiyun 	status = write16(state, QAM_DQ_QUAL_FUN3__A, 3);
4479*4882a593Smuzhiyun 	if (status < 0)
4480*4882a593Smuzhiyun 		goto error;
4481*4882a593Smuzhiyun 	status = write16(state, QAM_DQ_QUAL_FUN4__A, 3);
4482*4882a593Smuzhiyun 	if (status < 0)
4483*4882a593Smuzhiyun 		goto error;
4484*4882a593Smuzhiyun 	status = write16(state, QAM_DQ_QUAL_FUN5__A, 0);
4485*4882a593Smuzhiyun 	if (status < 0)
4486*4882a593Smuzhiyun 		goto error;
4487*4882a593Smuzhiyun 
4488*4882a593Smuzhiyun 	status = write16(state, QAM_SY_SYNC_HWM__A, 6);
4489*4882a593Smuzhiyun 	if (status < 0)
4490*4882a593Smuzhiyun 		goto error;
4491*4882a593Smuzhiyun 	status = write16(state, QAM_SY_SYNC_AWM__A, 5);
4492*4882a593Smuzhiyun 	if (status < 0)
4493*4882a593Smuzhiyun 		goto error;
4494*4882a593Smuzhiyun 	status = write16(state, QAM_SY_SYNC_LWM__A, 3);
4495*4882a593Smuzhiyun 	if (status < 0)
4496*4882a593Smuzhiyun 		goto error;
4497*4882a593Smuzhiyun 
4498*4882a593Smuzhiyun 	/* QAM Slicer Settings */
4499*4882a593Smuzhiyun 
4500*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_SL_SIG_POWER__A,
4501*4882a593Smuzhiyun 			 DRXK_QAM_SL_SIG_POWER_QAM32);
4502*4882a593Smuzhiyun 	if (status < 0)
4503*4882a593Smuzhiyun 		goto error;
4504*4882a593Smuzhiyun 
4505*4882a593Smuzhiyun 
4506*4882a593Smuzhiyun 	/* QAM Loop Controller Coeficients */
4507*4882a593Smuzhiyun 
4508*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_CA_FINE__A, 15);
4509*4882a593Smuzhiyun 	if (status < 0)
4510*4882a593Smuzhiyun 		goto error;
4511*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_CA_COARSE__A, 40);
4512*4882a593Smuzhiyun 	if (status < 0)
4513*4882a593Smuzhiyun 		goto error;
4514*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_EP_FINE__A, 12);
4515*4882a593Smuzhiyun 	if (status < 0)
4516*4882a593Smuzhiyun 		goto error;
4517*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_EP_MEDIUM__A, 24);
4518*4882a593Smuzhiyun 	if (status < 0)
4519*4882a593Smuzhiyun 		goto error;
4520*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_EP_COARSE__A, 24);
4521*4882a593Smuzhiyun 	if (status < 0)
4522*4882a593Smuzhiyun 		goto error;
4523*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_EI_FINE__A, 12);
4524*4882a593Smuzhiyun 	if (status < 0)
4525*4882a593Smuzhiyun 		goto error;
4526*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_EI_MEDIUM__A, 16);
4527*4882a593Smuzhiyun 	if (status < 0)
4528*4882a593Smuzhiyun 		goto error;
4529*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_EI_COARSE__A, 16);
4530*4882a593Smuzhiyun 	if (status < 0)
4531*4882a593Smuzhiyun 		goto error;
4532*4882a593Smuzhiyun 
4533*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_CP_FINE__A, 5);
4534*4882a593Smuzhiyun 	if (status < 0)
4535*4882a593Smuzhiyun 		goto error;
4536*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_CP_MEDIUM__A, 20);
4537*4882a593Smuzhiyun 	if (status < 0)
4538*4882a593Smuzhiyun 		goto error;
4539*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_CP_COARSE__A, 80);
4540*4882a593Smuzhiyun 	if (status < 0)
4541*4882a593Smuzhiyun 		goto error;
4542*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_CI_FINE__A, 5);
4543*4882a593Smuzhiyun 	if (status < 0)
4544*4882a593Smuzhiyun 		goto error;
4545*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_CI_MEDIUM__A, 20);
4546*4882a593Smuzhiyun 	if (status < 0)
4547*4882a593Smuzhiyun 		goto error;
4548*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_CI_COARSE__A, 50);
4549*4882a593Smuzhiyun 	if (status < 0)
4550*4882a593Smuzhiyun 		goto error;
4551*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_CF_FINE__A, 16);
4552*4882a593Smuzhiyun 	if (status < 0)
4553*4882a593Smuzhiyun 		goto error;
4554*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_CF_MEDIUM__A, 16);
4555*4882a593Smuzhiyun 	if (status < 0)
4556*4882a593Smuzhiyun 		goto error;
4557*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_CF_COARSE__A, 16);
4558*4882a593Smuzhiyun 	if (status < 0)
4559*4882a593Smuzhiyun 		goto error;
4560*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_CF1_FINE__A, 5);
4561*4882a593Smuzhiyun 	if (status < 0)
4562*4882a593Smuzhiyun 		goto error;
4563*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_CF1_MEDIUM__A, 10);
4564*4882a593Smuzhiyun 	if (status < 0)
4565*4882a593Smuzhiyun 		goto error;
4566*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_CF1_COARSE__A, 0);
4567*4882a593Smuzhiyun 	if (status < 0)
4568*4882a593Smuzhiyun 		goto error;
4569*4882a593Smuzhiyun 
4570*4882a593Smuzhiyun 
4571*4882a593Smuzhiyun 	/* QAM State Machine (FSM) Thresholds */
4572*4882a593Smuzhiyun 
4573*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_FSM_RTH__A, 90);
4574*4882a593Smuzhiyun 	if (status < 0)
4575*4882a593Smuzhiyun 		goto error;
4576*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_FSM_FTH__A, 50);
4577*4882a593Smuzhiyun 	if (status < 0)
4578*4882a593Smuzhiyun 		goto error;
4579*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_FSM_CTH__A, 80);
4580*4882a593Smuzhiyun 	if (status < 0)
4581*4882a593Smuzhiyun 		goto error;
4582*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_FSM_PTH__A, 100);
4583*4882a593Smuzhiyun 	if (status < 0)
4584*4882a593Smuzhiyun 		goto error;
4585*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_FSM_QTH__A, 170);
4586*4882a593Smuzhiyun 	if (status < 0)
4587*4882a593Smuzhiyun 		goto error;
4588*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_FSM_MTH__A, 100);
4589*4882a593Smuzhiyun 	if (status < 0)
4590*4882a593Smuzhiyun 		goto error;
4591*4882a593Smuzhiyun 
4592*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_FSM_RATE_LIM__A, 40);
4593*4882a593Smuzhiyun 	if (status < 0)
4594*4882a593Smuzhiyun 		goto error;
4595*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_FSM_COUNT_LIM__A, 4);
4596*4882a593Smuzhiyun 	if (status < 0)
4597*4882a593Smuzhiyun 		goto error;
4598*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_FSM_FREQ_LIM__A, 10);
4599*4882a593Smuzhiyun 	if (status < 0)
4600*4882a593Smuzhiyun 		goto error;
4601*4882a593Smuzhiyun 
4602*4882a593Smuzhiyun 
4603*4882a593Smuzhiyun 	/* QAM FSM Tracking Parameters */
4604*4882a593Smuzhiyun 
4605*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_FSM_MEDIAN_AV_MULT__A, (u16) 12);
4606*4882a593Smuzhiyun 	if (status < 0)
4607*4882a593Smuzhiyun 		goto error;
4608*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_FSM_RADIUS_AV_LIMIT__A, (u16) 140);
4609*4882a593Smuzhiyun 	if (status < 0)
4610*4882a593Smuzhiyun 		goto error;
4611*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET1__A, (u16) -8);
4612*4882a593Smuzhiyun 	if (status < 0)
4613*4882a593Smuzhiyun 		goto error;
4614*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET2__A, (u16) -16);
4615*4882a593Smuzhiyun 	if (status < 0)
4616*4882a593Smuzhiyun 		goto error;
4617*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET3__A, (u16) -26);
4618*4882a593Smuzhiyun 	if (status < 0)
4619*4882a593Smuzhiyun 		goto error;
4620*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET4__A, (u16) -56);
4621*4882a593Smuzhiyun 	if (status < 0)
4622*4882a593Smuzhiyun 		goto error;
4623*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET5__A, (u16) -86);
4624*4882a593Smuzhiyun error:
4625*4882a593Smuzhiyun 	if (status < 0)
4626*4882a593Smuzhiyun 		pr_err("Error %d on %s\n", status, __func__);
4627*4882a593Smuzhiyun 	return status;
4628*4882a593Smuzhiyun }
4629*4882a593Smuzhiyun 
4630*4882a593Smuzhiyun /*============================================================================*/
4631*4882a593Smuzhiyun 
4632*4882a593Smuzhiyun /*
4633*4882a593Smuzhiyun * \brief QAM64 specific setup
4634*4882a593Smuzhiyun * \param demod instance of demod.
4635*4882a593Smuzhiyun * \return DRXStatus_t.
4636*4882a593Smuzhiyun */
set_qam64(struct drxk_state * state)4637*4882a593Smuzhiyun static int set_qam64(struct drxk_state *state)
4638*4882a593Smuzhiyun {
4639*4882a593Smuzhiyun 	int status = 0;
4640*4882a593Smuzhiyun 
4641*4882a593Smuzhiyun 	dprintk(1, "\n");
4642*4882a593Smuzhiyun 	/* QAM Equalizer Setup */
4643*4882a593Smuzhiyun 	/* Equalizer */
4644*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD0__A, 13336);
4645*4882a593Smuzhiyun 	if (status < 0)
4646*4882a593Smuzhiyun 		goto error;
4647*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD1__A, 12618);
4648*4882a593Smuzhiyun 	if (status < 0)
4649*4882a593Smuzhiyun 		goto error;
4650*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD2__A, 11988);
4651*4882a593Smuzhiyun 	if (status < 0)
4652*4882a593Smuzhiyun 		goto error;
4653*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD3__A, 13809);
4654*4882a593Smuzhiyun 	if (status < 0)
4655*4882a593Smuzhiyun 		goto error;
4656*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD4__A, 13809);
4657*4882a593Smuzhiyun 	if (status < 0)
4658*4882a593Smuzhiyun 		goto error;
4659*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD5__A, 15609);
4660*4882a593Smuzhiyun 	if (status < 0)
4661*4882a593Smuzhiyun 		goto error;
4662*4882a593Smuzhiyun 
4663*4882a593Smuzhiyun 	/* Decision Feedback Equalizer */
4664*4882a593Smuzhiyun 	status = write16(state, QAM_DQ_QUAL_FUN0__A, 4);
4665*4882a593Smuzhiyun 	if (status < 0)
4666*4882a593Smuzhiyun 		goto error;
4667*4882a593Smuzhiyun 	status = write16(state, QAM_DQ_QUAL_FUN1__A, 4);
4668*4882a593Smuzhiyun 	if (status < 0)
4669*4882a593Smuzhiyun 		goto error;
4670*4882a593Smuzhiyun 	status = write16(state, QAM_DQ_QUAL_FUN2__A, 4);
4671*4882a593Smuzhiyun 	if (status < 0)
4672*4882a593Smuzhiyun 		goto error;
4673*4882a593Smuzhiyun 	status = write16(state, QAM_DQ_QUAL_FUN3__A, 4);
4674*4882a593Smuzhiyun 	if (status < 0)
4675*4882a593Smuzhiyun 		goto error;
4676*4882a593Smuzhiyun 	status = write16(state, QAM_DQ_QUAL_FUN4__A, 3);
4677*4882a593Smuzhiyun 	if (status < 0)
4678*4882a593Smuzhiyun 		goto error;
4679*4882a593Smuzhiyun 	status = write16(state, QAM_DQ_QUAL_FUN5__A, 0);
4680*4882a593Smuzhiyun 	if (status < 0)
4681*4882a593Smuzhiyun 		goto error;
4682*4882a593Smuzhiyun 
4683*4882a593Smuzhiyun 	status = write16(state, QAM_SY_SYNC_HWM__A, 5);
4684*4882a593Smuzhiyun 	if (status < 0)
4685*4882a593Smuzhiyun 		goto error;
4686*4882a593Smuzhiyun 	status = write16(state, QAM_SY_SYNC_AWM__A, 4);
4687*4882a593Smuzhiyun 	if (status < 0)
4688*4882a593Smuzhiyun 		goto error;
4689*4882a593Smuzhiyun 	status = write16(state, QAM_SY_SYNC_LWM__A, 3);
4690*4882a593Smuzhiyun 	if (status < 0)
4691*4882a593Smuzhiyun 		goto error;
4692*4882a593Smuzhiyun 
4693*4882a593Smuzhiyun 	/* QAM Slicer Settings */
4694*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_SL_SIG_POWER__A,
4695*4882a593Smuzhiyun 			 DRXK_QAM_SL_SIG_POWER_QAM64);
4696*4882a593Smuzhiyun 	if (status < 0)
4697*4882a593Smuzhiyun 		goto error;
4698*4882a593Smuzhiyun 
4699*4882a593Smuzhiyun 
4700*4882a593Smuzhiyun 	/* QAM Loop Controller Coeficients */
4701*4882a593Smuzhiyun 
4702*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_CA_FINE__A, 15);
4703*4882a593Smuzhiyun 	if (status < 0)
4704*4882a593Smuzhiyun 		goto error;
4705*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_CA_COARSE__A, 40);
4706*4882a593Smuzhiyun 	if (status < 0)
4707*4882a593Smuzhiyun 		goto error;
4708*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_EP_FINE__A, 12);
4709*4882a593Smuzhiyun 	if (status < 0)
4710*4882a593Smuzhiyun 		goto error;
4711*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_EP_MEDIUM__A, 24);
4712*4882a593Smuzhiyun 	if (status < 0)
4713*4882a593Smuzhiyun 		goto error;
4714*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_EP_COARSE__A, 24);
4715*4882a593Smuzhiyun 	if (status < 0)
4716*4882a593Smuzhiyun 		goto error;
4717*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_EI_FINE__A, 12);
4718*4882a593Smuzhiyun 	if (status < 0)
4719*4882a593Smuzhiyun 		goto error;
4720*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_EI_MEDIUM__A, 16);
4721*4882a593Smuzhiyun 	if (status < 0)
4722*4882a593Smuzhiyun 		goto error;
4723*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_EI_COARSE__A, 16);
4724*4882a593Smuzhiyun 	if (status < 0)
4725*4882a593Smuzhiyun 		goto error;
4726*4882a593Smuzhiyun 
4727*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_CP_FINE__A, 5);
4728*4882a593Smuzhiyun 	if (status < 0)
4729*4882a593Smuzhiyun 		goto error;
4730*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_CP_MEDIUM__A, 30);
4731*4882a593Smuzhiyun 	if (status < 0)
4732*4882a593Smuzhiyun 		goto error;
4733*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_CP_COARSE__A, 100);
4734*4882a593Smuzhiyun 	if (status < 0)
4735*4882a593Smuzhiyun 		goto error;
4736*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_CI_FINE__A, 5);
4737*4882a593Smuzhiyun 	if (status < 0)
4738*4882a593Smuzhiyun 		goto error;
4739*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_CI_MEDIUM__A, 30);
4740*4882a593Smuzhiyun 	if (status < 0)
4741*4882a593Smuzhiyun 		goto error;
4742*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_CI_COARSE__A, 50);
4743*4882a593Smuzhiyun 	if (status < 0)
4744*4882a593Smuzhiyun 		goto error;
4745*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_CF_FINE__A, 16);
4746*4882a593Smuzhiyun 	if (status < 0)
4747*4882a593Smuzhiyun 		goto error;
4748*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_CF_MEDIUM__A, 25);
4749*4882a593Smuzhiyun 	if (status < 0)
4750*4882a593Smuzhiyun 		goto error;
4751*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_CF_COARSE__A, 48);
4752*4882a593Smuzhiyun 	if (status < 0)
4753*4882a593Smuzhiyun 		goto error;
4754*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_CF1_FINE__A, 5);
4755*4882a593Smuzhiyun 	if (status < 0)
4756*4882a593Smuzhiyun 		goto error;
4757*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_CF1_MEDIUM__A, 10);
4758*4882a593Smuzhiyun 	if (status < 0)
4759*4882a593Smuzhiyun 		goto error;
4760*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_CF1_COARSE__A, 10);
4761*4882a593Smuzhiyun 	if (status < 0)
4762*4882a593Smuzhiyun 		goto error;
4763*4882a593Smuzhiyun 
4764*4882a593Smuzhiyun 
4765*4882a593Smuzhiyun 	/* QAM State Machine (FSM) Thresholds */
4766*4882a593Smuzhiyun 
4767*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_FSM_RTH__A, 100);
4768*4882a593Smuzhiyun 	if (status < 0)
4769*4882a593Smuzhiyun 		goto error;
4770*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_FSM_FTH__A, 60);
4771*4882a593Smuzhiyun 	if (status < 0)
4772*4882a593Smuzhiyun 		goto error;
4773*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_FSM_CTH__A, 80);
4774*4882a593Smuzhiyun 	if (status < 0)
4775*4882a593Smuzhiyun 		goto error;
4776*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_FSM_PTH__A, 110);
4777*4882a593Smuzhiyun 	if (status < 0)
4778*4882a593Smuzhiyun 		goto error;
4779*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_FSM_QTH__A, 200);
4780*4882a593Smuzhiyun 	if (status < 0)
4781*4882a593Smuzhiyun 		goto error;
4782*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_FSM_MTH__A, 95);
4783*4882a593Smuzhiyun 	if (status < 0)
4784*4882a593Smuzhiyun 		goto error;
4785*4882a593Smuzhiyun 
4786*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_FSM_RATE_LIM__A, 40);
4787*4882a593Smuzhiyun 	if (status < 0)
4788*4882a593Smuzhiyun 		goto error;
4789*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_FSM_COUNT_LIM__A, 4);
4790*4882a593Smuzhiyun 	if (status < 0)
4791*4882a593Smuzhiyun 		goto error;
4792*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_FSM_FREQ_LIM__A, 15);
4793*4882a593Smuzhiyun 	if (status < 0)
4794*4882a593Smuzhiyun 		goto error;
4795*4882a593Smuzhiyun 
4796*4882a593Smuzhiyun 
4797*4882a593Smuzhiyun 	/* QAM FSM Tracking Parameters */
4798*4882a593Smuzhiyun 
4799*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_FSM_MEDIAN_AV_MULT__A, (u16) 12);
4800*4882a593Smuzhiyun 	if (status < 0)
4801*4882a593Smuzhiyun 		goto error;
4802*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_FSM_RADIUS_AV_LIMIT__A, (u16) 141);
4803*4882a593Smuzhiyun 	if (status < 0)
4804*4882a593Smuzhiyun 		goto error;
4805*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET1__A, (u16) 7);
4806*4882a593Smuzhiyun 	if (status < 0)
4807*4882a593Smuzhiyun 		goto error;
4808*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET2__A, (u16) 0);
4809*4882a593Smuzhiyun 	if (status < 0)
4810*4882a593Smuzhiyun 		goto error;
4811*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET3__A, (u16) -15);
4812*4882a593Smuzhiyun 	if (status < 0)
4813*4882a593Smuzhiyun 		goto error;
4814*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET4__A, (u16) -45);
4815*4882a593Smuzhiyun 	if (status < 0)
4816*4882a593Smuzhiyun 		goto error;
4817*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET5__A, (u16) -80);
4818*4882a593Smuzhiyun error:
4819*4882a593Smuzhiyun 	if (status < 0)
4820*4882a593Smuzhiyun 		pr_err("Error %d on %s\n", status, __func__);
4821*4882a593Smuzhiyun 
4822*4882a593Smuzhiyun 	return status;
4823*4882a593Smuzhiyun }
4824*4882a593Smuzhiyun 
4825*4882a593Smuzhiyun /*============================================================================*/
4826*4882a593Smuzhiyun 
4827*4882a593Smuzhiyun /*
4828*4882a593Smuzhiyun * \brief QAM128 specific setup
4829*4882a593Smuzhiyun * \param demod: instance of demod.
4830*4882a593Smuzhiyun * \return DRXStatus_t.
4831*4882a593Smuzhiyun */
set_qam128(struct drxk_state * state)4832*4882a593Smuzhiyun static int set_qam128(struct drxk_state *state)
4833*4882a593Smuzhiyun {
4834*4882a593Smuzhiyun 	int status = 0;
4835*4882a593Smuzhiyun 
4836*4882a593Smuzhiyun 	dprintk(1, "\n");
4837*4882a593Smuzhiyun 	/* QAM Equalizer Setup */
4838*4882a593Smuzhiyun 	/* Equalizer */
4839*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD0__A, 6564);
4840*4882a593Smuzhiyun 	if (status < 0)
4841*4882a593Smuzhiyun 		goto error;
4842*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD1__A, 6598);
4843*4882a593Smuzhiyun 	if (status < 0)
4844*4882a593Smuzhiyun 		goto error;
4845*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD2__A, 6394);
4846*4882a593Smuzhiyun 	if (status < 0)
4847*4882a593Smuzhiyun 		goto error;
4848*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD3__A, 6409);
4849*4882a593Smuzhiyun 	if (status < 0)
4850*4882a593Smuzhiyun 		goto error;
4851*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD4__A, 6656);
4852*4882a593Smuzhiyun 	if (status < 0)
4853*4882a593Smuzhiyun 		goto error;
4854*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD5__A, 7238);
4855*4882a593Smuzhiyun 	if (status < 0)
4856*4882a593Smuzhiyun 		goto error;
4857*4882a593Smuzhiyun 
4858*4882a593Smuzhiyun 	/* Decision Feedback Equalizer */
4859*4882a593Smuzhiyun 	status = write16(state, QAM_DQ_QUAL_FUN0__A, 6);
4860*4882a593Smuzhiyun 	if (status < 0)
4861*4882a593Smuzhiyun 		goto error;
4862*4882a593Smuzhiyun 	status = write16(state, QAM_DQ_QUAL_FUN1__A, 6);
4863*4882a593Smuzhiyun 	if (status < 0)
4864*4882a593Smuzhiyun 		goto error;
4865*4882a593Smuzhiyun 	status = write16(state, QAM_DQ_QUAL_FUN2__A, 6);
4866*4882a593Smuzhiyun 	if (status < 0)
4867*4882a593Smuzhiyun 		goto error;
4868*4882a593Smuzhiyun 	status = write16(state, QAM_DQ_QUAL_FUN3__A, 6);
4869*4882a593Smuzhiyun 	if (status < 0)
4870*4882a593Smuzhiyun 		goto error;
4871*4882a593Smuzhiyun 	status = write16(state, QAM_DQ_QUAL_FUN4__A, 5);
4872*4882a593Smuzhiyun 	if (status < 0)
4873*4882a593Smuzhiyun 		goto error;
4874*4882a593Smuzhiyun 	status = write16(state, QAM_DQ_QUAL_FUN5__A, 0);
4875*4882a593Smuzhiyun 	if (status < 0)
4876*4882a593Smuzhiyun 		goto error;
4877*4882a593Smuzhiyun 
4878*4882a593Smuzhiyun 	status = write16(state, QAM_SY_SYNC_HWM__A, 6);
4879*4882a593Smuzhiyun 	if (status < 0)
4880*4882a593Smuzhiyun 		goto error;
4881*4882a593Smuzhiyun 	status = write16(state, QAM_SY_SYNC_AWM__A, 5);
4882*4882a593Smuzhiyun 	if (status < 0)
4883*4882a593Smuzhiyun 		goto error;
4884*4882a593Smuzhiyun 	status = write16(state, QAM_SY_SYNC_LWM__A, 3);
4885*4882a593Smuzhiyun 	if (status < 0)
4886*4882a593Smuzhiyun 		goto error;
4887*4882a593Smuzhiyun 
4888*4882a593Smuzhiyun 
4889*4882a593Smuzhiyun 	/* QAM Slicer Settings */
4890*4882a593Smuzhiyun 
4891*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_SL_SIG_POWER__A,
4892*4882a593Smuzhiyun 			 DRXK_QAM_SL_SIG_POWER_QAM128);
4893*4882a593Smuzhiyun 	if (status < 0)
4894*4882a593Smuzhiyun 		goto error;
4895*4882a593Smuzhiyun 
4896*4882a593Smuzhiyun 
4897*4882a593Smuzhiyun 	/* QAM Loop Controller Coeficients */
4898*4882a593Smuzhiyun 
4899*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_CA_FINE__A, 15);
4900*4882a593Smuzhiyun 	if (status < 0)
4901*4882a593Smuzhiyun 		goto error;
4902*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_CA_COARSE__A, 40);
4903*4882a593Smuzhiyun 	if (status < 0)
4904*4882a593Smuzhiyun 		goto error;
4905*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_EP_FINE__A, 12);
4906*4882a593Smuzhiyun 	if (status < 0)
4907*4882a593Smuzhiyun 		goto error;
4908*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_EP_MEDIUM__A, 24);
4909*4882a593Smuzhiyun 	if (status < 0)
4910*4882a593Smuzhiyun 		goto error;
4911*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_EP_COARSE__A, 24);
4912*4882a593Smuzhiyun 	if (status < 0)
4913*4882a593Smuzhiyun 		goto error;
4914*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_EI_FINE__A, 12);
4915*4882a593Smuzhiyun 	if (status < 0)
4916*4882a593Smuzhiyun 		goto error;
4917*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_EI_MEDIUM__A, 16);
4918*4882a593Smuzhiyun 	if (status < 0)
4919*4882a593Smuzhiyun 		goto error;
4920*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_EI_COARSE__A, 16);
4921*4882a593Smuzhiyun 	if (status < 0)
4922*4882a593Smuzhiyun 		goto error;
4923*4882a593Smuzhiyun 
4924*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_CP_FINE__A, 5);
4925*4882a593Smuzhiyun 	if (status < 0)
4926*4882a593Smuzhiyun 		goto error;
4927*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_CP_MEDIUM__A, 40);
4928*4882a593Smuzhiyun 	if (status < 0)
4929*4882a593Smuzhiyun 		goto error;
4930*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_CP_COARSE__A, 120);
4931*4882a593Smuzhiyun 	if (status < 0)
4932*4882a593Smuzhiyun 		goto error;
4933*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_CI_FINE__A, 5);
4934*4882a593Smuzhiyun 	if (status < 0)
4935*4882a593Smuzhiyun 		goto error;
4936*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_CI_MEDIUM__A, 40);
4937*4882a593Smuzhiyun 	if (status < 0)
4938*4882a593Smuzhiyun 		goto error;
4939*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_CI_COARSE__A, 60);
4940*4882a593Smuzhiyun 	if (status < 0)
4941*4882a593Smuzhiyun 		goto error;
4942*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_CF_FINE__A, 16);
4943*4882a593Smuzhiyun 	if (status < 0)
4944*4882a593Smuzhiyun 		goto error;
4945*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_CF_MEDIUM__A, 25);
4946*4882a593Smuzhiyun 	if (status < 0)
4947*4882a593Smuzhiyun 		goto error;
4948*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_CF_COARSE__A, 64);
4949*4882a593Smuzhiyun 	if (status < 0)
4950*4882a593Smuzhiyun 		goto error;
4951*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_CF1_FINE__A, 5);
4952*4882a593Smuzhiyun 	if (status < 0)
4953*4882a593Smuzhiyun 		goto error;
4954*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_CF1_MEDIUM__A, 10);
4955*4882a593Smuzhiyun 	if (status < 0)
4956*4882a593Smuzhiyun 		goto error;
4957*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_CF1_COARSE__A, 0);
4958*4882a593Smuzhiyun 	if (status < 0)
4959*4882a593Smuzhiyun 		goto error;
4960*4882a593Smuzhiyun 
4961*4882a593Smuzhiyun 
4962*4882a593Smuzhiyun 	/* QAM State Machine (FSM) Thresholds */
4963*4882a593Smuzhiyun 
4964*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_FSM_RTH__A, 50);
4965*4882a593Smuzhiyun 	if (status < 0)
4966*4882a593Smuzhiyun 		goto error;
4967*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_FSM_FTH__A, 60);
4968*4882a593Smuzhiyun 	if (status < 0)
4969*4882a593Smuzhiyun 		goto error;
4970*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_FSM_CTH__A, 80);
4971*4882a593Smuzhiyun 	if (status < 0)
4972*4882a593Smuzhiyun 		goto error;
4973*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_FSM_PTH__A, 100);
4974*4882a593Smuzhiyun 	if (status < 0)
4975*4882a593Smuzhiyun 		goto error;
4976*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_FSM_QTH__A, 140);
4977*4882a593Smuzhiyun 	if (status < 0)
4978*4882a593Smuzhiyun 		goto error;
4979*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_FSM_MTH__A, 100);
4980*4882a593Smuzhiyun 	if (status < 0)
4981*4882a593Smuzhiyun 		goto error;
4982*4882a593Smuzhiyun 
4983*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_FSM_RATE_LIM__A, 40);
4984*4882a593Smuzhiyun 	if (status < 0)
4985*4882a593Smuzhiyun 		goto error;
4986*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_FSM_COUNT_LIM__A, 5);
4987*4882a593Smuzhiyun 	if (status < 0)
4988*4882a593Smuzhiyun 		goto error;
4989*4882a593Smuzhiyun 
4990*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_FSM_FREQ_LIM__A, 12);
4991*4882a593Smuzhiyun 	if (status < 0)
4992*4882a593Smuzhiyun 		goto error;
4993*4882a593Smuzhiyun 
4994*4882a593Smuzhiyun 	/* QAM FSM Tracking Parameters */
4995*4882a593Smuzhiyun 
4996*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_FSM_MEDIAN_AV_MULT__A, (u16) 8);
4997*4882a593Smuzhiyun 	if (status < 0)
4998*4882a593Smuzhiyun 		goto error;
4999*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_FSM_RADIUS_AV_LIMIT__A, (u16) 65);
5000*4882a593Smuzhiyun 	if (status < 0)
5001*4882a593Smuzhiyun 		goto error;
5002*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET1__A, (u16) 5);
5003*4882a593Smuzhiyun 	if (status < 0)
5004*4882a593Smuzhiyun 		goto error;
5005*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET2__A, (u16) 3);
5006*4882a593Smuzhiyun 	if (status < 0)
5007*4882a593Smuzhiyun 		goto error;
5008*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET3__A, (u16) -1);
5009*4882a593Smuzhiyun 	if (status < 0)
5010*4882a593Smuzhiyun 		goto error;
5011*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET4__A, (u16) -12);
5012*4882a593Smuzhiyun 	if (status < 0)
5013*4882a593Smuzhiyun 		goto error;
5014*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET5__A, (u16) -23);
5015*4882a593Smuzhiyun error:
5016*4882a593Smuzhiyun 	if (status < 0)
5017*4882a593Smuzhiyun 		pr_err("Error %d on %s\n", status, __func__);
5018*4882a593Smuzhiyun 
5019*4882a593Smuzhiyun 	return status;
5020*4882a593Smuzhiyun }
5021*4882a593Smuzhiyun 
5022*4882a593Smuzhiyun /*============================================================================*/
5023*4882a593Smuzhiyun 
5024*4882a593Smuzhiyun /*
5025*4882a593Smuzhiyun * \brief QAM256 specific setup
5026*4882a593Smuzhiyun * \param demod: instance of demod.
5027*4882a593Smuzhiyun * \return DRXStatus_t.
5028*4882a593Smuzhiyun */
set_qam256(struct drxk_state * state)5029*4882a593Smuzhiyun static int set_qam256(struct drxk_state *state)
5030*4882a593Smuzhiyun {
5031*4882a593Smuzhiyun 	int status = 0;
5032*4882a593Smuzhiyun 
5033*4882a593Smuzhiyun 	dprintk(1, "\n");
5034*4882a593Smuzhiyun 	/* QAM Equalizer Setup */
5035*4882a593Smuzhiyun 	/* Equalizer */
5036*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD0__A, 11502);
5037*4882a593Smuzhiyun 	if (status < 0)
5038*4882a593Smuzhiyun 		goto error;
5039*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD1__A, 12084);
5040*4882a593Smuzhiyun 	if (status < 0)
5041*4882a593Smuzhiyun 		goto error;
5042*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD2__A, 12543);
5043*4882a593Smuzhiyun 	if (status < 0)
5044*4882a593Smuzhiyun 		goto error;
5045*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD3__A, 12931);
5046*4882a593Smuzhiyun 	if (status < 0)
5047*4882a593Smuzhiyun 		goto error;
5048*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD4__A, 13629);
5049*4882a593Smuzhiyun 	if (status < 0)
5050*4882a593Smuzhiyun 		goto error;
5051*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD5__A, 15385);
5052*4882a593Smuzhiyun 	if (status < 0)
5053*4882a593Smuzhiyun 		goto error;
5054*4882a593Smuzhiyun 
5055*4882a593Smuzhiyun 	/* Decision Feedback Equalizer */
5056*4882a593Smuzhiyun 	status = write16(state, QAM_DQ_QUAL_FUN0__A, 8);
5057*4882a593Smuzhiyun 	if (status < 0)
5058*4882a593Smuzhiyun 		goto error;
5059*4882a593Smuzhiyun 	status = write16(state, QAM_DQ_QUAL_FUN1__A, 8);
5060*4882a593Smuzhiyun 	if (status < 0)
5061*4882a593Smuzhiyun 		goto error;
5062*4882a593Smuzhiyun 	status = write16(state, QAM_DQ_QUAL_FUN2__A, 8);
5063*4882a593Smuzhiyun 	if (status < 0)
5064*4882a593Smuzhiyun 		goto error;
5065*4882a593Smuzhiyun 	status = write16(state, QAM_DQ_QUAL_FUN3__A, 8);
5066*4882a593Smuzhiyun 	if (status < 0)
5067*4882a593Smuzhiyun 		goto error;
5068*4882a593Smuzhiyun 	status = write16(state, QAM_DQ_QUAL_FUN4__A, 6);
5069*4882a593Smuzhiyun 	if (status < 0)
5070*4882a593Smuzhiyun 		goto error;
5071*4882a593Smuzhiyun 	status = write16(state, QAM_DQ_QUAL_FUN5__A, 0);
5072*4882a593Smuzhiyun 	if (status < 0)
5073*4882a593Smuzhiyun 		goto error;
5074*4882a593Smuzhiyun 
5075*4882a593Smuzhiyun 	status = write16(state, QAM_SY_SYNC_HWM__A, 5);
5076*4882a593Smuzhiyun 	if (status < 0)
5077*4882a593Smuzhiyun 		goto error;
5078*4882a593Smuzhiyun 	status = write16(state, QAM_SY_SYNC_AWM__A, 4);
5079*4882a593Smuzhiyun 	if (status < 0)
5080*4882a593Smuzhiyun 		goto error;
5081*4882a593Smuzhiyun 	status = write16(state, QAM_SY_SYNC_LWM__A, 3);
5082*4882a593Smuzhiyun 	if (status < 0)
5083*4882a593Smuzhiyun 		goto error;
5084*4882a593Smuzhiyun 
5085*4882a593Smuzhiyun 	/* QAM Slicer Settings */
5086*4882a593Smuzhiyun 
5087*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_SL_SIG_POWER__A,
5088*4882a593Smuzhiyun 			 DRXK_QAM_SL_SIG_POWER_QAM256);
5089*4882a593Smuzhiyun 	if (status < 0)
5090*4882a593Smuzhiyun 		goto error;
5091*4882a593Smuzhiyun 
5092*4882a593Smuzhiyun 
5093*4882a593Smuzhiyun 	/* QAM Loop Controller Coeficients */
5094*4882a593Smuzhiyun 
5095*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_CA_FINE__A, 15);
5096*4882a593Smuzhiyun 	if (status < 0)
5097*4882a593Smuzhiyun 		goto error;
5098*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_CA_COARSE__A, 40);
5099*4882a593Smuzhiyun 	if (status < 0)
5100*4882a593Smuzhiyun 		goto error;
5101*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_EP_FINE__A, 12);
5102*4882a593Smuzhiyun 	if (status < 0)
5103*4882a593Smuzhiyun 		goto error;
5104*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_EP_MEDIUM__A, 24);
5105*4882a593Smuzhiyun 	if (status < 0)
5106*4882a593Smuzhiyun 		goto error;
5107*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_EP_COARSE__A, 24);
5108*4882a593Smuzhiyun 	if (status < 0)
5109*4882a593Smuzhiyun 		goto error;
5110*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_EI_FINE__A, 12);
5111*4882a593Smuzhiyun 	if (status < 0)
5112*4882a593Smuzhiyun 		goto error;
5113*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_EI_MEDIUM__A, 16);
5114*4882a593Smuzhiyun 	if (status < 0)
5115*4882a593Smuzhiyun 		goto error;
5116*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_EI_COARSE__A, 16);
5117*4882a593Smuzhiyun 	if (status < 0)
5118*4882a593Smuzhiyun 		goto error;
5119*4882a593Smuzhiyun 
5120*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_CP_FINE__A, 5);
5121*4882a593Smuzhiyun 	if (status < 0)
5122*4882a593Smuzhiyun 		goto error;
5123*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_CP_MEDIUM__A, 50);
5124*4882a593Smuzhiyun 	if (status < 0)
5125*4882a593Smuzhiyun 		goto error;
5126*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_CP_COARSE__A, 250);
5127*4882a593Smuzhiyun 	if (status < 0)
5128*4882a593Smuzhiyun 		goto error;
5129*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_CI_FINE__A, 5);
5130*4882a593Smuzhiyun 	if (status < 0)
5131*4882a593Smuzhiyun 		goto error;
5132*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_CI_MEDIUM__A, 50);
5133*4882a593Smuzhiyun 	if (status < 0)
5134*4882a593Smuzhiyun 		goto error;
5135*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_CI_COARSE__A, 125);
5136*4882a593Smuzhiyun 	if (status < 0)
5137*4882a593Smuzhiyun 		goto error;
5138*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_CF_FINE__A, 16);
5139*4882a593Smuzhiyun 	if (status < 0)
5140*4882a593Smuzhiyun 		goto error;
5141*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_CF_MEDIUM__A, 25);
5142*4882a593Smuzhiyun 	if (status < 0)
5143*4882a593Smuzhiyun 		goto error;
5144*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_CF_COARSE__A, 48);
5145*4882a593Smuzhiyun 	if (status < 0)
5146*4882a593Smuzhiyun 		goto error;
5147*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_CF1_FINE__A, 5);
5148*4882a593Smuzhiyun 	if (status < 0)
5149*4882a593Smuzhiyun 		goto error;
5150*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_CF1_MEDIUM__A, 10);
5151*4882a593Smuzhiyun 	if (status < 0)
5152*4882a593Smuzhiyun 		goto error;
5153*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_LC_CF1_COARSE__A, 10);
5154*4882a593Smuzhiyun 	if (status < 0)
5155*4882a593Smuzhiyun 		goto error;
5156*4882a593Smuzhiyun 
5157*4882a593Smuzhiyun 
5158*4882a593Smuzhiyun 	/* QAM State Machine (FSM) Thresholds */
5159*4882a593Smuzhiyun 
5160*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_FSM_RTH__A, 50);
5161*4882a593Smuzhiyun 	if (status < 0)
5162*4882a593Smuzhiyun 		goto error;
5163*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_FSM_FTH__A, 60);
5164*4882a593Smuzhiyun 	if (status < 0)
5165*4882a593Smuzhiyun 		goto error;
5166*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_FSM_CTH__A, 80);
5167*4882a593Smuzhiyun 	if (status < 0)
5168*4882a593Smuzhiyun 		goto error;
5169*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_FSM_PTH__A, 100);
5170*4882a593Smuzhiyun 	if (status < 0)
5171*4882a593Smuzhiyun 		goto error;
5172*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_FSM_QTH__A, 150);
5173*4882a593Smuzhiyun 	if (status < 0)
5174*4882a593Smuzhiyun 		goto error;
5175*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_FSM_MTH__A, 110);
5176*4882a593Smuzhiyun 	if (status < 0)
5177*4882a593Smuzhiyun 		goto error;
5178*4882a593Smuzhiyun 
5179*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_FSM_RATE_LIM__A, 40);
5180*4882a593Smuzhiyun 	if (status < 0)
5181*4882a593Smuzhiyun 		goto error;
5182*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_FSM_COUNT_LIM__A, 4);
5183*4882a593Smuzhiyun 	if (status < 0)
5184*4882a593Smuzhiyun 		goto error;
5185*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_FSM_FREQ_LIM__A, 12);
5186*4882a593Smuzhiyun 	if (status < 0)
5187*4882a593Smuzhiyun 		goto error;
5188*4882a593Smuzhiyun 
5189*4882a593Smuzhiyun 
5190*4882a593Smuzhiyun 	/* QAM FSM Tracking Parameters */
5191*4882a593Smuzhiyun 
5192*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_FSM_MEDIAN_AV_MULT__A, (u16) 8);
5193*4882a593Smuzhiyun 	if (status < 0)
5194*4882a593Smuzhiyun 		goto error;
5195*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_FSM_RADIUS_AV_LIMIT__A, (u16) 74);
5196*4882a593Smuzhiyun 	if (status < 0)
5197*4882a593Smuzhiyun 		goto error;
5198*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET1__A, (u16) 18);
5199*4882a593Smuzhiyun 	if (status < 0)
5200*4882a593Smuzhiyun 		goto error;
5201*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET2__A, (u16) 13);
5202*4882a593Smuzhiyun 	if (status < 0)
5203*4882a593Smuzhiyun 		goto error;
5204*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET3__A, (u16) 7);
5205*4882a593Smuzhiyun 	if (status < 0)
5206*4882a593Smuzhiyun 		goto error;
5207*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET4__A, (u16) 0);
5208*4882a593Smuzhiyun 	if (status < 0)
5209*4882a593Smuzhiyun 		goto error;
5210*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET5__A, (u16) -8);
5211*4882a593Smuzhiyun error:
5212*4882a593Smuzhiyun 	if (status < 0)
5213*4882a593Smuzhiyun 		pr_err("Error %d on %s\n", status, __func__);
5214*4882a593Smuzhiyun 	return status;
5215*4882a593Smuzhiyun }
5216*4882a593Smuzhiyun 
5217*4882a593Smuzhiyun 
5218*4882a593Smuzhiyun /*============================================================================*/
5219*4882a593Smuzhiyun /*
5220*4882a593Smuzhiyun * \brief Reset QAM block.
5221*4882a593Smuzhiyun * \param demod:   instance of demod.
5222*4882a593Smuzhiyun * \param channel: pointer to channel data.
5223*4882a593Smuzhiyun * \return DRXStatus_t.
5224*4882a593Smuzhiyun */
qam_reset_qam(struct drxk_state * state)5225*4882a593Smuzhiyun static int qam_reset_qam(struct drxk_state *state)
5226*4882a593Smuzhiyun {
5227*4882a593Smuzhiyun 	int status;
5228*4882a593Smuzhiyun 	u16 cmd_result;
5229*4882a593Smuzhiyun 
5230*4882a593Smuzhiyun 	dprintk(1, "\n");
5231*4882a593Smuzhiyun 	/* Stop QAM comstate->m_exec */
5232*4882a593Smuzhiyun 	status = write16(state, QAM_COMM_EXEC__A, QAM_COMM_EXEC_STOP);
5233*4882a593Smuzhiyun 	if (status < 0)
5234*4882a593Smuzhiyun 		goto error;
5235*4882a593Smuzhiyun 
5236*4882a593Smuzhiyun 	status = scu_command(state, SCU_RAM_COMMAND_STANDARD_QAM
5237*4882a593Smuzhiyun 			     | SCU_RAM_COMMAND_CMD_DEMOD_RESET,
5238*4882a593Smuzhiyun 			     0, NULL, 1, &cmd_result);
5239*4882a593Smuzhiyun error:
5240*4882a593Smuzhiyun 	if (status < 0)
5241*4882a593Smuzhiyun 		pr_err("Error %d on %s\n", status, __func__);
5242*4882a593Smuzhiyun 	return status;
5243*4882a593Smuzhiyun }
5244*4882a593Smuzhiyun 
5245*4882a593Smuzhiyun /*============================================================================*/
5246*4882a593Smuzhiyun 
5247*4882a593Smuzhiyun /*
5248*4882a593Smuzhiyun * \brief Set QAM symbolrate.
5249*4882a593Smuzhiyun * \param demod:   instance of demod.
5250*4882a593Smuzhiyun * \param channel: pointer to channel data.
5251*4882a593Smuzhiyun * \return DRXStatus_t.
5252*4882a593Smuzhiyun */
qam_set_symbolrate(struct drxk_state * state)5253*4882a593Smuzhiyun static int qam_set_symbolrate(struct drxk_state *state)
5254*4882a593Smuzhiyun {
5255*4882a593Smuzhiyun 	u32 adc_frequency = 0;
5256*4882a593Smuzhiyun 	u32 symb_freq = 0;
5257*4882a593Smuzhiyun 	u32 iqm_rc_rate = 0;
5258*4882a593Smuzhiyun 	u16 ratesel = 0;
5259*4882a593Smuzhiyun 	u32 lc_symb_rate = 0;
5260*4882a593Smuzhiyun 	int status;
5261*4882a593Smuzhiyun 
5262*4882a593Smuzhiyun 	dprintk(1, "\n");
5263*4882a593Smuzhiyun 	/* Select & calculate correct IQM rate */
5264*4882a593Smuzhiyun 	adc_frequency = (state->m_sys_clock_freq * 1000) / 3;
5265*4882a593Smuzhiyun 	ratesel = 0;
5266*4882a593Smuzhiyun 	if (state->props.symbol_rate <= 1188750)
5267*4882a593Smuzhiyun 		ratesel = 3;
5268*4882a593Smuzhiyun 	else if (state->props.symbol_rate <= 2377500)
5269*4882a593Smuzhiyun 		ratesel = 2;
5270*4882a593Smuzhiyun 	else if (state->props.symbol_rate <= 4755000)
5271*4882a593Smuzhiyun 		ratesel = 1;
5272*4882a593Smuzhiyun 	status = write16(state, IQM_FD_RATESEL__A, ratesel);
5273*4882a593Smuzhiyun 	if (status < 0)
5274*4882a593Smuzhiyun 		goto error;
5275*4882a593Smuzhiyun 
5276*4882a593Smuzhiyun 	/*
5277*4882a593Smuzhiyun 		IqmRcRate = ((Fadc / (symbolrate * (4<<ratesel))) - 1) * (1<<23)
5278*4882a593Smuzhiyun 		*/
5279*4882a593Smuzhiyun 	symb_freq = state->props.symbol_rate * (1 << ratesel);
5280*4882a593Smuzhiyun 	if (symb_freq == 0) {
5281*4882a593Smuzhiyun 		/* Divide by zero */
5282*4882a593Smuzhiyun 		status = -EINVAL;
5283*4882a593Smuzhiyun 		goto error;
5284*4882a593Smuzhiyun 	}
5285*4882a593Smuzhiyun 	iqm_rc_rate = (adc_frequency / symb_freq) * (1 << 21) +
5286*4882a593Smuzhiyun 		(Frac28a((adc_frequency % symb_freq), symb_freq) >> 7) -
5287*4882a593Smuzhiyun 		(1 << 23);
5288*4882a593Smuzhiyun 	status = write32(state, IQM_RC_RATE_OFS_LO__A, iqm_rc_rate);
5289*4882a593Smuzhiyun 	if (status < 0)
5290*4882a593Smuzhiyun 		goto error;
5291*4882a593Smuzhiyun 	state->m_iqm_rc_rate = iqm_rc_rate;
5292*4882a593Smuzhiyun 	/*
5293*4882a593Smuzhiyun 		LcSymbFreq = round (.125 *  symbolrate / adc_freq * (1<<15))
5294*4882a593Smuzhiyun 		*/
5295*4882a593Smuzhiyun 	symb_freq = state->props.symbol_rate;
5296*4882a593Smuzhiyun 	if (adc_frequency == 0) {
5297*4882a593Smuzhiyun 		/* Divide by zero */
5298*4882a593Smuzhiyun 		status = -EINVAL;
5299*4882a593Smuzhiyun 		goto error;
5300*4882a593Smuzhiyun 	}
5301*4882a593Smuzhiyun 	lc_symb_rate = (symb_freq / adc_frequency) * (1 << 12) +
5302*4882a593Smuzhiyun 		(Frac28a((symb_freq % adc_frequency), adc_frequency) >>
5303*4882a593Smuzhiyun 		16);
5304*4882a593Smuzhiyun 	if (lc_symb_rate > 511)
5305*4882a593Smuzhiyun 		lc_symb_rate = 511;
5306*4882a593Smuzhiyun 	status = write16(state, QAM_LC_SYMBOL_FREQ__A, (u16) lc_symb_rate);
5307*4882a593Smuzhiyun 
5308*4882a593Smuzhiyun error:
5309*4882a593Smuzhiyun 	if (status < 0)
5310*4882a593Smuzhiyun 		pr_err("Error %d on %s\n", status, __func__);
5311*4882a593Smuzhiyun 	return status;
5312*4882a593Smuzhiyun }
5313*4882a593Smuzhiyun 
5314*4882a593Smuzhiyun /*============================================================================*/
5315*4882a593Smuzhiyun 
5316*4882a593Smuzhiyun /*
5317*4882a593Smuzhiyun * \brief Get QAM lock status.
5318*4882a593Smuzhiyun * \param demod:   instance of demod.
5319*4882a593Smuzhiyun * \param channel: pointer to channel data.
5320*4882a593Smuzhiyun * \return DRXStatus_t.
5321*4882a593Smuzhiyun */
5322*4882a593Smuzhiyun 
get_qam_lock_status(struct drxk_state * state,u32 * p_lock_status)5323*4882a593Smuzhiyun static int get_qam_lock_status(struct drxk_state *state, u32 *p_lock_status)
5324*4882a593Smuzhiyun {
5325*4882a593Smuzhiyun 	int status;
5326*4882a593Smuzhiyun 	u16 result[2] = { 0, 0 };
5327*4882a593Smuzhiyun 
5328*4882a593Smuzhiyun 	dprintk(1, "\n");
5329*4882a593Smuzhiyun 	*p_lock_status = NOT_LOCKED;
5330*4882a593Smuzhiyun 	status = scu_command(state,
5331*4882a593Smuzhiyun 			SCU_RAM_COMMAND_STANDARD_QAM |
5332*4882a593Smuzhiyun 			SCU_RAM_COMMAND_CMD_DEMOD_GET_LOCK, 0, NULL, 2,
5333*4882a593Smuzhiyun 			result);
5334*4882a593Smuzhiyun 	if (status < 0)
5335*4882a593Smuzhiyun 		pr_err("Error %d on %s\n", status, __func__);
5336*4882a593Smuzhiyun 
5337*4882a593Smuzhiyun 	if (result[1] < SCU_RAM_QAM_LOCKED_LOCKED_DEMOD_LOCKED) {
5338*4882a593Smuzhiyun 		/* 0x0000 NOT LOCKED */
5339*4882a593Smuzhiyun 	} else if (result[1] < SCU_RAM_QAM_LOCKED_LOCKED_LOCKED) {
5340*4882a593Smuzhiyun 		/* 0x4000 DEMOD LOCKED */
5341*4882a593Smuzhiyun 		*p_lock_status = DEMOD_LOCK;
5342*4882a593Smuzhiyun 	} else if (result[1] < SCU_RAM_QAM_LOCKED_LOCKED_NEVER_LOCK) {
5343*4882a593Smuzhiyun 		/* 0x8000 DEMOD + FEC LOCKED (system lock) */
5344*4882a593Smuzhiyun 		*p_lock_status = MPEG_LOCK;
5345*4882a593Smuzhiyun 	} else {
5346*4882a593Smuzhiyun 		/* 0xC000 NEVER LOCKED */
5347*4882a593Smuzhiyun 		/* (system will never be able to lock to the signal) */
5348*4882a593Smuzhiyun 		/*
5349*4882a593Smuzhiyun 		 * TODO: check this, intermediate & standard specific lock
5350*4882a593Smuzhiyun 		 * states are not taken into account here
5351*4882a593Smuzhiyun 		 */
5352*4882a593Smuzhiyun 		*p_lock_status = NEVER_LOCK;
5353*4882a593Smuzhiyun 	}
5354*4882a593Smuzhiyun 	return status;
5355*4882a593Smuzhiyun }
5356*4882a593Smuzhiyun 
5357*4882a593Smuzhiyun #define QAM_MIRROR__M         0x03
5358*4882a593Smuzhiyun #define QAM_MIRROR_NORMAL     0x00
5359*4882a593Smuzhiyun #define QAM_MIRRORED          0x01
5360*4882a593Smuzhiyun #define QAM_MIRROR_AUTO_ON    0x02
5361*4882a593Smuzhiyun #define QAM_LOCKRANGE__M      0x10
5362*4882a593Smuzhiyun #define QAM_LOCKRANGE_NORMAL  0x10
5363*4882a593Smuzhiyun 
qam_demodulator_command(struct drxk_state * state,int number_of_parameters)5364*4882a593Smuzhiyun static int qam_demodulator_command(struct drxk_state *state,
5365*4882a593Smuzhiyun 				 int number_of_parameters)
5366*4882a593Smuzhiyun {
5367*4882a593Smuzhiyun 	int status;
5368*4882a593Smuzhiyun 	u16 cmd_result;
5369*4882a593Smuzhiyun 	u16 set_param_parameters[4] = { 0, 0, 0, 0 };
5370*4882a593Smuzhiyun 
5371*4882a593Smuzhiyun 	set_param_parameters[0] = state->m_constellation;	/* modulation     */
5372*4882a593Smuzhiyun 	set_param_parameters[1] = DRXK_QAM_I12_J17;	/* interleave mode   */
5373*4882a593Smuzhiyun 
5374*4882a593Smuzhiyun 	if (number_of_parameters == 2) {
5375*4882a593Smuzhiyun 		u16 set_env_parameters[1] = { 0 };
5376*4882a593Smuzhiyun 
5377*4882a593Smuzhiyun 		if (state->m_operation_mode == OM_QAM_ITU_C)
5378*4882a593Smuzhiyun 			set_env_parameters[0] = QAM_TOP_ANNEX_C;
5379*4882a593Smuzhiyun 		else
5380*4882a593Smuzhiyun 			set_env_parameters[0] = QAM_TOP_ANNEX_A;
5381*4882a593Smuzhiyun 
5382*4882a593Smuzhiyun 		status = scu_command(state,
5383*4882a593Smuzhiyun 				     SCU_RAM_COMMAND_STANDARD_QAM
5384*4882a593Smuzhiyun 				     | SCU_RAM_COMMAND_CMD_DEMOD_SET_ENV,
5385*4882a593Smuzhiyun 				     1, set_env_parameters, 1, &cmd_result);
5386*4882a593Smuzhiyun 		if (status < 0)
5387*4882a593Smuzhiyun 			goto error;
5388*4882a593Smuzhiyun 
5389*4882a593Smuzhiyun 		status = scu_command(state,
5390*4882a593Smuzhiyun 				     SCU_RAM_COMMAND_STANDARD_QAM
5391*4882a593Smuzhiyun 				     | SCU_RAM_COMMAND_CMD_DEMOD_SET_PARAM,
5392*4882a593Smuzhiyun 				     number_of_parameters, set_param_parameters,
5393*4882a593Smuzhiyun 				     1, &cmd_result);
5394*4882a593Smuzhiyun 	} else if (number_of_parameters == 4) {
5395*4882a593Smuzhiyun 		if (state->m_operation_mode == OM_QAM_ITU_C)
5396*4882a593Smuzhiyun 			set_param_parameters[2] = QAM_TOP_ANNEX_C;
5397*4882a593Smuzhiyun 		else
5398*4882a593Smuzhiyun 			set_param_parameters[2] = QAM_TOP_ANNEX_A;
5399*4882a593Smuzhiyun 
5400*4882a593Smuzhiyun 		set_param_parameters[3] |= (QAM_MIRROR_AUTO_ON);
5401*4882a593Smuzhiyun 		/* Env parameters */
5402*4882a593Smuzhiyun 		/* check for LOCKRANGE Extended */
5403*4882a593Smuzhiyun 		/* set_param_parameters[3] |= QAM_LOCKRANGE_NORMAL; */
5404*4882a593Smuzhiyun 
5405*4882a593Smuzhiyun 		status = scu_command(state,
5406*4882a593Smuzhiyun 				     SCU_RAM_COMMAND_STANDARD_QAM
5407*4882a593Smuzhiyun 				     | SCU_RAM_COMMAND_CMD_DEMOD_SET_PARAM,
5408*4882a593Smuzhiyun 				     number_of_parameters, set_param_parameters,
5409*4882a593Smuzhiyun 				     1, &cmd_result);
5410*4882a593Smuzhiyun 	} else {
5411*4882a593Smuzhiyun 		pr_warn("Unknown QAM demodulator parameter count %d\n",
5412*4882a593Smuzhiyun 			number_of_parameters);
5413*4882a593Smuzhiyun 		status = -EINVAL;
5414*4882a593Smuzhiyun 	}
5415*4882a593Smuzhiyun 
5416*4882a593Smuzhiyun error:
5417*4882a593Smuzhiyun 	if (status < 0)
5418*4882a593Smuzhiyun 		pr_warn("Warning %d on %s\n", status, __func__);
5419*4882a593Smuzhiyun 	return status;
5420*4882a593Smuzhiyun }
5421*4882a593Smuzhiyun 
set_qam(struct drxk_state * state,u16 intermediate_freqk_hz,s32 tuner_freq_offset)5422*4882a593Smuzhiyun static int set_qam(struct drxk_state *state, u16 intermediate_freqk_hz,
5423*4882a593Smuzhiyun 		  s32 tuner_freq_offset)
5424*4882a593Smuzhiyun {
5425*4882a593Smuzhiyun 	int status;
5426*4882a593Smuzhiyun 	u16 cmd_result;
5427*4882a593Smuzhiyun 	int qam_demod_param_count = state->qam_demod_parameter_count;
5428*4882a593Smuzhiyun 
5429*4882a593Smuzhiyun 	dprintk(1, "\n");
5430*4882a593Smuzhiyun 	/*
5431*4882a593Smuzhiyun 	 * STEP 1: reset demodulator
5432*4882a593Smuzhiyun 	 *	resets FEC DI and FEC RS
5433*4882a593Smuzhiyun 	 *	resets QAM block
5434*4882a593Smuzhiyun 	 *	resets SCU variables
5435*4882a593Smuzhiyun 	 */
5436*4882a593Smuzhiyun 	status = write16(state, FEC_DI_COMM_EXEC__A, FEC_DI_COMM_EXEC_STOP);
5437*4882a593Smuzhiyun 	if (status < 0)
5438*4882a593Smuzhiyun 		goto error;
5439*4882a593Smuzhiyun 	status = write16(state, FEC_RS_COMM_EXEC__A, FEC_RS_COMM_EXEC_STOP);
5440*4882a593Smuzhiyun 	if (status < 0)
5441*4882a593Smuzhiyun 		goto error;
5442*4882a593Smuzhiyun 	status = qam_reset_qam(state);
5443*4882a593Smuzhiyun 	if (status < 0)
5444*4882a593Smuzhiyun 		goto error;
5445*4882a593Smuzhiyun 
5446*4882a593Smuzhiyun 	/*
5447*4882a593Smuzhiyun 	 * STEP 2: configure demodulator
5448*4882a593Smuzhiyun 	 *	-set params; resets IQM,QAM,FEC HW; initializes some
5449*4882a593Smuzhiyun 	 *       SCU variables
5450*4882a593Smuzhiyun 	 */
5451*4882a593Smuzhiyun 	status = qam_set_symbolrate(state);
5452*4882a593Smuzhiyun 	if (status < 0)
5453*4882a593Smuzhiyun 		goto error;
5454*4882a593Smuzhiyun 
5455*4882a593Smuzhiyun 	/* Set params */
5456*4882a593Smuzhiyun 	switch (state->props.modulation) {
5457*4882a593Smuzhiyun 	case QAM_256:
5458*4882a593Smuzhiyun 		state->m_constellation = DRX_CONSTELLATION_QAM256;
5459*4882a593Smuzhiyun 		break;
5460*4882a593Smuzhiyun 	case QAM_AUTO:
5461*4882a593Smuzhiyun 	case QAM_64:
5462*4882a593Smuzhiyun 		state->m_constellation = DRX_CONSTELLATION_QAM64;
5463*4882a593Smuzhiyun 		break;
5464*4882a593Smuzhiyun 	case QAM_16:
5465*4882a593Smuzhiyun 		state->m_constellation = DRX_CONSTELLATION_QAM16;
5466*4882a593Smuzhiyun 		break;
5467*4882a593Smuzhiyun 	case QAM_32:
5468*4882a593Smuzhiyun 		state->m_constellation = DRX_CONSTELLATION_QAM32;
5469*4882a593Smuzhiyun 		break;
5470*4882a593Smuzhiyun 	case QAM_128:
5471*4882a593Smuzhiyun 		state->m_constellation = DRX_CONSTELLATION_QAM128;
5472*4882a593Smuzhiyun 		break;
5473*4882a593Smuzhiyun 	default:
5474*4882a593Smuzhiyun 		status = -EINVAL;
5475*4882a593Smuzhiyun 		break;
5476*4882a593Smuzhiyun 	}
5477*4882a593Smuzhiyun 	if (status < 0)
5478*4882a593Smuzhiyun 		goto error;
5479*4882a593Smuzhiyun 
5480*4882a593Smuzhiyun 	/* Use the 4-parameter if it's requested or we're probing for
5481*4882a593Smuzhiyun 	 * the correct command. */
5482*4882a593Smuzhiyun 	if (state->qam_demod_parameter_count == 4
5483*4882a593Smuzhiyun 		|| !state->qam_demod_parameter_count) {
5484*4882a593Smuzhiyun 		qam_demod_param_count = 4;
5485*4882a593Smuzhiyun 		status = qam_demodulator_command(state, qam_demod_param_count);
5486*4882a593Smuzhiyun 	}
5487*4882a593Smuzhiyun 
5488*4882a593Smuzhiyun 	/* Use the 2-parameter command if it was requested or if we're
5489*4882a593Smuzhiyun 	 * probing for the correct command and the 4-parameter command
5490*4882a593Smuzhiyun 	 * failed. */
5491*4882a593Smuzhiyun 	if (state->qam_demod_parameter_count == 2
5492*4882a593Smuzhiyun 		|| (!state->qam_demod_parameter_count && status < 0)) {
5493*4882a593Smuzhiyun 		qam_demod_param_count = 2;
5494*4882a593Smuzhiyun 		status = qam_demodulator_command(state, qam_demod_param_count);
5495*4882a593Smuzhiyun 	}
5496*4882a593Smuzhiyun 
5497*4882a593Smuzhiyun 	if (status < 0) {
5498*4882a593Smuzhiyun 		dprintk(1, "Could not set demodulator parameters.\n");
5499*4882a593Smuzhiyun 		dprintk(1,
5500*4882a593Smuzhiyun 			"Make sure qam_demod_parameter_count (%d) is correct for your firmware (%s).\n",
5501*4882a593Smuzhiyun 			state->qam_demod_parameter_count,
5502*4882a593Smuzhiyun 			state->microcode_name);
5503*4882a593Smuzhiyun 		goto error;
5504*4882a593Smuzhiyun 	} else if (!state->qam_demod_parameter_count) {
5505*4882a593Smuzhiyun 		dprintk(1,
5506*4882a593Smuzhiyun 			"Auto-probing the QAM command parameters was successful - using %d parameters.\n",
5507*4882a593Smuzhiyun 			qam_demod_param_count);
5508*4882a593Smuzhiyun 
5509*4882a593Smuzhiyun 		/*
5510*4882a593Smuzhiyun 		 * One of our commands was successful. We don't need to
5511*4882a593Smuzhiyun 		 * auto-probe anymore, now that we got the correct command.
5512*4882a593Smuzhiyun 		 */
5513*4882a593Smuzhiyun 		state->qam_demod_parameter_count = qam_demod_param_count;
5514*4882a593Smuzhiyun 	}
5515*4882a593Smuzhiyun 
5516*4882a593Smuzhiyun 	/*
5517*4882a593Smuzhiyun 	 * STEP 3: enable the system in a mode where the ADC provides valid
5518*4882a593Smuzhiyun 	 * signal setup modulation independent registers
5519*4882a593Smuzhiyun 	 */
5520*4882a593Smuzhiyun #if 0
5521*4882a593Smuzhiyun 	status = set_frequency(channel, tuner_freq_offset));
5522*4882a593Smuzhiyun 	if (status < 0)
5523*4882a593Smuzhiyun 		goto error;
5524*4882a593Smuzhiyun #endif
5525*4882a593Smuzhiyun 	status = set_frequency_shifter(state, intermediate_freqk_hz,
5526*4882a593Smuzhiyun 				       tuner_freq_offset, true);
5527*4882a593Smuzhiyun 	if (status < 0)
5528*4882a593Smuzhiyun 		goto error;
5529*4882a593Smuzhiyun 
5530*4882a593Smuzhiyun 	/* Setup BER measurement */
5531*4882a593Smuzhiyun 	status = set_qam_measurement(state, state->m_constellation,
5532*4882a593Smuzhiyun 				     state->props.symbol_rate);
5533*4882a593Smuzhiyun 	if (status < 0)
5534*4882a593Smuzhiyun 		goto error;
5535*4882a593Smuzhiyun 
5536*4882a593Smuzhiyun 	/* Reset default values */
5537*4882a593Smuzhiyun 	status = write16(state, IQM_CF_SCALE_SH__A, IQM_CF_SCALE_SH__PRE);
5538*4882a593Smuzhiyun 	if (status < 0)
5539*4882a593Smuzhiyun 		goto error;
5540*4882a593Smuzhiyun 	status = write16(state, QAM_SY_TIMEOUT__A, QAM_SY_TIMEOUT__PRE);
5541*4882a593Smuzhiyun 	if (status < 0)
5542*4882a593Smuzhiyun 		goto error;
5543*4882a593Smuzhiyun 
5544*4882a593Smuzhiyun 	/* Reset default LC values */
5545*4882a593Smuzhiyun 	status = write16(state, QAM_LC_RATE_LIMIT__A, 3);
5546*4882a593Smuzhiyun 	if (status < 0)
5547*4882a593Smuzhiyun 		goto error;
5548*4882a593Smuzhiyun 	status = write16(state, QAM_LC_LPF_FACTORP__A, 4);
5549*4882a593Smuzhiyun 	if (status < 0)
5550*4882a593Smuzhiyun 		goto error;
5551*4882a593Smuzhiyun 	status = write16(state, QAM_LC_LPF_FACTORI__A, 4);
5552*4882a593Smuzhiyun 	if (status < 0)
5553*4882a593Smuzhiyun 		goto error;
5554*4882a593Smuzhiyun 	status = write16(state, QAM_LC_MODE__A, 7);
5555*4882a593Smuzhiyun 	if (status < 0)
5556*4882a593Smuzhiyun 		goto error;
5557*4882a593Smuzhiyun 
5558*4882a593Smuzhiyun 	status = write16(state, QAM_LC_QUAL_TAB0__A, 1);
5559*4882a593Smuzhiyun 	if (status < 0)
5560*4882a593Smuzhiyun 		goto error;
5561*4882a593Smuzhiyun 	status = write16(state, QAM_LC_QUAL_TAB1__A, 1);
5562*4882a593Smuzhiyun 	if (status < 0)
5563*4882a593Smuzhiyun 		goto error;
5564*4882a593Smuzhiyun 	status = write16(state, QAM_LC_QUAL_TAB2__A, 1);
5565*4882a593Smuzhiyun 	if (status < 0)
5566*4882a593Smuzhiyun 		goto error;
5567*4882a593Smuzhiyun 	status = write16(state, QAM_LC_QUAL_TAB3__A, 1);
5568*4882a593Smuzhiyun 	if (status < 0)
5569*4882a593Smuzhiyun 		goto error;
5570*4882a593Smuzhiyun 	status = write16(state, QAM_LC_QUAL_TAB4__A, 2);
5571*4882a593Smuzhiyun 	if (status < 0)
5572*4882a593Smuzhiyun 		goto error;
5573*4882a593Smuzhiyun 	status = write16(state, QAM_LC_QUAL_TAB5__A, 2);
5574*4882a593Smuzhiyun 	if (status < 0)
5575*4882a593Smuzhiyun 		goto error;
5576*4882a593Smuzhiyun 	status = write16(state, QAM_LC_QUAL_TAB6__A, 2);
5577*4882a593Smuzhiyun 	if (status < 0)
5578*4882a593Smuzhiyun 		goto error;
5579*4882a593Smuzhiyun 	status = write16(state, QAM_LC_QUAL_TAB8__A, 2);
5580*4882a593Smuzhiyun 	if (status < 0)
5581*4882a593Smuzhiyun 		goto error;
5582*4882a593Smuzhiyun 	status = write16(state, QAM_LC_QUAL_TAB9__A, 2);
5583*4882a593Smuzhiyun 	if (status < 0)
5584*4882a593Smuzhiyun 		goto error;
5585*4882a593Smuzhiyun 	status = write16(state, QAM_LC_QUAL_TAB10__A, 2);
5586*4882a593Smuzhiyun 	if (status < 0)
5587*4882a593Smuzhiyun 		goto error;
5588*4882a593Smuzhiyun 	status = write16(state, QAM_LC_QUAL_TAB12__A, 2);
5589*4882a593Smuzhiyun 	if (status < 0)
5590*4882a593Smuzhiyun 		goto error;
5591*4882a593Smuzhiyun 	status = write16(state, QAM_LC_QUAL_TAB15__A, 3);
5592*4882a593Smuzhiyun 	if (status < 0)
5593*4882a593Smuzhiyun 		goto error;
5594*4882a593Smuzhiyun 	status = write16(state, QAM_LC_QUAL_TAB16__A, 3);
5595*4882a593Smuzhiyun 	if (status < 0)
5596*4882a593Smuzhiyun 		goto error;
5597*4882a593Smuzhiyun 	status = write16(state, QAM_LC_QUAL_TAB20__A, 4);
5598*4882a593Smuzhiyun 	if (status < 0)
5599*4882a593Smuzhiyun 		goto error;
5600*4882a593Smuzhiyun 	status = write16(state, QAM_LC_QUAL_TAB25__A, 4);
5601*4882a593Smuzhiyun 	if (status < 0)
5602*4882a593Smuzhiyun 		goto error;
5603*4882a593Smuzhiyun 
5604*4882a593Smuzhiyun 	/* Mirroring, QAM-block starting point not inverted */
5605*4882a593Smuzhiyun 	status = write16(state, QAM_SY_SP_INV__A,
5606*4882a593Smuzhiyun 			 QAM_SY_SP_INV_SPECTRUM_INV_DIS);
5607*4882a593Smuzhiyun 	if (status < 0)
5608*4882a593Smuzhiyun 		goto error;
5609*4882a593Smuzhiyun 
5610*4882a593Smuzhiyun 	/* Halt SCU to enable safe non-atomic accesses */
5611*4882a593Smuzhiyun 	status = write16(state, SCU_COMM_EXEC__A, SCU_COMM_EXEC_HOLD);
5612*4882a593Smuzhiyun 	if (status < 0)
5613*4882a593Smuzhiyun 		goto error;
5614*4882a593Smuzhiyun 
5615*4882a593Smuzhiyun 	/* STEP 4: modulation specific setup */
5616*4882a593Smuzhiyun 	switch (state->props.modulation) {
5617*4882a593Smuzhiyun 	case QAM_16:
5618*4882a593Smuzhiyun 		status = set_qam16(state);
5619*4882a593Smuzhiyun 		break;
5620*4882a593Smuzhiyun 	case QAM_32:
5621*4882a593Smuzhiyun 		status = set_qam32(state);
5622*4882a593Smuzhiyun 		break;
5623*4882a593Smuzhiyun 	case QAM_AUTO:
5624*4882a593Smuzhiyun 	case QAM_64:
5625*4882a593Smuzhiyun 		status = set_qam64(state);
5626*4882a593Smuzhiyun 		break;
5627*4882a593Smuzhiyun 	case QAM_128:
5628*4882a593Smuzhiyun 		status = set_qam128(state);
5629*4882a593Smuzhiyun 		break;
5630*4882a593Smuzhiyun 	case QAM_256:
5631*4882a593Smuzhiyun 		status = set_qam256(state);
5632*4882a593Smuzhiyun 		break;
5633*4882a593Smuzhiyun 	default:
5634*4882a593Smuzhiyun 		status = -EINVAL;
5635*4882a593Smuzhiyun 		break;
5636*4882a593Smuzhiyun 	}
5637*4882a593Smuzhiyun 	if (status < 0)
5638*4882a593Smuzhiyun 		goto error;
5639*4882a593Smuzhiyun 
5640*4882a593Smuzhiyun 	/* Activate SCU to enable SCU commands */
5641*4882a593Smuzhiyun 	status = write16(state, SCU_COMM_EXEC__A, SCU_COMM_EXEC_ACTIVE);
5642*4882a593Smuzhiyun 	if (status < 0)
5643*4882a593Smuzhiyun 		goto error;
5644*4882a593Smuzhiyun 
5645*4882a593Smuzhiyun 	/* Re-configure MPEG output, requires knowledge of channel bitrate */
5646*4882a593Smuzhiyun 	/* extAttr->currentChannel.modulation = channel->modulation; */
5647*4882a593Smuzhiyun 	/* extAttr->currentChannel.symbolrate    = channel->symbolrate; */
5648*4882a593Smuzhiyun 	status = mpegts_dto_setup(state, state->m_operation_mode);
5649*4882a593Smuzhiyun 	if (status < 0)
5650*4882a593Smuzhiyun 		goto error;
5651*4882a593Smuzhiyun 
5652*4882a593Smuzhiyun 	/* start processes */
5653*4882a593Smuzhiyun 	status = mpegts_start(state);
5654*4882a593Smuzhiyun 	if (status < 0)
5655*4882a593Smuzhiyun 		goto error;
5656*4882a593Smuzhiyun 	status = write16(state, FEC_COMM_EXEC__A, FEC_COMM_EXEC_ACTIVE);
5657*4882a593Smuzhiyun 	if (status < 0)
5658*4882a593Smuzhiyun 		goto error;
5659*4882a593Smuzhiyun 	status = write16(state, QAM_COMM_EXEC__A, QAM_COMM_EXEC_ACTIVE);
5660*4882a593Smuzhiyun 	if (status < 0)
5661*4882a593Smuzhiyun 		goto error;
5662*4882a593Smuzhiyun 	status = write16(state, IQM_COMM_EXEC__A, IQM_COMM_EXEC_B_ACTIVE);
5663*4882a593Smuzhiyun 	if (status < 0)
5664*4882a593Smuzhiyun 		goto error;
5665*4882a593Smuzhiyun 
5666*4882a593Smuzhiyun 	/* STEP 5: start QAM demodulator (starts FEC, QAM and IQM HW) */
5667*4882a593Smuzhiyun 	status = scu_command(state, SCU_RAM_COMMAND_STANDARD_QAM
5668*4882a593Smuzhiyun 			     | SCU_RAM_COMMAND_CMD_DEMOD_START,
5669*4882a593Smuzhiyun 			     0, NULL, 1, &cmd_result);
5670*4882a593Smuzhiyun 	if (status < 0)
5671*4882a593Smuzhiyun 		goto error;
5672*4882a593Smuzhiyun 
5673*4882a593Smuzhiyun 	/* update global DRXK data container */
5674*4882a593Smuzhiyun /*?     extAttr->qamInterleaveMode = DRXK_QAM_I12_J17; */
5675*4882a593Smuzhiyun 
5676*4882a593Smuzhiyun error:
5677*4882a593Smuzhiyun 	if (status < 0)
5678*4882a593Smuzhiyun 		pr_err("Error %d on %s\n", status, __func__);
5679*4882a593Smuzhiyun 	return status;
5680*4882a593Smuzhiyun }
5681*4882a593Smuzhiyun 
set_qam_standard(struct drxk_state * state,enum operation_mode o_mode)5682*4882a593Smuzhiyun static int set_qam_standard(struct drxk_state *state,
5683*4882a593Smuzhiyun 			  enum operation_mode o_mode)
5684*4882a593Smuzhiyun {
5685*4882a593Smuzhiyun 	int status;
5686*4882a593Smuzhiyun #ifdef DRXK_QAM_TAPS
5687*4882a593Smuzhiyun #define DRXK_QAMA_TAPS_SELECT
5688*4882a593Smuzhiyun #include "drxk_filters.h"
5689*4882a593Smuzhiyun #undef DRXK_QAMA_TAPS_SELECT
5690*4882a593Smuzhiyun #endif
5691*4882a593Smuzhiyun 
5692*4882a593Smuzhiyun 	dprintk(1, "\n");
5693*4882a593Smuzhiyun 
5694*4882a593Smuzhiyun 	/* added antenna switch */
5695*4882a593Smuzhiyun 	switch_antenna_to_qam(state);
5696*4882a593Smuzhiyun 
5697*4882a593Smuzhiyun 	/* Ensure correct power-up mode */
5698*4882a593Smuzhiyun 	status = power_up_qam(state);
5699*4882a593Smuzhiyun 	if (status < 0)
5700*4882a593Smuzhiyun 		goto error;
5701*4882a593Smuzhiyun 	/* Reset QAM block */
5702*4882a593Smuzhiyun 	status = qam_reset_qam(state);
5703*4882a593Smuzhiyun 	if (status < 0)
5704*4882a593Smuzhiyun 		goto error;
5705*4882a593Smuzhiyun 
5706*4882a593Smuzhiyun 	/* Setup IQM */
5707*4882a593Smuzhiyun 
5708*4882a593Smuzhiyun 	status = write16(state, IQM_COMM_EXEC__A, IQM_COMM_EXEC_B_STOP);
5709*4882a593Smuzhiyun 	if (status < 0)
5710*4882a593Smuzhiyun 		goto error;
5711*4882a593Smuzhiyun 	status = write16(state, IQM_AF_AMUX__A, IQM_AF_AMUX_SIGNAL2ADC);
5712*4882a593Smuzhiyun 	if (status < 0)
5713*4882a593Smuzhiyun 		goto error;
5714*4882a593Smuzhiyun 
5715*4882a593Smuzhiyun 	/* Upload IQM Channel Filter settings by
5716*4882a593Smuzhiyun 		boot loader from ROM table */
5717*4882a593Smuzhiyun 	switch (o_mode) {
5718*4882a593Smuzhiyun 	case OM_QAM_ITU_A:
5719*4882a593Smuzhiyun 		status = bl_chain_cmd(state, DRXK_BL_ROM_OFFSET_TAPS_ITU_A,
5720*4882a593Smuzhiyun 				      DRXK_BLCC_NR_ELEMENTS_TAPS,
5721*4882a593Smuzhiyun 			DRXK_BLC_TIMEOUT);
5722*4882a593Smuzhiyun 		break;
5723*4882a593Smuzhiyun 	case OM_QAM_ITU_C:
5724*4882a593Smuzhiyun 		status = bl_direct_cmd(state, IQM_CF_TAP_RE0__A,
5725*4882a593Smuzhiyun 				       DRXK_BL_ROM_OFFSET_TAPS_ITU_C,
5726*4882a593Smuzhiyun 				       DRXK_BLDC_NR_ELEMENTS_TAPS,
5727*4882a593Smuzhiyun 				       DRXK_BLC_TIMEOUT);
5728*4882a593Smuzhiyun 		if (status < 0)
5729*4882a593Smuzhiyun 			goto error;
5730*4882a593Smuzhiyun 		status = bl_direct_cmd(state,
5731*4882a593Smuzhiyun 				       IQM_CF_TAP_IM0__A,
5732*4882a593Smuzhiyun 				       DRXK_BL_ROM_OFFSET_TAPS_ITU_C,
5733*4882a593Smuzhiyun 				       DRXK_BLDC_NR_ELEMENTS_TAPS,
5734*4882a593Smuzhiyun 				       DRXK_BLC_TIMEOUT);
5735*4882a593Smuzhiyun 		break;
5736*4882a593Smuzhiyun 	default:
5737*4882a593Smuzhiyun 		status = -EINVAL;
5738*4882a593Smuzhiyun 	}
5739*4882a593Smuzhiyun 	if (status < 0)
5740*4882a593Smuzhiyun 		goto error;
5741*4882a593Smuzhiyun 
5742*4882a593Smuzhiyun 	status = write16(state, IQM_CF_OUT_ENA__A, 1 << IQM_CF_OUT_ENA_QAM__B);
5743*4882a593Smuzhiyun 	if (status < 0)
5744*4882a593Smuzhiyun 		goto error;
5745*4882a593Smuzhiyun 	status = write16(state, IQM_CF_SYMMETRIC__A, 0);
5746*4882a593Smuzhiyun 	if (status < 0)
5747*4882a593Smuzhiyun 		goto error;
5748*4882a593Smuzhiyun 	status = write16(state, IQM_CF_MIDTAP__A,
5749*4882a593Smuzhiyun 		     ((1 << IQM_CF_MIDTAP_RE__B) | (1 << IQM_CF_MIDTAP_IM__B)));
5750*4882a593Smuzhiyun 	if (status < 0)
5751*4882a593Smuzhiyun 		goto error;
5752*4882a593Smuzhiyun 
5753*4882a593Smuzhiyun 	status = write16(state, IQM_RC_STRETCH__A, 21);
5754*4882a593Smuzhiyun 	if (status < 0)
5755*4882a593Smuzhiyun 		goto error;
5756*4882a593Smuzhiyun 	status = write16(state, IQM_AF_CLP_LEN__A, 0);
5757*4882a593Smuzhiyun 	if (status < 0)
5758*4882a593Smuzhiyun 		goto error;
5759*4882a593Smuzhiyun 	status = write16(state, IQM_AF_CLP_TH__A, 448);
5760*4882a593Smuzhiyun 	if (status < 0)
5761*4882a593Smuzhiyun 		goto error;
5762*4882a593Smuzhiyun 	status = write16(state, IQM_AF_SNS_LEN__A, 0);
5763*4882a593Smuzhiyun 	if (status < 0)
5764*4882a593Smuzhiyun 		goto error;
5765*4882a593Smuzhiyun 	status = write16(state, IQM_CF_POW_MEAS_LEN__A, 0);
5766*4882a593Smuzhiyun 	if (status < 0)
5767*4882a593Smuzhiyun 		goto error;
5768*4882a593Smuzhiyun 
5769*4882a593Smuzhiyun 	status = write16(state, IQM_FS_ADJ_SEL__A, 1);
5770*4882a593Smuzhiyun 	if (status < 0)
5771*4882a593Smuzhiyun 		goto error;
5772*4882a593Smuzhiyun 	status = write16(state, IQM_RC_ADJ_SEL__A, 1);
5773*4882a593Smuzhiyun 	if (status < 0)
5774*4882a593Smuzhiyun 		goto error;
5775*4882a593Smuzhiyun 	status = write16(state, IQM_CF_ADJ_SEL__A, 1);
5776*4882a593Smuzhiyun 	if (status < 0)
5777*4882a593Smuzhiyun 		goto error;
5778*4882a593Smuzhiyun 	status = write16(state, IQM_AF_UPD_SEL__A, 0);
5779*4882a593Smuzhiyun 	if (status < 0)
5780*4882a593Smuzhiyun 		goto error;
5781*4882a593Smuzhiyun 
5782*4882a593Smuzhiyun 	/* IQM Impulse Noise Processing Unit */
5783*4882a593Smuzhiyun 	status = write16(state, IQM_CF_CLP_VAL__A, 500);
5784*4882a593Smuzhiyun 	if (status < 0)
5785*4882a593Smuzhiyun 		goto error;
5786*4882a593Smuzhiyun 	status = write16(state, IQM_CF_DATATH__A, 1000);
5787*4882a593Smuzhiyun 	if (status < 0)
5788*4882a593Smuzhiyun 		goto error;
5789*4882a593Smuzhiyun 	status = write16(state, IQM_CF_BYPASSDET__A, 1);
5790*4882a593Smuzhiyun 	if (status < 0)
5791*4882a593Smuzhiyun 		goto error;
5792*4882a593Smuzhiyun 	status = write16(state, IQM_CF_DET_LCT__A, 0);
5793*4882a593Smuzhiyun 	if (status < 0)
5794*4882a593Smuzhiyun 		goto error;
5795*4882a593Smuzhiyun 	status = write16(state, IQM_CF_WND_LEN__A, 1);
5796*4882a593Smuzhiyun 	if (status < 0)
5797*4882a593Smuzhiyun 		goto error;
5798*4882a593Smuzhiyun 	status = write16(state, IQM_CF_PKDTH__A, 1);
5799*4882a593Smuzhiyun 	if (status < 0)
5800*4882a593Smuzhiyun 		goto error;
5801*4882a593Smuzhiyun 	status = write16(state, IQM_AF_INC_BYPASS__A, 1);
5802*4882a593Smuzhiyun 	if (status < 0)
5803*4882a593Smuzhiyun 		goto error;
5804*4882a593Smuzhiyun 
5805*4882a593Smuzhiyun 	/* turn on IQMAF. Must be done before setAgc**() */
5806*4882a593Smuzhiyun 	status = set_iqm_af(state, true);
5807*4882a593Smuzhiyun 	if (status < 0)
5808*4882a593Smuzhiyun 		goto error;
5809*4882a593Smuzhiyun 	status = write16(state, IQM_AF_START_LOCK__A, 0x01);
5810*4882a593Smuzhiyun 	if (status < 0)
5811*4882a593Smuzhiyun 		goto error;
5812*4882a593Smuzhiyun 
5813*4882a593Smuzhiyun 	/* IQM will not be reset from here, sync ADC and update/init AGC */
5814*4882a593Smuzhiyun 	status = adc_synchronization(state);
5815*4882a593Smuzhiyun 	if (status < 0)
5816*4882a593Smuzhiyun 		goto error;
5817*4882a593Smuzhiyun 
5818*4882a593Smuzhiyun 	/* Set the FSM step period */
5819*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_QAM_FSM_STEP_PERIOD__A, 2000);
5820*4882a593Smuzhiyun 	if (status < 0)
5821*4882a593Smuzhiyun 		goto error;
5822*4882a593Smuzhiyun 
5823*4882a593Smuzhiyun 	/* Halt SCU to enable safe non-atomic accesses */
5824*4882a593Smuzhiyun 	status = write16(state, SCU_COMM_EXEC__A, SCU_COMM_EXEC_HOLD);
5825*4882a593Smuzhiyun 	if (status < 0)
5826*4882a593Smuzhiyun 		goto error;
5827*4882a593Smuzhiyun 
5828*4882a593Smuzhiyun 	/* No more resets of the IQM, current standard correctly set =>
5829*4882a593Smuzhiyun 		now AGCs can be configured. */
5830*4882a593Smuzhiyun 
5831*4882a593Smuzhiyun 	status = init_agc(state, true);
5832*4882a593Smuzhiyun 	if (status < 0)
5833*4882a593Smuzhiyun 		goto error;
5834*4882a593Smuzhiyun 	status = set_pre_saw(state, &(state->m_qam_pre_saw_cfg));
5835*4882a593Smuzhiyun 	if (status < 0)
5836*4882a593Smuzhiyun 		goto error;
5837*4882a593Smuzhiyun 
5838*4882a593Smuzhiyun 	/* Configure AGC's */
5839*4882a593Smuzhiyun 	status = set_agc_rf(state, &(state->m_qam_rf_agc_cfg), true);
5840*4882a593Smuzhiyun 	if (status < 0)
5841*4882a593Smuzhiyun 		goto error;
5842*4882a593Smuzhiyun 	status = set_agc_if(state, &(state->m_qam_if_agc_cfg), true);
5843*4882a593Smuzhiyun 	if (status < 0)
5844*4882a593Smuzhiyun 		goto error;
5845*4882a593Smuzhiyun 
5846*4882a593Smuzhiyun 	/* Activate SCU to enable SCU commands */
5847*4882a593Smuzhiyun 	status = write16(state, SCU_COMM_EXEC__A, SCU_COMM_EXEC_ACTIVE);
5848*4882a593Smuzhiyun error:
5849*4882a593Smuzhiyun 	if (status < 0)
5850*4882a593Smuzhiyun 		pr_err("Error %d on %s\n", status, __func__);
5851*4882a593Smuzhiyun 	return status;
5852*4882a593Smuzhiyun }
5853*4882a593Smuzhiyun 
write_gpio(struct drxk_state * state)5854*4882a593Smuzhiyun static int write_gpio(struct drxk_state *state)
5855*4882a593Smuzhiyun {
5856*4882a593Smuzhiyun 	int status;
5857*4882a593Smuzhiyun 	u16 value = 0;
5858*4882a593Smuzhiyun 
5859*4882a593Smuzhiyun 	dprintk(1, "\n");
5860*4882a593Smuzhiyun 	/* stop lock indicator process */
5861*4882a593Smuzhiyun 	status = write16(state, SCU_RAM_GPIO__A,
5862*4882a593Smuzhiyun 			 SCU_RAM_GPIO_HW_LOCK_IND_DISABLE);
5863*4882a593Smuzhiyun 	if (status < 0)
5864*4882a593Smuzhiyun 		goto error;
5865*4882a593Smuzhiyun 
5866*4882a593Smuzhiyun 	/*  Write magic word to enable pdr reg write               */
5867*4882a593Smuzhiyun 	status = write16(state, SIO_TOP_COMM_KEY__A, SIO_TOP_COMM_KEY_KEY);
5868*4882a593Smuzhiyun 	if (status < 0)
5869*4882a593Smuzhiyun 		goto error;
5870*4882a593Smuzhiyun 
5871*4882a593Smuzhiyun 	if (state->m_has_sawsw) {
5872*4882a593Smuzhiyun 		if (state->uio_mask & 0x0001) { /* UIO-1 */
5873*4882a593Smuzhiyun 			/* write to io pad configuration register - output mode */
5874*4882a593Smuzhiyun 			status = write16(state, SIO_PDR_SMA_TX_CFG__A,
5875*4882a593Smuzhiyun 					 state->m_gpio_cfg);
5876*4882a593Smuzhiyun 			if (status < 0)
5877*4882a593Smuzhiyun 				goto error;
5878*4882a593Smuzhiyun 
5879*4882a593Smuzhiyun 			/* use corresponding bit in io data output registar */
5880*4882a593Smuzhiyun 			status = read16(state, SIO_PDR_UIO_OUT_LO__A, &value);
5881*4882a593Smuzhiyun 			if (status < 0)
5882*4882a593Smuzhiyun 				goto error;
5883*4882a593Smuzhiyun 			if ((state->m_gpio & 0x0001) == 0)
5884*4882a593Smuzhiyun 				value &= 0x7FFF;	/* write zero to 15th bit - 1st UIO */
5885*4882a593Smuzhiyun 			else
5886*4882a593Smuzhiyun 				value |= 0x8000;	/* write one to 15th bit - 1st UIO */
5887*4882a593Smuzhiyun 			/* write back to io data output register */
5888*4882a593Smuzhiyun 			status = write16(state, SIO_PDR_UIO_OUT_LO__A, value);
5889*4882a593Smuzhiyun 			if (status < 0)
5890*4882a593Smuzhiyun 				goto error;
5891*4882a593Smuzhiyun 		}
5892*4882a593Smuzhiyun 		if (state->uio_mask & 0x0002) { /* UIO-2 */
5893*4882a593Smuzhiyun 			/* write to io pad configuration register - output mode */
5894*4882a593Smuzhiyun 			status = write16(state, SIO_PDR_SMA_RX_CFG__A,
5895*4882a593Smuzhiyun 					 state->m_gpio_cfg);
5896*4882a593Smuzhiyun 			if (status < 0)
5897*4882a593Smuzhiyun 				goto error;
5898*4882a593Smuzhiyun 
5899*4882a593Smuzhiyun 			/* use corresponding bit in io data output registar */
5900*4882a593Smuzhiyun 			status = read16(state, SIO_PDR_UIO_OUT_LO__A, &value);
5901*4882a593Smuzhiyun 			if (status < 0)
5902*4882a593Smuzhiyun 				goto error;
5903*4882a593Smuzhiyun 			if ((state->m_gpio & 0x0002) == 0)
5904*4882a593Smuzhiyun 				value &= 0xBFFF;	/* write zero to 14th bit - 2st UIO */
5905*4882a593Smuzhiyun 			else
5906*4882a593Smuzhiyun 				value |= 0x4000;	/* write one to 14th bit - 2st UIO */
5907*4882a593Smuzhiyun 			/* write back to io data output register */
5908*4882a593Smuzhiyun 			status = write16(state, SIO_PDR_UIO_OUT_LO__A, value);
5909*4882a593Smuzhiyun 			if (status < 0)
5910*4882a593Smuzhiyun 				goto error;
5911*4882a593Smuzhiyun 		}
5912*4882a593Smuzhiyun 		if (state->uio_mask & 0x0004) { /* UIO-3 */
5913*4882a593Smuzhiyun 			/* write to io pad configuration register - output mode */
5914*4882a593Smuzhiyun 			status = write16(state, SIO_PDR_GPIO_CFG__A,
5915*4882a593Smuzhiyun 					 state->m_gpio_cfg);
5916*4882a593Smuzhiyun 			if (status < 0)
5917*4882a593Smuzhiyun 				goto error;
5918*4882a593Smuzhiyun 
5919*4882a593Smuzhiyun 			/* use corresponding bit in io data output registar */
5920*4882a593Smuzhiyun 			status = read16(state, SIO_PDR_UIO_OUT_LO__A, &value);
5921*4882a593Smuzhiyun 			if (status < 0)
5922*4882a593Smuzhiyun 				goto error;
5923*4882a593Smuzhiyun 			if ((state->m_gpio & 0x0004) == 0)
5924*4882a593Smuzhiyun 				value &= 0xFFFB;            /* write zero to 2nd bit - 3rd UIO */
5925*4882a593Smuzhiyun 			else
5926*4882a593Smuzhiyun 				value |= 0x0004;            /* write one to 2nd bit - 3rd UIO */
5927*4882a593Smuzhiyun 			/* write back to io data output register */
5928*4882a593Smuzhiyun 			status = write16(state, SIO_PDR_UIO_OUT_LO__A, value);
5929*4882a593Smuzhiyun 			if (status < 0)
5930*4882a593Smuzhiyun 				goto error;
5931*4882a593Smuzhiyun 		}
5932*4882a593Smuzhiyun 	}
5933*4882a593Smuzhiyun 	/*  Write magic word to disable pdr reg write               */
5934*4882a593Smuzhiyun 	status = write16(state, SIO_TOP_COMM_KEY__A, 0x0000);
5935*4882a593Smuzhiyun error:
5936*4882a593Smuzhiyun 	if (status < 0)
5937*4882a593Smuzhiyun 		pr_err("Error %d on %s\n", status, __func__);
5938*4882a593Smuzhiyun 	return status;
5939*4882a593Smuzhiyun }
5940*4882a593Smuzhiyun 
switch_antenna_to_qam(struct drxk_state * state)5941*4882a593Smuzhiyun static int switch_antenna_to_qam(struct drxk_state *state)
5942*4882a593Smuzhiyun {
5943*4882a593Smuzhiyun 	int status = 0;
5944*4882a593Smuzhiyun 	bool gpio_state;
5945*4882a593Smuzhiyun 
5946*4882a593Smuzhiyun 	dprintk(1, "\n");
5947*4882a593Smuzhiyun 
5948*4882a593Smuzhiyun 	if (!state->antenna_gpio)
5949*4882a593Smuzhiyun 		return 0;
5950*4882a593Smuzhiyun 
5951*4882a593Smuzhiyun 	gpio_state = state->m_gpio & state->antenna_gpio;
5952*4882a593Smuzhiyun 
5953*4882a593Smuzhiyun 	if (state->antenna_dvbt ^ gpio_state) {
5954*4882a593Smuzhiyun 		/* Antenna is on DVB-T mode. Switch */
5955*4882a593Smuzhiyun 		if (state->antenna_dvbt)
5956*4882a593Smuzhiyun 			state->m_gpio &= ~state->antenna_gpio;
5957*4882a593Smuzhiyun 		else
5958*4882a593Smuzhiyun 			state->m_gpio |= state->antenna_gpio;
5959*4882a593Smuzhiyun 		status = write_gpio(state);
5960*4882a593Smuzhiyun 	}
5961*4882a593Smuzhiyun 	if (status < 0)
5962*4882a593Smuzhiyun 		pr_err("Error %d on %s\n", status, __func__);
5963*4882a593Smuzhiyun 	return status;
5964*4882a593Smuzhiyun }
5965*4882a593Smuzhiyun 
switch_antenna_to_dvbt(struct drxk_state * state)5966*4882a593Smuzhiyun static int switch_antenna_to_dvbt(struct drxk_state *state)
5967*4882a593Smuzhiyun {
5968*4882a593Smuzhiyun 	int status = 0;
5969*4882a593Smuzhiyun 	bool gpio_state;
5970*4882a593Smuzhiyun 
5971*4882a593Smuzhiyun 	dprintk(1, "\n");
5972*4882a593Smuzhiyun 
5973*4882a593Smuzhiyun 	if (!state->antenna_gpio)
5974*4882a593Smuzhiyun 		return 0;
5975*4882a593Smuzhiyun 
5976*4882a593Smuzhiyun 	gpio_state = state->m_gpio & state->antenna_gpio;
5977*4882a593Smuzhiyun 
5978*4882a593Smuzhiyun 	if (!(state->antenna_dvbt ^ gpio_state)) {
5979*4882a593Smuzhiyun 		/* Antenna is on DVB-C mode. Switch */
5980*4882a593Smuzhiyun 		if (state->antenna_dvbt)
5981*4882a593Smuzhiyun 			state->m_gpio |= state->antenna_gpio;
5982*4882a593Smuzhiyun 		else
5983*4882a593Smuzhiyun 			state->m_gpio &= ~state->antenna_gpio;
5984*4882a593Smuzhiyun 		status = write_gpio(state);
5985*4882a593Smuzhiyun 	}
5986*4882a593Smuzhiyun 	if (status < 0)
5987*4882a593Smuzhiyun 		pr_err("Error %d on %s\n", status, __func__);
5988*4882a593Smuzhiyun 	return status;
5989*4882a593Smuzhiyun }
5990*4882a593Smuzhiyun 
5991*4882a593Smuzhiyun 
power_down_device(struct drxk_state * state)5992*4882a593Smuzhiyun static int power_down_device(struct drxk_state *state)
5993*4882a593Smuzhiyun {
5994*4882a593Smuzhiyun 	/* Power down to requested mode */
5995*4882a593Smuzhiyun 	/* Backup some register settings */
5996*4882a593Smuzhiyun 	/* Set pins with possible pull-ups connected to them in input mode */
5997*4882a593Smuzhiyun 	/* Analog power down */
5998*4882a593Smuzhiyun 	/* ADC power down */
5999*4882a593Smuzhiyun 	/* Power down device */
6000*4882a593Smuzhiyun 	int status;
6001*4882a593Smuzhiyun 
6002*4882a593Smuzhiyun 	dprintk(1, "\n");
6003*4882a593Smuzhiyun 	if (state->m_b_p_down_open_bridge) {
6004*4882a593Smuzhiyun 		/* Open I2C bridge before power down of DRXK */
6005*4882a593Smuzhiyun 		status = ConfigureI2CBridge(state, true);
6006*4882a593Smuzhiyun 		if (status < 0)
6007*4882a593Smuzhiyun 			goto error;
6008*4882a593Smuzhiyun 	}
6009*4882a593Smuzhiyun 	/* driver 0.9.0 */
6010*4882a593Smuzhiyun 	status = dvbt_enable_ofdm_token_ring(state, false);
6011*4882a593Smuzhiyun 	if (status < 0)
6012*4882a593Smuzhiyun 		goto error;
6013*4882a593Smuzhiyun 
6014*4882a593Smuzhiyun 	status = write16(state, SIO_CC_PWD_MODE__A,
6015*4882a593Smuzhiyun 			 SIO_CC_PWD_MODE_LEVEL_CLOCK);
6016*4882a593Smuzhiyun 	if (status < 0)
6017*4882a593Smuzhiyun 		goto error;
6018*4882a593Smuzhiyun 	status = write16(state, SIO_CC_UPDATE__A, SIO_CC_UPDATE_KEY);
6019*4882a593Smuzhiyun 	if (status < 0)
6020*4882a593Smuzhiyun 		goto error;
6021*4882a593Smuzhiyun 	state->m_hi_cfg_ctrl |= SIO_HI_RA_RAM_PAR_5_CFG_SLEEP_ZZZ;
6022*4882a593Smuzhiyun 	status = hi_cfg_command(state);
6023*4882a593Smuzhiyun error:
6024*4882a593Smuzhiyun 	if (status < 0)
6025*4882a593Smuzhiyun 		pr_err("Error %d on %s\n", status, __func__);
6026*4882a593Smuzhiyun 
6027*4882a593Smuzhiyun 	return status;
6028*4882a593Smuzhiyun }
6029*4882a593Smuzhiyun 
init_drxk(struct drxk_state * state)6030*4882a593Smuzhiyun static int init_drxk(struct drxk_state *state)
6031*4882a593Smuzhiyun {
6032*4882a593Smuzhiyun 	int status = 0, n = 0;
6033*4882a593Smuzhiyun 	enum drx_power_mode power_mode = DRXK_POWER_DOWN_OFDM;
6034*4882a593Smuzhiyun 	u16 driver_version;
6035*4882a593Smuzhiyun 
6036*4882a593Smuzhiyun 	dprintk(1, "\n");
6037*4882a593Smuzhiyun 	if (state->m_drxk_state == DRXK_UNINITIALIZED) {
6038*4882a593Smuzhiyun 		drxk_i2c_lock(state);
6039*4882a593Smuzhiyun 		status = power_up_device(state);
6040*4882a593Smuzhiyun 		if (status < 0)
6041*4882a593Smuzhiyun 			goto error;
6042*4882a593Smuzhiyun 		status = drxx_open(state);
6043*4882a593Smuzhiyun 		if (status < 0)
6044*4882a593Smuzhiyun 			goto error;
6045*4882a593Smuzhiyun 		/* Soft reset of OFDM-, sys- and osc-clockdomain */
6046*4882a593Smuzhiyun 		status = write16(state, SIO_CC_SOFT_RST__A,
6047*4882a593Smuzhiyun 				 SIO_CC_SOFT_RST_OFDM__M
6048*4882a593Smuzhiyun 				 | SIO_CC_SOFT_RST_SYS__M
6049*4882a593Smuzhiyun 				 | SIO_CC_SOFT_RST_OSC__M);
6050*4882a593Smuzhiyun 		if (status < 0)
6051*4882a593Smuzhiyun 			goto error;
6052*4882a593Smuzhiyun 		status = write16(state, SIO_CC_UPDATE__A, SIO_CC_UPDATE_KEY);
6053*4882a593Smuzhiyun 		if (status < 0)
6054*4882a593Smuzhiyun 			goto error;
6055*4882a593Smuzhiyun 		/*
6056*4882a593Smuzhiyun 		 * TODO is this needed? If yes, how much delay in
6057*4882a593Smuzhiyun 		 * worst case scenario
6058*4882a593Smuzhiyun 		 */
6059*4882a593Smuzhiyun 		usleep_range(1000, 2000);
6060*4882a593Smuzhiyun 		state->m_drxk_a3_patch_code = true;
6061*4882a593Smuzhiyun 		status = get_device_capabilities(state);
6062*4882a593Smuzhiyun 		if (status < 0)
6063*4882a593Smuzhiyun 			goto error;
6064*4882a593Smuzhiyun 
6065*4882a593Smuzhiyun 		/* Bridge delay, uses oscilator clock */
6066*4882a593Smuzhiyun 		/* Delay = (delay (nano seconds) * oscclk (kHz))/ 1000 */
6067*4882a593Smuzhiyun 		/* SDA brdige delay */
6068*4882a593Smuzhiyun 		state->m_hi_cfg_bridge_delay =
6069*4882a593Smuzhiyun 			(u16) ((state->m_osc_clock_freq / 1000) *
6070*4882a593Smuzhiyun 				HI_I2C_BRIDGE_DELAY) / 1000;
6071*4882a593Smuzhiyun 		/* Clipping */
6072*4882a593Smuzhiyun 		if (state->m_hi_cfg_bridge_delay >
6073*4882a593Smuzhiyun 			SIO_HI_RA_RAM_PAR_3_CFG_DBL_SDA__M) {
6074*4882a593Smuzhiyun 			state->m_hi_cfg_bridge_delay =
6075*4882a593Smuzhiyun 				SIO_HI_RA_RAM_PAR_3_CFG_DBL_SDA__M;
6076*4882a593Smuzhiyun 		}
6077*4882a593Smuzhiyun 		/* SCL bridge delay, same as SDA for now */
6078*4882a593Smuzhiyun 		state->m_hi_cfg_bridge_delay +=
6079*4882a593Smuzhiyun 			state->m_hi_cfg_bridge_delay <<
6080*4882a593Smuzhiyun 			SIO_HI_RA_RAM_PAR_3_CFG_DBL_SCL__B;
6081*4882a593Smuzhiyun 
6082*4882a593Smuzhiyun 		status = init_hi(state);
6083*4882a593Smuzhiyun 		if (status < 0)
6084*4882a593Smuzhiyun 			goto error;
6085*4882a593Smuzhiyun 		/* disable various processes */
6086*4882a593Smuzhiyun #if NOA1ROM
6087*4882a593Smuzhiyun 		if (!(state->m_DRXK_A1_ROM_CODE)
6088*4882a593Smuzhiyun 			&& !(state->m_DRXK_A2_ROM_CODE))
6089*4882a593Smuzhiyun #endif
6090*4882a593Smuzhiyun 		{
6091*4882a593Smuzhiyun 			status = write16(state, SCU_RAM_GPIO__A,
6092*4882a593Smuzhiyun 					 SCU_RAM_GPIO_HW_LOCK_IND_DISABLE);
6093*4882a593Smuzhiyun 			if (status < 0)
6094*4882a593Smuzhiyun 				goto error;
6095*4882a593Smuzhiyun 		}
6096*4882a593Smuzhiyun 
6097*4882a593Smuzhiyun 		/* disable MPEG port */
6098*4882a593Smuzhiyun 		status = mpegts_disable(state);
6099*4882a593Smuzhiyun 		if (status < 0)
6100*4882a593Smuzhiyun 			goto error;
6101*4882a593Smuzhiyun 
6102*4882a593Smuzhiyun 		/* Stop AUD and SCU */
6103*4882a593Smuzhiyun 		status = write16(state, AUD_COMM_EXEC__A, AUD_COMM_EXEC_STOP);
6104*4882a593Smuzhiyun 		if (status < 0)
6105*4882a593Smuzhiyun 			goto error;
6106*4882a593Smuzhiyun 		status = write16(state, SCU_COMM_EXEC__A, SCU_COMM_EXEC_STOP);
6107*4882a593Smuzhiyun 		if (status < 0)
6108*4882a593Smuzhiyun 			goto error;
6109*4882a593Smuzhiyun 
6110*4882a593Smuzhiyun 		/* enable token-ring bus through OFDM block for possible ucode upload */
6111*4882a593Smuzhiyun 		status = write16(state, SIO_OFDM_SH_OFDM_RING_ENABLE__A,
6112*4882a593Smuzhiyun 				 SIO_OFDM_SH_OFDM_RING_ENABLE_ON);
6113*4882a593Smuzhiyun 		if (status < 0)
6114*4882a593Smuzhiyun 			goto error;
6115*4882a593Smuzhiyun 
6116*4882a593Smuzhiyun 		/* include boot loader section */
6117*4882a593Smuzhiyun 		status = write16(state, SIO_BL_COMM_EXEC__A,
6118*4882a593Smuzhiyun 				 SIO_BL_COMM_EXEC_ACTIVE);
6119*4882a593Smuzhiyun 		if (status < 0)
6120*4882a593Smuzhiyun 			goto error;
6121*4882a593Smuzhiyun 		status = bl_chain_cmd(state, 0, 6, 100);
6122*4882a593Smuzhiyun 		if (status < 0)
6123*4882a593Smuzhiyun 			goto error;
6124*4882a593Smuzhiyun 
6125*4882a593Smuzhiyun 		if (state->fw) {
6126*4882a593Smuzhiyun 			status = download_microcode(state, state->fw->data,
6127*4882a593Smuzhiyun 						   state->fw->size);
6128*4882a593Smuzhiyun 			if (status < 0)
6129*4882a593Smuzhiyun 				goto error;
6130*4882a593Smuzhiyun 		}
6131*4882a593Smuzhiyun 
6132*4882a593Smuzhiyun 		/* disable token-ring bus through OFDM block for possible ucode upload */
6133*4882a593Smuzhiyun 		status = write16(state, SIO_OFDM_SH_OFDM_RING_ENABLE__A,
6134*4882a593Smuzhiyun 				 SIO_OFDM_SH_OFDM_RING_ENABLE_OFF);
6135*4882a593Smuzhiyun 		if (status < 0)
6136*4882a593Smuzhiyun 			goto error;
6137*4882a593Smuzhiyun 
6138*4882a593Smuzhiyun 		/* Run SCU for a little while to initialize microcode version numbers */
6139*4882a593Smuzhiyun 		status = write16(state, SCU_COMM_EXEC__A, SCU_COMM_EXEC_ACTIVE);
6140*4882a593Smuzhiyun 		if (status < 0)
6141*4882a593Smuzhiyun 			goto error;
6142*4882a593Smuzhiyun 		status = drxx_open(state);
6143*4882a593Smuzhiyun 		if (status < 0)
6144*4882a593Smuzhiyun 			goto error;
6145*4882a593Smuzhiyun 		/* added for test */
6146*4882a593Smuzhiyun 		msleep(30);
6147*4882a593Smuzhiyun 
6148*4882a593Smuzhiyun 		power_mode = DRXK_POWER_DOWN_OFDM;
6149*4882a593Smuzhiyun 		status = ctrl_power_mode(state, &power_mode);
6150*4882a593Smuzhiyun 		if (status < 0)
6151*4882a593Smuzhiyun 			goto error;
6152*4882a593Smuzhiyun 
6153*4882a593Smuzhiyun 		/* Stamp driver version number in SCU data RAM in BCD code
6154*4882a593Smuzhiyun 			Done to enable field application engineers to retrieve drxdriver version
6155*4882a593Smuzhiyun 			via I2C from SCU RAM.
6156*4882a593Smuzhiyun 			Not using SCU command interface for SCU register access since no
6157*4882a593Smuzhiyun 			microcode may be present.
6158*4882a593Smuzhiyun 			*/
6159*4882a593Smuzhiyun 		driver_version =
6160*4882a593Smuzhiyun 			(((DRXK_VERSION_MAJOR / 100) % 10) << 12) +
6161*4882a593Smuzhiyun 			(((DRXK_VERSION_MAJOR / 10) % 10) << 8) +
6162*4882a593Smuzhiyun 			((DRXK_VERSION_MAJOR % 10) << 4) +
6163*4882a593Smuzhiyun 			(DRXK_VERSION_MINOR % 10);
6164*4882a593Smuzhiyun 		status = write16(state, SCU_RAM_DRIVER_VER_HI__A,
6165*4882a593Smuzhiyun 				 driver_version);
6166*4882a593Smuzhiyun 		if (status < 0)
6167*4882a593Smuzhiyun 			goto error;
6168*4882a593Smuzhiyun 		driver_version =
6169*4882a593Smuzhiyun 			(((DRXK_VERSION_PATCH / 1000) % 10) << 12) +
6170*4882a593Smuzhiyun 			(((DRXK_VERSION_PATCH / 100) % 10) << 8) +
6171*4882a593Smuzhiyun 			(((DRXK_VERSION_PATCH / 10) % 10) << 4) +
6172*4882a593Smuzhiyun 			(DRXK_VERSION_PATCH % 10);
6173*4882a593Smuzhiyun 		status = write16(state, SCU_RAM_DRIVER_VER_LO__A,
6174*4882a593Smuzhiyun 				 driver_version);
6175*4882a593Smuzhiyun 		if (status < 0)
6176*4882a593Smuzhiyun 			goto error;
6177*4882a593Smuzhiyun 
6178*4882a593Smuzhiyun 		pr_info("DRXK driver version %d.%d.%d\n",
6179*4882a593Smuzhiyun 			DRXK_VERSION_MAJOR, DRXK_VERSION_MINOR,
6180*4882a593Smuzhiyun 			DRXK_VERSION_PATCH);
6181*4882a593Smuzhiyun 
6182*4882a593Smuzhiyun 		/*
6183*4882a593Smuzhiyun 		 * Dirty fix of default values for ROM/PATCH microcode
6184*4882a593Smuzhiyun 		 * Dirty because this fix makes it impossible to setup
6185*4882a593Smuzhiyun 		 * suitable values before calling DRX_Open. This solution
6186*4882a593Smuzhiyun 		 * requires changes to RF AGC speed to be done via the CTRL
6187*4882a593Smuzhiyun 		 * function after calling DRX_Open
6188*4882a593Smuzhiyun 		 */
6189*4882a593Smuzhiyun 
6190*4882a593Smuzhiyun 		/* m_dvbt_rf_agc_cfg.speed = 3; */
6191*4882a593Smuzhiyun 
6192*4882a593Smuzhiyun 		/* Reset driver debug flags to 0 */
6193*4882a593Smuzhiyun 		status = write16(state, SCU_RAM_DRIVER_DEBUG__A, 0);
6194*4882a593Smuzhiyun 		if (status < 0)
6195*4882a593Smuzhiyun 			goto error;
6196*4882a593Smuzhiyun 		/* driver 0.9.0 */
6197*4882a593Smuzhiyun 		/* Setup FEC OC:
6198*4882a593Smuzhiyun 			NOTE: No more full FEC resets allowed afterwards!! */
6199*4882a593Smuzhiyun 		status = write16(state, FEC_COMM_EXEC__A, FEC_COMM_EXEC_STOP);
6200*4882a593Smuzhiyun 		if (status < 0)
6201*4882a593Smuzhiyun 			goto error;
6202*4882a593Smuzhiyun 		/* MPEGTS functions are still the same */
6203*4882a593Smuzhiyun 		status = mpegts_dto_init(state);
6204*4882a593Smuzhiyun 		if (status < 0)
6205*4882a593Smuzhiyun 			goto error;
6206*4882a593Smuzhiyun 		status = mpegts_stop(state);
6207*4882a593Smuzhiyun 		if (status < 0)
6208*4882a593Smuzhiyun 			goto error;
6209*4882a593Smuzhiyun 		status = mpegts_configure_polarity(state);
6210*4882a593Smuzhiyun 		if (status < 0)
6211*4882a593Smuzhiyun 			goto error;
6212*4882a593Smuzhiyun 		status = mpegts_configure_pins(state, state->m_enable_mpeg_output);
6213*4882a593Smuzhiyun 		if (status < 0)
6214*4882a593Smuzhiyun 			goto error;
6215*4882a593Smuzhiyun 		/* added: configure GPIO */
6216*4882a593Smuzhiyun 		status = write_gpio(state);
6217*4882a593Smuzhiyun 		if (status < 0)
6218*4882a593Smuzhiyun 			goto error;
6219*4882a593Smuzhiyun 
6220*4882a593Smuzhiyun 		state->m_drxk_state = DRXK_STOPPED;
6221*4882a593Smuzhiyun 
6222*4882a593Smuzhiyun 		if (state->m_b_power_down) {
6223*4882a593Smuzhiyun 			status = power_down_device(state);
6224*4882a593Smuzhiyun 			if (status < 0)
6225*4882a593Smuzhiyun 				goto error;
6226*4882a593Smuzhiyun 			state->m_drxk_state = DRXK_POWERED_DOWN;
6227*4882a593Smuzhiyun 		} else
6228*4882a593Smuzhiyun 			state->m_drxk_state = DRXK_STOPPED;
6229*4882a593Smuzhiyun 
6230*4882a593Smuzhiyun 		/* Initialize the supported delivery systems */
6231*4882a593Smuzhiyun 		n = 0;
6232*4882a593Smuzhiyun 		if (state->m_has_dvbc) {
6233*4882a593Smuzhiyun 			state->frontend.ops.delsys[n++] = SYS_DVBC_ANNEX_A;
6234*4882a593Smuzhiyun 			state->frontend.ops.delsys[n++] = SYS_DVBC_ANNEX_C;
6235*4882a593Smuzhiyun 			strlcat(state->frontend.ops.info.name, " DVB-C",
6236*4882a593Smuzhiyun 				sizeof(state->frontend.ops.info.name));
6237*4882a593Smuzhiyun 		}
6238*4882a593Smuzhiyun 		if (state->m_has_dvbt) {
6239*4882a593Smuzhiyun 			state->frontend.ops.delsys[n++] = SYS_DVBT;
6240*4882a593Smuzhiyun 			strlcat(state->frontend.ops.info.name, " DVB-T",
6241*4882a593Smuzhiyun 				sizeof(state->frontend.ops.info.name));
6242*4882a593Smuzhiyun 		}
6243*4882a593Smuzhiyun 		drxk_i2c_unlock(state);
6244*4882a593Smuzhiyun 	}
6245*4882a593Smuzhiyun error:
6246*4882a593Smuzhiyun 	if (status < 0) {
6247*4882a593Smuzhiyun 		state->m_drxk_state = DRXK_NO_DEV;
6248*4882a593Smuzhiyun 		drxk_i2c_unlock(state);
6249*4882a593Smuzhiyun 		pr_err("Error %d on %s\n", status, __func__);
6250*4882a593Smuzhiyun 	}
6251*4882a593Smuzhiyun 
6252*4882a593Smuzhiyun 	return status;
6253*4882a593Smuzhiyun }
6254*4882a593Smuzhiyun 
load_firmware_cb(const struct firmware * fw,void * context)6255*4882a593Smuzhiyun static void load_firmware_cb(const struct firmware *fw,
6256*4882a593Smuzhiyun 			     void *context)
6257*4882a593Smuzhiyun {
6258*4882a593Smuzhiyun 	struct drxk_state *state = context;
6259*4882a593Smuzhiyun 
6260*4882a593Smuzhiyun 	dprintk(1, ": %s\n", fw ? "firmware loaded" : "firmware not loaded");
6261*4882a593Smuzhiyun 	if (!fw) {
6262*4882a593Smuzhiyun 		pr_err("Could not load firmware file %s.\n",
6263*4882a593Smuzhiyun 			state->microcode_name);
6264*4882a593Smuzhiyun 		pr_info("Copy %s to your hotplug directory!\n",
6265*4882a593Smuzhiyun 			state->microcode_name);
6266*4882a593Smuzhiyun 		state->microcode_name = NULL;
6267*4882a593Smuzhiyun 
6268*4882a593Smuzhiyun 		/*
6269*4882a593Smuzhiyun 		 * As firmware is now load asynchronous, it is not possible
6270*4882a593Smuzhiyun 		 * anymore to fail at frontend attach. We might silently
6271*4882a593Smuzhiyun 		 * return here, and hope that the driver won't crash.
6272*4882a593Smuzhiyun 		 * We might also change all DVB callbacks to return -ENODEV
6273*4882a593Smuzhiyun 		 * if the device is not initialized.
6274*4882a593Smuzhiyun 		 * As the DRX-K devices have their own internal firmware,
6275*4882a593Smuzhiyun 		 * let's just hope that it will match a firmware revision
6276*4882a593Smuzhiyun 		 * compatible with this driver and proceed.
6277*4882a593Smuzhiyun 		 */
6278*4882a593Smuzhiyun 	}
6279*4882a593Smuzhiyun 	state->fw = fw;
6280*4882a593Smuzhiyun 
6281*4882a593Smuzhiyun 	init_drxk(state);
6282*4882a593Smuzhiyun }
6283*4882a593Smuzhiyun 
drxk_release(struct dvb_frontend * fe)6284*4882a593Smuzhiyun static void drxk_release(struct dvb_frontend *fe)
6285*4882a593Smuzhiyun {
6286*4882a593Smuzhiyun 	struct drxk_state *state = fe->demodulator_priv;
6287*4882a593Smuzhiyun 
6288*4882a593Smuzhiyun 	dprintk(1, "\n");
6289*4882a593Smuzhiyun 	release_firmware(state->fw);
6290*4882a593Smuzhiyun 
6291*4882a593Smuzhiyun 	kfree(state);
6292*4882a593Smuzhiyun }
6293*4882a593Smuzhiyun 
drxk_sleep(struct dvb_frontend * fe)6294*4882a593Smuzhiyun static int drxk_sleep(struct dvb_frontend *fe)
6295*4882a593Smuzhiyun {
6296*4882a593Smuzhiyun 	struct drxk_state *state = fe->demodulator_priv;
6297*4882a593Smuzhiyun 
6298*4882a593Smuzhiyun 	dprintk(1, "\n");
6299*4882a593Smuzhiyun 
6300*4882a593Smuzhiyun 	if (state->m_drxk_state == DRXK_NO_DEV)
6301*4882a593Smuzhiyun 		return -ENODEV;
6302*4882a593Smuzhiyun 	if (state->m_drxk_state == DRXK_UNINITIALIZED)
6303*4882a593Smuzhiyun 		return 0;
6304*4882a593Smuzhiyun 
6305*4882a593Smuzhiyun 	shut_down(state);
6306*4882a593Smuzhiyun 	return 0;
6307*4882a593Smuzhiyun }
6308*4882a593Smuzhiyun 
drxk_gate_ctrl(struct dvb_frontend * fe,int enable)6309*4882a593Smuzhiyun static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable)
6310*4882a593Smuzhiyun {
6311*4882a593Smuzhiyun 	struct drxk_state *state = fe->demodulator_priv;
6312*4882a593Smuzhiyun 
6313*4882a593Smuzhiyun 	dprintk(1, ": %s\n", enable ? "enable" : "disable");
6314*4882a593Smuzhiyun 
6315*4882a593Smuzhiyun 	if (state->m_drxk_state == DRXK_NO_DEV)
6316*4882a593Smuzhiyun 		return -ENODEV;
6317*4882a593Smuzhiyun 
6318*4882a593Smuzhiyun 	return ConfigureI2CBridge(state, enable ? true : false);
6319*4882a593Smuzhiyun }
6320*4882a593Smuzhiyun 
drxk_set_parameters(struct dvb_frontend * fe)6321*4882a593Smuzhiyun static int drxk_set_parameters(struct dvb_frontend *fe)
6322*4882a593Smuzhiyun {
6323*4882a593Smuzhiyun 	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
6324*4882a593Smuzhiyun 	u32 delsys  = p->delivery_system, old_delsys;
6325*4882a593Smuzhiyun 	struct drxk_state *state = fe->demodulator_priv;
6326*4882a593Smuzhiyun 	u32 IF;
6327*4882a593Smuzhiyun 
6328*4882a593Smuzhiyun 	dprintk(1, "\n");
6329*4882a593Smuzhiyun 
6330*4882a593Smuzhiyun 	if (state->m_drxk_state == DRXK_NO_DEV)
6331*4882a593Smuzhiyun 		return -ENODEV;
6332*4882a593Smuzhiyun 
6333*4882a593Smuzhiyun 	if (state->m_drxk_state == DRXK_UNINITIALIZED)
6334*4882a593Smuzhiyun 		return -EAGAIN;
6335*4882a593Smuzhiyun 
6336*4882a593Smuzhiyun 	if (!fe->ops.tuner_ops.get_if_frequency) {
6337*4882a593Smuzhiyun 		pr_err("Error: get_if_frequency() not defined at tuner. Can't work without it!\n");
6338*4882a593Smuzhiyun 		return -EINVAL;
6339*4882a593Smuzhiyun 	}
6340*4882a593Smuzhiyun 
6341*4882a593Smuzhiyun 	if (fe->ops.i2c_gate_ctrl)
6342*4882a593Smuzhiyun 		fe->ops.i2c_gate_ctrl(fe, 1);
6343*4882a593Smuzhiyun 	if (fe->ops.tuner_ops.set_params)
6344*4882a593Smuzhiyun 		fe->ops.tuner_ops.set_params(fe);
6345*4882a593Smuzhiyun 	if (fe->ops.i2c_gate_ctrl)
6346*4882a593Smuzhiyun 		fe->ops.i2c_gate_ctrl(fe, 0);
6347*4882a593Smuzhiyun 
6348*4882a593Smuzhiyun 	old_delsys = state->props.delivery_system;
6349*4882a593Smuzhiyun 	state->props = *p;
6350*4882a593Smuzhiyun 
6351*4882a593Smuzhiyun 	if (old_delsys != delsys) {
6352*4882a593Smuzhiyun 		shut_down(state);
6353*4882a593Smuzhiyun 		switch (delsys) {
6354*4882a593Smuzhiyun 		case SYS_DVBC_ANNEX_A:
6355*4882a593Smuzhiyun 		case SYS_DVBC_ANNEX_C:
6356*4882a593Smuzhiyun 			if (!state->m_has_dvbc)
6357*4882a593Smuzhiyun 				return -EINVAL;
6358*4882a593Smuzhiyun 			state->m_itut_annex_c = (delsys == SYS_DVBC_ANNEX_C) ?
6359*4882a593Smuzhiyun 						true : false;
6360*4882a593Smuzhiyun 			if (state->m_itut_annex_c)
6361*4882a593Smuzhiyun 				setoperation_mode(state, OM_QAM_ITU_C);
6362*4882a593Smuzhiyun 			else
6363*4882a593Smuzhiyun 				setoperation_mode(state, OM_QAM_ITU_A);
6364*4882a593Smuzhiyun 			break;
6365*4882a593Smuzhiyun 		case SYS_DVBT:
6366*4882a593Smuzhiyun 			if (!state->m_has_dvbt)
6367*4882a593Smuzhiyun 				return -EINVAL;
6368*4882a593Smuzhiyun 			setoperation_mode(state, OM_DVBT);
6369*4882a593Smuzhiyun 			break;
6370*4882a593Smuzhiyun 		default:
6371*4882a593Smuzhiyun 			return -EINVAL;
6372*4882a593Smuzhiyun 		}
6373*4882a593Smuzhiyun 	}
6374*4882a593Smuzhiyun 
6375*4882a593Smuzhiyun 	fe->ops.tuner_ops.get_if_frequency(fe, &IF);
6376*4882a593Smuzhiyun 	start(state, 0, IF);
6377*4882a593Smuzhiyun 
6378*4882a593Smuzhiyun 	/* After set_frontend, stats aren't available */
6379*4882a593Smuzhiyun 	p->strength.stat[0].scale = FE_SCALE_RELATIVE;
6380*4882a593Smuzhiyun 	p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
6381*4882a593Smuzhiyun 	p->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
6382*4882a593Smuzhiyun 	p->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
6383*4882a593Smuzhiyun 	p->pre_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
6384*4882a593Smuzhiyun 	p->pre_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
6385*4882a593Smuzhiyun 	p->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
6386*4882a593Smuzhiyun 	p->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
6387*4882a593Smuzhiyun 
6388*4882a593Smuzhiyun 	/* printk(KERN_DEBUG "drxk: %s IF=%d done\n", __func__, IF); */
6389*4882a593Smuzhiyun 
6390*4882a593Smuzhiyun 	return 0;
6391*4882a593Smuzhiyun }
6392*4882a593Smuzhiyun 
get_strength(struct drxk_state * state,u64 * strength)6393*4882a593Smuzhiyun static int get_strength(struct drxk_state *state, u64 *strength)
6394*4882a593Smuzhiyun {
6395*4882a593Smuzhiyun 	int status;
6396*4882a593Smuzhiyun 	struct s_cfg_agc   rf_agc, if_agc;
6397*4882a593Smuzhiyun 	u32          total_gain  = 0;
6398*4882a593Smuzhiyun 	u32          atten      = 0;
6399*4882a593Smuzhiyun 	u32          agc_range   = 0;
6400*4882a593Smuzhiyun 	u16            scu_lvl  = 0;
6401*4882a593Smuzhiyun 	u16            scu_coc  = 0;
6402*4882a593Smuzhiyun 	/* FIXME: those are part of the tuner presets */
6403*4882a593Smuzhiyun 	u16 tuner_rf_gain         = 50; /* Default value on az6007 driver */
6404*4882a593Smuzhiyun 	u16 tuner_if_gain         = 40; /* Default value on az6007 driver */
6405*4882a593Smuzhiyun 
6406*4882a593Smuzhiyun 	*strength = 0;
6407*4882a593Smuzhiyun 
6408*4882a593Smuzhiyun 	if (is_dvbt(state)) {
6409*4882a593Smuzhiyun 		rf_agc = state->m_dvbt_rf_agc_cfg;
6410*4882a593Smuzhiyun 		if_agc = state->m_dvbt_if_agc_cfg;
6411*4882a593Smuzhiyun 	} else if (is_qam(state)) {
6412*4882a593Smuzhiyun 		rf_agc = state->m_qam_rf_agc_cfg;
6413*4882a593Smuzhiyun 		if_agc = state->m_qam_if_agc_cfg;
6414*4882a593Smuzhiyun 	} else {
6415*4882a593Smuzhiyun 		rf_agc = state->m_atv_rf_agc_cfg;
6416*4882a593Smuzhiyun 		if_agc = state->m_atv_if_agc_cfg;
6417*4882a593Smuzhiyun 	}
6418*4882a593Smuzhiyun 
6419*4882a593Smuzhiyun 	if (rf_agc.ctrl_mode == DRXK_AGC_CTRL_AUTO) {
6420*4882a593Smuzhiyun 		/* SCU output_level */
6421*4882a593Smuzhiyun 		status = read16(state, SCU_RAM_AGC_RF_IACCU_HI__A, &scu_lvl);
6422*4882a593Smuzhiyun 		if (status < 0)
6423*4882a593Smuzhiyun 			return status;
6424*4882a593Smuzhiyun 
6425*4882a593Smuzhiyun 		/* SCU c.o.c. */
6426*4882a593Smuzhiyun 		status = read16(state, SCU_RAM_AGC_RF_IACCU_HI_CO__A, &scu_coc);
6427*4882a593Smuzhiyun 		if (status < 0)
6428*4882a593Smuzhiyun 			return status;
6429*4882a593Smuzhiyun 
6430*4882a593Smuzhiyun 		if (((u32) scu_lvl + (u32) scu_coc) < 0xffff)
6431*4882a593Smuzhiyun 			rf_agc.output_level = scu_lvl + scu_coc;
6432*4882a593Smuzhiyun 		else
6433*4882a593Smuzhiyun 			rf_agc.output_level = 0xffff;
6434*4882a593Smuzhiyun 
6435*4882a593Smuzhiyun 		/* Take RF gain into account */
6436*4882a593Smuzhiyun 		total_gain += tuner_rf_gain;
6437*4882a593Smuzhiyun 
6438*4882a593Smuzhiyun 		/* clip output value */
6439*4882a593Smuzhiyun 		if (rf_agc.output_level < rf_agc.min_output_level)
6440*4882a593Smuzhiyun 			rf_agc.output_level = rf_agc.min_output_level;
6441*4882a593Smuzhiyun 		if (rf_agc.output_level > rf_agc.max_output_level)
6442*4882a593Smuzhiyun 			rf_agc.output_level = rf_agc.max_output_level;
6443*4882a593Smuzhiyun 
6444*4882a593Smuzhiyun 		agc_range = (u32) (rf_agc.max_output_level - rf_agc.min_output_level);
6445*4882a593Smuzhiyun 		if (agc_range > 0) {
6446*4882a593Smuzhiyun 			atten += 100UL *
6447*4882a593Smuzhiyun 				((u32)(tuner_rf_gain)) *
6448*4882a593Smuzhiyun 				((u32)(rf_agc.output_level - rf_agc.min_output_level))
6449*4882a593Smuzhiyun 				/ agc_range;
6450*4882a593Smuzhiyun 		}
6451*4882a593Smuzhiyun 	}
6452*4882a593Smuzhiyun 
6453*4882a593Smuzhiyun 	if (if_agc.ctrl_mode == DRXK_AGC_CTRL_AUTO) {
6454*4882a593Smuzhiyun 		status = read16(state, SCU_RAM_AGC_IF_IACCU_HI__A,
6455*4882a593Smuzhiyun 				&if_agc.output_level);
6456*4882a593Smuzhiyun 		if (status < 0)
6457*4882a593Smuzhiyun 			return status;
6458*4882a593Smuzhiyun 
6459*4882a593Smuzhiyun 		status = read16(state, SCU_RAM_AGC_INGAIN_TGT_MIN__A,
6460*4882a593Smuzhiyun 				&if_agc.top);
6461*4882a593Smuzhiyun 		if (status < 0)
6462*4882a593Smuzhiyun 			return status;
6463*4882a593Smuzhiyun 
6464*4882a593Smuzhiyun 		/* Take IF gain into account */
6465*4882a593Smuzhiyun 		total_gain += (u32) tuner_if_gain;
6466*4882a593Smuzhiyun 
6467*4882a593Smuzhiyun 		/* clip output value */
6468*4882a593Smuzhiyun 		if (if_agc.output_level < if_agc.min_output_level)
6469*4882a593Smuzhiyun 			if_agc.output_level = if_agc.min_output_level;
6470*4882a593Smuzhiyun 		if (if_agc.output_level > if_agc.max_output_level)
6471*4882a593Smuzhiyun 			if_agc.output_level = if_agc.max_output_level;
6472*4882a593Smuzhiyun 
6473*4882a593Smuzhiyun 		agc_range  = (u32)(if_agc.max_output_level - if_agc.min_output_level);
6474*4882a593Smuzhiyun 		if (agc_range > 0) {
6475*4882a593Smuzhiyun 			atten += 100UL *
6476*4882a593Smuzhiyun 				((u32)(tuner_if_gain)) *
6477*4882a593Smuzhiyun 				((u32)(if_agc.output_level - if_agc.min_output_level))
6478*4882a593Smuzhiyun 				/ agc_range;
6479*4882a593Smuzhiyun 		}
6480*4882a593Smuzhiyun 	}
6481*4882a593Smuzhiyun 
6482*4882a593Smuzhiyun 	/*
6483*4882a593Smuzhiyun 	 * Convert to 0..65535 scale.
6484*4882a593Smuzhiyun 	 * If it can't be measured (AGC is disabled), just show 100%.
6485*4882a593Smuzhiyun 	 */
6486*4882a593Smuzhiyun 	if (total_gain > 0)
6487*4882a593Smuzhiyun 		*strength = (65535UL * atten / total_gain / 100);
6488*4882a593Smuzhiyun 	else
6489*4882a593Smuzhiyun 		*strength = 65535;
6490*4882a593Smuzhiyun 
6491*4882a593Smuzhiyun 	return 0;
6492*4882a593Smuzhiyun }
6493*4882a593Smuzhiyun 
drxk_get_stats(struct dvb_frontend * fe)6494*4882a593Smuzhiyun static int drxk_get_stats(struct dvb_frontend *fe)
6495*4882a593Smuzhiyun {
6496*4882a593Smuzhiyun 	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
6497*4882a593Smuzhiyun 	struct drxk_state *state = fe->demodulator_priv;
6498*4882a593Smuzhiyun 	int status;
6499*4882a593Smuzhiyun 	u32 stat;
6500*4882a593Smuzhiyun 	u16 reg16;
6501*4882a593Smuzhiyun 	u32 post_bit_count;
6502*4882a593Smuzhiyun 	u32 post_bit_err_count;
6503*4882a593Smuzhiyun 	u32 post_bit_error_scale;
6504*4882a593Smuzhiyun 	u32 pre_bit_err_count;
6505*4882a593Smuzhiyun 	u32 pre_bit_count;
6506*4882a593Smuzhiyun 	u32 pkt_count;
6507*4882a593Smuzhiyun 	u32 pkt_error_count;
6508*4882a593Smuzhiyun 	s32 cnr;
6509*4882a593Smuzhiyun 
6510*4882a593Smuzhiyun 	if (state->m_drxk_state == DRXK_NO_DEV)
6511*4882a593Smuzhiyun 		return -ENODEV;
6512*4882a593Smuzhiyun 	if (state->m_drxk_state == DRXK_UNINITIALIZED)
6513*4882a593Smuzhiyun 		return -EAGAIN;
6514*4882a593Smuzhiyun 
6515*4882a593Smuzhiyun 	/* get status */
6516*4882a593Smuzhiyun 	state->fe_status = 0;
6517*4882a593Smuzhiyun 	get_lock_status(state, &stat);
6518*4882a593Smuzhiyun 	if (stat == MPEG_LOCK)
6519*4882a593Smuzhiyun 		state->fe_status |= 0x1f;
6520*4882a593Smuzhiyun 	if (stat == FEC_LOCK)
6521*4882a593Smuzhiyun 		state->fe_status |= 0x0f;
6522*4882a593Smuzhiyun 	if (stat == DEMOD_LOCK)
6523*4882a593Smuzhiyun 		state->fe_status |= 0x07;
6524*4882a593Smuzhiyun 
6525*4882a593Smuzhiyun 	/*
6526*4882a593Smuzhiyun 	 * Estimate signal strength from AGC
6527*4882a593Smuzhiyun 	 */
6528*4882a593Smuzhiyun 	get_strength(state, &c->strength.stat[0].uvalue);
6529*4882a593Smuzhiyun 	c->strength.stat[0].scale = FE_SCALE_RELATIVE;
6530*4882a593Smuzhiyun 
6531*4882a593Smuzhiyun 
6532*4882a593Smuzhiyun 	if (stat >= DEMOD_LOCK) {
6533*4882a593Smuzhiyun 		get_signal_to_noise(state, &cnr);
6534*4882a593Smuzhiyun 		c->cnr.stat[0].svalue = cnr * 100;
6535*4882a593Smuzhiyun 		c->cnr.stat[0].scale = FE_SCALE_DECIBEL;
6536*4882a593Smuzhiyun 	} else {
6537*4882a593Smuzhiyun 		c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
6538*4882a593Smuzhiyun 	}
6539*4882a593Smuzhiyun 
6540*4882a593Smuzhiyun 	if (stat < FEC_LOCK) {
6541*4882a593Smuzhiyun 		c->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
6542*4882a593Smuzhiyun 		c->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
6543*4882a593Smuzhiyun 		c->pre_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
6544*4882a593Smuzhiyun 		c->pre_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
6545*4882a593Smuzhiyun 		c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
6546*4882a593Smuzhiyun 		c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
6547*4882a593Smuzhiyun 		return 0;
6548*4882a593Smuzhiyun 	}
6549*4882a593Smuzhiyun 
6550*4882a593Smuzhiyun 	/* Get post BER */
6551*4882a593Smuzhiyun 
6552*4882a593Smuzhiyun 	/* BER measurement is valid if at least FEC lock is achieved */
6553*4882a593Smuzhiyun 
6554*4882a593Smuzhiyun 	/*
6555*4882a593Smuzhiyun 	 * OFDM_EC_VD_REQ_SMB_CNT__A and/or OFDM_EC_VD_REQ_BIT_CNT can be
6556*4882a593Smuzhiyun 	 * written to set nr of symbols or bits over which to measure
6557*4882a593Smuzhiyun 	 * EC_VD_REG_ERR_BIT_CNT__A . See CtrlSetCfg().
6558*4882a593Smuzhiyun 	 */
6559*4882a593Smuzhiyun 
6560*4882a593Smuzhiyun 	/* Read registers for post/preViterbi BER calculation */
6561*4882a593Smuzhiyun 	status = read16(state, OFDM_EC_VD_ERR_BIT_CNT__A, &reg16);
6562*4882a593Smuzhiyun 	if (status < 0)
6563*4882a593Smuzhiyun 		goto error;
6564*4882a593Smuzhiyun 	pre_bit_err_count = reg16;
6565*4882a593Smuzhiyun 
6566*4882a593Smuzhiyun 	status = read16(state, OFDM_EC_VD_IN_BIT_CNT__A , &reg16);
6567*4882a593Smuzhiyun 	if (status < 0)
6568*4882a593Smuzhiyun 		goto error;
6569*4882a593Smuzhiyun 	pre_bit_count = reg16;
6570*4882a593Smuzhiyun 
6571*4882a593Smuzhiyun 	/* Number of bit-errors */
6572*4882a593Smuzhiyun 	status = read16(state, FEC_RS_NR_BIT_ERRORS__A, &reg16);
6573*4882a593Smuzhiyun 	if (status < 0)
6574*4882a593Smuzhiyun 		goto error;
6575*4882a593Smuzhiyun 	post_bit_err_count = reg16;
6576*4882a593Smuzhiyun 
6577*4882a593Smuzhiyun 	status = read16(state, FEC_RS_MEASUREMENT_PRESCALE__A, &reg16);
6578*4882a593Smuzhiyun 	if (status < 0)
6579*4882a593Smuzhiyun 		goto error;
6580*4882a593Smuzhiyun 	post_bit_error_scale = reg16;
6581*4882a593Smuzhiyun 
6582*4882a593Smuzhiyun 	status = read16(state, FEC_RS_MEASUREMENT_PERIOD__A, &reg16);
6583*4882a593Smuzhiyun 	if (status < 0)
6584*4882a593Smuzhiyun 		goto error;
6585*4882a593Smuzhiyun 	pkt_count = reg16;
6586*4882a593Smuzhiyun 
6587*4882a593Smuzhiyun 	status = read16(state, SCU_RAM_FEC_ACCUM_PKT_FAILURES__A, &reg16);
6588*4882a593Smuzhiyun 	if (status < 0)
6589*4882a593Smuzhiyun 		goto error;
6590*4882a593Smuzhiyun 	pkt_error_count = reg16;
6591*4882a593Smuzhiyun 	write16(state, SCU_RAM_FEC_ACCUM_PKT_FAILURES__A, 0);
6592*4882a593Smuzhiyun 
6593*4882a593Smuzhiyun 	post_bit_err_count *= post_bit_error_scale;
6594*4882a593Smuzhiyun 
6595*4882a593Smuzhiyun 	post_bit_count = pkt_count * 204 * 8;
6596*4882a593Smuzhiyun 
6597*4882a593Smuzhiyun 	/* Store the results */
6598*4882a593Smuzhiyun 	c->block_error.stat[0].scale = FE_SCALE_COUNTER;
6599*4882a593Smuzhiyun 	c->block_error.stat[0].uvalue += pkt_error_count;
6600*4882a593Smuzhiyun 	c->block_count.stat[0].scale = FE_SCALE_COUNTER;
6601*4882a593Smuzhiyun 	c->block_count.stat[0].uvalue += pkt_count;
6602*4882a593Smuzhiyun 
6603*4882a593Smuzhiyun 	c->pre_bit_error.stat[0].scale = FE_SCALE_COUNTER;
6604*4882a593Smuzhiyun 	c->pre_bit_error.stat[0].uvalue += pre_bit_err_count;
6605*4882a593Smuzhiyun 	c->pre_bit_count.stat[0].scale = FE_SCALE_COUNTER;
6606*4882a593Smuzhiyun 	c->pre_bit_count.stat[0].uvalue += pre_bit_count;
6607*4882a593Smuzhiyun 
6608*4882a593Smuzhiyun 	c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER;
6609*4882a593Smuzhiyun 	c->post_bit_error.stat[0].uvalue += post_bit_err_count;
6610*4882a593Smuzhiyun 	c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER;
6611*4882a593Smuzhiyun 	c->post_bit_count.stat[0].uvalue += post_bit_count;
6612*4882a593Smuzhiyun 
6613*4882a593Smuzhiyun error:
6614*4882a593Smuzhiyun 	return status;
6615*4882a593Smuzhiyun }
6616*4882a593Smuzhiyun 
6617*4882a593Smuzhiyun 
drxk_read_status(struct dvb_frontend * fe,enum fe_status * status)6618*4882a593Smuzhiyun static int drxk_read_status(struct dvb_frontend *fe, enum fe_status *status)
6619*4882a593Smuzhiyun {
6620*4882a593Smuzhiyun 	struct drxk_state *state = fe->demodulator_priv;
6621*4882a593Smuzhiyun 	int rc;
6622*4882a593Smuzhiyun 
6623*4882a593Smuzhiyun 	dprintk(1, "\n");
6624*4882a593Smuzhiyun 
6625*4882a593Smuzhiyun 	rc = drxk_get_stats(fe);
6626*4882a593Smuzhiyun 	if (rc < 0)
6627*4882a593Smuzhiyun 		return rc;
6628*4882a593Smuzhiyun 
6629*4882a593Smuzhiyun 	*status = state->fe_status;
6630*4882a593Smuzhiyun 
6631*4882a593Smuzhiyun 	return 0;
6632*4882a593Smuzhiyun }
6633*4882a593Smuzhiyun 
drxk_read_signal_strength(struct dvb_frontend * fe,u16 * strength)6634*4882a593Smuzhiyun static int drxk_read_signal_strength(struct dvb_frontend *fe,
6635*4882a593Smuzhiyun 				     u16 *strength)
6636*4882a593Smuzhiyun {
6637*4882a593Smuzhiyun 	struct drxk_state *state = fe->demodulator_priv;
6638*4882a593Smuzhiyun 	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
6639*4882a593Smuzhiyun 
6640*4882a593Smuzhiyun 	dprintk(1, "\n");
6641*4882a593Smuzhiyun 
6642*4882a593Smuzhiyun 	if (state->m_drxk_state == DRXK_NO_DEV)
6643*4882a593Smuzhiyun 		return -ENODEV;
6644*4882a593Smuzhiyun 	if (state->m_drxk_state == DRXK_UNINITIALIZED)
6645*4882a593Smuzhiyun 		return -EAGAIN;
6646*4882a593Smuzhiyun 
6647*4882a593Smuzhiyun 	*strength = c->strength.stat[0].uvalue;
6648*4882a593Smuzhiyun 	return 0;
6649*4882a593Smuzhiyun }
6650*4882a593Smuzhiyun 
drxk_read_snr(struct dvb_frontend * fe,u16 * snr)6651*4882a593Smuzhiyun static int drxk_read_snr(struct dvb_frontend *fe, u16 *snr)
6652*4882a593Smuzhiyun {
6653*4882a593Smuzhiyun 	struct drxk_state *state = fe->demodulator_priv;
6654*4882a593Smuzhiyun 	s32 snr2;
6655*4882a593Smuzhiyun 
6656*4882a593Smuzhiyun 	dprintk(1, "\n");
6657*4882a593Smuzhiyun 
6658*4882a593Smuzhiyun 	if (state->m_drxk_state == DRXK_NO_DEV)
6659*4882a593Smuzhiyun 		return -ENODEV;
6660*4882a593Smuzhiyun 	if (state->m_drxk_state == DRXK_UNINITIALIZED)
6661*4882a593Smuzhiyun 		return -EAGAIN;
6662*4882a593Smuzhiyun 
6663*4882a593Smuzhiyun 	get_signal_to_noise(state, &snr2);
6664*4882a593Smuzhiyun 
6665*4882a593Smuzhiyun 	/* No negative SNR, clip to zero */
6666*4882a593Smuzhiyun 	if (snr2 < 0)
6667*4882a593Smuzhiyun 		snr2 = 0;
6668*4882a593Smuzhiyun 	*snr = snr2 & 0xffff;
6669*4882a593Smuzhiyun 	return 0;
6670*4882a593Smuzhiyun }
6671*4882a593Smuzhiyun 
drxk_read_ucblocks(struct dvb_frontend * fe,u32 * ucblocks)6672*4882a593Smuzhiyun static int drxk_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
6673*4882a593Smuzhiyun {
6674*4882a593Smuzhiyun 	struct drxk_state *state = fe->demodulator_priv;
6675*4882a593Smuzhiyun 	u16 err = 0;
6676*4882a593Smuzhiyun 
6677*4882a593Smuzhiyun 	dprintk(1, "\n");
6678*4882a593Smuzhiyun 
6679*4882a593Smuzhiyun 	if (state->m_drxk_state == DRXK_NO_DEV)
6680*4882a593Smuzhiyun 		return -ENODEV;
6681*4882a593Smuzhiyun 	if (state->m_drxk_state == DRXK_UNINITIALIZED)
6682*4882a593Smuzhiyun 		return -EAGAIN;
6683*4882a593Smuzhiyun 
6684*4882a593Smuzhiyun 	dvbtqam_get_acc_pkt_err(state, &err);
6685*4882a593Smuzhiyun 	*ucblocks = (u32) err;
6686*4882a593Smuzhiyun 	return 0;
6687*4882a593Smuzhiyun }
6688*4882a593Smuzhiyun 
drxk_get_tune_settings(struct dvb_frontend * fe,struct dvb_frontend_tune_settings * sets)6689*4882a593Smuzhiyun static int drxk_get_tune_settings(struct dvb_frontend *fe,
6690*4882a593Smuzhiyun 				  struct dvb_frontend_tune_settings *sets)
6691*4882a593Smuzhiyun {
6692*4882a593Smuzhiyun 	struct drxk_state *state = fe->demodulator_priv;
6693*4882a593Smuzhiyun 	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
6694*4882a593Smuzhiyun 
6695*4882a593Smuzhiyun 	dprintk(1, "\n");
6696*4882a593Smuzhiyun 
6697*4882a593Smuzhiyun 	if (state->m_drxk_state == DRXK_NO_DEV)
6698*4882a593Smuzhiyun 		return -ENODEV;
6699*4882a593Smuzhiyun 	if (state->m_drxk_state == DRXK_UNINITIALIZED)
6700*4882a593Smuzhiyun 		return -EAGAIN;
6701*4882a593Smuzhiyun 
6702*4882a593Smuzhiyun 	switch (p->delivery_system) {
6703*4882a593Smuzhiyun 	case SYS_DVBC_ANNEX_A:
6704*4882a593Smuzhiyun 	case SYS_DVBC_ANNEX_C:
6705*4882a593Smuzhiyun 	case SYS_DVBT:
6706*4882a593Smuzhiyun 		sets->min_delay_ms = 3000;
6707*4882a593Smuzhiyun 		sets->max_drift = 0;
6708*4882a593Smuzhiyun 		sets->step_size = 0;
6709*4882a593Smuzhiyun 		return 0;
6710*4882a593Smuzhiyun 	default:
6711*4882a593Smuzhiyun 		return -EINVAL;
6712*4882a593Smuzhiyun 	}
6713*4882a593Smuzhiyun }
6714*4882a593Smuzhiyun 
6715*4882a593Smuzhiyun static const struct dvb_frontend_ops drxk_ops = {
6716*4882a593Smuzhiyun 	/* .delsys will be filled dynamically */
6717*4882a593Smuzhiyun 	.info = {
6718*4882a593Smuzhiyun 		.name = "DRXK",
6719*4882a593Smuzhiyun 		.frequency_min_hz =  47 * MHz,
6720*4882a593Smuzhiyun 		.frequency_max_hz = 865 * MHz,
6721*4882a593Smuzhiyun 		 /* For DVB-C */
6722*4882a593Smuzhiyun 		.symbol_rate_min =   870000,
6723*4882a593Smuzhiyun 		.symbol_rate_max = 11700000,
6724*4882a593Smuzhiyun 		/* For DVB-T */
6725*4882a593Smuzhiyun 		.frequency_stepsize_hz = 166667,
6726*4882a593Smuzhiyun 
6727*4882a593Smuzhiyun 		.caps = FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 |
6728*4882a593Smuzhiyun 			FE_CAN_QAM_128 | FE_CAN_QAM_256 | FE_CAN_FEC_AUTO |
6729*4882a593Smuzhiyun 			FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
6730*4882a593Smuzhiyun 			FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_MUTE_TS |
6731*4882a593Smuzhiyun 			FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_RECOVER |
6732*4882a593Smuzhiyun 			FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO
6733*4882a593Smuzhiyun 	},
6734*4882a593Smuzhiyun 
6735*4882a593Smuzhiyun 	.release = drxk_release,
6736*4882a593Smuzhiyun 	.sleep = drxk_sleep,
6737*4882a593Smuzhiyun 	.i2c_gate_ctrl = drxk_gate_ctrl,
6738*4882a593Smuzhiyun 
6739*4882a593Smuzhiyun 	.set_frontend = drxk_set_parameters,
6740*4882a593Smuzhiyun 	.get_tune_settings = drxk_get_tune_settings,
6741*4882a593Smuzhiyun 
6742*4882a593Smuzhiyun 	.read_status = drxk_read_status,
6743*4882a593Smuzhiyun 	.read_signal_strength = drxk_read_signal_strength,
6744*4882a593Smuzhiyun 	.read_snr = drxk_read_snr,
6745*4882a593Smuzhiyun 	.read_ucblocks = drxk_read_ucblocks,
6746*4882a593Smuzhiyun };
6747*4882a593Smuzhiyun 
drxk_attach(const struct drxk_config * config,struct i2c_adapter * i2c)6748*4882a593Smuzhiyun struct dvb_frontend *drxk_attach(const struct drxk_config *config,
6749*4882a593Smuzhiyun 				 struct i2c_adapter *i2c)
6750*4882a593Smuzhiyun {
6751*4882a593Smuzhiyun 	struct dtv_frontend_properties *p;
6752*4882a593Smuzhiyun 	struct drxk_state *state = NULL;
6753*4882a593Smuzhiyun 	u8 adr = config->adr;
6754*4882a593Smuzhiyun 	int status;
6755*4882a593Smuzhiyun 
6756*4882a593Smuzhiyun 	dprintk(1, "\n");
6757*4882a593Smuzhiyun 	state = kzalloc(sizeof(struct drxk_state), GFP_KERNEL);
6758*4882a593Smuzhiyun 	if (!state)
6759*4882a593Smuzhiyun 		return NULL;
6760*4882a593Smuzhiyun 
6761*4882a593Smuzhiyun 	state->i2c = i2c;
6762*4882a593Smuzhiyun 	state->demod_address = adr;
6763*4882a593Smuzhiyun 	state->single_master = config->single_master;
6764*4882a593Smuzhiyun 	state->microcode_name = config->microcode_name;
6765*4882a593Smuzhiyun 	state->qam_demod_parameter_count = config->qam_demod_parameter_count;
6766*4882a593Smuzhiyun 	state->no_i2c_bridge = config->no_i2c_bridge;
6767*4882a593Smuzhiyun 	state->antenna_gpio = config->antenna_gpio;
6768*4882a593Smuzhiyun 	state->antenna_dvbt = config->antenna_dvbt;
6769*4882a593Smuzhiyun 	state->m_chunk_size = config->chunk_size;
6770*4882a593Smuzhiyun 	state->enable_merr_cfg = config->enable_merr_cfg;
6771*4882a593Smuzhiyun 
6772*4882a593Smuzhiyun 	if (config->dynamic_clk) {
6773*4882a593Smuzhiyun 		state->m_dvbt_static_clk = false;
6774*4882a593Smuzhiyun 		state->m_dvbc_static_clk = false;
6775*4882a593Smuzhiyun 	} else {
6776*4882a593Smuzhiyun 		state->m_dvbt_static_clk = true;
6777*4882a593Smuzhiyun 		state->m_dvbc_static_clk = true;
6778*4882a593Smuzhiyun 	}
6779*4882a593Smuzhiyun 
6780*4882a593Smuzhiyun 
6781*4882a593Smuzhiyun 	if (config->mpeg_out_clk_strength)
6782*4882a593Smuzhiyun 		state->m_ts_clockk_strength = config->mpeg_out_clk_strength & 0x07;
6783*4882a593Smuzhiyun 	else
6784*4882a593Smuzhiyun 		state->m_ts_clockk_strength = 0x06;
6785*4882a593Smuzhiyun 
6786*4882a593Smuzhiyun 	if (config->parallel_ts)
6787*4882a593Smuzhiyun 		state->m_enable_parallel = true;
6788*4882a593Smuzhiyun 	else
6789*4882a593Smuzhiyun 		state->m_enable_parallel = false;
6790*4882a593Smuzhiyun 
6791*4882a593Smuzhiyun 	/* NOTE: as more UIO bits will be used, add them to the mask */
6792*4882a593Smuzhiyun 	state->uio_mask = config->antenna_gpio;
6793*4882a593Smuzhiyun 
6794*4882a593Smuzhiyun 	/* Default gpio to DVB-C */
6795*4882a593Smuzhiyun 	if (!state->antenna_dvbt && state->antenna_gpio)
6796*4882a593Smuzhiyun 		state->m_gpio |= state->antenna_gpio;
6797*4882a593Smuzhiyun 	else
6798*4882a593Smuzhiyun 		state->m_gpio &= ~state->antenna_gpio;
6799*4882a593Smuzhiyun 
6800*4882a593Smuzhiyun 	mutex_init(&state->mutex);
6801*4882a593Smuzhiyun 
6802*4882a593Smuzhiyun 	memcpy(&state->frontend.ops, &drxk_ops, sizeof(drxk_ops));
6803*4882a593Smuzhiyun 	state->frontend.demodulator_priv = state;
6804*4882a593Smuzhiyun 
6805*4882a593Smuzhiyun 	init_state(state);
6806*4882a593Smuzhiyun 
6807*4882a593Smuzhiyun 	/* Load firmware and initialize DRX-K */
6808*4882a593Smuzhiyun 	if (state->microcode_name) {
6809*4882a593Smuzhiyun 		const struct firmware *fw = NULL;
6810*4882a593Smuzhiyun 
6811*4882a593Smuzhiyun 		status = request_firmware(&fw, state->microcode_name,
6812*4882a593Smuzhiyun 					  state->i2c->dev.parent);
6813*4882a593Smuzhiyun 		if (status < 0)
6814*4882a593Smuzhiyun 			fw = NULL;
6815*4882a593Smuzhiyun 		load_firmware_cb(fw, state);
6816*4882a593Smuzhiyun 	} else if (init_drxk(state) < 0)
6817*4882a593Smuzhiyun 		goto error;
6818*4882a593Smuzhiyun 
6819*4882a593Smuzhiyun 
6820*4882a593Smuzhiyun 	/* Initialize stats */
6821*4882a593Smuzhiyun 	p = &state->frontend.dtv_property_cache;
6822*4882a593Smuzhiyun 	p->strength.len = 1;
6823*4882a593Smuzhiyun 	p->cnr.len = 1;
6824*4882a593Smuzhiyun 	p->block_error.len = 1;
6825*4882a593Smuzhiyun 	p->block_count.len = 1;
6826*4882a593Smuzhiyun 	p->pre_bit_error.len = 1;
6827*4882a593Smuzhiyun 	p->pre_bit_count.len = 1;
6828*4882a593Smuzhiyun 	p->post_bit_error.len = 1;
6829*4882a593Smuzhiyun 	p->post_bit_count.len = 1;
6830*4882a593Smuzhiyun 
6831*4882a593Smuzhiyun 	p->strength.stat[0].scale = FE_SCALE_RELATIVE;
6832*4882a593Smuzhiyun 	p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
6833*4882a593Smuzhiyun 	p->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
6834*4882a593Smuzhiyun 	p->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
6835*4882a593Smuzhiyun 	p->pre_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
6836*4882a593Smuzhiyun 	p->pre_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
6837*4882a593Smuzhiyun 	p->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
6838*4882a593Smuzhiyun 	p->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
6839*4882a593Smuzhiyun 
6840*4882a593Smuzhiyun 	pr_info("frontend initialized.\n");
6841*4882a593Smuzhiyun 	return &state->frontend;
6842*4882a593Smuzhiyun 
6843*4882a593Smuzhiyun error:
6844*4882a593Smuzhiyun 	pr_err("not found\n");
6845*4882a593Smuzhiyun 	kfree(state);
6846*4882a593Smuzhiyun 	return NULL;
6847*4882a593Smuzhiyun }
6848*4882a593Smuzhiyun EXPORT_SYMBOL(drxk_attach);
6849*4882a593Smuzhiyun 
6850*4882a593Smuzhiyun MODULE_DESCRIPTION("DRX-K driver");
6851*4882a593Smuzhiyun MODULE_AUTHOR("Ralph Metzler");
6852*4882a593Smuzhiyun MODULE_LICENSE("GPL");
6853