]> git.karo-electronics.de Git - linux-beck.git/blobdiff - drivers/media/video/cx88/cx88-video.c
Merge branch 'drm-intel-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/ickle...
[linux-beck.git] / drivers / media / video / cx88 / cx88-video.c
index b755bf100a2b1dc20a08eae59a811f82d7265a52..88b51194f917956a17c734a21d9c2a893b2e5104 100644 (file)
@@ -31,7 +31,6 @@
 #include <linux/kmod.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
 #include <linux/interrupt.h>
 #include <linux/dma-mapping.h>
 #include <linux/delay.h>
@@ -41,6 +40,7 @@
 #include "cx88.h"
 #include <media/v4l2-common.h>
 #include <media/v4l2-ioctl.h>
+#include <media/wm8775.h>
 
 MODULE_DESCRIPTION("v4l2 driver module for cx2388x based TV cards");
 MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
@@ -752,7 +752,7 @@ static int video_open(struct file *file)
 {
        struct video_device *vdev = video_devdata(file);
        struct cx8800_dev *dev = video_drvdata(file);
-       struct cx88_core *core;
+       struct cx88_core *core = dev->core;
        struct cx8800_fh *fh;
        enum v4l2_buf_type type = 0;
        int radio = 0;
@@ -769,19 +769,14 @@ static int video_open(struct file *file)
                break;
        }
 
-       lock_kernel();
-
-       core = dev->core;
-
        dprintk(1, "open dev=%s radio=%d type=%s\n",
                video_device_node_name(vdev), radio, v4l2_type_names[type]);
 
        /* allocate + initialize per filehandle data */
        fh = kzalloc(sizeof(*fh),GFP_KERNEL);
-       if (NULL == fh) {
-               unlock_kernel();
+       if (unlikely(!fh))
                return -ENOMEM;
-       }
+
        file->private_data = fh;
        fh->dev      = dev;
        fh->radio    = radio;
@@ -790,18 +785,20 @@ static int video_open(struct file *file)
        fh->height   = 240;
        fh->fmt      = format_by_fourcc(V4L2_PIX_FMT_BGR24);
 
+       mutex_lock(&core->lock);
+
        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);
+                           fh, NULL);
        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),
-                           fh);
+                           fh, NULL);
 
        if (fh->radio) {
                dprintk(1,"video_open: setting radio device\n");
@@ -826,9 +823,9 @@ static int video_open(struct file *file)
                }
                call_all(core, tuner, s_radio);
        }
-       unlock_kernel();
 
        atomic_inc(&core->users);
+       mutex_unlock(&core->lock);
 
        return 0;
 }
@@ -920,10 +917,11 @@ static int video_release(struct file *file)
 
        videobuf_mmap_free(&fh->vidq);
        videobuf_mmap_free(&fh->vbiq);
+
+       mutex_lock(&dev->core->lock);
        file->private_data = NULL;
        kfree(fh);
 
-       mutex_lock(&dev->core->lock);
        if(atomic_dec_and_test(&dev->core->users))
                call_all(dev->core, core, s_power, 0);
        mutex_unlock(&dev->core->lock);
@@ -979,6 +977,7 @@ int cx88_set_control(struct cx88_core *core, struct v4l2_control *ctl)
        const struct cx88_ctrl *c = NULL;
        u32 value,mask;
        int i;
+       struct v4l2_control client_ctl;
 
        for (i = 0; i < CX8800_CTLS; i++) {
                if (cx8800_ctls[i].v.id == ctl->id) {
@@ -992,6 +991,27 @@ int cx88_set_control(struct cx88_core *core, struct v4l2_control *ctl)
                ctl->value = c->v.minimum;
        if (ctl->value > c->v.maximum)
                ctl->value = c->v.maximum;
+
+       /* Pass changes onto any WM8775 */
+       client_ctl.id = ctl->id;
+       switch (ctl->id) {
+       case V4L2_CID_AUDIO_MUTE:
+               client_ctl.value = ctl->value;
+               break;
+       case V4L2_CID_AUDIO_VOLUME:
+               client_ctl.value = (ctl->value) ?
+                       (0x90 + ctl->value) << 8 : 0;
+               break;
+       case V4L2_CID_AUDIO_BALANCE:
+               client_ctl.value = ctl->value << 9;
+               break;
+       default:
+               client_ctl.id = 0;
+               break;
+       }
+       if (client_ctl.id)
+               call_hw(core, WM8775_GID, core, s_ctrl, &client_ctl);
+
        mask=c->mask;
        switch (ctl->id) {
        case V4L2_CID_AUDIO_BALANCE:
@@ -1538,7 +1558,9 @@ static int radio_queryctrl (struct file *file, void *priv,
        if (c->id <  V4L2_CID_BASE ||
                c->id >= V4L2_CID_LASTP1)
                return -EINVAL;
-       if (c->id == V4L2_CID_AUDIO_MUTE) {
+       if (c->id == V4L2_CID_AUDIO_MUTE ||
+               c->id == V4L2_CID_AUDIO_VOLUME ||
+               c->id == V4L2_CID_AUDIO_BALANCE) {
                for (i = 0; i < CX8800_CTLS; i++) {
                        if (cx8800_ctls[i].v.id == c->id)
                                break;
@@ -1873,14 +1895,14 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev,
 
        if (core->board.audio_chip == V4L2_IDENT_WM8775)
                v4l2_i2c_new_subdev(&core->v4l2_dev, &core->i2c_adap,
-                               "wm8775", "wm8775", 0x36 >> 1, NULL);
+                               NULL, "wm8775", 0x36 >> 1, NULL);
 
        if (core->board.audio_chip == V4L2_IDENT_TVAUDIO) {
                /* This probes for a tda9874 as is used on some
                   Pixelview Ultra boards. */
                v4l2_i2c_new_subdev(&core->v4l2_dev,
                                &core->i2c_adap,
-                               "tvaudio", "tvaudio", 0, I2C_ADDRS(0xb0 >> 1));
+                               NULL, "tvaudio", 0, I2C_ADDRS(0xb0 >> 1));
        }
 
        switch (core->boardnr) {