aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSylwester Nawrocki <s.nawrocki@samsung.com>2012-09-24 10:08:45 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2012-10-05 20:28:05 -0400
commit14783d253625618744c200945c29769b3cbcc896 (patch)
treec4cf17d544f39bd3c9fe358a65979b76e1ca7f57
parent36fa80927638babe523dce14f3408f9fdefa86d3 (diff)
[media] s5p-fimc: Add support for V4L2_PIX_FMT_S5C_UYVY_JPG fourcc
The V4L2_PIX_FMT_S5C_YUYV_JPG image formats consists of 2 planes, the first containing interleaved JPEG/YUYV data and the second containing meta data describing the interleaving method. The image data is transferred with MIPI-CSI "User Defined Byte-Based Data 1" type and is captured to memory by FIMC DMA engine. The meta data is transferred using MIPI-CSI2 "Embedded 8-bit non Image Data" and it is captured in the MIPI-CSI slave device and copied to the bridge provided buffer. To make sure the size of allocated buffers is correct for the subdevs configuration when VIDIOC_STREAMON ioctl is invoked, an additional check is added at the video pipeline validation function. Flag FMT_FLAGS_COMPRESSED indicates the buffer size must be retrieved from a sensor subdev. Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com> Signed-off-by: Andrzej Hajda <a.hajda@samsung.com> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r--drivers/media/platform/s5p-fimc/fimc-capture.c135
-rw-r--r--drivers/media/platform/s5p-fimc/fimc-core.c19
-rw-r--r--drivers/media/platform/s5p-fimc/fimc-core.h28
-rw-r--r--drivers/media/platform/s5p-fimc/fimc-reg.c23
-rw-r--r--drivers/media/platform/s5p-fimc/fimc-reg.h3
-rw-r--r--drivers/media/platform/s5p-fimc/mipi-csis.c8
6 files changed, 183 insertions, 33 deletions
diff --git a/drivers/media/platform/s5p-fimc/fimc-capture.c b/drivers/media/platform/s5p-fimc/fimc-capture.c
index dded98815220..367efd164d0f 100644
--- a/drivers/media/platform/s5p-fimc/fimc-capture.c
+++ b/drivers/media/platform/s5p-fimc/fimc-capture.c
@@ -177,7 +177,9 @@ static int fimc_capture_config_update(struct fimc_ctx *ctx)
177 177
178void fimc_capture_irq_handler(struct fimc_dev *fimc, int deq_buf) 178void fimc_capture_irq_handler(struct fimc_dev *fimc, int deq_buf)
179{ 179{
180 struct v4l2_subdev *csis = fimc->pipeline.subdevs[IDX_CSIS];
180 struct fimc_vid_cap *cap = &fimc->vid_cap; 181 struct fimc_vid_cap *cap = &fimc->vid_cap;
182 struct fimc_frame *f = &cap->ctx->d_frame;
181 struct fimc_vid_buffer *v_buf; 183 struct fimc_vid_buffer *v_buf;
182 struct timeval *tv; 184 struct timeval *tv;
183 struct timespec ts; 185 struct timespec ts;
@@ -216,6 +218,25 @@ void fimc_capture_irq_handler(struct fimc_dev *fimc, int deq_buf)
216 if (++cap->buf_index >= FIMC_MAX_OUT_BUFS) 218 if (++cap->buf_index >= FIMC_MAX_OUT_BUFS)
217 cap->buf_index = 0; 219 cap->buf_index = 0;
218 } 220 }
221 /*
222 * Set up a buffer at MIPI-CSIS if current image format
223 * requires the frame embedded data capture.
224 */
225 if (f->fmt->mdataplanes && !list_empty(&cap->active_buf_q)) {
226 unsigned int plane = ffs(f->fmt->mdataplanes) - 1;
227 unsigned int size = f->payload[plane];
228 s32 index = fimc_hw_get_frame_index(fimc);
229 void *vaddr;
230
231 list_for_each_entry(v_buf, &cap->active_buf_q, list) {
232 if (v_buf->index != index)
233 continue;
234 vaddr = vb2_plane_vaddr(&v_buf->vb, plane);
235 v4l2_subdev_call(csis, video, s_rx_buffer,
236 vaddr, &size);
237 break;
238 }
239 }
219 240
220 if (cap->active_buf_cnt == 0) { 241 if (cap->active_buf_cnt == 0) {
221 if (deq_buf) 242 if (deq_buf)
@@ -351,6 +372,8 @@ static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *pfmt,
351 unsigned int size = (wh * fmt->depth[i]) / 8; 372 unsigned int size = (wh * fmt->depth[i]) / 8;
352 if (pixm) 373 if (pixm)
353 sizes[i] = max(size, pixm->plane_fmt[i].sizeimage); 374 sizes[i] = max(size, pixm->plane_fmt[i].sizeimage);
375 else if (fimc_fmt_is_user_defined(fmt->color))
376 sizes[i] = frame->payload[i];
354 else 377 else
355 sizes[i] = max_t(u32, size, frame->payload[i]); 378 sizes[i] = max_t(u32, size, frame->payload[i]);
356 379
@@ -611,10 +634,10 @@ static struct fimc_fmt *fimc_capture_try_format(struct fimc_ctx *ctx,
611 u32 mask = FMT_FLAGS_CAM; 634 u32 mask = FMT_FLAGS_CAM;
612 struct fimc_fmt *ffmt; 635 struct fimc_fmt *ffmt;
613 636
614 /* Color conversion from/to JPEG is not supported */ 637 /* Conversion from/to JPEG or User Defined format is not supported */
615 if (code && ctx->s_frame.fmt && pad == FIMC_SD_PAD_SOURCE && 638 if (code && ctx->s_frame.fmt && pad == FIMC_SD_PAD_SOURCE &&
616 fimc_fmt_is_jpeg(ctx->s_frame.fmt->color)) 639 fimc_fmt_is_user_defined(ctx->s_frame.fmt->color))
617 *code = V4L2_MBUS_FMT_JPEG_1X8; 640 *code = ctx->s_frame.fmt->mbus_code;
618 641
619 if (fourcc && *fourcc != V4L2_PIX_FMT_JPEG && pad != FIMC_SD_PAD_SINK) 642 if (fourcc && *fourcc != V4L2_PIX_FMT_JPEG && pad != FIMC_SD_PAD_SINK)
620 mask |= FMT_FLAGS_M2M; 643 mask |= FMT_FLAGS_M2M;
@@ -628,18 +651,19 @@ static struct fimc_fmt *fimc_capture_try_format(struct fimc_ctx *ctx,
628 *fourcc = ffmt->fourcc; 651 *fourcc = ffmt->fourcc;
629 652
630 if (pad == FIMC_SD_PAD_SINK) { 653 if (pad == FIMC_SD_PAD_SINK) {
631 max_w = fimc_fmt_is_jpeg(ffmt->color) ? 654 max_w = fimc_fmt_is_user_defined(ffmt->color) ?
632 pl->scaler_dis_w : pl->scaler_en_w; 655 pl->scaler_dis_w : pl->scaler_en_w;
633 /* Apply the camera input interface pixel constraints */ 656 /* Apply the camera input interface pixel constraints */
634 v4l_bound_align_image(width, max_t(u32, *width, 32), max_w, 4, 657 v4l_bound_align_image(width, max_t(u32, *width, 32), max_w, 4,
635 height, max_t(u32, *height, 32), 658 height, max_t(u32, *height, 32),
636 FIMC_CAMIF_MAX_HEIGHT, 659 FIMC_CAMIF_MAX_HEIGHT,
637 fimc_fmt_is_jpeg(ffmt->color) ? 3 : 1, 660 fimc_fmt_is_user_defined(ffmt->color) ?
661 3 : 1,
638 0); 662 0);
639 return ffmt; 663 return ffmt;
640 } 664 }
641 /* Can't scale or crop in transparent (JPEG) transfer mode */ 665 /* Can't scale or crop in transparent (JPEG) transfer mode */
642 if (fimc_fmt_is_jpeg(ffmt->color)) { 666 if (fimc_fmt_is_user_defined(ffmt->color)) {
643 *width = ctx->s_frame.f_width; 667 *width = ctx->s_frame.f_width;
644 *height = ctx->s_frame.f_height; 668 *height = ctx->s_frame.f_height;
645 return ffmt; 669 return ffmt;
@@ -684,7 +708,7 @@ static void fimc_capture_try_selection(struct fimc_ctx *ctx,
684 u32 max_sc_h, max_sc_v; 708 u32 max_sc_h, max_sc_v;
685 709
686 /* In JPEG transparent transfer mode cropping is not supported */ 710 /* In JPEG transparent transfer mode cropping is not supported */
687 if (fimc_fmt_is_jpeg(ctx->d_frame.fmt->color)) { 711 if (fimc_fmt_is_user_defined(ctx->d_frame.fmt->color)) {
688 r->width = sink->f_width; 712 r->width = sink->f_width;
689 r->height = sink->f_height; 713 r->height = sink->f_height;
690 r->left = r->top = 0; 714 r->left = r->top = 0;
@@ -847,6 +871,48 @@ static int fimc_pipeline_try_format(struct fimc_ctx *ctx,
847 return 0; 871 return 0;
848} 872}
849 873
874/**
875 * fimc_get_sensor_frame_desc - query the sensor for media bus frame parameters
876 * @sensor: pointer to the sensor subdev
877 * @plane_fmt: provides plane sizes corresponding to the frame layout entries
878 * @try: true to set the frame parameters, false to query only
879 *
880 * This function is used by this driver only for compressed/blob data formats.
881 */
882static int fimc_get_sensor_frame_desc(struct v4l2_subdev *sensor,
883 struct v4l2_plane_pix_format *plane_fmt,
884 unsigned int num_planes, bool try)
885{
886 struct v4l2_mbus_frame_desc fd;
887 int i, ret;
888
889 for (i = 0; i < num_planes; i++)
890 fd.entry[i].length = plane_fmt[i].sizeimage;
891
892 if (try)
893 ret = v4l2_subdev_call(sensor, pad, set_frame_desc, 0, &fd);
894 else
895 ret = v4l2_subdev_call(sensor, pad, get_frame_desc, 0, &fd);
896
897 if (ret < 0)
898 return ret;
899
900 if (num_planes != fd.num_entries)
901 return -EINVAL;
902
903 for (i = 0; i < num_planes; i++)
904 plane_fmt[i].sizeimage = fd.entry[i].length;
905
906 if (fd.entry[0].length > FIMC_MAX_JPEG_BUF_SIZE) {
907 v4l2_err(sensor->v4l2_dev, "Unsupported buffer size: %u\n",
908 fd.entry[0].length);
909
910 return -EINVAL;
911 }
912
913 return 0;
914}
915
850static int fimc_cap_g_fmt_mplane(struct file *file, void *fh, 916static int fimc_cap_g_fmt_mplane(struct file *file, void *fh,
851 struct v4l2_format *f) 917 struct v4l2_format *f)
852{ 918{
@@ -865,7 +931,7 @@ static int fimc_cap_try_fmt_mplane(struct file *file, void *fh,
865 struct v4l2_mbus_framefmt mf; 931 struct v4l2_mbus_framefmt mf;
866 struct fimc_fmt *ffmt = NULL; 932 struct fimc_fmt *ffmt = NULL;
867 933
868 if (pix->pixelformat == V4L2_PIX_FMT_JPEG) { 934 if (fimc_jpeg_fourcc(pix->pixelformat)) {
869 fimc_capture_try_format(ctx, &pix->width, &pix->height, 935 fimc_capture_try_format(ctx, &pix->width, &pix->height,
870 NULL, &pix->pixelformat, 936 NULL, &pix->pixelformat,
871 FIMC_SD_PAD_SINK); 937 FIMC_SD_PAD_SINK);
@@ -879,25 +945,32 @@ static int fimc_cap_try_fmt_mplane(struct file *file, void *fh,
879 return -EINVAL; 945 return -EINVAL;
880 946
881 if (!fimc->vid_cap.user_subdev_api) { 947 if (!fimc->vid_cap.user_subdev_api) {
882 mf.width = pix->width; 948 mf.width = pix->width;
883 mf.height = pix->height; 949 mf.height = pix->height;
884 mf.code = ffmt->mbus_code; 950 mf.code = ffmt->mbus_code;
885 fimc_md_graph_lock(fimc); 951 fimc_md_graph_lock(fimc);
886 fimc_pipeline_try_format(ctx, &mf, &ffmt, false); 952 fimc_pipeline_try_format(ctx, &mf, &ffmt, false);
887 fimc_md_graph_unlock(fimc); 953 fimc_md_graph_unlock(fimc);
888 954 pix->width = mf.width;
889 pix->width = mf.width; 955 pix->height = mf.height;
890 pix->height = mf.height;
891 if (ffmt) 956 if (ffmt)
892 pix->pixelformat = ffmt->fourcc; 957 pix->pixelformat = ffmt->fourcc;
893 } 958 }
894 959
895 fimc_adjust_mplane_format(ffmt, pix->width, pix->height, pix); 960 fimc_adjust_mplane_format(ffmt, pix->width, pix->height, pix);
961
962 if (ffmt->flags & FMT_FLAGS_COMPRESSED)
963 fimc_get_sensor_frame_desc(fimc->pipeline.subdevs[IDX_SENSOR],
964 pix->plane_fmt, ffmt->memplanes, true);
965
896 return 0; 966 return 0;
897} 967}
898 968
899static void fimc_capture_mark_jpeg_xfer(struct fimc_ctx *ctx, bool jpeg) 969static void fimc_capture_mark_jpeg_xfer(struct fimc_ctx *ctx,
970 enum fimc_color_fmt color)
900{ 971{
972 bool jpeg = fimc_fmt_is_user_defined(color);
973
901 ctx->scaler.enabled = !jpeg; 974 ctx->scaler.enabled = !jpeg;
902 fimc_ctrls_activate(ctx, !jpeg); 975 fimc_ctrls_activate(ctx, !jpeg);
903 976
@@ -920,7 +993,7 @@ static int fimc_capture_set_format(struct fimc_dev *fimc, struct v4l2_format *f)
920 return -EBUSY; 993 return -EBUSY;
921 994
922 /* Pre-configure format at camera interface input, for JPEG only */ 995 /* Pre-configure format at camera interface input, for JPEG only */
923 if (pix->pixelformat == V4L2_PIX_FMT_JPEG) { 996 if (fimc_jpeg_fourcc(pix->pixelformat)) {
924 fimc_capture_try_format(ctx, &pix->width, &pix->height, 997 fimc_capture_try_format(ctx, &pix->width, &pix->height,
925 NULL, &pix->pixelformat, 998 NULL, &pix->pixelformat,
926 FIMC_SD_PAD_SINK); 999 FIMC_SD_PAD_SINK);
@@ -953,7 +1026,16 @@ static int fimc_capture_set_format(struct fimc_dev *fimc, struct v4l2_format *f)
953 } 1026 }
954 1027
955 fimc_adjust_mplane_format(ff->fmt, pix->width, pix->height, pix); 1028 fimc_adjust_mplane_format(ff->fmt, pix->width, pix->height, pix);
956 for (i = 0; i < ff->fmt->colplanes; i++) 1029
1030 if (ff->fmt->flags & FMT_FLAGS_COMPRESSED) {
1031 ret = fimc_get_sensor_frame_desc(fimc->pipeline.subdevs[IDX_SENSOR],
1032 pix->plane_fmt, ff->fmt->memplanes,
1033 true);
1034 if (ret < 0)
1035 return ret;
1036 }
1037
1038 for (i = 0; i < ff->fmt->memplanes; i++)
957 ff->payload[i] = pix->plane_fmt[i].sizeimage; 1039 ff->payload[i] = pix->plane_fmt[i].sizeimage;
958 1040
959 set_frame_bounds(ff, pix->width, pix->height); 1041 set_frame_bounds(ff, pix->width, pix->height);
@@ -961,7 +1043,7 @@ static int fimc_capture_set_format(struct fimc_dev *fimc, struct v4l2_format *f)
961 if (!(ctx->state & FIMC_COMPOSE)) 1043 if (!(ctx->state & FIMC_COMPOSE))
962 set_frame_crop(ff, 0, 0, pix->width, pix->height); 1044 set_frame_crop(ff, 0, 0, pix->width, pix->height);
963 1045
964 fimc_capture_mark_jpeg_xfer(ctx, fimc_fmt_is_jpeg(ff->fmt->color)); 1046 fimc_capture_mark_jpeg_xfer(ctx, ff->fmt->color);
965 1047
966 /* Reset cropping and set format at the camera interface input */ 1048 /* Reset cropping and set format at the camera interface input */
967 if (!fimc->vid_cap.user_subdev_api) { 1049 if (!fimc->vid_cap.user_subdev_api) {
@@ -1063,6 +1145,23 @@ static int fimc_pipeline_validate(struct fimc_dev *fimc)
1063 src_fmt.format.height != sink_fmt.format.height || 1145 src_fmt.format.height != sink_fmt.format.height ||
1064 src_fmt.format.code != sink_fmt.format.code) 1146 src_fmt.format.code != sink_fmt.format.code)
1065 return -EPIPE; 1147 return -EPIPE;
1148
1149 if (sd == fimc->pipeline.subdevs[IDX_SENSOR] &&
1150 fimc_user_defined_mbus_fmt(src_fmt.format.code)) {
1151 struct v4l2_plane_pix_format plane_fmt[FIMC_MAX_PLANES];
1152 struct fimc_frame *frame = &vid_cap->ctx->d_frame;
1153 unsigned int i;
1154
1155 ret = fimc_get_sensor_frame_desc(sd, plane_fmt,
1156 frame->fmt->memplanes,
1157 false);
1158 if (ret < 0)
1159 return -EPIPE;
1160
1161 for (i = 0; i < frame->fmt->memplanes; i++)
1162 if (frame->payload[i] < plane_fmt[i].sizeimage)
1163 return -EPIPE;
1164 }
1066 } 1165 }
1067 return 0; 1166 return 0;
1068} 1167}
@@ -1424,7 +1523,7 @@ static int fimc_subdev_set_fmt(struct v4l2_subdev *sd,
1424 /* Update RGB Alpha control state and value range */ 1523 /* Update RGB Alpha control state and value range */
1425 fimc_alpha_ctrl_update(ctx); 1524 fimc_alpha_ctrl_update(ctx);
1426 1525
1427 fimc_capture_mark_jpeg_xfer(ctx, fimc_fmt_is_jpeg(ffmt->color)); 1526 fimc_capture_mark_jpeg_xfer(ctx, ffmt->color);
1428 1527
1429 ff = fmt->pad == FIMC_SD_PAD_SINK ? 1528 ff = fmt->pad == FIMC_SD_PAD_SINK ?
1430 &ctx->s_frame : &ctx->d_frame; 1529 &ctx->s_frame : &ctx->d_frame;
diff --git a/drivers/media/platform/s5p-fimc/fimc-core.c b/drivers/media/platform/s5p-fimc/fimc-core.c
index 1a445404e73d..8d0d2b94a135 100644
--- a/drivers/media/platform/s5p-fimc/fimc-core.c
+++ b/drivers/media/platform/s5p-fimc/fimc-core.c
@@ -184,7 +184,17 @@ static struct fimc_fmt fimc_formats[] = {
184 .memplanes = 1, 184 .memplanes = 1,
185 .colplanes = 1, 185 .colplanes = 1,
186 .mbus_code = V4L2_MBUS_FMT_JPEG_1X8, 186 .mbus_code = V4L2_MBUS_FMT_JPEG_1X8,
187 .flags = FMT_FLAGS_CAM, 187 .flags = FMT_FLAGS_CAM | FMT_FLAGS_COMPRESSED,
188 }, {
189 .name = "S5C73MX interleaved UYVY/JPEG",
190 .fourcc = V4L2_PIX_FMT_S5C_UYVY_JPG,
191 .color = FIMC_FMT_YUYV_JPEG,
192 .depth = { 8 },
193 .memplanes = 2,
194 .colplanes = 1,
195 .mdataplanes = 0x2, /* plane 1 holds frame meta data */
196 .mbus_code = V4L2_MBUS_FMT_S5C_UYVY_JPEG_1X8,
197 .flags = FMT_FLAGS_CAM | FMT_FLAGS_COMPRESSED,
188 }, 198 },
189}; 199};
190 200
@@ -371,7 +381,7 @@ int fimc_prepare_addr(struct fimc_ctx *ctx, struct vb2_buffer *vb,
371 default: 381 default:
372 return -EINVAL; 382 return -EINVAL;
373 } 383 }
374 } else { 384 } else if (!frame->fmt->mdataplanes) {
375 if (frame->fmt->memplanes >= 2) 385 if (frame->fmt->memplanes >= 2)
376 paddr->cb = vb2_dma_contig_plane_dma_addr(vb, 1); 386 paddr->cb = vb2_dma_contig_plane_dma_addr(vb, 1);
377 387
@@ -698,6 +708,11 @@ int fimc_fill_format(struct fimc_frame *frame, struct v4l2_format *f)
698 if (frame->fmt->colplanes == 1) /* packed formats */ 708 if (frame->fmt->colplanes == 1) /* packed formats */
699 bpl = (bpl * frame->fmt->depth[0]) / 8; 709 bpl = (bpl * frame->fmt->depth[0]) / 8;
700 pixm->plane_fmt[i].bytesperline = bpl; 710 pixm->plane_fmt[i].bytesperline = bpl;
711
712 if (frame->fmt->flags & FMT_FLAGS_COMPRESSED) {
713 pixm->plane_fmt[i].sizeimage = frame->payload[i];
714 continue;
715 }
701 pixm->plane_fmt[i].sizeimage = (frame->o_width * 716 pixm->plane_fmt[i].sizeimage = (frame->o_width *
702 frame->o_height * frame->fmt->depth[i]) / 8; 717 frame->o_height * frame->fmt->depth[i]) / 8;
703 } 718 }
diff --git a/drivers/media/platform/s5p-fimc/fimc-core.h b/drivers/media/platform/s5p-fimc/fimc-core.h
index cd716ba6015f..c0040d792499 100644
--- a/drivers/media/platform/s5p-fimc/fimc-core.h
+++ b/drivers/media/platform/s5p-fimc/fimc-core.h
@@ -40,6 +40,8 @@
40#define SCALER_MAX_VRATIO 64 40#define SCALER_MAX_VRATIO 64
41#define DMA_MIN_SIZE 8 41#define DMA_MIN_SIZE 8
42#define FIMC_CAMIF_MAX_HEIGHT 0x2000 42#define FIMC_CAMIF_MAX_HEIGHT 0x2000
43#define FIMC_MAX_JPEG_BUF_SIZE (10 * SZ_1M)
44#define FIMC_MAX_PLANES 3
43 45
44/* indices to the clocks array */ 46/* indices to the clocks array */
45enum { 47enum {
@@ -83,7 +85,7 @@ enum fimc_datapath {
83}; 85};
84 86
85enum fimc_color_fmt { 87enum fimc_color_fmt {
86 FIMC_FMT_RGB444 = 0x10, 88 FIMC_FMT_RGB444 = 0x10,
87 FIMC_FMT_RGB555, 89 FIMC_FMT_RGB555,
88 FIMC_FMT_RGB565, 90 FIMC_FMT_RGB565,
89 FIMC_FMT_RGB666, 91 FIMC_FMT_RGB666,
@@ -95,14 +97,15 @@ enum fimc_color_fmt {
95 FIMC_FMT_CBYCRY422, 97 FIMC_FMT_CBYCRY422,
96 FIMC_FMT_CRYCBY422, 98 FIMC_FMT_CRYCBY422,
97 FIMC_FMT_YCBCR444_LOCAL, 99 FIMC_FMT_YCBCR444_LOCAL,
98 FIMC_FMT_JPEG = 0x40, 100 FIMC_FMT_RAW8 = 0x40,
99 FIMC_FMT_RAW8 = 0x80,
100 FIMC_FMT_RAW10, 101 FIMC_FMT_RAW10,
101 FIMC_FMT_RAW12, 102 FIMC_FMT_RAW12,
103 FIMC_FMT_JPEG = 0x80,
104 FIMC_FMT_YUYV_JPEG = 0x100,
102}; 105};
103 106
107#define fimc_fmt_is_user_defined(x) (!!((x) & 0x180))
104#define fimc_fmt_is_rgb(x) (!!((x) & 0x10)) 108#define fimc_fmt_is_rgb(x) (!!((x) & 0x10))
105#define fimc_fmt_is_jpeg(x) (!!((x) & 0x40))
106 109
107#define IS_M2M(__strt) ((__strt) == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE || \ 110#define IS_M2M(__strt) ((__strt) == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE || \
108 __strt == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) 111 __strt == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
@@ -139,6 +142,7 @@ enum fimc_color_fmt {
139 * @memplanes: number of physically non-contiguous data planes 142 * @memplanes: number of physically non-contiguous data planes
140 * @colplanes: number of physically contiguous data planes 143 * @colplanes: number of physically contiguous data planes
141 * @depth: per plane driver's private 'number of bits per pixel' 144 * @depth: per plane driver's private 'number of bits per pixel'
145 * @mdataplanes: bitmask indicating meta data plane(s), (1 << plane_no)
142 * @flags: flags indicating which operation mode format applies to 146 * @flags: flags indicating which operation mode format applies to
143 */ 147 */
144struct fimc_fmt { 148struct fimc_fmt {
@@ -149,12 +153,14 @@ struct fimc_fmt {
149 u16 memplanes; 153 u16 memplanes;
150 u16 colplanes; 154 u16 colplanes;
151 u8 depth[VIDEO_MAX_PLANES]; 155 u8 depth[VIDEO_MAX_PLANES];
156 u16 mdataplanes;
152 u16 flags; 157 u16 flags;
153#define FMT_FLAGS_CAM (1 << 0) 158#define FMT_FLAGS_CAM (1 << 0)
154#define FMT_FLAGS_M2M_IN (1 << 1) 159#define FMT_FLAGS_M2M_IN (1 << 1)
155#define FMT_FLAGS_M2M_OUT (1 << 2) 160#define FMT_FLAGS_M2M_OUT (1 << 2)
156#define FMT_FLAGS_M2M (1 << 1 | 1 << 2) 161#define FMT_FLAGS_M2M (1 << 1 | 1 << 2)
157#define FMT_HAS_ALPHA (1 << 3) 162#define FMT_HAS_ALPHA (1 << 3)
163#define FMT_FLAGS_COMPRESSED (1 << 4)
158}; 164};
159 165
160/** 166/**
@@ -272,7 +278,7 @@ struct fimc_frame {
272 u32 offs_v; 278 u32 offs_v;
273 u32 width; 279 u32 width;
274 u32 height; 280 u32 height;
275 unsigned long payload[VIDEO_MAX_PLANES]; 281 unsigned int payload[VIDEO_MAX_PLANES];
276 struct fimc_addr paddr; 282 struct fimc_addr paddr;
277 struct fimc_dma_offset dma_offset; 283 struct fimc_dma_offset dma_offset;
278 struct fimc_fmt *fmt; 284 struct fimc_fmt *fmt;
@@ -577,6 +583,18 @@ static inline int tiled_fmt(struct fimc_fmt *fmt)
577 return fmt->fourcc == V4L2_PIX_FMT_NV12MT; 583 return fmt->fourcc == V4L2_PIX_FMT_NV12MT;
578} 584}
579 585
586static inline bool fimc_jpeg_fourcc(u32 pixelformat)
587{
588 return (pixelformat == V4L2_PIX_FMT_JPEG ||
589 pixelformat == V4L2_PIX_FMT_S5C_UYVY_JPG);
590}
591
592static inline bool fimc_user_defined_mbus_fmt(u32 code)
593{
594 return (code == V4L2_MBUS_FMT_JPEG_1X8 ||
595 code == V4L2_MBUS_FMT_S5C_UYVY_JPEG_1X8);
596}
597
580/* Return the alpha component bit mask */ 598/* Return the alpha component bit mask */
581static inline int fimc_get_alpha_mask(struct fimc_fmt *fmt) 599static inline int fimc_get_alpha_mask(struct fimc_fmt *fmt)
582{ 600{
diff --git a/drivers/media/platform/s5p-fimc/fimc-reg.c b/drivers/media/platform/s5p-fimc/fimc-reg.c
index 783408fd7d56..2c9d0c06c9e8 100644
--- a/drivers/media/platform/s5p-fimc/fimc-reg.c
+++ b/drivers/media/platform/s5p-fimc/fimc-reg.c
@@ -625,7 +625,7 @@ int fimc_hw_set_camera_source(struct fimc_dev *fimc,
625 cfg |= FIMC_REG_CISRCFMT_ITU601_16BIT; 625 cfg |= FIMC_REG_CISRCFMT_ITU601_16BIT;
626 } /* else defaults to ITU-R BT.656 8-bit */ 626 } /* else defaults to ITU-R BT.656 8-bit */
627 } else if (cam->bus_type == FIMC_MIPI_CSI2) { 627 } else if (cam->bus_type == FIMC_MIPI_CSI2) {
628 if (fimc_fmt_is_jpeg(f->fmt->color)) 628 if (fimc_fmt_is_user_defined(f->fmt->color))
629 cfg |= FIMC_REG_CISRCFMT_ITU601_8BIT; 629 cfg |= FIMC_REG_CISRCFMT_ITU601_8BIT;
630 } 630 }
631 631
@@ -680,6 +680,7 @@ int fimc_hw_set_camera_type(struct fimc_dev *fimc,
680 tmp = FIMC_REG_CSIIMGFMT_YCBCR422_8BIT; 680 tmp = FIMC_REG_CSIIMGFMT_YCBCR422_8BIT;
681 break; 681 break;
682 case V4L2_MBUS_FMT_JPEG_1X8: 682 case V4L2_MBUS_FMT_JPEG_1X8:
683 case V4L2_MBUS_FMT_S5C_UYVY_JPEG_1X8:
683 tmp = FIMC_REG_CSIIMGFMT_USER(1); 684 tmp = FIMC_REG_CSIIMGFMT_USER(1);
684 cfg |= FIMC_REG_CIGCTRL_CAM_JPEG; 685 cfg |= FIMC_REG_CIGCTRL_CAM_JPEG;
685 break; 686 break;
@@ -744,13 +745,13 @@ void fimc_hw_dis_capture(struct fimc_dev *dev)
744} 745}
745 746
746/* Return an index to the buffer actually being written. */ 747/* Return an index to the buffer actually being written. */
747u32 fimc_hw_get_frame_index(struct fimc_dev *dev) 748s32 fimc_hw_get_frame_index(struct fimc_dev *dev)
748{ 749{
749 u32 reg; 750 s32 reg;
750 751
751 if (dev->variant->has_cistatus2) { 752 if (dev->variant->has_cistatus2) {
752 reg = readl(dev->regs + FIMC_REG_CISTATUS2) & 0x3F; 753 reg = readl(dev->regs + FIMC_REG_CISTATUS2) & 0x3f;
753 return reg > 0 ? --reg : reg; 754 return reg - 1;
754 } 755 }
755 756
756 reg = readl(dev->regs + FIMC_REG_CISTATUS); 757 reg = readl(dev->regs + FIMC_REG_CISTATUS);
@@ -759,6 +760,18 @@ u32 fimc_hw_get_frame_index(struct fimc_dev *dev)
759 FIMC_REG_CISTATUS_FRAMECNT_SHIFT; 760 FIMC_REG_CISTATUS_FRAMECNT_SHIFT;
760} 761}
761 762
763/* Return an index to the buffer being written previously. */
764s32 fimc_hw_get_prev_frame_index(struct fimc_dev *dev)
765{
766 s32 reg;
767
768 if (!dev->variant->has_cistatus2)
769 return -1;
770
771 reg = readl(dev->regs + FIMC_REG_CISTATUS2);
772 return ((reg >> 7) & 0x3f) - 1;
773}
774
762/* Locking: the caller holds fimc->slock */ 775/* Locking: the caller holds fimc->slock */
763void fimc_activate_capture(struct fimc_ctx *ctx) 776void fimc_activate_capture(struct fimc_ctx *ctx)
764{ 777{
diff --git a/drivers/media/platform/s5p-fimc/fimc-reg.h b/drivers/media/platform/s5p-fimc/fimc-reg.h
index 579ac8ac03de..b6abfc7b72ac 100644
--- a/drivers/media/platform/s5p-fimc/fimc-reg.h
+++ b/drivers/media/platform/s5p-fimc/fimc-reg.h
@@ -307,7 +307,8 @@ void fimc_hw_clear_irq(struct fimc_dev *dev);
307void fimc_hw_enable_scaler(struct fimc_dev *dev, bool on); 307void fimc_hw_enable_scaler(struct fimc_dev *dev, bool on);
308void fimc_hw_activate_input_dma(struct fimc_dev *dev, bool on); 308void fimc_hw_activate_input_dma(struct fimc_dev *dev, bool on);
309void fimc_hw_dis_capture(struct fimc_dev *dev); 309void fimc_hw_dis_capture(struct fimc_dev *dev);
310u32 fimc_hw_get_frame_index(struct fimc_dev *dev); 310s32 fimc_hw_get_frame_index(struct fimc_dev *dev);
311s32 fimc_hw_get_prev_frame_index(struct fimc_dev *dev);
311void fimc_activate_capture(struct fimc_ctx *ctx); 312void fimc_activate_capture(struct fimc_ctx *ctx);
312void fimc_deactivate_capture(struct fimc_dev *fimc); 313void fimc_deactivate_capture(struct fimc_dev *fimc);
313 314
diff --git a/drivers/media/platform/s5p-fimc/mipi-csis.c b/drivers/media/platform/s5p-fimc/mipi-csis.c
index acf4ce2c4bb9..9555ded65660 100644
--- a/drivers/media/platform/s5p-fimc/mipi-csis.c
+++ b/drivers/media/platform/s5p-fimc/mipi-csis.c
@@ -214,7 +214,11 @@ static const struct csis_pix_format s5pcsis_formats[] = {
214 .code = V4L2_MBUS_FMT_JPEG_1X8, 214 .code = V4L2_MBUS_FMT_JPEG_1X8,
215 .fmt_reg = S5PCSIS_CFG_FMT_USER(1), 215 .fmt_reg = S5PCSIS_CFG_FMT_USER(1),
216 .data_alignment = 32, 216 .data_alignment = 32,
217 }, 217 }, {
218 .code = V4L2_MBUS_FMT_S5C_UYVY_JPEG_1X8,
219 .fmt_reg = S5PCSIS_CFG_FMT_USER(1),
220 .data_alignment = 32,
221 }
218}; 222};
219 223
220#define s5pcsis_write(__csis, __r, __v) writel(__v, __csis->regs + __r) 224#define s5pcsis_write(__csis, __r, __v) writel(__v, __csis->regs + __r)
@@ -278,7 +282,7 @@ static void __s5pcsis_set_format(struct csis_state *state)
278 struct v4l2_mbus_framefmt *mf = &state->format; 282 struct v4l2_mbus_framefmt *mf = &state->format;
279 u32 val; 283 u32 val;
280 284
281 v4l2_dbg(1, debug, &state->sd, "fmt: %d, %d x %d\n", 285 v4l2_dbg(1, debug, &state->sd, "fmt: %#x, %d x %d\n",
282 mf->code, mf->width, mf->height); 286 mf->code, mf->width, mf->height);
283 287
284 /* Color format */ 288 /* Color format */