aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media
diff options
context:
space:
mode:
authorHans Verkuil <hans.verkuil@cisco.com>2015-12-14 05:25:32 -0500
committerMauro Carvalho Chehab <mchehab@s-opensource.com>2016-08-24 08:46:09 -0400
commit10d5509c8d50a2c2f761a08a616530dced35e2d8 (patch)
treee3140b6d25f56cce9fa4a7df00e7e14bb762f54f /drivers/media
parent65d9e14a659520c554feea8ef17ee3109bd67ebd (diff)
[media] v4l2: remove g/s_crop from video ops
Replace all calls to g/s_crop by calls to the get/set_selection pad ops. Remove the old g/s_crop video ops since they are now no longer used. The cropcap video op is now only used to pass pixelaspect information, and is only needed if the pixelaspect is not 1:1. Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Cc: Guennadi Liakhovetski <g.liakhovetski@gmx.de> Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
Diffstat (limited to 'drivers/media')
-rw-r--r--drivers/media/i2c/ak881x.c28
-rw-r--r--drivers/media/i2c/soc_camera/imx074.c42
-rw-r--r--drivers/media/i2c/soc_camera/mt9m001.c70
-rw-r--r--drivers/media/i2c/soc_camera/mt9m111.c57
-rw-r--r--drivers/media/i2c/soc_camera/mt9t031.c54
-rw-r--r--drivers/media/i2c/soc_camera/mt9t112.c60
-rw-r--r--drivers/media/i2c/soc_camera/mt9v022.c68
-rw-r--r--drivers/media/i2c/soc_camera/ov2640.c41
-rw-r--r--drivers/media/i2c/soc_camera/ov5642.c53
-rw-r--r--drivers/media/i2c/soc_camera/ov6650.c74
-rw-r--r--drivers/media/i2c/soc_camera/ov772x.c44
-rw-r--r--drivers/media/i2c/soc_camera/ov9640.c41
-rw-r--r--drivers/media/i2c/soc_camera/ov9740.c41
-rw-r--r--drivers/media/i2c/soc_camera/rj54n1cb0c.c52
-rw-r--r--drivers/media/i2c/soc_camera/tw9910.c47
-rw-r--r--drivers/media/i2c/tvp5150.c81
-rw-r--r--drivers/media/platform/omap3isp/ispvideo.c88
-rw-r--r--drivers/media/platform/sh_vou.c15
-rw-r--r--drivers/media/platform/soc_camera/pxa_camera.c17
-rw-r--r--drivers/media/platform/soc_camera/rcar_vin.c30
-rw-r--r--drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c38
-rw-r--r--drivers/media/platform/soc_camera/soc_camera.c130
-rw-r--r--drivers/media/platform/soc_camera/soc_camera_platform.c45
-rw-r--r--drivers/media/platform/soc_camera/soc_scale_crop.c97
-rw-r--r--drivers/media/platform/soc_camera/soc_scale_crop.h6
25 files changed, 650 insertions, 669 deletions
diff --git a/drivers/media/i2c/ak881x.c b/drivers/media/i2c/ak881x.c
index d9f2b6b76d59..3a795dcb7d8e 100644
--- a/drivers/media/i2c/ak881x.c
+++ b/drivers/media/i2c/ak881x.c
@@ -124,21 +124,27 @@ static int ak881x_enum_mbus_code(struct v4l2_subdev *sd,
124 return 0; 124 return 0;
125} 125}
126 126
127static int ak881x_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) 127static int ak881x_get_selection(struct v4l2_subdev *sd,
128 struct v4l2_subdev_pad_config *cfg,
129 struct v4l2_subdev_selection *sel)
128{ 130{
129 struct i2c_client *client = v4l2_get_subdevdata(sd); 131 struct i2c_client *client = v4l2_get_subdevdata(sd);
130 struct ak881x *ak881x = to_ak881x(client); 132 struct ak881x *ak881x = to_ak881x(client);
131 133
132 a->bounds.left = 0; 134 if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE)
133 a->bounds.top = 0; 135 return -EINVAL;
134 a->bounds.width = 720;
135 a->bounds.height = ak881x->lines;
136 a->defrect = a->bounds;
137 a->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
138 a->pixelaspect.numerator = 1;
139 a->pixelaspect.denominator = 1;
140 136
141 return 0; 137 switch (sel->target) {
138 case V4L2_SEL_TGT_CROP_BOUNDS:
139 case V4L2_SEL_TGT_CROP_DEFAULT:
140 sel->r.left = 0;
141 sel->r.top = 0;
142 sel->r.width = 720;
143 sel->r.height = ak881x->lines;
144 return 0;
145 default:
146 return -EINVAL;
147 }
142} 148}
143 149
144static int ak881x_s_std_output(struct v4l2_subdev *sd, v4l2_std_id std) 150static 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 = {
207}; 213};
208 214
209static struct v4l2_subdev_video_ops ak881x_subdev_video_ops = { 215static struct v4l2_subdev_video_ops ak881x_subdev_video_ops = {
210 .cropcap = ak881x_cropcap,
211 .s_std_output = ak881x_s_std_output, 216 .s_std_output = ak881x_s_std_output,
212 .s_stream = ak881x_s_stream, 217 .s_stream = ak881x_s_stream,
213}; 218};
214 219
215static const struct v4l2_subdev_pad_ops ak881x_subdev_pad_ops = { 220static const struct v4l2_subdev_pad_ops ak881x_subdev_pad_ops = {
216 .enum_mbus_code = ak881x_enum_mbus_code, 221 .enum_mbus_code = ak881x_enum_mbus_code,
222 .get_selection = ak881x_get_selection,
217 .set_fmt = ak881x_fill_fmt, 223 .set_fmt = ak881x_fill_fmt,
218 .get_fmt = ak881x_fill_fmt, 224 .get_fmt = ak881x_fill_fmt,
219}; 225};
diff --git a/drivers/media/i2c/soc_camera/imx074.c b/drivers/media/i2c/soc_camera/imx074.c
index f68c2352c63c..05b55cfe8147 100644
--- a/drivers/media/i2c/soc_camera/imx074.c
+++ b/drivers/media/i2c/soc_camera/imx074.c
@@ -209,31 +209,26 @@ static int imx074_get_fmt(struct v4l2_subdev *sd,
209 return 0; 209 return 0;
210} 210}
211 211
212static int imx074_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) 212static int imx074_get_selection(struct v4l2_subdev *sd,
213 struct v4l2_subdev_pad_config *cfg,
214 struct v4l2_subdev_selection *sel)
213{ 215{
214 struct v4l2_rect *rect = &a->c; 216 if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE)
215 217 return -EINVAL;
216 a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
217 rect->top = 0;
218 rect->left = 0;
219 rect->width = IMX074_WIDTH;
220 rect->height = IMX074_HEIGHT;
221
222 return 0;
223}
224 218
225static int imx074_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) 219 sel->r.left = 0;
226{ 220 sel->r.top = 0;
227 a->bounds.left = 0; 221 sel->r.width = IMX074_WIDTH;
228 a->bounds.top = 0; 222 sel->r.height = IMX074_HEIGHT;
229 a->bounds.width = IMX074_WIDTH;
230 a->bounds.height = IMX074_HEIGHT;
231 a->defrect = a->bounds;
232 a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
233 a->pixelaspect.numerator = 1;
234 a->pixelaspect.denominator = 1;
235 223
236 return 0; 224 switch (sel->target) {
225 case V4L2_SEL_TGT_CROP_BOUNDS:
226 case V4L2_SEL_TGT_CROP_DEFAULT:
227 case V4L2_SEL_TGT_CROP:
228 return 0;
229 default:
230 return -EINVAL;
231 }
237} 232}
238 233
239static int imx074_enum_mbus_code(struct v4l2_subdev *sd, 234static int imx074_enum_mbus_code(struct v4l2_subdev *sd,
@@ -278,8 +273,6 @@ static int imx074_g_mbus_config(struct v4l2_subdev *sd,
278 273
279static struct v4l2_subdev_video_ops imx074_subdev_video_ops = { 274static struct v4l2_subdev_video_ops imx074_subdev_video_ops = {
280 .s_stream = imx074_s_stream, 275 .s_stream = imx074_s_stream,
281 .g_crop = imx074_g_crop,
282 .cropcap = imx074_cropcap,
283 .g_mbus_config = imx074_g_mbus_config, 276 .g_mbus_config = imx074_g_mbus_config,
284}; 277};
285 278
@@ -289,6 +282,7 @@ static struct v4l2_subdev_core_ops imx074_subdev_core_ops = {
289 282
290static const struct v4l2_subdev_pad_ops imx074_subdev_pad_ops = { 283static const struct v4l2_subdev_pad_ops imx074_subdev_pad_ops = {
291 .enum_mbus_code = imx074_enum_mbus_code, 284 .enum_mbus_code = imx074_enum_mbus_code,
285 .get_selection = imx074_get_selection,
292 .get_fmt = imx074_get_fmt, 286 .get_fmt = imx074_get_fmt,
293 .set_fmt = imx074_set_fmt, 287 .set_fmt = imx074_set_fmt,
294}; 288};
diff --git a/drivers/media/i2c/soc_camera/mt9m001.c b/drivers/media/i2c/soc_camera/mt9m001.c
index 69becc358659..3d6378d4491c 100644
--- a/drivers/media/i2c/soc_camera/mt9m001.c
+++ b/drivers/media/i2c/soc_camera/mt9m001.c
@@ -171,13 +171,19 @@ static int mt9m001_s_stream(struct v4l2_subdev *sd, int enable)
171 return 0; 171 return 0;
172} 172}
173 173
174static int mt9m001_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a) 174static int mt9m001_set_selection(struct v4l2_subdev *sd,
175 struct v4l2_subdev_pad_config *cfg,
176 struct v4l2_subdev_selection *sel)
175{ 177{
176 struct i2c_client *client = v4l2_get_subdevdata(sd); 178 struct i2c_client *client = v4l2_get_subdevdata(sd);
177 struct mt9m001 *mt9m001 = to_mt9m001(client); 179 struct mt9m001 *mt9m001 = to_mt9m001(client);
178 struct v4l2_rect rect = a->c; 180 struct v4l2_rect rect = sel->r;
179 int ret;
180 const u16 hblank = 9, vblank = 25; 181 const u16 hblank = 9, vblank = 25;
182 int ret;
183
184 if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE ||
185 sel->target != V4L2_SEL_TGT_CROP)
186 return -EINVAL;
181 187
182 if (mt9m001->fmts == mt9m001_colour_fmts) 188 if (mt9m001->fmts == mt9m001_colour_fmts)
183 /* 189 /*
@@ -225,29 +231,30 @@ static int mt9m001_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a)
225 return ret; 231 return ret;
226} 232}
227 233
228static int mt9m001_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) 234static int mt9m001_get_selection(struct v4l2_subdev *sd,
235 struct v4l2_subdev_pad_config *cfg,
236 struct v4l2_subdev_selection *sel)
229{ 237{
230 struct i2c_client *client = v4l2_get_subdevdata(sd); 238 struct i2c_client *client = v4l2_get_subdevdata(sd);
231 struct mt9m001 *mt9m001 = to_mt9m001(client); 239 struct mt9m001 *mt9m001 = to_mt9m001(client);
232 240
233 a->c = mt9m001->rect; 241 if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE)
234 a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 242 return -EINVAL;
235
236 return 0;
237}
238
239static int mt9m001_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
240{
241 a->bounds.left = MT9M001_COLUMN_SKIP;
242 a->bounds.top = MT9M001_ROW_SKIP;
243 a->bounds.width = MT9M001_MAX_WIDTH;
244 a->bounds.height = MT9M001_MAX_HEIGHT;
245 a->defrect = a->bounds;
246 a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
247 a->pixelaspect.numerator = 1;
248 a->pixelaspect.denominator = 1;
249 243
250 return 0; 244 switch (sel->target) {
245 case V4L2_SEL_TGT_CROP_BOUNDS:
246 case V4L2_SEL_TGT_CROP_DEFAULT:
247 sel->r.left = MT9M001_COLUMN_SKIP;
248 sel->r.top = MT9M001_ROW_SKIP;
249 sel->r.width = MT9M001_MAX_WIDTH;
250 sel->r.height = MT9M001_MAX_HEIGHT;
251 return 0;
252 case V4L2_SEL_TGT_CROP:
253 sel->r = mt9m001->rect;
254 return 0;
255 default:
256 return -EINVAL;
257 }
251} 258}
252 259
253static int mt9m001_get_fmt(struct v4l2_subdev *sd, 260static int mt9m001_get_fmt(struct v4l2_subdev *sd,
@@ -275,18 +282,18 @@ static int mt9m001_s_fmt(struct v4l2_subdev *sd,
275{ 282{
276 struct i2c_client *client = v4l2_get_subdevdata(sd); 283 struct i2c_client *client = v4l2_get_subdevdata(sd);
277 struct mt9m001 *mt9m001 = to_mt9m001(client); 284 struct mt9m001 *mt9m001 = to_mt9m001(client);
278 struct v4l2_crop a = { 285 struct v4l2_subdev_selection sel = {
279 .c = { 286 .which = V4L2_SUBDEV_FORMAT_ACTIVE,
280 .left = mt9m001->rect.left, 287 .target = V4L2_SEL_TGT_CROP,
281 .top = mt9m001->rect.top, 288 .r.left = mt9m001->rect.left,
282 .width = mf->width, 289 .r.top = mt9m001->rect.top,
283 .height = mf->height, 290 .r.width = mf->width,
284 }, 291 .r.height = mf->height,
285 }; 292 };
286 int ret; 293 int ret;
287 294
288 /* No support for scaling so far, just crop. TODO: use skipping */ 295 /* No support for scaling so far, just crop. TODO: use skipping */
289 ret = mt9m001_s_crop(sd, &a); 296 ret = mt9m001_set_selection(sd, NULL, &sel);
290 if (!ret) { 297 if (!ret) {
291 mf->width = mt9m001->rect.width; 298 mf->width = mt9m001->rect.width;
292 mf->height = mt9m001->rect.height; 299 mf->height = mt9m001->rect.height;
@@ -625,9 +632,6 @@ static int mt9m001_s_mbus_config(struct v4l2_subdev *sd,
625 632
626static struct v4l2_subdev_video_ops mt9m001_subdev_video_ops = { 633static struct v4l2_subdev_video_ops mt9m001_subdev_video_ops = {
627 .s_stream = mt9m001_s_stream, 634 .s_stream = mt9m001_s_stream,
628 .s_crop = mt9m001_s_crop,
629 .g_crop = mt9m001_g_crop,
630 .cropcap = mt9m001_cropcap,
631 .g_mbus_config = mt9m001_g_mbus_config, 635 .g_mbus_config = mt9m001_g_mbus_config,
632 .s_mbus_config = mt9m001_s_mbus_config, 636 .s_mbus_config = mt9m001_s_mbus_config,
633}; 637};
@@ -638,6 +642,8 @@ static const struct v4l2_subdev_sensor_ops mt9m001_subdev_sensor_ops = {
638 642
639static const struct v4l2_subdev_pad_ops mt9m001_subdev_pad_ops = { 643static const struct v4l2_subdev_pad_ops mt9m001_subdev_pad_ops = {
640 .enum_mbus_code = mt9m001_enum_mbus_code, 644 .enum_mbus_code = mt9m001_enum_mbus_code,
645 .get_selection = mt9m001_get_selection,
646 .set_selection = mt9m001_set_selection,
641 .get_fmt = mt9m001_get_fmt, 647 .get_fmt = mt9m001_get_fmt,
642 .set_fmt = mt9m001_set_fmt, 648 .set_fmt = mt9m001_set_fmt,
643}; 649};
diff --git a/drivers/media/i2c/soc_camera/mt9m111.c b/drivers/media/i2c/soc_camera/mt9m111.c
index 6dfaead6aaa8..6c8d1123658c 100644
--- a/drivers/media/i2c/soc_camera/mt9m111.c
+++ b/drivers/media/i2c/soc_camera/mt9m111.c
@@ -383,14 +383,18 @@ static int mt9m111_reset(struct mt9m111 *mt9m111)
383 return ret; 383 return ret;
384} 384}
385 385
386static int mt9m111_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a) 386static int mt9m111_set_selection(struct v4l2_subdev *sd,
387 struct v4l2_subdev_pad_config *cfg,
388 struct v4l2_subdev_selection *sel)
387{ 389{
388 struct v4l2_rect rect = a->c; 390 struct i2c_client *client = v4l2_get_subdevdata(sd);
389 struct mt9m111 *mt9m111 = container_of(sd, struct mt9m111, subdev); 391 struct mt9m111 *mt9m111 = to_mt9m111(client);
392 struct v4l2_rect rect = sel->r;
390 int width, height; 393 int width, height;
391 int ret; 394 int ret;
392 395
393 if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) 396 if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE ||
397 sel->target != V4L2_SEL_TGT_CROP)
394 return -EINVAL; 398 return -EINVAL;
395 399
396 if (mt9m111->fmt->code == MEDIA_BUS_FMT_SBGGR8_1X8 || 400 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)
421 return ret; 425 return ret;
422} 426}
423 427
424static int mt9m111_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) 428static int mt9m111_get_selection(struct v4l2_subdev *sd,
429 struct v4l2_subdev_pad_config *cfg,
430 struct v4l2_subdev_selection *sel)
425{ 431{
426 struct mt9m111 *mt9m111 = container_of(sd, struct mt9m111, subdev); 432 struct i2c_client *client = v4l2_get_subdevdata(sd);
427 433 struct mt9m111 *mt9m111 = to_mt9m111(client);
428 a->c = mt9m111->rect;
429 a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
430
431 return 0;
432}
433 434
434static int mt9m111_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) 435 if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE)
435{
436 if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
437 return -EINVAL; 436 return -EINVAL;
438 437
439 a->bounds.left = MT9M111_MIN_DARK_COLS; 438 switch (sel->target) {
440 a->bounds.top = MT9M111_MIN_DARK_ROWS; 439 case V4L2_SEL_TGT_CROP_BOUNDS:
441 a->bounds.width = MT9M111_MAX_WIDTH; 440 case V4L2_SEL_TGT_CROP_DEFAULT:
442 a->bounds.height = MT9M111_MAX_HEIGHT; 441 sel->r.left = MT9M111_MIN_DARK_COLS;
443 a->defrect = a->bounds; 442 sel->r.top = MT9M111_MIN_DARK_ROWS;
444 a->pixelaspect.numerator = 1; 443 sel->r.width = MT9M111_MAX_WIDTH;
445 a->pixelaspect.denominator = 1; 444 sel->r.height = MT9M111_MAX_HEIGHT;
446 445 return 0;
447 return 0; 446 case V4L2_SEL_TGT_CROP:
447 sel->r = mt9m111->rect;
448 return 0;
449 default:
450 return -EINVAL;
451 }
448} 452}
449 453
450static int mt9m111_get_fmt(struct v4l2_subdev *sd, 454static int mt9m111_get_fmt(struct v4l2_subdev *sd,
@@ -867,14 +871,13 @@ static int mt9m111_g_mbus_config(struct v4l2_subdev *sd,
867} 871}
868 872
869static struct v4l2_subdev_video_ops mt9m111_subdev_video_ops = { 873static struct v4l2_subdev_video_ops mt9m111_subdev_video_ops = {
870 .s_crop = mt9m111_s_crop,
871 .g_crop = mt9m111_g_crop,
872 .cropcap = mt9m111_cropcap,
873 .g_mbus_config = mt9m111_g_mbus_config, 874 .g_mbus_config = mt9m111_g_mbus_config,
874}; 875};
875 876
876static const struct v4l2_subdev_pad_ops mt9m111_subdev_pad_ops = { 877static const struct v4l2_subdev_pad_ops mt9m111_subdev_pad_ops = {
877 .enum_mbus_code = mt9m111_enum_mbus_code, 878 .enum_mbus_code = mt9m111_enum_mbus_code,
879 .get_selection = mt9m111_get_selection,
880 .set_selection = mt9m111_set_selection,
878 .get_fmt = mt9m111_get_fmt, 881 .get_fmt = mt9m111_get_fmt,
879 .set_fmt = mt9m111_set_fmt, 882 .set_fmt = mt9m111_set_fmt,
880}; 883};
diff --git a/drivers/media/i2c/soc_camera/mt9t031.c b/drivers/media/i2c/soc_camera/mt9t031.c
index 5c8e3ffe3b27..3aa5569065ad 100644
--- a/drivers/media/i2c/soc_camera/mt9t031.c
+++ b/drivers/media/i2c/soc_camera/mt9t031.c
@@ -264,7 +264,7 @@ static int mt9t031_set_params(struct i2c_client *client,
264 264
265 /* 265 /*
266 * The caller provides a supported format, as guaranteed by 266 * The caller provides a supported format, as guaranteed by
267 * .set_fmt(FORMAT_TRY), soc_camera_s_crop() and soc_camera_cropcap() 267 * .set_fmt(FORMAT_TRY), soc_camera_s_selection() and soc_camera_cropcap()
268 */ 268 */
269 if (ret >= 0) 269 if (ret >= 0)
270 ret = reg_write(client, MT9T031_COLUMN_START, rect->left); 270 ret = reg_write(client, MT9T031_COLUMN_START, rect->left);
@@ -294,11 +294,17 @@ static int mt9t031_set_params(struct i2c_client *client,
294 return ret < 0 ? ret : 0; 294 return ret < 0 ? ret : 0;
295} 295}
296 296
297static int mt9t031_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a) 297static int mt9t031_set_selection(struct v4l2_subdev *sd,
298 struct v4l2_subdev_pad_config *cfg,
299 struct v4l2_subdev_selection *sel)
298{ 300{
299 struct v4l2_rect rect = a->c;
300 struct i2c_client *client = v4l2_get_subdevdata(sd); 301 struct i2c_client *client = v4l2_get_subdevdata(sd);
301 struct mt9t031 *mt9t031 = to_mt9t031(client); 302 struct mt9t031 *mt9t031 = to_mt9t031(client);
303 struct v4l2_rect rect = sel->r;
304
305 if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE ||
306 sel->target != V4L2_SEL_TGT_CROP)
307 return -EINVAL;
302 308
303 rect.width = ALIGN(rect.width, 2); 309 rect.width = ALIGN(rect.width, 2);
304 rect.height = ALIGN(rect.height, 2); 310 rect.height = ALIGN(rect.height, 2);
@@ -312,29 +318,30 @@ static int mt9t031_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a)
312 return mt9t031_set_params(client, &rect, mt9t031->xskip, mt9t031->yskip); 318 return mt9t031_set_params(client, &rect, mt9t031->xskip, mt9t031->yskip);
313} 319}
314 320
315static int mt9t031_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) 321static int mt9t031_get_selection(struct v4l2_subdev *sd,
322 struct v4l2_subdev_pad_config *cfg,
323 struct v4l2_subdev_selection *sel)
316{ 324{
317 struct i2c_client *client = v4l2_get_subdevdata(sd); 325 struct i2c_client *client = v4l2_get_subdevdata(sd);
318 struct mt9t031 *mt9t031 = to_mt9t031(client); 326 struct mt9t031 *mt9t031 = to_mt9t031(client);
319 327
320 a->c = mt9t031->rect; 328 if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE)
321 a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 329 return -EINVAL;
322
323 return 0;
324}
325
326static int mt9t031_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
327{
328 a->bounds.left = MT9T031_COLUMN_SKIP;
329 a->bounds.top = MT9T031_ROW_SKIP;
330 a->bounds.width = MT9T031_MAX_WIDTH;
331 a->bounds.height = MT9T031_MAX_HEIGHT;
332 a->defrect = a->bounds;
333 a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
334 a->pixelaspect.numerator = 1;
335 a->pixelaspect.denominator = 1;
336 330
337 return 0; 331 switch (sel->target) {
332 case V4L2_SEL_TGT_CROP_BOUNDS:
333 case V4L2_SEL_TGT_CROP_DEFAULT:
334 sel->r.left = MT9T031_COLUMN_SKIP;
335 sel->r.top = MT9T031_ROW_SKIP;
336 sel->r.width = MT9T031_MAX_WIDTH;
337 sel->r.height = MT9T031_MAX_HEIGHT;
338 return 0;
339 case V4L2_SEL_TGT_CROP:
340 sel->r = mt9t031->rect;
341 return 0;
342 default:
343 return -EINVAL;
344 }
338} 345}
339 346
340static int mt9t031_get_fmt(struct v4l2_subdev *sd, 347static int mt9t031_get_fmt(struct v4l2_subdev *sd,
@@ -721,9 +728,6 @@ static int mt9t031_s_mbus_config(struct v4l2_subdev *sd,
721 728
722static struct v4l2_subdev_video_ops mt9t031_subdev_video_ops = { 729static struct v4l2_subdev_video_ops mt9t031_subdev_video_ops = {
723 .s_stream = mt9t031_s_stream, 730 .s_stream = mt9t031_s_stream,
724 .s_crop = mt9t031_s_crop,
725 .g_crop = mt9t031_g_crop,
726 .cropcap = mt9t031_cropcap,
727 .g_mbus_config = mt9t031_g_mbus_config, 731 .g_mbus_config = mt9t031_g_mbus_config,
728 .s_mbus_config = mt9t031_s_mbus_config, 732 .s_mbus_config = mt9t031_s_mbus_config,
729}; 733};
@@ -734,6 +738,8 @@ static const struct v4l2_subdev_sensor_ops mt9t031_subdev_sensor_ops = {
734 738
735static const struct v4l2_subdev_pad_ops mt9t031_subdev_pad_ops = { 739static const struct v4l2_subdev_pad_ops mt9t031_subdev_pad_ops = {
736 .enum_mbus_code = mt9t031_enum_mbus_code, 740 .enum_mbus_code = mt9t031_enum_mbus_code,
741 .get_selection = mt9t031_get_selection,
742 .set_selection = mt9t031_set_selection,
737 .get_fmt = mt9t031_get_fmt, 743 .get_fmt = mt9t031_get_fmt,
738 .set_fmt = mt9t031_set_fmt, 744 .set_fmt = mt9t031_set_fmt,
739}; 745};
diff --git a/drivers/media/i2c/soc_camera/mt9t112.c b/drivers/media/i2c/soc_camera/mt9t112.c
index 6a1b2a9f9a09..2ef22241ec14 100644
--- a/drivers/media/i2c/soc_camera/mt9t112.c
+++ b/drivers/media/i2c/soc_camera/mt9t112.c
@@ -867,39 +867,48 @@ static int mt9t112_set_params(struct mt9t112_priv *priv,
867 return 0; 867 return 0;
868} 868}
869 869
870static int mt9t112_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) 870static int mt9t112_get_selection(struct v4l2_subdev *sd,
871{ 871 struct v4l2_subdev_pad_config *cfg,
872 a->bounds.left = 0; 872 struct v4l2_subdev_selection *sel)
873 a->bounds.top = 0;
874 a->bounds.width = MAX_WIDTH;
875 a->bounds.height = MAX_HEIGHT;
876 a->defrect.left = 0;
877 a->defrect.top = 0;
878 a->defrect.width = VGA_WIDTH;
879 a->defrect.height = VGA_HEIGHT;
880 a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
881 a->pixelaspect.numerator = 1;
882 a->pixelaspect.denominator = 1;
883
884 return 0;
885}
886
887static int mt9t112_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
888{ 873{
889 struct i2c_client *client = v4l2_get_subdevdata(sd); 874 struct i2c_client *client = v4l2_get_subdevdata(sd);
890 struct mt9t112_priv *priv = to_mt9t112(client); 875 struct mt9t112_priv *priv = to_mt9t112(client);
891 876
892 a->c = priv->frame; 877 if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE)
893 a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 878 return -EINVAL;
894 879
895 return 0; 880 switch (sel->target) {
881 case V4L2_SEL_TGT_CROP_BOUNDS:
882 sel->r.left = 0;
883 sel->r.top = 0;
884 sel->r.width = MAX_WIDTH;
885 sel->r.height = MAX_HEIGHT;
886 return 0;
887 case V4L2_SEL_TGT_CROP_DEFAULT:
888 sel->r.left = 0;
889 sel->r.top = 0;
890 sel->r.width = VGA_WIDTH;
891 sel->r.height = VGA_HEIGHT;
892 return 0;
893 case V4L2_SEL_TGT_CROP:
894 sel->r = priv->frame;
895 return 0;
896 default:
897 return -EINVAL;
898 }
896} 899}
897 900
898static int mt9t112_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a) 901static int mt9t112_set_selection(struct v4l2_subdev *sd,
902 struct v4l2_subdev_pad_config *cfg,
903 struct v4l2_subdev_selection *sel)
899{ 904{
900 struct i2c_client *client = v4l2_get_subdevdata(sd); 905 struct i2c_client *client = v4l2_get_subdevdata(sd);
901 struct mt9t112_priv *priv = to_mt9t112(client); 906 struct mt9t112_priv *priv = to_mt9t112(client);
902 const struct v4l2_rect *rect = &a->c; 907 const struct v4l2_rect *rect = &sel->r;
908
909 if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE ||
910 sel->target != V4L2_SEL_TGT_CROP)
911 return -EINVAL;
903 912
904 return mt9t112_set_params(priv, rect, priv->format->code); 913 return mt9t112_set_params(priv, rect, priv->format->code);
905} 914}
@@ -1024,15 +1033,14 @@ static int mt9t112_s_mbus_config(struct v4l2_subdev *sd,
1024 1033
1025static struct v4l2_subdev_video_ops mt9t112_subdev_video_ops = { 1034static struct v4l2_subdev_video_ops mt9t112_subdev_video_ops = {
1026 .s_stream = mt9t112_s_stream, 1035 .s_stream = mt9t112_s_stream,
1027 .cropcap = mt9t112_cropcap,
1028 .g_crop = mt9t112_g_crop,
1029 .s_crop = mt9t112_s_crop,
1030 .g_mbus_config = mt9t112_g_mbus_config, 1036 .g_mbus_config = mt9t112_g_mbus_config,
1031 .s_mbus_config = mt9t112_s_mbus_config, 1037 .s_mbus_config = mt9t112_s_mbus_config,
1032}; 1038};
1033 1039
1034static const struct v4l2_subdev_pad_ops mt9t112_subdev_pad_ops = { 1040static const struct v4l2_subdev_pad_ops mt9t112_subdev_pad_ops = {
1035 .enum_mbus_code = mt9t112_enum_mbus_code, 1041 .enum_mbus_code = mt9t112_enum_mbus_code,
1042 .get_selection = mt9t112_get_selection,
1043 .set_selection = mt9t112_set_selection,
1036 .get_fmt = mt9t112_get_fmt, 1044 .get_fmt = mt9t112_get_fmt,
1037 .set_fmt = mt9t112_set_fmt, 1045 .set_fmt = mt9t112_set_fmt,
1038}; 1046};
diff --git a/drivers/media/i2c/soc_camera/mt9v022.c b/drivers/media/i2c/soc_camera/mt9v022.c
index 2721e583bfa0..6a14ab5e4f2d 100644
--- a/drivers/media/i2c/soc_camera/mt9v022.c
+++ b/drivers/media/i2c/soc_camera/mt9v022.c
@@ -276,14 +276,20 @@ static int mt9v022_s_stream(struct v4l2_subdev *sd, int enable)
276 return 0; 276 return 0;
277} 277}
278 278
279static int mt9v022_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a) 279static int mt9v022_set_selection(struct v4l2_subdev *sd,
280 struct v4l2_subdev_pad_config *cfg,
281 struct v4l2_subdev_selection *sel)
280{ 282{
281 struct i2c_client *client = v4l2_get_subdevdata(sd); 283 struct i2c_client *client = v4l2_get_subdevdata(sd);
282 struct mt9v022 *mt9v022 = to_mt9v022(client); 284 struct mt9v022 *mt9v022 = to_mt9v022(client);
283 struct v4l2_rect rect = a->c; 285 struct v4l2_rect rect = sel->r;
284 int min_row, min_blank; 286 int min_row, min_blank;
285 int ret; 287 int ret;
286 288
289 if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE ||
290 sel->target != V4L2_SEL_TGT_CROP)
291 return -EINVAL;
292
287 /* Bayer format - even size lengths */ 293 /* Bayer format - even size lengths */
288 if (mt9v022->fmts == mt9v022_colour_fmts) { 294 if (mt9v022->fmts == mt9v022_colour_fmts) {
289 rect.width = ALIGN(rect.width, 2); 295 rect.width = ALIGN(rect.width, 2);
@@ -350,29 +356,30 @@ static int mt9v022_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a)
350 return 0; 356 return 0;
351} 357}
352 358
353static int mt9v022_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) 359static int mt9v022_get_selection(struct v4l2_subdev *sd,
360 struct v4l2_subdev_pad_config *cfg,
361 struct v4l2_subdev_selection *sel)
354{ 362{
355 struct i2c_client *client = v4l2_get_subdevdata(sd); 363 struct i2c_client *client = v4l2_get_subdevdata(sd);
356 struct mt9v022 *mt9v022 = to_mt9v022(client); 364 struct mt9v022 *mt9v022 = to_mt9v022(client);
357 365
358 a->c = mt9v022->rect; 366 if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE)
359 a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 367 return -EINVAL;
360
361 return 0;
362}
363
364static int mt9v022_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
365{
366 a->bounds.left = MT9V022_COLUMN_SKIP;
367 a->bounds.top = MT9V022_ROW_SKIP;
368 a->bounds.width = MT9V022_MAX_WIDTH;
369 a->bounds.height = MT9V022_MAX_HEIGHT;
370 a->defrect = a->bounds;
371 a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
372 a->pixelaspect.numerator = 1;
373 a->pixelaspect.denominator = 1;
374 368
375 return 0; 369 switch (sel->target) {
370 case V4L2_SEL_TGT_CROP_BOUNDS:
371 case V4L2_SEL_TGT_CROP_DEFAULT:
372 sel->r.left = MT9V022_COLUMN_SKIP;
373 sel->r.top = MT9V022_ROW_SKIP;
374 sel->r.width = MT9V022_MAX_WIDTH;
375 sel->r.height = MT9V022_MAX_HEIGHT;
376 return 0;
377 case V4L2_SEL_TGT_CROP:
378 sel->r = mt9v022->rect;
379 return 0;
380 default:
381 return -EINVAL;
382 }
376} 383}
377 384
378static int mt9v022_get_fmt(struct v4l2_subdev *sd, 385static int mt9v022_get_fmt(struct v4l2_subdev *sd,
@@ -400,13 +407,13 @@ static int mt9v022_s_fmt(struct v4l2_subdev *sd,
400{ 407{
401 struct i2c_client *client = v4l2_get_subdevdata(sd); 408 struct i2c_client *client = v4l2_get_subdevdata(sd);
402 struct mt9v022 *mt9v022 = to_mt9v022(client); 409 struct mt9v022 *mt9v022 = to_mt9v022(client);
403 struct v4l2_crop a = { 410 struct v4l2_subdev_selection sel = {
404 .c = { 411 .which = V4L2_SUBDEV_FORMAT_ACTIVE,
405 .left = mt9v022->rect.left, 412 .target = V4L2_SEL_TGT_CROP,
406 .top = mt9v022->rect.top, 413 .r.left = mt9v022->rect.left,
407 .width = mf->width, 414 .r.top = mt9v022->rect.top,
408 .height = mf->height, 415 .r.width = mf->width,
409 }, 416 .r.height = mf->height,
410 }; 417 };
411 int ret; 418 int ret;
412 419
@@ -430,7 +437,7 @@ static int mt9v022_s_fmt(struct v4l2_subdev *sd,
430 } 437 }
431 438
432 /* No support for scaling on this camera, just crop. */ 439 /* No support for scaling on this camera, just crop. */
433 ret = mt9v022_s_crop(sd, &a); 440 ret = mt9v022_set_selection(sd, NULL, &sel);
434 if (!ret) { 441 if (!ret) {
435 mf->width = mt9v022->rect.width; 442 mf->width = mt9v022->rect.width;
436 mf->height = mt9v022->rect.height; 443 mf->height = mt9v022->rect.height;
@@ -853,9 +860,6 @@ static int mt9v022_s_mbus_config(struct v4l2_subdev *sd,
853 860
854static struct v4l2_subdev_video_ops mt9v022_subdev_video_ops = { 861static struct v4l2_subdev_video_ops mt9v022_subdev_video_ops = {
855 .s_stream = mt9v022_s_stream, 862 .s_stream = mt9v022_s_stream,
856 .s_crop = mt9v022_s_crop,
857 .g_crop = mt9v022_g_crop,
858 .cropcap = mt9v022_cropcap,
859 .g_mbus_config = mt9v022_g_mbus_config, 863 .g_mbus_config = mt9v022_g_mbus_config,
860 .s_mbus_config = mt9v022_s_mbus_config, 864 .s_mbus_config = mt9v022_s_mbus_config,
861}; 865};
@@ -866,6 +870,8 @@ static const struct v4l2_subdev_sensor_ops mt9v022_subdev_sensor_ops = {
866 870
867static const struct v4l2_subdev_pad_ops mt9v022_subdev_pad_ops = { 871static const struct v4l2_subdev_pad_ops mt9v022_subdev_pad_ops = {
868 .enum_mbus_code = mt9v022_enum_mbus_code, 872 .enum_mbus_code = mt9v022_enum_mbus_code,
873 .get_selection = mt9v022_get_selection,
874 .set_selection = mt9v022_set_selection,
869 .get_fmt = mt9v022_get_fmt, 875 .get_fmt = mt9v022_get_fmt,
870 .set_fmt = mt9v022_set_fmt, 876 .set_fmt = mt9v022_set_fmt,
871}; 877};
diff --git a/drivers/media/i2c/soc_camera/ov2640.c b/drivers/media/i2c/soc_camera/ov2640.c
index 9b4f5deec748..56de18263359 100644
--- a/drivers/media/i2c/soc_camera/ov2640.c
+++ b/drivers/media/i2c/soc_camera/ov2640.c
@@ -928,29 +928,25 @@ static int ov2640_enum_mbus_code(struct v4l2_subdev *sd,
928 return 0; 928 return 0;
929} 929}
930 930
931static int ov2640_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) 931static int ov2640_get_selection(struct v4l2_subdev *sd,
932{ 932 struct v4l2_subdev_pad_config *cfg,
933 a->c.left = 0; 933 struct v4l2_subdev_selection *sel)
934 a->c.top = 0;
935 a->c.width = UXGA_WIDTH;
936 a->c.height = UXGA_HEIGHT;
937 a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
938
939 return 0;
940}
941
942static int ov2640_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
943{ 934{
944 a->bounds.left = 0; 935 if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE)
945 a->bounds.top = 0; 936 return -EINVAL;
946 a->bounds.width = UXGA_WIDTH;
947 a->bounds.height = UXGA_HEIGHT;
948 a->defrect = a->bounds;
949 a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
950 a->pixelaspect.numerator = 1;
951 a->pixelaspect.denominator = 1;
952 937
953 return 0; 938 switch (sel->target) {
939 case V4L2_SEL_TGT_CROP_BOUNDS:
940 case V4L2_SEL_TGT_CROP_DEFAULT:
941 case V4L2_SEL_TGT_CROP:
942 sel->r.left = 0;
943 sel->r.top = 0;
944 sel->r.width = UXGA_WIDTH;
945 sel->r.height = UXGA_HEIGHT;
946 return 0;
947 default:
948 return -EINVAL;
949 }
954} 950}
955 951
956static int ov2640_video_probe(struct i2c_client *client) 952static int ov2640_video_probe(struct i2c_client *client)
@@ -1024,13 +1020,12 @@ static int ov2640_g_mbus_config(struct v4l2_subdev *sd,
1024 1020
1025static struct v4l2_subdev_video_ops ov2640_subdev_video_ops = { 1021static struct v4l2_subdev_video_ops ov2640_subdev_video_ops = {
1026 .s_stream = ov2640_s_stream, 1022 .s_stream = ov2640_s_stream,
1027 .cropcap = ov2640_cropcap,
1028 .g_crop = ov2640_g_crop,
1029 .g_mbus_config = ov2640_g_mbus_config, 1023 .g_mbus_config = ov2640_g_mbus_config,
1030}; 1024};
1031 1025
1032static const struct v4l2_subdev_pad_ops ov2640_subdev_pad_ops = { 1026static const struct v4l2_subdev_pad_ops ov2640_subdev_pad_ops = {
1033 .enum_mbus_code = ov2640_enum_mbus_code, 1027 .enum_mbus_code = ov2640_enum_mbus_code,
1028 .get_selection = ov2640_get_selection,
1034 .get_fmt = ov2640_get_fmt, 1029 .get_fmt = ov2640_get_fmt,
1035 .set_fmt = ov2640_set_fmt, 1030 .set_fmt = ov2640_set_fmt,
1036}; 1031};
diff --git a/drivers/media/i2c/soc_camera/ov5642.c b/drivers/media/i2c/soc_camera/ov5642.c
index bab9ac0c1764..3d185bd622a3 100644
--- a/drivers/media/i2c/soc_camera/ov5642.c
+++ b/drivers/media/i2c/soc_camera/ov5642.c
@@ -850,13 +850,19 @@ static int ov5642_enum_mbus_code(struct v4l2_subdev *sd,
850 return 0; 850 return 0;
851} 851}
852 852
853static int ov5642_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a) 853static int ov5642_set_selection(struct v4l2_subdev *sd,
854 struct v4l2_subdev_pad_config *cfg,
855 struct v4l2_subdev_selection *sel)
854{ 856{
855 struct i2c_client *client = v4l2_get_subdevdata(sd); 857 struct i2c_client *client = v4l2_get_subdevdata(sd);
856 struct ov5642 *priv = to_ov5642(client); 858 struct ov5642 *priv = to_ov5642(client);
857 struct v4l2_rect rect = a->c; 859 struct v4l2_rect rect = sel->r;
858 int ret; 860 int ret;
859 861
862 if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE ||
863 sel->target != V4L2_SEL_TGT_CROP)
864 return -EINVAL;
865
860 v4l_bound_align_image(&rect.width, 48, OV5642_MAX_WIDTH, 1, 866 v4l_bound_align_image(&rect.width, 48, OV5642_MAX_WIDTH, 1,
861 &rect.height, 32, OV5642_MAX_HEIGHT, 1, 0); 867 &rect.height, 32, OV5642_MAX_HEIGHT, 1, 0);
862 868
@@ -878,32 +884,30 @@ static int ov5642_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a)
878 return ret; 884 return ret;
879} 885}
880 886
881static int ov5642_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) 887static int ov5642_get_selection(struct v4l2_subdev *sd,
888 struct v4l2_subdev_pad_config *cfg,
889 struct v4l2_subdev_selection *sel)
882{ 890{
883 struct i2c_client *client = v4l2_get_subdevdata(sd); 891 struct i2c_client *client = v4l2_get_subdevdata(sd);
884 struct ov5642 *priv = to_ov5642(client); 892 struct ov5642 *priv = to_ov5642(client);
885 struct v4l2_rect *rect = &a->c;
886 893
887 if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) 894 if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE)
888 return -EINVAL; 895 return -EINVAL;
889 896
890 *rect = priv->crop_rect; 897 switch (sel->target) {
891 898 case V4L2_SEL_TGT_CROP_BOUNDS:
892 return 0; 899 case V4L2_SEL_TGT_CROP_DEFAULT:
893} 900 sel->r.left = 0;
894 901 sel->r.top = 0;
895static int ov5642_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) 902 sel->r.width = OV5642_MAX_WIDTH;
896{ 903 sel->r.height = OV5642_MAX_HEIGHT;
897 a->bounds.left = 0; 904 return 0;
898 a->bounds.top = 0; 905 case V4L2_SEL_TGT_CROP:
899 a->bounds.width = OV5642_MAX_WIDTH; 906 sel->r = priv->crop_rect;
900 a->bounds.height = OV5642_MAX_HEIGHT; 907 return 0;
901 a->defrect = a->bounds; 908 default:
902 a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 909 return -EINVAL;
903 a->pixelaspect.numerator = 1; 910 }
904 a->pixelaspect.denominator = 1;
905
906 return 0;
907} 911}
908 912
909static int ov5642_g_mbus_config(struct v4l2_subdev *sd, 913static int ov5642_g_mbus_config(struct v4l2_subdev *sd,
@@ -940,14 +944,13 @@ static int ov5642_s_power(struct v4l2_subdev *sd, int on)
940} 944}
941 945
942static struct v4l2_subdev_video_ops ov5642_subdev_video_ops = { 946static struct v4l2_subdev_video_ops ov5642_subdev_video_ops = {
943 .s_crop = ov5642_s_crop,
944 .g_crop = ov5642_g_crop,
945 .cropcap = ov5642_cropcap,
946 .g_mbus_config = ov5642_g_mbus_config, 947 .g_mbus_config = ov5642_g_mbus_config,
947}; 948};
948 949
949static const struct v4l2_subdev_pad_ops ov5642_subdev_pad_ops = { 950static const struct v4l2_subdev_pad_ops ov5642_subdev_pad_ops = {
950 .enum_mbus_code = ov5642_enum_mbus_code, 951 .enum_mbus_code = ov5642_enum_mbus_code,
952 .get_selection = ov5642_get_selection,
953 .set_selection = ov5642_set_selection,
951 .get_fmt = ov5642_get_fmt, 954 .get_fmt = ov5642_get_fmt,
952 .set_fmt = ov5642_set_fmt, 955 .set_fmt = ov5642_set_fmt,
953}; 956};
diff --git a/drivers/media/i2c/soc_camera/ov6650.c b/drivers/media/i2c/soc_camera/ov6650.c
index 1f8af1ee8352..4bf2995e1cb8 100644
--- a/drivers/media/i2c/soc_camera/ov6650.c
+++ b/drivers/media/i2c/soc_camera/ov6650.c
@@ -432,25 +432,43 @@ static int ov6650_s_power(struct v4l2_subdev *sd, int on)
432 return soc_camera_set_power(&client->dev, ssdd, priv->clk, on); 432 return soc_camera_set_power(&client->dev, ssdd, priv->clk, on);
433} 433}
434 434
435static int ov6650_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) 435static int ov6650_get_selection(struct v4l2_subdev *sd,
436 struct v4l2_subdev_pad_config *cfg,
437 struct v4l2_subdev_selection *sel)
436{ 438{
437 struct i2c_client *client = v4l2_get_subdevdata(sd); 439 struct i2c_client *client = v4l2_get_subdevdata(sd);
438 struct ov6650 *priv = to_ov6650(client); 440 struct ov6650 *priv = to_ov6650(client);
439 441
440 a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 442 if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE)
441 a->c = priv->rect; 443 return -EINVAL;
442 444
443 return 0; 445 switch (sel->target) {
446 case V4L2_SEL_TGT_CROP_BOUNDS:
447 case V4L2_SEL_TGT_CROP_DEFAULT:
448 sel->r.left = DEF_HSTRT << 1;
449 sel->r.top = DEF_VSTRT << 1;
450 sel->r.width = W_CIF;
451 sel->r.height = H_CIF;
452 return 0;
453 case V4L2_SEL_TGT_CROP:
454 sel->r = priv->rect;
455 return 0;
456 default:
457 return -EINVAL;
458 }
444} 459}
445 460
446static int ov6650_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a) 461static int ov6650_set_selection(struct v4l2_subdev *sd,
462 struct v4l2_subdev_pad_config *cfg,
463 struct v4l2_subdev_selection *sel)
447{ 464{
448 struct i2c_client *client = v4l2_get_subdevdata(sd); 465 struct i2c_client *client = v4l2_get_subdevdata(sd);
449 struct ov6650 *priv = to_ov6650(client); 466 struct ov6650 *priv = to_ov6650(client);
450 struct v4l2_rect rect = a->c; 467 struct v4l2_rect rect = sel->r;
451 int ret; 468 int ret;
452 469
453 if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) 470 if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE ||
471 sel->target != V4L2_SEL_TGT_CROP)
454 return -EINVAL; 472 return -EINVAL;
455 473
456 rect.left = ALIGN(rect.left, 2); 474 rect.left = ALIGN(rect.left, 2);
@@ -483,22 +501,6 @@ static int ov6650_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a)
483 return ret; 501 return ret;
484} 502}
485 503
486static int ov6650_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
487{
488 if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
489 return -EINVAL;
490
491 a->bounds.left = DEF_HSTRT << 1;
492 a->bounds.top = DEF_VSTRT << 1;
493 a->bounds.width = W_CIF;
494 a->bounds.height = H_CIF;
495 a->defrect = a->bounds;
496 a->pixelaspect.numerator = 1;
497 a->pixelaspect.denominator = 1;
498
499 return 0;
500}
501
502static int ov6650_get_fmt(struct v4l2_subdev *sd, 504static int ov6650_get_fmt(struct v4l2_subdev *sd,
503 struct v4l2_subdev_pad_config *cfg, 505 struct v4l2_subdev_pad_config *cfg,
504 struct v4l2_subdev_format *format) 506 struct v4l2_subdev_format *format)
@@ -549,16 +551,15 @@ static int ov6650_s_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *mf)
549 struct soc_camera_sense *sense = icd->sense; 551 struct soc_camera_sense *sense = icd->sense;
550 struct ov6650 *priv = to_ov6650(client); 552 struct ov6650 *priv = to_ov6650(client);
551 bool half_scale = !is_unscaled_ok(mf->width, mf->height, &priv->rect); 553 bool half_scale = !is_unscaled_ok(mf->width, mf->height, &priv->rect);
552 struct v4l2_crop a = { 554 struct v4l2_subdev_selection sel = {
553 .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, 555 .which = V4L2_SUBDEV_FORMAT_ACTIVE,
554 .c = { 556 .target = V4L2_SEL_TGT_CROP,
555 .left = priv->rect.left + (priv->rect.width >> 1) - 557 .r.left = priv->rect.left + (priv->rect.width >> 1) -
556 (mf->width >> (1 - half_scale)), 558 (mf->width >> (1 - half_scale)),
557 .top = priv->rect.top + (priv->rect.height >> 1) - 559 .r.top = priv->rect.top + (priv->rect.height >> 1) -
558 (mf->height >> (1 - half_scale)), 560 (mf->height >> (1 - half_scale)),
559 .width = mf->width << half_scale, 561 .r.width = mf->width << half_scale,
560 .height = mf->height << half_scale, 562 .r.height = mf->height << half_scale,
561 },
562 }; 563 };
563 u32 code = mf->code; 564 u32 code = mf->code;
564 unsigned long mclk, pclk; 565 unsigned long mclk, pclk;
@@ -672,7 +673,7 @@ static int ov6650_s_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *mf)
672 dev_dbg(&client->dev, "pixel clock divider: %ld.%ld\n", 673 dev_dbg(&client->dev, "pixel clock divider: %ld.%ld\n",
673 mclk / pclk, 10 * mclk % pclk / pclk); 674 mclk / pclk, 10 * mclk % pclk / pclk);
674 675
675 ret = ov6650_s_crop(sd, &a); 676 ret = ov6650_set_selection(sd, NULL, &sel);
676 if (!ret) 677 if (!ret)
677 ret = ov6650_reg_rmw(client, REG_COMA, coma_set, coma_mask); 678 ret = ov6650_reg_rmw(client, REG_COMA, coma_set, coma_mask);
678 if (!ret) 679 if (!ret)
@@ -943,9 +944,6 @@ static int ov6650_s_mbus_config(struct v4l2_subdev *sd,
943 944
944static struct v4l2_subdev_video_ops ov6650_video_ops = { 945static struct v4l2_subdev_video_ops ov6650_video_ops = {
945 .s_stream = ov6650_s_stream, 946 .s_stream = ov6650_s_stream,
946 .cropcap = ov6650_cropcap,
947 .g_crop = ov6650_g_crop,
948 .s_crop = ov6650_s_crop,
949 .g_parm = ov6650_g_parm, 947 .g_parm = ov6650_g_parm,
950 .s_parm = ov6650_s_parm, 948 .s_parm = ov6650_s_parm,
951 .g_mbus_config = ov6650_g_mbus_config, 949 .g_mbus_config = ov6650_g_mbus_config,
@@ -954,6 +952,8 @@ static struct v4l2_subdev_video_ops ov6650_video_ops = {
954 952
955static const struct v4l2_subdev_pad_ops ov6650_pad_ops = { 953static const struct v4l2_subdev_pad_ops ov6650_pad_ops = {
956 .enum_mbus_code = ov6650_enum_mbus_code, 954 .enum_mbus_code = ov6650_enum_mbus_code,
955 .get_selection = ov6650_get_selection,
956 .set_selection = ov6650_set_selection,
957 .get_fmt = ov6650_get_fmt, 957 .get_fmt = ov6650_get_fmt,
958 .set_fmt = ov6650_set_fmt, 958 .set_fmt = ov6650_set_fmt,
959}; 959};
diff --git a/drivers/media/i2c/soc_camera/ov772x.c b/drivers/media/i2c/soc_camera/ov772x.c
index a43410c1e254..7e68762b3a4b 100644
--- a/drivers/media/i2c/soc_camera/ov772x.c
+++ b/drivers/media/i2c/soc_camera/ov772x.c
@@ -851,29 +851,28 @@ ov772x_set_fmt_error:
851 return ret; 851 return ret;
852} 852}
853 853
854static int ov772x_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) 854static int ov772x_get_selection(struct v4l2_subdev *sd,
855{ 855 struct v4l2_subdev_pad_config *cfg,
856 a->c.left = 0; 856 struct v4l2_subdev_selection *sel)
857 a->c.top = 0;
858 a->c.width = VGA_WIDTH;
859 a->c.height = VGA_HEIGHT;
860 a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
861
862 return 0;
863}
864
865static int ov772x_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
866{ 857{
867 a->bounds.left = 0; 858 if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE)
868 a->bounds.top = 0; 859 return -EINVAL;
869 a->bounds.width = OV772X_MAX_WIDTH;
870 a->bounds.height = OV772X_MAX_HEIGHT;
871 a->defrect = a->bounds;
872 a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
873 a->pixelaspect.numerator = 1;
874 a->pixelaspect.denominator = 1;
875 860
876 return 0; 861 sel->r.left = 0;
862 sel->r.top = 0;
863 switch (sel->target) {
864 case V4L2_SEL_TGT_CROP_BOUNDS:
865 case V4L2_SEL_TGT_CROP_DEFAULT:
866 sel->r.width = OV772X_MAX_WIDTH;
867 sel->r.height = OV772X_MAX_HEIGHT;
868 return 0;
869 case V4L2_SEL_TGT_CROP:
870 sel->r.width = VGA_WIDTH;
871 sel->r.height = VGA_HEIGHT;
872 return 0;
873 default:
874 return -EINVAL;
875 }
877} 876}
878 877
879static int ov772x_get_fmt(struct v4l2_subdev *sd, 878static int ov772x_get_fmt(struct v4l2_subdev *sd,
@@ -1030,13 +1029,12 @@ static int ov772x_g_mbus_config(struct v4l2_subdev *sd,
1030 1029
1031static struct v4l2_subdev_video_ops ov772x_subdev_video_ops = { 1030static struct v4l2_subdev_video_ops ov772x_subdev_video_ops = {
1032 .s_stream = ov772x_s_stream, 1031 .s_stream = ov772x_s_stream,
1033 .cropcap = ov772x_cropcap,
1034 .g_crop = ov772x_g_crop,
1035 .g_mbus_config = ov772x_g_mbus_config, 1032 .g_mbus_config = ov772x_g_mbus_config,
1036}; 1033};
1037 1034
1038static const struct v4l2_subdev_pad_ops ov772x_subdev_pad_ops = { 1035static const struct v4l2_subdev_pad_ops ov772x_subdev_pad_ops = {
1039 .enum_mbus_code = ov772x_enum_mbus_code, 1036 .enum_mbus_code = ov772x_enum_mbus_code,
1037 .get_selection = ov772x_get_selection,
1040 .get_fmt = ov772x_get_fmt, 1038 .get_fmt = ov772x_get_fmt,
1041 .set_fmt = ov772x_set_fmt, 1039 .set_fmt = ov772x_set_fmt,
1042}; 1040};
diff --git a/drivers/media/i2c/soc_camera/ov9640.c b/drivers/media/i2c/soc_camera/ov9640.c
index 8caae1c07541..8c93c57af71c 100644
--- a/drivers/media/i2c/soc_camera/ov9640.c
+++ b/drivers/media/i2c/soc_camera/ov9640.c
@@ -561,29 +561,25 @@ static int ov9640_enum_mbus_code(struct v4l2_subdev *sd,
561 return 0; 561 return 0;
562} 562}
563 563
564static int ov9640_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) 564static int ov9640_get_selection(struct v4l2_subdev *sd,
565{ 565 struct v4l2_subdev_pad_config *cfg,
566 a->c.left = 0; 566 struct v4l2_subdev_selection *sel)
567 a->c.top = 0;
568 a->c.width = W_SXGA;
569 a->c.height = H_SXGA;
570 a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
571
572 return 0;
573}
574
575static int ov9640_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
576{ 567{
577 a->bounds.left = 0; 568 if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE)
578 a->bounds.top = 0; 569 return -EINVAL;
579 a->bounds.width = W_SXGA;
580 a->bounds.height = H_SXGA;
581 a->defrect = a->bounds;
582 a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
583 a->pixelaspect.numerator = 1;
584 a->pixelaspect.denominator = 1;
585 570
586 return 0; 571 sel->r.left = 0;
572 sel->r.top = 0;
573 switch (sel->target) {
574 case V4L2_SEL_TGT_CROP_BOUNDS:
575 case V4L2_SEL_TGT_CROP_DEFAULT:
576 case V4L2_SEL_TGT_CROP:
577 sel->r.width = W_SXGA;
578 sel->r.height = H_SXGA;
579 return 0;
580 default:
581 return -EINVAL;
582 }
587} 583}
588 584
589static int ov9640_video_probe(struct i2c_client *client) 585static int ov9640_video_probe(struct i2c_client *client)
@@ -667,13 +663,12 @@ static int ov9640_g_mbus_config(struct v4l2_subdev *sd,
667 663
668static struct v4l2_subdev_video_ops ov9640_video_ops = { 664static struct v4l2_subdev_video_ops ov9640_video_ops = {
669 .s_stream = ov9640_s_stream, 665 .s_stream = ov9640_s_stream,
670 .cropcap = ov9640_cropcap,
671 .g_crop = ov9640_g_crop,
672 .g_mbus_config = ov9640_g_mbus_config, 666 .g_mbus_config = ov9640_g_mbus_config,
673}; 667};
674 668
675static const struct v4l2_subdev_pad_ops ov9640_pad_ops = { 669static const struct v4l2_subdev_pad_ops ov9640_pad_ops = {
676 .enum_mbus_code = ov9640_enum_mbus_code, 670 .enum_mbus_code = ov9640_enum_mbus_code,
671 .get_selection = ov9640_get_selection,
677 .set_fmt = ov9640_set_fmt, 672 .set_fmt = ov9640_set_fmt,
678}; 673};
679 674
diff --git a/drivers/media/i2c/soc_camera/ov9740.c b/drivers/media/i2c/soc_camera/ov9740.c
index 03a7fc7316ae..0da632d7d33a 100644
--- a/drivers/media/i2c/soc_camera/ov9740.c
+++ b/drivers/media/i2c/soc_camera/ov9740.c
@@ -737,29 +737,25 @@ static int ov9740_enum_mbus_code(struct v4l2_subdev *sd,
737 return 0; 737 return 0;
738} 738}
739 739
740static int ov9740_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) 740static int ov9740_get_selection(struct v4l2_subdev *sd,
741{ 741 struct v4l2_subdev_pad_config *cfg,
742 a->bounds.left = 0; 742 struct v4l2_subdev_selection *sel)
743 a->bounds.top = 0;
744 a->bounds.width = OV9740_MAX_WIDTH;
745 a->bounds.height = OV9740_MAX_HEIGHT;
746 a->defrect = a->bounds;
747 a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
748 a->pixelaspect.numerator = 1;
749 a->pixelaspect.denominator = 1;
750
751 return 0;
752}
753
754static int ov9740_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
755{ 743{
756 a->c.left = 0; 744 if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE)
757 a->c.top = 0; 745 return -EINVAL;
758 a->c.width = OV9740_MAX_WIDTH;
759 a->c.height = OV9740_MAX_HEIGHT;
760 a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
761 746
762 return 0; 747 switch (sel->target) {
748 case V4L2_SEL_TGT_CROP_BOUNDS:
749 case V4L2_SEL_TGT_CROP_DEFAULT:
750 case V4L2_SEL_TGT_CROP:
751 sel->r.left = 0;
752 sel->r.top = 0;
753 sel->r.width = OV9740_MAX_WIDTH;
754 sel->r.height = OV9740_MAX_HEIGHT;
755 return 0;
756 default:
757 return -EINVAL;
758 }
763} 759}
764 760
765/* Set status of additional camera capabilities */ 761/* Set status of additional camera capabilities */
@@ -914,8 +910,6 @@ static int ov9740_g_mbus_config(struct v4l2_subdev *sd,
914 910
915static struct v4l2_subdev_video_ops ov9740_video_ops = { 911static struct v4l2_subdev_video_ops ov9740_video_ops = {
916 .s_stream = ov9740_s_stream, 912 .s_stream = ov9740_s_stream,
917 .cropcap = ov9740_cropcap,
918 .g_crop = ov9740_g_crop,
919 .g_mbus_config = ov9740_g_mbus_config, 913 .g_mbus_config = ov9740_g_mbus_config,
920}; 914};
921 915
@@ -929,6 +923,7 @@ static struct v4l2_subdev_core_ops ov9740_core_ops = {
929 923
930static const struct v4l2_subdev_pad_ops ov9740_pad_ops = { 924static const struct v4l2_subdev_pad_ops ov9740_pad_ops = {
931 .enum_mbus_code = ov9740_enum_mbus_code, 925 .enum_mbus_code = ov9740_enum_mbus_code,
926 .get_selection = ov9740_get_selection,
932 .set_fmt = ov9740_set_fmt, 927 .set_fmt = ov9740_set_fmt,
933}; 928};
934 929
diff --git a/drivers/media/i2c/soc_camera/rj54n1cb0c.c b/drivers/media/i2c/soc_camera/rj54n1cb0c.c
index aa7bfbb4ad71..bc8ec59a3fbd 100644
--- a/drivers/media/i2c/soc_camera/rj54n1cb0c.c
+++ b/drivers/media/i2c/soc_camera/rj54n1cb0c.c
@@ -538,15 +538,21 @@ static int rj54n1_commit(struct i2c_client *client)
538static int rj54n1_sensor_scale(struct v4l2_subdev *sd, s32 *in_w, s32 *in_h, 538static int rj54n1_sensor_scale(struct v4l2_subdev *sd, s32 *in_w, s32 *in_h,
539 s32 *out_w, s32 *out_h); 539 s32 *out_w, s32 *out_h);
540 540
541static int rj54n1_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a) 541static int rj54n1_set_selection(struct v4l2_subdev *sd,
542 struct v4l2_subdev_pad_config *cfg,
543 struct v4l2_subdev_selection *sel)
542{ 544{
543 struct i2c_client *client = v4l2_get_subdevdata(sd); 545 struct i2c_client *client = v4l2_get_subdevdata(sd);
544 struct rj54n1 *rj54n1 = to_rj54n1(client); 546 struct rj54n1 *rj54n1 = to_rj54n1(client);
545 const struct v4l2_rect *rect = &a->c; 547 const struct v4l2_rect *rect = &sel->r;
546 int dummy = 0, output_w, output_h, 548 int dummy = 0, output_w, output_h,
547 input_w = rect->width, input_h = rect->height; 549 input_w = rect->width, input_h = rect->height;
548 int ret; 550 int ret;
549 551
552 if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE ||
553 sel->target != V4L2_SEL_TGT_CROP)
554 return -EINVAL;
555
550 /* arbitrary minimum width and height, edges unimportant */ 556 /* arbitrary minimum width and height, edges unimportant */
551 soc_camera_limit_side(&dummy, &input_w, 557 soc_camera_limit_side(&dummy, &input_w,
552 RJ54N1_COLUMN_SKIP, 8, RJ54N1_MAX_WIDTH); 558 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)
573 return 0; 579 return 0;
574} 580}
575 581
576static int rj54n1_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) 582static int rj54n1_get_selection(struct v4l2_subdev *sd,
583 struct v4l2_subdev_pad_config *cfg,
584 struct v4l2_subdev_selection *sel)
577{ 585{
578 struct i2c_client *client = v4l2_get_subdevdata(sd); 586 struct i2c_client *client = v4l2_get_subdevdata(sd);
579 struct rj54n1 *rj54n1 = to_rj54n1(client); 587 struct rj54n1 *rj54n1 = to_rj54n1(client);
580 588
581 a->c = rj54n1->rect; 589 if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE)
582 a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 590 return -EINVAL;
583
584 return 0;
585}
586
587static int rj54n1_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
588{
589 a->bounds.left = RJ54N1_COLUMN_SKIP;
590 a->bounds.top = RJ54N1_ROW_SKIP;
591 a->bounds.width = RJ54N1_MAX_WIDTH;
592 a->bounds.height = RJ54N1_MAX_HEIGHT;
593 a->defrect = a->bounds;
594 a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
595 a->pixelaspect.numerator = 1;
596 a->pixelaspect.denominator = 1;
597 591
598 return 0; 592 switch (sel->target) {
593 case V4L2_SEL_TGT_CROP_BOUNDS:
594 case V4L2_SEL_TGT_CROP_DEFAULT:
595 sel->r.left = RJ54N1_COLUMN_SKIP;
596 sel->r.top = RJ54N1_ROW_SKIP;
597 sel->r.width = RJ54N1_MAX_WIDTH;
598 sel->r.height = RJ54N1_MAX_HEIGHT;
599 return 0;
600 case V4L2_SEL_TGT_CROP:
601 sel->r = rj54n1->rect;
602 return 0;
603 default:
604 return -EINVAL;
605 }
599} 606}
600 607
601static int rj54n1_get_fmt(struct v4l2_subdev *sd, 608static int rj54n1_get_fmt(struct v4l2_subdev *sd,
@@ -1246,15 +1253,14 @@ static int rj54n1_s_mbus_config(struct v4l2_subdev *sd,
1246 1253
1247static struct v4l2_subdev_video_ops rj54n1_subdev_video_ops = { 1254static struct v4l2_subdev_video_ops rj54n1_subdev_video_ops = {
1248 .s_stream = rj54n1_s_stream, 1255 .s_stream = rj54n1_s_stream,
1249 .g_crop = rj54n1_g_crop,
1250 .s_crop = rj54n1_s_crop,
1251 .cropcap = rj54n1_cropcap,
1252 .g_mbus_config = rj54n1_g_mbus_config, 1256 .g_mbus_config = rj54n1_g_mbus_config,
1253 .s_mbus_config = rj54n1_s_mbus_config, 1257 .s_mbus_config = rj54n1_s_mbus_config,
1254}; 1258};
1255 1259
1256static const struct v4l2_subdev_pad_ops rj54n1_subdev_pad_ops = { 1260static const struct v4l2_subdev_pad_ops rj54n1_subdev_pad_ops = {
1257 .enum_mbus_code = rj54n1_enum_mbus_code, 1261 .enum_mbus_code = rj54n1_enum_mbus_code,
1262 .get_selection = rj54n1_get_selection,
1263 .set_selection = rj54n1_set_selection,
1258 .get_fmt = rj54n1_get_fmt, 1264 .get_fmt = rj54n1_get_fmt,
1259 .set_fmt = rj54n1_set_fmt, 1265 .set_fmt = rj54n1_set_fmt,
1260}; 1266};
diff --git a/drivers/media/i2c/soc_camera/tw9910.c b/drivers/media/i2c/soc_camera/tw9910.c
index 06aff81787a7..4002c07f3857 100644
--- a/drivers/media/i2c/soc_camera/tw9910.c
+++ b/drivers/media/i2c/soc_camera/tw9910.c
@@ -676,44 +676,28 @@ tw9910_set_fmt_error:
676 return ret; 676 return ret;
677} 677}
678 678
679static int tw9910_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) 679static int tw9910_get_selection(struct v4l2_subdev *sd,
680 struct v4l2_subdev_pad_config *cfg,
681 struct v4l2_subdev_selection *sel)
680{ 682{
681 struct i2c_client *client = v4l2_get_subdevdata(sd); 683 struct i2c_client *client = v4l2_get_subdevdata(sd);
682 struct tw9910_priv *priv = to_tw9910(client); 684 struct tw9910_priv *priv = to_tw9910(client);
683 685
684 a->c.left = 0; 686 if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE)
685 a->c.top = 0; 687 return -EINVAL;
686 if (priv->norm & V4L2_STD_NTSC) { 688 /* Only CROP, CROP_DEFAULT and CROP_BOUNDS are supported */
687 a->c.width = 640; 689 if (sel->target > V4L2_SEL_TGT_CROP_BOUNDS)
688 a->c.height = 480; 690 return -EINVAL;
689 } else {
690 a->c.width = 768;
691 a->c.height = 576;
692 }
693 a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
694
695 return 0;
696}
697
698static int tw9910_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
699{
700 struct i2c_client *client = v4l2_get_subdevdata(sd);
701 struct tw9910_priv *priv = to_tw9910(client);
702 691
703 a->bounds.left = 0; 692 sel->r.left = 0;
704 a->bounds.top = 0; 693 sel->r.top = 0;
705 if (priv->norm & V4L2_STD_NTSC) { 694 if (priv->norm & V4L2_STD_NTSC) {
706 a->bounds.width = 640; 695 sel->r.width = 640;
707 a->bounds.height = 480; 696 sel->r.height = 480;
708 } else { 697 } else {
709 a->bounds.width = 768; 698 sel->r.width = 768;
710 a->bounds.height = 576; 699 sel->r.height = 576;
711 } 700 }
712 a->defrect = a->bounds;
713 a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
714 a->pixelaspect.numerator = 1;
715 a->pixelaspect.denominator = 1;
716
717 return 0; 701 return 0;
718} 702}
719 703
@@ -921,8 +905,6 @@ static struct v4l2_subdev_video_ops tw9910_subdev_video_ops = {
921 .s_std = tw9910_s_std, 905 .s_std = tw9910_s_std,
922 .g_std = tw9910_g_std, 906 .g_std = tw9910_g_std,
923 .s_stream = tw9910_s_stream, 907 .s_stream = tw9910_s_stream,
924 .cropcap = tw9910_cropcap,
925 .g_crop = tw9910_g_crop,
926 .g_mbus_config = tw9910_g_mbus_config, 908 .g_mbus_config = tw9910_g_mbus_config,
927 .s_mbus_config = tw9910_s_mbus_config, 909 .s_mbus_config = tw9910_s_mbus_config,
928 .g_tvnorms = tw9910_g_tvnorms, 910 .g_tvnorms = tw9910_g_tvnorms,
@@ -930,6 +912,7 @@ static struct v4l2_subdev_video_ops tw9910_subdev_video_ops = {
930 912
931static const struct v4l2_subdev_pad_ops tw9910_subdev_pad_ops = { 913static const struct v4l2_subdev_pad_ops tw9910_subdev_pad_ops = {
932 .enum_mbus_code = tw9910_enum_mbus_code, 914 .enum_mbus_code = tw9910_enum_mbus_code,
915 .get_selection = tw9910_get_selection,
933 .get_fmt = tw9910_get_fmt, 916 .get_fmt = tw9910_get_fmt,
934 .set_fmt = tw9910_set_fmt, 917 .set_fmt = tw9910_set_fmt,
935}; 918};
diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
index 0b6d46c453bf..b7648fda519c 100644
--- a/drivers/media/i2c/tvp5150.c
+++ b/drivers/media/i2c/tvp5150.c
@@ -871,19 +871,22 @@ static int tvp5150_fill_fmt(struct v4l2_subdev *sd,
871 return 0; 871 return 0;
872} 872}
873 873
874static int tvp5150_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a) 874static int tvp5150_set_selection(struct v4l2_subdev *sd,
875 struct v4l2_subdev_pad_config *cfg,
876 struct v4l2_subdev_selection *sel)
875{ 877{
876 struct v4l2_rect rect = a->c;
877 struct tvp5150 *decoder = to_tvp5150(sd); 878 struct tvp5150 *decoder = to_tvp5150(sd);
879 struct v4l2_rect rect = sel->r;
878 v4l2_std_id std; 880 v4l2_std_id std;
879 unsigned int hmax; 881 int hmax;
882
883 if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE ||
884 sel->target != V4L2_SEL_TGT_CROP)
885 return -EINVAL;
880 886
881 v4l2_dbg(1, debug, sd, "%s left=%d, top=%d, width=%d, height=%d\n", 887 v4l2_dbg(1, debug, sd, "%s left=%d, top=%d, width=%d, height=%d\n",
882 __func__, rect.left, rect.top, rect.width, rect.height); 888 __func__, rect.left, rect.top, rect.width, rect.height);
883 889
884 if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
885 return -EINVAL;
886
887 /* tvp5150 has some special limits */ 890 /* tvp5150 has some special limits */
888 rect.left = clamp(rect.left, 0, TVP5150_MAX_CROP_LEFT); 891 rect.left = clamp(rect.left, 0, TVP5150_MAX_CROP_LEFT);
889 rect.width = clamp_t(unsigned int, rect.width, 892 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)
924 return 0; 927 return 0;
925} 928}
926 929
927static int tvp5150_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) 930static int tvp5150_get_selection(struct v4l2_subdev *sd,
931 struct v4l2_subdev_pad_config *cfg,
932 struct v4l2_subdev_selection *sel)
928{ 933{
929 struct tvp5150 *decoder = to_tvp5150(sd); 934 struct tvp5150 *decoder = container_of(sd, struct tvp5150, sd);
930
931 a->c = decoder->rect;
932 a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
933
934 return 0;
935}
936
937static int tvp5150_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
938{
939 struct tvp5150 *decoder = to_tvp5150(sd);
940 v4l2_std_id std; 935 v4l2_std_id std;
941 936
942 if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) 937 if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE)
943 return -EINVAL; 938 return -EINVAL;
944 939
945 a->bounds.left = 0; 940 switch (sel->target) {
946 a->bounds.top = 0; 941 case V4L2_SEL_TGT_CROP_BOUNDS:
947 a->bounds.width = TVP5150_H_MAX; 942 case V4L2_SEL_TGT_CROP_DEFAULT:
948 943 sel->r.left = 0;
949 /* Calculate height based on current standard */ 944 sel->r.top = 0;
950 if (decoder->norm == V4L2_STD_ALL) 945 sel->r.width = TVP5150_H_MAX;
951 std = tvp5150_read_std(sd); 946
952 else 947 /* Calculate height based on current standard */
953 std = decoder->norm; 948 if (decoder->norm == V4L2_STD_ALL)
954 949 std = tvp5150_read_std(sd);
955 if (std & V4L2_STD_525_60) 950 else
956 a->bounds.height = TVP5150_V_MAX_525_60; 951 std = decoder->norm;
957 else 952 if (std & V4L2_STD_525_60)
958 a->bounds.height = TVP5150_V_MAX_OTHERS; 953 sel->r.height = TVP5150_V_MAX_525_60;
959 954 else
960 a->defrect = a->bounds; 955 sel->r.height = TVP5150_V_MAX_OTHERS;
961 a->pixelaspect.numerator = 1; 956 return 0;
962 a->pixelaspect.denominator = 1; 957 case V4L2_SEL_TGT_CROP:
963 958 sel->r = decoder->rect;
964 return 0; 959 return 0;
960 default:
961 return -EINVAL;
962 }
965} 963}
966 964
967static int tvp5150_g_mbus_config(struct v4l2_subdev *sd, 965static int tvp5150_g_mbus_config(struct v4l2_subdev *sd,
@@ -1233,9 +1231,6 @@ static const struct v4l2_subdev_video_ops tvp5150_video_ops = {
1233 .s_std = tvp5150_s_std, 1231 .s_std = tvp5150_s_std,
1234 .s_stream = tvp5150_s_stream, 1232 .s_stream = tvp5150_s_stream,
1235 .s_routing = tvp5150_s_routing, 1233 .s_routing = tvp5150_s_routing,
1236 .s_crop = tvp5150_s_crop,
1237 .g_crop = tvp5150_g_crop,
1238 .cropcap = tvp5150_cropcap,
1239 .g_mbus_config = tvp5150_g_mbus_config, 1234 .g_mbus_config = tvp5150_g_mbus_config,
1240}; 1235};
1241 1236
@@ -1251,6 +1246,8 @@ static const struct v4l2_subdev_pad_ops tvp5150_pad_ops = {
1251 .enum_frame_size = tvp5150_enum_frame_size, 1246 .enum_frame_size = tvp5150_enum_frame_size,
1252 .set_fmt = tvp5150_fill_fmt, 1247 .set_fmt = tvp5150_fill_fmt,
1253 .get_fmt = tvp5150_fill_fmt, 1248 .get_fmt = tvp5150_fill_fmt,
1249 .get_selection = tvp5150_get_selection,
1250 .set_selection = tvp5150_set_selection,
1254}; 1251};
1255 1252
1256static const struct v4l2_subdev_ops tvp5150_ops = { 1253static const struct v4l2_subdev_ops tvp5150_ops = {
diff --git a/drivers/media/platform/omap3isp/ispvideo.c b/drivers/media/platform/omap3isp/ispvideo.c
index 7d9f35976d18..7354469670b7 100644
--- a/drivers/media/platform/omap3isp/ispvideo.c
+++ b/drivers/media/platform/omap3isp/ispvideo.c
@@ -772,40 +772,45 @@ isp_video_try_format(struct file *file, void *fh, struct v4l2_format *format)
772} 772}
773 773
774static int 774static int
775isp_video_cropcap(struct file *file, void *fh, struct v4l2_cropcap *cropcap) 775isp_video_get_selection(struct file *file, void *fh, struct v4l2_selection *sel)
776{
777 struct isp_video *video = video_drvdata(file);
778 struct v4l2_subdev *subdev;
779 int ret;
780
781 subdev = isp_video_remote_subdev(video, NULL);
782 if (subdev == NULL)
783 return -EINVAL;
784
785 mutex_lock(&video->mutex);
786 ret = v4l2_subdev_call(subdev, video, cropcap, cropcap);
787 mutex_unlock(&video->mutex);
788
789 return ret == -ENOIOCTLCMD ? -ENOTTY : ret;
790}
791
792static int
793isp_video_get_crop(struct file *file, void *fh, struct v4l2_crop *crop)
794{ 776{
795 struct isp_video *video = video_drvdata(file); 777 struct isp_video *video = video_drvdata(file);
796 struct v4l2_subdev_format format; 778 struct v4l2_subdev_format format;
797 struct v4l2_subdev *subdev; 779 struct v4l2_subdev *subdev;
780 struct v4l2_subdev_selection sdsel = {
781 .which = V4L2_SUBDEV_FORMAT_ACTIVE,
782 .target = sel->target,
783 };
798 u32 pad; 784 u32 pad;
799 int ret; 785 int ret;
800 786
787 switch (sel->target) {
788 case V4L2_SEL_TGT_CROP:
789 case V4L2_SEL_TGT_CROP_BOUNDS:
790 case V4L2_SEL_TGT_CROP_DEFAULT:
791 if (video->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
792 return -EINVAL;
793 break;
794 case V4L2_SEL_TGT_COMPOSE:
795 case V4L2_SEL_TGT_COMPOSE_BOUNDS:
796 case V4L2_SEL_TGT_COMPOSE_DEFAULT:
797 if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
798 return -EINVAL;
799 break;
800 default:
801 return -EINVAL;
802 }
801 subdev = isp_video_remote_subdev(video, &pad); 803 subdev = isp_video_remote_subdev(video, &pad);
802 if (subdev == NULL) 804 if (subdev == NULL)
803 return -EINVAL; 805 return -EINVAL;
804 806
805 /* Try the get crop operation first and fallback to get format if not 807 /* Try the get selection operation first and fallback to get format if not
806 * implemented. 808 * implemented.
807 */ 809 */
808 ret = v4l2_subdev_call(subdev, video, g_crop, crop); 810 sdsel.pad = pad;
811 ret = v4l2_subdev_call(subdev, pad, get_selection, NULL, &sdsel);
812 if (!ret)
813 sel->r = sdsel.r;
809 if (ret != -ENOIOCTLCMD) 814 if (ret != -ENOIOCTLCMD)
810 return ret; 815 return ret;
811 816
@@ -815,28 +820,50 @@ isp_video_get_crop(struct file *file, void *fh, struct v4l2_crop *crop)
815 if (ret < 0) 820 if (ret < 0)
816 return ret == -ENOIOCTLCMD ? -ENOTTY : ret; 821 return ret == -ENOIOCTLCMD ? -ENOTTY : ret;
817 822
818 crop->c.left = 0; 823 sel->r.left = 0;
819 crop->c.top = 0; 824 sel->r.top = 0;
820 crop->c.width = format.format.width; 825 sel->r.width = format.format.width;
821 crop->c.height = format.format.height; 826 sel->r.height = format.format.height;
822 827
823 return 0; 828 return 0;
824} 829}
825 830
826static int 831static int
827isp_video_set_crop(struct file *file, void *fh, const struct v4l2_crop *crop) 832isp_video_set_selection(struct file *file, void *fh, struct v4l2_selection *sel)
828{ 833{
829 struct isp_video *video = video_drvdata(file); 834 struct isp_video *video = video_drvdata(file);
830 struct v4l2_subdev *subdev; 835 struct v4l2_subdev *subdev;
836 struct v4l2_subdev_selection sdsel = {
837 .which = V4L2_SUBDEV_FORMAT_ACTIVE,
838 .target = sel->target,
839 .flags = sel->flags,
840 .r = sel->r,
841 };
842 u32 pad;
831 int ret; 843 int ret;
832 844
833 subdev = isp_video_remote_subdev(video, NULL); 845 switch (sel->target) {
846 case V4L2_SEL_TGT_CROP:
847 if (video->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
848 return -EINVAL;
849 break;
850 case V4L2_SEL_TGT_COMPOSE:
851 if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
852 return -EINVAL;
853 break;
854 default:
855 return -EINVAL;
856 }
857 subdev = isp_video_remote_subdev(video, &pad);
834 if (subdev == NULL) 858 if (subdev == NULL)
835 return -EINVAL; 859 return -EINVAL;
836 860
861 sdsel.pad = pad;
837 mutex_lock(&video->mutex); 862 mutex_lock(&video->mutex);
838 ret = v4l2_subdev_call(subdev, video, s_crop, crop); 863 ret = v4l2_subdev_call(subdev, pad, set_selection, NULL, &sdsel);
839 mutex_unlock(&video->mutex); 864 mutex_unlock(&video->mutex);
865 if (!ret)
866 sel->r = sdsel.r;
840 867
841 return ret == -ENOIOCTLCMD ? -ENOTTY : ret; 868 return ret == -ENOIOCTLCMD ? -ENOTTY : ret;
842} 869}
@@ -1252,9 +1279,8 @@ static const struct v4l2_ioctl_ops isp_video_ioctl_ops = {
1252 .vidioc_g_fmt_vid_out = isp_video_get_format, 1279 .vidioc_g_fmt_vid_out = isp_video_get_format,
1253 .vidioc_s_fmt_vid_out = isp_video_set_format, 1280 .vidioc_s_fmt_vid_out = isp_video_set_format,
1254 .vidioc_try_fmt_vid_out = isp_video_try_format, 1281 .vidioc_try_fmt_vid_out = isp_video_try_format,
1255 .vidioc_cropcap = isp_video_cropcap, 1282 .vidioc_g_selection = isp_video_get_selection,
1256 .vidioc_g_crop = isp_video_get_crop, 1283 .vidioc_s_selection = isp_video_set_selection,
1257 .vidioc_s_crop = isp_video_set_crop,
1258 .vidioc_g_parm = isp_video_get_param, 1284 .vidioc_g_parm = isp_video_get_param,
1259 .vidioc_s_parm = isp_video_set_param, 1285 .vidioc_s_parm = isp_video_set_param,
1260 .vidioc_reqbufs = isp_video_reqbufs, 1286 .vidioc_reqbufs = isp_video_reqbufs,
diff --git a/drivers/media/platform/sh_vou.c b/drivers/media/platform/sh_vou.c
index e1f39b4cf1cd..4ee7b1570f62 100644
--- a/drivers/media/platform/sh_vou.c
+++ b/drivers/media/platform/sh_vou.c
@@ -937,7 +937,10 @@ static int sh_vou_s_selection(struct file *file, void *fh,
937{ 937{
938 struct v4l2_rect *rect = &sel->r; 938 struct v4l2_rect *rect = &sel->r;
939 struct sh_vou_device *vou_dev = video_drvdata(file); 939 struct sh_vou_device *vou_dev = video_drvdata(file);
940 struct v4l2_crop sd_crop = {.type = V4L2_BUF_TYPE_VIDEO_OUTPUT}; 940 struct v4l2_subdev_selection sd_sel = {
941 .which = V4L2_SUBDEV_FORMAT_ACTIVE,
942 .target = V4L2_SEL_TGT_COMPOSE,
943 };
941 struct v4l2_pix_format *pix = &vou_dev->pix; 944 struct v4l2_pix_format *pix = &vou_dev->pix;
942 struct sh_vou_geometry geo; 945 struct sh_vou_geometry geo;
943 struct v4l2_subdev_format format = { 946 struct v4l2_subdev_format format = {
@@ -978,14 +981,14 @@ static int sh_vou_s_selection(struct file *file, void *fh,
978 geo.in_height = pix->height; 981 geo.in_height = pix->height;
979 982
980 /* Configure the encoder one-to-one, position at 0, ignore errors */ 983 /* Configure the encoder one-to-one, position at 0, ignore errors */
981 sd_crop.c.width = geo.output.width; 984 sd_sel.r.width = geo.output.width;
982 sd_crop.c.height = geo.output.height; 985 sd_sel.r.height = geo.output.height;
983 /* 986 /*
984 * We first issue a S_CROP, so that the subsequent S_FMT delivers the 987 * We first issue a S_SELECTION, so that the subsequent S_FMT delivers the
985 * final encoder configuration. 988 * final encoder configuration.
986 */ 989 */
987 v4l2_device_call_until_err(&vou_dev->v4l2_dev, 0, video, 990 v4l2_device_call_until_err(&vou_dev->v4l2_dev, 0, pad,
988 s_crop, &sd_crop); 991 set_selection, NULL, &sd_sel);
989 format.format.width = geo.output.width; 992 format.format.width = geo.output.width;
990 format.format.height = geo.output.height; 993 format.format.height = geo.output.height;
991 ret = v4l2_device_call_until_err(&vou_dev->v4l2_dev, 0, pad, 994 ret = v4l2_device_call_until_err(&vou_dev->v4l2_dev, 0, pad,
diff --git a/drivers/media/platform/soc_camera/pxa_camera.c b/drivers/media/platform/soc_camera/pxa_camera.c
index 2aaf4a8f71a0..ebbe514d64e2 100644
--- a/drivers/media/platform/soc_camera/pxa_camera.c
+++ b/drivers/media/platform/soc_camera/pxa_camera.c
@@ -1280,10 +1280,10 @@ static int pxa_camera_check_frame(u32 width, u32 height)
1280 (width & 0x01); 1280 (width & 0x01);
1281} 1281}
1282 1282
1283static int pxa_camera_set_crop(struct soc_camera_device *icd, 1283static int pxa_camera_set_selection(struct soc_camera_device *icd,
1284 const struct v4l2_crop *a) 1284 struct v4l2_selection *sel)
1285{ 1285{
1286 const struct v4l2_rect *rect = &a->c; 1286 const struct v4l2_rect *rect = &sel->r;
1287 struct device *dev = icd->parent; 1287 struct device *dev = icd->parent;
1288 struct soc_camera_host *ici = to_soc_camera_host(dev); 1288 struct soc_camera_host *ici = to_soc_camera_host(dev);
1289 struct pxa_camera_dev *pcdev = ici->priv; 1289 struct pxa_camera_dev *pcdev = ici->priv;
@@ -1298,13 +1298,19 @@ static int pxa_camera_set_crop(struct soc_camera_device *icd,
1298 struct v4l2_mbus_framefmt *mf = &fmt.format; 1298 struct v4l2_mbus_framefmt *mf = &fmt.format;
1299 struct pxa_cam *cam = icd->host_priv; 1299 struct pxa_cam *cam = icd->host_priv;
1300 u32 fourcc = icd->current_fmt->host_fmt->fourcc; 1300 u32 fourcc = icd->current_fmt->host_fmt->fourcc;
1301 struct v4l2_subdev_selection sdsel = {
1302 .which = V4L2_SUBDEV_FORMAT_ACTIVE,
1303 .target = sel->target,
1304 .flags = sel->flags,
1305 .r = sel->r,
1306 };
1301 int ret; 1307 int ret;
1302 1308
1303 /* If PCLK is used to latch data from the sensor, check sense */ 1309 /* If PCLK is used to latch data from the sensor, check sense */
1304 if (pcdev->platform_flags & PXA_CAMERA_PCLK_EN) 1310 if (pcdev->platform_flags & PXA_CAMERA_PCLK_EN)
1305 icd->sense = &sense; 1311 icd->sense = &sense;
1306 1312
1307 ret = v4l2_subdev_call(sd, video, s_crop, a); 1313 ret = v4l2_subdev_call(sd, pad, set_selection, NULL, &sdsel);
1308 1314
1309 icd->sense = NULL; 1315 icd->sense = NULL;
1310 1316
@@ -1313,6 +1319,7 @@ static int pxa_camera_set_crop(struct soc_camera_device *icd,
1313 rect->width, rect->height, rect->left, rect->top); 1319 rect->width, rect->height, rect->left, rect->top);
1314 return ret; 1320 return ret;
1315 } 1321 }
1322 sel->r = sdsel.r;
1316 1323
1317 ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, &fmt); 1324 ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, &fmt);
1318 if (ret < 0) 1325 if (ret < 0)
@@ -1592,7 +1599,7 @@ static struct soc_camera_host_ops pxa_soc_camera_host_ops = {
1592 .remove = pxa_camera_remove_device, 1599 .remove = pxa_camera_remove_device,
1593 .clock_start = pxa_camera_clock_start, 1600 .clock_start = pxa_camera_clock_start,
1594 .clock_stop = pxa_camera_clock_stop, 1601 .clock_stop = pxa_camera_clock_stop,
1595 .set_crop = pxa_camera_set_crop, 1602 .set_selection = pxa_camera_set_selection,
1596 .get_formats = pxa_camera_get_formats, 1603 .get_formats = pxa_camera_get_formats,
1597 .put_formats = pxa_camera_put_formats, 1604 .put_formats = pxa_camera_put_formats,
1598 .set_fmt = pxa_camera_set_fmt, 1605 .set_fmt = pxa_camera_set_fmt,
diff --git a/drivers/media/platform/soc_camera/rcar_vin.c b/drivers/media/platform/soc_camera/rcar_vin.c
index 9c137522c660..077f12d1575f 100644
--- a/drivers/media/platform/soc_camera/rcar_vin.c
+++ b/drivers/media/platform/soc_camera/rcar_vin.c
@@ -515,7 +515,7 @@ struct rcar_vin_cam {
515 unsigned int out_width; 515 unsigned int out_width;
516 unsigned int out_height; 516 unsigned int out_height;
517 /* 517 /*
518 * User window from S_CROP / G_CROP, produced by client cropping and 518 * User window from S_SELECTION / G_SELECTION, produced by client cropping and
519 * scaling, VIN scaling and VIN cropping, mapped back onto the client 519 * scaling, VIN scaling and VIN cropping, mapped back onto the client
520 * input window 520 * input window
521 */ 521 */
@@ -1471,16 +1471,15 @@ static void rcar_vin_put_formats(struct soc_camera_device *icd)
1471 icd->host_priv = NULL; 1471 icd->host_priv = NULL;
1472} 1472}
1473 1473
1474static int rcar_vin_set_crop(struct soc_camera_device *icd, 1474static int rcar_vin_set_selection(struct soc_camera_device *icd,
1475 const struct v4l2_crop *a) 1475 struct v4l2_selection *sel)
1476{ 1476{
1477 struct v4l2_crop a_writable = *a; 1477 const struct v4l2_rect *rect = &sel->r;
1478 const struct v4l2_rect *rect = &a_writable.c;
1479 struct soc_camera_host *ici = to_soc_camera_host(icd->parent); 1478 struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
1480 struct rcar_vin_priv *priv = ici->priv; 1479 struct rcar_vin_priv *priv = ici->priv;
1481 struct v4l2_crop cam_crop; 1480 struct v4l2_selection cam_sel;
1482 struct rcar_vin_cam *cam = icd->host_priv; 1481 struct rcar_vin_cam *cam = icd->host_priv;
1483 struct v4l2_rect *cam_rect = &cam_crop.c; 1482 struct v4l2_rect *cam_rect = &cam_sel.r;
1484 struct v4l2_subdev *sd = soc_camera_to_subdev(icd); 1483 struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
1485 struct device *dev = icd->parent; 1484 struct device *dev = icd->parent;
1486 struct v4l2_subdev_format fmt = { 1485 struct v4l2_subdev_format fmt = {
@@ -1490,15 +1489,15 @@ static int rcar_vin_set_crop(struct soc_camera_device *icd,
1490 u32 vnmc; 1489 u32 vnmc;
1491 int ret, i; 1490 int ret, i;
1492 1491
1493 dev_dbg(dev, "S_CROP(%ux%u@%u:%u)\n", rect->width, rect->height, 1492 dev_dbg(dev, "S_SELECTION(%ux%u@%u:%u)\n", rect->width, rect->height,
1494 rect->left, rect->top); 1493 rect->left, rect->top);
1495 1494
1496 /* During camera cropping its output window can change too, stop VIN */ 1495 /* During camera cropping its output window can change too, stop VIN */
1497 capture_stop_preserve(priv, &vnmc); 1496 capture_stop_preserve(priv, &vnmc);
1498 dev_dbg(dev, "VNMC_REG 0x%x\n", vnmc); 1497 dev_dbg(dev, "VNMC_REG 0x%x\n", vnmc);
1499 1498
1500 /* Apply iterative camera S_CROP for new input window. */ 1499 /* Apply iterative camera S_SELECTION for new input window. */
1501 ret = soc_camera_client_s_crop(sd, &a_writable, &cam_crop, 1500 ret = soc_camera_client_s_selection(sd, sel, &cam_sel,
1502 &cam->rect, &cam->subrect); 1501 &cam->rect, &cam->subrect);
1503 if (ret < 0) 1502 if (ret < 0)
1504 return ret; 1503 return ret;
@@ -1551,13 +1550,12 @@ static int rcar_vin_set_crop(struct soc_camera_device *icd,
1551 return ret; 1550 return ret;
1552} 1551}
1553 1552
1554static int rcar_vin_get_crop(struct soc_camera_device *icd, 1553static int rcar_vin_get_selection(struct soc_camera_device *icd,
1555 struct v4l2_crop *a) 1554 struct v4l2_selection *sel)
1556{ 1555{
1557 struct rcar_vin_cam *cam = icd->host_priv; 1556 struct rcar_vin_cam *cam = icd->host_priv;
1558 1557
1559 a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 1558 sel->r = cam->subrect;
1560 a->c = cam->subrect;
1561 1559
1562 return 0; 1560 return 0;
1563} 1561}
@@ -1824,8 +1822,8 @@ static struct soc_camera_host_ops rcar_vin_host_ops = {
1824 .remove = rcar_vin_remove_device, 1822 .remove = rcar_vin_remove_device,
1825 .get_formats = rcar_vin_get_formats, 1823 .get_formats = rcar_vin_get_formats,
1826 .put_formats = rcar_vin_put_formats, 1824 .put_formats = rcar_vin_put_formats,
1827 .get_crop = rcar_vin_get_crop, 1825 .get_selection = rcar_vin_get_selection,
1828 .set_crop = rcar_vin_set_crop, 1826 .set_selection = rcar_vin_set_selection,
1829 .try_fmt = rcar_vin_try_fmt, 1827 .try_fmt = rcar_vin_try_fmt,
1830 .set_fmt = rcar_vin_set_fmt, 1828 .set_fmt = rcar_vin_set_fmt,
1831 .poll = rcar_vin_poll, 1829 .poll = rcar_vin_poll,
diff --git a/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c b/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c
index 05eafe3a421e..e5571c8a368e 100644
--- a/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c
+++ b/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c
@@ -134,7 +134,7 @@ struct sh_mobile_ceu_cam {
134 unsigned int width; 134 unsigned int width;
135 unsigned int height; 135 unsigned int height;
136 /* 136 /*
137 * User window from S_CROP / G_CROP, produced by client cropping and 137 * User window from S_SELECTION / G_SELECTION, produced by client cropping and
138 * scaling, CEU scaling and CEU cropping, mapped back onto the client 138 * scaling, CEU scaling and CEU cropping, mapped back onto the client
139 * input window 139 * input window
140 */ 140 */
@@ -1109,17 +1109,16 @@ static void sh_mobile_ceu_put_formats(struct soc_camera_device *icd)
1109 * Documentation/video4linux/sh_mobile_ceu_camera.txt for a description of 1109 * Documentation/video4linux/sh_mobile_ceu_camera.txt for a description of
1110 * scaling and cropping algorithms and for the meaning of referenced here steps. 1110 * scaling and cropping algorithms and for the meaning of referenced here steps.
1111 */ 1111 */
1112static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd, 1112static int sh_mobile_ceu_set_selection(struct soc_camera_device *icd,
1113 const struct v4l2_crop *a) 1113 struct v4l2_selection *sel)
1114{ 1114{
1115 struct v4l2_crop a_writable = *a; 1115 struct v4l2_rect *rect = &sel->r;
1116 const struct v4l2_rect *rect = &a_writable.c;
1117 struct device *dev = icd->parent; 1116 struct device *dev = icd->parent;
1118 struct soc_camera_host *ici = to_soc_camera_host(dev); 1117 struct soc_camera_host *ici = to_soc_camera_host(dev);
1119 struct sh_mobile_ceu_dev *pcdev = ici->priv; 1118 struct sh_mobile_ceu_dev *pcdev = ici->priv;
1120 struct v4l2_crop cam_crop; 1119 struct v4l2_selection cam_sel;
1121 struct sh_mobile_ceu_cam *cam = icd->host_priv; 1120 struct sh_mobile_ceu_cam *cam = icd->host_priv;
1122 struct v4l2_rect *cam_rect = &cam_crop.c; 1121 struct v4l2_rect *cam_rect = &cam_sel.r;
1123 struct v4l2_subdev *sd = soc_camera_to_subdev(icd); 1122 struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
1124 struct v4l2_subdev_format fmt = { 1123 struct v4l2_subdev_format fmt = {
1125 .which = V4L2_SUBDEV_FORMAT_ACTIVE, 1124 .which = V4L2_SUBDEV_FORMAT_ACTIVE,
@@ -1131,7 +1130,7 @@ static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd,
1131 u32 capsr, cflcr; 1130 u32 capsr, cflcr;
1132 int ret; 1131 int ret;
1133 1132
1134 dev_geo(dev, "S_CROP(%ux%u@%u:%u)\n", rect->width, rect->height, 1133 dev_geo(dev, "S_SELECTION(%ux%u@%u:%u)\n", rect->width, rect->height,
1135 rect->left, rect->top); 1134 rect->left, rect->top);
1136 1135
1137 /* During camera cropping its output window can change too, stop CEU */ 1136 /* 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,
1139 dev_dbg(dev, "CAPSR 0x%x, CFLCR 0x%x\n", capsr, pcdev->cflcr); 1138 dev_dbg(dev, "CAPSR 0x%x, CFLCR 0x%x\n", capsr, pcdev->cflcr);
1140 1139
1141 /* 1140 /*
1142 * 1. - 2. Apply iterative camera S_CROP for new input window, read back 1141 * 1. - 2. Apply iterative camera S_SELECTION for new input window, read back
1143 * actual camera rectangle. 1142 * actual camera rectangle.
1144 */ 1143 */
1145 ret = soc_camera_client_s_crop(sd, &a_writable, &cam_crop, 1144 ret = soc_camera_client_s_selection(sd, sel, &cam_sel,
1146 &cam->rect, &cam->subrect); 1145 &cam->rect, &cam->subrect);
1147 if (ret < 0) 1146 if (ret < 0)
1148 return ret; 1147 return ret;
@@ -1251,13 +1250,12 @@ static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd,
1251 return ret; 1250 return ret;
1252} 1251}
1253 1252
1254static int sh_mobile_ceu_get_crop(struct soc_camera_device *icd, 1253static int sh_mobile_ceu_get_selection(struct soc_camera_device *icd,
1255 struct v4l2_crop *a) 1254 struct v4l2_selection *sel)
1256{ 1255{
1257 struct sh_mobile_ceu_cam *cam = icd->host_priv; 1256 struct sh_mobile_ceu_cam *cam = icd->host_priv;
1258 1257
1259 a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 1258 sel->r = cam->subrect;
1260 a->c = cam->subrect;
1261 1259
1262 return 0; 1260 return 0;
1263} 1261}
@@ -1499,8 +1497,8 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd,
1499 return ret; 1497 return ret;
1500} 1498}
1501 1499
1502static int sh_mobile_ceu_set_livecrop(struct soc_camera_device *icd, 1500static int sh_mobile_ceu_set_liveselection(struct soc_camera_device *icd,
1503 const struct v4l2_crop *a) 1501 struct v4l2_selection *sel)
1504{ 1502{
1505 struct v4l2_subdev *sd = soc_camera_to_subdev(icd); 1503 struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
1506 struct soc_camera_host *ici = to_soc_camera_host(icd->parent); 1504 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,
1519 "Client failed to stop the stream: %d\n", ret); 1517 "Client failed to stop the stream: %d\n", ret);
1520 else 1518 else
1521 /* Do the crop, if it fails, there's nothing more we can do */ 1519 /* Do the crop, if it fails, there's nothing more we can do */
1522 sh_mobile_ceu_set_crop(icd, a); 1520 sh_mobile_ceu_set_selection(icd, sel);
1523 1521
1524 dev_geo(icd->parent, "Output after crop: %ux%u\n", icd->user_width, icd->user_height); 1522 dev_geo(icd->parent, "Output after crop: %ux%u\n", icd->user_width, icd->user_height);
1525 1523
@@ -1600,9 +1598,9 @@ static struct soc_camera_host_ops sh_mobile_ceu_host_ops = {
1600 .clock_stop = sh_mobile_ceu_clock_stop, 1598 .clock_stop = sh_mobile_ceu_clock_stop,
1601 .get_formats = sh_mobile_ceu_get_formats, 1599 .get_formats = sh_mobile_ceu_get_formats,
1602 .put_formats = sh_mobile_ceu_put_formats, 1600 .put_formats = sh_mobile_ceu_put_formats,
1603 .get_crop = sh_mobile_ceu_get_crop, 1601 .get_selection = sh_mobile_ceu_get_selection,
1604 .set_crop = sh_mobile_ceu_set_crop, 1602 .set_selection = sh_mobile_ceu_set_selection,
1605 .set_livecrop = sh_mobile_ceu_set_livecrop, 1603 .set_liveselection = sh_mobile_ceu_set_liveselection,
1606 .set_fmt = sh_mobile_ceu_set_fmt, 1604 .set_fmt = sh_mobile_ceu_set_fmt,
1607 .try_fmt = sh_mobile_ceu_try_fmt, 1605 .try_fmt = sh_mobile_ceu_try_fmt,
1608 .poll = sh_mobile_ceu_poll, 1606 .poll = sh_mobile_ceu_poll,
diff --git a/drivers/media/platform/soc_camera/soc_camera.c b/drivers/media/platform/soc_camera/soc_camera.c
index 46c7186f7867..edd1c1de4e33 100644
--- a/drivers/media/platform/soc_camera/soc_camera.c
+++ b/drivers/media/platform/soc_camera/soc_camera.c
@@ -581,7 +581,7 @@ static int soc_camera_set_fmt(struct soc_camera_device *icd,
581 dev_dbg(icd->pdev, "S_FMT(%c%c%c%c, %ux%u)\n", 581 dev_dbg(icd->pdev, "S_FMT(%c%c%c%c, %ux%u)\n",
582 pixfmtstr(pix->pixelformat), pix->width, pix->height); 582 pixfmtstr(pix->pixelformat), pix->width, pix->height);
583 583
584 /* We always call try_fmt() before set_fmt() or set_crop() */ 584 /* We always call try_fmt() before set_fmt() or set_selection() */
585 ret = soc_camera_try_fmt(icd, f); 585 ret = soc_camera_try_fmt(icd, f);
586 if (ret < 0) 586 if (ret < 0)
587 return ret; 587 return ret;
@@ -1025,72 +1025,6 @@ static int soc_camera_streamoff(struct file *file, void *priv,
1025 return ret; 1025 return ret;
1026} 1026}
1027 1027
1028static int soc_camera_cropcap(struct file *file, void *fh,
1029 struct v4l2_cropcap *a)
1030{
1031 struct soc_camera_device *icd = file->private_data;
1032 struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
1033
1034 return ici->ops->cropcap(icd, a);
1035}
1036
1037static int soc_camera_g_crop(struct file *file, void *fh,
1038 struct v4l2_crop *a)
1039{
1040 struct soc_camera_device *icd = file->private_data;
1041 struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
1042 int ret;
1043
1044 ret = ici->ops->get_crop(icd, a);
1045
1046 return ret;
1047}
1048
1049/*
1050 * According to the V4L2 API, drivers shall not update the struct v4l2_crop
1051 * argument with the actual geometry, instead, the user shall use G_CROP to
1052 * retrieve it.
1053 */
1054static int soc_camera_s_crop(struct file *file, void *fh,
1055 const struct v4l2_crop *a)
1056{
1057 struct soc_camera_device *icd = file->private_data;
1058 struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
1059 const struct v4l2_rect *rect = &a->c;
1060 struct v4l2_crop current_crop;
1061 int ret;
1062
1063 if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1064 return -EINVAL;
1065
1066 dev_dbg(icd->pdev, "S_CROP(%ux%u@%u:%u)\n",
1067 rect->width, rect->height, rect->left, rect->top);
1068
1069 current_crop.type = a->type;
1070
1071 /* If get_crop fails, we'll let host and / or client drivers decide */
1072 ret = ici->ops->get_crop(icd, &current_crop);
1073
1074 /* Prohibit window size change with initialised buffers */
1075 if (ret < 0) {
1076 dev_err(icd->pdev,
1077 "S_CROP denied: getting current crop failed\n");
1078 } else if ((a->c.width == current_crop.c.width &&
1079 a->c.height == current_crop.c.height) ||
1080 !is_streaming(ici, icd)) {
1081 /* same size or not streaming - use .set_crop() */
1082 ret = ici->ops->set_crop(icd, a);
1083 } else if (ici->ops->set_livecrop) {
1084 ret = ici->ops->set_livecrop(icd, a);
1085 } else {
1086 dev_err(icd->pdev,
1087 "S_CROP denied: queue initialised and sizes differ\n");
1088 ret = -EBUSY;
1089 }
1090
1091 return ret;
1092}
1093
1094static int soc_camera_g_selection(struct file *file, void *fh, 1028static int soc_camera_g_selection(struct file *file, void *fh,
1095 struct v4l2_selection *s) 1029 struct v4l2_selection *s)
1096{ 1030{
@@ -1101,9 +1035,6 @@ static int soc_camera_g_selection(struct file *file, void *fh,
1101 if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) 1035 if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1102 return -EINVAL; 1036 return -EINVAL;
1103 1037
1104 if (!ici->ops->get_selection)
1105 return -ENOTTY;
1106
1107 return ici->ops->get_selection(icd, s); 1038 return ici->ops->get_selection(icd, s);
1108} 1039}
1109 1040
@@ -1135,10 +1066,11 @@ static int soc_camera_s_selection(struct file *file, void *fh,
1135 return -EBUSY; 1066 return -EBUSY;
1136 } 1067 }
1137 1068
1138 if (!ici->ops->set_selection) 1069 if (s->target == V4L2_SEL_TGT_CROP && is_streaming(ici, icd) &&
1139 return -ENOTTY; 1070 ici->ops->set_liveselection)
1140 1071 ret = ici->ops->set_liveselection(icd, s);
1141 ret = ici->ops->set_selection(icd, s); 1072 else
1073 ret = ici->ops->set_selection(icd, s);
1142 if (!ret && 1074 if (!ret &&
1143 s->target == V4L2_SEL_TGT_COMPOSE) { 1075 s->target == V4L2_SEL_TGT_COMPOSE) {
1144 icd->user_width = s->r.width; 1076 icd->user_width = s->r.width;
@@ -1881,23 +1813,40 @@ static int soc_camera_remove(struct soc_camera_device *icd)
1881 return 0; 1813 return 0;
1882} 1814}
1883 1815
1884static int default_cropcap(struct soc_camera_device *icd, 1816static int default_g_selection(struct soc_camera_device *icd,
1885 struct v4l2_cropcap *a) 1817 struct v4l2_selection *sel)
1886{ 1818{
1887 struct v4l2_subdev *sd = soc_camera_to_subdev(icd); 1819 struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
1888 return v4l2_subdev_call(sd, video, cropcap, a); 1820 struct v4l2_subdev_selection sdsel = {
1889} 1821 .which = V4L2_SUBDEV_FORMAT_ACTIVE,
1822 .target = sel->target,
1823 };
1824 int ret;
1890 1825
1891static int default_g_crop(struct soc_camera_device *icd, struct v4l2_crop *a) 1826 ret = v4l2_subdev_call(sd, pad, get_selection, NULL, &sdsel);
1892{ 1827 if (ret)
1893 struct v4l2_subdev *sd = soc_camera_to_subdev(icd); 1828 return ret;
1894 return v4l2_subdev_call(sd, video, g_crop, a); 1829 sel->r = sdsel.r;
1830 return 0;
1895} 1831}
1896 1832
1897static int default_s_crop(struct soc_camera_device *icd, const struct v4l2_crop *a) 1833static int default_s_selection(struct soc_camera_device *icd,
1834 struct v4l2_selection *sel)
1898{ 1835{
1899 struct v4l2_subdev *sd = soc_camera_to_subdev(icd); 1836 struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
1900 return v4l2_subdev_call(sd, video, s_crop, a); 1837 struct v4l2_subdev_selection sdsel = {
1838 .which = V4L2_SUBDEV_FORMAT_ACTIVE,
1839 .target = sel->target,
1840 .flags = sel->flags,
1841 .r = sel->r,
1842 };
1843 int ret;
1844
1845 ret = v4l2_subdev_call(sd, pad, set_selection, NULL, &sdsel);
1846 if (ret)
1847 return ret;
1848 sel->r = sdsel.r;
1849 return 0;
1901} 1850}
1902 1851
1903static int default_g_parm(struct soc_camera_device *icd, 1852static int default_g_parm(struct soc_camera_device *icd,
@@ -1968,12 +1917,10 @@ int soc_camera_host_register(struct soc_camera_host *ici)
1968 !ici->v4l2_dev.dev) 1917 !ici->v4l2_dev.dev)
1969 return -EINVAL; 1918 return -EINVAL;
1970 1919
1971 if (!ici->ops->set_crop) 1920 if (!ici->ops->set_selection)
1972 ici->ops->set_crop = default_s_crop; 1921 ici->ops->set_selection = default_s_selection;
1973 if (!ici->ops->get_crop) 1922 if (!ici->ops->get_selection)
1974 ici->ops->get_crop = default_g_crop; 1923 ici->ops->get_selection = default_g_selection;
1975 if (!ici->ops->cropcap)
1976 ici->ops->cropcap = default_cropcap;
1977 if (!ici->ops->set_parm) 1924 if (!ici->ops->set_parm)
1978 ici->ops->set_parm = default_s_parm; 1925 ici->ops->set_parm = default_s_parm;
1979 if (!ici->ops->get_parm) 1926 if (!ici->ops->get_parm)
@@ -2126,9 +2073,6 @@ static const struct v4l2_ioctl_ops soc_camera_ioctl_ops = {
2126 .vidioc_expbuf = soc_camera_expbuf, 2073 .vidioc_expbuf = soc_camera_expbuf,
2127 .vidioc_streamon = soc_camera_streamon, 2074 .vidioc_streamon = soc_camera_streamon,
2128 .vidioc_streamoff = soc_camera_streamoff, 2075 .vidioc_streamoff = soc_camera_streamoff,
2129 .vidioc_cropcap = soc_camera_cropcap,
2130 .vidioc_g_crop = soc_camera_g_crop,
2131 .vidioc_s_crop = soc_camera_s_crop,
2132 .vidioc_g_selection = soc_camera_g_selection, 2076 .vidioc_g_selection = soc_camera_g_selection,
2133 .vidioc_s_selection = soc_camera_s_selection, 2077 .vidioc_s_selection = soc_camera_s_selection,
2134 .vidioc_g_parm = soc_camera_g_parm, 2078 .vidioc_g_parm = soc_camera_g_parm,
diff --git a/drivers/media/platform/soc_camera/soc_camera_platform.c b/drivers/media/platform/soc_camera/soc_camera_platform.c
index a51d2a42998c..534d6c3c6d60 100644
--- a/drivers/media/platform/soc_camera/soc_camera_platform.c
+++ b/drivers/media/platform/soc_camera/soc_camera_platform.c
@@ -76,35 +76,27 @@ static int soc_camera_platform_enum_mbus_code(struct v4l2_subdev *sd,
76 return 0; 76 return 0;
77} 77}
78 78
79static int soc_camera_platform_g_crop(struct v4l2_subdev *sd, 79static int soc_camera_platform_get_selection(struct v4l2_subdev *sd,
80 struct v4l2_crop *a) 80 struct v4l2_subdev_pad_config *cfg,
81{ 81 struct v4l2_subdev_selection *sel)
82 struct soc_camera_platform_info *p = v4l2_get_subdevdata(sd);
83
84 a->c.left = 0;
85 a->c.top = 0;
86 a->c.width = p->format.width;
87 a->c.height = p->format.height;
88 a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
89
90 return 0;
91}
92
93static int soc_camera_platform_cropcap(struct v4l2_subdev *sd,
94 struct v4l2_cropcap *a)
95{ 82{
96 struct soc_camera_platform_info *p = v4l2_get_subdevdata(sd); 83 struct soc_camera_platform_info *p = v4l2_get_subdevdata(sd);
97 84
98 a->bounds.left = 0; 85 if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE)
99 a->bounds.top = 0; 86 return -EINVAL;
100 a->bounds.width = p->format.width;
101 a->bounds.height = p->format.height;
102 a->defrect = a->bounds;
103 a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
104 a->pixelaspect.numerator = 1;
105 a->pixelaspect.denominator = 1;
106 87
107 return 0; 88 switch (sel->target) {
89 case V4L2_SEL_TGT_CROP_BOUNDS:
90 case V4L2_SEL_TGT_CROP_DEFAULT:
91 case V4L2_SEL_TGT_CROP:
92 sel->r.left = 0;
93 sel->r.top = 0;
94 sel->r.width = p->format.width;
95 sel->r.height = p->format.height;
96 return 0;
97 default:
98 return -EINVAL;
99 }
108} 100}
109 101
110static int soc_camera_platform_g_mbus_config(struct v4l2_subdev *sd, 102static 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,
120 112
121static struct v4l2_subdev_video_ops platform_subdev_video_ops = { 113static struct v4l2_subdev_video_ops platform_subdev_video_ops = {
122 .s_stream = soc_camera_platform_s_stream, 114 .s_stream = soc_camera_platform_s_stream,
123 .cropcap = soc_camera_platform_cropcap,
124 .g_crop = soc_camera_platform_g_crop,
125 .g_mbus_config = soc_camera_platform_g_mbus_config, 115 .g_mbus_config = soc_camera_platform_g_mbus_config,
126}; 116};
127 117
128static const struct v4l2_subdev_pad_ops platform_subdev_pad_ops = { 118static const struct v4l2_subdev_pad_ops platform_subdev_pad_ops = {
129 .enum_mbus_code = soc_camera_platform_enum_mbus_code, 119 .enum_mbus_code = soc_camera_platform_enum_mbus_code,
120 .get_selection = soc_camera_platform_get_selection,
130 .get_fmt = soc_camera_platform_fill_fmt, 121 .get_fmt = soc_camera_platform_fill_fmt,
131 .set_fmt = soc_camera_platform_fill_fmt, 122 .set_fmt = soc_camera_platform_fill_fmt,
132}; 123};
diff --git a/drivers/media/platform/soc_camera/soc_scale_crop.c b/drivers/media/platform/soc_camera/soc_scale_crop.c
index bda29bc1b933..f77252d6ccd3 100644
--- a/drivers/media/platform/soc_camera/soc_scale_crop.c
+++ b/drivers/media/platform/soc_camera/soc_scale_crop.c
@@ -40,24 +40,22 @@ static bool is_inside(const struct v4l2_rect *r1, const struct v4l2_rect *r2)
40/* Get and store current client crop */ 40/* Get and store current client crop */
41int soc_camera_client_g_rect(struct v4l2_subdev *sd, struct v4l2_rect *rect) 41int soc_camera_client_g_rect(struct v4l2_subdev *sd, struct v4l2_rect *rect)
42{ 42{
43 struct v4l2_crop crop; 43 struct v4l2_subdev_selection sdsel = {
44 struct v4l2_cropcap cap; 44 .which = V4L2_SUBDEV_FORMAT_ACTIVE,
45 .target = V4L2_SEL_TGT_CROP,
46 };
45 int ret; 47 int ret;
46 48
47 crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 49 ret = v4l2_subdev_call(sd, pad, get_selection, NULL, &sdsel);
48
49 ret = v4l2_subdev_call(sd, video, g_crop, &crop);
50 if (!ret) { 50 if (!ret) {
51 *rect = crop.c; 51 *rect = sdsel.r;
52 return ret; 52 return ret;
53 } 53 }
54 54
55 /* Camera driver doesn't support .g_crop(), assume default rectangle */ 55 sdsel.target = V4L2_SEL_TGT_CROP_DEFAULT;
56 cap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 56 ret = v4l2_subdev_call(sd, pad, get_selection, NULL, &sdsel);
57
58 ret = v4l2_subdev_call(sd, video, cropcap, &cap);
59 if (!ret) 57 if (!ret)
60 *rect = cap.defrect; 58 *rect = sdsel.r;
61 59
62 return ret; 60 return ret;
63} 61}
@@ -93,17 +91,27 @@ static void update_subrect(struct v4l2_rect *rect, struct v4l2_rect *subrect)
93 * 2. if (1) failed, try to double the client image until we get one big enough 91 * 2. if (1) failed, try to double the client image until we get one big enough
94 * 3. if (2) failed, try to request the maximum image 92 * 3. if (2) failed, try to request the maximum image
95 */ 93 */
96int soc_camera_client_s_crop(struct v4l2_subdev *sd, 94int soc_camera_client_s_selection(struct v4l2_subdev *sd,
97 struct v4l2_crop *crop, struct v4l2_crop *cam_crop, 95 struct v4l2_selection *sel, struct v4l2_selection *cam_sel,
98 struct v4l2_rect *target_rect, struct v4l2_rect *subrect) 96 struct v4l2_rect *target_rect, struct v4l2_rect *subrect)
99{ 97{
100 struct v4l2_rect *rect = &crop->c, *cam_rect = &cam_crop->c; 98 struct v4l2_subdev_selection sdsel = {
99 .which = V4L2_SUBDEV_FORMAT_ACTIVE,
100 .target = sel->target,
101 .flags = sel->flags,
102 .r = sel->r,
103 };
104 struct v4l2_subdev_selection bounds = {
105 .which = V4L2_SUBDEV_FORMAT_ACTIVE,
106 .target = V4L2_SEL_TGT_CROP_BOUNDS,
107 };
108 struct v4l2_rect *rect = &sel->r, *cam_rect = &cam_sel->r;
101 struct device *dev = sd->v4l2_dev->dev; 109 struct device *dev = sd->v4l2_dev->dev;
102 struct v4l2_cropcap cap;
103 int ret; 110 int ret;
104 unsigned int width, height; 111 unsigned int width, height;
105 112
106 v4l2_subdev_call(sd, video, s_crop, crop); 113 v4l2_subdev_call(sd, pad, set_selection, NULL, &sdsel);
114 sel->r = sdsel.r;
107 ret = soc_camera_client_g_rect(sd, cam_rect); 115 ret = soc_camera_client_g_rect(sd, cam_rect);
108 if (ret < 0) 116 if (ret < 0)
109 return ret; 117 return ret;
@@ -113,29 +121,29 @@ int soc_camera_client_s_crop(struct v4l2_subdev *sd,
113 * be within camera cropcap bounds 121 * be within camera cropcap bounds
114 */ 122 */
115 if (!memcmp(rect, cam_rect, sizeof(*rect))) { 123 if (!memcmp(rect, cam_rect, sizeof(*rect))) {
116 /* Even if camera S_CROP failed, but camera rectangle matches */ 124 /* Even if camera S_SELECTION failed, but camera rectangle matches */
117 dev_dbg(dev, "Camera S_CROP successful for %dx%d@%d:%d\n", 125 dev_dbg(dev, "Camera S_SELECTION successful for %dx%d@%d:%d\n",
118 rect->width, rect->height, rect->left, rect->top); 126 rect->width, rect->height, rect->left, rect->top);
119 *target_rect = *cam_rect; 127 *target_rect = *cam_rect;
120 return 0; 128 return 0;
121 } 129 }
122 130
123 /* Try to fix cropping, that camera hasn't managed to set */ 131 /* Try to fix cropping, that camera hasn't managed to set */
124 dev_geo(dev, "Fix camera S_CROP for %dx%d@%d:%d to %dx%d@%d:%d\n", 132 dev_geo(dev, "Fix camera S_SELECTION for %dx%d@%d:%d to %dx%d@%d:%d\n",
125 cam_rect->width, cam_rect->height, 133 cam_rect->width, cam_rect->height,
126 cam_rect->left, cam_rect->top, 134 cam_rect->left, cam_rect->top,
127 rect->width, rect->height, rect->left, rect->top); 135 rect->width, rect->height, rect->left, rect->top);
128 136
129 /* We need sensor maximum rectangle */ 137 /* We need sensor maximum rectangle */
130 ret = v4l2_subdev_call(sd, video, cropcap, &cap); 138 ret = v4l2_subdev_call(sd, pad, get_selection, NULL, &bounds);
131 if (ret < 0) 139 if (ret < 0)
132 return ret; 140 return ret;
133 141
134 /* Put user requested rectangle within sensor bounds */ 142 /* Put user requested rectangle within sensor bounds */
135 soc_camera_limit_side(&rect->left, &rect->width, cap.bounds.left, 2, 143 soc_camera_limit_side(&rect->left, &rect->width, sdsel.r.left, 2,
136 cap.bounds.width); 144 bounds.r.width);
137 soc_camera_limit_side(&rect->top, &rect->height, cap.bounds.top, 4, 145 soc_camera_limit_side(&rect->top, &rect->height, sdsel.r.top, 4,
138 cap.bounds.height); 146 bounds.r.height);
139 147
140 /* 148 /*
141 * Popular special case - some cameras can only handle fixed sizes like 149 * 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,
150 */ 158 */
151 while (!ret && (is_smaller(cam_rect, rect) || 159 while (!ret && (is_smaller(cam_rect, rect) ||
152 is_inside(cam_rect, rect)) && 160 is_inside(cam_rect, rect)) &&
153 (cap.bounds.width > width || cap.bounds.height > height)) { 161 (bounds.r.width > width || bounds.r.height > height)) {
154 162
155 width *= 2; 163 width *= 2;
156 height *= 2; 164 height *= 2;
@@ -168,36 +176,40 @@ int soc_camera_client_s_crop(struct v4l2_subdev *sd,
168 * Instead we just drop to the left and top bounds. 176 * Instead we just drop to the left and top bounds.
169 */ 177 */
170 if (cam_rect->left > rect->left) 178 if (cam_rect->left > rect->left)
171 cam_rect->left = cap.bounds.left; 179 cam_rect->left = bounds.r.left;
172 180
173 if (cam_rect->left + cam_rect->width < rect->left + rect->width) 181 if (cam_rect->left + cam_rect->width < rect->left + rect->width)
174 cam_rect->width = rect->left + rect->width - 182 cam_rect->width = rect->left + rect->width -
175 cam_rect->left; 183 cam_rect->left;
176 184
177 if (cam_rect->top > rect->top) 185 if (cam_rect->top > rect->top)
178 cam_rect->top = cap.bounds.top; 186 cam_rect->top = bounds.r.top;
179 187
180 if (cam_rect->top + cam_rect->height < rect->top + rect->height) 188 if (cam_rect->top + cam_rect->height < rect->top + rect->height)
181 cam_rect->height = rect->top + rect->height - 189 cam_rect->height = rect->top + rect->height -
182 cam_rect->top; 190 cam_rect->top;
183 191
184 v4l2_subdev_call(sd, video, s_crop, cam_crop); 192 sdsel.r = *cam_rect;
193 v4l2_subdev_call(sd, pad, set_selection, NULL, &sdsel);
194 *cam_rect = sdsel.r;
185 ret = soc_camera_client_g_rect(sd, cam_rect); 195 ret = soc_camera_client_g_rect(sd, cam_rect);
186 dev_geo(dev, "Camera S_CROP %d for %dx%d@%d:%d\n", ret, 196 dev_geo(dev, "Camera S_SELECTION %d for %dx%d@%d:%d\n", ret,
187 cam_rect->width, cam_rect->height, 197 cam_rect->width, cam_rect->height,
188 cam_rect->left, cam_rect->top); 198 cam_rect->left, cam_rect->top);
189 } 199 }
190 200
191 /* S_CROP must not modify the rectangle */ 201 /* S_SELECTION must not modify the rectangle */
192 if (is_smaller(cam_rect, rect) || is_inside(cam_rect, rect)) { 202 if (is_smaller(cam_rect, rect) || is_inside(cam_rect, rect)) {
193 /* 203 /*
194 * The camera failed to configure a suitable cropping, 204 * The camera failed to configure a suitable cropping,
195 * we cannot use the current rectangle, set to max 205 * we cannot use the current rectangle, set to max
196 */ 206 */
197 *cam_rect = cap.bounds; 207 sdsel.r = bounds.r;
198 v4l2_subdev_call(sd, video, s_crop, cam_crop); 208 v4l2_subdev_call(sd, pad, set_selection, NULL, &sdsel);
209 *cam_rect = sdsel.r;
210
199 ret = soc_camera_client_g_rect(sd, cam_rect); 211 ret = soc_camera_client_g_rect(sd, cam_rect);
200 dev_geo(dev, "Camera S_CROP %d for max %dx%d@%d:%d\n", ret, 212 dev_geo(dev, "Camera S_SELECTION %d for max %dx%d@%d:%d\n", ret,
201 cam_rect->width, cam_rect->height, 213 cam_rect->width, cam_rect->height,
202 cam_rect->left, cam_rect->top); 214 cam_rect->left, cam_rect->top);
203 } 215 }
@@ -209,7 +221,7 @@ int soc_camera_client_s_crop(struct v4l2_subdev *sd,
209 221
210 return ret; 222 return ret;
211} 223}
212EXPORT_SYMBOL(soc_camera_client_s_crop); 224EXPORT_SYMBOL(soc_camera_client_s_selection);
213 225
214/* Iterative set_fmt, also updates cached client crop on success */ 226/* Iterative set_fmt, also updates cached client crop on success */
215static int client_set_fmt(struct soc_camera_device *icd, 227static int client_set_fmt(struct soc_camera_device *icd,
@@ -221,7 +233,10 @@ static int client_set_fmt(struct soc_camera_device *icd,
221 struct device *dev = icd->parent; 233 struct device *dev = icd->parent;
222 struct v4l2_mbus_framefmt *mf = &format->format; 234 struct v4l2_mbus_framefmt *mf = &format->format;
223 unsigned int width = mf->width, height = mf->height, tmp_w, tmp_h; 235 unsigned int width = mf->width, height = mf->height, tmp_w, tmp_h;
224 struct v4l2_cropcap cap; 236 struct v4l2_subdev_selection sdsel = {
237 .which = V4L2_SUBDEV_FORMAT_ACTIVE,
238 .target = V4L2_SEL_TGT_CROP_BOUNDS,
239 };
225 bool host_1to1; 240 bool host_1to1;
226 int ret; 241 int ret;
227 242
@@ -243,16 +258,14 @@ static int client_set_fmt(struct soc_camera_device *icd,
243 if (!host_can_scale) 258 if (!host_can_scale)
244 goto update_cache; 259 goto update_cache;
245 260
246 cap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 261 ret = v4l2_subdev_call(sd, pad, get_selection, NULL, &sdsel);
247
248 ret = v4l2_subdev_call(sd, video, cropcap, &cap);
249 if (ret < 0) 262 if (ret < 0)
250 return ret; 263 return ret;
251 264
252 if (max_width > cap.bounds.width) 265 if (max_width > sdsel.r.width)
253 max_width = cap.bounds.width; 266 max_width = sdsel.r.width;
254 if (max_height > cap.bounds.height) 267 if (max_height > sdsel.r.height)
255 max_height = cap.bounds.height; 268 max_height = sdsel.r.height;
256 269
257 /* Camera set a format, but geometry is not precise, try to improve */ 270 /* Camera set a format, but geometry is not precise, try to improve */
258 tmp_w = mf->width; 271 tmp_w = mf->width;
diff --git a/drivers/media/platform/soc_camera/soc_scale_crop.h b/drivers/media/platform/soc_camera/soc_scale_crop.h
index 184a30dff541..9ca469312a1f 100644
--- a/drivers/media/platform/soc_camera/soc_scale_crop.h
+++ b/drivers/media/platform/soc_camera/soc_scale_crop.h
@@ -16,7 +16,7 @@
16 16
17struct soc_camera_device; 17struct soc_camera_device;
18 18
19struct v4l2_crop; 19struct v4l2_selection;
20struct v4l2_mbus_framefmt; 20struct v4l2_mbus_framefmt;
21struct v4l2_pix_format; 21struct v4l2_pix_format;
22struct v4l2_rect; 22struct v4l2_rect;
@@ -31,8 +31,8 @@ static inline unsigned int soc_camera_shift_scale(unsigned int size,
31#define soc_camera_calc_scale(in, shift, out) soc_camera_shift_scale(in, shift, out) 31#define soc_camera_calc_scale(in, shift, out) soc_camera_shift_scale(in, shift, out)
32 32
33int soc_camera_client_g_rect(struct v4l2_subdev *sd, struct v4l2_rect *rect); 33int soc_camera_client_g_rect(struct v4l2_subdev *sd, struct v4l2_rect *rect);
34int soc_camera_client_s_crop(struct v4l2_subdev *sd, 34int soc_camera_client_s_selection(struct v4l2_subdev *sd,
35 struct v4l2_crop *crop, struct v4l2_crop *cam_crop, 35 struct v4l2_selection *sel, struct v4l2_selection *cam_sel,
36 struct v4l2_rect *target_rect, struct v4l2_rect *subrect); 36 struct v4l2_rect *target_rect, struct v4l2_rect *subrect);
37int soc_camera_client_scale(struct soc_camera_device *icd, 37int soc_camera_client_scale(struct soc_camera_device *icd,
38 struct v4l2_rect *rect, struct v4l2_rect *subrect, 38 struct v4l2_rect *rect, struct v4l2_rect *subrect,