diff options
author | Sylwester Nawrocki <s.nawrocki@samsung.com> | 2012-09-24 10:08:45 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-10-05 20:28:05 -0400 |
commit | 14783d253625618744c200945c29769b3cbcc896 (patch) | |
tree | c4cf17d544f39bd3c9fe358a65979b76e1ca7f57 | |
parent | 36fa80927638babe523dce14f3408f9fdefa86d3 (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.c | 135 | ||||
-rw-r--r-- | drivers/media/platform/s5p-fimc/fimc-core.c | 19 | ||||
-rw-r--r-- | drivers/media/platform/s5p-fimc/fimc-core.h | 28 | ||||
-rw-r--r-- | drivers/media/platform/s5p-fimc/fimc-reg.c | 23 | ||||
-rw-r--r-- | drivers/media/platform/s5p-fimc/fimc-reg.h | 3 | ||||
-rw-r--r-- | drivers/media/platform/s5p-fimc/mipi-csis.c | 8 |
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 | ||
178 | void fimc_capture_irq_handler(struct fimc_dev *fimc, int deq_buf) | 178 | void 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 | */ | ||
882 | static 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 | |||
850 | static int fimc_cap_g_fmt_mplane(struct file *file, void *fh, | 916 | static 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 | ||
899 | static void fimc_capture_mark_jpeg_xfer(struct fimc_ctx *ctx, bool jpeg) | 969 | static 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 */ |
45 | enum { | 47 | enum { |
@@ -83,7 +85,7 @@ enum fimc_datapath { | |||
83 | }; | 85 | }; |
84 | 86 | ||
85 | enum fimc_color_fmt { | 87 | enum 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 | */ |
144 | struct fimc_fmt { | 148 | struct 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 | ||
586 | static 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 | |||
592 | static 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 */ |
581 | static inline int fimc_get_alpha_mask(struct fimc_fmt *fmt) | 599 | static 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. */ |
747 | u32 fimc_hw_get_frame_index(struct fimc_dev *dev) | 748 | s32 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. */ | ||
764 | s32 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 */ |
763 | void fimc_activate_capture(struct fimc_ctx *ctx) | 776 | void 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); | |||
307 | void fimc_hw_enable_scaler(struct fimc_dev *dev, bool on); | 307 | void fimc_hw_enable_scaler(struct fimc_dev *dev, bool on); |
308 | void fimc_hw_activate_input_dma(struct fimc_dev *dev, bool on); | 308 | void fimc_hw_activate_input_dma(struct fimc_dev *dev, bool on); |
309 | void fimc_hw_dis_capture(struct fimc_dev *dev); | 309 | void fimc_hw_dis_capture(struct fimc_dev *dev); |
310 | u32 fimc_hw_get_frame_index(struct fimc_dev *dev); | 310 | s32 fimc_hw_get_frame_index(struct fimc_dev *dev); |
311 | s32 fimc_hw_get_prev_frame_index(struct fimc_dev *dev); | ||
311 | void fimc_activate_capture(struct fimc_ctx *ctx); | 312 | void fimc_activate_capture(struct fimc_ctx *ctx); |
312 | void fimc_deactivate_capture(struct fimc_dev *fimc); | 313 | void 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 */ |