0001
0002 #include <linux/module.h>
0003 #include <linux/kernel.h>
0004 #include <linux/i2c.h>
0005 #include <linux/types.h>
0006 #include <linux/init.h>
0007 #include <linux/errno.h>
0008 #include <linux/delay.h>
0009 #include <linux/videodev2.h>
0010 #include <media/v4l2-common.h>
0011 #include <media/tuner.h>
0012 #include "tuner-i2c.h"
0013 #include "tda9887.h"
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024 static int debug;
0025 module_param(debug, int, 0644);
0026 MODULE_PARM_DESC(debug, "enable verbose debug messages");
0027
0028 static DEFINE_MUTEX(tda9887_list_mutex);
0029 static LIST_HEAD(hybrid_tuner_instance_list);
0030
0031 struct tda9887_priv {
0032 struct tuner_i2c_props i2c_props;
0033 struct list_head hybrid_tuner_instance_list;
0034
0035 unsigned char data[4];
0036 unsigned int config;
0037 unsigned int mode;
0038 unsigned int audmode;
0039 v4l2_std_id std;
0040
0041 bool standby;
0042 };
0043
0044
0045
0046 #define UNSET (-1U)
0047
0048 struct tvnorm {
0049 v4l2_std_id std;
0050 char *name;
0051 unsigned char b;
0052 unsigned char c;
0053 unsigned char e;
0054 };
0055
0056
0057
0058
0059
0060
0061
0062
0063 #define cVideoTrapBypassOFF 0x00
0064 #define cVideoTrapBypassON 0x01
0065
0066 #define cAutoMuteFmInactive 0x00
0067 #define cAutoMuteFmActive 0x02
0068
0069 #define cIntercarrier 0x00
0070 #define cQSS 0x04
0071
0072 #define cPositiveAmTV 0x00
0073 #define cFmRadio 0x08
0074 #define cNegativeFmTV 0x10
0075
0076
0077 #define cForcedMuteAudioON 0x20
0078 #define cForcedMuteAudioOFF 0x00
0079
0080 #define cOutputPort1Active 0x00
0081 #define cOutputPort1Inactive 0x40
0082
0083 #define cOutputPort2Active 0x00
0084 #define cOutputPort2Inactive 0x80
0085
0086
0087
0088 #define cDeemphasisOFF 0x00
0089 #define cDeemphasisON 0x20
0090
0091 #define cDeemphasis75 0x00
0092 #define cDeemphasis50 0x40
0093
0094 #define cAudioGain0 0x00
0095 #define cAudioGain6 0x80
0096
0097 #define cTopMask 0x1f
0098 #define cTopDefault 0x10
0099
0100
0101 #define cAudioIF_4_5 0x00
0102 #define cAudioIF_5_5 0x01
0103 #define cAudioIF_6_0 0x02
0104 #define cAudioIF_6_5 0x03
0105
0106
0107 #define cVideoIFMask 0x1c
0108
0109 #define cVideoIF_58_75 0x00
0110 #define cVideoIF_45_75 0x04
0111 #define cVideoIF_38_90 0x08
0112 #define cVideoIF_38_00 0x0C
0113 #define cVideoIF_33_90 0x10
0114 #define cVideoIF_33_40 0x14
0115 #define cRadioIF_45_75 0x18
0116 #define cRadioIF_38_90 0x1C
0117
0118
0119 #define cRadioIF_33_30 0x00
0120 #define cRadioIF_41_30 0x04
0121
0122
0123 #define cRadioAGC_SIF 0x00
0124 #define cRadioAGC_FM 0x08
0125
0126 #define cTunerGainNormal 0x00
0127 #define cTunerGainLow 0x20
0128
0129 #define cGating_18 0x00
0130 #define cGating_36 0x40
0131
0132 #define cAgcOutON 0x80
0133 #define cAgcOutOFF 0x00
0134
0135
0136
0137 static struct tvnorm tvnorms[] = {
0138 {
0139 .std = V4L2_STD_PAL_BG | V4L2_STD_PAL_H | V4L2_STD_PAL_N,
0140 .name = "PAL-BGHN",
0141 .b = ( cNegativeFmTV |
0142 cQSS ),
0143 .c = ( cDeemphasisON |
0144 cDeemphasis50 |
0145 cTopDefault),
0146 .e = ( cGating_36 |
0147 cAudioIF_5_5 |
0148 cVideoIF_38_90 ),
0149 },{
0150 .std = V4L2_STD_PAL_I,
0151 .name = "PAL-I",
0152 .b = ( cNegativeFmTV |
0153 cQSS ),
0154 .c = ( cDeemphasisON |
0155 cDeemphasis50 |
0156 cTopDefault),
0157 .e = ( cGating_36 |
0158 cAudioIF_6_0 |
0159 cVideoIF_38_90 ),
0160 },{
0161 .std = V4L2_STD_PAL_DK,
0162 .name = "PAL-DK",
0163 .b = ( cNegativeFmTV |
0164 cQSS ),
0165 .c = ( cDeemphasisON |
0166 cDeemphasis50 |
0167 cTopDefault),
0168 .e = ( cGating_36 |
0169 cAudioIF_6_5 |
0170 cVideoIF_38_90 ),
0171 },{
0172 .std = V4L2_STD_PAL_M | V4L2_STD_PAL_Nc,
0173 .name = "PAL-M/Nc",
0174 .b = ( cNegativeFmTV |
0175 cQSS ),
0176 .c = ( cDeemphasisON |
0177 cDeemphasis75 |
0178 cTopDefault),
0179 .e = ( cGating_36 |
0180 cAudioIF_4_5 |
0181 cVideoIF_45_75 ),
0182 },{
0183 .std = V4L2_STD_SECAM_B | V4L2_STD_SECAM_G | V4L2_STD_SECAM_H,
0184 .name = "SECAM-BGH",
0185 .b = ( cNegativeFmTV |
0186 cQSS ),
0187 .c = ( cTopDefault),
0188 .e = ( cAudioIF_5_5 |
0189 cVideoIF_38_90 ),
0190 },{
0191 .std = V4L2_STD_SECAM_L,
0192 .name = "SECAM-L",
0193 .b = ( cPositiveAmTV |
0194 cQSS ),
0195 .c = ( cTopDefault),
0196 .e = ( cGating_36 |
0197 cAudioIF_6_5 |
0198 cVideoIF_38_90 ),
0199 },{
0200 .std = V4L2_STD_SECAM_LC,
0201 .name = "SECAM-L'",
0202 .b = ( cOutputPort2Inactive |
0203 cPositiveAmTV |
0204 cQSS ),
0205 .c = ( cTopDefault),
0206 .e = ( cGating_36 |
0207 cAudioIF_6_5 |
0208 cVideoIF_33_90 ),
0209 },{
0210 .std = V4L2_STD_SECAM_DK,
0211 .name = "SECAM-DK",
0212 .b = ( cNegativeFmTV |
0213 cQSS ),
0214 .c = ( cDeemphasisON |
0215 cDeemphasis50 |
0216 cTopDefault),
0217 .e = ( cGating_36 |
0218 cAudioIF_6_5 |
0219 cVideoIF_38_90 ),
0220 },{
0221 .std = V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_KR,
0222 .name = "NTSC-M",
0223 .b = ( cNegativeFmTV |
0224 cQSS ),
0225 .c = ( cDeemphasisON |
0226 cDeemphasis75 |
0227 cTopDefault),
0228 .e = ( cGating_36 |
0229 cAudioIF_4_5 |
0230 cVideoIF_45_75 ),
0231 },{
0232 .std = V4L2_STD_NTSC_M_JP,
0233 .name = "NTSC-M-JP",
0234 .b = ( cNegativeFmTV |
0235 cQSS ),
0236 .c = ( cDeemphasisON |
0237 cDeemphasis50 |
0238 cTopDefault),
0239 .e = ( cGating_36 |
0240 cAudioIF_4_5 |
0241 cVideoIF_58_75 ),
0242 }
0243 };
0244
0245 static struct tvnorm radio_stereo = {
0246 .name = "Radio Stereo",
0247 .b = ( cFmRadio |
0248 cQSS ),
0249 .c = ( cDeemphasisOFF |
0250 cAudioGain6 |
0251 cTopDefault),
0252 .e = ( cTunerGainLow |
0253 cAudioIF_5_5 |
0254 cRadioIF_38_90 ),
0255 };
0256
0257 static struct tvnorm radio_mono = {
0258 .name = "Radio Mono",
0259 .b = ( cFmRadio |
0260 cQSS ),
0261 .c = ( cDeemphasisON |
0262 cDeemphasis75 |
0263 cTopDefault),
0264 .e = ( cTunerGainLow |
0265 cAudioIF_5_5 |
0266 cRadioIF_38_90 ),
0267 };
0268
0269
0270
0271 static void dump_read_message(struct dvb_frontend *fe, unsigned char *buf)
0272 {
0273 struct tda9887_priv *priv = fe->analog_demod_priv;
0274
0275 static char *afc[16] = {
0276 "- 12.5 kHz",
0277 "- 37.5 kHz",
0278 "- 62.5 kHz",
0279 "- 87.5 kHz",
0280 "-112.5 kHz",
0281 "-137.5 kHz",
0282 "-162.5 kHz",
0283 "-187.5 kHz [min]",
0284 "+187.5 kHz [max]",
0285 "+162.5 kHz",
0286 "+137.5 kHz",
0287 "+112.5 kHz",
0288 "+ 87.5 kHz",
0289 "+ 62.5 kHz",
0290 "+ 37.5 kHz",
0291 "+ 12.5 kHz",
0292 };
0293 tuner_info("read: 0x%2x\n", buf[0]);
0294 tuner_info(" after power on : %s\n", (buf[0] & 0x01) ? "yes" : "no");
0295 tuner_info(" afc : %s\n", afc[(buf[0] >> 1) & 0x0f]);
0296 tuner_info(" fmif level : %s\n", (buf[0] & 0x20) ? "high" : "low");
0297 tuner_info(" afc window : %s\n", (buf[0] & 0x40) ? "in" : "out");
0298 tuner_info(" vfi level : %s\n", (buf[0] & 0x80) ? "high" : "low");
0299 }
0300
0301 static void dump_write_message(struct dvb_frontend *fe, unsigned char *buf)
0302 {
0303 struct tda9887_priv *priv = fe->analog_demod_priv;
0304
0305 static char *sound[4] = {
0306 "AM/TV",
0307 "FM/radio",
0308 "FM/TV",
0309 "FM/radio"
0310 };
0311 static char *adjust[32] = {
0312 "-16", "-15", "-14", "-13", "-12", "-11", "-10", "-9",
0313 "-8", "-7", "-6", "-5", "-4", "-3", "-2", "-1",
0314 "0", "+1", "+2", "+3", "+4", "+5", "+6", "+7",
0315 "+8", "+9", "+10", "+11", "+12", "+13", "+14", "+15"
0316 };
0317 static char *deemph[4] = {
0318 "no", "no", "75", "50"
0319 };
0320 static char *carrier[4] = {
0321 "4.5 MHz",
0322 "5.5 MHz",
0323 "6.0 MHz",
0324 "6.5 MHz / AM"
0325 };
0326 static char *vif[8] = {
0327 "58.75 MHz",
0328 "45.75 MHz",
0329 "38.9 MHz",
0330 "38.0 MHz",
0331 "33.9 MHz",
0332 "33.4 MHz",
0333 "45.75 MHz + pin13",
0334 "38.9 MHz + pin13",
0335 };
0336 static char *rif[4] = {
0337 "44 MHz",
0338 "52 MHz",
0339 "52 MHz",
0340 "44 MHz",
0341 };
0342
0343 tuner_info("write: byte B 0x%02x\n", buf[1]);
0344 tuner_info(" B0 video mode : %s\n",
0345 (buf[1] & 0x01) ? "video trap" : "sound trap");
0346 tuner_info(" B1 auto mute fm : %s\n",
0347 (buf[1] & 0x02) ? "yes" : "no");
0348 tuner_info(" B2 carrier mode : %s\n",
0349 (buf[1] & 0x04) ? "QSS" : "Intercarrier");
0350 tuner_info(" B3-4 tv sound/radio : %s\n",
0351 sound[(buf[1] & 0x18) >> 3]);
0352 tuner_info(" B5 force mute audio: %s\n",
0353 (buf[1] & 0x20) ? "yes" : "no");
0354 tuner_info(" B6 output port 1 : %s\n",
0355 (buf[1] & 0x40) ? "high (inactive)" : "low (active)");
0356 tuner_info(" B7 output port 2 : %s\n",
0357 (buf[1] & 0x80) ? "high (inactive)" : "low (active)");
0358
0359 tuner_info("write: byte C 0x%02x\n", buf[2]);
0360 tuner_info(" C0-4 top adjustment : %s dB\n",
0361 adjust[buf[2] & 0x1f]);
0362 tuner_info(" C5-6 de-emphasis : %s\n",
0363 deemph[(buf[2] & 0x60) >> 5]);
0364 tuner_info(" C7 audio gain : %s\n",
0365 (buf[2] & 0x80) ? "-6" : "0");
0366
0367 tuner_info("write: byte E 0x%02x\n", buf[3]);
0368 tuner_info(" E0-1 sound carrier : %s\n",
0369 carrier[(buf[3] & 0x03)]);
0370 tuner_info(" E6 l pll gating : %s\n",
0371 (buf[3] & 0x40) ? "36" : "13");
0372
0373 if (buf[1] & 0x08) {
0374
0375 tuner_info(" E2-4 video if : %s\n",
0376 rif[(buf[3] & 0x0c) >> 2]);
0377 tuner_info(" E7 vif agc output : %s\n",
0378 (buf[3] & 0x80)
0379 ? ((buf[3] & 0x10) ? "fm-agc radio" :
0380 "sif-agc radio")
0381 : "fm radio carrier afc");
0382 } else {
0383
0384 tuner_info(" E2-4 video if : %s\n",
0385 vif[(buf[3] & 0x1c) >> 2]);
0386 tuner_info(" E5 tuner gain : %s\n",
0387 (buf[3] & 0x80)
0388 ? ((buf[3] & 0x20) ? "external" : "normal")
0389 : ((buf[3] & 0x20) ? "minimum" : "normal"));
0390 tuner_info(" E7 vif agc output : %s\n",
0391 (buf[3] & 0x80) ? ((buf[3] & 0x20)
0392 ? "pin3 port, pin22 vif agc out"
0393 : "pin22 port, pin3 vif acg ext in")
0394 : "pin3+pin22 port");
0395 }
0396 tuner_info("--\n");
0397 }
0398
0399
0400
0401 static int tda9887_set_tvnorm(struct dvb_frontend *fe)
0402 {
0403 struct tda9887_priv *priv = fe->analog_demod_priv;
0404 struct tvnorm *norm = NULL;
0405 char *buf = priv->data;
0406 int i;
0407
0408 if (priv->mode == V4L2_TUNER_RADIO) {
0409 if (priv->audmode == V4L2_TUNER_MODE_MONO)
0410 norm = &radio_mono;
0411 else
0412 norm = &radio_stereo;
0413 } else {
0414 for (i = 0; i < ARRAY_SIZE(tvnorms); i++) {
0415 if (tvnorms[i].std & priv->std) {
0416 norm = tvnorms+i;
0417 break;
0418 }
0419 }
0420 }
0421 if (NULL == norm) {
0422 tuner_dbg("Unsupported tvnorm entry - audio muted\n");
0423 return -1;
0424 }
0425
0426 tuner_dbg("configure for: %s\n", norm->name);
0427 buf[1] = norm->b;
0428 buf[2] = norm->c;
0429 buf[3] = norm->e;
0430 return 0;
0431 }
0432
0433 static unsigned int port1 = UNSET;
0434 static unsigned int port2 = UNSET;
0435 static unsigned int qss = UNSET;
0436 static unsigned int adjust = UNSET;
0437
0438 module_param(port1, int, 0644);
0439 module_param(port2, int, 0644);
0440 module_param(qss, int, 0644);
0441 module_param(adjust, int, 0644);
0442
0443 static int tda9887_set_insmod(struct dvb_frontend *fe)
0444 {
0445 struct tda9887_priv *priv = fe->analog_demod_priv;
0446 char *buf = priv->data;
0447
0448 if (UNSET != port1) {
0449 if (port1)
0450 buf[1] |= cOutputPort1Inactive;
0451 else
0452 buf[1] &= ~cOutputPort1Inactive;
0453 }
0454 if (UNSET != port2) {
0455 if (port2)
0456 buf[1] |= cOutputPort2Inactive;
0457 else
0458 buf[1] &= ~cOutputPort2Inactive;
0459 }
0460
0461 if (UNSET != qss) {
0462 if (qss)
0463 buf[1] |= cQSS;
0464 else
0465 buf[1] &= ~cQSS;
0466 }
0467
0468 if (adjust < 0x20) {
0469 buf[2] &= ~cTopMask;
0470 buf[2] |= adjust;
0471 }
0472 return 0;
0473 }
0474
0475 static int tda9887_do_config(struct dvb_frontend *fe)
0476 {
0477 struct tda9887_priv *priv = fe->analog_demod_priv;
0478 char *buf = priv->data;
0479
0480 if (priv->config & TDA9887_PORT1_ACTIVE)
0481 buf[1] &= ~cOutputPort1Inactive;
0482 if (priv->config & TDA9887_PORT1_INACTIVE)
0483 buf[1] |= cOutputPort1Inactive;
0484 if (priv->config & TDA9887_PORT2_ACTIVE)
0485 buf[1] &= ~cOutputPort2Inactive;
0486 if (priv->config & TDA9887_PORT2_INACTIVE)
0487 buf[1] |= cOutputPort2Inactive;
0488
0489 if (priv->config & TDA9887_QSS)
0490 buf[1] |= cQSS;
0491 if (priv->config & TDA9887_INTERCARRIER)
0492 buf[1] &= ~cQSS;
0493
0494 if (priv->config & TDA9887_AUTOMUTE)
0495 buf[1] |= cAutoMuteFmActive;
0496 if (priv->config & TDA9887_DEEMPHASIS_MASK) {
0497 buf[2] &= ~0x60;
0498 switch (priv->config & TDA9887_DEEMPHASIS_MASK) {
0499 case TDA9887_DEEMPHASIS_NONE:
0500 buf[2] |= cDeemphasisOFF;
0501 break;
0502 case TDA9887_DEEMPHASIS_50:
0503 buf[2] |= cDeemphasisON | cDeemphasis50;
0504 break;
0505 case TDA9887_DEEMPHASIS_75:
0506 buf[2] |= cDeemphasisON | cDeemphasis75;
0507 break;
0508 }
0509 }
0510 if (priv->config & TDA9887_TOP_SET) {
0511 buf[2] &= ~cTopMask;
0512 buf[2] |= (priv->config >> 8) & cTopMask;
0513 }
0514 if ((priv->config & TDA9887_INTERCARRIER_NTSC) &&
0515 (priv->std & V4L2_STD_NTSC))
0516 buf[1] &= ~cQSS;
0517 if (priv->config & TDA9887_GATING_18)
0518 buf[3] &= ~cGating_36;
0519
0520 if (priv->mode == V4L2_TUNER_RADIO) {
0521 if (priv->config & TDA9887_RIF_41_3) {
0522 buf[3] &= ~cVideoIFMask;
0523 buf[3] |= cRadioIF_41_30;
0524 }
0525 if (priv->config & TDA9887_GAIN_NORMAL)
0526 buf[3] &= ~cTunerGainLow;
0527 }
0528
0529 return 0;
0530 }
0531
0532
0533
0534 static int tda9887_status(struct dvb_frontend *fe)
0535 {
0536 struct tda9887_priv *priv = fe->analog_demod_priv;
0537 unsigned char buf[1];
0538 int rc;
0539
0540 rc = tuner_i2c_xfer_recv(&priv->i2c_props, buf, 1);
0541 if (rc != 1)
0542 tuner_info("i2c i/o error: rc == %d (should be 1)\n", rc);
0543 dump_read_message(fe, buf);
0544 return 0;
0545 }
0546
0547 static void tda9887_configure(struct dvb_frontend *fe)
0548 {
0549 struct tda9887_priv *priv = fe->analog_demod_priv;
0550 int rc;
0551
0552 memset(priv->data,0,sizeof(priv->data));
0553 tda9887_set_tvnorm(fe);
0554
0555
0556
0557
0558
0559
0560
0561
0562
0563
0564
0565
0566
0567
0568 priv->data[1] |= cOutputPort1Inactive;
0569 priv->data[1] |= cOutputPort2Inactive;
0570
0571 tda9887_do_config(fe);
0572 tda9887_set_insmod(fe);
0573
0574 if (priv->standby)
0575 priv->data[1] |= cForcedMuteAudioON;
0576
0577 tuner_dbg("writing: b=0x%02x c=0x%02x e=0x%02x\n",
0578 priv->data[1], priv->data[2], priv->data[3]);
0579 if (debug > 1)
0580 dump_write_message(fe, priv->data);
0581
0582 if (4 != (rc = tuner_i2c_xfer_send(&priv->i2c_props,priv->data,4)))
0583 tuner_info("i2c i/o error: rc == %d (should be 4)\n", rc);
0584
0585 if (debug > 2) {
0586 msleep_interruptible(1000);
0587 tda9887_status(fe);
0588 }
0589 }
0590
0591
0592
0593 static void tda9887_tuner_status(struct dvb_frontend *fe)
0594 {
0595 struct tda9887_priv *priv = fe->analog_demod_priv;
0596 tuner_info("Data bytes: b=0x%02x c=0x%02x e=0x%02x\n",
0597 priv->data[1], priv->data[2], priv->data[3]);
0598 }
0599
0600 static int tda9887_get_afc(struct dvb_frontend *fe, s32 *afc)
0601 {
0602 struct tda9887_priv *priv = fe->analog_demod_priv;
0603 static const int AFC_BITS_2_kHz[] = {
0604 -12500, -37500, -62500, -97500,
0605 -112500, -137500, -162500, -187500,
0606 187500, 162500, 137500, 112500,
0607 97500 , 62500, 37500 , 12500
0608 };
0609 __u8 reg = 0;
0610
0611 if (priv->mode != V4L2_TUNER_RADIO)
0612 return 0;
0613 if (1 == tuner_i2c_xfer_recv(&priv->i2c_props, ®, 1))
0614 *afc = AFC_BITS_2_kHz[(reg >> 1) & 0x0f];
0615 return 0;
0616 }
0617
0618 static void tda9887_standby(struct dvb_frontend *fe)
0619 {
0620 struct tda9887_priv *priv = fe->analog_demod_priv;
0621
0622 priv->standby = true;
0623
0624 tda9887_configure(fe);
0625 }
0626
0627 static void tda9887_set_params(struct dvb_frontend *fe,
0628 struct analog_parameters *params)
0629 {
0630 struct tda9887_priv *priv = fe->analog_demod_priv;
0631
0632 priv->standby = false;
0633 priv->mode = params->mode;
0634 priv->audmode = params->audmode;
0635 priv->std = params->std;
0636 tda9887_configure(fe);
0637 }
0638
0639 static int tda9887_set_config(struct dvb_frontend *fe, void *priv_cfg)
0640 {
0641 struct tda9887_priv *priv = fe->analog_demod_priv;
0642
0643 priv->config = *(unsigned int *)priv_cfg;
0644 tda9887_configure(fe);
0645
0646 return 0;
0647 }
0648
0649 static void tda9887_release(struct dvb_frontend *fe)
0650 {
0651 struct tda9887_priv *priv = fe->analog_demod_priv;
0652
0653 mutex_lock(&tda9887_list_mutex);
0654
0655 if (priv)
0656 hybrid_tuner_release_state(priv);
0657
0658 mutex_unlock(&tda9887_list_mutex);
0659
0660 fe->analog_demod_priv = NULL;
0661 }
0662
0663 static const struct analog_demod_ops tda9887_ops = {
0664 .info = {
0665 .name = "tda9887",
0666 },
0667 .set_params = tda9887_set_params,
0668 .standby = tda9887_standby,
0669 .tuner_status = tda9887_tuner_status,
0670 .get_afc = tda9887_get_afc,
0671 .release = tda9887_release,
0672 .set_config = tda9887_set_config,
0673 };
0674
0675 struct dvb_frontend *tda9887_attach(struct dvb_frontend *fe,
0676 struct i2c_adapter *i2c_adap,
0677 u8 i2c_addr)
0678 {
0679 struct tda9887_priv *priv = NULL;
0680 int instance;
0681
0682 mutex_lock(&tda9887_list_mutex);
0683
0684 instance = hybrid_tuner_request_state(struct tda9887_priv, priv,
0685 hybrid_tuner_instance_list,
0686 i2c_adap, i2c_addr, "tda9887");
0687 switch (instance) {
0688 case 0:
0689 mutex_unlock(&tda9887_list_mutex);
0690 return NULL;
0691 case 1:
0692 fe->analog_demod_priv = priv;
0693 priv->standby = true;
0694 tuner_info("tda988[5/6/7] found\n");
0695 break;
0696 default:
0697 fe->analog_demod_priv = priv;
0698 break;
0699 }
0700
0701 mutex_unlock(&tda9887_list_mutex);
0702
0703 memcpy(&fe->ops.analog_ops, &tda9887_ops,
0704 sizeof(struct analog_demod_ops));
0705
0706 return fe;
0707 }
0708 EXPORT_SYMBOL_GPL(tda9887_attach);
0709
0710 MODULE_LICENSE("GPL");