// 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_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));
}
