All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 0/5] imx-jpeg: Support dynamic resolution change
@ 2022-03-23  9:05 ` Ming Qian
  0 siblings, 0 replies; 20+ messages in thread
From: Ming Qian @ 2022-03-23  9:05 UTC (permalink / raw)
  To: mchehab, shawnguo, s.hauer, mirela.rabulea
  Cc: hverkuil-cisco, kernel, festevam, linux-imx, linux-media,
	linux-kernel, devicetree, linux-arm-kernel

These patchset are to support dynamic resolution change.
Avoid decoding error or even kernel panic.
Otherwise, the Gstreamer v4l2videodec will fail to decode jpeg
who is not decoded to yuyv.

Ming Qian (5):
  media: imx-jpeg: Refactor function mxc_jpeg_parse
  media: imx-jpeg: Identify and handle precision correctly
  media: imx-jpeg: Propagate the output frame size to the capture side
  media: imx-jpeg: Handle source change in a function
  media: imx-jpeg: Support dynamic resolution change

 .../media/platform/nxp/imx-jpeg/mxc-jpeg.c    | 249 ++++++++++++------
 .../media/platform/nxp/imx-jpeg/mxc-jpeg.h    |   3 +
 2 files changed, 174 insertions(+), 78 deletions(-)


base-commit: 71e6d0608e4d1b79069990c7dacb3600ced28a3b
-- 
2.33.0


^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH v3 0/5] imx-jpeg: Support dynamic resolution change
@ 2022-03-23  9:05 ` Ming Qian
  0 siblings, 0 replies; 20+ messages in thread
From: Ming Qian @ 2022-03-23  9:05 UTC (permalink / raw)
  To: mchehab, shawnguo, s.hauer, mirela.rabulea
  Cc: hverkuil-cisco, kernel, festevam, linux-imx, linux-media,
	linux-kernel, devicetree, linux-arm-kernel

These patchset are to support dynamic resolution change.
Avoid decoding error or even kernel panic.
Otherwise, the Gstreamer v4l2videodec will fail to decode jpeg
who is not decoded to yuyv.

Ming Qian (5):
  media: imx-jpeg: Refactor function mxc_jpeg_parse
  media: imx-jpeg: Identify and handle precision correctly
  media: imx-jpeg: Propagate the output frame size to the capture side
  media: imx-jpeg: Handle source change in a function
  media: imx-jpeg: Support dynamic resolution change

 .../media/platform/nxp/imx-jpeg/mxc-jpeg.c    | 249 ++++++++++++------
 .../media/platform/nxp/imx-jpeg/mxc-jpeg.h    |   3 +
 2 files changed, 174 insertions(+), 78 deletions(-)


base-commit: 71e6d0608e4d1b79069990c7dacb3600ced28a3b
-- 
2.33.0


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH v3 1/5] media: imx-jpeg: Refactor function mxc_jpeg_parse
  2022-03-23  9:05 ` Ming Qian
@ 2022-03-23  9:05   ` Ming Qian
  -1 siblings, 0 replies; 20+ messages in thread
From: Ming Qian @ 2022-03-23  9:05 UTC (permalink / raw)
  To: mchehab, shawnguo, s.hauer, mirela.rabulea
  Cc: hverkuil-cisco, kernel, festevam, linux-imx, linux-media,
	linux-kernel, devicetree, linux-arm-kernel

Refine code to support dynamic resolution change

Signed-off-by: Ming Qian <ming.qian@nxp.com>
---
 drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c | 13 ++++++-------
 1 file changed, 6 insertions(+), 7 deletions(-)

diff --git a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
index d1ec1f4b506b..48e496cec04d 100644
--- a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
+++ b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
@@ -1245,8 +1245,7 @@ static void mxc_jpeg_sizeimage(struct mxc_jpeg_q_data *q)
 	}
 }
 
-static int mxc_jpeg_parse(struct mxc_jpeg_ctx *ctx,
-			  u8 *src_addr, u32 size, bool *dht_needed)
+static int mxc_jpeg_parse(struct mxc_jpeg_ctx *ctx, struct vb2_buffer *vb)
 {
 	struct device *dev = ctx->mxc_jpeg->dev;
 	struct mxc_jpeg_q_data *q_data_out, *q_data_cap;
@@ -1256,6 +1255,9 @@ static int mxc_jpeg_parse(struct mxc_jpeg_ctx *ctx,
 	struct v4l2_jpeg_header header;
 	struct mxc_jpeg_sof *psof = NULL;
 	struct mxc_jpeg_sos *psos = NULL;
+	struct mxc_jpeg_src_buf *jpeg_src_buf = vb2_to_mxc_buf(vb);
+	u8 *src_addr = (u8 *)vb2_plane_vaddr(vb, 0);
+	u32 size = vb2_get_plane_payload(vb, 0);
 	int ret;
 
 	memset(&header, 0, sizeof(header));
@@ -1266,7 +1268,7 @@ static int mxc_jpeg_parse(struct mxc_jpeg_ctx *ctx,
 	}
 
 	/* if DHT marker present, no need to inject default one */
-	*dht_needed = (header.num_dht == 0);
+	jpeg_src_buf->dht_needed = (header.num_dht == 0);
 
 	q_data_out = mxc_jpeg_get_q_data(ctx,
 					 V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
@@ -1381,10 +1383,7 @@ static void mxc_jpeg_buf_queue(struct vb2_buffer *vb)
 
 	jpeg_src_buf = vb2_to_mxc_buf(vb);
 	jpeg_src_buf->jpeg_parse_error = false;
-	ret = mxc_jpeg_parse(ctx,
-			     (u8 *)vb2_plane_vaddr(vb, 0),
-			     vb2_get_plane_payload(vb, 0),
-			     &jpeg_src_buf->dht_needed);
+	ret = mxc_jpeg_parse(ctx, vb);
 	if (ret)
 		jpeg_src_buf->jpeg_parse_error = true;
 
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v3 1/5] media: imx-jpeg: Refactor function mxc_jpeg_parse
@ 2022-03-23  9:05   ` Ming Qian
  0 siblings, 0 replies; 20+ messages in thread
From: Ming Qian @ 2022-03-23  9:05 UTC (permalink / raw)
  To: mchehab, shawnguo, s.hauer, mirela.rabulea
  Cc: hverkuil-cisco, kernel, festevam, linux-imx, linux-media,
	linux-kernel, devicetree, linux-arm-kernel

Refine code to support dynamic resolution change

Signed-off-by: Ming Qian <ming.qian@nxp.com>
---
 drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c | 13 ++++++-------
 1 file changed, 6 insertions(+), 7 deletions(-)

diff --git a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
index d1ec1f4b506b..48e496cec04d 100644
--- a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
+++ b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
@@ -1245,8 +1245,7 @@ static void mxc_jpeg_sizeimage(struct mxc_jpeg_q_data *q)
 	}
 }
 
-static int mxc_jpeg_parse(struct mxc_jpeg_ctx *ctx,
-			  u8 *src_addr, u32 size, bool *dht_needed)
+static int mxc_jpeg_parse(struct mxc_jpeg_ctx *ctx, struct vb2_buffer *vb)
 {
 	struct device *dev = ctx->mxc_jpeg->dev;
 	struct mxc_jpeg_q_data *q_data_out, *q_data_cap;
@@ -1256,6 +1255,9 @@ static int mxc_jpeg_parse(struct mxc_jpeg_ctx *ctx,
 	struct v4l2_jpeg_header header;
 	struct mxc_jpeg_sof *psof = NULL;
 	struct mxc_jpeg_sos *psos = NULL;
+	struct mxc_jpeg_src_buf *jpeg_src_buf = vb2_to_mxc_buf(vb);
+	u8 *src_addr = (u8 *)vb2_plane_vaddr(vb, 0);
+	u32 size = vb2_get_plane_payload(vb, 0);
 	int ret;
 
 	memset(&header, 0, sizeof(header));
@@ -1266,7 +1268,7 @@ static int mxc_jpeg_parse(struct mxc_jpeg_ctx *ctx,
 	}
 
 	/* if DHT marker present, no need to inject default one */
-	*dht_needed = (header.num_dht == 0);
+	jpeg_src_buf->dht_needed = (header.num_dht == 0);
 
 	q_data_out = mxc_jpeg_get_q_data(ctx,
 					 V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
@@ -1381,10 +1383,7 @@ static void mxc_jpeg_buf_queue(struct vb2_buffer *vb)
 
 	jpeg_src_buf = vb2_to_mxc_buf(vb);
 	jpeg_src_buf->jpeg_parse_error = false;
-	ret = mxc_jpeg_parse(ctx,
-			     (u8 *)vb2_plane_vaddr(vb, 0),
-			     vb2_get_plane_payload(vb, 0),
-			     &jpeg_src_buf->dht_needed);
+	ret = mxc_jpeg_parse(ctx, vb);
 	if (ret)
 		jpeg_src_buf->jpeg_parse_error = true;
 
-- 
2.33.0


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v3 2/5] media: imx-jpeg: Identify and handle precision correctly
  2022-03-23  9:05 ` Ming Qian
@ 2022-03-23  9:05   ` Ming Qian
  -1 siblings, 0 replies; 20+ messages in thread
From: Ming Qian @ 2022-03-23  9:05 UTC (permalink / raw)
  To: mchehab, shawnguo, s.hauer, mirela.rabulea
  Cc: hverkuil-cisco, kernel, festevam, linux-imx, linux-media,
	linux-kernel, devicetree, linux-arm-kernel

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.

Signed-off-by: Ming Qian <ming.qian@nxp.com>
---
 .../media/platform/nxp/imx-jpeg/mxc-jpeg.c    | 37 +++++++++++++------
 .../media/platform/nxp/imx-jpeg/mxc-jpeg.h    |  1 +
 2 files changed, 26 insertions(+), 12 deletions(-)

diff --git a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
index 48e496cec04d..a95305639dd9 100644
--- a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
+++ b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
@@ -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 */
@@ -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 */
@@ -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 */
@@ -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 */
@@ -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 */
@@ -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,
 	},
 };
 
@@ -1175,14 +1181,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;
 	}
 	/*
@@ -1208,18 +1217,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;
 	}
 }
@@ -1353,7 +1366,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);
 
 	/*
@@ -1509,7 +1522,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]);
 	}
 }
@@ -1651,7 +1664,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 */
diff --git a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.h b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.h
index f53f004ba851..82b38cc2dfab 100644
--- a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.h
+++ b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.h
@@ -60,6 +60,7 @@ struct mxc_jpeg_fmt {
 	int					h_align;
 	int					v_align;
 	u32					flags;
+	u8					precision;
 };
 
 struct mxc_jpeg_desc {
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v3 2/5] media: imx-jpeg: Identify and handle precision correctly
@ 2022-03-23  9:05   ` Ming Qian
  0 siblings, 0 replies; 20+ messages in thread
From: Ming Qian @ 2022-03-23  9:05 UTC (permalink / raw)
  To: mchehab, shawnguo, s.hauer, mirela.rabulea
  Cc: hverkuil-cisco, kernel, festevam, linux-imx, linux-media,
	linux-kernel, devicetree, linux-arm-kernel

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.

Signed-off-by: Ming Qian <ming.qian@nxp.com>
---
 .../media/platform/nxp/imx-jpeg/mxc-jpeg.c    | 37 +++++++++++++------
 .../media/platform/nxp/imx-jpeg/mxc-jpeg.h    |  1 +
 2 files changed, 26 insertions(+), 12 deletions(-)

diff --git a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
index 48e496cec04d..a95305639dd9 100644
--- a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
+++ b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
@@ -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 */
@@ -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 */
@@ -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 */
@@ -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 */
@@ -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 */
@@ -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,
 	},
 };
 
@@ -1175,14 +1181,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;
 	}
 	/*
@@ -1208,18 +1217,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;
 	}
 }
@@ -1353,7 +1366,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);
 
 	/*
@@ -1509,7 +1522,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]);
 	}
 }
@@ -1651,7 +1664,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 */
diff --git a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.h b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.h
index f53f004ba851..82b38cc2dfab 100644
--- a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.h
+++ b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.h
@@ -60,6 +60,7 @@ struct mxc_jpeg_fmt {
 	int					h_align;
 	int					v_align;
 	u32					flags;
+	u8					precision;
 };
 
 struct mxc_jpeg_desc {
-- 
2.33.0


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v3 3/5] media: imx-jpeg: Propagate the output frame size to the capture side
  2022-03-23  9:05 ` Ming Qian
@ 2022-03-23  9:05   ` Ming Qian
  -1 siblings, 0 replies; 20+ messages in thread
From: Ming Qian @ 2022-03-23  9:05 UTC (permalink / raw)
  To: mchehab, shawnguo, s.hauer, mirela.rabulea
  Cc: hverkuil-cisco, kernel, festevam, linux-imx, linux-media,
	linux-kernel, devicetree, linux-arm-kernel

The GStreamer v4l2videodec only ever calls S_FMT on the output side
and then expects G_FMT on the capture side to return a valid format.

Signed-off-by: Ming Qian <ming.qian@nxp.com>
---
 .../media/platform/nxp/imx-jpeg/mxc-jpeg.c    | 30 ++++++++++++++++++-
 1 file changed, 29 insertions(+), 1 deletion(-)

diff --git a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
index a95305639dd9..5dfa6f87871e 100644
--- a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
+++ b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
@@ -1831,12 +1831,40 @@ static int mxc_jpeg_s_fmt_vid_out(struct file *file, void *priv,
 				  struct v4l2_format *f)
 {
 	int ret;
+	struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(priv);
+	struct vb2_queue *dst_vq;
+	struct mxc_jpeg_q_data *q_data_cap;
+	enum v4l2_buf_type cap_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+	struct v4l2_format fc;
 
 	ret = mxc_jpeg_try_fmt_vid_out(file, priv, f);
 	if (ret)
 		return ret;
 
-	return mxc_jpeg_s_fmt(mxc_jpeg_fh_to_ctx(priv), f);
+	ret = mxc_jpeg_s_fmt(mxc_jpeg_fh_to_ctx(priv), f);
+	if (ret)
+		return ret;
+
+	if (ctx->mxc_jpeg->mode != MXC_JPEG_DECODE)
+		return 0;
+
+	dst_vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, cap_type);
+	if (!dst_vq)
+		return -EINVAL;
+
+	if (vb2_is_busy(dst_vq))
+		return 0;
+
+	q_data_cap = mxc_jpeg_get_q_data(ctx, cap_type);
+	if (q_data_cap->w == f->fmt.pix_mp.width && q_data_cap->h == f->fmt.pix_mp.height)
+		return 0;
+	memset(&fc, 0, sizeof(fc));
+	fc.type = cap_type;
+	fc.fmt.pix_mp.pixelformat = q_data_cap->fmt->fourcc;
+	fc.fmt.pix_mp.width = f->fmt.pix_mp.width;
+	fc.fmt.pix_mp.height = f->fmt.pix_mp.height;
+
+	return mxc_jpeg_s_fmt_vid_cap(file, priv, &fc);
 }
 
 static int mxc_jpeg_g_fmt_vid(struct file *file, void *priv,
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v3 3/5] media: imx-jpeg: Propagate the output frame size to the capture side
@ 2022-03-23  9:05   ` Ming Qian
  0 siblings, 0 replies; 20+ messages in thread
From: Ming Qian @ 2022-03-23  9:05 UTC (permalink / raw)
  To: mchehab, shawnguo, s.hauer, mirela.rabulea
  Cc: hverkuil-cisco, kernel, festevam, linux-imx, linux-media,
	linux-kernel, devicetree, linux-arm-kernel

The GStreamer v4l2videodec only ever calls S_FMT on the output side
and then expects G_FMT on the capture side to return a valid format.

Signed-off-by: Ming Qian <ming.qian@nxp.com>
---
 .../media/platform/nxp/imx-jpeg/mxc-jpeg.c    | 30 ++++++++++++++++++-
 1 file changed, 29 insertions(+), 1 deletion(-)

diff --git a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
index a95305639dd9..5dfa6f87871e 100644
--- a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
+++ b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
@@ -1831,12 +1831,40 @@ static int mxc_jpeg_s_fmt_vid_out(struct file *file, void *priv,
 				  struct v4l2_format *f)
 {
 	int ret;
+	struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(priv);
+	struct vb2_queue *dst_vq;
+	struct mxc_jpeg_q_data *q_data_cap;
+	enum v4l2_buf_type cap_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+	struct v4l2_format fc;
 
 	ret = mxc_jpeg_try_fmt_vid_out(file, priv, f);
 	if (ret)
 		return ret;
 
-	return mxc_jpeg_s_fmt(mxc_jpeg_fh_to_ctx(priv), f);
+	ret = mxc_jpeg_s_fmt(mxc_jpeg_fh_to_ctx(priv), f);
+	if (ret)
+		return ret;
+
+	if (ctx->mxc_jpeg->mode != MXC_JPEG_DECODE)
+		return 0;
+
+	dst_vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, cap_type);
+	if (!dst_vq)
+		return -EINVAL;
+
+	if (vb2_is_busy(dst_vq))
+		return 0;
+
+	q_data_cap = mxc_jpeg_get_q_data(ctx, cap_type);
+	if (q_data_cap->w == f->fmt.pix_mp.width && q_data_cap->h == f->fmt.pix_mp.height)
+		return 0;
+	memset(&fc, 0, sizeof(fc));
+	fc.type = cap_type;
+	fc.fmt.pix_mp.pixelformat = q_data_cap->fmt->fourcc;
+	fc.fmt.pix_mp.width = f->fmt.pix_mp.width;
+	fc.fmt.pix_mp.height = f->fmt.pix_mp.height;
+
+	return mxc_jpeg_s_fmt_vid_cap(file, priv, &fc);
 }
 
 static int mxc_jpeg_g_fmt_vid(struct file *file, void *priv,
-- 
2.33.0


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v3 4/5] media: imx-jpeg: Handle source change in a function
  2022-03-23  9:05 ` Ming Qian
@ 2022-03-23  9:05   ` Ming Qian
  -1 siblings, 0 replies; 20+ messages in thread
From: Ming Qian @ 2022-03-23  9:05 UTC (permalink / raw)
  To: mchehab, shawnguo, s.hauer, mirela.rabulea
  Cc: hverkuil-cisco, kernel, festevam, linux-imx, linux-media,
	linux-kernel, devicetree, linux-arm-kernel

Refine code to support dynamic resolution change

Signed-off-by: Ming Qian <ming.qian@nxp.com>
---
 .../media/platform/nxp/imx-jpeg/mxc-jpeg.c    | 114 ++++++++++--------
 1 file changed, 65 insertions(+), 49 deletions(-)

diff --git a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
index 5dfa6f87871e..30289f2be3dd 100644
--- a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
+++ b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
@@ -315,6 +315,9 @@ struct mxc_jpeg_src_buf {
 	/* mxc-jpeg specific */
 	bool			dht_needed;
 	bool			jpeg_parse_error;
+	const struct mxc_jpeg_fmt	*fmt;
+	int			w;
+	int			h;
 };
 
 static inline struct mxc_jpeg_src_buf *vb2_to_mxc_buf(struct vb2_buffer *vb)
@@ -327,6 +330,9 @@ static unsigned int debug;
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "Debug level (0-3)");
 
+static void mxc_jpeg_bytesperline(struct mxc_jpeg_q_data *q, u32 precision);
+static void mxc_jpeg_sizeimage(struct mxc_jpeg_q_data *q);
+
 static void _bswap16(u16 *a)
 {
 	*a = ((*a & 0x00FF) << 8) | ((*a & 0xFF00) >> 8);
@@ -922,6 +928,59 @@ static void mxc_jpeg_config_enc_desc(struct vb2_buffer *out_buf,
 	mxc_jpeg_set_desc(cfg_desc_handle, reg, slot);
 }
 
+static bool mxc_jpeg_source_change(struct mxc_jpeg_ctx *ctx,
+				   struct mxc_jpeg_src_buf *jpeg_src_buf)
+{
+	struct device *dev = ctx->mxc_jpeg->dev;
+	struct mxc_jpeg_q_data *q_data_cap;
+	bool src_chg = false;
+
+	if (!jpeg_src_buf->fmt)
+		return src_chg;
+
+	q_data_cap = mxc_jpeg_get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
+	if (q_data_cap->w != jpeg_src_buf->w || q_data_cap->h != jpeg_src_buf->h) {
+		dev_dbg(dev, "Detected jpeg res=(%dx%d)->(%dx%d), pixfmt=%c%c%c%c\n",
+			q_data_cap->w, q_data_cap->h,
+			jpeg_src_buf->w, jpeg_src_buf->h,
+			(jpeg_src_buf->fmt->fourcc & 0xff),
+			(jpeg_src_buf->fmt->fourcc >>  8) & 0xff,
+			(jpeg_src_buf->fmt->fourcc >> 16) & 0xff,
+			(jpeg_src_buf->fmt->fourcc >> 24) & 0xff);
+
+		/*
+		 * set-up the capture queue with the pixelformat and resolution
+		 * detected from the jpeg output stream
+		 */
+		q_data_cap->w = jpeg_src_buf->w;
+		q_data_cap->h = jpeg_src_buf->h;
+		q_data_cap->fmt = jpeg_src_buf->fmt;
+		q_data_cap->w_adjusted = q_data_cap->w;
+		q_data_cap->h_adjusted = q_data_cap->h;
+
+		/*
+		 * align up the resolution for CAST IP,
+		 * but leave the buffer resolution unchanged
+		 */
+		v4l_bound_align_image(&q_data_cap->w_adjusted,
+				      q_data_cap->w_adjusted,  /* adjust up */
+				      MXC_JPEG_MAX_WIDTH,
+				      q_data_cap->fmt->h_align,
+				      &q_data_cap->h_adjusted,
+				      q_data_cap->h_adjusted, /* adjust up */
+				      MXC_JPEG_MAX_HEIGHT,
+				      q_data_cap->fmt->v_align,
+				      0);
+
+		/* setup bytesperline/sizeimage for capture queue */
+		mxc_jpeg_bytesperline(q_data_cap, jpeg_src_buf->fmt->precision);
+		mxc_jpeg_sizeimage(q_data_cap);
+		notify_src_chg(ctx);
+		src_chg = true;
+	}
+	return src_chg;
+}
+
 static void mxc_jpeg_device_run(void *priv)
 {
 	struct mxc_jpeg_ctx *ctx = priv;
@@ -1209,8 +1268,7 @@ static u32 mxc_jpeg_get_image_format(struct device *dev,
 	return fourcc;
 }
 
-static void mxc_jpeg_bytesperline(struct mxc_jpeg_q_data *q,
-				  u32 precision)
+static void mxc_jpeg_bytesperline(struct mxc_jpeg_q_data *q, u32 precision)
 {
 	/* Bytes distance between the leftmost pixels in two adjacent lines */
 	if (q->fmt->fourcc == V4L2_PIX_FMT_JPEG) {
@@ -1261,9 +1319,7 @@ static void mxc_jpeg_sizeimage(struct mxc_jpeg_q_data *q)
 static int mxc_jpeg_parse(struct mxc_jpeg_ctx *ctx, struct vb2_buffer *vb)
 {
 	struct device *dev = ctx->mxc_jpeg->dev;
-	struct mxc_jpeg_q_data *q_data_out, *q_data_cap;
-	enum v4l2_buf_type cap_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
-	bool src_chg = false;
+	struct mxc_jpeg_q_data *q_data_out;
 	u32 fourcc;
 	struct v4l2_jpeg_header header;
 	struct mxc_jpeg_sof *psof = NULL;
@@ -1331,51 +1387,11 @@ static int mxc_jpeg_parse(struct mxc_jpeg_ctx *ctx, struct vb2_buffer *vb)
 	if (fourcc == 0)
 		return -EINVAL;
 
-	/*
-	 * set-up the capture queue with the pixelformat and resolution
-	 * detected from the jpeg output stream
-	 */
-	q_data_cap = mxc_jpeg_get_q_data(ctx, cap_type);
-	if (q_data_cap->w != header.frame.width ||
-	    q_data_cap->h != header.frame.height)
-		src_chg = true;
-	q_data_cap->w = header.frame.width;
-	q_data_cap->h = header.frame.height;
-	q_data_cap->fmt = mxc_jpeg_find_format(ctx, fourcc);
-	q_data_cap->w_adjusted = q_data_cap->w;
-	q_data_cap->h_adjusted = q_data_cap->h;
-	/*
-	 * align up the resolution for CAST IP,
-	 * but leave the buffer resolution unchanged
-	 */
-	v4l_bound_align_image(&q_data_cap->w_adjusted,
-			      q_data_cap->w_adjusted,  /* adjust up */
-			      MXC_JPEG_MAX_WIDTH,
-			      q_data_cap->fmt->h_align,
-			      &q_data_cap->h_adjusted,
-			      q_data_cap->h_adjusted, /* adjust up */
-			      MXC_JPEG_MAX_HEIGHT,
-			      q_data_cap->fmt->v_align,
-			      0);
-	dev_dbg(dev, "Detected jpeg res=(%dx%d)->(%dx%d), pixfmt=%c%c%c%c\n",
-		q_data_cap->w, q_data_cap->h,
-		q_data_cap->w_adjusted, q_data_cap->h_adjusted,
-		(fourcc & 0xff),
-		(fourcc >>  8) & 0xff,
-		(fourcc >> 16) & 0xff,
-		(fourcc >> 24) & 0xff);
-
-	/* setup bytesperline/sizeimage for capture queue */
-	mxc_jpeg_bytesperline(q_data_cap, q_data_cap->fmt->precision);
-	mxc_jpeg_sizeimage(q_data_cap);
+	jpeg_src_buf->fmt = mxc_jpeg_find_format(ctx, fourcc);
+	jpeg_src_buf->w = header.frame.width;
+	jpeg_src_buf->h = header.frame.height;
 
-	/*
-	 * if the CAPTURE format was updated with new values, regardless of
-	 * whether they match the values set by the client or not, signal
-	 * a source change event
-	 */
-	if (src_chg)
-		notify_src_chg(ctx);
+	mxc_jpeg_source_change(ctx, jpeg_src_buf);
 
 	return 0;
 }
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v3 4/5] media: imx-jpeg: Handle source change in a function
@ 2022-03-23  9:05   ` Ming Qian
  0 siblings, 0 replies; 20+ messages in thread
From: Ming Qian @ 2022-03-23  9:05 UTC (permalink / raw)
  To: mchehab, shawnguo, s.hauer, mirela.rabulea
  Cc: hverkuil-cisco, kernel, festevam, linux-imx, linux-media,
	linux-kernel, devicetree, linux-arm-kernel

Refine code to support dynamic resolution change

Signed-off-by: Ming Qian <ming.qian@nxp.com>
---
 .../media/platform/nxp/imx-jpeg/mxc-jpeg.c    | 114 ++++++++++--------
 1 file changed, 65 insertions(+), 49 deletions(-)

diff --git a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
index 5dfa6f87871e..30289f2be3dd 100644
--- a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
+++ b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
@@ -315,6 +315,9 @@ struct mxc_jpeg_src_buf {
 	/* mxc-jpeg specific */
 	bool			dht_needed;
 	bool			jpeg_parse_error;
+	const struct mxc_jpeg_fmt	*fmt;
+	int			w;
+	int			h;
 };
 
 static inline struct mxc_jpeg_src_buf *vb2_to_mxc_buf(struct vb2_buffer *vb)
@@ -327,6 +330,9 @@ static unsigned int debug;
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "Debug level (0-3)");
 
+static void mxc_jpeg_bytesperline(struct mxc_jpeg_q_data *q, u32 precision);
+static void mxc_jpeg_sizeimage(struct mxc_jpeg_q_data *q);
+
 static void _bswap16(u16 *a)
 {
 	*a = ((*a & 0x00FF) << 8) | ((*a & 0xFF00) >> 8);
@@ -922,6 +928,59 @@ static void mxc_jpeg_config_enc_desc(struct vb2_buffer *out_buf,
 	mxc_jpeg_set_desc(cfg_desc_handle, reg, slot);
 }
 
+static bool mxc_jpeg_source_change(struct mxc_jpeg_ctx *ctx,
+				   struct mxc_jpeg_src_buf *jpeg_src_buf)
+{
+	struct device *dev = ctx->mxc_jpeg->dev;
+	struct mxc_jpeg_q_data *q_data_cap;
+	bool src_chg = false;
+
+	if (!jpeg_src_buf->fmt)
+		return src_chg;
+
+	q_data_cap = mxc_jpeg_get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
+	if (q_data_cap->w != jpeg_src_buf->w || q_data_cap->h != jpeg_src_buf->h) {
+		dev_dbg(dev, "Detected jpeg res=(%dx%d)->(%dx%d), pixfmt=%c%c%c%c\n",
+			q_data_cap->w, q_data_cap->h,
+			jpeg_src_buf->w, jpeg_src_buf->h,
+			(jpeg_src_buf->fmt->fourcc & 0xff),
+			(jpeg_src_buf->fmt->fourcc >>  8) & 0xff,
+			(jpeg_src_buf->fmt->fourcc >> 16) & 0xff,
+			(jpeg_src_buf->fmt->fourcc >> 24) & 0xff);
+
+		/*
+		 * set-up the capture queue with the pixelformat and resolution
+		 * detected from the jpeg output stream
+		 */
+		q_data_cap->w = jpeg_src_buf->w;
+		q_data_cap->h = jpeg_src_buf->h;
+		q_data_cap->fmt = jpeg_src_buf->fmt;
+		q_data_cap->w_adjusted = q_data_cap->w;
+		q_data_cap->h_adjusted = q_data_cap->h;
+
+		/*
+		 * align up the resolution for CAST IP,
+		 * but leave the buffer resolution unchanged
+		 */
+		v4l_bound_align_image(&q_data_cap->w_adjusted,
+				      q_data_cap->w_adjusted,  /* adjust up */
+				      MXC_JPEG_MAX_WIDTH,
+				      q_data_cap->fmt->h_align,
+				      &q_data_cap->h_adjusted,
+				      q_data_cap->h_adjusted, /* adjust up */
+				      MXC_JPEG_MAX_HEIGHT,
+				      q_data_cap->fmt->v_align,
+				      0);
+
+		/* setup bytesperline/sizeimage for capture queue */
+		mxc_jpeg_bytesperline(q_data_cap, jpeg_src_buf->fmt->precision);
+		mxc_jpeg_sizeimage(q_data_cap);
+		notify_src_chg(ctx);
+		src_chg = true;
+	}
+	return src_chg;
+}
+
 static void mxc_jpeg_device_run(void *priv)
 {
 	struct mxc_jpeg_ctx *ctx = priv;
@@ -1209,8 +1268,7 @@ static u32 mxc_jpeg_get_image_format(struct device *dev,
 	return fourcc;
 }
 
-static void mxc_jpeg_bytesperline(struct mxc_jpeg_q_data *q,
-				  u32 precision)
+static void mxc_jpeg_bytesperline(struct mxc_jpeg_q_data *q, u32 precision)
 {
 	/* Bytes distance between the leftmost pixels in two adjacent lines */
 	if (q->fmt->fourcc == V4L2_PIX_FMT_JPEG) {
@@ -1261,9 +1319,7 @@ static void mxc_jpeg_sizeimage(struct mxc_jpeg_q_data *q)
 static int mxc_jpeg_parse(struct mxc_jpeg_ctx *ctx, struct vb2_buffer *vb)
 {
 	struct device *dev = ctx->mxc_jpeg->dev;
-	struct mxc_jpeg_q_data *q_data_out, *q_data_cap;
-	enum v4l2_buf_type cap_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
-	bool src_chg = false;
+	struct mxc_jpeg_q_data *q_data_out;
 	u32 fourcc;
 	struct v4l2_jpeg_header header;
 	struct mxc_jpeg_sof *psof = NULL;
@@ -1331,51 +1387,11 @@ static int mxc_jpeg_parse(struct mxc_jpeg_ctx *ctx, struct vb2_buffer *vb)
 	if (fourcc == 0)
 		return -EINVAL;
 
-	/*
-	 * set-up the capture queue with the pixelformat and resolution
-	 * detected from the jpeg output stream
-	 */
-	q_data_cap = mxc_jpeg_get_q_data(ctx, cap_type);
-	if (q_data_cap->w != header.frame.width ||
-	    q_data_cap->h != header.frame.height)
-		src_chg = true;
-	q_data_cap->w = header.frame.width;
-	q_data_cap->h = header.frame.height;
-	q_data_cap->fmt = mxc_jpeg_find_format(ctx, fourcc);
-	q_data_cap->w_adjusted = q_data_cap->w;
-	q_data_cap->h_adjusted = q_data_cap->h;
-	/*
-	 * align up the resolution for CAST IP,
-	 * but leave the buffer resolution unchanged
-	 */
-	v4l_bound_align_image(&q_data_cap->w_adjusted,
-			      q_data_cap->w_adjusted,  /* adjust up */
-			      MXC_JPEG_MAX_WIDTH,
-			      q_data_cap->fmt->h_align,
-			      &q_data_cap->h_adjusted,
-			      q_data_cap->h_adjusted, /* adjust up */
-			      MXC_JPEG_MAX_HEIGHT,
-			      q_data_cap->fmt->v_align,
-			      0);
-	dev_dbg(dev, "Detected jpeg res=(%dx%d)->(%dx%d), pixfmt=%c%c%c%c\n",
-		q_data_cap->w, q_data_cap->h,
-		q_data_cap->w_adjusted, q_data_cap->h_adjusted,
-		(fourcc & 0xff),
-		(fourcc >>  8) & 0xff,
-		(fourcc >> 16) & 0xff,
-		(fourcc >> 24) & 0xff);
-
-	/* setup bytesperline/sizeimage for capture queue */
-	mxc_jpeg_bytesperline(q_data_cap, q_data_cap->fmt->precision);
-	mxc_jpeg_sizeimage(q_data_cap);
+	jpeg_src_buf->fmt = mxc_jpeg_find_format(ctx, fourcc);
+	jpeg_src_buf->w = header.frame.width;
+	jpeg_src_buf->h = header.frame.height;
 
-	/*
-	 * if the CAPTURE format was updated with new values, regardless of
-	 * whether they match the values set by the client or not, signal
-	 * a source change event
-	 */
-	if (src_chg)
-		notify_src_chg(ctx);
+	mxc_jpeg_source_change(ctx, jpeg_src_buf);
 
 	return 0;
 }
-- 
2.33.0


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v3 5/5] media: imx-jpeg: Support dynamic resolution change
  2022-03-23  9:05 ` Ming Qian
@ 2022-03-23  9:05   ` Ming Qian
  -1 siblings, 0 replies; 20+ messages in thread
From: Ming Qian @ 2022-03-23  9:05 UTC (permalink / raw)
  To: mchehab, shawnguo, s.hauer, mirela.rabulea
  Cc: hverkuil-cisco, kernel, festevam, linux-imx, linux-media,
	linux-kernel, devicetree, linux-arm-kernel

To support dynamic resolution change,
driver should meet the following conditions:
1. the previous pictures are all decoded before source change event.
2. prevent decoding new resolution pictures with incorrect capture
   buffer, until user handle source change event and setup capture.
3. report correct fmt and resolution during source change.

Signed-off-by: Ming Qian <ming.qian@nxp.com>
---
 .../media/platform/nxp/imx-jpeg/mxc-jpeg.c    | 69 ++++++++++++++-----
 .../media/platform/nxp/imx-jpeg/mxc-jpeg.h    |  2 +
 2 files changed, 55 insertions(+), 16 deletions(-)

diff --git a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
index 30289f2be3dd..0c3a1efbeae7 100644
--- a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
+++ b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
@@ -933,13 +933,14 @@ static bool mxc_jpeg_source_change(struct mxc_jpeg_ctx *ctx,
 {
 	struct device *dev = ctx->mxc_jpeg->dev;
 	struct mxc_jpeg_q_data *q_data_cap;
-	bool src_chg = false;
 
 	if (!jpeg_src_buf->fmt)
-		return src_chg;
+		return false;
 
 	q_data_cap = mxc_jpeg_get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
-	if (q_data_cap->w != jpeg_src_buf->w || q_data_cap->h != jpeg_src_buf->h) {
+	if (q_data_cap->fmt != jpeg_src_buf->fmt ||
+	    q_data_cap->w != jpeg_src_buf->w ||
+	    q_data_cap->h != jpeg_src_buf->h) {
 		dev_dbg(dev, "Detected jpeg res=(%dx%d)->(%dx%d), pixfmt=%c%c%c%c\n",
 			q_data_cap->w, q_data_cap->h,
 			jpeg_src_buf->w, jpeg_src_buf->h,
@@ -976,9 +977,16 @@ static bool mxc_jpeg_source_change(struct mxc_jpeg_ctx *ctx,
 		mxc_jpeg_bytesperline(q_data_cap, jpeg_src_buf->fmt->precision);
 		mxc_jpeg_sizeimage(q_data_cap);
 		notify_src_chg(ctx);
-		src_chg = true;
+		ctx->source_change = 1;
 	}
-	return src_chg;
+	return ctx->source_change ? true : false;
+}
+
+static int mxc_jpeg_job_ready(void *priv)
+{
+	struct mxc_jpeg_ctx *ctx = priv;
+
+	return ctx->source_change ? 0 : 1;
 }
 
 static void mxc_jpeg_device_run(void *priv)
@@ -1028,6 +1036,13 @@ static void mxc_jpeg_device_run(void *priv)
 
 		return;
 	}
+	if (ctx->mxc_jpeg->mode == MXC_JPEG_DECODE) {
+		if (ctx->source_change || mxc_jpeg_source_change(ctx, jpeg_src_buf)) {
+			spin_unlock_irqrestore(&ctx->mxc_jpeg->hw_lock, flags);
+			v4l2_m2m_job_finish(jpeg->m2m_dev, ctx->fh.m2m_ctx);
+			return;
+		}
+	}
 
 	mxc_jpeg_enable(reg);
 	mxc_jpeg_set_l_endian(reg, 1);
@@ -1074,6 +1089,7 @@ static void mxc_jpeg_set_last_buffer_dequeued(struct mxc_jpeg_ctx *ctx)
 	q->last_buffer_dequeued = true;
 	wake_up(&q->done_wq);
 	ctx->stopped = 0;
+	ctx->header_parsed = false;
 }
 
 static int mxc_jpeg_decoder_cmd(struct file *file, void *priv,
@@ -1167,6 +1183,8 @@ static int mxc_jpeg_start_streaming(struct vb2_queue *q, unsigned int count)
 	struct mxc_jpeg_q_data *q_data = mxc_jpeg_get_q_data(ctx, q->type);
 	int ret;
 
+	if (ctx->mxc_jpeg->mode == MXC_JPEG_DECODE && V4L2_TYPE_IS_CAPTURE(q->type))
+		ctx->source_change = 0;
 	dev_dbg(ctx->mxc_jpeg->dev, "Start streaming ctx=%p", ctx);
 	q_data->sequence = 0;
 
@@ -1345,16 +1363,15 @@ static int mxc_jpeg_parse(struct mxc_jpeg_ctx *ctx, struct vb2_buffer *vb)
 		dev_warn(dev, "Invalid user resolution 0x0");
 		dev_warn(dev, "Keeping resolution from JPEG: %dx%d",
 			 header.frame.width, header.frame.height);
-		q_data_out->w = header.frame.width;
-		q_data_out->h = header.frame.height;
 	} else if (header.frame.width != q_data_out->w ||
 		   header.frame.height != q_data_out->h) {
 		dev_err(dev,
 			"Resolution mismatch: %dx%d (JPEG) versus %dx%d(user)",
 			header.frame.width, header.frame.height,
 			q_data_out->w, q_data_out->h);
-		return -EINVAL;
 	}
+	q_data_out->w = header.frame.width;
+	q_data_out->h = header.frame.height;
 	if (header.frame.width % 8 != 0 || header.frame.height % 8 != 0) {
 		dev_err(dev, "JPEG width or height not multiple of 8: %dx%d\n",
 			header.frame.width, header.frame.height);
@@ -1390,8 +1407,10 @@ static int mxc_jpeg_parse(struct mxc_jpeg_ctx *ctx, struct vb2_buffer *vb)
 	jpeg_src_buf->fmt = mxc_jpeg_find_format(ctx, fourcc);
 	jpeg_src_buf->w = header.frame.width;
 	jpeg_src_buf->h = header.frame.height;
+	ctx->header_parsed = true;
 
-	mxc_jpeg_source_change(ctx, jpeg_src_buf);
+	if (!v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx))
+		mxc_jpeg_source_change(ctx, jpeg_src_buf);
 
 	return 0;
 }
@@ -1468,6 +1487,7 @@ static void mxc_jpeg_buf_finish(struct vb2_buffer *vb)
 	if (list_empty(&q->done_list)) {
 		vbuf->flags |= V4L2_BUF_FLAG_LAST;
 		ctx->stopped = 0;
+		ctx->header_parsed = false;
 	}
 }
 
@@ -1613,26 +1633,42 @@ static int mxc_jpeg_enum_fmt_vid_cap(struct file *file, void *priv,
 				     struct v4l2_fmtdesc *f)
 {
 	struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(priv);
+	struct mxc_jpeg_q_data *q_data = mxc_jpeg_get_q_data(ctx, f->type);
 
-	if (ctx->mxc_jpeg->mode == MXC_JPEG_ENCODE)
+	if (ctx->mxc_jpeg->mode == MXC_JPEG_ENCODE) {
 		return enum_fmt(mxc_formats, MXC_JPEG_NUM_FORMATS, f,
 			MXC_JPEG_FMT_TYPE_ENC);
-	else
+	} else if (!ctx->header_parsed) {
 		return enum_fmt(mxc_formats, MXC_JPEG_NUM_FORMATS, f,
 			MXC_JPEG_FMT_TYPE_RAW);
+	} else {
+		/* For the decoder CAPTURE queue, only enumerate the raw formats
+		 * supported for the format currently active on OUTPUT
+		 * (more precisely what was propagated on capture queue
+		 * after jpeg parse on the output buffer)
+		 */
+		if (f->index)
+			return -EINVAL;
+		f->pixelformat = q_data->fmt->fourcc;
+		strscpy(f->description, q_data->fmt->name, sizeof(f->description));
+		return 0;
+	}
 }
 
 static int mxc_jpeg_enum_fmt_vid_out(struct file *file, void *priv,
 				     struct v4l2_fmtdesc *f)
 {
 	struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(priv);
+	u32 type = ctx->mxc_jpeg->mode == MXC_JPEG_DECODE ?  MXC_JPEG_FMT_TYPE_ENC :
+							     MXC_JPEG_FMT_TYPE_RAW;
+	int ret;
 
+	ret = enum_fmt(mxc_formats, MXC_JPEG_NUM_FORMATS, f, type);
+	if (ret)
+		return ret;
 	if (ctx->mxc_jpeg->mode == MXC_JPEG_DECODE)
-		return enum_fmt(mxc_formats, MXC_JPEG_NUM_FORMATS, f,
-				MXC_JPEG_FMT_TYPE_ENC);
-	else
-		return enum_fmt(mxc_formats, MXC_JPEG_NUM_FORMATS, f,
-				MXC_JPEG_FMT_TYPE_RAW);
+		f->flags = V4L2_FMT_FLAG_DYN_RESOLUTION;
+	return 0;
 }
 
 static int mxc_jpeg_try_fmt(struct v4l2_format *f, const struct mxc_jpeg_fmt *fmt,
@@ -2018,6 +2054,7 @@ static const struct v4l2_file_operations mxc_jpeg_fops = {
 };
 
 static const struct v4l2_m2m_ops mxc_jpeg_m2m_ops = {
+	.job_ready      = mxc_jpeg_job_ready,
 	.device_run	= mxc_jpeg_device_run,
 };
 
diff --git a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.h b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.h
index 82b38cc2dfab..9ae56e6e0fbe 100644
--- a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.h
+++ b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.h
@@ -94,6 +94,8 @@ struct mxc_jpeg_ctx {
 	unsigned int			stopping;
 	unsigned int			stopped;
 	unsigned int			slot;
+	unsigned int			source_change;
+	bool				header_parsed;
 };
 
 struct mxc_jpeg_slot_data {
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v3 5/5] media: imx-jpeg: Support dynamic resolution change
@ 2022-03-23  9:05   ` Ming Qian
  0 siblings, 0 replies; 20+ messages in thread
From: Ming Qian @ 2022-03-23  9:05 UTC (permalink / raw)
  To: mchehab, shawnguo, s.hauer, mirela.rabulea
  Cc: hverkuil-cisco, kernel, festevam, linux-imx, linux-media,
	linux-kernel, devicetree, linux-arm-kernel

To support dynamic resolution change,
driver should meet the following conditions:
1. the previous pictures are all decoded before source change event.
2. prevent decoding new resolution pictures with incorrect capture
   buffer, until user handle source change event and setup capture.
3. report correct fmt and resolution during source change.

Signed-off-by: Ming Qian <ming.qian@nxp.com>
---
 .../media/platform/nxp/imx-jpeg/mxc-jpeg.c    | 69 ++++++++++++++-----
 .../media/platform/nxp/imx-jpeg/mxc-jpeg.h    |  2 +
 2 files changed, 55 insertions(+), 16 deletions(-)

diff --git a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
index 30289f2be3dd..0c3a1efbeae7 100644
--- a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
+++ b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
@@ -933,13 +933,14 @@ static bool mxc_jpeg_source_change(struct mxc_jpeg_ctx *ctx,
 {
 	struct device *dev = ctx->mxc_jpeg->dev;
 	struct mxc_jpeg_q_data *q_data_cap;
-	bool src_chg = false;
 
 	if (!jpeg_src_buf->fmt)
-		return src_chg;
+		return false;
 
 	q_data_cap = mxc_jpeg_get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
-	if (q_data_cap->w != jpeg_src_buf->w || q_data_cap->h != jpeg_src_buf->h) {
+	if (q_data_cap->fmt != jpeg_src_buf->fmt ||
+	    q_data_cap->w != jpeg_src_buf->w ||
+	    q_data_cap->h != jpeg_src_buf->h) {
 		dev_dbg(dev, "Detected jpeg res=(%dx%d)->(%dx%d), pixfmt=%c%c%c%c\n",
 			q_data_cap->w, q_data_cap->h,
 			jpeg_src_buf->w, jpeg_src_buf->h,
@@ -976,9 +977,16 @@ static bool mxc_jpeg_source_change(struct mxc_jpeg_ctx *ctx,
 		mxc_jpeg_bytesperline(q_data_cap, jpeg_src_buf->fmt->precision);
 		mxc_jpeg_sizeimage(q_data_cap);
 		notify_src_chg(ctx);
-		src_chg = true;
+		ctx->source_change = 1;
 	}
-	return src_chg;
+	return ctx->source_change ? true : false;
+}
+
+static int mxc_jpeg_job_ready(void *priv)
+{
+	struct mxc_jpeg_ctx *ctx = priv;
+
+	return ctx->source_change ? 0 : 1;
 }
 
 static void mxc_jpeg_device_run(void *priv)
@@ -1028,6 +1036,13 @@ static void mxc_jpeg_device_run(void *priv)
 
 		return;
 	}
+	if (ctx->mxc_jpeg->mode == MXC_JPEG_DECODE) {
+		if (ctx->source_change || mxc_jpeg_source_change(ctx, jpeg_src_buf)) {
+			spin_unlock_irqrestore(&ctx->mxc_jpeg->hw_lock, flags);
+			v4l2_m2m_job_finish(jpeg->m2m_dev, ctx->fh.m2m_ctx);
+			return;
+		}
+	}
 
 	mxc_jpeg_enable(reg);
 	mxc_jpeg_set_l_endian(reg, 1);
@@ -1074,6 +1089,7 @@ static void mxc_jpeg_set_last_buffer_dequeued(struct mxc_jpeg_ctx *ctx)
 	q->last_buffer_dequeued = true;
 	wake_up(&q->done_wq);
 	ctx->stopped = 0;
+	ctx->header_parsed = false;
 }
 
 static int mxc_jpeg_decoder_cmd(struct file *file, void *priv,
@@ -1167,6 +1183,8 @@ static int mxc_jpeg_start_streaming(struct vb2_queue *q, unsigned int count)
 	struct mxc_jpeg_q_data *q_data = mxc_jpeg_get_q_data(ctx, q->type);
 	int ret;
 
+	if (ctx->mxc_jpeg->mode == MXC_JPEG_DECODE && V4L2_TYPE_IS_CAPTURE(q->type))
+		ctx->source_change = 0;
 	dev_dbg(ctx->mxc_jpeg->dev, "Start streaming ctx=%p", ctx);
 	q_data->sequence = 0;
 
@@ -1345,16 +1363,15 @@ static int mxc_jpeg_parse(struct mxc_jpeg_ctx *ctx, struct vb2_buffer *vb)
 		dev_warn(dev, "Invalid user resolution 0x0");
 		dev_warn(dev, "Keeping resolution from JPEG: %dx%d",
 			 header.frame.width, header.frame.height);
-		q_data_out->w = header.frame.width;
-		q_data_out->h = header.frame.height;
 	} else if (header.frame.width != q_data_out->w ||
 		   header.frame.height != q_data_out->h) {
 		dev_err(dev,
 			"Resolution mismatch: %dx%d (JPEG) versus %dx%d(user)",
 			header.frame.width, header.frame.height,
 			q_data_out->w, q_data_out->h);
-		return -EINVAL;
 	}
+	q_data_out->w = header.frame.width;
+	q_data_out->h = header.frame.height;
 	if (header.frame.width % 8 != 0 || header.frame.height % 8 != 0) {
 		dev_err(dev, "JPEG width or height not multiple of 8: %dx%d\n",
 			header.frame.width, header.frame.height);
@@ -1390,8 +1407,10 @@ static int mxc_jpeg_parse(struct mxc_jpeg_ctx *ctx, struct vb2_buffer *vb)
 	jpeg_src_buf->fmt = mxc_jpeg_find_format(ctx, fourcc);
 	jpeg_src_buf->w = header.frame.width;
 	jpeg_src_buf->h = header.frame.height;
+	ctx->header_parsed = true;
 
-	mxc_jpeg_source_change(ctx, jpeg_src_buf);
+	if (!v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx))
+		mxc_jpeg_source_change(ctx, jpeg_src_buf);
 
 	return 0;
 }
@@ -1468,6 +1487,7 @@ static void mxc_jpeg_buf_finish(struct vb2_buffer *vb)
 	if (list_empty(&q->done_list)) {
 		vbuf->flags |= V4L2_BUF_FLAG_LAST;
 		ctx->stopped = 0;
+		ctx->header_parsed = false;
 	}
 }
 
@@ -1613,26 +1633,42 @@ static int mxc_jpeg_enum_fmt_vid_cap(struct file *file, void *priv,
 				     struct v4l2_fmtdesc *f)
 {
 	struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(priv);
+	struct mxc_jpeg_q_data *q_data = mxc_jpeg_get_q_data(ctx, f->type);
 
-	if (ctx->mxc_jpeg->mode == MXC_JPEG_ENCODE)
+	if (ctx->mxc_jpeg->mode == MXC_JPEG_ENCODE) {
 		return enum_fmt(mxc_formats, MXC_JPEG_NUM_FORMATS, f,
 			MXC_JPEG_FMT_TYPE_ENC);
-	else
+	} else if (!ctx->header_parsed) {
 		return enum_fmt(mxc_formats, MXC_JPEG_NUM_FORMATS, f,
 			MXC_JPEG_FMT_TYPE_RAW);
+	} else {
+		/* For the decoder CAPTURE queue, only enumerate the raw formats
+		 * supported for the format currently active on OUTPUT
+		 * (more precisely what was propagated on capture queue
+		 * after jpeg parse on the output buffer)
+		 */
+		if (f->index)
+			return -EINVAL;
+		f->pixelformat = q_data->fmt->fourcc;
+		strscpy(f->description, q_data->fmt->name, sizeof(f->description));
+		return 0;
+	}
 }
 
 static int mxc_jpeg_enum_fmt_vid_out(struct file *file, void *priv,
 				     struct v4l2_fmtdesc *f)
 {
 	struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(priv);
+	u32 type = ctx->mxc_jpeg->mode == MXC_JPEG_DECODE ?  MXC_JPEG_FMT_TYPE_ENC :
+							     MXC_JPEG_FMT_TYPE_RAW;
+	int ret;
 
+	ret = enum_fmt(mxc_formats, MXC_JPEG_NUM_FORMATS, f, type);
+	if (ret)
+		return ret;
 	if (ctx->mxc_jpeg->mode == MXC_JPEG_DECODE)
-		return enum_fmt(mxc_formats, MXC_JPEG_NUM_FORMATS, f,
-				MXC_JPEG_FMT_TYPE_ENC);
-	else
-		return enum_fmt(mxc_formats, MXC_JPEG_NUM_FORMATS, f,
-				MXC_JPEG_FMT_TYPE_RAW);
+		f->flags = V4L2_FMT_FLAG_DYN_RESOLUTION;
+	return 0;
 }
 
 static int mxc_jpeg_try_fmt(struct v4l2_format *f, const struct mxc_jpeg_fmt *fmt,
@@ -2018,6 +2054,7 @@ static const struct v4l2_file_operations mxc_jpeg_fops = {
 };
 
 static const struct v4l2_m2m_ops mxc_jpeg_m2m_ops = {
+	.job_ready      = mxc_jpeg_job_ready,
 	.device_run	= mxc_jpeg_device_run,
 };
 
diff --git a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.h b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.h
index 82b38cc2dfab..9ae56e6e0fbe 100644
--- a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.h
+++ b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.h
@@ -94,6 +94,8 @@ struct mxc_jpeg_ctx {
 	unsigned int			stopping;
 	unsigned int			stopped;
 	unsigned int			slot;
+	unsigned int			source_change;
+	bool				header_parsed;
 };
 
 struct mxc_jpeg_slot_data {
-- 
2.33.0


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* Re: [PATCH v3 3/5] media: imx-jpeg: Propagate the output frame size to the capture side
  2022-03-23  9:05   ` Ming Qian
@ 2022-04-11 11:50     ` mirela.rabulea
  -1 siblings, 0 replies; 20+ messages in thread
From: mirela.rabulea @ 2022-04-11 11:50 UTC (permalink / raw)
  To: Ming Qian, mchehab, shawnguo, s.hauer
  Cc: hverkuil-cisco, kernel, festevam, linux-imx, linux-media,
	linux-kernel, devicetree, linux-arm-kernel

Hi Ming,

On 23.03.2022 11:05, Ming Qian wrote:
> The GStreamer v4l2videodec only ever calls S_FMT on the output side
> and then expects G_FMT on the capture side to return a valid format.
> 
> Signed-off-by: Ming Qian <ming.qian@nxp.com>
> ---
>   .../media/platform/nxp/imx-jpeg/mxc-jpeg.c    | 30 ++++++++++++++++++-
>   1 file changed, 29 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
> index a95305639dd9..5dfa6f87871e 100644
> --- a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
> +++ b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
> @@ -1831,12 +1831,40 @@ static int mxc_jpeg_s_fmt_vid_out(struct file *file, void *priv,
>   				  struct v4l2_format *f)
>   {
>   	int ret;
> +	struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(priv);
> +	struct vb2_queue *dst_vq;
> +	struct mxc_jpeg_q_data *q_data_cap;
> +	enum v4l2_buf_type cap_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
> +	struct v4l2_format fc;
>   
>   	ret = mxc_jpeg_try_fmt_vid_out(file, priv, f);
>   	if (ret)
>   		return ret;
>   
> -	return mxc_jpeg_s_fmt(mxc_jpeg_fh_to_ctx(priv), f);
> +	ret = mxc_jpeg_s_fmt(mxc_jpeg_fh_to_ctx(priv), f);
> +	if (ret)
> +		return ret;
> +
> +	if (ctx->mxc_jpeg->mode != MXC_JPEG_DECODE)
> +		return 0;
> +
> +	dst_vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, cap_type);
> +	if (!dst_vq)
> +		return -EINVAL;
> +
> +	if (vb2_is_busy(dst_vq))
> +		return 0;
> +
> +	q_data_cap = mxc_jpeg_get_q_data(ctx, cap_type);
> +	if (q_data_cap->w == f->fmt.pix_mp.width && q_data_cap->h == f->fmt.pix_mp.height)
> +		return 0;

Is this an optimization, to avoid propagating the format to the capture 
queue, if it is already set? If so, shouldn't fourcc also be part of the 
comparison?

Thanks,
Mirela

> +	memset(&fc, 0, sizeof(fc));
> +	fc.type = cap_type;
> +	fc.fmt.pix_mp.pixelformat = q_data_cap->fmt->fourcc;
> +	fc.fmt.pix_mp.width = f->fmt.pix_mp.width;
> +	fc.fmt.pix_mp.height = f->fmt.pix_mp.height;
> +
> +	return mxc_jpeg_s_fmt_vid_cap(file, priv, &fc);
>   }
>   
>   static int mxc_jpeg_g_fmt_vid(struct file *file, void *priv,

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v3 3/5] media: imx-jpeg: Propagate the output frame size to the capture side
@ 2022-04-11 11:50     ` mirela.rabulea
  0 siblings, 0 replies; 20+ messages in thread
From: mirela.rabulea @ 2022-04-11 11:50 UTC (permalink / raw)
  To: Ming Qian, mchehab, shawnguo, s.hauer
  Cc: hverkuil-cisco, kernel, festevam, linux-imx, linux-media,
	linux-kernel, devicetree, linux-arm-kernel

Hi Ming,

On 23.03.2022 11:05, Ming Qian wrote:
> The GStreamer v4l2videodec only ever calls S_FMT on the output side
> and then expects G_FMT on the capture side to return a valid format.
> 
> Signed-off-by: Ming Qian <ming.qian@nxp.com>
> ---
>   .../media/platform/nxp/imx-jpeg/mxc-jpeg.c    | 30 ++++++++++++++++++-
>   1 file changed, 29 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
> index a95305639dd9..5dfa6f87871e 100644
> --- a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
> +++ b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
> @@ -1831,12 +1831,40 @@ static int mxc_jpeg_s_fmt_vid_out(struct file *file, void *priv,
>   				  struct v4l2_format *f)
>   {
>   	int ret;
> +	struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(priv);
> +	struct vb2_queue *dst_vq;
> +	struct mxc_jpeg_q_data *q_data_cap;
> +	enum v4l2_buf_type cap_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
> +	struct v4l2_format fc;
>   
>   	ret = mxc_jpeg_try_fmt_vid_out(file, priv, f);
>   	if (ret)
>   		return ret;
>   
> -	return mxc_jpeg_s_fmt(mxc_jpeg_fh_to_ctx(priv), f);
> +	ret = mxc_jpeg_s_fmt(mxc_jpeg_fh_to_ctx(priv), f);
> +	if (ret)
> +		return ret;
> +
> +	if (ctx->mxc_jpeg->mode != MXC_JPEG_DECODE)
> +		return 0;
> +
> +	dst_vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, cap_type);
> +	if (!dst_vq)
> +		return -EINVAL;
> +
> +	if (vb2_is_busy(dst_vq))
> +		return 0;
> +
> +	q_data_cap = mxc_jpeg_get_q_data(ctx, cap_type);
> +	if (q_data_cap->w == f->fmt.pix_mp.width && q_data_cap->h == f->fmt.pix_mp.height)
> +		return 0;

Is this an optimization, to avoid propagating the format to the capture 
queue, if it is already set? If so, shouldn't fourcc also be part of the 
comparison?

Thanks,
Mirela

> +	memset(&fc, 0, sizeof(fc));
> +	fc.type = cap_type;
> +	fc.fmt.pix_mp.pixelformat = q_data_cap->fmt->fourcc;
> +	fc.fmt.pix_mp.width = f->fmt.pix_mp.width;
> +	fc.fmt.pix_mp.height = f->fmt.pix_mp.height;
> +
> +	return mxc_jpeg_s_fmt_vid_cap(file, priv, &fc);
>   }
>   
>   static int mxc_jpeg_g_fmt_vid(struct file *file, void *priv,

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 20+ messages in thread

* RE: [PATCH v3 3/5] media: imx-jpeg: Propagate the output frame size to the capture side
  2022-04-11 11:50     ` mirela.rabulea
@ 2022-04-12  2:11       ` Ming Qian
  -1 siblings, 0 replies; 20+ messages in thread
From: Ming Qian @ 2022-04-12  2:11 UTC (permalink / raw)
  To: Mirela Rabulea (OSS), mchehab, shawnguo, s.hauer
  Cc: hverkuil-cisco, kernel, festevam, dl-linux-imx, linux-media,
	linux-kernel, devicetree, linux-arm-kernel

> From: Mirela Rabulea (OSS)
> Sent: Monday, April 11, 2022 7:50 PM
> To: Ming Qian <ming.qian@nxp.com>; mchehab@kernel.org;
> shawnguo@kernel.org; s.hauer@pengutronix.de
> Cc: hverkuil-cisco@xs4all.nl; kernel@pengutronix.de; festevam@gmail.com;
> dl-linux-imx <linux-imx@nxp.com>; linux-media@vger.kernel.org;
> linux-kernel@vger.kernel.org; devicetree@vger.kernel.org;
> linux-arm-kernel@lists.infradead.org
> Subject: Re: [PATCH v3 3/5] media: imx-jpeg: Propagate the output frame size
> to the capture side
> 
> Hi Ming,
> 
> On 23.03.2022 11:05, Ming Qian wrote:
> > The GStreamer v4l2videodec only ever calls S_FMT on the output side
> > and then expects G_FMT on the capture side to return a valid format.
> >
> > Signed-off-by: Ming Qian <ming.qian@nxp.com>
> > ---
> >   .../media/platform/nxp/imx-jpeg/mxc-jpeg.c    | 30
> ++++++++++++++++++-
> >   1 file changed, 29 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
> > b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
> > index a95305639dd9..5dfa6f87871e 100644
> > --- a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
> > +++ b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
> > @@ -1831,12 +1831,40 @@ static int mxc_jpeg_s_fmt_vid_out(struct file
> *file, void *priv,
> >   				  struct v4l2_format *f)
> >   {
> >   	int ret;
> > +	struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(priv);
> > +	struct vb2_queue *dst_vq;
> > +	struct mxc_jpeg_q_data *q_data_cap;
> > +	enum v4l2_buf_type cap_type =
> V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
> > +	struct v4l2_format fc;
> >
> >   	ret = mxc_jpeg_try_fmt_vid_out(file, priv, f);
> >   	if (ret)
> >   		return ret;
> >
> > -	return mxc_jpeg_s_fmt(mxc_jpeg_fh_to_ctx(priv), f);
> > +	ret = mxc_jpeg_s_fmt(mxc_jpeg_fh_to_ctx(priv), f);
> > +	if (ret)
> > +		return ret;
> > +
> > +	if (ctx->mxc_jpeg->mode != MXC_JPEG_DECODE)
> > +		return 0;
> > +
> > +	dst_vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, cap_type);
> > +	if (!dst_vq)
> > +		return -EINVAL;
> > +
> > +	if (vb2_is_busy(dst_vq))
> > +		return 0;
> > +
> > +	q_data_cap = mxc_jpeg_get_q_data(ctx, cap_type);
> > +	if (q_data_cap->w == f->fmt.pix_mp.width && q_data_cap->h ==
> f->fmt.pix_mp.height)
> > +		return 0;
> 
> Is this an optimization, to avoid propagating the format to the capture queue,
> if it is already set? If so, shouldn't fourcc also be part of the comparison?
> 
> Thanks,
> Mirela
> 

Hi Mirela,
    Yes, if the capture size is equal to the output size, we don't need to set it again. For decoder, the format of output is jpeg, and the format for capture is uncompressed format, such as nv12, so the fourcc are always different.

> > +	memset(&fc, 0, sizeof(fc));
> > +	fc.type = cap_type;
> > +	fc.fmt.pix_mp.pixelformat = q_data_cap->fmt->fourcc;
> > +	fc.fmt.pix_mp.width = f->fmt.pix_mp.width;
> > +	fc.fmt.pix_mp.height = f->fmt.pix_mp.height;
> > +
> > +	return mxc_jpeg_s_fmt_vid_cap(file, priv, &fc);
> >   }
> >
> >   static int mxc_jpeg_g_fmt_vid(struct file *file, void *priv,

^ permalink raw reply	[flat|nested] 20+ messages in thread

* RE: [PATCH v3 3/5] media: imx-jpeg: Propagate the output frame size to the capture side
@ 2022-04-12  2:11       ` Ming Qian
  0 siblings, 0 replies; 20+ messages in thread
From: Ming Qian @ 2022-04-12  2:11 UTC (permalink / raw)
  To: Mirela Rabulea (OSS), mchehab, shawnguo, s.hauer
  Cc: hverkuil-cisco, kernel, festevam, dl-linux-imx, linux-media,
	linux-kernel, devicetree, linux-arm-kernel

> From: Mirela Rabulea (OSS)
> Sent: Monday, April 11, 2022 7:50 PM
> To: Ming Qian <ming.qian@nxp.com>; mchehab@kernel.org;
> shawnguo@kernel.org; s.hauer@pengutronix.de
> Cc: hverkuil-cisco@xs4all.nl; kernel@pengutronix.de; festevam@gmail.com;
> dl-linux-imx <linux-imx@nxp.com>; linux-media@vger.kernel.org;
> linux-kernel@vger.kernel.org; devicetree@vger.kernel.org;
> linux-arm-kernel@lists.infradead.org
> Subject: Re: [PATCH v3 3/5] media: imx-jpeg: Propagate the output frame size
> to the capture side
> 
> Hi Ming,
> 
> On 23.03.2022 11:05, Ming Qian wrote:
> > The GStreamer v4l2videodec only ever calls S_FMT on the output side
> > and then expects G_FMT on the capture side to return a valid format.
> >
> > Signed-off-by: Ming Qian <ming.qian@nxp.com>
> > ---
> >   .../media/platform/nxp/imx-jpeg/mxc-jpeg.c    | 30
> ++++++++++++++++++-
> >   1 file changed, 29 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
> > b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
> > index a95305639dd9..5dfa6f87871e 100644
> > --- a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
> > +++ b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
> > @@ -1831,12 +1831,40 @@ static int mxc_jpeg_s_fmt_vid_out(struct file
> *file, void *priv,
> >   				  struct v4l2_format *f)
> >   {
> >   	int ret;
> > +	struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(priv);
> > +	struct vb2_queue *dst_vq;
> > +	struct mxc_jpeg_q_data *q_data_cap;
> > +	enum v4l2_buf_type cap_type =
> V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
> > +	struct v4l2_format fc;
> >
> >   	ret = mxc_jpeg_try_fmt_vid_out(file, priv, f);
> >   	if (ret)
> >   		return ret;
> >
> > -	return mxc_jpeg_s_fmt(mxc_jpeg_fh_to_ctx(priv), f);
> > +	ret = mxc_jpeg_s_fmt(mxc_jpeg_fh_to_ctx(priv), f);
> > +	if (ret)
> > +		return ret;
> > +
> > +	if (ctx->mxc_jpeg->mode != MXC_JPEG_DECODE)
> > +		return 0;
> > +
> > +	dst_vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, cap_type);
> > +	if (!dst_vq)
> > +		return -EINVAL;
> > +
> > +	if (vb2_is_busy(dst_vq))
> > +		return 0;
> > +
> > +	q_data_cap = mxc_jpeg_get_q_data(ctx, cap_type);
> > +	if (q_data_cap->w == f->fmt.pix_mp.width && q_data_cap->h ==
> f->fmt.pix_mp.height)
> > +		return 0;
> 
> Is this an optimization, to avoid propagating the format to the capture queue,
> if it is already set? If so, shouldn't fourcc also be part of the comparison?
> 
> Thanks,
> Mirela
> 

Hi Mirela,
    Yes, if the capture size is equal to the output size, we don't need to set it again. For decoder, the format of output is jpeg, and the format for capture is uncompressed format, such as nv12, so the fourcc are always different.

> > +	memset(&fc, 0, sizeof(fc));
> > +	fc.type = cap_type;
> > +	fc.fmt.pix_mp.pixelformat = q_data_cap->fmt->fourcc;
> > +	fc.fmt.pix_mp.width = f->fmt.pix_mp.width;
> > +	fc.fmt.pix_mp.height = f->fmt.pix_mp.height;
> > +
> > +	return mxc_jpeg_s_fmt_vid_cap(file, priv, &fc);
> >   }
> >
> >   static int mxc_jpeg_g_fmt_vid(struct file *file, void *priv,
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v3 0/5] imx-jpeg: Support dynamic resolution change
  2022-03-23  9:05 ` Ming Qian
@ 2022-04-12  9:46   ` mirela.rabulea
  -1 siblings, 0 replies; 20+ messages in thread
From: mirela.rabulea @ 2022-04-12  9:46 UTC (permalink / raw)
  To: Ming Qian, mchehab, shawnguo, s.hauer
  Cc: hverkuil-cisco, kernel, festevam, linux-imx, linux-media,
	linux-kernel, devicetree, linux-arm-kernel

Hi,

On 23.03.2022 11:05, Ming Qian wrote:
> These patchset are to support dynamic resolution change.
> Avoid decoding error or even kernel panic.
> Otherwise, the Gstreamer v4l2videodec will fail to decode jpeg
> who is not decoded to yuyv.
> 
> Ming Qian (5):
>    media: imx-jpeg: Refactor function mxc_jpeg_parse
>    media: imx-jpeg: Identify and handle precision correctly
>    media: imx-jpeg: Propagate the output frame size to the capture side
>    media: imx-jpeg: Handle source change in a function
>    media: imx-jpeg: Support dynamic resolution change

For the entire patch set, v3:
Reviewed-by: Mirela Rabulea <mirela.rabulea@nxp.com>

> 
>   .../media/platform/nxp/imx-jpeg/mxc-jpeg.c    | 249 ++++++++++++------
>   .../media/platform/nxp/imx-jpeg/mxc-jpeg.h    |   3 +
>   2 files changed, 174 insertions(+), 78 deletions(-)
> 
> 
> base-commit: 71e6d0608e4d1b79069990c7dacb3600ced28a3b

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v3 0/5] imx-jpeg: Support dynamic resolution change
@ 2022-04-12  9:46   ` mirela.rabulea
  0 siblings, 0 replies; 20+ messages in thread
From: mirela.rabulea @ 2022-04-12  9:46 UTC (permalink / raw)
  To: Ming Qian, mchehab, shawnguo, s.hauer
  Cc: hverkuil-cisco, kernel, festevam, linux-imx, linux-media,
	linux-kernel, devicetree, linux-arm-kernel

Hi,

On 23.03.2022 11:05, Ming Qian wrote:
> These patchset are to support dynamic resolution change.
> Avoid decoding error or even kernel panic.
> Otherwise, the Gstreamer v4l2videodec will fail to decode jpeg
> who is not decoded to yuyv.
> 
> Ming Qian (5):
>    media: imx-jpeg: Refactor function mxc_jpeg_parse
>    media: imx-jpeg: Identify and handle precision correctly
>    media: imx-jpeg: Propagate the output frame size to the capture side
>    media: imx-jpeg: Handle source change in a function
>    media: imx-jpeg: Support dynamic resolution change

For the entire patch set, v3:
Reviewed-by: Mirela Rabulea <mirela.rabulea@nxp.com>

> 
>   .../media/platform/nxp/imx-jpeg/mxc-jpeg.c    | 249 ++++++++++++------
>   .../media/platform/nxp/imx-jpeg/mxc-jpeg.h    |   3 +
>   2 files changed, 174 insertions(+), 78 deletions(-)
> 
> 
> base-commit: 71e6d0608e4d1b79069990c7dacb3600ced28a3b

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v3 5/5] media: imx-jpeg: Support dynamic resolution change
  2022-03-23  9:05   ` Ming Qian
@ 2022-04-27  7:03     ` Hans Verkuil
  -1 siblings, 0 replies; 20+ messages in thread
From: Hans Verkuil @ 2022-04-27  7:03 UTC (permalink / raw)
  To: Ming Qian, mchehab, shawnguo, s.hauer, mirela.rabulea
  Cc: kernel, festevam, linux-imx, linux-media, linux-kernel,
	devicetree, linux-arm-kernel

On 23/03/2022 10:05, Ming Qian wrote:
> To support dynamic resolution change,
> driver should meet the following conditions:
> 1. the previous pictures are all decoded before source change event.
> 2. prevent decoding new resolution pictures with incorrect capture
>    buffer, until user handle source change event and setup capture.
> 3. report correct fmt and resolution during source change.
> 
> Signed-off-by: Ming Qian <ming.qian@nxp.com>
> ---
>  .../media/platform/nxp/imx-jpeg/mxc-jpeg.c    | 69 ++++++++++++++-----
>  .../media/platform/nxp/imx-jpeg/mxc-jpeg.h    |  2 +
>  2 files changed, 55 insertions(+), 16 deletions(-)
> 
> diff --git a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
> index 30289f2be3dd..0c3a1efbeae7 100644
> --- a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
> +++ b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
> @@ -933,13 +933,14 @@ static bool mxc_jpeg_source_change(struct mxc_jpeg_ctx *ctx,
>  {
>  	struct device *dev = ctx->mxc_jpeg->dev;
>  	struct mxc_jpeg_q_data *q_data_cap;
> -	bool src_chg = false;
>  
>  	if (!jpeg_src_buf->fmt)
> -		return src_chg;
> +		return false;
>  
>  	q_data_cap = mxc_jpeg_get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
> -	if (q_data_cap->w != jpeg_src_buf->w || q_data_cap->h != jpeg_src_buf->h) {
> +	if (q_data_cap->fmt != jpeg_src_buf->fmt ||
> +	    q_data_cap->w != jpeg_src_buf->w ||
> +	    q_data_cap->h != jpeg_src_buf->h) {
>  		dev_dbg(dev, "Detected jpeg res=(%dx%d)->(%dx%d), pixfmt=%c%c%c%c\n",
>  			q_data_cap->w, q_data_cap->h,
>  			jpeg_src_buf->w, jpeg_src_buf->h,
> @@ -976,9 +977,16 @@ static bool mxc_jpeg_source_change(struct mxc_jpeg_ctx *ctx,
>  		mxc_jpeg_bytesperline(q_data_cap, jpeg_src_buf->fmt->precision);
>  		mxc_jpeg_sizeimage(q_data_cap);
>  		notify_src_chg(ctx);
> -		src_chg = true;
> +		ctx->source_change = 1;
>  	}
> -	return src_chg;
> +	return ctx->source_change ? true : false;
> +}
> +
> +static int mxc_jpeg_job_ready(void *priv)
> +{
> +	struct mxc_jpeg_ctx *ctx = priv;
> +
> +	return ctx->source_change ? 0 : 1;
>  }
>  
>  static void mxc_jpeg_device_run(void *priv)
> @@ -1028,6 +1036,13 @@ static void mxc_jpeg_device_run(void *priv)
>  
>  		return;
>  	}
> +	if (ctx->mxc_jpeg->mode == MXC_JPEG_DECODE) {
> +		if (ctx->source_change || mxc_jpeg_source_change(ctx, jpeg_src_buf)) {
> +			spin_unlock_irqrestore(&ctx->mxc_jpeg->hw_lock, flags);
> +			v4l2_m2m_job_finish(jpeg->m2m_dev, ctx->fh.m2m_ctx);
> +			return;
> +		}
> +	}
>  
>  	mxc_jpeg_enable(reg);
>  	mxc_jpeg_set_l_endian(reg, 1);
> @@ -1074,6 +1089,7 @@ static void mxc_jpeg_set_last_buffer_dequeued(struct mxc_jpeg_ctx *ctx)
>  	q->last_buffer_dequeued = true;
>  	wake_up(&q->done_wq);
>  	ctx->stopped = 0;
> +	ctx->header_parsed = false;
>  }
>  
>  static int mxc_jpeg_decoder_cmd(struct file *file, void *priv,
> @@ -1167,6 +1183,8 @@ static int mxc_jpeg_start_streaming(struct vb2_queue *q, unsigned int count)
>  	struct mxc_jpeg_q_data *q_data = mxc_jpeg_get_q_data(ctx, q->type);
>  	int ret;
>  
> +	if (ctx->mxc_jpeg->mode == MXC_JPEG_DECODE && V4L2_TYPE_IS_CAPTURE(q->type))
> +		ctx->source_change = 0;
>  	dev_dbg(ctx->mxc_jpeg->dev, "Start streaming ctx=%p", ctx);
>  	q_data->sequence = 0;
>  
> @@ -1345,16 +1363,15 @@ static int mxc_jpeg_parse(struct mxc_jpeg_ctx *ctx, struct vb2_buffer *vb)
>  		dev_warn(dev, "Invalid user resolution 0x0");
>  		dev_warn(dev, "Keeping resolution from JPEG: %dx%d",
>  			 header.frame.width, header.frame.height);
> -		q_data_out->w = header.frame.width;
> -		q_data_out->h = header.frame.height;
>  	} else if (header.frame.width != q_data_out->w ||
>  		   header.frame.height != q_data_out->h) {
>  		dev_err(dev,
>  			"Resolution mismatch: %dx%d (JPEG) versus %dx%d(user)",
>  			header.frame.width, header.frame.height,
>  			q_data_out->w, q_data_out->h);
> -		return -EINVAL;
>  	}
> +	q_data_out->w = header.frame.width;
> +	q_data_out->h = header.frame.height;
>  	if (header.frame.width % 8 != 0 || header.frame.height % 8 != 0) {
>  		dev_err(dev, "JPEG width or height not multiple of 8: %dx%d\n",
>  			header.frame.width, header.frame.height);
> @@ -1390,8 +1407,10 @@ static int mxc_jpeg_parse(struct mxc_jpeg_ctx *ctx, struct vb2_buffer *vb)
>  	jpeg_src_buf->fmt = mxc_jpeg_find_format(ctx, fourcc);
>  	jpeg_src_buf->w = header.frame.width;
>  	jpeg_src_buf->h = header.frame.height;
> +	ctx->header_parsed = true;
>  
> -	mxc_jpeg_source_change(ctx, jpeg_src_buf);
> +	if (!v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx))
> +		mxc_jpeg_source_change(ctx, jpeg_src_buf);
>  
>  	return 0;
>  }
> @@ -1468,6 +1487,7 @@ static void mxc_jpeg_buf_finish(struct vb2_buffer *vb)
>  	if (list_empty(&q->done_list)) {
>  		vbuf->flags |= V4L2_BUF_FLAG_LAST;
>  		ctx->stopped = 0;
> +		ctx->header_parsed = false;
>  	}
>  }
>  
> @@ -1613,26 +1633,42 @@ static int mxc_jpeg_enum_fmt_vid_cap(struct file *file, void *priv,
>  				     struct v4l2_fmtdesc *f)
>  {
>  	struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(priv);
> +	struct mxc_jpeg_q_data *q_data = mxc_jpeg_get_q_data(ctx, f->type);
>  
> -	if (ctx->mxc_jpeg->mode == MXC_JPEG_ENCODE)
> +	if (ctx->mxc_jpeg->mode == MXC_JPEG_ENCODE) {
>  		return enum_fmt(mxc_formats, MXC_JPEG_NUM_FORMATS, f,
>  			MXC_JPEG_FMT_TYPE_ENC);
> -	else
> +	} else if (!ctx->header_parsed) {
>  		return enum_fmt(mxc_formats, MXC_JPEG_NUM_FORMATS, f,
>  			MXC_JPEG_FMT_TYPE_RAW);
> +	} else {
> +		/* For the decoder CAPTURE queue, only enumerate the raw formats
> +		 * supported for the format currently active on OUTPUT
> +		 * (more precisely what was propagated on capture queue
> +		 * after jpeg parse on the output buffer)
> +		 */
> +		if (f->index)
> +			return -EINVAL;
> +		f->pixelformat = q_data->fmt->fourcc;
> +		strscpy(f->description, q_data->fmt->name, sizeof(f->description));

Don't fill the description field in struct v4l2_fmtdesc. The core will fill
this for you, ensuring consistent format description names.

I've seen this in enum_fmt() and in mxc_jpeg_enum_fmt_vid_cap(), so both
functions should be adapted. This can be done in a new patch since it is
unrelated to the changes of this patch series.

Just something I noticed :-)

Regards,

	Hans

> +		return 0;
> +	}
>  }
>  
>  static int mxc_jpeg_enum_fmt_vid_out(struct file *file, void *priv,
>  				     struct v4l2_fmtdesc *f)
>  {
>  	struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(priv);
> +	u32 type = ctx->mxc_jpeg->mode == MXC_JPEG_DECODE ?  MXC_JPEG_FMT_TYPE_ENC :
> +							     MXC_JPEG_FMT_TYPE_RAW;
> +	int ret;
>  
> +	ret = enum_fmt(mxc_formats, MXC_JPEG_NUM_FORMATS, f, type);
> +	if (ret)
> +		return ret;
>  	if (ctx->mxc_jpeg->mode == MXC_JPEG_DECODE)
> -		return enum_fmt(mxc_formats, MXC_JPEG_NUM_FORMATS, f,
> -				MXC_JPEG_FMT_TYPE_ENC);
> -	else
> -		return enum_fmt(mxc_formats, MXC_JPEG_NUM_FORMATS, f,
> -				MXC_JPEG_FMT_TYPE_RAW);
> +		f->flags = V4L2_FMT_FLAG_DYN_RESOLUTION;
> +	return 0;
>  }
>  
>  static int mxc_jpeg_try_fmt(struct v4l2_format *f, const struct mxc_jpeg_fmt *fmt,
> @@ -2018,6 +2054,7 @@ static const struct v4l2_file_operations mxc_jpeg_fops = {
>  };
>  
>  static const struct v4l2_m2m_ops mxc_jpeg_m2m_ops = {
> +	.job_ready      = mxc_jpeg_job_ready,
>  	.device_run	= mxc_jpeg_device_run,
>  };
>  
> diff --git a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.h b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.h
> index 82b38cc2dfab..9ae56e6e0fbe 100644
> --- a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.h
> +++ b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.h
> @@ -94,6 +94,8 @@ struct mxc_jpeg_ctx {
>  	unsigned int			stopping;
>  	unsigned int			stopped;
>  	unsigned int			slot;
> +	unsigned int			source_change;
> +	bool				header_parsed;
>  };
>  
>  struct mxc_jpeg_slot_data {


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v3 5/5] media: imx-jpeg: Support dynamic resolution change
@ 2022-04-27  7:03     ` Hans Verkuil
  0 siblings, 0 replies; 20+ messages in thread
From: Hans Verkuil @ 2022-04-27  7:03 UTC (permalink / raw)
  To: Ming Qian, mchehab, shawnguo, s.hauer, mirela.rabulea
  Cc: kernel, festevam, linux-imx, linux-media, linux-kernel,
	devicetree, linux-arm-kernel

On 23/03/2022 10:05, Ming Qian wrote:
> To support dynamic resolution change,
> driver should meet the following conditions:
> 1. the previous pictures are all decoded before source change event.
> 2. prevent decoding new resolution pictures with incorrect capture
>    buffer, until user handle source change event and setup capture.
> 3. report correct fmt and resolution during source change.
> 
> Signed-off-by: Ming Qian <ming.qian@nxp.com>
> ---
>  .../media/platform/nxp/imx-jpeg/mxc-jpeg.c    | 69 ++++++++++++++-----
>  .../media/platform/nxp/imx-jpeg/mxc-jpeg.h    |  2 +
>  2 files changed, 55 insertions(+), 16 deletions(-)
> 
> diff --git a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
> index 30289f2be3dd..0c3a1efbeae7 100644
> --- a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
> +++ b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
> @@ -933,13 +933,14 @@ static bool mxc_jpeg_source_change(struct mxc_jpeg_ctx *ctx,
>  {
>  	struct device *dev = ctx->mxc_jpeg->dev;
>  	struct mxc_jpeg_q_data *q_data_cap;
> -	bool src_chg = false;
>  
>  	if (!jpeg_src_buf->fmt)
> -		return src_chg;
> +		return false;
>  
>  	q_data_cap = mxc_jpeg_get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
> -	if (q_data_cap->w != jpeg_src_buf->w || q_data_cap->h != jpeg_src_buf->h) {
> +	if (q_data_cap->fmt != jpeg_src_buf->fmt ||
> +	    q_data_cap->w != jpeg_src_buf->w ||
> +	    q_data_cap->h != jpeg_src_buf->h) {
>  		dev_dbg(dev, "Detected jpeg res=(%dx%d)->(%dx%d), pixfmt=%c%c%c%c\n",
>  			q_data_cap->w, q_data_cap->h,
>  			jpeg_src_buf->w, jpeg_src_buf->h,
> @@ -976,9 +977,16 @@ static bool mxc_jpeg_source_change(struct mxc_jpeg_ctx *ctx,
>  		mxc_jpeg_bytesperline(q_data_cap, jpeg_src_buf->fmt->precision);
>  		mxc_jpeg_sizeimage(q_data_cap);
>  		notify_src_chg(ctx);
> -		src_chg = true;
> +		ctx->source_change = 1;
>  	}
> -	return src_chg;
> +	return ctx->source_change ? true : false;
> +}
> +
> +static int mxc_jpeg_job_ready(void *priv)
> +{
> +	struct mxc_jpeg_ctx *ctx = priv;
> +
> +	return ctx->source_change ? 0 : 1;
>  }
>  
>  static void mxc_jpeg_device_run(void *priv)
> @@ -1028,6 +1036,13 @@ static void mxc_jpeg_device_run(void *priv)
>  
>  		return;
>  	}
> +	if (ctx->mxc_jpeg->mode == MXC_JPEG_DECODE) {
> +		if (ctx->source_change || mxc_jpeg_source_change(ctx, jpeg_src_buf)) {
> +			spin_unlock_irqrestore(&ctx->mxc_jpeg->hw_lock, flags);
> +			v4l2_m2m_job_finish(jpeg->m2m_dev, ctx->fh.m2m_ctx);
> +			return;
> +		}
> +	}
>  
>  	mxc_jpeg_enable(reg);
>  	mxc_jpeg_set_l_endian(reg, 1);
> @@ -1074,6 +1089,7 @@ static void mxc_jpeg_set_last_buffer_dequeued(struct mxc_jpeg_ctx *ctx)
>  	q->last_buffer_dequeued = true;
>  	wake_up(&q->done_wq);
>  	ctx->stopped = 0;
> +	ctx->header_parsed = false;
>  }
>  
>  static int mxc_jpeg_decoder_cmd(struct file *file, void *priv,
> @@ -1167,6 +1183,8 @@ static int mxc_jpeg_start_streaming(struct vb2_queue *q, unsigned int count)
>  	struct mxc_jpeg_q_data *q_data = mxc_jpeg_get_q_data(ctx, q->type);
>  	int ret;
>  
> +	if (ctx->mxc_jpeg->mode == MXC_JPEG_DECODE && V4L2_TYPE_IS_CAPTURE(q->type))
> +		ctx->source_change = 0;
>  	dev_dbg(ctx->mxc_jpeg->dev, "Start streaming ctx=%p", ctx);
>  	q_data->sequence = 0;
>  
> @@ -1345,16 +1363,15 @@ static int mxc_jpeg_parse(struct mxc_jpeg_ctx *ctx, struct vb2_buffer *vb)
>  		dev_warn(dev, "Invalid user resolution 0x0");
>  		dev_warn(dev, "Keeping resolution from JPEG: %dx%d",
>  			 header.frame.width, header.frame.height);
> -		q_data_out->w = header.frame.width;
> -		q_data_out->h = header.frame.height;
>  	} else if (header.frame.width != q_data_out->w ||
>  		   header.frame.height != q_data_out->h) {
>  		dev_err(dev,
>  			"Resolution mismatch: %dx%d (JPEG) versus %dx%d(user)",
>  			header.frame.width, header.frame.height,
>  			q_data_out->w, q_data_out->h);
> -		return -EINVAL;
>  	}
> +	q_data_out->w = header.frame.width;
> +	q_data_out->h = header.frame.height;
>  	if (header.frame.width % 8 != 0 || header.frame.height % 8 != 0) {
>  		dev_err(dev, "JPEG width or height not multiple of 8: %dx%d\n",
>  			header.frame.width, header.frame.height);
> @@ -1390,8 +1407,10 @@ static int mxc_jpeg_parse(struct mxc_jpeg_ctx *ctx, struct vb2_buffer *vb)
>  	jpeg_src_buf->fmt = mxc_jpeg_find_format(ctx, fourcc);
>  	jpeg_src_buf->w = header.frame.width;
>  	jpeg_src_buf->h = header.frame.height;
> +	ctx->header_parsed = true;
>  
> -	mxc_jpeg_source_change(ctx, jpeg_src_buf);
> +	if (!v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx))
> +		mxc_jpeg_source_change(ctx, jpeg_src_buf);
>  
>  	return 0;
>  }
> @@ -1468,6 +1487,7 @@ static void mxc_jpeg_buf_finish(struct vb2_buffer *vb)
>  	if (list_empty(&q->done_list)) {
>  		vbuf->flags |= V4L2_BUF_FLAG_LAST;
>  		ctx->stopped = 0;
> +		ctx->header_parsed = false;
>  	}
>  }
>  
> @@ -1613,26 +1633,42 @@ static int mxc_jpeg_enum_fmt_vid_cap(struct file *file, void *priv,
>  				     struct v4l2_fmtdesc *f)
>  {
>  	struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(priv);
> +	struct mxc_jpeg_q_data *q_data = mxc_jpeg_get_q_data(ctx, f->type);
>  
> -	if (ctx->mxc_jpeg->mode == MXC_JPEG_ENCODE)
> +	if (ctx->mxc_jpeg->mode == MXC_JPEG_ENCODE) {
>  		return enum_fmt(mxc_formats, MXC_JPEG_NUM_FORMATS, f,
>  			MXC_JPEG_FMT_TYPE_ENC);
> -	else
> +	} else if (!ctx->header_parsed) {
>  		return enum_fmt(mxc_formats, MXC_JPEG_NUM_FORMATS, f,
>  			MXC_JPEG_FMT_TYPE_RAW);
> +	} else {
> +		/* For the decoder CAPTURE queue, only enumerate the raw formats
> +		 * supported for the format currently active on OUTPUT
> +		 * (more precisely what was propagated on capture queue
> +		 * after jpeg parse on the output buffer)
> +		 */
> +		if (f->index)
> +			return -EINVAL;
> +		f->pixelformat = q_data->fmt->fourcc;
> +		strscpy(f->description, q_data->fmt->name, sizeof(f->description));

Don't fill the description field in struct v4l2_fmtdesc. The core will fill
this for you, ensuring consistent format description names.

I've seen this in enum_fmt() and in mxc_jpeg_enum_fmt_vid_cap(), so both
functions should be adapted. This can be done in a new patch since it is
unrelated to the changes of this patch series.

Just something I noticed :-)

Regards,

	Hans

> +		return 0;
> +	}
>  }
>  
>  static int mxc_jpeg_enum_fmt_vid_out(struct file *file, void *priv,
>  				     struct v4l2_fmtdesc *f)
>  {
>  	struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(priv);
> +	u32 type = ctx->mxc_jpeg->mode == MXC_JPEG_DECODE ?  MXC_JPEG_FMT_TYPE_ENC :
> +							     MXC_JPEG_FMT_TYPE_RAW;
> +	int ret;
>  
> +	ret = enum_fmt(mxc_formats, MXC_JPEG_NUM_FORMATS, f, type);
> +	if (ret)
> +		return ret;
>  	if (ctx->mxc_jpeg->mode == MXC_JPEG_DECODE)
> -		return enum_fmt(mxc_formats, MXC_JPEG_NUM_FORMATS, f,
> -				MXC_JPEG_FMT_TYPE_ENC);
> -	else
> -		return enum_fmt(mxc_formats, MXC_JPEG_NUM_FORMATS, f,
> -				MXC_JPEG_FMT_TYPE_RAW);
> +		f->flags = V4L2_FMT_FLAG_DYN_RESOLUTION;
> +	return 0;
>  }
>  
>  static int mxc_jpeg_try_fmt(struct v4l2_format *f, const struct mxc_jpeg_fmt *fmt,
> @@ -2018,6 +2054,7 @@ static const struct v4l2_file_operations mxc_jpeg_fops = {
>  };
>  
>  static const struct v4l2_m2m_ops mxc_jpeg_m2m_ops = {
> +	.job_ready      = mxc_jpeg_job_ready,
>  	.device_run	= mxc_jpeg_device_run,
>  };
>  
> diff --git a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.h b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.h
> index 82b38cc2dfab..9ae56e6e0fbe 100644
> --- a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.h
> +++ b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.h
> @@ -94,6 +94,8 @@ struct mxc_jpeg_ctx {
>  	unsigned int			stopping;
>  	unsigned int			stopped;
>  	unsigned int			slot;
> +	unsigned int			source_change;
> +	bool				header_parsed;
>  };
>  
>  struct mxc_jpeg_slot_data {


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 20+ messages in thread

end of thread, other threads:[~2022-04-27  7:04 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-03-23  9:05 [PATCH v3 0/5] imx-jpeg: Support dynamic resolution change Ming Qian
2022-03-23  9:05 ` Ming Qian
2022-03-23  9:05 ` [PATCH v3 1/5] media: imx-jpeg: Refactor function mxc_jpeg_parse Ming Qian
2022-03-23  9:05   ` Ming Qian
2022-03-23  9:05 ` [PATCH v3 2/5] media: imx-jpeg: Identify and handle precision correctly Ming Qian
2022-03-23  9:05   ` Ming Qian
2022-03-23  9:05 ` [PATCH v3 3/5] media: imx-jpeg: Propagate the output frame size to the capture side Ming Qian
2022-03-23  9:05   ` Ming Qian
2022-04-11 11:50   ` mirela.rabulea
2022-04-11 11:50     ` mirela.rabulea
2022-04-12  2:11     ` Ming Qian
2022-04-12  2:11       ` Ming Qian
2022-03-23  9:05 ` [PATCH v3 4/5] media: imx-jpeg: Handle source change in a function Ming Qian
2022-03-23  9:05   ` Ming Qian
2022-03-23  9:05 ` [PATCH v3 5/5] media: imx-jpeg: Support dynamic resolution change Ming Qian
2022-03-23  9:05   ` Ming Qian
2022-04-27  7:03   ` Hans Verkuil
2022-04-27  7:03     ` Hans Verkuil
2022-04-12  9:46 ` [PATCH v3 0/5] " mirela.rabulea
2022-04-12  9:46   ` mirela.rabulea

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.