// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * Copyright (C) 2016 Free Electrons
 * Copyright (C) 2016 NextThing Co
 *
 * Maxime Ripard <maxime.ripard@free-electrons.com>
 */

#include <linux/clk-provider.h>
#include <linux/io.h>

#include "sun4i_hdmi.h"

struct sun4i_tmds {
	struct clk_hw		hw;
	struct sun4i_hdmi	*hdmi;

	u8			div_offset;
};

static inline struct sun4i_tmds *hw_to_tmds(struct clk_hw *hw)
{
	return container_of(hw, struct sun4i_tmds, hw);
}


static unsigned long sun4i_tmds_calc_divider(unsigned long rate,
					     unsigned long parent_rate,
					     u8 div_offset,
					     u8 *div,
					     bool *half)
{
	unsigned long best_rate = 0;
	u8 best_m = 0, m;
	bool is_double = false;

	for (m = div_offset ?: 1; m < (16 + div_offset); m++) {
		u8 d;

		for (d = 1; d < 3; d++) {
			unsigned long tmp_rate;

			tmp_rate = parent_rate / m / d;

			if (tmp_rate > rate)
				continue;

			if (!best_rate ||
			    (rate - tmp_rate) < (rate - best_rate)) {
				best_rate = tmp_rate;
				best_m = m;
				is_double = (d == 2) ? true : false;
			}
		}
	}

	if (div && half) {
		*div = best_m;
		*half = is_double;
	}

	return best_rate;
}


static int sun4i_tmds_determine_rate(struct clk_hw *hw,
				     struct clk_rate_request *req)
{
	struct sun4i_tmds *tmds = hw_to_tmds(hw);
	struct clk_hw *parent = NULL;
	unsigned long best_parent = 0;
	unsigned long rate = req->rate;
	int best_div = 1, best_half = 1;
	int i, j, p;

	/*
	 * We only consider PLL3, since the TCON is very likely to be
	 * clocked from it, and to have the same rate than our HDMI
	 * clock, so we should not need to do anything.
	 */

	for (p = 0; p < clk_hw_get_num_parents(hw); p++) {
		parent = clk_hw_get_parent_by_index(hw, p);
		if (!parent)
			continue;

		for (i = 1; i < 3; i++) {
			for (j = tmds->div_offset ?: 1;
			     j < (16 + tmds->div_offset); j++) {
				unsigned long ideal = rate * i * j;
				unsigned long rounded;

				rounded = clk_hw_round_rate(parent, ideal);

				if (rounded == ideal) {
					best_parent = rounded;
					best_half = i;
					best_div = j;
					goto out;
				}

				if (!best_parent ||
				    abs(rate - rounded / i / j) <
				    abs(rate - best_parent / best_half /
					best_div)) {
					best_parent = rounded;
					best_half = i;
					best_div = j;
				}
			}
		}
	}

	if (!parent)
		return -EINVAL;

out:
	req->rate = best_parent / best_half / best_div;
	req->best_parent_rate = best_parent;
	req->best_parent_hw = parent;

	return 0;
}

static unsigned long sun4i_tmds_recalc_rate(struct clk_hw *hw,
					    unsigned long parent_rate)
{
	struct sun4i_tmds *tmds = hw_to_tmds(hw);
	u32 reg;

	reg = readl(tmds->hdmi->base + SUN4I_HDMI_PAD_CTRL1_REG);
	if (reg & SUN4I_HDMI_PAD_CTRL1_HALVE_CLK)
		parent_rate /= 2;

	reg = readl(tmds->hdmi->base + SUN4I_HDMI_PLL_CTRL_REG);
	reg = ((reg >> 4) & 0xf) + tmds->div_offset;
	if (!reg)
		reg = 1;

	return parent_rate / reg;
}

static int sun4i_tmds_set_rate(struct clk_hw *hw, unsigned long rate,
			       unsigned long parent_rate)
{
	struct sun4i_tmds *tmds = hw_to_tmds(hw);
	bool half;
	u32 reg;
	u8 div;

	sun4i_tmds_calc_divider(rate, parent_rate, tmds->div_offset,
				&div, &half);

	reg = readl(tmds->hdmi->base + SUN4I_HDMI_PAD_CTRL1_REG);
	reg &= ~SUN4I_HDMI_PAD_CTRL1_HALVE_CLK;
	if (half)
		reg |= SUN4I_HDMI_PAD_CTRL1_HALVE_CLK;
	writel(reg, tmds->hdmi->base + SUN4I_HDMI_PAD_CTRL1_REG);

	reg = readl(tmds->hdmi->base + SUN4I_HDMI_PLL_CTRL_REG);
	reg &= ~SUN4I_HDMI_PLL_CTRL_DIV_MASK;
	writel(reg | SUN4I_HDMI_PLL_CTRL_DIV(div - tmds->div_offset),
	       tmds->hdmi->base + SUN4I_HDMI_PLL_CTRL_REG);

	return 0;
}

static u8 sun4i_tmds_get_parent(struct clk_hw *hw)
{
	struct sun4i_tmds *tmds = hw_to_tmds(hw);
	u32 reg;

	reg = readl(tmds->hdmi->base + SUN4I_HDMI_PLL_DBG0_REG);
	return ((reg & SUN4I_HDMI_PLL_DBG0_TMDS_PARENT_MASK) >>
		SUN4I_HDMI_PLL_DBG0_TMDS_PARENT_SHIFT);
}

static int sun4i_tmds_set_parent(struct clk_hw *hw, u8 index)
{
	struct sun4i_tmds *tmds = hw_to_tmds(hw);
	u32 reg;

	if (index > 1)
		return -EINVAL;

	reg = readl(tmds->hdmi->base + SUN4I_HDMI_PLL_DBG0_REG);
	reg &= ~SUN4I_HDMI_PLL_DBG0_TMDS_PARENT_MASK;
	writel(reg | SUN4I_HDMI_PLL_DBG0_TMDS_PARENT(index),
	       tmds->hdmi->base + SUN4I_HDMI_PLL_DBG0_REG);

	return 0;
}

static const struct clk_ops sun4i_tmds_ops = {
	.determine_rate	= sun4i_tmds_determine_rate,
	.recalc_rate	= sun4i_tmds_recalc_rate,
	.set_rate	= sun4i_tmds_set_rate,

	.get_parent	= sun4i_tmds_get_parent,
	.set_parent	= sun4i_tmds_set_parent,
};

int sun4i_tmds_create(struct sun4i_hdmi *hdmi)
{
	struct clk_init_data init;
	struct sun4i_tmds *tmds;
	const char *parents[2];

	parents[0] = __clk_get_name(hdmi->pll0_clk);
	if (!parents[0])
		return -ENODEV;

	parents[1] = __clk_get_name(hdmi->pll1_clk);
	if (!parents[1])
		return -ENODEV;

	tmds = devm_kzalloc(hdmi->dev, sizeof(*tmds), GFP_KERNEL);
	if (!tmds)
		return -ENOMEM;

	init.name = "hdmi-tmds";
	init.ops = &sun4i_tmds_ops;
	init.parent_names = parents;
	init.num_parents = 2;
	init.flags = CLK_SET_RATE_PARENT;

	tmds->hdmi = hdmi;
	tmds->hw.init = &init;
	tmds->div_offset = hdmi->variant->tmds_clk_div_offset;

	hdmi->tmds_clk = devm_clk_register(hdmi->dev, &tmds->hw);
	if (IS_ERR(hdmi->tmds_clk))
		return PTR_ERR(hdmi->tmds_clk);

	return 0;
}
