15bc3cb74SMauro Carvalho Chehab /*
25bc3cb74SMauro Carvalho Chehab  * Video capture interface for Linux version 2
35bc3cb74SMauro Carvalho Chehab  *
45bc3cb74SMauro Carvalho Chehab  * A generic framework to process V4L2 ioctl commands.
55bc3cb74SMauro Carvalho Chehab  *
65bc3cb74SMauro Carvalho Chehab  * This program is free software; you can redistribute it and/or
75bc3cb74SMauro Carvalho Chehab  * modify it under the terms of the GNU General Public License
85bc3cb74SMauro Carvalho Chehab  * as published by the Free Software Foundation; either version
95bc3cb74SMauro Carvalho Chehab  * 2 of the License, or (at your option) any later version.
105bc3cb74SMauro Carvalho Chehab  *
115bc3cb74SMauro Carvalho Chehab  * Authors:	Alan Cox, <alan@lxorguk.ukuu.org.uk> (version 1)
125bc3cb74SMauro Carvalho Chehab  *              Mauro Carvalho Chehab <mchehab@infradead.org> (version 2)
135bc3cb74SMauro Carvalho Chehab  */
145bc3cb74SMauro Carvalho Chehab 
15758d90e1STomasz Figa #include <linux/mm.h>
165bc3cb74SMauro Carvalho Chehab #include <linux/module.h>
175bc3cb74SMauro Carvalho Chehab #include <linux/slab.h>
185bc3cb74SMauro Carvalho Chehab #include <linux/types.h>
195bc3cb74SMauro Carvalho Chehab #include <linux/kernel.h>
205bc3cb74SMauro Carvalho Chehab #include <linux/version.h>
215bc3cb74SMauro Carvalho Chehab 
225bc3cb74SMauro Carvalho Chehab #include <linux/videodev2.h>
235bc3cb74SMauro Carvalho Chehab 
245bc3cb74SMauro Carvalho Chehab #include <media/v4l2-common.h>
255bc3cb74SMauro Carvalho Chehab #include <media/v4l2-ioctl.h>
265bc3cb74SMauro Carvalho Chehab #include <media/v4l2-ctrls.h>
275bc3cb74SMauro Carvalho Chehab #include <media/v4l2-fh.h>
285bc3cb74SMauro Carvalho Chehab #include <media/v4l2-event.h>
295bc3cb74SMauro Carvalho Chehab #include <media/v4l2-device.h>
30c139990eSJunghak Sung #include <media/videobuf2-v4l2.h>
3177fa4e07SShuah Khan #include <media/v4l2-mc.h>
325bc3cb74SMauro Carvalho Chehab 
33aa32f4c0SHans Verkuil #include <trace/events/v4l2.h>
34aa32f4c0SHans Verkuil 
355bc3cb74SMauro Carvalho Chehab /* Zero out the end of the struct pointed to by p.  Everything after, but
365bc3cb74SMauro Carvalho Chehab  * not including, the specified field is cleared. */
375bc3cb74SMauro Carvalho Chehab #define CLEAR_AFTER_FIELD(p, field) \
385bc3cb74SMauro Carvalho Chehab 	memset((u8 *)(p) + offsetof(typeof(*(p)), field) + sizeof((p)->field), \
395bc3cb74SMauro Carvalho Chehab 	0, sizeof(*(p)) - offsetof(typeof(*(p)), field) - sizeof((p)->field))
405bc3cb74SMauro Carvalho Chehab 
4173f35418SHans Verkuil #define is_valid_ioctl(vfd, cmd) test_bit(_IOC_NR(cmd), (vfd)->valid_ioctls)
4273f35418SHans Verkuil 
435bc3cb74SMauro Carvalho Chehab struct std_descr {
445bc3cb74SMauro Carvalho Chehab 	v4l2_std_id std;
455bc3cb74SMauro Carvalho Chehab 	const char *descr;
465bc3cb74SMauro Carvalho Chehab };
475bc3cb74SMauro Carvalho Chehab 
485bc3cb74SMauro Carvalho Chehab static const struct std_descr standards[] = {
495bc3cb74SMauro Carvalho Chehab 	{ V4L2_STD_NTSC, 	"NTSC"      },
505bc3cb74SMauro Carvalho Chehab 	{ V4L2_STD_NTSC_M, 	"NTSC-M"    },
515bc3cb74SMauro Carvalho Chehab 	{ V4L2_STD_NTSC_M_JP, 	"NTSC-M-JP" },
525bc3cb74SMauro Carvalho Chehab 	{ V4L2_STD_NTSC_M_KR,	"NTSC-M-KR" },
535bc3cb74SMauro Carvalho Chehab 	{ V4L2_STD_NTSC_443, 	"NTSC-443"  },
545bc3cb74SMauro Carvalho Chehab 	{ V4L2_STD_PAL, 	"PAL"       },
555bc3cb74SMauro Carvalho Chehab 	{ V4L2_STD_PAL_BG, 	"PAL-BG"    },
565bc3cb74SMauro Carvalho Chehab 	{ V4L2_STD_PAL_B, 	"PAL-B"     },
575bc3cb74SMauro Carvalho Chehab 	{ V4L2_STD_PAL_B1, 	"PAL-B1"    },
585bc3cb74SMauro Carvalho Chehab 	{ V4L2_STD_PAL_G, 	"PAL-G"     },
595bc3cb74SMauro Carvalho Chehab 	{ V4L2_STD_PAL_H, 	"PAL-H"     },
605bc3cb74SMauro Carvalho Chehab 	{ V4L2_STD_PAL_I, 	"PAL-I"     },
615bc3cb74SMauro Carvalho Chehab 	{ V4L2_STD_PAL_DK, 	"PAL-DK"    },
625bc3cb74SMauro Carvalho Chehab 	{ V4L2_STD_PAL_D, 	"PAL-D"     },
635bc3cb74SMauro Carvalho Chehab 	{ V4L2_STD_PAL_D1, 	"PAL-D1"    },
645bc3cb74SMauro Carvalho Chehab 	{ V4L2_STD_PAL_K, 	"PAL-K"     },
655bc3cb74SMauro Carvalho Chehab 	{ V4L2_STD_PAL_M, 	"PAL-M"     },
665bc3cb74SMauro Carvalho Chehab 	{ V4L2_STD_PAL_N, 	"PAL-N"     },
675bc3cb74SMauro Carvalho Chehab 	{ V4L2_STD_PAL_Nc, 	"PAL-Nc"    },
685bc3cb74SMauro Carvalho Chehab 	{ V4L2_STD_PAL_60, 	"PAL-60"    },
695bc3cb74SMauro Carvalho Chehab 	{ V4L2_STD_SECAM, 	"SECAM"     },
705bc3cb74SMauro Carvalho Chehab 	{ V4L2_STD_SECAM_B, 	"SECAM-B"   },
715bc3cb74SMauro Carvalho Chehab 	{ V4L2_STD_SECAM_G, 	"SECAM-G"   },
725bc3cb74SMauro Carvalho Chehab 	{ V4L2_STD_SECAM_H, 	"SECAM-H"   },
735bc3cb74SMauro Carvalho Chehab 	{ V4L2_STD_SECAM_DK, 	"SECAM-DK"  },
745bc3cb74SMauro Carvalho Chehab 	{ V4L2_STD_SECAM_D, 	"SECAM-D"   },
755bc3cb74SMauro Carvalho Chehab 	{ V4L2_STD_SECAM_K, 	"SECAM-K"   },
765bc3cb74SMauro Carvalho Chehab 	{ V4L2_STD_SECAM_K1, 	"SECAM-K1"  },
775bc3cb74SMauro Carvalho Chehab 	{ V4L2_STD_SECAM_L, 	"SECAM-L"   },
785bc3cb74SMauro Carvalho Chehab 	{ V4L2_STD_SECAM_LC, 	"SECAM-Lc"  },
795bc3cb74SMauro Carvalho Chehab 	{ 0, 			"Unknown"   }
805bc3cb74SMauro Carvalho Chehab };
815bc3cb74SMauro Carvalho Chehab 
825bc3cb74SMauro Carvalho Chehab /* video4linux standard ID conversion to standard name
835bc3cb74SMauro Carvalho Chehab  */
845bc3cb74SMauro Carvalho Chehab const char *v4l2_norm_to_name(v4l2_std_id id)
855bc3cb74SMauro Carvalho Chehab {
865bc3cb74SMauro Carvalho Chehab 	u32 myid = id;
875bc3cb74SMauro Carvalho Chehab 	int i;
885bc3cb74SMauro Carvalho Chehab 
895bc3cb74SMauro Carvalho Chehab 	/* HACK: ppc32 architecture doesn't have __ucmpdi2 function to handle
905bc3cb74SMauro Carvalho Chehab 	   64 bit comparations. So, on that architecture, with some gcc
915bc3cb74SMauro Carvalho Chehab 	   variants, compilation fails. Currently, the max value is 30bit wide.
925bc3cb74SMauro Carvalho Chehab 	 */
935bc3cb74SMauro Carvalho Chehab 	BUG_ON(myid != id);
945bc3cb74SMauro Carvalho Chehab 
955bc3cb74SMauro Carvalho Chehab 	for (i = 0; standards[i].std; i++)
965bc3cb74SMauro Carvalho Chehab 		if (myid == standards[i].std)
975bc3cb74SMauro Carvalho Chehab 			break;
985bc3cb74SMauro Carvalho Chehab 	return standards[i].descr;
995bc3cb74SMauro Carvalho Chehab }
1005bc3cb74SMauro Carvalho Chehab EXPORT_SYMBOL(v4l2_norm_to_name);
1015bc3cb74SMauro Carvalho Chehab 
1025bc3cb74SMauro Carvalho Chehab /* Returns frame period for the given standard */
1035bc3cb74SMauro Carvalho Chehab void v4l2_video_std_frame_period(int id, struct v4l2_fract *frameperiod)
1045bc3cb74SMauro Carvalho Chehab {
1055bc3cb74SMauro Carvalho Chehab 	if (id & V4L2_STD_525_60) {
1065bc3cb74SMauro Carvalho Chehab 		frameperiod->numerator = 1001;
1075bc3cb74SMauro Carvalho Chehab 		frameperiod->denominator = 30000;
1085bc3cb74SMauro Carvalho Chehab 	} else {
1095bc3cb74SMauro Carvalho Chehab 		frameperiod->numerator = 1;
1105bc3cb74SMauro Carvalho Chehab 		frameperiod->denominator = 25;
1115bc3cb74SMauro Carvalho Chehab 	}
1125bc3cb74SMauro Carvalho Chehab }
1135bc3cb74SMauro Carvalho Chehab EXPORT_SYMBOL(v4l2_video_std_frame_period);
1145bc3cb74SMauro Carvalho Chehab 
1155bc3cb74SMauro Carvalho Chehab /* Fill in the fields of a v4l2_standard structure according to the
1165bc3cb74SMauro Carvalho Chehab    'id' and 'transmission' parameters.  Returns negative on error.  */
1175bc3cb74SMauro Carvalho Chehab int v4l2_video_std_construct(struct v4l2_standard *vs,
1185bc3cb74SMauro Carvalho Chehab 			     int id, const char *name)
1195bc3cb74SMauro Carvalho Chehab {
1205bc3cb74SMauro Carvalho Chehab 	vs->id = id;
1215bc3cb74SMauro Carvalho Chehab 	v4l2_video_std_frame_period(id, &vs->frameperiod);
1225bc3cb74SMauro Carvalho Chehab 	vs->framelines = (id & V4L2_STD_525_60) ? 525 : 625;
1235bc3cb74SMauro Carvalho Chehab 	strlcpy(vs->name, name, sizeof(vs->name));
1245bc3cb74SMauro Carvalho Chehab 	return 0;
1255bc3cb74SMauro Carvalho Chehab }
1265bc3cb74SMauro Carvalho Chehab EXPORT_SYMBOL(v4l2_video_std_construct);
1275bc3cb74SMauro Carvalho Chehab 
1285bc3cb74SMauro Carvalho Chehab /* ----------------------------------------------------------------- */
1295bc3cb74SMauro Carvalho Chehab /* some arrays for pretty-printing debug messages of enum types      */
1305bc3cb74SMauro Carvalho Chehab 
1315bc3cb74SMauro Carvalho Chehab const char *v4l2_field_names[] = {
1325bc3cb74SMauro Carvalho Chehab 	[V4L2_FIELD_ANY]        = "any",
1335bc3cb74SMauro Carvalho Chehab 	[V4L2_FIELD_NONE]       = "none",
1345bc3cb74SMauro Carvalho Chehab 	[V4L2_FIELD_TOP]        = "top",
1355bc3cb74SMauro Carvalho Chehab 	[V4L2_FIELD_BOTTOM]     = "bottom",
1365bc3cb74SMauro Carvalho Chehab 	[V4L2_FIELD_INTERLACED] = "interlaced",
1375bc3cb74SMauro Carvalho Chehab 	[V4L2_FIELD_SEQ_TB]     = "seq-tb",
1385bc3cb74SMauro Carvalho Chehab 	[V4L2_FIELD_SEQ_BT]     = "seq-bt",
1395bc3cb74SMauro Carvalho Chehab 	[V4L2_FIELD_ALTERNATE]  = "alternate",
1405bc3cb74SMauro Carvalho Chehab 	[V4L2_FIELD_INTERLACED_TB] = "interlaced-tb",
1415bc3cb74SMauro Carvalho Chehab 	[V4L2_FIELD_INTERLACED_BT] = "interlaced-bt",
1425bc3cb74SMauro Carvalho Chehab };
1435bc3cb74SMauro Carvalho Chehab EXPORT_SYMBOL(v4l2_field_names);
1445bc3cb74SMauro Carvalho Chehab 
1455bc3cb74SMauro Carvalho Chehab const char *v4l2_type_names[] = {
146839aa56dSHans Verkuil 	[0]				   = "0",
1475bc3cb74SMauro Carvalho Chehab 	[V4L2_BUF_TYPE_VIDEO_CAPTURE]      = "vid-cap",
1485bc3cb74SMauro Carvalho Chehab 	[V4L2_BUF_TYPE_VIDEO_OVERLAY]      = "vid-overlay",
1495bc3cb74SMauro Carvalho Chehab 	[V4L2_BUF_TYPE_VIDEO_OUTPUT]       = "vid-out",
1505bc3cb74SMauro Carvalho Chehab 	[V4L2_BUF_TYPE_VBI_CAPTURE]        = "vbi-cap",
1515bc3cb74SMauro Carvalho Chehab 	[V4L2_BUF_TYPE_VBI_OUTPUT]         = "vbi-out",
1525bc3cb74SMauro Carvalho Chehab 	[V4L2_BUF_TYPE_SLICED_VBI_CAPTURE] = "sliced-vbi-cap",
1535bc3cb74SMauro Carvalho Chehab 	[V4L2_BUF_TYPE_SLICED_VBI_OUTPUT]  = "sliced-vbi-out",
1545bc3cb74SMauro Carvalho Chehab 	[V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY] = "vid-out-overlay",
1555bc3cb74SMauro Carvalho Chehab 	[V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE] = "vid-cap-mplane",
1565bc3cb74SMauro Carvalho Chehab 	[V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE] = "vid-out-mplane",
1576f3073b8SAntti Palosaari 	[V4L2_BUF_TYPE_SDR_CAPTURE]        = "sdr-cap",
1589effc72fSAntti Palosaari 	[V4L2_BUF_TYPE_SDR_OUTPUT]         = "sdr-out",
159fb9ffa6aSLaurent Pinchart 	[V4L2_BUF_TYPE_META_CAPTURE]       = "meta-cap",
1605bc3cb74SMauro Carvalho Chehab };
1615bc3cb74SMauro Carvalho Chehab EXPORT_SYMBOL(v4l2_type_names);
1625bc3cb74SMauro Carvalho Chehab 
1635bc3cb74SMauro Carvalho Chehab static const char *v4l2_memory_names[] = {
1645bc3cb74SMauro Carvalho Chehab 	[V4L2_MEMORY_MMAP]    = "mmap",
1655bc3cb74SMauro Carvalho Chehab 	[V4L2_MEMORY_USERPTR] = "userptr",
1665bc3cb74SMauro Carvalho Chehab 	[V4L2_MEMORY_OVERLAY] = "overlay",
167051c7788SSumit Semwal 	[V4L2_MEMORY_DMABUF] = "dmabuf",
1685bc3cb74SMauro Carvalho Chehab };
1695bc3cb74SMauro Carvalho Chehab 
170d9246240SHans Verkuil #define prt_names(a, arr) (((unsigned)(a)) < ARRAY_SIZE(arr) ? arr[a] : "unknown")
1715bc3cb74SMauro Carvalho Chehab 
1725bc3cb74SMauro Carvalho Chehab /* ------------------------------------------------------------------ */
1735bc3cb74SMauro Carvalho Chehab /* debug help functions                                               */
1745bc3cb74SMauro Carvalho Chehab 
1755bc3cb74SMauro Carvalho Chehab static void v4l_print_querycap(const void *arg, bool write_only)
1765bc3cb74SMauro Carvalho Chehab {
1775bc3cb74SMauro Carvalho Chehab 	const struct v4l2_capability *p = arg;
1785bc3cb74SMauro Carvalho Chehab 
1798720427cSMauro Carvalho Chehab 	pr_cont("driver=%.*s, card=%.*s, bus=%.*s, version=0x%08x, capabilities=0x%08x, device_caps=0x%08x\n",
18027d5a87cSHans Verkuil 		(int)sizeof(p->driver), p->driver,
18127d5a87cSHans Verkuil 		(int)sizeof(p->card), p->card,
18227d5a87cSHans Verkuil 		(int)sizeof(p->bus_info), p->bus_info,
1835bc3cb74SMauro Carvalho Chehab 		p->version, p->capabilities, p->device_caps);
1845bc3cb74SMauro Carvalho Chehab }
1855bc3cb74SMauro Carvalho Chehab 
1865bc3cb74SMauro Carvalho Chehab static void v4l_print_enuminput(const void *arg, bool write_only)
1875bc3cb74SMauro Carvalho Chehab {
1885bc3cb74SMauro Carvalho Chehab 	const struct v4l2_input *p = arg;
1895bc3cb74SMauro Carvalho Chehab 
1908720427cSMauro Carvalho Chehab 	pr_cont("index=%u, name=%.*s, type=%u, audioset=0x%x, tuner=%u, std=0x%08Lx, status=0x%x, capabilities=0x%x\n",
19127d5a87cSHans Verkuil 		p->index, (int)sizeof(p->name), p->name, p->type, p->audioset,
19227d5a87cSHans Verkuil 		p->tuner, (unsigned long long)p->std, p->status,
19327d5a87cSHans Verkuil 		p->capabilities);
1945bc3cb74SMauro Carvalho Chehab }
1955bc3cb74SMauro Carvalho Chehab 
1965bc3cb74SMauro Carvalho Chehab static void v4l_print_enumoutput(const void *arg, bool write_only)
1975bc3cb74SMauro Carvalho Chehab {
1985bc3cb74SMauro Carvalho Chehab 	const struct v4l2_output *p = arg;
1995bc3cb74SMauro Carvalho Chehab 
2008720427cSMauro Carvalho Chehab 	pr_cont("index=%u, name=%.*s, type=%u, audioset=0x%x, modulator=%u, std=0x%08Lx, capabilities=0x%x\n",
20127d5a87cSHans Verkuil 		p->index, (int)sizeof(p->name), p->name, p->type, p->audioset,
20227d5a87cSHans Verkuil 		p->modulator, (unsigned long long)p->std, p->capabilities);
2035bc3cb74SMauro Carvalho Chehab }
2045bc3cb74SMauro Carvalho Chehab 
2055bc3cb74SMauro Carvalho Chehab static void v4l_print_audio(const void *arg, bool write_only)
2065bc3cb74SMauro Carvalho Chehab {
2075bc3cb74SMauro Carvalho Chehab 	const struct v4l2_audio *p = arg;
2085bc3cb74SMauro Carvalho Chehab 
2095bc3cb74SMauro Carvalho Chehab 	if (write_only)
2105bc3cb74SMauro Carvalho Chehab 		pr_cont("index=%u, mode=0x%x\n", p->index, p->mode);
2115bc3cb74SMauro Carvalho Chehab 	else
21227d5a87cSHans Verkuil 		pr_cont("index=%u, name=%.*s, capability=0x%x, mode=0x%x\n",
21327d5a87cSHans Verkuil 			p->index, (int)sizeof(p->name), p->name,
21427d5a87cSHans Verkuil 			p->capability, p->mode);
2155bc3cb74SMauro Carvalho Chehab }
2165bc3cb74SMauro Carvalho Chehab 
2175bc3cb74SMauro Carvalho Chehab static void v4l_print_audioout(const void *arg, bool write_only)
2185bc3cb74SMauro Carvalho Chehab {
2195bc3cb74SMauro Carvalho Chehab 	const struct v4l2_audioout *p = arg;
2205bc3cb74SMauro Carvalho Chehab 
2215bc3cb74SMauro Carvalho Chehab 	if (write_only)
2225bc3cb74SMauro Carvalho Chehab 		pr_cont("index=%u\n", p->index);
2235bc3cb74SMauro Carvalho Chehab 	else
22427d5a87cSHans Verkuil 		pr_cont("index=%u, name=%.*s, capability=0x%x, mode=0x%x\n",
22527d5a87cSHans Verkuil 			p->index, (int)sizeof(p->name), p->name,
22627d5a87cSHans Verkuil 			p->capability, p->mode);
2275bc3cb74SMauro Carvalho Chehab }
2285bc3cb74SMauro Carvalho Chehab 
2295bc3cb74SMauro Carvalho Chehab static void v4l_print_fmtdesc(const void *arg, bool write_only)
2305bc3cb74SMauro Carvalho Chehab {
2315bc3cb74SMauro Carvalho Chehab 	const struct v4l2_fmtdesc *p = arg;
2325bc3cb74SMauro Carvalho Chehab 
23327d5a87cSHans Verkuil 	pr_cont("index=%u, type=%s, flags=0x%x, pixelformat=%c%c%c%c, description='%.*s'\n",
2345bc3cb74SMauro Carvalho Chehab 		p->index, prt_names(p->type, v4l2_type_names),
2355bc3cb74SMauro Carvalho Chehab 		p->flags, (p->pixelformat & 0xff),
2365bc3cb74SMauro Carvalho Chehab 		(p->pixelformat >>  8) & 0xff,
2375bc3cb74SMauro Carvalho Chehab 		(p->pixelformat >> 16) & 0xff,
2385bc3cb74SMauro Carvalho Chehab 		(p->pixelformat >> 24) & 0xff,
23927d5a87cSHans Verkuil 		(int)sizeof(p->description), p->description);
2405bc3cb74SMauro Carvalho Chehab }
2415bc3cb74SMauro Carvalho Chehab 
2425bc3cb74SMauro Carvalho Chehab static void v4l_print_format(const void *arg, bool write_only)
2435bc3cb74SMauro Carvalho Chehab {
2445bc3cb74SMauro Carvalho Chehab 	const struct v4l2_format *p = arg;
2455bc3cb74SMauro Carvalho Chehab 	const struct v4l2_pix_format *pix;
2465bc3cb74SMauro Carvalho Chehab 	const struct v4l2_pix_format_mplane *mp;
2475bc3cb74SMauro Carvalho Chehab 	const struct v4l2_vbi_format *vbi;
2485bc3cb74SMauro Carvalho Chehab 	const struct v4l2_sliced_vbi_format *sliced;
2495bc3cb74SMauro Carvalho Chehab 	const struct v4l2_window *win;
25087185c95SAntti Palosaari 	const struct v4l2_sdr_format *sdr;
251fb9ffa6aSLaurent Pinchart 	const struct v4l2_meta_format *meta;
2525bc3cb74SMauro Carvalho Chehab 	unsigned i;
2535bc3cb74SMauro Carvalho Chehab 
2545bc3cb74SMauro Carvalho Chehab 	pr_cont("type=%s", prt_names(p->type, v4l2_type_names));
2555bc3cb74SMauro Carvalho Chehab 	switch (p->type) {
2565bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
2575bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_OUTPUT:
2585bc3cb74SMauro Carvalho Chehab 		pix = &p->fmt.pix;
2598720427cSMauro Carvalho Chehab 		pr_cont(", width=%u, height=%u, pixelformat=%c%c%c%c, field=%s, bytesperline=%u, sizeimage=%u, colorspace=%d, flags=0x%x, ycbcr_enc=%u, quantization=%u, xfer_func=%u\n",
2605bc3cb74SMauro Carvalho Chehab 			pix->width, pix->height,
2615bc3cb74SMauro Carvalho Chehab 			(pix->pixelformat & 0xff),
2625bc3cb74SMauro Carvalho Chehab 			(pix->pixelformat >>  8) & 0xff,
2635bc3cb74SMauro Carvalho Chehab 			(pix->pixelformat >> 16) & 0xff,
2645bc3cb74SMauro Carvalho Chehab 			(pix->pixelformat >> 24) & 0xff,
2655bc3cb74SMauro Carvalho Chehab 			prt_names(pix->field, v4l2_field_names),
2665bc3cb74SMauro Carvalho Chehab 			pix->bytesperline, pix->sizeimage,
267736d96b5SHans Verkuil 			pix->colorspace, pix->flags, pix->ycbcr_enc,
26874fdcb2eSHans Verkuil 			pix->quantization, pix->xfer_func);
2695bc3cb74SMauro Carvalho Chehab 		break;
2705bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
2715bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
2725bc3cb74SMauro Carvalho Chehab 		mp = &p->fmt.pix_mp;
2738720427cSMauro Carvalho Chehab 		pr_cont(", width=%u, height=%u, format=%c%c%c%c, field=%s, colorspace=%d, num_planes=%u, flags=0x%x, ycbcr_enc=%u, quantization=%u, xfer_func=%u\n",
2745bc3cb74SMauro Carvalho Chehab 			mp->width, mp->height,
2755bc3cb74SMauro Carvalho Chehab 			(mp->pixelformat & 0xff),
2765bc3cb74SMauro Carvalho Chehab 			(mp->pixelformat >>  8) & 0xff,
2775bc3cb74SMauro Carvalho Chehab 			(mp->pixelformat >> 16) & 0xff,
2785bc3cb74SMauro Carvalho Chehab 			(mp->pixelformat >> 24) & 0xff,
2795bc3cb74SMauro Carvalho Chehab 			prt_names(mp->field, v4l2_field_names),
280736d96b5SHans Verkuil 			mp->colorspace, mp->num_planes, mp->flags,
28174fdcb2eSHans Verkuil 			mp->ycbcr_enc, mp->quantization, mp->xfer_func);
2825bc3cb74SMauro Carvalho Chehab 		for (i = 0; i < mp->num_planes; i++)
2835bc3cb74SMauro Carvalho Chehab 			printk(KERN_DEBUG "plane %u: bytesperline=%u sizeimage=%u\n", i,
2845bc3cb74SMauro Carvalho Chehab 					mp->plane_fmt[i].bytesperline,
2855bc3cb74SMauro Carvalho Chehab 					mp->plane_fmt[i].sizeimage);
2865bc3cb74SMauro Carvalho Chehab 		break;
2875bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_OVERLAY:
2885bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
2895bc3cb74SMauro Carvalho Chehab 		win = &p->fmt.win;
290560dde24SHans Verkuil 		/* Note: we can't print the clip list here since the clips
291560dde24SHans Verkuil 		 * pointer is a userspace pointer, not a kernelspace
292560dde24SHans Verkuil 		 * pointer. */
293560dde24SHans Verkuil 		pr_cont(", wxh=%dx%d, x,y=%d,%d, field=%s, chromakey=0x%08x, clipcount=%u, clips=%p, bitmap=%p, global_alpha=0x%02x\n",
294560dde24SHans Verkuil 			win->w.width, win->w.height, win->w.left, win->w.top,
2955bc3cb74SMauro Carvalho Chehab 			prt_names(win->field, v4l2_field_names),
296560dde24SHans Verkuil 			win->chromakey, win->clipcount, win->clips,
297560dde24SHans Verkuil 			win->bitmap, win->global_alpha);
2985bc3cb74SMauro Carvalho Chehab 		break;
2995bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VBI_CAPTURE:
3005bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VBI_OUTPUT:
3015bc3cb74SMauro Carvalho Chehab 		vbi = &p->fmt.vbi;
3028720427cSMauro Carvalho Chehab 		pr_cont(", sampling_rate=%u, offset=%u, samples_per_line=%u, sample_format=%c%c%c%c, start=%u,%u, count=%u,%u\n",
3035bc3cb74SMauro Carvalho Chehab 			vbi->sampling_rate, vbi->offset,
3045bc3cb74SMauro Carvalho Chehab 			vbi->samples_per_line,
3055bc3cb74SMauro Carvalho Chehab 			(vbi->sample_format & 0xff),
3065bc3cb74SMauro Carvalho Chehab 			(vbi->sample_format >>  8) & 0xff,
3075bc3cb74SMauro Carvalho Chehab 			(vbi->sample_format >> 16) & 0xff,
3085bc3cb74SMauro Carvalho Chehab 			(vbi->sample_format >> 24) & 0xff,
3095bc3cb74SMauro Carvalho Chehab 			vbi->start[0], vbi->start[1],
3105bc3cb74SMauro Carvalho Chehab 			vbi->count[0], vbi->count[1]);
3115bc3cb74SMauro Carvalho Chehab 		break;
3125bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
3135bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
3145bc3cb74SMauro Carvalho Chehab 		sliced = &p->fmt.sliced;
3155bc3cb74SMauro Carvalho Chehab 		pr_cont(", service_set=0x%08x, io_size=%d\n",
3165bc3cb74SMauro Carvalho Chehab 				sliced->service_set, sliced->io_size);
3175bc3cb74SMauro Carvalho Chehab 		for (i = 0; i < 24; i++)
3185bc3cb74SMauro Carvalho Chehab 			printk(KERN_DEBUG "line[%02u]=0x%04x, 0x%04x\n", i,
3195bc3cb74SMauro Carvalho Chehab 				sliced->service_lines[0][i],
3205bc3cb74SMauro Carvalho Chehab 				sliced->service_lines[1][i]);
3215bc3cb74SMauro Carvalho Chehab 		break;
322582c52cbSAntti Palosaari 	case V4L2_BUF_TYPE_SDR_CAPTURE:
3239effc72fSAntti Palosaari 	case V4L2_BUF_TYPE_SDR_OUTPUT:
324582c52cbSAntti Palosaari 		sdr = &p->fmt.sdr;
325582c52cbSAntti Palosaari 		pr_cont(", pixelformat=%c%c%c%c\n",
326582c52cbSAntti Palosaari 			(sdr->pixelformat >>  0) & 0xff,
327582c52cbSAntti Palosaari 			(sdr->pixelformat >>  8) & 0xff,
328582c52cbSAntti Palosaari 			(sdr->pixelformat >> 16) & 0xff,
329582c52cbSAntti Palosaari 			(sdr->pixelformat >> 24) & 0xff);
330582c52cbSAntti Palosaari 		break;
331fb9ffa6aSLaurent Pinchart 	case V4L2_BUF_TYPE_META_CAPTURE:
332fb9ffa6aSLaurent Pinchart 		meta = &p->fmt.meta;
333fb9ffa6aSLaurent Pinchart 		pr_cont(", dataformat=%c%c%c%c, buffersize=%u\n",
334fb9ffa6aSLaurent Pinchart 			(meta->dataformat >>  0) & 0xff,
335fb9ffa6aSLaurent Pinchart 			(meta->dataformat >>  8) & 0xff,
336fb9ffa6aSLaurent Pinchart 			(meta->dataformat >> 16) & 0xff,
337fb9ffa6aSLaurent Pinchart 			(meta->dataformat >> 24) & 0xff,
338fb9ffa6aSLaurent Pinchart 			meta->buffersize);
339fb9ffa6aSLaurent Pinchart 		break;
3405bc3cb74SMauro Carvalho Chehab 	}
3415bc3cb74SMauro Carvalho Chehab }
3425bc3cb74SMauro Carvalho Chehab 
3435bc3cb74SMauro Carvalho Chehab static void v4l_print_framebuffer(const void *arg, bool write_only)
3445bc3cb74SMauro Carvalho Chehab {
3455bc3cb74SMauro Carvalho Chehab 	const struct v4l2_framebuffer *p = arg;
3465bc3cb74SMauro Carvalho Chehab 
3478720427cSMauro Carvalho Chehab 	pr_cont("capability=0x%x, flags=0x%x, base=0x%p, width=%u, height=%u, pixelformat=%c%c%c%c, bytesperline=%u, sizeimage=%u, colorspace=%d\n",
3485bc3cb74SMauro Carvalho Chehab 			p->capability, p->flags, p->base,
3495bc3cb74SMauro Carvalho Chehab 			p->fmt.width, p->fmt.height,
3505bc3cb74SMauro Carvalho Chehab 			(p->fmt.pixelformat & 0xff),
3515bc3cb74SMauro Carvalho Chehab 			(p->fmt.pixelformat >>  8) & 0xff,
3525bc3cb74SMauro Carvalho Chehab 			(p->fmt.pixelformat >> 16) & 0xff,
3535bc3cb74SMauro Carvalho Chehab 			(p->fmt.pixelformat >> 24) & 0xff,
3545bc3cb74SMauro Carvalho Chehab 			p->fmt.bytesperline, p->fmt.sizeimage,
3555bc3cb74SMauro Carvalho Chehab 			p->fmt.colorspace);
3565bc3cb74SMauro Carvalho Chehab }
3575bc3cb74SMauro Carvalho Chehab 
3585bc3cb74SMauro Carvalho Chehab static void v4l_print_buftype(const void *arg, bool write_only)
3595bc3cb74SMauro Carvalho Chehab {
3605bc3cb74SMauro Carvalho Chehab 	pr_cont("type=%s\n", prt_names(*(u32 *)arg, v4l2_type_names));
3615bc3cb74SMauro Carvalho Chehab }
3625bc3cb74SMauro Carvalho Chehab 
3635bc3cb74SMauro Carvalho Chehab static void v4l_print_modulator(const void *arg, bool write_only)
3645bc3cb74SMauro Carvalho Chehab {
3655bc3cb74SMauro Carvalho Chehab 	const struct v4l2_modulator *p = arg;
3665bc3cb74SMauro Carvalho Chehab 
3675bc3cb74SMauro Carvalho Chehab 	if (write_only)
368560dde24SHans Verkuil 		pr_cont("index=%u, txsubchans=0x%x\n", p->index, p->txsubchans);
3695bc3cb74SMauro Carvalho Chehab 	else
3708720427cSMauro Carvalho Chehab 		pr_cont("index=%u, name=%.*s, capability=0x%x, rangelow=%u, rangehigh=%u, txsubchans=0x%x\n",
37127d5a87cSHans Verkuil 			p->index, (int)sizeof(p->name), p->name, p->capability,
3725bc3cb74SMauro Carvalho Chehab 			p->rangelow, p->rangehigh, p->txsubchans);
3735bc3cb74SMauro Carvalho Chehab }
3745bc3cb74SMauro Carvalho Chehab 
3755bc3cb74SMauro Carvalho Chehab static void v4l_print_tuner(const void *arg, bool write_only)
3765bc3cb74SMauro Carvalho Chehab {
3775bc3cb74SMauro Carvalho Chehab 	const struct v4l2_tuner *p = arg;
3785bc3cb74SMauro Carvalho Chehab 
3795bc3cb74SMauro Carvalho Chehab 	if (write_only)
3805bc3cb74SMauro Carvalho Chehab 		pr_cont("index=%u, audmode=%u\n", p->index, p->audmode);
3815bc3cb74SMauro Carvalho Chehab 	else
3828720427cSMauro Carvalho Chehab 		pr_cont("index=%u, name=%.*s, type=%u, capability=0x%x, rangelow=%u, rangehigh=%u, signal=%u, afc=%d, rxsubchans=0x%x, audmode=%u\n",
38327d5a87cSHans Verkuil 			p->index, (int)sizeof(p->name), p->name, p->type,
3845bc3cb74SMauro Carvalho Chehab 			p->capability, p->rangelow,
3855bc3cb74SMauro Carvalho Chehab 			p->rangehigh, p->signal, p->afc,
3865bc3cb74SMauro Carvalho Chehab 			p->rxsubchans, p->audmode);
3875bc3cb74SMauro Carvalho Chehab }
3885bc3cb74SMauro Carvalho Chehab 
3895bc3cb74SMauro Carvalho Chehab static void v4l_print_frequency(const void *arg, bool write_only)
3905bc3cb74SMauro Carvalho Chehab {
3915bc3cb74SMauro Carvalho Chehab 	const struct v4l2_frequency *p = arg;
3925bc3cb74SMauro Carvalho Chehab 
3935bc3cb74SMauro Carvalho Chehab 	pr_cont("tuner=%u, type=%u, frequency=%u\n",
3945bc3cb74SMauro Carvalho Chehab 				p->tuner, p->type, p->frequency);
3955bc3cb74SMauro Carvalho Chehab }
3965bc3cb74SMauro Carvalho Chehab 
3975bc3cb74SMauro Carvalho Chehab static void v4l_print_standard(const void *arg, bool write_only)
3985bc3cb74SMauro Carvalho Chehab {
3995bc3cb74SMauro Carvalho Chehab 	const struct v4l2_standard *p = arg;
4005bc3cb74SMauro Carvalho Chehab 
4018720427cSMauro Carvalho Chehab 	pr_cont("index=%u, id=0x%Lx, name=%.*s, fps=%u/%u, framelines=%u\n",
4028720427cSMauro Carvalho Chehab 		p->index,
40327d5a87cSHans Verkuil 		(unsigned long long)p->id, (int)sizeof(p->name), p->name,
4045bc3cb74SMauro Carvalho Chehab 		p->frameperiod.numerator,
4055bc3cb74SMauro Carvalho Chehab 		p->frameperiod.denominator,
4065bc3cb74SMauro Carvalho Chehab 		p->framelines);
4075bc3cb74SMauro Carvalho Chehab }
4085bc3cb74SMauro Carvalho Chehab 
4095bc3cb74SMauro Carvalho Chehab static void v4l_print_std(const void *arg, bool write_only)
4105bc3cb74SMauro Carvalho Chehab {
4115bc3cb74SMauro Carvalho Chehab 	pr_cont("std=0x%08Lx\n", *(const long long unsigned *)arg);
4125bc3cb74SMauro Carvalho Chehab }
4135bc3cb74SMauro Carvalho Chehab 
4145bc3cb74SMauro Carvalho Chehab static void v4l_print_hw_freq_seek(const void *arg, bool write_only)
4155bc3cb74SMauro Carvalho Chehab {
4165bc3cb74SMauro Carvalho Chehab 	const struct v4l2_hw_freq_seek *p = arg;
4175bc3cb74SMauro Carvalho Chehab 
4188720427cSMauro Carvalho Chehab 	pr_cont("tuner=%u, type=%u, seek_upward=%u, wrap_around=%u, spacing=%u, rangelow=%u, rangehigh=%u\n",
41979e8c7beSMauro Carvalho Chehab 		p->tuner, p->type, p->seek_upward, p->wrap_around, p->spacing,
42079e8c7beSMauro Carvalho Chehab 		p->rangelow, p->rangehigh);
4215bc3cb74SMauro Carvalho Chehab }
4225bc3cb74SMauro Carvalho Chehab 
4235bc3cb74SMauro Carvalho Chehab static void v4l_print_requestbuffers(const void *arg, bool write_only)
4245bc3cb74SMauro Carvalho Chehab {
4255bc3cb74SMauro Carvalho Chehab 	const struct v4l2_requestbuffers *p = arg;
4265bc3cb74SMauro Carvalho Chehab 
4275bc3cb74SMauro Carvalho Chehab 	pr_cont("count=%d, type=%s, memory=%s\n",
4285bc3cb74SMauro Carvalho Chehab 		p->count,
4295bc3cb74SMauro Carvalho Chehab 		prt_names(p->type, v4l2_type_names),
4305bc3cb74SMauro Carvalho Chehab 		prt_names(p->memory, v4l2_memory_names));
4315bc3cb74SMauro Carvalho Chehab }
4325bc3cb74SMauro Carvalho Chehab 
4335bc3cb74SMauro Carvalho Chehab static void v4l_print_buffer(const void *arg, bool write_only)
4345bc3cb74SMauro Carvalho Chehab {
4355bc3cb74SMauro Carvalho Chehab 	const struct v4l2_buffer *p = arg;
4365bc3cb74SMauro Carvalho Chehab 	const struct v4l2_timecode *tc = &p->timecode;
4375bc3cb74SMauro Carvalho Chehab 	const struct v4l2_plane *plane;
4385bc3cb74SMauro Carvalho Chehab 	int i;
4395bc3cb74SMauro Carvalho Chehab 
4408720427cSMauro Carvalho Chehab 	pr_cont("%02ld:%02d:%02d.%08ld index=%d, type=%s, flags=0x%08x, field=%s, sequence=%d, memory=%s",
4415bc3cb74SMauro Carvalho Chehab 			p->timestamp.tv_sec / 3600,
4425bc3cb74SMauro Carvalho Chehab 			(int)(p->timestamp.tv_sec / 60) % 60,
4435bc3cb74SMauro Carvalho Chehab 			(int)(p->timestamp.tv_sec % 60),
4445bc3cb74SMauro Carvalho Chehab 			(long)p->timestamp.tv_usec,
4455bc3cb74SMauro Carvalho Chehab 			p->index,
4465bc3cb74SMauro Carvalho Chehab 			prt_names(p->type, v4l2_type_names),
4475bc3cb74SMauro Carvalho Chehab 			p->flags, prt_names(p->field, v4l2_field_names),
4485bc3cb74SMauro Carvalho Chehab 			p->sequence, prt_names(p->memory, v4l2_memory_names));
4495bc3cb74SMauro Carvalho Chehab 
4505bc3cb74SMauro Carvalho Chehab 	if (V4L2_TYPE_IS_MULTIPLANAR(p->type) && p->m.planes) {
4515bc3cb74SMauro Carvalho Chehab 		pr_cont("\n");
4525bc3cb74SMauro Carvalho Chehab 		for (i = 0; i < p->length; ++i) {
4535bc3cb74SMauro Carvalho Chehab 			plane = &p->m.planes[i];
4545bc3cb74SMauro Carvalho Chehab 			printk(KERN_DEBUG
4558720427cSMauro Carvalho Chehab 				"plane %d: bytesused=%d, data_offset=0x%08x, offset/userptr=0x%lx, length=%d\n",
4565bc3cb74SMauro Carvalho Chehab 				i, plane->bytesused, plane->data_offset,
4575bc3cb74SMauro Carvalho Chehab 				plane->m.userptr, plane->length);
4585bc3cb74SMauro Carvalho Chehab 		}
4595bc3cb74SMauro Carvalho Chehab 	} else {
460560dde24SHans Verkuil 		pr_cont(", bytesused=%d, offset/userptr=0x%lx, length=%d\n",
4615bc3cb74SMauro Carvalho Chehab 			p->bytesused, p->m.userptr, p->length);
4625bc3cb74SMauro Carvalho Chehab 	}
4635bc3cb74SMauro Carvalho Chehab 
4648720427cSMauro Carvalho Chehab 	printk(KERN_DEBUG "timecode=%02d:%02d:%02d type=%d, flags=0x%08x, frames=%d, userbits=0x%08x\n",
4655bc3cb74SMauro Carvalho Chehab 			tc->hours, tc->minutes, tc->seconds,
4665bc3cb74SMauro Carvalho Chehab 			tc->type, tc->flags, tc->frames, *(__u32 *)tc->userbits);
4675bc3cb74SMauro Carvalho Chehab }
4685bc3cb74SMauro Carvalho Chehab 
469b799d09aSTomasz Stanislawski static void v4l_print_exportbuffer(const void *arg, bool write_only)
470b799d09aSTomasz Stanislawski {
471b799d09aSTomasz Stanislawski 	const struct v4l2_exportbuffer *p = arg;
472b799d09aSTomasz Stanislawski 
473b799d09aSTomasz Stanislawski 	pr_cont("fd=%d, type=%s, index=%u, plane=%u, flags=0x%08x\n",
474b799d09aSTomasz Stanislawski 		p->fd, prt_names(p->type, v4l2_type_names),
475b799d09aSTomasz Stanislawski 		p->index, p->plane, p->flags);
476b799d09aSTomasz Stanislawski }
477b799d09aSTomasz Stanislawski 
4785bc3cb74SMauro Carvalho Chehab static void v4l_print_create_buffers(const void *arg, bool write_only)
4795bc3cb74SMauro Carvalho Chehab {
4805bc3cb74SMauro Carvalho Chehab 	const struct v4l2_create_buffers *p = arg;
4815bc3cb74SMauro Carvalho Chehab 
4825bc3cb74SMauro Carvalho Chehab 	pr_cont("index=%d, count=%d, memory=%s, ",
4835bc3cb74SMauro Carvalho Chehab 			p->index, p->count,
4845bc3cb74SMauro Carvalho Chehab 			prt_names(p->memory, v4l2_memory_names));
4855bc3cb74SMauro Carvalho Chehab 	v4l_print_format(&p->format, write_only);
4865bc3cb74SMauro Carvalho Chehab }
4875bc3cb74SMauro Carvalho Chehab 
4885bc3cb74SMauro Carvalho Chehab static void v4l_print_streamparm(const void *arg, bool write_only)
4895bc3cb74SMauro Carvalho Chehab {
4905bc3cb74SMauro Carvalho Chehab 	const struct v4l2_streamparm *p = arg;
4915bc3cb74SMauro Carvalho Chehab 
4925bc3cb74SMauro Carvalho Chehab 	pr_cont("type=%s", prt_names(p->type, v4l2_type_names));
4935bc3cb74SMauro Carvalho Chehab 
4945bc3cb74SMauro Carvalho Chehab 	if (p->type == V4L2_BUF_TYPE_VIDEO_CAPTURE ||
4955bc3cb74SMauro Carvalho Chehab 	    p->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
4965bc3cb74SMauro Carvalho Chehab 		const struct v4l2_captureparm *c = &p->parm.capture;
4975bc3cb74SMauro Carvalho Chehab 
4988720427cSMauro Carvalho Chehab 		pr_cont(", capability=0x%x, capturemode=0x%x, timeperframe=%d/%d, extendedmode=%d, readbuffers=%d\n",
4995bc3cb74SMauro Carvalho Chehab 			c->capability, c->capturemode,
5005bc3cb74SMauro Carvalho Chehab 			c->timeperframe.numerator, c->timeperframe.denominator,
5015bc3cb74SMauro Carvalho Chehab 			c->extendedmode, c->readbuffers);
5025bc3cb74SMauro Carvalho Chehab 	} else if (p->type == V4L2_BUF_TYPE_VIDEO_OUTPUT ||
5035bc3cb74SMauro Carvalho Chehab 		   p->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
5045bc3cb74SMauro Carvalho Chehab 		const struct v4l2_outputparm *c = &p->parm.output;
5055bc3cb74SMauro Carvalho Chehab 
5068720427cSMauro Carvalho Chehab 		pr_cont(", capability=0x%x, outputmode=0x%x, timeperframe=%d/%d, extendedmode=%d, writebuffers=%d\n",
5075bc3cb74SMauro Carvalho Chehab 			c->capability, c->outputmode,
5085bc3cb74SMauro Carvalho Chehab 			c->timeperframe.numerator, c->timeperframe.denominator,
5095bc3cb74SMauro Carvalho Chehab 			c->extendedmode, c->writebuffers);
510560dde24SHans Verkuil 	} else {
511560dde24SHans Verkuil 		pr_cont("\n");
5125bc3cb74SMauro Carvalho Chehab 	}
5135bc3cb74SMauro Carvalho Chehab }
5145bc3cb74SMauro Carvalho Chehab 
5155bc3cb74SMauro Carvalho Chehab static void v4l_print_queryctrl(const void *arg, bool write_only)
5165bc3cb74SMauro Carvalho Chehab {
5175bc3cb74SMauro Carvalho Chehab 	const struct v4l2_queryctrl *p = arg;
5185bc3cb74SMauro Carvalho Chehab 
5198720427cSMauro Carvalho Chehab 	pr_cont("id=0x%x, type=%d, name=%.*s, min/max=%d/%d, step=%d, default=%d, flags=0x%08x\n",
52027d5a87cSHans Verkuil 			p->id, p->type, (int)sizeof(p->name), p->name,
5215bc3cb74SMauro Carvalho Chehab 			p->minimum, p->maximum,
5225bc3cb74SMauro Carvalho Chehab 			p->step, p->default_value, p->flags);
5235bc3cb74SMauro Carvalho Chehab }
5245bc3cb74SMauro Carvalho Chehab 
525e6bee368SHans Verkuil static void v4l_print_query_ext_ctrl(const void *arg, bool write_only)
526e6bee368SHans Verkuil {
527e6bee368SHans Verkuil 	const struct v4l2_query_ext_ctrl *p = arg;
528e6bee368SHans Verkuil 
5298720427cSMauro Carvalho Chehab 	pr_cont("id=0x%x, type=%d, name=%.*s, min/max=%lld/%lld, step=%lld, default=%lld, flags=0x%08x, elem_size=%u, elems=%u, nr_of_dims=%u, dims=%u,%u,%u,%u\n",
530e6bee368SHans Verkuil 			p->id, p->type, (int)sizeof(p->name), p->name,
531e6bee368SHans Verkuil 			p->minimum, p->maximum,
532e6bee368SHans Verkuil 			p->step, p->default_value, p->flags,
533e6bee368SHans Verkuil 			p->elem_size, p->elems, p->nr_of_dims,
5340176077aSHans Verkuil 			p->dims[0], p->dims[1], p->dims[2], p->dims[3]);
535e6bee368SHans Verkuil }
536e6bee368SHans Verkuil 
5375bc3cb74SMauro Carvalho Chehab static void v4l_print_querymenu(const void *arg, bool write_only)
5385bc3cb74SMauro Carvalho Chehab {
5395bc3cb74SMauro Carvalho Chehab 	const struct v4l2_querymenu *p = arg;
5405bc3cb74SMauro Carvalho Chehab 
5415bc3cb74SMauro Carvalho Chehab 	pr_cont("id=0x%x, index=%d\n", p->id, p->index);
5425bc3cb74SMauro Carvalho Chehab }
5435bc3cb74SMauro Carvalho Chehab 
5445bc3cb74SMauro Carvalho Chehab static void v4l_print_control(const void *arg, bool write_only)
5455bc3cb74SMauro Carvalho Chehab {
5465bc3cb74SMauro Carvalho Chehab 	const struct v4l2_control *p = arg;
5475bc3cb74SMauro Carvalho Chehab 
5485bc3cb74SMauro Carvalho Chehab 	pr_cont("id=0x%x, value=%d\n", p->id, p->value);
5495bc3cb74SMauro Carvalho Chehab }
5505bc3cb74SMauro Carvalho Chehab 
5515bc3cb74SMauro Carvalho Chehab static void v4l_print_ext_controls(const void *arg, bool write_only)
5525bc3cb74SMauro Carvalho Chehab {
5535bc3cb74SMauro Carvalho Chehab 	const struct v4l2_ext_controls *p = arg;
5545bc3cb74SMauro Carvalho Chehab 	int i;
5555bc3cb74SMauro Carvalho Chehab 
5560f8017beSRicardo Ribalda 	pr_cont("which=0x%x, count=%d, error_idx=%d",
5570f8017beSRicardo Ribalda 			p->which, p->count, p->error_idx);
5585bc3cb74SMauro Carvalho Chehab 	for (i = 0; i < p->count; i++) {
559017ab36aSHans Verkuil 		if (!p->controls[i].size)
5605bc3cb74SMauro Carvalho Chehab 			pr_cont(", id/val=0x%x/0x%x",
5615bc3cb74SMauro Carvalho Chehab 				p->controls[i].id, p->controls[i].value);
5625bc3cb74SMauro Carvalho Chehab 		else
5635bc3cb74SMauro Carvalho Chehab 			pr_cont(", id/size=0x%x/%u",
5645bc3cb74SMauro Carvalho Chehab 				p->controls[i].id, p->controls[i].size);
5655bc3cb74SMauro Carvalho Chehab 	}
5665bc3cb74SMauro Carvalho Chehab 	pr_cont("\n");
5675bc3cb74SMauro Carvalho Chehab }
5685bc3cb74SMauro Carvalho Chehab 
5695bc3cb74SMauro Carvalho Chehab static void v4l_print_cropcap(const void *arg, bool write_only)
5705bc3cb74SMauro Carvalho Chehab {
5715bc3cb74SMauro Carvalho Chehab 	const struct v4l2_cropcap *p = arg;
5725bc3cb74SMauro Carvalho Chehab 
5738720427cSMauro Carvalho Chehab 	pr_cont("type=%s, bounds wxh=%dx%d, x,y=%d,%d, defrect wxh=%dx%d, x,y=%d,%d, pixelaspect %d/%d\n",
5745bc3cb74SMauro Carvalho Chehab 		prt_names(p->type, v4l2_type_names),
5755bc3cb74SMauro Carvalho Chehab 		p->bounds.width, p->bounds.height,
5765bc3cb74SMauro Carvalho Chehab 		p->bounds.left, p->bounds.top,
5775bc3cb74SMauro Carvalho Chehab 		p->defrect.width, p->defrect.height,
5785bc3cb74SMauro Carvalho Chehab 		p->defrect.left, p->defrect.top,
5795bc3cb74SMauro Carvalho Chehab 		p->pixelaspect.numerator, p->pixelaspect.denominator);
5805bc3cb74SMauro Carvalho Chehab }
5815bc3cb74SMauro Carvalho Chehab 
5825bc3cb74SMauro Carvalho Chehab static void v4l_print_crop(const void *arg, bool write_only)
5835bc3cb74SMauro Carvalho Chehab {
5845bc3cb74SMauro Carvalho Chehab 	const struct v4l2_crop *p = arg;
5855bc3cb74SMauro Carvalho Chehab 
5865bc3cb74SMauro Carvalho Chehab 	pr_cont("type=%s, wxh=%dx%d, x,y=%d,%d\n",
5875bc3cb74SMauro Carvalho Chehab 		prt_names(p->type, v4l2_type_names),
5885bc3cb74SMauro Carvalho Chehab 		p->c.width, p->c.height,
5895bc3cb74SMauro Carvalho Chehab 		p->c.left, p->c.top);
5905bc3cb74SMauro Carvalho Chehab }
5915bc3cb74SMauro Carvalho Chehab 
5925bc3cb74SMauro Carvalho Chehab static void v4l_print_selection(const void *arg, bool write_only)
5935bc3cb74SMauro Carvalho Chehab {
5945bc3cb74SMauro Carvalho Chehab 	const struct v4l2_selection *p = arg;
5955bc3cb74SMauro Carvalho Chehab 
5965bc3cb74SMauro Carvalho Chehab 	pr_cont("type=%s, target=%d, flags=0x%x, wxh=%dx%d, x,y=%d,%d\n",
5975bc3cb74SMauro Carvalho Chehab 		prt_names(p->type, v4l2_type_names),
5985bc3cb74SMauro Carvalho Chehab 		p->target, p->flags,
5995bc3cb74SMauro Carvalho Chehab 		p->r.width, p->r.height, p->r.left, p->r.top);
6005bc3cb74SMauro Carvalho Chehab }
6015bc3cb74SMauro Carvalho Chehab 
6025bc3cb74SMauro Carvalho Chehab static void v4l_print_jpegcompression(const void *arg, bool write_only)
6035bc3cb74SMauro Carvalho Chehab {
6045bc3cb74SMauro Carvalho Chehab 	const struct v4l2_jpegcompression *p = arg;
6055bc3cb74SMauro Carvalho Chehab 
6068720427cSMauro Carvalho Chehab 	pr_cont("quality=%d, APPn=%d, APP_len=%d, COM_len=%d, jpeg_markers=0x%x\n",
6075bc3cb74SMauro Carvalho Chehab 		p->quality, p->APPn, p->APP_len,
6085bc3cb74SMauro Carvalho Chehab 		p->COM_len, p->jpeg_markers);
6095bc3cb74SMauro Carvalho Chehab }
6105bc3cb74SMauro Carvalho Chehab 
6115bc3cb74SMauro Carvalho Chehab static void v4l_print_enc_idx(const void *arg, bool write_only)
6125bc3cb74SMauro Carvalho Chehab {
6135bc3cb74SMauro Carvalho Chehab 	const struct v4l2_enc_idx *p = arg;
6145bc3cb74SMauro Carvalho Chehab 
6155bc3cb74SMauro Carvalho Chehab 	pr_cont("entries=%d, entries_cap=%d\n",
6165bc3cb74SMauro Carvalho Chehab 			p->entries, p->entries_cap);
6175bc3cb74SMauro Carvalho Chehab }
6185bc3cb74SMauro Carvalho Chehab 
6195bc3cb74SMauro Carvalho Chehab static void v4l_print_encoder_cmd(const void *arg, bool write_only)
6205bc3cb74SMauro Carvalho Chehab {
6215bc3cb74SMauro Carvalho Chehab 	const struct v4l2_encoder_cmd *p = arg;
6225bc3cb74SMauro Carvalho Chehab 
6235bc3cb74SMauro Carvalho Chehab 	pr_cont("cmd=%d, flags=0x%x\n",
6245bc3cb74SMauro Carvalho Chehab 			p->cmd, p->flags);
6255bc3cb74SMauro Carvalho Chehab }
6265bc3cb74SMauro Carvalho Chehab 
6275bc3cb74SMauro Carvalho Chehab static void v4l_print_decoder_cmd(const void *arg, bool write_only)
6285bc3cb74SMauro Carvalho Chehab {
6295bc3cb74SMauro Carvalho Chehab 	const struct v4l2_decoder_cmd *p = arg;
6305bc3cb74SMauro Carvalho Chehab 
6315bc3cb74SMauro Carvalho Chehab 	pr_cont("cmd=%d, flags=0x%x\n", p->cmd, p->flags);
6325bc3cb74SMauro Carvalho Chehab 
6335bc3cb74SMauro Carvalho Chehab 	if (p->cmd == V4L2_DEC_CMD_START)
6345bc3cb74SMauro Carvalho Chehab 		pr_info("speed=%d, format=%u\n",
6355bc3cb74SMauro Carvalho Chehab 				p->start.speed, p->start.format);
6365bc3cb74SMauro Carvalho Chehab 	else if (p->cmd == V4L2_DEC_CMD_STOP)
6375bc3cb74SMauro Carvalho Chehab 		pr_info("pts=%llu\n", p->stop.pts);
6385bc3cb74SMauro Carvalho Chehab }
6395bc3cb74SMauro Carvalho Chehab 
64096b03d2aSHans Verkuil static void v4l_print_dbg_chip_info(const void *arg, bool write_only)
64179b0c640SHans Verkuil {
64296b03d2aSHans Verkuil 	const struct v4l2_dbg_chip_info *p = arg;
64379b0c640SHans Verkuil 
64479b0c640SHans Verkuil 	pr_cont("type=%u, ", p->match.type);
6453eef2510SHans Verkuil 	if (p->match.type == V4L2_CHIP_MATCH_I2C_DRIVER)
64679b0c640SHans Verkuil 		pr_cont("name=%.*s, ",
64779b0c640SHans Verkuil 				(int)sizeof(p->match.name), p->match.name);
64879b0c640SHans Verkuil 	else
64979b0c640SHans Verkuil 		pr_cont("addr=%u, ", p->match.addr);
65079b0c640SHans Verkuil 	pr_cont("name=%.*s\n", (int)sizeof(p->name), p->name);
65179b0c640SHans Verkuil }
65279b0c640SHans Verkuil 
6535bc3cb74SMauro Carvalho Chehab static void v4l_print_dbg_register(const void *arg, bool write_only)
6545bc3cb74SMauro Carvalho Chehab {
6555bc3cb74SMauro Carvalho Chehab 	const struct v4l2_dbg_register *p = arg;
6565bc3cb74SMauro Carvalho Chehab 
6575bc3cb74SMauro Carvalho Chehab 	pr_cont("type=%u, ", p->match.type);
6583eef2510SHans Verkuil 	if (p->match.type == V4L2_CHIP_MATCH_I2C_DRIVER)
65927d5a87cSHans Verkuil 		pr_cont("name=%.*s, ",
66027d5a87cSHans Verkuil 				(int)sizeof(p->match.name), p->match.name);
6615bc3cb74SMauro Carvalho Chehab 	else
6625bc3cb74SMauro Carvalho Chehab 		pr_cont("addr=%u, ", p->match.addr);
6635bc3cb74SMauro Carvalho Chehab 	pr_cont("reg=0x%llx, val=0x%llx\n",
6645bc3cb74SMauro Carvalho Chehab 			p->reg, p->val);
6655bc3cb74SMauro Carvalho Chehab }
6665bc3cb74SMauro Carvalho Chehab 
6675bc3cb74SMauro Carvalho Chehab static void v4l_print_dv_timings(const void *arg, bool write_only)
6685bc3cb74SMauro Carvalho Chehab {
6695bc3cb74SMauro Carvalho Chehab 	const struct v4l2_dv_timings *p = arg;
6705bc3cb74SMauro Carvalho Chehab 
6715bc3cb74SMauro Carvalho Chehab 	switch (p->type) {
6725bc3cb74SMauro Carvalho Chehab 	case V4L2_DV_BT_656_1120:
6738720427cSMauro Carvalho Chehab 		pr_cont("type=bt-656/1120, interlaced=%u, pixelclock=%llu, width=%u, height=%u, polarities=0x%x, hfrontporch=%u, hsync=%u, hbackporch=%u, vfrontporch=%u, vsync=%u, vbackporch=%u, il_vfrontporch=%u, il_vsync=%u, il_vbackporch=%u, standards=0x%x, flags=0x%x\n",
6745bc3cb74SMauro Carvalho Chehab 				p->bt.interlaced, p->bt.pixelclock,
6755bc3cb74SMauro Carvalho Chehab 				p->bt.width, p->bt.height,
6765bc3cb74SMauro Carvalho Chehab 				p->bt.polarities, p->bt.hfrontporch,
6775bc3cb74SMauro Carvalho Chehab 				p->bt.hsync, p->bt.hbackporch,
6785bc3cb74SMauro Carvalho Chehab 				p->bt.vfrontporch, p->bt.vsync,
6795bc3cb74SMauro Carvalho Chehab 				p->bt.vbackporch, p->bt.il_vfrontporch,
6805bc3cb74SMauro Carvalho Chehab 				p->bt.il_vsync, p->bt.il_vbackporch,
6815bc3cb74SMauro Carvalho Chehab 				p->bt.standards, p->bt.flags);
6825bc3cb74SMauro Carvalho Chehab 		break;
6835bc3cb74SMauro Carvalho Chehab 	default:
6845bc3cb74SMauro Carvalho Chehab 		pr_cont("type=%d\n", p->type);
6855bc3cb74SMauro Carvalho Chehab 		break;
6865bc3cb74SMauro Carvalho Chehab 	}
6875bc3cb74SMauro Carvalho Chehab }
6885bc3cb74SMauro Carvalho Chehab 
6895bc3cb74SMauro Carvalho Chehab static void v4l_print_enum_dv_timings(const void *arg, bool write_only)
6905bc3cb74SMauro Carvalho Chehab {
6915bc3cb74SMauro Carvalho Chehab 	const struct v4l2_enum_dv_timings *p = arg;
6925bc3cb74SMauro Carvalho Chehab 
6935bc3cb74SMauro Carvalho Chehab 	pr_cont("index=%u, ", p->index);
6945bc3cb74SMauro Carvalho Chehab 	v4l_print_dv_timings(&p->timings, write_only);
6955bc3cb74SMauro Carvalho Chehab }
6965bc3cb74SMauro Carvalho Chehab 
6975bc3cb74SMauro Carvalho Chehab static void v4l_print_dv_timings_cap(const void *arg, bool write_only)
6985bc3cb74SMauro Carvalho Chehab {
6995bc3cb74SMauro Carvalho Chehab 	const struct v4l2_dv_timings_cap *p = arg;
7005bc3cb74SMauro Carvalho Chehab 
7015bc3cb74SMauro Carvalho Chehab 	switch (p->type) {
7025bc3cb74SMauro Carvalho Chehab 	case V4L2_DV_BT_656_1120:
7038720427cSMauro Carvalho Chehab 		pr_cont("type=bt-656/1120, width=%u-%u, height=%u-%u, pixelclock=%llu-%llu, standards=0x%x, capabilities=0x%x\n",
7045bc3cb74SMauro Carvalho Chehab 			p->bt.min_width, p->bt.max_width,
7055bc3cb74SMauro Carvalho Chehab 			p->bt.min_height, p->bt.max_height,
7065bc3cb74SMauro Carvalho Chehab 			p->bt.min_pixelclock, p->bt.max_pixelclock,
7075bc3cb74SMauro Carvalho Chehab 			p->bt.standards, p->bt.capabilities);
7085bc3cb74SMauro Carvalho Chehab 		break;
7095bc3cb74SMauro Carvalho Chehab 	default:
7105bc3cb74SMauro Carvalho Chehab 		pr_cont("type=%u\n", p->type);
7115bc3cb74SMauro Carvalho Chehab 		break;
7125bc3cb74SMauro Carvalho Chehab 	}
7135bc3cb74SMauro Carvalho Chehab }
7145bc3cb74SMauro Carvalho Chehab 
7155bc3cb74SMauro Carvalho Chehab static void v4l_print_frmsizeenum(const void *arg, bool write_only)
7165bc3cb74SMauro Carvalho Chehab {
7175bc3cb74SMauro Carvalho Chehab 	const struct v4l2_frmsizeenum *p = arg;
7185bc3cb74SMauro Carvalho Chehab 
7195bc3cb74SMauro Carvalho Chehab 	pr_cont("index=%u, pixelformat=%c%c%c%c, type=%u",
7205bc3cb74SMauro Carvalho Chehab 			p->index,
7215bc3cb74SMauro Carvalho Chehab 			(p->pixel_format & 0xff),
7225bc3cb74SMauro Carvalho Chehab 			(p->pixel_format >>  8) & 0xff,
7235bc3cb74SMauro Carvalho Chehab 			(p->pixel_format >> 16) & 0xff,
7245bc3cb74SMauro Carvalho Chehab 			(p->pixel_format >> 24) & 0xff,
7255bc3cb74SMauro Carvalho Chehab 			p->type);
7265bc3cb74SMauro Carvalho Chehab 	switch (p->type) {
7275bc3cb74SMauro Carvalho Chehab 	case V4L2_FRMSIZE_TYPE_DISCRETE:
728560dde24SHans Verkuil 		pr_cont(", wxh=%ux%u\n",
7295bc3cb74SMauro Carvalho Chehab 			p->discrete.width, p->discrete.height);
7305bc3cb74SMauro Carvalho Chehab 		break;
7315bc3cb74SMauro Carvalho Chehab 	case V4L2_FRMSIZE_TYPE_STEPWISE:
732560dde24SHans Verkuil 		pr_cont(", min=%ux%u, max=%ux%u, step=%ux%u\n",
7335bc3cb74SMauro Carvalho Chehab 				p->stepwise.min_width,  p->stepwise.min_height,
7345bc3cb74SMauro Carvalho Chehab 				p->stepwise.step_width, p->stepwise.step_height,
7355bc3cb74SMauro Carvalho Chehab 				p->stepwise.max_width,  p->stepwise.max_height);
7365bc3cb74SMauro Carvalho Chehab 		break;
7375bc3cb74SMauro Carvalho Chehab 	case V4L2_FRMSIZE_TYPE_CONTINUOUS:
7385bc3cb74SMauro Carvalho Chehab 		/* fall through */
7395bc3cb74SMauro Carvalho Chehab 	default:
7405bc3cb74SMauro Carvalho Chehab 		pr_cont("\n");
7415bc3cb74SMauro Carvalho Chehab 		break;
7425bc3cb74SMauro Carvalho Chehab 	}
7435bc3cb74SMauro Carvalho Chehab }
7445bc3cb74SMauro Carvalho Chehab 
7455bc3cb74SMauro Carvalho Chehab static void v4l_print_frmivalenum(const void *arg, bool write_only)
7465bc3cb74SMauro Carvalho Chehab {
7475bc3cb74SMauro Carvalho Chehab 	const struct v4l2_frmivalenum *p = arg;
7485bc3cb74SMauro Carvalho Chehab 
7495bc3cb74SMauro Carvalho Chehab 	pr_cont("index=%u, pixelformat=%c%c%c%c, wxh=%ux%u, type=%u",
7505bc3cb74SMauro Carvalho Chehab 			p->index,
7515bc3cb74SMauro Carvalho Chehab 			(p->pixel_format & 0xff),
7525bc3cb74SMauro Carvalho Chehab 			(p->pixel_format >>  8) & 0xff,
7535bc3cb74SMauro Carvalho Chehab 			(p->pixel_format >> 16) & 0xff,
7545bc3cb74SMauro Carvalho Chehab 			(p->pixel_format >> 24) & 0xff,
7555bc3cb74SMauro Carvalho Chehab 			p->width, p->height, p->type);
7565bc3cb74SMauro Carvalho Chehab 	switch (p->type) {
7575bc3cb74SMauro Carvalho Chehab 	case V4L2_FRMIVAL_TYPE_DISCRETE:
758560dde24SHans Verkuil 		pr_cont(", fps=%d/%d\n",
7595bc3cb74SMauro Carvalho Chehab 				p->discrete.numerator,
7605bc3cb74SMauro Carvalho Chehab 				p->discrete.denominator);
7615bc3cb74SMauro Carvalho Chehab 		break;
7625bc3cb74SMauro Carvalho Chehab 	case V4L2_FRMIVAL_TYPE_STEPWISE:
763560dde24SHans Verkuil 		pr_cont(", min=%d/%d, max=%d/%d, step=%d/%d\n",
7645bc3cb74SMauro Carvalho Chehab 				p->stepwise.min.numerator,
7655bc3cb74SMauro Carvalho Chehab 				p->stepwise.min.denominator,
7665bc3cb74SMauro Carvalho Chehab 				p->stepwise.max.numerator,
7675bc3cb74SMauro Carvalho Chehab 				p->stepwise.max.denominator,
7685bc3cb74SMauro Carvalho Chehab 				p->stepwise.step.numerator,
7695bc3cb74SMauro Carvalho Chehab 				p->stepwise.step.denominator);
7705bc3cb74SMauro Carvalho Chehab 		break;
7715bc3cb74SMauro Carvalho Chehab 	case V4L2_FRMIVAL_TYPE_CONTINUOUS:
7725bc3cb74SMauro Carvalho Chehab 		/* fall through */
7735bc3cb74SMauro Carvalho Chehab 	default:
7745bc3cb74SMauro Carvalho Chehab 		pr_cont("\n");
7755bc3cb74SMauro Carvalho Chehab 		break;
7765bc3cb74SMauro Carvalho Chehab 	}
7775bc3cb74SMauro Carvalho Chehab }
7785bc3cb74SMauro Carvalho Chehab 
7795bc3cb74SMauro Carvalho Chehab static void v4l_print_event(const void *arg, bool write_only)
7805bc3cb74SMauro Carvalho Chehab {
7815bc3cb74SMauro Carvalho Chehab 	const struct v4l2_event *p = arg;
7825bc3cb74SMauro Carvalho Chehab 	const struct v4l2_event_ctrl *c;
7835bc3cb74SMauro Carvalho Chehab 
7848720427cSMauro Carvalho Chehab 	pr_cont("type=0x%x, pending=%u, sequence=%u, id=%u, timestamp=%lu.%9.9lu\n",
7855bc3cb74SMauro Carvalho Chehab 			p->type, p->pending, p->sequence, p->id,
7865bc3cb74SMauro Carvalho Chehab 			p->timestamp.tv_sec, p->timestamp.tv_nsec);
7875bc3cb74SMauro Carvalho Chehab 	switch (p->type) {
7885bc3cb74SMauro Carvalho Chehab 	case V4L2_EVENT_VSYNC:
7895bc3cb74SMauro Carvalho Chehab 		printk(KERN_DEBUG "field=%s\n",
7905bc3cb74SMauro Carvalho Chehab 			prt_names(p->u.vsync.field, v4l2_field_names));
7915bc3cb74SMauro Carvalho Chehab 		break;
7925bc3cb74SMauro Carvalho Chehab 	case V4L2_EVENT_CTRL:
7935bc3cb74SMauro Carvalho Chehab 		c = &p->u.ctrl;
7945bc3cb74SMauro Carvalho Chehab 		printk(KERN_DEBUG "changes=0x%x, type=%u, ",
7955bc3cb74SMauro Carvalho Chehab 			c->changes, c->type);
7965bc3cb74SMauro Carvalho Chehab 		if (c->type == V4L2_CTRL_TYPE_INTEGER64)
7975bc3cb74SMauro Carvalho Chehab 			pr_cont("value64=%lld, ", c->value64);
7985bc3cb74SMauro Carvalho Chehab 		else
7995bc3cb74SMauro Carvalho Chehab 			pr_cont("value=%d, ", c->value);
8008720427cSMauro Carvalho Chehab 		pr_cont("flags=0x%x, minimum=%d, maximum=%d, step=%d, default_value=%d\n",
8015bc3cb74SMauro Carvalho Chehab 			c->flags, c->minimum, c->maximum,
8025bc3cb74SMauro Carvalho Chehab 			c->step, c->default_value);
8035bc3cb74SMauro Carvalho Chehab 		break;
8045bc3cb74SMauro Carvalho Chehab 	case V4L2_EVENT_FRAME_SYNC:
8055bc3cb74SMauro Carvalho Chehab 		pr_cont("frame_sequence=%u\n",
8065bc3cb74SMauro Carvalho Chehab 			p->u.frame_sync.frame_sequence);
8075bc3cb74SMauro Carvalho Chehab 		break;
8085bc3cb74SMauro Carvalho Chehab 	}
8095bc3cb74SMauro Carvalho Chehab }
8105bc3cb74SMauro Carvalho Chehab 
8115bc3cb74SMauro Carvalho Chehab static void v4l_print_event_subscription(const void *arg, bool write_only)
8125bc3cb74SMauro Carvalho Chehab {
8135bc3cb74SMauro Carvalho Chehab 	const struct v4l2_event_subscription *p = arg;
8145bc3cb74SMauro Carvalho Chehab 
8155bc3cb74SMauro Carvalho Chehab 	pr_cont("type=0x%x, id=0x%x, flags=0x%x\n",
8165bc3cb74SMauro Carvalho Chehab 			p->type, p->id, p->flags);
8175bc3cb74SMauro Carvalho Chehab }
8185bc3cb74SMauro Carvalho Chehab 
8195bc3cb74SMauro Carvalho Chehab static void v4l_print_sliced_vbi_cap(const void *arg, bool write_only)
8205bc3cb74SMauro Carvalho Chehab {
8215bc3cb74SMauro Carvalho Chehab 	const struct v4l2_sliced_vbi_cap *p = arg;
8225bc3cb74SMauro Carvalho Chehab 	int i;
8235bc3cb74SMauro Carvalho Chehab 
8245bc3cb74SMauro Carvalho Chehab 	pr_cont("type=%s, service_set=0x%08x\n",
8255bc3cb74SMauro Carvalho Chehab 			prt_names(p->type, v4l2_type_names), p->service_set);
8265bc3cb74SMauro Carvalho Chehab 	for (i = 0; i < 24; i++)
8275bc3cb74SMauro Carvalho Chehab 		printk(KERN_DEBUG "line[%02u]=0x%04x, 0x%04x\n", i,
8285bc3cb74SMauro Carvalho Chehab 				p->service_lines[0][i],
8295bc3cb74SMauro Carvalho Chehab 				p->service_lines[1][i]);
8305bc3cb74SMauro Carvalho Chehab }
8315bc3cb74SMauro Carvalho Chehab 
8325bc3cb74SMauro Carvalho Chehab static void v4l_print_freq_band(const void *arg, bool write_only)
8335bc3cb74SMauro Carvalho Chehab {
8345bc3cb74SMauro Carvalho Chehab 	const struct v4l2_frequency_band *p = arg;
8355bc3cb74SMauro Carvalho Chehab 
8368720427cSMauro Carvalho Chehab 	pr_cont("tuner=%u, type=%u, index=%u, capability=0x%x, rangelow=%u, rangehigh=%u, modulation=0x%x\n",
8375bc3cb74SMauro Carvalho Chehab 			p->tuner, p->type, p->index,
8385bc3cb74SMauro Carvalho Chehab 			p->capability, p->rangelow,
8395bc3cb74SMauro Carvalho Chehab 			p->rangehigh, p->modulation);
8405bc3cb74SMauro Carvalho Chehab }
8415bc3cb74SMauro Carvalho Chehab 
842dd519bb3SHans Verkuil static void v4l_print_edid(const void *arg, bool write_only)
843dd519bb3SHans Verkuil {
844dd519bb3SHans Verkuil 	const struct v4l2_edid *p = arg;
845dd519bb3SHans Verkuil 
846dd519bb3SHans Verkuil 	pr_cont("pad=%u, start_block=%u, blocks=%u\n",
847dd519bb3SHans Verkuil 		p->pad, p->start_block, p->blocks);
848dd519bb3SHans Verkuil }
849dd519bb3SHans Verkuil 
8505bc3cb74SMauro Carvalho Chehab static void v4l_print_u32(const void *arg, bool write_only)
8515bc3cb74SMauro Carvalho Chehab {
8525bc3cb74SMauro Carvalho Chehab 	pr_cont("value=%u\n", *(const u32 *)arg);
8535bc3cb74SMauro Carvalho Chehab }
8545bc3cb74SMauro Carvalho Chehab 
8555bc3cb74SMauro Carvalho Chehab static void v4l_print_newline(const void *arg, bool write_only)
8565bc3cb74SMauro Carvalho Chehab {
8575bc3cb74SMauro Carvalho Chehab 	pr_cont("\n");
8585bc3cb74SMauro Carvalho Chehab }
8595bc3cb74SMauro Carvalho Chehab 
8605bc3cb74SMauro Carvalho Chehab static void v4l_print_default(const void *arg, bool write_only)
8615bc3cb74SMauro Carvalho Chehab {
8625bc3cb74SMauro Carvalho Chehab 	pr_cont("driver-specific ioctl\n");
8635bc3cb74SMauro Carvalho Chehab }
8645bc3cb74SMauro Carvalho Chehab 
8655bc3cb74SMauro Carvalho Chehab static int check_ext_ctrls(struct v4l2_ext_controls *c, int allow_priv)
8665bc3cb74SMauro Carvalho Chehab {
8675bc3cb74SMauro Carvalho Chehab 	__u32 i;
8685bc3cb74SMauro Carvalho Chehab 
8695bc3cb74SMauro Carvalho Chehab 	/* zero the reserved fields */
8705bc3cb74SMauro Carvalho Chehab 	c->reserved[0] = c->reserved[1] = 0;
8715bc3cb74SMauro Carvalho Chehab 	for (i = 0; i < c->count; i++)
8725bc3cb74SMauro Carvalho Chehab 		c->controls[i].reserved2[0] = 0;
8735bc3cb74SMauro Carvalho Chehab 
8745bc3cb74SMauro Carvalho Chehab 	/* V4L2_CID_PRIVATE_BASE cannot be used as control class
8755bc3cb74SMauro Carvalho Chehab 	   when using extended controls.
8765bc3cb74SMauro Carvalho Chehab 	   Only when passed in through VIDIOC_G_CTRL and VIDIOC_S_CTRL
8775bc3cb74SMauro Carvalho Chehab 	   is it allowed for backwards compatibility.
8785bc3cb74SMauro Carvalho Chehab 	 */
8790f8017beSRicardo Ribalda 	if (!allow_priv && c->which == V4L2_CID_PRIVATE_BASE)
8805bc3cb74SMauro Carvalho Chehab 		return 0;
8810f8017beSRicardo Ribalda 	if (!c->which)
8829b239b22SHans Verkuil 		return 1;
8835bc3cb74SMauro Carvalho Chehab 	/* Check that all controls are from the same control class. */
8845bc3cb74SMauro Carvalho Chehab 	for (i = 0; i < c->count; i++) {
8850f8017beSRicardo Ribalda 		if (V4L2_CTRL_ID2WHICH(c->controls[i].id) != c->which) {
8865bc3cb74SMauro Carvalho Chehab 			c->error_idx = i;
8875bc3cb74SMauro Carvalho Chehab 			return 0;
8885bc3cb74SMauro Carvalho Chehab 		}
8895bc3cb74SMauro Carvalho Chehab 	}
8905bc3cb74SMauro Carvalho Chehab 	return 1;
8915bc3cb74SMauro Carvalho Chehab }
8925bc3cb74SMauro Carvalho Chehab 
8934b20259fSHans Verkuil static int check_fmt(struct file *file, enum v4l2_buf_type type)
8945bc3cb74SMauro Carvalho Chehab {
8954b20259fSHans Verkuil 	struct video_device *vfd = video_devdata(file);
8964b20259fSHans Verkuil 	const struct v4l2_ioctl_ops *ops = vfd->ioctl_ops;
8974b20259fSHans Verkuil 	bool is_vid = vfd->vfl_type == VFL_TYPE_GRABBER;
8984b20259fSHans Verkuil 	bool is_vbi = vfd->vfl_type == VFL_TYPE_VBI;
899582c52cbSAntti Palosaari 	bool is_sdr = vfd->vfl_type == VFL_TYPE_SDR;
900b2fe22d0SNick Dyer 	bool is_tch = vfd->vfl_type == VFL_TYPE_TOUCH;
9014b20259fSHans Verkuil 	bool is_rx = vfd->vfl_dir != VFL_DIR_TX;
9024b20259fSHans Verkuil 	bool is_tx = vfd->vfl_dir != VFL_DIR_RX;
9034b20259fSHans Verkuil 
9045bc3cb74SMauro Carvalho Chehab 	if (ops == NULL)
9055bc3cb74SMauro Carvalho Chehab 		return -EINVAL;
9065bc3cb74SMauro Carvalho Chehab 
9075bc3cb74SMauro Carvalho Chehab 	switch (type) {
9085bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
909b2fe22d0SNick Dyer 		if ((is_vid || is_tch) && is_rx &&
9104b20259fSHans Verkuil 		    (ops->vidioc_g_fmt_vid_cap || ops->vidioc_g_fmt_vid_cap_mplane))
9115bc3cb74SMauro Carvalho Chehab 			return 0;
9125bc3cb74SMauro Carvalho Chehab 		break;
9135bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
9144b20259fSHans Verkuil 		if (is_vid && is_rx && ops->vidioc_g_fmt_vid_cap_mplane)
9155bc3cb74SMauro Carvalho Chehab 			return 0;
9165bc3cb74SMauro Carvalho Chehab 		break;
9175bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_OVERLAY:
9184b20259fSHans Verkuil 		if (is_vid && is_rx && ops->vidioc_g_fmt_vid_overlay)
9195bc3cb74SMauro Carvalho Chehab 			return 0;
9205bc3cb74SMauro Carvalho Chehab 		break;
9215bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_OUTPUT:
9224b20259fSHans Verkuil 		if (is_vid && is_tx &&
9234b20259fSHans Verkuil 		    (ops->vidioc_g_fmt_vid_out || ops->vidioc_g_fmt_vid_out_mplane))
9245bc3cb74SMauro Carvalho Chehab 			return 0;
9255bc3cb74SMauro Carvalho Chehab 		break;
9265bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
9274b20259fSHans Verkuil 		if (is_vid && is_tx && ops->vidioc_g_fmt_vid_out_mplane)
9285bc3cb74SMauro Carvalho Chehab 			return 0;
9295bc3cb74SMauro Carvalho Chehab 		break;
9305bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
9314b20259fSHans Verkuil 		if (is_vid && is_tx && ops->vidioc_g_fmt_vid_out_overlay)
9325bc3cb74SMauro Carvalho Chehab 			return 0;
9335bc3cb74SMauro Carvalho Chehab 		break;
9345bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VBI_CAPTURE:
9354b20259fSHans Verkuil 		if (is_vbi && is_rx && ops->vidioc_g_fmt_vbi_cap)
9365bc3cb74SMauro Carvalho Chehab 			return 0;
9375bc3cb74SMauro Carvalho Chehab 		break;
9385bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VBI_OUTPUT:
9394b20259fSHans Verkuil 		if (is_vbi && is_tx && ops->vidioc_g_fmt_vbi_out)
9405bc3cb74SMauro Carvalho Chehab 			return 0;
9415bc3cb74SMauro Carvalho Chehab 		break;
9425bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
9434b20259fSHans Verkuil 		if (is_vbi && is_rx && ops->vidioc_g_fmt_sliced_vbi_cap)
9445bc3cb74SMauro Carvalho Chehab 			return 0;
9455bc3cb74SMauro Carvalho Chehab 		break;
9465bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
9474b20259fSHans Verkuil 		if (is_vbi && is_tx && ops->vidioc_g_fmt_sliced_vbi_out)
9485bc3cb74SMauro Carvalho Chehab 			return 0;
9495bc3cb74SMauro Carvalho Chehab 		break;
950582c52cbSAntti Palosaari 	case V4L2_BUF_TYPE_SDR_CAPTURE:
951582c52cbSAntti Palosaari 		if (is_sdr && is_rx && ops->vidioc_g_fmt_sdr_cap)
952582c52cbSAntti Palosaari 			return 0;
953582c52cbSAntti Palosaari 		break;
9549effc72fSAntti Palosaari 	case V4L2_BUF_TYPE_SDR_OUTPUT:
9559effc72fSAntti Palosaari 		if (is_sdr && is_tx && ops->vidioc_g_fmt_sdr_out)
9569effc72fSAntti Palosaari 			return 0;
9579effc72fSAntti Palosaari 		break;
958fb9ffa6aSLaurent Pinchart 	case V4L2_BUF_TYPE_META_CAPTURE:
959fb9ffa6aSLaurent Pinchart 		if (is_vid && is_rx && ops->vidioc_g_fmt_meta_cap)
960fb9ffa6aSLaurent Pinchart 			return 0;
961fb9ffa6aSLaurent Pinchart 		break;
962633c98e5SHans Verkuil 	default:
9635bc3cb74SMauro Carvalho Chehab 		break;
9645bc3cb74SMauro Carvalho Chehab 	}
9655bc3cb74SMauro Carvalho Chehab 	return -EINVAL;
9665bc3cb74SMauro Carvalho Chehab }
9675bc3cb74SMauro Carvalho Chehab 
968d52e2381SLaurent Pinchart static void v4l_sanitize_format(struct v4l2_format *fmt)
969d52e2381SLaurent Pinchart {
970d52e2381SLaurent Pinchart 	unsigned int offset;
971d52e2381SLaurent Pinchart 
972d52e2381SLaurent Pinchart 	/*
973d52e2381SLaurent Pinchart 	 * The v4l2_pix_format structure has been extended with fields that were
974d52e2381SLaurent Pinchart 	 * not previously required to be set to zero by applications. The priv
975d52e2381SLaurent Pinchart 	 * field, when set to a magic value, indicates the the extended fields
976d52e2381SLaurent Pinchart 	 * are valid. Otherwise they will contain undefined values. To simplify
977d52e2381SLaurent Pinchart 	 * the API towards drivers zero the extended fields and set the priv
978d52e2381SLaurent Pinchart 	 * field to the magic value when the extended pixel format structure
979d52e2381SLaurent Pinchart 	 * isn't used by applications.
980d52e2381SLaurent Pinchart 	 */
981d52e2381SLaurent Pinchart 
982d52e2381SLaurent Pinchart 	if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
983d52e2381SLaurent Pinchart 	    fmt->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
984d52e2381SLaurent Pinchart 		return;
985d52e2381SLaurent Pinchart 
986d52e2381SLaurent Pinchart 	if (fmt->fmt.pix.priv == V4L2_PIX_FMT_PRIV_MAGIC)
987d52e2381SLaurent Pinchart 		return;
988d52e2381SLaurent Pinchart 
989d52e2381SLaurent Pinchart 	fmt->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC;
990d52e2381SLaurent Pinchart 
991d52e2381SLaurent Pinchart 	offset = offsetof(struct v4l2_pix_format, priv)
992d52e2381SLaurent Pinchart 	       + sizeof(fmt->fmt.pix.priv);
993d52e2381SLaurent Pinchart 	memset(((void *)&fmt->fmt.pix) + offset, 0,
994d52e2381SLaurent Pinchart 	       sizeof(fmt->fmt.pix) - offset);
995d52e2381SLaurent Pinchart }
996d52e2381SLaurent Pinchart 
9975bc3cb74SMauro Carvalho Chehab static int v4l_querycap(const struct v4l2_ioctl_ops *ops,
9985bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
9995bc3cb74SMauro Carvalho Chehab {
10005bc3cb74SMauro Carvalho Chehab 	struct v4l2_capability *cap = (struct v4l2_capability *)arg;
10017bbe7813SHans Verkuil 	struct video_device *vfd = video_devdata(file);
1002d52e2381SLaurent Pinchart 	int ret;
10035bc3cb74SMauro Carvalho Chehab 
10045bc3cb74SMauro Carvalho Chehab 	cap->version = LINUX_VERSION_CODE;
10057bbe7813SHans Verkuil 	cap->device_caps = vfd->device_caps;
10067bbe7813SHans Verkuil 	cap->capabilities = vfd->device_caps | V4L2_CAP_DEVICE_CAPS;
1007d52e2381SLaurent Pinchart 
1008d52e2381SLaurent Pinchart 	ret = ops->vidioc_querycap(file, fh, cap);
1009d52e2381SLaurent Pinchart 
1010d52e2381SLaurent Pinchart 	cap->capabilities |= V4L2_CAP_EXT_PIX_FORMAT;
1011454a4e72SHans Verkuil 	/*
1012454a4e72SHans Verkuil 	 * Drivers MUST fill in device_caps, so check for this and
1013454a4e72SHans Verkuil 	 * warn if it was forgotten.
1014454a4e72SHans Verkuil 	 */
10156d7570c4SLaura Abbott 	WARN(!(cap->capabilities & V4L2_CAP_DEVICE_CAPS) ||
10166d7570c4SLaura Abbott 		!cap->device_caps, "Bad caps for driver %s, %x %x",
10176d7570c4SLaura Abbott 		cap->driver, cap->capabilities, cap->device_caps);
1018796a2bd2SHans Verkuil 	cap->device_caps |= V4L2_CAP_EXT_PIX_FORMAT;
1019d52e2381SLaurent Pinchart 
1020d52e2381SLaurent Pinchart 	return ret;
10215bc3cb74SMauro Carvalho Chehab }
10225bc3cb74SMauro Carvalho Chehab 
10235bc3cb74SMauro Carvalho Chehab static int v4l_s_input(const struct v4l2_ioctl_ops *ops,
10245bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
10255bc3cb74SMauro Carvalho Chehab {
102677fa4e07SShuah Khan 	struct video_device *vfd = video_devdata(file);
102777fa4e07SShuah Khan 	int ret;
102877fa4e07SShuah Khan 
102977fa4e07SShuah Khan 	ret = v4l_enable_media_source(vfd);
103077fa4e07SShuah Khan 	if (ret)
103177fa4e07SShuah Khan 		return ret;
10325bc3cb74SMauro Carvalho Chehab 	return ops->vidioc_s_input(file, fh, *(unsigned int *)arg);
10335bc3cb74SMauro Carvalho Chehab }
10345bc3cb74SMauro Carvalho Chehab 
10355bc3cb74SMauro Carvalho Chehab static int v4l_s_output(const struct v4l2_ioctl_ops *ops,
10365bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
10375bc3cb74SMauro Carvalho Chehab {
10385bc3cb74SMauro Carvalho Chehab 	return ops->vidioc_s_output(file, fh, *(unsigned int *)arg);
10395bc3cb74SMauro Carvalho Chehab }
10405bc3cb74SMauro Carvalho Chehab 
10415bc3cb74SMauro Carvalho Chehab static int v4l_g_priority(const struct v4l2_ioctl_ops *ops,
10425bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
10435bc3cb74SMauro Carvalho Chehab {
10445bc3cb74SMauro Carvalho Chehab 	struct video_device *vfd;
10455bc3cb74SMauro Carvalho Chehab 	u32 *p = arg;
10465bc3cb74SMauro Carvalho Chehab 
10475bc3cb74SMauro Carvalho Chehab 	vfd = video_devdata(file);
104859b702eaSLaurent Pinchart 	*p = v4l2_prio_max(vfd->prio);
10495bc3cb74SMauro Carvalho Chehab 	return 0;
10505bc3cb74SMauro Carvalho Chehab }
10515bc3cb74SMauro Carvalho Chehab 
10525bc3cb74SMauro Carvalho Chehab static int v4l_s_priority(const struct v4l2_ioctl_ops *ops,
10535bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
10545bc3cb74SMauro Carvalho Chehab {
10555bc3cb74SMauro Carvalho Chehab 	struct video_device *vfd;
10565bc3cb74SMauro Carvalho Chehab 	struct v4l2_fh *vfh;
10575bc3cb74SMauro Carvalho Chehab 	u32 *p = arg;
10585bc3cb74SMauro Carvalho Chehab 
10595bc3cb74SMauro Carvalho Chehab 	vfd = video_devdata(file);
10602438e78aSHans Verkuil 	if (!test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags))
10612438e78aSHans Verkuil 		return -ENOTTY;
10625bc3cb74SMauro Carvalho Chehab 	vfh = file->private_data;
106359b702eaSLaurent Pinchart 	return v4l2_prio_change(vfd->prio, &vfh->prio, *p);
10645bc3cb74SMauro Carvalho Chehab }
10655bc3cb74SMauro Carvalho Chehab 
10665bc3cb74SMauro Carvalho Chehab static int v4l_enuminput(const struct v4l2_ioctl_ops *ops,
10675bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
10685bc3cb74SMauro Carvalho Chehab {
106973f35418SHans Verkuil 	struct video_device *vfd = video_devdata(file);
10705bc3cb74SMauro Carvalho Chehab 	struct v4l2_input *p = arg;
10715bc3cb74SMauro Carvalho Chehab 
10725bc3cb74SMauro Carvalho Chehab 	/*
107302fa6282SHans Verkuil 	 * We set the flags for CAP_DV_TIMINGS &
10745bc3cb74SMauro Carvalho Chehab 	 * CAP_STD here based on ioctl handler provided by the
10755bc3cb74SMauro Carvalho Chehab 	 * driver. If the driver doesn't support these
10765bc3cb74SMauro Carvalho Chehab 	 * for a specific input, it must override these flags.
10775bc3cb74SMauro Carvalho Chehab 	 */
107873f35418SHans Verkuil 	if (is_valid_ioctl(vfd, VIDIOC_S_STD))
10795bc3cb74SMauro Carvalho Chehab 		p->capabilities |= V4L2_IN_CAP_STD;
10805bc3cb74SMauro Carvalho Chehab 
10815bc3cb74SMauro Carvalho Chehab 	return ops->vidioc_enum_input(file, fh, p);
10825bc3cb74SMauro Carvalho Chehab }
10835bc3cb74SMauro Carvalho Chehab 
10845bc3cb74SMauro Carvalho Chehab static int v4l_enumoutput(const struct v4l2_ioctl_ops *ops,
10855bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
10865bc3cb74SMauro Carvalho Chehab {
108773f35418SHans Verkuil 	struct video_device *vfd = video_devdata(file);
10885bc3cb74SMauro Carvalho Chehab 	struct v4l2_output *p = arg;
10895bc3cb74SMauro Carvalho Chehab 
10905bc3cb74SMauro Carvalho Chehab 	/*
109102fa6282SHans Verkuil 	 * We set the flags for CAP_DV_TIMINGS &
10925bc3cb74SMauro Carvalho Chehab 	 * CAP_STD here based on ioctl handler provided by the
10935bc3cb74SMauro Carvalho Chehab 	 * driver. If the driver doesn't support these
10945bc3cb74SMauro Carvalho Chehab 	 * for a specific output, it must override these flags.
10955bc3cb74SMauro Carvalho Chehab 	 */
109673f35418SHans Verkuil 	if (is_valid_ioctl(vfd, VIDIOC_S_STD))
10975bc3cb74SMauro Carvalho Chehab 		p->capabilities |= V4L2_OUT_CAP_STD;
10985bc3cb74SMauro Carvalho Chehab 
10995bc3cb74SMauro Carvalho Chehab 	return ops->vidioc_enum_output(file, fh, p);
11005bc3cb74SMauro Carvalho Chehab }
11015bc3cb74SMauro Carvalho Chehab 
1102ba300204SHans Verkuil static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt)
1103ba300204SHans Verkuil {
1104ba300204SHans Verkuil 	const unsigned sz = sizeof(fmt->description);
1105ba300204SHans Verkuil 	const char *descr = NULL;
1106ba300204SHans Verkuil 	u32 flags = 0;
1107ba300204SHans Verkuil 
1108ba300204SHans Verkuil 	/*
1109ba300204SHans Verkuil 	 * We depart from the normal coding style here since the descriptions
1110ba300204SHans Verkuil 	 * should be aligned so it is easy to see which descriptions will be
1111ba300204SHans Verkuil 	 * longer than 31 characters (the max length for a description).
1112ba300204SHans Verkuil 	 * And frankly, this is easier to read anyway.
1113ba300204SHans Verkuil 	 *
1114ba300204SHans Verkuil 	 * Note that gcc will use O(log N) comparisons to find the right case.
1115ba300204SHans Verkuil 	 */
1116ba300204SHans Verkuil 	switch (fmt->pixelformat) {
1117ba300204SHans Verkuil 	/* Max description length mask:	descr = "0123456789012345678901234567890" */
1118ba300204SHans Verkuil 	case V4L2_PIX_FMT_RGB332:	descr = "8-bit RGB 3-3-2"; break;
1119ba300204SHans Verkuil 	case V4L2_PIX_FMT_RGB444:	descr = "16-bit A/XRGB 4-4-4-4"; break;
1120ba300204SHans Verkuil 	case V4L2_PIX_FMT_ARGB444:	descr = "16-bit ARGB 4-4-4-4"; break;
1121ba300204SHans Verkuil 	case V4L2_PIX_FMT_XRGB444:	descr = "16-bit XRGB 4-4-4-4"; break;
1122ba300204SHans Verkuil 	case V4L2_PIX_FMT_RGB555:	descr = "16-bit A/XRGB 1-5-5-5"; break;
1123ba300204SHans Verkuil 	case V4L2_PIX_FMT_ARGB555:	descr = "16-bit ARGB 1-5-5-5"; break;
1124ba300204SHans Verkuil 	case V4L2_PIX_FMT_XRGB555:	descr = "16-bit XRGB 1-5-5-5"; break;
1125ba300204SHans Verkuil 	case V4L2_PIX_FMT_RGB565:	descr = "16-bit RGB 5-6-5"; break;
1126ba300204SHans Verkuil 	case V4L2_PIX_FMT_RGB555X:	descr = "16-bit A/XRGB 1-5-5-5 BE"; break;
1127ba300204SHans Verkuil 	case V4L2_PIX_FMT_ARGB555X:	descr = "16-bit ARGB 1-5-5-5 BE"; break;
1128ba300204SHans Verkuil 	case V4L2_PIX_FMT_XRGB555X:	descr = "16-bit XRGB 1-5-5-5 BE"; break;
1129ba300204SHans Verkuil 	case V4L2_PIX_FMT_RGB565X:	descr = "16-bit RGB 5-6-5 BE"; break;
1130ba300204SHans Verkuil 	case V4L2_PIX_FMT_BGR666:	descr = "18-bit BGRX 6-6-6-14"; break;
1131ba300204SHans Verkuil 	case V4L2_PIX_FMT_BGR24:	descr = "24-bit BGR 8-8-8"; break;
1132ba300204SHans Verkuil 	case V4L2_PIX_FMT_RGB24:	descr = "24-bit RGB 8-8-8"; break;
1133ba300204SHans Verkuil 	case V4L2_PIX_FMT_BGR32:	descr = "32-bit BGRA/X 8-8-8-8"; break;
1134ba300204SHans Verkuil 	case V4L2_PIX_FMT_ABGR32:	descr = "32-bit BGRA 8-8-8-8"; break;
1135ba300204SHans Verkuil 	case V4L2_PIX_FMT_XBGR32:	descr = "32-bit BGRX 8-8-8-8"; break;
1136ba300204SHans Verkuil 	case V4L2_PIX_FMT_RGB32:	descr = "32-bit A/XRGB 8-8-8-8"; break;
1137ba300204SHans Verkuil 	case V4L2_PIX_FMT_ARGB32:	descr = "32-bit ARGB 8-8-8-8"; break;
1138ba300204SHans Verkuil 	case V4L2_PIX_FMT_XRGB32:	descr = "32-bit XRGB 8-8-8-8"; break;
1139ba300204SHans Verkuil 	case V4L2_PIX_FMT_GREY:		descr = "8-bit Greyscale"; break;
1140ba300204SHans Verkuil 	case V4L2_PIX_FMT_Y4:		descr = "4-bit Greyscale"; break;
1141ba300204SHans Verkuil 	case V4L2_PIX_FMT_Y6:		descr = "6-bit Greyscale"; break;
1142ba300204SHans Verkuil 	case V4L2_PIX_FMT_Y10:		descr = "10-bit Greyscale"; break;
1143ba300204SHans Verkuil 	case V4L2_PIX_FMT_Y12:		descr = "12-bit Greyscale"; break;
1144ba300204SHans Verkuil 	case V4L2_PIX_FMT_Y16:		descr = "16-bit Greyscale"; break;
11452e5e435fSRicardo Ribalda 	case V4L2_PIX_FMT_Y16_BE:	descr = "16-bit Greyscale BE"; break;
1146ba300204SHans Verkuil 	case V4L2_PIX_FMT_Y10BPACK:	descr = "10-bit Greyscale (Packed)"; break;
11475b382290SLaurent Pinchart 	case V4L2_PIX_FMT_Y8I:		descr = "Interleaved 8-bit Greyscale"; break;
11485b382290SLaurent Pinchart 	case V4L2_PIX_FMT_Y12I:		descr = "Interleaved 12-bit Greyscale"; break;
11495b382290SLaurent Pinchart 	case V4L2_PIX_FMT_Z16:		descr = "16-bit Depth"; break;
11505df082e2SEvgeni Raikhel 	case V4L2_PIX_FMT_INZI:		descr = "Planar 10:16 Greyscale Depth"; break;
1151ba300204SHans Verkuil 	case V4L2_PIX_FMT_PAL8:		descr = "8-bit Palette"; break;
1152ba300204SHans Verkuil 	case V4L2_PIX_FMT_UV8:		descr = "8-bit Chrominance UV 4-4"; break;
1153ba300204SHans Verkuil 	case V4L2_PIX_FMT_YVU410:	descr = "Planar YVU 4:1:0"; break;
1154ba300204SHans Verkuil 	case V4L2_PIX_FMT_YVU420:	descr = "Planar YVU 4:2:0"; break;
1155ba300204SHans Verkuil 	case V4L2_PIX_FMT_YUYV:		descr = "YUYV 4:2:2"; break;
1156ba300204SHans Verkuil 	case V4L2_PIX_FMT_YYUV:		descr = "YYUV 4:2:2"; break;
1157ba300204SHans Verkuil 	case V4L2_PIX_FMT_YVYU:		descr = "YVYU 4:2:2"; break;
1158ba300204SHans Verkuil 	case V4L2_PIX_FMT_UYVY:		descr = "UYVY 4:2:2"; break;
1159ba300204SHans Verkuil 	case V4L2_PIX_FMT_VYUY:		descr = "VYUY 4:2:2"; break;
1160fcbafafbSPhilipp Zabel 	case V4L2_PIX_FMT_YUV422P:	descr = "Planar YUV 4:2:2"; break;
1161ba300204SHans Verkuil 	case V4L2_PIX_FMT_YUV411P:	descr = "Planar YUV 4:1:1"; break;
1162ba300204SHans Verkuil 	case V4L2_PIX_FMT_Y41P:		descr = "YUV 4:1:1 (Packed)"; break;
1163ba300204SHans Verkuil 	case V4L2_PIX_FMT_YUV444:	descr = "16-bit A/XYUV 4-4-4-4"; break;
1164ba300204SHans Verkuil 	case V4L2_PIX_FMT_YUV555:	descr = "16-bit A/XYUV 1-5-5-5"; break;
1165ba300204SHans Verkuil 	case V4L2_PIX_FMT_YUV565:	descr = "16-bit YUV 5-6-5"; break;
1166ba300204SHans Verkuil 	case V4L2_PIX_FMT_YUV32:	descr = "32-bit A/XYUV 8-8-8-8"; break;
1167ba300204SHans Verkuil 	case V4L2_PIX_FMT_YUV410:	descr = "Planar YUV 4:1:0"; break;
1168ba300204SHans Verkuil 	case V4L2_PIX_FMT_YUV420:	descr = "Planar YUV 4:2:0"; break;
1169ba300204SHans Verkuil 	case V4L2_PIX_FMT_HI240:	descr = "8-bit Dithered RGB (BTTV)"; break;
1170ba300204SHans Verkuil 	case V4L2_PIX_FMT_HM12:		descr = "YUV 4:2:0 (16x16 Macroblocks)"; break;
1171ba300204SHans Verkuil 	case V4L2_PIX_FMT_M420:		descr = "YUV 4:2:0 (M420)"; break;
1172ba300204SHans Verkuil 	case V4L2_PIX_FMT_NV12:		descr = "Y/CbCr 4:2:0"; break;
1173ba300204SHans Verkuil 	case V4L2_PIX_FMT_NV21:		descr = "Y/CrCb 4:2:0"; break;
1174ba300204SHans Verkuil 	case V4L2_PIX_FMT_NV16:		descr = "Y/CbCr 4:2:2"; break;
1175ba300204SHans Verkuil 	case V4L2_PIX_FMT_NV61:		descr = "Y/CrCb 4:2:2"; break;
1176ba300204SHans Verkuil 	case V4L2_PIX_FMT_NV24:		descr = "Y/CbCr 4:4:4"; break;
1177ba300204SHans Verkuil 	case V4L2_PIX_FMT_NV42:		descr = "Y/CrCb 4:4:4"; break;
1178ba300204SHans Verkuil 	case V4L2_PIX_FMT_NV12M:	descr = "Y/CbCr 4:2:0 (N-C)"; break;
1179ba300204SHans Verkuil 	case V4L2_PIX_FMT_NV21M:	descr = "Y/CrCb 4:2:0 (N-C)"; break;
1180ba300204SHans Verkuil 	case V4L2_PIX_FMT_NV16M:	descr = "Y/CbCr 4:2:2 (N-C)"; break;
1181ba300204SHans Verkuil 	case V4L2_PIX_FMT_NV61M:	descr = "Y/CrCb 4:2:2 (N-C)"; break;
1182ba300204SHans Verkuil 	case V4L2_PIX_FMT_NV12MT:	descr = "Y/CbCr 4:2:0 (64x32 MB, N-C)"; break;
1183ba300204SHans Verkuil 	case V4L2_PIX_FMT_NV12MT_16X16:	descr = "Y/CbCr 4:2:0 (16x16 MB, N-C)"; break;
1184ba300204SHans Verkuil 	case V4L2_PIX_FMT_YUV420M:	descr = "Planar YUV 4:2:0 (N-C)"; break;
1185ba300204SHans Verkuil 	case V4L2_PIX_FMT_YVU420M:	descr = "Planar YVU 4:2:0 (N-C)"; break;
1186d65fae92SLaurent Pinchart 	case V4L2_PIX_FMT_YUV422M:	descr = "Planar YUV 4:2:2 (N-C)"; break;
1187d65fae92SLaurent Pinchart 	case V4L2_PIX_FMT_YVU422M:	descr = "Planar YVU 4:2:2 (N-C)"; break;
1188d65fae92SLaurent Pinchart 	case V4L2_PIX_FMT_YUV444M:	descr = "Planar YUV 4:4:4 (N-C)"; break;
1189d65fae92SLaurent Pinchart 	case V4L2_PIX_FMT_YVU444M:	descr = "Planar YVU 4:4:4 (N-C)"; break;
1190ba300204SHans Verkuil 	case V4L2_PIX_FMT_SBGGR8:	descr = "8-bit Bayer BGBG/GRGR"; break;
1191ba300204SHans Verkuil 	case V4L2_PIX_FMT_SGBRG8:	descr = "8-bit Bayer GBGB/RGRG"; break;
1192ba300204SHans Verkuil 	case V4L2_PIX_FMT_SGRBG8:	descr = "8-bit Bayer GRGR/BGBG"; break;
1193ba300204SHans Verkuil 	case V4L2_PIX_FMT_SRGGB8:	descr = "8-bit Bayer RGRG/GBGB"; break;
1194ba300204SHans Verkuil 	case V4L2_PIX_FMT_SBGGR10:	descr = "10-bit Bayer BGBG/GRGR"; break;
1195ba300204SHans Verkuil 	case V4L2_PIX_FMT_SGBRG10:	descr = "10-bit Bayer GBGB/RGRG"; break;
1196ba300204SHans Verkuil 	case V4L2_PIX_FMT_SGRBG10:	descr = "10-bit Bayer GRGR/BGBG"; break;
1197ba300204SHans Verkuil 	case V4L2_PIX_FMT_SRGGB10:	descr = "10-bit Bayer RGRG/GBGB"; break;
1198ba300204SHans Verkuil 	case V4L2_PIX_FMT_SBGGR10P:	descr = "10-bit Bayer BGBG/GRGR Packed"; break;
1199ba300204SHans Verkuil 	case V4L2_PIX_FMT_SGBRG10P:	descr = "10-bit Bayer GBGB/RGRG Packed"; break;
1200ba300204SHans Verkuil 	case V4L2_PIX_FMT_SGRBG10P:	descr = "10-bit Bayer GRGR/BGBG Packed"; break;
1201ba300204SHans Verkuil 	case V4L2_PIX_FMT_SRGGB10P:	descr = "10-bit Bayer RGRG/GBGB Packed"; break;
1202ba300204SHans Verkuil 	case V4L2_PIX_FMT_SBGGR10ALAW8:	descr = "8-bit Bayer BGBG/GRGR (A-law)"; break;
1203ba300204SHans Verkuil 	case V4L2_PIX_FMT_SGBRG10ALAW8:	descr = "8-bit Bayer GBGB/RGRG (A-law)"; break;
1204ba300204SHans Verkuil 	case V4L2_PIX_FMT_SGRBG10ALAW8:	descr = "8-bit Bayer GRGR/BGBG (A-law)"; break;
1205ba300204SHans Verkuil 	case V4L2_PIX_FMT_SRGGB10ALAW8:	descr = "8-bit Bayer RGRG/GBGB (A-law)"; break;
1206ba300204SHans Verkuil 	case V4L2_PIX_FMT_SBGGR10DPCM8:	descr = "8-bit Bayer BGBG/GRGR (DPCM)"; break;
1207ba300204SHans Verkuil 	case V4L2_PIX_FMT_SGBRG10DPCM8:	descr = "8-bit Bayer GBGB/RGRG (DPCM)"; break;
1208ba300204SHans Verkuil 	case V4L2_PIX_FMT_SGRBG10DPCM8:	descr = "8-bit Bayer GRGR/BGBG (DPCM)"; break;
1209ba300204SHans Verkuil 	case V4L2_PIX_FMT_SRGGB10DPCM8:	descr = "8-bit Bayer RGRG/GBGB (DPCM)"; break;
1210d1b3437eSSakari Ailus 	case V4L2_PIX_FMT_SBGGR12:	descr = "12-bit Bayer BGBG/GRGR"; break;
1211d1b3437eSSakari Ailus 	case V4L2_PIX_FMT_SGBRG12:	descr = "12-bit Bayer GBGB/RGRG"; break;
1212d1b3437eSSakari Ailus 	case V4L2_PIX_FMT_SGRBG12:	descr = "12-bit Bayer GRGR/BGBG"; break;
1213d1b3437eSSakari Ailus 	case V4L2_PIX_FMT_SRGGB12:	descr = "12-bit Bayer RGRG/GBGB"; break;
1214d1b3437eSSakari Ailus 	case V4L2_PIX_FMT_SBGGR12P:	descr = "12-bit Bayer BGBG/GRGR Packed"; break;
1215d1b3437eSSakari Ailus 	case V4L2_PIX_FMT_SGBRG12P:	descr = "12-bit Bayer GBGB/RGRG Packed"; break;
1216d1b3437eSSakari Ailus 	case V4L2_PIX_FMT_SGRBG12P:	descr = "12-bit Bayer GRGR/BGBG Packed"; break;
1217d1b3437eSSakari Ailus 	case V4L2_PIX_FMT_SRGGB12P:	descr = "12-bit Bayer RGRG/GBGB Packed"; break;
1218b9a4b13cSSakari Ailus 	case V4L2_PIX_FMT_SBGGR16:	descr = "16-bit Bayer BGBG/GRGR"; break;
1219b9a4b13cSSakari Ailus 	case V4L2_PIX_FMT_SGBRG16:	descr = "16-bit Bayer GBGB/RGRG"; break;
1220b9a4b13cSSakari Ailus 	case V4L2_PIX_FMT_SGRBG16:	descr = "16-bit Bayer GRGR/BGBG"; break;
1221b9a4b13cSSakari Ailus 	case V4L2_PIX_FMT_SRGGB16:	descr = "16-bit Bayer RGRG/GBGB"; break;
122299b74277SMauro Carvalho Chehab 	case V4L2_PIX_FMT_SN9C20X_I420:	descr = "GSPCA SN9C20X I420"; break;
1223ba300204SHans Verkuil 	case V4L2_PIX_FMT_SPCA501:	descr = "GSPCA SPCA501"; break;
1224ba300204SHans Verkuil 	case V4L2_PIX_FMT_SPCA505:	descr = "GSPCA SPCA505"; break;
1225ba300204SHans Verkuil 	case V4L2_PIX_FMT_SPCA508:	descr = "GSPCA SPCA508"; break;
1226ba300204SHans Verkuil 	case V4L2_PIX_FMT_STV0680:	descr = "GSPCA STV0680"; break;
1227ba300204SHans Verkuil 	case V4L2_PIX_FMT_TM6000:	descr = "A/V + VBI Mux Packet"; break;
1228ba300204SHans Verkuil 	case V4L2_PIX_FMT_CIT_YYVYUY:	descr = "GSPCA CIT YYVYUY"; break;
1229ba300204SHans Verkuil 	case V4L2_PIX_FMT_KONICA420:	descr = "GSPCA KONICA420"; break;
123066b2ab27SRicardo Ribalda Delgado 	case V4L2_PIX_FMT_HSV24:	descr = "24-bit HSV 8-8-8"; break;
123166b2ab27SRicardo Ribalda Delgado 	case V4L2_PIX_FMT_HSV32:	descr = "32-bit XHSV 8-8-8-8"; break;
123248fc10aaSAntti Palosaari 	case V4L2_SDR_FMT_CU8:		descr = "Complex U8"; break;
123348fc10aaSAntti Palosaari 	case V4L2_SDR_FMT_CU16LE:	descr = "Complex U16LE"; break;
1234ba300204SHans Verkuil 	case V4L2_SDR_FMT_CS8:		descr = "Complex S8"; break;
1235ba300204SHans Verkuil 	case V4L2_SDR_FMT_CS14LE:	descr = "Complex S14LE"; break;
1236ba300204SHans Verkuil 	case V4L2_SDR_FMT_RU12LE:	descr = "Real U12LE"; break;
1237c28f2118SRamesh Shanmugasundaram 	case V4L2_SDR_FMT_PCU16BE:	descr = "Planar Complex U16BE"; break;
1238c28f2118SRamesh Shanmugasundaram 	case V4L2_SDR_FMT_PCU18BE:	descr = "Planar Complex U18BE"; break;
1239c28f2118SRamesh Shanmugasundaram 	case V4L2_SDR_FMT_PCU20BE:	descr = "Planar Complex U20BE"; break;
1240b2fe22d0SNick Dyer 	case V4L2_TCH_FMT_DELTA_TD16:	descr = "16-bit signed deltas"; break;
1241b2fe22d0SNick Dyer 	case V4L2_TCH_FMT_DELTA_TD08:	descr = "8-bit signed deltas"; break;
1242b2fe22d0SNick Dyer 	case V4L2_TCH_FMT_TU16:		descr = "16-bit unsigned touch data"; break;
1243b2fe22d0SNick Dyer 	case V4L2_TCH_FMT_TU08:		descr = "8-bit unsigned touch data"; break;
124414d66538SLaurent Pinchart 	case V4L2_META_FMT_VSP1_HGO:	descr = "R-Car VSP1 1-D Histogram"; break;
12455deb1c04SNiklas Söderlund 	case V4L2_META_FMT_VSP1_HGT:	descr = "R-Car VSP1 2-D Histogram"; break;
1246ba300204SHans Verkuil 
1247ba300204SHans Verkuil 	default:
1248ba300204SHans Verkuil 		/* Compressed formats */
1249ba300204SHans Verkuil 		flags = V4L2_FMT_FLAG_COMPRESSED;
1250ba300204SHans Verkuil 		switch (fmt->pixelformat) {
1251ba300204SHans Verkuil 		/* Max description length mask:	descr = "0123456789012345678901234567890" */
1252ba300204SHans Verkuil 		case V4L2_PIX_FMT_MJPEG:	descr = "Motion-JPEG"; break;
1253ba300204SHans Verkuil 		case V4L2_PIX_FMT_JPEG:		descr = "JFIF JPEG"; break;
1254ba300204SHans Verkuil 		case V4L2_PIX_FMT_DV:		descr = "1394"; break;
1255ba300204SHans Verkuil 		case V4L2_PIX_FMT_MPEG:		descr = "MPEG-1/2/4"; break;
1256ba300204SHans Verkuil 		case V4L2_PIX_FMT_H264:		descr = "H.264"; break;
1257ba300204SHans Verkuil 		case V4L2_PIX_FMT_H264_NO_SC:	descr = "H.264 (No Start Codes)"; break;
1258ba300204SHans Verkuil 		case V4L2_PIX_FMT_H264_MVC:	descr = "H.264 MVC"; break;
1259ba300204SHans Verkuil 		case V4L2_PIX_FMT_H263:		descr = "H.263"; break;
1260ba300204SHans Verkuil 		case V4L2_PIX_FMT_MPEG1:	descr = "MPEG-1 ES"; break;
1261ba300204SHans Verkuil 		case V4L2_PIX_FMT_MPEG2:	descr = "MPEG-2 ES"; break;
1262ba300204SHans Verkuil 		case V4L2_PIX_FMT_MPEG4:	descr = "MPEG-4 part 2 ES"; break;
1263ba300204SHans Verkuil 		case V4L2_PIX_FMT_XVID:		descr = "Xvid"; break;
1264ba300204SHans Verkuil 		case V4L2_PIX_FMT_VC1_ANNEX_G:	descr = "VC-1 (SMPTE 412M Annex G)"; break;
1265ba300204SHans Verkuil 		case V4L2_PIX_FMT_VC1_ANNEX_L:	descr = "VC-1 (SMPTE 412M Annex L)"; break;
1266ba300204SHans Verkuil 		case V4L2_PIX_FMT_VP8:		descr = "VP8"; break;
1267fa14a564SWu-Cheng Li 		case V4L2_PIX_FMT_VP9:		descr = "VP9"; break;
1268ba300204SHans Verkuil 		case V4L2_PIX_FMT_CPIA1:	descr = "GSPCA CPiA YUV"; break;
1269ba300204SHans Verkuil 		case V4L2_PIX_FMT_WNVA:		descr = "WNVA"; break;
1270ba300204SHans Verkuil 		case V4L2_PIX_FMT_SN9C10X:	descr = "GSPCA SN9C10X"; break;
1271ba300204SHans Verkuil 		case V4L2_PIX_FMT_PWC1:		descr = "Raw Philips Webcam Type (Old)"; break;
1272ba300204SHans Verkuil 		case V4L2_PIX_FMT_PWC2:		descr = "Raw Philips Webcam Type (New)"; break;
1273ba300204SHans Verkuil 		case V4L2_PIX_FMT_ET61X251:	descr = "GSPCA ET61X251"; break;
1274ba300204SHans Verkuil 		case V4L2_PIX_FMT_SPCA561:	descr = "GSPCA SPCA561"; break;
1275ba300204SHans Verkuil 		case V4L2_PIX_FMT_PAC207:	descr = "GSPCA PAC207"; break;
1276ba300204SHans Verkuil 		case V4L2_PIX_FMT_MR97310A:	descr = "GSPCA MR97310A"; break;
1277ba300204SHans Verkuil 		case V4L2_PIX_FMT_JL2005BCD:	descr = "GSPCA JL2005BCD"; break;
1278ba300204SHans Verkuil 		case V4L2_PIX_FMT_SN9C2028:	descr = "GSPCA SN9C2028"; break;
1279ba300204SHans Verkuil 		case V4L2_PIX_FMT_SQ905C:	descr = "GSPCA SQ905C"; break;
1280ba300204SHans Verkuil 		case V4L2_PIX_FMT_PJPG:		descr = "GSPCA PJPG"; break;
1281ba300204SHans Verkuil 		case V4L2_PIX_FMT_OV511:	descr = "GSPCA OV511"; break;
1282ba300204SHans Verkuil 		case V4L2_PIX_FMT_OV518:	descr = "GSPCA OV518"; break;
1283ba300204SHans Verkuil 		case V4L2_PIX_FMT_JPGL:		descr = "JPEG Lite"; break;
1284ba300204SHans Verkuil 		case V4L2_PIX_FMT_SE401:	descr = "GSPCA SE401"; break;
1285ba300204SHans Verkuil 		case V4L2_PIX_FMT_S5C_UYVY_JPG:	descr = "S5C73MX interleaved UYVY/JPEG"; break;
1286d4de6634STiffany Lin 		case V4L2_PIX_FMT_MT21C:	descr = "Mediatek Compressed Format"; break;
1287ba300204SHans Verkuil 		default:
1288ba300204SHans Verkuil 			WARN(1, "Unknown pixelformat 0x%08x\n", fmt->pixelformat);
1289ba300204SHans Verkuil 			if (fmt->description[0])
1290ba300204SHans Verkuil 				return;
1291ba300204SHans Verkuil 			flags = 0;
1292ba300204SHans Verkuil 			snprintf(fmt->description, sz, "%c%c%c%c%s",
1293ba300204SHans Verkuil 					(char)(fmt->pixelformat & 0x7f),
1294ba300204SHans Verkuil 					(char)((fmt->pixelformat >> 8) & 0x7f),
1295ba300204SHans Verkuil 					(char)((fmt->pixelformat >> 16) & 0x7f),
1296ba300204SHans Verkuil 					(char)((fmt->pixelformat >> 24) & 0x7f),
1297ba300204SHans Verkuil 					(fmt->pixelformat & (1 << 31)) ? "-BE" : "");
1298ba300204SHans Verkuil 			break;
1299ba300204SHans Verkuil 		}
1300ba300204SHans Verkuil 	}
1301ba300204SHans Verkuil 
1302ba300204SHans Verkuil 	if (descr)
1303ba300204SHans Verkuil 		WARN_ON(strlcpy(fmt->description, descr, sz) >= sz);
1304ba300204SHans Verkuil 	fmt->flags = flags;
1305ba300204SHans Verkuil }
1306ba300204SHans Verkuil 
13075bc3cb74SMauro Carvalho Chehab static int v4l_enum_fmt(const struct v4l2_ioctl_ops *ops,
13085bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
13095bc3cb74SMauro Carvalho Chehab {
13105bc3cb74SMauro Carvalho Chehab 	struct v4l2_fmtdesc *p = arg;
13114b20259fSHans Verkuil 	struct video_device *vfd = video_devdata(file);
1312ce71bbc9SHans Verkuil 	bool is_vid = vfd->vfl_type == VFL_TYPE_GRABBER;
1313ce71bbc9SHans Verkuil 	bool is_sdr = vfd->vfl_type == VFL_TYPE_SDR;
1314b2fe22d0SNick Dyer 	bool is_tch = vfd->vfl_type == VFL_TYPE_TOUCH;
13154b20259fSHans Verkuil 	bool is_rx = vfd->vfl_dir != VFL_DIR_TX;
13164b20259fSHans Verkuil 	bool is_tx = vfd->vfl_dir != VFL_DIR_RX;
1317ba300204SHans Verkuil 	int ret = -EINVAL;
13185bc3cb74SMauro Carvalho Chehab 
13195bc3cb74SMauro Carvalho Chehab 	switch (p->type) {
13205bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
1321b2fe22d0SNick Dyer 		if (unlikely(!is_rx || (!is_vid && !is_tch) || !ops->vidioc_enum_fmt_vid_cap))
13225bc3cb74SMauro Carvalho Chehab 			break;
1323ba300204SHans Verkuil 		ret = ops->vidioc_enum_fmt_vid_cap(file, fh, arg);
1324ba300204SHans Verkuil 		break;
13255bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
1326ce71bbc9SHans Verkuil 		if (unlikely(!is_rx || !is_vid || !ops->vidioc_enum_fmt_vid_cap_mplane))
13275bc3cb74SMauro Carvalho Chehab 			break;
1328ba300204SHans Verkuil 		ret = ops->vidioc_enum_fmt_vid_cap_mplane(file, fh, arg);
1329ba300204SHans Verkuil 		break;
13305bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_OVERLAY:
1331ce71bbc9SHans Verkuil 		if (unlikely(!is_rx || !is_vid || !ops->vidioc_enum_fmt_vid_overlay))
13325bc3cb74SMauro Carvalho Chehab 			break;
1333ba300204SHans Verkuil 		ret = ops->vidioc_enum_fmt_vid_overlay(file, fh, arg);
1334ba300204SHans Verkuil 		break;
13355bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_OUTPUT:
1336ce71bbc9SHans Verkuil 		if (unlikely(!is_tx || !is_vid || !ops->vidioc_enum_fmt_vid_out))
13375bc3cb74SMauro Carvalho Chehab 			break;
1338ba300204SHans Verkuil 		ret = ops->vidioc_enum_fmt_vid_out(file, fh, arg);
1339ba300204SHans Verkuil 		break;
13405bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
1341ce71bbc9SHans Verkuil 		if (unlikely(!is_tx || !is_vid || !ops->vidioc_enum_fmt_vid_out_mplane))
13425bc3cb74SMauro Carvalho Chehab 			break;
1343ba300204SHans Verkuil 		ret = ops->vidioc_enum_fmt_vid_out_mplane(file, fh, arg);
1344ba300204SHans Verkuil 		break;
1345582c52cbSAntti Palosaari 	case V4L2_BUF_TYPE_SDR_CAPTURE:
1346ce71bbc9SHans Verkuil 		if (unlikely(!is_rx || !is_sdr || !ops->vidioc_enum_fmt_sdr_cap))
1347582c52cbSAntti Palosaari 			break;
1348ba300204SHans Verkuil 		ret = ops->vidioc_enum_fmt_sdr_cap(file, fh, arg);
1349ba300204SHans Verkuil 		break;
13509effc72fSAntti Palosaari 	case V4L2_BUF_TYPE_SDR_OUTPUT:
13519effc72fSAntti Palosaari 		if (unlikely(!is_tx || !is_sdr || !ops->vidioc_enum_fmt_sdr_out))
13529effc72fSAntti Palosaari 			break;
13539effc72fSAntti Palosaari 		ret = ops->vidioc_enum_fmt_sdr_out(file, fh, arg);
13549effc72fSAntti Palosaari 		break;
1355fb9ffa6aSLaurent Pinchart 	case V4L2_BUF_TYPE_META_CAPTURE:
1356fb9ffa6aSLaurent Pinchart 		if (unlikely(!is_rx || !is_vid || !ops->vidioc_enum_fmt_meta_cap))
1357fb9ffa6aSLaurent Pinchart 			break;
1358fb9ffa6aSLaurent Pinchart 		ret = ops->vidioc_enum_fmt_meta_cap(file, fh, arg);
1359fb9ffa6aSLaurent Pinchart 		break;
13605bc3cb74SMauro Carvalho Chehab 	}
1361ba300204SHans Verkuil 	if (ret == 0)
1362ba300204SHans Verkuil 		v4l_fill_fmtdesc(p);
1363ba300204SHans Verkuil 	return ret;
13645bc3cb74SMauro Carvalho Chehab }
13655bc3cb74SMauro Carvalho Chehab 
13665bc3cb74SMauro Carvalho Chehab static int v4l_g_fmt(const struct v4l2_ioctl_ops *ops,
13675bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
13685bc3cb74SMauro Carvalho Chehab {
13695bc3cb74SMauro Carvalho Chehab 	struct v4l2_format *p = arg;
13704b20259fSHans Verkuil 	struct video_device *vfd = video_devdata(file);
13714b20259fSHans Verkuil 	bool is_vid = vfd->vfl_type == VFL_TYPE_GRABBER;
1372582c52cbSAntti Palosaari 	bool is_sdr = vfd->vfl_type == VFL_TYPE_SDR;
1373b2fe22d0SNick Dyer 	bool is_tch = vfd->vfl_type == VFL_TYPE_TOUCH;
13744b20259fSHans Verkuil 	bool is_rx = vfd->vfl_dir != VFL_DIR_TX;
13754b20259fSHans Verkuil 	bool is_tx = vfd->vfl_dir != VFL_DIR_RX;
1376d52e2381SLaurent Pinchart 	int ret;
1377d52e2381SLaurent Pinchart 
1378e5ce558aSHans Verkuil 	/*
1379e5ce558aSHans Verkuil 	 * fmt can't be cleared for these overlay types due to the 'clips'
1380e5ce558aSHans Verkuil 	 * 'clipcount' and 'bitmap' pointers in struct v4l2_window.
1381e5ce558aSHans Verkuil 	 * Those are provided by the user. So handle these two overlay types
1382e5ce558aSHans Verkuil 	 * first, and then just do a simple memset for the other types.
1383e5ce558aSHans Verkuil 	 */
1384e5ce558aSHans Verkuil 	switch (p->type) {
1385e5ce558aSHans Verkuil 	case V4L2_BUF_TYPE_VIDEO_OVERLAY:
1386e5ce558aSHans Verkuil 	case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: {
13874d1afa51SHans Verkuil 		struct v4l2_clip __user *clips = p->fmt.win.clips;
1388e5ce558aSHans Verkuil 		u32 clipcount = p->fmt.win.clipcount;
13894d1afa51SHans Verkuil 		void __user *bitmap = p->fmt.win.bitmap;
1390e5ce558aSHans Verkuil 
1391e5ce558aSHans Verkuil 		memset(&p->fmt, 0, sizeof(p->fmt));
1392e5ce558aSHans Verkuil 		p->fmt.win.clips = clips;
1393e5ce558aSHans Verkuil 		p->fmt.win.clipcount = clipcount;
1394e5ce558aSHans Verkuil 		p->fmt.win.bitmap = bitmap;
1395e5ce558aSHans Verkuil 		break;
1396e5ce558aSHans Verkuil 	}
1397e5ce558aSHans Verkuil 	default:
1398e5ce558aSHans Verkuil 		memset(&p->fmt, 0, sizeof(p->fmt));
1399e5ce558aSHans Verkuil 		break;
1400e5ce558aSHans Verkuil 	}
1401e5ce558aSHans Verkuil 
14025bc3cb74SMauro Carvalho Chehab 	switch (p->type) {
14035bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
1404b2fe22d0SNick Dyer 		if (unlikely(!is_rx || (!is_vid && !is_tch) || !ops->vidioc_g_fmt_vid_cap))
14055bc3cb74SMauro Carvalho Chehab 			break;
140648f2650aSHans Verkuil 		p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC;
1407d52e2381SLaurent Pinchart 		ret = ops->vidioc_g_fmt_vid_cap(file, fh, arg);
140848f2650aSHans Verkuil 		/* just in case the driver zeroed it again */
1409d52e2381SLaurent Pinchart 		p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC;
1410d52e2381SLaurent Pinchart 		return ret;
14115bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
14124b20259fSHans Verkuil 		if (unlikely(!is_rx || !is_vid || !ops->vidioc_g_fmt_vid_cap_mplane))
14135bc3cb74SMauro Carvalho Chehab 			break;
14145bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_g_fmt_vid_cap_mplane(file, fh, arg);
14155bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_OVERLAY:
14164b20259fSHans Verkuil 		if (unlikely(!is_rx || !is_vid || !ops->vidioc_g_fmt_vid_overlay))
14175bc3cb74SMauro Carvalho Chehab 			break;
14185bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_g_fmt_vid_overlay(file, fh, arg);
14194b20259fSHans Verkuil 	case V4L2_BUF_TYPE_VBI_CAPTURE:
14204b20259fSHans Verkuil 		if (unlikely(!is_rx || is_vid || !ops->vidioc_g_fmt_vbi_cap))
14214b20259fSHans Verkuil 			break;
14224b20259fSHans Verkuil 		return ops->vidioc_g_fmt_vbi_cap(file, fh, arg);
14234b20259fSHans Verkuil 	case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
14244b20259fSHans Verkuil 		if (unlikely(!is_rx || is_vid || !ops->vidioc_g_fmt_sliced_vbi_cap))
14254b20259fSHans Verkuil 			break;
14264b20259fSHans Verkuil 		return ops->vidioc_g_fmt_sliced_vbi_cap(file, fh, arg);
14275bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_OUTPUT:
14284b20259fSHans Verkuil 		if (unlikely(!is_tx || !is_vid || !ops->vidioc_g_fmt_vid_out))
14295bc3cb74SMauro Carvalho Chehab 			break;
143048f2650aSHans Verkuil 		p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC;
1431d52e2381SLaurent Pinchart 		ret = ops->vidioc_g_fmt_vid_out(file, fh, arg);
143248f2650aSHans Verkuil 		/* just in case the driver zeroed it again */
1433d52e2381SLaurent Pinchart 		p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC;
1434d52e2381SLaurent Pinchart 		return ret;
14355bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
14364b20259fSHans Verkuil 		if (unlikely(!is_tx || !is_vid || !ops->vidioc_g_fmt_vid_out_mplane))
14375bc3cb74SMauro Carvalho Chehab 			break;
14385bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_g_fmt_vid_out_mplane(file, fh, arg);
14395bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
14404b20259fSHans Verkuil 		if (unlikely(!is_tx || !is_vid || !ops->vidioc_g_fmt_vid_out_overlay))
14415bc3cb74SMauro Carvalho Chehab 			break;
14425bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_g_fmt_vid_out_overlay(file, fh, arg);
14435bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VBI_OUTPUT:
14444b20259fSHans Verkuil 		if (unlikely(!is_tx || is_vid || !ops->vidioc_g_fmt_vbi_out))
14455bc3cb74SMauro Carvalho Chehab 			break;
14465bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_g_fmt_vbi_out(file, fh, arg);
14475bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
14484b20259fSHans Verkuil 		if (unlikely(!is_tx || is_vid || !ops->vidioc_g_fmt_sliced_vbi_out))
14495bc3cb74SMauro Carvalho Chehab 			break;
14505bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_g_fmt_sliced_vbi_out(file, fh, arg);
1451582c52cbSAntti Palosaari 	case V4L2_BUF_TYPE_SDR_CAPTURE:
1452582c52cbSAntti Palosaari 		if (unlikely(!is_rx || !is_sdr || !ops->vidioc_g_fmt_sdr_cap))
1453582c52cbSAntti Palosaari 			break;
1454582c52cbSAntti Palosaari 		return ops->vidioc_g_fmt_sdr_cap(file, fh, arg);
14559effc72fSAntti Palosaari 	case V4L2_BUF_TYPE_SDR_OUTPUT:
14569effc72fSAntti Palosaari 		if (unlikely(!is_tx || !is_sdr || !ops->vidioc_g_fmt_sdr_out))
14579effc72fSAntti Palosaari 			break;
14589effc72fSAntti Palosaari 		return ops->vidioc_g_fmt_sdr_out(file, fh, arg);
1459fb9ffa6aSLaurent Pinchart 	case V4L2_BUF_TYPE_META_CAPTURE:
1460fb9ffa6aSLaurent Pinchart 		if (unlikely(!is_rx || !is_vid || !ops->vidioc_g_fmt_meta_cap))
1461fb9ffa6aSLaurent Pinchart 			break;
1462fb9ffa6aSLaurent Pinchart 		return ops->vidioc_g_fmt_meta_cap(file, fh, arg);
14635bc3cb74SMauro Carvalho Chehab 	}
14645bc3cb74SMauro Carvalho Chehab 	return -EINVAL;
14655bc3cb74SMauro Carvalho Chehab }
14665bc3cb74SMauro Carvalho Chehab 
1467b2fe22d0SNick Dyer static void v4l_pix_format_touch(struct v4l2_pix_format *p)
1468b2fe22d0SNick Dyer {
1469b2fe22d0SNick Dyer 	/*
1470b2fe22d0SNick Dyer 	 * The v4l2_pix_format structure contains fields that make no sense for
1471b2fe22d0SNick Dyer 	 * touch. Set them to default values in this case.
1472b2fe22d0SNick Dyer 	 */
1473b2fe22d0SNick Dyer 
1474b2fe22d0SNick Dyer 	p->field = V4L2_FIELD_NONE;
1475b2fe22d0SNick Dyer 	p->colorspace = V4L2_COLORSPACE_RAW;
1476b2fe22d0SNick Dyer 	p->flags = 0;
1477b2fe22d0SNick Dyer 	p->ycbcr_enc = 0;
1478b2fe22d0SNick Dyer 	p->quantization = 0;
1479b2fe22d0SNick Dyer 	p->xfer_func = 0;
1480b2fe22d0SNick Dyer }
1481b2fe22d0SNick Dyer 
14825bc3cb74SMauro Carvalho Chehab static int v4l_s_fmt(const struct v4l2_ioctl_ops *ops,
14835bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
14845bc3cb74SMauro Carvalho Chehab {
14855bc3cb74SMauro Carvalho Chehab 	struct v4l2_format *p = arg;
14864b20259fSHans Verkuil 	struct video_device *vfd = video_devdata(file);
14874b20259fSHans Verkuil 	bool is_vid = vfd->vfl_type == VFL_TYPE_GRABBER;
1488582c52cbSAntti Palosaari 	bool is_sdr = vfd->vfl_type == VFL_TYPE_SDR;
1489b2fe22d0SNick Dyer 	bool is_tch = vfd->vfl_type == VFL_TYPE_TOUCH;
14904b20259fSHans Verkuil 	bool is_rx = vfd->vfl_dir != VFL_DIR_TX;
14914b20259fSHans Verkuil 	bool is_tx = vfd->vfl_dir != VFL_DIR_RX;
149248f2650aSHans Verkuil 	int ret;
14935bc3cb74SMauro Carvalho Chehab 
149477fa4e07SShuah Khan 	ret = v4l_enable_media_source(vfd);
149577fa4e07SShuah Khan 	if (ret)
149677fa4e07SShuah Khan 		return ret;
1497d52e2381SLaurent Pinchart 	v4l_sanitize_format(p);
1498d52e2381SLaurent Pinchart 
14995bc3cb74SMauro Carvalho Chehab 	switch (p->type) {
15005bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
1501b2fe22d0SNick Dyer 		if (unlikely(!is_rx || (!is_vid && !is_tch) || !ops->vidioc_s_fmt_vid_cap))
15025bc3cb74SMauro Carvalho Chehab 			break;
15035bc3cb74SMauro Carvalho Chehab 		CLEAR_AFTER_FIELD(p, fmt.pix);
150448f2650aSHans Verkuil 		ret = ops->vidioc_s_fmt_vid_cap(file, fh, arg);
150548f2650aSHans Verkuil 		/* just in case the driver zeroed it again */
150648f2650aSHans Verkuil 		p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC;
1507b2fe22d0SNick Dyer 		if (is_tch)
1508b2fe22d0SNick Dyer 			v4l_pix_format_touch(&p->fmt.pix);
150948f2650aSHans Verkuil 		return ret;
15105bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
15114b20259fSHans Verkuil 		if (unlikely(!is_rx || !is_vid || !ops->vidioc_s_fmt_vid_cap_mplane))
15125bc3cb74SMauro Carvalho Chehab 			break;
1513c49148e8SLaurent Pinchart 		CLEAR_AFTER_FIELD(p, fmt.pix_mp.xfer_func);
15145bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_s_fmt_vid_cap_mplane(file, fh, arg);
15155bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_OVERLAY:
15164b20259fSHans Verkuil 		if (unlikely(!is_rx || !is_vid || !ops->vidioc_s_fmt_vid_overlay))
15175bc3cb74SMauro Carvalho Chehab 			break;
15185bc3cb74SMauro Carvalho Chehab 		CLEAR_AFTER_FIELD(p, fmt.win);
15195bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_s_fmt_vid_overlay(file, fh, arg);
15204b20259fSHans Verkuil 	case V4L2_BUF_TYPE_VBI_CAPTURE:
15214b20259fSHans Verkuil 		if (unlikely(!is_rx || is_vid || !ops->vidioc_s_fmt_vbi_cap))
15224b20259fSHans Verkuil 			break;
15234b20259fSHans Verkuil 		CLEAR_AFTER_FIELD(p, fmt.vbi);
15244b20259fSHans Verkuil 		return ops->vidioc_s_fmt_vbi_cap(file, fh, arg);
15254b20259fSHans Verkuil 	case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
15264b20259fSHans Verkuil 		if (unlikely(!is_rx || is_vid || !ops->vidioc_s_fmt_sliced_vbi_cap))
15274b20259fSHans Verkuil 			break;
15284b20259fSHans Verkuil 		CLEAR_AFTER_FIELD(p, fmt.sliced);
15294b20259fSHans Verkuil 		return ops->vidioc_s_fmt_sliced_vbi_cap(file, fh, arg);
15305bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_OUTPUT:
15314b20259fSHans Verkuil 		if (unlikely(!is_tx || !is_vid || !ops->vidioc_s_fmt_vid_out))
15325bc3cb74SMauro Carvalho Chehab 			break;
15335bc3cb74SMauro Carvalho Chehab 		CLEAR_AFTER_FIELD(p, fmt.pix);
153448f2650aSHans Verkuil 		ret = ops->vidioc_s_fmt_vid_out(file, fh, arg);
153548f2650aSHans Verkuil 		/* just in case the driver zeroed it again */
153648f2650aSHans Verkuil 		p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC;
153748f2650aSHans Verkuil 		return ret;
15385bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
15394b20259fSHans Verkuil 		if (unlikely(!is_tx || !is_vid || !ops->vidioc_s_fmt_vid_out_mplane))
15405bc3cb74SMauro Carvalho Chehab 			break;
1541c49148e8SLaurent Pinchart 		CLEAR_AFTER_FIELD(p, fmt.pix_mp.xfer_func);
15425bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_s_fmt_vid_out_mplane(file, fh, arg);
15435bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
15444b20259fSHans Verkuil 		if (unlikely(!is_tx || !is_vid || !ops->vidioc_s_fmt_vid_out_overlay))
15455bc3cb74SMauro Carvalho Chehab 			break;
15465bc3cb74SMauro Carvalho Chehab 		CLEAR_AFTER_FIELD(p, fmt.win);
15475bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_s_fmt_vid_out_overlay(file, fh, arg);
15485bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VBI_OUTPUT:
15494b20259fSHans Verkuil 		if (unlikely(!is_tx || is_vid || !ops->vidioc_s_fmt_vbi_out))
15505bc3cb74SMauro Carvalho Chehab 			break;
15515bc3cb74SMauro Carvalho Chehab 		CLEAR_AFTER_FIELD(p, fmt.vbi);
15525bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_s_fmt_vbi_out(file, fh, arg);
15535bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
15544b20259fSHans Verkuil 		if (unlikely(!is_tx || is_vid || !ops->vidioc_s_fmt_sliced_vbi_out))
15555bc3cb74SMauro Carvalho Chehab 			break;
15565bc3cb74SMauro Carvalho Chehab 		CLEAR_AFTER_FIELD(p, fmt.sliced);
15575bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_s_fmt_sliced_vbi_out(file, fh, arg);
1558582c52cbSAntti Palosaari 	case V4L2_BUF_TYPE_SDR_CAPTURE:
1559582c52cbSAntti Palosaari 		if (unlikely(!is_rx || !is_sdr || !ops->vidioc_s_fmt_sdr_cap))
1560582c52cbSAntti Palosaari 			break;
1561582c52cbSAntti Palosaari 		CLEAR_AFTER_FIELD(p, fmt.sdr);
1562582c52cbSAntti Palosaari 		return ops->vidioc_s_fmt_sdr_cap(file, fh, arg);
15639effc72fSAntti Palosaari 	case V4L2_BUF_TYPE_SDR_OUTPUT:
15649effc72fSAntti Palosaari 		if (unlikely(!is_tx || !is_sdr || !ops->vidioc_s_fmt_sdr_out))
15659effc72fSAntti Palosaari 			break;
15669effc72fSAntti Palosaari 		CLEAR_AFTER_FIELD(p, fmt.sdr);
15679effc72fSAntti Palosaari 		return ops->vidioc_s_fmt_sdr_out(file, fh, arg);
1568fb9ffa6aSLaurent Pinchart 	case V4L2_BUF_TYPE_META_CAPTURE:
1569fb9ffa6aSLaurent Pinchart 		if (unlikely(!is_rx || !is_vid || !ops->vidioc_s_fmt_meta_cap))
1570fb9ffa6aSLaurent Pinchart 			break;
1571fb9ffa6aSLaurent Pinchart 		CLEAR_AFTER_FIELD(p, fmt.meta);
1572fb9ffa6aSLaurent Pinchart 		return ops->vidioc_s_fmt_meta_cap(file, fh, arg);
15735bc3cb74SMauro Carvalho Chehab 	}
15745bc3cb74SMauro Carvalho Chehab 	return -EINVAL;
15755bc3cb74SMauro Carvalho Chehab }
15765bc3cb74SMauro Carvalho Chehab 
15775bc3cb74SMauro Carvalho Chehab static int v4l_try_fmt(const struct v4l2_ioctl_ops *ops,
15785bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
15795bc3cb74SMauro Carvalho Chehab {
15805bc3cb74SMauro Carvalho Chehab 	struct v4l2_format *p = arg;
15814b20259fSHans Verkuil 	struct video_device *vfd = video_devdata(file);
15824b20259fSHans Verkuil 	bool is_vid = vfd->vfl_type == VFL_TYPE_GRABBER;
1583582c52cbSAntti Palosaari 	bool is_sdr = vfd->vfl_type == VFL_TYPE_SDR;
1584b2fe22d0SNick Dyer 	bool is_tch = vfd->vfl_type == VFL_TYPE_TOUCH;
15854b20259fSHans Verkuil 	bool is_rx = vfd->vfl_dir != VFL_DIR_TX;
15864b20259fSHans Verkuil 	bool is_tx = vfd->vfl_dir != VFL_DIR_RX;
158748f2650aSHans Verkuil 	int ret;
15885bc3cb74SMauro Carvalho Chehab 
1589d52e2381SLaurent Pinchart 	v4l_sanitize_format(p);
1590d52e2381SLaurent Pinchart 
15915bc3cb74SMauro Carvalho Chehab 	switch (p->type) {
15925bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
1593b2fe22d0SNick Dyer 		if (unlikely(!is_rx || (!is_vid && !is_tch) || !ops->vidioc_try_fmt_vid_cap))
15945bc3cb74SMauro Carvalho Chehab 			break;
15955bc3cb74SMauro Carvalho Chehab 		CLEAR_AFTER_FIELD(p, fmt.pix);
159648f2650aSHans Verkuil 		ret = ops->vidioc_try_fmt_vid_cap(file, fh, arg);
159748f2650aSHans Verkuil 		/* just in case the driver zeroed it again */
159848f2650aSHans Verkuil 		p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC;
159948f2650aSHans Verkuil 		return ret;
16005bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
16014b20259fSHans Verkuil 		if (unlikely(!is_rx || !is_vid || !ops->vidioc_try_fmt_vid_cap_mplane))
16025bc3cb74SMauro Carvalho Chehab 			break;
1603c49148e8SLaurent Pinchart 		CLEAR_AFTER_FIELD(p, fmt.pix_mp.xfer_func);
16045bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_try_fmt_vid_cap_mplane(file, fh, arg);
16055bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_OVERLAY:
16064b20259fSHans Verkuil 		if (unlikely(!is_rx || !is_vid || !ops->vidioc_try_fmt_vid_overlay))
16075bc3cb74SMauro Carvalho Chehab 			break;
16085bc3cb74SMauro Carvalho Chehab 		CLEAR_AFTER_FIELD(p, fmt.win);
16095bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_try_fmt_vid_overlay(file, fh, arg);
16104b20259fSHans Verkuil 	case V4L2_BUF_TYPE_VBI_CAPTURE:
16114b20259fSHans Verkuil 		if (unlikely(!is_rx || is_vid || !ops->vidioc_try_fmt_vbi_cap))
16124b20259fSHans Verkuil 			break;
16134b20259fSHans Verkuil 		CLEAR_AFTER_FIELD(p, fmt.vbi);
16144b20259fSHans Verkuil 		return ops->vidioc_try_fmt_vbi_cap(file, fh, arg);
16154b20259fSHans Verkuil 	case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
16164b20259fSHans Verkuil 		if (unlikely(!is_rx || is_vid || !ops->vidioc_try_fmt_sliced_vbi_cap))
16174b20259fSHans Verkuil 			break;
16184b20259fSHans Verkuil 		CLEAR_AFTER_FIELD(p, fmt.sliced);
16194b20259fSHans Verkuil 		return ops->vidioc_try_fmt_sliced_vbi_cap(file, fh, arg);
16205bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_OUTPUT:
16214b20259fSHans Verkuil 		if (unlikely(!is_tx || !is_vid || !ops->vidioc_try_fmt_vid_out))
16225bc3cb74SMauro Carvalho Chehab 			break;
16235bc3cb74SMauro Carvalho Chehab 		CLEAR_AFTER_FIELD(p, fmt.pix);
162448f2650aSHans Verkuil 		ret = ops->vidioc_try_fmt_vid_out(file, fh, arg);
162548f2650aSHans Verkuil 		/* just in case the driver zeroed it again */
162648f2650aSHans Verkuil 		p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC;
162748f2650aSHans Verkuil 		return ret;
16285bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
16294b20259fSHans Verkuil 		if (unlikely(!is_tx || !is_vid || !ops->vidioc_try_fmt_vid_out_mplane))
16305bc3cb74SMauro Carvalho Chehab 			break;
1631c49148e8SLaurent Pinchart 		CLEAR_AFTER_FIELD(p, fmt.pix_mp.xfer_func);
16325bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_try_fmt_vid_out_mplane(file, fh, arg);
16335bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
16344b20259fSHans Verkuil 		if (unlikely(!is_tx || !is_vid || !ops->vidioc_try_fmt_vid_out_overlay))
16355bc3cb74SMauro Carvalho Chehab 			break;
16365bc3cb74SMauro Carvalho Chehab 		CLEAR_AFTER_FIELD(p, fmt.win);
16375bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_try_fmt_vid_out_overlay(file, fh, arg);
16385bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VBI_OUTPUT:
16394b20259fSHans Verkuil 		if (unlikely(!is_tx || is_vid || !ops->vidioc_try_fmt_vbi_out))
16405bc3cb74SMauro Carvalho Chehab 			break;
16415bc3cb74SMauro Carvalho Chehab 		CLEAR_AFTER_FIELD(p, fmt.vbi);
16425bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_try_fmt_vbi_out(file, fh, arg);
16435bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
16444b20259fSHans Verkuil 		if (unlikely(!is_tx || is_vid || !ops->vidioc_try_fmt_sliced_vbi_out))
16455bc3cb74SMauro Carvalho Chehab 			break;
16465bc3cb74SMauro Carvalho Chehab 		CLEAR_AFTER_FIELD(p, fmt.sliced);
16475bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_try_fmt_sliced_vbi_out(file, fh, arg);
1648582c52cbSAntti Palosaari 	case V4L2_BUF_TYPE_SDR_CAPTURE:
1649582c52cbSAntti Palosaari 		if (unlikely(!is_rx || !is_sdr || !ops->vidioc_try_fmt_sdr_cap))
1650582c52cbSAntti Palosaari 			break;
1651582c52cbSAntti Palosaari 		CLEAR_AFTER_FIELD(p, fmt.sdr);
1652582c52cbSAntti Palosaari 		return ops->vidioc_try_fmt_sdr_cap(file, fh, arg);
16539effc72fSAntti Palosaari 	case V4L2_BUF_TYPE_SDR_OUTPUT:
16549effc72fSAntti Palosaari 		if (unlikely(!is_tx || !is_sdr || !ops->vidioc_try_fmt_sdr_out))
16559effc72fSAntti Palosaari 			break;
16569effc72fSAntti Palosaari 		CLEAR_AFTER_FIELD(p, fmt.sdr);
16579effc72fSAntti Palosaari 		return ops->vidioc_try_fmt_sdr_out(file, fh, arg);
1658fb9ffa6aSLaurent Pinchart 	case V4L2_BUF_TYPE_META_CAPTURE:
1659fb9ffa6aSLaurent Pinchart 		if (unlikely(!is_rx || !is_vid || !ops->vidioc_try_fmt_meta_cap))
1660fb9ffa6aSLaurent Pinchart 			break;
1661fb9ffa6aSLaurent Pinchart 		CLEAR_AFTER_FIELD(p, fmt.meta);
1662fb9ffa6aSLaurent Pinchart 		return ops->vidioc_try_fmt_meta_cap(file, fh, arg);
16635bc3cb74SMauro Carvalho Chehab 	}
16645bc3cb74SMauro Carvalho Chehab 	return -EINVAL;
16655bc3cb74SMauro Carvalho Chehab }
16665bc3cb74SMauro Carvalho Chehab 
16675bc3cb74SMauro Carvalho Chehab static int v4l_streamon(const struct v4l2_ioctl_ops *ops,
16685bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
16695bc3cb74SMauro Carvalho Chehab {
16705bc3cb74SMauro Carvalho Chehab 	return ops->vidioc_streamon(file, fh, *(unsigned int *)arg);
16715bc3cb74SMauro Carvalho Chehab }
16725bc3cb74SMauro Carvalho Chehab 
16735bc3cb74SMauro Carvalho Chehab static int v4l_streamoff(const struct v4l2_ioctl_ops *ops,
16745bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
16755bc3cb74SMauro Carvalho Chehab {
16765bc3cb74SMauro Carvalho Chehab 	return ops->vidioc_streamoff(file, fh, *(unsigned int *)arg);
16775bc3cb74SMauro Carvalho Chehab }
16785bc3cb74SMauro Carvalho Chehab 
16795bc3cb74SMauro Carvalho Chehab static int v4l_g_tuner(const struct v4l2_ioctl_ops *ops,
16805bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
16815bc3cb74SMauro Carvalho Chehab {
16825bc3cb74SMauro Carvalho Chehab 	struct video_device *vfd = video_devdata(file);
16835bc3cb74SMauro Carvalho Chehab 	struct v4l2_tuner *p = arg;
16845bc3cb74SMauro Carvalho Chehab 	int err;
16855bc3cb74SMauro Carvalho Chehab 
16865bc3cb74SMauro Carvalho Chehab 	p->type = (vfd->vfl_type == VFL_TYPE_RADIO) ?
16875bc3cb74SMauro Carvalho Chehab 			V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
16885bc3cb74SMauro Carvalho Chehab 	err = ops->vidioc_g_tuner(file, fh, p);
16895bc3cb74SMauro Carvalho Chehab 	if (!err)
16905bc3cb74SMauro Carvalho Chehab 		p->capability |= V4L2_TUNER_CAP_FREQ_BANDS;
16915bc3cb74SMauro Carvalho Chehab 	return err;
16925bc3cb74SMauro Carvalho Chehab }
16935bc3cb74SMauro Carvalho Chehab 
16945bc3cb74SMauro Carvalho Chehab static int v4l_s_tuner(const struct v4l2_ioctl_ops *ops,
16955bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
16965bc3cb74SMauro Carvalho Chehab {
16975bc3cb74SMauro Carvalho Chehab 	struct video_device *vfd = video_devdata(file);
16985bc3cb74SMauro Carvalho Chehab 	struct v4l2_tuner *p = arg;
169977fa4e07SShuah Khan 	int ret;
17005bc3cb74SMauro Carvalho Chehab 
170177fa4e07SShuah Khan 	ret = v4l_enable_media_source(vfd);
170277fa4e07SShuah Khan 	if (ret)
170377fa4e07SShuah Khan 		return ret;
17045bc3cb74SMauro Carvalho Chehab 	p->type = (vfd->vfl_type == VFL_TYPE_RADIO) ?
17055bc3cb74SMauro Carvalho Chehab 			V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
17065bc3cb74SMauro Carvalho Chehab 	return ops->vidioc_s_tuner(file, fh, p);
17075bc3cb74SMauro Carvalho Chehab }
17085bc3cb74SMauro Carvalho Chehab 
17095bc3cb74SMauro Carvalho Chehab static int v4l_g_modulator(const struct v4l2_ioctl_ops *ops,
17105bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
17115bc3cb74SMauro Carvalho Chehab {
17124124a3c4SAntti Palosaari 	struct video_device *vfd = video_devdata(file);
17135bc3cb74SMauro Carvalho Chehab 	struct v4l2_modulator *p = arg;
17145bc3cb74SMauro Carvalho Chehab 	int err;
17155bc3cb74SMauro Carvalho Chehab 
17164124a3c4SAntti Palosaari 	if (vfd->vfl_type == VFL_TYPE_RADIO)
17174124a3c4SAntti Palosaari 		p->type = V4L2_TUNER_RADIO;
17184124a3c4SAntti Palosaari 
17195bc3cb74SMauro Carvalho Chehab 	err = ops->vidioc_g_modulator(file, fh, p);
17205bc3cb74SMauro Carvalho Chehab 	if (!err)
17215bc3cb74SMauro Carvalho Chehab 		p->capability |= V4L2_TUNER_CAP_FREQ_BANDS;
17225bc3cb74SMauro Carvalho Chehab 	return err;
17235bc3cb74SMauro Carvalho Chehab }
17245bc3cb74SMauro Carvalho Chehab 
17254124a3c4SAntti Palosaari static int v4l_s_modulator(const struct v4l2_ioctl_ops *ops,
17264124a3c4SAntti Palosaari 				struct file *file, void *fh, void *arg)
17274124a3c4SAntti Palosaari {
17284124a3c4SAntti Palosaari 	struct video_device *vfd = video_devdata(file);
17294124a3c4SAntti Palosaari 	struct v4l2_modulator *p = arg;
17304124a3c4SAntti Palosaari 
17314124a3c4SAntti Palosaari 	if (vfd->vfl_type == VFL_TYPE_RADIO)
17324124a3c4SAntti Palosaari 		p->type = V4L2_TUNER_RADIO;
17334124a3c4SAntti Palosaari 
17344124a3c4SAntti Palosaari 	return ops->vidioc_s_modulator(file, fh, p);
17354124a3c4SAntti Palosaari }
17364124a3c4SAntti Palosaari 
17375bc3cb74SMauro Carvalho Chehab static int v4l_g_frequency(const struct v4l2_ioctl_ops *ops,
17385bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
17395bc3cb74SMauro Carvalho Chehab {
17405bc3cb74SMauro Carvalho Chehab 	struct video_device *vfd = video_devdata(file);
17415bc3cb74SMauro Carvalho Chehab 	struct v4l2_frequency *p = arg;
17425bc3cb74SMauro Carvalho Chehab 
174384099a28SAntti Palosaari 	if (vfd->vfl_type == VFL_TYPE_SDR)
1744f3c3ececSAntti Palosaari 		p->type = V4L2_TUNER_SDR;
174584099a28SAntti Palosaari 	else
17465bc3cb74SMauro Carvalho Chehab 		p->type = (vfd->vfl_type == VFL_TYPE_RADIO) ?
17475bc3cb74SMauro Carvalho Chehab 				V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
17485bc3cb74SMauro Carvalho Chehab 	return ops->vidioc_g_frequency(file, fh, p);
17495bc3cb74SMauro Carvalho Chehab }
17505bc3cb74SMauro Carvalho Chehab 
17515bc3cb74SMauro Carvalho Chehab static int v4l_s_frequency(const struct v4l2_ioctl_ops *ops,
17525bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
17535bc3cb74SMauro Carvalho Chehab {
17545bc3cb74SMauro Carvalho Chehab 	struct video_device *vfd = video_devdata(file);
1755b530a447SHans Verkuil 	const struct v4l2_frequency *p = arg;
17565bc3cb74SMauro Carvalho Chehab 	enum v4l2_tuner_type type;
175777fa4e07SShuah Khan 	int ret;
17585bc3cb74SMauro Carvalho Chehab 
175977fa4e07SShuah Khan 	ret = v4l_enable_media_source(vfd);
176077fa4e07SShuah Khan 	if (ret)
176177fa4e07SShuah Khan 		return ret;
176284099a28SAntti Palosaari 	if (vfd->vfl_type == VFL_TYPE_SDR) {
1763f3c3ececSAntti Palosaari 		if (p->type != V4L2_TUNER_SDR && p->type != V4L2_TUNER_RF)
176484099a28SAntti Palosaari 			return -EINVAL;
176584099a28SAntti Palosaari 	} else {
17665bc3cb74SMauro Carvalho Chehab 		type = (vfd->vfl_type == VFL_TYPE_RADIO) ?
17675bc3cb74SMauro Carvalho Chehab 				V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
176884099a28SAntti Palosaari 		if (type != p->type)
17695bc3cb74SMauro Carvalho Chehab 			return -EINVAL;
177084099a28SAntti Palosaari 	}
17715bc3cb74SMauro Carvalho Chehab 	return ops->vidioc_s_frequency(file, fh, p);
17725bc3cb74SMauro Carvalho Chehab }
17735bc3cb74SMauro Carvalho Chehab 
17745bc3cb74SMauro Carvalho Chehab static int v4l_enumstd(const struct v4l2_ioctl_ops *ops,
17755bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
17765bc3cb74SMauro Carvalho Chehab {
17775bc3cb74SMauro Carvalho Chehab 	struct video_device *vfd = video_devdata(file);
17785bc3cb74SMauro Carvalho Chehab 	struct v4l2_standard *p = arg;
17795bc3cb74SMauro Carvalho Chehab 	v4l2_std_id id = vfd->tvnorms, curr_id = 0;
17805bc3cb74SMauro Carvalho Chehab 	unsigned int index = p->index, i, j = 0;
17815bc3cb74SMauro Carvalho Chehab 	const char *descr = "";
17825bc3cb74SMauro Carvalho Chehab 
1783a5338190SHans Verkuil 	/* Return -ENODATA if the tvnorms for the current input
1784a5338190SHans Verkuil 	   or output is 0, meaning that it doesn't support this API. */
1785a5338190SHans Verkuil 	if (id == 0)
1786a5338190SHans Verkuil 		return -ENODATA;
1787a5338190SHans Verkuil 
17885bc3cb74SMauro Carvalho Chehab 	/* Return norm array in a canonical way */
17895bc3cb74SMauro Carvalho Chehab 	for (i = 0; i <= index && id; i++) {
17905bc3cb74SMauro Carvalho Chehab 		/* last std value in the standards array is 0, so this
17915bc3cb74SMauro Carvalho Chehab 		   while always ends there since (id & 0) == 0. */
17925bc3cb74SMauro Carvalho Chehab 		while ((id & standards[j].std) != standards[j].std)
17935bc3cb74SMauro Carvalho Chehab 			j++;
17945bc3cb74SMauro Carvalho Chehab 		curr_id = standards[j].std;
17955bc3cb74SMauro Carvalho Chehab 		descr = standards[j].descr;
17965bc3cb74SMauro Carvalho Chehab 		j++;
17975bc3cb74SMauro Carvalho Chehab 		if (curr_id == 0)
17985bc3cb74SMauro Carvalho Chehab 			break;
17995bc3cb74SMauro Carvalho Chehab 		if (curr_id != V4L2_STD_PAL &&
18005bc3cb74SMauro Carvalho Chehab 				curr_id != V4L2_STD_SECAM &&
18015bc3cb74SMauro Carvalho Chehab 				curr_id != V4L2_STD_NTSC)
18025bc3cb74SMauro Carvalho Chehab 			id &= ~curr_id;
18035bc3cb74SMauro Carvalho Chehab 	}
18045bc3cb74SMauro Carvalho Chehab 	if (i <= index)
18055bc3cb74SMauro Carvalho Chehab 		return -EINVAL;
18065bc3cb74SMauro Carvalho Chehab 
18075bc3cb74SMauro Carvalho Chehab 	v4l2_video_std_construct(p, curr_id, descr);
18085bc3cb74SMauro Carvalho Chehab 	return 0;
18095bc3cb74SMauro Carvalho Chehab }
18105bc3cb74SMauro Carvalho Chehab 
18115bc3cb74SMauro Carvalho Chehab static int v4l_s_std(const struct v4l2_ioctl_ops *ops,
18125bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
18135bc3cb74SMauro Carvalho Chehab {
18145bc3cb74SMauro Carvalho Chehab 	struct video_device *vfd = video_devdata(file);
1815314527acSHans Verkuil 	v4l2_std_id id = *(v4l2_std_id *)arg, norm;
181677fa4e07SShuah Khan 	int ret;
18175bc3cb74SMauro Carvalho Chehab 
181877fa4e07SShuah Khan 	ret = v4l_enable_media_source(vfd);
181977fa4e07SShuah Khan 	if (ret)
182077fa4e07SShuah Khan 		return ret;
1821314527acSHans Verkuil 	norm = id & vfd->tvnorms;
18225bc3cb74SMauro Carvalho Chehab 	if (vfd->tvnorms && !norm)	/* Check if std is supported */
18235bc3cb74SMauro Carvalho Chehab 		return -EINVAL;
18245bc3cb74SMauro Carvalho Chehab 
18255bc3cb74SMauro Carvalho Chehab 	/* Calls the specific handler */
1826ca371575SHans Verkuil 	return ops->vidioc_s_std(file, fh, norm);
18275bc3cb74SMauro Carvalho Chehab }
18285bc3cb74SMauro Carvalho Chehab 
18295bc3cb74SMauro Carvalho Chehab static int v4l_querystd(const struct v4l2_ioctl_ops *ops,
18305bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
18315bc3cb74SMauro Carvalho Chehab {
18325bc3cb74SMauro Carvalho Chehab 	struct video_device *vfd = video_devdata(file);
18335bc3cb74SMauro Carvalho Chehab 	v4l2_std_id *p = arg;
183477fa4e07SShuah Khan 	int ret;
18355bc3cb74SMauro Carvalho Chehab 
183677fa4e07SShuah Khan 	ret = v4l_enable_media_source(vfd);
183777fa4e07SShuah Khan 	if (ret)
183877fa4e07SShuah Khan 		return ret;
18395bc3cb74SMauro Carvalho Chehab 	/*
18401a2c6866SHans Verkuil 	 * If no signal is detected, then the driver should return
18411a2c6866SHans Verkuil 	 * V4L2_STD_UNKNOWN. Otherwise it should return tvnorms with
18421a2c6866SHans Verkuil 	 * any standards that do not apply removed.
18431a2c6866SHans Verkuil 	 *
18445bc3cb74SMauro Carvalho Chehab 	 * This means that tuners, audio and video decoders can join
18455bc3cb74SMauro Carvalho Chehab 	 * their efforts to improve the standards detection.
18465bc3cb74SMauro Carvalho Chehab 	 */
18475bc3cb74SMauro Carvalho Chehab 	*p = vfd->tvnorms;
18485bc3cb74SMauro Carvalho Chehab 	return ops->vidioc_querystd(file, fh, arg);
18495bc3cb74SMauro Carvalho Chehab }
18505bc3cb74SMauro Carvalho Chehab 
18515bc3cb74SMauro Carvalho Chehab static int v4l_s_hw_freq_seek(const struct v4l2_ioctl_ops *ops,
18525bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
18535bc3cb74SMauro Carvalho Chehab {
18545bc3cb74SMauro Carvalho Chehab 	struct video_device *vfd = video_devdata(file);
18555bc3cb74SMauro Carvalho Chehab 	struct v4l2_hw_freq_seek *p = arg;
18565bc3cb74SMauro Carvalho Chehab 	enum v4l2_tuner_type type;
185777fa4e07SShuah Khan 	int ret;
18585bc3cb74SMauro Carvalho Chehab 
185977fa4e07SShuah Khan 	ret = v4l_enable_media_source(vfd);
186077fa4e07SShuah Khan 	if (ret)
186177fa4e07SShuah Khan 		return ret;
186284099a28SAntti Palosaari 	/* s_hw_freq_seek is not supported for SDR for now */
186384099a28SAntti Palosaari 	if (vfd->vfl_type == VFL_TYPE_SDR)
186484099a28SAntti Palosaari 		return -EINVAL;
186584099a28SAntti Palosaari 
18665bc3cb74SMauro Carvalho Chehab 	type = (vfd->vfl_type == VFL_TYPE_RADIO) ?
18675bc3cb74SMauro Carvalho Chehab 		V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
18685bc3cb74SMauro Carvalho Chehab 	if (p->type != type)
18695bc3cb74SMauro Carvalho Chehab 		return -EINVAL;
18705bc3cb74SMauro Carvalho Chehab 	return ops->vidioc_s_hw_freq_seek(file, fh, p);
18715bc3cb74SMauro Carvalho Chehab }
18725bc3cb74SMauro Carvalho Chehab 
1873737c097bSHans Verkuil static int v4l_overlay(const struct v4l2_ioctl_ops *ops,
1874737c097bSHans Verkuil 				struct file *file, void *fh, void *arg)
1875737c097bSHans Verkuil {
1876737c097bSHans Verkuil 	return ops->vidioc_overlay(file, fh, *(unsigned int *)arg);
1877737c097bSHans Verkuil }
1878737c097bSHans Verkuil 
18795bc3cb74SMauro Carvalho Chehab static int v4l_reqbufs(const struct v4l2_ioctl_ops *ops,
18805bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
18815bc3cb74SMauro Carvalho Chehab {
18825bc3cb74SMauro Carvalho Chehab 	struct v4l2_requestbuffers *p = arg;
18834b20259fSHans Verkuil 	int ret = check_fmt(file, p->type);
18845bc3cb74SMauro Carvalho Chehab 
18855bc3cb74SMauro Carvalho Chehab 	if (ret)
18865bc3cb74SMauro Carvalho Chehab 		return ret;
18875bc3cb74SMauro Carvalho Chehab 
18885bc3cb74SMauro Carvalho Chehab 	CLEAR_AFTER_FIELD(p, memory);
18895bc3cb74SMauro Carvalho Chehab 
18905bc3cb74SMauro Carvalho Chehab 	return ops->vidioc_reqbufs(file, fh, p);
18915bc3cb74SMauro Carvalho Chehab }
18925bc3cb74SMauro Carvalho Chehab 
18935bc3cb74SMauro Carvalho Chehab static int v4l_querybuf(const struct v4l2_ioctl_ops *ops,
18945bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
18955bc3cb74SMauro Carvalho Chehab {
18965bc3cb74SMauro Carvalho Chehab 	struct v4l2_buffer *p = arg;
18974b20259fSHans Verkuil 	int ret = check_fmt(file, p->type);
18985bc3cb74SMauro Carvalho Chehab 
18995bc3cb74SMauro Carvalho Chehab 	return ret ? ret : ops->vidioc_querybuf(file, fh, p);
19005bc3cb74SMauro Carvalho Chehab }
19015bc3cb74SMauro Carvalho Chehab 
19025bc3cb74SMauro Carvalho Chehab static int v4l_qbuf(const struct v4l2_ioctl_ops *ops,
19035bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
19045bc3cb74SMauro Carvalho Chehab {
19055bc3cb74SMauro Carvalho Chehab 	struct v4l2_buffer *p = arg;
19064b20259fSHans Verkuil 	int ret = check_fmt(file, p->type);
19075bc3cb74SMauro Carvalho Chehab 
19085bc3cb74SMauro Carvalho Chehab 	return ret ? ret : ops->vidioc_qbuf(file, fh, p);
19095bc3cb74SMauro Carvalho Chehab }
19105bc3cb74SMauro Carvalho Chehab 
19115bc3cb74SMauro Carvalho Chehab static int v4l_dqbuf(const struct v4l2_ioctl_ops *ops,
19125bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
19135bc3cb74SMauro Carvalho Chehab {
19145bc3cb74SMauro Carvalho Chehab 	struct v4l2_buffer *p = arg;
19154b20259fSHans Verkuil 	int ret = check_fmt(file, p->type);
19165bc3cb74SMauro Carvalho Chehab 
19175bc3cb74SMauro Carvalho Chehab 	return ret ? ret : ops->vidioc_dqbuf(file, fh, p);
19185bc3cb74SMauro Carvalho Chehab }
19195bc3cb74SMauro Carvalho Chehab 
19205bc3cb74SMauro Carvalho Chehab static int v4l_create_bufs(const struct v4l2_ioctl_ops *ops,
19215bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
19225bc3cb74SMauro Carvalho Chehab {
19235bc3cb74SMauro Carvalho Chehab 	struct v4l2_create_buffers *create = arg;
19244b20259fSHans Verkuil 	int ret = check_fmt(file, create->format.type);
19255bc3cb74SMauro Carvalho Chehab 
1926d52e2381SLaurent Pinchart 	if (ret)
1927d52e2381SLaurent Pinchart 		return ret;
1928d52e2381SLaurent Pinchart 
19295d351251SHans Verkuil 	CLEAR_AFTER_FIELD(create, format);
19305d351251SHans Verkuil 
1931d52e2381SLaurent Pinchart 	v4l_sanitize_format(&create->format);
1932d52e2381SLaurent Pinchart 
1933d52e2381SLaurent Pinchart 	ret = ops->vidioc_create_bufs(file, fh, create);
1934d52e2381SLaurent Pinchart 
1935d52e2381SLaurent Pinchart 	if (create->format.type == V4L2_BUF_TYPE_VIDEO_CAPTURE ||
1936d52e2381SLaurent Pinchart 	    create->format.type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
1937d52e2381SLaurent Pinchart 		create->format.fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC;
1938d52e2381SLaurent Pinchart 
1939d52e2381SLaurent Pinchart 	return ret;
19405bc3cb74SMauro Carvalho Chehab }
19415bc3cb74SMauro Carvalho Chehab 
19425bc3cb74SMauro Carvalho Chehab static int v4l_prepare_buf(const struct v4l2_ioctl_ops *ops,
19435bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
19445bc3cb74SMauro Carvalho Chehab {
19455bc3cb74SMauro Carvalho Chehab 	struct v4l2_buffer *b = arg;
19464b20259fSHans Verkuil 	int ret = check_fmt(file, b->type);
19475bc3cb74SMauro Carvalho Chehab 
19485bc3cb74SMauro Carvalho Chehab 	return ret ? ret : ops->vidioc_prepare_buf(file, fh, b);
19495bc3cb74SMauro Carvalho Chehab }
19505bc3cb74SMauro Carvalho Chehab 
19515bc3cb74SMauro Carvalho Chehab static int v4l_g_parm(const struct v4l2_ioctl_ops *ops,
19525bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
19535bc3cb74SMauro Carvalho Chehab {
19545bc3cb74SMauro Carvalho Chehab 	struct v4l2_streamparm *p = arg;
19555bc3cb74SMauro Carvalho Chehab 	v4l2_std_id std;
19564b20259fSHans Verkuil 	int ret = check_fmt(file, p->type);
19575bc3cb74SMauro Carvalho Chehab 
19585bc3cb74SMauro Carvalho Chehab 	if (ret)
19595bc3cb74SMauro Carvalho Chehab 		return ret;
19605bc3cb74SMauro Carvalho Chehab 	if (ops->vidioc_g_parm)
19615bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_g_parm(file, fh, p);
19625bc3cb74SMauro Carvalho Chehab 	if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
19635bc3cb74SMauro Carvalho Chehab 	    p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
19645bc3cb74SMauro Carvalho Chehab 		return -EINVAL;
19655bc3cb74SMauro Carvalho Chehab 	p->parm.capture.readbuffers = 2;
19665bc3cb74SMauro Carvalho Chehab 	ret = ops->vidioc_g_std(file, fh, &std);
19675bc3cb74SMauro Carvalho Chehab 	if (ret == 0)
1968ca371575SHans Verkuil 		v4l2_video_std_frame_period(std, &p->parm.capture.timeperframe);
19695bc3cb74SMauro Carvalho Chehab 	return ret;
19705bc3cb74SMauro Carvalho Chehab }
19715bc3cb74SMauro Carvalho Chehab 
19725bc3cb74SMauro Carvalho Chehab static int v4l_s_parm(const struct v4l2_ioctl_ops *ops,
19735bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
19745bc3cb74SMauro Carvalho Chehab {
19755bc3cb74SMauro Carvalho Chehab 	struct v4l2_streamparm *p = arg;
19764b20259fSHans Verkuil 	int ret = check_fmt(file, p->type);
19775bc3cb74SMauro Carvalho Chehab 
19785bc3cb74SMauro Carvalho Chehab 	return ret ? ret : ops->vidioc_s_parm(file, fh, p);
19795bc3cb74SMauro Carvalho Chehab }
19805bc3cb74SMauro Carvalho Chehab 
19815bc3cb74SMauro Carvalho Chehab static int v4l_queryctrl(const struct v4l2_ioctl_ops *ops,
19825bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
19835bc3cb74SMauro Carvalho Chehab {
19845bc3cb74SMauro Carvalho Chehab 	struct video_device *vfd = video_devdata(file);
19855bc3cb74SMauro Carvalho Chehab 	struct v4l2_queryctrl *p = arg;
19865bc3cb74SMauro Carvalho Chehab 	struct v4l2_fh *vfh =
19875bc3cb74SMauro Carvalho Chehab 		test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags) ? fh : NULL;
19885bc3cb74SMauro Carvalho Chehab 
19895bc3cb74SMauro Carvalho Chehab 	if (vfh && vfh->ctrl_handler)
19905bc3cb74SMauro Carvalho Chehab 		return v4l2_queryctrl(vfh->ctrl_handler, p);
19915bc3cb74SMauro Carvalho Chehab 	if (vfd->ctrl_handler)
19925bc3cb74SMauro Carvalho Chehab 		return v4l2_queryctrl(vfd->ctrl_handler, p);
19935bc3cb74SMauro Carvalho Chehab 	if (ops->vidioc_queryctrl)
19945bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_queryctrl(file, fh, p);
19955bc3cb74SMauro Carvalho Chehab 	return -ENOTTY;
19965bc3cb74SMauro Carvalho Chehab }
19975bc3cb74SMauro Carvalho Chehab 
1998e6bee368SHans Verkuil static int v4l_query_ext_ctrl(const struct v4l2_ioctl_ops *ops,
1999e6bee368SHans Verkuil 				struct file *file, void *fh, void *arg)
2000e6bee368SHans Verkuil {
2001e6bee368SHans Verkuil 	struct video_device *vfd = video_devdata(file);
2002e6bee368SHans Verkuil 	struct v4l2_query_ext_ctrl *p = arg;
2003e6bee368SHans Verkuil 	struct v4l2_fh *vfh =
2004e6bee368SHans Verkuil 		test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags) ? fh : NULL;
2005e6bee368SHans Verkuil 
2006e6bee368SHans Verkuil 	if (vfh && vfh->ctrl_handler)
2007e6bee368SHans Verkuil 		return v4l2_query_ext_ctrl(vfh->ctrl_handler, p);
2008e6bee368SHans Verkuil 	if (vfd->ctrl_handler)
2009e6bee368SHans Verkuil 		return v4l2_query_ext_ctrl(vfd->ctrl_handler, p);
2010e6bee368SHans Verkuil 	if (ops->vidioc_query_ext_ctrl)
2011e6bee368SHans Verkuil 		return ops->vidioc_query_ext_ctrl(file, fh, p);
2012e6bee368SHans Verkuil 	return -ENOTTY;
2013e6bee368SHans Verkuil }
2014e6bee368SHans Verkuil 
20155bc3cb74SMauro Carvalho Chehab static int v4l_querymenu(const struct v4l2_ioctl_ops *ops,
20165bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
20175bc3cb74SMauro Carvalho Chehab {
20185bc3cb74SMauro Carvalho Chehab 	struct video_device *vfd = video_devdata(file);
20195bc3cb74SMauro Carvalho Chehab 	struct v4l2_querymenu *p = arg;
20205bc3cb74SMauro Carvalho Chehab 	struct v4l2_fh *vfh =
20215bc3cb74SMauro Carvalho Chehab 		test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags) ? fh : NULL;
20225bc3cb74SMauro Carvalho Chehab 
20235bc3cb74SMauro Carvalho Chehab 	if (vfh && vfh->ctrl_handler)
20245bc3cb74SMauro Carvalho Chehab 		return v4l2_querymenu(vfh->ctrl_handler, p);
20255bc3cb74SMauro Carvalho Chehab 	if (vfd->ctrl_handler)
20265bc3cb74SMauro Carvalho Chehab 		return v4l2_querymenu(vfd->ctrl_handler, p);
20275bc3cb74SMauro Carvalho Chehab 	if (ops->vidioc_querymenu)
20285bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_querymenu(file, fh, p);
20295bc3cb74SMauro Carvalho Chehab 	return -ENOTTY;
20305bc3cb74SMauro Carvalho Chehab }
20315bc3cb74SMauro Carvalho Chehab 
20325bc3cb74SMauro Carvalho Chehab static int v4l_g_ctrl(const struct v4l2_ioctl_ops *ops,
20335bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
20345bc3cb74SMauro Carvalho Chehab {
20355bc3cb74SMauro Carvalho Chehab 	struct video_device *vfd = video_devdata(file);
20365bc3cb74SMauro Carvalho Chehab 	struct v4l2_control *p = arg;
20375bc3cb74SMauro Carvalho Chehab 	struct v4l2_fh *vfh =
20385bc3cb74SMauro Carvalho Chehab 		test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags) ? fh : NULL;
20395bc3cb74SMauro Carvalho Chehab 	struct v4l2_ext_controls ctrls;
20405bc3cb74SMauro Carvalho Chehab 	struct v4l2_ext_control ctrl;
20415bc3cb74SMauro Carvalho Chehab 
20425bc3cb74SMauro Carvalho Chehab 	if (vfh && vfh->ctrl_handler)
20435bc3cb74SMauro Carvalho Chehab 		return v4l2_g_ctrl(vfh->ctrl_handler, p);
20445bc3cb74SMauro Carvalho Chehab 	if (vfd->ctrl_handler)
20455bc3cb74SMauro Carvalho Chehab 		return v4l2_g_ctrl(vfd->ctrl_handler, p);
20465bc3cb74SMauro Carvalho Chehab 	if (ops->vidioc_g_ctrl)
20475bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_g_ctrl(file, fh, p);
20485bc3cb74SMauro Carvalho Chehab 	if (ops->vidioc_g_ext_ctrls == NULL)
20495bc3cb74SMauro Carvalho Chehab 		return -ENOTTY;
20505bc3cb74SMauro Carvalho Chehab 
20510f8017beSRicardo Ribalda 	ctrls.which = V4L2_CTRL_ID2WHICH(p->id);
20525bc3cb74SMauro Carvalho Chehab 	ctrls.count = 1;
20535bc3cb74SMauro Carvalho Chehab 	ctrls.controls = &ctrl;
20545bc3cb74SMauro Carvalho Chehab 	ctrl.id = p->id;
20555bc3cb74SMauro Carvalho Chehab 	ctrl.value = p->value;
20565bc3cb74SMauro Carvalho Chehab 	if (check_ext_ctrls(&ctrls, 1)) {
20575bc3cb74SMauro Carvalho Chehab 		int ret = ops->vidioc_g_ext_ctrls(file, fh, &ctrls);
20585bc3cb74SMauro Carvalho Chehab 
20595bc3cb74SMauro Carvalho Chehab 		if (ret == 0)
20605bc3cb74SMauro Carvalho Chehab 			p->value = ctrl.value;
20615bc3cb74SMauro Carvalho Chehab 		return ret;
20625bc3cb74SMauro Carvalho Chehab 	}
20635bc3cb74SMauro Carvalho Chehab 	return -EINVAL;
20645bc3cb74SMauro Carvalho Chehab }
20655bc3cb74SMauro Carvalho Chehab 
20665bc3cb74SMauro Carvalho Chehab static int v4l_s_ctrl(const struct v4l2_ioctl_ops *ops,
20675bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
20685bc3cb74SMauro Carvalho Chehab {
20695bc3cb74SMauro Carvalho Chehab 	struct video_device *vfd = video_devdata(file);
20705bc3cb74SMauro Carvalho Chehab 	struct v4l2_control *p = arg;
20715bc3cb74SMauro Carvalho Chehab 	struct v4l2_fh *vfh =
20725bc3cb74SMauro Carvalho Chehab 		test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags) ? fh : NULL;
20735bc3cb74SMauro Carvalho Chehab 	struct v4l2_ext_controls ctrls;
20745bc3cb74SMauro Carvalho Chehab 	struct v4l2_ext_control ctrl;
20755bc3cb74SMauro Carvalho Chehab 
20765bc3cb74SMauro Carvalho Chehab 	if (vfh && vfh->ctrl_handler)
20775bc3cb74SMauro Carvalho Chehab 		return v4l2_s_ctrl(vfh, vfh->ctrl_handler, p);
20785bc3cb74SMauro Carvalho Chehab 	if (vfd->ctrl_handler)
20795bc3cb74SMauro Carvalho Chehab 		return v4l2_s_ctrl(NULL, vfd->ctrl_handler, p);
20805bc3cb74SMauro Carvalho Chehab 	if (ops->vidioc_s_ctrl)
20815bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_s_ctrl(file, fh, p);
20825bc3cb74SMauro Carvalho Chehab 	if (ops->vidioc_s_ext_ctrls == NULL)
20835bc3cb74SMauro Carvalho Chehab 		return -ENOTTY;
20845bc3cb74SMauro Carvalho Chehab 
20850f8017beSRicardo Ribalda 	ctrls.which = V4L2_CTRL_ID2WHICH(p->id);
20865bc3cb74SMauro Carvalho Chehab 	ctrls.count = 1;
20875bc3cb74SMauro Carvalho Chehab 	ctrls.controls = &ctrl;
20885bc3cb74SMauro Carvalho Chehab 	ctrl.id = p->id;
20895bc3cb74SMauro Carvalho Chehab 	ctrl.value = p->value;
20905bc3cb74SMauro Carvalho Chehab 	if (check_ext_ctrls(&ctrls, 1))
20915bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_s_ext_ctrls(file, fh, &ctrls);
20925bc3cb74SMauro Carvalho Chehab 	return -EINVAL;
20935bc3cb74SMauro Carvalho Chehab }
20945bc3cb74SMauro Carvalho Chehab 
20955bc3cb74SMauro Carvalho Chehab static int v4l_g_ext_ctrls(const struct v4l2_ioctl_ops *ops,
20965bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
20975bc3cb74SMauro Carvalho Chehab {
20985bc3cb74SMauro Carvalho Chehab 	struct video_device *vfd = video_devdata(file);
20995bc3cb74SMauro Carvalho Chehab 	struct v4l2_ext_controls *p = arg;
21005bc3cb74SMauro Carvalho Chehab 	struct v4l2_fh *vfh =
21015bc3cb74SMauro Carvalho Chehab 		test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags) ? fh : NULL;
21025bc3cb74SMauro Carvalho Chehab 
21035bc3cb74SMauro Carvalho Chehab 	p->error_idx = p->count;
21045bc3cb74SMauro Carvalho Chehab 	if (vfh && vfh->ctrl_handler)
21055bc3cb74SMauro Carvalho Chehab 		return v4l2_g_ext_ctrls(vfh->ctrl_handler, p);
21065bc3cb74SMauro Carvalho Chehab 	if (vfd->ctrl_handler)
21075bc3cb74SMauro Carvalho Chehab 		return v4l2_g_ext_ctrls(vfd->ctrl_handler, p);
21085bc3cb74SMauro Carvalho Chehab 	if (ops->vidioc_g_ext_ctrls == NULL)
21095bc3cb74SMauro Carvalho Chehab 		return -ENOTTY;
21105bc3cb74SMauro Carvalho Chehab 	return check_ext_ctrls(p, 0) ? ops->vidioc_g_ext_ctrls(file, fh, p) :
21115bc3cb74SMauro Carvalho Chehab 					-EINVAL;
21125bc3cb74SMauro Carvalho Chehab }
21135bc3cb74SMauro Carvalho Chehab 
21145bc3cb74SMauro Carvalho Chehab static int v4l_s_ext_ctrls(const struct v4l2_ioctl_ops *ops,
21155bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
21165bc3cb74SMauro Carvalho Chehab {
21175bc3cb74SMauro Carvalho Chehab 	struct video_device *vfd = video_devdata(file);
21185bc3cb74SMauro Carvalho Chehab 	struct v4l2_ext_controls *p = arg;
21195bc3cb74SMauro Carvalho Chehab 	struct v4l2_fh *vfh =
21205bc3cb74SMauro Carvalho Chehab 		test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags) ? fh : NULL;
21215bc3cb74SMauro Carvalho Chehab 
21225bc3cb74SMauro Carvalho Chehab 	p->error_idx = p->count;
21235bc3cb74SMauro Carvalho Chehab 	if (vfh && vfh->ctrl_handler)
21245bc3cb74SMauro Carvalho Chehab 		return v4l2_s_ext_ctrls(vfh, vfh->ctrl_handler, p);
21255bc3cb74SMauro Carvalho Chehab 	if (vfd->ctrl_handler)
21265bc3cb74SMauro Carvalho Chehab 		return v4l2_s_ext_ctrls(NULL, vfd->ctrl_handler, p);
21275bc3cb74SMauro Carvalho Chehab 	if (ops->vidioc_s_ext_ctrls == NULL)
21285bc3cb74SMauro Carvalho Chehab 		return -ENOTTY;
21295bc3cb74SMauro Carvalho Chehab 	return check_ext_ctrls(p, 0) ? ops->vidioc_s_ext_ctrls(file, fh, p) :
21305bc3cb74SMauro Carvalho Chehab 					-EINVAL;
21315bc3cb74SMauro Carvalho Chehab }
21325bc3cb74SMauro Carvalho Chehab 
21335bc3cb74SMauro Carvalho Chehab static int v4l_try_ext_ctrls(const struct v4l2_ioctl_ops *ops,
21345bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
21355bc3cb74SMauro Carvalho Chehab {
21365bc3cb74SMauro Carvalho Chehab 	struct video_device *vfd = video_devdata(file);
21375bc3cb74SMauro Carvalho Chehab 	struct v4l2_ext_controls *p = arg;
21385bc3cb74SMauro Carvalho Chehab 	struct v4l2_fh *vfh =
21395bc3cb74SMauro Carvalho Chehab 		test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags) ? fh : NULL;
21405bc3cb74SMauro Carvalho Chehab 
21415bc3cb74SMauro Carvalho Chehab 	p->error_idx = p->count;
21425bc3cb74SMauro Carvalho Chehab 	if (vfh && vfh->ctrl_handler)
21435bc3cb74SMauro Carvalho Chehab 		return v4l2_try_ext_ctrls(vfh->ctrl_handler, p);
21445bc3cb74SMauro Carvalho Chehab 	if (vfd->ctrl_handler)
21455bc3cb74SMauro Carvalho Chehab 		return v4l2_try_ext_ctrls(vfd->ctrl_handler, p);
21465bc3cb74SMauro Carvalho Chehab 	if (ops->vidioc_try_ext_ctrls == NULL)
21475bc3cb74SMauro Carvalho Chehab 		return -ENOTTY;
21485bc3cb74SMauro Carvalho Chehab 	return check_ext_ctrls(p, 0) ? ops->vidioc_try_ext_ctrls(file, fh, p) :
21495bc3cb74SMauro Carvalho Chehab 					-EINVAL;
21505bc3cb74SMauro Carvalho Chehab }
21515bc3cb74SMauro Carvalho Chehab 
2152eaec420fSHans Verkuil /*
2153eaec420fSHans Verkuil  * The selection API specified originally that the _MPLANE buffer types
2154eaec420fSHans Verkuil  * shouldn't be used. The reasons for this are lost in the mists of time
2155eaec420fSHans Verkuil  * (or just really crappy memories). Regardless, this is really annoying
2156eaec420fSHans Verkuil  * for userspace. So to keep things simple we map _MPLANE buffer types
2157eaec420fSHans Verkuil  * to their 'regular' counterparts before calling the driver. And we
2158eaec420fSHans Verkuil  * restore it afterwards. This way applications can use either buffer
2159eaec420fSHans Verkuil  * type and drivers don't need to check for both.
2160eaec420fSHans Verkuil  */
2161eaec420fSHans Verkuil static int v4l_g_selection(const struct v4l2_ioctl_ops *ops,
2162eaec420fSHans Verkuil 			   struct file *file, void *fh, void *arg)
2163eaec420fSHans Verkuil {
2164eaec420fSHans Verkuil 	struct v4l2_selection *p = arg;
2165eaec420fSHans Verkuil 	u32 old_type = p->type;
2166eaec420fSHans Verkuil 	int ret;
2167eaec420fSHans Verkuil 
2168eaec420fSHans Verkuil 	if (p->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
2169eaec420fSHans Verkuil 		p->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2170eaec420fSHans Verkuil 	else if (p->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
2171eaec420fSHans Verkuil 		p->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
2172eaec420fSHans Verkuil 	ret = ops->vidioc_g_selection(file, fh, p);
2173eaec420fSHans Verkuil 	p->type = old_type;
2174eaec420fSHans Verkuil 	return ret;
2175eaec420fSHans Verkuil }
2176eaec420fSHans Verkuil 
2177eaec420fSHans Verkuil static int v4l_s_selection(const struct v4l2_ioctl_ops *ops,
2178eaec420fSHans Verkuil 			   struct file *file, void *fh, void *arg)
2179eaec420fSHans Verkuil {
2180eaec420fSHans Verkuil 	struct v4l2_selection *p = arg;
2181eaec420fSHans Verkuil 	u32 old_type = p->type;
2182eaec420fSHans Verkuil 	int ret;
2183eaec420fSHans Verkuil 
2184eaec420fSHans Verkuil 	if (p->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
2185eaec420fSHans Verkuil 		p->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2186eaec420fSHans Verkuil 	else if (p->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
2187eaec420fSHans Verkuil 		p->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
2188eaec420fSHans Verkuil 	ret = ops->vidioc_s_selection(file, fh, p);
2189eaec420fSHans Verkuil 	p->type = old_type;
2190eaec420fSHans Verkuil 	return ret;
2191eaec420fSHans Verkuil }
2192eaec420fSHans Verkuil 
21935bc3cb74SMauro Carvalho Chehab static int v4l_g_crop(const struct v4l2_ioctl_ops *ops,
21945bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
21955bc3cb74SMauro Carvalho Chehab {
21965bc3cb74SMauro Carvalho Chehab 	struct v4l2_crop *p = arg;
21975bc3cb74SMauro Carvalho Chehab 	struct v4l2_selection s = {
21985bc3cb74SMauro Carvalho Chehab 		.type = p->type,
21995bc3cb74SMauro Carvalho Chehab 	};
22005bc3cb74SMauro Carvalho Chehab 	int ret;
22015bc3cb74SMauro Carvalho Chehab 
22025bc3cb74SMauro Carvalho Chehab 	if (ops->vidioc_g_crop)
22035bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_g_crop(file, fh, p);
22045bc3cb74SMauro Carvalho Chehab 	/* simulate capture crop using selection api */
22055bc3cb74SMauro Carvalho Chehab 
22065bc3cb74SMauro Carvalho Chehab 	/* crop means compose for output devices */
22075bc3cb74SMauro Carvalho Chehab 	if (V4L2_TYPE_IS_OUTPUT(p->type))
22085bc3cb74SMauro Carvalho Chehab 		s.target = V4L2_SEL_TGT_COMPOSE_ACTIVE;
22095bc3cb74SMauro Carvalho Chehab 	else
22105bc3cb74SMauro Carvalho Chehab 		s.target = V4L2_SEL_TGT_CROP_ACTIVE;
22115bc3cb74SMauro Carvalho Chehab 
2212eaec420fSHans Verkuil 	ret = v4l_g_selection(ops, file, fh, &s);
22135bc3cb74SMauro Carvalho Chehab 
22145bc3cb74SMauro Carvalho Chehab 	/* copying results to old structure on success */
22155bc3cb74SMauro Carvalho Chehab 	if (!ret)
22165bc3cb74SMauro Carvalho Chehab 		p->c = s.r;
22175bc3cb74SMauro Carvalho Chehab 	return ret;
22185bc3cb74SMauro Carvalho Chehab }
22195bc3cb74SMauro Carvalho Chehab 
22205bc3cb74SMauro Carvalho Chehab static int v4l_s_crop(const struct v4l2_ioctl_ops *ops,
22215bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
22225bc3cb74SMauro Carvalho Chehab {
22235bc3cb74SMauro Carvalho Chehab 	struct v4l2_crop *p = arg;
22245bc3cb74SMauro Carvalho Chehab 	struct v4l2_selection s = {
22255bc3cb74SMauro Carvalho Chehab 		.type = p->type,
22265bc3cb74SMauro Carvalho Chehab 		.r = p->c,
22275bc3cb74SMauro Carvalho Chehab 	};
22285bc3cb74SMauro Carvalho Chehab 
22295bc3cb74SMauro Carvalho Chehab 	if (ops->vidioc_s_crop)
22305bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_s_crop(file, fh, p);
22315bc3cb74SMauro Carvalho Chehab 	/* simulate capture crop using selection api */
22325bc3cb74SMauro Carvalho Chehab 
22335bc3cb74SMauro Carvalho Chehab 	/* crop means compose for output devices */
22345bc3cb74SMauro Carvalho Chehab 	if (V4L2_TYPE_IS_OUTPUT(p->type))
22355bc3cb74SMauro Carvalho Chehab 		s.target = V4L2_SEL_TGT_COMPOSE_ACTIVE;
22365bc3cb74SMauro Carvalho Chehab 	else
22375bc3cb74SMauro Carvalho Chehab 		s.target = V4L2_SEL_TGT_CROP_ACTIVE;
22385bc3cb74SMauro Carvalho Chehab 
2239eaec420fSHans Verkuil 	return v4l_s_selection(ops, file, fh, &s);
22405bc3cb74SMauro Carvalho Chehab }
22415bc3cb74SMauro Carvalho Chehab 
22425bc3cb74SMauro Carvalho Chehab static int v4l_cropcap(const struct v4l2_ioctl_ops *ops,
22435bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
22445bc3cb74SMauro Carvalho Chehab {
22455bc3cb74SMauro Carvalho Chehab 	struct v4l2_cropcap *p = arg;
22465bc3cb74SMauro Carvalho Chehab 	struct v4l2_selection s = { .type = p->type };
224795dd7b7eSHans Verkuil 	int ret = 0;
224895dd7b7eSHans Verkuil 
224995dd7b7eSHans Verkuil 	/* setting trivial pixelaspect */
225095dd7b7eSHans Verkuil 	p->pixelaspect.numerator = 1;
225195dd7b7eSHans Verkuil 	p->pixelaspect.denominator = 1;
225295dd7b7eSHans Verkuil 
225395dd7b7eSHans Verkuil 	/*
225495dd7b7eSHans Verkuil 	 * The determine_valid_ioctls() call already should ensure
225595dd7b7eSHans Verkuil 	 * that this can never happen, but just in case...
225695dd7b7eSHans Verkuil 	 */
22571ca830b1SHans Verkuil 	if (WARN_ON(!ops->vidioc_cropcap && !ops->vidioc_g_selection))
225895dd7b7eSHans Verkuil 		return -ENOTTY;
225995dd7b7eSHans Verkuil 
226095dd7b7eSHans Verkuil 	if (ops->vidioc_cropcap)
226195dd7b7eSHans Verkuil 		ret = ops->vidioc_cropcap(file, fh, p);
226295dd7b7eSHans Verkuil 
226395dd7b7eSHans Verkuil 	if (!ops->vidioc_g_selection)
226495dd7b7eSHans Verkuil 		return ret;
226595dd7b7eSHans Verkuil 
226695dd7b7eSHans Verkuil 	/*
226795dd7b7eSHans Verkuil 	 * Ignore ENOTTY or ENOIOCTLCMD error returns, just use the
226895dd7b7eSHans Verkuil 	 * square pixel aspect ratio in that case.
226995dd7b7eSHans Verkuil 	 */
227095dd7b7eSHans Verkuil 	if (ret && ret != -ENOTTY && ret != -ENOIOCTLCMD)
227195dd7b7eSHans Verkuil 		return ret;
227295dd7b7eSHans Verkuil 
227395dd7b7eSHans Verkuil 	/* Use g_selection() to fill in the bounds and defrect rectangles */
22745bc3cb74SMauro Carvalho Chehab 
22755bc3cb74SMauro Carvalho Chehab 	/* obtaining bounds */
22765bc3cb74SMauro Carvalho Chehab 	if (V4L2_TYPE_IS_OUTPUT(p->type))
22775bc3cb74SMauro Carvalho Chehab 		s.target = V4L2_SEL_TGT_COMPOSE_BOUNDS;
22785bc3cb74SMauro Carvalho Chehab 	else
22795bc3cb74SMauro Carvalho Chehab 		s.target = V4L2_SEL_TGT_CROP_BOUNDS;
22805bc3cb74SMauro Carvalho Chehab 
2281eaec420fSHans Verkuil 	ret = v4l_g_selection(ops, file, fh, &s);
22825bc3cb74SMauro Carvalho Chehab 	if (ret)
22835bc3cb74SMauro Carvalho Chehab 		return ret;
22845bc3cb74SMauro Carvalho Chehab 	p->bounds = s.r;
22855bc3cb74SMauro Carvalho Chehab 
22865bc3cb74SMauro Carvalho Chehab 	/* obtaining defrect */
22875bc3cb74SMauro Carvalho Chehab 	if (V4L2_TYPE_IS_OUTPUT(p->type))
22885bc3cb74SMauro Carvalho Chehab 		s.target = V4L2_SEL_TGT_COMPOSE_DEFAULT;
22895bc3cb74SMauro Carvalho Chehab 	else
22905bc3cb74SMauro Carvalho Chehab 		s.target = V4L2_SEL_TGT_CROP_DEFAULT;
22915bc3cb74SMauro Carvalho Chehab 
2292eaec420fSHans Verkuil 	ret = v4l_g_selection(ops, file, fh, &s);
22935bc3cb74SMauro Carvalho Chehab 	if (ret)
22945bc3cb74SMauro Carvalho Chehab 		return ret;
22955bc3cb74SMauro Carvalho Chehab 	p->defrect = s.r;
22969409945cSHans Verkuil 
22975bc3cb74SMauro Carvalho Chehab 	return 0;
22985bc3cb74SMauro Carvalho Chehab }
22995bc3cb74SMauro Carvalho Chehab 
23005bc3cb74SMauro Carvalho Chehab static int v4l_log_status(const struct v4l2_ioctl_ops *ops,
23015bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
23025bc3cb74SMauro Carvalho Chehab {
23035bc3cb74SMauro Carvalho Chehab 	struct video_device *vfd = video_devdata(file);
23045bc3cb74SMauro Carvalho Chehab 	int ret;
23055bc3cb74SMauro Carvalho Chehab 
23065bc3cb74SMauro Carvalho Chehab 	if (vfd->v4l2_dev)
23075bc3cb74SMauro Carvalho Chehab 		pr_info("%s: =================  START STATUS  =================\n",
23085bc3cb74SMauro Carvalho Chehab 			vfd->v4l2_dev->name);
23095bc3cb74SMauro Carvalho Chehab 	ret = ops->vidioc_log_status(file, fh);
23105bc3cb74SMauro Carvalho Chehab 	if (vfd->v4l2_dev)
23115bc3cb74SMauro Carvalho Chehab 		pr_info("%s: ==================  END STATUS  ==================\n",
23125bc3cb74SMauro Carvalho Chehab 			vfd->v4l2_dev->name);
23135bc3cb74SMauro Carvalho Chehab 	return ret;
23145bc3cb74SMauro Carvalho Chehab }
23155bc3cb74SMauro Carvalho Chehab 
23165bc3cb74SMauro Carvalho Chehab static int v4l_dbg_g_register(const struct v4l2_ioctl_ops *ops,
23175bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
23185bc3cb74SMauro Carvalho Chehab {
23195bc3cb74SMauro Carvalho Chehab #ifdef CONFIG_VIDEO_ADV_DEBUG
23205bc3cb74SMauro Carvalho Chehab 	struct v4l2_dbg_register *p = arg;
232179b0c640SHans Verkuil 	struct video_device *vfd = video_devdata(file);
232279b0c640SHans Verkuil 	struct v4l2_subdev *sd;
232379b0c640SHans Verkuil 	int idx = 0;
23245bc3cb74SMauro Carvalho Chehab 
23255bc3cb74SMauro Carvalho Chehab 	if (!capable(CAP_SYS_ADMIN))
23265bc3cb74SMauro Carvalho Chehab 		return -EPERM;
23273eef2510SHans Verkuil 	if (p->match.type == V4L2_CHIP_MATCH_SUBDEV) {
232879b0c640SHans Verkuil 		if (vfd->v4l2_dev == NULL)
232979b0c640SHans Verkuil 			return -EINVAL;
23303eef2510SHans Verkuil 		v4l2_device_for_each_subdev(sd, vfd->v4l2_dev)
23313eef2510SHans Verkuil 			if (p->match.addr == idx++)
233279b0c640SHans Verkuil 				return v4l2_subdev_call(sd, core, g_register, p);
233379b0c640SHans Verkuil 		return -EINVAL;
233479b0c640SHans Verkuil 	}
2335191b79b0SHans Verkuil 	if (ops->vidioc_g_register && p->match.type == V4L2_CHIP_MATCH_BRIDGE &&
2336191b79b0SHans Verkuil 	    (ops->vidioc_g_chip_info || p->match.addr == 0))
23375bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_g_register(file, fh, p);
233879b0c640SHans Verkuil 	return -EINVAL;
23395bc3cb74SMauro Carvalho Chehab #else
23405bc3cb74SMauro Carvalho Chehab 	return -ENOTTY;
23415bc3cb74SMauro Carvalho Chehab #endif
23425bc3cb74SMauro Carvalho Chehab }
23435bc3cb74SMauro Carvalho Chehab 
23445bc3cb74SMauro Carvalho Chehab static int v4l_dbg_s_register(const struct v4l2_ioctl_ops *ops,
23455bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
23465bc3cb74SMauro Carvalho Chehab {
23475bc3cb74SMauro Carvalho Chehab #ifdef CONFIG_VIDEO_ADV_DEBUG
2348977ba3b1SHans Verkuil 	const struct v4l2_dbg_register *p = arg;
234979b0c640SHans Verkuil 	struct video_device *vfd = video_devdata(file);
235079b0c640SHans Verkuil 	struct v4l2_subdev *sd;
235179b0c640SHans Verkuil 	int idx = 0;
23525bc3cb74SMauro Carvalho Chehab 
23535bc3cb74SMauro Carvalho Chehab 	if (!capable(CAP_SYS_ADMIN))
23545bc3cb74SMauro Carvalho Chehab 		return -EPERM;
23553eef2510SHans Verkuil 	if (p->match.type == V4L2_CHIP_MATCH_SUBDEV) {
235679b0c640SHans Verkuil 		if (vfd->v4l2_dev == NULL)
235779b0c640SHans Verkuil 			return -EINVAL;
23583eef2510SHans Verkuil 		v4l2_device_for_each_subdev(sd, vfd->v4l2_dev)
23593eef2510SHans Verkuil 			if (p->match.addr == idx++)
236079b0c640SHans Verkuil 				return v4l2_subdev_call(sd, core, s_register, p);
236179b0c640SHans Verkuil 		return -EINVAL;
236279b0c640SHans Verkuil 	}
2363191b79b0SHans Verkuil 	if (ops->vidioc_s_register && p->match.type == V4L2_CHIP_MATCH_BRIDGE &&
2364191b79b0SHans Verkuil 	    (ops->vidioc_g_chip_info || p->match.addr == 0))
23655bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_s_register(file, fh, p);
236679b0c640SHans Verkuil 	return -EINVAL;
23675bc3cb74SMauro Carvalho Chehab #else
23685bc3cb74SMauro Carvalho Chehab 	return -ENOTTY;
23695bc3cb74SMauro Carvalho Chehab #endif
23705bc3cb74SMauro Carvalho Chehab }
23715bc3cb74SMauro Carvalho Chehab 
237296b03d2aSHans Verkuil static int v4l_dbg_g_chip_info(const struct v4l2_ioctl_ops *ops,
237379b0c640SHans Verkuil 				struct file *file, void *fh, void *arg)
237479b0c640SHans Verkuil {
2375cd634f1bSHans Verkuil #ifdef CONFIG_VIDEO_ADV_DEBUG
237679b0c640SHans Verkuil 	struct video_device *vfd = video_devdata(file);
237796b03d2aSHans Verkuil 	struct v4l2_dbg_chip_info *p = arg;
237879b0c640SHans Verkuil 	struct v4l2_subdev *sd;
237979b0c640SHans Verkuil 	int idx = 0;
238079b0c640SHans Verkuil 
238179b0c640SHans Verkuil 	switch (p->match.type) {
238279b0c640SHans Verkuil 	case V4L2_CHIP_MATCH_BRIDGE:
238379b0c640SHans Verkuil 		if (ops->vidioc_s_register)
238479b0c640SHans Verkuil 			p->flags |= V4L2_CHIP_FL_WRITABLE;
238579b0c640SHans Verkuil 		if (ops->vidioc_g_register)
238679b0c640SHans Verkuil 			p->flags |= V4L2_CHIP_FL_READABLE;
238779b0c640SHans Verkuil 		strlcpy(p->name, vfd->v4l2_dev->name, sizeof(p->name));
238896b03d2aSHans Verkuil 		if (ops->vidioc_g_chip_info)
238996b03d2aSHans Verkuil 			return ops->vidioc_g_chip_info(file, fh, arg);
23900f0fe4b9SHans Verkuil 		if (p->match.addr)
23910f0fe4b9SHans Verkuil 			return -EINVAL;
239279b0c640SHans Verkuil 		return 0;
239379b0c640SHans Verkuil 
23943eef2510SHans Verkuil 	case V4L2_CHIP_MATCH_SUBDEV:
239579b0c640SHans Verkuil 		if (vfd->v4l2_dev == NULL)
239679b0c640SHans Verkuil 			break;
239779b0c640SHans Verkuil 		v4l2_device_for_each_subdev(sd, vfd->v4l2_dev) {
23983eef2510SHans Verkuil 			if (p->match.addr != idx++)
23993eef2510SHans Verkuil 				continue;
240079b0c640SHans Verkuil 			if (sd->ops->core && sd->ops->core->s_register)
240179b0c640SHans Verkuil 				p->flags |= V4L2_CHIP_FL_WRITABLE;
240279b0c640SHans Verkuil 			if (sd->ops->core && sd->ops->core->g_register)
240379b0c640SHans Verkuil 				p->flags |= V4L2_CHIP_FL_READABLE;
240479b0c640SHans Verkuil 			strlcpy(p->name, sd->name, sizeof(p->name));
240579b0c640SHans Verkuil 			return 0;
240679b0c640SHans Verkuil 		}
240779b0c640SHans Verkuil 		break;
240879b0c640SHans Verkuil 	}
240979b0c640SHans Verkuil 	return -EINVAL;
2410cd634f1bSHans Verkuil #else
2411cd634f1bSHans Verkuil 	return -ENOTTY;
2412cd634f1bSHans Verkuil #endif
241379b0c640SHans Verkuil }
241479b0c640SHans Verkuil 
24155bc3cb74SMauro Carvalho Chehab static int v4l_dqevent(const struct v4l2_ioctl_ops *ops,
24165bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
24175bc3cb74SMauro Carvalho Chehab {
24185bc3cb74SMauro Carvalho Chehab 	return v4l2_event_dequeue(fh, arg, file->f_flags & O_NONBLOCK);
24195bc3cb74SMauro Carvalho Chehab }
24205bc3cb74SMauro Carvalho Chehab 
24215bc3cb74SMauro Carvalho Chehab static int v4l_subscribe_event(const struct v4l2_ioctl_ops *ops,
24225bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
24235bc3cb74SMauro Carvalho Chehab {
24245bc3cb74SMauro Carvalho Chehab 	return ops->vidioc_subscribe_event(fh, arg);
24255bc3cb74SMauro Carvalho Chehab }
24265bc3cb74SMauro Carvalho Chehab 
24275bc3cb74SMauro Carvalho Chehab static int v4l_unsubscribe_event(const struct v4l2_ioctl_ops *ops,
24285bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
24295bc3cb74SMauro Carvalho Chehab {
24305bc3cb74SMauro Carvalho Chehab 	return ops->vidioc_unsubscribe_event(fh, arg);
24315bc3cb74SMauro Carvalho Chehab }
24325bc3cb74SMauro Carvalho Chehab 
24335bc3cb74SMauro Carvalho Chehab static int v4l_g_sliced_vbi_cap(const struct v4l2_ioctl_ops *ops,
24345bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
24355bc3cb74SMauro Carvalho Chehab {
24365bc3cb74SMauro Carvalho Chehab 	struct v4l2_sliced_vbi_cap *p = arg;
24374b20259fSHans Verkuil 	int ret = check_fmt(file, p->type);
24384b20259fSHans Verkuil 
24394b20259fSHans Verkuil 	if (ret)
24404b20259fSHans Verkuil 		return ret;
24415bc3cb74SMauro Carvalho Chehab 
24425bc3cb74SMauro Carvalho Chehab 	/* Clear up to type, everything after type is zeroed already */
24435bc3cb74SMauro Carvalho Chehab 	memset(p, 0, offsetof(struct v4l2_sliced_vbi_cap, type));
24445bc3cb74SMauro Carvalho Chehab 
24455bc3cb74SMauro Carvalho Chehab 	return ops->vidioc_g_sliced_vbi_cap(file, fh, p);
24465bc3cb74SMauro Carvalho Chehab }
24475bc3cb74SMauro Carvalho Chehab 
24485bc3cb74SMauro Carvalho Chehab static int v4l_enum_freq_bands(const struct v4l2_ioctl_ops *ops,
24495bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
24505bc3cb74SMauro Carvalho Chehab {
24515bc3cb74SMauro Carvalho Chehab 	struct video_device *vfd = video_devdata(file);
24525bc3cb74SMauro Carvalho Chehab 	struct v4l2_frequency_band *p = arg;
24535bc3cb74SMauro Carvalho Chehab 	enum v4l2_tuner_type type;
24545bc3cb74SMauro Carvalho Chehab 	int err;
24555bc3cb74SMauro Carvalho Chehab 
245684099a28SAntti Palosaari 	if (vfd->vfl_type == VFL_TYPE_SDR) {
2457f3c3ececSAntti Palosaari 		if (p->type != V4L2_TUNER_SDR && p->type != V4L2_TUNER_RF)
245884099a28SAntti Palosaari 			return -EINVAL;
245984099a28SAntti Palosaari 		type = p->type;
246084099a28SAntti Palosaari 	} else {
24615bc3cb74SMauro Carvalho Chehab 		type = (vfd->vfl_type == VFL_TYPE_RADIO) ?
24625bc3cb74SMauro Carvalho Chehab 				V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
24635bc3cb74SMauro Carvalho Chehab 		if (type != p->type)
24645bc3cb74SMauro Carvalho Chehab 			return -EINVAL;
246584099a28SAntti Palosaari 	}
2466a7f404afSHans Verkuil 	if (ops->vidioc_enum_freq_bands) {
2467a7f404afSHans Verkuil 		err = ops->vidioc_enum_freq_bands(file, fh, p);
2468a7f404afSHans Verkuil 		if (err != -ENOTTY)
2469a7f404afSHans Verkuil 			return err;
2470a7f404afSHans Verkuil 	}
247173f35418SHans Verkuil 	if (is_valid_ioctl(vfd, VIDIOC_G_TUNER)) {
24725bc3cb74SMauro Carvalho Chehab 		struct v4l2_tuner t = {
24735bc3cb74SMauro Carvalho Chehab 			.index = p->tuner,
24745bc3cb74SMauro Carvalho Chehab 			.type = type,
24755bc3cb74SMauro Carvalho Chehab 		};
24765bc3cb74SMauro Carvalho Chehab 
247779e8c7beSMauro Carvalho Chehab 		if (p->index)
247879e8c7beSMauro Carvalho Chehab 			return -EINVAL;
24795bc3cb74SMauro Carvalho Chehab 		err = ops->vidioc_g_tuner(file, fh, &t);
24805bc3cb74SMauro Carvalho Chehab 		if (err)
24815bc3cb74SMauro Carvalho Chehab 			return err;
24825bc3cb74SMauro Carvalho Chehab 		p->capability = t.capability | V4L2_TUNER_CAP_FREQ_BANDS;
24835bc3cb74SMauro Carvalho Chehab 		p->rangelow = t.rangelow;
24845bc3cb74SMauro Carvalho Chehab 		p->rangehigh = t.rangehigh;
24855bc3cb74SMauro Carvalho Chehab 		p->modulation = (type == V4L2_TUNER_RADIO) ?
24865bc3cb74SMauro Carvalho Chehab 			V4L2_BAND_MODULATION_FM : V4L2_BAND_MODULATION_VSB;
24875bc3cb74SMauro Carvalho Chehab 		return 0;
24885bc3cb74SMauro Carvalho Chehab 	}
248973f35418SHans Verkuil 	if (is_valid_ioctl(vfd, VIDIOC_G_MODULATOR)) {
24905bc3cb74SMauro Carvalho Chehab 		struct v4l2_modulator m = {
24915bc3cb74SMauro Carvalho Chehab 			.index = p->tuner,
24925bc3cb74SMauro Carvalho Chehab 		};
24935bc3cb74SMauro Carvalho Chehab 
24945bc3cb74SMauro Carvalho Chehab 		if (type != V4L2_TUNER_RADIO)
24955bc3cb74SMauro Carvalho Chehab 			return -EINVAL;
249679e8c7beSMauro Carvalho Chehab 		if (p->index)
249779e8c7beSMauro Carvalho Chehab 			return -EINVAL;
24985bc3cb74SMauro Carvalho Chehab 		err = ops->vidioc_g_modulator(file, fh, &m);
24995bc3cb74SMauro Carvalho Chehab 		if (err)
25005bc3cb74SMauro Carvalho Chehab 			return err;
25015bc3cb74SMauro Carvalho Chehab 		p->capability = m.capability | V4L2_TUNER_CAP_FREQ_BANDS;
25025bc3cb74SMauro Carvalho Chehab 		p->rangelow = m.rangelow;
25035bc3cb74SMauro Carvalho Chehab 		p->rangehigh = m.rangehigh;
25045bc3cb74SMauro Carvalho Chehab 		p->modulation = (type == V4L2_TUNER_RADIO) ?
25055bc3cb74SMauro Carvalho Chehab 			V4L2_BAND_MODULATION_FM : V4L2_BAND_MODULATION_VSB;
25065bc3cb74SMauro Carvalho Chehab 		return 0;
25075bc3cb74SMauro Carvalho Chehab 	}
25085bc3cb74SMauro Carvalho Chehab 	return -ENOTTY;
25095bc3cb74SMauro Carvalho Chehab }
25105bc3cb74SMauro Carvalho Chehab 
25115bc3cb74SMauro Carvalho Chehab struct v4l2_ioctl_info {
25125bc3cb74SMauro Carvalho Chehab 	unsigned int ioctl;
25135bc3cb74SMauro Carvalho Chehab 	u32 flags;
25145bc3cb74SMauro Carvalho Chehab 	const char * const name;
25155bc3cb74SMauro Carvalho Chehab 	union {
25165bc3cb74SMauro Carvalho Chehab 		u32 offset;
25175bc3cb74SMauro Carvalho Chehab 		int (*func)(const struct v4l2_ioctl_ops *ops,
25185bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *p);
25195bc3cb74SMauro Carvalho Chehab 	} u;
25205bc3cb74SMauro Carvalho Chehab 	void (*debug)(const void *arg, bool write_only);
25215bc3cb74SMauro Carvalho Chehab };
25225bc3cb74SMauro Carvalho Chehab 
25235bc3cb74SMauro Carvalho Chehab /* This control needs a priority check */
25245bc3cb74SMauro Carvalho Chehab #define INFO_FL_PRIO		(1 << 0)
25255bc3cb74SMauro Carvalho Chehab /* This control can be valid if the filehandle passes a control handler. */
25265bc3cb74SMauro Carvalho Chehab #define INFO_FL_CTRL		(1 << 1)
25275bc3cb74SMauro Carvalho Chehab /* This is a standard ioctl, no need for special code */
25285bc3cb74SMauro Carvalho Chehab #define INFO_FL_STD		(1 << 2)
25295bc3cb74SMauro Carvalho Chehab /* This is ioctl has its own function */
25305bc3cb74SMauro Carvalho Chehab #define INFO_FL_FUNC		(1 << 3)
25315bc3cb74SMauro Carvalho Chehab /* Queuing ioctl */
25325bc3cb74SMauro Carvalho Chehab #define INFO_FL_QUEUE		(1 << 4)
2533043f77edSHans Verkuil /* Always copy back result, even on error */
2534043f77edSHans Verkuil #define INFO_FL_ALWAYS_COPY	(1 << 5)
25355bc3cb74SMauro Carvalho Chehab /* Zero struct from after the field to the end */
25365bc3cb74SMauro Carvalho Chehab #define INFO_FL_CLEAR(v4l2_struct, field)			\
25375bc3cb74SMauro Carvalho Chehab 	((offsetof(struct v4l2_struct, field) +			\
25385bc3cb74SMauro Carvalho Chehab 	  sizeof(((struct v4l2_struct *)0)->field)) << 16)
25395bc3cb74SMauro Carvalho Chehab #define INFO_FL_CLEAR_MASK 	(_IOC_SIZEMASK << 16)
25405bc3cb74SMauro Carvalho Chehab 
25415bc3cb74SMauro Carvalho Chehab #define IOCTL_INFO_STD(_ioctl, _vidioc, _debug, _flags)			\
25425bc3cb74SMauro Carvalho Chehab 	[_IOC_NR(_ioctl)] = {						\
25435bc3cb74SMauro Carvalho Chehab 		.ioctl = _ioctl,					\
25445bc3cb74SMauro Carvalho Chehab 		.flags = _flags | INFO_FL_STD,				\
25455bc3cb74SMauro Carvalho Chehab 		.name = #_ioctl,					\
25465bc3cb74SMauro Carvalho Chehab 		.u.offset = offsetof(struct v4l2_ioctl_ops, _vidioc),	\
25475bc3cb74SMauro Carvalho Chehab 		.debug = _debug,					\
25485bc3cb74SMauro Carvalho Chehab 	}
25495bc3cb74SMauro Carvalho Chehab 
25505bc3cb74SMauro Carvalho Chehab #define IOCTL_INFO_FNC(_ioctl, _func, _debug, _flags)			\
25515bc3cb74SMauro Carvalho Chehab 	[_IOC_NR(_ioctl)] = {						\
25525bc3cb74SMauro Carvalho Chehab 		.ioctl = _ioctl,					\
25535bc3cb74SMauro Carvalho Chehab 		.flags = _flags | INFO_FL_FUNC,				\
25545bc3cb74SMauro Carvalho Chehab 		.name = #_ioctl,					\
25555bc3cb74SMauro Carvalho Chehab 		.u.func = _func,					\
25565bc3cb74SMauro Carvalho Chehab 		.debug = _debug,					\
25575bc3cb74SMauro Carvalho Chehab 	}
25585bc3cb74SMauro Carvalho Chehab 
25595bc3cb74SMauro Carvalho Chehab static struct v4l2_ioctl_info v4l2_ioctls[] = {
25605bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_QUERYCAP, v4l_querycap, v4l_print_querycap, 0),
25615bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_ENUM_FMT, v4l_enum_fmt, v4l_print_fmtdesc, INFO_FL_CLEAR(v4l2_fmtdesc, type)),
2562e5ce558aSHans Verkuil 	IOCTL_INFO_FNC(VIDIOC_G_FMT, v4l_g_fmt, v4l_print_format, 0),
25635bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_S_FMT, v4l_s_fmt, v4l_print_format, INFO_FL_PRIO),
25645bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_REQBUFS, v4l_reqbufs, v4l_print_requestbuffers, INFO_FL_PRIO | INFO_FL_QUEUE),
25655bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_QUERYBUF, v4l_querybuf, v4l_print_buffer, INFO_FL_QUEUE | INFO_FL_CLEAR(v4l2_buffer, length)),
25665bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_STD(VIDIOC_G_FBUF, vidioc_g_fbuf, v4l_print_framebuffer, 0),
25675bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_STD(VIDIOC_S_FBUF, vidioc_s_fbuf, v4l_print_framebuffer, INFO_FL_PRIO),
2568737c097bSHans Verkuil 	IOCTL_INFO_FNC(VIDIOC_OVERLAY, v4l_overlay, v4l_print_u32, INFO_FL_PRIO),
25695bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_QBUF, v4l_qbuf, v4l_print_buffer, INFO_FL_QUEUE),
2570b799d09aSTomasz Stanislawski 	IOCTL_INFO_STD(VIDIOC_EXPBUF, vidioc_expbuf, v4l_print_exportbuffer, INFO_FL_QUEUE | INFO_FL_CLEAR(v4l2_exportbuffer, flags)),
25715bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_DQBUF, v4l_dqbuf, v4l_print_buffer, INFO_FL_QUEUE),
25725bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_STREAMON, v4l_streamon, v4l_print_buftype, INFO_FL_PRIO | INFO_FL_QUEUE),
25735bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_STREAMOFF, v4l_streamoff, v4l_print_buftype, INFO_FL_PRIO | INFO_FL_QUEUE),
25745bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_G_PARM, v4l_g_parm, v4l_print_streamparm, INFO_FL_CLEAR(v4l2_streamparm, type)),
25755bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_S_PARM, v4l_s_parm, v4l_print_streamparm, INFO_FL_PRIO),
2576ca371575SHans Verkuil 	IOCTL_INFO_STD(VIDIOC_G_STD, vidioc_g_std, v4l_print_std, 0),
25775bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_S_STD, v4l_s_std, v4l_print_std, INFO_FL_PRIO),
25785bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_ENUMSTD, v4l_enumstd, v4l_print_standard, INFO_FL_CLEAR(v4l2_standard, index)),
25795bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_ENUMINPUT, v4l_enuminput, v4l_print_enuminput, INFO_FL_CLEAR(v4l2_input, index)),
25805bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_G_CTRL, v4l_g_ctrl, v4l_print_control, INFO_FL_CTRL | INFO_FL_CLEAR(v4l2_control, id)),
25815bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_S_CTRL, v4l_s_ctrl, v4l_print_control, INFO_FL_PRIO | INFO_FL_CTRL),
25825bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_G_TUNER, v4l_g_tuner, v4l_print_tuner, INFO_FL_CLEAR(v4l2_tuner, index)),
25835bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_S_TUNER, v4l_s_tuner, v4l_print_tuner, INFO_FL_PRIO),
25845bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_STD(VIDIOC_G_AUDIO, vidioc_g_audio, v4l_print_audio, 0),
25855bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_STD(VIDIOC_S_AUDIO, vidioc_s_audio, v4l_print_audio, INFO_FL_PRIO),
25865bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_QUERYCTRL, v4l_queryctrl, v4l_print_queryctrl, INFO_FL_CTRL | INFO_FL_CLEAR(v4l2_queryctrl, id)),
25875bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_QUERYMENU, v4l_querymenu, v4l_print_querymenu, INFO_FL_CTRL | INFO_FL_CLEAR(v4l2_querymenu, index)),
25885bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_STD(VIDIOC_G_INPUT, vidioc_g_input, v4l_print_u32, 0),
25895bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_S_INPUT, v4l_s_input, v4l_print_u32, INFO_FL_PRIO),
2590043f77edSHans Verkuil 	IOCTL_INFO_STD(VIDIOC_G_EDID, vidioc_g_edid, v4l_print_edid, INFO_FL_ALWAYS_COPY),
2591043f77edSHans Verkuil 	IOCTL_INFO_STD(VIDIOC_S_EDID, vidioc_s_edid, v4l_print_edid, INFO_FL_PRIO | INFO_FL_ALWAYS_COPY),
25925bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_STD(VIDIOC_G_OUTPUT, vidioc_g_output, v4l_print_u32, 0),
25935bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_S_OUTPUT, v4l_s_output, v4l_print_u32, INFO_FL_PRIO),
25945bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_ENUMOUTPUT, v4l_enumoutput, v4l_print_enumoutput, INFO_FL_CLEAR(v4l2_output, index)),
25955bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_STD(VIDIOC_G_AUDOUT, vidioc_g_audout, v4l_print_audioout, 0),
25965bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_STD(VIDIOC_S_AUDOUT, vidioc_s_audout, v4l_print_audioout, INFO_FL_PRIO),
25975bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_G_MODULATOR, v4l_g_modulator, v4l_print_modulator, INFO_FL_CLEAR(v4l2_modulator, index)),
25984124a3c4SAntti Palosaari 	IOCTL_INFO_FNC(VIDIOC_S_MODULATOR, v4l_s_modulator, v4l_print_modulator, INFO_FL_PRIO),
25995bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_G_FREQUENCY, v4l_g_frequency, v4l_print_frequency, INFO_FL_CLEAR(v4l2_frequency, tuner)),
26005bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_S_FREQUENCY, v4l_s_frequency, v4l_print_frequency, INFO_FL_PRIO),
26015bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_CROPCAP, v4l_cropcap, v4l_print_cropcap, INFO_FL_CLEAR(v4l2_cropcap, type)),
26025bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_G_CROP, v4l_g_crop, v4l_print_crop, INFO_FL_CLEAR(v4l2_crop, type)),
26035bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_S_CROP, v4l_s_crop, v4l_print_crop, INFO_FL_PRIO),
2604eaec420fSHans Verkuil 	IOCTL_INFO_FNC(VIDIOC_G_SELECTION, v4l_g_selection, v4l_print_selection, INFO_FL_CLEAR(v4l2_selection, r)),
2605eaec420fSHans Verkuil 	IOCTL_INFO_FNC(VIDIOC_S_SELECTION, v4l_s_selection, v4l_print_selection, INFO_FL_PRIO | INFO_FL_CLEAR(v4l2_selection, r)),
26065bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_STD(VIDIOC_G_JPEGCOMP, vidioc_g_jpegcomp, v4l_print_jpegcompression, 0),
26075bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_STD(VIDIOC_S_JPEGCOMP, vidioc_s_jpegcomp, v4l_print_jpegcompression, INFO_FL_PRIO),
26085bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_QUERYSTD, v4l_querystd, v4l_print_std, 0),
26095bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_TRY_FMT, v4l_try_fmt, v4l_print_format, 0),
26105bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_STD(VIDIOC_ENUMAUDIO, vidioc_enumaudio, v4l_print_audio, INFO_FL_CLEAR(v4l2_audio, index)),
26115bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_STD(VIDIOC_ENUMAUDOUT, vidioc_enumaudout, v4l_print_audioout, INFO_FL_CLEAR(v4l2_audioout, index)),
26125bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_G_PRIORITY, v4l_g_priority, v4l_print_u32, 0),
26135bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_S_PRIORITY, v4l_s_priority, v4l_print_u32, INFO_FL_PRIO),
26145bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_G_SLICED_VBI_CAP, v4l_g_sliced_vbi_cap, v4l_print_sliced_vbi_cap, INFO_FL_CLEAR(v4l2_sliced_vbi_cap, type)),
26155bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_LOG_STATUS, v4l_log_status, v4l_print_newline, 0),
26165bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_G_EXT_CTRLS, v4l_g_ext_ctrls, v4l_print_ext_controls, INFO_FL_CTRL),
26175bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_S_EXT_CTRLS, v4l_s_ext_ctrls, v4l_print_ext_controls, INFO_FL_PRIO | INFO_FL_CTRL),
26185bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_TRY_EXT_CTRLS, v4l_try_ext_ctrls, v4l_print_ext_controls, INFO_FL_CTRL),
26195bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_STD(VIDIOC_ENUM_FRAMESIZES, vidioc_enum_framesizes, v4l_print_frmsizeenum, INFO_FL_CLEAR(v4l2_frmsizeenum, pixel_format)),
26205bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_STD(VIDIOC_ENUM_FRAMEINTERVALS, vidioc_enum_frameintervals, v4l_print_frmivalenum, INFO_FL_CLEAR(v4l2_frmivalenum, height)),
26215bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_STD(VIDIOC_G_ENC_INDEX, vidioc_g_enc_index, v4l_print_enc_idx, 0),
26225bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_STD(VIDIOC_ENCODER_CMD, vidioc_encoder_cmd, v4l_print_encoder_cmd, INFO_FL_PRIO | INFO_FL_CLEAR(v4l2_encoder_cmd, flags)),
26235bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_STD(VIDIOC_TRY_ENCODER_CMD, vidioc_try_encoder_cmd, v4l_print_encoder_cmd, INFO_FL_CLEAR(v4l2_encoder_cmd, flags)),
26245bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_STD(VIDIOC_DECODER_CMD, vidioc_decoder_cmd, v4l_print_decoder_cmd, INFO_FL_PRIO),
26255bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_STD(VIDIOC_TRY_DECODER_CMD, vidioc_try_decoder_cmd, v4l_print_decoder_cmd, 0),
26265bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_DBG_S_REGISTER, v4l_dbg_s_register, v4l_print_dbg_register, 0),
26275bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_DBG_G_REGISTER, v4l_dbg_g_register, v4l_print_dbg_register, 0),
26285bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_S_HW_FREQ_SEEK, v4l_s_hw_freq_seek, v4l_print_hw_freq_seek, INFO_FL_PRIO),
2629f932af80SHans Verkuil 	IOCTL_INFO_STD(VIDIOC_S_DV_TIMINGS, vidioc_s_dv_timings, v4l_print_dv_timings, INFO_FL_PRIO | INFO_FL_CLEAR(v4l2_dv_timings, bt.flags)),
26305bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_STD(VIDIOC_G_DV_TIMINGS, vidioc_g_dv_timings, v4l_print_dv_timings, 0),
26315bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_DQEVENT, v4l_dqevent, v4l_print_event, 0),
26325bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_SUBSCRIBE_EVENT, v4l_subscribe_event, v4l_print_event_subscription, 0),
26335bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_UNSUBSCRIBE_EVENT, v4l_unsubscribe_event, v4l_print_event_subscription, 0),
26345bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_CREATE_BUFS, v4l_create_bufs, v4l_print_create_buffers, INFO_FL_PRIO | INFO_FL_QUEUE),
26355bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_PREPARE_BUF, v4l_prepare_buf, v4l_print_buffer, INFO_FL_QUEUE),
2636f932af80SHans Verkuil 	IOCTL_INFO_STD(VIDIOC_ENUM_DV_TIMINGS, vidioc_enum_dv_timings, v4l_print_enum_dv_timings, INFO_FL_CLEAR(v4l2_enum_dv_timings, pad)),
2637043f77edSHans Verkuil 	IOCTL_INFO_STD(VIDIOC_QUERY_DV_TIMINGS, vidioc_query_dv_timings, v4l_print_dv_timings, INFO_FL_ALWAYS_COPY),
26385bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_STD(VIDIOC_DV_TIMINGS_CAP, vidioc_dv_timings_cap, v4l_print_dv_timings_cap, INFO_FL_CLEAR(v4l2_dv_timings_cap, type)),
26395bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_ENUM_FREQ_BANDS, v4l_enum_freq_bands, v4l_print_freq_band, 0),
264096b03d2aSHans Verkuil 	IOCTL_INFO_FNC(VIDIOC_DBG_G_CHIP_INFO, v4l_dbg_g_chip_info, v4l_print_dbg_chip_info, INFO_FL_CLEAR(v4l2_dbg_chip_info, match)),
2641e6bee368SHans Verkuil 	IOCTL_INFO_FNC(VIDIOC_QUERY_EXT_CTRL, v4l_query_ext_ctrl, v4l_print_query_ext_ctrl, INFO_FL_CTRL | INFO_FL_CLEAR(v4l2_query_ext_ctrl, id)),
26425bc3cb74SMauro Carvalho Chehab };
26435bc3cb74SMauro Carvalho Chehab #define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls)
26445bc3cb74SMauro Carvalho Chehab 
26455bc3cb74SMauro Carvalho Chehab bool v4l2_is_known_ioctl(unsigned int cmd)
26465bc3cb74SMauro Carvalho Chehab {
26475bc3cb74SMauro Carvalho Chehab 	if (_IOC_NR(cmd) >= V4L2_IOCTLS)
26485bc3cb74SMauro Carvalho Chehab 		return false;
26495bc3cb74SMauro Carvalho Chehab 	return v4l2_ioctls[_IOC_NR(cmd)].ioctl == cmd;
26505bc3cb74SMauro Carvalho Chehab }
26515bc3cb74SMauro Carvalho Chehab 
26525bc3cb74SMauro Carvalho Chehab struct mutex *v4l2_ioctl_get_lock(struct video_device *vdev, unsigned cmd)
26535bc3cb74SMauro Carvalho Chehab {
26545bc3cb74SMauro Carvalho Chehab 	if (_IOC_NR(cmd) >= V4L2_IOCTLS)
26555bc3cb74SMauro Carvalho Chehab 		return vdev->lock;
26565bc3cb74SMauro Carvalho Chehab 	if (test_bit(_IOC_NR(cmd), vdev->disable_locking))
26575bc3cb74SMauro Carvalho Chehab 		return NULL;
26585bc3cb74SMauro Carvalho Chehab 	if (vdev->queue && vdev->queue->lock &&
26595bc3cb74SMauro Carvalho Chehab 			(v4l2_ioctls[_IOC_NR(cmd)].flags & INFO_FL_QUEUE))
26605bc3cb74SMauro Carvalho Chehab 		return vdev->queue->lock;
26615bc3cb74SMauro Carvalho Chehab 	return vdev->lock;
26625bc3cb74SMauro Carvalho Chehab }
26635bc3cb74SMauro Carvalho Chehab 
26645bc3cb74SMauro Carvalho Chehab /* Common ioctl debug function. This function can be used by
26655bc3cb74SMauro Carvalho Chehab    external ioctl messages as well as internal V4L ioctl */
26665bc3cb74SMauro Carvalho Chehab void v4l_printk_ioctl(const char *prefix, unsigned int cmd)
26675bc3cb74SMauro Carvalho Chehab {
26685bc3cb74SMauro Carvalho Chehab 	const char *dir, *type;
26695bc3cb74SMauro Carvalho Chehab 
26705bc3cb74SMauro Carvalho Chehab 	if (prefix)
26715bc3cb74SMauro Carvalho Chehab 		printk(KERN_DEBUG "%s: ", prefix);
26725bc3cb74SMauro Carvalho Chehab 
26735bc3cb74SMauro Carvalho Chehab 	switch (_IOC_TYPE(cmd)) {
26745bc3cb74SMauro Carvalho Chehab 	case 'd':
26755bc3cb74SMauro Carvalho Chehab 		type = "v4l2_int";
26765bc3cb74SMauro Carvalho Chehab 		break;
26775bc3cb74SMauro Carvalho Chehab 	case 'V':
26785bc3cb74SMauro Carvalho Chehab 		if (_IOC_NR(cmd) >= V4L2_IOCTLS) {
26795bc3cb74SMauro Carvalho Chehab 			type = "v4l2";
26805bc3cb74SMauro Carvalho Chehab 			break;
26815bc3cb74SMauro Carvalho Chehab 		}
26825bc3cb74SMauro Carvalho Chehab 		pr_cont("%s", v4l2_ioctls[_IOC_NR(cmd)].name);
26835bc3cb74SMauro Carvalho Chehab 		return;
26845bc3cb74SMauro Carvalho Chehab 	default:
26855bc3cb74SMauro Carvalho Chehab 		type = "unknown";
26865bc3cb74SMauro Carvalho Chehab 		break;
26875bc3cb74SMauro Carvalho Chehab 	}
26885bc3cb74SMauro Carvalho Chehab 
26895bc3cb74SMauro Carvalho Chehab 	switch (_IOC_DIR(cmd)) {
26905bc3cb74SMauro Carvalho Chehab 	case _IOC_NONE:              dir = "--"; break;
26915bc3cb74SMauro Carvalho Chehab 	case _IOC_READ:              dir = "r-"; break;
26925bc3cb74SMauro Carvalho Chehab 	case _IOC_WRITE:             dir = "-w"; break;
26935bc3cb74SMauro Carvalho Chehab 	case _IOC_READ | _IOC_WRITE: dir = "rw"; break;
26945bc3cb74SMauro Carvalho Chehab 	default:                     dir = "*ERR*"; break;
26955bc3cb74SMauro Carvalho Chehab 	}
26965bc3cb74SMauro Carvalho Chehab 	pr_cont("%s ioctl '%c', dir=%s, #%d (0x%08x)",
26975bc3cb74SMauro Carvalho Chehab 		type, _IOC_TYPE(cmd), dir, _IOC_NR(cmd), cmd);
26985bc3cb74SMauro Carvalho Chehab }
26995bc3cb74SMauro Carvalho Chehab EXPORT_SYMBOL(v4l_printk_ioctl);
27005bc3cb74SMauro Carvalho Chehab 
27015bc3cb74SMauro Carvalho Chehab static long __video_do_ioctl(struct file *file,
27025bc3cb74SMauro Carvalho Chehab 		unsigned int cmd, void *arg)
27035bc3cb74SMauro Carvalho Chehab {
27045bc3cb74SMauro Carvalho Chehab 	struct video_device *vfd = video_devdata(file);
27055bc3cb74SMauro Carvalho Chehab 	const struct v4l2_ioctl_ops *ops = vfd->ioctl_ops;
27065bc3cb74SMauro Carvalho Chehab 	bool write_only = false;
27075bc3cb74SMauro Carvalho Chehab 	struct v4l2_ioctl_info default_info;
27085bc3cb74SMauro Carvalho Chehab 	const struct v4l2_ioctl_info *info;
27095bc3cb74SMauro Carvalho Chehab 	void *fh = file->private_data;
27105bc3cb74SMauro Carvalho Chehab 	struct v4l2_fh *vfh = NULL;
271117028cdbSHans Verkuil 	int dev_debug = vfd->dev_debug;
27125bc3cb74SMauro Carvalho Chehab 	long ret = -ENOTTY;
27135bc3cb74SMauro Carvalho Chehab 
27145bc3cb74SMauro Carvalho Chehab 	if (ops == NULL) {
27155bc3cb74SMauro Carvalho Chehab 		pr_warn("%s: has no ioctl_ops.\n",
27165bc3cb74SMauro Carvalho Chehab 				video_device_node_name(vfd));
27175bc3cb74SMauro Carvalho Chehab 		return ret;
27185bc3cb74SMauro Carvalho Chehab 	}
27195bc3cb74SMauro Carvalho Chehab 
2720b7284bb0SRamakrishnan Muthukrishnan 	if (test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags))
27215bc3cb74SMauro Carvalho Chehab 		vfh = file->private_data;
27225bc3cb74SMauro Carvalho Chehab 
27235bc3cb74SMauro Carvalho Chehab 	if (v4l2_is_known_ioctl(cmd)) {
27245bc3cb74SMauro Carvalho Chehab 		info = &v4l2_ioctls[_IOC_NR(cmd)];
27255bc3cb74SMauro Carvalho Chehab 
27265bc3cb74SMauro Carvalho Chehab 		if (!test_bit(_IOC_NR(cmd), vfd->valid_ioctls) &&
27275bc3cb74SMauro Carvalho Chehab 		    !((info->flags & INFO_FL_CTRL) && vfh && vfh->ctrl_handler))
27285bc3cb74SMauro Carvalho Chehab 			goto done;
27295bc3cb74SMauro Carvalho Chehab 
2730b7284bb0SRamakrishnan Muthukrishnan 		if (vfh && (info->flags & INFO_FL_PRIO)) {
27315bc3cb74SMauro Carvalho Chehab 			ret = v4l2_prio_check(vfd->prio, vfh->prio);
27325bc3cb74SMauro Carvalho Chehab 			if (ret)
27335bc3cb74SMauro Carvalho Chehab 				goto done;
27345bc3cb74SMauro Carvalho Chehab 		}
27355bc3cb74SMauro Carvalho Chehab 	} else {
27365bc3cb74SMauro Carvalho Chehab 		default_info.ioctl = cmd;
27375bc3cb74SMauro Carvalho Chehab 		default_info.flags = 0;
27385bc3cb74SMauro Carvalho Chehab 		default_info.debug = v4l_print_default;
27395bc3cb74SMauro Carvalho Chehab 		info = &default_info;
27405bc3cb74SMauro Carvalho Chehab 	}
27415bc3cb74SMauro Carvalho Chehab 
27425bc3cb74SMauro Carvalho Chehab 	write_only = _IOC_DIR(cmd) == _IOC_WRITE;
27435bc3cb74SMauro Carvalho Chehab 	if (info->flags & INFO_FL_STD) {
27445bc3cb74SMauro Carvalho Chehab 		typedef int (*vidioc_op)(struct file *file, void *fh, void *p);
27455bc3cb74SMauro Carvalho Chehab 		const void *p = vfd->ioctl_ops;
27465bc3cb74SMauro Carvalho Chehab 		const vidioc_op *vidioc = p + info->u.offset;
27475bc3cb74SMauro Carvalho Chehab 
27485bc3cb74SMauro Carvalho Chehab 		ret = (*vidioc)(file, fh, arg);
27495bc3cb74SMauro Carvalho Chehab 	} else if (info->flags & INFO_FL_FUNC) {
27505bc3cb74SMauro Carvalho Chehab 		ret = info->u.func(ops, file, fh, arg);
27515bc3cb74SMauro Carvalho Chehab 	} else if (!ops->vidioc_default) {
27525bc3cb74SMauro Carvalho Chehab 		ret = -ENOTTY;
27535bc3cb74SMauro Carvalho Chehab 	} else {
27545bc3cb74SMauro Carvalho Chehab 		ret = ops->vidioc_default(file, fh,
2755b7284bb0SRamakrishnan Muthukrishnan 			vfh ? v4l2_prio_check(vfd->prio, vfh->prio) >= 0 : 0,
27565bc3cb74SMauro Carvalho Chehab 			cmd, arg);
27575bc3cb74SMauro Carvalho Chehab 	}
27585bc3cb74SMauro Carvalho Chehab 
27595bc3cb74SMauro Carvalho Chehab done:
276017028cdbSHans Verkuil 	if (dev_debug & (V4L2_DEV_DEBUG_IOCTL | V4L2_DEV_DEBUG_IOCTL_ARG)) {
276117028cdbSHans Verkuil 		if (!(dev_debug & V4L2_DEV_DEBUG_STREAMING) &&
276217028cdbSHans Verkuil 		    (cmd == VIDIOC_QBUF || cmd == VIDIOC_DQBUF))
276317028cdbSHans Verkuil 			return ret;
276417028cdbSHans Verkuil 
27655bc3cb74SMauro Carvalho Chehab 		v4l_printk_ioctl(video_device_node_name(vfd), cmd);
27665bc3cb74SMauro Carvalho Chehab 		if (ret < 0)
2767505d04bdSHans Verkuil 			pr_cont(": error %ld", ret);
276817028cdbSHans Verkuil 		if (!(dev_debug & V4L2_DEV_DEBUG_IOCTL_ARG))
27695bc3cb74SMauro Carvalho Chehab 			pr_cont("\n");
27705bc3cb74SMauro Carvalho Chehab 		else if (_IOC_DIR(cmd) == _IOC_NONE)
27715bc3cb74SMauro Carvalho Chehab 			info->debug(arg, write_only);
27725bc3cb74SMauro Carvalho Chehab 		else {
27735bc3cb74SMauro Carvalho Chehab 			pr_cont(": ");
27745bc3cb74SMauro Carvalho Chehab 			info->debug(arg, write_only);
27755bc3cb74SMauro Carvalho Chehab 		}
27765bc3cb74SMauro Carvalho Chehab 	}
27775bc3cb74SMauro Carvalho Chehab 
27785bc3cb74SMauro Carvalho Chehab 	return ret;
27795bc3cb74SMauro Carvalho Chehab }
27805bc3cb74SMauro Carvalho Chehab 
27815bc3cb74SMauro Carvalho Chehab static int check_array_args(unsigned int cmd, void *parg, size_t *array_size,
2782ba2d35c1SHans Verkuil 			    void __user **user_ptr, void ***kernel_ptr)
27835bc3cb74SMauro Carvalho Chehab {
27845bc3cb74SMauro Carvalho Chehab 	int ret = 0;
27855bc3cb74SMauro Carvalho Chehab 
27865bc3cb74SMauro Carvalho Chehab 	switch (cmd) {
278796b1a702SHans Verkuil 	case VIDIOC_PREPARE_BUF:
27885bc3cb74SMauro Carvalho Chehab 	case VIDIOC_QUERYBUF:
27895bc3cb74SMauro Carvalho Chehab 	case VIDIOC_QBUF:
27905bc3cb74SMauro Carvalho Chehab 	case VIDIOC_DQBUF: {
27915bc3cb74SMauro Carvalho Chehab 		struct v4l2_buffer *buf = parg;
27925bc3cb74SMauro Carvalho Chehab 
27935bc3cb74SMauro Carvalho Chehab 		if (V4L2_TYPE_IS_MULTIPLANAR(buf->type) && buf->length > 0) {
27945bc3cb74SMauro Carvalho Chehab 			if (buf->length > VIDEO_MAX_PLANES) {
27955bc3cb74SMauro Carvalho Chehab 				ret = -EINVAL;
27965bc3cb74SMauro Carvalho Chehab 				break;
27975bc3cb74SMauro Carvalho Chehab 			}
27985bc3cb74SMauro Carvalho Chehab 			*user_ptr = (void __user *)buf->m.planes;
2799ba2d35c1SHans Verkuil 			*kernel_ptr = (void **)&buf->m.planes;
28005bc3cb74SMauro Carvalho Chehab 			*array_size = sizeof(struct v4l2_plane) * buf->length;
28015bc3cb74SMauro Carvalho Chehab 			ret = 1;
28025bc3cb74SMauro Carvalho Chehab 		}
28035bc3cb74SMauro Carvalho Chehab 		break;
28045bc3cb74SMauro Carvalho Chehab 	}
28055bc3cb74SMauro Carvalho Chehab 
2806dd519bb3SHans Verkuil 	case VIDIOC_G_EDID:
2807dd519bb3SHans Verkuil 	case VIDIOC_S_EDID: {
2808dd519bb3SHans Verkuil 		struct v4l2_edid *edid = parg;
2809ed45ce2cSHans Verkuil 
2810ed45ce2cSHans Verkuil 		if (edid->blocks) {
28111b8b10ccSHans Verkuil 			if (edid->blocks > 256) {
28121b8b10ccSHans Verkuil 				ret = -EINVAL;
28131b8b10ccSHans Verkuil 				break;
28141b8b10ccSHans Verkuil 			}
2815ed45ce2cSHans Verkuil 			*user_ptr = (void __user *)edid->edid;
2816ba2d35c1SHans Verkuil 			*kernel_ptr = (void **)&edid->edid;
2817ed45ce2cSHans Verkuil 			*array_size = edid->blocks * 128;
2818ed45ce2cSHans Verkuil 			ret = 1;
2819ed45ce2cSHans Verkuil 		}
2820ed45ce2cSHans Verkuil 		break;
2821ed45ce2cSHans Verkuil 	}
2822ed45ce2cSHans Verkuil 
28235bc3cb74SMauro Carvalho Chehab 	case VIDIOC_S_EXT_CTRLS:
28245bc3cb74SMauro Carvalho Chehab 	case VIDIOC_G_EXT_CTRLS:
28255bc3cb74SMauro Carvalho Chehab 	case VIDIOC_TRY_EXT_CTRLS: {
28265bc3cb74SMauro Carvalho Chehab 		struct v4l2_ext_controls *ctrls = parg;
28275bc3cb74SMauro Carvalho Chehab 
28285bc3cb74SMauro Carvalho Chehab 		if (ctrls->count != 0) {
28295bc3cb74SMauro Carvalho Chehab 			if (ctrls->count > V4L2_CID_MAX_CTRLS) {
28305bc3cb74SMauro Carvalho Chehab 				ret = -EINVAL;
28315bc3cb74SMauro Carvalho Chehab 				break;
28325bc3cb74SMauro Carvalho Chehab 			}
28335bc3cb74SMauro Carvalho Chehab 			*user_ptr = (void __user *)ctrls->controls;
2834ba2d35c1SHans Verkuil 			*kernel_ptr = (void **)&ctrls->controls;
28355bc3cb74SMauro Carvalho Chehab 			*array_size = sizeof(struct v4l2_ext_control)
28365bc3cb74SMauro Carvalho Chehab 				    * ctrls->count;
28375bc3cb74SMauro Carvalho Chehab 			ret = 1;
28385bc3cb74SMauro Carvalho Chehab 		}
28395bc3cb74SMauro Carvalho Chehab 		break;
28405bc3cb74SMauro Carvalho Chehab 	}
28415bc3cb74SMauro Carvalho Chehab 	}
28425bc3cb74SMauro Carvalho Chehab 
28435bc3cb74SMauro Carvalho Chehab 	return ret;
28445bc3cb74SMauro Carvalho Chehab }
28455bc3cb74SMauro Carvalho Chehab 
28465bc3cb74SMauro Carvalho Chehab long
28475bc3cb74SMauro Carvalho Chehab video_usercopy(struct file *file, unsigned int cmd, unsigned long arg,
28485bc3cb74SMauro Carvalho Chehab 	       v4l2_kioctl func)
28495bc3cb74SMauro Carvalho Chehab {
28505bc3cb74SMauro Carvalho Chehab 	char	sbuf[128];
28515bc3cb74SMauro Carvalho Chehab 	void    *mbuf = NULL;
28525bc3cb74SMauro Carvalho Chehab 	void	*parg = (void *)arg;
28535bc3cb74SMauro Carvalho Chehab 	long	err  = -EINVAL;
28545bc3cb74SMauro Carvalho Chehab 	bool	has_array_args;
2855043f77edSHans Verkuil 	bool	always_copy = false;
28565bc3cb74SMauro Carvalho Chehab 	size_t  array_size = 0;
28575bc3cb74SMauro Carvalho Chehab 	void __user *user_ptr = NULL;
28585bc3cb74SMauro Carvalho Chehab 	void	**kernel_ptr = NULL;
28595bc3cb74SMauro Carvalho Chehab 
28605bc3cb74SMauro Carvalho Chehab 	/*  Copy arguments into temp kernel buffer  */
28615bc3cb74SMauro Carvalho Chehab 	if (_IOC_DIR(cmd) != _IOC_NONE) {
28625bc3cb74SMauro Carvalho Chehab 		if (_IOC_SIZE(cmd) <= sizeof(sbuf)) {
28635bc3cb74SMauro Carvalho Chehab 			parg = sbuf;
28645bc3cb74SMauro Carvalho Chehab 		} else {
28655bc3cb74SMauro Carvalho Chehab 			/* too big to allocate from stack */
2866758d90e1STomasz Figa 			mbuf = kvmalloc(_IOC_SIZE(cmd), GFP_KERNEL);
28675bc3cb74SMauro Carvalho Chehab 			if (NULL == mbuf)
28685bc3cb74SMauro Carvalho Chehab 				return -ENOMEM;
28695bc3cb74SMauro Carvalho Chehab 			parg = mbuf;
28705bc3cb74SMauro Carvalho Chehab 		}
28715bc3cb74SMauro Carvalho Chehab 
28725bc3cb74SMauro Carvalho Chehab 		err = -EFAULT;
28735bc3cb74SMauro Carvalho Chehab 		if (_IOC_DIR(cmd) & _IOC_WRITE) {
28745bc3cb74SMauro Carvalho Chehab 			unsigned int n = _IOC_SIZE(cmd);
28755bc3cb74SMauro Carvalho Chehab 
28765bc3cb74SMauro Carvalho Chehab 			/*
28775bc3cb74SMauro Carvalho Chehab 			 * In some cases, only a few fields are used as input,
28785bc3cb74SMauro Carvalho Chehab 			 * i.e. when the app sets "index" and then the driver
28795bc3cb74SMauro Carvalho Chehab 			 * fills in the rest of the structure for the thing
28805bc3cb74SMauro Carvalho Chehab 			 * with that index.  We only need to copy up the first
28815bc3cb74SMauro Carvalho Chehab 			 * non-input field.
28825bc3cb74SMauro Carvalho Chehab 			 */
28835bc3cb74SMauro Carvalho Chehab 			if (v4l2_is_known_ioctl(cmd)) {
28845bc3cb74SMauro Carvalho Chehab 				u32 flags = v4l2_ioctls[_IOC_NR(cmd)].flags;
2885043f77edSHans Verkuil 
28865bc3cb74SMauro Carvalho Chehab 				if (flags & INFO_FL_CLEAR_MASK)
28875bc3cb74SMauro Carvalho Chehab 					n = (flags & INFO_FL_CLEAR_MASK) >> 16;
2888043f77edSHans Verkuil 				always_copy = flags & INFO_FL_ALWAYS_COPY;
28895bc3cb74SMauro Carvalho Chehab 			}
28905bc3cb74SMauro Carvalho Chehab 
28915bc3cb74SMauro Carvalho Chehab 			if (copy_from_user(parg, (void __user *)arg, n))
28925bc3cb74SMauro Carvalho Chehab 				goto out;
28935bc3cb74SMauro Carvalho Chehab 
28945bc3cb74SMauro Carvalho Chehab 			/* zero out anything we don't copy from userspace */
28955bc3cb74SMauro Carvalho Chehab 			if (n < _IOC_SIZE(cmd))
28965bc3cb74SMauro Carvalho Chehab 				memset((u8 *)parg + n, 0, _IOC_SIZE(cmd) - n);
28975bc3cb74SMauro Carvalho Chehab 		} else {
28985bc3cb74SMauro Carvalho Chehab 			/* read-only ioctl */
28995bc3cb74SMauro Carvalho Chehab 			memset(parg, 0, _IOC_SIZE(cmd));
29005bc3cb74SMauro Carvalho Chehab 		}
29015bc3cb74SMauro Carvalho Chehab 	}
29025bc3cb74SMauro Carvalho Chehab 
29035bc3cb74SMauro Carvalho Chehab 	err = check_array_args(cmd, parg, &array_size, &user_ptr, &kernel_ptr);
29045bc3cb74SMauro Carvalho Chehab 	if (err < 0)
29055bc3cb74SMauro Carvalho Chehab 		goto out;
29065bc3cb74SMauro Carvalho Chehab 	has_array_args = err;
29075bc3cb74SMauro Carvalho Chehab 
29085bc3cb74SMauro Carvalho Chehab 	if (has_array_args) {
29095bc3cb74SMauro Carvalho Chehab 		/*
29105bc3cb74SMauro Carvalho Chehab 		 * When adding new types of array args, make sure that the
29115bc3cb74SMauro Carvalho Chehab 		 * parent argument to ioctl (which contains the pointer to the
29125bc3cb74SMauro Carvalho Chehab 		 * array) fits into sbuf (so that mbuf will still remain
29135bc3cb74SMauro Carvalho Chehab 		 * unused up to here).
29145bc3cb74SMauro Carvalho Chehab 		 */
2915758d90e1STomasz Figa 		mbuf = kvmalloc(array_size, GFP_KERNEL);
29165bc3cb74SMauro Carvalho Chehab 		err = -ENOMEM;
29175bc3cb74SMauro Carvalho Chehab 		if (NULL == mbuf)
29185bc3cb74SMauro Carvalho Chehab 			goto out_array_args;
29195bc3cb74SMauro Carvalho Chehab 		err = -EFAULT;
29205bc3cb74SMauro Carvalho Chehab 		if (copy_from_user(mbuf, user_ptr, array_size))
29215bc3cb74SMauro Carvalho Chehab 			goto out_array_args;
29225bc3cb74SMauro Carvalho Chehab 		*kernel_ptr = mbuf;
29235bc3cb74SMauro Carvalho Chehab 	}
29245bc3cb74SMauro Carvalho Chehab 
29255bc3cb74SMauro Carvalho Chehab 	/* Handles IOCTL */
29265bc3cb74SMauro Carvalho Chehab 	err = func(file, cmd, parg);
29275bc3cb74SMauro Carvalho Chehab 	if (err == -ENOIOCTLCMD)
29285bc3cb74SMauro Carvalho Chehab 		err = -ENOTTY;
2929aa32f4c0SHans Verkuil 	if (err == 0) {
2930aa32f4c0SHans Verkuil 		if (cmd == VIDIOC_DQBUF)
2931aa32f4c0SHans Verkuil 			trace_v4l2_dqbuf(video_devdata(file)->minor, parg);
2932aa32f4c0SHans Verkuil 		else if (cmd == VIDIOC_QBUF)
2933aa32f4c0SHans Verkuil 			trace_v4l2_qbuf(video_devdata(file)->minor, parg);
2934aa32f4c0SHans Verkuil 	}
29355bc3cb74SMauro Carvalho Chehab 
29365bc3cb74SMauro Carvalho Chehab 	if (has_array_args) {
2937ba2d35c1SHans Verkuil 		*kernel_ptr = (void __force *)user_ptr;
29385bc3cb74SMauro Carvalho Chehab 		if (copy_to_user(user_ptr, mbuf, array_size))
29395bc3cb74SMauro Carvalho Chehab 			err = -EFAULT;
29405bc3cb74SMauro Carvalho Chehab 		goto out_array_args;
29415bc3cb74SMauro Carvalho Chehab 	}
2942043f77edSHans Verkuil 	/*
2943043f77edSHans Verkuil 	 * Some ioctls can return an error, but still have valid
2944043f77edSHans Verkuil 	 * results that must be returned.
2945043f77edSHans Verkuil 	 */
2946043f77edSHans Verkuil 	if (err < 0 && !always_copy)
29475bc3cb74SMauro Carvalho Chehab 		goto out;
29485bc3cb74SMauro Carvalho Chehab 
29495bc3cb74SMauro Carvalho Chehab out_array_args:
29505bc3cb74SMauro Carvalho Chehab 	/*  Copy results into user buffer  */
29515bc3cb74SMauro Carvalho Chehab 	switch (_IOC_DIR(cmd)) {
29525bc3cb74SMauro Carvalho Chehab 	case _IOC_READ:
29535bc3cb74SMauro Carvalho Chehab 	case (_IOC_WRITE | _IOC_READ):
29545bc3cb74SMauro Carvalho Chehab 		if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd)))
29555bc3cb74SMauro Carvalho Chehab 			err = -EFAULT;
29565bc3cb74SMauro Carvalho Chehab 		break;
29575bc3cb74SMauro Carvalho Chehab 	}
29585bc3cb74SMauro Carvalho Chehab 
29595bc3cb74SMauro Carvalho Chehab out:
2960758d90e1STomasz Figa 	kvfree(mbuf);
29615bc3cb74SMauro Carvalho Chehab 	return err;
29625bc3cb74SMauro Carvalho Chehab }
29635bc3cb74SMauro Carvalho Chehab EXPORT_SYMBOL(video_usercopy);
29645bc3cb74SMauro Carvalho Chehab 
29655bc3cb74SMauro Carvalho Chehab long video_ioctl2(struct file *file,
29665bc3cb74SMauro Carvalho Chehab 	       unsigned int cmd, unsigned long arg)
29675bc3cb74SMauro Carvalho Chehab {
29685bc3cb74SMauro Carvalho Chehab 	return video_usercopy(file, cmd, arg, __video_do_ioctl);
29695bc3cb74SMauro Carvalho Chehab }
29705bc3cb74SMauro Carvalho Chehab EXPORT_SYMBOL(video_ioctl2);
2971