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
iris_valid_cap_id(enum platform_inst_fw_cap_type cap_id)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
iris_get_cap_id(u32 id)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
iris_get_v4l2_id(enum platform_inst_fw_cap_type cap_id)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
iris_vdec_op_s_ctrl(struct v4l2_ctrl * ctrl)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
iris_ctrls_init(struct iris_inst * inst)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
iris_session_init_caps(struct iris_core * core)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
iris_get_port_info(struct iris_inst * inst,enum platform_inst_fw_cap_type cap_id)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
iris_set_u32_enum(struct iris_inst * inst,enum platform_inst_fw_cap_type cap_id)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
iris_set_u32(struct iris_inst * inst,enum platform_inst_fw_cap_type cap_id)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
iris_set_stage(struct iris_inst * inst,enum platform_inst_fw_cap_type cap_id)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
iris_set_pipe(struct iris_inst * inst,enum platform_inst_fw_cap_type cap_id)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
iris_set_properties(struct iris_inst * inst,u32 plane)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