aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/platform
diff options
context:
space:
mode:
authorJacek Anaszewski <j.anaszewski@samsung.com>2013-11-22 04:13:34 -0500
committerMauro Carvalho Chehab <m.chehab@samsung.com>2013-12-18 08:49:03 -0500
commit337777a42d033b3be1a7f9af13eb8f5eb0cdd95a (patch)
tree778a56b919c47883d1ab006ddd34dbdc919b1a15 /drivers/media/platform
parentf84339628d9224200e9145320da494da2d92cd50 (diff)
[media] s5p-jpeg: Ensure correct capture format for Exynos4x12
Adjust capture format to the Exynos4x12 device limitations, according to the subsampling value parsed from the source JPEG image header. If the capture format was set to YUV with subsampling lower than the one of the source JPEG image the decoding process would not succeed. Signed-off-by: Jacek Anaszewski <j.anaszewski@samsung.com> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com> Acked-by: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com> Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
Diffstat (limited to 'drivers/media/platform')
-rw-r--r--drivers/media/platform/s5p-jpeg/jpeg-core.c116
1 files changed, 116 insertions, 0 deletions
diff --git a/drivers/media/platform/s5p-jpeg/jpeg-core.c b/drivers/media/platform/s5p-jpeg/jpeg-core.c
index 0ae3d2cdef03..ba8e4fcb8f33 100644
--- a/drivers/media/platform/s5p-jpeg/jpeg-core.c
+++ b/drivers/media/platform/s5p-jpeg/jpeg-core.c
@@ -358,6 +358,99 @@ static const unsigned char hactblg0[162] = {
358 0xf9, 0xfa 358 0xf9, 0xfa
359}; 359};
360 360
361/*
362 * Fourcc downgrade schema lookup tables for 422 and 420
363 * chroma subsampling - fourcc on each position maps on the
364 * fourcc from the table fourcc_to_dwngrd_schema_id which allows
365 * to get the most suitable fourcc counterpart for the given
366 * downgraded subsampling property.
367 */
368static const u32 subs422_fourcc_dwngrd_schema[] = {
369 V4L2_PIX_FMT_NV16,
370 V4L2_PIX_FMT_NV61,
371};
372
373static const u32 subs420_fourcc_dwngrd_schema[] = {
374 V4L2_PIX_FMT_NV12,
375 V4L2_PIX_FMT_NV21,
376 V4L2_PIX_FMT_NV12,
377 V4L2_PIX_FMT_NV21,
378 V4L2_PIX_FMT_NV12,
379 V4L2_PIX_FMT_NV21,
380 V4L2_PIX_FMT_GREY,
381 V4L2_PIX_FMT_GREY,
382 V4L2_PIX_FMT_GREY,
383 V4L2_PIX_FMT_GREY,
384};
385
386/*
387 * Lookup table for translation of a fourcc to the position
388 * of its downgraded counterpart in the *fourcc_dwngrd_schema
389 * tables.
390 */
391static const u32 fourcc_to_dwngrd_schema_id[] = {
392 V4L2_PIX_FMT_NV24,
393 V4L2_PIX_FMT_NV42,
394 V4L2_PIX_FMT_NV16,
395 V4L2_PIX_FMT_NV61,
396 V4L2_PIX_FMT_YUYV,
397 V4L2_PIX_FMT_YVYU,
398 V4L2_PIX_FMT_NV12,
399 V4L2_PIX_FMT_NV21,
400 V4L2_PIX_FMT_YUV420,
401 V4L2_PIX_FMT_GREY,
402};
403
404static int s5p_jpeg_get_dwngrd_sch_id_by_fourcc(u32 fourcc)
405{
406 int i;
407 for (i = 0; i < ARRAY_SIZE(fourcc_to_dwngrd_schema_id); ++i) {
408 if (fourcc_to_dwngrd_schema_id[i] == fourcc)
409 return i;
410 }
411
412 return -EINVAL;
413}
414
415static int s5p_jpeg_adjust_fourcc_to_subsampling(
416 enum v4l2_jpeg_chroma_subsampling subs,
417 u32 in_fourcc,
418 u32 *out_fourcc,
419 struct s5p_jpeg_ctx *ctx)
420{
421 int dwngrd_sch_id;
422
423 if (ctx->subsampling != V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY) {
424 dwngrd_sch_id =
425 s5p_jpeg_get_dwngrd_sch_id_by_fourcc(in_fourcc);
426 if (dwngrd_sch_id < 0)
427 return -EINVAL;
428 }
429
430 switch (ctx->subsampling) {
431 case V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY:
432 *out_fourcc = V4L2_PIX_FMT_GREY;
433 break;
434 case V4L2_JPEG_CHROMA_SUBSAMPLING_420:
435 if (dwngrd_sch_id >
436 ARRAY_SIZE(subs420_fourcc_dwngrd_schema) - 1)
437 return -EINVAL;
438 *out_fourcc = subs420_fourcc_dwngrd_schema[dwngrd_sch_id];
439 break;
440 case V4L2_JPEG_CHROMA_SUBSAMPLING_422:
441 if (dwngrd_sch_id >
442 ARRAY_SIZE(subs422_fourcc_dwngrd_schema) - 1)
443 return -EINVAL;
444 *out_fourcc = subs422_fourcc_dwngrd_schema[dwngrd_sch_id];
445 break;
446 default:
447 *out_fourcc = V4L2_PIX_FMT_GREY;
448 break;
449 }
450
451 return 0;
452}
453
361static inline struct s5p_jpeg_ctx *ctrl_to_ctx(struct v4l2_ctrl *c) 454static inline struct s5p_jpeg_ctx *ctrl_to_ctx(struct v4l2_ctrl *c)
362{ 455{
363 return container_of(c->handler, struct s5p_jpeg_ctx, ctrl_handler); 456 return container_of(c->handler, struct s5p_jpeg_ctx, ctrl_handler);
@@ -941,7 +1034,9 @@ static int s5p_jpeg_try_fmt_vid_cap(struct file *file, void *priv,
941 struct v4l2_format *f) 1034 struct v4l2_format *f)
942{ 1035{
943 struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv); 1036 struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv);
1037 struct v4l2_pix_format *pix = &f->fmt.pix;
944 struct s5p_jpeg_fmt *fmt; 1038 struct s5p_jpeg_fmt *fmt;
1039 int ret;
945 1040
946 fmt = s5p_jpeg_find_format(ctx, f->fmt.pix.pixelformat, 1041 fmt = s5p_jpeg_find_format(ctx, f->fmt.pix.pixelformat,
947 FMT_TYPE_CAPTURE); 1042 FMT_TYPE_CAPTURE);
@@ -952,6 +1047,27 @@ static int s5p_jpeg_try_fmt_vid_cap(struct file *file, void *priv,
952 return -EINVAL; 1047 return -EINVAL;
953 } 1048 }
954 1049
1050 /*
1051 * The exynos4x12 device requires resulting YUV image
1052 * subsampling not to be lower than the input jpeg subsampling.
1053 * If this requirement is not met then downgrade the requested
1054 * capture format to the one with subsampling equal to the input jpeg.
1055 */
1056 if ((ctx->jpeg->variant->version != SJPEG_S5P) &&
1057 (ctx->mode == S5P_JPEG_DECODE) &&
1058 (fmt->flags & SJPEG_FMT_NON_RGB) &&
1059 (fmt->subsampling < ctx->subsampling)) {
1060 ret = s5p_jpeg_adjust_fourcc_to_subsampling(ctx->subsampling,
1061 fmt->fourcc,
1062 &pix->pixelformat,
1063 ctx);
1064 if (ret < 0)
1065 pix->pixelformat = V4L2_PIX_FMT_GREY;
1066
1067 fmt = s5p_jpeg_find_format(ctx, pix->pixelformat,
1068 FMT_TYPE_CAPTURE);
1069 }
1070
955 return vidioc_try_fmt(f, fmt, ctx, FMT_TYPE_CAPTURE); 1071 return vidioc_try_fmt(f, fmt, ctx, FMT_TYPE_CAPTURE);
956} 1072}
957 1073