/*
 * Copyright (C) 2010-2012, 2014-2016 ARM Limited. All rights reserved.
 * 
 * This program is free software and is provided to you under the terms of the GNU General Public License version 2
 * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
 * 
 * A copy of the licence is included with the program, and can also be obtained from Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

#include "mali_kernel_utilization.h"
#include "mali_osk.h"
#include "mali_osk_mali.h"
#include "mali_kernel_common.h"
#include "mali_session.h"
#include "mali_dvfs_policy.h"
#include "mali_control_timer.h"

static u64 period_start_time = 0;

static _mali_osk_timer_t *mali_control_timer = NULL;
static mali_bool timer_running = MALI_FALSE;

static u32 mali_control_timeout = 1000;

void mali_control_timer_add(u32 timeout)
{
	_mali_osk_timer_add(mali_control_timer, _mali_osk_time_mstoticks(timeout));
}

static void mali_control_timer_callback(void *arg)
{
	if (mali_utilization_enabled()) {
		struct mali_gpu_utilization_data *util_data = NULL;
		u64 time_period = 0;
		mali_bool need_add_timer = MALI_TRUE;

		/* Calculate gpu utilization */
		util_data = mali_utilization_calculate(&period_start_time, &time_period, &need_add_timer);

		if (util_data) {
#if defined(CONFIG_MALI_DVFS)
			mali_dvfs_policy_realize(util_data, time_period);
#else
			mali_utilization_platform_realize(util_data);
#endif

			if (MALI_TRUE == need_add_timer) {
				mali_control_timer_add(mali_control_timeout);
			}
		}
	}
}

/* Init a timer (for now it is used for GPU utilization and dvfs) */
_mali_osk_errcode_t mali_control_timer_init(void)
{
	_mali_osk_device_data data;

	if (_MALI_OSK_ERR_OK == _mali_osk_device_data_get(&data)) {
		/* Use device specific settings (if defined) */
		if (0 != data.control_interval) {
			mali_control_timeout = data.control_interval;
			MALI_DEBUG_PRINT(2, ("Mali GPU Timer: %u\n", mali_control_timeout));
		}
	}

	mali_control_timer = _mali_osk_timer_init();
	if (NULL == mali_control_timer) {
		return _MALI_OSK_ERR_FAULT;
	}
	_mali_osk_timer_setcallback(mali_control_timer, mali_control_timer_callback, NULL);

	return _MALI_OSK_ERR_OK;
}

void mali_control_timer_term(void)
{
	if (NULL != mali_control_timer) {
		_mali_osk_timer_del(mali_control_timer);
		timer_running = MALI_FALSE;
		_mali_osk_timer_term(mali_control_timer);
		mali_control_timer = NULL;
	}
}

mali_bool mali_control_timer_resume(u64 time_now)
{
	mali_utilization_data_assert_locked();

	if (timer_running != MALI_TRUE) {
		timer_running = MALI_TRUE;

		period_start_time = time_now;

		mali_utilization_reset();

		return MALI_TRUE;
	}

	return MALI_FALSE;
}

void mali_control_timer_pause(void)
{
	mali_utilization_data_assert_locked();
	if (timer_running == MALI_TRUE) {
		timer_running = MALI_FALSE;
	}
}

void mali_control_timer_suspend(mali_bool suspend)
{
	mali_utilization_data_lock();

	if (timer_running == MALI_TRUE) {
		timer_running = MALI_FALSE;

		mali_utilization_data_unlock();

		if (suspend == MALI_TRUE) {
			_mali_osk_timer_del(mali_control_timer);
			mali_utilization_reset();
		}
	} else {
		mali_utilization_data_unlock();
	}
}
