From: Dikshita Agarwal via B4 Relay <devnull+quic_dikshita.quicinc.com@kernel.org>
To: Vikash Garodia <quic_vgarodia@quicinc.com>,
Abhinav Kumar <quic_abhinavk@quicinc.com>,
Mauro Carvalho Chehab <mchehab@kernel.org>,
Rob Herring <robh@kernel.org>,
Krzysztof Kozlowski <krzk+dt@kernel.org>,
Conor Dooley <conor+dt@kernel.org>,
Philipp Zabel <p.zabel@pengutronix.de>
Cc: linux-media@vger.kernel.org, linux-arm-msm@vger.kernel.org,
devicetree@vger.kernel.org, linux-kernel@vger.kernel.org,
Dikshita Agarwal <quic_dikshita@quicinc.com>
Subject: [PATCH v3 25/29] media: iris: add support for drain sequence
Date: Tue, 27 Aug 2024 15:35:50 +0530 [thread overview]
Message-ID: <20240827-iris_v3-v3-25-c5fdbbe65e70@quicinc.com> (raw)
In-Reply-To: <20240827-iris_v3-v3-0-c5fdbbe65e70@quicinc.com>
From: Dikshita Agarwal <quic_dikshita@quicinc.com>
handle the V4L2_DEC_CMD_STOP by initiating drain sequence
to firmware.
Process and decode all OUTPUT buffers queued by the client
before the VIDIOC_DECODER_CMD() was issued and mark the last
buffer with V4L2_BUF_FLAG_LAST flag. Decoder is stopped after
processing the last buffer.
Resume the decoder when one of below are issued by client:
- V4L2_DEC_CMD_START
- pair of VIDIOC_STREAMOFF() and VIDIOC_STREAMON() on the CAPTURE queue
- pair of VIDIOC_STREAMOFF() and VIDIOC_STREAMON() on the OUTPUT queue
Add the handling to resume decoding when client issues
V4L2_DEC_CMD_START to resume decoding after source change is
detected.
Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
---
drivers/media/platform/qcom/iris/iris_hfi_common.h | 2 +
.../platform/qcom/iris/iris_hfi_gen1_command.c | 13 +++
.../platform/qcom/iris/iris_hfi_gen1_defines.h | 1 +
.../platform/qcom/iris/iris_hfi_gen1_response.c | 14 +++
.../platform/qcom/iris/iris_hfi_gen2_command.c | 43 +++++++++
.../platform/qcom/iris/iris_hfi_gen2_defines.h | 2 +
.../platform/qcom/iris/iris_hfi_gen2_response.c | 46 ++++++++-
drivers/media/platform/qcom/iris/iris_state.c | 36 +++++++
drivers/media/platform/qcom/iris/iris_state.h | 11 ++-
drivers/media/platform/qcom/iris/iris_vb2.c | 6 +-
drivers/media/platform/qcom/iris/iris_vdec.c | 105 ++++++++++++++++++++-
drivers/media/platform/qcom/iris/iris_vdec.h | 2 +
drivers/media/platform/qcom/iris/iris_vidc.c | 36 +++++++
13 files changed, 307 insertions(+), 10 deletions(-)
diff --git a/drivers/media/platform/qcom/iris/iris_hfi_common.h b/drivers/media/platform/qcom/iris/iris_hfi_common.h
index ef76207aa749..5bd7073a2d9b 100644
--- a/drivers/media/platform/qcom/iris/iris_hfi_common.h
+++ b/drivers/media/platform/qcom/iris/iris_hfi_common.h
@@ -121,6 +121,8 @@ struct iris_hfi_command_ops {
int (*session_pause)(struct iris_inst *inst, u32 plane);
int (*session_resume_drc)(struct iris_inst *inst, u32 plane);
int (*session_stop)(struct iris_inst *inst, u32 plane);
+ int (*session_drain)(struct iris_inst *inst, u32 plane);
+ int (*session_resume_drain)(struct iris_inst *inst, u32 plane);
int (*session_close)(struct iris_inst *inst);
};
diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c
index d65aacb2bb13..17333768afa2 100644
--- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c
+++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c
@@ -369,6 +369,18 @@ static int iris_hfi_gen1_session_unset_buffers(struct iris_inst *inst, struct ir
return ret;
}
+static int iris_hfi_gen1_session_drain(struct iris_inst *inst, u32 plane)
+{
+ struct hfi_session_empty_buffer_compressed_pkt ip_pkt = {0};
+
+ ip_pkt.shdr.hdr.size = sizeof(struct hfi_session_empty_buffer_compressed_pkt);
+ ip_pkt.shdr.hdr.pkt_type = HFI_CMD_SESSION_EMPTY_BUFFER;
+ ip_pkt.shdr.session_id = inst->session_id;
+ ip_pkt.flags = HFI_BUFFERFLAG_EOS;
+
+ return iris_hfi_queue_cmd_write(inst->core, &ip_pkt, ip_pkt.shdr.hdr.size);
+}
+
static int
iris_hfi_gen1_packet_session_set_property(struct hfi_session_set_property_pkt *packet,
struct iris_inst *inst, u32 ptype, void *pdata)
@@ -797,6 +809,7 @@ static const struct iris_hfi_command_ops iris_hfi_gen1_command_ops = {
.session_release_buf = iris_hfi_gen1_session_unset_buffers,
.session_resume_drc = iris_hfi_gen1_session_continue,
.session_stop = iris_hfi_gen1_session_stop,
+ .session_drain = iris_hfi_gen1_session_drain,
.session_close = iris_hfi_gen1_session_close,
};
diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h b/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h
index 48d0d8e4dfe5..7f910fa0bfd7 100644
--- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h
+++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h
@@ -49,6 +49,7 @@
#define HFI_EVENT_DATA_SEQUENCE_CHANGED_INSUFFICIENT_BUF_RESOURCES 0x1000002
#define HFI_EVENT_SESSION_SEQUENCE_CHANGED 0x1000003
+#define HFI_BUFFERFLAG_EOS 0x00000001
#define HFI_BUFFERFLAG_TIMESTAMPINVALID 0x00000100
#define HFI_FLUSH_OUTPUT 0x1000002
diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c b/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c
index e3d9bfb8bef6..2d537babd3e7 100644
--- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c
+++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c
@@ -378,6 +378,7 @@ static void iris_hfi_gen1_session_ftb_done(struct iris_inst *inst, void *packet)
struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx;
struct v4l2_m2m_buffer *m2m_buffer, *n;
u32 timestamp_hi = 0, timestamp_lo = 0;
+ struct hfi_session_flush_pkt flush_pkt;
struct iris_buffer *buf = NULL, *iter;
struct iris_core *core = inst->core;
u32 pic_type = 0, output_tag = -1;
@@ -393,6 +394,19 @@ static void iris_hfi_gen1_session_ftb_done(struct iris_inst *inst, void *packet)
pic_type = pkt->picture_type;
output_tag = pkt->output_tag;
+ if ((hfi_flags & HFI_BUFFERFLAG_EOS) && !filled_len) {
+ reinit_completion(&inst->flush_completion);
+
+ flush_pkt.shdr.hdr.size = sizeof(struct hfi_session_flush_pkt);
+ flush_pkt.shdr.hdr.pkt_type = HFI_CMD_SESSION_FLUSH;
+ flush_pkt.shdr.session_id = inst->session_id;
+ flush_pkt.flush_type = HFI_FLUSH_OUTPUT;
+ iris_hfi_queue_cmd_write(core, &flush_pkt, flush_pkt.shdr.hdr.size);
+ iris_inst_sub_state_change_drain_last(inst);
+
+ return;
+ }
+
if (iris_split_mode_enabled(inst) && pkt->stream_id == 0) {
buffers = &inst->buffers[BUF_DPB];
if (!buffers)
diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c b/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c
index 42e86d6d435c..ee73a2b072db 100644
--- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c
+++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c
@@ -822,6 +822,47 @@ static int iris_hfi_gen2_session_resume_drc(struct iris_inst *inst, u32 plane)
inst_hfi_gen2->packet->size);
}
+static int iris_hfi_gen2_session_resume_drain(struct iris_inst *inst, u32 plane)
+{
+ struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst);
+ u32 payload = HFI_CMD_DRAIN;
+
+ iris_hfi_gen2_packet_session_command(inst,
+ HFI_CMD_RESUME,
+ (HFI_HOST_FLAGS_RESPONSE_REQUIRED |
+ HFI_HOST_FLAGS_INTR_REQUIRED),
+ iris_hfi_gen2_get_port(plane),
+ inst->session_id,
+ HFI_PAYLOAD_U32,
+ &payload,
+ sizeof(u32));
+
+ return iris_hfi_queue_cmd_write(inst->core, inst_hfi_gen2->packet,
+ inst_hfi_gen2->packet->size);
+}
+
+static int iris_hfi_gen2_session_drain(struct iris_inst *inst, u32 plane)
+{
+ struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst);
+
+ if (!V4L2_TYPE_IS_OUTPUT(plane))
+ return 0;
+
+ iris_hfi_gen2_packet_session_command(inst,
+ HFI_CMD_DRAIN,
+ (HFI_HOST_FLAGS_RESPONSE_REQUIRED |
+ HFI_HOST_FLAGS_INTR_REQUIRED |
+ HFI_HOST_FLAGS_NON_DISCARDABLE),
+ iris_hfi_gen2_get_port(plane),
+ inst->session_id,
+ HFI_PAYLOAD_NONE,
+ NULL,
+ 0);
+
+ return iris_hfi_queue_cmd_write(inst->core, inst_hfi_gen2->packet,
+ inst_hfi_gen2->packet->size);
+}
+
static u32 iris_hfi_gen2_buf_type_from_driver(enum iris_buffer_type buffer_type)
{
switch (buffer_type) {
@@ -946,6 +987,8 @@ static const struct iris_hfi_command_ops iris_hfi_gen2_command_ops = {
.session_pause = iris_hfi_gen2_session_pause,
.session_resume_drc = iris_hfi_gen2_session_resume_drc,
.session_stop = iris_hfi_gen2_session_stop,
+ .session_drain = iris_hfi_gen2_session_drain,
+ .session_resume_drain = iris_hfi_gen2_session_resume_drain,
.session_close = iris_hfi_gen2_session_close,
};
diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h b/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h
index 0aaba5f1ce91..72d41445d765 100644
--- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h
+++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h
@@ -17,6 +17,7 @@
#define HFI_CMD_CLOSE 0x01000004
#define HFI_CMD_START 0x01000005
#define HFI_CMD_STOP 0x01000006
+#define HFI_CMD_DRAIN 0x01000007
#define HFI_CMD_RESUME 0x01000008
#define HFI_CMD_BUFFER 0x01000009
#define HFI_CMD_SUBSCRIBE_MODE 0x0100000B
@@ -79,6 +80,7 @@
#define HFI_INFO_UNSUPPORTED 0x06000001
#define HFI_INFO_DATA_CORRUPT 0x06000002
#define HFI_INFO_BUFFER_OVERFLOW 0x06000004
+#define HFI_INFO_HFI_FLAG_DRAIN_LAST 0x06000006
#define HFI_INFO_HFI_FLAG_PSC_LAST 0x06000007
#define HFI_INFORMATION_END 0x06FFFFFF
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 626a858e803c..8b3402635674 100644
--- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c
+++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c
@@ -202,6 +202,10 @@ static int iris_hfi_gen2_handle_session_info(struct iris_inst *inst,
info = "buffer overflow";
inst_hfi_gen2->hfi_frame_info.overflow = 1;
break;
+ case HFI_INFO_HFI_FLAG_DRAIN_LAST:
+ info = "drain last flag";
+ ret = iris_inst_sub_state_change_drain_last(inst);
+ break;
case HFI_INFO_HFI_FLAG_PSC_LAST:
info = "drc last flag";
ret = iris_inst_sub_state_change_drc_last(inst);
@@ -329,6 +333,12 @@ static int iris_hfi_gen2_handle_output_buffer(struct iris_inst *inst,
int ret = 0;
bool found = false;
+ if (hfi_buffer->flags & HFI_BUF_FW_FLAG_LAST) {
+ ret = iris_inst_sub_state_change_drain_last(inst);
+ if (ret)
+ return ret;
+ }
+
if (hfi_buffer->flags & HFI_BUF_FW_FLAG_PSC_LAST) {
ret = iris_inst_sub_state_change_drc_last(inst);
if (ret)
@@ -429,6 +439,21 @@ static int iris_hfi_gen2_handle_release_internal_buffer(struct iris_inst *inst,
return ret;
}
+static int iris_hfi_gen2_handle_session_stop(struct iris_inst *inst,
+ struct iris_hfi_packet *pkt)
+{
+ int ret = 0;
+
+ if (pkt->port == HFI_PORT_RAW)
+ ret = iris_inst_sub_state_change_pause(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
+ else if (pkt->port == HFI_PORT_BITSTREAM)
+ ret = iris_inst_sub_state_change_pause(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
+
+ complete(&inst->completion);
+
+ return ret;
+}
+
static int iris_hfi_gen2_handle_session_buffer(struct iris_inst *inst,
struct iris_hfi_packet *pkt)
{
@@ -457,6 +482,22 @@ static int iris_hfi_gen2_handle_session_buffer(struct iris_inst *inst,
return iris_hfi_gen2_handle_release_internal_buffer(inst, buffer);
}
+static int iris_hfi_gen2_handle_session_drain(struct iris_inst *inst,
+ struct iris_hfi_packet *pkt)
+{
+ int ret = 0;
+
+ if (!(pkt->flags & HFI_FW_FLAGS_SUCCESS)) {
+ iris_inst_change_state(inst, IRIS_INST_ERROR);
+ return 0;
+ }
+
+ if (inst->sub_state & IRIS_INST_SUB_DRAIN)
+ ret = iris_inst_change_sub_state(inst, 0, IRIS_INST_SUB_INPUT_PAUSE);
+
+ return ret;
+}
+
static void iris_hfi_gen2_read_input_subcr_params(struct iris_inst *inst)
{
struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst);
@@ -569,7 +610,7 @@ static int iris_hfi_gen2_handle_session_command(struct iris_inst *inst,
iris_hfi_gen2_handle_session_close(inst, pkt);
break;
case HFI_CMD_STOP:
- complete(&inst->completion);
+ iris_hfi_gen2_handle_session_stop(inst, pkt);
break;
case HFI_CMD_BUFFER:
ret = iris_hfi_gen2_handle_session_buffer(inst, pkt);
@@ -577,6 +618,9 @@ static int iris_hfi_gen2_handle_session_command(struct iris_inst *inst,
case HFI_CMD_SETTINGS_CHANGE:
ret = iris_hfi_gen2_handle_src_change(inst, pkt);
break;
+ case HFI_CMD_DRAIN:
+ ret = iris_hfi_gen2_handle_session_drain(inst, pkt);
+ break;
default:
break;
}
diff --git a/drivers/media/platform/qcom/iris/iris_state.c b/drivers/media/platform/qcom/iris/iris_state.c
index e39c110b75e0..d37f99d72491 100644
--- a/drivers/media/platform/qcom/iris/iris_state.c
+++ b/drivers/media/platform/qcom/iris/iris_state.c
@@ -160,6 +160,21 @@ int iris_inst_sub_state_change_drc(struct iris_inst *inst)
return iris_inst_change_sub_state(inst, 0, set_sub_state);
}
+int iris_inst_sub_state_change_drain_last(struct iris_inst *inst)
+{
+ enum iris_inst_sub_state set_sub_state = IRIS_INST_SUB_NONE;
+
+ if (inst->sub_state & IRIS_INST_SUB_DRAIN_LAST)
+ return -EINVAL;
+
+ if (!(inst->sub_state & IRIS_INST_SUB_DRAIN))
+ return -EINVAL;
+
+ set_sub_state = IRIS_INST_SUB_DRAIN_LAST | IRIS_INST_SUB_OUTPUT_PAUSE;
+
+ return iris_inst_change_sub_state(inst, 0, set_sub_state);
+}
+
int iris_inst_sub_state_change_drc_last(struct iris_inst *inst)
{
enum iris_inst_sub_state set_sub_state = IRIS_INST_SUB_NONE;
@@ -178,3 +193,24 @@ int iris_inst_sub_state_change_drc_last(struct iris_inst *inst)
return iris_inst_change_sub_state(inst, 0, set_sub_state);
}
+
+int iris_inst_sub_state_change_pause(struct iris_inst *inst, u32 plane)
+{
+ enum iris_inst_sub_state set_sub_state = IRIS_INST_SUB_NONE;
+
+ if (V4L2_TYPE_IS_OUTPUT(plane)) {
+ if (inst->sub_state & IRIS_INST_SUB_DRC &&
+ !(inst->sub_state & IRIS_INST_SUB_DRC_LAST))
+ return -EINVAL;
+
+ if (inst->sub_state & IRIS_INST_SUB_DRAIN &&
+ !(inst->sub_state & IRIS_INST_SUB_DRAIN_LAST))
+ return -EINVAL;
+
+ set_sub_state = IRIS_INST_SUB_INPUT_PAUSE;
+ } else {
+ set_sub_state = IRIS_INST_SUB_OUTPUT_PAUSE;
+ }
+
+ return iris_inst_change_sub_state(inst, 0, set_sub_state);
+}
diff --git a/drivers/media/platform/qcom/iris/iris_state.h b/drivers/media/platform/qcom/iris/iris_state.h
index 786b82ca0307..a01037918a9c 100644
--- a/drivers/media/platform/qcom/iris/iris_state.h
+++ b/drivers/media/platform/qcom/iris/iris_state.h
@@ -106,6 +106,9 @@ enum iris_inst_state {
* sent to client.
* IRIS_INST_SUB_DRC_LAST: indicates last buffer is received from firmware
* as part of source change.
+ * IRIS_INST_SUB_DRAIN: indicates drain is in progress.
+ * IRIS_INST_SUB_DRAIN_LAST: indicates last buffer is received from firmware
+ * as part of drain sequence.
* IRIS_INST_SUB_INPUT_PAUSE: source change is received form firmware. This
* indicates that firmware is paused to process
* any further input frames.
@@ -117,8 +120,10 @@ enum iris_inst_sub_state {
IRIS_INST_SUB_FIRST_IPSC = BIT(0),
IRIS_INST_SUB_DRC = BIT(1),
IRIS_INST_SUB_DRC_LAST = BIT(2),
- IRIS_INST_SUB_INPUT_PAUSE = BIT(3),
- IRIS_INST_SUB_OUTPUT_PAUSE = BIT(4),
+ IRIS_INST_SUB_DRAIN = BIT(3),
+ IRIS_INST_SUB_DRAIN_LAST = BIT(4),
+ IRIS_INST_SUB_INPUT_PAUSE = BIT(5),
+ IRIS_INST_SUB_OUTPUT_PAUSE = BIT(6),
};
void iris_change_core_state(struct iris_core *core,
@@ -131,5 +136,7 @@ int iris_inst_change_sub_state(struct iris_inst *inst,
int iris_inst_state_change_streamon(struct iris_inst *inst, u32 plane);
int iris_inst_state_change_streamoff(struct iris_inst *inst, u32 plane);
int iris_inst_sub_state_change_drc(struct iris_inst *inst);
+int iris_inst_sub_state_change_drain_last(struct iris_inst *inst);
int iris_inst_sub_state_change_drc_last(struct iris_inst *inst);
+int iris_inst_sub_state_change_pause(struct iris_inst *inst, u32 plane);
#endif
diff --git a/drivers/media/platform/qcom/iris/iris_vb2.c b/drivers/media/platform/qcom/iris/iris_vb2.c
index cc9d5f14d125..8bed24cf610e 100644
--- a/drivers/media/platform/qcom/iris/iris_vb2.c
+++ b/drivers/media/platform/qcom/iris/iris_vb2.c
@@ -229,8 +229,10 @@ void iris_vb2_buf_queue(struct vb2_buffer *vb2)
}
if (V4L2_TYPE_IS_CAPTURE(vb2->vb2_queue->type)) {
- if (inst->sub_state & IRIS_INST_SUB_DRC &&
- inst->sub_state & IRIS_INST_SUB_DRC_LAST) {
+ if ((inst->sub_state & IRIS_INST_SUB_DRC &&
+ inst->sub_state & IRIS_INST_SUB_DRC_LAST) ||
+ (inst->sub_state & IRIS_INST_SUB_DRAIN &&
+ inst->sub_state & IRIS_INST_SUB_DRAIN_LAST)) {
vbuf->flags |= V4L2_BUF_FLAG_LAST;
vbuf->field = V4L2_FIELD_NONE;
vb2_set_plane_payload(vb2, 0, 0);
diff --git a/drivers/media/platform/qcom/iris/iris_vdec.c b/drivers/media/platform/qcom/iris/iris_vdec.c
index 6d3b06150cf7..b8d2d6846daa 100644
--- a/drivers/media/platform/qcom/iris/iris_vdec.c
+++ b/drivers/media/platform/qcom/iris/iris_vdec.c
@@ -399,6 +399,7 @@ static int iris_vdec_process_streamon_input(struct iris_inst *inst)
}
if (inst->sub_state & IRIS_INST_SUB_DRC ||
+ inst->sub_state & IRIS_INST_SUB_DRAIN ||
inst->sub_state & IRIS_INST_SUB_FIRST_IPSC) {
if (!(inst->sub_state & IRIS_INST_SUB_INPUT_PAUSE)) {
if (hfi_ops->session_pause) {
@@ -457,14 +458,19 @@ static int iris_vdec_process_streamon_output(struct iris_inst *inst)
{
const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops;
enum iris_inst_sub_state clear_sub_state = IRIS_INST_SUB_NONE;
- bool drc_active = false;
+ bool drain_active = false, drc_active = false;
int ret;
+ drain_active = inst->sub_state & IRIS_INST_SUB_DRAIN &&
+ inst->sub_state & IRIS_INST_SUB_DRAIN_LAST;
+
drc_active = inst->sub_state & IRIS_INST_SUB_DRC &&
inst->sub_state & IRIS_INST_SUB_DRC_LAST;
if (drc_active)
clear_sub_state = IRIS_INST_SUB_DRC | IRIS_INST_SUB_DRC_LAST;
+ else if (drain_active)
+ clear_sub_state = IRIS_INST_SUB_DRAIN | IRIS_INST_SUB_DRAIN_LAST;
if (inst->sub_state & IRIS_INST_SUB_INPUT_PAUSE) {
ret = iris_alloc_and_queue_input_int_bufs(inst);
@@ -480,10 +486,20 @@ static int iris_vdec_process_streamon_output(struct iris_inst *inst)
if (inst->state == IRIS_INST_INPUT_STREAMING &&
inst->sub_state & IRIS_INST_SUB_INPUT_PAUSE) {
- ret = hfi_ops->session_resume_drc(inst,
- V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
- if (ret)
- return ret;
+ if (!drain_active) {
+ ret = hfi_ops->session_resume_drc(inst,
+ V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
+ if (ret)
+ return ret;
+ } else {
+ if (hfi_ops->session_resume_drain) {
+ ret =
+ hfi_ops->session_resume_drain(inst,
+ V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
+ if (ret)
+ return ret;
+ }
+ }
clear_sub_state |= IRIS_INST_SUB_INPUT_PAUSE;
}
@@ -584,3 +600,82 @@ int iris_vdec_qbuf(struct iris_inst *inst, struct vb2_v4l2_buffer *vbuf)
return iris_queue_buffer(inst, buf);
}
+
+int iris_vdec_start_cmd(struct iris_inst *inst)
+{
+ const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops;
+ enum iris_inst_sub_state clear_sub_state = IRIS_INST_SUB_NONE;
+ struct vb2_queue *dst_vq;
+ int ret;
+
+ dst_vq = v4l2_m2m_get_vq(inst->m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
+
+ if (inst->sub_state & IRIS_INST_SUB_DRC &&
+ inst->sub_state & IRIS_INST_SUB_DRC_LAST) {
+ vb2_clear_last_buffer_dequeued(dst_vq);
+ clear_sub_state = IRIS_INST_SUB_DRC | IRIS_INST_SUB_DRC_LAST;
+
+ if (inst->sub_state & IRIS_INST_SUB_INPUT_PAUSE) {
+ ret = hfi_ops->session_resume_drc(inst,
+ V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
+ if (ret)
+ return ret;
+ clear_sub_state |= IRIS_INST_SUB_INPUT_PAUSE;
+ }
+ if (inst->sub_state & IRIS_INST_SUB_OUTPUT_PAUSE) {
+ ret = hfi_ops->session_resume_drc(inst,
+ V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
+ if (ret)
+ return ret;
+ clear_sub_state |= IRIS_INST_SUB_OUTPUT_PAUSE;
+ }
+ } else if (inst->sub_state & IRIS_INST_SUB_DRAIN &&
+ inst->sub_state & IRIS_INST_SUB_DRAIN_LAST) {
+ vb2_clear_last_buffer_dequeued(dst_vq);
+ clear_sub_state = IRIS_INST_SUB_DRAIN | IRIS_INST_SUB_DRAIN_LAST;
+ if (inst->sub_state & IRIS_INST_SUB_INPUT_PAUSE) {
+ if (hfi_ops->session_resume_drain) {
+ ret =
+ hfi_ops->session_resume_drain(inst,
+ V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
+ if (ret)
+ return ret;
+ }
+
+ clear_sub_state |= IRIS_INST_SUB_INPUT_PAUSE;
+ }
+ if (inst->sub_state & IRIS_INST_SUB_OUTPUT_PAUSE) {
+ if (hfi_ops->session_resume_drain) {
+ ret =
+ hfi_ops->session_resume_drain(inst,
+ V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
+ if (ret)
+ return ret;
+ }
+
+ clear_sub_state |= IRIS_INST_SUB_OUTPUT_PAUSE;
+ }
+ } else {
+ dev_err(inst->core->dev, "start called before receiving last_flag\n");
+ iris_inst_change_state(inst, IRIS_INST_ERROR);
+ return -EBUSY;
+ }
+
+ ret = iris_inst_change_sub_state(inst, clear_sub_state, 0);
+
+ return ret;
+}
+
+int iris_vdec_stop_cmd(struct iris_inst *inst)
+{
+ const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops;
+ int ret;
+
+ ret = hfi_ops->session_drain(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
+ if (ret)
+ return ret;
+
+ iris_inst_change_sub_state(inst, 0, IRIS_INST_SUB_DRAIN);
+
+ return ret;
+}
diff --git a/drivers/media/platform/qcom/iris/iris_vdec.h b/drivers/media/platform/qcom/iris/iris_vdec.h
index a5d63d6f7723..1d0231db24de 100644
--- a/drivers/media/platform/qcom/iris/iris_vdec.h
+++ b/drivers/media/platform/qcom/iris/iris_vdec.h
@@ -18,6 +18,8 @@ void iris_vdec_src_change(struct iris_inst *inst);
int iris_vdec_streamon_input(struct iris_inst *inst);
int iris_vdec_streamon_output(struct iris_inst *inst);
int iris_vdec_qbuf(struct iris_inst *inst, struct vb2_v4l2_buffer *vbuf);
+int iris_vdec_start_cmd(struct iris_inst *inst);
+int iris_vdec_stop_cmd(struct iris_inst *inst);
int iris_vdec_session_streamoff(struct iris_inst *inst, u32 plane);
#endif
diff --git a/drivers/media/platform/qcom/iris/iris_vidc.c b/drivers/media/platform/qcom/iris/iris_vidc.c
index 34c2548bce9f..07eb276472f6 100644
--- a/drivers/media/platform/qcom/iris/iris_vidc.c
+++ b/drivers/media/platform/qcom/iris/iris_vidc.c
@@ -603,6 +603,40 @@ static int iris_unsubscribe_event(struct v4l2_fh *fh, const struct v4l2_event_su
return ret;
}
+static int iris_dec_cmd(struct file *filp, void *fh,
+ struct v4l2_decoder_cmd *dec)
+{
+ struct iris_inst *inst;
+ int ret = 0;
+
+ inst = iris_get_inst(filp, fh);
+ if (!inst || !dec)
+ return -EINVAL;
+
+ mutex_lock(&inst->lock);
+
+ if (dec->cmd != V4L2_DEC_CMD_START &&
+ dec->cmd != V4L2_DEC_CMD_STOP) {
+ ret = -EINVAL;
+ goto unlock;
+ }
+
+ if (inst->state == IRIS_INST_DEINIT)
+ goto unlock;
+
+ if (dec->cmd == V4L2_DEC_CMD_START)
+ ret = iris_vdec_start_cmd(inst);
+ else if (dec->cmd == V4L2_DEC_CMD_STOP)
+ ret = iris_vdec_stop_cmd(inst);
+ else
+ ret = -EINVAL;
+
+unlock:
+ mutex_unlock(&inst->lock);
+
+ return ret;
+}
+
static struct v4l2_file_operations iris_v4l2_file_ops = {
.owner = THIS_MODULE,
.open = iris_open,
@@ -645,6 +679,8 @@ static const struct v4l2_ioctl_ops iris_v4l2_ioctl_ops = {
.vidioc_unsubscribe_event = iris_unsubscribe_event,
.vidioc_streamon = v4l2_m2m_ioctl_streamon,
.vidioc_streamoff = v4l2_m2m_ioctl_streamoff,
+ .vidioc_try_decoder_cmd = v4l2_m2m_ioctl_try_decoder_cmd,
+ .vidioc_decoder_cmd = iris_dec_cmd,
};
void iris_init_ops(struct iris_core *core)
--
2.34.1
next prev parent reply other threads:[~2024-08-27 10:06 UTC|newest]
Thread overview: 93+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-08-27 10:05 [PATCH v3 00/29] Qualcomm iris video decoder driver Dikshita Agarwal via B4 Relay
2024-08-27 10:05 ` [PATCH v3 01/29] dt-bindings: media: Add sm8550 dt schema Dikshita Agarwal via B4 Relay
2024-08-27 10:42 ` Krzysztof Kozlowski
2024-09-05 5:41 ` Dikshita Agarwal
2024-08-27 10:05 ` [PATCH v3 02/29] media: MAINTAINERS: Add Qualcomm Iris video accelerator driver Dikshita Agarwal via B4 Relay
2024-08-27 10:42 ` Krzysztof Kozlowski
2024-09-05 5:47 ` Dikshita Agarwal
2024-09-05 10:10 ` Dmitry Baryshkov
2024-09-05 11:02 ` Dikshita Agarwal
2024-09-05 11:02 ` Dmitry Baryshkov
2024-09-05 11:14 ` Dikshita Agarwal
2024-08-27 10:05 ` [PATCH v3 03/29] media: iris: add platform driver for iris video device Dikshita Agarwal via B4 Relay
2024-08-27 14:08 ` Bryan O'Donoghue
2024-08-29 9:13 ` Dmitry Baryshkov
2024-08-29 9:36 ` Bryan O'Donoghue
2024-09-05 6:12 ` Dikshita Agarwal
2024-09-05 6:15 ` Dikshita Agarwal
2024-09-05 10:11 ` Dmitry Baryshkov
2024-09-05 10:59 ` Dikshita Agarwal
2024-09-05 11:07 ` Dmitry Baryshkov
2024-09-05 11:13 ` Dikshita Agarwal
2024-08-27 10:05 ` [PATCH v3 04/29] media: iris: initialize power resources Dikshita Agarwal via B4 Relay
2024-08-27 10:51 ` Krzysztof Kozlowski
2024-09-05 11:53 ` Dikshita Agarwal
2024-09-05 11:57 ` Krzysztof Kozlowski
2024-09-06 11:21 ` Vikash Garodia
2024-09-06 12:04 ` Krzysztof Kozlowski
2024-09-06 19:47 ` Vikash Garodia
2024-09-07 9:07 ` Krzysztof Kozlowski
2024-08-27 10:05 ` [PATCH v3 05/29] media: iris: implement iris v4l2 file ops Dikshita Agarwal via B4 Relay
2024-09-06 19:05 ` Markus Elfring
2024-09-07 8:52 ` Markus Elfring
2024-08-27 10:05 ` [PATCH v3 06/29] media: iris: introduce iris core state management with shared queues Dikshita Agarwal via B4 Relay
2024-08-28 2:38 ` kernel test robot
2024-08-27 10:05 ` [PATCH v3 07/29] media: iris: implement video firmware load/unload Dikshita Agarwal via B4 Relay
2024-08-27 23:13 ` kernel test robot
2024-08-31 13:18 ` Bryan O'Donoghue
2024-09-02 0:04 ` Dmitry Baryshkov
2024-09-05 6:17 ` Dikshita Agarwal
2024-08-27 10:05 ` [PATCH v3 08/29] media: iris: implement boot sequence of the firmware Dikshita Agarwal via B4 Relay
2024-09-05 12:34 ` Bryan O'Donoghue
2024-09-06 11:27 ` Vikash Garodia
2024-08-27 10:05 ` [PATCH v3 09/29] media: iris: introduce Host firmware interface with necessary hooks Dikshita Agarwal via B4 Relay
2024-09-05 12:36 ` Bryan O'Donoghue
2024-09-24 9:13 ` Dikshita Agarwal
2024-09-05 13:10 ` Bryan O'Donoghue
2024-09-06 13:31 ` Vikash Garodia
2024-08-27 10:05 ` [PATCH v3 10/29] media: iris: implement power management Dikshita Agarwal via B4 Relay
2024-09-05 13:23 ` Bryan O'Donoghue
2024-09-05 13:46 ` Krzysztof Kozlowski
2024-09-24 8:38 ` Dikshita Agarwal
2024-09-24 8:36 ` Dikshita Agarwal
2024-08-27 10:05 ` [PATCH v3 11/29] media: iris: implement reqbuf ioctl with vb2_queue_setup Dikshita Agarwal via B4 Relay
2024-09-06 12:50 ` Bryan O'Donoghue
2024-09-06 13:05 ` Bryan O'Donoghue
2024-09-26 10:47 ` Dikshita Agarwal
2024-08-27 10:05 ` [PATCH v3 12/29] media: iris: implement s_fmt, g_fmt and try_fmt ioctls Dikshita Agarwal via B4 Relay
2024-09-24 14:41 ` Bryan O'Donoghue
2024-09-26 10:49 ` Dikshita Agarwal
2024-08-27 10:05 ` [PATCH v3 13/29] media: iris: implement g_selection ioctl Dikshita Agarwal via B4 Relay
2024-08-27 10:05 ` [PATCH v3 14/29] media: iris: implement enum_fmt and enum_frameintervals ioctls Dikshita Agarwal via B4 Relay
2024-08-27 10:05 ` [PATCH v3 15/29] media: iris: implement subscribe_event and unsubscribe_event ioctls Dikshita Agarwal via B4 Relay
2024-08-27 10:05 ` [PATCH v3 16/29] media: iris: implement iris v4l2_ctrl_ops and prepare capabilities Dikshita Agarwal via B4 Relay
2024-08-29 9:33 ` Dmitry Baryshkov
2024-10-01 13:01 ` Vedang Nagar
2024-10-06 16:46 ` Dmitry Baryshkov
2024-08-27 10:05 ` [PATCH v3 17/29] media: iris: implement query_cap, query_ctrl and query_menu ioctls Dikshita Agarwal via B4 Relay
2024-09-24 14:49 ` Bryan O'Donoghue
2024-09-26 10:50 ` Dikshita Agarwal
2024-08-27 10:05 ` [PATCH v3 18/29] media: iris: implement vb2 streaming ops Dikshita Agarwal via B4 Relay
2024-08-28 0:26 ` kernel test robot
2024-08-27 10:05 ` [PATCH v3 19/29] media: iris: implement set properties to firmware during streamon Dikshita Agarwal via B4 Relay
2024-09-24 15:09 ` Bryan O'Donoghue
2024-08-27 10:05 ` [PATCH v3 20/29] media: iris: subscribe parameters and properties to firmware for hfi_gen2 Dikshita Agarwal via B4 Relay
2024-09-24 15:16 ` Bryan O'Donoghue
2024-09-26 10:55 ` Dikshita Agarwal
2024-08-27 10:05 ` [PATCH v3 21/29] media: iris: allocate, initialize and queue internal buffers Dikshita Agarwal via B4 Relay
2024-08-27 10:05 ` [PATCH v3 22/29] media: iris: implement vb2 ops for buf_queue and firmware response Dikshita Agarwal via B4 Relay
2024-08-27 10:05 ` [PATCH v3 23/29] media: iris: add support for dynamic resolution change Dikshita Agarwal via B4 Relay
2024-08-27 10:05 ` [PATCH v3 24/29] media: iris: handle streamoff/on from client in " Dikshita Agarwal via B4 Relay
2024-08-27 10:05 ` Dikshita Agarwal via B4 Relay [this message]
2024-08-27 10:05 ` [PATCH v3 26/29] media: iris: add check whether the video session is supported or not Dikshita Agarwal via B4 Relay
2024-08-27 10:05 ` [PATCH v3 27/29] media: iris: implement power scaling for vpu2 and vpu3 Dikshita Agarwal via B4 Relay
2024-08-27 10:05 ` [PATCH v3 28/29] media: iris: add allow checks for v4l2 ioctls Dikshita Agarwal via B4 Relay
2024-08-27 10:05 ` [PATCH v3 29/29] media: iris: add check to allow sub states transitions Dikshita Agarwal via B4 Relay
2024-08-27 13:41 ` [PATCH v3 00/29] Qualcomm iris video decoder driver neil.armstrong
2024-09-24 9:13 ` Dikshita Agarwal
2024-10-01 13:28 ` Neil Armstrong
2024-08-31 15:18 ` Bryan O'Donoghue
2024-09-02 0:02 ` Dmitry Baryshkov
2024-09-06 14:19 ` Nicolas Dufresne
2024-09-06 19:26 ` Vikash Garodia
2024-09-06 16:28 ` Abhinav Kumar
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20240827-iris_v3-v3-25-c5fdbbe65e70@quicinc.com \
--to=devnull+quic_dikshita.quicinc.com@kernel.org \
--cc=conor+dt@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=krzk+dt@kernel.org \
--cc=linux-arm-msm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-media@vger.kernel.org \
--cc=mchehab@kernel.org \
--cc=p.zabel@pengutronix.de \
--cc=quic_abhinavk@quicinc.com \
--cc=quic_dikshita@quicinc.com \
--cc=quic_vgarodia@quicinc.com \
--cc=robh@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).