1/*
2 * vivid-vid-common.c - common video support functions.
3 *
4 * Copyright 2014 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
5 *
6 * This program is free software; you may redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
11 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
12 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
13 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
14 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
15 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
16 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
17 * SOFTWARE.
18 */
19
20#include <linux/errno.h>
21#include <linux/kernel.h>
22#include <linux/sched.h>
23#include <linux/videodev2.h>
24#include <linux/v4l2-dv-timings.h>
25#include <media/v4l2-common.h>
26#include <media/v4l2-event.h>
27#include <media/v4l2-dv-timings.h>
28
29#include "vivid-core.h"
30#include "vivid-vid-common.h"
31
32const struct v4l2_dv_timings_cap vivid_dv_timings_cap = {
33	.type = V4L2_DV_BT_656_1120,
34	/* keep this initialization for compatibility with GCC < 4.4.6 */
35	.reserved = { 0 },
36	V4L2_INIT_BT_TIMINGS(0, MAX_WIDTH, 0, MAX_HEIGHT, 14000000, 775000000,
37		V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT |
38		V4L2_DV_BT_STD_CVT | V4L2_DV_BT_STD_GTF,
39		V4L2_DV_BT_CAP_PROGRESSIVE | V4L2_DV_BT_CAP_INTERLACED)
40};
41
42/* ------------------------------------------------------------------
43	Basic structures
44   ------------------------------------------------------------------*/
45
46struct vivid_fmt vivid_formats[] = {
47	{
48		.name     = "4:2:2, packed, YUYV",
49		.fourcc   = V4L2_PIX_FMT_YUYV,
50		.vdownsampling = { 1 },
51		.bit_depth = { 16 },
52		.is_yuv   = true,
53		.planes   = 1,
54		.buffers = 1,
55		.data_offset = { PLANE0_DATA_OFFSET },
56	},
57	{
58		.name     = "4:2:2, packed, UYVY",
59		.fourcc   = V4L2_PIX_FMT_UYVY,
60		.vdownsampling = { 1 },
61		.bit_depth = { 16 },
62		.is_yuv   = true,
63		.planes   = 1,
64		.buffers = 1,
65	},
66	{
67		.name     = "4:2:2, packed, YVYU",
68		.fourcc   = V4L2_PIX_FMT_YVYU,
69		.vdownsampling = { 1 },
70		.bit_depth = { 16 },
71		.is_yuv   = true,
72		.planes   = 1,
73		.buffers = 1,
74	},
75	{
76		.name     = "4:2:2, packed, VYUY",
77		.fourcc   = V4L2_PIX_FMT_VYUY,
78		.vdownsampling = { 1 },
79		.bit_depth = { 16 },
80		.is_yuv   = true,
81		.planes   = 1,
82		.buffers = 1,
83	},
84	{
85		.name     = "YUV 4:2:2 triplanar",
86		.fourcc   = V4L2_PIX_FMT_YUV422P,
87		.vdownsampling = { 1, 1, 1 },
88		.bit_depth = { 8, 4, 4 },
89		.is_yuv   = true,
90		.planes   = 3,
91		.buffers = 1,
92	},
93	{
94		.name     = "YUV 4:2:0 triplanar",
95		.fourcc   = V4L2_PIX_FMT_YUV420,
96		.vdownsampling = { 1, 2, 2 },
97		.bit_depth = { 8, 4, 4 },
98		.is_yuv   = true,
99		.planes   = 3,
100		.buffers = 1,
101	},
102	{
103		.name     = "YVU 4:2:0 triplanar",
104		.fourcc   = V4L2_PIX_FMT_YVU420,
105		.vdownsampling = { 1, 2, 2 },
106		.bit_depth = { 8, 4, 4 },
107		.is_yuv   = true,
108		.planes   = 3,
109		.buffers = 1,
110	},
111	{
112		.name     = "YUV 4:2:0 biplanar",
113		.fourcc   = V4L2_PIX_FMT_NV12,
114		.vdownsampling = { 1, 2 },
115		.bit_depth = { 8, 8 },
116		.is_yuv   = true,
117		.planes   = 2,
118		.buffers = 1,
119	},
120	{
121		.name     = "YVU 4:2:0 biplanar",
122		.fourcc   = V4L2_PIX_FMT_NV21,
123		.vdownsampling = { 1, 2 },
124		.bit_depth = { 8, 8 },
125		.is_yuv   = true,
126		.planes   = 2,
127		.buffers = 1,
128	},
129	{
130		.name     = "YUV 4:2:2 biplanar",
131		.fourcc   = V4L2_PIX_FMT_NV16,
132		.vdownsampling = { 1, 1 },
133		.bit_depth = { 8, 8 },
134		.is_yuv   = true,
135		.planes   = 2,
136		.buffers = 1,
137	},
138	{
139		.name     = "YVU 4:2:2 biplanar",
140		.fourcc   = V4L2_PIX_FMT_NV61,
141		.vdownsampling = { 1, 1 },
142		.bit_depth = { 8, 8 },
143		.is_yuv   = true,
144		.planes   = 2,
145		.buffers = 1,
146	},
147	{
148		.name     = "YUV 4:4:4 biplanar",
149		.fourcc   = V4L2_PIX_FMT_NV24,
150		.vdownsampling = { 1, 1 },
151		.bit_depth = { 8, 16 },
152		.is_yuv   = true,
153		.planes   = 2,
154		.buffers = 1,
155	},
156	{
157		.name     = "YVU 4:4:4 biplanar",
158		.fourcc   = V4L2_PIX_FMT_NV42,
159		.vdownsampling = { 1, 1 },
160		.bit_depth = { 8, 16 },
161		.is_yuv   = true,
162		.planes   = 2,
163		.buffers = 1,
164	},
165	{
166		.name     = "YUV555 (LE)",
167		.fourcc   = V4L2_PIX_FMT_YUV555, /* uuuvvvvv ayyyyyuu */
168		.vdownsampling = { 1 },
169		.bit_depth = { 16 },
170		.planes   = 1,
171		.buffers = 1,
172		.alpha_mask = 0x8000,
173	},
174	{
175		.name     = "YUV565 (LE)",
176		.fourcc   = V4L2_PIX_FMT_YUV565, /* uuuvvvvv yyyyyuuu */
177		.vdownsampling = { 1 },
178		.bit_depth = { 16 },
179		.planes   = 1,
180		.buffers = 1,
181	},
182	{
183		.name     = "YUV444",
184		.fourcc   = V4L2_PIX_FMT_YUV444, /* uuuuvvvv aaaayyyy */
185		.vdownsampling = { 1 },
186		.bit_depth = { 16 },
187		.planes   = 1,
188		.buffers = 1,
189		.alpha_mask = 0xf000,
190	},
191	{
192		.name     = "YUV32 (LE)",
193		.fourcc   = V4L2_PIX_FMT_YUV32, /* ayuv */
194		.vdownsampling = { 1 },
195		.bit_depth = { 32 },
196		.planes   = 1,
197		.buffers = 1,
198		.alpha_mask = 0x000000ff,
199	},
200	{
201		.name     = "Monochrome",
202		.fourcc   = V4L2_PIX_FMT_GREY,
203		.vdownsampling = { 1 },
204		.bit_depth = { 8 },
205		.is_yuv   = true,
206		.planes   = 1,
207		.buffers = 1,
208	},
209	{
210		.name     = "RGB332",
211		.fourcc   = V4L2_PIX_FMT_RGB332, /* rrrgggbb */
212		.vdownsampling = { 1 },
213		.bit_depth = { 8 },
214		.planes   = 1,
215		.buffers = 1,
216	},
217	{
218		.name     = "RGB565 (LE)",
219		.fourcc   = V4L2_PIX_FMT_RGB565, /* gggbbbbb rrrrrggg */
220		.vdownsampling = { 1 },
221		.bit_depth = { 16 },
222		.planes   = 1,
223		.buffers = 1,
224		.can_do_overlay = true,
225	},
226	{
227		.name     = "RGB565 (BE)",
228		.fourcc   = V4L2_PIX_FMT_RGB565X, /* rrrrrggg gggbbbbb */
229		.vdownsampling = { 1 },
230		.bit_depth = { 16 },
231		.planes   = 1,
232		.buffers = 1,
233		.can_do_overlay = true,
234	},
235	{
236		.name     = "RGB444",
237		.fourcc   = V4L2_PIX_FMT_RGB444, /* xxxxrrrr ggggbbbb */
238		.vdownsampling = { 1 },
239		.bit_depth = { 16 },
240		.planes   = 1,
241		.buffers = 1,
242	},
243	{
244		.name     = "XRGB444",
245		.fourcc   = V4L2_PIX_FMT_XRGB444, /* xxxxrrrr ggggbbbb */
246		.vdownsampling = { 1 },
247		.bit_depth = { 16 },
248		.planes   = 1,
249		.buffers = 1,
250	},
251	{
252		.name     = "ARGB444",
253		.fourcc   = V4L2_PIX_FMT_ARGB444, /* aaaarrrr ggggbbbb */
254		.vdownsampling = { 1 },
255		.bit_depth = { 16 },
256		.planes   = 1,
257		.buffers = 1,
258		.alpha_mask = 0x00f0,
259	},
260	{
261		.name     = "RGB555 (LE)",
262		.fourcc   = V4L2_PIX_FMT_RGB555, /* gggbbbbb xrrrrrgg */
263		.vdownsampling = { 1 },
264		.bit_depth = { 16 },
265		.planes   = 1,
266		.buffers = 1,
267		.can_do_overlay = true,
268	},
269	{
270		.name     = "XRGB555 (LE)",
271		.fourcc   = V4L2_PIX_FMT_XRGB555, /* gggbbbbb xrrrrrgg */
272		.vdownsampling = { 1 },
273		.bit_depth = { 16 },
274		.planes   = 1,
275		.buffers = 1,
276		.can_do_overlay = true,
277	},
278	{
279		.name     = "ARGB555 (LE)",
280		.fourcc   = V4L2_PIX_FMT_ARGB555, /* gggbbbbb arrrrrgg */
281		.vdownsampling = { 1 },
282		.bit_depth = { 16 },
283		.planes   = 1,
284		.buffers = 1,
285		.can_do_overlay = true,
286		.alpha_mask = 0x8000,
287	},
288	{
289		.name     = "RGB555 (BE)",
290		.fourcc   = V4L2_PIX_FMT_RGB555X, /* xrrrrrgg gggbbbbb */
291		.vdownsampling = { 1 },
292		.bit_depth = { 16 },
293		.planes   = 1,
294		.buffers = 1,
295	},
296	{
297		.name     = "XRGB555 (BE)",
298		.fourcc   = V4L2_PIX_FMT_XRGB555X, /* xrrrrrgg gggbbbbb */
299		.vdownsampling = { 1 },
300		.bit_depth = { 16 },
301		.planes   = 1,
302		.buffers = 1,
303	},
304	{
305		.name     = "ARGB555 (BE)",
306		.fourcc   = V4L2_PIX_FMT_ARGB555X, /* arrrrrgg gggbbbbb */
307		.vdownsampling = { 1 },
308		.bit_depth = { 16 },
309		.planes   = 1,
310		.buffers = 1,
311		.alpha_mask = 0x0080,
312	},
313	{
314		.name     = "RGB24 (LE)",
315		.fourcc   = V4L2_PIX_FMT_RGB24, /* rgb */
316		.vdownsampling = { 1 },
317		.bit_depth = { 24 },
318		.planes   = 1,
319		.buffers = 1,
320	},
321	{
322		.name     = "RGB24 (BE)",
323		.fourcc   = V4L2_PIX_FMT_BGR24, /* bgr */
324		.vdownsampling = { 1 },
325		.bit_depth = { 24 },
326		.planes   = 1,
327		.buffers = 1,
328	},
329	{
330		.name     = "BGR666",
331		.fourcc   = V4L2_PIX_FMT_BGR666, /* bbbbbbgg ggggrrrr rrxxxxxx */
332		.vdownsampling = { 1 },
333		.bit_depth = { 32 },
334		.planes   = 1,
335		.buffers = 1,
336	},
337	{
338		.name     = "RGB32 (LE)",
339		.fourcc   = V4L2_PIX_FMT_RGB32, /* xrgb */
340		.vdownsampling = { 1 },
341		.bit_depth = { 32 },
342		.planes   = 1,
343		.buffers = 1,
344	},
345	{
346		.name     = "RGB32 (BE)",
347		.fourcc   = V4L2_PIX_FMT_BGR32, /* bgrx */
348		.vdownsampling = { 1 },
349		.bit_depth = { 32 },
350		.planes   = 1,
351		.buffers = 1,
352	},
353	{
354		.name     = "XRGB32 (LE)",
355		.fourcc   = V4L2_PIX_FMT_XRGB32, /* xrgb */
356		.vdownsampling = { 1 },
357		.bit_depth = { 32 },
358		.planes   = 1,
359		.buffers = 1,
360	},
361	{
362		.name     = "XRGB32 (BE)",
363		.fourcc   = V4L2_PIX_FMT_XBGR32, /* bgrx */
364		.vdownsampling = { 1 },
365		.bit_depth = { 32 },
366		.planes   = 1,
367		.buffers = 1,
368	},
369	{
370		.name     = "ARGB32 (LE)",
371		.fourcc   = V4L2_PIX_FMT_ARGB32, /* argb */
372		.vdownsampling = { 1 },
373		.bit_depth = { 32 },
374		.planes   = 1,
375		.buffers = 1,
376		.alpha_mask = 0x000000ff,
377	},
378	{
379		.name     = "ARGB32 (BE)",
380		.fourcc   = V4L2_PIX_FMT_ABGR32, /* bgra */
381		.vdownsampling = { 1 },
382		.bit_depth = { 32 },
383		.planes   = 1,
384		.buffers = 1,
385		.alpha_mask = 0xff000000,
386	},
387	{
388		.name     = "Bayer BG/GR",
389		.fourcc   = V4L2_PIX_FMT_SBGGR8, /* Bayer BG/GR */
390		.vdownsampling = { 1 },
391		.bit_depth = { 8 },
392		.planes   = 1,
393		.buffers = 1,
394	},
395	{
396		.name     = "Bayer GB/RG",
397		.fourcc   = V4L2_PIX_FMT_SGBRG8, /* Bayer GB/RG */
398		.vdownsampling = { 1 },
399		.bit_depth = { 8 },
400		.planes   = 1,
401		.buffers = 1,
402	},
403	{
404		.name     = "Bayer GR/BG",
405		.fourcc   = V4L2_PIX_FMT_SGRBG8, /* Bayer GR/BG */
406		.vdownsampling = { 1 },
407		.bit_depth = { 8 },
408		.planes   = 1,
409		.buffers = 1,
410	},
411	{
412		.name     = "Bayer RG/GB",
413		.fourcc   = V4L2_PIX_FMT_SRGGB8, /* Bayer RG/GB */
414		.vdownsampling = { 1 },
415		.bit_depth = { 8 },
416		.planes   = 1,
417		.buffers = 1,
418	},
419	{
420		.name     = "4:2:2, biplanar, YUV",
421		.fourcc   = V4L2_PIX_FMT_NV16M,
422		.vdownsampling = { 1, 1 },
423		.bit_depth = { 8, 8 },
424		.is_yuv   = true,
425		.planes   = 2,
426		.buffers = 2,
427		.data_offset = { PLANE0_DATA_OFFSET, 0 },
428	},
429	{
430		.name     = "4:2:2, biplanar, YVU",
431		.fourcc   = V4L2_PIX_FMT_NV61M,
432		.vdownsampling = { 1, 1 },
433		.bit_depth = { 8, 8 },
434		.is_yuv   = true,
435		.planes   = 2,
436		.buffers = 2,
437		.data_offset = { 0, PLANE0_DATA_OFFSET },
438	},
439	{
440		.name     = "4:2:0, triplanar, YUV",
441		.fourcc   = V4L2_PIX_FMT_YUV420M,
442		.vdownsampling = { 1, 2, 2 },
443		.bit_depth = { 8, 4, 4 },
444		.is_yuv   = true,
445		.planes   = 3,
446		.buffers = 3,
447	},
448	{
449		.name     = "4:2:0, triplanar, YVU",
450		.fourcc   = V4L2_PIX_FMT_YVU420M,
451		.vdownsampling = { 1, 2, 2 },
452		.bit_depth = { 8, 4, 4 },
453		.is_yuv   = true,
454		.planes   = 3,
455		.buffers = 3,
456	},
457	{
458		.name     = "4:2:0, biplanar, YUV",
459		.fourcc   = V4L2_PIX_FMT_NV12M,
460		.vdownsampling = { 1, 2 },
461		.bit_depth = { 8, 8 },
462		.is_yuv   = true,
463		.planes   = 2,
464		.buffers = 2,
465	},
466	{
467		.name     = "4:2:0, biplanar, YVU",
468		.fourcc   = V4L2_PIX_FMT_NV21M,
469		.vdownsampling = { 1, 2 },
470		.bit_depth = { 8, 8 },
471		.is_yuv   = true,
472		.planes   = 2,
473		.buffers = 2,
474	},
475};
476
477/* There are 6 multiplanar formats in the list */
478#define VIVID_MPLANAR_FORMATS 6
479
480const struct vivid_fmt *vivid_get_format(struct vivid_dev *dev, u32 pixelformat)
481{
482	const struct vivid_fmt *fmt;
483	unsigned k;
484
485	for (k = 0; k < ARRAY_SIZE(vivid_formats); k++) {
486		fmt = &vivid_formats[k];
487		if (fmt->fourcc == pixelformat)
488			if (fmt->buffers == 1 || dev->multiplanar)
489				return fmt;
490	}
491
492	return NULL;
493}
494
495bool vivid_vid_can_loop(struct vivid_dev *dev)
496{
497	if (dev->src_rect.width != dev->sink_rect.width ||
498	    dev->src_rect.height != dev->sink_rect.height)
499		return false;
500	if (dev->fmt_cap->fourcc != dev->fmt_out->fourcc)
501		return false;
502	if (dev->field_cap != dev->field_out)
503		return false;
504	/*
505	 * While this can be supported, it is just too much work
506	 * to actually implement.
507	 */
508	if (dev->field_cap == V4L2_FIELD_SEQ_TB ||
509	    dev->field_cap == V4L2_FIELD_SEQ_BT)
510		return false;
511	if (vivid_is_svid_cap(dev) && vivid_is_svid_out(dev)) {
512		if (!(dev->std_cap & V4L2_STD_525_60) !=
513		    !(dev->std_out & V4L2_STD_525_60))
514			return false;
515		return true;
516	}
517	if (vivid_is_hdmi_cap(dev) && vivid_is_hdmi_out(dev))
518		return true;
519	return false;
520}
521
522void vivid_send_source_change(struct vivid_dev *dev, unsigned type)
523{
524	struct v4l2_event ev = {
525		.type = V4L2_EVENT_SOURCE_CHANGE,
526		.u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION,
527	};
528	unsigned i;
529
530	for (i = 0; i < dev->num_inputs; i++) {
531		ev.id = i;
532		if (dev->input_type[i] == type) {
533			if (video_is_registered(&dev->vid_cap_dev) && dev->has_vid_cap)
534				v4l2_event_queue(&dev->vid_cap_dev, &ev);
535			if (video_is_registered(&dev->vbi_cap_dev) && dev->has_vbi_cap)
536				v4l2_event_queue(&dev->vbi_cap_dev, &ev);
537		}
538	}
539}
540
541/*
542 * Conversion function that converts a single-planar format to a
543 * single-plane multiplanar format.
544 */
545void fmt_sp2mp(const struct v4l2_format *sp_fmt, struct v4l2_format *mp_fmt)
546{
547	struct v4l2_pix_format_mplane *mp = &mp_fmt->fmt.pix_mp;
548	struct v4l2_plane_pix_format *ppix = &mp->plane_fmt[0];
549	const struct v4l2_pix_format *pix = &sp_fmt->fmt.pix;
550	bool is_out = sp_fmt->type == V4L2_BUF_TYPE_VIDEO_OUTPUT;
551
552	memset(mp->reserved, 0, sizeof(mp->reserved));
553	mp_fmt->type = is_out ? V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE :
554			   V4L2_CAP_VIDEO_CAPTURE_MPLANE;
555	mp->width = pix->width;
556	mp->height = pix->height;
557	mp->pixelformat = pix->pixelformat;
558	mp->field = pix->field;
559	mp->colorspace = pix->colorspace;
560	mp->ycbcr_enc = pix->ycbcr_enc;
561	mp->quantization = pix->quantization;
562	mp->num_planes = 1;
563	mp->flags = pix->flags;
564	ppix->sizeimage = pix->sizeimage;
565	ppix->bytesperline = pix->bytesperline;
566	memset(ppix->reserved, 0, sizeof(ppix->reserved));
567}
568
569int fmt_sp2mp_func(struct file *file, void *priv,
570		struct v4l2_format *f, fmtfunc func)
571{
572	struct v4l2_format fmt;
573	struct v4l2_pix_format_mplane *mp = &fmt.fmt.pix_mp;
574	struct v4l2_plane_pix_format *ppix = &mp->plane_fmt[0];
575	struct v4l2_pix_format *pix = &f->fmt.pix;
576	int ret;
577
578	/* Converts to a mplane format */
579	fmt_sp2mp(f, &fmt);
580	/* Passes it to the generic mplane format function */
581	ret = func(file, priv, &fmt);
582	/* Copies back the mplane data to the single plane format */
583	pix->width = mp->width;
584	pix->height = mp->height;
585	pix->pixelformat = mp->pixelformat;
586	pix->field = mp->field;
587	pix->colorspace = mp->colorspace;
588	pix->ycbcr_enc = mp->ycbcr_enc;
589	pix->quantization = mp->quantization;
590	pix->sizeimage = ppix->sizeimage;
591	pix->bytesperline = ppix->bytesperline;
592	pix->flags = mp->flags;
593	return ret;
594}
595
596/* v4l2_rect helper function: copy the width/height values */
597void rect_set_size_to(struct v4l2_rect *r, const struct v4l2_rect *size)
598{
599	r->width = size->width;
600	r->height = size->height;
601}
602
603/* v4l2_rect helper function: width and height of r should be >= min_size */
604void rect_set_min_size(struct v4l2_rect *r, const struct v4l2_rect *min_size)
605{
606	if (r->width < min_size->width)
607		r->width = min_size->width;
608	if (r->height < min_size->height)
609		r->height = min_size->height;
610}
611
612/* v4l2_rect helper function: width and height of r should be <= max_size */
613void rect_set_max_size(struct v4l2_rect *r, const struct v4l2_rect *max_size)
614{
615	if (r->width > max_size->width)
616		r->width = max_size->width;
617	if (r->height > max_size->height)
618		r->height = max_size->height;
619}
620
621/* v4l2_rect helper function: r should be inside boundary */
622void rect_map_inside(struct v4l2_rect *r, const struct v4l2_rect *boundary)
623{
624	rect_set_max_size(r, boundary);
625	if (r->left < boundary->left)
626		r->left = boundary->left;
627	if (r->top < boundary->top)
628		r->top = boundary->top;
629	if (r->left + r->width > boundary->width)
630		r->left = boundary->width - r->width;
631	if (r->top + r->height > boundary->height)
632		r->top = boundary->height - r->height;
633}
634
635/* v4l2_rect helper function: return true if r1 has the same size as r2 */
636bool rect_same_size(const struct v4l2_rect *r1, const struct v4l2_rect *r2)
637{
638	return r1->width == r2->width && r1->height == r2->height;
639}
640
641/* v4l2_rect helper function: calculate the intersection of two rects */
642struct v4l2_rect rect_intersect(const struct v4l2_rect *a, const struct v4l2_rect *b)
643{
644	struct v4l2_rect r;
645	int right, bottom;
646
647	r.top = max(a->top, b->top);
648	r.left = max(a->left, b->left);
649	bottom = min(a->top + a->height, b->top + b->height);
650	right = min(a->left + a->width, b->left + b->width);
651	r.height = max(0, bottom - r.top);
652	r.width = max(0, right - r.left);
653	return r;
654}
655
656/*
657 * v4l2_rect helper function: scale rect r by to->width / from->width and
658 * to->height / from->height.
659 */
660void rect_scale(struct v4l2_rect *r, const struct v4l2_rect *from,
661				     const struct v4l2_rect *to)
662{
663	if (from->width == 0 || from->height == 0) {
664		r->left = r->top = r->width = r->height = 0;
665		return;
666	}
667	r->left = (((r->left - from->left) * to->width) / from->width) & ~1;
668	r->width = ((r->width * to->width) / from->width) & ~1;
669	r->top = ((r->top - from->top) * to->height) / from->height;
670	r->height = (r->height * to->height) / from->height;
671}
672
673bool rect_overlap(const struct v4l2_rect *r1, const struct v4l2_rect *r2)
674{
675	/*
676	 * IF the left side of r1 is to the right of the right side of r2 OR
677	 *    the left side of r2 is to the right of the right side of r1 THEN
678	 * they do not overlap.
679	 */
680	if (r1->left >= r2->left + r2->width ||
681	    r2->left >= r1->left + r1->width)
682		return false;
683	/*
684	 * IF the top side of r1 is below the bottom of r2 OR
685	 *    the top side of r2 is below the bottom of r1 THEN
686	 * they do not overlap.
687	 */
688	if (r1->top >= r2->top + r2->height ||
689	    r2->top >= r1->top + r1->height)
690		return false;
691	return true;
692}
693int vivid_vid_adjust_sel(unsigned flags, struct v4l2_rect *r)
694{
695	unsigned w = r->width;
696	unsigned h = r->height;
697
698	/* sanitize w and h in case someone passes ~0 as the value */
699	w &= 0xffff;
700	h &= 0xffff;
701	if (!(flags & V4L2_SEL_FLAG_LE)) {
702		w++;
703		h++;
704		if (w < 2)
705			w = 2;
706		if (h < 2)
707			h = 2;
708	}
709	if (!(flags & V4L2_SEL_FLAG_GE)) {
710		if (w > MAX_WIDTH)
711			w = MAX_WIDTH;
712		if (h > MAX_HEIGHT)
713			h = MAX_HEIGHT;
714	}
715	w = w & ~1;
716	h = h & ~1;
717	if (w < 2 || h < 2)
718		return -ERANGE;
719	if (w > MAX_WIDTH || h > MAX_HEIGHT)
720		return -ERANGE;
721	if (r->top < 0)
722		r->top = 0;
723	if (r->left < 0)
724		r->left = 0;
725	/* sanitize left and top in case someone passes ~0 as the value */
726	r->left &= 0xfffe;
727	r->top &= 0xfffe;
728	if (r->left + w > MAX_WIDTH)
729		r->left = MAX_WIDTH - w;
730	if (r->top + h > MAX_HEIGHT)
731		r->top = MAX_HEIGHT - h;
732	if ((flags & (V4L2_SEL_FLAG_GE | V4L2_SEL_FLAG_LE)) ==
733			(V4L2_SEL_FLAG_GE | V4L2_SEL_FLAG_LE) &&
734	    (r->width != w || r->height != h))
735		return -ERANGE;
736	r->width = w;
737	r->height = h;
738	return 0;
739}
740
741int vivid_enum_fmt_vid(struct file *file, void  *priv,
742					struct v4l2_fmtdesc *f)
743{
744	struct vivid_dev *dev = video_drvdata(file);
745	const struct vivid_fmt *fmt;
746
747	if (f->index >= ARRAY_SIZE(vivid_formats) -
748	    (dev->multiplanar ? 0 : VIVID_MPLANAR_FORMATS))
749		return -EINVAL;
750
751	fmt = &vivid_formats[f->index];
752
753	strlcpy(f->description, fmt->name, sizeof(f->description));
754	f->pixelformat = fmt->fourcc;
755	return 0;
756}
757
758int vidioc_enum_fmt_vid_mplane(struct file *file, void  *priv,
759					struct v4l2_fmtdesc *f)
760{
761	struct vivid_dev *dev = video_drvdata(file);
762
763	if (!dev->multiplanar)
764		return -ENOTTY;
765	return vivid_enum_fmt_vid(file, priv, f);
766}
767
768int vidioc_enum_fmt_vid(struct file *file, void  *priv,
769					struct v4l2_fmtdesc *f)
770{
771	struct vivid_dev *dev = video_drvdata(file);
772
773	if (dev->multiplanar)
774		return -ENOTTY;
775	return vivid_enum_fmt_vid(file, priv, f);
776}
777
778int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *id)
779{
780	struct vivid_dev *dev = video_drvdata(file);
781	struct video_device *vdev = video_devdata(file);
782
783	if (vdev->vfl_dir == VFL_DIR_RX) {
784		if (!vivid_is_sdtv_cap(dev))
785			return -ENODATA;
786		*id = dev->std_cap;
787	} else {
788		if (!vivid_is_svid_out(dev))
789			return -ENODATA;
790		*id = dev->std_out;
791	}
792	return 0;
793}
794
795int vidioc_g_dv_timings(struct file *file, void *_fh,
796				    struct v4l2_dv_timings *timings)
797{
798	struct vivid_dev *dev = video_drvdata(file);
799	struct video_device *vdev = video_devdata(file);
800
801	if (vdev->vfl_dir == VFL_DIR_RX) {
802		if (!vivid_is_hdmi_cap(dev))
803			return -ENODATA;
804		*timings = dev->dv_timings_cap;
805	} else {
806		if (!vivid_is_hdmi_out(dev))
807			return -ENODATA;
808		*timings = dev->dv_timings_out;
809	}
810	return 0;
811}
812
813int vidioc_enum_dv_timings(struct file *file, void *_fh,
814				    struct v4l2_enum_dv_timings *timings)
815{
816	struct vivid_dev *dev = video_drvdata(file);
817	struct video_device *vdev = video_devdata(file);
818
819	if (vdev->vfl_dir == VFL_DIR_RX) {
820		if (!vivid_is_hdmi_cap(dev))
821			return -ENODATA;
822	} else {
823		if (!vivid_is_hdmi_out(dev))
824			return -ENODATA;
825	}
826	return v4l2_enum_dv_timings_cap(timings, &vivid_dv_timings_cap,
827			NULL, NULL);
828}
829
830int vidioc_dv_timings_cap(struct file *file, void *_fh,
831				    struct v4l2_dv_timings_cap *cap)
832{
833	struct vivid_dev *dev = video_drvdata(file);
834	struct video_device *vdev = video_devdata(file);
835
836	if (vdev->vfl_dir == VFL_DIR_RX) {
837		if (!vivid_is_hdmi_cap(dev))
838			return -ENODATA;
839	} else {
840		if (!vivid_is_hdmi_out(dev))
841			return -ENODATA;
842	}
843	*cap = vivid_dv_timings_cap;
844	return 0;
845}
846
847int vidioc_g_edid(struct file *file, void *_fh,
848			 struct v4l2_edid *edid)
849{
850	struct vivid_dev *dev = video_drvdata(file);
851	struct video_device *vdev = video_devdata(file);
852
853	memset(edid->reserved, 0, sizeof(edid->reserved));
854	if (vdev->vfl_dir == VFL_DIR_RX) {
855		if (edid->pad >= dev->num_inputs)
856			return -EINVAL;
857		if (dev->input_type[edid->pad] != HDMI)
858			return -EINVAL;
859	} else {
860		if (edid->pad >= dev->num_outputs)
861			return -EINVAL;
862		if (dev->output_type[edid->pad] != HDMI)
863			return -EINVAL;
864	}
865	if (edid->start_block == 0 && edid->blocks == 0) {
866		edid->blocks = dev->edid_blocks;
867		return 0;
868	}
869	if (dev->edid_blocks == 0)
870		return -ENODATA;
871	if (edid->start_block >= dev->edid_blocks)
872		return -EINVAL;
873	if (edid->start_block + edid->blocks > dev->edid_blocks)
874		edid->blocks = dev->edid_blocks - edid->start_block;
875	memcpy(edid->edid, dev->edid, edid->blocks * 128);
876	return 0;
877}
878