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

Commit b4972652 authored by Nick Dyer's avatar Nick Dyer Committed by Mauro Carvalho Chehab
Browse files

[media] Input: sur40 - use new V4L2 touch input type



Support both V4L2_TCH_FMT_TU08 and V4L2_PIX_FMT_GREY for backwards
compatibility.

Signed-off-by: default avatarNick Dyer <nick@shmanahar.org>
Signed-off-by: default avatarHans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@s-opensource.com>
Acked-by: default avatarDmitry Torokhov <dmitry.torokhov@gmail.com>
parent 3a762dbd
Loading
Loading
Loading
Loading
+91 −33
Original line number Original line Diff line number Diff line
@@ -139,6 +139,27 @@ struct sur40_image_header {
#define SUR40_GET_STATE   0xc5 /*  4 bytes state (?) */
#define SUR40_GET_STATE   0xc5 /*  4 bytes state (?) */
#define SUR40_GET_SENSORS 0xb1 /*  8 bytes sensors   */
#define SUR40_GET_SENSORS 0xb1 /*  8 bytes sensors   */


static const struct v4l2_pix_format sur40_pix_format[] = {
	{
		.pixelformat = V4L2_TCH_FMT_TU08,
		.width  = SENSOR_RES_X / 2,
		.height = SENSOR_RES_Y / 2,
		.field = V4L2_FIELD_NONE,
		.colorspace = V4L2_COLORSPACE_SRGB,
		.bytesperline = SENSOR_RES_X / 2,
		.sizeimage = (SENSOR_RES_X/2) * (SENSOR_RES_Y/2),
	},
	{
		.pixelformat = V4L2_PIX_FMT_GREY,
		.width  = SENSOR_RES_X / 2,
		.height = SENSOR_RES_Y / 2,
		.field = V4L2_FIELD_NONE,
		.colorspace = V4L2_COLORSPACE_SRGB,
		.bytesperline = SENSOR_RES_X / 2,
		.sizeimage = (SENSOR_RES_X/2) * (SENSOR_RES_Y/2),
	}
};

/* master device state */
/* master device state */
struct sur40_state {
struct sur40_state {


@@ -149,6 +170,7 @@ struct sur40_state {
	struct v4l2_device v4l2;
	struct v4l2_device v4l2;
	struct video_device vdev;
	struct video_device vdev;
	struct mutex lock;
	struct mutex lock;
	struct v4l2_pix_format pix_fmt;


	struct vb2_queue queue;
	struct vb2_queue queue;
	struct list_head buf_list;
	struct list_head buf_list;
@@ -169,7 +191,6 @@ struct sur40_buffer {


/* forward declarations */
/* forward declarations */
static const struct video_device sur40_video_device;
static const struct video_device sur40_video_device;
static const struct v4l2_pix_format sur40_video_format;
static const struct vb2_queue sur40_queue;
static const struct vb2_queue sur40_queue;
static void sur40_process_video(struct sur40_state *sur40);
static void sur40_process_video(struct sur40_state *sur40);


@@ -420,7 +441,7 @@ static void sur40_process_video(struct sur40_state *sur40)
		goto err_poll;
		goto err_poll;
	}
	}


	if (le32_to_cpu(img->size) != sur40_video_format.sizeimage) {
	if (le32_to_cpu(img->size) != sur40->pix_fmt.sizeimage) {
		dev_err(sur40->dev, "image size mismatch\n");
		dev_err(sur40->dev, "image size mismatch\n");
		goto err_poll;
		goto err_poll;
	}
	}
@@ -431,7 +452,7 @@ static void sur40_process_video(struct sur40_state *sur40)


	result = usb_sg_init(&sgr, sur40->usbdev,
	result = usb_sg_init(&sgr, sur40->usbdev,
		usb_rcvbulkpipe(sur40->usbdev, VIDEO_ENDPOINT), 0,
		usb_rcvbulkpipe(sur40->usbdev, VIDEO_ENDPOINT), 0,
		sgt->sgl, sgt->nents, sur40_video_format.sizeimage, 0);
		sgt->sgl, sgt->nents, sur40->pix_fmt.sizeimage, 0);
	if (result < 0) {
	if (result < 0) {
		dev_err(sur40->dev, "error %d in usb_sg_init\n", result);
		dev_err(sur40->dev, "error %d in usb_sg_init\n", result);
		goto err_poll;
		goto err_poll;
@@ -586,13 +607,14 @@ static int sur40_probe(struct usb_interface *interface,
	if (error)
	if (error)
		goto err_unreg_v4l2;
		goto err_unreg_v4l2;


	sur40->pix_fmt = sur40_pix_format[0];
	sur40->vdev = sur40_video_device;
	sur40->vdev = sur40_video_device;
	sur40->vdev.v4l2_dev = &sur40->v4l2;
	sur40->vdev.v4l2_dev = &sur40->v4l2;
	sur40->vdev.lock = &sur40->lock;
	sur40->vdev.lock = &sur40->lock;
	sur40->vdev.queue = &sur40->queue;
	sur40->vdev.queue = &sur40->queue;
	video_set_drvdata(&sur40->vdev, sur40);
	video_set_drvdata(&sur40->vdev, sur40);


	error = video_register_device(&sur40->vdev, VFL_TYPE_GRABBER, -1);
	error = video_register_device(&sur40->vdev, VFL_TYPE_TOUCH, -1);
	if (error) {
	if (error) {
		dev_err(&interface->dev,
		dev_err(&interface->dev,
			"Unable to register video subdevice.");
			"Unable to register video subdevice.");
@@ -647,14 +669,16 @@ static int sur40_queue_setup(struct vb2_queue *q,
		       unsigned int *nbuffers, unsigned int *nplanes,
		       unsigned int *nbuffers, unsigned int *nplanes,
		       unsigned int sizes[], struct device *alloc_devs[])
		       unsigned int sizes[], struct device *alloc_devs[])
{
{
	struct sur40_state *sur40 = vb2_get_drv_priv(q);

	if (q->num_buffers + *nbuffers < 3)
	if (q->num_buffers + *nbuffers < 3)
		*nbuffers = 3 - q->num_buffers;
		*nbuffers = 3 - q->num_buffers;


	if (*nplanes)
	if (*nplanes)
		return sizes[0] < sur40_video_format.sizeimage ? -EINVAL : 0;
		return sizes[0] < sur40->pix_fmt.sizeimage ? -EINVAL : 0;


	*nplanes = 1;
	*nplanes = 1;
	sizes[0] = sur40_video_format.sizeimage;
	sizes[0] = sur40->pix_fmt.sizeimage;


	return 0;
	return 0;
}
}
@@ -666,7 +690,7 @@ static int sur40_queue_setup(struct vb2_queue *q,
static int sur40_buffer_prepare(struct vb2_buffer *vb)
static int sur40_buffer_prepare(struct vb2_buffer *vb)
{
{
	struct sur40_state *sur40 = vb2_get_drv_priv(vb->vb2_queue);
	struct sur40_state *sur40 = vb2_get_drv_priv(vb->vb2_queue);
	unsigned long size = sur40_video_format.sizeimage;
	unsigned long size = sur40->pix_fmt.sizeimage;


	if (vb2_plane_size(vb, 0) < size) {
	if (vb2_plane_size(vb, 0) < size) {
		dev_err(&sur40->usbdev->dev, "buffer too small (%lu < %lu)\n",
		dev_err(&sur40->usbdev->dev, "buffer too small (%lu < %lu)\n",
@@ -741,7 +765,7 @@ static int sur40_vidioc_querycap(struct file *file, void *priv,
	strlcpy(cap->driver, DRIVER_SHORT, sizeof(cap->driver));
	strlcpy(cap->driver, DRIVER_SHORT, sizeof(cap->driver));
	strlcpy(cap->card, DRIVER_LONG, sizeof(cap->card));
	strlcpy(cap->card, DRIVER_LONG, sizeof(cap->card));
	usb_make_path(sur40->usbdev, cap->bus_info, sizeof(cap->bus_info));
	usb_make_path(sur40->usbdev, cap->bus_info, sizeof(cap->bus_info));
	cap->device_caps = V4L2_CAP_VIDEO_CAPTURE |
	cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_TOUCH |
		V4L2_CAP_READWRITE |
		V4L2_CAP_READWRITE |
		V4L2_CAP_STREAMING;
		V4L2_CAP_STREAMING;
	cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
	cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
@@ -753,7 +777,7 @@ static int sur40_vidioc_enum_input(struct file *file, void *priv,
{
{
	if (i->index != 0)
	if (i->index != 0)
		return -EINVAL;
		return -EINVAL;
	i->type = V4L2_INPUT_TYPE_CAMERA;
	i->type = V4L2_INPUT_TYPE_TOUCH;
	i->std = V4L2_STD_UNKNOWN;
	i->std = V4L2_STD_UNKNOWN;
	strlcpy(i->name, "In-Cell Sensor", sizeof(i->name));
	strlcpy(i->name, "In-Cell Sensor", sizeof(i->name));
	i->capabilities = 0;
	i->capabilities = 0;
@@ -771,19 +795,57 @@ static int sur40_vidioc_g_input(struct file *file, void *priv, unsigned int *i)
	return 0;
	return 0;
}
}


static int sur40_vidioc_fmt(struct file *file, void *priv,
static int sur40_vidioc_try_fmt(struct file *file, void *priv,
			    struct v4l2_format *f)
			    struct v4l2_format *f)
{
{
	f->fmt.pix = sur40_video_format;
	switch (f->fmt.pix.pixelformat) {
	case V4L2_PIX_FMT_GREY:
		f->fmt.pix = sur40_pix_format[1];
		break;

	default:
		f->fmt.pix = sur40_pix_format[0];
		break;
	}

	return 0;
}

static int sur40_vidioc_s_fmt(struct file *file, void *priv,
			    struct v4l2_format *f)
{
	struct sur40_state *sur40 = video_drvdata(file);

	switch (f->fmt.pix.pixelformat) {
	case V4L2_PIX_FMT_GREY:
		sur40->pix_fmt = sur40_pix_format[1];
		break;

	default:
		sur40->pix_fmt = sur40_pix_format[0];
		break;
	}

	f->fmt.pix = sur40->pix_fmt;
	return 0;
}

static int sur40_vidioc_g_fmt(struct file *file, void *priv,
			    struct v4l2_format *f)
{
	struct sur40_state *sur40 = video_drvdata(file);

	f->fmt.pix = sur40->pix_fmt;
	return 0;
	return 0;
}
}


static int sur40_vidioc_enum_fmt(struct file *file, void *priv,
static int sur40_vidioc_enum_fmt(struct file *file, void *priv,
				 struct v4l2_fmtdesc *f)
				 struct v4l2_fmtdesc *f)
{
{
	if (f->index != 0)
	if (f->index >= ARRAY_SIZE(sur40_pix_format))
		return -EINVAL;
		return -EINVAL;
	f->pixelformat = V4L2_PIX_FMT_GREY;

	f->pixelformat = sur40_pix_format[f->index].pixelformat;
	f->flags = 0;
	f->flags = 0;
	return 0;
	return 0;
}
}
@@ -791,21 +853,27 @@ static int sur40_vidioc_enum_fmt(struct file *file, void *priv,
static int sur40_vidioc_enum_framesizes(struct file *file, void *priv,
static int sur40_vidioc_enum_framesizes(struct file *file, void *priv,
					struct v4l2_frmsizeenum *f)
					struct v4l2_frmsizeenum *f)
{
{
	if ((f->index != 0) || (f->pixel_format != V4L2_PIX_FMT_GREY))
	struct sur40_state *sur40 = video_drvdata(file);

	if ((f->index != 0) || ((f->pixel_format != V4L2_TCH_FMT_TU08)
		&& (f->pixel_format != V4L2_PIX_FMT_GREY)))
		return -EINVAL;
		return -EINVAL;


	f->type = V4L2_FRMSIZE_TYPE_DISCRETE;
	f->type = V4L2_FRMSIZE_TYPE_DISCRETE;
	f->discrete.width  = sur40_video_format.width;
	f->discrete.width  = sur40->pix_fmt.width;
	f->discrete.height = sur40_video_format.height;
	f->discrete.height = sur40->pix_fmt.height;
	return 0;
	return 0;
}
}


static int sur40_vidioc_enum_frameintervals(struct file *file, void *priv,
static int sur40_vidioc_enum_frameintervals(struct file *file, void *priv,
					    struct v4l2_frmivalenum *f)
					    struct v4l2_frmivalenum *f)
{
{
	if ((f->index > 1) || (f->pixel_format != V4L2_PIX_FMT_GREY)
	struct sur40_state *sur40 = video_drvdata(file);
		|| (f->width  != sur40_video_format.width)

		|| (f->height != sur40_video_format.height))
	if ((f->index > 1) || ((f->pixel_format != V4L2_TCH_FMT_TU08)
		&& (f->pixel_format != V4L2_PIX_FMT_GREY))
		|| (f->width  != sur40->pix_fmt.width)
		|| (f->height != sur40->pix_fmt.height))
		return -EINVAL;
		return -EINVAL;


	f->type = V4L2_FRMIVAL_TYPE_DISCRETE;
	f->type = V4L2_FRMIVAL_TYPE_DISCRETE;
@@ -862,9 +930,9 @@ static const struct v4l2_ioctl_ops sur40_video_ioctl_ops = {
	.vidioc_querycap	= sur40_vidioc_querycap,
	.vidioc_querycap	= sur40_vidioc_querycap,


	.vidioc_enum_fmt_vid_cap = sur40_vidioc_enum_fmt,
	.vidioc_enum_fmt_vid_cap = sur40_vidioc_enum_fmt,
	.vidioc_try_fmt_vid_cap	= sur40_vidioc_fmt,
	.vidioc_try_fmt_vid_cap	= sur40_vidioc_try_fmt,
	.vidioc_s_fmt_vid_cap	= sur40_vidioc_fmt,
	.vidioc_s_fmt_vid_cap	= sur40_vidioc_s_fmt,
	.vidioc_g_fmt_vid_cap	= sur40_vidioc_fmt,
	.vidioc_g_fmt_vid_cap	= sur40_vidioc_g_fmt,


	.vidioc_enum_framesizes = sur40_vidioc_enum_framesizes,
	.vidioc_enum_framesizes = sur40_vidioc_enum_framesizes,
	.vidioc_enum_frameintervals = sur40_vidioc_enum_frameintervals,
	.vidioc_enum_frameintervals = sur40_vidioc_enum_frameintervals,
@@ -891,16 +959,6 @@ static const struct video_device sur40_video_device = {
	.release = video_device_release_empty,
	.release = video_device_release_empty,
};
};


static const struct v4l2_pix_format sur40_video_format = {
	.pixelformat = V4L2_PIX_FMT_GREY,
	.width  = SENSOR_RES_X / 2,
	.height = SENSOR_RES_Y / 2,
	.field = V4L2_FIELD_NONE,
	.colorspace = V4L2_COLORSPACE_SRGB,
	.bytesperline = SENSOR_RES_X / 2,
	.sizeimage = (SENSOR_RES_X/2) * (SENSOR_RES_Y/2),
};

/* USB-specific object needed to register this driver with the USB subsystem. */
/* USB-specific object needed to register this driver with the USB subsystem. */
static struct usb_driver sur40_driver = {
static struct usb_driver sur40_driver = {
	.name = DRIVER_SHORT,
	.name = DRIVER_SHORT,