linux/drivers/media/usb/tm6000/tm6000-dvb.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 *  tm6000-dvb.c - dvb-t support for TM5600/TM6000/TM6010 USB video capture devices
   4 *
   5 *  Copyright (C) 2007 Michel Ludwig <michel.ludwig@gmail.com>
   6 */
   7
   8#include <linux/kernel.h>
   9#include <linux/slab.h>
  10#include <linux/usb.h>
  11
  12#include "tm6000.h"
  13#include "tm6000-regs.h"
  14
  15#include "zl10353.h"
  16
  17#include <media/tuner.h>
  18
  19#include "tuner-xc2028.h"
  20#include "xc5000.h"
  21
  22MODULE_DESCRIPTION("DVB driver extension module for tm5600/6000/6010 based TV cards");
  23MODULE_AUTHOR("Mauro Carvalho Chehab");
  24MODULE_LICENSE("GPL");
  25
  26static int debug;
  27
  28module_param(debug, int, 0644);
  29MODULE_PARM_DESC(debug, "enable debug message");
  30
  31static inline void print_err_status(struct tm6000_core *dev,
  32                                    int packet, int status)
  33{
  34        char *errmsg = "Unknown";
  35
  36        switch (status) {
  37        case -ENOENT:
  38                errmsg = "unlinked synchronously";
  39                break;
  40        case -ECONNRESET:
  41                errmsg = "unlinked asynchronously";
  42                break;
  43        case -ENOSR:
  44                errmsg = "Buffer error (overrun)";
  45                break;
  46        case -EPIPE:
  47                errmsg = "Stalled (device not responding)";
  48                break;
  49        case -EOVERFLOW:
  50                errmsg = "Babble (bad cable?)";
  51                break;
  52        case -EPROTO:
  53                errmsg = "Bit-stuff error (bad cable?)";
  54                break;
  55        case -EILSEQ:
  56                errmsg = "CRC/Timeout (could be anything)";
  57                break;
  58        case -ETIME:
  59                errmsg = "Device does not respond";
  60                break;
  61        }
  62        if (packet < 0) {
  63                dprintk(dev, 1, "URB status %d [%s].\n",
  64                        status, errmsg);
  65        } else {
  66                dprintk(dev, 1, "URB packet %d, status %d [%s].\n",
  67                        packet, status, errmsg);
  68        }
  69}
  70
  71static void tm6000_urb_received(struct urb *urb)
  72{
  73        int ret;
  74        struct tm6000_core *dev = urb->context;
  75
  76        switch (urb->status) {
  77        case 0:
  78        case -ETIMEDOUT:
  79                break;
  80        case -ENOENT:
  81        case -ECONNRESET:
  82        case -ESHUTDOWN:
  83                return;
  84        default:
  85                print_err_status(dev, 0, urb->status);
  86        }
  87
  88        if (urb->actual_length > 0)
  89                dvb_dmx_swfilter(&dev->dvb->demux, urb->transfer_buffer,
  90                                                   urb->actual_length);
  91
  92        if (dev->dvb->streams > 0) {
  93                ret = usb_submit_urb(urb, GFP_ATOMIC);
  94                if (ret < 0) {
  95                        printk(KERN_ERR "tm6000:  error %s\n", __func__);
  96                        kfree(urb->transfer_buffer);
  97                        usb_free_urb(urb);
  98                        dev->dvb->bulk_urb = NULL;
  99                }
 100        }
 101}
 102
 103static int tm6000_start_stream(struct tm6000_core *dev)
 104{
 105        int ret;
 106        unsigned int pipe, size;
 107        struct tm6000_dvb *dvb = dev->dvb;
 108
 109        printk(KERN_INFO "tm6000: got start stream request %s\n", __func__);
 110
 111        if (dev->mode != TM6000_MODE_DIGITAL) {
 112                tm6000_init_digital_mode(dev);
 113                dev->mode = TM6000_MODE_DIGITAL;
 114        }
 115
 116        dvb->bulk_urb = usb_alloc_urb(0, GFP_KERNEL);
 117        if (!dvb->bulk_urb)
 118                return -ENOMEM;
 119
 120        pipe = usb_rcvbulkpipe(dev->udev, dev->bulk_in.endp->desc.bEndpointAddress
 121                                                          & USB_ENDPOINT_NUMBER_MASK);
 122
 123        size = usb_maxpacket(dev->udev, pipe, usb_pipeout(pipe));
 124        size = size * 15; /* 512 x 8 or 12 or 15 */
 125
 126        dvb->bulk_urb->transfer_buffer = kzalloc(size, GFP_KERNEL);
 127        if (!dvb->bulk_urb->transfer_buffer) {
 128                usb_free_urb(dvb->bulk_urb);
 129                dvb->bulk_urb = NULL;
 130                return -ENOMEM;
 131        }
 132
 133        usb_fill_bulk_urb(dvb->bulk_urb, dev->udev, pipe,
 134                                                 dvb->bulk_urb->transfer_buffer,
 135                                                 size,
 136                                                 tm6000_urb_received, dev);
 137
 138        ret = usb_clear_halt(dev->udev, pipe);
 139        if (ret < 0) {
 140                printk(KERN_ERR "tm6000: error %i in %s during pipe reset\n",
 141                                                        ret, __func__);
 142
 143                kfree(dvb->bulk_urb->transfer_buffer);
 144                usb_free_urb(dvb->bulk_urb);
 145                dvb->bulk_urb = NULL;
 146                return ret;
 147        } else
 148                printk(KERN_ERR "tm6000: pipe reset\n");
 149
 150/*      mutex_lock(&tm6000_driver.open_close_mutex); */
 151        ret = usb_submit_urb(dvb->bulk_urb, GFP_ATOMIC);
 152
 153/*      mutex_unlock(&tm6000_driver.open_close_mutex); */
 154        if (ret) {
 155                printk(KERN_ERR "tm6000: submit of urb failed (error=%i)\n",
 156                                                                        ret);
 157
 158                kfree(dvb->bulk_urb->transfer_buffer);
 159                usb_free_urb(dvb->bulk_urb);
 160                dvb->bulk_urb = NULL;
 161                return ret;
 162        }
 163
 164        return 0;
 165}
 166
 167static void tm6000_stop_stream(struct tm6000_core *dev)
 168{
 169        struct tm6000_dvb *dvb = dev->dvb;
 170
 171        if (dvb->bulk_urb) {
 172                printk(KERN_INFO "urb killing\n");
 173                usb_kill_urb(dvb->bulk_urb);
 174                printk(KERN_INFO "urb buffer free\n");
 175                kfree(dvb->bulk_urb->transfer_buffer);
 176                usb_free_urb(dvb->bulk_urb);
 177                dvb->bulk_urb = NULL;
 178        }
 179}
 180
 181static int tm6000_start_feed(struct dvb_demux_feed *feed)
 182{
 183        struct dvb_demux *demux = feed->demux;
 184        struct tm6000_core *dev = demux->priv;
 185        struct tm6000_dvb *dvb = dev->dvb;
 186        printk(KERN_INFO "tm6000: got start feed request %s\n", __func__);
 187
 188        mutex_lock(&dvb->mutex);
 189        if (dvb->streams == 0) {
 190                dvb->streams = 1;
 191/*              mutex_init(&tm6000_dev->streming_mutex); */
 192                tm6000_start_stream(dev);
 193        } else
 194                ++(dvb->streams);
 195        mutex_unlock(&dvb->mutex);
 196
 197        return 0;
 198}
 199
 200static int tm6000_stop_feed(struct dvb_demux_feed *feed)
 201{
 202        struct dvb_demux *demux = feed->demux;
 203        struct tm6000_core *dev = demux->priv;
 204        struct tm6000_dvb *dvb = dev->dvb;
 205
 206        printk(KERN_INFO "tm6000: got stop feed request %s\n", __func__);
 207
 208        mutex_lock(&dvb->mutex);
 209
 210        printk(KERN_INFO "stream %#x\n", dvb->streams);
 211        --(dvb->streams);
 212        if (dvb->streams == 0) {
 213                printk(KERN_INFO "stop stream\n");
 214                tm6000_stop_stream(dev);
 215/*              mutex_destroy(&tm6000_dev->streaming_mutex); */
 216        }
 217        mutex_unlock(&dvb->mutex);
 218/*      mutex_destroy(&tm6000_dev->streaming_mutex); */
 219
 220        return 0;
 221}
 222
 223static int tm6000_dvb_attach_frontend(struct tm6000_core *dev)
 224{
 225        struct tm6000_dvb *dvb = dev->dvb;
 226
 227        if (dev->caps.has_zl10353) {
 228                struct zl10353_config config = {
 229                                     .demod_address = dev->demod_addr,
 230                                     .no_tuner = 1,
 231                                     .parallel_ts = 1,
 232                                     .if2 = 45700,
 233                                     .disable_i2c_gate_ctrl = 1,
 234                                    };
 235
 236                dvb->frontend = dvb_attach(zl10353_attach, &config,
 237                                                           &dev->i2c_adap);
 238        } else {
 239                printk(KERN_ERR "tm6000: no frontend defined for the device!\n");
 240                return -1;
 241        }
 242
 243        return (!dvb->frontend) ? -1 : 0;
 244}
 245
 246DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
 247
 248static int register_dvb(struct tm6000_core *dev)
 249{
 250        int ret = -1;
 251        struct tm6000_dvb *dvb = dev->dvb;
 252
 253        mutex_init(&dvb->mutex);
 254
 255        dvb->streams = 0;
 256
 257        /* attach the frontend */
 258        ret = tm6000_dvb_attach_frontend(dev);
 259        if (ret < 0) {
 260                printk(KERN_ERR "tm6000: couldn't attach the frontend!\n");
 261                goto err;
 262        }
 263
 264        ret = dvb_register_adapter(&dvb->adapter, "Trident TVMaster 6000 DVB-T",
 265                                        THIS_MODULE, &dev->udev->dev, adapter_nr);
 266        if (ret < 0) {
 267                pr_err("tm6000: couldn't register the adapter!\n");
 268                goto err;
 269        }
 270
 271        dvb->adapter.priv = dev;
 272
 273        if (dvb->frontend) {
 274                switch (dev->tuner_type) {
 275                case TUNER_XC2028: {
 276                        struct xc2028_config cfg = {
 277                                .i2c_adap = &dev->i2c_adap,
 278                                .i2c_addr = dev->tuner_addr,
 279                        };
 280
 281                        dvb->frontend->callback = tm6000_tuner_callback;
 282                        ret = dvb_register_frontend(&dvb->adapter, dvb->frontend);
 283                        if (ret < 0) {
 284                                printk(KERN_ERR
 285                                        "tm6000: couldn't register frontend\n");
 286                                goto adapter_err;
 287                        }
 288
 289                        if (!dvb_attach(xc2028_attach, dvb->frontend, &cfg)) {
 290                                printk(KERN_ERR "tm6000: couldn't register frontend (xc3028)\n");
 291                                ret = -EINVAL;
 292                                goto frontend_err;
 293                        }
 294                        printk(KERN_INFO "tm6000: XC2028/3028 asked to be attached to frontend!\n");
 295                        break;
 296                        }
 297                case TUNER_XC5000: {
 298                        struct xc5000_config cfg = {
 299                                .i2c_address = dev->tuner_addr,
 300                        };
 301
 302                        dvb->frontend->callback = tm6000_xc5000_callback;
 303                        ret = dvb_register_frontend(&dvb->adapter, dvb->frontend);
 304                        if (ret < 0) {
 305                                printk(KERN_ERR
 306                                        "tm6000: couldn't register frontend\n");
 307                                goto adapter_err;
 308                        }
 309
 310                        if (!dvb_attach(xc5000_attach, dvb->frontend, &dev->i2c_adap, &cfg)) {
 311                                printk(KERN_ERR "tm6000: couldn't register frontend (xc5000)\n");
 312                                ret = -EINVAL;
 313                                goto frontend_err;
 314                        }
 315                        printk(KERN_INFO "tm6000: XC5000 asked to be attached to frontend!\n");
 316                        break;
 317                        }
 318                }
 319        } else
 320                printk(KERN_ERR "tm6000: no frontend found\n");
 321
 322        dvb->demux.dmx.capabilities = DMX_TS_FILTERING | DMX_SECTION_FILTERING
 323                                                            | DMX_MEMORY_BASED_FILTERING;
 324        dvb->demux.priv = dev;
 325        dvb->demux.filternum = 8;
 326        dvb->demux.feednum = 8;
 327        dvb->demux.start_feed = tm6000_start_feed;
 328        dvb->demux.stop_feed = tm6000_stop_feed;
 329        dvb->demux.write_to_decoder = NULL;
 330        ret = dvb_dmx_init(&dvb->demux);
 331        if (ret < 0) {
 332                printk(KERN_ERR "tm6000: dvb_dmx_init failed (errno = %d)\n", ret);
 333                goto frontend_err;
 334        }
 335
 336        dvb->dmxdev.filternum = dev->dvb->demux.filternum;
 337        dvb->dmxdev.demux = &dev->dvb->demux.dmx;
 338        dvb->dmxdev.capabilities = 0;
 339
 340        ret =  dvb_dmxdev_init(&dvb->dmxdev, &dvb->adapter);
 341        if (ret < 0) {
 342                printk(KERN_ERR "tm6000: dvb_dmxdev_init failed (errno = %d)\n", ret);
 343                goto dvb_dmx_err;
 344        }
 345
 346        return 0;
 347
 348dvb_dmx_err:
 349        dvb_dmx_release(&dvb->demux);
 350frontend_err:
 351        if (dvb->frontend) {
 352                dvb_unregister_frontend(dvb->frontend);
 353                dvb_frontend_detach(dvb->frontend);
 354        }
 355adapter_err:
 356        dvb_unregister_adapter(&dvb->adapter);
 357err:
 358        return ret;
 359}
 360
 361static void unregister_dvb(struct tm6000_core *dev)
 362{
 363        struct tm6000_dvb *dvb = dev->dvb;
 364
 365        if (dvb->bulk_urb) {
 366                struct urb *bulk_urb = dvb->bulk_urb;
 367
 368                kfree(bulk_urb->transfer_buffer);
 369                bulk_urb->transfer_buffer = NULL;
 370                usb_unlink_urb(bulk_urb);
 371                usb_free_urb(bulk_urb);
 372        }
 373
 374/*      mutex_lock(&tm6000_driver.open_close_mutex); */
 375        if (dvb->frontend) {
 376                dvb_unregister_frontend(dvb->frontend);
 377                dvb_frontend_detach(dvb->frontend);
 378        }
 379
 380        dvb_dmxdev_release(&dvb->dmxdev);
 381        dvb_dmx_release(&dvb->demux);
 382        dvb_unregister_adapter(&dvb->adapter);
 383        mutex_destroy(&dvb->mutex);
 384/*      mutex_unlock(&tm6000_driver.open_close_mutex); */
 385}
 386
 387static int dvb_init(struct tm6000_core *dev)
 388{
 389        struct tm6000_dvb *dvb;
 390        int rc;
 391
 392        if (!dev)
 393                return 0;
 394
 395        if (!dev->caps.has_dvb)
 396                return 0;
 397
 398        if (dev->udev->speed == USB_SPEED_FULL) {
 399                printk(KERN_INFO "This USB2.0 device cannot be run on a USB1.1 port. (it lacks a hardware PID filter)\n");
 400                return 0;
 401        }
 402
 403        dvb = kzalloc(sizeof(struct tm6000_dvb), GFP_KERNEL);
 404        if (!dvb)
 405                return -ENOMEM;
 406
 407        dev->dvb = dvb;
 408
 409        rc = register_dvb(dev);
 410        if (rc < 0) {
 411                kfree(dvb);
 412                dev->dvb = NULL;
 413                return 0;
 414        }
 415
 416        return 0;
 417}
 418
 419static int dvb_fini(struct tm6000_core *dev)
 420{
 421        if (!dev)
 422                return 0;
 423
 424        if (!dev->caps.has_dvb)
 425                return 0;
 426
 427        if (dev->dvb) {
 428                unregister_dvb(dev);
 429                kfree(dev->dvb);
 430                dev->dvb = NULL;
 431        }
 432
 433        return 0;
 434}
 435
 436static struct tm6000_ops dvb_ops = {
 437        .type   = TM6000_DVB,
 438        .name   = "TM6000 dvb Extension",
 439        .init   = dvb_init,
 440        .fini   = dvb_fini,
 441};
 442
 443static int __init tm6000_dvb_register(void)
 444{
 445        return tm6000_register_extension(&dvb_ops);
 446}
 447
 448static void __exit tm6000_dvb_unregister(void)
 449{
 450        tm6000_unregister_extension(&dvb_ops);
 451}
 452
 453module_init(tm6000_dvb_register);
 454module_exit(tm6000_dvb_unregister);
 455