aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video
diff options
context:
space:
mode:
authorSylwester Nawrocki <s.nawrocki@samsung.com>2010-12-08 12:05:08 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2011-03-21 19:31:36 -0400
commitef7af59b2cf950a44576d4364459ffd3d5d1d9bc (patch)
tree6d9134410b750457347d32307ee28d9aed16d523 /drivers/media/video
parent2dab38e2272e9b30540e2782ef7aa8bc45848144 (diff)
[media] s5p-fimc: Conversion to multiplanar formats
Conversion to multiplanar color formats and minor cleanup. Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video')
-rw-r--r--drivers/media/video/s5p-fimc/fimc-capture.c114
-rw-r--r--drivers/media/video/s5p-fimc/fimc-core.c387
-rw-r--r--drivers/media/video/s5p-fimc/fimc-core.h37
-rw-r--r--drivers/media/video/s5p-fimc/fimc-reg.c14
4 files changed, 304 insertions, 248 deletions
diff --git a/drivers/media/video/s5p-fimc/fimc-capture.c b/drivers/media/video/s5p-fimc/fimc-capture.c
index 24b77b76e68d..e746b684c3b8 100644
--- a/drivers/media/video/s5p-fimc/fimc-capture.c
+++ b/drivers/media/video/s5p-fimc/fimc-capture.c
@@ -280,34 +280,16 @@ static int stop_streaming(struct vb2_queue *q)
280 return fimc_stop_capture(fimc); 280 return fimc_stop_capture(fimc);
281} 281}
282 282
283static unsigned int get_plane_size(struct fimc_frame *frame, unsigned int plane) 283static unsigned int get_plane_size(struct fimc_frame *fr, unsigned int plane)
284{ 284{
285 unsigned long size = 0; 285 if (!fr || plane >= fr->fmt->memplanes)
286
287 if (!frame || plane > frame->fmt->buff_cnt - 1)
288 return 0; 286 return 0;
289 287
290 if (1 == frame->fmt->planes_cnt) { 288 dbg("%s: w: %d. h: %d. depth[%d]: %d",
291 size = (frame->width * frame->height * frame->fmt->depth) >> 3; 289 __func__, fr->width, fr->height, plane, fr->fmt->depth[plane]);
292 } else if (frame->fmt->planes_cnt <= 3) { 290
293 switch (plane) { 291 return fr->f_width * fr->f_height * fr->fmt->depth[plane] / 8;
294 case 0:
295 size = frame->width * frame->height;
296 break;
297 case 1:
298 case 2:
299 if (S5P_FIMC_YCBCR420 == frame->fmt->color
300 && 2 != frame->fmt->planes_cnt)
301 size = (frame->width * frame->height) >> 2;
302 else /* 422 */
303 size = (frame->width * frame->height) >> 1;
304 break;
305 }
306 } else {
307 size = 0;
308 }
309 292
310 return size;
311} 293}
312 294
313static int queue_setup(struct vb2_queue *vq, unsigned int *num_buffers, 295static int queue_setup(struct vb2_queue *vq, unsigned int *num_buffers,
@@ -315,25 +297,24 @@ static int queue_setup(struct vb2_queue *vq, unsigned int *num_buffers,
315 void *allocators[]) 297 void *allocators[])
316{ 298{
317 struct fimc_ctx *ctx = vq->drv_priv; 299 struct fimc_ctx *ctx = vq->drv_priv;
318 struct fimc_fmt *fmt = fmt = ctx->d_frame.fmt; 300 struct fimc_fmt *fmt = ctx->d_frame.fmt;
319 struct fimc_frame *frame; 301 int i;
320 302
321 if (!fmt) 303 if (!fmt)
322 return -EINVAL; 304 return -EINVAL;
323 305
324 *num_planes = fmt->buff_cnt; 306 *num_planes = fmt->memplanes;
325 307
326 dbg("%s, buffer count=%d, plane count=%d", 308 dbg("%s, buffer count=%d, plane count=%d",
327 __func__, *num_buffers, *num_planes); 309 __func__, *num_buffers, *num_planes);
328
329 frame = ctx_get_frame(ctx, vq->type);
330 if (IS_ERR(frame))
331 return PTR_ERR(frame);
332 310
333 sizes[0] = get_plane_size(frame, 0); 311 for (i = 0; i < fmt->memplanes; i++) {
334 allocators[0] = ctx->fimc_dev->alloc_ctx; 312 sizes[i] = get_plane_size(&ctx->d_frame, i);
313 dbg("plane: %u, plane_size: %lu", i, sizes[i]);
314 allocators[i] = ctx->fimc_dev->alloc_ctx;
315 }
335 316
336 return -EINVAL; 317 return 0;
337} 318}
338 319
339static int buffer_init(struct vb2_buffer *vb) 320static int buffer_init(struct vb2_buffer *vb)
@@ -347,16 +328,13 @@ static int buffer_prepare(struct vb2_buffer *vb)
347 struct vb2_queue *vq = vb->vb2_queue; 328 struct vb2_queue *vq = vb->vb2_queue;
348 struct fimc_ctx *ctx = vq->drv_priv; 329 struct fimc_ctx *ctx = vq->drv_priv;
349 struct v4l2_device *v4l2_dev = &ctx->fimc_dev->m2m.v4l2_dev; 330 struct v4l2_device *v4l2_dev = &ctx->fimc_dev->m2m.v4l2_dev;
350 struct fimc_frame *frame;
351 unsigned long size;
352 int i; 331 int i;
353 332
354 frame = ctx_get_frame(ctx, vq->type); 333 if (!ctx->d_frame.fmt || vq->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
355 if (IS_ERR(frame)) 334 return -EINVAL;
356 return PTR_ERR(frame);
357 335
358 for (i = 0; i < frame->fmt->buff_cnt; i++) { 336 for (i = 0; i < ctx->d_frame.fmt->memplanes; i++) {
359 size = get_plane_size(frame, i); 337 unsigned long size = get_plane_size(&ctx->d_frame, i);
360 338
361 if (vb2_plane_size(vb, i) < size) { 339 if (vb2_plane_size(vb, i) < size) {
362 v4l2_err(v4l2_dev, "User buffer too small (%ld < %ld)\n", 340 v4l2_err(v4l2_dev, "User buffer too small (%ld < %ld)\n",
@@ -451,7 +429,6 @@ static int fimc_capture_close(struct file *file)
451 429
452 if (mutex_lock_interruptible(&fimc->lock)) 430 if (mutex_lock_interruptible(&fimc->lock))
453 return -ERESTARTSYS; 431 return -ERESTARTSYS;
454
455 dbg("pid: %d, state: 0x%lx", task_pid_nr(current), fimc->state); 432 dbg("pid: %d, state: 0x%lx", task_pid_nr(current), fimc->state);
456 433
457 if (--fimc->vid_cap.refcnt == 0) { 434 if (--fimc->vid_cap.refcnt == 0) {
@@ -519,7 +496,8 @@ static int fimc_vidioc_querycap_capture(struct file *file, void *priv,
519 strncpy(cap->card, fimc->pdev->name, sizeof(cap->card) - 1); 496 strncpy(cap->card, fimc->pdev->name, sizeof(cap->card) - 1);
520 cap->bus_info[0] = 0; 497 cap->bus_info[0] = 0;
521 cap->version = KERNEL_VERSION(1, 0, 0); 498 cap->version = KERNEL_VERSION(1, 0, 0);
522 cap->capabilities = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_CAPTURE; 499 cap->capabilities = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_CAPTURE |
500 V4L2_CAP_VIDEO_CAPTURE_MPLANE;
523 501
524 return 0; 502 return 0;
525} 503}
@@ -560,19 +538,20 @@ static int sync_capture_fmt(struct fimc_ctx *ctx)
560 return 0; 538 return 0;
561} 539}
562 540
563static int fimc_cap_s_fmt(struct file *file, void *priv, 541static int fimc_cap_s_fmt_mplane(struct file *file, void *priv,
564 struct v4l2_format *f) 542 struct v4l2_format *f)
565{ 543{
566 struct fimc_ctx *ctx = priv; 544 struct fimc_ctx *ctx = priv;
567 struct fimc_dev *fimc = ctx->fimc_dev; 545 struct fimc_dev *fimc = ctx->fimc_dev;
568 struct fimc_frame *frame; 546 struct fimc_frame *frame;
569 struct v4l2_pix_format *pix; 547 struct v4l2_pix_format_mplane *pix;
570 int ret; 548 int ret;
549 int i;
571 550
572 if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) 551 if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
573 return -EINVAL; 552 return -EINVAL;
574 553
575 ret = fimc_vidioc_try_fmt(file, priv, f); 554 ret = fimc_vidioc_try_fmt_mplane(file, priv, f);
576 if (ret) 555 if (ret)
577 return ret; 556 return ret;
578 557
@@ -583,10 +562,12 @@ static int fimc_cap_s_fmt(struct file *file, void *priv,
583 ret = -EBUSY; 562 ret = -EBUSY;
584 goto sf_unlock; 563 goto sf_unlock;
585 } 564 }
565 if (vb2_is_streaming(&fimc->vid_cap.vbq) || fimc_capture_active(fimc))
566 return -EBUSY;
586 567
587 frame = &ctx->d_frame; 568 frame = &ctx->d_frame;
588 569
589 pix = &f->fmt.pix; 570 pix = &f->fmt.pix_mp;
590 frame->fmt = find_format(f, FMT_FLAGS_M2M | FMT_FLAGS_CAM); 571 frame->fmt = find_format(f, FMT_FLAGS_M2M | FMT_FLAGS_CAM);
591 if (!frame->fmt) { 572 if (!frame->fmt) {
592 err("fimc target format not found\n"); 573 err("fimc target format not found\n");
@@ -594,14 +575,17 @@ static int fimc_cap_s_fmt(struct file *file, void *priv,
594 goto sf_unlock; 575 goto sf_unlock;
595 } 576 }
596 577
578 for (i = 0; i < frame->fmt->colplanes; i++)
579 frame->payload[i] = pix->plane_fmt[i].bytesperline * pix->height;
580
597 /* Output DMA frame pixel size and offsets. */ 581 /* Output DMA frame pixel size and offsets. */
598 frame->f_width = pix->bytesperline * 8 / frame->fmt->depth; 582 frame->f_width = pix->plane_fmt[0].bytesperline * 8
583 / frame->fmt->depth[0];
599 frame->f_height = pix->height; 584 frame->f_height = pix->height;
600 frame->width = pix->width; 585 frame->width = pix->width;
601 frame->height = pix->height; 586 frame->height = pix->height;
602 frame->o_width = pix->width; 587 frame->o_width = pix->width;
603 frame->o_height = pix->height; 588 frame->o_height = pix->height;
604 frame->size = (pix->width * pix->height * frame->fmt->depth) >> 3;
605 frame->offs_h = 0; 589 frame->offs_h = 0;
606 frame->offs_v = 0; 590 frame->offs_v = 0;
607 591
@@ -769,7 +753,7 @@ static int fimc_cap_streamoff(struct file *file, void *priv,
769} 753}
770 754
771static int fimc_cap_reqbufs(struct file *file, void *priv, 755static int fimc_cap_reqbufs(struct file *file, void *priv,
772 struct v4l2_requestbuffers *reqbufs) 756 struct v4l2_requestbuffers *reqbufs)
773{ 757{
774 struct fimc_ctx *ctx = priv; 758 struct fimc_ctx *ctx = priv;
775 struct fimc_dev *fimc = ctx->fimc_dev; 759 struct fimc_dev *fimc = ctx->fimc_dev;
@@ -870,13 +854,13 @@ static int fimc_cap_cropcap(struct file *file, void *fh,
870 struct fimc_ctx *ctx = fh; 854 struct fimc_ctx *ctx = fh;
871 struct fimc_dev *fimc = ctx->fimc_dev; 855 struct fimc_dev *fimc = ctx->fimc_dev;
872 856
873 if (cr->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) 857 if (cr->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
874 return -EINVAL; 858 return -EINVAL;
875 859
876 if (mutex_lock_interruptible(&fimc->lock)) 860 if (mutex_lock_interruptible(&fimc->lock))
877 return -ERESTARTSYS; 861 return -ERESTARTSYS;
878
879 f = &ctx->s_frame; 862 f = &ctx->s_frame;
863
880 cr->bounds.left = 0; 864 cr->bounds.left = 0;
881 cr->bounds.top = 0; 865 cr->bounds.top = 0;
882 cr->bounds.width = f->o_width; 866 cr->bounds.width = f->o_width;
@@ -953,10 +937,10 @@ sc_unlock:
953static const struct v4l2_ioctl_ops fimc_capture_ioctl_ops = { 937static const struct v4l2_ioctl_ops fimc_capture_ioctl_ops = {
954 .vidioc_querycap = fimc_vidioc_querycap_capture, 938 .vidioc_querycap = fimc_vidioc_querycap_capture,
955 939
956 .vidioc_enum_fmt_vid_cap = fimc_vidioc_enum_fmt, 940 .vidioc_enum_fmt_vid_cap_mplane = fimc_vidioc_enum_fmt_mplane,
957 .vidioc_try_fmt_vid_cap = fimc_vidioc_try_fmt, 941 .vidioc_try_fmt_vid_cap_mplane = fimc_vidioc_try_fmt_mplane,
958 .vidioc_s_fmt_vid_cap = fimc_cap_s_fmt, 942 .vidioc_s_fmt_vid_cap_mplane = fimc_cap_s_fmt_mplane,
959 .vidioc_g_fmt_vid_cap = fimc_vidioc_g_fmt, 943 .vidioc_g_fmt_vid_cap_mplane = fimc_vidioc_g_fmt_mplane,
960 944
961 .vidioc_reqbufs = fimc_cap_reqbufs, 945 .vidioc_reqbufs = fimc_cap_reqbufs,
962 .vidioc_querybuf = fimc_cap_querybuf, 946 .vidioc_querybuf = fimc_cap_querybuf,
@@ -980,6 +964,7 @@ static const struct v4l2_ioctl_ops fimc_capture_ioctl_ops = {
980 .vidioc_g_input = fimc_cap_g_input, 964 .vidioc_g_input = fimc_cap_g_input,
981}; 965};
982 966
967/* fimc->lock must be already initialized */
983int fimc_register_capture_device(struct fimc_dev *fimc) 968int fimc_register_capture_device(struct fimc_dev *fimc)
984{ 969{
985 struct v4l2_device *v4l2_dev = &fimc->vid_cap.v4l2_dev; 970 struct v4l2_device *v4l2_dev = &fimc->vid_cap.v4l2_dev;
@@ -987,6 +972,7 @@ int fimc_register_capture_device(struct fimc_dev *fimc)
987 struct fimc_vid_cap *vid_cap; 972 struct fimc_vid_cap *vid_cap;
988 struct fimc_ctx *ctx; 973 struct fimc_ctx *ctx;
989 struct v4l2_format f; 974 struct v4l2_format f;
975 struct fimc_frame *fr;
990 struct vb2_queue *q; 976 struct vb2_queue *q;
991 int ret; 977 int ret;
992 978
@@ -999,8 +985,12 @@ int fimc_register_capture_device(struct fimc_dev *fimc)
999 ctx->out_path = FIMC_DMA; 985 ctx->out_path = FIMC_DMA;
1000 ctx->state = FIMC_CTX_CAP; 986 ctx->state = FIMC_CTX_CAP;
1001 987
1002 f.fmt.pix.pixelformat = V4L2_PIX_FMT_RGB24; 988 /* Default format of the output frames */
1003 ctx->d_frame.fmt = find_format(&f, FMT_FLAGS_M2M); 989 f.fmt.pix.pixelformat = V4L2_PIX_FMT_RGB32;
990 fr = &ctx->d_frame;
991 fr->fmt = find_format(&f, FMT_FLAGS_M2M);
992 fr->width = fr->f_width = fr->o_width = 640;
993 fr->height = fr->f_height = fr->o_height = 480;
1004 994
1005 if (!v4l2_dev->name[0]) 995 if (!v4l2_dev->name[0])
1006 snprintf(v4l2_dev->name, sizeof(v4l2_dev->name), 996 snprintf(v4l2_dev->name, sizeof(v4l2_dev->name),
@@ -1030,7 +1020,7 @@ int fimc_register_capture_device(struct fimc_dev *fimc)
1030 vid_cap->active_buf_cnt = 0; 1020 vid_cap->active_buf_cnt = 0;
1031 vid_cap->reqbufs_count = 0; 1021 vid_cap->reqbufs_count = 0;
1032 vid_cap->refcnt = 0; 1022 vid_cap->refcnt = 0;
1033 /* The default color format for image sensor. */ 1023 /* Default color format for image sensor */
1034 vid_cap->fmt.code = V4L2_MBUS_FMT_YUYV8_2X8; 1024 vid_cap->fmt.code = V4L2_MBUS_FMT_YUYV8_2X8;
1035 1025
1036 INIT_LIST_HEAD(&vid_cap->pending_buf_q); 1026 INIT_LIST_HEAD(&vid_cap->pending_buf_q);
@@ -1040,7 +1030,7 @@ int fimc_register_capture_device(struct fimc_dev *fimc)
1040 1030
1041 q = &fimc->vid_cap.vbq; 1031 q = &fimc->vid_cap.vbq;
1042 memset(q, 0, sizeof(*q)); 1032 memset(q, 0, sizeof(*q));
1043 q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 1033 q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1044 q->io_modes = VB2_MMAP | VB2_USERPTR; 1034 q->io_modes = VB2_MMAP | VB2_USERPTR;
1045 q->drv_priv = fimc->vid_cap.ctx; 1035 q->drv_priv = fimc->vid_cap.ctx;
1046 q->ops = &fimc_capture_qops; 1036 q->ops = &fimc_capture_qops;
diff --git a/drivers/media/video/s5p-fimc/fimc-core.c b/drivers/media/video/s5p-fimc/fimc-core.c
index 65d25b374f5c..fe210976f30b 100644
--- a/drivers/media/video/s5p-fimc/fimc-core.c
+++ b/drivers/media/video/s5p-fimc/fimc-core.c
@@ -34,106 +34,130 @@ static char *fimc_clock_name[NUM_FIMC_CLOCKS] = { "sclk_fimc", "fimc" };
34 34
35static struct fimc_fmt fimc_formats[] = { 35static struct fimc_fmt fimc_formats[] = {
36 { 36 {
37 .name = "RGB565", 37 .name = "RGB565",
38 .fourcc = V4L2_PIX_FMT_RGB565X, 38 .fourcc = V4L2_PIX_FMT_RGB565X,
39 .depth = 16, 39 .depth = { 16 },
40 .color = S5P_FIMC_RGB565, 40 .color = S5P_FIMC_RGB565,
41 .buff_cnt = 1, 41 .memplanes = 1,
42 .planes_cnt = 1, 42 .colplanes = 1,
43 .mbus_code = V4L2_MBUS_FMT_RGB565_2X8_BE, 43 .mbus_code = V4L2_MBUS_FMT_RGB565_2X8_BE,
44 .flags = FMT_FLAGS_M2M, 44 .flags = FMT_FLAGS_M2M,
45 }, { 45 }, {
46 .name = "BGR666", 46 .name = "BGR666",
47 .fourcc = V4L2_PIX_FMT_BGR666, 47 .fourcc = V4L2_PIX_FMT_BGR666,
48 .depth = 32, 48 .depth = { 32 },
49 .color = S5P_FIMC_RGB666, 49 .color = S5P_FIMC_RGB666,
50 .buff_cnt = 1, 50 .memplanes = 1,
51 .planes_cnt = 1, 51 .colplanes = 1,
52 .flags = FMT_FLAGS_M2M, 52 .flags = FMT_FLAGS_M2M,
53 }, { 53 }, {
54 .name = "XRGB-8-8-8-8, 32 bpp", 54 .name = "XRGB-8-8-8-8, 32 bpp",
55 .fourcc = V4L2_PIX_FMT_RGB32, 55 .fourcc = V4L2_PIX_FMT_RGB32,
56 .depth = 32, 56 .depth = { 32 },
57 .color = S5P_FIMC_RGB888, 57 .color = S5P_FIMC_RGB888,
58 .buff_cnt = 1, 58 .memplanes = 1,
59 .planes_cnt = 1, 59 .colplanes = 1,
60 .flags = FMT_FLAGS_M2M, 60 .flags = FMT_FLAGS_M2M,
61 }, { 61 }, {
62 .name = "YUV 4:2:2 packed, YCbYCr", 62 .name = "YUV 4:2:2 packed, YCbYCr",
63 .fourcc = V4L2_PIX_FMT_YUYV, 63 .fourcc = V4L2_PIX_FMT_YUYV,
64 .depth = 16, 64 .depth = { 16 },
65 .color = S5P_FIMC_YCBYCR422, 65 .color = S5P_FIMC_YCBYCR422,
66 .buff_cnt = 1, 66 .memplanes = 1,
67 .planes_cnt = 1, 67 .colplanes = 1,
68 .mbus_code = V4L2_MBUS_FMT_YUYV8_2X8, 68 .mbus_code = V4L2_MBUS_FMT_YUYV8_2X8,
69 .flags = FMT_FLAGS_M2M | FMT_FLAGS_CAM, 69 .flags = FMT_FLAGS_M2M | FMT_FLAGS_CAM,
70 }, { 70 }, {
71 .name = "YUV 4:2:2 packed, CbYCrY", 71 .name = "YUV 4:2:2 packed, CbYCrY",
72 .fourcc = V4L2_PIX_FMT_UYVY, 72 .fourcc = V4L2_PIX_FMT_UYVY,
73 .depth = 16, 73 .depth = { 16 },
74 .color = S5P_FIMC_CBYCRY422, 74 .color = S5P_FIMC_CBYCRY422,
75 .buff_cnt = 1, 75 .memplanes = 1,
76 .planes_cnt = 1, 76 .colplanes = 1,
77 .mbus_code = V4L2_MBUS_FMT_UYVY8_2X8, 77 .mbus_code = V4L2_MBUS_FMT_UYVY8_2X8,
78 .flags = FMT_FLAGS_M2M | FMT_FLAGS_CAM, 78 .flags = FMT_FLAGS_M2M | FMT_FLAGS_CAM,
79 }, { 79 }, {
80 .name = "YUV 4:2:2 packed, CrYCbY", 80 .name = "YUV 4:2:2 packed, CrYCbY",
81 .fourcc = V4L2_PIX_FMT_VYUY, 81 .fourcc = V4L2_PIX_FMT_VYUY,
82 .depth = 16, 82 .depth = { 16 },
83 .color = S5P_FIMC_CRYCBY422, 83 .color = S5P_FIMC_CRYCBY422,
84 .buff_cnt = 1, 84 .memplanes = 1,
85 .planes_cnt = 1, 85 .colplanes = 1,
86 .mbus_code = V4L2_MBUS_FMT_VYUY8_2X8, 86 .mbus_code = V4L2_MBUS_FMT_VYUY8_2X8,
87 .flags = FMT_FLAGS_M2M | FMT_FLAGS_CAM, 87 .flags = FMT_FLAGS_M2M | FMT_FLAGS_CAM,
88 }, { 88 }, {
89 .name = "YUV 4:2:2 packed, YCrYCb", 89 .name = "YUV 4:2:2 packed, YCrYCb",
90 .fourcc = V4L2_PIX_FMT_YVYU, 90 .fourcc = V4L2_PIX_FMT_YVYU,
91 .depth = 16, 91 .depth = { 16 },
92 .color = S5P_FIMC_YCRYCB422, 92 .color = S5P_FIMC_YCRYCB422,
93 .buff_cnt = 1, 93 .memplanes = 1,
94 .planes_cnt = 1, 94 .colplanes = 1,
95 .mbus_code = V4L2_MBUS_FMT_YVYU8_2X8, 95 .mbus_code = V4L2_MBUS_FMT_YVYU8_2X8,
96 .flags = FMT_FLAGS_M2M | FMT_FLAGS_CAM, 96 .flags = FMT_FLAGS_M2M | FMT_FLAGS_CAM,
97 }, { 97 }, {
98 .name = "YUV 4:2:2 planar, Y/Cb/Cr", 98 .name = "YUV 4:2:2 planar, Y/Cb/Cr",
99 .fourcc = V4L2_PIX_FMT_YUV422P, 99 .fourcc = V4L2_PIX_FMT_YUV422P,
100 .depth = 12, 100 .depth = { 12 },
101 .color = S5P_FIMC_YCBCR422, 101 .color = S5P_FIMC_YCBYCR422,
102 .buff_cnt = 1, 102 .memplanes = 1,
103 .planes_cnt = 3, 103 .colplanes = 3,
104 .flags = FMT_FLAGS_M2M, 104 .flags = FMT_FLAGS_M2M,
105 }, { 105 }, {
106 .name = "YUV 4:2:2 planar, Y/CbCr", 106 .name = "YUV 4:2:2 planar, Y/CbCr",
107 .fourcc = V4L2_PIX_FMT_NV16, 107 .fourcc = V4L2_PIX_FMT_NV16,
108 .depth = 16, 108 .depth = { 16 },
109 .color = S5P_FIMC_YCBCR422, 109 .color = S5P_FIMC_YCBYCR422,
110 .buff_cnt = 1, 110 .memplanes = 1,
111 .planes_cnt = 2, 111 .colplanes = 2,
112 .flags = FMT_FLAGS_M2M, 112 .flags = FMT_FLAGS_M2M,
113 }, { 113 }, {
114 .name = "YUV 4:2:2 planar, Y/CrCb", 114 .name = "YUV 4:2:2 planar, Y/CrCb",
115 .fourcc = V4L2_PIX_FMT_NV61, 115 .fourcc = V4L2_PIX_FMT_NV61,
116 .depth = 16, 116 .depth = { 16 },
117 .color = S5P_FIMC_RGB565, 117 .color = S5P_FIMC_YCRYCB422,
118 .buff_cnt = 1, 118 .memplanes = 1,
119 .planes_cnt = 2, 119 .colplanes = 2,
120 .flags = FMT_FLAGS_M2M, 120 .flags = FMT_FLAGS_M2M,
121 }, { 121 }, {
122 .name = "YUV 4:2:0 planar, YCbCr", 122 .name = "YUV 4:2:0 planar, YCbCr",
123 .fourcc = V4L2_PIX_FMT_YUV420, 123 .fourcc = V4L2_PIX_FMT_YUV420,
124 .depth = 12, 124 .depth = { 12 },
125 .color = S5P_FIMC_YCBCR420, 125 .color = S5P_FIMC_YCBCR420,
126 .buff_cnt = 1, 126 .memplanes = 1,
127 .planes_cnt = 3, 127 .colplanes = 3,
128 .flags = FMT_FLAGS_M2M, 128 .flags = FMT_FLAGS_M2M,
129 }, { 129 }, {
130 .name = "YUV 4:2:0 planar, Y/CbCr", 130 .name = "YUV 4:2:0 planar, Y/CbCr",
131 .fourcc = V4L2_PIX_FMT_NV12, 131 .fourcc = V4L2_PIX_FMT_NV12,
132 .depth = 12, 132 .depth = { 12 },
133 .color = S5P_FIMC_YCBCR420, 133 .color = S5P_FIMC_YCBCR420,
134 .buff_cnt = 1, 134 .memplanes = 1,
135 .planes_cnt = 2, 135 .colplanes = 2,
136 .flags = FMT_FLAGS_M2M, 136 .flags = FMT_FLAGS_M2M,
137 }, {
138 .name = "YUV 4:2:0 non-contiguous 2-planar, Y/CbCr",
139 .fourcc = V4L2_PIX_FMT_NV12M,
140 .color = S5P_FIMC_YCBCR420,
141 .depth = { 8, 4 },
142 .memplanes = 2,
143 .colplanes = 2,
144 .flags = FMT_FLAGS_M2M,
145 }, {
146 .name = "YUV 4:2:0 non-contiguous 3-planar, Y/Cb/Cr",
147 .fourcc = V4L2_PIX_FMT_YUV420M,
148 .color = S5P_FIMC_YCBCR420,
149 .depth = { 8, 2, 2 },
150 .memplanes = 3,
151 .colplanes = 3,
152 .flags = FMT_FLAGS_M2M,
153 }, {
154 .name = "YUV 4:2:0 non-contiguous 2-planar, Y/CbCr, tiled",
155 .fourcc = V4L2_PIX_FMT_NV12MT,
156 .color = S5P_FIMC_YCBCR420,
157 .depth = { 8, 4 },
158 .memplanes = 2,
159 .colplanes = 2,
160 .flags = FMT_FLAGS_M2M,
137 }, 161 },
138}; 162};
139 163
@@ -359,7 +383,7 @@ isr_unlock:
359 return IRQ_HANDLED; 383 return IRQ_HANDLED;
360} 384}
361 385
362/* The color format (planes_cnt, buff_cnt) must be already configured. */ 386/* The color format (colplanes, memplanes) must be already configured. */
363int fimc_prepare_addr(struct fimc_ctx *ctx, struct vb2_buffer *vb, 387int fimc_prepare_addr(struct fimc_ctx *ctx, struct vb2_buffer *vb,
364 struct fimc_frame *frame, struct fimc_addr *paddr) 388 struct fimc_frame *frame, struct fimc_addr *paddr)
365{ 389{
@@ -371,13 +395,13 @@ int fimc_prepare_addr(struct fimc_ctx *ctx, struct vb2_buffer *vb,
371 395
372 pix_size = frame->width * frame->height; 396 pix_size = frame->width * frame->height;
373 397
374 dbg("buff_cnt= %d, planes_cnt= %d, frame->size= %d, pix_size= %d", 398 dbg("memplanes= %d, colplanes= %d, pix_size= %d",
375 frame->fmt->buff_cnt, frame->fmt->planes_cnt, 399 frame->fmt->memplanes, frame->fmt->colplanes, pix_size);
376 frame->size, pix_size); 400
401 paddr->y = vb2_dma_contig_plane_paddr(vb, 0);
377 402
378 if (frame->fmt->buff_cnt == 1) { 403 if (frame->fmt->memplanes == 1) {
379 paddr->y = vb2_dma_contig_plane_paddr(vb, 0); 404 switch (frame->fmt->colplanes) {
380 switch (frame->fmt->planes_cnt) {
381 case 1: 405 case 1:
382 paddr->cb = 0; 406 paddr->cb = 0;
383 paddr->cr = 0; 407 paddr->cr = 0;
@@ -400,6 +424,12 @@ int fimc_prepare_addr(struct fimc_ctx *ctx, struct vb2_buffer *vb,
400 default: 424 default:
401 return -EINVAL; 425 return -EINVAL;
402 } 426 }
427 } else {
428 if (frame->fmt->memplanes >= 2)
429 paddr->cb = vb2_dma_contig_plane_paddr(vb, 1);
430
431 if (frame->fmt->memplanes == 3)
432 paddr->cr = vb2_dma_contig_plane_paddr(vb, 2);
403 } 433 }
404 434
405 dbg("PHYS_ADDR: y= 0x%X cb= 0x%X cr= 0x%X ret= %d", 435 dbg("PHYS_ADDR: y= 0x%X cb= 0x%X cr= 0x%X ret= %d",
@@ -454,10 +484,14 @@ static void fimc_set_yuv_order(struct fimc_ctx *ctx)
454static void fimc_prepare_dma_offset(struct fimc_ctx *ctx, struct fimc_frame *f) 484static void fimc_prepare_dma_offset(struct fimc_ctx *ctx, struct fimc_frame *f)
455{ 485{
456 struct samsung_fimc_variant *variant = ctx->fimc_dev->variant; 486 struct samsung_fimc_variant *variant = ctx->fimc_dev->variant;
487 u32 i, depth = 0;
488
489 for (i = 0; i < f->fmt->colplanes; i++)
490 depth += f->fmt->depth[i];
457 491
458 f->dma_offset.y_h = f->offs_h; 492 f->dma_offset.y_h = f->offs_h;
459 if (!variant->pix_hoff) 493 if (!variant->pix_hoff)
460 f->dma_offset.y_h *= (f->fmt->depth >> 3); 494 f->dma_offset.y_h *= (depth >> 3);
461 495
462 f->dma_offset.y_v = f->offs_v; 496 f->dma_offset.y_v = f->offs_v;
463 497
@@ -468,7 +502,7 @@ static void fimc_prepare_dma_offset(struct fimc_ctx *ctx, struct fimc_frame *f)
468 f->dma_offset.cr_v = f->offs_v; 502 f->dma_offset.cr_v = f->offs_v;
469 503
470 if (!variant->pix_hoff) { 504 if (!variant->pix_hoff) {
471 if (f->fmt->planes_cnt == 3) { 505 if (f->fmt->colplanes == 3) {
472 f->dma_offset.cb_h >>= 1; 506 f->dma_offset.cb_h >>= 1;
473 f->dma_offset.cr_h >>= 1; 507 f->dma_offset.cr_h >>= 1;
474 } 508 }
@@ -596,20 +630,31 @@ static void fimc_job_abort(void *priv)
596} 630}
597 631
598static int fimc_queue_setup(struct vb2_queue *vq, unsigned int *num_buffers, 632static int fimc_queue_setup(struct vb2_queue *vq, unsigned int *num_buffers,
599 unsigned int *num_planes, unsigned long sizes[], 633 unsigned int *num_planes, unsigned long sizes[],
600 void *allocators[]) 634 void *allocators[])
601{ 635{
602 struct fimc_ctx *ctx = vb2_get_drv_priv(vq); 636 struct fimc_ctx *ctx = vb2_get_drv_priv(vq);
603 struct fimc_frame *fr; 637 struct fimc_frame *f;
638 int i;
639
640 f = ctx_get_frame(ctx, vq->type);
641 if (IS_ERR(f))
642 return PTR_ERR(f);
604 643
605 fr = ctx_get_frame(ctx, vq->type); 644 /*
606 if (IS_ERR(fr)) 645 * Return number of non-contigous planes (plane buffers)
607 return PTR_ERR(fr); 646 * depending on the configured color format.
647 */
648 if (f->fmt)
649 *num_planes = f->fmt->memplanes;
608 650
609 *num_planes = 1; 651 for (i = 0; i < f->fmt->memplanes; i++) {
652 sizes[i] = (f->width * f->height * f->fmt->depth[i]) >> 3;
653 allocators[i] = ctx->fimc_dev->alloc_ctx;
654 }
610 655
611 sizes[0] = (fr->width * fr->height * fr->fmt->depth) >> 3; 656 if (*num_buffers == 0)
612 allocators[0] = ctx->fimc_dev->alloc_ctx; 657 *num_buffers = 1;
613 658
614 return 0; 659 return 0;
615} 660}
@@ -618,18 +663,15 @@ static int fimc_buf_prepare(struct vb2_buffer *vb)
618{ 663{
619 struct fimc_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); 664 struct fimc_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
620 struct fimc_frame *frame; 665 struct fimc_frame *frame;
666 int i;
621 667
622 frame = ctx_get_frame(ctx, vb->vb2_queue->type); 668 frame = ctx_get_frame(ctx, vb->vb2_queue->type);
623 if (IS_ERR(frame)) 669 if (IS_ERR(frame))
624 return PTR_ERR(frame); 670 return PTR_ERR(frame);
625 671
626 if (vb2_plane_size(vb, 0) < frame->size) { 672 for (i = 0; i < frame->fmt->memplanes; i++)
627 dbg("%s data will not fit into plane (%lu < %lu)\n", 673 vb2_set_plane_payload(vb, i, frame->payload[i]);
628 __func__, vb2_plane_size(vb, 0), (long)frame->size);
629 return -EINVAL;
630 }
631 674
632 vb2_set_plane_payload(vb, 0, frame->size);
633 return 0; 675 return 0;
634} 676}
635 677
@@ -674,12 +716,13 @@ static int fimc_m2m_querycap(struct file *file, void *priv,
674 cap->bus_info[0] = 0; 716 cap->bus_info[0] = 0;
675 cap->version = KERNEL_VERSION(1, 0, 0); 717 cap->version = KERNEL_VERSION(1, 0, 0);
676 cap->capabilities = V4L2_CAP_STREAMING | 718 cap->capabilities = V4L2_CAP_STREAMING |
677 V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT; 719 V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT |
720 V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_VIDEO_OUTPUT_MPLANE;
678 721
679 return 0; 722 return 0;
680} 723}
681 724
682int fimc_vidioc_enum_fmt(struct file *file, void *priv, 725int fimc_vidioc_enum_fmt_mplane(struct file *file, void *priv,
683 struct v4l2_fmtdesc *f) 726 struct v4l2_fmtdesc *f)
684{ 727{
685 struct fimc_fmt *fmt; 728 struct fimc_fmt *fmt;
@@ -694,7 +737,8 @@ int fimc_vidioc_enum_fmt(struct file *file, void *priv,
694 return 0; 737 return 0;
695} 738}
696 739
697int fimc_vidioc_g_fmt(struct file *file, void *priv, struct v4l2_format *f) 740int fimc_vidioc_g_fmt_mplane(struct file *file, void *priv,
741 struct v4l2_format *f)
698{ 742{
699 struct fimc_ctx *ctx = priv; 743 struct fimc_ctx *ctx = priv;
700 struct fimc_dev *fimc = ctx->fimc_dev; 744 struct fimc_dev *fimc = ctx->fimc_dev;
@@ -747,29 +791,28 @@ struct fimc_fmt *find_mbus_format(struct v4l2_mbus_framefmt *f,
747} 791}
748 792
749 793
750int fimc_vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f) 794int fimc_vidioc_try_fmt_mplane(struct file *file, void *priv,
795 struct v4l2_format *f)
751{ 796{
752 struct fimc_ctx *ctx = priv; 797 struct fimc_ctx *ctx = priv;
753 struct fimc_dev *fimc = ctx->fimc_dev; 798 struct fimc_dev *fimc = ctx->fimc_dev;
754 struct samsung_fimc_variant *variant = fimc->variant; 799 struct samsung_fimc_variant *variant = fimc->variant;
755 struct v4l2_pix_format *pix = &f->fmt.pix; 800 struct v4l2_pix_format_mplane *pix = &f->fmt.pix_mp;
756 struct fimc_fmt *fmt; 801 struct fimc_fmt *fmt;
757 u32 max_width, mod_x, mod_y, mask; 802 u32 max_width, mod_x, mod_y, mask;
758 int ret = -EINVAL, is_output = 0; 803 int ret, i, is_output = 0;
759 804
760 if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) { 805 if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
761 if (ctx->state & FIMC_CTX_CAP) 806 if (ctx->state & FIMC_CTX_CAP)
762 return -EINVAL; 807 return -EINVAL;
763 is_output = 1; 808 is_output = 1;
764 } else if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { 809 } else if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
765 return -EINVAL; 810 return -EINVAL;
766 } 811 }
767 812
768 dbg("w: %d, h: %d, bpl: %d",
769 pix->width, pix->height, pix->bytesperline);
770
771 if (mutex_lock_interruptible(&fimc->lock)) 813 if (mutex_lock_interruptible(&fimc->lock))
772 return -ERESTARTSYS; 814 return -ERESTARTSYS;
815 dbg("w: %d, h: %d", pix->width, pix->height);
773 816
774 mask = is_output ? FMT_FLAGS_M2M : FMT_FLAGS_M2M | FMT_FLAGS_CAM; 817 mask = is_output ? FMT_FLAGS_M2M : FMT_FLAGS_M2M | FMT_FLAGS_CAM;
775 fmt = find_format(f, mask); 818 fmt = find_format(f, mask);
@@ -796,7 +839,7 @@ int fimc_vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f)
796 mod_x = 6; /* 64 x 32 pixels tile */ 839 mod_x = 6; /* 64 x 32 pixels tile */
797 mod_y = 5; 840 mod_y = 5;
798 } else { 841 } else {
799 if (fimc->id == 1 && fimc->variant->pix_hoff) 842 if (fimc->id == 1 && variant->pix_hoff)
800 mod_y = fimc_fmt_is_rgb(fmt->color) ? 0 : 1; 843 mod_y = fimc_fmt_is_rgb(fmt->color) ? 0 : 1;
801 else 844 else
802 mod_y = mod_x; 845 mod_y = mod_x;
@@ -807,15 +850,26 @@ int fimc_vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f)
807 v4l_bound_align_image(&pix->width, 16, max_width, mod_x, 850 v4l_bound_align_image(&pix->width, 16, max_width, mod_x,
808 &pix->height, 8, variant->pix_limit->scaler_dis_w, mod_y, 0); 851 &pix->height, 8, variant->pix_limit->scaler_dis_w, mod_y, 0);
809 852
810 if (pix->bytesperline == 0 || 853 pix->num_planes = fmt->memplanes;
811 (pix->bytesperline * 8 / fmt->depth) > pix->width) 854
812 pix->bytesperline = (pix->width * fmt->depth) >> 3; 855 for (i = 0; i < pix->num_planes; ++i) {
856 int bpl = pix->plane_fmt[i].bytesperline;
857
858 dbg("[%d] bpl: %d, depth: %d, w: %d, h: %d",
859 i, bpl, fmt->depth[i], pix->width, pix->height);
813 860
814 if (pix->sizeimage == 0) 861 if (!bpl || (bpl * 8 / fmt->depth[i]) > pix->width)
815 pix->sizeimage = pix->height * pix->bytesperline; 862 bpl = (pix->width * fmt->depth[0]) >> 3;
816 863
817 dbg("w: %d, h: %d, bpl: %d, depth: %d", 864 if (!pix->plane_fmt[i].sizeimage)
818 pix->width, pix->height, pix->bytesperline, fmt->depth); 865 pix->plane_fmt[i].sizeimage = pix->height * bpl;
866
867 pix->plane_fmt[i].bytesperline = bpl;
868
869 dbg("[%d]: bpl: %d, sizeimage: %d",
870 i, pix->plane_fmt[i].bytesperline,
871 pix->plane_fmt[i].sizeimage);
872 }
819 873
820 ret = 0; 874 ret = 0;
821 875
@@ -824,18 +878,18 @@ tf_out:
824 return ret; 878 return ret;
825} 879}
826 880
827static int fimc_m2m_s_fmt(struct file *file, void *priv, struct v4l2_format *f) 881static int fimc_m2m_s_fmt_mplane(struct file *file, void *priv,
882 struct v4l2_format *f)
828{ 883{
829 struct fimc_ctx *ctx = priv; 884 struct fimc_ctx *ctx = priv;
830 struct fimc_dev *fimc = ctx->fimc_dev; 885 struct fimc_dev *fimc = ctx->fimc_dev;
831 struct v4l2_device *v4l2_dev = &fimc->m2m.v4l2_dev;
832 struct vb2_queue *vq; 886 struct vb2_queue *vq;
833 struct fimc_frame *frame; 887 struct fimc_frame *frame;
834 struct v4l2_pix_format *pix; 888 struct v4l2_pix_format_mplane *pix;
835 unsigned long flags; 889 unsigned long flags;
836 int ret = 0; 890 int i, ret = 0;
837 891
838 ret = fimc_vidioc_try_fmt(file, priv, f); 892 ret = fimc_vidioc_try_fmt_mplane(file, priv, f);
839 if (ret) 893 if (ret)
840 return ret; 894 return ret;
841 895
@@ -845,35 +899,40 @@ static int fimc_m2m_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
845 vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type); 899 vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type);
846 900
847 if (vb2_is_streaming(vq)) { 901 if (vb2_is_streaming(vq)) {
848 v4l2_err(v4l2_dev, "%s: queue (%d) busy\n", __func__, f->type); 902 v4l2_err(&fimc->vid_cap.v4l2_dev, "%s: queue (%d) busy\n",
903 __func__, f->type);
849 ret = -EBUSY; 904 ret = -EBUSY;
850 goto sf_out; 905 goto sf_out;
851 } 906 }
852 907
853 spin_lock_irqsave(&ctx->slock, flags); 908 spin_lock_irqsave(&ctx->slock, flags);
854 if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) { 909 if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
855 frame = &ctx->s_frame; 910 frame = &ctx->s_frame;
856 ctx->state |= FIMC_SRC_FMT; 911 ctx->state |= FIMC_SRC_FMT;
857 } else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { 912 } else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
858 frame = &ctx->d_frame; 913 frame = &ctx->d_frame;
859 ctx->state |= FIMC_DST_FMT; 914 ctx->state |= FIMC_DST_FMT;
860 } else { 915 } else {
861 spin_unlock_irqrestore(&ctx->slock, flags); 916 spin_unlock_irqrestore(&ctx->slock, flags);
862 v4l2_err(&ctx->fimc_dev->m2m.v4l2_dev, 917 v4l2_err(&fimc->m2m.v4l2_dev,
863 "Wrong buffer/video queue type (%d)\n", f->type); 918 "Wrong buffer/video queue type (%d)\n", f->type);
864 ret = -EINVAL; 919 ret = -EINVAL;
865 goto sf_out; 920 goto sf_out;
866 } 921 }
867 spin_unlock_irqrestore(&ctx->slock, flags); 922 spin_unlock_irqrestore(&ctx->slock, flags);
868 923
869 pix = &f->fmt.pix; 924 pix = &f->fmt.pix_mp;
870 frame->fmt = find_format(f, FMT_FLAGS_M2M); 925 frame->fmt = find_format(f, FMT_FLAGS_M2M);
871 if (!frame->fmt) { 926 if (!frame->fmt) {
872 ret = -EINVAL; 927 ret = -EINVAL;
873 goto sf_out; 928 goto sf_out;
874 } 929 }
875 930
876 frame->f_width = pix->bytesperline * 8 / frame->fmt->depth; 931 for (i = 0; i < frame->fmt->colplanes; i++)
932 frame->payload[i] = pix->plane_fmt[i].bytesperline * pix->height;
933
934 frame->f_width = pix->plane_fmt[0].bytesperline * 8 /
935 frame->fmt->depth[0];
877 frame->f_height = pix->height; 936 frame->f_height = pix->height;
878 frame->width = pix->width; 937 frame->width = pix->width;
879 frame->height = pix->height; 938 frame->height = pix->height;
@@ -881,7 +940,6 @@ static int fimc_m2m_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
881 frame->o_height = pix->height; 940 frame->o_height = pix->height;
882 frame->offs_h = 0; 941 frame->offs_h = 0;
883 frame->offs_v = 0; 942 frame->offs_v = 0;
884 frame->size = (pix->width * pix->height * frame->fmt->depth) >> 3;
885 943
886 spin_lock_irqsave(&ctx->slock, flags); 944 spin_lock_irqsave(&ctx->slock, flags);
887 ctx->state |= FIMC_PARAMS; 945 ctx->state |= FIMC_PARAMS;
@@ -929,8 +987,12 @@ static int fimc_m2m_streamon(struct file *file, void *priv,
929 struct fimc_ctx *ctx = priv; 987 struct fimc_ctx *ctx = priv;
930 988
931 /* The source and target color format need to be set */ 989 /* The source and target color format need to be set */
932 if (~ctx->state & (FIMC_DST_FMT | FIMC_SRC_FMT)) 990 if (V4L2_TYPE_IS_OUTPUT(type)) {
991 if (~ctx->state & FIMC_SRC_FMT)
992 return -EINVAL;
993 } else if (~ctx->state & FIMC_DST_FMT) {
933 return -EINVAL; 994 return -EINVAL;
995 }
934 996
935 return v4l2_m2m_streamon(file, ctx->m2m_ctx, type); 997 return v4l2_m2m_streamon(file, ctx->m2m_ctx, type);
936} 998}
@@ -1134,7 +1196,8 @@ int fimc_try_crop(struct fimc_ctx *ctx, struct v4l2_crop *cr)
1134{ 1196{
1135 struct fimc_dev *fimc = ctx->fimc_dev; 1197 struct fimc_dev *fimc = ctx->fimc_dev;
1136 struct fimc_frame *f; 1198 struct fimc_frame *f;
1137 u32 min_size, halign; 1199 u32 min_size, halign, depth = 0;
1200 int i;
1138 1201
1139 if (cr->c.top < 0 || cr->c.left < 0) { 1202 if (cr->c.top < 0 || cr->c.left < 0) {
1140 v4l2_err(&fimc->m2m.v4l2_dev, 1203 v4l2_err(&fimc->m2m.v4l2_dev,
@@ -1142,9 +1205,9 @@ int fimc_try_crop(struct fimc_ctx *ctx, struct v4l2_crop *cr)
1142 return -EINVAL; 1205 return -EINVAL;
1143 } 1206 }
1144 1207
1145 if (cr->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) 1208 if (cr->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
1146 f = (ctx->state & FIMC_CTX_CAP) ? &ctx->s_frame : &ctx->d_frame; 1209 f = (ctx->state & FIMC_CTX_CAP) ? &ctx->s_frame : &ctx->d_frame;
1147 else if (cr->type == V4L2_BUF_TYPE_VIDEO_OUTPUT && 1210 else if (cr->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE &&
1148 ctx->state & FIMC_CTX_M2M) 1211 ctx->state & FIMC_CTX_M2M)
1149 f = &ctx->s_frame; 1212 f = &ctx->s_frame;
1150 else 1213 else
@@ -1164,10 +1227,13 @@ int fimc_try_crop(struct fimc_ctx *ctx, struct v4l2_crop *cr)
1164 halign = 4; 1227 halign = 4;
1165 } 1228 }
1166 1229
1230 for (i = 0; i < f->fmt->colplanes; i++)
1231 depth += f->fmt->depth[i];
1232
1167 v4l_bound_align_image(&cr->c.width, min_size, f->o_width, 1233 v4l_bound_align_image(&cr->c.width, min_size, f->o_width,
1168 ffs(min_size) - 1, 1234 ffs(min_size) - 1,
1169 &cr->c.height, min_size, f->o_height, 1235 &cr->c.height, min_size, f->o_height,
1170 halign, 64/(ALIGN(f->fmt->depth, 8))); 1236 halign, 64/(ALIGN(depth, 8)));
1171 1237
1172 /* adjust left/top if cropping rectangle is out of bounds */ 1238 /* adjust left/top if cropping rectangle is out of bounds */
1173 if (cr->c.left + cr->c.width > f->o_width) 1239 if (cr->c.left + cr->c.width > f->o_width)
@@ -1199,7 +1265,7 @@ static int fimc_m2m_s_crop(struct file *file, void *fh, struct v4l2_crop *cr)
1199 if (ret) 1265 if (ret)
1200 return ret; 1266 return ret;
1201 1267
1202 f = (cr->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) ? 1268 f = (cr->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) ?
1203 &ctx->s_frame : &ctx->d_frame; 1269 &ctx->s_frame : &ctx->d_frame;
1204 1270
1205 if (mutex_lock_interruptible(&fimc->lock)) 1271 if (mutex_lock_interruptible(&fimc->lock))
@@ -1208,7 +1274,7 @@ static int fimc_m2m_s_crop(struct file *file, void *fh, struct v4l2_crop *cr)
1208 spin_lock_irqsave(&ctx->slock, flags); 1274 spin_lock_irqsave(&ctx->slock, flags);
1209 if (~ctx->state & (FIMC_SRC_FMT | FIMC_DST_FMT)) { 1275 if (~ctx->state & (FIMC_SRC_FMT | FIMC_DST_FMT)) {
1210 /* Check to see if scaling ratio is within supported range */ 1276 /* Check to see if scaling ratio is within supported range */
1211 if (cr->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) 1277 if (cr->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
1212 ret = fimc_check_scaler_ratio(&cr->c, &ctx->d_frame); 1278 ret = fimc_check_scaler_ratio(&cr->c, &ctx->d_frame);
1213 else 1279 else
1214 ret = fimc_check_scaler_ratio(&cr->c, &ctx->s_frame); 1280 ret = fimc_check_scaler_ratio(&cr->c, &ctx->s_frame);
@@ -1234,17 +1300,17 @@ scr_unlock:
1234static const struct v4l2_ioctl_ops fimc_m2m_ioctl_ops = { 1300static const struct v4l2_ioctl_ops fimc_m2m_ioctl_ops = {
1235 .vidioc_querycap = fimc_m2m_querycap, 1301 .vidioc_querycap = fimc_m2m_querycap,
1236 1302
1237 .vidioc_enum_fmt_vid_cap = fimc_vidioc_enum_fmt, 1303 .vidioc_enum_fmt_vid_cap_mplane = fimc_vidioc_enum_fmt_mplane,
1238 .vidioc_enum_fmt_vid_out = fimc_vidioc_enum_fmt, 1304 .vidioc_enum_fmt_vid_out_mplane = fimc_vidioc_enum_fmt_mplane,
1239 1305
1240 .vidioc_g_fmt_vid_cap = fimc_vidioc_g_fmt, 1306 .vidioc_g_fmt_vid_cap_mplane = fimc_vidioc_g_fmt_mplane,
1241 .vidioc_g_fmt_vid_out = fimc_vidioc_g_fmt, 1307 .vidioc_g_fmt_vid_out_mplane = fimc_vidioc_g_fmt_mplane,
1242 1308
1243 .vidioc_try_fmt_vid_cap = fimc_vidioc_try_fmt, 1309 .vidioc_try_fmt_vid_cap_mplane = fimc_vidioc_try_fmt_mplane,
1244 .vidioc_try_fmt_vid_out = fimc_vidioc_try_fmt, 1310 .vidioc_try_fmt_vid_out_mplane = fimc_vidioc_try_fmt_mplane,
1245 1311
1246 .vidioc_s_fmt_vid_cap = fimc_m2m_s_fmt, 1312 .vidioc_s_fmt_vid_cap_mplane = fimc_m2m_s_fmt_mplane,
1247 .vidioc_s_fmt_vid_out = fimc_m2m_s_fmt, 1313 .vidioc_s_fmt_vid_out_mplane = fimc_m2m_s_fmt_mplane,
1248 1314
1249 .vidioc_reqbufs = fimc_m2m_reqbufs, 1315 .vidioc_reqbufs = fimc_m2m_reqbufs,
1250 .vidioc_querybuf = fimc_m2m_querybuf, 1316 .vidioc_querybuf = fimc_m2m_querybuf,
@@ -1265,7 +1331,8 @@ static const struct v4l2_ioctl_ops fimc_m2m_ioctl_ops = {
1265 1331
1266}; 1332};
1267 1333
1268static int queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_vq) 1334static int queue_init(void *priv, struct vb2_queue *src_vq,
1335 struct vb2_queue *dst_vq)
1269{ 1336{
1270 struct fimc_ctx *ctx = priv; 1337 struct fimc_ctx *ctx = priv;
1271 int ret; 1338 int ret;
diff --git a/drivers/media/video/s5p-fimc/fimc-core.h b/drivers/media/video/s5p-fimc/fimc-core.h
index 590fbf230792..187af60bcf69 100644
--- a/drivers/media/video/s5p-fimc/fimc-core.h
+++ b/drivers/media/video/s5p-fimc/fimc-core.h
@@ -84,7 +84,6 @@ enum fimc_color_fmt {
84 S5P_FIMC_RGB888, 84 S5P_FIMC_RGB888,
85 S5P_FIMC_RGB30_LOCAL, 85 S5P_FIMC_RGB30_LOCAL,
86 S5P_FIMC_YCBCR420 = 0x20, 86 S5P_FIMC_YCBCR420 = 0x20,
87 S5P_FIMC_YCBCR422,
88 S5P_FIMC_YCBYCR422, 87 S5P_FIMC_YCBYCR422,
89 S5P_FIMC_YCRYCB422, 88 S5P_FIMC_YCRYCB422,
90 S5P_FIMC_CBYCRY422, 89 S5P_FIMC_CBYCRY422,
@@ -151,18 +150,18 @@ enum fimc_color_fmt {
151 * @name: format description 150 * @name: format description
152 * @fourcc: the fourcc code for this format, 0 if not applicable 151 * @fourcc: the fourcc code for this format, 0 if not applicable
153 * @color: the corresponding fimc_color_fmt 152 * @color: the corresponding fimc_color_fmt
154 * @depth: driver's private 'number of bits per pixel' 153 * @depth: per plane driver's private 'number of bits per pixel'
155 * @buff_cnt: number of physically non-contiguous data planes 154 * @memplanes: number of physically non-contiguous data planes
156 * @planes_cnt: number of physically contiguous data planes 155 * @colplanes: number of physically contiguous data planes
157 */ 156 */
158struct fimc_fmt { 157struct fimc_fmt {
159 enum v4l2_mbus_pixelcode mbus_code; 158 enum v4l2_mbus_pixelcode mbus_code;
160 char *name; 159 char *name;
161 u32 fourcc; 160 u32 fourcc;
162 u32 color; 161 u32 color;
163 u16 buff_cnt; 162 u16 memplanes;
164 u16 planes_cnt; 163 u16 colplanes;
165 u16 depth; 164 u8 depth[VIDEO_MAX_PLANES];
166 u16 flags; 165 u16 flags;
167#define FMT_FLAGS_CAM (1 << 0) 166#define FMT_FLAGS_CAM (1 << 0)
168#define FMT_FLAGS_M2M (1 << 1) 167#define FMT_FLAGS_M2M (1 << 1)
@@ -272,7 +271,7 @@ struct fimc_vid_buffer {
272 * @height: image pixel weight 271 * @height: image pixel weight
273 * @paddr: image frame buffer physical addresses 272 * @paddr: image frame buffer physical addresses
274 * @buf_cnt: number of buffers depending on a color format 273 * @buf_cnt: number of buffers depending on a color format
275 * @size: image size in bytes 274 * @payload: image size in bytes (w x h x bpp)
276 * @color: color format 275 * @color: color format
277 * @dma_offset: DMA offset in bytes 276 * @dma_offset: DMA offset in bytes
278 */ 277 */
@@ -285,7 +284,7 @@ struct fimc_frame {
285 u32 offs_v; 284 u32 offs_v;
286 u32 width; 285 u32 width;
287 u32 height; 286 u32 height;
288 u32 size; 287 unsigned long payload[VIDEO_MAX_PLANES];
289 struct fimc_addr paddr; 288 struct fimc_addr paddr;
290 struct fimc_dma_offset dma_offset; 289 struct fimc_dma_offset dma_offset;
291 struct fimc_fmt *fmt; 290 struct fimc_fmt *fmt;
@@ -479,7 +478,7 @@ struct fimc_ctx {
479 478
480static inline int tiled_fmt(struct fimc_fmt *fmt) 479static inline int tiled_fmt(struct fimc_fmt *fmt)
481{ 480{
482 return 0; 481 return fmt->fourcc == V4L2_PIX_FMT_NV12MT;
483} 482}
484 483
485static inline void fimc_hw_clear_irq(struct fimc_dev *dev) 484static inline void fimc_hw_clear_irq(struct fimc_dev *dev)
@@ -535,12 +534,12 @@ static inline struct fimc_frame *ctx_get_frame(struct fimc_ctx *ctx,
535{ 534{
536 struct fimc_frame *frame; 535 struct fimc_frame *frame;
537 536
538 if (V4L2_BUF_TYPE_VIDEO_OUTPUT == type) { 537 if (V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE == type) {
539 if (ctx->state & FIMC_CTX_M2M) 538 if (ctx->state & FIMC_CTX_M2M)
540 frame = &ctx->s_frame; 539 frame = &ctx->s_frame;
541 else 540 else
542 return ERR_PTR(-EINVAL); 541 return ERR_PTR(-EINVAL);
543 } else if (V4L2_BUF_TYPE_VIDEO_CAPTURE == type) { 542 } else if (V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE == type) {
544 frame = &ctx->d_frame; 543 frame = &ctx->d_frame;
545 } else { 544 } else {
546 v4l2_err(&ctx->fimc_dev->m2m.v4l2_dev, 545 v4l2_err(&ctx->fimc_dev->m2m.v4l2_dev,
@@ -582,7 +581,7 @@ void fimc_hw_set_input_path(struct fimc_ctx *ctx);
582void fimc_hw_set_output_path(struct fimc_ctx *ctx); 581void fimc_hw_set_output_path(struct fimc_ctx *ctx);
583void fimc_hw_set_input_addr(struct fimc_dev *fimc, struct fimc_addr *paddr); 582void fimc_hw_set_input_addr(struct fimc_dev *fimc, struct fimc_addr *paddr);
584void fimc_hw_set_output_addr(struct fimc_dev *fimc, struct fimc_addr *paddr, 583void fimc_hw_set_output_addr(struct fimc_dev *fimc, struct fimc_addr *paddr,
585 int index); 584 int index);
586int fimc_hw_set_camera_source(struct fimc_dev *fimc, 585int fimc_hw_set_camera_source(struct fimc_dev *fimc,
587 struct s3c_fimc_isp_info *cam); 586 struct s3c_fimc_isp_info *cam);
588int fimc_hw_set_camera_offset(struct fimc_dev *fimc, struct fimc_frame *f); 587int fimc_hw_set_camera_offset(struct fimc_dev *fimc, struct fimc_frame *f);
@@ -593,12 +592,12 @@ int fimc_hw_set_camera_type(struct fimc_dev *fimc,
593 592
594/* -----------------------------------------------------*/ 593/* -----------------------------------------------------*/
595/* fimc-core.c */ 594/* fimc-core.c */
596int fimc_vidioc_enum_fmt(struct file *file, void *priv, 595int fimc_vidioc_enum_fmt_mplane(struct file *file, void *priv,
597 struct v4l2_fmtdesc *f); 596 struct v4l2_fmtdesc *f);
598int fimc_vidioc_g_fmt(struct file *file, void *priv, 597int fimc_vidioc_g_fmt_mplane(struct file *file, void *priv,
599 struct v4l2_format *f); 598 struct v4l2_format *f);
600int fimc_vidioc_try_fmt(struct file *file, void *priv, 599int fimc_vidioc_try_fmt_mplane(struct file *file, void *priv,
601 struct v4l2_format *f); 600 struct v4l2_format *f);
602int fimc_vidioc_queryctrl(struct file *file, void *priv, 601int fimc_vidioc_queryctrl(struct file *file, void *priv,
603 struct v4l2_queryctrl *qc); 602 struct v4l2_queryctrl *qc);
604int fimc_vidioc_g_ctrl(struct file *file, void *priv, 603int fimc_vidioc_g_ctrl(struct file *file, void *priv,
diff --git a/drivers/media/video/s5p-fimc/fimc-reg.c b/drivers/media/video/s5p-fimc/fimc-reg.c
index 511631a2e5c3..5ed8f06ca015 100644
--- a/drivers/media/video/s5p-fimc/fimc-reg.c
+++ b/drivers/media/video/s5p-fimc/fimc-reg.c
@@ -143,7 +143,7 @@ void fimc_hw_set_target_format(struct fimc_ctx *ctx)
143 case S5P_FIMC_YCRYCB422: 143 case S5P_FIMC_YCRYCB422:
144 case S5P_FIMC_CBYCRY422: 144 case S5P_FIMC_CBYCRY422:
145 case S5P_FIMC_CRYCBY422: 145 case S5P_FIMC_CRYCBY422:
146 if (frame->fmt->planes_cnt == 1) 146 if (frame->fmt->colplanes == 1)
147 cfg |= S5P_CITRGFMT_YCBCR422_1P; 147 cfg |= S5P_CITRGFMT_YCBCR422_1P;
148 else 148 else
149 cfg |= S5P_CITRGFMT_YCBCR422; 149 cfg |= S5P_CITRGFMT_YCBCR422;
@@ -219,11 +219,11 @@ void fimc_hw_set_out_dma(struct fimc_ctx *ctx)
219 cfg &= ~(S5P_CIOCTRL_ORDER2P_MASK | S5P_CIOCTRL_ORDER422_MASK | 219 cfg &= ~(S5P_CIOCTRL_ORDER2P_MASK | S5P_CIOCTRL_ORDER422_MASK |
220 S5P_CIOCTRL_YCBCR_PLANE_MASK); 220 S5P_CIOCTRL_YCBCR_PLANE_MASK);
221 221
222 if (frame->fmt->planes_cnt == 1) 222 if (frame->fmt->colplanes == 1)
223 cfg |= ctx->out_order_1p; 223 cfg |= ctx->out_order_1p;
224 else if (frame->fmt->planes_cnt == 2) 224 else if (frame->fmt->colplanes == 2)
225 cfg |= ctx->out_order_2p | S5P_CIOCTRL_YCBCR_2PLANE; 225 cfg |= ctx->out_order_2p | S5P_CIOCTRL_YCBCR_2PLANE;
226 else if (frame->fmt->planes_cnt == 3) 226 else if (frame->fmt->colplanes == 3)
227 cfg |= S5P_CIOCTRL_YCBCR_3PLANE; 227 cfg |= S5P_CIOCTRL_YCBCR_3PLANE;
228 228
229 writel(cfg, dev->regs + S5P_CIOCTRL); 229 writel(cfg, dev->regs + S5P_CIOCTRL);
@@ -428,7 +428,7 @@ void fimc_hw_set_in_dma(struct fimc_ctx *ctx)
428 case S5P_FIMC_YCBCR420: 428 case S5P_FIMC_YCBCR420:
429 cfg |= S5P_MSCTRL_INFORMAT_YCBCR420; 429 cfg |= S5P_MSCTRL_INFORMAT_YCBCR420;
430 430
431 if (frame->fmt->planes_cnt == 2) 431 if (frame->fmt->colplanes == 2)
432 cfg |= ctx->in_order_2p | S5P_MSCTRL_C_INT_IN_2PLANE; 432 cfg |= ctx->in_order_2p | S5P_MSCTRL_C_INT_IN_2PLANE;
433 else 433 else
434 cfg |= S5P_MSCTRL_C_INT_IN_3PLANE; 434 cfg |= S5P_MSCTRL_C_INT_IN_3PLANE;
@@ -438,13 +438,13 @@ void fimc_hw_set_in_dma(struct fimc_ctx *ctx)
438 case S5P_FIMC_YCRYCB422: 438 case S5P_FIMC_YCRYCB422:
439 case S5P_FIMC_CBYCRY422: 439 case S5P_FIMC_CBYCRY422:
440 case S5P_FIMC_CRYCBY422: 440 case S5P_FIMC_CRYCBY422:
441 if (frame->fmt->planes_cnt == 1) { 441 if (frame->fmt->colplanes == 1) {
442 cfg |= ctx->in_order_1p 442 cfg |= ctx->in_order_1p
443 | S5P_MSCTRL_INFORMAT_YCBCR422_1P; 443 | S5P_MSCTRL_INFORMAT_YCBCR422_1P;
444 } else { 444 } else {
445 cfg |= S5P_MSCTRL_INFORMAT_YCBCR422; 445 cfg |= S5P_MSCTRL_INFORMAT_YCBCR422;
446 446
447 if (frame->fmt->planes_cnt == 2) 447 if (frame->fmt->colplanes == 2)
448 cfg |= ctx->in_order_2p 448 cfg |= ctx->in_order_2p
449 | S5P_MSCTRL_C_INT_IN_2PLANE; 449 | S5P_MSCTRL_C_INT_IN_2PLANE;
450 else 450 else