1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * vivid-vid-common.c - common video support functions.
4 *
5 * Copyright 2014 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
6 */
7
8#include <linux/errno.h>
9#include <linux/kernel.h>
10#include <linux/sched.h>
11#include <linux/videodev2.h>
12#include <linux/v4l2-dv-timings.h>
13#include <media/v4l2-common.h>
14#include <media/v4l2-event.h>
15#include <media/v4l2-dv-timings.h>
16
17#include "vivid-core.h"
18#include "vivid-vid-common.h"
19
20const struct v4l2_dv_timings_cap vivid_dv_timings_cap = {
21	.type = V4L2_DV_BT_656_1120,
22	/* keep this initialization for compatibility with GCC < 4.4.6 */
23	.reserved = { 0 },
24	V4L2_INIT_BT_TIMINGS(16, MAX_WIDTH, 16, MAX_HEIGHT, 14000000, 775000000,
25		V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT |
26		V4L2_DV_BT_STD_CVT | V4L2_DV_BT_STD_GTF,
27		V4L2_DV_BT_CAP_PROGRESSIVE | V4L2_DV_BT_CAP_INTERLACED)
28};
29
30/* ------------------------------------------------------------------
31	Basic structures
32   ------------------------------------------------------------------*/
33
34struct vivid_fmt vivid_formats[] = {
35	{
36		.fourcc   = V4L2_PIX_FMT_YUYV,
37		.vdownsampling = { 1 },
38		.bit_depth = { 16 },
39		.color_enc = TGP_COLOR_ENC_YCBCR,
40		.planes   = 1,
41		.buffers = 1,
42		.data_offset = { PLANE0_DATA_OFFSET },
43	},
44	{
45		.fourcc   = V4L2_PIX_FMT_UYVY,
46		.vdownsampling = { 1 },
47		.bit_depth = { 16 },
48		.color_enc = TGP_COLOR_ENC_YCBCR,
49		.planes   = 1,
50		.buffers = 1,
51	},
52	{
53		.fourcc   = V4L2_PIX_FMT_YVYU,
54		.vdownsampling = { 1 },
55		.bit_depth = { 16 },
56		.color_enc = TGP_COLOR_ENC_YCBCR,
57		.planes   = 1,
58		.buffers = 1,
59	},
60	{
61		.fourcc   = V4L2_PIX_FMT_VYUY,
62		.vdownsampling = { 1 },
63		.bit_depth = { 16 },
64		.color_enc = TGP_COLOR_ENC_YCBCR,
65		.planes   = 1,
66		.buffers = 1,
67	},
68	{
69		.fourcc   = V4L2_PIX_FMT_YUV422P,
70		.vdownsampling = { 1, 1, 1 },
71		.bit_depth = { 8, 4, 4 },
72		.color_enc = TGP_COLOR_ENC_YCBCR,
73		.planes   = 3,
74		.buffers = 1,
75	},
76	{
77		.fourcc   = V4L2_PIX_FMT_YUV420,
78		.vdownsampling = { 1, 2, 2 },
79		.bit_depth = { 8, 4, 4 },
80		.color_enc = TGP_COLOR_ENC_YCBCR,
81		.planes   = 3,
82		.buffers = 1,
83	},
84	{
85		.fourcc   = V4L2_PIX_FMT_YVU420,
86		.vdownsampling = { 1, 2, 2 },
87		.bit_depth = { 8, 4, 4 },
88		.color_enc = TGP_COLOR_ENC_YCBCR,
89		.planes   = 3,
90		.buffers = 1,
91	},
92	{
93		.fourcc   = V4L2_PIX_FMT_NV12,
94		.vdownsampling = { 1, 2 },
95		.bit_depth = { 8, 8 },
96		.color_enc = TGP_COLOR_ENC_YCBCR,
97		.planes   = 2,
98		.buffers = 1,
99	},
100	{
101		.fourcc   = V4L2_PIX_FMT_NV21,
102		.vdownsampling = { 1, 2 },
103		.bit_depth = { 8, 8 },
104		.color_enc = TGP_COLOR_ENC_YCBCR,
105		.planes   = 2,
106		.buffers = 1,
107	},
108	{
109		.fourcc   = V4L2_PIX_FMT_NV16,
110		.vdownsampling = { 1, 1 },
111		.bit_depth = { 8, 8 },
112		.color_enc = TGP_COLOR_ENC_YCBCR,
113		.planes   = 2,
114		.buffers = 1,
115	},
116	{
117		.fourcc   = V4L2_PIX_FMT_NV61,
118		.vdownsampling = { 1, 1 },
119		.bit_depth = { 8, 8 },
120		.color_enc = TGP_COLOR_ENC_YCBCR,
121		.planes   = 2,
122		.buffers = 1,
123	},
124	{
125		.fourcc   = V4L2_PIX_FMT_NV24,
126		.vdownsampling = { 1, 1 },
127		.bit_depth = { 8, 16 },
128		.color_enc = TGP_COLOR_ENC_YCBCR,
129		.planes   = 2,
130		.buffers = 1,
131	},
132	{
133		.fourcc   = V4L2_PIX_FMT_NV42,
134		.vdownsampling = { 1, 1 },
135		.bit_depth = { 8, 16 },
136		.color_enc = TGP_COLOR_ENC_YCBCR,
137		.planes   = 2,
138		.buffers = 1,
139	},
140	{
141		.fourcc   = V4L2_PIX_FMT_YUV555, /* uuuvvvvv ayyyyyuu */
142		.vdownsampling = { 1 },
143		.bit_depth = { 16 },
144		.planes   = 1,
145		.buffers = 1,
146		.alpha_mask = 0x8000,
147	},
148	{
149		.fourcc   = V4L2_PIX_FMT_YUV565, /* uuuvvvvv yyyyyuuu */
150		.vdownsampling = { 1 },
151		.bit_depth = { 16 },
152		.planes   = 1,
153		.buffers = 1,
154	},
155	{
156		.fourcc   = V4L2_PIX_FMT_YUV444, /* uuuuvvvv aaaayyyy */
157		.vdownsampling = { 1 },
158		.bit_depth = { 16 },
159		.planes   = 1,
160		.buffers = 1,
161		.alpha_mask = 0xf000,
162	},
163	{
164		.fourcc   = V4L2_PIX_FMT_YUV32, /* ayuv */
165		.vdownsampling = { 1 },
166		.bit_depth = { 32 },
167		.planes   = 1,
168		.buffers = 1,
169		.alpha_mask = 0x000000ff,
170	},
171	{
172		.fourcc   = V4L2_PIX_FMT_AYUV32,
173		.vdownsampling = { 1 },
174		.bit_depth = { 32 },
175		.planes   = 1,
176		.buffers = 1,
177		.alpha_mask = 0x000000ff,
178	},
179	{
180		.fourcc   = V4L2_PIX_FMT_XYUV32,
181		.vdownsampling = { 1 },
182		.bit_depth = { 32 },
183		.planes   = 1,
184		.buffers = 1,
185	},
186	{
187		.fourcc   = V4L2_PIX_FMT_VUYA32,
188		.vdownsampling = { 1 },
189		.bit_depth = { 32 },
190		.planes   = 1,
191		.buffers = 1,
192		.alpha_mask = 0xff000000,
193	},
194	{
195		.fourcc   = V4L2_PIX_FMT_VUYX32,
196		.vdownsampling = { 1 },
197		.bit_depth = { 32 },
198		.planes   = 1,
199		.buffers = 1,
200	},
201	{
202		.fourcc   = V4L2_PIX_FMT_YUVA32,
203		.vdownsampling = { 1 },
204		.bit_depth = { 32 },
205		.planes   = 1,
206		.buffers = 1,
207		.alpha_mask = 0xff000000,
208	},
209	{
210		.fourcc   = V4L2_PIX_FMT_YUVX32,
211		.vdownsampling = { 1 },
212		.bit_depth = { 32 },
213		.planes   = 1,
214		.buffers = 1,
215	},
216	{
217		.fourcc   = V4L2_PIX_FMT_GREY,
218		.vdownsampling = { 1 },
219		.bit_depth = { 8 },
220		.color_enc = TGP_COLOR_ENC_LUMA,
221		.planes   = 1,
222		.buffers = 1,
223	},
224	{
225		.fourcc   = V4L2_PIX_FMT_Y10,
226		.vdownsampling = { 1 },
227		.bit_depth = { 16 },
228		.color_enc = TGP_COLOR_ENC_LUMA,
229		.planes   = 1,
230		.buffers = 1,
231	},
232	{
233		.fourcc   = V4L2_PIX_FMT_Y12,
234		.vdownsampling = { 1 },
235		.bit_depth = { 16 },
236		.color_enc = TGP_COLOR_ENC_LUMA,
237		.planes   = 1,
238		.buffers = 1,
239	},
240	{
241		.fourcc   = V4L2_PIX_FMT_Y16,
242		.vdownsampling = { 1 },
243		.bit_depth = { 16 },
244		.color_enc = TGP_COLOR_ENC_LUMA,
245		.planes   = 1,
246		.buffers = 1,
247	},
248	{
249		.fourcc   = V4L2_PIX_FMT_Y16_BE,
250		.vdownsampling = { 1 },
251		.bit_depth = { 16 },
252		.color_enc = TGP_COLOR_ENC_LUMA,
253		.planes   = 1,
254		.buffers = 1,
255	},
256	{
257		.fourcc   = V4L2_PIX_FMT_RGB332, /* rrrgggbb */
258		.vdownsampling = { 1 },
259		.bit_depth = { 8 },
260		.planes   = 1,
261		.buffers = 1,
262	},
263	{
264		.fourcc   = V4L2_PIX_FMT_RGB565, /* gggbbbbb rrrrrggg */
265		.vdownsampling = { 1 },
266		.bit_depth = { 16 },
267		.planes   = 1,
268		.buffers = 1,
269		.can_do_overlay = true,
270	},
271	{
272		.fourcc   = V4L2_PIX_FMT_RGB565X, /* rrrrrggg gggbbbbb */
273		.vdownsampling = { 1 },
274		.bit_depth = { 16 },
275		.planes   = 1,
276		.buffers = 1,
277		.can_do_overlay = true,
278	},
279	{
280		.fourcc   = V4L2_PIX_FMT_RGB444, /* ggggbbbb xxxxrrrr */
281		.vdownsampling = { 1 },
282		.bit_depth = { 16 },
283		.planes   = 1,
284		.buffers = 1,
285	},
286	{
287		.fourcc   = V4L2_PIX_FMT_XRGB444, /* ggggbbbb xxxxrrrr */
288		.vdownsampling = { 1 },
289		.bit_depth = { 16 },
290		.planes   = 1,
291		.buffers = 1,
292	},
293	{
294		.fourcc   = V4L2_PIX_FMT_ARGB444, /* ggggbbbb aaaarrrr */
295		.vdownsampling = { 1 },
296		.bit_depth = { 16 },
297		.planes   = 1,
298		.buffers = 1,
299		.alpha_mask = 0x00f0,
300	},
301	{
302		.fourcc   = V4L2_PIX_FMT_RGBX444, /* bbbbxxxx rrrrgggg */
303		.vdownsampling = { 1 },
304		.bit_depth = { 16 },
305		.planes   = 1,
306		.buffers = 1,
307	},
308	{
309		.fourcc   = V4L2_PIX_FMT_RGBA444, /* bbbbaaaa rrrrgggg */
310		.vdownsampling = { 1 },
311		.bit_depth = { 16 },
312		.planes   = 1,
313		.buffers = 1,
314		.alpha_mask = 0x00f0,
315	},
316	{
317		.fourcc   = V4L2_PIX_FMT_XBGR444, /* ggggrrrr xxxxbbbb */
318		.vdownsampling = { 1 },
319		.bit_depth = { 16 },
320		.planes   = 1,
321		.buffers = 1,
322	},
323	{
324		.fourcc   = V4L2_PIX_FMT_ABGR444, /* ggggrrrr aaaabbbb */
325		.vdownsampling = { 1 },
326		.bit_depth = { 16 },
327		.planes   = 1,
328		.buffers = 1,
329		.alpha_mask = 0x00f0,
330	},
331	{
332		.fourcc   = V4L2_PIX_FMT_BGRX444, /* rrrrxxxx bbbbgggg */
333		.vdownsampling = { 1 },
334		.bit_depth = { 16 },
335		.planes   = 1,
336		.buffers = 1,
337	},
338	{
339		.fourcc   = V4L2_PIX_FMT_BGRA444, /* rrrraaaa bbbbgggg  */
340		.vdownsampling = { 1 },
341		.bit_depth = { 16 },
342		.planes   = 1,
343		.buffers = 1,
344		.alpha_mask = 0x00f0,
345	},
346	{
347		.fourcc   = V4L2_PIX_FMT_RGB555, /* gggbbbbb xrrrrrgg */
348		.vdownsampling = { 1 },
349		.bit_depth = { 16 },
350		.planes   = 1,
351		.buffers = 1,
352		.can_do_overlay = true,
353	},
354	{
355		.fourcc   = V4L2_PIX_FMT_XRGB555, /* gggbbbbb xrrrrrgg */
356		.vdownsampling = { 1 },
357		.bit_depth = { 16 },
358		.planes   = 1,
359		.buffers = 1,
360		.can_do_overlay = true,
361	},
362	{
363		.fourcc   = V4L2_PIX_FMT_ARGB555, /* gggbbbbb arrrrrgg */
364		.vdownsampling = { 1 },
365		.bit_depth = { 16 },
366		.planes   = 1,
367		.buffers = 1,
368		.can_do_overlay = true,
369		.alpha_mask = 0x8000,
370	},
371	{
372		.fourcc   = V4L2_PIX_FMT_RGBX555, /* ggbbbbbx rrrrrggg */
373		.vdownsampling = { 1 },
374		.bit_depth = { 16 },
375		.planes   = 1,
376		.buffers = 1,
377		.can_do_overlay = true,
378	},
379	{
380		.fourcc   = V4L2_PIX_FMT_RGBA555, /* ggbbbbba rrrrrggg */
381		.vdownsampling = { 1 },
382		.bit_depth = { 16 },
383		.planes   = 1,
384		.buffers = 1,
385		.can_do_overlay = true,
386		.alpha_mask = 0x8000,
387	},
388	{
389		.fourcc   = V4L2_PIX_FMT_XBGR555, /* gggrrrrr xbbbbbgg */
390		.vdownsampling = { 1 },
391		.bit_depth = { 16 },
392		.planes   = 1,
393		.buffers = 1,
394		.can_do_overlay = true,
395	},
396	{
397		.fourcc   = V4L2_PIX_FMT_ABGR555, /* gggrrrrr abbbbbgg */
398		.vdownsampling = { 1 },
399		.bit_depth = { 16 },
400		.planes   = 1,
401		.buffers = 1,
402		.can_do_overlay = true,
403		.alpha_mask = 0x8000,
404	},
405	{
406		.fourcc   = V4L2_PIX_FMT_BGRX555, /* ggrrrrrx bbbbbggg */
407		.vdownsampling = { 1 },
408		.bit_depth = { 16 },
409		.planes   = 1,
410		.buffers = 1,
411		.can_do_overlay = true,
412	},
413	{
414		.fourcc   = V4L2_PIX_FMT_BGRA555, /* ggrrrrra bbbbbggg */
415		.vdownsampling = { 1 },
416		.bit_depth = { 16 },
417		.planes   = 1,
418		.buffers = 1,
419		.can_do_overlay = true,
420		.alpha_mask = 0x8000,
421	},
422	{
423		.fourcc   = V4L2_PIX_FMT_RGB555X, /* xrrrrrgg gggbbbbb */
424		.vdownsampling = { 1 },
425		.bit_depth = { 16 },
426		.planes   = 1,
427		.buffers = 1,
428	},
429	{
430		.fourcc   = V4L2_PIX_FMT_XRGB555X, /* xrrrrrgg gggbbbbb */
431		.vdownsampling = { 1 },
432		.bit_depth = { 16 },
433		.planes   = 1,
434		.buffers = 1,
435	},
436	{
437		.fourcc   = V4L2_PIX_FMT_ARGB555X, /* arrrrrgg gggbbbbb */
438		.vdownsampling = { 1 },
439		.bit_depth = { 16 },
440		.planes   = 1,
441		.buffers = 1,
442		.alpha_mask = 0x0080,
443	},
444	{
445		.fourcc   = V4L2_PIX_FMT_RGB24, /* rgb */
446		.vdownsampling = { 1 },
447		.bit_depth = { 24 },
448		.planes   = 1,
449		.buffers = 1,
450	},
451	{
452		.fourcc   = V4L2_PIX_FMT_BGR24, /* bgr */
453		.vdownsampling = { 1 },
454		.bit_depth = { 24 },
455		.planes   = 1,
456		.buffers = 1,
457	},
458	{
459		.fourcc   = V4L2_PIX_FMT_BGR666, /* bbbbbbgg ggggrrrr rrxxxxxx */
460		.vdownsampling = { 1 },
461		.bit_depth = { 32 },
462		.planes   = 1,
463		.buffers = 1,
464	},
465	{
466		.fourcc   = V4L2_PIX_FMT_RGB32, /* xrgb */
467		.vdownsampling = { 1 },
468		.bit_depth = { 32 },
469		.planes   = 1,
470		.buffers = 1,
471	},
472	{
473		.fourcc   = V4L2_PIX_FMT_BGR32, /* bgrx */
474		.vdownsampling = { 1 },
475		.bit_depth = { 32 },
476		.planes   = 1,
477		.buffers = 1,
478	},
479	{
480		.fourcc   = V4L2_PIX_FMT_XRGB32, /* xrgb */
481		.vdownsampling = { 1 },
482		.bit_depth = { 32 },
483		.planes   = 1,
484		.buffers = 1,
485	},
486	{
487		.fourcc   = V4L2_PIX_FMT_XBGR32, /* bgrx */
488		.vdownsampling = { 1 },
489		.bit_depth = { 32 },
490		.planes   = 1,
491		.buffers = 1,
492	},
493	{
494		.fourcc   = V4L2_PIX_FMT_ARGB32, /* argb */
495		.vdownsampling = { 1 },
496		.bit_depth = { 32 },
497		.planes   = 1,
498		.buffers = 1,
499		.alpha_mask = 0x000000ff,
500	},
501	{
502		.fourcc   = V4L2_PIX_FMT_ABGR32, /* bgra */
503		.vdownsampling = { 1 },
504		.bit_depth = { 32 },
505		.planes   = 1,
506		.buffers = 1,
507		.alpha_mask = 0xff000000,
508	},
509	{
510		.fourcc   = V4L2_PIX_FMT_RGBX32, /* rgbx */
511		.vdownsampling = { 1 },
512		.bit_depth = { 32 },
513		.planes   = 1,
514		.buffers = 1,
515	},
516	{
517		.fourcc   = V4L2_PIX_FMT_BGRX32, /* xbgr */
518		.vdownsampling = { 1 },
519		.bit_depth = { 32 },
520		.planes   = 1,
521		.buffers = 1,
522	},
523	{
524		.fourcc   = V4L2_PIX_FMT_RGBA32, /* rgba */
525		.vdownsampling = { 1 },
526		.bit_depth = { 32 },
527		.planes   = 1,
528		.buffers = 1,
529		.alpha_mask = 0x000000ff,
530	},
531	{
532		.fourcc   = V4L2_PIX_FMT_BGRA32, /* abgr */
533		.vdownsampling = { 1 },
534		.bit_depth = { 32 },
535		.planes   = 1,
536		.buffers = 1,
537		.alpha_mask = 0xff000000,
538	},
539	{
540		.fourcc   = V4L2_PIX_FMT_SBGGR8, /* Bayer BG/GR */
541		.vdownsampling = { 1 },
542		.bit_depth = { 8 },
543		.planes   = 1,
544		.buffers = 1,
545	},
546	{
547		.fourcc   = V4L2_PIX_FMT_SGBRG8, /* Bayer GB/RG */
548		.vdownsampling = { 1 },
549		.bit_depth = { 8 },
550		.planes   = 1,
551		.buffers = 1,
552	},
553	{
554		.fourcc   = V4L2_PIX_FMT_SGRBG8, /* Bayer GR/BG */
555		.vdownsampling = { 1 },
556		.bit_depth = { 8 },
557		.planes   = 1,
558		.buffers = 1,
559	},
560	{
561		.fourcc   = V4L2_PIX_FMT_SRGGB8, /* Bayer RG/GB */
562		.vdownsampling = { 1 },
563		.bit_depth = { 8 },
564		.planes   = 1,
565		.buffers = 1,
566	},
567	{
568		.fourcc   = V4L2_PIX_FMT_SBGGR10, /* Bayer BG/GR */
569		.vdownsampling = { 1 },
570		.bit_depth = { 16 },
571		.planes   = 1,
572		.buffers = 1,
573	},
574	{
575		.fourcc   = V4L2_PIX_FMT_SGBRG10, /* Bayer GB/RG */
576		.vdownsampling = { 1 },
577		.bit_depth = { 16 },
578		.planes   = 1,
579		.buffers = 1,
580	},
581	{
582		.fourcc   = V4L2_PIX_FMT_SGRBG10, /* Bayer GR/BG */
583		.vdownsampling = { 1 },
584		.bit_depth = { 16 },
585		.planes   = 1,
586		.buffers = 1,
587	},
588	{
589		.fourcc   = V4L2_PIX_FMT_SRGGB10, /* Bayer RG/GB */
590		.vdownsampling = { 1 },
591		.bit_depth = { 16 },
592		.planes   = 1,
593		.buffers = 1,
594	},
595	{
596		.fourcc   = V4L2_PIX_FMT_SBGGR12, /* Bayer BG/GR */
597		.vdownsampling = { 1 },
598		.bit_depth = { 16 },
599		.planes   = 1,
600		.buffers = 1,
601	},
602	{
603		.fourcc   = V4L2_PIX_FMT_SGBRG12, /* Bayer GB/RG */
604		.vdownsampling = { 1 },
605		.bit_depth = { 16 },
606		.planes   = 1,
607		.buffers = 1,
608	},
609	{
610		.fourcc   = V4L2_PIX_FMT_SGRBG12, /* Bayer GR/BG */
611		.vdownsampling = { 1 },
612		.bit_depth = { 16 },
613		.planes   = 1,
614		.buffers = 1,
615	},
616	{
617		.fourcc   = V4L2_PIX_FMT_SRGGB12, /* Bayer RG/GB */
618		.vdownsampling = { 1 },
619		.bit_depth = { 16 },
620		.planes   = 1,
621		.buffers = 1,
622	},
623	{
624		.fourcc   = V4L2_PIX_FMT_SBGGR16, /* Bayer BG/GR */
625		.vdownsampling = { 1 },
626		.bit_depth = { 16 },
627		.planes   = 1,
628		.buffers = 1,
629	},
630	{
631		.fourcc   = V4L2_PIX_FMT_SGBRG16, /* Bayer GB/RG */
632		.vdownsampling = { 1 },
633		.bit_depth = { 16 },
634		.planes   = 1,
635		.buffers = 1,
636	},
637	{
638		.fourcc   = V4L2_PIX_FMT_SGRBG16, /* Bayer GR/BG */
639		.vdownsampling = { 1 },
640		.bit_depth = { 16 },
641		.planes   = 1,
642		.buffers = 1,
643	},
644	{
645		.fourcc   = V4L2_PIX_FMT_SRGGB16, /* Bayer RG/GB */
646		.vdownsampling = { 1 },
647		.bit_depth = { 16 },
648		.planes   = 1,
649		.buffers = 1,
650	},
651	{
652		.fourcc   = V4L2_PIX_FMT_HSV24, /* HSV 24bits */
653		.color_enc = TGP_COLOR_ENC_HSV,
654		.vdownsampling = { 1 },
655		.bit_depth = { 24 },
656		.planes   = 1,
657		.buffers = 1,
658	},
659	{
660		.fourcc   = V4L2_PIX_FMT_HSV32, /* HSV 32bits */
661		.color_enc = TGP_COLOR_ENC_HSV,
662		.vdownsampling = { 1 },
663		.bit_depth = { 32 },
664		.planes   = 1,
665		.buffers = 1,
666	},
667
668	/* Multiplanar formats */
669
670	{
671		.fourcc   = V4L2_PIX_FMT_NV16M,
672		.vdownsampling = { 1, 1 },
673		.bit_depth = { 8, 8 },
674		.color_enc = TGP_COLOR_ENC_YCBCR,
675		.planes   = 2,
676		.buffers = 2,
677		.data_offset = { PLANE0_DATA_OFFSET, 0 },
678	},
679	{
680		.fourcc   = V4L2_PIX_FMT_NV61M,
681		.vdownsampling = { 1, 1 },
682		.bit_depth = { 8, 8 },
683		.color_enc = TGP_COLOR_ENC_YCBCR,
684		.planes   = 2,
685		.buffers = 2,
686		.data_offset = { 0, PLANE0_DATA_OFFSET },
687	},
688	{
689		.fourcc   = V4L2_PIX_FMT_YUV420M,
690		.vdownsampling = { 1, 2, 2 },
691		.bit_depth = { 8, 4, 4 },
692		.color_enc = TGP_COLOR_ENC_YCBCR,
693		.planes   = 3,
694		.buffers = 3,
695	},
696	{
697		.fourcc   = V4L2_PIX_FMT_YVU420M,
698		.vdownsampling = { 1, 2, 2 },
699		.bit_depth = { 8, 4, 4 },
700		.color_enc = TGP_COLOR_ENC_YCBCR,
701		.planes   = 3,
702		.buffers = 3,
703	},
704	{
705		.fourcc   = V4L2_PIX_FMT_NV12M,
706		.vdownsampling = { 1, 2 },
707		.bit_depth = { 8, 8 },
708		.color_enc = TGP_COLOR_ENC_YCBCR,
709		.planes   = 2,
710		.buffers = 2,
711	},
712	{
713		.fourcc   = V4L2_PIX_FMT_NV21M,
714		.vdownsampling = { 1, 2 },
715		.bit_depth = { 8, 8 },
716		.color_enc = TGP_COLOR_ENC_YCBCR,
717		.planes   = 2,
718		.buffers = 2,
719	},
720	{
721		.fourcc   = V4L2_PIX_FMT_YUV422M,
722		.vdownsampling = { 1, 1, 1 },
723		.bit_depth = { 8, 4, 4 },
724		.color_enc = TGP_COLOR_ENC_YCBCR,
725		.planes   = 3,
726		.buffers = 3,
727	},
728	{
729		.fourcc   = V4L2_PIX_FMT_YVU422M,
730		.vdownsampling = { 1, 1, 1 },
731		.bit_depth = { 8, 4, 4 },
732		.color_enc = TGP_COLOR_ENC_YCBCR,
733		.planes   = 3,
734		.buffers = 3,
735	},
736	{
737		.fourcc   = V4L2_PIX_FMT_YUV444M,
738		.vdownsampling = { 1, 1, 1 },
739		.bit_depth = { 8, 8, 8 },
740		.color_enc = TGP_COLOR_ENC_YCBCR,
741		.planes   = 3,
742		.buffers = 3,
743	},
744	{
745		.fourcc   = V4L2_PIX_FMT_YVU444M,
746		.vdownsampling = { 1, 1, 1 },
747		.bit_depth = { 8, 8, 8 },
748		.color_enc = TGP_COLOR_ENC_YCBCR,
749		.planes   = 3,
750		.buffers = 3,
751	},
752};
753
754/* There are this many multiplanar formats in the list */
755#define VIVID_MPLANAR_FORMATS 10
756
757const struct vivid_fmt *vivid_get_format(struct vivid_dev *dev, u32 pixelformat)
758{
759	const struct vivid_fmt *fmt;
760	unsigned k;
761
762	for (k = 0; k < ARRAY_SIZE(vivid_formats); k++) {
763		fmt = &vivid_formats[k];
764		if (fmt->fourcc == pixelformat)
765			if (fmt->buffers == 1 || dev->multiplanar)
766				return fmt;
767	}
768
769	return NULL;
770}
771
772bool vivid_vid_can_loop(struct vivid_dev *dev)
773{
774	if (dev->src_rect.width != dev->sink_rect.width ||
775	    dev->src_rect.height != dev->sink_rect.height)
776		return false;
777	if (dev->fmt_cap->fourcc != dev->fmt_out->fourcc)
778		return false;
779	if (dev->field_cap != dev->field_out)
780		return false;
781	/*
782	 * While this can be supported, it is just too much work
783	 * to actually implement.
784	 */
785	if (dev->field_cap == V4L2_FIELD_SEQ_TB ||
786	    dev->field_cap == V4L2_FIELD_SEQ_BT)
787		return false;
788	if (vivid_is_svid_cap(dev) && vivid_is_svid_out(dev)) {
789		if (!(dev->std_cap[dev->input] & V4L2_STD_525_60) !=
790		    !(dev->std_out & V4L2_STD_525_60))
791			return false;
792		return true;
793	}
794	if (vivid_is_hdmi_cap(dev) && vivid_is_hdmi_out(dev))
795		return true;
796	return false;
797}
798
799void vivid_send_source_change(struct vivid_dev *dev, unsigned type)
800{
801	struct v4l2_event ev = {
802		.type = V4L2_EVENT_SOURCE_CHANGE,
803		.u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION,
804	};
805	unsigned i;
806
807	for (i = 0; i < dev->num_inputs; i++) {
808		ev.id = i;
809		if (dev->input_type[i] == type) {
810			if (video_is_registered(&dev->vid_cap_dev) && dev->has_vid_cap)
811				v4l2_event_queue(&dev->vid_cap_dev, &ev);
812			if (video_is_registered(&dev->vbi_cap_dev) && dev->has_vbi_cap)
813				v4l2_event_queue(&dev->vbi_cap_dev, &ev);
814		}
815	}
816}
817
818/*
819 * Conversion function that converts a single-planar format to a
820 * single-plane multiplanar format.
821 */
822void fmt_sp2mp(const struct v4l2_format *sp_fmt, struct v4l2_format *mp_fmt)
823{
824	struct v4l2_pix_format_mplane *mp = &mp_fmt->fmt.pix_mp;
825	struct v4l2_plane_pix_format *ppix = &mp->plane_fmt[0];
826	const struct v4l2_pix_format *pix = &sp_fmt->fmt.pix;
827	bool is_out = sp_fmt->type == V4L2_BUF_TYPE_VIDEO_OUTPUT;
828
829	memset(mp->reserved, 0, sizeof(mp->reserved));
830	mp_fmt->type = is_out ? V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE :
831			   V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
832	mp->width = pix->width;
833	mp->height = pix->height;
834	mp->pixelformat = pix->pixelformat;
835	mp->field = pix->field;
836	mp->colorspace = pix->colorspace;
837	mp->xfer_func = pix->xfer_func;
838	/* Also copies hsv_enc */
839	mp->ycbcr_enc = pix->ycbcr_enc;
840	mp->quantization = pix->quantization;
841	mp->num_planes = 1;
842	mp->flags = pix->flags;
843	ppix->sizeimage = pix->sizeimage;
844	ppix->bytesperline = pix->bytesperline;
845	memset(ppix->reserved, 0, sizeof(ppix->reserved));
846}
847
848int fmt_sp2mp_func(struct file *file, void *priv,
849		struct v4l2_format *f, fmtfunc func)
850{
851	struct v4l2_format fmt;
852	struct v4l2_pix_format_mplane *mp = &fmt.fmt.pix_mp;
853	struct v4l2_plane_pix_format *ppix = &mp->plane_fmt[0];
854	struct v4l2_pix_format *pix = &f->fmt.pix;
855	int ret;
856
857	/* Converts to a mplane format */
858	fmt_sp2mp(f, &fmt);
859	/* Passes it to the generic mplane format function */
860	ret = func(file, priv, &fmt);
861	/* Copies back the mplane data to the single plane format */
862	pix->width = mp->width;
863	pix->height = mp->height;
864	pix->pixelformat = mp->pixelformat;
865	pix->field = mp->field;
866	pix->colorspace = mp->colorspace;
867	pix->xfer_func = mp->xfer_func;
868	/* Also copies hsv_enc */
869	pix->ycbcr_enc = mp->ycbcr_enc;
870	pix->quantization = mp->quantization;
871	pix->sizeimage = ppix->sizeimage;
872	pix->bytesperline = ppix->bytesperline;
873	pix->flags = mp->flags;
874	return ret;
875}
876
877int vivid_vid_adjust_sel(unsigned flags, struct v4l2_rect *r)
878{
879	unsigned w = r->width;
880	unsigned h = r->height;
881
882	/* sanitize w and h in case someone passes ~0 as the value */
883	w &= 0xffff;
884	h &= 0xffff;
885	if (!(flags & V4L2_SEL_FLAG_LE)) {
886		w++;
887		h++;
888		if (w < 2)
889			w = 2;
890		if (h < 2)
891			h = 2;
892	}
893	if (!(flags & V4L2_SEL_FLAG_GE)) {
894		if (w > MAX_WIDTH)
895			w = MAX_WIDTH;
896		if (h > MAX_HEIGHT)
897			h = MAX_HEIGHT;
898	}
899	w = w & ~1;
900	h = h & ~1;
901	if (w < 2 || h < 2)
902		return -ERANGE;
903	if (w > MAX_WIDTH || h > MAX_HEIGHT)
904		return -ERANGE;
905	if (r->top < 0)
906		r->top = 0;
907	if (r->left < 0)
908		r->left = 0;
909	/* sanitize left and top in case someone passes ~0 as the value */
910	r->left &= 0xfffe;
911	r->top &= 0xfffe;
912	if (r->left + w > MAX_WIDTH)
913		r->left = MAX_WIDTH - w;
914	if (r->top + h > MAX_HEIGHT)
915		r->top = MAX_HEIGHT - h;
916	if ((flags & (V4L2_SEL_FLAG_GE | V4L2_SEL_FLAG_LE)) ==
917			(V4L2_SEL_FLAG_GE | V4L2_SEL_FLAG_LE) &&
918	    (r->width != w || r->height != h))
919		return -ERANGE;
920	r->width = w;
921	r->height = h;
922	return 0;
923}
924
925int vivid_enum_fmt_vid(struct file *file, void  *priv,
926					struct v4l2_fmtdesc *f)
927{
928	struct vivid_dev *dev = video_drvdata(file);
929	const struct vivid_fmt *fmt;
930
931	if (f->index >= ARRAY_SIZE(vivid_formats) -
932	    (dev->multiplanar ? 0 : VIVID_MPLANAR_FORMATS))
933		return -EINVAL;
934
935	fmt = &vivid_formats[f->index];
936
937	f->pixelformat = fmt->fourcc;
938
939	if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
940	    f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
941		return 0;
942	/*
943	 * For capture devices, we support the CSC API.
944	 * We allow userspace to:
945	 * 1. set the colorspace
946	 * 2. set the xfer_func
947	 * 3. set the ycbcr_enc on YUV formats
948	 * 4. set the hsv_enc on HSV formats
949	 * 5. set the quantization on YUV and RGB formats
950	 */
951	f->flags |= V4L2_FMT_FLAG_CSC_COLORSPACE;
952	f->flags |= V4L2_FMT_FLAG_CSC_XFER_FUNC;
953
954	if (fmt->color_enc == TGP_COLOR_ENC_YCBCR) {
955		f->flags |= V4L2_FMT_FLAG_CSC_YCBCR_ENC;
956		f->flags |= V4L2_FMT_FLAG_CSC_QUANTIZATION;
957	} else if (fmt->color_enc == TGP_COLOR_ENC_HSV) {
958		f->flags |= V4L2_FMT_FLAG_CSC_HSV_ENC;
959	} else if (fmt->color_enc == TGP_COLOR_ENC_RGB) {
960		f->flags |= V4L2_FMT_FLAG_CSC_QUANTIZATION;
961	}
962
963	return 0;
964}
965
966int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *id)
967{
968	struct vivid_dev *dev = video_drvdata(file);
969	struct video_device *vdev = video_devdata(file);
970
971	if (vdev->vfl_dir == VFL_DIR_RX) {
972		if (!vivid_is_sdtv_cap(dev))
973			return -ENODATA;
974		*id = dev->std_cap[dev->input];
975	} else {
976		if (!vivid_is_svid_out(dev))
977			return -ENODATA;
978		*id = dev->std_out;
979	}
980	return 0;
981}
982
983int vidioc_g_dv_timings(struct file *file, void *_fh,
984				    struct v4l2_dv_timings *timings)
985{
986	struct vivid_dev *dev = video_drvdata(file);
987	struct video_device *vdev = video_devdata(file);
988
989	if (vdev->vfl_dir == VFL_DIR_RX) {
990		if (!vivid_is_hdmi_cap(dev))
991			return -ENODATA;
992		*timings = dev->dv_timings_cap[dev->input];
993	} else {
994		if (!vivid_is_hdmi_out(dev))
995			return -ENODATA;
996		*timings = dev->dv_timings_out;
997	}
998	return 0;
999}
1000
1001int vidioc_enum_dv_timings(struct file *file, void *_fh,
1002				    struct v4l2_enum_dv_timings *timings)
1003{
1004	struct vivid_dev *dev = video_drvdata(file);
1005	struct video_device *vdev = video_devdata(file);
1006
1007	if (vdev->vfl_dir == VFL_DIR_RX) {
1008		if (!vivid_is_hdmi_cap(dev))
1009			return -ENODATA;
1010	} else {
1011		if (!vivid_is_hdmi_out(dev))
1012			return -ENODATA;
1013	}
1014	return v4l2_enum_dv_timings_cap(timings, &vivid_dv_timings_cap,
1015			NULL, NULL);
1016}
1017
1018int vidioc_dv_timings_cap(struct file *file, void *_fh,
1019				    struct v4l2_dv_timings_cap *cap)
1020{
1021	struct vivid_dev *dev = video_drvdata(file);
1022	struct video_device *vdev = video_devdata(file);
1023
1024	if (vdev->vfl_dir == VFL_DIR_RX) {
1025		if (!vivid_is_hdmi_cap(dev))
1026			return -ENODATA;
1027	} else {
1028		if (!vivid_is_hdmi_out(dev))
1029			return -ENODATA;
1030	}
1031	*cap = vivid_dv_timings_cap;
1032	return 0;
1033}
1034
1035int vidioc_g_edid(struct file *file, void *_fh,
1036			 struct v4l2_edid *edid)
1037{
1038	struct vivid_dev *dev = video_drvdata(file);
1039	struct video_device *vdev = video_devdata(file);
1040	struct cec_adapter *adap;
1041
1042	memset(edid->reserved, 0, sizeof(edid->reserved));
1043	if (vdev->vfl_dir == VFL_DIR_RX) {
1044		if (edid->pad >= dev->num_inputs)
1045			return -EINVAL;
1046		if (dev->input_type[edid->pad] != HDMI)
1047			return -EINVAL;
1048		adap = dev->cec_rx_adap;
1049	} else {
1050		unsigned int bus_idx;
1051
1052		if (edid->pad >= dev->num_outputs)
1053			return -EINVAL;
1054		if (dev->output_type[edid->pad] != HDMI)
1055			return -EINVAL;
1056		if (!dev->display_present[edid->pad])
1057			return -ENODATA;
1058		bus_idx = dev->cec_output2bus_map[edid->pad];
1059		adap = dev->cec_tx_adap[bus_idx];
1060	}
1061	if (edid->start_block == 0 && edid->blocks == 0) {
1062		edid->blocks = dev->edid_blocks;
1063		return 0;
1064	}
1065	if (dev->edid_blocks == 0)
1066		return -ENODATA;
1067	if (edid->start_block >= dev->edid_blocks)
1068		return -EINVAL;
1069	if (edid->blocks > dev->edid_blocks - edid->start_block)
1070		edid->blocks = dev->edid_blocks - edid->start_block;
1071	if (adap)
1072		v4l2_set_edid_phys_addr(dev->edid, dev->edid_blocks * 128, adap->phys_addr);
1073	memcpy(edid->edid, dev->edid + edid->start_block * 128, edid->blocks * 128);
1074	return 0;
1075}
1076