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 = ® },
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 = ® },
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