xref: /OK3568_Linux_fs/kernel/drivers/media/tuners/mxl5007t.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  *  mxl5007t.c - driver for the MaxLinear MxL5007T silicon tuner
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  *  Copyright (C) 2008, 2009 Michael Krufky <mkrufky@linuxtv.org>
6*4882a593Smuzhiyun  */
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun #include <linux/i2c.h>
9*4882a593Smuzhiyun #include <linux/types.h>
10*4882a593Smuzhiyun #include <linux/videodev2.h>
11*4882a593Smuzhiyun #include "tuner-i2c.h"
12*4882a593Smuzhiyun #include "mxl5007t.h"
13*4882a593Smuzhiyun 
14*4882a593Smuzhiyun static DEFINE_MUTEX(mxl5007t_list_mutex);
15*4882a593Smuzhiyun static LIST_HEAD(hybrid_tuner_instance_list);
16*4882a593Smuzhiyun 
17*4882a593Smuzhiyun static int mxl5007t_debug;
18*4882a593Smuzhiyun module_param_named(debug, mxl5007t_debug, int, 0644);
19*4882a593Smuzhiyun MODULE_PARM_DESC(debug, "set debug level");
20*4882a593Smuzhiyun 
21*4882a593Smuzhiyun /* ------------------------------------------------------------------------- */
22*4882a593Smuzhiyun 
23*4882a593Smuzhiyun #define mxl_printk(kern, fmt, arg...) \
24*4882a593Smuzhiyun 	printk(kern "%s: " fmt "\n", __func__, ##arg)
25*4882a593Smuzhiyun 
26*4882a593Smuzhiyun #define mxl_err(fmt, arg...) \
27*4882a593Smuzhiyun 	mxl_printk(KERN_ERR, "%d: " fmt, __LINE__, ##arg)
28*4882a593Smuzhiyun 
29*4882a593Smuzhiyun #define mxl_warn(fmt, arg...) \
30*4882a593Smuzhiyun 	mxl_printk(KERN_WARNING, fmt, ##arg)
31*4882a593Smuzhiyun 
32*4882a593Smuzhiyun #define mxl_info(fmt, arg...) \
33*4882a593Smuzhiyun 	mxl_printk(KERN_INFO, fmt, ##arg)
34*4882a593Smuzhiyun 
35*4882a593Smuzhiyun #define mxl_debug(fmt, arg...)				\
36*4882a593Smuzhiyun ({							\
37*4882a593Smuzhiyun 	if (mxl5007t_debug)				\
38*4882a593Smuzhiyun 		mxl_printk(KERN_DEBUG, fmt, ##arg);	\
39*4882a593Smuzhiyun })
40*4882a593Smuzhiyun 
41*4882a593Smuzhiyun #define mxl_fail(ret)							\
42*4882a593Smuzhiyun ({									\
43*4882a593Smuzhiyun 	int __ret;							\
44*4882a593Smuzhiyun 	__ret = (ret < 0);						\
45*4882a593Smuzhiyun 	if (__ret)							\
46*4882a593Smuzhiyun 		mxl_printk(KERN_ERR, "error %d on line %d",		\
47*4882a593Smuzhiyun 			   ret, __LINE__);				\
48*4882a593Smuzhiyun 	__ret;								\
49*4882a593Smuzhiyun })
50*4882a593Smuzhiyun 
51*4882a593Smuzhiyun /* ------------------------------------------------------------------------- */
52*4882a593Smuzhiyun 
53*4882a593Smuzhiyun enum mxl5007t_mode {
54*4882a593Smuzhiyun 	MxL_MODE_ISDBT     =    0,
55*4882a593Smuzhiyun 	MxL_MODE_DVBT      =    1,
56*4882a593Smuzhiyun 	MxL_MODE_ATSC      =    2,
57*4882a593Smuzhiyun 	MxL_MODE_CABLE     = 0x10,
58*4882a593Smuzhiyun };
59*4882a593Smuzhiyun 
60*4882a593Smuzhiyun enum mxl5007t_chip_version {
61*4882a593Smuzhiyun 	MxL_UNKNOWN_ID     = 0x00,
62*4882a593Smuzhiyun 	MxL_5007_V1_F1     = 0x11,
63*4882a593Smuzhiyun 	MxL_5007_V1_F2     = 0x12,
64*4882a593Smuzhiyun 	MxL_5007_V4        = 0x14,
65*4882a593Smuzhiyun 	MxL_5007_V2_100_F1 = 0x21,
66*4882a593Smuzhiyun 	MxL_5007_V2_100_F2 = 0x22,
67*4882a593Smuzhiyun 	MxL_5007_V2_200_F1 = 0x23,
68*4882a593Smuzhiyun 	MxL_5007_V2_200_F2 = 0x24,
69*4882a593Smuzhiyun };
70*4882a593Smuzhiyun 
71*4882a593Smuzhiyun struct reg_pair_t {
72*4882a593Smuzhiyun 	u8 reg;
73*4882a593Smuzhiyun 	u8 val;
74*4882a593Smuzhiyun };
75*4882a593Smuzhiyun 
76*4882a593Smuzhiyun /* ------------------------------------------------------------------------- */
77*4882a593Smuzhiyun 
78*4882a593Smuzhiyun static struct reg_pair_t init_tab[] = {
79*4882a593Smuzhiyun 	{ 0x02, 0x06 },
80*4882a593Smuzhiyun 	{ 0x03, 0x48 },
81*4882a593Smuzhiyun 	{ 0x05, 0x04 },
82*4882a593Smuzhiyun 	{ 0x06, 0x10 },
83*4882a593Smuzhiyun 	{ 0x2e, 0x15 }, /* OVERRIDE */
84*4882a593Smuzhiyun 	{ 0x30, 0x10 }, /* OVERRIDE */
85*4882a593Smuzhiyun 	{ 0x45, 0x58 }, /* OVERRIDE */
86*4882a593Smuzhiyun 	{ 0x48, 0x19 }, /* OVERRIDE */
87*4882a593Smuzhiyun 	{ 0x52, 0x03 }, /* OVERRIDE */
88*4882a593Smuzhiyun 	{ 0x53, 0x44 }, /* OVERRIDE */
89*4882a593Smuzhiyun 	{ 0x6a, 0x4b }, /* OVERRIDE */
90*4882a593Smuzhiyun 	{ 0x76, 0x00 }, /* OVERRIDE */
91*4882a593Smuzhiyun 	{ 0x78, 0x18 }, /* OVERRIDE */
92*4882a593Smuzhiyun 	{ 0x7a, 0x17 }, /* OVERRIDE */
93*4882a593Smuzhiyun 	{ 0x85, 0x06 }, /* OVERRIDE */
94*4882a593Smuzhiyun 	{ 0x01, 0x01 }, /* TOP_MASTER_ENABLE */
95*4882a593Smuzhiyun 	{ 0, 0 }
96*4882a593Smuzhiyun };
97*4882a593Smuzhiyun 
98*4882a593Smuzhiyun static struct reg_pair_t init_tab_cable[] = {
99*4882a593Smuzhiyun 	{ 0x02, 0x06 },
100*4882a593Smuzhiyun 	{ 0x03, 0x48 },
101*4882a593Smuzhiyun 	{ 0x05, 0x04 },
102*4882a593Smuzhiyun 	{ 0x06, 0x10 },
103*4882a593Smuzhiyun 	{ 0x09, 0x3f },
104*4882a593Smuzhiyun 	{ 0x0a, 0x3f },
105*4882a593Smuzhiyun 	{ 0x0b, 0x3f },
106*4882a593Smuzhiyun 	{ 0x2e, 0x15 }, /* OVERRIDE */
107*4882a593Smuzhiyun 	{ 0x30, 0x10 }, /* OVERRIDE */
108*4882a593Smuzhiyun 	{ 0x45, 0x58 }, /* OVERRIDE */
109*4882a593Smuzhiyun 	{ 0x48, 0x19 }, /* OVERRIDE */
110*4882a593Smuzhiyun 	{ 0x52, 0x03 }, /* OVERRIDE */
111*4882a593Smuzhiyun 	{ 0x53, 0x44 }, /* OVERRIDE */
112*4882a593Smuzhiyun 	{ 0x6a, 0x4b }, /* OVERRIDE */
113*4882a593Smuzhiyun 	{ 0x76, 0x00 }, /* OVERRIDE */
114*4882a593Smuzhiyun 	{ 0x78, 0x18 }, /* OVERRIDE */
115*4882a593Smuzhiyun 	{ 0x7a, 0x17 }, /* OVERRIDE */
116*4882a593Smuzhiyun 	{ 0x85, 0x06 }, /* OVERRIDE */
117*4882a593Smuzhiyun 	{ 0x01, 0x01 }, /* TOP_MASTER_ENABLE */
118*4882a593Smuzhiyun 	{ 0, 0 }
119*4882a593Smuzhiyun };
120*4882a593Smuzhiyun 
121*4882a593Smuzhiyun /* ------------------------------------------------------------------------- */
122*4882a593Smuzhiyun 
123*4882a593Smuzhiyun static struct reg_pair_t reg_pair_rftune[] = {
124*4882a593Smuzhiyun 	{ 0x0f, 0x00 }, /* abort tune */
125*4882a593Smuzhiyun 	{ 0x0c, 0x15 },
126*4882a593Smuzhiyun 	{ 0x0d, 0x40 },
127*4882a593Smuzhiyun 	{ 0x0e, 0x0e },
128*4882a593Smuzhiyun 	{ 0x1f, 0x87 }, /* OVERRIDE */
129*4882a593Smuzhiyun 	{ 0x20, 0x1f }, /* OVERRIDE */
130*4882a593Smuzhiyun 	{ 0x21, 0x87 }, /* OVERRIDE */
131*4882a593Smuzhiyun 	{ 0x22, 0x1f }, /* OVERRIDE */
132*4882a593Smuzhiyun 	{ 0x80, 0x01 }, /* freq dependent */
133*4882a593Smuzhiyun 	{ 0x0f, 0x01 }, /* start tune */
134*4882a593Smuzhiyun 	{ 0, 0 }
135*4882a593Smuzhiyun };
136*4882a593Smuzhiyun 
137*4882a593Smuzhiyun /* ------------------------------------------------------------------------- */
138*4882a593Smuzhiyun 
139*4882a593Smuzhiyun struct mxl5007t_state {
140*4882a593Smuzhiyun 	struct list_head hybrid_tuner_instance_list;
141*4882a593Smuzhiyun 	struct tuner_i2c_props i2c_props;
142*4882a593Smuzhiyun 
143*4882a593Smuzhiyun 	struct mutex lock;
144*4882a593Smuzhiyun 
145*4882a593Smuzhiyun 	struct mxl5007t_config *config;
146*4882a593Smuzhiyun 
147*4882a593Smuzhiyun 	enum mxl5007t_chip_version chip_id;
148*4882a593Smuzhiyun 
149*4882a593Smuzhiyun 	struct reg_pair_t tab_init[ARRAY_SIZE(init_tab)];
150*4882a593Smuzhiyun 	struct reg_pair_t tab_init_cable[ARRAY_SIZE(init_tab_cable)];
151*4882a593Smuzhiyun 	struct reg_pair_t tab_rftune[ARRAY_SIZE(reg_pair_rftune)];
152*4882a593Smuzhiyun 
153*4882a593Smuzhiyun 	enum mxl5007t_if_freq if_freq;
154*4882a593Smuzhiyun 
155*4882a593Smuzhiyun 	u32 frequency;
156*4882a593Smuzhiyun 	u32 bandwidth;
157*4882a593Smuzhiyun };
158*4882a593Smuzhiyun 
159*4882a593Smuzhiyun /* ------------------------------------------------------------------------- */
160*4882a593Smuzhiyun 
161*4882a593Smuzhiyun /* called by _init and _rftun to manipulate the register arrays */
162*4882a593Smuzhiyun 
set_reg_bits(struct reg_pair_t * reg_pair,u8 reg,u8 mask,u8 val)163*4882a593Smuzhiyun static void set_reg_bits(struct reg_pair_t *reg_pair, u8 reg, u8 mask, u8 val)
164*4882a593Smuzhiyun {
165*4882a593Smuzhiyun 	unsigned int i = 0;
166*4882a593Smuzhiyun 
167*4882a593Smuzhiyun 	while (reg_pair[i].reg || reg_pair[i].val) {
168*4882a593Smuzhiyun 		if (reg_pair[i].reg == reg) {
169*4882a593Smuzhiyun 			reg_pair[i].val &= ~mask;
170*4882a593Smuzhiyun 			reg_pair[i].val |= val;
171*4882a593Smuzhiyun 		}
172*4882a593Smuzhiyun 		i++;
173*4882a593Smuzhiyun 
174*4882a593Smuzhiyun 	}
175*4882a593Smuzhiyun 	return;
176*4882a593Smuzhiyun }
177*4882a593Smuzhiyun 
copy_reg_bits(struct reg_pair_t * reg_pair1,struct reg_pair_t * reg_pair2)178*4882a593Smuzhiyun static void copy_reg_bits(struct reg_pair_t *reg_pair1,
179*4882a593Smuzhiyun 			  struct reg_pair_t *reg_pair2)
180*4882a593Smuzhiyun {
181*4882a593Smuzhiyun 	unsigned int i, j;
182*4882a593Smuzhiyun 
183*4882a593Smuzhiyun 	i = j = 0;
184*4882a593Smuzhiyun 
185*4882a593Smuzhiyun 	while (reg_pair1[i].reg || reg_pair1[i].val) {
186*4882a593Smuzhiyun 		while (reg_pair2[j].reg || reg_pair2[j].val) {
187*4882a593Smuzhiyun 			if (reg_pair1[i].reg != reg_pair2[j].reg) {
188*4882a593Smuzhiyun 				j++;
189*4882a593Smuzhiyun 				continue;
190*4882a593Smuzhiyun 			}
191*4882a593Smuzhiyun 			reg_pair2[j].val = reg_pair1[i].val;
192*4882a593Smuzhiyun 			break;
193*4882a593Smuzhiyun 		}
194*4882a593Smuzhiyun 		i++;
195*4882a593Smuzhiyun 	}
196*4882a593Smuzhiyun 	return;
197*4882a593Smuzhiyun }
198*4882a593Smuzhiyun 
199*4882a593Smuzhiyun /* ------------------------------------------------------------------------- */
200*4882a593Smuzhiyun 
mxl5007t_set_mode_bits(struct mxl5007t_state * state,enum mxl5007t_mode mode,s32 if_diff_out_level)201*4882a593Smuzhiyun static void mxl5007t_set_mode_bits(struct mxl5007t_state *state,
202*4882a593Smuzhiyun 				   enum mxl5007t_mode mode,
203*4882a593Smuzhiyun 				   s32 if_diff_out_level)
204*4882a593Smuzhiyun {
205*4882a593Smuzhiyun 	switch (mode) {
206*4882a593Smuzhiyun 	case MxL_MODE_ATSC:
207*4882a593Smuzhiyun 		set_reg_bits(state->tab_init, 0x06, 0x1f, 0x12);
208*4882a593Smuzhiyun 		break;
209*4882a593Smuzhiyun 	case MxL_MODE_DVBT:
210*4882a593Smuzhiyun 		set_reg_bits(state->tab_init, 0x06, 0x1f, 0x11);
211*4882a593Smuzhiyun 		break;
212*4882a593Smuzhiyun 	case MxL_MODE_ISDBT:
213*4882a593Smuzhiyun 		set_reg_bits(state->tab_init, 0x06, 0x1f, 0x10);
214*4882a593Smuzhiyun 		break;
215*4882a593Smuzhiyun 	case MxL_MODE_CABLE:
216*4882a593Smuzhiyun 		set_reg_bits(state->tab_init_cable, 0x09, 0xff, 0xc1);
217*4882a593Smuzhiyun 		set_reg_bits(state->tab_init_cable, 0x0a, 0xff,
218*4882a593Smuzhiyun 			     8 - if_diff_out_level);
219*4882a593Smuzhiyun 		set_reg_bits(state->tab_init_cable, 0x0b, 0xff, 0x17);
220*4882a593Smuzhiyun 		break;
221*4882a593Smuzhiyun 	default:
222*4882a593Smuzhiyun 		mxl_fail(-EINVAL);
223*4882a593Smuzhiyun 	}
224*4882a593Smuzhiyun 	return;
225*4882a593Smuzhiyun }
226*4882a593Smuzhiyun 
mxl5007t_set_if_freq_bits(struct mxl5007t_state * state,enum mxl5007t_if_freq if_freq,int invert_if)227*4882a593Smuzhiyun static void mxl5007t_set_if_freq_bits(struct mxl5007t_state *state,
228*4882a593Smuzhiyun 				      enum mxl5007t_if_freq if_freq,
229*4882a593Smuzhiyun 				      int invert_if)
230*4882a593Smuzhiyun {
231*4882a593Smuzhiyun 	u8 val;
232*4882a593Smuzhiyun 
233*4882a593Smuzhiyun 	switch (if_freq) {
234*4882a593Smuzhiyun 	case MxL_IF_4_MHZ:
235*4882a593Smuzhiyun 		val = 0x00;
236*4882a593Smuzhiyun 		break;
237*4882a593Smuzhiyun 	case MxL_IF_4_5_MHZ:
238*4882a593Smuzhiyun 		val = 0x02;
239*4882a593Smuzhiyun 		break;
240*4882a593Smuzhiyun 	case MxL_IF_4_57_MHZ:
241*4882a593Smuzhiyun 		val = 0x03;
242*4882a593Smuzhiyun 		break;
243*4882a593Smuzhiyun 	case MxL_IF_5_MHZ:
244*4882a593Smuzhiyun 		val = 0x04;
245*4882a593Smuzhiyun 		break;
246*4882a593Smuzhiyun 	case MxL_IF_5_38_MHZ:
247*4882a593Smuzhiyun 		val = 0x05;
248*4882a593Smuzhiyun 		break;
249*4882a593Smuzhiyun 	case MxL_IF_6_MHZ:
250*4882a593Smuzhiyun 		val = 0x06;
251*4882a593Smuzhiyun 		break;
252*4882a593Smuzhiyun 	case MxL_IF_6_28_MHZ:
253*4882a593Smuzhiyun 		val = 0x07;
254*4882a593Smuzhiyun 		break;
255*4882a593Smuzhiyun 	case MxL_IF_9_1915_MHZ:
256*4882a593Smuzhiyun 		val = 0x08;
257*4882a593Smuzhiyun 		break;
258*4882a593Smuzhiyun 	case MxL_IF_35_25_MHZ:
259*4882a593Smuzhiyun 		val = 0x09;
260*4882a593Smuzhiyun 		break;
261*4882a593Smuzhiyun 	case MxL_IF_36_15_MHZ:
262*4882a593Smuzhiyun 		val = 0x0a;
263*4882a593Smuzhiyun 		break;
264*4882a593Smuzhiyun 	case MxL_IF_44_MHZ:
265*4882a593Smuzhiyun 		val = 0x0b;
266*4882a593Smuzhiyun 		break;
267*4882a593Smuzhiyun 	default:
268*4882a593Smuzhiyun 		mxl_fail(-EINVAL);
269*4882a593Smuzhiyun 		return;
270*4882a593Smuzhiyun 	}
271*4882a593Smuzhiyun 	set_reg_bits(state->tab_init, 0x02, 0x0f, val);
272*4882a593Smuzhiyun 
273*4882a593Smuzhiyun 	/* set inverted IF or normal IF */
274*4882a593Smuzhiyun 	set_reg_bits(state->tab_init, 0x02, 0x10, invert_if ? 0x10 : 0x00);
275*4882a593Smuzhiyun 
276*4882a593Smuzhiyun 	state->if_freq = if_freq;
277*4882a593Smuzhiyun 
278*4882a593Smuzhiyun 	return;
279*4882a593Smuzhiyun }
280*4882a593Smuzhiyun 
mxl5007t_set_xtal_freq_bits(struct mxl5007t_state * state,enum mxl5007t_xtal_freq xtal_freq)281*4882a593Smuzhiyun static void mxl5007t_set_xtal_freq_bits(struct mxl5007t_state *state,
282*4882a593Smuzhiyun 					enum mxl5007t_xtal_freq xtal_freq)
283*4882a593Smuzhiyun {
284*4882a593Smuzhiyun 	switch (xtal_freq) {
285*4882a593Smuzhiyun 	case MxL_XTAL_16_MHZ:
286*4882a593Smuzhiyun 		/* select xtal freq & ref freq */
287*4882a593Smuzhiyun 		set_reg_bits(state->tab_init, 0x03, 0xf0, 0x00);
288*4882a593Smuzhiyun 		set_reg_bits(state->tab_init, 0x05, 0x0f, 0x00);
289*4882a593Smuzhiyun 		break;
290*4882a593Smuzhiyun 	case MxL_XTAL_20_MHZ:
291*4882a593Smuzhiyun 		set_reg_bits(state->tab_init, 0x03, 0xf0, 0x10);
292*4882a593Smuzhiyun 		set_reg_bits(state->tab_init, 0x05, 0x0f, 0x01);
293*4882a593Smuzhiyun 		break;
294*4882a593Smuzhiyun 	case MxL_XTAL_20_25_MHZ:
295*4882a593Smuzhiyun 		set_reg_bits(state->tab_init, 0x03, 0xf0, 0x20);
296*4882a593Smuzhiyun 		set_reg_bits(state->tab_init, 0x05, 0x0f, 0x02);
297*4882a593Smuzhiyun 		break;
298*4882a593Smuzhiyun 	case MxL_XTAL_20_48_MHZ:
299*4882a593Smuzhiyun 		set_reg_bits(state->tab_init, 0x03, 0xf0, 0x30);
300*4882a593Smuzhiyun 		set_reg_bits(state->tab_init, 0x05, 0x0f, 0x03);
301*4882a593Smuzhiyun 		break;
302*4882a593Smuzhiyun 	case MxL_XTAL_24_MHZ:
303*4882a593Smuzhiyun 		set_reg_bits(state->tab_init, 0x03, 0xf0, 0x40);
304*4882a593Smuzhiyun 		set_reg_bits(state->tab_init, 0x05, 0x0f, 0x04);
305*4882a593Smuzhiyun 		break;
306*4882a593Smuzhiyun 	case MxL_XTAL_25_MHZ:
307*4882a593Smuzhiyun 		set_reg_bits(state->tab_init, 0x03, 0xf0, 0x50);
308*4882a593Smuzhiyun 		set_reg_bits(state->tab_init, 0x05, 0x0f, 0x05);
309*4882a593Smuzhiyun 		break;
310*4882a593Smuzhiyun 	case MxL_XTAL_25_14_MHZ:
311*4882a593Smuzhiyun 		set_reg_bits(state->tab_init, 0x03, 0xf0, 0x60);
312*4882a593Smuzhiyun 		set_reg_bits(state->tab_init, 0x05, 0x0f, 0x06);
313*4882a593Smuzhiyun 		break;
314*4882a593Smuzhiyun 	case MxL_XTAL_27_MHZ:
315*4882a593Smuzhiyun 		set_reg_bits(state->tab_init, 0x03, 0xf0, 0x70);
316*4882a593Smuzhiyun 		set_reg_bits(state->tab_init, 0x05, 0x0f, 0x07);
317*4882a593Smuzhiyun 		break;
318*4882a593Smuzhiyun 	case MxL_XTAL_28_8_MHZ:
319*4882a593Smuzhiyun 		set_reg_bits(state->tab_init, 0x03, 0xf0, 0x80);
320*4882a593Smuzhiyun 		set_reg_bits(state->tab_init, 0x05, 0x0f, 0x08);
321*4882a593Smuzhiyun 		break;
322*4882a593Smuzhiyun 	case MxL_XTAL_32_MHZ:
323*4882a593Smuzhiyun 		set_reg_bits(state->tab_init, 0x03, 0xf0, 0x90);
324*4882a593Smuzhiyun 		set_reg_bits(state->tab_init, 0x05, 0x0f, 0x09);
325*4882a593Smuzhiyun 		break;
326*4882a593Smuzhiyun 	case MxL_XTAL_40_MHZ:
327*4882a593Smuzhiyun 		set_reg_bits(state->tab_init, 0x03, 0xf0, 0xa0);
328*4882a593Smuzhiyun 		set_reg_bits(state->tab_init, 0x05, 0x0f, 0x0a);
329*4882a593Smuzhiyun 		break;
330*4882a593Smuzhiyun 	case MxL_XTAL_44_MHZ:
331*4882a593Smuzhiyun 		set_reg_bits(state->tab_init, 0x03, 0xf0, 0xb0);
332*4882a593Smuzhiyun 		set_reg_bits(state->tab_init, 0x05, 0x0f, 0x0b);
333*4882a593Smuzhiyun 		break;
334*4882a593Smuzhiyun 	case MxL_XTAL_48_MHZ:
335*4882a593Smuzhiyun 		set_reg_bits(state->tab_init, 0x03, 0xf0, 0xc0);
336*4882a593Smuzhiyun 		set_reg_bits(state->tab_init, 0x05, 0x0f, 0x0c);
337*4882a593Smuzhiyun 		break;
338*4882a593Smuzhiyun 	case MxL_XTAL_49_3811_MHZ:
339*4882a593Smuzhiyun 		set_reg_bits(state->tab_init, 0x03, 0xf0, 0xd0);
340*4882a593Smuzhiyun 		set_reg_bits(state->tab_init, 0x05, 0x0f, 0x0d);
341*4882a593Smuzhiyun 		break;
342*4882a593Smuzhiyun 	default:
343*4882a593Smuzhiyun 		mxl_fail(-EINVAL);
344*4882a593Smuzhiyun 		return;
345*4882a593Smuzhiyun 	}
346*4882a593Smuzhiyun 
347*4882a593Smuzhiyun 	return;
348*4882a593Smuzhiyun }
349*4882a593Smuzhiyun 
mxl5007t_calc_init_regs(struct mxl5007t_state * state,enum mxl5007t_mode mode)350*4882a593Smuzhiyun static struct reg_pair_t *mxl5007t_calc_init_regs(struct mxl5007t_state *state,
351*4882a593Smuzhiyun 						  enum mxl5007t_mode mode)
352*4882a593Smuzhiyun {
353*4882a593Smuzhiyun 	struct mxl5007t_config *cfg = state->config;
354*4882a593Smuzhiyun 
355*4882a593Smuzhiyun 	memcpy(&state->tab_init, &init_tab, sizeof(init_tab));
356*4882a593Smuzhiyun 	memcpy(&state->tab_init_cable, &init_tab_cable, sizeof(init_tab_cable));
357*4882a593Smuzhiyun 
358*4882a593Smuzhiyun 	mxl5007t_set_mode_bits(state, mode, cfg->if_diff_out_level);
359*4882a593Smuzhiyun 	mxl5007t_set_if_freq_bits(state, cfg->if_freq_hz, cfg->invert_if);
360*4882a593Smuzhiyun 	mxl5007t_set_xtal_freq_bits(state, cfg->xtal_freq_hz);
361*4882a593Smuzhiyun 
362*4882a593Smuzhiyun 	set_reg_bits(state->tab_init, 0x03, 0x08, cfg->clk_out_enable << 3);
363*4882a593Smuzhiyun 	set_reg_bits(state->tab_init, 0x03, 0x07, cfg->clk_out_amp);
364*4882a593Smuzhiyun 
365*4882a593Smuzhiyun 	if (mode >= MxL_MODE_CABLE) {
366*4882a593Smuzhiyun 		copy_reg_bits(state->tab_init, state->tab_init_cable);
367*4882a593Smuzhiyun 		return state->tab_init_cable;
368*4882a593Smuzhiyun 	} else
369*4882a593Smuzhiyun 		return state->tab_init;
370*4882a593Smuzhiyun }
371*4882a593Smuzhiyun 
372*4882a593Smuzhiyun /* ------------------------------------------------------------------------- */
373*4882a593Smuzhiyun 
374*4882a593Smuzhiyun enum mxl5007t_bw_mhz {
375*4882a593Smuzhiyun 	MxL_BW_6MHz = 6,
376*4882a593Smuzhiyun 	MxL_BW_7MHz = 7,
377*4882a593Smuzhiyun 	MxL_BW_8MHz = 8,
378*4882a593Smuzhiyun };
379*4882a593Smuzhiyun 
mxl5007t_set_bw_bits(struct mxl5007t_state * state,enum mxl5007t_bw_mhz bw)380*4882a593Smuzhiyun static void mxl5007t_set_bw_bits(struct mxl5007t_state *state,
381*4882a593Smuzhiyun 				 enum mxl5007t_bw_mhz bw)
382*4882a593Smuzhiyun {
383*4882a593Smuzhiyun 	u8 val;
384*4882a593Smuzhiyun 
385*4882a593Smuzhiyun 	switch (bw) {
386*4882a593Smuzhiyun 	case MxL_BW_6MHz:
387*4882a593Smuzhiyun 		val = 0x15; /* set DIG_MODEINDEX, DIG_MODEINDEX_A,
388*4882a593Smuzhiyun 			     * and DIG_MODEINDEX_CSF */
389*4882a593Smuzhiyun 		break;
390*4882a593Smuzhiyun 	case MxL_BW_7MHz:
391*4882a593Smuzhiyun 		val = 0x2a;
392*4882a593Smuzhiyun 		break;
393*4882a593Smuzhiyun 	case MxL_BW_8MHz:
394*4882a593Smuzhiyun 		val = 0x3f;
395*4882a593Smuzhiyun 		break;
396*4882a593Smuzhiyun 	default:
397*4882a593Smuzhiyun 		mxl_fail(-EINVAL);
398*4882a593Smuzhiyun 		return;
399*4882a593Smuzhiyun 	}
400*4882a593Smuzhiyun 	set_reg_bits(state->tab_rftune, 0x0c, 0x3f, val);
401*4882a593Smuzhiyun 
402*4882a593Smuzhiyun 	return;
403*4882a593Smuzhiyun }
404*4882a593Smuzhiyun 
405*4882a593Smuzhiyun static struct
mxl5007t_calc_rf_tune_regs(struct mxl5007t_state * state,u32 rf_freq,enum mxl5007t_bw_mhz bw)406*4882a593Smuzhiyun reg_pair_t *mxl5007t_calc_rf_tune_regs(struct mxl5007t_state *state,
407*4882a593Smuzhiyun 				       u32 rf_freq, enum mxl5007t_bw_mhz bw)
408*4882a593Smuzhiyun {
409*4882a593Smuzhiyun 	u32 dig_rf_freq = 0;
410*4882a593Smuzhiyun 	u32 temp;
411*4882a593Smuzhiyun 	u32 frac_divider = 1000000;
412*4882a593Smuzhiyun 	unsigned int i;
413*4882a593Smuzhiyun 
414*4882a593Smuzhiyun 	memcpy(&state->tab_rftune, &reg_pair_rftune, sizeof(reg_pair_rftune));
415*4882a593Smuzhiyun 
416*4882a593Smuzhiyun 	mxl5007t_set_bw_bits(state, bw);
417*4882a593Smuzhiyun 
418*4882a593Smuzhiyun 	/* Convert RF frequency into 16 bits =>
419*4882a593Smuzhiyun 	 * 10 bit integer (MHz) + 6 bit fraction */
420*4882a593Smuzhiyun 	dig_rf_freq = rf_freq / MHz;
421*4882a593Smuzhiyun 
422*4882a593Smuzhiyun 	temp = rf_freq % MHz;
423*4882a593Smuzhiyun 
424*4882a593Smuzhiyun 	for (i = 0; i < 6; i++) {
425*4882a593Smuzhiyun 		dig_rf_freq <<= 1;
426*4882a593Smuzhiyun 		frac_divider /= 2;
427*4882a593Smuzhiyun 		if (temp > frac_divider) {
428*4882a593Smuzhiyun 			temp -= frac_divider;
429*4882a593Smuzhiyun 			dig_rf_freq++;
430*4882a593Smuzhiyun 		}
431*4882a593Smuzhiyun 	}
432*4882a593Smuzhiyun 
433*4882a593Smuzhiyun 	/* add to have shift center point by 7.8124 kHz */
434*4882a593Smuzhiyun 	if (temp > 7812)
435*4882a593Smuzhiyun 		dig_rf_freq++;
436*4882a593Smuzhiyun 
437*4882a593Smuzhiyun 	set_reg_bits(state->tab_rftune, 0x0d, 0xff, (u8) dig_rf_freq);
438*4882a593Smuzhiyun 	set_reg_bits(state->tab_rftune, 0x0e, 0xff, (u8) (dig_rf_freq >> 8));
439*4882a593Smuzhiyun 
440*4882a593Smuzhiyun 	if (rf_freq >= 333000000)
441*4882a593Smuzhiyun 		set_reg_bits(state->tab_rftune, 0x80, 0x40, 0x40);
442*4882a593Smuzhiyun 
443*4882a593Smuzhiyun 	return state->tab_rftune;
444*4882a593Smuzhiyun }
445*4882a593Smuzhiyun 
446*4882a593Smuzhiyun /* ------------------------------------------------------------------------- */
447*4882a593Smuzhiyun 
mxl5007t_write_reg(struct mxl5007t_state * state,u8 reg,u8 val)448*4882a593Smuzhiyun static int mxl5007t_write_reg(struct mxl5007t_state *state, u8 reg, u8 val)
449*4882a593Smuzhiyun {
450*4882a593Smuzhiyun 	u8 buf[] = { reg, val };
451*4882a593Smuzhiyun 	struct i2c_msg msg = { .addr = state->i2c_props.addr, .flags = 0,
452*4882a593Smuzhiyun 			       .buf = buf, .len = 2 };
453*4882a593Smuzhiyun 	int ret;
454*4882a593Smuzhiyun 
455*4882a593Smuzhiyun 	ret = i2c_transfer(state->i2c_props.adap, &msg, 1);
456*4882a593Smuzhiyun 	if (ret != 1) {
457*4882a593Smuzhiyun 		mxl_err("failed!");
458*4882a593Smuzhiyun 		return -EREMOTEIO;
459*4882a593Smuzhiyun 	}
460*4882a593Smuzhiyun 	return 0;
461*4882a593Smuzhiyun }
462*4882a593Smuzhiyun 
mxl5007t_write_regs(struct mxl5007t_state * state,struct reg_pair_t * reg_pair)463*4882a593Smuzhiyun static int mxl5007t_write_regs(struct mxl5007t_state *state,
464*4882a593Smuzhiyun 			       struct reg_pair_t *reg_pair)
465*4882a593Smuzhiyun {
466*4882a593Smuzhiyun 	unsigned int i = 0;
467*4882a593Smuzhiyun 	int ret = 0;
468*4882a593Smuzhiyun 
469*4882a593Smuzhiyun 	while ((ret == 0) && (reg_pair[i].reg || reg_pair[i].val)) {
470*4882a593Smuzhiyun 		ret = mxl5007t_write_reg(state,
471*4882a593Smuzhiyun 					 reg_pair[i].reg, reg_pair[i].val);
472*4882a593Smuzhiyun 		i++;
473*4882a593Smuzhiyun 	}
474*4882a593Smuzhiyun 	return ret;
475*4882a593Smuzhiyun }
476*4882a593Smuzhiyun 
mxl5007t_read_reg(struct mxl5007t_state * state,u8 reg,u8 * val)477*4882a593Smuzhiyun static int mxl5007t_read_reg(struct mxl5007t_state *state, u8 reg, u8 *val)
478*4882a593Smuzhiyun {
479*4882a593Smuzhiyun 	u8 buf[2] = { 0xfb, reg };
480*4882a593Smuzhiyun 	struct i2c_msg msg[] = {
481*4882a593Smuzhiyun 		{ .addr = state->i2c_props.addr, .flags = 0,
482*4882a593Smuzhiyun 		  .buf = buf, .len = 2 },
483*4882a593Smuzhiyun 		{ .addr = state->i2c_props.addr, .flags = I2C_M_RD,
484*4882a593Smuzhiyun 		  .buf = val, .len = 1 },
485*4882a593Smuzhiyun 	};
486*4882a593Smuzhiyun 	int ret;
487*4882a593Smuzhiyun 
488*4882a593Smuzhiyun 	ret = i2c_transfer(state->i2c_props.adap, msg, 2);
489*4882a593Smuzhiyun 	if (ret != 2) {
490*4882a593Smuzhiyun 		mxl_err("failed!");
491*4882a593Smuzhiyun 		return -EREMOTEIO;
492*4882a593Smuzhiyun 	}
493*4882a593Smuzhiyun 	return 0;
494*4882a593Smuzhiyun }
495*4882a593Smuzhiyun 
mxl5007t_soft_reset(struct mxl5007t_state * state)496*4882a593Smuzhiyun static int mxl5007t_soft_reset(struct mxl5007t_state *state)
497*4882a593Smuzhiyun {
498*4882a593Smuzhiyun 	u8 d = 0xff;
499*4882a593Smuzhiyun 	struct i2c_msg msg = {
500*4882a593Smuzhiyun 		.addr = state->i2c_props.addr, .flags = 0,
501*4882a593Smuzhiyun 		.buf = &d, .len = 1
502*4882a593Smuzhiyun 	};
503*4882a593Smuzhiyun 	int ret = i2c_transfer(state->i2c_props.adap, &msg, 1);
504*4882a593Smuzhiyun 
505*4882a593Smuzhiyun 	if (ret != 1) {
506*4882a593Smuzhiyun 		mxl_err("failed!");
507*4882a593Smuzhiyun 		return -EREMOTEIO;
508*4882a593Smuzhiyun 	}
509*4882a593Smuzhiyun 	return 0;
510*4882a593Smuzhiyun }
511*4882a593Smuzhiyun 
mxl5007t_tuner_init(struct mxl5007t_state * state,enum mxl5007t_mode mode)512*4882a593Smuzhiyun static int mxl5007t_tuner_init(struct mxl5007t_state *state,
513*4882a593Smuzhiyun 			       enum mxl5007t_mode mode)
514*4882a593Smuzhiyun {
515*4882a593Smuzhiyun 	struct reg_pair_t *init_regs;
516*4882a593Smuzhiyun 	int ret;
517*4882a593Smuzhiyun 
518*4882a593Smuzhiyun 	/* calculate initialization reg array */
519*4882a593Smuzhiyun 	init_regs = mxl5007t_calc_init_regs(state, mode);
520*4882a593Smuzhiyun 
521*4882a593Smuzhiyun 	ret = mxl5007t_write_regs(state, init_regs);
522*4882a593Smuzhiyun 	if (mxl_fail(ret))
523*4882a593Smuzhiyun 		goto fail;
524*4882a593Smuzhiyun 	mdelay(1);
525*4882a593Smuzhiyun fail:
526*4882a593Smuzhiyun 	return ret;
527*4882a593Smuzhiyun }
528*4882a593Smuzhiyun 
mxl5007t_tuner_rf_tune(struct mxl5007t_state * state,u32 rf_freq_hz,enum mxl5007t_bw_mhz bw)529*4882a593Smuzhiyun static int mxl5007t_tuner_rf_tune(struct mxl5007t_state *state, u32 rf_freq_hz,
530*4882a593Smuzhiyun 				  enum mxl5007t_bw_mhz bw)
531*4882a593Smuzhiyun {
532*4882a593Smuzhiyun 	struct reg_pair_t *rf_tune_regs;
533*4882a593Smuzhiyun 	int ret;
534*4882a593Smuzhiyun 
535*4882a593Smuzhiyun 	/* calculate channel change reg array */
536*4882a593Smuzhiyun 	rf_tune_regs = mxl5007t_calc_rf_tune_regs(state, rf_freq_hz, bw);
537*4882a593Smuzhiyun 
538*4882a593Smuzhiyun 	ret = mxl5007t_write_regs(state, rf_tune_regs);
539*4882a593Smuzhiyun 	if (mxl_fail(ret))
540*4882a593Smuzhiyun 		goto fail;
541*4882a593Smuzhiyun 	msleep(3);
542*4882a593Smuzhiyun fail:
543*4882a593Smuzhiyun 	return ret;
544*4882a593Smuzhiyun }
545*4882a593Smuzhiyun 
546*4882a593Smuzhiyun /* ------------------------------------------------------------------------- */
547*4882a593Smuzhiyun 
mxl5007t_synth_lock_status(struct mxl5007t_state * state,int * rf_locked,int * ref_locked)548*4882a593Smuzhiyun static int mxl5007t_synth_lock_status(struct mxl5007t_state *state,
549*4882a593Smuzhiyun 				      int *rf_locked, int *ref_locked)
550*4882a593Smuzhiyun {
551*4882a593Smuzhiyun 	u8 d;
552*4882a593Smuzhiyun 	int ret;
553*4882a593Smuzhiyun 
554*4882a593Smuzhiyun 	*rf_locked = 0;
555*4882a593Smuzhiyun 	*ref_locked = 0;
556*4882a593Smuzhiyun 
557*4882a593Smuzhiyun 	ret = mxl5007t_read_reg(state, 0xd8, &d);
558*4882a593Smuzhiyun 	if (mxl_fail(ret))
559*4882a593Smuzhiyun 		goto fail;
560*4882a593Smuzhiyun 
561*4882a593Smuzhiyun 	if ((d & 0x0c) == 0x0c)
562*4882a593Smuzhiyun 		*rf_locked = 1;
563*4882a593Smuzhiyun 
564*4882a593Smuzhiyun 	if ((d & 0x03) == 0x03)
565*4882a593Smuzhiyun 		*ref_locked = 1;
566*4882a593Smuzhiyun fail:
567*4882a593Smuzhiyun 	return ret;
568*4882a593Smuzhiyun }
569*4882a593Smuzhiyun 
570*4882a593Smuzhiyun /* ------------------------------------------------------------------------- */
571*4882a593Smuzhiyun 
mxl5007t_get_status(struct dvb_frontend * fe,u32 * status)572*4882a593Smuzhiyun static int mxl5007t_get_status(struct dvb_frontend *fe, u32 *status)
573*4882a593Smuzhiyun {
574*4882a593Smuzhiyun 	struct mxl5007t_state *state = fe->tuner_priv;
575*4882a593Smuzhiyun 	int rf_locked, ref_locked, ret;
576*4882a593Smuzhiyun 
577*4882a593Smuzhiyun 	*status = 0;
578*4882a593Smuzhiyun 
579*4882a593Smuzhiyun 	if (fe->ops.i2c_gate_ctrl)
580*4882a593Smuzhiyun 		fe->ops.i2c_gate_ctrl(fe, 1);
581*4882a593Smuzhiyun 
582*4882a593Smuzhiyun 	ret = mxl5007t_synth_lock_status(state, &rf_locked, &ref_locked);
583*4882a593Smuzhiyun 	if (mxl_fail(ret))
584*4882a593Smuzhiyun 		goto fail;
585*4882a593Smuzhiyun 	mxl_debug("%s%s", rf_locked ? "rf locked " : "",
586*4882a593Smuzhiyun 		  ref_locked ? "ref locked" : "");
587*4882a593Smuzhiyun 
588*4882a593Smuzhiyun 	if ((rf_locked) || (ref_locked))
589*4882a593Smuzhiyun 		*status |= TUNER_STATUS_LOCKED;
590*4882a593Smuzhiyun fail:
591*4882a593Smuzhiyun 	if (fe->ops.i2c_gate_ctrl)
592*4882a593Smuzhiyun 		fe->ops.i2c_gate_ctrl(fe, 0);
593*4882a593Smuzhiyun 
594*4882a593Smuzhiyun 	return ret;
595*4882a593Smuzhiyun }
596*4882a593Smuzhiyun 
597*4882a593Smuzhiyun /* ------------------------------------------------------------------------- */
598*4882a593Smuzhiyun 
mxl5007t_set_params(struct dvb_frontend * fe)599*4882a593Smuzhiyun static int mxl5007t_set_params(struct dvb_frontend *fe)
600*4882a593Smuzhiyun {
601*4882a593Smuzhiyun 	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
602*4882a593Smuzhiyun 	u32 delsys = c->delivery_system;
603*4882a593Smuzhiyun 	struct mxl5007t_state *state = fe->tuner_priv;
604*4882a593Smuzhiyun 	enum mxl5007t_bw_mhz bw;
605*4882a593Smuzhiyun 	enum mxl5007t_mode mode;
606*4882a593Smuzhiyun 	int ret;
607*4882a593Smuzhiyun 	u32 freq = c->frequency;
608*4882a593Smuzhiyun 
609*4882a593Smuzhiyun 	switch (delsys) {
610*4882a593Smuzhiyun 	case SYS_ATSC:
611*4882a593Smuzhiyun 		mode = MxL_MODE_ATSC;
612*4882a593Smuzhiyun 		bw = MxL_BW_6MHz;
613*4882a593Smuzhiyun 		break;
614*4882a593Smuzhiyun 	case SYS_DVBC_ANNEX_B:
615*4882a593Smuzhiyun 		mode = MxL_MODE_CABLE;
616*4882a593Smuzhiyun 		bw = MxL_BW_6MHz;
617*4882a593Smuzhiyun 		break;
618*4882a593Smuzhiyun 	case SYS_DVBT:
619*4882a593Smuzhiyun 	case SYS_DVBT2:
620*4882a593Smuzhiyun 		mode = MxL_MODE_DVBT;
621*4882a593Smuzhiyun 		switch (c->bandwidth_hz) {
622*4882a593Smuzhiyun 		case 6000000:
623*4882a593Smuzhiyun 			bw = MxL_BW_6MHz;
624*4882a593Smuzhiyun 			break;
625*4882a593Smuzhiyun 		case 7000000:
626*4882a593Smuzhiyun 			bw = MxL_BW_7MHz;
627*4882a593Smuzhiyun 			break;
628*4882a593Smuzhiyun 		case 8000000:
629*4882a593Smuzhiyun 			bw = MxL_BW_8MHz;
630*4882a593Smuzhiyun 			break;
631*4882a593Smuzhiyun 		default:
632*4882a593Smuzhiyun 			return -EINVAL;
633*4882a593Smuzhiyun 		}
634*4882a593Smuzhiyun 		break;
635*4882a593Smuzhiyun 	default:
636*4882a593Smuzhiyun 		mxl_err("modulation type not supported!");
637*4882a593Smuzhiyun 		return -EINVAL;
638*4882a593Smuzhiyun 	}
639*4882a593Smuzhiyun 
640*4882a593Smuzhiyun 	if (fe->ops.i2c_gate_ctrl)
641*4882a593Smuzhiyun 		fe->ops.i2c_gate_ctrl(fe, 1);
642*4882a593Smuzhiyun 
643*4882a593Smuzhiyun 	mutex_lock(&state->lock);
644*4882a593Smuzhiyun 
645*4882a593Smuzhiyun 	ret = mxl5007t_tuner_init(state, mode);
646*4882a593Smuzhiyun 	if (mxl_fail(ret))
647*4882a593Smuzhiyun 		goto fail;
648*4882a593Smuzhiyun 
649*4882a593Smuzhiyun 	ret = mxl5007t_tuner_rf_tune(state, freq, bw);
650*4882a593Smuzhiyun 	if (mxl_fail(ret))
651*4882a593Smuzhiyun 		goto fail;
652*4882a593Smuzhiyun 
653*4882a593Smuzhiyun 	state->frequency = freq;
654*4882a593Smuzhiyun 	state->bandwidth = c->bandwidth_hz;
655*4882a593Smuzhiyun fail:
656*4882a593Smuzhiyun 	mutex_unlock(&state->lock);
657*4882a593Smuzhiyun 
658*4882a593Smuzhiyun 	if (fe->ops.i2c_gate_ctrl)
659*4882a593Smuzhiyun 		fe->ops.i2c_gate_ctrl(fe, 0);
660*4882a593Smuzhiyun 
661*4882a593Smuzhiyun 	return ret;
662*4882a593Smuzhiyun }
663*4882a593Smuzhiyun 
664*4882a593Smuzhiyun /* ------------------------------------------------------------------------- */
665*4882a593Smuzhiyun 
mxl5007t_init(struct dvb_frontend * fe)666*4882a593Smuzhiyun static int mxl5007t_init(struct dvb_frontend *fe)
667*4882a593Smuzhiyun {
668*4882a593Smuzhiyun 	struct mxl5007t_state *state = fe->tuner_priv;
669*4882a593Smuzhiyun 	int ret;
670*4882a593Smuzhiyun 
671*4882a593Smuzhiyun 	if (fe->ops.i2c_gate_ctrl)
672*4882a593Smuzhiyun 		fe->ops.i2c_gate_ctrl(fe, 1);
673*4882a593Smuzhiyun 
674*4882a593Smuzhiyun 	/* wake from standby */
675*4882a593Smuzhiyun 	ret = mxl5007t_write_reg(state, 0x01, 0x01);
676*4882a593Smuzhiyun 	mxl_fail(ret);
677*4882a593Smuzhiyun 
678*4882a593Smuzhiyun 	if (fe->ops.i2c_gate_ctrl)
679*4882a593Smuzhiyun 		fe->ops.i2c_gate_ctrl(fe, 0);
680*4882a593Smuzhiyun 
681*4882a593Smuzhiyun 	return ret;
682*4882a593Smuzhiyun }
683*4882a593Smuzhiyun 
mxl5007t_sleep(struct dvb_frontend * fe)684*4882a593Smuzhiyun static int mxl5007t_sleep(struct dvb_frontend *fe)
685*4882a593Smuzhiyun {
686*4882a593Smuzhiyun 	struct mxl5007t_state *state = fe->tuner_priv;
687*4882a593Smuzhiyun 	int ret;
688*4882a593Smuzhiyun 
689*4882a593Smuzhiyun 	if (fe->ops.i2c_gate_ctrl)
690*4882a593Smuzhiyun 		fe->ops.i2c_gate_ctrl(fe, 1);
691*4882a593Smuzhiyun 
692*4882a593Smuzhiyun 	/* enter standby mode */
693*4882a593Smuzhiyun 	ret = mxl5007t_write_reg(state, 0x01, 0x00);
694*4882a593Smuzhiyun 	mxl_fail(ret);
695*4882a593Smuzhiyun 	ret = mxl5007t_write_reg(state, 0x0f, 0x00);
696*4882a593Smuzhiyun 	mxl_fail(ret);
697*4882a593Smuzhiyun 
698*4882a593Smuzhiyun 	if (fe->ops.i2c_gate_ctrl)
699*4882a593Smuzhiyun 		fe->ops.i2c_gate_ctrl(fe, 0);
700*4882a593Smuzhiyun 
701*4882a593Smuzhiyun 	return ret;
702*4882a593Smuzhiyun }
703*4882a593Smuzhiyun 
704*4882a593Smuzhiyun /* ------------------------------------------------------------------------- */
705*4882a593Smuzhiyun 
mxl5007t_get_frequency(struct dvb_frontend * fe,u32 * frequency)706*4882a593Smuzhiyun static int mxl5007t_get_frequency(struct dvb_frontend *fe, u32 *frequency)
707*4882a593Smuzhiyun {
708*4882a593Smuzhiyun 	struct mxl5007t_state *state = fe->tuner_priv;
709*4882a593Smuzhiyun 	*frequency = state->frequency;
710*4882a593Smuzhiyun 	return 0;
711*4882a593Smuzhiyun }
712*4882a593Smuzhiyun 
mxl5007t_get_bandwidth(struct dvb_frontend * fe,u32 * bandwidth)713*4882a593Smuzhiyun static int mxl5007t_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
714*4882a593Smuzhiyun {
715*4882a593Smuzhiyun 	struct mxl5007t_state *state = fe->tuner_priv;
716*4882a593Smuzhiyun 	*bandwidth = state->bandwidth;
717*4882a593Smuzhiyun 	return 0;
718*4882a593Smuzhiyun }
719*4882a593Smuzhiyun 
mxl5007t_get_if_frequency(struct dvb_frontend * fe,u32 * frequency)720*4882a593Smuzhiyun static int mxl5007t_get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
721*4882a593Smuzhiyun {
722*4882a593Smuzhiyun 	struct mxl5007t_state *state = fe->tuner_priv;
723*4882a593Smuzhiyun 
724*4882a593Smuzhiyun 	*frequency = 0;
725*4882a593Smuzhiyun 
726*4882a593Smuzhiyun 	switch (state->if_freq) {
727*4882a593Smuzhiyun 	case MxL_IF_4_MHZ:
728*4882a593Smuzhiyun 		*frequency = 4000000;
729*4882a593Smuzhiyun 		break;
730*4882a593Smuzhiyun 	case MxL_IF_4_5_MHZ:
731*4882a593Smuzhiyun 		*frequency = 4500000;
732*4882a593Smuzhiyun 		break;
733*4882a593Smuzhiyun 	case MxL_IF_4_57_MHZ:
734*4882a593Smuzhiyun 		*frequency = 4570000;
735*4882a593Smuzhiyun 		break;
736*4882a593Smuzhiyun 	case MxL_IF_5_MHZ:
737*4882a593Smuzhiyun 		*frequency = 5000000;
738*4882a593Smuzhiyun 		break;
739*4882a593Smuzhiyun 	case MxL_IF_5_38_MHZ:
740*4882a593Smuzhiyun 		*frequency = 5380000;
741*4882a593Smuzhiyun 		break;
742*4882a593Smuzhiyun 	case MxL_IF_6_MHZ:
743*4882a593Smuzhiyun 		*frequency = 6000000;
744*4882a593Smuzhiyun 		break;
745*4882a593Smuzhiyun 	case MxL_IF_6_28_MHZ:
746*4882a593Smuzhiyun 		*frequency = 6280000;
747*4882a593Smuzhiyun 		break;
748*4882a593Smuzhiyun 	case MxL_IF_9_1915_MHZ:
749*4882a593Smuzhiyun 		*frequency = 9191500;
750*4882a593Smuzhiyun 		break;
751*4882a593Smuzhiyun 	case MxL_IF_35_25_MHZ:
752*4882a593Smuzhiyun 		*frequency = 35250000;
753*4882a593Smuzhiyun 		break;
754*4882a593Smuzhiyun 	case MxL_IF_36_15_MHZ:
755*4882a593Smuzhiyun 		*frequency = 36150000;
756*4882a593Smuzhiyun 		break;
757*4882a593Smuzhiyun 	case MxL_IF_44_MHZ:
758*4882a593Smuzhiyun 		*frequency = 44000000;
759*4882a593Smuzhiyun 		break;
760*4882a593Smuzhiyun 	}
761*4882a593Smuzhiyun 	return 0;
762*4882a593Smuzhiyun }
763*4882a593Smuzhiyun 
mxl5007t_release(struct dvb_frontend * fe)764*4882a593Smuzhiyun static void mxl5007t_release(struct dvb_frontend *fe)
765*4882a593Smuzhiyun {
766*4882a593Smuzhiyun 	struct mxl5007t_state *state = fe->tuner_priv;
767*4882a593Smuzhiyun 
768*4882a593Smuzhiyun 	mutex_lock(&mxl5007t_list_mutex);
769*4882a593Smuzhiyun 
770*4882a593Smuzhiyun 	if (state)
771*4882a593Smuzhiyun 		hybrid_tuner_release_state(state);
772*4882a593Smuzhiyun 
773*4882a593Smuzhiyun 	mutex_unlock(&mxl5007t_list_mutex);
774*4882a593Smuzhiyun 
775*4882a593Smuzhiyun 	fe->tuner_priv = NULL;
776*4882a593Smuzhiyun }
777*4882a593Smuzhiyun 
778*4882a593Smuzhiyun /* ------------------------------------------------------------------------- */
779*4882a593Smuzhiyun 
780*4882a593Smuzhiyun static const struct dvb_tuner_ops mxl5007t_tuner_ops = {
781*4882a593Smuzhiyun 	.info = {
782*4882a593Smuzhiyun 		.name = "MaxLinear MxL5007T",
783*4882a593Smuzhiyun 	},
784*4882a593Smuzhiyun 	.init              = mxl5007t_init,
785*4882a593Smuzhiyun 	.sleep             = mxl5007t_sleep,
786*4882a593Smuzhiyun 	.set_params        = mxl5007t_set_params,
787*4882a593Smuzhiyun 	.get_status        = mxl5007t_get_status,
788*4882a593Smuzhiyun 	.get_frequency     = mxl5007t_get_frequency,
789*4882a593Smuzhiyun 	.get_bandwidth     = mxl5007t_get_bandwidth,
790*4882a593Smuzhiyun 	.release           = mxl5007t_release,
791*4882a593Smuzhiyun 	.get_if_frequency  = mxl5007t_get_if_frequency,
792*4882a593Smuzhiyun };
793*4882a593Smuzhiyun 
mxl5007t_get_chip_id(struct mxl5007t_state * state)794*4882a593Smuzhiyun static int mxl5007t_get_chip_id(struct mxl5007t_state *state)
795*4882a593Smuzhiyun {
796*4882a593Smuzhiyun 	char *name;
797*4882a593Smuzhiyun 	int ret;
798*4882a593Smuzhiyun 	u8 id;
799*4882a593Smuzhiyun 
800*4882a593Smuzhiyun 	ret = mxl5007t_read_reg(state, 0xd9, &id);
801*4882a593Smuzhiyun 	if (mxl_fail(ret))
802*4882a593Smuzhiyun 		goto fail;
803*4882a593Smuzhiyun 
804*4882a593Smuzhiyun 	switch (id) {
805*4882a593Smuzhiyun 	case MxL_5007_V1_F1:
806*4882a593Smuzhiyun 		name = "MxL5007.v1.f1";
807*4882a593Smuzhiyun 		break;
808*4882a593Smuzhiyun 	case MxL_5007_V1_F2:
809*4882a593Smuzhiyun 		name = "MxL5007.v1.f2";
810*4882a593Smuzhiyun 		break;
811*4882a593Smuzhiyun 	case MxL_5007_V2_100_F1:
812*4882a593Smuzhiyun 		name = "MxL5007.v2.100.f1";
813*4882a593Smuzhiyun 		break;
814*4882a593Smuzhiyun 	case MxL_5007_V2_100_F2:
815*4882a593Smuzhiyun 		name = "MxL5007.v2.100.f2";
816*4882a593Smuzhiyun 		break;
817*4882a593Smuzhiyun 	case MxL_5007_V2_200_F1:
818*4882a593Smuzhiyun 		name = "MxL5007.v2.200.f1";
819*4882a593Smuzhiyun 		break;
820*4882a593Smuzhiyun 	case MxL_5007_V2_200_F2:
821*4882a593Smuzhiyun 		name = "MxL5007.v2.200.f2";
822*4882a593Smuzhiyun 		break;
823*4882a593Smuzhiyun 	case MxL_5007_V4:
824*4882a593Smuzhiyun 		name = "MxL5007T.v4";
825*4882a593Smuzhiyun 		break;
826*4882a593Smuzhiyun 	default:
827*4882a593Smuzhiyun 		name = "MxL5007T";
828*4882a593Smuzhiyun 		printk(KERN_WARNING "%s: unknown rev (%02x)\n", __func__, id);
829*4882a593Smuzhiyun 		id = MxL_UNKNOWN_ID;
830*4882a593Smuzhiyun 	}
831*4882a593Smuzhiyun 	state->chip_id = id;
832*4882a593Smuzhiyun 	mxl_info("%s detected @ %d-%04x", name,
833*4882a593Smuzhiyun 		 i2c_adapter_id(state->i2c_props.adap),
834*4882a593Smuzhiyun 		 state->i2c_props.addr);
835*4882a593Smuzhiyun 	return 0;
836*4882a593Smuzhiyun fail:
837*4882a593Smuzhiyun 	mxl_warn("unable to identify device @ %d-%04x",
838*4882a593Smuzhiyun 		 i2c_adapter_id(state->i2c_props.adap),
839*4882a593Smuzhiyun 		 state->i2c_props.addr);
840*4882a593Smuzhiyun 
841*4882a593Smuzhiyun 	state->chip_id = MxL_UNKNOWN_ID;
842*4882a593Smuzhiyun 	return ret;
843*4882a593Smuzhiyun }
844*4882a593Smuzhiyun 
mxl5007t_attach(struct dvb_frontend * fe,struct i2c_adapter * i2c,u8 addr,struct mxl5007t_config * cfg)845*4882a593Smuzhiyun struct dvb_frontend *mxl5007t_attach(struct dvb_frontend *fe,
846*4882a593Smuzhiyun 				     struct i2c_adapter *i2c, u8 addr,
847*4882a593Smuzhiyun 				     struct mxl5007t_config *cfg)
848*4882a593Smuzhiyun {
849*4882a593Smuzhiyun 	struct mxl5007t_state *state = NULL;
850*4882a593Smuzhiyun 	int instance, ret;
851*4882a593Smuzhiyun 
852*4882a593Smuzhiyun 	mutex_lock(&mxl5007t_list_mutex);
853*4882a593Smuzhiyun 	instance = hybrid_tuner_request_state(struct mxl5007t_state, state,
854*4882a593Smuzhiyun 					      hybrid_tuner_instance_list,
855*4882a593Smuzhiyun 					      i2c, addr, "mxl5007t");
856*4882a593Smuzhiyun 	switch (instance) {
857*4882a593Smuzhiyun 	case 0:
858*4882a593Smuzhiyun 		goto fail;
859*4882a593Smuzhiyun 	case 1:
860*4882a593Smuzhiyun 		/* new tuner instance */
861*4882a593Smuzhiyun 		state->config = cfg;
862*4882a593Smuzhiyun 
863*4882a593Smuzhiyun 		mutex_init(&state->lock);
864*4882a593Smuzhiyun 
865*4882a593Smuzhiyun 		if (fe->ops.i2c_gate_ctrl)
866*4882a593Smuzhiyun 			fe->ops.i2c_gate_ctrl(fe, 1);
867*4882a593Smuzhiyun 
868*4882a593Smuzhiyun 		ret = mxl5007t_get_chip_id(state);
869*4882a593Smuzhiyun 
870*4882a593Smuzhiyun 		if (fe->ops.i2c_gate_ctrl)
871*4882a593Smuzhiyun 			fe->ops.i2c_gate_ctrl(fe, 0);
872*4882a593Smuzhiyun 
873*4882a593Smuzhiyun 		/* check return value of mxl5007t_get_chip_id */
874*4882a593Smuzhiyun 		if (mxl_fail(ret))
875*4882a593Smuzhiyun 			goto fail;
876*4882a593Smuzhiyun 		break;
877*4882a593Smuzhiyun 	default:
878*4882a593Smuzhiyun 		/* existing tuner instance */
879*4882a593Smuzhiyun 		break;
880*4882a593Smuzhiyun 	}
881*4882a593Smuzhiyun 
882*4882a593Smuzhiyun 	if (fe->ops.i2c_gate_ctrl)
883*4882a593Smuzhiyun 		fe->ops.i2c_gate_ctrl(fe, 1);
884*4882a593Smuzhiyun 
885*4882a593Smuzhiyun 	ret = mxl5007t_soft_reset(state);
886*4882a593Smuzhiyun 
887*4882a593Smuzhiyun 	if (fe->ops.i2c_gate_ctrl)
888*4882a593Smuzhiyun 		fe->ops.i2c_gate_ctrl(fe, 0);
889*4882a593Smuzhiyun 
890*4882a593Smuzhiyun 	if (mxl_fail(ret))
891*4882a593Smuzhiyun 		goto fail;
892*4882a593Smuzhiyun 
893*4882a593Smuzhiyun 	if (fe->ops.i2c_gate_ctrl)
894*4882a593Smuzhiyun 		fe->ops.i2c_gate_ctrl(fe, 1);
895*4882a593Smuzhiyun 
896*4882a593Smuzhiyun 	ret = mxl5007t_write_reg(state, 0x04,
897*4882a593Smuzhiyun 		state->config->loop_thru_enable);
898*4882a593Smuzhiyun 
899*4882a593Smuzhiyun 	if (fe->ops.i2c_gate_ctrl)
900*4882a593Smuzhiyun 		fe->ops.i2c_gate_ctrl(fe, 0);
901*4882a593Smuzhiyun 
902*4882a593Smuzhiyun 	if (mxl_fail(ret))
903*4882a593Smuzhiyun 		goto fail;
904*4882a593Smuzhiyun 
905*4882a593Smuzhiyun 	fe->tuner_priv = state;
906*4882a593Smuzhiyun 
907*4882a593Smuzhiyun 	mutex_unlock(&mxl5007t_list_mutex);
908*4882a593Smuzhiyun 
909*4882a593Smuzhiyun 	memcpy(&fe->ops.tuner_ops, &mxl5007t_tuner_ops,
910*4882a593Smuzhiyun 	       sizeof(struct dvb_tuner_ops));
911*4882a593Smuzhiyun 
912*4882a593Smuzhiyun 	return fe;
913*4882a593Smuzhiyun fail:
914*4882a593Smuzhiyun 	mutex_unlock(&mxl5007t_list_mutex);
915*4882a593Smuzhiyun 
916*4882a593Smuzhiyun 	mxl5007t_release(fe);
917*4882a593Smuzhiyun 	return NULL;
918*4882a593Smuzhiyun }
919*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(mxl5007t_attach);
920*4882a593Smuzhiyun MODULE_DESCRIPTION("MaxLinear MxL5007T Silicon IC tuner driver");
921*4882a593Smuzhiyun MODULE_AUTHOR("Michael Krufky <mkrufky@linuxtv.org>");
922*4882a593Smuzhiyun MODULE_LICENSE("GPL");
923*4882a593Smuzhiyun MODULE_VERSION("0.2");
924