Merge branch 'x86-pti-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
[sfrench/cifs-2.6.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