Commit | Line | Data |
---|---|---|
73c3f482 HV |
1 | /* |
2 | * vivid-ctrls.c - control support functions. | |
3 | * | |
4 | * Copyright 2014 Cisco Systems, Inc. and/or its affiliates. All rights reserved. | |
5 | * | |
6 | * This program is free software; you may redistribute it and/or modify | |
7 | * it under the terms of the GNU General Public License as published by | |
8 | * the Free Software Foundation; version 2 of the License. | |
9 | * | |
10 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |
11 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
12 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |
13 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | |
14 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | |
15 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | |
16 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
17 | * SOFTWARE. | |
18 | */ | |
19 | ||
20 | #include <linux/errno.h> | |
21 | #include <linux/kernel.h> | |
22 | #include <linux/videodev2.h> | |
23 | #include <media/v4l2-event.h> | |
24 | #include <media/v4l2-common.h> | |
25 | ||
26 | #include "vivid-core.h" | |
27 | #include "vivid-vid-cap.h" | |
28 | #include "vivid-vid-out.h" | |
29 | #include "vivid-vid-common.h" | |
30 | #include "vivid-radio-common.h" | |
31 | #include "vivid-osd.h" | |
32 | #include "vivid-ctrls.h" | |
33 | ||
34 | #define VIVID_CID_CUSTOM_BASE (V4L2_CID_USER_BASE | 0xf000) | |
35 | #define VIVID_CID_BUTTON (VIVID_CID_CUSTOM_BASE + 0) | |
36 | #define VIVID_CID_BOOLEAN (VIVID_CID_CUSTOM_BASE + 1) | |
37 | #define VIVID_CID_INTEGER (VIVID_CID_CUSTOM_BASE + 2) | |
38 | #define VIVID_CID_INTEGER64 (VIVID_CID_CUSTOM_BASE + 3) | |
39 | #define VIVID_CID_MENU (VIVID_CID_CUSTOM_BASE + 4) | |
40 | #define VIVID_CID_STRING (VIVID_CID_CUSTOM_BASE + 5) | |
41 | #define VIVID_CID_BITMASK (VIVID_CID_CUSTOM_BASE + 6) | |
42 | #define VIVID_CID_INTMENU (VIVID_CID_CUSTOM_BASE + 7) | |
24c4942d HV |
43 | #define VIVID_CID_U32_ARRAY (VIVID_CID_CUSTOM_BASE + 8) |
44 | #define VIVID_CID_U16_MATRIX (VIVID_CID_CUSTOM_BASE + 9) | |
45 | #define VIVID_CID_U8_4D_ARRAY (VIVID_CID_CUSTOM_BASE + 10) | |
73c3f482 HV |
46 | |
47 | #define VIVID_CID_VIVID_BASE (0x00f00000 | 0xf000) | |
48 | #define VIVID_CID_VIVID_CLASS (0x00f00000 | 1) | |
49 | #define VIVID_CID_TEST_PATTERN (VIVID_CID_VIVID_BASE + 0) | |
50 | #define VIVID_CID_OSD_TEXT_MODE (VIVID_CID_VIVID_BASE + 1) | |
51 | #define VIVID_CID_HOR_MOVEMENT (VIVID_CID_VIVID_BASE + 2) | |
52 | #define VIVID_CID_VERT_MOVEMENT (VIVID_CID_VIVID_BASE + 3) | |
53 | #define VIVID_CID_SHOW_BORDER (VIVID_CID_VIVID_BASE + 4) | |
54 | #define VIVID_CID_SHOW_SQUARE (VIVID_CID_VIVID_BASE + 5) | |
55 | #define VIVID_CID_INSERT_SAV (VIVID_CID_VIVID_BASE + 6) | |
56 | #define VIVID_CID_INSERT_EAV (VIVID_CID_VIVID_BASE + 7) | |
57 | #define VIVID_CID_VBI_CAP_INTERLACED (VIVID_CID_VIVID_BASE + 8) | |
58 | ||
59 | #define VIVID_CID_HFLIP (VIVID_CID_VIVID_BASE + 20) | |
60 | #define VIVID_CID_VFLIP (VIVID_CID_VIVID_BASE + 21) | |
61 | #define VIVID_CID_STD_ASPECT_RATIO (VIVID_CID_VIVID_BASE + 22) | |
62 | #define VIVID_CID_DV_TIMINGS_ASPECT_RATIO (VIVID_CID_VIVID_BASE + 23) | |
63 | #define VIVID_CID_TSTAMP_SRC (VIVID_CID_VIVID_BASE + 24) | |
64 | #define VIVID_CID_COLORSPACE (VIVID_CID_VIVID_BASE + 25) | |
ca5316db HV |
65 | #define VIVID_CID_XFER_FUNC (VIVID_CID_VIVID_BASE + 26) |
66 | #define VIVID_CID_YCBCR_ENC (VIVID_CID_VIVID_BASE + 27) | |
67 | #define VIVID_CID_QUANTIZATION (VIVID_CID_VIVID_BASE + 28) | |
68 | #define VIVID_CID_LIMITED_RGB_RANGE (VIVID_CID_VIVID_BASE + 29) | |
69 | #define VIVID_CID_ALPHA_MODE (VIVID_CID_VIVID_BASE + 30) | |
70 | #define VIVID_CID_HAS_CROP_CAP (VIVID_CID_VIVID_BASE + 31) | |
71 | #define VIVID_CID_HAS_COMPOSE_CAP (VIVID_CID_VIVID_BASE + 32) | |
72 | #define VIVID_CID_HAS_SCALER_CAP (VIVID_CID_VIVID_BASE + 33) | |
73 | #define VIVID_CID_HAS_CROP_OUT (VIVID_CID_VIVID_BASE + 34) | |
74 | #define VIVID_CID_HAS_COMPOSE_OUT (VIVID_CID_VIVID_BASE + 35) | |
75 | #define VIVID_CID_HAS_SCALER_OUT (VIVID_CID_VIVID_BASE + 36) | |
76 | #define VIVID_CID_LOOP_VIDEO (VIVID_CID_VIVID_BASE + 37) | |
77 | #define VIVID_CID_SEQ_WRAP (VIVID_CID_VIVID_BASE + 38) | |
78 | #define VIVID_CID_TIME_WRAP (VIVID_CID_VIVID_BASE + 39) | |
79 | #define VIVID_CID_MAX_EDID_BLOCKS (VIVID_CID_VIVID_BASE + 40) | |
80 | #define VIVID_CID_PERCENTAGE_FILL (VIVID_CID_VIVID_BASE + 41) | |
c79aa6ae | 81 | #define VIVID_CID_REDUCED_FPS (VIVID_CID_VIVID_BASE + 42) |
73c3f482 HV |
82 | |
83 | #define VIVID_CID_STD_SIGNAL_MODE (VIVID_CID_VIVID_BASE + 60) | |
84 | #define VIVID_CID_STANDARD (VIVID_CID_VIVID_BASE + 61) | |
85 | #define VIVID_CID_DV_TIMINGS_SIGNAL_MODE (VIVID_CID_VIVID_BASE + 62) | |
86 | #define VIVID_CID_DV_TIMINGS (VIVID_CID_VIVID_BASE + 63) | |
87 | #define VIVID_CID_PERC_DROPPED (VIVID_CID_VIVID_BASE + 64) | |
88 | #define VIVID_CID_DISCONNECT (VIVID_CID_VIVID_BASE + 65) | |
89 | #define VIVID_CID_DQBUF_ERROR (VIVID_CID_VIVID_BASE + 66) | |
90 | #define VIVID_CID_QUEUE_SETUP_ERROR (VIVID_CID_VIVID_BASE + 67) | |
91 | #define VIVID_CID_BUF_PREPARE_ERROR (VIVID_CID_VIVID_BASE + 68) | |
92 | #define VIVID_CID_START_STR_ERROR (VIVID_CID_VIVID_BASE + 69) | |
93 | #define VIVID_CID_QUEUE_ERROR (VIVID_CID_VIVID_BASE + 70) | |
94 | #define VIVID_CID_CLEAR_FB (VIVID_CID_VIVID_BASE + 71) | |
95 | ||
96 | #define VIVID_CID_RADIO_SEEK_MODE (VIVID_CID_VIVID_BASE + 90) | |
97 | #define VIVID_CID_RADIO_SEEK_PROG_LIM (VIVID_CID_VIVID_BASE + 91) | |
98 | #define VIVID_CID_RADIO_RX_RDS_RBDS (VIVID_CID_VIVID_BASE + 92) | |
99 | #define VIVID_CID_RADIO_RX_RDS_BLOCKIO (VIVID_CID_VIVID_BASE + 93) | |
100 | ||
101 | #define VIVID_CID_RADIO_TX_RDS_BLOCKIO (VIVID_CID_VIVID_BASE + 94) | |
102 | ||
f335c3f2 | 103 | #define VIVID_CID_SDR_CAP_FM_DEVIATION (VIVID_CID_VIVID_BASE + 110) |
73c3f482 HV |
104 | |
105 | /* General User Controls */ | |
106 | ||
107 | static int vivid_user_gen_s_ctrl(struct v4l2_ctrl *ctrl) | |
108 | { | |
109 | struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_user_gen); | |
110 | ||
111 | switch (ctrl->id) { | |
112 | case VIVID_CID_DISCONNECT: | |
113 | v4l2_info(&dev->v4l2_dev, "disconnect\n"); | |
114 | clear_bit(V4L2_FL_REGISTERED, &dev->vid_cap_dev.flags); | |
115 | clear_bit(V4L2_FL_REGISTERED, &dev->vid_out_dev.flags); | |
116 | clear_bit(V4L2_FL_REGISTERED, &dev->vbi_cap_dev.flags); | |
117 | clear_bit(V4L2_FL_REGISTERED, &dev->vbi_out_dev.flags); | |
118 | clear_bit(V4L2_FL_REGISTERED, &dev->sdr_cap_dev.flags); | |
119 | clear_bit(V4L2_FL_REGISTERED, &dev->radio_rx_dev.flags); | |
120 | clear_bit(V4L2_FL_REGISTERED, &dev->radio_tx_dev.flags); | |
121 | break; | |
122 | case VIVID_CID_CLEAR_FB: | |
123 | vivid_clear_fb(dev); | |
124 | break; | |
125 | case VIVID_CID_BUTTON: | |
126 | dev->button_pressed = 30; | |
127 | break; | |
128 | } | |
129 | return 0; | |
130 | } | |
131 | ||
132 | static const struct v4l2_ctrl_ops vivid_user_gen_ctrl_ops = { | |
133 | .s_ctrl = vivid_user_gen_s_ctrl, | |
134 | }; | |
135 | ||
136 | static const struct v4l2_ctrl_config vivid_ctrl_button = { | |
137 | .ops = &vivid_user_gen_ctrl_ops, | |
138 | .id = VIVID_CID_BUTTON, | |
139 | .name = "Button", | |
140 | .type = V4L2_CTRL_TYPE_BUTTON, | |
141 | }; | |
142 | ||
143 | static const struct v4l2_ctrl_config vivid_ctrl_boolean = { | |
144 | .ops = &vivid_user_gen_ctrl_ops, | |
145 | .id = VIVID_CID_BOOLEAN, | |
146 | .name = "Boolean", | |
147 | .type = V4L2_CTRL_TYPE_BOOLEAN, | |
148 | .min = 0, | |
149 | .max = 1, | |
150 | .step = 1, | |
151 | .def = 1, | |
152 | }; | |
153 | ||
154 | static const struct v4l2_ctrl_config vivid_ctrl_int32 = { | |
155 | .ops = &vivid_user_gen_ctrl_ops, | |
156 | .id = VIVID_CID_INTEGER, | |
157 | .name = "Integer 32 Bits", | |
158 | .type = V4L2_CTRL_TYPE_INTEGER, | |
159 | .min = 0xffffffff80000000ULL, | |
160 | .max = 0x7fffffff, | |
161 | .step = 1, | |
162 | }; | |
163 | ||
164 | static const struct v4l2_ctrl_config vivid_ctrl_int64 = { | |
165 | .ops = &vivid_user_gen_ctrl_ops, | |
166 | .id = VIVID_CID_INTEGER64, | |
167 | .name = "Integer 64 Bits", | |
168 | .type = V4L2_CTRL_TYPE_INTEGER64, | |
169 | .min = 0x8000000000000000ULL, | |
170 | .max = 0x7fffffffffffffffLL, | |
171 | .step = 1, | |
172 | }; | |
173 | ||
24c4942d HV |
174 | static const struct v4l2_ctrl_config vivid_ctrl_u32_array = { |
175 | .ops = &vivid_user_gen_ctrl_ops, | |
176 | .id = VIVID_CID_U32_ARRAY, | |
177 | .name = "U32 1 Element Array", | |
178 | .type = V4L2_CTRL_TYPE_U32, | |
179 | .def = 0x18, | |
180 | .min = 0x10, | |
181 | .max = 0x20000, | |
182 | .step = 1, | |
183 | .dims = { 1 }, | |
184 | }; | |
185 | ||
186 | static const struct v4l2_ctrl_config vivid_ctrl_u16_matrix = { | |
187 | .ops = &vivid_user_gen_ctrl_ops, | |
188 | .id = VIVID_CID_U16_MATRIX, | |
189 | .name = "U16 8x16 Matrix", | |
190 | .type = V4L2_CTRL_TYPE_U16, | |
191 | .def = 0x18, | |
192 | .min = 0x10, | |
193 | .max = 0x2000, | |
194 | .step = 1, | |
195 | .dims = { 8, 16 }, | |
196 | }; | |
197 | ||
198 | static const struct v4l2_ctrl_config vivid_ctrl_u8_4d_array = { | |
199 | .ops = &vivid_user_gen_ctrl_ops, | |
200 | .id = VIVID_CID_U8_4D_ARRAY, | |
201 | .name = "U8 2x3x4x5 Array", | |
202 | .type = V4L2_CTRL_TYPE_U8, | |
203 | .def = 0x18, | |
204 | .min = 0x10, | |
205 | .max = 0x20, | |
206 | .step = 1, | |
207 | .dims = { 2, 3, 4, 5 }, | |
208 | }; | |
209 | ||
73c3f482 HV |
210 | static const char * const vivid_ctrl_menu_strings[] = { |
211 | "Menu Item 0 (Skipped)", | |
212 | "Menu Item 1", | |
213 | "Menu Item 2 (Skipped)", | |
214 | "Menu Item 3", | |
215 | "Menu Item 4", | |
216 | "Menu Item 5 (Skipped)", | |
217 | NULL, | |
218 | }; | |
219 | ||
220 | static const struct v4l2_ctrl_config vivid_ctrl_menu = { | |
221 | .ops = &vivid_user_gen_ctrl_ops, | |
222 | .id = VIVID_CID_MENU, | |
223 | .name = "Menu", | |
224 | .type = V4L2_CTRL_TYPE_MENU, | |
225 | .min = 1, | |
226 | .max = 4, | |
227 | .def = 3, | |
228 | .menu_skip_mask = 0x04, | |
229 | .qmenu = vivid_ctrl_menu_strings, | |
230 | }; | |
231 | ||
232 | static const struct v4l2_ctrl_config vivid_ctrl_string = { | |
233 | .ops = &vivid_user_gen_ctrl_ops, | |
234 | .id = VIVID_CID_STRING, | |
235 | .name = "String", | |
236 | .type = V4L2_CTRL_TYPE_STRING, | |
237 | .min = 2, | |
238 | .max = 4, | |
239 | .step = 1, | |
240 | }; | |
241 | ||
242 | static const struct v4l2_ctrl_config vivid_ctrl_bitmask = { | |
243 | .ops = &vivid_user_gen_ctrl_ops, | |
244 | .id = VIVID_CID_BITMASK, | |
245 | .name = "Bitmask", | |
246 | .type = V4L2_CTRL_TYPE_BITMASK, | |
247 | .def = 0x80002000, | |
248 | .min = 0, | |
249 | .max = 0x80402010, | |
250 | .step = 0, | |
251 | }; | |
252 | ||
253 | static const s64 vivid_ctrl_int_menu_values[] = { | |
254 | 1, 1, 2, 3, 5, 8, 13, 21, 42, | |
255 | }; | |
256 | ||
257 | static const struct v4l2_ctrl_config vivid_ctrl_int_menu = { | |
258 | .ops = &vivid_user_gen_ctrl_ops, | |
259 | .id = VIVID_CID_INTMENU, | |
260 | .name = "Integer Menu", | |
261 | .type = V4L2_CTRL_TYPE_INTEGER_MENU, | |
262 | .min = 1, | |
263 | .max = 8, | |
264 | .def = 4, | |
265 | .menu_skip_mask = 0x02, | |
266 | .qmenu_int = vivid_ctrl_int_menu_values, | |
267 | }; | |
268 | ||
269 | static const struct v4l2_ctrl_config vivid_ctrl_disconnect = { | |
270 | .ops = &vivid_user_gen_ctrl_ops, | |
271 | .id = VIVID_CID_DISCONNECT, | |
272 | .name = "Disconnect", | |
273 | .type = V4L2_CTRL_TYPE_BUTTON, | |
274 | }; | |
275 | ||
276 | static const struct v4l2_ctrl_config vivid_ctrl_clear_fb = { | |
277 | .ops = &vivid_user_gen_ctrl_ops, | |
278 | .id = VIVID_CID_CLEAR_FB, | |
279 | .name = "Clear Framebuffer", | |
280 | .type = V4L2_CTRL_TYPE_BUTTON, | |
281 | }; | |
282 | ||
283 | ||
284 | /* Video User Controls */ | |
285 | ||
286 | static int vivid_user_vid_g_volatile_ctrl(struct v4l2_ctrl *ctrl) | |
287 | { | |
288 | struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_user_vid); | |
289 | ||
290 | switch (ctrl->id) { | |
291 | case V4L2_CID_AUTOGAIN: | |
292 | dev->gain->val = dev->jiffies_vid_cap & 0xff; | |
293 | break; | |
294 | } | |
295 | return 0; | |
296 | } | |
297 | ||
298 | static int vivid_user_vid_s_ctrl(struct v4l2_ctrl *ctrl) | |
299 | { | |
300 | struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_user_vid); | |
301 | ||
302 | switch (ctrl->id) { | |
303 | case V4L2_CID_BRIGHTNESS: | |
304 | dev->input_brightness[dev->input] = ctrl->val - dev->input * 128; | |
305 | tpg_s_brightness(&dev->tpg, dev->input_brightness[dev->input]); | |
306 | break; | |
307 | case V4L2_CID_CONTRAST: | |
308 | tpg_s_contrast(&dev->tpg, ctrl->val); | |
309 | break; | |
310 | case V4L2_CID_SATURATION: | |
311 | tpg_s_saturation(&dev->tpg, ctrl->val); | |
312 | break; | |
313 | case V4L2_CID_HUE: | |
314 | tpg_s_hue(&dev->tpg, ctrl->val); | |
315 | break; | |
316 | case V4L2_CID_HFLIP: | |
317 | dev->hflip = ctrl->val; | |
318 | tpg_s_hflip(&dev->tpg, dev->sensor_hflip ^ dev->hflip); | |
319 | break; | |
320 | case V4L2_CID_VFLIP: | |
321 | dev->vflip = ctrl->val; | |
322 | tpg_s_vflip(&dev->tpg, dev->sensor_vflip ^ dev->vflip); | |
323 | break; | |
324 | case V4L2_CID_ALPHA_COMPONENT: | |
325 | tpg_s_alpha_component(&dev->tpg, ctrl->val); | |
326 | break; | |
327 | } | |
328 | return 0; | |
329 | } | |
330 | ||
331 | static const struct v4l2_ctrl_ops vivid_user_vid_ctrl_ops = { | |
332 | .g_volatile_ctrl = vivid_user_vid_g_volatile_ctrl, | |
333 | .s_ctrl = vivid_user_vid_s_ctrl, | |
334 | }; | |
335 | ||
336 | ||
337 | /* Video Capture Controls */ | |
338 | ||
339 | static int vivid_vid_cap_s_ctrl(struct v4l2_ctrl *ctrl) | |
340 | { | |
cd8adbe7 HV |
341 | static const u32 colorspaces[] = { |
342 | V4L2_COLORSPACE_SMPTE170M, | |
343 | V4L2_COLORSPACE_REC709, | |
344 | V4L2_COLORSPACE_SRGB, | |
345 | V4L2_COLORSPACE_ADOBERGB, | |
346 | V4L2_COLORSPACE_BT2020, | |
1d780535 | 347 | V4L2_COLORSPACE_DCI_P3, |
cd8adbe7 HV |
348 | V4L2_COLORSPACE_SMPTE240M, |
349 | V4L2_COLORSPACE_470_SYSTEM_M, | |
350 | V4L2_COLORSPACE_470_SYSTEM_BG, | |
351 | }; | |
73c3f482 HV |
352 | struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_vid_cap); |
353 | unsigned i; | |
354 | ||
355 | switch (ctrl->id) { | |
356 | case VIVID_CID_TEST_PATTERN: | |
357 | vivid_update_quality(dev); | |
358 | tpg_s_pattern(&dev->tpg, ctrl->val); | |
359 | break; | |
360 | case VIVID_CID_COLORSPACE: | |
cd8adbe7 | 361 | tpg_s_colorspace(&dev->tpg, colorspaces[ctrl->val]); |
73c3f482 HV |
362 | vivid_send_source_change(dev, TV); |
363 | vivid_send_source_change(dev, SVID); | |
364 | vivid_send_source_change(dev, HDMI); | |
365 | vivid_send_source_change(dev, WEBCAM); | |
366 | break; | |
ca5316db HV |
367 | case VIVID_CID_XFER_FUNC: |
368 | tpg_s_xfer_func(&dev->tpg, ctrl->val); | |
369 | vivid_send_source_change(dev, TV); | |
370 | vivid_send_source_change(dev, SVID); | |
371 | vivid_send_source_change(dev, HDMI); | |
372 | vivid_send_source_change(dev, WEBCAM); | |
373 | break; | |
3e8a78d1 HV |
374 | case VIVID_CID_YCBCR_ENC: |
375 | tpg_s_ycbcr_enc(&dev->tpg, ctrl->val); | |
376 | vivid_send_source_change(dev, TV); | |
377 | vivid_send_source_change(dev, SVID); | |
378 | vivid_send_source_change(dev, HDMI); | |
379 | vivid_send_source_change(dev, WEBCAM); | |
380 | break; | |
381 | case VIVID_CID_QUANTIZATION: | |
382 | tpg_s_quantization(&dev->tpg, ctrl->val); | |
383 | vivid_send_source_change(dev, TV); | |
384 | vivid_send_source_change(dev, SVID); | |
385 | vivid_send_source_change(dev, HDMI); | |
386 | vivid_send_source_change(dev, WEBCAM); | |
387 | break; | |
73c3f482 HV |
388 | case V4L2_CID_DV_RX_RGB_RANGE: |
389 | if (!vivid_is_hdmi_cap(dev)) | |
390 | break; | |
391 | tpg_s_rgb_range(&dev->tpg, ctrl->val); | |
392 | break; | |
393 | case VIVID_CID_LIMITED_RGB_RANGE: | |
394 | tpg_s_real_rgb_range(&dev->tpg, ctrl->val ? | |
395 | V4L2_DV_RGB_RANGE_LIMITED : V4L2_DV_RGB_RANGE_FULL); | |
396 | break; | |
397 | case VIVID_CID_ALPHA_MODE: | |
398 | tpg_s_alpha_mode(&dev->tpg, ctrl->val); | |
399 | break; | |
400 | case VIVID_CID_HOR_MOVEMENT: | |
401 | tpg_s_mv_hor_mode(&dev->tpg, ctrl->val); | |
402 | break; | |
403 | case VIVID_CID_VERT_MOVEMENT: | |
404 | tpg_s_mv_vert_mode(&dev->tpg, ctrl->val); | |
405 | break; | |
406 | case VIVID_CID_OSD_TEXT_MODE: | |
407 | dev->osd_mode = ctrl->val; | |
408 | break; | |
409 | case VIVID_CID_PERCENTAGE_FILL: | |
410 | tpg_s_perc_fill(&dev->tpg, ctrl->val); | |
411 | for (i = 0; i < VIDEO_MAX_FRAME; i++) | |
412 | dev->must_blank[i] = ctrl->val < 100; | |
413 | break; | |
414 | case VIVID_CID_INSERT_SAV: | |
415 | tpg_s_insert_sav(&dev->tpg, ctrl->val); | |
416 | break; | |
417 | case VIVID_CID_INSERT_EAV: | |
418 | tpg_s_insert_eav(&dev->tpg, ctrl->val); | |
419 | break; | |
420 | case VIVID_CID_HFLIP: | |
421 | dev->sensor_hflip = ctrl->val; | |
422 | tpg_s_hflip(&dev->tpg, dev->sensor_hflip ^ dev->hflip); | |
423 | break; | |
424 | case VIVID_CID_VFLIP: | |
425 | dev->sensor_vflip = ctrl->val; | |
426 | tpg_s_vflip(&dev->tpg, dev->sensor_vflip ^ dev->vflip); | |
427 | break; | |
c79aa6ae PL |
428 | case VIVID_CID_REDUCED_FPS: |
429 | dev->reduced_fps = ctrl->val; | |
430 | vivid_update_format_cap(dev, true); | |
431 | break; | |
73c3f482 HV |
432 | case VIVID_CID_HAS_CROP_CAP: |
433 | dev->has_crop_cap = ctrl->val; | |
434 | vivid_update_format_cap(dev, true); | |
435 | break; | |
436 | case VIVID_CID_HAS_COMPOSE_CAP: | |
437 | dev->has_compose_cap = ctrl->val; | |
438 | vivid_update_format_cap(dev, true); | |
439 | break; | |
440 | case VIVID_CID_HAS_SCALER_CAP: | |
441 | dev->has_scaler_cap = ctrl->val; | |
442 | vivid_update_format_cap(dev, true); | |
443 | break; | |
444 | case VIVID_CID_SHOW_BORDER: | |
445 | tpg_s_show_border(&dev->tpg, ctrl->val); | |
446 | break; | |
447 | case VIVID_CID_SHOW_SQUARE: | |
448 | tpg_s_show_square(&dev->tpg, ctrl->val); | |
449 | break; | |
450 | case VIVID_CID_STD_ASPECT_RATIO: | |
451 | dev->std_aspect_ratio = ctrl->val; | |
452 | tpg_s_video_aspect(&dev->tpg, vivid_get_video_aspect(dev)); | |
453 | break; | |
454 | case VIVID_CID_DV_TIMINGS_SIGNAL_MODE: | |
455 | dev->dv_timings_signal_mode = dev->ctrl_dv_timings_signal_mode->val; | |
456 | if (dev->dv_timings_signal_mode == SELECTED_DV_TIMINGS) | |
457 | dev->query_dv_timings = dev->ctrl_dv_timings->val; | |
458 | v4l2_ctrl_activate(dev->ctrl_dv_timings, | |
459 | dev->dv_timings_signal_mode == SELECTED_DV_TIMINGS); | |
460 | vivid_update_quality(dev); | |
461 | vivid_send_source_change(dev, HDMI); | |
462 | break; | |
463 | case VIVID_CID_DV_TIMINGS_ASPECT_RATIO: | |
464 | dev->dv_timings_aspect_ratio = ctrl->val; | |
465 | tpg_s_video_aspect(&dev->tpg, vivid_get_video_aspect(dev)); | |
466 | break; | |
467 | case VIVID_CID_TSTAMP_SRC: | |
468 | dev->tstamp_src_is_soe = ctrl->val; | |
469 | dev->vb_vid_cap_q.timestamp_flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK; | |
470 | if (dev->tstamp_src_is_soe) | |
471 | dev->vb_vid_cap_q.timestamp_flags |= V4L2_BUF_FLAG_TSTAMP_SRC_SOE; | |
472 | break; | |
473 | case VIVID_CID_MAX_EDID_BLOCKS: | |
474 | dev->edid_max_blocks = ctrl->val; | |
475 | if (dev->edid_blocks > dev->edid_max_blocks) | |
476 | dev->edid_blocks = dev->edid_max_blocks; | |
477 | break; | |
478 | } | |
479 | return 0; | |
480 | } | |
481 | ||
482 | static const struct v4l2_ctrl_ops vivid_vid_cap_ctrl_ops = { | |
483 | .s_ctrl = vivid_vid_cap_s_ctrl, | |
484 | }; | |
485 | ||
486 | static const char * const vivid_ctrl_hor_movement_strings[] = { | |
487 | "Move Left Fast", | |
488 | "Move Left", | |
489 | "Move Left Slow", | |
490 | "No Movement", | |
491 | "Move Right Slow", | |
492 | "Move Right", | |
493 | "Move Right Fast", | |
494 | NULL, | |
495 | }; | |
496 | ||
497 | static const struct v4l2_ctrl_config vivid_ctrl_hor_movement = { | |
498 | .ops = &vivid_vid_cap_ctrl_ops, | |
499 | .id = VIVID_CID_HOR_MOVEMENT, | |
500 | .name = "Horizontal Movement", | |
501 | .type = V4L2_CTRL_TYPE_MENU, | |
502 | .max = TPG_MOVE_POS_FAST, | |
503 | .def = TPG_MOVE_NONE, | |
504 | .qmenu = vivid_ctrl_hor_movement_strings, | |
505 | }; | |
506 | ||
507 | static const char * const vivid_ctrl_vert_movement_strings[] = { | |
508 | "Move Up Fast", | |
509 | "Move Up", | |
510 | "Move Up Slow", | |
511 | "No Movement", | |
512 | "Move Down Slow", | |
513 | "Move Down", | |
514 | "Move Down Fast", | |
515 | NULL, | |
516 | }; | |
517 | ||
518 | static const struct v4l2_ctrl_config vivid_ctrl_vert_movement = { | |
519 | .ops = &vivid_vid_cap_ctrl_ops, | |
520 | .id = VIVID_CID_VERT_MOVEMENT, | |
521 | .name = "Vertical Movement", | |
522 | .type = V4L2_CTRL_TYPE_MENU, | |
523 | .max = TPG_MOVE_POS_FAST, | |
524 | .def = TPG_MOVE_NONE, | |
525 | .qmenu = vivid_ctrl_vert_movement_strings, | |
526 | }; | |
527 | ||
528 | static const struct v4l2_ctrl_config vivid_ctrl_show_border = { | |
529 | .ops = &vivid_vid_cap_ctrl_ops, | |
530 | .id = VIVID_CID_SHOW_BORDER, | |
531 | .name = "Show Border", | |
532 | .type = V4L2_CTRL_TYPE_BOOLEAN, | |
533 | .max = 1, | |
534 | .step = 1, | |
535 | }; | |
536 | ||
537 | static const struct v4l2_ctrl_config vivid_ctrl_show_square = { | |
538 | .ops = &vivid_vid_cap_ctrl_ops, | |
539 | .id = VIVID_CID_SHOW_SQUARE, | |
540 | .name = "Show Square", | |
541 | .type = V4L2_CTRL_TYPE_BOOLEAN, | |
542 | .max = 1, | |
543 | .step = 1, | |
544 | }; | |
545 | ||
546 | static const char * const vivid_ctrl_osd_mode_strings[] = { | |
547 | "All", | |
548 | "Counters Only", | |
549 | "None", | |
550 | NULL, | |
551 | }; | |
552 | ||
553 | static const struct v4l2_ctrl_config vivid_ctrl_osd_mode = { | |
554 | .ops = &vivid_vid_cap_ctrl_ops, | |
555 | .id = VIVID_CID_OSD_TEXT_MODE, | |
556 | .name = "OSD Text Mode", | |
557 | .type = V4L2_CTRL_TYPE_MENU, | |
ff144726 | 558 | .max = ARRAY_SIZE(vivid_ctrl_osd_mode_strings) - 2, |
73c3f482 HV |
559 | .qmenu = vivid_ctrl_osd_mode_strings, |
560 | }; | |
561 | ||
562 | static const struct v4l2_ctrl_config vivid_ctrl_perc_fill = { | |
563 | .ops = &vivid_vid_cap_ctrl_ops, | |
564 | .id = VIVID_CID_PERCENTAGE_FILL, | |
565 | .name = "Fill Percentage of Frame", | |
566 | .type = V4L2_CTRL_TYPE_INTEGER, | |
567 | .min = 0, | |
568 | .max = 100, | |
569 | .def = 100, | |
570 | .step = 1, | |
571 | }; | |
572 | ||
573 | static const struct v4l2_ctrl_config vivid_ctrl_insert_sav = { | |
574 | .ops = &vivid_vid_cap_ctrl_ops, | |
575 | .id = VIVID_CID_INSERT_SAV, | |
576 | .name = "Insert SAV Code in Image", | |
577 | .type = V4L2_CTRL_TYPE_BOOLEAN, | |
578 | .max = 1, | |
579 | .step = 1, | |
580 | }; | |
581 | ||
582 | static const struct v4l2_ctrl_config vivid_ctrl_insert_eav = { | |
583 | .ops = &vivid_vid_cap_ctrl_ops, | |
584 | .id = VIVID_CID_INSERT_EAV, | |
585 | .name = "Insert EAV Code in Image", | |
586 | .type = V4L2_CTRL_TYPE_BOOLEAN, | |
587 | .max = 1, | |
588 | .step = 1, | |
589 | }; | |
590 | ||
591 | static const struct v4l2_ctrl_config vivid_ctrl_hflip = { | |
592 | .ops = &vivid_vid_cap_ctrl_ops, | |
593 | .id = VIVID_CID_HFLIP, | |
594 | .name = "Sensor Flipped Horizontally", | |
595 | .type = V4L2_CTRL_TYPE_BOOLEAN, | |
596 | .max = 1, | |
597 | .step = 1, | |
598 | }; | |
599 | ||
600 | static const struct v4l2_ctrl_config vivid_ctrl_vflip = { | |
601 | .ops = &vivid_vid_cap_ctrl_ops, | |
602 | .id = VIVID_CID_VFLIP, | |
603 | .name = "Sensor Flipped Vertically", | |
604 | .type = V4L2_CTRL_TYPE_BOOLEAN, | |
605 | .max = 1, | |
606 | .step = 1, | |
607 | }; | |
608 | ||
c79aa6ae PL |
609 | static const struct v4l2_ctrl_config vivid_ctrl_reduced_fps = { |
610 | .ops = &vivid_vid_cap_ctrl_ops, | |
611 | .id = VIVID_CID_REDUCED_FPS, | |
612 | .name = "Reduced Framerate", | |
613 | .type = V4L2_CTRL_TYPE_BOOLEAN, | |
614 | .max = 1, | |
615 | .step = 1, | |
616 | }; | |
617 | ||
73c3f482 HV |
618 | static const struct v4l2_ctrl_config vivid_ctrl_has_crop_cap = { |
619 | .ops = &vivid_vid_cap_ctrl_ops, | |
620 | .id = VIVID_CID_HAS_CROP_CAP, | |
621 | .name = "Enable Capture Cropping", | |
622 | .type = V4L2_CTRL_TYPE_BOOLEAN, | |
623 | .max = 1, | |
624 | .def = 1, | |
625 | .step = 1, | |
626 | }; | |
627 | ||
628 | static const struct v4l2_ctrl_config vivid_ctrl_has_compose_cap = { | |
629 | .ops = &vivid_vid_cap_ctrl_ops, | |
630 | .id = VIVID_CID_HAS_COMPOSE_CAP, | |
631 | .name = "Enable Capture Composing", | |
632 | .type = V4L2_CTRL_TYPE_BOOLEAN, | |
633 | .max = 1, | |
634 | .def = 1, | |
635 | .step = 1, | |
636 | }; | |
637 | ||
638 | static const struct v4l2_ctrl_config vivid_ctrl_has_scaler_cap = { | |
639 | .ops = &vivid_vid_cap_ctrl_ops, | |
640 | .id = VIVID_CID_HAS_SCALER_CAP, | |
641 | .name = "Enable Capture Scaler", | |
642 | .type = V4L2_CTRL_TYPE_BOOLEAN, | |
643 | .max = 1, | |
644 | .def = 1, | |
645 | .step = 1, | |
646 | }; | |
647 | ||
648 | static const char * const vivid_ctrl_tstamp_src_strings[] = { | |
649 | "End of Frame", | |
650 | "Start of Exposure", | |
651 | NULL, | |
652 | }; | |
653 | ||
654 | static const struct v4l2_ctrl_config vivid_ctrl_tstamp_src = { | |
655 | .ops = &vivid_vid_cap_ctrl_ops, | |
656 | .id = VIVID_CID_TSTAMP_SRC, | |
657 | .name = "Timestamp Source", | |
658 | .type = V4L2_CTRL_TYPE_MENU, | |
ff144726 | 659 | .max = ARRAY_SIZE(vivid_ctrl_tstamp_src_strings) - 2, |
73c3f482 HV |
660 | .qmenu = vivid_ctrl_tstamp_src_strings, |
661 | }; | |
662 | ||
663 | static const struct v4l2_ctrl_config vivid_ctrl_std_aspect_ratio = { | |
664 | .ops = &vivid_vid_cap_ctrl_ops, | |
665 | .id = VIVID_CID_STD_ASPECT_RATIO, | |
666 | .name = "Standard Aspect Ratio", | |
667 | .type = V4L2_CTRL_TYPE_MENU, | |
668 | .min = 1, | |
669 | .max = 4, | |
670 | .def = 1, | |
671 | .qmenu = tpg_aspect_strings, | |
672 | }; | |
673 | ||
674 | static const char * const vivid_ctrl_dv_timings_signal_mode_strings[] = { | |
675 | "Current DV Timings", | |
676 | "No Signal", | |
677 | "No Lock", | |
678 | "Out of Range", | |
679 | "Selected DV Timings", | |
680 | "Cycle Through All DV Timings", | |
681 | "Custom DV Timings", | |
682 | NULL, | |
683 | }; | |
684 | ||
685 | static const struct v4l2_ctrl_config vivid_ctrl_dv_timings_signal_mode = { | |
686 | .ops = &vivid_vid_cap_ctrl_ops, | |
687 | .id = VIVID_CID_DV_TIMINGS_SIGNAL_MODE, | |
688 | .name = "DV Timings Signal Mode", | |
689 | .type = V4L2_CTRL_TYPE_MENU, | |
690 | .max = 5, | |
691 | .qmenu = vivid_ctrl_dv_timings_signal_mode_strings, | |
692 | }; | |
693 | ||
694 | static const struct v4l2_ctrl_config vivid_ctrl_dv_timings_aspect_ratio = { | |
695 | .ops = &vivid_vid_cap_ctrl_ops, | |
696 | .id = VIVID_CID_DV_TIMINGS_ASPECT_RATIO, | |
697 | .name = "DV Timings Aspect Ratio", | |
698 | .type = V4L2_CTRL_TYPE_MENU, | |
699 | .max = 3, | |
700 | .qmenu = tpg_aspect_strings, | |
701 | }; | |
702 | ||
703 | static const struct v4l2_ctrl_config vivid_ctrl_max_edid_blocks = { | |
704 | .ops = &vivid_vid_cap_ctrl_ops, | |
705 | .id = VIVID_CID_MAX_EDID_BLOCKS, | |
706 | .name = "Maximum EDID Blocks", | |
707 | .type = V4L2_CTRL_TYPE_INTEGER, | |
708 | .min = 1, | |
709 | .max = 256, | |
710 | .def = 2, | |
711 | .step = 1, | |
712 | }; | |
713 | ||
714 | static const char * const vivid_ctrl_colorspace_strings[] = { | |
73c3f482 | 715 | "SMPTE 170M", |
eb79dbf6 | 716 | "Rec. 709", |
cd8adbe7 HV |
717 | "sRGB", |
718 | "AdobeRGB", | |
719 | "BT.2020", | |
1d780535 | 720 | "DCI-P3", |
cd8adbe7 | 721 | "SMPTE 240M", |
73c3f482 HV |
722 | "470 System M", |
723 | "470 System BG", | |
73c3f482 HV |
724 | NULL, |
725 | }; | |
726 | ||
727 | static const struct v4l2_ctrl_config vivid_ctrl_colorspace = { | |
728 | .ops = &vivid_vid_cap_ctrl_ops, | |
729 | .id = VIVID_CID_COLORSPACE, | |
730 | .name = "Colorspace", | |
731 | .type = V4L2_CTRL_TYPE_MENU, | |
ff144726 | 732 | .max = ARRAY_SIZE(vivid_ctrl_colorspace_strings) - 2, |
cd8adbe7 | 733 | .def = 2, |
73c3f482 HV |
734 | .qmenu = vivid_ctrl_colorspace_strings, |
735 | }; | |
736 | ||
ca5316db HV |
737 | static const char * const vivid_ctrl_xfer_func_strings[] = { |
738 | "Default", | |
739 | "Rec. 709", | |
740 | "sRGB", | |
741 | "AdobeRGB", | |
742 | "SMPTE 240M", | |
743 | "None", | |
1d780535 | 744 | "DCI-P3", |
c732e647 | 745 | "SMPTE 2084", |
ca5316db HV |
746 | NULL, |
747 | }; | |
748 | ||
749 | static const struct v4l2_ctrl_config vivid_ctrl_xfer_func = { | |
750 | .ops = &vivid_vid_cap_ctrl_ops, | |
751 | .id = VIVID_CID_XFER_FUNC, | |
752 | .name = "Transfer Function", | |
753 | .type = V4L2_CTRL_TYPE_MENU, | |
ff144726 | 754 | .max = ARRAY_SIZE(vivid_ctrl_xfer_func_strings) - 2, |
ca5316db HV |
755 | .qmenu = vivid_ctrl_xfer_func_strings, |
756 | }; | |
757 | ||
3e8a78d1 HV |
758 | static const char * const vivid_ctrl_ycbcr_enc_strings[] = { |
759 | "Default", | |
760 | "ITU-R 601", | |
761 | "Rec. 709", | |
762 | "xvYCC 601", | |
763 | "xvYCC 709", | |
764 | "sYCC", | |
eb79dbf6 | 765 | "BT.2020", |
3e8a78d1 HV |
766 | "BT.2020 Constant Luminance", |
767 | "SMPTE 240M", | |
768 | NULL, | |
769 | }; | |
770 | ||
771 | static const struct v4l2_ctrl_config vivid_ctrl_ycbcr_enc = { | |
772 | .ops = &vivid_vid_cap_ctrl_ops, | |
773 | .id = VIVID_CID_YCBCR_ENC, | |
774 | .name = "Y'CbCr Encoding", | |
775 | .type = V4L2_CTRL_TYPE_MENU, | |
ff144726 | 776 | .max = ARRAY_SIZE(vivid_ctrl_ycbcr_enc_strings) - 2, |
3e8a78d1 HV |
777 | .qmenu = vivid_ctrl_ycbcr_enc_strings, |
778 | }; | |
779 | ||
780 | static const char * const vivid_ctrl_quantization_strings[] = { | |
781 | "Default", | |
782 | "Full Range", | |
783 | "Limited Range", | |
784 | NULL, | |
785 | }; | |
786 | ||
787 | static const struct v4l2_ctrl_config vivid_ctrl_quantization = { | |
788 | .ops = &vivid_vid_cap_ctrl_ops, | |
789 | .id = VIVID_CID_QUANTIZATION, | |
790 | .name = "Quantization", | |
791 | .type = V4L2_CTRL_TYPE_MENU, | |
ff144726 | 792 | .max = ARRAY_SIZE(vivid_ctrl_quantization_strings) - 2, |
3e8a78d1 HV |
793 | .qmenu = vivid_ctrl_quantization_strings, |
794 | }; | |
795 | ||
73c3f482 HV |
796 | static const struct v4l2_ctrl_config vivid_ctrl_alpha_mode = { |
797 | .ops = &vivid_vid_cap_ctrl_ops, | |
798 | .id = VIVID_CID_ALPHA_MODE, | |
799 | .name = "Apply Alpha To Red Only", | |
800 | .type = V4L2_CTRL_TYPE_BOOLEAN, | |
801 | .max = 1, | |
802 | .step = 1, | |
803 | }; | |
804 | ||
805 | static const struct v4l2_ctrl_config vivid_ctrl_limited_rgb_range = { | |
806 | .ops = &vivid_vid_cap_ctrl_ops, | |
807 | .id = VIVID_CID_LIMITED_RGB_RANGE, | |
808 | .name = "Limited RGB Range (16-235)", | |
809 | .type = V4L2_CTRL_TYPE_BOOLEAN, | |
810 | .max = 1, | |
811 | .step = 1, | |
812 | }; | |
813 | ||
814 | ||
63344b65 HV |
815 | /* Video Loop Control */ |
816 | ||
817 | static int vivid_loop_cap_s_ctrl(struct v4l2_ctrl *ctrl) | |
818 | { | |
819 | struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_loop_cap); | |
820 | ||
821 | switch (ctrl->id) { | |
822 | case VIVID_CID_LOOP_VIDEO: | |
823 | dev->loop_video = ctrl->val; | |
824 | vivid_update_quality(dev); | |
825 | vivid_send_source_change(dev, SVID); | |
826 | vivid_send_source_change(dev, HDMI); | |
827 | break; | |
828 | } | |
829 | return 0; | |
830 | } | |
831 | ||
832 | static const struct v4l2_ctrl_ops vivid_loop_cap_ctrl_ops = { | |
833 | .s_ctrl = vivid_loop_cap_s_ctrl, | |
834 | }; | |
835 | ||
836 | static const struct v4l2_ctrl_config vivid_ctrl_loop_video = { | |
837 | .ops = &vivid_loop_cap_ctrl_ops, | |
838 | .id = VIVID_CID_LOOP_VIDEO, | |
839 | .name = "Loop Video", | |
840 | .type = V4L2_CTRL_TYPE_BOOLEAN, | |
841 | .max = 1, | |
842 | .step = 1, | |
843 | }; | |
844 | ||
845 | ||
73c3f482 HV |
846 | /* VBI Capture Control */ |
847 | ||
848 | static int vivid_vbi_cap_s_ctrl(struct v4l2_ctrl *ctrl) | |
849 | { | |
850 | struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_vbi_cap); | |
851 | ||
852 | switch (ctrl->id) { | |
853 | case VIVID_CID_VBI_CAP_INTERLACED: | |
854 | dev->vbi_cap_interlaced = ctrl->val; | |
855 | break; | |
856 | } | |
857 | return 0; | |
858 | } | |
859 | ||
860 | static const struct v4l2_ctrl_ops vivid_vbi_cap_ctrl_ops = { | |
861 | .s_ctrl = vivid_vbi_cap_s_ctrl, | |
862 | }; | |
863 | ||
864 | static const struct v4l2_ctrl_config vivid_ctrl_vbi_cap_interlaced = { | |
865 | .ops = &vivid_vbi_cap_ctrl_ops, | |
866 | .id = VIVID_CID_VBI_CAP_INTERLACED, | |
867 | .name = "Interlaced VBI Format", | |
868 | .type = V4L2_CTRL_TYPE_BOOLEAN, | |
869 | .max = 1, | |
870 | .step = 1, | |
871 | }; | |
872 | ||
873 | ||
874 | /* Video Output Controls */ | |
875 | ||
876 | static int vivid_vid_out_s_ctrl(struct v4l2_ctrl *ctrl) | |
877 | { | |
878 | struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_vid_out); | |
879 | struct v4l2_bt_timings *bt = &dev->dv_timings_out.bt; | |
880 | ||
881 | switch (ctrl->id) { | |
882 | case VIVID_CID_HAS_CROP_OUT: | |
883 | dev->has_crop_out = ctrl->val; | |
884 | vivid_update_format_out(dev); | |
885 | break; | |
886 | case VIVID_CID_HAS_COMPOSE_OUT: | |
887 | dev->has_compose_out = ctrl->val; | |
888 | vivid_update_format_out(dev); | |
889 | break; | |
890 | case VIVID_CID_HAS_SCALER_OUT: | |
891 | dev->has_scaler_out = ctrl->val; | |
892 | vivid_update_format_out(dev); | |
893 | break; | |
894 | case V4L2_CID_DV_TX_MODE: | |
895 | dev->dvi_d_out = ctrl->val == V4L2_DV_TX_MODE_DVI_D; | |
896 | if (!vivid_is_hdmi_out(dev)) | |
897 | break; | |
4a203349 | 898 | if (!dev->dvi_d_out && (bt->flags & V4L2_DV_FL_IS_CE_VIDEO)) { |
73c3f482 HV |
899 | if (bt->width == 720 && bt->height <= 576) |
900 | dev->colorspace_out = V4L2_COLORSPACE_SMPTE170M; | |
901 | else | |
902 | dev->colorspace_out = V4L2_COLORSPACE_REC709; | |
3e8a78d1 | 903 | dev->quantization_out = V4L2_QUANTIZATION_DEFAULT; |
73c3f482 HV |
904 | } else { |
905 | dev->colorspace_out = V4L2_COLORSPACE_SRGB; | |
3e8a78d1 HV |
906 | dev->quantization_out = dev->dvi_d_out ? |
907 | V4L2_QUANTIZATION_LIM_RANGE : | |
908 | V4L2_QUANTIZATION_DEFAULT; | |
73c3f482 HV |
909 | } |
910 | if (dev->loop_video) | |
911 | vivid_send_source_change(dev, HDMI); | |
912 | break; | |
913 | } | |
914 | return 0; | |
915 | } | |
916 | ||
917 | static const struct v4l2_ctrl_ops vivid_vid_out_ctrl_ops = { | |
918 | .s_ctrl = vivid_vid_out_s_ctrl, | |
919 | }; | |
920 | ||
921 | static const struct v4l2_ctrl_config vivid_ctrl_has_crop_out = { | |
922 | .ops = &vivid_vid_out_ctrl_ops, | |
923 | .id = VIVID_CID_HAS_CROP_OUT, | |
924 | .name = "Enable Output Cropping", | |
925 | .type = V4L2_CTRL_TYPE_BOOLEAN, | |
926 | .max = 1, | |
927 | .def = 1, | |
928 | .step = 1, | |
929 | }; | |
930 | ||
931 | static const struct v4l2_ctrl_config vivid_ctrl_has_compose_out = { | |
932 | .ops = &vivid_vid_out_ctrl_ops, | |
933 | .id = VIVID_CID_HAS_COMPOSE_OUT, | |
934 | .name = "Enable Output Composing", | |
935 | .type = V4L2_CTRL_TYPE_BOOLEAN, | |
936 | .max = 1, | |
937 | .def = 1, | |
938 | .step = 1, | |
939 | }; | |
940 | ||
941 | static const struct v4l2_ctrl_config vivid_ctrl_has_scaler_out = { | |
942 | .ops = &vivid_vid_out_ctrl_ops, | |
943 | .id = VIVID_CID_HAS_SCALER_OUT, | |
944 | .name = "Enable Output Scaler", | |
945 | .type = V4L2_CTRL_TYPE_BOOLEAN, | |
946 | .max = 1, | |
947 | .def = 1, | |
948 | .step = 1, | |
949 | }; | |
950 | ||
951 | ||
952 | /* Streaming Controls */ | |
953 | ||
954 | static int vivid_streaming_s_ctrl(struct v4l2_ctrl *ctrl) | |
955 | { | |
956 | struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_streaming); | |
d6dd645e | 957 | u64 rem; |
73c3f482 HV |
958 | |
959 | switch (ctrl->id) { | |
960 | case VIVID_CID_DQBUF_ERROR: | |
961 | dev->dqbuf_error = true; | |
962 | break; | |
963 | case VIVID_CID_PERC_DROPPED: | |
964 | dev->perc_dropped_buffers = ctrl->val; | |
965 | break; | |
966 | case VIVID_CID_QUEUE_SETUP_ERROR: | |
967 | dev->queue_setup_error = true; | |
968 | break; | |
969 | case VIVID_CID_BUF_PREPARE_ERROR: | |
970 | dev->buf_prepare_error = true; | |
971 | break; | |
972 | case VIVID_CID_START_STR_ERROR: | |
973 | dev->start_streaming_error = true; | |
974 | break; | |
975 | case VIVID_CID_QUEUE_ERROR: | |
eab34eab | 976 | if (vb2_start_streaming_called(&dev->vb_vid_cap_q)) |
73c3f482 | 977 | vb2_queue_error(&dev->vb_vid_cap_q); |
eab34eab | 978 | if (vb2_start_streaming_called(&dev->vb_vbi_cap_q)) |
73c3f482 | 979 | vb2_queue_error(&dev->vb_vbi_cap_q); |
eab34eab | 980 | if (vb2_start_streaming_called(&dev->vb_vid_out_q)) |
73c3f482 | 981 | vb2_queue_error(&dev->vb_vid_out_q); |
eab34eab | 982 | if (vb2_start_streaming_called(&dev->vb_vbi_out_q)) |
73c3f482 | 983 | vb2_queue_error(&dev->vb_vbi_out_q); |
eab34eab | 984 | if (vb2_start_streaming_called(&dev->vb_sdr_cap_q)) |
73c3f482 HV |
985 | vb2_queue_error(&dev->vb_sdr_cap_q); |
986 | break; | |
987 | case VIVID_CID_SEQ_WRAP: | |
988 | dev->seq_wrap = ctrl->val; | |
989 | break; | |
990 | case VIVID_CID_TIME_WRAP: | |
991 | dev->time_wrap = ctrl->val; | |
992 | if (ctrl->val == 0) { | |
993 | dev->time_wrap_offset = 0; | |
994 | break; | |
995 | } | |
d6dd645e JS |
996 | /* |
997 | * We want to set the time 16 seconds before the 32 bit tv_sec | |
998 | * value of struct timeval would wrap around. So first we | |
999 | * calculate ktime_get_ns() % ((1 << 32) * NSEC_PER_SEC), and | |
1000 | * then we set the offset to ((1 << 32) - 16) * NSEC_PER_SEC). | |
1001 | */ | |
1002 | div64_u64_rem(ktime_get_ns(), | |
1003 | 0x100000000ULL * NSEC_PER_SEC, &rem); | |
1004 | dev->time_wrap_offset = | |
1005 | (0x100000000ULL - 16) * NSEC_PER_SEC - rem; | |
73c3f482 HV |
1006 | break; |
1007 | } | |
1008 | return 0; | |
1009 | } | |
1010 | ||
1011 | static const struct v4l2_ctrl_ops vivid_streaming_ctrl_ops = { | |
1012 | .s_ctrl = vivid_streaming_s_ctrl, | |
1013 | }; | |
1014 | ||
1015 | static const struct v4l2_ctrl_config vivid_ctrl_dqbuf_error = { | |
1016 | .ops = &vivid_streaming_ctrl_ops, | |
1017 | .id = VIVID_CID_DQBUF_ERROR, | |
1018 | .name = "Inject V4L2_BUF_FLAG_ERROR", | |
1019 | .type = V4L2_CTRL_TYPE_BUTTON, | |
1020 | }; | |
1021 | ||
1022 | static const struct v4l2_ctrl_config vivid_ctrl_perc_dropped = { | |
1023 | .ops = &vivid_streaming_ctrl_ops, | |
1024 | .id = VIVID_CID_PERC_DROPPED, | |
1025 | .name = "Percentage of Dropped Buffers", | |
1026 | .type = V4L2_CTRL_TYPE_INTEGER, | |
1027 | .min = 0, | |
1028 | .max = 100, | |
1029 | .step = 1, | |
1030 | }; | |
1031 | ||
1032 | static const struct v4l2_ctrl_config vivid_ctrl_queue_setup_error = { | |
1033 | .ops = &vivid_streaming_ctrl_ops, | |
1034 | .id = VIVID_CID_QUEUE_SETUP_ERROR, | |
1035 | .name = "Inject VIDIOC_REQBUFS Error", | |
1036 | .type = V4L2_CTRL_TYPE_BUTTON, | |
1037 | }; | |
1038 | ||
1039 | static const struct v4l2_ctrl_config vivid_ctrl_buf_prepare_error = { | |
1040 | .ops = &vivid_streaming_ctrl_ops, | |
1041 | .id = VIVID_CID_BUF_PREPARE_ERROR, | |
1042 | .name = "Inject VIDIOC_QBUF Error", | |
1043 | .type = V4L2_CTRL_TYPE_BUTTON, | |
1044 | }; | |
1045 | ||
1046 | static const struct v4l2_ctrl_config vivid_ctrl_start_streaming_error = { | |
1047 | .ops = &vivid_streaming_ctrl_ops, | |
1048 | .id = VIVID_CID_START_STR_ERROR, | |
1049 | .name = "Inject VIDIOC_STREAMON Error", | |
1050 | .type = V4L2_CTRL_TYPE_BUTTON, | |
1051 | }; | |
1052 | ||
1053 | static const struct v4l2_ctrl_config vivid_ctrl_queue_error = { | |
1054 | .ops = &vivid_streaming_ctrl_ops, | |
1055 | .id = VIVID_CID_QUEUE_ERROR, | |
1056 | .name = "Inject Fatal Streaming Error", | |
1057 | .type = V4L2_CTRL_TYPE_BUTTON, | |
1058 | }; | |
1059 | ||
1060 | static const struct v4l2_ctrl_config vivid_ctrl_seq_wrap = { | |
1061 | .ops = &vivid_streaming_ctrl_ops, | |
1062 | .id = VIVID_CID_SEQ_WRAP, | |
1063 | .name = "Wrap Sequence Number", | |
1064 | .type = V4L2_CTRL_TYPE_BOOLEAN, | |
1065 | .max = 1, | |
1066 | .step = 1, | |
1067 | }; | |
1068 | ||
1069 | static const struct v4l2_ctrl_config vivid_ctrl_time_wrap = { | |
1070 | .ops = &vivid_streaming_ctrl_ops, | |
1071 | .id = VIVID_CID_TIME_WRAP, | |
1072 | .name = "Wrap Timestamp", | |
1073 | .type = V4L2_CTRL_TYPE_BOOLEAN, | |
1074 | .max = 1, | |
1075 | .step = 1, | |
1076 | }; | |
1077 | ||
1078 | ||
1079 | /* SDTV Capture Controls */ | |
1080 | ||
1081 | static int vivid_sdtv_cap_s_ctrl(struct v4l2_ctrl *ctrl) | |
1082 | { | |
1083 | struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_sdtv_cap); | |
1084 | ||
1085 | switch (ctrl->id) { | |
1086 | case VIVID_CID_STD_SIGNAL_MODE: | |
1087 | dev->std_signal_mode = dev->ctrl_std_signal_mode->val; | |
1088 | if (dev->std_signal_mode == SELECTED_STD) | |
1089 | dev->query_std = vivid_standard[dev->ctrl_standard->val]; | |
1090 | v4l2_ctrl_activate(dev->ctrl_standard, dev->std_signal_mode == SELECTED_STD); | |
1091 | vivid_update_quality(dev); | |
1092 | vivid_send_source_change(dev, TV); | |
1093 | vivid_send_source_change(dev, SVID); | |
1094 | break; | |
1095 | } | |
1096 | return 0; | |
1097 | } | |
1098 | ||
1099 | static const struct v4l2_ctrl_ops vivid_sdtv_cap_ctrl_ops = { | |
1100 | .s_ctrl = vivid_sdtv_cap_s_ctrl, | |
1101 | }; | |
1102 | ||
1103 | static const char * const vivid_ctrl_std_signal_mode_strings[] = { | |
1104 | "Current Standard", | |
1105 | "No Signal", | |
1106 | "No Lock", | |
1107 | "", | |
1108 | "Selected Standard", | |
1109 | "Cycle Through All Standards", | |
1110 | NULL, | |
1111 | }; | |
1112 | ||
1113 | static const struct v4l2_ctrl_config vivid_ctrl_std_signal_mode = { | |
1114 | .ops = &vivid_sdtv_cap_ctrl_ops, | |
1115 | .id = VIVID_CID_STD_SIGNAL_MODE, | |
1116 | .name = "Standard Signal Mode", | |
1117 | .type = V4L2_CTRL_TYPE_MENU, | |
ff144726 | 1118 | .max = ARRAY_SIZE(vivid_ctrl_std_signal_mode_strings) - 2, |
73c3f482 HV |
1119 | .menu_skip_mask = 1 << 3, |
1120 | .qmenu = vivid_ctrl_std_signal_mode_strings, | |
1121 | }; | |
1122 | ||
1123 | static const struct v4l2_ctrl_config vivid_ctrl_standard = { | |
1124 | .ops = &vivid_sdtv_cap_ctrl_ops, | |
1125 | .id = VIVID_CID_STANDARD, | |
1126 | .name = "Standard", | |
1127 | .type = V4L2_CTRL_TYPE_MENU, | |
1128 | .max = 14, | |
1129 | .qmenu = vivid_ctrl_standard_strings, | |
1130 | }; | |
1131 | ||
1132 | ||
1133 | ||
1134 | /* Radio Receiver Controls */ | |
1135 | ||
1136 | static int vivid_radio_rx_s_ctrl(struct v4l2_ctrl *ctrl) | |
1137 | { | |
1138 | struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_radio_rx); | |
1139 | ||
1140 | switch (ctrl->id) { | |
1141 | case VIVID_CID_RADIO_SEEK_MODE: | |
1142 | dev->radio_rx_hw_seek_mode = ctrl->val; | |
1143 | break; | |
1144 | case VIVID_CID_RADIO_SEEK_PROG_LIM: | |
1145 | dev->radio_rx_hw_seek_prog_lim = ctrl->val; | |
1146 | break; | |
1147 | case VIVID_CID_RADIO_RX_RDS_RBDS: | |
1148 | dev->rds_gen.use_rbds = ctrl->val; | |
1149 | break; | |
1150 | case VIVID_CID_RADIO_RX_RDS_BLOCKIO: | |
1151 | dev->radio_rx_rds_controls = ctrl->val; | |
1152 | dev->radio_rx_caps &= ~V4L2_CAP_READWRITE; | |
1153 | dev->radio_rx_rds_use_alternates = false; | |
1154 | if (!dev->radio_rx_rds_controls) { | |
1155 | dev->radio_rx_caps |= V4L2_CAP_READWRITE; | |
1156 | __v4l2_ctrl_s_ctrl(dev->radio_rx_rds_pty, 0); | |
1157 | __v4l2_ctrl_s_ctrl(dev->radio_rx_rds_ta, 0); | |
1158 | __v4l2_ctrl_s_ctrl(dev->radio_rx_rds_tp, 0); | |
1159 | __v4l2_ctrl_s_ctrl(dev->radio_rx_rds_ms, 0); | |
1160 | __v4l2_ctrl_s_ctrl_string(dev->radio_rx_rds_psname, ""); | |
1161 | __v4l2_ctrl_s_ctrl_string(dev->radio_rx_rds_radiotext, ""); | |
1162 | } | |
1163 | v4l2_ctrl_activate(dev->radio_rx_rds_pty, dev->radio_rx_rds_controls); | |
1164 | v4l2_ctrl_activate(dev->radio_rx_rds_psname, dev->radio_rx_rds_controls); | |
1165 | v4l2_ctrl_activate(dev->radio_rx_rds_radiotext, dev->radio_rx_rds_controls); | |
1166 | v4l2_ctrl_activate(dev->radio_rx_rds_ta, dev->radio_rx_rds_controls); | |
1167 | v4l2_ctrl_activate(dev->radio_rx_rds_tp, dev->radio_rx_rds_controls); | |
1168 | v4l2_ctrl_activate(dev->radio_rx_rds_ms, dev->radio_rx_rds_controls); | |
1169 | break; | |
1170 | case V4L2_CID_RDS_RECEPTION: | |
1171 | dev->radio_rx_rds_enabled = ctrl->val; | |
1172 | break; | |
1173 | } | |
1174 | return 0; | |
1175 | } | |
1176 | ||
1177 | static const struct v4l2_ctrl_ops vivid_radio_rx_ctrl_ops = { | |
1178 | .s_ctrl = vivid_radio_rx_s_ctrl, | |
1179 | }; | |
1180 | ||
1181 | static const char * const vivid_ctrl_radio_rds_mode_strings[] = { | |
1182 | "Block I/O", | |
1183 | "Controls", | |
1184 | NULL, | |
1185 | }; | |
1186 | ||
1187 | static const struct v4l2_ctrl_config vivid_ctrl_radio_rx_rds_blockio = { | |
1188 | .ops = &vivid_radio_rx_ctrl_ops, | |
1189 | .id = VIVID_CID_RADIO_RX_RDS_BLOCKIO, | |
1190 | .name = "RDS Rx I/O Mode", | |
1191 | .type = V4L2_CTRL_TYPE_MENU, | |
1192 | .qmenu = vivid_ctrl_radio_rds_mode_strings, | |
1193 | .max = 1, | |
1194 | }; | |
1195 | ||
1196 | static const struct v4l2_ctrl_config vivid_ctrl_radio_rx_rds_rbds = { | |
1197 | .ops = &vivid_radio_rx_ctrl_ops, | |
1198 | .id = VIVID_CID_RADIO_RX_RDS_RBDS, | |
1199 | .name = "Generate RBDS Instead of RDS", | |
1200 | .type = V4L2_CTRL_TYPE_BOOLEAN, | |
1201 | .max = 1, | |
1202 | .step = 1, | |
1203 | }; | |
1204 | ||
1205 | static const char * const vivid_ctrl_radio_hw_seek_mode_strings[] = { | |
1206 | "Bounded", | |
1207 | "Wrap Around", | |
1208 | "Both", | |
1209 | NULL, | |
1210 | }; | |
1211 | ||
1212 | static const struct v4l2_ctrl_config vivid_ctrl_radio_hw_seek_mode = { | |
1213 | .ops = &vivid_radio_rx_ctrl_ops, | |
1214 | .id = VIVID_CID_RADIO_SEEK_MODE, | |
1215 | .name = "Radio HW Seek Mode", | |
1216 | .type = V4L2_CTRL_TYPE_MENU, | |
1217 | .max = 2, | |
1218 | .qmenu = vivid_ctrl_radio_hw_seek_mode_strings, | |
1219 | }; | |
1220 | ||
1221 | static const struct v4l2_ctrl_config vivid_ctrl_radio_hw_seek_prog_lim = { | |
1222 | .ops = &vivid_radio_rx_ctrl_ops, | |
1223 | .id = VIVID_CID_RADIO_SEEK_PROG_LIM, | |
1224 | .name = "Radio Programmable HW Seek", | |
1225 | .type = V4L2_CTRL_TYPE_BOOLEAN, | |
1226 | .max = 1, | |
1227 | .step = 1, | |
1228 | }; | |
1229 | ||
1230 | ||
1231 | /* Radio Transmitter Controls */ | |
1232 | ||
1233 | static int vivid_radio_tx_s_ctrl(struct v4l2_ctrl *ctrl) | |
1234 | { | |
1235 | struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_radio_tx); | |
1236 | ||
1237 | switch (ctrl->id) { | |
1238 | case VIVID_CID_RADIO_TX_RDS_BLOCKIO: | |
1239 | dev->radio_tx_rds_controls = ctrl->val; | |
1240 | dev->radio_tx_caps &= ~V4L2_CAP_READWRITE; | |
1241 | if (!dev->radio_tx_rds_controls) | |
1242 | dev->radio_tx_caps |= V4L2_CAP_READWRITE; | |
1243 | break; | |
1244 | case V4L2_CID_RDS_TX_PTY: | |
1245 | if (dev->radio_rx_rds_controls) | |
1246 | v4l2_ctrl_s_ctrl(dev->radio_rx_rds_pty, ctrl->val); | |
1247 | break; | |
1248 | case V4L2_CID_RDS_TX_PS_NAME: | |
1249 | if (dev->radio_rx_rds_controls) | |
1250 | v4l2_ctrl_s_ctrl_string(dev->radio_rx_rds_psname, ctrl->p_new.p_char); | |
1251 | break; | |
1252 | case V4L2_CID_RDS_TX_RADIO_TEXT: | |
1253 | if (dev->radio_rx_rds_controls) | |
1254 | v4l2_ctrl_s_ctrl_string(dev->radio_rx_rds_radiotext, ctrl->p_new.p_char); | |
1255 | break; | |
1256 | case V4L2_CID_RDS_TX_TRAFFIC_ANNOUNCEMENT: | |
1257 | if (dev->radio_rx_rds_controls) | |
1258 | v4l2_ctrl_s_ctrl(dev->radio_rx_rds_ta, ctrl->val); | |
1259 | break; | |
1260 | case V4L2_CID_RDS_TX_TRAFFIC_PROGRAM: | |
1261 | if (dev->radio_rx_rds_controls) | |
1262 | v4l2_ctrl_s_ctrl(dev->radio_rx_rds_tp, ctrl->val); | |
1263 | break; | |
1264 | case V4L2_CID_RDS_TX_MUSIC_SPEECH: | |
1265 | if (dev->radio_rx_rds_controls) | |
1266 | v4l2_ctrl_s_ctrl(dev->radio_rx_rds_ms, ctrl->val); | |
1267 | break; | |
1268 | } | |
1269 | return 0; | |
1270 | } | |
1271 | ||
1272 | static const struct v4l2_ctrl_ops vivid_radio_tx_ctrl_ops = { | |
1273 | .s_ctrl = vivid_radio_tx_s_ctrl, | |
1274 | }; | |
1275 | ||
1276 | static const struct v4l2_ctrl_config vivid_ctrl_radio_tx_rds_blockio = { | |
1277 | .ops = &vivid_radio_tx_ctrl_ops, | |
1278 | .id = VIVID_CID_RADIO_TX_RDS_BLOCKIO, | |
1279 | .name = "RDS Tx I/O Mode", | |
1280 | .type = V4L2_CTRL_TYPE_MENU, | |
1281 | .qmenu = vivid_ctrl_radio_rds_mode_strings, | |
1282 | .max = 1, | |
1283 | .def = 1, | |
1284 | }; | |
1285 | ||
1286 | ||
f335c3f2 AP |
1287 | /* SDR Capture Controls */ |
1288 | ||
1289 | static int vivid_sdr_cap_s_ctrl(struct v4l2_ctrl *ctrl) | |
1290 | { | |
1291 | struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_sdr_cap); | |
1292 | ||
1293 | switch (ctrl->id) { | |
1294 | case VIVID_CID_SDR_CAP_FM_DEVIATION: | |
1295 | dev->sdr_fm_deviation = ctrl->val; | |
1296 | break; | |
1297 | } | |
1298 | return 0; | |
1299 | } | |
1300 | ||
1301 | static const struct v4l2_ctrl_ops vivid_sdr_cap_ctrl_ops = { | |
1302 | .s_ctrl = vivid_sdr_cap_s_ctrl, | |
1303 | }; | |
1304 | ||
1305 | static const struct v4l2_ctrl_config vivid_ctrl_sdr_cap_fm_deviation = { | |
1306 | .ops = &vivid_sdr_cap_ctrl_ops, | |
1307 | .id = VIVID_CID_SDR_CAP_FM_DEVIATION, | |
1308 | .name = "FM Deviation", | |
1309 | .type = V4L2_CTRL_TYPE_INTEGER, | |
1310 | .min = 100, | |
1311 | .max = 200000, | |
1312 | .def = 75000, | |
1313 | .step = 1, | |
1314 | }; | |
1315 | ||
1316 | ||
73c3f482 HV |
1317 | static const struct v4l2_ctrl_config vivid_ctrl_class = { |
1318 | .ops = &vivid_user_gen_ctrl_ops, | |
1319 | .flags = V4L2_CTRL_FLAG_READ_ONLY | V4L2_CTRL_FLAG_WRITE_ONLY, | |
1320 | .id = VIVID_CID_VIVID_CLASS, | |
1321 | .name = "Vivid Controls", | |
1322 | .type = V4L2_CTRL_TYPE_CTRL_CLASS, | |
1323 | }; | |
1324 | ||
1325 | int vivid_create_controls(struct vivid_dev *dev, bool show_ccs_cap, | |
1326 | bool show_ccs_out, bool no_error_inj, | |
1327 | bool has_sdtv, bool has_hdmi) | |
1328 | { | |
1329 | struct v4l2_ctrl_handler *hdl_user_gen = &dev->ctrl_hdl_user_gen; | |
1330 | struct v4l2_ctrl_handler *hdl_user_vid = &dev->ctrl_hdl_user_vid; | |
1331 | struct v4l2_ctrl_handler *hdl_user_aud = &dev->ctrl_hdl_user_aud; | |
1332 | struct v4l2_ctrl_handler *hdl_streaming = &dev->ctrl_hdl_streaming; | |
1333 | struct v4l2_ctrl_handler *hdl_sdtv_cap = &dev->ctrl_hdl_sdtv_cap; | |
63344b65 | 1334 | struct v4l2_ctrl_handler *hdl_loop_cap = &dev->ctrl_hdl_loop_cap; |
73c3f482 HV |
1335 | struct v4l2_ctrl_handler *hdl_vid_cap = &dev->ctrl_hdl_vid_cap; |
1336 | struct v4l2_ctrl_handler *hdl_vid_out = &dev->ctrl_hdl_vid_out; | |
1337 | struct v4l2_ctrl_handler *hdl_vbi_cap = &dev->ctrl_hdl_vbi_cap; | |
1338 | struct v4l2_ctrl_handler *hdl_vbi_out = &dev->ctrl_hdl_vbi_out; | |
1339 | struct v4l2_ctrl_handler *hdl_radio_rx = &dev->ctrl_hdl_radio_rx; | |
1340 | struct v4l2_ctrl_handler *hdl_radio_tx = &dev->ctrl_hdl_radio_tx; | |
1341 | struct v4l2_ctrl_handler *hdl_sdr_cap = &dev->ctrl_hdl_sdr_cap; | |
1342 | struct v4l2_ctrl_config vivid_ctrl_dv_timings = { | |
1343 | .ops = &vivid_vid_cap_ctrl_ops, | |
1344 | .id = VIVID_CID_DV_TIMINGS, | |
1345 | .name = "DV Timings", | |
1346 | .type = V4L2_CTRL_TYPE_MENU, | |
1347 | }; | |
1348 | int i; | |
1349 | ||
1350 | v4l2_ctrl_handler_init(hdl_user_gen, 10); | |
1351 | v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_class, NULL); | |
1352 | v4l2_ctrl_handler_init(hdl_user_vid, 9); | |
1353 | v4l2_ctrl_new_custom(hdl_user_vid, &vivid_ctrl_class, NULL); | |
1354 | v4l2_ctrl_handler_init(hdl_user_aud, 2); | |
1355 | v4l2_ctrl_new_custom(hdl_user_aud, &vivid_ctrl_class, NULL); | |
1356 | v4l2_ctrl_handler_init(hdl_streaming, 8); | |
1357 | v4l2_ctrl_new_custom(hdl_streaming, &vivid_ctrl_class, NULL); | |
1358 | v4l2_ctrl_handler_init(hdl_sdtv_cap, 2); | |
1359 | v4l2_ctrl_new_custom(hdl_sdtv_cap, &vivid_ctrl_class, NULL); | |
63344b65 HV |
1360 | v4l2_ctrl_handler_init(hdl_loop_cap, 1); |
1361 | v4l2_ctrl_new_custom(hdl_loop_cap, &vivid_ctrl_class, NULL); | |
73c3f482 HV |
1362 | v4l2_ctrl_handler_init(hdl_vid_cap, 55); |
1363 | v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_class, NULL); | |
1364 | v4l2_ctrl_handler_init(hdl_vid_out, 26); | |
f6de9f60 HV |
1365 | if (!no_error_inj) |
1366 | v4l2_ctrl_new_custom(hdl_vid_out, &vivid_ctrl_class, NULL); | |
73c3f482 HV |
1367 | v4l2_ctrl_handler_init(hdl_vbi_cap, 21); |
1368 | v4l2_ctrl_new_custom(hdl_vbi_cap, &vivid_ctrl_class, NULL); | |
1369 | v4l2_ctrl_handler_init(hdl_vbi_out, 19); | |
f6de9f60 HV |
1370 | if (!no_error_inj) |
1371 | v4l2_ctrl_new_custom(hdl_vbi_out, &vivid_ctrl_class, NULL); | |
73c3f482 HV |
1372 | v4l2_ctrl_handler_init(hdl_radio_rx, 17); |
1373 | v4l2_ctrl_new_custom(hdl_radio_rx, &vivid_ctrl_class, NULL); | |
1374 | v4l2_ctrl_handler_init(hdl_radio_tx, 17); | |
1375 | v4l2_ctrl_new_custom(hdl_radio_tx, &vivid_ctrl_class, NULL); | |
f335c3f2 | 1376 | v4l2_ctrl_handler_init(hdl_sdr_cap, 19); |
73c3f482 HV |
1377 | v4l2_ctrl_new_custom(hdl_sdr_cap, &vivid_ctrl_class, NULL); |
1378 | ||
1379 | /* User Controls */ | |
1380 | dev->volume = v4l2_ctrl_new_std(hdl_user_aud, NULL, | |
1381 | V4L2_CID_AUDIO_VOLUME, 0, 255, 1, 200); | |
1382 | dev->mute = v4l2_ctrl_new_std(hdl_user_aud, NULL, | |
1383 | V4L2_CID_AUDIO_MUTE, 0, 1, 1, 0); | |
1384 | if (dev->has_vid_cap) { | |
1385 | dev->brightness = v4l2_ctrl_new_std(hdl_user_vid, &vivid_user_vid_ctrl_ops, | |
1386 | V4L2_CID_BRIGHTNESS, 0, 255, 1, 128); | |
1387 | for (i = 0; i < MAX_INPUTS; i++) | |
1388 | dev->input_brightness[i] = 128; | |
1389 | dev->contrast = v4l2_ctrl_new_std(hdl_user_vid, &vivid_user_vid_ctrl_ops, | |
1390 | V4L2_CID_CONTRAST, 0, 255, 1, 128); | |
1391 | dev->saturation = v4l2_ctrl_new_std(hdl_user_vid, &vivid_user_vid_ctrl_ops, | |
1392 | V4L2_CID_SATURATION, 0, 255, 1, 128); | |
1393 | dev->hue = v4l2_ctrl_new_std(hdl_user_vid, &vivid_user_vid_ctrl_ops, | |
1394 | V4L2_CID_HUE, -128, 128, 1, 0); | |
1395 | v4l2_ctrl_new_std(hdl_user_vid, &vivid_user_vid_ctrl_ops, | |
1396 | V4L2_CID_HFLIP, 0, 1, 1, 0); | |
1397 | v4l2_ctrl_new_std(hdl_user_vid, &vivid_user_vid_ctrl_ops, | |
1398 | V4L2_CID_VFLIP, 0, 1, 1, 0); | |
1399 | dev->autogain = v4l2_ctrl_new_std(hdl_user_vid, &vivid_user_vid_ctrl_ops, | |
1400 | V4L2_CID_AUTOGAIN, 0, 1, 1, 1); | |
1401 | dev->gain = v4l2_ctrl_new_std(hdl_user_vid, &vivid_user_vid_ctrl_ops, | |
1402 | V4L2_CID_GAIN, 0, 255, 1, 100); | |
1403 | dev->alpha = v4l2_ctrl_new_std(hdl_user_vid, &vivid_user_vid_ctrl_ops, | |
1404 | V4L2_CID_ALPHA_COMPONENT, 0, 255, 1, 0); | |
1405 | } | |
1406 | dev->button = v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_button, NULL); | |
1407 | dev->int32 = v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_int32, NULL); | |
1408 | dev->int64 = v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_int64, NULL); | |
1409 | dev->boolean = v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_boolean, NULL); | |
1410 | dev->menu = v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_menu, NULL); | |
1411 | dev->string = v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_string, NULL); | |
1412 | dev->bitmask = v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_bitmask, NULL); | |
1413 | dev->int_menu = v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_int_menu, NULL); | |
24c4942d HV |
1414 | v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_u32_array, NULL); |
1415 | v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_u16_matrix, NULL); | |
1416 | v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_u8_4d_array, NULL); | |
73c3f482 HV |
1417 | |
1418 | if (dev->has_vid_cap) { | |
1419 | /* Image Processing Controls */ | |
1420 | struct v4l2_ctrl_config vivid_ctrl_test_pattern = { | |
1421 | .ops = &vivid_vid_cap_ctrl_ops, | |
1422 | .id = VIVID_CID_TEST_PATTERN, | |
1423 | .name = "Test Pattern", | |
1424 | .type = V4L2_CTRL_TYPE_MENU, | |
1425 | .max = TPG_PAT_NOISE, | |
1426 | .qmenu = tpg_pattern_strings, | |
1427 | }; | |
1428 | ||
1429 | dev->test_pattern = v4l2_ctrl_new_custom(hdl_vid_cap, | |
1430 | &vivid_ctrl_test_pattern, NULL); | |
1431 | v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_perc_fill, NULL); | |
1432 | v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_hor_movement, NULL); | |
1433 | v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_vert_movement, NULL); | |
1434 | v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_osd_mode, NULL); | |
1435 | v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_show_border, NULL); | |
1436 | v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_show_square, NULL); | |
1437 | v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_hflip, NULL); | |
1438 | v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_vflip, NULL); | |
1439 | v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_insert_sav, NULL); | |
1440 | v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_insert_eav, NULL); | |
c79aa6ae | 1441 | v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_reduced_fps, NULL); |
73c3f482 HV |
1442 | if (show_ccs_cap) { |
1443 | dev->ctrl_has_crop_cap = v4l2_ctrl_new_custom(hdl_vid_cap, | |
1444 | &vivid_ctrl_has_crop_cap, NULL); | |
1445 | dev->ctrl_has_compose_cap = v4l2_ctrl_new_custom(hdl_vid_cap, | |
1446 | &vivid_ctrl_has_compose_cap, NULL); | |
1447 | dev->ctrl_has_scaler_cap = v4l2_ctrl_new_custom(hdl_vid_cap, | |
1448 | &vivid_ctrl_has_scaler_cap, NULL); | |
1449 | } | |
1450 | ||
1451 | v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_tstamp_src, NULL); | |
1452 | dev->colorspace = v4l2_ctrl_new_custom(hdl_vid_cap, | |
1453 | &vivid_ctrl_colorspace, NULL); | |
ca5316db | 1454 | v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_xfer_func, NULL); |
3e8a78d1 HV |
1455 | v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_ycbcr_enc, NULL); |
1456 | v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_quantization, NULL); | |
73c3f482 HV |
1457 | v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_alpha_mode, NULL); |
1458 | } | |
1459 | ||
1460 | if (dev->has_vid_out && show_ccs_out) { | |
1461 | dev->ctrl_has_crop_out = v4l2_ctrl_new_custom(hdl_vid_out, | |
1462 | &vivid_ctrl_has_crop_out, NULL); | |
1463 | dev->ctrl_has_compose_out = v4l2_ctrl_new_custom(hdl_vid_out, | |
1464 | &vivid_ctrl_has_compose_out, NULL); | |
1465 | dev->ctrl_has_scaler_out = v4l2_ctrl_new_custom(hdl_vid_out, | |
1466 | &vivid_ctrl_has_scaler_out, NULL); | |
1467 | } | |
1468 | ||
1469 | /* | |
1470 | * Testing this driver with v4l2-compliance will trigger the error | |
1471 | * injection controls, and after that nothing will work as expected. | |
1472 | * So we have a module option to drop these error injecting controls | |
1473 | * allowing us to run v4l2_compliance again. | |
1474 | */ | |
1475 | if (!no_error_inj) { | |
1476 | v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_disconnect, NULL); | |
1477 | v4l2_ctrl_new_custom(hdl_streaming, &vivid_ctrl_dqbuf_error, NULL); | |
1478 | v4l2_ctrl_new_custom(hdl_streaming, &vivid_ctrl_perc_dropped, NULL); | |
1479 | v4l2_ctrl_new_custom(hdl_streaming, &vivid_ctrl_queue_setup_error, NULL); | |
1480 | v4l2_ctrl_new_custom(hdl_streaming, &vivid_ctrl_buf_prepare_error, NULL); | |
1481 | v4l2_ctrl_new_custom(hdl_streaming, &vivid_ctrl_start_streaming_error, NULL); | |
1482 | v4l2_ctrl_new_custom(hdl_streaming, &vivid_ctrl_queue_error, NULL); | |
1483 | v4l2_ctrl_new_custom(hdl_streaming, &vivid_ctrl_seq_wrap, NULL); | |
1484 | v4l2_ctrl_new_custom(hdl_streaming, &vivid_ctrl_time_wrap, NULL); | |
1485 | } | |
1486 | ||
1487 | if (has_sdtv && (dev->has_vid_cap || dev->has_vbi_cap)) { | |
1488 | if (dev->has_vid_cap) | |
1489 | v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_std_aspect_ratio, NULL); | |
1490 | dev->ctrl_std_signal_mode = v4l2_ctrl_new_custom(hdl_sdtv_cap, | |
1491 | &vivid_ctrl_std_signal_mode, NULL); | |
1492 | dev->ctrl_standard = v4l2_ctrl_new_custom(hdl_sdtv_cap, | |
1493 | &vivid_ctrl_standard, NULL); | |
1494 | if (dev->ctrl_std_signal_mode) | |
1495 | v4l2_ctrl_cluster(2, &dev->ctrl_std_signal_mode); | |
1496 | if (dev->has_raw_vbi_cap) | |
1497 | v4l2_ctrl_new_custom(hdl_vbi_cap, &vivid_ctrl_vbi_cap_interlaced, NULL); | |
1498 | } | |
1499 | ||
1500 | if (has_hdmi && dev->has_vid_cap) { | |
1501 | dev->ctrl_dv_timings_signal_mode = v4l2_ctrl_new_custom(hdl_vid_cap, | |
1502 | &vivid_ctrl_dv_timings_signal_mode, NULL); | |
1503 | ||
1504 | vivid_ctrl_dv_timings.max = dev->query_dv_timings_size - 1; | |
1505 | vivid_ctrl_dv_timings.qmenu = | |
1506 | (const char * const *)dev->query_dv_timings_qmenu; | |
1507 | dev->ctrl_dv_timings = v4l2_ctrl_new_custom(hdl_vid_cap, | |
1508 | &vivid_ctrl_dv_timings, NULL); | |
1509 | if (dev->ctrl_dv_timings_signal_mode) | |
1510 | v4l2_ctrl_cluster(2, &dev->ctrl_dv_timings_signal_mode); | |
1511 | ||
1512 | v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_dv_timings_aspect_ratio, NULL); | |
1513 | v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_max_edid_blocks, NULL); | |
1514 | dev->real_rgb_range_cap = v4l2_ctrl_new_custom(hdl_vid_cap, | |
1515 | &vivid_ctrl_limited_rgb_range, NULL); | |
1516 | dev->rgb_range_cap = v4l2_ctrl_new_std_menu(hdl_vid_cap, | |
1517 | &vivid_vid_cap_ctrl_ops, | |
1518 | V4L2_CID_DV_RX_RGB_RANGE, V4L2_DV_RGB_RANGE_FULL, | |
1519 | 0, V4L2_DV_RGB_RANGE_AUTO); | |
1520 | } | |
1521 | if (has_hdmi && dev->has_vid_out) { | |
1522 | /* | |
1523 | * We aren't doing anything with this at the moment, but | |
1524 | * HDMI outputs typically have this controls. | |
1525 | */ | |
1526 | dev->ctrl_tx_rgb_range = v4l2_ctrl_new_std_menu(hdl_vid_out, NULL, | |
1527 | V4L2_CID_DV_TX_RGB_RANGE, V4L2_DV_RGB_RANGE_FULL, | |
1528 | 0, V4L2_DV_RGB_RANGE_AUTO); | |
1529 | dev->ctrl_tx_mode = v4l2_ctrl_new_std_menu(hdl_vid_out, NULL, | |
1530 | V4L2_CID_DV_TX_MODE, V4L2_DV_TX_MODE_HDMI, | |
1531 | 0, V4L2_DV_TX_MODE_HDMI); | |
1532 | } | |
1533 | if ((dev->has_vid_cap && dev->has_vid_out) || | |
1534 | (dev->has_vbi_cap && dev->has_vbi_out)) | |
63344b65 | 1535 | v4l2_ctrl_new_custom(hdl_loop_cap, &vivid_ctrl_loop_video, NULL); |
73c3f482 HV |
1536 | |
1537 | if (dev->has_fb) | |
1538 | v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_clear_fb, NULL); | |
1539 | ||
1540 | if (dev->has_radio_rx) { | |
1541 | v4l2_ctrl_new_custom(hdl_radio_rx, &vivid_ctrl_radio_hw_seek_mode, NULL); | |
1542 | v4l2_ctrl_new_custom(hdl_radio_rx, &vivid_ctrl_radio_hw_seek_prog_lim, NULL); | |
1543 | v4l2_ctrl_new_custom(hdl_radio_rx, &vivid_ctrl_radio_rx_rds_blockio, NULL); | |
1544 | v4l2_ctrl_new_custom(hdl_radio_rx, &vivid_ctrl_radio_rx_rds_rbds, NULL); | |
1545 | v4l2_ctrl_new_std(hdl_radio_rx, &vivid_radio_rx_ctrl_ops, | |
1546 | V4L2_CID_RDS_RECEPTION, 0, 1, 1, 1); | |
1547 | dev->radio_rx_rds_pty = v4l2_ctrl_new_std(hdl_radio_rx, | |
1548 | &vivid_radio_rx_ctrl_ops, | |
1549 | V4L2_CID_RDS_RX_PTY, 0, 31, 1, 0); | |
1550 | dev->radio_rx_rds_psname = v4l2_ctrl_new_std(hdl_radio_rx, | |
1551 | &vivid_radio_rx_ctrl_ops, | |
1552 | V4L2_CID_RDS_RX_PS_NAME, 0, 8, 8, 0); | |
1553 | dev->radio_rx_rds_radiotext = v4l2_ctrl_new_std(hdl_radio_rx, | |
1554 | &vivid_radio_rx_ctrl_ops, | |
1555 | V4L2_CID_RDS_RX_RADIO_TEXT, 0, 64, 64, 0); | |
1556 | dev->radio_rx_rds_ta = v4l2_ctrl_new_std(hdl_radio_rx, | |
1557 | &vivid_radio_rx_ctrl_ops, | |
1558 | V4L2_CID_RDS_RX_TRAFFIC_ANNOUNCEMENT, 0, 1, 1, 0); | |
1559 | dev->radio_rx_rds_tp = v4l2_ctrl_new_std(hdl_radio_rx, | |
1560 | &vivid_radio_rx_ctrl_ops, | |
1561 | V4L2_CID_RDS_RX_TRAFFIC_PROGRAM, 0, 1, 1, 0); | |
1562 | dev->radio_rx_rds_ms = v4l2_ctrl_new_std(hdl_radio_rx, | |
1563 | &vivid_radio_rx_ctrl_ops, | |
1564 | V4L2_CID_RDS_RX_MUSIC_SPEECH, 0, 1, 1, 1); | |
1565 | } | |
1566 | if (dev->has_radio_tx) { | |
1567 | v4l2_ctrl_new_custom(hdl_radio_tx, | |
1568 | &vivid_ctrl_radio_tx_rds_blockio, NULL); | |
1569 | dev->radio_tx_rds_pi = v4l2_ctrl_new_std(hdl_radio_tx, | |
1570 | &vivid_radio_tx_ctrl_ops, | |
1571 | V4L2_CID_RDS_TX_PI, 0, 0xffff, 1, 0x8088); | |
1572 | dev->radio_tx_rds_pty = v4l2_ctrl_new_std(hdl_radio_tx, | |
1573 | &vivid_radio_tx_ctrl_ops, | |
1574 | V4L2_CID_RDS_TX_PTY, 0, 31, 1, 3); | |
1575 | dev->radio_tx_rds_psname = v4l2_ctrl_new_std(hdl_radio_tx, | |
1576 | &vivid_radio_tx_ctrl_ops, | |
1577 | V4L2_CID_RDS_TX_PS_NAME, 0, 8, 8, 0); | |
1578 | if (dev->radio_tx_rds_psname) | |
1579 | v4l2_ctrl_s_ctrl_string(dev->radio_tx_rds_psname, "VIVID-TX"); | |
1580 | dev->radio_tx_rds_radiotext = v4l2_ctrl_new_std(hdl_radio_tx, | |
1581 | &vivid_radio_tx_ctrl_ops, | |
1582 | V4L2_CID_RDS_TX_RADIO_TEXT, 0, 64 * 2, 64, 0); | |
1583 | if (dev->radio_tx_rds_radiotext) | |
1584 | v4l2_ctrl_s_ctrl_string(dev->radio_tx_rds_radiotext, | |
1585 | "This is a VIVID default Radio Text template text, change at will"); | |
1586 | dev->radio_tx_rds_mono_stereo = v4l2_ctrl_new_std(hdl_radio_tx, | |
1587 | &vivid_radio_tx_ctrl_ops, | |
1588 | V4L2_CID_RDS_TX_MONO_STEREO, 0, 1, 1, 1); | |
1589 | dev->radio_tx_rds_art_head = v4l2_ctrl_new_std(hdl_radio_tx, | |
1590 | &vivid_radio_tx_ctrl_ops, | |
1591 | V4L2_CID_RDS_TX_ARTIFICIAL_HEAD, 0, 1, 1, 0); | |
1592 | dev->radio_tx_rds_compressed = v4l2_ctrl_new_std(hdl_radio_tx, | |
1593 | &vivid_radio_tx_ctrl_ops, | |
1594 | V4L2_CID_RDS_TX_COMPRESSED, 0, 1, 1, 0); | |
1595 | dev->radio_tx_rds_dyn_pty = v4l2_ctrl_new_std(hdl_radio_tx, | |
1596 | &vivid_radio_tx_ctrl_ops, | |
1597 | V4L2_CID_RDS_TX_DYNAMIC_PTY, 0, 1, 1, 0); | |
1598 | dev->radio_tx_rds_ta = v4l2_ctrl_new_std(hdl_radio_tx, | |
1599 | &vivid_radio_tx_ctrl_ops, | |
1600 | V4L2_CID_RDS_TX_TRAFFIC_ANNOUNCEMENT, 0, 1, 1, 0); | |
1601 | dev->radio_tx_rds_tp = v4l2_ctrl_new_std(hdl_radio_tx, | |
1602 | &vivid_radio_tx_ctrl_ops, | |
1603 | V4L2_CID_RDS_TX_TRAFFIC_PROGRAM, 0, 1, 1, 1); | |
1604 | dev->radio_tx_rds_ms = v4l2_ctrl_new_std(hdl_radio_tx, | |
1605 | &vivid_radio_tx_ctrl_ops, | |
1606 | V4L2_CID_RDS_TX_MUSIC_SPEECH, 0, 1, 1, 1); | |
1607 | } | |
f335c3f2 AP |
1608 | if (dev->has_sdr_cap) { |
1609 | v4l2_ctrl_new_custom(hdl_sdr_cap, | |
1610 | &vivid_ctrl_sdr_cap_fm_deviation, NULL); | |
1611 | } | |
73c3f482 HV |
1612 | if (hdl_user_gen->error) |
1613 | return hdl_user_gen->error; | |
1614 | if (hdl_user_vid->error) | |
1615 | return hdl_user_vid->error; | |
1616 | if (hdl_user_aud->error) | |
1617 | return hdl_user_aud->error; | |
1618 | if (hdl_streaming->error) | |
1619 | return hdl_streaming->error; | |
1620 | if (hdl_sdr_cap->error) | |
1621 | return hdl_sdr_cap->error; | |
63344b65 HV |
1622 | if (hdl_loop_cap->error) |
1623 | return hdl_loop_cap->error; | |
73c3f482 HV |
1624 | |
1625 | if (dev->autogain) | |
1626 | v4l2_ctrl_auto_cluster(2, &dev->autogain, 0, true); | |
1627 | ||
1628 | if (dev->has_vid_cap) { | |
1629 | v4l2_ctrl_add_handler(hdl_vid_cap, hdl_user_gen, NULL); | |
1630 | v4l2_ctrl_add_handler(hdl_vid_cap, hdl_user_vid, NULL); | |
1631 | v4l2_ctrl_add_handler(hdl_vid_cap, hdl_user_aud, NULL); | |
1632 | v4l2_ctrl_add_handler(hdl_vid_cap, hdl_streaming, NULL); | |
1633 | v4l2_ctrl_add_handler(hdl_vid_cap, hdl_sdtv_cap, NULL); | |
63344b65 | 1634 | v4l2_ctrl_add_handler(hdl_vid_cap, hdl_loop_cap, NULL); |
73c3f482 HV |
1635 | if (hdl_vid_cap->error) |
1636 | return hdl_vid_cap->error; | |
1637 | dev->vid_cap_dev.ctrl_handler = hdl_vid_cap; | |
1638 | } | |
1639 | if (dev->has_vid_out) { | |
1640 | v4l2_ctrl_add_handler(hdl_vid_out, hdl_user_gen, NULL); | |
1641 | v4l2_ctrl_add_handler(hdl_vid_out, hdl_user_aud, NULL); | |
1642 | v4l2_ctrl_add_handler(hdl_vid_out, hdl_streaming, NULL); | |
73c3f482 HV |
1643 | if (hdl_vid_out->error) |
1644 | return hdl_vid_out->error; | |
1645 | dev->vid_out_dev.ctrl_handler = hdl_vid_out; | |
1646 | } | |
1647 | if (dev->has_vbi_cap) { | |
1648 | v4l2_ctrl_add_handler(hdl_vbi_cap, hdl_user_gen, NULL); | |
1649 | v4l2_ctrl_add_handler(hdl_vbi_cap, hdl_streaming, NULL); | |
1650 | v4l2_ctrl_add_handler(hdl_vbi_cap, hdl_sdtv_cap, NULL); | |
63344b65 | 1651 | v4l2_ctrl_add_handler(hdl_vbi_cap, hdl_loop_cap, NULL); |
73c3f482 HV |
1652 | if (hdl_vbi_cap->error) |
1653 | return hdl_vbi_cap->error; | |
1654 | dev->vbi_cap_dev.ctrl_handler = hdl_vbi_cap; | |
1655 | } | |
1656 | if (dev->has_vbi_out) { | |
1657 | v4l2_ctrl_add_handler(hdl_vbi_out, hdl_user_gen, NULL); | |
1658 | v4l2_ctrl_add_handler(hdl_vbi_out, hdl_streaming, NULL); | |
73c3f482 HV |
1659 | if (hdl_vbi_out->error) |
1660 | return hdl_vbi_out->error; | |
1661 | dev->vbi_out_dev.ctrl_handler = hdl_vbi_out; | |
1662 | } | |
1663 | if (dev->has_radio_rx) { | |
1664 | v4l2_ctrl_add_handler(hdl_radio_rx, hdl_user_gen, NULL); | |
1665 | v4l2_ctrl_add_handler(hdl_radio_rx, hdl_user_aud, NULL); | |
1666 | if (hdl_radio_rx->error) | |
1667 | return hdl_radio_rx->error; | |
1668 | dev->radio_rx_dev.ctrl_handler = hdl_radio_rx; | |
1669 | } | |
1670 | if (dev->has_radio_tx) { | |
1671 | v4l2_ctrl_add_handler(hdl_radio_tx, hdl_user_gen, NULL); | |
1672 | v4l2_ctrl_add_handler(hdl_radio_tx, hdl_user_aud, NULL); | |
1673 | if (hdl_radio_tx->error) | |
1674 | return hdl_radio_tx->error; | |
1675 | dev->radio_tx_dev.ctrl_handler = hdl_radio_tx; | |
1676 | } | |
1677 | if (dev->has_sdr_cap) { | |
1678 | v4l2_ctrl_add_handler(hdl_sdr_cap, hdl_user_gen, NULL); | |
1679 | v4l2_ctrl_add_handler(hdl_sdr_cap, hdl_streaming, NULL); | |
1680 | if (hdl_sdr_cap->error) | |
1681 | return hdl_sdr_cap->error; | |
1682 | dev->sdr_cap_dev.ctrl_handler = hdl_sdr_cap; | |
1683 | } | |
1684 | return 0; | |
1685 | } | |
1686 | ||
1687 | void vivid_free_controls(struct vivid_dev *dev) | |
1688 | { | |
1689 | v4l2_ctrl_handler_free(&dev->ctrl_hdl_vid_cap); | |
1690 | v4l2_ctrl_handler_free(&dev->ctrl_hdl_vid_out); | |
1691 | v4l2_ctrl_handler_free(&dev->ctrl_hdl_vbi_cap); | |
1692 | v4l2_ctrl_handler_free(&dev->ctrl_hdl_vbi_out); | |
1693 | v4l2_ctrl_handler_free(&dev->ctrl_hdl_radio_rx); | |
1694 | v4l2_ctrl_handler_free(&dev->ctrl_hdl_radio_tx); | |
1695 | v4l2_ctrl_handler_free(&dev->ctrl_hdl_sdr_cap); | |
1696 | v4l2_ctrl_handler_free(&dev->ctrl_hdl_user_gen); | |
1697 | v4l2_ctrl_handler_free(&dev->ctrl_hdl_user_vid); | |
1698 | v4l2_ctrl_handler_free(&dev->ctrl_hdl_user_aud); | |
1699 | v4l2_ctrl_handler_free(&dev->ctrl_hdl_streaming); | |
1700 | v4l2_ctrl_handler_free(&dev->ctrl_hdl_sdtv_cap); | |
63344b65 | 1701 | v4l2_ctrl_handler_free(&dev->ctrl_hdl_loop_cap); |
73c3f482 | 1702 | } |