/*
 * Allwinner DE2 display driver
 *
 * (C) Copyright 2017 Jernej Skrabec <jernej.skrabec@siol.net>
 *
 * SPDX-License-Identifier:	GPL-2.0+
 */

#include <common.h>
#include <display.h>
#include <dm.h>
#include <edid.h>
#include <video.h>
#include <asm/global_data.h>
#include <asm/io.h>
#include <asm/arch/clock.h>
#include <asm/arch/display2.h>
#include <dm/device-internal.h>
#include <dm/uclass-internal.h>

DECLARE_GLOBAL_DATA_PTR;

enum {
	/* Maximum LCD size we support */
	LCD_MAX_WIDTH		= 3840,
	LCD_MAX_HEIGHT		= 2160,
	LCD_MAX_LOG2_BPP	= VIDEO_BPP32,
};

static void sunxi_de2_composer_init(void)
{
	struct sunxi_ccm_reg * const ccm =
		(struct sunxi_ccm_reg *)SUNXI_CCM_BASE;

#ifdef CONFIG_MACH_SUN50I
	u32 reg_value;

	/* set SRAM for video use (A64 only) */
	reg_value = readl(SUNXI_SRAMC_BASE + 0x04);
	reg_value &= ~(0x01 << 24);
	writel(reg_value, SUNXI_SRAMC_BASE + 0x04);
#endif

	clock_set_pll10(432000000);

	/* Set DE parent to pll10 */
	clrsetbits_le32(&ccm->de_clk_cfg, CCM_DE2_CTRL_PLL_MASK,
			CCM_DE2_CTRL_PLL10);

	/* Set ahb gating to pass */
	setbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_DE);
	setbits_le32(&ccm->ahb_gate1, 1 << AHB_GATE_OFFSET_DE);

	/* Clock on */
	setbits_le32(&ccm->de_clk_cfg, CCM_DE2_CTRL_GATE);
}

static void sunxi_de2_mode_set(int mux, const struct display_timing *mode,
			       int bpp, ulong address)
{
	ulong de_mux_base = (mux == 0) ?
			    SUNXI_DE2_MUX0_BASE : SUNXI_DE2_MUX1_BASE;
	struct de_clk * const de_clk_regs =
		(struct de_clk *)(SUNXI_DE2_BASE);
	struct de_glb * const de_glb_regs =
		(struct de_glb *)(de_mux_base +
				  SUNXI_DE2_MUX_GLB_REGS);
	struct de_bld * const de_bld_regs =
		(struct de_bld *)(de_mux_base +
				  SUNXI_DE2_MUX_BLD_REGS);
	struct de_ui * const de_ui_regs =
		(struct de_ui *)(de_mux_base +
				 SUNXI_DE2_MUX_CHAN_REGS +
				 SUNXI_DE2_MUX_CHAN_SZ * 1);
	u32 size = SUNXI_DE2_WH(mode->hactive.typ, mode->vactive.typ);
	int channel;
	u32 format;

	/* enable clock */
#ifdef CONFIG_MACH_SUN8I_H3
	setbits_le32(&de_clk_regs->rst_cfg, (mux == 0) ? 1 : 4);
#else
	setbits_le32(&de_clk_regs->rst_cfg, BIT(mux));
#endif
	setbits_le32(&de_clk_regs->gate_cfg, BIT(mux));
	setbits_le32(&de_clk_regs->bus_cfg, BIT(mux));

	clrbits_le32(&de_clk_regs->sel_cfg, 1);

	writel(SUNXI_DE2_MUX_GLB_CTL_EN, &de_glb_regs->ctl);
	writel(0, &de_glb_regs->status);
	writel(1, &de_glb_regs->dbuff);
	writel(size, &de_glb_regs->size);

	for (channel = 0; channel < 4; channel++) {
		void *ch = (void *)(de_mux_base + SUNXI_DE2_MUX_CHAN_REGS +
				    SUNXI_DE2_MUX_CHAN_SZ * channel);
		memset(ch, 0, (channel == 0) ?
			sizeof(struct de_vi) : sizeof(struct de_ui));
	}
	memset(de_bld_regs, 0, sizeof(struct de_bld));

	writel(0x00000101, &de_bld_regs->fcolor_ctl);

	writel(1, &de_bld_regs->route);

	writel(0, &de_bld_regs->premultiply);
	writel(0xff000000, &de_bld_regs->bkcolor);

	writel(0x03010301, &de_bld_regs->bld_mode[0]);

	writel(size, &de_bld_regs->output_size);
	writel(mode->flags & DISPLAY_FLAGS_INTERLACED ? 2 : 0,
	       &de_bld_regs->out_ctl);
	writel(0, &de_bld_regs->ck_ctl);

	writel(0xff000000, &de_bld_regs->attr[0].fcolor);
	writel(size, &de_bld_regs->attr[0].insize);

	/* Disable all other units */
	writel(0, de_mux_base + SUNXI_DE2_MUX_VSU_REGS);
	writel(0, de_mux_base + SUNXI_DE2_MUX_GSU1_REGS);
	writel(0, de_mux_base + SUNXI_DE2_MUX_GSU2_REGS);
	writel(0, de_mux_base + SUNXI_DE2_MUX_GSU3_REGS);
	writel(0, de_mux_base + SUNXI_DE2_MUX_FCE_REGS);
	writel(0, de_mux_base + SUNXI_DE2_MUX_BWS_REGS);
	writel(0, de_mux_base + SUNXI_DE2_MUX_LTI_REGS);
	writel(0, de_mux_base + SUNXI_DE2_MUX_PEAK_REGS);
	writel(0, de_mux_base + SUNXI_DE2_MUX_ASE_REGS);
	writel(0, de_mux_base + SUNXI_DE2_MUX_FCC_REGS);
	writel(0, de_mux_base + SUNXI_DE2_MUX_DCSC_REGS);

	switch (bpp) {
	case 16:
		format = SUNXI_DE2_UI_CFG_ATTR_FMT(SUNXI_DE2_FORMAT_RGB_565);
		break;
	case 32:
	default:
		format = SUNXI_DE2_UI_CFG_ATTR_FMT(SUNXI_DE2_FORMAT_XRGB_8888);
		break;
	}

	writel(SUNXI_DE2_UI_CFG_ATTR_EN | format, &de_ui_regs->cfg[0].attr);
	writel(size, &de_ui_regs->cfg[0].size);
	writel(0, &de_ui_regs->cfg[0].coord);
	writel((bpp / 8) * mode->hactive.typ, &de_ui_regs->cfg[0].pitch);
	writel(address, &de_ui_regs->cfg[0].top_laddr);
	writel(size, &de_ui_regs->ovl_size);

	/* apply settings */
	writel(1, &de_glb_regs->dbuff);
}

static int sunxi_de2_init(struct udevice *dev, ulong fbbase,
			  enum video_log2_bpp l2bpp,
			  struct udevice *disp, int mux)
{
	struct video_priv *uc_priv = dev_get_uclass_priv(dev);
	struct display_timing timing;
	struct display_plat *disp_uc_plat;
	int ret;

	disp_uc_plat = dev_get_uclass_platdata(disp);
	debug("Using device '%s', disp_uc_priv=%p\n", disp->name, disp_uc_plat);
	if (display_in_use(disp)) {
		debug("   - device in use\n");
		return -EBUSY;
	}

	disp_uc_plat->source_id = mux;

	ret = device_probe(disp);
	if (ret) {
		debug("%s: device '%s' display won't probe (ret=%d)\n",
		      __func__, dev->name, ret);
		return ret;
	}

	ret = display_read_timing(disp, &timing);
	if (ret) {
		debug("%s: Failed to read timings\n", __func__);
		return ret;
	}

	sunxi_de2_composer_init();
	sunxi_de2_mode_set(mux, &timing, 1 << l2bpp, fbbase);

	ret = display_enable(disp, 1 << l2bpp, &timing);
	if (ret) {
		debug("%s: Failed to enable display\n", __func__);
		return ret;
	}

	uc_priv->xsize = timing.hactive.typ;
	uc_priv->ysize = timing.vactive.typ;
	uc_priv->bpix = l2bpp;
	debug("fb=%lx, size=%d %d\n", fbbase, uc_priv->xsize, uc_priv->ysize);

	return 0;
}

static int sunxi_de2_probe(struct udevice *dev)
{
	struct video_uc_platdata *plat = dev_get_uclass_platdata(dev);
	struct udevice *disp;
	int ret;
	int mux;

	/* Before relocation we don't need to do anything */
	if (!(gd->flags & GD_FLG_RELOC))
		return 0;

	ret = uclass_find_device_by_name(UCLASS_DISPLAY,
					 "sunxi_dw_hdmi", &disp);
	if (ret) {
		debug("%s: hdmi display not found (ret=%d)\n", __func__, ret);
		return ret;
	}

	if (IS_ENABLED(CONFIG_MACH_SUNXI_H3_H5))
		mux = 0;
	else
		mux = 1;

	ret = sunxi_de2_init(dev, plat->base, VIDEO_BPP32, disp, mux);
	if (ret)
		return ret;

	video_set_flush_dcache(dev, 1);

	return 0;
}

static int sunxi_de2_bind(struct udevice *dev)
{
	struct video_uc_platdata *plat = dev_get_uclass_platdata(dev);

	plat->size = LCD_MAX_WIDTH * LCD_MAX_HEIGHT *
		(1 << LCD_MAX_LOG2_BPP) / 8;

	return 0;
}

static const struct video_ops sunxi_de2_ops = {
};

U_BOOT_DRIVER(sunxi_de2) = {
	.name	= "sunxi_de2",
	.id	= UCLASS_VIDEO,
	.ops	= &sunxi_de2_ops,
	.bind	= sunxi_de2_bind,
	.probe	= sunxi_de2_probe,
	.flags	= DM_FLAG_PRE_RELOC,
};

U_BOOT_DEVICE(sunxi_de2) = {
	.name = "sunxi_de2"
};
