// SPDX-License-Identifier: GPL-2.0
/*
 * Support for Intel Camera Imaging ISP subsystem.
 * Copyright (c) 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"

#include "assert_support.h"
#include "platform_support.h"
#include "ia_css_isys.h"
#include "ibuf_ctrl_rmgr.h"

static ibuf_rsrc_t	ibuf_rsrc;

static ibuf_handle_t *getHandle(uint16_t index)
{
	ibuf_handle_t *handle = NULL;

	if (index < MAX_IBUF_HANDLES)
		handle = &ibuf_rsrc.handles[index];
	return handle;
}

void ia_css_isys_ibuf_rmgr_init(void)
{
	memset(&ibuf_rsrc, 0, sizeof(ibuf_rsrc));
	ibuf_rsrc.free_size = MAX_INPUT_BUFFER_SIZE;
}

void ia_css_isys_ibuf_rmgr_uninit(void)
{
	memset(&ibuf_rsrc, 0, sizeof(ibuf_rsrc));
	ibuf_rsrc.free_size = MAX_INPUT_BUFFER_SIZE;
}

bool ia_css_isys_ibuf_rmgr_acquire(
    u32	size,
    uint32_t	*start_addr)
{
	bool retval = false;
	bool input_buffer_found = false;
	u32 aligned_size;
	ibuf_handle_t *handle = NULL;
	u16 i;

	assert(start_addr);
	assert(size > 0);

	aligned_size = (size + (IBUF_ALIGN - 1)) & ~(IBUF_ALIGN - 1);

	/* Check if there is an available un-used handle with the size
	 * that will fulfill the request.
	 */
	if (ibuf_rsrc.num_active < ibuf_rsrc.num_allocated) {
		for (i = 0; i < ibuf_rsrc.num_allocated; i++) {
			handle = getHandle(i);
			if (!handle->active) {
				if (handle->size >= aligned_size) {
					handle->active = true;
					input_buffer_found = true;
					ibuf_rsrc.num_active++;
					break;
				}
			}
		}
	}

	if (!input_buffer_found) {
		/* There were no available handles that fulfilled the
		 * request. Allocate a new handle with the requested size.
		 */
		if ((ibuf_rsrc.num_allocated < MAX_IBUF_HANDLES) &&
		    (ibuf_rsrc.free_size >= aligned_size)) {
			handle = getHandle(ibuf_rsrc.num_allocated);
			handle->start_addr	= ibuf_rsrc.free_start_addr;
			handle->size		= aligned_size;
			handle->active		= true;

			ibuf_rsrc.free_start_addr += aligned_size;
			ibuf_rsrc.free_size -= aligned_size;
			ibuf_rsrc.num_active++;
			ibuf_rsrc.num_allocated++;

			input_buffer_found = true;
		}
	}

	if (input_buffer_found && handle) {
		*start_addr = handle->start_addr;
		retval = true;
	}

	return retval;
}

void ia_css_isys_ibuf_rmgr_release(
    uint32_t	*start_addr)
{
	u16 i;
	ibuf_handle_t *handle = NULL;

	assert(start_addr);

	for (i = 0; i < ibuf_rsrc.num_allocated; i++) {
		handle = getHandle(i);
		if (handle->active && handle->start_addr == *start_addr) {
			handle->active = false;
			ibuf_rsrc.num_active--;
			break;
		}
	}
}
