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 <linux/kernel.h>
  23#include <linux/slab.h>
  24#include <linux/usb.h>
  25
  26#include "cx231xx.h"
  27#include <media/v4l2-common.h>
  28#include <media/videobuf-vmalloc.h>
  29
  30#include "xc5000.h"
  31#include "s5h1432.h"
  32#include "tda18271.h"
  33#include "s5h1411.h"
  34#include "lgdt3305.h"
  35#include "mb86a20s.h"
  36
  37MODULE_DESCRIPTION("driver for cx231xx based DVB cards");
  38MODULE_AUTHOR("Srinivasa Deevi <srinivasa.deevi@conexant.com>");
  39MODULE_LICENSE("GPL");
  40
  41static unsigned int debug;
  42module_param(debug, int, 0644);
  43MODULE_PARM_DESC(debug, "enable debug messages [dvb]");
  44
  45DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
  46
  47#define dprintk(level, fmt, arg...) do {                        \
  48if (debug >= level)                                             \
  49        printk(KERN_DEBUG "%s/2-dvb: " fmt, dev->name, ## arg); \
  50} while (0)
  51
  52#define CX231XX_DVB_NUM_BUFS 5
  53#define CX231XX_DVB_MAX_PACKETSIZE 564
  54#define CX231XX_DVB_MAX_PACKETS 64
  55
  56struct cx231xx_dvb {
  57        struct dvb_frontend *frontend;
  58
  59        /* feed count management */
  60        struct mutex lock;
  61        int nfeeds;
  62
  63        /* general boilerplate stuff */
  64        struct dvb_adapter adapter;
  65        struct dvb_demux demux;
  66        struct dmxdev dmxdev;
  67        struct dmx_frontend fe_hw;
  68        struct dmx_frontend fe_mem;
  69        struct dvb_net net;
  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 inline void print_err_status(struct cx231xx *dev, int packet, int status)
 155{
 156        char *errmsg = "Unknown";
 157
 158        switch (status) {
 159        case -ENOENT:
 160                errmsg = "unlinked synchronuously";
 161                break;
 162        case -ECONNRESET:
 163                errmsg = "unlinked asynchronuously";
 164                break;
 165        case -ENOSR:
 166                errmsg = "Buffer error (overrun)";
 167                break;
 168        case -EPIPE:
 169                errmsg = "Stalled (device not responding)";
 170                break;
 171        case -EOVERFLOW:
 172                errmsg = "Babble (bad cable?)";
 173                break;
 174        case -EPROTO:
 175                errmsg = "Bit-stuff error (bad cable?)";
 176                break;
 177        case -EILSEQ:
 178                errmsg = "CRC/Timeout (could be anything)";
 179                break;
 180        case -ETIME:
 181                errmsg = "Device does not respond";
 182                break;
 183        }
 184        if (packet < 0) {
 185                dprintk(1, "URB status %d [%s].\n", status, errmsg);
 186        } else {
 187                dprintk(1, "URB packet %d, status %d [%s].\n",
 188                        packet, status, errmsg);
 189        }
 190}
 191
 192static inline int dvb_isoc_copy(struct cx231xx *dev, struct urb *urb)
 193{
 194        int i;
 195
 196        if (!dev)
 197                return 0;
 198
 199        if (dev->state & DEV_DISCONNECTED)
 200                return 0;
 201
 202        if (urb->status < 0) {
 203                print_err_status(dev, -1, urb->status);
 204                if (urb->status == -ENOENT)
 205                        return 0;
 206        }
 207
 208        for (i = 0; i < urb->number_of_packets; i++) {
 209                int status = urb->iso_frame_desc[i].status;
 210
 211                if (status < 0) {
 212                        print_err_status(dev, i, status);
 213                        if (urb->iso_frame_desc[i].status != -EPROTO)
 214                                continue;
 215                }
 216
 217                dvb_dmx_swfilter(&dev->dvb->demux,
 218                                 urb->transfer_buffer +
 219                                urb->iso_frame_desc[i].offset,
 220                                urb->iso_frame_desc[i].actual_length);
 221        }
 222
 223        return 0;
 224}
 225
 226static inline int dvb_bulk_copy(struct cx231xx *dev, struct urb *urb)
 227{
 228        if (!dev)
 229                return 0;
 230
 231        if (dev->state & DEV_DISCONNECTED)
 232                return 0;
 233
 234        if (urb->status < 0) {
 235                print_err_status(dev, -1, urb->status);
 236                if (urb->status == -ENOENT)
 237                        return 0;
 238        }
 239
 240        /* Feed the transport payload into the kernel demux */
 241        dvb_dmx_swfilter(&dev->dvb->demux,
 242                urb->transfer_buffer, urb->actual_length);
 243
 244        return 0;
 245}
 246
 247static int start_streaming(struct cx231xx_dvb *dvb)
 248{
 249        int rc;
 250        struct cx231xx *dev = dvb->adapter.priv;
 251
 252        if (dev->USE_ISO) {
 253                cx231xx_info("DVB transfer mode is ISO.\n");
 254                mutex_lock(&dev->i2c_lock);
 255                cx231xx_enable_i2c_port_3(dev, false);
 256                cx231xx_set_alt_setting(dev, INDEX_TS1, 4);
 257                cx231xx_enable_i2c_port_3(dev, true);
 258                mutex_unlock(&dev->i2c_lock);
 259                rc = cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE);
 260                if (rc < 0)
 261                        return rc;
 262                dev->mode_tv = 1;
 263                return cx231xx_init_isoc(dev, CX231XX_DVB_MAX_PACKETS,
 264                                        CX231XX_DVB_NUM_BUFS,
 265                                        dev->ts1_mode.max_pkt_size,
 266                                        dvb_isoc_copy);
 267        } else {
 268                cx231xx_info("DVB transfer mode is BULK.\n");
 269                cx231xx_set_alt_setting(dev, INDEX_TS1, 0);
 270                rc = cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE);
 271                if (rc < 0)
 272                        return rc;
 273                dev->mode_tv = 1;
 274                return cx231xx_init_bulk(dev, CX231XX_DVB_MAX_PACKETS,
 275                                        CX231XX_DVB_NUM_BUFS,
 276                                        dev->ts1_mode.max_pkt_size,
 277                                        dvb_bulk_copy);
 278        }
 279
 280}
 281
 282static int stop_streaming(struct cx231xx_dvb *dvb)
 283{
 284        struct cx231xx *dev = dvb->adapter.priv;
 285
 286        if (dev->USE_ISO)
 287                cx231xx_uninit_isoc(dev);
 288        else
 289                cx231xx_uninit_bulk(dev);
 290
 291        cx231xx_set_mode(dev, CX231XX_SUSPEND);
 292
 293        return 0;
 294}
 295
 296static int start_feed(struct dvb_demux_feed *feed)
 297{
 298        struct dvb_demux *demux = feed->demux;
 299        struct cx231xx_dvb *dvb = demux->priv;
 300        int rc, ret;
 301
 302        if (!demux->dmx.frontend)
 303                return -EINVAL;
 304
 305        mutex_lock(&dvb->lock);
 306        dvb->nfeeds++;
 307        rc = dvb->nfeeds;
 308
 309        if (dvb->nfeeds == 1) {
 310                ret = start_streaming(dvb);
 311                if (ret < 0)
 312                        rc = ret;
 313        }
 314
 315        mutex_unlock(&dvb->lock);
 316        return rc;
 317}
 318
 319static int stop_feed(struct dvb_demux_feed *feed)
 320{
 321        struct dvb_demux *demux = feed->demux;
 322        struct cx231xx_dvb *dvb = demux->priv;
 323        int err = 0;
 324
 325        mutex_lock(&dvb->lock);
 326        dvb->nfeeds--;
 327
 328        if (0 == dvb->nfeeds)
 329                err = stop_streaming(dvb);
 330
 331        mutex_unlock(&dvb->lock);
 332        return err;
 333}
 334
 335/* ------------------------------------------------------------------ */
 336static int cx231xx_dvb_bus_ctrl(struct dvb_frontend *fe, int acquire)
 337{
 338        struct cx231xx *dev = fe->dvb->priv;
 339
 340        if (acquire)
 341                return cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE);
 342        else
 343                return cx231xx_set_mode(dev, CX231XX_SUSPEND);
 344}
 345
 346/* ------------------------------------------------------------------ */
 347
 348static struct xc5000_config cnxt_rde250_tunerconfig = {
 349        .i2c_address = 0x61,
 350        .if_khz = 4000,
 351};
 352static struct xc5000_config cnxt_rdu250_tunerconfig = {
 353        .i2c_address = 0x61,
 354        .if_khz = 3250,
 355};
 356
 357/* ------------------------------------------------------------------ */
 358#if 0
 359static int attach_xc5000(u8 addr, struct cx231xx *dev)
 360{
 361
 362        struct dvb_frontend *fe;
 363        struct xc5000_config cfg;
 364
 365        memset(&cfg, 0, sizeof(cfg));
 366        cfg.i2c_adap = &dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap;
 367        cfg.i2c_addr = addr;
 368
 369        if (!dev->dvb->frontend) {
 370                printk(KERN_ERR "%s/2: dvb frontend not attached. "
 371                       "Can't attach xc5000\n", dev->name);
 372                return -EINVAL;
 373        }
 374
 375        fe = dvb_attach(xc5000_attach, dev->dvb->frontend, &cfg);
 376        if (!fe) {
 377                printk(KERN_ERR "%s/2: xc5000 attach failed\n", dev->name);
 378                dvb_frontend_detach(dev->dvb->frontend);
 379                dev->dvb->frontend = NULL;
 380                return -EINVAL;
 381        }
 382
 383        printk(KERN_INFO "%s/2: xc5000 attached\n", dev->name);
 384
 385        return 0;
 386}
 387#endif
 388
 389int cx231xx_set_analog_freq(struct cx231xx *dev, u32 freq)
 390{
 391        int status = 0;
 392
 393        if ((dev->dvb != NULL) && (dev->dvb->frontend != NULL)) {
 394
 395                struct dvb_tuner_ops *dops = &dev->dvb->frontend->ops.tuner_ops;
 396
 397                if (dops->set_analog_params != NULL) {
 398                        struct analog_parameters params;
 399
 400                        params.frequency = freq;
 401                        params.std = dev->norm;
 402                        params.mode = 0;        /* 0- Air; 1 - cable */
 403                        /*params.audmode = ;       */
 404
 405                        /* Set the analog parameters to set the frequency */
 406                        dops->set_analog_params(dev->dvb->frontend, &params);
 407                }
 408
 409        }
 410
 411        return status;
 412}
 413
 414int cx231xx_reset_analog_tuner(struct cx231xx *dev)
 415{
 416        int status = 0;
 417
 418        if ((dev->dvb != NULL) && (dev->dvb->frontend != NULL)) {
 419
 420                struct dvb_tuner_ops *dops = &dev->dvb->frontend->ops.tuner_ops;
 421
 422                if (dops->init != NULL && !dev->xc_fw_load_done) {
 423
 424                        cx231xx_info("Reloading firmware for XC5000\n");
 425                        status = dops->init(dev->dvb->frontend);
 426                        if (status == 0) {
 427                                dev->xc_fw_load_done = 1;
 428                                cx231xx_info
 429                                    ("XC5000 firmware download completed\n");
 430                        } else {
 431                                dev->xc_fw_load_done = 0;
 432                                cx231xx_info
 433                                    ("XC5000 firmware download failed !!!\n");
 434                        }
 435                }
 436
 437        }
 438
 439        return status;
 440}
 441
 442/* ------------------------------------------------------------------ */
 443
 444static int register_dvb(struct cx231xx_dvb *dvb,
 445                        struct module *module,
 446                        struct cx231xx *dev, struct device *device)
 447{
 448        int result;
 449
 450        mutex_init(&dvb->lock);
 451
 452        /* register adapter */
 453        result = dvb_register_adapter(&dvb->adapter, dev->name, module, device,
 454                                      adapter_nr);
 455        if (result < 0) {
 456                printk(KERN_WARNING
 457                       "%s: dvb_register_adapter failed (errno = %d)\n",
 458                       dev->name, result);
 459                goto fail_adapter;
 460        }
 461
 462        /* Ensure all frontends negotiate bus access */
 463        dvb->frontend->ops.ts_bus_ctrl = cx231xx_dvb_bus_ctrl;
 464
 465        dvb->adapter.priv = dev;
 466
 467        /* register frontend */
 468        result = dvb_register_frontend(&dvb->adapter, dvb->frontend);
 469        if (result < 0) {
 470                printk(KERN_WARNING
 471                       "%s: dvb_register_frontend failed (errno = %d)\n",
 472                       dev->name, result);
 473                goto fail_frontend;
 474        }
 475
 476        /* register demux stuff */
 477        dvb->demux.dmx.capabilities =
 478            DMX_TS_FILTERING | DMX_SECTION_FILTERING |
 479            DMX_MEMORY_BASED_FILTERING;
 480        dvb->demux.priv = dvb;
 481        dvb->demux.filternum = 256;
 482        dvb->demux.feednum = 256;
 483        dvb->demux.start_feed = start_feed;
 484        dvb->demux.stop_feed = stop_feed;
 485
 486        result = dvb_dmx_init(&dvb->demux);
 487        if (result < 0) {
 488                printk(KERN_WARNING "%s: dvb_dmx_init failed (errno = %d)\n",
 489                       dev->name, result);
 490                goto fail_dmx;
 491        }
 492
 493        dvb->dmxdev.filternum = 256;
 494        dvb->dmxdev.demux = &dvb->demux.dmx;
 495        dvb->dmxdev.capabilities = 0;
 496        result = dvb_dmxdev_init(&dvb->dmxdev, &dvb->adapter);
 497        if (result < 0) {
 498                printk(KERN_WARNING "%s: dvb_dmxdev_init failed (errno = %d)\n",
 499                       dev->name, result);
 500                goto fail_dmxdev;
 501        }
 502
 503        dvb->fe_hw.source = DMX_FRONTEND_0;
 504        result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_hw);
 505        if (result < 0) {
 506                printk(KERN_WARNING
 507                       "%s: add_frontend failed (DMX_FRONTEND_0, errno = %d)\n",
 508                       dev->name, result);
 509                goto fail_fe_hw;
 510        }
 511
 512        dvb->fe_mem.source = DMX_MEMORY_FE;
 513        result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_mem);
 514        if (result < 0) {
 515                printk(KERN_WARNING
 516                       "%s: add_frontend failed (DMX_MEMORY_FE, errno = %d)\n",
 517                       dev->name, result);
 518                goto fail_fe_mem;
 519        }
 520
 521        result = dvb->demux.dmx.connect_frontend(&dvb->demux.dmx, &dvb->fe_hw);
 522        if (result < 0) {
 523                printk(KERN_WARNING
 524                       "%s: connect_frontend failed (errno = %d)\n", dev->name,
 525                       result);
 526                goto fail_fe_conn;
 527        }
 528
 529        /* register network adapter */
 530        dvb_net_init(&dvb->adapter, &dvb->net, &dvb->demux.dmx);
 531        return 0;
 532
 533fail_fe_conn:
 534        dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem);
 535fail_fe_mem:
 536        dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw);
 537fail_fe_hw:
 538        dvb_dmxdev_release(&dvb->dmxdev);
 539fail_dmxdev:
 540        dvb_dmx_release(&dvb->demux);
 541fail_dmx:
 542        dvb_unregister_frontend(dvb->frontend);
 543fail_frontend:
 544        dvb_frontend_detach(dvb->frontend);
 545        dvb_unregister_adapter(&dvb->adapter);
 546fail_adapter:
 547        return result;
 548}
 549
 550static void unregister_dvb(struct cx231xx_dvb *dvb)
 551{
 552        dvb_net_release(&dvb->net);
 553        dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem);
 554        dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw);
 555        dvb_dmxdev_release(&dvb->dmxdev);
 556        dvb_dmx_release(&dvb->demux);
 557        dvb_unregister_frontend(dvb->frontend);
 558        dvb_frontend_detach(dvb->frontend);
 559        dvb_unregister_adapter(&dvb->adapter);
 560}
 561
 562static int dvb_init(struct cx231xx *dev)
 563{
 564        int result = 0;
 565        struct cx231xx_dvb *dvb;
 566
 567        if (!dev->board.has_dvb) {
 568                /* This device does not support the extension */
 569                return 0;
 570        }
 571
 572        dvb = kzalloc(sizeof(struct cx231xx_dvb), GFP_KERNEL);
 573
 574        if (dvb == NULL) {
 575                printk(KERN_INFO "cx231xx_dvb: memory allocation failed\n");
 576                return -ENOMEM;
 577        }
 578        dev->dvb = dvb;
 579        dev->cx231xx_set_analog_freq = cx231xx_set_analog_freq;
 580        dev->cx231xx_reset_analog_tuner = cx231xx_reset_analog_tuner;
 581
 582        mutex_lock(&dev->lock);
 583        cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE);
 584        cx231xx_demod_reset(dev);
 585        /* init frontend */
 586        switch (dev->model) {
 587        case CX231XX_BOARD_CNXT_CARRAERA:
 588        case CX231XX_BOARD_CNXT_RDE_250:
 589
 590                dev->dvb->frontend = dvb_attach(s5h1432_attach,
 591                                        &dvico_s5h1432_config,
 592                                        &dev->i2c_bus[dev->board.demod_i2c_master].i2c_adap);
 593
 594                if (dev->dvb->frontend == NULL) {
 595                        printk(DRIVER_NAME
 596                               ": Failed to attach s5h1432 front end\n");
 597                        result = -EINVAL;
 598                        goto out_free;
 599                }
 600
 601                /* define general-purpose callback pointer */
 602                dvb->frontend->callback = cx231xx_tuner_callback;
 603
 604                if (!dvb_attach(xc5000_attach, dev->dvb->frontend,
 605                               &dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap,
 606                               &cnxt_rde250_tunerconfig)) {
 607                        result = -EINVAL;
 608                        goto out_free;
 609                }
 610
 611                break;
 612        case CX231XX_BOARD_CNXT_SHELBY:
 613        case CX231XX_BOARD_CNXT_RDU_250:
 614
 615                dev->dvb->frontend = dvb_attach(s5h1411_attach,
 616                                               &xc5000_s5h1411_config,
 617                                               &dev->i2c_bus[dev->board.demod_i2c_master].i2c_adap);
 618
 619                if (dev->dvb->frontend == NULL) {
 620                        printk(DRIVER_NAME
 621                               ": Failed to attach s5h1411 front end\n");
 622                        result = -EINVAL;
 623                        goto out_free;
 624                }
 625
 626                /* define general-purpose callback pointer */
 627                dvb->frontend->callback = cx231xx_tuner_callback;
 628
 629                if (!dvb_attach(xc5000_attach, dev->dvb->frontend,
 630                               &dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap,
 631                               &cnxt_rdu250_tunerconfig)) {
 632                        result = -EINVAL;
 633                        goto out_free;
 634                }
 635                break;
 636        case CX231XX_BOARD_CNXT_RDE_253S:
 637
 638                dev->dvb->frontend = dvb_attach(s5h1432_attach,
 639                                        &dvico_s5h1432_config,
 640                                        &dev->i2c_bus[dev->board.demod_i2c_master].i2c_adap);
 641
 642                if (dev->dvb->frontend == NULL) {
 643                        printk(DRIVER_NAME
 644                               ": Failed to attach s5h1432 front end\n");
 645                        result = -EINVAL;
 646                        goto out_free;
 647                }
 648
 649                /* define general-purpose callback pointer */
 650                dvb->frontend->callback = cx231xx_tuner_callback;
 651
 652                if (!dvb_attach(tda18271_attach, dev->dvb->frontend,
 653                               0x60, &dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap,
 654                               &cnxt_rde253s_tunerconfig)) {
 655                        result = -EINVAL;
 656                        goto out_free;
 657                }
 658                break;
 659        case CX231XX_BOARD_CNXT_RDU_253S:
 660
 661                dev->dvb->frontend = dvb_attach(s5h1411_attach,
 662                                               &tda18271_s5h1411_config,
 663                                               &dev->i2c_bus[dev->board.demod_i2c_master].i2c_adap);
 664
 665                if (dev->dvb->frontend == NULL) {
 666                        printk(DRIVER_NAME
 667                               ": Failed to attach s5h1411 front end\n");
 668                        result = -EINVAL;
 669                        goto out_free;
 670                }
 671
 672                /* define general-purpose callback pointer */
 673                dvb->frontend->callback = cx231xx_tuner_callback;
 674
 675                if (!dvb_attach(tda18271_attach, dev->dvb->frontend,
 676                               0x60, &dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap,
 677                               &cnxt_rde253s_tunerconfig)) {
 678                        result = -EINVAL;
 679                        goto out_free;
 680                }
 681                break;
 682        case CX231XX_BOARD_HAUPPAUGE_EXETER:
 683
 684                printk(KERN_INFO "%s: looking for tuner / demod on i2c bus: %d\n",
 685                       __func__, i2c_adapter_id(&dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap));
 686
 687                dev->dvb->frontend = dvb_attach(lgdt3305_attach,
 688                                                &hcw_lgdt3305_config,
 689                                                &dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap);
 690
 691                if (dev->dvb->frontend == NULL) {
 692                        printk(DRIVER_NAME
 693                               ": Failed to attach LG3305 front end\n");
 694                        result = -EINVAL;
 695                        goto out_free;
 696                }
 697
 698                /* define general-purpose callback pointer */
 699                dvb->frontend->callback = cx231xx_tuner_callback;
 700
 701                dvb_attach(tda18271_attach, dev->dvb->frontend,
 702                           0x60, &dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap,
 703                           &hcw_tda18271_config);
 704                break;
 705
 706        case CX231XX_BOARD_PV_PLAYTV_USB_HYBRID:
 707        case CX231XX_BOARD_KWORLD_UB430_USB_HYBRID:
 708
 709                printk(KERN_INFO "%s: looking for demod on i2c bus: %d\n",
 710                       __func__, i2c_adapter_id(&dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap));
 711
 712                dev->dvb->frontend = dvb_attach(mb86a20s_attach,
 713                                                &pv_mb86a20s_config,
 714                                                &dev->i2c_bus[dev->board.demod_i2c_master].i2c_adap);
 715
 716                if (dev->dvb->frontend == NULL) {
 717                        printk(DRIVER_NAME
 718                               ": Failed to attach mb86a20s demod\n");
 719                        result = -EINVAL;
 720                        goto out_free;
 721                }
 722
 723                /* define general-purpose callback pointer */
 724                dvb->frontend->callback = cx231xx_tuner_callback;
 725
 726                dvb_attach(tda18271_attach, dev->dvb->frontend,
 727                           0x60, &dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap,
 728                           &pv_tda18271_config);
 729                break;
 730
 731        default:
 732                printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card"
 733                       " isn't supported yet\n", dev->name);
 734                break;
 735        }
 736        if (NULL == dvb->frontend) {
 737                printk(KERN_ERR
 738                       "%s/2: frontend initialization failed\n", dev->name);
 739                result = -EINVAL;
 740                goto out_free;
 741        }
 742
 743        /* register everything */
 744        result = register_dvb(dvb, THIS_MODULE, dev, &dev->udev->dev);
 745
 746        if (result < 0)
 747                goto out_free;
 748
 749
 750        printk(KERN_INFO "Successfully loaded cx231xx-dvb\n");
 751
 752ret:
 753        cx231xx_set_mode(dev, CX231XX_SUSPEND);
 754        mutex_unlock(&dev->lock);
 755        return result;
 756
 757out_free:
 758        kfree(dvb);
 759        dev->dvb = NULL;
 760        goto ret;
 761}
 762
 763static int dvb_fini(struct cx231xx *dev)
 764{
 765        if (!dev->board.has_dvb) {
 766                /* This device does not support the extension */
 767                return 0;
 768        }
 769
 770        if (dev->dvb) {
 771                unregister_dvb(dev->dvb);
 772                dev->dvb = NULL;
 773        }
 774
 775        return 0;
 776}
 777
 778static struct cx231xx_ops dvb_ops = {
 779        .id = CX231XX_DVB,
 780        .name = "Cx231xx dvb Extension",
 781        .init = dvb_init,
 782        .fini = dvb_fini,
 783};
 784
 785static int __init cx231xx_dvb_register(void)
 786{
 787        return cx231xx_register_extension(&dvb_ops);
 788}
 789
 790static void __exit cx231xx_dvb_unregister(void)
 791{
 792        cx231xx_unregister_extension(&dvb_ops);
 793}
 794
 795module_init(cx231xx_dvb_register);
 796module_exit(cx231xx_dvb_unregister);
 797