aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Kocialkowski2024-09-03 19:14:06 +0200
committerPaul Kocialkowski2024-09-03 19:14:06 +0200
commit5acc2f557495298391ee585237dfe2fd69b5024e (patch)
treef9f56f42e166b98150b134624b1248bcf1a54992
parentc193c161a59e7e890074e2f4934ee133f77af5e4 (diff)
media: cedrus: Rework subsampling handling to allow 4:2:2 destinations
This reworks subsampling handling to allow decoding 4:2:2 (and 4:4:4) JPEG without downsampling to 4:2:0. The configured destination pixel format is checked to support the coded subsampling and downsampling is only applied for 4:2:0 destination pixel formats. The JPEG subsampling information is obtained from the structure returned by the common helper instead of a custom switch/case. Note that the so-called 422T subsampling (also known as 440) is dropped from the list since the common helper does not support it and will error out when encoutering it anyway. Signed-off-by: Paul Kocialkowski <paulk@sys-base.io>
-rw-r--r--drivers/staging/media/sunxi/cedrus/cedrus_jpeg.c53
1 files changed, 35 insertions, 18 deletions
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_jpeg.c b/drivers/staging/media/sunxi/cedrus/cedrus_jpeg.c
index d705e1d6623c..b7b336bcf7a3 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus_jpeg.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_jpeg.c
@@ -176,7 +176,9 @@ static int cedrus_jpeg_setup(struct cedrus_ctx *ctx, struct cedrus_run *run)
.quantization_tables = quantization_tables,
.huffman_tables = huffman_tables,
};
+ const struct v4l2_format_info *format_info;
u32 reg, subsampling;
+ bool downsample = false;
unsigned long size;
int ret, index;
u8 hmax, vmax;
@@ -184,34 +186,52 @@ static int cedrus_jpeg_setup(struct cedrus_ctx *ctx, struct cedrus_run *run)
size = vb2_get_plane_payload(src_buf, 0);
components = header.frame.component;
+ format_info = v4l2_format_info(ctx->dst_fmt.pixelformat);
+ if (!format_info)
+ return -EINVAL;
+
ret = v4l2_jpeg_parse_header(vb2_plane_vaddr(src_buf, 0), size, &header);
if (ret < 0) {
v4l2_err(&dev->v4l2_dev, "failed to parse JPEG header: %d\n", ret);
return -EINVAL;
}
- index = components[0].horizontal_sampling_factor << 20 |
- components[0].vertical_sampling_factor << 16 |
- components[1].horizontal_sampling_factor << 12 |
- components[1].vertical_sampling_factor << 8 |
- components[2].horizontal_sampling_factor << 4 |
- components[2].vertical_sampling_factor;
+ switch (header.frame.subsampling) {
+ case V4L2_JPEG_CHROMA_SUBSAMPLING_420:
+ if (format_info->hdiv != 2 || format_info->vdiv != 2) {
+ v4l2_err(&dev->v4l2_dev,
+ "invalid JPEG 4:2:0 subsampling for destination format\n");
+ return -EINVAL;
+ }
- switch (index) {
- case 0x221111:
subsampling = VE_DEC_MPEG_TRIGGER_CHROMA_FMT_420;
break;
- case 0x211111:
+ case V4L2_JPEG_CHROMA_SUBSAMPLING_422:
+ /* Only allow 4:2:2 or 4:2:0 formats. */
+ if (format_info->hdiv == 2 && format_info->vdiv == 2) {
+ downsample = true;
+ } else if (format_info->hdiv != 2 || format_info->vdiv != 1) {
+ v4l2_err(&dev->v4l2_dev,
+ "invalid JPEG 4:2:2 subsampling for destination format\n");
+ return -EINVAL;
+ }
+
subsampling = VE_DEC_MPEG_TRIGGER_CHROMA_FMT_422;
break;
- case 0x111111:
+ case V4L2_JPEG_CHROMA_SUBSAMPLING_444:
+ /* Only allow 4:4:4 or 4:2:0 formats. */
+ if (format_info->hdiv == 2 && format_info->vdiv == 2) {
+ downsample = true;
+ } else if (format_info->hdiv != 1 || format_info->vdiv != 1) {
+ v4l2_err(&dev->v4l2_dev,
+ "invalid JPEG 4:4:4 subsampling for destination format\n");
+ return -EINVAL;
+ }
+
subsampling = VE_DEC_MPEG_TRIGGER_CHROMA_FMT_444;
break;
- case 0x121111:
- subsampling = VE_DEC_MPEG_TRIGGER_CHROMA_FMT_422T;
- break;
default:
- v4l2_err(&dev->v4l2_dev, "unsupported subsampling\n");
+ v4l2_err(&dev->v4l2_dev, "unsupported JPEG subsampling\n");
return -EINVAL;
}
@@ -295,11 +315,8 @@ static int cedrus_jpeg_setup(struct cedrus_ctx *ctx, struct cedrus_run *run)
/* Enable appropriate interrupts and components. */
reg = VE_DEC_MPEG_CTRL_IRQ_MASK;
- if (subsampling == VE_DEC_MPEG_TRIGGER_CHROMA_FMT_422 ||
- subsampling == VE_DEC_MPEG_TRIGGER_CHROMA_FMT_422T ||
- subsampling == VE_DEC_MPEG_TRIGGER_CHROMA_FMT_444)
+ if (downsample)
reg |= VE_DEC_MPEG_CTRL_JPEG_FORCE_420;
-
cedrus_write(dev, VE_DEC_MPEG_CTRL, reg);
return 0;