aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/sh_mobile_ceu_camera.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/sh_mobile_ceu_camera.c')
-rw-r--r--drivers/media/video/sh_mobile_ceu_camera.c520
1 files changed, 319 insertions, 201 deletions
diff --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c
index 961e4484d721..d69363f0d8c9 100644
--- a/drivers/media/video/sh_mobile_ceu_camera.c
+++ b/drivers/media/video/sh_mobile_ceu_camera.c
@@ -38,6 +38,8 @@
38#include <media/soc_camera.h> 38#include <media/soc_camera.h>
39#include <media/sh_mobile_ceu.h> 39#include <media/sh_mobile_ceu.h>
40#include <media/videobuf-dma-contig.h> 40#include <media/videobuf-dma-contig.h>
41#include <media/v4l2-mediabus.h>
42#include <media/soc_mediabus.h>
41 43
42/* register offsets for sh7722 / sh7723 */ 44/* register offsets for sh7722 / sh7723 */
43 45
@@ -85,7 +87,7 @@
85/* per video frame buffer */ 87/* per video frame buffer */
86struct sh_mobile_ceu_buffer { 88struct sh_mobile_ceu_buffer {
87 struct videobuf_buffer vb; /* v4l buffer must be first */ 89 struct videobuf_buffer vb; /* v4l buffer must be first */
88 const struct soc_camera_data_format *fmt; 90 enum v4l2_mbus_pixelcode code;
89}; 91};
90 92
91struct sh_mobile_ceu_dev { 93struct sh_mobile_ceu_dev {
@@ -105,7 +107,8 @@ struct sh_mobile_ceu_dev {
105 107
106 u32 cflcr; 108 u32 cflcr;
107 109
108 unsigned int is_interlaced:1; 110 enum v4l2_field field;
111
109 unsigned int image_mode:1; 112 unsigned int image_mode:1;
110 unsigned int is_16bit:1; 113 unsigned int is_16bit:1;
111}; 114};
@@ -114,8 +117,8 @@ struct sh_mobile_ceu_cam {
114 struct v4l2_rect ceu_rect; 117 struct v4l2_rect ceu_rect;
115 unsigned int cam_width; 118 unsigned int cam_width;
116 unsigned int cam_height; 119 unsigned int cam_height;
117 const struct soc_camera_data_format *extra_fmt; 120 const struct soc_mbus_pixelfmt *extra_fmt;
118 const struct soc_camera_data_format *camera_fmt; 121 enum v4l2_mbus_pixelcode code;
119}; 122};
120 123
121static unsigned long make_bus_param(struct sh_mobile_ceu_dev *pcdev) 124static unsigned long make_bus_param(struct sh_mobile_ceu_dev *pcdev)
@@ -197,16 +200,19 @@ static int sh_mobile_ceu_videobuf_setup(struct videobuf_queue *vq,
197 struct soc_camera_device *icd = vq->priv_data; 200 struct soc_camera_device *icd = vq->priv_data;
198 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); 201 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
199 struct sh_mobile_ceu_dev *pcdev = ici->priv; 202 struct sh_mobile_ceu_dev *pcdev = ici->priv;
200 int bytes_per_pixel = (icd->current_fmt->depth + 7) >> 3; 203 int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
204 icd->current_fmt->host_fmt);
205
206 if (bytes_per_line < 0)
207 return bytes_per_line;
201 208
202 *size = PAGE_ALIGN(icd->user_width * icd->user_height * 209 *size = bytes_per_line * icd->user_height;
203 bytes_per_pixel);
204 210
205 if (0 == *count) 211 if (0 == *count)
206 *count = 2; 212 *count = 2;
207 213
208 if (pcdev->video_limit) { 214 if (pcdev->video_limit) {
209 while (*size * *count > pcdev->video_limit) 215 while (PAGE_ALIGN(*size) * *count > pcdev->video_limit)
210 (*count)--; 216 (*count)--;
211 } 217 }
212 218
@@ -249,10 +255,13 @@ static int sh_mobile_ceu_capture(struct sh_mobile_ceu_dev *pcdev)
249{ 255{
250 struct soc_camera_device *icd = pcdev->icd; 256 struct soc_camera_device *icd = pcdev->icd;
251 dma_addr_t phys_addr_top, phys_addr_bottom; 257 dma_addr_t phys_addr_top, phys_addr_bottom;
258 unsigned long top1, top2;
259 unsigned long bottom1, bottom2;
252 u32 status; 260 u32 status;
253 int ret = 0; 261 int ret = 0;
254 262
255 /* The hardware is _very_ picky about this sequence. Especially 263 /*
264 * The hardware is _very_ picky about this sequence. Especially
256 * the CEU_CETCR_MAGIC value. It seems like we need to acknowledge 265 * the CEU_CETCR_MAGIC value. It seems like we need to acknowledge
257 * several not-so-well documented interrupt sources in CETCR. 266 * several not-so-well documented interrupt sources in CETCR.
258 */ 267 */
@@ -276,25 +285,36 @@ static int sh_mobile_ceu_capture(struct sh_mobile_ceu_dev *pcdev)
276 if (!pcdev->active) 285 if (!pcdev->active)
277 return ret; 286 return ret;
278 287
288 if (V4L2_FIELD_INTERLACED_BT == pcdev->field) {
289 top1 = CDBYR;
290 top2 = CDBCR;
291 bottom1 = CDAYR;
292 bottom2 = CDACR;
293 } else {
294 top1 = CDAYR;
295 top2 = CDACR;
296 bottom1 = CDBYR;
297 bottom2 = CDBCR;
298 }
299
279 phys_addr_top = videobuf_to_dma_contig(pcdev->active); 300 phys_addr_top = videobuf_to_dma_contig(pcdev->active);
280 ceu_write(pcdev, CDAYR, phys_addr_top); 301 ceu_write(pcdev, top1, phys_addr_top);
281 if (pcdev->is_interlaced) { 302 if (V4L2_FIELD_NONE != pcdev->field) {
282 phys_addr_bottom = phys_addr_top + icd->user_width; 303 phys_addr_bottom = phys_addr_top + icd->user_width;
283 ceu_write(pcdev, CDBYR, phys_addr_bottom); 304 ceu_write(pcdev, bottom1, phys_addr_bottom);
284 } 305 }
285 306
286 switch (icd->current_fmt->fourcc) { 307 switch (icd->current_fmt->host_fmt->fourcc) {
287 case V4L2_PIX_FMT_NV12: 308 case V4L2_PIX_FMT_NV12:
288 case V4L2_PIX_FMT_NV21: 309 case V4L2_PIX_FMT_NV21:
289 case V4L2_PIX_FMT_NV16: 310 case V4L2_PIX_FMT_NV16:
290 case V4L2_PIX_FMT_NV61: 311 case V4L2_PIX_FMT_NV61:
291 phys_addr_top += icd->user_width * 312 phys_addr_top += icd->user_width *
292 icd->user_height; 313 icd->user_height;
293 ceu_write(pcdev, CDACR, phys_addr_top); 314 ceu_write(pcdev, top2, phys_addr_top);
294 if (pcdev->is_interlaced) { 315 if (V4L2_FIELD_NONE != pcdev->field) {
295 phys_addr_bottom = phys_addr_top + 316 phys_addr_bottom = phys_addr_top + icd->user_width;
296 icd->user_width; 317 ceu_write(pcdev, bottom2, phys_addr_bottom);
297 ceu_write(pcdev, CDBCR, phys_addr_bottom);
298 } 318 }
299 } 319 }
300 320
@@ -310,8 +330,13 @@ static int sh_mobile_ceu_videobuf_prepare(struct videobuf_queue *vq,
310{ 330{
311 struct soc_camera_device *icd = vq->priv_data; 331 struct soc_camera_device *icd = vq->priv_data;
312 struct sh_mobile_ceu_buffer *buf; 332 struct sh_mobile_ceu_buffer *buf;
333 int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
334 icd->current_fmt->host_fmt);
313 int ret; 335 int ret;
314 336
337 if (bytes_per_line < 0)
338 return bytes_per_line;
339
315 buf = container_of(vb, struct sh_mobile_ceu_buffer, vb); 340 buf = container_of(vb, struct sh_mobile_ceu_buffer, vb);
316 341
317 dev_dbg(icd->dev.parent, "%s (vb=0x%p) 0x%08lx %zd\n", __func__, 342 dev_dbg(icd->dev.parent, "%s (vb=0x%p) 0x%08lx %zd\n", __func__,
@@ -321,25 +346,27 @@ static int sh_mobile_ceu_videobuf_prepare(struct videobuf_queue *vq,
321 WARN_ON(!list_empty(&vb->queue)); 346 WARN_ON(!list_empty(&vb->queue));
322 347
323#ifdef DEBUG 348#ifdef DEBUG
324 /* This can be useful if you want to see if we actually fill 349 /*
325 * the buffer with something */ 350 * This can be useful if you want to see if we actually fill
351 * the buffer with something
352 */
326 memset((void *)vb->baddr, 0xaa, vb->bsize); 353 memset((void *)vb->baddr, 0xaa, vb->bsize);
327#endif 354#endif
328 355
329 BUG_ON(NULL == icd->current_fmt); 356 BUG_ON(NULL == icd->current_fmt);
330 357
331 if (buf->fmt != icd->current_fmt || 358 if (buf->code != icd->current_fmt->code ||
332 vb->width != icd->user_width || 359 vb->width != icd->user_width ||
333 vb->height != icd->user_height || 360 vb->height != icd->user_height ||
334 vb->field != field) { 361 vb->field != field) {
335 buf->fmt = icd->current_fmt; 362 buf->code = icd->current_fmt->code;
336 vb->width = icd->user_width; 363 vb->width = icd->user_width;
337 vb->height = icd->user_height; 364 vb->height = icd->user_height;
338 vb->field = field; 365 vb->field = field;
339 vb->state = VIDEOBUF_NEEDS_INIT; 366 vb->state = VIDEOBUF_NEEDS_INIT;
340 } 367 }
341 368
342 vb->size = vb->width * vb->height * ((buf->fmt->depth + 7) >> 3); 369 vb->size = vb->height * bytes_per_line;
343 if (0 != vb->baddr && vb->bsize < vb->size) { 370 if (0 != vb->baddr && vb->bsize < vb->size) {
344 ret = -EINVAL; 371 ret = -EINVAL;
345 goto out; 372 goto out;
@@ -456,6 +483,7 @@ static int sh_mobile_ceu_add_device(struct soc_camera_device *icd)
456{ 483{
457 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); 484 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
458 struct sh_mobile_ceu_dev *pcdev = ici->priv; 485 struct sh_mobile_ceu_dev *pcdev = ici->priv;
486 int ret;
459 487
460 if (pcdev->icd) 488 if (pcdev->icd)
461 return -EBUSY; 489 return -EBUSY;
@@ -466,9 +494,11 @@ static int sh_mobile_ceu_add_device(struct soc_camera_device *icd)
466 494
467 pm_runtime_get_sync(ici->v4l2_dev.dev); 495 pm_runtime_get_sync(ici->v4l2_dev.dev);
468 496
469 pcdev->icd = icd; 497 ret = sh_mobile_ceu_soft_reset(pcdev);
498 if (!ret)
499 pcdev->icd = icd;
470 500
471 return sh_mobile_ceu_soft_reset(pcdev); 501 return ret;
472} 502}
473 503
474/* Called with .video_lock held */ 504/* Called with .video_lock held */
@@ -558,24 +588,35 @@ static void sh_mobile_ceu_set_rect(struct soc_camera_device *icd,
558 in_width *= 2; 588 in_width *= 2;
559 left_offset *= 2; 589 left_offset *= 2;
560 } 590 }
561 width = cdwdr_width = out_width; 591 width = out_width;
592 cdwdr_width = out_width;
562 } else { 593 } else {
563 unsigned int w_factor = (icd->current_fmt->depth + 7) >> 3; 594 int bytes_per_line = soc_mbus_bytes_per_line(out_width,
595 icd->current_fmt->host_fmt);
596 unsigned int w_factor;
564 597
565 width = out_width * w_factor / 2; 598 width = out_width;
566 599
567 if (!pcdev->is_16bit) 600 switch (icd->current_fmt->host_fmt->packing) {
568 w_factor *= 2; 601 case SOC_MBUS_PACKING_2X8_PADHI:
602 w_factor = 2;
603 break;
604 default:
605 w_factor = 1;
606 }
569 607
570 in_width = rect->width * w_factor / 2; 608 in_width = rect->width * w_factor;
571 left_offset = left_offset * w_factor / 2; 609 left_offset = left_offset * w_factor;
572 610
573 cdwdr_width = width * 2; 611 if (bytes_per_line < 0)
612 cdwdr_width = out_width;
613 else
614 cdwdr_width = bytes_per_line;
574 } 615 }
575 616
576 height = out_height; 617 height = out_height;
577 in_height = rect->height; 618 in_height = rect->height;
578 if (pcdev->is_interlaced) { 619 if (V4L2_FIELD_NONE != pcdev->field) {
579 height /= 2; 620 height /= 2;
580 in_height /= 2; 621 in_height /= 2;
581 top_offset /= 2; 622 top_offset /= 2;
@@ -646,6 +687,23 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd,
646 if (!common_flags) 687 if (!common_flags)
647 return -EINVAL; 688 return -EINVAL;
648 689
690 /* Make choises, based on platform preferences */
691 if ((common_flags & SOCAM_HSYNC_ACTIVE_HIGH) &&
692 (common_flags & SOCAM_HSYNC_ACTIVE_LOW)) {
693 if (pcdev->pdata->flags & SH_CEU_FLAG_HSYNC_LOW)
694 common_flags &= ~SOCAM_HSYNC_ACTIVE_HIGH;
695 else
696 common_flags &= ~SOCAM_HSYNC_ACTIVE_LOW;
697 }
698
699 if ((common_flags & SOCAM_VSYNC_ACTIVE_HIGH) &&
700 (common_flags & SOCAM_VSYNC_ACTIVE_LOW)) {
701 if (pcdev->pdata->flags & SH_CEU_FLAG_VSYNC_LOW)
702 common_flags &= ~SOCAM_VSYNC_ACTIVE_HIGH;
703 else
704 common_flags &= ~SOCAM_VSYNC_ACTIVE_LOW;
705 }
706
649 ret = icd->ops->set_bus_param(icd, common_flags); 707 ret = icd->ops->set_bus_param(icd, common_flags);
650 if (ret < 0) 708 if (ret < 0)
651 return ret; 709 return ret;
@@ -667,24 +725,24 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd,
667 value = 0x00000010; /* data fetch by default */ 725 value = 0x00000010; /* data fetch by default */
668 yuv_lineskip = 0; 726 yuv_lineskip = 0;
669 727
670 switch (icd->current_fmt->fourcc) { 728 switch (icd->current_fmt->host_fmt->fourcc) {
671 case V4L2_PIX_FMT_NV12: 729 case V4L2_PIX_FMT_NV12:
672 case V4L2_PIX_FMT_NV21: 730 case V4L2_PIX_FMT_NV21:
673 yuv_lineskip = 1; /* skip for NV12/21, no skip for NV16/61 */ 731 yuv_lineskip = 1; /* skip for NV12/21, no skip for NV16/61 */
674 /* fall-through */ 732 /* fall-through */
675 case V4L2_PIX_FMT_NV16: 733 case V4L2_PIX_FMT_NV16:
676 case V4L2_PIX_FMT_NV61: 734 case V4L2_PIX_FMT_NV61:
677 switch (cam->camera_fmt->fourcc) { 735 switch (cam->code) {
678 case V4L2_PIX_FMT_UYVY: 736 case V4L2_MBUS_FMT_YUYV8_2X8_BE:
679 value = 0x00000000; /* Cb0, Y0, Cr0, Y1 */ 737 value = 0x00000000; /* Cb0, Y0, Cr0, Y1 */
680 break; 738 break;
681 case V4L2_PIX_FMT_VYUY: 739 case V4L2_MBUS_FMT_YVYU8_2X8_BE:
682 value = 0x00000100; /* Cr0, Y0, Cb0, Y1 */ 740 value = 0x00000100; /* Cr0, Y0, Cb0, Y1 */
683 break; 741 break;
684 case V4L2_PIX_FMT_YUYV: 742 case V4L2_MBUS_FMT_YUYV8_2X8_LE:
685 value = 0x00000200; /* Y0, Cb0, Y1, Cr0 */ 743 value = 0x00000200; /* Y0, Cb0, Y1, Cr0 */
686 break; 744 break;
687 case V4L2_PIX_FMT_YVYU: 745 case V4L2_MBUS_FMT_YVYU8_2X8_LE:
688 value = 0x00000300; /* Y0, Cr0, Y1, Cb0 */ 746 value = 0x00000300; /* Y0, Cr0, Y1, Cb0 */
689 break; 747 break;
690 default: 748 default:
@@ -692,8 +750,8 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd,
692 } 750 }
693 } 751 }
694 752
695 if (icd->current_fmt->fourcc == V4L2_PIX_FMT_NV21 || 753 if (icd->current_fmt->host_fmt->fourcc == V4L2_PIX_FMT_NV21 ||
696 icd->current_fmt->fourcc == V4L2_PIX_FMT_NV61) 754 icd->current_fmt->host_fmt->fourcc == V4L2_PIX_FMT_NV61)
697 value ^= 0x00000100; /* swap U, V to change from NV1x->NVx1 */ 755 value ^= 0x00000100; /* swap U, V to change from NV1x->NVx1 */
698 756
699 value |= common_flags & SOCAM_VSYNC_ACTIVE_LOW ? 1 << 1 : 0; 757 value |= common_flags & SOCAM_VSYNC_ACTIVE_LOW ? 1 << 1 : 0;
@@ -702,14 +760,27 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd,
702 ceu_write(pcdev, CAMCR, value); 760 ceu_write(pcdev, CAMCR, value);
703 761
704 ceu_write(pcdev, CAPCR, 0x00300000); 762 ceu_write(pcdev, CAPCR, 0x00300000);
705 ceu_write(pcdev, CAIFR, pcdev->is_interlaced ? 0x101 : 0); 763
764 switch (pcdev->field) {
765 case V4L2_FIELD_INTERLACED_TB:
766 value = 0x101;
767 break;
768 case V4L2_FIELD_INTERLACED_BT:
769 value = 0x102;
770 break;
771 default:
772 value = 0;
773 break;
774 }
775 ceu_write(pcdev, CAIFR, value);
706 776
707 sh_mobile_ceu_set_rect(icd, icd->user_width, icd->user_height); 777 sh_mobile_ceu_set_rect(icd, icd->user_width, icd->user_height);
708 mdelay(1); 778 mdelay(1);
709 779
710 ceu_write(pcdev, CFLCR, pcdev->cflcr); 780 ceu_write(pcdev, CFLCR, pcdev->cflcr);
711 781
712 /* A few words about byte order (observed in Big Endian mode) 782 /*
783 * A few words about byte order (observed in Big Endian mode)
713 * 784 *
714 * In data fetch mode bytes are received in chunks of 8 bytes. 785 * In data fetch mode bytes are received in chunks of 8 bytes.
715 * D0, D1, D2, D3, D4, D5, D6, D7 (D0 received first) 786 * D0, D1, D2, D3, D4, D5, D6, D7 (D0 received first)
@@ -739,7 +810,8 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd,
739 return 0; 810 return 0;
740} 811}
741 812
742static int sh_mobile_ceu_try_bus_param(struct soc_camera_device *icd) 813static int sh_mobile_ceu_try_bus_param(struct soc_camera_device *icd,
814 unsigned char buswidth)
743{ 815{
744 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); 816 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
745 struct sh_mobile_ceu_dev *pcdev = ici->priv; 817 struct sh_mobile_ceu_dev *pcdev = ici->priv;
@@ -748,48 +820,75 @@ static int sh_mobile_ceu_try_bus_param(struct soc_camera_device *icd)
748 camera_flags = icd->ops->query_bus_param(icd); 820 camera_flags = icd->ops->query_bus_param(icd);
749 common_flags = soc_camera_bus_param_compatible(camera_flags, 821 common_flags = soc_camera_bus_param_compatible(camera_flags,
750 make_bus_param(pcdev)); 822 make_bus_param(pcdev));
751 if (!common_flags) 823 if (!common_flags || buswidth > 16 ||
824 (buswidth > 8 && !(common_flags & SOCAM_DATAWIDTH_16)))
752 return -EINVAL; 825 return -EINVAL;
753 826
754 return 0; 827 return 0;
755} 828}
756 829
757static const struct soc_camera_data_format sh_mobile_ceu_formats[] = { 830static const struct soc_mbus_pixelfmt sh_mobile_ceu_formats[] = {
758 {
759 .name = "NV12",
760 .depth = 12,
761 .fourcc = V4L2_PIX_FMT_NV12,
762 .colorspace = V4L2_COLORSPACE_JPEG,
763 },
764 {
765 .name = "NV21",
766 .depth = 12,
767 .fourcc = V4L2_PIX_FMT_NV21,
768 .colorspace = V4L2_COLORSPACE_JPEG,
769 },
770 {
771 .name = "NV16",
772 .depth = 16,
773 .fourcc = V4L2_PIX_FMT_NV16,
774 .colorspace = V4L2_COLORSPACE_JPEG,
775 },
776 { 831 {
777 .name = "NV61", 832 .fourcc = V4L2_PIX_FMT_NV12,
778 .depth = 16, 833 .name = "NV12",
779 .fourcc = V4L2_PIX_FMT_NV61, 834 .bits_per_sample = 12,
780 .colorspace = V4L2_COLORSPACE_JPEG, 835 .packing = SOC_MBUS_PACKING_NONE,
836 .order = SOC_MBUS_ORDER_LE,
837 }, {
838 .fourcc = V4L2_PIX_FMT_NV21,
839 .name = "NV21",
840 .bits_per_sample = 12,
841 .packing = SOC_MBUS_PACKING_NONE,
842 .order = SOC_MBUS_ORDER_LE,
843 }, {
844 .fourcc = V4L2_PIX_FMT_NV16,
845 .name = "NV16",
846 .bits_per_sample = 16,
847 .packing = SOC_MBUS_PACKING_NONE,
848 .order = SOC_MBUS_ORDER_LE,
849 }, {
850 .fourcc = V4L2_PIX_FMT_NV61,
851 .name = "NV61",
852 .bits_per_sample = 16,
853 .packing = SOC_MBUS_PACKING_NONE,
854 .order = SOC_MBUS_ORDER_LE,
781 }, 855 },
782}; 856};
783 857
858/* This will be corrected as we get more formats */
859static bool sh_mobile_ceu_packing_supported(const struct soc_mbus_pixelfmt *fmt)
860{
861 return fmt->packing == SOC_MBUS_PACKING_NONE ||
862 (fmt->bits_per_sample == 8 &&
863 fmt->packing == SOC_MBUS_PACKING_2X8_PADHI) ||
864 (fmt->bits_per_sample > 8 &&
865 fmt->packing == SOC_MBUS_PACKING_EXTEND16);
866}
867
784static int sh_mobile_ceu_get_formats(struct soc_camera_device *icd, int idx, 868static int sh_mobile_ceu_get_formats(struct soc_camera_device *icd, int idx,
785 struct soc_camera_format_xlate *xlate) 869 struct soc_camera_format_xlate *xlate)
786{ 870{
871 struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
787 struct device *dev = icd->dev.parent; 872 struct device *dev = icd->dev.parent;
788 int ret, k, n; 873 int ret, k, n;
789 int formats = 0; 874 int formats = 0;
790 struct sh_mobile_ceu_cam *cam; 875 struct sh_mobile_ceu_cam *cam;
876 enum v4l2_mbus_pixelcode code;
877 const struct soc_mbus_pixelfmt *fmt;
791 878
792 ret = sh_mobile_ceu_try_bus_param(icd); 879 ret = v4l2_subdev_call(sd, video, enum_mbus_fmt, idx, &code);
880 if (ret < 0)
881 /* No more formats */
882 return 0;
883
884 fmt = soc_mbus_get_fmtdesc(code);
885 if (!fmt) {
886 dev_err(icd->dev.parent,
887 "Invalid format code #%d: %d\n", idx, code);
888 return -EINVAL;
889 }
890
891 ret = sh_mobile_ceu_try_bus_param(icd, fmt->bits_per_sample);
793 if (ret < 0) 892 if (ret < 0)
794 return 0; 893 return 0;
795 894
@@ -807,13 +906,13 @@ static int sh_mobile_ceu_get_formats(struct soc_camera_device *icd, int idx,
807 if (!idx) 906 if (!idx)
808 cam->extra_fmt = NULL; 907 cam->extra_fmt = NULL;
809 908
810 switch (icd->formats[idx].fourcc) { 909 switch (code) {
811 case V4L2_PIX_FMT_UYVY: 910 case V4L2_MBUS_FMT_YUYV8_2X8_BE:
812 case V4L2_PIX_FMT_VYUY: 911 case V4L2_MBUS_FMT_YVYU8_2X8_BE:
813 case V4L2_PIX_FMT_YUYV: 912 case V4L2_MBUS_FMT_YUYV8_2X8_LE:
814 case V4L2_PIX_FMT_YVYU: 913 case V4L2_MBUS_FMT_YVYU8_2X8_LE:
815 if (cam->extra_fmt) 914 if (cam->extra_fmt)
816 goto add_single_format; 915 break;
817 916
818 /* 917 /*
819 * Our case is simple so far: for any of the above four camera 918 * Our case is simple so far: for any of the above four camera
@@ -824,32 +923,31 @@ static int sh_mobile_ceu_get_formats(struct soc_camera_device *icd, int idx,
824 * the host_priv pointer and check whether the format you're 923 * the host_priv pointer and check whether the format you're
825 * going to add now is already there. 924 * going to add now is already there.
826 */ 925 */
827 cam->extra_fmt = (void *)sh_mobile_ceu_formats; 926 cam->extra_fmt = sh_mobile_ceu_formats;
828 927
829 n = ARRAY_SIZE(sh_mobile_ceu_formats); 928 n = ARRAY_SIZE(sh_mobile_ceu_formats);
830 formats += n; 929 formats += n;
831 for (k = 0; xlate && k < n; k++) { 930 for (k = 0; xlate && k < n; k++) {
832 xlate->host_fmt = &sh_mobile_ceu_formats[k]; 931 xlate->host_fmt = &sh_mobile_ceu_formats[k];
833 xlate->cam_fmt = icd->formats + idx; 932 xlate->code = code;
834 xlate->buswidth = icd->formats[idx].depth;
835 xlate++; 933 xlate++;
836 dev_dbg(dev, "Providing format %s using %s\n", 934 dev_dbg(dev, "Providing format %s using code %d\n",
837 sh_mobile_ceu_formats[k].name, 935 sh_mobile_ceu_formats[k].name, code);
838 icd->formats[idx].name);
839 } 936 }
937 break;
840 default: 938 default:
841add_single_format: 939 if (!sh_mobile_ceu_packing_supported(fmt))
842 /* Generic pass-through */ 940 return 0;
843 formats++; 941 }
844 if (xlate) { 942
845 xlate->host_fmt = icd->formats + idx; 943 /* Generic pass-through */
846 xlate->cam_fmt = icd->formats + idx; 944 formats++;
847 xlate->buswidth = icd->formats[idx].depth; 945 if (xlate) {
848 xlate++; 946 xlate->host_fmt = fmt;
849 dev_dbg(dev, 947 xlate->code = code;
850 "Providing format %s in pass-through mode\n", 948 xlate++;
851 icd->formats[idx].name); 949 dev_dbg(dev, "Providing format %s in pass-through mode\n",
852 } 950 xlate->host_fmt->name);
853 } 951 }
854 952
855 return formats; 953 return formats;
@@ -1029,17 +1127,15 @@ static int client_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *crop,
1029static int get_camera_scales(struct v4l2_subdev *sd, struct v4l2_rect *rect, 1127static int get_camera_scales(struct v4l2_subdev *sd, struct v4l2_rect *rect,
1030 unsigned int *scale_h, unsigned int *scale_v) 1128 unsigned int *scale_h, unsigned int *scale_v)
1031{ 1129{
1032 struct v4l2_format f; 1130 struct v4l2_mbus_framefmt mf;
1033 int ret; 1131 int ret;
1034 1132
1035 f.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 1133 ret = v4l2_subdev_call(sd, video, g_mbus_fmt, &mf);
1036
1037 ret = v4l2_subdev_call(sd, video, g_fmt, &f);
1038 if (ret < 0) 1134 if (ret < 0)
1039 return ret; 1135 return ret;
1040 1136
1041 *scale_h = calc_generic_scale(rect->width, f.fmt.pix.width); 1137 *scale_h = calc_generic_scale(rect->width, mf.width);
1042 *scale_v = calc_generic_scale(rect->height, f.fmt.pix.height); 1138 *scale_v = calc_generic_scale(rect->height, mf.height);
1043 1139
1044 return 0; 1140 return 0;
1045} 1141}
@@ -1054,32 +1150,29 @@ static int get_camera_subwin(struct soc_camera_device *icd,
1054 if (!ceu_rect->width) { 1150 if (!ceu_rect->width) {
1055 struct v4l2_subdev *sd = soc_camera_to_subdev(icd); 1151 struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
1056 struct device *dev = icd->dev.parent; 1152 struct device *dev = icd->dev.parent;
1057 struct v4l2_format f; 1153 struct v4l2_mbus_framefmt mf;
1058 struct v4l2_pix_format *pix = &f.fmt.pix;
1059 int ret; 1154 int ret;
1060 /* First time */ 1155 /* First time */
1061 1156
1062 f.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 1157 ret = v4l2_subdev_call(sd, video, g_mbus_fmt, &mf);
1063
1064 ret = v4l2_subdev_call(sd, video, g_fmt, &f);
1065 if (ret < 0) 1158 if (ret < 0)
1066 return ret; 1159 return ret;
1067 1160
1068 dev_geo(dev, "camera fmt %ux%u\n", pix->width, pix->height); 1161 dev_geo(dev, "camera fmt %ux%u\n", mf.width, mf.height);
1069 1162
1070 if (pix->width > 2560) { 1163 if (mf.width > 2560) {
1071 ceu_rect->width = 2560; 1164 ceu_rect->width = 2560;
1072 ceu_rect->left = (pix->width - 2560) / 2; 1165 ceu_rect->left = (mf.width - 2560) / 2;
1073 } else { 1166 } else {
1074 ceu_rect->width = pix->width; 1167 ceu_rect->width = mf.width;
1075 ceu_rect->left = 0; 1168 ceu_rect->left = 0;
1076 } 1169 }
1077 1170
1078 if (pix->height > 1920) { 1171 if (mf.height > 1920) {
1079 ceu_rect->height = 1920; 1172 ceu_rect->height = 1920;
1080 ceu_rect->top = (pix->height - 1920) / 2; 1173 ceu_rect->top = (mf.height - 1920) / 2;
1081 } else { 1174 } else {
1082 ceu_rect->height = pix->height; 1175 ceu_rect->height = mf.height;
1083 ceu_rect->top = 0; 1176 ceu_rect->top = 0;
1084 } 1177 }
1085 1178
@@ -1096,13 +1189,12 @@ static int get_camera_subwin(struct soc_camera_device *icd,
1096 return 0; 1189 return 0;
1097} 1190}
1098 1191
1099static int client_s_fmt(struct soc_camera_device *icd, struct v4l2_format *f, 1192static int client_s_fmt(struct soc_camera_device *icd,
1100 bool ceu_can_scale) 1193 struct v4l2_mbus_framefmt *mf, bool ceu_can_scale)
1101{ 1194{
1102 struct v4l2_subdev *sd = soc_camera_to_subdev(icd); 1195 struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
1103 struct device *dev = icd->dev.parent; 1196 struct device *dev = icd->dev.parent;
1104 struct v4l2_pix_format *pix = &f->fmt.pix; 1197 unsigned int width = mf->width, height = mf->height, tmp_w, tmp_h;
1105 unsigned int width = pix->width, height = pix->height, tmp_w, tmp_h;
1106 unsigned int max_width, max_height; 1198 unsigned int max_width, max_height;
1107 struct v4l2_cropcap cap; 1199 struct v4l2_cropcap cap;
1108 int ret; 1200 int ret;
@@ -1116,29 +1208,29 @@ static int client_s_fmt(struct soc_camera_device *icd, struct v4l2_format *f,
1116 max_width = min(cap.bounds.width, 2560); 1208 max_width = min(cap.bounds.width, 2560);
1117 max_height = min(cap.bounds.height, 1920); 1209 max_height = min(cap.bounds.height, 1920);
1118 1210
1119 ret = v4l2_subdev_call(sd, video, s_fmt, f); 1211 ret = v4l2_subdev_call(sd, video, s_mbus_fmt, mf);
1120 if (ret < 0) 1212 if (ret < 0)
1121 return ret; 1213 return ret;
1122 1214
1123 dev_geo(dev, "camera scaled to %ux%u\n", pix->width, pix->height); 1215 dev_geo(dev, "camera scaled to %ux%u\n", mf->width, mf->height);
1124 1216
1125 if ((width == pix->width && height == pix->height) || !ceu_can_scale) 1217 if ((width == mf->width && height == mf->height) || !ceu_can_scale)
1126 return 0; 1218 return 0;
1127 1219
1128 /* Camera set a format, but geometry is not precise, try to improve */ 1220 /* Camera set a format, but geometry is not precise, try to improve */
1129 tmp_w = pix->width; 1221 tmp_w = mf->width;
1130 tmp_h = pix->height; 1222 tmp_h = mf->height;
1131 1223
1132 /* width <= max_width && height <= max_height - guaranteed by try_fmt */ 1224 /* width <= max_width && height <= max_height - guaranteed by try_fmt */
1133 while ((width > tmp_w || height > tmp_h) && 1225 while ((width > tmp_w || height > tmp_h) &&
1134 tmp_w < max_width && tmp_h < max_height) { 1226 tmp_w < max_width && tmp_h < max_height) {
1135 tmp_w = min(2 * tmp_w, max_width); 1227 tmp_w = min(2 * tmp_w, max_width);
1136 tmp_h = min(2 * tmp_h, max_height); 1228 tmp_h = min(2 * tmp_h, max_height);
1137 pix->width = tmp_w; 1229 mf->width = tmp_w;
1138 pix->height = tmp_h; 1230 mf->height = tmp_h;
1139 ret = v4l2_subdev_call(sd, video, s_fmt, f); 1231 ret = v4l2_subdev_call(sd, video, s_mbus_fmt, mf);
1140 dev_geo(dev, "Camera scaled to %ux%u\n", 1232 dev_geo(dev, "Camera scaled to %ux%u\n",
1141 pix->width, pix->height); 1233 mf->width, mf->height);
1142 if (ret < 0) { 1234 if (ret < 0) {
1143 /* This shouldn't happen */ 1235 /* This shouldn't happen */
1144 dev_err(dev, "Client failed to set format: %d\n", ret); 1236 dev_err(dev, "Client failed to set format: %d\n", ret);
@@ -1156,27 +1248,26 @@ static int client_s_fmt(struct soc_camera_device *icd, struct v4l2_format *f,
1156 */ 1248 */
1157static int client_scale(struct soc_camera_device *icd, struct v4l2_rect *rect, 1249static int client_scale(struct soc_camera_device *icd, struct v4l2_rect *rect,
1158 struct v4l2_rect *sub_rect, struct v4l2_rect *ceu_rect, 1250 struct v4l2_rect *sub_rect, struct v4l2_rect *ceu_rect,
1159 struct v4l2_format *f, bool ceu_can_scale) 1251 struct v4l2_mbus_framefmt *mf, bool ceu_can_scale)
1160{ 1252{
1161 struct v4l2_subdev *sd = soc_camera_to_subdev(icd); 1253 struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
1162 struct sh_mobile_ceu_cam *cam = icd->host_priv; 1254 struct sh_mobile_ceu_cam *cam = icd->host_priv;
1163 struct device *dev = icd->dev.parent; 1255 struct device *dev = icd->dev.parent;
1164 struct v4l2_format f_tmp = *f; 1256 struct v4l2_mbus_framefmt mf_tmp = *mf;
1165 struct v4l2_pix_format *pix_tmp = &f_tmp.fmt.pix;
1166 unsigned int scale_h, scale_v; 1257 unsigned int scale_h, scale_v;
1167 int ret; 1258 int ret;
1168 1259
1169 /* 5. Apply iterative camera S_FMT for camera user window. */ 1260 /* 5. Apply iterative camera S_FMT for camera user window. */
1170 ret = client_s_fmt(icd, &f_tmp, ceu_can_scale); 1261 ret = client_s_fmt(icd, &mf_tmp, ceu_can_scale);
1171 if (ret < 0) 1262 if (ret < 0)
1172 return ret; 1263 return ret;
1173 1264
1174 dev_geo(dev, "5: camera scaled to %ux%u\n", 1265 dev_geo(dev, "5: camera scaled to %ux%u\n",
1175 pix_tmp->width, pix_tmp->height); 1266 mf_tmp.width, mf_tmp.height);
1176 1267
1177 /* 6. Retrieve camera output window (g_fmt) */ 1268 /* 6. Retrieve camera output window (g_fmt) */
1178 1269
1179 /* unneeded - it is already in "f_tmp" */ 1270 /* unneeded - it is already in "mf_tmp" */
1180 1271
1181 /* 7. Calculate new camera scales. */ 1272 /* 7. Calculate new camera scales. */
1182 ret = get_camera_scales(sd, rect, &scale_h, &scale_v); 1273 ret = get_camera_scales(sd, rect, &scale_h, &scale_v);
@@ -1185,10 +1276,11 @@ static int client_scale(struct soc_camera_device *icd, struct v4l2_rect *rect,
1185 1276
1186 dev_geo(dev, "7: camera scales %u:%u\n", scale_h, scale_v); 1277 dev_geo(dev, "7: camera scales %u:%u\n", scale_h, scale_v);
1187 1278
1188 cam->cam_width = pix_tmp->width; 1279 cam->cam_width = mf_tmp.width;
1189 cam->cam_height = pix_tmp->height; 1280 cam->cam_height = mf_tmp.height;
1190 f->fmt.pix.width = pix_tmp->width; 1281 mf->width = mf_tmp.width;
1191 f->fmt.pix.height = pix_tmp->height; 1282 mf->height = mf_tmp.height;
1283 mf->colorspace = mf_tmp.colorspace;
1192 1284
1193 /* 1285 /*
1194 * 8. Calculate new CEU crop - apply camera scales to previously 1286 * 8. Calculate new CEU crop - apply camera scales to previously
@@ -1252,8 +1344,7 @@ static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd,
1252 struct v4l2_rect *cam_rect = &cam_crop.c, *ceu_rect = &cam->ceu_rect; 1344 struct v4l2_rect *cam_rect = &cam_crop.c, *ceu_rect = &cam->ceu_rect;
1253 struct v4l2_subdev *sd = soc_camera_to_subdev(icd); 1345 struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
1254 struct device *dev = icd->dev.parent; 1346 struct device *dev = icd->dev.parent;
1255 struct v4l2_format f; 1347 struct v4l2_mbus_framefmt mf;
1256 struct v4l2_pix_format *pix = &f.fmt.pix;
1257 unsigned int scale_comb_h, scale_comb_v, scale_ceu_h, scale_ceu_v, 1348 unsigned int scale_comb_h, scale_comb_v, scale_ceu_h, scale_ceu_v,
1258 out_width, out_height; 1349 out_width, out_height;
1259 u32 capsr, cflcr; 1350 u32 capsr, cflcr;
@@ -1302,26 +1393,25 @@ static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd,
1302 * 5. Using actual input window and calculated combined scales calculate 1393 * 5. Using actual input window and calculated combined scales calculate
1303 * camera target output window. 1394 * camera target output window.
1304 */ 1395 */
1305 pix->width = scale_down(cam_rect->width, scale_comb_h); 1396 mf.width = scale_down(cam_rect->width, scale_comb_h);
1306 pix->height = scale_down(cam_rect->height, scale_comb_v); 1397 mf.height = scale_down(cam_rect->height, scale_comb_v);
1307 1398
1308 dev_geo(dev, "5: camera target %ux%u\n", pix->width, pix->height); 1399 dev_geo(dev, "5: camera target %ux%u\n", mf.width, mf.height);
1309 1400
1310 /* 6. - 9. */ 1401 /* 6. - 9. */
1311 pix->pixelformat = cam->camera_fmt->fourcc; 1402 mf.code = cam->code;
1312 pix->colorspace = cam->camera_fmt->colorspace; 1403 mf.field = pcdev->field;
1313 1404
1314 capsr = capture_save_reset(pcdev); 1405 capsr = capture_save_reset(pcdev);
1315 dev_dbg(dev, "CAPSR 0x%x, CFLCR 0x%x\n", capsr, pcdev->cflcr); 1406 dev_dbg(dev, "CAPSR 0x%x, CFLCR 0x%x\n", capsr, pcdev->cflcr);
1316 1407
1317 /* Make relative to camera rectangle */ 1408 /* Make relative to camera rectangle */
1318 rect->left -= cam_rect->left; 1409 rect->left -= cam_rect->left;
1319 rect->top -= cam_rect->top; 1410 rect->top -= cam_rect->top;
1320 1411
1321 f.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 1412 ret = client_scale(icd, cam_rect, rect, ceu_rect, &mf,
1322 1413 pcdev->image_mode &&
1323 ret = client_scale(icd, cam_rect, rect, ceu_rect, &f, 1414 V4L2_FIELD_NONE == pcdev->field);
1324 pcdev->image_mode && !pcdev->is_interlaced);
1325 1415
1326 dev_geo(dev, "6-9: %d\n", ret); 1416 dev_geo(dev, "6-9: %d\n", ret);
1327 1417
@@ -1368,8 +1458,7 @@ static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd,
1368 struct sh_mobile_ceu_dev *pcdev = ici->priv; 1458 struct sh_mobile_ceu_dev *pcdev = ici->priv;
1369 struct sh_mobile_ceu_cam *cam = icd->host_priv; 1459 struct sh_mobile_ceu_cam *cam = icd->host_priv;
1370 struct v4l2_pix_format *pix = &f->fmt.pix; 1460 struct v4l2_pix_format *pix = &f->fmt.pix;
1371 struct v4l2_format cam_f = *f; 1461 struct v4l2_mbus_framefmt mf;
1372 struct v4l2_pix_format *cam_pix = &cam_f.fmt.pix;
1373 struct v4l2_subdev *sd = soc_camera_to_subdev(icd); 1462 struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
1374 struct device *dev = icd->dev.parent; 1463 struct device *dev = icd->dev.parent;
1375 __u32 pixfmt = pix->pixelformat; 1464 __u32 pixfmt = pix->pixelformat;
@@ -1379,18 +1468,20 @@ static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd,
1379 unsigned int scale_cam_h, scale_cam_v; 1468 unsigned int scale_cam_h, scale_cam_v;
1380 u16 scale_v, scale_h; 1469 u16 scale_v, scale_h;
1381 int ret; 1470 int ret;
1382 bool is_interlaced, image_mode; 1471 bool image_mode;
1472 enum v4l2_field field;
1383 1473
1384 switch (pix->field) { 1474 switch (pix->field) {
1385 case V4L2_FIELD_INTERLACED:
1386 is_interlaced = true;
1387 break;
1388 case V4L2_FIELD_ANY:
1389 default: 1475 default:
1390 pix->field = V4L2_FIELD_NONE; 1476 pix->field = V4L2_FIELD_NONE;
1391 /* fall-through */ 1477 /* fall-through */
1478 case V4L2_FIELD_INTERLACED_TB:
1479 case V4L2_FIELD_INTERLACED_BT:
1392 case V4L2_FIELD_NONE: 1480 case V4L2_FIELD_NONE:
1393 is_interlaced = false; 1481 field = pix->field;
1482 break;
1483 case V4L2_FIELD_INTERLACED:
1484 field = V4L2_FIELD_INTERLACED_TB;
1394 break; 1485 break;
1395 } 1486 }
1396 1487
@@ -1438,9 +1529,11 @@ static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd,
1438 * 4. Calculate camera output window by applying combined scales to real 1529 * 4. Calculate camera output window by applying combined scales to real
1439 * input window. 1530 * input window.
1440 */ 1531 */
1441 cam_pix->width = scale_down(cam_rect->width, scale_h); 1532 mf.width = scale_down(cam_rect->width, scale_h);
1442 cam_pix->height = scale_down(cam_rect->height, scale_v); 1533 mf.height = scale_down(cam_rect->height, scale_v);
1443 cam_pix->pixelformat = xlate->cam_fmt->fourcc; 1534 mf.field = pix->field;
1535 mf.colorspace = pix->colorspace;
1536 mf.code = xlate->code;
1444 1537
1445 switch (pixfmt) { 1538 switch (pixfmt) {
1446 case V4L2_PIX_FMT_NV12: 1539 case V4L2_PIX_FMT_NV12:
@@ -1453,51 +1546,61 @@ static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd,
1453 image_mode = false; 1546 image_mode = false;
1454 } 1547 }
1455 1548
1456 dev_geo(dev, "4: camera output %ux%u\n", 1549 dev_geo(dev, "4: camera output %ux%u\n", mf.width, mf.height);
1457 cam_pix->width, cam_pix->height);
1458 1550
1459 /* 5. - 9. */ 1551 /* 5. - 9. */
1460 ret = client_scale(icd, cam_rect, &cam_subrect, &ceu_rect, &cam_f, 1552 ret = client_scale(icd, cam_rect, &cam_subrect, &ceu_rect, &mf,
1461 image_mode && !is_interlaced); 1553 image_mode && V4L2_FIELD_NONE == field);
1462 1554
1463 dev_geo(dev, "5-9: client scale %d\n", ret); 1555 dev_geo(dev, "5-9: client scale %d\n", ret);
1464 1556
1465 /* Done with the camera. Now see if we can improve the result */ 1557 /* Done with the camera. Now see if we can improve the result */
1466 1558
1467 dev_dbg(dev, "Camera %d fmt %ux%u, requested %ux%u\n", 1559 dev_dbg(dev, "Camera %d fmt %ux%u, requested %ux%u\n",
1468 ret, cam_pix->width, cam_pix->height, pix->width, pix->height); 1560 ret, mf.width, mf.height, pix->width, pix->height);
1469 if (ret < 0) 1561 if (ret < 0)
1470 return ret; 1562 return ret;
1471 1563
1564 if (mf.code != xlate->code)
1565 return -EINVAL;
1566
1472 /* 10. Use CEU scaling to scale to the requested user window. */ 1567 /* 10. Use CEU scaling to scale to the requested user window. */
1473 1568
1474 /* We cannot scale up */ 1569 /* We cannot scale up */
1475 if (pix->width > cam_pix->width) 1570 if (pix->width > mf.width)
1476 pix->width = cam_pix->width; 1571 pix->width = mf.width;
1477 if (pix->width > ceu_rect.width) 1572 if (pix->width > ceu_rect.width)
1478 pix->width = ceu_rect.width; 1573 pix->width = ceu_rect.width;
1479 1574
1480 if (pix->height > cam_pix->height) 1575 if (pix->height > mf.height)
1481 pix->height = cam_pix->height; 1576 pix->height = mf.height;
1482 if (pix->height > ceu_rect.height) 1577 if (pix->height > ceu_rect.height)
1483 pix->height = ceu_rect.height; 1578 pix->height = ceu_rect.height;
1484 1579
1485 /* Let's rock: scale pix->{width x height} down to width x height */ 1580 pix->colorspace = mf.colorspace;
1486 scale_h = calc_scale(ceu_rect.width, &pix->width); 1581
1487 scale_v = calc_scale(ceu_rect.height, &pix->height); 1582 if (image_mode) {
1583 /* Scale pix->{width x height} down to width x height */
1584 scale_h = calc_scale(ceu_rect.width, &pix->width);
1585 scale_v = calc_scale(ceu_rect.height, &pix->height);
1586
1587 pcdev->cflcr = scale_h | (scale_v << 16);
1588 } else {
1589 pix->width = ceu_rect.width;
1590 pix->height = ceu_rect.height;
1591 scale_h = scale_v = 0;
1592 pcdev->cflcr = 0;
1593 }
1488 1594
1489 dev_geo(dev, "10: W: %u : 0x%x = %u, H: %u : 0x%x = %u\n", 1595 dev_geo(dev, "10: W: %u : 0x%x = %u, H: %u : 0x%x = %u\n",
1490 ceu_rect.width, scale_h, pix->width, 1596 ceu_rect.width, scale_h, pix->width,
1491 ceu_rect.height, scale_v, pix->height); 1597 ceu_rect.height, scale_v, pix->height);
1492 1598
1493 pcdev->cflcr = scale_h | (scale_v << 16); 1599 cam->code = xlate->code;
1600 cam->ceu_rect = ceu_rect;
1601 icd->current_fmt = xlate;
1494 1602
1495 icd->buswidth = xlate->buswidth; 1603 pcdev->field = field;
1496 icd->current_fmt = xlate->host_fmt;
1497 cam->camera_fmt = xlate->cam_fmt;
1498 cam->ceu_rect = ceu_rect;
1499
1500 pcdev->is_interlaced = is_interlaced;
1501 pcdev->image_mode = image_mode; 1604 pcdev->image_mode = image_mode;
1502 1605
1503 return 0; 1606 return 0;
@@ -1509,6 +1612,7 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd,
1509 const struct soc_camera_format_xlate *xlate; 1612 const struct soc_camera_format_xlate *xlate;
1510 struct v4l2_pix_format *pix = &f->fmt.pix; 1613 struct v4l2_pix_format *pix = &f->fmt.pix;
1511 struct v4l2_subdev *sd = soc_camera_to_subdev(icd); 1614 struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
1615 struct v4l2_mbus_framefmt mf;
1512 __u32 pixfmt = pix->pixelformat; 1616 __u32 pixfmt = pix->pixelformat;
1513 int width, height; 1617 int width, height;
1514 int ret; 1618 int ret;
@@ -1527,18 +1631,27 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd,
1527 width = pix->width; 1631 width = pix->width;
1528 height = pix->height; 1632 height = pix->height;
1529 1633
1530 pix->bytesperline = pix->width * 1634 pix->bytesperline = soc_mbus_bytes_per_line(width, xlate->host_fmt);
1531 DIV_ROUND_UP(xlate->host_fmt->depth, 8); 1635 if (pix->bytesperline < 0)
1532 pix->sizeimage = pix->height * pix->bytesperline; 1636 return pix->bytesperline;
1533 1637 pix->sizeimage = height * pix->bytesperline;
1534 pix->pixelformat = xlate->cam_fmt->fourcc;
1535 1638
1536 /* limit to sensor capabilities */ 1639 /* limit to sensor capabilities */
1537 ret = v4l2_subdev_call(sd, video, try_fmt, f); 1640 mf.width = pix->width;
1538 pix->pixelformat = pixfmt; 1641 mf.height = pix->height;
1642 mf.field = pix->field;
1643 mf.code = xlate->code;
1644 mf.colorspace = pix->colorspace;
1645
1646 ret = v4l2_subdev_call(sd, video, try_mbus_fmt, &mf);
1539 if (ret < 0) 1647 if (ret < 0)
1540 return ret; 1648 return ret;
1541 1649
1650 pix->width = mf.width;
1651 pix->height = mf.height;
1652 pix->field = mf.field;
1653 pix->colorspace = mf.colorspace;
1654
1542 switch (pixfmt) { 1655 switch (pixfmt) {
1543 case V4L2_PIX_FMT_NV12: 1656 case V4L2_PIX_FMT_NV12:
1544 case V4L2_PIX_FMT_NV21: 1657 case V4L2_PIX_FMT_NV21:
@@ -1547,21 +1660,25 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd,
1547 /* FIXME: check against rect_max after converting soc-camera */ 1660 /* FIXME: check against rect_max after converting soc-camera */
1548 /* We can scale precisely, need a bigger image from camera */ 1661 /* We can scale precisely, need a bigger image from camera */
1549 if (pix->width < width || pix->height < height) { 1662 if (pix->width < width || pix->height < height) {
1550 int tmp_w = pix->width, tmp_h = pix->height; 1663 /*
1551 pix->width = 2560; 1664 * We presume, the sensor behaves sanely, i.e., if
1552 pix->height = 1920; 1665 * requested a bigger rectangle, it will not return a
1553 ret = v4l2_subdev_call(sd, video, try_fmt, f); 1666 * smaller one.
1667 */
1668 mf.width = 2560;
1669 mf.height = 1920;
1670 ret = v4l2_subdev_call(sd, video, try_mbus_fmt, &mf);
1554 if (ret < 0) { 1671 if (ret < 0) {
1555 /* Shouldn't actually happen... */ 1672 /* Shouldn't actually happen... */
1556 dev_err(icd->dev.parent, 1673 dev_err(icd->dev.parent,
1557 "FIXME: try_fmt() returned %d\n", ret); 1674 "FIXME: client try_fmt() = %d\n", ret);
1558 pix->width = tmp_w; 1675 return ret;
1559 pix->height = tmp_h;
1560 } 1676 }
1561 } 1677 }
1562 if (pix->width > width) 1678 /* We will scale exactly */
1679 if (mf.width > width)
1563 pix->width = width; 1680 pix->width = width;
1564 if (pix->height > height) 1681 if (mf.height > height)
1565 pix->height = height; 1682 pix->height = height;
1566 } 1683 }
1567 1684
@@ -1573,10 +1690,12 @@ static int sh_mobile_ceu_reqbufs(struct soc_camera_file *icf,
1573{ 1690{
1574 int i; 1691 int i;
1575 1692
1576 /* This is for locking debugging only. I removed spinlocks and now I 1693 /*
1694 * This is for locking debugging only. I removed spinlocks and now I
1577 * check whether .prepare is ever called on a linked buffer, or whether 1695 * check whether .prepare is ever called on a linked buffer, or whether
1578 * a dma IRQ can occur for an in-work or unlinked buffer. Until now 1696 * a dma IRQ can occur for an in-work or unlinked buffer. Until now
1579 * it hadn't triggered */ 1697 * it hadn't triggered
1698 */
1580 for (i = 0; i < p->count; i++) { 1699 for (i = 0; i < p->count; i++) {
1581 struct sh_mobile_ceu_buffer *buf; 1700 struct sh_mobile_ceu_buffer *buf;
1582 1701
@@ -1624,8 +1743,7 @@ static void sh_mobile_ceu_init_videobuf(struct videobuf_queue *q,
1624 &sh_mobile_ceu_videobuf_ops, 1743 &sh_mobile_ceu_videobuf_ops,
1625 icd->dev.parent, &pcdev->lock, 1744 icd->dev.parent, &pcdev->lock,
1626 V4L2_BUF_TYPE_VIDEO_CAPTURE, 1745 V4L2_BUF_TYPE_VIDEO_CAPTURE,
1627 pcdev->is_interlaced ? 1746 pcdev->field,
1628 V4L2_FIELD_INTERLACED : V4L2_FIELD_NONE,
1629 sizeof(struct sh_mobile_ceu_buffer), 1747 sizeof(struct sh_mobile_ceu_buffer),
1630 icd); 1748 icd);
1631} 1749}
@@ -1654,7 +1772,7 @@ static int sh_mobile_ceu_set_ctrl(struct soc_camera_device *icd,
1654 1772
1655 switch (ctrl->id) { 1773 switch (ctrl->id) {
1656 case V4L2_CID_SHARPNESS: 1774 case V4L2_CID_SHARPNESS:
1657 switch (icd->current_fmt->fourcc) { 1775 switch (icd->current_fmt->host_fmt->fourcc) {
1658 case V4L2_PIX_FMT_NV12: 1776 case V4L2_PIX_FMT_NV12:
1659 case V4L2_PIX_FMT_NV21: 1777 case V4L2_PIX_FMT_NV21:
1660 case V4L2_PIX_FMT_NV16: 1778 case V4L2_PIX_FMT_NV16:
@@ -1836,7 +1954,7 @@ static struct platform_driver sh_mobile_ceu_driver = {
1836 .pm = &sh_mobile_ceu_dev_pm_ops, 1954 .pm = &sh_mobile_ceu_dev_pm_ops,
1837 }, 1955 },
1838 .probe = sh_mobile_ceu_probe, 1956 .probe = sh_mobile_ceu_probe,
1839 .remove = __exit_p(sh_mobile_ceu_remove), 1957 .remove = __devexit_p(sh_mobile_ceu_remove),
1840}; 1958};
1841 1959
1842static int __init sh_mobile_ceu_init(void) 1960static int __init sh_mobile_ceu_init(void)