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