aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/media/video/mt9m001.c77
-rw-r--r--drivers/media/video/mt9v022.c129
-rw-r--r--drivers/media/video/pxa_camera.c156
-rw-r--r--drivers/media/video/soc_camera.c49
-rw-r--r--include/media/soc_camera.h52
5 files changed, 301 insertions, 162 deletions
diff --git a/drivers/media/video/mt9m001.c b/drivers/media/video/mt9m001.c
index 4ad834326fa8..acb5454b57eb 100644
--- a/drivers/media/video/mt9m001.c
+++ b/drivers/media/video/mt9m001.c
@@ -210,40 +210,64 @@ static int bus_switch_act(struct mt9m001 *mt9m001, int go8bit)
210#endif 210#endif
211} 211}
212 212
213static int mt9m001_set_capture_format(struct soc_camera_device *icd, 213static int bus_switch_possible(struct mt9m001 *mt9m001)
214 __u32 pixfmt, struct v4l2_rect *rect, unsigned int flags) 214{
215#ifdef CONFIG_MT9M001_PCA9536_SWITCH
216 return gpio_is_valid(mt9m001->switch_gpio);
217#else
218 return 0;
219#endif
220}
221
222static int mt9m001_set_bus_param(struct soc_camera_device *icd,
223 unsigned long flags)
215{ 224{
216 struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); 225 struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
217 unsigned int width_flag = flags & (IS_DATAWIDTH_10 | IS_DATAWIDTH_9 | 226 unsigned int width_flag = flags & SOCAM_DATAWIDTH_MASK;
218 IS_DATAWIDTH_8);
219 int ret; 227 int ret;
220 const u16 hblank = 9, vblank = 25;
221 228
222 /* MT9M001 has all capture_format parameters fixed */ 229 /* Flags validity verified in test_bus_param */
223 if (!(flags & IS_MASTER) ||
224 !(flags & IS_PCLK_SAMPLE_RISING) ||
225 !(flags & IS_HSYNC_ACTIVE_HIGH) ||
226 !(flags & IS_VSYNC_ACTIVE_HIGH))
227 return -EINVAL;
228
229 /* Only one width bit may be set */
230 if (!is_power_of_2(width_flag))
231 return -EINVAL;
232 230
233 if ((mt9m001->datawidth != 10 && (width_flag == IS_DATAWIDTH_10)) || 231 if ((mt9m001->datawidth != 10 && (width_flag == SOCAM_DATAWIDTH_10)) ||
234 (mt9m001->datawidth != 9 && (width_flag == IS_DATAWIDTH_9)) || 232 (mt9m001->datawidth != 9 && (width_flag == SOCAM_DATAWIDTH_9)) ||
235 (mt9m001->datawidth != 8 && (width_flag == IS_DATAWIDTH_8))) { 233 (mt9m001->datawidth != 8 && (width_flag == SOCAM_DATAWIDTH_8))) {
236 /* Well, we actually only can do 10 or 8 bits... */ 234 /* Well, we actually only can do 10 or 8 bits... */
237 if (width_flag == IS_DATAWIDTH_9) 235 if (width_flag == SOCAM_DATAWIDTH_9)
238 return -EINVAL; 236 return -EINVAL;
239 ret = bus_switch_act(mt9m001, 237 ret = bus_switch_act(mt9m001,
240 width_flag == IS_DATAWIDTH_8); 238 width_flag == SOCAM_DATAWIDTH_8);
241 if (ret < 0) 239 if (ret < 0)
242 return ret; 240 return ret;
243 241
244 mt9m001->datawidth = width_flag == IS_DATAWIDTH_8 ? 8 : 10; 242 mt9m001->datawidth = width_flag == SOCAM_DATAWIDTH_8 ? 8 : 10;
245 } 243 }
246 244
245 return 0;
246}
247
248static unsigned long mt9m001_query_bus_param(struct soc_camera_device *icd)
249{
250 struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
251 unsigned int width_flag = SOCAM_DATAWIDTH_10;
252
253 if (bus_switch_possible(mt9m001))
254 width_flag |= SOCAM_DATAWIDTH_8;
255
256 /* MT9M001 has all capture_format parameters fixed */
257 return SOCAM_PCLK_SAMPLE_RISING |
258 SOCAM_HSYNC_ACTIVE_HIGH |
259 SOCAM_VSYNC_ACTIVE_HIGH |
260 SOCAM_MASTER |
261 width_flag;
262}
263
264static int mt9m001_set_fmt_cap(struct soc_camera_device *icd,
265 __u32 pixfmt, struct v4l2_rect *rect)
266{
267 struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
268 int ret;
269 const u16 hblank = 9, vblank = 25;
270
247 /* Blanking and start values - default... */ 271 /* Blanking and start values - default... */
248 ret = reg_write(icd, MT9M001_HORIZONTAL_BLANKING, hblank); 272 ret = reg_write(icd, MT9M001_HORIZONTAL_BLANKING, hblank);
249 if (ret >= 0) 273 if (ret >= 0)
@@ -348,12 +372,6 @@ static int mt9m001_set_register(struct soc_camera_device *icd,
348} 372}
349#endif 373#endif
350 374
351static unsigned int mt9m001_get_datawidth(struct soc_camera_device *icd)
352{
353 struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
354 return mt9m001->datawidth;
355}
356
357const struct v4l2_queryctrl mt9m001_controls[] = { 375const struct v4l2_queryctrl mt9m001_controls[] = {
358 { 376 {
359 .id = V4L2_CID_VFLIP, 377 .id = V4L2_CID_VFLIP,
@@ -401,11 +419,12 @@ static struct soc_camera_ops mt9m001_ops = {
401 .release = mt9m001_release, 419 .release = mt9m001_release,
402 .start_capture = mt9m001_start_capture, 420 .start_capture = mt9m001_start_capture,
403 .stop_capture = mt9m001_stop_capture, 421 .stop_capture = mt9m001_stop_capture,
404 .set_capture_format = mt9m001_set_capture_format, 422 .set_fmt_cap = mt9m001_set_fmt_cap,
405 .try_fmt_cap = mt9m001_try_fmt_cap, 423 .try_fmt_cap = mt9m001_try_fmt_cap,
424 .set_bus_param = mt9m001_set_bus_param,
425 .query_bus_param = mt9m001_query_bus_param,
406 .formats = NULL, /* Filled in later depending on the */ 426 .formats = NULL, /* Filled in later depending on the */
407 .num_formats = 0, /* camera type and data widths */ 427 .num_formats = 0, /* camera type and data widths */
408 .get_datawidth = mt9m001_get_datawidth,
409 .controls = mt9m001_controls, 428 .controls = mt9m001_controls,
410 .num_controls = ARRAY_SIZE(mt9m001_controls), 429 .num_controls = ARRAY_SIZE(mt9m001_controls),
411 .get_control = mt9m001_get_control, 430 .get_control = mt9m001_get_control,
diff --git a/drivers/media/video/mt9v022.c b/drivers/media/video/mt9v022.c
index d677344d233d..a2f161dcc72d 100644
--- a/drivers/media/video/mt9v022.c
+++ b/drivers/media/video/mt9v022.c
@@ -241,19 +241,89 @@ static int bus_switch_act(struct mt9v022 *mt9v022, int go8bit)
241#endif 241#endif
242} 242}
243 243
244static int mt9v022_set_capture_format(struct soc_camera_device *icd, 244static int bus_switch_possible(struct mt9v022 *mt9v022)
245 __u32 pixfmt, struct v4l2_rect *rect, unsigned int flags) 245{
246#ifdef CONFIG_MT9V022_PCA9536_SWITCH
247 return gpio_is_valid(mt9v022->switch_gpio);
248#else
249 return 0;
250#endif
251}
252
253static int mt9v022_set_bus_param(struct soc_camera_device *icd,
254 unsigned long flags)
246{ 255{
247 struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); 256 struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
248 unsigned int width_flag = flags & (IS_DATAWIDTH_10 | IS_DATAWIDTH_9 | 257 unsigned int width_flag = flags & SOCAM_DATAWIDTH_MASK;
249 IS_DATAWIDTH_8);
250 u16 pixclk = 0;
251 int ret; 258 int ret;
259 u16 pixclk = 0;
252 260
253 /* Only one width bit may be set */ 261 /* Only one width bit may be set */
254 if (!is_power_of_2(width_flag)) 262 if (!is_power_of_2(width_flag))
255 return -EINVAL; 263 return -EINVAL;
256 264
265 if ((mt9v022->datawidth != 10 && (width_flag == SOCAM_DATAWIDTH_10)) ||
266 (mt9v022->datawidth != 9 && (width_flag == SOCAM_DATAWIDTH_9)) ||
267 (mt9v022->datawidth != 8 && (width_flag == SOCAM_DATAWIDTH_8))) {
268 /* Well, we actually only can do 10 or 8 bits... */
269 if (width_flag == SOCAM_DATAWIDTH_9)
270 return -EINVAL;
271
272 ret = bus_switch_act(mt9v022,
273 width_flag == SOCAM_DATAWIDTH_8);
274 if (ret < 0)
275 return ret;
276
277 mt9v022->datawidth = width_flag == SOCAM_DATAWIDTH_8 ? 8 : 10;
278 }
279
280 if (flags & SOCAM_PCLK_SAMPLE_RISING)
281 pixclk |= 0x10;
282
283 if (!(flags & SOCAM_HSYNC_ACTIVE_HIGH))
284 pixclk |= 0x1;
285
286 if (!(flags & SOCAM_VSYNC_ACTIVE_HIGH))
287 pixclk |= 0x2;
288
289 ret = reg_write(icd, MT9V022_PIXCLK_FV_LV, pixclk);
290 if (ret < 0)
291 return ret;
292
293 if (!(flags & SOCAM_MASTER))
294 mt9v022->chip_control &= ~0x8;
295
296 ret = reg_write(icd, MT9V022_CHIP_CONTROL, mt9v022->chip_control);
297 if (ret < 0)
298 return ret;
299
300 dev_dbg(&icd->dev, "Calculated pixclk 0x%x, chip control 0x%x\n",
301 pixclk, mt9v022->chip_control);
302
303 return 0;
304}
305
306static unsigned long mt9v022_query_bus_param(struct soc_camera_device *icd)
307{
308 struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
309 unsigned int width_flag = SOCAM_DATAWIDTH_10;
310
311 if (bus_switch_possible(mt9v022))
312 width_flag |= SOCAM_DATAWIDTH_8;
313
314 return SOCAM_PCLK_SAMPLE_RISING | SOCAM_PCLK_SAMPLE_FALLING |
315 SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_LOW |
316 SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_LOW |
317 SOCAM_MASTER | SOCAM_SLAVE |
318 width_flag;
319}
320
321static int mt9v022_set_fmt_cap(struct soc_camera_device *icd,
322 __u32 pixfmt, struct v4l2_rect *rect)
323{
324 struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
325 int ret;
326
257 /* The caller provides a supported format, as verified per call to 327 /* The caller provides a supported format, as verified per call to
258 * icd->try_fmt_cap(), datawidth is from our supported format list */ 328 * icd->try_fmt_cap(), datawidth is from our supported format list */
259 switch (pixfmt) { 329 switch (pixfmt) {
@@ -308,44 +378,6 @@ static int mt9v022_set_capture_format(struct soc_camera_device *icd,
308 378
309 dev_dbg(&icd->dev, "Frame %ux%u pixel\n", rect->width, rect->height); 379 dev_dbg(&icd->dev, "Frame %ux%u pixel\n", rect->width, rect->height);
310 380
311 if ((mt9v022->datawidth != 10 && (width_flag == IS_DATAWIDTH_10)) ||
312 (mt9v022->datawidth != 9 && (width_flag == IS_DATAWIDTH_9)) ||
313 (mt9v022->datawidth != 8 && (width_flag == IS_DATAWIDTH_8))) {
314 /* Well, we actually only can do 10 or 8 bits... */
315 if (width_flag == IS_DATAWIDTH_9)
316 return -EINVAL;
317
318 ret = bus_switch_act(mt9v022,
319 width_flag == IS_DATAWIDTH_8);
320 if (ret < 0)
321 return ret;
322
323 mt9v022->datawidth = width_flag == IS_DATAWIDTH_8 ? 8 : 10;
324 }
325
326 if (flags & IS_PCLK_SAMPLE_RISING)
327 pixclk |= 0x10;
328
329 if (!(flags & IS_HSYNC_ACTIVE_HIGH))
330 pixclk |= 0x1;
331
332 if (!(flags & IS_VSYNC_ACTIVE_HIGH))
333 pixclk |= 0x2;
334
335 ret = reg_write(icd, MT9V022_PIXCLK_FV_LV, pixclk);
336 if (ret < 0)
337 return ret;
338
339 if (!(flags & IS_MASTER))
340 mt9v022->chip_control &= ~0x8;
341
342 ret = reg_write(icd, MT9V022_CHIP_CONTROL, mt9v022->chip_control);
343 if (ret < 0)
344 return ret;
345
346 dev_dbg(&icd->dev, "Calculated pixclk 0x%x, chip control 0x%x\n",
347 pixclk, mt9v022->chip_control);
348
349 return 0; 381 return 0;
350} 382}
351 383
@@ -420,12 +452,6 @@ static int mt9v022_set_register(struct soc_camera_device *icd,
420} 452}
421#endif 453#endif
422 454
423static unsigned int mt9v022_get_datawidth(struct soc_camera_device *icd)
424{
425 struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
426 return mt9v022->datawidth;
427}
428
429const struct v4l2_queryctrl mt9v022_controls[] = { 455const struct v4l2_queryctrl mt9v022_controls[] = {
430 { 456 {
431 .id = V4L2_CID_VFLIP, 457 .id = V4L2_CID_VFLIP,
@@ -491,11 +517,12 @@ static struct soc_camera_ops mt9v022_ops = {
491 .release = mt9v022_release, 517 .release = mt9v022_release,
492 .start_capture = mt9v022_start_capture, 518 .start_capture = mt9v022_start_capture,
493 .stop_capture = mt9v022_stop_capture, 519 .stop_capture = mt9v022_stop_capture,
494 .set_capture_format = mt9v022_set_capture_format, 520 .set_fmt_cap = mt9v022_set_fmt_cap,
495 .try_fmt_cap = mt9v022_try_fmt_cap, 521 .try_fmt_cap = mt9v022_try_fmt_cap,
522 .set_bus_param = mt9v022_set_bus_param,
523 .query_bus_param = mt9v022_query_bus_param,
496 .formats = NULL, /* Filled in later depending on the */ 524 .formats = NULL, /* Filled in later depending on the */
497 .num_formats = 0, /* sensor type and data widths */ 525 .num_formats = 0, /* sensor type and data widths */
498 .get_datawidth = mt9v022_get_datawidth,
499 .controls = mt9v022_controls, 526 .controls = mt9v022_controls,
500 .num_controls = ARRAY_SIZE(mt9v022_controls), 527 .num_controls = ARRAY_SIZE(mt9v022_controls),
501 .get_control = mt9v022_get_control, 528 .get_control = mt9v022_get_control,
diff --git a/drivers/media/video/pxa_camera.c b/drivers/media/video/pxa_camera.c
index a34a193249f6..4756699d16aa 100644
--- a/drivers/media/video/pxa_camera.c
+++ b/drivers/media/video/pxa_camera.c
@@ -581,64 +581,109 @@ static void pxa_camera_remove_device(struct soc_camera_device *icd)
581 pcdev->icd = NULL; 581 pcdev->icd = NULL;
582} 582}
583 583
584static int pxa_camera_set_capture_format(struct soc_camera_device *icd, 584static int test_platform_param(struct pxa_camera_dev *pcdev,
585 __u32 pixfmt, struct v4l2_rect *rect) 585 unsigned char buswidth, unsigned long *flags)
586{ 586{
587 struct soc_camera_host *ici = 587 /*
588 to_soc_camera_host(icd->dev.parent); 588 * Platform specified synchronization and pixel clock polarities are
589 struct pxa_camera_dev *pcdev = ici->priv; 589 * only a recommendation and are only used during probing. The PXA270
590 unsigned int datawidth = 0, dw, bpp; 590 * quick capture interface supports both.
591 u32 cicr0, cicr4 = 0; 591 */
592 int ret; 592 *flags = (pcdev->platform_flags & PXA_CAMERA_MASTER ?
593 SOCAM_MASTER : SOCAM_SLAVE) |
594 SOCAM_HSYNC_ACTIVE_HIGH |
595 SOCAM_HSYNC_ACTIVE_LOW |
596 SOCAM_VSYNC_ACTIVE_HIGH |
597 SOCAM_VSYNC_ACTIVE_LOW |
598 SOCAM_PCLK_SAMPLE_RISING |
599 SOCAM_PCLK_SAMPLE_FALLING;
593 600
594 /* If requested data width is supported by the platform, use it */ 601 /* If requested data width is supported by the platform, use it */
595 switch (icd->cached_datawidth) { 602 switch (buswidth) {
596 case 10: 603 case 10:
597 if (pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_10) 604 if (!(pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_10))
598 datawidth = IS_DATAWIDTH_10; 605 return -EINVAL;
606 *flags |= SOCAM_DATAWIDTH_10;
599 break; 607 break;
600 case 9: 608 case 9:
601 if (pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_9) 609 if (!(pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_9))
602 datawidth = IS_DATAWIDTH_9; 610 return -EINVAL;
611 *flags |= SOCAM_DATAWIDTH_9;
603 break; 612 break;
604 case 8: 613 case 8:
605 if (pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_8) 614 if (!(pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_8))
606 datawidth = IS_DATAWIDTH_8; 615 return -EINVAL;
616 *flags |= SOCAM_DATAWIDTH_8;
607 } 617 }
608 if (!datawidth) 618
619 return 0;
620}
621
622static int pxa_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
623{
624 struct soc_camera_host *ici =
625 to_soc_camera_host(icd->dev.parent);
626 struct pxa_camera_dev *pcdev = ici->priv;
627 unsigned long dw, bpp, bus_flags, camera_flags, common_flags;
628 u32 cicr0, cicr4 = 0;
629 int ret = test_platform_param(pcdev, icd->buswidth, &bus_flags);
630
631 if (ret < 0)
632 return ret;
633
634 camera_flags = icd->ops->query_bus_param(icd);
635
636 common_flags = soc_camera_bus_param_compatible(camera_flags, bus_flags);
637 if (!common_flags)
609 return -EINVAL; 638 return -EINVAL;
610 639
611 ret = icd->ops->set_capture_format(icd, pixfmt, rect, 640 /* Make choises, based on platform preferences */
612 datawidth | 641 if ((common_flags & SOCAM_HSYNC_ACTIVE_HIGH) &&
613 (pcdev->platform_flags & PXA_CAMERA_MASTER ? 642 (common_flags & SOCAM_HSYNC_ACTIVE_LOW)) {
614 IS_MASTER : 0) | 643 if (pcdev->platform_flags & PXA_CAMERA_HSP)
615 (pcdev->platform_flags & PXA_CAMERA_HSP ? 644 common_flags &= ~SOCAM_HSYNC_ACTIVE_HIGH;
616 0 : IS_HSYNC_ACTIVE_HIGH) | 645 else
617 (pcdev->platform_flags & PXA_CAMERA_VSP ? 646 common_flags &= ~SOCAM_HSYNC_ACTIVE_LOW;
618 0 : IS_VSYNC_ACTIVE_HIGH) | 647 }
619 (pcdev->platform_flags & PXA_CAMERA_PCP ? 648
620 0 : IS_PCLK_SAMPLE_RISING)); 649 if ((common_flags & SOCAM_VSYNC_ACTIVE_HIGH) &&
650 (common_flags & SOCAM_VSYNC_ACTIVE_LOW)) {
651 if (pcdev->platform_flags & PXA_CAMERA_VSP)
652 common_flags &= ~SOCAM_VSYNC_ACTIVE_HIGH;
653 else
654 common_flags &= ~SOCAM_VSYNC_ACTIVE_LOW;
655 }
656
657 if ((common_flags & SOCAM_PCLK_SAMPLE_RISING) &&
658 (common_flags & SOCAM_PCLK_SAMPLE_FALLING)) {
659 if (pcdev->platform_flags & PXA_CAMERA_PCP)
660 common_flags &= ~SOCAM_PCLK_SAMPLE_RISING;
661 else
662 common_flags &= ~SOCAM_PCLK_SAMPLE_FALLING;
663 }
664
665 ret = icd->ops->set_bus_param(icd, common_flags);
621 if (ret < 0) 666 if (ret < 0)
622 return ret; 667 return ret;
623 668
624 /* Datawidth is now guaranteed to be equal to one of the three values. 669 /* Datawidth is now guaranteed to be equal to one of the three values.
625 * We fix bit-per-pixel equal to data-width... */ 670 * We fix bit-per-pixel equal to data-width... */
626 switch (datawidth) { 671 switch (common_flags & SOCAM_DATAWIDTH_MASK) {
627 case IS_DATAWIDTH_10: 672 case SOCAM_DATAWIDTH_10:
628 icd->cached_datawidth = 10; 673 icd->buswidth = 10;
629 dw = 4; 674 dw = 4;
630 bpp = 0x40; 675 bpp = 0x40;
631 break; 676 break;
632 case IS_DATAWIDTH_9: 677 case SOCAM_DATAWIDTH_9:
633 icd->cached_datawidth = 9; 678 icd->buswidth = 9;
634 dw = 3; 679 dw = 3;
635 bpp = 0x20; 680 bpp = 0x20;
636 break; 681 break;
637 default: 682 default:
638 /* Actually it can only be 8 now, 683 /* Actually it can only be 8 now,
639 * default is just to silence compiler warnings */ 684 * default is just to silence compiler warnings */
640 case IS_DATAWIDTH_8: 685 case SOCAM_DATAWIDTH_8:
641 icd->cached_datawidth = 8; 686 icd->buswidth = 8;
642 dw = 2; 687 dw = 2;
643 bpp = 0; 688 bpp = 0;
644 } 689 }
@@ -647,19 +692,19 @@ static int pxa_camera_set_capture_format(struct soc_camera_device *icd,
647 cicr4 |= CICR4_PCLK_EN; 692 cicr4 |= CICR4_PCLK_EN;
648 if (pcdev->platform_flags & PXA_CAMERA_MCLK_EN) 693 if (pcdev->platform_flags & PXA_CAMERA_MCLK_EN)
649 cicr4 |= CICR4_MCLK_EN; 694 cicr4 |= CICR4_MCLK_EN;
650 if (pcdev->platform_flags & PXA_CAMERA_PCP) 695 if (common_flags & SOCAM_PCLK_SAMPLE_FALLING)
651 cicr4 |= CICR4_PCP; 696 cicr4 |= CICR4_PCP;
652 if (pcdev->platform_flags & PXA_CAMERA_HSP) 697 if (common_flags & SOCAM_HSYNC_ACTIVE_LOW)
653 cicr4 |= CICR4_HSP; 698 cicr4 |= CICR4_HSP;
654 if (pcdev->platform_flags & PXA_CAMERA_VSP) 699 if (common_flags & SOCAM_VSYNC_ACTIVE_LOW)
655 cicr4 |= CICR4_VSP; 700 cicr4 |= CICR4_VSP;
656 701
657 cicr0 = CICR0; 702 cicr0 = CICR0;
658 if (cicr0 & CICR0_ENB) 703 if (cicr0 & CICR0_ENB)
659 CICR0 = cicr0 & ~CICR0_ENB; 704 CICR0 = cicr0 & ~CICR0_ENB;
660 CICR1 = CICR1_PPL_VAL(rect->width - 1) | bpp | dw; 705 CICR1 = CICR1_PPL_VAL(icd->width - 1) | bpp | dw;
661 CICR2 = 0; 706 CICR2 = 0;
662 CICR3 = CICR3_LPF_VAL(rect->height - 1) | 707 CICR3 = CICR3_LPF_VAL(icd->height - 1) |
663 CICR3_BFW_VAL(min((unsigned short)255, icd->y_skip_top)); 708 CICR3_BFW_VAL(min((unsigned short)255, icd->y_skip_top));
664 CICR4 = mclk_get_divisor(pcdev) | cicr4; 709 CICR4 = mclk_get_divisor(pcdev) | cicr4;
665 710
@@ -671,7 +716,29 @@ static int pxa_camera_set_capture_format(struct soc_camera_device *icd,
671 return 0; 716 return 0;
672} 717}
673 718
674static int pxa_camera_try_fmt_cap(struct soc_camera_host *ici, 719static int pxa_camera_try_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
720{
721 struct soc_camera_host *ici =
722 to_soc_camera_host(icd->dev.parent);
723 struct pxa_camera_dev *pcdev = ici->priv;
724 unsigned long bus_flags, camera_flags;
725 int ret = test_platform_param(pcdev, icd->buswidth, &bus_flags);
726
727 if (ret < 0)
728 return ret;
729
730 camera_flags = icd->ops->query_bus_param(icd);
731
732 return soc_camera_bus_param_compatible(camera_flags, bus_flags) ? 0 : -EINVAL;
733}
734
735static int pxa_camera_set_fmt_cap(struct soc_camera_device *icd,
736 __u32 pixfmt, struct v4l2_rect *rect)
737{
738 return icd->ops->set_fmt_cap(icd, pixfmt, rect);
739}
740
741static int pxa_camera_try_fmt_cap(struct soc_camera_device *icd,
675 struct v4l2_format *f) 742 struct v4l2_format *f)
676{ 743{
677 /* limit to pxa hardware capabilities */ 744 /* limit to pxa hardware capabilities */
@@ -685,7 +752,8 @@ static int pxa_camera_try_fmt_cap(struct soc_camera_host *ici,
685 f->fmt.pix.width = 2048; 752 f->fmt.pix.width = 2048;
686 f->fmt.pix.width &= ~0x01; 753 f->fmt.pix.width &= ~0x01;
687 754
688 return 0; 755 /* limit to sensor capabilities */
756 return icd->ops->try_fmt_cap(icd, f);
689} 757}
690 758
691static int pxa_camera_reqbufs(struct soc_camera_file *icf, 759static int pxa_camera_reqbufs(struct soc_camera_file *icf,
@@ -742,11 +810,13 @@ static struct soc_camera_host pxa_soc_camera_host = {
742 .add = pxa_camera_add_device, 810 .add = pxa_camera_add_device,
743 .remove = pxa_camera_remove_device, 811 .remove = pxa_camera_remove_device,
744 .msize = sizeof(struct pxa_buffer), 812 .msize = sizeof(struct pxa_buffer),
745 .set_capture_format = pxa_camera_set_capture_format, 813 .set_fmt_cap = pxa_camera_set_fmt_cap,
746 .try_fmt_cap = pxa_camera_try_fmt_cap, 814 .try_fmt_cap = pxa_camera_try_fmt_cap,
747 .reqbufs = pxa_camera_reqbufs, 815 .reqbufs = pxa_camera_reqbufs,
748 .poll = pxa_camera_poll, 816 .poll = pxa_camera_poll,
749 .querycap = pxa_camera_querycap, 817 .querycap = pxa_camera_querycap,
818 .try_bus_param = pxa_camera_try_bus_param,
819 .set_bus_param = pxa_camera_set_bus_param,
750}; 820};
751 821
752static int pxa_camera_probe(struct platform_device *pdev) 822static int pxa_camera_probe(struct platform_device *pdev)
@@ -782,8 +852,8 @@ static int pxa_camera_probe(struct platform_device *pdev)
782 852
783 pcdev->pdata = pdev->dev.platform_data; 853 pcdev->pdata = pdev->dev.platform_data;
784 pcdev->platform_flags = pcdev->pdata->flags; 854 pcdev->platform_flags = pcdev->pdata->flags;
785 if (!pcdev->platform_flags & (PXA_CAMERA_DATAWIDTH_8 | 855 if (!(pcdev->platform_flags & (PXA_CAMERA_DATAWIDTH_8 |
786 PXA_CAMERA_DATAWIDTH_9 | PXA_CAMERA_DATAWIDTH_10)) { 856 PXA_CAMERA_DATAWIDTH_9 | PXA_CAMERA_DATAWIDTH_10))) {
787 /* Platform hasn't set available data widths. This is bad. 857 /* Platform hasn't set available data widths. This is bad.
788 * Warn and use a default. */ 858 * Warn and use a default. */
789 dev_warn(&pdev->dev, "WARNING! Platform hasn't set available " 859 dev_warn(&pdev->dev, "WARNING! Platform hasn't set available "
diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c
index 322f837bcfea..bd8677cb1cab 100644
--- a/drivers/media/video/soc_camera.c
+++ b/drivers/media/video/soc_camera.c
@@ -75,12 +75,13 @@ static int soc_camera_try_fmt_cap(struct file *file, void *priv,
75 return -EINVAL; 75 return -EINVAL;
76 } 76 }
77 77
78 /* limit to host capabilities */ 78 /* test physical bus parameters */
79 ret = ici->try_fmt_cap(ici, f); 79 ret = ici->try_bus_param(icd, f->fmt.pix.pixelformat);
80 if (ret)
81 return ret;
80 82
81 /* limit to sensor capabilities */ 83 /* limit format to hardware capabilities */
82 if (!ret) 84 ret = ici->try_fmt_cap(icd, f);
83 ret = icd->ops->try_fmt_cap(icd, f);
84 85
85 /* calculate missing fields */ 86 /* calculate missing fields */
86 f->fmt.pix.field = field; 87 f->fmt.pix.field = field;
@@ -344,8 +345,8 @@ static int soc_camera_s_fmt_cap(struct file *file, void *priv,
344 if (!data_fmt) 345 if (!data_fmt)
345 return -EINVAL; 346 return -EINVAL;
346 347
347 /* cached_datawidth may be further adjusted by the ici */ 348 /* buswidth may be further adjusted by the ici */
348 icd->cached_datawidth = data_fmt->depth; 349 icd->buswidth = data_fmt->depth;
349 350
350 ret = soc_camera_try_fmt_cap(file, icf, f); 351 ret = soc_camera_try_fmt_cap(file, icf, f);
351 if (ret < 0) 352 if (ret < 0)
@@ -355,22 +356,23 @@ static int soc_camera_s_fmt_cap(struct file *file, void *priv,
355 rect.top = icd->y_current; 356 rect.top = icd->y_current;
356 rect.width = f->fmt.pix.width; 357 rect.width = f->fmt.pix.width;
357 rect.height = f->fmt.pix.height; 358 rect.height = f->fmt.pix.height;
358 ret = ici->set_capture_format(icd, f->fmt.pix.pixelformat, &rect); 359 ret = ici->set_fmt_cap(icd, f->fmt.pix.pixelformat, &rect);
360 if (ret < 0)
361 return ret;
359 362
360 if (!ret) { 363 icd->current_fmt = data_fmt;
361 icd->current_fmt = data_fmt; 364 icd->width = rect.width;
362 icd->width = rect.width; 365 icd->height = rect.height;
363 icd->height = rect.height; 366 icf->vb_vidq.field = f->fmt.pix.field;
364 icf->vb_vidq.field = f->fmt.pix.field; 367 if (V4L2_BUF_TYPE_VIDEO_CAPTURE != f->type)
365 if (V4L2_BUF_TYPE_VIDEO_CAPTURE != f->type) 368 dev_warn(&icd->dev, "Attention! Wrong buf-type %d\n",
366 dev_warn(&icd->dev, "Attention! Wrong buf-type %d\n", 369 f->type);
367 f->type);
368
369 dev_dbg(&icd->dev, "set width: %d height: %d\n",
370 icd->width, icd->height);
371 }
372 370
373 return ret; 371 dev_dbg(&icd->dev, "set width: %d height: %d\n",
372 icd->width, icd->height);
373
374 /* set physical bus parameters */
375 return ici->set_bus_param(icd, f->fmt.pix.pixelformat);
374} 376}
375 377
376static int soc_camera_enum_fmt_cap(struct file *file, void *priv, 378static int soc_camera_enum_fmt_cap(struct file *file, void *priv,
@@ -577,7 +579,7 @@ static int soc_camera_s_crop(struct file *file, void *fh,
577 if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) 579 if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
578 return -EINVAL; 580 return -EINVAL;
579 581
580 ret = ici->set_capture_format(icd, 0, &a->c); 582 ret = ici->set_fmt_cap(icd, 0, &a->c);
581 if (!ret) { 583 if (!ret) {
582 icd->width = a->c.width; 584 icd->width = a->c.width;
583 icd->height = a->c.height; 585 icd->height = a->c.height;
@@ -860,9 +862,6 @@ int soc_camera_device_register(struct soc_camera_device *icd)
860 862
861 icd->dev.release = dummy_release; 863 icd->dev.release = dummy_release;
862 864
863 if (icd->ops->get_datawidth)
864 icd->cached_datawidth = icd->ops->get_datawidth(icd);
865
866 return scan_add_device(icd); 865 return scan_add_device(icd);
867} 866}
868EXPORT_SYMBOL(soc_camera_device_register); 867EXPORT_SYMBOL(soc_camera_device_register);
diff --git a/include/media/soc_camera.h b/include/media/soc_camera.h
index c886b1e64872..3e48e435b21a 100644
--- a/include/media/soc_camera.h
+++ b/include/media/soc_camera.h
@@ -34,7 +34,7 @@ struct soc_camera_device {
34 unsigned short exposure; 34 unsigned short exposure;
35 unsigned char iface; /* Host number */ 35 unsigned char iface; /* Host number */
36 unsigned char devnum; /* Device number per host */ 36 unsigned char devnum; /* Device number per host */
37 unsigned char cached_datawidth; /* See comment in .c */ 37 unsigned char buswidth; /* See comment in .c */
38 struct soc_camera_ops *ops; 38 struct soc_camera_ops *ops;
39 struct video_device *vdev; 39 struct video_device *vdev;
40 const struct soc_camera_data_format *current_fmt; 40 const struct soc_camera_data_format *current_fmt;
@@ -61,11 +61,13 @@ struct soc_camera_host {
61 char *drv_name; 61 char *drv_name;
62 int (*add)(struct soc_camera_device *); 62 int (*add)(struct soc_camera_device *);
63 void (*remove)(struct soc_camera_device *); 63 void (*remove)(struct soc_camera_device *);
64 int (*set_capture_format)(struct soc_camera_device *, __u32, 64 int (*set_fmt_cap)(struct soc_camera_device *, __u32,
65 struct v4l2_rect *); 65 struct v4l2_rect *);
66 int (*try_fmt_cap)(struct soc_camera_host *, struct v4l2_format *); 66 int (*try_fmt_cap)(struct soc_camera_device *, struct v4l2_format *);
67 int (*reqbufs)(struct soc_camera_file *, struct v4l2_requestbuffers *); 67 int (*reqbufs)(struct soc_camera_file *, struct v4l2_requestbuffers *);
68 int (*querycap)(struct soc_camera_host *, struct v4l2_capability *); 68 int (*querycap)(struct soc_camera_host *, struct v4l2_capability *);
69 int (*try_bus_param)(struct soc_camera_device *, __u32);
70 int (*set_bus_param)(struct soc_camera_device *, __u32);
69 unsigned int (*poll)(struct file *, poll_table *); 71 unsigned int (*poll)(struct file *, poll_table *);
70}; 72};
71 73
@@ -108,9 +110,11 @@ struct soc_camera_ops {
108 int (*release)(struct soc_camera_device *); 110 int (*release)(struct soc_camera_device *);
109 int (*start_capture)(struct soc_camera_device *); 111 int (*start_capture)(struct soc_camera_device *);
110 int (*stop_capture)(struct soc_camera_device *); 112 int (*stop_capture)(struct soc_camera_device *);
111 int (*set_capture_format)(struct soc_camera_device *, __u32, 113 int (*set_fmt_cap)(struct soc_camera_device *, __u32,
112 struct v4l2_rect *, unsigned int); 114 struct v4l2_rect *);
113 int (*try_fmt_cap)(struct soc_camera_device *, struct v4l2_format *); 115 int (*try_fmt_cap)(struct soc_camera_device *, struct v4l2_format *);
116 unsigned long (*query_bus_param)(struct soc_camera_device *);
117 int (*set_bus_param)(struct soc_camera_device *, unsigned long);
114 int (*get_chip_id)(struct soc_camera_device *, 118 int (*get_chip_id)(struct soc_camera_device *,
115 struct v4l2_chip_ident *); 119 struct v4l2_chip_ident *);
116#ifdef CONFIG_VIDEO_ADV_DEBUG 120#ifdef CONFIG_VIDEO_ADV_DEBUG
@@ -123,7 +127,6 @@ struct soc_camera_ops {
123 int (*set_control)(struct soc_camera_device *, struct v4l2_control *); 127 int (*set_control)(struct soc_camera_device *, struct v4l2_control *);
124 const struct v4l2_queryctrl *controls; 128 const struct v4l2_queryctrl *controls;
125 int num_controls; 129 int num_controls;
126 unsigned int(*get_datawidth)(struct soc_camera_device *icd);
127}; 130};
128 131
129static inline struct v4l2_queryctrl const *soc_camera_find_qctrl( 132static inline struct v4l2_queryctrl const *soc_camera_find_qctrl(
@@ -138,12 +141,33 @@ static inline struct v4l2_queryctrl const *soc_camera_find_qctrl(
138 return NULL; 141 return NULL;
139} 142}
140 143
141#define IS_MASTER (1<<0) 144#define SOCAM_MASTER (1 << 0)
142#define IS_HSYNC_ACTIVE_HIGH (1<<1) 145#define SOCAM_SLAVE (1 << 1)
143#define IS_VSYNC_ACTIVE_HIGH (1<<2) 146#define SOCAM_HSYNC_ACTIVE_HIGH (1 << 2)
144#define IS_DATAWIDTH_8 (1<<3) 147#define SOCAM_HSYNC_ACTIVE_LOW (1 << 3)
145#define IS_DATAWIDTH_9 (1<<4) 148#define SOCAM_VSYNC_ACTIVE_HIGH (1 << 4)
146#define IS_DATAWIDTH_10 (1<<5) 149#define SOCAM_VSYNC_ACTIVE_LOW (1 << 5)
147#define IS_PCLK_SAMPLE_RISING (1<<6) 150#define SOCAM_DATAWIDTH_8 (1 << 6)
151#define SOCAM_DATAWIDTH_9 (1 << 7)
152#define SOCAM_DATAWIDTH_10 (1 << 8)
153#define SOCAM_PCLK_SAMPLE_RISING (1 << 9)
154#define SOCAM_PCLK_SAMPLE_FALLING (1 << 10)
155
156#define SOCAM_DATAWIDTH_MASK (SOCAM_DATAWIDTH_8 | SOCAM_DATAWIDTH_9 | \
157 SOCAM_DATAWIDTH_10)
158
159static inline unsigned long soc_camera_bus_param_compatible(
160 unsigned long camera_flags, unsigned long bus_flags)
161{
162 unsigned long common_flags, hsync, vsync, pclk;
163
164 common_flags = camera_flags & bus_flags;
165
166 hsync = common_flags & (SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_LOW);
167 vsync = common_flags & (SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_LOW);
168 pclk = common_flags & (SOCAM_PCLK_SAMPLE_RISING | SOCAM_PCLK_SAMPLE_FALLING);
169
170 return (!hsync || !vsync || !pclk) ? 0 : common_flags;
171}
148 172
149#endif 173#endif