media: imx-jpeg: initiate a drain of the capture queue in dynamic resolution change
authorMing Qian <ming.qian@nxp.com>
Tue, 22 Aug 2023 01:45:06 +0000 (09:45 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 20 Nov 2023 10:59:31 +0000 (11:59 +0100)
[ Upstream commit 1c2786632e20c8f0fd4004fae3b3490276e5e5da ]

The last buffer from before the change must be marked,
with the V4L2_BUF_FLAG_LAST flag,
similarly to the Drain sequence above.

Meanwhile if V4L2_DEC_CMD_STOP is sent before
the source change triggered,
we need to restore the is_draing flag after
the draining in dynamic resolution change.

Fixes: b4e1fb8643da ("media: imx-jpeg: Support dynamic resolution change")
Signed-off-by: Ming Qian <ming.qian@nxp.com>
Reviewed-by: Nicolas Dufresne <nicolas.dufresne@collabora.com>
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c

index b7a7201..e74b0ed 100644 (file)
@@ -1322,6 +1322,20 @@ static bool mxc_jpeg_compare_format(const struct mxc_jpeg_fmt *fmt1,
        return false;
 }
 
+static void mxc_jpeg_set_last_buffer(struct mxc_jpeg_ctx *ctx)
+{
+       struct vb2_v4l2_buffer *next_dst_buf;
+
+       next_dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
+       if (!next_dst_buf) {
+               ctx->fh.m2m_ctx->is_draining = true;
+               ctx->fh.m2m_ctx->next_buf_last = true;
+               return;
+       }
+
+       v4l2_m2m_last_buffer_done(ctx->fh.m2m_ctx, next_dst_buf);
+}
+
 static bool mxc_jpeg_source_change(struct mxc_jpeg_ctx *ctx,
                                   struct mxc_jpeg_src_buf *jpeg_src_buf)
 {
@@ -1378,6 +1392,8 @@ static bool mxc_jpeg_source_change(struct mxc_jpeg_ctx *ctx,
                mxc_jpeg_sizeimage(q_data_cap);
                notify_src_chg(ctx);
                ctx->source_change = 1;
+               if (vb2_is_streaming(v4l2_m2m_get_dst_vq(ctx->fh.m2m_ctx)))
+                       mxc_jpeg_set_last_buffer(ctx);
        }
 
        return ctx->source_change ? true : false;
@@ -1638,8 +1654,13 @@ static void mxc_jpeg_stop_streaming(struct vb2_queue *q)
                v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_ERROR);
        }
 
-       if (V4L2_TYPE_IS_OUTPUT(q->type) || !ctx->source_change)
-               v4l2_m2m_update_stop_streaming_state(ctx->fh.m2m_ctx, q);
+       v4l2_m2m_update_stop_streaming_state(ctx->fh.m2m_ctx, q);
+       /* if V4L2_DEC_CMD_STOP is sent before the source change triggered,
+        * restore the is_draining flag
+        */
+       if (V4L2_TYPE_IS_CAPTURE(q->type) && ctx->source_change && ctx->fh.m2m_ctx->last_src_buf)
+               ctx->fh.m2m_ctx->is_draining = true;
+
        if (V4L2_TYPE_IS_OUTPUT(q->type) &&
            v4l2_m2m_has_stopped(ctx->fh.m2m_ctx)) {
                notify_eos(ctx);
@@ -1916,7 +1937,7 @@ static int mxc_jpeg_buf_prepare(struct vb2_buffer *vb)
                return -EINVAL;
        for (i = 0; i < q_data->fmt->mem_planes; i++) {
                sizeimage = mxc_jpeg_get_plane_size(q_data, i);
-               if (vb2_plane_size(vb, i) < sizeimage) {
+               if (!ctx->source_change && vb2_plane_size(vb, i) < sizeimage) {
                        dev_err(dev, "plane %d too small (%lu < %lu)",
                                i, vb2_plane_size(vb, i), sizeimage);
                        return -EINVAL;