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 <linux/types.h> 7 #include <media/v4l2-mem2mem.h> 8 9 #include "iris_ctrls.h" 10 #include "iris_instance.h" 11 12 static inline bool iris_valid_cap_id(enum platform_inst_fw_cap_type cap_id) 13 { 14 return cap_id >= 1 && cap_id < INST_FW_CAP_MAX; 15 } 16 17 static enum platform_inst_fw_cap_type iris_get_cap_id(u32 id) 18 { 19 switch (id) { 20 case V4L2_CID_MPEG_VIDEO_DECODER_MPEG4_DEBLOCK_FILTER: 21 return DEBLOCK; 22 case V4L2_CID_MPEG_VIDEO_H264_PROFILE: 23 return PROFILE; 24 case V4L2_CID_MPEG_VIDEO_H264_LEVEL: 25 return LEVEL; 26 default: 27 return INST_FW_CAP_MAX; 28 } 29 } 30 31 static u32 iris_get_v4l2_id(enum platform_inst_fw_cap_type cap_id) 32 { 33 if (!iris_valid_cap_id(cap_id)) 34 return 0; 35 36 switch (cap_id) { 37 case DEBLOCK: 38 return V4L2_CID_MPEG_VIDEO_DECODER_MPEG4_DEBLOCK_FILTER; 39 case PROFILE: 40 return V4L2_CID_MPEG_VIDEO_H264_PROFILE; 41 case LEVEL: 42 return V4L2_CID_MPEG_VIDEO_H264_LEVEL; 43 default: 44 return 0; 45 } 46 } 47 48 static int iris_vdec_op_s_ctrl(struct v4l2_ctrl *ctrl) 49 { 50 struct iris_inst *inst = container_of(ctrl->handler, struct iris_inst, ctrl_handler); 51 enum platform_inst_fw_cap_type cap_id; 52 struct platform_inst_fw_cap *cap; 53 struct vb2_queue *q; 54 55 cap = &inst->fw_caps[0]; 56 cap_id = iris_get_cap_id(ctrl->id); 57 if (!iris_valid_cap_id(cap_id)) 58 return -EINVAL; 59 60 q = v4l2_m2m_get_src_vq(inst->m2m_ctx); 61 if (vb2_is_streaming(q) && 62 (!(inst->fw_caps[cap_id].flags & CAP_FLAG_DYNAMIC_ALLOWED))) 63 return -EINVAL; 64 65 cap[cap_id].flags |= CAP_FLAG_CLIENT_SET; 66 67 inst->fw_caps[cap_id].value = ctrl->val; 68 69 return 0; 70 } 71 72 static const struct v4l2_ctrl_ops iris_ctrl_ops = { 73 .s_ctrl = iris_vdec_op_s_ctrl, 74 }; 75 76 int iris_ctrls_init(struct iris_inst *inst) 77 { 78 struct platform_inst_fw_cap *cap = &inst->fw_caps[0]; 79 u32 num_ctrls = 0, ctrl_idx = 0, idx = 0; 80 u32 v4l2_id; 81 int ret; 82 83 for (idx = 1; idx < INST_FW_CAP_MAX; idx++) { 84 if (iris_get_v4l2_id(cap[idx].cap_id)) 85 num_ctrls++; 86 } 87 if (!num_ctrls) 88 return -EINVAL; 89 90 /* Adding 1 to num_ctrls to include V4L2_CID_MIN_BUFFERS_FOR_CAPTURE */ 91 92 ret = v4l2_ctrl_handler_init(&inst->ctrl_handler, num_ctrls + 1); 93 if (ret) 94 return ret; 95 96 for (idx = 1; idx < INST_FW_CAP_MAX; idx++) { 97 struct v4l2_ctrl *ctrl; 98 99 v4l2_id = iris_get_v4l2_id(cap[idx].cap_id); 100 if (!v4l2_id) 101 continue; 102 103 if (ctrl_idx >= num_ctrls) { 104 ret = -EINVAL; 105 goto error; 106 } 107 108 if (cap[idx].flags & CAP_FLAG_MENU) { 109 ctrl = v4l2_ctrl_new_std_menu(&inst->ctrl_handler, 110 &iris_ctrl_ops, 111 v4l2_id, 112 cap[idx].max, 113 ~(cap[idx].step_or_mask), 114 cap[idx].value); 115 } else { 116 ctrl = v4l2_ctrl_new_std(&inst->ctrl_handler, 117 &iris_ctrl_ops, 118 v4l2_id, 119 cap[idx].min, 120 cap[idx].max, 121 cap[idx].step_or_mask, 122 cap[idx].value); 123 } 124 if (!ctrl) { 125 ret = -EINVAL; 126 goto error; 127 } 128 129 ctrl_idx++; 130 } 131 132 v4l2_ctrl_new_std(&inst->ctrl_handler, NULL, 133 V4L2_CID_MIN_BUFFERS_FOR_CAPTURE, 1, 32, 1, 4); 134 135 ret = inst->ctrl_handler.error; 136 if (ret) 137 goto error; 138 139 return 0; 140 error: 141 v4l2_ctrl_handler_free(&inst->ctrl_handler); 142 143 return ret; 144 } 145 146 void iris_session_init_caps(struct iris_core *core) 147 { 148 struct platform_inst_fw_cap *caps; 149 u32 i, num_cap, cap_id; 150 151 caps = core->iris_platform_data->inst_fw_caps; 152 num_cap = core->iris_platform_data->inst_fw_caps_size; 153 154 for (i = 0; i < num_cap; i++) { 155 cap_id = caps[i].cap_id; 156 if (!iris_valid_cap_id(cap_id)) 157 continue; 158 159 core->inst_fw_caps[cap_id].cap_id = caps[i].cap_id; 160 core->inst_fw_caps[cap_id].min = caps[i].min; 161 core->inst_fw_caps[cap_id].max = caps[i].max; 162 core->inst_fw_caps[cap_id].step_or_mask = caps[i].step_or_mask; 163 core->inst_fw_caps[cap_id].value = caps[i].value; 164 core->inst_fw_caps[cap_id].flags = caps[i].flags; 165 core->inst_fw_caps[cap_id].hfi_id = caps[i].hfi_id; 166 } 167 } 168 169 static u32 iris_get_port_info(struct iris_inst *inst, 170 enum platform_inst_fw_cap_type cap_id) 171 { 172 if (inst->fw_caps[cap_id].flags & CAP_FLAG_INPUT_PORT) 173 return HFI_PORT_BITSTREAM; 174 else if (inst->fw_caps[cap_id].flags & CAP_FLAG_OUTPUT_PORT) 175 return HFI_PORT_RAW; 176 177 return HFI_PORT_NONE; 178 } 179 180 int iris_set_u32_enum(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id) 181 { 182 const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops; 183 u32 hfi_value = inst->fw_caps[cap_id].value; 184 u32 hfi_id = inst->fw_caps[cap_id].hfi_id; 185 186 return hfi_ops->session_set_property(inst, hfi_id, 187 HFI_HOST_FLAGS_NONE, 188 iris_get_port_info(inst, cap_id), 189 HFI_PAYLOAD_U32_ENUM, 190 &hfi_value, sizeof(u32)); 191 } 192 193 int iris_set_u32(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id) 194 { 195 const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops; 196 u32 hfi_value = inst->fw_caps[cap_id].value; 197 u32 hfi_id = inst->fw_caps[cap_id].hfi_id; 198 199 return hfi_ops->session_set_property(inst, hfi_id, 200 HFI_HOST_FLAGS_NONE, 201 iris_get_port_info(inst, cap_id), 202 HFI_PAYLOAD_U32, 203 &hfi_value, sizeof(u32)); 204 } 205 206 int iris_set_stage(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id) 207 { 208 const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops; 209 struct v4l2_format *inp_f = inst->fmt_src; 210 u32 hfi_id = inst->fw_caps[cap_id].hfi_id; 211 u32 height = inp_f->fmt.pix_mp.height; 212 u32 width = inp_f->fmt.pix_mp.width; 213 u32 work_mode = STAGE_2; 214 215 if (iris_res_is_less_than(width, height, 1280, 720)) 216 work_mode = STAGE_1; 217 218 return hfi_ops->session_set_property(inst, hfi_id, 219 HFI_HOST_FLAGS_NONE, 220 iris_get_port_info(inst, cap_id), 221 HFI_PAYLOAD_U32, 222 &work_mode, sizeof(u32)); 223 } 224 225 int iris_set_pipe(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id) 226 { 227 const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops; 228 u32 work_route = inst->fw_caps[PIPE].value; 229 u32 hfi_id = inst->fw_caps[cap_id].hfi_id; 230 231 return hfi_ops->session_set_property(inst, hfi_id, 232 HFI_HOST_FLAGS_NONE, 233 iris_get_port_info(inst, cap_id), 234 HFI_PAYLOAD_U32, 235 &work_route, sizeof(u32)); 236 } 237 238 int iris_set_properties(struct iris_inst *inst, u32 plane) 239 { 240 const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops; 241 struct platform_inst_fw_cap *cap; 242 int ret; 243 u32 i; 244 245 ret = hfi_ops->session_set_config_params(inst, plane); 246 if (ret) 247 return ret; 248 249 for (i = 1; i < INST_FW_CAP_MAX; i++) { 250 cap = &inst->fw_caps[i]; 251 if (!iris_valid_cap_id(cap->cap_id)) 252 continue; 253 254 if (cap->cap_id && cap->set) 255 cap->set(inst, i); 256 } 257 258 return 0; 259 } 260