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(0, MAX_WIDTH, 0, 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_GREY,
173 		.vdownsampling = { 1 },
174 		.bit_depth = { 8 },
175 		.color_enc = TGP_COLOR_ENC_LUMA,
176 		.planes   = 1,
177 		.buffers = 1,
178 	},
179 	{
180 		.fourcc   = V4L2_PIX_FMT_Y10,
181 		.vdownsampling = { 1 },
182 		.bit_depth = { 16 },
183 		.color_enc = TGP_COLOR_ENC_LUMA,
184 		.planes   = 1,
185 		.buffers = 1,
186 	},
187 	{
188 		.fourcc   = V4L2_PIX_FMT_Y12,
189 		.vdownsampling = { 1 },
190 		.bit_depth = { 16 },
191 		.color_enc = TGP_COLOR_ENC_LUMA,
192 		.planes   = 1,
193 		.buffers = 1,
194 	},
195 	{
196 		.fourcc   = V4L2_PIX_FMT_Y16,
197 		.vdownsampling = { 1 },
198 		.bit_depth = { 16 },
199 		.color_enc = TGP_COLOR_ENC_LUMA,
200 		.planes   = 1,
201 		.buffers = 1,
202 	},
203 	{
204 		.fourcc   = V4L2_PIX_FMT_Y16_BE,
205 		.vdownsampling = { 1 },
206 		.bit_depth = { 16 },
207 		.color_enc = TGP_COLOR_ENC_LUMA,
208 		.planes   = 1,
209 		.buffers = 1,
210 	},
211 	{
212 		.fourcc   = V4L2_PIX_FMT_RGB332, /* rrrgggbb */
213 		.vdownsampling = { 1 },
214 		.bit_depth = { 8 },
215 		.planes   = 1,
216 		.buffers = 1,
217 	},
218 	{
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 		.fourcc   = V4L2_PIX_FMT_RGB565X, /* rrrrrggg gggbbbbb */
228 		.vdownsampling = { 1 },
229 		.bit_depth = { 16 },
230 		.planes   = 1,
231 		.buffers = 1,
232 		.can_do_overlay = true,
233 	},
234 	{
235 		.fourcc   = V4L2_PIX_FMT_RGB444, /* xxxxrrrr ggggbbbb */
236 		.vdownsampling = { 1 },
237 		.bit_depth = { 16 },
238 		.planes   = 1,
239 		.buffers = 1,
240 	},
241 	{
242 		.fourcc   = V4L2_PIX_FMT_XRGB444, /* xxxxrrrr ggggbbbb */
243 		.vdownsampling = { 1 },
244 		.bit_depth = { 16 },
245 		.planes   = 1,
246 		.buffers = 1,
247 	},
248 	{
249 		.fourcc   = V4L2_PIX_FMT_ARGB444, /* aaaarrrr ggggbbbb */
250 		.vdownsampling = { 1 },
251 		.bit_depth = { 16 },
252 		.planes   = 1,
253 		.buffers = 1,
254 		.alpha_mask = 0x00f0,
255 	},
256 	{
257 		.fourcc   = V4L2_PIX_FMT_RGB555, /* gggbbbbb xrrrrrgg */
258 		.vdownsampling = { 1 },
259 		.bit_depth = { 16 },
260 		.planes   = 1,
261 		.buffers = 1,
262 		.can_do_overlay = true,
263 	},
264 	{
265 		.fourcc   = V4L2_PIX_FMT_XRGB555, /* gggbbbbb xrrrrrgg */
266 		.vdownsampling = { 1 },
267 		.bit_depth = { 16 },
268 		.planes   = 1,
269 		.buffers = 1,
270 		.can_do_overlay = true,
271 	},
272 	{
273 		.fourcc   = V4L2_PIX_FMT_ARGB555, /* gggbbbbb arrrrrgg */
274 		.vdownsampling = { 1 },
275 		.bit_depth = { 16 },
276 		.planes   = 1,
277 		.buffers = 1,
278 		.can_do_overlay = true,
279 		.alpha_mask = 0x8000,
280 	},
281 	{
282 		.fourcc   = V4L2_PIX_FMT_RGB555X, /* xrrrrrgg gggbbbbb */
283 		.vdownsampling = { 1 },
284 		.bit_depth = { 16 },
285 		.planes   = 1,
286 		.buffers = 1,
287 	},
288 	{
289 		.fourcc   = V4L2_PIX_FMT_XRGB555X, /* xrrrrrgg gggbbbbb */
290 		.vdownsampling = { 1 },
291 		.bit_depth = { 16 },
292 		.planes   = 1,
293 		.buffers = 1,
294 	},
295 	{
296 		.fourcc   = V4L2_PIX_FMT_ARGB555X, /* arrrrrgg gggbbbbb */
297 		.vdownsampling = { 1 },
298 		.bit_depth = { 16 },
299 		.planes   = 1,
300 		.buffers = 1,
301 		.alpha_mask = 0x0080,
302 	},
303 	{
304 		.fourcc   = V4L2_PIX_FMT_RGB24, /* rgb */
305 		.vdownsampling = { 1 },
306 		.bit_depth = { 24 },
307 		.planes   = 1,
308 		.buffers = 1,
309 	},
310 	{
311 		.fourcc   = V4L2_PIX_FMT_BGR24, /* bgr */
312 		.vdownsampling = { 1 },
313 		.bit_depth = { 24 },
314 		.planes   = 1,
315 		.buffers = 1,
316 	},
317 	{
318 		.fourcc   = V4L2_PIX_FMT_BGR666, /* bbbbbbgg ggggrrrr rrxxxxxx */
319 		.vdownsampling = { 1 },
320 		.bit_depth = { 32 },
321 		.planes   = 1,
322 		.buffers = 1,
323 	},
324 	{
325 		.fourcc   = V4L2_PIX_FMT_RGB32, /* xrgb */
326 		.vdownsampling = { 1 },
327 		.bit_depth = { 32 },
328 		.planes   = 1,
329 		.buffers = 1,
330 	},
331 	{
332 		.fourcc   = V4L2_PIX_FMT_BGR32, /* bgrx */
333 		.vdownsampling = { 1 },
334 		.bit_depth = { 32 },
335 		.planes   = 1,
336 		.buffers = 1,
337 	},
338 	{
339 		.fourcc   = V4L2_PIX_FMT_XRGB32, /* xrgb */
340 		.vdownsampling = { 1 },
341 		.bit_depth = { 32 },
342 		.planes   = 1,
343 		.buffers = 1,
344 	},
345 	{
346 		.fourcc   = V4L2_PIX_FMT_XBGR32, /* bgrx */
347 		.vdownsampling = { 1 },
348 		.bit_depth = { 32 },
349 		.planes   = 1,
350 		.buffers = 1,
351 	},
352 	{
353 		.fourcc   = V4L2_PIX_FMT_ARGB32, /* argb */
354 		.vdownsampling = { 1 },
355 		.bit_depth = { 32 },
356 		.planes   = 1,
357 		.buffers = 1,
358 		.alpha_mask = 0x000000ff,
359 	},
360 	{
361 		.fourcc   = V4L2_PIX_FMT_ABGR32, /* bgra */
362 		.vdownsampling = { 1 },
363 		.bit_depth = { 32 },
364 		.planes   = 1,
365 		.buffers = 1,
366 		.alpha_mask = 0xff000000,
367 	},
368 	{
369 		.fourcc   = V4L2_PIX_FMT_SBGGR8, /* Bayer BG/GR */
370 		.vdownsampling = { 1 },
371 		.bit_depth = { 8 },
372 		.planes   = 1,
373 		.buffers = 1,
374 	},
375 	{
376 		.fourcc   = V4L2_PIX_FMT_SGBRG8, /* Bayer GB/RG */
377 		.vdownsampling = { 1 },
378 		.bit_depth = { 8 },
379 		.planes   = 1,
380 		.buffers = 1,
381 	},
382 	{
383 		.fourcc   = V4L2_PIX_FMT_SGRBG8, /* Bayer GR/BG */
384 		.vdownsampling = { 1 },
385 		.bit_depth = { 8 },
386 		.planes   = 1,
387 		.buffers = 1,
388 	},
389 	{
390 		.fourcc   = V4L2_PIX_FMT_SRGGB8, /* Bayer RG/GB */
391 		.vdownsampling = { 1 },
392 		.bit_depth = { 8 },
393 		.planes   = 1,
394 		.buffers = 1,
395 	},
396 	{
397 		.fourcc   = V4L2_PIX_FMT_SBGGR10, /* Bayer BG/GR */
398 		.vdownsampling = { 1 },
399 		.bit_depth = { 16 },
400 		.planes   = 1,
401 		.buffers = 1,
402 	},
403 	{
404 		.fourcc   = V4L2_PIX_FMT_SGBRG10, /* Bayer GB/RG */
405 		.vdownsampling = { 1 },
406 		.bit_depth = { 16 },
407 		.planes   = 1,
408 		.buffers = 1,
409 	},
410 	{
411 		.fourcc   = V4L2_PIX_FMT_SGRBG10, /* Bayer GR/BG */
412 		.vdownsampling = { 1 },
413 		.bit_depth = { 16 },
414 		.planes   = 1,
415 		.buffers = 1,
416 	},
417 	{
418 		.fourcc   = V4L2_PIX_FMT_SRGGB10, /* Bayer RG/GB */
419 		.vdownsampling = { 1 },
420 		.bit_depth = { 16 },
421 		.planes   = 1,
422 		.buffers = 1,
423 	},
424 	{
425 		.fourcc   = V4L2_PIX_FMT_SBGGR12, /* Bayer BG/GR */
426 		.vdownsampling = { 1 },
427 		.bit_depth = { 16 },
428 		.planes   = 1,
429 		.buffers = 1,
430 	},
431 	{
432 		.fourcc   = V4L2_PIX_FMT_SGBRG12, /* Bayer GB/RG */
433 		.vdownsampling = { 1 },
434 		.bit_depth = { 16 },
435 		.planes   = 1,
436 		.buffers = 1,
437 	},
438 	{
439 		.fourcc   = V4L2_PIX_FMT_SGRBG12, /* Bayer GR/BG */
440 		.vdownsampling = { 1 },
441 		.bit_depth = { 16 },
442 		.planes   = 1,
443 		.buffers = 1,
444 	},
445 	{
446 		.fourcc   = V4L2_PIX_FMT_SRGGB12, /* Bayer RG/GB */
447 		.vdownsampling = { 1 },
448 		.bit_depth = { 16 },
449 		.planes   = 1,
450 		.buffers = 1,
451 	},
452 	{
453 		.fourcc   = V4L2_PIX_FMT_HSV24, /* HSV 24bits */
454 		.color_enc = TGP_COLOR_ENC_HSV,
455 		.vdownsampling = { 1 },
456 		.bit_depth = { 24 },
457 		.planes   = 1,
458 		.buffers = 1,
459 	},
460 	{
461 		.fourcc   = V4L2_PIX_FMT_HSV32, /* HSV 32bits */
462 		.color_enc = TGP_COLOR_ENC_HSV,
463 		.vdownsampling = { 1 },
464 		.bit_depth = { 32 },
465 		.planes   = 1,
466 		.buffers = 1,
467 	},
468 
469 	/* Multiplanar formats */
470 
471 	{
472 		.fourcc   = V4L2_PIX_FMT_NV16M,
473 		.vdownsampling = { 1, 1 },
474 		.bit_depth = { 8, 8 },
475 		.color_enc = TGP_COLOR_ENC_YCBCR,
476 		.planes   = 2,
477 		.buffers = 2,
478 		.data_offset = { PLANE0_DATA_OFFSET, 0 },
479 	},
480 	{
481 		.fourcc   = V4L2_PIX_FMT_NV61M,
482 		.vdownsampling = { 1, 1 },
483 		.bit_depth = { 8, 8 },
484 		.color_enc = TGP_COLOR_ENC_YCBCR,
485 		.planes   = 2,
486 		.buffers = 2,
487 		.data_offset = { 0, PLANE0_DATA_OFFSET },
488 	},
489 	{
490 		.fourcc   = V4L2_PIX_FMT_YUV420M,
491 		.vdownsampling = { 1, 2, 2 },
492 		.bit_depth = { 8, 4, 4 },
493 		.color_enc = TGP_COLOR_ENC_YCBCR,
494 		.planes   = 3,
495 		.buffers = 3,
496 	},
497 	{
498 		.fourcc   = V4L2_PIX_FMT_YVU420M,
499 		.vdownsampling = { 1, 2, 2 },
500 		.bit_depth = { 8, 4, 4 },
501 		.color_enc = TGP_COLOR_ENC_YCBCR,
502 		.planes   = 3,
503 		.buffers = 3,
504 	},
505 	{
506 		.fourcc   = V4L2_PIX_FMT_NV12M,
507 		.vdownsampling = { 1, 2 },
508 		.bit_depth = { 8, 8 },
509 		.color_enc = TGP_COLOR_ENC_YCBCR,
510 		.planes   = 2,
511 		.buffers = 2,
512 	},
513 	{
514 		.fourcc   = V4L2_PIX_FMT_NV21M,
515 		.vdownsampling = { 1, 2 },
516 		.bit_depth = { 8, 8 },
517 		.color_enc = TGP_COLOR_ENC_YCBCR,
518 		.planes   = 2,
519 		.buffers = 2,
520 	},
521 	{
522 		.fourcc   = V4L2_PIX_FMT_YUV422M,
523 		.vdownsampling = { 1, 1, 1 },
524 		.bit_depth = { 8, 4, 4 },
525 		.color_enc = TGP_COLOR_ENC_YCBCR,
526 		.planes   = 3,
527 		.buffers = 3,
528 	},
529 	{
530 		.fourcc   = V4L2_PIX_FMT_YVU422M,
531 		.vdownsampling = { 1, 1, 1 },
532 		.bit_depth = { 8, 4, 4 },
533 		.color_enc = TGP_COLOR_ENC_YCBCR,
534 		.planes   = 3,
535 		.buffers = 3,
536 	},
537 	{
538 		.fourcc   = V4L2_PIX_FMT_YUV444M,
539 		.vdownsampling = { 1, 1, 1 },
540 		.bit_depth = { 8, 8, 8 },
541 		.color_enc = TGP_COLOR_ENC_YCBCR,
542 		.planes   = 3,
543 		.buffers = 3,
544 	},
545 	{
546 		.fourcc   = V4L2_PIX_FMT_YVU444M,
547 		.vdownsampling = { 1, 1, 1 },
548 		.bit_depth = { 8, 8, 8 },
549 		.color_enc = TGP_COLOR_ENC_YCBCR,
550 		.planes   = 3,
551 		.buffers = 3,
552 	},
553 };
554 
555 /* There are this many multiplanar formats in the list */
556 #define VIVID_MPLANAR_FORMATS 10
557 
vivid_get_format(struct vivid_dev * dev,u32 pixelformat)558 const struct vivid_fmt *vivid_get_format(struct vivid_dev *dev, u32 pixelformat)
559 {
560 	const struct vivid_fmt *fmt;
561 	unsigned k;
562 
563 	for (k = 0; k < ARRAY_SIZE(vivid_formats); k++) {
564 		fmt = &vivid_formats[k];
565 		if (fmt->fourcc == pixelformat)
566 			if (fmt->buffers == 1 || dev->multiplanar)
567 				return fmt;
568 	}
569 
570 	return NULL;
571 }
572 
vivid_vid_can_loop(struct vivid_dev * dev)573 bool vivid_vid_can_loop(struct vivid_dev *dev)
574 {
575 	if (dev->src_rect.width != dev->sink_rect.width ||
576 	    dev->src_rect.height != dev->sink_rect.height)
577 		return false;
578 	if (dev->fmt_cap->fourcc != dev->fmt_out->fourcc)
579 		return false;
580 	if (dev->field_cap != dev->field_out)
581 		return false;
582 	/*
583 	 * While this can be supported, it is just too much work
584 	 * to actually implement.
585 	 */
586 	if (dev->field_cap == V4L2_FIELD_SEQ_TB ||
587 	    dev->field_cap == V4L2_FIELD_SEQ_BT)
588 		return false;
589 	if (vivid_is_svid_cap(dev) && vivid_is_svid_out(dev)) {
590 		if (!(dev->std_cap & V4L2_STD_525_60) !=
591 		    !(dev->std_out & V4L2_STD_525_60))
592 			return false;
593 		return true;
594 	}
595 	if (vivid_is_hdmi_cap(dev) && vivid_is_hdmi_out(dev))
596 		return true;
597 	return false;
598 }
599 
vivid_send_source_change(struct vivid_dev * dev,unsigned type)600 void vivid_send_source_change(struct vivid_dev *dev, unsigned type)
601 {
602 	struct v4l2_event ev = {
603 		.type = V4L2_EVENT_SOURCE_CHANGE,
604 		.u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION,
605 	};
606 	unsigned i;
607 
608 	for (i = 0; i < dev->num_inputs; i++) {
609 		ev.id = i;
610 		if (dev->input_type[i] == type) {
611 			if (video_is_registered(&dev->vid_cap_dev) && dev->has_vid_cap)
612 				v4l2_event_queue(&dev->vid_cap_dev, &ev);
613 			if (video_is_registered(&dev->vbi_cap_dev) && dev->has_vbi_cap)
614 				v4l2_event_queue(&dev->vbi_cap_dev, &ev);
615 		}
616 	}
617 }
618 
619 /*
620  * Conversion function that converts a single-planar format to a
621  * single-plane multiplanar format.
622  */
fmt_sp2mp(const struct v4l2_format * sp_fmt,struct v4l2_format * mp_fmt)623 void fmt_sp2mp(const struct v4l2_format *sp_fmt, struct v4l2_format *mp_fmt)
624 {
625 	struct v4l2_pix_format_mplane *mp = &mp_fmt->fmt.pix_mp;
626 	struct v4l2_plane_pix_format *ppix = &mp->plane_fmt[0];
627 	const struct v4l2_pix_format *pix = &sp_fmt->fmt.pix;
628 	bool is_out = sp_fmt->type == V4L2_BUF_TYPE_VIDEO_OUTPUT;
629 
630 	memset(mp->reserved, 0, sizeof(mp->reserved));
631 	mp_fmt->type = is_out ? V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE :
632 			   V4L2_CAP_VIDEO_CAPTURE_MPLANE;
633 	mp->width = pix->width;
634 	mp->height = pix->height;
635 	mp->pixelformat = pix->pixelformat;
636 	mp->field = pix->field;
637 	mp->colorspace = pix->colorspace;
638 	mp->xfer_func = pix->xfer_func;
639 	/* Also copies hsv_enc */
640 	mp->ycbcr_enc = pix->ycbcr_enc;
641 	mp->quantization = pix->quantization;
642 	mp->num_planes = 1;
643 	mp->flags = pix->flags;
644 	ppix->sizeimage = pix->sizeimage;
645 	ppix->bytesperline = pix->bytesperline;
646 	memset(ppix->reserved, 0, sizeof(ppix->reserved));
647 }
648 
fmt_sp2mp_func(struct file * file,void * priv,struct v4l2_format * f,fmtfunc func)649 int fmt_sp2mp_func(struct file *file, void *priv,
650 		struct v4l2_format *f, fmtfunc func)
651 {
652 	struct v4l2_format fmt;
653 	struct v4l2_pix_format_mplane *mp = &fmt.fmt.pix_mp;
654 	struct v4l2_plane_pix_format *ppix = &mp->plane_fmt[0];
655 	struct v4l2_pix_format *pix = &f->fmt.pix;
656 	int ret;
657 
658 	/* Converts to a mplane format */
659 	fmt_sp2mp(f, &fmt);
660 	/* Passes it to the generic mplane format function */
661 	ret = func(file, priv, &fmt);
662 	/* Copies back the mplane data to the single plane format */
663 	pix->width = mp->width;
664 	pix->height = mp->height;
665 	pix->pixelformat = mp->pixelformat;
666 	pix->field = mp->field;
667 	pix->colorspace = mp->colorspace;
668 	pix->xfer_func = mp->xfer_func;
669 	/* Also copies hsv_enc */
670 	pix->ycbcr_enc = mp->ycbcr_enc;
671 	pix->quantization = mp->quantization;
672 	pix->sizeimage = ppix->sizeimage;
673 	pix->bytesperline = ppix->bytesperline;
674 	pix->flags = mp->flags;
675 	return ret;
676 }
677 
vivid_vid_adjust_sel(unsigned flags,struct v4l2_rect * r)678 int vivid_vid_adjust_sel(unsigned flags, struct v4l2_rect *r)
679 {
680 	unsigned w = r->width;
681 	unsigned h = r->height;
682 
683 	/* sanitize w and h in case someone passes ~0 as the value */
684 	w &= 0xffff;
685 	h &= 0xffff;
686 	if (!(flags & V4L2_SEL_FLAG_LE)) {
687 		w++;
688 		h++;
689 		if (w < 2)
690 			w = 2;
691 		if (h < 2)
692 			h = 2;
693 	}
694 	if (!(flags & V4L2_SEL_FLAG_GE)) {
695 		if (w > MAX_WIDTH)
696 			w = MAX_WIDTH;
697 		if (h > MAX_HEIGHT)
698 			h = MAX_HEIGHT;
699 	}
700 	w = w & ~1;
701 	h = h & ~1;
702 	if (w < 2 || h < 2)
703 		return -ERANGE;
704 	if (w > MAX_WIDTH || h > MAX_HEIGHT)
705 		return -ERANGE;
706 	if (r->top < 0)
707 		r->top = 0;
708 	if (r->left < 0)
709 		r->left = 0;
710 	/* sanitize left and top in case someone passes ~0 as the value */
711 	r->left &= 0xfffe;
712 	r->top &= 0xfffe;
713 	if (r->left + w > MAX_WIDTH)
714 		r->left = MAX_WIDTH - w;
715 	if (r->top + h > MAX_HEIGHT)
716 		r->top = MAX_HEIGHT - h;
717 	if ((flags & (V4L2_SEL_FLAG_GE | V4L2_SEL_FLAG_LE)) ==
718 			(V4L2_SEL_FLAG_GE | V4L2_SEL_FLAG_LE) &&
719 	    (r->width != w || r->height != h))
720 		return -ERANGE;
721 	r->width = w;
722 	r->height = h;
723 	return 0;
724 }
725 
vivid_enum_fmt_vid(struct file * file,void * priv,struct v4l2_fmtdesc * f)726 int vivid_enum_fmt_vid(struct file *file, void  *priv,
727 					struct v4l2_fmtdesc *f)
728 {
729 	struct vivid_dev *dev = video_drvdata(file);
730 	const struct vivid_fmt *fmt;
731 
732 	if (f->index >= ARRAY_SIZE(vivid_formats) -
733 	    (dev->multiplanar ? 0 : VIVID_MPLANAR_FORMATS))
734 		return -EINVAL;
735 
736 	fmt = &vivid_formats[f->index];
737 
738 	f->pixelformat = fmt->fourcc;
739 	return 0;
740 }
741 
vidioc_enum_fmt_vid_mplane(struct file * file,void * priv,struct v4l2_fmtdesc * f)742 int vidioc_enum_fmt_vid_mplane(struct file *file, void  *priv,
743 					struct v4l2_fmtdesc *f)
744 {
745 	struct vivid_dev *dev = video_drvdata(file);
746 
747 	if (!dev->multiplanar)
748 		return -ENOTTY;
749 	return vivid_enum_fmt_vid(file, priv, f);
750 }
751 
vidioc_enum_fmt_vid(struct file * file,void * priv,struct v4l2_fmtdesc * f)752 int vidioc_enum_fmt_vid(struct file *file, void  *priv,
753 					struct v4l2_fmtdesc *f)
754 {
755 	struct vivid_dev *dev = video_drvdata(file);
756 
757 	if (dev->multiplanar)
758 		return -ENOTTY;
759 	return vivid_enum_fmt_vid(file, priv, f);
760 }
761 
vidioc_g_std(struct file * file,void * priv,v4l2_std_id * id)762 int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *id)
763 {
764 	struct vivid_dev *dev = video_drvdata(file);
765 	struct video_device *vdev = video_devdata(file);
766 
767 	if (vdev->vfl_dir == VFL_DIR_RX) {
768 		if (!vivid_is_sdtv_cap(dev))
769 			return -ENODATA;
770 		*id = dev->std_cap;
771 	} else {
772 		if (!vivid_is_svid_out(dev))
773 			return -ENODATA;
774 		*id = dev->std_out;
775 	}
776 	return 0;
777 }
778 
vidioc_g_dv_timings(struct file * file,void * _fh,struct v4l2_dv_timings * timings)779 int vidioc_g_dv_timings(struct file *file, void *_fh,
780 				    struct v4l2_dv_timings *timings)
781 {
782 	struct vivid_dev *dev = video_drvdata(file);
783 	struct video_device *vdev = video_devdata(file);
784 
785 	if (vdev->vfl_dir == VFL_DIR_RX) {
786 		if (!vivid_is_hdmi_cap(dev))
787 			return -ENODATA;
788 		*timings = dev->dv_timings_cap;
789 	} else {
790 		if (!vivid_is_hdmi_out(dev))
791 			return -ENODATA;
792 		*timings = dev->dv_timings_out;
793 	}
794 	return 0;
795 }
796 
vidioc_enum_dv_timings(struct file * file,void * _fh,struct v4l2_enum_dv_timings * timings)797 int vidioc_enum_dv_timings(struct file *file, void *_fh,
798 				    struct v4l2_enum_dv_timings *timings)
799 {
800 	struct vivid_dev *dev = video_drvdata(file);
801 	struct video_device *vdev = video_devdata(file);
802 
803 	if (vdev->vfl_dir == VFL_DIR_RX) {
804 		if (!vivid_is_hdmi_cap(dev))
805 			return -ENODATA;
806 	} else {
807 		if (!vivid_is_hdmi_out(dev))
808 			return -ENODATA;
809 	}
810 	return v4l2_enum_dv_timings_cap(timings, &vivid_dv_timings_cap,
811 			NULL, NULL);
812 }
813 
vidioc_dv_timings_cap(struct file * file,void * _fh,struct v4l2_dv_timings_cap * cap)814 int vidioc_dv_timings_cap(struct file *file, void *_fh,
815 				    struct v4l2_dv_timings_cap *cap)
816 {
817 	struct vivid_dev *dev = video_drvdata(file);
818 	struct video_device *vdev = video_devdata(file);
819 
820 	if (vdev->vfl_dir == VFL_DIR_RX) {
821 		if (!vivid_is_hdmi_cap(dev))
822 			return -ENODATA;
823 	} else {
824 		if (!vivid_is_hdmi_out(dev))
825 			return -ENODATA;
826 	}
827 	*cap = vivid_dv_timings_cap;
828 	return 0;
829 }
830 
vidioc_g_edid(struct file * file,void * _fh,struct v4l2_edid * edid)831 int vidioc_g_edid(struct file *file, void *_fh,
832 			 struct v4l2_edid *edid)
833 {
834 	struct vivid_dev *dev = video_drvdata(file);
835 	struct video_device *vdev = video_devdata(file);
836 	struct cec_adapter *adap;
837 
838 	memset(edid->reserved, 0, sizeof(edid->reserved));
839 	if (vdev->vfl_dir == VFL_DIR_RX) {
840 		if (edid->pad >= dev->num_inputs)
841 			return -EINVAL;
842 		if (dev->input_type[edid->pad] != HDMI)
843 			return -EINVAL;
844 		adap = dev->cec_rx_adap;
845 	} else {
846 		unsigned int bus_idx;
847 
848 		if (edid->pad >= dev->num_outputs)
849 			return -EINVAL;
850 		if (dev->output_type[edid->pad] != HDMI)
851 			return -EINVAL;
852 		bus_idx = dev->cec_output2bus_map[edid->pad];
853 		adap = dev->cec_tx_adap[bus_idx];
854 	}
855 	if (edid->start_block == 0 && edid->blocks == 0) {
856 		edid->blocks = dev->edid_blocks;
857 		return 0;
858 	}
859 	if (dev->edid_blocks == 0)
860 		return -ENODATA;
861 	if (edid->start_block >= dev->edid_blocks)
862 		return -EINVAL;
863 	if (edid->blocks > dev->edid_blocks - edid->start_block)
864 		edid->blocks = dev->edid_blocks - edid->start_block;
865 	if (adap)
866 		cec_set_edid_phys_addr(dev->edid, dev->edid_blocks * 128, adap->phys_addr);
867 	memcpy(edid->edid, dev->edid + edid->start_block * 128, edid->blocks * 128);
868 	return 0;
869 }
870