aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuennadi Liakhovetski <g.liakhovetski@gmx.de>2009-08-25 10:46:52 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2009-09-18 23:18:55 -0400
commit904078f16fab80ed1f6adf7f6a0bd166d6b58d07 (patch)
treefa9e2083330cbab197add5e99a6b4afb12c2fbde
parenta12222a73e7a9efd927eb99d1dec1cedc9887e0a (diff)
V4L/DVB (12522): sh-mobile-ceu-camera: implement host-side cropping
Not all video capture devices can configure arbitrary cropping, whereas the CEU module on SuperH CPUs can crop with pixel precision. However, we want to use camera cropping if possible to save bandwidth and increase the frame-rate. This patch verifies whether the camera managed to crop exactly the requested rectangle, and if not, uses host-side cropping. To be able to crop on CEU we have to preserve camera rectangle too, for which the host_priv member in struct soc_camera_device is used. We now allocate memory dynamically, thus we have to use the .put_formats() method from struct soc_camera_host_ops to free it. Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r--drivers/media/video/sh_mobile_ceu_camera.c309
1 files changed, 259 insertions, 50 deletions
diff --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c
index c0dc4a1e8e52..3fee7c01fd57 100644
--- a/drivers/media/video/sh_mobile_ceu_camera.c
+++ b/drivers/media/video/sh_mobile_ceu_camera.c
@@ -92,10 +92,17 @@ struct sh_mobile_ceu_dev {
92 spinlock_t lock; 92 spinlock_t lock;
93 struct list_head capture; 93 struct list_head capture;
94 struct videobuf_buffer *active; 94 struct videobuf_buffer *active;
95 int is_interlaced;
96 95
97 struct sh_mobile_ceu_info *pdata; 96 struct sh_mobile_ceu_info *pdata;
98 97
98 unsigned int is_interlaced:1;
99 unsigned int image_mode:1;
100 unsigned int is_16bit:1;
101};
102
103struct sh_mobile_ceu_cam {
104 struct v4l2_rect camera_rect;
105 const struct soc_camera_data_format *extra_fmt;
99 const struct soc_camera_data_format *camera_fmt; 106 const struct soc_camera_data_format *camera_fmt;
100}; 107};
101 108
@@ -428,14 +435,101 @@ static void sh_mobile_ceu_remove_device(struct soc_camera_device *icd)
428 pcdev->icd = NULL; 435 pcdev->icd = NULL;
429} 436}
430 437
438static void sh_mobile_ceu_set_rect(struct soc_camera_device *icd,
439 struct v4l2_rect *rect)
440{
441 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
442 struct sh_mobile_ceu_cam *cam = icd->host_priv;
443 struct sh_mobile_ceu_dev *pcdev = ici->priv;
444 int width, height, cfszr_width, cdwdr_width;
445 unsigned int left_offset, top_offset;
446 u32 camor;
447
448 if (rect->left > cam->camera_rect.left) {
449 left_offset = rect->left - cam->camera_rect.left;
450 } else {
451 left_offset = 0;
452 rect->left = cam->camera_rect.left;
453 }
454
455 if (rect->top > cam->camera_rect.top) {
456 top_offset = rect->top - cam->camera_rect.top;
457 } else {
458 top_offset = 0;
459 rect->top = cam->camera_rect.top;
460 }
461
462 dev_dbg(&icd->dev, "Offsets %u:%u\n", left_offset, top_offset);
463
464 if (pcdev->image_mode) {
465 width = rect->width;
466 if (!pcdev->is_16bit)
467 width *= 2;
468 cfszr_width = cdwdr_width = rect->width;
469 } else {
470 width = rect->width *
471 ((icd->current_fmt->depth + 7) >> 3);
472 width = pcdev->is_16bit ? width / 2 : width;
473 cfszr_width = pcdev->is_16bit ? width : width / 2;
474 cdwdr_width = pcdev->is_16bit ? width * 2 : width;
475 }
476
477 height = rect->height;
478 if (pcdev->is_interlaced) {
479 height /= 2;
480 cdwdr_width *= 2;
481 }
482
483 camor = left_offset | (top_offset << 16);
484 ceu_write(pcdev, CAMOR, camor);
485 ceu_write(pcdev, CAPWR, (height << 16) | width);
486 ceu_write(pcdev, CFSZR, (height << 16) | cfszr_width);
487 ceu_write(pcdev, CDWDR, cdwdr_width);
488}
489
490static u32 capture_save_reset(struct sh_mobile_ceu_dev *pcdev)
491{
492 u32 capsr = ceu_read(pcdev, CAPSR);
493 ceu_write(pcdev, CAPSR, 1 << 16); /* reset, stop capture */
494 return capsr;
495}
496
497static void capture_restore(struct sh_mobile_ceu_dev *pcdev, u32 capsr)
498{
499 unsigned long timeout = jiffies + 10 * HZ;
500
501 /*
502 * Wait until the end of the current frame. It can take a long time,
503 * but if it has been aborted by a CAPSR reset, it shoule exit sooner.
504 */
505 while ((ceu_read(pcdev, CSTSR) & 1) && time_before(jiffies, timeout))
506 msleep(1);
507
508 if (time_after(jiffies, timeout)) {
509 dev_err(pcdev->ici.v4l2_dev.dev,
510 "Timeout waiting for frame end! Interface problem?\n");
511 return;
512 }
513
514 /* Wait until reset clears, this shall not hang... */
515 while (ceu_read(pcdev, CAPSR) & (1 << 16))
516 udelay(10);
517
518 /* Anything to restore? */
519 if (capsr & ~(1 << 16))
520 ceu_write(pcdev, CAPSR, capsr);
521}
522
431static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd, 523static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd,
432 __u32 pixfmt) 524 __u32 pixfmt)
433{ 525{
434 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); 526 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
435 struct sh_mobile_ceu_dev *pcdev = ici->priv; 527 struct sh_mobile_ceu_dev *pcdev = ici->priv;
436 int ret, buswidth, width, height, cfszr_width, cdwdr_width; 528 int ret;
437 unsigned long camera_flags, common_flags, value; 529 unsigned long camera_flags, common_flags, value;
438 int yuv_mode, yuv_lineskip; 530 int yuv_lineskip;
531 struct sh_mobile_ceu_cam *cam = icd->host_priv;
532 u32 capsr = capture_save_reset(pcdev);
439 533
440 camera_flags = icd->ops->query_bus_param(icd); 534 camera_flags = icd->ops->query_bus_param(icd);
441 common_flags = soc_camera_bus_param_compatible(camera_flags, 535 common_flags = soc_camera_bus_param_compatible(camera_flags,
@@ -449,10 +543,10 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd,
449 543
450 switch (common_flags & SOCAM_DATAWIDTH_MASK) { 544 switch (common_flags & SOCAM_DATAWIDTH_MASK) {
451 case SOCAM_DATAWIDTH_8: 545 case SOCAM_DATAWIDTH_8:
452 buswidth = 8; 546 pcdev->is_16bit = 0;
453 break; 547 break;
454 case SOCAM_DATAWIDTH_16: 548 case SOCAM_DATAWIDTH_16:
455 buswidth = 16; 549 pcdev->is_16bit = 1;
456 break; 550 break;
457 default: 551 default:
458 return -EINVAL; 552 return -EINVAL;
@@ -462,7 +556,7 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd,
462 ceu_write(pcdev, CRCMPR, 0); 556 ceu_write(pcdev, CRCMPR, 0);
463 557
464 value = 0x00000010; /* data fetch by default */ 558 value = 0x00000010; /* data fetch by default */
465 yuv_mode = yuv_lineskip = 0; 559 pcdev->image_mode = yuv_lineskip = 0;
466 560
467 switch (icd->current_fmt->fourcc) { 561 switch (icd->current_fmt->fourcc) {
468 case V4L2_PIX_FMT_NV12: 562 case V4L2_PIX_FMT_NV12:
@@ -471,8 +565,8 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd,
471 /* fall-through */ 565 /* fall-through */
472 case V4L2_PIX_FMT_NV16: 566 case V4L2_PIX_FMT_NV16:
473 case V4L2_PIX_FMT_NV61: 567 case V4L2_PIX_FMT_NV61:
474 yuv_mode = 1; 568 pcdev->image_mode = 1;
475 switch (pcdev->camera_fmt->fourcc) { 569 switch (cam->camera_fmt->fourcc) {
476 case V4L2_PIX_FMT_UYVY: 570 case V4L2_PIX_FMT_UYVY:
477 value = 0x00000000; /* Cb0, Y0, Cr0, Y1 */ 571 value = 0x00000000; /* Cb0, Y0, Cr0, Y1 */
478 break; 572 break;
@@ -496,36 +590,16 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd,
496 590
497 value |= common_flags & SOCAM_VSYNC_ACTIVE_LOW ? 1 << 1 : 0; 591 value |= common_flags & SOCAM_VSYNC_ACTIVE_LOW ? 1 << 1 : 0;
498 value |= common_flags & SOCAM_HSYNC_ACTIVE_LOW ? 1 << 0 : 0; 592 value |= common_flags & SOCAM_HSYNC_ACTIVE_LOW ? 1 << 0 : 0;
499 value |= buswidth == 16 ? 1 << 12 : 0; 593 value |= pcdev->is_16bit ? 1 << 12 : 0;
500 ceu_write(pcdev, CAMCR, value); 594 ceu_write(pcdev, CAMCR, value);
501 595
502 ceu_write(pcdev, CAPCR, 0x00300000); 596 ceu_write(pcdev, CAPCR, 0x00300000);
503 ceu_write(pcdev, CAIFR, pcdev->is_interlaced ? 0x101 : 0); 597 ceu_write(pcdev, CAIFR, pcdev->is_interlaced ? 0x101 : 0);
504 598
505 mdelay(1); 599 mdelay(1);
600 sh_mobile_ceu_set_rect(icd, &icd->rect_current);
506 601
507 if (yuv_mode) {
508 width = icd->rect_current.width * 2;
509 width = buswidth == 16 ? width / 2 : width;
510 cfszr_width = cdwdr_width = icd->rect_current.width;
511 } else {
512 width = icd->rect_current.width *
513 ((icd->current_fmt->depth + 7) >> 3);
514 width = buswidth == 16 ? width / 2 : width;
515 cfszr_width = buswidth == 8 ? width / 2 : width;
516 cdwdr_width = buswidth == 16 ? width * 2 : width;
517 }
518
519 height = icd->rect_current.height;
520 if (pcdev->is_interlaced) {
521 height /= 2;
522 cdwdr_width *= 2;
523 }
524
525 ceu_write(pcdev, CAMOR, 0);
526 ceu_write(pcdev, CAPWR, (height << 16) | width);
527 ceu_write(pcdev, CFLCR, 0); /* no scaling */ 602 ceu_write(pcdev, CFLCR, 0); /* no scaling */
528 ceu_write(pcdev, CFSZR, (height << 16) | cfszr_width);
529 603
530 /* A few words about byte order (observed in Big Endian mode) 604 /* A few words about byte order (observed in Big Endian mode)
531 * 605 *
@@ -544,10 +618,16 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd,
544 value &= ~0x00000010; /* convert 4:2:2 -> 4:2:0 */ 618 value &= ~0x00000010; /* convert 4:2:2 -> 4:2:0 */
545 619
546 ceu_write(pcdev, CDOCR, value); 620 ceu_write(pcdev, CDOCR, value);
547
548 ceu_write(pcdev, CDWDR, cdwdr_width);
549 ceu_write(pcdev, CFWCR, 0); /* keep "datafetch firewall" disabled */ 621 ceu_write(pcdev, CFWCR, 0); /* keep "datafetch firewall" disabled */
550 622
623 dev_dbg(&icd->dev, "S_FMT successful for %c%c%c%c %ux%u@%u.%u\n",
624 pixfmt & 0xff, (pixfmt >> 8) & 0xff,
625 (pixfmt >> 16) & 0xff, (pixfmt >> 24) & 0xff,
626 icd->rect_current.width, icd->rect_current.height,
627 icd->rect_current.left, icd->rect_current.top);
628
629 capture_restore(pcdev, capsr);
630
551 /* not in bundle mode: skip CBDSR, CDAYR2, CDACR2, CDBYR2, CDBCR2 */ 631 /* not in bundle mode: skip CBDSR, CDAYR2, CDACR2, CDBYR2, CDBCR2 */
552 return 0; 632 return 0;
553} 633}
@@ -600,21 +680,32 @@ static int sh_mobile_ceu_get_formats(struct soc_camera_device *icd, int idx,
600 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); 680 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
601 int ret, k, n; 681 int ret, k, n;
602 int formats = 0; 682 int formats = 0;
683 struct sh_mobile_ceu_cam *cam;
603 684
604 ret = sh_mobile_ceu_try_bus_param(icd); 685 ret = sh_mobile_ceu_try_bus_param(icd);
605 if (ret < 0) 686 if (ret < 0)
606 return 0; 687 return 0;
607 688
689 if (!icd->host_priv) {
690 cam = kzalloc(sizeof(*cam), GFP_KERNEL);
691 if (!cam)
692 return -ENOMEM;
693
694 icd->host_priv = cam;
695 } else {
696 cam = icd->host_priv;
697 }
698
608 /* Beginning of a pass */ 699 /* Beginning of a pass */
609 if (!idx) 700 if (!idx)
610 icd->host_priv = NULL; 701 cam->extra_fmt = NULL;
611 702
612 switch (icd->formats[idx].fourcc) { 703 switch (icd->formats[idx].fourcc) {
613 case V4L2_PIX_FMT_UYVY: 704 case V4L2_PIX_FMT_UYVY:
614 case V4L2_PIX_FMT_VYUY: 705 case V4L2_PIX_FMT_VYUY:
615 case V4L2_PIX_FMT_YUYV: 706 case V4L2_PIX_FMT_YUYV:
616 case V4L2_PIX_FMT_YVYU: 707 case V4L2_PIX_FMT_YVYU:
617 if (icd->host_priv) 708 if (cam->extra_fmt)
618 goto add_single_format; 709 goto add_single_format;
619 710
620 /* 711 /*
@@ -626,7 +717,7 @@ static int sh_mobile_ceu_get_formats(struct soc_camera_device *icd, int idx,
626 * the host_priv pointer and check whether the format you're 717 * the host_priv pointer and check whether the format you're
627 * going to add now is already there. 718 * going to add now is already there.
628 */ 719 */
629 icd->host_priv = (void *)sh_mobile_ceu_formats; 720 cam->extra_fmt = (void *)sh_mobile_ceu_formats;
630 721
631 n = ARRAY_SIZE(sh_mobile_ceu_formats); 722 n = ARRAY_SIZE(sh_mobile_ceu_formats);
632 formats += n; 723 formats += n;
@@ -657,18 +748,130 @@ add_single_format:
657 return formats; 748 return formats;
658} 749}
659 750
751static void sh_mobile_ceu_put_formats(struct soc_camera_device *icd)
752{
753 kfree(icd->host_priv);
754 icd->host_priv = NULL;
755}
756
757static bool is_smaller(struct v4l2_rect *r1, struct v4l2_rect *r2)
758{
759 return r1->width < r2->width || r1->height < r2->height;
760}
761
660static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd, 762static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd,
661 struct v4l2_rect *rect) 763 struct v4l2_rect *rect)
662{ 764{
663 return icd->ops->set_crop(icd, rect); 765 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
766 struct sh_mobile_ceu_dev *pcdev = ici->priv;
767 struct v4l2_rect cam_rect = *rect;
768 struct sh_mobile_ceu_cam *cam = icd->host_priv;
769 unsigned short width, height;
770 u32 capsr;
771 int ret;
772
773 capsr = capture_save_reset(pcdev);
774 dev_dbg(&icd->dev, "CAPSR %x\n", capsr);
775
776 ret = icd->ops->set_crop(icd, &cam_rect);
777 if (!ret && !memcmp(rect, &cam_rect, sizeof(*rect))) {
778 dev_dbg(&icd->dev, "Camera S_CROP successful for %ux%u@%u.%u\n",
779 cam_rect.width, cam_rect.height,
780 cam_rect.left, cam_rect.top);
781 goto ceu_set_rect;
782 }
783
784 /* Try to fix cropping, that camera hasn't managed to do */
785 dev_dbg(&icd->dev, "Fix camera S_CROP %d for %ux%u@%u.%u\n",
786 ret, cam_rect.width, cam_rect.height,
787 cam_rect.left, cam_rect.top);
788
789 /*
790 * Popular special case - some cameras can only handle fixed sizes like
791 * QVGA, VGA,... Take care to avoid infinite loop.
792 */
793 width = max(cam_rect.width, 1) * 2;
794 height = max(cam_rect.height, 1) * 2;
795 while (!ret && is_smaller(&cam_rect, rect) &&
796 (icd->rect_max.width >= width &&
797 icd->rect_max.height >= height)) {
798 cam_rect.width = width;
799 cam_rect.height = height;
800
801 if (cam_rect.width + cam_rect.left >
802 icd->rect_max.width + icd->rect_max.left)
803 cam_rect.left = icd->rect_max.width +
804 icd->rect_max.left - cam_rect.width;
805
806 if (cam_rect.height + cam_rect.top >
807 icd->rect_max.height + icd->rect_max.top)
808 cam_rect.top = icd->rect_max.height +
809 icd->rect_max.top - cam_rect.height;
810
811 ret = icd->ops->set_crop(icd, &cam_rect);
812 dev_dbg(&icd->dev, "Camera S_CROP %d for %ux%u@%u.%u\n",
813 ret, cam_rect.width, cam_rect.height,
814 cam_rect.left, cam_rect.top);
815 width *= 2;
816 height *= 2;
817 }
818
819 /*
820 * If the camera failed to configure cropping, it should not modify the
821 * rectangle
822 */
823 if ((ret < 0 && is_smaller(&icd->rect_current, rect)) ||
824 is_smaller(&cam_rect, rect)) {
825 /*
826 * The camera failed to configure a suitable cropping,
827 * we cannot use the current rectangle, set to max
828 */
829 cam_rect = icd->rect_max;
830 ret = icd->ops->set_crop(icd, &cam_rect);
831 dev_dbg(&icd->dev, "Camera S_CROP %d for max %ux%u@%u.%u\n",
832 ret, cam_rect.width, cam_rect.height,
833 cam_rect.left, cam_rect.top);
834 if (ret < 0)
835 /* All failed, hopefully resume current capture */
836 goto resume_capture;
837 }
838
839 /* We now have a rectangle, larger than requested, let's crop */
840
841 /*
842 * We have to preserve camera rectangle between close() / open(),
843 * because soc-camera core calls .set_fmt() on each first open() with
844 * last before last close() _user_ rectangle, which can be different
845 * from camera rectangle.
846 */
847 dev_dbg(&icd->dev, "SH S_CROP from %ux%u@%u.%u to %ux%u@%u.%u\n",
848 cam_rect.width, cam_rect.height, cam_rect.left, cam_rect.top,
849 rect->width, rect->height, rect->left, rect->top);
850
851 ret = 0;
852
853ceu_set_rect:
854 cam->camera_rect = cam_rect;
855
856 /* Set CAMOR, CAPWR, CFSZR, take care of CDWDR */
857 if (pcdev->active)
858 capsr |= 1;
859 sh_mobile_ceu_set_rect(icd, rect);
860 capture_restore(pcdev, capsr);
861
862resume_capture:
863
864 /* Even if only camera cropping succeeded */
865 return ret;
664} 866}
665 867
666static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd, 868static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd,
667 struct v4l2_format *f) 869 struct v4l2_format *f)
668{ 870{
669 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); 871 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
670 struct sh_mobile_ceu_dev *pcdev = ici->priv; 872 struct sh_mobile_ceu_cam *cam = icd->host_priv;
671 __u32 pixfmt = f->fmt.pix.pixelformat; 873 struct v4l2_pix_format *pix = &f->fmt.pix;
874 __u32 pixfmt = pix->pixelformat;
672 const struct soc_camera_format_xlate *xlate; 875 const struct soc_camera_format_xlate *xlate;
673 int ret; 876 int ret;
674 877
@@ -678,13 +881,17 @@ static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd,
678 return -EINVAL; 881 return -EINVAL;
679 } 882 }
680 883
681 f->fmt.pix.pixelformat = xlate->cam_fmt->fourcc; 884 pix->pixelformat = xlate->cam_fmt->fourcc;
682 ret = v4l2_device_call_until_err(&ici->v4l2_dev, (__u32)icd, video, s_fmt, f); 885 ret = v4l2_device_call_until_err(&ici->v4l2_dev, (__u32)icd, video, s_fmt, f);
683 f->fmt.pix.pixelformat = pixfmt; 886 pix->pixelformat = pixfmt;
684 if (!ret) { 887 if (!ret) {
685 icd->buswidth = xlate->buswidth; 888 icd->buswidth = xlate->buswidth;
686 icd->current_fmt = xlate->host_fmt; 889 icd->current_fmt = xlate->host_fmt;
687 pcdev->camera_fmt = xlate->cam_fmt; 890 cam->camera_fmt = xlate->cam_fmt;
891 cam->camera_rect.width = pix->width;
892 cam->camera_rect.height = pix->height;
893 cam->camera_rect.left = icd->rect_current.left;
894 cam->camera_rect.top = icd->rect_current.top;
688 } 895 }
689 896
690 return ret; 897 return ret;
@@ -696,7 +903,8 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd,
696 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); 903 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
697 struct sh_mobile_ceu_dev *pcdev = ici->priv; 904 struct sh_mobile_ceu_dev *pcdev = ici->priv;
698 const struct soc_camera_format_xlate *xlate; 905 const struct soc_camera_format_xlate *xlate;
699 __u32 pixfmt = f->fmt.pix.pixelformat; 906 struct v4l2_pix_format *pix = &f->fmt.pix;
907 __u32 pixfmt = pix->pixelformat;
700 int ret; 908 int ret;
701 909
702 xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); 910 xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
@@ -707,27 +915,27 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd,
707 915
708 /* FIXME: calculate using depth and bus width */ 916 /* FIXME: calculate using depth and bus width */
709 917
710 v4l_bound_align_image(&f->fmt.pix.width, 2, 2560, 1, 918 v4l_bound_align_image(&pix->width, 2, 2560, 1,
711 &f->fmt.pix.height, 4, 1920, 2, 0); 919 &pix->height, 4, 1920, 2, 0);
712 920
713 f->fmt.pix.bytesperline = f->fmt.pix.width * 921 pix->bytesperline = pix->width *
714 DIV_ROUND_UP(xlate->host_fmt->depth, 8); 922 DIV_ROUND_UP(xlate->host_fmt->depth, 8);
715 f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; 923 pix->sizeimage = pix->height * pix->bytesperline;
716 924
717 f->fmt.pix.pixelformat = xlate->cam_fmt->fourcc; 925 pix->pixelformat = xlate->cam_fmt->fourcc;
718 926
719 /* limit to sensor capabilities */ 927 /* limit to sensor capabilities */
720 ret = v4l2_device_call_until_err(&ici->v4l2_dev, (__u32)icd, video, try_fmt, f); 928 ret = v4l2_device_call_until_err(&ici->v4l2_dev, (__u32)icd, video, try_fmt, f);
721 f->fmt.pix.pixelformat = pixfmt; 929 pix->pixelformat = pixfmt;
722 if (ret < 0) 930 if (ret < 0)
723 return ret; 931 return ret;
724 932
725 switch (f->fmt.pix.field) { 933 switch (pix->field) {
726 case V4L2_FIELD_INTERLACED: 934 case V4L2_FIELD_INTERLACED:
727 pcdev->is_interlaced = 1; 935 pcdev->is_interlaced = 1;
728 break; 936 break;
729 case V4L2_FIELD_ANY: 937 case V4L2_FIELD_ANY:
730 f->fmt.pix.field = V4L2_FIELD_NONE; 938 pix->field = V4L2_FIELD_NONE;
731 /* fall-through */ 939 /* fall-through */
732 case V4L2_FIELD_NONE: 940 case V4L2_FIELD_NONE:
733 pcdev->is_interlaced = 0; 941 pcdev->is_interlaced = 0;
@@ -856,6 +1064,7 @@ static struct soc_camera_host_ops sh_mobile_ceu_host_ops = {
856 .add = sh_mobile_ceu_add_device, 1064 .add = sh_mobile_ceu_add_device,
857 .remove = sh_mobile_ceu_remove_device, 1065 .remove = sh_mobile_ceu_remove_device,
858 .get_formats = sh_mobile_ceu_get_formats, 1066 .get_formats = sh_mobile_ceu_get_formats,
1067 .put_formats = sh_mobile_ceu_put_formats,
859 .set_crop = sh_mobile_ceu_set_crop, 1068 .set_crop = sh_mobile_ceu_set_crop,
860 .set_fmt = sh_mobile_ceu_set_fmt, 1069 .set_fmt = sh_mobile_ceu_set_fmt,
861 .try_fmt = sh_mobile_ceu_try_fmt, 1070 .try_fmt = sh_mobile_ceu_try_fmt,