162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * vivid-ctrls.c - control support functions.
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright 2014 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
662306a36Sopenharmony_ci */
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#include <linux/errno.h>
962306a36Sopenharmony_ci#include <linux/kernel.h>
1062306a36Sopenharmony_ci#include <linux/videodev2.h>
1162306a36Sopenharmony_ci#include <media/v4l2-event.h>
1262306a36Sopenharmony_ci#include <media/v4l2-common.h>
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_ci#include "vivid-core.h"
1562306a36Sopenharmony_ci#include "vivid-vid-cap.h"
1662306a36Sopenharmony_ci#include "vivid-vid-out.h"
1762306a36Sopenharmony_ci#include "vivid-vid-common.h"
1862306a36Sopenharmony_ci#include "vivid-radio-common.h"
1962306a36Sopenharmony_ci#include "vivid-osd.h"
2062306a36Sopenharmony_ci#include "vivid-ctrls.h"
2162306a36Sopenharmony_ci#include "vivid-cec.h"
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_ci#define VIVID_CID_CUSTOM_BASE		(V4L2_CID_USER_BASE | 0xf000)
2462306a36Sopenharmony_ci#define VIVID_CID_BUTTON		(VIVID_CID_CUSTOM_BASE + 0)
2562306a36Sopenharmony_ci#define VIVID_CID_BOOLEAN		(VIVID_CID_CUSTOM_BASE + 1)
2662306a36Sopenharmony_ci#define VIVID_CID_INTEGER		(VIVID_CID_CUSTOM_BASE + 2)
2762306a36Sopenharmony_ci#define VIVID_CID_INTEGER64		(VIVID_CID_CUSTOM_BASE + 3)
2862306a36Sopenharmony_ci#define VIVID_CID_MENU			(VIVID_CID_CUSTOM_BASE + 4)
2962306a36Sopenharmony_ci#define VIVID_CID_STRING		(VIVID_CID_CUSTOM_BASE + 5)
3062306a36Sopenharmony_ci#define VIVID_CID_BITMASK		(VIVID_CID_CUSTOM_BASE + 6)
3162306a36Sopenharmony_ci#define VIVID_CID_INTMENU		(VIVID_CID_CUSTOM_BASE + 7)
3262306a36Sopenharmony_ci#define VIVID_CID_U32_ARRAY		(VIVID_CID_CUSTOM_BASE + 8)
3362306a36Sopenharmony_ci#define VIVID_CID_U16_MATRIX		(VIVID_CID_CUSTOM_BASE + 9)
3462306a36Sopenharmony_ci#define VIVID_CID_U8_4D_ARRAY		(VIVID_CID_CUSTOM_BASE + 10)
3562306a36Sopenharmony_ci#define VIVID_CID_AREA			(VIVID_CID_CUSTOM_BASE + 11)
3662306a36Sopenharmony_ci#define VIVID_CID_RO_INTEGER		(VIVID_CID_CUSTOM_BASE + 12)
3762306a36Sopenharmony_ci#define VIVID_CID_U32_DYN_ARRAY		(VIVID_CID_CUSTOM_BASE + 13)
3862306a36Sopenharmony_ci#define VIVID_CID_U8_PIXEL_ARRAY	(VIVID_CID_CUSTOM_BASE + 14)
3962306a36Sopenharmony_ci#define VIVID_CID_S32_ARRAY		(VIVID_CID_CUSTOM_BASE + 15)
4062306a36Sopenharmony_ci#define VIVID_CID_S64_ARRAY		(VIVID_CID_CUSTOM_BASE + 16)
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ci#define VIVID_CID_VIVID_BASE		(0x00f00000 | 0xf000)
4362306a36Sopenharmony_ci#define VIVID_CID_VIVID_CLASS		(0x00f00000 | 1)
4462306a36Sopenharmony_ci#define VIVID_CID_TEST_PATTERN		(VIVID_CID_VIVID_BASE + 0)
4562306a36Sopenharmony_ci#define VIVID_CID_OSD_TEXT_MODE		(VIVID_CID_VIVID_BASE + 1)
4662306a36Sopenharmony_ci#define VIVID_CID_HOR_MOVEMENT		(VIVID_CID_VIVID_BASE + 2)
4762306a36Sopenharmony_ci#define VIVID_CID_VERT_MOVEMENT		(VIVID_CID_VIVID_BASE + 3)
4862306a36Sopenharmony_ci#define VIVID_CID_SHOW_BORDER		(VIVID_CID_VIVID_BASE + 4)
4962306a36Sopenharmony_ci#define VIVID_CID_SHOW_SQUARE		(VIVID_CID_VIVID_BASE + 5)
5062306a36Sopenharmony_ci#define VIVID_CID_INSERT_SAV		(VIVID_CID_VIVID_BASE + 6)
5162306a36Sopenharmony_ci#define VIVID_CID_INSERT_EAV		(VIVID_CID_VIVID_BASE + 7)
5262306a36Sopenharmony_ci#define VIVID_CID_VBI_CAP_INTERLACED	(VIVID_CID_VIVID_BASE + 8)
5362306a36Sopenharmony_ci#define VIVID_CID_INSERT_HDMI_VIDEO_GUARD_BAND (VIVID_CID_VIVID_BASE + 9)
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ci#define VIVID_CID_HFLIP			(VIVID_CID_VIVID_BASE + 20)
5662306a36Sopenharmony_ci#define VIVID_CID_VFLIP			(VIVID_CID_VIVID_BASE + 21)
5762306a36Sopenharmony_ci#define VIVID_CID_STD_ASPECT_RATIO	(VIVID_CID_VIVID_BASE + 22)
5862306a36Sopenharmony_ci#define VIVID_CID_DV_TIMINGS_ASPECT_RATIO	(VIVID_CID_VIVID_BASE + 23)
5962306a36Sopenharmony_ci#define VIVID_CID_TSTAMP_SRC		(VIVID_CID_VIVID_BASE + 24)
6062306a36Sopenharmony_ci#define VIVID_CID_COLORSPACE		(VIVID_CID_VIVID_BASE + 25)
6162306a36Sopenharmony_ci#define VIVID_CID_XFER_FUNC		(VIVID_CID_VIVID_BASE + 26)
6262306a36Sopenharmony_ci#define VIVID_CID_YCBCR_ENC		(VIVID_CID_VIVID_BASE + 27)
6362306a36Sopenharmony_ci#define VIVID_CID_QUANTIZATION		(VIVID_CID_VIVID_BASE + 28)
6462306a36Sopenharmony_ci#define VIVID_CID_LIMITED_RGB_RANGE	(VIVID_CID_VIVID_BASE + 29)
6562306a36Sopenharmony_ci#define VIVID_CID_ALPHA_MODE		(VIVID_CID_VIVID_BASE + 30)
6662306a36Sopenharmony_ci#define VIVID_CID_HAS_CROP_CAP		(VIVID_CID_VIVID_BASE + 31)
6762306a36Sopenharmony_ci#define VIVID_CID_HAS_COMPOSE_CAP	(VIVID_CID_VIVID_BASE + 32)
6862306a36Sopenharmony_ci#define VIVID_CID_HAS_SCALER_CAP	(VIVID_CID_VIVID_BASE + 33)
6962306a36Sopenharmony_ci#define VIVID_CID_HAS_CROP_OUT		(VIVID_CID_VIVID_BASE + 34)
7062306a36Sopenharmony_ci#define VIVID_CID_HAS_COMPOSE_OUT	(VIVID_CID_VIVID_BASE + 35)
7162306a36Sopenharmony_ci#define VIVID_CID_HAS_SCALER_OUT	(VIVID_CID_VIVID_BASE + 36)
7262306a36Sopenharmony_ci#define VIVID_CID_LOOP_VIDEO		(VIVID_CID_VIVID_BASE + 37)
7362306a36Sopenharmony_ci#define VIVID_CID_SEQ_WRAP		(VIVID_CID_VIVID_BASE + 38)
7462306a36Sopenharmony_ci#define VIVID_CID_TIME_WRAP		(VIVID_CID_VIVID_BASE + 39)
7562306a36Sopenharmony_ci#define VIVID_CID_MAX_EDID_BLOCKS	(VIVID_CID_VIVID_BASE + 40)
7662306a36Sopenharmony_ci#define VIVID_CID_PERCENTAGE_FILL	(VIVID_CID_VIVID_BASE + 41)
7762306a36Sopenharmony_ci#define VIVID_CID_REDUCED_FPS		(VIVID_CID_VIVID_BASE + 42)
7862306a36Sopenharmony_ci#define VIVID_CID_HSV_ENC		(VIVID_CID_VIVID_BASE + 43)
7962306a36Sopenharmony_ci#define VIVID_CID_DISPLAY_PRESENT	(VIVID_CID_VIVID_BASE + 44)
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_ci#define VIVID_CID_STD_SIGNAL_MODE	(VIVID_CID_VIVID_BASE + 60)
8262306a36Sopenharmony_ci#define VIVID_CID_STANDARD		(VIVID_CID_VIVID_BASE + 61)
8362306a36Sopenharmony_ci#define VIVID_CID_DV_TIMINGS_SIGNAL_MODE	(VIVID_CID_VIVID_BASE + 62)
8462306a36Sopenharmony_ci#define VIVID_CID_DV_TIMINGS		(VIVID_CID_VIVID_BASE + 63)
8562306a36Sopenharmony_ci#define VIVID_CID_PERC_DROPPED		(VIVID_CID_VIVID_BASE + 64)
8662306a36Sopenharmony_ci#define VIVID_CID_DISCONNECT		(VIVID_CID_VIVID_BASE + 65)
8762306a36Sopenharmony_ci#define VIVID_CID_DQBUF_ERROR		(VIVID_CID_VIVID_BASE + 66)
8862306a36Sopenharmony_ci#define VIVID_CID_QUEUE_SETUP_ERROR	(VIVID_CID_VIVID_BASE + 67)
8962306a36Sopenharmony_ci#define VIVID_CID_BUF_PREPARE_ERROR	(VIVID_CID_VIVID_BASE + 68)
9062306a36Sopenharmony_ci#define VIVID_CID_START_STR_ERROR	(VIVID_CID_VIVID_BASE + 69)
9162306a36Sopenharmony_ci#define VIVID_CID_QUEUE_ERROR		(VIVID_CID_VIVID_BASE + 70)
9262306a36Sopenharmony_ci#define VIVID_CID_CLEAR_FB		(VIVID_CID_VIVID_BASE + 71)
9362306a36Sopenharmony_ci#define VIVID_CID_REQ_VALIDATE_ERROR	(VIVID_CID_VIVID_BASE + 72)
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_ci#define VIVID_CID_RADIO_SEEK_MODE	(VIVID_CID_VIVID_BASE + 90)
9662306a36Sopenharmony_ci#define VIVID_CID_RADIO_SEEK_PROG_LIM	(VIVID_CID_VIVID_BASE + 91)
9762306a36Sopenharmony_ci#define VIVID_CID_RADIO_RX_RDS_RBDS	(VIVID_CID_VIVID_BASE + 92)
9862306a36Sopenharmony_ci#define VIVID_CID_RADIO_RX_RDS_BLOCKIO	(VIVID_CID_VIVID_BASE + 93)
9962306a36Sopenharmony_ci
10062306a36Sopenharmony_ci#define VIVID_CID_RADIO_TX_RDS_BLOCKIO	(VIVID_CID_VIVID_BASE + 94)
10162306a36Sopenharmony_ci
10262306a36Sopenharmony_ci#define VIVID_CID_SDR_CAP_FM_DEVIATION	(VIVID_CID_VIVID_BASE + 110)
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_ci#define VIVID_CID_META_CAP_GENERATE_PTS	(VIVID_CID_VIVID_BASE + 111)
10562306a36Sopenharmony_ci#define VIVID_CID_META_CAP_GENERATE_SCR	(VIVID_CID_VIVID_BASE + 112)
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_ci/* General User Controls */
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_cistatic void vivid_unregister_dev(bool valid, struct video_device *vdev)
11062306a36Sopenharmony_ci{
11162306a36Sopenharmony_ci	if (!valid)
11262306a36Sopenharmony_ci		return;
11362306a36Sopenharmony_ci	clear_bit(V4L2_FL_REGISTERED, &vdev->flags);
11462306a36Sopenharmony_ci	v4l2_event_wake_all(vdev);
11562306a36Sopenharmony_ci}
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_cistatic int vivid_user_gen_s_ctrl(struct v4l2_ctrl *ctrl)
11862306a36Sopenharmony_ci{
11962306a36Sopenharmony_ci	struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_user_gen);
12062306a36Sopenharmony_ci
12162306a36Sopenharmony_ci	switch (ctrl->id) {
12262306a36Sopenharmony_ci	case VIVID_CID_DISCONNECT:
12362306a36Sopenharmony_ci		v4l2_info(&dev->v4l2_dev, "disconnect\n");
12462306a36Sopenharmony_ci		dev->disconnect_error = true;
12562306a36Sopenharmony_ci		vivid_unregister_dev(dev->has_vid_cap, &dev->vid_cap_dev);
12662306a36Sopenharmony_ci		vivid_unregister_dev(dev->has_vid_out, &dev->vid_out_dev);
12762306a36Sopenharmony_ci		vivid_unregister_dev(dev->has_vbi_cap, &dev->vbi_cap_dev);
12862306a36Sopenharmony_ci		vivid_unregister_dev(dev->has_vbi_out, &dev->vbi_out_dev);
12962306a36Sopenharmony_ci		vivid_unregister_dev(dev->has_radio_rx, &dev->radio_rx_dev);
13062306a36Sopenharmony_ci		vivid_unregister_dev(dev->has_radio_tx, &dev->radio_tx_dev);
13162306a36Sopenharmony_ci		vivid_unregister_dev(dev->has_sdr_cap, &dev->sdr_cap_dev);
13262306a36Sopenharmony_ci		vivid_unregister_dev(dev->has_meta_cap, &dev->meta_cap_dev);
13362306a36Sopenharmony_ci		vivid_unregister_dev(dev->has_meta_out, &dev->meta_out_dev);
13462306a36Sopenharmony_ci		vivid_unregister_dev(dev->has_touch_cap, &dev->touch_cap_dev);
13562306a36Sopenharmony_ci		break;
13662306a36Sopenharmony_ci	case VIVID_CID_BUTTON:
13762306a36Sopenharmony_ci		dev->button_pressed = 30;
13862306a36Sopenharmony_ci		break;
13962306a36Sopenharmony_ci	}
14062306a36Sopenharmony_ci	return 0;
14162306a36Sopenharmony_ci}
14262306a36Sopenharmony_ci
14362306a36Sopenharmony_cistatic const struct v4l2_ctrl_ops vivid_user_gen_ctrl_ops = {
14462306a36Sopenharmony_ci	.s_ctrl = vivid_user_gen_s_ctrl,
14562306a36Sopenharmony_ci};
14662306a36Sopenharmony_ci
14762306a36Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_button = {
14862306a36Sopenharmony_ci	.ops = &vivid_user_gen_ctrl_ops,
14962306a36Sopenharmony_ci	.id = VIVID_CID_BUTTON,
15062306a36Sopenharmony_ci	.name = "Button",
15162306a36Sopenharmony_ci	.type = V4L2_CTRL_TYPE_BUTTON,
15262306a36Sopenharmony_ci};
15362306a36Sopenharmony_ci
15462306a36Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_boolean = {
15562306a36Sopenharmony_ci	.ops = &vivid_user_gen_ctrl_ops,
15662306a36Sopenharmony_ci	.id = VIVID_CID_BOOLEAN,
15762306a36Sopenharmony_ci	.name = "Boolean",
15862306a36Sopenharmony_ci	.type = V4L2_CTRL_TYPE_BOOLEAN,
15962306a36Sopenharmony_ci	.min = 0,
16062306a36Sopenharmony_ci	.max = 1,
16162306a36Sopenharmony_ci	.step = 1,
16262306a36Sopenharmony_ci	.def = 1,
16362306a36Sopenharmony_ci};
16462306a36Sopenharmony_ci
16562306a36Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_int32 = {
16662306a36Sopenharmony_ci	.ops = &vivid_user_gen_ctrl_ops,
16762306a36Sopenharmony_ci	.id = VIVID_CID_INTEGER,
16862306a36Sopenharmony_ci	.name = "Integer 32 Bits",
16962306a36Sopenharmony_ci	.type = V4L2_CTRL_TYPE_INTEGER,
17062306a36Sopenharmony_ci	.min = 0xffffffff80000000ULL,
17162306a36Sopenharmony_ci	.max = 0x7fffffff,
17262306a36Sopenharmony_ci	.step = 1,
17362306a36Sopenharmony_ci};
17462306a36Sopenharmony_ci
17562306a36Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_int64 = {
17662306a36Sopenharmony_ci	.ops = &vivid_user_gen_ctrl_ops,
17762306a36Sopenharmony_ci	.id = VIVID_CID_INTEGER64,
17862306a36Sopenharmony_ci	.name = "Integer 64 Bits",
17962306a36Sopenharmony_ci	.type = V4L2_CTRL_TYPE_INTEGER64,
18062306a36Sopenharmony_ci	.min = 0x8000000000000000ULL,
18162306a36Sopenharmony_ci	.max = 0x7fffffffffffffffLL,
18262306a36Sopenharmony_ci	.step = 1,
18362306a36Sopenharmony_ci};
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_u32_array = {
18662306a36Sopenharmony_ci	.ops = &vivid_user_gen_ctrl_ops,
18762306a36Sopenharmony_ci	.id = VIVID_CID_U32_ARRAY,
18862306a36Sopenharmony_ci	.name = "U32 1 Element Array",
18962306a36Sopenharmony_ci	.type = V4L2_CTRL_TYPE_U32,
19062306a36Sopenharmony_ci	.def = 0x18,
19162306a36Sopenharmony_ci	.min = 0x10,
19262306a36Sopenharmony_ci	.max = 0x20000,
19362306a36Sopenharmony_ci	.step = 1,
19462306a36Sopenharmony_ci	.dims = { 1 },
19562306a36Sopenharmony_ci};
19662306a36Sopenharmony_ci
19762306a36Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_u32_dyn_array = {
19862306a36Sopenharmony_ci	.ops = &vivid_user_gen_ctrl_ops,
19962306a36Sopenharmony_ci	.id = VIVID_CID_U32_DYN_ARRAY,
20062306a36Sopenharmony_ci	.name = "U32 Dynamic Array",
20162306a36Sopenharmony_ci	.type = V4L2_CTRL_TYPE_U32,
20262306a36Sopenharmony_ci	.flags = V4L2_CTRL_FLAG_DYNAMIC_ARRAY,
20362306a36Sopenharmony_ci	.def = 50,
20462306a36Sopenharmony_ci	.min = 10,
20562306a36Sopenharmony_ci	.max = 90,
20662306a36Sopenharmony_ci	.step = 1,
20762306a36Sopenharmony_ci	.dims = { 100 },
20862306a36Sopenharmony_ci};
20962306a36Sopenharmony_ci
21062306a36Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_u16_matrix = {
21162306a36Sopenharmony_ci	.ops = &vivid_user_gen_ctrl_ops,
21262306a36Sopenharmony_ci	.id = VIVID_CID_U16_MATRIX,
21362306a36Sopenharmony_ci	.name = "U16 8x16 Matrix",
21462306a36Sopenharmony_ci	.type = V4L2_CTRL_TYPE_U16,
21562306a36Sopenharmony_ci	.def = 0x18,
21662306a36Sopenharmony_ci	.min = 0x10,
21762306a36Sopenharmony_ci	.max = 0x2000,
21862306a36Sopenharmony_ci	.step = 1,
21962306a36Sopenharmony_ci	.dims = { 8, 16 },
22062306a36Sopenharmony_ci};
22162306a36Sopenharmony_ci
22262306a36Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_u8_4d_array = {
22362306a36Sopenharmony_ci	.ops = &vivid_user_gen_ctrl_ops,
22462306a36Sopenharmony_ci	.id = VIVID_CID_U8_4D_ARRAY,
22562306a36Sopenharmony_ci	.name = "U8 2x3x4x5 Array",
22662306a36Sopenharmony_ci	.type = V4L2_CTRL_TYPE_U8,
22762306a36Sopenharmony_ci	.def = 0x18,
22862306a36Sopenharmony_ci	.min = 0x10,
22962306a36Sopenharmony_ci	.max = 0x20,
23062306a36Sopenharmony_ci	.step = 1,
23162306a36Sopenharmony_ci	.dims = { 2, 3, 4, 5 },
23262306a36Sopenharmony_ci};
23362306a36Sopenharmony_ci
23462306a36Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_u8_pixel_array = {
23562306a36Sopenharmony_ci	.ops = &vivid_user_gen_ctrl_ops,
23662306a36Sopenharmony_ci	.id = VIVID_CID_U8_PIXEL_ARRAY,
23762306a36Sopenharmony_ci	.name = "U8 Pixel Array",
23862306a36Sopenharmony_ci	.type = V4L2_CTRL_TYPE_U8,
23962306a36Sopenharmony_ci	.def = 0x80,
24062306a36Sopenharmony_ci	.min = 0x00,
24162306a36Sopenharmony_ci	.max = 0xff,
24262306a36Sopenharmony_ci	.step = 1,
24362306a36Sopenharmony_ci	.dims = { 640 / PIXEL_ARRAY_DIV, 360 / PIXEL_ARRAY_DIV },
24462306a36Sopenharmony_ci};
24562306a36Sopenharmony_ci
24662306a36Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_s32_array = {
24762306a36Sopenharmony_ci	.ops = &vivid_user_gen_ctrl_ops,
24862306a36Sopenharmony_ci	.id = VIVID_CID_S32_ARRAY,
24962306a36Sopenharmony_ci	.name = "S32 2 Element Array",
25062306a36Sopenharmony_ci	.type = V4L2_CTRL_TYPE_INTEGER,
25162306a36Sopenharmony_ci	.def = 2,
25262306a36Sopenharmony_ci	.min = -10,
25362306a36Sopenharmony_ci	.max = 10,
25462306a36Sopenharmony_ci	.step = 1,
25562306a36Sopenharmony_ci	.dims = { 2 },
25662306a36Sopenharmony_ci};
25762306a36Sopenharmony_ci
25862306a36Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_s64_array = {
25962306a36Sopenharmony_ci	.ops = &vivid_user_gen_ctrl_ops,
26062306a36Sopenharmony_ci	.id = VIVID_CID_S64_ARRAY,
26162306a36Sopenharmony_ci	.name = "S64 5 Element Array",
26262306a36Sopenharmony_ci	.type = V4L2_CTRL_TYPE_INTEGER64,
26362306a36Sopenharmony_ci	.def = 4,
26462306a36Sopenharmony_ci	.min = -10,
26562306a36Sopenharmony_ci	.max = 10,
26662306a36Sopenharmony_ci	.step = 1,
26762306a36Sopenharmony_ci	.dims = { 5 },
26862306a36Sopenharmony_ci};
26962306a36Sopenharmony_ci
27062306a36Sopenharmony_cistatic const char * const vivid_ctrl_menu_strings[] = {
27162306a36Sopenharmony_ci	"Menu Item 0 (Skipped)",
27262306a36Sopenharmony_ci	"Menu Item 1",
27362306a36Sopenharmony_ci	"Menu Item 2 (Skipped)",
27462306a36Sopenharmony_ci	"Menu Item 3",
27562306a36Sopenharmony_ci	"Menu Item 4",
27662306a36Sopenharmony_ci	"Menu Item 5 (Skipped)",
27762306a36Sopenharmony_ci	NULL,
27862306a36Sopenharmony_ci};
27962306a36Sopenharmony_ci
28062306a36Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_menu = {
28162306a36Sopenharmony_ci	.ops = &vivid_user_gen_ctrl_ops,
28262306a36Sopenharmony_ci	.id = VIVID_CID_MENU,
28362306a36Sopenharmony_ci	.name = "Menu",
28462306a36Sopenharmony_ci	.type = V4L2_CTRL_TYPE_MENU,
28562306a36Sopenharmony_ci	.min = 1,
28662306a36Sopenharmony_ci	.max = 4,
28762306a36Sopenharmony_ci	.def = 3,
28862306a36Sopenharmony_ci	.menu_skip_mask = 0x04,
28962306a36Sopenharmony_ci	.qmenu = vivid_ctrl_menu_strings,
29062306a36Sopenharmony_ci};
29162306a36Sopenharmony_ci
29262306a36Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_string = {
29362306a36Sopenharmony_ci	.ops = &vivid_user_gen_ctrl_ops,
29462306a36Sopenharmony_ci	.id = VIVID_CID_STRING,
29562306a36Sopenharmony_ci	.name = "String",
29662306a36Sopenharmony_ci	.type = V4L2_CTRL_TYPE_STRING,
29762306a36Sopenharmony_ci	.min = 2,
29862306a36Sopenharmony_ci	.max = 4,
29962306a36Sopenharmony_ci	.step = 1,
30062306a36Sopenharmony_ci};
30162306a36Sopenharmony_ci
30262306a36Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_bitmask = {
30362306a36Sopenharmony_ci	.ops = &vivid_user_gen_ctrl_ops,
30462306a36Sopenharmony_ci	.id = VIVID_CID_BITMASK,
30562306a36Sopenharmony_ci	.name = "Bitmask",
30662306a36Sopenharmony_ci	.type = V4L2_CTRL_TYPE_BITMASK,
30762306a36Sopenharmony_ci	.def = 0x80002000,
30862306a36Sopenharmony_ci	.min = 0,
30962306a36Sopenharmony_ci	.max = 0x80402010,
31062306a36Sopenharmony_ci	.step = 0,
31162306a36Sopenharmony_ci};
31262306a36Sopenharmony_ci
31362306a36Sopenharmony_cistatic const s64 vivid_ctrl_int_menu_values[] = {
31462306a36Sopenharmony_ci	1, 1, 2, 3, 5, 8, 13, 21, 42,
31562306a36Sopenharmony_ci};
31662306a36Sopenharmony_ci
31762306a36Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_int_menu = {
31862306a36Sopenharmony_ci	.ops = &vivid_user_gen_ctrl_ops,
31962306a36Sopenharmony_ci	.id = VIVID_CID_INTMENU,
32062306a36Sopenharmony_ci	.name = "Integer Menu",
32162306a36Sopenharmony_ci	.type = V4L2_CTRL_TYPE_INTEGER_MENU,
32262306a36Sopenharmony_ci	.min = 1,
32362306a36Sopenharmony_ci	.max = 8,
32462306a36Sopenharmony_ci	.def = 4,
32562306a36Sopenharmony_ci	.menu_skip_mask = 0x02,
32662306a36Sopenharmony_ci	.qmenu_int = vivid_ctrl_int_menu_values,
32762306a36Sopenharmony_ci};
32862306a36Sopenharmony_ci
32962306a36Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_disconnect = {
33062306a36Sopenharmony_ci	.ops = &vivid_user_gen_ctrl_ops,
33162306a36Sopenharmony_ci	.id = VIVID_CID_DISCONNECT,
33262306a36Sopenharmony_ci	.name = "Disconnect",
33362306a36Sopenharmony_ci	.type = V4L2_CTRL_TYPE_BUTTON,
33462306a36Sopenharmony_ci};
33562306a36Sopenharmony_ci
33662306a36Sopenharmony_cistatic const struct v4l2_area area = {
33762306a36Sopenharmony_ci	.width = 1000,
33862306a36Sopenharmony_ci	.height = 2000,
33962306a36Sopenharmony_ci};
34062306a36Sopenharmony_ci
34162306a36Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_area = {
34262306a36Sopenharmony_ci	.ops = &vivid_user_gen_ctrl_ops,
34362306a36Sopenharmony_ci	.id = VIVID_CID_AREA,
34462306a36Sopenharmony_ci	.name = "Area",
34562306a36Sopenharmony_ci	.type = V4L2_CTRL_TYPE_AREA,
34662306a36Sopenharmony_ci	.p_def.p_const = &area,
34762306a36Sopenharmony_ci};
34862306a36Sopenharmony_ci
34962306a36Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_ro_int32 = {
35062306a36Sopenharmony_ci	.ops = &vivid_user_gen_ctrl_ops,
35162306a36Sopenharmony_ci	.id = VIVID_CID_RO_INTEGER,
35262306a36Sopenharmony_ci	.name = "Read-Only Integer 32 Bits",
35362306a36Sopenharmony_ci	.type = V4L2_CTRL_TYPE_INTEGER,
35462306a36Sopenharmony_ci	.flags = V4L2_CTRL_FLAG_READ_ONLY,
35562306a36Sopenharmony_ci	.min = 0,
35662306a36Sopenharmony_ci	.max = 255,
35762306a36Sopenharmony_ci	.step = 1,
35862306a36Sopenharmony_ci};
35962306a36Sopenharmony_ci
36062306a36Sopenharmony_ci/* Framebuffer Controls */
36162306a36Sopenharmony_ci
36262306a36Sopenharmony_cistatic int vivid_fb_s_ctrl(struct v4l2_ctrl *ctrl)
36362306a36Sopenharmony_ci{
36462306a36Sopenharmony_ci	struct vivid_dev *dev = container_of(ctrl->handler,
36562306a36Sopenharmony_ci					     struct vivid_dev, ctrl_hdl_fb);
36662306a36Sopenharmony_ci
36762306a36Sopenharmony_ci	switch (ctrl->id) {
36862306a36Sopenharmony_ci	case VIVID_CID_CLEAR_FB:
36962306a36Sopenharmony_ci		vivid_clear_fb(dev);
37062306a36Sopenharmony_ci		break;
37162306a36Sopenharmony_ci	}
37262306a36Sopenharmony_ci	return 0;
37362306a36Sopenharmony_ci}
37462306a36Sopenharmony_ci
37562306a36Sopenharmony_cistatic const struct v4l2_ctrl_ops vivid_fb_ctrl_ops = {
37662306a36Sopenharmony_ci	.s_ctrl = vivid_fb_s_ctrl,
37762306a36Sopenharmony_ci};
37862306a36Sopenharmony_ci
37962306a36Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_clear_fb = {
38062306a36Sopenharmony_ci	.ops = &vivid_fb_ctrl_ops,
38162306a36Sopenharmony_ci	.id = VIVID_CID_CLEAR_FB,
38262306a36Sopenharmony_ci	.name = "Clear Framebuffer",
38362306a36Sopenharmony_ci	.type = V4L2_CTRL_TYPE_BUTTON,
38462306a36Sopenharmony_ci};
38562306a36Sopenharmony_ci
38662306a36Sopenharmony_ci
38762306a36Sopenharmony_ci/* Video User Controls */
38862306a36Sopenharmony_ci
38962306a36Sopenharmony_cistatic int vivid_user_vid_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
39062306a36Sopenharmony_ci{
39162306a36Sopenharmony_ci	struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_user_vid);
39262306a36Sopenharmony_ci
39362306a36Sopenharmony_ci	switch (ctrl->id) {
39462306a36Sopenharmony_ci	case V4L2_CID_AUTOGAIN:
39562306a36Sopenharmony_ci		dev->gain->val = (jiffies_to_msecs(jiffies) / 1000) & 0xff;
39662306a36Sopenharmony_ci		break;
39762306a36Sopenharmony_ci	}
39862306a36Sopenharmony_ci	return 0;
39962306a36Sopenharmony_ci}
40062306a36Sopenharmony_ci
40162306a36Sopenharmony_cistatic int vivid_user_vid_s_ctrl(struct v4l2_ctrl *ctrl)
40262306a36Sopenharmony_ci{
40362306a36Sopenharmony_ci	struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_user_vid);
40462306a36Sopenharmony_ci
40562306a36Sopenharmony_ci	switch (ctrl->id) {
40662306a36Sopenharmony_ci	case V4L2_CID_BRIGHTNESS:
40762306a36Sopenharmony_ci		dev->input_brightness[dev->input] = ctrl->val - dev->input * 128;
40862306a36Sopenharmony_ci		tpg_s_brightness(&dev->tpg, dev->input_brightness[dev->input]);
40962306a36Sopenharmony_ci		break;
41062306a36Sopenharmony_ci	case V4L2_CID_CONTRAST:
41162306a36Sopenharmony_ci		tpg_s_contrast(&dev->tpg, ctrl->val);
41262306a36Sopenharmony_ci		break;
41362306a36Sopenharmony_ci	case V4L2_CID_SATURATION:
41462306a36Sopenharmony_ci		tpg_s_saturation(&dev->tpg, ctrl->val);
41562306a36Sopenharmony_ci		break;
41662306a36Sopenharmony_ci	case V4L2_CID_HUE:
41762306a36Sopenharmony_ci		tpg_s_hue(&dev->tpg, ctrl->val);
41862306a36Sopenharmony_ci		break;
41962306a36Sopenharmony_ci	case V4L2_CID_HFLIP:
42062306a36Sopenharmony_ci		dev->hflip = ctrl->val;
42162306a36Sopenharmony_ci		tpg_s_hflip(&dev->tpg, dev->sensor_hflip ^ dev->hflip);
42262306a36Sopenharmony_ci		break;
42362306a36Sopenharmony_ci	case V4L2_CID_VFLIP:
42462306a36Sopenharmony_ci		dev->vflip = ctrl->val;
42562306a36Sopenharmony_ci		tpg_s_vflip(&dev->tpg, dev->sensor_vflip ^ dev->vflip);
42662306a36Sopenharmony_ci		break;
42762306a36Sopenharmony_ci	case V4L2_CID_ALPHA_COMPONENT:
42862306a36Sopenharmony_ci		tpg_s_alpha_component(&dev->tpg, ctrl->val);
42962306a36Sopenharmony_ci		break;
43062306a36Sopenharmony_ci	}
43162306a36Sopenharmony_ci	return 0;
43262306a36Sopenharmony_ci}
43362306a36Sopenharmony_ci
43462306a36Sopenharmony_cistatic const struct v4l2_ctrl_ops vivid_user_vid_ctrl_ops = {
43562306a36Sopenharmony_ci	.g_volatile_ctrl = vivid_user_vid_g_volatile_ctrl,
43662306a36Sopenharmony_ci	.s_ctrl = vivid_user_vid_s_ctrl,
43762306a36Sopenharmony_ci};
43862306a36Sopenharmony_ci
43962306a36Sopenharmony_ci
44062306a36Sopenharmony_ci/* Video Capture Controls */
44162306a36Sopenharmony_ci
44262306a36Sopenharmony_cistatic int vivid_vid_cap_s_ctrl(struct v4l2_ctrl *ctrl)
44362306a36Sopenharmony_ci{
44462306a36Sopenharmony_ci	static const u32 colorspaces[] = {
44562306a36Sopenharmony_ci		V4L2_COLORSPACE_SMPTE170M,
44662306a36Sopenharmony_ci		V4L2_COLORSPACE_REC709,
44762306a36Sopenharmony_ci		V4L2_COLORSPACE_SRGB,
44862306a36Sopenharmony_ci		V4L2_COLORSPACE_OPRGB,
44962306a36Sopenharmony_ci		V4L2_COLORSPACE_BT2020,
45062306a36Sopenharmony_ci		V4L2_COLORSPACE_DCI_P3,
45162306a36Sopenharmony_ci		V4L2_COLORSPACE_SMPTE240M,
45262306a36Sopenharmony_ci		V4L2_COLORSPACE_470_SYSTEM_M,
45362306a36Sopenharmony_ci		V4L2_COLORSPACE_470_SYSTEM_BG,
45462306a36Sopenharmony_ci	};
45562306a36Sopenharmony_ci	struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_vid_cap);
45662306a36Sopenharmony_ci	unsigned int i, j;
45762306a36Sopenharmony_ci
45862306a36Sopenharmony_ci	switch (ctrl->id) {
45962306a36Sopenharmony_ci	case VIVID_CID_TEST_PATTERN:
46062306a36Sopenharmony_ci		vivid_update_quality(dev);
46162306a36Sopenharmony_ci		tpg_s_pattern(&dev->tpg, ctrl->val);
46262306a36Sopenharmony_ci		break;
46362306a36Sopenharmony_ci	case VIVID_CID_COLORSPACE:
46462306a36Sopenharmony_ci		tpg_s_colorspace(&dev->tpg, colorspaces[ctrl->val]);
46562306a36Sopenharmony_ci		vivid_send_source_change(dev, TV);
46662306a36Sopenharmony_ci		vivid_send_source_change(dev, SVID);
46762306a36Sopenharmony_ci		vivid_send_source_change(dev, HDMI);
46862306a36Sopenharmony_ci		vivid_send_source_change(dev, WEBCAM);
46962306a36Sopenharmony_ci		break;
47062306a36Sopenharmony_ci	case VIVID_CID_XFER_FUNC:
47162306a36Sopenharmony_ci		tpg_s_xfer_func(&dev->tpg, ctrl->val);
47262306a36Sopenharmony_ci		vivid_send_source_change(dev, TV);
47362306a36Sopenharmony_ci		vivid_send_source_change(dev, SVID);
47462306a36Sopenharmony_ci		vivid_send_source_change(dev, HDMI);
47562306a36Sopenharmony_ci		vivid_send_source_change(dev, WEBCAM);
47662306a36Sopenharmony_ci		break;
47762306a36Sopenharmony_ci	case VIVID_CID_YCBCR_ENC:
47862306a36Sopenharmony_ci		tpg_s_ycbcr_enc(&dev->tpg, ctrl->val);
47962306a36Sopenharmony_ci		vivid_send_source_change(dev, TV);
48062306a36Sopenharmony_ci		vivid_send_source_change(dev, SVID);
48162306a36Sopenharmony_ci		vivid_send_source_change(dev, HDMI);
48262306a36Sopenharmony_ci		vivid_send_source_change(dev, WEBCAM);
48362306a36Sopenharmony_ci		break;
48462306a36Sopenharmony_ci	case VIVID_CID_HSV_ENC:
48562306a36Sopenharmony_ci		tpg_s_hsv_enc(&dev->tpg, ctrl->val ? V4L2_HSV_ENC_256 :
48662306a36Sopenharmony_ci						     V4L2_HSV_ENC_180);
48762306a36Sopenharmony_ci		vivid_send_source_change(dev, TV);
48862306a36Sopenharmony_ci		vivid_send_source_change(dev, SVID);
48962306a36Sopenharmony_ci		vivid_send_source_change(dev, HDMI);
49062306a36Sopenharmony_ci		vivid_send_source_change(dev, WEBCAM);
49162306a36Sopenharmony_ci		break;
49262306a36Sopenharmony_ci	case VIVID_CID_QUANTIZATION:
49362306a36Sopenharmony_ci		tpg_s_quantization(&dev->tpg, ctrl->val);
49462306a36Sopenharmony_ci		vivid_send_source_change(dev, TV);
49562306a36Sopenharmony_ci		vivid_send_source_change(dev, SVID);
49662306a36Sopenharmony_ci		vivid_send_source_change(dev, HDMI);
49762306a36Sopenharmony_ci		vivid_send_source_change(dev, WEBCAM);
49862306a36Sopenharmony_ci		break;
49962306a36Sopenharmony_ci	case V4L2_CID_DV_RX_RGB_RANGE:
50062306a36Sopenharmony_ci		if (!vivid_is_hdmi_cap(dev))
50162306a36Sopenharmony_ci			break;
50262306a36Sopenharmony_ci		tpg_s_rgb_range(&dev->tpg, ctrl->val);
50362306a36Sopenharmony_ci		break;
50462306a36Sopenharmony_ci	case VIVID_CID_LIMITED_RGB_RANGE:
50562306a36Sopenharmony_ci		tpg_s_real_rgb_range(&dev->tpg, ctrl->val ?
50662306a36Sopenharmony_ci				V4L2_DV_RGB_RANGE_LIMITED : V4L2_DV_RGB_RANGE_FULL);
50762306a36Sopenharmony_ci		break;
50862306a36Sopenharmony_ci	case VIVID_CID_ALPHA_MODE:
50962306a36Sopenharmony_ci		tpg_s_alpha_mode(&dev->tpg, ctrl->val);
51062306a36Sopenharmony_ci		break;
51162306a36Sopenharmony_ci	case VIVID_CID_HOR_MOVEMENT:
51262306a36Sopenharmony_ci		tpg_s_mv_hor_mode(&dev->tpg, ctrl->val);
51362306a36Sopenharmony_ci		break;
51462306a36Sopenharmony_ci	case VIVID_CID_VERT_MOVEMENT:
51562306a36Sopenharmony_ci		tpg_s_mv_vert_mode(&dev->tpg, ctrl->val);
51662306a36Sopenharmony_ci		break;
51762306a36Sopenharmony_ci	case VIVID_CID_OSD_TEXT_MODE:
51862306a36Sopenharmony_ci		dev->osd_mode = ctrl->val;
51962306a36Sopenharmony_ci		break;
52062306a36Sopenharmony_ci	case VIVID_CID_PERCENTAGE_FILL:
52162306a36Sopenharmony_ci		tpg_s_perc_fill(&dev->tpg, ctrl->val);
52262306a36Sopenharmony_ci		for (i = 0; i < VIDEO_MAX_FRAME; i++)
52362306a36Sopenharmony_ci			dev->must_blank[i] = ctrl->val < 100;
52462306a36Sopenharmony_ci		break;
52562306a36Sopenharmony_ci	case VIVID_CID_INSERT_SAV:
52662306a36Sopenharmony_ci		tpg_s_insert_sav(&dev->tpg, ctrl->val);
52762306a36Sopenharmony_ci		break;
52862306a36Sopenharmony_ci	case VIVID_CID_INSERT_EAV:
52962306a36Sopenharmony_ci		tpg_s_insert_eav(&dev->tpg, ctrl->val);
53062306a36Sopenharmony_ci		break;
53162306a36Sopenharmony_ci	case VIVID_CID_INSERT_HDMI_VIDEO_GUARD_BAND:
53262306a36Sopenharmony_ci		tpg_s_insert_hdmi_video_guard_band(&dev->tpg, ctrl->val);
53362306a36Sopenharmony_ci		break;
53462306a36Sopenharmony_ci	case VIVID_CID_HFLIP:
53562306a36Sopenharmony_ci		dev->sensor_hflip = ctrl->val;
53662306a36Sopenharmony_ci		tpg_s_hflip(&dev->tpg, dev->sensor_hflip ^ dev->hflip);
53762306a36Sopenharmony_ci		break;
53862306a36Sopenharmony_ci	case VIVID_CID_VFLIP:
53962306a36Sopenharmony_ci		dev->sensor_vflip = ctrl->val;
54062306a36Sopenharmony_ci		tpg_s_vflip(&dev->tpg, dev->sensor_vflip ^ dev->vflip);
54162306a36Sopenharmony_ci		break;
54262306a36Sopenharmony_ci	case VIVID_CID_REDUCED_FPS:
54362306a36Sopenharmony_ci		dev->reduced_fps = ctrl->val;
54462306a36Sopenharmony_ci		vivid_update_format_cap(dev, true);
54562306a36Sopenharmony_ci		break;
54662306a36Sopenharmony_ci	case VIVID_CID_HAS_CROP_CAP:
54762306a36Sopenharmony_ci		dev->has_crop_cap = ctrl->val;
54862306a36Sopenharmony_ci		vivid_update_format_cap(dev, true);
54962306a36Sopenharmony_ci		break;
55062306a36Sopenharmony_ci	case VIVID_CID_HAS_COMPOSE_CAP:
55162306a36Sopenharmony_ci		dev->has_compose_cap = ctrl->val;
55262306a36Sopenharmony_ci		vivid_update_format_cap(dev, true);
55362306a36Sopenharmony_ci		break;
55462306a36Sopenharmony_ci	case VIVID_CID_HAS_SCALER_CAP:
55562306a36Sopenharmony_ci		dev->has_scaler_cap = ctrl->val;
55662306a36Sopenharmony_ci		vivid_update_format_cap(dev, true);
55762306a36Sopenharmony_ci		break;
55862306a36Sopenharmony_ci	case VIVID_CID_SHOW_BORDER:
55962306a36Sopenharmony_ci		tpg_s_show_border(&dev->tpg, ctrl->val);
56062306a36Sopenharmony_ci		break;
56162306a36Sopenharmony_ci	case VIVID_CID_SHOW_SQUARE:
56262306a36Sopenharmony_ci		tpg_s_show_square(&dev->tpg, ctrl->val);
56362306a36Sopenharmony_ci		break;
56462306a36Sopenharmony_ci	case VIVID_CID_STD_ASPECT_RATIO:
56562306a36Sopenharmony_ci		dev->std_aspect_ratio[dev->input] = ctrl->val;
56662306a36Sopenharmony_ci		tpg_s_video_aspect(&dev->tpg, vivid_get_video_aspect(dev));
56762306a36Sopenharmony_ci		break;
56862306a36Sopenharmony_ci	case VIVID_CID_DV_TIMINGS_SIGNAL_MODE:
56962306a36Sopenharmony_ci		dev->dv_timings_signal_mode[dev->input] =
57062306a36Sopenharmony_ci			dev->ctrl_dv_timings_signal_mode->val;
57162306a36Sopenharmony_ci		dev->query_dv_timings[dev->input] = dev->ctrl_dv_timings->val;
57262306a36Sopenharmony_ci
57362306a36Sopenharmony_ci		dev->power_present = 0;
57462306a36Sopenharmony_ci		for (i = 0, j = 0;
57562306a36Sopenharmony_ci		     i < ARRAY_SIZE(dev->dv_timings_signal_mode);
57662306a36Sopenharmony_ci		     i++)
57762306a36Sopenharmony_ci			if (dev->input_type[i] == HDMI) {
57862306a36Sopenharmony_ci				if (dev->dv_timings_signal_mode[i] != NO_SIGNAL)
57962306a36Sopenharmony_ci					dev->power_present |= (1 << j);
58062306a36Sopenharmony_ci				j++;
58162306a36Sopenharmony_ci			}
58262306a36Sopenharmony_ci		__v4l2_ctrl_s_ctrl(dev->ctrl_rx_power_present,
58362306a36Sopenharmony_ci				   dev->power_present);
58462306a36Sopenharmony_ci
58562306a36Sopenharmony_ci		v4l2_ctrl_activate(dev->ctrl_dv_timings,
58662306a36Sopenharmony_ci			dev->dv_timings_signal_mode[dev->input] ==
58762306a36Sopenharmony_ci				SELECTED_DV_TIMINGS);
58862306a36Sopenharmony_ci
58962306a36Sopenharmony_ci		vivid_update_quality(dev);
59062306a36Sopenharmony_ci		vivid_send_source_change(dev, HDMI);
59162306a36Sopenharmony_ci		break;
59262306a36Sopenharmony_ci	case VIVID_CID_DV_TIMINGS_ASPECT_RATIO:
59362306a36Sopenharmony_ci		dev->dv_timings_aspect_ratio[dev->input] = ctrl->val;
59462306a36Sopenharmony_ci		tpg_s_video_aspect(&dev->tpg, vivid_get_video_aspect(dev));
59562306a36Sopenharmony_ci		break;
59662306a36Sopenharmony_ci	case VIVID_CID_TSTAMP_SRC:
59762306a36Sopenharmony_ci		dev->tstamp_src_is_soe = ctrl->val;
59862306a36Sopenharmony_ci		dev->vb_vid_cap_q.timestamp_flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
59962306a36Sopenharmony_ci		if (dev->tstamp_src_is_soe)
60062306a36Sopenharmony_ci			dev->vb_vid_cap_q.timestamp_flags |= V4L2_BUF_FLAG_TSTAMP_SRC_SOE;
60162306a36Sopenharmony_ci		break;
60262306a36Sopenharmony_ci	case VIVID_CID_MAX_EDID_BLOCKS:
60362306a36Sopenharmony_ci		dev->edid_max_blocks = ctrl->val;
60462306a36Sopenharmony_ci		if (dev->edid_blocks > dev->edid_max_blocks)
60562306a36Sopenharmony_ci			dev->edid_blocks = dev->edid_max_blocks;
60662306a36Sopenharmony_ci		break;
60762306a36Sopenharmony_ci	}
60862306a36Sopenharmony_ci	return 0;
60962306a36Sopenharmony_ci}
61062306a36Sopenharmony_ci
61162306a36Sopenharmony_cistatic const struct v4l2_ctrl_ops vivid_vid_cap_ctrl_ops = {
61262306a36Sopenharmony_ci	.s_ctrl = vivid_vid_cap_s_ctrl,
61362306a36Sopenharmony_ci};
61462306a36Sopenharmony_ci
61562306a36Sopenharmony_cistatic const char * const vivid_ctrl_hor_movement_strings[] = {
61662306a36Sopenharmony_ci	"Move Left Fast",
61762306a36Sopenharmony_ci	"Move Left",
61862306a36Sopenharmony_ci	"Move Left Slow",
61962306a36Sopenharmony_ci	"No Movement",
62062306a36Sopenharmony_ci	"Move Right Slow",
62162306a36Sopenharmony_ci	"Move Right",
62262306a36Sopenharmony_ci	"Move Right Fast",
62362306a36Sopenharmony_ci	NULL,
62462306a36Sopenharmony_ci};
62562306a36Sopenharmony_ci
62662306a36Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_hor_movement = {
62762306a36Sopenharmony_ci	.ops = &vivid_vid_cap_ctrl_ops,
62862306a36Sopenharmony_ci	.id = VIVID_CID_HOR_MOVEMENT,
62962306a36Sopenharmony_ci	.name = "Horizontal Movement",
63062306a36Sopenharmony_ci	.type = V4L2_CTRL_TYPE_MENU,
63162306a36Sopenharmony_ci	.max = TPG_MOVE_POS_FAST,
63262306a36Sopenharmony_ci	.def = TPG_MOVE_NONE,
63362306a36Sopenharmony_ci	.qmenu = vivid_ctrl_hor_movement_strings,
63462306a36Sopenharmony_ci};
63562306a36Sopenharmony_ci
63662306a36Sopenharmony_cistatic const char * const vivid_ctrl_vert_movement_strings[] = {
63762306a36Sopenharmony_ci	"Move Up Fast",
63862306a36Sopenharmony_ci	"Move Up",
63962306a36Sopenharmony_ci	"Move Up Slow",
64062306a36Sopenharmony_ci	"No Movement",
64162306a36Sopenharmony_ci	"Move Down Slow",
64262306a36Sopenharmony_ci	"Move Down",
64362306a36Sopenharmony_ci	"Move Down Fast",
64462306a36Sopenharmony_ci	NULL,
64562306a36Sopenharmony_ci};
64662306a36Sopenharmony_ci
64762306a36Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_vert_movement = {
64862306a36Sopenharmony_ci	.ops = &vivid_vid_cap_ctrl_ops,
64962306a36Sopenharmony_ci	.id = VIVID_CID_VERT_MOVEMENT,
65062306a36Sopenharmony_ci	.name = "Vertical Movement",
65162306a36Sopenharmony_ci	.type = V4L2_CTRL_TYPE_MENU,
65262306a36Sopenharmony_ci	.max = TPG_MOVE_POS_FAST,
65362306a36Sopenharmony_ci	.def = TPG_MOVE_NONE,
65462306a36Sopenharmony_ci	.qmenu = vivid_ctrl_vert_movement_strings,
65562306a36Sopenharmony_ci};
65662306a36Sopenharmony_ci
65762306a36Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_show_border = {
65862306a36Sopenharmony_ci	.ops = &vivid_vid_cap_ctrl_ops,
65962306a36Sopenharmony_ci	.id = VIVID_CID_SHOW_BORDER,
66062306a36Sopenharmony_ci	.name = "Show Border",
66162306a36Sopenharmony_ci	.type = V4L2_CTRL_TYPE_BOOLEAN,
66262306a36Sopenharmony_ci	.max = 1,
66362306a36Sopenharmony_ci	.step = 1,
66462306a36Sopenharmony_ci};
66562306a36Sopenharmony_ci
66662306a36Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_show_square = {
66762306a36Sopenharmony_ci	.ops = &vivid_vid_cap_ctrl_ops,
66862306a36Sopenharmony_ci	.id = VIVID_CID_SHOW_SQUARE,
66962306a36Sopenharmony_ci	.name = "Show Square",
67062306a36Sopenharmony_ci	.type = V4L2_CTRL_TYPE_BOOLEAN,
67162306a36Sopenharmony_ci	.max = 1,
67262306a36Sopenharmony_ci	.step = 1,
67362306a36Sopenharmony_ci};
67462306a36Sopenharmony_ci
67562306a36Sopenharmony_cistatic const char * const vivid_ctrl_osd_mode_strings[] = {
67662306a36Sopenharmony_ci	"All",
67762306a36Sopenharmony_ci	"Counters Only",
67862306a36Sopenharmony_ci	"None",
67962306a36Sopenharmony_ci	NULL,
68062306a36Sopenharmony_ci};
68162306a36Sopenharmony_ci
68262306a36Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_osd_mode = {
68362306a36Sopenharmony_ci	.ops = &vivid_vid_cap_ctrl_ops,
68462306a36Sopenharmony_ci	.id = VIVID_CID_OSD_TEXT_MODE,
68562306a36Sopenharmony_ci	.name = "OSD Text Mode",
68662306a36Sopenharmony_ci	.type = V4L2_CTRL_TYPE_MENU,
68762306a36Sopenharmony_ci	.max = ARRAY_SIZE(vivid_ctrl_osd_mode_strings) - 2,
68862306a36Sopenharmony_ci	.qmenu = vivid_ctrl_osd_mode_strings,
68962306a36Sopenharmony_ci};
69062306a36Sopenharmony_ci
69162306a36Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_perc_fill = {
69262306a36Sopenharmony_ci	.ops = &vivid_vid_cap_ctrl_ops,
69362306a36Sopenharmony_ci	.id = VIVID_CID_PERCENTAGE_FILL,
69462306a36Sopenharmony_ci	.name = "Fill Percentage of Frame",
69562306a36Sopenharmony_ci	.type = V4L2_CTRL_TYPE_INTEGER,
69662306a36Sopenharmony_ci	.min = 0,
69762306a36Sopenharmony_ci	.max = 100,
69862306a36Sopenharmony_ci	.def = 100,
69962306a36Sopenharmony_ci	.step = 1,
70062306a36Sopenharmony_ci};
70162306a36Sopenharmony_ci
70262306a36Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_insert_sav = {
70362306a36Sopenharmony_ci	.ops = &vivid_vid_cap_ctrl_ops,
70462306a36Sopenharmony_ci	.id = VIVID_CID_INSERT_SAV,
70562306a36Sopenharmony_ci	.name = "Insert SAV Code in Image",
70662306a36Sopenharmony_ci	.type = V4L2_CTRL_TYPE_BOOLEAN,
70762306a36Sopenharmony_ci	.max = 1,
70862306a36Sopenharmony_ci	.step = 1,
70962306a36Sopenharmony_ci};
71062306a36Sopenharmony_ci
71162306a36Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_insert_eav = {
71262306a36Sopenharmony_ci	.ops = &vivid_vid_cap_ctrl_ops,
71362306a36Sopenharmony_ci	.id = VIVID_CID_INSERT_EAV,
71462306a36Sopenharmony_ci	.name = "Insert EAV Code in Image",
71562306a36Sopenharmony_ci	.type = V4L2_CTRL_TYPE_BOOLEAN,
71662306a36Sopenharmony_ci	.max = 1,
71762306a36Sopenharmony_ci	.step = 1,
71862306a36Sopenharmony_ci};
71962306a36Sopenharmony_ci
72062306a36Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_insert_hdmi_video_guard_band = {
72162306a36Sopenharmony_ci	.ops = &vivid_vid_cap_ctrl_ops,
72262306a36Sopenharmony_ci	.id = VIVID_CID_INSERT_HDMI_VIDEO_GUARD_BAND,
72362306a36Sopenharmony_ci	.name = "Insert Video Guard Band",
72462306a36Sopenharmony_ci	.type = V4L2_CTRL_TYPE_BOOLEAN,
72562306a36Sopenharmony_ci	.max = 1,
72662306a36Sopenharmony_ci	.step = 1,
72762306a36Sopenharmony_ci};
72862306a36Sopenharmony_ci
72962306a36Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_hflip = {
73062306a36Sopenharmony_ci	.ops = &vivid_vid_cap_ctrl_ops,
73162306a36Sopenharmony_ci	.id = VIVID_CID_HFLIP,
73262306a36Sopenharmony_ci	.name = "Sensor Flipped Horizontally",
73362306a36Sopenharmony_ci	.type = V4L2_CTRL_TYPE_BOOLEAN,
73462306a36Sopenharmony_ci	.max = 1,
73562306a36Sopenharmony_ci	.step = 1,
73662306a36Sopenharmony_ci};
73762306a36Sopenharmony_ci
73862306a36Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_vflip = {
73962306a36Sopenharmony_ci	.ops = &vivid_vid_cap_ctrl_ops,
74062306a36Sopenharmony_ci	.id = VIVID_CID_VFLIP,
74162306a36Sopenharmony_ci	.name = "Sensor Flipped Vertically",
74262306a36Sopenharmony_ci	.type = V4L2_CTRL_TYPE_BOOLEAN,
74362306a36Sopenharmony_ci	.max = 1,
74462306a36Sopenharmony_ci	.step = 1,
74562306a36Sopenharmony_ci};
74662306a36Sopenharmony_ci
74762306a36Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_reduced_fps = {
74862306a36Sopenharmony_ci	.ops = &vivid_vid_cap_ctrl_ops,
74962306a36Sopenharmony_ci	.id = VIVID_CID_REDUCED_FPS,
75062306a36Sopenharmony_ci	.name = "Reduced Framerate",
75162306a36Sopenharmony_ci	.type = V4L2_CTRL_TYPE_BOOLEAN,
75262306a36Sopenharmony_ci	.max = 1,
75362306a36Sopenharmony_ci	.step = 1,
75462306a36Sopenharmony_ci};
75562306a36Sopenharmony_ci
75662306a36Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_has_crop_cap = {
75762306a36Sopenharmony_ci	.ops = &vivid_vid_cap_ctrl_ops,
75862306a36Sopenharmony_ci	.id = VIVID_CID_HAS_CROP_CAP,
75962306a36Sopenharmony_ci	.name = "Enable Capture Cropping",
76062306a36Sopenharmony_ci	.type = V4L2_CTRL_TYPE_BOOLEAN,
76162306a36Sopenharmony_ci	.max = 1,
76262306a36Sopenharmony_ci	.def = 1,
76362306a36Sopenharmony_ci	.step = 1,
76462306a36Sopenharmony_ci};
76562306a36Sopenharmony_ci
76662306a36Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_has_compose_cap = {
76762306a36Sopenharmony_ci	.ops = &vivid_vid_cap_ctrl_ops,
76862306a36Sopenharmony_ci	.id = VIVID_CID_HAS_COMPOSE_CAP,
76962306a36Sopenharmony_ci	.name = "Enable Capture Composing",
77062306a36Sopenharmony_ci	.type = V4L2_CTRL_TYPE_BOOLEAN,
77162306a36Sopenharmony_ci	.max = 1,
77262306a36Sopenharmony_ci	.def = 1,
77362306a36Sopenharmony_ci	.step = 1,
77462306a36Sopenharmony_ci};
77562306a36Sopenharmony_ci
77662306a36Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_has_scaler_cap = {
77762306a36Sopenharmony_ci	.ops = &vivid_vid_cap_ctrl_ops,
77862306a36Sopenharmony_ci	.id = VIVID_CID_HAS_SCALER_CAP,
77962306a36Sopenharmony_ci	.name = "Enable Capture Scaler",
78062306a36Sopenharmony_ci	.type = V4L2_CTRL_TYPE_BOOLEAN,
78162306a36Sopenharmony_ci	.max = 1,
78262306a36Sopenharmony_ci	.def = 1,
78362306a36Sopenharmony_ci	.step = 1,
78462306a36Sopenharmony_ci};
78562306a36Sopenharmony_ci
78662306a36Sopenharmony_cistatic const char * const vivid_ctrl_tstamp_src_strings[] = {
78762306a36Sopenharmony_ci	"End of Frame",
78862306a36Sopenharmony_ci	"Start of Exposure",
78962306a36Sopenharmony_ci	NULL,
79062306a36Sopenharmony_ci};
79162306a36Sopenharmony_ci
79262306a36Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_tstamp_src = {
79362306a36Sopenharmony_ci	.ops = &vivid_vid_cap_ctrl_ops,
79462306a36Sopenharmony_ci	.id = VIVID_CID_TSTAMP_SRC,
79562306a36Sopenharmony_ci	.name = "Timestamp Source",
79662306a36Sopenharmony_ci	.type = V4L2_CTRL_TYPE_MENU,
79762306a36Sopenharmony_ci	.max = ARRAY_SIZE(vivid_ctrl_tstamp_src_strings) - 2,
79862306a36Sopenharmony_ci	.qmenu = vivid_ctrl_tstamp_src_strings,
79962306a36Sopenharmony_ci};
80062306a36Sopenharmony_ci
80162306a36Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_std_aspect_ratio = {
80262306a36Sopenharmony_ci	.ops = &vivid_vid_cap_ctrl_ops,
80362306a36Sopenharmony_ci	.id = VIVID_CID_STD_ASPECT_RATIO,
80462306a36Sopenharmony_ci	.name = "Standard Aspect Ratio",
80562306a36Sopenharmony_ci	.type = V4L2_CTRL_TYPE_MENU,
80662306a36Sopenharmony_ci	.min = 1,
80762306a36Sopenharmony_ci	.max = 4,
80862306a36Sopenharmony_ci	.def = 1,
80962306a36Sopenharmony_ci	.qmenu = tpg_aspect_strings,
81062306a36Sopenharmony_ci};
81162306a36Sopenharmony_ci
81262306a36Sopenharmony_cistatic const char * const vivid_ctrl_dv_timings_signal_mode_strings[] = {
81362306a36Sopenharmony_ci	"Current DV Timings",
81462306a36Sopenharmony_ci	"No Signal",
81562306a36Sopenharmony_ci	"No Lock",
81662306a36Sopenharmony_ci	"Out of Range",
81762306a36Sopenharmony_ci	"Selected DV Timings",
81862306a36Sopenharmony_ci	"Cycle Through All DV Timings",
81962306a36Sopenharmony_ci	"Custom DV Timings",
82062306a36Sopenharmony_ci	NULL,
82162306a36Sopenharmony_ci};
82262306a36Sopenharmony_ci
82362306a36Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_dv_timings_signal_mode = {
82462306a36Sopenharmony_ci	.ops = &vivid_vid_cap_ctrl_ops,
82562306a36Sopenharmony_ci	.id = VIVID_CID_DV_TIMINGS_SIGNAL_MODE,
82662306a36Sopenharmony_ci	.name = "DV Timings Signal Mode",
82762306a36Sopenharmony_ci	.type = V4L2_CTRL_TYPE_MENU,
82862306a36Sopenharmony_ci	.max = 5,
82962306a36Sopenharmony_ci	.qmenu = vivid_ctrl_dv_timings_signal_mode_strings,
83062306a36Sopenharmony_ci};
83162306a36Sopenharmony_ci
83262306a36Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_dv_timings_aspect_ratio = {
83362306a36Sopenharmony_ci	.ops = &vivid_vid_cap_ctrl_ops,
83462306a36Sopenharmony_ci	.id = VIVID_CID_DV_TIMINGS_ASPECT_RATIO,
83562306a36Sopenharmony_ci	.name = "DV Timings Aspect Ratio",
83662306a36Sopenharmony_ci	.type = V4L2_CTRL_TYPE_MENU,
83762306a36Sopenharmony_ci	.max = 3,
83862306a36Sopenharmony_ci	.qmenu = tpg_aspect_strings,
83962306a36Sopenharmony_ci};
84062306a36Sopenharmony_ci
84162306a36Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_max_edid_blocks = {
84262306a36Sopenharmony_ci	.ops = &vivid_vid_cap_ctrl_ops,
84362306a36Sopenharmony_ci	.id = VIVID_CID_MAX_EDID_BLOCKS,
84462306a36Sopenharmony_ci	.name = "Maximum EDID Blocks",
84562306a36Sopenharmony_ci	.type = V4L2_CTRL_TYPE_INTEGER,
84662306a36Sopenharmony_ci	.min = 1,
84762306a36Sopenharmony_ci	.max = 256,
84862306a36Sopenharmony_ci	.def = 2,
84962306a36Sopenharmony_ci	.step = 1,
85062306a36Sopenharmony_ci};
85162306a36Sopenharmony_ci
85262306a36Sopenharmony_cistatic const char * const vivid_ctrl_colorspace_strings[] = {
85362306a36Sopenharmony_ci	"SMPTE 170M",
85462306a36Sopenharmony_ci	"Rec. 709",
85562306a36Sopenharmony_ci	"sRGB",
85662306a36Sopenharmony_ci	"opRGB",
85762306a36Sopenharmony_ci	"BT.2020",
85862306a36Sopenharmony_ci	"DCI-P3",
85962306a36Sopenharmony_ci	"SMPTE 240M",
86062306a36Sopenharmony_ci	"470 System M",
86162306a36Sopenharmony_ci	"470 System BG",
86262306a36Sopenharmony_ci	NULL,
86362306a36Sopenharmony_ci};
86462306a36Sopenharmony_ci
86562306a36Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_colorspace = {
86662306a36Sopenharmony_ci	.ops = &vivid_vid_cap_ctrl_ops,
86762306a36Sopenharmony_ci	.id = VIVID_CID_COLORSPACE,
86862306a36Sopenharmony_ci	.name = "Colorspace",
86962306a36Sopenharmony_ci	.type = V4L2_CTRL_TYPE_MENU,
87062306a36Sopenharmony_ci	.max = ARRAY_SIZE(vivid_ctrl_colorspace_strings) - 2,
87162306a36Sopenharmony_ci	.def = 2,
87262306a36Sopenharmony_ci	.qmenu = vivid_ctrl_colorspace_strings,
87362306a36Sopenharmony_ci};
87462306a36Sopenharmony_ci
87562306a36Sopenharmony_cistatic const char * const vivid_ctrl_xfer_func_strings[] = {
87662306a36Sopenharmony_ci	"Default",
87762306a36Sopenharmony_ci	"Rec. 709",
87862306a36Sopenharmony_ci	"sRGB",
87962306a36Sopenharmony_ci	"opRGB",
88062306a36Sopenharmony_ci	"SMPTE 240M",
88162306a36Sopenharmony_ci	"None",
88262306a36Sopenharmony_ci	"DCI-P3",
88362306a36Sopenharmony_ci	"SMPTE 2084",
88462306a36Sopenharmony_ci	NULL,
88562306a36Sopenharmony_ci};
88662306a36Sopenharmony_ci
88762306a36Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_xfer_func = {
88862306a36Sopenharmony_ci	.ops = &vivid_vid_cap_ctrl_ops,
88962306a36Sopenharmony_ci	.id = VIVID_CID_XFER_FUNC,
89062306a36Sopenharmony_ci	.name = "Transfer Function",
89162306a36Sopenharmony_ci	.type = V4L2_CTRL_TYPE_MENU,
89262306a36Sopenharmony_ci	.max = ARRAY_SIZE(vivid_ctrl_xfer_func_strings) - 2,
89362306a36Sopenharmony_ci	.qmenu = vivid_ctrl_xfer_func_strings,
89462306a36Sopenharmony_ci};
89562306a36Sopenharmony_ci
89662306a36Sopenharmony_cistatic const char * const vivid_ctrl_ycbcr_enc_strings[] = {
89762306a36Sopenharmony_ci	"Default",
89862306a36Sopenharmony_ci	"ITU-R 601",
89962306a36Sopenharmony_ci	"Rec. 709",
90062306a36Sopenharmony_ci	"xvYCC 601",
90162306a36Sopenharmony_ci	"xvYCC 709",
90262306a36Sopenharmony_ci	"",
90362306a36Sopenharmony_ci	"BT.2020",
90462306a36Sopenharmony_ci	"BT.2020 Constant Luminance",
90562306a36Sopenharmony_ci	"SMPTE 240M",
90662306a36Sopenharmony_ci	NULL,
90762306a36Sopenharmony_ci};
90862306a36Sopenharmony_ci
90962306a36Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_ycbcr_enc = {
91062306a36Sopenharmony_ci	.ops = &vivid_vid_cap_ctrl_ops,
91162306a36Sopenharmony_ci	.id = VIVID_CID_YCBCR_ENC,
91262306a36Sopenharmony_ci	.name = "Y'CbCr Encoding",
91362306a36Sopenharmony_ci	.type = V4L2_CTRL_TYPE_MENU,
91462306a36Sopenharmony_ci	.menu_skip_mask = 1 << 5,
91562306a36Sopenharmony_ci	.max = ARRAY_SIZE(vivid_ctrl_ycbcr_enc_strings) - 2,
91662306a36Sopenharmony_ci	.qmenu = vivid_ctrl_ycbcr_enc_strings,
91762306a36Sopenharmony_ci};
91862306a36Sopenharmony_ci
91962306a36Sopenharmony_cistatic const char * const vivid_ctrl_hsv_enc_strings[] = {
92062306a36Sopenharmony_ci	"Hue 0-179",
92162306a36Sopenharmony_ci	"Hue 0-256",
92262306a36Sopenharmony_ci	NULL,
92362306a36Sopenharmony_ci};
92462306a36Sopenharmony_ci
92562306a36Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_hsv_enc = {
92662306a36Sopenharmony_ci	.ops = &vivid_vid_cap_ctrl_ops,
92762306a36Sopenharmony_ci	.id = VIVID_CID_HSV_ENC,
92862306a36Sopenharmony_ci	.name = "HSV Encoding",
92962306a36Sopenharmony_ci	.type = V4L2_CTRL_TYPE_MENU,
93062306a36Sopenharmony_ci	.max = ARRAY_SIZE(vivid_ctrl_hsv_enc_strings) - 2,
93162306a36Sopenharmony_ci	.qmenu = vivid_ctrl_hsv_enc_strings,
93262306a36Sopenharmony_ci};
93362306a36Sopenharmony_ci
93462306a36Sopenharmony_cistatic const char * const vivid_ctrl_quantization_strings[] = {
93562306a36Sopenharmony_ci	"Default",
93662306a36Sopenharmony_ci	"Full Range",
93762306a36Sopenharmony_ci	"Limited Range",
93862306a36Sopenharmony_ci	NULL,
93962306a36Sopenharmony_ci};
94062306a36Sopenharmony_ci
94162306a36Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_quantization = {
94262306a36Sopenharmony_ci	.ops = &vivid_vid_cap_ctrl_ops,
94362306a36Sopenharmony_ci	.id = VIVID_CID_QUANTIZATION,
94462306a36Sopenharmony_ci	.name = "Quantization",
94562306a36Sopenharmony_ci	.type = V4L2_CTRL_TYPE_MENU,
94662306a36Sopenharmony_ci	.max = ARRAY_SIZE(vivid_ctrl_quantization_strings) - 2,
94762306a36Sopenharmony_ci	.qmenu = vivid_ctrl_quantization_strings,
94862306a36Sopenharmony_ci};
94962306a36Sopenharmony_ci
95062306a36Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_alpha_mode = {
95162306a36Sopenharmony_ci	.ops = &vivid_vid_cap_ctrl_ops,
95262306a36Sopenharmony_ci	.id = VIVID_CID_ALPHA_MODE,
95362306a36Sopenharmony_ci	.name = "Apply Alpha To Red Only",
95462306a36Sopenharmony_ci	.type = V4L2_CTRL_TYPE_BOOLEAN,
95562306a36Sopenharmony_ci	.max = 1,
95662306a36Sopenharmony_ci	.step = 1,
95762306a36Sopenharmony_ci};
95862306a36Sopenharmony_ci
95962306a36Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_limited_rgb_range = {
96062306a36Sopenharmony_ci	.ops = &vivid_vid_cap_ctrl_ops,
96162306a36Sopenharmony_ci	.id = VIVID_CID_LIMITED_RGB_RANGE,
96262306a36Sopenharmony_ci	.name = "Limited RGB Range (16-235)",
96362306a36Sopenharmony_ci	.type = V4L2_CTRL_TYPE_BOOLEAN,
96462306a36Sopenharmony_ci	.max = 1,
96562306a36Sopenharmony_ci	.step = 1,
96662306a36Sopenharmony_ci};
96762306a36Sopenharmony_ci
96862306a36Sopenharmony_ci
96962306a36Sopenharmony_ci/* Video Loop Control */
97062306a36Sopenharmony_ci
97162306a36Sopenharmony_cistatic int vivid_loop_cap_s_ctrl(struct v4l2_ctrl *ctrl)
97262306a36Sopenharmony_ci{
97362306a36Sopenharmony_ci	struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_loop_cap);
97462306a36Sopenharmony_ci
97562306a36Sopenharmony_ci	switch (ctrl->id) {
97662306a36Sopenharmony_ci	case VIVID_CID_LOOP_VIDEO:
97762306a36Sopenharmony_ci		dev->loop_video = ctrl->val;
97862306a36Sopenharmony_ci		vivid_update_quality(dev);
97962306a36Sopenharmony_ci		vivid_send_source_change(dev, SVID);
98062306a36Sopenharmony_ci		vivid_send_source_change(dev, HDMI);
98162306a36Sopenharmony_ci		break;
98262306a36Sopenharmony_ci	}
98362306a36Sopenharmony_ci	return 0;
98462306a36Sopenharmony_ci}
98562306a36Sopenharmony_ci
98662306a36Sopenharmony_cistatic const struct v4l2_ctrl_ops vivid_loop_cap_ctrl_ops = {
98762306a36Sopenharmony_ci	.s_ctrl = vivid_loop_cap_s_ctrl,
98862306a36Sopenharmony_ci};
98962306a36Sopenharmony_ci
99062306a36Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_loop_video = {
99162306a36Sopenharmony_ci	.ops = &vivid_loop_cap_ctrl_ops,
99262306a36Sopenharmony_ci	.id = VIVID_CID_LOOP_VIDEO,
99362306a36Sopenharmony_ci	.name = "Loop Video",
99462306a36Sopenharmony_ci	.type = V4L2_CTRL_TYPE_BOOLEAN,
99562306a36Sopenharmony_ci	.max = 1,
99662306a36Sopenharmony_ci	.step = 1,
99762306a36Sopenharmony_ci};
99862306a36Sopenharmony_ci
99962306a36Sopenharmony_ci
100062306a36Sopenharmony_ci/* VBI Capture Control */
100162306a36Sopenharmony_ci
100262306a36Sopenharmony_cistatic int vivid_vbi_cap_s_ctrl(struct v4l2_ctrl *ctrl)
100362306a36Sopenharmony_ci{
100462306a36Sopenharmony_ci	struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_vbi_cap);
100562306a36Sopenharmony_ci
100662306a36Sopenharmony_ci	switch (ctrl->id) {
100762306a36Sopenharmony_ci	case VIVID_CID_VBI_CAP_INTERLACED:
100862306a36Sopenharmony_ci		dev->vbi_cap_interlaced = ctrl->val;
100962306a36Sopenharmony_ci		break;
101062306a36Sopenharmony_ci	}
101162306a36Sopenharmony_ci	return 0;
101262306a36Sopenharmony_ci}
101362306a36Sopenharmony_ci
101462306a36Sopenharmony_cistatic const struct v4l2_ctrl_ops vivid_vbi_cap_ctrl_ops = {
101562306a36Sopenharmony_ci	.s_ctrl = vivid_vbi_cap_s_ctrl,
101662306a36Sopenharmony_ci};
101762306a36Sopenharmony_ci
101862306a36Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_vbi_cap_interlaced = {
101962306a36Sopenharmony_ci	.ops = &vivid_vbi_cap_ctrl_ops,
102062306a36Sopenharmony_ci	.id = VIVID_CID_VBI_CAP_INTERLACED,
102162306a36Sopenharmony_ci	.name = "Interlaced VBI Format",
102262306a36Sopenharmony_ci	.type = V4L2_CTRL_TYPE_BOOLEAN,
102362306a36Sopenharmony_ci	.max = 1,
102462306a36Sopenharmony_ci	.step = 1,
102562306a36Sopenharmony_ci};
102662306a36Sopenharmony_ci
102762306a36Sopenharmony_ci
102862306a36Sopenharmony_ci/* Video Output Controls */
102962306a36Sopenharmony_ci
103062306a36Sopenharmony_cistatic int vivid_vid_out_s_ctrl(struct v4l2_ctrl *ctrl)
103162306a36Sopenharmony_ci{
103262306a36Sopenharmony_ci	struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_vid_out);
103362306a36Sopenharmony_ci	struct v4l2_bt_timings *bt = &dev->dv_timings_out.bt;
103462306a36Sopenharmony_ci	u32 display_present = 0;
103562306a36Sopenharmony_ci	unsigned int i, j, bus_idx;
103662306a36Sopenharmony_ci
103762306a36Sopenharmony_ci	switch (ctrl->id) {
103862306a36Sopenharmony_ci	case VIVID_CID_HAS_CROP_OUT:
103962306a36Sopenharmony_ci		dev->has_crop_out = ctrl->val;
104062306a36Sopenharmony_ci		vivid_update_format_out(dev);
104162306a36Sopenharmony_ci		break;
104262306a36Sopenharmony_ci	case VIVID_CID_HAS_COMPOSE_OUT:
104362306a36Sopenharmony_ci		dev->has_compose_out = ctrl->val;
104462306a36Sopenharmony_ci		vivid_update_format_out(dev);
104562306a36Sopenharmony_ci		break;
104662306a36Sopenharmony_ci	case VIVID_CID_HAS_SCALER_OUT:
104762306a36Sopenharmony_ci		dev->has_scaler_out = ctrl->val;
104862306a36Sopenharmony_ci		vivid_update_format_out(dev);
104962306a36Sopenharmony_ci		break;
105062306a36Sopenharmony_ci	case V4L2_CID_DV_TX_MODE:
105162306a36Sopenharmony_ci		dev->dvi_d_out = ctrl->val == V4L2_DV_TX_MODE_DVI_D;
105262306a36Sopenharmony_ci		if (!vivid_is_hdmi_out(dev))
105362306a36Sopenharmony_ci			break;
105462306a36Sopenharmony_ci		if (!dev->dvi_d_out && (bt->flags & V4L2_DV_FL_IS_CE_VIDEO)) {
105562306a36Sopenharmony_ci			if (bt->width == 720 && bt->height <= 576)
105662306a36Sopenharmony_ci				dev->colorspace_out = V4L2_COLORSPACE_SMPTE170M;
105762306a36Sopenharmony_ci			else
105862306a36Sopenharmony_ci				dev->colorspace_out = V4L2_COLORSPACE_REC709;
105962306a36Sopenharmony_ci			dev->quantization_out = V4L2_QUANTIZATION_DEFAULT;
106062306a36Sopenharmony_ci		} else {
106162306a36Sopenharmony_ci			dev->colorspace_out = V4L2_COLORSPACE_SRGB;
106262306a36Sopenharmony_ci			dev->quantization_out = dev->dvi_d_out ?
106362306a36Sopenharmony_ci					V4L2_QUANTIZATION_LIM_RANGE :
106462306a36Sopenharmony_ci					V4L2_QUANTIZATION_DEFAULT;
106562306a36Sopenharmony_ci		}
106662306a36Sopenharmony_ci		if (dev->loop_video)
106762306a36Sopenharmony_ci			vivid_send_source_change(dev, HDMI);
106862306a36Sopenharmony_ci		break;
106962306a36Sopenharmony_ci	case VIVID_CID_DISPLAY_PRESENT:
107062306a36Sopenharmony_ci		if (dev->output_type[dev->output] != HDMI)
107162306a36Sopenharmony_ci			break;
107262306a36Sopenharmony_ci
107362306a36Sopenharmony_ci		dev->display_present[dev->output] = ctrl->val;
107462306a36Sopenharmony_ci		for (i = 0, j = 0; i < dev->num_outputs; i++)
107562306a36Sopenharmony_ci			if (dev->output_type[i] == HDMI)
107662306a36Sopenharmony_ci				display_present |=
107762306a36Sopenharmony_ci					dev->display_present[i] << j++;
107862306a36Sopenharmony_ci
107962306a36Sopenharmony_ci		__v4l2_ctrl_s_ctrl(dev->ctrl_tx_rxsense, display_present);
108062306a36Sopenharmony_ci
108162306a36Sopenharmony_ci		if (dev->edid_blocks) {
108262306a36Sopenharmony_ci			__v4l2_ctrl_s_ctrl(dev->ctrl_tx_edid_present,
108362306a36Sopenharmony_ci					   display_present);
108462306a36Sopenharmony_ci			__v4l2_ctrl_s_ctrl(dev->ctrl_tx_hotplug,
108562306a36Sopenharmony_ci					   display_present);
108662306a36Sopenharmony_ci		}
108762306a36Sopenharmony_ci
108862306a36Sopenharmony_ci		bus_idx = dev->cec_output2bus_map[dev->output];
108962306a36Sopenharmony_ci		if (!dev->cec_tx_adap[bus_idx])
109062306a36Sopenharmony_ci			break;
109162306a36Sopenharmony_ci
109262306a36Sopenharmony_ci		if (ctrl->val && dev->edid_blocks)
109362306a36Sopenharmony_ci			cec_s_phys_addr(dev->cec_tx_adap[bus_idx],
109462306a36Sopenharmony_ci					dev->cec_tx_adap[bus_idx]->phys_addr,
109562306a36Sopenharmony_ci					false);
109662306a36Sopenharmony_ci		else
109762306a36Sopenharmony_ci			cec_phys_addr_invalidate(dev->cec_tx_adap[bus_idx]);
109862306a36Sopenharmony_ci
109962306a36Sopenharmony_ci		break;
110062306a36Sopenharmony_ci	}
110162306a36Sopenharmony_ci	return 0;
110262306a36Sopenharmony_ci}
110362306a36Sopenharmony_ci
110462306a36Sopenharmony_cistatic const struct v4l2_ctrl_ops vivid_vid_out_ctrl_ops = {
110562306a36Sopenharmony_ci	.s_ctrl = vivid_vid_out_s_ctrl,
110662306a36Sopenharmony_ci};
110762306a36Sopenharmony_ci
110862306a36Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_has_crop_out = {
110962306a36Sopenharmony_ci	.ops = &vivid_vid_out_ctrl_ops,
111062306a36Sopenharmony_ci	.id = VIVID_CID_HAS_CROP_OUT,
111162306a36Sopenharmony_ci	.name = "Enable Output Cropping",
111262306a36Sopenharmony_ci	.type = V4L2_CTRL_TYPE_BOOLEAN,
111362306a36Sopenharmony_ci	.max = 1,
111462306a36Sopenharmony_ci	.def = 1,
111562306a36Sopenharmony_ci	.step = 1,
111662306a36Sopenharmony_ci};
111762306a36Sopenharmony_ci
111862306a36Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_has_compose_out = {
111962306a36Sopenharmony_ci	.ops = &vivid_vid_out_ctrl_ops,
112062306a36Sopenharmony_ci	.id = VIVID_CID_HAS_COMPOSE_OUT,
112162306a36Sopenharmony_ci	.name = "Enable Output Composing",
112262306a36Sopenharmony_ci	.type = V4L2_CTRL_TYPE_BOOLEAN,
112362306a36Sopenharmony_ci	.max = 1,
112462306a36Sopenharmony_ci	.def = 1,
112562306a36Sopenharmony_ci	.step = 1,
112662306a36Sopenharmony_ci};
112762306a36Sopenharmony_ci
112862306a36Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_has_scaler_out = {
112962306a36Sopenharmony_ci	.ops = &vivid_vid_out_ctrl_ops,
113062306a36Sopenharmony_ci	.id = VIVID_CID_HAS_SCALER_OUT,
113162306a36Sopenharmony_ci	.name = "Enable Output Scaler",
113262306a36Sopenharmony_ci	.type = V4L2_CTRL_TYPE_BOOLEAN,
113362306a36Sopenharmony_ci	.max = 1,
113462306a36Sopenharmony_ci	.def = 1,
113562306a36Sopenharmony_ci	.step = 1,
113662306a36Sopenharmony_ci};
113762306a36Sopenharmony_ci
113862306a36Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_display_present = {
113962306a36Sopenharmony_ci	.ops = &vivid_vid_out_ctrl_ops,
114062306a36Sopenharmony_ci	.id = VIVID_CID_DISPLAY_PRESENT,
114162306a36Sopenharmony_ci	.name = "Display Present",
114262306a36Sopenharmony_ci	.type = V4L2_CTRL_TYPE_BOOLEAN,
114362306a36Sopenharmony_ci	.max = 1,
114462306a36Sopenharmony_ci	.def = 1,
114562306a36Sopenharmony_ci	.step = 1,
114662306a36Sopenharmony_ci};
114762306a36Sopenharmony_ci
114862306a36Sopenharmony_ci/* Streaming Controls */
114962306a36Sopenharmony_ci
115062306a36Sopenharmony_cistatic int vivid_streaming_s_ctrl(struct v4l2_ctrl *ctrl)
115162306a36Sopenharmony_ci{
115262306a36Sopenharmony_ci	struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_streaming);
115362306a36Sopenharmony_ci
115462306a36Sopenharmony_ci	switch (ctrl->id) {
115562306a36Sopenharmony_ci	case VIVID_CID_DQBUF_ERROR:
115662306a36Sopenharmony_ci		dev->dqbuf_error = true;
115762306a36Sopenharmony_ci		break;
115862306a36Sopenharmony_ci	case VIVID_CID_PERC_DROPPED:
115962306a36Sopenharmony_ci		dev->perc_dropped_buffers = ctrl->val;
116062306a36Sopenharmony_ci		break;
116162306a36Sopenharmony_ci	case VIVID_CID_QUEUE_SETUP_ERROR:
116262306a36Sopenharmony_ci		dev->queue_setup_error = true;
116362306a36Sopenharmony_ci		break;
116462306a36Sopenharmony_ci	case VIVID_CID_BUF_PREPARE_ERROR:
116562306a36Sopenharmony_ci		dev->buf_prepare_error = true;
116662306a36Sopenharmony_ci		break;
116762306a36Sopenharmony_ci	case VIVID_CID_START_STR_ERROR:
116862306a36Sopenharmony_ci		dev->start_streaming_error = true;
116962306a36Sopenharmony_ci		break;
117062306a36Sopenharmony_ci	case VIVID_CID_REQ_VALIDATE_ERROR:
117162306a36Sopenharmony_ci		dev->req_validate_error = true;
117262306a36Sopenharmony_ci		break;
117362306a36Sopenharmony_ci	case VIVID_CID_QUEUE_ERROR:
117462306a36Sopenharmony_ci		if (vb2_start_streaming_called(&dev->vb_vid_cap_q))
117562306a36Sopenharmony_ci			vb2_queue_error(&dev->vb_vid_cap_q);
117662306a36Sopenharmony_ci		if (vb2_start_streaming_called(&dev->vb_vbi_cap_q))
117762306a36Sopenharmony_ci			vb2_queue_error(&dev->vb_vbi_cap_q);
117862306a36Sopenharmony_ci		if (vb2_start_streaming_called(&dev->vb_vid_out_q))
117962306a36Sopenharmony_ci			vb2_queue_error(&dev->vb_vid_out_q);
118062306a36Sopenharmony_ci		if (vb2_start_streaming_called(&dev->vb_vbi_out_q))
118162306a36Sopenharmony_ci			vb2_queue_error(&dev->vb_vbi_out_q);
118262306a36Sopenharmony_ci		if (vb2_start_streaming_called(&dev->vb_sdr_cap_q))
118362306a36Sopenharmony_ci			vb2_queue_error(&dev->vb_sdr_cap_q);
118462306a36Sopenharmony_ci		break;
118562306a36Sopenharmony_ci	case VIVID_CID_SEQ_WRAP:
118662306a36Sopenharmony_ci		dev->seq_wrap = ctrl->val;
118762306a36Sopenharmony_ci		break;
118862306a36Sopenharmony_ci	case VIVID_CID_TIME_WRAP:
118962306a36Sopenharmony_ci		dev->time_wrap = ctrl->val;
119062306a36Sopenharmony_ci		if (dev->time_wrap == 1)
119162306a36Sopenharmony_ci			dev->time_wrap = (1ULL << 63) - NSEC_PER_SEC * 16ULL;
119262306a36Sopenharmony_ci		else if (dev->time_wrap == 2)
119362306a36Sopenharmony_ci			dev->time_wrap = ((1ULL << 31) - 16) * NSEC_PER_SEC;
119462306a36Sopenharmony_ci		break;
119562306a36Sopenharmony_ci	}
119662306a36Sopenharmony_ci	return 0;
119762306a36Sopenharmony_ci}
119862306a36Sopenharmony_ci
119962306a36Sopenharmony_cistatic const struct v4l2_ctrl_ops vivid_streaming_ctrl_ops = {
120062306a36Sopenharmony_ci	.s_ctrl = vivid_streaming_s_ctrl,
120162306a36Sopenharmony_ci};
120262306a36Sopenharmony_ci
120362306a36Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_dqbuf_error = {
120462306a36Sopenharmony_ci	.ops = &vivid_streaming_ctrl_ops,
120562306a36Sopenharmony_ci	.id = VIVID_CID_DQBUF_ERROR,
120662306a36Sopenharmony_ci	.name = "Inject V4L2_BUF_FLAG_ERROR",
120762306a36Sopenharmony_ci	.type = V4L2_CTRL_TYPE_BUTTON,
120862306a36Sopenharmony_ci};
120962306a36Sopenharmony_ci
121062306a36Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_perc_dropped = {
121162306a36Sopenharmony_ci	.ops = &vivid_streaming_ctrl_ops,
121262306a36Sopenharmony_ci	.id = VIVID_CID_PERC_DROPPED,
121362306a36Sopenharmony_ci	.name = "Percentage of Dropped Buffers",
121462306a36Sopenharmony_ci	.type = V4L2_CTRL_TYPE_INTEGER,
121562306a36Sopenharmony_ci	.min = 0,
121662306a36Sopenharmony_ci	.max = 100,
121762306a36Sopenharmony_ci	.step = 1,
121862306a36Sopenharmony_ci};
121962306a36Sopenharmony_ci
122062306a36Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_queue_setup_error = {
122162306a36Sopenharmony_ci	.ops = &vivid_streaming_ctrl_ops,
122262306a36Sopenharmony_ci	.id = VIVID_CID_QUEUE_SETUP_ERROR,
122362306a36Sopenharmony_ci	.name = "Inject VIDIOC_REQBUFS Error",
122462306a36Sopenharmony_ci	.type = V4L2_CTRL_TYPE_BUTTON,
122562306a36Sopenharmony_ci};
122662306a36Sopenharmony_ci
122762306a36Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_buf_prepare_error = {
122862306a36Sopenharmony_ci	.ops = &vivid_streaming_ctrl_ops,
122962306a36Sopenharmony_ci	.id = VIVID_CID_BUF_PREPARE_ERROR,
123062306a36Sopenharmony_ci	.name = "Inject VIDIOC_QBUF Error",
123162306a36Sopenharmony_ci	.type = V4L2_CTRL_TYPE_BUTTON,
123262306a36Sopenharmony_ci};
123362306a36Sopenharmony_ci
123462306a36Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_start_streaming_error = {
123562306a36Sopenharmony_ci	.ops = &vivid_streaming_ctrl_ops,
123662306a36Sopenharmony_ci	.id = VIVID_CID_START_STR_ERROR,
123762306a36Sopenharmony_ci	.name = "Inject VIDIOC_STREAMON Error",
123862306a36Sopenharmony_ci	.type = V4L2_CTRL_TYPE_BUTTON,
123962306a36Sopenharmony_ci};
124062306a36Sopenharmony_ci
124162306a36Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_queue_error = {
124262306a36Sopenharmony_ci	.ops = &vivid_streaming_ctrl_ops,
124362306a36Sopenharmony_ci	.id = VIVID_CID_QUEUE_ERROR,
124462306a36Sopenharmony_ci	.name = "Inject Fatal Streaming Error",
124562306a36Sopenharmony_ci	.type = V4L2_CTRL_TYPE_BUTTON,
124662306a36Sopenharmony_ci};
124762306a36Sopenharmony_ci
124862306a36Sopenharmony_ci#ifdef CONFIG_MEDIA_CONTROLLER
124962306a36Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_req_validate_error = {
125062306a36Sopenharmony_ci	.ops = &vivid_streaming_ctrl_ops,
125162306a36Sopenharmony_ci	.id = VIVID_CID_REQ_VALIDATE_ERROR,
125262306a36Sopenharmony_ci	.name = "Inject req_validate() Error",
125362306a36Sopenharmony_ci	.type = V4L2_CTRL_TYPE_BUTTON,
125462306a36Sopenharmony_ci};
125562306a36Sopenharmony_ci#endif
125662306a36Sopenharmony_ci
125762306a36Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_seq_wrap = {
125862306a36Sopenharmony_ci	.ops = &vivid_streaming_ctrl_ops,
125962306a36Sopenharmony_ci	.id = VIVID_CID_SEQ_WRAP,
126062306a36Sopenharmony_ci	.name = "Wrap Sequence Number",
126162306a36Sopenharmony_ci	.type = V4L2_CTRL_TYPE_BOOLEAN,
126262306a36Sopenharmony_ci	.max = 1,
126362306a36Sopenharmony_ci	.step = 1,
126462306a36Sopenharmony_ci};
126562306a36Sopenharmony_ci
126662306a36Sopenharmony_cistatic const char * const vivid_ctrl_time_wrap_strings[] = {
126762306a36Sopenharmony_ci	"None",
126862306a36Sopenharmony_ci	"64 Bit",
126962306a36Sopenharmony_ci	"32 Bit",
127062306a36Sopenharmony_ci	NULL,
127162306a36Sopenharmony_ci};
127262306a36Sopenharmony_ci
127362306a36Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_time_wrap = {
127462306a36Sopenharmony_ci	.ops = &vivid_streaming_ctrl_ops,
127562306a36Sopenharmony_ci	.id = VIVID_CID_TIME_WRAP,
127662306a36Sopenharmony_ci	.name = "Wrap Timestamp",
127762306a36Sopenharmony_ci	.type = V4L2_CTRL_TYPE_MENU,
127862306a36Sopenharmony_ci	.max = ARRAY_SIZE(vivid_ctrl_time_wrap_strings) - 2,
127962306a36Sopenharmony_ci	.qmenu = vivid_ctrl_time_wrap_strings,
128062306a36Sopenharmony_ci};
128162306a36Sopenharmony_ci
128262306a36Sopenharmony_ci
128362306a36Sopenharmony_ci/* SDTV Capture Controls */
128462306a36Sopenharmony_ci
128562306a36Sopenharmony_cistatic int vivid_sdtv_cap_s_ctrl(struct v4l2_ctrl *ctrl)
128662306a36Sopenharmony_ci{
128762306a36Sopenharmony_ci	struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_sdtv_cap);
128862306a36Sopenharmony_ci
128962306a36Sopenharmony_ci	switch (ctrl->id) {
129062306a36Sopenharmony_ci	case VIVID_CID_STD_SIGNAL_MODE:
129162306a36Sopenharmony_ci		dev->std_signal_mode[dev->input] =
129262306a36Sopenharmony_ci			dev->ctrl_std_signal_mode->val;
129362306a36Sopenharmony_ci		if (dev->std_signal_mode[dev->input] == SELECTED_STD)
129462306a36Sopenharmony_ci			dev->query_std[dev->input] =
129562306a36Sopenharmony_ci				vivid_standard[dev->ctrl_standard->val];
129662306a36Sopenharmony_ci		v4l2_ctrl_activate(dev->ctrl_standard,
129762306a36Sopenharmony_ci				   dev->std_signal_mode[dev->input] ==
129862306a36Sopenharmony_ci					SELECTED_STD);
129962306a36Sopenharmony_ci		vivid_update_quality(dev);
130062306a36Sopenharmony_ci		vivid_send_source_change(dev, TV);
130162306a36Sopenharmony_ci		vivid_send_source_change(dev, SVID);
130262306a36Sopenharmony_ci		break;
130362306a36Sopenharmony_ci	}
130462306a36Sopenharmony_ci	return 0;
130562306a36Sopenharmony_ci}
130662306a36Sopenharmony_ci
130762306a36Sopenharmony_cistatic const struct v4l2_ctrl_ops vivid_sdtv_cap_ctrl_ops = {
130862306a36Sopenharmony_ci	.s_ctrl = vivid_sdtv_cap_s_ctrl,
130962306a36Sopenharmony_ci};
131062306a36Sopenharmony_ci
131162306a36Sopenharmony_cistatic const char * const vivid_ctrl_std_signal_mode_strings[] = {
131262306a36Sopenharmony_ci	"Current Standard",
131362306a36Sopenharmony_ci	"No Signal",
131462306a36Sopenharmony_ci	"No Lock",
131562306a36Sopenharmony_ci	"",
131662306a36Sopenharmony_ci	"Selected Standard",
131762306a36Sopenharmony_ci	"Cycle Through All Standards",
131862306a36Sopenharmony_ci	NULL,
131962306a36Sopenharmony_ci};
132062306a36Sopenharmony_ci
132162306a36Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_std_signal_mode = {
132262306a36Sopenharmony_ci	.ops = &vivid_sdtv_cap_ctrl_ops,
132362306a36Sopenharmony_ci	.id = VIVID_CID_STD_SIGNAL_MODE,
132462306a36Sopenharmony_ci	.name = "Standard Signal Mode",
132562306a36Sopenharmony_ci	.type = V4L2_CTRL_TYPE_MENU,
132662306a36Sopenharmony_ci	.max = ARRAY_SIZE(vivid_ctrl_std_signal_mode_strings) - 2,
132762306a36Sopenharmony_ci	.menu_skip_mask = 1 << 3,
132862306a36Sopenharmony_ci	.qmenu = vivid_ctrl_std_signal_mode_strings,
132962306a36Sopenharmony_ci};
133062306a36Sopenharmony_ci
133162306a36Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_standard = {
133262306a36Sopenharmony_ci	.ops = &vivid_sdtv_cap_ctrl_ops,
133362306a36Sopenharmony_ci	.id = VIVID_CID_STANDARD,
133462306a36Sopenharmony_ci	.name = "Standard",
133562306a36Sopenharmony_ci	.type = V4L2_CTRL_TYPE_MENU,
133662306a36Sopenharmony_ci	.max = 14,
133762306a36Sopenharmony_ci	.qmenu = vivid_ctrl_standard_strings,
133862306a36Sopenharmony_ci};
133962306a36Sopenharmony_ci
134062306a36Sopenharmony_ci
134162306a36Sopenharmony_ci
134262306a36Sopenharmony_ci/* Radio Receiver Controls */
134362306a36Sopenharmony_ci
134462306a36Sopenharmony_cistatic int vivid_radio_rx_s_ctrl(struct v4l2_ctrl *ctrl)
134562306a36Sopenharmony_ci{
134662306a36Sopenharmony_ci	struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_radio_rx);
134762306a36Sopenharmony_ci
134862306a36Sopenharmony_ci	switch (ctrl->id) {
134962306a36Sopenharmony_ci	case VIVID_CID_RADIO_SEEK_MODE:
135062306a36Sopenharmony_ci		dev->radio_rx_hw_seek_mode = ctrl->val;
135162306a36Sopenharmony_ci		break;
135262306a36Sopenharmony_ci	case VIVID_CID_RADIO_SEEK_PROG_LIM:
135362306a36Sopenharmony_ci		dev->radio_rx_hw_seek_prog_lim = ctrl->val;
135462306a36Sopenharmony_ci		break;
135562306a36Sopenharmony_ci	case VIVID_CID_RADIO_RX_RDS_RBDS:
135662306a36Sopenharmony_ci		dev->rds_gen.use_rbds = ctrl->val;
135762306a36Sopenharmony_ci		break;
135862306a36Sopenharmony_ci	case VIVID_CID_RADIO_RX_RDS_BLOCKIO:
135962306a36Sopenharmony_ci		dev->radio_rx_rds_controls = ctrl->val;
136062306a36Sopenharmony_ci		dev->radio_rx_caps &= ~V4L2_CAP_READWRITE;
136162306a36Sopenharmony_ci		dev->radio_rx_rds_use_alternates = false;
136262306a36Sopenharmony_ci		if (!dev->radio_rx_rds_controls) {
136362306a36Sopenharmony_ci			dev->radio_rx_caps |= V4L2_CAP_READWRITE;
136462306a36Sopenharmony_ci			__v4l2_ctrl_s_ctrl(dev->radio_rx_rds_pty, 0);
136562306a36Sopenharmony_ci			__v4l2_ctrl_s_ctrl(dev->radio_rx_rds_ta, 0);
136662306a36Sopenharmony_ci			__v4l2_ctrl_s_ctrl(dev->radio_rx_rds_tp, 0);
136762306a36Sopenharmony_ci			__v4l2_ctrl_s_ctrl(dev->radio_rx_rds_ms, 0);
136862306a36Sopenharmony_ci			__v4l2_ctrl_s_ctrl_string(dev->radio_rx_rds_psname, "");
136962306a36Sopenharmony_ci			__v4l2_ctrl_s_ctrl_string(dev->radio_rx_rds_radiotext, "");
137062306a36Sopenharmony_ci		}
137162306a36Sopenharmony_ci		v4l2_ctrl_activate(dev->radio_rx_rds_pty, dev->radio_rx_rds_controls);
137262306a36Sopenharmony_ci		v4l2_ctrl_activate(dev->radio_rx_rds_psname, dev->radio_rx_rds_controls);
137362306a36Sopenharmony_ci		v4l2_ctrl_activate(dev->radio_rx_rds_radiotext, dev->radio_rx_rds_controls);
137462306a36Sopenharmony_ci		v4l2_ctrl_activate(dev->radio_rx_rds_ta, dev->radio_rx_rds_controls);
137562306a36Sopenharmony_ci		v4l2_ctrl_activate(dev->radio_rx_rds_tp, dev->radio_rx_rds_controls);
137662306a36Sopenharmony_ci		v4l2_ctrl_activate(dev->radio_rx_rds_ms, dev->radio_rx_rds_controls);
137762306a36Sopenharmony_ci		dev->radio_rx_dev.device_caps = dev->radio_rx_caps;
137862306a36Sopenharmony_ci		break;
137962306a36Sopenharmony_ci	case V4L2_CID_RDS_RECEPTION:
138062306a36Sopenharmony_ci		dev->radio_rx_rds_enabled = ctrl->val;
138162306a36Sopenharmony_ci		break;
138262306a36Sopenharmony_ci	}
138362306a36Sopenharmony_ci	return 0;
138462306a36Sopenharmony_ci}
138562306a36Sopenharmony_ci
138662306a36Sopenharmony_cistatic const struct v4l2_ctrl_ops vivid_radio_rx_ctrl_ops = {
138762306a36Sopenharmony_ci	.s_ctrl = vivid_radio_rx_s_ctrl,
138862306a36Sopenharmony_ci};
138962306a36Sopenharmony_ci
139062306a36Sopenharmony_cistatic const char * const vivid_ctrl_radio_rds_mode_strings[] = {
139162306a36Sopenharmony_ci	"Block I/O",
139262306a36Sopenharmony_ci	"Controls",
139362306a36Sopenharmony_ci	NULL,
139462306a36Sopenharmony_ci};
139562306a36Sopenharmony_ci
139662306a36Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_radio_rx_rds_blockio = {
139762306a36Sopenharmony_ci	.ops = &vivid_radio_rx_ctrl_ops,
139862306a36Sopenharmony_ci	.id = VIVID_CID_RADIO_RX_RDS_BLOCKIO,
139962306a36Sopenharmony_ci	.name = "RDS Rx I/O Mode",
140062306a36Sopenharmony_ci	.type = V4L2_CTRL_TYPE_MENU,
140162306a36Sopenharmony_ci	.qmenu = vivid_ctrl_radio_rds_mode_strings,
140262306a36Sopenharmony_ci	.max = 1,
140362306a36Sopenharmony_ci};
140462306a36Sopenharmony_ci
140562306a36Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_radio_rx_rds_rbds = {
140662306a36Sopenharmony_ci	.ops = &vivid_radio_rx_ctrl_ops,
140762306a36Sopenharmony_ci	.id = VIVID_CID_RADIO_RX_RDS_RBDS,
140862306a36Sopenharmony_ci	.name = "Generate RBDS Instead of RDS",
140962306a36Sopenharmony_ci	.type = V4L2_CTRL_TYPE_BOOLEAN,
141062306a36Sopenharmony_ci	.max = 1,
141162306a36Sopenharmony_ci	.step = 1,
141262306a36Sopenharmony_ci};
141362306a36Sopenharmony_ci
141462306a36Sopenharmony_cistatic const char * const vivid_ctrl_radio_hw_seek_mode_strings[] = {
141562306a36Sopenharmony_ci	"Bounded",
141662306a36Sopenharmony_ci	"Wrap Around",
141762306a36Sopenharmony_ci	"Both",
141862306a36Sopenharmony_ci	NULL,
141962306a36Sopenharmony_ci};
142062306a36Sopenharmony_ci
142162306a36Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_radio_hw_seek_mode = {
142262306a36Sopenharmony_ci	.ops = &vivid_radio_rx_ctrl_ops,
142362306a36Sopenharmony_ci	.id = VIVID_CID_RADIO_SEEK_MODE,
142462306a36Sopenharmony_ci	.name = "Radio HW Seek Mode",
142562306a36Sopenharmony_ci	.type = V4L2_CTRL_TYPE_MENU,
142662306a36Sopenharmony_ci	.max = 2,
142762306a36Sopenharmony_ci	.qmenu = vivid_ctrl_radio_hw_seek_mode_strings,
142862306a36Sopenharmony_ci};
142962306a36Sopenharmony_ci
143062306a36Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_radio_hw_seek_prog_lim = {
143162306a36Sopenharmony_ci	.ops = &vivid_radio_rx_ctrl_ops,
143262306a36Sopenharmony_ci	.id = VIVID_CID_RADIO_SEEK_PROG_LIM,
143362306a36Sopenharmony_ci	.name = "Radio Programmable HW Seek",
143462306a36Sopenharmony_ci	.type = V4L2_CTRL_TYPE_BOOLEAN,
143562306a36Sopenharmony_ci	.max = 1,
143662306a36Sopenharmony_ci	.step = 1,
143762306a36Sopenharmony_ci};
143862306a36Sopenharmony_ci
143962306a36Sopenharmony_ci
144062306a36Sopenharmony_ci/* Radio Transmitter Controls */
144162306a36Sopenharmony_ci
144262306a36Sopenharmony_cistatic int vivid_radio_tx_s_ctrl(struct v4l2_ctrl *ctrl)
144362306a36Sopenharmony_ci{
144462306a36Sopenharmony_ci	struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_radio_tx);
144562306a36Sopenharmony_ci
144662306a36Sopenharmony_ci	switch (ctrl->id) {
144762306a36Sopenharmony_ci	case VIVID_CID_RADIO_TX_RDS_BLOCKIO:
144862306a36Sopenharmony_ci		dev->radio_tx_rds_controls = ctrl->val;
144962306a36Sopenharmony_ci		dev->radio_tx_caps &= ~V4L2_CAP_READWRITE;
145062306a36Sopenharmony_ci		if (!dev->radio_tx_rds_controls)
145162306a36Sopenharmony_ci			dev->radio_tx_caps |= V4L2_CAP_READWRITE;
145262306a36Sopenharmony_ci		dev->radio_tx_dev.device_caps = dev->radio_tx_caps;
145362306a36Sopenharmony_ci		break;
145462306a36Sopenharmony_ci	case V4L2_CID_RDS_TX_PTY:
145562306a36Sopenharmony_ci		if (dev->radio_rx_rds_controls)
145662306a36Sopenharmony_ci			v4l2_ctrl_s_ctrl(dev->radio_rx_rds_pty, ctrl->val);
145762306a36Sopenharmony_ci		break;
145862306a36Sopenharmony_ci	case V4L2_CID_RDS_TX_PS_NAME:
145962306a36Sopenharmony_ci		if (dev->radio_rx_rds_controls)
146062306a36Sopenharmony_ci			v4l2_ctrl_s_ctrl_string(dev->radio_rx_rds_psname, ctrl->p_new.p_char);
146162306a36Sopenharmony_ci		break;
146262306a36Sopenharmony_ci	case V4L2_CID_RDS_TX_RADIO_TEXT:
146362306a36Sopenharmony_ci		if (dev->radio_rx_rds_controls)
146462306a36Sopenharmony_ci			v4l2_ctrl_s_ctrl_string(dev->radio_rx_rds_radiotext, ctrl->p_new.p_char);
146562306a36Sopenharmony_ci		break;
146662306a36Sopenharmony_ci	case V4L2_CID_RDS_TX_TRAFFIC_ANNOUNCEMENT:
146762306a36Sopenharmony_ci		if (dev->radio_rx_rds_controls)
146862306a36Sopenharmony_ci			v4l2_ctrl_s_ctrl(dev->radio_rx_rds_ta, ctrl->val);
146962306a36Sopenharmony_ci		break;
147062306a36Sopenharmony_ci	case V4L2_CID_RDS_TX_TRAFFIC_PROGRAM:
147162306a36Sopenharmony_ci		if (dev->radio_rx_rds_controls)
147262306a36Sopenharmony_ci			v4l2_ctrl_s_ctrl(dev->radio_rx_rds_tp, ctrl->val);
147362306a36Sopenharmony_ci		break;
147462306a36Sopenharmony_ci	case V4L2_CID_RDS_TX_MUSIC_SPEECH:
147562306a36Sopenharmony_ci		if (dev->radio_rx_rds_controls)
147662306a36Sopenharmony_ci			v4l2_ctrl_s_ctrl(dev->radio_rx_rds_ms, ctrl->val);
147762306a36Sopenharmony_ci		break;
147862306a36Sopenharmony_ci	}
147962306a36Sopenharmony_ci	return 0;
148062306a36Sopenharmony_ci}
148162306a36Sopenharmony_ci
148262306a36Sopenharmony_cistatic const struct v4l2_ctrl_ops vivid_radio_tx_ctrl_ops = {
148362306a36Sopenharmony_ci	.s_ctrl = vivid_radio_tx_s_ctrl,
148462306a36Sopenharmony_ci};
148562306a36Sopenharmony_ci
148662306a36Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_radio_tx_rds_blockio = {
148762306a36Sopenharmony_ci	.ops = &vivid_radio_tx_ctrl_ops,
148862306a36Sopenharmony_ci	.id = VIVID_CID_RADIO_TX_RDS_BLOCKIO,
148962306a36Sopenharmony_ci	.name = "RDS Tx I/O Mode",
149062306a36Sopenharmony_ci	.type = V4L2_CTRL_TYPE_MENU,
149162306a36Sopenharmony_ci	.qmenu = vivid_ctrl_radio_rds_mode_strings,
149262306a36Sopenharmony_ci	.max = 1,
149362306a36Sopenharmony_ci	.def = 1,
149462306a36Sopenharmony_ci};
149562306a36Sopenharmony_ci
149662306a36Sopenharmony_ci
149762306a36Sopenharmony_ci/* SDR Capture Controls */
149862306a36Sopenharmony_ci
149962306a36Sopenharmony_cistatic int vivid_sdr_cap_s_ctrl(struct v4l2_ctrl *ctrl)
150062306a36Sopenharmony_ci{
150162306a36Sopenharmony_ci	struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_sdr_cap);
150262306a36Sopenharmony_ci
150362306a36Sopenharmony_ci	switch (ctrl->id) {
150462306a36Sopenharmony_ci	case VIVID_CID_SDR_CAP_FM_DEVIATION:
150562306a36Sopenharmony_ci		dev->sdr_fm_deviation = ctrl->val;
150662306a36Sopenharmony_ci		break;
150762306a36Sopenharmony_ci	}
150862306a36Sopenharmony_ci	return 0;
150962306a36Sopenharmony_ci}
151062306a36Sopenharmony_ci
151162306a36Sopenharmony_cistatic const struct v4l2_ctrl_ops vivid_sdr_cap_ctrl_ops = {
151262306a36Sopenharmony_ci	.s_ctrl = vivid_sdr_cap_s_ctrl,
151362306a36Sopenharmony_ci};
151462306a36Sopenharmony_ci
151562306a36Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_sdr_cap_fm_deviation = {
151662306a36Sopenharmony_ci	.ops = &vivid_sdr_cap_ctrl_ops,
151762306a36Sopenharmony_ci	.id = VIVID_CID_SDR_CAP_FM_DEVIATION,
151862306a36Sopenharmony_ci	.name = "FM Deviation",
151962306a36Sopenharmony_ci	.type = V4L2_CTRL_TYPE_INTEGER,
152062306a36Sopenharmony_ci	.min =    100,
152162306a36Sopenharmony_ci	.max = 200000,
152262306a36Sopenharmony_ci	.def =  75000,
152362306a36Sopenharmony_ci	.step =     1,
152462306a36Sopenharmony_ci};
152562306a36Sopenharmony_ci
152662306a36Sopenharmony_ci/* Metadata Capture Control */
152762306a36Sopenharmony_ci
152862306a36Sopenharmony_cistatic int vivid_meta_cap_s_ctrl(struct v4l2_ctrl *ctrl)
152962306a36Sopenharmony_ci{
153062306a36Sopenharmony_ci	struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev,
153162306a36Sopenharmony_ci					     ctrl_hdl_meta_cap);
153262306a36Sopenharmony_ci
153362306a36Sopenharmony_ci	switch (ctrl->id) {
153462306a36Sopenharmony_ci	case VIVID_CID_META_CAP_GENERATE_PTS:
153562306a36Sopenharmony_ci		dev->meta_pts = ctrl->val;
153662306a36Sopenharmony_ci		break;
153762306a36Sopenharmony_ci	case VIVID_CID_META_CAP_GENERATE_SCR:
153862306a36Sopenharmony_ci		dev->meta_scr = ctrl->val;
153962306a36Sopenharmony_ci		break;
154062306a36Sopenharmony_ci	}
154162306a36Sopenharmony_ci	return 0;
154262306a36Sopenharmony_ci}
154362306a36Sopenharmony_ci
154462306a36Sopenharmony_cistatic const struct v4l2_ctrl_ops vivid_meta_cap_ctrl_ops = {
154562306a36Sopenharmony_ci	.s_ctrl = vivid_meta_cap_s_ctrl,
154662306a36Sopenharmony_ci};
154762306a36Sopenharmony_ci
154862306a36Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_meta_has_pts = {
154962306a36Sopenharmony_ci	.ops = &vivid_meta_cap_ctrl_ops,
155062306a36Sopenharmony_ci	.id = VIVID_CID_META_CAP_GENERATE_PTS,
155162306a36Sopenharmony_ci	.name = "Generate PTS",
155262306a36Sopenharmony_ci	.type = V4L2_CTRL_TYPE_BOOLEAN,
155362306a36Sopenharmony_ci	.max = 1,
155462306a36Sopenharmony_ci	.def = 1,
155562306a36Sopenharmony_ci	.step = 1,
155662306a36Sopenharmony_ci};
155762306a36Sopenharmony_ci
155862306a36Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_meta_has_src_clk = {
155962306a36Sopenharmony_ci	.ops = &vivid_meta_cap_ctrl_ops,
156062306a36Sopenharmony_ci	.id = VIVID_CID_META_CAP_GENERATE_SCR,
156162306a36Sopenharmony_ci	.name = "Generate SCR",
156262306a36Sopenharmony_ci	.type = V4L2_CTRL_TYPE_BOOLEAN,
156362306a36Sopenharmony_ci	.max = 1,
156462306a36Sopenharmony_ci	.def = 1,
156562306a36Sopenharmony_ci	.step = 1,
156662306a36Sopenharmony_ci};
156762306a36Sopenharmony_ci
156862306a36Sopenharmony_cistatic const struct v4l2_ctrl_config vivid_ctrl_class = {
156962306a36Sopenharmony_ci	.ops = &vivid_user_gen_ctrl_ops,
157062306a36Sopenharmony_ci	.flags = V4L2_CTRL_FLAG_READ_ONLY | V4L2_CTRL_FLAG_WRITE_ONLY,
157162306a36Sopenharmony_ci	.id = VIVID_CID_VIVID_CLASS,
157262306a36Sopenharmony_ci	.name = "Vivid Controls",
157362306a36Sopenharmony_ci	.type = V4L2_CTRL_TYPE_CTRL_CLASS,
157462306a36Sopenharmony_ci};
157562306a36Sopenharmony_ci
157662306a36Sopenharmony_ciint vivid_create_controls(struct vivid_dev *dev, bool show_ccs_cap,
157762306a36Sopenharmony_ci		bool show_ccs_out, bool no_error_inj,
157862306a36Sopenharmony_ci		bool has_sdtv, bool has_hdmi)
157962306a36Sopenharmony_ci{
158062306a36Sopenharmony_ci	struct v4l2_ctrl_handler *hdl_user_gen = &dev->ctrl_hdl_user_gen;
158162306a36Sopenharmony_ci	struct v4l2_ctrl_handler *hdl_user_vid = &dev->ctrl_hdl_user_vid;
158262306a36Sopenharmony_ci	struct v4l2_ctrl_handler *hdl_user_aud = &dev->ctrl_hdl_user_aud;
158362306a36Sopenharmony_ci	struct v4l2_ctrl_handler *hdl_streaming = &dev->ctrl_hdl_streaming;
158462306a36Sopenharmony_ci	struct v4l2_ctrl_handler *hdl_sdtv_cap = &dev->ctrl_hdl_sdtv_cap;
158562306a36Sopenharmony_ci	struct v4l2_ctrl_handler *hdl_loop_cap = &dev->ctrl_hdl_loop_cap;
158662306a36Sopenharmony_ci	struct v4l2_ctrl_handler *hdl_fb = &dev->ctrl_hdl_fb;
158762306a36Sopenharmony_ci	struct v4l2_ctrl_handler *hdl_vid_cap = &dev->ctrl_hdl_vid_cap;
158862306a36Sopenharmony_ci	struct v4l2_ctrl_handler *hdl_vid_out = &dev->ctrl_hdl_vid_out;
158962306a36Sopenharmony_ci	struct v4l2_ctrl_handler *hdl_vbi_cap = &dev->ctrl_hdl_vbi_cap;
159062306a36Sopenharmony_ci	struct v4l2_ctrl_handler *hdl_vbi_out = &dev->ctrl_hdl_vbi_out;
159162306a36Sopenharmony_ci	struct v4l2_ctrl_handler *hdl_radio_rx = &dev->ctrl_hdl_radio_rx;
159262306a36Sopenharmony_ci	struct v4l2_ctrl_handler *hdl_radio_tx = &dev->ctrl_hdl_radio_tx;
159362306a36Sopenharmony_ci	struct v4l2_ctrl_handler *hdl_sdr_cap = &dev->ctrl_hdl_sdr_cap;
159462306a36Sopenharmony_ci	struct v4l2_ctrl_handler *hdl_meta_cap = &dev->ctrl_hdl_meta_cap;
159562306a36Sopenharmony_ci	struct v4l2_ctrl_handler *hdl_meta_out = &dev->ctrl_hdl_meta_out;
159662306a36Sopenharmony_ci	struct v4l2_ctrl_handler *hdl_tch_cap = &dev->ctrl_hdl_touch_cap;
159762306a36Sopenharmony_ci
159862306a36Sopenharmony_ci	struct v4l2_ctrl_config vivid_ctrl_dv_timings = {
159962306a36Sopenharmony_ci		.ops = &vivid_vid_cap_ctrl_ops,
160062306a36Sopenharmony_ci		.id = VIVID_CID_DV_TIMINGS,
160162306a36Sopenharmony_ci		.name = "DV Timings",
160262306a36Sopenharmony_ci		.type = V4L2_CTRL_TYPE_MENU,
160362306a36Sopenharmony_ci	};
160462306a36Sopenharmony_ci	int i;
160562306a36Sopenharmony_ci
160662306a36Sopenharmony_ci	v4l2_ctrl_handler_init(hdl_user_gen, 10);
160762306a36Sopenharmony_ci	v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_class, NULL);
160862306a36Sopenharmony_ci	v4l2_ctrl_handler_init(hdl_user_vid, 9);
160962306a36Sopenharmony_ci	v4l2_ctrl_new_custom(hdl_user_vid, &vivid_ctrl_class, NULL);
161062306a36Sopenharmony_ci	v4l2_ctrl_handler_init(hdl_user_aud, 2);
161162306a36Sopenharmony_ci	v4l2_ctrl_new_custom(hdl_user_aud, &vivid_ctrl_class, NULL);
161262306a36Sopenharmony_ci	v4l2_ctrl_handler_init(hdl_streaming, 8);
161362306a36Sopenharmony_ci	v4l2_ctrl_new_custom(hdl_streaming, &vivid_ctrl_class, NULL);
161462306a36Sopenharmony_ci	v4l2_ctrl_handler_init(hdl_sdtv_cap, 2);
161562306a36Sopenharmony_ci	v4l2_ctrl_new_custom(hdl_sdtv_cap, &vivid_ctrl_class, NULL);
161662306a36Sopenharmony_ci	v4l2_ctrl_handler_init(hdl_loop_cap, 1);
161762306a36Sopenharmony_ci	v4l2_ctrl_new_custom(hdl_loop_cap, &vivid_ctrl_class, NULL);
161862306a36Sopenharmony_ci	v4l2_ctrl_handler_init(hdl_fb, 1);
161962306a36Sopenharmony_ci	v4l2_ctrl_new_custom(hdl_fb, &vivid_ctrl_class, NULL);
162062306a36Sopenharmony_ci	v4l2_ctrl_handler_init(hdl_vid_cap, 55);
162162306a36Sopenharmony_ci	v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_class, NULL);
162262306a36Sopenharmony_ci	v4l2_ctrl_handler_init(hdl_vid_out, 26);
162362306a36Sopenharmony_ci	if (!no_error_inj || dev->has_fb || dev->num_hdmi_outputs)
162462306a36Sopenharmony_ci		v4l2_ctrl_new_custom(hdl_vid_out, &vivid_ctrl_class, NULL);
162562306a36Sopenharmony_ci	v4l2_ctrl_handler_init(hdl_vbi_cap, 21);
162662306a36Sopenharmony_ci	v4l2_ctrl_new_custom(hdl_vbi_cap, &vivid_ctrl_class, NULL);
162762306a36Sopenharmony_ci	v4l2_ctrl_handler_init(hdl_vbi_out, 19);
162862306a36Sopenharmony_ci	if (!no_error_inj)
162962306a36Sopenharmony_ci		v4l2_ctrl_new_custom(hdl_vbi_out, &vivid_ctrl_class, NULL);
163062306a36Sopenharmony_ci	v4l2_ctrl_handler_init(hdl_radio_rx, 17);
163162306a36Sopenharmony_ci	v4l2_ctrl_new_custom(hdl_radio_rx, &vivid_ctrl_class, NULL);
163262306a36Sopenharmony_ci	v4l2_ctrl_handler_init(hdl_radio_tx, 17);
163362306a36Sopenharmony_ci	v4l2_ctrl_new_custom(hdl_radio_tx, &vivid_ctrl_class, NULL);
163462306a36Sopenharmony_ci	v4l2_ctrl_handler_init(hdl_sdr_cap, 19);
163562306a36Sopenharmony_ci	v4l2_ctrl_new_custom(hdl_sdr_cap, &vivid_ctrl_class, NULL);
163662306a36Sopenharmony_ci	v4l2_ctrl_handler_init(hdl_meta_cap, 2);
163762306a36Sopenharmony_ci	v4l2_ctrl_new_custom(hdl_meta_cap, &vivid_ctrl_class, NULL);
163862306a36Sopenharmony_ci	v4l2_ctrl_handler_init(hdl_meta_out, 2);
163962306a36Sopenharmony_ci	v4l2_ctrl_new_custom(hdl_meta_out, &vivid_ctrl_class, NULL);
164062306a36Sopenharmony_ci	v4l2_ctrl_handler_init(hdl_tch_cap, 2);
164162306a36Sopenharmony_ci	v4l2_ctrl_new_custom(hdl_tch_cap, &vivid_ctrl_class, NULL);
164262306a36Sopenharmony_ci
164362306a36Sopenharmony_ci	/* User Controls */
164462306a36Sopenharmony_ci	dev->volume = v4l2_ctrl_new_std(hdl_user_aud, NULL,
164562306a36Sopenharmony_ci		V4L2_CID_AUDIO_VOLUME, 0, 255, 1, 200);
164662306a36Sopenharmony_ci	dev->mute = v4l2_ctrl_new_std(hdl_user_aud, NULL,
164762306a36Sopenharmony_ci		V4L2_CID_AUDIO_MUTE, 0, 1, 1, 0);
164862306a36Sopenharmony_ci	if (dev->has_vid_cap) {
164962306a36Sopenharmony_ci		dev->brightness = v4l2_ctrl_new_std(hdl_user_vid, &vivid_user_vid_ctrl_ops,
165062306a36Sopenharmony_ci			V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
165162306a36Sopenharmony_ci		for (i = 0; i < MAX_INPUTS; i++)
165262306a36Sopenharmony_ci			dev->input_brightness[i] = 128;
165362306a36Sopenharmony_ci		dev->contrast = v4l2_ctrl_new_std(hdl_user_vid, &vivid_user_vid_ctrl_ops,
165462306a36Sopenharmony_ci			V4L2_CID_CONTRAST, 0, 255, 1, 128);
165562306a36Sopenharmony_ci		dev->saturation = v4l2_ctrl_new_std(hdl_user_vid, &vivid_user_vid_ctrl_ops,
165662306a36Sopenharmony_ci			V4L2_CID_SATURATION, 0, 255, 1, 128);
165762306a36Sopenharmony_ci		dev->hue = v4l2_ctrl_new_std(hdl_user_vid, &vivid_user_vid_ctrl_ops,
165862306a36Sopenharmony_ci			V4L2_CID_HUE, -128, 128, 1, 0);
165962306a36Sopenharmony_ci		v4l2_ctrl_new_std(hdl_user_vid, &vivid_user_vid_ctrl_ops,
166062306a36Sopenharmony_ci			V4L2_CID_HFLIP, 0, 1, 1, 0);
166162306a36Sopenharmony_ci		v4l2_ctrl_new_std(hdl_user_vid, &vivid_user_vid_ctrl_ops,
166262306a36Sopenharmony_ci			V4L2_CID_VFLIP, 0, 1, 1, 0);
166362306a36Sopenharmony_ci		dev->autogain = v4l2_ctrl_new_std(hdl_user_vid, &vivid_user_vid_ctrl_ops,
166462306a36Sopenharmony_ci			V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
166562306a36Sopenharmony_ci		dev->gain = v4l2_ctrl_new_std(hdl_user_vid, &vivid_user_vid_ctrl_ops,
166662306a36Sopenharmony_ci			V4L2_CID_GAIN, 0, 255, 1, 100);
166762306a36Sopenharmony_ci		dev->alpha = v4l2_ctrl_new_std(hdl_user_vid, &vivid_user_vid_ctrl_ops,
166862306a36Sopenharmony_ci			V4L2_CID_ALPHA_COMPONENT, 0, 255, 1, 0);
166962306a36Sopenharmony_ci	}
167062306a36Sopenharmony_ci	dev->button = v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_button, NULL);
167162306a36Sopenharmony_ci	dev->int32 = v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_int32, NULL);
167262306a36Sopenharmony_ci	dev->int64 = v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_int64, NULL);
167362306a36Sopenharmony_ci	dev->boolean = v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_boolean, NULL);
167462306a36Sopenharmony_ci	dev->menu = v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_menu, NULL);
167562306a36Sopenharmony_ci	dev->string = v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_string, NULL);
167662306a36Sopenharmony_ci	dev->bitmask = v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_bitmask, NULL);
167762306a36Sopenharmony_ci	dev->int_menu = v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_int_menu, NULL);
167862306a36Sopenharmony_ci	dev->ro_int32 = v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_ro_int32, NULL);
167962306a36Sopenharmony_ci	v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_area, NULL);
168062306a36Sopenharmony_ci	v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_u32_array, NULL);
168162306a36Sopenharmony_ci	v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_u32_dyn_array, NULL);
168262306a36Sopenharmony_ci	v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_u16_matrix, NULL);
168362306a36Sopenharmony_ci	v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_u8_4d_array, NULL);
168462306a36Sopenharmony_ci	dev->pixel_array = v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_u8_pixel_array, NULL);
168562306a36Sopenharmony_ci	v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_s32_array, NULL);
168662306a36Sopenharmony_ci	v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_s64_array, NULL);
168762306a36Sopenharmony_ci
168862306a36Sopenharmony_ci	if (dev->has_vid_cap) {
168962306a36Sopenharmony_ci		/* Image Processing Controls */
169062306a36Sopenharmony_ci		struct v4l2_ctrl_config vivid_ctrl_test_pattern = {
169162306a36Sopenharmony_ci			.ops = &vivid_vid_cap_ctrl_ops,
169262306a36Sopenharmony_ci			.id = VIVID_CID_TEST_PATTERN,
169362306a36Sopenharmony_ci			.name = "Test Pattern",
169462306a36Sopenharmony_ci			.type = V4L2_CTRL_TYPE_MENU,
169562306a36Sopenharmony_ci			.max = TPG_PAT_NOISE,
169662306a36Sopenharmony_ci			.qmenu = tpg_pattern_strings,
169762306a36Sopenharmony_ci		};
169862306a36Sopenharmony_ci
169962306a36Sopenharmony_ci		dev->test_pattern = v4l2_ctrl_new_custom(hdl_vid_cap,
170062306a36Sopenharmony_ci				&vivid_ctrl_test_pattern, NULL);
170162306a36Sopenharmony_ci		v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_perc_fill, NULL);
170262306a36Sopenharmony_ci		v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_hor_movement, NULL);
170362306a36Sopenharmony_ci		v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_vert_movement, NULL);
170462306a36Sopenharmony_ci		v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_osd_mode, NULL);
170562306a36Sopenharmony_ci		v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_show_border, NULL);
170662306a36Sopenharmony_ci		v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_show_square, NULL);
170762306a36Sopenharmony_ci		v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_hflip, NULL);
170862306a36Sopenharmony_ci		v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_vflip, NULL);
170962306a36Sopenharmony_ci		v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_insert_sav, NULL);
171062306a36Sopenharmony_ci		v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_insert_eav, NULL);
171162306a36Sopenharmony_ci		v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_insert_hdmi_video_guard_band, NULL);
171262306a36Sopenharmony_ci		v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_reduced_fps, NULL);
171362306a36Sopenharmony_ci		if (show_ccs_cap) {
171462306a36Sopenharmony_ci			dev->ctrl_has_crop_cap = v4l2_ctrl_new_custom(hdl_vid_cap,
171562306a36Sopenharmony_ci				&vivid_ctrl_has_crop_cap, NULL);
171662306a36Sopenharmony_ci			dev->ctrl_has_compose_cap = v4l2_ctrl_new_custom(hdl_vid_cap,
171762306a36Sopenharmony_ci				&vivid_ctrl_has_compose_cap, NULL);
171862306a36Sopenharmony_ci			dev->ctrl_has_scaler_cap = v4l2_ctrl_new_custom(hdl_vid_cap,
171962306a36Sopenharmony_ci				&vivid_ctrl_has_scaler_cap, NULL);
172062306a36Sopenharmony_ci		}
172162306a36Sopenharmony_ci
172262306a36Sopenharmony_ci		v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_tstamp_src, NULL);
172362306a36Sopenharmony_ci		dev->colorspace = v4l2_ctrl_new_custom(hdl_vid_cap,
172462306a36Sopenharmony_ci			&vivid_ctrl_colorspace, NULL);
172562306a36Sopenharmony_ci		v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_xfer_func, NULL);
172662306a36Sopenharmony_ci		v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_ycbcr_enc, NULL);
172762306a36Sopenharmony_ci		v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_hsv_enc, NULL);
172862306a36Sopenharmony_ci		v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_quantization, NULL);
172962306a36Sopenharmony_ci		v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_alpha_mode, NULL);
173062306a36Sopenharmony_ci	}
173162306a36Sopenharmony_ci
173262306a36Sopenharmony_ci	if (dev->has_vid_out && show_ccs_out) {
173362306a36Sopenharmony_ci		dev->ctrl_has_crop_out = v4l2_ctrl_new_custom(hdl_vid_out,
173462306a36Sopenharmony_ci			&vivid_ctrl_has_crop_out, NULL);
173562306a36Sopenharmony_ci		dev->ctrl_has_compose_out = v4l2_ctrl_new_custom(hdl_vid_out,
173662306a36Sopenharmony_ci			&vivid_ctrl_has_compose_out, NULL);
173762306a36Sopenharmony_ci		dev->ctrl_has_scaler_out = v4l2_ctrl_new_custom(hdl_vid_out,
173862306a36Sopenharmony_ci			&vivid_ctrl_has_scaler_out, NULL);
173962306a36Sopenharmony_ci	}
174062306a36Sopenharmony_ci
174162306a36Sopenharmony_ci	/*
174262306a36Sopenharmony_ci	 * Testing this driver with v4l2-compliance will trigger the error
174362306a36Sopenharmony_ci	 * injection controls, and after that nothing will work as expected.
174462306a36Sopenharmony_ci	 * So we have a module option to drop these error injecting controls
174562306a36Sopenharmony_ci	 * allowing us to run v4l2_compliance again.
174662306a36Sopenharmony_ci	 */
174762306a36Sopenharmony_ci	if (!no_error_inj) {
174862306a36Sopenharmony_ci		v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_disconnect, NULL);
174962306a36Sopenharmony_ci		v4l2_ctrl_new_custom(hdl_streaming, &vivid_ctrl_dqbuf_error, NULL);
175062306a36Sopenharmony_ci		v4l2_ctrl_new_custom(hdl_streaming, &vivid_ctrl_perc_dropped, NULL);
175162306a36Sopenharmony_ci		v4l2_ctrl_new_custom(hdl_streaming, &vivid_ctrl_queue_setup_error, NULL);
175262306a36Sopenharmony_ci		v4l2_ctrl_new_custom(hdl_streaming, &vivid_ctrl_buf_prepare_error, NULL);
175362306a36Sopenharmony_ci		v4l2_ctrl_new_custom(hdl_streaming, &vivid_ctrl_start_streaming_error, NULL);
175462306a36Sopenharmony_ci		v4l2_ctrl_new_custom(hdl_streaming, &vivid_ctrl_queue_error, NULL);
175562306a36Sopenharmony_ci#ifdef CONFIG_MEDIA_CONTROLLER
175662306a36Sopenharmony_ci		v4l2_ctrl_new_custom(hdl_streaming, &vivid_ctrl_req_validate_error, NULL);
175762306a36Sopenharmony_ci#endif
175862306a36Sopenharmony_ci		v4l2_ctrl_new_custom(hdl_streaming, &vivid_ctrl_seq_wrap, NULL);
175962306a36Sopenharmony_ci		v4l2_ctrl_new_custom(hdl_streaming, &vivid_ctrl_time_wrap, NULL);
176062306a36Sopenharmony_ci	}
176162306a36Sopenharmony_ci
176262306a36Sopenharmony_ci	if (has_sdtv && (dev->has_vid_cap || dev->has_vbi_cap)) {
176362306a36Sopenharmony_ci		if (dev->has_vid_cap)
176462306a36Sopenharmony_ci			v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_std_aspect_ratio, NULL);
176562306a36Sopenharmony_ci		dev->ctrl_std_signal_mode = v4l2_ctrl_new_custom(hdl_sdtv_cap,
176662306a36Sopenharmony_ci			&vivid_ctrl_std_signal_mode, NULL);
176762306a36Sopenharmony_ci		dev->ctrl_standard = v4l2_ctrl_new_custom(hdl_sdtv_cap,
176862306a36Sopenharmony_ci			&vivid_ctrl_standard, NULL);
176962306a36Sopenharmony_ci		if (dev->ctrl_std_signal_mode)
177062306a36Sopenharmony_ci			v4l2_ctrl_cluster(2, &dev->ctrl_std_signal_mode);
177162306a36Sopenharmony_ci		if (dev->has_raw_vbi_cap)
177262306a36Sopenharmony_ci			v4l2_ctrl_new_custom(hdl_vbi_cap, &vivid_ctrl_vbi_cap_interlaced, NULL);
177362306a36Sopenharmony_ci	}
177462306a36Sopenharmony_ci
177562306a36Sopenharmony_ci	if (dev->num_hdmi_inputs) {
177662306a36Sopenharmony_ci		s64 hdmi_input_mask = GENMASK(dev->num_hdmi_inputs - 1, 0);
177762306a36Sopenharmony_ci
177862306a36Sopenharmony_ci		dev->ctrl_dv_timings_signal_mode = v4l2_ctrl_new_custom(hdl_vid_cap,
177962306a36Sopenharmony_ci					&vivid_ctrl_dv_timings_signal_mode, NULL);
178062306a36Sopenharmony_ci
178162306a36Sopenharmony_ci		vivid_ctrl_dv_timings.max = dev->query_dv_timings_size - 1;
178262306a36Sopenharmony_ci		vivid_ctrl_dv_timings.qmenu =
178362306a36Sopenharmony_ci			(const char * const *)dev->query_dv_timings_qmenu;
178462306a36Sopenharmony_ci		dev->ctrl_dv_timings = v4l2_ctrl_new_custom(hdl_vid_cap,
178562306a36Sopenharmony_ci			&vivid_ctrl_dv_timings, NULL);
178662306a36Sopenharmony_ci		if (dev->ctrl_dv_timings_signal_mode)
178762306a36Sopenharmony_ci			v4l2_ctrl_cluster(2, &dev->ctrl_dv_timings_signal_mode);
178862306a36Sopenharmony_ci
178962306a36Sopenharmony_ci		v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_dv_timings_aspect_ratio, NULL);
179062306a36Sopenharmony_ci		v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_max_edid_blocks, NULL);
179162306a36Sopenharmony_ci		dev->real_rgb_range_cap = v4l2_ctrl_new_custom(hdl_vid_cap,
179262306a36Sopenharmony_ci			&vivid_ctrl_limited_rgb_range, NULL);
179362306a36Sopenharmony_ci		dev->rgb_range_cap = v4l2_ctrl_new_std_menu(hdl_vid_cap,
179462306a36Sopenharmony_ci			&vivid_vid_cap_ctrl_ops,
179562306a36Sopenharmony_ci			V4L2_CID_DV_RX_RGB_RANGE, V4L2_DV_RGB_RANGE_FULL,
179662306a36Sopenharmony_ci			0, V4L2_DV_RGB_RANGE_AUTO);
179762306a36Sopenharmony_ci		dev->ctrl_rx_power_present = v4l2_ctrl_new_std(hdl_vid_cap,
179862306a36Sopenharmony_ci			NULL, V4L2_CID_DV_RX_POWER_PRESENT, 0, hdmi_input_mask,
179962306a36Sopenharmony_ci			0, hdmi_input_mask);
180062306a36Sopenharmony_ci
180162306a36Sopenharmony_ci	}
180262306a36Sopenharmony_ci	if (dev->num_hdmi_outputs) {
180362306a36Sopenharmony_ci		s64 hdmi_output_mask = GENMASK(dev->num_hdmi_outputs - 1, 0);
180462306a36Sopenharmony_ci
180562306a36Sopenharmony_ci		/*
180662306a36Sopenharmony_ci		 * We aren't doing anything with this at the moment, but
180762306a36Sopenharmony_ci		 * HDMI outputs typically have this controls.
180862306a36Sopenharmony_ci		 */
180962306a36Sopenharmony_ci		dev->ctrl_tx_rgb_range = v4l2_ctrl_new_std_menu(hdl_vid_out, NULL,
181062306a36Sopenharmony_ci			V4L2_CID_DV_TX_RGB_RANGE, V4L2_DV_RGB_RANGE_FULL,
181162306a36Sopenharmony_ci			0, V4L2_DV_RGB_RANGE_AUTO);
181262306a36Sopenharmony_ci		dev->ctrl_tx_mode = v4l2_ctrl_new_std_menu(hdl_vid_out, NULL,
181362306a36Sopenharmony_ci			V4L2_CID_DV_TX_MODE, V4L2_DV_TX_MODE_HDMI,
181462306a36Sopenharmony_ci			0, V4L2_DV_TX_MODE_HDMI);
181562306a36Sopenharmony_ci		dev->ctrl_display_present = v4l2_ctrl_new_custom(hdl_vid_out,
181662306a36Sopenharmony_ci			&vivid_ctrl_display_present, NULL);
181762306a36Sopenharmony_ci		dev->ctrl_tx_hotplug = v4l2_ctrl_new_std(hdl_vid_out,
181862306a36Sopenharmony_ci			NULL, V4L2_CID_DV_TX_HOTPLUG, 0, hdmi_output_mask,
181962306a36Sopenharmony_ci			0, hdmi_output_mask);
182062306a36Sopenharmony_ci		dev->ctrl_tx_rxsense = v4l2_ctrl_new_std(hdl_vid_out,
182162306a36Sopenharmony_ci			NULL, V4L2_CID_DV_TX_RXSENSE, 0, hdmi_output_mask,
182262306a36Sopenharmony_ci			0, hdmi_output_mask);
182362306a36Sopenharmony_ci		dev->ctrl_tx_edid_present = v4l2_ctrl_new_std(hdl_vid_out,
182462306a36Sopenharmony_ci			NULL, V4L2_CID_DV_TX_EDID_PRESENT, 0, hdmi_output_mask,
182562306a36Sopenharmony_ci			0, hdmi_output_mask);
182662306a36Sopenharmony_ci	}
182762306a36Sopenharmony_ci	if ((dev->has_vid_cap && dev->has_vid_out) ||
182862306a36Sopenharmony_ci	    (dev->has_vbi_cap && dev->has_vbi_out))
182962306a36Sopenharmony_ci		v4l2_ctrl_new_custom(hdl_loop_cap, &vivid_ctrl_loop_video, NULL);
183062306a36Sopenharmony_ci
183162306a36Sopenharmony_ci	if (dev->has_fb)
183262306a36Sopenharmony_ci		v4l2_ctrl_new_custom(hdl_fb, &vivid_ctrl_clear_fb, NULL);
183362306a36Sopenharmony_ci
183462306a36Sopenharmony_ci	if (dev->has_radio_rx) {
183562306a36Sopenharmony_ci		v4l2_ctrl_new_custom(hdl_radio_rx, &vivid_ctrl_radio_hw_seek_mode, NULL);
183662306a36Sopenharmony_ci		v4l2_ctrl_new_custom(hdl_radio_rx, &vivid_ctrl_radio_hw_seek_prog_lim, NULL);
183762306a36Sopenharmony_ci		v4l2_ctrl_new_custom(hdl_radio_rx, &vivid_ctrl_radio_rx_rds_blockio, NULL);
183862306a36Sopenharmony_ci		v4l2_ctrl_new_custom(hdl_radio_rx, &vivid_ctrl_radio_rx_rds_rbds, NULL);
183962306a36Sopenharmony_ci		v4l2_ctrl_new_std(hdl_radio_rx, &vivid_radio_rx_ctrl_ops,
184062306a36Sopenharmony_ci			V4L2_CID_RDS_RECEPTION, 0, 1, 1, 1);
184162306a36Sopenharmony_ci		dev->radio_rx_rds_pty = v4l2_ctrl_new_std(hdl_radio_rx,
184262306a36Sopenharmony_ci			&vivid_radio_rx_ctrl_ops,
184362306a36Sopenharmony_ci			V4L2_CID_RDS_RX_PTY, 0, 31, 1, 0);
184462306a36Sopenharmony_ci		dev->radio_rx_rds_psname = v4l2_ctrl_new_std(hdl_radio_rx,
184562306a36Sopenharmony_ci			&vivid_radio_rx_ctrl_ops,
184662306a36Sopenharmony_ci			V4L2_CID_RDS_RX_PS_NAME, 0, 8, 8, 0);
184762306a36Sopenharmony_ci		dev->radio_rx_rds_radiotext = v4l2_ctrl_new_std(hdl_radio_rx,
184862306a36Sopenharmony_ci			&vivid_radio_rx_ctrl_ops,
184962306a36Sopenharmony_ci			V4L2_CID_RDS_RX_RADIO_TEXT, 0, 64, 64, 0);
185062306a36Sopenharmony_ci		dev->radio_rx_rds_ta = v4l2_ctrl_new_std(hdl_radio_rx,
185162306a36Sopenharmony_ci			&vivid_radio_rx_ctrl_ops,
185262306a36Sopenharmony_ci			V4L2_CID_RDS_RX_TRAFFIC_ANNOUNCEMENT, 0, 1, 1, 0);
185362306a36Sopenharmony_ci		dev->radio_rx_rds_tp = v4l2_ctrl_new_std(hdl_radio_rx,
185462306a36Sopenharmony_ci			&vivid_radio_rx_ctrl_ops,
185562306a36Sopenharmony_ci			V4L2_CID_RDS_RX_TRAFFIC_PROGRAM, 0, 1, 1, 0);
185662306a36Sopenharmony_ci		dev->radio_rx_rds_ms = v4l2_ctrl_new_std(hdl_radio_rx,
185762306a36Sopenharmony_ci			&vivid_radio_rx_ctrl_ops,
185862306a36Sopenharmony_ci			V4L2_CID_RDS_RX_MUSIC_SPEECH, 0, 1, 1, 1);
185962306a36Sopenharmony_ci	}
186062306a36Sopenharmony_ci	if (dev->has_radio_tx) {
186162306a36Sopenharmony_ci		v4l2_ctrl_new_custom(hdl_radio_tx,
186262306a36Sopenharmony_ci			&vivid_ctrl_radio_tx_rds_blockio, NULL);
186362306a36Sopenharmony_ci		dev->radio_tx_rds_pi = v4l2_ctrl_new_std(hdl_radio_tx,
186462306a36Sopenharmony_ci			&vivid_radio_tx_ctrl_ops,
186562306a36Sopenharmony_ci			V4L2_CID_RDS_TX_PI, 0, 0xffff, 1, 0x8088);
186662306a36Sopenharmony_ci		dev->radio_tx_rds_pty = v4l2_ctrl_new_std(hdl_radio_tx,
186762306a36Sopenharmony_ci			&vivid_radio_tx_ctrl_ops,
186862306a36Sopenharmony_ci			V4L2_CID_RDS_TX_PTY, 0, 31, 1, 3);
186962306a36Sopenharmony_ci		dev->radio_tx_rds_psname = v4l2_ctrl_new_std(hdl_radio_tx,
187062306a36Sopenharmony_ci			&vivid_radio_tx_ctrl_ops,
187162306a36Sopenharmony_ci			V4L2_CID_RDS_TX_PS_NAME, 0, 8, 8, 0);
187262306a36Sopenharmony_ci		if (dev->radio_tx_rds_psname)
187362306a36Sopenharmony_ci			v4l2_ctrl_s_ctrl_string(dev->radio_tx_rds_psname, "VIVID-TX");
187462306a36Sopenharmony_ci		dev->radio_tx_rds_radiotext = v4l2_ctrl_new_std(hdl_radio_tx,
187562306a36Sopenharmony_ci			&vivid_radio_tx_ctrl_ops,
187662306a36Sopenharmony_ci			V4L2_CID_RDS_TX_RADIO_TEXT, 0, 64 * 2, 64, 0);
187762306a36Sopenharmony_ci		if (dev->radio_tx_rds_radiotext)
187862306a36Sopenharmony_ci			v4l2_ctrl_s_ctrl_string(dev->radio_tx_rds_radiotext,
187962306a36Sopenharmony_ci			       "This is a VIVID default Radio Text template text, change at will");
188062306a36Sopenharmony_ci		dev->radio_tx_rds_mono_stereo = v4l2_ctrl_new_std(hdl_radio_tx,
188162306a36Sopenharmony_ci			&vivid_radio_tx_ctrl_ops,
188262306a36Sopenharmony_ci			V4L2_CID_RDS_TX_MONO_STEREO, 0, 1, 1, 1);
188362306a36Sopenharmony_ci		dev->radio_tx_rds_art_head = v4l2_ctrl_new_std(hdl_radio_tx,
188462306a36Sopenharmony_ci			&vivid_radio_tx_ctrl_ops,
188562306a36Sopenharmony_ci			V4L2_CID_RDS_TX_ARTIFICIAL_HEAD, 0, 1, 1, 0);
188662306a36Sopenharmony_ci		dev->radio_tx_rds_compressed = v4l2_ctrl_new_std(hdl_radio_tx,
188762306a36Sopenharmony_ci			&vivid_radio_tx_ctrl_ops,
188862306a36Sopenharmony_ci			V4L2_CID_RDS_TX_COMPRESSED, 0, 1, 1, 0);
188962306a36Sopenharmony_ci		dev->radio_tx_rds_dyn_pty = v4l2_ctrl_new_std(hdl_radio_tx,
189062306a36Sopenharmony_ci			&vivid_radio_tx_ctrl_ops,
189162306a36Sopenharmony_ci			V4L2_CID_RDS_TX_DYNAMIC_PTY, 0, 1, 1, 0);
189262306a36Sopenharmony_ci		dev->radio_tx_rds_ta = v4l2_ctrl_new_std(hdl_radio_tx,
189362306a36Sopenharmony_ci			&vivid_radio_tx_ctrl_ops,
189462306a36Sopenharmony_ci			V4L2_CID_RDS_TX_TRAFFIC_ANNOUNCEMENT, 0, 1, 1, 0);
189562306a36Sopenharmony_ci		dev->radio_tx_rds_tp = v4l2_ctrl_new_std(hdl_radio_tx,
189662306a36Sopenharmony_ci			&vivid_radio_tx_ctrl_ops,
189762306a36Sopenharmony_ci			V4L2_CID_RDS_TX_TRAFFIC_PROGRAM, 0, 1, 1, 1);
189862306a36Sopenharmony_ci		dev->radio_tx_rds_ms = v4l2_ctrl_new_std(hdl_radio_tx,
189962306a36Sopenharmony_ci			&vivid_radio_tx_ctrl_ops,
190062306a36Sopenharmony_ci			V4L2_CID_RDS_TX_MUSIC_SPEECH, 0, 1, 1, 1);
190162306a36Sopenharmony_ci	}
190262306a36Sopenharmony_ci	if (dev->has_sdr_cap) {
190362306a36Sopenharmony_ci		v4l2_ctrl_new_custom(hdl_sdr_cap,
190462306a36Sopenharmony_ci			&vivid_ctrl_sdr_cap_fm_deviation, NULL);
190562306a36Sopenharmony_ci	}
190662306a36Sopenharmony_ci	if (dev->has_meta_cap) {
190762306a36Sopenharmony_ci		v4l2_ctrl_new_custom(hdl_meta_cap,
190862306a36Sopenharmony_ci				     &vivid_ctrl_meta_has_pts, NULL);
190962306a36Sopenharmony_ci		v4l2_ctrl_new_custom(hdl_meta_cap,
191062306a36Sopenharmony_ci				     &vivid_ctrl_meta_has_src_clk, NULL);
191162306a36Sopenharmony_ci	}
191262306a36Sopenharmony_ci
191362306a36Sopenharmony_ci	if (hdl_user_gen->error)
191462306a36Sopenharmony_ci		return hdl_user_gen->error;
191562306a36Sopenharmony_ci	if (hdl_user_vid->error)
191662306a36Sopenharmony_ci		return hdl_user_vid->error;
191762306a36Sopenharmony_ci	if (hdl_user_aud->error)
191862306a36Sopenharmony_ci		return hdl_user_aud->error;
191962306a36Sopenharmony_ci	if (hdl_streaming->error)
192062306a36Sopenharmony_ci		return hdl_streaming->error;
192162306a36Sopenharmony_ci	if (hdl_sdr_cap->error)
192262306a36Sopenharmony_ci		return hdl_sdr_cap->error;
192362306a36Sopenharmony_ci	if (hdl_loop_cap->error)
192462306a36Sopenharmony_ci		return hdl_loop_cap->error;
192562306a36Sopenharmony_ci
192662306a36Sopenharmony_ci	if (dev->autogain)
192762306a36Sopenharmony_ci		v4l2_ctrl_auto_cluster(2, &dev->autogain, 0, true);
192862306a36Sopenharmony_ci
192962306a36Sopenharmony_ci	if (dev->has_vid_cap) {
193062306a36Sopenharmony_ci		v4l2_ctrl_add_handler(hdl_vid_cap, hdl_user_gen, NULL, false);
193162306a36Sopenharmony_ci		v4l2_ctrl_add_handler(hdl_vid_cap, hdl_user_vid, NULL, false);
193262306a36Sopenharmony_ci		v4l2_ctrl_add_handler(hdl_vid_cap, hdl_user_aud, NULL, false);
193362306a36Sopenharmony_ci		v4l2_ctrl_add_handler(hdl_vid_cap, hdl_streaming, NULL, false);
193462306a36Sopenharmony_ci		v4l2_ctrl_add_handler(hdl_vid_cap, hdl_sdtv_cap, NULL, false);
193562306a36Sopenharmony_ci		v4l2_ctrl_add_handler(hdl_vid_cap, hdl_loop_cap, NULL, false);
193662306a36Sopenharmony_ci		v4l2_ctrl_add_handler(hdl_vid_cap, hdl_fb, NULL, false);
193762306a36Sopenharmony_ci		if (hdl_vid_cap->error)
193862306a36Sopenharmony_ci			return hdl_vid_cap->error;
193962306a36Sopenharmony_ci		dev->vid_cap_dev.ctrl_handler = hdl_vid_cap;
194062306a36Sopenharmony_ci	}
194162306a36Sopenharmony_ci	if (dev->has_vid_out) {
194262306a36Sopenharmony_ci		v4l2_ctrl_add_handler(hdl_vid_out, hdl_user_gen, NULL, false);
194362306a36Sopenharmony_ci		v4l2_ctrl_add_handler(hdl_vid_out, hdl_user_aud, NULL, false);
194462306a36Sopenharmony_ci		v4l2_ctrl_add_handler(hdl_vid_out, hdl_streaming, NULL, false);
194562306a36Sopenharmony_ci		v4l2_ctrl_add_handler(hdl_vid_out, hdl_fb, NULL, false);
194662306a36Sopenharmony_ci		if (hdl_vid_out->error)
194762306a36Sopenharmony_ci			return hdl_vid_out->error;
194862306a36Sopenharmony_ci		dev->vid_out_dev.ctrl_handler = hdl_vid_out;
194962306a36Sopenharmony_ci	}
195062306a36Sopenharmony_ci	if (dev->has_vbi_cap) {
195162306a36Sopenharmony_ci		v4l2_ctrl_add_handler(hdl_vbi_cap, hdl_user_gen, NULL, false);
195262306a36Sopenharmony_ci		v4l2_ctrl_add_handler(hdl_vbi_cap, hdl_streaming, NULL, false);
195362306a36Sopenharmony_ci		v4l2_ctrl_add_handler(hdl_vbi_cap, hdl_sdtv_cap, NULL, false);
195462306a36Sopenharmony_ci		v4l2_ctrl_add_handler(hdl_vbi_cap, hdl_loop_cap, NULL, false);
195562306a36Sopenharmony_ci		if (hdl_vbi_cap->error)
195662306a36Sopenharmony_ci			return hdl_vbi_cap->error;
195762306a36Sopenharmony_ci		dev->vbi_cap_dev.ctrl_handler = hdl_vbi_cap;
195862306a36Sopenharmony_ci	}
195962306a36Sopenharmony_ci	if (dev->has_vbi_out) {
196062306a36Sopenharmony_ci		v4l2_ctrl_add_handler(hdl_vbi_out, hdl_user_gen, NULL, false);
196162306a36Sopenharmony_ci		v4l2_ctrl_add_handler(hdl_vbi_out, hdl_streaming, NULL, false);
196262306a36Sopenharmony_ci		if (hdl_vbi_out->error)
196362306a36Sopenharmony_ci			return hdl_vbi_out->error;
196462306a36Sopenharmony_ci		dev->vbi_out_dev.ctrl_handler = hdl_vbi_out;
196562306a36Sopenharmony_ci	}
196662306a36Sopenharmony_ci	if (dev->has_radio_rx) {
196762306a36Sopenharmony_ci		v4l2_ctrl_add_handler(hdl_radio_rx, hdl_user_gen, NULL, false);
196862306a36Sopenharmony_ci		v4l2_ctrl_add_handler(hdl_radio_rx, hdl_user_aud, NULL, false);
196962306a36Sopenharmony_ci		if (hdl_radio_rx->error)
197062306a36Sopenharmony_ci			return hdl_radio_rx->error;
197162306a36Sopenharmony_ci		dev->radio_rx_dev.ctrl_handler = hdl_radio_rx;
197262306a36Sopenharmony_ci	}
197362306a36Sopenharmony_ci	if (dev->has_radio_tx) {
197462306a36Sopenharmony_ci		v4l2_ctrl_add_handler(hdl_radio_tx, hdl_user_gen, NULL, false);
197562306a36Sopenharmony_ci		v4l2_ctrl_add_handler(hdl_radio_tx, hdl_user_aud, NULL, false);
197662306a36Sopenharmony_ci		if (hdl_radio_tx->error)
197762306a36Sopenharmony_ci			return hdl_radio_tx->error;
197862306a36Sopenharmony_ci		dev->radio_tx_dev.ctrl_handler = hdl_radio_tx;
197962306a36Sopenharmony_ci	}
198062306a36Sopenharmony_ci	if (dev->has_sdr_cap) {
198162306a36Sopenharmony_ci		v4l2_ctrl_add_handler(hdl_sdr_cap, hdl_user_gen, NULL, false);
198262306a36Sopenharmony_ci		v4l2_ctrl_add_handler(hdl_sdr_cap, hdl_streaming, NULL, false);
198362306a36Sopenharmony_ci		if (hdl_sdr_cap->error)
198462306a36Sopenharmony_ci			return hdl_sdr_cap->error;
198562306a36Sopenharmony_ci		dev->sdr_cap_dev.ctrl_handler = hdl_sdr_cap;
198662306a36Sopenharmony_ci	}
198762306a36Sopenharmony_ci	if (dev->has_meta_cap) {
198862306a36Sopenharmony_ci		v4l2_ctrl_add_handler(hdl_meta_cap, hdl_user_gen, NULL, false);
198962306a36Sopenharmony_ci		v4l2_ctrl_add_handler(hdl_meta_cap, hdl_streaming, NULL, false);
199062306a36Sopenharmony_ci		if (hdl_meta_cap->error)
199162306a36Sopenharmony_ci			return hdl_meta_cap->error;
199262306a36Sopenharmony_ci		dev->meta_cap_dev.ctrl_handler = hdl_meta_cap;
199362306a36Sopenharmony_ci	}
199462306a36Sopenharmony_ci	if (dev->has_meta_out) {
199562306a36Sopenharmony_ci		v4l2_ctrl_add_handler(hdl_meta_out, hdl_user_gen, NULL, false);
199662306a36Sopenharmony_ci		v4l2_ctrl_add_handler(hdl_meta_out, hdl_streaming, NULL, false);
199762306a36Sopenharmony_ci		if (hdl_meta_out->error)
199862306a36Sopenharmony_ci			return hdl_meta_out->error;
199962306a36Sopenharmony_ci		dev->meta_out_dev.ctrl_handler = hdl_meta_out;
200062306a36Sopenharmony_ci	}
200162306a36Sopenharmony_ci	if (dev->has_touch_cap) {
200262306a36Sopenharmony_ci		v4l2_ctrl_add_handler(hdl_tch_cap, hdl_user_gen, NULL, false);
200362306a36Sopenharmony_ci		v4l2_ctrl_add_handler(hdl_tch_cap, hdl_streaming, NULL, false);
200462306a36Sopenharmony_ci		if (hdl_tch_cap->error)
200562306a36Sopenharmony_ci			return hdl_tch_cap->error;
200662306a36Sopenharmony_ci		dev->touch_cap_dev.ctrl_handler = hdl_tch_cap;
200762306a36Sopenharmony_ci	}
200862306a36Sopenharmony_ci	return 0;
200962306a36Sopenharmony_ci}
201062306a36Sopenharmony_ci
201162306a36Sopenharmony_civoid vivid_free_controls(struct vivid_dev *dev)
201262306a36Sopenharmony_ci{
201362306a36Sopenharmony_ci	v4l2_ctrl_handler_free(&dev->ctrl_hdl_vid_cap);
201462306a36Sopenharmony_ci	v4l2_ctrl_handler_free(&dev->ctrl_hdl_vid_out);
201562306a36Sopenharmony_ci	v4l2_ctrl_handler_free(&dev->ctrl_hdl_vbi_cap);
201662306a36Sopenharmony_ci	v4l2_ctrl_handler_free(&dev->ctrl_hdl_vbi_out);
201762306a36Sopenharmony_ci	v4l2_ctrl_handler_free(&dev->ctrl_hdl_radio_rx);
201862306a36Sopenharmony_ci	v4l2_ctrl_handler_free(&dev->ctrl_hdl_radio_tx);
201962306a36Sopenharmony_ci	v4l2_ctrl_handler_free(&dev->ctrl_hdl_sdr_cap);
202062306a36Sopenharmony_ci	v4l2_ctrl_handler_free(&dev->ctrl_hdl_user_gen);
202162306a36Sopenharmony_ci	v4l2_ctrl_handler_free(&dev->ctrl_hdl_user_vid);
202262306a36Sopenharmony_ci	v4l2_ctrl_handler_free(&dev->ctrl_hdl_user_aud);
202362306a36Sopenharmony_ci	v4l2_ctrl_handler_free(&dev->ctrl_hdl_streaming);
202462306a36Sopenharmony_ci	v4l2_ctrl_handler_free(&dev->ctrl_hdl_sdtv_cap);
202562306a36Sopenharmony_ci	v4l2_ctrl_handler_free(&dev->ctrl_hdl_loop_cap);
202662306a36Sopenharmony_ci	v4l2_ctrl_handler_free(&dev->ctrl_hdl_fb);
202762306a36Sopenharmony_ci	v4l2_ctrl_handler_free(&dev->ctrl_hdl_meta_cap);
202862306a36Sopenharmony_ci	v4l2_ctrl_handler_free(&dev->ctrl_hdl_meta_out);
202962306a36Sopenharmony_ci	v4l2_ctrl_handler_free(&dev->ctrl_hdl_touch_cap);
203062306a36Sopenharmony_ci}
2031