1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (c) 2022-2025 Qualcomm Innovation Center, Inc. All rights reserved. 4 */ 5 6 #include <media/v4l2-mem2mem.h> 7 8 #include "iris_common.h" 9 #include "iris_ctrls.h" 10 #include "iris_instance.h" 11 #include "iris_power.h" 12 13 int iris_process_streamon_input(struct iris_inst *inst) 14 { 15 const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops; 16 enum iris_inst_sub_state set_sub_state = 0; 17 int ret; 18 19 iris_scale_power(inst); 20 21 ret = hfi_ops->session_start(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); 22 if (ret) 23 return ret; 24 25 if (inst->sub_state & IRIS_INST_SUB_INPUT_PAUSE) { 26 ret = iris_inst_change_sub_state(inst, IRIS_INST_SUB_INPUT_PAUSE, 0); 27 if (ret) 28 return ret; 29 } 30 31 if (inst->domain == DECODER && 32 (inst->sub_state & IRIS_INST_SUB_DRC || 33 inst->sub_state & IRIS_INST_SUB_DRAIN || 34 inst->sub_state & IRIS_INST_SUB_FIRST_IPSC)) { 35 if (!(inst->sub_state & IRIS_INST_SUB_INPUT_PAUSE)) { 36 if (hfi_ops->session_pause) { 37 ret = hfi_ops->session_pause(inst, 38 V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); 39 if (ret) 40 return ret; 41 } 42 set_sub_state = IRIS_INST_SUB_INPUT_PAUSE; 43 } 44 } 45 46 ret = iris_inst_state_change_streamon(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); 47 if (ret) 48 return ret; 49 50 inst->last_buffer_dequeued = false; 51 52 return iris_inst_change_sub_state(inst, 0, set_sub_state); 53 } 54 55 int iris_process_streamon_output(struct iris_inst *inst) 56 { 57 const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops; 58 bool drain_active = false, drc_active = false; 59 enum iris_inst_sub_state clear_sub_state = 0; 60 int ret = 0; 61 62 iris_scale_power(inst); 63 64 drain_active = inst->sub_state & IRIS_INST_SUB_DRAIN && 65 inst->sub_state & IRIS_INST_SUB_DRAIN_LAST; 66 67 drc_active = inst->sub_state & IRIS_INST_SUB_DRC && 68 inst->sub_state & IRIS_INST_SUB_DRC_LAST; 69 70 if (drc_active) 71 clear_sub_state = IRIS_INST_SUB_DRC | IRIS_INST_SUB_DRC_LAST; 72 else if (drain_active) 73 clear_sub_state = IRIS_INST_SUB_DRAIN | IRIS_INST_SUB_DRAIN_LAST; 74 75 if (inst->domain == DECODER && inst->sub_state & IRIS_INST_SUB_INPUT_PAUSE) { 76 ret = iris_alloc_and_queue_input_int_bufs(inst); 77 if (ret) 78 return ret; 79 ret = iris_set_stage(inst, STAGE); 80 if (ret) 81 return ret; 82 ret = iris_set_pipe(inst, PIPE); 83 if (ret) 84 return ret; 85 } 86 87 if (inst->state == IRIS_INST_INPUT_STREAMING && 88 inst->sub_state & IRIS_INST_SUB_INPUT_PAUSE) { 89 if (!drain_active) 90 ret = hfi_ops->session_resume_drc(inst, 91 V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); 92 else if (hfi_ops->session_resume_drain) 93 ret = hfi_ops->session_resume_drain(inst, 94 V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); 95 if (ret) 96 return ret; 97 clear_sub_state |= IRIS_INST_SUB_INPUT_PAUSE; 98 } 99 100 if (inst->sub_state & IRIS_INST_SUB_FIRST_IPSC) 101 clear_sub_state |= IRIS_INST_SUB_FIRST_IPSC; 102 103 ret = hfi_ops->session_start(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); 104 if (ret) 105 return ret; 106 107 if (inst->sub_state & IRIS_INST_SUB_OUTPUT_PAUSE) 108 clear_sub_state |= IRIS_INST_SUB_OUTPUT_PAUSE; 109 110 ret = iris_inst_state_change_streamon(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); 111 if (ret) 112 return ret; 113 114 inst->last_buffer_dequeued = false; 115 116 return iris_inst_change_sub_state(inst, clear_sub_state, 0); 117 } 118 119 static void iris_flush_deferred_buffers(struct iris_inst *inst, 120 enum iris_buffer_type type) 121 { 122 struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx; 123 struct v4l2_m2m_buffer *buffer, *n; 124 struct iris_buffer *buf; 125 126 if (type == BUF_INPUT) { 127 v4l2_m2m_for_each_src_buf_safe(m2m_ctx, buffer, n) { 128 buf = to_iris_buffer(&buffer->vb); 129 if (buf->attr & BUF_ATTR_DEFERRED) { 130 if (!(buf->attr & BUF_ATTR_BUFFER_DONE)) { 131 buf->attr |= BUF_ATTR_BUFFER_DONE; 132 buf->data_size = 0; 133 iris_vb2_buffer_done(inst, buf); 134 } 135 } 136 } 137 } else { 138 v4l2_m2m_for_each_dst_buf_safe(m2m_ctx, buffer, n) { 139 buf = to_iris_buffer(&buffer->vb); 140 if (buf->attr & BUF_ATTR_DEFERRED) { 141 if (!(buf->attr & BUF_ATTR_BUFFER_DONE)) { 142 buf->attr |= BUF_ATTR_BUFFER_DONE; 143 buf->data_size = 0; 144 iris_vb2_buffer_done(inst, buf); 145 } 146 } 147 } 148 } 149 } 150 151 static void iris_kill_session(struct iris_inst *inst) 152 { 153 const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops; 154 155 if (!inst->session_id) 156 return; 157 158 hfi_ops->session_close(inst); 159 iris_inst_change_state(inst, IRIS_INST_ERROR); 160 } 161 162 int iris_session_streamoff(struct iris_inst *inst, u32 plane) 163 { 164 const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops; 165 enum iris_buffer_type buffer_type; 166 int ret; 167 168 switch (plane) { 169 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: 170 buffer_type = BUF_INPUT; 171 break; 172 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: 173 buffer_type = BUF_OUTPUT; 174 break; 175 default: 176 return -EINVAL; 177 } 178 179 ret = hfi_ops->session_stop(inst, plane); 180 if (ret) 181 goto error; 182 183 ret = iris_inst_state_change_streamoff(inst, plane); 184 if (ret) 185 goto error; 186 187 iris_flush_deferred_buffers(inst, buffer_type); 188 189 return 0; 190 191 error: 192 iris_kill_session(inst); 193 iris_flush_deferred_buffers(inst, buffer_type); 194 195 return ret; 196 } 197