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