Showing error 1633

User: Jiri Slaby
Error type: Invalid Pointer Dereference
Error type description: A pointer which is invalid is being dereferenced
File location: drivers/media/common/tuners/tda9887.c
Line in file: 691
Project: Linux Kernel
Project version: 2.6.28
Tools: Smatch (1.59)
Entered: 2013-09-10 07:54:05 UTC


Source:

  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/videodev2.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
 24static int debug;
 25module_param(debug, int, 0644);
 26MODULE_PARM_DESC(debug, "enable verbose debug messages");
 27
 28static DEFINE_MUTEX(tda9887_list_mutex);
 29static LIST_HEAD(hybrid_tuner_instance_list);
 30
 31struct tda9887_priv {
 32        struct tuner_i2c_props i2c_props;
 33        struct list_head hybrid_tuner_instance_list;
 34
 35        unsigned char            data[4];
 36        unsigned int       config;
 37        unsigned int       mode;
 38        unsigned int       audmode;
 39        v4l2_std_id        std;
 40};
 41
 42/* ---------------------------------------------------------------------- */
 43
 44#define UNSET       (-1U)
 45
 46struct tvnorm {
 47        v4l2_std_id       std;
 48        char              *name;
 49        unsigned char     b;
 50        unsigned char     c;
 51        unsigned char     e;
 52};
 53
 54/* ---------------------------------------------------------------------- */
 55
 56//
 57// TDA defines
 58//
 59
 60//// first reg (b)
 61#define cVideoTrapBypassOFF     0x00    // bit b0
 62#define cVideoTrapBypassON      0x01    // bit b0
 63
 64#define cAutoMuteFmInactive     0x00    // bit b1
 65#define cAutoMuteFmActive       0x02    // bit b1
 66
 67#define cIntercarrier           0x00    // bit b2
 68#define cQSS                    0x04    // bit b2
 69
 70#define cPositiveAmTV           0x00    // bit b3:4
 71#define cFmRadio                0x08    // bit b3:4
 72#define cNegativeFmTV           0x10    // bit b3:4
 73
 74
 75#define cForcedMuteAudioON      0x20    // bit b5
 76#define cForcedMuteAudioOFF     0x00    // bit b5
 77
 78#define cOutputPort1Active      0x00    // bit b6
 79#define cOutputPort1Inactive    0x40    // bit b6
 80
 81#define cOutputPort2Active      0x00    // bit b7
 82#define cOutputPort2Inactive    0x80    // bit b7
 83
 84
 85//// second reg (c)
 86#define cDeemphasisOFF          0x00    // bit c5
 87#define cDeemphasisON           0x20    // bit c5
 88
 89#define cDeemphasis75           0x00    // bit c6
 90#define cDeemphasis50           0x40    // bit c6
 91
 92#define cAudioGain0             0x00    // bit c7
 93#define cAudioGain6             0x80    // bit c7
 94
 95#define cTopMask                0x1f    // bit c0:4
 96#define cTopDefault                0x10         // bit c0:4
 97
 98//// third reg (e)
 99#define cAudioIF_4_5             0x00    // bit e0:1
100#define cAudioIF_5_5             0x01    // bit e0:1
101#define cAudioIF_6_0             0x02    // bit e0:1
102#define cAudioIF_6_5             0x03    // bit e0:1
103
104
105#define cVideoIFMask                0x1c        // bit e2:4
106/* Video IF selection in TV Mode (bit B3=0) */
107#define cVideoIF_58_75           0x00    // bit e2:4
108#define cVideoIF_45_75           0x04    // bit e2:4
109#define cVideoIF_38_90           0x08    // bit e2:4
110#define cVideoIF_38_00           0x0C    // bit e2:4
111#define cVideoIF_33_90           0x10    // bit e2:4
112#define cVideoIF_33_40           0x14    // bit e2:4
113#define cRadioIF_45_75           0x18    // bit e2:4
114#define cRadioIF_38_90           0x1C    // bit e2:4
115
116/* IF1 selection in Radio Mode (bit B3=1) */
117#define cRadioIF_33_30                0x00        // bit e2,4 (also 0x10,0x14)
118#define cRadioIF_41_30                0x04        // bit e2,4
119
120/* Output of AFC pin in radio mode when bit E7=1 */
121#define cRadioAGC_SIF                0x00        // bit e3
122#define cRadioAGC_FM                0x08        // bit e3
123
124#define cTunerGainNormal         0x00    // bit e5
125#define cTunerGainLow            0x20    // bit e5
126
127#define cGating_18               0x00    // bit e6
128#define cGating_36               0x40    // bit e6
129
130#define cAgcOutON                0x80    // bit e7
131#define cAgcOutOFF               0x00    // bit e7
132
133/* ---------------------------------------------------------------------- */
134
135static struct tvnorm tvnorms[] = {
136        {
137                .std   = V4L2_STD_PAL_BG | V4L2_STD_PAL_H | V4L2_STD_PAL_N,
138                .name  = "PAL-BGHN",
139                .b     = ( cNegativeFmTV  |
140                           cQSS           ),
141                .c     = ( cDeemphasisON  |
142                           cDeemphasis50  |
143                           cTopDefault),
144                .e     = ( cGating_36     |
145                           cAudioIF_5_5   |
146                           cVideoIF_38_90 ),
147        },{
148                .std   = V4L2_STD_PAL_I,
149                .name  = "PAL-I",
150                .b     = ( cNegativeFmTV  |
151                           cQSS           ),
152                .c     = ( cDeemphasisON  |
153                           cDeemphasis50  |
154                           cTopDefault),
155                .e     = ( cGating_36     |
156                           cAudioIF_6_0   |
157                           cVideoIF_38_90 ),
158        },{
159                .std   = V4L2_STD_PAL_DK,
160                .name  = "PAL-DK",
161                .b     = ( cNegativeFmTV  |
162                           cQSS           ),
163                .c     = ( cDeemphasisON  |
164                           cDeemphasis50  |
165                           cTopDefault),
166                .e     = ( cGating_36     |
167                           cAudioIF_6_5   |
168                           cVideoIF_38_90 ),
169        },{
170                .std   = V4L2_STD_PAL_M | V4L2_STD_PAL_Nc,
171                .name  = "PAL-M/Nc",
172                .b     = ( cNegativeFmTV  |
173                           cQSS           ),
174                .c     = ( cDeemphasisON  |
175                           cDeemphasis75  |
176                           cTopDefault),
177                .e     = ( cGating_36     |
178                           cAudioIF_4_5   |
179                           cVideoIF_45_75 ),
180        },{
181                .std   = V4L2_STD_SECAM_B | V4L2_STD_SECAM_G | V4L2_STD_SECAM_H,
182                .name  = "SECAM-BGH",
183                .b     = ( cPositiveAmTV  |
184                           cQSS           ),
185                .c     = ( cTopDefault),
186                .e     = ( cGating_36          |
187                           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
244static 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
256static 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
270static 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
300static 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
400static 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
432static unsigned int port1  = UNSET;
433static unsigned int port2  = UNSET;
434static unsigned int qss    = UNSET;
435static unsigned int adjust = UNSET;
436
437module_param(port1, int, 0644);
438module_param(port2, int, 0644);
439module_param(qss, int, 0644);
440module_param(adjust, int, 0644);
441
442static 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 >= 0x00 && adjust < 0x20) {
468                buf[2] &= ~cTopMask;
469                buf[2] |= adjust;
470        }
471        return 0;
472}
473
474static 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
533static 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
546static 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->mode == T_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
592static 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
599static 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
617static void tda9887_standby(struct dvb_frontend *fe)
618{
619        struct tda9887_priv *priv = fe->analog_demod_priv;
620
621        priv->mode = T_STANDBY;
622
623        tda9887_configure(fe);
624}
625
626static 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->mode    = params->mode;
632        priv->audmode = params->audmode;
633        priv->std     = params->std;
634        tda9887_configure(fe);
635}
636
637static int tda9887_set_config(struct dvb_frontend *fe, void *priv_cfg)
638{
639        struct tda9887_priv *priv = fe->analog_demod_priv;
640
641        priv->config = *(unsigned int *)priv_cfg;
642        tda9887_configure(fe);
643
644        return 0;
645}
646
647static void tda9887_release(struct dvb_frontend *fe)
648{
649        struct tda9887_priv *priv = fe->analog_demod_priv;
650
651        mutex_lock(&tda9887_list_mutex);
652
653        if (priv)
654                hybrid_tuner_release_state(priv);
655
656        mutex_unlock(&tda9887_list_mutex);
657
658        fe->analog_demod_priv = NULL;
659}
660
661static struct analog_demod_ops tda9887_ops = {
662        .info                = {
663                .name        = "tda9887",
664        },
665        .set_params     = tda9887_set_params,
666        .standby        = tda9887_standby,
667        .tuner_status   = tda9887_tuner_status,
668        .get_afc        = tda9887_get_afc,
669        .release        = tda9887_release,
670        .set_config     = tda9887_set_config,
671};
672
673struct dvb_frontend *tda9887_attach(struct dvb_frontend *fe,
674                                    struct i2c_adapter *i2c_adap,
675                                    u8 i2c_addr)
676{
677        struct tda9887_priv *priv = NULL;
678        int instance;
679
680        mutex_lock(&tda9887_list_mutex);
681
682        instance = hybrid_tuner_request_state(struct tda9887_priv, priv,
683                                              hybrid_tuner_instance_list,
684                                              i2c_adap, i2c_addr, "tda9887");
685        switch (instance) {
686        case 0:
687                mutex_unlock(&tda9887_list_mutex);
688                return NULL;
689        case 1:
690                fe->analog_demod_priv = priv;
691                priv->mode = T_STANDBY;
692                tuner_info("tda988[5/6/7] found\n");
693                break;
694        default:
695                fe->analog_demod_priv = priv;
696                break;
697        }
698
699        mutex_unlock(&tda9887_list_mutex);
700
701        memcpy(&fe->ops.analog_ops, &tda9887_ops,
702               sizeof(struct analog_demod_ops));
703
704        return fe;
705}
706EXPORT_SYMBOL_GPL(tda9887_attach);
707
708MODULE_LICENSE("GPL");
709
710/*
711 * Overrides for Emacs so that we follow Linus's tabbing style.
712 * ---------------------------------------------------------------------------
713 * Local variables:
714 * c-basic-offset: 8
715 * End:
716 */