linux/drivers/media/video/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/usb.h>
  24
  25#include "cx231xx.h"
  26#include <media/v4l2-common.h>
  27#include <media/videobuf-vmalloc.h>
  28
  29#include "xc5000.h"
  30#include "dvb_dummy_fe.h"
  31
  32MODULE_DESCRIPTION("driver for cx231xx based DVB cards");
  33MODULE_AUTHOR("Srinivasa Deevi <srinivasa.deevi@conexant.com>");
  34MODULE_LICENSE("GPL");
  35
  36static unsigned int debug;
  37module_param(debug, int, 0644);
  38MODULE_PARM_DESC(debug, "enable debug messages [dvb]");
  39
  40DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
  41
  42#define dprintk(level, fmt, arg...) do {                        \
  43if (debug >= level)                                             \
  44        printk(KERN_DEBUG "%s/2-dvb: " fmt, dev->name, ## arg); \
  45} while (0)
  46
  47#define CX231XX_DVB_NUM_BUFS 5
  48#define CX231XX_DVB_MAX_PACKETSIZE 564
  49#define CX231XX_DVB_MAX_PACKETS 64
  50
  51struct cx231xx_dvb {
  52        struct dvb_frontend *frontend;
  53
  54        /* feed count management */
  55        struct mutex lock;
  56        int nfeeds;
  57
  58        /* general boilerplate stuff */
  59        struct dvb_adapter adapter;
  60        struct dvb_demux demux;
  61        struct dmxdev dmxdev;
  62        struct dmx_frontend fe_hw;
  63        struct dmx_frontend fe_mem;
  64        struct dvb_net net;
  65};
  66
  67static inline void print_err_status(struct cx231xx *dev, int packet, int status)
  68{
  69        char *errmsg = "Unknown";
  70
  71        switch (status) {
  72        case -ENOENT:
  73                errmsg = "unlinked synchronuously";
  74                break;
  75        case -ECONNRESET:
  76                errmsg = "unlinked asynchronuously";
  77                break;
  78        case -ENOSR:
  79                errmsg = "Buffer error (overrun)";
  80                break;
  81        case -EPIPE:
  82                errmsg = "Stalled (device not responding)";
  83                break;
  84        case -EOVERFLOW:
  85                errmsg = "Babble (bad cable?)";
  86                break;
  87        case -EPROTO:
  88                errmsg = "Bit-stuff error (bad cable?)";
  89                break;
  90        case -EILSEQ:
  91                errmsg = "CRC/Timeout (could be anything)";
  92                break;
  93        case -ETIME:
  94                errmsg = "Device does not respond";
  95                break;
  96        }
  97        if (packet < 0) {
  98                dprintk(1, "URB status %d [%s].\n", status, errmsg);
  99        } else {
 100                dprintk(1, "URB packet %d, status %d [%s].\n",
 101                        packet, status, errmsg);
 102        }
 103}
 104
 105static inline int dvb_isoc_copy(struct cx231xx *dev, struct urb *urb)
 106{
 107        int i;
 108
 109        if (!dev)
 110                return 0;
 111
 112        if ((dev->state & DEV_DISCONNECTED) || (dev->state & DEV_MISCONFIGURED))
 113                return 0;
 114
 115        if (urb->status < 0) {
 116                print_err_status(dev, -1, urb->status);
 117                if (urb->status == -ENOENT)
 118                        return 0;
 119        }
 120
 121        for (i = 0; i < urb->number_of_packets; i++) {
 122                int status = urb->iso_frame_desc[i].status;
 123
 124                if (status < 0) {
 125                        print_err_status(dev, i, status);
 126                        if (urb->iso_frame_desc[i].status != -EPROTO)
 127                                continue;
 128                }
 129
 130                dvb_dmx_swfilter(&dev->dvb->demux, urb->transfer_buffer +
 131                                 urb->iso_frame_desc[i].offset,
 132                                 urb->iso_frame_desc[i].actual_length);
 133        }
 134
 135        return 0;
 136}
 137
 138static int start_streaming(struct cx231xx_dvb *dvb)
 139{
 140        int rc;
 141        struct cx231xx *dev = dvb->adapter.priv;
 142
 143        usb_set_interface(dev->udev, 0, 1);
 144        rc = cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE);
 145        if (rc < 0)
 146                return rc;
 147
 148        return cx231xx_init_isoc(dev, CX231XX_DVB_MAX_PACKETS,
 149                                 CX231XX_DVB_NUM_BUFS,
 150                                 CX231XX_DVB_MAX_PACKETSIZE, dvb_isoc_copy);
 151}
 152
 153static int stop_streaming(struct cx231xx_dvb *dvb)
 154{
 155        struct cx231xx *dev = dvb->adapter.priv;
 156
 157        cx231xx_uninit_isoc(dev);
 158
 159        cx231xx_set_mode(dev, CX231XX_SUSPEND);
 160
 161        return 0;
 162}
 163
 164static int start_feed(struct dvb_demux_feed *feed)
 165{
 166        struct dvb_demux *demux = feed->demux;
 167        struct cx231xx_dvb *dvb = demux->priv;
 168        int rc, ret;
 169
 170        if (!demux->dmx.frontend)
 171                return -EINVAL;
 172
 173        mutex_lock(&dvb->lock);
 174        dvb->nfeeds++;
 175        rc = dvb->nfeeds;
 176
 177        if (dvb->nfeeds == 1) {
 178                ret = start_streaming(dvb);
 179                if (ret < 0)
 180                        rc = ret;
 181        }
 182
 183        mutex_unlock(&dvb->lock);
 184        return rc;
 185}
 186
 187static int stop_feed(struct dvb_demux_feed *feed)
 188{
 189        struct dvb_demux *demux = feed->demux;
 190        struct cx231xx_dvb *dvb = demux->priv;
 191        int err = 0;
 192
 193        mutex_lock(&dvb->lock);
 194        dvb->nfeeds--;
 195
 196        if (0 == dvb->nfeeds)
 197                err = stop_streaming(dvb);
 198
 199        mutex_unlock(&dvb->lock);
 200        return err;
 201}
 202
 203/* ------------------------------------------------------------------ */
 204static int cx231xx_dvb_bus_ctrl(struct dvb_frontend *fe, int acquire)
 205{
 206        struct cx231xx *dev = fe->dvb->priv;
 207
 208        if (acquire)
 209                return cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE);
 210        else
 211                return cx231xx_set_mode(dev, CX231XX_SUSPEND);
 212}
 213
 214/* ------------------------------------------------------------------ */
 215
 216static struct xc5000_config cnxt_rde250_tunerconfig = {
 217        .i2c_address = 0x61,
 218        .if_khz = 5380,
 219};
 220
 221/* ------------------------------------------------------------------ */
 222#if 0
 223static int attach_xc5000(u8 addr, struct cx231xx *dev)
 224{
 225
 226        struct dvb_frontend *fe;
 227        struct xc5000_config cfg;
 228
 229        memset(&cfg, 0, sizeof(cfg));
 230        cfg.i2c_adap = &dev->i2c_bus[1].i2c_adap;
 231        cfg.i2c_addr = addr;
 232
 233        if (!dev->dvb->frontend) {
 234                printk(KERN_ERR "%s/2: dvb frontend not attached. "
 235                       "Can't attach xc5000\n", dev->name);
 236                return -EINVAL;
 237        }
 238
 239        fe = dvb_attach(xc5000_attach, dev->dvb->frontend, &cfg);
 240        if (!fe) {
 241                printk(KERN_ERR "%s/2: xc5000 attach failed\n", dev->name);
 242                dvb_frontend_detach(dev->dvb->frontend);
 243                dev->dvb->frontend = NULL;
 244                return -EINVAL;
 245        }
 246
 247        printk(KERN_INFO "%s/2: xc5000 attached\n", dev->name);
 248
 249        return 0;
 250}
 251#endif
 252
 253int cx231xx_set_analog_freq(struct cx231xx *dev, u32 freq)
 254{
 255        int status = 0;
 256
 257        if ((dev->dvb != NULL) && (dev->dvb->frontend != NULL)) {
 258
 259                struct dvb_tuner_ops *dops = &dev->dvb->frontend->ops.tuner_ops;
 260
 261                if (dops->set_analog_params != NULL) {
 262                        struct analog_parameters params;
 263
 264                        params.frequency = freq;
 265                        params.std = dev->norm;
 266                        params.mode = 0;        /* 0- Air; 1 - cable */
 267                        /*params.audmode = ;       */
 268
 269                        /* Set the analog parameters to set the frequency */
 270                        cx231xx_info("Setting Frequency for XC5000\n");
 271                        dops->set_analog_params(dev->dvb->frontend, &params);
 272                }
 273
 274        }
 275
 276        return status;
 277}
 278
 279int cx231xx_reset_analog_tuner(struct cx231xx *dev)
 280{
 281        int status = 0;
 282
 283        if ((dev->dvb != NULL) && (dev->dvb->frontend != NULL)) {
 284
 285                struct dvb_tuner_ops *dops = &dev->dvb->frontend->ops.tuner_ops;
 286
 287                if (dops->init != NULL && !dev->xc_fw_load_done) {
 288
 289                        cx231xx_info("Reloading firmware for XC5000\n");
 290                        status = dops->init(dev->dvb->frontend);
 291                        if (status == 0) {
 292                                dev->xc_fw_load_done = 1;
 293                                cx231xx_info
 294                                    ("XC5000 firmware download completed\n");
 295                        } else {
 296                                dev->xc_fw_load_done = 0;
 297                                cx231xx_info
 298                                    ("XC5000 firmware download failed !!!\n");
 299                        }
 300                }
 301
 302        }
 303
 304        return status;
 305}
 306
 307/* ------------------------------------------------------------------ */
 308
 309static int register_dvb(struct cx231xx_dvb *dvb,
 310                        struct module *module,
 311                        struct cx231xx *dev, struct device *device)
 312{
 313        int result;
 314
 315        mutex_init(&dvb->lock);
 316
 317        /* register adapter */
 318        result = dvb_register_adapter(&dvb->adapter, dev->name, module, device,
 319                                      adapter_nr);
 320        if (result < 0) {
 321                printk(KERN_WARNING
 322                       "%s: dvb_register_adapter failed (errno = %d)\n",
 323                       dev->name, result);
 324                goto fail_adapter;
 325        }
 326
 327        /* Ensure all frontends negotiate bus access */
 328        dvb->frontend->ops.ts_bus_ctrl = cx231xx_dvb_bus_ctrl;
 329
 330        dvb->adapter.priv = dev;
 331
 332        /* register frontend */
 333        result = dvb_register_frontend(&dvb->adapter, dvb->frontend);
 334        if (result < 0) {
 335                printk(KERN_WARNING
 336                       "%s: dvb_register_frontend failed (errno = %d)\n",
 337                       dev->name, result);
 338                goto fail_frontend;
 339        }
 340
 341        /* register demux stuff */
 342        dvb->demux.dmx.capabilities =
 343            DMX_TS_FILTERING | DMX_SECTION_FILTERING |
 344            DMX_MEMORY_BASED_FILTERING;
 345        dvb->demux.priv = dvb;
 346        dvb->demux.filternum = 256;
 347        dvb->demux.feednum = 256;
 348        dvb->demux.start_feed = start_feed;
 349        dvb->demux.stop_feed = stop_feed;
 350
 351        result = dvb_dmx_init(&dvb->demux);
 352        if (result < 0) {
 353                printk(KERN_WARNING "%s: dvb_dmx_init failed (errno = %d)\n",
 354                       dev->name, result);
 355                goto fail_dmx;
 356        }
 357
 358        dvb->dmxdev.filternum = 256;
 359        dvb->dmxdev.demux = &dvb->demux.dmx;
 360        dvb->dmxdev.capabilities = 0;
 361        result = dvb_dmxdev_init(&dvb->dmxdev, &dvb->adapter);
 362        if (result < 0) {
 363                printk(KERN_WARNING "%s: dvb_dmxdev_init failed (errno = %d)\n",
 364                       dev->name, result);
 365                goto fail_dmxdev;
 366        }
 367
 368        dvb->fe_hw.source = DMX_FRONTEND_0;
 369        result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_hw);
 370        if (result < 0) {
 371                printk(KERN_WARNING
 372                       "%s: add_frontend failed (DMX_FRONTEND_0, errno = %d)\n",
 373                       dev->name, result);
 374                goto fail_fe_hw;
 375        }
 376
 377        dvb->fe_mem.source = DMX_MEMORY_FE;
 378        result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_mem);
 379        if (result < 0) {
 380                printk(KERN_WARNING
 381                       "%s: add_frontend failed (DMX_MEMORY_FE, errno = %d)\n",
 382                       dev->name, result);
 383                goto fail_fe_mem;
 384        }
 385
 386        result = dvb->demux.dmx.connect_frontend(&dvb->demux.dmx, &dvb->fe_hw);
 387        if (result < 0) {
 388                printk(KERN_WARNING
 389                       "%s: connect_frontend failed (errno = %d)\n", dev->name,
 390                       result);
 391                goto fail_fe_conn;
 392        }
 393
 394        /* register network adapter */
 395        dvb_net_init(&dvb->adapter, &dvb->net, &dvb->demux.dmx);
 396        return 0;
 397
 398fail_fe_conn:
 399        dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem);
 400fail_fe_mem:
 401        dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw);
 402fail_fe_hw:
 403        dvb_dmxdev_release(&dvb->dmxdev);
 404fail_dmxdev:
 405        dvb_dmx_release(&dvb->demux);
 406fail_dmx:
 407        dvb_unregister_frontend(dvb->frontend);
 408fail_frontend:
 409        dvb_frontend_detach(dvb->frontend);
 410        dvb_unregister_adapter(&dvb->adapter);
 411fail_adapter:
 412        return result;
 413}
 414
 415static void unregister_dvb(struct cx231xx_dvb *dvb)
 416{
 417        dvb_net_release(&dvb->net);
 418        dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem);
 419        dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw);
 420        dvb_dmxdev_release(&dvb->dmxdev);
 421        dvb_dmx_release(&dvb->demux);
 422        dvb_unregister_frontend(dvb->frontend);
 423        dvb_frontend_detach(dvb->frontend);
 424        dvb_unregister_adapter(&dvb->adapter);
 425}
 426
 427static int dvb_init(struct cx231xx *dev)
 428{
 429        int result = 0;
 430        struct cx231xx_dvb *dvb;
 431
 432        if (!dev->board.has_dvb) {
 433                /* This device does not support the extension */
 434                return 0;
 435        }
 436
 437        dvb = kzalloc(sizeof(struct cx231xx_dvb), GFP_KERNEL);
 438
 439        if (dvb == NULL) {
 440                printk(KERN_INFO "cx231xx_dvb: memory allocation failed\n");
 441                return -ENOMEM;
 442        }
 443        dev->dvb = dvb;
 444        dev->cx231xx_set_analog_freq = cx231xx_set_analog_freq;
 445        dev->cx231xx_reset_analog_tuner = cx231xx_reset_analog_tuner;
 446
 447        cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE);
 448        /* init frontend */
 449        switch (dev->model) {
 450        case CX231XX_BOARD_CNXT_RDE_250:
 451
 452                /* dev->dvb->frontend = dvb_attach(s5h1411_attach,
 453                   &dvico_s5h1411_config,
 454                   &dev->i2c_bus[1].i2c_adap); */
 455                dev->dvb->frontend = dvb_attach(dvb_dummy_fe_ofdm_attach);
 456
 457                if (dev->dvb->frontend == NULL) {
 458                        printk(DRIVER_NAME
 459                               ": Failed to attach dummy front end\n");
 460                        result = -EINVAL;
 461                        goto out_free;
 462                }
 463
 464                /* define general-purpose callback pointer */
 465                dvb->frontend->callback = cx231xx_tuner_callback;
 466
 467                if (dvb_attach(xc5000_attach, dev->dvb->frontend,
 468                               &dev->i2c_bus[1].i2c_adap,
 469                               &cnxt_rde250_tunerconfig) < 0) {
 470                        result = -EINVAL;
 471                        goto out_free;
 472                }
 473
 474                break;
 475        case CX231XX_BOARD_CNXT_RDU_250:
 476
 477                dev->dvb->frontend = dvb_attach(dvb_dummy_fe_ofdm_attach);
 478
 479                if (dev->dvb->frontend == NULL) {
 480                        printk(DRIVER_NAME
 481                               ": Failed to attach dummy front end\n");
 482                        result = -EINVAL;
 483                        goto out_free;
 484                }
 485
 486                /* define general-purpose callback pointer */
 487                dvb->frontend->callback = cx231xx_tuner_callback;
 488
 489                if (dvb_attach(xc5000_attach, dev->dvb->frontend,
 490                               &dev->i2c_bus[1].i2c_adap,
 491                               &cnxt_rde250_tunerconfig) < 0) {
 492                        result = -EINVAL;
 493                        goto out_free;
 494                }
 495                break;
 496
 497        default:
 498                printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card"
 499                       " isn't supported yet\n", dev->name);
 500                break;
 501        }
 502        if (NULL == dvb->frontend) {
 503                printk(KERN_ERR
 504                       "%s/2: frontend initialization failed\n", dev->name);
 505                result = -EINVAL;
 506                goto out_free;
 507        }
 508
 509        /* register everything */
 510        result = register_dvb(dvb, THIS_MODULE, dev, &dev->udev->dev);
 511
 512        if (result < 0)
 513                goto out_free;
 514
 515        cx231xx_set_mode(dev, CX231XX_SUSPEND);
 516        printk(KERN_INFO "Successfully loaded cx231xx-dvb\n");
 517        return 0;
 518
 519out_free:
 520        cx231xx_set_mode(dev, CX231XX_SUSPEND);
 521        kfree(dvb);
 522        dev->dvb = NULL;
 523        return result;
 524}
 525
 526static int dvb_fini(struct cx231xx *dev)
 527{
 528        if (!dev->board.has_dvb) {
 529                /* This device does not support the extension */
 530                return 0;
 531        }
 532
 533        if (dev->dvb) {
 534                unregister_dvb(dev->dvb);
 535                dev->dvb = NULL;
 536        }
 537
 538        return 0;
 539}
 540
 541static struct cx231xx_ops dvb_ops = {
 542        .id = CX231XX_DVB,
 543        .name = "Cx231xx dvb Extension",
 544        .init = dvb_init,
 545        .fini = dvb_fini,
 546};
 547
 548static int __init cx231xx_dvb_register(void)
 549{
 550        return cx231xx_register_extension(&dvb_ops);
 551}
 552
 553static void __exit cx231xx_dvb_unregister(void)
 554{
 555        cx231xx_unregister_extension(&dvb_ops);
 556}
 557
 558module_init(cx231xx_dvb_register);
 559module_exit(cx231xx_dvb_unregister);
 560