aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuennadi Liakhovetski <g.liakhovetski@gmx.de>2009-03-13 05:08:20 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2009-03-30 11:43:21 -0400
commit09e231b35173313cd92e27532e5028f2042dcee4 (patch)
tree3ecda063aa52f954d2f797921bdce131d7f1cc28
parent1cd3c0fa927084549005fc22e54d99684b314f14 (diff)
V4L/DVB (11024): soc-camera: separate S_FMT and S_CROP operations
As host and camera drivers become more complex, differences between S_FMT and S_CROP functionality grow, this patch separates them. 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.c19
-rw-r--r--drivers/media/video/mt9m111.c56
-rw-r--r--drivers/media/video/mt9t031.c84
-rw-r--r--drivers/media/video/mt9v022.c62
-rw-r--r--drivers/media/video/mx3_camera.c157
-rw-r--r--drivers/media/video/ov772x.c31
-rw-r--r--drivers/media/video/pxa_camera.c67
-rw-r--r--drivers/media/video/sh_mobile_ceu_camera.c17
-rw-r--r--drivers/media/video/soc_camera.c20
-rw-r--r--drivers/media/video/soc_camera_platform.c9
-rw-r--r--drivers/media/video/tw9910.c45
-rw-r--r--include/media/soc_camera.h6
12 files changed, 381 insertions, 192 deletions
diff --git a/drivers/media/video/mt9m001.c b/drivers/media/video/mt9m001.c
index 2d1034dad495..a6703d25227f 100644
--- a/drivers/media/video/mt9m001.c
+++ b/drivers/media/video/mt9m001.c
@@ -284,8 +284,8 @@ static unsigned long mt9m001_query_bus_param(struct soc_camera_device *icd)
284 return soc_camera_apply_sensor_flags(icl, flags); 284 return soc_camera_apply_sensor_flags(icl, flags);
285} 285}
286 286
287static int mt9m001_set_fmt(struct soc_camera_device *icd, 287static int mt9m001_set_crop(struct soc_camera_device *icd,
288 __u32 pixfmt, struct v4l2_rect *rect) 288 struct v4l2_rect *rect)
289{ 289{
290 struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); 290 struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
291 int ret; 291 int ret;
@@ -324,6 +324,20 @@ static int mt9m001_set_fmt(struct soc_camera_device *icd,
324 return ret; 324 return ret;
325} 325}
326 326
327static int mt9m001_set_fmt(struct soc_camera_device *icd,
328 struct v4l2_format *f)
329{
330 struct v4l2_rect rect = {
331 .left = icd->x_current,
332 .top = icd->y_current,
333 .width = f->fmt.pix.width,
334 .height = f->fmt.pix.height,
335 };
336
337 /* No support for scaling so far, just crop. TODO: use skipping */
338 return mt9m001_set_crop(icd, &rect);
339}
340
327static int mt9m001_try_fmt(struct soc_camera_device *icd, 341static int mt9m001_try_fmt(struct soc_camera_device *icd,
328 struct v4l2_format *f) 342 struct v4l2_format *f)
329{ 343{
@@ -449,6 +463,7 @@ static struct soc_camera_ops mt9m001_ops = {
449 .release = mt9m001_release, 463 .release = mt9m001_release,
450 .start_capture = mt9m001_start_capture, 464 .start_capture = mt9m001_start_capture,
451 .stop_capture = mt9m001_stop_capture, 465 .stop_capture = mt9m001_stop_capture,
466 .set_crop = mt9m001_set_crop,
452 .set_fmt = mt9m001_set_fmt, 467 .set_fmt = mt9m001_set_fmt,
453 .try_fmt = mt9m001_try_fmt, 468 .try_fmt = mt9m001_try_fmt,
454 .set_bus_param = mt9m001_set_bus_param, 469 .set_bus_param = mt9m001_set_bus_param,
diff --git a/drivers/media/video/mt9m111.c b/drivers/media/video/mt9m111.c
index 7e6be36f0855..cdd1ddb51388 100644
--- a/drivers/media/video/mt9m111.c
+++ b/drivers/media/video/mt9m111.c
@@ -152,7 +152,7 @@ struct mt9m111 {
152 struct soc_camera_device icd; 152 struct soc_camera_device icd;
153 int model; /* V4L2_IDENT_MT9M11x* codes from v4l2-chip-ident.h */ 153 int model; /* V4L2_IDENT_MT9M11x* codes from v4l2-chip-ident.h */
154 enum mt9m111_context context; 154 enum mt9m111_context context;
155 unsigned int left, top, width, height; 155 struct v4l2_rect rect;
156 u32 pixfmt; 156 u32 pixfmt;
157 unsigned char autoexposure; 157 unsigned char autoexposure;
158 unsigned char datawidth; 158 unsigned char datawidth;
@@ -249,12 +249,13 @@ static int mt9m111_set_context(struct soc_camera_device *icd,
249 return reg_write(CONTEXT_CONTROL, valA); 249 return reg_write(CONTEXT_CONTROL, valA);
250} 250}
251 251
252static int mt9m111_setup_rect(struct soc_camera_device *icd) 252static int mt9m111_setup_rect(struct soc_camera_device *icd,
253 struct v4l2_rect *rect)
253{ 254{
254 struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); 255 struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
255 int ret, is_raw_format; 256 int ret, is_raw_format;
256 int width = mt9m111->width; 257 int width = rect->width;
257 int height = mt9m111->height; 258 int height = rect->height;
258 259
259 if ((mt9m111->pixfmt == V4L2_PIX_FMT_SBGGR8) 260 if ((mt9m111->pixfmt == V4L2_PIX_FMT_SBGGR8)
260 || (mt9m111->pixfmt == V4L2_PIX_FMT_SBGGR16)) 261 || (mt9m111->pixfmt == V4L2_PIX_FMT_SBGGR16))
@@ -262,9 +263,9 @@ static int mt9m111_setup_rect(struct soc_camera_device *icd)
262 else 263 else
263 is_raw_format = 0; 264 is_raw_format = 0;
264 265
265 ret = reg_write(COLUMN_START, mt9m111->left); 266 ret = reg_write(COLUMN_START, rect->left);
266 if (!ret) 267 if (!ret)
267 ret = reg_write(ROW_START, mt9m111->top); 268 ret = reg_write(ROW_START, rect->top);
268 269
269 if (is_raw_format) { 270 if (is_raw_format) {
270 if (!ret) 271 if (!ret)
@@ -436,6 +437,22 @@ static int mt9m111_set_bus_param(struct soc_camera_device *icd, unsigned long f)
436 return 0; 437 return 0;
437} 438}
438 439
440static int mt9m111_set_crop(struct soc_camera_device *icd,
441 struct v4l2_rect *rect)
442{
443 struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
444 int ret;
445
446 dev_dbg(&icd->dev, "%s left=%d, top=%d, width=%d, height=%d\n",
447 __func__, rect->left, rect->top, rect->width,
448 rect->height);
449
450 ret = mt9m111_setup_rect(icd, rect);
451 if (!ret)
452 mt9m111->rect = *rect;
453 return ret;
454}
455
439static int mt9m111_set_pixfmt(struct soc_camera_device *icd, u32 pixfmt) 456static int mt9m111_set_pixfmt(struct soc_camera_device *icd, u32 pixfmt)
440{ 457{
441 struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); 458 struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
@@ -486,23 +503,27 @@ static int mt9m111_set_pixfmt(struct soc_camera_device *icd, u32 pixfmt)
486} 503}
487 504
488static int mt9m111_set_fmt(struct soc_camera_device *icd, 505static int mt9m111_set_fmt(struct soc_camera_device *icd,
489 __u32 pixfmt, struct v4l2_rect *rect) 506 struct v4l2_format *f)
490{ 507{
491 struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); 508 struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
509 struct v4l2_pix_format *pix = &f->fmt.pix;
510 struct v4l2_rect rect = {
511 .left = mt9m111->rect.left,
512 .top = mt9m111->rect.top,
513 .width = pix->width,
514 .height = pix->height,
515 };
492 int ret; 516 int ret;
493 517
494 mt9m111->left = rect->left;
495 mt9m111->top = rect->top;
496 mt9m111->width = rect->width;
497 mt9m111->height = rect->height;
498
499 dev_dbg(&icd->dev, "%s fmt=%x left=%d, top=%d, width=%d, height=%d\n", 518 dev_dbg(&icd->dev, "%s fmt=%x left=%d, top=%d, width=%d, height=%d\n",
500 __func__, pixfmt, mt9m111->left, mt9m111->top, mt9m111->width, 519 __func__, pix->pixelformat, rect.left, rect.top, rect.width,
501 mt9m111->height); 520 rect.height);
502 521
503 ret = mt9m111_setup_rect(icd); 522 ret = mt9m111_setup_rect(icd, &rect);
523 if (!ret)
524 ret = mt9m111_set_pixfmt(icd, pix->pixelformat);
504 if (!ret) 525 if (!ret)
505 ret = mt9m111_set_pixfmt(icd, pixfmt); 526 mt9m111->rect = rect;
506 return ret; 527 return ret;
507} 528}
508 529
@@ -633,6 +654,7 @@ static struct soc_camera_ops mt9m111_ops = {
633 .release = mt9m111_release, 654 .release = mt9m111_release,
634 .start_capture = mt9m111_start_capture, 655 .start_capture = mt9m111_start_capture,
635 .stop_capture = mt9m111_stop_capture, 656 .stop_capture = mt9m111_stop_capture,
657 .set_crop = mt9m111_set_crop,
636 .set_fmt = mt9m111_set_fmt, 658 .set_fmt = mt9m111_set_fmt,
637 .try_fmt = mt9m111_try_fmt, 659 .try_fmt = mt9m111_try_fmt,
638 .query_bus_param = mt9m111_query_bus_param, 660 .query_bus_param = mt9m111_query_bus_param,
@@ -817,7 +839,7 @@ static int mt9m111_restore_state(struct soc_camera_device *icd)
817 839
818 mt9m111_set_context(icd, mt9m111->context); 840 mt9m111_set_context(icd, mt9m111->context);
819 mt9m111_set_pixfmt(icd, mt9m111->pixfmt); 841 mt9m111_set_pixfmt(icd, mt9m111->pixfmt);
820 mt9m111_setup_rect(icd); 842 mt9m111_setup_rect(icd, &mt9m111->rect);
821 mt9m111_set_flip(icd, mt9m111->hflip, MT9M111_RMB_MIRROR_COLS); 843 mt9m111_set_flip(icd, mt9m111->hflip, MT9M111_RMB_MIRROR_COLS);
822 mt9m111_set_flip(icd, mt9m111->vflip, MT9M111_RMB_MIRROR_ROWS); 844 mt9m111_set_flip(icd, mt9m111->vflip, MT9M111_RMB_MIRROR_ROWS);
823 mt9m111_set_global_gain(icd, icd->gain); 845 mt9m111_set_global_gain(icd, icd->gain);
diff --git a/drivers/media/video/mt9t031.c b/drivers/media/video/mt9t031.c
index acc1fa9db67d..677be18df9b3 100644
--- a/drivers/media/video/mt9t031.c
+++ b/drivers/media/video/mt9t031.c
@@ -213,36 +213,14 @@ static void recalculate_limits(struct soc_camera_device *icd,
213 icd->height_max = MT9T031_MAX_HEIGHT / yskip; 213 icd->height_max = MT9T031_MAX_HEIGHT / yskip;
214} 214}
215 215
216static int mt9t031_set_fmt(struct soc_camera_device *icd, 216static int mt9t031_set_params(struct soc_camera_device *icd,
217 __u32 pixfmt, struct v4l2_rect *rect) 217 struct v4l2_rect *rect, u16 xskip, u16 yskip)
218{ 218{
219 struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd); 219 struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
220 int ret; 220 int ret;
221 u16 xbin, ybin, width, height, left, top;
221 const u16 hblank = MT9T031_HORIZONTAL_BLANK, 222 const u16 hblank = MT9T031_HORIZONTAL_BLANK,
222 vblank = MT9T031_VERTICAL_BLANK; 223 vblank = MT9T031_VERTICAL_BLANK;
223 u16 xbin, xskip, ybin, yskip, width, height, left, top;
224
225 if (pixfmt) {
226 /*
227 * try_fmt has put rectangle within limits.
228 * S_FMT - use binning and skipping for scaling, recalculate
229 * limits, used for cropping
230 */
231 /* Is this more optimal than just a division? */
232 for (xskip = 8; xskip > 1; xskip--)
233 if (rect->width * xskip <= MT9T031_MAX_WIDTH)
234 break;
235
236 for (yskip = 8; yskip > 1; yskip--)
237 if (rect->height * yskip <= MT9T031_MAX_HEIGHT)
238 break;
239
240 recalculate_limits(icd, xskip, yskip);
241 } else {
242 /* CROP - no change in scaling, or in limits */
243 xskip = mt9t031->xskip;
244 yskip = mt9t031->yskip;
245 }
246 224
247 /* Make sure we don't exceed sensor limits */ 225 /* Make sure we don't exceed sensor limits */
248 if (rect->left + rect->width > icd->width_max) 226 if (rect->left + rect->width > icd->width_max)
@@ -289,7 +267,7 @@ static int mt9t031_set_fmt(struct soc_camera_device *icd,
289 if (ret >= 0) 267 if (ret >= 0)
290 ret = reg_write(icd, MT9T031_VERTICAL_BLANKING, vblank); 268 ret = reg_write(icd, MT9T031_VERTICAL_BLANKING, vblank);
291 269
292 if (pixfmt) { 270 if (yskip != mt9t031->yskip || xskip != mt9t031->xskip) {
293 /* Binning, skipping */ 271 /* Binning, skipping */
294 if (ret >= 0) 272 if (ret >= 0)
295 ret = reg_write(icd, MT9T031_COLUMN_ADDRESS_MODE, 273 ret = reg_write(icd, MT9T031_COLUMN_ADDRESS_MODE,
@@ -325,15 +303,58 @@ static int mt9t031_set_fmt(struct soc_camera_device *icd,
325 } 303 }
326 } 304 }
327 305
328 if (!ret && pixfmt) { 306 /* Re-enable register update, commit all changes */
307 if (ret >= 0)
308 ret = reg_clear(icd, MT9T031_OUTPUT_CONTROL, 1);
309
310 return ret < 0 ? ret : 0;
311}
312
313static int mt9t031_set_crop(struct soc_camera_device *icd,
314 struct v4l2_rect *rect)
315{
316 struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
317
318 /* CROP - no change in scaling, or in limits */
319 return mt9t031_set_params(icd, rect, mt9t031->xskip, mt9t031->yskip);
320}
321
322static int mt9t031_set_fmt(struct soc_camera_device *icd,
323 struct v4l2_format *f)
324{
325 struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
326 int ret;
327 u16 xskip, yskip;
328 struct v4l2_rect rect = {
329 .left = icd->x_current,
330 .top = icd->y_current,
331 .width = f->fmt.pix.width,
332 .height = f->fmt.pix.height,
333 };
334
335 /*
336 * try_fmt has put rectangle within limits.
337 * S_FMT - use binning and skipping for scaling, recalculate
338 * limits, used for cropping
339 */
340 /* Is this more optimal than just a division? */
341 for (xskip = 8; xskip > 1; xskip--)
342 if (rect.width * xskip <= MT9T031_MAX_WIDTH)
343 break;
344
345 for (yskip = 8; yskip > 1; yskip--)
346 if (rect.height * yskip <= MT9T031_MAX_HEIGHT)
347 break;
348
349 recalculate_limits(icd, xskip, yskip);
350
351 ret = mt9t031_set_params(icd, &rect, xskip, yskip);
352 if (!ret) {
329 mt9t031->xskip = xskip; 353 mt9t031->xskip = xskip;
330 mt9t031->yskip = yskip; 354 mt9t031->yskip = yskip;
331 } 355 }
332 356
333 /* Re-enable register update, commit all changes */ 357 return ret;
334 reg_clear(icd, MT9T031_OUTPUT_CONTROL, 1);
335
336 return ret < 0 ? ret : 0;
337} 358}
338 359
339static int mt9t031_try_fmt(struct soc_camera_device *icd, 360static int mt9t031_try_fmt(struct soc_camera_device *icd,
@@ -470,6 +491,7 @@ static struct soc_camera_ops mt9t031_ops = {
470 .release = mt9t031_release, 491 .release = mt9t031_release,
471 .start_capture = mt9t031_start_capture, 492 .start_capture = mt9t031_start_capture,
472 .stop_capture = mt9t031_stop_capture, 493 .stop_capture = mt9t031_stop_capture,
494 .set_crop = mt9t031_set_crop,
473 .set_fmt = mt9t031_set_fmt, 495 .set_fmt = mt9t031_set_fmt,
474 .try_fmt = mt9t031_try_fmt, 496 .try_fmt = mt9t031_try_fmt,
475 .set_bus_param = mt9t031_set_bus_param, 497 .set_bus_param = mt9t031_set_bus_param,
diff --git a/drivers/media/video/mt9v022.c b/drivers/media/video/mt9v022.c
index 6eb4b3a818d7..3871d4a2d8ff 100644
--- a/drivers/media/video/mt9v022.c
+++ b/drivers/media/video/mt9v022.c
@@ -340,32 +340,11 @@ static unsigned long mt9v022_query_bus_param(struct soc_camera_device *icd)
340 width_flag; 340 width_flag;
341} 341}
342 342
343static int mt9v022_set_fmt(struct soc_camera_device *icd, 343static int mt9v022_set_crop(struct soc_camera_device *icd,
344 __u32 pixfmt, struct v4l2_rect *rect) 344 struct v4l2_rect *rect)
345{ 345{
346 struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
347 int ret; 346 int ret;
348 347
349 /* The caller provides a supported format, as verified per call to
350 * icd->try_fmt(), datawidth is from our supported format list */
351 switch (pixfmt) {
352 case V4L2_PIX_FMT_GREY:
353 case V4L2_PIX_FMT_Y16:
354 if (mt9v022->model != V4L2_IDENT_MT9V022IX7ATM)
355 return -EINVAL;
356 break;
357 case V4L2_PIX_FMT_SBGGR8:
358 case V4L2_PIX_FMT_SBGGR16:
359 if (mt9v022->model != V4L2_IDENT_MT9V022IX7ATC)
360 return -EINVAL;
361 break;
362 case 0:
363 /* No format change, only geometry */
364 break;
365 default:
366 return -EINVAL;
367 }
368
369 /* Like in example app. Contradicts the datasheet though */ 348 /* Like in example app. Contradicts the datasheet though */
370 ret = reg_read(icd, MT9V022_AEC_AGC_ENABLE); 349 ret = reg_read(icd, MT9V022_AEC_AGC_ENABLE);
371 if (ret >= 0) { 350 if (ret >= 0) {
@@ -403,6 +382,42 @@ static int mt9v022_set_fmt(struct soc_camera_device *icd,
403 return 0; 382 return 0;
404} 383}
405 384
385static int mt9v022_set_fmt(struct soc_camera_device *icd,
386 struct v4l2_format *f)
387{
388 struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
389 struct v4l2_pix_format *pix = &f->fmt.pix;
390 struct v4l2_rect rect = {
391 .left = icd->x_current,
392 .top = icd->y_current,
393 .width = pix->width,
394 .height = pix->height,
395 };
396
397 /* The caller provides a supported format, as verified per call to
398 * icd->try_fmt(), datawidth is from our supported format list */
399 switch (pix->pixelformat) {
400 case V4L2_PIX_FMT_GREY:
401 case V4L2_PIX_FMT_Y16:
402 if (mt9v022->model != V4L2_IDENT_MT9V022IX7ATM)
403 return -EINVAL;
404 break;
405 case V4L2_PIX_FMT_SBGGR8:
406 case V4L2_PIX_FMT_SBGGR16:
407 if (mt9v022->model != V4L2_IDENT_MT9V022IX7ATC)
408 return -EINVAL;
409 break;
410 case 0:
411 /* No format change, only geometry */
412 break;
413 default:
414 return -EINVAL;
415 }
416
417 /* No support for scaling on this camera, just crop. */
418 return mt9v022_set_crop(icd, &rect);
419}
420
406static int mt9v022_try_fmt(struct soc_camera_device *icd, 421static int mt9v022_try_fmt(struct soc_camera_device *icd,
407 struct v4l2_format *f) 422 struct v4l2_format *f)
408{ 423{
@@ -544,6 +559,7 @@ static struct soc_camera_ops mt9v022_ops = {
544 .release = mt9v022_release, 559 .release = mt9v022_release,
545 .start_capture = mt9v022_start_capture, 560 .start_capture = mt9v022_start_capture,
546 .stop_capture = mt9v022_stop_capture, 561 .stop_capture = mt9v022_stop_capture,
562 .set_crop = mt9v022_set_crop,
547 .set_fmt = mt9v022_set_fmt, 563 .set_fmt = mt9v022_set_fmt,
548 .try_fmt = mt9v022_try_fmt, 564 .try_fmt = mt9v022_try_fmt,
549 .set_bus_param = mt9v022_set_bus_param, 565 .set_bus_param = mt9v022_set_bus_param,
diff --git a/drivers/media/video/mx3_camera.c b/drivers/media/video/mx3_camera.c
index f525dc48f6ca..70629e172e65 100644
--- a/drivers/media/video/mx3_camera.c
+++ b/drivers/media/video/mx3_camera.c
@@ -544,16 +544,14 @@ static void mx3_camera_remove_device(struct soc_camera_device *icd)
544} 544}
545 545
546static bool channel_change_requested(struct soc_camera_device *icd, 546static bool channel_change_requested(struct soc_camera_device *icd,
547 const struct soc_camera_format_xlate *xlate, 547 struct v4l2_rect *rect)
548 __u32 pixfmt, struct v4l2_rect *rect)
549{ 548{
550 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); 549 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
551 struct mx3_camera_dev *mx3_cam = ici->priv; 550 struct mx3_camera_dev *mx3_cam = ici->priv;
552 struct idmac_channel *ichan = mx3_cam->idmac_channel[0]; 551 struct idmac_channel *ichan = mx3_cam->idmac_channel[0];
553 552
554 /* So far only one configuration is supported */ 553 /* Do buffers have to be re-allocated or channel re-configured? */
555 return pixfmt || (ichan && rect->width * rect->height > 554 return ichan && rect->width * rect->height > icd->width * icd->height;
556 icd->width * icd->height);
557} 555}
558 556
559static int test_platform_param(struct mx3_camera_dev *mx3_cam, 557static int test_platform_param(struct mx3_camera_dev *mx3_cam,
@@ -733,61 +731,10 @@ passthrough:
733 return formats; 731 return formats;
734} 732}
735 733
736static int mx3_camera_set_fmt(struct soc_camera_device *icd, 734static void configure_geometry(struct mx3_camera_dev *mx3_cam,
737 __u32 pixfmt, struct v4l2_rect *rect) 735 struct v4l2_rect *rect)
738{ 736{
739 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
740 struct mx3_camera_dev *mx3_cam = ici->priv;
741 const struct soc_camera_format_xlate *xlate;
742 u32 ctrl, width_field, height_field; 737 u32 ctrl, width_field, height_field;
743 int ret;
744
745 xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
746 if (pixfmt && !xlate) {
747 dev_warn(&ici->dev, "Format %x not found\n", pixfmt);
748 return -EINVAL;
749 }
750
751 /*
752 * We now know pixel formats and can decide upon DMA-channel(s)
753 * So far only direct camera-to-memory is supported
754 */
755 if (channel_change_requested(icd, xlate, pixfmt, rect)) {
756 dma_cap_mask_t mask;
757 struct dma_chan *chan;
758 struct idmac_channel **ichan = &mx3_cam->idmac_channel[0];
759 /* We have to use IDMAC_IC_7 for Bayer / generic data */
760 struct dma_chan_request rq = {.mx3_cam = mx3_cam,
761 .id = IDMAC_IC_7};
762
763 if (*ichan) {
764 struct videobuf_buffer *vb, *_vb;
765 dma_release_channel(&(*ichan)->dma_chan);
766 *ichan = NULL;
767 mx3_cam->active = NULL;
768 list_for_each_entry_safe(vb, _vb, &mx3_cam->capture, queue) {
769 list_del_init(&vb->queue);
770 vb->state = VIDEOBUF_ERROR;
771 wake_up(&vb->done);
772 }
773 }
774
775 dma_cap_zero(mask);
776 dma_cap_set(DMA_SLAVE, mask);
777 dma_cap_set(DMA_PRIVATE, mask);
778 chan = dma_request_channel(mask, chan_filter, &rq);
779 if (!chan)
780 return -EBUSY;
781
782 *ichan = to_idmac_chan(chan);
783 (*ichan)->client = mx3_cam;
784 }
785
786 /*
787 * Might have to perform a complete interface initialisation like in
788 * ipu_csi_init_interface() in mxc_v4l2_s_param(). Also consider
789 * mxc_v4l2_s_fmt()
790 */
791 738
792 /* Setup frame size - this cannot be changed on-the-fly... */ 739 /* Setup frame size - this cannot be changed on-the-fly... */
793 width_field = rect->width - 1; 740 width_field = rect->width - 1;
@@ -808,9 +755,98 @@ static int mx3_camera_set_fmt(struct soc_camera_device *icd,
808 * No need to free resources here if we fail, we'll see if we need to 755 * No need to free resources here if we fail, we'll see if we need to
809 * do this next time we are called 756 * do this next time we are called
810 */ 757 */
758}
759
760static int acquire_dma_channel(struct mx3_camera_dev *mx3_cam)
761{
762 dma_cap_mask_t mask;
763 struct dma_chan *chan;
764 struct idmac_channel **ichan = &mx3_cam->idmac_channel[0];
765 /* We have to use IDMAC_IC_7 for Bayer / generic data */
766 struct dma_chan_request rq = {.mx3_cam = mx3_cam,
767 .id = IDMAC_IC_7};
768
769 if (*ichan) {
770 struct videobuf_buffer *vb, *_vb;
771 dma_release_channel(&(*ichan)->dma_chan);
772 *ichan = NULL;
773 mx3_cam->active = NULL;
774 list_for_each_entry_safe(vb, _vb, &mx3_cam->capture, queue) {
775 list_del_init(&vb->queue);
776 vb->state = VIDEOBUF_ERROR;
777 wake_up(&vb->done);
778 }
779 }
780
781 dma_cap_zero(mask);
782 dma_cap_set(DMA_SLAVE, mask);
783 dma_cap_set(DMA_PRIVATE, mask);
784 chan = dma_request_channel(mask, chan_filter, &rq);
785 if (!chan)
786 return -EBUSY;
787
788 *ichan = to_idmac_chan(chan);
789 (*ichan)->client = mx3_cam;
790
791 return 0;
792}
793
794static int mx3_camera_set_crop(struct soc_camera_device *icd,
795 struct v4l2_rect *rect)
796{
797 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
798 struct mx3_camera_dev *mx3_cam = ici->priv;
799
800 /*
801 * We now know pixel formats and can decide upon DMA-channel(s)
802 * So far only direct camera-to-memory is supported
803 */
804 if (channel_change_requested(icd, rect)) {
805 int ret = acquire_dma_channel(mx3_cam);
806 if (ret < 0)
807 return ret;
808 }
809
810 configure_geometry(mx3_cam, rect);
811
812 return icd->ops->set_crop(icd, rect);
813}
814
815static int mx3_camera_set_fmt(struct soc_camera_device *icd,
816 struct v4l2_format *f)
817{
818 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
819 struct mx3_camera_dev *mx3_cam = ici->priv;
820 const struct soc_camera_format_xlate *xlate;
821 struct v4l2_pix_format *pix = &f->fmt.pix;
822 struct v4l2_rect rect = {
823 .left = icd->x_current,
824 .top = icd->y_current,
825 .width = pix->width,
826 .height = pix->height,
827 };
828 int ret;
829
830 xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat);
831 if (!xlate) {
832 dev_warn(&ici->dev, "Format %x not found\n", pix->pixelformat);
833 return -EINVAL;
834 }
835
836 ret = acquire_dma_channel(mx3_cam);
837 if (ret < 0)
838 return ret;
839
840 /*
841 * Might have to perform a complete interface initialisation like in
842 * ipu_csi_init_interface() in mxc_v4l2_s_param(). Also consider
843 * mxc_v4l2_s_fmt()
844 */
845
846 configure_geometry(mx3_cam, &rect);
811 847
812 ret = icd->ops->set_fmt(icd, pixfmt ? xlate->cam_fmt->fourcc : 0, rect); 848 ret = icd->ops->set_fmt(icd, f);
813 if (pixfmt && !ret) { 849 if (!ret) {
814 icd->buswidth = xlate->buswidth; 850 icd->buswidth = xlate->buswidth;
815 icd->current_fmt = xlate->host_fmt; 851 icd->current_fmt = xlate->host_fmt;
816 } 852 }
@@ -1031,6 +1067,7 @@ static struct soc_camera_host_ops mx3_soc_camera_host_ops = {
1031 .suspend = mx3_camera_suspend, 1067 .suspend = mx3_camera_suspend,
1032 .resume = mx3_camera_resume, 1068 .resume = mx3_camera_resume,
1033#endif 1069#endif
1070 .set_crop = mx3_camera_set_crop,
1034 .set_fmt = mx3_camera_set_fmt, 1071 .set_fmt = mx3_camera_set_fmt,
1035 .try_fmt = mx3_camera_try_fmt, 1072 .try_fmt = mx3_camera_try_fmt,
1036 .get_formats = mx3_camera_get_formats, 1073 .get_formats = mx3_camera_get_formats,
diff --git a/drivers/media/video/ov772x.c b/drivers/media/video/ov772x.c
index 880e51f0e9fd..8dd93b36c787 100644
--- a/drivers/media/video/ov772x.c
+++ b/drivers/media/video/ov772x.c
@@ -781,11 +781,9 @@ ov772x_select_win(u32 width, u32 height)
781 return win; 781 return win;
782} 782}
783 783
784static int ov772x_set_fmt(struct soc_camera_device *icd, 784static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height,
785 __u32 pixfmt, 785 u32 pixfmt)
786 struct v4l2_rect *rect)
787{ 786{
788 struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
789 int ret = -EINVAL; 787 int ret = -EINVAL;
790 u8 val; 788 u8 val;
791 int i; 789 int i;
@@ -806,7 +804,7 @@ static int ov772x_set_fmt(struct soc_camera_device *icd,
806 /* 804 /*
807 * select win 805 * select win
808 */ 806 */
809 priv->win = ov772x_select_win(rect->width, rect->height); 807 priv->win = ov772x_select_win(width, height);
810 808
811 /* 809 /*
812 * reset hardware 810 * reset hardware
@@ -870,6 +868,28 @@ ov772x_set_fmt_error:
870 return ret; 868 return ret;
871} 869}
872 870
871static int ov772x_set_crop(struct soc_camera_device *icd,
872 struct v4l2_rect *rect)
873{
874 struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
875
876 if (!priv->fmt)
877 return -EINVAL;
878
879 return ov772x_set_params(priv, rect->width, rect->height,
880 priv->fmt->fourcc);
881}
882
883static int ov772x_set_fmt(struct soc_camera_device *icd,
884 struct v4l2_format *f)
885{
886 struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
887 struct v4l2_pix_format *pix = &f->fmt.pix;
888
889 return ov772x_set_params(priv, pix->width, pix->height,
890 pix->pixelformat);
891}
892
873static int ov772x_try_fmt(struct soc_camera_device *icd, 893static int ov772x_try_fmt(struct soc_camera_device *icd,
874 struct v4l2_format *f) 894 struct v4l2_format *f)
875{ 895{
@@ -959,6 +979,7 @@ static struct soc_camera_ops ov772x_ops = {
959 .release = ov772x_release, 979 .release = ov772x_release,
960 .start_capture = ov772x_start_capture, 980 .start_capture = ov772x_start_capture,
961 .stop_capture = ov772x_stop_capture, 981 .stop_capture = ov772x_stop_capture,
982 .set_crop = ov772x_set_crop,
962 .set_fmt = ov772x_set_fmt, 983 .set_fmt = ov772x_set_fmt,
963 .try_fmt = ov772x_try_fmt, 984 .try_fmt = ov772x_try_fmt,
964 .set_bus_param = ov772x_set_bus_param, 985 .set_bus_param = ov772x_set_bus_param,
diff --git a/drivers/media/video/pxa_camera.c b/drivers/media/video/pxa_camera.c
index 2cc203cfbe6c..c522616ef38f 100644
--- a/drivers/media/video/pxa_camera.c
+++ b/drivers/media/video/pxa_camera.c
@@ -1150,8 +1150,43 @@ static int pxa_camera_get_formats(struct soc_camera_device *icd, int idx,
1150 return formats; 1150 return formats;
1151} 1151}
1152 1152
1153static int pxa_camera_set_crop(struct soc_camera_device *icd,
1154 struct v4l2_rect *rect)
1155{
1156 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
1157 struct pxa_camera_dev *pcdev = ici->priv;
1158 struct soc_camera_sense sense = {
1159 .master_clock = pcdev->mclk,
1160 .pixel_clock_max = pcdev->ciclk / 4,
1161 };
1162 int ret;
1163
1164 /* If PCLK is used to latch data from the sensor, check sense */
1165 if (pcdev->platform_flags & PXA_CAMERA_PCLK_EN)
1166 icd->sense = &sense;
1167
1168 ret = icd->ops->set_crop(icd, rect);
1169
1170 icd->sense = NULL;
1171
1172 if (ret < 0) {
1173 dev_warn(&ici->dev, "Failed to crop to %ux%u@%u:%u\n",
1174 rect->width, rect->height, rect->left, rect->top);
1175 } else if (sense.flags & SOCAM_SENSE_PCLK_CHANGED) {
1176 if (sense.pixel_clock > sense.pixel_clock_max) {
1177 dev_err(&ici->dev,
1178 "pixel clock %lu set by the camera too high!",
1179 sense.pixel_clock);
1180 return -EIO;
1181 }
1182 recalculate_fifo_timeout(pcdev, sense.pixel_clock);
1183 }
1184
1185 return ret;
1186}
1187
1153static int pxa_camera_set_fmt(struct soc_camera_device *icd, 1188static int pxa_camera_set_fmt(struct soc_camera_device *icd,
1154 __u32 pixfmt, struct v4l2_rect *rect) 1189 struct v4l2_format *f)
1155{ 1190{
1156 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); 1191 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
1157 struct pxa_camera_dev *pcdev = ici->priv; 1192 struct pxa_camera_dev *pcdev = ici->priv;
@@ -1161,35 +1196,30 @@ static int pxa_camera_set_fmt(struct soc_camera_device *icd,
1161 .master_clock = pcdev->mclk, 1196 .master_clock = pcdev->mclk,
1162 .pixel_clock_max = pcdev->ciclk / 4, 1197 .pixel_clock_max = pcdev->ciclk / 4,
1163 }; 1198 };
1199 struct v4l2_pix_format *pix = &f->fmt.pix;
1200 struct v4l2_format cam_f = *f;
1164 int ret; 1201 int ret;
1165 1202
1166 if (pixfmt) { 1203 xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat);
1167 xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); 1204 if (!xlate) {
1168 if (!xlate) { 1205 dev_warn(&ici->dev, "Format %x not found\n", pix->pixelformat);
1169 dev_warn(&ici->dev, "Format %x not found\n", pixfmt); 1206 return -EINVAL;
1170 return -EINVAL;
1171 }
1172
1173 cam_fmt = xlate->cam_fmt;
1174 } 1207 }
1175 1208
1209 cam_fmt = xlate->cam_fmt;
1210
1176 /* If PCLK is used to latch data from the sensor, check sense */ 1211 /* If PCLK is used to latch data from the sensor, check sense */
1177 if (pcdev->platform_flags & PXA_CAMERA_PCLK_EN) 1212 if (pcdev->platform_flags & PXA_CAMERA_PCLK_EN)
1178 icd->sense = &sense; 1213 icd->sense = &sense;
1179 1214
1180 switch (pixfmt) { 1215 cam_f.fmt.pix.pixelformat = cam_fmt->fourcc;
1181 case 0: /* Only geometry change */ 1216 ret = icd->ops->set_fmt(icd, &cam_f);
1182 ret = icd->ops->set_fmt(icd, pixfmt, rect);
1183 break;
1184 default:
1185 ret = icd->ops->set_fmt(icd, cam_fmt->fourcc, rect);
1186 }
1187 1217
1188 icd->sense = NULL; 1218 icd->sense = NULL;
1189 1219
1190 if (ret < 0) { 1220 if (ret < 0) {
1191 dev_warn(&ici->dev, "Failed to configure for format %x\n", 1221 dev_warn(&ici->dev, "Failed to configure for format %x\n",
1192 pixfmt); 1222 pix->pixelformat);
1193 } else if (sense.flags & SOCAM_SENSE_PCLK_CHANGED) { 1223 } else if (sense.flags & SOCAM_SENSE_PCLK_CHANGED) {
1194 if (sense.pixel_clock > sense.pixel_clock_max) { 1224 if (sense.pixel_clock > sense.pixel_clock_max) {
1195 dev_err(&ici->dev, 1225 dev_err(&ici->dev,
@@ -1200,7 +1230,7 @@ static int pxa_camera_set_fmt(struct soc_camera_device *icd,
1200 recalculate_fifo_timeout(pcdev, sense.pixel_clock); 1230 recalculate_fifo_timeout(pcdev, sense.pixel_clock);
1201 } 1231 }
1202 1232
1203 if (pixfmt && !ret) { 1233 if (!ret) {
1204 icd->buswidth = xlate->buswidth; 1234 icd->buswidth = xlate->buswidth;
1205 icd->current_fmt = xlate->host_fmt; 1235 icd->current_fmt = xlate->host_fmt;
1206 } 1236 }
@@ -1364,6 +1394,7 @@ static struct soc_camera_host_ops pxa_soc_camera_host_ops = {
1364 .remove = pxa_camera_remove_device, 1394 .remove = pxa_camera_remove_device,
1365 .suspend = pxa_camera_suspend, 1395 .suspend = pxa_camera_suspend,
1366 .resume = pxa_camera_resume, 1396 .resume = pxa_camera_resume,
1397 .set_crop = pxa_camera_set_crop,
1367 .get_formats = pxa_camera_get_formats, 1398 .get_formats = pxa_camera_get_formats,
1368 .set_fmt = pxa_camera_set_fmt, 1399 .set_fmt = pxa_camera_set_fmt,
1369 .try_fmt = pxa_camera_try_fmt, 1400 .try_fmt = pxa_camera_try_fmt,
diff --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c
index ed3bfc4cf9f9..3f71cb809652 100644
--- a/drivers/media/video/sh_mobile_ceu_camera.c
+++ b/drivers/media/video/sh_mobile_ceu_camera.c
@@ -638,24 +638,30 @@ add_single_format:
638 return formats; 638 return formats;
639} 639}
640 640
641static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd,
642 struct v4l2_rect *rect)
643{
644 return icd->ops->set_crop(icd, rect);
645}
646
641static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd, 647static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd,
642 __u32 pixfmt, struct v4l2_rect *rect) 648 struct v4l2_format *f)
643{ 649{
644 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); 650 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
645 struct sh_mobile_ceu_dev *pcdev = ici->priv; 651 struct sh_mobile_ceu_dev *pcdev = ici->priv;
652 __u32 pixfmt = f->fmt.pix.pixelformat;
646 const struct soc_camera_format_xlate *xlate; 653 const struct soc_camera_format_xlate *xlate;
654 struct v4l2_format cam_f = *f;
647 int ret; 655 int ret;
648 656
649 if (!pixfmt)
650 return icd->ops->set_fmt(icd, pixfmt, rect);
651
652 xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); 657 xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
653 if (!xlate) { 658 if (!xlate) {
654 dev_warn(&ici->dev, "Format %x not found\n", pixfmt); 659 dev_warn(&ici->dev, "Format %x not found\n", pixfmt);
655 return -EINVAL; 660 return -EINVAL;
656 } 661 }
657 662
658 ret = icd->ops->set_fmt(icd, xlate->cam_fmt->fourcc, rect); 663 cam_f.fmt.pix.pixelformat = xlate->cam_fmt->fourcc;
664 ret = icd->ops->set_fmt(icd, &cam_f);
659 665
660 if (!ret) { 666 if (!ret) {
661 icd->buswidth = xlate->buswidth; 667 icd->buswidth = xlate->buswidth;
@@ -787,6 +793,7 @@ static struct soc_camera_host_ops sh_mobile_ceu_host_ops = {
787 .add = sh_mobile_ceu_add_device, 793 .add = sh_mobile_ceu_add_device,
788 .remove = sh_mobile_ceu_remove_device, 794 .remove = sh_mobile_ceu_remove_device,
789 .get_formats = sh_mobile_ceu_get_formats, 795 .get_formats = sh_mobile_ceu_get_formats,
796 .set_crop = sh_mobile_ceu_set_crop,
790 .set_fmt = sh_mobile_ceu_set_fmt, 797 .set_fmt = sh_mobile_ceu_set_fmt,
791 .try_fmt = sh_mobile_ceu_try_fmt, 798 .try_fmt = sh_mobile_ceu_try_fmt,
792 .reqbufs = sh_mobile_ceu_reqbufs, 799 .reqbufs = sh_mobile_ceu_reqbufs,
diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c
index fcb05f06de8f..9939b045cb4c 100644
--- a/drivers/media/video/soc_camera.c
+++ b/drivers/media/video/soc_camera.c
@@ -417,9 +417,7 @@ static int soc_camera_s_fmt_vid_cap(struct file *file, void *priv,
417 struct soc_camera_device *icd = icf->icd; 417 struct soc_camera_device *icd = icf->icd;
418 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); 418 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
419 struct v4l2_pix_format *pix = &f->fmt.pix; 419 struct v4l2_pix_format *pix = &f->fmt.pix;
420 __u32 pixfmt = pix->pixelformat;
421 int ret; 420 int ret;
422 struct v4l2_rect rect;
423 421
424 WARN_ON(priv != file->private_data); 422 WARN_ON(priv != file->private_data);
425 423
@@ -435,23 +433,19 @@ static int soc_camera_s_fmt_vid_cap(struct file *file, void *priv,
435 goto unlock; 433 goto unlock;
436 } 434 }
437 435
438 rect.left = icd->x_current; 436 ret = ici->ops->set_fmt(icd, f);
439 rect.top = icd->y_current;
440 rect.width = pix->width;
441 rect.height = pix->height;
442 ret = ici->ops->set_fmt(icd, pix->pixelformat, &rect);
443 if (ret < 0) { 437 if (ret < 0) {
444 goto unlock; 438 goto unlock;
445 } else if (!icd->current_fmt || 439 } else if (!icd->current_fmt ||
446 icd->current_fmt->fourcc != pixfmt) { 440 icd->current_fmt->fourcc != pix->pixelformat) {
447 dev_err(&ici->dev, 441 dev_err(&ici->dev,
448 "Host driver hasn't set up current format correctly!\n"); 442 "Host driver hasn't set up current format correctly!\n");
449 ret = -EINVAL; 443 ret = -EINVAL;
450 goto unlock; 444 goto unlock;
451 } 445 }
452 446
453 icd->width = rect.width; 447 icd->width = f->fmt.pix.width;
454 icd->height = rect.height; 448 icd->height = f->fmt.pix.height;
455 icf->vb_vidq.field = pix->field; 449 icf->vb_vidq.field = pix->field;
456 if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) 450 if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
457 dev_warn(&icd->dev, "Attention! Wrong buf-type %d\n", 451 dev_warn(&icd->dev, "Attention! Wrong buf-type %d\n",
@@ -461,7 +455,7 @@ static int soc_camera_s_fmt_vid_cap(struct file *file, void *priv,
461 icd->width, icd->height); 455 icd->width, icd->height);
462 456
463 /* set physical bus parameters */ 457 /* set physical bus parameters */
464 ret = ici->ops->set_bus_param(icd, pixfmt); 458 ret = ici->ops->set_bus_param(icd, pix->pixelformat);
465 459
466unlock: 460unlock:
467 mutex_unlock(&icf->vb_vidq.vb_lock); 461 mutex_unlock(&icf->vb_vidq.vb_lock);
@@ -685,7 +679,7 @@ static int soc_camera_s_crop(struct file *file, void *fh,
685 /* Cropping is allowed during a running capture, guard consistency */ 679 /* Cropping is allowed during a running capture, guard consistency */
686 mutex_lock(&icf->vb_vidq.vb_lock); 680 mutex_lock(&icf->vb_vidq.vb_lock);
687 681
688 ret = ici->ops->set_fmt(icd, 0, &a->c); 682 ret = ici->ops->set_crop(icd, &a->c);
689 if (!ret) { 683 if (!ret) {
690 icd->width = a->c.width; 684 icd->width = a->c.width;
691 icd->height = a->c.height; 685 icd->height = a->c.height;
@@ -918,6 +912,7 @@ int soc_camera_host_register(struct soc_camera_host *ici)
918 if (!ici || !ici->ops || 912 if (!ici || !ici->ops ||
919 !ici->ops->try_fmt || 913 !ici->ops->try_fmt ||
920 !ici->ops->set_fmt || 914 !ici->ops->set_fmt ||
915 !ici->ops->set_crop ||
921 !ici->ops->set_bus_param || 916 !ici->ops->set_bus_param ||
922 !ici->ops->querycap || 917 !ici->ops->querycap ||
923 !ici->ops->init_videobuf || 918 !ici->ops->init_videobuf ||
@@ -998,6 +993,7 @@ int soc_camera_device_register(struct soc_camera_device *icd)
998 !icd->ops->release || 993 !icd->ops->release ||
999 !icd->ops->start_capture || 994 !icd->ops->start_capture ||
1000 !icd->ops->stop_capture || 995 !icd->ops->stop_capture ||
996 !icd->ops->set_crop ||
1001 !icd->ops->set_fmt || 997 !icd->ops->set_fmt ||
1002 !icd->ops->try_fmt || 998 !icd->ops->try_fmt ||
1003 !icd->ops->query_bus_param || 999 !icd->ops->query_bus_param ||
diff --git a/drivers/media/video/soc_camera_platform.c b/drivers/media/video/soc_camera_platform.c
index 013ab06e3180..c48676356ab7 100644
--- a/drivers/media/video/soc_camera_platform.c
+++ b/drivers/media/video/soc_camera_platform.c
@@ -79,8 +79,14 @@ soc_camera_platform_query_bus_param(struct soc_camera_device *icd)
79 return p->bus_param; 79 return p->bus_param;
80} 80}
81 81
82static int soc_camera_platform_set_crop(struct soc_camera_device *icd,
83 struct v4l2_rect *rect)
84{
85 return 0;
86}
87
82static int soc_camera_platform_set_fmt(struct soc_camera_device *icd, 88static int soc_camera_platform_set_fmt(struct soc_camera_device *icd,
83 __u32 pixfmt, struct v4l2_rect *rect) 89 struct v4l2_format *f)
84{ 90{
85 return 0; 91 return 0;
86} 92}
@@ -125,6 +131,7 @@ static struct soc_camera_ops soc_camera_platform_ops = {
125 .release = soc_camera_platform_release, 131 .release = soc_camera_platform_release,
126 .start_capture = soc_camera_platform_start_capture, 132 .start_capture = soc_camera_platform_start_capture,
127 .stop_capture = soc_camera_platform_stop_capture, 133 .stop_capture = soc_camera_platform_stop_capture,
134 .set_crop = soc_camera_platform_set_crop,
128 .set_fmt = soc_camera_platform_set_fmt, 135 .set_fmt = soc_camera_platform_set_fmt,
129 .try_fmt = soc_camera_platform_try_fmt, 136 .try_fmt = soc_camera_platform_try_fmt,
130 .set_bus_param = soc_camera_platform_set_bus_param, 137 .set_bus_param = soc_camera_platform_set_bus_param,
diff --git a/drivers/media/video/tw9910.c b/drivers/media/video/tw9910.c
index 0558b22fd3fb..a39947643992 100644
--- a/drivers/media/video/tw9910.c
+++ b/drivers/media/video/tw9910.c
@@ -641,25 +641,12 @@ static int tw9910_set_register(struct soc_camera_device *icd,
641} 641}
642#endif 642#endif
643 643
644static int tw9910_set_fmt(struct soc_camera_device *icd, __u32 pixfmt, 644static int tw9910_set_crop(struct soc_camera_device *icd,
645 struct v4l2_rect *rect) 645 struct v4l2_rect *rect)
646{ 646{
647 struct tw9910_priv *priv = container_of(icd, struct tw9910_priv, icd); 647 struct tw9910_priv *priv = container_of(icd, struct tw9910_priv, icd);
648 int ret = -EINVAL; 648 int ret = -EINVAL;
649 u8 val; 649 u8 val;
650 int i;
651
652 /*
653 * check color format
654 */
655 for (i = 0 ; i < ARRAY_SIZE(tw9910_color_fmt) ; i++) {
656 if (pixfmt == tw9910_color_fmt[i].fourcc) {
657 ret = 0;
658 break;
659 }
660 }
661 if (ret < 0)
662 goto tw9910_set_fmt_error;
663 650
664 /* 651 /*
665 * select suitable norm 652 * select suitable norm
@@ -746,8 +733,33 @@ tw9910_set_fmt_error:
746 return ret; 733 return ret;
747} 734}
748 735
736static int tw9910_set_fmt(struct soc_camera_device *icd,
737 struct v4l2_format *f)
738{
739 struct v4l2_pix_format *pix = &f->fmt.pix;
740 struct v4l2_rect rect = {
741 .left = icd->x_current,
742 .top = icd->y_current,
743 .width = pix->width,
744 .height = pix->height,
745 };
746 int i;
747
748 /*
749 * check color format
750 */
751 for (i = 0; i < ARRAY_SIZE(tw9910_color_fmt); i++)
752 if (pix->pixelformat == tw9910_color_fmt[i].fourcc)
753 break;
754
755 if (i == ARRAY_SIZE(tw9910_color_fmt))
756 return -EINVAL;
757
758 return tw9910_set_crop(icd, &rect);
759}
760
749static int tw9910_try_fmt(struct soc_camera_device *icd, 761static int tw9910_try_fmt(struct soc_camera_device *icd,
750 struct v4l2_format *f) 762 struct v4l2_format *f)
751{ 763{
752 struct v4l2_pix_format *pix = &f->fmt.pix; 764 struct v4l2_pix_format *pix = &f->fmt.pix;
753 const struct tw9910_scale_ctrl *scale; 765 const struct tw9910_scale_ctrl *scale;
@@ -835,6 +847,7 @@ static struct soc_camera_ops tw9910_ops = {
835 .release = tw9910_release, 847 .release = tw9910_release,
836 .start_capture = tw9910_start_capture, 848 .start_capture = tw9910_start_capture,
837 .stop_capture = tw9910_stop_capture, 849 .stop_capture = tw9910_stop_capture,
850 .set_crop = tw9910_set_crop,
838 .set_fmt = tw9910_set_fmt, 851 .set_fmt = tw9910_set_fmt,
839 .try_fmt = tw9910_try_fmt, 852 .try_fmt = tw9910_try_fmt,
840 .set_bus_param = tw9910_set_bus_param, 853 .set_bus_param = tw9910_set_bus_param,
diff --git a/include/media/soc_camera.h b/include/media/soc_camera.h
index c63a3409ffb7..e9eb60740aaa 100644
--- a/include/media/soc_camera.h
+++ b/include/media/soc_camera.h
@@ -74,7 +74,8 @@ struct soc_camera_host_ops {
74 int (*resume)(struct soc_camera_device *); 74 int (*resume)(struct soc_camera_device *);
75 int (*get_formats)(struct soc_camera_device *, int, 75 int (*get_formats)(struct soc_camera_device *, int,
76 struct soc_camera_format_xlate *); 76 struct soc_camera_format_xlate *);
77 int (*set_fmt)(struct soc_camera_device *, __u32, struct v4l2_rect *); 77 int (*set_crop)(struct soc_camera_device *, struct v4l2_rect *);
78 int (*set_fmt)(struct soc_camera_device *, struct v4l2_format *);
78 int (*try_fmt)(struct soc_camera_device *, struct v4l2_format *); 79 int (*try_fmt)(struct soc_camera_device *, struct v4l2_format *);
79 void (*init_videobuf)(struct videobuf_queue *, 80 void (*init_videobuf)(struct videobuf_queue *,
80 struct soc_camera_device *); 81 struct soc_camera_device *);
@@ -159,7 +160,8 @@ struct soc_camera_ops {
159 int (*release)(struct soc_camera_device *); 160 int (*release)(struct soc_camera_device *);
160 int (*start_capture)(struct soc_camera_device *); 161 int (*start_capture)(struct soc_camera_device *);
161 int (*stop_capture)(struct soc_camera_device *); 162 int (*stop_capture)(struct soc_camera_device *);
162 int (*set_fmt)(struct soc_camera_device *, __u32, struct v4l2_rect *); 163 int (*set_crop)(struct soc_camera_device *, struct v4l2_rect *);
164 int (*set_fmt)(struct soc_camera_device *, struct v4l2_format *);
163 int (*try_fmt)(struct soc_camera_device *, struct v4l2_format *); 165 int (*try_fmt)(struct soc_camera_device *, struct v4l2_format *);
164 unsigned long (*query_bus_param)(struct soc_camera_device *); 166 unsigned long (*query_bus_param)(struct soc_camera_device *);
165 int (*set_bus_param)(struct soc_camera_device *, unsigned long); 167 int (*set_bus_param)(struct soc_camera_device *, unsigned long);