// SPDX-License-Identifier: GPL-2.0
/*
Support for Intel Camera Imaging ISP subsystem.
Copyright (c) 2010 - 2015, Intel Corporation.

This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
version 2, as published by the Free Software Foundation.

This program is distributed in the hope it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
more details.
*/

#include "ia_css_yuv444_io.host.h"
#include "dma.h"
#include "math_support.h"
#ifndef IA_CSS_NO_DEBUG
#include "ia_css_debug.h"
#endif
#include "ia_css_isp_params.h"
#include "ia_css_frame.h"

int ia_css_yuv444_io_config(const struct ia_css_binary      *binary,
			    const struct sh_css_binary_args *args)
{
	const struct ia_css_frame *in_frame = args->in_frame;
	const struct ia_css_frame **out_frames = (const struct ia_css_frame **)
		&args->out_frame;
	const struct ia_css_frame_info *in_frame_info = (in_frame) ? &in_frame->info :
		&binary->in_frame_info;

	const unsigned int ddr_bits_per_element = sizeof(short) * 8;
	const unsigned int ddr_elems_per_word = ceil_div(HIVE_ISP_DDR_WORD_BITS,
						ddr_bits_per_element);
	unsigned int size_get = 0, size_put = 0;
	unsigned int offset = 0;
	int ret;

	if (binary->info->mem_offsets.offsets.param) {
		size_get = binary->info->mem_offsets.offsets.param->dmem.get.size;
		offset = binary->info->mem_offsets.offsets.param->dmem.get.offset;
	}

	if (size_get) {
		struct ia_css_common_io_config *to = (struct ia_css_common_io_config *)
						     &binary->mem_params.params[IA_CSS_PARAM_CLASS_PARAM][IA_CSS_ISP_DMEM].address[offset];
		struct dma_port_config config;
#ifndef IA_CSS_NO_DEBUG
		ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
				    "ia_css_yuv444_io_config() get part enter:\n");
#endif

		ret = ia_css_dma_configure_from_info(&config, in_frame_info);
		if (ret)
			return ret;

		// The base_address of the input frame will be set in the ISP
		to->width = in_frame_info->res.width;
		to->height = in_frame_info->res.height;
		to->stride = config.stride;
		to->ddr_elems_per_word = ddr_elems_per_word;
#ifndef IA_CSS_NO_DEBUG
		ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
				    "ia_css_yuv444_io_config() get part leave:\n");
#endif
	}

	if (binary->info->mem_offsets.offsets.param) {
		size_put = binary->info->mem_offsets.offsets.param->dmem.put.size;
		offset = binary->info->mem_offsets.offsets.param->dmem.put.offset;
	}

	if (size_put) {
		struct ia_css_common_io_config *to = (struct ia_css_common_io_config *)
						     &binary->mem_params.params[IA_CSS_PARAM_CLASS_PARAM][IA_CSS_ISP_DMEM].address[offset];
		struct dma_port_config config;
#ifndef IA_CSS_NO_DEBUG
		ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
				    "ia_css_yuv444_io_config() put part enter:\n");
#endif

		ret = ia_css_dma_configure_from_info(&config, &out_frames[0]->info);
		if (ret)
			return ret;

		to->base_address = out_frames[0]->data;
		to->width = out_frames[0]->info.res.width;
		to->height = out_frames[0]->info.res.height;
		to->stride = config.stride;
		to->ddr_elems_per_word = ddr_elems_per_word;

#ifndef IA_CSS_NO_DEBUG
		ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
				    "ia_css_yuv444_io_config() put part leave:\n");
#endif
	}
	return 0;
}
