// SPDX-License-Identifier: GPL-2.0
/*
 * Amlogic Meson Video Processing Unit driver
 *
 * Copyright (c) 2018 BayLibre, SAS.
 * Author: Neil Armstrong <narmstrong@baylibre.com>
 */

#include <common.h>
#include <dm.h>
#include <asm/io.h>
#include <linux/bitfield.h>

#include "meson_vpu.h"

/* OSDx_BLKx_CFG */
#define OSD_CANVAS_SEL		16

#define OSD_ENDIANNESS_LE	BIT(15)
#define OSD_ENDIANNESS_BE	(0)

#define OSD_BLK_MODE_422	(0x03 << 8)
#define OSD_BLK_MODE_16		(0x04 << 8)
#define OSD_BLK_MODE_32		(0x05 << 8)
#define OSD_BLK_MODE_24		(0x07 << 8)

#define OSD_OUTPUT_COLOR_RGB	BIT(7)
#define OSD_OUTPUT_COLOR_YUV	(0)

#define OSD_COLOR_MATRIX_32_RGBA	(0x00 << 2)
#define OSD_COLOR_MATRIX_32_ARGB	(0x01 << 2)
#define OSD_COLOR_MATRIX_32_ABGR	(0x02 << 2)
#define OSD_COLOR_MATRIX_32_BGRA	(0x03 << 2)

#define OSD_COLOR_MATRIX_24_RGB		(0x00 << 2)

#define OSD_COLOR_MATRIX_16_RGB655	(0x00 << 2)
#define OSD_COLOR_MATRIX_16_RGB565	(0x04 << 2)

#define OSD_INTERLACE_ENABLED	BIT(1)
#define OSD_INTERLACE_ODD	BIT(0)
#define OSD_INTERLACE_EVEN	(0)

/* OSDx_CTRL_STAT */
#define OSD_ENABLE		BIT(21)
#define OSD_BLK0_ENABLE		BIT(0)

#define OSD_GLOBAL_ALPHA_SHIFT	12

/* OSDx_CTRL_STAT2 */
#define OSD_REPLACE_EN		BIT(14)
#define OSD_REPLACE_SHIFT	6

/*
 * When the output is interlaced, the OSD must switch between
 * each field using the INTERLACE_SEL_ODD (0) of VIU_OSD1_BLK0_CFG_W0
 * at each vsync.
 * But the vertical scaler can provide such funtionnality if
 * is configured for 2:1 scaling with interlace options enabled.
 */
static void meson_vpp_setup_interlace_vscaler_osd1(struct meson_vpu_priv *priv,
						   struct video_priv *uc_priv)
{
	writel(BIT(3) /* Enable scaler */ |
	       BIT(2), /* Select OSD1 */
	       priv->io_base + _REG(VPP_OSD_SC_CTRL0));

	writel(((uc_priv->xsize - 1) << 16) | (uc_priv->ysize - 1),
	       priv->io_base + _REG(VPP_OSD_SCI_WH_M1));
	/* 2:1 scaling */
	writel((0 << 16) | uc_priv->xsize,
	       priv->io_base + _REG(VPP_OSD_SCO_H_START_END));
	writel(((0 >> 1) << 16) | (uc_priv->ysize >> 1),
	       priv->io_base + _REG(VPP_OSD_SCO_V_START_END));

	/* 2:1 scaling values */
	writel(BIT(16), priv->io_base + _REG(VPP_OSD_VSC_INI_PHASE));
	writel(BIT(25), priv->io_base + _REG(VPP_OSD_VSC_PHASE_STEP));

	writel(0, priv->io_base + _REG(VPP_OSD_HSC_CTRL0));

	writel((4 << 0)  /* osd_vsc_bank_length */ |
	       (4 << 3)  /* osd_vsc_top_ini_rcv_num0 */ |
	       (1 << 8)  /* osd_vsc_top_rpt_p0_num0 */ |
	       (6 << 11) /* osd_vsc_bot_ini_rcv_num0 */ |
	       (2 << 16) /* osd_vsc_bot_rpt_p0_num0 */ |
	       BIT(23)	 /* osd_prog_interlace */ |
	       BIT(24),  /* Enable vertical scaler */
	       priv->io_base + _REG(VPP_OSD_VSC_CTRL0));
}

static void
meson_vpp_disable_interlace_vscaler_osd1(struct meson_vpu_priv *priv)
{
	writel(0, priv->io_base + _REG(VPP_OSD_SC_CTRL0));
	writel(0, priv->io_base + _REG(VPP_OSD_VSC_CTRL0));
	writel(0, priv->io_base + _REG(VPP_OSD_HSC_CTRL0));
}

void meson_vpu_setup_plane(struct udevice *dev, bool is_interlaced)
{
	struct video_uc_platdata *uc_plat = dev_get_uclass_platdata(dev);
	struct video_priv *uc_priv = dev_get_uclass_priv(dev);
	struct meson_vpu_priv *priv = dev_get_priv(dev);
	u32 osd1_ctrl_stat;
	u32 osd1_blk0_cfg[5];
	bool osd1_interlace;
	unsigned int src_x1, src_x2, src_y1, src_y2;
	unsigned int dest_x1, dest_x2, dest_y1, dest_y2;

	dest_x1 = src_x1 = 0;
	dest_x2 = src_x2 = uc_priv->xsize;
	dest_y1 = src_y1 = 0;
	dest_y2 = src_y2 = uc_priv->ysize;

	if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
		/* VD1 Preblend vertical start/end */
		writel(FIELD_PREP(GENMASK(11, 0), 2303),
		       priv->io_base + _REG(VPP_PREBLEND_VD1_V_START_END));

		/* Setup Blender */
		writel(uc_priv->xsize |
		       uc_priv->ysize << 16,
		       priv->io_base + _REG(VPP_POSTBLEND_H_SIZE));

		writel(0 << 16 |
		       (uc_priv->xsize - 1),
		       priv->io_base + _REG(VPP_OSD1_BLD_H_SCOPE));
		writel(0 << 16 |
		       (uc_priv->ysize - 1),
		       priv->io_base + _REG(VPP_OSD1_BLD_V_SCOPE));
		writel(uc_priv->xsize << 16 |
		       uc_priv->ysize,
		       priv->io_base + _REG(VPP_OUT_H_V_SIZE));
	} else {
		/* Enable VPP Postblend */
		writel(uc_priv->xsize,
		       priv->io_base + _REG(VPP_POSTBLEND_H_SIZE));

		writel_bits(VPP_POSTBLEND_ENABLE, VPP_POSTBLEND_ENABLE,
			    priv->io_base + _REG(VPP_MISC));
	}

	/* uc_plat->base is the framebuffer */

	/* Enable OSD and BLK0, set max global alpha */
	osd1_ctrl_stat = OSD_ENABLE | (0xFF << OSD_GLOBAL_ALPHA_SHIFT) |
			 OSD_BLK0_ENABLE;

	/* Set up BLK0 to point to the right canvas */
	osd1_blk0_cfg[0] = ((MESON_CANVAS_ID_OSD1 << OSD_CANVAS_SEL) |
			   OSD_ENDIANNESS_LE);

	/* On GXBB, Use the old non-HDR RGB2YUV converter */
	if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXBB))
		osd1_blk0_cfg[0] |= OSD_OUTPUT_COLOR_RGB;

	/* For XRGB, replace the pixel's alpha by 0xFF */
	writel_bits(OSD_REPLACE_EN, OSD_REPLACE_EN,
		    priv->io_base + _REG(VIU_OSD1_CTRL_STAT2));
	osd1_blk0_cfg[0] |= OSD_BLK_MODE_32 |
		OSD_COLOR_MATRIX_32_ARGB;

	if (is_interlaced) {
		osd1_interlace = true;
		dest_y1 /= 2;
		dest_y2 /= 2;
	} else {
		osd1_interlace = false;
	}

	/*
	 * The format of these registers is (x2 << 16 | x1),
	 * where x2 is exclusive.
	 * e.g. +30x1920 would be (1919 << 16) | 30
	 */
	osd1_blk0_cfg[1] = ((src_x2 - 1) << 16) | src_x1;
	osd1_blk0_cfg[2] = ((src_y2 - 1) << 16) | src_y1;
	osd1_blk0_cfg[3] = ((dest_x2 - 1) << 16) | dest_x1;
	osd1_blk0_cfg[4] = ((dest_y2 - 1) << 16) | dest_y1;

	writel(osd1_ctrl_stat, priv->io_base + _REG(VIU_OSD1_CTRL_STAT));
	writel(osd1_blk0_cfg[0], priv->io_base + _REG(VIU_OSD1_BLK0_CFG_W0));
	writel(osd1_blk0_cfg[1], priv->io_base + _REG(VIU_OSD1_BLK0_CFG_W1));
	writel(osd1_blk0_cfg[2], priv->io_base + _REG(VIU_OSD1_BLK0_CFG_W2));
	writel(osd1_blk0_cfg[3], priv->io_base + _REG(VIU_OSD1_BLK0_CFG_W3));
	writel(osd1_blk0_cfg[4], priv->io_base + _REG(VIU_OSD1_BLK0_CFG_W4));

	/* If output is interlace, make use of the Scaler */
	if (osd1_interlace)
		meson_vpp_setup_interlace_vscaler_osd1(priv, uc_priv);
	else
		meson_vpp_disable_interlace_vscaler_osd1(priv);

	meson_canvas_setup(priv, MESON_CANVAS_ID_OSD1,
			   uc_plat->base, uc_priv->xsize * 4,
			   uc_priv->ysize, MESON_CANVAS_WRAP_NONE,
			   MESON_CANVAS_BLKMODE_LINEAR);

	/* Enable OSD1 */
	if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
		writel(((dest_x2 - 1) << 16) | dest_x1,
		       priv->io_base + _REG(VIU_OSD_BLEND_DIN0_SCOPE_H));
		writel(((dest_y2 - 1) << 16) | dest_y1,
		       priv->io_base + _REG(VIU_OSD_BLEND_DIN0_SCOPE_V));
		writel(uc_priv->xsize << 16 | uc_priv->ysize,
		       priv->io_base + _REG(VIU_OSD_BLEND_BLEND0_SIZE));
		writel(uc_priv->xsize << 16 | uc_priv->ysize,
		       priv->io_base + _REG(VIU_OSD_BLEND_BLEND1_SIZE));
		writel_bits(3 << 8, 3 << 8,
			    priv->io_base + _REG(OSD1_BLEND_SRC_CTRL));
	} else
		writel_bits(VPP_OSD1_POSTBLEND, VPP_OSD1_POSTBLEND,
			    priv->io_base + _REG(VPP_MISC));
}
