summaryrefslogtreecommitdiff
path: root/drivers/media/platform/soc_camera
diff options
context:
space:
mode:
authorHans Verkuil <hans.verkuil@cisco.com>2015-12-14 08:25:32 -0200
committerMauro Carvalho Chehab <mchehab@s-opensource.com>2016-08-24 09:46:09 -0300
commit10d5509c8d50a2c2f761a08a616530dced35e2d8 (patch)
treee3140b6d25f56cce9fa4a7df00e7e14bb762f54f /drivers/media/platform/soc_camera
parent65d9e14a659520c554feea8ef17ee3109bd67ebd (diff)
[media] v4l2: remove g/s_crop from video ops
Replace all calls to g/s_crop by calls to the get/set_selection pad ops. Remove the old g/s_crop video ops since they are now no longer used. The cropcap video op is now only used to pass pixelaspect information, and is only needed if the pixelaspect is not 1:1. Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Cc: Guennadi Liakhovetski <g.liakhovetski@gmx.de> Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
Diffstat (limited to 'drivers/media/platform/soc_camera')
-rw-r--r--drivers/media/platform/soc_camera/pxa_camera.c17
-rw-r--r--drivers/media/platform/soc_camera/rcar_vin.c30
-rw-r--r--drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c38
-rw-r--r--drivers/media/platform/soc_camera/soc_camera.c130
-rw-r--r--drivers/media/platform/soc_camera/soc_camera_platform.c45
-rw-r--r--drivers/media/platform/soc_camera/soc_scale_crop.c97
-rw-r--r--drivers/media/platform/soc_camera/soc_scale_crop.h6
7 files changed, 157 insertions, 206 deletions
diff --git a/drivers/media/platform/soc_camera/pxa_camera.c b/drivers/media/platform/soc_camera/pxa_camera.c
index 2aaf4a8f71a0..ebbe514d64e2 100644
--- a/drivers/media/platform/soc_camera/pxa_camera.c
+++ b/drivers/media/platform/soc_camera/pxa_camera.c
@@ -1280,10 +1280,10 @@ static int pxa_camera_check_frame(u32 width, u32 height)
(width & 0x01);
}
-static int pxa_camera_set_crop(struct soc_camera_device *icd,
- const struct v4l2_crop *a)
+static int pxa_camera_set_selection(struct soc_camera_device *icd,
+ struct v4l2_selection *sel)
{
- const struct v4l2_rect *rect = &a->c;
+ const struct v4l2_rect *rect = &sel->r;
struct device *dev = icd->parent;
struct soc_camera_host *ici = to_soc_camera_host(dev);
struct pxa_camera_dev *pcdev = ici->priv;
@@ -1298,13 +1298,19 @@ static int pxa_camera_set_crop(struct soc_camera_device *icd,
struct v4l2_mbus_framefmt *mf = &fmt.format;
struct pxa_cam *cam = icd->host_priv;
u32 fourcc = icd->current_fmt->host_fmt->fourcc;
+ struct v4l2_subdev_selection sdsel = {
+ .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+ .target = sel->target,
+ .flags = sel->flags,
+ .r = sel->r,
+ };
int ret;
/* If PCLK is used to latch data from the sensor, check sense */
if (pcdev->platform_flags & PXA_CAMERA_PCLK_EN)
icd->sense = &sense;
- ret = v4l2_subdev_call(sd, video, s_crop, a);
+ ret = v4l2_subdev_call(sd, pad, set_selection, NULL, &sdsel);
icd->sense = NULL;
@@ -1313,6 +1319,7 @@ static int pxa_camera_set_crop(struct soc_camera_device *icd,
rect->width, rect->height, rect->left, rect->top);
return ret;
}
+ sel->r = sdsel.r;
ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, &fmt);
if (ret < 0)
@@ -1592,7 +1599,7 @@ static struct soc_camera_host_ops pxa_soc_camera_host_ops = {
.remove = pxa_camera_remove_device,
.clock_start = pxa_camera_clock_start,
.clock_stop = pxa_camera_clock_stop,
- .set_crop = pxa_camera_set_crop,
+ .set_selection = pxa_camera_set_selection,
.get_formats = pxa_camera_get_formats,
.put_formats = pxa_camera_put_formats,
.set_fmt = pxa_camera_set_fmt,
diff --git a/drivers/media/platform/soc_camera/rcar_vin.c b/drivers/media/platform/soc_camera/rcar_vin.c
index 9c137522c660..077f12d1575f 100644
--- a/drivers/media/platform/soc_camera/rcar_vin.c
+++ b/drivers/media/platform/soc_camera/rcar_vin.c
@@ -515,7 +515,7 @@ struct rcar_vin_cam {
unsigned int out_width;
unsigned int out_height;
/*
- * User window from S_CROP / G_CROP, produced by client cropping and
+ * User window from S_SELECTION / G_SELECTION, produced by client cropping and
* scaling, VIN scaling and VIN cropping, mapped back onto the client
* input window
*/
@@ -1471,16 +1471,15 @@ static void rcar_vin_put_formats(struct soc_camera_device *icd)
icd->host_priv = NULL;
}
-static int rcar_vin_set_crop(struct soc_camera_device *icd,
- const struct v4l2_crop *a)
+static int rcar_vin_set_selection(struct soc_camera_device *icd,
+ struct v4l2_selection *sel)
{
- struct v4l2_crop a_writable = *a;
- const struct v4l2_rect *rect = &a_writable.c;
+ const struct v4l2_rect *rect = &sel->r;
struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
struct rcar_vin_priv *priv = ici->priv;
- struct v4l2_crop cam_crop;
+ struct v4l2_selection cam_sel;
struct rcar_vin_cam *cam = icd->host_priv;
- struct v4l2_rect *cam_rect = &cam_crop.c;
+ struct v4l2_rect *cam_rect = &cam_sel.r;
struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
struct device *dev = icd->parent;
struct v4l2_subdev_format fmt = {
@@ -1490,15 +1489,15 @@ static int rcar_vin_set_crop(struct soc_camera_device *icd,
u32 vnmc;
int ret, i;
- dev_dbg(dev, "S_CROP(%ux%u@%u:%u)\n", rect->width, rect->height,
+ dev_dbg(dev, "S_SELECTION(%ux%u@%u:%u)\n", rect->width, rect->height,
rect->left, rect->top);
/* During camera cropping its output window can change too, stop VIN */
capture_stop_preserve(priv, &vnmc);
dev_dbg(dev, "VNMC_REG 0x%x\n", vnmc);
- /* Apply iterative camera S_CROP for new input window. */
- ret = soc_camera_client_s_crop(sd, &a_writable, &cam_crop,
+ /* Apply iterative camera S_SELECTION for new input window. */
+ ret = soc_camera_client_s_selection(sd, sel, &cam_sel,
&cam->rect, &cam->subrect);
if (ret < 0)
return ret;
@@ -1551,13 +1550,12 @@ static int rcar_vin_set_crop(struct soc_camera_device *icd,
return ret;
}
-static int rcar_vin_get_crop(struct soc_camera_device *icd,
- struct v4l2_crop *a)
+static int rcar_vin_get_selection(struct soc_camera_device *icd,
+ struct v4l2_selection *sel)
{
struct rcar_vin_cam *cam = icd->host_priv;
- a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- a->c = cam->subrect;
+ sel->r = cam->subrect;
return 0;
}
@@ -1824,8 +1822,8 @@ static struct soc_camera_host_ops rcar_vin_host_ops = {
.remove = rcar_vin_remove_device,
.get_formats = rcar_vin_get_formats,
.put_formats = rcar_vin_put_formats,
- .get_crop = rcar_vin_get_crop,
- .set_crop = rcar_vin_set_crop,
+ .get_selection = rcar_vin_get_selection,
+ .set_selection = rcar_vin_set_selection,
.try_fmt = rcar_vin_try_fmt,
.set_fmt = rcar_vin_set_fmt,
.poll = rcar_vin_poll,
diff --git a/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c b/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c
index 05eafe3a421e..e5571c8a368e 100644
--- a/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c
+++ b/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c
@@ -134,7 +134,7 @@ struct sh_mobile_ceu_cam {
unsigned int width;
unsigned int height;
/*
- * User window from S_CROP / G_CROP, produced by client cropping and
+ * User window from S_SELECTION / G_SELECTION, produced by client cropping and
* scaling, CEU scaling and CEU cropping, mapped back onto the client
* input window
*/
@@ -1109,17 +1109,16 @@ static void sh_mobile_ceu_put_formats(struct soc_camera_device *icd)
* Documentation/video4linux/sh_mobile_ceu_camera.txt for a description of
* scaling and cropping algorithms and for the meaning of referenced here steps.
*/
-static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd,
- const struct v4l2_crop *a)
+static int sh_mobile_ceu_set_selection(struct soc_camera_device *icd,
+ struct v4l2_selection *sel)
{
- struct v4l2_crop a_writable = *a;
- const struct v4l2_rect *rect = &a_writable.c;
+ struct v4l2_rect *rect = &sel->r;
struct device *dev = icd->parent;
struct soc_camera_host *ici = to_soc_camera_host(dev);
struct sh_mobile_ceu_dev *pcdev = ici->priv;
- struct v4l2_crop cam_crop;
+ struct v4l2_selection cam_sel;
struct sh_mobile_ceu_cam *cam = icd->host_priv;
- struct v4l2_rect *cam_rect = &cam_crop.c;
+ struct v4l2_rect *cam_rect = &cam_sel.r;
struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
struct v4l2_subdev_format fmt = {
.which = V4L2_SUBDEV_FORMAT_ACTIVE,
@@ -1131,7 +1130,7 @@ static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd,
u32 capsr, cflcr;
int ret;
- dev_geo(dev, "S_CROP(%ux%u@%u:%u)\n", rect->width, rect->height,
+ dev_geo(dev, "S_SELECTION(%ux%u@%u:%u)\n", rect->width, rect->height,
rect->left, rect->top);
/* During camera cropping its output window can change too, stop CEU */
@@ -1139,10 +1138,10 @@ static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd,
dev_dbg(dev, "CAPSR 0x%x, CFLCR 0x%x\n", capsr, pcdev->cflcr);
/*
- * 1. - 2. Apply iterative camera S_CROP for new input window, read back
+ * 1. - 2. Apply iterative camera S_SELECTION for new input window, read back
* actual camera rectangle.
*/
- ret = soc_camera_client_s_crop(sd, &a_writable, &cam_crop,
+ ret = soc_camera_client_s_selection(sd, sel, &cam_sel,
&cam->rect, &cam->subrect);
if (ret < 0)
return ret;
@@ -1251,13 +1250,12 @@ static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd,
return ret;
}
-static int sh_mobile_ceu_get_crop(struct soc_camera_device *icd,
- struct v4l2_crop *a)
+static int sh_mobile_ceu_get_selection(struct soc_camera_device *icd,
+ struct v4l2_selection *sel)
{
struct sh_mobile_ceu_cam *cam = icd->host_priv;
- a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- a->c = cam->subrect;
+ sel->r = cam->subrect;
return 0;
}
@@ -1499,8 +1497,8 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd,
return ret;
}
-static int sh_mobile_ceu_set_livecrop(struct soc_camera_device *icd,
- const struct v4l2_crop *a)
+static int sh_mobile_ceu_set_liveselection(struct soc_camera_device *icd,
+ struct v4l2_selection *sel)
{
struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
@@ -1519,7 +1517,7 @@ static int sh_mobile_ceu_set_livecrop(struct soc_camera_device *icd,
"Client failed to stop the stream: %d\n", ret);
else
/* Do the crop, if it fails, there's nothing more we can do */
- sh_mobile_ceu_set_crop(icd, a);
+ sh_mobile_ceu_set_selection(icd, sel);
dev_geo(icd->parent, "Output after crop: %ux%u\n", icd->user_width, icd->user_height);
@@ -1600,9 +1598,9 @@ static struct soc_camera_host_ops sh_mobile_ceu_host_ops = {
.clock_stop = sh_mobile_ceu_clock_stop,
.get_formats = sh_mobile_ceu_get_formats,
.put_formats = sh_mobile_ceu_put_formats,
- .get_crop = sh_mobile_ceu_get_crop,
- .set_crop = sh_mobile_ceu_set_crop,
- .set_livecrop = sh_mobile_ceu_set_livecrop,
+ .get_selection = sh_mobile_ceu_get_selection,
+ .set_selection = sh_mobile_ceu_set_selection,
+ .set_liveselection = sh_mobile_ceu_set_liveselection,
.set_fmt = sh_mobile_ceu_set_fmt,
.try_fmt = sh_mobile_ceu_try_fmt,
.poll = sh_mobile_ceu_poll,
diff --git a/drivers/media/platform/soc_camera/soc_camera.c b/drivers/media/platform/soc_camera/soc_camera.c
index 46c7186f7867..edd1c1de4e33 100644
--- a/drivers/media/platform/soc_camera/soc_camera.c
+++ b/drivers/media/platform/soc_camera/soc_camera.c
@@ -581,7 +581,7 @@ static int soc_camera_set_fmt(struct soc_camera_device *icd,
dev_dbg(icd->pdev, "S_FMT(%c%c%c%c, %ux%u)\n",
pixfmtstr(pix->pixelformat), pix->width, pix->height);
- /* We always call try_fmt() before set_fmt() or set_crop() */
+ /* We always call try_fmt() before set_fmt() or set_selection() */
ret = soc_camera_try_fmt(icd, f);
if (ret < 0)
return ret;
@@ -1025,72 +1025,6 @@ static int soc_camera_streamoff(struct file *file, void *priv,
return ret;
}
-static int soc_camera_cropcap(struct file *file, void *fh,
- struct v4l2_cropcap *a)
-{
- struct soc_camera_device *icd = file->private_data;
- struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
-
- return ici->ops->cropcap(icd, a);
-}
-
-static int soc_camera_g_crop(struct file *file, void *fh,
- struct v4l2_crop *a)
-{
- struct soc_camera_device *icd = file->private_data;
- struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
- int ret;
-
- ret = ici->ops->get_crop(icd, a);
-
- return ret;
-}
-
-/*
- * According to the V4L2 API, drivers shall not update the struct v4l2_crop
- * argument with the actual geometry, instead, the user shall use G_CROP to
- * retrieve it.
- */
-static int soc_camera_s_crop(struct file *file, void *fh,
- const struct v4l2_crop *a)
-{
- struct soc_camera_device *icd = file->private_data;
- struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
- const struct v4l2_rect *rect = &a->c;
- struct v4l2_crop current_crop;
- int ret;
-
- if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
- return -EINVAL;
-
- dev_dbg(icd->pdev, "S_CROP(%ux%u@%u:%u)\n",
- rect->width, rect->height, rect->left, rect->top);
-
- current_crop.type = a->type;
-
- /* If get_crop fails, we'll let host and / or client drivers decide */
- ret = ici->ops->get_crop(icd, &current_crop);
-
- /* Prohibit window size change with initialised buffers */
- if (ret < 0) {
- dev_err(icd->pdev,
- "S_CROP denied: getting current crop failed\n");
- } 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->pdev,
- "S_CROP denied: queue initialised and sizes differ\n");
- ret = -EBUSY;
- }
-
- return ret;
-}
-
static int soc_camera_g_selection(struct file *file, void *fh,
struct v4l2_selection *s)
{
@@ -1101,9 +1035,6 @@ static int soc_camera_g_selection(struct file *file, void *fh,
if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
return -EINVAL;
- if (!ici->ops->get_selection)
- return -ENOTTY;
-
return ici->ops->get_selection(icd, s);
}
@@ -1135,10 +1066,11 @@ static int soc_camera_s_selection(struct file *file, void *fh,
return -EBUSY;
}
- if (!ici->ops->set_selection)
- return -ENOTTY;
-
- ret = ici->ops->set_selection(icd, s);
+ if (s->target == V4L2_SEL_TGT_CROP && is_streaming(ici, icd) &&
+ ici->ops->set_liveselection)
+ ret = ici->ops->set_liveselection(icd, s);
+ else
+ ret = ici->ops->set_selection(icd, s);
if (!ret &&
s->target == V4L2_SEL_TGT_COMPOSE) {
icd->user_width = s->r.width;
@@ -1881,23 +1813,40 @@ static int soc_camera_remove(struct soc_camera_device *icd)
return 0;
}
-static int default_cropcap(struct soc_camera_device *icd,
- struct v4l2_cropcap *a)
+static int default_g_selection(struct soc_camera_device *icd,
+ struct v4l2_selection *sel)
{
struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
- return v4l2_subdev_call(sd, video, cropcap, a);
-}
+ struct v4l2_subdev_selection sdsel = {
+ .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+ .target = sel->target,
+ };
+ int ret;
-static int default_g_crop(struct soc_camera_device *icd, struct v4l2_crop *a)
-{
- struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
- return v4l2_subdev_call(sd, video, g_crop, a);
+ ret = v4l2_subdev_call(sd, pad, get_selection, NULL, &sdsel);
+ if (ret)
+ return ret;
+ sel->r = sdsel.r;
+ return 0;
}
-static int default_s_crop(struct soc_camera_device *icd, const struct v4l2_crop *a)
+static int default_s_selection(struct soc_camera_device *icd,
+ struct v4l2_selection *sel)
{
struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
- return v4l2_subdev_call(sd, video, s_crop, a);
+ struct v4l2_subdev_selection sdsel = {
+ .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+ .target = sel->target,
+ .flags = sel->flags,
+ .r = sel->r,
+ };
+ int ret;
+
+ ret = v4l2_subdev_call(sd, pad, set_selection, NULL, &sdsel);
+ if (ret)
+ return ret;
+ sel->r = sdsel.r;
+ return 0;
}
static int default_g_parm(struct soc_camera_device *icd,
@@ -1968,12 +1917,10 @@ int soc_camera_host_register(struct soc_camera_host *ici)
!ici->v4l2_dev.dev)
return -EINVAL;
- if (!ici->ops->set_crop)
- ici->ops->set_crop = default_s_crop;
- if (!ici->ops->get_crop)
- ici->ops->get_crop = default_g_crop;
- if (!ici->ops->cropcap)
- ici->ops->cropcap = default_cropcap;
+ if (!ici->ops->set_selection)
+ ici->ops->set_selection = default_s_selection;
+ if (!ici->ops->get_selection)
+ ici->ops->get_selection = default_g_selection;
if (!ici->ops->set_parm)
ici->ops->set_parm = default_s_parm;
if (!ici->ops->get_parm)
@@ -2126,9 +2073,6 @@ static const struct v4l2_ioctl_ops soc_camera_ioctl_ops = {
.vidioc_expbuf = soc_camera_expbuf,
.vidioc_streamon = soc_camera_streamon,
.vidioc_streamoff = soc_camera_streamoff,
- .vidioc_cropcap = soc_camera_cropcap,
- .vidioc_g_crop = soc_camera_g_crop,
- .vidioc_s_crop = soc_camera_s_crop,
.vidioc_g_selection = soc_camera_g_selection,
.vidioc_s_selection = soc_camera_s_selection,
.vidioc_g_parm = soc_camera_g_parm,
diff --git a/drivers/media/platform/soc_camera/soc_camera_platform.c b/drivers/media/platform/soc_camera/soc_camera_platform.c
index a51d2a42998c..534d6c3c6d60 100644
--- a/drivers/media/platform/soc_camera/soc_camera_platform.c
+++ b/drivers/media/platform/soc_camera/soc_camera_platform.c
@@ -76,35 +76,27 @@ static int soc_camera_platform_enum_mbus_code(struct v4l2_subdev *sd,
return 0;
}
-static int soc_camera_platform_g_crop(struct v4l2_subdev *sd,
- struct v4l2_crop *a)
-{
- struct soc_camera_platform_info *p = v4l2_get_subdevdata(sd);
-
- a->c.left = 0;
- a->c.top = 0;
- a->c.width = p->format.width;
- a->c.height = p->format.height;
- a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-
- return 0;
-}
-
-static int soc_camera_platform_cropcap(struct v4l2_subdev *sd,
- struct v4l2_cropcap *a)
+static int soc_camera_platform_get_selection(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_selection *sel)
{
struct soc_camera_platform_info *p = v4l2_get_subdevdata(sd);
- a->bounds.left = 0;
- a->bounds.top = 0;
- a->bounds.width = p->format.width;
- a->bounds.height = p->format.height;
- a->defrect = a->bounds;
- a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- a->pixelaspect.numerator = 1;
- a->pixelaspect.denominator = 1;
+ if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+ return -EINVAL;
- return 0;
+ switch (sel->target) {
+ case V4L2_SEL_TGT_CROP_BOUNDS:
+ case V4L2_SEL_TGT_CROP_DEFAULT:
+ case V4L2_SEL_TGT_CROP:
+ sel->r.left = 0;
+ sel->r.top = 0;
+ sel->r.width = p->format.width;
+ sel->r.height = p->format.height;
+ return 0;
+ default:
+ return -EINVAL;
+ }
}
static int soc_camera_platform_g_mbus_config(struct v4l2_subdev *sd,
@@ -120,13 +112,12 @@ static int soc_camera_platform_g_mbus_config(struct v4l2_subdev *sd,
static struct v4l2_subdev_video_ops platform_subdev_video_ops = {
.s_stream = soc_camera_platform_s_stream,
- .cropcap = soc_camera_platform_cropcap,
- .g_crop = soc_camera_platform_g_crop,
.g_mbus_config = soc_camera_platform_g_mbus_config,
};
static const struct v4l2_subdev_pad_ops platform_subdev_pad_ops = {
.enum_mbus_code = soc_camera_platform_enum_mbus_code,
+ .get_selection = soc_camera_platform_get_selection,
.get_fmt = soc_camera_platform_fill_fmt,
.set_fmt = soc_camera_platform_fill_fmt,
};
diff --git a/drivers/media/platform/soc_camera/soc_scale_crop.c b/drivers/media/platform/soc_camera/soc_scale_crop.c
index bda29bc1b933..f77252d6ccd3 100644
--- a/drivers/media/platform/soc_camera/soc_scale_crop.c
+++ b/drivers/media/platform/soc_camera/soc_scale_crop.c
@@ -40,24 +40,22 @@ static bool is_inside(const struct v4l2_rect *r1, const struct v4l2_rect *r2)
/* Get and store current client crop */
int soc_camera_client_g_rect(struct v4l2_subdev *sd, struct v4l2_rect *rect)
{
- struct v4l2_crop crop;
- struct v4l2_cropcap cap;
+ struct v4l2_subdev_selection sdsel = {
+ .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+ .target = V4L2_SEL_TGT_CROP,
+ };
int ret;
- crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-
- ret = v4l2_subdev_call(sd, video, g_crop, &crop);
+ ret = v4l2_subdev_call(sd, pad, get_selection, NULL, &sdsel);
if (!ret) {
- *rect = crop.c;
+ *rect = sdsel.r;
return ret;
}
- /* Camera driver doesn't support .g_crop(), assume default rectangle */
- cap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-
- ret = v4l2_subdev_call(sd, video, cropcap, &cap);
+ sdsel.target = V4L2_SEL_TGT_CROP_DEFAULT;
+ ret = v4l2_subdev_call(sd, pad, get_selection, NULL, &sdsel);
if (!ret)
- *rect = cap.defrect;
+ *rect = sdsel.r;
return ret;
}
@@ -93,17 +91,27 @@ static void update_subrect(struct v4l2_rect *rect, struct v4l2_rect *subrect)
* 2. if (1) failed, try to double the client image until we get one big enough
* 3. if (2) failed, try to request the maximum image
*/
-int soc_camera_client_s_crop(struct v4l2_subdev *sd,
- struct v4l2_crop *crop, struct v4l2_crop *cam_crop,
+int soc_camera_client_s_selection(struct v4l2_subdev *sd,
+ struct v4l2_selection *sel, struct v4l2_selection *cam_sel,
struct v4l2_rect *target_rect, struct v4l2_rect *subrect)
{
- struct v4l2_rect *rect = &crop->c, *cam_rect = &cam_crop->c;
+ struct v4l2_subdev_selection sdsel = {
+ .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+ .target = sel->target,
+ .flags = sel->flags,
+ .r = sel->r,
+ };
+ struct v4l2_subdev_selection bounds = {
+ .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+ .target = V4L2_SEL_TGT_CROP_BOUNDS,
+ };
+ struct v4l2_rect *rect = &sel->r, *cam_rect = &cam_sel->r;
struct device *dev = sd->v4l2_dev->dev;
- struct v4l2_cropcap cap;
int ret;
unsigned int width, height;
- v4l2_subdev_call(sd, video, s_crop, crop);
+ v4l2_subdev_call(sd, pad, set_selection, NULL, &sdsel);
+ sel->r = sdsel.r;
ret = soc_camera_client_g_rect(sd, cam_rect);
if (ret < 0)
return ret;
@@ -113,29 +121,29 @@ int soc_camera_client_s_crop(struct v4l2_subdev *sd,
* be within camera cropcap bounds
*/
if (!memcmp(rect, cam_rect, sizeof(*rect))) {
- /* Even if camera S_CROP failed, but camera rectangle matches */
- dev_dbg(dev, "Camera S_CROP successful for %dx%d@%d:%d\n",
+ /* Even if camera S_SELECTION failed, but camera rectangle matches */
+ dev_dbg(dev, "Camera S_SELECTION successful for %dx%d@%d:%d\n",
rect->width, rect->height, rect->left, rect->top);
*target_rect = *cam_rect;
return 0;
}
/* Try to fix cropping, that camera hasn't managed to set */
- dev_geo(dev, "Fix camera S_CROP for %dx%d@%d:%d to %dx%d@%d:%d\n",
+ dev_geo(dev, "Fix camera S_SELECTION for %dx%d@%d:%d to %dx%d@%d:%d\n",
cam_rect->width, cam_rect->height,
cam_rect->left, cam_rect->top,
rect->width, rect->height, rect->left, rect->top);
/* We need sensor maximum rectangle */
- ret = v4l2_subdev_call(sd, video, cropcap, &cap);
+ ret = v4l2_subdev_call(sd, pad, get_selection, NULL, &bounds);
if (ret < 0)
return ret;
/* Put user requested rectangle within sensor bounds */
- soc_camera_limit_side(&rect->left, &rect->width, cap.bounds.left, 2,
- cap.bounds.width);
- soc_camera_limit_side(&rect->top, &rect->height, cap.bounds.top, 4,
- cap.bounds.height);
+ soc_camera_limit_side(&rect->left, &rect->width, sdsel.r.left, 2,
+ bounds.r.width);
+ soc_camera_limit_side(&rect->top, &rect->height, sdsel.r.top, 4,
+ bounds.r.height);
/*
* Popular special case - some cameras can only handle fixed sizes like
@@ -150,7 +158,7 @@ int soc_camera_client_s_crop(struct v4l2_subdev *sd,
*/
while (!ret && (is_smaller(cam_rect, rect) ||
is_inside(cam_rect, rect)) &&
- (cap.bounds.width > width || cap.bounds.height > height)) {
+ (bounds.r.width > width || bounds.r.height > height)) {
width *= 2;
height *= 2;
@@ -168,36 +176,40 @@ int soc_camera_client_s_crop(struct v4l2_subdev *sd,
* Instead we just drop to the left and top bounds.
*/
if (cam_rect->left > rect->left)
- cam_rect->left = cap.bounds.left;
+ cam_rect->left = bounds.r.left;
if (cam_rect->left + cam_rect->width < rect->left + rect->width)
cam_rect->width = rect->left + rect->width -
cam_rect->left;
if (cam_rect->top > rect->top)
- cam_rect->top = cap.bounds.top;
+ cam_rect->top = bounds.r.top;
if (cam_rect->top + cam_rect->height < rect->top + rect->height)
cam_rect->height = rect->top + rect->height -
cam_rect->top;
- v4l2_subdev_call(sd, video, s_crop, cam_crop);
+ sdsel.r = *cam_rect;
+ v4l2_subdev_call(sd, pad, set_selection, NULL, &sdsel);
+ *cam_rect = sdsel.r;
ret = soc_camera_client_g_rect(sd, cam_rect);
- dev_geo(dev, "Camera S_CROP %d for %dx%d@%d:%d\n", ret,
+ dev_geo(dev, "Camera S_SELECTION %d for %dx%d@%d:%d\n", ret,
cam_rect->width, cam_rect->height,
cam_rect->left, cam_rect->top);
}
- /* S_CROP must not modify the rectangle */
+ /* S_SELECTION must not modify the rectangle */
if (is_smaller(cam_rect, rect) || is_inside(cam_rect, rect)) {
/*
* The camera failed to configure a suitable cropping,
* we cannot use the current rectangle, set to max
*/
- *cam_rect = cap.bounds;
- v4l2_subdev_call(sd, video, s_crop, cam_crop);
+ sdsel.r = bounds.r;
+ v4l2_subdev_call(sd, pad, set_selection, NULL, &sdsel);
+ *cam_rect = sdsel.r;
+
ret = soc_camera_client_g_rect(sd, cam_rect);
- dev_geo(dev, "Camera S_CROP %d for max %dx%d@%d:%d\n", ret,
+ dev_geo(dev, "Camera S_SELECTION %d for max %dx%d@%d:%d\n", ret,
cam_rect->width, cam_rect->height,
cam_rect->left, cam_rect->top);
}
@@ -209,7 +221,7 @@ int soc_camera_client_s_crop(struct v4l2_subdev *sd,
return ret;
}
-EXPORT_SYMBOL(soc_camera_client_s_crop);
+EXPORT_SYMBOL(soc_camera_client_s_selection);
/* Iterative set_fmt, also updates cached client crop on success */
static int client_set_fmt(struct soc_camera_device *icd,
@@ -221,7 +233,10 @@ static int client_set_fmt(struct soc_camera_device *icd,
struct device *dev = icd->parent;
struct v4l2_mbus_framefmt *mf = &format->format;
unsigned int width = mf->width, height = mf->height, tmp_w, tmp_h;
- struct v4l2_cropcap cap;
+ struct v4l2_subdev_selection sdsel = {
+ .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+ .target = V4L2_SEL_TGT_CROP_BOUNDS,
+ };
bool host_1to1;
int ret;
@@ -243,16 +258,14 @@ static int client_set_fmt(struct soc_camera_device *icd,
if (!host_can_scale)
goto update_cache;
- cap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-
- ret = v4l2_subdev_call(sd, video, cropcap, &cap);
+ ret = v4l2_subdev_call(sd, pad, get_selection, NULL, &sdsel);
if (ret < 0)
return ret;
- if (max_width > cap.bounds.width)
- max_width = cap.bounds.width;
- if (max_height > cap.bounds.height)
- max_height = cap.bounds.height;
+ if (max_width > sdsel.r.width)
+ max_width = sdsel.r.width;
+ if (max_height > sdsel.r.height)
+ max_height = sdsel.r.height;
/* Camera set a format, but geometry is not precise, try to improve */
tmp_w = mf->width;
diff --git a/drivers/media/platform/soc_camera/soc_scale_crop.h b/drivers/media/platform/soc_camera/soc_scale_crop.h
index 184a30dff541..9ca469312a1f 100644
--- a/drivers/media/platform/soc_camera/soc_scale_crop.h
+++ b/drivers/media/platform/soc_camera/soc_scale_crop.h
@@ -16,7 +16,7 @@
struct soc_camera_device;
-struct v4l2_crop;
+struct v4l2_selection;
struct v4l2_mbus_framefmt;
struct v4l2_pix_format;
struct v4l2_rect;
@@ -31,8 +31,8 @@ static inline unsigned int soc_camera_shift_scale(unsigned int size,
#define soc_camera_calc_scale(in, shift, out) soc_camera_shift_scale(in, shift, out)
int soc_camera_client_g_rect(struct v4l2_subdev *sd, struct v4l2_rect *rect);
-int soc_camera_client_s_crop(struct v4l2_subdev *sd,
- struct v4l2_crop *crop, struct v4l2_crop *cam_crop,
+int soc_camera_client_s_selection(struct v4l2_subdev *sd,
+ struct v4l2_selection *sel, struct v4l2_selection *cam_sel,
struct v4l2_rect *target_rect, struct v4l2_rect *subrect);
int soc_camera_client_scale(struct soc_camera_device *icd,
struct v4l2_rect *rect, struct v4l2_rect *subrect,