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 		ctr->profile = ctrl->val;
26 		break;
27 	case V4L2_CID_MPEG_VIDEO_H264_LEVEL:
28 	case V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL:
29 		ctr->level = ctrl->val;
30 		break;
31 	default:
32 		return -EINVAL;
33 	}
34 
35 	return 0;
36 }
37 
38 static int vdec_op_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
39 {
40 	struct venus_inst *inst = ctrl_to_inst(ctrl);
41 	struct vdec_controls *ctr = &inst->controls.dec;
42 	struct hfi_buffer_requirements bufreq;
43 	union hfi_get_property hprop;
44 	enum hfi_version ver = inst->core->res->hfi_version;
45 	u32 ptype = HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT;
46 	int ret;
47 
48 	switch (ctrl->id) {
49 	case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
50 	case V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE:
51 	case V4L2_CID_MPEG_VIDEO_VP8_PROFILE:
52 		ret = hfi_session_get_property(inst, ptype, &hprop);
53 		if (!ret)
54 			ctr->profile = hprop.profile_level.profile;
55 		ctrl->val = ctr->profile;
56 		break;
57 	case V4L2_CID_MPEG_VIDEO_H264_LEVEL:
58 	case V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL:
59 		ret = hfi_session_get_property(inst, ptype, &hprop);
60 		if (!ret)
61 			ctr->level = hprop.profile_level.level;
62 		ctrl->val = ctr->level;
63 		break;
64 	case V4L2_CID_MPEG_VIDEO_DECODER_MPEG4_DEBLOCK_FILTER:
65 		ctrl->val = ctr->post_loop_deb_mode;
66 		break;
67 	case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE:
68 		ret = venus_helper_get_bufreq(inst, HFI_BUFFER_OUTPUT, &bufreq);
69 		if (!ret)
70 			ctrl->val = HFI_BUFREQ_COUNT_MIN(&bufreq, ver);
71 		break;
72 	default:
73 		return -EINVAL;
74 	}
75 
76 	return 0;
77 }
78 
79 static const struct v4l2_ctrl_ops vdec_ctrl_ops = {
80 	.s_ctrl = vdec_op_s_ctrl,
81 	.g_volatile_ctrl = vdec_op_g_volatile_ctrl,
82 };
83 
84 int vdec_ctrl_init(struct venus_inst *inst)
85 {
86 	struct v4l2_ctrl *ctrl;
87 	int ret;
88 
89 	ret = v4l2_ctrl_handler_init(&inst->ctrl_handler, 7);
90 	if (ret)
91 		return ret;
92 
93 	ctrl = v4l2_ctrl_new_std_menu(&inst->ctrl_handler, &vdec_ctrl_ops,
94 		V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE,
95 		V4L2_MPEG_VIDEO_MPEG4_PROFILE_ADVANCED_CODING_EFFICIENCY,
96 		~((1 << V4L2_MPEG_VIDEO_MPEG4_PROFILE_SIMPLE) |
97 		  (1 << V4L2_MPEG_VIDEO_MPEG4_PROFILE_ADVANCED_SIMPLE)),
98 		V4L2_MPEG_VIDEO_MPEG4_PROFILE_SIMPLE);
99 	if (ctrl)
100 		ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
101 
102 	ctrl = v4l2_ctrl_new_std_menu(&inst->ctrl_handler, &vdec_ctrl_ops,
103 				      V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL,
104 				      V4L2_MPEG_VIDEO_MPEG4_LEVEL_5,
105 				      0, V4L2_MPEG_VIDEO_MPEG4_LEVEL_0);
106 	if (ctrl)
107 		ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
108 
109 	ctrl = v4l2_ctrl_new_std_menu(&inst->ctrl_handler, &vdec_ctrl_ops,
110 		V4L2_CID_MPEG_VIDEO_H264_PROFILE,
111 		V4L2_MPEG_VIDEO_H264_PROFILE_MULTIVIEW_HIGH,
112 		~((1 << V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE) |
113 		  (1 << V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE) |
114 		  (1 << V4L2_MPEG_VIDEO_H264_PROFILE_MAIN) |
115 		  (1 << V4L2_MPEG_VIDEO_H264_PROFILE_HIGH) |
116 		  (1 << V4L2_MPEG_VIDEO_H264_PROFILE_STEREO_HIGH) |
117 		  (1 << V4L2_MPEG_VIDEO_H264_PROFILE_MULTIVIEW_HIGH)),
118 		V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE);
119 	if (ctrl)
120 		ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
121 
122 	ctrl = v4l2_ctrl_new_std_menu(&inst->ctrl_handler, &vdec_ctrl_ops,
123 				      V4L2_CID_MPEG_VIDEO_H264_LEVEL,
124 				      V4L2_MPEG_VIDEO_H264_LEVEL_5_1,
125 				      0, V4L2_MPEG_VIDEO_H264_LEVEL_1_0);
126 	if (ctrl)
127 		ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
128 
129 	ctrl = v4l2_ctrl_new_std_menu(&inst->ctrl_handler, &vdec_ctrl_ops,
130 				      V4L2_CID_MPEG_VIDEO_VP8_PROFILE,
131 				      V4L2_MPEG_VIDEO_VP8_PROFILE_3,
132 				      0, V4L2_MPEG_VIDEO_VP8_PROFILE_0);
133 	if (ctrl)
134 		ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
135 
136 	v4l2_ctrl_new_std(&inst->ctrl_handler, &vdec_ctrl_ops,
137 		V4L2_CID_MPEG_VIDEO_DECODER_MPEG4_DEBLOCK_FILTER, 0, 1, 1, 0);
138 
139 	ctrl = v4l2_ctrl_new_std(&inst->ctrl_handler, &vdec_ctrl_ops,
140 		V4L2_CID_MIN_BUFFERS_FOR_CAPTURE, 1, 32, 1, 1);
141 	if (ctrl)
142 		ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
143 
144 	ret = inst->ctrl_handler.error;
145 	if (ret) {
146 		v4l2_ctrl_handler_free(&inst->ctrl_handler);
147 		return ret;
148 	}
149 
150 	return 0;
151 }
152 
153 void vdec_ctrl_deinit(struct venus_inst *inst)
154 {
155 	v4l2_ctrl_handler_free(&inst->ctrl_handler);
156 }
157