blob: a78d676575bcae619d9ad098609180efee77dbea [file] [log] [blame]
Hans Verkuil67a51352018-02-07 09:12:45 -05001// SPDX-License-Identifier: GPL-2.0-only
Hans Verkuil73c3f482014-08-25 07:55:23 -03002/*
3 * vivid-ctrls.c - control support functions.
4 *
5 * Copyright 2014 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
Hans Verkuil73c3f482014-08-25 07:55:23 -03006 */
7
8#include <linux/errno.h>
9#include <linux/kernel.h>
10#include <linux/videodev2.h>
11#include <media/v4l2-event.h>
12#include <media/v4l2-common.h>
13
14#include "vivid-core.h"
15#include "vivid-vid-cap.h"
16#include "vivid-vid-out.h"
17#include "vivid-vid-common.h"
18#include "vivid-radio-common.h"
19#include "vivid-osd.h"
20#include "vivid-ctrls.h"
Johan Korsnes49389582019-06-18 03:37:25 -040021#include "vivid-cec.h"
Hans Verkuil73c3f482014-08-25 07:55:23 -030022
23#define VIVID_CID_CUSTOM_BASE (V4L2_CID_USER_BASE | 0xf000)
24#define VIVID_CID_BUTTON (VIVID_CID_CUSTOM_BASE + 0)
25#define VIVID_CID_BOOLEAN (VIVID_CID_CUSTOM_BASE + 1)
26#define VIVID_CID_INTEGER (VIVID_CID_CUSTOM_BASE + 2)
27#define VIVID_CID_INTEGER64 (VIVID_CID_CUSTOM_BASE + 3)
28#define VIVID_CID_MENU (VIVID_CID_CUSTOM_BASE + 4)
29#define VIVID_CID_STRING (VIVID_CID_CUSTOM_BASE + 5)
30#define VIVID_CID_BITMASK (VIVID_CID_CUSTOM_BASE + 6)
31#define VIVID_CID_INTMENU (VIVID_CID_CUSTOM_BASE + 7)
Hans Verkuil24c49422014-11-06 09:06:46 -030032#define VIVID_CID_U32_ARRAY (VIVID_CID_CUSTOM_BASE + 8)
33#define VIVID_CID_U16_MATRIX (VIVID_CID_CUSTOM_BASE + 9)
34#define VIVID_CID_U8_4D_ARRAY (VIVID_CID_CUSTOM_BASE + 10)
Ricardo Ribalda Delgado483b2212019-11-04 14:09:20 +010035#define VIVID_CID_AREA (VIVID_CID_CUSTOM_BASE + 11)
Hans Verkuilbb65e3d2020-08-18 16:37:09 +020036#define VIVID_CID_RO_INTEGER (VIVID_CID_CUSTOM_BASE + 12)
Hans Verkuile17d0262022-07-08 17:21:42 +010037#define VIVID_CID_U32_DYN_ARRAY (VIVID_CID_CUSTOM_BASE + 13)
Hans Verkuil73c3f482014-08-25 07:55:23 -030038
39#define VIVID_CID_VIVID_BASE (0x00f00000 | 0xf000)
40#define VIVID_CID_VIVID_CLASS (0x00f00000 | 1)
41#define VIVID_CID_TEST_PATTERN (VIVID_CID_VIVID_BASE + 0)
42#define VIVID_CID_OSD_TEXT_MODE (VIVID_CID_VIVID_BASE + 1)
43#define VIVID_CID_HOR_MOVEMENT (VIVID_CID_VIVID_BASE + 2)
44#define VIVID_CID_VERT_MOVEMENT (VIVID_CID_VIVID_BASE + 3)
45#define VIVID_CID_SHOW_BORDER (VIVID_CID_VIVID_BASE + 4)
46#define VIVID_CID_SHOW_SQUARE (VIVID_CID_VIVID_BASE + 5)
47#define VIVID_CID_INSERT_SAV (VIVID_CID_VIVID_BASE + 6)
48#define VIVID_CID_INSERT_EAV (VIVID_CID_VIVID_BASE + 7)
49#define VIVID_CID_VBI_CAP_INTERLACED (VIVID_CID_VIVID_BASE + 8)
Hans Verkuilaabcc212022-05-13 13:53:07 +010050#define VIVID_CID_INSERT_HDMI_VIDEO_GUARD_BAND (VIVID_CID_VIVID_BASE + 9)
Hans Verkuil73c3f482014-08-25 07:55:23 -030051
52#define VIVID_CID_HFLIP (VIVID_CID_VIVID_BASE + 20)
53#define VIVID_CID_VFLIP (VIVID_CID_VIVID_BASE + 21)
54#define VIVID_CID_STD_ASPECT_RATIO (VIVID_CID_VIVID_BASE + 22)
55#define VIVID_CID_DV_TIMINGS_ASPECT_RATIO (VIVID_CID_VIVID_BASE + 23)
56#define VIVID_CID_TSTAMP_SRC (VIVID_CID_VIVID_BASE + 24)
57#define VIVID_CID_COLORSPACE (VIVID_CID_VIVID_BASE + 25)
Hans Verkuilca5316d2015-04-28 09:41:37 -030058#define VIVID_CID_XFER_FUNC (VIVID_CID_VIVID_BASE + 26)
59#define VIVID_CID_YCBCR_ENC (VIVID_CID_VIVID_BASE + 27)
60#define VIVID_CID_QUANTIZATION (VIVID_CID_VIVID_BASE + 28)
61#define VIVID_CID_LIMITED_RGB_RANGE (VIVID_CID_VIVID_BASE + 29)
62#define VIVID_CID_ALPHA_MODE (VIVID_CID_VIVID_BASE + 30)
63#define VIVID_CID_HAS_CROP_CAP (VIVID_CID_VIVID_BASE + 31)
64#define VIVID_CID_HAS_COMPOSE_CAP (VIVID_CID_VIVID_BASE + 32)
65#define VIVID_CID_HAS_SCALER_CAP (VIVID_CID_VIVID_BASE + 33)
66#define VIVID_CID_HAS_CROP_OUT (VIVID_CID_VIVID_BASE + 34)
67#define VIVID_CID_HAS_COMPOSE_OUT (VIVID_CID_VIVID_BASE + 35)
68#define VIVID_CID_HAS_SCALER_OUT (VIVID_CID_VIVID_BASE + 36)
69#define VIVID_CID_LOOP_VIDEO (VIVID_CID_VIVID_BASE + 37)
70#define VIVID_CID_SEQ_WRAP (VIVID_CID_VIVID_BASE + 38)
71#define VIVID_CID_TIME_WRAP (VIVID_CID_VIVID_BASE + 39)
72#define VIVID_CID_MAX_EDID_BLOCKS (VIVID_CID_VIVID_BASE + 40)
73#define VIVID_CID_PERCENTAGE_FILL (VIVID_CID_VIVID_BASE + 41)
Prashant Laddhac79aa6a2015-09-22 11:27:30 -030074#define VIVID_CID_REDUCED_FPS (VIVID_CID_VIVID_BASE + 42)
Ricardo Ribalda Delgado429175e2016-07-18 09:16:15 -030075#define VIVID_CID_HSV_ENC (VIVID_CID_VIVID_BASE + 43)
Johan Korsnesc5334352019-06-18 03:37:20 -040076#define VIVID_CID_DISPLAY_PRESENT (VIVID_CID_VIVID_BASE + 44)
Hans Verkuil73c3f482014-08-25 07:55:23 -030077
78#define VIVID_CID_STD_SIGNAL_MODE (VIVID_CID_VIVID_BASE + 60)
79#define VIVID_CID_STANDARD (VIVID_CID_VIVID_BASE + 61)
80#define VIVID_CID_DV_TIMINGS_SIGNAL_MODE (VIVID_CID_VIVID_BASE + 62)
81#define VIVID_CID_DV_TIMINGS (VIVID_CID_VIVID_BASE + 63)
82#define VIVID_CID_PERC_DROPPED (VIVID_CID_VIVID_BASE + 64)
83#define VIVID_CID_DISCONNECT (VIVID_CID_VIVID_BASE + 65)
84#define VIVID_CID_DQBUF_ERROR (VIVID_CID_VIVID_BASE + 66)
85#define VIVID_CID_QUEUE_SETUP_ERROR (VIVID_CID_VIVID_BASE + 67)
86#define VIVID_CID_BUF_PREPARE_ERROR (VIVID_CID_VIVID_BASE + 68)
87#define VIVID_CID_START_STR_ERROR (VIVID_CID_VIVID_BASE + 69)
88#define VIVID_CID_QUEUE_ERROR (VIVID_CID_VIVID_BASE + 70)
89#define VIVID_CID_CLEAR_FB (VIVID_CID_VIVID_BASE + 71)
Hans Verkuila4b36752018-11-28 04:11:52 -050090#define VIVID_CID_REQ_VALIDATE_ERROR (VIVID_CID_VIVID_BASE + 72)
Hans Verkuil73c3f482014-08-25 07:55:23 -030091
92#define VIVID_CID_RADIO_SEEK_MODE (VIVID_CID_VIVID_BASE + 90)
93#define VIVID_CID_RADIO_SEEK_PROG_LIM (VIVID_CID_VIVID_BASE + 91)
94#define VIVID_CID_RADIO_RX_RDS_RBDS (VIVID_CID_VIVID_BASE + 92)
95#define VIVID_CID_RADIO_RX_RDS_BLOCKIO (VIVID_CID_VIVID_BASE + 93)
96
97#define VIVID_CID_RADIO_TX_RDS_BLOCKIO (VIVID_CID_VIVID_BASE + 94)
98
Antti Palosaarif335c3f2015-09-01 20:04:50 -030099#define VIVID_CID_SDR_CAP_FM_DEVIATION (VIVID_CID_VIVID_BASE + 110)
Hans Verkuil73c3f482014-08-25 07:55:23 -0300100
Vandana BNd5797cf2019-10-15 07:40:15 -0300101#define VIVID_CID_META_CAP_GENERATE_PTS (VIVID_CID_VIVID_BASE + 111)
102#define VIVID_CID_META_CAP_GENERATE_SCR (VIVID_CID_VIVID_BASE + 112)
103
Hans Verkuil73c3f482014-08-25 07:55:23 -0300104/* General User Controls */
105
Hans Verkuilb9969222020-12-01 13:44:44 +0100106static void vivid_unregister_dev(bool valid, struct video_device *vdev)
107{
108 if (!valid)
109 return;
110 clear_bit(V4L2_FL_REGISTERED, &vdev->flags);
111 v4l2_event_wake_all(vdev);
112}
113
Hans Verkuil73c3f482014-08-25 07:55:23 -0300114static int vivid_user_gen_s_ctrl(struct v4l2_ctrl *ctrl)
115{
116 struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_user_gen);
117
118 switch (ctrl->id) {
119 case VIVID_CID_DISCONNECT:
120 v4l2_info(&dev->v4l2_dev, "disconnect\n");
Hans Verkuil9e5f21d2020-12-01 13:44:40 +0100121 dev->disconnect_error = true;
Hans Verkuilb9969222020-12-01 13:44:44 +0100122 vivid_unregister_dev(dev->has_vid_cap, &dev->vid_cap_dev);
123 vivid_unregister_dev(dev->has_vid_out, &dev->vid_out_dev);
124 vivid_unregister_dev(dev->has_vbi_cap, &dev->vbi_cap_dev);
125 vivid_unregister_dev(dev->has_vbi_out, &dev->vbi_out_dev);
126 vivid_unregister_dev(dev->has_radio_rx, &dev->radio_rx_dev);
127 vivid_unregister_dev(dev->has_radio_tx, &dev->radio_tx_dev);
128 vivid_unregister_dev(dev->has_sdr_cap, &dev->sdr_cap_dev);
129 vivid_unregister_dev(dev->has_meta_cap, &dev->meta_cap_dev);
130 vivid_unregister_dev(dev->has_meta_out, &dev->meta_out_dev);
131 vivid_unregister_dev(dev->has_touch_cap, &dev->touch_cap_dev);
Hans Verkuil73c3f482014-08-25 07:55:23 -0300132 break;
Hans Verkuil73c3f482014-08-25 07:55:23 -0300133 case VIVID_CID_BUTTON:
134 dev->button_pressed = 30;
135 break;
136 }
137 return 0;
138}
139
140static const struct v4l2_ctrl_ops vivid_user_gen_ctrl_ops = {
141 .s_ctrl = vivid_user_gen_s_ctrl,
142};
143
144static const struct v4l2_ctrl_config vivid_ctrl_button = {
145 .ops = &vivid_user_gen_ctrl_ops,
146 .id = VIVID_CID_BUTTON,
147 .name = "Button",
148 .type = V4L2_CTRL_TYPE_BUTTON,
149};
150
151static const struct v4l2_ctrl_config vivid_ctrl_boolean = {
152 .ops = &vivid_user_gen_ctrl_ops,
153 .id = VIVID_CID_BOOLEAN,
154 .name = "Boolean",
155 .type = V4L2_CTRL_TYPE_BOOLEAN,
156 .min = 0,
157 .max = 1,
158 .step = 1,
159 .def = 1,
160};
161
162static const struct v4l2_ctrl_config vivid_ctrl_int32 = {
163 .ops = &vivid_user_gen_ctrl_ops,
164 .id = VIVID_CID_INTEGER,
165 .name = "Integer 32 Bits",
166 .type = V4L2_CTRL_TYPE_INTEGER,
167 .min = 0xffffffff80000000ULL,
168 .max = 0x7fffffff,
169 .step = 1,
170};
171
172static const struct v4l2_ctrl_config vivid_ctrl_int64 = {
173 .ops = &vivid_user_gen_ctrl_ops,
174 .id = VIVID_CID_INTEGER64,
175 .name = "Integer 64 Bits",
176 .type = V4L2_CTRL_TYPE_INTEGER64,
177 .min = 0x8000000000000000ULL,
178 .max = 0x7fffffffffffffffLL,
179 .step = 1,
180};
181
Hans Verkuil24c49422014-11-06 09:06:46 -0300182static const struct v4l2_ctrl_config vivid_ctrl_u32_array = {
183 .ops = &vivid_user_gen_ctrl_ops,
184 .id = VIVID_CID_U32_ARRAY,
185 .name = "U32 1 Element Array",
186 .type = V4L2_CTRL_TYPE_U32,
187 .def = 0x18,
188 .min = 0x10,
189 .max = 0x20000,
190 .step = 1,
191 .dims = { 1 },
192};
193
Hans Verkuile17d0262022-07-08 17:21:42 +0100194static const struct v4l2_ctrl_config vivid_ctrl_u32_dyn_array = {
195 .ops = &vivid_user_gen_ctrl_ops,
196 .id = VIVID_CID_U32_DYN_ARRAY,
197 .name = "U32 Dynamic Array",
198 .type = V4L2_CTRL_TYPE_U32,
199 .flags = V4L2_CTRL_FLAG_DYNAMIC_ARRAY,
200 .def = 50,
201 .min = 10,
202 .max = 90,
203 .step = 1,
204 .dims = { 100 },
205};
206
Hans Verkuil24c49422014-11-06 09:06:46 -0300207static const struct v4l2_ctrl_config vivid_ctrl_u16_matrix = {
208 .ops = &vivid_user_gen_ctrl_ops,
209 .id = VIVID_CID_U16_MATRIX,
210 .name = "U16 8x16 Matrix",
211 .type = V4L2_CTRL_TYPE_U16,
212 .def = 0x18,
213 .min = 0x10,
214 .max = 0x2000,
215 .step = 1,
216 .dims = { 8, 16 },
217};
218
219static const struct v4l2_ctrl_config vivid_ctrl_u8_4d_array = {
220 .ops = &vivid_user_gen_ctrl_ops,
221 .id = VIVID_CID_U8_4D_ARRAY,
222 .name = "U8 2x3x4x5 Array",
223 .type = V4L2_CTRL_TYPE_U8,
224 .def = 0x18,
225 .min = 0x10,
226 .max = 0x20,
227 .step = 1,
228 .dims = { 2, 3, 4, 5 },
229};
230
Hans Verkuil73c3f482014-08-25 07:55:23 -0300231static const char * const vivid_ctrl_menu_strings[] = {
232 "Menu Item 0 (Skipped)",
233 "Menu Item 1",
234 "Menu Item 2 (Skipped)",
235 "Menu Item 3",
236 "Menu Item 4",
237 "Menu Item 5 (Skipped)",
238 NULL,
239};
240
241static const struct v4l2_ctrl_config vivid_ctrl_menu = {
242 .ops = &vivid_user_gen_ctrl_ops,
243 .id = VIVID_CID_MENU,
244 .name = "Menu",
245 .type = V4L2_CTRL_TYPE_MENU,
246 .min = 1,
247 .max = 4,
248 .def = 3,
249 .menu_skip_mask = 0x04,
250 .qmenu = vivid_ctrl_menu_strings,
251};
252
253static const struct v4l2_ctrl_config vivid_ctrl_string = {
254 .ops = &vivid_user_gen_ctrl_ops,
255 .id = VIVID_CID_STRING,
256 .name = "String",
257 .type = V4L2_CTRL_TYPE_STRING,
258 .min = 2,
259 .max = 4,
260 .step = 1,
261};
262
263static const struct v4l2_ctrl_config vivid_ctrl_bitmask = {
264 .ops = &vivid_user_gen_ctrl_ops,
265 .id = VIVID_CID_BITMASK,
266 .name = "Bitmask",
267 .type = V4L2_CTRL_TYPE_BITMASK,
268 .def = 0x80002000,
269 .min = 0,
270 .max = 0x80402010,
271 .step = 0,
272};
273
274static const s64 vivid_ctrl_int_menu_values[] = {
275 1, 1, 2, 3, 5, 8, 13, 21, 42,
276};
277
278static const struct v4l2_ctrl_config vivid_ctrl_int_menu = {
279 .ops = &vivid_user_gen_ctrl_ops,
280 .id = VIVID_CID_INTMENU,
281 .name = "Integer Menu",
282 .type = V4L2_CTRL_TYPE_INTEGER_MENU,
283 .min = 1,
284 .max = 8,
285 .def = 4,
286 .menu_skip_mask = 0x02,
287 .qmenu_int = vivid_ctrl_int_menu_values,
288};
289
290static const struct v4l2_ctrl_config vivid_ctrl_disconnect = {
291 .ops = &vivid_user_gen_ctrl_ops,
292 .id = VIVID_CID_DISCONNECT,
293 .name = "Disconnect",
294 .type = V4L2_CTRL_TYPE_BUTTON,
295};
296
Ricardo Ribalda Delgado483b2212019-11-04 14:09:20 +0100297static const struct v4l2_area area = {
298 .width = 1000,
299 .height = 2000,
300};
301
302static const struct v4l2_ctrl_config vivid_ctrl_area = {
303 .ops = &vivid_user_gen_ctrl_ops,
304 .id = VIVID_CID_AREA,
305 .name = "Area",
306 .type = V4L2_CTRL_TYPE_AREA,
307 .p_def.p_const = &area,
308};
Hans Verkuil0fa2c5f2018-01-25 06:57:45 -0500309
Hans Verkuilbb65e3d2020-08-18 16:37:09 +0200310static const struct v4l2_ctrl_config vivid_ctrl_ro_int32 = {
311 .ops = &vivid_user_gen_ctrl_ops,
312 .id = VIVID_CID_RO_INTEGER,
313 .name = "Read-Only Integer 32 Bits",
314 .type = V4L2_CTRL_TYPE_INTEGER,
315 .flags = V4L2_CTRL_FLAG_READ_ONLY,
316 .min = 0,
317 .max = 255,
318 .step = 1,
319};
320
Hans Verkuil0fa2c5f2018-01-25 06:57:45 -0500321/* Framebuffer Controls */
322
323static int vivid_fb_s_ctrl(struct v4l2_ctrl *ctrl)
324{
325 struct vivid_dev *dev = container_of(ctrl->handler,
326 struct vivid_dev, ctrl_hdl_fb);
327
328 switch (ctrl->id) {
329 case VIVID_CID_CLEAR_FB:
330 vivid_clear_fb(dev);
331 break;
332 }
333 return 0;
334}
335
336static const struct v4l2_ctrl_ops vivid_fb_ctrl_ops = {
337 .s_ctrl = vivid_fb_s_ctrl,
338};
339
Hans Verkuil73c3f482014-08-25 07:55:23 -0300340static const struct v4l2_ctrl_config vivid_ctrl_clear_fb = {
Hans Verkuil0fa2c5f2018-01-25 06:57:45 -0500341 .ops = &vivid_fb_ctrl_ops,
Hans Verkuil73c3f482014-08-25 07:55:23 -0300342 .id = VIVID_CID_CLEAR_FB,
343 .name = "Clear Framebuffer",
344 .type = V4L2_CTRL_TYPE_BUTTON,
345};
346
347
348/* Video User Controls */
349
350static int vivid_user_vid_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
351{
352 struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_user_vid);
353
354 switch (ctrl->id) {
355 case V4L2_CID_AUTOGAIN:
Hans Verkuil83a72952018-06-29 05:40:41 -0400356 dev->gain->val = (jiffies_to_msecs(jiffies) / 1000) & 0xff;
Hans Verkuil73c3f482014-08-25 07:55:23 -0300357 break;
358 }
359 return 0;
360}
361
362static int vivid_user_vid_s_ctrl(struct v4l2_ctrl *ctrl)
363{
364 struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_user_vid);
365
366 switch (ctrl->id) {
367 case V4L2_CID_BRIGHTNESS:
368 dev->input_brightness[dev->input] = ctrl->val - dev->input * 128;
369 tpg_s_brightness(&dev->tpg, dev->input_brightness[dev->input]);
370 break;
371 case V4L2_CID_CONTRAST:
372 tpg_s_contrast(&dev->tpg, ctrl->val);
373 break;
374 case V4L2_CID_SATURATION:
375 tpg_s_saturation(&dev->tpg, ctrl->val);
376 break;
377 case V4L2_CID_HUE:
378 tpg_s_hue(&dev->tpg, ctrl->val);
379 break;
380 case V4L2_CID_HFLIP:
381 dev->hflip = ctrl->val;
382 tpg_s_hflip(&dev->tpg, dev->sensor_hflip ^ dev->hflip);
383 break;
384 case V4L2_CID_VFLIP:
385 dev->vflip = ctrl->val;
386 tpg_s_vflip(&dev->tpg, dev->sensor_vflip ^ dev->vflip);
387 break;
388 case V4L2_CID_ALPHA_COMPONENT:
389 tpg_s_alpha_component(&dev->tpg, ctrl->val);
390 break;
391 }
392 return 0;
393}
394
395static const struct v4l2_ctrl_ops vivid_user_vid_ctrl_ops = {
396 .g_volatile_ctrl = vivid_user_vid_g_volatile_ctrl,
397 .s_ctrl = vivid_user_vid_s_ctrl,
398};
399
400
401/* Video Capture Controls */
402
403static int vivid_vid_cap_s_ctrl(struct v4l2_ctrl *ctrl)
404{
Hans Verkuilcd8adbe2014-11-17 10:21:19 -0300405 static const u32 colorspaces[] = {
406 V4L2_COLORSPACE_SMPTE170M,
407 V4L2_COLORSPACE_REC709,
408 V4L2_COLORSPACE_SRGB,
Hans Verkuildb034012018-09-14 04:58:03 -0400409 V4L2_COLORSPACE_OPRGB,
Hans Verkuilcd8adbe2014-11-17 10:21:19 -0300410 V4L2_COLORSPACE_BT2020,
Hans Verkuil1d780532015-09-13 13:41:32 -0300411 V4L2_COLORSPACE_DCI_P3,
Hans Verkuilcd8adbe2014-11-17 10:21:19 -0300412 V4L2_COLORSPACE_SMPTE240M,
413 V4L2_COLORSPACE_470_SYSTEM_M,
414 V4L2_COLORSPACE_470_SYSTEM_BG,
415 };
Hans Verkuil73c3f482014-08-25 07:55:23 -0300416 struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_vid_cap);
Johan Korsnes8a99e9f2019-06-18 03:37:23 -0400417 unsigned int i, j;
Hans Verkuil73c3f482014-08-25 07:55:23 -0300418
419 switch (ctrl->id) {
420 case VIVID_CID_TEST_PATTERN:
421 vivid_update_quality(dev);
422 tpg_s_pattern(&dev->tpg, ctrl->val);
423 break;
424 case VIVID_CID_COLORSPACE:
Hans Verkuilcd8adbe2014-11-17 10:21:19 -0300425 tpg_s_colorspace(&dev->tpg, colorspaces[ctrl->val]);
Hans Verkuil73c3f482014-08-25 07:55:23 -0300426 vivid_send_source_change(dev, TV);
427 vivid_send_source_change(dev, SVID);
428 vivid_send_source_change(dev, HDMI);
429 vivid_send_source_change(dev, WEBCAM);
430 break;
Hans Verkuilca5316d2015-04-28 09:41:37 -0300431 case VIVID_CID_XFER_FUNC:
432 tpg_s_xfer_func(&dev->tpg, ctrl->val);
433 vivid_send_source_change(dev, TV);
434 vivid_send_source_change(dev, SVID);
435 vivid_send_source_change(dev, HDMI);
436 vivid_send_source_change(dev, WEBCAM);
437 break;
Hans Verkuil3e8a78d2014-11-17 10:26:01 -0300438 case VIVID_CID_YCBCR_ENC:
439 tpg_s_ycbcr_enc(&dev->tpg, ctrl->val);
440 vivid_send_source_change(dev, TV);
441 vivid_send_source_change(dev, SVID);
442 vivid_send_source_change(dev, HDMI);
443 vivid_send_source_change(dev, WEBCAM);
444 break;
Ricardo Ribalda Delgado429175e2016-07-18 09:16:15 -0300445 case VIVID_CID_HSV_ENC:
446 tpg_s_hsv_enc(&dev->tpg, ctrl->val ? V4L2_HSV_ENC_256 :
447 V4L2_HSV_ENC_180);
448 vivid_send_source_change(dev, TV);
449 vivid_send_source_change(dev, SVID);
450 vivid_send_source_change(dev, HDMI);
451 vivid_send_source_change(dev, WEBCAM);
452 break;
Hans Verkuil3e8a78d2014-11-17 10:26:01 -0300453 case VIVID_CID_QUANTIZATION:
454 tpg_s_quantization(&dev->tpg, ctrl->val);
455 vivid_send_source_change(dev, TV);
456 vivid_send_source_change(dev, SVID);
457 vivid_send_source_change(dev, HDMI);
458 vivid_send_source_change(dev, WEBCAM);
459 break;
Hans Verkuil73c3f482014-08-25 07:55:23 -0300460 case V4L2_CID_DV_RX_RGB_RANGE:
461 if (!vivid_is_hdmi_cap(dev))
462 break;
463 tpg_s_rgb_range(&dev->tpg, ctrl->val);
464 break;
465 case VIVID_CID_LIMITED_RGB_RANGE:
466 tpg_s_real_rgb_range(&dev->tpg, ctrl->val ?
467 V4L2_DV_RGB_RANGE_LIMITED : V4L2_DV_RGB_RANGE_FULL);
468 break;
469 case VIVID_CID_ALPHA_MODE:
470 tpg_s_alpha_mode(&dev->tpg, ctrl->val);
471 break;
472 case VIVID_CID_HOR_MOVEMENT:
473 tpg_s_mv_hor_mode(&dev->tpg, ctrl->val);
474 break;
475 case VIVID_CID_VERT_MOVEMENT:
476 tpg_s_mv_vert_mode(&dev->tpg, ctrl->val);
477 break;
478 case VIVID_CID_OSD_TEXT_MODE:
479 dev->osd_mode = ctrl->val;
480 break;
481 case VIVID_CID_PERCENTAGE_FILL:
482 tpg_s_perc_fill(&dev->tpg, ctrl->val);
483 for (i = 0; i < VIDEO_MAX_FRAME; i++)
484 dev->must_blank[i] = ctrl->val < 100;
485 break;
486 case VIVID_CID_INSERT_SAV:
487 tpg_s_insert_sav(&dev->tpg, ctrl->val);
488 break;
489 case VIVID_CID_INSERT_EAV:
490 tpg_s_insert_eav(&dev->tpg, ctrl->val);
491 break;
Hans Verkuilaabcc212022-05-13 13:53:07 +0100492 case VIVID_CID_INSERT_HDMI_VIDEO_GUARD_BAND:
493 tpg_s_insert_hdmi_video_guard_band(&dev->tpg, ctrl->val);
494 break;
Hans Verkuil73c3f482014-08-25 07:55:23 -0300495 case VIVID_CID_HFLIP:
496 dev->sensor_hflip = ctrl->val;
497 tpg_s_hflip(&dev->tpg, dev->sensor_hflip ^ dev->hflip);
498 break;
499 case VIVID_CID_VFLIP:
500 dev->sensor_vflip = ctrl->val;
501 tpg_s_vflip(&dev->tpg, dev->sensor_vflip ^ dev->vflip);
502 break;
Prashant Laddhac79aa6a2015-09-22 11:27:30 -0300503 case VIVID_CID_REDUCED_FPS:
504 dev->reduced_fps = ctrl->val;
505 vivid_update_format_cap(dev, true);
506 break;
Hans Verkuil73c3f482014-08-25 07:55:23 -0300507 case VIVID_CID_HAS_CROP_CAP:
508 dev->has_crop_cap = ctrl->val;
509 vivid_update_format_cap(dev, true);
510 break;
511 case VIVID_CID_HAS_COMPOSE_CAP:
512 dev->has_compose_cap = ctrl->val;
513 vivid_update_format_cap(dev, true);
514 break;
515 case VIVID_CID_HAS_SCALER_CAP:
516 dev->has_scaler_cap = ctrl->val;
517 vivid_update_format_cap(dev, true);
518 break;
519 case VIVID_CID_SHOW_BORDER:
520 tpg_s_show_border(&dev->tpg, ctrl->val);
521 break;
522 case VIVID_CID_SHOW_SQUARE:
523 tpg_s_show_square(&dev->tpg, ctrl->val);
524 break;
525 case VIVID_CID_STD_ASPECT_RATIO:
Johan Korsnes6c396c22019-06-18 03:37:19 -0400526 dev->std_aspect_ratio[dev->input] = ctrl->val;
Hans Verkuil73c3f482014-08-25 07:55:23 -0300527 tpg_s_video_aspect(&dev->tpg, vivid_get_video_aspect(dev));
528 break;
529 case VIVID_CID_DV_TIMINGS_SIGNAL_MODE:
Johan Korsnes448e1152019-06-18 03:37:18 -0400530 dev->dv_timings_signal_mode[dev->input] =
531 dev->ctrl_dv_timings_signal_mode->val;
532 dev->query_dv_timings[dev->input] = dev->ctrl_dv_timings->val;
533
Johan Korsnes8a99e9f2019-06-18 03:37:23 -0400534 dev->power_present = 0;
535 for (i = 0, j = 0;
536 i < ARRAY_SIZE(dev->dv_timings_signal_mode);
537 i++)
538 if (dev->input_type[i] == HDMI) {
539 if (dev->dv_timings_signal_mode[i] != NO_SIGNAL)
540 dev->power_present |= (1 << j);
541 j++;
542 }
543 __v4l2_ctrl_s_ctrl(dev->ctrl_rx_power_present,
544 dev->power_present);
545
Hans Verkuil73c3f482014-08-25 07:55:23 -0300546 v4l2_ctrl_activate(dev->ctrl_dv_timings,
Johan Korsnes448e1152019-06-18 03:37:18 -0400547 dev->dv_timings_signal_mode[dev->input] ==
548 SELECTED_DV_TIMINGS);
549
Hans Verkuil73c3f482014-08-25 07:55:23 -0300550 vivid_update_quality(dev);
551 vivid_send_source_change(dev, HDMI);
552 break;
553 case VIVID_CID_DV_TIMINGS_ASPECT_RATIO:
Johan Korsnes448e1152019-06-18 03:37:18 -0400554 dev->dv_timings_aspect_ratio[dev->input] = ctrl->val;
Hans Verkuil73c3f482014-08-25 07:55:23 -0300555 tpg_s_video_aspect(&dev->tpg, vivid_get_video_aspect(dev));
556 break;
557 case VIVID_CID_TSTAMP_SRC:
558 dev->tstamp_src_is_soe = ctrl->val;
559 dev->vb_vid_cap_q.timestamp_flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
560 if (dev->tstamp_src_is_soe)
561 dev->vb_vid_cap_q.timestamp_flags |= V4L2_BUF_FLAG_TSTAMP_SRC_SOE;
562 break;
563 case VIVID_CID_MAX_EDID_BLOCKS:
564 dev->edid_max_blocks = ctrl->val;
565 if (dev->edid_blocks > dev->edid_max_blocks)
566 dev->edid_blocks = dev->edid_max_blocks;
567 break;
568 }
569 return 0;
570}
571
572static const struct v4l2_ctrl_ops vivid_vid_cap_ctrl_ops = {
573 .s_ctrl = vivid_vid_cap_s_ctrl,
574};
575
576static const char * const vivid_ctrl_hor_movement_strings[] = {
577 "Move Left Fast",
578 "Move Left",
579 "Move Left Slow",
580 "No Movement",
581 "Move Right Slow",
582 "Move Right",
583 "Move Right Fast",
584 NULL,
585};
586
587static const struct v4l2_ctrl_config vivid_ctrl_hor_movement = {
588 .ops = &vivid_vid_cap_ctrl_ops,
589 .id = VIVID_CID_HOR_MOVEMENT,
590 .name = "Horizontal Movement",
591 .type = V4L2_CTRL_TYPE_MENU,
592 .max = TPG_MOVE_POS_FAST,
593 .def = TPG_MOVE_NONE,
594 .qmenu = vivid_ctrl_hor_movement_strings,
595};
596
597static const char * const vivid_ctrl_vert_movement_strings[] = {
598 "Move Up Fast",
599 "Move Up",
600 "Move Up Slow",
601 "No Movement",
602 "Move Down Slow",
603 "Move Down",
604 "Move Down Fast",
605 NULL,
606};
607
608static const struct v4l2_ctrl_config vivid_ctrl_vert_movement = {
609 .ops = &vivid_vid_cap_ctrl_ops,
610 .id = VIVID_CID_VERT_MOVEMENT,
611 .name = "Vertical Movement",
612 .type = V4L2_CTRL_TYPE_MENU,
613 .max = TPG_MOVE_POS_FAST,
614 .def = TPG_MOVE_NONE,
615 .qmenu = vivid_ctrl_vert_movement_strings,
616};
617
618static const struct v4l2_ctrl_config vivid_ctrl_show_border = {
619 .ops = &vivid_vid_cap_ctrl_ops,
620 .id = VIVID_CID_SHOW_BORDER,
621 .name = "Show Border",
622 .type = V4L2_CTRL_TYPE_BOOLEAN,
623 .max = 1,
624 .step = 1,
625};
626
627static const struct v4l2_ctrl_config vivid_ctrl_show_square = {
628 .ops = &vivid_vid_cap_ctrl_ops,
629 .id = VIVID_CID_SHOW_SQUARE,
630 .name = "Show Square",
631 .type = V4L2_CTRL_TYPE_BOOLEAN,
632 .max = 1,
633 .step = 1,
634};
635
636static const char * const vivid_ctrl_osd_mode_strings[] = {
637 "All",
638 "Counters Only",
639 "None",
640 NULL,
641};
642
643static const struct v4l2_ctrl_config vivid_ctrl_osd_mode = {
644 .ops = &vivid_vid_cap_ctrl_ops,
645 .id = VIVID_CID_OSD_TEXT_MODE,
646 .name = "OSD Text Mode",
647 .type = V4L2_CTRL_TYPE_MENU,
Hans Verkuilff144722015-09-13 13:41:27 -0300648 .max = ARRAY_SIZE(vivid_ctrl_osd_mode_strings) - 2,
Hans Verkuil73c3f482014-08-25 07:55:23 -0300649 .qmenu = vivid_ctrl_osd_mode_strings,
650};
651
652static const struct v4l2_ctrl_config vivid_ctrl_perc_fill = {
653 .ops = &vivid_vid_cap_ctrl_ops,
654 .id = VIVID_CID_PERCENTAGE_FILL,
655 .name = "Fill Percentage of Frame",
656 .type = V4L2_CTRL_TYPE_INTEGER,
657 .min = 0,
658 .max = 100,
659 .def = 100,
660 .step = 1,
661};
662
663static const struct v4l2_ctrl_config vivid_ctrl_insert_sav = {
664 .ops = &vivid_vid_cap_ctrl_ops,
665 .id = VIVID_CID_INSERT_SAV,
666 .name = "Insert SAV Code in Image",
667 .type = V4L2_CTRL_TYPE_BOOLEAN,
668 .max = 1,
669 .step = 1,
670};
671
672static const struct v4l2_ctrl_config vivid_ctrl_insert_eav = {
673 .ops = &vivid_vid_cap_ctrl_ops,
674 .id = VIVID_CID_INSERT_EAV,
675 .name = "Insert EAV Code in Image",
676 .type = V4L2_CTRL_TYPE_BOOLEAN,
677 .max = 1,
678 .step = 1,
679};
680
Hans Verkuilaabcc212022-05-13 13:53:07 +0100681static const struct v4l2_ctrl_config vivid_ctrl_insert_hdmi_video_guard_band = {
682 .ops = &vivid_vid_cap_ctrl_ops,
683 .id = VIVID_CID_INSERT_HDMI_VIDEO_GUARD_BAND,
684 .name = "Insert Video Guard Band",
685 .type = V4L2_CTRL_TYPE_BOOLEAN,
686 .max = 1,
687 .step = 1,
688};
689
Hans Verkuil73c3f482014-08-25 07:55:23 -0300690static const struct v4l2_ctrl_config vivid_ctrl_hflip = {
691 .ops = &vivid_vid_cap_ctrl_ops,
692 .id = VIVID_CID_HFLIP,
693 .name = "Sensor Flipped Horizontally",
694 .type = V4L2_CTRL_TYPE_BOOLEAN,
695 .max = 1,
696 .step = 1,
697};
698
699static const struct v4l2_ctrl_config vivid_ctrl_vflip = {
700 .ops = &vivid_vid_cap_ctrl_ops,
701 .id = VIVID_CID_VFLIP,
702 .name = "Sensor Flipped Vertically",
703 .type = V4L2_CTRL_TYPE_BOOLEAN,
704 .max = 1,
705 .step = 1,
706};
707
Prashant Laddhac79aa6a2015-09-22 11:27:30 -0300708static const struct v4l2_ctrl_config vivid_ctrl_reduced_fps = {
709 .ops = &vivid_vid_cap_ctrl_ops,
710 .id = VIVID_CID_REDUCED_FPS,
711 .name = "Reduced Framerate",
712 .type = V4L2_CTRL_TYPE_BOOLEAN,
713 .max = 1,
714 .step = 1,
715};
716
Hans Verkuil73c3f482014-08-25 07:55:23 -0300717static const struct v4l2_ctrl_config vivid_ctrl_has_crop_cap = {
718 .ops = &vivid_vid_cap_ctrl_ops,
719 .id = VIVID_CID_HAS_CROP_CAP,
720 .name = "Enable Capture Cropping",
721 .type = V4L2_CTRL_TYPE_BOOLEAN,
722 .max = 1,
723 .def = 1,
724 .step = 1,
725};
726
727static const struct v4l2_ctrl_config vivid_ctrl_has_compose_cap = {
728 .ops = &vivid_vid_cap_ctrl_ops,
729 .id = VIVID_CID_HAS_COMPOSE_CAP,
730 .name = "Enable Capture Composing",
731 .type = V4L2_CTRL_TYPE_BOOLEAN,
732 .max = 1,
733 .def = 1,
734 .step = 1,
735};
736
737static const struct v4l2_ctrl_config vivid_ctrl_has_scaler_cap = {
738 .ops = &vivid_vid_cap_ctrl_ops,
739 .id = VIVID_CID_HAS_SCALER_CAP,
740 .name = "Enable Capture Scaler",
741 .type = V4L2_CTRL_TYPE_BOOLEAN,
742 .max = 1,
743 .def = 1,
744 .step = 1,
745};
746
747static const char * const vivid_ctrl_tstamp_src_strings[] = {
748 "End of Frame",
749 "Start of Exposure",
750 NULL,
751};
752
753static const struct v4l2_ctrl_config vivid_ctrl_tstamp_src = {
754 .ops = &vivid_vid_cap_ctrl_ops,
755 .id = VIVID_CID_TSTAMP_SRC,
756 .name = "Timestamp Source",
757 .type = V4L2_CTRL_TYPE_MENU,
Hans Verkuilff144722015-09-13 13:41:27 -0300758 .max = ARRAY_SIZE(vivid_ctrl_tstamp_src_strings) - 2,
Hans Verkuil73c3f482014-08-25 07:55:23 -0300759 .qmenu = vivid_ctrl_tstamp_src_strings,
760};
761
762static const struct v4l2_ctrl_config vivid_ctrl_std_aspect_ratio = {
763 .ops = &vivid_vid_cap_ctrl_ops,
764 .id = VIVID_CID_STD_ASPECT_RATIO,
765 .name = "Standard Aspect Ratio",
766 .type = V4L2_CTRL_TYPE_MENU,
767 .min = 1,
768 .max = 4,
769 .def = 1,
770 .qmenu = tpg_aspect_strings,
771};
772
773static const char * const vivid_ctrl_dv_timings_signal_mode_strings[] = {
774 "Current DV Timings",
775 "No Signal",
776 "No Lock",
777 "Out of Range",
778 "Selected DV Timings",
779 "Cycle Through All DV Timings",
780 "Custom DV Timings",
781 NULL,
782};
783
784static const struct v4l2_ctrl_config vivid_ctrl_dv_timings_signal_mode = {
785 .ops = &vivid_vid_cap_ctrl_ops,
786 .id = VIVID_CID_DV_TIMINGS_SIGNAL_MODE,
787 .name = "DV Timings Signal Mode",
788 .type = V4L2_CTRL_TYPE_MENU,
789 .max = 5,
790 .qmenu = vivid_ctrl_dv_timings_signal_mode_strings,
791};
792
793static const struct v4l2_ctrl_config vivid_ctrl_dv_timings_aspect_ratio = {
794 .ops = &vivid_vid_cap_ctrl_ops,
795 .id = VIVID_CID_DV_TIMINGS_ASPECT_RATIO,
796 .name = "DV Timings Aspect Ratio",
797 .type = V4L2_CTRL_TYPE_MENU,
798 .max = 3,
799 .qmenu = tpg_aspect_strings,
800};
801
802static const struct v4l2_ctrl_config vivid_ctrl_max_edid_blocks = {
803 .ops = &vivid_vid_cap_ctrl_ops,
804 .id = VIVID_CID_MAX_EDID_BLOCKS,
805 .name = "Maximum EDID Blocks",
806 .type = V4L2_CTRL_TYPE_INTEGER,
807 .min = 1,
808 .max = 256,
809 .def = 2,
810 .step = 1,
811};
812
813static const char * const vivid_ctrl_colorspace_strings[] = {
Hans Verkuil73c3f482014-08-25 07:55:23 -0300814 "SMPTE 170M",
Hans Verkuileb79dbf2015-01-29 08:22:37 -0300815 "Rec. 709",
Hans Verkuilcd8adbe2014-11-17 10:21:19 -0300816 "sRGB",
Hans Verkuildb034012018-09-14 04:58:03 -0400817 "opRGB",
Hans Verkuilcd8adbe2014-11-17 10:21:19 -0300818 "BT.2020",
Hans Verkuil1d780532015-09-13 13:41:32 -0300819 "DCI-P3",
Hans Verkuilcd8adbe2014-11-17 10:21:19 -0300820 "SMPTE 240M",
Hans Verkuil73c3f482014-08-25 07:55:23 -0300821 "470 System M",
822 "470 System BG",
Hans Verkuil73c3f482014-08-25 07:55:23 -0300823 NULL,
824};
825
826static const struct v4l2_ctrl_config vivid_ctrl_colorspace = {
827 .ops = &vivid_vid_cap_ctrl_ops,
828 .id = VIVID_CID_COLORSPACE,
829 .name = "Colorspace",
830 .type = V4L2_CTRL_TYPE_MENU,
Hans Verkuilff144722015-09-13 13:41:27 -0300831 .max = ARRAY_SIZE(vivid_ctrl_colorspace_strings) - 2,
Hans Verkuilcd8adbe2014-11-17 10:21:19 -0300832 .def = 2,
Hans Verkuil73c3f482014-08-25 07:55:23 -0300833 .qmenu = vivid_ctrl_colorspace_strings,
834};
835
Hans Verkuilca5316d2015-04-28 09:41:37 -0300836static const char * const vivid_ctrl_xfer_func_strings[] = {
837 "Default",
838 "Rec. 709",
839 "sRGB",
Hans Verkuildb034012018-09-14 04:58:03 -0400840 "opRGB",
Hans Verkuilca5316d2015-04-28 09:41:37 -0300841 "SMPTE 240M",
842 "None",
Hans Verkuil1d780532015-09-13 13:41:32 -0300843 "DCI-P3",
Hans Verkuilc732e642015-09-13 16:15:20 -0300844 "SMPTE 2084",
Hans Verkuilca5316d2015-04-28 09:41:37 -0300845 NULL,
846};
847
848static const struct v4l2_ctrl_config vivid_ctrl_xfer_func = {
849 .ops = &vivid_vid_cap_ctrl_ops,
850 .id = VIVID_CID_XFER_FUNC,
851 .name = "Transfer Function",
852 .type = V4L2_CTRL_TYPE_MENU,
Hans Verkuilff144722015-09-13 13:41:27 -0300853 .max = ARRAY_SIZE(vivid_ctrl_xfer_func_strings) - 2,
Hans Verkuilca5316d2015-04-28 09:41:37 -0300854 .qmenu = vivid_ctrl_xfer_func_strings,
855};
856
Hans Verkuil3e8a78d2014-11-17 10:26:01 -0300857static const char * const vivid_ctrl_ycbcr_enc_strings[] = {
858 "Default",
859 "ITU-R 601",
860 "Rec. 709",
861 "xvYCC 601",
862 "xvYCC 709",
Hans Verkuild0a3a272016-08-04 05:57:45 -0300863 "",
Hans Verkuileb79dbf2015-01-29 08:22:37 -0300864 "BT.2020",
Hans Verkuil3e8a78d2014-11-17 10:26:01 -0300865 "BT.2020 Constant Luminance",
866 "SMPTE 240M",
867 NULL,
868};
869
870static const struct v4l2_ctrl_config vivid_ctrl_ycbcr_enc = {
871 .ops = &vivid_vid_cap_ctrl_ops,
872 .id = VIVID_CID_YCBCR_ENC,
873 .name = "Y'CbCr Encoding",
874 .type = V4L2_CTRL_TYPE_MENU,
Hans Verkuild0a3a272016-08-04 05:57:45 -0300875 .menu_skip_mask = 1 << 5,
Hans Verkuilff144722015-09-13 13:41:27 -0300876 .max = ARRAY_SIZE(vivid_ctrl_ycbcr_enc_strings) - 2,
Hans Verkuil3e8a78d2014-11-17 10:26:01 -0300877 .qmenu = vivid_ctrl_ycbcr_enc_strings,
878};
879
Ricardo Ribalda Delgado429175e2016-07-18 09:16:15 -0300880static const char * const vivid_ctrl_hsv_enc_strings[] = {
881 "Hue 0-179",
882 "Hue 0-256",
883 NULL,
884};
885
886static const struct v4l2_ctrl_config vivid_ctrl_hsv_enc = {
887 .ops = &vivid_vid_cap_ctrl_ops,
888 .id = VIVID_CID_HSV_ENC,
889 .name = "HSV Encoding",
890 .type = V4L2_CTRL_TYPE_MENU,
891 .max = ARRAY_SIZE(vivid_ctrl_hsv_enc_strings) - 2,
892 .qmenu = vivid_ctrl_hsv_enc_strings,
893};
894
Hans Verkuil3e8a78d2014-11-17 10:26:01 -0300895static const char * const vivid_ctrl_quantization_strings[] = {
896 "Default",
897 "Full Range",
898 "Limited Range",
899 NULL,
900};
901
902static const struct v4l2_ctrl_config vivid_ctrl_quantization = {
903 .ops = &vivid_vid_cap_ctrl_ops,
904 .id = VIVID_CID_QUANTIZATION,
905 .name = "Quantization",
906 .type = V4L2_CTRL_TYPE_MENU,
Hans Verkuilff144722015-09-13 13:41:27 -0300907 .max = ARRAY_SIZE(vivid_ctrl_quantization_strings) - 2,
Hans Verkuil3e8a78d2014-11-17 10:26:01 -0300908 .qmenu = vivid_ctrl_quantization_strings,
909};
910
Hans Verkuil73c3f482014-08-25 07:55:23 -0300911static const struct v4l2_ctrl_config vivid_ctrl_alpha_mode = {
912 .ops = &vivid_vid_cap_ctrl_ops,
913 .id = VIVID_CID_ALPHA_MODE,
914 .name = "Apply Alpha To Red Only",
915 .type = V4L2_CTRL_TYPE_BOOLEAN,
916 .max = 1,
917 .step = 1,
918};
919
920static const struct v4l2_ctrl_config vivid_ctrl_limited_rgb_range = {
921 .ops = &vivid_vid_cap_ctrl_ops,
922 .id = VIVID_CID_LIMITED_RGB_RANGE,
923 .name = "Limited RGB Range (16-235)",
924 .type = V4L2_CTRL_TYPE_BOOLEAN,
925 .max = 1,
926 .step = 1,
927};
928
929
Hans Verkuil63344b62015-06-01 07:15:53 -0300930/* Video Loop Control */
931
932static int vivid_loop_cap_s_ctrl(struct v4l2_ctrl *ctrl)
933{
934 struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_loop_cap);
935
936 switch (ctrl->id) {
937 case VIVID_CID_LOOP_VIDEO:
938 dev->loop_video = ctrl->val;
939 vivid_update_quality(dev);
940 vivid_send_source_change(dev, SVID);
941 vivid_send_source_change(dev, HDMI);
942 break;
943 }
944 return 0;
945}
946
947static const struct v4l2_ctrl_ops vivid_loop_cap_ctrl_ops = {
948 .s_ctrl = vivid_loop_cap_s_ctrl,
949};
950
951static const struct v4l2_ctrl_config vivid_ctrl_loop_video = {
952 .ops = &vivid_loop_cap_ctrl_ops,
953 .id = VIVID_CID_LOOP_VIDEO,
954 .name = "Loop Video",
955 .type = V4L2_CTRL_TYPE_BOOLEAN,
956 .max = 1,
957 .step = 1,
958};
959
960
Hans Verkuil73c3f482014-08-25 07:55:23 -0300961/* VBI Capture Control */
962
963static int vivid_vbi_cap_s_ctrl(struct v4l2_ctrl *ctrl)
964{
965 struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_vbi_cap);
966
967 switch (ctrl->id) {
968 case VIVID_CID_VBI_CAP_INTERLACED:
969 dev->vbi_cap_interlaced = ctrl->val;
970 break;
971 }
972 return 0;
973}
974
975static const struct v4l2_ctrl_ops vivid_vbi_cap_ctrl_ops = {
976 .s_ctrl = vivid_vbi_cap_s_ctrl,
977};
978
979static const struct v4l2_ctrl_config vivid_ctrl_vbi_cap_interlaced = {
980 .ops = &vivid_vbi_cap_ctrl_ops,
981 .id = VIVID_CID_VBI_CAP_INTERLACED,
982 .name = "Interlaced VBI Format",
983 .type = V4L2_CTRL_TYPE_BOOLEAN,
984 .max = 1,
985 .step = 1,
986};
987
988
989/* Video Output Controls */
990
991static int vivid_vid_out_s_ctrl(struct v4l2_ctrl *ctrl)
992{
993 struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_vid_out);
994 struct v4l2_bt_timings *bt = &dev->dv_timings_out.bt;
Johan Korsnes79a792d2019-06-18 03:37:22 -0400995 u32 display_present = 0;
Johan Korsnes49389582019-06-18 03:37:25 -0400996 unsigned int i, j, bus_idx;
Hans Verkuil73c3f482014-08-25 07:55:23 -0300997
998 switch (ctrl->id) {
999 case VIVID_CID_HAS_CROP_OUT:
1000 dev->has_crop_out = ctrl->val;
1001 vivid_update_format_out(dev);
1002 break;
1003 case VIVID_CID_HAS_COMPOSE_OUT:
1004 dev->has_compose_out = ctrl->val;
1005 vivid_update_format_out(dev);
1006 break;
1007 case VIVID_CID_HAS_SCALER_OUT:
1008 dev->has_scaler_out = ctrl->val;
1009 vivid_update_format_out(dev);
1010 break;
1011 case V4L2_CID_DV_TX_MODE:
1012 dev->dvi_d_out = ctrl->val == V4L2_DV_TX_MODE_DVI_D;
1013 if (!vivid_is_hdmi_out(dev))
1014 break;
Hans Verkuil4a203342015-03-20 14:05:06 -03001015 if (!dev->dvi_d_out && (bt->flags & V4L2_DV_FL_IS_CE_VIDEO)) {
Hans Verkuil73c3f482014-08-25 07:55:23 -03001016 if (bt->width == 720 && bt->height <= 576)
1017 dev->colorspace_out = V4L2_COLORSPACE_SMPTE170M;
1018 else
1019 dev->colorspace_out = V4L2_COLORSPACE_REC709;
Hans Verkuil3e8a78d2014-11-17 10:26:01 -03001020 dev->quantization_out = V4L2_QUANTIZATION_DEFAULT;
Hans Verkuil73c3f482014-08-25 07:55:23 -03001021 } else {
1022 dev->colorspace_out = V4L2_COLORSPACE_SRGB;
Hans Verkuil3e8a78d2014-11-17 10:26:01 -03001023 dev->quantization_out = dev->dvi_d_out ?
1024 V4L2_QUANTIZATION_LIM_RANGE :
1025 V4L2_QUANTIZATION_DEFAULT;
Hans Verkuil73c3f482014-08-25 07:55:23 -03001026 }
1027 if (dev->loop_video)
1028 vivid_send_source_change(dev, HDMI);
1029 break;
Johan Korsnesc5334352019-06-18 03:37:20 -04001030 case VIVID_CID_DISPLAY_PRESENT:
1031 if (dev->output_type[dev->output] != HDMI)
1032 break;
1033
1034 dev->display_present[dev->output] = ctrl->val;
Johan Korsnes79a792d2019-06-18 03:37:22 -04001035 for (i = 0, j = 0; i < dev->num_outputs; i++)
1036 if (dev->output_type[i] == HDMI)
1037 display_present |=
1038 dev->display_present[i] << j++;
1039
Johan Korsnes79a792d2019-06-18 03:37:22 -04001040 __v4l2_ctrl_s_ctrl(dev->ctrl_tx_rxsense, display_present);
Johan Korsnes49389582019-06-18 03:37:25 -04001041
1042 if (dev->edid_blocks) {
1043 __v4l2_ctrl_s_ctrl(dev->ctrl_tx_edid_present,
1044 display_present);
1045 __v4l2_ctrl_s_ctrl(dev->ctrl_tx_hotplug,
1046 display_present);
1047 }
1048
1049 bus_idx = dev->cec_output2bus_map[dev->output];
1050 if (!dev->cec_tx_adap[bus_idx])
1051 break;
1052
1053 if (ctrl->val && dev->edid_blocks)
1054 cec_s_phys_addr(dev->cec_tx_adap[bus_idx],
1055 dev->cec_tx_adap[bus_idx]->phys_addr,
1056 false);
1057 else
1058 cec_phys_addr_invalidate(dev->cec_tx_adap[bus_idx]);
1059
Johan Korsnesc5334352019-06-18 03:37:20 -04001060 break;
Hans Verkuil73c3f482014-08-25 07:55:23 -03001061 }
1062 return 0;
1063}
1064
1065static const struct v4l2_ctrl_ops vivid_vid_out_ctrl_ops = {
1066 .s_ctrl = vivid_vid_out_s_ctrl,
1067};
1068
1069static const struct v4l2_ctrl_config vivid_ctrl_has_crop_out = {
1070 .ops = &vivid_vid_out_ctrl_ops,
1071 .id = VIVID_CID_HAS_CROP_OUT,
1072 .name = "Enable Output Cropping",
1073 .type = V4L2_CTRL_TYPE_BOOLEAN,
1074 .max = 1,
1075 .def = 1,
1076 .step = 1,
1077};
1078
1079static const struct v4l2_ctrl_config vivid_ctrl_has_compose_out = {
1080 .ops = &vivid_vid_out_ctrl_ops,
1081 .id = VIVID_CID_HAS_COMPOSE_OUT,
1082 .name = "Enable Output Composing",
1083 .type = V4L2_CTRL_TYPE_BOOLEAN,
1084 .max = 1,
1085 .def = 1,
1086 .step = 1,
1087};
1088
1089static const struct v4l2_ctrl_config vivid_ctrl_has_scaler_out = {
1090 .ops = &vivid_vid_out_ctrl_ops,
1091 .id = VIVID_CID_HAS_SCALER_OUT,
1092 .name = "Enable Output Scaler",
1093 .type = V4L2_CTRL_TYPE_BOOLEAN,
1094 .max = 1,
1095 .def = 1,
1096 .step = 1,
1097};
1098
Johan Korsnesc5334352019-06-18 03:37:20 -04001099static const struct v4l2_ctrl_config vivid_ctrl_display_present = {
1100 .ops = &vivid_vid_out_ctrl_ops,
1101 .id = VIVID_CID_DISPLAY_PRESENT,
1102 .name = "Display Present",
1103 .type = V4L2_CTRL_TYPE_BOOLEAN,
1104 .max = 1,
1105 .def = 1,
1106 .step = 1,
1107};
Hans Verkuil73c3f482014-08-25 07:55:23 -03001108
1109/* Streaming Controls */
1110
1111static int vivid_streaming_s_ctrl(struct v4l2_ctrl *ctrl)
1112{
1113 struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_streaming);
Hans Verkuil73c3f482014-08-25 07:55:23 -03001114
1115 switch (ctrl->id) {
1116 case VIVID_CID_DQBUF_ERROR:
1117 dev->dqbuf_error = true;
1118 break;
1119 case VIVID_CID_PERC_DROPPED:
1120 dev->perc_dropped_buffers = ctrl->val;
1121 break;
1122 case VIVID_CID_QUEUE_SETUP_ERROR:
1123 dev->queue_setup_error = true;
1124 break;
1125 case VIVID_CID_BUF_PREPARE_ERROR:
1126 dev->buf_prepare_error = true;
1127 break;
1128 case VIVID_CID_START_STR_ERROR:
1129 dev->start_streaming_error = true;
1130 break;
Hans Verkuila4b36752018-11-28 04:11:52 -05001131 case VIVID_CID_REQ_VALIDATE_ERROR:
1132 dev->req_validate_error = true;
1133 break;
Hans Verkuil73c3f482014-08-25 07:55:23 -03001134 case VIVID_CID_QUEUE_ERROR:
Prabhakar Ladeab34ea2014-11-10 13:55:53 -03001135 if (vb2_start_streaming_called(&dev->vb_vid_cap_q))
Hans Verkuil73c3f482014-08-25 07:55:23 -03001136 vb2_queue_error(&dev->vb_vid_cap_q);
Prabhakar Ladeab34ea2014-11-10 13:55:53 -03001137 if (vb2_start_streaming_called(&dev->vb_vbi_cap_q))
Hans Verkuil73c3f482014-08-25 07:55:23 -03001138 vb2_queue_error(&dev->vb_vbi_cap_q);
Prabhakar Ladeab34ea2014-11-10 13:55:53 -03001139 if (vb2_start_streaming_called(&dev->vb_vid_out_q))
Hans Verkuil73c3f482014-08-25 07:55:23 -03001140 vb2_queue_error(&dev->vb_vid_out_q);
Prabhakar Ladeab34ea2014-11-10 13:55:53 -03001141 if (vb2_start_streaming_called(&dev->vb_vbi_out_q))
Hans Verkuil73c3f482014-08-25 07:55:23 -03001142 vb2_queue_error(&dev->vb_vbi_out_q);
Prabhakar Ladeab34ea2014-11-10 13:55:53 -03001143 if (vb2_start_streaming_called(&dev->vb_sdr_cap_q))
Hans Verkuil73c3f482014-08-25 07:55:23 -03001144 vb2_queue_error(&dev->vb_sdr_cap_q);
1145 break;
1146 case VIVID_CID_SEQ_WRAP:
1147 dev->seq_wrap = ctrl->val;
1148 break;
1149 case VIVID_CID_TIME_WRAP:
1150 dev->time_wrap = ctrl->val;
Deborah Brouwer57c1d5d2021-12-08 01:40:42 +01001151 if (dev->time_wrap == 1)
1152 dev->time_wrap = (1ULL << 63) - NSEC_PER_SEC * 16ULL;
1153 else if (dev->time_wrap == 2)
1154 dev->time_wrap = ((1ULL << 31) - 16) * NSEC_PER_SEC;
Hans Verkuil73c3f482014-08-25 07:55:23 -03001155 break;
1156 }
1157 return 0;
1158}
1159
1160static const struct v4l2_ctrl_ops vivid_streaming_ctrl_ops = {
1161 .s_ctrl = vivid_streaming_s_ctrl,
1162};
1163
1164static const struct v4l2_ctrl_config vivid_ctrl_dqbuf_error = {
1165 .ops = &vivid_streaming_ctrl_ops,
1166 .id = VIVID_CID_DQBUF_ERROR,
1167 .name = "Inject V4L2_BUF_FLAG_ERROR",
1168 .type = V4L2_CTRL_TYPE_BUTTON,
1169};
1170
1171static const struct v4l2_ctrl_config vivid_ctrl_perc_dropped = {
1172 .ops = &vivid_streaming_ctrl_ops,
1173 .id = VIVID_CID_PERC_DROPPED,
1174 .name = "Percentage of Dropped Buffers",
1175 .type = V4L2_CTRL_TYPE_INTEGER,
1176 .min = 0,
1177 .max = 100,
1178 .step = 1,
1179};
1180
1181static const struct v4l2_ctrl_config vivid_ctrl_queue_setup_error = {
1182 .ops = &vivid_streaming_ctrl_ops,
1183 .id = VIVID_CID_QUEUE_SETUP_ERROR,
1184 .name = "Inject VIDIOC_REQBUFS Error",
1185 .type = V4L2_CTRL_TYPE_BUTTON,
1186};
1187
1188static const struct v4l2_ctrl_config vivid_ctrl_buf_prepare_error = {
1189 .ops = &vivid_streaming_ctrl_ops,
1190 .id = VIVID_CID_BUF_PREPARE_ERROR,
1191 .name = "Inject VIDIOC_QBUF Error",
1192 .type = V4L2_CTRL_TYPE_BUTTON,
1193};
1194
1195static const struct v4l2_ctrl_config vivid_ctrl_start_streaming_error = {
1196 .ops = &vivid_streaming_ctrl_ops,
1197 .id = VIVID_CID_START_STR_ERROR,
1198 .name = "Inject VIDIOC_STREAMON Error",
1199 .type = V4L2_CTRL_TYPE_BUTTON,
1200};
1201
1202static const struct v4l2_ctrl_config vivid_ctrl_queue_error = {
1203 .ops = &vivid_streaming_ctrl_ops,
1204 .id = VIVID_CID_QUEUE_ERROR,
1205 .name = "Inject Fatal Streaming Error",
1206 .type = V4L2_CTRL_TYPE_BUTTON,
1207};
1208
Hans Verkuila4b36752018-11-28 04:11:52 -05001209#ifdef CONFIG_MEDIA_CONTROLLER
1210static const struct v4l2_ctrl_config vivid_ctrl_req_validate_error = {
1211 .ops = &vivid_streaming_ctrl_ops,
1212 .id = VIVID_CID_REQ_VALIDATE_ERROR,
1213 .name = "Inject req_validate() Error",
1214 .type = V4L2_CTRL_TYPE_BUTTON,
1215};
1216#endif
1217
Hans Verkuil73c3f482014-08-25 07:55:23 -03001218static const struct v4l2_ctrl_config vivid_ctrl_seq_wrap = {
1219 .ops = &vivid_streaming_ctrl_ops,
1220 .id = VIVID_CID_SEQ_WRAP,
1221 .name = "Wrap Sequence Number",
1222 .type = V4L2_CTRL_TYPE_BOOLEAN,
1223 .max = 1,
1224 .step = 1,
1225};
1226
Deborah Brouwer57c1d5d2021-12-08 01:40:42 +01001227static const char * const vivid_ctrl_time_wrap_strings[] = {
1228 "None",
1229 "64 Bit",
1230 "32 Bit",
1231 NULL,
1232};
1233
Hans Verkuil73c3f482014-08-25 07:55:23 -03001234static const struct v4l2_ctrl_config vivid_ctrl_time_wrap = {
1235 .ops = &vivid_streaming_ctrl_ops,
1236 .id = VIVID_CID_TIME_WRAP,
1237 .name = "Wrap Timestamp",
Deborah Brouwer57c1d5d2021-12-08 01:40:42 +01001238 .type = V4L2_CTRL_TYPE_MENU,
1239 .max = ARRAY_SIZE(vivid_ctrl_time_wrap_strings) - 2,
1240 .qmenu = vivid_ctrl_time_wrap_strings,
Hans Verkuil73c3f482014-08-25 07:55:23 -03001241};
1242
1243
1244/* SDTV Capture Controls */
1245
1246static int vivid_sdtv_cap_s_ctrl(struct v4l2_ctrl *ctrl)
1247{
1248 struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_sdtv_cap);
1249
1250 switch (ctrl->id) {
1251 case VIVID_CID_STD_SIGNAL_MODE:
Johan Korsnes6c396c22019-06-18 03:37:19 -04001252 dev->std_signal_mode[dev->input] =
1253 dev->ctrl_std_signal_mode->val;
1254 if (dev->std_signal_mode[dev->input] == SELECTED_STD)
1255 dev->query_std[dev->input] =
1256 vivid_standard[dev->ctrl_standard->val];
1257 v4l2_ctrl_activate(dev->ctrl_standard,
1258 dev->std_signal_mode[dev->input] ==
1259 SELECTED_STD);
Hans Verkuil73c3f482014-08-25 07:55:23 -03001260 vivid_update_quality(dev);
1261 vivid_send_source_change(dev, TV);
1262 vivid_send_source_change(dev, SVID);
1263 break;
1264 }
1265 return 0;
1266}
1267
1268static const struct v4l2_ctrl_ops vivid_sdtv_cap_ctrl_ops = {
1269 .s_ctrl = vivid_sdtv_cap_s_ctrl,
1270};
1271
1272static const char * const vivid_ctrl_std_signal_mode_strings[] = {
1273 "Current Standard",
1274 "No Signal",
1275 "No Lock",
1276 "",
1277 "Selected Standard",
1278 "Cycle Through All Standards",
1279 NULL,
1280};
1281
1282static const struct v4l2_ctrl_config vivid_ctrl_std_signal_mode = {
1283 .ops = &vivid_sdtv_cap_ctrl_ops,
1284 .id = VIVID_CID_STD_SIGNAL_MODE,
1285 .name = "Standard Signal Mode",
1286 .type = V4L2_CTRL_TYPE_MENU,
Hans Verkuilff144722015-09-13 13:41:27 -03001287 .max = ARRAY_SIZE(vivid_ctrl_std_signal_mode_strings) - 2,
Hans Verkuil73c3f482014-08-25 07:55:23 -03001288 .menu_skip_mask = 1 << 3,
1289 .qmenu = vivid_ctrl_std_signal_mode_strings,
1290};
1291
1292static const struct v4l2_ctrl_config vivid_ctrl_standard = {
1293 .ops = &vivid_sdtv_cap_ctrl_ops,
1294 .id = VIVID_CID_STANDARD,
1295 .name = "Standard",
1296 .type = V4L2_CTRL_TYPE_MENU,
1297 .max = 14,
1298 .qmenu = vivid_ctrl_standard_strings,
1299};
1300
1301
1302
1303/* Radio Receiver Controls */
1304
1305static int vivid_radio_rx_s_ctrl(struct v4l2_ctrl *ctrl)
1306{
1307 struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_radio_rx);
1308
1309 switch (ctrl->id) {
1310 case VIVID_CID_RADIO_SEEK_MODE:
1311 dev->radio_rx_hw_seek_mode = ctrl->val;
1312 break;
1313 case VIVID_CID_RADIO_SEEK_PROG_LIM:
1314 dev->radio_rx_hw_seek_prog_lim = ctrl->val;
1315 break;
1316 case VIVID_CID_RADIO_RX_RDS_RBDS:
1317 dev->rds_gen.use_rbds = ctrl->val;
1318 break;
1319 case VIVID_CID_RADIO_RX_RDS_BLOCKIO:
1320 dev->radio_rx_rds_controls = ctrl->val;
1321 dev->radio_rx_caps &= ~V4L2_CAP_READWRITE;
1322 dev->radio_rx_rds_use_alternates = false;
1323 if (!dev->radio_rx_rds_controls) {
1324 dev->radio_rx_caps |= V4L2_CAP_READWRITE;
1325 __v4l2_ctrl_s_ctrl(dev->radio_rx_rds_pty, 0);
1326 __v4l2_ctrl_s_ctrl(dev->radio_rx_rds_ta, 0);
1327 __v4l2_ctrl_s_ctrl(dev->radio_rx_rds_tp, 0);
1328 __v4l2_ctrl_s_ctrl(dev->radio_rx_rds_ms, 0);
1329 __v4l2_ctrl_s_ctrl_string(dev->radio_rx_rds_psname, "");
1330 __v4l2_ctrl_s_ctrl_string(dev->radio_rx_rds_radiotext, "");
1331 }
1332 v4l2_ctrl_activate(dev->radio_rx_rds_pty, dev->radio_rx_rds_controls);
1333 v4l2_ctrl_activate(dev->radio_rx_rds_psname, dev->radio_rx_rds_controls);
1334 v4l2_ctrl_activate(dev->radio_rx_rds_radiotext, dev->radio_rx_rds_controls);
1335 v4l2_ctrl_activate(dev->radio_rx_rds_ta, dev->radio_rx_rds_controls);
1336 v4l2_ctrl_activate(dev->radio_rx_rds_tp, dev->radio_rx_rds_controls);
1337 v4l2_ctrl_activate(dev->radio_rx_rds_ms, dev->radio_rx_rds_controls);
Hans Verkuil65243382018-02-01 02:36:33 -05001338 dev->radio_rx_dev.device_caps = dev->radio_rx_caps;
Hans Verkuil73c3f482014-08-25 07:55:23 -03001339 break;
1340 case V4L2_CID_RDS_RECEPTION:
1341 dev->radio_rx_rds_enabled = ctrl->val;
1342 break;
1343 }
1344 return 0;
1345}
1346
1347static const struct v4l2_ctrl_ops vivid_radio_rx_ctrl_ops = {
1348 .s_ctrl = vivid_radio_rx_s_ctrl,
1349};
1350
1351static const char * const vivid_ctrl_radio_rds_mode_strings[] = {
1352 "Block I/O",
1353 "Controls",
1354 NULL,
1355};
1356
1357static const struct v4l2_ctrl_config vivid_ctrl_radio_rx_rds_blockio = {
1358 .ops = &vivid_radio_rx_ctrl_ops,
1359 .id = VIVID_CID_RADIO_RX_RDS_BLOCKIO,
1360 .name = "RDS Rx I/O Mode",
1361 .type = V4L2_CTRL_TYPE_MENU,
1362 .qmenu = vivid_ctrl_radio_rds_mode_strings,
1363 .max = 1,
1364};
1365
1366static const struct v4l2_ctrl_config vivid_ctrl_radio_rx_rds_rbds = {
1367 .ops = &vivid_radio_rx_ctrl_ops,
1368 .id = VIVID_CID_RADIO_RX_RDS_RBDS,
1369 .name = "Generate RBDS Instead of RDS",
1370 .type = V4L2_CTRL_TYPE_BOOLEAN,
1371 .max = 1,
1372 .step = 1,
1373};
1374
1375static const char * const vivid_ctrl_radio_hw_seek_mode_strings[] = {
1376 "Bounded",
1377 "Wrap Around",
1378 "Both",
1379 NULL,
1380};
1381
1382static const struct v4l2_ctrl_config vivid_ctrl_radio_hw_seek_mode = {
1383 .ops = &vivid_radio_rx_ctrl_ops,
1384 .id = VIVID_CID_RADIO_SEEK_MODE,
1385 .name = "Radio HW Seek Mode",
1386 .type = V4L2_CTRL_TYPE_MENU,
1387 .max = 2,
1388 .qmenu = vivid_ctrl_radio_hw_seek_mode_strings,
1389};
1390
1391static const struct v4l2_ctrl_config vivid_ctrl_radio_hw_seek_prog_lim = {
1392 .ops = &vivid_radio_rx_ctrl_ops,
1393 .id = VIVID_CID_RADIO_SEEK_PROG_LIM,
1394 .name = "Radio Programmable HW Seek",
1395 .type = V4L2_CTRL_TYPE_BOOLEAN,
1396 .max = 1,
1397 .step = 1,
1398};
1399
1400
1401/* Radio Transmitter Controls */
1402
1403static int vivid_radio_tx_s_ctrl(struct v4l2_ctrl *ctrl)
1404{
1405 struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_radio_tx);
1406
1407 switch (ctrl->id) {
1408 case VIVID_CID_RADIO_TX_RDS_BLOCKIO:
1409 dev->radio_tx_rds_controls = ctrl->val;
1410 dev->radio_tx_caps &= ~V4L2_CAP_READWRITE;
1411 if (!dev->radio_tx_rds_controls)
1412 dev->radio_tx_caps |= V4L2_CAP_READWRITE;
Hans Verkuil65243382018-02-01 02:36:33 -05001413 dev->radio_tx_dev.device_caps = dev->radio_tx_caps;
Hans Verkuil73c3f482014-08-25 07:55:23 -03001414 break;
1415 case V4L2_CID_RDS_TX_PTY:
1416 if (dev->radio_rx_rds_controls)
1417 v4l2_ctrl_s_ctrl(dev->radio_rx_rds_pty, ctrl->val);
1418 break;
1419 case V4L2_CID_RDS_TX_PS_NAME:
1420 if (dev->radio_rx_rds_controls)
1421 v4l2_ctrl_s_ctrl_string(dev->radio_rx_rds_psname, ctrl->p_new.p_char);
1422 break;
1423 case V4L2_CID_RDS_TX_RADIO_TEXT:
1424 if (dev->radio_rx_rds_controls)
1425 v4l2_ctrl_s_ctrl_string(dev->radio_rx_rds_radiotext, ctrl->p_new.p_char);
1426 break;
1427 case V4L2_CID_RDS_TX_TRAFFIC_ANNOUNCEMENT:
1428 if (dev->radio_rx_rds_controls)
1429 v4l2_ctrl_s_ctrl(dev->radio_rx_rds_ta, ctrl->val);
1430 break;
1431 case V4L2_CID_RDS_TX_TRAFFIC_PROGRAM:
1432 if (dev->radio_rx_rds_controls)
1433 v4l2_ctrl_s_ctrl(dev->radio_rx_rds_tp, ctrl->val);
1434 break;
1435 case V4L2_CID_RDS_TX_MUSIC_SPEECH:
1436 if (dev->radio_rx_rds_controls)
1437 v4l2_ctrl_s_ctrl(dev->radio_rx_rds_ms, ctrl->val);
1438 break;
1439 }
1440 return 0;
1441}
1442
1443static const struct v4l2_ctrl_ops vivid_radio_tx_ctrl_ops = {
1444 .s_ctrl = vivid_radio_tx_s_ctrl,
1445};
1446
1447static const struct v4l2_ctrl_config vivid_ctrl_radio_tx_rds_blockio = {
1448 .ops = &vivid_radio_tx_ctrl_ops,
1449 .id = VIVID_CID_RADIO_TX_RDS_BLOCKIO,
1450 .name = "RDS Tx I/O Mode",
1451 .type = V4L2_CTRL_TYPE_MENU,
1452 .qmenu = vivid_ctrl_radio_rds_mode_strings,
1453 .max = 1,
1454 .def = 1,
1455};
1456
1457
Antti Palosaarif335c3f2015-09-01 20:04:50 -03001458/* SDR Capture Controls */
1459
1460static int vivid_sdr_cap_s_ctrl(struct v4l2_ctrl *ctrl)
1461{
1462 struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_sdr_cap);
1463
1464 switch (ctrl->id) {
1465 case VIVID_CID_SDR_CAP_FM_DEVIATION:
1466 dev->sdr_fm_deviation = ctrl->val;
1467 break;
1468 }
1469 return 0;
1470}
1471
1472static const struct v4l2_ctrl_ops vivid_sdr_cap_ctrl_ops = {
1473 .s_ctrl = vivid_sdr_cap_s_ctrl,
1474};
1475
1476static const struct v4l2_ctrl_config vivid_ctrl_sdr_cap_fm_deviation = {
1477 .ops = &vivid_sdr_cap_ctrl_ops,
1478 .id = VIVID_CID_SDR_CAP_FM_DEVIATION,
1479 .name = "FM Deviation",
1480 .type = V4L2_CTRL_TYPE_INTEGER,
1481 .min = 100,
1482 .max = 200000,
1483 .def = 75000,
1484 .step = 1,
1485};
1486
Vandana BNd5797cf2019-10-15 07:40:15 -03001487/* Metadata Capture Control */
1488
1489static int vivid_meta_cap_s_ctrl(struct v4l2_ctrl *ctrl)
1490{
1491 struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev,
1492 ctrl_hdl_meta_cap);
1493
1494 switch (ctrl->id) {
1495 case VIVID_CID_META_CAP_GENERATE_PTS:
1496 dev->meta_pts = ctrl->val;
1497 break;
1498 case VIVID_CID_META_CAP_GENERATE_SCR:
1499 dev->meta_scr = ctrl->val;
1500 break;
1501 }
1502 return 0;
1503}
1504
1505static const struct v4l2_ctrl_ops vivid_meta_cap_ctrl_ops = {
1506 .s_ctrl = vivid_meta_cap_s_ctrl,
1507};
1508
1509static const struct v4l2_ctrl_config vivid_ctrl_meta_has_pts = {
1510 .ops = &vivid_meta_cap_ctrl_ops,
1511 .id = VIVID_CID_META_CAP_GENERATE_PTS,
1512 .name = "Generate PTS",
1513 .type = V4L2_CTRL_TYPE_BOOLEAN,
1514 .max = 1,
1515 .def = 1,
1516 .step = 1,
1517};
1518
1519static const struct v4l2_ctrl_config vivid_ctrl_meta_has_src_clk = {
1520 .ops = &vivid_meta_cap_ctrl_ops,
1521 .id = VIVID_CID_META_CAP_GENERATE_SCR,
1522 .name = "Generate SCR",
1523 .type = V4L2_CTRL_TYPE_BOOLEAN,
1524 .max = 1,
1525 .def = 1,
1526 .step = 1,
1527};
Antti Palosaarif335c3f2015-09-01 20:04:50 -03001528
Hans Verkuil73c3f482014-08-25 07:55:23 -03001529static const struct v4l2_ctrl_config vivid_ctrl_class = {
1530 .ops = &vivid_user_gen_ctrl_ops,
1531 .flags = V4L2_CTRL_FLAG_READ_ONLY | V4L2_CTRL_FLAG_WRITE_ONLY,
1532 .id = VIVID_CID_VIVID_CLASS,
1533 .name = "Vivid Controls",
1534 .type = V4L2_CTRL_TYPE_CTRL_CLASS,
1535};
1536
1537int vivid_create_controls(struct vivid_dev *dev, bool show_ccs_cap,
1538 bool show_ccs_out, bool no_error_inj,
1539 bool has_sdtv, bool has_hdmi)
1540{
1541 struct v4l2_ctrl_handler *hdl_user_gen = &dev->ctrl_hdl_user_gen;
1542 struct v4l2_ctrl_handler *hdl_user_vid = &dev->ctrl_hdl_user_vid;
1543 struct v4l2_ctrl_handler *hdl_user_aud = &dev->ctrl_hdl_user_aud;
1544 struct v4l2_ctrl_handler *hdl_streaming = &dev->ctrl_hdl_streaming;
1545 struct v4l2_ctrl_handler *hdl_sdtv_cap = &dev->ctrl_hdl_sdtv_cap;
Hans Verkuil63344b62015-06-01 07:15:53 -03001546 struct v4l2_ctrl_handler *hdl_loop_cap = &dev->ctrl_hdl_loop_cap;
Hans Verkuil0fa2c5f2018-01-25 06:57:45 -05001547 struct v4l2_ctrl_handler *hdl_fb = &dev->ctrl_hdl_fb;
Hans Verkuil73c3f482014-08-25 07:55:23 -03001548 struct v4l2_ctrl_handler *hdl_vid_cap = &dev->ctrl_hdl_vid_cap;
1549 struct v4l2_ctrl_handler *hdl_vid_out = &dev->ctrl_hdl_vid_out;
1550 struct v4l2_ctrl_handler *hdl_vbi_cap = &dev->ctrl_hdl_vbi_cap;
1551 struct v4l2_ctrl_handler *hdl_vbi_out = &dev->ctrl_hdl_vbi_out;
1552 struct v4l2_ctrl_handler *hdl_radio_rx = &dev->ctrl_hdl_radio_rx;
1553 struct v4l2_ctrl_handler *hdl_radio_tx = &dev->ctrl_hdl_radio_tx;
1554 struct v4l2_ctrl_handler *hdl_sdr_cap = &dev->ctrl_hdl_sdr_cap;
Vandana BNd5797cf2019-10-15 07:40:15 -03001555 struct v4l2_ctrl_handler *hdl_meta_cap = &dev->ctrl_hdl_meta_cap;
Vandana BN746facd2019-10-15 07:40:17 -03001556 struct v4l2_ctrl_handler *hdl_meta_out = &dev->ctrl_hdl_meta_out;
Vandana BN3d15c762019-11-26 15:16:50 +01001557 struct v4l2_ctrl_handler *hdl_tch_cap = &dev->ctrl_hdl_touch_cap;
Vandana BNd5797cf2019-10-15 07:40:15 -03001558
Hans Verkuil73c3f482014-08-25 07:55:23 -03001559 struct v4l2_ctrl_config vivid_ctrl_dv_timings = {
1560 .ops = &vivid_vid_cap_ctrl_ops,
1561 .id = VIVID_CID_DV_TIMINGS,
1562 .name = "DV Timings",
1563 .type = V4L2_CTRL_TYPE_MENU,
1564 };
1565 int i;
1566
1567 v4l2_ctrl_handler_init(hdl_user_gen, 10);
1568 v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_class, NULL);
1569 v4l2_ctrl_handler_init(hdl_user_vid, 9);
1570 v4l2_ctrl_new_custom(hdl_user_vid, &vivid_ctrl_class, NULL);
1571 v4l2_ctrl_handler_init(hdl_user_aud, 2);
1572 v4l2_ctrl_new_custom(hdl_user_aud, &vivid_ctrl_class, NULL);
1573 v4l2_ctrl_handler_init(hdl_streaming, 8);
1574 v4l2_ctrl_new_custom(hdl_streaming, &vivid_ctrl_class, NULL);
1575 v4l2_ctrl_handler_init(hdl_sdtv_cap, 2);
1576 v4l2_ctrl_new_custom(hdl_sdtv_cap, &vivid_ctrl_class, NULL);
Hans Verkuil63344b62015-06-01 07:15:53 -03001577 v4l2_ctrl_handler_init(hdl_loop_cap, 1);
1578 v4l2_ctrl_new_custom(hdl_loop_cap, &vivid_ctrl_class, NULL);
Hans Verkuil0fa2c5f2018-01-25 06:57:45 -05001579 v4l2_ctrl_handler_init(hdl_fb, 1);
1580 v4l2_ctrl_new_custom(hdl_fb, &vivid_ctrl_class, NULL);
Hans Verkuil73c3f482014-08-25 07:55:23 -03001581 v4l2_ctrl_handler_init(hdl_vid_cap, 55);
1582 v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_class, NULL);
1583 v4l2_ctrl_handler_init(hdl_vid_out, 26);
Guillaume Tucker79e85d12019-07-24 11:19:22 -04001584 if (!no_error_inj || dev->has_fb || dev->num_hdmi_outputs)
Hans Verkuilf6de9f62015-10-29 02:59:37 -02001585 v4l2_ctrl_new_custom(hdl_vid_out, &vivid_ctrl_class, NULL);
Hans Verkuil73c3f482014-08-25 07:55:23 -03001586 v4l2_ctrl_handler_init(hdl_vbi_cap, 21);
1587 v4l2_ctrl_new_custom(hdl_vbi_cap, &vivid_ctrl_class, NULL);
1588 v4l2_ctrl_handler_init(hdl_vbi_out, 19);
Hans Verkuilf6de9f62015-10-29 02:59:37 -02001589 if (!no_error_inj)
1590 v4l2_ctrl_new_custom(hdl_vbi_out, &vivid_ctrl_class, NULL);
Hans Verkuil73c3f482014-08-25 07:55:23 -03001591 v4l2_ctrl_handler_init(hdl_radio_rx, 17);
1592 v4l2_ctrl_new_custom(hdl_radio_rx, &vivid_ctrl_class, NULL);
1593 v4l2_ctrl_handler_init(hdl_radio_tx, 17);
1594 v4l2_ctrl_new_custom(hdl_radio_tx, &vivid_ctrl_class, NULL);
Antti Palosaarif335c3f2015-09-01 20:04:50 -03001595 v4l2_ctrl_handler_init(hdl_sdr_cap, 19);
Hans Verkuil73c3f482014-08-25 07:55:23 -03001596 v4l2_ctrl_new_custom(hdl_sdr_cap, &vivid_ctrl_class, NULL);
Vandana BNd5797cf2019-10-15 07:40:15 -03001597 v4l2_ctrl_handler_init(hdl_meta_cap, 2);
1598 v4l2_ctrl_new_custom(hdl_meta_cap, &vivid_ctrl_class, NULL);
Vandana BN746facd2019-10-15 07:40:17 -03001599 v4l2_ctrl_handler_init(hdl_meta_out, 2);
1600 v4l2_ctrl_new_custom(hdl_meta_out, &vivid_ctrl_class, NULL);
Vandana BN3d15c762019-11-26 15:16:50 +01001601 v4l2_ctrl_handler_init(hdl_tch_cap, 2);
1602 v4l2_ctrl_new_custom(hdl_tch_cap, &vivid_ctrl_class, NULL);
Hans Verkuil73c3f482014-08-25 07:55:23 -03001603
1604 /* User Controls */
1605 dev->volume = v4l2_ctrl_new_std(hdl_user_aud, NULL,
1606 V4L2_CID_AUDIO_VOLUME, 0, 255, 1, 200);
1607 dev->mute = v4l2_ctrl_new_std(hdl_user_aud, NULL,
1608 V4L2_CID_AUDIO_MUTE, 0, 1, 1, 0);
1609 if (dev->has_vid_cap) {
1610 dev->brightness = v4l2_ctrl_new_std(hdl_user_vid, &vivid_user_vid_ctrl_ops,
1611 V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
1612 for (i = 0; i < MAX_INPUTS; i++)
1613 dev->input_brightness[i] = 128;
1614 dev->contrast = v4l2_ctrl_new_std(hdl_user_vid, &vivid_user_vid_ctrl_ops,
1615 V4L2_CID_CONTRAST, 0, 255, 1, 128);
1616 dev->saturation = v4l2_ctrl_new_std(hdl_user_vid, &vivid_user_vid_ctrl_ops,
1617 V4L2_CID_SATURATION, 0, 255, 1, 128);
1618 dev->hue = v4l2_ctrl_new_std(hdl_user_vid, &vivid_user_vid_ctrl_ops,
1619 V4L2_CID_HUE, -128, 128, 1, 0);
1620 v4l2_ctrl_new_std(hdl_user_vid, &vivid_user_vid_ctrl_ops,
1621 V4L2_CID_HFLIP, 0, 1, 1, 0);
1622 v4l2_ctrl_new_std(hdl_user_vid, &vivid_user_vid_ctrl_ops,
1623 V4L2_CID_VFLIP, 0, 1, 1, 0);
1624 dev->autogain = v4l2_ctrl_new_std(hdl_user_vid, &vivid_user_vid_ctrl_ops,
1625 V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
1626 dev->gain = v4l2_ctrl_new_std(hdl_user_vid, &vivid_user_vid_ctrl_ops,
1627 V4L2_CID_GAIN, 0, 255, 1, 100);
1628 dev->alpha = v4l2_ctrl_new_std(hdl_user_vid, &vivid_user_vid_ctrl_ops,
1629 V4L2_CID_ALPHA_COMPONENT, 0, 255, 1, 0);
1630 }
1631 dev->button = v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_button, NULL);
1632 dev->int32 = v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_int32, NULL);
1633 dev->int64 = v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_int64, NULL);
1634 dev->boolean = v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_boolean, NULL);
1635 dev->menu = v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_menu, NULL);
1636 dev->string = v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_string, NULL);
1637 dev->bitmask = v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_bitmask, NULL);
1638 dev->int_menu = v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_int_menu, NULL);
Hans Verkuilbb65e3d2020-08-18 16:37:09 +02001639 dev->ro_int32 = v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_ro_int32, NULL);
Ricardo Ribalda Delgado483b2212019-11-04 14:09:20 +01001640 v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_area, NULL);
Hans Verkuil24c49422014-11-06 09:06:46 -03001641 v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_u32_array, NULL);
Hans Verkuile17d0262022-07-08 17:21:42 +01001642 v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_u32_dyn_array, NULL);
Hans Verkuil24c49422014-11-06 09:06:46 -03001643 v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_u16_matrix, NULL);
1644 v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_u8_4d_array, NULL);
Hans Verkuil73c3f482014-08-25 07:55:23 -03001645
1646 if (dev->has_vid_cap) {
1647 /* Image Processing Controls */
1648 struct v4l2_ctrl_config vivid_ctrl_test_pattern = {
1649 .ops = &vivid_vid_cap_ctrl_ops,
1650 .id = VIVID_CID_TEST_PATTERN,
1651 .name = "Test Pattern",
1652 .type = V4L2_CTRL_TYPE_MENU,
1653 .max = TPG_PAT_NOISE,
1654 .qmenu = tpg_pattern_strings,
1655 };
1656
1657 dev->test_pattern = v4l2_ctrl_new_custom(hdl_vid_cap,
1658 &vivid_ctrl_test_pattern, NULL);
1659 v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_perc_fill, NULL);
1660 v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_hor_movement, NULL);
1661 v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_vert_movement, NULL);
1662 v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_osd_mode, NULL);
1663 v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_show_border, NULL);
1664 v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_show_square, NULL);
1665 v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_hflip, NULL);
1666 v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_vflip, NULL);
1667 v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_insert_sav, NULL);
1668 v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_insert_eav, NULL);
Hans Verkuilaabcc212022-05-13 13:53:07 +01001669 v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_insert_hdmi_video_guard_band, NULL);
Prashant Laddhac79aa6a2015-09-22 11:27:30 -03001670 v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_reduced_fps, NULL);
Hans Verkuil73c3f482014-08-25 07:55:23 -03001671 if (show_ccs_cap) {
1672 dev->ctrl_has_crop_cap = v4l2_ctrl_new_custom(hdl_vid_cap,
1673 &vivid_ctrl_has_crop_cap, NULL);
1674 dev->ctrl_has_compose_cap = v4l2_ctrl_new_custom(hdl_vid_cap,
1675 &vivid_ctrl_has_compose_cap, NULL);
1676 dev->ctrl_has_scaler_cap = v4l2_ctrl_new_custom(hdl_vid_cap,
1677 &vivid_ctrl_has_scaler_cap, NULL);
1678 }
1679
1680 v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_tstamp_src, NULL);
1681 dev->colorspace = v4l2_ctrl_new_custom(hdl_vid_cap,
1682 &vivid_ctrl_colorspace, NULL);
Hans Verkuilca5316d2015-04-28 09:41:37 -03001683 v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_xfer_func, NULL);
Hans Verkuil3e8a78d2014-11-17 10:26:01 -03001684 v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_ycbcr_enc, NULL);
Ricardo Ribalda Delgado429175e2016-07-18 09:16:15 -03001685 v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_hsv_enc, NULL);
Hans Verkuil3e8a78d2014-11-17 10:26:01 -03001686 v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_quantization, NULL);
Hans Verkuil73c3f482014-08-25 07:55:23 -03001687 v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_alpha_mode, NULL);
1688 }
1689
1690 if (dev->has_vid_out && show_ccs_out) {
1691 dev->ctrl_has_crop_out = v4l2_ctrl_new_custom(hdl_vid_out,
1692 &vivid_ctrl_has_crop_out, NULL);
1693 dev->ctrl_has_compose_out = v4l2_ctrl_new_custom(hdl_vid_out,
1694 &vivid_ctrl_has_compose_out, NULL);
1695 dev->ctrl_has_scaler_out = v4l2_ctrl_new_custom(hdl_vid_out,
1696 &vivid_ctrl_has_scaler_out, NULL);
1697 }
1698
1699 /*
1700 * Testing this driver with v4l2-compliance will trigger the error
1701 * injection controls, and after that nothing will work as expected.
1702 * So we have a module option to drop these error injecting controls
1703 * allowing us to run v4l2_compliance again.
1704 */
1705 if (!no_error_inj) {
1706 v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_disconnect, NULL);
1707 v4l2_ctrl_new_custom(hdl_streaming, &vivid_ctrl_dqbuf_error, NULL);
1708 v4l2_ctrl_new_custom(hdl_streaming, &vivid_ctrl_perc_dropped, NULL);
1709 v4l2_ctrl_new_custom(hdl_streaming, &vivid_ctrl_queue_setup_error, NULL);
1710 v4l2_ctrl_new_custom(hdl_streaming, &vivid_ctrl_buf_prepare_error, NULL);
1711 v4l2_ctrl_new_custom(hdl_streaming, &vivid_ctrl_start_streaming_error, NULL);
1712 v4l2_ctrl_new_custom(hdl_streaming, &vivid_ctrl_queue_error, NULL);
Hans Verkuila4b36752018-11-28 04:11:52 -05001713#ifdef CONFIG_MEDIA_CONTROLLER
1714 v4l2_ctrl_new_custom(hdl_streaming, &vivid_ctrl_req_validate_error, NULL);
1715#endif
Hans Verkuil73c3f482014-08-25 07:55:23 -03001716 v4l2_ctrl_new_custom(hdl_streaming, &vivid_ctrl_seq_wrap, NULL);
1717 v4l2_ctrl_new_custom(hdl_streaming, &vivid_ctrl_time_wrap, NULL);
1718 }
1719
1720 if (has_sdtv && (dev->has_vid_cap || dev->has_vbi_cap)) {
1721 if (dev->has_vid_cap)
1722 v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_std_aspect_ratio, NULL);
1723 dev->ctrl_std_signal_mode = v4l2_ctrl_new_custom(hdl_sdtv_cap,
1724 &vivid_ctrl_std_signal_mode, NULL);
1725 dev->ctrl_standard = v4l2_ctrl_new_custom(hdl_sdtv_cap,
1726 &vivid_ctrl_standard, NULL);
1727 if (dev->ctrl_std_signal_mode)
1728 v4l2_ctrl_cluster(2, &dev->ctrl_std_signal_mode);
1729 if (dev->has_raw_vbi_cap)
1730 v4l2_ctrl_new_custom(hdl_vbi_cap, &vivid_ctrl_vbi_cap_interlaced, NULL);
1731 }
1732
Johan Korsnes8a99e9f2019-06-18 03:37:23 -04001733 if (dev->num_hdmi_inputs) {
Colin Ian Kingb98fd3c2019-06-27 04:05:41 -04001734 s64 hdmi_input_mask = GENMASK(dev->num_hdmi_inputs - 1, 0);
1735
Hans Verkuil73c3f482014-08-25 07:55:23 -03001736 dev->ctrl_dv_timings_signal_mode = v4l2_ctrl_new_custom(hdl_vid_cap,
1737 &vivid_ctrl_dv_timings_signal_mode, NULL);
1738
1739 vivid_ctrl_dv_timings.max = dev->query_dv_timings_size - 1;
1740 vivid_ctrl_dv_timings.qmenu =
1741 (const char * const *)dev->query_dv_timings_qmenu;
1742 dev->ctrl_dv_timings = v4l2_ctrl_new_custom(hdl_vid_cap,
1743 &vivid_ctrl_dv_timings, NULL);
1744 if (dev->ctrl_dv_timings_signal_mode)
1745 v4l2_ctrl_cluster(2, &dev->ctrl_dv_timings_signal_mode);
1746
1747 v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_dv_timings_aspect_ratio, NULL);
1748 v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_max_edid_blocks, NULL);
1749 dev->real_rgb_range_cap = v4l2_ctrl_new_custom(hdl_vid_cap,
1750 &vivid_ctrl_limited_rgb_range, NULL);
1751 dev->rgb_range_cap = v4l2_ctrl_new_std_menu(hdl_vid_cap,
1752 &vivid_vid_cap_ctrl_ops,
1753 V4L2_CID_DV_RX_RGB_RANGE, V4L2_DV_RGB_RANGE_FULL,
1754 0, V4L2_DV_RGB_RANGE_AUTO);
Johan Korsnes8a99e9f2019-06-18 03:37:23 -04001755 dev->ctrl_rx_power_present = v4l2_ctrl_new_std(hdl_vid_cap,
Colin Ian Kingb98fd3c2019-06-27 04:05:41 -04001756 NULL, V4L2_CID_DV_RX_POWER_PRESENT, 0, hdmi_input_mask,
1757 0, hdmi_input_mask);
Johan Korsnes8a99e9f2019-06-18 03:37:23 -04001758
Hans Verkuil73c3f482014-08-25 07:55:23 -03001759 }
Johan Korsnes79a792d2019-06-18 03:37:22 -04001760 if (dev->num_hdmi_outputs) {
Colin Ian Kingb98fd3c2019-06-27 04:05:41 -04001761 s64 hdmi_output_mask = GENMASK(dev->num_hdmi_outputs - 1, 0);
1762
Hans Verkuil73c3f482014-08-25 07:55:23 -03001763 /*
1764 * We aren't doing anything with this at the moment, but
1765 * HDMI outputs typically have this controls.
1766 */
1767 dev->ctrl_tx_rgb_range = v4l2_ctrl_new_std_menu(hdl_vid_out, NULL,
1768 V4L2_CID_DV_TX_RGB_RANGE, V4L2_DV_RGB_RANGE_FULL,
1769 0, V4L2_DV_RGB_RANGE_AUTO);
1770 dev->ctrl_tx_mode = v4l2_ctrl_new_std_menu(hdl_vid_out, NULL,
1771 V4L2_CID_DV_TX_MODE, V4L2_DV_TX_MODE_HDMI,
1772 0, V4L2_DV_TX_MODE_HDMI);
Johan Korsnesc5334352019-06-18 03:37:20 -04001773 dev->ctrl_display_present = v4l2_ctrl_new_custom(hdl_vid_out,
1774 &vivid_ctrl_display_present, NULL);
Johan Korsnes79a792d2019-06-18 03:37:22 -04001775 dev->ctrl_tx_hotplug = v4l2_ctrl_new_std(hdl_vid_out,
Colin Ian Kingb98fd3c2019-06-27 04:05:41 -04001776 NULL, V4L2_CID_DV_TX_HOTPLUG, 0, hdmi_output_mask,
1777 0, hdmi_output_mask);
Johan Korsnes79a792d2019-06-18 03:37:22 -04001778 dev->ctrl_tx_rxsense = v4l2_ctrl_new_std(hdl_vid_out,
Colin Ian Kingb98fd3c2019-06-27 04:05:41 -04001779 NULL, V4L2_CID_DV_TX_RXSENSE, 0, hdmi_output_mask,
1780 0, hdmi_output_mask);
Johan Korsnes79a792d2019-06-18 03:37:22 -04001781 dev->ctrl_tx_edid_present = v4l2_ctrl_new_std(hdl_vid_out,
Colin Ian Kingb98fd3c2019-06-27 04:05:41 -04001782 NULL, V4L2_CID_DV_TX_EDID_PRESENT, 0, hdmi_output_mask,
1783 0, hdmi_output_mask);
Hans Verkuil73c3f482014-08-25 07:55:23 -03001784 }
1785 if ((dev->has_vid_cap && dev->has_vid_out) ||
1786 (dev->has_vbi_cap && dev->has_vbi_out))
Hans Verkuil63344b62015-06-01 07:15:53 -03001787 v4l2_ctrl_new_custom(hdl_loop_cap, &vivid_ctrl_loop_video, NULL);
Hans Verkuil73c3f482014-08-25 07:55:23 -03001788
1789 if (dev->has_fb)
Hans Verkuil0fa2c5f2018-01-25 06:57:45 -05001790 v4l2_ctrl_new_custom(hdl_fb, &vivid_ctrl_clear_fb, NULL);
Hans Verkuil73c3f482014-08-25 07:55:23 -03001791
1792 if (dev->has_radio_rx) {
1793 v4l2_ctrl_new_custom(hdl_radio_rx, &vivid_ctrl_radio_hw_seek_mode, NULL);
1794 v4l2_ctrl_new_custom(hdl_radio_rx, &vivid_ctrl_radio_hw_seek_prog_lim, NULL);
1795 v4l2_ctrl_new_custom(hdl_radio_rx, &vivid_ctrl_radio_rx_rds_blockio, NULL);
1796 v4l2_ctrl_new_custom(hdl_radio_rx, &vivid_ctrl_radio_rx_rds_rbds, NULL);
1797 v4l2_ctrl_new_std(hdl_radio_rx, &vivid_radio_rx_ctrl_ops,
1798 V4L2_CID_RDS_RECEPTION, 0, 1, 1, 1);
1799 dev->radio_rx_rds_pty = v4l2_ctrl_new_std(hdl_radio_rx,
1800 &vivid_radio_rx_ctrl_ops,
1801 V4L2_CID_RDS_RX_PTY, 0, 31, 1, 0);
1802 dev->radio_rx_rds_psname = v4l2_ctrl_new_std(hdl_radio_rx,
1803 &vivid_radio_rx_ctrl_ops,
1804 V4L2_CID_RDS_RX_PS_NAME, 0, 8, 8, 0);
1805 dev->radio_rx_rds_radiotext = v4l2_ctrl_new_std(hdl_radio_rx,
1806 &vivid_radio_rx_ctrl_ops,
1807 V4L2_CID_RDS_RX_RADIO_TEXT, 0, 64, 64, 0);
1808 dev->radio_rx_rds_ta = v4l2_ctrl_new_std(hdl_radio_rx,
1809 &vivid_radio_rx_ctrl_ops,
1810 V4L2_CID_RDS_RX_TRAFFIC_ANNOUNCEMENT, 0, 1, 1, 0);
1811 dev->radio_rx_rds_tp = v4l2_ctrl_new_std(hdl_radio_rx,
1812 &vivid_radio_rx_ctrl_ops,
1813 V4L2_CID_RDS_RX_TRAFFIC_PROGRAM, 0, 1, 1, 0);
1814 dev->radio_rx_rds_ms = v4l2_ctrl_new_std(hdl_radio_rx,
1815 &vivid_radio_rx_ctrl_ops,
1816 V4L2_CID_RDS_RX_MUSIC_SPEECH, 0, 1, 1, 1);
1817 }
1818 if (dev->has_radio_tx) {
1819 v4l2_ctrl_new_custom(hdl_radio_tx,
1820 &vivid_ctrl_radio_tx_rds_blockio, NULL);
1821 dev->radio_tx_rds_pi = v4l2_ctrl_new_std(hdl_radio_tx,
1822 &vivid_radio_tx_ctrl_ops,
1823 V4L2_CID_RDS_TX_PI, 0, 0xffff, 1, 0x8088);
1824 dev->radio_tx_rds_pty = v4l2_ctrl_new_std(hdl_radio_tx,
1825 &vivid_radio_tx_ctrl_ops,
1826 V4L2_CID_RDS_TX_PTY, 0, 31, 1, 3);
1827 dev->radio_tx_rds_psname = v4l2_ctrl_new_std(hdl_radio_tx,
1828 &vivid_radio_tx_ctrl_ops,
1829 V4L2_CID_RDS_TX_PS_NAME, 0, 8, 8, 0);
1830 if (dev->radio_tx_rds_psname)
1831 v4l2_ctrl_s_ctrl_string(dev->radio_tx_rds_psname, "VIVID-TX");
1832 dev->radio_tx_rds_radiotext = v4l2_ctrl_new_std(hdl_radio_tx,
1833 &vivid_radio_tx_ctrl_ops,
1834 V4L2_CID_RDS_TX_RADIO_TEXT, 0, 64 * 2, 64, 0);
1835 if (dev->radio_tx_rds_radiotext)
1836 v4l2_ctrl_s_ctrl_string(dev->radio_tx_rds_radiotext,
1837 "This is a VIVID default Radio Text template text, change at will");
1838 dev->radio_tx_rds_mono_stereo = v4l2_ctrl_new_std(hdl_radio_tx,
1839 &vivid_radio_tx_ctrl_ops,
1840 V4L2_CID_RDS_TX_MONO_STEREO, 0, 1, 1, 1);
1841 dev->radio_tx_rds_art_head = v4l2_ctrl_new_std(hdl_radio_tx,
1842 &vivid_radio_tx_ctrl_ops,
1843 V4L2_CID_RDS_TX_ARTIFICIAL_HEAD, 0, 1, 1, 0);
1844 dev->radio_tx_rds_compressed = v4l2_ctrl_new_std(hdl_radio_tx,
1845 &vivid_radio_tx_ctrl_ops,
1846 V4L2_CID_RDS_TX_COMPRESSED, 0, 1, 1, 0);
1847 dev->radio_tx_rds_dyn_pty = v4l2_ctrl_new_std(hdl_radio_tx,
1848 &vivid_radio_tx_ctrl_ops,
1849 V4L2_CID_RDS_TX_DYNAMIC_PTY, 0, 1, 1, 0);
1850 dev->radio_tx_rds_ta = v4l2_ctrl_new_std(hdl_radio_tx,
1851 &vivid_radio_tx_ctrl_ops,
1852 V4L2_CID_RDS_TX_TRAFFIC_ANNOUNCEMENT, 0, 1, 1, 0);
1853 dev->radio_tx_rds_tp = v4l2_ctrl_new_std(hdl_radio_tx,
1854 &vivid_radio_tx_ctrl_ops,
1855 V4L2_CID_RDS_TX_TRAFFIC_PROGRAM, 0, 1, 1, 1);
1856 dev->radio_tx_rds_ms = v4l2_ctrl_new_std(hdl_radio_tx,
1857 &vivid_radio_tx_ctrl_ops,
1858 V4L2_CID_RDS_TX_MUSIC_SPEECH, 0, 1, 1, 1);
1859 }
Antti Palosaarif335c3f2015-09-01 20:04:50 -03001860 if (dev->has_sdr_cap) {
1861 v4l2_ctrl_new_custom(hdl_sdr_cap,
1862 &vivid_ctrl_sdr_cap_fm_deviation, NULL);
1863 }
Vandana BNd5797cf2019-10-15 07:40:15 -03001864 if (dev->has_meta_cap) {
1865 v4l2_ctrl_new_custom(hdl_meta_cap,
1866 &vivid_ctrl_meta_has_pts, NULL);
1867 v4l2_ctrl_new_custom(hdl_meta_cap,
1868 &vivid_ctrl_meta_has_src_clk, NULL);
1869 }
1870
Hans Verkuil73c3f482014-08-25 07:55:23 -03001871 if (hdl_user_gen->error)
1872 return hdl_user_gen->error;
1873 if (hdl_user_vid->error)
1874 return hdl_user_vid->error;
1875 if (hdl_user_aud->error)
1876 return hdl_user_aud->error;
1877 if (hdl_streaming->error)
1878 return hdl_streaming->error;
1879 if (hdl_sdr_cap->error)
1880 return hdl_sdr_cap->error;
Hans Verkuil63344b62015-06-01 07:15:53 -03001881 if (hdl_loop_cap->error)
1882 return hdl_loop_cap->error;
Hans Verkuil73c3f482014-08-25 07:55:23 -03001883
1884 if (dev->autogain)
1885 v4l2_ctrl_auto_cluster(2, &dev->autogain, 0, true);
1886
1887 if (dev->has_vid_cap) {
Hans Verkuilda1b1ae2018-05-21 04:54:36 -04001888 v4l2_ctrl_add_handler(hdl_vid_cap, hdl_user_gen, NULL, false);
1889 v4l2_ctrl_add_handler(hdl_vid_cap, hdl_user_vid, NULL, false);
1890 v4l2_ctrl_add_handler(hdl_vid_cap, hdl_user_aud, NULL, false);
1891 v4l2_ctrl_add_handler(hdl_vid_cap, hdl_streaming, NULL, false);
1892 v4l2_ctrl_add_handler(hdl_vid_cap, hdl_sdtv_cap, NULL, false);
1893 v4l2_ctrl_add_handler(hdl_vid_cap, hdl_loop_cap, NULL, false);
1894 v4l2_ctrl_add_handler(hdl_vid_cap, hdl_fb, NULL, false);
Hans Verkuil73c3f482014-08-25 07:55:23 -03001895 if (hdl_vid_cap->error)
1896 return hdl_vid_cap->error;
1897 dev->vid_cap_dev.ctrl_handler = hdl_vid_cap;
1898 }
1899 if (dev->has_vid_out) {
Hans Verkuilda1b1ae2018-05-21 04:54:36 -04001900 v4l2_ctrl_add_handler(hdl_vid_out, hdl_user_gen, NULL, false);
1901 v4l2_ctrl_add_handler(hdl_vid_out, hdl_user_aud, NULL, false);
1902 v4l2_ctrl_add_handler(hdl_vid_out, hdl_streaming, NULL, false);
1903 v4l2_ctrl_add_handler(hdl_vid_out, hdl_fb, NULL, false);
Hans Verkuil73c3f482014-08-25 07:55:23 -03001904 if (hdl_vid_out->error)
1905 return hdl_vid_out->error;
1906 dev->vid_out_dev.ctrl_handler = hdl_vid_out;
1907 }
1908 if (dev->has_vbi_cap) {
Hans Verkuilda1b1ae2018-05-21 04:54:36 -04001909 v4l2_ctrl_add_handler(hdl_vbi_cap, hdl_user_gen, NULL, false);
1910 v4l2_ctrl_add_handler(hdl_vbi_cap, hdl_streaming, NULL, false);
1911 v4l2_ctrl_add_handler(hdl_vbi_cap, hdl_sdtv_cap, NULL, false);
1912 v4l2_ctrl_add_handler(hdl_vbi_cap, hdl_loop_cap, NULL, false);
Hans Verkuil73c3f482014-08-25 07:55:23 -03001913 if (hdl_vbi_cap->error)
1914 return hdl_vbi_cap->error;
1915 dev->vbi_cap_dev.ctrl_handler = hdl_vbi_cap;
1916 }
1917 if (dev->has_vbi_out) {
Hans Verkuilda1b1ae2018-05-21 04:54:36 -04001918 v4l2_ctrl_add_handler(hdl_vbi_out, hdl_user_gen, NULL, false);
1919 v4l2_ctrl_add_handler(hdl_vbi_out, hdl_streaming, NULL, false);
Hans Verkuil73c3f482014-08-25 07:55:23 -03001920 if (hdl_vbi_out->error)
1921 return hdl_vbi_out->error;
1922 dev->vbi_out_dev.ctrl_handler = hdl_vbi_out;
1923 }
1924 if (dev->has_radio_rx) {
Hans Verkuilda1b1ae2018-05-21 04:54:36 -04001925 v4l2_ctrl_add_handler(hdl_radio_rx, hdl_user_gen, NULL, false);
1926 v4l2_ctrl_add_handler(hdl_radio_rx, hdl_user_aud, NULL, false);
Hans Verkuil73c3f482014-08-25 07:55:23 -03001927 if (hdl_radio_rx->error)
1928 return hdl_radio_rx->error;
1929 dev->radio_rx_dev.ctrl_handler = hdl_radio_rx;
1930 }
1931 if (dev->has_radio_tx) {
Hans Verkuilda1b1ae2018-05-21 04:54:36 -04001932 v4l2_ctrl_add_handler(hdl_radio_tx, hdl_user_gen, NULL, false);
1933 v4l2_ctrl_add_handler(hdl_radio_tx, hdl_user_aud, NULL, false);
Hans Verkuil73c3f482014-08-25 07:55:23 -03001934 if (hdl_radio_tx->error)
1935 return hdl_radio_tx->error;
1936 dev->radio_tx_dev.ctrl_handler = hdl_radio_tx;
1937 }
1938 if (dev->has_sdr_cap) {
Hans Verkuilda1b1ae2018-05-21 04:54:36 -04001939 v4l2_ctrl_add_handler(hdl_sdr_cap, hdl_user_gen, NULL, false);
1940 v4l2_ctrl_add_handler(hdl_sdr_cap, hdl_streaming, NULL, false);
Hans Verkuil73c3f482014-08-25 07:55:23 -03001941 if (hdl_sdr_cap->error)
1942 return hdl_sdr_cap->error;
1943 dev->sdr_cap_dev.ctrl_handler = hdl_sdr_cap;
1944 }
Vandana BNd5797cf2019-10-15 07:40:15 -03001945 if (dev->has_meta_cap) {
1946 v4l2_ctrl_add_handler(hdl_meta_cap, hdl_user_gen, NULL, false);
1947 v4l2_ctrl_add_handler(hdl_meta_cap, hdl_streaming, NULL, false);
1948 if (hdl_meta_cap->error)
1949 return hdl_meta_cap->error;
1950 dev->meta_cap_dev.ctrl_handler = hdl_meta_cap;
1951 }
Vandana BN746facd2019-10-15 07:40:17 -03001952 if (dev->has_meta_out) {
1953 v4l2_ctrl_add_handler(hdl_meta_out, hdl_user_gen, NULL, false);
1954 v4l2_ctrl_add_handler(hdl_meta_out, hdl_streaming, NULL, false);
1955 if (hdl_meta_out->error)
1956 return hdl_meta_out->error;
1957 dev->meta_out_dev.ctrl_handler = hdl_meta_out;
1958 }
Vandana BN3d15c762019-11-26 15:16:50 +01001959 if (dev->has_touch_cap) {
1960 v4l2_ctrl_add_handler(hdl_tch_cap, hdl_user_gen, NULL, false);
1961 v4l2_ctrl_add_handler(hdl_tch_cap, hdl_streaming, NULL, false);
1962 if (hdl_tch_cap->error)
1963 return hdl_tch_cap->error;
1964 dev->touch_cap_dev.ctrl_handler = hdl_tch_cap;
1965 }
Hans Verkuil73c3f482014-08-25 07:55:23 -03001966 return 0;
1967}
1968
1969void vivid_free_controls(struct vivid_dev *dev)
1970{
1971 v4l2_ctrl_handler_free(&dev->ctrl_hdl_vid_cap);
1972 v4l2_ctrl_handler_free(&dev->ctrl_hdl_vid_out);
1973 v4l2_ctrl_handler_free(&dev->ctrl_hdl_vbi_cap);
1974 v4l2_ctrl_handler_free(&dev->ctrl_hdl_vbi_out);
1975 v4l2_ctrl_handler_free(&dev->ctrl_hdl_radio_rx);
1976 v4l2_ctrl_handler_free(&dev->ctrl_hdl_radio_tx);
1977 v4l2_ctrl_handler_free(&dev->ctrl_hdl_sdr_cap);
1978 v4l2_ctrl_handler_free(&dev->ctrl_hdl_user_gen);
1979 v4l2_ctrl_handler_free(&dev->ctrl_hdl_user_vid);
1980 v4l2_ctrl_handler_free(&dev->ctrl_hdl_user_aud);
1981 v4l2_ctrl_handler_free(&dev->ctrl_hdl_streaming);
1982 v4l2_ctrl_handler_free(&dev->ctrl_hdl_sdtv_cap);
Hans Verkuil63344b62015-06-01 07:15:53 -03001983 v4l2_ctrl_handler_free(&dev->ctrl_hdl_loop_cap);
Hans Verkuil0fa2c5f2018-01-25 06:57:45 -05001984 v4l2_ctrl_handler_free(&dev->ctrl_hdl_fb);
Vandana BNd5797cf2019-10-15 07:40:15 -03001985 v4l2_ctrl_handler_free(&dev->ctrl_hdl_meta_cap);
Vandana BN746facd2019-10-15 07:40:17 -03001986 v4l2_ctrl_handler_free(&dev->ctrl_hdl_meta_out);
Vandana BN3d15c762019-11-26 15:16:50 +01001987 v4l2_ctrl_handler_free(&dev->ctrl_hdl_touch_cap);
Hans Verkuil73c3f482014-08-25 07:55:23 -03001988}