Input: xpad - add support for Xbox1 PDP Camo series gamepad
[linux/fpc-iii.git] / drivers / media / platform / vivid / vivid-ctrls.c
blobb1c37252a6c7621254af52ca492e9c40d0d53ad1
1 /*
2 * vivid-ctrls.c - control support functions.
4 * Copyright 2014 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
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.
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.
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>
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"
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)
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)
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)
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)
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)
81 #define VIVID_CID_REDUCED_FPS (VIVID_CID_VIVID_BASE + 42)
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)
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)
101 #define VIVID_CID_RADIO_TX_RDS_BLOCKIO (VIVID_CID_VIVID_BASE + 94)
103 #define VIVID_CID_SDR_CAP_FM_DEVIATION (VIVID_CID_VIVID_BASE + 110)
105 /* General User Controls */
107 static int vivid_user_gen_s_ctrl(struct v4l2_ctrl *ctrl)
109 struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_user_gen);
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;
129 return 0;
132 static const struct v4l2_ctrl_ops vivid_user_gen_ctrl_ops = {
133 .s_ctrl = vivid_user_gen_s_ctrl,
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,
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,
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,
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,
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 },
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 },
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 },
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,
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,
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,
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,
253 static const s64 vivid_ctrl_int_menu_values[] = {
254 1, 1, 2, 3, 5, 8, 13, 21, 42,
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,
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,
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,
284 /* Video User Controls */
286 static int vivid_user_vid_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
288 struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_user_vid);
290 switch (ctrl->id) {
291 case V4L2_CID_AUTOGAIN:
292 dev->gain->val = dev->jiffies_vid_cap & 0xff;
293 break;
295 return 0;
298 static int vivid_user_vid_s_ctrl(struct v4l2_ctrl *ctrl)
300 struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_user_vid);
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;
328 return 0;
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,
337 /* Video Capture Controls */
339 static int vivid_vid_cap_s_ctrl(struct v4l2_ctrl *ctrl)
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,
347 V4L2_COLORSPACE_DCI_P3,
348 V4L2_COLORSPACE_SMPTE240M,
349 V4L2_COLORSPACE_470_SYSTEM_M,
350 V4L2_COLORSPACE_470_SYSTEM_BG,
352 struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_vid_cap);
353 unsigned i;
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:
361 tpg_s_colorspace(&dev->tpg, colorspaces[ctrl->val]);
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;
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;
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;
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;
428 case VIVID_CID_REDUCED_FPS:
429 dev->reduced_fps = ctrl->val;
430 vivid_update_format_cap(dev, true);
431 break;
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;
479 return 0;
482 static const struct v4l2_ctrl_ops vivid_vid_cap_ctrl_ops = {
483 .s_ctrl = vivid_vid_cap_s_ctrl,
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,
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,
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,
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,
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,
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,
546 static const char * const vivid_ctrl_osd_mode_strings[] = {
547 "All",
548 "Counters Only",
549 "None",
550 NULL,
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,
558 .max = ARRAY_SIZE(vivid_ctrl_osd_mode_strings) - 2,
559 .qmenu = vivid_ctrl_osd_mode_strings,
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,
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,
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,
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,
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,
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,
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,
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,
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,
648 static const char * const vivid_ctrl_tstamp_src_strings[] = {
649 "End of Frame",
650 "Start of Exposure",
651 NULL,
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,
659 .max = ARRAY_SIZE(vivid_ctrl_tstamp_src_strings) - 2,
660 .qmenu = vivid_ctrl_tstamp_src_strings,
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,
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,
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,
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,
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,
714 static const char * const vivid_ctrl_colorspace_strings[] = {
715 "SMPTE 170M",
716 "Rec. 709",
717 "sRGB",
718 "AdobeRGB",
719 "BT.2020",
720 "DCI-P3",
721 "SMPTE 240M",
722 "470 System M",
723 "470 System BG",
724 NULL,
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,
732 .max = ARRAY_SIZE(vivid_ctrl_colorspace_strings) - 2,
733 .def = 2,
734 .qmenu = vivid_ctrl_colorspace_strings,
737 static const char * const vivid_ctrl_xfer_func_strings[] = {
738 "Default",
739 "Rec. 709",
740 "sRGB",
741 "AdobeRGB",
742 "SMPTE 240M",
743 "None",
744 "DCI-P3",
745 "SMPTE 2084",
746 NULL,
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,
754 .max = ARRAY_SIZE(vivid_ctrl_xfer_func_strings) - 2,
755 .qmenu = vivid_ctrl_xfer_func_strings,
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",
765 "BT.2020",
766 "BT.2020 Constant Luminance",
767 "SMPTE 240M",
768 NULL,
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,
776 .menu_skip_mask = 1 << 5,
777 .max = ARRAY_SIZE(vivid_ctrl_ycbcr_enc_strings) - 2,
778 .qmenu = vivid_ctrl_ycbcr_enc_strings,
781 static const char * const vivid_ctrl_quantization_strings[] = {
782 "Default",
783 "Full Range",
784 "Limited Range",
785 NULL,
788 static const struct v4l2_ctrl_config vivid_ctrl_quantization = {
789 .ops = &vivid_vid_cap_ctrl_ops,
790 .id = VIVID_CID_QUANTIZATION,
791 .name = "Quantization",
792 .type = V4L2_CTRL_TYPE_MENU,
793 .max = ARRAY_SIZE(vivid_ctrl_quantization_strings) - 2,
794 .qmenu = vivid_ctrl_quantization_strings,
797 static const struct v4l2_ctrl_config vivid_ctrl_alpha_mode = {
798 .ops = &vivid_vid_cap_ctrl_ops,
799 .id = VIVID_CID_ALPHA_MODE,
800 .name = "Apply Alpha To Red Only",
801 .type = V4L2_CTRL_TYPE_BOOLEAN,
802 .max = 1,
803 .step = 1,
806 static const struct v4l2_ctrl_config vivid_ctrl_limited_rgb_range = {
807 .ops = &vivid_vid_cap_ctrl_ops,
808 .id = VIVID_CID_LIMITED_RGB_RANGE,
809 .name = "Limited RGB Range (16-235)",
810 .type = V4L2_CTRL_TYPE_BOOLEAN,
811 .max = 1,
812 .step = 1,
816 /* Video Loop Control */
818 static int vivid_loop_cap_s_ctrl(struct v4l2_ctrl *ctrl)
820 struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_loop_cap);
822 switch (ctrl->id) {
823 case VIVID_CID_LOOP_VIDEO:
824 dev->loop_video = ctrl->val;
825 vivid_update_quality(dev);
826 vivid_send_source_change(dev, SVID);
827 vivid_send_source_change(dev, HDMI);
828 break;
830 return 0;
833 static const struct v4l2_ctrl_ops vivid_loop_cap_ctrl_ops = {
834 .s_ctrl = vivid_loop_cap_s_ctrl,
837 static const struct v4l2_ctrl_config vivid_ctrl_loop_video = {
838 .ops = &vivid_loop_cap_ctrl_ops,
839 .id = VIVID_CID_LOOP_VIDEO,
840 .name = "Loop Video",
841 .type = V4L2_CTRL_TYPE_BOOLEAN,
842 .max = 1,
843 .step = 1,
847 /* VBI Capture Control */
849 static int vivid_vbi_cap_s_ctrl(struct v4l2_ctrl *ctrl)
851 struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_vbi_cap);
853 switch (ctrl->id) {
854 case VIVID_CID_VBI_CAP_INTERLACED:
855 dev->vbi_cap_interlaced = ctrl->val;
856 break;
858 return 0;
861 static const struct v4l2_ctrl_ops vivid_vbi_cap_ctrl_ops = {
862 .s_ctrl = vivid_vbi_cap_s_ctrl,
865 static const struct v4l2_ctrl_config vivid_ctrl_vbi_cap_interlaced = {
866 .ops = &vivid_vbi_cap_ctrl_ops,
867 .id = VIVID_CID_VBI_CAP_INTERLACED,
868 .name = "Interlaced VBI Format",
869 .type = V4L2_CTRL_TYPE_BOOLEAN,
870 .max = 1,
871 .step = 1,
875 /* Video Output Controls */
877 static int vivid_vid_out_s_ctrl(struct v4l2_ctrl *ctrl)
879 struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_vid_out);
880 struct v4l2_bt_timings *bt = &dev->dv_timings_out.bt;
882 switch (ctrl->id) {
883 case VIVID_CID_HAS_CROP_OUT:
884 dev->has_crop_out = ctrl->val;
885 vivid_update_format_out(dev);
886 break;
887 case VIVID_CID_HAS_COMPOSE_OUT:
888 dev->has_compose_out = ctrl->val;
889 vivid_update_format_out(dev);
890 break;
891 case VIVID_CID_HAS_SCALER_OUT:
892 dev->has_scaler_out = ctrl->val;
893 vivid_update_format_out(dev);
894 break;
895 case V4L2_CID_DV_TX_MODE:
896 dev->dvi_d_out = ctrl->val == V4L2_DV_TX_MODE_DVI_D;
897 if (!vivid_is_hdmi_out(dev))
898 break;
899 if (!dev->dvi_d_out && (bt->flags & V4L2_DV_FL_IS_CE_VIDEO)) {
900 if (bt->width == 720 && bt->height <= 576)
901 dev->colorspace_out = V4L2_COLORSPACE_SMPTE170M;
902 else
903 dev->colorspace_out = V4L2_COLORSPACE_REC709;
904 dev->quantization_out = V4L2_QUANTIZATION_DEFAULT;
905 } else {
906 dev->colorspace_out = V4L2_COLORSPACE_SRGB;
907 dev->quantization_out = dev->dvi_d_out ?
908 V4L2_QUANTIZATION_LIM_RANGE :
909 V4L2_QUANTIZATION_DEFAULT;
911 if (dev->loop_video)
912 vivid_send_source_change(dev, HDMI);
913 break;
915 return 0;
918 static const struct v4l2_ctrl_ops vivid_vid_out_ctrl_ops = {
919 .s_ctrl = vivid_vid_out_s_ctrl,
922 static const struct v4l2_ctrl_config vivid_ctrl_has_crop_out = {
923 .ops = &vivid_vid_out_ctrl_ops,
924 .id = VIVID_CID_HAS_CROP_OUT,
925 .name = "Enable Output Cropping",
926 .type = V4L2_CTRL_TYPE_BOOLEAN,
927 .max = 1,
928 .def = 1,
929 .step = 1,
932 static const struct v4l2_ctrl_config vivid_ctrl_has_compose_out = {
933 .ops = &vivid_vid_out_ctrl_ops,
934 .id = VIVID_CID_HAS_COMPOSE_OUT,
935 .name = "Enable Output Composing",
936 .type = V4L2_CTRL_TYPE_BOOLEAN,
937 .max = 1,
938 .def = 1,
939 .step = 1,
942 static const struct v4l2_ctrl_config vivid_ctrl_has_scaler_out = {
943 .ops = &vivid_vid_out_ctrl_ops,
944 .id = VIVID_CID_HAS_SCALER_OUT,
945 .name = "Enable Output Scaler",
946 .type = V4L2_CTRL_TYPE_BOOLEAN,
947 .max = 1,
948 .def = 1,
949 .step = 1,
953 /* Streaming Controls */
955 static int vivid_streaming_s_ctrl(struct v4l2_ctrl *ctrl)
957 struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_streaming);
958 u64 rem;
960 switch (ctrl->id) {
961 case VIVID_CID_DQBUF_ERROR:
962 dev->dqbuf_error = true;
963 break;
964 case VIVID_CID_PERC_DROPPED:
965 dev->perc_dropped_buffers = ctrl->val;
966 break;
967 case VIVID_CID_QUEUE_SETUP_ERROR:
968 dev->queue_setup_error = true;
969 break;
970 case VIVID_CID_BUF_PREPARE_ERROR:
971 dev->buf_prepare_error = true;
972 break;
973 case VIVID_CID_START_STR_ERROR:
974 dev->start_streaming_error = true;
975 break;
976 case VIVID_CID_QUEUE_ERROR:
977 if (vb2_start_streaming_called(&dev->vb_vid_cap_q))
978 vb2_queue_error(&dev->vb_vid_cap_q);
979 if (vb2_start_streaming_called(&dev->vb_vbi_cap_q))
980 vb2_queue_error(&dev->vb_vbi_cap_q);
981 if (vb2_start_streaming_called(&dev->vb_vid_out_q))
982 vb2_queue_error(&dev->vb_vid_out_q);
983 if (vb2_start_streaming_called(&dev->vb_vbi_out_q))
984 vb2_queue_error(&dev->vb_vbi_out_q);
985 if (vb2_start_streaming_called(&dev->vb_sdr_cap_q))
986 vb2_queue_error(&dev->vb_sdr_cap_q);
987 break;
988 case VIVID_CID_SEQ_WRAP:
989 dev->seq_wrap = ctrl->val;
990 break;
991 case VIVID_CID_TIME_WRAP:
992 dev->time_wrap = ctrl->val;
993 if (ctrl->val == 0) {
994 dev->time_wrap_offset = 0;
995 break;
998 * We want to set the time 16 seconds before the 32 bit tv_sec
999 * value of struct timeval would wrap around. So first we
1000 * calculate ktime_get_ns() % ((1 << 32) * NSEC_PER_SEC), and
1001 * then we set the offset to ((1 << 32) - 16) * NSEC_PER_SEC).
1003 div64_u64_rem(ktime_get_ns(),
1004 0x100000000ULL * NSEC_PER_SEC, &rem);
1005 dev->time_wrap_offset =
1006 (0x100000000ULL - 16) * NSEC_PER_SEC - rem;
1007 break;
1009 return 0;
1012 static const struct v4l2_ctrl_ops vivid_streaming_ctrl_ops = {
1013 .s_ctrl = vivid_streaming_s_ctrl,
1016 static const struct v4l2_ctrl_config vivid_ctrl_dqbuf_error = {
1017 .ops = &vivid_streaming_ctrl_ops,
1018 .id = VIVID_CID_DQBUF_ERROR,
1019 .name = "Inject V4L2_BUF_FLAG_ERROR",
1020 .type = V4L2_CTRL_TYPE_BUTTON,
1023 static const struct v4l2_ctrl_config vivid_ctrl_perc_dropped = {
1024 .ops = &vivid_streaming_ctrl_ops,
1025 .id = VIVID_CID_PERC_DROPPED,
1026 .name = "Percentage of Dropped Buffers",
1027 .type = V4L2_CTRL_TYPE_INTEGER,
1028 .min = 0,
1029 .max = 100,
1030 .step = 1,
1033 static const struct v4l2_ctrl_config vivid_ctrl_queue_setup_error = {
1034 .ops = &vivid_streaming_ctrl_ops,
1035 .id = VIVID_CID_QUEUE_SETUP_ERROR,
1036 .name = "Inject VIDIOC_REQBUFS Error",
1037 .type = V4L2_CTRL_TYPE_BUTTON,
1040 static const struct v4l2_ctrl_config vivid_ctrl_buf_prepare_error = {
1041 .ops = &vivid_streaming_ctrl_ops,
1042 .id = VIVID_CID_BUF_PREPARE_ERROR,
1043 .name = "Inject VIDIOC_QBUF Error",
1044 .type = V4L2_CTRL_TYPE_BUTTON,
1047 static const struct v4l2_ctrl_config vivid_ctrl_start_streaming_error = {
1048 .ops = &vivid_streaming_ctrl_ops,
1049 .id = VIVID_CID_START_STR_ERROR,
1050 .name = "Inject VIDIOC_STREAMON Error",
1051 .type = V4L2_CTRL_TYPE_BUTTON,
1054 static const struct v4l2_ctrl_config vivid_ctrl_queue_error = {
1055 .ops = &vivid_streaming_ctrl_ops,
1056 .id = VIVID_CID_QUEUE_ERROR,
1057 .name = "Inject Fatal Streaming Error",
1058 .type = V4L2_CTRL_TYPE_BUTTON,
1061 static const struct v4l2_ctrl_config vivid_ctrl_seq_wrap = {
1062 .ops = &vivid_streaming_ctrl_ops,
1063 .id = VIVID_CID_SEQ_WRAP,
1064 .name = "Wrap Sequence Number",
1065 .type = V4L2_CTRL_TYPE_BOOLEAN,
1066 .max = 1,
1067 .step = 1,
1070 static const struct v4l2_ctrl_config vivid_ctrl_time_wrap = {
1071 .ops = &vivid_streaming_ctrl_ops,
1072 .id = VIVID_CID_TIME_WRAP,
1073 .name = "Wrap Timestamp",
1074 .type = V4L2_CTRL_TYPE_BOOLEAN,
1075 .max = 1,
1076 .step = 1,
1080 /* SDTV Capture Controls */
1082 static int vivid_sdtv_cap_s_ctrl(struct v4l2_ctrl *ctrl)
1084 struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_sdtv_cap);
1086 switch (ctrl->id) {
1087 case VIVID_CID_STD_SIGNAL_MODE:
1088 dev->std_signal_mode = dev->ctrl_std_signal_mode->val;
1089 if (dev->std_signal_mode == SELECTED_STD)
1090 dev->query_std = vivid_standard[dev->ctrl_standard->val];
1091 v4l2_ctrl_activate(dev->ctrl_standard, dev->std_signal_mode == SELECTED_STD);
1092 vivid_update_quality(dev);
1093 vivid_send_source_change(dev, TV);
1094 vivid_send_source_change(dev, SVID);
1095 break;
1097 return 0;
1100 static const struct v4l2_ctrl_ops vivid_sdtv_cap_ctrl_ops = {
1101 .s_ctrl = vivid_sdtv_cap_s_ctrl,
1104 static const char * const vivid_ctrl_std_signal_mode_strings[] = {
1105 "Current Standard",
1106 "No Signal",
1107 "No Lock",
1109 "Selected Standard",
1110 "Cycle Through All Standards",
1111 NULL,
1114 static const struct v4l2_ctrl_config vivid_ctrl_std_signal_mode = {
1115 .ops = &vivid_sdtv_cap_ctrl_ops,
1116 .id = VIVID_CID_STD_SIGNAL_MODE,
1117 .name = "Standard Signal Mode",
1118 .type = V4L2_CTRL_TYPE_MENU,
1119 .max = ARRAY_SIZE(vivid_ctrl_std_signal_mode_strings) - 2,
1120 .menu_skip_mask = 1 << 3,
1121 .qmenu = vivid_ctrl_std_signal_mode_strings,
1124 static const struct v4l2_ctrl_config vivid_ctrl_standard = {
1125 .ops = &vivid_sdtv_cap_ctrl_ops,
1126 .id = VIVID_CID_STANDARD,
1127 .name = "Standard",
1128 .type = V4L2_CTRL_TYPE_MENU,
1129 .max = 14,
1130 .qmenu = vivid_ctrl_standard_strings,
1135 /* Radio Receiver Controls */
1137 static int vivid_radio_rx_s_ctrl(struct v4l2_ctrl *ctrl)
1139 struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_radio_rx);
1141 switch (ctrl->id) {
1142 case VIVID_CID_RADIO_SEEK_MODE:
1143 dev->radio_rx_hw_seek_mode = ctrl->val;
1144 break;
1145 case VIVID_CID_RADIO_SEEK_PROG_LIM:
1146 dev->radio_rx_hw_seek_prog_lim = ctrl->val;
1147 break;
1148 case VIVID_CID_RADIO_RX_RDS_RBDS:
1149 dev->rds_gen.use_rbds = ctrl->val;
1150 break;
1151 case VIVID_CID_RADIO_RX_RDS_BLOCKIO:
1152 dev->radio_rx_rds_controls = ctrl->val;
1153 dev->radio_rx_caps &= ~V4L2_CAP_READWRITE;
1154 dev->radio_rx_rds_use_alternates = false;
1155 if (!dev->radio_rx_rds_controls) {
1156 dev->radio_rx_caps |= V4L2_CAP_READWRITE;
1157 __v4l2_ctrl_s_ctrl(dev->radio_rx_rds_pty, 0);
1158 __v4l2_ctrl_s_ctrl(dev->radio_rx_rds_ta, 0);
1159 __v4l2_ctrl_s_ctrl(dev->radio_rx_rds_tp, 0);
1160 __v4l2_ctrl_s_ctrl(dev->radio_rx_rds_ms, 0);
1161 __v4l2_ctrl_s_ctrl_string(dev->radio_rx_rds_psname, "");
1162 __v4l2_ctrl_s_ctrl_string(dev->radio_rx_rds_radiotext, "");
1164 v4l2_ctrl_activate(dev->radio_rx_rds_pty, dev->radio_rx_rds_controls);
1165 v4l2_ctrl_activate(dev->radio_rx_rds_psname, dev->radio_rx_rds_controls);
1166 v4l2_ctrl_activate(dev->radio_rx_rds_radiotext, dev->radio_rx_rds_controls);
1167 v4l2_ctrl_activate(dev->radio_rx_rds_ta, dev->radio_rx_rds_controls);
1168 v4l2_ctrl_activate(dev->radio_rx_rds_tp, dev->radio_rx_rds_controls);
1169 v4l2_ctrl_activate(dev->radio_rx_rds_ms, dev->radio_rx_rds_controls);
1170 dev->radio_rx_dev.device_caps = dev->radio_rx_caps;
1171 break;
1172 case V4L2_CID_RDS_RECEPTION:
1173 dev->radio_rx_rds_enabled = ctrl->val;
1174 break;
1176 return 0;
1179 static const struct v4l2_ctrl_ops vivid_radio_rx_ctrl_ops = {
1180 .s_ctrl = vivid_radio_rx_s_ctrl,
1183 static const char * const vivid_ctrl_radio_rds_mode_strings[] = {
1184 "Block I/O",
1185 "Controls",
1186 NULL,
1189 static const struct v4l2_ctrl_config vivid_ctrl_radio_rx_rds_blockio = {
1190 .ops = &vivid_radio_rx_ctrl_ops,
1191 .id = VIVID_CID_RADIO_RX_RDS_BLOCKIO,
1192 .name = "RDS Rx I/O Mode",
1193 .type = V4L2_CTRL_TYPE_MENU,
1194 .qmenu = vivid_ctrl_radio_rds_mode_strings,
1195 .max = 1,
1198 static const struct v4l2_ctrl_config vivid_ctrl_radio_rx_rds_rbds = {
1199 .ops = &vivid_radio_rx_ctrl_ops,
1200 .id = VIVID_CID_RADIO_RX_RDS_RBDS,
1201 .name = "Generate RBDS Instead of RDS",
1202 .type = V4L2_CTRL_TYPE_BOOLEAN,
1203 .max = 1,
1204 .step = 1,
1207 static const char * const vivid_ctrl_radio_hw_seek_mode_strings[] = {
1208 "Bounded",
1209 "Wrap Around",
1210 "Both",
1211 NULL,
1214 static const struct v4l2_ctrl_config vivid_ctrl_radio_hw_seek_mode = {
1215 .ops = &vivid_radio_rx_ctrl_ops,
1216 .id = VIVID_CID_RADIO_SEEK_MODE,
1217 .name = "Radio HW Seek Mode",
1218 .type = V4L2_CTRL_TYPE_MENU,
1219 .max = 2,
1220 .qmenu = vivid_ctrl_radio_hw_seek_mode_strings,
1223 static const struct v4l2_ctrl_config vivid_ctrl_radio_hw_seek_prog_lim = {
1224 .ops = &vivid_radio_rx_ctrl_ops,
1225 .id = VIVID_CID_RADIO_SEEK_PROG_LIM,
1226 .name = "Radio Programmable HW Seek",
1227 .type = V4L2_CTRL_TYPE_BOOLEAN,
1228 .max = 1,
1229 .step = 1,
1233 /* Radio Transmitter Controls */
1235 static int vivid_radio_tx_s_ctrl(struct v4l2_ctrl *ctrl)
1237 struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_radio_tx);
1239 switch (ctrl->id) {
1240 case VIVID_CID_RADIO_TX_RDS_BLOCKIO:
1241 dev->radio_tx_rds_controls = ctrl->val;
1242 dev->radio_tx_caps &= ~V4L2_CAP_READWRITE;
1243 if (!dev->radio_tx_rds_controls)
1244 dev->radio_tx_caps |= V4L2_CAP_READWRITE;
1245 dev->radio_tx_dev.device_caps = dev->radio_tx_caps;
1246 break;
1247 case V4L2_CID_RDS_TX_PTY:
1248 if (dev->radio_rx_rds_controls)
1249 v4l2_ctrl_s_ctrl(dev->radio_rx_rds_pty, ctrl->val);
1250 break;
1251 case V4L2_CID_RDS_TX_PS_NAME:
1252 if (dev->radio_rx_rds_controls)
1253 v4l2_ctrl_s_ctrl_string(dev->radio_rx_rds_psname, ctrl->p_new.p_char);
1254 break;
1255 case V4L2_CID_RDS_TX_RADIO_TEXT:
1256 if (dev->radio_rx_rds_controls)
1257 v4l2_ctrl_s_ctrl_string(dev->radio_rx_rds_radiotext, ctrl->p_new.p_char);
1258 break;
1259 case V4L2_CID_RDS_TX_TRAFFIC_ANNOUNCEMENT:
1260 if (dev->radio_rx_rds_controls)
1261 v4l2_ctrl_s_ctrl(dev->radio_rx_rds_ta, ctrl->val);
1262 break;
1263 case V4L2_CID_RDS_TX_TRAFFIC_PROGRAM:
1264 if (dev->radio_rx_rds_controls)
1265 v4l2_ctrl_s_ctrl(dev->radio_rx_rds_tp, ctrl->val);
1266 break;
1267 case V4L2_CID_RDS_TX_MUSIC_SPEECH:
1268 if (dev->radio_rx_rds_controls)
1269 v4l2_ctrl_s_ctrl(dev->radio_rx_rds_ms, ctrl->val);
1270 break;
1272 return 0;
1275 static const struct v4l2_ctrl_ops vivid_radio_tx_ctrl_ops = {
1276 .s_ctrl = vivid_radio_tx_s_ctrl,
1279 static const struct v4l2_ctrl_config vivid_ctrl_radio_tx_rds_blockio = {
1280 .ops = &vivid_radio_tx_ctrl_ops,
1281 .id = VIVID_CID_RADIO_TX_RDS_BLOCKIO,
1282 .name = "RDS Tx I/O Mode",
1283 .type = V4L2_CTRL_TYPE_MENU,
1284 .qmenu = vivid_ctrl_radio_rds_mode_strings,
1285 .max = 1,
1286 .def = 1,
1290 /* SDR Capture Controls */
1292 static int vivid_sdr_cap_s_ctrl(struct v4l2_ctrl *ctrl)
1294 struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_sdr_cap);
1296 switch (ctrl->id) {
1297 case VIVID_CID_SDR_CAP_FM_DEVIATION:
1298 dev->sdr_fm_deviation = ctrl->val;
1299 break;
1301 return 0;
1304 static const struct v4l2_ctrl_ops vivid_sdr_cap_ctrl_ops = {
1305 .s_ctrl = vivid_sdr_cap_s_ctrl,
1308 static const struct v4l2_ctrl_config vivid_ctrl_sdr_cap_fm_deviation = {
1309 .ops = &vivid_sdr_cap_ctrl_ops,
1310 .id = VIVID_CID_SDR_CAP_FM_DEVIATION,
1311 .name = "FM Deviation",
1312 .type = V4L2_CTRL_TYPE_INTEGER,
1313 .min = 100,
1314 .max = 200000,
1315 .def = 75000,
1316 .step = 1,
1320 static const struct v4l2_ctrl_config vivid_ctrl_class = {
1321 .ops = &vivid_user_gen_ctrl_ops,
1322 .flags = V4L2_CTRL_FLAG_READ_ONLY | V4L2_CTRL_FLAG_WRITE_ONLY,
1323 .id = VIVID_CID_VIVID_CLASS,
1324 .name = "Vivid Controls",
1325 .type = V4L2_CTRL_TYPE_CTRL_CLASS,
1328 int vivid_create_controls(struct vivid_dev *dev, bool show_ccs_cap,
1329 bool show_ccs_out, bool no_error_inj,
1330 bool has_sdtv, bool has_hdmi)
1332 struct v4l2_ctrl_handler *hdl_user_gen = &dev->ctrl_hdl_user_gen;
1333 struct v4l2_ctrl_handler *hdl_user_vid = &dev->ctrl_hdl_user_vid;
1334 struct v4l2_ctrl_handler *hdl_user_aud = &dev->ctrl_hdl_user_aud;
1335 struct v4l2_ctrl_handler *hdl_streaming = &dev->ctrl_hdl_streaming;
1336 struct v4l2_ctrl_handler *hdl_sdtv_cap = &dev->ctrl_hdl_sdtv_cap;
1337 struct v4l2_ctrl_handler *hdl_loop_cap = &dev->ctrl_hdl_loop_cap;
1338 struct v4l2_ctrl_handler *hdl_vid_cap = &dev->ctrl_hdl_vid_cap;
1339 struct v4l2_ctrl_handler *hdl_vid_out = &dev->ctrl_hdl_vid_out;
1340 struct v4l2_ctrl_handler *hdl_vbi_cap = &dev->ctrl_hdl_vbi_cap;
1341 struct v4l2_ctrl_handler *hdl_vbi_out = &dev->ctrl_hdl_vbi_out;
1342 struct v4l2_ctrl_handler *hdl_radio_rx = &dev->ctrl_hdl_radio_rx;
1343 struct v4l2_ctrl_handler *hdl_radio_tx = &dev->ctrl_hdl_radio_tx;
1344 struct v4l2_ctrl_handler *hdl_sdr_cap = &dev->ctrl_hdl_sdr_cap;
1345 struct v4l2_ctrl_config vivid_ctrl_dv_timings = {
1346 .ops = &vivid_vid_cap_ctrl_ops,
1347 .id = VIVID_CID_DV_TIMINGS,
1348 .name = "DV Timings",
1349 .type = V4L2_CTRL_TYPE_MENU,
1351 int i;
1353 v4l2_ctrl_handler_init(hdl_user_gen, 10);
1354 v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_class, NULL);
1355 v4l2_ctrl_handler_init(hdl_user_vid, 9);
1356 v4l2_ctrl_new_custom(hdl_user_vid, &vivid_ctrl_class, NULL);
1357 v4l2_ctrl_handler_init(hdl_user_aud, 2);
1358 v4l2_ctrl_new_custom(hdl_user_aud, &vivid_ctrl_class, NULL);
1359 v4l2_ctrl_handler_init(hdl_streaming, 8);
1360 v4l2_ctrl_new_custom(hdl_streaming, &vivid_ctrl_class, NULL);
1361 v4l2_ctrl_handler_init(hdl_sdtv_cap, 2);
1362 v4l2_ctrl_new_custom(hdl_sdtv_cap, &vivid_ctrl_class, NULL);
1363 v4l2_ctrl_handler_init(hdl_loop_cap, 1);
1364 v4l2_ctrl_new_custom(hdl_loop_cap, &vivid_ctrl_class, NULL);
1365 v4l2_ctrl_handler_init(hdl_vid_cap, 55);
1366 v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_class, NULL);
1367 v4l2_ctrl_handler_init(hdl_vid_out, 26);
1368 if (!no_error_inj)
1369 v4l2_ctrl_new_custom(hdl_vid_out, &vivid_ctrl_class, NULL);
1370 v4l2_ctrl_handler_init(hdl_vbi_cap, 21);
1371 v4l2_ctrl_new_custom(hdl_vbi_cap, &vivid_ctrl_class, NULL);
1372 v4l2_ctrl_handler_init(hdl_vbi_out, 19);
1373 if (!no_error_inj)
1374 v4l2_ctrl_new_custom(hdl_vbi_out, &vivid_ctrl_class, NULL);
1375 v4l2_ctrl_handler_init(hdl_radio_rx, 17);
1376 v4l2_ctrl_new_custom(hdl_radio_rx, &vivid_ctrl_class, NULL);
1377 v4l2_ctrl_handler_init(hdl_radio_tx, 17);
1378 v4l2_ctrl_new_custom(hdl_radio_tx, &vivid_ctrl_class, NULL);
1379 v4l2_ctrl_handler_init(hdl_sdr_cap, 19);
1380 v4l2_ctrl_new_custom(hdl_sdr_cap, &vivid_ctrl_class, NULL);
1382 /* User Controls */
1383 dev->volume = v4l2_ctrl_new_std(hdl_user_aud, NULL,
1384 V4L2_CID_AUDIO_VOLUME, 0, 255, 1, 200);
1385 dev->mute = v4l2_ctrl_new_std(hdl_user_aud, NULL,
1386 V4L2_CID_AUDIO_MUTE, 0, 1, 1, 0);
1387 if (dev->has_vid_cap) {
1388 dev->brightness = v4l2_ctrl_new_std(hdl_user_vid, &vivid_user_vid_ctrl_ops,
1389 V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
1390 for (i = 0; i < MAX_INPUTS; i++)
1391 dev->input_brightness[i] = 128;
1392 dev->contrast = v4l2_ctrl_new_std(hdl_user_vid, &vivid_user_vid_ctrl_ops,
1393 V4L2_CID_CONTRAST, 0, 255, 1, 128);
1394 dev->saturation = v4l2_ctrl_new_std(hdl_user_vid, &vivid_user_vid_ctrl_ops,
1395 V4L2_CID_SATURATION, 0, 255, 1, 128);
1396 dev->hue = v4l2_ctrl_new_std(hdl_user_vid, &vivid_user_vid_ctrl_ops,
1397 V4L2_CID_HUE, -128, 128, 1, 0);
1398 v4l2_ctrl_new_std(hdl_user_vid, &vivid_user_vid_ctrl_ops,
1399 V4L2_CID_HFLIP, 0, 1, 1, 0);
1400 v4l2_ctrl_new_std(hdl_user_vid, &vivid_user_vid_ctrl_ops,
1401 V4L2_CID_VFLIP, 0, 1, 1, 0);
1402 dev->autogain = v4l2_ctrl_new_std(hdl_user_vid, &vivid_user_vid_ctrl_ops,
1403 V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
1404 dev->gain = v4l2_ctrl_new_std(hdl_user_vid, &vivid_user_vid_ctrl_ops,
1405 V4L2_CID_GAIN, 0, 255, 1, 100);
1406 dev->alpha = v4l2_ctrl_new_std(hdl_user_vid, &vivid_user_vid_ctrl_ops,
1407 V4L2_CID_ALPHA_COMPONENT, 0, 255, 1, 0);
1409 dev->button = v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_button, NULL);
1410 dev->int32 = v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_int32, NULL);
1411 dev->int64 = v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_int64, NULL);
1412 dev->boolean = v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_boolean, NULL);
1413 dev->menu = v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_menu, NULL);
1414 dev->string = v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_string, NULL);
1415 dev->bitmask = v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_bitmask, NULL);
1416 dev->int_menu = v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_int_menu, NULL);
1417 v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_u32_array, NULL);
1418 v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_u16_matrix, NULL);
1419 v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_u8_4d_array, NULL);
1421 if (dev->has_vid_cap) {
1422 /* Image Processing Controls */
1423 struct v4l2_ctrl_config vivid_ctrl_test_pattern = {
1424 .ops = &vivid_vid_cap_ctrl_ops,
1425 .id = VIVID_CID_TEST_PATTERN,
1426 .name = "Test Pattern",
1427 .type = V4L2_CTRL_TYPE_MENU,
1428 .max = TPG_PAT_NOISE,
1429 .qmenu = tpg_pattern_strings,
1432 dev->test_pattern = v4l2_ctrl_new_custom(hdl_vid_cap,
1433 &vivid_ctrl_test_pattern, NULL);
1434 v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_perc_fill, NULL);
1435 v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_hor_movement, NULL);
1436 v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_vert_movement, NULL);
1437 v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_osd_mode, NULL);
1438 v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_show_border, NULL);
1439 v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_show_square, NULL);
1440 v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_hflip, NULL);
1441 v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_vflip, NULL);
1442 v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_insert_sav, NULL);
1443 v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_insert_eav, NULL);
1444 v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_reduced_fps, NULL);
1445 if (show_ccs_cap) {
1446 dev->ctrl_has_crop_cap = v4l2_ctrl_new_custom(hdl_vid_cap,
1447 &vivid_ctrl_has_crop_cap, NULL);
1448 dev->ctrl_has_compose_cap = v4l2_ctrl_new_custom(hdl_vid_cap,
1449 &vivid_ctrl_has_compose_cap, NULL);
1450 dev->ctrl_has_scaler_cap = v4l2_ctrl_new_custom(hdl_vid_cap,
1451 &vivid_ctrl_has_scaler_cap, NULL);
1454 v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_tstamp_src, NULL);
1455 dev->colorspace = v4l2_ctrl_new_custom(hdl_vid_cap,
1456 &vivid_ctrl_colorspace, NULL);
1457 v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_xfer_func, NULL);
1458 v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_ycbcr_enc, NULL);
1459 v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_quantization, NULL);
1460 v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_alpha_mode, NULL);
1463 if (dev->has_vid_out && show_ccs_out) {
1464 dev->ctrl_has_crop_out = v4l2_ctrl_new_custom(hdl_vid_out,
1465 &vivid_ctrl_has_crop_out, NULL);
1466 dev->ctrl_has_compose_out = v4l2_ctrl_new_custom(hdl_vid_out,
1467 &vivid_ctrl_has_compose_out, NULL);
1468 dev->ctrl_has_scaler_out = v4l2_ctrl_new_custom(hdl_vid_out,
1469 &vivid_ctrl_has_scaler_out, NULL);
1473 * Testing this driver with v4l2-compliance will trigger the error
1474 * injection controls, and after that nothing will work as expected.
1475 * So we have a module option to drop these error injecting controls
1476 * allowing us to run v4l2_compliance again.
1478 if (!no_error_inj) {
1479 v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_disconnect, NULL);
1480 v4l2_ctrl_new_custom(hdl_streaming, &vivid_ctrl_dqbuf_error, NULL);
1481 v4l2_ctrl_new_custom(hdl_streaming, &vivid_ctrl_perc_dropped, NULL);
1482 v4l2_ctrl_new_custom(hdl_streaming, &vivid_ctrl_queue_setup_error, NULL);
1483 v4l2_ctrl_new_custom(hdl_streaming, &vivid_ctrl_buf_prepare_error, NULL);
1484 v4l2_ctrl_new_custom(hdl_streaming, &vivid_ctrl_start_streaming_error, NULL);
1485 v4l2_ctrl_new_custom(hdl_streaming, &vivid_ctrl_queue_error, NULL);
1486 v4l2_ctrl_new_custom(hdl_streaming, &vivid_ctrl_seq_wrap, NULL);
1487 v4l2_ctrl_new_custom(hdl_streaming, &vivid_ctrl_time_wrap, NULL);
1490 if (has_sdtv && (dev->has_vid_cap || dev->has_vbi_cap)) {
1491 if (dev->has_vid_cap)
1492 v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_std_aspect_ratio, NULL);
1493 dev->ctrl_std_signal_mode = v4l2_ctrl_new_custom(hdl_sdtv_cap,
1494 &vivid_ctrl_std_signal_mode, NULL);
1495 dev->ctrl_standard = v4l2_ctrl_new_custom(hdl_sdtv_cap,
1496 &vivid_ctrl_standard, NULL);
1497 if (dev->ctrl_std_signal_mode)
1498 v4l2_ctrl_cluster(2, &dev->ctrl_std_signal_mode);
1499 if (dev->has_raw_vbi_cap)
1500 v4l2_ctrl_new_custom(hdl_vbi_cap, &vivid_ctrl_vbi_cap_interlaced, NULL);
1503 if (has_hdmi && dev->has_vid_cap) {
1504 dev->ctrl_dv_timings_signal_mode = v4l2_ctrl_new_custom(hdl_vid_cap,
1505 &vivid_ctrl_dv_timings_signal_mode, NULL);
1507 vivid_ctrl_dv_timings.max = dev->query_dv_timings_size - 1;
1508 vivid_ctrl_dv_timings.qmenu =
1509 (const char * const *)dev->query_dv_timings_qmenu;
1510 dev->ctrl_dv_timings = v4l2_ctrl_new_custom(hdl_vid_cap,
1511 &vivid_ctrl_dv_timings, NULL);
1512 if (dev->ctrl_dv_timings_signal_mode)
1513 v4l2_ctrl_cluster(2, &dev->ctrl_dv_timings_signal_mode);
1515 v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_dv_timings_aspect_ratio, NULL);
1516 v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_max_edid_blocks, NULL);
1517 dev->real_rgb_range_cap = v4l2_ctrl_new_custom(hdl_vid_cap,
1518 &vivid_ctrl_limited_rgb_range, NULL);
1519 dev->rgb_range_cap = v4l2_ctrl_new_std_menu(hdl_vid_cap,
1520 &vivid_vid_cap_ctrl_ops,
1521 V4L2_CID_DV_RX_RGB_RANGE, V4L2_DV_RGB_RANGE_FULL,
1522 0, V4L2_DV_RGB_RANGE_AUTO);
1524 if (has_hdmi && dev->has_vid_out) {
1526 * We aren't doing anything with this at the moment, but
1527 * HDMI outputs typically have this controls.
1529 dev->ctrl_tx_rgb_range = v4l2_ctrl_new_std_menu(hdl_vid_out, NULL,
1530 V4L2_CID_DV_TX_RGB_RANGE, V4L2_DV_RGB_RANGE_FULL,
1531 0, V4L2_DV_RGB_RANGE_AUTO);
1532 dev->ctrl_tx_mode = v4l2_ctrl_new_std_menu(hdl_vid_out, NULL,
1533 V4L2_CID_DV_TX_MODE, V4L2_DV_TX_MODE_HDMI,
1534 0, V4L2_DV_TX_MODE_HDMI);
1536 if ((dev->has_vid_cap && dev->has_vid_out) ||
1537 (dev->has_vbi_cap && dev->has_vbi_out))
1538 v4l2_ctrl_new_custom(hdl_loop_cap, &vivid_ctrl_loop_video, NULL);
1540 if (dev->has_fb)
1541 v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_clear_fb, NULL);
1543 if (dev->has_radio_rx) {
1544 v4l2_ctrl_new_custom(hdl_radio_rx, &vivid_ctrl_radio_hw_seek_mode, NULL);
1545 v4l2_ctrl_new_custom(hdl_radio_rx, &vivid_ctrl_radio_hw_seek_prog_lim, NULL);
1546 v4l2_ctrl_new_custom(hdl_radio_rx, &vivid_ctrl_radio_rx_rds_blockio, NULL);
1547 v4l2_ctrl_new_custom(hdl_radio_rx, &vivid_ctrl_radio_rx_rds_rbds, NULL);
1548 v4l2_ctrl_new_std(hdl_radio_rx, &vivid_radio_rx_ctrl_ops,
1549 V4L2_CID_RDS_RECEPTION, 0, 1, 1, 1);
1550 dev->radio_rx_rds_pty = v4l2_ctrl_new_std(hdl_radio_rx,
1551 &vivid_radio_rx_ctrl_ops,
1552 V4L2_CID_RDS_RX_PTY, 0, 31, 1, 0);
1553 dev->radio_rx_rds_psname = v4l2_ctrl_new_std(hdl_radio_rx,
1554 &vivid_radio_rx_ctrl_ops,
1555 V4L2_CID_RDS_RX_PS_NAME, 0, 8, 8, 0);
1556 dev->radio_rx_rds_radiotext = v4l2_ctrl_new_std(hdl_radio_rx,
1557 &vivid_radio_rx_ctrl_ops,
1558 V4L2_CID_RDS_RX_RADIO_TEXT, 0, 64, 64, 0);
1559 dev->radio_rx_rds_ta = v4l2_ctrl_new_std(hdl_radio_rx,
1560 &vivid_radio_rx_ctrl_ops,
1561 V4L2_CID_RDS_RX_TRAFFIC_ANNOUNCEMENT, 0, 1, 1, 0);
1562 dev->radio_rx_rds_tp = v4l2_ctrl_new_std(hdl_radio_rx,
1563 &vivid_radio_rx_ctrl_ops,
1564 V4L2_CID_RDS_RX_TRAFFIC_PROGRAM, 0, 1, 1, 0);
1565 dev->radio_rx_rds_ms = v4l2_ctrl_new_std(hdl_radio_rx,
1566 &vivid_radio_rx_ctrl_ops,
1567 V4L2_CID_RDS_RX_MUSIC_SPEECH, 0, 1, 1, 1);
1569 if (dev->has_radio_tx) {
1570 v4l2_ctrl_new_custom(hdl_radio_tx,
1571 &vivid_ctrl_radio_tx_rds_blockio, NULL);
1572 dev->radio_tx_rds_pi = v4l2_ctrl_new_std(hdl_radio_tx,
1573 &vivid_radio_tx_ctrl_ops,
1574 V4L2_CID_RDS_TX_PI, 0, 0xffff, 1, 0x8088);
1575 dev->radio_tx_rds_pty = v4l2_ctrl_new_std(hdl_radio_tx,
1576 &vivid_radio_tx_ctrl_ops,
1577 V4L2_CID_RDS_TX_PTY, 0, 31, 1, 3);
1578 dev->radio_tx_rds_psname = v4l2_ctrl_new_std(hdl_radio_tx,
1579 &vivid_radio_tx_ctrl_ops,
1580 V4L2_CID_RDS_TX_PS_NAME, 0, 8, 8, 0);
1581 if (dev->radio_tx_rds_psname)
1582 v4l2_ctrl_s_ctrl_string(dev->radio_tx_rds_psname, "VIVID-TX");
1583 dev->radio_tx_rds_radiotext = v4l2_ctrl_new_std(hdl_radio_tx,
1584 &vivid_radio_tx_ctrl_ops,
1585 V4L2_CID_RDS_TX_RADIO_TEXT, 0, 64 * 2, 64, 0);
1586 if (dev->radio_tx_rds_radiotext)
1587 v4l2_ctrl_s_ctrl_string(dev->radio_tx_rds_radiotext,
1588 "This is a VIVID default Radio Text template text, change at will");
1589 dev->radio_tx_rds_mono_stereo = v4l2_ctrl_new_std(hdl_radio_tx,
1590 &vivid_radio_tx_ctrl_ops,
1591 V4L2_CID_RDS_TX_MONO_STEREO, 0, 1, 1, 1);
1592 dev->radio_tx_rds_art_head = v4l2_ctrl_new_std(hdl_radio_tx,
1593 &vivid_radio_tx_ctrl_ops,
1594 V4L2_CID_RDS_TX_ARTIFICIAL_HEAD, 0, 1, 1, 0);
1595 dev->radio_tx_rds_compressed = v4l2_ctrl_new_std(hdl_radio_tx,
1596 &vivid_radio_tx_ctrl_ops,
1597 V4L2_CID_RDS_TX_COMPRESSED, 0, 1, 1, 0);
1598 dev->radio_tx_rds_dyn_pty = v4l2_ctrl_new_std(hdl_radio_tx,
1599 &vivid_radio_tx_ctrl_ops,
1600 V4L2_CID_RDS_TX_DYNAMIC_PTY, 0, 1, 1, 0);
1601 dev->radio_tx_rds_ta = v4l2_ctrl_new_std(hdl_radio_tx,
1602 &vivid_radio_tx_ctrl_ops,
1603 V4L2_CID_RDS_TX_TRAFFIC_ANNOUNCEMENT, 0, 1, 1, 0);
1604 dev->radio_tx_rds_tp = v4l2_ctrl_new_std(hdl_radio_tx,
1605 &vivid_radio_tx_ctrl_ops,
1606 V4L2_CID_RDS_TX_TRAFFIC_PROGRAM, 0, 1, 1, 1);
1607 dev->radio_tx_rds_ms = v4l2_ctrl_new_std(hdl_radio_tx,
1608 &vivid_radio_tx_ctrl_ops,
1609 V4L2_CID_RDS_TX_MUSIC_SPEECH, 0, 1, 1, 1);
1611 if (dev->has_sdr_cap) {
1612 v4l2_ctrl_new_custom(hdl_sdr_cap,
1613 &vivid_ctrl_sdr_cap_fm_deviation, NULL);
1615 if (hdl_user_gen->error)
1616 return hdl_user_gen->error;
1617 if (hdl_user_vid->error)
1618 return hdl_user_vid->error;
1619 if (hdl_user_aud->error)
1620 return hdl_user_aud->error;
1621 if (hdl_streaming->error)
1622 return hdl_streaming->error;
1623 if (hdl_sdr_cap->error)
1624 return hdl_sdr_cap->error;
1625 if (hdl_loop_cap->error)
1626 return hdl_loop_cap->error;
1628 if (dev->autogain)
1629 v4l2_ctrl_auto_cluster(2, &dev->autogain, 0, true);
1631 if (dev->has_vid_cap) {
1632 v4l2_ctrl_add_handler(hdl_vid_cap, hdl_user_gen, NULL);
1633 v4l2_ctrl_add_handler(hdl_vid_cap, hdl_user_vid, NULL);
1634 v4l2_ctrl_add_handler(hdl_vid_cap, hdl_user_aud, NULL);
1635 v4l2_ctrl_add_handler(hdl_vid_cap, hdl_streaming, NULL);
1636 v4l2_ctrl_add_handler(hdl_vid_cap, hdl_sdtv_cap, NULL);
1637 v4l2_ctrl_add_handler(hdl_vid_cap, hdl_loop_cap, NULL);
1638 if (hdl_vid_cap->error)
1639 return hdl_vid_cap->error;
1640 dev->vid_cap_dev.ctrl_handler = hdl_vid_cap;
1642 if (dev->has_vid_out) {
1643 v4l2_ctrl_add_handler(hdl_vid_out, hdl_user_gen, NULL);
1644 v4l2_ctrl_add_handler(hdl_vid_out, hdl_user_aud, NULL);
1645 v4l2_ctrl_add_handler(hdl_vid_out, hdl_streaming, NULL);
1646 if (hdl_vid_out->error)
1647 return hdl_vid_out->error;
1648 dev->vid_out_dev.ctrl_handler = hdl_vid_out;
1650 if (dev->has_vbi_cap) {
1651 v4l2_ctrl_add_handler(hdl_vbi_cap, hdl_user_gen, NULL);
1652 v4l2_ctrl_add_handler(hdl_vbi_cap, hdl_streaming, NULL);
1653 v4l2_ctrl_add_handler(hdl_vbi_cap, hdl_sdtv_cap, NULL);
1654 v4l2_ctrl_add_handler(hdl_vbi_cap, hdl_loop_cap, NULL);
1655 if (hdl_vbi_cap->error)
1656 return hdl_vbi_cap->error;
1657 dev->vbi_cap_dev.ctrl_handler = hdl_vbi_cap;
1659 if (dev->has_vbi_out) {
1660 v4l2_ctrl_add_handler(hdl_vbi_out, hdl_user_gen, NULL);
1661 v4l2_ctrl_add_handler(hdl_vbi_out, hdl_streaming, NULL);
1662 if (hdl_vbi_out->error)
1663 return hdl_vbi_out->error;
1664 dev->vbi_out_dev.ctrl_handler = hdl_vbi_out;
1666 if (dev->has_radio_rx) {
1667 v4l2_ctrl_add_handler(hdl_radio_rx, hdl_user_gen, NULL);
1668 v4l2_ctrl_add_handler(hdl_radio_rx, hdl_user_aud, NULL);
1669 if (hdl_radio_rx->error)
1670 return hdl_radio_rx->error;
1671 dev->radio_rx_dev.ctrl_handler = hdl_radio_rx;
1673 if (dev->has_radio_tx) {
1674 v4l2_ctrl_add_handler(hdl_radio_tx, hdl_user_gen, NULL);
1675 v4l2_ctrl_add_handler(hdl_radio_tx, hdl_user_aud, NULL);
1676 if (hdl_radio_tx->error)
1677 return hdl_radio_tx->error;
1678 dev->radio_tx_dev.ctrl_handler = hdl_radio_tx;
1680 if (dev->has_sdr_cap) {
1681 v4l2_ctrl_add_handler(hdl_sdr_cap, hdl_user_gen, NULL);
1682 v4l2_ctrl_add_handler(hdl_sdr_cap, hdl_streaming, NULL);
1683 if (hdl_sdr_cap->error)
1684 return hdl_sdr_cap->error;
1685 dev->sdr_cap_dev.ctrl_handler = hdl_sdr_cap;
1687 return 0;
1690 void vivid_free_controls(struct vivid_dev *dev)
1692 v4l2_ctrl_handler_free(&dev->ctrl_hdl_vid_cap);
1693 v4l2_ctrl_handler_free(&dev->ctrl_hdl_vid_out);
1694 v4l2_ctrl_handler_free(&dev->ctrl_hdl_vbi_cap);
1695 v4l2_ctrl_handler_free(&dev->ctrl_hdl_vbi_out);
1696 v4l2_ctrl_handler_free(&dev->ctrl_hdl_radio_rx);
1697 v4l2_ctrl_handler_free(&dev->ctrl_hdl_radio_tx);
1698 v4l2_ctrl_handler_free(&dev->ctrl_hdl_sdr_cap);
1699 v4l2_ctrl_handler_free(&dev->ctrl_hdl_user_gen);
1700 v4l2_ctrl_handler_free(&dev->ctrl_hdl_user_vid);
1701 v4l2_ctrl_handler_free(&dev->ctrl_hdl_user_aud);
1702 v4l2_ctrl_handler_free(&dev->ctrl_hdl_streaming);
1703 v4l2_ctrl_handler_free(&dev->ctrl_hdl_sdtv_cap);
1704 v4l2_ctrl_handler_free(&dev->ctrl_hdl_loop_cap);