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