linux/drivers/media/tuners/tda9887.c
<<
>>
Prefs
   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
  23static int debug;
  24module_param(debug, int, 0644);
  25MODULE_PARM_DESC(debug, "enable verbose debug messages");
  26
  27static DEFINE_MUTEX(tda9887_list_mutex);
  28static LIST_HEAD(hybrid_tuner_instance_list);
  29
  30struct 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
  47struct 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
 136static 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
 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 < 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        rc = tuner_i2c_xfer_recv(&priv->i2c_props, buf, 1);
 540        if (rc != 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->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, s32 *afc)
 600{
 601        struct tda9887_priv *priv = fe->analog_demod_priv;
 602        static const 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        __u8 reg = 0;
 609
 610        if (priv->mode != V4L2_TUNER_RADIO)
 611                return 0;
 612        if (1 == tuner_i2c_xfer_recv(&priv->i2c_props, &reg, 1))
 613                *afc = AFC_BITS_2_kHz[(reg >> 1) & 0x0f];
 614        return 0;
 615}
 616
 617static 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
 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->standby = false;
 632        priv->mode    = params->mode;
 633        priv->audmode = params->audmode;
 634        priv->std     = params->std;
 635        tda9887_configure(fe);
 636}
 637
 638static 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
 648static 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
 662static const 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
 674struct 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}
 707EXPORT_SYMBOL_GPL(tda9887_attach);
 708
 709MODULE_LICENSE("GPL");
 710