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