/*
 * Samsung EXYNOS4x12 FIMC-IS (Imaging Subsystem) driver
 *
 * Copyright (C) 2012 - 2013 Samsung Electronics Co., Ltd.
 *
 * Authors: Younghwan Joo <yhwan.joo@samsung.com>
 *          Sylwester Nawrocki <s.nawrocki@samsung.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */
#include <linux/delay.h>

#include "fimc-is.h"
#include "fimc-is-command.h"
#include "fimc-is-regs.h"
#include "fimc-is-sensor.h"

void fimc_is_fw_clear_irq1(struct fimc_is *is, unsigned int nr)
{
	mcuctl_write(1UL << nr, is, MCUCTL_REG_INTCR1);
}

void fimc_is_fw_clear_irq2(struct fimc_is *is)
{
	u32 cfg = mcuctl_read(is, MCUCTL_REG_INTSR2);
	mcuctl_write(cfg, is, MCUCTL_REG_INTCR2);
}

void fimc_is_hw_set_intgr0_gd0(struct fimc_is *is)
{
	mcuctl_write(INTGR0_INTGD(0), is, MCUCTL_REG_INTGR0);
}

int fimc_is_hw_wait_intmsr0_intmsd0(struct fimc_is *is)
{
	unsigned int timeout = 2000;
	u32 cfg, status;

	do {
		cfg = mcuctl_read(is, MCUCTL_REG_INTMSR0);
		status = INTMSR0_GET_INTMSD(0, cfg);

		if (--timeout == 0) {
			dev_warn(&is->pdev->dev, "%s timeout\n",
				 __func__);
			return -ETIMEDOUT;
		}
		udelay(1);
	} while (status != 0);

	return 0;
}

int fimc_is_hw_set_param(struct fimc_is *is)
{
	struct chain_config *config = &is->config[is->config_index];
	unsigned int param_count = __get_pending_param_count(is);

	fimc_is_hw_wait_intmsr0_intmsd0(is);

	mcuctl_write(HIC_SET_PARAMETER, is, MCUCTL_REG_ISSR(0));
	mcuctl_write(is->sensor_index, is, MCUCTL_REG_ISSR(1));
	mcuctl_write(is->config_index, is, MCUCTL_REG_ISSR(2));

	mcuctl_write(param_count, is, MCUCTL_REG_ISSR(3));
	mcuctl_write(config->p_region_index[0], is, MCUCTL_REG_ISSR(4));
	mcuctl_write(config->p_region_index[1], is, MCUCTL_REG_ISSR(5));

	fimc_is_hw_set_intgr0_gd0(is);
	return 0;
}

static int __maybe_unused fimc_is_hw_set_tune(struct fimc_is *is)
{
	fimc_is_hw_wait_intmsr0_intmsd0(is);

	mcuctl_write(HIC_SET_TUNE, is, MCUCTL_REG_ISSR(0));
	mcuctl_write(is->sensor_index, is, MCUCTL_REG_ISSR(1));
	mcuctl_write(is->h2i_cmd.entry_id, is, MCUCTL_REG_ISSR(2));

	fimc_is_hw_set_intgr0_gd0(is);
	return 0;
}

#define FIMC_IS_MAX_PARAMS	4

int fimc_is_hw_get_params(struct fimc_is *is, unsigned int num_args)
{
	int i;

	if (num_args > FIMC_IS_MAX_PARAMS)
		return -EINVAL;

	is->i2h_cmd.num_args = num_args;

	for (i = 0; i < FIMC_IS_MAX_PARAMS; i++) {
		if (i < num_args)
			is->i2h_cmd.args[i] = mcuctl_read(is,
					MCUCTL_REG_ISSR(12 + i));
		else
			is->i2h_cmd.args[i] = 0;
	}
	return 0;
}

void fimc_is_hw_set_isp_buf_mask(struct fimc_is *is, unsigned int mask)
{
	if (hweight32(mask) == 1) {
		dev_err(&is->pdev->dev, "%s(): not enough buffers (mask %#x)\n",
							__func__, mask);
		return;
	}

	if (mcuctl_read(is, MCUCTL_REG_ISSR(23)) != 0)
		dev_dbg(&is->pdev->dev, "non-zero DMA buffer mask\n");

	mcuctl_write(mask, is, MCUCTL_REG_ISSR(23));
}

void fimc_is_hw_set_sensor_num(struct fimc_is *is)
{
	pr_debug("setting sensor index to: %d\n", is->sensor_index);

	mcuctl_write(IH_REPLY_DONE, is, MCUCTL_REG_ISSR(0));
	mcuctl_write(is->sensor_index, is, MCUCTL_REG_ISSR(1));
	mcuctl_write(IHC_GET_SENSOR_NUM, is, MCUCTL_REG_ISSR(2));
	mcuctl_write(FIMC_IS_SENSORS_NUM, is, MCUCTL_REG_ISSR(3));
}

void fimc_is_hw_close_sensor(struct fimc_is *is, unsigned int index)
{
	if (is->sensor_index != index)
		return;

	fimc_is_hw_wait_intmsr0_intmsd0(is);
	mcuctl_write(HIC_CLOSE_SENSOR, is, MCUCTL_REG_ISSR(0));
	mcuctl_write(is->sensor_index, is, MCUCTL_REG_ISSR(1));
	mcuctl_write(is->sensor_index, is, MCUCTL_REG_ISSR(2));
	fimc_is_hw_set_intgr0_gd0(is);
}

void fimc_is_hw_get_setfile_addr(struct fimc_is *is)
{
	fimc_is_hw_wait_intmsr0_intmsd0(is);
	mcuctl_write(HIC_GET_SET_FILE_ADDR, is, MCUCTL_REG_ISSR(0));
	mcuctl_write(is->sensor_index, is, MCUCTL_REG_ISSR(1));
	fimc_is_hw_set_intgr0_gd0(is);
}

void fimc_is_hw_load_setfile(struct fimc_is *is)
{
	fimc_is_hw_wait_intmsr0_intmsd0(is);
	mcuctl_write(HIC_LOAD_SET_FILE, is, MCUCTL_REG_ISSR(0));
	mcuctl_write(is->sensor_index, is, MCUCTL_REG_ISSR(1));
	fimc_is_hw_set_intgr0_gd0(is);
}

int fimc_is_hw_change_mode(struct fimc_is *is)
{
	const u8 cmd[] = {
		HIC_PREVIEW_STILL, HIC_PREVIEW_VIDEO,
		HIC_CAPTURE_STILL, HIC_CAPTURE_VIDEO,
	};

	if (WARN_ON(is->config_index >= ARRAY_SIZE(cmd)))
		return -EINVAL;

	mcuctl_write(cmd[is->config_index], is, MCUCTL_REG_ISSR(0));
	mcuctl_write(is->sensor_index, is, MCUCTL_REG_ISSR(1));
	mcuctl_write(is->setfile.sub_index, is, MCUCTL_REG_ISSR(2));
	fimc_is_hw_set_intgr0_gd0(is);
	return 0;
}

void fimc_is_hw_stream_on(struct fimc_is *is)
{
	fimc_is_hw_wait_intmsr0_intmsd0(is);
	mcuctl_write(HIC_STREAM_ON, is, MCUCTL_REG_ISSR(0));
	mcuctl_write(is->sensor_index, is, MCUCTL_REG_ISSR(1));
	mcuctl_write(0, is, MCUCTL_REG_ISSR(2));
	fimc_is_hw_set_intgr0_gd0(is);
}

void fimc_is_hw_stream_off(struct fimc_is *is)
{
	fimc_is_hw_wait_intmsr0_intmsd0(is);
	mcuctl_write(HIC_STREAM_OFF, is, MCUCTL_REG_ISSR(0));
	mcuctl_write(is->sensor_index, is, MCUCTL_REG_ISSR(1));
	fimc_is_hw_set_intgr0_gd0(is);
}

void fimc_is_hw_subip_power_off(struct fimc_is *is)
{
	fimc_is_hw_wait_intmsr0_intmsd0(is);
	mcuctl_write(HIC_POWER_DOWN, is, MCUCTL_REG_ISSR(0));
	mcuctl_write(is->sensor_index, is, MCUCTL_REG_ISSR(1));
	fimc_is_hw_set_intgr0_gd0(is);
}

int fimc_is_itf_s_param(struct fimc_is *is, bool update)
{
	int ret;

	if (update)
		__is_hw_update_params(is);

	fimc_is_mem_barrier();

	clear_bit(IS_ST_BLOCK_CMD_CLEARED, &is->state);
	fimc_is_hw_set_param(is);
	ret = fimc_is_wait_event(is, IS_ST_BLOCK_CMD_CLEARED, 1,
				FIMC_IS_CONFIG_TIMEOUT);
	if (ret < 0)
		dev_err(&is->pdev->dev, "%s() timeout\n", __func__);

	return ret;
}

int fimc_is_itf_mode_change(struct fimc_is *is)
{
	int ret;

	clear_bit(IS_ST_CHANGE_MODE, &is->state);
	fimc_is_hw_change_mode(is);
	ret = fimc_is_wait_event(is, IS_ST_CHANGE_MODE, 1,
				FIMC_IS_CONFIG_TIMEOUT);
	if (ret < 0)
		dev_err(&is->pdev->dev, "%s(): mode change (%d) timeout\n",
			__func__, is->config_index);
	return ret;
}
