xref: /OK3568_Linux_fs/kernel/drivers/media/tuners/tda8290.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun 
4*4882a593Smuzhiyun    i2c tv tuner chip device driver
5*4882a593Smuzhiyun    controls the philips tda8290+75 tuner chip combo.
6*4882a593Smuzhiyun 
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun    This "tda8290" module was split apart from the original "tuner" module.
9*4882a593Smuzhiyun */
10*4882a593Smuzhiyun 
11*4882a593Smuzhiyun #include <linux/i2c.h>
12*4882a593Smuzhiyun #include <linux/slab.h>
13*4882a593Smuzhiyun #include <linux/delay.h>
14*4882a593Smuzhiyun #include <linux/videodev2.h>
15*4882a593Smuzhiyun #include "tuner-i2c.h"
16*4882a593Smuzhiyun #include "tda8290.h"
17*4882a593Smuzhiyun #include "tda827x.h"
18*4882a593Smuzhiyun #include "tda18271.h"
19*4882a593Smuzhiyun 
20*4882a593Smuzhiyun static int debug;
21*4882a593Smuzhiyun module_param(debug, int, 0644);
22*4882a593Smuzhiyun MODULE_PARM_DESC(debug, "enable verbose debug messages");
23*4882a593Smuzhiyun 
24*4882a593Smuzhiyun static int deemphasis_50;
25*4882a593Smuzhiyun module_param(deemphasis_50, int, 0644);
26*4882a593Smuzhiyun MODULE_PARM_DESC(deemphasis_50, "0 - 75us deemphasis; 1 - 50us deemphasis");
27*4882a593Smuzhiyun 
28*4882a593Smuzhiyun /* ---------------------------------------------------------------------- */
29*4882a593Smuzhiyun 
30*4882a593Smuzhiyun struct tda8290_priv {
31*4882a593Smuzhiyun 	struct tuner_i2c_props i2c_props;
32*4882a593Smuzhiyun 
33*4882a593Smuzhiyun 	unsigned char tda8290_easy_mode;
34*4882a593Smuzhiyun 
35*4882a593Smuzhiyun 	unsigned char tda827x_addr;
36*4882a593Smuzhiyun 
37*4882a593Smuzhiyun 	unsigned char ver;
38*4882a593Smuzhiyun #define TDA8290   1
39*4882a593Smuzhiyun #define TDA8295   2
40*4882a593Smuzhiyun #define TDA8275   4
41*4882a593Smuzhiyun #define TDA8275A  8
42*4882a593Smuzhiyun #define TDA18271 16
43*4882a593Smuzhiyun 
44*4882a593Smuzhiyun 	struct tda827x_config cfg;
45*4882a593Smuzhiyun 	struct tda18271_std_map *tda18271_std_map;
46*4882a593Smuzhiyun };
47*4882a593Smuzhiyun 
48*4882a593Smuzhiyun /*---------------------------------------------------------------------*/
49*4882a593Smuzhiyun 
tda8290_i2c_bridge(struct dvb_frontend * fe,int close)50*4882a593Smuzhiyun static int tda8290_i2c_bridge(struct dvb_frontend *fe, int close)
51*4882a593Smuzhiyun {
52*4882a593Smuzhiyun 	struct tda8290_priv *priv = fe->analog_demod_priv;
53*4882a593Smuzhiyun 
54*4882a593Smuzhiyun 	static unsigned char  enable[2] = { 0x21, 0xC0 };
55*4882a593Smuzhiyun 	static unsigned char disable[2] = { 0x21, 0x00 };
56*4882a593Smuzhiyun 	unsigned char *msg;
57*4882a593Smuzhiyun 
58*4882a593Smuzhiyun 	if (close) {
59*4882a593Smuzhiyun 		msg = enable;
60*4882a593Smuzhiyun 		tuner_i2c_xfer_send(&priv->i2c_props, msg, 2);
61*4882a593Smuzhiyun 		/* let the bridge stabilize */
62*4882a593Smuzhiyun 		msleep(20);
63*4882a593Smuzhiyun 	} else {
64*4882a593Smuzhiyun 		msg = disable;
65*4882a593Smuzhiyun 		tuner_i2c_xfer_send(&priv->i2c_props, msg, 2);
66*4882a593Smuzhiyun 	}
67*4882a593Smuzhiyun 
68*4882a593Smuzhiyun 	return 0;
69*4882a593Smuzhiyun }
70*4882a593Smuzhiyun 
tda8295_i2c_bridge(struct dvb_frontend * fe,int close)71*4882a593Smuzhiyun static int tda8295_i2c_bridge(struct dvb_frontend *fe, int close)
72*4882a593Smuzhiyun {
73*4882a593Smuzhiyun 	struct tda8290_priv *priv = fe->analog_demod_priv;
74*4882a593Smuzhiyun 
75*4882a593Smuzhiyun 	static unsigned char  enable[2] = { 0x45, 0xc1 };
76*4882a593Smuzhiyun 	static unsigned char disable[2] = { 0x46, 0x00 };
77*4882a593Smuzhiyun 	static unsigned char buf[3] = { 0x45, 0x01, 0x00 };
78*4882a593Smuzhiyun 	unsigned char *msg;
79*4882a593Smuzhiyun 
80*4882a593Smuzhiyun 	if (close) {
81*4882a593Smuzhiyun 		msg = enable;
82*4882a593Smuzhiyun 		tuner_i2c_xfer_send(&priv->i2c_props, msg, 2);
83*4882a593Smuzhiyun 		/* let the bridge stabilize */
84*4882a593Smuzhiyun 		msleep(20);
85*4882a593Smuzhiyun 	} else {
86*4882a593Smuzhiyun 		msg = disable;
87*4882a593Smuzhiyun 		tuner_i2c_xfer_send_recv(&priv->i2c_props, msg, 1, &msg[1], 1);
88*4882a593Smuzhiyun 
89*4882a593Smuzhiyun 		buf[2] = msg[1];
90*4882a593Smuzhiyun 		buf[2] &= ~0x04;
91*4882a593Smuzhiyun 		tuner_i2c_xfer_send(&priv->i2c_props, buf, 3);
92*4882a593Smuzhiyun 		msleep(5);
93*4882a593Smuzhiyun 
94*4882a593Smuzhiyun 		msg[1] |= 0x04;
95*4882a593Smuzhiyun 		tuner_i2c_xfer_send(&priv->i2c_props, msg, 2);
96*4882a593Smuzhiyun 	}
97*4882a593Smuzhiyun 
98*4882a593Smuzhiyun 	return 0;
99*4882a593Smuzhiyun }
100*4882a593Smuzhiyun 
101*4882a593Smuzhiyun /*---------------------------------------------------------------------*/
102*4882a593Smuzhiyun 
set_audio(struct dvb_frontend * fe,struct analog_parameters * params)103*4882a593Smuzhiyun static void set_audio(struct dvb_frontend *fe,
104*4882a593Smuzhiyun 		      struct analog_parameters *params)
105*4882a593Smuzhiyun {
106*4882a593Smuzhiyun 	struct tda8290_priv *priv = fe->analog_demod_priv;
107*4882a593Smuzhiyun 	char* mode;
108*4882a593Smuzhiyun 
109*4882a593Smuzhiyun 	if (params->std & V4L2_STD_MN) {
110*4882a593Smuzhiyun 		priv->tda8290_easy_mode = 0x01;
111*4882a593Smuzhiyun 		mode = "MN";
112*4882a593Smuzhiyun 	} else if (params->std & V4L2_STD_B) {
113*4882a593Smuzhiyun 		priv->tda8290_easy_mode = 0x02;
114*4882a593Smuzhiyun 		mode = "B";
115*4882a593Smuzhiyun 	} else if (params->std & V4L2_STD_GH) {
116*4882a593Smuzhiyun 		priv->tda8290_easy_mode = 0x04;
117*4882a593Smuzhiyun 		mode = "GH";
118*4882a593Smuzhiyun 	} else if (params->std & V4L2_STD_PAL_I) {
119*4882a593Smuzhiyun 		priv->tda8290_easy_mode = 0x08;
120*4882a593Smuzhiyun 		mode = "I";
121*4882a593Smuzhiyun 	} else if (params->std & V4L2_STD_DK) {
122*4882a593Smuzhiyun 		priv->tda8290_easy_mode = 0x10;
123*4882a593Smuzhiyun 		mode = "DK";
124*4882a593Smuzhiyun 	} else if (params->std & V4L2_STD_SECAM_L) {
125*4882a593Smuzhiyun 		priv->tda8290_easy_mode = 0x20;
126*4882a593Smuzhiyun 		mode = "L";
127*4882a593Smuzhiyun 	} else if (params->std & V4L2_STD_SECAM_LC) {
128*4882a593Smuzhiyun 		priv->tda8290_easy_mode = 0x40;
129*4882a593Smuzhiyun 		mode = "LC";
130*4882a593Smuzhiyun 	} else {
131*4882a593Smuzhiyun 		priv->tda8290_easy_mode = 0x10;
132*4882a593Smuzhiyun 		mode = "xx";
133*4882a593Smuzhiyun 	}
134*4882a593Smuzhiyun 
135*4882a593Smuzhiyun 	if (params->mode == V4L2_TUNER_RADIO) {
136*4882a593Smuzhiyun 		/* Set TDA8295 to FM radio; Start TDA8290 with MN values */
137*4882a593Smuzhiyun 		priv->tda8290_easy_mode = (priv->ver & TDA8295) ? 0x80 : 0x01;
138*4882a593Smuzhiyun 		tuner_dbg("setting to radio FM\n");
139*4882a593Smuzhiyun 	} else {
140*4882a593Smuzhiyun 		tuner_dbg("setting tda829x to system %s\n", mode);
141*4882a593Smuzhiyun 	}
142*4882a593Smuzhiyun }
143*4882a593Smuzhiyun 
144*4882a593Smuzhiyun static struct {
145*4882a593Smuzhiyun 	unsigned char seq[2];
146*4882a593Smuzhiyun } fm_mode[] = {
147*4882a593Smuzhiyun 	{ { 0x01, 0x81} },	/* Put device into expert mode */
148*4882a593Smuzhiyun 	{ { 0x03, 0x48} },	/* Disable NOTCH and VIDEO filters */
149*4882a593Smuzhiyun 	{ { 0x04, 0x04} },	/* Disable color carrier filter (SSIF) */
150*4882a593Smuzhiyun 	{ { 0x05, 0x04} },	/* ADC headroom */
151*4882a593Smuzhiyun 	{ { 0x06, 0x10} },	/* group delay flat */
152*4882a593Smuzhiyun 
153*4882a593Smuzhiyun 	{ { 0x07, 0x00} },	/* use the same radio DTO values as a tda8295 */
154*4882a593Smuzhiyun 	{ { 0x08, 0x00} },
155*4882a593Smuzhiyun 	{ { 0x09, 0x80} },
156*4882a593Smuzhiyun 	{ { 0x0a, 0xda} },
157*4882a593Smuzhiyun 	{ { 0x0b, 0x4b} },
158*4882a593Smuzhiyun 	{ { 0x0c, 0x68} },
159*4882a593Smuzhiyun 
160*4882a593Smuzhiyun 	{ { 0x0d, 0x00} },	/* PLL off, no video carrier detect */
161*4882a593Smuzhiyun 	{ { 0x14, 0x00} },	/* disable auto mute if no video */
162*4882a593Smuzhiyun };
163*4882a593Smuzhiyun 
tda8290_set_params(struct dvb_frontend * fe,struct analog_parameters * params)164*4882a593Smuzhiyun static void tda8290_set_params(struct dvb_frontend *fe,
165*4882a593Smuzhiyun 			       struct analog_parameters *params)
166*4882a593Smuzhiyun {
167*4882a593Smuzhiyun 	struct tda8290_priv *priv = fe->analog_demod_priv;
168*4882a593Smuzhiyun 
169*4882a593Smuzhiyun 	static unsigned char soft_reset[]  = { 0x00, 0x00 };
170*4882a593Smuzhiyun 	unsigned char easy_mode[]   = { 0x01, priv->tda8290_easy_mode };
171*4882a593Smuzhiyun 	static unsigned char expert_mode[] = { 0x01, 0x80 };
172*4882a593Smuzhiyun 	static unsigned char agc_out_on[]  = { 0x02, 0x00 };
173*4882a593Smuzhiyun 	static unsigned char gainset_off[] = { 0x28, 0x14 };
174*4882a593Smuzhiyun 	static unsigned char if_agc_spd[]  = { 0x0f, 0x88 };
175*4882a593Smuzhiyun 	static unsigned char adc_head_6[]  = { 0x05, 0x04 };
176*4882a593Smuzhiyun 	static unsigned char adc_head_9[]  = { 0x05, 0x02 };
177*4882a593Smuzhiyun 	static unsigned char adc_head_12[] = { 0x05, 0x01 };
178*4882a593Smuzhiyun 	static unsigned char pll_bw_nom[]  = { 0x0d, 0x47 };
179*4882a593Smuzhiyun 	static unsigned char pll_bw_low[]  = { 0x0d, 0x27 };
180*4882a593Smuzhiyun 	static unsigned char gainset_2[]   = { 0x28, 0x64 };
181*4882a593Smuzhiyun 	static unsigned char agc_rst_on[]  = { 0x0e, 0x0b };
182*4882a593Smuzhiyun 	static unsigned char agc_rst_off[] = { 0x0e, 0x09 };
183*4882a593Smuzhiyun 	static unsigned char if_agc_set[]  = { 0x0f, 0x81 };
184*4882a593Smuzhiyun 	static unsigned char addr_adc_sat  = 0x1a;
185*4882a593Smuzhiyun 	static unsigned char addr_agc_stat = 0x1d;
186*4882a593Smuzhiyun 	static unsigned char addr_pll_stat = 0x1b;
187*4882a593Smuzhiyun 	static unsigned char adc_sat = 0, agc_stat = 0,
188*4882a593Smuzhiyun 		      pll_stat;
189*4882a593Smuzhiyun 	int i;
190*4882a593Smuzhiyun 
191*4882a593Smuzhiyun 	set_audio(fe, params);
192*4882a593Smuzhiyun 
193*4882a593Smuzhiyun 	if (priv->cfg.config)
194*4882a593Smuzhiyun 		tuner_dbg("tda827xa config is 0x%02x\n", priv->cfg.config);
195*4882a593Smuzhiyun 	tuner_i2c_xfer_send(&priv->i2c_props, easy_mode, 2);
196*4882a593Smuzhiyun 	tuner_i2c_xfer_send(&priv->i2c_props, agc_out_on, 2);
197*4882a593Smuzhiyun 	tuner_i2c_xfer_send(&priv->i2c_props, soft_reset, 2);
198*4882a593Smuzhiyun 	msleep(1);
199*4882a593Smuzhiyun 
200*4882a593Smuzhiyun 	if (params->mode == V4L2_TUNER_RADIO) {
201*4882a593Smuzhiyun 		unsigned char deemphasis[]  = { 0x13, 1 };
202*4882a593Smuzhiyun 
203*4882a593Smuzhiyun 		/* FIXME: allow using a different deemphasis */
204*4882a593Smuzhiyun 
205*4882a593Smuzhiyun 		if (deemphasis_50)
206*4882a593Smuzhiyun 			deemphasis[1] = 2;
207*4882a593Smuzhiyun 
208*4882a593Smuzhiyun 		for (i = 0; i < ARRAY_SIZE(fm_mode); i++)
209*4882a593Smuzhiyun 			tuner_i2c_xfer_send(&priv->i2c_props, fm_mode[i].seq, 2);
210*4882a593Smuzhiyun 
211*4882a593Smuzhiyun 		tuner_i2c_xfer_send(&priv->i2c_props, deemphasis, 2);
212*4882a593Smuzhiyun 	} else {
213*4882a593Smuzhiyun 		expert_mode[1] = priv->tda8290_easy_mode + 0x80;
214*4882a593Smuzhiyun 		tuner_i2c_xfer_send(&priv->i2c_props, expert_mode, 2);
215*4882a593Smuzhiyun 		tuner_i2c_xfer_send(&priv->i2c_props, gainset_off, 2);
216*4882a593Smuzhiyun 		tuner_i2c_xfer_send(&priv->i2c_props, if_agc_spd, 2);
217*4882a593Smuzhiyun 		if (priv->tda8290_easy_mode & 0x60)
218*4882a593Smuzhiyun 			tuner_i2c_xfer_send(&priv->i2c_props, adc_head_9, 2);
219*4882a593Smuzhiyun 		else
220*4882a593Smuzhiyun 			tuner_i2c_xfer_send(&priv->i2c_props, adc_head_6, 2);
221*4882a593Smuzhiyun 		tuner_i2c_xfer_send(&priv->i2c_props, pll_bw_nom, 2);
222*4882a593Smuzhiyun 	}
223*4882a593Smuzhiyun 
224*4882a593Smuzhiyun 
225*4882a593Smuzhiyun 	if (fe->ops.analog_ops.i2c_gate_ctrl)
226*4882a593Smuzhiyun 		fe->ops.analog_ops.i2c_gate_ctrl(fe, 1);
227*4882a593Smuzhiyun 
228*4882a593Smuzhiyun 	if (fe->ops.tuner_ops.set_analog_params)
229*4882a593Smuzhiyun 		fe->ops.tuner_ops.set_analog_params(fe, params);
230*4882a593Smuzhiyun 
231*4882a593Smuzhiyun 	for (i = 0; i < 3; i++) {
232*4882a593Smuzhiyun 		tuner_i2c_xfer_send_recv(&priv->i2c_props,
233*4882a593Smuzhiyun 					 &addr_pll_stat, 1, &pll_stat, 1);
234*4882a593Smuzhiyun 		if (pll_stat & 0x80) {
235*4882a593Smuzhiyun 			tuner_i2c_xfer_send_recv(&priv->i2c_props,
236*4882a593Smuzhiyun 						 &addr_adc_sat, 1,
237*4882a593Smuzhiyun 						 &adc_sat, 1);
238*4882a593Smuzhiyun 			tuner_i2c_xfer_send_recv(&priv->i2c_props,
239*4882a593Smuzhiyun 						 &addr_agc_stat, 1,
240*4882a593Smuzhiyun 						 &agc_stat, 1);
241*4882a593Smuzhiyun 			tuner_dbg("tda8290 is locked, AGC: %d\n", agc_stat);
242*4882a593Smuzhiyun 			break;
243*4882a593Smuzhiyun 		} else {
244*4882a593Smuzhiyun 			tuner_dbg("tda8290 not locked, no signal?\n");
245*4882a593Smuzhiyun 			msleep(100);
246*4882a593Smuzhiyun 		}
247*4882a593Smuzhiyun 	}
248*4882a593Smuzhiyun 	/* adjust headroom resp. gain */
249*4882a593Smuzhiyun 	if ((agc_stat > 115) || (!(pll_stat & 0x80) && (adc_sat < 20))) {
250*4882a593Smuzhiyun 		tuner_dbg("adjust gain, step 1. Agc: %d, ADC stat: %d, lock: %d\n",
251*4882a593Smuzhiyun 			   agc_stat, adc_sat, pll_stat & 0x80);
252*4882a593Smuzhiyun 		tuner_i2c_xfer_send(&priv->i2c_props, gainset_2, 2);
253*4882a593Smuzhiyun 		msleep(100);
254*4882a593Smuzhiyun 		tuner_i2c_xfer_send_recv(&priv->i2c_props,
255*4882a593Smuzhiyun 					 &addr_agc_stat, 1, &agc_stat, 1);
256*4882a593Smuzhiyun 		tuner_i2c_xfer_send_recv(&priv->i2c_props,
257*4882a593Smuzhiyun 					 &addr_pll_stat, 1, &pll_stat, 1);
258*4882a593Smuzhiyun 		if ((agc_stat > 115) || !(pll_stat & 0x80)) {
259*4882a593Smuzhiyun 			tuner_dbg("adjust gain, step 2. Agc: %d, lock: %d\n",
260*4882a593Smuzhiyun 				   agc_stat, pll_stat & 0x80);
261*4882a593Smuzhiyun 			if (priv->cfg.agcf)
262*4882a593Smuzhiyun 				priv->cfg.agcf(fe);
263*4882a593Smuzhiyun 			msleep(100);
264*4882a593Smuzhiyun 			tuner_i2c_xfer_send_recv(&priv->i2c_props,
265*4882a593Smuzhiyun 						 &addr_agc_stat, 1,
266*4882a593Smuzhiyun 						 &agc_stat, 1);
267*4882a593Smuzhiyun 			tuner_i2c_xfer_send_recv(&priv->i2c_props,
268*4882a593Smuzhiyun 						 &addr_pll_stat, 1,
269*4882a593Smuzhiyun 						 &pll_stat, 1);
270*4882a593Smuzhiyun 			if((agc_stat > 115) || !(pll_stat & 0x80)) {
271*4882a593Smuzhiyun 				tuner_dbg("adjust gain, step 3. Agc: %d\n", agc_stat);
272*4882a593Smuzhiyun 				tuner_i2c_xfer_send(&priv->i2c_props, adc_head_12, 2);
273*4882a593Smuzhiyun 				tuner_i2c_xfer_send(&priv->i2c_props, pll_bw_low, 2);
274*4882a593Smuzhiyun 				msleep(100);
275*4882a593Smuzhiyun 			}
276*4882a593Smuzhiyun 		}
277*4882a593Smuzhiyun 	}
278*4882a593Smuzhiyun 
279*4882a593Smuzhiyun 	/* l/ l' deadlock? */
280*4882a593Smuzhiyun 	if(priv->tda8290_easy_mode & 0x60) {
281*4882a593Smuzhiyun 		tuner_i2c_xfer_send_recv(&priv->i2c_props,
282*4882a593Smuzhiyun 					 &addr_adc_sat, 1,
283*4882a593Smuzhiyun 					 &adc_sat, 1);
284*4882a593Smuzhiyun 		tuner_i2c_xfer_send_recv(&priv->i2c_props,
285*4882a593Smuzhiyun 					 &addr_pll_stat, 1,
286*4882a593Smuzhiyun 					 &pll_stat, 1);
287*4882a593Smuzhiyun 		if ((adc_sat > 20) || !(pll_stat & 0x80)) {
288*4882a593Smuzhiyun 			tuner_dbg("trying to resolve SECAM L deadlock\n");
289*4882a593Smuzhiyun 			tuner_i2c_xfer_send(&priv->i2c_props, agc_rst_on, 2);
290*4882a593Smuzhiyun 			msleep(40);
291*4882a593Smuzhiyun 			tuner_i2c_xfer_send(&priv->i2c_props, agc_rst_off, 2);
292*4882a593Smuzhiyun 		}
293*4882a593Smuzhiyun 	}
294*4882a593Smuzhiyun 
295*4882a593Smuzhiyun 	if (fe->ops.analog_ops.i2c_gate_ctrl)
296*4882a593Smuzhiyun 		fe->ops.analog_ops.i2c_gate_ctrl(fe, 0);
297*4882a593Smuzhiyun 	tuner_i2c_xfer_send(&priv->i2c_props, if_agc_set, 2);
298*4882a593Smuzhiyun }
299*4882a593Smuzhiyun 
300*4882a593Smuzhiyun /*---------------------------------------------------------------------*/
301*4882a593Smuzhiyun 
tda8295_power(struct dvb_frontend * fe,int enable)302*4882a593Smuzhiyun static void tda8295_power(struct dvb_frontend *fe, int enable)
303*4882a593Smuzhiyun {
304*4882a593Smuzhiyun 	struct tda8290_priv *priv = fe->analog_demod_priv;
305*4882a593Smuzhiyun 	unsigned char buf[] = { 0x30, 0x00 }; /* clb_stdbt */
306*4882a593Smuzhiyun 
307*4882a593Smuzhiyun 	tuner_i2c_xfer_send_recv(&priv->i2c_props, &buf[0], 1, &buf[1], 1);
308*4882a593Smuzhiyun 
309*4882a593Smuzhiyun 	if (enable)
310*4882a593Smuzhiyun 		buf[1] = 0x01;
311*4882a593Smuzhiyun 	else
312*4882a593Smuzhiyun 		buf[1] = 0x03;
313*4882a593Smuzhiyun 
314*4882a593Smuzhiyun 	tuner_i2c_xfer_send(&priv->i2c_props, buf, 2);
315*4882a593Smuzhiyun }
316*4882a593Smuzhiyun 
tda8295_set_easy_mode(struct dvb_frontend * fe,int enable)317*4882a593Smuzhiyun static void tda8295_set_easy_mode(struct dvb_frontend *fe, int enable)
318*4882a593Smuzhiyun {
319*4882a593Smuzhiyun 	struct tda8290_priv *priv = fe->analog_demod_priv;
320*4882a593Smuzhiyun 	unsigned char buf[] = { 0x01, 0x00 };
321*4882a593Smuzhiyun 
322*4882a593Smuzhiyun 	tuner_i2c_xfer_send_recv(&priv->i2c_props, &buf[0], 1, &buf[1], 1);
323*4882a593Smuzhiyun 
324*4882a593Smuzhiyun 	if (enable)
325*4882a593Smuzhiyun 		buf[1] = 0x01; /* rising edge sets regs 0x02 - 0x23 */
326*4882a593Smuzhiyun 	else
327*4882a593Smuzhiyun 		buf[1] = 0x00; /* reset active bit */
328*4882a593Smuzhiyun 
329*4882a593Smuzhiyun 	tuner_i2c_xfer_send(&priv->i2c_props, buf, 2);
330*4882a593Smuzhiyun }
331*4882a593Smuzhiyun 
tda8295_set_video_std(struct dvb_frontend * fe)332*4882a593Smuzhiyun static void tda8295_set_video_std(struct dvb_frontend *fe)
333*4882a593Smuzhiyun {
334*4882a593Smuzhiyun 	struct tda8290_priv *priv = fe->analog_demod_priv;
335*4882a593Smuzhiyun 	unsigned char buf[] = { 0x00, priv->tda8290_easy_mode };
336*4882a593Smuzhiyun 
337*4882a593Smuzhiyun 	tuner_i2c_xfer_send(&priv->i2c_props, buf, 2);
338*4882a593Smuzhiyun 
339*4882a593Smuzhiyun 	tda8295_set_easy_mode(fe, 1);
340*4882a593Smuzhiyun 	msleep(20);
341*4882a593Smuzhiyun 	tda8295_set_easy_mode(fe, 0);
342*4882a593Smuzhiyun }
343*4882a593Smuzhiyun 
344*4882a593Smuzhiyun /*---------------------------------------------------------------------*/
345*4882a593Smuzhiyun 
tda8295_agc1_out(struct dvb_frontend * fe,int enable)346*4882a593Smuzhiyun static void tda8295_agc1_out(struct dvb_frontend *fe, int enable)
347*4882a593Smuzhiyun {
348*4882a593Smuzhiyun 	struct tda8290_priv *priv = fe->analog_demod_priv;
349*4882a593Smuzhiyun 	unsigned char buf[] = { 0x02, 0x00 }; /* DIV_FUNC */
350*4882a593Smuzhiyun 
351*4882a593Smuzhiyun 	tuner_i2c_xfer_send_recv(&priv->i2c_props, &buf[0], 1, &buf[1], 1);
352*4882a593Smuzhiyun 
353*4882a593Smuzhiyun 	if (enable)
354*4882a593Smuzhiyun 		buf[1] &= ~0x40;
355*4882a593Smuzhiyun 	else
356*4882a593Smuzhiyun 		buf[1] |= 0x40;
357*4882a593Smuzhiyun 
358*4882a593Smuzhiyun 	tuner_i2c_xfer_send(&priv->i2c_props, buf, 2);
359*4882a593Smuzhiyun }
360*4882a593Smuzhiyun 
tda8295_agc2_out(struct dvb_frontend * fe,int enable)361*4882a593Smuzhiyun static void tda8295_agc2_out(struct dvb_frontend *fe, int enable)
362*4882a593Smuzhiyun {
363*4882a593Smuzhiyun 	struct tda8290_priv *priv = fe->analog_demod_priv;
364*4882a593Smuzhiyun 	unsigned char set_gpio_cf[]    = { 0x44, 0x00 };
365*4882a593Smuzhiyun 	unsigned char set_gpio_val[]   = { 0x46, 0x00 };
366*4882a593Smuzhiyun 
367*4882a593Smuzhiyun 	tuner_i2c_xfer_send_recv(&priv->i2c_props,
368*4882a593Smuzhiyun 				 &set_gpio_cf[0], 1, &set_gpio_cf[1], 1);
369*4882a593Smuzhiyun 	tuner_i2c_xfer_send_recv(&priv->i2c_props,
370*4882a593Smuzhiyun 				 &set_gpio_val[0], 1, &set_gpio_val[1], 1);
371*4882a593Smuzhiyun 
372*4882a593Smuzhiyun 	set_gpio_cf[1] &= 0xf0; /* clear GPIO_0 bits 3-0 */
373*4882a593Smuzhiyun 
374*4882a593Smuzhiyun 	if (enable) {
375*4882a593Smuzhiyun 		set_gpio_cf[1]  |= 0x01; /* config GPIO_0 as Open Drain Out */
376*4882a593Smuzhiyun 		set_gpio_val[1] &= 0xfe; /* set GPIO_0 pin low */
377*4882a593Smuzhiyun 	}
378*4882a593Smuzhiyun 	tuner_i2c_xfer_send(&priv->i2c_props, set_gpio_cf, 2);
379*4882a593Smuzhiyun 	tuner_i2c_xfer_send(&priv->i2c_props, set_gpio_val, 2);
380*4882a593Smuzhiyun }
381*4882a593Smuzhiyun 
tda8295_has_signal(struct dvb_frontend * fe,u16 * signal)382*4882a593Smuzhiyun static int tda8295_has_signal(struct dvb_frontend *fe, u16 *signal)
383*4882a593Smuzhiyun {
384*4882a593Smuzhiyun 	struct tda8290_priv *priv = fe->analog_demod_priv;
385*4882a593Smuzhiyun 
386*4882a593Smuzhiyun 	unsigned char hvpll_stat = 0x26;
387*4882a593Smuzhiyun 	unsigned char ret;
388*4882a593Smuzhiyun 
389*4882a593Smuzhiyun 	tuner_i2c_xfer_send_recv(&priv->i2c_props, &hvpll_stat, 1, &ret, 1);
390*4882a593Smuzhiyun 	*signal = (ret & 0x01) ? 65535 : 0;
391*4882a593Smuzhiyun 	return 0;
392*4882a593Smuzhiyun }
393*4882a593Smuzhiyun 
394*4882a593Smuzhiyun /*---------------------------------------------------------------------*/
395*4882a593Smuzhiyun 
tda8295_set_params(struct dvb_frontend * fe,struct analog_parameters * params)396*4882a593Smuzhiyun static void tda8295_set_params(struct dvb_frontend *fe,
397*4882a593Smuzhiyun 			       struct analog_parameters *params)
398*4882a593Smuzhiyun {
399*4882a593Smuzhiyun 	struct tda8290_priv *priv = fe->analog_demod_priv;
400*4882a593Smuzhiyun 	u16 signal = 0;
401*4882a593Smuzhiyun 	unsigned char blanking_mode[]     = { 0x1d, 0x00 };
402*4882a593Smuzhiyun 
403*4882a593Smuzhiyun 	set_audio(fe, params);
404*4882a593Smuzhiyun 
405*4882a593Smuzhiyun 	tuner_dbg("%s: freq = %d\n", __func__, params->frequency);
406*4882a593Smuzhiyun 
407*4882a593Smuzhiyun 	tda8295_power(fe, 1);
408*4882a593Smuzhiyun 	tda8295_agc1_out(fe, 1);
409*4882a593Smuzhiyun 
410*4882a593Smuzhiyun 	tuner_i2c_xfer_send_recv(&priv->i2c_props,
411*4882a593Smuzhiyun 				 &blanking_mode[0], 1, &blanking_mode[1], 1);
412*4882a593Smuzhiyun 
413*4882a593Smuzhiyun 	tda8295_set_video_std(fe);
414*4882a593Smuzhiyun 
415*4882a593Smuzhiyun 	blanking_mode[1] = 0x03;
416*4882a593Smuzhiyun 	tuner_i2c_xfer_send(&priv->i2c_props, blanking_mode, 2);
417*4882a593Smuzhiyun 	msleep(20);
418*4882a593Smuzhiyun 
419*4882a593Smuzhiyun 	if (fe->ops.analog_ops.i2c_gate_ctrl)
420*4882a593Smuzhiyun 		fe->ops.analog_ops.i2c_gate_ctrl(fe, 1);
421*4882a593Smuzhiyun 
422*4882a593Smuzhiyun 	if (fe->ops.tuner_ops.set_analog_params)
423*4882a593Smuzhiyun 		fe->ops.tuner_ops.set_analog_params(fe, params);
424*4882a593Smuzhiyun 
425*4882a593Smuzhiyun 	if (priv->cfg.agcf)
426*4882a593Smuzhiyun 		priv->cfg.agcf(fe);
427*4882a593Smuzhiyun 
428*4882a593Smuzhiyun 	tda8295_has_signal(fe, &signal);
429*4882a593Smuzhiyun 	if (signal)
430*4882a593Smuzhiyun 		tuner_dbg("tda8295 is locked\n");
431*4882a593Smuzhiyun 	else
432*4882a593Smuzhiyun 		tuner_dbg("tda8295 not locked, no signal?\n");
433*4882a593Smuzhiyun 
434*4882a593Smuzhiyun 	if (fe->ops.analog_ops.i2c_gate_ctrl)
435*4882a593Smuzhiyun 		fe->ops.analog_ops.i2c_gate_ctrl(fe, 0);
436*4882a593Smuzhiyun }
437*4882a593Smuzhiyun 
438*4882a593Smuzhiyun /*---------------------------------------------------------------------*/
439*4882a593Smuzhiyun 
tda8290_has_signal(struct dvb_frontend * fe,u16 * signal)440*4882a593Smuzhiyun static int tda8290_has_signal(struct dvb_frontend *fe, u16 *signal)
441*4882a593Smuzhiyun {
442*4882a593Smuzhiyun 	struct tda8290_priv *priv = fe->analog_demod_priv;
443*4882a593Smuzhiyun 
444*4882a593Smuzhiyun 	unsigned char i2c_get_afc[1] = { 0x1B };
445*4882a593Smuzhiyun 	unsigned char afc = 0;
446*4882a593Smuzhiyun 
447*4882a593Smuzhiyun 	tuner_i2c_xfer_send_recv(&priv->i2c_props,
448*4882a593Smuzhiyun 				 i2c_get_afc, ARRAY_SIZE(i2c_get_afc), &afc, 1);
449*4882a593Smuzhiyun 	*signal = (afc & 0x80) ? 65535 : 0;
450*4882a593Smuzhiyun 	return 0;
451*4882a593Smuzhiyun }
452*4882a593Smuzhiyun 
453*4882a593Smuzhiyun /*---------------------------------------------------------------------*/
454*4882a593Smuzhiyun 
tda8290_standby(struct dvb_frontend * fe)455*4882a593Smuzhiyun static void tda8290_standby(struct dvb_frontend *fe)
456*4882a593Smuzhiyun {
457*4882a593Smuzhiyun 	struct tda8290_priv *priv = fe->analog_demod_priv;
458*4882a593Smuzhiyun 
459*4882a593Smuzhiyun 	static unsigned char cb1[] = { 0x30, 0xD0 };
460*4882a593Smuzhiyun 	static unsigned char tda8290_standby[] = { 0x00, 0x02 };
461*4882a593Smuzhiyun 	static unsigned char tda8290_agc_tri[] = { 0x02, 0x20 };
462*4882a593Smuzhiyun 	struct i2c_msg msg = {.addr = priv->tda827x_addr, .flags=0, .buf=cb1, .len = 2};
463*4882a593Smuzhiyun 
464*4882a593Smuzhiyun 	if (fe->ops.analog_ops.i2c_gate_ctrl)
465*4882a593Smuzhiyun 		fe->ops.analog_ops.i2c_gate_ctrl(fe, 1);
466*4882a593Smuzhiyun 	if (priv->ver & TDA8275A)
467*4882a593Smuzhiyun 		cb1[1] = 0x90;
468*4882a593Smuzhiyun 	i2c_transfer(priv->i2c_props.adap, &msg, 1);
469*4882a593Smuzhiyun 	if (fe->ops.analog_ops.i2c_gate_ctrl)
470*4882a593Smuzhiyun 		fe->ops.analog_ops.i2c_gate_ctrl(fe, 0);
471*4882a593Smuzhiyun 	tuner_i2c_xfer_send(&priv->i2c_props, tda8290_agc_tri, 2);
472*4882a593Smuzhiyun 	tuner_i2c_xfer_send(&priv->i2c_props, tda8290_standby, 2);
473*4882a593Smuzhiyun }
474*4882a593Smuzhiyun 
tda8295_standby(struct dvb_frontend * fe)475*4882a593Smuzhiyun static void tda8295_standby(struct dvb_frontend *fe)
476*4882a593Smuzhiyun {
477*4882a593Smuzhiyun 	tda8295_agc1_out(fe, 0); /* Put AGC in tri-state */
478*4882a593Smuzhiyun 
479*4882a593Smuzhiyun 	tda8295_power(fe, 0);
480*4882a593Smuzhiyun }
481*4882a593Smuzhiyun 
tda8290_init_if(struct dvb_frontend * fe)482*4882a593Smuzhiyun static void tda8290_init_if(struct dvb_frontend *fe)
483*4882a593Smuzhiyun {
484*4882a593Smuzhiyun 	struct tda8290_priv *priv = fe->analog_demod_priv;
485*4882a593Smuzhiyun 
486*4882a593Smuzhiyun 	static unsigned char set_VS[] = { 0x30, 0x6F };
487*4882a593Smuzhiyun 	static unsigned char set_GP00_CF[] = { 0x20, 0x01 };
488*4882a593Smuzhiyun 	static unsigned char set_GP01_CF[] = { 0x20, 0x0B };
489*4882a593Smuzhiyun 
490*4882a593Smuzhiyun 	if ((priv->cfg.config == TDA8290_LNA_GP0_HIGH_ON) ||
491*4882a593Smuzhiyun 	    (priv->cfg.config == TDA8290_LNA_GP0_HIGH_OFF))
492*4882a593Smuzhiyun 		tuner_i2c_xfer_send(&priv->i2c_props, set_GP00_CF, 2);
493*4882a593Smuzhiyun 	else
494*4882a593Smuzhiyun 		tuner_i2c_xfer_send(&priv->i2c_props, set_GP01_CF, 2);
495*4882a593Smuzhiyun 	tuner_i2c_xfer_send(&priv->i2c_props, set_VS, 2);
496*4882a593Smuzhiyun }
497*4882a593Smuzhiyun 
tda8295_init_if(struct dvb_frontend * fe)498*4882a593Smuzhiyun static void tda8295_init_if(struct dvb_frontend *fe)
499*4882a593Smuzhiyun {
500*4882a593Smuzhiyun 	struct tda8290_priv *priv = fe->analog_demod_priv;
501*4882a593Smuzhiyun 
502*4882a593Smuzhiyun 	static unsigned char set_adc_ctl[]       = { 0x33, 0x14 };
503*4882a593Smuzhiyun 	static unsigned char set_adc_ctl2[]      = { 0x34, 0x00 };
504*4882a593Smuzhiyun 	static unsigned char set_pll_reg6[]      = { 0x3e, 0x63 };
505*4882a593Smuzhiyun 	static unsigned char set_pll_reg0[]      = { 0x38, 0x23 };
506*4882a593Smuzhiyun 	static unsigned char set_pll_reg7[]      = { 0x3f, 0x01 };
507*4882a593Smuzhiyun 	static unsigned char set_pll_reg10[]     = { 0x42, 0x61 };
508*4882a593Smuzhiyun 	static unsigned char set_gpio_reg0[]     = { 0x44, 0x0b };
509*4882a593Smuzhiyun 
510*4882a593Smuzhiyun 	tda8295_power(fe, 1);
511*4882a593Smuzhiyun 
512*4882a593Smuzhiyun 	tda8295_set_easy_mode(fe, 0);
513*4882a593Smuzhiyun 	tda8295_set_video_std(fe);
514*4882a593Smuzhiyun 
515*4882a593Smuzhiyun 	tuner_i2c_xfer_send(&priv->i2c_props, set_adc_ctl, 2);
516*4882a593Smuzhiyun 	tuner_i2c_xfer_send(&priv->i2c_props, set_adc_ctl2, 2);
517*4882a593Smuzhiyun 	tuner_i2c_xfer_send(&priv->i2c_props, set_pll_reg6, 2);
518*4882a593Smuzhiyun 	tuner_i2c_xfer_send(&priv->i2c_props, set_pll_reg0, 2);
519*4882a593Smuzhiyun 	tuner_i2c_xfer_send(&priv->i2c_props, set_pll_reg7, 2);
520*4882a593Smuzhiyun 	tuner_i2c_xfer_send(&priv->i2c_props, set_pll_reg10, 2);
521*4882a593Smuzhiyun 	tuner_i2c_xfer_send(&priv->i2c_props, set_gpio_reg0, 2);
522*4882a593Smuzhiyun 
523*4882a593Smuzhiyun 	tda8295_agc1_out(fe, 0);
524*4882a593Smuzhiyun 	tda8295_agc2_out(fe, 0);
525*4882a593Smuzhiyun }
526*4882a593Smuzhiyun 
tda8290_init_tuner(struct dvb_frontend * fe)527*4882a593Smuzhiyun static void tda8290_init_tuner(struct dvb_frontend *fe)
528*4882a593Smuzhiyun {
529*4882a593Smuzhiyun 	struct tda8290_priv *priv = fe->analog_demod_priv;
530*4882a593Smuzhiyun 	static unsigned char tda8275_init[]  =
531*4882a593Smuzhiyun 		{ 0x00, 0x00, 0x00, 0x40, 0xdC, 0x04, 0xAf,
532*4882a593Smuzhiyun 		  0x3F, 0x2A, 0x04, 0xFF, 0x00, 0x00, 0x40 };
533*4882a593Smuzhiyun 	static unsigned char tda8275a_init[] =
534*4882a593Smuzhiyun 		 { 0x00, 0x00, 0x00, 0x00, 0xdC, 0x05, 0x8b,
535*4882a593Smuzhiyun 		   0x0c, 0x04, 0x20, 0xFF, 0x00, 0x00, 0x4b };
536*4882a593Smuzhiyun 	struct i2c_msg msg = {.addr = priv->tda827x_addr, .flags=0,
537*4882a593Smuzhiyun 			      .buf=tda8275_init, .len = 14};
538*4882a593Smuzhiyun 	if (priv->ver & TDA8275A)
539*4882a593Smuzhiyun 		msg.buf = tda8275a_init;
540*4882a593Smuzhiyun 
541*4882a593Smuzhiyun 	if (fe->ops.analog_ops.i2c_gate_ctrl)
542*4882a593Smuzhiyun 		fe->ops.analog_ops.i2c_gate_ctrl(fe, 1);
543*4882a593Smuzhiyun 	i2c_transfer(priv->i2c_props.adap, &msg, 1);
544*4882a593Smuzhiyun 	if (fe->ops.analog_ops.i2c_gate_ctrl)
545*4882a593Smuzhiyun 		fe->ops.analog_ops.i2c_gate_ctrl(fe, 0);
546*4882a593Smuzhiyun }
547*4882a593Smuzhiyun 
548*4882a593Smuzhiyun /*---------------------------------------------------------------------*/
549*4882a593Smuzhiyun 
tda829x_release(struct dvb_frontend * fe)550*4882a593Smuzhiyun static void tda829x_release(struct dvb_frontend *fe)
551*4882a593Smuzhiyun {
552*4882a593Smuzhiyun 	struct tda8290_priv *priv = fe->analog_demod_priv;
553*4882a593Smuzhiyun 
554*4882a593Smuzhiyun 	/* only try to release the tuner if we've
555*4882a593Smuzhiyun 	 * attached it from within this module */
556*4882a593Smuzhiyun 	if (priv->ver & (TDA18271 | TDA8275 | TDA8275A))
557*4882a593Smuzhiyun 		if (fe->ops.tuner_ops.release)
558*4882a593Smuzhiyun 			fe->ops.tuner_ops.release(fe);
559*4882a593Smuzhiyun 
560*4882a593Smuzhiyun 	kfree(fe->analog_demod_priv);
561*4882a593Smuzhiyun 	fe->analog_demod_priv = NULL;
562*4882a593Smuzhiyun }
563*4882a593Smuzhiyun 
564*4882a593Smuzhiyun static struct tda18271_config tda829x_tda18271_config = {
565*4882a593Smuzhiyun 	.gate    = TDA18271_GATE_ANALOG,
566*4882a593Smuzhiyun };
567*4882a593Smuzhiyun 
tda829x_find_tuner(struct dvb_frontend * fe)568*4882a593Smuzhiyun static int tda829x_find_tuner(struct dvb_frontend *fe)
569*4882a593Smuzhiyun {
570*4882a593Smuzhiyun 	struct tda8290_priv *priv = fe->analog_demod_priv;
571*4882a593Smuzhiyun 	int i, ret, tuners_found;
572*4882a593Smuzhiyun 	u32 tuner_addrs;
573*4882a593Smuzhiyun 	u8 data;
574*4882a593Smuzhiyun 	struct i2c_msg msg = { .flags = I2C_M_RD, .buf = &data, .len = 1 };
575*4882a593Smuzhiyun 
576*4882a593Smuzhiyun 	if (fe->ops.analog_ops.i2c_gate_ctrl)
577*4882a593Smuzhiyun 		fe->ops.analog_ops.i2c_gate_ctrl(fe, 1);
578*4882a593Smuzhiyun 
579*4882a593Smuzhiyun 	/* probe for tuner chip */
580*4882a593Smuzhiyun 	tuners_found = 0;
581*4882a593Smuzhiyun 	tuner_addrs = 0;
582*4882a593Smuzhiyun 	for (i = 0x60; i <= 0x63; i++) {
583*4882a593Smuzhiyun 		msg.addr = i;
584*4882a593Smuzhiyun 		ret = i2c_transfer(priv->i2c_props.adap, &msg, 1);
585*4882a593Smuzhiyun 		if (ret == 1) {
586*4882a593Smuzhiyun 			tuners_found++;
587*4882a593Smuzhiyun 			tuner_addrs = (tuner_addrs << 8) + i;
588*4882a593Smuzhiyun 		}
589*4882a593Smuzhiyun 	}
590*4882a593Smuzhiyun 	/* if there is more than one tuner, we expect the right one is
591*4882a593Smuzhiyun 	   behind the bridge and we choose the highest address that doesn't
592*4882a593Smuzhiyun 	   give a response now
593*4882a593Smuzhiyun 	 */
594*4882a593Smuzhiyun 
595*4882a593Smuzhiyun 	if (fe->ops.analog_ops.i2c_gate_ctrl)
596*4882a593Smuzhiyun 		fe->ops.analog_ops.i2c_gate_ctrl(fe, 0);
597*4882a593Smuzhiyun 
598*4882a593Smuzhiyun 	if (tuners_found > 1)
599*4882a593Smuzhiyun 		for (i = 0; i < tuners_found; i++) {
600*4882a593Smuzhiyun 			msg.addr = tuner_addrs  & 0xff;
601*4882a593Smuzhiyun 			ret = i2c_transfer(priv->i2c_props.adap, &msg, 1);
602*4882a593Smuzhiyun 			if (ret == 1)
603*4882a593Smuzhiyun 				tuner_addrs = tuner_addrs >> 8;
604*4882a593Smuzhiyun 			else
605*4882a593Smuzhiyun 				break;
606*4882a593Smuzhiyun 		}
607*4882a593Smuzhiyun 
608*4882a593Smuzhiyun 	if (tuner_addrs == 0) {
609*4882a593Smuzhiyun 		tuner_addrs = 0x60;
610*4882a593Smuzhiyun 		tuner_info("could not clearly identify tuner address, defaulting to %x\n",
611*4882a593Smuzhiyun 			   tuner_addrs);
612*4882a593Smuzhiyun 	} else {
613*4882a593Smuzhiyun 		tuner_addrs = tuner_addrs & 0xff;
614*4882a593Smuzhiyun 		tuner_info("setting tuner address to %x\n", tuner_addrs);
615*4882a593Smuzhiyun 	}
616*4882a593Smuzhiyun 	priv->tda827x_addr = tuner_addrs;
617*4882a593Smuzhiyun 	msg.addr = tuner_addrs;
618*4882a593Smuzhiyun 
619*4882a593Smuzhiyun 	if (fe->ops.analog_ops.i2c_gate_ctrl)
620*4882a593Smuzhiyun 		fe->ops.analog_ops.i2c_gate_ctrl(fe, 1);
621*4882a593Smuzhiyun 	ret = i2c_transfer(priv->i2c_props.adap, &msg, 1);
622*4882a593Smuzhiyun 
623*4882a593Smuzhiyun 	if (ret != 1) {
624*4882a593Smuzhiyun 		tuner_warn("tuner access failed!\n");
625*4882a593Smuzhiyun 		if (fe->ops.analog_ops.i2c_gate_ctrl)
626*4882a593Smuzhiyun 			fe->ops.analog_ops.i2c_gate_ctrl(fe, 0);
627*4882a593Smuzhiyun 		return -EREMOTEIO;
628*4882a593Smuzhiyun 	}
629*4882a593Smuzhiyun 
630*4882a593Smuzhiyun 	if ((data == 0x83) || (data == 0x84)) {
631*4882a593Smuzhiyun 		priv->ver |= TDA18271;
632*4882a593Smuzhiyun 		tda829x_tda18271_config.config = priv->cfg.config;
633*4882a593Smuzhiyun 		tda829x_tda18271_config.std_map = priv->tda18271_std_map;
634*4882a593Smuzhiyun 		dvb_attach(tda18271_attach, fe, priv->tda827x_addr,
635*4882a593Smuzhiyun 			   priv->i2c_props.adap, &tda829x_tda18271_config);
636*4882a593Smuzhiyun 	} else {
637*4882a593Smuzhiyun 		if ((data & 0x3c) == 0)
638*4882a593Smuzhiyun 			priv->ver |= TDA8275;
639*4882a593Smuzhiyun 		else
640*4882a593Smuzhiyun 			priv->ver |= TDA8275A;
641*4882a593Smuzhiyun 
642*4882a593Smuzhiyun 		dvb_attach(tda827x_attach, fe, priv->tda827x_addr,
643*4882a593Smuzhiyun 			   priv->i2c_props.adap, &priv->cfg);
644*4882a593Smuzhiyun 		priv->cfg.switch_addr = priv->i2c_props.addr;
645*4882a593Smuzhiyun 	}
646*4882a593Smuzhiyun 	if (fe->ops.tuner_ops.init)
647*4882a593Smuzhiyun 		fe->ops.tuner_ops.init(fe);
648*4882a593Smuzhiyun 
649*4882a593Smuzhiyun 	if (fe->ops.tuner_ops.sleep)
650*4882a593Smuzhiyun 		fe->ops.tuner_ops.sleep(fe);
651*4882a593Smuzhiyun 
652*4882a593Smuzhiyun 	if (fe->ops.analog_ops.i2c_gate_ctrl)
653*4882a593Smuzhiyun 		fe->ops.analog_ops.i2c_gate_ctrl(fe, 0);
654*4882a593Smuzhiyun 
655*4882a593Smuzhiyun 	return 0;
656*4882a593Smuzhiyun }
657*4882a593Smuzhiyun 
tda8290_probe(struct tuner_i2c_props * i2c_props)658*4882a593Smuzhiyun static int tda8290_probe(struct tuner_i2c_props *i2c_props)
659*4882a593Smuzhiyun {
660*4882a593Smuzhiyun #define TDA8290_ID 0x89
661*4882a593Smuzhiyun 	u8 reg = 0x1f, id;
662*4882a593Smuzhiyun 	struct i2c_msg msg_read[] = {
663*4882a593Smuzhiyun 		{ .addr = i2c_props->addr, .flags = 0, .len = 1, .buf = &reg },
664*4882a593Smuzhiyun 		{ .addr = i2c_props->addr, .flags = I2C_M_RD, .len = 1, .buf = &id },
665*4882a593Smuzhiyun 	};
666*4882a593Smuzhiyun 
667*4882a593Smuzhiyun 	/* detect tda8290 */
668*4882a593Smuzhiyun 	if (i2c_transfer(i2c_props->adap, msg_read, 2) != 2) {
669*4882a593Smuzhiyun 		printk(KERN_WARNING "%s: couldn't read register 0x%02x\n",
670*4882a593Smuzhiyun 			       __func__, reg);
671*4882a593Smuzhiyun 		return -ENODEV;
672*4882a593Smuzhiyun 	}
673*4882a593Smuzhiyun 
674*4882a593Smuzhiyun 	if (id == TDA8290_ID) {
675*4882a593Smuzhiyun 		if (debug)
676*4882a593Smuzhiyun 			printk(KERN_DEBUG "%s: tda8290 detected @ %d-%04x\n",
677*4882a593Smuzhiyun 			       __func__, i2c_adapter_id(i2c_props->adap),
678*4882a593Smuzhiyun 			       i2c_props->addr);
679*4882a593Smuzhiyun 		return 0;
680*4882a593Smuzhiyun 	}
681*4882a593Smuzhiyun 	return -ENODEV;
682*4882a593Smuzhiyun }
683*4882a593Smuzhiyun 
tda8295_probe(struct tuner_i2c_props * i2c_props)684*4882a593Smuzhiyun static int tda8295_probe(struct tuner_i2c_props *i2c_props)
685*4882a593Smuzhiyun {
686*4882a593Smuzhiyun #define TDA8295_ID 0x8a
687*4882a593Smuzhiyun #define TDA8295C2_ID 0x8b
688*4882a593Smuzhiyun 	u8 reg = 0x2f, id;
689*4882a593Smuzhiyun 	struct i2c_msg msg_read[] = {
690*4882a593Smuzhiyun 		{ .addr = i2c_props->addr, .flags = 0, .len = 1, .buf = &reg },
691*4882a593Smuzhiyun 		{ .addr = i2c_props->addr, .flags = I2C_M_RD, .len = 1, .buf = &id },
692*4882a593Smuzhiyun 	};
693*4882a593Smuzhiyun 
694*4882a593Smuzhiyun 	/* detect tda8295 */
695*4882a593Smuzhiyun 	if (i2c_transfer(i2c_props->adap, msg_read, 2) != 2) {
696*4882a593Smuzhiyun 		printk(KERN_WARNING "%s: couldn't read register 0x%02x\n",
697*4882a593Smuzhiyun 			       __func__, reg);
698*4882a593Smuzhiyun 		return -ENODEV;
699*4882a593Smuzhiyun 	}
700*4882a593Smuzhiyun 
701*4882a593Smuzhiyun 	if ((id & 0xfe) == TDA8295_ID) {
702*4882a593Smuzhiyun 		if (debug)
703*4882a593Smuzhiyun 			printk(KERN_DEBUG "%s: %s detected @ %d-%04x\n",
704*4882a593Smuzhiyun 			       __func__, (id == TDA8295_ID) ?
705*4882a593Smuzhiyun 			       "tda8295c1" : "tda8295c2",
706*4882a593Smuzhiyun 			       i2c_adapter_id(i2c_props->adap),
707*4882a593Smuzhiyun 			       i2c_props->addr);
708*4882a593Smuzhiyun 		return 0;
709*4882a593Smuzhiyun 	}
710*4882a593Smuzhiyun 
711*4882a593Smuzhiyun 	return -ENODEV;
712*4882a593Smuzhiyun }
713*4882a593Smuzhiyun 
714*4882a593Smuzhiyun static const struct analog_demod_ops tda8290_ops = {
715*4882a593Smuzhiyun 	.set_params     = tda8290_set_params,
716*4882a593Smuzhiyun 	.has_signal     = tda8290_has_signal,
717*4882a593Smuzhiyun 	.standby        = tda8290_standby,
718*4882a593Smuzhiyun 	.release        = tda829x_release,
719*4882a593Smuzhiyun 	.i2c_gate_ctrl  = tda8290_i2c_bridge,
720*4882a593Smuzhiyun };
721*4882a593Smuzhiyun 
722*4882a593Smuzhiyun static const struct analog_demod_ops tda8295_ops = {
723*4882a593Smuzhiyun 	.set_params     = tda8295_set_params,
724*4882a593Smuzhiyun 	.has_signal     = tda8295_has_signal,
725*4882a593Smuzhiyun 	.standby        = tda8295_standby,
726*4882a593Smuzhiyun 	.release        = tda829x_release,
727*4882a593Smuzhiyun 	.i2c_gate_ctrl  = tda8295_i2c_bridge,
728*4882a593Smuzhiyun };
729*4882a593Smuzhiyun 
tda829x_attach(struct dvb_frontend * fe,struct i2c_adapter * i2c_adap,u8 i2c_addr,struct tda829x_config * cfg)730*4882a593Smuzhiyun struct dvb_frontend *tda829x_attach(struct dvb_frontend *fe,
731*4882a593Smuzhiyun 				    struct i2c_adapter *i2c_adap, u8 i2c_addr,
732*4882a593Smuzhiyun 				    struct tda829x_config *cfg)
733*4882a593Smuzhiyun {
734*4882a593Smuzhiyun 	struct tda8290_priv *priv = NULL;
735*4882a593Smuzhiyun 	char *name;
736*4882a593Smuzhiyun 
737*4882a593Smuzhiyun 	priv = kzalloc(sizeof(struct tda8290_priv), GFP_KERNEL);
738*4882a593Smuzhiyun 	if (priv == NULL)
739*4882a593Smuzhiyun 		return NULL;
740*4882a593Smuzhiyun 	fe->analog_demod_priv = priv;
741*4882a593Smuzhiyun 
742*4882a593Smuzhiyun 	priv->i2c_props.addr     = i2c_addr;
743*4882a593Smuzhiyun 	priv->i2c_props.adap     = i2c_adap;
744*4882a593Smuzhiyun 	priv->i2c_props.name     = "tda829x";
745*4882a593Smuzhiyun 	if (cfg) {
746*4882a593Smuzhiyun 		priv->cfg.config = cfg->lna_cfg;
747*4882a593Smuzhiyun 		priv->tda18271_std_map = cfg->tda18271_std_map;
748*4882a593Smuzhiyun 	}
749*4882a593Smuzhiyun 
750*4882a593Smuzhiyun 	if (tda8290_probe(&priv->i2c_props) == 0) {
751*4882a593Smuzhiyun 		priv->ver = TDA8290;
752*4882a593Smuzhiyun 		memcpy(&fe->ops.analog_ops, &tda8290_ops,
753*4882a593Smuzhiyun 		       sizeof(struct analog_demod_ops));
754*4882a593Smuzhiyun 	}
755*4882a593Smuzhiyun 
756*4882a593Smuzhiyun 	if (tda8295_probe(&priv->i2c_props) == 0) {
757*4882a593Smuzhiyun 		priv->ver = TDA8295;
758*4882a593Smuzhiyun 		memcpy(&fe->ops.analog_ops, &tda8295_ops,
759*4882a593Smuzhiyun 		       sizeof(struct analog_demod_ops));
760*4882a593Smuzhiyun 	}
761*4882a593Smuzhiyun 
762*4882a593Smuzhiyun 	if (cfg && cfg->no_i2c_gate)
763*4882a593Smuzhiyun 		fe->ops.analog_ops.i2c_gate_ctrl = NULL;
764*4882a593Smuzhiyun 
765*4882a593Smuzhiyun 	if (!(cfg) || (TDA829X_PROBE_TUNER == cfg->probe_tuner)) {
766*4882a593Smuzhiyun 		tda8295_power(fe, 1);
767*4882a593Smuzhiyun 		if (tda829x_find_tuner(fe) < 0)
768*4882a593Smuzhiyun 			goto fail;
769*4882a593Smuzhiyun 	}
770*4882a593Smuzhiyun 
771*4882a593Smuzhiyun 	switch (priv->ver) {
772*4882a593Smuzhiyun 	case TDA8290:
773*4882a593Smuzhiyun 		name = "tda8290";
774*4882a593Smuzhiyun 		break;
775*4882a593Smuzhiyun 	case TDA8295:
776*4882a593Smuzhiyun 		name = "tda8295";
777*4882a593Smuzhiyun 		break;
778*4882a593Smuzhiyun 	case TDA8290 | TDA8275:
779*4882a593Smuzhiyun 		name = "tda8290+75";
780*4882a593Smuzhiyun 		break;
781*4882a593Smuzhiyun 	case TDA8295 | TDA8275:
782*4882a593Smuzhiyun 		name = "tda8295+75";
783*4882a593Smuzhiyun 		break;
784*4882a593Smuzhiyun 	case TDA8290 | TDA8275A:
785*4882a593Smuzhiyun 		name = "tda8290+75a";
786*4882a593Smuzhiyun 		break;
787*4882a593Smuzhiyun 	case TDA8295 | TDA8275A:
788*4882a593Smuzhiyun 		name = "tda8295+75a";
789*4882a593Smuzhiyun 		break;
790*4882a593Smuzhiyun 	case TDA8290 | TDA18271:
791*4882a593Smuzhiyun 		name = "tda8290+18271";
792*4882a593Smuzhiyun 		break;
793*4882a593Smuzhiyun 	case TDA8295 | TDA18271:
794*4882a593Smuzhiyun 		name = "tda8295+18271";
795*4882a593Smuzhiyun 		break;
796*4882a593Smuzhiyun 	default:
797*4882a593Smuzhiyun 		goto fail;
798*4882a593Smuzhiyun 	}
799*4882a593Smuzhiyun 	tuner_info("type set to %s\n", name);
800*4882a593Smuzhiyun 
801*4882a593Smuzhiyun 	fe->ops.analog_ops.info.name = name;
802*4882a593Smuzhiyun 
803*4882a593Smuzhiyun 	if (priv->ver & TDA8290) {
804*4882a593Smuzhiyun 		if (priv->ver & (TDA8275 | TDA8275A))
805*4882a593Smuzhiyun 			tda8290_init_tuner(fe);
806*4882a593Smuzhiyun 		tda8290_init_if(fe);
807*4882a593Smuzhiyun 	} else if (priv->ver & TDA8295)
808*4882a593Smuzhiyun 		tda8295_init_if(fe);
809*4882a593Smuzhiyun 
810*4882a593Smuzhiyun 	return fe;
811*4882a593Smuzhiyun 
812*4882a593Smuzhiyun fail:
813*4882a593Smuzhiyun 	memset(&fe->ops.analog_ops, 0, sizeof(struct analog_demod_ops));
814*4882a593Smuzhiyun 
815*4882a593Smuzhiyun 	tda829x_release(fe);
816*4882a593Smuzhiyun 	return NULL;
817*4882a593Smuzhiyun }
818*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(tda829x_attach);
819*4882a593Smuzhiyun 
tda829x_probe(struct i2c_adapter * i2c_adap,u8 i2c_addr)820*4882a593Smuzhiyun int tda829x_probe(struct i2c_adapter *i2c_adap, u8 i2c_addr)
821*4882a593Smuzhiyun {
822*4882a593Smuzhiyun 	struct tuner_i2c_props i2c_props = {
823*4882a593Smuzhiyun 		.adap = i2c_adap,
824*4882a593Smuzhiyun 		.addr = i2c_addr,
825*4882a593Smuzhiyun 	};
826*4882a593Smuzhiyun 
827*4882a593Smuzhiyun 	static unsigned char soft_reset[]   = { 0x00, 0x00 };
828*4882a593Smuzhiyun 	static unsigned char easy_mode_b[]  = { 0x01, 0x02 };
829*4882a593Smuzhiyun 	static unsigned char easy_mode_g[]  = { 0x01, 0x04 };
830*4882a593Smuzhiyun 	static unsigned char restore_9886[] = { 0x00, 0xd6, 0x30 };
831*4882a593Smuzhiyun 	static unsigned char addr_dto_lsb = 0x07;
832*4882a593Smuzhiyun 	unsigned char data;
833*4882a593Smuzhiyun #define PROBE_BUFFER_SIZE 8
834*4882a593Smuzhiyun 	unsigned char buf[PROBE_BUFFER_SIZE];
835*4882a593Smuzhiyun 	int i;
836*4882a593Smuzhiyun 
837*4882a593Smuzhiyun 	/* rule out tda9887, which would return the same byte repeatedly */
838*4882a593Smuzhiyun 	tuner_i2c_xfer_send_recv(&i2c_props,
839*4882a593Smuzhiyun 				 soft_reset, 1, buf, PROBE_BUFFER_SIZE);
840*4882a593Smuzhiyun 	for (i = 1; i < PROBE_BUFFER_SIZE; i++) {
841*4882a593Smuzhiyun 		if (buf[i] != buf[0])
842*4882a593Smuzhiyun 			break;
843*4882a593Smuzhiyun 	}
844*4882a593Smuzhiyun 
845*4882a593Smuzhiyun 	/* all bytes are equal, not a tda829x - probably a tda9887 */
846*4882a593Smuzhiyun 	if (i == PROBE_BUFFER_SIZE)
847*4882a593Smuzhiyun 		return -ENODEV;
848*4882a593Smuzhiyun 
849*4882a593Smuzhiyun 	if ((tda8290_probe(&i2c_props) == 0) ||
850*4882a593Smuzhiyun 	    (tda8295_probe(&i2c_props) == 0))
851*4882a593Smuzhiyun 		return 0;
852*4882a593Smuzhiyun 
853*4882a593Smuzhiyun 	/* fall back to old probing method */
854*4882a593Smuzhiyun 	tuner_i2c_xfer_send(&i2c_props, easy_mode_b, 2);
855*4882a593Smuzhiyun 	tuner_i2c_xfer_send(&i2c_props, soft_reset, 2);
856*4882a593Smuzhiyun 	tuner_i2c_xfer_send_recv(&i2c_props, &addr_dto_lsb, 1, &data, 1);
857*4882a593Smuzhiyun 	if (data == 0) {
858*4882a593Smuzhiyun 		tuner_i2c_xfer_send(&i2c_props, easy_mode_g, 2);
859*4882a593Smuzhiyun 		tuner_i2c_xfer_send(&i2c_props, soft_reset, 2);
860*4882a593Smuzhiyun 		tuner_i2c_xfer_send_recv(&i2c_props,
861*4882a593Smuzhiyun 					 &addr_dto_lsb, 1, &data, 1);
862*4882a593Smuzhiyun 		if (data == 0x7b) {
863*4882a593Smuzhiyun 			return 0;
864*4882a593Smuzhiyun 		}
865*4882a593Smuzhiyun 	}
866*4882a593Smuzhiyun 	tuner_i2c_xfer_send(&i2c_props, restore_9886, 3);
867*4882a593Smuzhiyun 	return -ENODEV;
868*4882a593Smuzhiyun }
869*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(tda829x_probe);
870*4882a593Smuzhiyun 
871*4882a593Smuzhiyun MODULE_DESCRIPTION("Philips/NXP TDA8290/TDA8295 analog IF demodulator driver");
872*4882a593Smuzhiyun MODULE_AUTHOR("Gerd Knorr, Hartmut Hackmann, Michael Krufky");
873*4882a593Smuzhiyun MODULE_LICENSE("GPL");
874