Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ab49ae0f authored by Hans Verkuil's avatar Hans Verkuil Committed by Mauro Carvalho Chehab
Browse files

[media] saa7146: fix querycap, vbi/video separation and g/s_register



The querycap ioctl returned an incorrect version number and incorrect
capabilities (mixing up vbi and video caps).

The reason for that was that video nodes could do vbi activities: that
should be separated between the vbi and video nodes.

There were also a few minor problems with dbg_g/s_register that have
been resolved. The mxb/saa7146 driver now passes the v4l2_compliance tests.

Signed-off-by: default avatarHans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 537fa492
Loading
Loading
Loading
Loading
+6 −2
Original line number Diff line number Diff line
@@ -478,7 +478,8 @@ int saa7146_vv_init(struct saa7146_dev* dev, struct saa7146_ext_vv *ext_vv)
		v4l2_ctrl_handler_free(hdl);
		return -ENOMEM;
	}
	ext_vv->ops = saa7146_video_ioctl_ops;
	ext_vv->vid_ops = saa7146_video_ioctl_ops;
	ext_vv->vbi_ops = saa7146_vbi_ioctl_ops;
	ext_vv->core_ops = &saa7146_video_ioctl_ops;

	DEB_EE("dev:%p\n", dev);
@@ -579,7 +580,10 @@ int saa7146_register_device(struct video_device **vid, struct saa7146_dev* dev,
		return -ENOMEM;

	vfd->fops = &video_fops;
	vfd->ioctl_ops = &dev->ext_vv_data->ops;
	if (type == VFL_TYPE_GRABBER)
		vfd->ioctl_ops = &dev->ext_vv_data->vid_ops;
	else
		vfd->ioctl_ops = &dev->ext_vv_data->vbi_ops;
	vfd->release = video_device_release;
	/* Locking in file operations other than ioctl should be done by
	   the driver, not the V4L2 core.
+31 −4
Original line number Diff line number Diff line
@@ -446,18 +446,24 @@ static int video_end(struct saa7146_fh *fh, struct file *file)

static int vidioc_querycap(struct file *file, void *fh, struct v4l2_capability *cap)
{
	struct video_device *vdev = video_devdata(file);
	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;

	strcpy((char *)cap->driver, "saa7146 v4l2");
	strlcpy((char *)cap->card, dev->ext->name, sizeof(cap->card));
	sprintf((char *)cap->bus_info, "PCI:%s", pci_name(dev->pci));
	cap->version = SAA7146_VERSION_CODE;
	cap->device_caps =
		V4L2_CAP_VIDEO_CAPTURE |
		V4L2_CAP_VIDEO_OVERLAY |
		V4L2_CAP_READWRITE |
		V4L2_CAP_STREAMING;
	cap->device_caps |= dev->ext_vv_data->capabilities;
	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;
	return 0;
}
@@ -990,10 +996,14 @@ static int vidioc_g_chip_ident(struct file *file, void *__fh,

	chip->ident = V4L2_IDENT_NONE;
	chip->revision = 0;
	if (chip->match.type == V4L2_CHIP_MATCH_HOST && !chip->match.addr) {
	if (chip->match.type == V4L2_CHIP_MATCH_HOST) {
		if (v4l2_chip_match_host(&chip->match))
			chip->ident = V4L2_IDENT_SAA7146;
		return 0;
	}
	if (chip->match.type != V4L2_CHIP_MATCH_I2C_DRIVER &&
	    chip->match.type != V4L2_CHIP_MATCH_I2C_ADDR)
		return -EINVAL;
	return v4l2_device_call_until_err(&dev->v4l2_dev, 0,
			core, g_chip_ident, chip);
}
@@ -1008,7 +1018,6 @@ const struct v4l2_ioctl_ops saa7146_video_ioctl_ops = {
	.vidioc_g_fmt_vid_overlay    = vidioc_g_fmt_vid_overlay,
	.vidioc_try_fmt_vid_overlay  = vidioc_try_fmt_vid_overlay,
	.vidioc_s_fmt_vid_overlay    = vidioc_s_fmt_vid_overlay,
	.vidioc_g_fmt_vbi_cap        = vidioc_g_fmt_vbi_cap,
	.vidioc_g_chip_ident         = vidioc_g_chip_ident,

	.vidioc_overlay 	     = vidioc_overlay,
@@ -1027,6 +1036,24 @@ const struct v4l2_ioctl_ops saa7146_video_ioctl_ops = {
	.vidioc_unsubscribe_event    = v4l2_event_unsubscribe,
};

const struct v4l2_ioctl_ops saa7146_vbi_ioctl_ops = {
	.vidioc_querycap             = vidioc_querycap,
	.vidioc_g_fmt_vbi_cap        = vidioc_g_fmt_vbi_cap,
	.vidioc_g_chip_ident         = vidioc_g_chip_ident,

	.vidioc_reqbufs              = vidioc_reqbufs,
	.vidioc_querybuf             = vidioc_querybuf,
	.vidioc_qbuf                 = vidioc_qbuf,
	.vidioc_dqbuf                = vidioc_dqbuf,
	.vidioc_g_std                = vidioc_g_std,
	.vidioc_s_std                = vidioc_s_std,
	.vidioc_streamon             = vidioc_streamon,
	.vidioc_streamoff            = vidioc_streamoff,
	.vidioc_g_parm		     = vidioc_g_parm,
	.vidioc_subscribe_event      = v4l2_ctrl_subscribe_event,
	.vidioc_unsubscribe_event    = v4l2_event_unsubscribe,
};

/*********************************************************************************/
/* buffer handling functions                                                  */

+12 −12
Original line number Diff line number Diff line
@@ -802,18 +802,18 @@ int av7110_init_v4l(struct av7110 *av7110)
		ERR("cannot init capture device. skipping\n");
		return -ENODEV;
	}
	vv_data->ops.vidioc_enum_input = vidioc_enum_input;
	vv_data->ops.vidioc_g_input = vidioc_g_input;
	vv_data->ops.vidioc_s_input = vidioc_s_input;
	vv_data->ops.vidioc_g_tuner = vidioc_g_tuner;
	vv_data->ops.vidioc_s_tuner = vidioc_s_tuner;
	vv_data->ops.vidioc_g_frequency = vidioc_g_frequency;
	vv_data->ops.vidioc_s_frequency = vidioc_s_frequency;
	vv_data->ops.vidioc_g_audio = vidioc_g_audio;
	vv_data->ops.vidioc_s_audio = vidioc_s_audio;
	vv_data->ops.vidioc_g_sliced_vbi_cap = vidioc_g_sliced_vbi_cap;
	vv_data->ops.vidioc_g_fmt_sliced_vbi_out = vidioc_g_fmt_sliced_vbi_out;
	vv_data->ops.vidioc_s_fmt_sliced_vbi_out = vidioc_s_fmt_sliced_vbi_out;
	vv_data->vid_ops.vidioc_enum_input = vidioc_enum_input;
	vv_data->vid_ops.vidioc_g_input = vidioc_g_input;
	vv_data->vid_ops.vidioc_s_input = vidioc_s_input;
	vv_data->vid_ops.vidioc_g_tuner = vidioc_g_tuner;
	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_g_audio = vidioc_g_audio;
	vv_data->vid_ops.vidioc_s_audio = vidioc_s_audio;
	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 (saa7146_register_device(&av7110->v4l_dev, dev, "av7110", VFL_TYPE_GRABBER)) {
		ERR("cannot register capture device. skipping\n");
+3 −3
Original line number Diff line number Diff line
@@ -1483,9 +1483,9 @@ static int budget_av_attach(struct saa7146_dev *dev, struct saa7146_pci_extensio
			ERR("cannot init vv subsystem\n");
			return err;
		}
		vv_data.ops.vidioc_enum_input = vidioc_enum_input;
		vv_data.ops.vidioc_g_input = vidioc_g_input;
		vv_data.ops.vidioc_s_input = vidioc_s_input;
		vv_data.vid_ops.vidioc_enum_input = vidioc_enum_input;
		vv_data.vid_ops.vidioc_g_input = vidioc_g_input;
		vv_data.vid_ops.vidioc_s_input = vidioc_s_input;

		if ((err = saa7146_register_device(&budget_av->vd, dev, "knc1", VFL_TYPE_GRABBER))) {
			/* fixme: proper cleanup here */
+6 −6
Original line number Diff line number Diff line
@@ -399,12 +399,12 @@ static int hexium_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_d
	hexium->cur_input = 0;

	saa7146_vv_init(dev, &vv_data);
	vv_data.ops.vidioc_queryctrl = vidioc_queryctrl;
	vv_data.ops.vidioc_g_ctrl = vidioc_g_ctrl;
	vv_data.ops.vidioc_s_ctrl = vidioc_s_ctrl;
	vv_data.ops.vidioc_enum_input = vidioc_enum_input;
	vv_data.ops.vidioc_g_input = vidioc_g_input;
	vv_data.ops.vidioc_s_input = vidioc_s_input;
	vv_data.vid_ops.vidioc_queryctrl = vidioc_queryctrl;
	vv_data.vid_ops.vidioc_g_ctrl = vidioc_g_ctrl;
	vv_data.vid_ops.vidioc_s_ctrl = vidioc_s_ctrl;
	vv_data.vid_ops.vidioc_enum_input = vidioc_enum_input;
	vv_data.vid_ops.vidioc_g_input = vidioc_g_input;
	vv_data.vid_ops.vidioc_s_input = vidioc_s_input;
	ret = saa7146_register_device(&hexium->video_dev, dev, "hexium gemini", VFL_TYPE_GRABBER);
	if (ret < 0) {
		pr_err("cannot register capture v4l2 device. skipping.\n");
Loading