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