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