]> err.no Git - linux-2.6/blobdiff - drivers/media/video/cx88/cx88-video.c
Merge branches 'pxa' and 'orion-fixes1'
[linux-2.6] / drivers / media / video / cx88 / cx88-video.c
index c84dafbdb991aae420a0f4bc80f3b8f71174110c..eea23f95edb751d42f9dce1588f817038e0ba5bf 100644 (file)
@@ -63,11 +63,11 @@ MODULE_PARM_DESC(video_nr,"video device numbers");
 MODULE_PARM_DESC(vbi_nr,"vbi device numbers");
 MODULE_PARM_DESC(radio_nr,"radio device numbers");
 
-static unsigned int video_debug = 0;
+static unsigned int video_debug;
 module_param(video_debug,int,0644);
 MODULE_PARM_DESC(video_debug,"enable debug messages [video]");
 
-static unsigned int irq_debug = 0;
+static unsigned int irq_debug;
 module_param(irq_debug,int,0644);
 MODULE_PARM_DESC(irq_debug,"enable debug messages [IRQ handler]");
 
@@ -228,6 +228,30 @@ static struct cx88_ctrl cx8800_ctls[] = {
                .mask                  = 0x00ff,
                .shift                 = 0,
        },{
+               .v = {
+                       .id            = V4L2_CID_CHROMA_AGC,
+                       .name          = "Chroma AGC",
+                       .minimum       = 0,
+                       .maximum       = 1,
+                       .default_value = 0x1,
+                       .type          = V4L2_CTRL_TYPE_BOOLEAN,
+               },
+               .reg                   = MO_INPUT_FORMAT,
+               .mask                  = 1 << 10,
+               .shift                 = 10,
+       }, {
+               .v = {
+                       .id            = V4L2_CID_COLOR_KILLER,
+                       .name          = "Color killer",
+                       .minimum       = 0,
+                       .maximum       = 1,
+                       .default_value = 0x1,
+                       .type          = V4L2_CTRL_TYPE_BOOLEAN,
+               },
+               .reg                   = MO_INPUT_FORMAT,
+               .mask                  = 1 << 9,
+               .shift                 = 9,
+       }, {
        /* --- audio --- */
                .v = {
                        .id            = V4L2_CID_AUDIO_MUTE,
@@ -282,6 +306,8 @@ const u32 cx88_user_ctrls[] = {
        V4L2_CID_AUDIO_VOLUME,
        V4L2_CID_AUDIO_BALANCE,
        V4L2_CID_AUDIO_MUTE,
+       V4L2_CID_CHROMA_AGC,
+       V4L2_CID_COLOR_KILLER,
        0
 };
 EXPORT_SYMBOL(cx88_user_ctrls);
@@ -291,7 +317,7 @@ static const u32 *ctrl_classes[] = {
        NULL
 };
 
-int cx8800_ctrl_query(struct v4l2_queryctrl *qctrl)
+int cx8800_ctrl_query(struct cx88_core *core, struct v4l2_queryctrl *qctrl)
 {
        int i;
 
@@ -306,6 +332,11 @@ int cx8800_ctrl_query(struct v4l2_queryctrl *qctrl)
                return 0;
        }
        *qctrl = cx8800_ctls[i].v;
+       /* Report chroma AGC as inactive when SECAM is selected */
+       if (cx8800_ctls[i].v.id == V4L2_CID_CHROMA_AGC &&
+           core->tvnorm & V4L2_STD_SECAM)
+               qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
+
        return 0;
 }
 EXPORT_SYMBOL(cx8800_ctrl_query);
@@ -392,13 +423,41 @@ int cx88_video_mux(struct cx88_core *core, unsigned int input)
                break;
        }
 
-       if (core->board.mpeg & CX88_MPEG_BLACKBIRD) {
-               /* sets sound input from external adc */
-               if (INPUT(input).extadc)
+       /* if there are audioroutes defined, we have an external
+          ADC to deal with audio */
+
+       if (INPUT(input).audioroute) {
+
+               /* cx2388's C-ADC is connected to the tuner only.
+                  When used with S-Video, that ADC is busy dealing with
+                  chroma, so an external must be used for baseband audio */
+
+               if (INPUT(input).type != CX88_VMUX_TELEVISION &&
+                       INPUT(input).type != CX88_RADIO) {
+                       /* "ADC mode" */
+                       cx_write(AUD_I2SCNTL, 0x1);
                        cx_set(AUD_CTL, EN_I2SIN_ENABLE);
-               else
+               } else {
+                       /* Normal mode */
+                       cx_write(AUD_I2SCNTL, 0x0);
                        cx_clear(AUD_CTL, EN_I2SIN_ENABLE);
+               }
+
+               /* The wm8775 module has the "2" route hardwired into
+                  the initialization. Some boards may use different
+                  routes for different inputs. HVR-1300 surely does */
+               if (core->board.audio_chip &&
+                   core->board.audio_chip == AUDIO_CHIP_WM8775) {
+                       struct v4l2_routing route;
+
+                       route.input = INPUT(input).audioroute;
+                       cx88_call_i2c_clients(core,
+                               VIDIOC_INT_S_AUDIO_ROUTING, &route);
+
+               }
+
        }
+
        return 0;
 }
 EXPORT_SYMBOL(cx88_video_mux);
@@ -486,7 +545,7 @@ static int restart_video_queue(struct cx8800_dev    *dev,
                if (NULL == prev) {
                        list_move_tail(&buf->vb.queue, &q->active);
                        start_video_dma(dev, q, buf);
-                       buf->vb.state = STATE_ACTIVE;
+                       buf->vb.state = VIDEOBUF_ACTIVE;
                        buf->count    = q->count++;
                        mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
                        dprintk(2,"[%p/%d] restart_queue - first active\n",
@@ -496,7 +555,7 @@ static int restart_video_queue(struct cx8800_dev    *dev,
                           prev->vb.height == buf->vb.height &&
                           prev->fmt       == buf->fmt) {
                        list_move_tail(&buf->vb.queue, &q->active);
-                       buf->vb.state = STATE_ACTIVE;
+                       buf->vb.state = VIDEOBUF_ACTIVE;
                        buf->count    = q->count++;
                        prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
                        dprintk(2,"[%p/%d] restart_queue - move to active\n",
@@ -553,7 +612,7 @@ buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
                init_buffer = 1;
        }
 
-       if (STATE_NEEDS_INIT == buf->vb.state) {
+       if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
                init_buffer = 1;
                if (0 != (rc = videobuf_iolock(q,&buf->vb,NULL)))
                        goto fail;
@@ -601,7 +660,7 @@ buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
                fh->width, fh->height, fh->fmt->depth, fh->fmt->name,
                (unsigned long)buf->risc.dma);
 
-       buf->vb.state = STATE_PREPARED;
+       buf->vb.state = VIDEOBUF_PREPARED;
        return 0;
 
  fail:
@@ -625,14 +684,14 @@ buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
 
        if (!list_empty(&q->queued)) {
                list_add_tail(&buf->vb.queue,&q->queued);
-               buf->vb.state = STATE_QUEUED;
+               buf->vb.state = VIDEOBUF_QUEUED;
                dprintk(2,"[%p/%d] buffer_queue - append to queued\n",
                        buf, buf->vb.i);
 
        } else if (list_empty(&q->active)) {
                list_add_tail(&buf->vb.queue,&q->active);
                start_video_dma(dev, q, buf);
-               buf->vb.state = STATE_ACTIVE;
+               buf->vb.state = VIDEOBUF_ACTIVE;
                buf->count    = q->count++;
                mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
                dprintk(2,"[%p/%d] buffer_queue - first active\n",
@@ -644,7 +703,7 @@ buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
                    prev->vb.height == buf->vb.height &&
                    prev->fmt       == buf->fmt) {
                        list_add_tail(&buf->vb.queue,&q->active);
-                       buf->vb.state = STATE_ACTIVE;
+                       buf->vb.state = VIDEOBUF_ACTIVE;
                        buf->count    = q->count++;
                        prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
                        dprintk(2,"[%p/%d] buffer_queue - append to active\n",
@@ -652,7 +711,7 @@ buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
 
                } else {
                        list_add_tail(&buf->vb.queue,&q->queued);
-                       buf->vb.state = STATE_QUEUED;
+                       buf->vb.state = VIDEOBUF_QUEUED;
                        dprintk(2,"[%p/%d] buffer_queue - first queued\n",
                                buf, buf->vb.i);
                }
@@ -748,14 +807,14 @@ static int video_open(struct inode *inode, struct file *file)
        fh->height   = 240;
        fh->fmt      = format_by_fourcc(V4L2_PIX_FMT_BGR24);
 
-       videobuf_queue_pci_init(&fh->vidq, &cx8800_video_qops,
-                           dev->pci, &dev->slock,
+       videobuf_queue_sg_init(&fh->vidq, &cx8800_video_qops,
+                           &dev->pci->dev, &dev->slock,
                            V4L2_BUF_TYPE_VIDEO_CAPTURE,
                            V4L2_FIELD_INTERLACED,
                            sizeof(struct cx88_buffer),
                            fh);
-       videobuf_queue_pci_init(&fh->vbiq, &cx8800_vbi_qops,
-                           dev->pci, &dev->slock,
+       videobuf_queue_sg_init(&fh->vbiq, &cx8800_vbi_qops,
+                           &dev->pci->dev, &dev->slock,
                            V4L2_BUF_TYPE_VBI_CAPTURE,
                            V4L2_FIELD_SEQ_TB,
                            sizeof(struct cx88_buffer),
@@ -822,8 +881,8 @@ video_poll(struct file *file, struct poll_table_struct *wait)
                        return POLLERR;
        }
        poll_wait(file, &buf->vb.done, wait);
-       if (buf->vb.state == STATE_DONE ||
-           buf->vb.state == STATE_ERROR)
+       if (buf->vb.state == VIDEOBUF_DONE ||
+           buf->vb.state == VIDEOBUF_ERROR)
                return POLLIN|POLLRDNORM;
        return 0;
 }
@@ -948,6 +1007,12 @@ int cx88_set_control(struct cx88_core *core, struct v4l2_control *ctl)
                }
                mask=0xffff;
                break;
+       case V4L2_CID_CHROMA_AGC:
+               /* Do not allow chroma AGC to be enabled for SECAM */
+               value = ((ctl->value - c->off) << c->shift) & c->mask;
+               if (core->tvnorm & V4L2_STD_SECAM && value)
+                       return -EINVAL;
+               break;
        default:
                value = ((ctl->value - c->off) << c->shift) & c->mask;
                break;
@@ -1240,10 +1305,12 @@ static int vidioc_s_input (struct file *file, void *priv, unsigned int i)
 static int vidioc_queryctrl (struct file *file, void *priv,
                                struct v4l2_queryctrl *qctrl)
 {
+       struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core;
+
        qctrl->id = v4l2_ctrl_next(ctrl_classes, qctrl->id);
        if (unlikely(qctrl->id == 0))
                return -EINVAL;
-       return cx8800_ctrl_query(qctrl);
+       return cx8800_ctrl_query(core, qctrl);
 }
 
 static int vidioc_g_ctrl (struct file *file, void *priv,
@@ -1496,7 +1563,7 @@ static void cx8800_vid_timeout(unsigned long data)
        while (!list_empty(&q->active)) {
                buf = list_entry(q->active.next, struct cx88_buffer, vb.queue);
                list_del(&buf->vb.queue);
-               buf->vb.state = STATE_ERROR;
+               buf->vb.state = VIDEOBUF_ERROR;
                wake_up(&buf->vb.done);
                printk("%s/0: [%p/%d] timeout - dma=0x%08lx\n", core->name,
                       buf, buf->vb.i, (unsigned long)buf->risc.dma);
@@ -1798,16 +1865,17 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev,
        cx_set(MO_PCI_INTMSK, core->pci_irqmask);
 
        /* load and configure helper modules */
-       if (TUNER_ABSENT != core->board.tuner_type)
-               request_module("tuner");
 
        if (core->board.audio_chip == AUDIO_CHIP_WM8775)
                request_module("wm8775");
 
        switch (core->boardnr) {
        case CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD:
-               request_module("ir-kbd-i2c");
+       case CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD:
                request_module("rtc-isl1208");
+               /* break intentionally omitted */
+       case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO:
+               request_module("ir-kbd-i2c");
        }
 
        /* register v4l devices */
@@ -1891,6 +1959,9 @@ static void __devexit cx8800_finidev(struct pci_dev *pci_dev)
                core->kthread = NULL;
        }
 
+       if (core->ir)
+               cx88_ir_stop(core, core->ir);
+
        cx88_shutdown(core); /* FIXME */
        pci_disable_device(pci_dev);