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