linux/drivers/media/tuners/tda9887.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2#include <linux/module.h>
   3#include <linux/kernel.h>
   4#include <linux/i2c.h>
   5#include <linux/types.h>
   6#include <linux/init.h>
   7#include <linux/errno.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        bool               standby;
  42};
  43
  44/* ---------------------------------------------------------------------- */
  45
  46#define UNSET       (-1U)
  47
  48struct tvnorm {
  49        v4l2_std_id       std;
  50        char              *name;
  51        unsigned char     b;
  52        unsigned char     c;
  53        unsigned char     e;
  54};
  55
  56/* ---------------------------------------------------------------------- */
  57
  58//
  59// TDA defines
  60//
  61
  62//// first reg (b)
  63#define cVideoTrapBypassOFF     0x00    // bit b0
  64#define cVideoTrapBypassON      0x01    // bit b0
  65
  66#define cAutoMuteFmInactive     0x00    // bit b1
  67#define cAutoMuteFmActive       0x02    // bit b1
  68
  69#define cIntercarrier           0x00    // bit b2
  70#define cQSS                    0x04    // bit b2
  71
  72#define cPositiveAmTV           0x00    // bit b3:4
  73#define cFmRadio                0x08    // bit b3:4
  74#define cNegativeFmTV           0x10    // bit b3:4
  75
  76
  77#define cForcedMuteAudioON      0x20    // bit b5
  78#define cForcedMuteAudioOFF     0x00    // bit b5
  79
  80#define cOutputPort1Active      0x00    // bit b6
  81#define cOutputPort1Inactive    0x40    // bit b6
  82
  83#define cOutputPort2Active      0x00    // bit b7
  84#define cOutputPort2Inactive    0x80    // bit b7
  85
  86
  87//// second reg (c)
  88#define cDeemphasisOFF          0x00    // bit c5
  89#define cDeemphasisON           0x20    // bit c5
  90
  91#define cDeemphasis75           0x00    // bit c6
  92#define cDeemphasis50           0x40    // bit c6
  93
  94#define cAudioGain0             0x00    // bit c7
  95#define cAudioGain6             0x80    // bit c7
  96
  97#define cTopMask                0x1f    // bit c0:4
  98#define cTopDefault             0x10    // bit c0:4
  99
 100//// third reg (e)
 101#define cAudioIF_4_5             0x00    // bit e0:1
 102#define cAudioIF_5_5             0x01    // bit e0:1
 103#define cAudioIF_6_0             0x02    // bit e0:1
 104#define cAudioIF_6_5             0x03    // bit e0:1
 105
 106
 107#define cVideoIFMask            0x1c    // bit e2:4
 108/* Video IF selection in TV Mode (bit B3=0) */
 109#define cVideoIF_58_75           0x00    // bit e2:4
 110#define cVideoIF_45_75           0x04    // bit e2:4
 111#define cVideoIF_38_90           0x08    // bit e2:4
 112#define cVideoIF_38_00           0x0C    // bit e2:4
 113#define cVideoIF_33_90           0x10    // bit e2:4
 114#define cVideoIF_33_40           0x14    // bit e2:4
 115#define cRadioIF_45_75           0x18    // bit e2:4
 116#define cRadioIF_38_90           0x1C    // bit e2:4
 117
 118/* IF1 selection in Radio Mode (bit B3=1) */
 119#define cRadioIF_33_30          0x00    // bit e2,4 (also 0x10,0x14)
 120#define cRadioIF_41_30          0x04    // bit e2,4
 121
 122/* Output of AFC pin in radio mode when bit E7=1 */
 123#define cRadioAGC_SIF           0x00    // bit e3
 124#define cRadioAGC_FM            0x08    // bit e3
 125
 126#define cTunerGainNormal         0x00    // bit e5
 127#define cTunerGainLow            0x20    // bit e5
 128
 129#define cGating_18               0x00    // bit e6
 130#define cGating_36               0x40    // bit e6
 131
 132#define cAgcOutON                0x80    // bit e7
 133#define cAgcOutOFF               0x00    // bit e7
 134
 135/* ---------------------------------------------------------------------- */
 136
 137static struct tvnorm tvnorms[] = {
 138        {
 139                .std   = V4L2_STD_PAL_BG | V4L2_STD_PAL_H | V4L2_STD_PAL_N,
 140                .name  = "PAL-BGHN",
 141                .b     = ( cNegativeFmTV  |
 142                           cQSS           ),
 143                .c     = ( cDeemphasisON  |
 144                           cDeemphasis50  |
 145                           cTopDefault),
 146                .e     = ( cGating_36     |
 147                           cAudioIF_5_5   |
 148                           cVideoIF_38_90 ),
 149        },{
 150                .std   = V4L2_STD_PAL_I,
 151                .name  = "PAL-I",
 152                .b     = ( cNegativeFmTV  |
 153                           cQSS           ),
 154                .c     = ( cDeemphasisON  |
 155                           cDeemphasis50  |
 156                           cTopDefault),
 157                .e     = ( cGating_36     |
 158                           cAudioIF_6_0   |
 159                           cVideoIF_38_90 ),
 160        },{
 161                .std   = V4L2_STD_PAL_DK,
 162                .name  = "PAL-DK",
 163                .b     = ( cNegativeFmTV  |
 164                           cQSS           ),
 165                .c     = ( cDeemphasisON  |
 166                           cDeemphasis50  |
 167                           cTopDefault),
 168                .e     = ( cGating_36     |
 169                           cAudioIF_6_5   |
 170                           cVideoIF_38_90 ),
 171        },{
 172                .std   = V4L2_STD_PAL_M | V4L2_STD_PAL_Nc,
 173                .name  = "PAL-M/Nc",
 174                .b     = ( cNegativeFmTV  |
 175                           cQSS           ),
 176                .c     = ( cDeemphasisON  |
 177                           cDeemphasis75  |
 178                           cTopDefault),
 179                .e     = ( cGating_36     |
 180                           cAudioIF_4_5   |
 181                           cVideoIF_45_75 ),
 182        },{
 183                .std   = V4L2_STD_SECAM_B | V4L2_STD_SECAM_G | V4L2_STD_SECAM_H,
 184                .name  = "SECAM-BGH",
 185                .b     = ( cNegativeFmTV  |
 186                           cQSS           ),
 187                .c     = ( cTopDefault),
 188                .e     = ( cAudioIF_5_5   |
 189                           cVideoIF_38_90 ),
 190        },{
 191                .std   = V4L2_STD_SECAM_L,
 192                .name  = "SECAM-L",
 193                .b     = ( cPositiveAmTV  |
 194                           cQSS           ),
 195                .c     = ( cTopDefault),
 196                .e     = ( cGating_36     |
 197                           cAudioIF_6_5   |
 198                           cVideoIF_38_90 ),
 199        },{
 200                .std   = V4L2_STD_SECAM_LC,
 201                .name  = "SECAM-L'",
 202                .b     = ( cOutputPort2Inactive |
 203                           cPositiveAmTV  |
 204                           cQSS           ),
 205                .c     = ( cTopDefault),
 206                .e     = ( cGating_36     |
 207                           cAudioIF_6_5   |
 208                           cVideoIF_33_90 ),
 209        },{
 210                .std   = V4L2_STD_SECAM_DK,
 211                .name  = "SECAM-DK",
 212                .b     = ( cNegativeFmTV  |
 213                           cQSS           ),
 214                .c     = ( cDeemphasisON  |
 215                           cDeemphasis50  |
 216                           cTopDefault),
 217                .e     = ( cGating_36     |
 218                           cAudioIF_6_5   |
 219                           cVideoIF_38_90 ),
 220        },{
 221                .std   = V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_KR,
 222                .name  = "NTSC-M",
 223                .b     = ( cNegativeFmTV  |
 224                           cQSS           ),
 225                .c     = ( cDeemphasisON  |
 226                           cDeemphasis75  |
 227                           cTopDefault),
 228                .e     = ( cGating_36     |
 229                           cAudioIF_4_5   |
 230                           cVideoIF_45_75 ),
 231        },{
 232                .std   = V4L2_STD_NTSC_M_JP,
 233                .name  = "NTSC-M-JP",
 234                .b     = ( cNegativeFmTV  |
 235                           cQSS           ),
 236                .c     = ( cDeemphasisON  |
 237                           cDeemphasis50  |
 238                           cTopDefault),
 239                .e     = ( cGating_36     |
 240                           cAudioIF_4_5   |
 241                           cVideoIF_58_75 ),
 242        }
 243};
 244
 245static struct tvnorm radio_stereo = {
 246        .name = "Radio Stereo",
 247        .b    = ( cFmRadio       |
 248                  cQSS           ),
 249        .c    = ( cDeemphasisOFF |
 250                  cAudioGain6    |
 251                  cTopDefault),
 252        .e    = ( cTunerGainLow  |
 253                  cAudioIF_5_5   |
 254                  cRadioIF_38_90 ),
 255};
 256
 257static struct tvnorm radio_mono = {
 258        .name = "Radio Mono",
 259        .b    = ( cFmRadio       |
 260                  cQSS           ),
 261        .c    = ( cDeemphasisON  |
 262                  cDeemphasis75  |
 263                  cTopDefault),
 264        .e    = ( cTunerGainLow  |
 265                  cAudioIF_5_5   |
 266                  cRadioIF_38_90 ),
 267};
 268
 269/* ---------------------------------------------------------------------- */
 270
 271static void dump_read_message(struct dvb_frontend *fe, unsigned char *buf)
 272{
 273        struct tda9887_priv *priv = fe->analog_demod_priv;
 274
 275        static char *afc[16] = {
 276                "- 12.5 kHz",
 277                "- 37.5 kHz",
 278                "- 62.5 kHz",
 279                "- 87.5 kHz",
 280                "-112.5 kHz",
 281                "-137.5 kHz",
 282                "-162.5 kHz",
 283                "-187.5 kHz [min]",
 284                "+187.5 kHz [max]",
 285                "+162.5 kHz",
 286                "+137.5 kHz",
 287                "+112.5 kHz",
 288                "+ 87.5 kHz",
 289                "+ 62.5 kHz",
 290                "+ 37.5 kHz",
 291                "+ 12.5 kHz",
 292        };
 293        tuner_info("read: 0x%2x\n", buf[0]);
 294        tuner_info("  after power on : %s\n", (buf[0] & 0x01) ? "yes" : "no");
 295        tuner_info("  afc            : %s\n", afc[(buf[0] >> 1) & 0x0f]);
 296        tuner_info("  fmif level     : %s\n", (buf[0] & 0x20) ? "high" : "low");
 297        tuner_info("  afc window     : %s\n", (buf[0] & 0x40) ? "in" : "out");
 298        tuner_info("  vfi level      : %s\n", (buf[0] & 0x80) ? "high" : "low");
 299}
 300
 301static void dump_write_message(struct dvb_frontend *fe, unsigned char *buf)
 302{
 303        struct tda9887_priv *priv = fe->analog_demod_priv;
 304
 305        static char *sound[4] = {
 306                "AM/TV",
 307                "FM/radio",
 308                "FM/TV",
 309                "FM/radio"
 310        };
 311        static char *adjust[32] = {
 312                "-16", "-15", "-14", "-13", "-12", "-11", "-10", "-9",
 313                "-8",  "-7",  "-6",  "-5",  "-4",  "-3",  "-2",  "-1",
 314                "0",   "+1",  "+2",  "+3",  "+4",  "+5",  "+6",  "+7",
 315                "+8",  "+9",  "+10", "+11", "+12", "+13", "+14", "+15"
 316        };
 317        static char *deemph[4] = {
 318                "no", "no", "75", "50"
 319        };
 320        static char *carrier[4] = {
 321                "4.5 MHz",
 322                "5.5 MHz",
 323                "6.0 MHz",
 324                "6.5 MHz / AM"
 325        };
 326        static char *vif[8] = {
 327                "58.75 MHz",
 328                "45.75 MHz",
 329                "38.9 MHz",
 330                "38.0 MHz",
 331                "33.9 MHz",
 332                "33.4 MHz",
 333                "45.75 MHz + pin13",
 334                "38.9 MHz + pin13",
 335        };
 336        static char *rif[4] = {
 337                "44 MHz",
 338                "52 MHz",
 339                "52 MHz",
 340                "44 MHz",
 341        };
 342
 343        tuner_info("write: byte B 0x%02x\n", buf[1]);
 344        tuner_info("  B0   video mode      : %s\n",
 345                   (buf[1] & 0x01) ? "video trap" : "sound trap");
 346        tuner_info("  B1   auto mute fm    : %s\n",
 347                   (buf[1] & 0x02) ? "yes" : "no");
 348        tuner_info("  B2   carrier mode    : %s\n",
 349                   (buf[1] & 0x04) ? "QSS" : "Intercarrier");
 350        tuner_info("  B3-4 tv sound/radio  : %s\n",
 351                   sound[(buf[1] & 0x18) >> 3]);
 352        tuner_info("  B5   force mute audio: %s\n",
 353                   (buf[1] & 0x20) ? "yes" : "no");
 354        tuner_info("  B6   output port 1   : %s\n",
 355                   (buf[1] & 0x40) ? "high (inactive)" : "low (active)");
 356        tuner_info("  B7   output port 2   : %s\n",
 357                   (buf[1] & 0x80) ? "high (inactive)" : "low (active)");
 358
 359        tuner_info("write: byte C 0x%02x\n", buf[2]);
 360        tuner_info("  C0-4 top adjustment  : %s dB\n",
 361                   adjust[buf[2] & 0x1f]);
 362        tuner_info("  C5-6 de-emphasis     : %s\n",
 363                   deemph[(buf[2] & 0x60) >> 5]);
 364        tuner_info("  C7   audio gain      : %s\n",
 365                   (buf[2] & 0x80) ? "-6" : "0");
 366
 367        tuner_info("write: byte E 0x%02x\n", buf[3]);
 368        tuner_info("  E0-1 sound carrier   : %s\n",
 369                   carrier[(buf[3] & 0x03)]);
 370        tuner_info("  E6   l pll gating   : %s\n",
 371                   (buf[3] & 0x40) ? "36" : "13");
 372
 373        if (buf[1] & 0x08) {
 374                /* radio */
 375                tuner_info("  E2-4 video if        : %s\n",
 376                           rif[(buf[3] & 0x0c) >> 2]);
 377                tuner_info("  E7   vif agc output  : %s\n",
 378                           (buf[3] & 0x80)
 379                           ? ((buf[3] & 0x10) ? "fm-agc radio" :
 380                                                "sif-agc radio")
 381                           : "fm radio carrier afc");
 382        } else {
 383                /* video */
 384                tuner_info("  E2-4 video if        : %s\n",
 385                           vif[(buf[3] & 0x1c) >> 2]);
 386                tuner_info("  E5   tuner gain      : %s\n",
 387                           (buf[3] & 0x80)
 388                           ? ((buf[3] & 0x20) ? "external" : "normal")
 389                           : ((buf[3] & 0x20) ? "minimum"  : "normal"));
 390                tuner_info("  E7   vif agc output  : %s\n",
 391                           (buf[3] & 0x80) ? ((buf[3] & 0x20)
 392                                ? "pin3 port, pin22 vif agc out"
 393                                : "pin22 port, pin3 vif acg ext in")
 394                                : "pin3+pin22 port");
 395        }
 396        tuner_info("--\n");
 397}
 398
 399/* ---------------------------------------------------------------------- */
 400
 401static int tda9887_set_tvnorm(struct dvb_frontend *fe)
 402{
 403        struct tda9887_priv *priv = fe->analog_demod_priv;
 404        struct tvnorm *norm = NULL;
 405        char *buf = priv->data;
 406        int i;
 407
 408        if (priv->mode == V4L2_TUNER_RADIO) {
 409                if (priv->audmode == V4L2_TUNER_MODE_MONO)
 410                        norm = &radio_mono;
 411                else
 412                        norm = &radio_stereo;
 413        } else {
 414                for (i = 0; i < ARRAY_SIZE(tvnorms); i++) {
 415                        if (tvnorms[i].std & priv->std) {
 416                                norm = tvnorms+i;
 417                                break;
 418                        }
 419                }
 420        }
 421        if (NULL == norm) {
 422                tuner_dbg("Unsupported tvnorm entry - audio muted\n");
 423                return -1;
 424        }
 425
 426        tuner_dbg("configure for: %s\n", norm->name);
 427        buf[1] = norm->b;
 428        buf[2] = norm->c;
 429        buf[3] = norm->e;
 430        return 0;
 431}
 432
 433static unsigned int port1  = UNSET;
 434static unsigned int port2  = UNSET;
 435static unsigned int qss    = UNSET;
 436static unsigned int adjust = UNSET;
 437
 438module_param(port1, int, 0644);
 439module_param(port2, int, 0644);
 440module_param(qss, int, 0644);
 441module_param(adjust, int, 0644);
 442
 443static int tda9887_set_insmod(struct dvb_frontend *fe)
 444{
 445        struct tda9887_priv *priv = fe->analog_demod_priv;
 446        char *buf = priv->data;
 447
 448        if (UNSET != port1) {
 449                if (port1)
 450                        buf[1] |= cOutputPort1Inactive;
 451                else
 452                        buf[1] &= ~cOutputPort1Inactive;
 453        }
 454        if (UNSET != port2) {
 455                if (port2)
 456                        buf[1] |= cOutputPort2Inactive;
 457                else
 458                        buf[1] &= ~cOutputPort2Inactive;
 459        }
 460
 461        if (UNSET != qss) {
 462                if (qss)
 463                        buf[1] |= cQSS;
 464                else
 465                        buf[1] &= ~cQSS;
 466        }
 467
 468        if (adjust < 0x20) {
 469                buf[2] &= ~cTopMask;
 470                buf[2] |= adjust;
 471        }
 472        return 0;
 473}
 474
 475static int tda9887_do_config(struct dvb_frontend *fe)
 476{
 477        struct tda9887_priv *priv = fe->analog_demod_priv;
 478        char *buf = priv->data;
 479
 480        if (priv->config & TDA9887_PORT1_ACTIVE)
 481                buf[1] &= ~cOutputPort1Inactive;
 482        if (priv->config & TDA9887_PORT1_INACTIVE)
 483                buf[1] |= cOutputPort1Inactive;
 484        if (priv->config & TDA9887_PORT2_ACTIVE)
 485                buf[1] &= ~cOutputPort2Inactive;
 486        if (priv->config & TDA9887_PORT2_INACTIVE)
 487                buf[1] |= cOutputPort2Inactive;
 488
 489        if (priv->config & TDA9887_QSS)
 490                buf[1] |= cQSS;
 491        if (priv->config & TDA9887_INTERCARRIER)
 492                buf[1] &= ~cQSS;
 493
 494        if (priv->config & TDA9887_AUTOMUTE)
 495                buf[1] |= cAutoMuteFmActive;
 496        if (priv->config & TDA9887_DEEMPHASIS_MASK) {
 497                buf[2] &= ~0x60;
 498                switch (priv->config & TDA9887_DEEMPHASIS_MASK) {
 499                case TDA9887_DEEMPHASIS_NONE:
 500                        buf[2] |= cDeemphasisOFF;
 501                        break;
 502                case TDA9887_DEEMPHASIS_50:
 503                        buf[2] |= cDeemphasisON | cDeemphasis50;
 504                        break;
 505                case TDA9887_DEEMPHASIS_75:
 506                        buf[2] |= cDeemphasisON | cDeemphasis75;
 507                        break;
 508                }
 509        }
 510        if (priv->config & TDA9887_TOP_SET) {
 511                buf[2] &= ~cTopMask;
 512                buf[2] |= (priv->config >> 8) & cTopMask;
 513        }
 514        if ((priv->config & TDA9887_INTERCARRIER_NTSC) &&
 515            (priv->std & V4L2_STD_NTSC))
 516                buf[1] &= ~cQSS;
 517        if (priv->config & TDA9887_GATING_18)
 518                buf[3] &= ~cGating_36;
 519
 520        if (priv->mode == V4L2_TUNER_RADIO) {
 521                if (priv->config & TDA9887_RIF_41_3) {
 522                        buf[3] &= ~cVideoIFMask;
 523                        buf[3] |= cRadioIF_41_30;
 524                }
 525                if (priv->config & TDA9887_GAIN_NORMAL)
 526                        buf[3] &= ~cTunerGainLow;
 527        }
 528
 529        return 0;
 530}
 531
 532/* ---------------------------------------------------------------------- */
 533
 534static int tda9887_status(struct dvb_frontend *fe)
 535{
 536        struct tda9887_priv *priv = fe->analog_demod_priv;
 537        unsigned char buf[1];
 538        int rc;
 539
 540        rc = tuner_i2c_xfer_recv(&priv->i2c_props, buf, 1);
 541        if (rc != 1)
 542                tuner_info("i2c i/o error: rc == %d (should be 1)\n", rc);
 543        dump_read_message(fe, buf);
 544        return 0;
 545}
 546
 547static void tda9887_configure(struct dvb_frontend *fe)
 548{
 549        struct tda9887_priv *priv = fe->analog_demod_priv;
 550        int rc;
 551
 552        memset(priv->data,0,sizeof(priv->data));
 553        tda9887_set_tvnorm(fe);
 554
 555        /* A note on the port settings:
 556           These settings tend to depend on the specifics of the board.
 557           By default they are set to inactive (bit value 1) by this driver,
 558           overwriting any changes made by the tvnorm. This means that it
 559           is the responsibility of the module using the tda9887 to set
 560           these values in case of changes in the tvnorm.
 561           In many cases port 2 should be made active (0) when selecting
 562           SECAM-L, and port 2 should remain inactive (1) for SECAM-L'.
 563
 564           For the other standards the tda9887 application note says that
 565           the ports should be set to active (0), but, again, that may
 566           differ depending on the precise hardware configuration.
 567         */
 568        priv->data[1] |= cOutputPort1Inactive;
 569        priv->data[1] |= cOutputPort2Inactive;
 570
 571        tda9887_do_config(fe);
 572        tda9887_set_insmod(fe);
 573
 574        if (priv->standby)
 575                priv->data[1] |= cForcedMuteAudioON;
 576
 577        tuner_dbg("writing: b=0x%02x c=0x%02x e=0x%02x\n",
 578                  priv->data[1], priv->data[2], priv->data[3]);
 579        if (debug > 1)
 580                dump_write_message(fe, priv->data);
 581
 582        if (4 != (rc = tuner_i2c_xfer_send(&priv->i2c_props,priv->data,4)))
 583                tuner_info("i2c i/o error: rc == %d (should be 4)\n", rc);
 584
 585        if (debug > 2) {
 586                msleep_interruptible(1000);
 587                tda9887_status(fe);
 588        }
 589}
 590
 591/* ---------------------------------------------------------------------- */
 592
 593static void tda9887_tuner_status(struct dvb_frontend *fe)
 594{
 595        struct tda9887_priv *priv = fe->analog_demod_priv;
 596        tuner_info("Data bytes: b=0x%02x c=0x%02x e=0x%02x\n",
 597                   priv->data[1], priv->data[2], priv->data[3]);
 598}
 599
 600static int tda9887_get_afc(struct dvb_frontend *fe, s32 *afc)
 601{
 602        struct tda9887_priv *priv = fe->analog_demod_priv;
 603        static const int AFC_BITS_2_kHz[] = {
 604                -12500,  -37500,  -62500,  -97500,
 605                -112500, -137500, -162500, -187500,
 606                187500,  162500,  137500,  112500,
 607                97500 ,  62500,   37500 ,  12500
 608        };
 609        __u8 reg = 0;
 610
 611        if (priv->mode != V4L2_TUNER_RADIO)
 612                return 0;
 613        if (1 == tuner_i2c_xfer_recv(&priv->i2c_props, &reg, 1))
 614                *afc = AFC_BITS_2_kHz[(reg >> 1) & 0x0f];
 615        return 0;
 616}
 617
 618static void tda9887_standby(struct dvb_frontend *fe)
 619{
 620        struct tda9887_priv *priv = fe->analog_demod_priv;
 621
 622        priv->standby = true;
 623
 624        tda9887_configure(fe);
 625}
 626
 627static void tda9887_set_params(struct dvb_frontend *fe,
 628                               struct analog_parameters *params)
 629{
 630        struct tda9887_priv *priv = fe->analog_demod_priv;
 631
 632        priv->standby = false;
 633        priv->mode    = params->mode;
 634        priv->audmode = params->audmode;
 635        priv->std     = params->std;
 636        tda9887_configure(fe);
 637}
 638
 639static int tda9887_set_config(struct dvb_frontend *fe, void *priv_cfg)
 640{
 641        struct tda9887_priv *priv = fe->analog_demod_priv;
 642
 643        priv->config = *(unsigned int *)priv_cfg;
 644        tda9887_configure(fe);
 645
 646        return 0;
 647}
 648
 649static void tda9887_release(struct dvb_frontend *fe)
 650{
 651        struct tda9887_priv *priv = fe->analog_demod_priv;
 652
 653        mutex_lock(&tda9887_list_mutex);
 654
 655        if (priv)
 656                hybrid_tuner_release_state(priv);
 657
 658        mutex_unlock(&tda9887_list_mutex);
 659
 660        fe->analog_demod_priv = NULL;
 661}
 662
 663static const struct analog_demod_ops tda9887_ops = {
 664        .info           = {
 665                .name   = "tda9887",
 666        },
 667        .set_params     = tda9887_set_params,
 668        .standby        = tda9887_standby,
 669        .tuner_status   = tda9887_tuner_status,
 670        .get_afc        = tda9887_get_afc,
 671        .release        = tda9887_release,
 672        .set_config     = tda9887_set_config,
 673};
 674
 675struct dvb_frontend *tda9887_attach(struct dvb_frontend *fe,
 676                                    struct i2c_adapter *i2c_adap,
 677                                    u8 i2c_addr)
 678{
 679        struct tda9887_priv *priv = NULL;
 680        int instance;
 681
 682        mutex_lock(&tda9887_list_mutex);
 683
 684        instance = hybrid_tuner_request_state(struct tda9887_priv, priv,
 685                                              hybrid_tuner_instance_list,
 686                                              i2c_adap, i2c_addr, "tda9887");
 687        switch (instance) {
 688        case 0:
 689                mutex_unlock(&tda9887_list_mutex);
 690                return NULL;
 691        case 1:
 692                fe->analog_demod_priv = priv;
 693                priv->standby = true;
 694                tuner_info("tda988[5/6/7] found\n");
 695                break;
 696        default:
 697                fe->analog_demod_priv = priv;
 698                break;
 699        }
 700
 701        mutex_unlock(&tda9887_list_mutex);
 702
 703        memcpy(&fe->ops.analog_ops, &tda9887_ops,
 704               sizeof(struct analog_demod_ops));
 705
 706        return fe;
 707}
 708EXPORT_SYMBOL_GPL(tda9887_attach);
 709
 710MODULE_LICENSE("GPL");
 711