* [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 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.