Merge tag 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost
[cris-mirror.git] / drivers / media / platform / vivid / vivid-ctrls.c
blob3f9d354827af35de8b9b986f5f0bc0ab466a9060
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)
82 #define VIVID_CID_HSV_ENC (VIVID_CID_VIVID_BASE + 43)
84 #define VIVID_CID_STD_SIGNAL_MODE (VIVID_CID_VIVID_BASE + 60)
85 #define VIVID_CID_STANDARD (VIVID_CID_VIVID_BASE + 61)
86 #define VIVID_CID_DV_TIMINGS_SIGNAL_MODE (VIVID_CID_VIVID_BASE + 62)
87 #define VIVID_CID_DV_TIMINGS (VIVID_CID_VIVID_BASE + 63)
88 #define VIVID_CID_PERC_DROPPED (VIVID_CID_VIVID_BASE + 64)
89 #define VIVID_CID_DISCONNECT (VIVID_CID_VIVID_BASE + 65)
90 #define VIVID_CID_DQBUF_ERROR (VIVID_CID_VIVID_BASE + 66)
91 #define VIVID_CID_QUEUE_SETUP_ERROR (VIVID_CID_VIVID_BASE + 67)
92 #define VIVID_CID_BUF_PREPARE_ERROR (VIVID_CID_VIVID_BASE + 68)
93 #define VIVID_CID_START_STR_ERROR (VIVID_CID_VIVID_BASE + 69)
94 #define VIVID_CID_QUEUE_ERROR (VIVID_CID_VIVID_BASE + 70)
95 #define VIVID_CID_CLEAR_FB (VIVID_CID_VIVID_BASE + 71)
97 #define VIVID_CID_RADIO_SEEK_MODE (VIVID_CID_VIVID_BASE + 90)
98 #define VIVID_CID_RADIO_SEEK_PROG_LIM (VIVID_CID_VIVID_BASE + 91)
99 #define VIVID_CID_RADIO_RX_RDS_RBDS (VIVID_CID_VIVID_BASE + 92)
100 #define VIVID_CID_RADIO_RX_RDS_BLOCKIO (VIVID_CID_VIVID_BASE + 93)
102 #define VIVID_CID_RADIO_TX_RDS_BLOCKIO (VIVID_CID_VIVID_BASE + 94)
104 #define VIVID_CID_SDR_CAP_FM_DEVIATION (VIVID_CID_VIVID_BASE + 110)
106 /* General User Controls */
108 static int vivid_user_gen_s_ctrl(struct v4l2_ctrl *ctrl)
110 struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_user_gen);
112 switch (ctrl->id) {
113 case VIVID_CID_DISCONNECT:
114 v4l2_info(&dev->v4l2_dev, "disconnect\n");
115 clear_bit(V4L2_FL_REGISTERED, &dev->vid_cap_dev.flags);
116 clear_bit(V4L2_FL_REGISTERED, &dev->vid_out_dev.flags);
117 clear_bit(V4L2_FL_REGISTERED, &dev->vbi_cap_dev.flags);
118 clear_bit(V4L2_FL_REGISTERED, &dev->vbi_out_dev.flags);
119 clear_bit(V4L2_FL_REGISTERED, &dev->sdr_cap_dev.flags);
120 clear_bit(V4L2_FL_REGISTERED, &dev->radio_rx_dev.flags);
121 clear_bit(V4L2_FL_REGISTERED, &dev->radio_tx_dev.flags);
122 break;
123 case VIVID_CID_BUTTON:
124 dev->button_pressed = 30;
125 break;
127 return 0;
130 static const struct v4l2_ctrl_ops vivid_user_gen_ctrl_ops = {
131 .s_ctrl = vivid_user_gen_s_ctrl,
134 static const struct v4l2_ctrl_config vivid_ctrl_button = {
135 .ops = &vivid_user_gen_ctrl_ops,
136 .id = VIVID_CID_BUTTON,
137 .name = "Button",
138 .type = V4L2_CTRL_TYPE_BUTTON,
141 static const struct v4l2_ctrl_config vivid_ctrl_boolean = {
142 .ops = &vivid_user_gen_ctrl_ops,
143 .id = VIVID_CID_BOOLEAN,
144 .name = "Boolean",
145 .type = V4L2_CTRL_TYPE_BOOLEAN,
146 .min = 0,
147 .max = 1,
148 .step = 1,
149 .def = 1,
152 static const struct v4l2_ctrl_config vivid_ctrl_int32 = {
153 .ops = &vivid_user_gen_ctrl_ops,
154 .id = VIVID_CID_INTEGER,
155 .name = "Integer 32 Bits",
156 .type = V4L2_CTRL_TYPE_INTEGER,
157 .min = 0xffffffff80000000ULL,
158 .max = 0x7fffffff,
159 .step = 1,
162 static const struct v4l2_ctrl_config vivid_ctrl_int64 = {
163 .ops = &vivid_user_gen_ctrl_ops,
164 .id = VIVID_CID_INTEGER64,
165 .name = "Integer 64 Bits",
166 .type = V4L2_CTRL_TYPE_INTEGER64,
167 .min = 0x8000000000000000ULL,
168 .max = 0x7fffffffffffffffLL,
169 .step = 1,
172 static const struct v4l2_ctrl_config vivid_ctrl_u32_array = {
173 .ops = &vivid_user_gen_ctrl_ops,
174 .id = VIVID_CID_U32_ARRAY,
175 .name = "U32 1 Element Array",
176 .type = V4L2_CTRL_TYPE_U32,
177 .def = 0x18,
178 .min = 0x10,
179 .max = 0x20000,
180 .step = 1,
181 .dims = { 1 },
184 static const struct v4l2_ctrl_config vivid_ctrl_u16_matrix = {
185 .ops = &vivid_user_gen_ctrl_ops,
186 .id = VIVID_CID_U16_MATRIX,
187 .name = "U16 8x16 Matrix",
188 .type = V4L2_CTRL_TYPE_U16,
189 .def = 0x18,
190 .min = 0x10,
191 .max = 0x2000,
192 .step = 1,
193 .dims = { 8, 16 },
196 static const struct v4l2_ctrl_config vivid_ctrl_u8_4d_array = {
197 .ops = &vivid_user_gen_ctrl_ops,
198 .id = VIVID_CID_U8_4D_ARRAY,
199 .name = "U8 2x3x4x5 Array",
200 .type = V4L2_CTRL_TYPE_U8,
201 .def = 0x18,
202 .min = 0x10,
203 .max = 0x20,
204 .step = 1,
205 .dims = { 2, 3, 4, 5 },
208 static const char * const vivid_ctrl_menu_strings[] = {
209 "Menu Item 0 (Skipped)",
210 "Menu Item 1",
211 "Menu Item 2 (Skipped)",
212 "Menu Item 3",
213 "Menu Item 4",
214 "Menu Item 5 (Skipped)",
215 NULL,
218 static const struct v4l2_ctrl_config vivid_ctrl_menu = {
219 .ops = &vivid_user_gen_ctrl_ops,
220 .id = VIVID_CID_MENU,
221 .name = "Menu",
222 .type = V4L2_CTRL_TYPE_MENU,
223 .min = 1,
224 .max = 4,
225 .def = 3,
226 .menu_skip_mask = 0x04,
227 .qmenu = vivid_ctrl_menu_strings,
230 static const struct v4l2_ctrl_config vivid_ctrl_string = {
231 .ops = &vivid_user_gen_ctrl_ops,
232 .id = VIVID_CID_STRING,
233 .name = "String",
234 .type = V4L2_CTRL_TYPE_STRING,
235 .min = 2,
236 .max = 4,
237 .step = 1,
240 static const struct v4l2_ctrl_config vivid_ctrl_bitmask = {
241 .ops = &vivid_user_gen_ctrl_ops,
242 .id = VIVID_CID_BITMASK,
243 .name = "Bitmask",
244 .type = V4L2_CTRL_TYPE_BITMASK,
245 .def = 0x80002000,
246 .min = 0,
247 .max = 0x80402010,
248 .step = 0,
251 static const s64 vivid_ctrl_int_menu_values[] = {
252 1, 1, 2, 3, 5, 8, 13, 21, 42,
255 static const struct v4l2_ctrl_config vivid_ctrl_int_menu = {
256 .ops = &vivid_user_gen_ctrl_ops,
257 .id = VIVID_CID_INTMENU,
258 .name = "Integer Menu",
259 .type = V4L2_CTRL_TYPE_INTEGER_MENU,
260 .min = 1,
261 .max = 8,
262 .def = 4,
263 .menu_skip_mask = 0x02,
264 .qmenu_int = vivid_ctrl_int_menu_values,
267 static const struct v4l2_ctrl_config vivid_ctrl_disconnect = {
268 .ops = &vivid_user_gen_ctrl_ops,
269 .id = VIVID_CID_DISCONNECT,
270 .name = "Disconnect",
271 .type = V4L2_CTRL_TYPE_BUTTON,
275 /* Framebuffer Controls */
277 static int vivid_fb_s_ctrl(struct v4l2_ctrl *ctrl)
279 struct vivid_dev *dev = container_of(ctrl->handler,
280 struct vivid_dev, ctrl_hdl_fb);
282 switch (ctrl->id) {
283 case VIVID_CID_CLEAR_FB:
284 vivid_clear_fb(dev);
285 break;
287 return 0;
290 static const struct v4l2_ctrl_ops vivid_fb_ctrl_ops = {
291 .s_ctrl = vivid_fb_s_ctrl,
294 static const struct v4l2_ctrl_config vivid_ctrl_clear_fb = {
295 .ops = &vivid_fb_ctrl_ops,
296 .id = VIVID_CID_CLEAR_FB,
297 .name = "Clear Framebuffer",
298 .type = V4L2_CTRL_TYPE_BUTTON,
302 /* Video User Controls */
304 static int vivid_user_vid_g_volatile_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_AUTOGAIN:
310 dev->gain->val = dev->jiffies_vid_cap & 0xff;
311 break;
313 return 0;
316 static int vivid_user_vid_s_ctrl(struct v4l2_ctrl *ctrl)
318 struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_user_vid);
320 switch (ctrl->id) {
321 case V4L2_CID_BRIGHTNESS:
322 dev->input_brightness[dev->input] = ctrl->val - dev->input * 128;
323 tpg_s_brightness(&dev->tpg, dev->input_brightness[dev->input]);
324 break;
325 case V4L2_CID_CONTRAST:
326 tpg_s_contrast(&dev->tpg, ctrl->val);
327 break;
328 case V4L2_CID_SATURATION:
329 tpg_s_saturation(&dev->tpg, ctrl->val);
330 break;
331 case V4L2_CID_HUE:
332 tpg_s_hue(&dev->tpg, ctrl->val);
333 break;
334 case V4L2_CID_HFLIP:
335 dev->hflip = ctrl->val;
336 tpg_s_hflip(&dev->tpg, dev->sensor_hflip ^ dev->hflip);
337 break;
338 case V4L2_CID_VFLIP:
339 dev->vflip = ctrl->val;
340 tpg_s_vflip(&dev->tpg, dev->sensor_vflip ^ dev->vflip);
341 break;
342 case V4L2_CID_ALPHA_COMPONENT:
343 tpg_s_alpha_component(&dev->tpg, ctrl->val);
344 break;
346 return 0;
349 static const struct v4l2_ctrl_ops vivid_user_vid_ctrl_ops = {
350 .g_volatile_ctrl = vivid_user_vid_g_volatile_ctrl,
351 .s_ctrl = vivid_user_vid_s_ctrl,
355 /* Video Capture Controls */
357 static int vivid_vid_cap_s_ctrl(struct v4l2_ctrl *ctrl)
359 static const u32 colorspaces[] = {
360 V4L2_COLORSPACE_SMPTE170M,
361 V4L2_COLORSPACE_REC709,
362 V4L2_COLORSPACE_SRGB,
363 V4L2_COLORSPACE_ADOBERGB,
364 V4L2_COLORSPACE_BT2020,
365 V4L2_COLORSPACE_DCI_P3,
366 V4L2_COLORSPACE_SMPTE240M,
367 V4L2_COLORSPACE_470_SYSTEM_M,
368 V4L2_COLORSPACE_470_SYSTEM_BG,
370 struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_vid_cap);
371 unsigned i;
373 switch (ctrl->id) {
374 case VIVID_CID_TEST_PATTERN:
375 vivid_update_quality(dev);
376 tpg_s_pattern(&dev->tpg, ctrl->val);
377 break;
378 case VIVID_CID_COLORSPACE:
379 tpg_s_colorspace(&dev->tpg, colorspaces[ctrl->val]);
380 vivid_send_source_change(dev, TV);
381 vivid_send_source_change(dev, SVID);
382 vivid_send_source_change(dev, HDMI);
383 vivid_send_source_change(dev, WEBCAM);
384 break;
385 case VIVID_CID_XFER_FUNC:
386 tpg_s_xfer_func(&dev->tpg, ctrl->val);
387 vivid_send_source_change(dev, TV);
388 vivid_send_source_change(dev, SVID);
389 vivid_send_source_change(dev, HDMI);
390 vivid_send_source_change(dev, WEBCAM);
391 break;
392 case VIVID_CID_YCBCR_ENC:
393 tpg_s_ycbcr_enc(&dev->tpg, ctrl->val);
394 vivid_send_source_change(dev, TV);
395 vivid_send_source_change(dev, SVID);
396 vivid_send_source_change(dev, HDMI);
397 vivid_send_source_change(dev, WEBCAM);
398 break;
399 case VIVID_CID_HSV_ENC:
400 tpg_s_hsv_enc(&dev->tpg, ctrl->val ? V4L2_HSV_ENC_256 :
401 V4L2_HSV_ENC_180);
402 vivid_send_source_change(dev, TV);
403 vivid_send_source_change(dev, SVID);
404 vivid_send_source_change(dev, HDMI);
405 vivid_send_source_change(dev, WEBCAM);
406 break;
407 case VIVID_CID_QUANTIZATION:
408 tpg_s_quantization(&dev->tpg, ctrl->val);
409 vivid_send_source_change(dev, TV);
410 vivid_send_source_change(dev, SVID);
411 vivid_send_source_change(dev, HDMI);
412 vivid_send_source_change(dev, WEBCAM);
413 break;
414 case V4L2_CID_DV_RX_RGB_RANGE:
415 if (!vivid_is_hdmi_cap(dev))
416 break;
417 tpg_s_rgb_range(&dev->tpg, ctrl->val);
418 break;
419 case VIVID_CID_LIMITED_RGB_RANGE:
420 tpg_s_real_rgb_range(&dev->tpg, ctrl->val ?
421 V4L2_DV_RGB_RANGE_LIMITED : V4L2_DV_RGB_RANGE_FULL);
422 break;
423 case VIVID_CID_ALPHA_MODE:
424 tpg_s_alpha_mode(&dev->tpg, ctrl->val);
425 break;
426 case VIVID_CID_HOR_MOVEMENT:
427 tpg_s_mv_hor_mode(&dev->tpg, ctrl->val);
428 break;
429 case VIVID_CID_VERT_MOVEMENT:
430 tpg_s_mv_vert_mode(&dev->tpg, ctrl->val);
431 break;
432 case VIVID_CID_OSD_TEXT_MODE:
433 dev->osd_mode = ctrl->val;
434 break;
435 case VIVID_CID_PERCENTAGE_FILL:
436 tpg_s_perc_fill(&dev->tpg, ctrl->val);
437 for (i = 0; i < VIDEO_MAX_FRAME; i++)
438 dev->must_blank[i] = ctrl->val < 100;
439 break;
440 case VIVID_CID_INSERT_SAV:
441 tpg_s_insert_sav(&dev->tpg, ctrl->val);
442 break;
443 case VIVID_CID_INSERT_EAV:
444 tpg_s_insert_eav(&dev->tpg, ctrl->val);
445 break;
446 case VIVID_CID_HFLIP:
447 dev->sensor_hflip = ctrl->val;
448 tpg_s_hflip(&dev->tpg, dev->sensor_hflip ^ dev->hflip);
449 break;
450 case VIVID_CID_VFLIP:
451 dev->sensor_vflip = ctrl->val;
452 tpg_s_vflip(&dev->tpg, dev->sensor_vflip ^ dev->vflip);
453 break;
454 case VIVID_CID_REDUCED_FPS:
455 dev->reduced_fps = ctrl->val;
456 vivid_update_format_cap(dev, true);
457 break;
458 case VIVID_CID_HAS_CROP_CAP:
459 dev->has_crop_cap = ctrl->val;
460 vivid_update_format_cap(dev, true);
461 break;
462 case VIVID_CID_HAS_COMPOSE_CAP:
463 dev->has_compose_cap = ctrl->val;
464 vivid_update_format_cap(dev, true);
465 break;
466 case VIVID_CID_HAS_SCALER_CAP:
467 dev->has_scaler_cap = ctrl->val;
468 vivid_update_format_cap(dev, true);
469 break;
470 case VIVID_CID_SHOW_BORDER:
471 tpg_s_show_border(&dev->tpg, ctrl->val);
472 break;
473 case VIVID_CID_SHOW_SQUARE:
474 tpg_s_show_square(&dev->tpg, ctrl->val);
475 break;
476 case VIVID_CID_STD_ASPECT_RATIO:
477 dev->std_aspect_ratio = ctrl->val;
478 tpg_s_video_aspect(&dev->tpg, vivid_get_video_aspect(dev));
479 break;
480 case VIVID_CID_DV_TIMINGS_SIGNAL_MODE:
481 dev->dv_timings_signal_mode = dev->ctrl_dv_timings_signal_mode->val;
482 if (dev->dv_timings_signal_mode == SELECTED_DV_TIMINGS)
483 dev->query_dv_timings = dev->ctrl_dv_timings->val;
484 v4l2_ctrl_activate(dev->ctrl_dv_timings,
485 dev->dv_timings_signal_mode == SELECTED_DV_TIMINGS);
486 vivid_update_quality(dev);
487 vivid_send_source_change(dev, HDMI);
488 break;
489 case VIVID_CID_DV_TIMINGS_ASPECT_RATIO:
490 dev->dv_timings_aspect_ratio = ctrl->val;
491 tpg_s_video_aspect(&dev->tpg, vivid_get_video_aspect(dev));
492 break;
493 case VIVID_CID_TSTAMP_SRC:
494 dev->tstamp_src_is_soe = ctrl->val;
495 dev->vb_vid_cap_q.timestamp_flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
496 if (dev->tstamp_src_is_soe)
497 dev->vb_vid_cap_q.timestamp_flags |= V4L2_BUF_FLAG_TSTAMP_SRC_SOE;
498 break;
499 case VIVID_CID_MAX_EDID_BLOCKS:
500 dev->edid_max_blocks = ctrl->val;
501 if (dev->edid_blocks > dev->edid_max_blocks)
502 dev->edid_blocks = dev->edid_max_blocks;
503 break;
505 return 0;
508 static const struct v4l2_ctrl_ops vivid_vid_cap_ctrl_ops = {
509 .s_ctrl = vivid_vid_cap_s_ctrl,
512 static const char * const vivid_ctrl_hor_movement_strings[] = {
513 "Move Left Fast",
514 "Move Left",
515 "Move Left Slow",
516 "No Movement",
517 "Move Right Slow",
518 "Move Right",
519 "Move Right Fast",
520 NULL,
523 static const struct v4l2_ctrl_config vivid_ctrl_hor_movement = {
524 .ops = &vivid_vid_cap_ctrl_ops,
525 .id = VIVID_CID_HOR_MOVEMENT,
526 .name = "Horizontal Movement",
527 .type = V4L2_CTRL_TYPE_MENU,
528 .max = TPG_MOVE_POS_FAST,
529 .def = TPG_MOVE_NONE,
530 .qmenu = vivid_ctrl_hor_movement_strings,
533 static const char * const vivid_ctrl_vert_movement_strings[] = {
534 "Move Up Fast",
535 "Move Up",
536 "Move Up Slow",
537 "No Movement",
538 "Move Down Slow",
539 "Move Down",
540 "Move Down Fast",
541 NULL,
544 static const struct v4l2_ctrl_config vivid_ctrl_vert_movement = {
545 .ops = &vivid_vid_cap_ctrl_ops,
546 .id = VIVID_CID_VERT_MOVEMENT,
547 .name = "Vertical Movement",
548 .type = V4L2_CTRL_TYPE_MENU,
549 .max = TPG_MOVE_POS_FAST,
550 .def = TPG_MOVE_NONE,
551 .qmenu = vivid_ctrl_vert_movement_strings,
554 static const struct v4l2_ctrl_config vivid_ctrl_show_border = {
555 .ops = &vivid_vid_cap_ctrl_ops,
556 .id = VIVID_CID_SHOW_BORDER,
557 .name = "Show Border",
558 .type = V4L2_CTRL_TYPE_BOOLEAN,
559 .max = 1,
560 .step = 1,
563 static const struct v4l2_ctrl_config vivid_ctrl_show_square = {
564 .ops = &vivid_vid_cap_ctrl_ops,
565 .id = VIVID_CID_SHOW_SQUARE,
566 .name = "Show Square",
567 .type = V4L2_CTRL_TYPE_BOOLEAN,
568 .max = 1,
569 .step = 1,
572 static const char * const vivid_ctrl_osd_mode_strings[] = {
573 "All",
574 "Counters Only",
575 "None",
576 NULL,
579 static const struct v4l2_ctrl_config vivid_ctrl_osd_mode = {
580 .ops = &vivid_vid_cap_ctrl_ops,
581 .id = VIVID_CID_OSD_TEXT_MODE,
582 .name = "OSD Text Mode",
583 .type = V4L2_CTRL_TYPE_MENU,
584 .max = ARRAY_SIZE(vivid_ctrl_osd_mode_strings) - 2,
585 .qmenu = vivid_ctrl_osd_mode_strings,
588 static const struct v4l2_ctrl_config vivid_ctrl_perc_fill = {
589 .ops = &vivid_vid_cap_ctrl_ops,
590 .id = VIVID_CID_PERCENTAGE_FILL,
591 .name = "Fill Percentage of Frame",
592 .type = V4L2_CTRL_TYPE_INTEGER,
593 .min = 0,
594 .max = 100,
595 .def = 100,
596 .step = 1,
599 static const struct v4l2_ctrl_config vivid_ctrl_insert_sav = {
600 .ops = &vivid_vid_cap_ctrl_ops,
601 .id = VIVID_CID_INSERT_SAV,
602 .name = "Insert SAV Code in Image",
603 .type = V4L2_CTRL_TYPE_BOOLEAN,
604 .max = 1,
605 .step = 1,
608 static const struct v4l2_ctrl_config vivid_ctrl_insert_eav = {
609 .ops = &vivid_vid_cap_ctrl_ops,
610 .id = VIVID_CID_INSERT_EAV,
611 .name = "Insert EAV Code in Image",
612 .type = V4L2_CTRL_TYPE_BOOLEAN,
613 .max = 1,
614 .step = 1,
617 static const struct v4l2_ctrl_config vivid_ctrl_hflip = {
618 .ops = &vivid_vid_cap_ctrl_ops,
619 .id = VIVID_CID_HFLIP,
620 .name = "Sensor Flipped Horizontally",
621 .type = V4L2_CTRL_TYPE_BOOLEAN,
622 .max = 1,
623 .step = 1,
626 static const struct v4l2_ctrl_config vivid_ctrl_vflip = {
627 .ops = &vivid_vid_cap_ctrl_ops,
628 .id = VIVID_CID_VFLIP,
629 .name = "Sensor Flipped Vertically",
630 .type = V4L2_CTRL_TYPE_BOOLEAN,
631 .max = 1,
632 .step = 1,
635 static const struct v4l2_ctrl_config vivid_ctrl_reduced_fps = {
636 .ops = &vivid_vid_cap_ctrl_ops,
637 .id = VIVID_CID_REDUCED_FPS,
638 .name = "Reduced Framerate",
639 .type = V4L2_CTRL_TYPE_BOOLEAN,
640 .max = 1,
641 .step = 1,
644 static const struct v4l2_ctrl_config vivid_ctrl_has_crop_cap = {
645 .ops = &vivid_vid_cap_ctrl_ops,
646 .id = VIVID_CID_HAS_CROP_CAP,
647 .name = "Enable Capture Cropping",
648 .type = V4L2_CTRL_TYPE_BOOLEAN,
649 .max = 1,
650 .def = 1,
651 .step = 1,
654 static const struct v4l2_ctrl_config vivid_ctrl_has_compose_cap = {
655 .ops = &vivid_vid_cap_ctrl_ops,
656 .id = VIVID_CID_HAS_COMPOSE_CAP,
657 .name = "Enable Capture Composing",
658 .type = V4L2_CTRL_TYPE_BOOLEAN,
659 .max = 1,
660 .def = 1,
661 .step = 1,
664 static const struct v4l2_ctrl_config vivid_ctrl_has_scaler_cap = {
665 .ops = &vivid_vid_cap_ctrl_ops,
666 .id = VIVID_CID_HAS_SCALER_CAP,
667 .name = "Enable Capture Scaler",
668 .type = V4L2_CTRL_TYPE_BOOLEAN,
669 .max = 1,
670 .def = 1,
671 .step = 1,
674 static const char * const vivid_ctrl_tstamp_src_strings[] = {
675 "End of Frame",
676 "Start of Exposure",
677 NULL,
680 static const struct v4l2_ctrl_config vivid_ctrl_tstamp_src = {
681 .ops = &vivid_vid_cap_ctrl_ops,
682 .id = VIVID_CID_TSTAMP_SRC,
683 .name = "Timestamp Source",
684 .type = V4L2_CTRL_TYPE_MENU,
685 .max = ARRAY_SIZE(vivid_ctrl_tstamp_src_strings) - 2,
686 .qmenu = vivid_ctrl_tstamp_src_strings,
689 static const struct v4l2_ctrl_config vivid_ctrl_std_aspect_ratio = {
690 .ops = &vivid_vid_cap_ctrl_ops,
691 .id = VIVID_CID_STD_ASPECT_RATIO,
692 .name = "Standard Aspect Ratio",
693 .type = V4L2_CTRL_TYPE_MENU,
694 .min = 1,
695 .max = 4,
696 .def = 1,
697 .qmenu = tpg_aspect_strings,
700 static const char * const vivid_ctrl_dv_timings_signal_mode_strings[] = {
701 "Current DV Timings",
702 "No Signal",
703 "No Lock",
704 "Out of Range",
705 "Selected DV Timings",
706 "Cycle Through All DV Timings",
707 "Custom DV Timings",
708 NULL,
711 static const struct v4l2_ctrl_config vivid_ctrl_dv_timings_signal_mode = {
712 .ops = &vivid_vid_cap_ctrl_ops,
713 .id = VIVID_CID_DV_TIMINGS_SIGNAL_MODE,
714 .name = "DV Timings Signal Mode",
715 .type = V4L2_CTRL_TYPE_MENU,
716 .max = 5,
717 .qmenu = vivid_ctrl_dv_timings_signal_mode_strings,
720 static const struct v4l2_ctrl_config vivid_ctrl_dv_timings_aspect_ratio = {
721 .ops = &vivid_vid_cap_ctrl_ops,
722 .id = VIVID_CID_DV_TIMINGS_ASPECT_RATIO,
723 .name = "DV Timings Aspect Ratio",
724 .type = V4L2_CTRL_TYPE_MENU,
725 .max = 3,
726 .qmenu = tpg_aspect_strings,
729 static const struct v4l2_ctrl_config vivid_ctrl_max_edid_blocks = {
730 .ops = &vivid_vid_cap_ctrl_ops,
731 .id = VIVID_CID_MAX_EDID_BLOCKS,
732 .name = "Maximum EDID Blocks",
733 .type = V4L2_CTRL_TYPE_INTEGER,
734 .min = 1,
735 .max = 256,
736 .def = 2,
737 .step = 1,
740 static const char * const vivid_ctrl_colorspace_strings[] = {
741 "SMPTE 170M",
742 "Rec. 709",
743 "sRGB",
744 "AdobeRGB",
745 "BT.2020",
746 "DCI-P3",
747 "SMPTE 240M",
748 "470 System M",
749 "470 System BG",
750 NULL,
753 static const struct v4l2_ctrl_config vivid_ctrl_colorspace = {
754 .ops = &vivid_vid_cap_ctrl_ops,
755 .id = VIVID_CID_COLORSPACE,
756 .name = "Colorspace",
757 .type = V4L2_CTRL_TYPE_MENU,
758 .max = ARRAY_SIZE(vivid_ctrl_colorspace_strings) - 2,
759 .def = 2,
760 .qmenu = vivid_ctrl_colorspace_strings,
763 static const char * const vivid_ctrl_xfer_func_strings[] = {
764 "Default",
765 "Rec. 709",
766 "sRGB",
767 "AdobeRGB",
768 "SMPTE 240M",
769 "None",
770 "DCI-P3",
771 "SMPTE 2084",
772 NULL,
775 static const struct v4l2_ctrl_config vivid_ctrl_xfer_func = {
776 .ops = &vivid_vid_cap_ctrl_ops,
777 .id = VIVID_CID_XFER_FUNC,
778 .name = "Transfer Function",
779 .type = V4L2_CTRL_TYPE_MENU,
780 .max = ARRAY_SIZE(vivid_ctrl_xfer_func_strings) - 2,
781 .qmenu = vivid_ctrl_xfer_func_strings,
784 static const char * const vivid_ctrl_ycbcr_enc_strings[] = {
785 "Default",
786 "ITU-R 601",
787 "Rec. 709",
788 "xvYCC 601",
789 "xvYCC 709",
791 "BT.2020",
792 "BT.2020 Constant Luminance",
793 "SMPTE 240M",
794 NULL,
797 static const struct v4l2_ctrl_config vivid_ctrl_ycbcr_enc = {
798 .ops = &vivid_vid_cap_ctrl_ops,
799 .id = VIVID_CID_YCBCR_ENC,
800 .name = "Y'CbCr Encoding",
801 .type = V4L2_CTRL_TYPE_MENU,
802 .menu_skip_mask = 1 << 5,
803 .max = ARRAY_SIZE(vivid_ctrl_ycbcr_enc_strings) - 2,
804 .qmenu = vivid_ctrl_ycbcr_enc_strings,
807 static const char * const vivid_ctrl_hsv_enc_strings[] = {
808 "Hue 0-179",
809 "Hue 0-256",
810 NULL,
813 static const struct v4l2_ctrl_config vivid_ctrl_hsv_enc = {
814 .ops = &vivid_vid_cap_ctrl_ops,
815 .id = VIVID_CID_HSV_ENC,
816 .name = "HSV Encoding",
817 .type = V4L2_CTRL_TYPE_MENU,
818 .max = ARRAY_SIZE(vivid_ctrl_hsv_enc_strings) - 2,
819 .qmenu = vivid_ctrl_hsv_enc_strings,
822 static const char * const vivid_ctrl_quantization_strings[] = {
823 "Default",
824 "Full Range",
825 "Limited Range",
826 NULL,
829 static const struct v4l2_ctrl_config vivid_ctrl_quantization = {
830 .ops = &vivid_vid_cap_ctrl_ops,
831 .id = VIVID_CID_QUANTIZATION,
832 .name = "Quantization",
833 .type = V4L2_CTRL_TYPE_MENU,
834 .max = ARRAY_SIZE(vivid_ctrl_quantization_strings) - 2,
835 .qmenu = vivid_ctrl_quantization_strings,
838 static const struct v4l2_ctrl_config vivid_ctrl_alpha_mode = {
839 .ops = &vivid_vid_cap_ctrl_ops,
840 .id = VIVID_CID_ALPHA_MODE,
841 .name = "Apply Alpha To Red Only",
842 .type = V4L2_CTRL_TYPE_BOOLEAN,
843 .max = 1,
844 .step = 1,
847 static const struct v4l2_ctrl_config vivid_ctrl_limited_rgb_range = {
848 .ops = &vivid_vid_cap_ctrl_ops,
849 .id = VIVID_CID_LIMITED_RGB_RANGE,
850 .name = "Limited RGB Range (16-235)",
851 .type = V4L2_CTRL_TYPE_BOOLEAN,
852 .max = 1,
853 .step = 1,
857 /* Video Loop Control */
859 static int vivid_loop_cap_s_ctrl(struct v4l2_ctrl *ctrl)
861 struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_loop_cap);
863 switch (ctrl->id) {
864 case VIVID_CID_LOOP_VIDEO:
865 dev->loop_video = ctrl->val;
866 vivid_update_quality(dev);
867 vivid_send_source_change(dev, SVID);
868 vivid_send_source_change(dev, HDMI);
869 break;
871 return 0;
874 static const struct v4l2_ctrl_ops vivid_loop_cap_ctrl_ops = {
875 .s_ctrl = vivid_loop_cap_s_ctrl,
878 static const struct v4l2_ctrl_config vivid_ctrl_loop_video = {
879 .ops = &vivid_loop_cap_ctrl_ops,
880 .id = VIVID_CID_LOOP_VIDEO,
881 .name = "Loop Video",
882 .type = V4L2_CTRL_TYPE_BOOLEAN,
883 .max = 1,
884 .step = 1,
888 /* VBI Capture Control */
890 static int vivid_vbi_cap_s_ctrl(struct v4l2_ctrl *ctrl)
892 struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_vbi_cap);
894 switch (ctrl->id) {
895 case VIVID_CID_VBI_CAP_INTERLACED:
896 dev->vbi_cap_interlaced = ctrl->val;
897 break;
899 return 0;
902 static const struct v4l2_ctrl_ops vivid_vbi_cap_ctrl_ops = {
903 .s_ctrl = vivid_vbi_cap_s_ctrl,
906 static const struct v4l2_ctrl_config vivid_ctrl_vbi_cap_interlaced = {
907 .ops = &vivid_vbi_cap_ctrl_ops,
908 .id = VIVID_CID_VBI_CAP_INTERLACED,
909 .name = "Interlaced VBI Format",
910 .type = V4L2_CTRL_TYPE_BOOLEAN,
911 .max = 1,
912 .step = 1,
916 /* Video Output Controls */
918 static int vivid_vid_out_s_ctrl(struct v4l2_ctrl *ctrl)
920 struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_vid_out);
921 struct v4l2_bt_timings *bt = &dev->dv_timings_out.bt;
923 switch (ctrl->id) {
924 case VIVID_CID_HAS_CROP_OUT:
925 dev->has_crop_out = ctrl->val;
926 vivid_update_format_out(dev);
927 break;
928 case VIVID_CID_HAS_COMPOSE_OUT:
929 dev->has_compose_out = ctrl->val;
930 vivid_update_format_out(dev);
931 break;
932 case VIVID_CID_HAS_SCALER_OUT:
933 dev->has_scaler_out = ctrl->val;
934 vivid_update_format_out(dev);
935 break;
936 case V4L2_CID_DV_TX_MODE:
937 dev->dvi_d_out = ctrl->val == V4L2_DV_TX_MODE_DVI_D;
938 if (!vivid_is_hdmi_out(dev))
939 break;
940 if (!dev->dvi_d_out && (bt->flags & V4L2_DV_FL_IS_CE_VIDEO)) {
941 if (bt->width == 720 && bt->height <= 576)
942 dev->colorspace_out = V4L2_COLORSPACE_SMPTE170M;
943 else
944 dev->colorspace_out = V4L2_COLORSPACE_REC709;
945 dev->quantization_out = V4L2_QUANTIZATION_DEFAULT;
946 } else {
947 dev->colorspace_out = V4L2_COLORSPACE_SRGB;
948 dev->quantization_out = dev->dvi_d_out ?
949 V4L2_QUANTIZATION_LIM_RANGE :
950 V4L2_QUANTIZATION_DEFAULT;
952 if (dev->loop_video)
953 vivid_send_source_change(dev, HDMI);
954 break;
956 return 0;
959 static const struct v4l2_ctrl_ops vivid_vid_out_ctrl_ops = {
960 .s_ctrl = vivid_vid_out_s_ctrl,
963 static const struct v4l2_ctrl_config vivid_ctrl_has_crop_out = {
964 .ops = &vivid_vid_out_ctrl_ops,
965 .id = VIVID_CID_HAS_CROP_OUT,
966 .name = "Enable Output Cropping",
967 .type = V4L2_CTRL_TYPE_BOOLEAN,
968 .max = 1,
969 .def = 1,
970 .step = 1,
973 static const struct v4l2_ctrl_config vivid_ctrl_has_compose_out = {
974 .ops = &vivid_vid_out_ctrl_ops,
975 .id = VIVID_CID_HAS_COMPOSE_OUT,
976 .name = "Enable Output Composing",
977 .type = V4L2_CTRL_TYPE_BOOLEAN,
978 .max = 1,
979 .def = 1,
980 .step = 1,
983 static const struct v4l2_ctrl_config vivid_ctrl_has_scaler_out = {
984 .ops = &vivid_vid_out_ctrl_ops,
985 .id = VIVID_CID_HAS_SCALER_OUT,
986 .name = "Enable Output Scaler",
987 .type = V4L2_CTRL_TYPE_BOOLEAN,
988 .max = 1,
989 .def = 1,
990 .step = 1,
994 /* Streaming Controls */
996 static int vivid_streaming_s_ctrl(struct v4l2_ctrl *ctrl)
998 struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_streaming);
999 u64 rem;
1001 switch (ctrl->id) {
1002 case VIVID_CID_DQBUF_ERROR:
1003 dev->dqbuf_error = true;
1004 break;
1005 case VIVID_CID_PERC_DROPPED:
1006 dev->perc_dropped_buffers = ctrl->val;
1007 break;
1008 case VIVID_CID_QUEUE_SETUP_ERROR:
1009 dev->queue_setup_error = true;
1010 break;
1011 case VIVID_CID_BUF_PREPARE_ERROR:
1012 dev->buf_prepare_error = true;
1013 break;
1014 case VIVID_CID_START_STR_ERROR:
1015 dev->start_streaming_error = true;
1016 break;
1017 case VIVID_CID_QUEUE_ERROR:
1018 if (vb2_start_streaming_called(&dev->vb_vid_cap_q))
1019 vb2_queue_error(&dev->vb_vid_cap_q);
1020 if (vb2_start_streaming_called(&dev->vb_vbi_cap_q))
1021 vb2_queue_error(&dev->vb_vbi_cap_q);
1022 if (vb2_start_streaming_called(&dev->vb_vid_out_q))
1023 vb2_queue_error(&dev->vb_vid_out_q);
1024 if (vb2_start_streaming_called(&dev->vb_vbi_out_q))
1025 vb2_queue_error(&dev->vb_vbi_out_q);
1026 if (vb2_start_streaming_called(&dev->vb_sdr_cap_q))
1027 vb2_queue_error(&dev->vb_sdr_cap_q);
1028 break;
1029 case VIVID_CID_SEQ_WRAP:
1030 dev->seq_wrap = ctrl->val;
1031 break;
1032 case VIVID_CID_TIME_WRAP:
1033 dev->time_wrap = ctrl->val;
1034 if (ctrl->val == 0) {
1035 dev->time_wrap_offset = 0;
1036 break;
1039 * We want to set the time 16 seconds before the 32 bit tv_sec
1040 * value of struct timeval would wrap around. So first we
1041 * calculate ktime_get_ns() % ((1 << 32) * NSEC_PER_SEC), and
1042 * then we set the offset to ((1 << 32) - 16) * NSEC_PER_SEC).
1044 div64_u64_rem(ktime_get_ns(),
1045 0x100000000ULL * NSEC_PER_SEC, &rem);
1046 dev->time_wrap_offset =
1047 (0x100000000ULL - 16) * NSEC_PER_SEC - rem;
1048 break;
1050 return 0;
1053 static const struct v4l2_ctrl_ops vivid_streaming_ctrl_ops = {
1054 .s_ctrl = vivid_streaming_s_ctrl,
1057 static const struct v4l2_ctrl_config vivid_ctrl_dqbuf_error = {
1058 .ops = &vivid_streaming_ctrl_ops,
1059 .id = VIVID_CID_DQBUF_ERROR,
1060 .name = "Inject V4L2_BUF_FLAG_ERROR",
1061 .type = V4L2_CTRL_TYPE_BUTTON,
1064 static const struct v4l2_ctrl_config vivid_ctrl_perc_dropped = {
1065 .ops = &vivid_streaming_ctrl_ops,
1066 .id = VIVID_CID_PERC_DROPPED,
1067 .name = "Percentage of Dropped Buffers",
1068 .type = V4L2_CTRL_TYPE_INTEGER,
1069 .min = 0,
1070 .max = 100,
1071 .step = 1,
1074 static const struct v4l2_ctrl_config vivid_ctrl_queue_setup_error = {
1075 .ops = &vivid_streaming_ctrl_ops,
1076 .id = VIVID_CID_QUEUE_SETUP_ERROR,
1077 .name = "Inject VIDIOC_REQBUFS Error",
1078 .type = V4L2_CTRL_TYPE_BUTTON,
1081 static const struct v4l2_ctrl_config vivid_ctrl_buf_prepare_error = {
1082 .ops = &vivid_streaming_ctrl_ops,
1083 .id = VIVID_CID_BUF_PREPARE_ERROR,
1084 .name = "Inject VIDIOC_QBUF Error",
1085 .type = V4L2_CTRL_TYPE_BUTTON,
1088 static const struct v4l2_ctrl_config vivid_ctrl_start_streaming_error = {
1089 .ops = &vivid_streaming_ctrl_ops,
1090 .id = VIVID_CID_START_STR_ERROR,
1091 .name = "Inject VIDIOC_STREAMON Error",
1092 .type = V4L2_CTRL_TYPE_BUTTON,
1095 static const struct v4l2_ctrl_config vivid_ctrl_queue_error = {
1096 .ops = &vivid_streaming_ctrl_ops,
1097 .id = VIVID_CID_QUEUE_ERROR,
1098 .name = "Inject Fatal Streaming Error",
1099 .type = V4L2_CTRL_TYPE_BUTTON,
1102 static const struct v4l2_ctrl_config vivid_ctrl_seq_wrap = {
1103 .ops = &vivid_streaming_ctrl_ops,
1104 .id = VIVID_CID_SEQ_WRAP,
1105 .name = "Wrap Sequence Number",
1106 .type = V4L2_CTRL_TYPE_BOOLEAN,
1107 .max = 1,
1108 .step = 1,
1111 static const struct v4l2_ctrl_config vivid_ctrl_time_wrap = {
1112 .ops = &vivid_streaming_ctrl_ops,
1113 .id = VIVID_CID_TIME_WRAP,
1114 .name = "Wrap Timestamp",
1115 .type = V4L2_CTRL_TYPE_BOOLEAN,
1116 .max = 1,
1117 .step = 1,
1121 /* SDTV Capture Controls */
1123 static int vivid_sdtv_cap_s_ctrl(struct v4l2_ctrl *ctrl)
1125 struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_sdtv_cap);
1127 switch (ctrl->id) {
1128 case VIVID_CID_STD_SIGNAL_MODE:
1129 dev->std_signal_mode = dev->ctrl_std_signal_mode->val;
1130 if (dev->std_signal_mode == SELECTED_STD)
1131 dev->query_std = vivid_standard[dev->ctrl_standard->val];
1132 v4l2_ctrl_activate(dev->ctrl_standard, dev->std_signal_mode == SELECTED_STD);
1133 vivid_update_quality(dev);
1134 vivid_send_source_change(dev, TV);
1135 vivid_send_source_change(dev, SVID);
1136 break;
1138 return 0;
1141 static const struct v4l2_ctrl_ops vivid_sdtv_cap_ctrl_ops = {
1142 .s_ctrl = vivid_sdtv_cap_s_ctrl,
1145 static const char * const vivid_ctrl_std_signal_mode_strings[] = {
1146 "Current Standard",
1147 "No Signal",
1148 "No Lock",
1150 "Selected Standard",
1151 "Cycle Through All Standards",
1152 NULL,
1155 static const struct v4l2_ctrl_config vivid_ctrl_std_signal_mode = {
1156 .ops = &vivid_sdtv_cap_ctrl_ops,
1157 .id = VIVID_CID_STD_SIGNAL_MODE,
1158 .name = "Standard Signal Mode",
1159 .type = V4L2_CTRL_TYPE_MENU,
1160 .max = ARRAY_SIZE(vivid_ctrl_std_signal_mode_strings) - 2,
1161 .menu_skip_mask = 1 << 3,
1162 .qmenu = vivid_ctrl_std_signal_mode_strings,
1165 static const struct v4l2_ctrl_config vivid_ctrl_standard = {
1166 .ops = &vivid_sdtv_cap_ctrl_ops,
1167 .id = VIVID_CID_STANDARD,
1168 .name = "Standard",
1169 .type = V4L2_CTRL_TYPE_MENU,
1170 .max = 14,
1171 .qmenu = vivid_ctrl_standard_strings,
1176 /* Radio Receiver Controls */
1178 static int vivid_radio_rx_s_ctrl(struct v4l2_ctrl *ctrl)
1180 struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_radio_rx);
1182 switch (ctrl->id) {
1183 case VIVID_CID_RADIO_SEEK_MODE:
1184 dev->radio_rx_hw_seek_mode = ctrl->val;
1185 break;
1186 case VIVID_CID_RADIO_SEEK_PROG_LIM:
1187 dev->radio_rx_hw_seek_prog_lim = ctrl->val;
1188 break;
1189 case VIVID_CID_RADIO_RX_RDS_RBDS:
1190 dev->rds_gen.use_rbds = ctrl->val;
1191 break;
1192 case VIVID_CID_RADIO_RX_RDS_BLOCKIO:
1193 dev->radio_rx_rds_controls = ctrl->val;
1194 dev->radio_rx_caps &= ~V4L2_CAP_READWRITE;
1195 dev->radio_rx_rds_use_alternates = false;
1196 if (!dev->radio_rx_rds_controls) {
1197 dev->radio_rx_caps |= V4L2_CAP_READWRITE;
1198 __v4l2_ctrl_s_ctrl(dev->radio_rx_rds_pty, 0);
1199 __v4l2_ctrl_s_ctrl(dev->radio_rx_rds_ta, 0);
1200 __v4l2_ctrl_s_ctrl(dev->radio_rx_rds_tp, 0);
1201 __v4l2_ctrl_s_ctrl(dev->radio_rx_rds_ms, 0);
1202 __v4l2_ctrl_s_ctrl_string(dev->radio_rx_rds_psname, "");
1203 __v4l2_ctrl_s_ctrl_string(dev->radio_rx_rds_radiotext, "");
1205 v4l2_ctrl_activate(dev->radio_rx_rds_pty, dev->radio_rx_rds_controls);
1206 v4l2_ctrl_activate(dev->radio_rx_rds_psname, dev->radio_rx_rds_controls);
1207 v4l2_ctrl_activate(dev->radio_rx_rds_radiotext, dev->radio_rx_rds_controls);
1208 v4l2_ctrl_activate(dev->radio_rx_rds_ta, dev->radio_rx_rds_controls);
1209 v4l2_ctrl_activate(dev->radio_rx_rds_tp, dev->radio_rx_rds_controls);
1210 v4l2_ctrl_activate(dev->radio_rx_rds_ms, dev->radio_rx_rds_controls);
1211 break;
1212 case V4L2_CID_RDS_RECEPTION:
1213 dev->radio_rx_rds_enabled = ctrl->val;
1214 break;
1216 return 0;
1219 static const struct v4l2_ctrl_ops vivid_radio_rx_ctrl_ops = {
1220 .s_ctrl = vivid_radio_rx_s_ctrl,
1223 static const char * const vivid_ctrl_radio_rds_mode_strings[] = {
1224 "Block I/O",
1225 "Controls",
1226 NULL,
1229 static const struct v4l2_ctrl_config vivid_ctrl_radio_rx_rds_blockio = {
1230 .ops = &vivid_radio_rx_ctrl_ops,
1231 .id = VIVID_CID_RADIO_RX_RDS_BLOCKIO,
1232 .name = "RDS Rx I/O Mode",
1233 .type = V4L2_CTRL_TYPE_MENU,
1234 .qmenu = vivid_ctrl_radio_rds_mode_strings,
1235 .max = 1,
1238 static const struct v4l2_ctrl_config vivid_ctrl_radio_rx_rds_rbds = {
1239 .ops = &vivid_radio_rx_ctrl_ops,
1240 .id = VIVID_CID_RADIO_RX_RDS_RBDS,
1241 .name = "Generate RBDS Instead of RDS",
1242 .type = V4L2_CTRL_TYPE_BOOLEAN,
1243 .max = 1,
1244 .step = 1,
1247 static const char * const vivid_ctrl_radio_hw_seek_mode_strings[] = {
1248 "Bounded",
1249 "Wrap Around",
1250 "Both",
1251 NULL,
1254 static const struct v4l2_ctrl_config vivid_ctrl_radio_hw_seek_mode = {
1255 .ops = &vivid_radio_rx_ctrl_ops,
1256 .id = VIVID_CID_RADIO_SEEK_MODE,
1257 .name = "Radio HW Seek Mode",
1258 .type = V4L2_CTRL_TYPE_MENU,
1259 .max = 2,
1260 .qmenu = vivid_ctrl_radio_hw_seek_mode_strings,
1263 static const struct v4l2_ctrl_config vivid_ctrl_radio_hw_seek_prog_lim = {
1264 .ops = &vivid_radio_rx_ctrl_ops,
1265 .id = VIVID_CID_RADIO_SEEK_PROG_LIM,
1266 .name = "Radio Programmable HW Seek",
1267 .type = V4L2_CTRL_TYPE_BOOLEAN,
1268 .max = 1,
1269 .step = 1,
1273 /* Radio Transmitter Controls */
1275 static int vivid_radio_tx_s_ctrl(struct v4l2_ctrl *ctrl)
1277 struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_radio_tx);
1279 switch (ctrl->id) {
1280 case VIVID_CID_RADIO_TX_RDS_BLOCKIO:
1281 dev->radio_tx_rds_controls = ctrl->val;
1282 dev->radio_tx_caps &= ~V4L2_CAP_READWRITE;
1283 if (!dev->radio_tx_rds_controls)
1284 dev->radio_tx_caps |= V4L2_CAP_READWRITE;
1285 break;
1286 case V4L2_CID_RDS_TX_PTY:
1287 if (dev->radio_rx_rds_controls)
1288 v4l2_ctrl_s_ctrl(dev->radio_rx_rds_pty, ctrl->val);
1289 break;
1290 case V4L2_CID_RDS_TX_PS_NAME:
1291 if (dev->radio_rx_rds_controls)
1292 v4l2_ctrl_s_ctrl_string(dev->radio_rx_rds_psname, ctrl->p_new.p_char);
1293 break;
1294 case V4L2_CID_RDS_TX_RADIO_TEXT:
1295 if (dev->radio_rx_rds_controls)
1296 v4l2_ctrl_s_ctrl_string(dev->radio_rx_rds_radiotext, ctrl->p_new.p_char);
1297 break;
1298 case V4L2_CID_RDS_TX_TRAFFIC_ANNOUNCEMENT:
1299 if (dev->radio_rx_rds_controls)
1300 v4l2_ctrl_s_ctrl(dev->radio_rx_rds_ta, ctrl->val);
1301 break;
1302 case V4L2_CID_RDS_TX_TRAFFIC_PROGRAM:
1303 if (dev->radio_rx_rds_controls)
1304 v4l2_ctrl_s_ctrl(dev->radio_rx_rds_tp, ctrl->val);
1305 break;
1306 case V4L2_CID_RDS_TX_MUSIC_SPEECH:
1307 if (dev->radio_rx_rds_controls)
1308 v4l2_ctrl_s_ctrl(dev->radio_rx_rds_ms, ctrl->val);
1309 break;
1311 return 0;
1314 static const struct v4l2_ctrl_ops vivid_radio_tx_ctrl_ops = {
1315 .s_ctrl = vivid_radio_tx_s_ctrl,
1318 static const struct v4l2_ctrl_config vivid_ctrl_radio_tx_rds_blockio = {
1319 .ops = &vivid_radio_tx_ctrl_ops,
1320 .id = VIVID_CID_RADIO_TX_RDS_BLOCKIO,
1321 .name = "RDS Tx I/O Mode",
1322 .type = V4L2_CTRL_TYPE_MENU,
1323 .qmenu = vivid_ctrl_radio_rds_mode_strings,
1324 .max = 1,
1325 .def = 1,
1329 /* SDR Capture Controls */
1331 static int vivid_sdr_cap_s_ctrl(struct v4l2_ctrl *ctrl)
1333 struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_sdr_cap);
1335 switch (ctrl->id) {
1336 case VIVID_CID_SDR_CAP_FM_DEVIATION:
1337 dev->sdr_fm_deviation = ctrl->val;
1338 break;
1340 return 0;
1343 static const struct v4l2_ctrl_ops vivid_sdr_cap_ctrl_ops = {
1344 .s_ctrl = vivid_sdr_cap_s_ctrl,
1347 static const struct v4l2_ctrl_config vivid_ctrl_sdr_cap_fm_deviation = {
1348 .ops = &vivid_sdr_cap_ctrl_ops,
1349 .id = VIVID_CID_SDR_CAP_FM_DEVIATION,
1350 .name = "FM Deviation",
1351 .type = V4L2_CTRL_TYPE_INTEGER,
1352 .min = 100,
1353 .max = 200000,
1354 .def = 75000,
1355 .step = 1,
1359 static const struct v4l2_ctrl_config vivid_ctrl_class = {
1360 .ops = &vivid_user_gen_ctrl_ops,
1361 .flags = V4L2_CTRL_FLAG_READ_ONLY | V4L2_CTRL_FLAG_WRITE_ONLY,
1362 .id = VIVID_CID_VIVID_CLASS,
1363 .name = "Vivid Controls",
1364 .type = V4L2_CTRL_TYPE_CTRL_CLASS,
1367 int vivid_create_controls(struct vivid_dev *dev, bool show_ccs_cap,
1368 bool show_ccs_out, bool no_error_inj,
1369 bool has_sdtv, bool has_hdmi)
1371 struct v4l2_ctrl_handler *hdl_user_gen = &dev->ctrl_hdl_user_gen;
1372 struct v4l2_ctrl_handler *hdl_user_vid = &dev->ctrl_hdl_user_vid;
1373 struct v4l2_ctrl_handler *hdl_user_aud = &dev->ctrl_hdl_user_aud;
1374 struct v4l2_ctrl_handler *hdl_streaming = &dev->ctrl_hdl_streaming;
1375 struct v4l2_ctrl_handler *hdl_sdtv_cap = &dev->ctrl_hdl_sdtv_cap;
1376 struct v4l2_ctrl_handler *hdl_loop_cap = &dev->ctrl_hdl_loop_cap;
1377 struct v4l2_ctrl_handler *hdl_fb = &dev->ctrl_hdl_fb;
1378 struct v4l2_ctrl_handler *hdl_vid_cap = &dev->ctrl_hdl_vid_cap;
1379 struct v4l2_ctrl_handler *hdl_vid_out = &dev->ctrl_hdl_vid_out;
1380 struct v4l2_ctrl_handler *hdl_vbi_cap = &dev->ctrl_hdl_vbi_cap;
1381 struct v4l2_ctrl_handler *hdl_vbi_out = &dev->ctrl_hdl_vbi_out;
1382 struct v4l2_ctrl_handler *hdl_radio_rx = &dev->ctrl_hdl_radio_rx;
1383 struct v4l2_ctrl_handler *hdl_radio_tx = &dev->ctrl_hdl_radio_tx;
1384 struct v4l2_ctrl_handler *hdl_sdr_cap = &dev->ctrl_hdl_sdr_cap;
1385 struct v4l2_ctrl_config vivid_ctrl_dv_timings = {
1386 .ops = &vivid_vid_cap_ctrl_ops,
1387 .id = VIVID_CID_DV_TIMINGS,
1388 .name = "DV Timings",
1389 .type = V4L2_CTRL_TYPE_MENU,
1391 int i;
1393 v4l2_ctrl_handler_init(hdl_user_gen, 10);
1394 v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_class, NULL);
1395 v4l2_ctrl_handler_init(hdl_user_vid, 9);
1396 v4l2_ctrl_new_custom(hdl_user_vid, &vivid_ctrl_class, NULL);
1397 v4l2_ctrl_handler_init(hdl_user_aud, 2);
1398 v4l2_ctrl_new_custom(hdl_user_aud, &vivid_ctrl_class, NULL);
1399 v4l2_ctrl_handler_init(hdl_streaming, 8);
1400 v4l2_ctrl_new_custom(hdl_streaming, &vivid_ctrl_class, NULL);
1401 v4l2_ctrl_handler_init(hdl_sdtv_cap, 2);
1402 v4l2_ctrl_new_custom(hdl_sdtv_cap, &vivid_ctrl_class, NULL);
1403 v4l2_ctrl_handler_init(hdl_loop_cap, 1);
1404 v4l2_ctrl_new_custom(hdl_loop_cap, &vivid_ctrl_class, NULL);
1405 v4l2_ctrl_handler_init(hdl_fb, 1);
1406 v4l2_ctrl_new_custom(hdl_fb, &vivid_ctrl_class, NULL);
1407 v4l2_ctrl_handler_init(hdl_vid_cap, 55);
1408 v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_class, NULL);
1409 v4l2_ctrl_handler_init(hdl_vid_out, 26);
1410 if (!no_error_inj || dev->has_fb)
1411 v4l2_ctrl_new_custom(hdl_vid_out, &vivid_ctrl_class, NULL);
1412 v4l2_ctrl_handler_init(hdl_vbi_cap, 21);
1413 v4l2_ctrl_new_custom(hdl_vbi_cap, &vivid_ctrl_class, NULL);
1414 v4l2_ctrl_handler_init(hdl_vbi_out, 19);
1415 if (!no_error_inj)
1416 v4l2_ctrl_new_custom(hdl_vbi_out, &vivid_ctrl_class, NULL);
1417 v4l2_ctrl_handler_init(hdl_radio_rx, 17);
1418 v4l2_ctrl_new_custom(hdl_radio_rx, &vivid_ctrl_class, NULL);
1419 v4l2_ctrl_handler_init(hdl_radio_tx, 17);
1420 v4l2_ctrl_new_custom(hdl_radio_tx, &vivid_ctrl_class, NULL);
1421 v4l2_ctrl_handler_init(hdl_sdr_cap, 19);
1422 v4l2_ctrl_new_custom(hdl_sdr_cap, &vivid_ctrl_class, NULL);
1424 /* User Controls */
1425 dev->volume = v4l2_ctrl_new_std(hdl_user_aud, NULL,
1426 V4L2_CID_AUDIO_VOLUME, 0, 255, 1, 200);
1427 dev->mute = v4l2_ctrl_new_std(hdl_user_aud, NULL,
1428 V4L2_CID_AUDIO_MUTE, 0, 1, 1, 0);
1429 if (dev->has_vid_cap) {
1430 dev->brightness = v4l2_ctrl_new_std(hdl_user_vid, &vivid_user_vid_ctrl_ops,
1431 V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
1432 for (i = 0; i < MAX_INPUTS; i++)
1433 dev->input_brightness[i] = 128;
1434 dev->contrast = v4l2_ctrl_new_std(hdl_user_vid, &vivid_user_vid_ctrl_ops,
1435 V4L2_CID_CONTRAST, 0, 255, 1, 128);
1436 dev->saturation = v4l2_ctrl_new_std(hdl_user_vid, &vivid_user_vid_ctrl_ops,
1437 V4L2_CID_SATURATION, 0, 255, 1, 128);
1438 dev->hue = v4l2_ctrl_new_std(hdl_user_vid, &vivid_user_vid_ctrl_ops,
1439 V4L2_CID_HUE, -128, 128, 1, 0);
1440 v4l2_ctrl_new_std(hdl_user_vid, &vivid_user_vid_ctrl_ops,
1441 V4L2_CID_HFLIP, 0, 1, 1, 0);
1442 v4l2_ctrl_new_std(hdl_user_vid, &vivid_user_vid_ctrl_ops,
1443 V4L2_CID_VFLIP, 0, 1, 1, 0);
1444 dev->autogain = v4l2_ctrl_new_std(hdl_user_vid, &vivid_user_vid_ctrl_ops,
1445 V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
1446 dev->gain = v4l2_ctrl_new_std(hdl_user_vid, &vivid_user_vid_ctrl_ops,
1447 V4L2_CID_GAIN, 0, 255, 1, 100);
1448 dev->alpha = v4l2_ctrl_new_std(hdl_user_vid, &vivid_user_vid_ctrl_ops,
1449 V4L2_CID_ALPHA_COMPONENT, 0, 255, 1, 0);
1451 dev->button = v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_button, NULL);
1452 dev->int32 = v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_int32, NULL);
1453 dev->int64 = v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_int64, NULL);
1454 dev->boolean = v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_boolean, NULL);
1455 dev->menu = v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_menu, NULL);
1456 dev->string = v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_string, NULL);
1457 dev->bitmask = v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_bitmask, NULL);
1458 dev->int_menu = v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_int_menu, NULL);
1459 v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_u32_array, NULL);
1460 v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_u16_matrix, NULL);
1461 v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_u8_4d_array, NULL);
1463 if (dev->has_vid_cap) {
1464 /* Image Processing Controls */
1465 struct v4l2_ctrl_config vivid_ctrl_test_pattern = {
1466 .ops = &vivid_vid_cap_ctrl_ops,
1467 .id = VIVID_CID_TEST_PATTERN,
1468 .name = "Test Pattern",
1469 .type = V4L2_CTRL_TYPE_MENU,
1470 .max = TPG_PAT_NOISE,
1471 .qmenu = tpg_pattern_strings,
1474 dev->test_pattern = v4l2_ctrl_new_custom(hdl_vid_cap,
1475 &vivid_ctrl_test_pattern, NULL);
1476 v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_perc_fill, NULL);
1477 v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_hor_movement, NULL);
1478 v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_vert_movement, NULL);
1479 v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_osd_mode, NULL);
1480 v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_show_border, NULL);
1481 v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_show_square, NULL);
1482 v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_hflip, NULL);
1483 v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_vflip, NULL);
1484 v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_insert_sav, NULL);
1485 v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_insert_eav, NULL);
1486 v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_reduced_fps, NULL);
1487 if (show_ccs_cap) {
1488 dev->ctrl_has_crop_cap = v4l2_ctrl_new_custom(hdl_vid_cap,
1489 &vivid_ctrl_has_crop_cap, NULL);
1490 dev->ctrl_has_compose_cap = v4l2_ctrl_new_custom(hdl_vid_cap,
1491 &vivid_ctrl_has_compose_cap, NULL);
1492 dev->ctrl_has_scaler_cap = v4l2_ctrl_new_custom(hdl_vid_cap,
1493 &vivid_ctrl_has_scaler_cap, NULL);
1496 v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_tstamp_src, NULL);
1497 dev->colorspace = v4l2_ctrl_new_custom(hdl_vid_cap,
1498 &vivid_ctrl_colorspace, NULL);
1499 v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_xfer_func, NULL);
1500 v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_ycbcr_enc, NULL);
1501 v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_hsv_enc, NULL);
1502 v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_quantization, NULL);
1503 v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_alpha_mode, NULL);
1506 if (dev->has_vid_out && show_ccs_out) {
1507 dev->ctrl_has_crop_out = v4l2_ctrl_new_custom(hdl_vid_out,
1508 &vivid_ctrl_has_crop_out, NULL);
1509 dev->ctrl_has_compose_out = v4l2_ctrl_new_custom(hdl_vid_out,
1510 &vivid_ctrl_has_compose_out, NULL);
1511 dev->ctrl_has_scaler_out = v4l2_ctrl_new_custom(hdl_vid_out,
1512 &vivid_ctrl_has_scaler_out, NULL);
1516 * Testing this driver with v4l2-compliance will trigger the error
1517 * injection controls, and after that nothing will work as expected.
1518 * So we have a module option to drop these error injecting controls
1519 * allowing us to run v4l2_compliance again.
1521 if (!no_error_inj) {
1522 v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_disconnect, NULL);
1523 v4l2_ctrl_new_custom(hdl_streaming, &vivid_ctrl_dqbuf_error, NULL);
1524 v4l2_ctrl_new_custom(hdl_streaming, &vivid_ctrl_perc_dropped, NULL);
1525 v4l2_ctrl_new_custom(hdl_streaming, &vivid_ctrl_queue_setup_error, NULL);
1526 v4l2_ctrl_new_custom(hdl_streaming, &vivid_ctrl_buf_prepare_error, NULL);
1527 v4l2_ctrl_new_custom(hdl_streaming, &vivid_ctrl_start_streaming_error, NULL);
1528 v4l2_ctrl_new_custom(hdl_streaming, &vivid_ctrl_queue_error, NULL);
1529 v4l2_ctrl_new_custom(hdl_streaming, &vivid_ctrl_seq_wrap, NULL);
1530 v4l2_ctrl_new_custom(hdl_streaming, &vivid_ctrl_time_wrap, NULL);
1533 if (has_sdtv && (dev->has_vid_cap || dev->has_vbi_cap)) {
1534 if (dev->has_vid_cap)
1535 v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_std_aspect_ratio, NULL);
1536 dev->ctrl_std_signal_mode = v4l2_ctrl_new_custom(hdl_sdtv_cap,
1537 &vivid_ctrl_std_signal_mode, NULL);
1538 dev->ctrl_standard = v4l2_ctrl_new_custom(hdl_sdtv_cap,
1539 &vivid_ctrl_standard, NULL);
1540 if (dev->ctrl_std_signal_mode)
1541 v4l2_ctrl_cluster(2, &dev->ctrl_std_signal_mode);
1542 if (dev->has_raw_vbi_cap)
1543 v4l2_ctrl_new_custom(hdl_vbi_cap, &vivid_ctrl_vbi_cap_interlaced, NULL);
1546 if (has_hdmi && dev->has_vid_cap) {
1547 dev->ctrl_dv_timings_signal_mode = v4l2_ctrl_new_custom(hdl_vid_cap,
1548 &vivid_ctrl_dv_timings_signal_mode, NULL);
1550 vivid_ctrl_dv_timings.max = dev->query_dv_timings_size - 1;
1551 vivid_ctrl_dv_timings.qmenu =
1552 (const char * const *)dev->query_dv_timings_qmenu;
1553 dev->ctrl_dv_timings = v4l2_ctrl_new_custom(hdl_vid_cap,
1554 &vivid_ctrl_dv_timings, NULL);
1555 if (dev->ctrl_dv_timings_signal_mode)
1556 v4l2_ctrl_cluster(2, &dev->ctrl_dv_timings_signal_mode);
1558 v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_dv_timings_aspect_ratio, NULL);
1559 v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_max_edid_blocks, NULL);
1560 dev->real_rgb_range_cap = v4l2_ctrl_new_custom(hdl_vid_cap,
1561 &vivid_ctrl_limited_rgb_range, NULL);
1562 dev->rgb_range_cap = v4l2_ctrl_new_std_menu(hdl_vid_cap,
1563 &vivid_vid_cap_ctrl_ops,
1564 V4L2_CID_DV_RX_RGB_RANGE, V4L2_DV_RGB_RANGE_FULL,
1565 0, V4L2_DV_RGB_RANGE_AUTO);
1567 if (has_hdmi && dev->has_vid_out) {
1569 * We aren't doing anything with this at the moment, but
1570 * HDMI outputs typically have this controls.
1572 dev->ctrl_tx_rgb_range = v4l2_ctrl_new_std_menu(hdl_vid_out, NULL,
1573 V4L2_CID_DV_TX_RGB_RANGE, V4L2_DV_RGB_RANGE_FULL,
1574 0, V4L2_DV_RGB_RANGE_AUTO);
1575 dev->ctrl_tx_mode = v4l2_ctrl_new_std_menu(hdl_vid_out, NULL,
1576 V4L2_CID_DV_TX_MODE, V4L2_DV_TX_MODE_HDMI,
1577 0, V4L2_DV_TX_MODE_HDMI);
1579 if ((dev->has_vid_cap && dev->has_vid_out) ||
1580 (dev->has_vbi_cap && dev->has_vbi_out))
1581 v4l2_ctrl_new_custom(hdl_loop_cap, &vivid_ctrl_loop_video, NULL);
1583 if (dev->has_fb)
1584 v4l2_ctrl_new_custom(hdl_fb, &vivid_ctrl_clear_fb, NULL);
1586 if (dev->has_radio_rx) {
1587 v4l2_ctrl_new_custom(hdl_radio_rx, &vivid_ctrl_radio_hw_seek_mode, NULL);
1588 v4l2_ctrl_new_custom(hdl_radio_rx, &vivid_ctrl_radio_hw_seek_prog_lim, NULL);
1589 v4l2_ctrl_new_custom(hdl_radio_rx, &vivid_ctrl_radio_rx_rds_blockio, NULL);
1590 v4l2_ctrl_new_custom(hdl_radio_rx, &vivid_ctrl_radio_rx_rds_rbds, NULL);
1591 v4l2_ctrl_new_std(hdl_radio_rx, &vivid_radio_rx_ctrl_ops,
1592 V4L2_CID_RDS_RECEPTION, 0, 1, 1, 1);
1593 dev->radio_rx_rds_pty = v4l2_ctrl_new_std(hdl_radio_rx,
1594 &vivid_radio_rx_ctrl_ops,
1595 V4L2_CID_RDS_RX_PTY, 0, 31, 1, 0);
1596 dev->radio_rx_rds_psname = v4l2_ctrl_new_std(hdl_radio_rx,
1597 &vivid_radio_rx_ctrl_ops,
1598 V4L2_CID_RDS_RX_PS_NAME, 0, 8, 8, 0);
1599 dev->radio_rx_rds_radiotext = v4l2_ctrl_new_std(hdl_radio_rx,
1600 &vivid_radio_rx_ctrl_ops,
1601 V4L2_CID_RDS_RX_RADIO_TEXT, 0, 64, 64, 0);
1602 dev->radio_rx_rds_ta = v4l2_ctrl_new_std(hdl_radio_rx,
1603 &vivid_radio_rx_ctrl_ops,
1604 V4L2_CID_RDS_RX_TRAFFIC_ANNOUNCEMENT, 0, 1, 1, 0);
1605 dev->radio_rx_rds_tp = v4l2_ctrl_new_std(hdl_radio_rx,
1606 &vivid_radio_rx_ctrl_ops,
1607 V4L2_CID_RDS_RX_TRAFFIC_PROGRAM, 0, 1, 1, 0);
1608 dev->radio_rx_rds_ms = v4l2_ctrl_new_std(hdl_radio_rx,
1609 &vivid_radio_rx_ctrl_ops,
1610 V4L2_CID_RDS_RX_MUSIC_SPEECH, 0, 1, 1, 1);
1612 if (dev->has_radio_tx) {
1613 v4l2_ctrl_new_custom(hdl_radio_tx,
1614 &vivid_ctrl_radio_tx_rds_blockio, NULL);
1615 dev->radio_tx_rds_pi = v4l2_ctrl_new_std(hdl_radio_tx,
1616 &vivid_radio_tx_ctrl_ops,
1617 V4L2_CID_RDS_TX_PI, 0, 0xffff, 1, 0x8088);
1618 dev->radio_tx_rds_pty = v4l2_ctrl_new_std(hdl_radio_tx,
1619 &vivid_radio_tx_ctrl_ops,
1620 V4L2_CID_RDS_TX_PTY, 0, 31, 1, 3);
1621 dev->radio_tx_rds_psname = v4l2_ctrl_new_std(hdl_radio_tx,
1622 &vivid_radio_tx_ctrl_ops,
1623 V4L2_CID_RDS_TX_PS_NAME, 0, 8, 8, 0);
1624 if (dev->radio_tx_rds_psname)
1625 v4l2_ctrl_s_ctrl_string(dev->radio_tx_rds_psname, "VIVID-TX");
1626 dev->radio_tx_rds_radiotext = v4l2_ctrl_new_std(hdl_radio_tx,
1627 &vivid_radio_tx_ctrl_ops,
1628 V4L2_CID_RDS_TX_RADIO_TEXT, 0, 64 * 2, 64, 0);
1629 if (dev->radio_tx_rds_radiotext)
1630 v4l2_ctrl_s_ctrl_string(dev->radio_tx_rds_radiotext,
1631 "This is a VIVID default Radio Text template text, change at will");
1632 dev->radio_tx_rds_mono_stereo = v4l2_ctrl_new_std(hdl_radio_tx,
1633 &vivid_radio_tx_ctrl_ops,
1634 V4L2_CID_RDS_TX_MONO_STEREO, 0, 1, 1, 1);
1635 dev->radio_tx_rds_art_head = v4l2_ctrl_new_std(hdl_radio_tx,
1636 &vivid_radio_tx_ctrl_ops,
1637 V4L2_CID_RDS_TX_ARTIFICIAL_HEAD, 0, 1, 1, 0);
1638 dev->radio_tx_rds_compressed = v4l2_ctrl_new_std(hdl_radio_tx,
1639 &vivid_radio_tx_ctrl_ops,
1640 V4L2_CID_RDS_TX_COMPRESSED, 0, 1, 1, 0);
1641 dev->radio_tx_rds_dyn_pty = v4l2_ctrl_new_std(hdl_radio_tx,
1642 &vivid_radio_tx_ctrl_ops,
1643 V4L2_CID_RDS_TX_DYNAMIC_PTY, 0, 1, 1, 0);
1644 dev->radio_tx_rds_ta = v4l2_ctrl_new_std(hdl_radio_tx,
1645 &vivid_radio_tx_ctrl_ops,
1646 V4L2_CID_RDS_TX_TRAFFIC_ANNOUNCEMENT, 0, 1, 1, 0);
1647 dev->radio_tx_rds_tp = v4l2_ctrl_new_std(hdl_radio_tx,
1648 &vivid_radio_tx_ctrl_ops,
1649 V4L2_CID_RDS_TX_TRAFFIC_PROGRAM, 0, 1, 1, 1);
1650 dev->radio_tx_rds_ms = v4l2_ctrl_new_std(hdl_radio_tx,
1651 &vivid_radio_tx_ctrl_ops,
1652 V4L2_CID_RDS_TX_MUSIC_SPEECH, 0, 1, 1, 1);
1654 if (dev->has_sdr_cap) {
1655 v4l2_ctrl_new_custom(hdl_sdr_cap,
1656 &vivid_ctrl_sdr_cap_fm_deviation, NULL);
1658 if (hdl_user_gen->error)
1659 return hdl_user_gen->error;
1660 if (hdl_user_vid->error)
1661 return hdl_user_vid->error;
1662 if (hdl_user_aud->error)
1663 return hdl_user_aud->error;
1664 if (hdl_streaming->error)
1665 return hdl_streaming->error;
1666 if (hdl_sdr_cap->error)
1667 return hdl_sdr_cap->error;
1668 if (hdl_loop_cap->error)
1669 return hdl_loop_cap->error;
1671 if (dev->autogain)
1672 v4l2_ctrl_auto_cluster(2, &dev->autogain, 0, true);
1674 if (dev->has_vid_cap) {
1675 v4l2_ctrl_add_handler(hdl_vid_cap, hdl_user_gen, NULL);
1676 v4l2_ctrl_add_handler(hdl_vid_cap, hdl_user_vid, NULL);
1677 v4l2_ctrl_add_handler(hdl_vid_cap, hdl_user_aud, NULL);
1678 v4l2_ctrl_add_handler(hdl_vid_cap, hdl_streaming, NULL);
1679 v4l2_ctrl_add_handler(hdl_vid_cap, hdl_sdtv_cap, NULL);
1680 v4l2_ctrl_add_handler(hdl_vid_cap, hdl_loop_cap, NULL);
1681 v4l2_ctrl_add_handler(hdl_vid_cap, hdl_fb, NULL);
1682 if (hdl_vid_cap->error)
1683 return hdl_vid_cap->error;
1684 dev->vid_cap_dev.ctrl_handler = hdl_vid_cap;
1686 if (dev->has_vid_out) {
1687 v4l2_ctrl_add_handler(hdl_vid_out, hdl_user_gen, NULL);
1688 v4l2_ctrl_add_handler(hdl_vid_out, hdl_user_aud, NULL);
1689 v4l2_ctrl_add_handler(hdl_vid_out, hdl_streaming, NULL);
1690 v4l2_ctrl_add_handler(hdl_vid_out, hdl_fb, NULL);
1691 if (hdl_vid_out->error)
1692 return hdl_vid_out->error;
1693 dev->vid_out_dev.ctrl_handler = hdl_vid_out;
1695 if (dev->has_vbi_cap) {
1696 v4l2_ctrl_add_handler(hdl_vbi_cap, hdl_user_gen, NULL);
1697 v4l2_ctrl_add_handler(hdl_vbi_cap, hdl_streaming, NULL);
1698 v4l2_ctrl_add_handler(hdl_vbi_cap, hdl_sdtv_cap, NULL);
1699 v4l2_ctrl_add_handler(hdl_vbi_cap, hdl_loop_cap, NULL);
1700 if (hdl_vbi_cap->error)
1701 return hdl_vbi_cap->error;
1702 dev->vbi_cap_dev.ctrl_handler = hdl_vbi_cap;
1704 if (dev->has_vbi_out) {
1705 v4l2_ctrl_add_handler(hdl_vbi_out, hdl_user_gen, NULL);
1706 v4l2_ctrl_add_handler(hdl_vbi_out, hdl_streaming, NULL);
1707 if (hdl_vbi_out->error)
1708 return hdl_vbi_out->error;
1709 dev->vbi_out_dev.ctrl_handler = hdl_vbi_out;
1711 if (dev->has_radio_rx) {
1712 v4l2_ctrl_add_handler(hdl_radio_rx, hdl_user_gen, NULL);
1713 v4l2_ctrl_add_handler(hdl_radio_rx, hdl_user_aud, NULL);
1714 if (hdl_radio_rx->error)
1715 return hdl_radio_rx->error;
1716 dev->radio_rx_dev.ctrl_handler = hdl_radio_rx;
1718 if (dev->has_radio_tx) {
1719 v4l2_ctrl_add_handler(hdl_radio_tx, hdl_user_gen, NULL);
1720 v4l2_ctrl_add_handler(hdl_radio_tx, hdl_user_aud, NULL);
1721 if (hdl_radio_tx->error)
1722 return hdl_radio_tx->error;
1723 dev->radio_tx_dev.ctrl_handler = hdl_radio_tx;
1725 if (dev->has_sdr_cap) {
1726 v4l2_ctrl_add_handler(hdl_sdr_cap, hdl_user_gen, NULL);
1727 v4l2_ctrl_add_handler(hdl_sdr_cap, hdl_streaming, NULL);
1728 if (hdl_sdr_cap->error)
1729 return hdl_sdr_cap->error;
1730 dev->sdr_cap_dev.ctrl_handler = hdl_sdr_cap;
1732 return 0;
1735 void vivid_free_controls(struct vivid_dev *dev)
1737 v4l2_ctrl_handler_free(&dev->ctrl_hdl_vid_cap);
1738 v4l2_ctrl_handler_free(&dev->ctrl_hdl_vid_out);
1739 v4l2_ctrl_handler_free(&dev->ctrl_hdl_vbi_cap);
1740 v4l2_ctrl_handler_free(&dev->ctrl_hdl_vbi_out);
1741 v4l2_ctrl_handler_free(&dev->ctrl_hdl_radio_rx);
1742 v4l2_ctrl_handler_free(&dev->ctrl_hdl_radio_tx);
1743 v4l2_ctrl_handler_free(&dev->ctrl_hdl_sdr_cap);
1744 v4l2_ctrl_handler_free(&dev->ctrl_hdl_user_gen);
1745 v4l2_ctrl_handler_free(&dev->ctrl_hdl_user_vid);
1746 v4l2_ctrl_handler_free(&dev->ctrl_hdl_user_aud);
1747 v4l2_ctrl_handler_free(&dev->ctrl_hdl_streaming);
1748 v4l2_ctrl_handler_free(&dev->ctrl_hdl_sdtv_cap);
1749 v4l2_ctrl_handler_free(&dev->ctrl_hdl_loop_cap);
1750 v4l2_ctrl_handler_free(&dev->ctrl_hdl_fb);