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