[media] av7110: fix v4l2_compliance test issues
authorHans Verkuil <hans.verkuil@cisco.com>
Sun, 6 May 2012 16:31:27 +0000 (13:31 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Mon, 14 May 2012 18:04:11 +0000 (15:04 -0300)
Besides the usual inconsistencies in input enumeration there was also a
kernel crash if you tried to poll on a vbi node. The checks for sliced
vbi output vs vbi capture were not complete enough.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
drivers/media/common/saa7146_fops.c
drivers/media/common/saa7146_video.c
drivers/media/dvb/ttpci/av7110_v4l.c

index 428a543ec2cea2dd7305032f66e20112e6ba076f..7d42c11c868434020c8aaddc2c6b9a0fee5d96aa 100644 (file)
@@ -309,6 +309,8 @@ static int fops_mmap(struct file *file, struct vm_area_struct * vma)
        case VFL_TYPE_VBI: {
                DEB_EE("V4L2_BUF_TYPE_VBI_CAPTURE: file:%p, vma:%p\n",
                       file, vma);
+               if (fh->dev->ext_vv_data->capabilities & V4L2_CAP_SLICED_VBI_OUTPUT)
+                       return -ENODEV;
                q = &fh->vbi_q;
                break;
                }
@@ -331,6 +333,8 @@ static unsigned int fops_poll(struct file *file, struct poll_table_struct *wait)
        DEB_EE("file:%p, poll:%p\n", file, wait);
 
        if (vdev->vfl_type == VFL_TYPE_VBI) {
+               if (fh->dev->ext_vv_data->capabilities & V4L2_CAP_SLICED_VBI_OUTPUT)
+                       return res | POLLOUT | POLLWRNORM;
                if( 0 == fh->vbi_q.streaming )
                        return res | videobuf_poll_stream(file, &fh->vbi_q, wait);
                q = &fh->vbi_q;
index 9d193208b8929bec08e1a6f0ecc74f0a306668ce..6d14785d47471fd1c290c5ee43cf792ac30245f7 100644 (file)
@@ -458,13 +458,13 @@ static int vidioc_querycap(struct file *file, void *fh, struct v4l2_capability *
                V4L2_CAP_READWRITE |
                V4L2_CAP_STREAMING;
        cap->device_caps |= dev->ext_vv_data->capabilities;
+       cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
        if (vdev->vfl_type == VFL_TYPE_GRABBER)
                cap->device_caps &=
                        ~(V4L2_CAP_VBI_CAPTURE | V4L2_CAP_SLICED_VBI_OUTPUT);
        else
                cap->device_caps &=
-                       ~(V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OVERLAY);
-       cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
+                       ~(V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OVERLAY | V4L2_CAP_AUDIO);
        return 0;
 }
 
index 3b7a624b5e9f58aa8afc843e12ceb85276c4a7ca..1b2d15140a1d938f63269b1d94c224e36197b976 100644 (file)
@@ -107,7 +107,7 @@ static struct v4l2_input inputs[4] = {
                .index          = 1,
                .name           = "Television",
                .type           = V4L2_INPUT_TYPE_TUNER,
-               .audioset       = 2,
+               .audioset       = 1,
                .tuner          = 0,
                .std            = V4L2_STD_PAL_BG|V4L2_STD_NTSC_M,
                .status         = 0,
@@ -494,7 +494,7 @@ static int vidioc_s_input(struct file *file, void *fh, unsigned int input)
        dprintk(2, "VIDIOC_S_INPUT: %d\n", input);
 
        if (!av7110->analog_tuner_flags)
-               return 0;
+               return input ? -EINVAL : 0;
 
        if (input >= 4)
                return -EINVAL;
@@ -503,19 +503,38 @@ static int vidioc_s_input(struct file *file, void *fh, unsigned int input)
        return av7110_dvb_c_switch(fh);
 }
 
+static int vidioc_enumaudio(struct file *file, void *fh, struct v4l2_audio *a)
+{
+       dprintk(2, "VIDIOC_G_AUDIO: %d\n", a->index);
+       if (a->index != 0)
+               return -EINVAL;
+       *a = msp3400_v4l2_audio;
+       return 0;
+}
+
 static int vidioc_g_audio(struct file *file, void *fh, struct v4l2_audio *a)
 {
+       struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+       struct av7110 *av7110 = (struct av7110 *)dev->ext_priv;
+
        dprintk(2, "VIDIOC_G_AUDIO: %d\n", a->index);
        if (a->index != 0)
                return -EINVAL;
-       memcpy(a, &msp3400_v4l2_audio, sizeof(struct v4l2_audio));
+       if (av7110->current_input >= 2)
+               return -EINVAL;
+       *a = msp3400_v4l2_audio;
        return 0;
 }
 
 static int vidioc_s_audio(struct file *file, void *fh, struct v4l2_audio *a)
 {
+       struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+       struct av7110 *av7110 = (struct av7110 *)dev->ext_priv;
+
        dprintk(2, "VIDIOC_S_AUDIO: %d\n", a->index);
-       return 0;
+       if (av7110->current_input >= 2)
+               return -EINVAL;
+       return a->index ? -EINVAL : 0;
 }
 
 static int vidioc_g_sliced_vbi_cap(struct file *file, void *fh,
@@ -809,29 +828,32 @@ int av7110_init_v4l(struct av7110 *av7110)
        vv_data->vid_ops.vidioc_s_tuner = vidioc_s_tuner;
        vv_data->vid_ops.vidioc_g_frequency = vidioc_g_frequency;
        vv_data->vid_ops.vidioc_s_frequency = vidioc_s_frequency;
+       vv_data->vid_ops.vidioc_enumaudio = vidioc_enumaudio;
        vv_data->vid_ops.vidioc_g_audio = vidioc_g_audio;
        vv_data->vid_ops.vidioc_s_audio = vidioc_s_audio;
+       vv_data->vid_ops.vidioc_g_fmt_vbi_cap = NULL;
 
-       vv_data->vbi_ops.vidioc_enum_input = vidioc_enum_input;
-       vv_data->vbi_ops.vidioc_g_input = vidioc_g_input;
-       vv_data->vbi_ops.vidioc_s_input = vidioc_s_input;
        vv_data->vbi_ops.vidioc_g_tuner = vidioc_g_tuner;
        vv_data->vbi_ops.vidioc_s_tuner = vidioc_s_tuner;
        vv_data->vbi_ops.vidioc_g_frequency = vidioc_g_frequency;
        vv_data->vbi_ops.vidioc_s_frequency = vidioc_s_frequency;
-       vv_data->vbi_ops.vidioc_g_audio = vidioc_g_audio;
-       vv_data->vbi_ops.vidioc_s_audio = vidioc_s_audio;
+       vv_data->vbi_ops.vidioc_g_fmt_vbi_cap = NULL;
        vv_data->vbi_ops.vidioc_g_sliced_vbi_cap = vidioc_g_sliced_vbi_cap;
        vv_data->vbi_ops.vidioc_g_fmt_sliced_vbi_out = vidioc_g_fmt_sliced_vbi_out;
        vv_data->vbi_ops.vidioc_s_fmt_sliced_vbi_out = vidioc_s_fmt_sliced_vbi_out;
 
+       if (FW_VERSION(av7110->arm_app) < 0x2623)
+               vv_data->capabilities &= ~V4L2_CAP_SLICED_VBI_OUTPUT;
+
        if (saa7146_register_device(&av7110->v4l_dev, dev, "av7110", VFL_TYPE_GRABBER)) {
                ERR("cannot register capture device. skipping\n");
                saa7146_vv_release(dev);
                return -ENODEV;
        }
-       if (saa7146_register_device(&av7110->vbi_dev, dev, "av7110", VFL_TYPE_VBI))
-               ERR("cannot register vbi v4l2 device. skipping\n");
+       if (FW_VERSION(av7110->arm_app) >= 0x2623) {
+               if (saa7146_register_device(&av7110->vbi_dev, dev, "av7110", VFL_TYPE_VBI))
+                       ERR("cannot register vbi v4l2 device. skipping\n");
+       }
        return 0;
 }
 
@@ -915,7 +937,7 @@ static int std_callback(struct saa7146_dev* dev, struct saa7146_standard *std)
 static struct saa7146_ext_vv av7110_vv_data_st = {
        .inputs         = 1,
        .audios         = 1,
-       .capabilities   = V4L2_CAP_SLICED_VBI_OUTPUT,
+       .capabilities   = V4L2_CAP_SLICED_VBI_OUTPUT | V4L2_CAP_AUDIO,
        .flags          = 0,
 
        .stds           = &standard[0],
@@ -930,7 +952,7 @@ static struct saa7146_ext_vv av7110_vv_data_st = {
 static struct saa7146_ext_vv av7110_vv_data_c = {
        .inputs         = 1,
        .audios         = 1,
-       .capabilities   = V4L2_CAP_TUNER | V4L2_CAP_SLICED_VBI_OUTPUT,
+       .capabilities   = V4L2_CAP_TUNER | V4L2_CAP_SLICED_VBI_OUTPUT | V4L2_CAP_AUDIO,
        .flags          = SAA7146_USE_PORT_B_FOR_VBI,
 
        .stds           = &standard[0],