Linux Media Controller development
 help / color / mirror / Atom feed
* [RFC PATCH v2 0/4] media: iris: decoder fixes for resolution changes
@ 2026-10-28  3:43 ` Christian Cortner
  2026-10-28  3:43   ` [RFC PATCH v2 1/4] media: iris: Don't flag an empty source change LAST buffer as an error Christian Cortner
                     ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: Christian Cortner @ 2026-10-28  3:43 UTC (permalink / raw)
  To: Bryan O'Donoghue, Vikash Garodia, Dikshita Agarwal
  Cc: Abhinav Kumar, Birk Skyum, linux-media, linux-arm-msm

Four fixes for iris decoder problems at resolution changes, reworked
after Bryan's review of v1 [1]. There is no Signed-off-by from me,
since I'm not a kernel developer and can't vouch for the code; please
take over whatever is useful. An AI assistant wrote the code and the
logs (Assisted-by in each patch). I'm happy to test.

Tested on glymur (Zenbook A16, laptops tree 65f4ae73 with these four
and the iris patches listed in [2]): v4l2-compliance passes, and
GStreamer and a spec-following client decode bit-exact across
resolution changes. ffmpeg's h264_v4l2m2m still stops at the first
source change when it sets up CAPTURE early (problem 1 in [2]).
Build-tested on media-committers next with W=1, sparse and smatch.

Changes in v2:
- 1/4: shorter log, with the traced firmware flags (Bryan)
- 2/4: shorter log (Bryan)
- 3/4: one helper for the EOS check (Bryan)
- 4/4: comment states the 500 ms limit, no domain check, warn on
  timeout (Bryan)
- v1 5/5 dropped: too much for stable, and broken (Bryan)

[1] https://lore.kernel.org/linux-media/20261027021934.22113-1-ccortner@gmail.com/
[2] https://lore.kernel.org/linux-media/20261026160952.22082-1-ccortner@gmail.com/

Christian Cortner (4):
  media: iris: Don't flag an empty source change LAST buffer as an error
  media: iris: Update the CAPTURE stride and size on S_FMT(OUTPUT)
  media: iris: Signal V4L2_EVENT_EOS only at the end of a drain
  media: iris: Let a resolution change drain before stopping CAPTURE

 .../media/platform/qcom/iris/iris_buffer.c    | 26 +++++---
 .../media/platform/qcom/iris/iris_buffer.h    |  1 +
 .../qcom/iris/iris_hfi_gen2_response.c        |  7 ++-
 .../media/platform/qcom/iris/iris_instance.h  |  3 +
 drivers/media/platform/qcom/iris/iris_state.c |  8 ++-
 drivers/media/platform/qcom/iris/iris_vb2.c   | 26 ++++++--
 drivers/media/platform/qcom/iris/iris_vdec.c  | 61 ++++++++++---------
 drivers/media/platform/qcom/iris/iris_vidc.c  |  1 +
 8 files changed, 91 insertions(+), 42 deletions(-)


base-commit: d7e7bca7169873b46e857c025c10f3336c1258d8
-- 
2.56.0


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

* [RFC PATCH v2 1/4] media: iris: Don't flag an empty source change LAST buffer as an error
  2026-10-28  3:43 ` [RFC PATCH v2 0/4] media: iris: decoder fixes for resolution changes Christian Cortner
@ 2026-10-28  3:43   ` Christian Cortner
  2026-10-28  3:43   ` [RFC PATCH v2 2/4] media: iris: Update the CAPTURE stride and size on S_FMT(OUTPUT) Christian Cortner
                     ` (3 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Christian Cortner @ 2026-10-28  3:43 UTC (permalink / raw)
  To: Bryan O'Donoghue, Vikash Garodia, Dikshita Agarwal
  Cc: Abhinav Kumar, Birk Skyum, linux-media, linux-arm-msm

The firmware ends both a drain and a source change with an empty
capture buffer. Traced on glymur, it flags the first
HFI_BUF_FW_FLAG_LAST (0x10000000) and the second
HFI_BUF_FW_FLAG_PSC_LAST (0x20000000). Only LAST is exempt from the
empty buffer check, so the client gets the source change buffer as
LAST|ERROR, and ffmpeg's h264_v4l2m2m reports a decode error.

Exempt HFI_BUF_FW_FLAG_PSC_LAST as well.

Fixes: 7adc11e6abf6 ("media: iris: Send V4L2_BUF_FLAG_ERROR for capture buffers with 0 filled length")
Cc: stable@vger.kernel.org
Assisted-by: LLM sparse smatch
---
 drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c b/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c
index f0782c4b1e6e..b4fe9066fcb8 100644
--- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c
+++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c
@@ -390,8 +390,13 @@ static int iris_hfi_gen2_handle_output_buffer(struct iris_inst *inst,
 
 	buf->flags = iris_hfi_gen2_get_driver_buffer_flags(inst, hfi_buffer->flags);
 
+	/*
+	 * The empty buffer that ends a drain (LAST) or a source change
+	 * (PSC_LAST) is not an error, the client just ignores it.
+	 */
 	if (!buf->data_size && inst->state == IRIS_INST_STREAMING &&
-	    !(hfi_buffer->flags & HFI_BUF_FW_FLAG_LAST)) {
+	    !(hfi_buffer->flags &
+	      (HFI_BUF_FW_FLAG_LAST | HFI_BUF_FW_FLAG_PSC_LAST))) {
 		buf->flags |= V4L2_BUF_FLAG_ERROR;
 	}
 
-- 
2.56.0


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

* [RFC PATCH v2 2/4] media: iris: Update the CAPTURE stride and size on S_FMT(OUTPUT)
  2026-10-28  3:43 ` [RFC PATCH v2 0/4] media: iris: decoder fixes for resolution changes Christian Cortner
  2026-10-28  3:43   ` [RFC PATCH v2 1/4] media: iris: Don't flag an empty source change LAST buffer as an error Christian Cortner
@ 2026-10-28  3:43   ` Christian Cortner
  2026-10-28  3:43   ` [RFC PATCH v2 3/4] media: iris: Signal V4L2_EVENT_EOS only at the end of a drain Christian Cortner
                     ` (2 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Christian Cortner @ 2026-10-28  3:43 UTC (permalink / raw)
  To: Bryan O'Donoghue, Vikash Garodia, Dikshita Agarwal
  Cc: Abhinav Kumar, Birk Skyum, linux-media, linux-arm-msm

S_FMT(OUTPUT) updates the CAPTURE width and height but not
bytesperline and sizeimage, which keep the values of the previous
format. With a 640x360 stream, REQBUFS(CAPTURE) then allocates buffers
that iris_vb2_buf_prepare() rejects with -EINVAL.

Move the CAPTURE format rules of S_FMT(CAPTURE) into a helper and use
it for S_FMT(OUTPUT) as well.

Fixes: 8aadfd445373 ("media: iris: Update CAPTURE format info based on OUTPUT format")
Cc: stable@vger.kernel.org
Assisted-by: LLM sparse smatch
---
 drivers/media/platform/qcom/iris/iris_vdec.c | 61 +++++++++++---------
 1 file changed, 33 insertions(+), 28 deletions(-)

diff --git a/drivers/media/platform/qcom/iris/iris_vdec.c b/drivers/media/platform/qcom/iris/iris_vdec.c
index 0dd33ff447bb..472e8e50830d 100644
--- a/drivers/media/platform/qcom/iris/iris_vdec.c
+++ b/drivers/media/platform/qcom/iris/iris_vdec.c
@@ -212,6 +212,35 @@ int iris_vdec_try_fmt(struct iris_inst *inst, struct v4l2_format *f)
 	return 0;
 }
 
+static void iris_vdec_set_capture_size(struct iris_inst *inst, u32 width,
+				       u32 height)
+{
+	struct v4l2_pix_format_mplane *pix_mp = &inst->fmt_dst->fmt.pix_mp;
+	struct iris_buffers *bufs = &inst->buffers[BUF_OUTPUT];
+
+	switch (pix_mp->pixelformat) {
+	case V4L2_PIX_FMT_P010:
+		pix_mp->width = ALIGN(width, 128);
+		pix_mp->height = ALIGN(height, 32);
+		pix_mp->plane_fmt[0].bytesperline = ALIGN(width * 2, 256);
+		break;
+	case V4L2_PIX_FMT_QC10C:
+		pix_mp->width = roundup(width, 192);
+		pix_mp->height = ALIGN(height, 16);
+		pix_mp->plane_fmt[0].bytesperline = ALIGN(width * 4 / 3, 256);
+		break;
+	case V4L2_PIX_FMT_NV12:
+	case V4L2_PIX_FMT_QC08C:
+		pix_mp->width = ALIGN(width, 128);
+		pix_mp->height = ALIGN(height, 32);
+		pix_mp->plane_fmt[0].bytesperline = ALIGN(width, 128);
+		break;
+	}
+	pix_mp->plane_fmt[0].sizeimage = iris_get_buffer_size(inst, BUF_OUTPUT);
+	bufs->min_count = iris_vpu_buf_count(inst, BUF_OUTPUT);
+	bufs->size = pix_mp->plane_fmt[0].sizeimage;
+}
+
 int iris_vdec_s_fmt(struct iris_inst *inst, struct v4l2_format *f)
 {
 	struct v4l2_format *fmt, *output_fmt;
@@ -263,10 +292,8 @@ int iris_vdec_s_fmt(struct iris_inst *inst, struct v4l2_format *f)
 		output_fmt->fmt.pix_mp.quantization = f->fmt.pix_mp.quantization;
 
 		/* Update capture format based on new ip w/h */
-		output_fmt->fmt.pix_mp.width = ALIGN(f->fmt.pix_mp.width, 128);
-		output_fmt->fmt.pix_mp.height = ALIGN(f->fmt.pix_mp.height, 32);
-		inst->buffers[BUF_OUTPUT].min_count = iris_vpu_buf_count(inst, BUF_OUTPUT);
-		inst->buffers[BUF_OUTPUT].size = iris_get_buffer_size(inst, BUF_OUTPUT);
+		iris_vdec_set_capture_size(inst, f->fmt.pix_mp.width,
+					   f->fmt.pix_mp.height);
 
 		inst->crop.left = 0;
 		inst->crop.top = 0;
@@ -281,30 +308,8 @@ int iris_vdec_s_fmt(struct iris_inst *inst, struct v4l2_format *f)
 		fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
 		fmt->fmt.pix_mp.pixelformat = f->fmt.pix_mp.pixelformat;
 		fmt->fmt.pix_mp.num_planes = 1;
-		switch (f->fmt.pix_mp.pixelformat) {
-		case V4L2_PIX_FMT_P010:
-			fmt->fmt.pix_mp.width = ALIGN(f->fmt.pix_mp.width, 128);
-			fmt->fmt.pix_mp.height = ALIGN(f->fmt.pix_mp.height, 32);
-			fmt->fmt.pix_mp.plane_fmt[0].bytesperline =
-				ALIGN(f->fmt.pix_mp.width * 2, 256);
-			break;
-		case V4L2_PIX_FMT_QC10C:
-			fmt->fmt.pix_mp.width = roundup(f->fmt.pix_mp.width, 192);
-			fmt->fmt.pix_mp.height = ALIGN(f->fmt.pix_mp.height, 16);
-			fmt->fmt.pix_mp.plane_fmt[0].bytesperline =
-				ALIGN(f->fmt.pix_mp.width * 4 / 3, 256);
-			break;
-		case V4L2_PIX_FMT_NV12:
-		case V4L2_PIX_FMT_QC08C:
-			fmt->fmt.pix_mp.width = ALIGN(f->fmt.pix_mp.width, 128);
-			fmt->fmt.pix_mp.height = ALIGN(f->fmt.pix_mp.height, 32);
-			fmt->fmt.pix_mp.plane_fmt[0].bytesperline =
-				ALIGN(f->fmt.pix_mp.width, 128);
-			break;
-		}
-		fmt->fmt.pix_mp.plane_fmt[0].sizeimage = iris_get_buffer_size(inst, BUF_OUTPUT);
-		inst->buffers[BUF_OUTPUT].min_count = iris_vpu_buf_count(inst, BUF_OUTPUT);
-		inst->buffers[BUF_OUTPUT].size = fmt->fmt.pix_mp.plane_fmt[0].sizeimage;
+		iris_vdec_set_capture_size(inst, f->fmt.pix_mp.width,
+					   f->fmt.pix_mp.height);
 
 		inst->crop.top = 0;
 		inst->crop.left = 0;
-- 
2.56.0


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

* [RFC PATCH v2 3/4] media: iris: Signal V4L2_EVENT_EOS only at the end of a drain
  2026-10-28  3:43 ` [RFC PATCH v2 0/4] media: iris: decoder fixes for resolution changes Christian Cortner
  2026-10-28  3:43   ` [RFC PATCH v2 1/4] media: iris: Don't flag an empty source change LAST buffer as an error Christian Cortner
  2026-10-28  3:43   ` [RFC PATCH v2 2/4] media: iris: Update the CAPTURE stride and size on S_FMT(OUTPUT) Christian Cortner
@ 2026-10-28  3:43   ` Christian Cortner
  2026-10-28  3:43   ` [RFC PATCH v2 4/4] media: iris: Let a resolution change drain before stopping CAPTURE Christian Cortner
  2026-10-28 10:00   ` [RFC PATCH v2 0/4] media: iris: decoder fixes for resolution changes Bryan O'Donoghue
  4 siblings, 0 replies; 6+ messages in thread
From: Christian Cortner @ 2026-10-28  3:43 UTC (permalink / raw)
  To: Bryan O'Donoghue, Vikash Garodia, Dikshita Agarwal
  Cc: Abhinav Kumar, Birk Skyum, linux-media, linux-arm-msm

V4L2_EVENT_EOS is queued, and the m2m context marked stopped, for every
LAST capture buffer, including the one that ends a source change. With
a stream that changes resolution, a client gets EOS at the change and
none at the end, and ffmpeg's h264_v4l2m2m stops decoding there.

Do both only when IRIS_INST_SUB_DRAIN_LAST is set, which both HFI
generations do before they return the LAST buffer of a drain. Use one
helper for iris_vb2_buffer_done() and iris_vb2_buf_queue().

Fixes: 84e17adae3e3 ("media: iris: add support for dynamic resolution change")
Cc: stable@vger.kernel.org
Assisted-by: LLM sparse smatch
---
 .../media/platform/qcom/iris/iris_buffer.c    | 26 ++++++++++++++-----
 .../media/platform/qcom/iris/iris_buffer.h    |  1 +
 drivers/media/platform/qcom/iris/iris_vb2.c   |  6 +----
 3 files changed, 21 insertions(+), 12 deletions(-)

diff --git a/drivers/media/platform/qcom/iris/iris_buffer.c b/drivers/media/platform/qcom/iris/iris_buffer.c
index eb8de60c1177..178e50eadcf7 100644
--- a/drivers/media/platform/qcom/iris/iris_buffer.c
+++ b/drivers/media/platform/qcom/iris/iris_buffer.c
@@ -870,9 +870,26 @@ static void iris_get_ts_metadata(struct iris_inst *inst, u64 timestamp_ns,
 	vbuf->timecode = inst->tss[inst->metadata_idx].tc;
 }
 
-int iris_vb2_buffer_done(struct iris_inst *inst, struct iris_buffer *buf)
+/*
+ * Queue V4L2_EVENT_EOS and mark the m2m context stopped, once, when a LAST
+ * capture buffer ends a drain. The LAST buffer of a source change does not
+ * end the stream.
+ */
+void iris_vb2_signal_eos(struct iris_inst *inst)
 {
+	static const struct v4l2_event eos = { .type = V4L2_EVENT_EOS };
 	struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx;
+
+	if (!(inst->sub_state & IRIS_INST_SUB_DRAIN_LAST) ||
+	    v4l2_m2m_has_stopped(m2m_ctx))
+		return;
+
+	v4l2_event_queue_fh(&inst->fh, &eos);
+	v4l2_m2m_mark_stopped(m2m_ctx);
+}
+
+int iris_vb2_buffer_done(struct iris_inst *inst, struct iris_buffer *buf)
+{
 	struct vb2_v4l2_buffer *vbuf;
 	struct vb2_buffer *vb2;
 	u32 type, state;
@@ -913,12 +930,7 @@ int iris_vb2_buffer_done(struct iris_inst *inst, struct iris_buffer *buf)
 	}
 
 	if (vbuf->flags & V4L2_BUF_FLAG_LAST) {
-		if (!v4l2_m2m_has_stopped(m2m_ctx)) {
-			const struct v4l2_event ev = { .type = V4L2_EVENT_EOS };
-
-			v4l2_event_queue_fh(&inst->fh, &ev);
-			v4l2_m2m_mark_stopped(m2m_ctx);
-		}
+		iris_vb2_signal_eos(inst);
 		inst->last_buffer_dequeued = true;
 	}
 
diff --git a/drivers/media/platform/qcom/iris/iris_buffer.h b/drivers/media/platform/qcom/iris/iris_buffer.h
index ab8e5d953101..a8d2002e00ee 100644
--- a/drivers/media/platform/qcom/iris/iris_buffer.h
+++ b/drivers/media/platform/qcom/iris/iris_buffer.h
@@ -120,6 +120,7 @@ int iris_alloc_and_queue_input_int_bufs(struct iris_inst *inst);
 int iris_queue_buffer(struct iris_inst *inst, struct iris_buffer *buf);
 int iris_queue_deferred_buffers(struct iris_inst *inst, enum iris_buffer_type buf_type);
 int iris_vb2_buffer_done(struct iris_inst *inst, struct iris_buffer *buf);
+void iris_vb2_signal_eos(struct iris_inst *inst);
 void iris_vb2_queue_error(struct iris_inst *inst);
 
 #endif
diff --git a/drivers/media/platform/qcom/iris/iris_vb2.c b/drivers/media/platform/qcom/iris/iris_vb2.c
index 8faf709c26c1..bb713da20605 100644
--- a/drivers/media/platform/qcom/iris/iris_vb2.c
+++ b/drivers/media/platform/qcom/iris/iris_vb2.c
@@ -290,7 +290,6 @@ int iris_vb2_buf_out_validate(struct vb2_buffer *vb)
 
 void iris_vb2_buf_queue(struct vb2_buffer *vb2)
 {
-	static const struct v4l2_event eos = { .type = V4L2_EVENT_EOS };
 	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb2);
 	struct v4l2_m2m_ctx *m2m_ctx;
 	struct iris_inst *inst;
@@ -324,10 +323,7 @@ void iris_vb2_buf_queue(struct vb2_buffer *vb2)
 			vbuf->field = V4L2_FIELD_NONE;
 			vb2_set_plane_payload(vb2, 0, 0);
 			v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_DONE);
-			if (!v4l2_m2m_has_stopped(m2m_ctx)) {
-				v4l2_event_queue_fh(&inst->fh, &eos);
-				v4l2_m2m_mark_stopped(m2m_ctx);
-			}
+			iris_vb2_signal_eos(inst);
 			inst->last_buffer_dequeued = true;
 			goto exit;
 		}
-- 
2.56.0


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

* [RFC PATCH v2 4/4] media: iris: Let a resolution change drain before stopping CAPTURE
  2026-10-28  3:43 ` [RFC PATCH v2 0/4] media: iris: decoder fixes for resolution changes Christian Cortner
                     ` (2 preceding siblings ...)
  2026-10-28  3:43   ` [RFC PATCH v2 3/4] media: iris: Signal V4L2_EVENT_EOS only at the end of a drain Christian Cortner
@ 2026-10-28  3:43   ` Christian Cortner
  2026-10-28 10:00   ` [RFC PATCH v2 0/4] media: iris: decoder fixes for resolution changes Bryan O'Donoghue
  4 siblings, 0 replies; 6+ messages in thread
From: Christian Cortner @ 2026-10-28  3:43 UTC (permalink / raw)
  To: Bryan O'Donoghue, Vikash Garodia, Dikshita Agarwal
  Cc: Abhinav Kumar, Birk Skyum, linux-media, linux-arm-msm

ffmpeg's h264_v4l2m2m stops CAPTURE about 10 us after it dequeues a
source change event. If the stop reaches the firmware before the
PSC_LAST buffer, that buffer still arrives (1.3 ms later in a trace),
iris_inst_sub_state_change_drc_last() rejects it, and the instance
goes to IRIS_INST_ERROR: no more buffers come back.

Wait up to 500 ms in iris_vb2_stop_streaming() for a pending source
change to drain, and warn when it does not.

Fixes: 84e17adae3e3 ("media: iris: add support for dynamic resolution change")
Assisted-by: LLM sparse smatch
---
 .../media/platform/qcom/iris/iris_instance.h  |  3 +++
 drivers/media/platform/qcom/iris/iris_state.c |  8 +++++++-
 drivers/media/platform/qcom/iris/iris_vb2.c   | 20 +++++++++++++++++++
 drivers/media/platform/qcom/iris/iris_vidc.c  |  1 +
 4 files changed, 31 insertions(+), 1 deletion(-)

diff --git a/drivers/media/platform/qcom/iris/iris_instance.h b/drivers/media/platform/qcom/iris/iris_instance.h
index 771269e705d9..1013ed2911a1 100644
--- a/drivers/media/platform/qcom/iris/iris_instance.h
+++ b/drivers/media/platform/qcom/iris/iris_instance.h
@@ -7,6 +7,7 @@
 #define __IRIS_INSTANCE_H__
 
 #include <linux/kref.h>
+#include <linux/wait.h>
 
 #include <media/v4l2-ctrls.h>
 
@@ -56,6 +57,7 @@ struct iris_hfi_session_ops;
  * @metadata_idx: index for metadata buffer
  * @codec: codec type
  * @last_buffer_dequeued: a flag to indicate that last buffer is sent by driver
+ * @drc_wq: woken when IRIS_INST_SUB_DRC_LAST is set
  * @last_buf_ns: start time of received input buffer for current one second FPS window
  * @frame_counter: input buffer counter for current one second FPS window
  * @frame_rate: frame rate of current instance
@@ -104,6 +106,7 @@ struct iris_inst {
 	u32				metadata_idx;
 	u32				codec;
 	bool				last_buffer_dequeued;
+	wait_queue_head_t		drc_wq;
 	u64				last_buf_ns;
 	u32				frame_counter;
 	u32				frame_rate;
diff --git a/drivers/media/platform/qcom/iris/iris_state.c b/drivers/media/platform/qcom/iris/iris_state.c
index 5552725c614e..dd8e0093b972 100644
--- a/drivers/media/platform/qcom/iris/iris_state.c
+++ b/drivers/media/platform/qcom/iris/iris_state.c
@@ -209,6 +209,7 @@ int iris_inst_sub_state_change_drain_last(struct iris_inst *inst)
 int iris_inst_sub_state_change_drc_last(struct iris_inst *inst)
 {
 	enum iris_inst_sub_state set_sub_state;
+	int ret;
 
 	if (inst->sub_state & IRIS_INST_SUB_DRC_LAST)
 		return -EINVAL;
@@ -222,7 +223,12 @@ int iris_inst_sub_state_change_drc_last(struct iris_inst *inst)
 
 	set_sub_state = IRIS_INST_SUB_DRC_LAST | IRIS_INST_SUB_OUTPUT_PAUSE;
 
-	return iris_inst_change_sub_state(inst, 0, set_sub_state);
+	ret = iris_inst_change_sub_state(inst, 0, set_sub_state);
+	/* a CAPTURE STREAMOFF may be waiting, see iris_vb2_stop_streaming() */
+	if (!ret)
+		wake_up_all(&inst->drc_wq);
+
+	return ret;
 }
 
 int iris_inst_sub_state_change_pause(struct iris_inst *inst, u32 plane)
diff --git a/drivers/media/platform/qcom/iris/iris_vb2.c b/drivers/media/platform/qcom/iris/iris_vb2.c
index bb713da20605..2460778c408d 100644
--- a/drivers/media/platform/qcom/iris/iris_vb2.c
+++ b/drivers/media/platform/qcom/iris/iris_vb2.c
@@ -228,6 +228,15 @@ int iris_vb2_start_streaming(struct vb2_queue *q, unsigned int count)
 	return ret;
 }
 
+/* a source change whose drain the firmware has not completed yet */
+static bool iris_drc_draining(struct iris_inst *inst)
+{
+	enum iris_inst_sub_state sub_state = READ_ONCE(inst->sub_state);
+
+	return sub_state & IRIS_INST_SUB_DRC &&
+	       !(sub_state & IRIS_INST_SUB_DRC_LAST);
+}
+
 void iris_vb2_stop_streaming(struct vb2_queue *q)
 {
 	struct iris_inst *inst;
@@ -238,6 +247,17 @@ void iris_vb2_stop_streaming(struct vb2_queue *q)
 	if (V4L2_TYPE_IS_CAPTURE(q->type) && inst->state == IRIS_INST_INIT)
 		return;
 
+	/*
+	 * Stopping CAPTURE before the firmware has drained a pending
+	 * resolution change leaves the change incomplete, and decoding stalls
+	 * after the next STREAMON. Wait up to 500 ms for the drain.
+	 */
+	if (V4L2_TYPE_IS_CAPTURE(q->type) &&
+	    !wait_event_timeout(inst->drc_wq, !iris_drc_draining(inst),
+				msecs_to_jiffies(500)))
+		dev_warn(inst->core->dev,
+			 "resolution change drain timed out, stopping CAPTURE\n");
+
 	mutex_lock(&inst->lock);
 
 	if (!V4L2_TYPE_IS_OUTPUT(q->type) &&
diff --git a/drivers/media/platform/qcom/iris/iris_vidc.c b/drivers/media/platform/qcom/iris/iris_vidc.c
index 05aab6e3005d..0df0a5915e16 100644
--- a/drivers/media/platform/qcom/iris/iris_vidc.c
+++ b/drivers/media/platform/qcom/iris/iris_vidc.c
@@ -201,6 +201,7 @@ int iris_open(struct file *filp)
 	INIT_LIST_HEAD(&inst->buffers[BUF_PARTIAL].list);
 	init_completion(&inst->completion);
 	init_completion(&inst->flush_completion);
+	init_waitqueue_head(&inst->drc_wq);
 
 	iris_v4l2_fh_init(inst, filp);
 
-- 
2.56.0


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

* Re: [RFC PATCH v2 0/4] media: iris: decoder fixes for resolution changes
  2026-10-28  3:43 ` [RFC PATCH v2 0/4] media: iris: decoder fixes for resolution changes Christian Cortner
                     ` (3 preceding siblings ...)
  2026-10-28  3:43   ` [RFC PATCH v2 4/4] media: iris: Let a resolution change drain before stopping CAPTURE Christian Cortner
@ 2026-10-28 10:00   ` Bryan O'Donoghue
  4 siblings, 0 replies; 6+ messages in thread
From: Bryan O'Donoghue @ 2026-10-28 10:00 UTC (permalink / raw)
  To: Christian Cortner, Vikash Garodia, Dikshita Agarwal
  Cc: Abhinav Kumar, Birk Skyum, linux-media, linux-arm-msm

On 28/10/2026 03:43, Christian Cortner wrote:
> Four fixes for iris decoder problems at resolution changes, reworked
> after Bryan's review of v1 [1]. There is no Signed-off-by from me,
> since I'm not a kernel developer and can't vouch for the code; please
> take over whatever is useful. An AI assistant wrote the code and the
> logs (Assisted-by in each patch). I'm happy to test.
> 
> Tested on glymur (Zenbook A16, laptops tree 65f4ae73 with these four
> and the iris patches listed in [2]): v4l2-compliance passes, and
> GStreamer and a spec-following client decode bit-exact across
> resolution changes. ffmpeg's h264_v4l2m2m still stops at the first
> source change when it sets up CAPTURE early (problem 1 in [2]).
> Build-tested on media-committers next with W=1, sparse and smatch.
> 
> Changes in v2:
> - 1/4: shorter log, with the traced firmware flags (Bryan)
> - 2/4: shorter log (Bryan)
> - 3/4: one helper for the EOS check (Bryan)
> - 4/4: comment states the 500 ms limit, no domain check, warn on
>    timeout (Bryan)
> - v1 5/5 dropped: too much for stable, and broken (Bryan)
> 
> [1] https://lore.kernel.org/linux-media/20261027021934.22113-1-ccortner@gmail.com/
> [2] https://lore.kernel.org/linux-media/20261026160952.22082-1-ccortner@gmail.com/
> 
> Christian Cortner (4):
>    media: iris: Don't flag an empty source change LAST buffer as an error
>    media: iris: Update the CAPTURE stride and size on S_FMT(OUTPUT)
>    media: iris: Signal V4L2_EVENT_EOS only at the end of a drain
>    media: iris: Let a resolution change drain before stopping CAPTURE
> 
>   .../media/platform/qcom/iris/iris_buffer.c    | 26 +++++---
>   .../media/platform/qcom/iris/iris_buffer.h    |  1 +
>   .../qcom/iris/iris_hfi_gen2_response.c        |  7 ++-
>   .../media/platform/qcom/iris/iris_instance.h  |  3 +
>   drivers/media/platform/qcom/iris/iris_state.c |  8 ++-
>   drivers/media/platform/qcom/iris/iris_vb2.c   | 26 ++++++--
>   drivers/media/platform/qcom/iris/iris_vdec.c  | 61 ++++++++++---------
>   drivers/media/platform/qcom/iris/iris_vidc.c  |  1 +
>   8 files changed, 91 insertions(+), 42 deletions(-)
> 
> 
> base-commit: d7e7bca7169873b46e857c025c10f3336c1258d8
> --
> 2.56.0

Thank you for your bug report and suggested fixes.

I will mark is as under-review and ensure we do Closes: and 
Suggested-by: with whatever lads upstream.

---
bod

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

end of thread, other threads:[~2026-10-28 10:00 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <-D3aZIsoO4_H5CdnB-7Co7GWmm5F9FuU6aFuhXWogBXhfqNOaqC2Y8tkBxT9ljDcy84UAX1jmUWGl7NtGUG6Mg==@protonmail.internalid>
2026-10-28  3:43 ` [RFC PATCH v2 0/4] media: iris: decoder fixes for resolution changes Christian Cortner
2026-10-28  3:43   ` [RFC PATCH v2 1/4] media: iris: Don't flag an empty source change LAST buffer as an error Christian Cortner
2026-10-28  3:43   ` [RFC PATCH v2 2/4] media: iris: Update the CAPTURE stride and size on S_FMT(OUTPUT) Christian Cortner
2026-10-28  3:43   ` [RFC PATCH v2 3/4] media: iris: Signal V4L2_EVENT_EOS only at the end of a drain Christian Cortner
2026-10-28  3:43   ` [RFC PATCH v2 4/4] media: iris: Let a resolution change drain before stopping CAPTURE Christian Cortner
2026-10-28 10:00   ` [RFC PATCH v2 0/4] media: iris: decoder fixes for resolution changes Bryan O'Donoghue

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox