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