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