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