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