3 * Support for Intel Camera Imaging ISP subsystem.
4 * Copyright (c) 2015, Intel Corporation.
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License,
8 * version 2, as published by the Free Software Foundation.
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17 Support for Intel Camera Imaging ISP subsystem.
18 Copyright (c) 2010 - 2015, Intel Corporation.
20 This program is free software; you can redistribute it and/or modify it
21 under the terms and conditions of the GNU General Public License,
22 version 2, as published by the Free Software Foundation.
24 This program is distributed in the hope it will be useful, but WITHOUT
25 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
26 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
31 #include "ia_css_frame.h"
32 #include <math_support.h>
33 #include "assert_support.h"
34 #include "ia_css_debug.h"
36 #include "sh_css_internal.h"
37 #include "memory_access.h"
40 #define NV12_TILEY_TILE_WIDTH 128
41 #define NV12_TILEY_TILE_HEIGHT 32
43 /**************************************************************************
44 ** Static functions declarations
45 **************************************************************************/
46 static void frame_init_plane(struct ia_css_frame_plane
*plane
,
52 static void frame_init_single_plane(struct ia_css_frame
*frame
,
53 struct ia_css_frame_plane
*plane
,
55 unsigned int subpixels_per_line
,
56 unsigned int bytes_per_pixel
);
58 static void frame_init_raw_single_plane(
59 struct ia_css_frame
*frame
,
60 struct ia_css_frame_plane
*plane
,
62 unsigned int subpixels_per_line
,
63 unsigned int bits_per_pixel
);
65 static void frame_init_mipi_plane(struct ia_css_frame
*frame
,
66 struct ia_css_frame_plane
*plane
,
68 unsigned int subpixels_per_line
,
69 unsigned int bytes_per_pixel
);
71 static void frame_init_nv_planes(struct ia_css_frame
*frame
,
72 unsigned int horizontal_decimation
,
73 unsigned int vertical_decimation
,
74 unsigned int bytes_per_element
);
76 static void frame_init_yuv_planes(struct ia_css_frame
*frame
,
77 unsigned int horizontal_decimation
,
78 unsigned int vertical_decimation
,
80 unsigned int bytes_per_element
);
82 static void frame_init_rgb_planes(struct ia_css_frame
*frame
,
83 unsigned int bytes_per_element
);
85 static void frame_init_qplane6_planes(struct ia_css_frame
*frame
);
87 static enum ia_css_err
frame_allocate_buffer_data(struct ia_css_frame
*frame
);
89 static enum ia_css_err
frame_allocate_with_data(struct ia_css_frame
**frame
,
92 enum ia_css_frame_format format
,
93 unsigned int padded_width
,
94 unsigned int raw_bit_depth
,
97 static struct ia_css_frame
*frame_create(unsigned int width
,
99 enum ia_css_frame_format format
,
100 unsigned int padded_width
,
101 unsigned int raw_bit_depth
,
106 ia_css_elems_bytes_from_info(
107 const struct ia_css_frame_info
*info
);
109 /**************************************************************************
110 ** CSS API functions, exposed by ia_css.h
111 **************************************************************************/
113 void ia_css_frame_zero(struct ia_css_frame
*frame
)
115 assert(frame
!= NULL
);
116 mmgr_clear(frame
->data
, frame
->data_bytes
);
119 enum ia_css_err
ia_css_frame_allocate_from_info(struct ia_css_frame
**frame
,
120 const struct ia_css_frame_info
*info
)
122 enum ia_css_err err
= IA_CSS_SUCCESS
;
123 if (frame
== NULL
|| info
== NULL
)
124 return IA_CSS_ERR_INVALID_ARGUMENTS
;
125 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE
,
126 "ia_css_frame_allocate_from_info() enter:\n");
128 ia_css_frame_allocate(frame
, info
->res
.width
, info
->res
.height
,
129 info
->format
, info
->padded_width
,
130 info
->raw_bit_depth
);
131 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE
,
132 "ia_css_frame_allocate_from_info() leave:\n");
136 enum ia_css_err
ia_css_frame_allocate(struct ia_css_frame
**frame
,
139 enum ia_css_frame_format format
,
140 unsigned int padded_width
,
141 unsigned int raw_bit_depth
)
143 enum ia_css_err err
= IA_CSS_SUCCESS
;
145 if (frame
== NULL
|| width
== 0 || height
== 0)
146 return IA_CSS_ERR_INVALID_ARGUMENTS
;
148 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE
,
150 "ia_css_frame_allocate() enter: width=%d, height=%d, format=%d\n",
151 width
, height
, format
);
153 "ia_css_frame_allocate() enter: width=%d, height=%d, format=%d, padded_width=%d, raw_bit_depth=%d\n",
154 width
, height
, format
, padded_width
, raw_bit_depth
);
157 err
= frame_allocate_with_data(frame
, width
, height
, format
,
158 padded_width
, raw_bit_depth
, false);
161 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE
,
162 "ia_css_frame_allocate() leave: frame=%p\n", *frame
);
164 if ((*frame
!= NULL
) && err
== IA_CSS_SUCCESS
)
165 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE
,
166 "ia_css_frame_allocate() leave: frame=%p, data(DDR address)=0x%x\n", *frame
, (*frame
)->data
);
168 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE
,
169 "ia_css_frame_allocate() leave: frame=%p, data(DDR address)=0x%x\n",
170 (void *)-1, (unsigned int)-1);
176 enum ia_css_err
ia_css_frame_map(struct ia_css_frame
**frame
,
177 const struct ia_css_frame_info
*info
,
182 enum ia_css_err err
= IA_CSS_SUCCESS
;
183 struct ia_css_frame
*me
;
184 assert(frame
!= NULL
);
186 /* Create the frame structure */
187 err
= ia_css_frame_create_from_info(&me
, info
);
189 if (err
!= IA_CSS_SUCCESS
)
192 if (err
== IA_CSS_SUCCESS
) {
193 /* use mmgr_mmap to map */
194 me
->data
= (ia_css_ptr
) mmgr_mmap(data
,
197 if (me
->data
== mmgr_NULL
)
198 err
= IA_CSS_ERR_INVALID_ARGUMENTS
;
201 if (err
!= IA_CSS_SUCCESS
) {
215 enum ia_css_err
ia_css_frame_create_from_info(struct ia_css_frame
**frame
,
216 const struct ia_css_frame_info
*info
)
218 enum ia_css_err err
= IA_CSS_SUCCESS
;
219 struct ia_css_frame
*me
;
220 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE
,
221 "ia_css_frame_create_from_info() enter:\n");
222 if (frame
== NULL
|| info
== NULL
) {
223 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE
,
224 "ia_css_frame_create_from_info() leave:"
225 " invalid arguments\n");
226 return IA_CSS_ERR_INVALID_ARGUMENTS
;
229 me
= frame_create(info
->res
.width
,
237 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE
,
238 "ia_css_frame_create_from_info() leave:"
239 " frame create failed\n");
240 return IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY
;
243 err
= ia_css_frame_init_planes(me
);
246 if (err
== IA_CSS_SUCCESS
)
250 if (err
!= IA_CSS_SUCCESS
) {
260 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE
, "ia_css_frame_create_from_info() leave:\n");
265 enum ia_css_err
ia_css_frame_set_data(struct ia_css_frame
*frame
,
266 const ia_css_ptr mapped_data
,
269 enum ia_css_err err
= IA_CSS_SUCCESS
;
270 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE
,
271 "ia_css_frame_set_data() enter:\n");
273 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE
,
274 "ia_css_frame_set_data() leave: NULL frame\n");
275 return IA_CSS_ERR_INVALID_ARGUMENTS
;
278 /* If we are setting a valid data.
279 * Make sure that there is enough
280 * room for the expected frame format
282 if ((mapped_data
!= mmgr_NULL
) && (frame
->data_bytes
> data_bytes
)) {
283 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE
,
284 "ia_css_frame_set_data() leave: invalid arguments\n");
285 return IA_CSS_ERR_INVALID_ARGUMENTS
;
288 frame
->data
= mapped_data
;
290 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE
, "ia_css_frame_set_data() leave:\n");
295 enum ia_css_err
ia_css_frame_allocate_contiguous(struct ia_css_frame
**frame
,
298 enum ia_css_frame_format format
,
299 unsigned int padded_width
,
300 unsigned int raw_bit_depth
)
302 enum ia_css_err err
= IA_CSS_SUCCESS
;
304 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE
,
305 "ia_css_frame_allocate_contiguous() "
307 "enter: width=%d, height=%d, format=%d\n",
308 width
, height
, format
);
310 "enter: width=%d, height=%d, format=%d, padded_width=%d, raw_bit_depth=%d\n",
311 width
, height
, format
, padded_width
, raw_bit_depth
);
314 err
= frame_allocate_with_data(frame
, width
, height
, format
,
315 padded_width
, raw_bit_depth
, true);
317 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE
,
318 "ia_css_frame_allocate_contiguous() leave: frame=%p\n",
319 frame
? *frame
: (void *)-1);
324 enum ia_css_err
ia_css_frame_allocate_contiguous_from_info(
325 struct ia_css_frame
**frame
,
326 const struct ia_css_frame_info
*info
)
328 enum ia_css_err err
= IA_CSS_SUCCESS
;
329 assert(frame
!= NULL
);
330 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE
,
331 "ia_css_frame_allocate_contiguous_from_info() enter:\n");
332 err
= ia_css_frame_allocate_contiguous(frame
,
337 info
->raw_bit_depth
);
338 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE
,
339 "ia_css_frame_allocate_contiguous_from_info() leave:\n");
343 void ia_css_frame_free(struct ia_css_frame
*frame
)
345 IA_CSS_ENTER_PRIVATE("frame = %p", frame
);
348 hmm_free(frame
->data
);
352 IA_CSS_LEAVE_PRIVATE("void");
355 /**************************************************************************
356 ** Module public functions
357 **************************************************************************/
359 enum ia_css_err
ia_css_frame_check_info(const struct ia_css_frame_info
*info
)
361 assert(info
!= NULL
);
362 if (info
->res
.width
== 0 || info
->res
.height
== 0)
363 return IA_CSS_ERR_INVALID_ARGUMENTS
;
364 return IA_CSS_SUCCESS
;
367 enum ia_css_err
ia_css_frame_init_planes(struct ia_css_frame
*frame
)
369 assert(frame
!= NULL
);
371 switch (frame
->info
.format
) {
372 case IA_CSS_FRAME_FORMAT_MIPI
:
373 frame_init_mipi_plane(frame
, &frame
->planes
.raw
,
374 frame
->info
.res
.height
,
375 frame
->info
.padded_width
,
376 frame
->info
.raw_bit_depth
<= 8 ? 1 : 2);
378 case IA_CSS_FRAME_FORMAT_RAW_PACKED
:
379 frame_init_raw_single_plane(frame
, &frame
->planes
.raw
,
380 frame
->info
.res
.height
,
381 frame
->info
.padded_width
,
382 frame
->info
.raw_bit_depth
);
384 case IA_CSS_FRAME_FORMAT_RAW
:
385 frame_init_single_plane(frame
, &frame
->planes
.raw
,
386 frame
->info
.res
.height
,
387 frame
->info
.padded_width
,
388 frame
->info
.raw_bit_depth
<= 8 ? 1 : 2);
390 case IA_CSS_FRAME_FORMAT_RGB565
:
391 frame_init_single_plane(frame
, &frame
->planes
.rgb
,
392 frame
->info
.res
.height
,
393 frame
->info
.padded_width
, 2);
395 case IA_CSS_FRAME_FORMAT_RGBA888
:
396 frame_init_single_plane(frame
, &frame
->planes
.rgb
,
397 frame
->info
.res
.height
,
398 frame
->info
.padded_width
* 4, 1);
400 case IA_CSS_FRAME_FORMAT_PLANAR_RGB888
:
401 frame_init_rgb_planes(frame
, 1);
403 /* yuyv and uyvu have the same frame layout, only the data
404 * positioning differs.
406 case IA_CSS_FRAME_FORMAT_YUYV
:
407 case IA_CSS_FRAME_FORMAT_UYVY
:
408 case IA_CSS_FRAME_FORMAT_CSI_MIPI_YUV420_8
:
409 case IA_CSS_FRAME_FORMAT_CSI_MIPI_LEGACY_YUV420_8
:
410 frame_init_single_plane(frame
, &frame
->planes
.yuyv
,
411 frame
->info
.res
.height
,
412 frame
->info
.padded_width
* 2, 1);
414 case IA_CSS_FRAME_FORMAT_YUV_LINE
:
415 /* Needs 3 extra lines to allow vf_pp prefetching */
416 frame_init_single_plane(frame
, &frame
->planes
.yuyv
,
417 frame
->info
.res
.height
* 3 / 2 + 3,
418 frame
->info
.padded_width
, 1);
420 case IA_CSS_FRAME_FORMAT_NV11
:
421 frame_init_nv_planes(frame
, 4, 1, 1);
423 /* nv12 and nv21 have the same frame layout, only the data
424 * positioning differs.
426 case IA_CSS_FRAME_FORMAT_NV12
:
427 case IA_CSS_FRAME_FORMAT_NV21
:
428 case IA_CSS_FRAME_FORMAT_NV12_TILEY
:
429 frame_init_nv_planes(frame
, 2, 2, 1);
431 case IA_CSS_FRAME_FORMAT_NV12_16
:
432 frame_init_nv_planes(frame
, 2, 2, 2);
434 /* nv16 and nv61 have the same frame layout, only the data
435 * positioning differs.
437 case IA_CSS_FRAME_FORMAT_NV16
:
438 case IA_CSS_FRAME_FORMAT_NV61
:
439 frame_init_nv_planes(frame
, 2, 1, 1);
441 case IA_CSS_FRAME_FORMAT_YUV420
:
442 frame_init_yuv_planes(frame
, 2, 2, false, 1);
444 case IA_CSS_FRAME_FORMAT_YUV422
:
445 frame_init_yuv_planes(frame
, 2, 1, false, 1);
447 case IA_CSS_FRAME_FORMAT_YUV444
:
448 frame_init_yuv_planes(frame
, 1, 1, false, 1);
450 case IA_CSS_FRAME_FORMAT_YUV420_16
:
451 frame_init_yuv_planes(frame
, 2, 2, false, 2);
453 case IA_CSS_FRAME_FORMAT_YUV422_16
:
454 frame_init_yuv_planes(frame
, 2, 1, false, 2);
456 case IA_CSS_FRAME_FORMAT_YV12
:
457 frame_init_yuv_planes(frame
, 2, 2, true, 1);
459 case IA_CSS_FRAME_FORMAT_YV16
:
460 frame_init_yuv_planes(frame
, 2, 1, true, 1);
462 case IA_CSS_FRAME_FORMAT_QPLANE6
:
463 frame_init_qplane6_planes(frame
);
465 case IA_CSS_FRAME_FORMAT_BINARY_8
:
466 frame_init_single_plane(frame
, &frame
->planes
.binary
.data
,
467 frame
->info
.res
.height
,
468 frame
->info
.padded_width
, 1);
469 frame
->planes
.binary
.size
= 0;
472 return IA_CSS_ERR_INVALID_ARGUMENTS
;
474 return IA_CSS_SUCCESS
;
477 void ia_css_frame_info_set_width(struct ia_css_frame_info
*info
,
479 unsigned int min_padded_width
)
483 IA_CSS_ENTER_PRIVATE("info = %p,width = %d, minimum padded width = %d",
484 info
, width
, min_padded_width
);
486 IA_CSS_ERROR("NULL input parameter");
487 IA_CSS_LEAVE_PRIVATE("");
490 if (min_padded_width
> width
)
491 align
= min_padded_width
;
495 info
->res
.width
= width
;
496 /* frames with a U and V plane of 8 bits per pixel need to have
497 all planes aligned, this means double the alignment for the
498 Y plane if the horizontal decimation is 2. */
499 if (info
->format
== IA_CSS_FRAME_FORMAT_YUV420
||
500 info
->format
== IA_CSS_FRAME_FORMAT_YV12
||
501 info
->format
== IA_CSS_FRAME_FORMAT_NV12
||
502 info
->format
== IA_CSS_FRAME_FORMAT_NV21
||
503 info
->format
== IA_CSS_FRAME_FORMAT_BINARY_8
||
504 info
->format
== IA_CSS_FRAME_FORMAT_YUV_LINE
)
506 CEIL_MUL(align
, 2 * HIVE_ISP_DDR_WORD_BYTES
);
507 else if (info
->format
== IA_CSS_FRAME_FORMAT_NV12_TILEY
)
508 info
->padded_width
= CEIL_MUL(align
, NV12_TILEY_TILE_WIDTH
);
509 else if (info
->format
== IA_CSS_FRAME_FORMAT_RAW
||
510 info
->format
== IA_CSS_FRAME_FORMAT_RAW_PACKED
)
511 info
->padded_width
= CEIL_MUL(align
, 2 * ISP_VEC_NELEMS
);
513 info
->padded_width
= CEIL_MUL(align
, HIVE_ISP_DDR_WORD_BYTES
);
515 IA_CSS_LEAVE_PRIVATE("");
518 void ia_css_frame_info_set_format(struct ia_css_frame_info
*info
,
519 enum ia_css_frame_format format
)
521 assert(info
!= NULL
);
522 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE
,
523 "ia_css_frame_info_set_format() enter:\n");
524 info
->format
= format
;
527 void ia_css_frame_info_init(struct ia_css_frame_info
*info
,
530 enum ia_css_frame_format format
,
531 unsigned int aligned
)
533 IA_CSS_ENTER_PRIVATE("info = %p, width = %d, height = %d, format = %d, aligned = %d",
534 info
, width
, height
, format
, aligned
);
536 IA_CSS_ERROR("NULL input parameter");
537 IA_CSS_LEAVE_PRIVATE("");
540 info
->res
.height
= height
;
541 info
->format
= format
;
542 ia_css_frame_info_set_width(info
, width
, aligned
);
543 IA_CSS_LEAVE_PRIVATE("");
546 void ia_css_frame_free_multiple(unsigned int num_frames
,
547 struct ia_css_frame
**frames_array
)
550 for (i
= 0; i
< num_frames
; i
++) {
551 if (frames_array
[i
]) {
552 ia_css_frame_free(frames_array
[i
]);
553 frames_array
[i
] = NULL
;
558 enum ia_css_err
ia_css_frame_allocate_with_buffer_size(
559 struct ia_css_frame
**frame
,
560 const unsigned int buffer_size_bytes
,
561 const bool contiguous
)
563 /* AM: Body coppied from frame_allocate_with_data(). */
565 struct ia_css_frame
*me
= frame_create(0, 0,
566 IA_CSS_FRAME_FORMAT_NUM
,/* Not valid format yet */
567 0, 0, contiguous
, false);
570 return IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY
;
572 /* Get the data size */
573 me
->data_bytes
= buffer_size_bytes
;
575 err
= frame_allocate_buffer_data(me
);
577 if (err
!= IA_CSS_SUCCESS
) {
591 bool ia_css_frame_info_is_same_resolution(
592 const struct ia_css_frame_info
*info_a
,
593 const struct ia_css_frame_info
*info_b
)
595 if (!info_a
|| !info_b
)
597 return (info_a
->res
.width
== info_b
->res
.width
) &&
598 (info_a
->res
.height
== info_b
->res
.height
);
601 bool ia_css_frame_is_same_type(const struct ia_css_frame
*frame_a
,
602 const struct ia_css_frame
*frame_b
)
604 bool is_equal
= false;
605 const struct ia_css_frame_info
*info_a
= &frame_a
->info
,
606 *info_b
= &frame_b
->info
;
608 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE
,
609 "ia_css_frame_is_same_type() enter:\n");
611 if (!info_a
|| !info_b
)
613 if (info_a
->format
!= info_b
->format
)
615 if (info_a
->padded_width
!= info_b
->padded_width
)
617 is_equal
= ia_css_frame_info_is_same_resolution(info_a
, info_b
);
619 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE
,
620 "ia_css_frame_is_same_type() leave:\n");
626 ia_css_dma_configure_from_info(
627 struct dma_port_config
*config
,
628 const struct ia_css_frame_info
*info
)
630 unsigned is_raw_packed
= info
->format
== IA_CSS_FRAME_FORMAT_RAW_PACKED
;
631 unsigned bits_per_pixel
= is_raw_packed
? info
->raw_bit_depth
: ia_css_elems_bytes_from_info(info
)*8;
632 unsigned pix_per_ddrword
= HIVE_ISP_DDR_WORD_BITS
/ bits_per_pixel
;
633 unsigned words_per_line
= CEIL_DIV(info
->padded_width
, pix_per_ddrword
);
634 unsigned elems_b
= pix_per_ddrword
;
636 config
->stride
= HIVE_ISP_DDR_WORD_BYTES
* words_per_line
;
637 config
->elems
= (uint8_t)elems_b
;
638 config
->width
= (uint16_t)info
->res
.width
;
640 assert(config
->width
<= info
->padded_width
);
643 /**************************************************************************
645 **************************************************************************/
647 static void frame_init_plane(struct ia_css_frame_plane
*plane
,
653 plane
->height
= height
;
654 plane
->width
= width
;
655 plane
->stride
= stride
;
656 plane
->offset
= offset
;
659 static void frame_init_single_plane(struct ia_css_frame
*frame
,
660 struct ia_css_frame_plane
*plane
,
662 unsigned int subpixels_per_line
,
663 unsigned int bytes_per_pixel
)
667 stride
= subpixels_per_line
* bytes_per_pixel
;
668 /* Frame height needs to be even number - needed by hw ISYS2401
669 In case of odd number, round up to even.
670 Images won't be impacted by this round up,
671 only needed by jpeg/embedded data.
672 As long as buffer allocation and release are using data_bytes,
673 there won't be memory leak. */
674 frame
->data_bytes
= stride
* CEIL_MUL2(height
, 2);
675 frame_init_plane(plane
, subpixels_per_line
, stride
, height
, 0);
679 static void frame_init_raw_single_plane(
680 struct ia_css_frame
*frame
,
681 struct ia_css_frame_plane
*plane
,
683 unsigned int subpixels_per_line
,
684 unsigned int bits_per_pixel
)
687 assert(frame
!= NULL
);
689 stride
= HIVE_ISP_DDR_WORD_BYTES
*
690 CEIL_DIV(subpixels_per_line
,
691 HIVE_ISP_DDR_WORD_BITS
/ bits_per_pixel
);
692 frame
->data_bytes
= stride
* height
;
693 frame_init_plane(plane
, subpixels_per_line
, stride
, height
, 0);
697 static void frame_init_mipi_plane(struct ia_css_frame
*frame
,
698 struct ia_css_frame_plane
*plane
,
700 unsigned int subpixels_per_line
,
701 unsigned int bytes_per_pixel
)
705 stride
= subpixels_per_line
* bytes_per_pixel
;
706 frame
->data_bytes
= 8388608; /* 8*1024*1024 */
707 frame
->valid
= false;
708 frame
->contiguous
= true;
709 frame_init_plane(plane
, subpixels_per_line
, stride
, height
, 0);
713 static void frame_init_nv_planes(struct ia_css_frame
*frame
,
714 unsigned int horizontal_decimation
,
715 unsigned int vertical_decimation
,
716 unsigned int bytes_per_element
)
718 unsigned int y_width
= frame
->info
.padded_width
;
719 unsigned int y_height
= frame
->info
.res
.height
;
720 unsigned int uv_width
;
721 unsigned int uv_height
;
722 unsigned int y_bytes
;
723 unsigned int uv_bytes
;
724 unsigned int y_stride
;
725 unsigned int uv_stride
;
727 assert(horizontal_decimation
!= 0 && vertical_decimation
!= 0);
729 uv_width
= 2 * (y_width
/ horizontal_decimation
);
730 uv_height
= y_height
/ vertical_decimation
;
732 if (IA_CSS_FRAME_FORMAT_NV12_TILEY
== frame
->info
.format
) {
733 y_width
= CEIL_MUL(y_width
, NV12_TILEY_TILE_WIDTH
);
734 uv_width
= CEIL_MUL(uv_width
, NV12_TILEY_TILE_WIDTH
);
735 y_height
= CEIL_MUL(y_height
, NV12_TILEY_TILE_HEIGHT
);
736 uv_height
= CEIL_MUL(uv_height
, NV12_TILEY_TILE_HEIGHT
);
739 y_stride
= y_width
* bytes_per_element
;
740 uv_stride
= uv_width
* bytes_per_element
;
741 y_bytes
= y_stride
* y_height
;
742 uv_bytes
= uv_stride
* uv_height
;
744 frame
->data_bytes
= y_bytes
+ uv_bytes
;
745 frame_init_plane(&frame
->planes
.nv
.y
, y_width
, y_stride
, y_height
, 0);
746 frame_init_plane(&frame
->planes
.nv
.uv
, uv_width
,
747 uv_stride
, uv_height
, y_bytes
);
751 static void frame_init_yuv_planes(struct ia_css_frame
*frame
,
752 unsigned int horizontal_decimation
,
753 unsigned int vertical_decimation
,
755 unsigned int bytes_per_element
)
757 unsigned int y_width
= frame
->info
.padded_width
,
758 y_height
= frame
->info
.res
.height
,
759 uv_width
= y_width
/ horizontal_decimation
,
760 uv_height
= y_height
/ vertical_decimation
,
761 y_stride
, y_bytes
, uv_bytes
, uv_stride
;
763 y_stride
= y_width
* bytes_per_element
;
764 uv_stride
= uv_width
* bytes_per_element
;
765 y_bytes
= y_stride
* y_height
;
766 uv_bytes
= uv_stride
* uv_height
;
768 frame
->data_bytes
= y_bytes
+ 2 * uv_bytes
;
769 frame_init_plane(&frame
->planes
.yuv
.y
, y_width
, y_stride
, y_height
, 0);
771 frame_init_plane(&frame
->planes
.yuv
.v
, uv_width
, uv_stride
,
773 frame_init_plane(&frame
->planes
.yuv
.u
, uv_width
, uv_stride
,
774 uv_height
, y_bytes
+ uv_bytes
);
776 frame_init_plane(&frame
->planes
.yuv
.u
, uv_width
, uv_stride
,
778 frame_init_plane(&frame
->planes
.yuv
.v
, uv_width
, uv_stride
,
779 uv_height
, y_bytes
+ uv_bytes
);
784 static void frame_init_rgb_planes(struct ia_css_frame
*frame
,
785 unsigned int bytes_per_element
)
787 unsigned int width
= frame
->info
.res
.width
,
788 height
= frame
->info
.res
.height
, stride
, bytes
;
790 stride
= width
* bytes_per_element
;
791 bytes
= stride
* height
;
792 frame
->data_bytes
= 3 * bytes
;
793 frame_init_plane(&frame
->planes
.planar_rgb
.r
, width
, stride
, height
, 0);
794 frame_init_plane(&frame
->planes
.planar_rgb
.g
,
795 width
, stride
, height
, 1 * bytes
);
796 frame_init_plane(&frame
->planes
.planar_rgb
.b
,
797 width
, stride
, height
, 2 * bytes
);
801 static void frame_init_qplane6_planes(struct ia_css_frame
*frame
)
803 unsigned int width
= frame
->info
.padded_width
/ 2,
804 height
= frame
->info
.res
.height
/ 2, bytes
, stride
;
807 bytes
= stride
* height
;
809 frame
->data_bytes
= 6 * bytes
;
810 frame_init_plane(&frame
->planes
.plane6
.r
,
811 width
, stride
, height
, 0 * bytes
);
812 frame_init_plane(&frame
->planes
.plane6
.r_at_b
,
813 width
, stride
, height
, 1 * bytes
);
814 frame_init_plane(&frame
->planes
.plane6
.gr
,
815 width
, stride
, height
, 2 * bytes
);
816 frame_init_plane(&frame
->planes
.plane6
.gb
,
817 width
, stride
, height
, 3 * bytes
);
818 frame_init_plane(&frame
->planes
.plane6
.b
,
819 width
, stride
, height
, 4 * bytes
);
820 frame_init_plane(&frame
->planes
.plane6
.b_at_r
,
821 width
, stride
, height
, 5 * bytes
);
825 static enum ia_css_err
frame_allocate_buffer_data(struct ia_css_frame
*frame
)
828 IA_CSS_ENTER_LEAVE_PRIVATE("frame->data_bytes=%d\n", frame
->data_bytes
);
830 frame
->data
= mmgr_alloc_attr(frame
->data_bytes
,
832 MMGR_ATTRIBUTE_CONTIGUOUS
:
833 MMGR_ATTRIBUTE_DEFAULT
);
835 if (frame
->data
== mmgr_NULL
)
836 return IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY
;
837 return IA_CSS_SUCCESS
;
840 static enum ia_css_err
frame_allocate_with_data(struct ia_css_frame
**frame
,
843 enum ia_css_frame_format format
,
844 unsigned int padded_width
,
845 unsigned int raw_bit_depth
,
849 struct ia_css_frame
*me
= frame_create(width
,
858 return IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY
;
860 err
= ia_css_frame_init_planes(me
);
862 if (err
== IA_CSS_SUCCESS
)
863 err
= frame_allocate_buffer_data(me
);
865 if (err
!= IA_CSS_SUCCESS
) {
879 static struct ia_css_frame
*frame_create(unsigned int width
,
881 enum ia_css_frame_format format
,
882 unsigned int padded_width
,
883 unsigned int raw_bit_depth
,
887 struct ia_css_frame
*me
= sh_css_malloc(sizeof(*me
));
892 memset(me
, 0, sizeof(*me
));
893 me
->info
.res
.width
= width
;
894 me
->info
.res
.height
= height
;
895 me
->info
.format
= format
;
896 me
->info
.padded_width
= padded_width
;
897 me
->info
.raw_bit_depth
= raw_bit_depth
;
898 me
->contiguous
= contiguous
;
901 me
->data
= mmgr_NULL
;
902 /* To indicate it is not valid frame. */
903 me
->dynamic_queue_id
= (int)SH_CSS_INVALID_QUEUE_ID
;
904 me
->buf_type
= IA_CSS_BUFFER_TYPE_INVALID
;
910 ia_css_elems_bytes_from_info(const struct ia_css_frame_info
*info
)
912 if (info
->format
== IA_CSS_FRAME_FORMAT_RGB565
)
913 return 2; /* bytes per pixel */
914 if (info
->format
== IA_CSS_FRAME_FORMAT_YUV420_16
)
915 return 2; /* bytes per pixel */
916 if (info
->format
== IA_CSS_FRAME_FORMAT_YUV422_16
)
917 return 2; /* bytes per pixel */
918 /* Note: Essentially NV12_16 is a 2 bytes per pixel format, this return value is used
919 * to configure DMA for the output buffer,
920 * At least in SKC this data is overwriten by isp_output_init.sp.c except for elements(elems),
921 * which is configured from this return value,
922 * NV12_16 is implemented by a double buffer of 8 bit elements hence elems should be configured as 8 */
923 if (info
->format
== IA_CSS_FRAME_FORMAT_NV12_16
)
924 return 1; /* bytes per pixel */
926 if (info
->format
== IA_CSS_FRAME_FORMAT_RAW
927 || (info
->format
== IA_CSS_FRAME_FORMAT_RAW_PACKED
)) {
928 if (info
->raw_bit_depth
)
929 return CEIL_DIV(info
->raw_bit_depth
,8);
931 return 2; /* bytes per pixel */
933 if (info
->format
== IA_CSS_FRAME_FORMAT_PLANAR_RGB888
)
934 return 3; /* bytes per pixel */
935 if (info
->format
== IA_CSS_FRAME_FORMAT_RGBA888
)
936 return 4; /* bytes per pixel */
937 if (info
->format
== IA_CSS_FRAME_FORMAT_QPLANE6
)
938 return 2; /* bytes per pixel */
939 return 1; /* Default is 1 byte per pixel */
942 void ia_css_frame_info_to_frame_sp_info(
943 struct ia_css_frame_sp_info
*to
,
944 const struct ia_css_frame_info
*from
)
946 ia_css_resolution_to_sp_resolution(&to
->res
, &from
->res
);
947 to
->padded_width
= (uint16_t)from
->padded_width
;
948 to
->format
= (uint8_t)from
->format
;
949 to
->raw_bit_depth
= (uint8_t)from
->raw_bit_depth
;
950 to
->raw_bayer_order
= from
->raw_bayer_order
;
953 void ia_css_resolution_to_sp_resolution(
954 struct ia_css_sp_resolution
*to
,
955 const struct ia_css_resolution
*from
)
957 to
->width
= (uint16_t)from
->width
;
958 to
->height
= (uint16_t)from
->height
;
963 ia_css_frame_find_crop_resolution(const struct ia_css_resolution
*in_res
,
964 const struct ia_css_resolution
*out_res
,
965 struct ia_css_resolution
*crop_res
)
967 uint32_t wd_even_ceil
, ht_even_ceil
;
968 uint32_t in_ratio
, out_ratio
;
970 if ((in_res
== NULL
) || (out_res
== NULL
) || (crop_res
== NULL
))
971 return IA_CSS_ERR_INVALID_ARGUMENTS
;
973 IA_CSS_ENTER_PRIVATE("in(%ux%u) -> out(%ux%u)", in_res
->width
,
974 in_res
->height
, out_res
->width
, out_res
->height
);
976 if ((in_res
->width
== 0)
977 || (in_res
->height
== 0)
978 || (out_res
->width
== 0)
979 || (out_res
->height
== 0))
980 return IA_CSS_ERR_INVALID_ARGUMENTS
;
982 if ((out_res
->width
> in_res
->width
) ||
983 (out_res
->height
> in_res
->height
))
984 return IA_CSS_ERR_INVALID_ARGUMENTS
;
986 /* If aspect ratio (width/height) of out_res is higher than the aspect
987 * ratio of the in_res, then we crop vertically, otherwise we crop
990 in_ratio
= in_res
->width
* out_res
->height
;
991 out_ratio
= out_res
->width
* in_res
->height
;
993 if (in_ratio
== out_ratio
) {
994 crop_res
->width
= in_res
->width
;
995 crop_res
->height
= in_res
->height
;
996 } else if (out_ratio
> in_ratio
) {
997 crop_res
->width
= in_res
->width
;
998 crop_res
->height
= ROUND_DIV(out_res
->height
* crop_res
->width
,
1001 crop_res
->height
= in_res
->height
;
1002 crop_res
->width
= ROUND_DIV(out_res
->width
* crop_res
->height
,
1006 /* Round new (cropped) width and height to an even number.
1007 * binarydesc_calculate_bds_factor is such that we should consider as
1008 * much of the input as possible. This is different only when we end up
1009 * with an odd number in the last step. So, we take the next even number
1010 * if it falls within the input, otherwise take the previous even no.
1012 wd_even_ceil
= EVEN_CEIL(crop_res
->width
);
1013 ht_even_ceil
= EVEN_CEIL(crop_res
->height
);
1014 if ((wd_even_ceil
> in_res
->width
) || (ht_even_ceil
> in_res
->height
)) {
1015 crop_res
->width
= EVEN_FLOOR(crop_res
->width
);
1016 crop_res
->height
= EVEN_FLOOR(crop_res
->height
);
1018 crop_res
->width
= wd_even_ceil
;
1019 crop_res
->height
= ht_even_ceil
;
1022 IA_CSS_LEAVE_PRIVATE("in(%ux%u) -> out(%ux%u)", crop_res
->width
,
1023 crop_res
->height
, out_res
->width
, out_res
->height
);
1024 return IA_CSS_SUCCESS
;