• 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 		.is_yuv   = true,
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 		.is_yuv   = true,
61 		.planes   = 1,
62 		.buffers = 1,
63 	},
64 	{
65 		.fourcc   = V4L2_PIX_FMT_YVYU,
66 		.vdownsampling = { 1 },
67 		.bit_depth = { 16 },
68 		.is_yuv   = true,
69 		.planes   = 1,
70 		.buffers = 1,
71 	},
72 	{
73 		.fourcc   = V4L2_PIX_FMT_VYUY,
74 		.vdownsampling = { 1 },
75 		.bit_depth = { 16 },
76 		.is_yuv   = true,
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 		.is_yuv   = true,
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 		.is_yuv   = true,
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 		.is_yuv   = true,
101 		.planes   = 3,
102 		.buffers = 1,
103 	},
104 	{
105 		.fourcc   = V4L2_PIX_FMT_NV12,
106 		.vdownsampling = { 1, 2 },
107 		.bit_depth = { 8, 8 },
108 		.is_yuv   = true,
109 		.planes   = 2,
110 		.buffers = 1,
111 	},
112 	{
113 		.fourcc   = V4L2_PIX_FMT_NV21,
114 		.vdownsampling = { 1, 2 },
115 		.bit_depth = { 8, 8 },
116 		.is_yuv   = true,
117 		.planes   = 2,
118 		.buffers = 1,
119 	},
120 	{
121 		.fourcc   = V4L2_PIX_FMT_NV16,
122 		.vdownsampling = { 1, 1 },
123 		.bit_depth = { 8, 8 },
124 		.is_yuv   = true,
125 		.planes   = 2,
126 		.buffers = 1,
127 	},
128 	{
129 		.fourcc   = V4L2_PIX_FMT_NV61,
130 		.vdownsampling = { 1, 1 },
131 		.bit_depth = { 8, 8 },
132 		.is_yuv   = true,
133 		.planes   = 2,
134 		.buffers = 1,
135 	},
136 	{
137 		.fourcc   = V4L2_PIX_FMT_NV24,
138 		.vdownsampling = { 1, 1 },
139 		.bit_depth = { 8, 16 },
140 		.is_yuv   = true,
141 		.planes   = 2,
142 		.buffers = 1,
143 	},
144 	{
145 		.fourcc   = V4L2_PIX_FMT_NV42,
146 		.vdownsampling = { 1, 1 },
147 		.bit_depth = { 8, 16 },
148 		.is_yuv   = true,
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 		.is_yuv   = true,
188 		.planes   = 1,
189 		.buffers = 1,
190 	},
191 	{
192 		.fourcc   = V4L2_PIX_FMT_Y16,
193 		.vdownsampling = { 1 },
194 		.bit_depth = { 16 },
195 		.is_yuv   = true,
196 		.planes   = 1,
197 		.buffers = 1,
198 	},
199 	{
200 		.fourcc   = V4L2_PIX_FMT_Y16_BE,
201 		.vdownsampling = { 1 },
202 		.bit_depth = { 16 },
203 		.is_yuv   = true,
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_NV16M,
450 		.vdownsampling = { 1, 1 },
451 		.bit_depth = { 8, 8 },
452 		.is_yuv   = true,
453 		.planes   = 2,
454 		.buffers = 2,
455 		.data_offset = { PLANE0_DATA_OFFSET, 0 },
456 	},
457 	{
458 		.fourcc   = V4L2_PIX_FMT_NV61M,
459 		.vdownsampling = { 1, 1 },
460 		.bit_depth = { 8, 8 },
461 		.is_yuv   = true,
462 		.planes   = 2,
463 		.buffers = 2,
464 		.data_offset = { 0, PLANE0_DATA_OFFSET },
465 	},
466 	{
467 		.fourcc   = V4L2_PIX_FMT_YUV420M,
468 		.vdownsampling = { 1, 2, 2 },
469 		.bit_depth = { 8, 4, 4 },
470 		.is_yuv   = true,
471 		.planes   = 3,
472 		.buffers = 3,
473 	},
474 	{
475 		.fourcc   = V4L2_PIX_FMT_YVU420M,
476 		.vdownsampling = { 1, 2, 2 },
477 		.bit_depth = { 8, 4, 4 },
478 		.is_yuv   = true,
479 		.planes   = 3,
480 		.buffers = 3,
481 	},
482 	{
483 		.fourcc   = V4L2_PIX_FMT_NV12M,
484 		.vdownsampling = { 1, 2 },
485 		.bit_depth = { 8, 8 },
486 		.is_yuv   = true,
487 		.planes   = 2,
488 		.buffers = 2,
489 	},
490 	{
491 		.fourcc   = V4L2_PIX_FMT_NV21M,
492 		.vdownsampling = { 1, 2 },
493 		.bit_depth = { 8, 8 },
494 		.is_yuv   = true,
495 		.planes   = 2,
496 		.buffers = 2,
497 	},
498 };
499 
500 /* There are 6 multiplanar formats in the list */
501 #define VIVID_MPLANAR_FORMATS 6
502 
vivid_get_format(struct vivid_dev * dev,u32 pixelformat)503 const struct vivid_fmt *vivid_get_format(struct vivid_dev *dev, u32 pixelformat)
504 {
505 	const struct vivid_fmt *fmt;
506 	unsigned k;
507 
508 	for (k = 0; k < ARRAY_SIZE(vivid_formats); k++) {
509 		fmt = &vivid_formats[k];
510 		if (fmt->fourcc == pixelformat)
511 			if (fmt->buffers == 1 || dev->multiplanar)
512 				return fmt;
513 	}
514 
515 	return NULL;
516 }
517 
vivid_vid_can_loop(struct vivid_dev * dev)518 bool vivid_vid_can_loop(struct vivid_dev *dev)
519 {
520 	if (dev->src_rect.width != dev->sink_rect.width ||
521 	    dev->src_rect.height != dev->sink_rect.height)
522 		return false;
523 	if (dev->fmt_cap->fourcc != dev->fmt_out->fourcc)
524 		return false;
525 	if (dev->field_cap != dev->field_out)
526 		return false;
527 	/*
528 	 * While this can be supported, it is just too much work
529 	 * to actually implement.
530 	 */
531 	if (dev->field_cap == V4L2_FIELD_SEQ_TB ||
532 	    dev->field_cap == V4L2_FIELD_SEQ_BT)
533 		return false;
534 	if (vivid_is_svid_cap(dev) && vivid_is_svid_out(dev)) {
535 		if (!(dev->std_cap & V4L2_STD_525_60) !=
536 		    !(dev->std_out & V4L2_STD_525_60))
537 			return false;
538 		return true;
539 	}
540 	if (vivid_is_hdmi_cap(dev) && vivid_is_hdmi_out(dev))
541 		return true;
542 	return false;
543 }
544 
vivid_send_source_change(struct vivid_dev * dev,unsigned type)545 void vivid_send_source_change(struct vivid_dev *dev, unsigned type)
546 {
547 	struct v4l2_event ev = {
548 		.type = V4L2_EVENT_SOURCE_CHANGE,
549 		.u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION,
550 	};
551 	unsigned i;
552 
553 	for (i = 0; i < dev->num_inputs; i++) {
554 		ev.id = i;
555 		if (dev->input_type[i] == type) {
556 			if (video_is_registered(&dev->vid_cap_dev) && dev->has_vid_cap)
557 				v4l2_event_queue(&dev->vid_cap_dev, &ev);
558 			if (video_is_registered(&dev->vbi_cap_dev) && dev->has_vbi_cap)
559 				v4l2_event_queue(&dev->vbi_cap_dev, &ev);
560 		}
561 	}
562 }
563 
564 /*
565  * Conversion function that converts a single-planar format to a
566  * single-plane multiplanar format.
567  */
fmt_sp2mp(const struct v4l2_format * sp_fmt,struct v4l2_format * mp_fmt)568 void fmt_sp2mp(const struct v4l2_format *sp_fmt, struct v4l2_format *mp_fmt)
569 {
570 	struct v4l2_pix_format_mplane *mp = &mp_fmt->fmt.pix_mp;
571 	struct v4l2_plane_pix_format *ppix = &mp->plane_fmt[0];
572 	const struct v4l2_pix_format *pix = &sp_fmt->fmt.pix;
573 	bool is_out = sp_fmt->type == V4L2_BUF_TYPE_VIDEO_OUTPUT;
574 
575 	memset(mp->reserved, 0, sizeof(mp->reserved));
576 	mp_fmt->type = is_out ? V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE :
577 			   V4L2_CAP_VIDEO_CAPTURE_MPLANE;
578 	mp->width = pix->width;
579 	mp->height = pix->height;
580 	mp->pixelformat = pix->pixelformat;
581 	mp->field = pix->field;
582 	mp->colorspace = pix->colorspace;
583 	mp->xfer_func = pix->xfer_func;
584 	mp->ycbcr_enc = pix->ycbcr_enc;
585 	mp->quantization = pix->quantization;
586 	mp->num_planes = 1;
587 	mp->flags = pix->flags;
588 	ppix->sizeimage = pix->sizeimage;
589 	ppix->bytesperline = pix->bytesperline;
590 	memset(ppix->reserved, 0, sizeof(ppix->reserved));
591 }
592 
fmt_sp2mp_func(struct file * file,void * priv,struct v4l2_format * f,fmtfunc func)593 int fmt_sp2mp_func(struct file *file, void *priv,
594 		struct v4l2_format *f, fmtfunc func)
595 {
596 	struct v4l2_format fmt;
597 	struct v4l2_pix_format_mplane *mp = &fmt.fmt.pix_mp;
598 	struct v4l2_plane_pix_format *ppix = &mp->plane_fmt[0];
599 	struct v4l2_pix_format *pix = &f->fmt.pix;
600 	int ret;
601 
602 	/* Converts to a mplane format */
603 	fmt_sp2mp(f, &fmt);
604 	/* Passes it to the generic mplane format function */
605 	ret = func(file, priv, &fmt);
606 	/* Copies back the mplane data to the single plane format */
607 	pix->width = mp->width;
608 	pix->height = mp->height;
609 	pix->pixelformat = mp->pixelformat;
610 	pix->field = mp->field;
611 	pix->colorspace = mp->colorspace;
612 	pix->xfer_func = mp->xfer_func;
613 	pix->ycbcr_enc = mp->ycbcr_enc;
614 	pix->quantization = mp->quantization;
615 	pix->sizeimage = ppix->sizeimage;
616 	pix->bytesperline = ppix->bytesperline;
617 	pix->flags = mp->flags;
618 	return ret;
619 }
620 
621 /* v4l2_rect helper function: copy the width/height values */
rect_set_size_to(struct v4l2_rect * r,const struct v4l2_rect * size)622 void rect_set_size_to(struct v4l2_rect *r, const struct v4l2_rect *size)
623 {
624 	r->width = size->width;
625 	r->height = size->height;
626 }
627 
628 /* v4l2_rect helper function: width and height of r should be >= min_size */
rect_set_min_size(struct v4l2_rect * r,const struct v4l2_rect * min_size)629 void rect_set_min_size(struct v4l2_rect *r, const struct v4l2_rect *min_size)
630 {
631 	if (r->width < min_size->width)
632 		r->width = min_size->width;
633 	if (r->height < min_size->height)
634 		r->height = min_size->height;
635 }
636 
637 /* v4l2_rect helper function: width and height of r should be <= max_size */
rect_set_max_size(struct v4l2_rect * r,const struct v4l2_rect * max_size)638 void rect_set_max_size(struct v4l2_rect *r, const struct v4l2_rect *max_size)
639 {
640 	if (r->width > max_size->width)
641 		r->width = max_size->width;
642 	if (r->height > max_size->height)
643 		r->height = max_size->height;
644 }
645 
646 /* v4l2_rect helper function: r should be inside boundary */
rect_map_inside(struct v4l2_rect * r,const struct v4l2_rect * boundary)647 void rect_map_inside(struct v4l2_rect *r, const struct v4l2_rect *boundary)
648 {
649 	rect_set_max_size(r, boundary);
650 	if (r->left < boundary->left)
651 		r->left = boundary->left;
652 	if (r->top < boundary->top)
653 		r->top = boundary->top;
654 	if (r->left + r->width > boundary->width)
655 		r->left = boundary->width - r->width;
656 	if (r->top + r->height > boundary->height)
657 		r->top = boundary->height - r->height;
658 }
659 
660 /* v4l2_rect helper function: return true if r1 has the same size as r2 */
rect_same_size(const struct v4l2_rect * r1,const struct v4l2_rect * r2)661 bool rect_same_size(const struct v4l2_rect *r1, const struct v4l2_rect *r2)
662 {
663 	return r1->width == r2->width && r1->height == r2->height;
664 }
665 
666 /* v4l2_rect helper function: calculate the intersection of two rects */
rect_intersect(const struct v4l2_rect * a,const struct v4l2_rect * b)667 struct v4l2_rect rect_intersect(const struct v4l2_rect *a, const struct v4l2_rect *b)
668 {
669 	struct v4l2_rect r;
670 	int right, bottom;
671 
672 	r.top = max(a->top, b->top);
673 	r.left = max(a->left, b->left);
674 	bottom = min(a->top + a->height, b->top + b->height);
675 	right = min(a->left + a->width, b->left + b->width);
676 	r.height = max(0, bottom - r.top);
677 	r.width = max(0, right - r.left);
678 	return r;
679 }
680 
681 /*
682  * v4l2_rect helper function: scale rect r by to->width / from->width and
683  * to->height / from->height.
684  */
rect_scale(struct v4l2_rect * r,const struct v4l2_rect * from,const struct v4l2_rect * to)685 void rect_scale(struct v4l2_rect *r, const struct v4l2_rect *from,
686 				     const struct v4l2_rect *to)
687 {
688 	if (from->width == 0 || from->height == 0) {
689 		r->left = r->top = r->width = r->height = 0;
690 		return;
691 	}
692 	r->left = (((r->left - from->left) * to->width) / from->width) & ~1;
693 	r->width = ((r->width * to->width) / from->width) & ~1;
694 	r->top = ((r->top - from->top) * to->height) / from->height;
695 	r->height = (r->height * to->height) / from->height;
696 }
697 
rect_overlap(const struct v4l2_rect * r1,const struct v4l2_rect * r2)698 bool rect_overlap(const struct v4l2_rect *r1, const struct v4l2_rect *r2)
699 {
700 	/*
701 	 * IF the left side of r1 is to the right of the right side of r2 OR
702 	 *    the left side of r2 is to the right of the right side of r1 THEN
703 	 * they do not overlap.
704 	 */
705 	if (r1->left >= r2->left + r2->width ||
706 	    r2->left >= r1->left + r1->width)
707 		return false;
708 	/*
709 	 * IF the top side of r1 is below the bottom of r2 OR
710 	 *    the top side of r2 is below the bottom of r1 THEN
711 	 * they do not overlap.
712 	 */
713 	if (r1->top >= r2->top + r2->height ||
714 	    r2->top >= r1->top + r1->height)
715 		return false;
716 	return true;
717 }
vivid_vid_adjust_sel(unsigned flags,struct v4l2_rect * r)718 int vivid_vid_adjust_sel(unsigned flags, struct v4l2_rect *r)
719 {
720 	unsigned w = r->width;
721 	unsigned h = r->height;
722 
723 	/* sanitize w and h in case someone passes ~0 as the value */
724 	w &= 0xffff;
725 	h &= 0xffff;
726 	if (!(flags & V4L2_SEL_FLAG_LE)) {
727 		w++;
728 		h++;
729 		if (w < 2)
730 			w = 2;
731 		if (h < 2)
732 			h = 2;
733 	}
734 	if (!(flags & V4L2_SEL_FLAG_GE)) {
735 		if (w > MAX_WIDTH)
736 			w = MAX_WIDTH;
737 		if (h > MAX_HEIGHT)
738 			h = MAX_HEIGHT;
739 	}
740 	w = w & ~1;
741 	h = h & ~1;
742 	if (w < 2 || h < 2)
743 		return -ERANGE;
744 	if (w > MAX_WIDTH || h > MAX_HEIGHT)
745 		return -ERANGE;
746 	if (r->top < 0)
747 		r->top = 0;
748 	if (r->left < 0)
749 		r->left = 0;
750 	/* sanitize left and top in case someone passes ~0 as the value */
751 	r->left &= 0xfffe;
752 	r->top &= 0xfffe;
753 	if (r->left + w > MAX_WIDTH)
754 		r->left = MAX_WIDTH - w;
755 	if (r->top + h > MAX_HEIGHT)
756 		r->top = MAX_HEIGHT - h;
757 	if ((flags & (V4L2_SEL_FLAG_GE | V4L2_SEL_FLAG_LE)) ==
758 			(V4L2_SEL_FLAG_GE | V4L2_SEL_FLAG_LE) &&
759 	    (r->width != w || r->height != h))
760 		return -ERANGE;
761 	r->width = w;
762 	r->height = h;
763 	return 0;
764 }
765 
vivid_enum_fmt_vid(struct file * file,void * priv,struct v4l2_fmtdesc * f)766 int vivid_enum_fmt_vid(struct file *file, void  *priv,
767 					struct v4l2_fmtdesc *f)
768 {
769 	struct vivid_dev *dev = video_drvdata(file);
770 	const struct vivid_fmt *fmt;
771 
772 	if (f->index >= ARRAY_SIZE(vivid_formats) -
773 	    (dev->multiplanar ? 0 : VIVID_MPLANAR_FORMATS))
774 		return -EINVAL;
775 
776 	fmt = &vivid_formats[f->index];
777 
778 	f->pixelformat = fmt->fourcc;
779 	return 0;
780 }
781 
vidioc_enum_fmt_vid_mplane(struct file * file,void * priv,struct v4l2_fmtdesc * f)782 int vidioc_enum_fmt_vid_mplane(struct file *file, void  *priv,
783 					struct v4l2_fmtdesc *f)
784 {
785 	struct vivid_dev *dev = video_drvdata(file);
786 
787 	if (!dev->multiplanar)
788 		return -ENOTTY;
789 	return vivid_enum_fmt_vid(file, priv, f);
790 }
791 
vidioc_enum_fmt_vid(struct file * file,void * priv,struct v4l2_fmtdesc * f)792 int vidioc_enum_fmt_vid(struct file *file, void  *priv,
793 					struct v4l2_fmtdesc *f)
794 {
795 	struct vivid_dev *dev = video_drvdata(file);
796 
797 	if (dev->multiplanar)
798 		return -ENOTTY;
799 	return vivid_enum_fmt_vid(file, priv, f);
800 }
801 
vidioc_g_std(struct file * file,void * priv,v4l2_std_id * id)802 int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *id)
803 {
804 	struct vivid_dev *dev = video_drvdata(file);
805 	struct video_device *vdev = video_devdata(file);
806 
807 	if (vdev->vfl_dir == VFL_DIR_RX) {
808 		if (!vivid_is_sdtv_cap(dev))
809 			return -ENODATA;
810 		*id = dev->std_cap;
811 	} else {
812 		if (!vivid_is_svid_out(dev))
813 			return -ENODATA;
814 		*id = dev->std_out;
815 	}
816 	return 0;
817 }
818 
vidioc_g_dv_timings(struct file * file,void * _fh,struct v4l2_dv_timings * timings)819 int vidioc_g_dv_timings(struct file *file, void *_fh,
820 				    struct v4l2_dv_timings *timings)
821 {
822 	struct vivid_dev *dev = video_drvdata(file);
823 	struct video_device *vdev = video_devdata(file);
824 
825 	if (vdev->vfl_dir == VFL_DIR_RX) {
826 		if (!vivid_is_hdmi_cap(dev))
827 			return -ENODATA;
828 		*timings = dev->dv_timings_cap;
829 	} else {
830 		if (!vivid_is_hdmi_out(dev))
831 			return -ENODATA;
832 		*timings = dev->dv_timings_out;
833 	}
834 	return 0;
835 }
836 
vidioc_enum_dv_timings(struct file * file,void * _fh,struct v4l2_enum_dv_timings * timings)837 int vidioc_enum_dv_timings(struct file *file, void *_fh,
838 				    struct v4l2_enum_dv_timings *timings)
839 {
840 	struct vivid_dev *dev = video_drvdata(file);
841 	struct video_device *vdev = video_devdata(file);
842 
843 	if (vdev->vfl_dir == VFL_DIR_RX) {
844 		if (!vivid_is_hdmi_cap(dev))
845 			return -ENODATA;
846 	} else {
847 		if (!vivid_is_hdmi_out(dev))
848 			return -ENODATA;
849 	}
850 	return v4l2_enum_dv_timings_cap(timings, &vivid_dv_timings_cap,
851 			NULL, NULL);
852 }
853 
vidioc_dv_timings_cap(struct file * file,void * _fh,struct v4l2_dv_timings_cap * cap)854 int vidioc_dv_timings_cap(struct file *file, void *_fh,
855 				    struct v4l2_dv_timings_cap *cap)
856 {
857 	struct vivid_dev *dev = video_drvdata(file);
858 	struct video_device *vdev = video_devdata(file);
859 
860 	if (vdev->vfl_dir == VFL_DIR_RX) {
861 		if (!vivid_is_hdmi_cap(dev))
862 			return -ENODATA;
863 	} else {
864 		if (!vivid_is_hdmi_out(dev))
865 			return -ENODATA;
866 	}
867 	*cap = vivid_dv_timings_cap;
868 	return 0;
869 }
870 
vidioc_g_edid(struct file * file,void * _fh,struct v4l2_edid * edid)871 int vidioc_g_edid(struct file *file, void *_fh,
872 			 struct v4l2_edid *edid)
873 {
874 	struct vivid_dev *dev = video_drvdata(file);
875 	struct video_device *vdev = video_devdata(file);
876 
877 	memset(edid->reserved, 0, sizeof(edid->reserved));
878 	if (vdev->vfl_dir == VFL_DIR_RX) {
879 		if (edid->pad >= dev->num_inputs)
880 			return -EINVAL;
881 		if (dev->input_type[edid->pad] != HDMI)
882 			return -EINVAL;
883 	} else {
884 		if (edid->pad >= dev->num_outputs)
885 			return -EINVAL;
886 		if (dev->output_type[edid->pad] != HDMI)
887 			return -EINVAL;
888 	}
889 	if (edid->start_block == 0 && edid->blocks == 0) {
890 		edid->blocks = dev->edid_blocks;
891 		return 0;
892 	}
893 	if (dev->edid_blocks == 0)
894 		return -ENODATA;
895 	if (edid->start_block >= dev->edid_blocks)
896 		return -EINVAL;
897 	if (edid->start_block + edid->blocks > dev->edid_blocks)
898 		edid->blocks = dev->edid_blocks - edid->start_block;
899 	memcpy(edid->edid, dev->edid, edid->blocks * 128);
900 	return 0;
901 }
902