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