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  
20  const 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  
34  struct 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  
vivid_get_format(struct vivid_dev * dev,u32 pixelformat)757  const 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  
vivid_output_is_connected_to(struct vivid_dev * dev)772  struct vivid_dev *vivid_output_is_connected_to(struct vivid_dev *dev)
773  {
774  	struct vivid_dev *input_inst = dev->output_to_input_instance[dev->output];
775  
776  	if (!input_inst)
777  		return NULL;
778  	if (input_inst->input != dev->output_to_input_index[dev->output])
779  		return NULL;
780  	return input_inst;
781  }
782  
vivid_input_is_connected_to(struct vivid_dev * dev)783  struct vivid_dev *vivid_input_is_connected_to(struct vivid_dev *dev)
784  {
785  	s32 connected_output = dev->input_is_connected_to_output[dev->input];
786  
787  	if (connected_output < FIXED_MENU_ITEMS)
788  		return NULL;
789  	struct vivid_dev *output_inst = NULL;
790  
791  	if (vivid_is_hdmi_cap(dev)) {
792  		output_inst = vivid_ctrl_hdmi_to_output_instance[connected_output];
793  		if (vivid_ctrl_hdmi_to_output_index[connected_output] != output_inst->output)
794  			return NULL;
795  		return output_inst;
796  	} else if (vivid_is_svid_cap(dev)) {
797  		output_inst = vivid_ctrl_svid_to_output_instance[connected_output];
798  		if (vivid_ctrl_svid_to_output_index[connected_output] != output_inst->output)
799  			return NULL;
800  		return output_inst;
801  	} else {
802  		return NULL;
803  	}
804  	return output_inst;
805  }
806  
vivid_vid_can_loop(struct vivid_dev * dev)807  bool vivid_vid_can_loop(struct vivid_dev *dev)
808  {
809  	struct vivid_dev *output_inst = vivid_input_is_connected_to(dev);
810  
811  	if (!output_inst)
812  		return false;
813  	if (!vb2_is_streaming(&output_inst->vb_vid_out_q))
814  		return false;
815  	if (dev->src_rect.width != output_inst->sink_rect.width ||
816  	    dev->src_rect.height != output_inst->sink_rect.height)
817  		return false;
818  	if (dev->fmt_cap->fourcc != output_inst->fmt_out->fourcc)
819  		return false;
820  	if (dev->field_cap != output_inst->field_out)
821  		return false;
822  	/*
823  	 * While this can be supported, it is just too much work
824  	 * to actually implement.
825  	 */
826  	if (dev->field_cap == V4L2_FIELD_SEQ_TB ||
827  	    dev->field_cap == V4L2_FIELD_SEQ_BT)
828  		return false;
829  	if (vivid_is_hdmi_cap(dev))
830  		return true;
831  	if (!(dev->std_cap[dev->input] & V4L2_STD_525_60) !=
832  	    !(output_inst->std_out & V4L2_STD_525_60))
833  		return false;
834  	return true;
835  }
836  
vivid_send_input_source_change(struct vivid_dev * dev,unsigned int input_index)837  void vivid_send_input_source_change(struct vivid_dev *dev, unsigned int input_index)
838  {
839  	struct v4l2_event ev = {
840  		.type = V4L2_EVENT_SOURCE_CHANGE,
841  		.u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION,
842  	};
843  	ev.id = input_index;
844  
845  	if (video_is_registered(&dev->vid_cap_dev) && dev->has_vid_cap)
846  		v4l2_event_queue(&dev->vid_cap_dev, &ev);
847  	if (dev->input_type[input_index] == TV || dev->input_type[input_index] == SVID)
848  		if (video_is_registered(&dev->vbi_cap_dev) && dev->has_vbi_cap)
849  			v4l2_event_queue(&dev->vbi_cap_dev, &ev);
850  }
851  
vivid_send_source_change(struct vivid_dev * dev,unsigned int type)852  void vivid_send_source_change(struct vivid_dev *dev, unsigned int type)
853  {
854  	for (int i = 0; i < dev->num_inputs; i++)
855  		if (dev->input_type[i] == type)
856  			vivid_send_input_source_change(dev, i);
857  }
858  
859  /*
860   * Conversion function that converts a single-planar format to a
861   * single-plane multiplanar format.
862   */
fmt_sp2mp(const struct v4l2_format * sp_fmt,struct v4l2_format * mp_fmt)863  void fmt_sp2mp(const struct v4l2_format *sp_fmt, struct v4l2_format *mp_fmt)
864  {
865  	struct v4l2_pix_format_mplane *mp = &mp_fmt->fmt.pix_mp;
866  	struct v4l2_plane_pix_format *ppix = &mp->plane_fmt[0];
867  	const struct v4l2_pix_format *pix = &sp_fmt->fmt.pix;
868  	bool is_out = sp_fmt->type == V4L2_BUF_TYPE_VIDEO_OUTPUT;
869  
870  	memset(mp->reserved, 0, sizeof(mp->reserved));
871  	mp_fmt->type = is_out ? V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE :
872  			   V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
873  	mp->width = pix->width;
874  	mp->height = pix->height;
875  	mp->pixelformat = pix->pixelformat;
876  	mp->field = pix->field;
877  	mp->colorspace = pix->colorspace;
878  	mp->xfer_func = pix->xfer_func;
879  	/* Also copies hsv_enc */
880  	mp->ycbcr_enc = pix->ycbcr_enc;
881  	mp->quantization = pix->quantization;
882  	mp->num_planes = 1;
883  	mp->flags = pix->flags;
884  	ppix->sizeimage = pix->sizeimage;
885  	ppix->bytesperline = pix->bytesperline;
886  	memset(ppix->reserved, 0, sizeof(ppix->reserved));
887  }
888  
fmt_sp2mp_func(struct file * file,void * priv,struct v4l2_format * f,fmtfunc func)889  int fmt_sp2mp_func(struct file *file, void *priv,
890  		struct v4l2_format *f, fmtfunc func)
891  {
892  	struct v4l2_format fmt;
893  	struct v4l2_pix_format_mplane *mp = &fmt.fmt.pix_mp;
894  	struct v4l2_plane_pix_format *ppix = &mp->plane_fmt[0];
895  	struct v4l2_pix_format *pix = &f->fmt.pix;
896  	int ret;
897  
898  	/* Converts to a mplane format */
899  	fmt_sp2mp(f, &fmt);
900  	/* Passes it to the generic mplane format function */
901  	ret = func(file, priv, &fmt);
902  	/* Copies back the mplane data to the single plane format */
903  	pix->width = mp->width;
904  	pix->height = mp->height;
905  	pix->pixelformat = mp->pixelformat;
906  	pix->field = mp->field;
907  	pix->colorspace = mp->colorspace;
908  	pix->xfer_func = mp->xfer_func;
909  	/* Also copies hsv_enc */
910  	pix->ycbcr_enc = mp->ycbcr_enc;
911  	pix->quantization = mp->quantization;
912  	pix->sizeimage = ppix->sizeimage;
913  	pix->bytesperline = ppix->bytesperline;
914  	pix->flags = mp->flags;
915  	return ret;
916  }
917  
vivid_vid_adjust_sel(unsigned flags,struct v4l2_rect * r)918  int vivid_vid_adjust_sel(unsigned flags, struct v4l2_rect *r)
919  {
920  	unsigned w = r->width;
921  	unsigned h = r->height;
922  
923  	/* sanitize w and h in case someone passes ~0 as the value */
924  	w &= 0xffff;
925  	h &= 0xffff;
926  	if (!(flags & V4L2_SEL_FLAG_LE)) {
927  		w++;
928  		h++;
929  		if (w < 2)
930  			w = 2;
931  		if (h < 2)
932  			h = 2;
933  	}
934  	if (!(flags & V4L2_SEL_FLAG_GE)) {
935  		if (w > MAX_WIDTH)
936  			w = MAX_WIDTH;
937  		if (h > MAX_HEIGHT)
938  			h = MAX_HEIGHT;
939  	}
940  	w = w & ~1;
941  	h = h & ~1;
942  	if (w < 2 || h < 2)
943  		return -ERANGE;
944  	if (w > MAX_WIDTH || h > MAX_HEIGHT)
945  		return -ERANGE;
946  	if (r->top < 0)
947  		r->top = 0;
948  	if (r->left < 0)
949  		r->left = 0;
950  	/* sanitize left and top in case someone passes ~0 as the value */
951  	r->left &= 0xfffe;
952  	r->top &= 0xfffe;
953  	if (r->left + w > MAX_WIDTH)
954  		r->left = MAX_WIDTH - w;
955  	if (r->top + h > MAX_HEIGHT)
956  		r->top = MAX_HEIGHT - h;
957  	if ((flags & (V4L2_SEL_FLAG_GE | V4L2_SEL_FLAG_LE)) ==
958  			(V4L2_SEL_FLAG_GE | V4L2_SEL_FLAG_LE) &&
959  	    (r->width != w || r->height != h))
960  		return -ERANGE;
961  	r->width = w;
962  	r->height = h;
963  	return 0;
964  }
965  
vivid_enum_fmt_vid(struct file * file,void * priv,struct v4l2_fmtdesc * f)966  int vivid_enum_fmt_vid(struct file *file, void  *priv,
967  					struct v4l2_fmtdesc *f)
968  {
969  	struct vivid_dev *dev = video_drvdata(file);
970  	const struct vivid_fmt *fmt;
971  
972  	if (f->index >= ARRAY_SIZE(vivid_formats) -
973  	    (dev->multiplanar ? 0 : VIVID_MPLANAR_FORMATS))
974  		return -EINVAL;
975  
976  	fmt = &vivid_formats[f->index];
977  
978  	f->pixelformat = fmt->fourcc;
979  
980  	if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
981  	    f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
982  		return 0;
983  	/*
984  	 * For capture devices, we support the CSC API.
985  	 * We allow userspace to:
986  	 * 1. set the colorspace
987  	 * 2. set the xfer_func
988  	 * 3. set the ycbcr_enc on YUV formats
989  	 * 4. set the hsv_enc on HSV formats
990  	 * 5. set the quantization on YUV and RGB formats
991  	 */
992  	f->flags |= V4L2_FMT_FLAG_CSC_COLORSPACE;
993  	f->flags |= V4L2_FMT_FLAG_CSC_XFER_FUNC;
994  
995  	if (fmt->color_enc == TGP_COLOR_ENC_YCBCR) {
996  		f->flags |= V4L2_FMT_FLAG_CSC_YCBCR_ENC;
997  		f->flags |= V4L2_FMT_FLAG_CSC_QUANTIZATION;
998  	} else if (fmt->color_enc == TGP_COLOR_ENC_HSV) {
999  		f->flags |= V4L2_FMT_FLAG_CSC_HSV_ENC;
1000  	} else if (fmt->color_enc == TGP_COLOR_ENC_RGB) {
1001  		f->flags |= V4L2_FMT_FLAG_CSC_QUANTIZATION;
1002  	}
1003  
1004  	return 0;
1005  }
1006  
vidioc_g_std(struct file * file,void * priv,v4l2_std_id * id)1007  int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *id)
1008  {
1009  	struct vivid_dev *dev = video_drvdata(file);
1010  	struct video_device *vdev = video_devdata(file);
1011  
1012  	if (vdev->vfl_dir == VFL_DIR_RX) {
1013  		if (!vivid_is_sdtv_cap(dev))
1014  			return -ENODATA;
1015  		*id = dev->std_cap[dev->input];
1016  	} else {
1017  		if (!vivid_is_svid_out(dev))
1018  			return -ENODATA;
1019  		*id = dev->std_out;
1020  	}
1021  	return 0;
1022  }
1023  
vidioc_g_dv_timings(struct file * file,void * _fh,struct v4l2_dv_timings * timings)1024  int vidioc_g_dv_timings(struct file *file, void *_fh,
1025  				    struct v4l2_dv_timings *timings)
1026  {
1027  	struct vivid_dev *dev = video_drvdata(file);
1028  	struct video_device *vdev = video_devdata(file);
1029  
1030  	if (vdev->vfl_dir == VFL_DIR_RX) {
1031  		if (!vivid_is_hdmi_cap(dev))
1032  			return -ENODATA;
1033  		*timings = dev->dv_timings_cap[dev->input];
1034  	} else {
1035  		if (!vivid_is_hdmi_out(dev))
1036  			return -ENODATA;
1037  		*timings = dev->dv_timings_out;
1038  	}
1039  	return 0;
1040  }
1041  
vidioc_enum_dv_timings(struct file * file,void * _fh,struct v4l2_enum_dv_timings * timings)1042  int vidioc_enum_dv_timings(struct file *file, void *_fh,
1043  				    struct v4l2_enum_dv_timings *timings)
1044  {
1045  	struct vivid_dev *dev = video_drvdata(file);
1046  	struct video_device *vdev = video_devdata(file);
1047  
1048  	if (vdev->vfl_dir == VFL_DIR_RX) {
1049  		if (!vivid_is_hdmi_cap(dev))
1050  			return -ENODATA;
1051  	} else {
1052  		if (!vivid_is_hdmi_out(dev))
1053  			return -ENODATA;
1054  	}
1055  	return v4l2_enum_dv_timings_cap(timings, &vivid_dv_timings_cap,
1056  			NULL, NULL);
1057  }
1058  
vidioc_dv_timings_cap(struct file * file,void * _fh,struct v4l2_dv_timings_cap * cap)1059  int vidioc_dv_timings_cap(struct file *file, void *_fh,
1060  				    struct v4l2_dv_timings_cap *cap)
1061  {
1062  	struct vivid_dev *dev = video_drvdata(file);
1063  	struct video_device *vdev = video_devdata(file);
1064  
1065  	if (vdev->vfl_dir == VFL_DIR_RX) {
1066  		if (!vivid_is_hdmi_cap(dev))
1067  			return -ENODATA;
1068  	} else {
1069  		if (!vivid_is_hdmi_out(dev))
1070  			return -ENODATA;
1071  	}
1072  	*cap = vivid_dv_timings_cap;
1073  	return 0;
1074  }
1075  
vidioc_g_edid(struct file * file,void * _fh,struct v4l2_edid * edid)1076  int vidioc_g_edid(struct file *file, void *_fh,
1077  			 struct v4l2_edid *edid)
1078  {
1079  	struct vivid_dev *dev = video_drvdata(file);
1080  	struct vivid_dev *dev_rx = dev;
1081  	struct video_device *vdev = video_devdata(file);
1082  	struct cec_adapter *adap;
1083  	unsigned int loc;
1084  
1085  	memset(edid->reserved, 0, sizeof(edid->reserved));
1086  	if (vdev->vfl_dir == VFL_DIR_RX) {
1087  		if (edid->pad >= dev->num_inputs)
1088  			return -EINVAL;
1089  		if (dev->input_type[edid->pad] != HDMI)
1090  			return -EINVAL;
1091  		adap = dev->cec_rx_adap;
1092  	} else {
1093  		if (edid->pad >= dev->num_outputs)
1094  			return -EINVAL;
1095  		if (dev->output_type[edid->pad] != HDMI)
1096  			return -EINVAL;
1097  		dev_rx = dev->output_to_input_instance[edid->pad];
1098  		if (!dev_rx)
1099  			return -ENODATA;
1100  
1101  		unsigned int hdmi_output = dev->output_to_iface_index[edid->pad];
1102  
1103  		adap = dev->cec_tx_adap[hdmi_output];
1104  	}
1105  	if (edid->start_block == 0 && edid->blocks == 0) {
1106  		edid->blocks = dev_rx->edid_blocks;
1107  		return 0;
1108  	}
1109  	if (dev_rx->edid_blocks == 0)
1110  		return -ENODATA;
1111  	if (edid->start_block >= dev_rx->edid_blocks)
1112  		return -EINVAL;
1113  	if (edid->blocks > dev_rx->edid_blocks - edid->start_block)
1114  		edid->blocks = dev_rx->edid_blocks - edid->start_block;
1115  
1116  	memcpy(edid->edid, dev_rx->edid + edid->start_block * 128, edid->blocks * 128);
1117  
1118  	loc = cec_get_edid_spa_location(dev_rx->edid,
1119  					dev_rx->edid_blocks * 128);
1120  	if (vdev->vfl_dir == VFL_DIR_TX && adap && loc &&
1121  	    loc >= edid->start_block * 128 &&
1122  	    loc < (edid->start_block + edid->blocks) * 128) {
1123  		unsigned int i;
1124  		u8 sum = 0;
1125  
1126  		loc -= edid->start_block * 128;
1127  		edid->edid[loc] = adap->phys_addr >> 8;
1128  		edid->edid[loc + 1] = adap->phys_addr & 0xff;
1129  		loc &= ~0x7f;
1130  
1131  		/* update the checksum */
1132  		for (i = loc; i < loc + 127; i++)
1133  			sum += edid->edid[i];
1134  		edid->edid[i] = 256 - sum;
1135  	}
1136  	return 0;
1137  }
1138