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