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**************************************************************************/
32static 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
38static 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
44static 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
51static 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
56static 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
62static void frame_init_rgb_planes(struct ia_css_frame *frame,
63				  unsigned int bytes_per_element);
64
65static void frame_init_qplane6_planes(struct ia_css_frame *frame);
66
67static int frame_allocate_buffer_data(struct ia_css_frame *frame);
68
69static 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
76static 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
83static unsigned
84ia_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
91int 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
109int 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
140void 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
156int 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
164int 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
272unsigned 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
300void 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
321void 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
330void 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
349void 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
362int 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
389bool 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
399bool 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
423int 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
450static 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
462static 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
482static 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
501static 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
539static 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
572static 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
589static 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
613static 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
621static 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
654static 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
682static unsigned
683ia_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
715void 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
726void 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
734int 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