Commit aee5c2f1 authored by Guennadi Liakhovetski's avatar Guennadi Liakhovetski Committed by Mauro Carvalho Chehab
Browse files

[media] V4L: soc-camera: add a livecrop host operation



Add an soc-camera host livecrop operation to implement live zoom. If
a host driver implements it, it should take care to preserve output
frame format, then live crop doesn't break streaming.

Signed-off-by: default avatarGuennadi Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 08a31b96
Loading
Loading
Loading
Loading
+14 −6
Original line number Diff line number Diff line
@@ -41,6 +41,11 @@
#define DEFAULT_WIDTH	640
#define DEFAULT_HEIGHT	480

#define is_streaming(ici, icd)				\
	(((ici)->ops->init_videobuf) ?			\
	 (icd)->vb_vidq.streaming :			\
	 vb2_is_streaming(&(icd)->vb2_vidq))

static LIST_HEAD(hosts);
static LIST_HEAD(devices);
static DEFINE_MUTEX(list_lock);		/* Protects the list of hosts */
@@ -662,7 +667,7 @@ static int soc_camera_s_fmt_vid_cap(struct file *file, void *priv,
	if (icd->streamer && icd->streamer != file)
		return -EBUSY;

	if (icd->vb_vidq.bufs[0]) {
	if (is_streaming(to_soc_camera_host(icd->dev.parent), icd)) {
		dev_err(&icd->dev, "S_FMT denied: queue initialised\n");
		return -EBUSY;
	}
@@ -903,14 +908,17 @@ static int soc_camera_s_crop(struct file *file, void *fh,
	if (ret < 0) {
		dev_err(&icd->dev,
			"S_CROP denied: getting current crop failed\n");
	} else if (icd->vb_vidq.bufs[0] &&
		   (a->c.width != current_crop.c.width ||
		    a->c.height != current_crop.c.height)) {
	} else if ((a->c.width == current_crop.c.width &&
		    a->c.height == current_crop.c.height) ||
		   !is_streaming(ici, icd)) {
		/* same size or not streaming - use .set_crop() */
		ret = ici->ops->set_crop(icd, a);
	} else if (ici->ops->set_livecrop) {
		ret = ici->ops->set_livecrop(icd, a);
	} else {
		dev_err(&icd->dev,
			"S_CROP denied: queue initialised and sizes differ\n");
		ret = -EBUSY;
	} else {
		ret = ici->ops->set_crop(icd, a);
	}

	return ret;
+5 −0
Original line number Diff line number Diff line
@@ -80,6 +80,11 @@ struct soc_camera_host_ops {
	int (*cropcap)(struct soc_camera_device *, struct v4l2_cropcap *);
	int (*get_crop)(struct soc_camera_device *, struct v4l2_crop *);
	int (*set_crop)(struct soc_camera_device *, struct v4l2_crop *);
	/*
	 * The difference to .set_crop() is, that .set_livecrop is not allowed
	 * to change the output sizes
	 */
	int (*set_livecrop)(struct soc_camera_device *, struct v4l2_crop *);
	int (*set_fmt)(struct soc_camera_device *, struct v4l2_format *);
	int (*try_fmt)(struct soc_camera_device *, struct v4l2_format *);
	void (*init_videobuf)(struct videobuf_queue *,