18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * vivid-ctrls.c - control support functions.
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright 2014 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
68c2ecf20Sopenharmony_ci */
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci#include <linux/errno.h>
98c2ecf20Sopenharmony_ci#include <linux/kernel.h>
108c2ecf20Sopenharmony_ci#include <linux/videodev2.h>
118c2ecf20Sopenharmony_ci#include <media/v4l2-event.h>
128c2ecf20Sopenharmony_ci#include <media/v4l2-common.h>
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_ci#include "vivid-core.h"
158c2ecf20Sopenharmony_ci#include "vivid-vid-cap.h"
168c2ecf20Sopenharmony_ci#include "vivid-vid-out.h"
178c2ecf20Sopenharmony_ci#include "vivid-vid-common.h"
188c2ecf20Sopenharmony_ci#include "vivid-radio-common.h"
198c2ecf20Sopenharmony_ci#include "vivid-osd.h"
208c2ecf20Sopenharmony_ci#include "vivid-ctrls.h"
218c2ecf20Sopenharmony_ci#include "vivid-cec.h"
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_ci#define VIVID_CID_CUSTOM_BASE		(V4L2_CID_USER_BASE | 0xf000)
248c2ecf20Sopenharmony_ci#define VIVID_CID_BUTTON		(VIVID_CID_CUSTOM_BASE + 0)
258c2ecf20Sopenharmony_ci#define VIVID_CID_BOOLEAN		(VIVID_CID_CUSTOM_BASE + 1)
268c2ecf20Sopenharmony_ci#define VIVID_CID_INTEGER		(VIVID_CID_CUSTOM_BASE + 2)
278c2ecf20Sopenharmony_ci#define VIVID_CID_INTEGER64		(VIVID_CID_CUSTOM_BASE + 3)
288c2ecf20Sopenharmony_ci#define VIVID_CID_MENU			(VIVID_CID_CUSTOM_BASE + 4)
298c2ecf20Sopenharmony_ci#define VIVID_CID_STRING		(VIVID_CID_CUSTOM_BASE + 5)
308c2ecf20Sopenharmony_ci#define VIVID_CID_BITMASK		(VIVID_CID_CUSTOM_BASE + 6)
318c2ecf20Sopenharmony_ci#define VIVID_CID_INTMENU		(VIVID_CID_CUSTOM_BASE + 7)
328c2ecf20Sopenharmony_ci#define VIVID_CID_U32_ARRAY		(VIVID_CID_CUSTOM_BASE + 8)
338c2ecf20Sopenharmony_ci#define VIVID_CID_U16_MATRIX		(VIVID_CID_CUSTOM_BASE + 9)
348c2ecf20Sopenharmony_ci#define VIVID_CID_U8_4D_ARRAY		(VIVID_CID_CUSTOM_BASE + 10)
358c2ecf20Sopenharmony_ci#define VIVID_CID_AREA			(VIVID_CID_CUSTOM_BASE + 11)
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_ci#define VIVID_CID_VIVID_BASE		(0x00f00000 | 0xf000)
388c2ecf20Sopenharmony_ci#define VIVID_CID_VIVID_CLASS		(0x00f00000 | 1)
398c2ecf20Sopenharmony_ci#define VIVID_CID_TEST_PATTERN		(VIVID_CID_VIVID_BASE + 0)
408c2ecf20Sopenharmony_ci#define VIVID_CID_OSD_TEXT_MODE		(VIVID_CID_VIVID_BASE + 1)
418c2ecf20Sopenharmony_ci#define VIVID_CID_HOR_MOVEMENT		(VIVID_CID_VIVID_BASE + 2)
428c2ecf20Sopenharmony_ci#define VIVID_CID_VERT_MOVEMENT		(VIVID_CID_VIVID_BASE + 3)
438c2ecf20Sopenharmony_ci#define VIVID_CID_SHOW_BORDER		(VIVID_CID_VIVID_BASE + 4)
448c2ecf20Sopenharmony_ci#define VIVID_CID_SHOW_SQUARE		(VIVID_CID_VIVID_BASE + 5)
458c2ecf20Sopenharmony_ci#define VIVID_CID_INSERT_SAV		(VIVID_CID_VIVID_BASE + 6)
468c2ecf20Sopenharmony_ci#define VIVID_CID_INSERT_EAV		(VIVID_CID_VIVID_BASE + 7)
478c2ecf20Sopenharmony_ci#define VIVID_CID_VBI_CAP_INTERLACED	(VIVID_CID_VIVID_BASE + 8)
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_ci#define VIVID_CID_HFLIP			(VIVID_CID_VIVID_BASE + 20)
508c2ecf20Sopenharmony_ci#define VIVID_CID_VFLIP			(VIVID_CID_VIVID_BASE + 21)
518c2ecf20Sopenharmony_ci#define VIVID_CID_STD_ASPECT_RATIO	(VIVID_CID_VIVID_BASE + 22)
528c2ecf20Sopenharmony_ci#define VIVID_CID_DV_TIMINGS_ASPECT_RATIO	(VIVID_CID_VIVID_BASE + 23)
538c2ecf20Sopenharmony_ci#define VIVID_CID_TSTAMP_SRC		(VIVID_CID_VIVID_BASE + 24)
548c2ecf20Sopenharmony_ci#define VIVID_CID_COLORSPACE		(VIVID_CID_VIVID_BASE + 25)
558c2ecf20Sopenharmony_ci#define VIVID_CID_XFER_FUNC		(VIVID_CID_VIVID_BASE + 26)
568c2ecf20Sopenharmony_ci#define VIVID_CID_YCBCR_ENC		(VIVID_CID_VIVID_BASE + 27)
578c2ecf20Sopenharmony_ci#define VIVID_CID_QUANTIZATION		(VIVID_CID_VIVID_BASE + 28)
588c2ecf20Sopenharmony_ci#define VIVID_CID_LIMITED_RGB_RANGE	(VIVID_CID_VIVID_BASE + 29)
598c2ecf20Sopenharmony_ci#define VIVID_CID_ALPHA_MODE		(VIVID_CID_VIVID_BASE + 30)
608c2ecf20Sopenharmony_ci#define VIVID_CID_HAS_CROP_CAP		(VIVID_CID_VIVID_BASE + 31)
618c2ecf20Sopenharmony_ci#define VIVID_CID_HAS_COMPOSE_CAP	(VIVID_CID_VIVID_BASE + 32)
628c2ecf20Sopenharmony_ci#define VIVID_CID_HAS_SCALER_CAP	(VIVID_CID_VIVID_BASE + 33)
638c2ecf20Sopenharmony_ci#define VIVID_CID_HAS_CROP_OUT		(VIVID_CID_VIVID_BASE + 34)
648c2ecf20Sopenharmony_ci#define VIVID_CID_HAS_COMPOSE_OUT	(VIVID_CID_VIVID_BASE + 35)
658c2ecf20Sopenharmony_ci#define VIVID_CID_HAS_SCALER_OUT	(VIVID_CID_VIVID_BASE + 36)
668c2ecf20Sopenharmony_ci#define VIVID_CID_LOOP_VIDEO		(VIVID_CID_VIVID_BASE + 37)
678c2ecf20Sopenharmony_ci#define VIVID_CID_SEQ_WRAP		(VIVID_CID_VIVID_BASE + 38)
688c2ecf20Sopenharmony_ci#define VIVID_CID_TIME_WRAP		(VIVID_CID_VIVID_BASE + 39)
698c2ecf20Sopenharmony_ci#define VIVID_CID_MAX_EDID_BLOCKS	(VIVID_CID_VIVID_BASE + 40)
708c2ecf20Sopenharmony_ci#define VIVID_CID_PERCENTAGE_FILL	(VIVID_CID_VIVID_BASE + 41)
718c2ecf20Sopenharmony_ci#define VIVID_CID_REDUCED_FPS		(VIVID_CID_VIVID_BASE + 42)
728c2ecf20Sopenharmony_ci#define VIVID_CID_HSV_ENC		(VIVID_CID_VIVID_BASE + 43)
738c2ecf20Sopenharmony_ci#define VIVID_CID_DISPLAY_PRESENT	(VIVID_CID_VIVID_BASE + 44)
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_ci#define VIVID_CID_STD_SIGNAL_MODE	(VIVID_CID_VIVID_BASE + 60)
768c2ecf20Sopenharmony_ci#define VIVID_CID_STANDARD		(VIVID_CID_VIVID_BASE + 61)
778c2ecf20Sopenharmony_ci#define VIVID_CID_DV_TIMINGS_SIGNAL_MODE	(VIVID_CID_VIVID_BASE + 62)
788c2ecf20Sopenharmony_ci#define VIVID_CID_DV_TIMINGS		(VIVID_CID_VIVID_BASE + 63)
798c2ecf20Sopenharmony_ci#define VIVID_CID_PERC_DROPPED		(VIVID_CID_VIVID_BASE + 64)
808c2ecf20Sopenharmony_ci#define VIVID_CID_DISCONNECT		(VIVID_CID_VIVID_BASE + 65)
818c2ecf20Sopenharmony_ci#define VIVID_CID_DQBUF_ERROR		(VIVID_CID_VIVID_BASE + 66)
828c2ecf20Sopenharmony_ci#define VIVID_CID_QUEUE_SETUP_ERROR	(VIVID_CID_VIVID_BASE + 67)
838c2ecf20Sopenharmony_ci#define VIVID_CID_BUF_PREPARE_ERROR	(VIVID_CID_VIVID_BASE + 68)
848c2ecf20Sopenharmony_ci#define VIVID_CID_START_STR_ERROR	(VIVID_CID_VIVID_BASE + 69)
858c2ecf20Sopenharmony_ci#define VIVID_CID_QUEUE_ERROR		(VIVID_CID_VIVID_BASE + 70)
868c2ecf20Sopenharmony_ci#define VIVID_CID_CLEAR_FB		(VIVID_CID_VIVID_BASE + 71)
878c2ecf20Sopenharmony_ci#define VIVID_CID_REQ_VALIDATE_ERROR	(VIVID_CID_VIVID_BASE + 72)
888c2ecf20Sopenharmony_ci
898c2ecf20Sopenharmony_ci#define VIVID_CID_RADIO_SEEK_MODE	(VIVID_CID_VIVID_BASE + 90)
908c2ecf20Sopenharmony_ci#define VIVID_CID_RADIO_SEEK_PROG_LIM	(VIVID_CID_VIVID_BASE + 91)
918c2ecf20Sopenharmony_ci#define VIVID_CID_RADIO_RX_RDS_RBDS	(VIVID_CID_VIVID_BASE + 92)
928c2ecf20Sopenharmony_ci#define VIVID_CID_RADIO_RX_RDS_BLOCKIO	(VIVID_CID_VIVID_BASE + 93)
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_ci#define VIVID_CID_RADIO_TX_RDS_BLOCKIO	(VIVID_CID_VIVID_BASE + 94)
958c2ecf20Sopenharmony_ci
968c2ecf20Sopenharmony_ci#define VIVID_CID_SDR_CAP_FM_DEVIATION	(VIVID_CID_VIVID_BASE + 110)
978c2ecf20Sopenharmony_ci
988c2ecf20Sopenharmony_ci#define VIVID_CID_META_CAP_GENERATE_PTS	(VIVID_CID_VIVID_BASE + 111)
998c2ecf20Sopenharmony_ci#define VIVID_CID_META_CAP_GENERATE_SCR	(VIVID_CID_VIVID_BASE + 112)
1008c2ecf20Sopenharmony_ci
1018c2ecf20Sopenharmony_ci/* General User Controls */
1028c2ecf20Sopenharmony_ci
1038c2ecf20Sopenharmony_cistatic int vivid_user_gen_s_ctrl(struct v4l2_ctrl *ctrl)
1048c2ecf20Sopenharmony_ci{
1058c2ecf20Sopenharmony_ci	struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_user_gen);
1068c2ecf20Sopenharmony_ci
1078c2ecf20Sopenharmony_ci	switch (ctrl->id) {
1088c2ecf20Sopenharmony_ci	case VIVID_CID_DISCONNECT:
1098c2ecf20Sopenharmony_ci		v4l2_info(&dev->v4l2_dev, "disconnect\n");
1108c2ecf20Sopenharmony_ci		clear_bit(V4L2_FL_REGISTERED, &dev->vid_cap_dev.flags);
1118c2ecf20Sopenharmony_ci		clear_bit(V4L2_FL_REGISTERED, &dev->vid_out_dev.flags);
1128c2ecf20Sopenharmony_ci		clear_bit(V4L2_FL_REGISTERED, &dev->vbi_cap_dev.flags);
1138c2ecf20Sopenharmony_ci		clear_bit(V4L2_FL_REGISTERED, &dev->vbi_out_dev.flags);
1148c2ecf20Sopenharmony_ci		clear_bit(V4L2_FL_REGISTERED, &dev->sdr_cap_dev.flags);
1158c2ecf20Sopenharmony_ci		clear_bit(V4L2_FL_REGISTERED, &dev->radio_rx_dev.flags);
1168c2ecf20Sopenharmony_ci		clear_bit(V4L2_FL_REGISTERED, &dev->radio_tx_dev.flags);
1178c2ecf20Sopenharmony_ci		clear_bit(V4L2_FL_REGISTERED, &dev->meta_cap_dev.flags);
1188c2ecf20Sopenharmony_ci		break;
1198c2ecf20Sopenharmony_ci	case VIVID_CID_BUTTON:
1208c2ecf20Sopenharmony_ci		dev->button_pressed = 30;
1218c2ecf20Sopenharmony_ci		break;
1228c2ecf20Sopenharmony_ci	}
1238c2ecf20Sopenharmony_ci	return 0;
1248c2ecf20Sopenharmony_ci}
1258c2ecf20Sopenharmony_ci
1268c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_ops vivid_user_gen_ctrl_ops = {
1278c2ecf20Sopenharmony_ci	.s_ctrl = vivid_user_gen_s_ctrl,
1288c2ecf20Sopenharmony_ci};
1298c2ecf20Sopenharmony_ci
1308c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_button = {
1318c2ecf20Sopenharmony_ci	.ops = &vivid_user_gen_ctrl_ops,
1328c2ecf20Sopenharmony_ci	.id = VIVID_CID_BUTTON,
1338c2ecf20Sopenharmony_ci	.name = "Button",
1348c2ecf20Sopenharmony_ci	.type = V4L2_CTRL_TYPE_BUTTON,
1358c2ecf20Sopenharmony_ci};
1368c2ecf20Sopenharmony_ci
1378c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_boolean = {
1388c2ecf20Sopenharmony_ci	.ops = &vivid_user_gen_ctrl_ops,
1398c2ecf20Sopenharmony_ci	.id = VIVID_CID_BOOLEAN,
1408c2ecf20Sopenharmony_ci	.name = "Boolean",
1418c2ecf20Sopenharmony_ci	.type = V4L2_CTRL_TYPE_BOOLEAN,
1428c2ecf20Sopenharmony_ci	.min = 0,
1438c2ecf20Sopenharmony_ci	.max = 1,
1448c2ecf20Sopenharmony_ci	.step = 1,
1458c2ecf20Sopenharmony_ci	.def = 1,
1468c2ecf20Sopenharmony_ci};
1478c2ecf20Sopenharmony_ci
1488c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_int32 = {
1498c2ecf20Sopenharmony_ci	.ops = &vivid_user_gen_ctrl_ops,
1508c2ecf20Sopenharmony_ci	.id = VIVID_CID_INTEGER,
1518c2ecf20Sopenharmony_ci	.name = "Integer 32 Bits",
1528c2ecf20Sopenharmony_ci	.type = V4L2_CTRL_TYPE_INTEGER,
1538c2ecf20Sopenharmony_ci	.min = 0xffffffff80000000ULL,
1548c2ecf20Sopenharmony_ci	.max = 0x7fffffff,
1558c2ecf20Sopenharmony_ci	.step = 1,
1568c2ecf20Sopenharmony_ci};
1578c2ecf20Sopenharmony_ci
1588c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_int64 = {
1598c2ecf20Sopenharmony_ci	.ops = &vivid_user_gen_ctrl_ops,
1608c2ecf20Sopenharmony_ci	.id = VIVID_CID_INTEGER64,
1618c2ecf20Sopenharmony_ci	.name = "Integer 64 Bits",
1628c2ecf20Sopenharmony_ci	.type = V4L2_CTRL_TYPE_INTEGER64,
1638c2ecf20Sopenharmony_ci	.min = 0x8000000000000000ULL,
1648c2ecf20Sopenharmony_ci	.max = 0x7fffffffffffffffLL,
1658c2ecf20Sopenharmony_ci	.step = 1,
1668c2ecf20Sopenharmony_ci};
1678c2ecf20Sopenharmony_ci
1688c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_u32_array = {
1698c2ecf20Sopenharmony_ci	.ops = &vivid_user_gen_ctrl_ops,
1708c2ecf20Sopenharmony_ci	.id = VIVID_CID_U32_ARRAY,
1718c2ecf20Sopenharmony_ci	.name = "U32 1 Element Array",
1728c2ecf20Sopenharmony_ci	.type = V4L2_CTRL_TYPE_U32,
1738c2ecf20Sopenharmony_ci	.def = 0x18,
1748c2ecf20Sopenharmony_ci	.min = 0x10,
1758c2ecf20Sopenharmony_ci	.max = 0x20000,
1768c2ecf20Sopenharmony_ci	.step = 1,
1778c2ecf20Sopenharmony_ci	.dims = { 1 },
1788c2ecf20Sopenharmony_ci};
1798c2ecf20Sopenharmony_ci
1808c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_u16_matrix = {
1818c2ecf20Sopenharmony_ci	.ops = &vivid_user_gen_ctrl_ops,
1828c2ecf20Sopenharmony_ci	.id = VIVID_CID_U16_MATRIX,
1838c2ecf20Sopenharmony_ci	.name = "U16 8x16 Matrix",
1848c2ecf20Sopenharmony_ci	.type = V4L2_CTRL_TYPE_U16,
1858c2ecf20Sopenharmony_ci	.def = 0x18,
1868c2ecf20Sopenharmony_ci	.min = 0x10,
1878c2ecf20Sopenharmony_ci	.max = 0x2000,
1888c2ecf20Sopenharmony_ci	.step = 1,
1898c2ecf20Sopenharmony_ci	.dims = { 8, 16 },
1908c2ecf20Sopenharmony_ci};
1918c2ecf20Sopenharmony_ci
1928c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_u8_4d_array = {
1938c2ecf20Sopenharmony_ci	.ops = &vivid_user_gen_ctrl_ops,
1948c2ecf20Sopenharmony_ci	.id = VIVID_CID_U8_4D_ARRAY,
1958c2ecf20Sopenharmony_ci	.name = "U8 2x3x4x5 Array",
1968c2ecf20Sopenharmony_ci	.type = V4L2_CTRL_TYPE_U8,
1978c2ecf20Sopenharmony_ci	.def = 0x18,
1988c2ecf20Sopenharmony_ci	.min = 0x10,
1998c2ecf20Sopenharmony_ci	.max = 0x20,
2008c2ecf20Sopenharmony_ci	.step = 1,
2018c2ecf20Sopenharmony_ci	.dims = { 2, 3, 4, 5 },
2028c2ecf20Sopenharmony_ci};
2038c2ecf20Sopenharmony_ci
2048c2ecf20Sopenharmony_cistatic const char * const vivid_ctrl_menu_strings[] = {
2058c2ecf20Sopenharmony_ci	"Menu Item 0 (Skipped)",
2068c2ecf20Sopenharmony_ci	"Menu Item 1",
2078c2ecf20Sopenharmony_ci	"Menu Item 2 (Skipped)",
2088c2ecf20Sopenharmony_ci	"Menu Item 3",
2098c2ecf20Sopenharmony_ci	"Menu Item 4",
2108c2ecf20Sopenharmony_ci	"Menu Item 5 (Skipped)",
2118c2ecf20Sopenharmony_ci	NULL,
2128c2ecf20Sopenharmony_ci};
2138c2ecf20Sopenharmony_ci
2148c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_menu = {
2158c2ecf20Sopenharmony_ci	.ops = &vivid_user_gen_ctrl_ops,
2168c2ecf20Sopenharmony_ci	.id = VIVID_CID_MENU,
2178c2ecf20Sopenharmony_ci	.name = "Menu",
2188c2ecf20Sopenharmony_ci	.type = V4L2_CTRL_TYPE_MENU,
2198c2ecf20Sopenharmony_ci	.min = 1,
2208c2ecf20Sopenharmony_ci	.max = 4,
2218c2ecf20Sopenharmony_ci	.def = 3,
2228c2ecf20Sopenharmony_ci	.menu_skip_mask = 0x04,
2238c2ecf20Sopenharmony_ci	.qmenu = vivid_ctrl_menu_strings,
2248c2ecf20Sopenharmony_ci};
2258c2ecf20Sopenharmony_ci
2268c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_string = {
2278c2ecf20Sopenharmony_ci	.ops = &vivid_user_gen_ctrl_ops,
2288c2ecf20Sopenharmony_ci	.id = VIVID_CID_STRING,
2298c2ecf20Sopenharmony_ci	.name = "String",
2308c2ecf20Sopenharmony_ci	.type = V4L2_CTRL_TYPE_STRING,
2318c2ecf20Sopenharmony_ci	.min = 2,
2328c2ecf20Sopenharmony_ci	.max = 4,
2338c2ecf20Sopenharmony_ci	.step = 1,
2348c2ecf20Sopenharmony_ci};
2358c2ecf20Sopenharmony_ci
2368c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_bitmask = {
2378c2ecf20Sopenharmony_ci	.ops = &vivid_user_gen_ctrl_ops,
2388c2ecf20Sopenharmony_ci	.id = VIVID_CID_BITMASK,
2398c2ecf20Sopenharmony_ci	.name = "Bitmask",
2408c2ecf20Sopenharmony_ci	.type = V4L2_CTRL_TYPE_BITMASK,
2418c2ecf20Sopenharmony_ci	.def = 0x80002000,
2428c2ecf20Sopenharmony_ci	.min = 0,
2438c2ecf20Sopenharmony_ci	.max = 0x80402010,
2448c2ecf20Sopenharmony_ci	.step = 0,
2458c2ecf20Sopenharmony_ci};
2468c2ecf20Sopenharmony_ci
2478c2ecf20Sopenharmony_cistatic const s64 vivid_ctrl_int_menu_values[] = {
2488c2ecf20Sopenharmony_ci	1, 1, 2, 3, 5, 8, 13, 21, 42,
2498c2ecf20Sopenharmony_ci};
2508c2ecf20Sopenharmony_ci
2518c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_int_menu = {
2528c2ecf20Sopenharmony_ci	.ops = &vivid_user_gen_ctrl_ops,
2538c2ecf20Sopenharmony_ci	.id = VIVID_CID_INTMENU,
2548c2ecf20Sopenharmony_ci	.name = "Integer Menu",
2558c2ecf20Sopenharmony_ci	.type = V4L2_CTRL_TYPE_INTEGER_MENU,
2568c2ecf20Sopenharmony_ci	.min = 1,
2578c2ecf20Sopenharmony_ci	.max = 8,
2588c2ecf20Sopenharmony_ci	.def = 4,
2598c2ecf20Sopenharmony_ci	.menu_skip_mask = 0x02,
2608c2ecf20Sopenharmony_ci	.qmenu_int = vivid_ctrl_int_menu_values,
2618c2ecf20Sopenharmony_ci};
2628c2ecf20Sopenharmony_ci
2638c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_disconnect = {
2648c2ecf20Sopenharmony_ci	.ops = &vivid_user_gen_ctrl_ops,
2658c2ecf20Sopenharmony_ci	.id = VIVID_CID_DISCONNECT,
2668c2ecf20Sopenharmony_ci	.name = "Disconnect",
2678c2ecf20Sopenharmony_ci	.type = V4L2_CTRL_TYPE_BUTTON,
2688c2ecf20Sopenharmony_ci};
2698c2ecf20Sopenharmony_ci
2708c2ecf20Sopenharmony_cistatic const struct v4l2_area area = {
2718c2ecf20Sopenharmony_ci	.width = 1000,
2728c2ecf20Sopenharmony_ci	.height = 2000,
2738c2ecf20Sopenharmony_ci};
2748c2ecf20Sopenharmony_ci
2758c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_area = {
2768c2ecf20Sopenharmony_ci	.ops = &vivid_user_gen_ctrl_ops,
2778c2ecf20Sopenharmony_ci	.id = VIVID_CID_AREA,
2788c2ecf20Sopenharmony_ci	.name = "Area",
2798c2ecf20Sopenharmony_ci	.type = V4L2_CTRL_TYPE_AREA,
2808c2ecf20Sopenharmony_ci	.p_def.p_const = &area,
2818c2ecf20Sopenharmony_ci};
2828c2ecf20Sopenharmony_ci
2838c2ecf20Sopenharmony_ci/* Framebuffer Controls */
2848c2ecf20Sopenharmony_ci
2858c2ecf20Sopenharmony_cistatic int vivid_fb_s_ctrl(struct v4l2_ctrl *ctrl)
2868c2ecf20Sopenharmony_ci{
2878c2ecf20Sopenharmony_ci	struct vivid_dev *dev = container_of(ctrl->handler,
2888c2ecf20Sopenharmony_ci					     struct vivid_dev, ctrl_hdl_fb);
2898c2ecf20Sopenharmony_ci
2908c2ecf20Sopenharmony_ci	switch (ctrl->id) {
2918c2ecf20Sopenharmony_ci	case VIVID_CID_CLEAR_FB:
2928c2ecf20Sopenharmony_ci		vivid_clear_fb(dev);
2938c2ecf20Sopenharmony_ci		break;
2948c2ecf20Sopenharmony_ci	}
2958c2ecf20Sopenharmony_ci	return 0;
2968c2ecf20Sopenharmony_ci}
2978c2ecf20Sopenharmony_ci
2988c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_ops vivid_fb_ctrl_ops = {
2998c2ecf20Sopenharmony_ci	.s_ctrl = vivid_fb_s_ctrl,
3008c2ecf20Sopenharmony_ci};
3018c2ecf20Sopenharmony_ci
3028c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_clear_fb = {
3038c2ecf20Sopenharmony_ci	.ops = &vivid_fb_ctrl_ops,
3048c2ecf20Sopenharmony_ci	.id = VIVID_CID_CLEAR_FB,
3058c2ecf20Sopenharmony_ci	.name = "Clear Framebuffer",
3068c2ecf20Sopenharmony_ci	.type = V4L2_CTRL_TYPE_BUTTON,
3078c2ecf20Sopenharmony_ci};
3088c2ecf20Sopenharmony_ci
3098c2ecf20Sopenharmony_ci
3108c2ecf20Sopenharmony_ci/* Video User Controls */
3118c2ecf20Sopenharmony_ci
3128c2ecf20Sopenharmony_cistatic int vivid_user_vid_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
3138c2ecf20Sopenharmony_ci{
3148c2ecf20Sopenharmony_ci	struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_user_vid);
3158c2ecf20Sopenharmony_ci
3168c2ecf20Sopenharmony_ci	switch (ctrl->id) {
3178c2ecf20Sopenharmony_ci	case V4L2_CID_AUTOGAIN:
3188c2ecf20Sopenharmony_ci		dev->gain->val = (jiffies_to_msecs(jiffies) / 1000) & 0xff;
3198c2ecf20Sopenharmony_ci		break;
3208c2ecf20Sopenharmony_ci	}
3218c2ecf20Sopenharmony_ci	return 0;
3228c2ecf20Sopenharmony_ci}
3238c2ecf20Sopenharmony_ci
3248c2ecf20Sopenharmony_cistatic int vivid_user_vid_s_ctrl(struct v4l2_ctrl *ctrl)
3258c2ecf20Sopenharmony_ci{
3268c2ecf20Sopenharmony_ci	struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_user_vid);
3278c2ecf20Sopenharmony_ci
3288c2ecf20Sopenharmony_ci	switch (ctrl->id) {
3298c2ecf20Sopenharmony_ci	case V4L2_CID_BRIGHTNESS:
3308c2ecf20Sopenharmony_ci		dev->input_brightness[dev->input] = ctrl->val - dev->input * 128;
3318c2ecf20Sopenharmony_ci		tpg_s_brightness(&dev->tpg, dev->input_brightness[dev->input]);
3328c2ecf20Sopenharmony_ci		break;
3338c2ecf20Sopenharmony_ci	case V4L2_CID_CONTRAST:
3348c2ecf20Sopenharmony_ci		tpg_s_contrast(&dev->tpg, ctrl->val);
3358c2ecf20Sopenharmony_ci		break;
3368c2ecf20Sopenharmony_ci	case V4L2_CID_SATURATION:
3378c2ecf20Sopenharmony_ci		tpg_s_saturation(&dev->tpg, ctrl->val);
3388c2ecf20Sopenharmony_ci		break;
3398c2ecf20Sopenharmony_ci	case V4L2_CID_HUE:
3408c2ecf20Sopenharmony_ci		tpg_s_hue(&dev->tpg, ctrl->val);
3418c2ecf20Sopenharmony_ci		break;
3428c2ecf20Sopenharmony_ci	case V4L2_CID_HFLIP:
3438c2ecf20Sopenharmony_ci		dev->hflip = ctrl->val;
3448c2ecf20Sopenharmony_ci		tpg_s_hflip(&dev->tpg, dev->sensor_hflip ^ dev->hflip);
3458c2ecf20Sopenharmony_ci		break;
3468c2ecf20Sopenharmony_ci	case V4L2_CID_VFLIP:
3478c2ecf20Sopenharmony_ci		dev->vflip = ctrl->val;
3488c2ecf20Sopenharmony_ci		tpg_s_vflip(&dev->tpg, dev->sensor_vflip ^ dev->vflip);
3498c2ecf20Sopenharmony_ci		break;
3508c2ecf20Sopenharmony_ci	case V4L2_CID_ALPHA_COMPONENT:
3518c2ecf20Sopenharmony_ci		tpg_s_alpha_component(&dev->tpg, ctrl->val);
3528c2ecf20Sopenharmony_ci		break;
3538c2ecf20Sopenharmony_ci	}
3548c2ecf20Sopenharmony_ci	return 0;
3558c2ecf20Sopenharmony_ci}
3568c2ecf20Sopenharmony_ci
3578c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_ops vivid_user_vid_ctrl_ops = {
3588c2ecf20Sopenharmony_ci	.g_volatile_ctrl = vivid_user_vid_g_volatile_ctrl,
3598c2ecf20Sopenharmony_ci	.s_ctrl = vivid_user_vid_s_ctrl,
3608c2ecf20Sopenharmony_ci};
3618c2ecf20Sopenharmony_ci
3628c2ecf20Sopenharmony_ci
3638c2ecf20Sopenharmony_ci/* Video Capture Controls */
3648c2ecf20Sopenharmony_ci
3658c2ecf20Sopenharmony_cistatic int vivid_vid_cap_s_ctrl(struct v4l2_ctrl *ctrl)
3668c2ecf20Sopenharmony_ci{
3678c2ecf20Sopenharmony_ci	static const u32 colorspaces[] = {
3688c2ecf20Sopenharmony_ci		V4L2_COLORSPACE_SMPTE170M,
3698c2ecf20Sopenharmony_ci		V4L2_COLORSPACE_REC709,
3708c2ecf20Sopenharmony_ci		V4L2_COLORSPACE_SRGB,
3718c2ecf20Sopenharmony_ci		V4L2_COLORSPACE_OPRGB,
3728c2ecf20Sopenharmony_ci		V4L2_COLORSPACE_BT2020,
3738c2ecf20Sopenharmony_ci		V4L2_COLORSPACE_DCI_P3,
3748c2ecf20Sopenharmony_ci		V4L2_COLORSPACE_SMPTE240M,
3758c2ecf20Sopenharmony_ci		V4L2_COLORSPACE_470_SYSTEM_M,
3768c2ecf20Sopenharmony_ci		V4L2_COLORSPACE_470_SYSTEM_BG,
3778c2ecf20Sopenharmony_ci	};
3788c2ecf20Sopenharmony_ci	struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_vid_cap);
3798c2ecf20Sopenharmony_ci	unsigned int i, j;
3808c2ecf20Sopenharmony_ci
3818c2ecf20Sopenharmony_ci	switch (ctrl->id) {
3828c2ecf20Sopenharmony_ci	case VIVID_CID_TEST_PATTERN:
3838c2ecf20Sopenharmony_ci		vivid_update_quality(dev);
3848c2ecf20Sopenharmony_ci		tpg_s_pattern(&dev->tpg, ctrl->val);
3858c2ecf20Sopenharmony_ci		break;
3868c2ecf20Sopenharmony_ci	case VIVID_CID_COLORSPACE:
3878c2ecf20Sopenharmony_ci		tpg_s_colorspace(&dev->tpg, colorspaces[ctrl->val]);
3888c2ecf20Sopenharmony_ci		vivid_send_source_change(dev, TV);
3898c2ecf20Sopenharmony_ci		vivid_send_source_change(dev, SVID);
3908c2ecf20Sopenharmony_ci		vivid_send_source_change(dev, HDMI);
3918c2ecf20Sopenharmony_ci		vivid_send_source_change(dev, WEBCAM);
3928c2ecf20Sopenharmony_ci		break;
3938c2ecf20Sopenharmony_ci	case VIVID_CID_XFER_FUNC:
3948c2ecf20Sopenharmony_ci		tpg_s_xfer_func(&dev->tpg, ctrl->val);
3958c2ecf20Sopenharmony_ci		vivid_send_source_change(dev, TV);
3968c2ecf20Sopenharmony_ci		vivid_send_source_change(dev, SVID);
3978c2ecf20Sopenharmony_ci		vivid_send_source_change(dev, HDMI);
3988c2ecf20Sopenharmony_ci		vivid_send_source_change(dev, WEBCAM);
3998c2ecf20Sopenharmony_ci		break;
4008c2ecf20Sopenharmony_ci	case VIVID_CID_YCBCR_ENC:
4018c2ecf20Sopenharmony_ci		tpg_s_ycbcr_enc(&dev->tpg, ctrl->val);
4028c2ecf20Sopenharmony_ci		vivid_send_source_change(dev, TV);
4038c2ecf20Sopenharmony_ci		vivid_send_source_change(dev, SVID);
4048c2ecf20Sopenharmony_ci		vivid_send_source_change(dev, HDMI);
4058c2ecf20Sopenharmony_ci		vivid_send_source_change(dev, WEBCAM);
4068c2ecf20Sopenharmony_ci		break;
4078c2ecf20Sopenharmony_ci	case VIVID_CID_HSV_ENC:
4088c2ecf20Sopenharmony_ci		tpg_s_hsv_enc(&dev->tpg, ctrl->val ? V4L2_HSV_ENC_256 :
4098c2ecf20Sopenharmony_ci						     V4L2_HSV_ENC_180);
4108c2ecf20Sopenharmony_ci		vivid_send_source_change(dev, TV);
4118c2ecf20Sopenharmony_ci		vivid_send_source_change(dev, SVID);
4128c2ecf20Sopenharmony_ci		vivid_send_source_change(dev, HDMI);
4138c2ecf20Sopenharmony_ci		vivid_send_source_change(dev, WEBCAM);
4148c2ecf20Sopenharmony_ci		break;
4158c2ecf20Sopenharmony_ci	case VIVID_CID_QUANTIZATION:
4168c2ecf20Sopenharmony_ci		tpg_s_quantization(&dev->tpg, ctrl->val);
4178c2ecf20Sopenharmony_ci		vivid_send_source_change(dev, TV);
4188c2ecf20Sopenharmony_ci		vivid_send_source_change(dev, SVID);
4198c2ecf20Sopenharmony_ci		vivid_send_source_change(dev, HDMI);
4208c2ecf20Sopenharmony_ci		vivid_send_source_change(dev, WEBCAM);
4218c2ecf20Sopenharmony_ci		break;
4228c2ecf20Sopenharmony_ci	case V4L2_CID_DV_RX_RGB_RANGE:
4238c2ecf20Sopenharmony_ci		if (!vivid_is_hdmi_cap(dev))
4248c2ecf20Sopenharmony_ci			break;
4258c2ecf20Sopenharmony_ci		tpg_s_rgb_range(&dev->tpg, ctrl->val);
4268c2ecf20Sopenharmony_ci		break;
4278c2ecf20Sopenharmony_ci	case VIVID_CID_LIMITED_RGB_RANGE:
4288c2ecf20Sopenharmony_ci		tpg_s_real_rgb_range(&dev->tpg, ctrl->val ?
4298c2ecf20Sopenharmony_ci				V4L2_DV_RGB_RANGE_LIMITED : V4L2_DV_RGB_RANGE_FULL);
4308c2ecf20Sopenharmony_ci		break;
4318c2ecf20Sopenharmony_ci	case VIVID_CID_ALPHA_MODE:
4328c2ecf20Sopenharmony_ci		tpg_s_alpha_mode(&dev->tpg, ctrl->val);
4338c2ecf20Sopenharmony_ci		break;
4348c2ecf20Sopenharmony_ci	case VIVID_CID_HOR_MOVEMENT:
4358c2ecf20Sopenharmony_ci		tpg_s_mv_hor_mode(&dev->tpg, ctrl->val);
4368c2ecf20Sopenharmony_ci		break;
4378c2ecf20Sopenharmony_ci	case VIVID_CID_VERT_MOVEMENT:
4388c2ecf20Sopenharmony_ci		tpg_s_mv_vert_mode(&dev->tpg, ctrl->val);
4398c2ecf20Sopenharmony_ci		break;
4408c2ecf20Sopenharmony_ci	case VIVID_CID_OSD_TEXT_MODE:
4418c2ecf20Sopenharmony_ci		dev->osd_mode = ctrl->val;
4428c2ecf20Sopenharmony_ci		break;
4438c2ecf20Sopenharmony_ci	case VIVID_CID_PERCENTAGE_FILL:
4448c2ecf20Sopenharmony_ci		tpg_s_perc_fill(&dev->tpg, ctrl->val);
4458c2ecf20Sopenharmony_ci		for (i = 0; i < VIDEO_MAX_FRAME; i++)
4468c2ecf20Sopenharmony_ci			dev->must_blank[i] = ctrl->val < 100;
4478c2ecf20Sopenharmony_ci		break;
4488c2ecf20Sopenharmony_ci	case VIVID_CID_INSERT_SAV:
4498c2ecf20Sopenharmony_ci		tpg_s_insert_sav(&dev->tpg, ctrl->val);
4508c2ecf20Sopenharmony_ci		break;
4518c2ecf20Sopenharmony_ci	case VIVID_CID_INSERT_EAV:
4528c2ecf20Sopenharmony_ci		tpg_s_insert_eav(&dev->tpg, ctrl->val);
4538c2ecf20Sopenharmony_ci		break;
4548c2ecf20Sopenharmony_ci	case VIVID_CID_HFLIP:
4558c2ecf20Sopenharmony_ci		dev->sensor_hflip = ctrl->val;
4568c2ecf20Sopenharmony_ci		tpg_s_hflip(&dev->tpg, dev->sensor_hflip ^ dev->hflip);
4578c2ecf20Sopenharmony_ci		break;
4588c2ecf20Sopenharmony_ci	case VIVID_CID_VFLIP:
4598c2ecf20Sopenharmony_ci		dev->sensor_vflip = ctrl->val;
4608c2ecf20Sopenharmony_ci		tpg_s_vflip(&dev->tpg, dev->sensor_vflip ^ dev->vflip);
4618c2ecf20Sopenharmony_ci		break;
4628c2ecf20Sopenharmony_ci	case VIVID_CID_REDUCED_FPS:
4638c2ecf20Sopenharmony_ci		dev->reduced_fps = ctrl->val;
4648c2ecf20Sopenharmony_ci		vivid_update_format_cap(dev, true);
4658c2ecf20Sopenharmony_ci		break;
4668c2ecf20Sopenharmony_ci	case VIVID_CID_HAS_CROP_CAP:
4678c2ecf20Sopenharmony_ci		dev->has_crop_cap = ctrl->val;
4688c2ecf20Sopenharmony_ci		vivid_update_format_cap(dev, true);
4698c2ecf20Sopenharmony_ci		break;
4708c2ecf20Sopenharmony_ci	case VIVID_CID_HAS_COMPOSE_CAP:
4718c2ecf20Sopenharmony_ci		dev->has_compose_cap = ctrl->val;
4728c2ecf20Sopenharmony_ci		vivid_update_format_cap(dev, true);
4738c2ecf20Sopenharmony_ci		break;
4748c2ecf20Sopenharmony_ci	case VIVID_CID_HAS_SCALER_CAP:
4758c2ecf20Sopenharmony_ci		dev->has_scaler_cap = ctrl->val;
4768c2ecf20Sopenharmony_ci		vivid_update_format_cap(dev, true);
4778c2ecf20Sopenharmony_ci		break;
4788c2ecf20Sopenharmony_ci	case VIVID_CID_SHOW_BORDER:
4798c2ecf20Sopenharmony_ci		tpg_s_show_border(&dev->tpg, ctrl->val);
4808c2ecf20Sopenharmony_ci		break;
4818c2ecf20Sopenharmony_ci	case VIVID_CID_SHOW_SQUARE:
4828c2ecf20Sopenharmony_ci		tpg_s_show_square(&dev->tpg, ctrl->val);
4838c2ecf20Sopenharmony_ci		break;
4848c2ecf20Sopenharmony_ci	case VIVID_CID_STD_ASPECT_RATIO:
4858c2ecf20Sopenharmony_ci		dev->std_aspect_ratio[dev->input] = ctrl->val;
4868c2ecf20Sopenharmony_ci		tpg_s_video_aspect(&dev->tpg, vivid_get_video_aspect(dev));
4878c2ecf20Sopenharmony_ci		break;
4888c2ecf20Sopenharmony_ci	case VIVID_CID_DV_TIMINGS_SIGNAL_MODE:
4898c2ecf20Sopenharmony_ci		dev->dv_timings_signal_mode[dev->input] =
4908c2ecf20Sopenharmony_ci			dev->ctrl_dv_timings_signal_mode->val;
4918c2ecf20Sopenharmony_ci		dev->query_dv_timings[dev->input] = dev->ctrl_dv_timings->val;
4928c2ecf20Sopenharmony_ci
4938c2ecf20Sopenharmony_ci		dev->power_present = 0;
4948c2ecf20Sopenharmony_ci		for (i = 0, j = 0;
4958c2ecf20Sopenharmony_ci		     i < ARRAY_SIZE(dev->dv_timings_signal_mode);
4968c2ecf20Sopenharmony_ci		     i++)
4978c2ecf20Sopenharmony_ci			if (dev->input_type[i] == HDMI) {
4988c2ecf20Sopenharmony_ci				if (dev->dv_timings_signal_mode[i] != NO_SIGNAL)
4998c2ecf20Sopenharmony_ci					dev->power_present |= (1 << j);
5008c2ecf20Sopenharmony_ci				j++;
5018c2ecf20Sopenharmony_ci			}
5028c2ecf20Sopenharmony_ci		__v4l2_ctrl_s_ctrl(dev->ctrl_rx_power_present,
5038c2ecf20Sopenharmony_ci				   dev->power_present);
5048c2ecf20Sopenharmony_ci
5058c2ecf20Sopenharmony_ci		v4l2_ctrl_activate(dev->ctrl_dv_timings,
5068c2ecf20Sopenharmony_ci			dev->dv_timings_signal_mode[dev->input] ==
5078c2ecf20Sopenharmony_ci				SELECTED_DV_TIMINGS);
5088c2ecf20Sopenharmony_ci
5098c2ecf20Sopenharmony_ci		vivid_update_quality(dev);
5108c2ecf20Sopenharmony_ci		vivid_send_source_change(dev, HDMI);
5118c2ecf20Sopenharmony_ci		break;
5128c2ecf20Sopenharmony_ci	case VIVID_CID_DV_TIMINGS_ASPECT_RATIO:
5138c2ecf20Sopenharmony_ci		dev->dv_timings_aspect_ratio[dev->input] = ctrl->val;
5148c2ecf20Sopenharmony_ci		tpg_s_video_aspect(&dev->tpg, vivid_get_video_aspect(dev));
5158c2ecf20Sopenharmony_ci		break;
5168c2ecf20Sopenharmony_ci	case VIVID_CID_TSTAMP_SRC:
5178c2ecf20Sopenharmony_ci		dev->tstamp_src_is_soe = ctrl->val;
5188c2ecf20Sopenharmony_ci		dev->vb_vid_cap_q.timestamp_flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
5198c2ecf20Sopenharmony_ci		if (dev->tstamp_src_is_soe)
5208c2ecf20Sopenharmony_ci			dev->vb_vid_cap_q.timestamp_flags |= V4L2_BUF_FLAG_TSTAMP_SRC_SOE;
5218c2ecf20Sopenharmony_ci		break;
5228c2ecf20Sopenharmony_ci	case VIVID_CID_MAX_EDID_BLOCKS:
5238c2ecf20Sopenharmony_ci		dev->edid_max_blocks = ctrl->val;
5248c2ecf20Sopenharmony_ci		if (dev->edid_blocks > dev->edid_max_blocks)
5258c2ecf20Sopenharmony_ci			dev->edid_blocks = dev->edid_max_blocks;
5268c2ecf20Sopenharmony_ci		break;
5278c2ecf20Sopenharmony_ci	}
5288c2ecf20Sopenharmony_ci	return 0;
5298c2ecf20Sopenharmony_ci}
5308c2ecf20Sopenharmony_ci
5318c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_ops vivid_vid_cap_ctrl_ops = {
5328c2ecf20Sopenharmony_ci	.s_ctrl = vivid_vid_cap_s_ctrl,
5338c2ecf20Sopenharmony_ci};
5348c2ecf20Sopenharmony_ci
5358c2ecf20Sopenharmony_cistatic const char * const vivid_ctrl_hor_movement_strings[] = {
5368c2ecf20Sopenharmony_ci	"Move Left Fast",
5378c2ecf20Sopenharmony_ci	"Move Left",
5388c2ecf20Sopenharmony_ci	"Move Left Slow",
5398c2ecf20Sopenharmony_ci	"No Movement",
5408c2ecf20Sopenharmony_ci	"Move Right Slow",
5418c2ecf20Sopenharmony_ci	"Move Right",
5428c2ecf20Sopenharmony_ci	"Move Right Fast",
5438c2ecf20Sopenharmony_ci	NULL,
5448c2ecf20Sopenharmony_ci};
5458c2ecf20Sopenharmony_ci
5468c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_hor_movement = {
5478c2ecf20Sopenharmony_ci	.ops = &vivid_vid_cap_ctrl_ops,
5488c2ecf20Sopenharmony_ci	.id = VIVID_CID_HOR_MOVEMENT,
5498c2ecf20Sopenharmony_ci	.name = "Horizontal Movement",
5508c2ecf20Sopenharmony_ci	.type = V4L2_CTRL_TYPE_MENU,
5518c2ecf20Sopenharmony_ci	.max = TPG_MOVE_POS_FAST,
5528c2ecf20Sopenharmony_ci	.def = TPG_MOVE_NONE,
5538c2ecf20Sopenharmony_ci	.qmenu = vivid_ctrl_hor_movement_strings,
5548c2ecf20Sopenharmony_ci};
5558c2ecf20Sopenharmony_ci
5568c2ecf20Sopenharmony_cistatic const char * const vivid_ctrl_vert_movement_strings[] = {
5578c2ecf20Sopenharmony_ci	"Move Up Fast",
5588c2ecf20Sopenharmony_ci	"Move Up",
5598c2ecf20Sopenharmony_ci	"Move Up Slow",
5608c2ecf20Sopenharmony_ci	"No Movement",
5618c2ecf20Sopenharmony_ci	"Move Down Slow",
5628c2ecf20Sopenharmony_ci	"Move Down",
5638c2ecf20Sopenharmony_ci	"Move Down Fast",
5648c2ecf20Sopenharmony_ci	NULL,
5658c2ecf20Sopenharmony_ci};
5668c2ecf20Sopenharmony_ci
5678c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_vert_movement = {
5688c2ecf20Sopenharmony_ci	.ops = &vivid_vid_cap_ctrl_ops,
5698c2ecf20Sopenharmony_ci	.id = VIVID_CID_VERT_MOVEMENT,
5708c2ecf20Sopenharmony_ci	.name = "Vertical Movement",
5718c2ecf20Sopenharmony_ci	.type = V4L2_CTRL_TYPE_MENU,
5728c2ecf20Sopenharmony_ci	.max = TPG_MOVE_POS_FAST,
5738c2ecf20Sopenharmony_ci	.def = TPG_MOVE_NONE,
5748c2ecf20Sopenharmony_ci	.qmenu = vivid_ctrl_vert_movement_strings,
5758c2ecf20Sopenharmony_ci};
5768c2ecf20Sopenharmony_ci
5778c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_show_border = {
5788c2ecf20Sopenharmony_ci	.ops = &vivid_vid_cap_ctrl_ops,
5798c2ecf20Sopenharmony_ci	.id = VIVID_CID_SHOW_BORDER,
5808c2ecf20Sopenharmony_ci	.name = "Show Border",
5818c2ecf20Sopenharmony_ci	.type = V4L2_CTRL_TYPE_BOOLEAN,
5828c2ecf20Sopenharmony_ci	.max = 1,
5838c2ecf20Sopenharmony_ci	.step = 1,
5848c2ecf20Sopenharmony_ci};
5858c2ecf20Sopenharmony_ci
5868c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_show_square = {
5878c2ecf20Sopenharmony_ci	.ops = &vivid_vid_cap_ctrl_ops,
5888c2ecf20Sopenharmony_ci	.id = VIVID_CID_SHOW_SQUARE,
5898c2ecf20Sopenharmony_ci	.name = "Show Square",
5908c2ecf20Sopenharmony_ci	.type = V4L2_CTRL_TYPE_BOOLEAN,
5918c2ecf20Sopenharmony_ci	.max = 1,
5928c2ecf20Sopenharmony_ci	.step = 1,
5938c2ecf20Sopenharmony_ci};
5948c2ecf20Sopenharmony_ci
5958c2ecf20Sopenharmony_cistatic const char * const vivid_ctrl_osd_mode_strings[] = {
5968c2ecf20Sopenharmony_ci	"All",
5978c2ecf20Sopenharmony_ci	"Counters Only",
5988c2ecf20Sopenharmony_ci	"None",
5998c2ecf20Sopenharmony_ci	NULL,
6008c2ecf20Sopenharmony_ci};
6018c2ecf20Sopenharmony_ci
6028c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_osd_mode = {
6038c2ecf20Sopenharmony_ci	.ops = &vivid_vid_cap_ctrl_ops,
6048c2ecf20Sopenharmony_ci	.id = VIVID_CID_OSD_TEXT_MODE,
6058c2ecf20Sopenharmony_ci	.name = "OSD Text Mode",
6068c2ecf20Sopenharmony_ci	.type = V4L2_CTRL_TYPE_MENU,
6078c2ecf20Sopenharmony_ci	.max = ARRAY_SIZE(vivid_ctrl_osd_mode_strings) - 2,
6088c2ecf20Sopenharmony_ci	.qmenu = vivid_ctrl_osd_mode_strings,
6098c2ecf20Sopenharmony_ci};
6108c2ecf20Sopenharmony_ci
6118c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_perc_fill = {
6128c2ecf20Sopenharmony_ci	.ops = &vivid_vid_cap_ctrl_ops,
6138c2ecf20Sopenharmony_ci	.id = VIVID_CID_PERCENTAGE_FILL,
6148c2ecf20Sopenharmony_ci	.name = "Fill Percentage of Frame",
6158c2ecf20Sopenharmony_ci	.type = V4L2_CTRL_TYPE_INTEGER,
6168c2ecf20Sopenharmony_ci	.min = 0,
6178c2ecf20Sopenharmony_ci	.max = 100,
6188c2ecf20Sopenharmony_ci	.def = 100,
6198c2ecf20Sopenharmony_ci	.step = 1,
6208c2ecf20Sopenharmony_ci};
6218c2ecf20Sopenharmony_ci
6228c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_insert_sav = {
6238c2ecf20Sopenharmony_ci	.ops = &vivid_vid_cap_ctrl_ops,
6248c2ecf20Sopenharmony_ci	.id = VIVID_CID_INSERT_SAV,
6258c2ecf20Sopenharmony_ci	.name = "Insert SAV Code in Image",
6268c2ecf20Sopenharmony_ci	.type = V4L2_CTRL_TYPE_BOOLEAN,
6278c2ecf20Sopenharmony_ci	.max = 1,
6288c2ecf20Sopenharmony_ci	.step = 1,
6298c2ecf20Sopenharmony_ci};
6308c2ecf20Sopenharmony_ci
6318c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_insert_eav = {
6328c2ecf20Sopenharmony_ci	.ops = &vivid_vid_cap_ctrl_ops,
6338c2ecf20Sopenharmony_ci	.id = VIVID_CID_INSERT_EAV,
6348c2ecf20Sopenharmony_ci	.name = "Insert EAV Code in Image",
6358c2ecf20Sopenharmony_ci	.type = V4L2_CTRL_TYPE_BOOLEAN,
6368c2ecf20Sopenharmony_ci	.max = 1,
6378c2ecf20Sopenharmony_ci	.step = 1,
6388c2ecf20Sopenharmony_ci};
6398c2ecf20Sopenharmony_ci
6408c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_hflip = {
6418c2ecf20Sopenharmony_ci	.ops = &vivid_vid_cap_ctrl_ops,
6428c2ecf20Sopenharmony_ci	.id = VIVID_CID_HFLIP,
6438c2ecf20Sopenharmony_ci	.name = "Sensor Flipped Horizontally",
6448c2ecf20Sopenharmony_ci	.type = V4L2_CTRL_TYPE_BOOLEAN,
6458c2ecf20Sopenharmony_ci	.max = 1,
6468c2ecf20Sopenharmony_ci	.step = 1,
6478c2ecf20Sopenharmony_ci};
6488c2ecf20Sopenharmony_ci
6498c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_vflip = {
6508c2ecf20Sopenharmony_ci	.ops = &vivid_vid_cap_ctrl_ops,
6518c2ecf20Sopenharmony_ci	.id = VIVID_CID_VFLIP,
6528c2ecf20Sopenharmony_ci	.name = "Sensor Flipped Vertically",
6538c2ecf20Sopenharmony_ci	.type = V4L2_CTRL_TYPE_BOOLEAN,
6548c2ecf20Sopenharmony_ci	.max = 1,
6558c2ecf20Sopenharmony_ci	.step = 1,
6568c2ecf20Sopenharmony_ci};
6578c2ecf20Sopenharmony_ci
6588c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_reduced_fps = {
6598c2ecf20Sopenharmony_ci	.ops = &vivid_vid_cap_ctrl_ops,
6608c2ecf20Sopenharmony_ci	.id = VIVID_CID_REDUCED_FPS,
6618c2ecf20Sopenharmony_ci	.name = "Reduced Framerate",
6628c2ecf20Sopenharmony_ci	.type = V4L2_CTRL_TYPE_BOOLEAN,
6638c2ecf20Sopenharmony_ci	.max = 1,
6648c2ecf20Sopenharmony_ci	.step = 1,
6658c2ecf20Sopenharmony_ci};
6668c2ecf20Sopenharmony_ci
6678c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_has_crop_cap = {
6688c2ecf20Sopenharmony_ci	.ops = &vivid_vid_cap_ctrl_ops,
6698c2ecf20Sopenharmony_ci	.id = VIVID_CID_HAS_CROP_CAP,
6708c2ecf20Sopenharmony_ci	.name = "Enable Capture Cropping",
6718c2ecf20Sopenharmony_ci	.type = V4L2_CTRL_TYPE_BOOLEAN,
6728c2ecf20Sopenharmony_ci	.max = 1,
6738c2ecf20Sopenharmony_ci	.def = 1,
6748c2ecf20Sopenharmony_ci	.step = 1,
6758c2ecf20Sopenharmony_ci};
6768c2ecf20Sopenharmony_ci
6778c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_has_compose_cap = {
6788c2ecf20Sopenharmony_ci	.ops = &vivid_vid_cap_ctrl_ops,
6798c2ecf20Sopenharmony_ci	.id = VIVID_CID_HAS_COMPOSE_CAP,
6808c2ecf20Sopenharmony_ci	.name = "Enable Capture Composing",
6818c2ecf20Sopenharmony_ci	.type = V4L2_CTRL_TYPE_BOOLEAN,
6828c2ecf20Sopenharmony_ci	.max = 1,
6838c2ecf20Sopenharmony_ci	.def = 1,
6848c2ecf20Sopenharmony_ci	.step = 1,
6858c2ecf20Sopenharmony_ci};
6868c2ecf20Sopenharmony_ci
6878c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_has_scaler_cap = {
6888c2ecf20Sopenharmony_ci	.ops = &vivid_vid_cap_ctrl_ops,
6898c2ecf20Sopenharmony_ci	.id = VIVID_CID_HAS_SCALER_CAP,
6908c2ecf20Sopenharmony_ci	.name = "Enable Capture Scaler",
6918c2ecf20Sopenharmony_ci	.type = V4L2_CTRL_TYPE_BOOLEAN,
6928c2ecf20Sopenharmony_ci	.max = 1,
6938c2ecf20Sopenharmony_ci	.def = 1,
6948c2ecf20Sopenharmony_ci	.step = 1,
6958c2ecf20Sopenharmony_ci};
6968c2ecf20Sopenharmony_ci
6978c2ecf20Sopenharmony_cistatic const char * const vivid_ctrl_tstamp_src_strings[] = {
6988c2ecf20Sopenharmony_ci	"End of Frame",
6998c2ecf20Sopenharmony_ci	"Start of Exposure",
7008c2ecf20Sopenharmony_ci	NULL,
7018c2ecf20Sopenharmony_ci};
7028c2ecf20Sopenharmony_ci
7038c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_tstamp_src = {
7048c2ecf20Sopenharmony_ci	.ops = &vivid_vid_cap_ctrl_ops,
7058c2ecf20Sopenharmony_ci	.id = VIVID_CID_TSTAMP_SRC,
7068c2ecf20Sopenharmony_ci	.name = "Timestamp Source",
7078c2ecf20Sopenharmony_ci	.type = V4L2_CTRL_TYPE_MENU,
7088c2ecf20Sopenharmony_ci	.max = ARRAY_SIZE(vivid_ctrl_tstamp_src_strings) - 2,
7098c2ecf20Sopenharmony_ci	.qmenu = vivid_ctrl_tstamp_src_strings,
7108c2ecf20Sopenharmony_ci};
7118c2ecf20Sopenharmony_ci
7128c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_std_aspect_ratio = {
7138c2ecf20Sopenharmony_ci	.ops = &vivid_vid_cap_ctrl_ops,
7148c2ecf20Sopenharmony_ci	.id = VIVID_CID_STD_ASPECT_RATIO,
7158c2ecf20Sopenharmony_ci	.name = "Standard Aspect Ratio",
7168c2ecf20Sopenharmony_ci	.type = V4L2_CTRL_TYPE_MENU,
7178c2ecf20Sopenharmony_ci	.min = 1,
7188c2ecf20Sopenharmony_ci	.max = 4,
7198c2ecf20Sopenharmony_ci	.def = 1,
7208c2ecf20Sopenharmony_ci	.qmenu = tpg_aspect_strings,
7218c2ecf20Sopenharmony_ci};
7228c2ecf20Sopenharmony_ci
7238c2ecf20Sopenharmony_cistatic const char * const vivid_ctrl_dv_timings_signal_mode_strings[] = {
7248c2ecf20Sopenharmony_ci	"Current DV Timings",
7258c2ecf20Sopenharmony_ci	"No Signal",
7268c2ecf20Sopenharmony_ci	"No Lock",
7278c2ecf20Sopenharmony_ci	"Out of Range",
7288c2ecf20Sopenharmony_ci	"Selected DV Timings",
7298c2ecf20Sopenharmony_ci	"Cycle Through All DV Timings",
7308c2ecf20Sopenharmony_ci	"Custom DV Timings",
7318c2ecf20Sopenharmony_ci	NULL,
7328c2ecf20Sopenharmony_ci};
7338c2ecf20Sopenharmony_ci
7348c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_dv_timings_signal_mode = {
7358c2ecf20Sopenharmony_ci	.ops = &vivid_vid_cap_ctrl_ops,
7368c2ecf20Sopenharmony_ci	.id = VIVID_CID_DV_TIMINGS_SIGNAL_MODE,
7378c2ecf20Sopenharmony_ci	.name = "DV Timings Signal Mode",
7388c2ecf20Sopenharmony_ci	.type = V4L2_CTRL_TYPE_MENU,
7398c2ecf20Sopenharmony_ci	.max = 5,
7408c2ecf20Sopenharmony_ci	.qmenu = vivid_ctrl_dv_timings_signal_mode_strings,
7418c2ecf20Sopenharmony_ci};
7428c2ecf20Sopenharmony_ci
7438c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_dv_timings_aspect_ratio = {
7448c2ecf20Sopenharmony_ci	.ops = &vivid_vid_cap_ctrl_ops,
7458c2ecf20Sopenharmony_ci	.id = VIVID_CID_DV_TIMINGS_ASPECT_RATIO,
7468c2ecf20Sopenharmony_ci	.name = "DV Timings Aspect Ratio",
7478c2ecf20Sopenharmony_ci	.type = V4L2_CTRL_TYPE_MENU,
7488c2ecf20Sopenharmony_ci	.max = 3,
7498c2ecf20Sopenharmony_ci	.qmenu = tpg_aspect_strings,
7508c2ecf20Sopenharmony_ci};
7518c2ecf20Sopenharmony_ci
7528c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_max_edid_blocks = {
7538c2ecf20Sopenharmony_ci	.ops = &vivid_vid_cap_ctrl_ops,
7548c2ecf20Sopenharmony_ci	.id = VIVID_CID_MAX_EDID_BLOCKS,
7558c2ecf20Sopenharmony_ci	.name = "Maximum EDID Blocks",
7568c2ecf20Sopenharmony_ci	.type = V4L2_CTRL_TYPE_INTEGER,
7578c2ecf20Sopenharmony_ci	.min = 1,
7588c2ecf20Sopenharmony_ci	.max = 256,
7598c2ecf20Sopenharmony_ci	.def = 2,
7608c2ecf20Sopenharmony_ci	.step = 1,
7618c2ecf20Sopenharmony_ci};
7628c2ecf20Sopenharmony_ci
7638c2ecf20Sopenharmony_cistatic const char * const vivid_ctrl_colorspace_strings[] = {
7648c2ecf20Sopenharmony_ci	"SMPTE 170M",
7658c2ecf20Sopenharmony_ci	"Rec. 709",
7668c2ecf20Sopenharmony_ci	"sRGB",
7678c2ecf20Sopenharmony_ci	"opRGB",
7688c2ecf20Sopenharmony_ci	"BT.2020",
7698c2ecf20Sopenharmony_ci	"DCI-P3",
7708c2ecf20Sopenharmony_ci	"SMPTE 240M",
7718c2ecf20Sopenharmony_ci	"470 System M",
7728c2ecf20Sopenharmony_ci	"470 System BG",
7738c2ecf20Sopenharmony_ci	NULL,
7748c2ecf20Sopenharmony_ci};
7758c2ecf20Sopenharmony_ci
7768c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_colorspace = {
7778c2ecf20Sopenharmony_ci	.ops = &vivid_vid_cap_ctrl_ops,
7788c2ecf20Sopenharmony_ci	.id = VIVID_CID_COLORSPACE,
7798c2ecf20Sopenharmony_ci	.name = "Colorspace",
7808c2ecf20Sopenharmony_ci	.type = V4L2_CTRL_TYPE_MENU,
7818c2ecf20Sopenharmony_ci	.max = ARRAY_SIZE(vivid_ctrl_colorspace_strings) - 2,
7828c2ecf20Sopenharmony_ci	.def = 2,
7838c2ecf20Sopenharmony_ci	.qmenu = vivid_ctrl_colorspace_strings,
7848c2ecf20Sopenharmony_ci};
7858c2ecf20Sopenharmony_ci
7868c2ecf20Sopenharmony_cistatic const char * const vivid_ctrl_xfer_func_strings[] = {
7878c2ecf20Sopenharmony_ci	"Default",
7888c2ecf20Sopenharmony_ci	"Rec. 709",
7898c2ecf20Sopenharmony_ci	"sRGB",
7908c2ecf20Sopenharmony_ci	"opRGB",
7918c2ecf20Sopenharmony_ci	"SMPTE 240M",
7928c2ecf20Sopenharmony_ci	"None",
7938c2ecf20Sopenharmony_ci	"DCI-P3",
7948c2ecf20Sopenharmony_ci	"SMPTE 2084",
7958c2ecf20Sopenharmony_ci	NULL,
7968c2ecf20Sopenharmony_ci};
7978c2ecf20Sopenharmony_ci
7988c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_xfer_func = {
7998c2ecf20Sopenharmony_ci	.ops = &vivid_vid_cap_ctrl_ops,
8008c2ecf20Sopenharmony_ci	.id = VIVID_CID_XFER_FUNC,
8018c2ecf20Sopenharmony_ci	.name = "Transfer Function",
8028c2ecf20Sopenharmony_ci	.type = V4L2_CTRL_TYPE_MENU,
8038c2ecf20Sopenharmony_ci	.max = ARRAY_SIZE(vivid_ctrl_xfer_func_strings) - 2,
8048c2ecf20Sopenharmony_ci	.qmenu = vivid_ctrl_xfer_func_strings,
8058c2ecf20Sopenharmony_ci};
8068c2ecf20Sopenharmony_ci
8078c2ecf20Sopenharmony_cistatic const char * const vivid_ctrl_ycbcr_enc_strings[] = {
8088c2ecf20Sopenharmony_ci	"Default",
8098c2ecf20Sopenharmony_ci	"ITU-R 601",
8108c2ecf20Sopenharmony_ci	"Rec. 709",
8118c2ecf20Sopenharmony_ci	"xvYCC 601",
8128c2ecf20Sopenharmony_ci	"xvYCC 709",
8138c2ecf20Sopenharmony_ci	"",
8148c2ecf20Sopenharmony_ci	"BT.2020",
8158c2ecf20Sopenharmony_ci	"BT.2020 Constant Luminance",
8168c2ecf20Sopenharmony_ci	"SMPTE 240M",
8178c2ecf20Sopenharmony_ci	NULL,
8188c2ecf20Sopenharmony_ci};
8198c2ecf20Sopenharmony_ci
8208c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_ycbcr_enc = {
8218c2ecf20Sopenharmony_ci	.ops = &vivid_vid_cap_ctrl_ops,
8228c2ecf20Sopenharmony_ci	.id = VIVID_CID_YCBCR_ENC,
8238c2ecf20Sopenharmony_ci	.name = "Y'CbCr Encoding",
8248c2ecf20Sopenharmony_ci	.type = V4L2_CTRL_TYPE_MENU,
8258c2ecf20Sopenharmony_ci	.menu_skip_mask = 1 << 5,
8268c2ecf20Sopenharmony_ci	.max = ARRAY_SIZE(vivid_ctrl_ycbcr_enc_strings) - 2,
8278c2ecf20Sopenharmony_ci	.qmenu = vivid_ctrl_ycbcr_enc_strings,
8288c2ecf20Sopenharmony_ci};
8298c2ecf20Sopenharmony_ci
8308c2ecf20Sopenharmony_cistatic const char * const vivid_ctrl_hsv_enc_strings[] = {
8318c2ecf20Sopenharmony_ci	"Hue 0-179",
8328c2ecf20Sopenharmony_ci	"Hue 0-256",
8338c2ecf20Sopenharmony_ci	NULL,
8348c2ecf20Sopenharmony_ci};
8358c2ecf20Sopenharmony_ci
8368c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_hsv_enc = {
8378c2ecf20Sopenharmony_ci	.ops = &vivid_vid_cap_ctrl_ops,
8388c2ecf20Sopenharmony_ci	.id = VIVID_CID_HSV_ENC,
8398c2ecf20Sopenharmony_ci	.name = "HSV Encoding",
8408c2ecf20Sopenharmony_ci	.type = V4L2_CTRL_TYPE_MENU,
8418c2ecf20Sopenharmony_ci	.max = ARRAY_SIZE(vivid_ctrl_hsv_enc_strings) - 2,
8428c2ecf20Sopenharmony_ci	.qmenu = vivid_ctrl_hsv_enc_strings,
8438c2ecf20Sopenharmony_ci};
8448c2ecf20Sopenharmony_ci
8458c2ecf20Sopenharmony_cistatic const char * const vivid_ctrl_quantization_strings[] = {
8468c2ecf20Sopenharmony_ci	"Default",
8478c2ecf20Sopenharmony_ci	"Full Range",
8488c2ecf20Sopenharmony_ci	"Limited Range",
8498c2ecf20Sopenharmony_ci	NULL,
8508c2ecf20Sopenharmony_ci};
8518c2ecf20Sopenharmony_ci
8528c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_quantization = {
8538c2ecf20Sopenharmony_ci	.ops = &vivid_vid_cap_ctrl_ops,
8548c2ecf20Sopenharmony_ci	.id = VIVID_CID_QUANTIZATION,
8558c2ecf20Sopenharmony_ci	.name = "Quantization",
8568c2ecf20Sopenharmony_ci	.type = V4L2_CTRL_TYPE_MENU,
8578c2ecf20Sopenharmony_ci	.max = ARRAY_SIZE(vivid_ctrl_quantization_strings) - 2,
8588c2ecf20Sopenharmony_ci	.qmenu = vivid_ctrl_quantization_strings,
8598c2ecf20Sopenharmony_ci};
8608c2ecf20Sopenharmony_ci
8618c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_alpha_mode = {
8628c2ecf20Sopenharmony_ci	.ops = &vivid_vid_cap_ctrl_ops,
8638c2ecf20Sopenharmony_ci	.id = VIVID_CID_ALPHA_MODE,
8648c2ecf20Sopenharmony_ci	.name = "Apply Alpha To Red Only",
8658c2ecf20Sopenharmony_ci	.type = V4L2_CTRL_TYPE_BOOLEAN,
8668c2ecf20Sopenharmony_ci	.max = 1,
8678c2ecf20Sopenharmony_ci	.step = 1,
8688c2ecf20Sopenharmony_ci};
8698c2ecf20Sopenharmony_ci
8708c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_limited_rgb_range = {
8718c2ecf20Sopenharmony_ci	.ops = &vivid_vid_cap_ctrl_ops,
8728c2ecf20Sopenharmony_ci	.id = VIVID_CID_LIMITED_RGB_RANGE,
8738c2ecf20Sopenharmony_ci	.name = "Limited RGB Range (16-235)",
8748c2ecf20Sopenharmony_ci	.type = V4L2_CTRL_TYPE_BOOLEAN,
8758c2ecf20Sopenharmony_ci	.max = 1,
8768c2ecf20Sopenharmony_ci	.step = 1,
8778c2ecf20Sopenharmony_ci};
8788c2ecf20Sopenharmony_ci
8798c2ecf20Sopenharmony_ci
8808c2ecf20Sopenharmony_ci/* Video Loop Control */
8818c2ecf20Sopenharmony_ci
8828c2ecf20Sopenharmony_cistatic int vivid_loop_cap_s_ctrl(struct v4l2_ctrl *ctrl)
8838c2ecf20Sopenharmony_ci{
8848c2ecf20Sopenharmony_ci	struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_loop_cap);
8858c2ecf20Sopenharmony_ci
8868c2ecf20Sopenharmony_ci	switch (ctrl->id) {
8878c2ecf20Sopenharmony_ci	case VIVID_CID_LOOP_VIDEO:
8888c2ecf20Sopenharmony_ci		dev->loop_video = ctrl->val;
8898c2ecf20Sopenharmony_ci		vivid_update_quality(dev);
8908c2ecf20Sopenharmony_ci		vivid_send_source_change(dev, SVID);
8918c2ecf20Sopenharmony_ci		vivid_send_source_change(dev, HDMI);
8928c2ecf20Sopenharmony_ci		break;
8938c2ecf20Sopenharmony_ci	}
8948c2ecf20Sopenharmony_ci	return 0;
8958c2ecf20Sopenharmony_ci}
8968c2ecf20Sopenharmony_ci
8978c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_ops vivid_loop_cap_ctrl_ops = {
8988c2ecf20Sopenharmony_ci	.s_ctrl = vivid_loop_cap_s_ctrl,
8998c2ecf20Sopenharmony_ci};
9008c2ecf20Sopenharmony_ci
9018c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_loop_video = {
9028c2ecf20Sopenharmony_ci	.ops = &vivid_loop_cap_ctrl_ops,
9038c2ecf20Sopenharmony_ci	.id = VIVID_CID_LOOP_VIDEO,
9048c2ecf20Sopenharmony_ci	.name = "Loop Video",
9058c2ecf20Sopenharmony_ci	.type = V4L2_CTRL_TYPE_BOOLEAN,
9068c2ecf20Sopenharmony_ci	.max = 1,
9078c2ecf20Sopenharmony_ci	.step = 1,
9088c2ecf20Sopenharmony_ci};
9098c2ecf20Sopenharmony_ci
9108c2ecf20Sopenharmony_ci
9118c2ecf20Sopenharmony_ci/* VBI Capture Control */
9128c2ecf20Sopenharmony_ci
9138c2ecf20Sopenharmony_cistatic int vivid_vbi_cap_s_ctrl(struct v4l2_ctrl *ctrl)
9148c2ecf20Sopenharmony_ci{
9158c2ecf20Sopenharmony_ci	struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_vbi_cap);
9168c2ecf20Sopenharmony_ci
9178c2ecf20Sopenharmony_ci	switch (ctrl->id) {
9188c2ecf20Sopenharmony_ci	case VIVID_CID_VBI_CAP_INTERLACED:
9198c2ecf20Sopenharmony_ci		dev->vbi_cap_interlaced = ctrl->val;
9208c2ecf20Sopenharmony_ci		break;
9218c2ecf20Sopenharmony_ci	}
9228c2ecf20Sopenharmony_ci	return 0;
9238c2ecf20Sopenharmony_ci}
9248c2ecf20Sopenharmony_ci
9258c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_ops vivid_vbi_cap_ctrl_ops = {
9268c2ecf20Sopenharmony_ci	.s_ctrl = vivid_vbi_cap_s_ctrl,
9278c2ecf20Sopenharmony_ci};
9288c2ecf20Sopenharmony_ci
9298c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_vbi_cap_interlaced = {
9308c2ecf20Sopenharmony_ci	.ops = &vivid_vbi_cap_ctrl_ops,
9318c2ecf20Sopenharmony_ci	.id = VIVID_CID_VBI_CAP_INTERLACED,
9328c2ecf20Sopenharmony_ci	.name = "Interlaced VBI Format",
9338c2ecf20Sopenharmony_ci	.type = V4L2_CTRL_TYPE_BOOLEAN,
9348c2ecf20Sopenharmony_ci	.max = 1,
9358c2ecf20Sopenharmony_ci	.step = 1,
9368c2ecf20Sopenharmony_ci};
9378c2ecf20Sopenharmony_ci
9388c2ecf20Sopenharmony_ci
9398c2ecf20Sopenharmony_ci/* Video Output Controls */
9408c2ecf20Sopenharmony_ci
9418c2ecf20Sopenharmony_cistatic int vivid_vid_out_s_ctrl(struct v4l2_ctrl *ctrl)
9428c2ecf20Sopenharmony_ci{
9438c2ecf20Sopenharmony_ci	struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_vid_out);
9448c2ecf20Sopenharmony_ci	struct v4l2_bt_timings *bt = &dev->dv_timings_out.bt;
9458c2ecf20Sopenharmony_ci	u32 display_present = 0;
9468c2ecf20Sopenharmony_ci	unsigned int i, j, bus_idx;
9478c2ecf20Sopenharmony_ci
9488c2ecf20Sopenharmony_ci	switch (ctrl->id) {
9498c2ecf20Sopenharmony_ci	case VIVID_CID_HAS_CROP_OUT:
9508c2ecf20Sopenharmony_ci		dev->has_crop_out = ctrl->val;
9518c2ecf20Sopenharmony_ci		vivid_update_format_out(dev);
9528c2ecf20Sopenharmony_ci		break;
9538c2ecf20Sopenharmony_ci	case VIVID_CID_HAS_COMPOSE_OUT:
9548c2ecf20Sopenharmony_ci		dev->has_compose_out = ctrl->val;
9558c2ecf20Sopenharmony_ci		vivid_update_format_out(dev);
9568c2ecf20Sopenharmony_ci		break;
9578c2ecf20Sopenharmony_ci	case VIVID_CID_HAS_SCALER_OUT:
9588c2ecf20Sopenharmony_ci		dev->has_scaler_out = ctrl->val;
9598c2ecf20Sopenharmony_ci		vivid_update_format_out(dev);
9608c2ecf20Sopenharmony_ci		break;
9618c2ecf20Sopenharmony_ci	case V4L2_CID_DV_TX_MODE:
9628c2ecf20Sopenharmony_ci		dev->dvi_d_out = ctrl->val == V4L2_DV_TX_MODE_DVI_D;
9638c2ecf20Sopenharmony_ci		if (!vivid_is_hdmi_out(dev))
9648c2ecf20Sopenharmony_ci			break;
9658c2ecf20Sopenharmony_ci		if (!dev->dvi_d_out && (bt->flags & V4L2_DV_FL_IS_CE_VIDEO)) {
9668c2ecf20Sopenharmony_ci			if (bt->width == 720 && bt->height <= 576)
9678c2ecf20Sopenharmony_ci				dev->colorspace_out = V4L2_COLORSPACE_SMPTE170M;
9688c2ecf20Sopenharmony_ci			else
9698c2ecf20Sopenharmony_ci				dev->colorspace_out = V4L2_COLORSPACE_REC709;
9708c2ecf20Sopenharmony_ci			dev->quantization_out = V4L2_QUANTIZATION_DEFAULT;
9718c2ecf20Sopenharmony_ci		} else {
9728c2ecf20Sopenharmony_ci			dev->colorspace_out = V4L2_COLORSPACE_SRGB;
9738c2ecf20Sopenharmony_ci			dev->quantization_out = dev->dvi_d_out ?
9748c2ecf20Sopenharmony_ci					V4L2_QUANTIZATION_LIM_RANGE :
9758c2ecf20Sopenharmony_ci					V4L2_QUANTIZATION_DEFAULT;
9768c2ecf20Sopenharmony_ci		}
9778c2ecf20Sopenharmony_ci		if (dev->loop_video)
9788c2ecf20Sopenharmony_ci			vivid_send_source_change(dev, HDMI);
9798c2ecf20Sopenharmony_ci		break;
9808c2ecf20Sopenharmony_ci	case VIVID_CID_DISPLAY_PRESENT:
9818c2ecf20Sopenharmony_ci		if (dev->output_type[dev->output] != HDMI)
9828c2ecf20Sopenharmony_ci			break;
9838c2ecf20Sopenharmony_ci
9848c2ecf20Sopenharmony_ci		dev->display_present[dev->output] = ctrl->val;
9858c2ecf20Sopenharmony_ci		for (i = 0, j = 0; i < dev->num_outputs; i++)
9868c2ecf20Sopenharmony_ci			if (dev->output_type[i] == HDMI)
9878c2ecf20Sopenharmony_ci				display_present |=
9888c2ecf20Sopenharmony_ci					dev->display_present[i] << j++;
9898c2ecf20Sopenharmony_ci
9908c2ecf20Sopenharmony_ci		__v4l2_ctrl_s_ctrl(dev->ctrl_tx_rxsense, display_present);
9918c2ecf20Sopenharmony_ci
9928c2ecf20Sopenharmony_ci		if (dev->edid_blocks) {
9938c2ecf20Sopenharmony_ci			__v4l2_ctrl_s_ctrl(dev->ctrl_tx_edid_present,
9948c2ecf20Sopenharmony_ci					   display_present);
9958c2ecf20Sopenharmony_ci			__v4l2_ctrl_s_ctrl(dev->ctrl_tx_hotplug,
9968c2ecf20Sopenharmony_ci					   display_present);
9978c2ecf20Sopenharmony_ci		}
9988c2ecf20Sopenharmony_ci
9998c2ecf20Sopenharmony_ci		bus_idx = dev->cec_output2bus_map[dev->output];
10008c2ecf20Sopenharmony_ci		if (!dev->cec_tx_adap[bus_idx])
10018c2ecf20Sopenharmony_ci			break;
10028c2ecf20Sopenharmony_ci
10038c2ecf20Sopenharmony_ci		if (ctrl->val && dev->edid_blocks)
10048c2ecf20Sopenharmony_ci			cec_s_phys_addr(dev->cec_tx_adap[bus_idx],
10058c2ecf20Sopenharmony_ci					dev->cec_tx_adap[bus_idx]->phys_addr,
10068c2ecf20Sopenharmony_ci					false);
10078c2ecf20Sopenharmony_ci		else
10088c2ecf20Sopenharmony_ci			cec_phys_addr_invalidate(dev->cec_tx_adap[bus_idx]);
10098c2ecf20Sopenharmony_ci
10108c2ecf20Sopenharmony_ci		break;
10118c2ecf20Sopenharmony_ci	}
10128c2ecf20Sopenharmony_ci	return 0;
10138c2ecf20Sopenharmony_ci}
10148c2ecf20Sopenharmony_ci
10158c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_ops vivid_vid_out_ctrl_ops = {
10168c2ecf20Sopenharmony_ci	.s_ctrl = vivid_vid_out_s_ctrl,
10178c2ecf20Sopenharmony_ci};
10188c2ecf20Sopenharmony_ci
10198c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_has_crop_out = {
10208c2ecf20Sopenharmony_ci	.ops = &vivid_vid_out_ctrl_ops,
10218c2ecf20Sopenharmony_ci	.id = VIVID_CID_HAS_CROP_OUT,
10228c2ecf20Sopenharmony_ci	.name = "Enable Output Cropping",
10238c2ecf20Sopenharmony_ci	.type = V4L2_CTRL_TYPE_BOOLEAN,
10248c2ecf20Sopenharmony_ci	.max = 1,
10258c2ecf20Sopenharmony_ci	.def = 1,
10268c2ecf20Sopenharmony_ci	.step = 1,
10278c2ecf20Sopenharmony_ci};
10288c2ecf20Sopenharmony_ci
10298c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_has_compose_out = {
10308c2ecf20Sopenharmony_ci	.ops = &vivid_vid_out_ctrl_ops,
10318c2ecf20Sopenharmony_ci	.id = VIVID_CID_HAS_COMPOSE_OUT,
10328c2ecf20Sopenharmony_ci	.name = "Enable Output Composing",
10338c2ecf20Sopenharmony_ci	.type = V4L2_CTRL_TYPE_BOOLEAN,
10348c2ecf20Sopenharmony_ci	.max = 1,
10358c2ecf20Sopenharmony_ci	.def = 1,
10368c2ecf20Sopenharmony_ci	.step = 1,
10378c2ecf20Sopenharmony_ci};
10388c2ecf20Sopenharmony_ci
10398c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_has_scaler_out = {
10408c2ecf20Sopenharmony_ci	.ops = &vivid_vid_out_ctrl_ops,
10418c2ecf20Sopenharmony_ci	.id = VIVID_CID_HAS_SCALER_OUT,
10428c2ecf20Sopenharmony_ci	.name = "Enable Output Scaler",
10438c2ecf20Sopenharmony_ci	.type = V4L2_CTRL_TYPE_BOOLEAN,
10448c2ecf20Sopenharmony_ci	.max = 1,
10458c2ecf20Sopenharmony_ci	.def = 1,
10468c2ecf20Sopenharmony_ci	.step = 1,
10478c2ecf20Sopenharmony_ci};
10488c2ecf20Sopenharmony_ci
10498c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_display_present = {
10508c2ecf20Sopenharmony_ci	.ops = &vivid_vid_out_ctrl_ops,
10518c2ecf20Sopenharmony_ci	.id = VIVID_CID_DISPLAY_PRESENT,
10528c2ecf20Sopenharmony_ci	.name = "Display Present",
10538c2ecf20Sopenharmony_ci	.type = V4L2_CTRL_TYPE_BOOLEAN,
10548c2ecf20Sopenharmony_ci	.max = 1,
10558c2ecf20Sopenharmony_ci	.def = 1,
10568c2ecf20Sopenharmony_ci	.step = 1,
10578c2ecf20Sopenharmony_ci};
10588c2ecf20Sopenharmony_ci
10598c2ecf20Sopenharmony_ci/* Streaming Controls */
10608c2ecf20Sopenharmony_ci
10618c2ecf20Sopenharmony_cistatic int vivid_streaming_s_ctrl(struct v4l2_ctrl *ctrl)
10628c2ecf20Sopenharmony_ci{
10638c2ecf20Sopenharmony_ci	struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_streaming);
10648c2ecf20Sopenharmony_ci	u64 rem;
10658c2ecf20Sopenharmony_ci
10668c2ecf20Sopenharmony_ci	switch (ctrl->id) {
10678c2ecf20Sopenharmony_ci	case VIVID_CID_DQBUF_ERROR:
10688c2ecf20Sopenharmony_ci		dev->dqbuf_error = true;
10698c2ecf20Sopenharmony_ci		break;
10708c2ecf20Sopenharmony_ci	case VIVID_CID_PERC_DROPPED:
10718c2ecf20Sopenharmony_ci		dev->perc_dropped_buffers = ctrl->val;
10728c2ecf20Sopenharmony_ci		break;
10738c2ecf20Sopenharmony_ci	case VIVID_CID_QUEUE_SETUP_ERROR:
10748c2ecf20Sopenharmony_ci		dev->queue_setup_error = true;
10758c2ecf20Sopenharmony_ci		break;
10768c2ecf20Sopenharmony_ci	case VIVID_CID_BUF_PREPARE_ERROR:
10778c2ecf20Sopenharmony_ci		dev->buf_prepare_error = true;
10788c2ecf20Sopenharmony_ci		break;
10798c2ecf20Sopenharmony_ci	case VIVID_CID_START_STR_ERROR:
10808c2ecf20Sopenharmony_ci		dev->start_streaming_error = true;
10818c2ecf20Sopenharmony_ci		break;
10828c2ecf20Sopenharmony_ci	case VIVID_CID_REQ_VALIDATE_ERROR:
10838c2ecf20Sopenharmony_ci		dev->req_validate_error = true;
10848c2ecf20Sopenharmony_ci		break;
10858c2ecf20Sopenharmony_ci	case VIVID_CID_QUEUE_ERROR:
10868c2ecf20Sopenharmony_ci		if (vb2_start_streaming_called(&dev->vb_vid_cap_q))
10878c2ecf20Sopenharmony_ci			vb2_queue_error(&dev->vb_vid_cap_q);
10888c2ecf20Sopenharmony_ci		if (vb2_start_streaming_called(&dev->vb_vbi_cap_q))
10898c2ecf20Sopenharmony_ci			vb2_queue_error(&dev->vb_vbi_cap_q);
10908c2ecf20Sopenharmony_ci		if (vb2_start_streaming_called(&dev->vb_vid_out_q))
10918c2ecf20Sopenharmony_ci			vb2_queue_error(&dev->vb_vid_out_q);
10928c2ecf20Sopenharmony_ci		if (vb2_start_streaming_called(&dev->vb_vbi_out_q))
10938c2ecf20Sopenharmony_ci			vb2_queue_error(&dev->vb_vbi_out_q);
10948c2ecf20Sopenharmony_ci		if (vb2_start_streaming_called(&dev->vb_sdr_cap_q))
10958c2ecf20Sopenharmony_ci			vb2_queue_error(&dev->vb_sdr_cap_q);
10968c2ecf20Sopenharmony_ci		break;
10978c2ecf20Sopenharmony_ci	case VIVID_CID_SEQ_WRAP:
10988c2ecf20Sopenharmony_ci		dev->seq_wrap = ctrl->val;
10998c2ecf20Sopenharmony_ci		break;
11008c2ecf20Sopenharmony_ci	case VIVID_CID_TIME_WRAP:
11018c2ecf20Sopenharmony_ci		dev->time_wrap = ctrl->val;
11028c2ecf20Sopenharmony_ci		if (ctrl->val == 0) {
11038c2ecf20Sopenharmony_ci			dev->time_wrap_offset = 0;
11048c2ecf20Sopenharmony_ci			break;
11058c2ecf20Sopenharmony_ci		}
11068c2ecf20Sopenharmony_ci		/*
11078c2ecf20Sopenharmony_ci		 * We want to set the time 16 seconds before the 32 bit tv_sec
11088c2ecf20Sopenharmony_ci		 * value of struct timeval would wrap around. So first we
11098c2ecf20Sopenharmony_ci		 * calculate ktime_get_ns() % ((1 << 32) * NSEC_PER_SEC), and
11108c2ecf20Sopenharmony_ci		 * then we set the offset to ((1 << 32) - 16) * NSEC_PER_SEC).
11118c2ecf20Sopenharmony_ci		 */
11128c2ecf20Sopenharmony_ci		div64_u64_rem(ktime_get_ns(),
11138c2ecf20Sopenharmony_ci			0x100000000ULL * NSEC_PER_SEC, &rem);
11148c2ecf20Sopenharmony_ci		dev->time_wrap_offset =
11158c2ecf20Sopenharmony_ci			(0x100000000ULL - 16) * NSEC_PER_SEC - rem;
11168c2ecf20Sopenharmony_ci		break;
11178c2ecf20Sopenharmony_ci	}
11188c2ecf20Sopenharmony_ci	return 0;
11198c2ecf20Sopenharmony_ci}
11208c2ecf20Sopenharmony_ci
11218c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_ops vivid_streaming_ctrl_ops = {
11228c2ecf20Sopenharmony_ci	.s_ctrl = vivid_streaming_s_ctrl,
11238c2ecf20Sopenharmony_ci};
11248c2ecf20Sopenharmony_ci
11258c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_dqbuf_error = {
11268c2ecf20Sopenharmony_ci	.ops = &vivid_streaming_ctrl_ops,
11278c2ecf20Sopenharmony_ci	.id = VIVID_CID_DQBUF_ERROR,
11288c2ecf20Sopenharmony_ci	.name = "Inject V4L2_BUF_FLAG_ERROR",
11298c2ecf20Sopenharmony_ci	.type = V4L2_CTRL_TYPE_BUTTON,
11308c2ecf20Sopenharmony_ci};
11318c2ecf20Sopenharmony_ci
11328c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_perc_dropped = {
11338c2ecf20Sopenharmony_ci	.ops = &vivid_streaming_ctrl_ops,
11348c2ecf20Sopenharmony_ci	.id = VIVID_CID_PERC_DROPPED,
11358c2ecf20Sopenharmony_ci	.name = "Percentage of Dropped Buffers",
11368c2ecf20Sopenharmony_ci	.type = V4L2_CTRL_TYPE_INTEGER,
11378c2ecf20Sopenharmony_ci	.min = 0,
11388c2ecf20Sopenharmony_ci	.max = 100,
11398c2ecf20Sopenharmony_ci	.step = 1,
11408c2ecf20Sopenharmony_ci};
11418c2ecf20Sopenharmony_ci
11428c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_queue_setup_error = {
11438c2ecf20Sopenharmony_ci	.ops = &vivid_streaming_ctrl_ops,
11448c2ecf20Sopenharmony_ci	.id = VIVID_CID_QUEUE_SETUP_ERROR,
11458c2ecf20Sopenharmony_ci	.name = "Inject VIDIOC_REQBUFS Error",
11468c2ecf20Sopenharmony_ci	.type = V4L2_CTRL_TYPE_BUTTON,
11478c2ecf20Sopenharmony_ci};
11488c2ecf20Sopenharmony_ci
11498c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_buf_prepare_error = {
11508c2ecf20Sopenharmony_ci	.ops = &vivid_streaming_ctrl_ops,
11518c2ecf20Sopenharmony_ci	.id = VIVID_CID_BUF_PREPARE_ERROR,
11528c2ecf20Sopenharmony_ci	.name = "Inject VIDIOC_QBUF Error",
11538c2ecf20Sopenharmony_ci	.type = V4L2_CTRL_TYPE_BUTTON,
11548c2ecf20Sopenharmony_ci};
11558c2ecf20Sopenharmony_ci
11568c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_start_streaming_error = {
11578c2ecf20Sopenharmony_ci	.ops = &vivid_streaming_ctrl_ops,
11588c2ecf20Sopenharmony_ci	.id = VIVID_CID_START_STR_ERROR,
11598c2ecf20Sopenharmony_ci	.name = "Inject VIDIOC_STREAMON Error",
11608c2ecf20Sopenharmony_ci	.type = V4L2_CTRL_TYPE_BUTTON,
11618c2ecf20Sopenharmony_ci};
11628c2ecf20Sopenharmony_ci
11638c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_queue_error = {
11648c2ecf20Sopenharmony_ci	.ops = &vivid_streaming_ctrl_ops,
11658c2ecf20Sopenharmony_ci	.id = VIVID_CID_QUEUE_ERROR,
11668c2ecf20Sopenharmony_ci	.name = "Inject Fatal Streaming Error",
11678c2ecf20Sopenharmony_ci	.type = V4L2_CTRL_TYPE_BUTTON,
11688c2ecf20Sopenharmony_ci};
11698c2ecf20Sopenharmony_ci
11708c2ecf20Sopenharmony_ci#ifdef CONFIG_MEDIA_CONTROLLER
11718c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_req_validate_error = {
11728c2ecf20Sopenharmony_ci	.ops = &vivid_streaming_ctrl_ops,
11738c2ecf20Sopenharmony_ci	.id = VIVID_CID_REQ_VALIDATE_ERROR,
11748c2ecf20Sopenharmony_ci	.name = "Inject req_validate() Error",
11758c2ecf20Sopenharmony_ci	.type = V4L2_CTRL_TYPE_BUTTON,
11768c2ecf20Sopenharmony_ci};
11778c2ecf20Sopenharmony_ci#endif
11788c2ecf20Sopenharmony_ci
11798c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_seq_wrap = {
11808c2ecf20Sopenharmony_ci	.ops = &vivid_streaming_ctrl_ops,
11818c2ecf20Sopenharmony_ci	.id = VIVID_CID_SEQ_WRAP,
11828c2ecf20Sopenharmony_ci	.name = "Wrap Sequence Number",
11838c2ecf20Sopenharmony_ci	.type = V4L2_CTRL_TYPE_BOOLEAN,
11848c2ecf20Sopenharmony_ci	.max = 1,
11858c2ecf20Sopenharmony_ci	.step = 1,
11868c2ecf20Sopenharmony_ci};
11878c2ecf20Sopenharmony_ci
11888c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_time_wrap = {
11898c2ecf20Sopenharmony_ci	.ops = &vivid_streaming_ctrl_ops,
11908c2ecf20Sopenharmony_ci	.id = VIVID_CID_TIME_WRAP,
11918c2ecf20Sopenharmony_ci	.name = "Wrap Timestamp",
11928c2ecf20Sopenharmony_ci	.type = V4L2_CTRL_TYPE_BOOLEAN,
11938c2ecf20Sopenharmony_ci	.max = 1,
11948c2ecf20Sopenharmony_ci	.step = 1,
11958c2ecf20Sopenharmony_ci};
11968c2ecf20Sopenharmony_ci
11978c2ecf20Sopenharmony_ci
11988c2ecf20Sopenharmony_ci/* SDTV Capture Controls */
11998c2ecf20Sopenharmony_ci
12008c2ecf20Sopenharmony_cistatic int vivid_sdtv_cap_s_ctrl(struct v4l2_ctrl *ctrl)
12018c2ecf20Sopenharmony_ci{
12028c2ecf20Sopenharmony_ci	struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_sdtv_cap);
12038c2ecf20Sopenharmony_ci
12048c2ecf20Sopenharmony_ci	switch (ctrl->id) {
12058c2ecf20Sopenharmony_ci	case VIVID_CID_STD_SIGNAL_MODE:
12068c2ecf20Sopenharmony_ci		dev->std_signal_mode[dev->input] =
12078c2ecf20Sopenharmony_ci			dev->ctrl_std_signal_mode->val;
12088c2ecf20Sopenharmony_ci		if (dev->std_signal_mode[dev->input] == SELECTED_STD)
12098c2ecf20Sopenharmony_ci			dev->query_std[dev->input] =
12108c2ecf20Sopenharmony_ci				vivid_standard[dev->ctrl_standard->val];
12118c2ecf20Sopenharmony_ci		v4l2_ctrl_activate(dev->ctrl_standard,
12128c2ecf20Sopenharmony_ci				   dev->std_signal_mode[dev->input] ==
12138c2ecf20Sopenharmony_ci					SELECTED_STD);
12148c2ecf20Sopenharmony_ci		vivid_update_quality(dev);
12158c2ecf20Sopenharmony_ci		vivid_send_source_change(dev, TV);
12168c2ecf20Sopenharmony_ci		vivid_send_source_change(dev, SVID);
12178c2ecf20Sopenharmony_ci		break;
12188c2ecf20Sopenharmony_ci	}
12198c2ecf20Sopenharmony_ci	return 0;
12208c2ecf20Sopenharmony_ci}
12218c2ecf20Sopenharmony_ci
12228c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_ops vivid_sdtv_cap_ctrl_ops = {
12238c2ecf20Sopenharmony_ci	.s_ctrl = vivid_sdtv_cap_s_ctrl,
12248c2ecf20Sopenharmony_ci};
12258c2ecf20Sopenharmony_ci
12268c2ecf20Sopenharmony_cistatic const char * const vivid_ctrl_std_signal_mode_strings[] = {
12278c2ecf20Sopenharmony_ci	"Current Standard",
12288c2ecf20Sopenharmony_ci	"No Signal",
12298c2ecf20Sopenharmony_ci	"No Lock",
12308c2ecf20Sopenharmony_ci	"",
12318c2ecf20Sopenharmony_ci	"Selected Standard",
12328c2ecf20Sopenharmony_ci	"Cycle Through All Standards",
12338c2ecf20Sopenharmony_ci	NULL,
12348c2ecf20Sopenharmony_ci};
12358c2ecf20Sopenharmony_ci
12368c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_std_signal_mode = {
12378c2ecf20Sopenharmony_ci	.ops = &vivid_sdtv_cap_ctrl_ops,
12388c2ecf20Sopenharmony_ci	.id = VIVID_CID_STD_SIGNAL_MODE,
12398c2ecf20Sopenharmony_ci	.name = "Standard Signal Mode",
12408c2ecf20Sopenharmony_ci	.type = V4L2_CTRL_TYPE_MENU,
12418c2ecf20Sopenharmony_ci	.max = ARRAY_SIZE(vivid_ctrl_std_signal_mode_strings) - 2,
12428c2ecf20Sopenharmony_ci	.menu_skip_mask = 1 << 3,
12438c2ecf20Sopenharmony_ci	.qmenu = vivid_ctrl_std_signal_mode_strings,
12448c2ecf20Sopenharmony_ci};
12458c2ecf20Sopenharmony_ci
12468c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_standard = {
12478c2ecf20Sopenharmony_ci	.ops = &vivid_sdtv_cap_ctrl_ops,
12488c2ecf20Sopenharmony_ci	.id = VIVID_CID_STANDARD,
12498c2ecf20Sopenharmony_ci	.name = "Standard",
12508c2ecf20Sopenharmony_ci	.type = V4L2_CTRL_TYPE_MENU,
12518c2ecf20Sopenharmony_ci	.max = 14,
12528c2ecf20Sopenharmony_ci	.qmenu = vivid_ctrl_standard_strings,
12538c2ecf20Sopenharmony_ci};
12548c2ecf20Sopenharmony_ci
12558c2ecf20Sopenharmony_ci
12568c2ecf20Sopenharmony_ci
12578c2ecf20Sopenharmony_ci/* Radio Receiver Controls */
12588c2ecf20Sopenharmony_ci
12598c2ecf20Sopenharmony_cistatic int vivid_radio_rx_s_ctrl(struct v4l2_ctrl *ctrl)
12608c2ecf20Sopenharmony_ci{
12618c2ecf20Sopenharmony_ci	struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_radio_rx);
12628c2ecf20Sopenharmony_ci
12638c2ecf20Sopenharmony_ci	switch (ctrl->id) {
12648c2ecf20Sopenharmony_ci	case VIVID_CID_RADIO_SEEK_MODE:
12658c2ecf20Sopenharmony_ci		dev->radio_rx_hw_seek_mode = ctrl->val;
12668c2ecf20Sopenharmony_ci		break;
12678c2ecf20Sopenharmony_ci	case VIVID_CID_RADIO_SEEK_PROG_LIM:
12688c2ecf20Sopenharmony_ci		dev->radio_rx_hw_seek_prog_lim = ctrl->val;
12698c2ecf20Sopenharmony_ci		break;
12708c2ecf20Sopenharmony_ci	case VIVID_CID_RADIO_RX_RDS_RBDS:
12718c2ecf20Sopenharmony_ci		dev->rds_gen.use_rbds = ctrl->val;
12728c2ecf20Sopenharmony_ci		break;
12738c2ecf20Sopenharmony_ci	case VIVID_CID_RADIO_RX_RDS_BLOCKIO:
12748c2ecf20Sopenharmony_ci		dev->radio_rx_rds_controls = ctrl->val;
12758c2ecf20Sopenharmony_ci		dev->radio_rx_caps &= ~V4L2_CAP_READWRITE;
12768c2ecf20Sopenharmony_ci		dev->radio_rx_rds_use_alternates = false;
12778c2ecf20Sopenharmony_ci		if (!dev->radio_rx_rds_controls) {
12788c2ecf20Sopenharmony_ci			dev->radio_rx_caps |= V4L2_CAP_READWRITE;
12798c2ecf20Sopenharmony_ci			__v4l2_ctrl_s_ctrl(dev->radio_rx_rds_pty, 0);
12808c2ecf20Sopenharmony_ci			__v4l2_ctrl_s_ctrl(dev->radio_rx_rds_ta, 0);
12818c2ecf20Sopenharmony_ci			__v4l2_ctrl_s_ctrl(dev->radio_rx_rds_tp, 0);
12828c2ecf20Sopenharmony_ci			__v4l2_ctrl_s_ctrl(dev->radio_rx_rds_ms, 0);
12838c2ecf20Sopenharmony_ci			__v4l2_ctrl_s_ctrl_string(dev->radio_rx_rds_psname, "");
12848c2ecf20Sopenharmony_ci			__v4l2_ctrl_s_ctrl_string(dev->radio_rx_rds_radiotext, "");
12858c2ecf20Sopenharmony_ci		}
12868c2ecf20Sopenharmony_ci		v4l2_ctrl_activate(dev->radio_rx_rds_pty, dev->radio_rx_rds_controls);
12878c2ecf20Sopenharmony_ci		v4l2_ctrl_activate(dev->radio_rx_rds_psname, dev->radio_rx_rds_controls);
12888c2ecf20Sopenharmony_ci		v4l2_ctrl_activate(dev->radio_rx_rds_radiotext, dev->radio_rx_rds_controls);
12898c2ecf20Sopenharmony_ci		v4l2_ctrl_activate(dev->radio_rx_rds_ta, dev->radio_rx_rds_controls);
12908c2ecf20Sopenharmony_ci		v4l2_ctrl_activate(dev->radio_rx_rds_tp, dev->radio_rx_rds_controls);
12918c2ecf20Sopenharmony_ci		v4l2_ctrl_activate(dev->radio_rx_rds_ms, dev->radio_rx_rds_controls);
12928c2ecf20Sopenharmony_ci		dev->radio_rx_dev.device_caps = dev->radio_rx_caps;
12938c2ecf20Sopenharmony_ci		break;
12948c2ecf20Sopenharmony_ci	case V4L2_CID_RDS_RECEPTION:
12958c2ecf20Sopenharmony_ci		dev->radio_rx_rds_enabled = ctrl->val;
12968c2ecf20Sopenharmony_ci		break;
12978c2ecf20Sopenharmony_ci	}
12988c2ecf20Sopenharmony_ci	return 0;
12998c2ecf20Sopenharmony_ci}
13008c2ecf20Sopenharmony_ci
13018c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_ops vivid_radio_rx_ctrl_ops = {
13028c2ecf20Sopenharmony_ci	.s_ctrl = vivid_radio_rx_s_ctrl,
13038c2ecf20Sopenharmony_ci};
13048c2ecf20Sopenharmony_ci
13058c2ecf20Sopenharmony_cistatic const char * const vivid_ctrl_radio_rds_mode_strings[] = {
13068c2ecf20Sopenharmony_ci	"Block I/O",
13078c2ecf20Sopenharmony_ci	"Controls",
13088c2ecf20Sopenharmony_ci	NULL,
13098c2ecf20Sopenharmony_ci};
13108c2ecf20Sopenharmony_ci
13118c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_radio_rx_rds_blockio = {
13128c2ecf20Sopenharmony_ci	.ops = &vivid_radio_rx_ctrl_ops,
13138c2ecf20Sopenharmony_ci	.id = VIVID_CID_RADIO_RX_RDS_BLOCKIO,
13148c2ecf20Sopenharmony_ci	.name = "RDS Rx I/O Mode",
13158c2ecf20Sopenharmony_ci	.type = V4L2_CTRL_TYPE_MENU,
13168c2ecf20Sopenharmony_ci	.qmenu = vivid_ctrl_radio_rds_mode_strings,
13178c2ecf20Sopenharmony_ci	.max = 1,
13188c2ecf20Sopenharmony_ci};
13198c2ecf20Sopenharmony_ci
13208c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_radio_rx_rds_rbds = {
13218c2ecf20Sopenharmony_ci	.ops = &vivid_radio_rx_ctrl_ops,
13228c2ecf20Sopenharmony_ci	.id = VIVID_CID_RADIO_RX_RDS_RBDS,
13238c2ecf20Sopenharmony_ci	.name = "Generate RBDS Instead of RDS",
13248c2ecf20Sopenharmony_ci	.type = V4L2_CTRL_TYPE_BOOLEAN,
13258c2ecf20Sopenharmony_ci	.max = 1,
13268c2ecf20Sopenharmony_ci	.step = 1,
13278c2ecf20Sopenharmony_ci};
13288c2ecf20Sopenharmony_ci
13298c2ecf20Sopenharmony_cistatic const char * const vivid_ctrl_radio_hw_seek_mode_strings[] = {
13308c2ecf20Sopenharmony_ci	"Bounded",
13318c2ecf20Sopenharmony_ci	"Wrap Around",
13328c2ecf20Sopenharmony_ci	"Both",
13338c2ecf20Sopenharmony_ci	NULL,
13348c2ecf20Sopenharmony_ci};
13358c2ecf20Sopenharmony_ci
13368c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_radio_hw_seek_mode = {
13378c2ecf20Sopenharmony_ci	.ops = &vivid_radio_rx_ctrl_ops,
13388c2ecf20Sopenharmony_ci	.id = VIVID_CID_RADIO_SEEK_MODE,
13398c2ecf20Sopenharmony_ci	.name = "Radio HW Seek Mode",
13408c2ecf20Sopenharmony_ci	.type = V4L2_CTRL_TYPE_MENU,
13418c2ecf20Sopenharmony_ci	.max = 2,
13428c2ecf20Sopenharmony_ci	.qmenu = vivid_ctrl_radio_hw_seek_mode_strings,
13438c2ecf20Sopenharmony_ci};
13448c2ecf20Sopenharmony_ci
13458c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_radio_hw_seek_prog_lim = {
13468c2ecf20Sopenharmony_ci	.ops = &vivid_radio_rx_ctrl_ops,
13478c2ecf20Sopenharmony_ci	.id = VIVID_CID_RADIO_SEEK_PROG_LIM,
13488c2ecf20Sopenharmony_ci	.name = "Radio Programmable HW Seek",
13498c2ecf20Sopenharmony_ci	.type = V4L2_CTRL_TYPE_BOOLEAN,
13508c2ecf20Sopenharmony_ci	.max = 1,
13518c2ecf20Sopenharmony_ci	.step = 1,
13528c2ecf20Sopenharmony_ci};
13538c2ecf20Sopenharmony_ci
13548c2ecf20Sopenharmony_ci
13558c2ecf20Sopenharmony_ci/* Radio Transmitter Controls */
13568c2ecf20Sopenharmony_ci
13578c2ecf20Sopenharmony_cistatic int vivid_radio_tx_s_ctrl(struct v4l2_ctrl *ctrl)
13588c2ecf20Sopenharmony_ci{
13598c2ecf20Sopenharmony_ci	struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_radio_tx);
13608c2ecf20Sopenharmony_ci
13618c2ecf20Sopenharmony_ci	switch (ctrl->id) {
13628c2ecf20Sopenharmony_ci	case VIVID_CID_RADIO_TX_RDS_BLOCKIO:
13638c2ecf20Sopenharmony_ci		dev->radio_tx_rds_controls = ctrl->val;
13648c2ecf20Sopenharmony_ci		dev->radio_tx_caps &= ~V4L2_CAP_READWRITE;
13658c2ecf20Sopenharmony_ci		if (!dev->radio_tx_rds_controls)
13668c2ecf20Sopenharmony_ci			dev->radio_tx_caps |= V4L2_CAP_READWRITE;
13678c2ecf20Sopenharmony_ci		dev->radio_tx_dev.device_caps = dev->radio_tx_caps;
13688c2ecf20Sopenharmony_ci		break;
13698c2ecf20Sopenharmony_ci	case V4L2_CID_RDS_TX_PTY:
13708c2ecf20Sopenharmony_ci		if (dev->radio_rx_rds_controls)
13718c2ecf20Sopenharmony_ci			v4l2_ctrl_s_ctrl(dev->radio_rx_rds_pty, ctrl->val);
13728c2ecf20Sopenharmony_ci		break;
13738c2ecf20Sopenharmony_ci	case V4L2_CID_RDS_TX_PS_NAME:
13748c2ecf20Sopenharmony_ci		if (dev->radio_rx_rds_controls)
13758c2ecf20Sopenharmony_ci			v4l2_ctrl_s_ctrl_string(dev->radio_rx_rds_psname, ctrl->p_new.p_char);
13768c2ecf20Sopenharmony_ci		break;
13778c2ecf20Sopenharmony_ci	case V4L2_CID_RDS_TX_RADIO_TEXT:
13788c2ecf20Sopenharmony_ci		if (dev->radio_rx_rds_controls)
13798c2ecf20Sopenharmony_ci			v4l2_ctrl_s_ctrl_string(dev->radio_rx_rds_radiotext, ctrl->p_new.p_char);
13808c2ecf20Sopenharmony_ci		break;
13818c2ecf20Sopenharmony_ci	case V4L2_CID_RDS_TX_TRAFFIC_ANNOUNCEMENT:
13828c2ecf20Sopenharmony_ci		if (dev->radio_rx_rds_controls)
13838c2ecf20Sopenharmony_ci			v4l2_ctrl_s_ctrl(dev->radio_rx_rds_ta, ctrl->val);
13848c2ecf20Sopenharmony_ci		break;
13858c2ecf20Sopenharmony_ci	case V4L2_CID_RDS_TX_TRAFFIC_PROGRAM:
13868c2ecf20Sopenharmony_ci		if (dev->radio_rx_rds_controls)
13878c2ecf20Sopenharmony_ci			v4l2_ctrl_s_ctrl(dev->radio_rx_rds_tp, ctrl->val);
13888c2ecf20Sopenharmony_ci		break;
13898c2ecf20Sopenharmony_ci	case V4L2_CID_RDS_TX_MUSIC_SPEECH:
13908c2ecf20Sopenharmony_ci		if (dev->radio_rx_rds_controls)
13918c2ecf20Sopenharmony_ci			v4l2_ctrl_s_ctrl(dev->radio_rx_rds_ms, ctrl->val);
13928c2ecf20Sopenharmony_ci		break;
13938c2ecf20Sopenharmony_ci	}
13948c2ecf20Sopenharmony_ci	return 0;
13958c2ecf20Sopenharmony_ci}
13968c2ecf20Sopenharmony_ci
13978c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_ops vivid_radio_tx_ctrl_ops = {
13988c2ecf20Sopenharmony_ci	.s_ctrl = vivid_radio_tx_s_ctrl,
13998c2ecf20Sopenharmony_ci};
14008c2ecf20Sopenharmony_ci
14018c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_radio_tx_rds_blockio = {
14028c2ecf20Sopenharmony_ci	.ops = &vivid_radio_tx_ctrl_ops,
14038c2ecf20Sopenharmony_ci	.id = VIVID_CID_RADIO_TX_RDS_BLOCKIO,
14048c2ecf20Sopenharmony_ci	.name = "RDS Tx I/O Mode",
14058c2ecf20Sopenharmony_ci	.type = V4L2_CTRL_TYPE_MENU,
14068c2ecf20Sopenharmony_ci	.qmenu = vivid_ctrl_radio_rds_mode_strings,
14078c2ecf20Sopenharmony_ci	.max = 1,
14088c2ecf20Sopenharmony_ci	.def = 1,
14098c2ecf20Sopenharmony_ci};
14108c2ecf20Sopenharmony_ci
14118c2ecf20Sopenharmony_ci
14128c2ecf20Sopenharmony_ci/* SDR Capture Controls */
14138c2ecf20Sopenharmony_ci
14148c2ecf20Sopenharmony_cistatic int vivid_sdr_cap_s_ctrl(struct v4l2_ctrl *ctrl)
14158c2ecf20Sopenharmony_ci{
14168c2ecf20Sopenharmony_ci	struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_sdr_cap);
14178c2ecf20Sopenharmony_ci
14188c2ecf20Sopenharmony_ci	switch (ctrl->id) {
14198c2ecf20Sopenharmony_ci	case VIVID_CID_SDR_CAP_FM_DEVIATION:
14208c2ecf20Sopenharmony_ci		dev->sdr_fm_deviation = ctrl->val;
14218c2ecf20Sopenharmony_ci		break;
14228c2ecf20Sopenharmony_ci	}
14238c2ecf20Sopenharmony_ci	return 0;
14248c2ecf20Sopenharmony_ci}
14258c2ecf20Sopenharmony_ci
14268c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_ops vivid_sdr_cap_ctrl_ops = {
14278c2ecf20Sopenharmony_ci	.s_ctrl = vivid_sdr_cap_s_ctrl,
14288c2ecf20Sopenharmony_ci};
14298c2ecf20Sopenharmony_ci
14308c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_sdr_cap_fm_deviation = {
14318c2ecf20Sopenharmony_ci	.ops = &vivid_sdr_cap_ctrl_ops,
14328c2ecf20Sopenharmony_ci	.id = VIVID_CID_SDR_CAP_FM_DEVIATION,
14338c2ecf20Sopenharmony_ci	.name = "FM Deviation",
14348c2ecf20Sopenharmony_ci	.type = V4L2_CTRL_TYPE_INTEGER,
14358c2ecf20Sopenharmony_ci	.min =    100,
14368c2ecf20Sopenharmony_ci	.max = 200000,
14378c2ecf20Sopenharmony_ci	.def =  75000,
14388c2ecf20Sopenharmony_ci	.step =     1,
14398c2ecf20Sopenharmony_ci};
14408c2ecf20Sopenharmony_ci
14418c2ecf20Sopenharmony_ci/* Metadata Capture Control */
14428c2ecf20Sopenharmony_ci
14438c2ecf20Sopenharmony_cistatic int vivid_meta_cap_s_ctrl(struct v4l2_ctrl *ctrl)
14448c2ecf20Sopenharmony_ci{
14458c2ecf20Sopenharmony_ci	struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev,
14468c2ecf20Sopenharmony_ci					     ctrl_hdl_meta_cap);
14478c2ecf20Sopenharmony_ci
14488c2ecf20Sopenharmony_ci	switch (ctrl->id) {
14498c2ecf20Sopenharmony_ci	case VIVID_CID_META_CAP_GENERATE_PTS:
14508c2ecf20Sopenharmony_ci		dev->meta_pts = ctrl->val;
14518c2ecf20Sopenharmony_ci		break;
14528c2ecf20Sopenharmony_ci	case VIVID_CID_META_CAP_GENERATE_SCR:
14538c2ecf20Sopenharmony_ci		dev->meta_scr = ctrl->val;
14548c2ecf20Sopenharmony_ci		break;
14558c2ecf20Sopenharmony_ci	}
14568c2ecf20Sopenharmony_ci	return 0;
14578c2ecf20Sopenharmony_ci}
14588c2ecf20Sopenharmony_ci
14598c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_ops vivid_meta_cap_ctrl_ops = {
14608c2ecf20Sopenharmony_ci	.s_ctrl = vivid_meta_cap_s_ctrl,
14618c2ecf20Sopenharmony_ci};
14628c2ecf20Sopenharmony_ci
14638c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_meta_has_pts = {
14648c2ecf20Sopenharmony_ci	.ops = &vivid_meta_cap_ctrl_ops,
14658c2ecf20Sopenharmony_ci	.id = VIVID_CID_META_CAP_GENERATE_PTS,
14668c2ecf20Sopenharmony_ci	.name = "Generate PTS",
14678c2ecf20Sopenharmony_ci	.type = V4L2_CTRL_TYPE_BOOLEAN,
14688c2ecf20Sopenharmony_ci	.max = 1,
14698c2ecf20Sopenharmony_ci	.def = 1,
14708c2ecf20Sopenharmony_ci	.step = 1,
14718c2ecf20Sopenharmony_ci};
14728c2ecf20Sopenharmony_ci
14738c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_meta_has_src_clk = {
14748c2ecf20Sopenharmony_ci	.ops = &vivid_meta_cap_ctrl_ops,
14758c2ecf20Sopenharmony_ci	.id = VIVID_CID_META_CAP_GENERATE_SCR,
14768c2ecf20Sopenharmony_ci	.name = "Generate SCR",
14778c2ecf20Sopenharmony_ci	.type = V4L2_CTRL_TYPE_BOOLEAN,
14788c2ecf20Sopenharmony_ci	.max = 1,
14798c2ecf20Sopenharmony_ci	.def = 1,
14808c2ecf20Sopenharmony_ci	.step = 1,
14818c2ecf20Sopenharmony_ci};
14828c2ecf20Sopenharmony_ci
14838c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_class = {
14848c2ecf20Sopenharmony_ci	.ops = &vivid_user_gen_ctrl_ops,
14858c2ecf20Sopenharmony_ci	.flags = V4L2_CTRL_FLAG_READ_ONLY | V4L2_CTRL_FLAG_WRITE_ONLY,
14868c2ecf20Sopenharmony_ci	.id = VIVID_CID_VIVID_CLASS,
14878c2ecf20Sopenharmony_ci	.name = "Vivid Controls",
14888c2ecf20Sopenharmony_ci	.type = V4L2_CTRL_TYPE_CTRL_CLASS,
14898c2ecf20Sopenharmony_ci};
14908c2ecf20Sopenharmony_ci
14918c2ecf20Sopenharmony_ciint vivid_create_controls(struct vivid_dev *dev, bool show_ccs_cap,
14928c2ecf20Sopenharmony_ci		bool show_ccs_out, bool no_error_inj,
14938c2ecf20Sopenharmony_ci		bool has_sdtv, bool has_hdmi)
14948c2ecf20Sopenharmony_ci{
14958c2ecf20Sopenharmony_ci	struct v4l2_ctrl_handler *hdl_user_gen = &dev->ctrl_hdl_user_gen;
14968c2ecf20Sopenharmony_ci	struct v4l2_ctrl_handler *hdl_user_vid = &dev->ctrl_hdl_user_vid;
14978c2ecf20Sopenharmony_ci	struct v4l2_ctrl_handler *hdl_user_aud = &dev->ctrl_hdl_user_aud;
14988c2ecf20Sopenharmony_ci	struct v4l2_ctrl_handler *hdl_streaming = &dev->ctrl_hdl_streaming;
14998c2ecf20Sopenharmony_ci	struct v4l2_ctrl_handler *hdl_sdtv_cap = &dev->ctrl_hdl_sdtv_cap;
15008c2ecf20Sopenharmony_ci	struct v4l2_ctrl_handler *hdl_loop_cap = &dev->ctrl_hdl_loop_cap;
15018c2ecf20Sopenharmony_ci	struct v4l2_ctrl_handler *hdl_fb = &dev->ctrl_hdl_fb;
15028c2ecf20Sopenharmony_ci	struct v4l2_ctrl_handler *hdl_vid_cap = &dev->ctrl_hdl_vid_cap;
15038c2ecf20Sopenharmony_ci	struct v4l2_ctrl_handler *hdl_vid_out = &dev->ctrl_hdl_vid_out;
15048c2ecf20Sopenharmony_ci	struct v4l2_ctrl_handler *hdl_vbi_cap = &dev->ctrl_hdl_vbi_cap;
15058c2ecf20Sopenharmony_ci	struct v4l2_ctrl_handler *hdl_vbi_out = &dev->ctrl_hdl_vbi_out;
15068c2ecf20Sopenharmony_ci	struct v4l2_ctrl_handler *hdl_radio_rx = &dev->ctrl_hdl_radio_rx;
15078c2ecf20Sopenharmony_ci	struct v4l2_ctrl_handler *hdl_radio_tx = &dev->ctrl_hdl_radio_tx;
15088c2ecf20Sopenharmony_ci	struct v4l2_ctrl_handler *hdl_sdr_cap = &dev->ctrl_hdl_sdr_cap;
15098c2ecf20Sopenharmony_ci	struct v4l2_ctrl_handler *hdl_meta_cap = &dev->ctrl_hdl_meta_cap;
15108c2ecf20Sopenharmony_ci	struct v4l2_ctrl_handler *hdl_meta_out = &dev->ctrl_hdl_meta_out;
15118c2ecf20Sopenharmony_ci	struct v4l2_ctrl_handler *hdl_tch_cap = &dev->ctrl_hdl_touch_cap;
15128c2ecf20Sopenharmony_ci
15138c2ecf20Sopenharmony_ci	struct v4l2_ctrl_config vivid_ctrl_dv_timings = {
15148c2ecf20Sopenharmony_ci		.ops = &vivid_vid_cap_ctrl_ops,
15158c2ecf20Sopenharmony_ci		.id = VIVID_CID_DV_TIMINGS,
15168c2ecf20Sopenharmony_ci		.name = "DV Timings",
15178c2ecf20Sopenharmony_ci		.type = V4L2_CTRL_TYPE_MENU,
15188c2ecf20Sopenharmony_ci	};
15198c2ecf20Sopenharmony_ci	int i;
15208c2ecf20Sopenharmony_ci
15218c2ecf20Sopenharmony_ci	v4l2_ctrl_handler_init(hdl_user_gen, 10);
15228c2ecf20Sopenharmony_ci	v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_class, NULL);
15238c2ecf20Sopenharmony_ci	v4l2_ctrl_handler_init(hdl_user_vid, 9);
15248c2ecf20Sopenharmony_ci	v4l2_ctrl_new_custom(hdl_user_vid, &vivid_ctrl_class, NULL);
15258c2ecf20Sopenharmony_ci	v4l2_ctrl_handler_init(hdl_user_aud, 2);
15268c2ecf20Sopenharmony_ci	v4l2_ctrl_new_custom(hdl_user_aud, &vivid_ctrl_class, NULL);
15278c2ecf20Sopenharmony_ci	v4l2_ctrl_handler_init(hdl_streaming, 8);
15288c2ecf20Sopenharmony_ci	v4l2_ctrl_new_custom(hdl_streaming, &vivid_ctrl_class, NULL);
15298c2ecf20Sopenharmony_ci	v4l2_ctrl_handler_init(hdl_sdtv_cap, 2);
15308c2ecf20Sopenharmony_ci	v4l2_ctrl_new_custom(hdl_sdtv_cap, &vivid_ctrl_class, NULL);
15318c2ecf20Sopenharmony_ci	v4l2_ctrl_handler_init(hdl_loop_cap, 1);
15328c2ecf20Sopenharmony_ci	v4l2_ctrl_new_custom(hdl_loop_cap, &vivid_ctrl_class, NULL);
15338c2ecf20Sopenharmony_ci	v4l2_ctrl_handler_init(hdl_fb, 1);
15348c2ecf20Sopenharmony_ci	v4l2_ctrl_new_custom(hdl_fb, &vivid_ctrl_class, NULL);
15358c2ecf20Sopenharmony_ci	v4l2_ctrl_handler_init(hdl_vid_cap, 55);
15368c2ecf20Sopenharmony_ci	v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_class, NULL);
15378c2ecf20Sopenharmony_ci	v4l2_ctrl_handler_init(hdl_vid_out, 26);
15388c2ecf20Sopenharmony_ci	if (!no_error_inj || dev->has_fb || dev->num_hdmi_outputs)
15398c2ecf20Sopenharmony_ci		v4l2_ctrl_new_custom(hdl_vid_out, &vivid_ctrl_class, NULL);
15408c2ecf20Sopenharmony_ci	v4l2_ctrl_handler_init(hdl_vbi_cap, 21);
15418c2ecf20Sopenharmony_ci	v4l2_ctrl_new_custom(hdl_vbi_cap, &vivid_ctrl_class, NULL);
15428c2ecf20Sopenharmony_ci	v4l2_ctrl_handler_init(hdl_vbi_out, 19);
15438c2ecf20Sopenharmony_ci	if (!no_error_inj)
15448c2ecf20Sopenharmony_ci		v4l2_ctrl_new_custom(hdl_vbi_out, &vivid_ctrl_class, NULL);
15458c2ecf20Sopenharmony_ci	v4l2_ctrl_handler_init(hdl_radio_rx, 17);
15468c2ecf20Sopenharmony_ci	v4l2_ctrl_new_custom(hdl_radio_rx, &vivid_ctrl_class, NULL);
15478c2ecf20Sopenharmony_ci	v4l2_ctrl_handler_init(hdl_radio_tx, 17);
15488c2ecf20Sopenharmony_ci	v4l2_ctrl_new_custom(hdl_radio_tx, &vivid_ctrl_class, NULL);
15498c2ecf20Sopenharmony_ci	v4l2_ctrl_handler_init(hdl_sdr_cap, 19);
15508c2ecf20Sopenharmony_ci	v4l2_ctrl_new_custom(hdl_sdr_cap, &vivid_ctrl_class, NULL);
15518c2ecf20Sopenharmony_ci	v4l2_ctrl_handler_init(hdl_meta_cap, 2);
15528c2ecf20Sopenharmony_ci	v4l2_ctrl_new_custom(hdl_meta_cap, &vivid_ctrl_class, NULL);
15538c2ecf20Sopenharmony_ci	v4l2_ctrl_handler_init(hdl_meta_out, 2);
15548c2ecf20Sopenharmony_ci	v4l2_ctrl_new_custom(hdl_meta_out, &vivid_ctrl_class, NULL);
15558c2ecf20Sopenharmony_ci	v4l2_ctrl_handler_init(hdl_tch_cap, 2);
15568c2ecf20Sopenharmony_ci	v4l2_ctrl_new_custom(hdl_tch_cap, &vivid_ctrl_class, NULL);
15578c2ecf20Sopenharmony_ci
15588c2ecf20Sopenharmony_ci	/* User Controls */
15598c2ecf20Sopenharmony_ci	dev->volume = v4l2_ctrl_new_std(hdl_user_aud, NULL,
15608c2ecf20Sopenharmony_ci		V4L2_CID_AUDIO_VOLUME, 0, 255, 1, 200);
15618c2ecf20Sopenharmony_ci	dev->mute = v4l2_ctrl_new_std(hdl_user_aud, NULL,
15628c2ecf20Sopenharmony_ci		V4L2_CID_AUDIO_MUTE, 0, 1, 1, 0);
15638c2ecf20Sopenharmony_ci	if (dev->has_vid_cap) {
15648c2ecf20Sopenharmony_ci		dev->brightness = v4l2_ctrl_new_std(hdl_user_vid, &vivid_user_vid_ctrl_ops,
15658c2ecf20Sopenharmony_ci			V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
15668c2ecf20Sopenharmony_ci		for (i = 0; i < MAX_INPUTS; i++)
15678c2ecf20Sopenharmony_ci			dev->input_brightness[i] = 128;
15688c2ecf20Sopenharmony_ci		dev->contrast = v4l2_ctrl_new_std(hdl_user_vid, &vivid_user_vid_ctrl_ops,
15698c2ecf20Sopenharmony_ci			V4L2_CID_CONTRAST, 0, 255, 1, 128);
15708c2ecf20Sopenharmony_ci		dev->saturation = v4l2_ctrl_new_std(hdl_user_vid, &vivid_user_vid_ctrl_ops,
15718c2ecf20Sopenharmony_ci			V4L2_CID_SATURATION, 0, 255, 1, 128);
15728c2ecf20Sopenharmony_ci		dev->hue = v4l2_ctrl_new_std(hdl_user_vid, &vivid_user_vid_ctrl_ops,
15738c2ecf20Sopenharmony_ci			V4L2_CID_HUE, -128, 128, 1, 0);
15748c2ecf20Sopenharmony_ci		v4l2_ctrl_new_std(hdl_user_vid, &vivid_user_vid_ctrl_ops,
15758c2ecf20Sopenharmony_ci			V4L2_CID_HFLIP, 0, 1, 1, 0);
15768c2ecf20Sopenharmony_ci		v4l2_ctrl_new_std(hdl_user_vid, &vivid_user_vid_ctrl_ops,
15778c2ecf20Sopenharmony_ci			V4L2_CID_VFLIP, 0, 1, 1, 0);
15788c2ecf20Sopenharmony_ci		dev->autogain = v4l2_ctrl_new_std(hdl_user_vid, &vivid_user_vid_ctrl_ops,
15798c2ecf20Sopenharmony_ci			V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
15808c2ecf20Sopenharmony_ci		dev->gain = v4l2_ctrl_new_std(hdl_user_vid, &vivid_user_vid_ctrl_ops,
15818c2ecf20Sopenharmony_ci			V4L2_CID_GAIN, 0, 255, 1, 100);
15828c2ecf20Sopenharmony_ci		dev->alpha = v4l2_ctrl_new_std(hdl_user_vid, &vivid_user_vid_ctrl_ops,
15838c2ecf20Sopenharmony_ci			V4L2_CID_ALPHA_COMPONENT, 0, 255, 1, 0);
15848c2ecf20Sopenharmony_ci	}
15858c2ecf20Sopenharmony_ci	dev->button = v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_button, NULL);
15868c2ecf20Sopenharmony_ci	dev->int32 = v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_int32, NULL);
15878c2ecf20Sopenharmony_ci	dev->int64 = v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_int64, NULL);
15888c2ecf20Sopenharmony_ci	dev->boolean = v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_boolean, NULL);
15898c2ecf20Sopenharmony_ci	dev->menu = v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_menu, NULL);
15908c2ecf20Sopenharmony_ci	dev->string = v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_string, NULL);
15918c2ecf20Sopenharmony_ci	dev->bitmask = v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_bitmask, NULL);
15928c2ecf20Sopenharmony_ci	dev->int_menu = v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_int_menu, NULL);
15938c2ecf20Sopenharmony_ci	v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_area, NULL);
15948c2ecf20Sopenharmony_ci	v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_u32_array, NULL);
15958c2ecf20Sopenharmony_ci	v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_u16_matrix, NULL);
15968c2ecf20Sopenharmony_ci	v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_u8_4d_array, NULL);
15978c2ecf20Sopenharmony_ci
15988c2ecf20Sopenharmony_ci	if (dev->has_vid_cap) {
15998c2ecf20Sopenharmony_ci		/* Image Processing Controls */
16008c2ecf20Sopenharmony_ci		struct v4l2_ctrl_config vivid_ctrl_test_pattern = {
16018c2ecf20Sopenharmony_ci			.ops = &vivid_vid_cap_ctrl_ops,
16028c2ecf20Sopenharmony_ci			.id = VIVID_CID_TEST_PATTERN,
16038c2ecf20Sopenharmony_ci			.name = "Test Pattern",
16048c2ecf20Sopenharmony_ci			.type = V4L2_CTRL_TYPE_MENU,
16058c2ecf20Sopenharmony_ci			.max = TPG_PAT_NOISE,
16068c2ecf20Sopenharmony_ci			.qmenu = tpg_pattern_strings,
16078c2ecf20Sopenharmony_ci		};
16088c2ecf20Sopenharmony_ci
16098c2ecf20Sopenharmony_ci		dev->test_pattern = v4l2_ctrl_new_custom(hdl_vid_cap,
16108c2ecf20Sopenharmony_ci				&vivid_ctrl_test_pattern, NULL);
16118c2ecf20Sopenharmony_ci		v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_perc_fill, NULL);
16128c2ecf20Sopenharmony_ci		v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_hor_movement, NULL);
16138c2ecf20Sopenharmony_ci		v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_vert_movement, NULL);
16148c2ecf20Sopenharmony_ci		v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_osd_mode, NULL);
16158c2ecf20Sopenharmony_ci		v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_show_border, NULL);
16168c2ecf20Sopenharmony_ci		v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_show_square, NULL);
16178c2ecf20Sopenharmony_ci		v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_hflip, NULL);
16188c2ecf20Sopenharmony_ci		v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_vflip, NULL);
16198c2ecf20Sopenharmony_ci		v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_insert_sav, NULL);
16208c2ecf20Sopenharmony_ci		v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_insert_eav, NULL);
16218c2ecf20Sopenharmony_ci		v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_reduced_fps, NULL);
16228c2ecf20Sopenharmony_ci		if (show_ccs_cap) {
16238c2ecf20Sopenharmony_ci			dev->ctrl_has_crop_cap = v4l2_ctrl_new_custom(hdl_vid_cap,
16248c2ecf20Sopenharmony_ci				&vivid_ctrl_has_crop_cap, NULL);
16258c2ecf20Sopenharmony_ci			dev->ctrl_has_compose_cap = v4l2_ctrl_new_custom(hdl_vid_cap,
16268c2ecf20Sopenharmony_ci				&vivid_ctrl_has_compose_cap, NULL);
16278c2ecf20Sopenharmony_ci			dev->ctrl_has_scaler_cap = v4l2_ctrl_new_custom(hdl_vid_cap,
16288c2ecf20Sopenharmony_ci				&vivid_ctrl_has_scaler_cap, NULL);
16298c2ecf20Sopenharmony_ci		}
16308c2ecf20Sopenharmony_ci
16318c2ecf20Sopenharmony_ci		v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_tstamp_src, NULL);
16328c2ecf20Sopenharmony_ci		dev->colorspace = v4l2_ctrl_new_custom(hdl_vid_cap,
16338c2ecf20Sopenharmony_ci			&vivid_ctrl_colorspace, NULL);
16348c2ecf20Sopenharmony_ci		v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_xfer_func, NULL);
16358c2ecf20Sopenharmony_ci		v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_ycbcr_enc, NULL);
16368c2ecf20Sopenharmony_ci		v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_hsv_enc, NULL);
16378c2ecf20Sopenharmony_ci		v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_quantization, NULL);
16388c2ecf20Sopenharmony_ci		v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_alpha_mode, NULL);
16398c2ecf20Sopenharmony_ci	}
16408c2ecf20Sopenharmony_ci
16418c2ecf20Sopenharmony_ci	if (dev->has_vid_out && show_ccs_out) {
16428c2ecf20Sopenharmony_ci		dev->ctrl_has_crop_out = v4l2_ctrl_new_custom(hdl_vid_out,
16438c2ecf20Sopenharmony_ci			&vivid_ctrl_has_crop_out, NULL);
16448c2ecf20Sopenharmony_ci		dev->ctrl_has_compose_out = v4l2_ctrl_new_custom(hdl_vid_out,
16458c2ecf20Sopenharmony_ci			&vivid_ctrl_has_compose_out, NULL);
16468c2ecf20Sopenharmony_ci		dev->ctrl_has_scaler_out = v4l2_ctrl_new_custom(hdl_vid_out,
16478c2ecf20Sopenharmony_ci			&vivid_ctrl_has_scaler_out, NULL);
16488c2ecf20Sopenharmony_ci	}
16498c2ecf20Sopenharmony_ci
16508c2ecf20Sopenharmony_ci	/*
16518c2ecf20Sopenharmony_ci	 * Testing this driver with v4l2-compliance will trigger the error
16528c2ecf20Sopenharmony_ci	 * injection controls, and after that nothing will work as expected.
16538c2ecf20Sopenharmony_ci	 * So we have a module option to drop these error injecting controls
16548c2ecf20Sopenharmony_ci	 * allowing us to run v4l2_compliance again.
16558c2ecf20Sopenharmony_ci	 */
16568c2ecf20Sopenharmony_ci	if (!no_error_inj) {
16578c2ecf20Sopenharmony_ci		v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_disconnect, NULL);
16588c2ecf20Sopenharmony_ci		v4l2_ctrl_new_custom(hdl_streaming, &vivid_ctrl_dqbuf_error, NULL);
16598c2ecf20Sopenharmony_ci		v4l2_ctrl_new_custom(hdl_streaming, &vivid_ctrl_perc_dropped, NULL);
16608c2ecf20Sopenharmony_ci		v4l2_ctrl_new_custom(hdl_streaming, &vivid_ctrl_queue_setup_error, NULL);
16618c2ecf20Sopenharmony_ci		v4l2_ctrl_new_custom(hdl_streaming, &vivid_ctrl_buf_prepare_error, NULL);
16628c2ecf20Sopenharmony_ci		v4l2_ctrl_new_custom(hdl_streaming, &vivid_ctrl_start_streaming_error, NULL);
16638c2ecf20Sopenharmony_ci		v4l2_ctrl_new_custom(hdl_streaming, &vivid_ctrl_queue_error, NULL);
16648c2ecf20Sopenharmony_ci#ifdef CONFIG_MEDIA_CONTROLLER
16658c2ecf20Sopenharmony_ci		v4l2_ctrl_new_custom(hdl_streaming, &vivid_ctrl_req_validate_error, NULL);
16668c2ecf20Sopenharmony_ci#endif
16678c2ecf20Sopenharmony_ci		v4l2_ctrl_new_custom(hdl_streaming, &vivid_ctrl_seq_wrap, NULL);
16688c2ecf20Sopenharmony_ci		v4l2_ctrl_new_custom(hdl_streaming, &vivid_ctrl_time_wrap, NULL);
16698c2ecf20Sopenharmony_ci	}
16708c2ecf20Sopenharmony_ci
16718c2ecf20Sopenharmony_ci	if (has_sdtv && (dev->has_vid_cap || dev->has_vbi_cap)) {
16728c2ecf20Sopenharmony_ci		if (dev->has_vid_cap)
16738c2ecf20Sopenharmony_ci			v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_std_aspect_ratio, NULL);
16748c2ecf20Sopenharmony_ci		dev->ctrl_std_signal_mode = v4l2_ctrl_new_custom(hdl_sdtv_cap,
16758c2ecf20Sopenharmony_ci			&vivid_ctrl_std_signal_mode, NULL);
16768c2ecf20Sopenharmony_ci		dev->ctrl_standard = v4l2_ctrl_new_custom(hdl_sdtv_cap,
16778c2ecf20Sopenharmony_ci			&vivid_ctrl_standard, NULL);
16788c2ecf20Sopenharmony_ci		if (dev->ctrl_std_signal_mode)
16798c2ecf20Sopenharmony_ci			v4l2_ctrl_cluster(2, &dev->ctrl_std_signal_mode);
16808c2ecf20Sopenharmony_ci		if (dev->has_raw_vbi_cap)
16818c2ecf20Sopenharmony_ci			v4l2_ctrl_new_custom(hdl_vbi_cap, &vivid_ctrl_vbi_cap_interlaced, NULL);
16828c2ecf20Sopenharmony_ci	}
16838c2ecf20Sopenharmony_ci
16848c2ecf20Sopenharmony_ci	if (dev->num_hdmi_inputs) {
16858c2ecf20Sopenharmony_ci		s64 hdmi_input_mask = GENMASK(dev->num_hdmi_inputs - 1, 0);
16868c2ecf20Sopenharmony_ci
16878c2ecf20Sopenharmony_ci		dev->ctrl_dv_timings_signal_mode = v4l2_ctrl_new_custom(hdl_vid_cap,
16888c2ecf20Sopenharmony_ci					&vivid_ctrl_dv_timings_signal_mode, NULL);
16898c2ecf20Sopenharmony_ci
16908c2ecf20Sopenharmony_ci		vivid_ctrl_dv_timings.max = dev->query_dv_timings_size - 1;
16918c2ecf20Sopenharmony_ci		vivid_ctrl_dv_timings.qmenu =
16928c2ecf20Sopenharmony_ci			(const char * const *)dev->query_dv_timings_qmenu;
16938c2ecf20Sopenharmony_ci		dev->ctrl_dv_timings = v4l2_ctrl_new_custom(hdl_vid_cap,
16948c2ecf20Sopenharmony_ci			&vivid_ctrl_dv_timings, NULL);
16958c2ecf20Sopenharmony_ci		if (dev->ctrl_dv_timings_signal_mode)
16968c2ecf20Sopenharmony_ci			v4l2_ctrl_cluster(2, &dev->ctrl_dv_timings_signal_mode);
16978c2ecf20Sopenharmony_ci
16988c2ecf20Sopenharmony_ci		v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_dv_timings_aspect_ratio, NULL);
16998c2ecf20Sopenharmony_ci		v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_max_edid_blocks, NULL);
17008c2ecf20Sopenharmony_ci		dev->real_rgb_range_cap = v4l2_ctrl_new_custom(hdl_vid_cap,
17018c2ecf20Sopenharmony_ci			&vivid_ctrl_limited_rgb_range, NULL);
17028c2ecf20Sopenharmony_ci		dev->rgb_range_cap = v4l2_ctrl_new_std_menu(hdl_vid_cap,
17038c2ecf20Sopenharmony_ci			&vivid_vid_cap_ctrl_ops,
17048c2ecf20Sopenharmony_ci			V4L2_CID_DV_RX_RGB_RANGE, V4L2_DV_RGB_RANGE_FULL,
17058c2ecf20Sopenharmony_ci			0, V4L2_DV_RGB_RANGE_AUTO);
17068c2ecf20Sopenharmony_ci		dev->ctrl_rx_power_present = v4l2_ctrl_new_std(hdl_vid_cap,
17078c2ecf20Sopenharmony_ci			NULL, V4L2_CID_DV_RX_POWER_PRESENT, 0, hdmi_input_mask,
17088c2ecf20Sopenharmony_ci			0, hdmi_input_mask);
17098c2ecf20Sopenharmony_ci
17108c2ecf20Sopenharmony_ci	}
17118c2ecf20Sopenharmony_ci	if (dev->num_hdmi_outputs) {
17128c2ecf20Sopenharmony_ci		s64 hdmi_output_mask = GENMASK(dev->num_hdmi_outputs - 1, 0);
17138c2ecf20Sopenharmony_ci
17148c2ecf20Sopenharmony_ci		/*
17158c2ecf20Sopenharmony_ci		 * We aren't doing anything with this at the moment, but
17168c2ecf20Sopenharmony_ci		 * HDMI outputs typically have this controls.
17178c2ecf20Sopenharmony_ci		 */
17188c2ecf20Sopenharmony_ci		dev->ctrl_tx_rgb_range = v4l2_ctrl_new_std_menu(hdl_vid_out, NULL,
17198c2ecf20Sopenharmony_ci			V4L2_CID_DV_TX_RGB_RANGE, V4L2_DV_RGB_RANGE_FULL,
17208c2ecf20Sopenharmony_ci			0, V4L2_DV_RGB_RANGE_AUTO);
17218c2ecf20Sopenharmony_ci		dev->ctrl_tx_mode = v4l2_ctrl_new_std_menu(hdl_vid_out, NULL,
17228c2ecf20Sopenharmony_ci			V4L2_CID_DV_TX_MODE, V4L2_DV_TX_MODE_HDMI,
17238c2ecf20Sopenharmony_ci			0, V4L2_DV_TX_MODE_HDMI);
17248c2ecf20Sopenharmony_ci		dev->ctrl_display_present = v4l2_ctrl_new_custom(hdl_vid_out,
17258c2ecf20Sopenharmony_ci			&vivid_ctrl_display_present, NULL);
17268c2ecf20Sopenharmony_ci		dev->ctrl_tx_hotplug = v4l2_ctrl_new_std(hdl_vid_out,
17278c2ecf20Sopenharmony_ci			NULL, V4L2_CID_DV_TX_HOTPLUG, 0, hdmi_output_mask,
17288c2ecf20Sopenharmony_ci			0, hdmi_output_mask);
17298c2ecf20Sopenharmony_ci		dev->ctrl_tx_rxsense = v4l2_ctrl_new_std(hdl_vid_out,
17308c2ecf20Sopenharmony_ci			NULL, V4L2_CID_DV_TX_RXSENSE, 0, hdmi_output_mask,
17318c2ecf20Sopenharmony_ci			0, hdmi_output_mask);
17328c2ecf20Sopenharmony_ci		dev->ctrl_tx_edid_present = v4l2_ctrl_new_std(hdl_vid_out,
17338c2ecf20Sopenharmony_ci			NULL, V4L2_CID_DV_TX_EDID_PRESENT, 0, hdmi_output_mask,
17348c2ecf20Sopenharmony_ci			0, hdmi_output_mask);
17358c2ecf20Sopenharmony_ci	}
17368c2ecf20Sopenharmony_ci	if ((dev->has_vid_cap && dev->has_vid_out) ||
17378c2ecf20Sopenharmony_ci	    (dev->has_vbi_cap && dev->has_vbi_out))
17388c2ecf20Sopenharmony_ci		v4l2_ctrl_new_custom(hdl_loop_cap, &vivid_ctrl_loop_video, NULL);
17398c2ecf20Sopenharmony_ci
17408c2ecf20Sopenharmony_ci	if (dev->has_fb)
17418c2ecf20Sopenharmony_ci		v4l2_ctrl_new_custom(hdl_fb, &vivid_ctrl_clear_fb, NULL);
17428c2ecf20Sopenharmony_ci
17438c2ecf20Sopenharmony_ci	if (dev->has_radio_rx) {
17448c2ecf20Sopenharmony_ci		v4l2_ctrl_new_custom(hdl_radio_rx, &vivid_ctrl_radio_hw_seek_mode, NULL);
17458c2ecf20Sopenharmony_ci		v4l2_ctrl_new_custom(hdl_radio_rx, &vivid_ctrl_radio_hw_seek_prog_lim, NULL);
17468c2ecf20Sopenharmony_ci		v4l2_ctrl_new_custom(hdl_radio_rx, &vivid_ctrl_radio_rx_rds_blockio, NULL);
17478c2ecf20Sopenharmony_ci		v4l2_ctrl_new_custom(hdl_radio_rx, &vivid_ctrl_radio_rx_rds_rbds, NULL);
17488c2ecf20Sopenharmony_ci		v4l2_ctrl_new_std(hdl_radio_rx, &vivid_radio_rx_ctrl_ops,
17498c2ecf20Sopenharmony_ci			V4L2_CID_RDS_RECEPTION, 0, 1, 1, 1);
17508c2ecf20Sopenharmony_ci		dev->radio_rx_rds_pty = v4l2_ctrl_new_std(hdl_radio_rx,
17518c2ecf20Sopenharmony_ci			&vivid_radio_rx_ctrl_ops,
17528c2ecf20Sopenharmony_ci			V4L2_CID_RDS_RX_PTY, 0, 31, 1, 0);
17538c2ecf20Sopenharmony_ci		dev->radio_rx_rds_psname = v4l2_ctrl_new_std(hdl_radio_rx,
17548c2ecf20Sopenharmony_ci			&vivid_radio_rx_ctrl_ops,
17558c2ecf20Sopenharmony_ci			V4L2_CID_RDS_RX_PS_NAME, 0, 8, 8, 0);
17568c2ecf20Sopenharmony_ci		dev->radio_rx_rds_radiotext = v4l2_ctrl_new_std(hdl_radio_rx,
17578c2ecf20Sopenharmony_ci			&vivid_radio_rx_ctrl_ops,
17588c2ecf20Sopenharmony_ci			V4L2_CID_RDS_RX_RADIO_TEXT, 0, 64, 64, 0);
17598c2ecf20Sopenharmony_ci		dev->radio_rx_rds_ta = v4l2_ctrl_new_std(hdl_radio_rx,
17608c2ecf20Sopenharmony_ci			&vivid_radio_rx_ctrl_ops,
17618c2ecf20Sopenharmony_ci			V4L2_CID_RDS_RX_TRAFFIC_ANNOUNCEMENT, 0, 1, 1, 0);
17628c2ecf20Sopenharmony_ci		dev->radio_rx_rds_tp = v4l2_ctrl_new_std(hdl_radio_rx,
17638c2ecf20Sopenharmony_ci			&vivid_radio_rx_ctrl_ops,
17648c2ecf20Sopenharmony_ci			V4L2_CID_RDS_RX_TRAFFIC_PROGRAM, 0, 1, 1, 0);
17658c2ecf20Sopenharmony_ci		dev->radio_rx_rds_ms = v4l2_ctrl_new_std(hdl_radio_rx,
17668c2ecf20Sopenharmony_ci			&vivid_radio_rx_ctrl_ops,
17678c2ecf20Sopenharmony_ci			V4L2_CID_RDS_RX_MUSIC_SPEECH, 0, 1, 1, 1);
17688c2ecf20Sopenharmony_ci	}
17698c2ecf20Sopenharmony_ci	if (dev->has_radio_tx) {
17708c2ecf20Sopenharmony_ci		v4l2_ctrl_new_custom(hdl_radio_tx,
17718c2ecf20Sopenharmony_ci			&vivid_ctrl_radio_tx_rds_blockio, NULL);
17728c2ecf20Sopenharmony_ci		dev->radio_tx_rds_pi = v4l2_ctrl_new_std(hdl_radio_tx,
17738c2ecf20Sopenharmony_ci			&vivid_radio_tx_ctrl_ops,
17748c2ecf20Sopenharmony_ci			V4L2_CID_RDS_TX_PI, 0, 0xffff, 1, 0x8088);
17758c2ecf20Sopenharmony_ci		dev->radio_tx_rds_pty = v4l2_ctrl_new_std(hdl_radio_tx,
17768c2ecf20Sopenharmony_ci			&vivid_radio_tx_ctrl_ops,
17778c2ecf20Sopenharmony_ci			V4L2_CID_RDS_TX_PTY, 0, 31, 1, 3);
17788c2ecf20Sopenharmony_ci		dev->radio_tx_rds_psname = v4l2_ctrl_new_std(hdl_radio_tx,
17798c2ecf20Sopenharmony_ci			&vivid_radio_tx_ctrl_ops,
17808c2ecf20Sopenharmony_ci			V4L2_CID_RDS_TX_PS_NAME, 0, 8, 8, 0);
17818c2ecf20Sopenharmony_ci		if (dev->radio_tx_rds_psname)
17828c2ecf20Sopenharmony_ci			v4l2_ctrl_s_ctrl_string(dev->radio_tx_rds_psname, "VIVID-TX");
17838c2ecf20Sopenharmony_ci		dev->radio_tx_rds_radiotext = v4l2_ctrl_new_std(hdl_radio_tx,
17848c2ecf20Sopenharmony_ci			&vivid_radio_tx_ctrl_ops,
17858c2ecf20Sopenharmony_ci			V4L2_CID_RDS_TX_RADIO_TEXT, 0, 64 * 2, 64, 0);
17868c2ecf20Sopenharmony_ci		if (dev->radio_tx_rds_radiotext)
17878c2ecf20Sopenharmony_ci			v4l2_ctrl_s_ctrl_string(dev->radio_tx_rds_radiotext,
17888c2ecf20Sopenharmony_ci			       "This is a VIVID default Radio Text template text, change at will");
17898c2ecf20Sopenharmony_ci		dev->radio_tx_rds_mono_stereo = v4l2_ctrl_new_std(hdl_radio_tx,
17908c2ecf20Sopenharmony_ci			&vivid_radio_tx_ctrl_ops,
17918c2ecf20Sopenharmony_ci			V4L2_CID_RDS_TX_MONO_STEREO, 0, 1, 1, 1);
17928c2ecf20Sopenharmony_ci		dev->radio_tx_rds_art_head = v4l2_ctrl_new_std(hdl_radio_tx,
17938c2ecf20Sopenharmony_ci			&vivid_radio_tx_ctrl_ops,
17948c2ecf20Sopenharmony_ci			V4L2_CID_RDS_TX_ARTIFICIAL_HEAD, 0, 1, 1, 0);
17958c2ecf20Sopenharmony_ci		dev->radio_tx_rds_compressed = v4l2_ctrl_new_std(hdl_radio_tx,
17968c2ecf20Sopenharmony_ci			&vivid_radio_tx_ctrl_ops,
17978c2ecf20Sopenharmony_ci			V4L2_CID_RDS_TX_COMPRESSED, 0, 1, 1, 0);
17988c2ecf20Sopenharmony_ci		dev->radio_tx_rds_dyn_pty = v4l2_ctrl_new_std(hdl_radio_tx,
17998c2ecf20Sopenharmony_ci			&vivid_radio_tx_ctrl_ops,
18008c2ecf20Sopenharmony_ci			V4L2_CID_RDS_TX_DYNAMIC_PTY, 0, 1, 1, 0);
18018c2ecf20Sopenharmony_ci		dev->radio_tx_rds_ta = v4l2_ctrl_new_std(hdl_radio_tx,
18028c2ecf20Sopenharmony_ci			&vivid_radio_tx_ctrl_ops,
18038c2ecf20Sopenharmony_ci			V4L2_CID_RDS_TX_TRAFFIC_ANNOUNCEMENT, 0, 1, 1, 0);
18048c2ecf20Sopenharmony_ci		dev->radio_tx_rds_tp = v4l2_ctrl_new_std(hdl_radio_tx,
18058c2ecf20Sopenharmony_ci			&vivid_radio_tx_ctrl_ops,
18068c2ecf20Sopenharmony_ci			V4L2_CID_RDS_TX_TRAFFIC_PROGRAM, 0, 1, 1, 1);
18078c2ecf20Sopenharmony_ci		dev->radio_tx_rds_ms = v4l2_ctrl_new_std(hdl_radio_tx,
18088c2ecf20Sopenharmony_ci			&vivid_radio_tx_ctrl_ops,
18098c2ecf20Sopenharmony_ci			V4L2_CID_RDS_TX_MUSIC_SPEECH, 0, 1, 1, 1);
18108c2ecf20Sopenharmony_ci	}
18118c2ecf20Sopenharmony_ci	if (dev->has_sdr_cap) {
18128c2ecf20Sopenharmony_ci		v4l2_ctrl_new_custom(hdl_sdr_cap,
18138c2ecf20Sopenharmony_ci			&vivid_ctrl_sdr_cap_fm_deviation, NULL);
18148c2ecf20Sopenharmony_ci	}
18158c2ecf20Sopenharmony_ci	if (dev->has_meta_cap) {
18168c2ecf20Sopenharmony_ci		v4l2_ctrl_new_custom(hdl_meta_cap,
18178c2ecf20Sopenharmony_ci				     &vivid_ctrl_meta_has_pts, NULL);
18188c2ecf20Sopenharmony_ci		v4l2_ctrl_new_custom(hdl_meta_cap,
18198c2ecf20Sopenharmony_ci				     &vivid_ctrl_meta_has_src_clk, NULL);
18208c2ecf20Sopenharmony_ci	}
18218c2ecf20Sopenharmony_ci
18228c2ecf20Sopenharmony_ci	if (hdl_user_gen->error)
18238c2ecf20Sopenharmony_ci		return hdl_user_gen->error;
18248c2ecf20Sopenharmony_ci	if (hdl_user_vid->error)
18258c2ecf20Sopenharmony_ci		return hdl_user_vid->error;
18268c2ecf20Sopenharmony_ci	if (hdl_user_aud->error)
18278c2ecf20Sopenharmony_ci		return hdl_user_aud->error;
18288c2ecf20Sopenharmony_ci	if (hdl_streaming->error)
18298c2ecf20Sopenharmony_ci		return hdl_streaming->error;
18308c2ecf20Sopenharmony_ci	if (hdl_sdr_cap->error)
18318c2ecf20Sopenharmony_ci		return hdl_sdr_cap->error;
18328c2ecf20Sopenharmony_ci	if (hdl_loop_cap->error)
18338c2ecf20Sopenharmony_ci		return hdl_loop_cap->error;
18348c2ecf20Sopenharmony_ci
18358c2ecf20Sopenharmony_ci	if (dev->autogain)
18368c2ecf20Sopenharmony_ci		v4l2_ctrl_auto_cluster(2, &dev->autogain, 0, true);
18378c2ecf20Sopenharmony_ci
18388c2ecf20Sopenharmony_ci	if (dev->has_vid_cap) {
18398c2ecf20Sopenharmony_ci		v4l2_ctrl_add_handler(hdl_vid_cap, hdl_user_gen, NULL, false);
18408c2ecf20Sopenharmony_ci		v4l2_ctrl_add_handler(hdl_vid_cap, hdl_user_vid, NULL, false);
18418c2ecf20Sopenharmony_ci		v4l2_ctrl_add_handler(hdl_vid_cap, hdl_user_aud, NULL, false);
18428c2ecf20Sopenharmony_ci		v4l2_ctrl_add_handler(hdl_vid_cap, hdl_streaming, NULL, false);
18438c2ecf20Sopenharmony_ci		v4l2_ctrl_add_handler(hdl_vid_cap, hdl_sdtv_cap, NULL, false);
18448c2ecf20Sopenharmony_ci		v4l2_ctrl_add_handler(hdl_vid_cap, hdl_loop_cap, NULL, false);
18458c2ecf20Sopenharmony_ci		v4l2_ctrl_add_handler(hdl_vid_cap, hdl_fb, NULL, false);
18468c2ecf20Sopenharmony_ci		if (hdl_vid_cap->error)
18478c2ecf20Sopenharmony_ci			return hdl_vid_cap->error;
18488c2ecf20Sopenharmony_ci		dev->vid_cap_dev.ctrl_handler = hdl_vid_cap;
18498c2ecf20Sopenharmony_ci	}
18508c2ecf20Sopenharmony_ci	if (dev->has_vid_out) {
18518c2ecf20Sopenharmony_ci		v4l2_ctrl_add_handler(hdl_vid_out, hdl_user_gen, NULL, false);
18528c2ecf20Sopenharmony_ci		v4l2_ctrl_add_handler(hdl_vid_out, hdl_user_aud, NULL, false);
18538c2ecf20Sopenharmony_ci		v4l2_ctrl_add_handler(hdl_vid_out, hdl_streaming, NULL, false);
18548c2ecf20Sopenharmony_ci		v4l2_ctrl_add_handler(hdl_vid_out, hdl_fb, NULL, false);
18558c2ecf20Sopenharmony_ci		if (hdl_vid_out->error)
18568c2ecf20Sopenharmony_ci			return hdl_vid_out->error;
18578c2ecf20Sopenharmony_ci		dev->vid_out_dev.ctrl_handler = hdl_vid_out;
18588c2ecf20Sopenharmony_ci	}
18598c2ecf20Sopenharmony_ci	if (dev->has_vbi_cap) {
18608c2ecf20Sopenharmony_ci		v4l2_ctrl_add_handler(hdl_vbi_cap, hdl_user_gen, NULL, false);
18618c2ecf20Sopenharmony_ci		v4l2_ctrl_add_handler(hdl_vbi_cap, hdl_streaming, NULL, false);
18628c2ecf20Sopenharmony_ci		v4l2_ctrl_add_handler(hdl_vbi_cap, hdl_sdtv_cap, NULL, false);
18638c2ecf20Sopenharmony_ci		v4l2_ctrl_add_handler(hdl_vbi_cap, hdl_loop_cap, NULL, false);
18648c2ecf20Sopenharmony_ci		if (hdl_vbi_cap->error)
18658c2ecf20Sopenharmony_ci			return hdl_vbi_cap->error;
18668c2ecf20Sopenharmony_ci		dev->vbi_cap_dev.ctrl_handler = hdl_vbi_cap;
18678c2ecf20Sopenharmony_ci	}
18688c2ecf20Sopenharmony_ci	if (dev->has_vbi_out) {
18698c2ecf20Sopenharmony_ci		v4l2_ctrl_add_handler(hdl_vbi_out, hdl_user_gen, NULL, false);
18708c2ecf20Sopenharmony_ci		v4l2_ctrl_add_handler(hdl_vbi_out, hdl_streaming, NULL, false);
18718c2ecf20Sopenharmony_ci		if (hdl_vbi_out->error)
18728c2ecf20Sopenharmony_ci			return hdl_vbi_out->error;
18738c2ecf20Sopenharmony_ci		dev->vbi_out_dev.ctrl_handler = hdl_vbi_out;
18748c2ecf20Sopenharmony_ci	}
18758c2ecf20Sopenharmony_ci	if (dev->has_radio_rx) {
18768c2ecf20Sopenharmony_ci		v4l2_ctrl_add_handler(hdl_radio_rx, hdl_user_gen, NULL, false);
18778c2ecf20Sopenharmony_ci		v4l2_ctrl_add_handler(hdl_radio_rx, hdl_user_aud, NULL, false);
18788c2ecf20Sopenharmony_ci		if (hdl_radio_rx->error)
18798c2ecf20Sopenharmony_ci			return hdl_radio_rx->error;
18808c2ecf20Sopenharmony_ci		dev->radio_rx_dev.ctrl_handler = hdl_radio_rx;
18818c2ecf20Sopenharmony_ci	}
18828c2ecf20Sopenharmony_ci	if (dev->has_radio_tx) {
18838c2ecf20Sopenharmony_ci		v4l2_ctrl_add_handler(hdl_radio_tx, hdl_user_gen, NULL, false);
18848c2ecf20Sopenharmony_ci		v4l2_ctrl_add_handler(hdl_radio_tx, hdl_user_aud, NULL, false);
18858c2ecf20Sopenharmony_ci		if (hdl_radio_tx->error)
18868c2ecf20Sopenharmony_ci			return hdl_radio_tx->error;
18878c2ecf20Sopenharmony_ci		dev->radio_tx_dev.ctrl_handler = hdl_radio_tx;
18888c2ecf20Sopenharmony_ci	}
18898c2ecf20Sopenharmony_ci	if (dev->has_sdr_cap) {
18908c2ecf20Sopenharmony_ci		v4l2_ctrl_add_handler(hdl_sdr_cap, hdl_user_gen, NULL, false);
18918c2ecf20Sopenharmony_ci		v4l2_ctrl_add_handler(hdl_sdr_cap, hdl_streaming, NULL, false);
18928c2ecf20Sopenharmony_ci		if (hdl_sdr_cap->error)
18938c2ecf20Sopenharmony_ci			return hdl_sdr_cap->error;
18948c2ecf20Sopenharmony_ci		dev->sdr_cap_dev.ctrl_handler = hdl_sdr_cap;
18958c2ecf20Sopenharmony_ci	}
18968c2ecf20Sopenharmony_ci	if (dev->has_meta_cap) {
18978c2ecf20Sopenharmony_ci		v4l2_ctrl_add_handler(hdl_meta_cap, hdl_user_gen, NULL, false);
18988c2ecf20Sopenharmony_ci		v4l2_ctrl_add_handler(hdl_meta_cap, hdl_streaming, NULL, false);
18998c2ecf20Sopenharmony_ci		if (hdl_meta_cap->error)
19008c2ecf20Sopenharmony_ci			return hdl_meta_cap->error;
19018c2ecf20Sopenharmony_ci		dev->meta_cap_dev.ctrl_handler = hdl_meta_cap;
19028c2ecf20Sopenharmony_ci	}
19038c2ecf20Sopenharmony_ci	if (dev->has_meta_out) {
19048c2ecf20Sopenharmony_ci		v4l2_ctrl_add_handler(hdl_meta_out, hdl_user_gen, NULL, false);
19058c2ecf20Sopenharmony_ci		v4l2_ctrl_add_handler(hdl_meta_out, hdl_streaming, NULL, false);
19068c2ecf20Sopenharmony_ci		if (hdl_meta_out->error)
19078c2ecf20Sopenharmony_ci			return hdl_meta_out->error;
19088c2ecf20Sopenharmony_ci		dev->meta_out_dev.ctrl_handler = hdl_meta_out;
19098c2ecf20Sopenharmony_ci	}
19108c2ecf20Sopenharmony_ci	if (dev->has_touch_cap) {
19118c2ecf20Sopenharmony_ci		v4l2_ctrl_add_handler(hdl_tch_cap, hdl_user_gen, NULL, false);
19128c2ecf20Sopenharmony_ci		v4l2_ctrl_add_handler(hdl_tch_cap, hdl_streaming, NULL, false);
19138c2ecf20Sopenharmony_ci		if (hdl_tch_cap->error)
19148c2ecf20Sopenharmony_ci			return hdl_tch_cap->error;
19158c2ecf20Sopenharmony_ci		dev->touch_cap_dev.ctrl_handler = hdl_tch_cap;
19168c2ecf20Sopenharmony_ci	}
19178c2ecf20Sopenharmony_ci	return 0;
19188c2ecf20Sopenharmony_ci}
19198c2ecf20Sopenharmony_ci
19208c2ecf20Sopenharmony_civoid vivid_free_controls(struct vivid_dev *dev)
19218c2ecf20Sopenharmony_ci{
19228c2ecf20Sopenharmony_ci	v4l2_ctrl_handler_free(&dev->ctrl_hdl_vid_cap);
19238c2ecf20Sopenharmony_ci	v4l2_ctrl_handler_free(&dev->ctrl_hdl_vid_out);
19248c2ecf20Sopenharmony_ci	v4l2_ctrl_handler_free(&dev->ctrl_hdl_vbi_cap);
19258c2ecf20Sopenharmony_ci	v4l2_ctrl_handler_free(&dev->ctrl_hdl_vbi_out);
19268c2ecf20Sopenharmony_ci	v4l2_ctrl_handler_free(&dev->ctrl_hdl_radio_rx);
19278c2ecf20Sopenharmony_ci	v4l2_ctrl_handler_free(&dev->ctrl_hdl_radio_tx);
19288c2ecf20Sopenharmony_ci	v4l2_ctrl_handler_free(&dev->ctrl_hdl_sdr_cap);
19298c2ecf20Sopenharmony_ci	v4l2_ctrl_handler_free(&dev->ctrl_hdl_user_gen);
19308c2ecf20Sopenharmony_ci	v4l2_ctrl_handler_free(&dev->ctrl_hdl_user_vid);
19318c2ecf20Sopenharmony_ci	v4l2_ctrl_handler_free(&dev->ctrl_hdl_user_aud);
19328c2ecf20Sopenharmony_ci	v4l2_ctrl_handler_free(&dev->ctrl_hdl_streaming);
19338c2ecf20Sopenharmony_ci	v4l2_ctrl_handler_free(&dev->ctrl_hdl_sdtv_cap);
19348c2ecf20Sopenharmony_ci	v4l2_ctrl_handler_free(&dev->ctrl_hdl_loop_cap);
19358c2ecf20Sopenharmony_ci	v4l2_ctrl_handler_free(&dev->ctrl_hdl_fb);
19368c2ecf20Sopenharmony_ci	v4l2_ctrl_handler_free(&dev->ctrl_hdl_meta_cap);
19378c2ecf20Sopenharmony_ci	v4l2_ctrl_handler_free(&dev->ctrl_hdl_meta_out);
19388c2ecf20Sopenharmony_ci	v4l2_ctrl_handler_free(&dev->ctrl_hdl_touch_cap);
19398c2ecf20Sopenharmony_ci}
1940