18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci    V4L2 controls framework implementation.
48c2ecf20Sopenharmony_ci
58c2ecf20Sopenharmony_ci    Copyright (C) 2010  Hans Verkuil <hverkuil@xs4all.nl>
68c2ecf20Sopenharmony_ci
78c2ecf20Sopenharmony_ci */
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ci#define pr_fmt(fmt) "v4l2-ctrls: " fmt
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci#include <linux/ctype.h>
128c2ecf20Sopenharmony_ci#include <linux/export.h>
138c2ecf20Sopenharmony_ci#include <linux/mm.h>
148c2ecf20Sopenharmony_ci#include <linux/slab.h>
158c2ecf20Sopenharmony_ci#include <media/v4l2-ctrls.h>
168c2ecf20Sopenharmony_ci#include <media/v4l2-dev.h>
178c2ecf20Sopenharmony_ci#include <media/v4l2-device.h>
188c2ecf20Sopenharmony_ci#include <media/v4l2-event.h>
198c2ecf20Sopenharmony_ci#include <media/v4l2-fwnode.h>
208c2ecf20Sopenharmony_ci#include <media/v4l2-ioctl.h>
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_ci#define dprintk(vdev, fmt, arg...) do {					\
238c2ecf20Sopenharmony_ci	if (!WARN_ON(!(vdev)) && ((vdev)->dev_debug & V4L2_DEV_DEBUG_CTRL)) \
248c2ecf20Sopenharmony_ci		printk(KERN_DEBUG pr_fmt("%s: %s: " fmt),		\
258c2ecf20Sopenharmony_ci		       __func__, video_device_node_name(vdev), ##arg);	\
268c2ecf20Sopenharmony_ci} while (0)
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_ci#define has_op(master, op) \
298c2ecf20Sopenharmony_ci	(master->ops && master->ops->op)
308c2ecf20Sopenharmony_ci#define call_op(master, op) \
318c2ecf20Sopenharmony_ci	(has_op(master, op) ? master->ops->op(master) : 0)
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_cistatic const union v4l2_ctrl_ptr ptr_null;
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci/* Internal temporary helper struct, one for each v4l2_ext_control */
368c2ecf20Sopenharmony_cistruct v4l2_ctrl_helper {
378c2ecf20Sopenharmony_ci	/* Pointer to the control reference of the master control */
388c2ecf20Sopenharmony_ci	struct v4l2_ctrl_ref *mref;
398c2ecf20Sopenharmony_ci	/* The control ref corresponding to the v4l2_ext_control ID field. */
408c2ecf20Sopenharmony_ci	struct v4l2_ctrl_ref *ref;
418c2ecf20Sopenharmony_ci	/* v4l2_ext_control index of the next control belonging to the
428c2ecf20Sopenharmony_ci	   same cluster, or 0 if there isn't any. */
438c2ecf20Sopenharmony_ci	u32 next;
448c2ecf20Sopenharmony_ci};
458c2ecf20Sopenharmony_ci
468c2ecf20Sopenharmony_ci/* Small helper function to determine if the autocluster is set to manual
478c2ecf20Sopenharmony_ci   mode. */
488c2ecf20Sopenharmony_cistatic bool is_cur_manual(const struct v4l2_ctrl *master)
498c2ecf20Sopenharmony_ci{
508c2ecf20Sopenharmony_ci	return master->is_auto && master->cur.val == master->manual_mode_value;
518c2ecf20Sopenharmony_ci}
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_ci/* Same as above, but this checks the against the new value instead of the
548c2ecf20Sopenharmony_ci   current value. */
558c2ecf20Sopenharmony_cistatic bool is_new_manual(const struct v4l2_ctrl *master)
568c2ecf20Sopenharmony_ci{
578c2ecf20Sopenharmony_ci	return master->is_auto && master->val == master->manual_mode_value;
588c2ecf20Sopenharmony_ci}
598c2ecf20Sopenharmony_ci
608c2ecf20Sopenharmony_ci/* Returns NULL or a character pointer array containing the menu for
618c2ecf20Sopenharmony_ci   the given control ID. The pointer array ends with a NULL pointer.
628c2ecf20Sopenharmony_ci   An empty string signifies a menu entry that is invalid. This allows
638c2ecf20Sopenharmony_ci   drivers to disable certain options if it is not supported. */
648c2ecf20Sopenharmony_ciconst char * const *v4l2_ctrl_get_menu(u32 id)
658c2ecf20Sopenharmony_ci{
668c2ecf20Sopenharmony_ci	static const char * const mpeg_audio_sampling_freq[] = {
678c2ecf20Sopenharmony_ci		"44.1 kHz",
688c2ecf20Sopenharmony_ci		"48 kHz",
698c2ecf20Sopenharmony_ci		"32 kHz",
708c2ecf20Sopenharmony_ci		NULL
718c2ecf20Sopenharmony_ci	};
728c2ecf20Sopenharmony_ci	static const char * const mpeg_audio_encoding[] = {
738c2ecf20Sopenharmony_ci		"MPEG-1/2 Layer I",
748c2ecf20Sopenharmony_ci		"MPEG-1/2 Layer II",
758c2ecf20Sopenharmony_ci		"MPEG-1/2 Layer III",
768c2ecf20Sopenharmony_ci		"MPEG-2/4 AAC",
778c2ecf20Sopenharmony_ci		"AC-3",
788c2ecf20Sopenharmony_ci		NULL
798c2ecf20Sopenharmony_ci	};
808c2ecf20Sopenharmony_ci	static const char * const mpeg_audio_l1_bitrate[] = {
818c2ecf20Sopenharmony_ci		"32 kbps",
828c2ecf20Sopenharmony_ci		"64 kbps",
838c2ecf20Sopenharmony_ci		"96 kbps",
848c2ecf20Sopenharmony_ci		"128 kbps",
858c2ecf20Sopenharmony_ci		"160 kbps",
868c2ecf20Sopenharmony_ci		"192 kbps",
878c2ecf20Sopenharmony_ci		"224 kbps",
888c2ecf20Sopenharmony_ci		"256 kbps",
898c2ecf20Sopenharmony_ci		"288 kbps",
908c2ecf20Sopenharmony_ci		"320 kbps",
918c2ecf20Sopenharmony_ci		"352 kbps",
928c2ecf20Sopenharmony_ci		"384 kbps",
938c2ecf20Sopenharmony_ci		"416 kbps",
948c2ecf20Sopenharmony_ci		"448 kbps",
958c2ecf20Sopenharmony_ci		NULL
968c2ecf20Sopenharmony_ci	};
978c2ecf20Sopenharmony_ci	static const char * const mpeg_audio_l2_bitrate[] = {
988c2ecf20Sopenharmony_ci		"32 kbps",
998c2ecf20Sopenharmony_ci		"48 kbps",
1008c2ecf20Sopenharmony_ci		"56 kbps",
1018c2ecf20Sopenharmony_ci		"64 kbps",
1028c2ecf20Sopenharmony_ci		"80 kbps",
1038c2ecf20Sopenharmony_ci		"96 kbps",
1048c2ecf20Sopenharmony_ci		"112 kbps",
1058c2ecf20Sopenharmony_ci		"128 kbps",
1068c2ecf20Sopenharmony_ci		"160 kbps",
1078c2ecf20Sopenharmony_ci		"192 kbps",
1088c2ecf20Sopenharmony_ci		"224 kbps",
1098c2ecf20Sopenharmony_ci		"256 kbps",
1108c2ecf20Sopenharmony_ci		"320 kbps",
1118c2ecf20Sopenharmony_ci		"384 kbps",
1128c2ecf20Sopenharmony_ci		NULL
1138c2ecf20Sopenharmony_ci	};
1148c2ecf20Sopenharmony_ci	static const char * const mpeg_audio_l3_bitrate[] = {
1158c2ecf20Sopenharmony_ci		"32 kbps",
1168c2ecf20Sopenharmony_ci		"40 kbps",
1178c2ecf20Sopenharmony_ci		"48 kbps",
1188c2ecf20Sopenharmony_ci		"56 kbps",
1198c2ecf20Sopenharmony_ci		"64 kbps",
1208c2ecf20Sopenharmony_ci		"80 kbps",
1218c2ecf20Sopenharmony_ci		"96 kbps",
1228c2ecf20Sopenharmony_ci		"112 kbps",
1238c2ecf20Sopenharmony_ci		"128 kbps",
1248c2ecf20Sopenharmony_ci		"160 kbps",
1258c2ecf20Sopenharmony_ci		"192 kbps",
1268c2ecf20Sopenharmony_ci		"224 kbps",
1278c2ecf20Sopenharmony_ci		"256 kbps",
1288c2ecf20Sopenharmony_ci		"320 kbps",
1298c2ecf20Sopenharmony_ci		NULL
1308c2ecf20Sopenharmony_ci	};
1318c2ecf20Sopenharmony_ci	static const char * const mpeg_audio_ac3_bitrate[] = {
1328c2ecf20Sopenharmony_ci		"32 kbps",
1338c2ecf20Sopenharmony_ci		"40 kbps",
1348c2ecf20Sopenharmony_ci		"48 kbps",
1358c2ecf20Sopenharmony_ci		"56 kbps",
1368c2ecf20Sopenharmony_ci		"64 kbps",
1378c2ecf20Sopenharmony_ci		"80 kbps",
1388c2ecf20Sopenharmony_ci		"96 kbps",
1398c2ecf20Sopenharmony_ci		"112 kbps",
1408c2ecf20Sopenharmony_ci		"128 kbps",
1418c2ecf20Sopenharmony_ci		"160 kbps",
1428c2ecf20Sopenharmony_ci		"192 kbps",
1438c2ecf20Sopenharmony_ci		"224 kbps",
1448c2ecf20Sopenharmony_ci		"256 kbps",
1458c2ecf20Sopenharmony_ci		"320 kbps",
1468c2ecf20Sopenharmony_ci		"384 kbps",
1478c2ecf20Sopenharmony_ci		"448 kbps",
1488c2ecf20Sopenharmony_ci		"512 kbps",
1498c2ecf20Sopenharmony_ci		"576 kbps",
1508c2ecf20Sopenharmony_ci		"640 kbps",
1518c2ecf20Sopenharmony_ci		NULL
1528c2ecf20Sopenharmony_ci	};
1538c2ecf20Sopenharmony_ci	static const char * const mpeg_audio_mode[] = {
1548c2ecf20Sopenharmony_ci		"Stereo",
1558c2ecf20Sopenharmony_ci		"Joint Stereo",
1568c2ecf20Sopenharmony_ci		"Dual",
1578c2ecf20Sopenharmony_ci		"Mono",
1588c2ecf20Sopenharmony_ci		NULL
1598c2ecf20Sopenharmony_ci	};
1608c2ecf20Sopenharmony_ci	static const char * const mpeg_audio_mode_extension[] = {
1618c2ecf20Sopenharmony_ci		"Bound 4",
1628c2ecf20Sopenharmony_ci		"Bound 8",
1638c2ecf20Sopenharmony_ci		"Bound 12",
1648c2ecf20Sopenharmony_ci		"Bound 16",
1658c2ecf20Sopenharmony_ci		NULL
1668c2ecf20Sopenharmony_ci	};
1678c2ecf20Sopenharmony_ci	static const char * const mpeg_audio_emphasis[] = {
1688c2ecf20Sopenharmony_ci		"No Emphasis",
1698c2ecf20Sopenharmony_ci		"50/15 us",
1708c2ecf20Sopenharmony_ci		"CCITT J17",
1718c2ecf20Sopenharmony_ci		NULL
1728c2ecf20Sopenharmony_ci	};
1738c2ecf20Sopenharmony_ci	static const char * const mpeg_audio_crc[] = {
1748c2ecf20Sopenharmony_ci		"No CRC",
1758c2ecf20Sopenharmony_ci		"16-bit CRC",
1768c2ecf20Sopenharmony_ci		NULL
1778c2ecf20Sopenharmony_ci	};
1788c2ecf20Sopenharmony_ci	static const char * const mpeg_audio_dec_playback[] = {
1798c2ecf20Sopenharmony_ci		"Auto",
1808c2ecf20Sopenharmony_ci		"Stereo",
1818c2ecf20Sopenharmony_ci		"Left",
1828c2ecf20Sopenharmony_ci		"Right",
1838c2ecf20Sopenharmony_ci		"Mono",
1848c2ecf20Sopenharmony_ci		"Swapped Stereo",
1858c2ecf20Sopenharmony_ci		NULL
1868c2ecf20Sopenharmony_ci	};
1878c2ecf20Sopenharmony_ci	static const char * const mpeg_video_encoding[] = {
1888c2ecf20Sopenharmony_ci		"MPEG-1",
1898c2ecf20Sopenharmony_ci		"MPEG-2",
1908c2ecf20Sopenharmony_ci		"MPEG-4 AVC",
1918c2ecf20Sopenharmony_ci		NULL
1928c2ecf20Sopenharmony_ci	};
1938c2ecf20Sopenharmony_ci	static const char * const mpeg_video_aspect[] = {
1948c2ecf20Sopenharmony_ci		"1x1",
1958c2ecf20Sopenharmony_ci		"4x3",
1968c2ecf20Sopenharmony_ci		"16x9",
1978c2ecf20Sopenharmony_ci		"2.21x1",
1988c2ecf20Sopenharmony_ci		NULL
1998c2ecf20Sopenharmony_ci	};
2008c2ecf20Sopenharmony_ci	static const char * const mpeg_video_bitrate_mode[] = {
2018c2ecf20Sopenharmony_ci		"Variable Bitrate",
2028c2ecf20Sopenharmony_ci		"Constant Bitrate",
2038c2ecf20Sopenharmony_ci		"Constant Quality",
2048c2ecf20Sopenharmony_ci		NULL
2058c2ecf20Sopenharmony_ci	};
2068c2ecf20Sopenharmony_ci	static const char * const mpeg_stream_type[] = {
2078c2ecf20Sopenharmony_ci		"MPEG-2 Program Stream",
2088c2ecf20Sopenharmony_ci		"MPEG-2 Transport Stream",
2098c2ecf20Sopenharmony_ci		"MPEG-1 System Stream",
2108c2ecf20Sopenharmony_ci		"MPEG-2 DVD-compatible Stream",
2118c2ecf20Sopenharmony_ci		"MPEG-1 VCD-compatible Stream",
2128c2ecf20Sopenharmony_ci		"MPEG-2 SVCD-compatible Stream",
2138c2ecf20Sopenharmony_ci		NULL
2148c2ecf20Sopenharmony_ci	};
2158c2ecf20Sopenharmony_ci	static const char * const mpeg_stream_vbi_fmt[] = {
2168c2ecf20Sopenharmony_ci		"No VBI",
2178c2ecf20Sopenharmony_ci		"Private Packet, IVTV Format",
2188c2ecf20Sopenharmony_ci		NULL
2198c2ecf20Sopenharmony_ci	};
2208c2ecf20Sopenharmony_ci	static const char * const camera_power_line_frequency[] = {
2218c2ecf20Sopenharmony_ci		"Disabled",
2228c2ecf20Sopenharmony_ci		"50 Hz",
2238c2ecf20Sopenharmony_ci		"60 Hz",
2248c2ecf20Sopenharmony_ci		"Auto",
2258c2ecf20Sopenharmony_ci		NULL
2268c2ecf20Sopenharmony_ci	};
2278c2ecf20Sopenharmony_ci	static const char * const camera_exposure_auto[] = {
2288c2ecf20Sopenharmony_ci		"Auto Mode",
2298c2ecf20Sopenharmony_ci		"Manual Mode",
2308c2ecf20Sopenharmony_ci		"Shutter Priority Mode",
2318c2ecf20Sopenharmony_ci		"Aperture Priority Mode",
2328c2ecf20Sopenharmony_ci		NULL
2338c2ecf20Sopenharmony_ci	};
2348c2ecf20Sopenharmony_ci	static const char * const camera_exposure_metering[] = {
2358c2ecf20Sopenharmony_ci		"Average",
2368c2ecf20Sopenharmony_ci		"Center Weighted",
2378c2ecf20Sopenharmony_ci		"Spot",
2388c2ecf20Sopenharmony_ci		"Matrix",
2398c2ecf20Sopenharmony_ci		NULL
2408c2ecf20Sopenharmony_ci	};
2418c2ecf20Sopenharmony_ci	static const char * const camera_auto_focus_range[] = {
2428c2ecf20Sopenharmony_ci		"Auto",
2438c2ecf20Sopenharmony_ci		"Normal",
2448c2ecf20Sopenharmony_ci		"Macro",
2458c2ecf20Sopenharmony_ci		"Infinity",
2468c2ecf20Sopenharmony_ci		NULL
2478c2ecf20Sopenharmony_ci	};
2488c2ecf20Sopenharmony_ci	static const char * const colorfx[] = {
2498c2ecf20Sopenharmony_ci		"None",
2508c2ecf20Sopenharmony_ci		"Black & White",
2518c2ecf20Sopenharmony_ci		"Sepia",
2528c2ecf20Sopenharmony_ci		"Negative",
2538c2ecf20Sopenharmony_ci		"Emboss",
2548c2ecf20Sopenharmony_ci		"Sketch",
2558c2ecf20Sopenharmony_ci		"Sky Blue",
2568c2ecf20Sopenharmony_ci		"Grass Green",
2578c2ecf20Sopenharmony_ci		"Skin Whiten",
2588c2ecf20Sopenharmony_ci		"Vivid",
2598c2ecf20Sopenharmony_ci		"Aqua",
2608c2ecf20Sopenharmony_ci		"Art Freeze",
2618c2ecf20Sopenharmony_ci		"Silhouette",
2628c2ecf20Sopenharmony_ci		"Solarization",
2638c2ecf20Sopenharmony_ci		"Antique",
2648c2ecf20Sopenharmony_ci		"Set Cb/Cr",
2658c2ecf20Sopenharmony_ci		NULL
2668c2ecf20Sopenharmony_ci	};
2678c2ecf20Sopenharmony_ci	static const char * const auto_n_preset_white_balance[] = {
2688c2ecf20Sopenharmony_ci		"Manual",
2698c2ecf20Sopenharmony_ci		"Auto",
2708c2ecf20Sopenharmony_ci		"Incandescent",
2718c2ecf20Sopenharmony_ci		"Fluorescent",
2728c2ecf20Sopenharmony_ci		"Fluorescent H",
2738c2ecf20Sopenharmony_ci		"Horizon",
2748c2ecf20Sopenharmony_ci		"Daylight",
2758c2ecf20Sopenharmony_ci		"Flash",
2768c2ecf20Sopenharmony_ci		"Cloudy",
2778c2ecf20Sopenharmony_ci		"Shade",
2788c2ecf20Sopenharmony_ci		NULL,
2798c2ecf20Sopenharmony_ci	};
2808c2ecf20Sopenharmony_ci	static const char * const camera_iso_sensitivity_auto[] = {
2818c2ecf20Sopenharmony_ci		"Manual",
2828c2ecf20Sopenharmony_ci		"Auto",
2838c2ecf20Sopenharmony_ci		NULL
2848c2ecf20Sopenharmony_ci	};
2858c2ecf20Sopenharmony_ci	static const char * const scene_mode[] = {
2868c2ecf20Sopenharmony_ci		"None",
2878c2ecf20Sopenharmony_ci		"Backlight",
2888c2ecf20Sopenharmony_ci		"Beach/Snow",
2898c2ecf20Sopenharmony_ci		"Candle Light",
2908c2ecf20Sopenharmony_ci		"Dusk/Dawn",
2918c2ecf20Sopenharmony_ci		"Fall Colors",
2928c2ecf20Sopenharmony_ci		"Fireworks",
2938c2ecf20Sopenharmony_ci		"Landscape",
2948c2ecf20Sopenharmony_ci		"Night",
2958c2ecf20Sopenharmony_ci		"Party/Indoor",
2968c2ecf20Sopenharmony_ci		"Portrait",
2978c2ecf20Sopenharmony_ci		"Sports",
2988c2ecf20Sopenharmony_ci		"Sunset",
2998c2ecf20Sopenharmony_ci		"Text",
3008c2ecf20Sopenharmony_ci		NULL
3018c2ecf20Sopenharmony_ci	};
3028c2ecf20Sopenharmony_ci	static const char * const tune_emphasis[] = {
3038c2ecf20Sopenharmony_ci		"None",
3048c2ecf20Sopenharmony_ci		"50 Microseconds",
3058c2ecf20Sopenharmony_ci		"75 Microseconds",
3068c2ecf20Sopenharmony_ci		NULL,
3078c2ecf20Sopenharmony_ci	};
3088c2ecf20Sopenharmony_ci	static const char * const header_mode[] = {
3098c2ecf20Sopenharmony_ci		"Separate Buffer",
3108c2ecf20Sopenharmony_ci		"Joined With 1st Frame",
3118c2ecf20Sopenharmony_ci		NULL,
3128c2ecf20Sopenharmony_ci	};
3138c2ecf20Sopenharmony_ci	static const char * const multi_slice[] = {
3148c2ecf20Sopenharmony_ci		"Single",
3158c2ecf20Sopenharmony_ci		"Max Macroblocks",
3168c2ecf20Sopenharmony_ci		"Max Bytes",
3178c2ecf20Sopenharmony_ci		NULL,
3188c2ecf20Sopenharmony_ci	};
3198c2ecf20Sopenharmony_ci	static const char * const entropy_mode[] = {
3208c2ecf20Sopenharmony_ci		"CAVLC",
3218c2ecf20Sopenharmony_ci		"CABAC",
3228c2ecf20Sopenharmony_ci		NULL,
3238c2ecf20Sopenharmony_ci	};
3248c2ecf20Sopenharmony_ci	static const char * const mpeg_h264_level[] = {
3258c2ecf20Sopenharmony_ci		"1",
3268c2ecf20Sopenharmony_ci		"1b",
3278c2ecf20Sopenharmony_ci		"1.1",
3288c2ecf20Sopenharmony_ci		"1.2",
3298c2ecf20Sopenharmony_ci		"1.3",
3308c2ecf20Sopenharmony_ci		"2",
3318c2ecf20Sopenharmony_ci		"2.1",
3328c2ecf20Sopenharmony_ci		"2.2",
3338c2ecf20Sopenharmony_ci		"3",
3348c2ecf20Sopenharmony_ci		"3.1",
3358c2ecf20Sopenharmony_ci		"3.2",
3368c2ecf20Sopenharmony_ci		"4",
3378c2ecf20Sopenharmony_ci		"4.1",
3388c2ecf20Sopenharmony_ci		"4.2",
3398c2ecf20Sopenharmony_ci		"5",
3408c2ecf20Sopenharmony_ci		"5.1",
3418c2ecf20Sopenharmony_ci		"5.2",
3428c2ecf20Sopenharmony_ci		"6.0",
3438c2ecf20Sopenharmony_ci		"6.1",
3448c2ecf20Sopenharmony_ci		"6.2",
3458c2ecf20Sopenharmony_ci		NULL,
3468c2ecf20Sopenharmony_ci	};
3478c2ecf20Sopenharmony_ci	static const char * const h264_loop_filter[] = {
3488c2ecf20Sopenharmony_ci		"Enabled",
3498c2ecf20Sopenharmony_ci		"Disabled",
3508c2ecf20Sopenharmony_ci		"Disabled at Slice Boundary",
3518c2ecf20Sopenharmony_ci		NULL,
3528c2ecf20Sopenharmony_ci	};
3538c2ecf20Sopenharmony_ci	static const char * const h264_profile[] = {
3548c2ecf20Sopenharmony_ci		"Baseline",
3558c2ecf20Sopenharmony_ci		"Constrained Baseline",
3568c2ecf20Sopenharmony_ci		"Main",
3578c2ecf20Sopenharmony_ci		"Extended",
3588c2ecf20Sopenharmony_ci		"High",
3598c2ecf20Sopenharmony_ci		"High 10",
3608c2ecf20Sopenharmony_ci		"High 422",
3618c2ecf20Sopenharmony_ci		"High 444 Predictive",
3628c2ecf20Sopenharmony_ci		"High 10 Intra",
3638c2ecf20Sopenharmony_ci		"High 422 Intra",
3648c2ecf20Sopenharmony_ci		"High 444 Intra",
3658c2ecf20Sopenharmony_ci		"CAVLC 444 Intra",
3668c2ecf20Sopenharmony_ci		"Scalable Baseline",
3678c2ecf20Sopenharmony_ci		"Scalable High",
3688c2ecf20Sopenharmony_ci		"Scalable High Intra",
3698c2ecf20Sopenharmony_ci		"Stereo High",
3708c2ecf20Sopenharmony_ci		"Multiview High",
3718c2ecf20Sopenharmony_ci		"Constrained High",
3728c2ecf20Sopenharmony_ci		NULL,
3738c2ecf20Sopenharmony_ci	};
3748c2ecf20Sopenharmony_ci	static const char * const vui_sar_idc[] = {
3758c2ecf20Sopenharmony_ci		"Unspecified",
3768c2ecf20Sopenharmony_ci		"1:1",
3778c2ecf20Sopenharmony_ci		"12:11",
3788c2ecf20Sopenharmony_ci		"10:11",
3798c2ecf20Sopenharmony_ci		"16:11",
3808c2ecf20Sopenharmony_ci		"40:33",
3818c2ecf20Sopenharmony_ci		"24:11",
3828c2ecf20Sopenharmony_ci		"20:11",
3838c2ecf20Sopenharmony_ci		"32:11",
3848c2ecf20Sopenharmony_ci		"80:33",
3858c2ecf20Sopenharmony_ci		"18:11",
3868c2ecf20Sopenharmony_ci		"15:11",
3878c2ecf20Sopenharmony_ci		"64:33",
3888c2ecf20Sopenharmony_ci		"160:99",
3898c2ecf20Sopenharmony_ci		"4:3",
3908c2ecf20Sopenharmony_ci		"3:2",
3918c2ecf20Sopenharmony_ci		"2:1",
3928c2ecf20Sopenharmony_ci		"Extended SAR",
3938c2ecf20Sopenharmony_ci		NULL,
3948c2ecf20Sopenharmony_ci	};
3958c2ecf20Sopenharmony_ci	static const char * const h264_fp_arrangement_type[] = {
3968c2ecf20Sopenharmony_ci		"Checkerboard",
3978c2ecf20Sopenharmony_ci		"Column",
3988c2ecf20Sopenharmony_ci		"Row",
3998c2ecf20Sopenharmony_ci		"Side by Side",
4008c2ecf20Sopenharmony_ci		"Top Bottom",
4018c2ecf20Sopenharmony_ci		"Temporal",
4028c2ecf20Sopenharmony_ci		NULL,
4038c2ecf20Sopenharmony_ci	};
4048c2ecf20Sopenharmony_ci	static const char * const h264_fmo_map_type[] = {
4058c2ecf20Sopenharmony_ci		"Interleaved Slices",
4068c2ecf20Sopenharmony_ci		"Scattered Slices",
4078c2ecf20Sopenharmony_ci		"Foreground with Leftover",
4088c2ecf20Sopenharmony_ci		"Box Out",
4098c2ecf20Sopenharmony_ci		"Raster Scan",
4108c2ecf20Sopenharmony_ci		"Wipe Scan",
4118c2ecf20Sopenharmony_ci		"Explicit",
4128c2ecf20Sopenharmony_ci		NULL,
4138c2ecf20Sopenharmony_ci	};
4148c2ecf20Sopenharmony_ci	static const char * const h264_decode_mode[] = {
4158c2ecf20Sopenharmony_ci		"Slice-Based",
4168c2ecf20Sopenharmony_ci		"Frame-Based",
4178c2ecf20Sopenharmony_ci		NULL,
4188c2ecf20Sopenharmony_ci	};
4198c2ecf20Sopenharmony_ci	static const char * const h264_start_code[] = {
4208c2ecf20Sopenharmony_ci		"No Start Code",
4218c2ecf20Sopenharmony_ci		"Annex B Start Code",
4228c2ecf20Sopenharmony_ci		NULL,
4238c2ecf20Sopenharmony_ci	};
4248c2ecf20Sopenharmony_ci	static const char * const mpeg_mpeg2_level[] = {
4258c2ecf20Sopenharmony_ci		"Low",
4268c2ecf20Sopenharmony_ci		"Main",
4278c2ecf20Sopenharmony_ci		"High 1440",
4288c2ecf20Sopenharmony_ci		"High",
4298c2ecf20Sopenharmony_ci		NULL,
4308c2ecf20Sopenharmony_ci	};
4318c2ecf20Sopenharmony_ci	static const char * const mpeg2_profile[] = {
4328c2ecf20Sopenharmony_ci		"Simple",
4338c2ecf20Sopenharmony_ci		"Main",
4348c2ecf20Sopenharmony_ci		"SNR Scalable",
4358c2ecf20Sopenharmony_ci		"Spatially Scalable",
4368c2ecf20Sopenharmony_ci		"High",
4378c2ecf20Sopenharmony_ci		NULL,
4388c2ecf20Sopenharmony_ci	};
4398c2ecf20Sopenharmony_ci	static const char * const mpeg_mpeg4_level[] = {
4408c2ecf20Sopenharmony_ci		"0",
4418c2ecf20Sopenharmony_ci		"0b",
4428c2ecf20Sopenharmony_ci		"1",
4438c2ecf20Sopenharmony_ci		"2",
4448c2ecf20Sopenharmony_ci		"3",
4458c2ecf20Sopenharmony_ci		"3b",
4468c2ecf20Sopenharmony_ci		"4",
4478c2ecf20Sopenharmony_ci		"5",
4488c2ecf20Sopenharmony_ci		NULL,
4498c2ecf20Sopenharmony_ci	};
4508c2ecf20Sopenharmony_ci	static const char * const mpeg4_profile[] = {
4518c2ecf20Sopenharmony_ci		"Simple",
4528c2ecf20Sopenharmony_ci		"Advanced Simple",
4538c2ecf20Sopenharmony_ci		"Core",
4548c2ecf20Sopenharmony_ci		"Simple Scalable",
4558c2ecf20Sopenharmony_ci		"Advanced Coding Efficiency",
4568c2ecf20Sopenharmony_ci		NULL,
4578c2ecf20Sopenharmony_ci	};
4588c2ecf20Sopenharmony_ci
4598c2ecf20Sopenharmony_ci	static const char * const vpx_golden_frame_sel[] = {
4608c2ecf20Sopenharmony_ci		"Use Previous Frame",
4618c2ecf20Sopenharmony_ci		"Use Previous Specific Frame",
4628c2ecf20Sopenharmony_ci		NULL,
4638c2ecf20Sopenharmony_ci	};
4648c2ecf20Sopenharmony_ci	static const char * const vp8_profile[] = {
4658c2ecf20Sopenharmony_ci		"0",
4668c2ecf20Sopenharmony_ci		"1",
4678c2ecf20Sopenharmony_ci		"2",
4688c2ecf20Sopenharmony_ci		"3",
4698c2ecf20Sopenharmony_ci		NULL,
4708c2ecf20Sopenharmony_ci	};
4718c2ecf20Sopenharmony_ci	static const char * const vp9_profile[] = {
4728c2ecf20Sopenharmony_ci		"0",
4738c2ecf20Sopenharmony_ci		"1",
4748c2ecf20Sopenharmony_ci		"2",
4758c2ecf20Sopenharmony_ci		"3",
4768c2ecf20Sopenharmony_ci		NULL,
4778c2ecf20Sopenharmony_ci	};
4788c2ecf20Sopenharmony_ci	static const char * const vp9_level[] = {
4798c2ecf20Sopenharmony_ci		"1",
4808c2ecf20Sopenharmony_ci		"1.1",
4818c2ecf20Sopenharmony_ci		"2",
4828c2ecf20Sopenharmony_ci		"2.1",
4838c2ecf20Sopenharmony_ci		"3",
4848c2ecf20Sopenharmony_ci		"3.1",
4858c2ecf20Sopenharmony_ci		"4",
4868c2ecf20Sopenharmony_ci		"4.1",
4878c2ecf20Sopenharmony_ci		"5",
4888c2ecf20Sopenharmony_ci		"5.1",
4898c2ecf20Sopenharmony_ci		"5.2",
4908c2ecf20Sopenharmony_ci		"6",
4918c2ecf20Sopenharmony_ci		"6.1",
4928c2ecf20Sopenharmony_ci		"6.2",
4938c2ecf20Sopenharmony_ci		NULL,
4948c2ecf20Sopenharmony_ci	};
4958c2ecf20Sopenharmony_ci
4968c2ecf20Sopenharmony_ci	static const char * const flash_led_mode[] = {
4978c2ecf20Sopenharmony_ci		"Off",
4988c2ecf20Sopenharmony_ci		"Flash",
4998c2ecf20Sopenharmony_ci		"Torch",
5008c2ecf20Sopenharmony_ci		NULL,
5018c2ecf20Sopenharmony_ci	};
5028c2ecf20Sopenharmony_ci	static const char * const flash_strobe_source[] = {
5038c2ecf20Sopenharmony_ci		"Software",
5048c2ecf20Sopenharmony_ci		"External",
5058c2ecf20Sopenharmony_ci		NULL,
5068c2ecf20Sopenharmony_ci	};
5078c2ecf20Sopenharmony_ci
5088c2ecf20Sopenharmony_ci	static const char * const jpeg_chroma_subsampling[] = {
5098c2ecf20Sopenharmony_ci		"4:4:4",
5108c2ecf20Sopenharmony_ci		"4:2:2",
5118c2ecf20Sopenharmony_ci		"4:2:0",
5128c2ecf20Sopenharmony_ci		"4:1:1",
5138c2ecf20Sopenharmony_ci		"4:1:0",
5148c2ecf20Sopenharmony_ci		"Gray",
5158c2ecf20Sopenharmony_ci		NULL,
5168c2ecf20Sopenharmony_ci	};
5178c2ecf20Sopenharmony_ci	static const char * const dv_tx_mode[] = {
5188c2ecf20Sopenharmony_ci		"DVI-D",
5198c2ecf20Sopenharmony_ci		"HDMI",
5208c2ecf20Sopenharmony_ci		NULL,
5218c2ecf20Sopenharmony_ci	};
5228c2ecf20Sopenharmony_ci	static const char * const dv_rgb_range[] = {
5238c2ecf20Sopenharmony_ci		"Automatic",
5248c2ecf20Sopenharmony_ci		"RGB Limited Range (16-235)",
5258c2ecf20Sopenharmony_ci		"RGB Full Range (0-255)",
5268c2ecf20Sopenharmony_ci		NULL,
5278c2ecf20Sopenharmony_ci	};
5288c2ecf20Sopenharmony_ci	static const char * const dv_it_content_type[] = {
5298c2ecf20Sopenharmony_ci		"Graphics",
5308c2ecf20Sopenharmony_ci		"Photo",
5318c2ecf20Sopenharmony_ci		"Cinema",
5328c2ecf20Sopenharmony_ci		"Game",
5338c2ecf20Sopenharmony_ci		"No IT Content",
5348c2ecf20Sopenharmony_ci		NULL,
5358c2ecf20Sopenharmony_ci	};
5368c2ecf20Sopenharmony_ci	static const char * const detect_md_mode[] = {
5378c2ecf20Sopenharmony_ci		"Disabled",
5388c2ecf20Sopenharmony_ci		"Global",
5398c2ecf20Sopenharmony_ci		"Threshold Grid",
5408c2ecf20Sopenharmony_ci		"Region Grid",
5418c2ecf20Sopenharmony_ci		NULL,
5428c2ecf20Sopenharmony_ci	};
5438c2ecf20Sopenharmony_ci
5448c2ecf20Sopenharmony_ci	static const char * const hevc_profile[] = {
5458c2ecf20Sopenharmony_ci		"Main",
5468c2ecf20Sopenharmony_ci		"Main Still Picture",
5478c2ecf20Sopenharmony_ci		"Main 10",
5488c2ecf20Sopenharmony_ci		NULL,
5498c2ecf20Sopenharmony_ci	};
5508c2ecf20Sopenharmony_ci	static const char * const hevc_level[] = {
5518c2ecf20Sopenharmony_ci		"1",
5528c2ecf20Sopenharmony_ci		"2",
5538c2ecf20Sopenharmony_ci		"2.1",
5548c2ecf20Sopenharmony_ci		"3",
5558c2ecf20Sopenharmony_ci		"3.1",
5568c2ecf20Sopenharmony_ci		"4",
5578c2ecf20Sopenharmony_ci		"4.1",
5588c2ecf20Sopenharmony_ci		"5",
5598c2ecf20Sopenharmony_ci		"5.1",
5608c2ecf20Sopenharmony_ci		"5.2",
5618c2ecf20Sopenharmony_ci		"6",
5628c2ecf20Sopenharmony_ci		"6.1",
5638c2ecf20Sopenharmony_ci		"6.2",
5648c2ecf20Sopenharmony_ci		NULL,
5658c2ecf20Sopenharmony_ci	};
5668c2ecf20Sopenharmony_ci	static const char * const hevc_hierarchial_coding_type[] = {
5678c2ecf20Sopenharmony_ci		"B",
5688c2ecf20Sopenharmony_ci		"P",
5698c2ecf20Sopenharmony_ci		NULL,
5708c2ecf20Sopenharmony_ci	};
5718c2ecf20Sopenharmony_ci	static const char * const hevc_refresh_type[] = {
5728c2ecf20Sopenharmony_ci		"None",
5738c2ecf20Sopenharmony_ci		"CRA",
5748c2ecf20Sopenharmony_ci		"IDR",
5758c2ecf20Sopenharmony_ci		NULL,
5768c2ecf20Sopenharmony_ci	};
5778c2ecf20Sopenharmony_ci	static const char * const hevc_size_of_length_field[] = {
5788c2ecf20Sopenharmony_ci		"0",
5798c2ecf20Sopenharmony_ci		"1",
5808c2ecf20Sopenharmony_ci		"2",
5818c2ecf20Sopenharmony_ci		"4",
5828c2ecf20Sopenharmony_ci		NULL,
5838c2ecf20Sopenharmony_ci	};
5848c2ecf20Sopenharmony_ci	static const char * const hevc_tier[] = {
5858c2ecf20Sopenharmony_ci		"Main",
5868c2ecf20Sopenharmony_ci		"High",
5878c2ecf20Sopenharmony_ci		NULL,
5888c2ecf20Sopenharmony_ci	};
5898c2ecf20Sopenharmony_ci	static const char * const hevc_loop_filter_mode[] = {
5908c2ecf20Sopenharmony_ci		"Disabled",
5918c2ecf20Sopenharmony_ci		"Enabled",
5928c2ecf20Sopenharmony_ci		"Disabled at slice boundary",
5938c2ecf20Sopenharmony_ci		"NULL",
5948c2ecf20Sopenharmony_ci	};
5958c2ecf20Sopenharmony_ci	static const char * const hevc_decode_mode[] = {
5968c2ecf20Sopenharmony_ci		"Slice-Based",
5978c2ecf20Sopenharmony_ci		"Frame-Based",
5988c2ecf20Sopenharmony_ci		NULL,
5998c2ecf20Sopenharmony_ci	};
6008c2ecf20Sopenharmony_ci	static const char * const hevc_start_code[] = {
6018c2ecf20Sopenharmony_ci		"No Start Code",
6028c2ecf20Sopenharmony_ci		"Annex B Start Code",
6038c2ecf20Sopenharmony_ci		NULL,
6048c2ecf20Sopenharmony_ci	};
6058c2ecf20Sopenharmony_ci	static const char * const camera_orientation[] = {
6068c2ecf20Sopenharmony_ci		"Front",
6078c2ecf20Sopenharmony_ci		"Back",
6088c2ecf20Sopenharmony_ci		"External",
6098c2ecf20Sopenharmony_ci		NULL,
6108c2ecf20Sopenharmony_ci	};
6118c2ecf20Sopenharmony_ci	static const char * const mpeg_video_frame_skip[] = {
6128c2ecf20Sopenharmony_ci		"Disabled",
6138c2ecf20Sopenharmony_ci		"Level Limit",
6148c2ecf20Sopenharmony_ci		"VBV/CPB Limit",
6158c2ecf20Sopenharmony_ci		NULL,
6168c2ecf20Sopenharmony_ci	};
6178c2ecf20Sopenharmony_ci
6188c2ecf20Sopenharmony_ci	switch (id) {
6198c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
6208c2ecf20Sopenharmony_ci		return mpeg_audio_sampling_freq;
6218c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_AUDIO_ENCODING:
6228c2ecf20Sopenharmony_ci		return mpeg_audio_encoding;
6238c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_AUDIO_L1_BITRATE:
6248c2ecf20Sopenharmony_ci		return mpeg_audio_l1_bitrate;
6258c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
6268c2ecf20Sopenharmony_ci		return mpeg_audio_l2_bitrate;
6278c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_AUDIO_L3_BITRATE:
6288c2ecf20Sopenharmony_ci		return mpeg_audio_l3_bitrate;
6298c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_AUDIO_AC3_BITRATE:
6308c2ecf20Sopenharmony_ci		return mpeg_audio_ac3_bitrate;
6318c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_AUDIO_MODE:
6328c2ecf20Sopenharmony_ci		return mpeg_audio_mode;
6338c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION:
6348c2ecf20Sopenharmony_ci		return mpeg_audio_mode_extension;
6358c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_AUDIO_EMPHASIS:
6368c2ecf20Sopenharmony_ci		return mpeg_audio_emphasis;
6378c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_AUDIO_CRC:
6388c2ecf20Sopenharmony_ci		return mpeg_audio_crc;
6398c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_AUDIO_DEC_PLAYBACK:
6408c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_AUDIO_DEC_MULTILINGUAL_PLAYBACK:
6418c2ecf20Sopenharmony_ci		return mpeg_audio_dec_playback;
6428c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_ENCODING:
6438c2ecf20Sopenharmony_ci		return mpeg_video_encoding;
6448c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_ASPECT:
6458c2ecf20Sopenharmony_ci		return mpeg_video_aspect;
6468c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
6478c2ecf20Sopenharmony_ci		return mpeg_video_bitrate_mode;
6488c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_STREAM_TYPE:
6498c2ecf20Sopenharmony_ci		return mpeg_stream_type;
6508c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_STREAM_VBI_FMT:
6518c2ecf20Sopenharmony_ci		return mpeg_stream_vbi_fmt;
6528c2ecf20Sopenharmony_ci	case V4L2_CID_POWER_LINE_FREQUENCY:
6538c2ecf20Sopenharmony_ci		return camera_power_line_frequency;
6548c2ecf20Sopenharmony_ci	case V4L2_CID_EXPOSURE_AUTO:
6558c2ecf20Sopenharmony_ci		return camera_exposure_auto;
6568c2ecf20Sopenharmony_ci	case V4L2_CID_EXPOSURE_METERING:
6578c2ecf20Sopenharmony_ci		return camera_exposure_metering;
6588c2ecf20Sopenharmony_ci	case V4L2_CID_AUTO_FOCUS_RANGE:
6598c2ecf20Sopenharmony_ci		return camera_auto_focus_range;
6608c2ecf20Sopenharmony_ci	case V4L2_CID_COLORFX:
6618c2ecf20Sopenharmony_ci		return colorfx;
6628c2ecf20Sopenharmony_ci	case V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE:
6638c2ecf20Sopenharmony_ci		return auto_n_preset_white_balance;
6648c2ecf20Sopenharmony_ci	case V4L2_CID_ISO_SENSITIVITY_AUTO:
6658c2ecf20Sopenharmony_ci		return camera_iso_sensitivity_auto;
6668c2ecf20Sopenharmony_ci	case V4L2_CID_SCENE_MODE:
6678c2ecf20Sopenharmony_ci		return scene_mode;
6688c2ecf20Sopenharmony_ci	case V4L2_CID_TUNE_PREEMPHASIS:
6698c2ecf20Sopenharmony_ci		return tune_emphasis;
6708c2ecf20Sopenharmony_ci	case V4L2_CID_TUNE_DEEMPHASIS:
6718c2ecf20Sopenharmony_ci		return tune_emphasis;
6728c2ecf20Sopenharmony_ci	case V4L2_CID_FLASH_LED_MODE:
6738c2ecf20Sopenharmony_ci		return flash_led_mode;
6748c2ecf20Sopenharmony_ci	case V4L2_CID_FLASH_STROBE_SOURCE:
6758c2ecf20Sopenharmony_ci		return flash_strobe_source;
6768c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_HEADER_MODE:
6778c2ecf20Sopenharmony_ci		return header_mode;
6788c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_FRAME_SKIP_MODE:
6798c2ecf20Sopenharmony_ci		return mpeg_video_frame_skip;
6808c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE:
6818c2ecf20Sopenharmony_ci		return multi_slice;
6828c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE:
6838c2ecf20Sopenharmony_ci		return entropy_mode;
6848c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_H264_LEVEL:
6858c2ecf20Sopenharmony_ci		return mpeg_h264_level;
6868c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE:
6878c2ecf20Sopenharmony_ci		return h264_loop_filter;
6888c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
6898c2ecf20Sopenharmony_ci		return h264_profile;
6908c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_IDC:
6918c2ecf20Sopenharmony_ci		return vui_sar_idc;
6928c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE:
6938c2ecf20Sopenharmony_ci		return h264_fp_arrangement_type;
6948c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_H264_FMO_MAP_TYPE:
6958c2ecf20Sopenharmony_ci		return h264_fmo_map_type;
6968c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_H264_DECODE_MODE:
6978c2ecf20Sopenharmony_ci		return h264_decode_mode;
6988c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_H264_START_CODE:
6998c2ecf20Sopenharmony_ci		return h264_start_code;
7008c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_MPEG2_LEVEL:
7018c2ecf20Sopenharmony_ci		return mpeg_mpeg2_level;
7028c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_MPEG2_PROFILE:
7038c2ecf20Sopenharmony_ci		return mpeg2_profile;
7048c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL:
7058c2ecf20Sopenharmony_ci		return mpeg_mpeg4_level;
7068c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE:
7078c2ecf20Sopenharmony_ci		return mpeg4_profile;
7088c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_SEL:
7098c2ecf20Sopenharmony_ci		return vpx_golden_frame_sel;
7108c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_VP8_PROFILE:
7118c2ecf20Sopenharmony_ci		return vp8_profile;
7128c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_VP9_PROFILE:
7138c2ecf20Sopenharmony_ci		return vp9_profile;
7148c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_VP9_LEVEL:
7158c2ecf20Sopenharmony_ci		return vp9_level;
7168c2ecf20Sopenharmony_ci	case V4L2_CID_JPEG_CHROMA_SUBSAMPLING:
7178c2ecf20Sopenharmony_ci		return jpeg_chroma_subsampling;
7188c2ecf20Sopenharmony_ci	case V4L2_CID_DV_TX_MODE:
7198c2ecf20Sopenharmony_ci		return dv_tx_mode;
7208c2ecf20Sopenharmony_ci	case V4L2_CID_DV_TX_RGB_RANGE:
7218c2ecf20Sopenharmony_ci	case V4L2_CID_DV_RX_RGB_RANGE:
7228c2ecf20Sopenharmony_ci		return dv_rgb_range;
7238c2ecf20Sopenharmony_ci	case V4L2_CID_DV_TX_IT_CONTENT_TYPE:
7248c2ecf20Sopenharmony_ci	case V4L2_CID_DV_RX_IT_CONTENT_TYPE:
7258c2ecf20Sopenharmony_ci		return dv_it_content_type;
7268c2ecf20Sopenharmony_ci	case V4L2_CID_DETECT_MD_MODE:
7278c2ecf20Sopenharmony_ci		return detect_md_mode;
7288c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_HEVC_PROFILE:
7298c2ecf20Sopenharmony_ci		return hevc_profile;
7308c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_HEVC_LEVEL:
7318c2ecf20Sopenharmony_ci		return hevc_level;
7328c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_TYPE:
7338c2ecf20Sopenharmony_ci		return hevc_hierarchial_coding_type;
7348c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_HEVC_REFRESH_TYPE:
7358c2ecf20Sopenharmony_ci		return hevc_refresh_type;
7368c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_HEVC_SIZE_OF_LENGTH_FIELD:
7378c2ecf20Sopenharmony_ci		return hevc_size_of_length_field;
7388c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_HEVC_TIER:
7398c2ecf20Sopenharmony_ci		return hevc_tier;
7408c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_HEVC_LOOP_FILTER_MODE:
7418c2ecf20Sopenharmony_ci		return hevc_loop_filter_mode;
7428c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_HEVC_DECODE_MODE:
7438c2ecf20Sopenharmony_ci		return hevc_decode_mode;
7448c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_HEVC_START_CODE:
7458c2ecf20Sopenharmony_ci		return hevc_start_code;
7468c2ecf20Sopenharmony_ci	case V4L2_CID_CAMERA_ORIENTATION:
7478c2ecf20Sopenharmony_ci		return camera_orientation;
7488c2ecf20Sopenharmony_ci	default:
7498c2ecf20Sopenharmony_ci		return NULL;
7508c2ecf20Sopenharmony_ci	}
7518c2ecf20Sopenharmony_ci}
7528c2ecf20Sopenharmony_ciEXPORT_SYMBOL(v4l2_ctrl_get_menu);
7538c2ecf20Sopenharmony_ci
7548c2ecf20Sopenharmony_ci#define __v4l2_qmenu_int_len(arr, len) ({ *(len) = ARRAY_SIZE(arr); arr; })
7558c2ecf20Sopenharmony_ci/*
7568c2ecf20Sopenharmony_ci * Returns NULL or an s64 type array containing the menu for given
7578c2ecf20Sopenharmony_ci * control ID. The total number of the menu items is returned in @len.
7588c2ecf20Sopenharmony_ci */
7598c2ecf20Sopenharmony_ciconst s64 *v4l2_ctrl_get_int_menu(u32 id, u32 *len)
7608c2ecf20Sopenharmony_ci{
7618c2ecf20Sopenharmony_ci	static const s64 qmenu_int_vpx_num_partitions[] = {
7628c2ecf20Sopenharmony_ci		1, 2, 4, 8,
7638c2ecf20Sopenharmony_ci	};
7648c2ecf20Sopenharmony_ci
7658c2ecf20Sopenharmony_ci	static const s64 qmenu_int_vpx_num_ref_frames[] = {
7668c2ecf20Sopenharmony_ci		1, 2, 3,
7678c2ecf20Sopenharmony_ci	};
7688c2ecf20Sopenharmony_ci
7698c2ecf20Sopenharmony_ci	switch (id) {
7708c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_VPX_NUM_PARTITIONS:
7718c2ecf20Sopenharmony_ci		return __v4l2_qmenu_int_len(qmenu_int_vpx_num_partitions, len);
7728c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_VPX_NUM_REF_FRAMES:
7738c2ecf20Sopenharmony_ci		return __v4l2_qmenu_int_len(qmenu_int_vpx_num_ref_frames, len);
7748c2ecf20Sopenharmony_ci	default:
7758c2ecf20Sopenharmony_ci		*len = 0;
7768c2ecf20Sopenharmony_ci		return NULL;
7778c2ecf20Sopenharmony_ci	}
7788c2ecf20Sopenharmony_ci}
7798c2ecf20Sopenharmony_ciEXPORT_SYMBOL(v4l2_ctrl_get_int_menu);
7808c2ecf20Sopenharmony_ci
7818c2ecf20Sopenharmony_ci/* Return the control name. */
7828c2ecf20Sopenharmony_ciconst char *v4l2_ctrl_get_name(u32 id)
7838c2ecf20Sopenharmony_ci{
7848c2ecf20Sopenharmony_ci	switch (id) {
7858c2ecf20Sopenharmony_ci	/* USER controls */
7868c2ecf20Sopenharmony_ci	/* Keep the order of the 'case's the same as in v4l2-controls.h! */
7878c2ecf20Sopenharmony_ci	case V4L2_CID_USER_CLASS:		return "User Controls";
7888c2ecf20Sopenharmony_ci	case V4L2_CID_BRIGHTNESS:		return "Brightness";
7898c2ecf20Sopenharmony_ci	case V4L2_CID_CONTRAST:			return "Contrast";
7908c2ecf20Sopenharmony_ci	case V4L2_CID_SATURATION:		return "Saturation";
7918c2ecf20Sopenharmony_ci	case V4L2_CID_HUE:			return "Hue";
7928c2ecf20Sopenharmony_ci	case V4L2_CID_AUDIO_VOLUME:		return "Volume";
7938c2ecf20Sopenharmony_ci	case V4L2_CID_AUDIO_BALANCE:		return "Balance";
7948c2ecf20Sopenharmony_ci	case V4L2_CID_AUDIO_BASS:		return "Bass";
7958c2ecf20Sopenharmony_ci	case V4L2_CID_AUDIO_TREBLE:		return "Treble";
7968c2ecf20Sopenharmony_ci	case V4L2_CID_AUDIO_MUTE:		return "Mute";
7978c2ecf20Sopenharmony_ci	case V4L2_CID_AUDIO_LOUDNESS:		return "Loudness";
7988c2ecf20Sopenharmony_ci	case V4L2_CID_BLACK_LEVEL:		return "Black Level";
7998c2ecf20Sopenharmony_ci	case V4L2_CID_AUTO_WHITE_BALANCE:	return "White Balance, Automatic";
8008c2ecf20Sopenharmony_ci	case V4L2_CID_DO_WHITE_BALANCE:		return "Do White Balance";
8018c2ecf20Sopenharmony_ci	case V4L2_CID_RED_BALANCE:		return "Red Balance";
8028c2ecf20Sopenharmony_ci	case V4L2_CID_BLUE_BALANCE:		return "Blue Balance";
8038c2ecf20Sopenharmony_ci	case V4L2_CID_GAMMA:			return "Gamma";
8048c2ecf20Sopenharmony_ci	case V4L2_CID_EXPOSURE:			return "Exposure";
8058c2ecf20Sopenharmony_ci	case V4L2_CID_AUTOGAIN:			return "Gain, Automatic";
8068c2ecf20Sopenharmony_ci	case V4L2_CID_GAIN:			return "Gain";
8078c2ecf20Sopenharmony_ci	case V4L2_CID_HFLIP:			return "Horizontal Flip";
8088c2ecf20Sopenharmony_ci	case V4L2_CID_VFLIP:			return "Vertical Flip";
8098c2ecf20Sopenharmony_ci	case V4L2_CID_POWER_LINE_FREQUENCY:	return "Power Line Frequency";
8108c2ecf20Sopenharmony_ci	case V4L2_CID_HUE_AUTO:			return "Hue, Automatic";
8118c2ecf20Sopenharmony_ci	case V4L2_CID_WHITE_BALANCE_TEMPERATURE: return "White Balance Temperature";
8128c2ecf20Sopenharmony_ci	case V4L2_CID_SHARPNESS:		return "Sharpness";
8138c2ecf20Sopenharmony_ci	case V4L2_CID_BACKLIGHT_COMPENSATION:	return "Backlight Compensation";
8148c2ecf20Sopenharmony_ci	case V4L2_CID_CHROMA_AGC:		return "Chroma AGC";
8158c2ecf20Sopenharmony_ci	case V4L2_CID_COLOR_KILLER:		return "Color Killer";
8168c2ecf20Sopenharmony_ci	case V4L2_CID_COLORFX:			return "Color Effects";
8178c2ecf20Sopenharmony_ci	case V4L2_CID_AUTOBRIGHTNESS:		return "Brightness, Automatic";
8188c2ecf20Sopenharmony_ci	case V4L2_CID_BAND_STOP_FILTER:		return "Band-Stop Filter";
8198c2ecf20Sopenharmony_ci	case V4L2_CID_ROTATE:			return "Rotate";
8208c2ecf20Sopenharmony_ci	case V4L2_CID_BG_COLOR:			return "Background Color";
8218c2ecf20Sopenharmony_ci	case V4L2_CID_CHROMA_GAIN:		return "Chroma Gain";
8228c2ecf20Sopenharmony_ci	case V4L2_CID_ILLUMINATORS_1:		return "Illuminator 1";
8238c2ecf20Sopenharmony_ci	case V4L2_CID_ILLUMINATORS_2:		return "Illuminator 2";
8248c2ecf20Sopenharmony_ci	case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE:	return "Min Number of Capture Buffers";
8258c2ecf20Sopenharmony_ci	case V4L2_CID_MIN_BUFFERS_FOR_OUTPUT:	return "Min Number of Output Buffers";
8268c2ecf20Sopenharmony_ci	case V4L2_CID_ALPHA_COMPONENT:		return "Alpha Component";
8278c2ecf20Sopenharmony_ci	case V4L2_CID_COLORFX_CBCR:		return "Color Effects, CbCr";
8288c2ecf20Sopenharmony_ci
8298c2ecf20Sopenharmony_ci	/* Codec controls */
8308c2ecf20Sopenharmony_ci	/* The MPEG controls are applicable to all codec controls
8318c2ecf20Sopenharmony_ci	 * and the 'MPEG' part of the define is historical */
8328c2ecf20Sopenharmony_ci	/* Keep the order of the 'case's the same as in videodev2.h! */
8338c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_CLASS:		return "Codec Controls";
8348c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_STREAM_TYPE:		return "Stream Type";
8358c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_STREAM_PID_PMT:	return "Stream PMT Program ID";
8368c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_STREAM_PID_AUDIO:	return "Stream Audio Program ID";
8378c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_STREAM_PID_VIDEO:	return "Stream Video Program ID";
8388c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_STREAM_PID_PCR:	return "Stream PCR Program ID";
8398c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_STREAM_PES_ID_AUDIO: return "Stream PES Audio ID";
8408c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_STREAM_PES_ID_VIDEO: return "Stream PES Video ID";
8418c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_STREAM_VBI_FMT:	return "Stream VBI Format";
8428c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: return "Audio Sampling Frequency";
8438c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_AUDIO_ENCODING:	return "Audio Encoding";
8448c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_AUDIO_L1_BITRATE:	return "Audio Layer I Bitrate";
8458c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_AUDIO_L2_BITRATE:	return "Audio Layer II Bitrate";
8468c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_AUDIO_L3_BITRATE:	return "Audio Layer III Bitrate";
8478c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_AUDIO_MODE:		return "Audio Stereo Mode";
8488c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION: return "Audio Stereo Mode Extension";
8498c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_AUDIO_EMPHASIS:	return "Audio Emphasis";
8508c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_AUDIO_CRC:		return "Audio CRC";
8518c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_AUDIO_MUTE:		return "Audio Mute";
8528c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_AUDIO_AAC_BITRATE:	return "Audio AAC Bitrate";
8538c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_AUDIO_AC3_BITRATE:	return "Audio AC-3 Bitrate";
8548c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_AUDIO_DEC_PLAYBACK:	return "Audio Playback";
8558c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_AUDIO_DEC_MULTILINGUAL_PLAYBACK: return "Audio Multilingual Playback";
8568c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_ENCODING:	return "Video Encoding";
8578c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_ASPECT:	return "Video Aspect";
8588c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_B_FRAMES:	return "Video B Frames";
8598c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_GOP_SIZE:	return "Video GOP Size";
8608c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:	return "Video GOP Closure";
8618c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_PULLDOWN:	return "Video Pulldown";
8628c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:	return "Video Bitrate Mode";
8638c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_CONSTANT_QUALITY:	return "Constant Quality";
8648c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_BITRATE:	return "Video Bitrate";
8658c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:	return "Video Peak Bitrate";
8668c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION: return "Video Temporal Decimation";
8678c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_MUTE:		return "Video Mute";
8688c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_MUTE_YUV:	return "Video Mute YUV";
8698c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_DECODER_SLICE_INTERFACE:	return "Decoder Slice Interface";
8708c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_DECODER_MPEG4_DEBLOCK_FILTER:	return "MPEG4 Loop Filter Enable";
8718c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB:	return "Number of Intra Refresh MBs";
8728c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE:		return "Frame Level Rate Control Enable";
8738c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_MB_RC_ENABLE:			return "H264 MB Level Rate Control";
8748c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_HEADER_MODE:			return "Sequence Header Mode";
8758c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_MAX_REF_PIC:			return "Max Number of Reference Pics";
8768c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_FRAME_SKIP_MODE:		return "Frame Skip Mode";
8778c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_H263_I_FRAME_QP:		return "H263 I-Frame QP Value";
8788c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_H263_P_FRAME_QP:		return "H263 P-Frame QP Value";
8798c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_H263_B_FRAME_QP:		return "H263 B-Frame QP Value";
8808c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_H263_MIN_QP:			return "H263 Minimum QP Value";
8818c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_H263_MAX_QP:			return "H263 Maximum QP Value";
8828c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP:		return "H264 I-Frame QP Value";
8838c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP:		return "H264 P-Frame QP Value";
8848c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_H264_B_FRAME_QP:		return "H264 B-Frame QP Value";
8858c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_H264_MAX_QP:			return "H264 Maximum QP Value";
8868c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_H264_MIN_QP:			return "H264 Minimum QP Value";
8878c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_H264_8X8_TRANSFORM:		return "H264 8x8 Transform Enable";
8888c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_H264_CPB_SIZE:			return "H264 CPB Buffer Size";
8898c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE:		return "H264 Entropy Mode";
8908c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_H264_I_PERIOD:			return "H264 I-Frame Period";
8918c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_H264_LEVEL:			return "H264 Level";
8928c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_ALPHA:	return "H264 Loop Filter Alpha Offset";
8938c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_BETA:		return "H264 Loop Filter Beta Offset";
8948c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE:		return "H264 Loop Filter Mode";
8958c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_H264_PROFILE:			return "H264 Profile";
8968c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_HEIGHT:	return "Vertical Size of SAR";
8978c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_WIDTH:	return "Horizontal Size of SAR";
8988c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_ENABLE:		return "Aspect Ratio VUI Enable";
8998c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_IDC:		return "VUI Aspect Ratio IDC";
9008c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_H264_SEI_FRAME_PACKING:	return "H264 Enable Frame Packing SEI";
9018c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_H264_SEI_FP_CURRENT_FRAME_0:	return "H264 Set Curr. Frame as Frame0";
9028c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE:	return "H264 FP Arrangement Type";
9038c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_H264_FMO:			return "H264 Flexible MB Ordering";
9048c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_H264_FMO_MAP_TYPE:		return "H264 Map Type for FMO";
9058c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_H264_FMO_SLICE_GROUP:		return "H264 FMO Number of Slice Groups";
9068c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_H264_FMO_CHANGE_DIRECTION:	return "H264 FMO Direction of Change";
9078c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_H264_FMO_CHANGE_RATE:		return "H264 FMO Size of 1st Slice Grp";
9088c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_H264_FMO_RUN_LENGTH:		return "H264 FMO No. of Consecutive MBs";
9098c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_H264_ASO:			return "H264 Arbitrary Slice Ordering";
9108c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_H264_ASO_SLICE_ORDER:		return "H264 ASO Slice Order";
9118c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING:	return "Enable H264 Hierarchical Coding";
9128c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_TYPE:	return "H264 Hierarchical Coding Type";
9138c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER:return "H264 Number of HC Layers";
9148c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_QP:
9158c2ecf20Sopenharmony_ci								return "H264 Set QP Value for HC Layers";
9168c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_H264_CONSTRAINED_INTRA_PREDICTION:
9178c2ecf20Sopenharmony_ci								return "H264 Constrained Intra Pred";
9188c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_H264_CHROMA_QP_INDEX_OFFSET:	return "H264 Chroma QP Index Offset";
9198c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_H264_I_FRAME_MIN_QP:		return "H264 I-Frame Minimum QP Value";
9208c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_H264_I_FRAME_MAX_QP:		return "H264 I-Frame Maximum QP Value";
9218c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_H264_P_FRAME_MIN_QP:		return "H264 P-Frame Minimum QP Value";
9228c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_H264_P_FRAME_MAX_QP:		return "H264 P-Frame Maximum QP Value";
9238c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_H264_SPS:			return "H264 Sequence Parameter Set";
9248c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_H264_PPS:			return "H264 Picture Parameter Set";
9258c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_H264_SCALING_MATRIX:		return "H264 Scaling Matrix";
9268c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_H264_SLICE_PARAMS:		return "H264 Slice Parameters";
9278c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_H264_DECODE_PARAMS:		return "H264 Decode Parameters";
9288c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_H264_DECODE_MODE:		return "H264 Decode Mode";
9298c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_H264_START_CODE:		return "H264 Start Code";
9308c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_H264_PRED_WEIGHTS:		return "H264 Prediction Weight Table";
9318c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_MPEG2_LEVEL:			return "MPEG2 Level";
9328c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_MPEG2_PROFILE:			return "MPEG2 Profile";
9338c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP:		return "MPEG4 I-Frame QP Value";
9348c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_MPEG4_P_FRAME_QP:		return "MPEG4 P-Frame QP Value";
9358c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_MPEG4_B_FRAME_QP:		return "MPEG4 B-Frame QP Value";
9368c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP:			return "MPEG4 Minimum QP Value";
9378c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP:			return "MPEG4 Maximum QP Value";
9388c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL:			return "MPEG4 Level";
9398c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE:			return "MPEG4 Profile";
9408c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_MPEG4_QPEL:			return "Quarter Pixel Search Enable";
9418c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES:		return "Maximum Bytes in a Slice";
9428c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB:		return "Number of MBs in a Slice";
9438c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE:		return "Slice Partitioning Method";
9448c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_VBV_SIZE:			return "VBV Buffer Size";
9458c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_DEC_PTS:			return "Video Decoder PTS";
9468c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_DEC_FRAME:			return "Video Decoder Frame Count";
9478c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_VBV_DELAY:			return "Initial Delay for VBV Control";
9488c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_MV_H_SEARCH_RANGE:		return "Horizontal MV Search Range";
9498c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_MV_V_SEARCH_RANGE:		return "Vertical MV Search Range";
9508c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_REPEAT_SEQ_HEADER:		return "Repeat Sequence Header";
9518c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME:		return "Force Key Frame";
9528c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_MPEG2_SLICE_PARAMS:		return "MPEG-2 Slice Parameters";
9538c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_MPEG2_QUANTIZATION:		return "MPEG-2 Quantization Matrices";
9548c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_FWHT_PARAMS:			return "FWHT Stateless Parameters";
9558c2ecf20Sopenharmony_ci	case V4L2_CID_FWHT_I_FRAME_QP:				return "FWHT I-Frame QP Value";
9568c2ecf20Sopenharmony_ci	case V4L2_CID_FWHT_P_FRAME_QP:				return "FWHT P-Frame QP Value";
9578c2ecf20Sopenharmony_ci
9588c2ecf20Sopenharmony_ci	/* VPX controls */
9598c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_VPX_NUM_PARTITIONS:		return "VPX Number of Partitions";
9608c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_VPX_IMD_DISABLE_4X4:		return "VPX Intra Mode Decision Disable";
9618c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_VPX_NUM_REF_FRAMES:		return "VPX No. of Refs for P Frame";
9628c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_VPX_FILTER_LEVEL:		return "VPX Loop Filter Level Range";
9638c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_VPX_FILTER_SHARPNESS:		return "VPX Deblocking Effect Control";
9648c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_REF_PERIOD:	return "VPX Golden Frame Refresh Period";
9658c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_SEL:		return "VPX Golden Frame Indicator";
9668c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_VPX_MIN_QP:			return "VPX Minimum QP Value";
9678c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_VPX_MAX_QP:			return "VPX Maximum QP Value";
9688c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_VPX_I_FRAME_QP:		return "VPX I-Frame QP Value";
9698c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_VPX_P_FRAME_QP:		return "VPX P-Frame QP Value";
9708c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_VP8_PROFILE:			return "VP8 Profile";
9718c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_VP9_PROFILE:			return "VP9 Profile";
9728c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_VP9_LEVEL:			return "VP9 Level";
9738c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_VP8_FRAME_HEADER:		return "VP8 Frame Header";
9748c2ecf20Sopenharmony_ci
9758c2ecf20Sopenharmony_ci	/* HEVC controls */
9768c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_QP:		return "HEVC I-Frame QP Value";
9778c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_HEVC_P_FRAME_QP:		return "HEVC P-Frame QP Value";
9788c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_HEVC_B_FRAME_QP:		return "HEVC B-Frame QP Value";
9798c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP:			return "HEVC Minimum QP Value";
9808c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP:			return "HEVC Maximum QP Value";
9818c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_HEVC_PROFILE:			return "HEVC Profile";
9828c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_HEVC_LEVEL:			return "HEVC Level";
9838c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_HEVC_TIER:			return "HEVC Tier";
9848c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_HEVC_FRAME_RATE_RESOLUTION:	return "HEVC Frame Rate Resolution";
9858c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_HEVC_MAX_PARTITION_DEPTH:	return "HEVC Maximum Coding Unit Depth";
9868c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_HEVC_REFRESH_TYPE:		return "HEVC Refresh Type";
9878c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_HEVC_CONST_INTRA_PRED:		return "HEVC Constant Intra Prediction";
9888c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_HEVC_LOSSLESS_CU:		return "HEVC Lossless Encoding";
9898c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_HEVC_WAVEFRONT:		return "HEVC Wavefront";
9908c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_HEVC_LOOP_FILTER_MODE:		return "HEVC Loop Filter";
9918c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_HEVC_HIER_QP:			return "HEVC QP Values";
9928c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_TYPE:		return "HEVC Hierarchical Coding Type";
9938c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_LAYER:	return "HEVC Hierarchical Coding Layer";
9948c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L0_QP:	return "HEVC Hierarchical Layer 0 QP";
9958c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L1_QP:	return "HEVC Hierarchical Layer 1 QP";
9968c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L2_QP:	return "HEVC Hierarchical Layer 2 QP";
9978c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L3_QP:	return "HEVC Hierarchical Layer 3 QP";
9988c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L4_QP:	return "HEVC Hierarchical Layer 4 QP";
9998c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L5_QP:	return "HEVC Hierarchical Layer 5 QP";
10008c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L6_QP:	return "HEVC Hierarchical Layer 6 QP";
10018c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L0_BR:	return "HEVC Hierarchical Lay 0 BitRate";
10028c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L1_BR:	return "HEVC Hierarchical Lay 1 BitRate";
10038c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L2_BR:	return "HEVC Hierarchical Lay 2 BitRate";
10048c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L3_BR:	return "HEVC Hierarchical Lay 3 BitRate";
10058c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L4_BR:	return "HEVC Hierarchical Lay 4 BitRate";
10068c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L5_BR:	return "HEVC Hierarchical Lay 5 BitRate";
10078c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L6_BR:	return "HEVC Hierarchical Lay 6 BitRate";
10088c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_HEVC_GENERAL_PB:		return "HEVC General PB";
10098c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_HEVC_TEMPORAL_ID:		return "HEVC Temporal ID";
10108c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_HEVC_STRONG_SMOOTHING:		return "HEVC Strong Intra Smoothing";
10118c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_HEVC_INTRA_PU_SPLIT:		return "HEVC Intra PU Split";
10128c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_HEVC_TMV_PREDICTION:		return "HEVC TMV Prediction";
10138c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_HEVC_MAX_NUM_MERGE_MV_MINUS1:	return "HEVC Max Num of Candidate MVs";
10148c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_HEVC_WITHOUT_STARTCODE:	return "HEVC ENC Without Startcode";
10158c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_HEVC_REFRESH_PERIOD:		return "HEVC Num of I-Frame b/w 2 IDR";
10168c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_HEVC_LF_BETA_OFFSET_DIV2:	return "HEVC Loop Filter Beta Offset";
10178c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_HEVC_LF_TC_OFFSET_DIV2:	return "HEVC Loop Filter TC Offset";
10188c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_HEVC_SIZE_OF_LENGTH_FIELD:	return "HEVC Size of Length Field";
10198c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_REF_NUMBER_FOR_PFRAMES:	return "Reference Frames for a P-Frame";
10208c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_PREPEND_SPSPPS_TO_IDR:		return "Prepend SPS and PPS to IDR";
10218c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_HEVC_SPS:			return "HEVC Sequence Parameter Set";
10228c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_HEVC_PPS:			return "HEVC Picture Parameter Set";
10238c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS:		return "HEVC Slice Parameters";
10248c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_HEVC_DECODE_MODE:		return "HEVC Decode Mode";
10258c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_HEVC_START_CODE:		return "HEVC Start Code";
10268c2ecf20Sopenharmony_ci
10278c2ecf20Sopenharmony_ci	/* CAMERA controls */
10288c2ecf20Sopenharmony_ci	/* Keep the order of the 'case's the same as in v4l2-controls.h! */
10298c2ecf20Sopenharmony_ci	case V4L2_CID_CAMERA_CLASS:		return "Camera Controls";
10308c2ecf20Sopenharmony_ci	case V4L2_CID_EXPOSURE_AUTO:		return "Auto Exposure";
10318c2ecf20Sopenharmony_ci	case V4L2_CID_EXPOSURE_ABSOLUTE:	return "Exposure Time, Absolute";
10328c2ecf20Sopenharmony_ci	case V4L2_CID_EXPOSURE_AUTO_PRIORITY:	return "Exposure, Dynamic Framerate";
10338c2ecf20Sopenharmony_ci	case V4L2_CID_PAN_RELATIVE:		return "Pan, Relative";
10348c2ecf20Sopenharmony_ci	case V4L2_CID_TILT_RELATIVE:		return "Tilt, Relative";
10358c2ecf20Sopenharmony_ci	case V4L2_CID_PAN_RESET:		return "Pan, Reset";
10368c2ecf20Sopenharmony_ci	case V4L2_CID_TILT_RESET:		return "Tilt, Reset";
10378c2ecf20Sopenharmony_ci	case V4L2_CID_PAN_ABSOLUTE:		return "Pan, Absolute";
10388c2ecf20Sopenharmony_ci	case V4L2_CID_TILT_ABSOLUTE:		return "Tilt, Absolute";
10398c2ecf20Sopenharmony_ci	case V4L2_CID_FOCUS_ABSOLUTE:		return "Focus, Absolute";
10408c2ecf20Sopenharmony_ci	case V4L2_CID_FOCUS_RELATIVE:		return "Focus, Relative";
10418c2ecf20Sopenharmony_ci	case V4L2_CID_FOCUS_AUTO:		return "Focus, Automatic Continuous";
10428c2ecf20Sopenharmony_ci	case V4L2_CID_ZOOM_ABSOLUTE:		return "Zoom, Absolute";
10438c2ecf20Sopenharmony_ci	case V4L2_CID_ZOOM_RELATIVE:		return "Zoom, Relative";
10448c2ecf20Sopenharmony_ci	case V4L2_CID_ZOOM_CONTINUOUS:		return "Zoom, Continuous";
10458c2ecf20Sopenharmony_ci	case V4L2_CID_PRIVACY:			return "Privacy";
10468c2ecf20Sopenharmony_ci	case V4L2_CID_IRIS_ABSOLUTE:		return "Iris, Absolute";
10478c2ecf20Sopenharmony_ci	case V4L2_CID_IRIS_RELATIVE:		return "Iris, Relative";
10488c2ecf20Sopenharmony_ci	case V4L2_CID_AUTO_EXPOSURE_BIAS:	return "Auto Exposure, Bias";
10498c2ecf20Sopenharmony_ci	case V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE: return "White Balance, Auto & Preset";
10508c2ecf20Sopenharmony_ci	case V4L2_CID_WIDE_DYNAMIC_RANGE:	return "Wide Dynamic Range";
10518c2ecf20Sopenharmony_ci	case V4L2_CID_IMAGE_STABILIZATION:	return "Image Stabilization";
10528c2ecf20Sopenharmony_ci	case V4L2_CID_ISO_SENSITIVITY:		return "ISO Sensitivity";
10538c2ecf20Sopenharmony_ci	case V4L2_CID_ISO_SENSITIVITY_AUTO:	return "ISO Sensitivity, Auto";
10548c2ecf20Sopenharmony_ci	case V4L2_CID_EXPOSURE_METERING:	return "Exposure, Metering Mode";
10558c2ecf20Sopenharmony_ci	case V4L2_CID_SCENE_MODE:		return "Scene Mode";
10568c2ecf20Sopenharmony_ci	case V4L2_CID_3A_LOCK:			return "3A Lock";
10578c2ecf20Sopenharmony_ci	case V4L2_CID_AUTO_FOCUS_START:		return "Auto Focus, Start";
10588c2ecf20Sopenharmony_ci	case V4L2_CID_AUTO_FOCUS_STOP:		return "Auto Focus, Stop";
10598c2ecf20Sopenharmony_ci	case V4L2_CID_AUTO_FOCUS_STATUS:	return "Auto Focus, Status";
10608c2ecf20Sopenharmony_ci	case V4L2_CID_AUTO_FOCUS_RANGE:		return "Auto Focus, Range";
10618c2ecf20Sopenharmony_ci	case V4L2_CID_PAN_SPEED:		return "Pan, Speed";
10628c2ecf20Sopenharmony_ci	case V4L2_CID_TILT_SPEED:		return "Tilt, Speed";
10638c2ecf20Sopenharmony_ci	case V4L2_CID_UNIT_CELL_SIZE:		return "Unit Cell Size";
10648c2ecf20Sopenharmony_ci	case V4L2_CID_CAMERA_ORIENTATION:	return "Camera Orientation";
10658c2ecf20Sopenharmony_ci	case V4L2_CID_CAMERA_SENSOR_ROTATION:	return "Camera Sensor Rotation";
10668c2ecf20Sopenharmony_ci
10678c2ecf20Sopenharmony_ci	/* FM Radio Modulator controls */
10688c2ecf20Sopenharmony_ci	/* Keep the order of the 'case's the same as in v4l2-controls.h! */
10698c2ecf20Sopenharmony_ci	case V4L2_CID_FM_TX_CLASS:		return "FM Radio Modulator Controls";
10708c2ecf20Sopenharmony_ci	case V4L2_CID_RDS_TX_DEVIATION:		return "RDS Signal Deviation";
10718c2ecf20Sopenharmony_ci	case V4L2_CID_RDS_TX_PI:		return "RDS Program ID";
10728c2ecf20Sopenharmony_ci	case V4L2_CID_RDS_TX_PTY:		return "RDS Program Type";
10738c2ecf20Sopenharmony_ci	case V4L2_CID_RDS_TX_PS_NAME:		return "RDS PS Name";
10748c2ecf20Sopenharmony_ci	case V4L2_CID_RDS_TX_RADIO_TEXT:	return "RDS Radio Text";
10758c2ecf20Sopenharmony_ci	case V4L2_CID_RDS_TX_MONO_STEREO:	return "RDS Stereo";
10768c2ecf20Sopenharmony_ci	case V4L2_CID_RDS_TX_ARTIFICIAL_HEAD:	return "RDS Artificial Head";
10778c2ecf20Sopenharmony_ci	case V4L2_CID_RDS_TX_COMPRESSED:	return "RDS Compressed";
10788c2ecf20Sopenharmony_ci	case V4L2_CID_RDS_TX_DYNAMIC_PTY:	return "RDS Dynamic PTY";
10798c2ecf20Sopenharmony_ci	case V4L2_CID_RDS_TX_TRAFFIC_ANNOUNCEMENT: return "RDS Traffic Announcement";
10808c2ecf20Sopenharmony_ci	case V4L2_CID_RDS_TX_TRAFFIC_PROGRAM:	return "RDS Traffic Program";
10818c2ecf20Sopenharmony_ci	case V4L2_CID_RDS_TX_MUSIC_SPEECH:	return "RDS Music";
10828c2ecf20Sopenharmony_ci	case V4L2_CID_RDS_TX_ALT_FREQS_ENABLE:	return "RDS Enable Alt Frequencies";
10838c2ecf20Sopenharmony_ci	case V4L2_CID_RDS_TX_ALT_FREQS:		return "RDS Alternate Frequencies";
10848c2ecf20Sopenharmony_ci	case V4L2_CID_AUDIO_LIMITER_ENABLED:	return "Audio Limiter Feature Enabled";
10858c2ecf20Sopenharmony_ci	case V4L2_CID_AUDIO_LIMITER_RELEASE_TIME: return "Audio Limiter Release Time";
10868c2ecf20Sopenharmony_ci	case V4L2_CID_AUDIO_LIMITER_DEVIATION:	return "Audio Limiter Deviation";
10878c2ecf20Sopenharmony_ci	case V4L2_CID_AUDIO_COMPRESSION_ENABLED: return "Audio Compression Enabled";
10888c2ecf20Sopenharmony_ci	case V4L2_CID_AUDIO_COMPRESSION_GAIN:	return "Audio Compression Gain";
10898c2ecf20Sopenharmony_ci	case V4L2_CID_AUDIO_COMPRESSION_THRESHOLD: return "Audio Compression Threshold";
10908c2ecf20Sopenharmony_ci	case V4L2_CID_AUDIO_COMPRESSION_ATTACK_TIME: return "Audio Compression Attack Time";
10918c2ecf20Sopenharmony_ci	case V4L2_CID_AUDIO_COMPRESSION_RELEASE_TIME: return "Audio Compression Release Time";
10928c2ecf20Sopenharmony_ci	case V4L2_CID_PILOT_TONE_ENABLED:	return "Pilot Tone Feature Enabled";
10938c2ecf20Sopenharmony_ci	case V4L2_CID_PILOT_TONE_DEVIATION:	return "Pilot Tone Deviation";
10948c2ecf20Sopenharmony_ci	case V4L2_CID_PILOT_TONE_FREQUENCY:	return "Pilot Tone Frequency";
10958c2ecf20Sopenharmony_ci	case V4L2_CID_TUNE_PREEMPHASIS:		return "Pre-Emphasis";
10968c2ecf20Sopenharmony_ci	case V4L2_CID_TUNE_POWER_LEVEL:		return "Tune Power Level";
10978c2ecf20Sopenharmony_ci	case V4L2_CID_TUNE_ANTENNA_CAPACITOR:	return "Tune Antenna Capacitor";
10988c2ecf20Sopenharmony_ci
10998c2ecf20Sopenharmony_ci	/* Flash controls */
11008c2ecf20Sopenharmony_ci	/* Keep the order of the 'case's the same as in v4l2-controls.h! */
11018c2ecf20Sopenharmony_ci	case V4L2_CID_FLASH_CLASS:		return "Flash Controls";
11028c2ecf20Sopenharmony_ci	case V4L2_CID_FLASH_LED_MODE:		return "LED Mode";
11038c2ecf20Sopenharmony_ci	case V4L2_CID_FLASH_STROBE_SOURCE:	return "Strobe Source";
11048c2ecf20Sopenharmony_ci	case V4L2_CID_FLASH_STROBE:		return "Strobe";
11058c2ecf20Sopenharmony_ci	case V4L2_CID_FLASH_STROBE_STOP:	return "Stop Strobe";
11068c2ecf20Sopenharmony_ci	case V4L2_CID_FLASH_STROBE_STATUS:	return "Strobe Status";
11078c2ecf20Sopenharmony_ci	case V4L2_CID_FLASH_TIMEOUT:		return "Strobe Timeout";
11088c2ecf20Sopenharmony_ci	case V4L2_CID_FLASH_INTENSITY:		return "Intensity, Flash Mode";
11098c2ecf20Sopenharmony_ci	case V4L2_CID_FLASH_TORCH_INTENSITY:	return "Intensity, Torch Mode";
11108c2ecf20Sopenharmony_ci	case V4L2_CID_FLASH_INDICATOR_INTENSITY: return "Intensity, Indicator";
11118c2ecf20Sopenharmony_ci	case V4L2_CID_FLASH_FAULT:		return "Faults";
11128c2ecf20Sopenharmony_ci	case V4L2_CID_FLASH_CHARGE:		return "Charge";
11138c2ecf20Sopenharmony_ci	case V4L2_CID_FLASH_READY:		return "Ready to Strobe";
11148c2ecf20Sopenharmony_ci
11158c2ecf20Sopenharmony_ci	/* JPEG encoder controls */
11168c2ecf20Sopenharmony_ci	/* Keep the order of the 'case's the same as in v4l2-controls.h! */
11178c2ecf20Sopenharmony_ci	case V4L2_CID_JPEG_CLASS:		return "JPEG Compression Controls";
11188c2ecf20Sopenharmony_ci	case V4L2_CID_JPEG_CHROMA_SUBSAMPLING:	return "Chroma Subsampling";
11198c2ecf20Sopenharmony_ci	case V4L2_CID_JPEG_RESTART_INTERVAL:	return "Restart Interval";
11208c2ecf20Sopenharmony_ci	case V4L2_CID_JPEG_COMPRESSION_QUALITY:	return "Compression Quality";
11218c2ecf20Sopenharmony_ci	case V4L2_CID_JPEG_ACTIVE_MARKER:	return "Active Markers";
11228c2ecf20Sopenharmony_ci
11238c2ecf20Sopenharmony_ci	/* Image source controls */
11248c2ecf20Sopenharmony_ci	/* Keep the order of the 'case's the same as in v4l2-controls.h! */
11258c2ecf20Sopenharmony_ci	case V4L2_CID_IMAGE_SOURCE_CLASS:	return "Image Source Controls";
11268c2ecf20Sopenharmony_ci	case V4L2_CID_VBLANK:			return "Vertical Blanking";
11278c2ecf20Sopenharmony_ci	case V4L2_CID_HBLANK:			return "Horizontal Blanking";
11288c2ecf20Sopenharmony_ci	case V4L2_CID_ANALOGUE_GAIN:		return "Analogue Gain";
11298c2ecf20Sopenharmony_ci	case V4L2_CID_TEST_PATTERN_RED:		return "Red Pixel Value";
11308c2ecf20Sopenharmony_ci	case V4L2_CID_TEST_PATTERN_GREENR:	return "Green (Red) Pixel Value";
11318c2ecf20Sopenharmony_ci	case V4L2_CID_TEST_PATTERN_BLUE:	return "Blue Pixel Value";
11328c2ecf20Sopenharmony_ci	case V4L2_CID_TEST_PATTERN_GREENB:	return "Green (Blue) Pixel Value";
11338c2ecf20Sopenharmony_ci
11348c2ecf20Sopenharmony_ci	/* Image processing controls */
11358c2ecf20Sopenharmony_ci	/* Keep the order of the 'case's the same as in v4l2-controls.h! */
11368c2ecf20Sopenharmony_ci	case V4L2_CID_IMAGE_PROC_CLASS:		return "Image Processing Controls";
11378c2ecf20Sopenharmony_ci	case V4L2_CID_LINK_FREQ:		return "Link Frequency";
11388c2ecf20Sopenharmony_ci	case V4L2_CID_PIXEL_RATE:		return "Pixel Rate";
11398c2ecf20Sopenharmony_ci	case V4L2_CID_TEST_PATTERN:		return "Test Pattern";
11408c2ecf20Sopenharmony_ci	case V4L2_CID_DEINTERLACING_MODE:	return "Deinterlacing Mode";
11418c2ecf20Sopenharmony_ci	case V4L2_CID_DIGITAL_GAIN:		return "Digital Gain";
11428c2ecf20Sopenharmony_ci
11438c2ecf20Sopenharmony_ci	/* DV controls */
11448c2ecf20Sopenharmony_ci	/* Keep the order of the 'case's the same as in v4l2-controls.h! */
11458c2ecf20Sopenharmony_ci	case V4L2_CID_DV_CLASS:			return "Digital Video Controls";
11468c2ecf20Sopenharmony_ci	case V4L2_CID_DV_TX_HOTPLUG:		return "Hotplug Present";
11478c2ecf20Sopenharmony_ci	case V4L2_CID_DV_TX_RXSENSE:		return "RxSense Present";
11488c2ecf20Sopenharmony_ci	case V4L2_CID_DV_TX_EDID_PRESENT:	return "EDID Present";
11498c2ecf20Sopenharmony_ci	case V4L2_CID_DV_TX_MODE:		return "Transmit Mode";
11508c2ecf20Sopenharmony_ci	case V4L2_CID_DV_TX_RGB_RANGE:		return "Tx RGB Quantization Range";
11518c2ecf20Sopenharmony_ci	case V4L2_CID_DV_TX_IT_CONTENT_TYPE:	return "Tx IT Content Type";
11528c2ecf20Sopenharmony_ci	case V4L2_CID_DV_RX_POWER_PRESENT:	return "Power Present";
11538c2ecf20Sopenharmony_ci	case V4L2_CID_DV_RX_RGB_RANGE:		return "Rx RGB Quantization Range";
11548c2ecf20Sopenharmony_ci	case V4L2_CID_DV_RX_IT_CONTENT_TYPE:	return "Rx IT Content Type";
11558c2ecf20Sopenharmony_ci
11568c2ecf20Sopenharmony_ci	case V4L2_CID_FM_RX_CLASS:		return "FM Radio Receiver Controls";
11578c2ecf20Sopenharmony_ci	case V4L2_CID_TUNE_DEEMPHASIS:		return "De-Emphasis";
11588c2ecf20Sopenharmony_ci	case V4L2_CID_RDS_RECEPTION:		return "RDS Reception";
11598c2ecf20Sopenharmony_ci	case V4L2_CID_RF_TUNER_CLASS:		return "RF Tuner Controls";
11608c2ecf20Sopenharmony_ci	case V4L2_CID_RF_TUNER_RF_GAIN:		return "RF Gain";
11618c2ecf20Sopenharmony_ci	case V4L2_CID_RF_TUNER_LNA_GAIN_AUTO:	return "LNA Gain, Auto";
11628c2ecf20Sopenharmony_ci	case V4L2_CID_RF_TUNER_LNA_GAIN:	return "LNA Gain";
11638c2ecf20Sopenharmony_ci	case V4L2_CID_RF_TUNER_MIXER_GAIN_AUTO:	return "Mixer Gain, Auto";
11648c2ecf20Sopenharmony_ci	case V4L2_CID_RF_TUNER_MIXER_GAIN:	return "Mixer Gain";
11658c2ecf20Sopenharmony_ci	case V4L2_CID_RF_TUNER_IF_GAIN_AUTO:	return "IF Gain, Auto";
11668c2ecf20Sopenharmony_ci	case V4L2_CID_RF_TUNER_IF_GAIN:		return "IF Gain";
11678c2ecf20Sopenharmony_ci	case V4L2_CID_RF_TUNER_BANDWIDTH_AUTO:	return "Bandwidth, Auto";
11688c2ecf20Sopenharmony_ci	case V4L2_CID_RF_TUNER_BANDWIDTH:	return "Bandwidth";
11698c2ecf20Sopenharmony_ci	case V4L2_CID_RF_TUNER_PLL_LOCK:	return "PLL Lock";
11708c2ecf20Sopenharmony_ci	case V4L2_CID_RDS_RX_PTY:		return "RDS Program Type";
11718c2ecf20Sopenharmony_ci	case V4L2_CID_RDS_RX_PS_NAME:		return "RDS PS Name";
11728c2ecf20Sopenharmony_ci	case V4L2_CID_RDS_RX_RADIO_TEXT:	return "RDS Radio Text";
11738c2ecf20Sopenharmony_ci	case V4L2_CID_RDS_RX_TRAFFIC_ANNOUNCEMENT: return "RDS Traffic Announcement";
11748c2ecf20Sopenharmony_ci	case V4L2_CID_RDS_RX_TRAFFIC_PROGRAM:	return "RDS Traffic Program";
11758c2ecf20Sopenharmony_ci	case V4L2_CID_RDS_RX_MUSIC_SPEECH:	return "RDS Music";
11768c2ecf20Sopenharmony_ci
11778c2ecf20Sopenharmony_ci	/* Detection controls */
11788c2ecf20Sopenharmony_ci	/* Keep the order of the 'case's the same as in v4l2-controls.h! */
11798c2ecf20Sopenharmony_ci	case V4L2_CID_DETECT_CLASS:		return "Detection Controls";
11808c2ecf20Sopenharmony_ci	case V4L2_CID_DETECT_MD_MODE:		return "Motion Detection Mode";
11818c2ecf20Sopenharmony_ci	case V4L2_CID_DETECT_MD_GLOBAL_THRESHOLD: return "MD Global Threshold";
11828c2ecf20Sopenharmony_ci	case V4L2_CID_DETECT_MD_THRESHOLD_GRID:	return "MD Threshold Grid";
11838c2ecf20Sopenharmony_ci	case V4L2_CID_DETECT_MD_REGION_GRID:	return "MD Region Grid";
11848c2ecf20Sopenharmony_ci	default:
11858c2ecf20Sopenharmony_ci		return NULL;
11868c2ecf20Sopenharmony_ci	}
11878c2ecf20Sopenharmony_ci}
11888c2ecf20Sopenharmony_ciEXPORT_SYMBOL(v4l2_ctrl_get_name);
11898c2ecf20Sopenharmony_ci
11908c2ecf20Sopenharmony_civoid v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
11918c2ecf20Sopenharmony_ci		    s64 *min, s64 *max, u64 *step, s64 *def, u32 *flags)
11928c2ecf20Sopenharmony_ci{
11938c2ecf20Sopenharmony_ci	*name = v4l2_ctrl_get_name(id);
11948c2ecf20Sopenharmony_ci	*flags = 0;
11958c2ecf20Sopenharmony_ci
11968c2ecf20Sopenharmony_ci	switch (id) {
11978c2ecf20Sopenharmony_ci	case V4L2_CID_AUDIO_MUTE:
11988c2ecf20Sopenharmony_ci	case V4L2_CID_AUDIO_LOUDNESS:
11998c2ecf20Sopenharmony_ci	case V4L2_CID_AUTO_WHITE_BALANCE:
12008c2ecf20Sopenharmony_ci	case V4L2_CID_AUTOGAIN:
12018c2ecf20Sopenharmony_ci	case V4L2_CID_HFLIP:
12028c2ecf20Sopenharmony_ci	case V4L2_CID_VFLIP:
12038c2ecf20Sopenharmony_ci	case V4L2_CID_HUE_AUTO:
12048c2ecf20Sopenharmony_ci	case V4L2_CID_CHROMA_AGC:
12058c2ecf20Sopenharmony_ci	case V4L2_CID_COLOR_KILLER:
12068c2ecf20Sopenharmony_ci	case V4L2_CID_AUTOBRIGHTNESS:
12078c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_AUDIO_MUTE:
12088c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_MUTE:
12098c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
12108c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_PULLDOWN:
12118c2ecf20Sopenharmony_ci	case V4L2_CID_EXPOSURE_AUTO_PRIORITY:
12128c2ecf20Sopenharmony_ci	case V4L2_CID_FOCUS_AUTO:
12138c2ecf20Sopenharmony_ci	case V4L2_CID_PRIVACY:
12148c2ecf20Sopenharmony_ci	case V4L2_CID_AUDIO_LIMITER_ENABLED:
12158c2ecf20Sopenharmony_ci	case V4L2_CID_AUDIO_COMPRESSION_ENABLED:
12168c2ecf20Sopenharmony_ci	case V4L2_CID_PILOT_TONE_ENABLED:
12178c2ecf20Sopenharmony_ci	case V4L2_CID_ILLUMINATORS_1:
12188c2ecf20Sopenharmony_ci	case V4L2_CID_ILLUMINATORS_2:
12198c2ecf20Sopenharmony_ci	case V4L2_CID_FLASH_STROBE_STATUS:
12208c2ecf20Sopenharmony_ci	case V4L2_CID_FLASH_CHARGE:
12218c2ecf20Sopenharmony_ci	case V4L2_CID_FLASH_READY:
12228c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_DECODER_MPEG4_DEBLOCK_FILTER:
12238c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_DECODER_SLICE_INTERFACE:
12248c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE:
12258c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_MB_RC_ENABLE:
12268c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_H264_8X8_TRANSFORM:
12278c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_ENABLE:
12288c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_MPEG4_QPEL:
12298c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_REPEAT_SEQ_HEADER:
12308c2ecf20Sopenharmony_ci	case V4L2_CID_WIDE_DYNAMIC_RANGE:
12318c2ecf20Sopenharmony_ci	case V4L2_CID_IMAGE_STABILIZATION:
12328c2ecf20Sopenharmony_ci	case V4L2_CID_RDS_RECEPTION:
12338c2ecf20Sopenharmony_ci	case V4L2_CID_RF_TUNER_LNA_GAIN_AUTO:
12348c2ecf20Sopenharmony_ci	case V4L2_CID_RF_TUNER_MIXER_GAIN_AUTO:
12358c2ecf20Sopenharmony_ci	case V4L2_CID_RF_TUNER_IF_GAIN_AUTO:
12368c2ecf20Sopenharmony_ci	case V4L2_CID_RF_TUNER_BANDWIDTH_AUTO:
12378c2ecf20Sopenharmony_ci	case V4L2_CID_RF_TUNER_PLL_LOCK:
12388c2ecf20Sopenharmony_ci	case V4L2_CID_RDS_TX_MONO_STEREO:
12398c2ecf20Sopenharmony_ci	case V4L2_CID_RDS_TX_ARTIFICIAL_HEAD:
12408c2ecf20Sopenharmony_ci	case V4L2_CID_RDS_TX_COMPRESSED:
12418c2ecf20Sopenharmony_ci	case V4L2_CID_RDS_TX_DYNAMIC_PTY:
12428c2ecf20Sopenharmony_ci	case V4L2_CID_RDS_TX_TRAFFIC_ANNOUNCEMENT:
12438c2ecf20Sopenharmony_ci	case V4L2_CID_RDS_TX_TRAFFIC_PROGRAM:
12448c2ecf20Sopenharmony_ci	case V4L2_CID_RDS_TX_MUSIC_SPEECH:
12458c2ecf20Sopenharmony_ci	case V4L2_CID_RDS_TX_ALT_FREQS_ENABLE:
12468c2ecf20Sopenharmony_ci	case V4L2_CID_RDS_RX_TRAFFIC_ANNOUNCEMENT:
12478c2ecf20Sopenharmony_ci	case V4L2_CID_RDS_RX_TRAFFIC_PROGRAM:
12488c2ecf20Sopenharmony_ci	case V4L2_CID_RDS_RX_MUSIC_SPEECH:
12498c2ecf20Sopenharmony_ci		*type = V4L2_CTRL_TYPE_BOOLEAN;
12508c2ecf20Sopenharmony_ci		*min = 0;
12518c2ecf20Sopenharmony_ci		*max = *step = 1;
12528c2ecf20Sopenharmony_ci		break;
12538c2ecf20Sopenharmony_ci	case V4L2_CID_ROTATE:
12548c2ecf20Sopenharmony_ci		*type = V4L2_CTRL_TYPE_INTEGER;
12558c2ecf20Sopenharmony_ci		*flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT;
12568c2ecf20Sopenharmony_ci		break;
12578c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_MV_H_SEARCH_RANGE:
12588c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_MV_V_SEARCH_RANGE:
12598c2ecf20Sopenharmony_ci		*type = V4L2_CTRL_TYPE_INTEGER;
12608c2ecf20Sopenharmony_ci		break;
12618c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME:
12628c2ecf20Sopenharmony_ci	case V4L2_CID_PAN_RESET:
12638c2ecf20Sopenharmony_ci	case V4L2_CID_TILT_RESET:
12648c2ecf20Sopenharmony_ci	case V4L2_CID_FLASH_STROBE:
12658c2ecf20Sopenharmony_ci	case V4L2_CID_FLASH_STROBE_STOP:
12668c2ecf20Sopenharmony_ci	case V4L2_CID_AUTO_FOCUS_START:
12678c2ecf20Sopenharmony_ci	case V4L2_CID_AUTO_FOCUS_STOP:
12688c2ecf20Sopenharmony_ci	case V4L2_CID_DO_WHITE_BALANCE:
12698c2ecf20Sopenharmony_ci		*type = V4L2_CTRL_TYPE_BUTTON;
12708c2ecf20Sopenharmony_ci		*flags |= V4L2_CTRL_FLAG_WRITE_ONLY |
12718c2ecf20Sopenharmony_ci			  V4L2_CTRL_FLAG_EXECUTE_ON_WRITE;
12728c2ecf20Sopenharmony_ci		*min = *max = *step = *def = 0;
12738c2ecf20Sopenharmony_ci		break;
12748c2ecf20Sopenharmony_ci	case V4L2_CID_POWER_LINE_FREQUENCY:
12758c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
12768c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_AUDIO_ENCODING:
12778c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_AUDIO_L1_BITRATE:
12788c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
12798c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_AUDIO_L3_BITRATE:
12808c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_AUDIO_AC3_BITRATE:
12818c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_AUDIO_MODE:
12828c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION:
12838c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_AUDIO_EMPHASIS:
12848c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_AUDIO_CRC:
12858c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_AUDIO_DEC_PLAYBACK:
12868c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_AUDIO_DEC_MULTILINGUAL_PLAYBACK:
12878c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_ENCODING:
12888c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_ASPECT:
12898c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
12908c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_STREAM_TYPE:
12918c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_STREAM_VBI_FMT:
12928c2ecf20Sopenharmony_ci	case V4L2_CID_EXPOSURE_AUTO:
12938c2ecf20Sopenharmony_ci	case V4L2_CID_AUTO_FOCUS_RANGE:
12948c2ecf20Sopenharmony_ci	case V4L2_CID_COLORFX:
12958c2ecf20Sopenharmony_ci	case V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE:
12968c2ecf20Sopenharmony_ci	case V4L2_CID_TUNE_PREEMPHASIS:
12978c2ecf20Sopenharmony_ci	case V4L2_CID_FLASH_LED_MODE:
12988c2ecf20Sopenharmony_ci	case V4L2_CID_FLASH_STROBE_SOURCE:
12998c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_HEADER_MODE:
13008c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_FRAME_SKIP_MODE:
13018c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE:
13028c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE:
13038c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_H264_LEVEL:
13048c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE:
13058c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
13068c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_IDC:
13078c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE:
13088c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_H264_FMO_MAP_TYPE:
13098c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_H264_DECODE_MODE:
13108c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_H264_START_CODE:
13118c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_MPEG2_LEVEL:
13128c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_MPEG2_PROFILE:
13138c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL:
13148c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE:
13158c2ecf20Sopenharmony_ci	case V4L2_CID_JPEG_CHROMA_SUBSAMPLING:
13168c2ecf20Sopenharmony_ci	case V4L2_CID_ISO_SENSITIVITY_AUTO:
13178c2ecf20Sopenharmony_ci	case V4L2_CID_EXPOSURE_METERING:
13188c2ecf20Sopenharmony_ci	case V4L2_CID_SCENE_MODE:
13198c2ecf20Sopenharmony_ci	case V4L2_CID_DV_TX_MODE:
13208c2ecf20Sopenharmony_ci	case V4L2_CID_DV_TX_RGB_RANGE:
13218c2ecf20Sopenharmony_ci	case V4L2_CID_DV_TX_IT_CONTENT_TYPE:
13228c2ecf20Sopenharmony_ci	case V4L2_CID_DV_RX_RGB_RANGE:
13238c2ecf20Sopenharmony_ci	case V4L2_CID_DV_RX_IT_CONTENT_TYPE:
13248c2ecf20Sopenharmony_ci	case V4L2_CID_TEST_PATTERN:
13258c2ecf20Sopenharmony_ci	case V4L2_CID_DEINTERLACING_MODE:
13268c2ecf20Sopenharmony_ci	case V4L2_CID_TUNE_DEEMPHASIS:
13278c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_SEL:
13288c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_VP8_PROFILE:
13298c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_VP9_PROFILE:
13308c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_VP9_LEVEL:
13318c2ecf20Sopenharmony_ci	case V4L2_CID_DETECT_MD_MODE:
13328c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_HEVC_PROFILE:
13338c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_HEVC_LEVEL:
13348c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_TYPE:
13358c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_HEVC_REFRESH_TYPE:
13368c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_HEVC_SIZE_OF_LENGTH_FIELD:
13378c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_HEVC_TIER:
13388c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_HEVC_LOOP_FILTER_MODE:
13398c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_HEVC_DECODE_MODE:
13408c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_HEVC_START_CODE:
13418c2ecf20Sopenharmony_ci	case V4L2_CID_CAMERA_ORIENTATION:
13428c2ecf20Sopenharmony_ci		*type = V4L2_CTRL_TYPE_MENU;
13438c2ecf20Sopenharmony_ci		break;
13448c2ecf20Sopenharmony_ci	case V4L2_CID_LINK_FREQ:
13458c2ecf20Sopenharmony_ci		*type = V4L2_CTRL_TYPE_INTEGER_MENU;
13468c2ecf20Sopenharmony_ci		break;
13478c2ecf20Sopenharmony_ci	case V4L2_CID_RDS_TX_PS_NAME:
13488c2ecf20Sopenharmony_ci	case V4L2_CID_RDS_TX_RADIO_TEXT:
13498c2ecf20Sopenharmony_ci	case V4L2_CID_RDS_RX_PS_NAME:
13508c2ecf20Sopenharmony_ci	case V4L2_CID_RDS_RX_RADIO_TEXT:
13518c2ecf20Sopenharmony_ci		*type = V4L2_CTRL_TYPE_STRING;
13528c2ecf20Sopenharmony_ci		break;
13538c2ecf20Sopenharmony_ci	case V4L2_CID_ISO_SENSITIVITY:
13548c2ecf20Sopenharmony_ci	case V4L2_CID_AUTO_EXPOSURE_BIAS:
13558c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_VPX_NUM_PARTITIONS:
13568c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_VPX_NUM_REF_FRAMES:
13578c2ecf20Sopenharmony_ci		*type = V4L2_CTRL_TYPE_INTEGER_MENU;
13588c2ecf20Sopenharmony_ci		break;
13598c2ecf20Sopenharmony_ci	case V4L2_CID_USER_CLASS:
13608c2ecf20Sopenharmony_ci	case V4L2_CID_CAMERA_CLASS:
13618c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_CLASS:
13628c2ecf20Sopenharmony_ci	case V4L2_CID_FM_TX_CLASS:
13638c2ecf20Sopenharmony_ci	case V4L2_CID_FLASH_CLASS:
13648c2ecf20Sopenharmony_ci	case V4L2_CID_JPEG_CLASS:
13658c2ecf20Sopenharmony_ci	case V4L2_CID_IMAGE_SOURCE_CLASS:
13668c2ecf20Sopenharmony_ci	case V4L2_CID_IMAGE_PROC_CLASS:
13678c2ecf20Sopenharmony_ci	case V4L2_CID_DV_CLASS:
13688c2ecf20Sopenharmony_ci	case V4L2_CID_FM_RX_CLASS:
13698c2ecf20Sopenharmony_ci	case V4L2_CID_RF_TUNER_CLASS:
13708c2ecf20Sopenharmony_ci	case V4L2_CID_DETECT_CLASS:
13718c2ecf20Sopenharmony_ci		*type = V4L2_CTRL_TYPE_CTRL_CLASS;
13728c2ecf20Sopenharmony_ci		/* You can neither read not write these */
13738c2ecf20Sopenharmony_ci		*flags |= V4L2_CTRL_FLAG_READ_ONLY | V4L2_CTRL_FLAG_WRITE_ONLY;
13748c2ecf20Sopenharmony_ci		*min = *max = *step = *def = 0;
13758c2ecf20Sopenharmony_ci		break;
13768c2ecf20Sopenharmony_ci	case V4L2_CID_BG_COLOR:
13778c2ecf20Sopenharmony_ci		*type = V4L2_CTRL_TYPE_INTEGER;
13788c2ecf20Sopenharmony_ci		*step = 1;
13798c2ecf20Sopenharmony_ci		*min = 0;
13808c2ecf20Sopenharmony_ci		/* Max is calculated as RGB888 that is 2^24 */
13818c2ecf20Sopenharmony_ci		*max = 0xFFFFFF;
13828c2ecf20Sopenharmony_ci		break;
13838c2ecf20Sopenharmony_ci	case V4L2_CID_FLASH_FAULT:
13848c2ecf20Sopenharmony_ci	case V4L2_CID_JPEG_ACTIVE_MARKER:
13858c2ecf20Sopenharmony_ci	case V4L2_CID_3A_LOCK:
13868c2ecf20Sopenharmony_ci	case V4L2_CID_AUTO_FOCUS_STATUS:
13878c2ecf20Sopenharmony_ci	case V4L2_CID_DV_TX_HOTPLUG:
13888c2ecf20Sopenharmony_ci	case V4L2_CID_DV_TX_RXSENSE:
13898c2ecf20Sopenharmony_ci	case V4L2_CID_DV_TX_EDID_PRESENT:
13908c2ecf20Sopenharmony_ci	case V4L2_CID_DV_RX_POWER_PRESENT:
13918c2ecf20Sopenharmony_ci		*type = V4L2_CTRL_TYPE_BITMASK;
13928c2ecf20Sopenharmony_ci		break;
13938c2ecf20Sopenharmony_ci	case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE:
13948c2ecf20Sopenharmony_ci	case V4L2_CID_MIN_BUFFERS_FOR_OUTPUT:
13958c2ecf20Sopenharmony_ci		*type = V4L2_CTRL_TYPE_INTEGER;
13968c2ecf20Sopenharmony_ci		*flags |= V4L2_CTRL_FLAG_READ_ONLY;
13978c2ecf20Sopenharmony_ci		break;
13988c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_DEC_PTS:
13998c2ecf20Sopenharmony_ci		*type = V4L2_CTRL_TYPE_INTEGER64;
14008c2ecf20Sopenharmony_ci		*flags |= V4L2_CTRL_FLAG_VOLATILE | V4L2_CTRL_FLAG_READ_ONLY;
14018c2ecf20Sopenharmony_ci		*min = *def = 0;
14028c2ecf20Sopenharmony_ci		*max = 0x1ffffffffLL;
14038c2ecf20Sopenharmony_ci		*step = 1;
14048c2ecf20Sopenharmony_ci		break;
14058c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_DEC_FRAME:
14068c2ecf20Sopenharmony_ci		*type = V4L2_CTRL_TYPE_INTEGER64;
14078c2ecf20Sopenharmony_ci		*flags |= V4L2_CTRL_FLAG_VOLATILE | V4L2_CTRL_FLAG_READ_ONLY;
14088c2ecf20Sopenharmony_ci		*min = *def = 0;
14098c2ecf20Sopenharmony_ci		*max = 0x7fffffffffffffffLL;
14108c2ecf20Sopenharmony_ci		*step = 1;
14118c2ecf20Sopenharmony_ci		break;
14128c2ecf20Sopenharmony_ci	case V4L2_CID_PIXEL_RATE:
14138c2ecf20Sopenharmony_ci		*type = V4L2_CTRL_TYPE_INTEGER64;
14148c2ecf20Sopenharmony_ci		*flags |= V4L2_CTRL_FLAG_READ_ONLY;
14158c2ecf20Sopenharmony_ci		break;
14168c2ecf20Sopenharmony_ci	case V4L2_CID_DETECT_MD_REGION_GRID:
14178c2ecf20Sopenharmony_ci		*type = V4L2_CTRL_TYPE_U8;
14188c2ecf20Sopenharmony_ci		break;
14198c2ecf20Sopenharmony_ci	case V4L2_CID_DETECT_MD_THRESHOLD_GRID:
14208c2ecf20Sopenharmony_ci		*type = V4L2_CTRL_TYPE_U16;
14218c2ecf20Sopenharmony_ci		break;
14228c2ecf20Sopenharmony_ci	case V4L2_CID_RDS_TX_ALT_FREQS:
14238c2ecf20Sopenharmony_ci		*type = V4L2_CTRL_TYPE_U32;
14248c2ecf20Sopenharmony_ci		break;
14258c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_MPEG2_SLICE_PARAMS:
14268c2ecf20Sopenharmony_ci		*type = V4L2_CTRL_TYPE_MPEG2_SLICE_PARAMS;
14278c2ecf20Sopenharmony_ci		break;
14288c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_MPEG2_QUANTIZATION:
14298c2ecf20Sopenharmony_ci		*type = V4L2_CTRL_TYPE_MPEG2_QUANTIZATION;
14308c2ecf20Sopenharmony_ci		break;
14318c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_FWHT_PARAMS:
14328c2ecf20Sopenharmony_ci		*type = V4L2_CTRL_TYPE_FWHT_PARAMS;
14338c2ecf20Sopenharmony_ci		break;
14348c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_H264_SPS:
14358c2ecf20Sopenharmony_ci		*type = V4L2_CTRL_TYPE_H264_SPS;
14368c2ecf20Sopenharmony_ci		break;
14378c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_H264_PPS:
14388c2ecf20Sopenharmony_ci		*type = V4L2_CTRL_TYPE_H264_PPS;
14398c2ecf20Sopenharmony_ci		break;
14408c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_H264_SCALING_MATRIX:
14418c2ecf20Sopenharmony_ci		*type = V4L2_CTRL_TYPE_H264_SCALING_MATRIX;
14428c2ecf20Sopenharmony_ci		break;
14438c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_H264_SLICE_PARAMS:
14448c2ecf20Sopenharmony_ci		*type = V4L2_CTRL_TYPE_H264_SLICE_PARAMS;
14458c2ecf20Sopenharmony_ci		break;
14468c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_H264_DECODE_PARAMS:
14478c2ecf20Sopenharmony_ci		*type = V4L2_CTRL_TYPE_H264_DECODE_PARAMS;
14488c2ecf20Sopenharmony_ci		break;
14498c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_H264_PRED_WEIGHTS:
14508c2ecf20Sopenharmony_ci		*type = V4L2_CTRL_TYPE_H264_PRED_WEIGHTS;
14518c2ecf20Sopenharmony_ci		break;
14528c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_VP8_FRAME_HEADER:
14538c2ecf20Sopenharmony_ci		*type = V4L2_CTRL_TYPE_VP8_FRAME_HEADER;
14548c2ecf20Sopenharmony_ci		break;
14558c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_HEVC_SPS:
14568c2ecf20Sopenharmony_ci		*type = V4L2_CTRL_TYPE_HEVC_SPS;
14578c2ecf20Sopenharmony_ci		break;
14588c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_HEVC_PPS:
14598c2ecf20Sopenharmony_ci		*type = V4L2_CTRL_TYPE_HEVC_PPS;
14608c2ecf20Sopenharmony_ci		break;
14618c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS:
14628c2ecf20Sopenharmony_ci		*type = V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS;
14638c2ecf20Sopenharmony_ci		break;
14648c2ecf20Sopenharmony_ci	case V4L2_CID_UNIT_CELL_SIZE:
14658c2ecf20Sopenharmony_ci		*type = V4L2_CTRL_TYPE_AREA;
14668c2ecf20Sopenharmony_ci		*flags |= V4L2_CTRL_FLAG_READ_ONLY;
14678c2ecf20Sopenharmony_ci		break;
14688c2ecf20Sopenharmony_ci	default:
14698c2ecf20Sopenharmony_ci		*type = V4L2_CTRL_TYPE_INTEGER;
14708c2ecf20Sopenharmony_ci		break;
14718c2ecf20Sopenharmony_ci	}
14728c2ecf20Sopenharmony_ci	switch (id) {
14738c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_AUDIO_ENCODING:
14748c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_AUDIO_MODE:
14758c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
14768c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_VIDEO_B_FRAMES:
14778c2ecf20Sopenharmony_ci	case V4L2_CID_MPEG_STREAM_TYPE:
14788c2ecf20Sopenharmony_ci		*flags |= V4L2_CTRL_FLAG_UPDATE;
14798c2ecf20Sopenharmony_ci		break;
14808c2ecf20Sopenharmony_ci	case V4L2_CID_AUDIO_VOLUME:
14818c2ecf20Sopenharmony_ci	case V4L2_CID_AUDIO_BALANCE:
14828c2ecf20Sopenharmony_ci	case V4L2_CID_AUDIO_BASS:
14838c2ecf20Sopenharmony_ci	case V4L2_CID_AUDIO_TREBLE:
14848c2ecf20Sopenharmony_ci	case V4L2_CID_BRIGHTNESS:
14858c2ecf20Sopenharmony_ci	case V4L2_CID_CONTRAST:
14868c2ecf20Sopenharmony_ci	case V4L2_CID_SATURATION:
14878c2ecf20Sopenharmony_ci	case V4L2_CID_HUE:
14888c2ecf20Sopenharmony_ci	case V4L2_CID_RED_BALANCE:
14898c2ecf20Sopenharmony_ci	case V4L2_CID_BLUE_BALANCE:
14908c2ecf20Sopenharmony_ci	case V4L2_CID_GAMMA:
14918c2ecf20Sopenharmony_ci	case V4L2_CID_SHARPNESS:
14928c2ecf20Sopenharmony_ci	case V4L2_CID_CHROMA_GAIN:
14938c2ecf20Sopenharmony_ci	case V4L2_CID_RDS_TX_DEVIATION:
14948c2ecf20Sopenharmony_ci	case V4L2_CID_AUDIO_LIMITER_RELEASE_TIME:
14958c2ecf20Sopenharmony_ci	case V4L2_CID_AUDIO_LIMITER_DEVIATION:
14968c2ecf20Sopenharmony_ci	case V4L2_CID_AUDIO_COMPRESSION_GAIN:
14978c2ecf20Sopenharmony_ci	case V4L2_CID_AUDIO_COMPRESSION_THRESHOLD:
14988c2ecf20Sopenharmony_ci	case V4L2_CID_AUDIO_COMPRESSION_ATTACK_TIME:
14998c2ecf20Sopenharmony_ci	case V4L2_CID_AUDIO_COMPRESSION_RELEASE_TIME:
15008c2ecf20Sopenharmony_ci	case V4L2_CID_PILOT_TONE_DEVIATION:
15018c2ecf20Sopenharmony_ci	case V4L2_CID_PILOT_TONE_FREQUENCY:
15028c2ecf20Sopenharmony_ci	case V4L2_CID_TUNE_POWER_LEVEL:
15038c2ecf20Sopenharmony_ci	case V4L2_CID_TUNE_ANTENNA_CAPACITOR:
15048c2ecf20Sopenharmony_ci	case V4L2_CID_RF_TUNER_RF_GAIN:
15058c2ecf20Sopenharmony_ci	case V4L2_CID_RF_TUNER_LNA_GAIN:
15068c2ecf20Sopenharmony_ci	case V4L2_CID_RF_TUNER_MIXER_GAIN:
15078c2ecf20Sopenharmony_ci	case V4L2_CID_RF_TUNER_IF_GAIN:
15088c2ecf20Sopenharmony_ci	case V4L2_CID_RF_TUNER_BANDWIDTH:
15098c2ecf20Sopenharmony_ci	case V4L2_CID_DETECT_MD_GLOBAL_THRESHOLD:
15108c2ecf20Sopenharmony_ci		*flags |= V4L2_CTRL_FLAG_SLIDER;
15118c2ecf20Sopenharmony_ci		break;
15128c2ecf20Sopenharmony_ci	case V4L2_CID_PAN_RELATIVE:
15138c2ecf20Sopenharmony_ci	case V4L2_CID_TILT_RELATIVE:
15148c2ecf20Sopenharmony_ci	case V4L2_CID_FOCUS_RELATIVE:
15158c2ecf20Sopenharmony_ci	case V4L2_CID_IRIS_RELATIVE:
15168c2ecf20Sopenharmony_ci	case V4L2_CID_ZOOM_RELATIVE:
15178c2ecf20Sopenharmony_ci		*flags |= V4L2_CTRL_FLAG_WRITE_ONLY |
15188c2ecf20Sopenharmony_ci			  V4L2_CTRL_FLAG_EXECUTE_ON_WRITE;
15198c2ecf20Sopenharmony_ci		break;
15208c2ecf20Sopenharmony_ci	case V4L2_CID_FLASH_STROBE_STATUS:
15218c2ecf20Sopenharmony_ci	case V4L2_CID_AUTO_FOCUS_STATUS:
15228c2ecf20Sopenharmony_ci	case V4L2_CID_FLASH_READY:
15238c2ecf20Sopenharmony_ci	case V4L2_CID_DV_TX_HOTPLUG:
15248c2ecf20Sopenharmony_ci	case V4L2_CID_DV_TX_RXSENSE:
15258c2ecf20Sopenharmony_ci	case V4L2_CID_DV_TX_EDID_PRESENT:
15268c2ecf20Sopenharmony_ci	case V4L2_CID_DV_RX_POWER_PRESENT:
15278c2ecf20Sopenharmony_ci	case V4L2_CID_DV_RX_IT_CONTENT_TYPE:
15288c2ecf20Sopenharmony_ci	case V4L2_CID_RDS_RX_PTY:
15298c2ecf20Sopenharmony_ci	case V4L2_CID_RDS_RX_PS_NAME:
15308c2ecf20Sopenharmony_ci	case V4L2_CID_RDS_RX_RADIO_TEXT:
15318c2ecf20Sopenharmony_ci	case V4L2_CID_RDS_RX_TRAFFIC_ANNOUNCEMENT:
15328c2ecf20Sopenharmony_ci	case V4L2_CID_RDS_RX_TRAFFIC_PROGRAM:
15338c2ecf20Sopenharmony_ci	case V4L2_CID_RDS_RX_MUSIC_SPEECH:
15348c2ecf20Sopenharmony_ci	case V4L2_CID_CAMERA_ORIENTATION:
15358c2ecf20Sopenharmony_ci	case V4L2_CID_CAMERA_SENSOR_ROTATION:
15368c2ecf20Sopenharmony_ci		*flags |= V4L2_CTRL_FLAG_READ_ONLY;
15378c2ecf20Sopenharmony_ci		break;
15388c2ecf20Sopenharmony_ci	case V4L2_CID_RF_TUNER_PLL_LOCK:
15398c2ecf20Sopenharmony_ci		*flags |= V4L2_CTRL_FLAG_VOLATILE;
15408c2ecf20Sopenharmony_ci		break;
15418c2ecf20Sopenharmony_ci	}
15428c2ecf20Sopenharmony_ci}
15438c2ecf20Sopenharmony_ciEXPORT_SYMBOL(v4l2_ctrl_fill);
15448c2ecf20Sopenharmony_ci
15458c2ecf20Sopenharmony_cistatic u32 user_flags(const struct v4l2_ctrl *ctrl)
15468c2ecf20Sopenharmony_ci{
15478c2ecf20Sopenharmony_ci	u32 flags = ctrl->flags;
15488c2ecf20Sopenharmony_ci
15498c2ecf20Sopenharmony_ci	if (ctrl->is_ptr)
15508c2ecf20Sopenharmony_ci		flags |= V4L2_CTRL_FLAG_HAS_PAYLOAD;
15518c2ecf20Sopenharmony_ci
15528c2ecf20Sopenharmony_ci	return flags;
15538c2ecf20Sopenharmony_ci}
15548c2ecf20Sopenharmony_ci
15558c2ecf20Sopenharmony_cistatic void fill_event(struct v4l2_event *ev, struct v4l2_ctrl *ctrl, u32 changes)
15568c2ecf20Sopenharmony_ci{
15578c2ecf20Sopenharmony_ci	memset(ev, 0, sizeof(*ev));
15588c2ecf20Sopenharmony_ci	ev->type = V4L2_EVENT_CTRL;
15598c2ecf20Sopenharmony_ci	ev->id = ctrl->id;
15608c2ecf20Sopenharmony_ci	ev->u.ctrl.changes = changes;
15618c2ecf20Sopenharmony_ci	ev->u.ctrl.type = ctrl->type;
15628c2ecf20Sopenharmony_ci	ev->u.ctrl.flags = user_flags(ctrl);
15638c2ecf20Sopenharmony_ci	if (ctrl->is_ptr)
15648c2ecf20Sopenharmony_ci		ev->u.ctrl.value64 = 0;
15658c2ecf20Sopenharmony_ci	else
15668c2ecf20Sopenharmony_ci		ev->u.ctrl.value64 = *ctrl->p_cur.p_s64;
15678c2ecf20Sopenharmony_ci	ev->u.ctrl.minimum = ctrl->minimum;
15688c2ecf20Sopenharmony_ci	ev->u.ctrl.maximum = ctrl->maximum;
15698c2ecf20Sopenharmony_ci	if (ctrl->type == V4L2_CTRL_TYPE_MENU
15708c2ecf20Sopenharmony_ci	    || ctrl->type == V4L2_CTRL_TYPE_INTEGER_MENU)
15718c2ecf20Sopenharmony_ci		ev->u.ctrl.step = 1;
15728c2ecf20Sopenharmony_ci	else
15738c2ecf20Sopenharmony_ci		ev->u.ctrl.step = ctrl->step;
15748c2ecf20Sopenharmony_ci	ev->u.ctrl.default_value = ctrl->default_value;
15758c2ecf20Sopenharmony_ci}
15768c2ecf20Sopenharmony_ci
15778c2ecf20Sopenharmony_cistatic void send_event(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl, u32 changes)
15788c2ecf20Sopenharmony_ci{
15798c2ecf20Sopenharmony_ci	struct v4l2_event ev;
15808c2ecf20Sopenharmony_ci	struct v4l2_subscribed_event *sev;
15818c2ecf20Sopenharmony_ci
15828c2ecf20Sopenharmony_ci	if (list_empty(&ctrl->ev_subs))
15838c2ecf20Sopenharmony_ci		return;
15848c2ecf20Sopenharmony_ci	fill_event(&ev, ctrl, changes);
15858c2ecf20Sopenharmony_ci
15868c2ecf20Sopenharmony_ci	list_for_each_entry(sev, &ctrl->ev_subs, node)
15878c2ecf20Sopenharmony_ci		if (sev->fh != fh ||
15888c2ecf20Sopenharmony_ci		    (sev->flags & V4L2_EVENT_SUB_FL_ALLOW_FEEDBACK))
15898c2ecf20Sopenharmony_ci			v4l2_event_queue_fh(sev->fh, &ev);
15908c2ecf20Sopenharmony_ci}
15918c2ecf20Sopenharmony_ci
15928c2ecf20Sopenharmony_cistatic bool std_equal(const struct v4l2_ctrl *ctrl, u32 idx,
15938c2ecf20Sopenharmony_ci		      union v4l2_ctrl_ptr ptr1,
15948c2ecf20Sopenharmony_ci		      union v4l2_ctrl_ptr ptr2)
15958c2ecf20Sopenharmony_ci{
15968c2ecf20Sopenharmony_ci	switch (ctrl->type) {
15978c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_BUTTON:
15988c2ecf20Sopenharmony_ci		return false;
15998c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_STRING:
16008c2ecf20Sopenharmony_ci		idx *= ctrl->elem_size;
16018c2ecf20Sopenharmony_ci		/* strings are always 0-terminated */
16028c2ecf20Sopenharmony_ci		return !strcmp(ptr1.p_char + idx, ptr2.p_char + idx);
16038c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_INTEGER64:
16048c2ecf20Sopenharmony_ci		return ptr1.p_s64[idx] == ptr2.p_s64[idx];
16058c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_U8:
16068c2ecf20Sopenharmony_ci		return ptr1.p_u8[idx] == ptr2.p_u8[idx];
16078c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_U16:
16088c2ecf20Sopenharmony_ci		return ptr1.p_u16[idx] == ptr2.p_u16[idx];
16098c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_U32:
16108c2ecf20Sopenharmony_ci		return ptr1.p_u32[idx] == ptr2.p_u32[idx];
16118c2ecf20Sopenharmony_ci	default:
16128c2ecf20Sopenharmony_ci		if (ctrl->is_int)
16138c2ecf20Sopenharmony_ci			return ptr1.p_s32[idx] == ptr2.p_s32[idx];
16148c2ecf20Sopenharmony_ci		idx *= ctrl->elem_size;
16158c2ecf20Sopenharmony_ci		return !memcmp(ptr1.p_const + idx, ptr2.p_const + idx,
16168c2ecf20Sopenharmony_ci			       ctrl->elem_size);
16178c2ecf20Sopenharmony_ci	}
16188c2ecf20Sopenharmony_ci}
16198c2ecf20Sopenharmony_ci
16208c2ecf20Sopenharmony_cistatic void std_init_compound(const struct v4l2_ctrl *ctrl, u32 idx,
16218c2ecf20Sopenharmony_ci			      union v4l2_ctrl_ptr ptr)
16228c2ecf20Sopenharmony_ci{
16238c2ecf20Sopenharmony_ci	struct v4l2_ctrl_mpeg2_slice_params *p_mpeg2_slice_params;
16248c2ecf20Sopenharmony_ci	void *p = ptr.p + idx * ctrl->elem_size;
16258c2ecf20Sopenharmony_ci
16268c2ecf20Sopenharmony_ci	if (ctrl->p_def.p_const)
16278c2ecf20Sopenharmony_ci		memcpy(p, ctrl->p_def.p_const, ctrl->elem_size);
16288c2ecf20Sopenharmony_ci	else
16298c2ecf20Sopenharmony_ci		memset(p, 0, ctrl->elem_size);
16308c2ecf20Sopenharmony_ci
16318c2ecf20Sopenharmony_ci	/*
16328c2ecf20Sopenharmony_ci	 * The cast is needed to get rid of a gcc warning complaining that
16338c2ecf20Sopenharmony_ci	 * V4L2_CTRL_TYPE_MPEG2_SLICE_PARAMS is not part of the
16348c2ecf20Sopenharmony_ci	 * v4l2_ctrl_type enum.
16358c2ecf20Sopenharmony_ci	 */
16368c2ecf20Sopenharmony_ci	switch ((u32)ctrl->type) {
16378c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_MPEG2_SLICE_PARAMS:
16388c2ecf20Sopenharmony_ci		p_mpeg2_slice_params = p;
16398c2ecf20Sopenharmony_ci		/* 4:2:0 */
16408c2ecf20Sopenharmony_ci		p_mpeg2_slice_params->sequence.chroma_format = 1;
16418c2ecf20Sopenharmony_ci		/* interlaced top field */
16428c2ecf20Sopenharmony_ci		p_mpeg2_slice_params->picture.picture_structure = 1;
16438c2ecf20Sopenharmony_ci		p_mpeg2_slice_params->picture.picture_coding_type =
16448c2ecf20Sopenharmony_ci					V4L2_MPEG2_PICTURE_CODING_TYPE_I;
16458c2ecf20Sopenharmony_ci		break;
16468c2ecf20Sopenharmony_ci	}
16478c2ecf20Sopenharmony_ci}
16488c2ecf20Sopenharmony_ci
16498c2ecf20Sopenharmony_cistatic void std_init(const struct v4l2_ctrl *ctrl, u32 idx,
16508c2ecf20Sopenharmony_ci		     union v4l2_ctrl_ptr ptr)
16518c2ecf20Sopenharmony_ci{
16528c2ecf20Sopenharmony_ci	switch (ctrl->type) {
16538c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_STRING:
16548c2ecf20Sopenharmony_ci		idx *= ctrl->elem_size;
16558c2ecf20Sopenharmony_ci		memset(ptr.p_char + idx, ' ', ctrl->minimum);
16568c2ecf20Sopenharmony_ci		ptr.p_char[idx + ctrl->minimum] = '\0';
16578c2ecf20Sopenharmony_ci		break;
16588c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_INTEGER64:
16598c2ecf20Sopenharmony_ci		ptr.p_s64[idx] = ctrl->default_value;
16608c2ecf20Sopenharmony_ci		break;
16618c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_INTEGER:
16628c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_INTEGER_MENU:
16638c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_MENU:
16648c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_BITMASK:
16658c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_BOOLEAN:
16668c2ecf20Sopenharmony_ci		ptr.p_s32[idx] = ctrl->default_value;
16678c2ecf20Sopenharmony_ci		break;
16688c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_BUTTON:
16698c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_CTRL_CLASS:
16708c2ecf20Sopenharmony_ci		ptr.p_s32[idx] = 0;
16718c2ecf20Sopenharmony_ci		break;
16728c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_U8:
16738c2ecf20Sopenharmony_ci		ptr.p_u8[idx] = ctrl->default_value;
16748c2ecf20Sopenharmony_ci		break;
16758c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_U16:
16768c2ecf20Sopenharmony_ci		ptr.p_u16[idx] = ctrl->default_value;
16778c2ecf20Sopenharmony_ci		break;
16788c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_U32:
16798c2ecf20Sopenharmony_ci		ptr.p_u32[idx] = ctrl->default_value;
16808c2ecf20Sopenharmony_ci		break;
16818c2ecf20Sopenharmony_ci	default:
16828c2ecf20Sopenharmony_ci		std_init_compound(ctrl, idx, ptr);
16838c2ecf20Sopenharmony_ci		break;
16848c2ecf20Sopenharmony_ci	}
16858c2ecf20Sopenharmony_ci}
16868c2ecf20Sopenharmony_ci
16878c2ecf20Sopenharmony_cistatic void std_log(const struct v4l2_ctrl *ctrl)
16888c2ecf20Sopenharmony_ci{
16898c2ecf20Sopenharmony_ci	union v4l2_ctrl_ptr ptr = ctrl->p_cur;
16908c2ecf20Sopenharmony_ci
16918c2ecf20Sopenharmony_ci	if (ctrl->is_array) {
16928c2ecf20Sopenharmony_ci		unsigned i;
16938c2ecf20Sopenharmony_ci
16948c2ecf20Sopenharmony_ci		for (i = 0; i < ctrl->nr_of_dims; i++)
16958c2ecf20Sopenharmony_ci			pr_cont("[%u]", ctrl->dims[i]);
16968c2ecf20Sopenharmony_ci		pr_cont(" ");
16978c2ecf20Sopenharmony_ci	}
16988c2ecf20Sopenharmony_ci
16998c2ecf20Sopenharmony_ci	switch (ctrl->type) {
17008c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_INTEGER:
17018c2ecf20Sopenharmony_ci		pr_cont("%d", *ptr.p_s32);
17028c2ecf20Sopenharmony_ci		break;
17038c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_BOOLEAN:
17048c2ecf20Sopenharmony_ci		pr_cont("%s", *ptr.p_s32 ? "true" : "false");
17058c2ecf20Sopenharmony_ci		break;
17068c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_MENU:
17078c2ecf20Sopenharmony_ci		pr_cont("%s", ctrl->qmenu[*ptr.p_s32]);
17088c2ecf20Sopenharmony_ci		break;
17098c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_INTEGER_MENU:
17108c2ecf20Sopenharmony_ci		pr_cont("%lld", ctrl->qmenu_int[*ptr.p_s32]);
17118c2ecf20Sopenharmony_ci		break;
17128c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_BITMASK:
17138c2ecf20Sopenharmony_ci		pr_cont("0x%08x", *ptr.p_s32);
17148c2ecf20Sopenharmony_ci		break;
17158c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_INTEGER64:
17168c2ecf20Sopenharmony_ci		pr_cont("%lld", *ptr.p_s64);
17178c2ecf20Sopenharmony_ci		break;
17188c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_STRING:
17198c2ecf20Sopenharmony_ci		pr_cont("%s", ptr.p_char);
17208c2ecf20Sopenharmony_ci		break;
17218c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_U8:
17228c2ecf20Sopenharmony_ci		pr_cont("%u", (unsigned)*ptr.p_u8);
17238c2ecf20Sopenharmony_ci		break;
17248c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_U16:
17258c2ecf20Sopenharmony_ci		pr_cont("%u", (unsigned)*ptr.p_u16);
17268c2ecf20Sopenharmony_ci		break;
17278c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_U32:
17288c2ecf20Sopenharmony_ci		pr_cont("%u", (unsigned)*ptr.p_u32);
17298c2ecf20Sopenharmony_ci		break;
17308c2ecf20Sopenharmony_ci	default:
17318c2ecf20Sopenharmony_ci		pr_cont("unknown type %d", ctrl->type);
17328c2ecf20Sopenharmony_ci		break;
17338c2ecf20Sopenharmony_ci	}
17348c2ecf20Sopenharmony_ci}
17358c2ecf20Sopenharmony_ci
17368c2ecf20Sopenharmony_ci/*
17378c2ecf20Sopenharmony_ci * Round towards the closest legal value. Be careful when we are
17388c2ecf20Sopenharmony_ci * close to the maximum range of the control type to prevent
17398c2ecf20Sopenharmony_ci * wrap-arounds.
17408c2ecf20Sopenharmony_ci */
17418c2ecf20Sopenharmony_ci#define ROUND_TO_RANGE(val, offset_type, ctrl)			\
17428c2ecf20Sopenharmony_ci({								\
17438c2ecf20Sopenharmony_ci	offset_type offset;					\
17448c2ecf20Sopenharmony_ci	if ((ctrl)->maximum >= 0 &&				\
17458c2ecf20Sopenharmony_ci	    val >= (ctrl)->maximum - (s32)((ctrl)->step / 2))	\
17468c2ecf20Sopenharmony_ci		val = (ctrl)->maximum;				\
17478c2ecf20Sopenharmony_ci	else							\
17488c2ecf20Sopenharmony_ci		val += (s32)((ctrl)->step / 2);			\
17498c2ecf20Sopenharmony_ci	val = clamp_t(typeof(val), val,				\
17508c2ecf20Sopenharmony_ci		      (ctrl)->minimum, (ctrl)->maximum);	\
17518c2ecf20Sopenharmony_ci	offset = (val) - (ctrl)->minimum;			\
17528c2ecf20Sopenharmony_ci	offset = (ctrl)->step * (offset / (u32)(ctrl)->step);	\
17538c2ecf20Sopenharmony_ci	val = (ctrl)->minimum + offset;				\
17548c2ecf20Sopenharmony_ci	0;							\
17558c2ecf20Sopenharmony_ci})
17568c2ecf20Sopenharmony_ci
17578c2ecf20Sopenharmony_ci/* Validate a new control */
17588c2ecf20Sopenharmony_ci
17598c2ecf20Sopenharmony_ci#define zero_padding(s) \
17608c2ecf20Sopenharmony_ci	memset(&(s).padding, 0, sizeof((s).padding))
17618c2ecf20Sopenharmony_ci#define zero_reserved(s) \
17628c2ecf20Sopenharmony_ci	memset(&(s).reserved, 0, sizeof((s).reserved))
17638c2ecf20Sopenharmony_ci
17648c2ecf20Sopenharmony_ci/*
17658c2ecf20Sopenharmony_ci * Compound controls validation requires setting unused fields/flags to zero
17668c2ecf20Sopenharmony_ci * in order to properly detect unchanged controls with std_equal's memcmp.
17678c2ecf20Sopenharmony_ci */
17688c2ecf20Sopenharmony_cistatic int std_validate_compound(const struct v4l2_ctrl *ctrl, u32 idx,
17698c2ecf20Sopenharmony_ci				 union v4l2_ctrl_ptr ptr)
17708c2ecf20Sopenharmony_ci{
17718c2ecf20Sopenharmony_ci	struct v4l2_ctrl_mpeg2_slice_params *p_mpeg2_slice_params;
17728c2ecf20Sopenharmony_ci	struct v4l2_ctrl_vp8_frame_header *p_vp8_frame_header;
17738c2ecf20Sopenharmony_ci	struct v4l2_ctrl_h264_slice_params *p_h264_slice_params;
17748c2ecf20Sopenharmony_ci	struct v4l2_ctrl_h264_decode_params *p_h264_dec_params;
17758c2ecf20Sopenharmony_ci	struct v4l2_ctrl_hevc_sps *p_hevc_sps;
17768c2ecf20Sopenharmony_ci	struct v4l2_ctrl_hevc_pps *p_hevc_pps;
17778c2ecf20Sopenharmony_ci	struct v4l2_ctrl_hevc_slice_params *p_hevc_slice_params;
17788c2ecf20Sopenharmony_ci	struct v4l2_area *area;
17798c2ecf20Sopenharmony_ci	void *p = ptr.p + idx * ctrl->elem_size;
17808c2ecf20Sopenharmony_ci	unsigned int i;
17818c2ecf20Sopenharmony_ci
17828c2ecf20Sopenharmony_ci	switch ((u32)ctrl->type) {
17838c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_MPEG2_SLICE_PARAMS:
17848c2ecf20Sopenharmony_ci		p_mpeg2_slice_params = p;
17858c2ecf20Sopenharmony_ci
17868c2ecf20Sopenharmony_ci		switch (p_mpeg2_slice_params->sequence.chroma_format) {
17878c2ecf20Sopenharmony_ci		case 1: /* 4:2:0 */
17888c2ecf20Sopenharmony_ci		case 2: /* 4:2:2 */
17898c2ecf20Sopenharmony_ci		case 3: /* 4:4:4 */
17908c2ecf20Sopenharmony_ci			break;
17918c2ecf20Sopenharmony_ci		default:
17928c2ecf20Sopenharmony_ci			return -EINVAL;
17938c2ecf20Sopenharmony_ci		}
17948c2ecf20Sopenharmony_ci
17958c2ecf20Sopenharmony_ci		switch (p_mpeg2_slice_params->picture.intra_dc_precision) {
17968c2ecf20Sopenharmony_ci		case 0: /* 8 bits */
17978c2ecf20Sopenharmony_ci		case 1: /* 9 bits */
17988c2ecf20Sopenharmony_ci		case 2: /* 10 bits */
17998c2ecf20Sopenharmony_ci		case 3: /* 11 bits */
18008c2ecf20Sopenharmony_ci			break;
18018c2ecf20Sopenharmony_ci		default:
18028c2ecf20Sopenharmony_ci			return -EINVAL;
18038c2ecf20Sopenharmony_ci		}
18048c2ecf20Sopenharmony_ci
18058c2ecf20Sopenharmony_ci		switch (p_mpeg2_slice_params->picture.picture_structure) {
18068c2ecf20Sopenharmony_ci		case 1: /* interlaced top field */
18078c2ecf20Sopenharmony_ci		case 2: /* interlaced bottom field */
18088c2ecf20Sopenharmony_ci		case 3: /* progressive */
18098c2ecf20Sopenharmony_ci			break;
18108c2ecf20Sopenharmony_ci		default:
18118c2ecf20Sopenharmony_ci			return -EINVAL;
18128c2ecf20Sopenharmony_ci		}
18138c2ecf20Sopenharmony_ci
18148c2ecf20Sopenharmony_ci		switch (p_mpeg2_slice_params->picture.picture_coding_type) {
18158c2ecf20Sopenharmony_ci		case V4L2_MPEG2_PICTURE_CODING_TYPE_I:
18168c2ecf20Sopenharmony_ci		case V4L2_MPEG2_PICTURE_CODING_TYPE_P:
18178c2ecf20Sopenharmony_ci		case V4L2_MPEG2_PICTURE_CODING_TYPE_B:
18188c2ecf20Sopenharmony_ci			break;
18198c2ecf20Sopenharmony_ci		default:
18208c2ecf20Sopenharmony_ci			return -EINVAL;
18218c2ecf20Sopenharmony_ci		}
18228c2ecf20Sopenharmony_ci
18238c2ecf20Sopenharmony_ci		break;
18248c2ecf20Sopenharmony_ci
18258c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_MPEG2_QUANTIZATION:
18268c2ecf20Sopenharmony_ci		break;
18278c2ecf20Sopenharmony_ci
18288c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_FWHT_PARAMS:
18298c2ecf20Sopenharmony_ci		break;
18308c2ecf20Sopenharmony_ci
18318c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_H264_SPS:
18328c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_H264_PPS:
18338c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_H264_SCALING_MATRIX:
18348c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_H264_PRED_WEIGHTS:
18358c2ecf20Sopenharmony_ci		break;
18368c2ecf20Sopenharmony_ci
18378c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_H264_SLICE_PARAMS:
18388c2ecf20Sopenharmony_ci		p_h264_slice_params = p;
18398c2ecf20Sopenharmony_ci
18408c2ecf20Sopenharmony_ci		zero_reserved(*p_h264_slice_params);
18418c2ecf20Sopenharmony_ci		break;
18428c2ecf20Sopenharmony_ci
18438c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_H264_DECODE_PARAMS:
18448c2ecf20Sopenharmony_ci		p_h264_dec_params = p;
18458c2ecf20Sopenharmony_ci
18468c2ecf20Sopenharmony_ci		for (i = 0; i < V4L2_H264_NUM_DPB_ENTRIES; i++) {
18478c2ecf20Sopenharmony_ci			struct v4l2_h264_dpb_entry *dpb_entry =
18488c2ecf20Sopenharmony_ci				&p_h264_dec_params->dpb[i];
18498c2ecf20Sopenharmony_ci
18508c2ecf20Sopenharmony_ci			zero_reserved(*dpb_entry);
18518c2ecf20Sopenharmony_ci		}
18528c2ecf20Sopenharmony_ci		zero_reserved(*p_h264_dec_params);
18538c2ecf20Sopenharmony_ci		break;
18548c2ecf20Sopenharmony_ci
18558c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_VP8_FRAME_HEADER:
18568c2ecf20Sopenharmony_ci		p_vp8_frame_header = p;
18578c2ecf20Sopenharmony_ci
18588c2ecf20Sopenharmony_ci		switch (p_vp8_frame_header->num_dct_parts) {
18598c2ecf20Sopenharmony_ci		case 1:
18608c2ecf20Sopenharmony_ci		case 2:
18618c2ecf20Sopenharmony_ci		case 4:
18628c2ecf20Sopenharmony_ci		case 8:
18638c2ecf20Sopenharmony_ci			break;
18648c2ecf20Sopenharmony_ci		default:
18658c2ecf20Sopenharmony_ci			return -EINVAL;
18668c2ecf20Sopenharmony_ci		}
18678c2ecf20Sopenharmony_ci		zero_padding(p_vp8_frame_header->segment_header);
18688c2ecf20Sopenharmony_ci		zero_padding(p_vp8_frame_header->lf_header);
18698c2ecf20Sopenharmony_ci		zero_padding(p_vp8_frame_header->quant_header);
18708c2ecf20Sopenharmony_ci		zero_padding(p_vp8_frame_header->entropy_header);
18718c2ecf20Sopenharmony_ci		zero_padding(p_vp8_frame_header->coder_state);
18728c2ecf20Sopenharmony_ci		break;
18738c2ecf20Sopenharmony_ci
18748c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_HEVC_SPS:
18758c2ecf20Sopenharmony_ci		p_hevc_sps = p;
18768c2ecf20Sopenharmony_ci
18778c2ecf20Sopenharmony_ci		if (!(p_hevc_sps->flags & V4L2_HEVC_SPS_FLAG_PCM_ENABLED)) {
18788c2ecf20Sopenharmony_ci			p_hevc_sps->pcm_sample_bit_depth_luma_minus1 = 0;
18798c2ecf20Sopenharmony_ci			p_hevc_sps->pcm_sample_bit_depth_chroma_minus1 = 0;
18808c2ecf20Sopenharmony_ci			p_hevc_sps->log2_min_pcm_luma_coding_block_size_minus3 = 0;
18818c2ecf20Sopenharmony_ci			p_hevc_sps->log2_diff_max_min_pcm_luma_coding_block_size = 0;
18828c2ecf20Sopenharmony_ci		}
18838c2ecf20Sopenharmony_ci
18848c2ecf20Sopenharmony_ci		if (!(p_hevc_sps->flags &
18858c2ecf20Sopenharmony_ci		      V4L2_HEVC_SPS_FLAG_LONG_TERM_REF_PICS_PRESENT))
18868c2ecf20Sopenharmony_ci			p_hevc_sps->num_long_term_ref_pics_sps = 0;
18878c2ecf20Sopenharmony_ci		break;
18888c2ecf20Sopenharmony_ci
18898c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_HEVC_PPS:
18908c2ecf20Sopenharmony_ci		p_hevc_pps = p;
18918c2ecf20Sopenharmony_ci
18928c2ecf20Sopenharmony_ci		if (!(p_hevc_pps->flags &
18938c2ecf20Sopenharmony_ci		      V4L2_HEVC_PPS_FLAG_CU_QP_DELTA_ENABLED))
18948c2ecf20Sopenharmony_ci			p_hevc_pps->diff_cu_qp_delta_depth = 0;
18958c2ecf20Sopenharmony_ci
18968c2ecf20Sopenharmony_ci		if (!(p_hevc_pps->flags & V4L2_HEVC_PPS_FLAG_TILES_ENABLED)) {
18978c2ecf20Sopenharmony_ci			p_hevc_pps->num_tile_columns_minus1 = 0;
18988c2ecf20Sopenharmony_ci			p_hevc_pps->num_tile_rows_minus1 = 0;
18998c2ecf20Sopenharmony_ci			memset(&p_hevc_pps->column_width_minus1, 0,
19008c2ecf20Sopenharmony_ci			       sizeof(p_hevc_pps->column_width_minus1));
19018c2ecf20Sopenharmony_ci			memset(&p_hevc_pps->row_height_minus1, 0,
19028c2ecf20Sopenharmony_ci			       sizeof(p_hevc_pps->row_height_minus1));
19038c2ecf20Sopenharmony_ci
19048c2ecf20Sopenharmony_ci			p_hevc_pps->flags &=
19058c2ecf20Sopenharmony_ci				~V4L2_HEVC_PPS_FLAG_LOOP_FILTER_ACROSS_TILES_ENABLED;
19068c2ecf20Sopenharmony_ci		}
19078c2ecf20Sopenharmony_ci
19088c2ecf20Sopenharmony_ci		if (p_hevc_pps->flags &
19098c2ecf20Sopenharmony_ci		    V4L2_HEVC_PPS_FLAG_PPS_DISABLE_DEBLOCKING_FILTER) {
19108c2ecf20Sopenharmony_ci			p_hevc_pps->pps_beta_offset_div2 = 0;
19118c2ecf20Sopenharmony_ci			p_hevc_pps->pps_tc_offset_div2 = 0;
19128c2ecf20Sopenharmony_ci		}
19138c2ecf20Sopenharmony_ci
19148c2ecf20Sopenharmony_ci		zero_padding(*p_hevc_pps);
19158c2ecf20Sopenharmony_ci		break;
19168c2ecf20Sopenharmony_ci
19178c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS:
19188c2ecf20Sopenharmony_ci		p_hevc_slice_params = p;
19198c2ecf20Sopenharmony_ci
19208c2ecf20Sopenharmony_ci		if (p_hevc_slice_params->num_active_dpb_entries >
19218c2ecf20Sopenharmony_ci		    V4L2_HEVC_DPB_ENTRIES_NUM_MAX)
19228c2ecf20Sopenharmony_ci			return -EINVAL;
19238c2ecf20Sopenharmony_ci
19248c2ecf20Sopenharmony_ci		zero_padding(p_hevc_slice_params->pred_weight_table);
19258c2ecf20Sopenharmony_ci
19268c2ecf20Sopenharmony_ci		for (i = 0; i < p_hevc_slice_params->num_active_dpb_entries;
19278c2ecf20Sopenharmony_ci		     i++) {
19288c2ecf20Sopenharmony_ci			struct v4l2_hevc_dpb_entry *dpb_entry =
19298c2ecf20Sopenharmony_ci				&p_hevc_slice_params->dpb[i];
19308c2ecf20Sopenharmony_ci
19318c2ecf20Sopenharmony_ci			zero_padding(*dpb_entry);
19328c2ecf20Sopenharmony_ci		}
19338c2ecf20Sopenharmony_ci
19348c2ecf20Sopenharmony_ci		zero_padding(*p_hevc_slice_params);
19358c2ecf20Sopenharmony_ci		break;
19368c2ecf20Sopenharmony_ci
19378c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_AREA:
19388c2ecf20Sopenharmony_ci		area = p;
19398c2ecf20Sopenharmony_ci		if (!area->width || !area->height)
19408c2ecf20Sopenharmony_ci			return -EINVAL;
19418c2ecf20Sopenharmony_ci		break;
19428c2ecf20Sopenharmony_ci
19438c2ecf20Sopenharmony_ci	default:
19448c2ecf20Sopenharmony_ci		return -EINVAL;
19458c2ecf20Sopenharmony_ci	}
19468c2ecf20Sopenharmony_ci
19478c2ecf20Sopenharmony_ci	return 0;
19488c2ecf20Sopenharmony_ci}
19498c2ecf20Sopenharmony_ci
19508c2ecf20Sopenharmony_cistatic int std_validate(const struct v4l2_ctrl *ctrl, u32 idx,
19518c2ecf20Sopenharmony_ci			union v4l2_ctrl_ptr ptr)
19528c2ecf20Sopenharmony_ci{
19538c2ecf20Sopenharmony_ci	size_t len;
19548c2ecf20Sopenharmony_ci	u64 offset;
19558c2ecf20Sopenharmony_ci	s64 val;
19568c2ecf20Sopenharmony_ci
19578c2ecf20Sopenharmony_ci	switch ((u32)ctrl->type) {
19588c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_INTEGER:
19598c2ecf20Sopenharmony_ci		return ROUND_TO_RANGE(ptr.p_s32[idx], u32, ctrl);
19608c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_INTEGER64:
19618c2ecf20Sopenharmony_ci		/*
19628c2ecf20Sopenharmony_ci		 * We can't use the ROUND_TO_RANGE define here due to
19638c2ecf20Sopenharmony_ci		 * the u64 divide that needs special care.
19648c2ecf20Sopenharmony_ci		 */
19658c2ecf20Sopenharmony_ci		val = ptr.p_s64[idx];
19668c2ecf20Sopenharmony_ci		if (ctrl->maximum >= 0 && val >= ctrl->maximum - (s64)(ctrl->step / 2))
19678c2ecf20Sopenharmony_ci			val = ctrl->maximum;
19688c2ecf20Sopenharmony_ci		else
19698c2ecf20Sopenharmony_ci			val += (s64)(ctrl->step / 2);
19708c2ecf20Sopenharmony_ci		val = clamp_t(s64, val, ctrl->minimum, ctrl->maximum);
19718c2ecf20Sopenharmony_ci		offset = val - ctrl->minimum;
19728c2ecf20Sopenharmony_ci		do_div(offset, ctrl->step);
19738c2ecf20Sopenharmony_ci		ptr.p_s64[idx] = ctrl->minimum + offset * ctrl->step;
19748c2ecf20Sopenharmony_ci		return 0;
19758c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_U8:
19768c2ecf20Sopenharmony_ci		return ROUND_TO_RANGE(ptr.p_u8[idx], u8, ctrl);
19778c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_U16:
19788c2ecf20Sopenharmony_ci		return ROUND_TO_RANGE(ptr.p_u16[idx], u16, ctrl);
19798c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_U32:
19808c2ecf20Sopenharmony_ci		return ROUND_TO_RANGE(ptr.p_u32[idx], u32, ctrl);
19818c2ecf20Sopenharmony_ci
19828c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_BOOLEAN:
19838c2ecf20Sopenharmony_ci		ptr.p_s32[idx] = !!ptr.p_s32[idx];
19848c2ecf20Sopenharmony_ci		return 0;
19858c2ecf20Sopenharmony_ci
19868c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_MENU:
19878c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_INTEGER_MENU:
19888c2ecf20Sopenharmony_ci		if (ptr.p_s32[idx] < ctrl->minimum || ptr.p_s32[idx] > ctrl->maximum)
19898c2ecf20Sopenharmony_ci			return -ERANGE;
19908c2ecf20Sopenharmony_ci		if (ptr.p_s32[idx] < BITS_PER_LONG_LONG &&
19918c2ecf20Sopenharmony_ci		    (ctrl->menu_skip_mask & BIT_ULL(ptr.p_s32[idx])))
19928c2ecf20Sopenharmony_ci			return -EINVAL;
19938c2ecf20Sopenharmony_ci		if (ctrl->type == V4L2_CTRL_TYPE_MENU &&
19948c2ecf20Sopenharmony_ci		    ctrl->qmenu[ptr.p_s32[idx]][0] == '\0')
19958c2ecf20Sopenharmony_ci			return -EINVAL;
19968c2ecf20Sopenharmony_ci		return 0;
19978c2ecf20Sopenharmony_ci
19988c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_BITMASK:
19998c2ecf20Sopenharmony_ci		ptr.p_s32[idx] &= ctrl->maximum;
20008c2ecf20Sopenharmony_ci		return 0;
20018c2ecf20Sopenharmony_ci
20028c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_BUTTON:
20038c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_CTRL_CLASS:
20048c2ecf20Sopenharmony_ci		ptr.p_s32[idx] = 0;
20058c2ecf20Sopenharmony_ci		return 0;
20068c2ecf20Sopenharmony_ci
20078c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_STRING:
20088c2ecf20Sopenharmony_ci		idx *= ctrl->elem_size;
20098c2ecf20Sopenharmony_ci		len = strlen(ptr.p_char + idx);
20108c2ecf20Sopenharmony_ci		if (len < ctrl->minimum)
20118c2ecf20Sopenharmony_ci			return -ERANGE;
20128c2ecf20Sopenharmony_ci		if ((len - (u32)ctrl->minimum) % (u32)ctrl->step)
20138c2ecf20Sopenharmony_ci			return -ERANGE;
20148c2ecf20Sopenharmony_ci		return 0;
20158c2ecf20Sopenharmony_ci
20168c2ecf20Sopenharmony_ci	default:
20178c2ecf20Sopenharmony_ci		return std_validate_compound(ctrl, idx, ptr);
20188c2ecf20Sopenharmony_ci	}
20198c2ecf20Sopenharmony_ci}
20208c2ecf20Sopenharmony_ci
20218c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_type_ops std_type_ops = {
20228c2ecf20Sopenharmony_ci	.equal = std_equal,
20238c2ecf20Sopenharmony_ci	.init = std_init,
20248c2ecf20Sopenharmony_ci	.log = std_log,
20258c2ecf20Sopenharmony_ci	.validate = std_validate,
20268c2ecf20Sopenharmony_ci};
20278c2ecf20Sopenharmony_ci
20288c2ecf20Sopenharmony_ci/* Helper function: copy the given control value back to the caller */
20298c2ecf20Sopenharmony_cistatic int ptr_to_user(struct v4l2_ext_control *c,
20308c2ecf20Sopenharmony_ci		       struct v4l2_ctrl *ctrl,
20318c2ecf20Sopenharmony_ci		       union v4l2_ctrl_ptr ptr)
20328c2ecf20Sopenharmony_ci{
20338c2ecf20Sopenharmony_ci	u32 len;
20348c2ecf20Sopenharmony_ci
20358c2ecf20Sopenharmony_ci	if (ctrl->is_ptr && !ctrl->is_string)
20368c2ecf20Sopenharmony_ci		return copy_to_user(c->ptr, ptr.p_const, c->size) ?
20378c2ecf20Sopenharmony_ci		       -EFAULT : 0;
20388c2ecf20Sopenharmony_ci
20398c2ecf20Sopenharmony_ci	switch (ctrl->type) {
20408c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_STRING:
20418c2ecf20Sopenharmony_ci		len = strlen(ptr.p_char);
20428c2ecf20Sopenharmony_ci		if (c->size < len + 1) {
20438c2ecf20Sopenharmony_ci			c->size = ctrl->elem_size;
20448c2ecf20Sopenharmony_ci			return -ENOSPC;
20458c2ecf20Sopenharmony_ci		}
20468c2ecf20Sopenharmony_ci		return copy_to_user(c->string, ptr.p_char, len + 1) ?
20478c2ecf20Sopenharmony_ci		       -EFAULT : 0;
20488c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_INTEGER64:
20498c2ecf20Sopenharmony_ci		c->value64 = *ptr.p_s64;
20508c2ecf20Sopenharmony_ci		break;
20518c2ecf20Sopenharmony_ci	default:
20528c2ecf20Sopenharmony_ci		c->value = *ptr.p_s32;
20538c2ecf20Sopenharmony_ci		break;
20548c2ecf20Sopenharmony_ci	}
20558c2ecf20Sopenharmony_ci	return 0;
20568c2ecf20Sopenharmony_ci}
20578c2ecf20Sopenharmony_ci
20588c2ecf20Sopenharmony_ci/* Helper function: copy the current control value back to the caller */
20598c2ecf20Sopenharmony_cistatic int cur_to_user(struct v4l2_ext_control *c,
20608c2ecf20Sopenharmony_ci		       struct v4l2_ctrl *ctrl)
20618c2ecf20Sopenharmony_ci{
20628c2ecf20Sopenharmony_ci	return ptr_to_user(c, ctrl, ctrl->p_cur);
20638c2ecf20Sopenharmony_ci}
20648c2ecf20Sopenharmony_ci
20658c2ecf20Sopenharmony_ci/* Helper function: copy the new control value back to the caller */
20668c2ecf20Sopenharmony_cistatic int new_to_user(struct v4l2_ext_control *c,
20678c2ecf20Sopenharmony_ci		       struct v4l2_ctrl *ctrl)
20688c2ecf20Sopenharmony_ci{
20698c2ecf20Sopenharmony_ci	return ptr_to_user(c, ctrl, ctrl->p_new);
20708c2ecf20Sopenharmony_ci}
20718c2ecf20Sopenharmony_ci
20728c2ecf20Sopenharmony_ci/* Helper function: copy the request value back to the caller */
20738c2ecf20Sopenharmony_cistatic int req_to_user(struct v4l2_ext_control *c,
20748c2ecf20Sopenharmony_ci		       struct v4l2_ctrl_ref *ref)
20758c2ecf20Sopenharmony_ci{
20768c2ecf20Sopenharmony_ci	return ptr_to_user(c, ref->ctrl, ref->p_req);
20778c2ecf20Sopenharmony_ci}
20788c2ecf20Sopenharmony_ci
20798c2ecf20Sopenharmony_ci/* Helper function: copy the initial control value back to the caller */
20808c2ecf20Sopenharmony_cistatic int def_to_user(struct v4l2_ext_control *c, struct v4l2_ctrl *ctrl)
20818c2ecf20Sopenharmony_ci{
20828c2ecf20Sopenharmony_ci	int idx;
20838c2ecf20Sopenharmony_ci
20848c2ecf20Sopenharmony_ci	for (idx = 0; idx < ctrl->elems; idx++)
20858c2ecf20Sopenharmony_ci		ctrl->type_ops->init(ctrl, idx, ctrl->p_new);
20868c2ecf20Sopenharmony_ci
20878c2ecf20Sopenharmony_ci	return ptr_to_user(c, ctrl, ctrl->p_new);
20888c2ecf20Sopenharmony_ci}
20898c2ecf20Sopenharmony_ci
20908c2ecf20Sopenharmony_ci/* Helper function: copy the caller-provider value to the given control value */
20918c2ecf20Sopenharmony_cistatic int user_to_ptr(struct v4l2_ext_control *c,
20928c2ecf20Sopenharmony_ci		       struct v4l2_ctrl *ctrl,
20938c2ecf20Sopenharmony_ci		       union v4l2_ctrl_ptr ptr)
20948c2ecf20Sopenharmony_ci{
20958c2ecf20Sopenharmony_ci	int ret;
20968c2ecf20Sopenharmony_ci	u32 size;
20978c2ecf20Sopenharmony_ci
20988c2ecf20Sopenharmony_ci	ctrl->is_new = 1;
20998c2ecf20Sopenharmony_ci	if (ctrl->is_ptr && !ctrl->is_string) {
21008c2ecf20Sopenharmony_ci		unsigned idx;
21018c2ecf20Sopenharmony_ci
21028c2ecf20Sopenharmony_ci		ret = copy_from_user(ptr.p, c->ptr, c->size) ? -EFAULT : 0;
21038c2ecf20Sopenharmony_ci		if (ret || !ctrl->is_array)
21048c2ecf20Sopenharmony_ci			return ret;
21058c2ecf20Sopenharmony_ci		for (idx = c->size / ctrl->elem_size; idx < ctrl->elems; idx++)
21068c2ecf20Sopenharmony_ci			ctrl->type_ops->init(ctrl, idx, ptr);
21078c2ecf20Sopenharmony_ci		return 0;
21088c2ecf20Sopenharmony_ci	}
21098c2ecf20Sopenharmony_ci
21108c2ecf20Sopenharmony_ci	switch (ctrl->type) {
21118c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_INTEGER64:
21128c2ecf20Sopenharmony_ci		*ptr.p_s64 = c->value64;
21138c2ecf20Sopenharmony_ci		break;
21148c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_STRING:
21158c2ecf20Sopenharmony_ci		size = c->size;
21168c2ecf20Sopenharmony_ci		if (size == 0)
21178c2ecf20Sopenharmony_ci			return -ERANGE;
21188c2ecf20Sopenharmony_ci		if (size > ctrl->maximum + 1)
21198c2ecf20Sopenharmony_ci			size = ctrl->maximum + 1;
21208c2ecf20Sopenharmony_ci		ret = copy_from_user(ptr.p_char, c->string, size) ? -EFAULT : 0;
21218c2ecf20Sopenharmony_ci		if (!ret) {
21228c2ecf20Sopenharmony_ci			char last = ptr.p_char[size - 1];
21238c2ecf20Sopenharmony_ci
21248c2ecf20Sopenharmony_ci			ptr.p_char[size - 1] = 0;
21258c2ecf20Sopenharmony_ci			/* If the string was longer than ctrl->maximum,
21268c2ecf20Sopenharmony_ci			   then return an error. */
21278c2ecf20Sopenharmony_ci			if (strlen(ptr.p_char) == ctrl->maximum && last)
21288c2ecf20Sopenharmony_ci				return -ERANGE;
21298c2ecf20Sopenharmony_ci		}
21308c2ecf20Sopenharmony_ci		return ret;
21318c2ecf20Sopenharmony_ci	default:
21328c2ecf20Sopenharmony_ci		*ptr.p_s32 = c->value;
21338c2ecf20Sopenharmony_ci		break;
21348c2ecf20Sopenharmony_ci	}
21358c2ecf20Sopenharmony_ci	return 0;
21368c2ecf20Sopenharmony_ci}
21378c2ecf20Sopenharmony_ci
21388c2ecf20Sopenharmony_ci/* Helper function: copy the caller-provider value as the new control value */
21398c2ecf20Sopenharmony_cistatic int user_to_new(struct v4l2_ext_control *c,
21408c2ecf20Sopenharmony_ci		       struct v4l2_ctrl *ctrl)
21418c2ecf20Sopenharmony_ci{
21428c2ecf20Sopenharmony_ci	return user_to_ptr(c, ctrl, ctrl->p_new);
21438c2ecf20Sopenharmony_ci}
21448c2ecf20Sopenharmony_ci
21458c2ecf20Sopenharmony_ci/* Copy the one value to another. */
21468c2ecf20Sopenharmony_cistatic void ptr_to_ptr(struct v4l2_ctrl *ctrl,
21478c2ecf20Sopenharmony_ci		       union v4l2_ctrl_ptr from, union v4l2_ctrl_ptr to)
21488c2ecf20Sopenharmony_ci{
21498c2ecf20Sopenharmony_ci	if (ctrl == NULL)
21508c2ecf20Sopenharmony_ci		return;
21518c2ecf20Sopenharmony_ci	memcpy(to.p, from.p_const, ctrl->elems * ctrl->elem_size);
21528c2ecf20Sopenharmony_ci}
21538c2ecf20Sopenharmony_ci
21548c2ecf20Sopenharmony_ci/* Copy the new value to the current value. */
21558c2ecf20Sopenharmony_cistatic void new_to_cur(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl, u32 ch_flags)
21568c2ecf20Sopenharmony_ci{
21578c2ecf20Sopenharmony_ci	bool changed;
21588c2ecf20Sopenharmony_ci
21598c2ecf20Sopenharmony_ci	if (ctrl == NULL)
21608c2ecf20Sopenharmony_ci		return;
21618c2ecf20Sopenharmony_ci
21628c2ecf20Sopenharmony_ci	/* has_changed is set by cluster_changed */
21638c2ecf20Sopenharmony_ci	changed = ctrl->has_changed;
21648c2ecf20Sopenharmony_ci	if (changed)
21658c2ecf20Sopenharmony_ci		ptr_to_ptr(ctrl, ctrl->p_new, ctrl->p_cur);
21668c2ecf20Sopenharmony_ci
21678c2ecf20Sopenharmony_ci	if (ch_flags & V4L2_EVENT_CTRL_CH_FLAGS) {
21688c2ecf20Sopenharmony_ci		/* Note: CH_FLAGS is only set for auto clusters. */
21698c2ecf20Sopenharmony_ci		ctrl->flags &=
21708c2ecf20Sopenharmony_ci			~(V4L2_CTRL_FLAG_INACTIVE | V4L2_CTRL_FLAG_VOLATILE);
21718c2ecf20Sopenharmony_ci		if (!is_cur_manual(ctrl->cluster[0])) {
21728c2ecf20Sopenharmony_ci			ctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
21738c2ecf20Sopenharmony_ci			if (ctrl->cluster[0]->has_volatiles)
21748c2ecf20Sopenharmony_ci				ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
21758c2ecf20Sopenharmony_ci		}
21768c2ecf20Sopenharmony_ci		fh = NULL;
21778c2ecf20Sopenharmony_ci	}
21788c2ecf20Sopenharmony_ci	if (changed || ch_flags) {
21798c2ecf20Sopenharmony_ci		/* If a control was changed that was not one of the controls
21808c2ecf20Sopenharmony_ci		   modified by the application, then send the event to all. */
21818c2ecf20Sopenharmony_ci		if (!ctrl->is_new)
21828c2ecf20Sopenharmony_ci			fh = NULL;
21838c2ecf20Sopenharmony_ci		send_event(fh, ctrl,
21848c2ecf20Sopenharmony_ci			(changed ? V4L2_EVENT_CTRL_CH_VALUE : 0) | ch_flags);
21858c2ecf20Sopenharmony_ci		if (ctrl->call_notify && changed && ctrl->handler->notify)
21868c2ecf20Sopenharmony_ci			ctrl->handler->notify(ctrl, ctrl->handler->notify_priv);
21878c2ecf20Sopenharmony_ci	}
21888c2ecf20Sopenharmony_ci}
21898c2ecf20Sopenharmony_ci
21908c2ecf20Sopenharmony_ci/* Copy the current value to the new value */
21918c2ecf20Sopenharmony_cistatic void cur_to_new(struct v4l2_ctrl *ctrl)
21928c2ecf20Sopenharmony_ci{
21938c2ecf20Sopenharmony_ci	if (ctrl == NULL)
21948c2ecf20Sopenharmony_ci		return;
21958c2ecf20Sopenharmony_ci	ptr_to_ptr(ctrl, ctrl->p_cur, ctrl->p_new);
21968c2ecf20Sopenharmony_ci}
21978c2ecf20Sopenharmony_ci
21988c2ecf20Sopenharmony_ci/* Copy the new value to the request value */
21998c2ecf20Sopenharmony_cistatic void new_to_req(struct v4l2_ctrl_ref *ref)
22008c2ecf20Sopenharmony_ci{
22018c2ecf20Sopenharmony_ci	if (!ref)
22028c2ecf20Sopenharmony_ci		return;
22038c2ecf20Sopenharmony_ci	ptr_to_ptr(ref->ctrl, ref->ctrl->p_new, ref->p_req);
22048c2ecf20Sopenharmony_ci	ref->valid_p_req = true;
22058c2ecf20Sopenharmony_ci}
22068c2ecf20Sopenharmony_ci
22078c2ecf20Sopenharmony_ci/* Copy the current value to the request value */
22088c2ecf20Sopenharmony_cistatic void cur_to_req(struct v4l2_ctrl_ref *ref)
22098c2ecf20Sopenharmony_ci{
22108c2ecf20Sopenharmony_ci	if (!ref)
22118c2ecf20Sopenharmony_ci		return;
22128c2ecf20Sopenharmony_ci	ptr_to_ptr(ref->ctrl, ref->ctrl->p_cur, ref->p_req);
22138c2ecf20Sopenharmony_ci	ref->valid_p_req = true;
22148c2ecf20Sopenharmony_ci}
22158c2ecf20Sopenharmony_ci
22168c2ecf20Sopenharmony_ci/* Copy the request value to the new value */
22178c2ecf20Sopenharmony_cistatic void req_to_new(struct v4l2_ctrl_ref *ref)
22188c2ecf20Sopenharmony_ci{
22198c2ecf20Sopenharmony_ci	if (!ref)
22208c2ecf20Sopenharmony_ci		return;
22218c2ecf20Sopenharmony_ci	if (ref->valid_p_req)
22228c2ecf20Sopenharmony_ci		ptr_to_ptr(ref->ctrl, ref->p_req, ref->ctrl->p_new);
22238c2ecf20Sopenharmony_ci	else
22248c2ecf20Sopenharmony_ci		ptr_to_ptr(ref->ctrl, ref->ctrl->p_cur, ref->ctrl->p_new);
22258c2ecf20Sopenharmony_ci}
22268c2ecf20Sopenharmony_ci
22278c2ecf20Sopenharmony_ci/* Return non-zero if one or more of the controls in the cluster has a new
22288c2ecf20Sopenharmony_ci   value that differs from the current value. */
22298c2ecf20Sopenharmony_cistatic int cluster_changed(struct v4l2_ctrl *master)
22308c2ecf20Sopenharmony_ci{
22318c2ecf20Sopenharmony_ci	bool changed = false;
22328c2ecf20Sopenharmony_ci	unsigned idx;
22338c2ecf20Sopenharmony_ci	int i;
22348c2ecf20Sopenharmony_ci
22358c2ecf20Sopenharmony_ci	for (i = 0; i < master->ncontrols; i++) {
22368c2ecf20Sopenharmony_ci		struct v4l2_ctrl *ctrl = master->cluster[i];
22378c2ecf20Sopenharmony_ci		bool ctrl_changed = false;
22388c2ecf20Sopenharmony_ci
22398c2ecf20Sopenharmony_ci		if (ctrl == NULL)
22408c2ecf20Sopenharmony_ci			continue;
22418c2ecf20Sopenharmony_ci
22428c2ecf20Sopenharmony_ci		if (ctrl->flags & V4L2_CTRL_FLAG_EXECUTE_ON_WRITE)
22438c2ecf20Sopenharmony_ci			changed = ctrl_changed = true;
22448c2ecf20Sopenharmony_ci
22458c2ecf20Sopenharmony_ci		/*
22468c2ecf20Sopenharmony_ci		 * Set has_changed to false to avoid generating
22478c2ecf20Sopenharmony_ci		 * the event V4L2_EVENT_CTRL_CH_VALUE
22488c2ecf20Sopenharmony_ci		 */
22498c2ecf20Sopenharmony_ci		if (ctrl->flags & V4L2_CTRL_FLAG_VOLATILE) {
22508c2ecf20Sopenharmony_ci			ctrl->has_changed = false;
22518c2ecf20Sopenharmony_ci			continue;
22528c2ecf20Sopenharmony_ci		}
22538c2ecf20Sopenharmony_ci
22548c2ecf20Sopenharmony_ci		for (idx = 0; !ctrl_changed && idx < ctrl->elems; idx++)
22558c2ecf20Sopenharmony_ci			ctrl_changed = !ctrl->type_ops->equal(ctrl, idx,
22568c2ecf20Sopenharmony_ci				ctrl->p_cur, ctrl->p_new);
22578c2ecf20Sopenharmony_ci		ctrl->has_changed = ctrl_changed;
22588c2ecf20Sopenharmony_ci		changed |= ctrl->has_changed;
22598c2ecf20Sopenharmony_ci	}
22608c2ecf20Sopenharmony_ci	return changed;
22618c2ecf20Sopenharmony_ci}
22628c2ecf20Sopenharmony_ci
22638c2ecf20Sopenharmony_ci/* Control range checking */
22648c2ecf20Sopenharmony_cistatic int check_range(enum v4l2_ctrl_type type,
22658c2ecf20Sopenharmony_ci		s64 min, s64 max, u64 step, s64 def)
22668c2ecf20Sopenharmony_ci{
22678c2ecf20Sopenharmony_ci	switch (type) {
22688c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_BOOLEAN:
22698c2ecf20Sopenharmony_ci		if (step != 1 || max > 1 || min < 0)
22708c2ecf20Sopenharmony_ci			return -ERANGE;
22718c2ecf20Sopenharmony_ci		fallthrough;
22728c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_U8:
22738c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_U16:
22748c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_U32:
22758c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_INTEGER:
22768c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_INTEGER64:
22778c2ecf20Sopenharmony_ci		if (step == 0 || min > max || def < min || def > max)
22788c2ecf20Sopenharmony_ci			return -ERANGE;
22798c2ecf20Sopenharmony_ci		return 0;
22808c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_BITMASK:
22818c2ecf20Sopenharmony_ci		if (step || min || !max || (def & ~max))
22828c2ecf20Sopenharmony_ci			return -ERANGE;
22838c2ecf20Sopenharmony_ci		return 0;
22848c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_MENU:
22858c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_INTEGER_MENU:
22868c2ecf20Sopenharmony_ci		if (min > max || def < min || def > max)
22878c2ecf20Sopenharmony_ci			return -ERANGE;
22888c2ecf20Sopenharmony_ci		/* Note: step == menu_skip_mask for menu controls.
22898c2ecf20Sopenharmony_ci		   So here we check if the default value is masked out. */
22908c2ecf20Sopenharmony_ci		if (step && ((1 << def) & step))
22918c2ecf20Sopenharmony_ci			return -EINVAL;
22928c2ecf20Sopenharmony_ci		return 0;
22938c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_STRING:
22948c2ecf20Sopenharmony_ci		if (min > max || min < 0 || step < 1 || def)
22958c2ecf20Sopenharmony_ci			return -ERANGE;
22968c2ecf20Sopenharmony_ci		return 0;
22978c2ecf20Sopenharmony_ci	default:
22988c2ecf20Sopenharmony_ci		return 0;
22998c2ecf20Sopenharmony_ci	}
23008c2ecf20Sopenharmony_ci}
23018c2ecf20Sopenharmony_ci
23028c2ecf20Sopenharmony_ci/* Validate a new control */
23038c2ecf20Sopenharmony_cistatic int validate_new(const struct v4l2_ctrl *ctrl, union v4l2_ctrl_ptr p_new)
23048c2ecf20Sopenharmony_ci{
23058c2ecf20Sopenharmony_ci	unsigned idx;
23068c2ecf20Sopenharmony_ci	int err = 0;
23078c2ecf20Sopenharmony_ci
23088c2ecf20Sopenharmony_ci	for (idx = 0; !err && idx < ctrl->elems; idx++)
23098c2ecf20Sopenharmony_ci		err = ctrl->type_ops->validate(ctrl, idx, p_new);
23108c2ecf20Sopenharmony_ci	return err;
23118c2ecf20Sopenharmony_ci}
23128c2ecf20Sopenharmony_ci
23138c2ecf20Sopenharmony_cistatic inline u32 node2id(struct list_head *node)
23148c2ecf20Sopenharmony_ci{
23158c2ecf20Sopenharmony_ci	return list_entry(node, struct v4l2_ctrl_ref, node)->ctrl->id;
23168c2ecf20Sopenharmony_ci}
23178c2ecf20Sopenharmony_ci
23188c2ecf20Sopenharmony_ci/* Set the handler's error code if it wasn't set earlier already */
23198c2ecf20Sopenharmony_cistatic inline int handler_set_err(struct v4l2_ctrl_handler *hdl, int err)
23208c2ecf20Sopenharmony_ci{
23218c2ecf20Sopenharmony_ci	if (hdl->error == 0)
23228c2ecf20Sopenharmony_ci		hdl->error = err;
23238c2ecf20Sopenharmony_ci	return err;
23248c2ecf20Sopenharmony_ci}
23258c2ecf20Sopenharmony_ci
23268c2ecf20Sopenharmony_ci/* Initialize the handler */
23278c2ecf20Sopenharmony_ciint v4l2_ctrl_handler_init_class(struct v4l2_ctrl_handler *hdl,
23288c2ecf20Sopenharmony_ci				 unsigned nr_of_controls_hint,
23298c2ecf20Sopenharmony_ci				 struct lock_class_key *key, const char *name)
23308c2ecf20Sopenharmony_ci{
23318c2ecf20Sopenharmony_ci	mutex_init(&hdl->_lock);
23328c2ecf20Sopenharmony_ci	hdl->lock = &hdl->_lock;
23338c2ecf20Sopenharmony_ci	lockdep_set_class_and_name(hdl->lock, key, name);
23348c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&hdl->ctrls);
23358c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&hdl->ctrl_refs);
23368c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&hdl->requests);
23378c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&hdl->requests_queued);
23388c2ecf20Sopenharmony_ci	hdl->request_is_queued = false;
23398c2ecf20Sopenharmony_ci	hdl->nr_of_buckets = 1 + nr_of_controls_hint / 8;
23408c2ecf20Sopenharmony_ci	hdl->buckets = kvmalloc_array(hdl->nr_of_buckets,
23418c2ecf20Sopenharmony_ci				      sizeof(hdl->buckets[0]),
23428c2ecf20Sopenharmony_ci				      GFP_KERNEL | __GFP_ZERO);
23438c2ecf20Sopenharmony_ci	hdl->error = hdl->buckets ? 0 : -ENOMEM;
23448c2ecf20Sopenharmony_ci	media_request_object_init(&hdl->req_obj);
23458c2ecf20Sopenharmony_ci	return hdl->error;
23468c2ecf20Sopenharmony_ci}
23478c2ecf20Sopenharmony_ciEXPORT_SYMBOL(v4l2_ctrl_handler_init_class);
23488c2ecf20Sopenharmony_ci
23498c2ecf20Sopenharmony_ci/* Free all controls and control refs */
23508c2ecf20Sopenharmony_civoid v4l2_ctrl_handler_free(struct v4l2_ctrl_handler *hdl)
23518c2ecf20Sopenharmony_ci{
23528c2ecf20Sopenharmony_ci	struct v4l2_ctrl_ref *ref, *next_ref;
23538c2ecf20Sopenharmony_ci	struct v4l2_ctrl *ctrl, *next_ctrl;
23548c2ecf20Sopenharmony_ci	struct v4l2_subscribed_event *sev, *next_sev;
23558c2ecf20Sopenharmony_ci
23568c2ecf20Sopenharmony_ci	if (hdl == NULL || hdl->buckets == NULL)
23578c2ecf20Sopenharmony_ci		return;
23588c2ecf20Sopenharmony_ci
23598c2ecf20Sopenharmony_ci	/*
23608c2ecf20Sopenharmony_ci	 * If the main handler is freed and it is used by handler objects in
23618c2ecf20Sopenharmony_ci	 * outstanding requests, then unbind and put those objects before
23628c2ecf20Sopenharmony_ci	 * freeing the main handler.
23638c2ecf20Sopenharmony_ci	 *
23648c2ecf20Sopenharmony_ci	 * The main handler can be identified by having a NULL ops pointer in
23658c2ecf20Sopenharmony_ci	 * the request object.
23668c2ecf20Sopenharmony_ci	 */
23678c2ecf20Sopenharmony_ci	if (!hdl->req_obj.ops && !list_empty(&hdl->requests)) {
23688c2ecf20Sopenharmony_ci		struct v4l2_ctrl_handler *req, *next_req;
23698c2ecf20Sopenharmony_ci
23708c2ecf20Sopenharmony_ci		list_for_each_entry_safe(req, next_req, &hdl->requests, requests) {
23718c2ecf20Sopenharmony_ci			media_request_object_unbind(&req->req_obj);
23728c2ecf20Sopenharmony_ci			media_request_object_put(&req->req_obj);
23738c2ecf20Sopenharmony_ci		}
23748c2ecf20Sopenharmony_ci	}
23758c2ecf20Sopenharmony_ci	mutex_lock(hdl->lock);
23768c2ecf20Sopenharmony_ci	/* Free all nodes */
23778c2ecf20Sopenharmony_ci	list_for_each_entry_safe(ref, next_ref, &hdl->ctrl_refs, node) {
23788c2ecf20Sopenharmony_ci		list_del(&ref->node);
23798c2ecf20Sopenharmony_ci		kfree(ref);
23808c2ecf20Sopenharmony_ci	}
23818c2ecf20Sopenharmony_ci	/* Free all controls owned by the handler */
23828c2ecf20Sopenharmony_ci	list_for_each_entry_safe(ctrl, next_ctrl, &hdl->ctrls, node) {
23838c2ecf20Sopenharmony_ci		list_del(&ctrl->node);
23848c2ecf20Sopenharmony_ci		list_for_each_entry_safe(sev, next_sev, &ctrl->ev_subs, node)
23858c2ecf20Sopenharmony_ci			list_del(&sev->node);
23868c2ecf20Sopenharmony_ci		kvfree(ctrl);
23878c2ecf20Sopenharmony_ci	}
23888c2ecf20Sopenharmony_ci	kvfree(hdl->buckets);
23898c2ecf20Sopenharmony_ci	hdl->buckets = NULL;
23908c2ecf20Sopenharmony_ci	hdl->cached = NULL;
23918c2ecf20Sopenharmony_ci	hdl->error = 0;
23928c2ecf20Sopenharmony_ci	mutex_unlock(hdl->lock);
23938c2ecf20Sopenharmony_ci	mutex_destroy(&hdl->_lock);
23948c2ecf20Sopenharmony_ci}
23958c2ecf20Sopenharmony_ciEXPORT_SYMBOL(v4l2_ctrl_handler_free);
23968c2ecf20Sopenharmony_ci
23978c2ecf20Sopenharmony_ci/* For backwards compatibility: V4L2_CID_PRIVATE_BASE should no longer
23988c2ecf20Sopenharmony_ci   be used except in G_CTRL, S_CTRL, QUERYCTRL and QUERYMENU when dealing
23998c2ecf20Sopenharmony_ci   with applications that do not use the NEXT_CTRL flag.
24008c2ecf20Sopenharmony_ci
24018c2ecf20Sopenharmony_ci   We just find the n-th private user control. It's O(N), but that should not
24028c2ecf20Sopenharmony_ci   be an issue in this particular case. */
24038c2ecf20Sopenharmony_cistatic struct v4l2_ctrl_ref *find_private_ref(
24048c2ecf20Sopenharmony_ci		struct v4l2_ctrl_handler *hdl, u32 id)
24058c2ecf20Sopenharmony_ci{
24068c2ecf20Sopenharmony_ci	struct v4l2_ctrl_ref *ref;
24078c2ecf20Sopenharmony_ci
24088c2ecf20Sopenharmony_ci	id -= V4L2_CID_PRIVATE_BASE;
24098c2ecf20Sopenharmony_ci	list_for_each_entry(ref, &hdl->ctrl_refs, node) {
24108c2ecf20Sopenharmony_ci		/* Search for private user controls that are compatible with
24118c2ecf20Sopenharmony_ci		   VIDIOC_G/S_CTRL. */
24128c2ecf20Sopenharmony_ci		if (V4L2_CTRL_ID2WHICH(ref->ctrl->id) == V4L2_CTRL_CLASS_USER &&
24138c2ecf20Sopenharmony_ci		    V4L2_CTRL_DRIVER_PRIV(ref->ctrl->id)) {
24148c2ecf20Sopenharmony_ci			if (!ref->ctrl->is_int)
24158c2ecf20Sopenharmony_ci				continue;
24168c2ecf20Sopenharmony_ci			if (id == 0)
24178c2ecf20Sopenharmony_ci				return ref;
24188c2ecf20Sopenharmony_ci			id--;
24198c2ecf20Sopenharmony_ci		}
24208c2ecf20Sopenharmony_ci	}
24218c2ecf20Sopenharmony_ci	return NULL;
24228c2ecf20Sopenharmony_ci}
24238c2ecf20Sopenharmony_ci
24248c2ecf20Sopenharmony_ci/* Find a control with the given ID. */
24258c2ecf20Sopenharmony_cistatic struct v4l2_ctrl_ref *find_ref(struct v4l2_ctrl_handler *hdl, u32 id)
24268c2ecf20Sopenharmony_ci{
24278c2ecf20Sopenharmony_ci	struct v4l2_ctrl_ref *ref;
24288c2ecf20Sopenharmony_ci	int bucket;
24298c2ecf20Sopenharmony_ci
24308c2ecf20Sopenharmony_ci	id &= V4L2_CTRL_ID_MASK;
24318c2ecf20Sopenharmony_ci
24328c2ecf20Sopenharmony_ci	/* Old-style private controls need special handling */
24338c2ecf20Sopenharmony_ci	if (id >= V4L2_CID_PRIVATE_BASE)
24348c2ecf20Sopenharmony_ci		return find_private_ref(hdl, id);
24358c2ecf20Sopenharmony_ci	bucket = id % hdl->nr_of_buckets;
24368c2ecf20Sopenharmony_ci
24378c2ecf20Sopenharmony_ci	/* Simple optimization: cache the last control found */
24388c2ecf20Sopenharmony_ci	if (hdl->cached && hdl->cached->ctrl->id == id)
24398c2ecf20Sopenharmony_ci		return hdl->cached;
24408c2ecf20Sopenharmony_ci
24418c2ecf20Sopenharmony_ci	/* Not in cache, search the hash */
24428c2ecf20Sopenharmony_ci	ref = hdl->buckets ? hdl->buckets[bucket] : NULL;
24438c2ecf20Sopenharmony_ci	while (ref && ref->ctrl->id != id)
24448c2ecf20Sopenharmony_ci		ref = ref->next;
24458c2ecf20Sopenharmony_ci
24468c2ecf20Sopenharmony_ci	if (ref)
24478c2ecf20Sopenharmony_ci		hdl->cached = ref; /* cache it! */
24488c2ecf20Sopenharmony_ci	return ref;
24498c2ecf20Sopenharmony_ci}
24508c2ecf20Sopenharmony_ci
24518c2ecf20Sopenharmony_ci/* Find a control with the given ID. Take the handler's lock first. */
24528c2ecf20Sopenharmony_cistatic struct v4l2_ctrl_ref *find_ref_lock(
24538c2ecf20Sopenharmony_ci		struct v4l2_ctrl_handler *hdl, u32 id)
24548c2ecf20Sopenharmony_ci{
24558c2ecf20Sopenharmony_ci	struct v4l2_ctrl_ref *ref = NULL;
24568c2ecf20Sopenharmony_ci
24578c2ecf20Sopenharmony_ci	if (hdl) {
24588c2ecf20Sopenharmony_ci		mutex_lock(hdl->lock);
24598c2ecf20Sopenharmony_ci		ref = find_ref(hdl, id);
24608c2ecf20Sopenharmony_ci		mutex_unlock(hdl->lock);
24618c2ecf20Sopenharmony_ci	}
24628c2ecf20Sopenharmony_ci	return ref;
24638c2ecf20Sopenharmony_ci}
24648c2ecf20Sopenharmony_ci
24658c2ecf20Sopenharmony_ci/* Find a control with the given ID. */
24668c2ecf20Sopenharmony_cistruct v4l2_ctrl *v4l2_ctrl_find(struct v4l2_ctrl_handler *hdl, u32 id)
24678c2ecf20Sopenharmony_ci{
24688c2ecf20Sopenharmony_ci	struct v4l2_ctrl_ref *ref = find_ref_lock(hdl, id);
24698c2ecf20Sopenharmony_ci
24708c2ecf20Sopenharmony_ci	return ref ? ref->ctrl : NULL;
24718c2ecf20Sopenharmony_ci}
24728c2ecf20Sopenharmony_ciEXPORT_SYMBOL(v4l2_ctrl_find);
24738c2ecf20Sopenharmony_ci
24748c2ecf20Sopenharmony_ci/* Allocate a new v4l2_ctrl_ref and hook it into the handler. */
24758c2ecf20Sopenharmony_cistatic int handler_new_ref(struct v4l2_ctrl_handler *hdl,
24768c2ecf20Sopenharmony_ci			   struct v4l2_ctrl *ctrl,
24778c2ecf20Sopenharmony_ci			   struct v4l2_ctrl_ref **ctrl_ref,
24788c2ecf20Sopenharmony_ci			   bool from_other_dev, bool allocate_req)
24798c2ecf20Sopenharmony_ci{
24808c2ecf20Sopenharmony_ci	struct v4l2_ctrl_ref *ref;
24818c2ecf20Sopenharmony_ci	struct v4l2_ctrl_ref *new_ref;
24828c2ecf20Sopenharmony_ci	u32 id = ctrl->id;
24838c2ecf20Sopenharmony_ci	u32 class_ctrl = V4L2_CTRL_ID2WHICH(id) | 1;
24848c2ecf20Sopenharmony_ci	int bucket = id % hdl->nr_of_buckets;	/* which bucket to use */
24858c2ecf20Sopenharmony_ci	unsigned int size_extra_req = 0;
24868c2ecf20Sopenharmony_ci
24878c2ecf20Sopenharmony_ci	if (ctrl_ref)
24888c2ecf20Sopenharmony_ci		*ctrl_ref = NULL;
24898c2ecf20Sopenharmony_ci
24908c2ecf20Sopenharmony_ci	/*
24918c2ecf20Sopenharmony_ci	 * Automatically add the control class if it is not yet present and
24928c2ecf20Sopenharmony_ci	 * the new control is not a compound control.
24938c2ecf20Sopenharmony_ci	 */
24948c2ecf20Sopenharmony_ci	if (ctrl->type < V4L2_CTRL_COMPOUND_TYPES &&
24958c2ecf20Sopenharmony_ci	    id != class_ctrl && find_ref_lock(hdl, class_ctrl) == NULL)
24968c2ecf20Sopenharmony_ci		if (!v4l2_ctrl_new_std(hdl, NULL, class_ctrl, 0, 0, 0, 0))
24978c2ecf20Sopenharmony_ci			return hdl->error;
24988c2ecf20Sopenharmony_ci
24998c2ecf20Sopenharmony_ci	if (hdl->error)
25008c2ecf20Sopenharmony_ci		return hdl->error;
25018c2ecf20Sopenharmony_ci
25028c2ecf20Sopenharmony_ci	if (allocate_req)
25038c2ecf20Sopenharmony_ci		size_extra_req = ctrl->elems * ctrl->elem_size;
25048c2ecf20Sopenharmony_ci	new_ref = kzalloc(sizeof(*new_ref) + size_extra_req, GFP_KERNEL);
25058c2ecf20Sopenharmony_ci	if (!new_ref)
25068c2ecf20Sopenharmony_ci		return handler_set_err(hdl, -ENOMEM);
25078c2ecf20Sopenharmony_ci	new_ref->ctrl = ctrl;
25088c2ecf20Sopenharmony_ci	new_ref->from_other_dev = from_other_dev;
25098c2ecf20Sopenharmony_ci	if (size_extra_req)
25108c2ecf20Sopenharmony_ci		new_ref->p_req.p = &new_ref[1];
25118c2ecf20Sopenharmony_ci
25128c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&new_ref->node);
25138c2ecf20Sopenharmony_ci
25148c2ecf20Sopenharmony_ci	mutex_lock(hdl->lock);
25158c2ecf20Sopenharmony_ci
25168c2ecf20Sopenharmony_ci	/* Add immediately at the end of the list if the list is empty, or if
25178c2ecf20Sopenharmony_ci	   the last element in the list has a lower ID.
25188c2ecf20Sopenharmony_ci	   This ensures that when elements are added in ascending order the
25198c2ecf20Sopenharmony_ci	   insertion is an O(1) operation. */
25208c2ecf20Sopenharmony_ci	if (list_empty(&hdl->ctrl_refs) || id > node2id(hdl->ctrl_refs.prev)) {
25218c2ecf20Sopenharmony_ci		list_add_tail(&new_ref->node, &hdl->ctrl_refs);
25228c2ecf20Sopenharmony_ci		goto insert_in_hash;
25238c2ecf20Sopenharmony_ci	}
25248c2ecf20Sopenharmony_ci
25258c2ecf20Sopenharmony_ci	/* Find insert position in sorted list */
25268c2ecf20Sopenharmony_ci	list_for_each_entry(ref, &hdl->ctrl_refs, node) {
25278c2ecf20Sopenharmony_ci		if (ref->ctrl->id < id)
25288c2ecf20Sopenharmony_ci			continue;
25298c2ecf20Sopenharmony_ci		/* Don't add duplicates */
25308c2ecf20Sopenharmony_ci		if (ref->ctrl->id == id) {
25318c2ecf20Sopenharmony_ci			kfree(new_ref);
25328c2ecf20Sopenharmony_ci			goto unlock;
25338c2ecf20Sopenharmony_ci		}
25348c2ecf20Sopenharmony_ci		list_add(&new_ref->node, ref->node.prev);
25358c2ecf20Sopenharmony_ci		break;
25368c2ecf20Sopenharmony_ci	}
25378c2ecf20Sopenharmony_ci
25388c2ecf20Sopenharmony_ciinsert_in_hash:
25398c2ecf20Sopenharmony_ci	/* Insert the control node in the hash */
25408c2ecf20Sopenharmony_ci	new_ref->next = hdl->buckets[bucket];
25418c2ecf20Sopenharmony_ci	hdl->buckets[bucket] = new_ref;
25428c2ecf20Sopenharmony_ci	if (ctrl_ref)
25438c2ecf20Sopenharmony_ci		*ctrl_ref = new_ref;
25448c2ecf20Sopenharmony_ci	if (ctrl->handler == hdl) {
25458c2ecf20Sopenharmony_ci		/* By default each control starts in a cluster of its own.
25468c2ecf20Sopenharmony_ci		 * new_ref->ctrl is basically a cluster array with one
25478c2ecf20Sopenharmony_ci		 * element, so that's perfect to use as the cluster pointer.
25488c2ecf20Sopenharmony_ci		 * But only do this for the handler that owns the control.
25498c2ecf20Sopenharmony_ci		 */
25508c2ecf20Sopenharmony_ci		ctrl->cluster = &new_ref->ctrl;
25518c2ecf20Sopenharmony_ci		ctrl->ncontrols = 1;
25528c2ecf20Sopenharmony_ci	}
25538c2ecf20Sopenharmony_ci
25548c2ecf20Sopenharmony_ciunlock:
25558c2ecf20Sopenharmony_ci	mutex_unlock(hdl->lock);
25568c2ecf20Sopenharmony_ci	return 0;
25578c2ecf20Sopenharmony_ci}
25588c2ecf20Sopenharmony_ci
25598c2ecf20Sopenharmony_ci/* Add a new control */
25608c2ecf20Sopenharmony_cistatic struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl,
25618c2ecf20Sopenharmony_ci			const struct v4l2_ctrl_ops *ops,
25628c2ecf20Sopenharmony_ci			const struct v4l2_ctrl_type_ops *type_ops,
25638c2ecf20Sopenharmony_ci			u32 id, const char *name, enum v4l2_ctrl_type type,
25648c2ecf20Sopenharmony_ci			s64 min, s64 max, u64 step, s64 def,
25658c2ecf20Sopenharmony_ci			const u32 dims[V4L2_CTRL_MAX_DIMS], u32 elem_size,
25668c2ecf20Sopenharmony_ci			u32 flags, const char * const *qmenu,
25678c2ecf20Sopenharmony_ci			const s64 *qmenu_int, const union v4l2_ctrl_ptr p_def,
25688c2ecf20Sopenharmony_ci			void *priv)
25698c2ecf20Sopenharmony_ci{
25708c2ecf20Sopenharmony_ci	struct v4l2_ctrl *ctrl;
25718c2ecf20Sopenharmony_ci	unsigned sz_extra;
25728c2ecf20Sopenharmony_ci	unsigned nr_of_dims = 0;
25738c2ecf20Sopenharmony_ci	unsigned elems = 1;
25748c2ecf20Sopenharmony_ci	bool is_array;
25758c2ecf20Sopenharmony_ci	unsigned tot_ctrl_size;
25768c2ecf20Sopenharmony_ci	unsigned idx;
25778c2ecf20Sopenharmony_ci	void *data;
25788c2ecf20Sopenharmony_ci	int err;
25798c2ecf20Sopenharmony_ci
25808c2ecf20Sopenharmony_ci	if (hdl->error)
25818c2ecf20Sopenharmony_ci		return NULL;
25828c2ecf20Sopenharmony_ci
25838c2ecf20Sopenharmony_ci	while (dims && dims[nr_of_dims]) {
25848c2ecf20Sopenharmony_ci		elems *= dims[nr_of_dims];
25858c2ecf20Sopenharmony_ci		nr_of_dims++;
25868c2ecf20Sopenharmony_ci		if (nr_of_dims == V4L2_CTRL_MAX_DIMS)
25878c2ecf20Sopenharmony_ci			break;
25888c2ecf20Sopenharmony_ci	}
25898c2ecf20Sopenharmony_ci	is_array = nr_of_dims > 0;
25908c2ecf20Sopenharmony_ci
25918c2ecf20Sopenharmony_ci	/* Prefill elem_size for all types handled by std_type_ops */
25928c2ecf20Sopenharmony_ci	switch ((u32)type) {
25938c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_INTEGER64:
25948c2ecf20Sopenharmony_ci		elem_size = sizeof(s64);
25958c2ecf20Sopenharmony_ci		break;
25968c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_STRING:
25978c2ecf20Sopenharmony_ci		elem_size = max + 1;
25988c2ecf20Sopenharmony_ci		break;
25998c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_U8:
26008c2ecf20Sopenharmony_ci		elem_size = sizeof(u8);
26018c2ecf20Sopenharmony_ci		break;
26028c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_U16:
26038c2ecf20Sopenharmony_ci		elem_size = sizeof(u16);
26048c2ecf20Sopenharmony_ci		break;
26058c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_U32:
26068c2ecf20Sopenharmony_ci		elem_size = sizeof(u32);
26078c2ecf20Sopenharmony_ci		break;
26088c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_MPEG2_SLICE_PARAMS:
26098c2ecf20Sopenharmony_ci		elem_size = sizeof(struct v4l2_ctrl_mpeg2_slice_params);
26108c2ecf20Sopenharmony_ci		break;
26118c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_MPEG2_QUANTIZATION:
26128c2ecf20Sopenharmony_ci		elem_size = sizeof(struct v4l2_ctrl_mpeg2_quantization);
26138c2ecf20Sopenharmony_ci		break;
26148c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_FWHT_PARAMS:
26158c2ecf20Sopenharmony_ci		elem_size = sizeof(struct v4l2_ctrl_fwht_params);
26168c2ecf20Sopenharmony_ci		break;
26178c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_H264_SPS:
26188c2ecf20Sopenharmony_ci		elem_size = sizeof(struct v4l2_ctrl_h264_sps);
26198c2ecf20Sopenharmony_ci		break;
26208c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_H264_PPS:
26218c2ecf20Sopenharmony_ci		elem_size = sizeof(struct v4l2_ctrl_h264_pps);
26228c2ecf20Sopenharmony_ci		break;
26238c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_H264_SCALING_MATRIX:
26248c2ecf20Sopenharmony_ci		elem_size = sizeof(struct v4l2_ctrl_h264_scaling_matrix);
26258c2ecf20Sopenharmony_ci		break;
26268c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_H264_SLICE_PARAMS:
26278c2ecf20Sopenharmony_ci		elem_size = sizeof(struct v4l2_ctrl_h264_slice_params);
26288c2ecf20Sopenharmony_ci		break;
26298c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_H264_DECODE_PARAMS:
26308c2ecf20Sopenharmony_ci		elem_size = sizeof(struct v4l2_ctrl_h264_decode_params);
26318c2ecf20Sopenharmony_ci		break;
26328c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_H264_PRED_WEIGHTS:
26338c2ecf20Sopenharmony_ci		elem_size = sizeof(struct v4l2_ctrl_h264_pred_weights);
26348c2ecf20Sopenharmony_ci		break;
26358c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_VP8_FRAME_HEADER:
26368c2ecf20Sopenharmony_ci		elem_size = sizeof(struct v4l2_ctrl_vp8_frame_header);
26378c2ecf20Sopenharmony_ci		break;
26388c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_HEVC_SPS:
26398c2ecf20Sopenharmony_ci		elem_size = sizeof(struct v4l2_ctrl_hevc_sps);
26408c2ecf20Sopenharmony_ci		break;
26418c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_HEVC_PPS:
26428c2ecf20Sopenharmony_ci		elem_size = sizeof(struct v4l2_ctrl_hevc_pps);
26438c2ecf20Sopenharmony_ci		break;
26448c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS:
26458c2ecf20Sopenharmony_ci		elem_size = sizeof(struct v4l2_ctrl_hevc_slice_params);
26468c2ecf20Sopenharmony_ci		break;
26478c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_AREA:
26488c2ecf20Sopenharmony_ci		elem_size = sizeof(struct v4l2_area);
26498c2ecf20Sopenharmony_ci		break;
26508c2ecf20Sopenharmony_ci	default:
26518c2ecf20Sopenharmony_ci		if (type < V4L2_CTRL_COMPOUND_TYPES)
26528c2ecf20Sopenharmony_ci			elem_size = sizeof(s32);
26538c2ecf20Sopenharmony_ci		break;
26548c2ecf20Sopenharmony_ci	}
26558c2ecf20Sopenharmony_ci	tot_ctrl_size = elem_size * elems;
26568c2ecf20Sopenharmony_ci
26578c2ecf20Sopenharmony_ci	/* Sanity checks */
26588c2ecf20Sopenharmony_ci	if (id == 0 || name == NULL || !elem_size ||
26598c2ecf20Sopenharmony_ci	    id >= V4L2_CID_PRIVATE_BASE ||
26608c2ecf20Sopenharmony_ci	    (type == V4L2_CTRL_TYPE_MENU && qmenu == NULL) ||
26618c2ecf20Sopenharmony_ci	    (type == V4L2_CTRL_TYPE_INTEGER_MENU && qmenu_int == NULL)) {
26628c2ecf20Sopenharmony_ci		handler_set_err(hdl, -ERANGE);
26638c2ecf20Sopenharmony_ci		return NULL;
26648c2ecf20Sopenharmony_ci	}
26658c2ecf20Sopenharmony_ci	err = check_range(type, min, max, step, def);
26668c2ecf20Sopenharmony_ci	if (err) {
26678c2ecf20Sopenharmony_ci		handler_set_err(hdl, err);
26688c2ecf20Sopenharmony_ci		return NULL;
26698c2ecf20Sopenharmony_ci	}
26708c2ecf20Sopenharmony_ci	if (is_array &&
26718c2ecf20Sopenharmony_ci	    (type == V4L2_CTRL_TYPE_BUTTON ||
26728c2ecf20Sopenharmony_ci	     type == V4L2_CTRL_TYPE_CTRL_CLASS)) {
26738c2ecf20Sopenharmony_ci		handler_set_err(hdl, -EINVAL);
26748c2ecf20Sopenharmony_ci		return NULL;
26758c2ecf20Sopenharmony_ci	}
26768c2ecf20Sopenharmony_ci
26778c2ecf20Sopenharmony_ci	sz_extra = 0;
26788c2ecf20Sopenharmony_ci	if (type == V4L2_CTRL_TYPE_BUTTON)
26798c2ecf20Sopenharmony_ci		flags |= V4L2_CTRL_FLAG_WRITE_ONLY |
26808c2ecf20Sopenharmony_ci			V4L2_CTRL_FLAG_EXECUTE_ON_WRITE;
26818c2ecf20Sopenharmony_ci	else if (type == V4L2_CTRL_TYPE_CTRL_CLASS)
26828c2ecf20Sopenharmony_ci		flags |= V4L2_CTRL_FLAG_READ_ONLY;
26838c2ecf20Sopenharmony_ci	else if (type == V4L2_CTRL_TYPE_INTEGER64 ||
26848c2ecf20Sopenharmony_ci		 type == V4L2_CTRL_TYPE_STRING ||
26858c2ecf20Sopenharmony_ci		 type >= V4L2_CTRL_COMPOUND_TYPES ||
26868c2ecf20Sopenharmony_ci		 is_array)
26878c2ecf20Sopenharmony_ci		sz_extra += 2 * tot_ctrl_size;
26888c2ecf20Sopenharmony_ci
26898c2ecf20Sopenharmony_ci	if (type >= V4L2_CTRL_COMPOUND_TYPES && p_def.p_const)
26908c2ecf20Sopenharmony_ci		sz_extra += elem_size;
26918c2ecf20Sopenharmony_ci
26928c2ecf20Sopenharmony_ci	ctrl = kvzalloc(sizeof(*ctrl) + sz_extra, GFP_KERNEL);
26938c2ecf20Sopenharmony_ci	if (ctrl == NULL) {
26948c2ecf20Sopenharmony_ci		handler_set_err(hdl, -ENOMEM);
26958c2ecf20Sopenharmony_ci		return NULL;
26968c2ecf20Sopenharmony_ci	}
26978c2ecf20Sopenharmony_ci
26988c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&ctrl->node);
26998c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&ctrl->ev_subs);
27008c2ecf20Sopenharmony_ci	ctrl->handler = hdl;
27018c2ecf20Sopenharmony_ci	ctrl->ops = ops;
27028c2ecf20Sopenharmony_ci	ctrl->type_ops = type_ops ? type_ops : &std_type_ops;
27038c2ecf20Sopenharmony_ci	ctrl->id = id;
27048c2ecf20Sopenharmony_ci	ctrl->name = name;
27058c2ecf20Sopenharmony_ci	ctrl->type = type;
27068c2ecf20Sopenharmony_ci	ctrl->flags = flags;
27078c2ecf20Sopenharmony_ci	ctrl->minimum = min;
27088c2ecf20Sopenharmony_ci	ctrl->maximum = max;
27098c2ecf20Sopenharmony_ci	ctrl->step = step;
27108c2ecf20Sopenharmony_ci	ctrl->default_value = def;
27118c2ecf20Sopenharmony_ci	ctrl->is_string = !is_array && type == V4L2_CTRL_TYPE_STRING;
27128c2ecf20Sopenharmony_ci	ctrl->is_ptr = is_array || type >= V4L2_CTRL_COMPOUND_TYPES || ctrl->is_string;
27138c2ecf20Sopenharmony_ci	ctrl->is_int = !ctrl->is_ptr && type != V4L2_CTRL_TYPE_INTEGER64;
27148c2ecf20Sopenharmony_ci	ctrl->is_array = is_array;
27158c2ecf20Sopenharmony_ci	ctrl->elems = elems;
27168c2ecf20Sopenharmony_ci	ctrl->nr_of_dims = nr_of_dims;
27178c2ecf20Sopenharmony_ci	if (nr_of_dims)
27188c2ecf20Sopenharmony_ci		memcpy(ctrl->dims, dims, nr_of_dims * sizeof(dims[0]));
27198c2ecf20Sopenharmony_ci	ctrl->elem_size = elem_size;
27208c2ecf20Sopenharmony_ci	if (type == V4L2_CTRL_TYPE_MENU)
27218c2ecf20Sopenharmony_ci		ctrl->qmenu = qmenu;
27228c2ecf20Sopenharmony_ci	else if (type == V4L2_CTRL_TYPE_INTEGER_MENU)
27238c2ecf20Sopenharmony_ci		ctrl->qmenu_int = qmenu_int;
27248c2ecf20Sopenharmony_ci	ctrl->priv = priv;
27258c2ecf20Sopenharmony_ci	ctrl->cur.val = ctrl->val = def;
27268c2ecf20Sopenharmony_ci	data = &ctrl[1];
27278c2ecf20Sopenharmony_ci
27288c2ecf20Sopenharmony_ci	if (!ctrl->is_int) {
27298c2ecf20Sopenharmony_ci		ctrl->p_new.p = data;
27308c2ecf20Sopenharmony_ci		ctrl->p_cur.p = data + tot_ctrl_size;
27318c2ecf20Sopenharmony_ci	} else {
27328c2ecf20Sopenharmony_ci		ctrl->p_new.p = &ctrl->val;
27338c2ecf20Sopenharmony_ci		ctrl->p_cur.p = &ctrl->cur.val;
27348c2ecf20Sopenharmony_ci	}
27358c2ecf20Sopenharmony_ci
27368c2ecf20Sopenharmony_ci	if (type >= V4L2_CTRL_COMPOUND_TYPES && p_def.p_const) {
27378c2ecf20Sopenharmony_ci		ctrl->p_def.p = ctrl->p_cur.p + tot_ctrl_size;
27388c2ecf20Sopenharmony_ci		memcpy(ctrl->p_def.p, p_def.p_const, elem_size);
27398c2ecf20Sopenharmony_ci	}
27408c2ecf20Sopenharmony_ci
27418c2ecf20Sopenharmony_ci	for (idx = 0; idx < elems; idx++) {
27428c2ecf20Sopenharmony_ci		ctrl->type_ops->init(ctrl, idx, ctrl->p_cur);
27438c2ecf20Sopenharmony_ci		ctrl->type_ops->init(ctrl, idx, ctrl->p_new);
27448c2ecf20Sopenharmony_ci	}
27458c2ecf20Sopenharmony_ci
27468c2ecf20Sopenharmony_ci	if (handler_new_ref(hdl, ctrl, NULL, false, false)) {
27478c2ecf20Sopenharmony_ci		kvfree(ctrl);
27488c2ecf20Sopenharmony_ci		return NULL;
27498c2ecf20Sopenharmony_ci	}
27508c2ecf20Sopenharmony_ci	mutex_lock(hdl->lock);
27518c2ecf20Sopenharmony_ci	list_add_tail(&ctrl->node, &hdl->ctrls);
27528c2ecf20Sopenharmony_ci	mutex_unlock(hdl->lock);
27538c2ecf20Sopenharmony_ci	return ctrl;
27548c2ecf20Sopenharmony_ci}
27558c2ecf20Sopenharmony_ci
27568c2ecf20Sopenharmony_cistruct v4l2_ctrl *v4l2_ctrl_new_custom(struct v4l2_ctrl_handler *hdl,
27578c2ecf20Sopenharmony_ci			const struct v4l2_ctrl_config *cfg, void *priv)
27588c2ecf20Sopenharmony_ci{
27598c2ecf20Sopenharmony_ci	bool is_menu;
27608c2ecf20Sopenharmony_ci	struct v4l2_ctrl *ctrl;
27618c2ecf20Sopenharmony_ci	const char *name = cfg->name;
27628c2ecf20Sopenharmony_ci	const char * const *qmenu = cfg->qmenu;
27638c2ecf20Sopenharmony_ci	const s64 *qmenu_int = cfg->qmenu_int;
27648c2ecf20Sopenharmony_ci	enum v4l2_ctrl_type type = cfg->type;
27658c2ecf20Sopenharmony_ci	u32 flags = cfg->flags;
27668c2ecf20Sopenharmony_ci	s64 min = cfg->min;
27678c2ecf20Sopenharmony_ci	s64 max = cfg->max;
27688c2ecf20Sopenharmony_ci	u64 step = cfg->step;
27698c2ecf20Sopenharmony_ci	s64 def = cfg->def;
27708c2ecf20Sopenharmony_ci
27718c2ecf20Sopenharmony_ci	if (name == NULL)
27728c2ecf20Sopenharmony_ci		v4l2_ctrl_fill(cfg->id, &name, &type, &min, &max, &step,
27738c2ecf20Sopenharmony_ci								&def, &flags);
27748c2ecf20Sopenharmony_ci
27758c2ecf20Sopenharmony_ci	is_menu = (type == V4L2_CTRL_TYPE_MENU ||
27768c2ecf20Sopenharmony_ci		   type == V4L2_CTRL_TYPE_INTEGER_MENU);
27778c2ecf20Sopenharmony_ci	if (is_menu)
27788c2ecf20Sopenharmony_ci		WARN_ON(step);
27798c2ecf20Sopenharmony_ci	else
27808c2ecf20Sopenharmony_ci		WARN_ON(cfg->menu_skip_mask);
27818c2ecf20Sopenharmony_ci	if (type == V4L2_CTRL_TYPE_MENU && !qmenu) {
27828c2ecf20Sopenharmony_ci		qmenu = v4l2_ctrl_get_menu(cfg->id);
27838c2ecf20Sopenharmony_ci	} else if (type == V4L2_CTRL_TYPE_INTEGER_MENU && !qmenu_int) {
27848c2ecf20Sopenharmony_ci		handler_set_err(hdl, -EINVAL);
27858c2ecf20Sopenharmony_ci		return NULL;
27868c2ecf20Sopenharmony_ci	}
27878c2ecf20Sopenharmony_ci
27888c2ecf20Sopenharmony_ci	ctrl = v4l2_ctrl_new(hdl, cfg->ops, cfg->type_ops, cfg->id, name,
27898c2ecf20Sopenharmony_ci			type, min, max,
27908c2ecf20Sopenharmony_ci			is_menu ? cfg->menu_skip_mask : step, def,
27918c2ecf20Sopenharmony_ci			cfg->dims, cfg->elem_size,
27928c2ecf20Sopenharmony_ci			flags, qmenu, qmenu_int, cfg->p_def, priv);
27938c2ecf20Sopenharmony_ci	if (ctrl)
27948c2ecf20Sopenharmony_ci		ctrl->is_private = cfg->is_private;
27958c2ecf20Sopenharmony_ci	return ctrl;
27968c2ecf20Sopenharmony_ci}
27978c2ecf20Sopenharmony_ciEXPORT_SYMBOL(v4l2_ctrl_new_custom);
27988c2ecf20Sopenharmony_ci
27998c2ecf20Sopenharmony_ci/* Helper function for standard non-menu controls */
28008c2ecf20Sopenharmony_cistruct v4l2_ctrl *v4l2_ctrl_new_std(struct v4l2_ctrl_handler *hdl,
28018c2ecf20Sopenharmony_ci			const struct v4l2_ctrl_ops *ops,
28028c2ecf20Sopenharmony_ci			u32 id, s64 min, s64 max, u64 step, s64 def)
28038c2ecf20Sopenharmony_ci{
28048c2ecf20Sopenharmony_ci	const char *name;
28058c2ecf20Sopenharmony_ci	enum v4l2_ctrl_type type;
28068c2ecf20Sopenharmony_ci	u32 flags;
28078c2ecf20Sopenharmony_ci
28088c2ecf20Sopenharmony_ci	v4l2_ctrl_fill(id, &name, &type, &min, &max, &step, &def, &flags);
28098c2ecf20Sopenharmony_ci	if (type == V4L2_CTRL_TYPE_MENU ||
28108c2ecf20Sopenharmony_ci	    type == V4L2_CTRL_TYPE_INTEGER_MENU ||
28118c2ecf20Sopenharmony_ci	    type >= V4L2_CTRL_COMPOUND_TYPES) {
28128c2ecf20Sopenharmony_ci		handler_set_err(hdl, -EINVAL);
28138c2ecf20Sopenharmony_ci		return NULL;
28148c2ecf20Sopenharmony_ci	}
28158c2ecf20Sopenharmony_ci	return v4l2_ctrl_new(hdl, ops, NULL, id, name, type,
28168c2ecf20Sopenharmony_ci			     min, max, step, def, NULL, 0,
28178c2ecf20Sopenharmony_ci			     flags, NULL, NULL, ptr_null, NULL);
28188c2ecf20Sopenharmony_ci}
28198c2ecf20Sopenharmony_ciEXPORT_SYMBOL(v4l2_ctrl_new_std);
28208c2ecf20Sopenharmony_ci
28218c2ecf20Sopenharmony_ci/* Helper function for standard menu controls */
28228c2ecf20Sopenharmony_cistruct v4l2_ctrl *v4l2_ctrl_new_std_menu(struct v4l2_ctrl_handler *hdl,
28238c2ecf20Sopenharmony_ci			const struct v4l2_ctrl_ops *ops,
28248c2ecf20Sopenharmony_ci			u32 id, u8 _max, u64 mask, u8 _def)
28258c2ecf20Sopenharmony_ci{
28268c2ecf20Sopenharmony_ci	const char * const *qmenu = NULL;
28278c2ecf20Sopenharmony_ci	const s64 *qmenu_int = NULL;
28288c2ecf20Sopenharmony_ci	unsigned int qmenu_int_len = 0;
28298c2ecf20Sopenharmony_ci	const char *name;
28308c2ecf20Sopenharmony_ci	enum v4l2_ctrl_type type;
28318c2ecf20Sopenharmony_ci	s64 min;
28328c2ecf20Sopenharmony_ci	s64 max = _max;
28338c2ecf20Sopenharmony_ci	s64 def = _def;
28348c2ecf20Sopenharmony_ci	u64 step;
28358c2ecf20Sopenharmony_ci	u32 flags;
28368c2ecf20Sopenharmony_ci
28378c2ecf20Sopenharmony_ci	v4l2_ctrl_fill(id, &name, &type, &min, &max, &step, &def, &flags);
28388c2ecf20Sopenharmony_ci
28398c2ecf20Sopenharmony_ci	if (type == V4L2_CTRL_TYPE_MENU)
28408c2ecf20Sopenharmony_ci		qmenu = v4l2_ctrl_get_menu(id);
28418c2ecf20Sopenharmony_ci	else if (type == V4L2_CTRL_TYPE_INTEGER_MENU)
28428c2ecf20Sopenharmony_ci		qmenu_int = v4l2_ctrl_get_int_menu(id, &qmenu_int_len);
28438c2ecf20Sopenharmony_ci
28448c2ecf20Sopenharmony_ci	if ((!qmenu && !qmenu_int) || (qmenu_int && max > qmenu_int_len)) {
28458c2ecf20Sopenharmony_ci		handler_set_err(hdl, -EINVAL);
28468c2ecf20Sopenharmony_ci		return NULL;
28478c2ecf20Sopenharmony_ci	}
28488c2ecf20Sopenharmony_ci	return v4l2_ctrl_new(hdl, ops, NULL, id, name, type,
28498c2ecf20Sopenharmony_ci			     0, max, mask, def, NULL, 0,
28508c2ecf20Sopenharmony_ci			     flags, qmenu, qmenu_int, ptr_null, NULL);
28518c2ecf20Sopenharmony_ci}
28528c2ecf20Sopenharmony_ciEXPORT_SYMBOL(v4l2_ctrl_new_std_menu);
28538c2ecf20Sopenharmony_ci
28548c2ecf20Sopenharmony_ci/* Helper function for standard menu controls with driver defined menu */
28558c2ecf20Sopenharmony_cistruct v4l2_ctrl *v4l2_ctrl_new_std_menu_items(struct v4l2_ctrl_handler *hdl,
28568c2ecf20Sopenharmony_ci			const struct v4l2_ctrl_ops *ops, u32 id, u8 _max,
28578c2ecf20Sopenharmony_ci			u64 mask, u8 _def, const char * const *qmenu)
28588c2ecf20Sopenharmony_ci{
28598c2ecf20Sopenharmony_ci	enum v4l2_ctrl_type type;
28608c2ecf20Sopenharmony_ci	const char *name;
28618c2ecf20Sopenharmony_ci	u32 flags;
28628c2ecf20Sopenharmony_ci	u64 step;
28638c2ecf20Sopenharmony_ci	s64 min;
28648c2ecf20Sopenharmony_ci	s64 max = _max;
28658c2ecf20Sopenharmony_ci	s64 def = _def;
28668c2ecf20Sopenharmony_ci
28678c2ecf20Sopenharmony_ci	/* v4l2_ctrl_new_std_menu_items() should only be called for
28688c2ecf20Sopenharmony_ci	 * standard controls without a standard menu.
28698c2ecf20Sopenharmony_ci	 */
28708c2ecf20Sopenharmony_ci	if (v4l2_ctrl_get_menu(id)) {
28718c2ecf20Sopenharmony_ci		handler_set_err(hdl, -EINVAL);
28728c2ecf20Sopenharmony_ci		return NULL;
28738c2ecf20Sopenharmony_ci	}
28748c2ecf20Sopenharmony_ci
28758c2ecf20Sopenharmony_ci	v4l2_ctrl_fill(id, &name, &type, &min, &max, &step, &def, &flags);
28768c2ecf20Sopenharmony_ci	if (type != V4L2_CTRL_TYPE_MENU || qmenu == NULL) {
28778c2ecf20Sopenharmony_ci		handler_set_err(hdl, -EINVAL);
28788c2ecf20Sopenharmony_ci		return NULL;
28798c2ecf20Sopenharmony_ci	}
28808c2ecf20Sopenharmony_ci	return v4l2_ctrl_new(hdl, ops, NULL, id, name, type,
28818c2ecf20Sopenharmony_ci			     0, max, mask, def, NULL, 0,
28828c2ecf20Sopenharmony_ci			     flags, qmenu, NULL, ptr_null, NULL);
28838c2ecf20Sopenharmony_ci
28848c2ecf20Sopenharmony_ci}
28858c2ecf20Sopenharmony_ciEXPORT_SYMBOL(v4l2_ctrl_new_std_menu_items);
28868c2ecf20Sopenharmony_ci
28878c2ecf20Sopenharmony_ci/* Helper function for standard compound controls */
28888c2ecf20Sopenharmony_cistruct v4l2_ctrl *v4l2_ctrl_new_std_compound(struct v4l2_ctrl_handler *hdl,
28898c2ecf20Sopenharmony_ci				const struct v4l2_ctrl_ops *ops, u32 id,
28908c2ecf20Sopenharmony_ci				const union v4l2_ctrl_ptr p_def)
28918c2ecf20Sopenharmony_ci{
28928c2ecf20Sopenharmony_ci	const char *name;
28938c2ecf20Sopenharmony_ci	enum v4l2_ctrl_type type;
28948c2ecf20Sopenharmony_ci	u32 flags;
28958c2ecf20Sopenharmony_ci	s64 min, max, step, def;
28968c2ecf20Sopenharmony_ci
28978c2ecf20Sopenharmony_ci	v4l2_ctrl_fill(id, &name, &type, &min, &max, &step, &def, &flags);
28988c2ecf20Sopenharmony_ci	if (type < V4L2_CTRL_COMPOUND_TYPES) {
28998c2ecf20Sopenharmony_ci		handler_set_err(hdl, -EINVAL);
29008c2ecf20Sopenharmony_ci		return NULL;
29018c2ecf20Sopenharmony_ci	}
29028c2ecf20Sopenharmony_ci	return v4l2_ctrl_new(hdl, ops, NULL, id, name, type,
29038c2ecf20Sopenharmony_ci			     min, max, step, def, NULL, 0,
29048c2ecf20Sopenharmony_ci			     flags, NULL, NULL, p_def, NULL);
29058c2ecf20Sopenharmony_ci}
29068c2ecf20Sopenharmony_ciEXPORT_SYMBOL(v4l2_ctrl_new_std_compound);
29078c2ecf20Sopenharmony_ci
29088c2ecf20Sopenharmony_ci/* Helper function for standard integer menu controls */
29098c2ecf20Sopenharmony_cistruct v4l2_ctrl *v4l2_ctrl_new_int_menu(struct v4l2_ctrl_handler *hdl,
29108c2ecf20Sopenharmony_ci			const struct v4l2_ctrl_ops *ops,
29118c2ecf20Sopenharmony_ci			u32 id, u8 _max, u8 _def, const s64 *qmenu_int)
29128c2ecf20Sopenharmony_ci{
29138c2ecf20Sopenharmony_ci	const char *name;
29148c2ecf20Sopenharmony_ci	enum v4l2_ctrl_type type;
29158c2ecf20Sopenharmony_ci	s64 min;
29168c2ecf20Sopenharmony_ci	u64 step;
29178c2ecf20Sopenharmony_ci	s64 max = _max;
29188c2ecf20Sopenharmony_ci	s64 def = _def;
29198c2ecf20Sopenharmony_ci	u32 flags;
29208c2ecf20Sopenharmony_ci
29218c2ecf20Sopenharmony_ci	v4l2_ctrl_fill(id, &name, &type, &min, &max, &step, &def, &flags);
29228c2ecf20Sopenharmony_ci	if (type != V4L2_CTRL_TYPE_INTEGER_MENU) {
29238c2ecf20Sopenharmony_ci		handler_set_err(hdl, -EINVAL);
29248c2ecf20Sopenharmony_ci		return NULL;
29258c2ecf20Sopenharmony_ci	}
29268c2ecf20Sopenharmony_ci	return v4l2_ctrl_new(hdl, ops, NULL, id, name, type,
29278c2ecf20Sopenharmony_ci			     0, max, 0, def, NULL, 0,
29288c2ecf20Sopenharmony_ci			     flags, NULL, qmenu_int, ptr_null, NULL);
29298c2ecf20Sopenharmony_ci}
29308c2ecf20Sopenharmony_ciEXPORT_SYMBOL(v4l2_ctrl_new_int_menu);
29318c2ecf20Sopenharmony_ci
29328c2ecf20Sopenharmony_ci/* Add the controls from another handler to our own. */
29338c2ecf20Sopenharmony_ciint v4l2_ctrl_add_handler(struct v4l2_ctrl_handler *hdl,
29348c2ecf20Sopenharmony_ci			  struct v4l2_ctrl_handler *add,
29358c2ecf20Sopenharmony_ci			  bool (*filter)(const struct v4l2_ctrl *ctrl),
29368c2ecf20Sopenharmony_ci			  bool from_other_dev)
29378c2ecf20Sopenharmony_ci{
29388c2ecf20Sopenharmony_ci	struct v4l2_ctrl_ref *ref;
29398c2ecf20Sopenharmony_ci	int ret = 0;
29408c2ecf20Sopenharmony_ci
29418c2ecf20Sopenharmony_ci	/* Do nothing if either handler is NULL or if they are the same */
29428c2ecf20Sopenharmony_ci	if (!hdl || !add || hdl == add)
29438c2ecf20Sopenharmony_ci		return 0;
29448c2ecf20Sopenharmony_ci	if (hdl->error)
29458c2ecf20Sopenharmony_ci		return hdl->error;
29468c2ecf20Sopenharmony_ci	mutex_lock(add->lock);
29478c2ecf20Sopenharmony_ci	list_for_each_entry(ref, &add->ctrl_refs, node) {
29488c2ecf20Sopenharmony_ci		struct v4l2_ctrl *ctrl = ref->ctrl;
29498c2ecf20Sopenharmony_ci
29508c2ecf20Sopenharmony_ci		/* Skip handler-private controls. */
29518c2ecf20Sopenharmony_ci		if (ctrl->is_private)
29528c2ecf20Sopenharmony_ci			continue;
29538c2ecf20Sopenharmony_ci		/* And control classes */
29548c2ecf20Sopenharmony_ci		if (ctrl->type == V4L2_CTRL_TYPE_CTRL_CLASS)
29558c2ecf20Sopenharmony_ci			continue;
29568c2ecf20Sopenharmony_ci		/* Filter any unwanted controls */
29578c2ecf20Sopenharmony_ci		if (filter && !filter(ctrl))
29588c2ecf20Sopenharmony_ci			continue;
29598c2ecf20Sopenharmony_ci		ret = handler_new_ref(hdl, ctrl, NULL, from_other_dev, false);
29608c2ecf20Sopenharmony_ci		if (ret)
29618c2ecf20Sopenharmony_ci			break;
29628c2ecf20Sopenharmony_ci	}
29638c2ecf20Sopenharmony_ci	mutex_unlock(add->lock);
29648c2ecf20Sopenharmony_ci	return ret;
29658c2ecf20Sopenharmony_ci}
29668c2ecf20Sopenharmony_ciEXPORT_SYMBOL(v4l2_ctrl_add_handler);
29678c2ecf20Sopenharmony_ci
29688c2ecf20Sopenharmony_cibool v4l2_ctrl_radio_filter(const struct v4l2_ctrl *ctrl)
29698c2ecf20Sopenharmony_ci{
29708c2ecf20Sopenharmony_ci	if (V4L2_CTRL_ID2WHICH(ctrl->id) == V4L2_CTRL_CLASS_FM_TX)
29718c2ecf20Sopenharmony_ci		return true;
29728c2ecf20Sopenharmony_ci	if (V4L2_CTRL_ID2WHICH(ctrl->id) == V4L2_CTRL_CLASS_FM_RX)
29738c2ecf20Sopenharmony_ci		return true;
29748c2ecf20Sopenharmony_ci	switch (ctrl->id) {
29758c2ecf20Sopenharmony_ci	case V4L2_CID_AUDIO_MUTE:
29768c2ecf20Sopenharmony_ci	case V4L2_CID_AUDIO_VOLUME:
29778c2ecf20Sopenharmony_ci	case V4L2_CID_AUDIO_BALANCE:
29788c2ecf20Sopenharmony_ci	case V4L2_CID_AUDIO_BASS:
29798c2ecf20Sopenharmony_ci	case V4L2_CID_AUDIO_TREBLE:
29808c2ecf20Sopenharmony_ci	case V4L2_CID_AUDIO_LOUDNESS:
29818c2ecf20Sopenharmony_ci		return true;
29828c2ecf20Sopenharmony_ci	default:
29838c2ecf20Sopenharmony_ci		break;
29848c2ecf20Sopenharmony_ci	}
29858c2ecf20Sopenharmony_ci	return false;
29868c2ecf20Sopenharmony_ci}
29878c2ecf20Sopenharmony_ciEXPORT_SYMBOL(v4l2_ctrl_radio_filter);
29888c2ecf20Sopenharmony_ci
29898c2ecf20Sopenharmony_ci/* Cluster controls */
29908c2ecf20Sopenharmony_civoid v4l2_ctrl_cluster(unsigned ncontrols, struct v4l2_ctrl **controls)
29918c2ecf20Sopenharmony_ci{
29928c2ecf20Sopenharmony_ci	bool has_volatiles = false;
29938c2ecf20Sopenharmony_ci	int i;
29948c2ecf20Sopenharmony_ci
29958c2ecf20Sopenharmony_ci	/* The first control is the master control and it must not be NULL */
29968c2ecf20Sopenharmony_ci	if (WARN_ON(ncontrols == 0 || controls[0] == NULL))
29978c2ecf20Sopenharmony_ci		return;
29988c2ecf20Sopenharmony_ci
29998c2ecf20Sopenharmony_ci	for (i = 0; i < ncontrols; i++) {
30008c2ecf20Sopenharmony_ci		if (controls[i]) {
30018c2ecf20Sopenharmony_ci			controls[i]->cluster = controls;
30028c2ecf20Sopenharmony_ci			controls[i]->ncontrols = ncontrols;
30038c2ecf20Sopenharmony_ci			if (controls[i]->flags & V4L2_CTRL_FLAG_VOLATILE)
30048c2ecf20Sopenharmony_ci				has_volatiles = true;
30058c2ecf20Sopenharmony_ci		}
30068c2ecf20Sopenharmony_ci	}
30078c2ecf20Sopenharmony_ci	controls[0]->has_volatiles = has_volatiles;
30088c2ecf20Sopenharmony_ci}
30098c2ecf20Sopenharmony_ciEXPORT_SYMBOL(v4l2_ctrl_cluster);
30108c2ecf20Sopenharmony_ci
30118c2ecf20Sopenharmony_civoid v4l2_ctrl_auto_cluster(unsigned ncontrols, struct v4l2_ctrl **controls,
30128c2ecf20Sopenharmony_ci			    u8 manual_val, bool set_volatile)
30138c2ecf20Sopenharmony_ci{
30148c2ecf20Sopenharmony_ci	struct v4l2_ctrl *master = controls[0];
30158c2ecf20Sopenharmony_ci	u32 flag = 0;
30168c2ecf20Sopenharmony_ci	int i;
30178c2ecf20Sopenharmony_ci
30188c2ecf20Sopenharmony_ci	v4l2_ctrl_cluster(ncontrols, controls);
30198c2ecf20Sopenharmony_ci	WARN_ON(ncontrols <= 1);
30208c2ecf20Sopenharmony_ci	WARN_ON(manual_val < master->minimum || manual_val > master->maximum);
30218c2ecf20Sopenharmony_ci	WARN_ON(set_volatile && !has_op(master, g_volatile_ctrl));
30228c2ecf20Sopenharmony_ci	master->is_auto = true;
30238c2ecf20Sopenharmony_ci	master->has_volatiles = set_volatile;
30248c2ecf20Sopenharmony_ci	master->manual_mode_value = manual_val;
30258c2ecf20Sopenharmony_ci	master->flags |= V4L2_CTRL_FLAG_UPDATE;
30268c2ecf20Sopenharmony_ci
30278c2ecf20Sopenharmony_ci	if (!is_cur_manual(master))
30288c2ecf20Sopenharmony_ci		flag = V4L2_CTRL_FLAG_INACTIVE |
30298c2ecf20Sopenharmony_ci			(set_volatile ? V4L2_CTRL_FLAG_VOLATILE : 0);
30308c2ecf20Sopenharmony_ci
30318c2ecf20Sopenharmony_ci	for (i = 1; i < ncontrols; i++)
30328c2ecf20Sopenharmony_ci		if (controls[i])
30338c2ecf20Sopenharmony_ci			controls[i]->flags |= flag;
30348c2ecf20Sopenharmony_ci}
30358c2ecf20Sopenharmony_ciEXPORT_SYMBOL(v4l2_ctrl_auto_cluster);
30368c2ecf20Sopenharmony_ci
30378c2ecf20Sopenharmony_ci/* Activate/deactivate a control. */
30388c2ecf20Sopenharmony_civoid v4l2_ctrl_activate(struct v4l2_ctrl *ctrl, bool active)
30398c2ecf20Sopenharmony_ci{
30408c2ecf20Sopenharmony_ci	/* invert since the actual flag is called 'inactive' */
30418c2ecf20Sopenharmony_ci	bool inactive = !active;
30428c2ecf20Sopenharmony_ci	bool old;
30438c2ecf20Sopenharmony_ci
30448c2ecf20Sopenharmony_ci	if (ctrl == NULL)
30458c2ecf20Sopenharmony_ci		return;
30468c2ecf20Sopenharmony_ci
30478c2ecf20Sopenharmony_ci	if (inactive)
30488c2ecf20Sopenharmony_ci		/* set V4L2_CTRL_FLAG_INACTIVE */
30498c2ecf20Sopenharmony_ci		old = test_and_set_bit(4, &ctrl->flags);
30508c2ecf20Sopenharmony_ci	else
30518c2ecf20Sopenharmony_ci		/* clear V4L2_CTRL_FLAG_INACTIVE */
30528c2ecf20Sopenharmony_ci		old = test_and_clear_bit(4, &ctrl->flags);
30538c2ecf20Sopenharmony_ci	if (old != inactive)
30548c2ecf20Sopenharmony_ci		send_event(NULL, ctrl, V4L2_EVENT_CTRL_CH_FLAGS);
30558c2ecf20Sopenharmony_ci}
30568c2ecf20Sopenharmony_ciEXPORT_SYMBOL(v4l2_ctrl_activate);
30578c2ecf20Sopenharmony_ci
30588c2ecf20Sopenharmony_civoid __v4l2_ctrl_grab(struct v4l2_ctrl *ctrl, bool grabbed)
30598c2ecf20Sopenharmony_ci{
30608c2ecf20Sopenharmony_ci	bool old;
30618c2ecf20Sopenharmony_ci
30628c2ecf20Sopenharmony_ci	if (ctrl == NULL)
30638c2ecf20Sopenharmony_ci		return;
30648c2ecf20Sopenharmony_ci
30658c2ecf20Sopenharmony_ci	lockdep_assert_held(ctrl->handler->lock);
30668c2ecf20Sopenharmony_ci
30678c2ecf20Sopenharmony_ci	if (grabbed)
30688c2ecf20Sopenharmony_ci		/* set V4L2_CTRL_FLAG_GRABBED */
30698c2ecf20Sopenharmony_ci		old = test_and_set_bit(1, &ctrl->flags);
30708c2ecf20Sopenharmony_ci	else
30718c2ecf20Sopenharmony_ci		/* clear V4L2_CTRL_FLAG_GRABBED */
30728c2ecf20Sopenharmony_ci		old = test_and_clear_bit(1, &ctrl->flags);
30738c2ecf20Sopenharmony_ci	if (old != grabbed)
30748c2ecf20Sopenharmony_ci		send_event(NULL, ctrl, V4L2_EVENT_CTRL_CH_FLAGS);
30758c2ecf20Sopenharmony_ci}
30768c2ecf20Sopenharmony_ciEXPORT_SYMBOL(__v4l2_ctrl_grab);
30778c2ecf20Sopenharmony_ci
30788c2ecf20Sopenharmony_ci/* Log the control name and value */
30798c2ecf20Sopenharmony_cistatic void log_ctrl(const struct v4l2_ctrl *ctrl,
30808c2ecf20Sopenharmony_ci		     const char *prefix, const char *colon)
30818c2ecf20Sopenharmony_ci{
30828c2ecf20Sopenharmony_ci	if (ctrl->flags & (V4L2_CTRL_FLAG_DISABLED | V4L2_CTRL_FLAG_WRITE_ONLY))
30838c2ecf20Sopenharmony_ci		return;
30848c2ecf20Sopenharmony_ci	if (ctrl->type == V4L2_CTRL_TYPE_CTRL_CLASS)
30858c2ecf20Sopenharmony_ci		return;
30868c2ecf20Sopenharmony_ci
30878c2ecf20Sopenharmony_ci	pr_info("%s%s%s: ", prefix, colon, ctrl->name);
30888c2ecf20Sopenharmony_ci
30898c2ecf20Sopenharmony_ci	ctrl->type_ops->log(ctrl);
30908c2ecf20Sopenharmony_ci
30918c2ecf20Sopenharmony_ci	if (ctrl->flags & (V4L2_CTRL_FLAG_INACTIVE |
30928c2ecf20Sopenharmony_ci			   V4L2_CTRL_FLAG_GRABBED |
30938c2ecf20Sopenharmony_ci			   V4L2_CTRL_FLAG_VOLATILE)) {
30948c2ecf20Sopenharmony_ci		if (ctrl->flags & V4L2_CTRL_FLAG_INACTIVE)
30958c2ecf20Sopenharmony_ci			pr_cont(" inactive");
30968c2ecf20Sopenharmony_ci		if (ctrl->flags & V4L2_CTRL_FLAG_GRABBED)
30978c2ecf20Sopenharmony_ci			pr_cont(" grabbed");
30988c2ecf20Sopenharmony_ci		if (ctrl->flags & V4L2_CTRL_FLAG_VOLATILE)
30998c2ecf20Sopenharmony_ci			pr_cont(" volatile");
31008c2ecf20Sopenharmony_ci	}
31018c2ecf20Sopenharmony_ci	pr_cont("\n");
31028c2ecf20Sopenharmony_ci}
31038c2ecf20Sopenharmony_ci
31048c2ecf20Sopenharmony_ci/* Log all controls owned by the handler */
31058c2ecf20Sopenharmony_civoid v4l2_ctrl_handler_log_status(struct v4l2_ctrl_handler *hdl,
31068c2ecf20Sopenharmony_ci				  const char *prefix)
31078c2ecf20Sopenharmony_ci{
31088c2ecf20Sopenharmony_ci	struct v4l2_ctrl *ctrl;
31098c2ecf20Sopenharmony_ci	const char *colon = "";
31108c2ecf20Sopenharmony_ci	int len;
31118c2ecf20Sopenharmony_ci
31128c2ecf20Sopenharmony_ci	if (hdl == NULL)
31138c2ecf20Sopenharmony_ci		return;
31148c2ecf20Sopenharmony_ci	if (prefix == NULL)
31158c2ecf20Sopenharmony_ci		prefix = "";
31168c2ecf20Sopenharmony_ci	len = strlen(prefix);
31178c2ecf20Sopenharmony_ci	if (len && prefix[len - 1] != ' ')
31188c2ecf20Sopenharmony_ci		colon = ": ";
31198c2ecf20Sopenharmony_ci	mutex_lock(hdl->lock);
31208c2ecf20Sopenharmony_ci	list_for_each_entry(ctrl, &hdl->ctrls, node)
31218c2ecf20Sopenharmony_ci		if (!(ctrl->flags & V4L2_CTRL_FLAG_DISABLED))
31228c2ecf20Sopenharmony_ci			log_ctrl(ctrl, prefix, colon);
31238c2ecf20Sopenharmony_ci	mutex_unlock(hdl->lock);
31248c2ecf20Sopenharmony_ci}
31258c2ecf20Sopenharmony_ciEXPORT_SYMBOL(v4l2_ctrl_handler_log_status);
31268c2ecf20Sopenharmony_ci
31278c2ecf20Sopenharmony_ciint v4l2_ctrl_subdev_log_status(struct v4l2_subdev *sd)
31288c2ecf20Sopenharmony_ci{
31298c2ecf20Sopenharmony_ci	v4l2_ctrl_handler_log_status(sd->ctrl_handler, sd->name);
31308c2ecf20Sopenharmony_ci	return 0;
31318c2ecf20Sopenharmony_ci}
31328c2ecf20Sopenharmony_ciEXPORT_SYMBOL(v4l2_ctrl_subdev_log_status);
31338c2ecf20Sopenharmony_ci
31348c2ecf20Sopenharmony_ci/* Call s_ctrl for all controls owned by the handler */
31358c2ecf20Sopenharmony_ciint __v4l2_ctrl_handler_setup(struct v4l2_ctrl_handler *hdl)
31368c2ecf20Sopenharmony_ci{
31378c2ecf20Sopenharmony_ci	struct v4l2_ctrl *ctrl;
31388c2ecf20Sopenharmony_ci	int ret = 0;
31398c2ecf20Sopenharmony_ci
31408c2ecf20Sopenharmony_ci	if (hdl == NULL)
31418c2ecf20Sopenharmony_ci		return 0;
31428c2ecf20Sopenharmony_ci
31438c2ecf20Sopenharmony_ci	lockdep_assert_held(hdl->lock);
31448c2ecf20Sopenharmony_ci
31458c2ecf20Sopenharmony_ci	list_for_each_entry(ctrl, &hdl->ctrls, node)
31468c2ecf20Sopenharmony_ci		ctrl->done = false;
31478c2ecf20Sopenharmony_ci
31488c2ecf20Sopenharmony_ci	list_for_each_entry(ctrl, &hdl->ctrls, node) {
31498c2ecf20Sopenharmony_ci		struct v4l2_ctrl *master = ctrl->cluster[0];
31508c2ecf20Sopenharmony_ci		int i;
31518c2ecf20Sopenharmony_ci
31528c2ecf20Sopenharmony_ci		/* Skip if this control was already handled by a cluster. */
31538c2ecf20Sopenharmony_ci		/* Skip button controls and read-only controls. */
31548c2ecf20Sopenharmony_ci		if (ctrl->done || ctrl->type == V4L2_CTRL_TYPE_BUTTON ||
31558c2ecf20Sopenharmony_ci		    (ctrl->flags & V4L2_CTRL_FLAG_READ_ONLY))
31568c2ecf20Sopenharmony_ci			continue;
31578c2ecf20Sopenharmony_ci
31588c2ecf20Sopenharmony_ci		for (i = 0; i < master->ncontrols; i++) {
31598c2ecf20Sopenharmony_ci			if (master->cluster[i]) {
31608c2ecf20Sopenharmony_ci				cur_to_new(master->cluster[i]);
31618c2ecf20Sopenharmony_ci				master->cluster[i]->is_new = 1;
31628c2ecf20Sopenharmony_ci				master->cluster[i]->done = true;
31638c2ecf20Sopenharmony_ci			}
31648c2ecf20Sopenharmony_ci		}
31658c2ecf20Sopenharmony_ci		ret = call_op(master, s_ctrl);
31668c2ecf20Sopenharmony_ci		if (ret)
31678c2ecf20Sopenharmony_ci			break;
31688c2ecf20Sopenharmony_ci	}
31698c2ecf20Sopenharmony_ci
31708c2ecf20Sopenharmony_ci	return ret;
31718c2ecf20Sopenharmony_ci}
31728c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(__v4l2_ctrl_handler_setup);
31738c2ecf20Sopenharmony_ci
31748c2ecf20Sopenharmony_ciint v4l2_ctrl_handler_setup(struct v4l2_ctrl_handler *hdl)
31758c2ecf20Sopenharmony_ci{
31768c2ecf20Sopenharmony_ci	int ret;
31778c2ecf20Sopenharmony_ci
31788c2ecf20Sopenharmony_ci	if (hdl == NULL)
31798c2ecf20Sopenharmony_ci		return 0;
31808c2ecf20Sopenharmony_ci
31818c2ecf20Sopenharmony_ci	mutex_lock(hdl->lock);
31828c2ecf20Sopenharmony_ci	ret = __v4l2_ctrl_handler_setup(hdl);
31838c2ecf20Sopenharmony_ci	mutex_unlock(hdl->lock);
31848c2ecf20Sopenharmony_ci
31858c2ecf20Sopenharmony_ci	return ret;
31868c2ecf20Sopenharmony_ci}
31878c2ecf20Sopenharmony_ciEXPORT_SYMBOL(v4l2_ctrl_handler_setup);
31888c2ecf20Sopenharmony_ci
31898c2ecf20Sopenharmony_ci/* Implement VIDIOC_QUERY_EXT_CTRL */
31908c2ecf20Sopenharmony_ciint v4l2_query_ext_ctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_query_ext_ctrl *qc)
31918c2ecf20Sopenharmony_ci{
31928c2ecf20Sopenharmony_ci	const unsigned next_flags = V4L2_CTRL_FLAG_NEXT_CTRL | V4L2_CTRL_FLAG_NEXT_COMPOUND;
31938c2ecf20Sopenharmony_ci	u32 id = qc->id & V4L2_CTRL_ID_MASK;
31948c2ecf20Sopenharmony_ci	struct v4l2_ctrl_ref *ref;
31958c2ecf20Sopenharmony_ci	struct v4l2_ctrl *ctrl;
31968c2ecf20Sopenharmony_ci
31978c2ecf20Sopenharmony_ci	if (hdl == NULL)
31988c2ecf20Sopenharmony_ci		return -EINVAL;
31998c2ecf20Sopenharmony_ci
32008c2ecf20Sopenharmony_ci	mutex_lock(hdl->lock);
32018c2ecf20Sopenharmony_ci
32028c2ecf20Sopenharmony_ci	/* Try to find it */
32038c2ecf20Sopenharmony_ci	ref = find_ref(hdl, id);
32048c2ecf20Sopenharmony_ci
32058c2ecf20Sopenharmony_ci	if ((qc->id & next_flags) && !list_empty(&hdl->ctrl_refs)) {
32068c2ecf20Sopenharmony_ci		bool is_compound;
32078c2ecf20Sopenharmony_ci		/* Match any control that is not hidden */
32088c2ecf20Sopenharmony_ci		unsigned mask = 1;
32098c2ecf20Sopenharmony_ci		bool match = false;
32108c2ecf20Sopenharmony_ci
32118c2ecf20Sopenharmony_ci		if ((qc->id & next_flags) == V4L2_CTRL_FLAG_NEXT_COMPOUND) {
32128c2ecf20Sopenharmony_ci			/* Match any hidden control */
32138c2ecf20Sopenharmony_ci			match = true;
32148c2ecf20Sopenharmony_ci		} else if ((qc->id & next_flags) == next_flags) {
32158c2ecf20Sopenharmony_ci			/* Match any control, compound or not */
32168c2ecf20Sopenharmony_ci			mask = 0;
32178c2ecf20Sopenharmony_ci		}
32188c2ecf20Sopenharmony_ci
32198c2ecf20Sopenharmony_ci		/* Find the next control with ID > qc->id */
32208c2ecf20Sopenharmony_ci
32218c2ecf20Sopenharmony_ci		/* Did we reach the end of the control list? */
32228c2ecf20Sopenharmony_ci		if (id >= node2id(hdl->ctrl_refs.prev)) {
32238c2ecf20Sopenharmony_ci			ref = NULL; /* Yes, so there is no next control */
32248c2ecf20Sopenharmony_ci		} else if (ref) {
32258c2ecf20Sopenharmony_ci			/* We found a control with the given ID, so just get
32268c2ecf20Sopenharmony_ci			   the next valid one in the list. */
32278c2ecf20Sopenharmony_ci			list_for_each_entry_continue(ref, &hdl->ctrl_refs, node) {
32288c2ecf20Sopenharmony_ci				is_compound = ref->ctrl->is_array ||
32298c2ecf20Sopenharmony_ci					ref->ctrl->type >= V4L2_CTRL_COMPOUND_TYPES;
32308c2ecf20Sopenharmony_ci				if (id < ref->ctrl->id &&
32318c2ecf20Sopenharmony_ci				    (is_compound & mask) == match)
32328c2ecf20Sopenharmony_ci					break;
32338c2ecf20Sopenharmony_ci			}
32348c2ecf20Sopenharmony_ci			if (&ref->node == &hdl->ctrl_refs)
32358c2ecf20Sopenharmony_ci				ref = NULL;
32368c2ecf20Sopenharmony_ci		} else {
32378c2ecf20Sopenharmony_ci			/* No control with the given ID exists, so start
32388c2ecf20Sopenharmony_ci			   searching for the next largest ID. We know there
32398c2ecf20Sopenharmony_ci			   is one, otherwise the first 'if' above would have
32408c2ecf20Sopenharmony_ci			   been true. */
32418c2ecf20Sopenharmony_ci			list_for_each_entry(ref, &hdl->ctrl_refs, node) {
32428c2ecf20Sopenharmony_ci				is_compound = ref->ctrl->is_array ||
32438c2ecf20Sopenharmony_ci					ref->ctrl->type >= V4L2_CTRL_COMPOUND_TYPES;
32448c2ecf20Sopenharmony_ci				if (id < ref->ctrl->id &&
32458c2ecf20Sopenharmony_ci				    (is_compound & mask) == match)
32468c2ecf20Sopenharmony_ci					break;
32478c2ecf20Sopenharmony_ci			}
32488c2ecf20Sopenharmony_ci			if (&ref->node == &hdl->ctrl_refs)
32498c2ecf20Sopenharmony_ci				ref = NULL;
32508c2ecf20Sopenharmony_ci		}
32518c2ecf20Sopenharmony_ci	}
32528c2ecf20Sopenharmony_ci	mutex_unlock(hdl->lock);
32538c2ecf20Sopenharmony_ci
32548c2ecf20Sopenharmony_ci	if (!ref)
32558c2ecf20Sopenharmony_ci		return -EINVAL;
32568c2ecf20Sopenharmony_ci
32578c2ecf20Sopenharmony_ci	ctrl = ref->ctrl;
32588c2ecf20Sopenharmony_ci	memset(qc, 0, sizeof(*qc));
32598c2ecf20Sopenharmony_ci	if (id >= V4L2_CID_PRIVATE_BASE)
32608c2ecf20Sopenharmony_ci		qc->id = id;
32618c2ecf20Sopenharmony_ci	else
32628c2ecf20Sopenharmony_ci		qc->id = ctrl->id;
32638c2ecf20Sopenharmony_ci	strscpy(qc->name, ctrl->name, sizeof(qc->name));
32648c2ecf20Sopenharmony_ci	qc->flags = user_flags(ctrl);
32658c2ecf20Sopenharmony_ci	qc->type = ctrl->type;
32668c2ecf20Sopenharmony_ci	qc->elem_size = ctrl->elem_size;
32678c2ecf20Sopenharmony_ci	qc->elems = ctrl->elems;
32688c2ecf20Sopenharmony_ci	qc->nr_of_dims = ctrl->nr_of_dims;
32698c2ecf20Sopenharmony_ci	memcpy(qc->dims, ctrl->dims, qc->nr_of_dims * sizeof(qc->dims[0]));
32708c2ecf20Sopenharmony_ci	qc->minimum = ctrl->minimum;
32718c2ecf20Sopenharmony_ci	qc->maximum = ctrl->maximum;
32728c2ecf20Sopenharmony_ci	qc->default_value = ctrl->default_value;
32738c2ecf20Sopenharmony_ci	if (ctrl->type == V4L2_CTRL_TYPE_MENU
32748c2ecf20Sopenharmony_ci	    || ctrl->type == V4L2_CTRL_TYPE_INTEGER_MENU)
32758c2ecf20Sopenharmony_ci		qc->step = 1;
32768c2ecf20Sopenharmony_ci	else
32778c2ecf20Sopenharmony_ci		qc->step = ctrl->step;
32788c2ecf20Sopenharmony_ci	return 0;
32798c2ecf20Sopenharmony_ci}
32808c2ecf20Sopenharmony_ciEXPORT_SYMBOL(v4l2_query_ext_ctrl);
32818c2ecf20Sopenharmony_ci
32828c2ecf20Sopenharmony_ci/* Implement VIDIOC_QUERYCTRL */
32838c2ecf20Sopenharmony_ciint v4l2_queryctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_queryctrl *qc)
32848c2ecf20Sopenharmony_ci{
32858c2ecf20Sopenharmony_ci	struct v4l2_query_ext_ctrl qec = { qc->id };
32868c2ecf20Sopenharmony_ci	int rc;
32878c2ecf20Sopenharmony_ci
32888c2ecf20Sopenharmony_ci	rc = v4l2_query_ext_ctrl(hdl, &qec);
32898c2ecf20Sopenharmony_ci	if (rc)
32908c2ecf20Sopenharmony_ci		return rc;
32918c2ecf20Sopenharmony_ci
32928c2ecf20Sopenharmony_ci	qc->id = qec.id;
32938c2ecf20Sopenharmony_ci	qc->type = qec.type;
32948c2ecf20Sopenharmony_ci	qc->flags = qec.flags;
32958c2ecf20Sopenharmony_ci	strscpy(qc->name, qec.name, sizeof(qc->name));
32968c2ecf20Sopenharmony_ci	switch (qc->type) {
32978c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_INTEGER:
32988c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_BOOLEAN:
32998c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_MENU:
33008c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_INTEGER_MENU:
33018c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_STRING:
33028c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_BITMASK:
33038c2ecf20Sopenharmony_ci		qc->minimum = qec.minimum;
33048c2ecf20Sopenharmony_ci		qc->maximum = qec.maximum;
33058c2ecf20Sopenharmony_ci		qc->step = qec.step;
33068c2ecf20Sopenharmony_ci		qc->default_value = qec.default_value;
33078c2ecf20Sopenharmony_ci		break;
33088c2ecf20Sopenharmony_ci	default:
33098c2ecf20Sopenharmony_ci		qc->minimum = 0;
33108c2ecf20Sopenharmony_ci		qc->maximum = 0;
33118c2ecf20Sopenharmony_ci		qc->step = 0;
33128c2ecf20Sopenharmony_ci		qc->default_value = 0;
33138c2ecf20Sopenharmony_ci		break;
33148c2ecf20Sopenharmony_ci	}
33158c2ecf20Sopenharmony_ci	return 0;
33168c2ecf20Sopenharmony_ci}
33178c2ecf20Sopenharmony_ciEXPORT_SYMBOL(v4l2_queryctrl);
33188c2ecf20Sopenharmony_ci
33198c2ecf20Sopenharmony_ci/* Implement VIDIOC_QUERYMENU */
33208c2ecf20Sopenharmony_ciint v4l2_querymenu(struct v4l2_ctrl_handler *hdl, struct v4l2_querymenu *qm)
33218c2ecf20Sopenharmony_ci{
33228c2ecf20Sopenharmony_ci	struct v4l2_ctrl *ctrl;
33238c2ecf20Sopenharmony_ci	u32 i = qm->index;
33248c2ecf20Sopenharmony_ci
33258c2ecf20Sopenharmony_ci	ctrl = v4l2_ctrl_find(hdl, qm->id);
33268c2ecf20Sopenharmony_ci	if (!ctrl)
33278c2ecf20Sopenharmony_ci		return -EINVAL;
33288c2ecf20Sopenharmony_ci
33298c2ecf20Sopenharmony_ci	qm->reserved = 0;
33308c2ecf20Sopenharmony_ci	/* Sanity checks */
33318c2ecf20Sopenharmony_ci	switch (ctrl->type) {
33328c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_MENU:
33338c2ecf20Sopenharmony_ci		if (ctrl->qmenu == NULL)
33348c2ecf20Sopenharmony_ci			return -EINVAL;
33358c2ecf20Sopenharmony_ci		break;
33368c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_INTEGER_MENU:
33378c2ecf20Sopenharmony_ci		if (ctrl->qmenu_int == NULL)
33388c2ecf20Sopenharmony_ci			return -EINVAL;
33398c2ecf20Sopenharmony_ci		break;
33408c2ecf20Sopenharmony_ci	default:
33418c2ecf20Sopenharmony_ci		return -EINVAL;
33428c2ecf20Sopenharmony_ci	}
33438c2ecf20Sopenharmony_ci
33448c2ecf20Sopenharmony_ci	if (i < ctrl->minimum || i > ctrl->maximum)
33458c2ecf20Sopenharmony_ci		return -EINVAL;
33468c2ecf20Sopenharmony_ci
33478c2ecf20Sopenharmony_ci	/* Use mask to see if this menu item should be skipped */
33488c2ecf20Sopenharmony_ci	if (ctrl->menu_skip_mask & (1ULL << i))
33498c2ecf20Sopenharmony_ci		return -EINVAL;
33508c2ecf20Sopenharmony_ci	/* Empty menu items should also be skipped */
33518c2ecf20Sopenharmony_ci	if (ctrl->type == V4L2_CTRL_TYPE_MENU) {
33528c2ecf20Sopenharmony_ci		if (ctrl->qmenu[i] == NULL || ctrl->qmenu[i][0] == '\0')
33538c2ecf20Sopenharmony_ci			return -EINVAL;
33548c2ecf20Sopenharmony_ci		strscpy(qm->name, ctrl->qmenu[i], sizeof(qm->name));
33558c2ecf20Sopenharmony_ci	} else {
33568c2ecf20Sopenharmony_ci		qm->value = ctrl->qmenu_int[i];
33578c2ecf20Sopenharmony_ci	}
33588c2ecf20Sopenharmony_ci	return 0;
33598c2ecf20Sopenharmony_ci}
33608c2ecf20Sopenharmony_ciEXPORT_SYMBOL(v4l2_querymenu);
33618c2ecf20Sopenharmony_ci
33628c2ecf20Sopenharmony_cistatic int v4l2_ctrl_request_clone(struct v4l2_ctrl_handler *hdl,
33638c2ecf20Sopenharmony_ci				   const struct v4l2_ctrl_handler *from)
33648c2ecf20Sopenharmony_ci{
33658c2ecf20Sopenharmony_ci	struct v4l2_ctrl_ref *ref;
33668c2ecf20Sopenharmony_ci	int err = 0;
33678c2ecf20Sopenharmony_ci
33688c2ecf20Sopenharmony_ci	if (WARN_ON(!hdl || hdl == from))
33698c2ecf20Sopenharmony_ci		return -EINVAL;
33708c2ecf20Sopenharmony_ci
33718c2ecf20Sopenharmony_ci	if (hdl->error)
33728c2ecf20Sopenharmony_ci		return hdl->error;
33738c2ecf20Sopenharmony_ci
33748c2ecf20Sopenharmony_ci	WARN_ON(hdl->lock != &hdl->_lock);
33758c2ecf20Sopenharmony_ci
33768c2ecf20Sopenharmony_ci	mutex_lock(from->lock);
33778c2ecf20Sopenharmony_ci	list_for_each_entry(ref, &from->ctrl_refs, node) {
33788c2ecf20Sopenharmony_ci		struct v4l2_ctrl *ctrl = ref->ctrl;
33798c2ecf20Sopenharmony_ci		struct v4l2_ctrl_ref *new_ref;
33808c2ecf20Sopenharmony_ci
33818c2ecf20Sopenharmony_ci		/* Skip refs inherited from other devices */
33828c2ecf20Sopenharmony_ci		if (ref->from_other_dev)
33838c2ecf20Sopenharmony_ci			continue;
33848c2ecf20Sopenharmony_ci		/* And buttons */
33858c2ecf20Sopenharmony_ci		if (ctrl->type == V4L2_CTRL_TYPE_BUTTON)
33868c2ecf20Sopenharmony_ci			continue;
33878c2ecf20Sopenharmony_ci		err = handler_new_ref(hdl, ctrl, &new_ref, false, true);
33888c2ecf20Sopenharmony_ci		if (err)
33898c2ecf20Sopenharmony_ci			break;
33908c2ecf20Sopenharmony_ci	}
33918c2ecf20Sopenharmony_ci	mutex_unlock(from->lock);
33928c2ecf20Sopenharmony_ci	return err;
33938c2ecf20Sopenharmony_ci}
33948c2ecf20Sopenharmony_ci
33958c2ecf20Sopenharmony_cistatic void v4l2_ctrl_request_queue(struct media_request_object *obj)
33968c2ecf20Sopenharmony_ci{
33978c2ecf20Sopenharmony_ci	struct v4l2_ctrl_handler *hdl =
33988c2ecf20Sopenharmony_ci		container_of(obj, struct v4l2_ctrl_handler, req_obj);
33998c2ecf20Sopenharmony_ci	struct v4l2_ctrl_handler *main_hdl = obj->priv;
34008c2ecf20Sopenharmony_ci
34018c2ecf20Sopenharmony_ci	mutex_lock(main_hdl->lock);
34028c2ecf20Sopenharmony_ci	list_add_tail(&hdl->requests_queued, &main_hdl->requests_queued);
34038c2ecf20Sopenharmony_ci	hdl->request_is_queued = true;
34048c2ecf20Sopenharmony_ci	mutex_unlock(main_hdl->lock);
34058c2ecf20Sopenharmony_ci}
34068c2ecf20Sopenharmony_ci
34078c2ecf20Sopenharmony_cistatic void v4l2_ctrl_request_unbind(struct media_request_object *obj)
34088c2ecf20Sopenharmony_ci{
34098c2ecf20Sopenharmony_ci	struct v4l2_ctrl_handler *hdl =
34108c2ecf20Sopenharmony_ci		container_of(obj, struct v4l2_ctrl_handler, req_obj);
34118c2ecf20Sopenharmony_ci	struct v4l2_ctrl_handler *main_hdl = obj->priv;
34128c2ecf20Sopenharmony_ci
34138c2ecf20Sopenharmony_ci	mutex_lock(main_hdl->lock);
34148c2ecf20Sopenharmony_ci	list_del_init(&hdl->requests);
34158c2ecf20Sopenharmony_ci	if (hdl->request_is_queued) {
34168c2ecf20Sopenharmony_ci		list_del_init(&hdl->requests_queued);
34178c2ecf20Sopenharmony_ci		hdl->request_is_queued = false;
34188c2ecf20Sopenharmony_ci	}
34198c2ecf20Sopenharmony_ci	mutex_unlock(main_hdl->lock);
34208c2ecf20Sopenharmony_ci}
34218c2ecf20Sopenharmony_ci
34228c2ecf20Sopenharmony_cistatic void v4l2_ctrl_request_release(struct media_request_object *obj)
34238c2ecf20Sopenharmony_ci{
34248c2ecf20Sopenharmony_ci	struct v4l2_ctrl_handler *hdl =
34258c2ecf20Sopenharmony_ci		container_of(obj, struct v4l2_ctrl_handler, req_obj);
34268c2ecf20Sopenharmony_ci
34278c2ecf20Sopenharmony_ci	v4l2_ctrl_handler_free(hdl);
34288c2ecf20Sopenharmony_ci	kfree(hdl);
34298c2ecf20Sopenharmony_ci}
34308c2ecf20Sopenharmony_ci
34318c2ecf20Sopenharmony_cistatic const struct media_request_object_ops req_ops = {
34328c2ecf20Sopenharmony_ci	.queue = v4l2_ctrl_request_queue,
34338c2ecf20Sopenharmony_ci	.unbind = v4l2_ctrl_request_unbind,
34348c2ecf20Sopenharmony_ci	.release = v4l2_ctrl_request_release,
34358c2ecf20Sopenharmony_ci};
34368c2ecf20Sopenharmony_ci
34378c2ecf20Sopenharmony_cistruct v4l2_ctrl_handler *v4l2_ctrl_request_hdl_find(struct media_request *req,
34388c2ecf20Sopenharmony_ci					struct v4l2_ctrl_handler *parent)
34398c2ecf20Sopenharmony_ci{
34408c2ecf20Sopenharmony_ci	struct media_request_object *obj;
34418c2ecf20Sopenharmony_ci
34428c2ecf20Sopenharmony_ci	if (WARN_ON(req->state != MEDIA_REQUEST_STATE_VALIDATING &&
34438c2ecf20Sopenharmony_ci		    req->state != MEDIA_REQUEST_STATE_QUEUED))
34448c2ecf20Sopenharmony_ci		return NULL;
34458c2ecf20Sopenharmony_ci
34468c2ecf20Sopenharmony_ci	obj = media_request_object_find(req, &req_ops, parent);
34478c2ecf20Sopenharmony_ci	if (obj)
34488c2ecf20Sopenharmony_ci		return container_of(obj, struct v4l2_ctrl_handler, req_obj);
34498c2ecf20Sopenharmony_ci	return NULL;
34508c2ecf20Sopenharmony_ci}
34518c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(v4l2_ctrl_request_hdl_find);
34528c2ecf20Sopenharmony_ci
34538c2ecf20Sopenharmony_cistruct v4l2_ctrl *
34548c2ecf20Sopenharmony_civ4l2_ctrl_request_hdl_ctrl_find(struct v4l2_ctrl_handler *hdl, u32 id)
34558c2ecf20Sopenharmony_ci{
34568c2ecf20Sopenharmony_ci	struct v4l2_ctrl_ref *ref = find_ref_lock(hdl, id);
34578c2ecf20Sopenharmony_ci
34588c2ecf20Sopenharmony_ci	return (ref && ref->valid_p_req) ? ref->ctrl : NULL;
34598c2ecf20Sopenharmony_ci}
34608c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(v4l2_ctrl_request_hdl_ctrl_find);
34618c2ecf20Sopenharmony_ci
34628c2ecf20Sopenharmony_cistatic int v4l2_ctrl_request_bind(struct media_request *req,
34638c2ecf20Sopenharmony_ci			   struct v4l2_ctrl_handler *hdl,
34648c2ecf20Sopenharmony_ci			   struct v4l2_ctrl_handler *from)
34658c2ecf20Sopenharmony_ci{
34668c2ecf20Sopenharmony_ci	int ret;
34678c2ecf20Sopenharmony_ci
34688c2ecf20Sopenharmony_ci	ret = v4l2_ctrl_request_clone(hdl, from);
34698c2ecf20Sopenharmony_ci
34708c2ecf20Sopenharmony_ci	if (!ret) {
34718c2ecf20Sopenharmony_ci		ret = media_request_object_bind(req, &req_ops,
34728c2ecf20Sopenharmony_ci						from, false, &hdl->req_obj);
34738c2ecf20Sopenharmony_ci		if (!ret) {
34748c2ecf20Sopenharmony_ci			mutex_lock(from->lock);
34758c2ecf20Sopenharmony_ci			list_add_tail(&hdl->requests, &from->requests);
34768c2ecf20Sopenharmony_ci			mutex_unlock(from->lock);
34778c2ecf20Sopenharmony_ci		}
34788c2ecf20Sopenharmony_ci	}
34798c2ecf20Sopenharmony_ci	return ret;
34808c2ecf20Sopenharmony_ci}
34818c2ecf20Sopenharmony_ci
34828c2ecf20Sopenharmony_ci/* Some general notes on the atomic requirements of VIDIOC_G/TRY/S_EXT_CTRLS:
34838c2ecf20Sopenharmony_ci
34848c2ecf20Sopenharmony_ci   It is not a fully atomic operation, just best-effort only. After all, if
34858c2ecf20Sopenharmony_ci   multiple controls have to be set through multiple i2c writes (for example)
34868c2ecf20Sopenharmony_ci   then some initial writes may succeed while others fail. Thus leaving the
34878c2ecf20Sopenharmony_ci   system in an inconsistent state. The question is how much effort you are
34888c2ecf20Sopenharmony_ci   willing to spend on trying to make something atomic that really isn't.
34898c2ecf20Sopenharmony_ci
34908c2ecf20Sopenharmony_ci   From the point of view of an application the main requirement is that
34918c2ecf20Sopenharmony_ci   when you call VIDIOC_S_EXT_CTRLS and some values are invalid then an
34928c2ecf20Sopenharmony_ci   error should be returned without actually affecting any controls.
34938c2ecf20Sopenharmony_ci
34948c2ecf20Sopenharmony_ci   If all the values are correct, then it is acceptable to just give up
34958c2ecf20Sopenharmony_ci   in case of low-level errors.
34968c2ecf20Sopenharmony_ci
34978c2ecf20Sopenharmony_ci   It is important though that the application can tell when only a partial
34988c2ecf20Sopenharmony_ci   configuration was done. The way we do that is through the error_idx field
34998c2ecf20Sopenharmony_ci   of struct v4l2_ext_controls: if that is equal to the count field then no
35008c2ecf20Sopenharmony_ci   controls were affected. Otherwise all controls before that index were
35018c2ecf20Sopenharmony_ci   successful in performing their 'get' or 'set' operation, the control at
35028c2ecf20Sopenharmony_ci   the given index failed, and you don't know what happened with the controls
35038c2ecf20Sopenharmony_ci   after the failed one. Since if they were part of a control cluster they
35048c2ecf20Sopenharmony_ci   could have been successfully processed (if a cluster member was encountered
35058c2ecf20Sopenharmony_ci   at index < error_idx), they could have failed (if a cluster member was at
35068c2ecf20Sopenharmony_ci   error_idx), or they may not have been processed yet (if the first cluster
35078c2ecf20Sopenharmony_ci   member appeared after error_idx).
35088c2ecf20Sopenharmony_ci
35098c2ecf20Sopenharmony_ci   It is all fairly theoretical, though. In practice all you can do is to
35108c2ecf20Sopenharmony_ci   bail out. If error_idx == count, then it is an application bug. If
35118c2ecf20Sopenharmony_ci   error_idx < count then it is only an application bug if the error code was
35128c2ecf20Sopenharmony_ci   EBUSY. That usually means that something started streaming just when you
35138c2ecf20Sopenharmony_ci   tried to set the controls. In all other cases it is a driver/hardware
35148c2ecf20Sopenharmony_ci   problem and all you can do is to retry or bail out.
35158c2ecf20Sopenharmony_ci
35168c2ecf20Sopenharmony_ci   Note that these rules do not apply to VIDIOC_TRY_EXT_CTRLS: since that
35178c2ecf20Sopenharmony_ci   never modifies controls the error_idx is just set to whatever control
35188c2ecf20Sopenharmony_ci   has an invalid value.
35198c2ecf20Sopenharmony_ci */
35208c2ecf20Sopenharmony_ci
35218c2ecf20Sopenharmony_ci/* Prepare for the extended g/s/try functions.
35228c2ecf20Sopenharmony_ci   Find the controls in the control array and do some basic checks. */
35238c2ecf20Sopenharmony_cistatic int prepare_ext_ctrls(struct v4l2_ctrl_handler *hdl,
35248c2ecf20Sopenharmony_ci			     struct v4l2_ext_controls *cs,
35258c2ecf20Sopenharmony_ci			     struct v4l2_ctrl_helper *helpers,
35268c2ecf20Sopenharmony_ci			     struct video_device *vdev,
35278c2ecf20Sopenharmony_ci			     bool get)
35288c2ecf20Sopenharmony_ci{
35298c2ecf20Sopenharmony_ci	struct v4l2_ctrl_helper *h;
35308c2ecf20Sopenharmony_ci	bool have_clusters = false;
35318c2ecf20Sopenharmony_ci	u32 i;
35328c2ecf20Sopenharmony_ci
35338c2ecf20Sopenharmony_ci	for (i = 0, h = helpers; i < cs->count; i++, h++) {
35348c2ecf20Sopenharmony_ci		struct v4l2_ext_control *c = &cs->controls[i];
35358c2ecf20Sopenharmony_ci		struct v4l2_ctrl_ref *ref;
35368c2ecf20Sopenharmony_ci		struct v4l2_ctrl *ctrl;
35378c2ecf20Sopenharmony_ci		u32 id = c->id & V4L2_CTRL_ID_MASK;
35388c2ecf20Sopenharmony_ci
35398c2ecf20Sopenharmony_ci		cs->error_idx = i;
35408c2ecf20Sopenharmony_ci
35418c2ecf20Sopenharmony_ci		if (cs->which &&
35428c2ecf20Sopenharmony_ci		    cs->which != V4L2_CTRL_WHICH_DEF_VAL &&
35438c2ecf20Sopenharmony_ci		    cs->which != V4L2_CTRL_WHICH_REQUEST_VAL &&
35448c2ecf20Sopenharmony_ci		    V4L2_CTRL_ID2WHICH(id) != cs->which) {
35458c2ecf20Sopenharmony_ci			dprintk(vdev,
35468c2ecf20Sopenharmony_ci				"invalid which 0x%x or control id 0x%x\n",
35478c2ecf20Sopenharmony_ci				cs->which, id);
35488c2ecf20Sopenharmony_ci			return -EINVAL;
35498c2ecf20Sopenharmony_ci		}
35508c2ecf20Sopenharmony_ci
35518c2ecf20Sopenharmony_ci		/* Old-style private controls are not allowed for
35528c2ecf20Sopenharmony_ci		   extended controls */
35538c2ecf20Sopenharmony_ci		if (id >= V4L2_CID_PRIVATE_BASE) {
35548c2ecf20Sopenharmony_ci			dprintk(vdev,
35558c2ecf20Sopenharmony_ci				"old-style private controls not allowed\n");
35568c2ecf20Sopenharmony_ci			return -EINVAL;
35578c2ecf20Sopenharmony_ci		}
35588c2ecf20Sopenharmony_ci		ref = find_ref_lock(hdl, id);
35598c2ecf20Sopenharmony_ci		if (ref == NULL) {
35608c2ecf20Sopenharmony_ci			dprintk(vdev, "cannot find control id 0x%x\n", id);
35618c2ecf20Sopenharmony_ci			return -EINVAL;
35628c2ecf20Sopenharmony_ci		}
35638c2ecf20Sopenharmony_ci		h->ref = ref;
35648c2ecf20Sopenharmony_ci		ctrl = ref->ctrl;
35658c2ecf20Sopenharmony_ci		if (ctrl->flags & V4L2_CTRL_FLAG_DISABLED) {
35668c2ecf20Sopenharmony_ci			dprintk(vdev, "control id 0x%x is disabled\n", id);
35678c2ecf20Sopenharmony_ci			return -EINVAL;
35688c2ecf20Sopenharmony_ci		}
35698c2ecf20Sopenharmony_ci
35708c2ecf20Sopenharmony_ci		if (ctrl->cluster[0]->ncontrols > 1)
35718c2ecf20Sopenharmony_ci			have_clusters = true;
35728c2ecf20Sopenharmony_ci		if (ctrl->cluster[0] != ctrl)
35738c2ecf20Sopenharmony_ci			ref = find_ref_lock(hdl, ctrl->cluster[0]->id);
35748c2ecf20Sopenharmony_ci		if (ctrl->is_ptr && !ctrl->is_string) {
35758c2ecf20Sopenharmony_ci			unsigned tot_size = ctrl->elems * ctrl->elem_size;
35768c2ecf20Sopenharmony_ci
35778c2ecf20Sopenharmony_ci			if (c->size < tot_size) {
35788c2ecf20Sopenharmony_ci				/*
35798c2ecf20Sopenharmony_ci				 * In the get case the application first
35808c2ecf20Sopenharmony_ci				 * queries to obtain the size of the control.
35818c2ecf20Sopenharmony_ci				 */
35828c2ecf20Sopenharmony_ci				if (get) {
35838c2ecf20Sopenharmony_ci					c->size = tot_size;
35848c2ecf20Sopenharmony_ci					return -ENOSPC;
35858c2ecf20Sopenharmony_ci				}
35868c2ecf20Sopenharmony_ci				dprintk(vdev,
35878c2ecf20Sopenharmony_ci					"pointer control id 0x%x size too small, %d bytes but %d bytes needed\n",
35888c2ecf20Sopenharmony_ci					id, c->size, tot_size);
35898c2ecf20Sopenharmony_ci				return -EFAULT;
35908c2ecf20Sopenharmony_ci			}
35918c2ecf20Sopenharmony_ci			c->size = tot_size;
35928c2ecf20Sopenharmony_ci		}
35938c2ecf20Sopenharmony_ci		/* Store the ref to the master control of the cluster */
35948c2ecf20Sopenharmony_ci		h->mref = ref;
35958c2ecf20Sopenharmony_ci		/* Initially set next to 0, meaning that there is no other
35968c2ecf20Sopenharmony_ci		   control in this helper array belonging to the same
35978c2ecf20Sopenharmony_ci		   cluster */
35988c2ecf20Sopenharmony_ci		h->next = 0;
35998c2ecf20Sopenharmony_ci	}
36008c2ecf20Sopenharmony_ci
36018c2ecf20Sopenharmony_ci	/* We are done if there were no controls that belong to a multi-
36028c2ecf20Sopenharmony_ci	   control cluster. */
36038c2ecf20Sopenharmony_ci	if (!have_clusters)
36048c2ecf20Sopenharmony_ci		return 0;
36058c2ecf20Sopenharmony_ci
36068c2ecf20Sopenharmony_ci	/* The code below figures out in O(n) time which controls in the list
36078c2ecf20Sopenharmony_ci	   belong to the same cluster. */
36088c2ecf20Sopenharmony_ci
36098c2ecf20Sopenharmony_ci	/* This has to be done with the handler lock taken. */
36108c2ecf20Sopenharmony_ci	mutex_lock(hdl->lock);
36118c2ecf20Sopenharmony_ci
36128c2ecf20Sopenharmony_ci	/* First zero the helper field in the master control references */
36138c2ecf20Sopenharmony_ci	for (i = 0; i < cs->count; i++)
36148c2ecf20Sopenharmony_ci		helpers[i].mref->helper = NULL;
36158c2ecf20Sopenharmony_ci	for (i = 0, h = helpers; i < cs->count; i++, h++) {
36168c2ecf20Sopenharmony_ci		struct v4l2_ctrl_ref *mref = h->mref;
36178c2ecf20Sopenharmony_ci
36188c2ecf20Sopenharmony_ci		/* If the mref->helper is set, then it points to an earlier
36198c2ecf20Sopenharmony_ci		   helper that belongs to the same cluster. */
36208c2ecf20Sopenharmony_ci		if (mref->helper) {
36218c2ecf20Sopenharmony_ci			/* Set the next field of mref->helper to the current
36228c2ecf20Sopenharmony_ci			   index: this means that that earlier helper now
36238c2ecf20Sopenharmony_ci			   points to the next helper in the same cluster. */
36248c2ecf20Sopenharmony_ci			mref->helper->next = i;
36258c2ecf20Sopenharmony_ci			/* mref should be set only for the first helper in the
36268c2ecf20Sopenharmony_ci			   cluster, clear the others. */
36278c2ecf20Sopenharmony_ci			h->mref = NULL;
36288c2ecf20Sopenharmony_ci		}
36298c2ecf20Sopenharmony_ci		/* Point the mref helper to the current helper struct. */
36308c2ecf20Sopenharmony_ci		mref->helper = h;
36318c2ecf20Sopenharmony_ci	}
36328c2ecf20Sopenharmony_ci	mutex_unlock(hdl->lock);
36338c2ecf20Sopenharmony_ci	return 0;
36348c2ecf20Sopenharmony_ci}
36358c2ecf20Sopenharmony_ci
36368c2ecf20Sopenharmony_ci/* Handles the corner case where cs->count == 0. It checks whether the
36378c2ecf20Sopenharmony_ci   specified control class exists. If that class ID is 0, then it checks
36388c2ecf20Sopenharmony_ci   whether there are any controls at all. */
36398c2ecf20Sopenharmony_cistatic int class_check(struct v4l2_ctrl_handler *hdl, u32 which)
36408c2ecf20Sopenharmony_ci{
36418c2ecf20Sopenharmony_ci	if (which == 0 || which == V4L2_CTRL_WHICH_DEF_VAL ||
36428c2ecf20Sopenharmony_ci	    which == V4L2_CTRL_WHICH_REQUEST_VAL)
36438c2ecf20Sopenharmony_ci		return 0;
36448c2ecf20Sopenharmony_ci	return find_ref_lock(hdl, which | 1) ? 0 : -EINVAL;
36458c2ecf20Sopenharmony_ci}
36468c2ecf20Sopenharmony_ci
36478c2ecf20Sopenharmony_ci/*
36488c2ecf20Sopenharmony_ci * Get extended controls. Allocates the helpers array if needed.
36498c2ecf20Sopenharmony_ci *
36508c2ecf20Sopenharmony_ci * Note that v4l2_g_ext_ctrls_common() with 'which' set to
36518c2ecf20Sopenharmony_ci * V4L2_CTRL_WHICH_REQUEST_VAL is only called if the request was
36528c2ecf20Sopenharmony_ci * completed, and in that case valid_p_req is true for all controls.
36538c2ecf20Sopenharmony_ci */
36548c2ecf20Sopenharmony_cistatic int v4l2_g_ext_ctrls_common(struct v4l2_ctrl_handler *hdl,
36558c2ecf20Sopenharmony_ci				   struct v4l2_ext_controls *cs,
36568c2ecf20Sopenharmony_ci				   struct video_device *vdev)
36578c2ecf20Sopenharmony_ci{
36588c2ecf20Sopenharmony_ci	struct v4l2_ctrl_helper helper[4];
36598c2ecf20Sopenharmony_ci	struct v4l2_ctrl_helper *helpers = helper;
36608c2ecf20Sopenharmony_ci	int ret;
36618c2ecf20Sopenharmony_ci	int i, j;
36628c2ecf20Sopenharmony_ci	bool is_default, is_request;
36638c2ecf20Sopenharmony_ci
36648c2ecf20Sopenharmony_ci	is_default = (cs->which == V4L2_CTRL_WHICH_DEF_VAL);
36658c2ecf20Sopenharmony_ci	is_request = (cs->which == V4L2_CTRL_WHICH_REQUEST_VAL);
36668c2ecf20Sopenharmony_ci
36678c2ecf20Sopenharmony_ci	cs->error_idx = cs->count;
36688c2ecf20Sopenharmony_ci	cs->which = V4L2_CTRL_ID2WHICH(cs->which);
36698c2ecf20Sopenharmony_ci
36708c2ecf20Sopenharmony_ci	if (hdl == NULL)
36718c2ecf20Sopenharmony_ci		return -EINVAL;
36728c2ecf20Sopenharmony_ci
36738c2ecf20Sopenharmony_ci	if (cs->count == 0)
36748c2ecf20Sopenharmony_ci		return class_check(hdl, cs->which);
36758c2ecf20Sopenharmony_ci
36768c2ecf20Sopenharmony_ci	if (cs->count > ARRAY_SIZE(helper)) {
36778c2ecf20Sopenharmony_ci		helpers = kvmalloc_array(cs->count, sizeof(helper[0]),
36788c2ecf20Sopenharmony_ci					 GFP_KERNEL);
36798c2ecf20Sopenharmony_ci		if (helpers == NULL)
36808c2ecf20Sopenharmony_ci			return -ENOMEM;
36818c2ecf20Sopenharmony_ci	}
36828c2ecf20Sopenharmony_ci
36838c2ecf20Sopenharmony_ci	ret = prepare_ext_ctrls(hdl, cs, helpers, vdev, true);
36848c2ecf20Sopenharmony_ci	cs->error_idx = cs->count;
36858c2ecf20Sopenharmony_ci
36868c2ecf20Sopenharmony_ci	for (i = 0; !ret && i < cs->count; i++)
36878c2ecf20Sopenharmony_ci		if (helpers[i].ref->ctrl->flags & V4L2_CTRL_FLAG_WRITE_ONLY)
36888c2ecf20Sopenharmony_ci			ret = -EACCES;
36898c2ecf20Sopenharmony_ci
36908c2ecf20Sopenharmony_ci	for (i = 0; !ret && i < cs->count; i++) {
36918c2ecf20Sopenharmony_ci		struct v4l2_ctrl *master;
36928c2ecf20Sopenharmony_ci		bool is_volatile = false;
36938c2ecf20Sopenharmony_ci		u32 idx = i;
36948c2ecf20Sopenharmony_ci
36958c2ecf20Sopenharmony_ci		if (helpers[i].mref == NULL)
36968c2ecf20Sopenharmony_ci			continue;
36978c2ecf20Sopenharmony_ci
36988c2ecf20Sopenharmony_ci		master = helpers[i].mref->ctrl;
36998c2ecf20Sopenharmony_ci		cs->error_idx = i;
37008c2ecf20Sopenharmony_ci
37018c2ecf20Sopenharmony_ci		v4l2_ctrl_lock(master);
37028c2ecf20Sopenharmony_ci
37038c2ecf20Sopenharmony_ci		/*
37048c2ecf20Sopenharmony_ci		 * g_volatile_ctrl will update the new control values.
37058c2ecf20Sopenharmony_ci		 * This makes no sense for V4L2_CTRL_WHICH_DEF_VAL and
37068c2ecf20Sopenharmony_ci		 * V4L2_CTRL_WHICH_REQUEST_VAL. In the case of requests
37078c2ecf20Sopenharmony_ci		 * it is v4l2_ctrl_request_complete() that copies the
37088c2ecf20Sopenharmony_ci		 * volatile controls at the time of request completion
37098c2ecf20Sopenharmony_ci		 * to the request, so you don't want to do that again.
37108c2ecf20Sopenharmony_ci		 */
37118c2ecf20Sopenharmony_ci		if (!is_default && !is_request &&
37128c2ecf20Sopenharmony_ci		    ((master->flags & V4L2_CTRL_FLAG_VOLATILE) ||
37138c2ecf20Sopenharmony_ci		    (master->has_volatiles && !is_cur_manual(master)))) {
37148c2ecf20Sopenharmony_ci			for (j = 0; j < master->ncontrols; j++)
37158c2ecf20Sopenharmony_ci				cur_to_new(master->cluster[j]);
37168c2ecf20Sopenharmony_ci			ret = call_op(master, g_volatile_ctrl);
37178c2ecf20Sopenharmony_ci			is_volatile = true;
37188c2ecf20Sopenharmony_ci		}
37198c2ecf20Sopenharmony_ci
37208c2ecf20Sopenharmony_ci		if (ret) {
37218c2ecf20Sopenharmony_ci			v4l2_ctrl_unlock(master);
37228c2ecf20Sopenharmony_ci			break;
37238c2ecf20Sopenharmony_ci		}
37248c2ecf20Sopenharmony_ci
37258c2ecf20Sopenharmony_ci		/*
37268c2ecf20Sopenharmony_ci		 * Copy the default value (if is_default is true), the
37278c2ecf20Sopenharmony_ci		 * request value (if is_request is true and p_req is valid),
37288c2ecf20Sopenharmony_ci		 * the new volatile value (if is_volatile is true) or the
37298c2ecf20Sopenharmony_ci		 * current value.
37308c2ecf20Sopenharmony_ci		 */
37318c2ecf20Sopenharmony_ci		do {
37328c2ecf20Sopenharmony_ci			struct v4l2_ctrl_ref *ref = helpers[idx].ref;
37338c2ecf20Sopenharmony_ci
37348c2ecf20Sopenharmony_ci			if (is_default)
37358c2ecf20Sopenharmony_ci				ret = def_to_user(cs->controls + idx, ref->ctrl);
37368c2ecf20Sopenharmony_ci			else if (is_request && ref->valid_p_req)
37378c2ecf20Sopenharmony_ci				ret = req_to_user(cs->controls + idx, ref);
37388c2ecf20Sopenharmony_ci			else if (is_volatile)
37398c2ecf20Sopenharmony_ci				ret = new_to_user(cs->controls + idx, ref->ctrl);
37408c2ecf20Sopenharmony_ci			else
37418c2ecf20Sopenharmony_ci				ret = cur_to_user(cs->controls + idx, ref->ctrl);
37428c2ecf20Sopenharmony_ci			idx = helpers[idx].next;
37438c2ecf20Sopenharmony_ci		} while (!ret && idx);
37448c2ecf20Sopenharmony_ci
37458c2ecf20Sopenharmony_ci		v4l2_ctrl_unlock(master);
37468c2ecf20Sopenharmony_ci	}
37478c2ecf20Sopenharmony_ci
37488c2ecf20Sopenharmony_ci	if (cs->count > ARRAY_SIZE(helper))
37498c2ecf20Sopenharmony_ci		kvfree(helpers);
37508c2ecf20Sopenharmony_ci	return ret;
37518c2ecf20Sopenharmony_ci}
37528c2ecf20Sopenharmony_ci
37538c2ecf20Sopenharmony_cistatic struct media_request_object *
37548c2ecf20Sopenharmony_civ4l2_ctrls_find_req_obj(struct v4l2_ctrl_handler *hdl,
37558c2ecf20Sopenharmony_ci			struct media_request *req, bool set)
37568c2ecf20Sopenharmony_ci{
37578c2ecf20Sopenharmony_ci	struct media_request_object *obj;
37588c2ecf20Sopenharmony_ci	struct v4l2_ctrl_handler *new_hdl;
37598c2ecf20Sopenharmony_ci	int ret;
37608c2ecf20Sopenharmony_ci
37618c2ecf20Sopenharmony_ci	if (IS_ERR(req))
37628c2ecf20Sopenharmony_ci		return ERR_CAST(req);
37638c2ecf20Sopenharmony_ci
37648c2ecf20Sopenharmony_ci	if (set && WARN_ON(req->state != MEDIA_REQUEST_STATE_UPDATING))
37658c2ecf20Sopenharmony_ci		return ERR_PTR(-EBUSY);
37668c2ecf20Sopenharmony_ci
37678c2ecf20Sopenharmony_ci	obj = media_request_object_find(req, &req_ops, hdl);
37688c2ecf20Sopenharmony_ci	if (obj)
37698c2ecf20Sopenharmony_ci		return obj;
37708c2ecf20Sopenharmony_ci	if (!set)
37718c2ecf20Sopenharmony_ci		return ERR_PTR(-ENOENT);
37728c2ecf20Sopenharmony_ci
37738c2ecf20Sopenharmony_ci	new_hdl = kzalloc(sizeof(*new_hdl), GFP_KERNEL);
37748c2ecf20Sopenharmony_ci	if (!new_hdl)
37758c2ecf20Sopenharmony_ci		return ERR_PTR(-ENOMEM);
37768c2ecf20Sopenharmony_ci
37778c2ecf20Sopenharmony_ci	obj = &new_hdl->req_obj;
37788c2ecf20Sopenharmony_ci	ret = v4l2_ctrl_handler_init(new_hdl, (hdl->nr_of_buckets - 1) * 8);
37798c2ecf20Sopenharmony_ci	if (!ret)
37808c2ecf20Sopenharmony_ci		ret = v4l2_ctrl_request_bind(req, new_hdl, hdl);
37818c2ecf20Sopenharmony_ci	if (ret) {
37828c2ecf20Sopenharmony_ci		kfree(new_hdl);
37838c2ecf20Sopenharmony_ci
37848c2ecf20Sopenharmony_ci		return ERR_PTR(ret);
37858c2ecf20Sopenharmony_ci	}
37868c2ecf20Sopenharmony_ci
37878c2ecf20Sopenharmony_ci	media_request_object_get(obj);
37888c2ecf20Sopenharmony_ci	return obj;
37898c2ecf20Sopenharmony_ci}
37908c2ecf20Sopenharmony_ci
37918c2ecf20Sopenharmony_ciint v4l2_g_ext_ctrls(struct v4l2_ctrl_handler *hdl, struct video_device *vdev,
37928c2ecf20Sopenharmony_ci		     struct media_device *mdev, struct v4l2_ext_controls *cs)
37938c2ecf20Sopenharmony_ci{
37948c2ecf20Sopenharmony_ci	struct media_request_object *obj = NULL;
37958c2ecf20Sopenharmony_ci	struct media_request *req = NULL;
37968c2ecf20Sopenharmony_ci	int ret;
37978c2ecf20Sopenharmony_ci
37988c2ecf20Sopenharmony_ci	if (cs->which == V4L2_CTRL_WHICH_REQUEST_VAL) {
37998c2ecf20Sopenharmony_ci		if (!mdev || cs->request_fd < 0)
38008c2ecf20Sopenharmony_ci			return -EINVAL;
38018c2ecf20Sopenharmony_ci
38028c2ecf20Sopenharmony_ci		req = media_request_get_by_fd(mdev, cs->request_fd);
38038c2ecf20Sopenharmony_ci		if (IS_ERR(req))
38048c2ecf20Sopenharmony_ci			return PTR_ERR(req);
38058c2ecf20Sopenharmony_ci
38068c2ecf20Sopenharmony_ci		if (req->state != MEDIA_REQUEST_STATE_COMPLETE) {
38078c2ecf20Sopenharmony_ci			media_request_put(req);
38088c2ecf20Sopenharmony_ci			return -EACCES;
38098c2ecf20Sopenharmony_ci		}
38108c2ecf20Sopenharmony_ci
38118c2ecf20Sopenharmony_ci		ret = media_request_lock_for_access(req);
38128c2ecf20Sopenharmony_ci		if (ret) {
38138c2ecf20Sopenharmony_ci			media_request_put(req);
38148c2ecf20Sopenharmony_ci			return ret;
38158c2ecf20Sopenharmony_ci		}
38168c2ecf20Sopenharmony_ci
38178c2ecf20Sopenharmony_ci		obj = v4l2_ctrls_find_req_obj(hdl, req, false);
38188c2ecf20Sopenharmony_ci		if (IS_ERR(obj)) {
38198c2ecf20Sopenharmony_ci			media_request_unlock_for_access(req);
38208c2ecf20Sopenharmony_ci			media_request_put(req);
38218c2ecf20Sopenharmony_ci			return PTR_ERR(obj);
38228c2ecf20Sopenharmony_ci		}
38238c2ecf20Sopenharmony_ci
38248c2ecf20Sopenharmony_ci		hdl = container_of(obj, struct v4l2_ctrl_handler,
38258c2ecf20Sopenharmony_ci				   req_obj);
38268c2ecf20Sopenharmony_ci	}
38278c2ecf20Sopenharmony_ci
38288c2ecf20Sopenharmony_ci	ret = v4l2_g_ext_ctrls_common(hdl, cs, vdev);
38298c2ecf20Sopenharmony_ci
38308c2ecf20Sopenharmony_ci	if (obj) {
38318c2ecf20Sopenharmony_ci		media_request_unlock_for_access(req);
38328c2ecf20Sopenharmony_ci		media_request_object_put(obj);
38338c2ecf20Sopenharmony_ci		media_request_put(req);
38348c2ecf20Sopenharmony_ci	}
38358c2ecf20Sopenharmony_ci	return ret;
38368c2ecf20Sopenharmony_ci}
38378c2ecf20Sopenharmony_ciEXPORT_SYMBOL(v4l2_g_ext_ctrls);
38388c2ecf20Sopenharmony_ci
38398c2ecf20Sopenharmony_ci/* Helper function to get a single control */
38408c2ecf20Sopenharmony_cistatic int get_ctrl(struct v4l2_ctrl *ctrl, struct v4l2_ext_control *c)
38418c2ecf20Sopenharmony_ci{
38428c2ecf20Sopenharmony_ci	struct v4l2_ctrl *master = ctrl->cluster[0];
38438c2ecf20Sopenharmony_ci	int ret = 0;
38448c2ecf20Sopenharmony_ci	int i;
38458c2ecf20Sopenharmony_ci
38468c2ecf20Sopenharmony_ci	/* Compound controls are not supported. The new_to_user() and
38478c2ecf20Sopenharmony_ci	 * cur_to_user() calls below would need to be modified not to access
38488c2ecf20Sopenharmony_ci	 * userspace memory when called from get_ctrl().
38498c2ecf20Sopenharmony_ci	 */
38508c2ecf20Sopenharmony_ci	if (!ctrl->is_int && ctrl->type != V4L2_CTRL_TYPE_INTEGER64)
38518c2ecf20Sopenharmony_ci		return -EINVAL;
38528c2ecf20Sopenharmony_ci
38538c2ecf20Sopenharmony_ci	if (ctrl->flags & V4L2_CTRL_FLAG_WRITE_ONLY)
38548c2ecf20Sopenharmony_ci		return -EACCES;
38558c2ecf20Sopenharmony_ci
38568c2ecf20Sopenharmony_ci	v4l2_ctrl_lock(master);
38578c2ecf20Sopenharmony_ci	/* g_volatile_ctrl will update the current control values */
38588c2ecf20Sopenharmony_ci	if (ctrl->flags & V4L2_CTRL_FLAG_VOLATILE) {
38598c2ecf20Sopenharmony_ci		for (i = 0; i < master->ncontrols; i++)
38608c2ecf20Sopenharmony_ci			cur_to_new(master->cluster[i]);
38618c2ecf20Sopenharmony_ci		ret = call_op(master, g_volatile_ctrl);
38628c2ecf20Sopenharmony_ci		new_to_user(c, ctrl);
38638c2ecf20Sopenharmony_ci	} else {
38648c2ecf20Sopenharmony_ci		cur_to_user(c, ctrl);
38658c2ecf20Sopenharmony_ci	}
38668c2ecf20Sopenharmony_ci	v4l2_ctrl_unlock(master);
38678c2ecf20Sopenharmony_ci	return ret;
38688c2ecf20Sopenharmony_ci}
38698c2ecf20Sopenharmony_ci
38708c2ecf20Sopenharmony_ciint v4l2_g_ctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_control *control)
38718c2ecf20Sopenharmony_ci{
38728c2ecf20Sopenharmony_ci	struct v4l2_ctrl *ctrl = v4l2_ctrl_find(hdl, control->id);
38738c2ecf20Sopenharmony_ci	struct v4l2_ext_control c;
38748c2ecf20Sopenharmony_ci	int ret;
38758c2ecf20Sopenharmony_ci
38768c2ecf20Sopenharmony_ci	if (ctrl == NULL || !ctrl->is_int)
38778c2ecf20Sopenharmony_ci		return -EINVAL;
38788c2ecf20Sopenharmony_ci	ret = get_ctrl(ctrl, &c);
38798c2ecf20Sopenharmony_ci	control->value = c.value;
38808c2ecf20Sopenharmony_ci	return ret;
38818c2ecf20Sopenharmony_ci}
38828c2ecf20Sopenharmony_ciEXPORT_SYMBOL(v4l2_g_ctrl);
38838c2ecf20Sopenharmony_ci
38848c2ecf20Sopenharmony_cis32 v4l2_ctrl_g_ctrl(struct v4l2_ctrl *ctrl)
38858c2ecf20Sopenharmony_ci{
38868c2ecf20Sopenharmony_ci	struct v4l2_ext_control c;
38878c2ecf20Sopenharmony_ci
38888c2ecf20Sopenharmony_ci	/* It's a driver bug if this happens. */
38898c2ecf20Sopenharmony_ci	if (WARN_ON(!ctrl->is_int))
38908c2ecf20Sopenharmony_ci		return 0;
38918c2ecf20Sopenharmony_ci	c.value = 0;
38928c2ecf20Sopenharmony_ci	get_ctrl(ctrl, &c);
38938c2ecf20Sopenharmony_ci	return c.value;
38948c2ecf20Sopenharmony_ci}
38958c2ecf20Sopenharmony_ciEXPORT_SYMBOL(v4l2_ctrl_g_ctrl);
38968c2ecf20Sopenharmony_ci
38978c2ecf20Sopenharmony_cis64 v4l2_ctrl_g_ctrl_int64(struct v4l2_ctrl *ctrl)
38988c2ecf20Sopenharmony_ci{
38998c2ecf20Sopenharmony_ci	struct v4l2_ext_control c;
39008c2ecf20Sopenharmony_ci
39018c2ecf20Sopenharmony_ci	/* It's a driver bug if this happens. */
39028c2ecf20Sopenharmony_ci	if (WARN_ON(ctrl->is_ptr || ctrl->type != V4L2_CTRL_TYPE_INTEGER64))
39038c2ecf20Sopenharmony_ci		return 0;
39048c2ecf20Sopenharmony_ci	c.value64 = 0;
39058c2ecf20Sopenharmony_ci	get_ctrl(ctrl, &c);
39068c2ecf20Sopenharmony_ci	return c.value64;
39078c2ecf20Sopenharmony_ci}
39088c2ecf20Sopenharmony_ciEXPORT_SYMBOL(v4l2_ctrl_g_ctrl_int64);
39098c2ecf20Sopenharmony_ci
39108c2ecf20Sopenharmony_ci
39118c2ecf20Sopenharmony_ci/* Core function that calls try/s_ctrl and ensures that the new value is
39128c2ecf20Sopenharmony_ci   copied to the current value on a set.
39138c2ecf20Sopenharmony_ci   Must be called with ctrl->handler->lock held. */
39148c2ecf20Sopenharmony_cistatic int try_or_set_cluster(struct v4l2_fh *fh, struct v4l2_ctrl *master,
39158c2ecf20Sopenharmony_ci			      bool set, u32 ch_flags)
39168c2ecf20Sopenharmony_ci{
39178c2ecf20Sopenharmony_ci	bool update_flag;
39188c2ecf20Sopenharmony_ci	int ret;
39198c2ecf20Sopenharmony_ci	int i;
39208c2ecf20Sopenharmony_ci
39218c2ecf20Sopenharmony_ci	/* Go through the cluster and either validate the new value or
39228c2ecf20Sopenharmony_ci	   (if no new value was set), copy the current value to the new
39238c2ecf20Sopenharmony_ci	   value, ensuring a consistent view for the control ops when
39248c2ecf20Sopenharmony_ci	   called. */
39258c2ecf20Sopenharmony_ci	for (i = 0; i < master->ncontrols; i++) {
39268c2ecf20Sopenharmony_ci		struct v4l2_ctrl *ctrl = master->cluster[i];
39278c2ecf20Sopenharmony_ci
39288c2ecf20Sopenharmony_ci		if (ctrl == NULL)
39298c2ecf20Sopenharmony_ci			continue;
39308c2ecf20Sopenharmony_ci
39318c2ecf20Sopenharmony_ci		if (!ctrl->is_new) {
39328c2ecf20Sopenharmony_ci			cur_to_new(ctrl);
39338c2ecf20Sopenharmony_ci			continue;
39348c2ecf20Sopenharmony_ci		}
39358c2ecf20Sopenharmony_ci		/* Check again: it may have changed since the
39368c2ecf20Sopenharmony_ci		   previous check in try_or_set_ext_ctrls(). */
39378c2ecf20Sopenharmony_ci		if (set && (ctrl->flags & V4L2_CTRL_FLAG_GRABBED))
39388c2ecf20Sopenharmony_ci			return -EBUSY;
39398c2ecf20Sopenharmony_ci	}
39408c2ecf20Sopenharmony_ci
39418c2ecf20Sopenharmony_ci	ret = call_op(master, try_ctrl);
39428c2ecf20Sopenharmony_ci
39438c2ecf20Sopenharmony_ci	/* Don't set if there is no change */
39448c2ecf20Sopenharmony_ci	if (ret || !set || !cluster_changed(master))
39458c2ecf20Sopenharmony_ci		return ret;
39468c2ecf20Sopenharmony_ci	ret = call_op(master, s_ctrl);
39478c2ecf20Sopenharmony_ci	if (ret)
39488c2ecf20Sopenharmony_ci		return ret;
39498c2ecf20Sopenharmony_ci
39508c2ecf20Sopenharmony_ci	/* If OK, then make the new values permanent. */
39518c2ecf20Sopenharmony_ci	update_flag = is_cur_manual(master) != is_new_manual(master);
39528c2ecf20Sopenharmony_ci
39538c2ecf20Sopenharmony_ci	for (i = 0; i < master->ncontrols; i++) {
39548c2ecf20Sopenharmony_ci		/*
39558c2ecf20Sopenharmony_ci		 * If we switch from auto to manual mode, and this cluster
39568c2ecf20Sopenharmony_ci		 * contains volatile controls, then all non-master controls
39578c2ecf20Sopenharmony_ci		 * have to be marked as changed. The 'new' value contains
39588c2ecf20Sopenharmony_ci		 * the volatile value (obtained by update_from_auto_cluster),
39598c2ecf20Sopenharmony_ci		 * which now has to become the current value.
39608c2ecf20Sopenharmony_ci		 */
39618c2ecf20Sopenharmony_ci		if (i && update_flag && is_new_manual(master) &&
39628c2ecf20Sopenharmony_ci		    master->has_volatiles && master->cluster[i])
39638c2ecf20Sopenharmony_ci			master->cluster[i]->has_changed = true;
39648c2ecf20Sopenharmony_ci
39658c2ecf20Sopenharmony_ci		new_to_cur(fh, master->cluster[i], ch_flags |
39668c2ecf20Sopenharmony_ci			((update_flag && i > 0) ? V4L2_EVENT_CTRL_CH_FLAGS : 0));
39678c2ecf20Sopenharmony_ci	}
39688c2ecf20Sopenharmony_ci	return 0;
39698c2ecf20Sopenharmony_ci}
39708c2ecf20Sopenharmony_ci
39718c2ecf20Sopenharmony_ci/* Validate controls. */
39728c2ecf20Sopenharmony_cistatic int validate_ctrls(struct v4l2_ext_controls *cs,
39738c2ecf20Sopenharmony_ci			  struct v4l2_ctrl_helper *helpers,
39748c2ecf20Sopenharmony_ci			  struct video_device *vdev,
39758c2ecf20Sopenharmony_ci			  bool set)
39768c2ecf20Sopenharmony_ci{
39778c2ecf20Sopenharmony_ci	unsigned i;
39788c2ecf20Sopenharmony_ci	int ret = 0;
39798c2ecf20Sopenharmony_ci
39808c2ecf20Sopenharmony_ci	cs->error_idx = cs->count;
39818c2ecf20Sopenharmony_ci	for (i = 0; i < cs->count; i++) {
39828c2ecf20Sopenharmony_ci		struct v4l2_ctrl *ctrl = helpers[i].ref->ctrl;
39838c2ecf20Sopenharmony_ci		union v4l2_ctrl_ptr p_new;
39848c2ecf20Sopenharmony_ci
39858c2ecf20Sopenharmony_ci		cs->error_idx = i;
39868c2ecf20Sopenharmony_ci
39878c2ecf20Sopenharmony_ci		if (ctrl->flags & V4L2_CTRL_FLAG_READ_ONLY) {
39888c2ecf20Sopenharmony_ci			dprintk(vdev,
39898c2ecf20Sopenharmony_ci				"control id 0x%x is read-only\n",
39908c2ecf20Sopenharmony_ci				ctrl->id);
39918c2ecf20Sopenharmony_ci			return -EACCES;
39928c2ecf20Sopenharmony_ci		}
39938c2ecf20Sopenharmony_ci		/* This test is also done in try_set_control_cluster() which
39948c2ecf20Sopenharmony_ci		   is called in atomic context, so that has the final say,
39958c2ecf20Sopenharmony_ci		   but it makes sense to do an up-front check as well. Once
39968c2ecf20Sopenharmony_ci		   an error occurs in try_set_control_cluster() some other
39978c2ecf20Sopenharmony_ci		   controls may have been set already and we want to do a
39988c2ecf20Sopenharmony_ci		   best-effort to avoid that. */
39998c2ecf20Sopenharmony_ci		if (set && (ctrl->flags & V4L2_CTRL_FLAG_GRABBED)) {
40008c2ecf20Sopenharmony_ci			dprintk(vdev,
40018c2ecf20Sopenharmony_ci				"control id 0x%x is grabbed, cannot set\n",
40028c2ecf20Sopenharmony_ci				ctrl->id);
40038c2ecf20Sopenharmony_ci			return -EBUSY;
40048c2ecf20Sopenharmony_ci		}
40058c2ecf20Sopenharmony_ci		/*
40068c2ecf20Sopenharmony_ci		 * Skip validation for now if the payload needs to be copied
40078c2ecf20Sopenharmony_ci		 * from userspace into kernelspace. We'll validate those later.
40088c2ecf20Sopenharmony_ci		 */
40098c2ecf20Sopenharmony_ci		if (ctrl->is_ptr)
40108c2ecf20Sopenharmony_ci			continue;
40118c2ecf20Sopenharmony_ci		if (ctrl->type == V4L2_CTRL_TYPE_INTEGER64)
40128c2ecf20Sopenharmony_ci			p_new.p_s64 = &cs->controls[i].value64;
40138c2ecf20Sopenharmony_ci		else
40148c2ecf20Sopenharmony_ci			p_new.p_s32 = &cs->controls[i].value;
40158c2ecf20Sopenharmony_ci		ret = validate_new(ctrl, p_new);
40168c2ecf20Sopenharmony_ci		if (ret)
40178c2ecf20Sopenharmony_ci			return ret;
40188c2ecf20Sopenharmony_ci	}
40198c2ecf20Sopenharmony_ci	return 0;
40208c2ecf20Sopenharmony_ci}
40218c2ecf20Sopenharmony_ci
40228c2ecf20Sopenharmony_ci/* Obtain the current volatile values of an autocluster and mark them
40238c2ecf20Sopenharmony_ci   as new. */
40248c2ecf20Sopenharmony_cistatic void update_from_auto_cluster(struct v4l2_ctrl *master)
40258c2ecf20Sopenharmony_ci{
40268c2ecf20Sopenharmony_ci	int i;
40278c2ecf20Sopenharmony_ci
40288c2ecf20Sopenharmony_ci	for (i = 1; i < master->ncontrols; i++)
40298c2ecf20Sopenharmony_ci		cur_to_new(master->cluster[i]);
40308c2ecf20Sopenharmony_ci	if (!call_op(master, g_volatile_ctrl))
40318c2ecf20Sopenharmony_ci		for (i = 1; i < master->ncontrols; i++)
40328c2ecf20Sopenharmony_ci			if (master->cluster[i])
40338c2ecf20Sopenharmony_ci				master->cluster[i]->is_new = 1;
40348c2ecf20Sopenharmony_ci}
40358c2ecf20Sopenharmony_ci
40368c2ecf20Sopenharmony_ci/* Try or try-and-set controls */
40378c2ecf20Sopenharmony_cistatic int try_set_ext_ctrls_common(struct v4l2_fh *fh,
40388c2ecf20Sopenharmony_ci				    struct v4l2_ctrl_handler *hdl,
40398c2ecf20Sopenharmony_ci				    struct v4l2_ext_controls *cs,
40408c2ecf20Sopenharmony_ci				    struct video_device *vdev, bool set)
40418c2ecf20Sopenharmony_ci{
40428c2ecf20Sopenharmony_ci	struct v4l2_ctrl_helper helper[4];
40438c2ecf20Sopenharmony_ci	struct v4l2_ctrl_helper *helpers = helper;
40448c2ecf20Sopenharmony_ci	unsigned i, j;
40458c2ecf20Sopenharmony_ci	int ret;
40468c2ecf20Sopenharmony_ci
40478c2ecf20Sopenharmony_ci	cs->error_idx = cs->count;
40488c2ecf20Sopenharmony_ci
40498c2ecf20Sopenharmony_ci	/* Default value cannot be changed */
40508c2ecf20Sopenharmony_ci	if (cs->which == V4L2_CTRL_WHICH_DEF_VAL) {
40518c2ecf20Sopenharmony_ci		dprintk(vdev, "%s: cannot change default value\n",
40528c2ecf20Sopenharmony_ci			video_device_node_name(vdev));
40538c2ecf20Sopenharmony_ci		return -EINVAL;
40548c2ecf20Sopenharmony_ci	}
40558c2ecf20Sopenharmony_ci
40568c2ecf20Sopenharmony_ci	cs->which = V4L2_CTRL_ID2WHICH(cs->which);
40578c2ecf20Sopenharmony_ci
40588c2ecf20Sopenharmony_ci	if (hdl == NULL) {
40598c2ecf20Sopenharmony_ci		dprintk(vdev, "%s: invalid null control handler\n",
40608c2ecf20Sopenharmony_ci			video_device_node_name(vdev));
40618c2ecf20Sopenharmony_ci		return -EINVAL;
40628c2ecf20Sopenharmony_ci	}
40638c2ecf20Sopenharmony_ci
40648c2ecf20Sopenharmony_ci	if (cs->count == 0)
40658c2ecf20Sopenharmony_ci		return class_check(hdl, cs->which);
40668c2ecf20Sopenharmony_ci
40678c2ecf20Sopenharmony_ci	if (cs->count > ARRAY_SIZE(helper)) {
40688c2ecf20Sopenharmony_ci		helpers = kvmalloc_array(cs->count, sizeof(helper[0]),
40698c2ecf20Sopenharmony_ci					 GFP_KERNEL);
40708c2ecf20Sopenharmony_ci		if (!helpers)
40718c2ecf20Sopenharmony_ci			return -ENOMEM;
40728c2ecf20Sopenharmony_ci	}
40738c2ecf20Sopenharmony_ci	ret = prepare_ext_ctrls(hdl, cs, helpers, vdev, false);
40748c2ecf20Sopenharmony_ci	if (!ret)
40758c2ecf20Sopenharmony_ci		ret = validate_ctrls(cs, helpers, vdev, set);
40768c2ecf20Sopenharmony_ci	if (ret && set)
40778c2ecf20Sopenharmony_ci		cs->error_idx = cs->count;
40788c2ecf20Sopenharmony_ci	for (i = 0; !ret && i < cs->count; i++) {
40798c2ecf20Sopenharmony_ci		struct v4l2_ctrl *master;
40808c2ecf20Sopenharmony_ci		u32 idx = i;
40818c2ecf20Sopenharmony_ci
40828c2ecf20Sopenharmony_ci		if (helpers[i].mref == NULL)
40838c2ecf20Sopenharmony_ci			continue;
40848c2ecf20Sopenharmony_ci
40858c2ecf20Sopenharmony_ci		cs->error_idx = i;
40868c2ecf20Sopenharmony_ci		master = helpers[i].mref->ctrl;
40878c2ecf20Sopenharmony_ci		v4l2_ctrl_lock(master);
40888c2ecf20Sopenharmony_ci
40898c2ecf20Sopenharmony_ci		/* Reset the 'is_new' flags of the cluster */
40908c2ecf20Sopenharmony_ci		for (j = 0; j < master->ncontrols; j++)
40918c2ecf20Sopenharmony_ci			if (master->cluster[j])
40928c2ecf20Sopenharmony_ci				master->cluster[j]->is_new = 0;
40938c2ecf20Sopenharmony_ci
40948c2ecf20Sopenharmony_ci		/* For volatile autoclusters that are currently in auto mode
40958c2ecf20Sopenharmony_ci		   we need to discover if it will be set to manual mode.
40968c2ecf20Sopenharmony_ci		   If so, then we have to copy the current volatile values
40978c2ecf20Sopenharmony_ci		   first since those will become the new manual values (which
40988c2ecf20Sopenharmony_ci		   may be overwritten by explicit new values from this set
40998c2ecf20Sopenharmony_ci		   of controls). */
41008c2ecf20Sopenharmony_ci		if (master->is_auto && master->has_volatiles &&
41018c2ecf20Sopenharmony_ci						!is_cur_manual(master)) {
41028c2ecf20Sopenharmony_ci			/* Pick an initial non-manual value */
41038c2ecf20Sopenharmony_ci			s32 new_auto_val = master->manual_mode_value + 1;
41048c2ecf20Sopenharmony_ci			u32 tmp_idx = idx;
41058c2ecf20Sopenharmony_ci
41068c2ecf20Sopenharmony_ci			do {
41078c2ecf20Sopenharmony_ci				/* Check if the auto control is part of the
41088c2ecf20Sopenharmony_ci				   list, and remember the new value. */
41098c2ecf20Sopenharmony_ci				if (helpers[tmp_idx].ref->ctrl == master)
41108c2ecf20Sopenharmony_ci					new_auto_val = cs->controls[tmp_idx].value;
41118c2ecf20Sopenharmony_ci				tmp_idx = helpers[tmp_idx].next;
41128c2ecf20Sopenharmony_ci			} while (tmp_idx);
41138c2ecf20Sopenharmony_ci			/* If the new value == the manual value, then copy
41148c2ecf20Sopenharmony_ci			   the current volatile values. */
41158c2ecf20Sopenharmony_ci			if (new_auto_val == master->manual_mode_value)
41168c2ecf20Sopenharmony_ci				update_from_auto_cluster(master);
41178c2ecf20Sopenharmony_ci		}
41188c2ecf20Sopenharmony_ci
41198c2ecf20Sopenharmony_ci		/* Copy the new caller-supplied control values.
41208c2ecf20Sopenharmony_ci		   user_to_new() sets 'is_new' to 1. */
41218c2ecf20Sopenharmony_ci		do {
41228c2ecf20Sopenharmony_ci			struct v4l2_ctrl *ctrl = helpers[idx].ref->ctrl;
41238c2ecf20Sopenharmony_ci
41248c2ecf20Sopenharmony_ci			ret = user_to_new(cs->controls + idx, ctrl);
41258c2ecf20Sopenharmony_ci			if (!ret && ctrl->is_ptr)
41268c2ecf20Sopenharmony_ci				ret = validate_new(ctrl, ctrl->p_new);
41278c2ecf20Sopenharmony_ci			idx = helpers[idx].next;
41288c2ecf20Sopenharmony_ci		} while (!ret && idx);
41298c2ecf20Sopenharmony_ci
41308c2ecf20Sopenharmony_ci		if (!ret)
41318c2ecf20Sopenharmony_ci			ret = try_or_set_cluster(fh, master,
41328c2ecf20Sopenharmony_ci						 !hdl->req_obj.req && set, 0);
41338c2ecf20Sopenharmony_ci		if (!ret && hdl->req_obj.req && set) {
41348c2ecf20Sopenharmony_ci			for (j = 0; j < master->ncontrols; j++) {
41358c2ecf20Sopenharmony_ci				struct v4l2_ctrl_ref *ref =
41368c2ecf20Sopenharmony_ci					find_ref(hdl, master->cluster[j]->id);
41378c2ecf20Sopenharmony_ci
41388c2ecf20Sopenharmony_ci				new_to_req(ref);
41398c2ecf20Sopenharmony_ci			}
41408c2ecf20Sopenharmony_ci		}
41418c2ecf20Sopenharmony_ci
41428c2ecf20Sopenharmony_ci		/* Copy the new values back to userspace. */
41438c2ecf20Sopenharmony_ci		if (!ret) {
41448c2ecf20Sopenharmony_ci			idx = i;
41458c2ecf20Sopenharmony_ci			do {
41468c2ecf20Sopenharmony_ci				ret = new_to_user(cs->controls + idx,
41478c2ecf20Sopenharmony_ci						helpers[idx].ref->ctrl);
41488c2ecf20Sopenharmony_ci				idx = helpers[idx].next;
41498c2ecf20Sopenharmony_ci			} while (!ret && idx);
41508c2ecf20Sopenharmony_ci		}
41518c2ecf20Sopenharmony_ci		v4l2_ctrl_unlock(master);
41528c2ecf20Sopenharmony_ci	}
41538c2ecf20Sopenharmony_ci
41548c2ecf20Sopenharmony_ci	if (cs->count > ARRAY_SIZE(helper))
41558c2ecf20Sopenharmony_ci		kvfree(helpers);
41568c2ecf20Sopenharmony_ci	return ret;
41578c2ecf20Sopenharmony_ci}
41588c2ecf20Sopenharmony_ci
41598c2ecf20Sopenharmony_cistatic int try_set_ext_ctrls(struct v4l2_fh *fh,
41608c2ecf20Sopenharmony_ci			     struct v4l2_ctrl_handler *hdl,
41618c2ecf20Sopenharmony_ci			     struct video_device *vdev,
41628c2ecf20Sopenharmony_ci			     struct media_device *mdev,
41638c2ecf20Sopenharmony_ci			     struct v4l2_ext_controls *cs, bool set)
41648c2ecf20Sopenharmony_ci{
41658c2ecf20Sopenharmony_ci	struct media_request_object *obj = NULL;
41668c2ecf20Sopenharmony_ci	struct media_request *req = NULL;
41678c2ecf20Sopenharmony_ci	int ret;
41688c2ecf20Sopenharmony_ci
41698c2ecf20Sopenharmony_ci	if (cs->which == V4L2_CTRL_WHICH_REQUEST_VAL) {
41708c2ecf20Sopenharmony_ci		if (!mdev) {
41718c2ecf20Sopenharmony_ci			dprintk(vdev, "%s: missing media device\n",
41728c2ecf20Sopenharmony_ci				video_device_node_name(vdev));
41738c2ecf20Sopenharmony_ci			return -EINVAL;
41748c2ecf20Sopenharmony_ci		}
41758c2ecf20Sopenharmony_ci
41768c2ecf20Sopenharmony_ci		if (cs->request_fd < 0) {
41778c2ecf20Sopenharmony_ci			dprintk(vdev, "%s: invalid request fd %d\n",
41788c2ecf20Sopenharmony_ci				video_device_node_name(vdev), cs->request_fd);
41798c2ecf20Sopenharmony_ci			return -EINVAL;
41808c2ecf20Sopenharmony_ci		}
41818c2ecf20Sopenharmony_ci
41828c2ecf20Sopenharmony_ci		req = media_request_get_by_fd(mdev, cs->request_fd);
41838c2ecf20Sopenharmony_ci		if (IS_ERR(req)) {
41848c2ecf20Sopenharmony_ci			dprintk(vdev, "%s: cannot find request fd %d\n",
41858c2ecf20Sopenharmony_ci				video_device_node_name(vdev), cs->request_fd);
41868c2ecf20Sopenharmony_ci			return PTR_ERR(req);
41878c2ecf20Sopenharmony_ci		}
41888c2ecf20Sopenharmony_ci
41898c2ecf20Sopenharmony_ci		ret = media_request_lock_for_update(req);
41908c2ecf20Sopenharmony_ci		if (ret) {
41918c2ecf20Sopenharmony_ci			dprintk(vdev, "%s: cannot lock request fd %d\n",
41928c2ecf20Sopenharmony_ci				video_device_node_name(vdev), cs->request_fd);
41938c2ecf20Sopenharmony_ci			media_request_put(req);
41948c2ecf20Sopenharmony_ci			return ret;
41958c2ecf20Sopenharmony_ci		}
41968c2ecf20Sopenharmony_ci
41978c2ecf20Sopenharmony_ci		obj = v4l2_ctrls_find_req_obj(hdl, req, set);
41988c2ecf20Sopenharmony_ci		if (IS_ERR(obj)) {
41998c2ecf20Sopenharmony_ci			dprintk(vdev,
42008c2ecf20Sopenharmony_ci				"%s: cannot find request object for request fd %d\n",
42018c2ecf20Sopenharmony_ci				video_device_node_name(vdev),
42028c2ecf20Sopenharmony_ci				cs->request_fd);
42038c2ecf20Sopenharmony_ci			media_request_unlock_for_update(req);
42048c2ecf20Sopenharmony_ci			media_request_put(req);
42058c2ecf20Sopenharmony_ci			return PTR_ERR(obj);
42068c2ecf20Sopenharmony_ci		}
42078c2ecf20Sopenharmony_ci		hdl = container_of(obj, struct v4l2_ctrl_handler,
42088c2ecf20Sopenharmony_ci				   req_obj);
42098c2ecf20Sopenharmony_ci	}
42108c2ecf20Sopenharmony_ci
42118c2ecf20Sopenharmony_ci	ret = try_set_ext_ctrls_common(fh, hdl, cs, vdev, set);
42128c2ecf20Sopenharmony_ci	if (ret)
42138c2ecf20Sopenharmony_ci		dprintk(vdev,
42148c2ecf20Sopenharmony_ci			"%s: try_set_ext_ctrls_common failed (%d)\n",
42158c2ecf20Sopenharmony_ci			video_device_node_name(vdev), ret);
42168c2ecf20Sopenharmony_ci
42178c2ecf20Sopenharmony_ci	if (obj) {
42188c2ecf20Sopenharmony_ci		media_request_unlock_for_update(req);
42198c2ecf20Sopenharmony_ci		media_request_object_put(obj);
42208c2ecf20Sopenharmony_ci		media_request_put(req);
42218c2ecf20Sopenharmony_ci	}
42228c2ecf20Sopenharmony_ci
42238c2ecf20Sopenharmony_ci	return ret;
42248c2ecf20Sopenharmony_ci}
42258c2ecf20Sopenharmony_ci
42268c2ecf20Sopenharmony_ciint v4l2_try_ext_ctrls(struct v4l2_ctrl_handler *hdl,
42278c2ecf20Sopenharmony_ci		       struct video_device *vdev,
42288c2ecf20Sopenharmony_ci		       struct media_device *mdev,
42298c2ecf20Sopenharmony_ci		       struct v4l2_ext_controls *cs)
42308c2ecf20Sopenharmony_ci{
42318c2ecf20Sopenharmony_ci	return try_set_ext_ctrls(NULL, hdl, vdev, mdev, cs, false);
42328c2ecf20Sopenharmony_ci}
42338c2ecf20Sopenharmony_ciEXPORT_SYMBOL(v4l2_try_ext_ctrls);
42348c2ecf20Sopenharmony_ci
42358c2ecf20Sopenharmony_ciint v4l2_s_ext_ctrls(struct v4l2_fh *fh,
42368c2ecf20Sopenharmony_ci		     struct v4l2_ctrl_handler *hdl,
42378c2ecf20Sopenharmony_ci		     struct video_device *vdev,
42388c2ecf20Sopenharmony_ci		     struct media_device *mdev,
42398c2ecf20Sopenharmony_ci		     struct v4l2_ext_controls *cs)
42408c2ecf20Sopenharmony_ci{
42418c2ecf20Sopenharmony_ci	return try_set_ext_ctrls(fh, hdl, vdev, mdev, cs, true);
42428c2ecf20Sopenharmony_ci}
42438c2ecf20Sopenharmony_ciEXPORT_SYMBOL(v4l2_s_ext_ctrls);
42448c2ecf20Sopenharmony_ci
42458c2ecf20Sopenharmony_ci/* Helper function for VIDIOC_S_CTRL compatibility */
42468c2ecf20Sopenharmony_cistatic int set_ctrl(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl, u32 ch_flags)
42478c2ecf20Sopenharmony_ci{
42488c2ecf20Sopenharmony_ci	struct v4l2_ctrl *master = ctrl->cluster[0];
42498c2ecf20Sopenharmony_ci	int ret;
42508c2ecf20Sopenharmony_ci	int i;
42518c2ecf20Sopenharmony_ci
42528c2ecf20Sopenharmony_ci	/* Reset the 'is_new' flags of the cluster */
42538c2ecf20Sopenharmony_ci	for (i = 0; i < master->ncontrols; i++)
42548c2ecf20Sopenharmony_ci		if (master->cluster[i])
42558c2ecf20Sopenharmony_ci			master->cluster[i]->is_new = 0;
42568c2ecf20Sopenharmony_ci
42578c2ecf20Sopenharmony_ci	ret = validate_new(ctrl, ctrl->p_new);
42588c2ecf20Sopenharmony_ci	if (ret)
42598c2ecf20Sopenharmony_ci		return ret;
42608c2ecf20Sopenharmony_ci
42618c2ecf20Sopenharmony_ci	/* For autoclusters with volatiles that are switched from auto to
42628c2ecf20Sopenharmony_ci	   manual mode we have to update the current volatile values since
42638c2ecf20Sopenharmony_ci	   those will become the initial manual values after such a switch. */
42648c2ecf20Sopenharmony_ci	if (master->is_auto && master->has_volatiles && ctrl == master &&
42658c2ecf20Sopenharmony_ci	    !is_cur_manual(master) && ctrl->val == master->manual_mode_value)
42668c2ecf20Sopenharmony_ci		update_from_auto_cluster(master);
42678c2ecf20Sopenharmony_ci
42688c2ecf20Sopenharmony_ci	ctrl->is_new = 1;
42698c2ecf20Sopenharmony_ci	return try_or_set_cluster(fh, master, true, ch_flags);
42708c2ecf20Sopenharmony_ci}
42718c2ecf20Sopenharmony_ci
42728c2ecf20Sopenharmony_ci/* Helper function for VIDIOC_S_CTRL compatibility */
42738c2ecf20Sopenharmony_cistatic int set_ctrl_lock(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl,
42748c2ecf20Sopenharmony_ci			 struct v4l2_ext_control *c)
42758c2ecf20Sopenharmony_ci{
42768c2ecf20Sopenharmony_ci	int ret;
42778c2ecf20Sopenharmony_ci
42788c2ecf20Sopenharmony_ci	v4l2_ctrl_lock(ctrl);
42798c2ecf20Sopenharmony_ci	user_to_new(c, ctrl);
42808c2ecf20Sopenharmony_ci	ret = set_ctrl(fh, ctrl, 0);
42818c2ecf20Sopenharmony_ci	if (!ret)
42828c2ecf20Sopenharmony_ci		cur_to_user(c, ctrl);
42838c2ecf20Sopenharmony_ci	v4l2_ctrl_unlock(ctrl);
42848c2ecf20Sopenharmony_ci	return ret;
42858c2ecf20Sopenharmony_ci}
42868c2ecf20Sopenharmony_ci
42878c2ecf20Sopenharmony_ciint v4l2_s_ctrl(struct v4l2_fh *fh, struct v4l2_ctrl_handler *hdl,
42888c2ecf20Sopenharmony_ci					struct v4l2_control *control)
42898c2ecf20Sopenharmony_ci{
42908c2ecf20Sopenharmony_ci	struct v4l2_ctrl *ctrl = v4l2_ctrl_find(hdl, control->id);
42918c2ecf20Sopenharmony_ci	struct v4l2_ext_control c = { control->id };
42928c2ecf20Sopenharmony_ci	int ret;
42938c2ecf20Sopenharmony_ci
42948c2ecf20Sopenharmony_ci	if (ctrl == NULL || !ctrl->is_int)
42958c2ecf20Sopenharmony_ci		return -EINVAL;
42968c2ecf20Sopenharmony_ci
42978c2ecf20Sopenharmony_ci	if (ctrl->flags & V4L2_CTRL_FLAG_READ_ONLY)
42988c2ecf20Sopenharmony_ci		return -EACCES;
42998c2ecf20Sopenharmony_ci
43008c2ecf20Sopenharmony_ci	c.value = control->value;
43018c2ecf20Sopenharmony_ci	ret = set_ctrl_lock(fh, ctrl, &c);
43028c2ecf20Sopenharmony_ci	control->value = c.value;
43038c2ecf20Sopenharmony_ci	return ret;
43048c2ecf20Sopenharmony_ci}
43058c2ecf20Sopenharmony_ciEXPORT_SYMBOL(v4l2_s_ctrl);
43068c2ecf20Sopenharmony_ci
43078c2ecf20Sopenharmony_ciint __v4l2_ctrl_s_ctrl(struct v4l2_ctrl *ctrl, s32 val)
43088c2ecf20Sopenharmony_ci{
43098c2ecf20Sopenharmony_ci	lockdep_assert_held(ctrl->handler->lock);
43108c2ecf20Sopenharmony_ci
43118c2ecf20Sopenharmony_ci	/* It's a driver bug if this happens. */
43128c2ecf20Sopenharmony_ci	if (WARN_ON(!ctrl->is_int))
43138c2ecf20Sopenharmony_ci		return -EINVAL;
43148c2ecf20Sopenharmony_ci	ctrl->val = val;
43158c2ecf20Sopenharmony_ci	return set_ctrl(NULL, ctrl, 0);
43168c2ecf20Sopenharmony_ci}
43178c2ecf20Sopenharmony_ciEXPORT_SYMBOL(__v4l2_ctrl_s_ctrl);
43188c2ecf20Sopenharmony_ci
43198c2ecf20Sopenharmony_ciint __v4l2_ctrl_s_ctrl_int64(struct v4l2_ctrl *ctrl, s64 val)
43208c2ecf20Sopenharmony_ci{
43218c2ecf20Sopenharmony_ci	lockdep_assert_held(ctrl->handler->lock);
43228c2ecf20Sopenharmony_ci
43238c2ecf20Sopenharmony_ci	/* It's a driver bug if this happens. */
43248c2ecf20Sopenharmony_ci	if (WARN_ON(ctrl->is_ptr || ctrl->type != V4L2_CTRL_TYPE_INTEGER64))
43258c2ecf20Sopenharmony_ci		return -EINVAL;
43268c2ecf20Sopenharmony_ci	*ctrl->p_new.p_s64 = val;
43278c2ecf20Sopenharmony_ci	return set_ctrl(NULL, ctrl, 0);
43288c2ecf20Sopenharmony_ci}
43298c2ecf20Sopenharmony_ciEXPORT_SYMBOL(__v4l2_ctrl_s_ctrl_int64);
43308c2ecf20Sopenharmony_ci
43318c2ecf20Sopenharmony_ciint __v4l2_ctrl_s_ctrl_string(struct v4l2_ctrl *ctrl, const char *s)
43328c2ecf20Sopenharmony_ci{
43338c2ecf20Sopenharmony_ci	lockdep_assert_held(ctrl->handler->lock);
43348c2ecf20Sopenharmony_ci
43358c2ecf20Sopenharmony_ci	/* It's a driver bug if this happens. */
43368c2ecf20Sopenharmony_ci	if (WARN_ON(ctrl->type != V4L2_CTRL_TYPE_STRING))
43378c2ecf20Sopenharmony_ci		return -EINVAL;
43388c2ecf20Sopenharmony_ci	strscpy(ctrl->p_new.p_char, s, ctrl->maximum + 1);
43398c2ecf20Sopenharmony_ci	return set_ctrl(NULL, ctrl, 0);
43408c2ecf20Sopenharmony_ci}
43418c2ecf20Sopenharmony_ciEXPORT_SYMBOL(__v4l2_ctrl_s_ctrl_string);
43428c2ecf20Sopenharmony_ci
43438c2ecf20Sopenharmony_ciint __v4l2_ctrl_s_ctrl_compound(struct v4l2_ctrl *ctrl,
43448c2ecf20Sopenharmony_ci				enum v4l2_ctrl_type type, const void *p)
43458c2ecf20Sopenharmony_ci{
43468c2ecf20Sopenharmony_ci	lockdep_assert_held(ctrl->handler->lock);
43478c2ecf20Sopenharmony_ci
43488c2ecf20Sopenharmony_ci	/* It's a driver bug if this happens. */
43498c2ecf20Sopenharmony_ci	if (WARN_ON(ctrl->type != type))
43508c2ecf20Sopenharmony_ci		return -EINVAL;
43518c2ecf20Sopenharmony_ci	memcpy(ctrl->p_new.p, p, ctrl->elems * ctrl->elem_size);
43528c2ecf20Sopenharmony_ci	return set_ctrl(NULL, ctrl, 0);
43538c2ecf20Sopenharmony_ci}
43548c2ecf20Sopenharmony_ciEXPORT_SYMBOL(__v4l2_ctrl_s_ctrl_compound);
43558c2ecf20Sopenharmony_ci
43568c2ecf20Sopenharmony_civoid v4l2_ctrl_request_complete(struct media_request *req,
43578c2ecf20Sopenharmony_ci				struct v4l2_ctrl_handler *main_hdl)
43588c2ecf20Sopenharmony_ci{
43598c2ecf20Sopenharmony_ci	struct media_request_object *obj;
43608c2ecf20Sopenharmony_ci	struct v4l2_ctrl_handler *hdl;
43618c2ecf20Sopenharmony_ci	struct v4l2_ctrl_ref *ref;
43628c2ecf20Sopenharmony_ci
43638c2ecf20Sopenharmony_ci	if (!req || !main_hdl)
43648c2ecf20Sopenharmony_ci		return;
43658c2ecf20Sopenharmony_ci
43668c2ecf20Sopenharmony_ci	/*
43678c2ecf20Sopenharmony_ci	 * Note that it is valid if nothing was found. It means
43688c2ecf20Sopenharmony_ci	 * that this request doesn't have any controls and so just
43698c2ecf20Sopenharmony_ci	 * wants to leave the controls unchanged.
43708c2ecf20Sopenharmony_ci	 */
43718c2ecf20Sopenharmony_ci	obj = media_request_object_find(req, &req_ops, main_hdl);
43728c2ecf20Sopenharmony_ci	if (!obj)
43738c2ecf20Sopenharmony_ci		return;
43748c2ecf20Sopenharmony_ci	hdl = container_of(obj, struct v4l2_ctrl_handler, req_obj);
43758c2ecf20Sopenharmony_ci
43768c2ecf20Sopenharmony_ci	list_for_each_entry(ref, &hdl->ctrl_refs, node) {
43778c2ecf20Sopenharmony_ci		struct v4l2_ctrl *ctrl = ref->ctrl;
43788c2ecf20Sopenharmony_ci		struct v4l2_ctrl *master = ctrl->cluster[0];
43798c2ecf20Sopenharmony_ci		unsigned int i;
43808c2ecf20Sopenharmony_ci
43818c2ecf20Sopenharmony_ci		if (ctrl->flags & V4L2_CTRL_FLAG_VOLATILE) {
43828c2ecf20Sopenharmony_ci			v4l2_ctrl_lock(master);
43838c2ecf20Sopenharmony_ci			/* g_volatile_ctrl will update the current control values */
43848c2ecf20Sopenharmony_ci			for (i = 0; i < master->ncontrols; i++)
43858c2ecf20Sopenharmony_ci				cur_to_new(master->cluster[i]);
43868c2ecf20Sopenharmony_ci			call_op(master, g_volatile_ctrl);
43878c2ecf20Sopenharmony_ci			new_to_req(ref);
43888c2ecf20Sopenharmony_ci			v4l2_ctrl_unlock(master);
43898c2ecf20Sopenharmony_ci			continue;
43908c2ecf20Sopenharmony_ci		}
43918c2ecf20Sopenharmony_ci		if (ref->valid_p_req)
43928c2ecf20Sopenharmony_ci			continue;
43938c2ecf20Sopenharmony_ci
43948c2ecf20Sopenharmony_ci		/* Copy the current control value into the request */
43958c2ecf20Sopenharmony_ci		v4l2_ctrl_lock(ctrl);
43968c2ecf20Sopenharmony_ci		cur_to_req(ref);
43978c2ecf20Sopenharmony_ci		v4l2_ctrl_unlock(ctrl);
43988c2ecf20Sopenharmony_ci	}
43998c2ecf20Sopenharmony_ci
44008c2ecf20Sopenharmony_ci	mutex_lock(main_hdl->lock);
44018c2ecf20Sopenharmony_ci	WARN_ON(!hdl->request_is_queued);
44028c2ecf20Sopenharmony_ci	list_del_init(&hdl->requests_queued);
44038c2ecf20Sopenharmony_ci	hdl->request_is_queued = false;
44048c2ecf20Sopenharmony_ci	mutex_unlock(main_hdl->lock);
44058c2ecf20Sopenharmony_ci	media_request_object_complete(obj);
44068c2ecf20Sopenharmony_ci	media_request_object_put(obj);
44078c2ecf20Sopenharmony_ci}
44088c2ecf20Sopenharmony_ciEXPORT_SYMBOL(v4l2_ctrl_request_complete);
44098c2ecf20Sopenharmony_ci
44108c2ecf20Sopenharmony_ciint v4l2_ctrl_request_setup(struct media_request *req,
44118c2ecf20Sopenharmony_ci			     struct v4l2_ctrl_handler *main_hdl)
44128c2ecf20Sopenharmony_ci{
44138c2ecf20Sopenharmony_ci	struct media_request_object *obj;
44148c2ecf20Sopenharmony_ci	struct v4l2_ctrl_handler *hdl;
44158c2ecf20Sopenharmony_ci	struct v4l2_ctrl_ref *ref;
44168c2ecf20Sopenharmony_ci	int ret = 0;
44178c2ecf20Sopenharmony_ci
44188c2ecf20Sopenharmony_ci	if (!req || !main_hdl)
44198c2ecf20Sopenharmony_ci		return 0;
44208c2ecf20Sopenharmony_ci
44218c2ecf20Sopenharmony_ci	if (WARN_ON(req->state != MEDIA_REQUEST_STATE_QUEUED))
44228c2ecf20Sopenharmony_ci		return -EBUSY;
44238c2ecf20Sopenharmony_ci
44248c2ecf20Sopenharmony_ci	/*
44258c2ecf20Sopenharmony_ci	 * Note that it is valid if nothing was found. It means
44268c2ecf20Sopenharmony_ci	 * that this request doesn't have any controls and so just
44278c2ecf20Sopenharmony_ci	 * wants to leave the controls unchanged.
44288c2ecf20Sopenharmony_ci	 */
44298c2ecf20Sopenharmony_ci	obj = media_request_object_find(req, &req_ops, main_hdl);
44308c2ecf20Sopenharmony_ci	if (!obj)
44318c2ecf20Sopenharmony_ci		return 0;
44328c2ecf20Sopenharmony_ci	if (obj->completed) {
44338c2ecf20Sopenharmony_ci		media_request_object_put(obj);
44348c2ecf20Sopenharmony_ci		return -EBUSY;
44358c2ecf20Sopenharmony_ci	}
44368c2ecf20Sopenharmony_ci	hdl = container_of(obj, struct v4l2_ctrl_handler, req_obj);
44378c2ecf20Sopenharmony_ci
44388c2ecf20Sopenharmony_ci	list_for_each_entry(ref, &hdl->ctrl_refs, node)
44398c2ecf20Sopenharmony_ci		ref->req_done = false;
44408c2ecf20Sopenharmony_ci
44418c2ecf20Sopenharmony_ci	list_for_each_entry(ref, &hdl->ctrl_refs, node) {
44428c2ecf20Sopenharmony_ci		struct v4l2_ctrl *ctrl = ref->ctrl;
44438c2ecf20Sopenharmony_ci		struct v4l2_ctrl *master = ctrl->cluster[0];
44448c2ecf20Sopenharmony_ci		bool have_new_data = false;
44458c2ecf20Sopenharmony_ci		int i;
44468c2ecf20Sopenharmony_ci
44478c2ecf20Sopenharmony_ci		/*
44488c2ecf20Sopenharmony_ci		 * Skip if this control was already handled by a cluster.
44498c2ecf20Sopenharmony_ci		 * Skip button controls and read-only controls.
44508c2ecf20Sopenharmony_ci		 */
44518c2ecf20Sopenharmony_ci		if (ref->req_done || ctrl->type == V4L2_CTRL_TYPE_BUTTON ||
44528c2ecf20Sopenharmony_ci		    (ctrl->flags & V4L2_CTRL_FLAG_READ_ONLY))
44538c2ecf20Sopenharmony_ci			continue;
44548c2ecf20Sopenharmony_ci
44558c2ecf20Sopenharmony_ci		v4l2_ctrl_lock(master);
44568c2ecf20Sopenharmony_ci		for (i = 0; i < master->ncontrols; i++) {
44578c2ecf20Sopenharmony_ci			if (master->cluster[i]) {
44588c2ecf20Sopenharmony_ci				struct v4l2_ctrl_ref *r =
44598c2ecf20Sopenharmony_ci					find_ref(hdl, master->cluster[i]->id);
44608c2ecf20Sopenharmony_ci
44618c2ecf20Sopenharmony_ci				if (r->valid_p_req) {
44628c2ecf20Sopenharmony_ci					have_new_data = true;
44638c2ecf20Sopenharmony_ci					break;
44648c2ecf20Sopenharmony_ci				}
44658c2ecf20Sopenharmony_ci			}
44668c2ecf20Sopenharmony_ci		}
44678c2ecf20Sopenharmony_ci		if (!have_new_data) {
44688c2ecf20Sopenharmony_ci			v4l2_ctrl_unlock(master);
44698c2ecf20Sopenharmony_ci			continue;
44708c2ecf20Sopenharmony_ci		}
44718c2ecf20Sopenharmony_ci
44728c2ecf20Sopenharmony_ci		for (i = 0; i < master->ncontrols; i++) {
44738c2ecf20Sopenharmony_ci			if (master->cluster[i]) {
44748c2ecf20Sopenharmony_ci				struct v4l2_ctrl_ref *r =
44758c2ecf20Sopenharmony_ci					find_ref(hdl, master->cluster[i]->id);
44768c2ecf20Sopenharmony_ci
44778c2ecf20Sopenharmony_ci				req_to_new(r);
44788c2ecf20Sopenharmony_ci				master->cluster[i]->is_new = 1;
44798c2ecf20Sopenharmony_ci				r->req_done = true;
44808c2ecf20Sopenharmony_ci			}
44818c2ecf20Sopenharmony_ci		}
44828c2ecf20Sopenharmony_ci		/*
44838c2ecf20Sopenharmony_ci		 * For volatile autoclusters that are currently in auto mode
44848c2ecf20Sopenharmony_ci		 * we need to discover if it will be set to manual mode.
44858c2ecf20Sopenharmony_ci		 * If so, then we have to copy the current volatile values
44868c2ecf20Sopenharmony_ci		 * first since those will become the new manual values (which
44878c2ecf20Sopenharmony_ci		 * may be overwritten by explicit new values from this set
44888c2ecf20Sopenharmony_ci		 * of controls).
44898c2ecf20Sopenharmony_ci		 */
44908c2ecf20Sopenharmony_ci		if (master->is_auto && master->has_volatiles &&
44918c2ecf20Sopenharmony_ci		    !is_cur_manual(master)) {
44928c2ecf20Sopenharmony_ci			s32 new_auto_val = *master->p_new.p_s32;
44938c2ecf20Sopenharmony_ci
44948c2ecf20Sopenharmony_ci			/*
44958c2ecf20Sopenharmony_ci			 * If the new value == the manual value, then copy
44968c2ecf20Sopenharmony_ci			 * the current volatile values.
44978c2ecf20Sopenharmony_ci			 */
44988c2ecf20Sopenharmony_ci			if (new_auto_val == master->manual_mode_value)
44998c2ecf20Sopenharmony_ci				update_from_auto_cluster(master);
45008c2ecf20Sopenharmony_ci		}
45018c2ecf20Sopenharmony_ci
45028c2ecf20Sopenharmony_ci		ret = try_or_set_cluster(NULL, master, true, 0);
45038c2ecf20Sopenharmony_ci		v4l2_ctrl_unlock(master);
45048c2ecf20Sopenharmony_ci
45058c2ecf20Sopenharmony_ci		if (ret)
45068c2ecf20Sopenharmony_ci			break;
45078c2ecf20Sopenharmony_ci	}
45088c2ecf20Sopenharmony_ci
45098c2ecf20Sopenharmony_ci	media_request_object_put(obj);
45108c2ecf20Sopenharmony_ci	return ret;
45118c2ecf20Sopenharmony_ci}
45128c2ecf20Sopenharmony_ciEXPORT_SYMBOL(v4l2_ctrl_request_setup);
45138c2ecf20Sopenharmony_ci
45148c2ecf20Sopenharmony_civoid v4l2_ctrl_notify(struct v4l2_ctrl *ctrl, v4l2_ctrl_notify_fnc notify, void *priv)
45158c2ecf20Sopenharmony_ci{
45168c2ecf20Sopenharmony_ci	if (ctrl == NULL)
45178c2ecf20Sopenharmony_ci		return;
45188c2ecf20Sopenharmony_ci	if (notify == NULL) {
45198c2ecf20Sopenharmony_ci		ctrl->call_notify = 0;
45208c2ecf20Sopenharmony_ci		return;
45218c2ecf20Sopenharmony_ci	}
45228c2ecf20Sopenharmony_ci	if (WARN_ON(ctrl->handler->notify && ctrl->handler->notify != notify))
45238c2ecf20Sopenharmony_ci		return;
45248c2ecf20Sopenharmony_ci	ctrl->handler->notify = notify;
45258c2ecf20Sopenharmony_ci	ctrl->handler->notify_priv = priv;
45268c2ecf20Sopenharmony_ci	ctrl->call_notify = 1;
45278c2ecf20Sopenharmony_ci}
45288c2ecf20Sopenharmony_ciEXPORT_SYMBOL(v4l2_ctrl_notify);
45298c2ecf20Sopenharmony_ci
45308c2ecf20Sopenharmony_ciint __v4l2_ctrl_modify_range(struct v4l2_ctrl *ctrl,
45318c2ecf20Sopenharmony_ci			s64 min, s64 max, u64 step, s64 def)
45328c2ecf20Sopenharmony_ci{
45338c2ecf20Sopenharmony_ci	bool value_changed;
45348c2ecf20Sopenharmony_ci	bool range_changed = false;
45358c2ecf20Sopenharmony_ci	int ret;
45368c2ecf20Sopenharmony_ci
45378c2ecf20Sopenharmony_ci	lockdep_assert_held(ctrl->handler->lock);
45388c2ecf20Sopenharmony_ci
45398c2ecf20Sopenharmony_ci	switch (ctrl->type) {
45408c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_INTEGER:
45418c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_INTEGER64:
45428c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_BOOLEAN:
45438c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_MENU:
45448c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_INTEGER_MENU:
45458c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_BITMASK:
45468c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_U8:
45478c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_U16:
45488c2ecf20Sopenharmony_ci	case V4L2_CTRL_TYPE_U32:
45498c2ecf20Sopenharmony_ci		if (ctrl->is_array)
45508c2ecf20Sopenharmony_ci			return -EINVAL;
45518c2ecf20Sopenharmony_ci		ret = check_range(ctrl->type, min, max, step, def);
45528c2ecf20Sopenharmony_ci		if (ret)
45538c2ecf20Sopenharmony_ci			return ret;
45548c2ecf20Sopenharmony_ci		break;
45558c2ecf20Sopenharmony_ci	default:
45568c2ecf20Sopenharmony_ci		return -EINVAL;
45578c2ecf20Sopenharmony_ci	}
45588c2ecf20Sopenharmony_ci	if ((ctrl->minimum != min) || (ctrl->maximum != max) ||
45598c2ecf20Sopenharmony_ci		(ctrl->step != step) || ctrl->default_value != def) {
45608c2ecf20Sopenharmony_ci		range_changed = true;
45618c2ecf20Sopenharmony_ci		ctrl->minimum = min;
45628c2ecf20Sopenharmony_ci		ctrl->maximum = max;
45638c2ecf20Sopenharmony_ci		ctrl->step = step;
45648c2ecf20Sopenharmony_ci		ctrl->default_value = def;
45658c2ecf20Sopenharmony_ci	}
45668c2ecf20Sopenharmony_ci	cur_to_new(ctrl);
45678c2ecf20Sopenharmony_ci	if (validate_new(ctrl, ctrl->p_new)) {
45688c2ecf20Sopenharmony_ci		if (ctrl->type == V4L2_CTRL_TYPE_INTEGER64)
45698c2ecf20Sopenharmony_ci			*ctrl->p_new.p_s64 = def;
45708c2ecf20Sopenharmony_ci		else
45718c2ecf20Sopenharmony_ci			*ctrl->p_new.p_s32 = def;
45728c2ecf20Sopenharmony_ci	}
45738c2ecf20Sopenharmony_ci
45748c2ecf20Sopenharmony_ci	if (ctrl->type == V4L2_CTRL_TYPE_INTEGER64)
45758c2ecf20Sopenharmony_ci		value_changed = *ctrl->p_new.p_s64 != *ctrl->p_cur.p_s64;
45768c2ecf20Sopenharmony_ci	else
45778c2ecf20Sopenharmony_ci		value_changed = *ctrl->p_new.p_s32 != *ctrl->p_cur.p_s32;
45788c2ecf20Sopenharmony_ci	if (value_changed)
45798c2ecf20Sopenharmony_ci		ret = set_ctrl(NULL, ctrl, V4L2_EVENT_CTRL_CH_RANGE);
45808c2ecf20Sopenharmony_ci	else if (range_changed)
45818c2ecf20Sopenharmony_ci		send_event(NULL, ctrl, V4L2_EVENT_CTRL_CH_RANGE);
45828c2ecf20Sopenharmony_ci	return ret;
45838c2ecf20Sopenharmony_ci}
45848c2ecf20Sopenharmony_ciEXPORT_SYMBOL(__v4l2_ctrl_modify_range);
45858c2ecf20Sopenharmony_ci
45868c2ecf20Sopenharmony_cistatic int v4l2_ctrl_add_event(struct v4l2_subscribed_event *sev, unsigned elems)
45878c2ecf20Sopenharmony_ci{
45888c2ecf20Sopenharmony_ci	struct v4l2_ctrl *ctrl = v4l2_ctrl_find(sev->fh->ctrl_handler, sev->id);
45898c2ecf20Sopenharmony_ci
45908c2ecf20Sopenharmony_ci	if (ctrl == NULL)
45918c2ecf20Sopenharmony_ci		return -EINVAL;
45928c2ecf20Sopenharmony_ci
45938c2ecf20Sopenharmony_ci	v4l2_ctrl_lock(ctrl);
45948c2ecf20Sopenharmony_ci	list_add_tail(&sev->node, &ctrl->ev_subs);
45958c2ecf20Sopenharmony_ci	if (ctrl->type != V4L2_CTRL_TYPE_CTRL_CLASS &&
45968c2ecf20Sopenharmony_ci	    (sev->flags & V4L2_EVENT_SUB_FL_SEND_INITIAL)) {
45978c2ecf20Sopenharmony_ci		struct v4l2_event ev;
45988c2ecf20Sopenharmony_ci		u32 changes = V4L2_EVENT_CTRL_CH_FLAGS;
45998c2ecf20Sopenharmony_ci
46008c2ecf20Sopenharmony_ci		if (!(ctrl->flags & V4L2_CTRL_FLAG_WRITE_ONLY))
46018c2ecf20Sopenharmony_ci			changes |= V4L2_EVENT_CTRL_CH_VALUE;
46028c2ecf20Sopenharmony_ci		fill_event(&ev, ctrl, changes);
46038c2ecf20Sopenharmony_ci		/* Mark the queue as active, allowing this initial
46048c2ecf20Sopenharmony_ci		   event to be accepted. */
46058c2ecf20Sopenharmony_ci		sev->elems = elems;
46068c2ecf20Sopenharmony_ci		v4l2_event_queue_fh(sev->fh, &ev);
46078c2ecf20Sopenharmony_ci	}
46088c2ecf20Sopenharmony_ci	v4l2_ctrl_unlock(ctrl);
46098c2ecf20Sopenharmony_ci	return 0;
46108c2ecf20Sopenharmony_ci}
46118c2ecf20Sopenharmony_ci
46128c2ecf20Sopenharmony_cistatic void v4l2_ctrl_del_event(struct v4l2_subscribed_event *sev)
46138c2ecf20Sopenharmony_ci{
46148c2ecf20Sopenharmony_ci	struct v4l2_ctrl *ctrl = v4l2_ctrl_find(sev->fh->ctrl_handler, sev->id);
46158c2ecf20Sopenharmony_ci
46168c2ecf20Sopenharmony_ci	if (ctrl == NULL)
46178c2ecf20Sopenharmony_ci		return;
46188c2ecf20Sopenharmony_ci
46198c2ecf20Sopenharmony_ci	v4l2_ctrl_lock(ctrl);
46208c2ecf20Sopenharmony_ci	list_del(&sev->node);
46218c2ecf20Sopenharmony_ci	v4l2_ctrl_unlock(ctrl);
46228c2ecf20Sopenharmony_ci}
46238c2ecf20Sopenharmony_ci
46248c2ecf20Sopenharmony_civoid v4l2_ctrl_replace(struct v4l2_event *old, const struct v4l2_event *new)
46258c2ecf20Sopenharmony_ci{
46268c2ecf20Sopenharmony_ci	u32 old_changes = old->u.ctrl.changes;
46278c2ecf20Sopenharmony_ci
46288c2ecf20Sopenharmony_ci	old->u.ctrl = new->u.ctrl;
46298c2ecf20Sopenharmony_ci	old->u.ctrl.changes |= old_changes;
46308c2ecf20Sopenharmony_ci}
46318c2ecf20Sopenharmony_ciEXPORT_SYMBOL(v4l2_ctrl_replace);
46328c2ecf20Sopenharmony_ci
46338c2ecf20Sopenharmony_civoid v4l2_ctrl_merge(const struct v4l2_event *old, struct v4l2_event *new)
46348c2ecf20Sopenharmony_ci{
46358c2ecf20Sopenharmony_ci	new->u.ctrl.changes |= old->u.ctrl.changes;
46368c2ecf20Sopenharmony_ci}
46378c2ecf20Sopenharmony_ciEXPORT_SYMBOL(v4l2_ctrl_merge);
46388c2ecf20Sopenharmony_ci
46398c2ecf20Sopenharmony_ciconst struct v4l2_subscribed_event_ops v4l2_ctrl_sub_ev_ops = {
46408c2ecf20Sopenharmony_ci	.add = v4l2_ctrl_add_event,
46418c2ecf20Sopenharmony_ci	.del = v4l2_ctrl_del_event,
46428c2ecf20Sopenharmony_ci	.replace = v4l2_ctrl_replace,
46438c2ecf20Sopenharmony_ci	.merge = v4l2_ctrl_merge,
46448c2ecf20Sopenharmony_ci};
46458c2ecf20Sopenharmony_ciEXPORT_SYMBOL(v4l2_ctrl_sub_ev_ops);
46468c2ecf20Sopenharmony_ci
46478c2ecf20Sopenharmony_ciint v4l2_ctrl_log_status(struct file *file, void *fh)
46488c2ecf20Sopenharmony_ci{
46498c2ecf20Sopenharmony_ci	struct video_device *vfd = video_devdata(file);
46508c2ecf20Sopenharmony_ci	struct v4l2_fh *vfh = file->private_data;
46518c2ecf20Sopenharmony_ci
46528c2ecf20Sopenharmony_ci	if (test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags) && vfd->v4l2_dev)
46538c2ecf20Sopenharmony_ci		v4l2_ctrl_handler_log_status(vfh->ctrl_handler,
46548c2ecf20Sopenharmony_ci			vfd->v4l2_dev->name);
46558c2ecf20Sopenharmony_ci	return 0;
46568c2ecf20Sopenharmony_ci}
46578c2ecf20Sopenharmony_ciEXPORT_SYMBOL(v4l2_ctrl_log_status);
46588c2ecf20Sopenharmony_ci
46598c2ecf20Sopenharmony_ciint v4l2_ctrl_subscribe_event(struct v4l2_fh *fh,
46608c2ecf20Sopenharmony_ci				const struct v4l2_event_subscription *sub)
46618c2ecf20Sopenharmony_ci{
46628c2ecf20Sopenharmony_ci	if (sub->type == V4L2_EVENT_CTRL)
46638c2ecf20Sopenharmony_ci		return v4l2_event_subscribe(fh, sub, 0, &v4l2_ctrl_sub_ev_ops);
46648c2ecf20Sopenharmony_ci	return -EINVAL;
46658c2ecf20Sopenharmony_ci}
46668c2ecf20Sopenharmony_ciEXPORT_SYMBOL(v4l2_ctrl_subscribe_event);
46678c2ecf20Sopenharmony_ci
46688c2ecf20Sopenharmony_ciint v4l2_ctrl_subdev_subscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh,
46698c2ecf20Sopenharmony_ci				     struct v4l2_event_subscription *sub)
46708c2ecf20Sopenharmony_ci{
46718c2ecf20Sopenharmony_ci	if (!sd->ctrl_handler)
46728c2ecf20Sopenharmony_ci		return -EINVAL;
46738c2ecf20Sopenharmony_ci	return v4l2_ctrl_subscribe_event(fh, sub);
46748c2ecf20Sopenharmony_ci}
46758c2ecf20Sopenharmony_ciEXPORT_SYMBOL(v4l2_ctrl_subdev_subscribe_event);
46768c2ecf20Sopenharmony_ci
46778c2ecf20Sopenharmony_ci__poll_t v4l2_ctrl_poll(struct file *file, struct poll_table_struct *wait)
46788c2ecf20Sopenharmony_ci{
46798c2ecf20Sopenharmony_ci	struct v4l2_fh *fh = file->private_data;
46808c2ecf20Sopenharmony_ci
46818c2ecf20Sopenharmony_ci	poll_wait(file, &fh->wait, wait);
46828c2ecf20Sopenharmony_ci	if (v4l2_event_pending(fh))
46838c2ecf20Sopenharmony_ci		return EPOLLPRI;
46848c2ecf20Sopenharmony_ci	return 0;
46858c2ecf20Sopenharmony_ci}
46868c2ecf20Sopenharmony_ciEXPORT_SYMBOL(v4l2_ctrl_poll);
46878c2ecf20Sopenharmony_ci
46888c2ecf20Sopenharmony_ciint v4l2_ctrl_new_fwnode_properties(struct v4l2_ctrl_handler *hdl,
46898c2ecf20Sopenharmony_ci				    const struct v4l2_ctrl_ops *ctrl_ops,
46908c2ecf20Sopenharmony_ci				    const struct v4l2_fwnode_device_properties *p)
46918c2ecf20Sopenharmony_ci{
46928c2ecf20Sopenharmony_ci	if (p->orientation != V4L2_FWNODE_PROPERTY_UNSET) {
46938c2ecf20Sopenharmony_ci		u32 orientation_ctrl;
46948c2ecf20Sopenharmony_ci
46958c2ecf20Sopenharmony_ci		switch (p->orientation) {
46968c2ecf20Sopenharmony_ci		case V4L2_FWNODE_ORIENTATION_FRONT:
46978c2ecf20Sopenharmony_ci			orientation_ctrl = V4L2_CAMERA_ORIENTATION_FRONT;
46988c2ecf20Sopenharmony_ci			break;
46998c2ecf20Sopenharmony_ci		case V4L2_FWNODE_ORIENTATION_BACK:
47008c2ecf20Sopenharmony_ci			orientation_ctrl = V4L2_CAMERA_ORIENTATION_BACK;
47018c2ecf20Sopenharmony_ci			break;
47028c2ecf20Sopenharmony_ci		case V4L2_FWNODE_ORIENTATION_EXTERNAL:
47038c2ecf20Sopenharmony_ci			orientation_ctrl = V4L2_CAMERA_ORIENTATION_EXTERNAL;
47048c2ecf20Sopenharmony_ci			break;
47058c2ecf20Sopenharmony_ci		default:
47068c2ecf20Sopenharmony_ci			return -EINVAL;
47078c2ecf20Sopenharmony_ci		}
47088c2ecf20Sopenharmony_ci		if (!v4l2_ctrl_new_std_menu(hdl, ctrl_ops,
47098c2ecf20Sopenharmony_ci					    V4L2_CID_CAMERA_ORIENTATION,
47108c2ecf20Sopenharmony_ci					    V4L2_CAMERA_ORIENTATION_EXTERNAL, 0,
47118c2ecf20Sopenharmony_ci					    orientation_ctrl))
47128c2ecf20Sopenharmony_ci			return hdl->error;
47138c2ecf20Sopenharmony_ci	}
47148c2ecf20Sopenharmony_ci
47158c2ecf20Sopenharmony_ci	if (p->rotation != V4L2_FWNODE_PROPERTY_UNSET) {
47168c2ecf20Sopenharmony_ci		if (!v4l2_ctrl_new_std(hdl, ctrl_ops,
47178c2ecf20Sopenharmony_ci				       V4L2_CID_CAMERA_SENSOR_ROTATION,
47188c2ecf20Sopenharmony_ci				       p->rotation, p->rotation, 1,
47198c2ecf20Sopenharmony_ci				       p->rotation))
47208c2ecf20Sopenharmony_ci			return hdl->error;
47218c2ecf20Sopenharmony_ci	}
47228c2ecf20Sopenharmony_ci
47238c2ecf20Sopenharmony_ci	return hdl->error;
47248c2ecf20Sopenharmony_ci}
47258c2ecf20Sopenharmony_ciEXPORT_SYMBOL(v4l2_ctrl_new_fwnode_properties);
4726