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