[media] v4l2: remove g/s_crop from video ops
authorHans Verkuil <hans.verkuil@cisco.com>
Mon, 14 Dec 2015 10:25:32 +0000 (08:25 -0200)
committerMauro Carvalho Chehab <mchehab@s-opensource.com>
Wed, 24 Aug 2016 12:46:09 +0000 (09:46 -0300)
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>
28 files changed:
drivers/media/i2c/ak881x.c
drivers/media/i2c/soc_camera/imx074.c
drivers/media/i2c/soc_camera/mt9m001.c
drivers/media/i2c/soc_camera/mt9m111.c
drivers/media/i2c/soc_camera/mt9t031.c
drivers/media/i2c/soc_camera/mt9t112.c
drivers/media/i2c/soc_camera/mt9v022.c
drivers/media/i2c/soc_camera/ov2640.c
drivers/media/i2c/soc_camera/ov5642.c
drivers/media/i2c/soc_camera/ov6650.c
drivers/media/i2c/soc_camera/ov772x.c
drivers/media/i2c/soc_camera/ov9640.c
drivers/media/i2c/soc_camera/ov9740.c
drivers/media/i2c/soc_camera/rj54n1cb0c.c
drivers/media/i2c/soc_camera/tw9910.c
drivers/media/i2c/tvp5150.c
drivers/media/platform/omap3isp/ispvideo.c
drivers/media/platform/sh_vou.c
drivers/media/platform/soc_camera/pxa_camera.c
drivers/media/platform/soc_camera/rcar_vin.c
drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c
drivers/media/platform/soc_camera/soc_camera.c
drivers/media/platform/soc_camera/soc_camera_platform.c
drivers/media/platform/soc_camera/soc_scale_crop.c
drivers/media/platform/soc_camera/soc_scale_crop.h
drivers/staging/media/omap4iss/iss_video.c
include/media/soc_camera.h
include/media/v4l2-subdev.h

index d9f2b6b76d5950896bbd87c7d024b1029cd0376b..3a795dcb7d8e07c76c16720850b6cb99c7d60369 100644 (file)
@@ -124,21 +124,27 @@ static int ak881x_enum_mbus_code(struct v4l2_subdev *sd,
        return 0;
 }
 
-static int ak881x_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
+static int ak881x_get_selection(struct v4l2_subdev *sd,
+                               struct v4l2_subdev_pad_config *cfg,
+                               struct v4l2_subdev_selection *sel)
 {
        struct i2c_client *client = v4l2_get_subdevdata(sd);
        struct ak881x *ak881x = to_ak881x(client);
 
-       a->bounds.left                  = 0;
-       a->bounds.top                   = 0;
-       a->bounds.width                 = 720;
-       a->bounds.height                = ak881x->lines;
-       a->defrect                      = a->bounds;
-       a->type                         = V4L2_BUF_TYPE_VIDEO_OUTPUT;
-       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:
+               sel->r.left = 0;
+               sel->r.top = 0;
+               sel->r.width = 720;
+               sel->r.height = ak881x->lines;
+               return 0;
+       default:
+               return -EINVAL;
+       }
 }
 
 static int ak881x_s_std_output(struct v4l2_subdev *sd, v4l2_std_id std)
@@ -207,13 +213,13 @@ static struct v4l2_subdev_core_ops ak881x_subdev_core_ops = {
 };
 
 static struct v4l2_subdev_video_ops ak881x_subdev_video_ops = {
-       .cropcap        = ak881x_cropcap,
        .s_std_output   = ak881x_s_std_output,
        .s_stream       = ak881x_s_stream,
 };
 
 static const struct v4l2_subdev_pad_ops ak881x_subdev_pad_ops = {
        .enum_mbus_code = ak881x_enum_mbus_code,
+       .get_selection  = ak881x_get_selection,
        .set_fmt        = ak881x_fill_fmt,
        .get_fmt        = ak881x_fill_fmt,
 };
index f68c2352c63c4ef3c131cbabde7d5d11327079bc..05b55cfe814713924d4c44a52f65b88950277aa6 100644 (file)
@@ -209,31 +209,26 @@ static int imx074_get_fmt(struct v4l2_subdev *sd,
        return 0;
 }
 
-static int imx074_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
+static int imx074_get_selection(struct v4l2_subdev *sd,
+                               struct v4l2_subdev_pad_config *cfg,
+                               struct v4l2_subdev_selection *sel)
 {
-       struct v4l2_rect *rect = &a->c;
-
-       a->type         = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-       rect->top       = 0;
-       rect->left      = 0;
-       rect->width     = IMX074_WIDTH;
-       rect->height    = IMX074_HEIGHT;
-
-       return 0;
-}
+       if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+               return -EINVAL;
 
-static int imx074_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
-{
-       a->bounds.left                  = 0;
-       a->bounds.top                   = 0;
-       a->bounds.width                 = IMX074_WIDTH;
-       a->bounds.height                = IMX074_HEIGHT;
-       a->defrect                      = a->bounds;
-       a->type                         = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-       a->pixelaspect.numerator        = 1;
-       a->pixelaspect.denominator      = 1;
+       sel->r.left = 0;
+       sel->r.top = 0;
+       sel->r.width = IMX074_WIDTH;
+       sel->r.height = IMX074_HEIGHT;
 
-       return 0;
+       switch (sel->target) {
+       case V4L2_SEL_TGT_CROP_BOUNDS:
+       case V4L2_SEL_TGT_CROP_DEFAULT:
+       case V4L2_SEL_TGT_CROP:
+               return 0;
+       default:
+               return -EINVAL;
+       }
 }
 
 static int imx074_enum_mbus_code(struct v4l2_subdev *sd,
@@ -278,8 +273,6 @@ static int imx074_g_mbus_config(struct v4l2_subdev *sd,
 
 static struct v4l2_subdev_video_ops imx074_subdev_video_ops = {
        .s_stream       = imx074_s_stream,
-       .g_crop         = imx074_g_crop,
-       .cropcap        = imx074_cropcap,
        .g_mbus_config  = imx074_g_mbus_config,
 };
 
@@ -289,6 +282,7 @@ static struct v4l2_subdev_core_ops imx074_subdev_core_ops = {
 
 static const struct v4l2_subdev_pad_ops imx074_subdev_pad_ops = {
        .enum_mbus_code = imx074_enum_mbus_code,
+       .get_selection  = imx074_get_selection,
        .get_fmt        = imx074_get_fmt,
        .set_fmt        = imx074_set_fmt,
 };
index 69becc358659cf25dc6a4ccf7ddf0d2dbbe9573d..3d6378d4491c83462ab9ba10d3920f5139633157 100644 (file)
@@ -171,13 +171,19 @@ static int mt9m001_s_stream(struct v4l2_subdev *sd, int enable)
        return 0;
 }
 
-static int mt9m001_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a)
+static int mt9m001_set_selection(struct v4l2_subdev *sd,
+               struct v4l2_subdev_pad_config *cfg,
+               struct v4l2_subdev_selection *sel)
 {
        struct i2c_client *client = v4l2_get_subdevdata(sd);
        struct mt9m001 *mt9m001 = to_mt9m001(client);
-       struct v4l2_rect rect = a->c;
-       int ret;
+       struct v4l2_rect rect = sel->r;
        const u16 hblank = 9, vblank = 25;
+       int ret;
+
+       if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE ||
+           sel->target != V4L2_SEL_TGT_CROP)
+               return -EINVAL;
 
        if (mt9m001->fmts == mt9m001_colour_fmts)
                /*
@@ -225,29 +231,30 @@ static int mt9m001_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a)
        return ret;
 }
 
-static int mt9m001_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
+static int mt9m001_get_selection(struct v4l2_subdev *sd,
+               struct v4l2_subdev_pad_config *cfg,
+               struct v4l2_subdev_selection *sel)
 {
        struct i2c_client *client = v4l2_get_subdevdata(sd);
        struct mt9m001 *mt9m001 = to_mt9m001(client);
 
-       a->c    = mt9m001->rect;
-       a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-
-       return 0;
-}
-
-static int mt9m001_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
-{
-       a->bounds.left                  = MT9M001_COLUMN_SKIP;
-       a->bounds.top                   = MT9M001_ROW_SKIP;
-       a->bounds.width                 = MT9M001_MAX_WIDTH;
-       a->bounds.height                = MT9M001_MAX_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:
+               sel->r.left = MT9M001_COLUMN_SKIP;
+               sel->r.top = MT9M001_ROW_SKIP;
+               sel->r.width = MT9M001_MAX_WIDTH;
+               sel->r.height = MT9M001_MAX_HEIGHT;
+               return 0;
+       case V4L2_SEL_TGT_CROP:
+               sel->r = mt9m001->rect;
+               return 0;
+       default:
+               return -EINVAL;
+       }
 }
 
 static int mt9m001_get_fmt(struct v4l2_subdev *sd,
@@ -275,18 +282,18 @@ static int mt9m001_s_fmt(struct v4l2_subdev *sd,
 {
        struct i2c_client *client = v4l2_get_subdevdata(sd);
        struct mt9m001 *mt9m001 = to_mt9m001(client);
-       struct v4l2_crop a = {
-               .c = {
-                       .left   = mt9m001->rect.left,
-                       .top    = mt9m001->rect.top,
-                       .width  = mf->width,
-                       .height = mf->height,
-               },
+       struct v4l2_subdev_selection sel = {
+               .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+               .target = V4L2_SEL_TGT_CROP,
+               .r.left = mt9m001->rect.left,
+               .r.top = mt9m001->rect.top,
+               .r.width = mf->width,
+               .r.height = mf->height,
        };
        int ret;
 
        /* No support for scaling so far, just crop. TODO: use skipping */
-       ret = mt9m001_s_crop(sd, &a);
+       ret = mt9m001_set_selection(sd, NULL, &sel);
        if (!ret) {
                mf->width       = mt9m001->rect.width;
                mf->height      = mt9m001->rect.height;
@@ -625,9 +632,6 @@ static int mt9m001_s_mbus_config(struct v4l2_subdev *sd,
 
 static struct v4l2_subdev_video_ops mt9m001_subdev_video_ops = {
        .s_stream       = mt9m001_s_stream,
-       .s_crop         = mt9m001_s_crop,
-       .g_crop         = mt9m001_g_crop,
-       .cropcap        = mt9m001_cropcap,
        .g_mbus_config  = mt9m001_g_mbus_config,
        .s_mbus_config  = mt9m001_s_mbus_config,
 };
@@ -638,6 +642,8 @@ static const struct v4l2_subdev_sensor_ops mt9m001_subdev_sensor_ops = {
 
 static const struct v4l2_subdev_pad_ops mt9m001_subdev_pad_ops = {
        .enum_mbus_code = mt9m001_enum_mbus_code,
+       .get_selection  = mt9m001_get_selection,
+       .set_selection  = mt9m001_set_selection,
        .get_fmt        = mt9m001_get_fmt,
        .set_fmt        = mt9m001_set_fmt,
 };
index 6dfaead6aaa83401ba184b55999bfe4f3c58c4f0..6c8d1123658c4bd4809d41142b32e866c2c99010 100644 (file)
@@ -383,14 +383,18 @@ static int mt9m111_reset(struct mt9m111 *mt9m111)
        return ret;
 }
 
-static int mt9m111_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a)
+static int mt9m111_set_selection(struct v4l2_subdev *sd,
+                                struct v4l2_subdev_pad_config *cfg,
+                                struct v4l2_subdev_selection *sel)
 {
-       struct v4l2_rect rect = a->c;
-       struct mt9m111 *mt9m111 = container_of(sd, struct mt9m111, subdev);
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       struct mt9m111 *mt9m111 = to_mt9m111(client);
+       struct v4l2_rect rect = sel->r;
        int width, height;
        int ret;
 
-       if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+       if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE ||
+           sel->target != V4L2_SEL_TGT_CROP)
                return -EINVAL;
 
        if (mt9m111->fmt->code == MEDIA_BUS_FMT_SBGGR8_1X8 ||
@@ -421,30 +425,30 @@ static int mt9m111_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a)
        return ret;
 }
 
-static int mt9m111_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
+static int mt9m111_get_selection(struct v4l2_subdev *sd,
+                                struct v4l2_subdev_pad_config *cfg,
+                                struct v4l2_subdev_selection *sel)
 {
-       struct mt9m111 *mt9m111 = container_of(sd, struct mt9m111, subdev);
-
-       a->c    = mt9m111->rect;
-       a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-
-       return 0;
-}
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       struct mt9m111 *mt9m111 = to_mt9m111(client);
 
-static int mt9m111_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
-{
-       if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+       if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE)
                return -EINVAL;
 
-       a->bounds.left                  = MT9M111_MIN_DARK_COLS;
-       a->bounds.top                   = MT9M111_MIN_DARK_ROWS;
-       a->bounds.width                 = MT9M111_MAX_WIDTH;
-       a->bounds.height                = MT9M111_MAX_HEIGHT;
-       a->defrect                      = a->bounds;
-       a->pixelaspect.numerator        = 1;
-       a->pixelaspect.denominator      = 1;
-
-       return 0;
+       switch (sel->target) {
+       case V4L2_SEL_TGT_CROP_BOUNDS:
+       case V4L2_SEL_TGT_CROP_DEFAULT:
+               sel->r.left = MT9M111_MIN_DARK_COLS;
+               sel->r.top = MT9M111_MIN_DARK_ROWS;
+               sel->r.width = MT9M111_MAX_WIDTH;
+               sel->r.height = MT9M111_MAX_HEIGHT;
+               return 0;
+       case V4L2_SEL_TGT_CROP:
+               sel->r = mt9m111->rect;
+               return 0;
+       default:
+               return -EINVAL;
+       }
 }
 
 static int mt9m111_get_fmt(struct v4l2_subdev *sd,
@@ -867,14 +871,13 @@ static int mt9m111_g_mbus_config(struct v4l2_subdev *sd,
 }
 
 static struct v4l2_subdev_video_ops mt9m111_subdev_video_ops = {
-       .s_crop         = mt9m111_s_crop,
-       .g_crop         = mt9m111_g_crop,
-       .cropcap        = mt9m111_cropcap,
        .g_mbus_config  = mt9m111_g_mbus_config,
 };
 
 static const struct v4l2_subdev_pad_ops mt9m111_subdev_pad_ops = {
        .enum_mbus_code = mt9m111_enum_mbus_code,
+       .get_selection  = mt9m111_get_selection,
+       .set_selection  = mt9m111_set_selection,
        .get_fmt        = mt9m111_get_fmt,
        .set_fmt        = mt9m111_set_fmt,
 };
index 5c8e3ffe3b27bff0b69c51d218cd68e7f3001d0e..3aa5569065ad0041c0aae79f8cdccc80bc8e539b 100644 (file)
@@ -264,7 +264,7 @@ static int mt9t031_set_params(struct i2c_client *client,
 
        /*
         * The caller provides a supported format, as guaranteed by
-        * .set_fmt(FORMAT_TRY), soc_camera_s_crop() and soc_camera_cropcap()
+        * .set_fmt(FORMAT_TRY), soc_camera_s_selection() and soc_camera_cropcap()
         */
        if (ret >= 0)
                ret = reg_write(client, MT9T031_COLUMN_START, rect->left);
@@ -294,11 +294,17 @@ static int mt9t031_set_params(struct i2c_client *client,
        return ret < 0 ? ret : 0;
 }
 
-static int mt9t031_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a)
+static int mt9t031_set_selection(struct v4l2_subdev *sd,
+               struct v4l2_subdev_pad_config *cfg,
+               struct v4l2_subdev_selection *sel)
 {
-       struct v4l2_rect rect = a->c;
        struct i2c_client *client = v4l2_get_subdevdata(sd);
        struct mt9t031 *mt9t031 = to_mt9t031(client);
+       struct v4l2_rect rect = sel->r;
+
+       if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE ||
+           sel->target != V4L2_SEL_TGT_CROP)
+               return -EINVAL;
 
        rect.width = ALIGN(rect.width, 2);
        rect.height = ALIGN(rect.height, 2);
@@ -312,29 +318,30 @@ static int mt9t031_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a)
        return mt9t031_set_params(client, &rect, mt9t031->xskip, mt9t031->yskip);
 }
 
-static int mt9t031_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
+static int mt9t031_get_selection(struct v4l2_subdev *sd,
+               struct v4l2_subdev_pad_config *cfg,
+               struct v4l2_subdev_selection *sel)
 {
        struct i2c_client *client = v4l2_get_subdevdata(sd);
        struct mt9t031 *mt9t031 = to_mt9t031(client);
 
-       a->c    = mt9t031->rect;
-       a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-
-       return 0;
-}
-
-static int mt9t031_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
-{
-       a->bounds.left                  = MT9T031_COLUMN_SKIP;
-       a->bounds.top                   = MT9T031_ROW_SKIP;
-       a->bounds.width                 = MT9T031_MAX_WIDTH;
-       a->bounds.height                = MT9T031_MAX_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:
+               sel->r.left = MT9T031_COLUMN_SKIP;
+               sel->r.top = MT9T031_ROW_SKIP;
+               sel->r.width = MT9T031_MAX_WIDTH;
+               sel->r.height = MT9T031_MAX_HEIGHT;
+               return 0;
+       case V4L2_SEL_TGT_CROP:
+               sel->r = mt9t031->rect;
+               return 0;
+       default:
+               return -EINVAL;
+       }
 }
 
 static int mt9t031_get_fmt(struct v4l2_subdev *sd,
@@ -721,9 +728,6 @@ static int mt9t031_s_mbus_config(struct v4l2_subdev *sd,
 
 static struct v4l2_subdev_video_ops mt9t031_subdev_video_ops = {
        .s_stream       = mt9t031_s_stream,
-       .s_crop         = mt9t031_s_crop,
-       .g_crop         = mt9t031_g_crop,
-       .cropcap        = mt9t031_cropcap,
        .g_mbus_config  = mt9t031_g_mbus_config,
        .s_mbus_config  = mt9t031_s_mbus_config,
 };
@@ -734,6 +738,8 @@ static const struct v4l2_subdev_sensor_ops mt9t031_subdev_sensor_ops = {
 
 static const struct v4l2_subdev_pad_ops mt9t031_subdev_pad_ops = {
        .enum_mbus_code = mt9t031_enum_mbus_code,
+       .get_selection  = mt9t031_get_selection,
+       .set_selection  = mt9t031_set_selection,
        .get_fmt        = mt9t031_get_fmt,
        .set_fmt        = mt9t031_set_fmt,
 };
index 6a1b2a9f9a0914f88b5b35b2d6fff9829c4045d9..2ef22241ec149b893e5e26f0f1b9b12f527b67a2 100644 (file)
@@ -867,39 +867,48 @@ static int mt9t112_set_params(struct mt9t112_priv *priv,
        return 0;
 }
 
-static int mt9t112_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
-{
-       a->bounds.left                  = 0;
-       a->bounds.top                   = 0;
-       a->bounds.width                 = MAX_WIDTH;
-       a->bounds.height                = MAX_HEIGHT;
-       a->defrect.left                 = 0;
-       a->defrect.top                  = 0;
-       a->defrect.width                = VGA_WIDTH;
-       a->defrect.height               = VGA_HEIGHT;
-       a->type                         = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-       a->pixelaspect.numerator        = 1;
-       a->pixelaspect.denominator      = 1;
-
-       return 0;
-}
-
-static int mt9t112_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
+static int mt9t112_get_selection(struct v4l2_subdev *sd,
+               struct v4l2_subdev_pad_config *cfg,
+               struct v4l2_subdev_selection *sel)
 {
        struct i2c_client *client = v4l2_get_subdevdata(sd);
        struct mt9t112_priv *priv = to_mt9t112(client);
 
-       a->c    = priv->frame;
-       a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+               return -EINVAL;
 
-       return 0;
+       switch (sel->target) {
+       case V4L2_SEL_TGT_CROP_BOUNDS:
+               sel->r.left = 0;
+               sel->r.top = 0;
+               sel->r.width = MAX_WIDTH;
+               sel->r.height = MAX_HEIGHT;
+               return 0;
+       case V4L2_SEL_TGT_CROP_DEFAULT:
+               sel->r.left = 0;
+               sel->r.top = 0;
+               sel->r.width = VGA_WIDTH;
+               sel->r.height = VGA_HEIGHT;
+               return 0;
+       case V4L2_SEL_TGT_CROP:
+               sel->r = priv->frame;
+               return 0;
+       default:
+               return -EINVAL;
+       }
 }
 
-static int mt9t112_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a)
+static int mt9t112_set_selection(struct v4l2_subdev *sd,
+               struct v4l2_subdev_pad_config *cfg,
+               struct v4l2_subdev_selection *sel)
 {
        struct i2c_client *client = v4l2_get_subdevdata(sd);
        struct mt9t112_priv *priv = to_mt9t112(client);
-       const struct v4l2_rect *rect = &a->c;
+       const struct v4l2_rect *rect = &sel->r;
+
+       if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE ||
+           sel->target != V4L2_SEL_TGT_CROP)
+               return -EINVAL;
 
        return mt9t112_set_params(priv, rect, priv->format->code);
 }
@@ -1024,15 +1033,14 @@ static int mt9t112_s_mbus_config(struct v4l2_subdev *sd,
 
 static struct v4l2_subdev_video_ops mt9t112_subdev_video_ops = {
        .s_stream       = mt9t112_s_stream,
-       .cropcap        = mt9t112_cropcap,
-       .g_crop         = mt9t112_g_crop,
-       .s_crop         = mt9t112_s_crop,
        .g_mbus_config  = mt9t112_g_mbus_config,
        .s_mbus_config  = mt9t112_s_mbus_config,
 };
 
 static const struct v4l2_subdev_pad_ops mt9t112_subdev_pad_ops = {
        .enum_mbus_code = mt9t112_enum_mbus_code,
+       .get_selection  = mt9t112_get_selection,
+       .set_selection  = mt9t112_set_selection,
        .get_fmt        = mt9t112_get_fmt,
        .set_fmt        = mt9t112_set_fmt,
 };
index 2721e583bfa0b239c3f36b7cb8d3efa6affc53a4..6a14ab5e4f2d93d1b331f7f40197f7a54d245dde 100644 (file)
@@ -276,14 +276,20 @@ static int mt9v022_s_stream(struct v4l2_subdev *sd, int enable)
        return 0;
 }
 
-static int mt9v022_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a)
+static int mt9v022_set_selection(struct v4l2_subdev *sd,
+               struct v4l2_subdev_pad_config *cfg,
+               struct v4l2_subdev_selection *sel)
 {
        struct i2c_client *client = v4l2_get_subdevdata(sd);
        struct mt9v022 *mt9v022 = to_mt9v022(client);
-       struct v4l2_rect rect = a->c;
+       struct v4l2_rect rect = sel->r;
        int min_row, min_blank;
        int ret;
 
+       if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE ||
+           sel->target != V4L2_SEL_TGT_CROP)
+               return -EINVAL;
+
        /* Bayer format - even size lengths */
        if (mt9v022->fmts == mt9v022_colour_fmts) {
                rect.width      = ALIGN(rect.width, 2);
@@ -350,29 +356,30 @@ static int mt9v022_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a)
        return 0;
 }
 
-static int mt9v022_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
+static int mt9v022_get_selection(struct v4l2_subdev *sd,
+               struct v4l2_subdev_pad_config *cfg,
+               struct v4l2_subdev_selection *sel)
 {
        struct i2c_client *client = v4l2_get_subdevdata(sd);
        struct mt9v022 *mt9v022 = to_mt9v022(client);
 
-       a->c    = mt9v022->rect;
-       a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-
-       return 0;
-}
-
-static int mt9v022_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
-{
-       a->bounds.left                  = MT9V022_COLUMN_SKIP;
-       a->bounds.top                   = MT9V022_ROW_SKIP;
-       a->bounds.width                 = MT9V022_MAX_WIDTH;
-       a->bounds.height                = MT9V022_MAX_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:
+               sel->r.left = MT9V022_COLUMN_SKIP;
+               sel->r.top = MT9V022_ROW_SKIP;
+               sel->r.width = MT9V022_MAX_WIDTH;
+               sel->r.height = MT9V022_MAX_HEIGHT;
+               return 0;
+       case V4L2_SEL_TGT_CROP:
+               sel->r = mt9v022->rect;
+               return 0;
+       default:
+               return -EINVAL;
+       }
 }
 
 static int mt9v022_get_fmt(struct v4l2_subdev *sd,
@@ -400,13 +407,13 @@ static int mt9v022_s_fmt(struct v4l2_subdev *sd,
 {
        struct i2c_client *client = v4l2_get_subdevdata(sd);
        struct mt9v022 *mt9v022 = to_mt9v022(client);
-       struct v4l2_crop a = {
-               .c = {
-                       .left   = mt9v022->rect.left,
-                       .top    = mt9v022->rect.top,
-                       .width  = mf->width,
-                       .height = mf->height,
-               },
+       struct v4l2_subdev_selection sel = {
+               .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+               .target = V4L2_SEL_TGT_CROP,
+               .r.left = mt9v022->rect.left,
+               .r.top = mt9v022->rect.top,
+               .r.width = mf->width,
+               .r.height = mf->height,
        };
        int ret;
 
@@ -430,7 +437,7 @@ static int mt9v022_s_fmt(struct v4l2_subdev *sd,
        }
 
        /* No support for scaling on this camera, just crop. */
-       ret = mt9v022_s_crop(sd, &a);
+       ret = mt9v022_set_selection(sd, NULL, &sel);
        if (!ret) {
                mf->width       = mt9v022->rect.width;
                mf->height      = mt9v022->rect.height;
@@ -853,9 +860,6 @@ static int mt9v022_s_mbus_config(struct v4l2_subdev *sd,
 
 static struct v4l2_subdev_video_ops mt9v022_subdev_video_ops = {
        .s_stream       = mt9v022_s_stream,
-       .s_crop         = mt9v022_s_crop,
-       .g_crop         = mt9v022_g_crop,
-       .cropcap        = mt9v022_cropcap,
        .g_mbus_config  = mt9v022_g_mbus_config,
        .s_mbus_config  = mt9v022_s_mbus_config,
 };
@@ -866,6 +870,8 @@ static const struct v4l2_subdev_sensor_ops mt9v022_subdev_sensor_ops = {
 
 static const struct v4l2_subdev_pad_ops mt9v022_subdev_pad_ops = {
        .enum_mbus_code = mt9v022_enum_mbus_code,
+       .get_selection  = mt9v022_get_selection,
+       .set_selection  = mt9v022_set_selection,
        .get_fmt        = mt9v022_get_fmt,
        .set_fmt        = mt9v022_set_fmt,
 };
index 9b4f5deec748dca7b9a4411ad57b2d65908d1628..56de1826335908115d1c2ae573e40bd36c006df2 100644 (file)
@@ -928,29 +928,25 @@ static int ov2640_enum_mbus_code(struct v4l2_subdev *sd,
        return 0;
 }
 
-static int ov2640_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
-{
-       a->c.left       = 0;
-       a->c.top        = 0;
-       a->c.width      = UXGA_WIDTH;
-       a->c.height     = UXGA_HEIGHT;
-       a->type         = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-
-       return 0;
-}
-
-static int ov2640_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
+static int ov2640_get_selection(struct v4l2_subdev *sd,
+               struct v4l2_subdev_pad_config *cfg,
+               struct v4l2_subdev_selection *sel)
 {
-       a->bounds.left                  = 0;
-       a->bounds.top                   = 0;
-       a->bounds.width                 = UXGA_WIDTH;
-       a->bounds.height                = UXGA_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 = UXGA_WIDTH;
+               sel->r.height = UXGA_HEIGHT;
+               return 0;
+       default:
+               return -EINVAL;
+       }
 }
 
 static int ov2640_video_probe(struct i2c_client *client)
@@ -1024,13 +1020,12 @@ static int ov2640_g_mbus_config(struct v4l2_subdev *sd,
 
 static struct v4l2_subdev_video_ops ov2640_subdev_video_ops = {
        .s_stream       = ov2640_s_stream,
-       .cropcap        = ov2640_cropcap,
-       .g_crop         = ov2640_g_crop,
        .g_mbus_config  = ov2640_g_mbus_config,
 };
 
 static const struct v4l2_subdev_pad_ops ov2640_subdev_pad_ops = {
        .enum_mbus_code = ov2640_enum_mbus_code,
+       .get_selection  = ov2640_get_selection,
        .get_fmt        = ov2640_get_fmt,
        .set_fmt        = ov2640_set_fmt,
 };
index bab9ac0c176481b6293378ea828b3ce6b04fd3c7..3d185bd622a3173c1e9d453f37304d42a90cd16a 100644 (file)
@@ -850,13 +850,19 @@ static int ov5642_enum_mbus_code(struct v4l2_subdev *sd,
        return 0;
 }
 
-static int ov5642_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a)
+static int ov5642_set_selection(struct v4l2_subdev *sd,
+               struct v4l2_subdev_pad_config *cfg,
+               struct v4l2_subdev_selection *sel)
 {
        struct i2c_client *client = v4l2_get_subdevdata(sd);
        struct ov5642 *priv = to_ov5642(client);
-       struct v4l2_rect rect = a->c;
+       struct v4l2_rect rect = sel->r;
        int ret;
 
+       if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE ||
+           sel->target != V4L2_SEL_TGT_CROP)
+               return -EINVAL;
+
        v4l_bound_align_image(&rect.width, 48, OV5642_MAX_WIDTH, 1,
                              &rect.height, 32, OV5642_MAX_HEIGHT, 1, 0);
 
@@ -878,32 +884,30 @@ static int ov5642_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a)
        return ret;
 }
 
-static int ov5642_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
+static int ov5642_get_selection(struct v4l2_subdev *sd,
+               struct v4l2_subdev_pad_config *cfg,
+               struct v4l2_subdev_selection *sel)
 {
        struct i2c_client *client = v4l2_get_subdevdata(sd);
        struct ov5642 *priv = to_ov5642(client);
-       struct v4l2_rect *rect = &a->c;
 
-       if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+       if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE)
                return -EINVAL;
 
-       *rect = priv->crop_rect;
-
-       return 0;
-}
-
-static int ov5642_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
-{
-       a->bounds.left                  = 0;
-       a->bounds.top                   = 0;
-       a->bounds.width                 = OV5642_MAX_WIDTH;
-       a->bounds.height                = OV5642_MAX_HEIGHT;
-       a->defrect                      = a->bounds;
-       a->type                         = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-       a->pixelaspect.numerator        = 1;
-       a->pixelaspect.denominator      = 1;
-
-       return 0;
+       switch (sel->target) {
+       case V4L2_SEL_TGT_CROP_BOUNDS:
+       case V4L2_SEL_TGT_CROP_DEFAULT:
+               sel->r.left = 0;
+               sel->r.top = 0;
+               sel->r.width = OV5642_MAX_WIDTH;
+               sel->r.height = OV5642_MAX_HEIGHT;
+               return 0;
+       case V4L2_SEL_TGT_CROP:
+               sel->r = priv->crop_rect;
+               return 0;
+       default:
+               return -EINVAL;
+       }
 }
 
 static int ov5642_g_mbus_config(struct v4l2_subdev *sd,
@@ -940,14 +944,13 @@ static int ov5642_s_power(struct v4l2_subdev *sd, int on)
 }
 
 static struct v4l2_subdev_video_ops ov5642_subdev_video_ops = {
-       .s_crop         = ov5642_s_crop,
-       .g_crop         = ov5642_g_crop,
-       .cropcap        = ov5642_cropcap,
        .g_mbus_config  = ov5642_g_mbus_config,
 };
 
 static const struct v4l2_subdev_pad_ops ov5642_subdev_pad_ops = {
        .enum_mbus_code = ov5642_enum_mbus_code,
+       .get_selection  = ov5642_get_selection,
+       .set_selection  = ov5642_set_selection,
        .get_fmt        = ov5642_get_fmt,
        .set_fmt        = ov5642_set_fmt,
 };
index 1f8af1ee8352bf3efacd1a607d670bca7cdd0b2f..4bf2995e1cb802e8c0fd6ed59a41aa6253e30d01 100644 (file)
@@ -432,25 +432,43 @@ static int ov6650_s_power(struct v4l2_subdev *sd, int on)
        return soc_camera_set_power(&client->dev, ssdd, priv->clk, on);
 }
 
-static int ov6650_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
+static int ov6650_get_selection(struct v4l2_subdev *sd,
+               struct v4l2_subdev_pad_config *cfg,
+               struct v4l2_subdev_selection *sel)
 {
        struct i2c_client *client = v4l2_get_subdevdata(sd);
        struct ov6650 *priv = to_ov6650(client);
 
-       a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-       a->c = priv->rect;
+       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:
+               sel->r.left = DEF_HSTRT << 1;
+               sel->r.top = DEF_VSTRT << 1;
+               sel->r.width = W_CIF;
+               sel->r.height = H_CIF;
+               return 0;
+       case V4L2_SEL_TGT_CROP:
+               sel->r = priv->rect;
+               return 0;
+       default:
+               return -EINVAL;
+       }
 }
 
-static int ov6650_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a)
+static int ov6650_set_selection(struct v4l2_subdev *sd,
+               struct v4l2_subdev_pad_config *cfg,
+               struct v4l2_subdev_selection *sel)
 {
        struct i2c_client *client = v4l2_get_subdevdata(sd);
        struct ov6650 *priv = to_ov6650(client);
-       struct v4l2_rect rect = a->c;
+       struct v4l2_rect rect = sel->r;
        int ret;
 
-       if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+       if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE ||
+           sel->target != V4L2_SEL_TGT_CROP)
                return -EINVAL;
 
        rect.left   = ALIGN(rect.left,   2);
@@ -483,22 +501,6 @@ static int ov6650_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a)
        return ret;
 }
 
-static int ov6650_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
-{
-       if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-               return -EINVAL;
-
-       a->bounds.left                  = DEF_HSTRT << 1;
-       a->bounds.top                   = DEF_VSTRT << 1;
-       a->bounds.width                 = W_CIF;
-       a->bounds.height                = H_CIF;
-       a->defrect                      = a->bounds;
-       a->pixelaspect.numerator        = 1;
-       a->pixelaspect.denominator      = 1;
-
-       return 0;
-}
-
 static int ov6650_get_fmt(struct v4l2_subdev *sd,
                struct v4l2_subdev_pad_config *cfg,
                struct v4l2_subdev_format *format)
@@ -549,16 +551,15 @@ static int ov6650_s_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *mf)
        struct soc_camera_sense *sense = icd->sense;
        struct ov6650 *priv = to_ov6650(client);
        bool half_scale = !is_unscaled_ok(mf->width, mf->height, &priv->rect);
-       struct v4l2_crop a = {
-               .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
-               .c = {
-                       .left   = priv->rect.left + (priv->rect.width >> 1) -
-                                       (mf->width >> (1 - half_scale)),
-                       .top    = priv->rect.top + (priv->rect.height >> 1) -
-                                       (mf->height >> (1 - half_scale)),
-                       .width  = mf->width << half_scale,
-                       .height = mf->height << half_scale,
-               },
+       struct v4l2_subdev_selection sel = {
+               .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+               .target = V4L2_SEL_TGT_CROP,
+               .r.left = priv->rect.left + (priv->rect.width >> 1) -
+                       (mf->width >> (1 - half_scale)),
+               .r.top = priv->rect.top + (priv->rect.height >> 1) -
+                       (mf->height >> (1 - half_scale)),
+               .r.width = mf->width << half_scale,
+               .r.height = mf->height << half_scale,
        };
        u32 code = mf->code;
        unsigned long mclk, pclk;
@@ -672,7 +673,7 @@ static int ov6650_s_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *mf)
        dev_dbg(&client->dev, "pixel clock divider: %ld.%ld\n",
                        mclk / pclk, 10 * mclk % pclk / pclk);
 
-       ret = ov6650_s_crop(sd, &a);
+       ret = ov6650_set_selection(sd, NULL, &sel);
        if (!ret)
                ret = ov6650_reg_rmw(client, REG_COMA, coma_set, coma_mask);
        if (!ret)
@@ -943,9 +944,6 @@ static int ov6650_s_mbus_config(struct v4l2_subdev *sd,
 
 static struct v4l2_subdev_video_ops ov6650_video_ops = {
        .s_stream       = ov6650_s_stream,
-       .cropcap        = ov6650_cropcap,
-       .g_crop         = ov6650_g_crop,
-       .s_crop         = ov6650_s_crop,
        .g_parm         = ov6650_g_parm,
        .s_parm         = ov6650_s_parm,
        .g_mbus_config  = ov6650_g_mbus_config,
@@ -954,6 +952,8 @@ static struct v4l2_subdev_video_ops ov6650_video_ops = {
 
 static const struct v4l2_subdev_pad_ops ov6650_pad_ops = {
        .enum_mbus_code = ov6650_enum_mbus_code,
+       .get_selection  = ov6650_get_selection,
+       .set_selection  = ov6650_set_selection,
        .get_fmt        = ov6650_get_fmt,
        .set_fmt        = ov6650_set_fmt,
 };
index a43410c1e254f93d1922211b480ac08837a30061..7e68762b3a4bf9d2df32d8e188cb7e2adf2889ec 100644 (file)
@@ -851,29 +851,28 @@ ov772x_set_fmt_error:
        return ret;
 }
 
-static int ov772x_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
-{
-       a->c.left       = 0;
-       a->c.top        = 0;
-       a->c.width      = VGA_WIDTH;
-       a->c.height     = VGA_HEIGHT;
-       a->type         = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-
-       return 0;
-}
-
-static int ov772x_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
+static int ov772x_get_selection(struct v4l2_subdev *sd,
+               struct v4l2_subdev_pad_config *cfg,
+               struct v4l2_subdev_selection *sel)
 {
-       a->bounds.left                  = 0;
-       a->bounds.top                   = 0;
-       a->bounds.width                 = OV772X_MAX_WIDTH;
-       a->bounds.height                = OV772X_MAX_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;
+       sel->r.left = 0;
+       sel->r.top = 0;
+       switch (sel->target) {
+       case V4L2_SEL_TGT_CROP_BOUNDS:
+       case V4L2_SEL_TGT_CROP_DEFAULT:
+               sel->r.width = OV772X_MAX_WIDTH;
+               sel->r.height = OV772X_MAX_HEIGHT;
+               return 0;
+       case V4L2_SEL_TGT_CROP:
+               sel->r.width = VGA_WIDTH;
+               sel->r.height = VGA_HEIGHT;
+               return 0;
+       default:
+               return -EINVAL;
+       }
 }
 
 static int ov772x_get_fmt(struct v4l2_subdev *sd,
@@ -1030,13 +1029,12 @@ static int ov772x_g_mbus_config(struct v4l2_subdev *sd,
 
 static struct v4l2_subdev_video_ops ov772x_subdev_video_ops = {
        .s_stream       = ov772x_s_stream,
-       .cropcap        = ov772x_cropcap,
-       .g_crop         = ov772x_g_crop,
        .g_mbus_config  = ov772x_g_mbus_config,
 };
 
 static const struct v4l2_subdev_pad_ops ov772x_subdev_pad_ops = {
        .enum_mbus_code = ov772x_enum_mbus_code,
+       .get_selection  = ov772x_get_selection,
        .get_fmt        = ov772x_get_fmt,
        .set_fmt        = ov772x_set_fmt,
 };
index 8caae1c075413de2ed5c7d4afce36ecb37a3f08f..8c93c57af71cd2c7413b0bdd5564d1f070bf0f66 100644 (file)
@@ -561,29 +561,25 @@ static int ov9640_enum_mbus_code(struct v4l2_subdev *sd,
        return 0;
 }
 
-static int ov9640_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
-{
-       a->c.left       = 0;
-       a->c.top        = 0;
-       a->c.width      = W_SXGA;
-       a->c.height     = H_SXGA;
-       a->type         = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-
-       return 0;
-}
-
-static int ov9640_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
+static int ov9640_get_selection(struct v4l2_subdev *sd,
+               struct v4l2_subdev_pad_config *cfg,
+               struct v4l2_subdev_selection *sel)
 {
-       a->bounds.left                  = 0;
-       a->bounds.top                   = 0;
-       a->bounds.width                 = W_SXGA;
-       a->bounds.height                = H_SXGA;
-       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;
+       sel->r.left = 0;
+       sel->r.top = 0;
+       switch (sel->target) {
+       case V4L2_SEL_TGT_CROP_BOUNDS:
+       case V4L2_SEL_TGT_CROP_DEFAULT:
+       case V4L2_SEL_TGT_CROP:
+               sel->r.width = W_SXGA;
+               sel->r.height = H_SXGA;
+               return 0;
+       default:
+               return -EINVAL;
+       }
 }
 
 static int ov9640_video_probe(struct i2c_client *client)
@@ -667,13 +663,12 @@ static int ov9640_g_mbus_config(struct v4l2_subdev *sd,
 
 static struct v4l2_subdev_video_ops ov9640_video_ops = {
        .s_stream       = ov9640_s_stream,
-       .cropcap        = ov9640_cropcap,
-       .g_crop         = ov9640_g_crop,
        .g_mbus_config  = ov9640_g_mbus_config,
 };
 
 static const struct v4l2_subdev_pad_ops ov9640_pad_ops = {
        .enum_mbus_code = ov9640_enum_mbus_code,
+       .get_selection  = ov9640_get_selection,
        .set_fmt        = ov9640_set_fmt,
 };
 
index 03a7fc7316ae341f594e73b5ed1ec8a05dd50de7..0da632d7d33acd40306780de663ad514c75b18bd 100644 (file)
@@ -737,29 +737,25 @@ static int ov9740_enum_mbus_code(struct v4l2_subdev *sd,
        return 0;
 }
 
-static int ov9740_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
-{
-       a->bounds.left          = 0;
-       a->bounds.top           = 0;
-       a->bounds.width         = OV9740_MAX_WIDTH;
-       a->bounds.height        = OV9740_MAX_HEIGHT;
-       a->defrect              = a->bounds;
-       a->type                 = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-       a->pixelaspect.numerator        = 1;
-       a->pixelaspect.denominator      = 1;
-
-       return 0;
-}
-
-static int ov9740_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
+static int ov9740_get_selection(struct v4l2_subdev *sd,
+               struct v4l2_subdev_pad_config *cfg,
+               struct v4l2_subdev_selection *sel)
 {
-       a->c.left               = 0;
-       a->c.top                = 0;
-       a->c.width              = OV9740_MAX_WIDTH;
-       a->c.height             = OV9740_MAX_HEIGHT;
-       a->type                 = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       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 = OV9740_MAX_WIDTH;
+               sel->r.height = OV9740_MAX_HEIGHT;
+               return 0;
+       default:
+               return -EINVAL;
+       }
 }
 
 /* Set status of additional camera capabilities */
@@ -914,8 +910,6 @@ static int ov9740_g_mbus_config(struct v4l2_subdev *sd,
 
 static struct v4l2_subdev_video_ops ov9740_video_ops = {
        .s_stream       = ov9740_s_stream,
-       .cropcap        = ov9740_cropcap,
-       .g_crop         = ov9740_g_crop,
        .g_mbus_config  = ov9740_g_mbus_config,
 };
 
@@ -929,6 +923,7 @@ static struct v4l2_subdev_core_ops ov9740_core_ops = {
 
 static const struct v4l2_subdev_pad_ops ov9740_pad_ops = {
        .enum_mbus_code = ov9740_enum_mbus_code,
+       .get_selection  = ov9740_get_selection,
        .set_fmt        = ov9740_set_fmt,
 };
 
index aa7bfbb4ad71d8bd04cebe137e1666f0df3ee4f0..bc8ec59a3fbd52f26fda6162dbf4d8a0baed1b96 100644 (file)
@@ -538,15 +538,21 @@ static int rj54n1_commit(struct i2c_client *client)
 static int rj54n1_sensor_scale(struct v4l2_subdev *sd, s32 *in_w, s32 *in_h,
                               s32 *out_w, s32 *out_h);
 
-static int rj54n1_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a)
+static int rj54n1_set_selection(struct v4l2_subdev *sd,
+                               struct v4l2_subdev_pad_config *cfg,
+                               struct v4l2_subdev_selection *sel)
 {
        struct i2c_client *client = v4l2_get_subdevdata(sd);
        struct rj54n1 *rj54n1 = to_rj54n1(client);
-       const struct v4l2_rect *rect = &a->c;
+       const struct v4l2_rect *rect = &sel->r;
        int dummy = 0, output_w, output_h,
                input_w = rect->width, input_h = rect->height;
        int ret;
 
+       if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE ||
+           sel->target != V4L2_SEL_TGT_CROP)
+               return -EINVAL;
+
        /* arbitrary minimum width and height, edges unimportant */
        soc_camera_limit_side(&dummy, &input_w,
                     RJ54N1_COLUMN_SKIP, 8, RJ54N1_MAX_WIDTH);
@@ -573,29 +579,30 @@ static int rj54n1_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a)
        return 0;
 }
 
-static int rj54n1_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
+static int rj54n1_get_selection(struct v4l2_subdev *sd,
+                               struct v4l2_subdev_pad_config *cfg,
+                               struct v4l2_subdev_selection *sel)
 {
        struct i2c_client *client = v4l2_get_subdevdata(sd);
        struct rj54n1 *rj54n1 = to_rj54n1(client);
 
-       a->c    = rj54n1->rect;
-       a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-
-       return 0;
-}
-
-static int rj54n1_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
-{
-       a->bounds.left                  = RJ54N1_COLUMN_SKIP;
-       a->bounds.top                   = RJ54N1_ROW_SKIP;
-       a->bounds.width                 = RJ54N1_MAX_WIDTH;
-       a->bounds.height                = RJ54N1_MAX_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:
+               sel->r.left = RJ54N1_COLUMN_SKIP;
+               sel->r.top = RJ54N1_ROW_SKIP;
+               sel->r.width = RJ54N1_MAX_WIDTH;
+               sel->r.height = RJ54N1_MAX_HEIGHT;
+               return 0;
+       case V4L2_SEL_TGT_CROP:
+               sel->r = rj54n1->rect;
+               return 0;
+       default:
+               return -EINVAL;
+       }
 }
 
 static int rj54n1_get_fmt(struct v4l2_subdev *sd,
@@ -1246,15 +1253,14 @@ static int rj54n1_s_mbus_config(struct v4l2_subdev *sd,
 
 static struct v4l2_subdev_video_ops rj54n1_subdev_video_ops = {
        .s_stream       = rj54n1_s_stream,
-       .g_crop         = rj54n1_g_crop,
-       .s_crop         = rj54n1_s_crop,
-       .cropcap        = rj54n1_cropcap,
        .g_mbus_config  = rj54n1_g_mbus_config,
        .s_mbus_config  = rj54n1_s_mbus_config,
 };
 
 static const struct v4l2_subdev_pad_ops rj54n1_subdev_pad_ops = {
        .enum_mbus_code = rj54n1_enum_mbus_code,
+       .get_selection  = rj54n1_get_selection,
+       .set_selection  = rj54n1_set_selection,
        .get_fmt        = rj54n1_get_fmt,
        .set_fmt        = rj54n1_set_fmt,
 };
index 06aff81787a7bf43c5373395e0921e2c42f5de4b..4002c07f38572cc4aaf4cf4f570db7ecd1d052e9 100644 (file)
@@ -676,44 +676,28 @@ tw9910_set_fmt_error:
        return ret;
 }
 
-static int tw9910_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
+static int tw9910_get_selection(struct v4l2_subdev *sd,
+               struct v4l2_subdev_pad_config *cfg,
+               struct v4l2_subdev_selection *sel)
 {
        struct i2c_client *client = v4l2_get_subdevdata(sd);
        struct tw9910_priv *priv = to_tw9910(client);
 
-       a->c.left       = 0;
-       a->c.top        = 0;
-       if (priv->norm & V4L2_STD_NTSC) {
-               a->c.width      = 640;
-               a->c.height     = 480;
-       } else {
-               a->c.width      = 768;
-               a->c.height     = 576;
-       }
-       a->type         = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-
-       return 0;
-}
-
-static int tw9910_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
-{
-       struct i2c_client *client = v4l2_get_subdevdata(sd);
-       struct tw9910_priv *priv = to_tw9910(client);
+       if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+               return -EINVAL;
+       /* Only CROP, CROP_DEFAULT and CROP_BOUNDS are supported */
+       if (sel->target > V4L2_SEL_TGT_CROP_BOUNDS)
+               return -EINVAL;
 
-       a->bounds.left                  = 0;
-       a->bounds.top                   = 0;
+       sel->r.left     = 0;
+       sel->r.top      = 0;
        if (priv->norm & V4L2_STD_NTSC) {
-               a->bounds.width         = 640;
-               a->bounds.height        = 480;
+               sel->r.width    = 640;
+               sel->r.height   = 480;
        } else {
-               a->bounds.width         = 768;
-               a->bounds.height        = 576;
+               sel->r.width    = 768;
+               sel->r.height   = 576;
        }
-       a->defrect                      = a->bounds;
-       a->type                         = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-       a->pixelaspect.numerator        = 1;
-       a->pixelaspect.denominator      = 1;
-
        return 0;
 }
 
@@ -921,8 +905,6 @@ static struct v4l2_subdev_video_ops tw9910_subdev_video_ops = {
        .s_std          = tw9910_s_std,
        .g_std          = tw9910_g_std,
        .s_stream       = tw9910_s_stream,
-       .cropcap        = tw9910_cropcap,
-       .g_crop         = tw9910_g_crop,
        .g_mbus_config  = tw9910_g_mbus_config,
        .s_mbus_config  = tw9910_s_mbus_config,
        .g_tvnorms      = tw9910_g_tvnorms,
@@ -930,6 +912,7 @@ static struct v4l2_subdev_video_ops tw9910_subdev_video_ops = {
 
 static const struct v4l2_subdev_pad_ops tw9910_subdev_pad_ops = {
        .enum_mbus_code = tw9910_enum_mbus_code,
+       .get_selection  = tw9910_get_selection,
        .get_fmt        = tw9910_get_fmt,
        .set_fmt        = tw9910_set_fmt,
 };
index 0b6d46c453bf6157f0cebbac72e22d3eebdf9216..b7648fda519ca7fdb7b9977450a68a51ad040231 100644 (file)
@@ -871,19 +871,22 @@ static int tvp5150_fill_fmt(struct v4l2_subdev *sd,
        return 0;
 }
 
-static int tvp5150_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a)
+static int tvp5150_set_selection(struct v4l2_subdev *sd,
+                                struct v4l2_subdev_pad_config *cfg,
+                                struct v4l2_subdev_selection *sel)
 {
-       struct v4l2_rect rect = a->c;
        struct tvp5150 *decoder = to_tvp5150(sd);
+       struct v4l2_rect rect = sel->r;
        v4l2_std_id std;
-       unsigned int hmax;
+       int hmax;
+
+       if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE ||
+           sel->target != V4L2_SEL_TGT_CROP)
+               return -EINVAL;
 
        v4l2_dbg(1, debug, sd, "%s left=%d, top=%d, width=%d, height=%d\n",
                __func__, rect.left, rect.top, rect.width, rect.height);
 
-       if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-               return -EINVAL;
-
        /* tvp5150 has some special limits */
        rect.left = clamp(rect.left, 0, TVP5150_MAX_CROP_LEFT);
        rect.width = clamp_t(unsigned int, rect.width,
@@ -924,44 +927,39 @@ static int tvp5150_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a)
        return 0;
 }
 
-static int tvp5150_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
+static int tvp5150_get_selection(struct v4l2_subdev *sd,
+                                struct v4l2_subdev_pad_config *cfg,
+                                struct v4l2_subdev_selection *sel)
 {
-       struct tvp5150 *decoder = to_tvp5150(sd);
-
-       a->c    = decoder->rect;
-       a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-
-       return 0;
-}
-
-static int tvp5150_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
-{
-       struct tvp5150 *decoder = to_tvp5150(sd);
+       struct tvp5150 *decoder = container_of(sd, struct tvp5150, sd);
        v4l2_std_id std;
 
-       if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+       if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE)
                return -EINVAL;
 
-       a->bounds.left                  = 0;
-       a->bounds.top                   = 0;
-       a->bounds.width                 = TVP5150_H_MAX;
-
-       /* Calculate height based on current standard */
-       if (decoder->norm == V4L2_STD_ALL)
-               std = tvp5150_read_std(sd);
-       else
-               std = decoder->norm;
-
-       if (std & V4L2_STD_525_60)
-               a->bounds.height = TVP5150_V_MAX_525_60;
-       else
-               a->bounds.height = TVP5150_V_MAX_OTHERS;
-
-       a->defrect                      = a->bounds;
-       a->pixelaspect.numerator        = 1;
-       a->pixelaspect.denominator      = 1;
-
-       return 0;
+       switch (sel->target) {
+       case V4L2_SEL_TGT_CROP_BOUNDS:
+       case V4L2_SEL_TGT_CROP_DEFAULT:
+               sel->r.left = 0;
+               sel->r.top = 0;
+               sel->r.width = TVP5150_H_MAX;
+
+               /* Calculate height based on current standard */
+               if (decoder->norm == V4L2_STD_ALL)
+                       std = tvp5150_read_std(sd);
+               else
+                       std = decoder->norm;
+               if (std & V4L2_STD_525_60)
+                       sel->r.height = TVP5150_V_MAX_525_60;
+               else
+                       sel->r.height = TVP5150_V_MAX_OTHERS;
+               return 0;
+       case V4L2_SEL_TGT_CROP:
+               sel->r = decoder->rect;
+               return 0;
+       default:
+               return -EINVAL;
+       }
 }
 
 static int tvp5150_g_mbus_config(struct v4l2_subdev *sd,
@@ -1233,9 +1231,6 @@ static const struct v4l2_subdev_video_ops tvp5150_video_ops = {
        .s_std = tvp5150_s_std,
        .s_stream = tvp5150_s_stream,
        .s_routing = tvp5150_s_routing,
-       .s_crop = tvp5150_s_crop,
-       .g_crop = tvp5150_g_crop,
-       .cropcap = tvp5150_cropcap,
        .g_mbus_config = tvp5150_g_mbus_config,
 };
 
@@ -1251,6 +1246,8 @@ static const struct v4l2_subdev_pad_ops tvp5150_pad_ops = {
        .enum_frame_size = tvp5150_enum_frame_size,
        .set_fmt = tvp5150_fill_fmt,
        .get_fmt = tvp5150_fill_fmt,
+       .get_selection = tvp5150_get_selection,
+       .set_selection = tvp5150_set_selection,
 };
 
 static const struct v4l2_subdev_ops tvp5150_ops = {
index 7d9f35976d18e063e952a2b99c1acb3b04fc5493..7354469670b79a0e71298411c7b6791a314815d4 100644 (file)
@@ -772,40 +772,45 @@ isp_video_try_format(struct file *file, void *fh, struct v4l2_format *format)
 }
 
 static int
-isp_video_cropcap(struct file *file, void *fh, struct v4l2_cropcap *cropcap)
-{
-       struct isp_video *video = video_drvdata(file);
-       struct v4l2_subdev *subdev;
-       int ret;
-
-       subdev = isp_video_remote_subdev(video, NULL);
-       if (subdev == NULL)
-               return -EINVAL;
-
-       mutex_lock(&video->mutex);
-       ret = v4l2_subdev_call(subdev, video, cropcap, cropcap);
-       mutex_unlock(&video->mutex);
-
-       return ret == -ENOIOCTLCMD ? -ENOTTY : ret;
-}
-
-static int
-isp_video_get_crop(struct file *file, void *fh, struct v4l2_crop *crop)
+isp_video_get_selection(struct file *file, void *fh, struct v4l2_selection *sel)
 {
        struct isp_video *video = video_drvdata(file);
        struct v4l2_subdev_format format;
        struct v4l2_subdev *subdev;
+       struct v4l2_subdev_selection sdsel = {
+               .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+               .target = sel->target,
+       };
        u32 pad;
        int ret;
 
+       switch (sel->target) {
+       case V4L2_SEL_TGT_CROP:
+       case V4L2_SEL_TGT_CROP_BOUNDS:
+       case V4L2_SEL_TGT_CROP_DEFAULT:
+               if (video->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
+                       return -EINVAL;
+               break;
+       case V4L2_SEL_TGT_COMPOSE:
+       case V4L2_SEL_TGT_COMPOSE_BOUNDS:
+       case V4L2_SEL_TGT_COMPOSE_DEFAULT:
+               if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+                       return -EINVAL;
+               break;
+       default:
+               return -EINVAL;
+       }
        subdev = isp_video_remote_subdev(video, &pad);
        if (subdev == NULL)
                return -EINVAL;
 
-       /* Try the get crop operation first and fallback to get format if not
+       /* Try the get selection operation first and fallback to get format if not
         * implemented.
         */
-       ret = v4l2_subdev_call(subdev, video, g_crop, crop);
+       sdsel.pad = pad;
+       ret = v4l2_subdev_call(subdev, pad, get_selection, NULL, &sdsel);
+       if (!ret)
+               sel->r = sdsel.r;
        if (ret != -ENOIOCTLCMD)
                return ret;
 
@@ -815,28 +820,50 @@ isp_video_get_crop(struct file *file, void *fh, struct v4l2_crop *crop)
        if (ret < 0)
                return ret == -ENOIOCTLCMD ? -ENOTTY : ret;
 
-       crop->c.left = 0;
-       crop->c.top = 0;
-       crop->c.width = format.format.width;
-       crop->c.height = format.format.height;
+       sel->r.left = 0;
+       sel->r.top = 0;
+       sel->r.width = format.format.width;
+       sel->r.height = format.format.height;
 
        return 0;
 }
 
 static int
-isp_video_set_crop(struct file *file, void *fh, const struct v4l2_crop *crop)
+isp_video_set_selection(struct file *file, void *fh, struct v4l2_selection *sel)
 {
        struct isp_video *video = video_drvdata(file);
        struct v4l2_subdev *subdev;
+       struct v4l2_subdev_selection sdsel = {
+               .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+               .target = sel->target,
+               .flags = sel->flags,
+               .r = sel->r,
+       };
+       u32 pad;
        int ret;
 
-       subdev = isp_video_remote_subdev(video, NULL);
+       switch (sel->target) {
+       case V4L2_SEL_TGT_CROP:
+               if (video->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
+                       return -EINVAL;
+               break;
+       case V4L2_SEL_TGT_COMPOSE:
+               if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+                       return -EINVAL;
+               break;
+       default:
+               return -EINVAL;
+       }
+       subdev = isp_video_remote_subdev(video, &pad);
        if (subdev == NULL)
                return -EINVAL;
 
+       sdsel.pad = pad;
        mutex_lock(&video->mutex);
-       ret = v4l2_subdev_call(subdev, video, s_crop, crop);
+       ret = v4l2_subdev_call(subdev, pad, set_selection, NULL, &sdsel);
        mutex_unlock(&video->mutex);
+       if (!ret)
+               sel->r = sdsel.r;
 
        return ret == -ENOIOCTLCMD ? -ENOTTY : ret;
 }
@@ -1252,9 +1279,8 @@ static const struct v4l2_ioctl_ops isp_video_ioctl_ops = {
        .vidioc_g_fmt_vid_out           = isp_video_get_format,
        .vidioc_s_fmt_vid_out           = isp_video_set_format,
        .vidioc_try_fmt_vid_out         = isp_video_try_format,
-       .vidioc_cropcap                 = isp_video_cropcap,
-       .vidioc_g_crop                  = isp_video_get_crop,
-       .vidioc_s_crop                  = isp_video_set_crop,
+       .vidioc_g_selection             = isp_video_get_selection,
+       .vidioc_s_selection             = isp_video_set_selection,
        .vidioc_g_parm                  = isp_video_get_param,
        .vidioc_s_parm                  = isp_video_set_param,
        .vidioc_reqbufs                 = isp_video_reqbufs,
index e1f39b4cf1cd018d1ad52b31286847134c173405..4ee7b1570f62defa839b1ce5afdbd349506ca64c 100644 (file)
@@ -937,7 +937,10 @@ static int sh_vou_s_selection(struct file *file, void *fh,
 {
        struct v4l2_rect *rect = &sel->r;
        struct sh_vou_device *vou_dev = video_drvdata(file);
-       struct v4l2_crop sd_crop = {.type = V4L2_BUF_TYPE_VIDEO_OUTPUT};
+       struct v4l2_subdev_selection sd_sel = {
+               .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+               .target = V4L2_SEL_TGT_COMPOSE,
+       };
        struct v4l2_pix_format *pix = &vou_dev->pix;
        struct sh_vou_geometry geo;
        struct v4l2_subdev_format format = {
@@ -978,14 +981,14 @@ static int sh_vou_s_selection(struct file *file, void *fh,
        geo.in_height = pix->height;
 
        /* Configure the encoder one-to-one, position at 0, ignore errors */
-       sd_crop.c.width = geo.output.width;
-       sd_crop.c.height = geo.output.height;
+       sd_sel.r.width = geo.output.width;
+       sd_sel.r.height = geo.output.height;
        /*
-        * We first issue a S_CROP, so that the subsequent S_FMT delivers the
+        * We first issue a S_SELECTION, so that the subsequent S_FMT delivers the
         * final encoder configuration.
         */
-       v4l2_device_call_until_err(&vou_dev->v4l2_dev, 0, video,
-                                  s_crop, &sd_crop);
+       v4l2_device_call_until_err(&vou_dev->v4l2_dev, 0, pad,
+                                  set_selection, NULL, &sd_sel);
        format.format.width = geo.output.width;
        format.format.height = geo.output.height;
        ret = v4l2_device_call_until_err(&vou_dev->v4l2_dev, 0, pad,
index 2aaf4a8f71a023992def4c7af9f376c77a4fe327..ebbe514d64e20f132df785716c84151a15044ddb 100644 (file)
@@ -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,
index 9c137522c660e5704e8c1c3f7e3bec0aa9d60095..077f12d1575f301e01b01a3bb705944dbad636ac 100644 (file)
@@ -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,
index 05eafe3a421ee9e15a65cb76ed8006325a2a6476..e5571c8a368ea812e51df51255237081fbea242c 100644 (file)
@@ -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,
index 46c7186f78679a5ca09a01d8709cbb77cf1332bc..edd1c1de4e33828ad3e625dc08b5fba1e133fd97 100644 (file)
@@ -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,
index a51d2a42998c5797b2b4bb25a6944ee8bcf6c1e2..534d6c3c6d608865aa7afe0135c31dcdb4b61cfe 100644 (file)
@@ -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,
 };
index bda29bc1b9331c803702b3685df3a66b733c0e35..f77252d6ccd3a3c3caade41b2be891e5ddb4ed47 100644 (file)
@@ -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;
index 184a30dff5416d5835718f83ca5b34ce2c314a7a..9ca469312a1f554bc2b5e8e2adbb43f945098473 100644 (file)
@@ -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,
index 90b7ff56722d30a2d2c1324d492ac402d6f0fd4a..c16927ac8eb0b259ca1ece37da1043c53ecf279b 100644 (file)
@@ -645,6 +645,103 @@ iss_video_try_format(struct file *file, void *fh, struct v4l2_format *format)
        return 0;
 }
 
+static int
+iss_video_get_selection(struct file *file, void *fh, struct v4l2_selection *sel)
+{
+       struct iss_video *video = video_drvdata(file);
+       struct v4l2_subdev_format format;
+       struct v4l2_subdev *subdev;
+       struct v4l2_subdev_selection sdsel = {
+               .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+               .target = sel->target,
+       };
+       u32 pad;
+       int ret;
+
+       switch (sel->target) {
+       case V4L2_SEL_TGT_CROP:
+       case V4L2_SEL_TGT_CROP_BOUNDS:
+       case V4L2_SEL_TGT_CROP_DEFAULT:
+               if (video->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
+                       return -EINVAL;
+               break;
+       case V4L2_SEL_TGT_COMPOSE:
+       case V4L2_SEL_TGT_COMPOSE_BOUNDS:
+       case V4L2_SEL_TGT_COMPOSE_DEFAULT:
+               if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+                       return -EINVAL;
+               break;
+       default:
+               return -EINVAL;
+       }
+       subdev = iss_video_remote_subdev(video, &pad);
+       if (subdev == NULL)
+               return -EINVAL;
+
+       /* Try the get selection operation first and fallback to get format if not
+        * implemented.
+        */
+       sdsel.pad = pad;
+       ret = v4l2_subdev_call(subdev, pad, get_selection, NULL, &sdsel);
+       if (!ret)
+               sel->r = sdsel.r;
+       if (ret != -ENOIOCTLCMD)
+               return ret;
+
+       format.pad = pad;
+       format.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+       ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &format);
+       if (ret < 0)
+               return ret == -ENOIOCTLCMD ? -ENOTTY : ret;
+
+       sel->r.left = 0;
+       sel->r.top = 0;
+       sel->r.width = format.format.width;
+       sel->r.height = format.format.height;
+
+       return 0;
+}
+
+static int
+iss_video_set_selection(struct file *file, void *fh, struct v4l2_selection *sel)
+{
+       struct iss_video *video = video_drvdata(file);
+       struct v4l2_subdev *subdev;
+       struct v4l2_subdev_selection sdsel = {
+               .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+               .target = sel->target,
+               .flags = sel->flags,
+               .r = sel->r,
+       };
+       u32 pad;
+       int ret;
+
+       switch (sel->target) {
+       case V4L2_SEL_TGT_CROP:
+               if (video->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
+                       return -EINVAL;
+               break;
+       case V4L2_SEL_TGT_COMPOSE:
+               if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+                       return -EINVAL;
+               break;
+       default:
+               return -EINVAL;
+       }
+       subdev = iss_video_remote_subdev(video, &pad);
+       if (subdev == NULL)
+               return -EINVAL;
+
+       sdsel.pad = pad;
+       mutex_lock(&video->mutex);
+       ret = v4l2_subdev_call(subdev, pad, set_selection, NULL, &sdsel);
+       mutex_unlock(&video->mutex);
+       if (!ret)
+               sel->r = sdsel.r;
+
+       return ret == -ENOIOCTLCMD ? -ENOTTY : ret;
+}
+
 static int
 iss_video_get_param(struct file *file, void *fh, struct v4l2_streamparm *a)
 {
@@ -971,6 +1068,8 @@ static const struct v4l2_ioctl_ops iss_video_ioctl_ops = {
        .vidioc_g_fmt_vid_out           = iss_video_get_format,
        .vidioc_s_fmt_vid_out           = iss_video_set_format,
        .vidioc_try_fmt_vid_out         = iss_video_try_format,
+       .vidioc_g_selection             = iss_video_get_selection,
+       .vidioc_s_selection             = iss_video_set_selection,
        .vidioc_g_parm                  = iss_video_get_param,
        .vidioc_s_parm                  = iss_video_set_param,
        .vidioc_reqbufs                 = iss_video_reqbufs,
index 97aa13314bfd573cac01471be502b3af9462137d..1a15c3e4efd387ce5641946aaa67183ba5daa3f7 100644 (file)
@@ -105,16 +105,13 @@ struct soc_camera_host_ops {
        int (*get_formats)(struct soc_camera_device *, unsigned int,
                           struct soc_camera_format_xlate *);
        void (*put_formats)(struct soc_camera_device *);
-       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 *, const struct v4l2_crop *);
        int (*get_selection)(struct soc_camera_device *, struct v4l2_selection *);
        int (*set_selection)(struct soc_camera_device *, struct v4l2_selection *);
        /*
-        * The difference to .set_crop() is, that .set_livecrop is not allowed
+        * The difference to .set_selection() is, that .set_liveselection is not allowed
         * to change the output sizes
         */
-       int (*set_livecrop)(struct soc_camera_device *, const struct v4l2_crop *);
+       int (*set_liveselection)(struct soc_camera_device *, struct v4l2_selection *);
        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 *,
index 2a2240c99b30a975c226e41e792de31c5bc86fee..22ea819ada952ae699af0b1aa126675f8c1a2276 100644 (file)
@@ -360,10 +360,6 @@ struct v4l2_mbus_frame_desc {
  *
  * @cropcap: callback for %VIDIOC_CROPCAP ioctl handler code.
  *
- * @g_crop: callback for %VIDIOC_G_CROP ioctl handler code.
- *
- * @s_crop: callback for %VIDIOC_S_CROP ioctl handler code.
- *
  * @g_parm: callback for %VIDIOC_G_PARM ioctl handler code.
  *
  * @s_parm: callback for %VIDIOC_S_PARM ioctl handler code.
@@ -403,8 +399,6 @@ struct v4l2_subdev_video_ops {
        int (*g_input_status)(struct v4l2_subdev *sd, u32 *status);
        int (*s_stream)(struct v4l2_subdev *sd, int enable);
        int (*cropcap)(struct v4l2_subdev *sd, struct v4l2_cropcap *cc);
-       int (*g_crop)(struct v4l2_subdev *sd, struct v4l2_crop *crop);
-       int (*s_crop)(struct v4l2_subdev *sd, const struct v4l2_crop *crop);
        int (*g_parm)(struct v4l2_subdev *sd, struct v4l2_streamparm *param);
        int (*s_parm)(struct v4l2_subdev *sd, struct v4l2_streamparm *param);
        int (*g_frame_interval)(struct v4l2_subdev *sd,