/*
 * Copyright (C) 2013-2015 Freescale Semiconductor, Inc. All Rights Reserved.
 */

/*
 * The code contained herein is licensed under the GNU General Public
 * License. You may obtain a copy of the GNU General Public License
 * Version 2 or later at the following locations:
 *
 * http://www.opensource.org/licenses/gpl-license.html
 * http://www.gnu.org/copyleft/gpl.html
 */

/*!
 * @file ipu_pixel_clk.c
 *
 * @brief IPU pixel clock implementation
 *
 * @ingroup IPU
 */

#include <linux/clk-provider.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/ipu-v3.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/string.h>

#include "ipu_prv.h"
#include "ipu_regs.h"

 /*
 * muxd clock implementation
 */
struct clk_di_mux {
	struct clk_hw hw;
	u8		ipu_id;
	u8		di_id;
	u8		flags;
	u8		index;
};
#define to_clk_di_mux(_hw) container_of(_hw, struct clk_di_mux, hw)

static int _ipu_pixel_clk_set_parent(struct clk_hw *hw, u8 index)
{
	struct clk_di_mux *mux = to_clk_di_mux(hw);
	struct ipu_soc *ipu = ipu_get_soc(mux->ipu_id);
	u32 di_gen;

	di_gen = ipu_di_read(ipu, mux->di_id, DI_GENERAL);
	if (index == 0)
		/* ipu1_clk or ipu2_clk internal clk */
		di_gen &= ~DI_GEN_DI_CLK_EXT;
	else
		di_gen |= DI_GEN_DI_CLK_EXT;

	ipu_di_write(ipu, mux->di_id, di_gen, DI_GENERAL);
	mux->index = index;
	pr_debug("ipu_pixel_clk: di_clk_ext:0x%x, di_gen reg:0x%x.\n",
			!(di_gen & DI_GEN_DI_CLK_EXT), di_gen);
	return 0;
}

static u8 _ipu_pixel_clk_get_parent(struct clk_hw *hw)
{
	struct clk_di_mux *mux = to_clk_di_mux(hw);

	return mux->index;
}

const struct clk_ops clk_mux_di_ops = {
	.get_parent = _ipu_pixel_clk_get_parent,
	.set_parent = _ipu_pixel_clk_set_parent,
};

struct clk *clk_register_mux_pix_clk(struct device *dev, const char *name,
		const char **parent_names, u8 num_parents, unsigned long flags,
		u8 ipu_id, u8 di_id, u8 clk_mux_flags)
{
	struct clk_di_mux *mux;
	struct clk *clk;
	struct clk_init_data init;

	mux = kzalloc(sizeof(struct clk_di_mux), GFP_KERNEL);
	if (!mux)
		return ERR_PTR(-ENOMEM);

	init.name = name;
	init.ops = &clk_mux_di_ops;
	init.flags = flags;
	init.parent_names = parent_names;
	init.num_parents = num_parents;

	mux->ipu_id = ipu_id;
	mux->di_id = di_id;
	mux->flags = clk_mux_flags | CLK_SET_RATE_PARENT;
	mux->hw.init = &init;

	clk = clk_register(dev, &mux->hw);
	if (IS_ERR(clk))
		kfree(mux);

	return clk;
}

/*
 * Gated clock implementation
 */
struct clk_di_div {
	struct clk_hw hw;
	u8		ipu_id;
	u8		di_id;
	u8		flags;
};
#define to_clk_di_div(_hw) container_of(_hw, struct clk_di_div, hw)

static unsigned long _ipu_pixel_clk_div_recalc_rate(struct clk_hw *hw,
					unsigned long parent_rate)
{
	struct clk_di_div *di_div = to_clk_di_div(hw);
	struct ipu_soc *ipu = ipu_get_soc(di_div->ipu_id);
	u32 div;
	u64 final_rate = (unsigned long long)parent_rate * 16;

	_ipu_get(ipu);
	div = ipu_di_read(ipu, di_div->di_id, DI_BS_CLKGEN0);
	_ipu_put(ipu);
	pr_debug("ipu_di%d read BS_CLKGEN0 div:%d, final_rate:%lld, prate:%ld\n",
			di_div->di_id, div, final_rate, parent_rate);

	if (div == 0)
		return 0;
	do_div(final_rate, div);

	return (unsigned long)final_rate;
}

static long _ipu_pixel_clk_div_round_rate(struct clk_hw *hw, unsigned long rate,
			       unsigned long *parent_clk_rate)
{
	u64 div, final_rate;
	u32 remainder;
	u64 parent_rate = (unsigned long long)(*parent_clk_rate) * 16;

	/*
	 * Calculate divider
	 * Fractional part is 4 bits,
	 * so simply multiply by 2^4 to get fractional part.
	 */
	div = parent_rate;
	remainder = do_div(div, rate);
	/* Round the divider value */
	if (remainder > (rate/2))
		div++;
	if (div < 0x10)            /* Min DI disp clock divider is 1 */
		div = 0x10;
	if (div & ~0xFEF)
		div &= 0xFF8;
	else {
		/* Round up divider if it gets us closer to desired pix clk */
		if ((div & 0xC) == 0xC) {
			div += 0x10;
			div &= ~0xF;
		}
	}
	final_rate = parent_rate;
	do_div(final_rate, div);

	return final_rate;
}

static int _ipu_pixel_clk_div_set_rate(struct clk_hw *hw, unsigned long rate,
			    unsigned long parent_clk_rate)
{
	struct clk_di_div *di_div = to_clk_di_div(hw);
	struct ipu_soc *ipu = ipu_get_soc(di_div->ipu_id);
	u64 div, parent_rate;
	u32 remainder;

	parent_rate = (unsigned long long)parent_clk_rate * 16;
	div = parent_rate;
	remainder = do_div(div, rate);
	/* Round the divider value */
	if (remainder > (rate/2))
		div++;

	/* Round up divider if it gets us closer to desired pix clk */
	if ((div & 0xC) == 0xC) {
		div += 0x10;
		div &= ~0xF;
	}
	if (div > 0x1000)
		pr_err("Overflow, di:%d, DI_BS_CLKGEN0 div:0x%x\n",
				di_div->di_id, (u32)div);
	_ipu_get(ipu);
	ipu_di_write(ipu, di_div->di_id, (u32)div, DI_BS_CLKGEN0);

	/* Setup pixel clock timing */
	/* FIXME: needs to be more flexible */
	/* Down time is half of period */
	ipu_di_write(ipu, di_div->di_id, ((u32)div / 16) << 16, DI_BS_CLKGEN1);
	_ipu_put(ipu);

	return 0;
}

static struct clk_ops clk_div_ops = {
	.recalc_rate = _ipu_pixel_clk_div_recalc_rate,
	.round_rate = _ipu_pixel_clk_div_round_rate,
	.set_rate = _ipu_pixel_clk_div_set_rate,
};

struct clk *clk_register_div_pix_clk(struct device *dev, const char *name,
		const char *parent_name, unsigned long flags,
		u8 ipu_id, u8 di_id, u8 clk_div_flags)
{
	struct clk_di_div *di_div;
	struct clk *clk;
	struct clk_init_data init;

	di_div = kzalloc(sizeof(struct clk_di_div), GFP_KERNEL);
	if (!di_div)
		return ERR_PTR(-ENOMEM);

	/* struct clk_di_div assignments */
	di_div->ipu_id = ipu_id;
	di_div->di_id = di_id;
	di_div->flags = clk_div_flags;

	init.name = name;
	init.ops = &clk_div_ops;
	init.flags = flags | CLK_SET_RATE_PARENT;
	init.parent_names = parent_name ? &parent_name : NULL;
	init.num_parents = parent_name ? 1 : 0;

	di_div->hw.init = &init;

	clk = clk_register(dev, &di_div->hw);
	if (IS_ERR(clk))
		kfree(di_div);

	return clk;
}

/*
 * Gated clock implementation
 */
struct clk_di_gate {
	struct clk_hw hw;
	u8		ipu_id;
	u8		di_id;
	u8		flags;
};
#define to_clk_di_gate(_hw) container_of(_hw, struct clk_di_gate, hw)

static int _ipu_pixel_clk_enable(struct clk_hw *hw)
{
	struct clk_di_gate *gate = to_clk_di_gate(hw);
	struct ipu_soc *ipu = ipu_get_soc(gate->ipu_id);
	u32 disp_gen;

	disp_gen = ipu_cm_read(ipu, IPU_DISP_GEN);
	disp_gen |= gate->di_id ? DI1_COUNTER_RELEASE : DI0_COUNTER_RELEASE;
	ipu_cm_write(ipu, disp_gen, IPU_DISP_GEN);

	return 0;
}

static void _ipu_pixel_clk_disable(struct clk_hw *hw)
{
	struct clk_di_gate *gate = to_clk_di_gate(hw);
	struct ipu_soc *ipu = ipu_get_soc(gate->ipu_id);
	u32 disp_gen;

	disp_gen = ipu_cm_read(ipu, IPU_DISP_GEN);
	disp_gen &= gate->di_id ? ~DI1_COUNTER_RELEASE : ~DI0_COUNTER_RELEASE;
	ipu_cm_write(ipu, disp_gen, IPU_DISP_GEN);

}


static struct clk_ops clk_gate_di_ops = {
	.enable = _ipu_pixel_clk_enable,
	.disable = _ipu_pixel_clk_disable,
};

struct clk *clk_register_gate_pix_clk(struct device *dev, const char *name,
		const char *parent_name, unsigned long flags,
		u8 ipu_id, u8 di_id, u8 clk_gate_flags)
{
	struct clk_di_gate *gate;
	struct clk *clk;
	struct clk_init_data init;

	gate = kzalloc(sizeof(struct clk_di_gate), GFP_KERNEL);
	if (!gate)
		return ERR_PTR(-ENOMEM);

	gate->ipu_id = ipu_id;
	gate->di_id = di_id;
	gate->flags = clk_gate_flags;

	init.name = name;
	init.ops = &clk_gate_di_ops;
	init.flags = flags | CLK_SET_RATE_PARENT;
	init.parent_names = parent_name ? &parent_name : NULL;
	init.num_parents = parent_name ? 1 : 0;

	gate->hw.init = &init;

	clk = clk_register(dev, &gate->hw);
	if (IS_ERR(clk))
		kfree(gate);

	return clk;
}
