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