// 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 "system_global.h"

#ifdef ISP2401

#include "assert_support.h"
#include "platform_support.h"
#include "ia_css_isys.h"
#include "bitop_support.h"
#include "ia_css_pipeline.h"	/* ia_css_pipeline_get_pipe_io_status() */
#include "sh_css_internal.h"	/* sh_css_sp_pipeline_io_status
				 * SH_CSS_MAX_SP_THREADS
				 */
#include "csi_rx_rmgr.h"

static isys_csi_rx_rsrc_t  isys_csi_rx_rsrc[N_CSI_RX_BACKEND_ID];

void ia_css_isys_csi_rx_lut_rmgr_init(void)
{
	memset(isys_csi_rx_rsrc, 0, sizeof(isys_csi_rx_rsrc));
}

void ia_css_isys_csi_rx_lut_rmgr_uninit(void)
{
	memset(isys_csi_rx_rsrc, 0, sizeof(isys_csi_rx_rsrc));
}

bool ia_css_isys_csi_rx_lut_rmgr_acquire(
    csi_rx_backend_ID_t		backend,
    csi_mipi_packet_type_t		packet_type,
    csi_rx_backend_lut_entry_t	*entry)
{
	bool retval = false;
	u32 max_num_packets_of_type;
	u32 num_active_of_type;
	isys_csi_rx_rsrc_t *cur_rsrc = NULL;
	u16 i;

	assert(backend < N_CSI_RX_BACKEND_ID);
	assert((packet_type == CSI_MIPI_PACKET_TYPE_LONG) ||
	       (packet_type == CSI_MIPI_PACKET_TYPE_SHORT));
	assert(entry);

	if ((backend < N_CSI_RX_BACKEND_ID) && (entry)) {
		cur_rsrc = &isys_csi_rx_rsrc[backend];
		if (packet_type == CSI_MIPI_PACKET_TYPE_LONG) {
			max_num_packets_of_type = N_LONG_PACKET_LUT_ENTRIES[backend];
			num_active_of_type = cur_rsrc->num_long_packets;
		} else {
			max_num_packets_of_type = N_SHORT_PACKET_LUT_ENTRIES[backend];
			num_active_of_type = cur_rsrc->num_short_packets;
		}

		if (num_active_of_type < max_num_packets_of_type) {
			for (i = 0; i < max_num_packets_of_type; i++) {
				if (bitop_getbit(cur_rsrc->active_table, i) == 0) {
					bitop_setbit(cur_rsrc->active_table, i);

					if (packet_type == CSI_MIPI_PACKET_TYPE_LONG) {
						entry->long_packet_entry = i;
						entry->short_packet_entry = 0;
						cur_rsrc->num_long_packets++;
					} else {
						entry->long_packet_entry = 0;
						entry->short_packet_entry = i;
						cur_rsrc->num_short_packets++;
					}
					cur_rsrc->num_active++;
					retval = true;
					break;
				}
			}
		}
	}
	return retval;
}

void ia_css_isys_csi_rx_lut_rmgr_release(
    csi_rx_backend_ID_t		backend,
    csi_mipi_packet_type_t		packet_type,
    csi_rx_backend_lut_entry_t	*entry)
{
	u32 max_num_packets;
	isys_csi_rx_rsrc_t *cur_rsrc = NULL;
	u32 packet_entry = 0;

	assert(backend < N_CSI_RX_BACKEND_ID);
	assert(entry);
	assert((packet_type >= CSI_MIPI_PACKET_TYPE_LONG) ||
	       (packet_type <= CSI_MIPI_PACKET_TYPE_SHORT));

	if ((backend < N_CSI_RX_BACKEND_ID) && (entry)) {
		if (packet_type == CSI_MIPI_PACKET_TYPE_LONG) {
			max_num_packets = N_LONG_PACKET_LUT_ENTRIES[backend];
			packet_entry = entry->long_packet_entry;
		} else {
			max_num_packets = N_SHORT_PACKET_LUT_ENTRIES[backend];
			packet_entry = entry->short_packet_entry;
		}

		cur_rsrc = &isys_csi_rx_rsrc[backend];
		if ((packet_entry < max_num_packets) && (cur_rsrc->num_active > 0)) {
			if (bitop_getbit(cur_rsrc->active_table, packet_entry) == 1) {
				bitop_clearbit(cur_rsrc->active_table, packet_entry);

				if (packet_type == CSI_MIPI_PACKET_TYPE_LONG)
					cur_rsrc->num_long_packets--;
				else
					cur_rsrc->num_short_packets--;
				cur_rsrc->num_active--;
			}
		}
	}
}

int ia_css_isys_csi_rx_register_stream(
    enum mipi_port_id port,
    uint32_t isys_stream_id)
{
	int retval = -EINVAL;

	if ((port < N_INPUT_SYSTEM_CSI_PORT) &&
	    (isys_stream_id < SH_CSS_MAX_ISYS_CHANNEL_NODES)) {
		struct sh_css_sp_pipeline_io_status *pipe_io_status;

		pipe_io_status = ia_css_pipeline_get_pipe_io_status();
		if (bitop_getbit(pipe_io_status->active[port], isys_stream_id) == 0) {
			bitop_setbit(pipe_io_status->active[port], isys_stream_id);
			pipe_io_status->running[port] = 0;
			retval = 0;
		}
	}
	return retval;
}

int ia_css_isys_csi_rx_unregister_stream(
    enum mipi_port_id port,
    uint32_t isys_stream_id)
{
	int retval = -EINVAL;

	if ((port < N_INPUT_SYSTEM_CSI_PORT) &&
	    (isys_stream_id < SH_CSS_MAX_ISYS_CHANNEL_NODES)) {
		struct sh_css_sp_pipeline_io_status *pipe_io_status;

		pipe_io_status = ia_css_pipeline_get_pipe_io_status();
		if (bitop_getbit(pipe_io_status->active[port], isys_stream_id) == 1) {
			bitop_clearbit(pipe_io_status->active[port], isys_stream_id);
			retval = 0;
		}
	}
	return retval;
}
#endif
