FILE
iris_state.c
File preview with syntax highlighting.
linux-6.19.14/drivers/media/platform/qcom/iris/iris_state.c
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. 4 */ 5 6#include <media/v4l2-mem2mem.h> 7 8#include "iris_instance.h" 9 10static bool iris_allow_inst_state_change(struct iris_inst *inst, 11 enum iris_inst_state req_state) 12{ 13 switch (inst->state) { 14 case IRIS_INST_INIT: 15 if (req_state == IRIS_INST_INPUT_STREAMING || 16 req_state == IRIS_INST_OUTPUT_STREAMING || 17 req_state == IRIS_INST_DEINIT) 18 return true; 19 return false; 20 case IRIS_INST_INPUT_STREAMING: 21 if (req_state == IRIS_INST_INIT || 22 req_state == IRIS_INST_STREAMING || 23 req_state == IRIS_INST_DEINIT) 24 return true; 25 return false; 26 case IRIS_INST_OUTPUT_STREAMING: 27 if (req_state == IRIS_INST_INIT || 28 req_state == IRIS_INST_STREAMING || 29 req_state == IRIS_INST_DEINIT) 30 return true; 31 return false; 32 case IRIS_INST_STREAMING: 33 if (req_state == IRIS_INST_INPUT_STREAMING || 34 req_state == IRIS_INST_OUTPUT_STREAMING || 35 req_state == IRIS_INST_DEINIT) 36 return true; 37 return false; 38 case IRIS_INST_DEINIT: 39 if (req_state == IRIS_INST_INIT) 40 return true; 41 return false; 42 default: 43 return false; 44 } 45} 46 47int iris_inst_change_state(struct iris_inst *inst, 48 enum iris_inst_state request_state) 49{ 50 if (inst->state == IRIS_INST_ERROR) 51 return 0; 52 53 if (inst->state == request_state) 54 return 0; 55 56 if (request_state == IRIS_INST_ERROR) 57 goto change_state; 58 59 if (!iris_allow_inst_state_change(inst, request_state)) 60 return -EINVAL; 61 62change_state: 63 inst->state = request_state; 64 dev_dbg(inst->core->dev, "state changed from %x to %x\n", 65 inst->state, request_state); 66 67 return 0; 68} 69 70int iris_inst_state_change_streamon(struct iris_inst *inst, u32 plane) 71{ 72 enum iris_inst_state new_state = IRIS_INST_ERROR; 73 74 if (V4L2_TYPE_IS_OUTPUT(plane)) { 75 if (inst->state == IRIS_INST_INIT) 76 new_state = IRIS_INST_INPUT_STREAMING; 77 else if (inst->state == IRIS_INST_OUTPUT_STREAMING) 78 new_state = IRIS_INST_STREAMING; 79 } else if (V4L2_TYPE_IS_CAPTURE(plane)) { 80 if (inst->state == IRIS_INST_INIT) 81 new_state = IRIS_INST_OUTPUT_STREAMING; 82 else if (inst->state == IRIS_INST_INPUT_STREAMING) 83 new_state = IRIS_INST_STREAMING; 84 } 85 86 return iris_inst_change_state(inst, new_state); 87} 88 89int iris_inst_state_change_streamoff(struct iris_inst *inst, u32 plane) 90{ 91 enum iris_inst_state new_state = IRIS_INST_ERROR; 92 93 if (V4L2_TYPE_IS_OUTPUT(plane)) { 94 if (inst->state == IRIS_INST_INPUT_STREAMING) 95 new_state = IRIS_INST_INIT; 96 else if (inst->state == IRIS_INST_STREAMING) 97 new_state = IRIS_INST_OUTPUT_STREAMING; 98 } else if (V4L2_TYPE_IS_CAPTURE(plane)) { 99 if (inst->state == IRIS_INST_OUTPUT_STREAMING) 100 new_state = IRIS_INST_INIT; 101 else if (inst->state == IRIS_INST_STREAMING) 102 new_state = IRIS_INST_INPUT_STREAMING; 103 } 104 105 return iris_inst_change_state(inst, new_state); 106} 107 108static bool iris_inst_allow_sub_state(struct iris_inst *inst, enum iris_inst_sub_state sub_state) 109{ 110 if (!sub_state) 111 return true; 112 113 switch (inst->state) { 114 case IRIS_INST_INIT: 115 if (sub_state & IRIS_INST_SUB_LOAD_RESOURCES) 116 return true; 117 return false; 118 case IRIS_INST_INPUT_STREAMING: 119 if (sub_state & (IRIS_INST_SUB_FIRST_IPSC | IRIS_INST_SUB_DRC | 120 IRIS_INST_SUB_DRAIN | IRIS_INST_SUB_INPUT_PAUSE)) 121 return true; 122 return false; 123 case IRIS_INST_OUTPUT_STREAMING: 124 if (sub_state & (IRIS_INST_SUB_DRC_LAST | 125 IRIS_INST_SUB_DRAIN_LAST | IRIS_INST_SUB_OUTPUT_PAUSE | 126 IRIS_INST_SUB_LOAD_RESOURCES)) 127 return true; 128 return false; 129 case IRIS_INST_STREAMING: 130 if (sub_state & (IRIS_INST_SUB_DRC | IRIS_INST_SUB_DRAIN | 131 IRIS_INST_SUB_DRC_LAST | IRIS_INST_SUB_DRAIN_LAST | 132 IRIS_INST_SUB_INPUT_PAUSE | IRIS_INST_SUB_OUTPUT_PAUSE)) 133 return true; 134 return false; 135 case IRIS_INST_DEINIT: 136 if (sub_state & (IRIS_INST_SUB_DRC | IRIS_INST_SUB_DRAIN | 137 IRIS_INST_SUB_DRC_LAST | IRIS_INST_SUB_DRAIN_LAST | 138 IRIS_INST_SUB_INPUT_PAUSE | IRIS_INST_SUB_OUTPUT_PAUSE)) 139 return true; 140 return false; 141 default: 142 return false; 143 } 144} 145 146int iris_inst_change_sub_state(struct iris_inst *inst, 147 enum iris_inst_sub_state clear_sub_state, 148 enum iris_inst_sub_state set_sub_state) 149{ 150 enum iris_inst_sub_state prev_sub_state; 151 152 if (inst->state == IRIS_INST_ERROR) 153 return 0; 154 155 if (!clear_sub_state && !set_sub_state) 156 return 0; 157 158 if ((clear_sub_state & set_sub_state) || 159 set_sub_state > IRIS_INST_MAX_SUB_STATE_VALUE || 160 clear_sub_state > IRIS_INST_MAX_SUB_STATE_VALUE) 161 return -EINVAL; 162 163 prev_sub_state = inst->sub_state; 164 165 if (!iris_inst_allow_sub_state(inst, set_sub_state)) 166 return -EINVAL; 167 168 inst->sub_state |= set_sub_state; 169 inst->sub_state &= ~clear_sub_state; 170 171 if (inst->sub_state != prev_sub_state) 172 dev_dbg(inst->core->dev, "sub_state changed from %x to %x\n", 173 prev_sub_state, inst->sub_state); 174 175 return 0; 176} 177 178int iris_inst_sub_state_change_drc(struct iris_inst *inst) 179{ 180 enum iris_inst_sub_state set_sub_state = 0; 181 182 if (inst->sub_state & IRIS_INST_SUB_DRC) 183 return -EINVAL; 184 185 if (inst->state == IRIS_INST_INPUT_STREAMING || 186 inst->state == IRIS_INST_INIT) 187 set_sub_state = IRIS_INST_SUB_FIRST_IPSC | IRIS_INST_SUB_INPUT_PAUSE; 188 else 189 set_sub_state = IRIS_INST_SUB_DRC | IRIS_INST_SUB_INPUT_PAUSE; 190 191 return iris_inst_change_sub_state(inst, 0, set_sub_state); 192} 193 194int iris_inst_sub_state_change_drain_last(struct iris_inst *inst) 195{ 196 enum iris_inst_sub_state set_sub_state; 197 198 if (inst->sub_state & IRIS_INST_SUB_DRAIN_LAST) 199 return -EINVAL; 200 201 if (!(inst->sub_state & IRIS_INST_SUB_DRAIN)) 202 return -EINVAL; 203 204 set_sub_state = IRIS_INST_SUB_DRAIN_LAST | IRIS_INST_SUB_OUTPUT_PAUSE; 205 206 return iris_inst_change_sub_state(inst, 0, set_sub_state); 207} 208 209int iris_inst_sub_state_change_drc_last(struct iris_inst *inst) 210{ 211 enum iris_inst_sub_state set_sub_state; 212 213 if (inst->sub_state & IRIS_INST_SUB_DRC_LAST) 214 return -EINVAL; 215 216 if (!(inst->sub_state & IRIS_INST_SUB_DRC) || 217 !(inst->sub_state & IRIS_INST_SUB_INPUT_PAUSE)) 218 return -EINVAL; 219 220 if (inst->sub_state & IRIS_INST_SUB_FIRST_IPSC) 221 return 0; 222 223 set_sub_state = IRIS_INST_SUB_DRC_LAST | IRIS_INST_SUB_OUTPUT_PAUSE; 224 225 return iris_inst_change_sub_state(inst, 0, set_sub_state); 226} 227 228int iris_inst_sub_state_change_pause(struct iris_inst *inst, u32 plane) 229{ 230 enum iris_inst_sub_state set_sub_state; 231 232 if (V4L2_TYPE_IS_OUTPUT(plane)) { 233 if (inst->sub_state & IRIS_INST_SUB_DRC && 234 !(inst->sub_state & IRIS_INST_SUB_DRC_LAST)) 235 return -EINVAL; 236 237 if (inst->sub_state & IRIS_INST_SUB_DRAIN && 238 !(inst->sub_state & IRIS_INST_SUB_DRAIN_LAST)) 239 return -EINVAL; 240 241 set_sub_state = IRIS_INST_SUB_INPUT_PAUSE; 242 } else { 243 set_sub_state = IRIS_INST_SUB_OUTPUT_PAUSE; 244 } 245 246 return iris_inst_change_sub_state(inst, 0, set_sub_state); 247} 248 249bool iris_drc_pending(struct iris_inst *inst) 250{ 251 return inst->sub_state & IRIS_INST_SUB_DRC && 252 inst->sub_state & IRIS_INST_SUB_DRC_LAST; 253} 254 255bool iris_drain_pending(struct iris_inst *inst) 256{ 257 return inst->sub_state & IRIS_INST_SUB_DRAIN && 258 inst->sub_state & IRIS_INST_SUB_DRAIN_LAST; 259} 260 261bool iris_allow_cmd(struct iris_inst *inst, u32 cmd) 262{ 263 struct vb2_queue *src_q = v4l2_m2m_get_src_vq(inst->m2m_ctx); 264 struct vb2_queue *dst_q = v4l2_m2m_get_dst_vq(inst->m2m_ctx); 265 266 if (cmd == V4L2_DEC_CMD_START || cmd == V4L2_ENC_CMD_START) { 267 if (vb2_is_streaming(src_q) || vb2_is_streaming(dst_q)) 268 if (iris_drc_pending(inst) || iris_drain_pending(inst)) 269 return true; 270 } else if (cmd == V4L2_DEC_CMD_STOP || cmd == V4L2_ENC_CMD_STOP) { 271 if (vb2_is_streaming(src_q)) 272 if (inst->sub_state != IRIS_INST_SUB_DRAIN) 273 return true; 274 } 275 276 return false; 277}
~/
Read-only file preview.