// 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 <linux/bitops.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_plat *uc_plat = dev_get_uclass_plat(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));
}
