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