Merge git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6
[pandora-kernel.git] / drivers / media / video / tda9887.c
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/slab.h>
8 #include <linux/delay.h>
9 #include <linux/videodev.h>
10 #include <media/v4l2-common.h>
11 #include <media/tuner.h>
12 #include "tuner-i2c.h"
13 #include "tda9887.h"
14
15
16 /* Chips:
17    TDA9885 (PAL, NTSC)
18    TDA9886 (PAL, SECAM, NTSC)
19    TDA9887 (PAL, SECAM, NTSC, FM Radio)
20
21    Used as part of several tuners
22 */
23
24 static int debug;
25 module_param(debug, int, 0644);
26 MODULE_PARM_DESC(debug, "enable verbose debug messages");
27
28 #define PREFIX "tda9887"
29
30 struct tda9887_priv {
31         struct tuner_i2c_props i2c_props;
32
33         unsigned char      data[4];
34         unsigned int       config;
35         unsigned int       mode;
36         unsigned int       audmode;
37         v4l2_std_id        std;
38 };
39
40 /* ---------------------------------------------------------------------- */
41
42 #define UNSET       (-1U)
43
44 struct tvnorm {
45         v4l2_std_id       std;
46         char              *name;
47         unsigned char     b;
48         unsigned char     c;
49         unsigned char     e;
50 };
51
52 /* ---------------------------------------------------------------------- */
53
54 //
55 // TDA defines
56 //
57
58 //// first reg (b)
59 #define cVideoTrapBypassOFF     0x00    // bit b0
60 #define cVideoTrapBypassON      0x01    // bit b0
61
62 #define cAutoMuteFmInactive     0x00    // bit b1
63 #define cAutoMuteFmActive       0x02    // bit b1
64
65 #define cIntercarrier           0x00    // bit b2
66 #define cQSS                    0x04    // bit b2
67
68 #define cPositiveAmTV           0x00    // bit b3:4
69 #define cFmRadio                0x08    // bit b3:4
70 #define cNegativeFmTV           0x10    // bit b3:4
71
72
73 #define cForcedMuteAudioON      0x20    // bit b5
74 #define cForcedMuteAudioOFF     0x00    // bit b5
75
76 #define cOutputPort1Active      0x00    // bit b6
77 #define cOutputPort1Inactive    0x40    // bit b6
78
79 #define cOutputPort2Active      0x00    // bit b7
80 #define cOutputPort2Inactive    0x80    // bit b7
81
82
83 //// second reg (c)
84 #define cDeemphasisOFF          0x00    // bit c5
85 #define cDeemphasisON           0x20    // bit c5
86
87 #define cDeemphasis75           0x00    // bit c6
88 #define cDeemphasis50           0x40    // bit c6
89
90 #define cAudioGain0             0x00    // bit c7
91 #define cAudioGain6             0x80    // bit c7
92
93 #define cTopMask                0x1f    // bit c0:4
94 #define cTopDefault             0x10    // bit c0:4
95
96 //// third reg (e)
97 #define cAudioIF_4_5             0x00    // bit e0:1
98 #define cAudioIF_5_5             0x01    // bit e0:1
99 #define cAudioIF_6_0             0x02    // bit e0:1
100 #define cAudioIF_6_5             0x03    // bit e0:1
101
102
103 #define cVideoIFMask            0x1c    // bit e2:4
104 /* Video IF selection in TV Mode (bit B3=0) */
105 #define cVideoIF_58_75           0x00    // bit e2:4
106 #define cVideoIF_45_75           0x04    // bit e2:4
107 #define cVideoIF_38_90           0x08    // bit e2:4
108 #define cVideoIF_38_00           0x0C    // bit e2:4
109 #define cVideoIF_33_90           0x10    // bit e2:4
110 #define cVideoIF_33_40           0x14    // bit e2:4
111 #define cRadioIF_45_75           0x18    // bit e2:4
112 #define cRadioIF_38_90           0x1C    // bit e2:4
113
114 /* IF1 selection in Radio Mode (bit B3=1) */
115 #define cRadioIF_33_30          0x00    // bit e2,4 (also 0x10,0x14)
116 #define cRadioIF_41_30          0x04    // bit e2,4
117
118 /* Output of AFC pin in radio mode when bit E7=1 */
119 #define cRadioAGC_SIF           0x00    // bit e3
120 #define cRadioAGC_FM            0x08    // bit e3
121
122 #define cTunerGainNormal         0x00    // bit e5
123 #define cTunerGainLow            0x20    // bit e5
124
125 #define cGating_18               0x00    // bit e6
126 #define cGating_36               0x40    // bit e6
127
128 #define cAgcOutON                0x80    // bit e7
129 #define cAgcOutOFF               0x00    // bit e7
130
131 /* ---------------------------------------------------------------------- */
132
133 static struct tvnorm tvnorms[] = {
134         {
135                 .std   = V4L2_STD_PAL_BG | V4L2_STD_PAL_H | V4L2_STD_PAL_N,
136                 .name  = "PAL-BGHN",
137                 .b     = ( cNegativeFmTV  |
138                            cQSS           ),
139                 .c     = ( cDeemphasisON  |
140                            cDeemphasis50  |
141                            cTopDefault),
142                 .e     = ( cGating_36     |
143                            cAudioIF_5_5   |
144                            cVideoIF_38_90 ),
145         },{
146                 .std   = V4L2_STD_PAL_I,
147                 .name  = "PAL-I",
148                 .b     = ( cNegativeFmTV  |
149                            cQSS           ),
150                 .c     = ( cDeemphasisON  |
151                            cDeemphasis50  |
152                            cTopDefault),
153                 .e     = ( cGating_36     |
154                            cAudioIF_6_0   |
155                            cVideoIF_38_90 ),
156         },{
157                 .std   = V4L2_STD_PAL_DK,
158                 .name  = "PAL-DK",
159                 .b     = ( cNegativeFmTV  |
160                            cQSS           ),
161                 .c     = ( cDeemphasisON  |
162                            cDeemphasis50  |
163                            cTopDefault),
164                 .e     = ( cGating_36     |
165                            cAudioIF_6_5   |
166                            cVideoIF_38_90 ),
167         },{
168                 .std   = V4L2_STD_PAL_M | V4L2_STD_PAL_Nc,
169                 .name  = "PAL-M/Nc",
170                 .b     = ( cNegativeFmTV  |
171                            cQSS           ),
172                 .c     = ( cDeemphasisON  |
173                            cDeemphasis75  |
174                            cTopDefault),
175                 .e     = ( cGating_36     |
176                            cAudioIF_4_5   |
177                            cVideoIF_45_75 ),
178         },{
179                 .std   = V4L2_STD_SECAM_B | V4L2_STD_SECAM_G | V4L2_STD_SECAM_H,
180                 .name  = "SECAM-BGH",
181                 .b     = ( cPositiveAmTV  |
182                            cQSS           ),
183                 .c     = ( cTopDefault),
184                 .e     = ( cGating_36     |
185                            cAudioIF_5_5   |
186                            cVideoIF_38_90 ),
187         },{
188                 .std   = V4L2_STD_SECAM_L,
189                 .name  = "SECAM-L",
190                 .b     = ( cPositiveAmTV  |
191                            cQSS           ),
192                 .c     = ( cTopDefault),
193                 .e     = ( cGating_36     |
194                            cAudioIF_6_5   |
195                            cVideoIF_38_90 ),
196         },{
197                 .std   = V4L2_STD_SECAM_LC,
198                 .name  = "SECAM-L'",
199                 .b     = ( cOutputPort2Inactive |
200                            cPositiveAmTV  |
201                            cQSS           ),
202                 .c     = ( cTopDefault),
203                 .e     = ( cGating_36     |
204                            cAudioIF_6_5   |
205                            cVideoIF_33_90 ),
206         },{
207                 .std   = V4L2_STD_SECAM_DK,
208                 .name  = "SECAM-DK",
209                 .b     = ( cNegativeFmTV  |
210                            cQSS           ),
211                 .c     = ( cDeemphasisON  |
212                            cDeemphasis50  |
213                            cTopDefault),
214                 .e     = ( cGating_36     |
215                            cAudioIF_6_5   |
216                            cVideoIF_38_90 ),
217         },{
218                 .std   = V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_KR,
219                 .name  = "NTSC-M",
220                 .b     = ( cNegativeFmTV  |
221                            cQSS           ),
222                 .c     = ( cDeemphasisON  |
223                            cDeemphasis75  |
224                            cTopDefault),
225                 .e     = ( cGating_36     |
226                            cAudioIF_4_5   |
227                            cVideoIF_45_75 ),
228         },{
229                 .std   = V4L2_STD_NTSC_M_JP,
230                 .name  = "NTSC-M-JP",
231                 .b     = ( cNegativeFmTV  |
232                            cQSS           ),
233                 .c     = ( cDeemphasisON  |
234                            cDeemphasis50  |
235                            cTopDefault),
236                 .e     = ( cGating_36     |
237                            cAudioIF_4_5   |
238                            cVideoIF_58_75 ),
239         }
240 };
241
242 static struct tvnorm radio_stereo = {
243         .name = "Radio Stereo",
244         .b    = ( cFmRadio       |
245                   cQSS           ),
246         .c    = ( cDeemphasisOFF |
247                   cAudioGain6    |
248                   cTopDefault),
249         .e    = ( cTunerGainLow  |
250                   cAudioIF_5_5   |
251                   cRadioIF_38_90 ),
252 };
253
254 static struct tvnorm radio_mono = {
255         .name = "Radio Mono",
256         .b    = ( cFmRadio       |
257                   cQSS           ),
258         .c    = ( cDeemphasisON  |
259                   cDeemphasis75  |
260                   cTopDefault),
261         .e    = ( cTunerGainLow  |
262                   cAudioIF_5_5   |
263                   cRadioIF_38_90 ),
264 };
265
266 /* ---------------------------------------------------------------------- */
267
268 static void dump_read_message(struct dvb_frontend *fe, unsigned char *buf)
269 {
270         struct tda9887_priv *priv = fe->analog_demod_priv;
271
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         };
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");
296 }
297
298 static void dump_write_message(struct dvb_frontend *fe, unsigned char *buf)
299 {
300         struct tda9887_priv *priv = fe->analog_demod_priv;
301
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
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");
369
370         if (buf[1] & 0x08) {
371                 /* radio */
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");
379         } else {
380                 /* video */
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");
392         }
393         tuner_info("--\n");
394 }
395
396 /* ---------------------------------------------------------------------- */
397
398 static int tda9887_set_tvnorm(struct dvb_frontend *fe)
399 {
400         struct tda9887_priv *priv = fe->analog_demod_priv;
401         struct tvnorm *norm = NULL;
402         char *buf = priv->data;
403         int i;
404
405         if (priv->mode == V4L2_TUNER_RADIO) {
406                 if (priv->audmode == V4L2_TUNER_MODE_MONO)
407                         norm = &radio_mono;
408                 else
409                         norm = &radio_stereo;
410         } else {
411                 for (i = 0; i < ARRAY_SIZE(tvnorms); i++) {
412                         if (tvnorms[i].std & priv->std) {
413                                 norm = tvnorms+i;
414                                 break;
415                         }
416                 }
417         }
418         if (NULL == norm) {
419                 tuner_dbg("Unsupported tvnorm entry - audio muted\n");
420                 return -1;
421         }
422
423         tuner_dbg("configure for: %s\n", norm->name);
424         buf[1] = norm->b;
425         buf[2] = norm->c;
426         buf[3] = norm->e;
427         return 0;
428 }
429
430 static unsigned int port1  = UNSET;
431 static unsigned int port2  = UNSET;
432 static unsigned int qss    = UNSET;
433 static unsigned int adjust = UNSET;
434
435 module_param(port1, int, 0644);
436 module_param(port2, int, 0644);
437 module_param(qss, int, 0644);
438 module_param(adjust, int, 0644);
439
440 static int tda9887_set_insmod(struct dvb_frontend *fe)
441 {
442         struct tda9887_priv *priv = fe->analog_demod_priv;
443         char *buf = priv->data;
444
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
465         if (adjust >= 0x00 && adjust < 0x20) {
466                 buf[2] &= ~cTopMask;
467                 buf[2] |= adjust;
468         }
469         return 0;
470 }
471
472 static int tda9887_do_config(struct dvb_frontend *fe)
473 {
474         struct tda9887_priv *priv = fe->analog_demod_priv;
475         char *buf = priv->data;
476
477         if (priv->config & TDA9887_PORT1_ACTIVE)
478                 buf[1] &= ~cOutputPort1Inactive;
479         if (priv->config & TDA9887_PORT1_INACTIVE)
480                 buf[1] |= cOutputPort1Inactive;
481         if (priv->config & TDA9887_PORT2_ACTIVE)
482                 buf[1] &= ~cOutputPort2Inactive;
483         if (priv->config & TDA9887_PORT2_INACTIVE)
484                 buf[1] |= cOutputPort2Inactive;
485
486         if (priv->config & TDA9887_QSS)
487                 buf[1] |= cQSS;
488         if (priv->config & TDA9887_INTERCARRIER)
489                 buf[1] &= ~cQSS;
490
491         if (priv->config & TDA9887_AUTOMUTE)
492                 buf[1] |= cAutoMuteFmActive;
493         if (priv->config & TDA9887_DEEMPHASIS_MASK) {
494                 buf[2] &= ~0x60;
495                 switch (priv->config & TDA9887_DEEMPHASIS_MASK) {
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         }
507         if (priv->config & TDA9887_TOP_SET) {
508                 buf[2] &= ~cTopMask;
509                 buf[2] |= (priv->config >> 8) & cTopMask;
510         }
511         if ((priv->config & TDA9887_INTERCARRIER_NTSC) &&
512             (priv->std & V4L2_STD_NTSC))
513                 buf[1] &= ~cQSS;
514         if (priv->config & TDA9887_GATING_18)
515                 buf[3] &= ~cGating_36;
516
517         if (priv->mode == V4L2_TUNER_RADIO) {
518                 if (priv->config & TDA9887_RIF_41_3) {
519                         buf[3] &= ~cVideoIFMask;
520                         buf[3] |= cRadioIF_41_30;
521                 }
522                 if (priv->config & TDA9887_GAIN_NORMAL)
523                         buf[3] &= ~cTunerGainLow;
524         }
525
526         return 0;
527 }
528
529 /* ---------------------------------------------------------------------- */
530
531 static int tda9887_status(struct dvb_frontend *fe)
532 {
533         struct tda9887_priv *priv = fe->analog_demod_priv;
534         unsigned char buf[1];
535         int rc;
536
537         memset(buf,0,sizeof(buf));
538         if (1 != (rc = tuner_i2c_xfer_recv(&priv->i2c_props,buf,1)))
539                 tuner_info("i2c i/o error: rc == %d (should be 1)\n", rc);
540         dump_read_message(fe, buf);
541         return 0;
542 }
543
544 static void tda9887_configure(struct dvb_frontend *fe)
545 {
546         struct tda9887_priv *priv = fe->analog_demod_priv;
547         int rc;
548
549         memset(priv->data,0,sizeof(priv->data));
550         tda9887_set_tvnorm(fe);
551
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          */
565         priv->data[1] |= cOutputPort1Inactive;
566         priv->data[1] |= cOutputPort2Inactive;
567
568         tda9887_do_config(fe);
569         tda9887_set_insmod(fe);
570
571         if (priv->mode == T_STANDBY)
572                 priv->data[1] |= cForcedMuteAudioON;
573
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)
577                 dump_write_message(fe, priv->data);
578
579         if (4 != (rc = tuner_i2c_xfer_send(&priv->i2c_props,priv->data,4)))
580                 tuner_info("i2c i/o error: rc == %d (should be 4)\n", rc);
581
582         if (debug > 2) {
583                 msleep_interruptible(1000);
584                 tda9887_status(fe);
585         }
586 }
587
588 /* ---------------------------------------------------------------------- */
589
590 static void tda9887_tuner_status(struct dvb_frontend *fe)
591 {
592         struct tda9887_priv *priv = fe->analog_demod_priv;
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]);
595 }
596
597 static int tda9887_get_afc(struct dvb_frontend *fe)
598 {
599         struct tda9887_priv *priv = fe->analog_demod_priv;
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;
608
609         if (1 == tuner_i2c_xfer_recv(&priv->i2c_props,&reg,1))
610                 afc = AFC_BITS_2_kHz[(reg>>1)&0x0f];
611
612         return afc;
613 }
614
615 static void tda9887_standby(struct dvb_frontend *fe)
616 {
617         struct tda9887_priv *priv = fe->analog_demod_priv;
618
619         priv->mode = T_STANDBY;
620
621         tda9887_configure(fe);
622 }
623
624 static void tda9887_set_params(struct dvb_frontend *fe,
625                                struct analog_parameters *params)
626 {
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;
632         tda9887_configure(fe);
633 }
634
635 static 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
645 static void tda9887_release(struct dvb_frontend *fe)
646 {
647         kfree(fe->analog_demod_priv);
648         fe->analog_demod_priv = NULL;
649 }
650
651 static struct analog_demod_ops tda9887_ops = {
652         .info           = {
653                 .name   = "tda9887",
654         },
655         .set_params     = tda9887_set_params,
656         .standby        = tda9887_standby,
657         .tuner_status   = tda9887_tuner_status,
658         .get_afc        = tda9887_get_afc,
659         .release        = tda9887_release,
660         .set_config     = tda9887_set_config,
661 };
662
663 struct dvb_frontend *tda9887_attach(struct dvb_frontend *fe,
664                                     struct i2c_adapter *i2c_adap,
665                                     u8 i2c_addr)
666 {
667         struct tda9887_priv *priv = NULL;
668
669         priv = kzalloc(sizeof(struct tda9887_priv), GFP_KERNEL);
670         if (priv == NULL)
671                 return NULL;
672         fe->analog_demod_priv = priv;
673
674         priv->i2c_props.addr = i2c_addr;
675         priv->i2c_props.adap = i2c_adap;
676         priv->mode = T_STANDBY;
677
678         tuner_info("tda988[5/6/7] found\n");
679
680         memcpy(&fe->ops.analog_ops, &tda9887_ops,
681                sizeof(struct analog_demod_ops));
682
683         return fe;
684 }
685 EXPORT_SYMBOL_GPL(tda9887_attach);
686
687 MODULE_LICENSE("GPL");
688
689 /*
690  * Overrides for Emacs so that we follow Linus's tabbing style.
691  * ---------------------------------------------------------------------------
692  * Local variables:
693  * c-basic-offset: 8
694  * End:
695  */