]> git.proxmox.com Git - mirror_ubuntu-focal-kernel.git/blob - drivers/staging/media/atomisp/pci/atomisp2/css2400/runtime/frame/src/frame.c
ASoC: tlv320aic31xx: Reset registers during power up
[mirror_ubuntu-focal-kernel.git] / drivers / staging / media / atomisp / pci / atomisp2 / css2400 / runtime / frame / src / frame.c
1 #ifndef ISP2401
2 /*
3 * Support for Intel Camera Imaging ISP subsystem.
4 * Copyright (c) 2015, Intel Corporation.
5 *
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.
9 *
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
13 * more details.
14 */
15 #else
16 /**
17 Support for Intel Camera Imaging ISP subsystem.
18 Copyright (c) 2010 - 2015, Intel Corporation.
19
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.
23
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
27 more details.
28 */
29 #endif
30
31 #include "ia_css_frame.h"
32 #include <math_support.h>
33 #include "assert_support.h"
34 #include "ia_css_debug.h"
35 #include "isp.h"
36 #include "sh_css_internal.h"
37 #include "memory_access.h"
38
39
40 #define NV12_TILEY_TILE_WIDTH 128
41 #define NV12_TILEY_TILE_HEIGHT 32
42
43 /**************************************************************************
44 ** Static functions declarations
45 **************************************************************************/
46 static void frame_init_plane(struct ia_css_frame_plane *plane,
47 unsigned int width,
48 unsigned int stride,
49 unsigned int height,
50 unsigned int offset);
51
52 static void frame_init_single_plane(struct ia_css_frame *frame,
53 struct ia_css_frame_plane *plane,
54 unsigned int height,
55 unsigned int subpixels_per_line,
56 unsigned int bytes_per_pixel);
57
58 static void frame_init_raw_single_plane(
59 struct ia_css_frame *frame,
60 struct ia_css_frame_plane *plane,
61 unsigned int height,
62 unsigned int subpixels_per_line,
63 unsigned int bits_per_pixel);
64
65 static void frame_init_mipi_plane(struct ia_css_frame *frame,
66 struct ia_css_frame_plane *plane,
67 unsigned int height,
68 unsigned int subpixels_per_line,
69 unsigned int bytes_per_pixel);
70
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);
75
76 static void frame_init_yuv_planes(struct ia_css_frame *frame,
77 unsigned int horizontal_decimation,
78 unsigned int vertical_decimation,
79 bool swap_uv,
80 unsigned int bytes_per_element);
81
82 static void frame_init_rgb_planes(struct ia_css_frame *frame,
83 unsigned int bytes_per_element);
84
85 static void frame_init_qplane6_planes(struct ia_css_frame *frame);
86
87 static enum ia_css_err frame_allocate_buffer_data(struct ia_css_frame *frame);
88
89 static enum ia_css_err frame_allocate_with_data(struct ia_css_frame **frame,
90 unsigned int width,
91 unsigned int height,
92 enum ia_css_frame_format format,
93 unsigned int padded_width,
94 unsigned int raw_bit_depth,
95 bool contiguous);
96
97 static struct ia_css_frame *frame_create(unsigned int width,
98 unsigned int height,
99 enum ia_css_frame_format format,
100 unsigned int padded_width,
101 unsigned int raw_bit_depth,
102 bool contiguous,
103 bool valid);
104
105 static unsigned
106 ia_css_elems_bytes_from_info(
107 const struct ia_css_frame_info *info);
108
109 /**************************************************************************
110 ** CSS API functions, exposed by ia_css.h
111 **************************************************************************/
112
113 void ia_css_frame_zero(struct ia_css_frame *frame)
114 {
115 assert(frame != NULL);
116 mmgr_clear(frame->data, frame->data_bytes);
117 }
118
119 enum ia_css_err ia_css_frame_allocate_from_info(struct ia_css_frame **frame,
120 const struct ia_css_frame_info *info)
121 {
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");
127 err =
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");
133 return err;
134 }
135
136 enum ia_css_err ia_css_frame_allocate(struct ia_css_frame **frame,
137 unsigned int width,
138 unsigned int height,
139 enum ia_css_frame_format format,
140 unsigned int padded_width,
141 unsigned int raw_bit_depth)
142 {
143 enum ia_css_err err = IA_CSS_SUCCESS;
144
145 if (frame == NULL || width == 0 || height == 0)
146 return IA_CSS_ERR_INVALID_ARGUMENTS;
147
148 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
149 #ifndef ISP2401
150 "ia_css_frame_allocate() enter: width=%d, height=%d, format=%d\n",
151 width, height, format);
152 #else
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);
155 #endif
156
157 err = frame_allocate_with_data(frame, width, height, format,
158 padded_width, raw_bit_depth, false);
159
160 #ifndef ISP2401
161 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
162 "ia_css_frame_allocate() leave: frame=%p\n", *frame);
163 #else
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);
167 else
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);
171 #endif
172
173 return err;
174 }
175
176 enum ia_css_err ia_css_frame_map(struct ia_css_frame **frame,
177 const struct ia_css_frame_info *info,
178 const void *data,
179 uint16_t attribute,
180 void *context)
181 {
182 enum ia_css_err err = IA_CSS_SUCCESS;
183 struct ia_css_frame *me;
184 assert(frame != NULL);
185
186 /* Create the frame structure */
187 err = ia_css_frame_create_from_info(&me, info);
188
189 if (err != IA_CSS_SUCCESS)
190 return err;
191
192 if (err == IA_CSS_SUCCESS) {
193 /* use mmgr_mmap to map */
194 me->data = (ia_css_ptr) mmgr_mmap(data,
195 me->data_bytes,
196 attribute, context);
197 if (me->data == mmgr_NULL)
198 err = IA_CSS_ERR_INVALID_ARGUMENTS;
199 };
200
201 if (err != IA_CSS_SUCCESS) {
202 sh_css_free(me);
203 #ifndef ISP2401
204 return err;
205 #else
206 me = NULL;
207 #endif
208 }
209
210 *frame = me;
211
212 return err;
213 }
214
215 enum ia_css_err ia_css_frame_create_from_info(struct ia_css_frame **frame,
216 const struct ia_css_frame_info *info)
217 {
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;
227 }
228
229 me = frame_create(info->res.width,
230 info->res.height,
231 info->format,
232 info->padded_width,
233 info->raw_bit_depth,
234 false,
235 false);
236 if (me == NULL) {
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;
241 }
242
243 err = ia_css_frame_init_planes(me);
244
245 #ifndef ISP2401
246 if (err == IA_CSS_SUCCESS)
247 *frame = me;
248 else
249 #else
250 if (err != IA_CSS_SUCCESS) {
251 #endif
252 sh_css_free(me);
253 #ifdef ISP2401
254 me = NULL;
255 }
256
257 *frame = me;
258 #endif
259
260 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_frame_create_from_info() leave:\n");
261
262 return err;
263 }
264
265 enum ia_css_err ia_css_frame_set_data(struct ia_css_frame *frame,
266 const ia_css_ptr mapped_data,
267 size_t data_bytes)
268 {
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");
272 if (frame == NULL) {
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;
276 }
277
278 /* If we are setting a valid data.
279 * Make sure that there is enough
280 * room for the expected frame format
281 */
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;
286 }
287
288 frame->data = mapped_data;
289
290 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_frame_set_data() leave:\n");
291
292 return err;
293 }
294
295 enum ia_css_err ia_css_frame_allocate_contiguous(struct ia_css_frame **frame,
296 unsigned int width,
297 unsigned int height,
298 enum ia_css_frame_format format,
299 unsigned int padded_width,
300 unsigned int raw_bit_depth)
301 {
302 enum ia_css_err err = IA_CSS_SUCCESS;
303
304 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
305 "ia_css_frame_allocate_contiguous() "
306 #ifndef ISP2401
307 "enter: width=%d, height=%d, format=%d\n",
308 width, height, format);
309 #else
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);
312 #endif
313
314 err = frame_allocate_with_data(frame, width, height, format,
315 padded_width, raw_bit_depth, true);
316
317 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
318 "ia_css_frame_allocate_contiguous() leave: frame=%p\n",
319 frame ? *frame : (void *)-1);
320
321 return err;
322 }
323
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)
327 {
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,
333 info->res.width,
334 info->res.height,
335 info->format,
336 info->padded_width,
337 info->raw_bit_depth);
338 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
339 "ia_css_frame_allocate_contiguous_from_info() leave:\n");
340 return err;
341 }
342
343 void ia_css_frame_free(struct ia_css_frame *frame)
344 {
345 IA_CSS_ENTER_PRIVATE("frame = %p", frame);
346
347 if (frame != NULL) {
348 hmm_free(frame->data);
349 sh_css_free(frame);
350 }
351
352 IA_CSS_LEAVE_PRIVATE("void");
353 }
354
355 /**************************************************************************
356 ** Module public functions
357 **************************************************************************/
358
359 enum ia_css_err ia_css_frame_check_info(const struct ia_css_frame_info *info)
360 {
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;
365 }
366
367 enum ia_css_err ia_css_frame_init_planes(struct ia_css_frame *frame)
368 {
369 assert(frame != NULL);
370
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);
377 break;
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);
383 break;
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);
389 break;
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);
394 break;
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);
399 break;
400 case IA_CSS_FRAME_FORMAT_PLANAR_RGB888:
401 frame_init_rgb_planes(frame, 1);
402 break;
403 /* yuyv and uyvu have the same frame layout, only the data
404 * positioning differs.
405 */
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);
413 break;
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);
419 break;
420 case IA_CSS_FRAME_FORMAT_NV11:
421 frame_init_nv_planes(frame, 4, 1, 1);
422 break;
423 /* nv12 and nv21 have the same frame layout, only the data
424 * positioning differs.
425 */
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);
430 break;
431 case IA_CSS_FRAME_FORMAT_NV12_16:
432 frame_init_nv_planes(frame, 2, 2, 2);
433 break;
434 /* nv16 and nv61 have the same frame layout, only the data
435 * positioning differs.
436 */
437 case IA_CSS_FRAME_FORMAT_NV16:
438 case IA_CSS_FRAME_FORMAT_NV61:
439 frame_init_nv_planes(frame, 2, 1, 1);
440 break;
441 case IA_CSS_FRAME_FORMAT_YUV420:
442 frame_init_yuv_planes(frame, 2, 2, false, 1);
443 break;
444 case IA_CSS_FRAME_FORMAT_YUV422:
445 frame_init_yuv_planes(frame, 2, 1, false, 1);
446 break;
447 case IA_CSS_FRAME_FORMAT_YUV444:
448 frame_init_yuv_planes(frame, 1, 1, false, 1);
449 break;
450 case IA_CSS_FRAME_FORMAT_YUV420_16:
451 frame_init_yuv_planes(frame, 2, 2, false, 2);
452 break;
453 case IA_CSS_FRAME_FORMAT_YUV422_16:
454 frame_init_yuv_planes(frame, 2, 1, false, 2);
455 break;
456 case IA_CSS_FRAME_FORMAT_YV12:
457 frame_init_yuv_planes(frame, 2, 2, true, 1);
458 break;
459 case IA_CSS_FRAME_FORMAT_YV16:
460 frame_init_yuv_planes(frame, 2, 1, true, 1);
461 break;
462 case IA_CSS_FRAME_FORMAT_QPLANE6:
463 frame_init_qplane6_planes(frame);
464 break;
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;
470 break;
471 default:
472 return IA_CSS_ERR_INVALID_ARGUMENTS;
473 }
474 return IA_CSS_SUCCESS;
475 }
476
477 void ia_css_frame_info_set_width(struct ia_css_frame_info *info,
478 unsigned int width,
479 unsigned int min_padded_width)
480 {
481 unsigned int align;
482
483 IA_CSS_ENTER_PRIVATE("info = %p,width = %d, minimum padded width = %d",
484 info, width, min_padded_width);
485 if (info == NULL) {
486 IA_CSS_ERROR("NULL input parameter");
487 IA_CSS_LEAVE_PRIVATE("");
488 return;
489 }
490 if (min_padded_width > width)
491 align = min_padded_width;
492 else
493 align = width;
494
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)
505 info->padded_width =
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);
512 else {
513 info->padded_width = CEIL_MUL(align, HIVE_ISP_DDR_WORD_BYTES);
514 }
515 IA_CSS_LEAVE_PRIVATE("");
516 }
517
518 void ia_css_frame_info_set_format(struct ia_css_frame_info *info,
519 enum ia_css_frame_format format)
520 {
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;
525 }
526
527 void ia_css_frame_info_init(struct ia_css_frame_info *info,
528 unsigned int width,
529 unsigned int height,
530 enum ia_css_frame_format format,
531 unsigned int aligned)
532 {
533 IA_CSS_ENTER_PRIVATE("info = %p, width = %d, height = %d, format = %d, aligned = %d",
534 info, width, height, format, aligned);
535 if (info == NULL) {
536 IA_CSS_ERROR("NULL input parameter");
537 IA_CSS_LEAVE_PRIVATE("");
538 return;
539 }
540 info->res.height = height;
541 info->format = format;
542 ia_css_frame_info_set_width(info, width, aligned);
543 IA_CSS_LEAVE_PRIVATE("");
544 }
545
546 void ia_css_frame_free_multiple(unsigned int num_frames,
547 struct ia_css_frame **frames_array)
548 {
549 unsigned int i;
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;
554 }
555 }
556 }
557
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)
562 {
563 /* AM: Body coppied from frame_allocate_with_data(). */
564 enum ia_css_err err;
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);
568
569 if (me == NULL)
570 return IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
571
572 /* Get the data size */
573 me->data_bytes = buffer_size_bytes;
574
575 err = frame_allocate_buffer_data(me);
576
577 if (err != IA_CSS_SUCCESS) {
578 sh_css_free(me);
579 #ifndef ISP2401
580 return err;
581 #else
582 me = NULL;
583 #endif
584 }
585
586 *frame = me;
587
588 return err;
589 }
590
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)
594 {
595 if (!info_a || !info_b)
596 return false;
597 return (info_a->res.width == info_b->res.width) &&
598 (info_a->res.height == info_b->res.height);
599 }
600
601 bool ia_css_frame_is_same_type(const struct ia_css_frame *frame_a,
602 const struct ia_css_frame *frame_b)
603 {
604 bool is_equal = false;
605 const struct ia_css_frame_info *info_a = &frame_a->info,
606 *info_b = &frame_b->info;
607
608 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
609 "ia_css_frame_is_same_type() enter:\n");
610
611 if (!info_a || !info_b)
612 return false;
613 if (info_a->format != info_b->format)
614 return false;
615 if (info_a->padded_width != info_b->padded_width)
616 return false;
617 is_equal = ia_css_frame_info_is_same_resolution(info_a, info_b);
618
619 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
620 "ia_css_frame_is_same_type() leave:\n");
621
622 return is_equal;
623 }
624
625 void
626 ia_css_dma_configure_from_info(
627 struct dma_port_config *config,
628 const struct ia_css_frame_info *info)
629 {
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;
635
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;
639 config->crop = 0;
640 assert(config->width <= info->padded_width);
641 }
642
643 /**************************************************************************
644 ** Static functions
645 **************************************************************************/
646
647 static void frame_init_plane(struct ia_css_frame_plane *plane,
648 unsigned int width,
649 unsigned int stride,
650 unsigned int height,
651 unsigned int offset)
652 {
653 plane->height = height;
654 plane->width = width;
655 plane->stride = stride;
656 plane->offset = offset;
657 }
658
659 static void frame_init_single_plane(struct ia_css_frame *frame,
660 struct ia_css_frame_plane *plane,
661 unsigned int height,
662 unsigned int subpixels_per_line,
663 unsigned int bytes_per_pixel)
664 {
665 unsigned int stride;
666
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);
676 return;
677 }
678
679 static void frame_init_raw_single_plane(
680 struct ia_css_frame *frame,
681 struct ia_css_frame_plane *plane,
682 unsigned int height,
683 unsigned int subpixels_per_line,
684 unsigned int bits_per_pixel)
685 {
686 unsigned int stride;
687 assert(frame != NULL);
688
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);
694 return;
695 }
696
697 static void frame_init_mipi_plane(struct ia_css_frame *frame,
698 struct ia_css_frame_plane *plane,
699 unsigned int height,
700 unsigned int subpixels_per_line,
701 unsigned int bytes_per_pixel)
702 {
703 unsigned int stride;
704
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);
710 return;
711 }
712
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)
717 {
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;
726
727 assert(horizontal_decimation != 0 && vertical_decimation != 0);
728
729 uv_width = 2 * (y_width / horizontal_decimation);
730 uv_height = y_height / vertical_decimation;
731
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);
737 }
738
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;
743
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);
748 return;
749 }
750
751 static void frame_init_yuv_planes(struct ia_css_frame *frame,
752 unsigned int horizontal_decimation,
753 unsigned int vertical_decimation,
754 bool swap_uv,
755 unsigned int bytes_per_element)
756 {
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;
762
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;
767
768 frame->data_bytes = y_bytes + 2 * uv_bytes;
769 frame_init_plane(&frame->planes.yuv.y, y_width, y_stride, y_height, 0);
770 if (swap_uv) {
771 frame_init_plane(&frame->planes.yuv.v, uv_width, uv_stride,
772 uv_height, y_bytes);
773 frame_init_plane(&frame->planes.yuv.u, uv_width, uv_stride,
774 uv_height, y_bytes + uv_bytes);
775 } else {
776 frame_init_plane(&frame->planes.yuv.u, uv_width, uv_stride,
777 uv_height, y_bytes);
778 frame_init_plane(&frame->planes.yuv.v, uv_width, uv_stride,
779 uv_height, y_bytes + uv_bytes);
780 }
781 return;
782 }
783
784 static void frame_init_rgb_planes(struct ia_css_frame *frame,
785 unsigned int bytes_per_element)
786 {
787 unsigned int width = frame->info.res.width,
788 height = frame->info.res.height, stride, bytes;
789
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);
798 return;
799 }
800
801 static void frame_init_qplane6_planes(struct ia_css_frame *frame)
802 {
803 unsigned int width = frame->info.padded_width / 2,
804 height = frame->info.res.height / 2, bytes, stride;
805
806 stride = width * 2;
807 bytes = stride * height;
808
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);
822 return;
823 }
824
825 static enum ia_css_err frame_allocate_buffer_data(struct ia_css_frame *frame)
826 {
827 #ifdef ISP2401
828 IA_CSS_ENTER_LEAVE_PRIVATE("frame->data_bytes=%d\n", frame->data_bytes);
829 #endif
830 frame->data = mmgr_alloc_attr(frame->data_bytes,
831 frame->contiguous ?
832 MMGR_ATTRIBUTE_CONTIGUOUS :
833 MMGR_ATTRIBUTE_DEFAULT);
834
835 if (frame->data == mmgr_NULL)
836 return IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
837 return IA_CSS_SUCCESS;
838 }
839
840 static enum ia_css_err frame_allocate_with_data(struct ia_css_frame **frame,
841 unsigned int width,
842 unsigned int height,
843 enum ia_css_frame_format format,
844 unsigned int padded_width,
845 unsigned int raw_bit_depth,
846 bool contiguous)
847 {
848 enum ia_css_err err;
849 struct ia_css_frame *me = frame_create(width,
850 height,
851 format,
852 padded_width,
853 raw_bit_depth,
854 contiguous,
855 true);
856
857 if (me == NULL)
858 return IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
859
860 err = ia_css_frame_init_planes(me);
861
862 if (err == IA_CSS_SUCCESS)
863 err = frame_allocate_buffer_data(me);
864
865 if (err != IA_CSS_SUCCESS) {
866 sh_css_free(me);
867 #ifndef ISP2401
868 return err;
869 #else
870 me = NULL;
871 #endif
872 }
873
874 *frame = me;
875
876 return err;
877 }
878
879 static struct ia_css_frame *frame_create(unsigned int width,
880 unsigned int height,
881 enum ia_css_frame_format format,
882 unsigned int padded_width,
883 unsigned int raw_bit_depth,
884 bool contiguous,
885 bool valid)
886 {
887 struct ia_css_frame *me = sh_css_malloc(sizeof(*me));
888
889 if (me == NULL)
890 return NULL;
891
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;
899 me->valid = valid;
900 me->data_bytes = 0;
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;
905
906 return me;
907 }
908
909 static unsigned
910 ia_css_elems_bytes_from_info(const struct ia_css_frame_info *info)
911 {
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 */
925
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);
930 else
931 return 2; /* bytes per pixel */
932 }
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 */
940 }
941
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)
945 {
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;
951 }
952
953 void ia_css_resolution_to_sp_resolution(
954 struct ia_css_sp_resolution *to,
955 const struct ia_css_resolution *from)
956 {
957 to->width = (uint16_t)from->width;
958 to->height = (uint16_t)from->height;
959 }
960 #ifdef ISP2401
961
962 enum ia_css_err
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)
966 {
967 uint32_t wd_even_ceil, ht_even_ceil;
968 uint32_t in_ratio, out_ratio;
969
970 if ((in_res == NULL) || (out_res == NULL) || (crop_res == NULL))
971 return IA_CSS_ERR_INVALID_ARGUMENTS;
972
973 IA_CSS_ENTER_PRIVATE("in(%ux%u) -> out(%ux%u)", in_res->width,
974 in_res->height, out_res->width, out_res->height);
975
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;
981
982 if ((out_res->width > in_res->width) ||
983 (out_res->height > in_res->height))
984 return IA_CSS_ERR_INVALID_ARGUMENTS;
985
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
988 * horizontally.
989 */
990 in_ratio = in_res->width * out_res->height;
991 out_ratio = out_res->width * in_res->height;
992
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,
999 out_res->width);
1000 } else {
1001 crop_res->height = in_res->height;
1002 crop_res->width = ROUND_DIV(out_res->width * crop_res->height,
1003 out_res->height);
1004 }
1005
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.
1011 */
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);
1017 } else {
1018 crop_res->width = wd_even_ceil;
1019 crop_res->height = ht_even_ceil;
1020 }
1021
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;
1025 }
1026 #endif