aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuennadi Liakhovetski <g.liakhovetski@gmx.de>2009-08-25 10:46:54 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2009-09-18 23:19:06 -0400
commit08590b9613f7f624fe3a052586eea2dbb3584b38 (patch)
treea893d250a4edf84e93794be59e2b1d859314c972
parent961801bbb3448a86f0cc93747cecbfae686d81d1 (diff)
V4L/DVB (12529): soc-camera: switch to s_crop v4l2-subdev video operation
Remove set_crop soc-camera device method and switch to s_crop from v4l2-subdev video operations. Also extend non-i2c drivers to also hold a pointer to their v4l2-subdev instance in control device driver-data, i.e., in dev_get_drvdata((struct device *)to_soc_camera_control(icd)) Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r--drivers/media/video/mt9m001.c23
-rw-r--r--drivers/media/video/mt9m111.c9
-rw-r--r--drivers/media/video/mt9t031.c9
-rw-r--r--drivers/media/video/mt9v022.c23
-rw-r--r--drivers/media/video/mx1_camera.c8
-rw-r--r--drivers/media/video/mx3_camera.c7
-rw-r--r--drivers/media/video/ov772x.c19
-rw-r--r--drivers/media/video/pxa_camera.c7
-rw-r--r--drivers/media/video/sh_mobile_ceu_camera.c110
-rw-r--r--drivers/media/video/soc_camera.c4
-rw-r--r--drivers/media/video/soc_camera_platform.c28
-rw-r--r--drivers/media/video/tw9910.c31
-rw-r--r--include/media/soc_camera.h3
13 files changed, 142 insertions, 139 deletions
diff --git a/drivers/media/video/mt9m001.c b/drivers/media/video/mt9m001.c
index 8b36a74b1be0..6e762cd06e3f 100644
--- a/drivers/media/video/mt9m001.c
+++ b/drivers/media/video/mt9m001.c
@@ -194,11 +194,12 @@ static unsigned long mt9m001_query_bus_param(struct soc_camera_device *icd)
194 return soc_camera_apply_sensor_flags(icl, flags); 194 return soc_camera_apply_sensor_flags(icl, flags);
195} 195}
196 196
197static int mt9m001_set_crop(struct soc_camera_device *icd, 197static int mt9m001_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
198 struct v4l2_rect *rect)
199{ 198{
200 struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); 199 struct v4l2_rect *rect = &a->c;
200 struct i2c_client *client = sd->priv;
201 struct mt9m001 *mt9m001 = to_mt9m001(client); 201 struct mt9m001 *mt9m001 = to_mt9m001(client);
202 struct soc_camera_device *icd = client->dev.platform_data;
202 int ret; 203 int ret;
203 const u16 hblank = 9, vblank = 25; 204 const u16 hblank = 9, vblank = 25;
204 205
@@ -239,15 +240,17 @@ static int mt9m001_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
239{ 240{
240 struct i2c_client *client = sd->priv; 241 struct i2c_client *client = sd->priv;
241 struct soc_camera_device *icd = client->dev.platform_data; 242 struct soc_camera_device *icd = client->dev.platform_data;
242 struct v4l2_rect rect = { 243 struct v4l2_crop a = {
243 .left = icd->rect_current.left, 244 .c = {
244 .top = icd->rect_current.top, 245 .left = icd->rect_current.left,
245 .width = f->fmt.pix.width, 246 .top = icd->rect_current.top,
246 .height = f->fmt.pix.height, 247 .width = f->fmt.pix.width,
248 .height = f->fmt.pix.height,
249 },
247 }; 250 };
248 251
249 /* No support for scaling so far, just crop. TODO: use skipping */ 252 /* No support for scaling so far, just crop. TODO: use skipping */
250 return mt9m001_set_crop(icd, &rect); 253 return mt9m001_s_crop(sd, &a);
251} 254}
252 255
253static int mt9m001_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) 256static int mt9m001_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
@@ -361,7 +364,6 @@ static const struct v4l2_queryctrl mt9m001_controls[] = {
361static struct soc_camera_ops mt9m001_ops = { 364static struct soc_camera_ops mt9m001_ops = {
362 .init = mt9m001_init, 365 .init = mt9m001_init,
363 .release = mt9m001_release, 366 .release = mt9m001_release,
364 .set_crop = mt9m001_set_crop,
365 .set_bus_param = mt9m001_set_bus_param, 367 .set_bus_param = mt9m001_set_bus_param,
366 .query_bus_param = mt9m001_query_bus_param, 368 .query_bus_param = mt9m001_query_bus_param,
367 .controls = mt9m001_controls, 369 .controls = mt9m001_controls,
@@ -575,6 +577,7 @@ static struct v4l2_subdev_video_ops mt9m001_subdev_video_ops = {
575 .s_stream = mt9m001_s_stream, 577 .s_stream = mt9m001_s_stream,
576 .s_fmt = mt9m001_s_fmt, 578 .s_fmt = mt9m001_s_fmt,
577 .try_fmt = mt9m001_try_fmt, 579 .try_fmt = mt9m001_try_fmt,
580 .s_crop = mt9m001_s_crop,
578}; 581};
579 582
580static struct v4l2_subdev_ops mt9m001_subdev_ops = { 583static struct v4l2_subdev_ops mt9m001_subdev_ops = {
diff --git a/drivers/media/video/mt9m111.c b/drivers/media/video/mt9m111.c
index 45101fd90ce0..bef415170186 100644
--- a/drivers/media/video/mt9m111.c
+++ b/drivers/media/video/mt9m111.c
@@ -395,11 +395,12 @@ static int mt9m111_set_bus_param(struct soc_camera_device *icd, unsigned long f)
395 return 0; 395 return 0;
396} 396}
397 397
398static int mt9m111_set_crop(struct soc_camera_device *icd, 398static int mt9m111_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
399 struct v4l2_rect *rect)
400{ 399{
401 struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); 400 struct v4l2_rect *rect = &a->c;
401 struct i2c_client *client = sd->priv;
402 struct mt9m111 *mt9m111 = to_mt9m111(client); 402 struct mt9m111 *mt9m111 = to_mt9m111(client);
403 struct soc_camera_device *icd = client->dev.platform_data;
403 int ret; 404 int ret;
404 405
405 dev_dbg(&icd->dev, "%s left=%d, top=%d, width=%d, height=%d\n", 406 dev_dbg(&icd->dev, "%s left=%d, top=%d, width=%d, height=%d\n",
@@ -601,7 +602,6 @@ static struct soc_camera_ops mt9m111_ops = {
601 .init = mt9m111_init, 602 .init = mt9m111_init,
602 .resume = mt9m111_resume, 603 .resume = mt9m111_resume,
603 .release = mt9m111_release, 604 .release = mt9m111_release,
604 .set_crop = mt9m111_set_crop,
605 .query_bus_param = mt9m111_query_bus_param, 605 .query_bus_param = mt9m111_query_bus_param,
606 .set_bus_param = mt9m111_set_bus_param, 606 .set_bus_param = mt9m111_set_bus_param,
607 .controls = mt9m111_controls, 607 .controls = mt9m111_controls,
@@ -908,6 +908,7 @@ static struct v4l2_subdev_core_ops mt9m111_subdev_core_ops = {
908static struct v4l2_subdev_video_ops mt9m111_subdev_video_ops = { 908static struct v4l2_subdev_video_ops mt9m111_subdev_video_ops = {
909 .s_fmt = mt9m111_s_fmt, 909 .s_fmt = mt9m111_s_fmt,
910 .try_fmt = mt9m111_try_fmt, 910 .try_fmt = mt9m111_try_fmt,
911 .s_crop = mt9m111_s_crop,
911}; 912};
912 913
913static struct v4l2_subdev_ops mt9m111_subdev_ops = { 914static struct v4l2_subdev_ops mt9m111_subdev_ops = {
diff --git a/drivers/media/video/mt9t031.c b/drivers/media/video/mt9t031.c
index 125973bf08b9..3fa87be2fc6e 100644
--- a/drivers/media/video/mt9t031.c
+++ b/drivers/media/video/mt9t031.c
@@ -321,11 +321,12 @@ static int mt9t031_set_params(struct soc_camera_device *icd,
321 return ret < 0 ? ret : 0; 321 return ret < 0 ? ret : 0;
322} 322}
323 323
324static int mt9t031_set_crop(struct soc_camera_device *icd, 324static int mt9t031_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
325 struct v4l2_rect *rect)
326{ 325{
327 struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); 326 struct v4l2_rect *rect = &a->c;
327 struct i2c_client *client = sd->priv;
328 struct mt9t031 *mt9t031 = to_mt9t031(client); 328 struct mt9t031 *mt9t031 = to_mt9t031(client);
329 struct soc_camera_device *icd = client->dev.platform_data;
329 330
330 /* Make sure we don't exceed sensor limits */ 331 /* Make sure we don't exceed sensor limits */
331 if (rect->left + rect->width > icd->rect_max.left + icd->rect_max.width) 332 if (rect->left + rect->width > icd->rect_max.left + icd->rect_max.width)
@@ -495,7 +496,6 @@ static const struct v4l2_queryctrl mt9t031_controls[] = {
495static struct soc_camera_ops mt9t031_ops = { 496static struct soc_camera_ops mt9t031_ops = {
496 .init = mt9t031_init, 497 .init = mt9t031_init,
497 .release = mt9t031_release, 498 .release = mt9t031_release,
498 .set_crop = mt9t031_set_crop,
499 .set_bus_param = mt9t031_set_bus_param, 499 .set_bus_param = mt9t031_set_bus_param,
500 .query_bus_param = mt9t031_query_bus_param, 500 .query_bus_param = mt9t031_query_bus_param,
501 .controls = mt9t031_controls, 501 .controls = mt9t031_controls,
@@ -689,6 +689,7 @@ static struct v4l2_subdev_video_ops mt9t031_subdev_video_ops = {
689 .s_stream = mt9t031_s_stream, 689 .s_stream = mt9t031_s_stream,
690 .s_fmt = mt9t031_s_fmt, 690 .s_fmt = mt9t031_s_fmt,
691 .try_fmt = mt9t031_try_fmt, 691 .try_fmt = mt9t031_try_fmt,
692 .s_crop = mt9t031_s_crop,
692}; 693};
693 694
694static struct v4l2_subdev_ops mt9t031_subdev_ops = { 695static struct v4l2_subdev_ops mt9t031_subdev_ops = {
diff --git a/drivers/media/video/mt9v022.c b/drivers/media/video/mt9v022.c
index d2b0981ec1c1..e609ff51aa66 100644
--- a/drivers/media/video/mt9v022.c
+++ b/drivers/media/video/mt9v022.c
@@ -248,10 +248,11 @@ static unsigned long mt9v022_query_bus_param(struct soc_camera_device *icd)
248 width_flag; 248 width_flag;
249} 249}
250 250
251static int mt9v022_set_crop(struct soc_camera_device *icd, 251static int mt9v022_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
252 struct v4l2_rect *rect)
253{ 252{
254 struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); 253 struct v4l2_rect *rect = &a->c;
254 struct i2c_client *client = sd->priv;
255 struct soc_camera_device *icd = client->dev.platform_data;
255 int ret; 256 int ret;
256 257
257 /* Like in example app. Contradicts the datasheet though */ 258 /* Like in example app. Contradicts the datasheet though */
@@ -297,11 +298,13 @@ static int mt9v022_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
297 struct mt9v022 *mt9v022 = to_mt9v022(client); 298 struct mt9v022 *mt9v022 = to_mt9v022(client);
298 struct soc_camera_device *icd = client->dev.platform_data; 299 struct soc_camera_device *icd = client->dev.platform_data;
299 struct v4l2_pix_format *pix = &f->fmt.pix; 300 struct v4l2_pix_format *pix = &f->fmt.pix;
300 struct v4l2_rect rect = { 301 struct v4l2_crop a = {
301 .left = icd->rect_current.left, 302 .c = {
302 .top = icd->rect_current.top, 303 .left = icd->rect_current.left,
303 .width = pix->width, 304 .top = icd->rect_current.top,
304 .height = pix->height, 305 .width = pix->width,
306 .height = pix->height,
307 },
305 }; 308 };
306 309
307 /* The caller provides a supported format, as verified per call to 310 /* The caller provides a supported format, as verified per call to
@@ -325,7 +328,7 @@ static int mt9v022_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
325 } 328 }
326 329
327 /* No support for scaling on this camera, just crop. */ 330 /* No support for scaling on this camera, just crop. */
328 return mt9v022_set_crop(icd, &rect); 331 return mt9v022_s_crop(sd, &a);
329} 332}
330 333
331static int mt9v022_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) 334static int mt9v022_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
@@ -454,7 +457,6 @@ static const struct v4l2_queryctrl mt9v022_controls[] = {
454 457
455static struct soc_camera_ops mt9v022_ops = { 458static struct soc_camera_ops mt9v022_ops = {
456 .init = mt9v022_init, 459 .init = mt9v022_init,
457 .set_crop = mt9v022_set_crop,
458 .set_bus_param = mt9v022_set_bus_param, 460 .set_bus_param = mt9v022_set_bus_param,
459 .query_bus_param = mt9v022_query_bus_param, 461 .query_bus_param = mt9v022_query_bus_param,
460 .controls = mt9v022_controls, 462 .controls = mt9v022_controls,
@@ -700,6 +702,7 @@ static struct v4l2_subdev_video_ops mt9v022_subdev_video_ops = {
700 .s_stream = mt9v022_s_stream, 702 .s_stream = mt9v022_s_stream,
701 .s_fmt = mt9v022_s_fmt, 703 .s_fmt = mt9v022_s_fmt,
702 .try_fmt = mt9v022_try_fmt, 704 .try_fmt = mt9v022_try_fmt,
705 .s_crop = mt9v022_s_crop,
703}; 706};
704 707
705static struct v4l2_subdev_ops mt9v022_subdev_ops = { 708static struct v4l2_subdev_ops mt9v022_subdev_ops = {
diff --git a/drivers/media/video/mx1_camera.c b/drivers/media/video/mx1_camera.c
index 948a4714be9a..add496fca4d3 100644
--- a/drivers/media/video/mx1_camera.c
+++ b/drivers/media/video/mx1_camera.c
@@ -463,9 +463,13 @@ static void mx1_camera_remove_device(struct soc_camera_device *icd)
463} 463}
464 464
465static int mx1_camera_set_crop(struct soc_camera_device *icd, 465static int mx1_camera_set_crop(struct soc_camera_device *icd,
466 struct v4l2_rect *rect) 466 struct v4l2_crop *a)
467{ 467{
468 return icd->ops->set_crop(icd, rect); 468 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
469 struct device *control = to_soc_camera_control(icd);
470 struct v4l2_subdev *sd = dev_get_drvdata(control);
471
472 return v4l2_subdev_call(sd, video, s_crop, a);
469} 473}
470 474
471static int mx1_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) 475static int mx1_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
diff --git a/drivers/media/video/mx3_camera.c b/drivers/media/video/mx3_camera.c
index 6c3b7f9b906f..de7ebfbf0397 100644
--- a/drivers/media/video/mx3_camera.c
+++ b/drivers/media/video/mx3_camera.c
@@ -781,10 +781,13 @@ static int acquire_dma_channel(struct mx3_camera_dev *mx3_cam)
781} 781}
782 782
783static int mx3_camera_set_crop(struct soc_camera_device *icd, 783static int mx3_camera_set_crop(struct soc_camera_device *icd,
784 struct v4l2_rect *rect) 784 struct v4l2_crop *a)
785{ 785{
786 struct v4l2_rect *rect = &a->c;
786 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); 787 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
787 struct mx3_camera_dev *mx3_cam = ici->priv; 788 struct mx3_camera_dev *mx3_cam = ici->priv;
789 struct device *control = to_soc_camera_control(icd);
790 struct v4l2_subdev *sd = dev_get_drvdata(control);
788 791
789 /* 792 /*
790 * We now know pixel formats and can decide upon DMA-channel(s) 793 * We now know pixel formats and can decide upon DMA-channel(s)
@@ -798,7 +801,7 @@ static int mx3_camera_set_crop(struct soc_camera_device *icd,
798 801
799 configure_geometry(mx3_cam, rect); 802 configure_geometry(mx3_cam, rect);
800 803
801 return icd->ops->set_crop(icd, rect); 804 return v4l2_subdev_call(sd, video, s_crop, a);
802} 805}
803 806
804static int mx3_camera_set_fmt(struct soc_camera_device *icd, 807static int mx3_camera_set_fmt(struct soc_camera_device *icd,
diff --git a/drivers/media/video/ov772x.c b/drivers/media/video/ov772x.c
index 03488f9e1c88..bbe6f2d71c15 100644
--- a/drivers/media/video/ov772x.c
+++ b/drivers/media/video/ov772x.c
@@ -955,24 +955,6 @@ ov772x_set_fmt_error:
955 return ret; 955 return ret;
956} 956}
957 957
958/* Cannot crop, just return the current geometry */
959static int ov772x_set_crop(struct soc_camera_device *icd,
960 struct v4l2_rect *rect)
961{
962 struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
963 struct ov772x_priv *priv = to_ov772x(client);
964
965 if (!priv->fmt || !priv->win)
966 return -EINVAL;
967
968 rect->left = 0;
969 rect->top = 0;
970 rect->width = priv->win->width;
971 rect->height = priv->win->height;
972
973 return 0;
974}
975
976static int ov772x_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) 958static int ov772x_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
977{ 959{
978 struct i2c_client *client = sd->priv; 960 struct i2c_client *client = sd->priv;
@@ -1060,7 +1042,6 @@ static int ov772x_video_probe(struct soc_camera_device *icd,
1060} 1042}
1061 1043
1062static struct soc_camera_ops ov772x_ops = { 1044static struct soc_camera_ops ov772x_ops = {
1063 .set_crop = ov772x_set_crop,
1064 .set_bus_param = ov772x_set_bus_param, 1045 .set_bus_param = ov772x_set_bus_param,
1065 .query_bus_param = ov772x_query_bus_param, 1046 .query_bus_param = ov772x_query_bus_param,
1066 .controls = ov772x_controls, 1047 .controls = ov772x_controls,
diff --git a/drivers/media/video/pxa_camera.c b/drivers/media/video/pxa_camera.c
index 0e4daaad2f4d..c38ce84b944d 100644
--- a/drivers/media/video/pxa_camera.c
+++ b/drivers/media/video/pxa_camera.c
@@ -1281,10 +1281,13 @@ static int pxa_camera_get_formats(struct soc_camera_device *icd, int idx,
1281} 1281}
1282 1282
1283static int pxa_camera_set_crop(struct soc_camera_device *icd, 1283static int pxa_camera_set_crop(struct soc_camera_device *icd,
1284 struct v4l2_rect *rect) 1284 struct v4l2_crop *a)
1285{ 1285{
1286 struct v4l2_rect *rect = &a->c;
1286 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); 1287 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
1287 struct pxa_camera_dev *pcdev = ici->priv; 1288 struct pxa_camera_dev *pcdev = ici->priv;
1289 struct device *control = to_soc_camera_control(icd);
1290 struct v4l2_subdev *sd = dev_get_drvdata(control);
1288 struct soc_camera_sense sense = { 1291 struct soc_camera_sense sense = {
1289 .master_clock = pcdev->mclk, 1292 .master_clock = pcdev->mclk,
1290 .pixel_clock_max = pcdev->ciclk / 4, 1293 .pixel_clock_max = pcdev->ciclk / 4,
@@ -1295,7 +1298,7 @@ static int pxa_camera_set_crop(struct soc_camera_device *icd,
1295 if (pcdev->platform_flags & PXA_CAMERA_PCLK_EN) 1298 if (pcdev->platform_flags & PXA_CAMERA_PCLK_EN)
1296 icd->sense = &sense; 1299 icd->sense = &sense;
1297 1300
1298 ret = icd->ops->set_crop(icd, rect); 1301 ret = v4l2_subdev_call(sd, video, s_crop, a);
1299 1302
1300 icd->sense = NULL; 1303 icd->sense = NULL;
1301 1304
diff --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c
index 499d1a235fd7..726cf0e4dc23 100644
--- a/drivers/media/video/sh_mobile_ceu_camera.c
+++ b/drivers/media/video/sh_mobile_ceu_camera.c
@@ -846,12 +846,16 @@ static bool is_inside(struct v4l2_rect *r1, struct v4l2_rect *r2)
846 * 3. if (2) failed, try to request the maximum image 846 * 3. if (2) failed, try to request the maximum image
847 */ 847 */
848static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd, 848static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd,
849 struct v4l2_rect *rect) 849 struct v4l2_crop *a)
850{ 850{
851 struct v4l2_rect *rect = &a->c;
851 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); 852 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
852 struct sh_mobile_ceu_dev *pcdev = ici->priv; 853 struct sh_mobile_ceu_dev *pcdev = ici->priv;
853 struct v4l2_rect cam_rect, target, cam_max; 854 struct v4l2_crop cam_crop;
855 struct v4l2_rect *cam_rect = &cam_crop.c, target, cam_max;
854 struct sh_mobile_ceu_cam *cam = icd->host_priv; 856 struct sh_mobile_ceu_cam *cam = icd->host_priv;
857 struct device *control = to_soc_camera_control(icd);
858 struct v4l2_subdev *sd = dev_get_drvdata(control);
855 unsigned int hscale = pcdev->cflcr & 0xffff; 859 unsigned int hscale = pcdev->cflcr & 0xffff;
856 unsigned int vscale = (pcdev->cflcr >> 16) & 0xffff; 860 unsigned int vscale = (pcdev->cflcr >> 16) & 0xffff;
857 unsigned short width, height; 861 unsigned short width, height;
@@ -859,80 +863,80 @@ static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd,
859 int ret; 863 int ret;
860 864
861 /* Scale back up into client units */ 865 /* Scale back up into client units */
862 cam_rect.left = size_src(rect->left, hscale); 866 cam_rect->left = size_src(rect->left, hscale);
863 cam_rect.width = size_src(rect->width, hscale); 867 cam_rect->width = size_src(rect->width, hscale);
864 cam_rect.top = size_src(rect->top, vscale); 868 cam_rect->top = size_src(rect->top, vscale);
865 cam_rect.height = size_src(rect->height, vscale); 869 cam_rect->height = size_src(rect->height, vscale);
866 870
867 target = cam_rect; 871 target = *cam_rect;
868 872
869 capsr = capture_save_reset(pcdev); 873 capsr = capture_save_reset(pcdev);
870 dev_dbg(&icd->dev, "CAPSR 0x%x, CFLCR 0x%x\n", capsr, pcdev->cflcr); 874 dev_dbg(&icd->dev, "CAPSR 0x%x, CFLCR 0x%x\n", capsr, pcdev->cflcr);
871 875
872 /* First attempt - see if the client can deliver a perfect result */ 876 /* First attempt - see if the client can deliver a perfect result */
873 ret = icd->ops->set_crop(icd, &cam_rect); 877 ret = v4l2_subdev_call(sd, video, s_crop, &cam_crop);
874 if (!ret && !memcmp(&target, &cam_rect, sizeof(target))) { 878 if (!ret && !memcmp(&target, &cam_rect, sizeof(target))) {
875 dev_dbg(&icd->dev, "Camera S_CROP successful for %ux%u@%u:%u\n", 879 dev_dbg(&icd->dev, "Camera S_CROP successful for %ux%u@%u:%u\n",
876 cam_rect.width, cam_rect.height, 880 cam_rect->width, cam_rect->height,
877 cam_rect.left, cam_rect.top); 881 cam_rect->left, cam_rect->top);
878 goto ceu_set_rect; 882 goto ceu_set_rect;
879 } 883 }
880 884
881 /* Try to fix cropping, that camera hasn't managed to do */ 885 /* Try to fix cropping, that camera hasn't managed to do */
882 dev_dbg(&icd->dev, "Fix camera S_CROP %d for %ux%u@%u:%u" 886 dev_dbg(&icd->dev, "Fix camera S_CROP %d for %ux%u@%u:%u"
883 " to %ux%u@%u:%u\n", 887 " to %ux%u@%u:%u\n",
884 ret, cam_rect.width, cam_rect.height, 888 ret, cam_rect->width, cam_rect->height,
885 cam_rect.left, cam_rect.top, 889 cam_rect->left, cam_rect->top,
886 target.width, target.height, target.left, target.top); 890 target.width, target.height, target.left, target.top);
887 891
888 /* 892 /*
889 * Popular special case - some cameras can only handle fixed sizes like 893 * Popular special case - some cameras can only handle fixed sizes like
890 * QVGA, VGA,... Take care to avoid infinite loop. 894 * QVGA, VGA,... Take care to avoid infinite loop.
891 */ 895 */
892 width = max(cam_rect.width, 1); 896 width = max(cam_rect->width, 1);
893 height = max(cam_rect.height, 1); 897 height = max(cam_rect->height, 1);
894 cam_max.width = size_src(icd->rect_max.width, hscale); 898 cam_max.width = size_src(icd->rect_max.width, hscale);
895 cam_max.left = size_src(icd->rect_max.left, hscale); 899 cam_max.left = size_src(icd->rect_max.left, hscale);
896 cam_max.height = size_src(icd->rect_max.height, vscale); 900 cam_max.height = size_src(icd->rect_max.height, vscale);
897 cam_max.top = size_src(icd->rect_max.top, vscale); 901 cam_max.top = size_src(icd->rect_max.top, vscale);
898 while (!ret && (is_smaller(&cam_rect, &target) || 902 while (!ret && (is_smaller(cam_rect, &target) ||
899 is_inside(&cam_rect, &target)) && 903 is_inside(cam_rect, &target)) &&
900 cam_max.width >= width && cam_max.height >= height) { 904 cam_max.width >= width && cam_max.height >= height) {
901 905
902 width *= 2; 906 width *= 2;
903 height *= 2; 907 height *= 2;
904 cam_rect.width = width; 908 cam_rect->width = width;
905 cam_rect.height = height; 909 cam_rect->height = height;
906 910
907 /* We do not know what the camera is capable of, play safe */ 911 /* We do not know what the camera is capable of, play safe */
908 if (cam_rect.left > target.left) 912 if (cam_rect->left > target.left)
909 cam_rect.left = cam_max.left; 913 cam_rect->left = cam_max.left;
910 914
911 if (cam_rect.left + cam_rect.width < target.left + target.width) 915 if (cam_rect->left + cam_rect->width < target.left + target.width)
912 cam_rect.width = target.left + target.width - 916 cam_rect->width = target.left + target.width -
913 cam_rect.left; 917 cam_rect->left;
914 918
915 if (cam_rect.top > target.top) 919 if (cam_rect->top > target.top)
916 cam_rect.top = cam_max.top; 920 cam_rect->top = cam_max.top;
917 921
918 if (cam_rect.top + cam_rect.height < target.top + target.height) 922 if (cam_rect->top + cam_rect->height < target.top + target.height)
919 cam_rect.height = target.top + target.height - 923 cam_rect->height = target.top + target.height -
920 cam_rect.top; 924 cam_rect->top;
921 925
922 if (cam_rect.width + cam_rect.left > 926 if (cam_rect->width + cam_rect->left >
923 cam_max.width + cam_max.left) 927 cam_max.width + cam_max.left)
924 cam_rect.left = max(cam_max.width + cam_max.left - 928 cam_rect->left = max(cam_max.width + cam_max.left -
925 cam_rect.width, cam_max.left); 929 cam_rect->width, cam_max.left);
926 930
927 if (cam_rect.height + cam_rect.top > 931 if (cam_rect->height + cam_rect->top >
928 cam_max.height + cam_max.top) 932 cam_max.height + cam_max.top)
929 cam_rect.top = max(cam_max.height + cam_max.top - 933 cam_rect->top = max(cam_max.height + cam_max.top -
930 cam_rect.height, cam_max.top); 934 cam_rect->height, cam_max.top);
931 935
932 ret = icd->ops->set_crop(icd, &cam_rect); 936 ret = v4l2_subdev_call(sd, video, s_crop, &cam_crop);
933 dev_dbg(&icd->dev, "Camera S_CROP %d for %ux%u@%u:%u\n", 937 dev_dbg(&icd->dev, "Camera S_CROP %d for %ux%u@%u:%u\n",
934 ret, cam_rect.width, cam_rect.height, 938 ret, cam_rect->width, cam_rect->height,
935 cam_rect.left, cam_rect.top); 939 cam_rect->left, cam_rect->top);
936 } 940 }
937 941
938 /* 942 /*
@@ -941,30 +945,30 @@ static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd,
941 */ 945 */
942 if ((ret < 0 && (is_smaller(&icd->rect_current, rect) || 946 if ((ret < 0 && (is_smaller(&icd->rect_current, rect) ||
943 is_inside(&icd->rect_current, rect))) || 947 is_inside(&icd->rect_current, rect))) ||
944 is_smaller(&cam_rect, &target) || is_inside(&cam_rect, &target)) { 948 is_smaller(cam_rect, &target) || is_inside(cam_rect, &target)) {
945 /* 949 /*
946 * The camera failed to configure a suitable cropping, 950 * The camera failed to configure a suitable cropping,
947 * we cannot use the current rectangle, set to max 951 * we cannot use the current rectangle, set to max
948 */ 952 */
949 cam_rect = cam_max; 953 *cam_rect = cam_max;
950 ret = icd->ops->set_crop(icd, &cam_rect); 954 ret = v4l2_subdev_call(sd, video, s_crop, &cam_crop);
951 dev_dbg(&icd->dev, "Camera S_CROP %d for max %ux%u@%u:%u\n", 955 dev_dbg(&icd->dev, "Camera S_CROP %d for max %ux%u@%u:%u\n",
952 ret, cam_rect.width, cam_rect.height, 956 ret, cam_rect->width, cam_rect->height,
953 cam_rect.left, cam_rect.top); 957 cam_rect->left, cam_rect->top);
954 if (ret < 0) 958 if (ret < 0 && ret != -ENOIOCTLCMD)
955 /* All failed, hopefully resume current capture */ 959 /* All failed, hopefully resume current capture */
956 goto resume_capture; 960 goto resume_capture;
957 961
958 /* Finally, adjust the target rectangle */ 962 /* Finally, adjust the target rectangle */
959 if (target.width > cam_rect.width) 963 if (target.width > cam_rect->width)
960 target.width = cam_rect.width; 964 target.width = cam_rect->width;
961 if (target.height > cam_rect.height) 965 if (target.height > cam_rect->height)
962 target.height = cam_rect.height; 966 target.height = cam_rect->height;
963 if (target.left + target.width > cam_rect.left + cam_rect.width) 967 if (target.left + target.width > cam_rect->left + cam_rect->width)
964 target.left = cam_rect.left + cam_rect.width - 968 target.left = cam_rect->left + cam_rect->width -
965 target.width; 969 target.width;
966 if (target.top + target.height > cam_rect.top + cam_rect.height) 970 if (target.top + target.height > cam_rect->top + cam_rect->height)
967 target.top = cam_rect.top + cam_rect.height - 971 target.top = cam_rect->top + cam_rect->height -
968 target.height; 972 target.height;
969 } 973 }
970 974
@@ -978,14 +982,14 @@ static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd,
978 */ 982 */
979 dev_dbg(&icd->dev, 983 dev_dbg(&icd->dev,
980 "SH S_CROP from %ux%u@%u:%u to %ux%u@%u:%u, scale to %ux%u@%u:%u\n", 984 "SH S_CROP from %ux%u@%u:%u to %ux%u@%u:%u, scale to %ux%u@%u:%u\n",
981 cam_rect.width, cam_rect.height, cam_rect.left, cam_rect.top, 985 cam_rect->width, cam_rect->height, cam_rect->left, cam_rect->top,
982 target.width, target.height, target.left, target.top, 986 target.width, target.height, target.left, target.top,
983 rect->width, rect->height, rect->left, rect->top); 987 rect->width, rect->height, rect->left, rect->top);
984 988
985 ret = 0; 989 ret = 0;
986 990
987ceu_set_rect: 991ceu_set_rect:
988 cam->camera_rect = cam_rect; 992 cam->camera_rect = *cam_rect;
989 993
990 rect->width = size_dst(target.width, hscale); 994 rect->width = size_dst(target.width, hscale);
991 rect->left = size_dst(target.left, hscale); 995 rect->left = size_dst(target.left, hscale);
diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c
index 21a8aa586da5..d9ccc2866592 100644
--- a/drivers/media/video/soc_camera.c
+++ b/drivers/media/video/soc_camera.c
@@ -797,7 +797,7 @@ static int soc_camera_s_crop(struct file *file, void *fh,
797 rect.top = icd->rect_max.height + icd->rect_max.top - 797 rect.top = icd->rect_max.height + icd->rect_max.top -
798 rect.height; 798 rect.height;
799 799
800 ret = ici->ops->set_crop(icd, &rect); 800 ret = ici->ops->set_crop(icd, a);
801 if (!ret) 801 if (!ret)
802 icd->rect_current = rect; 802 icd->rect_current = rect;
803 803
@@ -970,7 +970,7 @@ static int soc_camera_probe(struct device *dev)
970 970
971 /* FIXME: this is racy, have to use driver-binding notification */ 971 /* FIXME: this is racy, have to use driver-binding notification */
972 control = to_soc_camera_control(icd); 972 control = to_soc_camera_control(icd);
973 if (!control || !control->driver || 973 if (!control || !control->driver || !dev_get_drvdata(control) ||
974 !try_module_get(control->driver->owner)) { 974 !try_module_get(control->driver->owner)) {
975 icl->del_device(icl); 975 icl->del_device(icl);
976 goto enodrv; 976 goto enodrv;
diff --git a/drivers/media/video/soc_camera_platform.c b/drivers/media/video/soc_camera_platform.c
index 9e406c113aa4..aec2cadbd2ee 100644
--- a/drivers/media/video/soc_camera_platform.c
+++ b/drivers/media/video/soc_camera_platform.c
@@ -25,10 +25,15 @@ struct soc_camera_platform_priv {
25 struct soc_camera_data_format format; 25 struct soc_camera_data_format format;
26}; 26};
27 27
28static struct soc_camera_platform_info * 28static struct soc_camera_platform_priv *get_priv(struct platform_device *pdev)
29soc_camera_platform_get_info(struct soc_camera_device *icd)
30{ 29{
31 struct platform_device *pdev = to_platform_device(dev_get_drvdata(&icd->dev)); 30 struct v4l2_subdev *subdev = platform_get_drvdata(pdev);
31 return container_of(subdev, struct soc_camera_platform_priv, subdev);
32}
33
34static struct soc_camera_platform_info *get_info(struct soc_camera_device *icd)
35{
36 struct platform_device *pdev = to_platform_device(to_soc_camera_control(icd));
32 return pdev->dev.platform_data; 37 return pdev->dev.platform_data;
33} 38}
34 39
@@ -47,16 +52,10 @@ static int soc_camera_platform_set_bus_param(struct soc_camera_device *icd,
47static unsigned long 52static unsigned long
48soc_camera_platform_query_bus_param(struct soc_camera_device *icd) 53soc_camera_platform_query_bus_param(struct soc_camera_device *icd)
49{ 54{
50 struct soc_camera_platform_info *p = soc_camera_platform_get_info(icd); 55 struct soc_camera_platform_info *p = get_info(icd);
51 return p->bus_param; 56 return p->bus_param;
52} 57}
53 58
54static int soc_camera_platform_set_crop(struct soc_camera_device *icd,
55 struct v4l2_rect *rect)
56{
57 return 0;
58}
59
60static int soc_camera_platform_try_fmt(struct v4l2_subdev *sd, 59static int soc_camera_platform_try_fmt(struct v4l2_subdev *sd,
61 struct v4l2_format *f) 60 struct v4l2_format *f)
62{ 61{
@@ -71,7 +70,7 @@ static int soc_camera_platform_try_fmt(struct v4l2_subdev *sd,
71static void soc_camera_platform_video_probe(struct soc_camera_device *icd, 70static void soc_camera_platform_video_probe(struct soc_camera_device *icd,
72 struct platform_device *pdev) 71 struct platform_device *pdev)
73{ 72{
74 struct soc_camera_platform_priv *priv = platform_get_drvdata(pdev); 73 struct soc_camera_platform_priv *priv = get_priv(pdev);
75 struct soc_camera_platform_info *p = pdev->dev.platform_data; 74 struct soc_camera_platform_info *p = pdev->dev.platform_data;
76 75
77 priv->format.name = p->format_name; 76 priv->format.name = p->format_name;
@@ -96,7 +95,6 @@ static struct v4l2_subdev_ops platform_subdev_ops = {
96}; 95};
97 96
98static struct soc_camera_ops soc_camera_platform_ops = { 97static struct soc_camera_ops soc_camera_platform_ops = {
99 .set_crop = soc_camera_platform_set_crop,
100 .set_bus_param = soc_camera_platform_set_bus_param, 98 .set_bus_param = soc_camera_platform_set_bus_param,
101 .query_bus_param = soc_camera_platform_query_bus_param, 99 .query_bus_param = soc_camera_platform_query_bus_param,
102}; 100};
@@ -124,7 +122,9 @@ static int soc_camera_platform_probe(struct platform_device *pdev)
124 122
125 icd = to_soc_camera_dev(p->dev); 123 icd = to_soc_camera_dev(p->dev);
126 124
127 platform_set_drvdata(pdev, priv); 125 /* soc-camera convention: control's drvdata points to the subdev */
126 platform_set_drvdata(pdev, &priv->subdev);
127 /* Set the control device reference */
128 dev_set_drvdata(&icd->dev, &pdev->dev); 128 dev_set_drvdata(&icd->dev, &pdev->dev);
129 129
130 icd->width_min = 0; 130 icd->width_min = 0;
@@ -158,7 +158,7 @@ evdrs:
158 158
159static int soc_camera_platform_remove(struct platform_device *pdev) 159static int soc_camera_platform_remove(struct platform_device *pdev)
160{ 160{
161 struct soc_camera_platform_priv *priv = platform_get_drvdata(pdev); 161 struct soc_camera_platform_priv *priv = get_priv(pdev);
162 struct soc_camera_platform_info *p = pdev->dev.platform_data; 162 struct soc_camera_platform_info *p = pdev->dev.platform_data;
163 struct soc_camera_device *icd = to_soc_camera_dev(p->dev); 163 struct soc_camera_device *icd = to_soc_camera_dev(p->dev);
164 164
diff --git a/drivers/media/video/tw9910.c b/drivers/media/video/tw9910.c
index 735d0bd4bb10..b6b15468b40a 100644
--- a/drivers/media/video/tw9910.c
+++ b/drivers/media/video/tw9910.c
@@ -616,11 +616,12 @@ static int tw9910_s_register(struct v4l2_subdev *sd,
616} 616}
617#endif 617#endif
618 618
619static int tw9910_set_crop(struct soc_camera_device *icd, 619static int tw9910_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
620 struct v4l2_rect *rect)
621{ 620{
622 struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); 621 struct v4l2_rect *rect = &a->c;
622 struct i2c_client *client = sd->priv;
623 struct tw9910_priv *priv = to_tw9910(client); 623 struct tw9910_priv *priv = to_tw9910(client);
624 struct soc_camera_device *icd = client->dev.platform_data;
624 int ret = -EINVAL; 625 int ret = -EINVAL;
625 u8 val; 626 u8 val;
626 627
@@ -716,15 +717,15 @@ tw9910_set_fmt_error:
716 717
717static int tw9910_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) 718static int tw9910_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
718{ 719{
719 struct i2c_client *client = sd->priv;
720 struct soc_camera_device *icd = client->dev.platform_data;
721 struct v4l2_pix_format *pix = &f->fmt.pix; 720 struct v4l2_pix_format *pix = &f->fmt.pix;
722 /* See tw9910_set_crop() - no proper cropping support */ 721 /* See tw9910_s_crop() - no proper cropping support */
723 struct v4l2_rect rect = { 722 struct v4l2_crop a = {
724 .left = 0, 723 .c = {
725 .top = 0, 724 .left = 0,
726 .width = pix->width, 725 .top = 0,
727 .height = pix->height, 726 .width = pix->width,
727 .height = pix->height,
728 },
728 }; 729 };
729 int i, ret; 730 int i, ret;
730 731
@@ -738,10 +739,10 @@ static int tw9910_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
738 if (i == ARRAY_SIZE(tw9910_color_fmt)) 739 if (i == ARRAY_SIZE(tw9910_color_fmt))
739 return -EINVAL; 740 return -EINVAL;
740 741
741 ret = tw9910_set_crop(icd, &rect); 742 ret = tw9910_s_crop(sd, &a);
742 if (!ret) { 743 if (!ret) {
743 pix->width = rect.width; 744 pix->width = a.c.width;
744 pix->height = rect.height; 745 pix->height = a.c.height;
745 } 746 }
746 return ret; 747 return ret;
747} 748}
@@ -821,7 +822,6 @@ static int tw9910_video_probe(struct soc_camera_device *icd,
821} 822}
822 823
823static struct soc_camera_ops tw9910_ops = { 824static struct soc_camera_ops tw9910_ops = {
824 .set_crop = tw9910_set_crop,
825 .set_bus_param = tw9910_set_bus_param, 825 .set_bus_param = tw9910_set_bus_param,
826 .query_bus_param = tw9910_query_bus_param, 826 .query_bus_param = tw9910_query_bus_param,
827 .enum_input = tw9910_enum_input, 827 .enum_input = tw9910_enum_input,
@@ -840,6 +840,7 @@ static struct v4l2_subdev_video_ops tw9910_subdev_video_ops = {
840 .s_stream = tw9910_s_stream, 840 .s_stream = tw9910_s_stream,
841 .s_fmt = tw9910_s_fmt, 841 .s_fmt = tw9910_s_fmt,
842 .try_fmt = tw9910_try_fmt, 842 .try_fmt = tw9910_try_fmt,
843 .s_crop = tw9910_s_crop,
843}; 844};
844 845
845static struct v4l2_subdev_ops tw9910_subdev_ops = { 846static struct v4l2_subdev_ops tw9910_subdev_ops = {
diff --git a/include/media/soc_camera.h b/include/media/soc_camera.h
index 7c44d4016561..0bad8f1d7e8d 100644
--- a/include/media/soc_camera.h
+++ b/include/media/soc_camera.h
@@ -76,7 +76,7 @@ struct soc_camera_host_ops {
76 int (*get_formats)(struct soc_camera_device *, int, 76 int (*get_formats)(struct soc_camera_device *, int,
77 struct soc_camera_format_xlate *); 77 struct soc_camera_format_xlate *);
78 void (*put_formats)(struct soc_camera_device *); 78 void (*put_formats)(struct soc_camera_device *);
79 int (*set_crop)(struct soc_camera_device *, struct v4l2_rect *); 79 int (*set_crop)(struct soc_camera_device *, struct v4l2_crop *);
80 int (*set_fmt)(struct soc_camera_device *, struct v4l2_format *); 80 int (*set_fmt)(struct soc_camera_device *, struct v4l2_format *);
81 int (*try_fmt)(struct soc_camera_device *, struct v4l2_format *); 81 int (*try_fmt)(struct soc_camera_device *, struct v4l2_format *);
82 void (*init_videobuf)(struct videobuf_queue *, 82 void (*init_videobuf)(struct videobuf_queue *,
@@ -185,7 +185,6 @@ struct soc_camera_ops {
185 int (*resume)(struct soc_camera_device *); 185 int (*resume)(struct soc_camera_device *);
186 int (*init)(struct soc_camera_device *); 186 int (*init)(struct soc_camera_device *);
187 int (*release)(struct soc_camera_device *); 187 int (*release)(struct soc_camera_device *);
188 int (*set_crop)(struct soc_camera_device *, struct v4l2_rect *);
189 unsigned long (*query_bus_param)(struct soc_camera_device *); 188 unsigned long (*query_bus_param)(struct soc_camera_device *);
190 int (*set_bus_param)(struct soc_camera_device *, unsigned long); 189 int (*set_bus_param)(struct soc_camera_device *, unsigned long);
191 int (*get_chip_id)(struct soc_camera_device *, 190 int (*get_chip_id)(struct soc_camera_device *,