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
13static 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	case V4L2_CID_MPEG_VIDEO_DEC_CONCEAL_COLOR:
40		ctr->conceal_color = *ctrl->p_new.p_s64;
41		break;
42	default:
43		return -EINVAL;
44	}
45
46	return 0;
47}
48
49static int vdec_op_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
50{
51	struct venus_inst *inst = ctrl_to_inst(ctrl);
52	struct vdec_controls *ctr = &inst->controls.dec;
53	struct hfi_buffer_requirements bufreq;
54	enum hfi_version ver = inst->core->res->hfi_version;
55	u32 profile, level;
56	int ret;
57
58	switch (ctrl->id) {
59	case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
60	case V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE:
61	case V4L2_CID_MPEG_VIDEO_VP8_PROFILE:
62	case V4L2_CID_MPEG_VIDEO_VP9_PROFILE:
63		ret = venus_helper_get_profile_level(inst, &profile, &level);
64		if (!ret)
65			ctr->profile = profile;
66		ctrl->val = ctr->profile;
67		break;
68	case V4L2_CID_MPEG_VIDEO_H264_LEVEL:
69	case V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL:
70	case V4L2_CID_MPEG_VIDEO_VP9_LEVEL:
71		ret = venus_helper_get_profile_level(inst, &profile, &level);
72		if (!ret)
73			ctr->level = level;
74		ctrl->val = ctr->level;
75		break;
76	case V4L2_CID_MPEG_VIDEO_DECODER_MPEG4_DEBLOCK_FILTER:
77		ctrl->val = ctr->post_loop_deb_mode;
78		break;
79	case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE:
80		ret = venus_helper_get_bufreq(inst, HFI_BUFFER_OUTPUT, &bufreq);
81		if (!ret)
82			ctrl->val = hfi_bufreq_get_count_min(&bufreq, ver);
83		break;
84	default:
85		return -EINVAL;
86	}
87
88	return 0;
89}
90
91static const struct v4l2_ctrl_ops vdec_ctrl_ops = {
92	.s_ctrl = vdec_op_s_ctrl,
93	.g_volatile_ctrl = vdec_op_g_volatile_ctrl,
94};
95
96int vdec_ctrl_init(struct venus_inst *inst)
97{
98	struct v4l2_ctrl *ctrl;
99	int ret;
100
101	ret = v4l2_ctrl_handler_init(&inst->ctrl_handler, 12);
102	if (ret)
103		return ret;
104
105	ctrl = v4l2_ctrl_new_std_menu(&inst->ctrl_handler, &vdec_ctrl_ops,
106		V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE,
107		V4L2_MPEG_VIDEO_MPEG4_PROFILE_ADVANCED_CODING_EFFICIENCY,
108		~((1 << V4L2_MPEG_VIDEO_MPEG4_PROFILE_SIMPLE) |
109		  (1 << V4L2_MPEG_VIDEO_MPEG4_PROFILE_ADVANCED_SIMPLE)),
110		V4L2_MPEG_VIDEO_MPEG4_PROFILE_SIMPLE);
111	if (ctrl)
112		ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
113
114	ctrl = v4l2_ctrl_new_std_menu(&inst->ctrl_handler, &vdec_ctrl_ops,
115				      V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL,
116				      V4L2_MPEG_VIDEO_MPEG4_LEVEL_5,
117				      0, V4L2_MPEG_VIDEO_MPEG4_LEVEL_0);
118	if (ctrl)
119		ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
120
121	ctrl = v4l2_ctrl_new_std_menu(&inst->ctrl_handler, &vdec_ctrl_ops,
122		V4L2_CID_MPEG_VIDEO_H264_PROFILE,
123		V4L2_MPEG_VIDEO_H264_PROFILE_MULTIVIEW_HIGH,
124		~((1 << V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE) |
125		  (1 << V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE) |
126		  (1 << V4L2_MPEG_VIDEO_H264_PROFILE_MAIN) |
127		  (1 << V4L2_MPEG_VIDEO_H264_PROFILE_HIGH) |
128		  (1 << V4L2_MPEG_VIDEO_H264_PROFILE_STEREO_HIGH) |
129		  (1 << V4L2_MPEG_VIDEO_H264_PROFILE_MULTIVIEW_HIGH)),
130		V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE);
131	if (ctrl)
132		ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
133
134	ctrl = v4l2_ctrl_new_std_menu(&inst->ctrl_handler, &vdec_ctrl_ops,
135				      V4L2_CID_MPEG_VIDEO_H264_LEVEL,
136				      V4L2_MPEG_VIDEO_H264_LEVEL_5_1,
137				      0, V4L2_MPEG_VIDEO_H264_LEVEL_1_0);
138	if (ctrl)
139		ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
140
141	ctrl = v4l2_ctrl_new_std_menu(&inst->ctrl_handler, &vdec_ctrl_ops,
142				      V4L2_CID_MPEG_VIDEO_VP8_PROFILE,
143				      V4L2_MPEG_VIDEO_VP8_PROFILE_3,
144				      0, V4L2_MPEG_VIDEO_VP8_PROFILE_0);
145	if (ctrl)
146		ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
147
148	ctrl = v4l2_ctrl_new_std_menu(&inst->ctrl_handler, &vdec_ctrl_ops,
149				      V4L2_CID_MPEG_VIDEO_VP9_PROFILE,
150				      V4L2_MPEG_VIDEO_VP9_PROFILE_3,
151				      0, V4L2_MPEG_VIDEO_VP9_PROFILE_0);
152	if (ctrl)
153		ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
154
155	ctrl = v4l2_ctrl_new_std_menu(&inst->ctrl_handler, &vdec_ctrl_ops,
156				      V4L2_CID_MPEG_VIDEO_VP9_LEVEL,
157				      V4L2_MPEG_VIDEO_VP9_LEVEL_6_2,
158				      0, V4L2_MPEG_VIDEO_VP9_LEVEL_1_0);
159	if (ctrl)
160		ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
161
162	v4l2_ctrl_new_std(&inst->ctrl_handler, &vdec_ctrl_ops,
163		V4L2_CID_MPEG_VIDEO_DECODER_MPEG4_DEBLOCK_FILTER, 0, 1, 1, 0);
164
165	ctrl = v4l2_ctrl_new_std(&inst->ctrl_handler, &vdec_ctrl_ops,
166		V4L2_CID_MIN_BUFFERS_FOR_CAPTURE, 1, 32, 1, 1);
167	if (ctrl)
168		ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
169
170	v4l2_ctrl_new_std(&inst->ctrl_handler, &vdec_ctrl_ops,
171			  V4L2_CID_MPEG_VIDEO_DEC_DISPLAY_DELAY,
172			  0, 16383, 1, 0);
173
174	v4l2_ctrl_new_std(&inst->ctrl_handler, &vdec_ctrl_ops,
175			  V4L2_CID_MPEG_VIDEO_DEC_DISPLAY_DELAY_ENABLE,
176			  0, 1, 1, 0);
177
178	v4l2_ctrl_new_std(&inst->ctrl_handler, &vdec_ctrl_ops,
179			  V4L2_CID_MPEG_VIDEO_DEC_CONCEAL_COLOR, 0,
180			  0xffffffffffffLL, 1, 0x8000800010LL);
181
182	ret = inst->ctrl_handler.error;
183	if (ret) {
184		v4l2_ctrl_handler_free(&inst->ctrl_handler);
185		return ret;
186	}
187
188	return 0;
189}
190
191void vdec_ctrl_deinit(struct venus_inst *inst)
192{
193	v4l2_ctrl_handler_free(&inst->ctrl_handler);
194}
195