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 #include "iris_ctrls.h"
8 #include "iris_instance.h"
9 
10 static inline bool iris_valid_cap_id(enum platform_inst_fw_cap_type cap_id)
11 {
12 	return cap_id >= 1 && cap_id < INST_FW_CAP_MAX;
13 }
14 
15 static enum platform_inst_fw_cap_type iris_get_cap_id(u32 id)
16 {
17 	switch (id) {
18 	case V4L2_CID_MPEG_VIDEO_DECODER_MPEG4_DEBLOCK_FILTER:
19 		return DEBLOCK;
20 	case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
21 		return PROFILE;
22 	case V4L2_CID_MPEG_VIDEO_H264_LEVEL:
23 		return LEVEL;
24 	default:
25 		return INST_FW_CAP_MAX;
26 	}
27 }
28 
29 static u32 iris_get_v4l2_id(enum platform_inst_fw_cap_type cap_id)
30 {
31 	if (!iris_valid_cap_id(cap_id))
32 		return 0;
33 
34 	switch (cap_id) {
35 	case DEBLOCK:
36 		return V4L2_CID_MPEG_VIDEO_DECODER_MPEG4_DEBLOCK_FILTER;
37 	case PROFILE:
38 		return V4L2_CID_MPEG_VIDEO_H264_PROFILE;
39 	case LEVEL:
40 		return V4L2_CID_MPEG_VIDEO_H264_LEVEL;
41 	default:
42 		return 0;
43 	}
44 }
45 
46 static int iris_vdec_op_s_ctrl(struct v4l2_ctrl *ctrl)
47 {
48 	struct iris_inst *inst = container_of(ctrl->handler, struct iris_inst, ctrl_handler);
49 	enum platform_inst_fw_cap_type cap_id;
50 	struct platform_inst_fw_cap *cap;
51 	struct vb2_queue *q;
52 
53 	cap = &inst->fw_caps[0];
54 	cap_id = iris_get_cap_id(ctrl->id);
55 	if (!iris_valid_cap_id(cap_id))
56 		return -EINVAL;
57 
58 	q = v4l2_m2m_get_src_vq(inst->m2m_ctx);
59 	if (vb2_is_streaming(q) &&
60 	    (!(inst->fw_caps[cap_id].flags & CAP_FLAG_DYNAMIC_ALLOWED)))
61 		return -EINVAL;
62 
63 	cap[cap_id].flags |= CAP_FLAG_CLIENT_SET;
64 
65 	inst->fw_caps[cap_id].value = ctrl->val;
66 
67 	return 0;
68 }
69 
70 static const struct v4l2_ctrl_ops iris_ctrl_ops = {
71 	.s_ctrl = iris_vdec_op_s_ctrl,
72 };
73 
74 int iris_ctrls_init(struct iris_inst *inst)
75 {
76 	struct platform_inst_fw_cap *cap = &inst->fw_caps[0];
77 	u32 num_ctrls = 0, ctrl_idx = 0, idx = 0;
78 	u32 v4l2_id;
79 	int ret;
80 
81 	for (idx = 1; idx < INST_FW_CAP_MAX; idx++) {
82 		if (iris_get_v4l2_id(cap[idx].cap_id))
83 			num_ctrls++;
84 	}
85 	if (!num_ctrls)
86 		return -EINVAL;
87 
88 	/* Adding 1 to num_ctrls to include V4L2_CID_MIN_BUFFERS_FOR_CAPTURE */
89 
90 	ret = v4l2_ctrl_handler_init(&inst->ctrl_handler, num_ctrls + 1);
91 	if (ret)
92 		return ret;
93 
94 	for (idx = 1; idx < INST_FW_CAP_MAX; idx++) {
95 		struct v4l2_ctrl *ctrl;
96 
97 		v4l2_id = iris_get_v4l2_id(cap[idx].cap_id);
98 		if (!v4l2_id)
99 			continue;
100 
101 		if (ctrl_idx >= num_ctrls) {
102 			ret = -EINVAL;
103 			goto error;
104 		}
105 
106 		if (cap[idx].flags & CAP_FLAG_MENU) {
107 			ctrl = v4l2_ctrl_new_std_menu(&inst->ctrl_handler,
108 						      &iris_ctrl_ops,
109 						      v4l2_id,
110 						      cap[idx].max,
111 						      ~(cap[idx].step_or_mask),
112 						      cap[idx].value);
113 		} else {
114 			ctrl = v4l2_ctrl_new_std(&inst->ctrl_handler,
115 						 &iris_ctrl_ops,
116 						 v4l2_id,
117 						 cap[idx].min,
118 						 cap[idx].max,
119 						 cap[idx].step_or_mask,
120 						 cap[idx].value);
121 		}
122 		if (!ctrl) {
123 			ret = -EINVAL;
124 			goto error;
125 		}
126 
127 		ctrl_idx++;
128 	}
129 
130 	v4l2_ctrl_new_std(&inst->ctrl_handler, NULL,
131 			  V4L2_CID_MIN_BUFFERS_FOR_CAPTURE, 1, 32, 1, 4);
132 
133 	ret = inst->ctrl_handler.error;
134 	if (ret)
135 		goto error;
136 
137 	return 0;
138 error:
139 	v4l2_ctrl_handler_free(&inst->ctrl_handler);
140 
141 	return ret;
142 }
143 
144 void iris_session_init_caps(struct iris_core *core)
145 {
146 	struct platform_inst_fw_cap *caps;
147 	u32 i, num_cap, cap_id;
148 
149 	caps = core->iris_platform_data->inst_fw_caps;
150 	num_cap = core->iris_platform_data->inst_fw_caps_size;
151 
152 	for (i = 0; i < num_cap; i++) {
153 		cap_id = caps[i].cap_id;
154 		if (!iris_valid_cap_id(cap_id))
155 			continue;
156 
157 		core->inst_fw_caps[cap_id].cap_id = caps[i].cap_id;
158 		core->inst_fw_caps[cap_id].min = caps[i].min;
159 		core->inst_fw_caps[cap_id].max = caps[i].max;
160 		core->inst_fw_caps[cap_id].step_or_mask = caps[i].step_or_mask;
161 		core->inst_fw_caps[cap_id].value = caps[i].value;
162 		core->inst_fw_caps[cap_id].flags = caps[i].flags;
163 		core->inst_fw_caps[cap_id].hfi_id = caps[i].hfi_id;
164 	}
165 }
166