1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
4  * Copyright (C) 2017 Linaro Ltd.
5  */
6 #include <linux/types.h>
7 #include <media/v4l2-ctrls.h>
8 
9 #include "core.h"
10 #include "helpers.h"
11 #include "vdec.h"
12 
13 static int vdec_op_s_ctrl(struct v4l2_ctrl *ctrl)
14 {
15 	struct venus_inst *inst = ctrl_to_inst(ctrl);
16 	struct vdec_controls *ctr = &inst->controls.dec;
17 
18 	switch (ctrl->id) {
19 	case V4L2_CID_MPEG_VIDEO_DECODER_MPEG4_DEBLOCK_FILTER:
20 		ctr->post_loop_deb_mode = ctrl->val;
21 		break;
22 	case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
23 	case V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE:
24 	case V4L2_CID_MPEG_VIDEO_VP8_PROFILE:
25 	case V4L2_CID_MPEG_VIDEO_VP9_PROFILE:
26 		ctr->profile = ctrl->val;
27 		break;
28 	case V4L2_CID_MPEG_VIDEO_H264_LEVEL:
29 	case V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL:
30 	case V4L2_CID_MPEG_VIDEO_VP9_LEVEL:
31 		ctr->level = ctrl->val;
32 		break;
33 	case V4L2_CID_MPEG_VIDEO_DEC_DISPLAY_DELAY:
34 		ctr->display_delay = ctrl->val;
35 		break;
36 	case V4L2_CID_MPEG_VIDEO_DEC_DISPLAY_DELAY_ENABLE:
37 		ctr->display_delay_enable = ctrl->val;
38 		break;
39 	default:
40 		return -EINVAL;
41 	}
42 
43 	return 0;
44 }
45 
46 static int vdec_op_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
47 {
48 	struct venus_inst *inst = ctrl_to_inst(ctrl);
49 	struct vdec_controls *ctr = &inst->controls.dec;
50 	struct hfi_buffer_requirements bufreq;
51 	enum hfi_version ver = inst->core->res->hfi_version;
52 	u32 profile, level;
53 	int ret;
54 
55 	switch (ctrl->id) {
56 	case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
57 	case V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE:
58 	case V4L2_CID_MPEG_VIDEO_VP8_PROFILE:
59 	case V4L2_CID_MPEG_VIDEO_VP9_PROFILE:
60 		ret = venus_helper_get_profile_level(inst, &profile, &level);
61 		if (!ret)
62 			ctr->profile = profile;
63 		ctrl->val = ctr->profile;
64 		break;
65 	case V4L2_CID_MPEG_VIDEO_H264_LEVEL:
66 	case V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL:
67 	case V4L2_CID_MPEG_VIDEO_VP9_LEVEL:
68 		ret = venus_helper_get_profile_level(inst, &profile, &level);
69 		if (!ret)
70 			ctr->level = level;
71 		ctrl->val = ctr->level;
72 		break;
73 	case V4L2_CID_MPEG_VIDEO_DECODER_MPEG4_DEBLOCK_FILTER:
74 		ctrl->val = ctr->post_loop_deb_mode;
75 		break;
76 	case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE:
77 		ret = venus_helper_get_bufreq(inst, HFI_BUFFER_OUTPUT, &bufreq);
78 		if (!ret)
79 			ctrl->val = HFI_BUFREQ_COUNT_MIN(&bufreq, ver);
80 		break;
81 	default:
82 		return -EINVAL;
83 	}
84 
85 	return 0;
86 }
87 
88 static const struct v4l2_ctrl_ops vdec_ctrl_ops = {
89 	.s_ctrl = vdec_op_s_ctrl,
90 	.g_volatile_ctrl = vdec_op_g_volatile_ctrl,
91 };
92 
93 int vdec_ctrl_init(struct venus_inst *inst)
94 {
95 	struct v4l2_ctrl *ctrl;
96 	int ret;
97 
98 	ret = v4l2_ctrl_handler_init(&inst->ctrl_handler, 11);
99 	if (ret)
100 		return ret;
101 
102 	ctrl = v4l2_ctrl_new_std_menu(&inst->ctrl_handler, &vdec_ctrl_ops,
103 		V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE,
104 		V4L2_MPEG_VIDEO_MPEG4_PROFILE_ADVANCED_CODING_EFFICIENCY,
105 		~((1 << V4L2_MPEG_VIDEO_MPEG4_PROFILE_SIMPLE) |
106 		  (1 << V4L2_MPEG_VIDEO_MPEG4_PROFILE_ADVANCED_SIMPLE)),
107 		V4L2_MPEG_VIDEO_MPEG4_PROFILE_SIMPLE);
108 	if (ctrl)
109 		ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
110 
111 	ctrl = v4l2_ctrl_new_std_menu(&inst->ctrl_handler, &vdec_ctrl_ops,
112 				      V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL,
113 				      V4L2_MPEG_VIDEO_MPEG4_LEVEL_5,
114 				      0, V4L2_MPEG_VIDEO_MPEG4_LEVEL_0);
115 	if (ctrl)
116 		ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
117 
118 	ctrl = v4l2_ctrl_new_std_menu(&inst->ctrl_handler, &vdec_ctrl_ops,
119 		V4L2_CID_MPEG_VIDEO_H264_PROFILE,
120 		V4L2_MPEG_VIDEO_H264_PROFILE_MULTIVIEW_HIGH,
121 		~((1 << V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE) |
122 		  (1 << V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE) |
123 		  (1 << V4L2_MPEG_VIDEO_H264_PROFILE_MAIN) |
124 		  (1 << V4L2_MPEG_VIDEO_H264_PROFILE_HIGH) |
125 		  (1 << V4L2_MPEG_VIDEO_H264_PROFILE_STEREO_HIGH) |
126 		  (1 << V4L2_MPEG_VIDEO_H264_PROFILE_MULTIVIEW_HIGH)),
127 		V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE);
128 	if (ctrl)
129 		ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
130 
131 	ctrl = v4l2_ctrl_new_std_menu(&inst->ctrl_handler, &vdec_ctrl_ops,
132 				      V4L2_CID_MPEG_VIDEO_H264_LEVEL,
133 				      V4L2_MPEG_VIDEO_H264_LEVEL_5_1,
134 				      0, V4L2_MPEG_VIDEO_H264_LEVEL_1_0);
135 	if (ctrl)
136 		ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
137 
138 	ctrl = v4l2_ctrl_new_std_menu(&inst->ctrl_handler, &vdec_ctrl_ops,
139 				      V4L2_CID_MPEG_VIDEO_VP8_PROFILE,
140 				      V4L2_MPEG_VIDEO_VP8_PROFILE_3,
141 				      0, V4L2_MPEG_VIDEO_VP8_PROFILE_0);
142 	if (ctrl)
143 		ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
144 
145 	ctrl = v4l2_ctrl_new_std_menu(&inst->ctrl_handler, &vdec_ctrl_ops,
146 				      V4L2_CID_MPEG_VIDEO_VP9_PROFILE,
147 				      V4L2_MPEG_VIDEO_VP9_PROFILE_3,
148 				      0, V4L2_MPEG_VIDEO_VP9_PROFILE_0);
149 	if (ctrl)
150 		ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
151 
152 	ctrl = v4l2_ctrl_new_std_menu(&inst->ctrl_handler, &vdec_ctrl_ops,
153 				      V4L2_CID_MPEG_VIDEO_VP9_LEVEL,
154 				      V4L2_MPEG_VIDEO_VP9_LEVEL_6_2,
155 				      0, V4L2_MPEG_VIDEO_VP9_LEVEL_1_0);
156 	if (ctrl)
157 		ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
158 
159 	v4l2_ctrl_new_std(&inst->ctrl_handler, &vdec_ctrl_ops,
160 		V4L2_CID_MPEG_VIDEO_DECODER_MPEG4_DEBLOCK_FILTER, 0, 1, 1, 0);
161 
162 	ctrl = v4l2_ctrl_new_std(&inst->ctrl_handler, &vdec_ctrl_ops,
163 		V4L2_CID_MIN_BUFFERS_FOR_CAPTURE, 1, 32, 1, 1);
164 	if (ctrl)
165 		ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
166 
167 	v4l2_ctrl_new_std(&inst->ctrl_handler, &vdec_ctrl_ops,
168 			  V4L2_CID_MPEG_VIDEO_DEC_DISPLAY_DELAY,
169 			  0, 16383, 1, 0);
170 
171 	v4l2_ctrl_new_std(&inst->ctrl_handler, &vdec_ctrl_ops,
172 			  V4L2_CID_MPEG_VIDEO_DEC_DISPLAY_DELAY_ENABLE,
173 			  0, 1, 1, 0);
174 
175 	ret = inst->ctrl_handler.error;
176 	if (ret) {
177 		v4l2_ctrl_handler_free(&inst->ctrl_handler);
178 		return ret;
179 	}
180 
181 	return 0;
182 }
183 
184 void vdec_ctrl_deinit(struct venus_inst *inst)
185 {
186 	v4l2_ctrl_handler_free(&inst->ctrl_handler);
187 }
188