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