xref: /OK3568_Linux_fs/kernel/drivers/media/tuners/tuner-simple.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * i2c tv tuner chip device driver
4*4882a593Smuzhiyun  * controls all those simple 4-control-bytes style tuners.
5*4882a593Smuzhiyun  *
6*4882a593Smuzhiyun  * This "tuner-simple" module was split apart from the original "tuner" module.
7*4882a593Smuzhiyun  */
8*4882a593Smuzhiyun #include <linux/delay.h>
9*4882a593Smuzhiyun #include <linux/i2c.h>
10*4882a593Smuzhiyun #include <linux/videodev2.h>
11*4882a593Smuzhiyun #include <media/tuner.h>
12*4882a593Smuzhiyun #include <media/v4l2-common.h>
13*4882a593Smuzhiyun #include <media/tuner-types.h>
14*4882a593Smuzhiyun #include "tuner-i2c.h"
15*4882a593Smuzhiyun #include "tuner-simple.h"
16*4882a593Smuzhiyun 
17*4882a593Smuzhiyun static int debug;
18*4882a593Smuzhiyun module_param(debug, int, 0644);
19*4882a593Smuzhiyun MODULE_PARM_DESC(debug, "enable verbose debug messages");
20*4882a593Smuzhiyun 
21*4882a593Smuzhiyun #define TUNER_SIMPLE_MAX 64
22*4882a593Smuzhiyun static unsigned int simple_devcount;
23*4882a593Smuzhiyun 
24*4882a593Smuzhiyun static int offset;
25*4882a593Smuzhiyun module_param(offset, int, 0664);
26*4882a593Smuzhiyun MODULE_PARM_DESC(offset, "Allows to specify an offset for tuner");
27*4882a593Smuzhiyun 
28*4882a593Smuzhiyun static unsigned int atv_input[TUNER_SIMPLE_MAX] = \
29*4882a593Smuzhiyun 			{ [0 ... (TUNER_SIMPLE_MAX-1)] = 0 };
30*4882a593Smuzhiyun static unsigned int dtv_input[TUNER_SIMPLE_MAX] = \
31*4882a593Smuzhiyun 			{ [0 ... (TUNER_SIMPLE_MAX-1)] = 0 };
32*4882a593Smuzhiyun module_param_array(atv_input, int, NULL, 0644);
33*4882a593Smuzhiyun module_param_array(dtv_input, int, NULL, 0644);
34*4882a593Smuzhiyun MODULE_PARM_DESC(atv_input, "specify atv rf input, 0 for autoselect");
35*4882a593Smuzhiyun MODULE_PARM_DESC(dtv_input, "specify dtv rf input, 0 for autoselect");
36*4882a593Smuzhiyun 
37*4882a593Smuzhiyun /* ---------------------------------------------------------------------- */
38*4882a593Smuzhiyun 
39*4882a593Smuzhiyun /* tv standard selection for Temic 4046 FM5
40*4882a593Smuzhiyun    this value takes the low bits of control byte 2
41*4882a593Smuzhiyun    from datasheet Rev.01, Feb.00
42*4882a593Smuzhiyun      standard     BG      I       L       L2      D
43*4882a593Smuzhiyun      picture IF   38.9    38.9    38.9    33.95   38.9
44*4882a593Smuzhiyun      sound 1      33.4    32.9    32.4    40.45   32.4
45*4882a593Smuzhiyun      sound 2      33.16
46*4882a593Smuzhiyun      NICAM        33.05   32.348  33.05           33.05
47*4882a593Smuzhiyun  */
48*4882a593Smuzhiyun #define TEMIC_SET_PAL_I         0x05
49*4882a593Smuzhiyun #define TEMIC_SET_PAL_DK        0x09
50*4882a593Smuzhiyun #define TEMIC_SET_PAL_L         0x0a /* SECAM ? */
51*4882a593Smuzhiyun #define TEMIC_SET_PAL_L2        0x0b /* change IF ! */
52*4882a593Smuzhiyun #define TEMIC_SET_PAL_BG        0x0c
53*4882a593Smuzhiyun 
54*4882a593Smuzhiyun /* tv tuner system standard selection for Philips FQ1216ME
55*4882a593Smuzhiyun    this value takes the low bits of control byte 2
56*4882a593Smuzhiyun    from datasheet "1999 Nov 16" (supersedes "1999 Mar 23")
57*4882a593Smuzhiyun      standard		BG	DK	I	L	L`
58*4882a593Smuzhiyun      picture carrier	38.90	38.90	38.90	38.90	33.95
59*4882a593Smuzhiyun      colour		34.47	34.47	34.47	34.47	38.38
60*4882a593Smuzhiyun      sound 1		33.40	32.40	32.90	32.40	40.45
61*4882a593Smuzhiyun      sound 2		33.16	-	-	-	-
62*4882a593Smuzhiyun      NICAM		33.05	33.05	32.35	33.05	39.80
63*4882a593Smuzhiyun  */
64*4882a593Smuzhiyun #define PHILIPS_SET_PAL_I	0x01 /* Bit 2 always zero !*/
65*4882a593Smuzhiyun #define PHILIPS_SET_PAL_BGDK	0x09
66*4882a593Smuzhiyun #define PHILIPS_SET_PAL_L2	0x0a
67*4882a593Smuzhiyun #define PHILIPS_SET_PAL_L	0x0b
68*4882a593Smuzhiyun 
69*4882a593Smuzhiyun /* system switching for Philips FI1216MF MK2
70*4882a593Smuzhiyun    from datasheet "1996 Jul 09",
71*4882a593Smuzhiyun     standard         BG     L      L'
72*4882a593Smuzhiyun     picture carrier  38.90  38.90  33.95
73*4882a593Smuzhiyun     colour	     34.47  34.37  38.38
74*4882a593Smuzhiyun     sound 1          33.40  32.40  40.45
75*4882a593Smuzhiyun     sound 2          33.16  -      -
76*4882a593Smuzhiyun     NICAM            33.05  33.05  39.80
77*4882a593Smuzhiyun  */
78*4882a593Smuzhiyun #define PHILIPS_MF_SET_STD_BG	0x01 /* Bit 2 must be zero, Bit 3 is system output */
79*4882a593Smuzhiyun #define PHILIPS_MF_SET_STD_L	0x03 /* Used on Secam France */
80*4882a593Smuzhiyun #define PHILIPS_MF_SET_STD_LC	0x02 /* Used on SECAM L' */
81*4882a593Smuzhiyun 
82*4882a593Smuzhiyun /* Control byte */
83*4882a593Smuzhiyun 
84*4882a593Smuzhiyun #define TUNER_RATIO_MASK        0x06 /* Bit cb1:cb2 */
85*4882a593Smuzhiyun #define TUNER_RATIO_SELECT_50   0x00
86*4882a593Smuzhiyun #define TUNER_RATIO_SELECT_32   0x02
87*4882a593Smuzhiyun #define TUNER_RATIO_SELECT_166  0x04
88*4882a593Smuzhiyun #define TUNER_RATIO_SELECT_62   0x06
89*4882a593Smuzhiyun 
90*4882a593Smuzhiyun #define TUNER_CHARGE_PUMP       0x40  /* Bit cb6 */
91*4882a593Smuzhiyun 
92*4882a593Smuzhiyun /* Status byte */
93*4882a593Smuzhiyun 
94*4882a593Smuzhiyun #define TUNER_POR	  0x80
95*4882a593Smuzhiyun #define TUNER_FL          0x40
96*4882a593Smuzhiyun #define TUNER_MODE        0x38
97*4882a593Smuzhiyun #define TUNER_AFC         0x07
98*4882a593Smuzhiyun #define TUNER_SIGNAL      0x07
99*4882a593Smuzhiyun #define TUNER_STEREO      0x10
100*4882a593Smuzhiyun 
101*4882a593Smuzhiyun #define TUNER_PLL_LOCKED   0x40
102*4882a593Smuzhiyun #define TUNER_STEREO_MK3   0x04
103*4882a593Smuzhiyun 
104*4882a593Smuzhiyun static DEFINE_MUTEX(tuner_simple_list_mutex);
105*4882a593Smuzhiyun static LIST_HEAD(hybrid_tuner_instance_list);
106*4882a593Smuzhiyun 
107*4882a593Smuzhiyun struct tuner_simple_priv {
108*4882a593Smuzhiyun 	unsigned int nr;
109*4882a593Smuzhiyun 	u16 last_div;
110*4882a593Smuzhiyun 
111*4882a593Smuzhiyun 	struct tuner_i2c_props i2c_props;
112*4882a593Smuzhiyun 	struct list_head hybrid_tuner_instance_list;
113*4882a593Smuzhiyun 
114*4882a593Smuzhiyun 	unsigned int type;
115*4882a593Smuzhiyun 	struct tunertype *tun;
116*4882a593Smuzhiyun 
117*4882a593Smuzhiyun 	u32 frequency;
118*4882a593Smuzhiyun 	u32 bandwidth;
119*4882a593Smuzhiyun 	bool radio_mode;
120*4882a593Smuzhiyun };
121*4882a593Smuzhiyun 
122*4882a593Smuzhiyun /* ---------------------------------------------------------------------- */
123*4882a593Smuzhiyun 
tuner_read_status(struct dvb_frontend * fe)124*4882a593Smuzhiyun static int tuner_read_status(struct dvb_frontend *fe)
125*4882a593Smuzhiyun {
126*4882a593Smuzhiyun 	struct tuner_simple_priv *priv = fe->tuner_priv;
127*4882a593Smuzhiyun 	unsigned char byte;
128*4882a593Smuzhiyun 
129*4882a593Smuzhiyun 	if (1 != tuner_i2c_xfer_recv(&priv->i2c_props, &byte, 1))
130*4882a593Smuzhiyun 		return 0;
131*4882a593Smuzhiyun 
132*4882a593Smuzhiyun 	return byte;
133*4882a593Smuzhiyun }
134*4882a593Smuzhiyun 
tuner_signal(const int status)135*4882a593Smuzhiyun static inline int tuner_signal(const int status)
136*4882a593Smuzhiyun {
137*4882a593Smuzhiyun 	return (status & TUNER_SIGNAL) << 13;
138*4882a593Smuzhiyun }
139*4882a593Smuzhiyun 
tuner_stereo(const int type,const int status)140*4882a593Smuzhiyun static inline int tuner_stereo(const int type, const int status)
141*4882a593Smuzhiyun {
142*4882a593Smuzhiyun 	switch (type) {
143*4882a593Smuzhiyun 	case TUNER_PHILIPS_FM1216ME_MK3:
144*4882a593Smuzhiyun 	case TUNER_PHILIPS_FM1236_MK3:
145*4882a593Smuzhiyun 	case TUNER_PHILIPS_FM1256_IH3:
146*4882a593Smuzhiyun 	case TUNER_LG_NTSC_TAPE:
147*4882a593Smuzhiyun 	case TUNER_TCL_MF02GIP_5N:
148*4882a593Smuzhiyun 		return ((status & TUNER_SIGNAL) == TUNER_STEREO_MK3);
149*4882a593Smuzhiyun 	case TUNER_PHILIPS_FM1216MK5:
150*4882a593Smuzhiyun 		return status | TUNER_STEREO;
151*4882a593Smuzhiyun 	default:
152*4882a593Smuzhiyun 		return status & TUNER_STEREO;
153*4882a593Smuzhiyun 	}
154*4882a593Smuzhiyun }
155*4882a593Smuzhiyun 
tuner_islocked(const int status)156*4882a593Smuzhiyun static inline int tuner_islocked(const int status)
157*4882a593Smuzhiyun {
158*4882a593Smuzhiyun 	return (status & TUNER_FL);
159*4882a593Smuzhiyun }
160*4882a593Smuzhiyun 
tuner_afcstatus(const int status)161*4882a593Smuzhiyun static inline int tuner_afcstatus(const int status)
162*4882a593Smuzhiyun {
163*4882a593Smuzhiyun 	return (status & TUNER_AFC) - 2;
164*4882a593Smuzhiyun }
165*4882a593Smuzhiyun 
166*4882a593Smuzhiyun 
simple_get_status(struct dvb_frontend * fe,u32 * status)167*4882a593Smuzhiyun static int simple_get_status(struct dvb_frontend *fe, u32 *status)
168*4882a593Smuzhiyun {
169*4882a593Smuzhiyun 	struct tuner_simple_priv *priv = fe->tuner_priv;
170*4882a593Smuzhiyun 	int tuner_status;
171*4882a593Smuzhiyun 
172*4882a593Smuzhiyun 	if (priv->i2c_props.adap == NULL)
173*4882a593Smuzhiyun 		return -EINVAL;
174*4882a593Smuzhiyun 
175*4882a593Smuzhiyun 	tuner_status = tuner_read_status(fe);
176*4882a593Smuzhiyun 
177*4882a593Smuzhiyun 	*status = 0;
178*4882a593Smuzhiyun 
179*4882a593Smuzhiyun 	if (tuner_islocked(tuner_status))
180*4882a593Smuzhiyun 		*status = TUNER_STATUS_LOCKED;
181*4882a593Smuzhiyun 	if (tuner_stereo(priv->type, tuner_status))
182*4882a593Smuzhiyun 		*status |= TUNER_STATUS_STEREO;
183*4882a593Smuzhiyun 
184*4882a593Smuzhiyun 	tuner_dbg("AFC Status: %d\n", tuner_afcstatus(tuner_status));
185*4882a593Smuzhiyun 
186*4882a593Smuzhiyun 	return 0;
187*4882a593Smuzhiyun }
188*4882a593Smuzhiyun 
simple_get_rf_strength(struct dvb_frontend * fe,u16 * strength)189*4882a593Smuzhiyun static int simple_get_rf_strength(struct dvb_frontend *fe, u16 *strength)
190*4882a593Smuzhiyun {
191*4882a593Smuzhiyun 	struct tuner_simple_priv *priv = fe->tuner_priv;
192*4882a593Smuzhiyun 	int signal;
193*4882a593Smuzhiyun 
194*4882a593Smuzhiyun 	if (priv->i2c_props.adap == NULL || !priv->radio_mode)
195*4882a593Smuzhiyun 		return -EINVAL;
196*4882a593Smuzhiyun 
197*4882a593Smuzhiyun 	signal = tuner_signal(tuner_read_status(fe));
198*4882a593Smuzhiyun 
199*4882a593Smuzhiyun 	*strength = signal;
200*4882a593Smuzhiyun 
201*4882a593Smuzhiyun 	tuner_dbg("Signal strength: %d\n", signal);
202*4882a593Smuzhiyun 
203*4882a593Smuzhiyun 	return 0;
204*4882a593Smuzhiyun }
205*4882a593Smuzhiyun 
206*4882a593Smuzhiyun /* ---------------------------------------------------------------------- */
207*4882a593Smuzhiyun 
tuner_param_name(enum param_type type)208*4882a593Smuzhiyun static inline char *tuner_param_name(enum param_type type)
209*4882a593Smuzhiyun {
210*4882a593Smuzhiyun 	char *name;
211*4882a593Smuzhiyun 
212*4882a593Smuzhiyun 	switch (type) {
213*4882a593Smuzhiyun 	case TUNER_PARAM_TYPE_RADIO:
214*4882a593Smuzhiyun 		name = "radio";
215*4882a593Smuzhiyun 		break;
216*4882a593Smuzhiyun 	case TUNER_PARAM_TYPE_PAL:
217*4882a593Smuzhiyun 		name = "pal";
218*4882a593Smuzhiyun 		break;
219*4882a593Smuzhiyun 	case TUNER_PARAM_TYPE_SECAM:
220*4882a593Smuzhiyun 		name = "secam";
221*4882a593Smuzhiyun 		break;
222*4882a593Smuzhiyun 	case TUNER_PARAM_TYPE_NTSC:
223*4882a593Smuzhiyun 		name = "ntsc";
224*4882a593Smuzhiyun 		break;
225*4882a593Smuzhiyun 	case TUNER_PARAM_TYPE_DIGITAL:
226*4882a593Smuzhiyun 		name = "digital";
227*4882a593Smuzhiyun 		break;
228*4882a593Smuzhiyun 	default:
229*4882a593Smuzhiyun 		name = "unknown";
230*4882a593Smuzhiyun 		break;
231*4882a593Smuzhiyun 	}
232*4882a593Smuzhiyun 	return name;
233*4882a593Smuzhiyun }
234*4882a593Smuzhiyun 
simple_tuner_params(struct dvb_frontend * fe,enum param_type desired_type)235*4882a593Smuzhiyun static struct tuner_params *simple_tuner_params(struct dvb_frontend *fe,
236*4882a593Smuzhiyun 						enum param_type desired_type)
237*4882a593Smuzhiyun {
238*4882a593Smuzhiyun 	struct tuner_simple_priv *priv = fe->tuner_priv;
239*4882a593Smuzhiyun 	struct tunertype *tun = priv->tun;
240*4882a593Smuzhiyun 	int i;
241*4882a593Smuzhiyun 
242*4882a593Smuzhiyun 	for (i = 0; i < tun->count; i++)
243*4882a593Smuzhiyun 		if (desired_type == tun->params[i].type)
244*4882a593Smuzhiyun 			break;
245*4882a593Smuzhiyun 
246*4882a593Smuzhiyun 	/* use default tuner params if desired_type not available */
247*4882a593Smuzhiyun 	if (i == tun->count) {
248*4882a593Smuzhiyun 		tuner_dbg("desired params (%s) undefined for tuner %d\n",
249*4882a593Smuzhiyun 			  tuner_param_name(desired_type), priv->type);
250*4882a593Smuzhiyun 		i = 0;
251*4882a593Smuzhiyun 	}
252*4882a593Smuzhiyun 
253*4882a593Smuzhiyun 	tuner_dbg("using tuner params #%d (%s)\n", i,
254*4882a593Smuzhiyun 		  tuner_param_name(tun->params[i].type));
255*4882a593Smuzhiyun 
256*4882a593Smuzhiyun 	return &tun->params[i];
257*4882a593Smuzhiyun }
258*4882a593Smuzhiyun 
simple_config_lookup(struct dvb_frontend * fe,struct tuner_params * t_params,unsigned * frequency,u8 * config,u8 * cb)259*4882a593Smuzhiyun static int simple_config_lookup(struct dvb_frontend *fe,
260*4882a593Smuzhiyun 				struct tuner_params *t_params,
261*4882a593Smuzhiyun 				unsigned *frequency, u8 *config, u8 *cb)
262*4882a593Smuzhiyun {
263*4882a593Smuzhiyun 	struct tuner_simple_priv *priv = fe->tuner_priv;
264*4882a593Smuzhiyun 	int i;
265*4882a593Smuzhiyun 
266*4882a593Smuzhiyun 	for (i = 0; i < t_params->count; i++) {
267*4882a593Smuzhiyun 		if (*frequency > t_params->ranges[i].limit)
268*4882a593Smuzhiyun 			continue;
269*4882a593Smuzhiyun 		break;
270*4882a593Smuzhiyun 	}
271*4882a593Smuzhiyun 	if (i == t_params->count) {
272*4882a593Smuzhiyun 		tuner_dbg("frequency out of range (%d > %d)\n",
273*4882a593Smuzhiyun 			  *frequency, t_params->ranges[i - 1].limit);
274*4882a593Smuzhiyun 		*frequency = t_params->ranges[--i].limit;
275*4882a593Smuzhiyun 	}
276*4882a593Smuzhiyun 	*config = t_params->ranges[i].config;
277*4882a593Smuzhiyun 	*cb     = t_params->ranges[i].cb;
278*4882a593Smuzhiyun 
279*4882a593Smuzhiyun 	tuner_dbg("freq = %d.%02d (%d), range = %d, config = 0x%02x, cb = 0x%02x\n",
280*4882a593Smuzhiyun 		  *frequency / 16, *frequency % 16 * 100 / 16, *frequency,
281*4882a593Smuzhiyun 		  i, *config, *cb);
282*4882a593Smuzhiyun 
283*4882a593Smuzhiyun 	return i;
284*4882a593Smuzhiyun }
285*4882a593Smuzhiyun 
286*4882a593Smuzhiyun /* ---------------------------------------------------------------------- */
287*4882a593Smuzhiyun 
simple_set_rf_input(struct dvb_frontend * fe,u8 * config,u8 * cb,unsigned int rf)288*4882a593Smuzhiyun static void simple_set_rf_input(struct dvb_frontend *fe,
289*4882a593Smuzhiyun 				u8 *config, u8 *cb, unsigned int rf)
290*4882a593Smuzhiyun {
291*4882a593Smuzhiyun 	struct tuner_simple_priv *priv = fe->tuner_priv;
292*4882a593Smuzhiyun 
293*4882a593Smuzhiyun 	switch (priv->type) {
294*4882a593Smuzhiyun 	case TUNER_PHILIPS_TUV1236D:
295*4882a593Smuzhiyun 		switch (rf) {
296*4882a593Smuzhiyun 		case 1:
297*4882a593Smuzhiyun 			*cb |= 0x08;
298*4882a593Smuzhiyun 			break;
299*4882a593Smuzhiyun 		default:
300*4882a593Smuzhiyun 			*cb &= ~0x08;
301*4882a593Smuzhiyun 			break;
302*4882a593Smuzhiyun 		}
303*4882a593Smuzhiyun 		break;
304*4882a593Smuzhiyun 	case TUNER_PHILIPS_FCV1236D:
305*4882a593Smuzhiyun 		switch (rf) {
306*4882a593Smuzhiyun 		case 1:
307*4882a593Smuzhiyun 			*cb |= 0x01;
308*4882a593Smuzhiyun 			break;
309*4882a593Smuzhiyun 		default:
310*4882a593Smuzhiyun 			*cb &= ~0x01;
311*4882a593Smuzhiyun 			break;
312*4882a593Smuzhiyun 		}
313*4882a593Smuzhiyun 		break;
314*4882a593Smuzhiyun 	default:
315*4882a593Smuzhiyun 		break;
316*4882a593Smuzhiyun 	}
317*4882a593Smuzhiyun }
318*4882a593Smuzhiyun 
simple_std_setup(struct dvb_frontend * fe,struct analog_parameters * params,u8 * config,u8 * cb)319*4882a593Smuzhiyun static int simple_std_setup(struct dvb_frontend *fe,
320*4882a593Smuzhiyun 			    struct analog_parameters *params,
321*4882a593Smuzhiyun 			    u8 *config, u8 *cb)
322*4882a593Smuzhiyun {
323*4882a593Smuzhiyun 	struct tuner_simple_priv *priv = fe->tuner_priv;
324*4882a593Smuzhiyun 	int rc;
325*4882a593Smuzhiyun 
326*4882a593Smuzhiyun 	/* tv norm specific stuff for multi-norm tuners */
327*4882a593Smuzhiyun 	switch (priv->type) {
328*4882a593Smuzhiyun 	case TUNER_PHILIPS_SECAM: /* FI1216MF */
329*4882a593Smuzhiyun 		/* 0x01 -> ??? no change ??? */
330*4882a593Smuzhiyun 		/* 0x02 -> PAL BDGHI / SECAM L */
331*4882a593Smuzhiyun 		/* 0x04 -> ??? PAL others / SECAM others ??? */
332*4882a593Smuzhiyun 		*cb &= ~0x03;
333*4882a593Smuzhiyun 		if (params->std & V4L2_STD_SECAM_L)
334*4882a593Smuzhiyun 			/* also valid for V4L2_STD_SECAM */
335*4882a593Smuzhiyun 			*cb |= PHILIPS_MF_SET_STD_L;
336*4882a593Smuzhiyun 		else if (params->std & V4L2_STD_SECAM_LC)
337*4882a593Smuzhiyun 			*cb |= PHILIPS_MF_SET_STD_LC;
338*4882a593Smuzhiyun 		else /* V4L2_STD_B|V4L2_STD_GH */
339*4882a593Smuzhiyun 			*cb |= PHILIPS_MF_SET_STD_BG;
340*4882a593Smuzhiyun 		break;
341*4882a593Smuzhiyun 
342*4882a593Smuzhiyun 	case TUNER_TEMIC_4046FM5:
343*4882a593Smuzhiyun 		*cb &= ~0x0f;
344*4882a593Smuzhiyun 
345*4882a593Smuzhiyun 		if (params->std & V4L2_STD_PAL_BG) {
346*4882a593Smuzhiyun 			*cb |= TEMIC_SET_PAL_BG;
347*4882a593Smuzhiyun 
348*4882a593Smuzhiyun 		} else if (params->std & V4L2_STD_PAL_I) {
349*4882a593Smuzhiyun 			*cb |= TEMIC_SET_PAL_I;
350*4882a593Smuzhiyun 
351*4882a593Smuzhiyun 		} else if (params->std & V4L2_STD_PAL_DK) {
352*4882a593Smuzhiyun 			*cb |= TEMIC_SET_PAL_DK;
353*4882a593Smuzhiyun 
354*4882a593Smuzhiyun 		} else if (params->std & V4L2_STD_SECAM_L) {
355*4882a593Smuzhiyun 			*cb |= TEMIC_SET_PAL_L;
356*4882a593Smuzhiyun 
357*4882a593Smuzhiyun 		}
358*4882a593Smuzhiyun 		break;
359*4882a593Smuzhiyun 
360*4882a593Smuzhiyun 	case TUNER_PHILIPS_FQ1216ME:
361*4882a593Smuzhiyun 		*cb &= ~0x0f;
362*4882a593Smuzhiyun 
363*4882a593Smuzhiyun 		if (params->std & (V4L2_STD_PAL_BG|V4L2_STD_PAL_DK)) {
364*4882a593Smuzhiyun 			*cb |= PHILIPS_SET_PAL_BGDK;
365*4882a593Smuzhiyun 
366*4882a593Smuzhiyun 		} else if (params->std & V4L2_STD_PAL_I) {
367*4882a593Smuzhiyun 			*cb |= PHILIPS_SET_PAL_I;
368*4882a593Smuzhiyun 
369*4882a593Smuzhiyun 		} else if (params->std & V4L2_STD_SECAM_L) {
370*4882a593Smuzhiyun 			*cb |= PHILIPS_SET_PAL_L;
371*4882a593Smuzhiyun 
372*4882a593Smuzhiyun 		}
373*4882a593Smuzhiyun 		break;
374*4882a593Smuzhiyun 
375*4882a593Smuzhiyun 	case TUNER_PHILIPS_FCV1236D:
376*4882a593Smuzhiyun 		/* 0x00 -> ATSC antenna input 1 */
377*4882a593Smuzhiyun 		/* 0x01 -> ATSC antenna input 2 */
378*4882a593Smuzhiyun 		/* 0x02 -> NTSC antenna input 1 */
379*4882a593Smuzhiyun 		/* 0x03 -> NTSC antenna input 2 */
380*4882a593Smuzhiyun 		*cb &= ~0x03;
381*4882a593Smuzhiyun 		if (!(params->std & V4L2_STD_ATSC))
382*4882a593Smuzhiyun 			*cb |= 2;
383*4882a593Smuzhiyun 		break;
384*4882a593Smuzhiyun 
385*4882a593Smuzhiyun 	case TUNER_MICROTUNE_4042FI5:
386*4882a593Smuzhiyun 		/* Set the charge pump for fast tuning */
387*4882a593Smuzhiyun 		*config |= TUNER_CHARGE_PUMP;
388*4882a593Smuzhiyun 		break;
389*4882a593Smuzhiyun 
390*4882a593Smuzhiyun 	case TUNER_PHILIPS_TUV1236D:
391*4882a593Smuzhiyun 	{
392*4882a593Smuzhiyun 		struct tuner_i2c_props i2c = priv->i2c_props;
393*4882a593Smuzhiyun 		/* 0x40 -> ATSC antenna input 1 */
394*4882a593Smuzhiyun 		/* 0x48 -> ATSC antenna input 2 */
395*4882a593Smuzhiyun 		/* 0x00 -> NTSC antenna input 1 */
396*4882a593Smuzhiyun 		/* 0x08 -> NTSC antenna input 2 */
397*4882a593Smuzhiyun 		u8 buffer[4] = { 0x14, 0x00, 0x17, 0x00};
398*4882a593Smuzhiyun 		*cb &= ~0x40;
399*4882a593Smuzhiyun 		if (params->std & V4L2_STD_ATSC) {
400*4882a593Smuzhiyun 			*cb |= 0x40;
401*4882a593Smuzhiyun 			buffer[1] = 0x04;
402*4882a593Smuzhiyun 		}
403*4882a593Smuzhiyun 		/* set to the correct mode (analog or digital) */
404*4882a593Smuzhiyun 		i2c.addr = 0x0a;
405*4882a593Smuzhiyun 		rc = tuner_i2c_xfer_send(&i2c, &buffer[0], 2);
406*4882a593Smuzhiyun 		if (2 != rc)
407*4882a593Smuzhiyun 			tuner_warn("i2c i/o error: rc == %d (should be 2)\n",
408*4882a593Smuzhiyun 				   rc);
409*4882a593Smuzhiyun 		rc = tuner_i2c_xfer_send(&i2c, &buffer[2], 2);
410*4882a593Smuzhiyun 		if (2 != rc)
411*4882a593Smuzhiyun 			tuner_warn("i2c i/o error: rc == %d (should be 2)\n",
412*4882a593Smuzhiyun 				   rc);
413*4882a593Smuzhiyun 		break;
414*4882a593Smuzhiyun 	}
415*4882a593Smuzhiyun 	}
416*4882a593Smuzhiyun 	if (atv_input[priv->nr])
417*4882a593Smuzhiyun 		simple_set_rf_input(fe, config, cb, atv_input[priv->nr]);
418*4882a593Smuzhiyun 
419*4882a593Smuzhiyun 	return 0;
420*4882a593Smuzhiyun }
421*4882a593Smuzhiyun 
simple_set_aux_byte(struct dvb_frontend * fe,u8 config,u8 aux)422*4882a593Smuzhiyun static int simple_set_aux_byte(struct dvb_frontend *fe, u8 config, u8 aux)
423*4882a593Smuzhiyun {
424*4882a593Smuzhiyun 	struct tuner_simple_priv *priv = fe->tuner_priv;
425*4882a593Smuzhiyun 	int rc;
426*4882a593Smuzhiyun 	u8 buffer[2];
427*4882a593Smuzhiyun 
428*4882a593Smuzhiyun 	buffer[0] = (config & ~0x38) | 0x18;
429*4882a593Smuzhiyun 	buffer[1] = aux;
430*4882a593Smuzhiyun 
431*4882a593Smuzhiyun 	tuner_dbg("setting aux byte: 0x%02x 0x%02x\n", buffer[0], buffer[1]);
432*4882a593Smuzhiyun 
433*4882a593Smuzhiyun 	rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 2);
434*4882a593Smuzhiyun 	if (2 != rc)
435*4882a593Smuzhiyun 		tuner_warn("i2c i/o error: rc == %d (should be 2)\n", rc);
436*4882a593Smuzhiyun 
437*4882a593Smuzhiyun 	return rc == 2 ? 0 : rc;
438*4882a593Smuzhiyun }
439*4882a593Smuzhiyun 
simple_post_tune(struct dvb_frontend * fe,u8 * buffer,u16 div,u8 config,u8 cb)440*4882a593Smuzhiyun static int simple_post_tune(struct dvb_frontend *fe, u8 *buffer,
441*4882a593Smuzhiyun 			    u16 div, u8 config, u8 cb)
442*4882a593Smuzhiyun {
443*4882a593Smuzhiyun 	struct tuner_simple_priv *priv = fe->tuner_priv;
444*4882a593Smuzhiyun 	int rc;
445*4882a593Smuzhiyun 
446*4882a593Smuzhiyun 	switch (priv->type) {
447*4882a593Smuzhiyun 	case TUNER_LG_TDVS_H06XF:
448*4882a593Smuzhiyun 		simple_set_aux_byte(fe, config, 0x20);
449*4882a593Smuzhiyun 		break;
450*4882a593Smuzhiyun 	case TUNER_PHILIPS_FQ1216LME_MK3:
451*4882a593Smuzhiyun 		simple_set_aux_byte(fe, config, 0x60); /* External AGC */
452*4882a593Smuzhiyun 		break;
453*4882a593Smuzhiyun 	case TUNER_MICROTUNE_4042FI5:
454*4882a593Smuzhiyun 	{
455*4882a593Smuzhiyun 		/* FIXME - this may also work for other tuners */
456*4882a593Smuzhiyun 		unsigned long timeout = jiffies + msecs_to_jiffies(1);
457*4882a593Smuzhiyun 		u8 status_byte = 0;
458*4882a593Smuzhiyun 
459*4882a593Smuzhiyun 		/* Wait until the PLL locks */
460*4882a593Smuzhiyun 		for (;;) {
461*4882a593Smuzhiyun 			if (time_after(jiffies, timeout))
462*4882a593Smuzhiyun 				return 0;
463*4882a593Smuzhiyun 			rc = tuner_i2c_xfer_recv(&priv->i2c_props,
464*4882a593Smuzhiyun 						 &status_byte, 1);
465*4882a593Smuzhiyun 			if (1 != rc) {
466*4882a593Smuzhiyun 				tuner_warn("i2c i/o read error: rc == %d (should be 1)\n",
467*4882a593Smuzhiyun 					   rc);
468*4882a593Smuzhiyun 				break;
469*4882a593Smuzhiyun 			}
470*4882a593Smuzhiyun 			if (status_byte & TUNER_PLL_LOCKED)
471*4882a593Smuzhiyun 				break;
472*4882a593Smuzhiyun 			udelay(10);
473*4882a593Smuzhiyun 		}
474*4882a593Smuzhiyun 
475*4882a593Smuzhiyun 		/* Set the charge pump for optimized phase noise figure */
476*4882a593Smuzhiyun 		config &= ~TUNER_CHARGE_PUMP;
477*4882a593Smuzhiyun 		buffer[0] = (div>>8) & 0x7f;
478*4882a593Smuzhiyun 		buffer[1] = div      & 0xff;
479*4882a593Smuzhiyun 		buffer[2] = config;
480*4882a593Smuzhiyun 		buffer[3] = cb;
481*4882a593Smuzhiyun 		tuner_dbg("tv 0x%02x 0x%02x 0x%02x 0x%02x\n",
482*4882a593Smuzhiyun 			  buffer[0], buffer[1], buffer[2], buffer[3]);
483*4882a593Smuzhiyun 
484*4882a593Smuzhiyun 		rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 4);
485*4882a593Smuzhiyun 		if (4 != rc)
486*4882a593Smuzhiyun 			tuner_warn("i2c i/o error: rc == %d (should be 4)\n",
487*4882a593Smuzhiyun 				   rc);
488*4882a593Smuzhiyun 		break;
489*4882a593Smuzhiyun 	}
490*4882a593Smuzhiyun 	}
491*4882a593Smuzhiyun 
492*4882a593Smuzhiyun 	return 0;
493*4882a593Smuzhiyun }
494*4882a593Smuzhiyun 
simple_radio_bandswitch(struct dvb_frontend * fe,u8 * buffer)495*4882a593Smuzhiyun static int simple_radio_bandswitch(struct dvb_frontend *fe, u8 *buffer)
496*4882a593Smuzhiyun {
497*4882a593Smuzhiyun 	struct tuner_simple_priv *priv = fe->tuner_priv;
498*4882a593Smuzhiyun 
499*4882a593Smuzhiyun 	switch (priv->type) {
500*4882a593Smuzhiyun 	case TUNER_TENA_9533_DI:
501*4882a593Smuzhiyun 	case TUNER_YMEC_TVF_5533MF:
502*4882a593Smuzhiyun 		tuner_dbg("This tuner doesn't have FM. Most cards have a TEA5767 for FM\n");
503*4882a593Smuzhiyun 		return -EINVAL;
504*4882a593Smuzhiyun 	case TUNER_PHILIPS_FM1216ME_MK3:
505*4882a593Smuzhiyun 	case TUNER_PHILIPS_FM1236_MK3:
506*4882a593Smuzhiyun 	case TUNER_PHILIPS_FMD1216ME_MK3:
507*4882a593Smuzhiyun 	case TUNER_PHILIPS_FMD1216MEX_MK3:
508*4882a593Smuzhiyun 	case TUNER_LG_NTSC_TAPE:
509*4882a593Smuzhiyun 	case TUNER_PHILIPS_FM1256_IH3:
510*4882a593Smuzhiyun 	case TUNER_TCL_MF02GIP_5N:
511*4882a593Smuzhiyun 		buffer[3] = 0x19;
512*4882a593Smuzhiyun 		break;
513*4882a593Smuzhiyun 	case TUNER_PHILIPS_FM1216MK5:
514*4882a593Smuzhiyun 		buffer[2] = 0x88;
515*4882a593Smuzhiyun 		buffer[3] = 0x09;
516*4882a593Smuzhiyun 		break;
517*4882a593Smuzhiyun 	case TUNER_TNF_5335MF:
518*4882a593Smuzhiyun 		buffer[3] = 0x11;
519*4882a593Smuzhiyun 		break;
520*4882a593Smuzhiyun 	case TUNER_LG_PAL_FM:
521*4882a593Smuzhiyun 		buffer[3] = 0xa5;
522*4882a593Smuzhiyun 		break;
523*4882a593Smuzhiyun 	case TUNER_THOMSON_DTT761X:
524*4882a593Smuzhiyun 		buffer[3] = 0x39;
525*4882a593Smuzhiyun 		break;
526*4882a593Smuzhiyun 	case TUNER_PHILIPS_FQ1216LME_MK3:
527*4882a593Smuzhiyun 	case TUNER_PHILIPS_FQ1236_MK5:
528*4882a593Smuzhiyun 		tuner_err("This tuner doesn't have FM\n");
529*4882a593Smuzhiyun 		/* Set the low band for sanity, since it covers 88-108 MHz */
530*4882a593Smuzhiyun 		buffer[3] = 0x01;
531*4882a593Smuzhiyun 		break;
532*4882a593Smuzhiyun 	case TUNER_MICROTUNE_4049FM5:
533*4882a593Smuzhiyun 	default:
534*4882a593Smuzhiyun 		buffer[3] = 0xa4;
535*4882a593Smuzhiyun 		break;
536*4882a593Smuzhiyun 	}
537*4882a593Smuzhiyun 
538*4882a593Smuzhiyun 	return 0;
539*4882a593Smuzhiyun }
540*4882a593Smuzhiyun 
541*4882a593Smuzhiyun /* ---------------------------------------------------------------------- */
542*4882a593Smuzhiyun 
simple_set_tv_freq(struct dvb_frontend * fe,struct analog_parameters * params)543*4882a593Smuzhiyun static int simple_set_tv_freq(struct dvb_frontend *fe,
544*4882a593Smuzhiyun 			      struct analog_parameters *params)
545*4882a593Smuzhiyun {
546*4882a593Smuzhiyun 	struct tuner_simple_priv *priv = fe->tuner_priv;
547*4882a593Smuzhiyun 	u8 config, cb;
548*4882a593Smuzhiyun 	u16 div;
549*4882a593Smuzhiyun 	u8 buffer[4];
550*4882a593Smuzhiyun 	int rc, IFPCoff, i;
551*4882a593Smuzhiyun 	enum param_type desired_type;
552*4882a593Smuzhiyun 	struct tuner_params *t_params;
553*4882a593Smuzhiyun 
554*4882a593Smuzhiyun 	/* IFPCoff = Video Intermediate Frequency - Vif:
555*4882a593Smuzhiyun 		940  =16*58.75  NTSC/J (Japan)
556*4882a593Smuzhiyun 		732  =16*45.75  M/N STD
557*4882a593Smuzhiyun 		704  =16*44     ATSC (at DVB code)
558*4882a593Smuzhiyun 		632  =16*39.50  I U.K.
559*4882a593Smuzhiyun 		622.4=16*38.90  B/G D/K I, L STD
560*4882a593Smuzhiyun 		592  =16*37.00  D China
561*4882a593Smuzhiyun 		590  =16.36.875 B Australia
562*4882a593Smuzhiyun 		543.2=16*33.95  L' STD
563*4882a593Smuzhiyun 		171.2=16*10.70  FM Radio (at set_radio_freq)
564*4882a593Smuzhiyun 	*/
565*4882a593Smuzhiyun 
566*4882a593Smuzhiyun 	if (params->std == V4L2_STD_NTSC_M_JP) {
567*4882a593Smuzhiyun 		IFPCoff      = 940;
568*4882a593Smuzhiyun 		desired_type = TUNER_PARAM_TYPE_NTSC;
569*4882a593Smuzhiyun 	} else if ((params->std & V4L2_STD_MN) &&
570*4882a593Smuzhiyun 		  !(params->std & ~V4L2_STD_MN)) {
571*4882a593Smuzhiyun 		IFPCoff      = 732;
572*4882a593Smuzhiyun 		desired_type = TUNER_PARAM_TYPE_NTSC;
573*4882a593Smuzhiyun 	} else if (params->std == V4L2_STD_SECAM_LC) {
574*4882a593Smuzhiyun 		IFPCoff      = 543;
575*4882a593Smuzhiyun 		desired_type = TUNER_PARAM_TYPE_SECAM;
576*4882a593Smuzhiyun 	} else {
577*4882a593Smuzhiyun 		IFPCoff      = 623;
578*4882a593Smuzhiyun 		desired_type = TUNER_PARAM_TYPE_PAL;
579*4882a593Smuzhiyun 	}
580*4882a593Smuzhiyun 
581*4882a593Smuzhiyun 	t_params = simple_tuner_params(fe, desired_type);
582*4882a593Smuzhiyun 
583*4882a593Smuzhiyun 	i = simple_config_lookup(fe, t_params, &params->frequency,
584*4882a593Smuzhiyun 				 &config, &cb);
585*4882a593Smuzhiyun 
586*4882a593Smuzhiyun 	div = params->frequency + IFPCoff + offset;
587*4882a593Smuzhiyun 
588*4882a593Smuzhiyun 	tuner_dbg("Freq= %d.%02d MHz, V_IF=%d.%02d MHz, Offset=%d.%02d MHz, div=%0d\n",
589*4882a593Smuzhiyun 		  params->frequency / 16, params->frequency % 16 * 100 / 16,
590*4882a593Smuzhiyun 		  IFPCoff / 16, IFPCoff % 16 * 100 / 16,
591*4882a593Smuzhiyun 		  offset / 16, offset % 16 * 100 / 16, div);
592*4882a593Smuzhiyun 
593*4882a593Smuzhiyun 	/* tv norm specific stuff for multi-norm tuners */
594*4882a593Smuzhiyun 	simple_std_setup(fe, params, &config, &cb);
595*4882a593Smuzhiyun 
596*4882a593Smuzhiyun 	if (t_params->cb_first_if_lower_freq && div < priv->last_div) {
597*4882a593Smuzhiyun 		buffer[0] = config;
598*4882a593Smuzhiyun 		buffer[1] = cb;
599*4882a593Smuzhiyun 		buffer[2] = (div>>8) & 0x7f;
600*4882a593Smuzhiyun 		buffer[3] = div      & 0xff;
601*4882a593Smuzhiyun 	} else {
602*4882a593Smuzhiyun 		buffer[0] = (div>>8) & 0x7f;
603*4882a593Smuzhiyun 		buffer[1] = div      & 0xff;
604*4882a593Smuzhiyun 		buffer[2] = config;
605*4882a593Smuzhiyun 		buffer[3] = cb;
606*4882a593Smuzhiyun 	}
607*4882a593Smuzhiyun 	priv->last_div = div;
608*4882a593Smuzhiyun 	if (t_params->has_tda9887) {
609*4882a593Smuzhiyun 		struct v4l2_priv_tun_config tda9887_cfg;
610*4882a593Smuzhiyun 		int tda_config = 0;
611*4882a593Smuzhiyun 		int is_secam_l = (params->std & (V4L2_STD_SECAM_L |
612*4882a593Smuzhiyun 						 V4L2_STD_SECAM_LC)) &&
613*4882a593Smuzhiyun 			!(params->std & ~(V4L2_STD_SECAM_L |
614*4882a593Smuzhiyun 					  V4L2_STD_SECAM_LC));
615*4882a593Smuzhiyun 
616*4882a593Smuzhiyun 		tda9887_cfg.tuner = TUNER_TDA9887;
617*4882a593Smuzhiyun 		tda9887_cfg.priv  = &tda_config;
618*4882a593Smuzhiyun 
619*4882a593Smuzhiyun 		if (params->std == V4L2_STD_SECAM_LC) {
620*4882a593Smuzhiyun 			if (t_params->port1_active ^ t_params->port1_invert_for_secam_lc)
621*4882a593Smuzhiyun 				tda_config |= TDA9887_PORT1_ACTIVE;
622*4882a593Smuzhiyun 			if (t_params->port2_active ^ t_params->port2_invert_for_secam_lc)
623*4882a593Smuzhiyun 				tda_config |= TDA9887_PORT2_ACTIVE;
624*4882a593Smuzhiyun 		} else {
625*4882a593Smuzhiyun 			if (t_params->port1_active)
626*4882a593Smuzhiyun 				tda_config |= TDA9887_PORT1_ACTIVE;
627*4882a593Smuzhiyun 			if (t_params->port2_active)
628*4882a593Smuzhiyun 				tda_config |= TDA9887_PORT2_ACTIVE;
629*4882a593Smuzhiyun 		}
630*4882a593Smuzhiyun 		if (t_params->intercarrier_mode)
631*4882a593Smuzhiyun 			tda_config |= TDA9887_INTERCARRIER;
632*4882a593Smuzhiyun 		if (is_secam_l) {
633*4882a593Smuzhiyun 			if (i == 0 && t_params->default_top_secam_low)
634*4882a593Smuzhiyun 				tda_config |= TDA9887_TOP(t_params->default_top_secam_low);
635*4882a593Smuzhiyun 			else if (i == 1 && t_params->default_top_secam_mid)
636*4882a593Smuzhiyun 				tda_config |= TDA9887_TOP(t_params->default_top_secam_mid);
637*4882a593Smuzhiyun 			else if (t_params->default_top_secam_high)
638*4882a593Smuzhiyun 				tda_config |= TDA9887_TOP(t_params->default_top_secam_high);
639*4882a593Smuzhiyun 		} else {
640*4882a593Smuzhiyun 			if (i == 0 && t_params->default_top_low)
641*4882a593Smuzhiyun 				tda_config |= TDA9887_TOP(t_params->default_top_low);
642*4882a593Smuzhiyun 			else if (i == 1 && t_params->default_top_mid)
643*4882a593Smuzhiyun 				tda_config |= TDA9887_TOP(t_params->default_top_mid);
644*4882a593Smuzhiyun 			else if (t_params->default_top_high)
645*4882a593Smuzhiyun 				tda_config |= TDA9887_TOP(t_params->default_top_high);
646*4882a593Smuzhiyun 		}
647*4882a593Smuzhiyun 		if (t_params->default_pll_gating_18)
648*4882a593Smuzhiyun 			tda_config |= TDA9887_GATING_18;
649*4882a593Smuzhiyun 		i2c_clients_command(priv->i2c_props.adap, TUNER_SET_CONFIG,
650*4882a593Smuzhiyun 				    &tda9887_cfg);
651*4882a593Smuzhiyun 	}
652*4882a593Smuzhiyun 	tuner_dbg("tv 0x%02x 0x%02x 0x%02x 0x%02x\n",
653*4882a593Smuzhiyun 		  buffer[0], buffer[1], buffer[2], buffer[3]);
654*4882a593Smuzhiyun 
655*4882a593Smuzhiyun 	rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 4);
656*4882a593Smuzhiyun 	if (4 != rc)
657*4882a593Smuzhiyun 		tuner_warn("i2c i/o error: rc == %d (should be 4)\n", rc);
658*4882a593Smuzhiyun 
659*4882a593Smuzhiyun 	simple_post_tune(fe, &buffer[0], div, config, cb);
660*4882a593Smuzhiyun 
661*4882a593Smuzhiyun 	return 0;
662*4882a593Smuzhiyun }
663*4882a593Smuzhiyun 
simple_set_radio_freq(struct dvb_frontend * fe,struct analog_parameters * params)664*4882a593Smuzhiyun static int simple_set_radio_freq(struct dvb_frontend *fe,
665*4882a593Smuzhiyun 				 struct analog_parameters *params)
666*4882a593Smuzhiyun {
667*4882a593Smuzhiyun 	struct tunertype *tun;
668*4882a593Smuzhiyun 	struct tuner_simple_priv *priv = fe->tuner_priv;
669*4882a593Smuzhiyun 	u8 buffer[4];
670*4882a593Smuzhiyun 	u16 div;
671*4882a593Smuzhiyun 	int rc, j;
672*4882a593Smuzhiyun 	struct tuner_params *t_params;
673*4882a593Smuzhiyun 	unsigned int freq = params->frequency;
674*4882a593Smuzhiyun 	bool mono = params->audmode == V4L2_TUNER_MODE_MONO;
675*4882a593Smuzhiyun 
676*4882a593Smuzhiyun 	tun = priv->tun;
677*4882a593Smuzhiyun 
678*4882a593Smuzhiyun 	for (j = tun->count-1; j > 0; j--)
679*4882a593Smuzhiyun 		if (tun->params[j].type == TUNER_PARAM_TYPE_RADIO)
680*4882a593Smuzhiyun 			break;
681*4882a593Smuzhiyun 	/* default t_params (j=0) will be used if desired type wasn't found */
682*4882a593Smuzhiyun 	t_params = &tun->params[j];
683*4882a593Smuzhiyun 
684*4882a593Smuzhiyun 	/* Select Radio 1st IF used */
685*4882a593Smuzhiyun 	switch (t_params->radio_if) {
686*4882a593Smuzhiyun 	case 0: /* 10.7 MHz */
687*4882a593Smuzhiyun 		freq += (unsigned int)(10.7*16000);
688*4882a593Smuzhiyun 		break;
689*4882a593Smuzhiyun 	case 1: /* 33.3 MHz */
690*4882a593Smuzhiyun 		freq += (unsigned int)(33.3*16000);
691*4882a593Smuzhiyun 		break;
692*4882a593Smuzhiyun 	case 2: /* 41.3 MHz */
693*4882a593Smuzhiyun 		freq += (unsigned int)(41.3*16000);
694*4882a593Smuzhiyun 		break;
695*4882a593Smuzhiyun 	default:
696*4882a593Smuzhiyun 		tuner_warn("Unsupported radio_if value %d\n",
697*4882a593Smuzhiyun 			   t_params->radio_if);
698*4882a593Smuzhiyun 		return 0;
699*4882a593Smuzhiyun 	}
700*4882a593Smuzhiyun 
701*4882a593Smuzhiyun 	buffer[2] = (t_params->ranges[0].config & ~TUNER_RATIO_MASK) |
702*4882a593Smuzhiyun 		    TUNER_RATIO_SELECT_50; /* 50 kHz step */
703*4882a593Smuzhiyun 
704*4882a593Smuzhiyun 	/* Bandswitch byte */
705*4882a593Smuzhiyun 	if (simple_radio_bandswitch(fe, &buffer[0]))
706*4882a593Smuzhiyun 		return 0;
707*4882a593Smuzhiyun 
708*4882a593Smuzhiyun 	/* Convert from 1/16 kHz V4L steps to 1/20 MHz (=50 kHz) PLL steps
709*4882a593Smuzhiyun 	   freq * (1 Mhz / 16000 V4L steps) * (20 PLL steps / 1 MHz) =
710*4882a593Smuzhiyun 	   freq * (1/800) */
711*4882a593Smuzhiyun 	div = (freq + 400) / 800;
712*4882a593Smuzhiyun 
713*4882a593Smuzhiyun 	if (t_params->cb_first_if_lower_freq && div < priv->last_div) {
714*4882a593Smuzhiyun 		buffer[0] = buffer[2];
715*4882a593Smuzhiyun 		buffer[1] = buffer[3];
716*4882a593Smuzhiyun 		buffer[2] = (div>>8) & 0x7f;
717*4882a593Smuzhiyun 		buffer[3] = div      & 0xff;
718*4882a593Smuzhiyun 	} else {
719*4882a593Smuzhiyun 		buffer[0] = (div>>8) & 0x7f;
720*4882a593Smuzhiyun 		buffer[1] = div      & 0xff;
721*4882a593Smuzhiyun 	}
722*4882a593Smuzhiyun 
723*4882a593Smuzhiyun 	tuner_dbg("radio 0x%02x 0x%02x 0x%02x 0x%02x\n",
724*4882a593Smuzhiyun 	       buffer[0], buffer[1], buffer[2], buffer[3]);
725*4882a593Smuzhiyun 	priv->last_div = div;
726*4882a593Smuzhiyun 
727*4882a593Smuzhiyun 	if (t_params->has_tda9887) {
728*4882a593Smuzhiyun 		int config = 0;
729*4882a593Smuzhiyun 		struct v4l2_priv_tun_config tda9887_cfg;
730*4882a593Smuzhiyun 
731*4882a593Smuzhiyun 		tda9887_cfg.tuner = TUNER_TDA9887;
732*4882a593Smuzhiyun 		tda9887_cfg.priv = &config;
733*4882a593Smuzhiyun 
734*4882a593Smuzhiyun 		if (t_params->port1_active &&
735*4882a593Smuzhiyun 		    !t_params->port1_fm_high_sensitivity)
736*4882a593Smuzhiyun 			config |= TDA9887_PORT1_ACTIVE;
737*4882a593Smuzhiyun 		if (t_params->port2_active &&
738*4882a593Smuzhiyun 		    !t_params->port2_fm_high_sensitivity)
739*4882a593Smuzhiyun 			config |= TDA9887_PORT2_ACTIVE;
740*4882a593Smuzhiyun 		if (t_params->intercarrier_mode)
741*4882a593Smuzhiyun 			config |= TDA9887_INTERCARRIER;
742*4882a593Smuzhiyun 		if (t_params->port1_set_for_fm_mono && mono)
743*4882a593Smuzhiyun 			config &= ~TDA9887_PORT1_ACTIVE;
744*4882a593Smuzhiyun 		if (t_params->fm_gain_normal)
745*4882a593Smuzhiyun 			config |= TDA9887_GAIN_NORMAL;
746*4882a593Smuzhiyun 		if (t_params->radio_if == 2)
747*4882a593Smuzhiyun 			config |= TDA9887_RIF_41_3;
748*4882a593Smuzhiyun 		i2c_clients_command(priv->i2c_props.adap, TUNER_SET_CONFIG,
749*4882a593Smuzhiyun 				    &tda9887_cfg);
750*4882a593Smuzhiyun 	}
751*4882a593Smuzhiyun 	rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 4);
752*4882a593Smuzhiyun 	if (4 != rc)
753*4882a593Smuzhiyun 		tuner_warn("i2c i/o error: rc == %d (should be 4)\n", rc);
754*4882a593Smuzhiyun 
755*4882a593Smuzhiyun 	/* Write AUX byte */
756*4882a593Smuzhiyun 	switch (priv->type) {
757*4882a593Smuzhiyun 	case TUNER_PHILIPS_FM1216ME_MK3:
758*4882a593Smuzhiyun 		buffer[2] = 0x98;
759*4882a593Smuzhiyun 		buffer[3] = 0x20; /* set TOP AGC */
760*4882a593Smuzhiyun 		rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 4);
761*4882a593Smuzhiyun 		if (4 != rc)
762*4882a593Smuzhiyun 			tuner_warn("i2c i/o error: rc == %d (should be 4)\n", rc);
763*4882a593Smuzhiyun 		break;
764*4882a593Smuzhiyun 	}
765*4882a593Smuzhiyun 
766*4882a593Smuzhiyun 	return 0;
767*4882a593Smuzhiyun }
768*4882a593Smuzhiyun 
simple_set_params(struct dvb_frontend * fe,struct analog_parameters * params)769*4882a593Smuzhiyun static int simple_set_params(struct dvb_frontend *fe,
770*4882a593Smuzhiyun 			     struct analog_parameters *params)
771*4882a593Smuzhiyun {
772*4882a593Smuzhiyun 	struct tuner_simple_priv *priv = fe->tuner_priv;
773*4882a593Smuzhiyun 	int ret = -EINVAL;
774*4882a593Smuzhiyun 
775*4882a593Smuzhiyun 	if (priv->i2c_props.adap == NULL)
776*4882a593Smuzhiyun 		return -EINVAL;
777*4882a593Smuzhiyun 
778*4882a593Smuzhiyun 	switch (params->mode) {
779*4882a593Smuzhiyun 	case V4L2_TUNER_RADIO:
780*4882a593Smuzhiyun 		priv->radio_mode = true;
781*4882a593Smuzhiyun 		ret = simple_set_radio_freq(fe, params);
782*4882a593Smuzhiyun 		priv->frequency = params->frequency * 125 / 2;
783*4882a593Smuzhiyun 		break;
784*4882a593Smuzhiyun 	case V4L2_TUNER_ANALOG_TV:
785*4882a593Smuzhiyun 	case V4L2_TUNER_DIGITAL_TV:
786*4882a593Smuzhiyun 		priv->radio_mode = false;
787*4882a593Smuzhiyun 		ret = simple_set_tv_freq(fe, params);
788*4882a593Smuzhiyun 		priv->frequency = params->frequency * 62500;
789*4882a593Smuzhiyun 		break;
790*4882a593Smuzhiyun 	}
791*4882a593Smuzhiyun 	priv->bandwidth = 0;
792*4882a593Smuzhiyun 
793*4882a593Smuzhiyun 	return ret;
794*4882a593Smuzhiyun }
795*4882a593Smuzhiyun 
simple_set_dvb(struct dvb_frontend * fe,u8 * buf,const u32 delsys,const u32 frequency,const u32 bandwidth)796*4882a593Smuzhiyun static void simple_set_dvb(struct dvb_frontend *fe, u8 *buf,
797*4882a593Smuzhiyun 			   const u32 delsys,
798*4882a593Smuzhiyun 			   const u32 frequency,
799*4882a593Smuzhiyun 			   const u32 bandwidth)
800*4882a593Smuzhiyun {
801*4882a593Smuzhiyun 	struct tuner_simple_priv *priv = fe->tuner_priv;
802*4882a593Smuzhiyun 
803*4882a593Smuzhiyun 	switch (priv->type) {
804*4882a593Smuzhiyun 	case TUNER_PHILIPS_FMD1216ME_MK3:
805*4882a593Smuzhiyun 	case TUNER_PHILIPS_FMD1216MEX_MK3:
806*4882a593Smuzhiyun 		if (bandwidth == 8000000 &&
807*4882a593Smuzhiyun 		    frequency >= 158870000)
808*4882a593Smuzhiyun 			buf[3] |= 0x08;
809*4882a593Smuzhiyun 		break;
810*4882a593Smuzhiyun 	case TUNER_PHILIPS_TD1316:
811*4882a593Smuzhiyun 		/* determine band */
812*4882a593Smuzhiyun 		buf[3] |= (frequency < 161000000) ? 1 :
813*4882a593Smuzhiyun 			  (frequency < 444000000) ? 2 : 4;
814*4882a593Smuzhiyun 
815*4882a593Smuzhiyun 		/* setup PLL filter */
816*4882a593Smuzhiyun 		if (bandwidth == 8000000)
817*4882a593Smuzhiyun 			buf[3] |= 1 << 3;
818*4882a593Smuzhiyun 		break;
819*4882a593Smuzhiyun 	case TUNER_PHILIPS_TUV1236D:
820*4882a593Smuzhiyun 	case TUNER_PHILIPS_FCV1236D:
821*4882a593Smuzhiyun 	{
822*4882a593Smuzhiyun 		unsigned int new_rf;
823*4882a593Smuzhiyun 
824*4882a593Smuzhiyun 		if (dtv_input[priv->nr])
825*4882a593Smuzhiyun 			new_rf = dtv_input[priv->nr];
826*4882a593Smuzhiyun 		else
827*4882a593Smuzhiyun 			switch (delsys) {
828*4882a593Smuzhiyun 			case SYS_DVBC_ANNEX_B:
829*4882a593Smuzhiyun 				new_rf = 1;
830*4882a593Smuzhiyun 				break;
831*4882a593Smuzhiyun 			case SYS_ATSC:
832*4882a593Smuzhiyun 			default:
833*4882a593Smuzhiyun 				new_rf = 0;
834*4882a593Smuzhiyun 				break;
835*4882a593Smuzhiyun 			}
836*4882a593Smuzhiyun 		simple_set_rf_input(fe, &buf[2], &buf[3], new_rf);
837*4882a593Smuzhiyun 		break;
838*4882a593Smuzhiyun 	}
839*4882a593Smuzhiyun 	default:
840*4882a593Smuzhiyun 		break;
841*4882a593Smuzhiyun 	}
842*4882a593Smuzhiyun }
843*4882a593Smuzhiyun 
simple_dvb_configure(struct dvb_frontend * fe,u8 * buf,const u32 delsys,const u32 freq,const u32 bw)844*4882a593Smuzhiyun static u32 simple_dvb_configure(struct dvb_frontend *fe, u8 *buf,
845*4882a593Smuzhiyun 				const u32 delsys,
846*4882a593Smuzhiyun 				const u32 freq,
847*4882a593Smuzhiyun 				const u32 bw)
848*4882a593Smuzhiyun {
849*4882a593Smuzhiyun 	/* This function returns the tuned frequency on success, 0 on error */
850*4882a593Smuzhiyun 	struct tuner_simple_priv *priv = fe->tuner_priv;
851*4882a593Smuzhiyun 	struct tunertype *tun = priv->tun;
852*4882a593Smuzhiyun 	struct tuner_params *t_params;
853*4882a593Smuzhiyun 	u8 config, cb;
854*4882a593Smuzhiyun 	u32 div;
855*4882a593Smuzhiyun 	int ret;
856*4882a593Smuzhiyun 	u32 frequency = freq / 62500;
857*4882a593Smuzhiyun 
858*4882a593Smuzhiyun 	if (!tun->stepsize) {
859*4882a593Smuzhiyun 		/* tuner-core was loaded before the digital tuner was
860*4882a593Smuzhiyun 		 * configured and somehow picked the wrong tuner type */
861*4882a593Smuzhiyun 		tuner_err("attempt to treat tuner %d (%s) as digital tuner without stepsize defined.\n",
862*4882a593Smuzhiyun 			  priv->type, priv->tun->name);
863*4882a593Smuzhiyun 		return 0; /* failure */
864*4882a593Smuzhiyun 	}
865*4882a593Smuzhiyun 
866*4882a593Smuzhiyun 	t_params = simple_tuner_params(fe, TUNER_PARAM_TYPE_DIGITAL);
867*4882a593Smuzhiyun 	ret = simple_config_lookup(fe, t_params, &frequency, &config, &cb);
868*4882a593Smuzhiyun 	if (ret < 0)
869*4882a593Smuzhiyun 		return 0; /* failure */
870*4882a593Smuzhiyun 
871*4882a593Smuzhiyun 	div = ((frequency + t_params->iffreq) * 62500 + offset +
872*4882a593Smuzhiyun 	       tun->stepsize/2) / tun->stepsize;
873*4882a593Smuzhiyun 
874*4882a593Smuzhiyun 	buf[0] = div >> 8;
875*4882a593Smuzhiyun 	buf[1] = div & 0xff;
876*4882a593Smuzhiyun 	buf[2] = config;
877*4882a593Smuzhiyun 	buf[3] = cb;
878*4882a593Smuzhiyun 
879*4882a593Smuzhiyun 	simple_set_dvb(fe, buf, delsys, freq, bw);
880*4882a593Smuzhiyun 
881*4882a593Smuzhiyun 	tuner_dbg("%s: div=%d | buf=0x%02x,0x%02x,0x%02x,0x%02x\n",
882*4882a593Smuzhiyun 		  tun->name, div, buf[0], buf[1], buf[2], buf[3]);
883*4882a593Smuzhiyun 
884*4882a593Smuzhiyun 	/* calculate the frequency we set it to */
885*4882a593Smuzhiyun 	return (div * tun->stepsize) - t_params->iffreq;
886*4882a593Smuzhiyun }
887*4882a593Smuzhiyun 
simple_dvb_calc_regs(struct dvb_frontend * fe,u8 * buf,int buf_len)888*4882a593Smuzhiyun static int simple_dvb_calc_regs(struct dvb_frontend *fe,
889*4882a593Smuzhiyun 				u8 *buf, int buf_len)
890*4882a593Smuzhiyun {
891*4882a593Smuzhiyun 	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
892*4882a593Smuzhiyun 	u32 delsys = c->delivery_system;
893*4882a593Smuzhiyun 	u32 bw = c->bandwidth_hz;
894*4882a593Smuzhiyun 	struct tuner_simple_priv *priv = fe->tuner_priv;
895*4882a593Smuzhiyun 	u32 frequency;
896*4882a593Smuzhiyun 
897*4882a593Smuzhiyun 	if (buf_len < 5)
898*4882a593Smuzhiyun 		return -EINVAL;
899*4882a593Smuzhiyun 
900*4882a593Smuzhiyun 	frequency = simple_dvb_configure(fe, buf+1, delsys, c->frequency, bw);
901*4882a593Smuzhiyun 	if (frequency == 0)
902*4882a593Smuzhiyun 		return -EINVAL;
903*4882a593Smuzhiyun 
904*4882a593Smuzhiyun 	buf[0] = priv->i2c_props.addr;
905*4882a593Smuzhiyun 
906*4882a593Smuzhiyun 	priv->frequency = frequency;
907*4882a593Smuzhiyun 	priv->bandwidth = c->bandwidth_hz;
908*4882a593Smuzhiyun 
909*4882a593Smuzhiyun 	return 5;
910*4882a593Smuzhiyun }
911*4882a593Smuzhiyun 
simple_dvb_set_params(struct dvb_frontend * fe)912*4882a593Smuzhiyun static int simple_dvb_set_params(struct dvb_frontend *fe)
913*4882a593Smuzhiyun {
914*4882a593Smuzhiyun 	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
915*4882a593Smuzhiyun 	u32 delsys = c->delivery_system;
916*4882a593Smuzhiyun 	u32 bw = c->bandwidth_hz;
917*4882a593Smuzhiyun 	u32 freq = c->frequency;
918*4882a593Smuzhiyun 	struct tuner_simple_priv *priv = fe->tuner_priv;
919*4882a593Smuzhiyun 	u32 frequency;
920*4882a593Smuzhiyun 	u32 prev_freq, prev_bw;
921*4882a593Smuzhiyun 	int ret;
922*4882a593Smuzhiyun 	u8 buf[5];
923*4882a593Smuzhiyun 
924*4882a593Smuzhiyun 	if (priv->i2c_props.adap == NULL)
925*4882a593Smuzhiyun 		return -EINVAL;
926*4882a593Smuzhiyun 
927*4882a593Smuzhiyun 	prev_freq = priv->frequency;
928*4882a593Smuzhiyun 	prev_bw   = priv->bandwidth;
929*4882a593Smuzhiyun 
930*4882a593Smuzhiyun 	frequency = simple_dvb_configure(fe, buf+1, delsys, freq, bw);
931*4882a593Smuzhiyun 	if (frequency == 0)
932*4882a593Smuzhiyun 		return -EINVAL;
933*4882a593Smuzhiyun 
934*4882a593Smuzhiyun 	buf[0] = priv->i2c_props.addr;
935*4882a593Smuzhiyun 
936*4882a593Smuzhiyun 	priv->frequency = frequency;
937*4882a593Smuzhiyun 	priv->bandwidth = bw;
938*4882a593Smuzhiyun 
939*4882a593Smuzhiyun 	/* put analog demod in standby when tuning digital */
940*4882a593Smuzhiyun 	if (fe->ops.analog_ops.standby)
941*4882a593Smuzhiyun 		fe->ops.analog_ops.standby(fe);
942*4882a593Smuzhiyun 
943*4882a593Smuzhiyun 	if (fe->ops.i2c_gate_ctrl)
944*4882a593Smuzhiyun 		fe->ops.i2c_gate_ctrl(fe, 1);
945*4882a593Smuzhiyun 
946*4882a593Smuzhiyun 	/* buf[0] contains the i2c address, but *
947*4882a593Smuzhiyun 	 * we already have it in i2c_props.addr */
948*4882a593Smuzhiyun 	ret = tuner_i2c_xfer_send(&priv->i2c_props, buf+1, 4);
949*4882a593Smuzhiyun 	if (ret != 4)
950*4882a593Smuzhiyun 		goto fail;
951*4882a593Smuzhiyun 
952*4882a593Smuzhiyun 	return 0;
953*4882a593Smuzhiyun fail:
954*4882a593Smuzhiyun 	/* calc_regs sets frequency and bandwidth. if we failed, unset them */
955*4882a593Smuzhiyun 	priv->frequency = prev_freq;
956*4882a593Smuzhiyun 	priv->bandwidth = prev_bw;
957*4882a593Smuzhiyun 
958*4882a593Smuzhiyun 	return ret;
959*4882a593Smuzhiyun }
960*4882a593Smuzhiyun 
simple_init(struct dvb_frontend * fe)961*4882a593Smuzhiyun static int simple_init(struct dvb_frontend *fe)
962*4882a593Smuzhiyun {
963*4882a593Smuzhiyun 	struct tuner_simple_priv *priv = fe->tuner_priv;
964*4882a593Smuzhiyun 
965*4882a593Smuzhiyun 	if (priv->i2c_props.adap == NULL)
966*4882a593Smuzhiyun 		return -EINVAL;
967*4882a593Smuzhiyun 
968*4882a593Smuzhiyun 	if (priv->tun->initdata) {
969*4882a593Smuzhiyun 		int ret;
970*4882a593Smuzhiyun 
971*4882a593Smuzhiyun 		if (fe->ops.i2c_gate_ctrl)
972*4882a593Smuzhiyun 			fe->ops.i2c_gate_ctrl(fe, 1);
973*4882a593Smuzhiyun 
974*4882a593Smuzhiyun 		ret = tuner_i2c_xfer_send(&priv->i2c_props,
975*4882a593Smuzhiyun 					  priv->tun->initdata + 1,
976*4882a593Smuzhiyun 					  priv->tun->initdata[0]);
977*4882a593Smuzhiyun 		if (ret != priv->tun->initdata[0])
978*4882a593Smuzhiyun 			return ret;
979*4882a593Smuzhiyun 	}
980*4882a593Smuzhiyun 
981*4882a593Smuzhiyun 	return 0;
982*4882a593Smuzhiyun }
983*4882a593Smuzhiyun 
simple_sleep(struct dvb_frontend * fe)984*4882a593Smuzhiyun static int simple_sleep(struct dvb_frontend *fe)
985*4882a593Smuzhiyun {
986*4882a593Smuzhiyun 	struct tuner_simple_priv *priv = fe->tuner_priv;
987*4882a593Smuzhiyun 
988*4882a593Smuzhiyun 	if (priv->i2c_props.adap == NULL)
989*4882a593Smuzhiyun 		return -EINVAL;
990*4882a593Smuzhiyun 
991*4882a593Smuzhiyun 	if (priv->tun->sleepdata) {
992*4882a593Smuzhiyun 		int ret;
993*4882a593Smuzhiyun 
994*4882a593Smuzhiyun 		if (fe->ops.i2c_gate_ctrl)
995*4882a593Smuzhiyun 			fe->ops.i2c_gate_ctrl(fe, 1);
996*4882a593Smuzhiyun 
997*4882a593Smuzhiyun 		ret = tuner_i2c_xfer_send(&priv->i2c_props,
998*4882a593Smuzhiyun 					  priv->tun->sleepdata + 1,
999*4882a593Smuzhiyun 					  priv->tun->sleepdata[0]);
1000*4882a593Smuzhiyun 		if (ret != priv->tun->sleepdata[0])
1001*4882a593Smuzhiyun 			return ret;
1002*4882a593Smuzhiyun 	}
1003*4882a593Smuzhiyun 
1004*4882a593Smuzhiyun 	return 0;
1005*4882a593Smuzhiyun }
1006*4882a593Smuzhiyun 
simple_release(struct dvb_frontend * fe)1007*4882a593Smuzhiyun static void simple_release(struct dvb_frontend *fe)
1008*4882a593Smuzhiyun {
1009*4882a593Smuzhiyun 	struct tuner_simple_priv *priv = fe->tuner_priv;
1010*4882a593Smuzhiyun 
1011*4882a593Smuzhiyun 	mutex_lock(&tuner_simple_list_mutex);
1012*4882a593Smuzhiyun 
1013*4882a593Smuzhiyun 	if (priv)
1014*4882a593Smuzhiyun 		hybrid_tuner_release_state(priv);
1015*4882a593Smuzhiyun 
1016*4882a593Smuzhiyun 	mutex_unlock(&tuner_simple_list_mutex);
1017*4882a593Smuzhiyun 
1018*4882a593Smuzhiyun 	fe->tuner_priv = NULL;
1019*4882a593Smuzhiyun }
1020*4882a593Smuzhiyun 
simple_get_frequency(struct dvb_frontend * fe,u32 * frequency)1021*4882a593Smuzhiyun static int simple_get_frequency(struct dvb_frontend *fe, u32 *frequency)
1022*4882a593Smuzhiyun {
1023*4882a593Smuzhiyun 	struct tuner_simple_priv *priv = fe->tuner_priv;
1024*4882a593Smuzhiyun 	*frequency = priv->frequency;
1025*4882a593Smuzhiyun 	return 0;
1026*4882a593Smuzhiyun }
1027*4882a593Smuzhiyun 
simple_get_bandwidth(struct dvb_frontend * fe,u32 * bandwidth)1028*4882a593Smuzhiyun static int simple_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
1029*4882a593Smuzhiyun {
1030*4882a593Smuzhiyun 	struct tuner_simple_priv *priv = fe->tuner_priv;
1031*4882a593Smuzhiyun 	*bandwidth = priv->bandwidth;
1032*4882a593Smuzhiyun 	return 0;
1033*4882a593Smuzhiyun }
1034*4882a593Smuzhiyun 
1035*4882a593Smuzhiyun static const struct dvb_tuner_ops simple_tuner_ops = {
1036*4882a593Smuzhiyun 	.init              = simple_init,
1037*4882a593Smuzhiyun 	.sleep             = simple_sleep,
1038*4882a593Smuzhiyun 	.set_analog_params = simple_set_params,
1039*4882a593Smuzhiyun 	.set_params        = simple_dvb_set_params,
1040*4882a593Smuzhiyun 	.calc_regs         = simple_dvb_calc_regs,
1041*4882a593Smuzhiyun 	.release           = simple_release,
1042*4882a593Smuzhiyun 	.get_frequency     = simple_get_frequency,
1043*4882a593Smuzhiyun 	.get_bandwidth     = simple_get_bandwidth,
1044*4882a593Smuzhiyun 	.get_status        = simple_get_status,
1045*4882a593Smuzhiyun 	.get_rf_strength   = simple_get_rf_strength,
1046*4882a593Smuzhiyun };
1047*4882a593Smuzhiyun 
simple_tuner_attach(struct dvb_frontend * fe,struct i2c_adapter * i2c_adap,u8 i2c_addr,unsigned int type)1048*4882a593Smuzhiyun struct dvb_frontend *simple_tuner_attach(struct dvb_frontend *fe,
1049*4882a593Smuzhiyun 					 struct i2c_adapter *i2c_adap,
1050*4882a593Smuzhiyun 					 u8 i2c_addr,
1051*4882a593Smuzhiyun 					 unsigned int type)
1052*4882a593Smuzhiyun {
1053*4882a593Smuzhiyun 	struct tuner_simple_priv *priv = NULL;
1054*4882a593Smuzhiyun 	int instance;
1055*4882a593Smuzhiyun 
1056*4882a593Smuzhiyun 	if (type >= tuner_count) {
1057*4882a593Smuzhiyun 		printk(KERN_WARNING "%s: invalid tuner type: %d (max: %d)\n",
1058*4882a593Smuzhiyun 		       __func__, type, tuner_count-1);
1059*4882a593Smuzhiyun 		return NULL;
1060*4882a593Smuzhiyun 	}
1061*4882a593Smuzhiyun 
1062*4882a593Smuzhiyun 	/* If i2c_adap is set, check that the tuner is at the correct address.
1063*4882a593Smuzhiyun 	 * Otherwise, if i2c_adap is NULL, the tuner will be programmed directly
1064*4882a593Smuzhiyun 	 * by the digital demod via calc_regs.
1065*4882a593Smuzhiyun 	 */
1066*4882a593Smuzhiyun 	if (i2c_adap != NULL) {
1067*4882a593Smuzhiyun 		u8 b[1];
1068*4882a593Smuzhiyun 		struct i2c_msg msg = {
1069*4882a593Smuzhiyun 			.addr = i2c_addr, .flags = I2C_M_RD,
1070*4882a593Smuzhiyun 			.buf = b, .len = 1,
1071*4882a593Smuzhiyun 		};
1072*4882a593Smuzhiyun 
1073*4882a593Smuzhiyun 		if (fe->ops.i2c_gate_ctrl)
1074*4882a593Smuzhiyun 			fe->ops.i2c_gate_ctrl(fe, 1);
1075*4882a593Smuzhiyun 
1076*4882a593Smuzhiyun 		if (1 != i2c_transfer(i2c_adap, &msg, 1))
1077*4882a593Smuzhiyun 			printk(KERN_WARNING "tuner-simple %d-%04x: unable to probe %s, proceeding anyway.",
1078*4882a593Smuzhiyun 			       i2c_adapter_id(i2c_adap), i2c_addr,
1079*4882a593Smuzhiyun 			       tuners[type].name);
1080*4882a593Smuzhiyun 
1081*4882a593Smuzhiyun 		if (fe->ops.i2c_gate_ctrl)
1082*4882a593Smuzhiyun 			fe->ops.i2c_gate_ctrl(fe, 0);
1083*4882a593Smuzhiyun 	}
1084*4882a593Smuzhiyun 
1085*4882a593Smuzhiyun 	mutex_lock(&tuner_simple_list_mutex);
1086*4882a593Smuzhiyun 
1087*4882a593Smuzhiyun 	instance = hybrid_tuner_request_state(struct tuner_simple_priv, priv,
1088*4882a593Smuzhiyun 					      hybrid_tuner_instance_list,
1089*4882a593Smuzhiyun 					      i2c_adap, i2c_addr,
1090*4882a593Smuzhiyun 					      "tuner-simple");
1091*4882a593Smuzhiyun 	switch (instance) {
1092*4882a593Smuzhiyun 	case 0:
1093*4882a593Smuzhiyun 		mutex_unlock(&tuner_simple_list_mutex);
1094*4882a593Smuzhiyun 		return NULL;
1095*4882a593Smuzhiyun 	case 1:
1096*4882a593Smuzhiyun 		fe->tuner_priv = priv;
1097*4882a593Smuzhiyun 
1098*4882a593Smuzhiyun 		priv->type = type;
1099*4882a593Smuzhiyun 		priv->tun  = &tuners[type];
1100*4882a593Smuzhiyun 		priv->nr   = simple_devcount++;
1101*4882a593Smuzhiyun 		break;
1102*4882a593Smuzhiyun 	default:
1103*4882a593Smuzhiyun 		fe->tuner_priv = priv;
1104*4882a593Smuzhiyun 		break;
1105*4882a593Smuzhiyun 	}
1106*4882a593Smuzhiyun 
1107*4882a593Smuzhiyun 	mutex_unlock(&tuner_simple_list_mutex);
1108*4882a593Smuzhiyun 
1109*4882a593Smuzhiyun 	memcpy(&fe->ops.tuner_ops, &simple_tuner_ops,
1110*4882a593Smuzhiyun 	       sizeof(struct dvb_tuner_ops));
1111*4882a593Smuzhiyun 
1112*4882a593Smuzhiyun 	if (type != priv->type)
1113*4882a593Smuzhiyun 		tuner_warn("couldn't set type to %d. Using %d (%s) instead\n",
1114*4882a593Smuzhiyun 			    type, priv->type, priv->tun->name);
1115*4882a593Smuzhiyun 	else
1116*4882a593Smuzhiyun 		tuner_info("type set to %d (%s)\n",
1117*4882a593Smuzhiyun 			   priv->type, priv->tun->name);
1118*4882a593Smuzhiyun 
1119*4882a593Smuzhiyun 	if ((debug) || ((atv_input[priv->nr] > 0) ||
1120*4882a593Smuzhiyun 			(dtv_input[priv->nr] > 0))) {
1121*4882a593Smuzhiyun 		if (0 == atv_input[priv->nr])
1122*4882a593Smuzhiyun 			tuner_info("tuner %d atv rf input will be autoselected\n",
1123*4882a593Smuzhiyun 				   priv->nr);
1124*4882a593Smuzhiyun 		else
1125*4882a593Smuzhiyun 			tuner_info("tuner %d atv rf input will be set to input %d (insmod option)\n",
1126*4882a593Smuzhiyun 				   priv->nr, atv_input[priv->nr]);
1127*4882a593Smuzhiyun 		if (0 == dtv_input[priv->nr])
1128*4882a593Smuzhiyun 			tuner_info("tuner %d dtv rf input will be autoselected\n",
1129*4882a593Smuzhiyun 				   priv->nr);
1130*4882a593Smuzhiyun 		else
1131*4882a593Smuzhiyun 			tuner_info("tuner %d dtv rf input will be set to input %d (insmod option)\n",
1132*4882a593Smuzhiyun 				   priv->nr, dtv_input[priv->nr]);
1133*4882a593Smuzhiyun 	}
1134*4882a593Smuzhiyun 
1135*4882a593Smuzhiyun 	strscpy(fe->ops.tuner_ops.info.name, priv->tun->name,
1136*4882a593Smuzhiyun 		sizeof(fe->ops.tuner_ops.info.name));
1137*4882a593Smuzhiyun 
1138*4882a593Smuzhiyun 	return fe;
1139*4882a593Smuzhiyun }
1140*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(simple_tuner_attach);
1141*4882a593Smuzhiyun 
1142*4882a593Smuzhiyun MODULE_DESCRIPTION("Simple 4-control-bytes style tuner driver");
1143*4882a593Smuzhiyun MODULE_AUTHOR("Ralph Metzler, Gerd Knorr, Gunther Mayer");
1144*4882a593Smuzhiyun MODULE_LICENSE("GPL");
1145