Skip to content

Commit

Permalink
media: imx-jpeg: Identify and handle precision correctly
Browse files Browse the repository at this point in the history
[ Upstream commit bec0a3a ]

The decoder will save the precision that was detected from jpeg header
and use it later, when choosing the pixel format and also calculate
bytesperline according to precision.

The 12bit jpeg is not supported yet,
but driver shouldn't led to serious problem if user enqueue a 12 bit jpeg.
And the 12bit jpeg is supported by hardware, driver may support it later.

[hverkuil: document the new precision field]

Signed-off-by: Ming Qian <ming.qian@nxp.com>
Reviewed-by: Mirela Rabulea <mirela.rabulea@nxp.com>
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
  • Loading branch information
mingqian-0 authored and gregkh committed Aug 17, 2022
1 parent 24eef33 commit 8fcbb2e
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 12 deletions.
37 changes: 25 additions & 12 deletions drivers/media/platform/imx-jpeg/mxc-jpeg.c
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ static const struct mxc_jpeg_fmt mxc_formats[] = {
.h_align = 3,
.v_align = 3,
.flags = MXC_JPEG_FMT_TYPE_RAW,
.precision = 8,
},
{
.name = "ARGB", /* ARGBARGB packed format */
Expand All @@ -93,6 +94,7 @@ static const struct mxc_jpeg_fmt mxc_formats[] = {
.h_align = 3,
.v_align = 3,
.flags = MXC_JPEG_FMT_TYPE_RAW,
.precision = 8,
},
{
.name = "YUV420", /* 1st plane = Y, 2nd plane = UV */
Expand All @@ -104,6 +106,7 @@ static const struct mxc_jpeg_fmt mxc_formats[] = {
.h_align = 4,
.v_align = 4,
.flags = MXC_JPEG_FMT_TYPE_RAW,
.precision = 8,
},
{
.name = "YUV422", /* YUYV */
Expand All @@ -115,6 +118,7 @@ static const struct mxc_jpeg_fmt mxc_formats[] = {
.h_align = 4,
.v_align = 3,
.flags = MXC_JPEG_FMT_TYPE_RAW,
.precision = 8,
},
{
.name = "YUV444", /* YUVYUV */
Expand All @@ -126,6 +130,7 @@ static const struct mxc_jpeg_fmt mxc_formats[] = {
.h_align = 3,
.v_align = 3,
.flags = MXC_JPEG_FMT_TYPE_RAW,
.precision = 8,
},
{
.name = "Gray", /* Gray (Y8/Y12) or Single Comp */
Expand All @@ -137,6 +142,7 @@ static const struct mxc_jpeg_fmt mxc_formats[] = {
.h_align = 3,
.v_align = 3,
.flags = MXC_JPEG_FMT_TYPE_RAW,
.precision = 8,
},
};

Expand Down Expand Up @@ -1166,14 +1172,17 @@ static u32 mxc_jpeg_get_image_format(struct device *dev,

for (i = 0; i < MXC_JPEG_NUM_FORMATS; i++)
if (mxc_formats[i].subsampling == header->frame.subsampling &&
mxc_formats[i].nc == header->frame.num_components) {
mxc_formats[i].nc == header->frame.num_components &&
mxc_formats[i].precision == header->frame.precision) {
fourcc = mxc_formats[i].fourcc;
break;
}
if (fourcc == 0) {
dev_err(dev, "Could not identify image format nc=%d, subsampling=%d\n",
dev_err(dev,
"Could not identify image format nc=%d, subsampling=%d, precision=%d\n",
header->frame.num_components,
header->frame.subsampling);
header->frame.subsampling,
header->frame.precision);
return fourcc;
}
/*
Expand All @@ -1199,18 +1208,22 @@ static void mxc_jpeg_bytesperline(struct mxc_jpeg_q_data *q,
/* bytesperline unused for compressed formats */
q->bytesperline[0] = 0;
q->bytesperline[1] = 0;
} else if (q->fmt->fourcc == V4L2_PIX_FMT_NV12M) {
} else if (q->fmt->subsampling == V4L2_JPEG_CHROMA_SUBSAMPLING_420) {
/* When the image format is planar the bytesperline value
* applies to the first plane and is divided by the same factor
* as the width field for the other planes
*/
q->bytesperline[0] = q->w * (precision / 8) *
(q->fmt->depth / 8);
q->bytesperline[0] = q->w * DIV_ROUND_UP(precision, 8);
q->bytesperline[1] = q->bytesperline[0];
} else if (q->fmt->subsampling == V4L2_JPEG_CHROMA_SUBSAMPLING_422) {
q->bytesperline[0] = q->w * DIV_ROUND_UP(precision, 8) * 2;
q->bytesperline[1] = 0;
} else if (q->fmt->subsampling == V4L2_JPEG_CHROMA_SUBSAMPLING_444) {
q->bytesperline[0] = q->w * DIV_ROUND_UP(precision, 8) * q->fmt->nc;
q->bytesperline[1] = 0;
} else {
/* single plane formats */
q->bytesperline[0] = q->w * (precision / 8) *
(q->fmt->depth / 8);
/* grayscale */
q->bytesperline[0] = q->w * DIV_ROUND_UP(precision, 8);
q->bytesperline[1] = 0;
}
}
Expand Down Expand Up @@ -1344,7 +1357,7 @@ static int mxc_jpeg_parse(struct mxc_jpeg_ctx *ctx, struct vb2_buffer *vb)
(fourcc >> 24) & 0xff);

/* setup bytesperline/sizeimage for capture queue */
mxc_jpeg_bytesperline(q_data_cap, header.frame.precision);
mxc_jpeg_bytesperline(q_data_cap, q_data_cap->fmt->precision);
mxc_jpeg_sizeimage(q_data_cap);

/*
Expand Down Expand Up @@ -1500,7 +1513,7 @@ static void mxc_jpeg_set_default_params(struct mxc_jpeg_ctx *ctx)
q[i]->h = MXC_JPEG_DEFAULT_HEIGHT;
q[i]->w_adjusted = MXC_JPEG_DEFAULT_WIDTH;
q[i]->h_adjusted = MXC_JPEG_DEFAULT_HEIGHT;
mxc_jpeg_bytesperline(q[i], 8);
mxc_jpeg_bytesperline(q[i], q[i]->fmt->precision);
mxc_jpeg_sizeimage(q[i]);
}
}
Expand Down Expand Up @@ -1642,7 +1655,7 @@ static int mxc_jpeg_try_fmt(struct v4l2_format *f, const struct mxc_jpeg_fmt *fm
}

/* calculate bytesperline & sizeimage into the tmp_q */
mxc_jpeg_bytesperline(&tmp_q, 8);
mxc_jpeg_bytesperline(&tmp_q, fmt->precision);
mxc_jpeg_sizeimage(&tmp_q);

/* adjust user format according to our calculations */
Expand Down
2 changes: 2 additions & 0 deletions drivers/media/platform/imx-jpeg/mxc-jpeg.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ enum mxc_jpeg_mode {
* @h_align: horizontal alignment order (align to 2^h_align)
* @v_align: vertical alignment order (align to 2^v_align)
* @flags: flags describing format applicability
* @precision: jpeg sample precision
*/
struct mxc_jpeg_fmt {
const char *name;
Expand All @@ -60,6 +61,7 @@ struct mxc_jpeg_fmt {
int h_align;
int v_align;
u32 flags;
u8 precision;
};

struct mxc_jpeg_desc {
Expand Down

0 comments on commit 8fcbb2e

Please sign in to comment.