linux/drivers/media/video/cx88/cx88-mpeg.c
<<
>>
Prefs
   1/*
   2 *
   3 *  Support for the mpeg transport stream transfers
   4 *  PCI function #2 of the cx2388x.
   5 *
   6 *    (c) 2004 Jelle Foks <jelle@foks.us>
   7 *    (c) 2004 Chris Pascoe <c.pascoe@itee.uq.edu.au>
   8 *    (c) 2004 Gerd Knorr <kraxel@bytesex.org>
   9 *
  10 *  This program is free software; you can redistribute it and/or modify
  11 *  it under the terms of the GNU General Public License as published by
  12 *  the Free Software Foundation; either version 2 of the License, or
  13 *  (at your option) any later version.
  14 *
  15 *  This program is distributed in the hope that it will be useful,
  16 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  17 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18 *  GNU General Public License for more details.
  19 *
  20 *  You should have received a copy of the GNU General Public License
  21 *  along with this program; if not, write to the Free Software
  22 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  23 */
  24
  25#include <linux/module.h>
  26#include <linux/slab.h>
  27#include <linux/init.h>
  28#include <linux/device.h>
  29#include <linux/dma-mapping.h>
  30#include <linux/interrupt.h>
  31#include <asm/delay.h>
  32
  33#include "cx88.h"
  34
  35/* ------------------------------------------------------------------ */
  36
  37MODULE_DESCRIPTION("mpeg driver for cx2388x based TV cards");
  38MODULE_AUTHOR("Jelle Foks <jelle@foks.us>");
  39MODULE_AUTHOR("Chris Pascoe <c.pascoe@itee.uq.edu.au>");
  40MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
  41MODULE_LICENSE("GPL");
  42MODULE_VERSION(CX88_VERSION);
  43
  44static unsigned int debug;
  45module_param(debug,int,0644);
  46MODULE_PARM_DESC(debug,"enable debug messages [mpeg]");
  47
  48#define dprintk(level,fmt, arg...)      if (debug >= level) \
  49        printk(KERN_DEBUG "%s/2-mpeg: " fmt, dev->core->name, ## arg)
  50
  51#define mpeg_dbg(level,fmt, arg...)     if (debug >= level) \
  52        printk(KERN_DEBUG "%s/2-mpeg: " fmt, core->name, ## arg)
  53
  54#if defined(CONFIG_MODULES) && defined(MODULE)
  55static void request_module_async(struct work_struct *work)
  56{
  57        struct cx8802_dev *dev=container_of(work, struct cx8802_dev, request_module_wk);
  58
  59        if (dev->core->board.mpeg & CX88_MPEG_DVB)
  60                request_module("cx88-dvb");
  61        if (dev->core->board.mpeg & CX88_MPEG_BLACKBIRD)
  62                request_module("cx88-blackbird");
  63}
  64
  65static void request_modules(struct cx8802_dev *dev)
  66{
  67        INIT_WORK(&dev->request_module_wk, request_module_async);
  68        schedule_work(&dev->request_module_wk);
  69}
  70
  71static void flush_request_modules(struct cx8802_dev *dev)
  72{
  73        flush_work_sync(&dev->request_module_wk);
  74}
  75#else
  76#define request_modules(dev)
  77#define flush_request_modules(dev)
  78#endif /* CONFIG_MODULES */
  79
  80
  81static LIST_HEAD(cx8802_devlist);
  82static DEFINE_MUTEX(cx8802_mutex);
  83/* ------------------------------------------------------------------ */
  84
  85static int cx8802_start_dma(struct cx8802_dev    *dev,
  86                            struct cx88_dmaqueue *q,
  87                            struct cx88_buffer   *buf)
  88{
  89        struct cx88_core *core = dev->core;
  90
  91        dprintk(1, "cx8802_start_dma w: %d, h: %d, f: %d\n",
  92                buf->vb.width, buf->vb.height, buf->vb.field);
  93
  94        /* setup fifo + format */
  95        cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH28],
  96                                dev->ts_packet_size, buf->risc.dma);
  97
  98        /* write TS length to chip */
  99        cx_write(MO_TS_LNGTH, buf->vb.width);
 100
 101        /* FIXME: this needs a review.
 102         * also: move to cx88-blackbird + cx88-dvb source files? */
 103
 104        dprintk( 1, "core->active_type_id = 0x%08x\n", core->active_type_id);
 105
 106        if ( (core->active_type_id == CX88_MPEG_DVB) &&
 107                (core->board.mpeg & CX88_MPEG_DVB) ) {
 108
 109                dprintk( 1, "cx8802_start_dma doing .dvb\n");
 110                /* negedge driven & software reset */
 111                cx_write(TS_GEN_CNTRL, 0x0040 | dev->ts_gen_cntrl);
 112                udelay(100);
 113                cx_write(MO_PINMUX_IO, 0x00);
 114                cx_write(TS_HW_SOP_CNTRL, 0x47<<16|188<<4|0x01);
 115                switch (core->boardnr) {
 116                case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q:
 117                case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T:
 118                case CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD:
 119                case CX88_BOARD_PCHDTV_HD5500:
 120                        cx_write(TS_SOP_STAT, 1<<13);
 121                        break;
 122                case CX88_BOARD_SAMSUNG_SMT_7020:
 123                        cx_write(TS_SOP_STAT, 0x00);
 124                        break;
 125                case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1:
 126                case CX88_BOARD_HAUPPAUGE_NOVASE2_S1:
 127                        cx_write(MO_PINMUX_IO, 0x88); /* Enable MPEG parallel IO and video signal pins */
 128                        udelay(100);
 129                        break;
 130                case CX88_BOARD_HAUPPAUGE_HVR1300:
 131                        /* Enable MPEG parallel IO and video signal pins */
 132                        cx_write(MO_PINMUX_IO, 0x88);
 133                        cx_write(TS_SOP_STAT, 0);
 134                        cx_write(TS_VALERR_CNTRL, 0);
 135                        break;
 136                case CX88_BOARD_PINNACLE_PCTV_HD_800i:
 137                        /* Enable MPEG parallel IO and video signal pins */
 138                        cx_write(MO_PINMUX_IO, 0x88);
 139                        cx_write(TS_HW_SOP_CNTRL, (0x47 << 16) | (188 << 4));
 140                        dev->ts_gen_cntrl = 5;
 141                        cx_write(TS_SOP_STAT, 0);
 142                        cx_write(TS_VALERR_CNTRL, 0);
 143                        udelay(100);
 144                        break;
 145                default:
 146                        cx_write(TS_SOP_STAT, 0x00);
 147                        break;
 148                }
 149                cx_write(TS_GEN_CNTRL, dev->ts_gen_cntrl);
 150                udelay(100);
 151        } else if ( (core->active_type_id == CX88_MPEG_BLACKBIRD) &&
 152                (core->board.mpeg & CX88_MPEG_BLACKBIRD) ) {
 153                dprintk( 1, "cx8802_start_dma doing .blackbird\n");
 154                cx_write(MO_PINMUX_IO, 0x88); /* enable MPEG parallel IO */
 155
 156                cx_write(TS_GEN_CNTRL, 0x46); /* punctured clock TS & posedge driven & software reset */
 157                udelay(100);
 158
 159                cx_write(TS_HW_SOP_CNTRL, 0x408); /* mpeg start byte */
 160                cx_write(TS_VALERR_CNTRL, 0x2000);
 161
 162                cx_write(TS_GEN_CNTRL, 0x06); /* punctured clock TS & posedge driven */
 163                udelay(100);
 164        } else {
 165                printk( "%s() Failed. Unsupported value in .mpeg (0x%08x)\n", __func__,
 166                        core->board.mpeg );
 167                return -EINVAL;
 168        }
 169
 170        /* reset counter */
 171        cx_write(MO_TS_GPCNTRL, GP_COUNT_CONTROL_RESET);
 172        q->count = 1;
 173
 174        /* enable irqs */
 175        dprintk( 1, "setting the interrupt mask\n" );
 176        cx_set(MO_PCI_INTMSK, core->pci_irqmask | PCI_INT_TSINT);
 177        cx_set(MO_TS_INTMSK,  0x1f0011);
 178
 179        /* start dma */
 180        cx_set(MO_DEV_CNTRL2, (1<<5));
 181        cx_set(MO_TS_DMACNTRL, 0x11);
 182        return 0;
 183}
 184
 185static int cx8802_stop_dma(struct cx8802_dev *dev)
 186{
 187        struct cx88_core *core = dev->core;
 188        dprintk( 1, "cx8802_stop_dma\n" );
 189
 190        /* stop dma */
 191        cx_clear(MO_TS_DMACNTRL, 0x11);
 192
 193        /* disable irqs */
 194        cx_clear(MO_PCI_INTMSK, PCI_INT_TSINT);
 195        cx_clear(MO_TS_INTMSK, 0x1f0011);
 196
 197        /* Reset the controller */
 198        cx_write(TS_GEN_CNTRL, 0xcd);
 199        return 0;
 200}
 201
 202static int cx8802_restart_queue(struct cx8802_dev    *dev,
 203                                struct cx88_dmaqueue *q)
 204{
 205        struct cx88_buffer *buf;
 206
 207        dprintk( 1, "cx8802_restart_queue\n" );
 208        if (list_empty(&q->active))
 209        {
 210                struct cx88_buffer *prev;
 211                prev = NULL;
 212
 213                dprintk(1, "cx8802_restart_queue: queue is empty\n" );
 214
 215                for (;;) {
 216                        if (list_empty(&q->queued))
 217                                return 0;
 218                        buf = list_entry(q->queued.next, struct cx88_buffer, vb.queue);
 219                        if (NULL == prev) {
 220                                list_del(&buf->vb.queue);
 221                                list_add_tail(&buf->vb.queue,&q->active);
 222                                cx8802_start_dma(dev, q, buf);
 223                                buf->vb.state = VIDEOBUF_ACTIVE;
 224                                buf->count    = q->count++;
 225                                mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
 226                                dprintk(1,"[%p/%d] restart_queue - first active\n",
 227                                        buf,buf->vb.i);
 228
 229                        } else if (prev->vb.width  == buf->vb.width  &&
 230                                   prev->vb.height == buf->vb.height &&
 231                                   prev->fmt       == buf->fmt) {
 232                                list_del(&buf->vb.queue);
 233                                list_add_tail(&buf->vb.queue,&q->active);
 234                                buf->vb.state = VIDEOBUF_ACTIVE;
 235                                buf->count    = q->count++;
 236                                prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
 237                                dprintk(1,"[%p/%d] restart_queue - move to active\n",
 238                                        buf,buf->vb.i);
 239                        } else {
 240                                return 0;
 241                        }
 242                        prev = buf;
 243                }
 244                return 0;
 245        }
 246
 247        buf = list_entry(q->active.next, struct cx88_buffer, vb.queue);
 248        dprintk(2,"restart_queue [%p/%d]: restart dma\n",
 249                buf, buf->vb.i);
 250        cx8802_start_dma(dev, q, buf);
 251        list_for_each_entry(buf, &q->active, vb.queue)
 252                buf->count = q->count++;
 253        mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
 254        return 0;
 255}
 256
 257/* ------------------------------------------------------------------ */
 258
 259int cx8802_buf_prepare(struct videobuf_queue *q, struct cx8802_dev *dev,
 260                        struct cx88_buffer *buf, enum v4l2_field field)
 261{
 262        int size = dev->ts_packet_size * dev->ts_packet_count;
 263        struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
 264        int rc;
 265
 266        dprintk(1, "%s: %p\n", __func__, buf);
 267        if (0 != buf->vb.baddr  &&  buf->vb.bsize < size)
 268                return -EINVAL;
 269
 270        if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
 271                buf->vb.width  = dev->ts_packet_size;
 272                buf->vb.height = dev->ts_packet_count;
 273                buf->vb.size   = size;
 274                buf->vb.field  = field /*V4L2_FIELD_TOP*/;
 275
 276                if (0 != (rc = videobuf_iolock(q,&buf->vb,NULL)))
 277                        goto fail;
 278                cx88_risc_databuffer(dev->pci, &buf->risc,
 279                                     dma->sglist,
 280                                     buf->vb.width, buf->vb.height, 0);
 281        }
 282        buf->vb.state = VIDEOBUF_PREPARED;
 283        return 0;
 284
 285 fail:
 286        cx88_free_buffer(q,buf);
 287        return rc;
 288}
 289
 290void cx8802_buf_queue(struct cx8802_dev *dev, struct cx88_buffer *buf)
 291{
 292        struct cx88_buffer    *prev;
 293        struct cx88_dmaqueue  *cx88q = &dev->mpegq;
 294
 295        dprintk( 1, "cx8802_buf_queue\n" );
 296        /* add jump to stopper */
 297        buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
 298        buf->risc.jmp[1] = cpu_to_le32(cx88q->stopper.dma);
 299
 300        if (list_empty(&cx88q->active)) {
 301                dprintk( 1, "queue is empty - first active\n" );
 302                list_add_tail(&buf->vb.queue,&cx88q->active);
 303                cx8802_start_dma(dev, cx88q, buf);
 304                buf->vb.state = VIDEOBUF_ACTIVE;
 305                buf->count    = cx88q->count++;
 306                mod_timer(&cx88q->timeout, jiffies+BUFFER_TIMEOUT);
 307                dprintk(1,"[%p/%d] %s - first active\n",
 308                        buf, buf->vb.i, __func__);
 309
 310        } else {
 311                dprintk( 1, "queue is not empty - append to active\n" );
 312                prev = list_entry(cx88q->active.prev, struct cx88_buffer, vb.queue);
 313                list_add_tail(&buf->vb.queue,&cx88q->active);
 314                buf->vb.state = VIDEOBUF_ACTIVE;
 315                buf->count    = cx88q->count++;
 316                prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
 317                dprintk( 1, "[%p/%d] %s - append to active\n",
 318                        buf, buf->vb.i, __func__);
 319        }
 320}
 321
 322/* ----------------------------------------------------------- */
 323
 324static void do_cancel_buffers(struct cx8802_dev *dev, const char *reason, int restart)
 325{
 326        struct cx88_dmaqueue *q = &dev->mpegq;
 327        struct cx88_buffer *buf;
 328        unsigned long flags;
 329
 330        spin_lock_irqsave(&dev->slock,flags);
 331        while (!list_empty(&q->active)) {
 332                buf = list_entry(q->active.next, struct cx88_buffer, vb.queue);
 333                list_del(&buf->vb.queue);
 334                buf->vb.state = VIDEOBUF_ERROR;
 335                wake_up(&buf->vb.done);
 336                dprintk(1,"[%p/%d] %s - dma=0x%08lx\n",
 337                        buf, buf->vb.i, reason, (unsigned long)buf->risc.dma);
 338        }
 339        if (restart)
 340        {
 341                dprintk(1, "restarting queue\n" );
 342                cx8802_restart_queue(dev,q);
 343        }
 344        spin_unlock_irqrestore(&dev->slock,flags);
 345}
 346
 347void cx8802_cancel_buffers(struct cx8802_dev *dev)
 348{
 349        struct cx88_dmaqueue *q = &dev->mpegq;
 350
 351        dprintk( 1, "cx8802_cancel_buffers" );
 352        del_timer_sync(&q->timeout);
 353        cx8802_stop_dma(dev);
 354        do_cancel_buffers(dev,"cancel",0);
 355}
 356
 357static void cx8802_timeout(unsigned long data)
 358{
 359        struct cx8802_dev *dev = (struct cx8802_dev*)data;
 360
 361        dprintk(1, "%s\n",__func__);
 362
 363        if (debug)
 364                cx88_sram_channel_dump(dev->core, &cx88_sram_channels[SRAM_CH28]);
 365        cx8802_stop_dma(dev);
 366        do_cancel_buffers(dev,"timeout",1);
 367}
 368
 369static const char * cx88_mpeg_irqs[32] = {
 370        "ts_risci1", NULL, NULL, NULL,
 371        "ts_risci2", NULL, NULL, NULL,
 372        "ts_oflow",  NULL, NULL, NULL,
 373        "ts_sync",   NULL, NULL, NULL,
 374        "opc_err", "par_err", "rip_err", "pci_abort",
 375        "ts_err?",
 376};
 377
 378static void cx8802_mpeg_irq(struct cx8802_dev *dev)
 379{
 380        struct cx88_core *core = dev->core;
 381        u32 status, mask, count;
 382
 383        dprintk( 1, "cx8802_mpeg_irq\n" );
 384        status = cx_read(MO_TS_INTSTAT);
 385        mask   = cx_read(MO_TS_INTMSK);
 386        if (0 == (status & mask))
 387                return;
 388
 389        cx_write(MO_TS_INTSTAT, status);
 390
 391        if (debug || (status & mask & ~0xff))
 392                cx88_print_irqbits(core->name, "irq mpeg ",
 393                                   cx88_mpeg_irqs, ARRAY_SIZE(cx88_mpeg_irqs),
 394                                   status, mask);
 395
 396        /* risc op code error */
 397        if (status & (1 << 16)) {
 398                printk(KERN_WARNING "%s: mpeg risc op code error\n",core->name);
 399                cx_clear(MO_TS_DMACNTRL, 0x11);
 400                cx88_sram_channel_dump(dev->core, &cx88_sram_channels[SRAM_CH28]);
 401        }
 402
 403        /* risc1 y */
 404        if (status & 0x01) {
 405                dprintk( 1, "wake up\n" );
 406                spin_lock(&dev->slock);
 407                count = cx_read(MO_TS_GPCNT);
 408                cx88_wakeup(dev->core, &dev->mpegq, count);
 409                spin_unlock(&dev->slock);
 410        }
 411
 412        /* risc2 y */
 413        if (status & 0x10) {
 414                spin_lock(&dev->slock);
 415                cx8802_restart_queue(dev,&dev->mpegq);
 416                spin_unlock(&dev->slock);
 417        }
 418
 419        /* other general errors */
 420        if (status & 0x1f0100) {
 421                dprintk( 0, "general errors: 0x%08x\n", status & 0x1f0100 );
 422                spin_lock(&dev->slock);
 423                cx8802_stop_dma(dev);
 424                cx8802_restart_queue(dev,&dev->mpegq);
 425                spin_unlock(&dev->slock);
 426        }
 427}
 428
 429#define MAX_IRQ_LOOP 10
 430
 431static irqreturn_t cx8802_irq(int irq, void *dev_id)
 432{
 433        struct cx8802_dev *dev = dev_id;
 434        struct cx88_core *core = dev->core;
 435        u32 status;
 436        int loop, handled = 0;
 437
 438        for (loop = 0; loop < MAX_IRQ_LOOP; loop++) {
 439                status = cx_read(MO_PCI_INTSTAT) &
 440                        (core->pci_irqmask | PCI_INT_TSINT);
 441                if (0 == status)
 442                        goto out;
 443                dprintk( 1, "cx8802_irq\n" );
 444                dprintk( 1, "    loop: %d/%d\n", loop, MAX_IRQ_LOOP );
 445                dprintk( 1, "    status: %d\n", status );
 446                handled = 1;
 447                cx_write(MO_PCI_INTSTAT, status);
 448
 449                if (status & core->pci_irqmask)
 450                        cx88_core_irq(core,status);
 451                if (status & PCI_INT_TSINT)
 452                        cx8802_mpeg_irq(dev);
 453        };
 454        if (MAX_IRQ_LOOP == loop) {
 455                dprintk( 0, "clearing mask\n" );
 456                printk(KERN_WARNING "%s/0: irq loop -- clearing mask\n",
 457                       core->name);
 458                cx_write(MO_PCI_INTMSK,0);
 459        }
 460
 461 out:
 462        return IRQ_RETVAL(handled);
 463}
 464
 465static int cx8802_init_common(struct cx8802_dev *dev)
 466{
 467        struct cx88_core *core = dev->core;
 468        int err;
 469
 470        /* pci init */
 471        if (pci_enable_device(dev->pci))
 472                return -EIO;
 473        pci_set_master(dev->pci);
 474        if (!pci_dma_supported(dev->pci,DMA_BIT_MASK(32))) {
 475                printk("%s/2: Oops: no 32bit PCI DMA ???\n",dev->core->name);
 476                return -EIO;
 477        }
 478
 479        dev->pci_rev = dev->pci->revision;
 480        pci_read_config_byte(dev->pci, PCI_LATENCY_TIMER,  &dev->pci_lat);
 481        printk(KERN_INFO "%s/2: found at %s, rev: %d, irq: %d, "
 482               "latency: %d, mmio: 0x%llx\n", dev->core->name,
 483               pci_name(dev->pci), dev->pci_rev, dev->pci->irq,
 484               dev->pci_lat,(unsigned long long)pci_resource_start(dev->pci,0));
 485
 486        /* initialize driver struct */
 487        spin_lock_init(&dev->slock);
 488
 489        /* init dma queue */
 490        INIT_LIST_HEAD(&dev->mpegq.active);
 491        INIT_LIST_HEAD(&dev->mpegq.queued);
 492        dev->mpegq.timeout.function = cx8802_timeout;
 493        dev->mpegq.timeout.data     = (unsigned long)dev;
 494        init_timer(&dev->mpegq.timeout);
 495        cx88_risc_stopper(dev->pci,&dev->mpegq.stopper,
 496                          MO_TS_DMACNTRL,0x11,0x00);
 497
 498        /* get irq */
 499        err = request_irq(dev->pci->irq, cx8802_irq,
 500                          IRQF_SHARED | IRQF_DISABLED, dev->core->name, dev);
 501        if (err < 0) {
 502                printk(KERN_ERR "%s: can't get IRQ %d\n",
 503                       dev->core->name, dev->pci->irq);
 504                return err;
 505        }
 506        cx_set(MO_PCI_INTMSK, core->pci_irqmask);
 507
 508        /* everything worked */
 509        pci_set_drvdata(dev->pci,dev);
 510        return 0;
 511}
 512
 513static void cx8802_fini_common(struct cx8802_dev *dev)
 514{
 515        dprintk( 2, "cx8802_fini_common\n" );
 516        cx8802_stop_dma(dev);
 517        pci_disable_device(dev->pci);
 518
 519        /* unregister stuff */
 520        free_irq(dev->pci->irq, dev);
 521        pci_set_drvdata(dev->pci, NULL);
 522
 523        /* free memory */
 524        btcx_riscmem_free(dev->pci,&dev->mpegq.stopper);
 525}
 526
 527/* ----------------------------------------------------------- */
 528
 529static int cx8802_suspend_common(struct pci_dev *pci_dev, pm_message_t state)
 530{
 531        struct cx8802_dev *dev = pci_get_drvdata(pci_dev);
 532        struct cx88_core *core = dev->core;
 533
 534        /* stop mpeg dma */
 535        spin_lock(&dev->slock);
 536        if (!list_empty(&dev->mpegq.active)) {
 537                dprintk( 2, "suspend\n" );
 538                printk("%s: suspend mpeg\n", core->name);
 539                cx8802_stop_dma(dev);
 540                del_timer(&dev->mpegq.timeout);
 541        }
 542        spin_unlock(&dev->slock);
 543
 544        /* FIXME -- shutdown device */
 545        cx88_shutdown(dev->core);
 546
 547        pci_save_state(pci_dev);
 548        if (0 != pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state))) {
 549                pci_disable_device(pci_dev);
 550                dev->state.disabled = 1;
 551        }
 552        return 0;
 553}
 554
 555static int cx8802_resume_common(struct pci_dev *pci_dev)
 556{
 557        struct cx8802_dev *dev = pci_get_drvdata(pci_dev);
 558        struct cx88_core *core = dev->core;
 559        int err;
 560
 561        if (dev->state.disabled) {
 562                err=pci_enable_device(pci_dev);
 563                if (err) {
 564                        printk(KERN_ERR "%s: can't enable device\n",
 565                                               dev->core->name);
 566                        return err;
 567                }
 568                dev->state.disabled = 0;
 569        }
 570        err=pci_set_power_state(pci_dev, PCI_D0);
 571        if (err) {
 572                printk(KERN_ERR "%s: can't enable device\n",
 573                                               dev->core->name);
 574                pci_disable_device(pci_dev);
 575                dev->state.disabled = 1;
 576
 577                return err;
 578        }
 579        pci_restore_state(pci_dev);
 580
 581        /* FIXME: re-initialize hardware */
 582        cx88_reset(dev->core);
 583
 584        /* restart video+vbi capture */
 585        spin_lock(&dev->slock);
 586        if (!list_empty(&dev->mpegq.active)) {
 587                printk("%s: resume mpeg\n", core->name);
 588                cx8802_restart_queue(dev,&dev->mpegq);
 589        }
 590        spin_unlock(&dev->slock);
 591
 592        return 0;
 593}
 594
 595struct cx8802_driver * cx8802_get_driver(struct cx8802_dev *dev, enum cx88_board_type btype)
 596{
 597        struct cx8802_driver *d;
 598
 599        list_for_each_entry(d, &dev->drvlist, drvlist)
 600                if (d->type_id == btype)
 601                        return d;
 602
 603        return NULL;
 604}
 605
 606/* Driver asked for hardware access. */
 607static int cx8802_request_acquire(struct cx8802_driver *drv)
 608{
 609        struct cx88_core *core = drv->core;
 610        unsigned int    i;
 611
 612        /* Fail a request for hardware if the device is busy. */
 613        if (core->active_type_id != CX88_BOARD_NONE &&
 614            core->active_type_id != drv->type_id)
 615                return -EBUSY;
 616
 617        if (drv->type_id == CX88_MPEG_DVB) {
 618                /* When switching to DVB, always set the input to the tuner */
 619                core->last_analog_input = core->input;
 620                core->input = 0;
 621                for (i = 0;
 622                     i < (sizeof(core->board.input) / sizeof(struct cx88_input));
 623                     i++) {
 624                        if (core->board.input[i].type == CX88_VMUX_DVB) {
 625                                core->input = i;
 626                                break;
 627                        }
 628                }
 629        }
 630
 631        if (drv->advise_acquire)
 632        {
 633                core->active_ref++;
 634                if (core->active_type_id == CX88_BOARD_NONE) {
 635                        core->active_type_id = drv->type_id;
 636                        drv->advise_acquire(drv);
 637                }
 638
 639                mpeg_dbg(1,"%s() Post acquire GPIO=%x\n", __func__, cx_read(MO_GP0_IO));
 640        }
 641
 642        return 0;
 643}
 644
 645/* Driver asked to release hardware. */
 646static int cx8802_request_release(struct cx8802_driver *drv)
 647{
 648        struct cx88_core *core = drv->core;
 649
 650        if (drv->advise_release && --core->active_ref == 0)
 651        {
 652                if (drv->type_id == CX88_MPEG_DVB) {
 653                        /* If the DVB driver is releasing, reset the input
 654                           state to the last configured analog input */
 655                        core->input = core->last_analog_input;
 656                }
 657
 658                drv->advise_release(drv);
 659                core->active_type_id = CX88_BOARD_NONE;
 660                mpeg_dbg(1,"%s() Post release GPIO=%x\n", __func__, cx_read(MO_GP0_IO));
 661        }
 662
 663        return 0;
 664}
 665
 666static int cx8802_check_driver(struct cx8802_driver *drv)
 667{
 668        if (drv == NULL)
 669                return -ENODEV;
 670
 671        if ((drv->type_id != CX88_MPEG_DVB) &&
 672                (drv->type_id != CX88_MPEG_BLACKBIRD))
 673                return -EINVAL;
 674
 675        if ((drv->hw_access != CX8802_DRVCTL_SHARED) &&
 676                (drv->hw_access != CX8802_DRVCTL_EXCLUSIVE))
 677                return -EINVAL;
 678
 679        if ((drv->probe == NULL) ||
 680                (drv->remove == NULL) ||
 681                (drv->advise_acquire == NULL) ||
 682                (drv->advise_release == NULL))
 683                return -EINVAL;
 684
 685        return 0;
 686}
 687
 688int cx8802_register_driver(struct cx8802_driver *drv)
 689{
 690        struct cx8802_dev *dev;
 691        struct cx8802_driver *driver;
 692        int err, i = 0;
 693
 694        printk(KERN_INFO
 695               "cx88/2: registering cx8802 driver, type: %s access: %s\n",
 696               drv->type_id == CX88_MPEG_DVB ? "dvb" : "blackbird",
 697               drv->hw_access == CX8802_DRVCTL_SHARED ? "shared" : "exclusive");
 698
 699        if ((err = cx8802_check_driver(drv)) != 0) {
 700                printk(KERN_ERR "cx88/2: cx8802_driver is invalid\n");
 701                return err;
 702        }
 703
 704        mutex_lock(&cx8802_mutex);
 705
 706        list_for_each_entry(dev, &cx8802_devlist, devlist) {
 707                printk(KERN_INFO
 708                       "%s/2: subsystem: %04x:%04x, board: %s [card=%d]\n",
 709                       dev->core->name, dev->pci->subsystem_vendor,
 710                       dev->pci->subsystem_device, dev->core->board.name,
 711                       dev->core->boardnr);
 712
 713                /* Bring up a new struct for each driver instance */
 714                driver = kzalloc(sizeof(*drv),GFP_KERNEL);
 715                if (driver == NULL) {
 716                        err = -ENOMEM;
 717                        goto out;
 718                }
 719
 720                /* Snapshot of the driver registration data */
 721                drv->core = dev->core;
 722                drv->suspend = cx8802_suspend_common;
 723                drv->resume = cx8802_resume_common;
 724                drv->request_acquire = cx8802_request_acquire;
 725                drv->request_release = cx8802_request_release;
 726                memcpy(driver, drv, sizeof(*driver));
 727
 728                mutex_lock(&drv->core->lock);
 729                err = drv->probe(driver);
 730                if (err == 0) {
 731                        i++;
 732                        list_add_tail(&driver->drvlist, &dev->drvlist);
 733                } else {
 734                        printk(KERN_ERR
 735                               "%s/2: cx8802 probe failed, err = %d\n",
 736                               dev->core->name, err);
 737                }
 738                mutex_unlock(&drv->core->lock);
 739        }
 740
 741        err = i ? 0 : -ENODEV;
 742out:
 743        mutex_unlock(&cx8802_mutex);
 744        return err;
 745}
 746
 747int cx8802_unregister_driver(struct cx8802_driver *drv)
 748{
 749        struct cx8802_dev *dev;
 750        struct cx8802_driver *d, *dtmp;
 751        int err = 0;
 752
 753        printk(KERN_INFO
 754               "cx88/2: unregistering cx8802 driver, type: %s access: %s\n",
 755               drv->type_id == CX88_MPEG_DVB ? "dvb" : "blackbird",
 756               drv->hw_access == CX8802_DRVCTL_SHARED ? "shared" : "exclusive");
 757
 758        mutex_lock(&cx8802_mutex);
 759
 760        list_for_each_entry(dev, &cx8802_devlist, devlist) {
 761                printk(KERN_INFO
 762                       "%s/2: subsystem: %04x:%04x, board: %s [card=%d]\n",
 763                       dev->core->name, dev->pci->subsystem_vendor,
 764                       dev->pci->subsystem_device, dev->core->board.name,
 765                       dev->core->boardnr);
 766
 767                mutex_lock(&dev->core->lock);
 768
 769                list_for_each_entry_safe(d, dtmp, &dev->drvlist, drvlist) {
 770                        /* only unregister the correct driver type */
 771                        if (d->type_id != drv->type_id)
 772                                continue;
 773
 774                        err = d->remove(d);
 775                        if (err == 0) {
 776                                list_del(&d->drvlist);
 777                                kfree(d);
 778                        } else
 779                                printk(KERN_ERR "%s/2: cx8802 driver remove "
 780                                       "failed (%d)\n", dev->core->name, err);
 781                }
 782
 783                mutex_unlock(&dev->core->lock);
 784        }
 785
 786        mutex_unlock(&cx8802_mutex);
 787
 788        return err;
 789}
 790
 791/* ----------------------------------------------------------- */
 792static int __devinit cx8802_probe(struct pci_dev *pci_dev,
 793                               const struct pci_device_id *pci_id)
 794{
 795        struct cx8802_dev *dev;
 796        struct cx88_core  *core;
 797        int err;
 798
 799        /* general setup */
 800        core = cx88_core_get(pci_dev);
 801        if (NULL == core)
 802                return -EINVAL;
 803
 804        printk("%s/2: cx2388x 8802 Driver Manager\n", core->name);
 805
 806        err = -ENODEV;
 807        if (!core->board.mpeg)
 808                goto fail_core;
 809
 810        err = -ENOMEM;
 811        dev = kzalloc(sizeof(*dev),GFP_KERNEL);
 812        if (NULL == dev)
 813                goto fail_core;
 814        dev->pci = pci_dev;
 815        dev->core = core;
 816
 817        /* Maintain a reference so cx88-video can query the 8802 device. */
 818        core->dvbdev = dev;
 819
 820        err = cx8802_init_common(dev);
 821        if (err != 0)
 822                goto fail_free;
 823
 824        INIT_LIST_HEAD(&dev->drvlist);
 825        mutex_lock(&cx8802_mutex);
 826        list_add_tail(&dev->devlist,&cx8802_devlist);
 827        mutex_unlock(&cx8802_mutex);
 828
 829        /* now autoload cx88-dvb or cx88-blackbird */
 830        request_modules(dev);
 831        return 0;
 832
 833 fail_free:
 834        kfree(dev);
 835 fail_core:
 836        core->dvbdev = NULL;
 837        cx88_core_put(core,pci_dev);
 838        return err;
 839}
 840
 841static void __devexit cx8802_remove(struct pci_dev *pci_dev)
 842{
 843        struct cx8802_dev *dev;
 844
 845        dev = pci_get_drvdata(pci_dev);
 846
 847        dprintk( 1, "%s\n", __func__);
 848
 849        flush_request_modules(dev);
 850
 851        mutex_lock(&dev->core->lock);
 852
 853        if (!list_empty(&dev->drvlist)) {
 854                struct cx8802_driver *drv, *tmp;
 855                int err;
 856
 857                printk(KERN_WARNING "%s/2: Trying to remove cx8802 driver "
 858                       "while cx8802 sub-drivers still loaded?!\n",
 859                       dev->core->name);
 860
 861                list_for_each_entry_safe(drv, tmp, &dev->drvlist, drvlist) {
 862                        err = drv->remove(drv);
 863                        if (err == 0) {
 864                                list_del(&drv->drvlist);
 865                        } else
 866                                printk(KERN_ERR "%s/2: cx8802 driver remove "
 867                                       "failed (%d)\n", dev->core->name, err);
 868                        kfree(drv);
 869                }
 870        }
 871
 872        mutex_unlock(&dev->core->lock);
 873
 874        /* Destroy any 8802 reference. */
 875        dev->core->dvbdev = NULL;
 876
 877        /* common */
 878        cx8802_fini_common(dev);
 879        cx88_core_put(dev->core,dev->pci);
 880        kfree(dev);
 881}
 882
 883static const struct pci_device_id cx8802_pci_tbl[] = {
 884        {
 885                .vendor       = 0x14f1,
 886                .device       = 0x8802,
 887                .subvendor    = PCI_ANY_ID,
 888                .subdevice    = PCI_ANY_ID,
 889        },{
 890                /* --- end of list --- */
 891        }
 892};
 893MODULE_DEVICE_TABLE(pci, cx8802_pci_tbl);
 894
 895static struct pci_driver cx8802_pci_driver = {
 896        .name     = "cx88-mpeg driver manager",
 897        .id_table = cx8802_pci_tbl,
 898        .probe    = cx8802_probe,
 899        .remove   = __devexit_p(cx8802_remove),
 900};
 901
 902static int __init cx8802_init(void)
 903{
 904        printk(KERN_INFO "cx88/2: cx2388x MPEG-TS Driver Manager version %s loaded\n",
 905               CX88_VERSION);
 906        return pci_register_driver(&cx8802_pci_driver);
 907}
 908
 909static void __exit cx8802_fini(void)
 910{
 911        pci_unregister_driver(&cx8802_pci_driver);
 912}
 913
 914module_init(cx8802_init);
 915module_exit(cx8802_fini);
 916EXPORT_SYMBOL(cx8802_buf_prepare);
 917EXPORT_SYMBOL(cx8802_buf_queue);
 918EXPORT_SYMBOL(cx8802_cancel_buffers);
 919
 920EXPORT_SYMBOL(cx8802_register_driver);
 921EXPORT_SYMBOL(cx8802_unregister_driver);
 922EXPORT_SYMBOL(cx8802_get_driver);
 923/* ----------------------------------------------------------- */
 924/*
 925 * Local variables:
 926 * c-basic-offset: 8
 927 * End:
 928 * kate: eol "unix"; indent-width 3; remove-trailing-space on; replace-trailing-space-save on; tab-width 8; replace-tabs off; space-indent off; mixed-indent off
 929 */
 930
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.