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