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