media: atomisp: Remove unused ia_css_frame_*() functions
[linux-block.git] / drivers / staging / media / atomisp / pci / runtime / frame / src / frame.c
1 // SPDX-License-Identifier: GPL-2.0
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
16 #include "hmm.h"
17
18 #include "ia_css_frame.h"
19 #include <math_support.h>
20 #include "assert_support.h"
21 #include "ia_css_debug.h"
22 #include "isp.h"
23 #include "sh_css_internal.h"
24 #include "atomisp_internal.h"
25
26 #define NV12_TILEY_TILE_WIDTH  128
27 #define NV12_TILEY_TILE_HEIGHT  32
28
29 /**************************************************************************
30 **      Static functions declarations
31 **************************************************************************/
32 static void frame_init_plane(struct ia_css_frame_plane *plane,
33                              unsigned int width,
34                              unsigned int stride,
35                              unsigned int height,
36                              unsigned int offset);
37
38 static void frame_init_single_plane(struct ia_css_frame *frame,
39                                     struct ia_css_frame_plane *plane,
40                                     unsigned int height,
41                                     unsigned int subpixels_per_line,
42                                     unsigned int bytes_per_pixel);
43
44 static void frame_init_raw_single_plane(
45     struct ia_css_frame *frame,
46     struct ia_css_frame_plane *plane,
47     unsigned int height,
48     unsigned int subpixels_per_line,
49     unsigned int bits_per_pixel);
50
51 static void frame_init_nv_planes(struct ia_css_frame *frame,
52                                  unsigned int horizontal_decimation,
53                                  unsigned int vertical_decimation,
54                                  unsigned int bytes_per_element);
55
56 static void frame_init_yuv_planes(struct ia_css_frame *frame,
57                                   unsigned int horizontal_decimation,
58                                   unsigned int vertical_decimation,
59                                   bool swap_uv,
60                                   unsigned int bytes_per_element);
61
62 static void frame_init_rgb_planes(struct ia_css_frame *frame,
63                                   unsigned int bytes_per_element);
64
65 static void frame_init_qplane6_planes(struct ia_css_frame *frame);
66
67 static int frame_allocate_buffer_data(struct ia_css_frame *frame);
68
69 static int frame_allocate_with_data(struct ia_css_frame **frame,
70         unsigned int width,
71         unsigned int height,
72         enum ia_css_frame_format format,
73         unsigned int padded_width,
74         unsigned int raw_bit_depth);
75
76 static struct ia_css_frame *frame_create(unsigned int width,
77         unsigned int height,
78         enum ia_css_frame_format format,
79         unsigned int padded_width,
80         unsigned int raw_bit_depth,
81         bool valid);
82
83 static unsigned
84 ia_css_elems_bytes_from_info(
85     const struct ia_css_frame_info *info);
86
87 /**************************************************************************
88 **      CSS API functions, exposed by ia_css.h
89 **************************************************************************/
90
91 int ia_css_frame_allocate_from_info(struct ia_css_frame **frame,
92         const struct ia_css_frame_info *info)
93 {
94         int err = 0;
95
96         if (!frame || !info)
97                 return -EINVAL;
98         ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
99                             "ia_css_frame_allocate_from_info() enter:\n");
100         err =
101             ia_css_frame_allocate(frame, info->res.width, info->res.height,
102                                   info->format, info->padded_width,
103                                   info->raw_bit_depth);
104         ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
105                             "ia_css_frame_allocate_from_info() leave:\n");
106         return err;
107 }
108
109 int ia_css_frame_allocate(struct ia_css_frame **frame,
110                                       unsigned int width,
111                                       unsigned int height,
112                                       enum ia_css_frame_format format,
113                                       unsigned int padded_width,
114                                       unsigned int raw_bit_depth)
115 {
116         int err = 0;
117
118         if (!frame || width == 0 || height == 0)
119                 return -EINVAL;
120
121         ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
122                             "ia_css_frame_allocate() enter: width=%d, height=%d, format=%d, padded_width=%d, raw_bit_depth=%d\n",
123                             width, height, format, padded_width, raw_bit_depth);
124
125         err = frame_allocate_with_data(frame, width, height, format,
126                                        padded_width, raw_bit_depth);
127
128         if ((*frame) && err == 0)
129                 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
130                                     "ia_css_frame_allocate() leave: frame=%p, data(DDR address)=0x%x\n", *frame,
131                                     (*frame)->data);
132         else
133                 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
134                                     "ia_css_frame_allocate() leave: frame=%p, data(DDR address)=0x%x\n",
135                                     (void *)-1, (unsigned int)-1);
136
137         return err;
138 }
139
140 void ia_css_frame_free(struct ia_css_frame *frame)
141 {
142         IA_CSS_ENTER_PRIVATE("frame = %p", frame);
143
144         if (frame) {
145                 hmm_free(frame->data);
146                 kvfree(frame);
147         }
148
149         IA_CSS_LEAVE_PRIVATE("void");
150 }
151
152 /**************************************************************************
153 **      Module public functions
154 **************************************************************************/
155
156 int ia_css_frame_check_info(const struct ia_css_frame_info *info)
157 {
158         assert(info);
159         if (info->res.width == 0 || info->res.height == 0)
160                 return -EINVAL;
161         return 0;
162 }
163
164 int ia_css_frame_init_planes(struct ia_css_frame *frame)
165 {
166         assert(frame);
167
168         switch (frame->frame_info.format) {
169         case IA_CSS_FRAME_FORMAT_MIPI:
170                 dev_err(atomisp_dev,
171                         "%s: unexpected use of IA_CSS_FRAME_FORMAT_MIPI\n", __func__);
172                 return -EINVAL;
173         case IA_CSS_FRAME_FORMAT_RAW_PACKED:
174                 frame_init_raw_single_plane(frame, &frame->planes.raw,
175                                             frame->frame_info.res.height,
176                                             frame->frame_info.padded_width,
177                                             frame->frame_info.raw_bit_depth);
178                 break;
179         case IA_CSS_FRAME_FORMAT_RAW:
180                 frame_init_single_plane(frame, &frame->planes.raw,
181                                         frame->frame_info.res.height,
182                                         frame->frame_info.padded_width,
183                                         frame->frame_info.raw_bit_depth <= 8 ? 1 : 2);
184                 break;
185         case IA_CSS_FRAME_FORMAT_RGB565:
186                 frame_init_single_plane(frame, &frame->planes.rgb,
187                                         frame->frame_info.res.height,
188                                         frame->frame_info.padded_width, 2);
189                 break;
190         case IA_CSS_FRAME_FORMAT_RGBA888:
191                 frame_init_single_plane(frame, &frame->planes.rgb,
192                                         frame->frame_info.res.height,
193                                         frame->frame_info.padded_width * 4, 1);
194                 break;
195         case IA_CSS_FRAME_FORMAT_PLANAR_RGB888:
196                 frame_init_rgb_planes(frame, 1);
197                 break;
198         /* yuyv and uyvu have the same frame layout, only the data
199          * positioning differs.
200          */
201         case IA_CSS_FRAME_FORMAT_YUYV:
202         case IA_CSS_FRAME_FORMAT_UYVY:
203         case IA_CSS_FRAME_FORMAT_CSI_MIPI_YUV420_8:
204         case IA_CSS_FRAME_FORMAT_CSI_MIPI_LEGACY_YUV420_8:
205                 frame_init_single_plane(frame, &frame->planes.yuyv,
206                                         frame->frame_info.res.height,
207                                         frame->frame_info.padded_width * 2, 1);
208                 break;
209         case IA_CSS_FRAME_FORMAT_YUV_LINE:
210                 /* Needs 3 extra lines to allow vf_pp prefetching */
211                 frame_init_single_plane(frame, &frame->planes.yuyv,
212                                         frame->frame_info.res.height * 3 / 2 + 3,
213                                         frame->frame_info.padded_width, 1);
214                 break;
215         case IA_CSS_FRAME_FORMAT_NV11:
216                 frame_init_nv_planes(frame, 4, 1, 1);
217                 break;
218         /* nv12 and nv21 have the same frame layout, only the data
219          * positioning differs.
220          */
221         case IA_CSS_FRAME_FORMAT_NV12:
222         case IA_CSS_FRAME_FORMAT_NV21:
223         case IA_CSS_FRAME_FORMAT_NV12_TILEY:
224                 frame_init_nv_planes(frame, 2, 2, 1);
225                 break;
226         case IA_CSS_FRAME_FORMAT_NV12_16:
227                 frame_init_nv_planes(frame, 2, 2, 2);
228                 break;
229         /* nv16 and nv61 have the same frame layout, only the data
230          * positioning differs.
231          */
232         case IA_CSS_FRAME_FORMAT_NV16:
233         case IA_CSS_FRAME_FORMAT_NV61:
234                 frame_init_nv_planes(frame, 2, 1, 1);
235                 break;
236         case IA_CSS_FRAME_FORMAT_YUV420:
237                 frame_init_yuv_planes(frame, 2, 2, false, 1);
238                 break;
239         case IA_CSS_FRAME_FORMAT_YUV422:
240                 frame_init_yuv_planes(frame, 2, 1, false, 1);
241                 break;
242         case IA_CSS_FRAME_FORMAT_YUV444:
243                 frame_init_yuv_planes(frame, 1, 1, false, 1);
244                 break;
245         case IA_CSS_FRAME_FORMAT_YUV420_16:
246                 frame_init_yuv_planes(frame, 2, 2, false, 2);
247                 break;
248         case IA_CSS_FRAME_FORMAT_YUV422_16:
249                 frame_init_yuv_planes(frame, 2, 1, false, 2);
250                 break;
251         case IA_CSS_FRAME_FORMAT_YV12:
252                 frame_init_yuv_planes(frame, 2, 2, true, 1);
253                 break;
254         case IA_CSS_FRAME_FORMAT_YV16:
255                 frame_init_yuv_planes(frame, 2, 1, true, 1);
256                 break;
257         case IA_CSS_FRAME_FORMAT_QPLANE6:
258                 frame_init_qplane6_planes(frame);
259                 break;
260         case IA_CSS_FRAME_FORMAT_BINARY_8:
261                 frame_init_single_plane(frame, &frame->planes.binary.data,
262                                         frame->frame_info.res.height,
263                                         frame->frame_info.padded_width, 1);
264                 frame->planes.binary.size = 0;
265                 break;
266         default:
267                 return -EINVAL;
268         }
269         return 0;
270 }
271
272 void ia_css_frame_info_set_width(struct ia_css_frame_info *info,
273                                  unsigned int width,
274                                  unsigned int min_padded_width)
275 {
276         unsigned int align;
277
278         IA_CSS_ENTER_PRIVATE("info = %p,width = %d, minimum padded width = %d",
279                              info, width, min_padded_width);
280         if (!info) {
281                 IA_CSS_ERROR("NULL input parameter");
282                 IA_CSS_LEAVE_PRIVATE("");
283                 return;
284         }
285         align = max(min_padded_width, width);
286
287         info->res.width = width;
288         /* frames with a U and V plane of 8 bits per pixel need to have
289            all planes aligned, this means double the alignment for the
290            Y plane if the horizontal decimation is 2. */
291         if (info->format == IA_CSS_FRAME_FORMAT_YUV420 ||
292             info->format == IA_CSS_FRAME_FORMAT_YV12 ||
293             info->format == IA_CSS_FRAME_FORMAT_NV12 ||
294             info->format == IA_CSS_FRAME_FORMAT_NV21 ||
295             info->format == IA_CSS_FRAME_FORMAT_BINARY_8 ||
296             info->format == IA_CSS_FRAME_FORMAT_YUV_LINE)
297                 info->padded_width =
298                     CEIL_MUL(align, 2 * HIVE_ISP_DDR_WORD_BYTES);
299         else if (info->format == IA_CSS_FRAME_FORMAT_NV12_TILEY)
300                 info->padded_width = CEIL_MUL(align, NV12_TILEY_TILE_WIDTH);
301         else if (info->format == IA_CSS_FRAME_FORMAT_RAW ||
302                  info->format == IA_CSS_FRAME_FORMAT_RAW_PACKED)
303                 info->padded_width = CEIL_MUL(align, 2 * ISP_VEC_NELEMS);
304         else {
305                 info->padded_width = CEIL_MUL(align, HIVE_ISP_DDR_WORD_BYTES);
306         }
307         IA_CSS_LEAVE_PRIVATE("");
308 }
309
310 void ia_css_frame_info_set_format(struct ia_css_frame_info *info,
311                                   enum ia_css_frame_format format)
312 {
313         assert(info);
314         ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
315                             "ia_css_frame_info_set_format() enter:\n");
316         info->format = format;
317 }
318
319 void ia_css_frame_info_init(struct ia_css_frame_info *info,
320                             unsigned int width,
321                             unsigned int height,
322                             enum ia_css_frame_format format,
323                             unsigned int aligned)
324 {
325         IA_CSS_ENTER_PRIVATE("info = %p, width = %d, height = %d, format = %d, aligned = %d",
326                              info, width, height, format, aligned);
327         if (!info) {
328                 IA_CSS_ERROR("NULL input parameter");
329                 IA_CSS_LEAVE_PRIVATE("");
330                 return;
331         }
332         info->res.height = height;
333         info->format     = format;
334         ia_css_frame_info_set_width(info, width, aligned);
335         IA_CSS_LEAVE_PRIVATE("");
336 }
337
338 void ia_css_frame_free_multiple(unsigned int num_frames,
339                                 struct ia_css_frame **frames_array)
340 {
341         unsigned int i;
342
343         for (i = 0; i < num_frames; i++) {
344                 if (frames_array[i]) {
345                         ia_css_frame_free(frames_array[i]);
346                         frames_array[i] = NULL;
347                 }
348         }
349 }
350
351 int ia_css_frame_allocate_with_buffer_size(struct ia_css_frame **frame,
352                                            const unsigned int buffer_size_bytes)
353 {
354         /* AM: Body coppied from frame_allocate_with_data(). */
355         int err;
356         struct ia_css_frame *me = frame_create(0, 0,
357                                                IA_CSS_FRAME_FORMAT_NUM,/* Not valid format yet */
358                                                0, 0, false);
359
360         if (!me)
361                 return -ENOMEM;
362
363         /* Get the data size */
364         me->data_bytes = buffer_size_bytes;
365
366         err = frame_allocate_buffer_data(me);
367
368         if (err) {
369                 kvfree(me);
370                 me = NULL;
371         }
372
373         *frame = me;
374
375         return err;
376 }
377
378 bool ia_css_frame_info_is_same_resolution(
379     const struct ia_css_frame_info *info_a,
380     const struct ia_css_frame_info *info_b)
381 {
382         if (!info_a || !info_b)
383                 return false;
384         return (info_a->res.width == info_b->res.width) &&
385                (info_a->res.height == info_b->res.height);
386 }
387
388 bool ia_css_frame_is_same_type(const struct ia_css_frame *frame_a,
389                                const struct ia_css_frame *frame_b)
390 {
391         bool is_equal = false;
392         const struct ia_css_frame_info *info_a = &frame_a->frame_info;
393         const struct ia_css_frame_info *info_b = &frame_b->frame_info;
394
395         ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
396                             "ia_css_frame_is_same_type() enter:\n");
397
398         if (!info_a || !info_b)
399                 return false;
400         if (info_a->format != info_b->format)
401                 return false;
402         if (info_a->padded_width != info_b->padded_width)
403                 return false;
404         is_equal = ia_css_frame_info_is_same_resolution(info_a, info_b);
405
406         ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
407                             "ia_css_frame_is_same_type() leave:\n");
408
409         return is_equal;
410 }
411
412 int ia_css_dma_configure_from_info(struct dma_port_config *config,
413                                    const struct ia_css_frame_info *info)
414 {
415         unsigned int is_raw_packed = info->format == IA_CSS_FRAME_FORMAT_RAW_PACKED;
416         unsigned int bits_per_pixel = is_raw_packed ? info->raw_bit_depth :
417                                       ia_css_elems_bytes_from_info(info) * 8;
418         unsigned int pix_per_ddrword = HIVE_ISP_DDR_WORD_BITS / bits_per_pixel;
419         unsigned int words_per_line = CEIL_DIV(info->padded_width, pix_per_ddrword);
420         unsigned int elems_b = pix_per_ddrword;
421
422         config->stride = HIVE_ISP_DDR_WORD_BYTES * words_per_line;
423         config->elems  = (uint8_t)elems_b;
424         config->width  = (uint16_t)info->res.width;
425         config->crop   = 0;
426
427         if (config->width > info->padded_width) {
428                 dev_err(atomisp_dev, "internal error: padded_width is too small!\n");
429                 return -EINVAL;
430         }
431
432         return 0;
433 }
434
435 /**************************************************************************
436 **      Static functions
437 **************************************************************************/
438
439 static void frame_init_plane(struct ia_css_frame_plane *plane,
440                              unsigned int width,
441                              unsigned int stride,
442                              unsigned int height,
443                              unsigned int offset)
444 {
445         plane->height = height;
446         plane->width = width;
447         plane->stride = stride;
448         plane->offset = offset;
449 }
450
451 static void frame_init_single_plane(struct ia_css_frame *frame,
452                                     struct ia_css_frame_plane *plane,
453                                     unsigned int height,
454                                     unsigned int subpixels_per_line,
455                                     unsigned int bytes_per_pixel)
456 {
457         unsigned int stride;
458
459         stride = subpixels_per_line * bytes_per_pixel;
460         /* Frame height needs to be even number - needed by hw ISYS2401
461            In case of odd number, round up to even.
462            Images won't be impacted by this round up,
463            only needed by jpeg/embedded data.
464            As long as buffer allocation and release are using data_bytes,
465            there won't be memory leak. */
466         frame->data_bytes = stride * CEIL_MUL2(height, 2);
467         frame_init_plane(plane, subpixels_per_line, stride, height, 0);
468         return;
469 }
470
471 static void frame_init_raw_single_plane(
472     struct ia_css_frame *frame,
473     struct ia_css_frame_plane *plane,
474     unsigned int height,
475     unsigned int subpixels_per_line,
476     unsigned int bits_per_pixel)
477 {
478         unsigned int stride;
479
480         assert(frame);
481
482         stride = HIVE_ISP_DDR_WORD_BYTES *
483                  CEIL_DIV(subpixels_per_line,
484                           HIVE_ISP_DDR_WORD_BITS / bits_per_pixel);
485         frame->data_bytes = stride * height;
486         frame_init_plane(plane, subpixels_per_line, stride, height, 0);
487         return;
488 }
489
490 static void frame_init_nv_planes(struct ia_css_frame *frame,
491                                  unsigned int horizontal_decimation,
492                                  unsigned int vertical_decimation,
493                                  unsigned int bytes_per_element)
494 {
495         unsigned int y_width = frame->frame_info.padded_width;
496         unsigned int y_height = frame->frame_info.res.height;
497         unsigned int uv_width;
498         unsigned int uv_height;
499         unsigned int y_bytes;
500         unsigned int uv_bytes;
501         unsigned int y_stride;
502         unsigned int uv_stride;
503
504         assert(horizontal_decimation != 0 && vertical_decimation != 0);
505
506         uv_width = 2 * (y_width / horizontal_decimation);
507         uv_height = y_height / vertical_decimation;
508
509         if (frame->frame_info.format == IA_CSS_FRAME_FORMAT_NV12_TILEY) {
510                 y_width   = CEIL_MUL(y_width,   NV12_TILEY_TILE_WIDTH);
511                 uv_width  = CEIL_MUL(uv_width,  NV12_TILEY_TILE_WIDTH);
512                 y_height  = CEIL_MUL(y_height,  NV12_TILEY_TILE_HEIGHT);
513                 uv_height = CEIL_MUL(uv_height, NV12_TILEY_TILE_HEIGHT);
514         }
515
516         y_stride = y_width * bytes_per_element;
517         uv_stride = uv_width * bytes_per_element;
518         y_bytes = y_stride * y_height;
519         uv_bytes = uv_stride * uv_height;
520
521         frame->data_bytes = y_bytes + uv_bytes;
522         frame_init_plane(&frame->planes.nv.y, y_width, y_stride, y_height, 0);
523         frame_init_plane(&frame->planes.nv.uv, uv_width,
524                          uv_stride, uv_height, y_bytes);
525         return;
526 }
527
528 static void frame_init_yuv_planes(struct ia_css_frame *frame,
529                                   unsigned int horizontal_decimation,
530                                   unsigned int vertical_decimation,
531                                   bool swap_uv,
532                                   unsigned int bytes_per_element)
533 {
534         unsigned int y_width = frame->frame_info.padded_width,
535                      y_height = frame->frame_info.res.height,
536                      uv_width = y_width / horizontal_decimation,
537                      uv_height = y_height / vertical_decimation,
538                      y_stride, y_bytes, uv_bytes, uv_stride;
539
540         y_stride = y_width * bytes_per_element;
541         uv_stride = uv_width * bytes_per_element;
542         y_bytes = y_stride * y_height;
543         uv_bytes = uv_stride * uv_height;
544
545         frame->data_bytes = y_bytes + 2 * uv_bytes;
546         frame_init_plane(&frame->planes.yuv.y, y_width, y_stride, y_height, 0);
547         if (swap_uv) {
548                 frame_init_plane(&frame->planes.yuv.v, uv_width, uv_stride,
549                                  uv_height, y_bytes);
550                 frame_init_plane(&frame->planes.yuv.u, uv_width, uv_stride,
551                                  uv_height, y_bytes + uv_bytes);
552         } else {
553                 frame_init_plane(&frame->planes.yuv.u, uv_width, uv_stride,
554                                  uv_height, y_bytes);
555                 frame_init_plane(&frame->planes.yuv.v, uv_width, uv_stride,
556                                  uv_height, y_bytes + uv_bytes);
557         }
558         return;
559 }
560
561 static void frame_init_rgb_planes(struct ia_css_frame *frame,
562                                   unsigned int bytes_per_element)
563 {
564         unsigned int width = frame->frame_info.res.width,
565                      height = frame->frame_info.res.height, stride, bytes;
566
567         stride = width * bytes_per_element;
568         bytes = stride * height;
569         frame->data_bytes = 3 * bytes;
570         frame_init_plane(&frame->planes.planar_rgb.r, width, stride, height, 0);
571         frame_init_plane(&frame->planes.planar_rgb.g,
572                          width, stride, height, 1 * bytes);
573         frame_init_plane(&frame->planes.planar_rgb.b,
574                          width, stride, height, 2 * bytes);
575         return;
576 }
577
578 static void frame_init_qplane6_planes(struct ia_css_frame *frame)
579 {
580         unsigned int width = frame->frame_info.padded_width / 2,
581                      height = frame->frame_info.res.height / 2, bytes, stride;
582
583         stride = width * 2;
584         bytes = stride * height;
585
586         frame->data_bytes = 6 * bytes;
587         frame_init_plane(&frame->planes.plane6.r,
588                          width, stride, height, 0 * bytes);
589         frame_init_plane(&frame->planes.plane6.r_at_b,
590                          width, stride, height, 1 * bytes);
591         frame_init_plane(&frame->planes.plane6.gr,
592                          width, stride, height, 2 * bytes);
593         frame_init_plane(&frame->planes.plane6.gb,
594                          width, stride, height, 3 * bytes);
595         frame_init_plane(&frame->planes.plane6.b,
596                          width, stride, height, 4 * bytes);
597         frame_init_plane(&frame->planes.plane6.b_at_r,
598                          width, stride, height, 5 * bytes);
599         return;
600 }
601
602 static int frame_allocate_buffer_data(struct ia_css_frame *frame)
603 {
604 #ifdef ISP2401
605         IA_CSS_ENTER_LEAVE_PRIVATE("frame->data_bytes=%d\n", frame->data_bytes);
606 #endif
607         frame->data = hmm_alloc(frame->data_bytes);
608         if (frame->data == mmgr_NULL)
609                 return -ENOMEM;
610         return 0;
611 }
612
613 static int frame_allocate_with_data(struct ia_css_frame **frame,
614         unsigned int width,
615         unsigned int height,
616         enum ia_css_frame_format format,
617         unsigned int padded_width,
618         unsigned int raw_bit_depth)
619 {
620         int err;
621         struct ia_css_frame *me = frame_create(width,
622                                                height,
623                                                format,
624                                                padded_width,
625                                                raw_bit_depth,
626                                                true);
627
628         if (!me)
629                 return -ENOMEM;
630
631         err = ia_css_frame_init_planes(me);
632
633         if (!err)
634                 err = frame_allocate_buffer_data(me);
635
636         if (err) {
637                 kvfree(me);
638 #ifndef ISP2401
639                 return err;
640 #else
641                 me = NULL;
642 #endif
643         }
644
645         *frame = me;
646
647         return err;
648 }
649
650 static struct ia_css_frame *frame_create(unsigned int width,
651         unsigned int height,
652         enum ia_css_frame_format format,
653         unsigned int padded_width,
654         unsigned int raw_bit_depth,
655         bool valid)
656 {
657         struct ia_css_frame *me = kvmalloc(sizeof(*me), GFP_KERNEL);
658
659         if (!me)
660                 return NULL;
661
662         memset(me, 0, sizeof(*me));
663         me->frame_info.res.width = width;
664         me->frame_info.res.height = height;
665         me->frame_info.format = format;
666         me->frame_info.padded_width = padded_width;
667         me->frame_info.raw_bit_depth = raw_bit_depth;
668         me->valid = valid;
669         me->data_bytes = 0;
670         me->data = mmgr_NULL;
671         /* To indicate it is not valid frame. */
672         me->dynamic_queue_id = (int)SH_CSS_INVALID_QUEUE_ID;
673         me->buf_type = IA_CSS_BUFFER_TYPE_INVALID;
674
675         return me;
676 }
677
678 static unsigned
679 ia_css_elems_bytes_from_info(const struct ia_css_frame_info *info)
680 {
681         if (info->format == IA_CSS_FRAME_FORMAT_RGB565)
682                 return 2; /* bytes per pixel */
683         if (info->format == IA_CSS_FRAME_FORMAT_YUV420_16)
684                 return 2; /* bytes per pixel */
685         if (info->format == IA_CSS_FRAME_FORMAT_YUV422_16)
686                 return 2; /* bytes per pixel */
687         /* Note: Essentially NV12_16 is a 2 bytes per pixel format, this return value is used
688          * to configure DMA for the output buffer,
689          * At least in SKC this data is overwritten by isp_output_init.sp.c except for elements(elems),
690          * which is configured from this return value,
691          * NV12_16 is implemented by a double buffer of 8 bit elements hence elems should be configured as 8 */
692         if (info->format == IA_CSS_FRAME_FORMAT_NV12_16)
693                 return 1; /* bytes per pixel */
694
695         if (info->format == IA_CSS_FRAME_FORMAT_RAW
696             || (info->format == IA_CSS_FRAME_FORMAT_RAW_PACKED)) {
697                 if (info->raw_bit_depth)
698                         return CEIL_DIV(info->raw_bit_depth, 8);
699                 else
700                         return 2; /* bytes per pixel */
701         }
702         if (info->format == IA_CSS_FRAME_FORMAT_PLANAR_RGB888)
703                 return 3; /* bytes per pixel */
704         if (info->format == IA_CSS_FRAME_FORMAT_RGBA888)
705                 return 4; /* bytes per pixel */
706         if (info->format == IA_CSS_FRAME_FORMAT_QPLANE6)
707                 return 2; /* bytes per pixel */
708         return 1; /* Default is 1 byte per pixel */
709 }
710
711 void ia_css_frame_info_to_frame_sp_info(
712     struct ia_css_frame_sp_info *to,
713     const struct ia_css_frame_info *from)
714 {
715         ia_css_resolution_to_sp_resolution(&to->res, &from->res);
716         to->padded_width = (uint16_t)from->padded_width;
717         to->format = (uint8_t)from->format;
718         to->raw_bit_depth = (uint8_t)from->raw_bit_depth;
719         to->raw_bayer_order = from->raw_bayer_order;
720 }
721
722 void ia_css_resolution_to_sp_resolution(
723     struct ia_css_sp_resolution *to,
724     const struct ia_css_resolution *from)
725 {
726         to->width  = (uint16_t)from->width;
727         to->height = (uint16_t)from->height;
728 }
729
730 int ia_css_frame_init_from_info(struct ia_css_frame *frame,
731                                 const struct ia_css_frame_info *frame_info)
732 {
733         frame->frame_info.res.width = frame_info->res.width;
734         frame->frame_info.res.height = frame_info->res.height;
735         frame->frame_info.format = frame_info->format;
736         frame->frame_info.padded_width = frame_info->padded_width;
737         frame->frame_info.raw_bit_depth = frame_info->raw_bit_depth;
738         frame->valid = true;
739         /* To indicate it is not valid frame. */
740         frame->dynamic_queue_id = SH_CSS_INVALID_QUEUE_ID;
741         frame->buf_type = IA_CSS_BUFFER_TYPE_INVALID;
742
743         return ia_css_frame_init_planes(frame);
744 }