]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
media: iris: handle streamoff/on from client in dynamic resolution change
authorDikshita Agarwal <quic_dikshita@quicinc.com>
Fri, 7 Feb 2025 07:55:02 +0000 (13:25 +0530)
committerHans Verkuil <hverkuil@xs4all.nl>
Fri, 7 Feb 2025 10:51:49 +0000 (11:51 +0100)
The decoder is stopped after it completes the dynamic resolution change
sequence. Handle VIDIOC_STREAMOFF() and VIDIOC_STREAMON() on the CAPTURE
queue to resume the decoding process.

Tested-by: Stefan Schmidt <stefan.schmidt@linaro.org> # x1e80100 (Dell XPS 13 9345)
Reviewed-by: Stefan Schmidt <stefan.schmidt@linaro.org>
Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-HDK
Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
drivers/media/platform/qcom/iris/iris_buffer.c
drivers/media/platform/qcom/iris/iris_buffer.h
drivers/media/platform/qcom/iris/iris_hfi_common.h
drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c
drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h
drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c
drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h
drivers/media/platform/qcom/iris/iris_vdec.c

index de1267c387f1d53f6c64fd1f9e028d93ea278b55..dc096e5e95bf0c02b272384e986a677174d73d07 100644 (file)
@@ -404,6 +404,47 @@ int iris_destroy_internal_buffers(struct iris_inst *inst, u32 plane)
        return 0;
 }
 
+static int iris_release_internal_buffers(struct iris_inst *inst,
+                                        enum iris_buffer_type buffer_type)
+{
+       const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops;
+       struct iris_buffers *buffers = &inst->buffers[buffer_type];
+       struct iris_buffer *buffer, *next;
+       int ret;
+
+       list_for_each_entry_safe(buffer, next, &buffers->list, list) {
+               if (buffer->attr & BUF_ATTR_PENDING_RELEASE)
+                       continue;
+               if (!(buffer->attr & BUF_ATTR_QUEUED))
+                       continue;
+               ret = hfi_ops->session_release_buf(inst, buffer);
+               if (ret)
+                       return ret;
+               buffer->attr |= BUF_ATTR_PENDING_RELEASE;
+       }
+
+       return 0;
+}
+
+static int iris_release_input_internal_buffers(struct iris_inst *inst)
+{
+       const struct iris_platform_data *platform_data = inst->core->iris_platform_data;
+       const u32 *internal_buf_type;
+       u32 internal_buffer_count, i;
+       int ret;
+
+       internal_buf_type = platform_data->dec_ip_int_buf_tbl;
+       internal_buffer_count = platform_data->dec_ip_int_buf_tbl_size;
+
+       for (i = 0; i < internal_buffer_count; i++) {
+               ret = iris_release_internal_buffers(inst, internal_buf_type[i]);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+
 int iris_alloc_and_queue_persist_bufs(struct iris_inst *inst)
 {
        struct iris_buffers *buffers = &inst->buffers[BUF_PERSIST];
@@ -435,6 +476,23 @@ int iris_alloc_and_queue_persist_bufs(struct iris_inst *inst)
        return 0;
 }
 
+int iris_alloc_and_queue_input_int_bufs(struct iris_inst *inst)
+{
+       int ret;
+
+       iris_get_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
+
+       ret = iris_release_input_internal_buffers(inst);
+       if (ret)
+               return ret;
+
+       ret = iris_create_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
+       if (ret)
+               return ret;
+
+       return iris_queue_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
+}
+
 int iris_queue_deferred_buffers(struct iris_inst *inst, enum iris_buffer_type buf_type)
 {
        struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx;
index 2c7432a59906ba640994e7eb5e335b49ac20eae8..c36b6347b0770a5abd6d63c0c4e027560fbb2f64 100644 (file)
@@ -108,6 +108,7 @@ int iris_queue_internal_buffers(struct iris_inst *inst, u32 plane);
 int iris_destroy_internal_buffer(struct iris_inst *inst, struct iris_buffer *buffer);
 int iris_destroy_internal_buffers(struct iris_inst *inst, u32 plane);
 int iris_alloc_and_queue_persist_bufs(struct iris_inst *inst);
+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);
index 6241098dc31df3c5a198f000a786d8ce14fa8343..8e14a61c9be4ad72c1870ec6b6b88e1de066f7ee 100644 (file)
@@ -118,6 +118,8 @@ struct iris_hfi_command_ops {
        int (*session_start)(struct iris_inst *inst, u32 plane);
        int (*session_queue_buf)(struct iris_inst *inst, struct iris_buffer *buffer);
        int (*session_release_buf)(struct iris_inst *inst, struct iris_buffer *buffer);
+       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_close)(struct iris_inst *inst);
 };
index 03f7e6ea4bf34b920b9e541006600c8eabbc369f..e0cb75a112e31ac1bb0321ec5827aaaf8642a934 100644 (file)
@@ -205,6 +205,15 @@ static int iris_hfi_gen1_session_stop(struct iris_inst *inst, u32 plane)
        return ret;
 }
 
+static int iris_hfi_gen1_session_continue(struct iris_inst *inst, u32 plane)
+{
+       struct hfi_session_pkt packet;
+
+       iris_hfi_gen1_packet_session_cmd(inst, &packet, HFI_CMD_SESSION_CONTINUE);
+
+       return iris_hfi_queue_cmd_write(inst->core, &packet, packet.shdr.hdr.size);
+}
+
 static int iris_hfi_gen1_queue_input_buffer(struct iris_inst *inst, struct iris_buffer *buf)
 {
        struct hfi_session_empty_buffer_compressed_pkt ip_pkt;
@@ -778,6 +787,7 @@ static const struct iris_hfi_command_ops iris_hfi_gen1_command_ops = {
        .session_start = iris_hfi_gen1_session_start,
        .session_queue_buf = iris_hfi_gen1_session_queue_buffer,
        .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_close = iris_hfi_gen1_session_close,
 };
index 416e9a19a26f9b08e6643b150e8f6387f9695326..c40e0a28b21f3e78c6c6db717885118d13e237cb 100644 (file)
@@ -34,6 +34,7 @@
 #define HFI_CMD_SESSION_FLUSH                          0x211008
 #define HFI_CMD_SESSION_RELEASE_BUFFERS                        0x21100b
 #define HFI_CMD_SESSION_RELEASE_RESOURCES              0x21100c
+#define HFI_CMD_SESSION_CONTINUE                       0x21100d
 
 #define HFI_ERR_SESSION_UNSUPPORTED_SETTING            0x1008
 #define HFI_ERR_SESSION_UNSUPPORTED_STREAM             0x100d
index cc75231f07f17a32b2d3fe3e85e3ab51af4646ed..8efc6a70a57ab2289e49ad9cd131260102af051e 100644 (file)
@@ -737,6 +737,43 @@ static int iris_hfi_gen2_session_stop(struct iris_inst *inst, u32 plane)
        return iris_wait_for_session_response(inst, false);
 }
 
+static int iris_hfi_gen2_session_pause(struct iris_inst *inst, u32 plane)
+{
+       struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst);
+
+       iris_hfi_gen2_packet_session_command(inst,
+                                            HFI_CMD_PAUSE,
+                                            (HFI_HOST_FLAGS_RESPONSE_REQUIRED |
+                                            HFI_HOST_FLAGS_INTR_REQUIRED),
+                                            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 int iris_hfi_gen2_session_resume_drc(struct iris_inst *inst, u32 plane)
+{
+       struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst);
+       u32 payload = HFI_CMD_SETTINGS_CHANGE;
+
+       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 u32 iris_hfi_gen2_buf_type_from_driver(enum iris_buffer_type buffer_type)
 {
        switch (buffer_type) {
@@ -860,6 +897,8 @@ static const struct iris_hfi_command_ops iris_hfi_gen2_command_ops = {
        .session_start = iris_hfi_gen2_session_start,
        .session_queue_buf = iris_hfi_gen2_session_queue_buffer,
        .session_release_buf = iris_hfi_gen2_session_release_buffer,
+       .session_pause = iris_hfi_gen2_session_pause,
+       .session_resume_drc = iris_hfi_gen2_session_resume_drc,
        .session_stop = iris_hfi_gen2_session_stop,
        .session_close = iris_hfi_gen2_session_close,
 };
index 42cd57d5e3b1c9528cec99820d62601fa424f2f2..620bcb90c35f7ac753bba3f401c09c842fa74969 100644 (file)
 #define HFI_CMD_CLOSE                          0x01000004
 #define HFI_CMD_START                          0x01000005
 #define HFI_CMD_STOP                           0x01000006
+#define HFI_CMD_RESUME                         0x01000008
 #define HFI_CMD_BUFFER                         0x01000009
 #define HFI_CMD_SUBSCRIBE_MODE                 0x0100000B
 #define HFI_CMD_SETTINGS_CHANGE                        0x0100000C
+#define HFI_CMD_PAUSE                          0x01000011
 #define HFI_CMD_END                            0x01FFFFFF
 
 #define HFI_BITMASK_BITSTREAM_WIDTH            0xffff0000
index 1da277ed6cb34375c2d2166fa6bb8e9051050d11..47a44978869b49a37067f986f73e00bb3c48a127 100644 (file)
@@ -357,13 +357,37 @@ error:
 static int iris_vdec_process_streamon_input(struct iris_inst *inst)
 {
        const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops;
+       enum iris_inst_sub_state set_sub_state = 0;
        int ret;
 
        ret = hfi_ops->session_start(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
        if (ret)
                return ret;
 
-       return iris_inst_state_change_streamon(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
+       if (inst->sub_state & IRIS_INST_SUB_INPUT_PAUSE) {
+               ret = iris_inst_change_sub_state(inst, IRIS_INST_SUB_INPUT_PAUSE, 0);
+               if (ret)
+                       return ret;
+       }
+
+       if (inst->sub_state & IRIS_INST_SUB_DRC ||
+           inst->sub_state & IRIS_INST_SUB_FIRST_IPSC) {
+               if (!(inst->sub_state & IRIS_INST_SUB_INPUT_PAUSE)) {
+                       if (hfi_ops->session_pause) {
+                               ret = hfi_ops->session_pause(inst,
+                                                            V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
+                               if (ret)
+                                       return ret;
+                       }
+                       set_sub_state = IRIS_INST_SUB_INPUT_PAUSE;
+               }
+       }
+
+       ret = iris_inst_state_change_streamon(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
+       if (ret)
+               return ret;
+
+       return iris_inst_change_sub_state(inst, 0, set_sub_state);
 }
 
 int iris_vdec_streamon_input(struct iris_inst *inst)
@@ -398,13 +422,52 @@ int iris_vdec_streamon_input(struct iris_inst *inst)
 static int iris_vdec_process_streamon_output(struct iris_inst *inst)
 {
        const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops;
-       int ret;
+       enum iris_inst_sub_state clear_sub_state = 0;
+       bool drc_active = false;
+       int ret = 0;
+
+       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;
+
+       if (inst->sub_state & IRIS_INST_SUB_INPUT_PAUSE) {
+               ret = iris_alloc_and_queue_input_int_bufs(inst);
+               if (ret)
+                       return ret;
+               ret = iris_set_stage(inst, STAGE);
+               if (ret)
+                       return ret;
+               ret = iris_set_pipe(inst, PIPE);
+               if (ret)
+                       return ret;
+       }
+
+       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;
+               clear_sub_state |= IRIS_INST_SUB_INPUT_PAUSE;
+       }
+
+       if (inst->sub_state & IRIS_INST_SUB_FIRST_IPSC)
+               clear_sub_state |= IRIS_INST_SUB_FIRST_IPSC;
 
        ret = hfi_ops->session_start(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
        if (ret)
                return ret;
 
-       return iris_inst_state_change_streamon(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
+       if (inst->sub_state & IRIS_INST_SUB_OUTPUT_PAUSE)
+               clear_sub_state |= IRIS_INST_SUB_OUTPUT_PAUSE;
+
+       ret = iris_inst_state_change_streamon(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
+       if (ret)
+               return ret;
+
+       return iris_inst_change_sub_state(inst, clear_sub_state, 0);
 }
 
 int iris_vdec_streamon_output(struct iris_inst *inst)