]> bbs.cooldavid.org Git - net-next-2.6.git/blame - drivers/media/common/tuners/tda9887.c
include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit...
[net-next-2.6.git] / drivers / media / common / tuners / tda9887.c
CommitLineData
1da177e4 1#include <linux/module.h>
1da177e4
LT
2#include <linux/kernel.h>
3#include <linux/i2c.h>
4#include <linux/types.h>
1da177e4
LT
5#include <linux/init.h>
6#include <linux/errno.h>
1da177e4 7#include <linux/delay.h>
f894dfd7 8#include <linux/videodev2.h>
5e453dc7 9#include <media/v4l2-common.h>
1da177e4 10#include <media/tuner.h>
ab166050 11#include "tuner-i2c.h"
31c9584c 12#include "tda9887.h"
1da177e4 13
674434c6 14
1da177e4
LT
15/* Chips:
16 TDA9885 (PAL, NTSC)
17 TDA9886 (PAL, SECAM, NTSC)
18 TDA9887 (PAL, SECAM, NTSC, FM Radio)
19
15396236 20 Used as part of several tuners
1da177e4
LT
21*/
22
790ba18e
MK
23static int debug;
24module_param(debug, int, 0644);
25MODULE_PARM_DESC(debug, "enable verbose debug messages");
26
ac8b63b3
MK
27static DEFINE_MUTEX(tda9887_list_mutex);
28static LIST_HEAD(hybrid_tuner_instance_list);
29
b2083199 30struct tda9887_priv {
db8a6956 31 struct tuner_i2c_props i2c_props;
ac8b63b3 32 struct list_head hybrid_tuner_instance_list;
db8a6956 33
b2083199 34 unsigned char data[4];
710401b8 35 unsigned int config;
91c9d4a1
MK
36 unsigned int mode;
37 unsigned int audmode;
38 v4l2_std_id std;
b2083199 39};
1da177e4
LT
40
41/* ---------------------------------------------------------------------- */
42
43#define UNSET (-1U)
1da177e4
LT
44
45struct tvnorm {
46 v4l2_std_id std;
47 char *name;
48 unsigned char b;
49 unsigned char c;
50 unsigned char e;
51};
52
1da177e4
LT
53/* ---------------------------------------------------------------------- */
54
55//
56// TDA defines
57//
58
59//// first reg (b)
60#define cVideoTrapBypassOFF 0x00 // bit b0
61#define cVideoTrapBypassON 0x01 // bit b0
62
63#define cAutoMuteFmInactive 0x00 // bit b1
64#define cAutoMuteFmActive 0x02 // bit b1
65
66#define cIntercarrier 0x00 // bit b2
67#define cQSS 0x04 // bit b2
68
69#define cPositiveAmTV 0x00 // bit b3:4
70#define cFmRadio 0x08 // bit b3:4
71#define cNegativeFmTV 0x10 // bit b3:4
72
73
74#define cForcedMuteAudioON 0x20 // bit b5
75#define cForcedMuteAudioOFF 0x00 // bit b5
76
77#define cOutputPort1Active 0x00 // bit b6
78#define cOutputPort1Inactive 0x40 // bit b6
79
80#define cOutputPort2Active 0x00 // bit b7
81#define cOutputPort2Inactive 0x80 // bit b7
82
83
84//// second reg (c)
85#define cDeemphasisOFF 0x00 // bit c5
86#define cDeemphasisON 0x20 // bit c5
87
88#define cDeemphasis75 0x00 // bit c6
89#define cDeemphasis50 0x40 // bit c6
90
91#define cAudioGain0 0x00 // bit c7
92#define cAudioGain6 0x80 // bit c7
93
f98c55ea 94#define cTopMask 0x1f // bit c0:4
f5b0142a 95#define cTopDefault 0x10 // bit c0:4
1da177e4
LT
96
97//// third reg (e)
98#define cAudioIF_4_5 0x00 // bit e0:1
99#define cAudioIF_5_5 0x01 // bit e0:1
100#define cAudioIF_6_0 0x02 // bit e0:1
101#define cAudioIF_6_5 0x03 // bit e0:1
102
103
5e082f15
TP
104#define cVideoIFMask 0x1c // bit e2:4
105/* Video IF selection in TV Mode (bit B3=0) */
1da177e4
LT
106#define cVideoIF_58_75 0x00 // bit e2:4
107#define cVideoIF_45_75 0x04 // bit e2:4
108#define cVideoIF_38_90 0x08 // bit e2:4
109#define cVideoIF_38_00 0x0C // bit e2:4
110#define cVideoIF_33_90 0x10 // bit e2:4
111#define cVideoIF_33_40 0x14 // bit e2:4
112#define cRadioIF_45_75 0x18 // bit e2:4
113#define cRadioIF_38_90 0x1C // bit e2:4
114
5e082f15
TP
115/* IF1 selection in Radio Mode (bit B3=1) */
116#define cRadioIF_33_30 0x00 // bit e2,4 (also 0x10,0x14)
117#define cRadioIF_41_30 0x04 // bit e2,4
118
119/* Output of AFC pin in radio mode when bit E7=1 */
120#define cRadioAGC_SIF 0x00 // bit e3
121#define cRadioAGC_FM 0x08 // bit e3
1da177e4
LT
122
123#define cTunerGainNormal 0x00 // bit e5
124#define cTunerGainLow 0x20 // bit e5
125
126#define cGating_18 0x00 // bit e6
127#define cGating_36 0x40 // bit e6
128
129#define cAgcOutON 0x80 // bit e7
130#define cAgcOutOFF 0x00 // bit e7
131
132/* ---------------------------------------------------------------------- */
133
134static struct tvnorm tvnorms[] = {
135 {
f98c55ea
HV
136 .std = V4L2_STD_PAL_BG | V4L2_STD_PAL_H | V4L2_STD_PAL_N,
137 .name = "PAL-BGHN",
1da177e4
LT
138 .b = ( cNegativeFmTV |
139 cQSS ),
140 .c = ( cDeemphasisON |
f98c55ea 141 cDeemphasis50 |
f5b0142a 142 cTopDefault),
f98c55ea
HV
143 .e = ( cGating_36 |
144 cAudioIF_5_5 |
1da177e4
LT
145 cVideoIF_38_90 ),
146 },{
147 .std = V4L2_STD_PAL_I,
148 .name = "PAL-I",
149 .b = ( cNegativeFmTV |
150 cQSS ),
151 .c = ( cDeemphasisON |
f98c55ea 152 cDeemphasis50 |
f5b0142a 153 cTopDefault),
f98c55ea
HV
154 .e = ( cGating_36 |
155 cAudioIF_6_0 |
1da177e4
LT
156 cVideoIF_38_90 ),
157 },{
158 .std = V4L2_STD_PAL_DK,
159 .name = "PAL-DK",
160 .b = ( cNegativeFmTV |
161 cQSS ),
162 .c = ( cDeemphasisON |
f98c55ea 163 cDeemphasis50 |
f5b0142a 164 cTopDefault),
f98c55ea
HV
165 .e = ( cGating_36 |
166 cAudioIF_6_5 |
167 cVideoIF_38_90 ),
1da177e4 168 },{
f98c55ea
HV
169 .std = V4L2_STD_PAL_M | V4L2_STD_PAL_Nc,
170 .name = "PAL-M/Nc",
1da177e4
LT
171 .b = ( cNegativeFmTV |
172 cQSS ),
173 .c = ( cDeemphasisON |
f98c55ea 174 cDeemphasis75 |
f5b0142a 175 cTopDefault),
f98c55ea
HV
176 .e = ( cGating_36 |
177 cAudioIF_4_5 |
1da177e4 178 cVideoIF_45_75 ),
f98c55ea
HV
179 },{
180 .std = V4L2_STD_SECAM_B | V4L2_STD_SECAM_G | V4L2_STD_SECAM_H,
181 .name = "SECAM-BGH",
b84ca9f2 182 .b = ( cNegativeFmTV |
f98c55ea 183 cQSS ),
f5b0142a 184 .c = ( cTopDefault),
b84ca9f2 185 .e = ( cAudioIF_5_5 |
f98c55ea 186 cVideoIF_38_90 ),
1da177e4
LT
187 },{
188 .std = V4L2_STD_SECAM_L,
189 .name = "SECAM-L",
190 .b = ( cPositiveAmTV |
191 cQSS ),
f5b0142a 192 .c = ( cTopDefault),
3375c398 193 .e = ( cGating_36 |
5f7591c0 194 cAudioIF_6_5 |
1da177e4 195 cVideoIF_38_90 ),
f3c5987a
MCC
196 },{
197 .std = V4L2_STD_SECAM_LC,
198 .name = "SECAM-L'",
199 .b = ( cOutputPort2Inactive |
200 cPositiveAmTV |
201 cQSS ),
f5b0142a 202 .c = ( cTopDefault),
f3c5987a
MCC
203 .e = ( cGating_36 |
204 cAudioIF_6_5 |
205 cVideoIF_33_90 ),
1da177e4
LT
206 },{
207 .std = V4L2_STD_SECAM_DK,
208 .name = "SECAM-DK",
209 .b = ( cNegativeFmTV |
210 cQSS ),
211 .c = ( cDeemphasisON |
f98c55ea 212 cDeemphasis50 |
f5b0142a 213 cTopDefault),
f98c55ea
HV
214 .e = ( cGating_36 |
215 cAudioIF_6_5 |
216 cVideoIF_38_90 ),
1da177e4 217 },{
0dfd812d 218 .std = V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_KR,
1da177e4
LT
219 .name = "NTSC-M",
220 .b = ( cNegativeFmTV |
221 cQSS ),
222 .c = ( cDeemphasisON |
f98c55ea 223 cDeemphasis75 |
f5b0142a 224 cTopDefault),
1da177e4
LT
225 .e = ( cGating_36 |
226 cAudioIF_4_5 |
227 cVideoIF_45_75 ),
228 },{
229 .std = V4L2_STD_NTSC_M_JP,
f98c55ea 230 .name = "NTSC-M-JP",
1da177e4
LT
231 .b = ( cNegativeFmTV |
232 cQSS ),
233 .c = ( cDeemphasisON |
f98c55ea 234 cDeemphasis50 |
f5b0142a 235 cTopDefault),
1da177e4
LT
236 .e = ( cGating_36 |
237 cAudioIF_4_5 |
238 cVideoIF_58_75 ),
239 }
240};
241
56fc08ca
MCC
242static struct tvnorm radio_stereo = {
243 .name = "Radio Stereo",
244 .b = ( cFmRadio |
245 cQSS ),
246 .c = ( cDeemphasisOFF |
f98c55ea 247 cAudioGain6 |
f5b0142a 248 cTopDefault),
f98c55ea
HV
249 .e = ( cTunerGainLow |
250 cAudioIF_5_5 |
56fc08ca
MCC
251 cRadioIF_38_90 ),
252};
253
254static struct tvnorm radio_mono = {
255 .name = "Radio Mono",
1da177e4
LT
256 .b = ( cFmRadio |
257 cQSS ),
258 .c = ( cDeemphasisON |
f98c55ea 259 cDeemphasis75 |
f5b0142a 260 cTopDefault),
f98c55ea
HV
261 .e = ( cTunerGainLow |
262 cAudioIF_5_5 |
1da177e4
LT
263 cRadioIF_38_90 ),
264};
265
266/* ---------------------------------------------------------------------- */
267
4e9154b8 268static void dump_read_message(struct dvb_frontend *fe, unsigned char *buf)
1da177e4 269{
4e9154b8
MK
270 struct tda9887_priv *priv = fe->analog_demod_priv;
271
1da177e4
LT
272 static char *afc[16] = {
273 "- 12.5 kHz",
274 "- 37.5 kHz",
275 "- 62.5 kHz",
276 "- 87.5 kHz",
277 "-112.5 kHz",
278 "-137.5 kHz",
279 "-162.5 kHz",
280 "-187.5 kHz [min]",
281 "+187.5 kHz [max]",
282 "+162.5 kHz",
283 "+137.5 kHz",
284 "+112.5 kHz",
285 "+ 87.5 kHz",
286 "+ 62.5 kHz",
287 "+ 37.5 kHz",
288 "+ 12.5 kHz",
289 };
790ba18e
MK
290 tuner_info("read: 0x%2x\n", buf[0]);
291 tuner_info(" after power on : %s\n", (buf[0] & 0x01) ? "yes" : "no");
292 tuner_info(" afc : %s\n", afc[(buf[0] >> 1) & 0x0f]);
293 tuner_info(" fmif level : %s\n", (buf[0] & 0x20) ? "high" : "low");
294 tuner_info(" afc window : %s\n", (buf[0] & 0x40) ? "in" : "out");
295 tuner_info(" vfi level : %s\n", (buf[0] & 0x80) ? "high" : "low");
1da177e4
LT
296}
297
4e9154b8 298static void dump_write_message(struct dvb_frontend *fe, unsigned char *buf)
1da177e4 299{
4e9154b8
MK
300 struct tda9887_priv *priv = fe->analog_demod_priv;
301
1da177e4
LT
302 static char *sound[4] = {
303 "AM/TV",
304 "FM/radio",
305 "FM/TV",
306 "FM/radio"
307 };
308 static char *adjust[32] = {
309 "-16", "-15", "-14", "-13", "-12", "-11", "-10", "-9",
310 "-8", "-7", "-6", "-5", "-4", "-3", "-2", "-1",
311 "0", "+1", "+2", "+3", "+4", "+5", "+6", "+7",
312 "+8", "+9", "+10", "+11", "+12", "+13", "+14", "+15"
313 };
314 static char *deemph[4] = {
315 "no", "no", "75", "50"
316 };
317 static char *carrier[4] = {
318 "4.5 MHz",
319 "5.5 MHz",
320 "6.0 MHz",
321 "6.5 MHz / AM"
322 };
323 static char *vif[8] = {
324 "58.75 MHz",
325 "45.75 MHz",
326 "38.9 MHz",
327 "38.0 MHz",
328 "33.9 MHz",
329 "33.4 MHz",
330 "45.75 MHz + pin13",
331 "38.9 MHz + pin13",
332 };
333 static char *rif[4] = {
334 "44 MHz",
335 "52 MHz",
336 "52 MHz",
337 "44 MHz",
338 };
339
790ba18e
MK
340 tuner_info("write: byte B 0x%02x\n", buf[1]);
341 tuner_info(" B0 video mode : %s\n",
342 (buf[1] & 0x01) ? "video trap" : "sound trap");
343 tuner_info(" B1 auto mute fm : %s\n",
344 (buf[1] & 0x02) ? "yes" : "no");
345 tuner_info(" B2 carrier mode : %s\n",
346 (buf[1] & 0x04) ? "QSS" : "Intercarrier");
347 tuner_info(" B3-4 tv sound/radio : %s\n",
348 sound[(buf[1] & 0x18) >> 3]);
349 tuner_info(" B5 force mute audio: %s\n",
350 (buf[1] & 0x20) ? "yes" : "no");
351 tuner_info(" B6 output port 1 : %s\n",
352 (buf[1] & 0x40) ? "high (inactive)" : "low (active)");
353 tuner_info(" B7 output port 2 : %s\n",
354 (buf[1] & 0x80) ? "high (inactive)" : "low (active)");
355
356 tuner_info("write: byte C 0x%02x\n", buf[2]);
357 tuner_info(" C0-4 top adjustment : %s dB\n",
358 adjust[buf[2] & 0x1f]);
359 tuner_info(" C5-6 de-emphasis : %s\n",
360 deemph[(buf[2] & 0x60) >> 5]);
361 tuner_info(" C7 audio gain : %s\n",
362 (buf[2] & 0x80) ? "-6" : "0");
363
364 tuner_info("write: byte E 0x%02x\n", buf[3]);
365 tuner_info(" E0-1 sound carrier : %s\n",
366 carrier[(buf[3] & 0x03)]);
367 tuner_info(" E6 l pll gating : %s\n",
368 (buf[3] & 0x40) ? "36" : "13");
1da177e4
LT
369
370 if (buf[1] & 0x08) {
371 /* radio */
790ba18e
MK
372 tuner_info(" E2-4 video if : %s\n",
373 rif[(buf[3] & 0x0c) >> 2]);
374 tuner_info(" E7 vif agc output : %s\n",
375 (buf[3] & 0x80)
376 ? ((buf[3] & 0x10) ? "fm-agc radio" :
377 "sif-agc radio")
378 : "fm radio carrier afc");
1da177e4
LT
379 } else {
380 /* video */
790ba18e
MK
381 tuner_info(" E2-4 video if : %s\n",
382 vif[(buf[3] & 0x1c) >> 2]);
383 tuner_info(" E5 tuner gain : %s\n",
384 (buf[3] & 0x80)
385 ? ((buf[3] & 0x20) ? "external" : "normal")
386 : ((buf[3] & 0x20) ? "minimum" : "normal"));
387 tuner_info(" E7 vif agc output : %s\n",
388 (buf[3] & 0x80) ? ((buf[3] & 0x20)
389 ? "pin3 port, pin22 vif agc out"
390 : "pin22 port, pin3 vif acg ext in")
391 : "pin3+pin22 port");
1da177e4 392 }
790ba18e 393 tuner_info("--\n");
1da177e4
LT
394}
395
396/* ---------------------------------------------------------------------- */
397
4e9154b8 398static int tda9887_set_tvnorm(struct dvb_frontend *fe)
1da177e4 399{
4e9154b8 400 struct tda9887_priv *priv = fe->analog_demod_priv;
1da177e4 401 struct tvnorm *norm = NULL;
4e9154b8 402 char *buf = priv->data;
1da177e4
LT
403 int i;
404
91c9d4a1
MK
405 if (priv->mode == V4L2_TUNER_RADIO) {
406 if (priv->audmode == V4L2_TUNER_MODE_MONO)
56fc08ca
MCC
407 norm = &radio_mono;
408 else
586b0cab 409 norm = &radio_stereo;
1da177e4
LT
410 } else {
411 for (i = 0; i < ARRAY_SIZE(tvnorms); i++) {
91c9d4a1 412 if (tvnorms[i].std & priv->std) {
1da177e4
LT
413 norm = tvnorms+i;
414 break;
415 }
416 }
417 }
418 if (NULL == norm) {
790ba18e 419 tuner_dbg("Unsupported tvnorm entry - audio muted\n");
1da177e4
LT
420 return -1;
421 }
422
790ba18e 423 tuner_dbg("configure for: %s\n", norm->name);
1da177e4
LT
424 buf[1] = norm->b;
425 buf[2] = norm->c;
426 buf[3] = norm->e;
427 return 0;
428}
429
430static unsigned int port1 = UNSET;
431static unsigned int port2 = UNSET;
432static unsigned int qss = UNSET;
f98c55ea
HV
433static unsigned int adjust = UNSET;
434
1da177e4
LT
435module_param(port1, int, 0644);
436module_param(port2, int, 0644);
437module_param(qss, int, 0644);
438module_param(adjust, int, 0644);
439
4e9154b8 440static int tda9887_set_insmod(struct dvb_frontend *fe)
1da177e4 441{
4e9154b8
MK
442 struct tda9887_priv *priv = fe->analog_demod_priv;
443 char *buf = priv->data;
444
1da177e4
LT
445 if (UNSET != port1) {
446 if (port1)
447 buf[1] |= cOutputPort1Inactive;
448 else
449 buf[1] &= ~cOutputPort1Inactive;
450 }
451 if (UNSET != port2) {
452 if (port2)
453 buf[1] |= cOutputPort2Inactive;
454 else
455 buf[1] &= ~cOutputPort2Inactive;
456 }
457
458 if (UNSET != qss) {
459 if (qss)
460 buf[1] |= cQSS;
461 else
462 buf[1] &= ~cQSS;
463 }
464
f14a2972 465 if (adjust < 0x20) {
f98c55ea 466 buf[2] &= ~cTopMask;
1da177e4 467 buf[2] |= adjust;
f98c55ea 468 }
1da177e4
LT
469 return 0;
470}
471
710401b8 472static int tda9887_do_config(struct dvb_frontend *fe)
1da177e4 473{
4e9154b8 474 struct tda9887_priv *priv = fe->analog_demod_priv;
4e9154b8
MK
475 char *buf = priv->data;
476
710401b8 477 if (priv->config & TDA9887_PORT1_ACTIVE)
1da177e4 478 buf[1] &= ~cOutputPort1Inactive;
710401b8 479 if (priv->config & TDA9887_PORT1_INACTIVE)
1da177e4 480 buf[1] |= cOutputPort1Inactive;
710401b8 481 if (priv->config & TDA9887_PORT2_ACTIVE)
1da177e4 482 buf[1] &= ~cOutputPort2Inactive;
710401b8 483 if (priv->config & TDA9887_PORT2_INACTIVE)
1da177e4
LT
484 buf[1] |= cOutputPort2Inactive;
485
710401b8 486 if (priv->config & TDA9887_QSS)
1da177e4 487 buf[1] |= cQSS;
710401b8 488 if (priv->config & TDA9887_INTERCARRIER)
1da177e4
LT
489 buf[1] &= ~cQSS;
490
710401b8 491 if (priv->config & TDA9887_AUTOMUTE)
1da177e4 492 buf[1] |= cAutoMuteFmActive;
710401b8 493 if (priv->config & TDA9887_DEEMPHASIS_MASK) {
1da177e4 494 buf[2] &= ~0x60;
710401b8 495 switch (priv->config & TDA9887_DEEMPHASIS_MASK) {
1da177e4
LT
496 case TDA9887_DEEMPHASIS_NONE:
497 buf[2] |= cDeemphasisOFF;
498 break;
499 case TDA9887_DEEMPHASIS_50:
500 buf[2] |= cDeemphasisON | cDeemphasis50;
501 break;
502 case TDA9887_DEEMPHASIS_75:
503 buf[2] |= cDeemphasisON | cDeemphasis75;
504 break;
505 }
506 }
710401b8 507 if (priv->config & TDA9887_TOP_SET) {
f98c55ea 508 buf[2] &= ~cTopMask;
710401b8 509 buf[2] |= (priv->config >> 8) & cTopMask;
f98c55ea 510 }
710401b8 511 if ((priv->config & TDA9887_INTERCARRIER_NTSC) &&
91c9d4a1 512 (priv->std & V4L2_STD_NTSC))
3ae1adc6 513 buf[1] &= ~cQSS;
710401b8 514 if (priv->config & TDA9887_GATING_18)
d7304dee 515 buf[3] &= ~cGating_36;
cefccc80 516
91c9d4a1 517 if (priv->mode == V4L2_TUNER_RADIO) {
710401b8 518 if (priv->config & TDA9887_RIF_41_3) {
5e082f15
TP
519 buf[3] &= ~cVideoIFMask;
520 buf[3] |= cRadioIF_41_30;
521 }
710401b8 522 if (priv->config & TDA9887_GAIN_NORMAL)
5e082f15 523 buf[3] &= ~cTunerGainLow;
cefccc80
MCC
524 }
525
1da177e4
LT
526 return 0;
527}
528
529/* ---------------------------------------------------------------------- */
530
4e9154b8 531static int tda9887_status(struct dvb_frontend *fe)
1da177e4 532{
4e9154b8 533 struct tda9887_priv *priv = fe->analog_demod_priv;
1da177e4
LT
534 unsigned char buf[1];
535 int rc;
536
537 memset(buf,0,sizeof(buf));
db8a6956 538 if (1 != (rc = tuner_i2c_xfer_recv(&priv->i2c_props,buf,1)))
790ba18e 539 tuner_info("i2c i/o error: rc == %d (should be 1)\n", rc);
4e9154b8 540 dump_read_message(fe, buf);
1da177e4
LT
541 return 0;
542}
543
4e9154b8 544static void tda9887_configure(struct dvb_frontend *fe)
1da177e4 545{
4e9154b8 546 struct tda9887_priv *priv = fe->analog_demod_priv;
1da177e4
LT
547 int rc;
548
b2083199 549 memset(priv->data,0,sizeof(priv->data));
4e9154b8 550 tda9887_set_tvnorm(fe);
56fc08ca 551
f98c55ea
HV
552 /* A note on the port settings:
553 These settings tend to depend on the specifics of the board.
554 By default they are set to inactive (bit value 1) by this driver,
555 overwriting any changes made by the tvnorm. This means that it
556 is the responsibility of the module using the tda9887 to set
557 these values in case of changes in the tvnorm.
558 In many cases port 2 should be made active (0) when selecting
559 SECAM-L, and port 2 should remain inactive (1) for SECAM-L'.
560
561 For the other standards the tda9887 application note says that
562 the ports should be set to active (0), but, again, that may
563 differ depending on the precise hardware configuration.
564 */
b2083199
MK
565 priv->data[1] |= cOutputPort1Inactive;
566 priv->data[1] |= cOutputPort2Inactive;
56fc08ca 567
710401b8 568 tda9887_do_config(fe);
4e9154b8 569 tda9887_set_insmod(fe);
1da177e4 570
91c9d4a1 571 if (priv->mode == T_STANDBY)
b2083199 572 priv->data[1] |= cForcedMuteAudioON;
793cf9e6 573
790ba18e
MK
574 tuner_dbg("writing: b=0x%02x c=0x%02x e=0x%02x\n",
575 priv->data[1], priv->data[2], priv->data[3]);
576 if (debug > 1)
4e9154b8 577 dump_write_message(fe, priv->data);
1da177e4 578
db8a6956 579 if (4 != (rc = tuner_i2c_xfer_send(&priv->i2c_props,priv->data,4)))
790ba18e 580 tuner_info("i2c i/o error: rc == %d (should be 4)\n", rc);
1da177e4 581
790ba18e 582 if (debug > 2) {
1da177e4 583 msleep_interruptible(1000);
4e9154b8 584 tda9887_status(fe);
1da177e4 585 }
1da177e4
LT
586}
587
588/* ---------------------------------------------------------------------- */
589
4e9154b8 590static void tda9887_tuner_status(struct dvb_frontend *fe)
1da177e4 591{
4e9154b8 592 struct tda9887_priv *priv = fe->analog_demod_priv;
790ba18e
MK
593 tuner_info("Data bytes: b=0x%02x c=0x%02x e=0x%02x\n",
594 priv->data[1], priv->data[2], priv->data[3]);
1da177e4
LT
595}
596
4e9154b8 597static int tda9887_get_afc(struct dvb_frontend *fe)
1da177e4 598{
4e9154b8 599 struct tda9887_priv *priv = fe->analog_demod_priv;
15396236
MCC
600 static int AFC_BITS_2_kHz[] = {
601 -12500, -37500, -62500, -97500,
602 -112500, -137500, -162500, -187500,
603 187500, 162500, 137500, 112500,
604 97500 , 62500, 37500 , 12500
605 };
606 int afc=0;
607 __u8 reg = 0;
1da177e4 608
db8a6956 609 if (1 == tuner_i2c_xfer_recv(&priv->i2c_props,&reg,1))
15396236 610 afc = AFC_BITS_2_kHz[(reg>>1)&0x0f];
1da177e4 611
15396236 612 return afc;
1da177e4
LT
613}
614
4e9154b8 615static void tda9887_standby(struct dvb_frontend *fe)
1da177e4 616{
91c9d4a1
MK
617 struct tda9887_priv *priv = fe->analog_demod_priv;
618
619 priv->mode = T_STANDBY;
620
4e9154b8 621 tda9887_configure(fe);
1da177e4
LT
622}
623
c7919d52
MK
624static void tda9887_set_params(struct dvb_frontend *fe,
625 struct analog_parameters *params)
1da177e4 626{
91c9d4a1
MK
627 struct tda9887_priv *priv = fe->analog_demod_priv;
628
629 priv->mode = params->mode;
630 priv->audmode = params->audmode;
631 priv->std = params->std;
4e9154b8 632 tda9887_configure(fe);
1da177e4
LT
633}
634
710401b8
MK
635static int tda9887_set_config(struct dvb_frontend *fe, void *priv_cfg)
636{
637 struct tda9887_priv *priv = fe->analog_demod_priv;
638
639 priv->config = *(unsigned int *)priv_cfg;
640 tda9887_configure(fe);
641
642 return 0;
643}
644
4e9154b8 645static void tda9887_release(struct dvb_frontend *fe)
024cf530 646{
ac8b63b3
MK
647 struct tda9887_priv *priv = fe->analog_demod_priv;
648
649 mutex_lock(&tda9887_list_mutex);
650
651 if (priv)
652 hybrid_tuner_release_state(priv);
653
654 mutex_unlock(&tda9887_list_mutex);
655
4e9154b8 656 fe->analog_demod_priv = NULL;
024cf530
MK
657}
658
bc3e5c7f 659static struct analog_demod_ops tda9887_ops = {
a55db8cd 660 .info = {
0f2ce983 661 .name = "tda9887",
a55db8cd 662 },
c7919d52 663 .set_params = tda9887_set_params,
9af596eb
MK
664 .standby = tda9887_standby,
665 .tuner_status = tda9887_tuner_status,
666 .get_afc = tda9887_get_afc,
667 .release = tda9887_release,
710401b8 668 .set_config = tda9887_set_config,
9af596eb
MK
669};
670
8ca4083b
MK
671struct dvb_frontend *tda9887_attach(struct dvb_frontend *fe,
672 struct i2c_adapter *i2c_adap,
673 u8 i2c_addr)
1da177e4 674{
b2083199 675 struct tda9887_priv *priv = NULL;
ac8b63b3 676 int instance;
1da177e4 677
ac8b63b3 678 mutex_lock(&tda9887_list_mutex);
b2083199 679
ac8b63b3
MK
680 instance = hybrid_tuner_request_state(struct tda9887_priv, priv,
681 hybrid_tuner_instance_list,
682 i2c_adap, i2c_addr, "tda9887");
683 switch (instance) {
684 case 0:
685 mutex_unlock(&tda9887_list_mutex);
686 return NULL;
ac8b63b3
MK
687 case 1:
688 fe->analog_demod_priv = priv;
689 priv->mode = T_STANDBY;
690 tuner_info("tda988[5/6/7] found\n");
691 break;
692 default:
693 fe->analog_demod_priv = priv;
694 break;
695 }
db8a6956 696
ac8b63b3 697 mutex_unlock(&tda9887_list_mutex);
1da177e4 698
bc3e5c7f
MK
699 memcpy(&fe->ops.analog_ops, &tda9887_ops,
700 sizeof(struct analog_demod_ops));
1da177e4 701
8ca4083b 702 return fe;
1da177e4 703}
31c9584c 704EXPORT_SYMBOL_GPL(tda9887_attach);
1da177e4 705
5ef4730d
MK
706MODULE_LICENSE("GPL");
707
1da177e4
LT
708/*
709 * Overrides for Emacs so that we follow Linus's tabbing style.
710 * ---------------------------------------------------------------------------
711 * Local variables:
712 * c-basic-offset: 8
713 * End:
714 */