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