linux/drivers/media/usb/cx231xx/cx231xx-dvb.c
<<
>>
Prefs
   1/*
   2 DVB device driver for cx231xx
   3
   4 Copyright (C) 2008 <srinivasa.deevi at conexant dot com>
   5                Based on em28xx driver
   6
   7 This program is free software; you can redistribute it and/or modify
   8   it under the terms of the GNU General Public License as published by
   9   the Free Software Foundation; either version 2 of the License, or
  10   (at your option) any later version.
  11
  12   This program is distributed in the hope that it will be useful,
  13   but WITHOUT ANY WARRANTY; without even the implied warranty of
  14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15   GNU General Public License for more details.
  16
  17   You should have received a copy of the GNU General Public License
  18   along with this program; if not, write to the Free Software
  19   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20 */
  21
  22#include "cx231xx.h"
  23#include <linux/kernel.h>
  24#include <linux/slab.h>
  25
  26#include <media/v4l2-common.h>
  27#include <media/videobuf-vmalloc.h>
  28#include <media/tuner.h>
  29
  30#include "xc5000.h"
  31#include "s5h1432.h"
  32#include "tda18271.h"
  33#include "s5h1411.h"
  34#include "lgdt3305.h"
  35#include "si2165.h"
  36#include "mb86a20s.h"
  37#include "si2157.h"
  38#include "lgdt3306a.h"
  39
  40MODULE_DESCRIPTION("driver for cx231xx based DVB cards");
  41MODULE_AUTHOR("Srinivasa Deevi <srinivasa.deevi@conexant.com>");
  42MODULE_LICENSE("GPL");
  43
  44static unsigned int debug;
  45module_param(debug, int, 0644);
  46MODULE_PARM_DESC(debug, "enable debug messages [dvb]");
  47
  48DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
  49
  50#define CX231XX_DVB_NUM_BUFS 5
  51#define CX231XX_DVB_MAX_PACKETSIZE 564
  52#define CX231XX_DVB_MAX_PACKETS 64
  53
  54struct cx231xx_dvb {
  55        struct dvb_frontend *frontend;
  56
  57        /* feed count management */
  58        struct mutex lock;
  59        int nfeeds;
  60
  61        /* general boilerplate stuff */
  62        struct dvb_adapter adapter;
  63        struct dvb_demux demux;
  64        struct dmxdev dmxdev;
  65        struct dmx_frontend fe_hw;
  66        struct dmx_frontend fe_mem;
  67        struct dvb_net net;
  68        struct i2c_client *i2c_client_demod;
  69        struct i2c_client *i2c_client_tuner;
  70};
  71
  72static struct s5h1432_config dvico_s5h1432_config = {
  73        .output_mode   = S5H1432_SERIAL_OUTPUT,
  74        .gpio          = S5H1432_GPIO_ON,
  75        .qam_if        = S5H1432_IF_4000,
  76        .vsb_if        = S5H1432_IF_4000,
  77        .inversion     = S5H1432_INVERSION_OFF,
  78        .status_mode   = S5H1432_DEMODLOCKING,
  79        .mpeg_timing   = S5H1432_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
  80};
  81
  82static struct tda18271_std_map cnxt_rde253s_tda18271_std_map = {
  83        .dvbt_6   = { .if_freq = 4000, .agc_mode = 3, .std = 4,
  84                      .if_lvl = 1, .rfagc_top = 0x37, },
  85        .dvbt_7   = { .if_freq = 4000, .agc_mode = 3, .std = 5,
  86                      .if_lvl = 1, .rfagc_top = 0x37, },
  87        .dvbt_8   = { .if_freq = 4000, .agc_mode = 3, .std = 6,
  88                      .if_lvl = 1, .rfagc_top = 0x37, },
  89};
  90
  91static struct tda18271_std_map mb86a20s_tda18271_config = {
  92        .dvbt_6   = { .if_freq = 4000, .agc_mode = 3, .std = 4,
  93                      .if_lvl = 0, .rfagc_top = 0x37, },
  94};
  95
  96static struct tda18271_config cnxt_rde253s_tunerconfig = {
  97        .std_map = &cnxt_rde253s_tda18271_std_map,
  98        .gate    = TDA18271_GATE_ANALOG,
  99};
 100
 101static struct s5h1411_config tda18271_s5h1411_config = {
 102        .output_mode   = S5H1411_SERIAL_OUTPUT,
 103        .gpio          = S5H1411_GPIO_OFF,
 104        .vsb_if        = S5H1411_IF_3250,
 105        .qam_if        = S5H1411_IF_4000,
 106        .inversion     = S5H1411_INVERSION_ON,
 107        .status_mode   = S5H1411_DEMODLOCKING,
 108        .mpeg_timing   = S5H1411_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
 109};
 110static struct s5h1411_config xc5000_s5h1411_config = {
 111        .output_mode   = S5H1411_SERIAL_OUTPUT,
 112        .gpio          = S5H1411_GPIO_OFF,
 113        .vsb_if        = S5H1411_IF_3250,
 114        .qam_if        = S5H1411_IF_3250,
 115        .inversion     = S5H1411_INVERSION_OFF,
 116        .status_mode   = S5H1411_DEMODLOCKING,
 117        .mpeg_timing   = S5H1411_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
 118};
 119
 120static struct lgdt3305_config hcw_lgdt3305_config = {
 121        .i2c_addr           = 0x0e,
 122        .mpeg_mode          = LGDT3305_MPEG_SERIAL,
 123        .tpclk_edge         = LGDT3305_TPCLK_FALLING_EDGE,
 124        .tpvalid_polarity   = LGDT3305_TP_VALID_HIGH,
 125        .deny_i2c_rptr      = 1,
 126        .spectral_inversion = 1,
 127        .qam_if_khz         = 4000,
 128        .vsb_if_khz         = 3250,
 129};
 130
 131static struct tda18271_std_map hauppauge_tda18271_std_map = {
 132        .atsc_6   = { .if_freq = 3250, .agc_mode = 3, .std = 4,
 133                      .if_lvl = 1, .rfagc_top = 0x58, },
 134        .qam_6    = { .if_freq = 4000, .agc_mode = 3, .std = 5,
 135                      .if_lvl = 1, .rfagc_top = 0x58, },
 136};
 137
 138static struct tda18271_config hcw_tda18271_config = {
 139        .std_map = &hauppauge_tda18271_std_map,
 140        .gate    = TDA18271_GATE_DIGITAL,
 141};
 142
 143static const struct mb86a20s_config pv_mb86a20s_config = {
 144        .demod_address = 0x10,
 145        .is_serial = true,
 146};
 147
 148static struct tda18271_config pv_tda18271_config = {
 149        .std_map = &mb86a20s_tda18271_config,
 150        .gate    = TDA18271_GATE_DIGITAL,
 151        .small_i2c = TDA18271_03_BYTE_CHUNK_INIT,
 152};
 153
 154static struct lgdt3306a_config hauppauge_955q_lgdt3306a_config = {
 155        .i2c_addr           = 0x59,
 156        .qam_if_khz         = 4000,
 157        .vsb_if_khz         = 3250,
 158        .deny_i2c_rptr      = 1,
 159        .spectral_inversion = 1,
 160        .mpeg_mode          = LGDT3306A_MPEG_SERIAL,
 161        .tpclk_edge         = LGDT3306A_TPCLK_RISING_EDGE,
 162        .tpvalid_polarity   = LGDT3306A_TP_VALID_HIGH,
 163        .xtalMHz            = 25,
 164};
 165
 166static inline void print_err_status(struct cx231xx *dev, int packet, int status)
 167{
 168        char *errmsg = "Unknown";
 169
 170        switch (status) {
 171        case -ENOENT:
 172                errmsg = "unlinked synchronuously";
 173                break;
 174        case -ECONNRESET:
 175                errmsg = "unlinked asynchronuously";
 176                break;
 177        case -ENOSR:
 178                errmsg = "Buffer error (overrun)";
 179                break;
 180        case -EPIPE:
 181                errmsg = "Stalled (device not responding)";
 182                break;
 183        case -EOVERFLOW:
 184                errmsg = "Babble (bad cable?)";
 185                break;
 186        case -EPROTO:
 187                errmsg = "Bit-stuff error (bad cable?)";
 188                break;
 189        case -EILSEQ:
 190                errmsg = "CRC/Timeout (could be anything)";
 191                break;
 192        case -ETIME:
 193                errmsg = "Device does not respond";
 194                break;
 195        }
 196        if (packet < 0) {
 197                dev_dbg(dev->dev,
 198                        "URB status %d [%s].\n", status, errmsg);
 199        } else {
 200                dev_dbg(dev->dev,
 201                        "URB packet %d, status %d [%s].\n",
 202                        packet, status, errmsg);
 203        }
 204}
 205
 206static inline int dvb_isoc_copy(struct cx231xx *dev, struct urb *urb)
 207{
 208        int i;
 209
 210        if (!dev)
 211                return 0;
 212
 213        if (dev->state & DEV_DISCONNECTED)
 214                return 0;
 215
 216        if (urb->status < 0) {
 217                print_err_status(dev, -1, urb->status);
 218                if (urb->status == -ENOENT)
 219                        return 0;
 220        }
 221
 222        for (i = 0; i < urb->number_of_packets; i++) {
 223                int status = urb->iso_frame_desc[i].status;
 224
 225                if (status < 0) {
 226                        print_err_status(dev, i, status);
 227                        if (urb->iso_frame_desc[i].status != -EPROTO)
 228                                continue;
 229                }
 230
 231                dvb_dmx_swfilter(&dev->dvb->demux,
 232                                 urb->transfer_buffer +
 233                                urb->iso_frame_desc[i].offset,
 234                                urb->iso_frame_desc[i].actual_length);
 235        }
 236
 237        return 0;
 238}
 239
 240static inline int dvb_bulk_copy(struct cx231xx *dev, struct urb *urb)
 241{
 242        if (!dev)
 243                return 0;
 244
 245        if (dev->state & DEV_DISCONNECTED)
 246                return 0;
 247
 248        if (urb->status < 0) {
 249                print_err_status(dev, -1, urb->status);
 250                if (urb->status == -ENOENT)
 251                        return 0;
 252        }
 253
 254        /* Feed the transport payload into the kernel demux */
 255        dvb_dmx_swfilter(&dev->dvb->demux,
 256                urb->transfer_buffer, urb->actual_length);
 257
 258        return 0;
 259}
 260
 261static int start_streaming(struct cx231xx_dvb *dvb)
 262{
 263        int rc;
 264        struct cx231xx *dev = dvb->adapter.priv;
 265
 266        if (dev->USE_ISO) {
 267                dev_dbg(dev->dev, "DVB transfer mode is ISO.\n");
 268                cx231xx_set_alt_setting(dev, INDEX_TS1, 4);
 269                rc = cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE);
 270                if (rc < 0)
 271                        return rc;
 272                dev->mode_tv = 1;
 273                return cx231xx_init_isoc(dev, CX231XX_DVB_MAX_PACKETS,
 274                                        CX231XX_DVB_NUM_BUFS,
 275                                        dev->ts1_mode.max_pkt_size,
 276                                        dvb_isoc_copy);
 277        } else {
 278                dev_dbg(dev->dev, "DVB transfer mode is BULK.\n");
 279                cx231xx_set_alt_setting(dev, INDEX_TS1, 0);
 280                rc = cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE);
 281                if (rc < 0)
 282                        return rc;
 283                dev->mode_tv = 1;
 284                return cx231xx_init_bulk(dev, CX231XX_DVB_MAX_PACKETS,
 285                                        CX231XX_DVB_NUM_BUFS,
 286                                        dev->ts1_mode.max_pkt_size,
 287                                        dvb_bulk_copy);
 288        }
 289
 290}
 291
 292static int stop_streaming(struct cx231xx_dvb *dvb)
 293{
 294        struct cx231xx *dev = dvb->adapter.priv;
 295
 296        if (dev->USE_ISO)
 297                cx231xx_uninit_isoc(dev);
 298        else
 299                cx231xx_uninit_bulk(dev);
 300
 301        cx231xx_set_mode(dev, CX231XX_SUSPEND);
 302
 303        return 0;
 304}
 305
 306static int start_feed(struct dvb_demux_feed *feed)
 307{
 308        struct dvb_demux *demux = feed->demux;
 309        struct cx231xx_dvb *dvb = demux->priv;
 310        int rc, ret;
 311
 312        if (!demux->dmx.frontend)
 313                return -EINVAL;
 314
 315        mutex_lock(&dvb->lock);
 316        dvb->nfeeds++;
 317        rc = dvb->nfeeds;
 318
 319        if (dvb->nfeeds == 1) {
 320                ret = start_streaming(dvb);
 321                if (ret < 0)
 322                        rc = ret;
 323        }
 324
 325        mutex_unlock(&dvb->lock);
 326        return rc;
 327}
 328
 329static int stop_feed(struct dvb_demux_feed *feed)
 330{
 331        struct dvb_demux *demux = feed->demux;
 332        struct cx231xx_dvb *dvb = demux->priv;
 333        int err = 0;
 334
 335        mutex_lock(&dvb->lock);
 336        dvb->nfeeds--;
 337
 338        if (0 == dvb->nfeeds)
 339                err = stop_streaming(dvb);
 340
 341        mutex_unlock(&dvb->lock);
 342        return err;
 343}
 344
 345/* ------------------------------------------------------------------ */
 346static int cx231xx_dvb_bus_ctrl(struct dvb_frontend *fe, int acquire)
 347{
 348        struct cx231xx *dev = fe->dvb->priv;
 349
 350        if (acquire)
 351                return cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE);
 352        else
 353                return cx231xx_set_mode(dev, CX231XX_SUSPEND);
 354}
 355
 356/* ------------------------------------------------------------------ */
 357
 358static struct xc5000_config cnxt_rde250_tunerconfig = {
 359        .i2c_address = 0x61,
 360        .if_khz = 4000,
 361};
 362static struct xc5000_config cnxt_rdu250_tunerconfig = {
 363        .i2c_address = 0x61,
 364        .if_khz = 3250,
 365};
 366
 367/* ------------------------------------------------------------------ */
 368#if 0
 369static int attach_xc5000(u8 addr, struct cx231xx *dev)
 370{
 371
 372        struct dvb_frontend *fe;
 373        struct xc5000_config cfg;
 374
 375        memset(&cfg, 0, sizeof(cfg));
 376        cfg.i2c_adap = cx231xx_get_i2c_adap(dev, dev->board.tuner_i2c_master);
 377        cfg.i2c_addr = addr;
 378
 379        if (!dev->dvb->frontend) {
 380                dev_err(dev->dev, "%s/2: dvb frontend not attached. Can't attach xc5000\n",
 381                        dev->name);
 382                return -EINVAL;
 383        }
 384
 385        fe = dvb_attach(xc5000_attach, dev->dvb->frontend, &cfg);
 386        if (!fe) {
 387                dev_err(dev->dev, "%s/2: xc5000 attach failed\n", dev->name);
 388                dvb_frontend_detach(dev->dvb->frontend);
 389                dev->dvb->frontend = NULL;
 390                return -EINVAL;
 391        }
 392
 393        dev_info(dev->dev, "%s/2: xc5000 attached\n", dev->name);
 394
 395        return 0;
 396}
 397#endif
 398
 399int cx231xx_set_analog_freq(struct cx231xx *dev, u32 freq)
 400{
 401        if ((dev->dvb != NULL) && (dev->dvb->frontend != NULL)) {
 402
 403                struct dvb_tuner_ops *dops = &dev->dvb->frontend->ops.tuner_ops;
 404
 405                if (dops->set_analog_params != NULL) {
 406                        struct analog_parameters params;
 407
 408                        params.frequency = freq;
 409                        params.std = dev->norm;
 410                        params.mode = 0;        /* 0- Air; 1 - cable */
 411                        /*params.audmode = ;       */
 412
 413                        /* Set the analog parameters to set the frequency */
 414                        dops->set_analog_params(dev->dvb->frontend, &params);
 415                }
 416
 417        }
 418
 419        return 0;
 420}
 421
 422int cx231xx_reset_analog_tuner(struct cx231xx *dev)
 423{
 424        int status = 0;
 425
 426        if ((dev->dvb != NULL) && (dev->dvb->frontend != NULL)) {
 427
 428                struct dvb_tuner_ops *dops = &dev->dvb->frontend->ops.tuner_ops;
 429
 430                if (dops->init != NULL && !dev->xc_fw_load_done) {
 431
 432                        dev_dbg(dev->dev,
 433                                "Reloading firmware for XC5000\n");
 434                        status = dops->init(dev->dvb->frontend);
 435                        if (status == 0) {
 436                                dev->xc_fw_load_done = 1;
 437                                dev_dbg(dev->dev,
 438                                        "XC5000 firmware download completed\n");
 439                        } else {
 440                                dev->xc_fw_load_done = 0;
 441                                dev_dbg(dev->dev,
 442                                        "XC5000 firmware download failed !!!\n");
 443                        }
 444                }
 445
 446        }
 447
 448        return status;
 449}
 450
 451/* ------------------------------------------------------------------ */
 452
 453static int register_dvb(struct cx231xx_dvb *dvb,
 454                        struct module *module,
 455                        struct cx231xx *dev, struct device *device)
 456{
 457        int result;
 458
 459        mutex_init(&dvb->lock);
 460
 461
 462        /* register adapter */
 463        result = dvb_register_adapter(&dvb->adapter, dev->name, module, device,
 464                                      adapter_nr);
 465        if (result < 0) {
 466                dev_warn(dev->dev,
 467                       "%s: dvb_register_adapter failed (errno = %d)\n",
 468                       dev->name, result);
 469                goto fail_adapter;
 470        }
 471        dvb_register_media_controller(&dvb->adapter, dev->media_dev);
 472
 473        /* Ensure all frontends negotiate bus access */
 474        dvb->frontend->ops.ts_bus_ctrl = cx231xx_dvb_bus_ctrl;
 475
 476        dvb->adapter.priv = dev;
 477
 478        /* register frontend */
 479        result = dvb_register_frontend(&dvb->adapter, dvb->frontend);
 480        if (result < 0) {
 481                dev_warn(dev->dev,
 482                       "%s: dvb_register_frontend failed (errno = %d)\n",
 483                       dev->name, result);
 484                goto fail_frontend;
 485        }
 486
 487        /* register demux stuff */
 488        dvb->demux.dmx.capabilities =
 489            DMX_TS_FILTERING | DMX_SECTION_FILTERING |
 490            DMX_MEMORY_BASED_FILTERING;
 491        dvb->demux.priv = dvb;
 492        dvb->demux.filternum = 256;
 493        dvb->demux.feednum = 256;
 494        dvb->demux.start_feed = start_feed;
 495        dvb->demux.stop_feed = stop_feed;
 496
 497        result = dvb_dmx_init(&dvb->demux);
 498        if (result < 0) {
 499                dev_warn(dev->dev,
 500                         "%s: dvb_dmx_init failed (errno = %d)\n",
 501                       dev->name, result);
 502                goto fail_dmx;
 503        }
 504
 505        dvb->dmxdev.filternum = 256;
 506        dvb->dmxdev.demux = &dvb->demux.dmx;
 507        dvb->dmxdev.capabilities = 0;
 508        result = dvb_dmxdev_init(&dvb->dmxdev, &dvb->adapter);
 509        if (result < 0) {
 510                dev_warn(dev->dev,
 511                         "%s: dvb_dmxdev_init failed (errno = %d)\n",
 512                         dev->name, result);
 513                goto fail_dmxdev;
 514        }
 515
 516        dvb->fe_hw.source = DMX_FRONTEND_0;
 517        result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_hw);
 518        if (result < 0) {
 519                dev_warn(dev->dev,
 520                       "%s: add_frontend failed (DMX_FRONTEND_0, errno = %d)\n",
 521                       dev->name, result);
 522                goto fail_fe_hw;
 523        }
 524
 525        dvb->fe_mem.source = DMX_MEMORY_FE;
 526        result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_mem);
 527        if (result < 0) {
 528                dev_warn(dev->dev,
 529                         "%s: add_frontend failed (DMX_MEMORY_FE, errno = %d)\n",
 530                         dev->name, result);
 531                goto fail_fe_mem;
 532        }
 533
 534        result = dvb->demux.dmx.connect_frontend(&dvb->demux.dmx, &dvb->fe_hw);
 535        if (result < 0) {
 536                dev_warn(dev->dev,
 537                         "%s: connect_frontend failed (errno = %d)\n",
 538                         dev->name, result);
 539                goto fail_fe_conn;
 540        }
 541
 542        /* register network adapter */
 543        dvb_net_init(&dvb->adapter, &dvb->net, &dvb->demux.dmx);
 544        result = dvb_create_media_graph(&dvb->adapter,
 545                                        dev->tuner_type == TUNER_ABSENT);
 546        if (result < 0)
 547                goto fail_create_graph;
 548
 549        return 0;
 550
 551fail_create_graph:
 552        dvb_net_release(&dvb->net);
 553fail_fe_conn:
 554        dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem);
 555fail_fe_mem:
 556        dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw);
 557fail_fe_hw:
 558        dvb_dmxdev_release(&dvb->dmxdev);
 559fail_dmxdev:
 560        dvb_dmx_release(&dvb->demux);
 561fail_dmx:
 562        dvb_unregister_frontend(dvb->frontend);
 563fail_frontend:
 564        dvb_frontend_detach(dvb->frontend);
 565        dvb_unregister_adapter(&dvb->adapter);
 566fail_adapter:
 567        return result;
 568}
 569
 570static void unregister_dvb(struct cx231xx_dvb *dvb)
 571{
 572        struct i2c_client *client;
 573        dvb_net_release(&dvb->net);
 574        dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem);
 575        dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw);
 576        dvb_dmxdev_release(&dvb->dmxdev);
 577        dvb_dmx_release(&dvb->demux);
 578        /* remove I2C tuner */
 579        client = dvb->i2c_client_tuner;
 580        if (client) {
 581                module_put(client->dev.driver->owner);
 582                i2c_unregister_device(client);
 583        }
 584        /* remove I2C demod */
 585        client = dvb->i2c_client_demod;
 586        if (client) {
 587                module_put(client->dev.driver->owner);
 588                i2c_unregister_device(client);
 589        }
 590        dvb_unregister_frontend(dvb->frontend);
 591        dvb_frontend_detach(dvb->frontend);
 592        dvb_unregister_adapter(&dvb->adapter);
 593}
 594
 595static int dvb_init(struct cx231xx *dev)
 596{
 597        int result = 0;
 598        struct cx231xx_dvb *dvb;
 599        struct i2c_adapter *tuner_i2c;
 600        struct i2c_adapter *demod_i2c;
 601
 602        if (!dev->board.has_dvb) {
 603                /* This device does not support the extension */
 604                return 0;
 605        }
 606
 607        dvb = kzalloc(sizeof(struct cx231xx_dvb), GFP_KERNEL);
 608
 609        if (dvb == NULL) {
 610                dev_info(dev->dev,
 611                         "cx231xx_dvb: memory allocation failed\n");
 612                return -ENOMEM;
 613        }
 614        dev->dvb = dvb;
 615        dev->cx231xx_set_analog_freq = cx231xx_set_analog_freq;
 616        dev->cx231xx_reset_analog_tuner = cx231xx_reset_analog_tuner;
 617
 618        tuner_i2c = cx231xx_get_i2c_adap(dev, dev->board.tuner_i2c_master);
 619        demod_i2c = cx231xx_get_i2c_adap(dev, dev->board.demod_i2c_master);
 620        mutex_lock(&dev->lock);
 621        cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE);
 622        cx231xx_demod_reset(dev);
 623        /* init frontend */
 624        switch (dev->model) {
 625        case CX231XX_BOARD_CNXT_CARRAERA:
 626        case CX231XX_BOARD_CNXT_RDE_250:
 627
 628                dev->dvb->frontend = dvb_attach(s5h1432_attach,
 629                                        &dvico_s5h1432_config,
 630                                        demod_i2c);
 631
 632                if (dev->dvb->frontend == NULL) {
 633                        dev_err(dev->dev,
 634                                "Failed to attach s5h1432 front end\n");
 635                        result = -EINVAL;
 636                        goto out_free;
 637                }
 638
 639                /* define general-purpose callback pointer */
 640                dvb->frontend->callback = cx231xx_tuner_callback;
 641
 642                if (!dvb_attach(xc5000_attach, dev->dvb->frontend,
 643                               tuner_i2c,
 644                               &cnxt_rde250_tunerconfig)) {
 645                        result = -EINVAL;
 646                        goto out_free;
 647                }
 648
 649                break;
 650        case CX231XX_BOARD_CNXT_SHELBY:
 651        case CX231XX_BOARD_CNXT_RDU_250:
 652
 653                dev->dvb->frontend = dvb_attach(s5h1411_attach,
 654                                               &xc5000_s5h1411_config,
 655                                               demod_i2c);
 656
 657                if (dev->dvb->frontend == NULL) {
 658                        dev_err(dev->dev,
 659                                "Failed to attach s5h1411 front end\n");
 660                        result = -EINVAL;
 661                        goto out_free;
 662                }
 663
 664                /* define general-purpose callback pointer */
 665                dvb->frontend->callback = cx231xx_tuner_callback;
 666
 667                if (!dvb_attach(xc5000_attach, dev->dvb->frontend,
 668                               tuner_i2c,
 669                               &cnxt_rdu250_tunerconfig)) {
 670                        result = -EINVAL;
 671                        goto out_free;
 672                }
 673                break;
 674        case CX231XX_BOARD_CNXT_RDE_253S:
 675
 676                dev->dvb->frontend = dvb_attach(s5h1432_attach,
 677                                        &dvico_s5h1432_config,
 678                                        demod_i2c);
 679
 680                if (dev->dvb->frontend == NULL) {
 681                        dev_err(dev->dev,
 682                                "Failed to attach s5h1432 front end\n");
 683                        result = -EINVAL;
 684                        goto out_free;
 685                }
 686
 687                /* define general-purpose callback pointer */
 688                dvb->frontend->callback = cx231xx_tuner_callback;
 689
 690                if (!dvb_attach(tda18271_attach, dev->dvb->frontend,
 691                               0x60, tuner_i2c,
 692                               &cnxt_rde253s_tunerconfig)) {
 693                        result = -EINVAL;
 694                        goto out_free;
 695                }
 696                break;
 697        case CX231XX_BOARD_CNXT_RDU_253S:
 698        case CX231XX_BOARD_KWORLD_UB445_USB_HYBRID:
 699
 700                dev->dvb->frontend = dvb_attach(s5h1411_attach,
 701                                               &tda18271_s5h1411_config,
 702                                               demod_i2c);
 703
 704                if (dev->dvb->frontend == NULL) {
 705                        dev_err(dev->dev,
 706                                "Failed to attach s5h1411 front end\n");
 707                        result = -EINVAL;
 708                        goto out_free;
 709                }
 710
 711                /* define general-purpose callback pointer */
 712                dvb->frontend->callback = cx231xx_tuner_callback;
 713
 714                if (!dvb_attach(tda18271_attach, dev->dvb->frontend,
 715                               0x60, tuner_i2c,
 716                               &cnxt_rde253s_tunerconfig)) {
 717                        result = -EINVAL;
 718                        goto out_free;
 719                }
 720                break;
 721        case CX231XX_BOARD_HAUPPAUGE_EXETER:
 722
 723                dev_info(dev->dev,
 724                         "%s: looking for tuner / demod on i2c bus: %d\n",
 725                       __func__, i2c_adapter_id(tuner_i2c));
 726
 727                dev->dvb->frontend = dvb_attach(lgdt3305_attach,
 728                                                &hcw_lgdt3305_config,
 729                                                demod_i2c);
 730
 731                if (dev->dvb->frontend == NULL) {
 732                        dev_err(dev->dev,
 733                                "Failed to attach LG3305 front end\n");
 734                        result = -EINVAL;
 735                        goto out_free;
 736                }
 737
 738                /* define general-purpose callback pointer */
 739                dvb->frontend->callback = cx231xx_tuner_callback;
 740
 741                dvb_attach(tda18271_attach, dev->dvb->frontend,
 742                           0x60, tuner_i2c,
 743                           &hcw_tda18271_config);
 744                break;
 745
 746        case CX231XX_BOARD_HAUPPAUGE_930C_HD_1113xx:
 747        {
 748                struct i2c_client *client;
 749                struct i2c_board_info info;
 750                struct si2165_platform_data si2165_pdata;
 751
 752                /* attach demod */
 753                memset(&si2165_pdata, 0, sizeof(si2165_pdata));
 754                si2165_pdata.fe = &dev->dvb->frontend;
 755                si2165_pdata.chip_mode = SI2165_MODE_PLL_XTAL,
 756                si2165_pdata.ref_freq_Hz = 16000000,
 757
 758                memset(&info, 0, sizeof(struct i2c_board_info));
 759                strlcpy(info.type, "si2165", I2C_NAME_SIZE);
 760                info.addr = 0x64;
 761                info.platform_data = &si2165_pdata;
 762                request_module(info.type);
 763                client = i2c_new_device(demod_i2c, &info);
 764                if (client == NULL || client->dev.driver == NULL || dev->dvb->frontend == NULL) {
 765                        dev_err(dev->dev,
 766                                "Failed to attach SI2165 front end\n");
 767                        result = -EINVAL;
 768                        goto out_free;
 769                }
 770
 771                if (!try_module_get(client->dev.driver->owner)) {
 772                        i2c_unregister_device(client);
 773                        result = -ENODEV;
 774                        goto out_free;
 775                }
 776
 777                dvb->i2c_client_demod = client;
 778
 779                dev->dvb->frontend->ops.i2c_gate_ctrl = NULL;
 780
 781                /* define general-purpose callback pointer */
 782                dvb->frontend->callback = cx231xx_tuner_callback;
 783
 784                dvb_attach(tda18271_attach, dev->dvb->frontend,
 785                        0x60,
 786                        tuner_i2c,
 787                        &hcw_tda18271_config);
 788
 789                dev->cx231xx_reset_analog_tuner = NULL;
 790                break;
 791        }
 792        case CX231XX_BOARD_HAUPPAUGE_930C_HD_1114xx:
 793        {
 794                struct i2c_client *client;
 795                struct i2c_board_info info;
 796                struct si2165_platform_data si2165_pdata;
 797                struct si2157_config si2157_config;
 798
 799                /* attach demod */
 800                memset(&si2165_pdata, 0, sizeof(si2165_pdata));
 801                si2165_pdata.fe = &dev->dvb->frontend;
 802                si2165_pdata.chip_mode = SI2165_MODE_PLL_EXT,
 803                si2165_pdata.ref_freq_Hz = 24000000,
 804
 805                memset(&info, 0, sizeof(struct i2c_board_info));
 806                strlcpy(info.type, "si2165", I2C_NAME_SIZE);
 807                info.addr = 0x64;
 808                info.platform_data = &si2165_pdata;
 809                request_module(info.type);
 810                client = i2c_new_device(demod_i2c, &info);
 811                if (client == NULL || client->dev.driver == NULL || dev->dvb->frontend == NULL) {
 812                        dev_err(dev->dev,
 813                                "Failed to attach SI2165 front end\n");
 814                        result = -EINVAL;
 815                        goto out_free;
 816                }
 817
 818                if (!try_module_get(client->dev.driver->owner)) {
 819                        i2c_unregister_device(client);
 820                        result = -ENODEV;
 821                        goto out_free;
 822                }
 823
 824                dvb->i2c_client_demod = client;
 825
 826                memset(&info, 0, sizeof(struct i2c_board_info));
 827
 828                dev->dvb->frontend->ops.i2c_gate_ctrl = NULL;
 829
 830                /* define general-purpose callback pointer */
 831                dvb->frontend->callback = cx231xx_tuner_callback;
 832
 833                /* attach tuner */
 834                memset(&si2157_config, 0, sizeof(si2157_config));
 835                si2157_config.fe = dev->dvb->frontend;
 836#ifdef CONFIG_MEDIA_CONTROLLER_DVB
 837                si2157_config.mdev = dev->media_dev;
 838#endif
 839                si2157_config.if_port = 1;
 840                si2157_config.inversion = true;
 841                strlcpy(info.type, "si2157", I2C_NAME_SIZE);
 842                info.addr = 0x60;
 843                info.platform_data = &si2157_config;
 844                request_module("si2157");
 845
 846                client = i2c_new_device(
 847                        tuner_i2c,
 848                        &info);
 849                if (client == NULL || client->dev.driver == NULL) {
 850                        dvb_frontend_detach(dev->dvb->frontend);
 851                        result = -ENODEV;
 852                        goto out_free;
 853                }
 854
 855                if (!try_module_get(client->dev.driver->owner)) {
 856                        i2c_unregister_device(client);
 857                        dvb_frontend_detach(dev->dvb->frontend);
 858                        result = -ENODEV;
 859                        goto out_free;
 860                }
 861
 862                dev->cx231xx_reset_analog_tuner = NULL;
 863
 864                dev->dvb->i2c_client_tuner = client;
 865                break;
 866        }
 867        case CX231XX_BOARD_HAUPPAUGE_955Q:
 868        {
 869                struct i2c_client *client;
 870                struct i2c_board_info info;
 871                struct si2157_config si2157_config;
 872
 873                memset(&info, 0, sizeof(struct i2c_board_info));
 874
 875                dev->dvb->frontend = dvb_attach(lgdt3306a_attach,
 876                        &hauppauge_955q_lgdt3306a_config,
 877                        demod_i2c
 878                        );
 879
 880                if (dev->dvb->frontend == NULL) {
 881                        dev_err(dev->dev,
 882                                "Failed to attach LGDT3306A frontend.\n");
 883                        result = -EINVAL;
 884                        goto out_free;
 885                }
 886
 887                dev->dvb->frontend->ops.i2c_gate_ctrl = NULL;
 888
 889                /* define general-purpose callback pointer */
 890                dvb->frontend->callback = cx231xx_tuner_callback;
 891
 892                /* attach tuner */
 893                memset(&si2157_config, 0, sizeof(si2157_config));
 894                si2157_config.fe = dev->dvb->frontend;
 895#ifdef CONFIG_MEDIA_CONTROLLER_DVB
 896                si2157_config.mdev = dev->media_dev;
 897#endif
 898                si2157_config.if_port = 1;
 899                si2157_config.inversion = true;
 900                strlcpy(info.type, "si2157", I2C_NAME_SIZE);
 901                info.addr = 0x60;
 902                info.platform_data = &si2157_config;
 903                request_module("si2157");
 904
 905                client = i2c_new_device(
 906                        tuner_i2c,
 907                        &info);
 908                if (client == NULL || client->dev.driver == NULL) {
 909                        dvb_frontend_detach(dev->dvb->frontend);
 910                        result = -ENODEV;
 911                        goto out_free;
 912                }
 913
 914                if (!try_module_get(client->dev.driver->owner)) {
 915                        i2c_unregister_device(client);
 916                        dvb_frontend_detach(dev->dvb->frontend);
 917                        result = -ENODEV;
 918                        goto out_free;
 919                }
 920
 921                dev->cx231xx_reset_analog_tuner = NULL;
 922
 923                dev->dvb->i2c_client_tuner = client;
 924                break;
 925        }
 926        case CX231XX_BOARD_PV_PLAYTV_USB_HYBRID:
 927        case CX231XX_BOARD_KWORLD_UB430_USB_HYBRID:
 928
 929                dev_info(dev->dev,
 930                         "%s: looking for demod on i2c bus: %d\n",
 931                         __func__, i2c_adapter_id(tuner_i2c));
 932
 933                dev->dvb->frontend = dvb_attach(mb86a20s_attach,
 934                                                &pv_mb86a20s_config,
 935                                                demod_i2c);
 936
 937                if (dev->dvb->frontend == NULL) {
 938                        dev_err(dev->dev,
 939                                "Failed to attach mb86a20s demod\n");
 940                        result = -EINVAL;
 941                        goto out_free;
 942                }
 943
 944                /* define general-purpose callback pointer */
 945                dvb->frontend->callback = cx231xx_tuner_callback;
 946
 947                dvb_attach(tda18271_attach, dev->dvb->frontend,
 948                           0x60, tuner_i2c,
 949                           &pv_tda18271_config);
 950                break;
 951
 952        default:
 953                dev_err(dev->dev,
 954                        "%s/2: The frontend of your DVB/ATSC card isn't supported yet\n",
 955                        dev->name);
 956                break;
 957        }
 958        if (NULL == dvb->frontend) {
 959                dev_err(dev->dev,
 960                       "%s/2: frontend initialization failed\n", dev->name);
 961                result = -EINVAL;
 962                goto out_free;
 963        }
 964
 965        /* register everything */
 966        result = register_dvb(dvb, THIS_MODULE, dev, dev->dev);
 967
 968        if (result < 0)
 969                goto out_free;
 970
 971
 972        dev_info(dev->dev, "Successfully loaded cx231xx-dvb\n");
 973
 974ret:
 975        cx231xx_set_mode(dev, CX231XX_SUSPEND);
 976        mutex_unlock(&dev->lock);
 977        return result;
 978
 979out_free:
 980        kfree(dvb);
 981        dev->dvb = NULL;
 982        goto ret;
 983}
 984
 985static int dvb_fini(struct cx231xx *dev)
 986{
 987        if (!dev->board.has_dvb) {
 988                /* This device does not support the extension */
 989                return 0;
 990        }
 991
 992        if (dev->dvb) {
 993                unregister_dvb(dev->dvb);
 994                dev->dvb = NULL;
 995        }
 996
 997        return 0;
 998}
 999
1000static struct cx231xx_ops dvb_ops = {
1001        .id = CX231XX_DVB,
1002        .name = "Cx231xx dvb Extension",
1003        .init = dvb_init,
1004        .fini = dvb_fini,
1005};
1006
1007static int __init cx231xx_dvb_register(void)
1008{
1009        return cx231xx_register_extension(&dvb_ops);
1010}
1011
1012static void __exit cx231xx_dvb_unregister(void)
1013{
1014        cx231xx_unregister_extension(&dvb_ops);
1015}
1016
1017module_init(cx231xx_dvb_register);
1018module_exit(cx231xx_dvb_unregister);
1019