aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/mx2_camera.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/mx2_camera.c')
-rw-r--r--drivers/media/video/mx2_camera.c78
1 files changed, 58 insertions, 20 deletions
diff --git a/drivers/media/video/mx2_camera.c b/drivers/media/video/mx2_camera.c
index 18afaeeadb7b..ded26b7286fa 100644
--- a/drivers/media/video/mx2_camera.c
+++ b/drivers/media/video/mx2_camera.c
@@ -22,6 +22,7 @@
22#include <linux/gcd.h> 22#include <linux/gcd.h>
23#include <linux/interrupt.h> 23#include <linux/interrupt.h>
24#include <linux/kernel.h> 24#include <linux/kernel.h>
25#include <linux/math64.h>
25#include <linux/mm.h> 26#include <linux/mm.h>
26#include <linux/moduleparam.h> 27#include <linux/moduleparam.h>
27#include <linux/time.h> 28#include <linux/time.h>
@@ -344,6 +345,19 @@ static struct mx2_fmt_cfg mx27_emma_prp_table[] = {
344 PRP_INTR_CH2OVF, 345 PRP_INTR_CH2OVF,
345 } 346 }
346 }, 347 },
348 {
349 .in_fmt = V4L2_MBUS_FMT_UYVY8_2X8,
350 .out_fmt = V4L2_PIX_FMT_YUV420,
351 .cfg = {
352 .channel = 2,
353 .in_fmt = PRP_CNTL_DATA_IN_YUV422,
354 .out_fmt = PRP_CNTL_CH2_OUT_YUV420,
355 .src_pixel = 0x22000888, /* YUV422 (YUYV) */
356 .irq_flags = PRP_INTR_RDERR | PRP_INTR_CH2WERR |
357 PRP_INTR_CH2FC | PRP_INTR_LBOVF |
358 PRP_INTR_CH2OVF,
359 }
360 },
347}; 361};
348 362
349static struct mx2_fmt_cfg *mx27_emma_prp_get_format( 363static struct mx2_fmt_cfg *mx27_emma_prp_get_format(
@@ -525,8 +539,6 @@ static int mx2_videobuf_setup(struct vb2_queue *vq,
525 struct soc_camera_device *icd = soc_camera_from_vb2q(vq); 539 struct soc_camera_device *icd = soc_camera_from_vb2q(vq);
526 struct soc_camera_host *ici = to_soc_camera_host(icd->parent); 540 struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
527 struct mx2_camera_dev *pcdev = ici->priv; 541 struct mx2_camera_dev *pcdev = ici->priv;
528 int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
529 icd->current_fmt->host_fmt);
530 542
531 dev_dbg(icd->parent, "count=%d, size=%d\n", *count, sizes[0]); 543 dev_dbg(icd->parent, "count=%d, size=%d\n", *count, sizes[0]);
532 544
@@ -534,12 +546,9 @@ static int mx2_videobuf_setup(struct vb2_queue *vq,
534 if (fmt != NULL) 546 if (fmt != NULL)
535 return -ENOTTY; 547 return -ENOTTY;
536 548
537 if (bytes_per_line < 0)
538 return bytes_per_line;
539
540 alloc_ctxs[0] = pcdev->alloc_ctx; 549 alloc_ctxs[0] = pcdev->alloc_ctx;
541 550
542 sizes[0] = bytes_per_line * icd->user_height; 551 sizes[0] = icd->sizeimage;
543 552
544 if (0 == *count) 553 if (0 == *count)
545 *count = 32; 554 *count = 32;
@@ -555,16 +564,11 @@ static int mx2_videobuf_setup(struct vb2_queue *vq,
555static int mx2_videobuf_prepare(struct vb2_buffer *vb) 564static int mx2_videobuf_prepare(struct vb2_buffer *vb)
556{ 565{
557 struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue); 566 struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue);
558 int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
559 icd->current_fmt->host_fmt);
560 int ret = 0; 567 int ret = 0;
561 568
562 dev_dbg(icd->parent, "%s (vb=0x%p) 0x%p %lu\n", __func__, 569 dev_dbg(icd->parent, "%s (vb=0x%p) 0x%p %lu\n", __func__,
563 vb, vb2_plane_vaddr(vb, 0), vb2_get_plane_payload(vb, 0)); 570 vb, vb2_plane_vaddr(vb, 0), vb2_get_plane_payload(vb, 0));
564 571
565 if (bytes_per_line < 0)
566 return bytes_per_line;
567
568#ifdef DEBUG 572#ifdef DEBUG
569 /* 573 /*
570 * This can be useful if you want to see if we actually fill 574 * This can be useful if you want to see if we actually fill
@@ -574,7 +578,7 @@ static int mx2_videobuf_prepare(struct vb2_buffer *vb)
574 0xaa, vb2_get_plane_payload(vb, 0)); 578 0xaa, vb2_get_plane_payload(vb, 0));
575#endif 579#endif
576 580
577 vb2_set_plane_payload(vb, 0, bytes_per_line * icd->user_height); 581 vb2_set_plane_payload(vb, 0, icd->sizeimage);
578 if (vb2_plane_vaddr(vb, 0) && 582 if (vb2_plane_vaddr(vb, 0) &&
579 vb2_get_plane_payload(vb, 0) > vb2_plane_size(vb, 0)) { 583 vb2_get_plane_payload(vb, 0) > vb2_plane_size(vb, 0)) {
580 ret = -EINVAL; 584 ret = -EINVAL;
@@ -980,6 +984,7 @@ static int mx2_camera_set_bus_param(struct soc_camera_device *icd)
980 struct soc_camera_host *ici = to_soc_camera_host(icd->parent); 984 struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
981 struct mx2_camera_dev *pcdev = ici->priv; 985 struct mx2_camera_dev *pcdev = ici->priv;
982 struct v4l2_mbus_config cfg = {.type = V4L2_MBUS_PARALLEL,}; 986 struct v4l2_mbus_config cfg = {.type = V4L2_MBUS_PARALLEL,};
987 const struct soc_camera_format_xlate *xlate;
983 unsigned long common_flags; 988 unsigned long common_flags;
984 int ret; 989 int ret;
985 int bytesperline; 990 int bytesperline;
@@ -1024,14 +1029,31 @@ static int mx2_camera_set_bus_param(struct soc_camera_device *icd)
1024 return ret; 1029 return ret;
1025 } 1030 }
1026 1031
1032 xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
1033 if (!xlate) {
1034 dev_warn(icd->parent, "Format %x not found\n", pixfmt);
1035 return -EINVAL;
1036 }
1037
1038 if (xlate->code == V4L2_MBUS_FMT_YUYV8_2X8) {
1039 csicr1 |= CSICR1_PACK_DIR;
1040 csicr1 &= ~CSICR1_SWAP16_EN;
1041 dev_dbg(icd->parent, "already yuyv format, don't convert\n");
1042 } else if (xlate->code == V4L2_MBUS_FMT_UYVY8_2X8) {
1043 csicr1 &= ~CSICR1_PACK_DIR;
1044 csicr1 |= CSICR1_SWAP16_EN;
1045 dev_dbg(icd->parent, "convert uyvy mbus format into yuyv\n");
1046 } else {
1047 dev_warn(icd->parent, "mbus format not supported\n");
1048 return -EINVAL;
1049 }
1050
1027 if (common_flags & V4L2_MBUS_PCLK_SAMPLE_RISING) 1051 if (common_flags & V4L2_MBUS_PCLK_SAMPLE_RISING)
1028 csicr1 |= CSICR1_REDGE; 1052 csicr1 |= CSICR1_REDGE;
1029 if (common_flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH) 1053 if (common_flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH)
1030 csicr1 |= CSICR1_SOF_POL; 1054 csicr1 |= CSICR1_SOF_POL;
1031 if (common_flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH) 1055 if (common_flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH)
1032 csicr1 |= CSICR1_HSYNC_POL; 1056 csicr1 |= CSICR1_HSYNC_POL;
1033 if (pcdev->platform_flags & MX2_CAMERA_SWAP16)
1034 csicr1 |= CSICR1_SWAP16_EN;
1035 if (pcdev->platform_flags & MX2_CAMERA_EXT_VSYNC) 1057 if (pcdev->platform_flags & MX2_CAMERA_EXT_VSYNC)
1036 csicr1 |= CSICR1_EXT_VSYNC; 1058 csicr1 |= CSICR1_EXT_VSYNC;
1037 if (pcdev->platform_flags & MX2_CAMERA_CCIR) 1059 if (pcdev->platform_flags & MX2_CAMERA_CCIR)
@@ -1042,8 +1064,6 @@ static int mx2_camera_set_bus_param(struct soc_camera_device *icd)
1042 csicr1 |= CSICR1_GCLK_MODE; 1064 csicr1 |= CSICR1_GCLK_MODE;
1043 if (pcdev->platform_flags & MX2_CAMERA_INV_DATA) 1065 if (pcdev->platform_flags & MX2_CAMERA_INV_DATA)
1044 csicr1 |= CSICR1_INV_DATA; 1066 csicr1 |= CSICR1_INV_DATA;
1045 if (pcdev->platform_flags & MX2_CAMERA_PACK_DIR_MSB)
1046 csicr1 |= CSICR1_PACK_DIR;
1047 1067
1048 pcdev->csicr1 = csicr1; 1068 pcdev->csicr1 = csicr1;
1049 1069
@@ -1118,7 +1138,8 @@ static int mx2_camera_get_formats(struct soc_camera_device *icd,
1118 return 0; 1138 return 0;
1119 } 1139 }
1120 1140
1121 if (code == V4L2_MBUS_FMT_YUYV8_2X8) { 1141 if (code == V4L2_MBUS_FMT_YUYV8_2X8 ||
1142 code == V4L2_MBUS_FMT_UYVY8_2X8) {
1122 formats++; 1143 formats++;
1123 if (xlate) { 1144 if (xlate) {
1124 /* 1145 /*
@@ -1134,6 +1155,18 @@ static int mx2_camera_get_formats(struct soc_camera_device *icd,
1134 } 1155 }
1135 } 1156 }
1136 1157
1158 if (code == V4L2_MBUS_FMT_UYVY8_2X8) {
1159 formats++;
1160 if (xlate) {
1161 xlate->host_fmt =
1162 soc_mbus_get_fmtdesc(V4L2_MBUS_FMT_YUYV8_2X8);
1163 xlate->code = code;
1164 dev_dbg(dev, "Providing host format %s for sensor code %d\n",
1165 xlate->host_fmt->name, code);
1166 xlate++;
1167 }
1168 }
1169
1137 /* Generic pass-trough */ 1170 /* Generic pass-trough */
1138 formats++; 1171 formats++;
1139 if (xlate) { 1172 if (xlate) {
@@ -1363,17 +1396,20 @@ static int mx2_camera_try_fmt(struct soc_camera_device *icd,
1363 xlate->host_fmt); 1396 xlate->host_fmt);
1364 if (pix->bytesperline < 0) 1397 if (pix->bytesperline < 0)
1365 return pix->bytesperline; 1398 return pix->bytesperline;
1366 pix->sizeimage = pix->height * pix->bytesperline; 1399 pix->sizeimage = soc_mbus_image_size(xlate->host_fmt,
1400 pix->bytesperline, pix->height);
1367 /* Check against the CSIRXCNT limit */ 1401 /* Check against the CSIRXCNT limit */
1368 if (pix->sizeimage > 4 * 0x3ffff) { 1402 if (pix->sizeimage > 4 * 0x3ffff) {
1369 /* Adjust geometry, preserve aspect ratio */ 1403 /* Adjust geometry, preserve aspect ratio */
1370 unsigned int new_height = int_sqrt(4 * 0x3ffff * 1404 unsigned int new_height = int_sqrt(div_u64(0x3ffffULL *
1371 pix->height / pix->bytesperline); 1405 4 * pix->height, pix->bytesperline));
1372 pix->width = new_height * pix->width / pix->height; 1406 pix->width = new_height * pix->width / pix->height;
1373 pix->height = new_height; 1407 pix->height = new_height;
1374 pix->bytesperline = soc_mbus_bytes_per_line(pix->width, 1408 pix->bytesperline = soc_mbus_bytes_per_line(pix->width,
1375 xlate->host_fmt); 1409 xlate->host_fmt);
1376 BUG_ON(pix->bytesperline < 0); 1410 BUG_ON(pix->bytesperline < 0);
1411 pix->sizeimage = soc_mbus_image_size(xlate->host_fmt,
1412 pix->bytesperline, pix->height);
1377 } 1413 }
1378 } 1414 }
1379 1415
@@ -1752,6 +1788,8 @@ static int __devinit mx2_camera_probe(struct platform_device *pdev)
1752 pcdev->soc_host.priv = pcdev; 1788 pcdev->soc_host.priv = pcdev;
1753 pcdev->soc_host.v4l2_dev.dev = &pdev->dev; 1789 pcdev->soc_host.v4l2_dev.dev = &pdev->dev;
1754 pcdev->soc_host.nr = pdev->id; 1790 pcdev->soc_host.nr = pdev->id;
1791 if (cpu_is_mx25())
1792 pcdev->soc_host.capabilities = SOCAM_HOST_CAP_STRIDE;
1755 1793
1756 pcdev->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev); 1794 pcdev->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
1757 if (IS_ERR(pcdev->alloc_ctx)) { 1795 if (IS_ERR(pcdev->alloc_ctx)) {