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