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