All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH 0/8] arm: meson: add Video support for G12A and SEI510 board
@ 2019-08-30 12:09 ` Neil Armstrong
  0 siblings, 0 replies; 38+ messages in thread
From: Neil Armstrong @ 2019-08-30 12:09 UTC (permalink / raw)
  To: u-boot

This patchset adds Amlogic G12A support for HDMI & Composite video output like
the Amlogic GXBB/GXL/GXM, by syncing from the latest Linux VPU DRM driver.

It also adds VPU/VAPB/HDMI Clock & VPU Power Domain support.

Finally it adds the necessary config to show a logo from a fastboot flashed
partition on the SEI510 board.

U200 and Odroid-N2 config support will be added later.

Neil Armstrong (8):
  power: domain: meson-gx-pwrc: add G12A support
  clk: meson: g12a: add support for VPU/HDMI clocks
  video: meson: remove power domain get
  video: meson: sync with linux drm-misc tree
  video: meson: add compatible for Amlogic G12A
  arm: meson: board-g12a: Setup VPU in fdt
  ARM: dts: meson-g12a: add U-Boot specific DT for graphics
  configs: sei510: enable Video Display support

 arch/arm/dts/meson-g12a-sei510-u-boot.dtsi    |   7 +
 arch/arm/dts/meson-g12a-u-boot.dtsi           |  29 +
 arch/arm/dts/meson-g12a-u200-u-boot.dtsi      |   7 +
 arch/arm/dts/meson-g12b-odroid-n2-u-boot.dtsi |   7 +
 arch/arm/mach-meson/board-g12a.c              |   5 +
 configs/sei510_defconfig                      |  11 +
 drivers/clk/meson/g12a.c                      | 620 +++++++++++++++++-
 drivers/power/domain/meson-gx-pwrc-vpu.c      | 155 ++++-
 drivers/video/meson/meson_dw_hdmi.c           |  61 +-
 drivers/video/meson/meson_plane.c             |  47 +-
 drivers/video/meson/meson_registers.h         | 373 ++++++++++-
 drivers/video/meson/meson_vclk.c              | 233 +++++--
 drivers/video/meson/meson_venc.c              | 169 ++++-
 drivers/video/meson/meson_vpu.c               |  11 +-
 drivers/video/meson/meson_vpu.h               |   2 +
 drivers/video/meson/meson_vpu_init.c          | 205 ++++--
 include/configs/sei510.h                      |  12 +
 17 files changed, 1757 insertions(+), 197 deletions(-)
 create mode 100644 arch/arm/dts/meson-g12a-sei510-u-boot.dtsi
 create mode 100644 arch/arm/dts/meson-g12a-u-boot.dtsi
 create mode 100644 arch/arm/dts/meson-g12a-u200-u-boot.dtsi
 create mode 100644 arch/arm/dts/meson-g12b-odroid-n2-u-boot.dtsi

-- 
2.22.0

^ permalink raw reply	[flat|nested] 38+ messages in thread

* [PATCH 0/8] arm: meson: add Video support for G12A and SEI510 board
@ 2019-08-30 12:09 ` Neil Armstrong
  0 siblings, 0 replies; 38+ messages in thread
From: Neil Armstrong @ 2019-08-30 12:09 UTC (permalink / raw)
  To: u-boot-amlogic, agust, jh80.chung, lukma; +Cc: Neil Armstrong, u-boot

This patchset adds Amlogic G12A support for HDMI & Composite video output like
the Amlogic GXBB/GXL/GXM, by syncing from the latest Linux VPU DRM driver.

It also adds VPU/VAPB/HDMI Clock & VPU Power Domain support.

Finally it adds the necessary config to show a logo from a fastboot flashed
partition on the SEI510 board.

U200 and Odroid-N2 config support will be added later.

Neil Armstrong (8):
  power: domain: meson-gx-pwrc: add G12A support
  clk: meson: g12a: add support for VPU/HDMI clocks
  video: meson: remove power domain get
  video: meson: sync with linux drm-misc tree
  video: meson: add compatible for Amlogic G12A
  arm: meson: board-g12a: Setup VPU in fdt
  ARM: dts: meson-g12a: add U-Boot specific DT for graphics
  configs: sei510: enable Video Display support

 arch/arm/dts/meson-g12a-sei510-u-boot.dtsi    |   7 +
 arch/arm/dts/meson-g12a-u-boot.dtsi           |  29 +
 arch/arm/dts/meson-g12a-u200-u-boot.dtsi      |   7 +
 arch/arm/dts/meson-g12b-odroid-n2-u-boot.dtsi |   7 +
 arch/arm/mach-meson/board-g12a.c              |   5 +
 configs/sei510_defconfig                      |  11 +
 drivers/clk/meson/g12a.c                      | 620 +++++++++++++++++-
 drivers/power/domain/meson-gx-pwrc-vpu.c      | 155 ++++-
 drivers/video/meson/meson_dw_hdmi.c           |  61 +-
 drivers/video/meson/meson_plane.c             |  47 +-
 drivers/video/meson/meson_registers.h         | 373 ++++++++++-
 drivers/video/meson/meson_vclk.c              | 233 +++++--
 drivers/video/meson/meson_venc.c              | 169 ++++-
 drivers/video/meson/meson_vpu.c               |  11 +-
 drivers/video/meson/meson_vpu.h               |   2 +
 drivers/video/meson/meson_vpu_init.c          | 205 ++++--
 include/configs/sei510.h                      |  12 +
 17 files changed, 1757 insertions(+), 197 deletions(-)
 create mode 100644 arch/arm/dts/meson-g12a-sei510-u-boot.dtsi
 create mode 100644 arch/arm/dts/meson-g12a-u-boot.dtsi
 create mode 100644 arch/arm/dts/meson-g12a-u200-u-boot.dtsi
 create mode 100644 arch/arm/dts/meson-g12b-odroid-n2-u-boot.dtsi

-- 
2.22.0


^ permalink raw reply	[flat|nested] 38+ messages in thread

* [U-Boot] [PATCH 1/8] power: domain: meson-gx-pwrc: add G12A support
  2019-08-30 12:09 ` Neil Armstrong
@ 2019-08-30 12:09   ` Neil Armstrong
  -1 siblings, 0 replies; 38+ messages in thread
From: Neil Armstrong @ 2019-08-30 12:09 UTC (permalink / raw)
  To: u-boot

Add Amlogic G12A support for the gx-pwrc driver, aligned on the
Linux v5.2 driver.

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 drivers/power/domain/meson-gx-pwrc-vpu.c | 155 +++++++++++++++++++++--
 1 file changed, 145 insertions(+), 10 deletions(-)

diff --git a/drivers/power/domain/meson-gx-pwrc-vpu.c b/drivers/power/domain/meson-gx-pwrc-vpu.c
index d631d3e6ff..f44e33bacb 100644
--- a/drivers/power/domain/meson-gx-pwrc-vpu.c
+++ b/drivers/power/domain/meson-gx-pwrc-vpu.c
@@ -14,6 +14,11 @@
 #include <reset.h>
 #include <clk.h>
 
+enum {
+	VPU_PWRC_COMPATIBLE_GX		= 0,
+	VPU_PWRC_COMPATIBLE_G12A	= 1,
+};
+
 /* AO Offsets */
 
 #define AO_RTI_GEN_PWR_SLEEP0		(0x3a << 2)
@@ -26,6 +31,7 @@
 #define HHI_MEM_PD_REG0			(0x40 << 2)
 #define HHI_VPU_MEM_PD_REG0		(0x41 << 2)
 #define HHI_VPU_MEM_PD_REG1		(0x42 << 2)
+#define HHI_VPU_MEM_PD_REG2		(0x4d << 2)
 
 struct meson_gx_pwrc_vpu_priv {
 	struct regmap *regmap_ao;
@@ -34,12 +40,12 @@ struct meson_gx_pwrc_vpu_priv {
 	struct clk_bulk clks;
 };
 
-static int meson_gx_pwrc_vpu_request(struct power_domain *power_domain)
+static int meson_pwrc_vpu_request(struct power_domain *power_domain)
 {
 	return 0;
 }
 
-static int meson_gx_pwrc_vpu_free(struct power_domain *power_domain)
+static int meson_pwrc_vpu_free(struct power_domain *power_domain)
 {
 	return 0;
 }
@@ -91,6 +97,73 @@ static int meson_gx_pwrc_vpu_on(struct power_domain *power_domain)
 	return 0;
 }
 
+static int meson_g12a_pwrc_vpu_on(struct power_domain *power_domain)
+{
+	struct meson_gx_pwrc_vpu_priv *priv = dev_get_priv(power_domain->dev);
+	int i, ret;
+
+	regmap_update_bits(priv->regmap_ao, AO_RTI_GEN_PWR_SLEEP0,
+			   GEN_PWR_VPU_HDMI, 0);
+	udelay(20);
+
+	/* Power Up Memories */
+	for (i = 0; i < 32; i += 2) {
+		regmap_update_bits(priv->regmap_hhi, HHI_VPU_MEM_PD_REG0,
+				   0x3 << i, 0);
+		udelay(5);
+	}
+
+	for (i = 0; i < 32; i += 2) {
+		regmap_update_bits(priv->regmap_hhi, HHI_VPU_MEM_PD_REG1,
+				   0x3 << i, 0);
+		udelay(5);
+	}
+
+	for (i = 0; i < 32; i += 2) {
+		regmap_update_bits(priv->regmap_hhi, HHI_VPU_MEM_PD_REG2,
+				   0x3 << i, 0);
+		udelay(5);
+	}
+
+	for (i = 8; i < 16; i++) {
+		regmap_update_bits(priv->regmap_hhi, HHI_MEM_PD_REG0,
+				   BIT(i), 0);
+		udelay(5);
+	}
+	udelay(20);
+
+	ret = reset_assert_bulk(&priv->resets);
+	if (ret)
+		return ret;
+
+	regmap_update_bits(priv->regmap_ao, AO_RTI_GEN_PWR_SLEEP0,
+			   GEN_PWR_VPU_HDMI_ISO, 0);
+
+	ret = reset_deassert_bulk(&priv->resets);
+	if (ret)
+		return ret;
+
+	ret = clk_enable_bulk(&priv->clks);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static int meson_pwrc_vpu_on(struct power_domain *power_domain)
+{
+	unsigned int compat = dev_get_driver_data(power_domain->dev);
+
+	switch (compat) {
+	case VPU_PWRC_COMPATIBLE_GX:
+		return meson_gx_pwrc_vpu_on(power_domain);
+	case VPU_PWRC_COMPATIBLE_G12A:
+		return meson_g12a_pwrc_vpu_on(power_domain);
+	}
+
+	return -EINVAL;
+}
+
 static int meson_gx_pwrc_vpu_off(struct power_domain *power_domain)
 {
 	struct meson_gx_pwrc_vpu_priv *priv = dev_get_priv(power_domain->dev);
@@ -127,8 +200,63 @@ static int meson_gx_pwrc_vpu_off(struct power_domain *power_domain)
 	return 0;
 }
 
-static int meson_gx_pwrc_vpu_of_xlate(struct power_domain *power_domain,
-				      struct ofnode_phandle_args *args)
+static int meson_g12a_pwrc_vpu_off(struct power_domain *power_domain)
+{
+	struct meson_gx_pwrc_vpu_priv *priv = dev_get_priv(power_domain->dev);
+	int i;
+
+	regmap_update_bits(priv->regmap_ao, AO_RTI_GEN_PWR_SLEEP0,
+			   GEN_PWR_VPU_HDMI_ISO, GEN_PWR_VPU_HDMI_ISO);
+	udelay(20);
+
+	/* Power Down Memories */
+	for (i = 0; i < 32; i += 2) {
+		regmap_update_bits(priv->regmap_hhi, HHI_VPU_MEM_PD_REG0,
+				   0x3 << i, 0x3 << i);
+		udelay(5);
+	}
+	for (i = 0; i < 32; i += 2) {
+		regmap_update_bits(priv->regmap_hhi, HHI_VPU_MEM_PD_REG1,
+				   0x3 << i, 0x3 << i);
+		udelay(5);
+	}
+	for (i = 0; i < 32; i += 2) {
+		regmap_update_bits(priv->regmap_hhi, HHI_VPU_MEM_PD_REG2,
+				   0x3 << i, 0x3 << i);
+		udelay(5);
+	}
+	for (i = 8; i < 16; i++) {
+		regmap_update_bits(priv->regmap_hhi, HHI_MEM_PD_REG0,
+				   BIT(i), BIT(i));
+		udelay(5);
+	}
+	udelay(20);
+
+	regmap_update_bits(priv->regmap_ao, AO_RTI_GEN_PWR_SLEEP0,
+			   GEN_PWR_VPU_HDMI, GEN_PWR_VPU_HDMI);
+	mdelay(20);
+
+	clk_disable_bulk(&priv->clks);
+
+	return 0;
+}
+
+static int meson_pwrc_vpu_off(struct power_domain *power_domain)
+{
+	unsigned int compat = dev_get_driver_data(power_domain->dev);
+
+	switch (compat) {
+	case VPU_PWRC_COMPATIBLE_GX:
+		return meson_gx_pwrc_vpu_off(power_domain);
+	case VPU_PWRC_COMPATIBLE_G12A:
+		return meson_g12a_pwrc_vpu_off(power_domain);
+	}
+
+	return -EINVAL;
+}
+
+static int meson_pwrc_vpu_of_xlate(struct power_domain *power_domain,
+				   struct ofnode_phandle_args *args)
 {
 	/* #power-domain-cells is 0 */
 
@@ -141,15 +269,22 @@ static int meson_gx_pwrc_vpu_of_xlate(struct power_domain *power_domain,
 }
 
 struct power_domain_ops meson_gx_pwrc_vpu_ops = {
-	.free = meson_gx_pwrc_vpu_free,
-	.off = meson_gx_pwrc_vpu_off,
-	.on = meson_gx_pwrc_vpu_on,
-	.request = meson_gx_pwrc_vpu_request,
-	.of_xlate = meson_gx_pwrc_vpu_of_xlate,
+	.free = meson_pwrc_vpu_free,
+	.off = meson_pwrc_vpu_off,
+	.on = meson_pwrc_vpu_on,
+	.request = meson_pwrc_vpu_request,
+	.of_xlate = meson_pwrc_vpu_of_xlate,
 };
 
 static const struct udevice_id meson_gx_pwrc_vpu_ids[] = {
-	{ .compatible = "amlogic,meson-gx-pwrc-vpu" },
+	{
+		.compatible = "amlogic,meson-gx-pwrc-vpu",
+		.data = VPU_PWRC_COMPATIBLE_GX,
+	},
+	{
+		.compatible = "amlogic,meson-g12a-pwrc-vpu",
+		.data = VPU_PWRC_COMPATIBLE_G12A,
+	},
 	{ }
 };
 
-- 
2.22.0

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH 1/8] power: domain: meson-gx-pwrc: add G12A support
@ 2019-08-30 12:09   ` Neil Armstrong
  0 siblings, 0 replies; 38+ messages in thread
From: Neil Armstrong @ 2019-08-30 12:09 UTC (permalink / raw)
  To: u-boot-amlogic, jh80.chung; +Cc: Neil Armstrong, u-boot

Add Amlogic G12A support for the gx-pwrc driver, aligned on the
Linux v5.2 driver.

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 drivers/power/domain/meson-gx-pwrc-vpu.c | 155 +++++++++++++++++++++--
 1 file changed, 145 insertions(+), 10 deletions(-)

diff --git a/drivers/power/domain/meson-gx-pwrc-vpu.c b/drivers/power/domain/meson-gx-pwrc-vpu.c
index d631d3e6ff..f44e33bacb 100644
--- a/drivers/power/domain/meson-gx-pwrc-vpu.c
+++ b/drivers/power/domain/meson-gx-pwrc-vpu.c
@@ -14,6 +14,11 @@
 #include <reset.h>
 #include <clk.h>
 
+enum {
+	VPU_PWRC_COMPATIBLE_GX		= 0,
+	VPU_PWRC_COMPATIBLE_G12A	= 1,
+};
+
 /* AO Offsets */
 
 #define AO_RTI_GEN_PWR_SLEEP0		(0x3a << 2)
@@ -26,6 +31,7 @@
 #define HHI_MEM_PD_REG0			(0x40 << 2)
 #define HHI_VPU_MEM_PD_REG0		(0x41 << 2)
 #define HHI_VPU_MEM_PD_REG1		(0x42 << 2)
+#define HHI_VPU_MEM_PD_REG2		(0x4d << 2)
 
 struct meson_gx_pwrc_vpu_priv {
 	struct regmap *regmap_ao;
@@ -34,12 +40,12 @@ struct meson_gx_pwrc_vpu_priv {
 	struct clk_bulk clks;
 };
 
-static int meson_gx_pwrc_vpu_request(struct power_domain *power_domain)
+static int meson_pwrc_vpu_request(struct power_domain *power_domain)
 {
 	return 0;
 }
 
-static int meson_gx_pwrc_vpu_free(struct power_domain *power_domain)
+static int meson_pwrc_vpu_free(struct power_domain *power_domain)
 {
 	return 0;
 }
@@ -91,6 +97,73 @@ static int meson_gx_pwrc_vpu_on(struct power_domain *power_domain)
 	return 0;
 }
 
+static int meson_g12a_pwrc_vpu_on(struct power_domain *power_domain)
+{
+	struct meson_gx_pwrc_vpu_priv *priv = dev_get_priv(power_domain->dev);
+	int i, ret;
+
+	regmap_update_bits(priv->regmap_ao, AO_RTI_GEN_PWR_SLEEP0,
+			   GEN_PWR_VPU_HDMI, 0);
+	udelay(20);
+
+	/* Power Up Memories */
+	for (i = 0; i < 32; i += 2) {
+		regmap_update_bits(priv->regmap_hhi, HHI_VPU_MEM_PD_REG0,
+				   0x3 << i, 0);
+		udelay(5);
+	}
+
+	for (i = 0; i < 32; i += 2) {
+		regmap_update_bits(priv->regmap_hhi, HHI_VPU_MEM_PD_REG1,
+				   0x3 << i, 0);
+		udelay(5);
+	}
+
+	for (i = 0; i < 32; i += 2) {
+		regmap_update_bits(priv->regmap_hhi, HHI_VPU_MEM_PD_REG2,
+				   0x3 << i, 0);
+		udelay(5);
+	}
+
+	for (i = 8; i < 16; i++) {
+		regmap_update_bits(priv->regmap_hhi, HHI_MEM_PD_REG0,
+				   BIT(i), 0);
+		udelay(5);
+	}
+	udelay(20);
+
+	ret = reset_assert_bulk(&priv->resets);
+	if (ret)
+		return ret;
+
+	regmap_update_bits(priv->regmap_ao, AO_RTI_GEN_PWR_SLEEP0,
+			   GEN_PWR_VPU_HDMI_ISO, 0);
+
+	ret = reset_deassert_bulk(&priv->resets);
+	if (ret)
+		return ret;
+
+	ret = clk_enable_bulk(&priv->clks);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static int meson_pwrc_vpu_on(struct power_domain *power_domain)
+{
+	unsigned int compat = dev_get_driver_data(power_domain->dev);
+
+	switch (compat) {
+	case VPU_PWRC_COMPATIBLE_GX:
+		return meson_gx_pwrc_vpu_on(power_domain);
+	case VPU_PWRC_COMPATIBLE_G12A:
+		return meson_g12a_pwrc_vpu_on(power_domain);
+	}
+
+	return -EINVAL;
+}
+
 static int meson_gx_pwrc_vpu_off(struct power_domain *power_domain)
 {
 	struct meson_gx_pwrc_vpu_priv *priv = dev_get_priv(power_domain->dev);
@@ -127,8 +200,63 @@ static int meson_gx_pwrc_vpu_off(struct power_domain *power_domain)
 	return 0;
 }
 
-static int meson_gx_pwrc_vpu_of_xlate(struct power_domain *power_domain,
-				      struct ofnode_phandle_args *args)
+static int meson_g12a_pwrc_vpu_off(struct power_domain *power_domain)
+{
+	struct meson_gx_pwrc_vpu_priv *priv = dev_get_priv(power_domain->dev);
+	int i;
+
+	regmap_update_bits(priv->regmap_ao, AO_RTI_GEN_PWR_SLEEP0,
+			   GEN_PWR_VPU_HDMI_ISO, GEN_PWR_VPU_HDMI_ISO);
+	udelay(20);
+
+	/* Power Down Memories */
+	for (i = 0; i < 32; i += 2) {
+		regmap_update_bits(priv->regmap_hhi, HHI_VPU_MEM_PD_REG0,
+				   0x3 << i, 0x3 << i);
+		udelay(5);
+	}
+	for (i = 0; i < 32; i += 2) {
+		regmap_update_bits(priv->regmap_hhi, HHI_VPU_MEM_PD_REG1,
+				   0x3 << i, 0x3 << i);
+		udelay(5);
+	}
+	for (i = 0; i < 32; i += 2) {
+		regmap_update_bits(priv->regmap_hhi, HHI_VPU_MEM_PD_REG2,
+				   0x3 << i, 0x3 << i);
+		udelay(5);
+	}
+	for (i = 8; i < 16; i++) {
+		regmap_update_bits(priv->regmap_hhi, HHI_MEM_PD_REG0,
+				   BIT(i), BIT(i));
+		udelay(5);
+	}
+	udelay(20);
+
+	regmap_update_bits(priv->regmap_ao, AO_RTI_GEN_PWR_SLEEP0,
+			   GEN_PWR_VPU_HDMI, GEN_PWR_VPU_HDMI);
+	mdelay(20);
+
+	clk_disable_bulk(&priv->clks);
+
+	return 0;
+}
+
+static int meson_pwrc_vpu_off(struct power_domain *power_domain)
+{
+	unsigned int compat = dev_get_driver_data(power_domain->dev);
+
+	switch (compat) {
+	case VPU_PWRC_COMPATIBLE_GX:
+		return meson_gx_pwrc_vpu_off(power_domain);
+	case VPU_PWRC_COMPATIBLE_G12A:
+		return meson_g12a_pwrc_vpu_off(power_domain);
+	}
+
+	return -EINVAL;
+}
+
+static int meson_pwrc_vpu_of_xlate(struct power_domain *power_domain,
+				   struct ofnode_phandle_args *args)
 {
 	/* #power-domain-cells is 0 */
 
@@ -141,15 +269,22 @@ static int meson_gx_pwrc_vpu_of_xlate(struct power_domain *power_domain,
 }
 
 struct power_domain_ops meson_gx_pwrc_vpu_ops = {
-	.free = meson_gx_pwrc_vpu_free,
-	.off = meson_gx_pwrc_vpu_off,
-	.on = meson_gx_pwrc_vpu_on,
-	.request = meson_gx_pwrc_vpu_request,
-	.of_xlate = meson_gx_pwrc_vpu_of_xlate,
+	.free = meson_pwrc_vpu_free,
+	.off = meson_pwrc_vpu_off,
+	.on = meson_pwrc_vpu_on,
+	.request = meson_pwrc_vpu_request,
+	.of_xlate = meson_pwrc_vpu_of_xlate,
 };
 
 static const struct udevice_id meson_gx_pwrc_vpu_ids[] = {
-	{ .compatible = "amlogic,meson-gx-pwrc-vpu" },
+	{
+		.compatible = "amlogic,meson-gx-pwrc-vpu",
+		.data = VPU_PWRC_COMPATIBLE_GX,
+	},
+	{
+		.compatible = "amlogic,meson-g12a-pwrc-vpu",
+		.data = VPU_PWRC_COMPATIBLE_G12A,
+	},
 	{ }
 };
 
-- 
2.22.0


^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [U-Boot] [PATCH 2/8] clk: meson: g12a: add support for VPU/HDMI clocks
  2019-08-30 12:09 ` Neil Armstrong
@ 2019-08-30 12:09   ` Neil Armstrong
  -1 siblings, 0 replies; 38+ messages in thread
From: Neil Armstrong @ 2019-08-30 12:09 UTC (permalink / raw)
  To: u-boot

Add necessary clock support to set up clock for the VPU and
HDMI support.

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 drivers/clk/meson/g12a.c | 620 +++++++++++++++++++++++++++++++++++++--
 1 file changed, 603 insertions(+), 17 deletions(-)

diff --git a/drivers/clk/meson/g12a.c b/drivers/clk/meson/g12a.c
index 43dac1aa37..c03738b6ca 100644
--- a/drivers/clk/meson/g12a.c
+++ b/drivers/clk/meson/g12a.c
@@ -14,16 +14,93 @@
 #include <syscon.h>
 #include <div64.h>
 #include <dt-bindings/clock/g12a-clkc.h>
+#include <linux/kernel.h>
 #include "clk_meson.h"
 
+/* This driver support only basic clock tree operations :
+ * - Can calculate clock frequency on a limited tree
+ * - Can Read muxes and basic dividers (0-based only)
+ * - Can enable/disable gates with limited propagation
+ * - Can reparent without propagation, only on muxes
+ * - Can set rates without reparenting
+ * This driver is adapted to what is actually supported by U-Boot
+ */
+
+/* Only the clocks ids we don't want to expose, such as the internal muxes
+ * and dividers of composite clocks, will remain defined here.
+ */
+#define CLKID_MPEG_SEL				8
+#define CLKID_MPEG_DIV				9
+#define CLKID_SD_EMMC_A_CLK0_SEL		63
+#define CLKID_SD_EMMC_A_CLK0_DIV		64
+#define CLKID_SD_EMMC_B_CLK0_SEL		65
+#define CLKID_SD_EMMC_B_CLK0_DIV		66
+#define CLKID_SD_EMMC_C_CLK0_SEL		67
+#define CLKID_SD_EMMC_C_CLK0_DIV		68
+#define CLKID_MPLL0_DIV				69
+#define CLKID_MPLL1_DIV				70
+#define CLKID_MPLL2_DIV				71
+#define CLKID_MPLL3_DIV				72
+#define CLKID_MPLL_PREDIV			73
+#define CLKID_FCLK_DIV2_DIV			75
+#define CLKID_FCLK_DIV3_DIV			76
+#define CLKID_FCLK_DIV4_DIV			77
+#define CLKID_FCLK_DIV5_DIV			78
+#define CLKID_FCLK_DIV7_DIV			79
+#define CLKID_FCLK_DIV2P5_DIV			100
+#define CLKID_FIXED_PLL_DCO			101
+#define CLKID_SYS_PLL_DCO			102
+#define CLKID_GP0_PLL_DCO			103
+#define CLKID_HIFI_PLL_DCO			104
+#define CLKID_VPU_0_DIV				111
+#define CLKID_VPU_1_DIV				114
+#define CLKID_VAPB_0_DIV			118
+#define CLKID_VAPB_1_DIV			121
+#define CLKID_HDMI_PLL_DCO			125
+#define CLKID_HDMI_PLL_OD			126
+#define CLKID_HDMI_PLL_OD2			127
+#define CLKID_VID_PLL_SEL			130
+#define CLKID_VID_PLL_DIV			131
+#define CLKID_VCLK_SEL				132
+#define CLKID_VCLK2_SEL				133
+#define CLKID_VCLK_INPUT			134
+#define CLKID_VCLK2_INPUT			135
+#define CLKID_VCLK_DIV				136
+#define CLKID_VCLK2_DIV				137
+#define CLKID_VCLK_DIV2_EN			140
+#define CLKID_VCLK_DIV4_EN			141
+#define CLKID_VCLK_DIV6_EN			142
+#define CLKID_VCLK_DIV12_EN			143
+#define CLKID_VCLK2_DIV2_EN			144
+#define CLKID_VCLK2_DIV4_EN			145
+#define CLKID_VCLK2_DIV6_EN			146
+#define CLKID_VCLK2_DIV12_EN			147
+#define CLKID_CTS_ENCI_SEL			158
+#define CLKID_CTS_ENCP_SEL			159
+#define CLKID_CTS_VDAC_SEL			160
+#define CLKID_HDMI_TX_SEL			161
+#define CLKID_HDMI_SEL				166
+#define CLKID_HDMI_DIV				167
+#define CLKID_MALI_0_DIV			170
+#define CLKID_MALI_1_DIV			173
+
+#define CLKID_XTAL				0x10000000
+
 #define XTAL_RATE 24000000
 
 struct meson_clk {
 	struct regmap *map;
 };
 
+static ulong meson_div_get_rate(struct clk *clk, unsigned long id);
+static ulong meson_div_set_rate(struct clk *clk, unsigned long id, ulong rate,
+				ulong current_rate);
+static ulong meson_mux_set_parent(struct clk *clk, unsigned long id,
+				  unsigned long parent_id);
+static ulong meson_mux_get_rate(struct clk *clk, unsigned long id);
 static ulong meson_clk_set_rate_by_id(struct clk *clk, unsigned long id,
 				      ulong rate, ulong current_rate);
+static ulong meson_mux_get_parent(struct clk *clk, unsigned long id);
 static ulong meson_clk_get_rate_by_id(struct clk *clk, unsigned long id);
 
 #define NUM_CLKS 178
@@ -39,40 +116,447 @@ static struct meson_gate gates[NUM_CLKS] = {
 	MESON_GATE(CLKID_ETH, HHI_GCLK_MPEG1, 3),
 	MESON_GATE(CLKID_UART1, HHI_GCLK_MPEG1, 16),
 	MESON_GATE(CLKID_USB, HHI_GCLK_MPEG1, 25),
+	MESON_GATE(CLKID_HTX_PCLK, HHI_GCLK_MPEG2, 4),
 	MESON_GATE(CLKID_USB1_DDR_BRIDGE, HHI_GCLK_MPEG2, 8),
+	MESON_GATE(CLKID_VPU_INTR, HHI_GCLK_MPEG2, 25),
 
 	/* Peripheral Gates */
+	MESON_GATE(CLKID_FCLK_DIV2, HHI_FIX_PLL_CNTL1, 24),
+	MESON_GATE(CLKID_FCLK_DIV3, HHI_FIX_PLL_CNTL1, 20),
+	MESON_GATE(CLKID_FCLK_DIV4, HHI_FIX_PLL_CNTL1, 21),
+	MESON_GATE(CLKID_FCLK_DIV5, HHI_FIX_PLL_CNTL1, 22),
+	MESON_GATE(CLKID_FCLK_DIV7, HHI_FIX_PLL_CNTL1, 23),
 	MESON_GATE(CLKID_SD_EMMC_B_CLK0, HHI_SD_EMMC_CLK_CNTL, 23),
 	MESON_GATE(CLKID_SD_EMMC_C_CLK0, HHI_NAND_CLK_CNTL, 7),
+	MESON_GATE(CLKID_VPU_0, HHI_VPU_CLK_CNTL, 8),
+	MESON_GATE(CLKID_VPU_1, HHI_VPU_CLK_CNTL, 24),
+	MESON_GATE(CLKID_VAPB_0, HHI_VAPBCLK_CNTL, 8),
+	MESON_GATE(CLKID_VAPB_1, HHI_VAPBCLK_CNTL, 24),
+	MESON_GATE(CLKID_VAPB, HHI_VAPBCLK_CNTL, 30),
+	MESON_GATE(CLKID_HDMI, HHI_HDMI_CLK_CNTL, 8),
 };
 
-static int meson_set_gate(struct clk *clk, bool on)
+static int meson_set_gate_by_id(struct clk *clk, unsigned long id, bool on)
 {
 	struct meson_clk *priv = dev_get_priv(clk->dev);
 	struct meson_gate *gate;
 
-	if (clk->id >= ARRAY_SIZE(gates))
+	debug("%s: %sabling %ld\n", __func__, on ? "en" : "dis", id);
+
+	/* Propagate through muxes */
+	switch (id) {
+	case CLKID_VPU:
+		return meson_set_gate_by_id(clk,
+				meson_mux_get_parent(clk, CLKID_VPU), on);
+	case CLKID_VAPB_SEL:
+		return meson_set_gate_by_id(clk,
+				meson_mux_get_parent(clk, CLKID_VAPB_SEL), on);
+	}
+
+	if (id >= ARRAY_SIZE(gates))
 		return -ENOENT;
 
-	gate = &gates[clk->id];
+	gate = &gates[id];
 
 	if (gate->reg == 0)
 		return 0;
 
+	debug("%s: really %sabling %ld\n", __func__, on ? "en" : "dis", id);
+
 	regmap_update_bits(priv->map, gate->reg,
 			   BIT(gate->bit), on ? BIT(gate->bit) : 0);
 
+	/* Propagate to next gate(s) */
+	switch (id) {
+	case CLKID_VAPB:
+		return meson_set_gate_by_id(clk, CLKID_VAPB_SEL, on);
+	case CLKID_VAPB_0:
+		return meson_set_gate_by_id(clk,
+			meson_mux_get_parent(clk, CLKID_VAPB_0_SEL), on);
+	case CLKID_VAPB_1:
+		return meson_set_gate_by_id(clk,
+			meson_mux_get_parent(clk, CLKID_VAPB_0_SEL), on);
+	case CLKID_VPU_0:
+		return meson_set_gate_by_id(clk,
+			meson_mux_get_parent(clk, CLKID_VPU_0_SEL), on);
+	case CLKID_VPU_1:
+		return meson_set_gate_by_id(clk,
+			meson_mux_get_parent(clk, CLKID_VPU_1_SEL), on);
+	}
+
 	return 0;
 }
 
 static int meson_clk_enable(struct clk *clk)
 {
-	return meson_set_gate(clk, true);
+	return meson_set_gate_by_id(clk, clk->id, true);
 }
 
 static int meson_clk_disable(struct clk *clk)
 {
-	return meson_set_gate(clk, false);
+	return meson_set_gate_by_id(clk, clk->id, false);
+}
+
+static struct parm meson_vpu_0_div_parm = {
+	HHI_VPU_CLK_CNTL, 0, 7,
+};
+
+int meson_vpu_0_div_parent = CLKID_VPU_0_SEL;
+
+static struct parm meson_vpu_1_div_parm = {
+	HHI_VPU_CLK_CNTL, 16, 7,
+};
+
+int meson_vpu_1_div_parent = CLKID_VPU_1_SEL;
+
+static struct parm meson_vapb_0_div_parm = {
+	HHI_VAPBCLK_CNTL, 0, 7,
+};
+
+int meson_vapb_0_div_parent = CLKID_VAPB_0_SEL;
+
+static struct parm meson_vapb_1_div_parm = {
+	HHI_VAPBCLK_CNTL, 16, 7,
+};
+
+int meson_vapb_1_div_parent = CLKID_VAPB_1_SEL;
+
+static struct parm meson_hdmi_div_parm = {
+	HHI_HDMI_CLK_CNTL, 0, 7,
+};
+
+int meson_hdmi_div_parent = CLKID_HDMI_SEL;
+
+static ulong meson_div_get_rate(struct clk *clk, unsigned long id)
+{
+	struct meson_clk *priv = dev_get_priv(clk->dev);
+	unsigned int rate, parent_rate;
+	struct parm *parm;
+	int parent;
+	uint reg;
+
+	switch (id) {
+	case CLKID_VPU_0_DIV:
+		parm = &meson_vpu_0_div_parm;
+		parent = meson_vpu_0_div_parent;
+		break;
+	case CLKID_VPU_1_DIV:
+		parm = &meson_vpu_1_div_parm;
+		parent = meson_vpu_1_div_parent;
+		break;
+	case CLKID_VAPB_0_DIV:
+		parm = &meson_vapb_0_div_parm;
+		parent = meson_vapb_0_div_parent;
+		break;
+	case CLKID_VAPB_1_DIV:
+		parm = &meson_vapb_1_div_parm;
+		parent = meson_vapb_1_div_parent;
+		break;
+	case CLKID_HDMI_DIV:
+		parm = &meson_hdmi_div_parm;
+		parent = meson_hdmi_div_parent;
+		break;
+	default:
+		return -ENOENT;
+	}
+
+	regmap_read(priv->map, parm->reg_off, &reg);
+	reg = PARM_GET(parm->width, parm->shift, reg);
+
+	debug("%s: div of %ld is %d\n", __func__, id, reg + 1);
+
+	parent_rate = meson_clk_get_rate_by_id(clk, parent);
+	if (IS_ERR_VALUE(parent_rate))
+		return parent_rate;
+
+	debug("%s: parent rate of %ld is %d\n", __func__, id, parent_rate);
+
+	rate = parent_rate / (reg + 1);
+
+	debug("%s: rate of %ld is %d\n", __func__, id, rate);
+
+	return rate;
+}
+
+static ulong meson_div_set_rate(struct clk *clk, unsigned long id, ulong rate,
+				ulong current_rate)
+{
+	struct meson_clk *priv = dev_get_priv(clk->dev);
+	unsigned int new_div = -EINVAL;
+	unsigned long parent_rate;
+	struct parm *parm;
+	int parent;
+	int ret;
+
+	if (current_rate == rate)
+		return 0;
+
+	debug("%s: setting rate of %ld from %ld to %ld\n",
+	      __func__, id, current_rate, rate);
+
+	switch (id) {
+	case CLKID_VPU_0_DIV:
+		parm = &meson_vpu_0_div_parm;
+		parent = meson_vpu_0_div_parent;
+		break;
+	case CLKID_VPU_1_DIV:
+		parm = &meson_vpu_1_div_parm;
+		parent = meson_vpu_1_div_parent;
+		break;
+	case CLKID_VAPB_0_DIV:
+		parm = &meson_vapb_0_div_parm;
+		parent = meson_vapb_0_div_parent;
+		break;
+	case CLKID_VAPB_1_DIV:
+		parm = &meson_vapb_1_div_parm;
+		parent = meson_vapb_1_div_parent;
+		break;
+	case CLKID_HDMI_DIV:
+		parm = &meson_hdmi_div_parm;
+		parent = meson_hdmi_div_parent;
+		break;
+	default:
+		return -ENOENT;
+	}
+
+	parent_rate = meson_clk_get_rate_by_id(clk, parent);
+	if (IS_ERR_VALUE(parent_rate))
+		return parent_rate;
+
+	debug("%s: parent rate of %ld is %ld\n", __func__, id, parent_rate);
+
+	/* If can't divide, set parent instead */
+	if (!parent_rate || rate > parent_rate)
+		return meson_clk_set_rate_by_id(clk, parent, rate,
+						current_rate);
+
+	new_div = DIV_ROUND_CLOSEST(parent_rate, rate);
+
+	debug("%s: new div of %ld is %d\n", __func__, id, new_div);
+
+	/* If overflow, try to set parent rate and retry */
+	if (!new_div || new_div > (1 << parm->width)) {
+		ret = meson_clk_set_rate_by_id(clk, parent, rate, current_rate);
+		if (IS_ERR_VALUE(ret))
+			return ret;
+
+		parent_rate = meson_clk_get_rate_by_id(clk, parent);
+		if (IS_ERR_VALUE(parent_rate))
+			return parent_rate;
+
+		new_div = DIV_ROUND_CLOSEST(parent_rate, rate);
+
+		debug("%s: new new div of %ld is %d\n", __func__, id, new_div);
+
+		if (!new_div || new_div > (1 << parm->width))
+			return -EINVAL;
+	}
+
+	debug("%s: setting div of %ld to %d\n", __func__, id, new_div);
+
+	regmap_update_bits(priv->map, parm->reg_off,
+			   SETPMASK(parm->width, parm->shift),
+			   (new_div - 1) << parm->shift);
+
+	debug("%s: new rate of %ld is %ld\n",
+	      __func__, id, meson_div_get_rate(clk, id));
+
+	return 0;
+}
+
+static struct parm meson_vpu_mux_parm = {
+	HHI_VPU_CLK_CNTL, 31, 1,
+};
+
+int meson_vpu_mux_parents[] = {
+	CLKID_VPU_0,
+	CLKID_VPU_1,
+};
+
+static struct parm meson_vpu_0_mux_parm = {
+	HHI_VPU_CLK_CNTL, 9, 3,
+};
+
+static struct parm meson_vpu_1_mux_parm = {
+	HHI_VPU_CLK_CNTL, 25, 3,
+};
+
+static int meson_vpu_0_1_mux_parents[] = {
+	CLKID_FCLK_DIV3,
+	CLKID_FCLK_DIV4,
+	CLKID_FCLK_DIV5,
+	CLKID_FCLK_DIV7,
+	-ENOENT,
+	-ENOENT,
+	-ENOENT,
+	-ENOENT,
+};
+
+static struct parm meson_vapb_sel_mux_parm = {
+	HHI_VAPBCLK_CNTL, 31, 1,
+};
+
+int meson_vapb_sel_mux_parents[] = {
+	CLKID_VAPB_0,
+	CLKID_VAPB_1,
+};
+
+static struct parm meson_vapb_0_mux_parm = {
+	HHI_VAPBCLK_CNTL, 9, 2,
+};
+
+static struct parm meson_vapb_1_mux_parm = {
+	HHI_VAPBCLK_CNTL, 25, 2,
+};
+
+static int meson_vapb_0_1_mux_parents[] = {
+	CLKID_FCLK_DIV4,
+	CLKID_FCLK_DIV3,
+	CLKID_FCLK_DIV5,
+	CLKID_FCLK_DIV7,
+};
+
+static struct parm meson_hdmi_mux_parm = {
+	HHI_HDMI_CLK_CNTL, 9, 2,
+};
+
+static int meson_hdmi_mux_parents[] = {
+	CLKID_XTAL,
+	CLKID_FCLK_DIV4,
+	CLKID_FCLK_DIV3,
+	CLKID_FCLK_DIV5,
+};
+
+static ulong meson_mux_get_parent(struct clk *clk, unsigned long id)
+{
+	struct meson_clk *priv = dev_get_priv(clk->dev);
+	struct parm *parm;
+	int *parents;
+	uint reg;
+
+	switch (id) {
+	case CLKID_VPU:
+		parm = &meson_vpu_mux_parm;
+		parents = meson_vpu_mux_parents;
+		break;
+	case CLKID_VPU_0_SEL:
+		parm = &meson_vpu_0_mux_parm;
+		parents = meson_vpu_0_1_mux_parents;
+		break;
+	case CLKID_VPU_1_SEL:
+		parm = &meson_vpu_1_mux_parm;
+		parents = meson_vpu_0_1_mux_parents;
+		break;
+	case CLKID_VAPB_SEL:
+		parm = &meson_vapb_sel_mux_parm;
+		parents = meson_vapb_sel_mux_parents;
+		break;
+	case CLKID_VAPB_0_SEL:
+		parm = &meson_vapb_0_mux_parm;
+		parents = meson_vapb_0_1_mux_parents;
+		break;
+	case CLKID_VAPB_1_SEL:
+		parm = &meson_vapb_1_mux_parm;
+		parents = meson_vapb_0_1_mux_parents;
+		break;
+	case CLKID_HDMI_SEL:
+		parm = &meson_hdmi_mux_parm;
+		parents = meson_hdmi_mux_parents;
+		break;
+	default:
+		return -ENOENT;
+	}
+
+	regmap_read(priv->map, parm->reg_off, &reg);
+	reg = PARM_GET(parm->width, parm->shift, reg);
+
+	debug("%s: parent of %ld is %d (%d)\n",
+	      __func__, id, parents[reg], reg);
+
+	return parents[reg];
+}
+
+static ulong meson_mux_set_parent(struct clk *clk, unsigned long id,
+				  unsigned long parent_id)
+{
+	unsigned long cur_parent = meson_mux_get_parent(clk, id);
+	struct meson_clk *priv = dev_get_priv(clk->dev);
+	unsigned int new_index = -EINVAL;
+	struct parm *parm;
+	int *parents;
+	int i;
+
+	if (IS_ERR_VALUE(cur_parent))
+		return cur_parent;
+
+	debug("%s: setting parent of %ld from %ld to %ld\n",
+	      __func__, id, cur_parent, parent_id);
+
+	if (cur_parent == parent_id)
+		return 0;
+
+	switch (id) {
+	case CLKID_VPU:
+		parm = &meson_vpu_mux_parm;
+		parents = meson_vpu_mux_parents;
+		break;
+	case CLKID_VPU_0_SEL:
+		parm = &meson_vpu_0_mux_parm;
+		parents = meson_vpu_0_1_mux_parents;
+		break;
+	case CLKID_VPU_1_SEL:
+		parm = &meson_vpu_1_mux_parm;
+		parents = meson_vpu_0_1_mux_parents;
+		break;
+	case CLKID_VAPB_SEL:
+		parm = &meson_vapb_sel_mux_parm;
+		parents = meson_vapb_sel_mux_parents;
+		break;
+	case CLKID_VAPB_0_SEL:
+		parm = &meson_vapb_0_mux_parm;
+		parents = meson_vapb_0_1_mux_parents;
+		break;
+	case CLKID_VAPB_1_SEL:
+		parm = &meson_vapb_1_mux_parm;
+		parents = meson_vapb_0_1_mux_parents;
+		break;
+	case CLKID_HDMI_SEL:
+		parm = &meson_hdmi_mux_parm;
+		parents = meson_hdmi_mux_parents;
+		break;
+	default:
+		/* Not a mux */
+		return -ENOENT;
+	}
+
+	for (i = 0 ; i < (1 << parm->width) ; ++i) {
+		if (parents[i] == parent_id)
+			new_index = i;
+	}
+
+	if (IS_ERR_VALUE(new_index))
+		return new_index;
+
+	debug("%s: new index of %ld is %d\n", __func__, id, new_index);
+
+	regmap_update_bits(priv->map, parm->reg_off,
+			   SETPMASK(parm->width, parm->shift),
+			   new_index << parm->shift);
+
+	debug("%s: new parent of %ld is %ld\n",
+	      __func__, id, meson_mux_get_parent(clk, id));
+
+	return 0;
+}
+
+static ulong meson_mux_get_rate(struct clk *clk, unsigned long id)
+{
+	int parent = meson_mux_get_parent(clk, id);
+
+	if (IS_ERR_VALUE(parent))
+		return parent;
+
+	return meson_clk_get_rate_by_id(clk, parent);
 }
 
 static unsigned long meson_clk81_get_rate(struct clk *clk)
@@ -81,7 +565,7 @@ static unsigned long meson_clk81_get_rate(struct clk *clk)
 	unsigned long parent_rate;
 	uint reg;
 	int parents[] = {
-		-1,
+		CLKID_XTAL,
 		-1,
 		CLKID_FCLK_DIV7,
 		CLKID_MPLL1,
@@ -96,9 +580,6 @@ static unsigned long meson_clk81_get_rate(struct clk *clk)
 	reg = (reg >> 12) & 7;
 
 	switch (reg) {
-	case 0:
-		parent_rate = XTAL_RATE;
-		break;
 	case 1:
 		return -ENOENT;
 	default:
@@ -183,24 +664,26 @@ static ulong meson_mpll_get_rate(struct clk *clk, unsigned long id)
 	return mpll_rate_from_params(parent_rate, sdm, n2);
 }
 
-static struct parm meson_fixed_pll_parm[3] = {
-	{HHI_FIX_PLL_CNTL0, 0, 8}, /* pm */
+static struct parm meson_fixed_pll_parm[4] = {
+	{HHI_FIX_PLL_CNTL0, 0, 9}, /* pm */
 	{HHI_FIX_PLL_CNTL0, 10, 5}, /* pn */
 	{HHI_FIX_PLL_CNTL0, 16, 2}, /* pod */
+	{HHI_FIX_PLL_CNTL1, 0, 17}, /* pfrac */
 };
 
 static struct parm meson_sys_pll_parm[3] = {
-	{HHI_SYS_PLL_CNTL0, 0, 8}, /* pm */
+	{HHI_SYS_PLL_CNTL0, 0, 9}, /* pm */
 	{HHI_SYS_PLL_CNTL0, 10, 5}, /* pn */
-	{HHI_SYS_PLL_CNTL0, 16, 2}, /* pod */
+	{HHI_SYS_PLL_CNTL0, 16, 3}, /* pod */
 };
 
 static ulong meson_pll_get_rate(struct clk *clk, unsigned long id)
 {
 	struct meson_clk *priv = dev_get_priv(clk->dev);
-	struct parm *pm, *pn, *pod;
+	struct parm *pm, *pn, *pod, *pfrac = NULL;
 	unsigned long parent_rate_mhz = XTAL_RATE / 1000000;
-	u16 n, m, od;
+	u16 n, m, od, frac;
+	ulong rate;
 	uint reg;
 
 	/*
@@ -213,6 +696,7 @@ static ulong meson_pll_get_rate(struct clk *clk, unsigned long id)
 		pm = &meson_fixed_pll_parm[0];
 		pn = &meson_fixed_pll_parm[1];
 		pod = &meson_fixed_pll_parm[2];
+		pfrac = &meson_fixed_pll_parm[3];
 		break;
 	case CLKID_SYS_PLL:
 		pm = &meson_sys_pll_parm[0];
@@ -232,7 +716,24 @@ static ulong meson_pll_get_rate(struct clk *clk, unsigned long id)
 	regmap_read(priv->map, pod->reg_off, &reg);
 	od = PARM_GET(pod->width, pod->shift, reg);
 
-	return ((parent_rate_mhz * m / n) >> od) * 1000000;
+	rate = parent_rate_mhz * m;
+
+	if (pfrac) {
+		ulong frac_rate;
+
+		regmap_read(priv->map, pfrac->reg_off, &reg);
+		frac = PARM_GET(pfrac->width - 1, pfrac->shift, reg);
+
+		frac_rate = DIV_ROUND_UP_ULL((u64)parent_rate_mhz * frac,
+					     1 << (pfrac->width - 2));
+
+		if (frac & BIT(pfrac->width - 1))
+			rate -= frac_rate;
+		else
+			rate += frac_rate;
+	}
+
+	return (DIV_ROUND_UP_ULL(rate, n) >> od) * 1000000;
 }
 
 static struct parm meson_pcie_pll_parm[3] = {
@@ -270,6 +771,9 @@ static ulong meson_clk_get_rate_by_id(struct clk *clk, unsigned long id)
 	ulong rate;
 
 	switch (id) {
+	case CLKID_XTAL:
+		rate = XTAL_RATE;
+		break;
 	case CLKID_FIXED_PLL:
 	case CLKID_SYS_PLL:
 		rate = meson_pll_get_rate(clk, id);
@@ -299,6 +803,39 @@ static ulong meson_clk_get_rate_by_id(struct clk *clk, unsigned long id)
 		break;
 	case CLKID_PCIE_PLL:
 		rate = meson_pcie_pll_get_rate(clk);
+	case CLKID_VPU_0:
+		rate = meson_div_get_rate(clk, CLKID_VPU_0_DIV);
+		break;
+	case CLKID_VPU_1:
+		rate = meson_div_get_rate(clk, CLKID_VPU_1_DIV);
+		break;
+	case CLKID_VAPB:
+		rate = meson_mux_get_rate(clk, CLKID_VAPB_SEL);
+		break;
+	case CLKID_VAPB_0:
+		rate = meson_div_get_rate(clk, CLKID_VAPB_0_DIV);
+		break;
+	case CLKID_VAPB_1:
+		rate = meson_div_get_rate(clk, CLKID_VAPB_1_DIV);
+		break;
+	case CLKID_HDMI:
+		rate = meson_div_get_rate(clk, CLKID_HDMI_DIV);
+		break;
+	case CLKID_VPU_0_DIV:
+	case CLKID_VPU_1_DIV:
+	case CLKID_VAPB_0_DIV:
+	case CLKID_VAPB_1_DIV:
+	case CLKID_HDMI_DIV:
+		rate = meson_div_get_rate(clk, id);
+		break;
+	case CLKID_VPU:
+	case CLKID_VPU_0_SEL:
+	case CLKID_VPU_1_SEL:
+	case CLKID_VAPB_SEL:
+	case CLKID_VAPB_0_SEL:
+	case CLKID_VAPB_1_SEL:
+	case CLKID_HDMI_SEL:
+		rate = meson_mux_get_rate(clk, id);
 		break;
 	default:
 		if (gates[id].reg != 0) {
@@ -343,6 +880,11 @@ static ulong meson_pcie_pll_set_rate(struct clk *clk, ulong rate)
 	return 100000000;
 }
 
+static int meson_clk_set_parent(struct clk *clk, struct clk *parent)
+{
+	return meson_mux_set_parent(clk, clk->id, parent->id);
+}
+
 static ulong meson_clk_set_rate_by_id(struct clk *clk, unsigned long id,
 				      ulong rate, ulong current_rate)
 {
@@ -351,9 +893,53 @@ static ulong meson_clk_set_rate_by_id(struct clk *clk, unsigned long id,
 
 	switch (id) {
 	/* Fixed clocks */
+	case CLKID_FIXED_PLL:
+	case CLKID_SYS_PLL:
+	case CLKID_FCLK_DIV2:
+	case CLKID_FCLK_DIV3:
+	case CLKID_FCLK_DIV4:
+	case CLKID_FCLK_DIV5:
+	case CLKID_FCLK_DIV7:
+	case CLKID_MPLL0:
+	case CLKID_MPLL1:
+	case CLKID_MPLL2:
+	case CLKID_CLK81:
+		if (current_rate != rate)
+			return -EINVAL;
 	case CLKID_PCIE_PLL:
 		return meson_pcie_pll_set_rate(clk, rate);
 
+		return 0;
+	case CLKID_VPU:
+		return meson_clk_set_rate_by_id(clk,
+				meson_mux_get_parent(clk, CLKID_VPU), rate,
+						     current_rate);
+	case CLKID_VAPB:
+	case CLKID_VAPB_SEL:
+		return meson_clk_set_rate_by_id(clk,
+				meson_mux_get_parent(clk, CLKID_VAPB_SEL),
+				rate, current_rate);
+	case CLKID_VPU_0:
+		return meson_div_set_rate(clk, CLKID_VPU_0_DIV, rate,
+					  current_rate);
+	case CLKID_VPU_1:
+		return meson_div_set_rate(clk, CLKID_VPU_1_DIV, rate,
+					  current_rate);
+	case CLKID_VAPB_0:
+		return meson_div_set_rate(clk, CLKID_VAPB_0_DIV, rate,
+					  current_rate);
+	case CLKID_VAPB_1:
+		return meson_div_set_rate(clk, CLKID_VAPB_1_DIV, rate,
+					  current_rate);
+	case CLKID_VPU_0_DIV:
+	case CLKID_VPU_1_DIV:
+	case CLKID_VAPB_0_DIV:
+	case CLKID_VAPB_1_DIV:
+	case CLKID_HDMI_DIV:
+		return meson_div_set_rate(clk, id, rate, current_rate);
+	case CLKID_HDMI:
+		return meson_clk_set_rate_by_id(clk, CLKID_HDMI_DIV,
+						rate, current_rate);
 	default:
 		return -ENOENT;
 	}
@@ -361,7 +947,6 @@ static ulong meson_clk_set_rate_by_id(struct clk *clk, unsigned long id,
 	return -EINVAL;
 }
 
-
 static ulong meson_clk_set_rate(struct clk *clk, ulong rate)
 {
 	ulong current_rate = meson_clk_get_rate_by_id(clk, clk->id);
@@ -400,6 +985,7 @@ static struct clk_ops meson_clk_ops = {
 	.disable	= meson_clk_disable,
 	.enable		= meson_clk_enable,
 	.get_rate	= meson_clk_get_rate,
+	.set_parent	= meson_clk_set_parent,
 	.set_rate	= meson_clk_set_rate,
 };
 
-- 
2.22.0

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH 2/8] clk: meson: g12a: add support for VPU/HDMI clocks
@ 2019-08-30 12:09   ` Neil Armstrong
  0 siblings, 0 replies; 38+ messages in thread
From: Neil Armstrong @ 2019-08-30 12:09 UTC (permalink / raw)
  To: u-boot-amlogic, lukma; +Cc: Neil Armstrong, u-boot

Add necessary clock support to set up clock for the VPU and
HDMI support.

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 drivers/clk/meson/g12a.c | 620 +++++++++++++++++++++++++++++++++++++--
 1 file changed, 603 insertions(+), 17 deletions(-)

diff --git a/drivers/clk/meson/g12a.c b/drivers/clk/meson/g12a.c
index 43dac1aa37..c03738b6ca 100644
--- a/drivers/clk/meson/g12a.c
+++ b/drivers/clk/meson/g12a.c
@@ -14,16 +14,93 @@
 #include <syscon.h>
 #include <div64.h>
 #include <dt-bindings/clock/g12a-clkc.h>
+#include <linux/kernel.h>
 #include "clk_meson.h"
 
+/* This driver support only basic clock tree operations :
+ * - Can calculate clock frequency on a limited tree
+ * - Can Read muxes and basic dividers (0-based only)
+ * - Can enable/disable gates with limited propagation
+ * - Can reparent without propagation, only on muxes
+ * - Can set rates without reparenting
+ * This driver is adapted to what is actually supported by U-Boot
+ */
+
+/* Only the clocks ids we don't want to expose, such as the internal muxes
+ * and dividers of composite clocks, will remain defined here.
+ */
+#define CLKID_MPEG_SEL				8
+#define CLKID_MPEG_DIV				9
+#define CLKID_SD_EMMC_A_CLK0_SEL		63
+#define CLKID_SD_EMMC_A_CLK0_DIV		64
+#define CLKID_SD_EMMC_B_CLK0_SEL		65
+#define CLKID_SD_EMMC_B_CLK0_DIV		66
+#define CLKID_SD_EMMC_C_CLK0_SEL		67
+#define CLKID_SD_EMMC_C_CLK0_DIV		68
+#define CLKID_MPLL0_DIV				69
+#define CLKID_MPLL1_DIV				70
+#define CLKID_MPLL2_DIV				71
+#define CLKID_MPLL3_DIV				72
+#define CLKID_MPLL_PREDIV			73
+#define CLKID_FCLK_DIV2_DIV			75
+#define CLKID_FCLK_DIV3_DIV			76
+#define CLKID_FCLK_DIV4_DIV			77
+#define CLKID_FCLK_DIV5_DIV			78
+#define CLKID_FCLK_DIV7_DIV			79
+#define CLKID_FCLK_DIV2P5_DIV			100
+#define CLKID_FIXED_PLL_DCO			101
+#define CLKID_SYS_PLL_DCO			102
+#define CLKID_GP0_PLL_DCO			103
+#define CLKID_HIFI_PLL_DCO			104
+#define CLKID_VPU_0_DIV				111
+#define CLKID_VPU_1_DIV				114
+#define CLKID_VAPB_0_DIV			118
+#define CLKID_VAPB_1_DIV			121
+#define CLKID_HDMI_PLL_DCO			125
+#define CLKID_HDMI_PLL_OD			126
+#define CLKID_HDMI_PLL_OD2			127
+#define CLKID_VID_PLL_SEL			130
+#define CLKID_VID_PLL_DIV			131
+#define CLKID_VCLK_SEL				132
+#define CLKID_VCLK2_SEL				133
+#define CLKID_VCLK_INPUT			134
+#define CLKID_VCLK2_INPUT			135
+#define CLKID_VCLK_DIV				136
+#define CLKID_VCLK2_DIV				137
+#define CLKID_VCLK_DIV2_EN			140
+#define CLKID_VCLK_DIV4_EN			141
+#define CLKID_VCLK_DIV6_EN			142
+#define CLKID_VCLK_DIV12_EN			143
+#define CLKID_VCLK2_DIV2_EN			144
+#define CLKID_VCLK2_DIV4_EN			145
+#define CLKID_VCLK2_DIV6_EN			146
+#define CLKID_VCLK2_DIV12_EN			147
+#define CLKID_CTS_ENCI_SEL			158
+#define CLKID_CTS_ENCP_SEL			159
+#define CLKID_CTS_VDAC_SEL			160
+#define CLKID_HDMI_TX_SEL			161
+#define CLKID_HDMI_SEL				166
+#define CLKID_HDMI_DIV				167
+#define CLKID_MALI_0_DIV			170
+#define CLKID_MALI_1_DIV			173
+
+#define CLKID_XTAL				0x10000000
+
 #define XTAL_RATE 24000000
 
 struct meson_clk {
 	struct regmap *map;
 };
 
+static ulong meson_div_get_rate(struct clk *clk, unsigned long id);
+static ulong meson_div_set_rate(struct clk *clk, unsigned long id, ulong rate,
+				ulong current_rate);
+static ulong meson_mux_set_parent(struct clk *clk, unsigned long id,
+				  unsigned long parent_id);
+static ulong meson_mux_get_rate(struct clk *clk, unsigned long id);
 static ulong meson_clk_set_rate_by_id(struct clk *clk, unsigned long id,
 				      ulong rate, ulong current_rate);
+static ulong meson_mux_get_parent(struct clk *clk, unsigned long id);
 static ulong meson_clk_get_rate_by_id(struct clk *clk, unsigned long id);
 
 #define NUM_CLKS 178
@@ -39,40 +116,447 @@ static struct meson_gate gates[NUM_CLKS] = {
 	MESON_GATE(CLKID_ETH, HHI_GCLK_MPEG1, 3),
 	MESON_GATE(CLKID_UART1, HHI_GCLK_MPEG1, 16),
 	MESON_GATE(CLKID_USB, HHI_GCLK_MPEG1, 25),
+	MESON_GATE(CLKID_HTX_PCLK, HHI_GCLK_MPEG2, 4),
 	MESON_GATE(CLKID_USB1_DDR_BRIDGE, HHI_GCLK_MPEG2, 8),
+	MESON_GATE(CLKID_VPU_INTR, HHI_GCLK_MPEG2, 25),
 
 	/* Peripheral Gates */
+	MESON_GATE(CLKID_FCLK_DIV2, HHI_FIX_PLL_CNTL1, 24),
+	MESON_GATE(CLKID_FCLK_DIV3, HHI_FIX_PLL_CNTL1, 20),
+	MESON_GATE(CLKID_FCLK_DIV4, HHI_FIX_PLL_CNTL1, 21),
+	MESON_GATE(CLKID_FCLK_DIV5, HHI_FIX_PLL_CNTL1, 22),
+	MESON_GATE(CLKID_FCLK_DIV7, HHI_FIX_PLL_CNTL1, 23),
 	MESON_GATE(CLKID_SD_EMMC_B_CLK0, HHI_SD_EMMC_CLK_CNTL, 23),
 	MESON_GATE(CLKID_SD_EMMC_C_CLK0, HHI_NAND_CLK_CNTL, 7),
+	MESON_GATE(CLKID_VPU_0, HHI_VPU_CLK_CNTL, 8),
+	MESON_GATE(CLKID_VPU_1, HHI_VPU_CLK_CNTL, 24),
+	MESON_GATE(CLKID_VAPB_0, HHI_VAPBCLK_CNTL, 8),
+	MESON_GATE(CLKID_VAPB_1, HHI_VAPBCLK_CNTL, 24),
+	MESON_GATE(CLKID_VAPB, HHI_VAPBCLK_CNTL, 30),
+	MESON_GATE(CLKID_HDMI, HHI_HDMI_CLK_CNTL, 8),
 };
 
-static int meson_set_gate(struct clk *clk, bool on)
+static int meson_set_gate_by_id(struct clk *clk, unsigned long id, bool on)
 {
 	struct meson_clk *priv = dev_get_priv(clk->dev);
 	struct meson_gate *gate;
 
-	if (clk->id >= ARRAY_SIZE(gates))
+	debug("%s: %sabling %ld\n", __func__, on ? "en" : "dis", id);
+
+	/* Propagate through muxes */
+	switch (id) {
+	case CLKID_VPU:
+		return meson_set_gate_by_id(clk,
+				meson_mux_get_parent(clk, CLKID_VPU), on);
+	case CLKID_VAPB_SEL:
+		return meson_set_gate_by_id(clk,
+				meson_mux_get_parent(clk, CLKID_VAPB_SEL), on);
+	}
+
+	if (id >= ARRAY_SIZE(gates))
 		return -ENOENT;
 
-	gate = &gates[clk->id];
+	gate = &gates[id];
 
 	if (gate->reg == 0)
 		return 0;
 
+	debug("%s: really %sabling %ld\n", __func__, on ? "en" : "dis", id);
+
 	regmap_update_bits(priv->map, gate->reg,
 			   BIT(gate->bit), on ? BIT(gate->bit) : 0);
 
+	/* Propagate to next gate(s) */
+	switch (id) {
+	case CLKID_VAPB:
+		return meson_set_gate_by_id(clk, CLKID_VAPB_SEL, on);
+	case CLKID_VAPB_0:
+		return meson_set_gate_by_id(clk,
+			meson_mux_get_parent(clk, CLKID_VAPB_0_SEL), on);
+	case CLKID_VAPB_1:
+		return meson_set_gate_by_id(clk,
+			meson_mux_get_parent(clk, CLKID_VAPB_0_SEL), on);
+	case CLKID_VPU_0:
+		return meson_set_gate_by_id(clk,
+			meson_mux_get_parent(clk, CLKID_VPU_0_SEL), on);
+	case CLKID_VPU_1:
+		return meson_set_gate_by_id(clk,
+			meson_mux_get_parent(clk, CLKID_VPU_1_SEL), on);
+	}
+
 	return 0;
 }
 
 static int meson_clk_enable(struct clk *clk)
 {
-	return meson_set_gate(clk, true);
+	return meson_set_gate_by_id(clk, clk->id, true);
 }
 
 static int meson_clk_disable(struct clk *clk)
 {
-	return meson_set_gate(clk, false);
+	return meson_set_gate_by_id(clk, clk->id, false);
+}
+
+static struct parm meson_vpu_0_div_parm = {
+	HHI_VPU_CLK_CNTL, 0, 7,
+};
+
+int meson_vpu_0_div_parent = CLKID_VPU_0_SEL;
+
+static struct parm meson_vpu_1_div_parm = {
+	HHI_VPU_CLK_CNTL, 16, 7,
+};
+
+int meson_vpu_1_div_parent = CLKID_VPU_1_SEL;
+
+static struct parm meson_vapb_0_div_parm = {
+	HHI_VAPBCLK_CNTL, 0, 7,
+};
+
+int meson_vapb_0_div_parent = CLKID_VAPB_0_SEL;
+
+static struct parm meson_vapb_1_div_parm = {
+	HHI_VAPBCLK_CNTL, 16, 7,
+};
+
+int meson_vapb_1_div_parent = CLKID_VAPB_1_SEL;
+
+static struct parm meson_hdmi_div_parm = {
+	HHI_HDMI_CLK_CNTL, 0, 7,
+};
+
+int meson_hdmi_div_parent = CLKID_HDMI_SEL;
+
+static ulong meson_div_get_rate(struct clk *clk, unsigned long id)
+{
+	struct meson_clk *priv = dev_get_priv(clk->dev);
+	unsigned int rate, parent_rate;
+	struct parm *parm;
+	int parent;
+	uint reg;
+
+	switch (id) {
+	case CLKID_VPU_0_DIV:
+		parm = &meson_vpu_0_div_parm;
+		parent = meson_vpu_0_div_parent;
+		break;
+	case CLKID_VPU_1_DIV:
+		parm = &meson_vpu_1_div_parm;
+		parent = meson_vpu_1_div_parent;
+		break;
+	case CLKID_VAPB_0_DIV:
+		parm = &meson_vapb_0_div_parm;
+		parent = meson_vapb_0_div_parent;
+		break;
+	case CLKID_VAPB_1_DIV:
+		parm = &meson_vapb_1_div_parm;
+		parent = meson_vapb_1_div_parent;
+		break;
+	case CLKID_HDMI_DIV:
+		parm = &meson_hdmi_div_parm;
+		parent = meson_hdmi_div_parent;
+		break;
+	default:
+		return -ENOENT;
+	}
+
+	regmap_read(priv->map, parm->reg_off, &reg);
+	reg = PARM_GET(parm->width, parm->shift, reg);
+
+	debug("%s: div of %ld is %d\n", __func__, id, reg + 1);
+
+	parent_rate = meson_clk_get_rate_by_id(clk, parent);
+	if (IS_ERR_VALUE(parent_rate))
+		return parent_rate;
+
+	debug("%s: parent rate of %ld is %d\n", __func__, id, parent_rate);
+
+	rate = parent_rate / (reg + 1);
+
+	debug("%s: rate of %ld is %d\n", __func__, id, rate);
+
+	return rate;
+}
+
+static ulong meson_div_set_rate(struct clk *clk, unsigned long id, ulong rate,
+				ulong current_rate)
+{
+	struct meson_clk *priv = dev_get_priv(clk->dev);
+	unsigned int new_div = -EINVAL;
+	unsigned long parent_rate;
+	struct parm *parm;
+	int parent;
+	int ret;
+
+	if (current_rate == rate)
+		return 0;
+
+	debug("%s: setting rate of %ld from %ld to %ld\n",
+	      __func__, id, current_rate, rate);
+
+	switch (id) {
+	case CLKID_VPU_0_DIV:
+		parm = &meson_vpu_0_div_parm;
+		parent = meson_vpu_0_div_parent;
+		break;
+	case CLKID_VPU_1_DIV:
+		parm = &meson_vpu_1_div_parm;
+		parent = meson_vpu_1_div_parent;
+		break;
+	case CLKID_VAPB_0_DIV:
+		parm = &meson_vapb_0_div_parm;
+		parent = meson_vapb_0_div_parent;
+		break;
+	case CLKID_VAPB_1_DIV:
+		parm = &meson_vapb_1_div_parm;
+		parent = meson_vapb_1_div_parent;
+		break;
+	case CLKID_HDMI_DIV:
+		parm = &meson_hdmi_div_parm;
+		parent = meson_hdmi_div_parent;
+		break;
+	default:
+		return -ENOENT;
+	}
+
+	parent_rate = meson_clk_get_rate_by_id(clk, parent);
+	if (IS_ERR_VALUE(parent_rate))
+		return parent_rate;
+
+	debug("%s: parent rate of %ld is %ld\n", __func__, id, parent_rate);
+
+	/* If can't divide, set parent instead */
+	if (!parent_rate || rate > parent_rate)
+		return meson_clk_set_rate_by_id(clk, parent, rate,
+						current_rate);
+
+	new_div = DIV_ROUND_CLOSEST(parent_rate, rate);
+
+	debug("%s: new div of %ld is %d\n", __func__, id, new_div);
+
+	/* If overflow, try to set parent rate and retry */
+	if (!new_div || new_div > (1 << parm->width)) {
+		ret = meson_clk_set_rate_by_id(clk, parent, rate, current_rate);
+		if (IS_ERR_VALUE(ret))
+			return ret;
+
+		parent_rate = meson_clk_get_rate_by_id(clk, parent);
+		if (IS_ERR_VALUE(parent_rate))
+			return parent_rate;
+
+		new_div = DIV_ROUND_CLOSEST(parent_rate, rate);
+
+		debug("%s: new new div of %ld is %d\n", __func__, id, new_div);
+
+		if (!new_div || new_div > (1 << parm->width))
+			return -EINVAL;
+	}
+
+	debug("%s: setting div of %ld to %d\n", __func__, id, new_div);
+
+	regmap_update_bits(priv->map, parm->reg_off,
+			   SETPMASK(parm->width, parm->shift),
+			   (new_div - 1) << parm->shift);
+
+	debug("%s: new rate of %ld is %ld\n",
+	      __func__, id, meson_div_get_rate(clk, id));
+
+	return 0;
+}
+
+static struct parm meson_vpu_mux_parm = {
+	HHI_VPU_CLK_CNTL, 31, 1,
+};
+
+int meson_vpu_mux_parents[] = {
+	CLKID_VPU_0,
+	CLKID_VPU_1,
+};
+
+static struct parm meson_vpu_0_mux_parm = {
+	HHI_VPU_CLK_CNTL, 9, 3,
+};
+
+static struct parm meson_vpu_1_mux_parm = {
+	HHI_VPU_CLK_CNTL, 25, 3,
+};
+
+static int meson_vpu_0_1_mux_parents[] = {
+	CLKID_FCLK_DIV3,
+	CLKID_FCLK_DIV4,
+	CLKID_FCLK_DIV5,
+	CLKID_FCLK_DIV7,
+	-ENOENT,
+	-ENOENT,
+	-ENOENT,
+	-ENOENT,
+};
+
+static struct parm meson_vapb_sel_mux_parm = {
+	HHI_VAPBCLK_CNTL, 31, 1,
+};
+
+int meson_vapb_sel_mux_parents[] = {
+	CLKID_VAPB_0,
+	CLKID_VAPB_1,
+};
+
+static struct parm meson_vapb_0_mux_parm = {
+	HHI_VAPBCLK_CNTL, 9, 2,
+};
+
+static struct parm meson_vapb_1_mux_parm = {
+	HHI_VAPBCLK_CNTL, 25, 2,
+};
+
+static int meson_vapb_0_1_mux_parents[] = {
+	CLKID_FCLK_DIV4,
+	CLKID_FCLK_DIV3,
+	CLKID_FCLK_DIV5,
+	CLKID_FCLK_DIV7,
+};
+
+static struct parm meson_hdmi_mux_parm = {
+	HHI_HDMI_CLK_CNTL, 9, 2,
+};
+
+static int meson_hdmi_mux_parents[] = {
+	CLKID_XTAL,
+	CLKID_FCLK_DIV4,
+	CLKID_FCLK_DIV3,
+	CLKID_FCLK_DIV5,
+};
+
+static ulong meson_mux_get_parent(struct clk *clk, unsigned long id)
+{
+	struct meson_clk *priv = dev_get_priv(clk->dev);
+	struct parm *parm;
+	int *parents;
+	uint reg;
+
+	switch (id) {
+	case CLKID_VPU:
+		parm = &meson_vpu_mux_parm;
+		parents = meson_vpu_mux_parents;
+		break;
+	case CLKID_VPU_0_SEL:
+		parm = &meson_vpu_0_mux_parm;
+		parents = meson_vpu_0_1_mux_parents;
+		break;
+	case CLKID_VPU_1_SEL:
+		parm = &meson_vpu_1_mux_parm;
+		parents = meson_vpu_0_1_mux_parents;
+		break;
+	case CLKID_VAPB_SEL:
+		parm = &meson_vapb_sel_mux_parm;
+		parents = meson_vapb_sel_mux_parents;
+		break;
+	case CLKID_VAPB_0_SEL:
+		parm = &meson_vapb_0_mux_parm;
+		parents = meson_vapb_0_1_mux_parents;
+		break;
+	case CLKID_VAPB_1_SEL:
+		parm = &meson_vapb_1_mux_parm;
+		parents = meson_vapb_0_1_mux_parents;
+		break;
+	case CLKID_HDMI_SEL:
+		parm = &meson_hdmi_mux_parm;
+		parents = meson_hdmi_mux_parents;
+		break;
+	default:
+		return -ENOENT;
+	}
+
+	regmap_read(priv->map, parm->reg_off, &reg);
+	reg = PARM_GET(parm->width, parm->shift, reg);
+
+	debug("%s: parent of %ld is %d (%d)\n",
+	      __func__, id, parents[reg], reg);
+
+	return parents[reg];
+}
+
+static ulong meson_mux_set_parent(struct clk *clk, unsigned long id,
+				  unsigned long parent_id)
+{
+	unsigned long cur_parent = meson_mux_get_parent(clk, id);
+	struct meson_clk *priv = dev_get_priv(clk->dev);
+	unsigned int new_index = -EINVAL;
+	struct parm *parm;
+	int *parents;
+	int i;
+
+	if (IS_ERR_VALUE(cur_parent))
+		return cur_parent;
+
+	debug("%s: setting parent of %ld from %ld to %ld\n",
+	      __func__, id, cur_parent, parent_id);
+
+	if (cur_parent == parent_id)
+		return 0;
+
+	switch (id) {
+	case CLKID_VPU:
+		parm = &meson_vpu_mux_parm;
+		parents = meson_vpu_mux_parents;
+		break;
+	case CLKID_VPU_0_SEL:
+		parm = &meson_vpu_0_mux_parm;
+		parents = meson_vpu_0_1_mux_parents;
+		break;
+	case CLKID_VPU_1_SEL:
+		parm = &meson_vpu_1_mux_parm;
+		parents = meson_vpu_0_1_mux_parents;
+		break;
+	case CLKID_VAPB_SEL:
+		parm = &meson_vapb_sel_mux_parm;
+		parents = meson_vapb_sel_mux_parents;
+		break;
+	case CLKID_VAPB_0_SEL:
+		parm = &meson_vapb_0_mux_parm;
+		parents = meson_vapb_0_1_mux_parents;
+		break;
+	case CLKID_VAPB_1_SEL:
+		parm = &meson_vapb_1_mux_parm;
+		parents = meson_vapb_0_1_mux_parents;
+		break;
+	case CLKID_HDMI_SEL:
+		parm = &meson_hdmi_mux_parm;
+		parents = meson_hdmi_mux_parents;
+		break;
+	default:
+		/* Not a mux */
+		return -ENOENT;
+	}
+
+	for (i = 0 ; i < (1 << parm->width) ; ++i) {
+		if (parents[i] == parent_id)
+			new_index = i;
+	}
+
+	if (IS_ERR_VALUE(new_index))
+		return new_index;
+
+	debug("%s: new index of %ld is %d\n", __func__, id, new_index);
+
+	regmap_update_bits(priv->map, parm->reg_off,
+			   SETPMASK(parm->width, parm->shift),
+			   new_index << parm->shift);
+
+	debug("%s: new parent of %ld is %ld\n",
+	      __func__, id, meson_mux_get_parent(clk, id));
+
+	return 0;
+}
+
+static ulong meson_mux_get_rate(struct clk *clk, unsigned long id)
+{
+	int parent = meson_mux_get_parent(clk, id);
+
+	if (IS_ERR_VALUE(parent))
+		return parent;
+
+	return meson_clk_get_rate_by_id(clk, parent);
 }
 
 static unsigned long meson_clk81_get_rate(struct clk *clk)
@@ -81,7 +565,7 @@ static unsigned long meson_clk81_get_rate(struct clk *clk)
 	unsigned long parent_rate;
 	uint reg;
 	int parents[] = {
-		-1,
+		CLKID_XTAL,
 		-1,
 		CLKID_FCLK_DIV7,
 		CLKID_MPLL1,
@@ -96,9 +580,6 @@ static unsigned long meson_clk81_get_rate(struct clk *clk)
 	reg = (reg >> 12) & 7;
 
 	switch (reg) {
-	case 0:
-		parent_rate = XTAL_RATE;
-		break;
 	case 1:
 		return -ENOENT;
 	default:
@@ -183,24 +664,26 @@ static ulong meson_mpll_get_rate(struct clk *clk, unsigned long id)
 	return mpll_rate_from_params(parent_rate, sdm, n2);
 }
 
-static struct parm meson_fixed_pll_parm[3] = {
-	{HHI_FIX_PLL_CNTL0, 0, 8}, /* pm */
+static struct parm meson_fixed_pll_parm[4] = {
+	{HHI_FIX_PLL_CNTL0, 0, 9}, /* pm */
 	{HHI_FIX_PLL_CNTL0, 10, 5}, /* pn */
 	{HHI_FIX_PLL_CNTL0, 16, 2}, /* pod */
+	{HHI_FIX_PLL_CNTL1, 0, 17}, /* pfrac */
 };
 
 static struct parm meson_sys_pll_parm[3] = {
-	{HHI_SYS_PLL_CNTL0, 0, 8}, /* pm */
+	{HHI_SYS_PLL_CNTL0, 0, 9}, /* pm */
 	{HHI_SYS_PLL_CNTL0, 10, 5}, /* pn */
-	{HHI_SYS_PLL_CNTL0, 16, 2}, /* pod */
+	{HHI_SYS_PLL_CNTL0, 16, 3}, /* pod */
 };
 
 static ulong meson_pll_get_rate(struct clk *clk, unsigned long id)
 {
 	struct meson_clk *priv = dev_get_priv(clk->dev);
-	struct parm *pm, *pn, *pod;
+	struct parm *pm, *pn, *pod, *pfrac = NULL;
 	unsigned long parent_rate_mhz = XTAL_RATE / 1000000;
-	u16 n, m, od;
+	u16 n, m, od, frac;
+	ulong rate;
 	uint reg;
 
 	/*
@@ -213,6 +696,7 @@ static ulong meson_pll_get_rate(struct clk *clk, unsigned long id)
 		pm = &meson_fixed_pll_parm[0];
 		pn = &meson_fixed_pll_parm[1];
 		pod = &meson_fixed_pll_parm[2];
+		pfrac = &meson_fixed_pll_parm[3];
 		break;
 	case CLKID_SYS_PLL:
 		pm = &meson_sys_pll_parm[0];
@@ -232,7 +716,24 @@ static ulong meson_pll_get_rate(struct clk *clk, unsigned long id)
 	regmap_read(priv->map, pod->reg_off, &reg);
 	od = PARM_GET(pod->width, pod->shift, reg);
 
-	return ((parent_rate_mhz * m / n) >> od) * 1000000;
+	rate = parent_rate_mhz * m;
+
+	if (pfrac) {
+		ulong frac_rate;
+
+		regmap_read(priv->map, pfrac->reg_off, &reg);
+		frac = PARM_GET(pfrac->width - 1, pfrac->shift, reg);
+
+		frac_rate = DIV_ROUND_UP_ULL((u64)parent_rate_mhz * frac,
+					     1 << (pfrac->width - 2));
+
+		if (frac & BIT(pfrac->width - 1))
+			rate -= frac_rate;
+		else
+			rate += frac_rate;
+	}
+
+	return (DIV_ROUND_UP_ULL(rate, n) >> od) * 1000000;
 }
 
 static struct parm meson_pcie_pll_parm[3] = {
@@ -270,6 +771,9 @@ static ulong meson_clk_get_rate_by_id(struct clk *clk, unsigned long id)
 	ulong rate;
 
 	switch (id) {
+	case CLKID_XTAL:
+		rate = XTAL_RATE;
+		break;
 	case CLKID_FIXED_PLL:
 	case CLKID_SYS_PLL:
 		rate = meson_pll_get_rate(clk, id);
@@ -299,6 +803,39 @@ static ulong meson_clk_get_rate_by_id(struct clk *clk, unsigned long id)
 		break;
 	case CLKID_PCIE_PLL:
 		rate = meson_pcie_pll_get_rate(clk);
+	case CLKID_VPU_0:
+		rate = meson_div_get_rate(clk, CLKID_VPU_0_DIV);
+		break;
+	case CLKID_VPU_1:
+		rate = meson_div_get_rate(clk, CLKID_VPU_1_DIV);
+		break;
+	case CLKID_VAPB:
+		rate = meson_mux_get_rate(clk, CLKID_VAPB_SEL);
+		break;
+	case CLKID_VAPB_0:
+		rate = meson_div_get_rate(clk, CLKID_VAPB_0_DIV);
+		break;
+	case CLKID_VAPB_1:
+		rate = meson_div_get_rate(clk, CLKID_VAPB_1_DIV);
+		break;
+	case CLKID_HDMI:
+		rate = meson_div_get_rate(clk, CLKID_HDMI_DIV);
+		break;
+	case CLKID_VPU_0_DIV:
+	case CLKID_VPU_1_DIV:
+	case CLKID_VAPB_0_DIV:
+	case CLKID_VAPB_1_DIV:
+	case CLKID_HDMI_DIV:
+		rate = meson_div_get_rate(clk, id);
+		break;
+	case CLKID_VPU:
+	case CLKID_VPU_0_SEL:
+	case CLKID_VPU_1_SEL:
+	case CLKID_VAPB_SEL:
+	case CLKID_VAPB_0_SEL:
+	case CLKID_VAPB_1_SEL:
+	case CLKID_HDMI_SEL:
+		rate = meson_mux_get_rate(clk, id);
 		break;
 	default:
 		if (gates[id].reg != 0) {
@@ -343,6 +880,11 @@ static ulong meson_pcie_pll_set_rate(struct clk *clk, ulong rate)
 	return 100000000;
 }
 
+static int meson_clk_set_parent(struct clk *clk, struct clk *parent)
+{
+	return meson_mux_set_parent(clk, clk->id, parent->id);
+}
+
 static ulong meson_clk_set_rate_by_id(struct clk *clk, unsigned long id,
 				      ulong rate, ulong current_rate)
 {
@@ -351,9 +893,53 @@ static ulong meson_clk_set_rate_by_id(struct clk *clk, unsigned long id,
 
 	switch (id) {
 	/* Fixed clocks */
+	case CLKID_FIXED_PLL:
+	case CLKID_SYS_PLL:
+	case CLKID_FCLK_DIV2:
+	case CLKID_FCLK_DIV3:
+	case CLKID_FCLK_DIV4:
+	case CLKID_FCLK_DIV5:
+	case CLKID_FCLK_DIV7:
+	case CLKID_MPLL0:
+	case CLKID_MPLL1:
+	case CLKID_MPLL2:
+	case CLKID_CLK81:
+		if (current_rate != rate)
+			return -EINVAL;
 	case CLKID_PCIE_PLL:
 		return meson_pcie_pll_set_rate(clk, rate);
 
+		return 0;
+	case CLKID_VPU:
+		return meson_clk_set_rate_by_id(clk,
+				meson_mux_get_parent(clk, CLKID_VPU), rate,
+						     current_rate);
+	case CLKID_VAPB:
+	case CLKID_VAPB_SEL:
+		return meson_clk_set_rate_by_id(clk,
+				meson_mux_get_parent(clk, CLKID_VAPB_SEL),
+				rate, current_rate);
+	case CLKID_VPU_0:
+		return meson_div_set_rate(clk, CLKID_VPU_0_DIV, rate,
+					  current_rate);
+	case CLKID_VPU_1:
+		return meson_div_set_rate(clk, CLKID_VPU_1_DIV, rate,
+					  current_rate);
+	case CLKID_VAPB_0:
+		return meson_div_set_rate(clk, CLKID_VAPB_0_DIV, rate,
+					  current_rate);
+	case CLKID_VAPB_1:
+		return meson_div_set_rate(clk, CLKID_VAPB_1_DIV, rate,
+					  current_rate);
+	case CLKID_VPU_0_DIV:
+	case CLKID_VPU_1_DIV:
+	case CLKID_VAPB_0_DIV:
+	case CLKID_VAPB_1_DIV:
+	case CLKID_HDMI_DIV:
+		return meson_div_set_rate(clk, id, rate, current_rate);
+	case CLKID_HDMI:
+		return meson_clk_set_rate_by_id(clk, CLKID_HDMI_DIV,
+						rate, current_rate);
 	default:
 		return -ENOENT;
 	}
@@ -361,7 +947,6 @@ static ulong meson_clk_set_rate_by_id(struct clk *clk, unsigned long id,
 	return -EINVAL;
 }
 
-
 static ulong meson_clk_set_rate(struct clk *clk, ulong rate)
 {
 	ulong current_rate = meson_clk_get_rate_by_id(clk, clk->id);
@@ -400,6 +985,7 @@ static struct clk_ops meson_clk_ops = {
 	.disable	= meson_clk_disable,
 	.enable		= meson_clk_enable,
 	.get_rate	= meson_clk_get_rate,
+	.set_parent	= meson_clk_set_parent,
 	.set_rate	= meson_clk_set_rate,
 };
 
-- 
2.22.0


^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [U-Boot] [PATCH 3/8] video: meson: remove power domain get
  2019-08-30 12:09 ` Neil Armstrong
@ 2019-08-30 12:09   ` Neil Armstrong
  -1 siblings, 0 replies; 38+ messages in thread
From: Neil Armstrong @ 2019-08-30 12:09 UTC (permalink / raw)
  To: u-boot

Remove getting and enabling the node power domain since it's now handled
by the dm core directly.

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 drivers/video/meson/meson_vpu.c | 10 ----------
 1 file changed, 10 deletions(-)

diff --git a/drivers/video/meson/meson_vpu.c b/drivers/video/meson/meson_vpu.c
index 279401d597..34d35749eb 100644
--- a/drivers/video/meson/meson_vpu.c
+++ b/drivers/video/meson/meson_vpu.c
@@ -7,7 +7,6 @@
  */
 
 #include "meson_vpu.h"
-#include <power-domain.h>
 #include <efi_loader.h>
 #include <dm/device-internal.h>
 #include <dm/uclass-internal.h>
@@ -93,7 +92,6 @@ static const struct udevice_id meson_vpu_ids[] = {
 static int meson_vpu_probe(struct udevice *dev)
 {
 	struct meson_vpu_priv *priv = dev_get_priv(dev);
-	struct power_domain pd;
 	struct udevice *disp;
 	int ret;
 
@@ -115,14 +113,6 @@ static int meson_vpu_probe(struct udevice *dev)
 	if (!priv->dmc_base)
 		return -EINVAL;
 
-	ret = power_domain_get(dev, &pd);
-	if (ret)
-		return ret;
-
-	ret = power_domain_on(&pd);
-	if (ret)
-		return ret;
-
 	meson_vpu_init(dev);
 
 	/* probe the display */
-- 
2.22.0

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH 3/8] video: meson: remove power domain get
@ 2019-08-30 12:09   ` Neil Armstrong
  0 siblings, 0 replies; 38+ messages in thread
From: Neil Armstrong @ 2019-08-30 12:09 UTC (permalink / raw)
  To: u-boot-amlogic, agust, jh80.chung; +Cc: Neil Armstrong, u-boot

Remove getting and enabling the node power domain since it's now handled
by the dm core directly.

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 drivers/video/meson/meson_vpu.c | 10 ----------
 1 file changed, 10 deletions(-)

diff --git a/drivers/video/meson/meson_vpu.c b/drivers/video/meson/meson_vpu.c
index 279401d597..34d35749eb 100644
--- a/drivers/video/meson/meson_vpu.c
+++ b/drivers/video/meson/meson_vpu.c
@@ -7,7 +7,6 @@
  */
 
 #include "meson_vpu.h"
-#include <power-domain.h>
 #include <efi_loader.h>
 #include <dm/device-internal.h>
 #include <dm/uclass-internal.h>
@@ -93,7 +92,6 @@ static const struct udevice_id meson_vpu_ids[] = {
 static int meson_vpu_probe(struct udevice *dev)
 {
 	struct meson_vpu_priv *priv = dev_get_priv(dev);
-	struct power_domain pd;
 	struct udevice *disp;
 	int ret;
 
@@ -115,14 +113,6 @@ static int meson_vpu_probe(struct udevice *dev)
 	if (!priv->dmc_base)
 		return -EINVAL;
 
-	ret = power_domain_get(dev, &pd);
-	if (ret)
-		return ret;
-
-	ret = power_domain_on(&pd);
-	if (ret)
-		return ret;
-
 	meson_vpu_init(dev);
 
 	/* probe the display */
-- 
2.22.0


^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [U-Boot] [PATCH 4/8] video: meson: sync with linux drm-misc tree
  2019-08-30 12:09 ` Neil Armstrong
@ 2019-08-30 12:09   ` Neil Armstrong
  -1 siblings, 0 replies; 38+ messages in thread
From: Neil Armstrong @ 2019-08-30 12:09 UTC (permalink / raw)
  To: u-boot

Synchronize the Amlogic Meson Video driver back with the latest
DRM misc tree, adding G12A platform support, from the latest commit:
528a25d040bc ("drm: meson: use match data to detect vpu compatibility")

The sync includes the following changes from Linux adapted to U-Boot:
- Add support for VIC alternate timings
- Switch PLL to 5.94GHz base for 297Mhz pixel clock
- Add registers for G12A SoC
- Add G12A Support for VPP setup
- Add G12A Support for VIU setup
- Add G12A support for OSD1 Plane
- Add G12A support for plane handling in CRTC driver
- Add G12A support for CVBS Encoder
- Add G12A Video Clock setup
- Add G12A support for the DW-HDMI Glue
- fix G12A HDMI PLL settings for 4K60 1000/1001 variations
- fix primary plane disabling
- fix G12A primary plane disabling
- mask value when writing bits relaxed
- crtc: drv: vpp: viu: venc: use proper macros instead of magic constants
- global clean-up
- add macro used to enable HDMI PLL
- venc: set the correct macrovision max amplitude value

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 drivers/video/meson/meson_dw_hdmi.c   |  61 ++++-
 drivers/video/meson/meson_plane.c     |  47 +++-
 drivers/video/meson/meson_registers.h | 373 +++++++++++++++++++++++++-
 drivers/video/meson/meson_vclk.c      | 233 ++++++++++++----
 drivers/video/meson/meson_venc.c      | 169 +++++++++---
 drivers/video/meson/meson_vpu.h       |   1 +
 drivers/video/meson/meson_vpu_init.c  | 205 +++++++++++---
 7 files changed, 929 insertions(+), 160 deletions(-)

diff --git a/drivers/video/meson/meson_dw_hdmi.c b/drivers/video/meson/meson_dw_hdmi.c
index 9831d978fc..ae2e6288f3 100644
--- a/drivers/video/meson/meson_dw_hdmi.c
+++ b/drivers/video/meson/meson_dw_hdmi.c
@@ -24,6 +24,7 @@
 #define HDMITX_TOP_ADDR_REG	0x0
 #define HDMITX_TOP_DATA_REG	0x4
 #define HDMITX_TOP_CTRL_REG	0x8
+#define HDMITX_TOP_G12A_OFFSET	0x8000
 
 /* Controller Communication Channel */
 #define HDMITX_DWC_ADDR_REG	0x10
@@ -37,6 +38,8 @@
 #define HHI_HDMI_PHY_CNTL1	0x3a4 /* 0xe9 */
 #define HHI_HDMI_PHY_CNTL2	0x3a8 /* 0xea */
 #define HHI_HDMI_PHY_CNTL3	0x3ac /* 0xeb */
+#define HHI_HDMI_PHY_CNTL4	0x3b0 /* 0xec */
+#define HHI_HDMI_PHY_CNTL5	0x3b4 /* 0xed */
 
 struct meson_dw_hdmi {
 	struct udevice *dev;
@@ -48,6 +51,7 @@ enum hdmi_compatible {
 	HDMI_COMPATIBLE_GXBB = 0,
 	HDMI_COMPATIBLE_GXL = 1,
 	HDMI_COMPATIBLE_GXM = 2,
+	HDMI_COMPATIBLE_G12A = 3,
 };
 
 static inline bool meson_hdmi_is_compatible(struct meson_dw_hdmi *priv,
@@ -60,8 +64,14 @@ static inline bool meson_hdmi_is_compatible(struct meson_dw_hdmi *priv,
 
 static unsigned int dw_hdmi_top_read(struct dw_hdmi *hdmi, unsigned int addr)
 {
+	struct meson_dw_hdmi *priv = container_of(hdmi, struct meson_dw_hdmi,
+						  hdmi);
 	unsigned int data;
 
+	if (meson_hdmi_is_compatible(priv, HDMI_COMPATIBLE_G12A))
+		return readl(hdmi->ioaddr +
+			     HDMITX_TOP_G12A_OFFSET + (addr << 2));
+
 	/* ADDR must be written twice */
 	writel(addr & 0xffff, hdmi->ioaddr + HDMITX_TOP_ADDR_REG);
 	writel(addr & 0xffff, hdmi->ioaddr + HDMITX_TOP_ADDR_REG);
@@ -76,6 +86,15 @@ static unsigned int dw_hdmi_top_read(struct dw_hdmi *hdmi, unsigned int addr)
 static inline void dw_hdmi_top_write(struct dw_hdmi *hdmi,
 				     unsigned int addr, unsigned int data)
 {
+	struct meson_dw_hdmi *priv = container_of(hdmi, struct meson_dw_hdmi,
+						  hdmi);
+
+	if (meson_hdmi_is_compatible(priv, HDMI_COMPATIBLE_G12A)) {
+		writel(data, hdmi->ioaddr +
+		       HDMITX_TOP_G12A_OFFSET + (addr << 2));
+		return;
+	}
+
 	/* ADDR must be written twice */
 	writel(addr & 0xffff, hdmi->ioaddr + HDMITX_TOP_ADDR_REG);
 	writel(addr & 0xffff, hdmi->ioaddr + HDMITX_TOP_ADDR_REG);
@@ -237,7 +256,7 @@ static void meson_dw_hdmi_phy_setup_mode(struct meson_dw_hdmi *priv,
 			hhi_write(HHI_HDMI_PHY_CNTL0, 0x33604142);
 			hhi_write(HHI_HDMI_PHY_CNTL3, 0x0016315b);
 		}
-	} else {
+	} else if (meson_hdmi_is_compatible(priv, HDMI_COMPATIBLE_GXBB)) {
 		if (pixel_clock >= 371250) {
 			/* 5.94Gbps, 3.7125Gbps */
 			hhi_write(HHI_HDMI_PHY_CNTL0, 0x33353245);
@@ -251,6 +270,23 @@ static void meson_dw_hdmi_phy_setup_mode(struct meson_dw_hdmi *priv,
 			hhi_write(HHI_HDMI_PHY_CNTL0, 0x33632122);
 			hhi_write(HHI_HDMI_PHY_CNTL3, 0x2000115b);
 		}
+	} else if (meson_hdmi_is_compatible(priv, HDMI_COMPATIBLE_G12A)) {
+		if (pixel_clock >= 371250) {
+			/* 5.94Gbps, 3.7125Gbps */
+			hhi_write(HHI_HDMI_PHY_CNTL0, 0x37eb65c4);
+			hhi_write(HHI_HDMI_PHY_CNTL3, 0x2ab0ff3b);
+			hhi_write(HHI_HDMI_PHY_CNTL5, 0x0000080b);
+		} else if (pixel_clock >= 297000) {
+			/* 2.97Gbps */
+			hhi_write(HHI_HDMI_PHY_CNTL0, 0x33eb6262);
+			hhi_write(HHI_HDMI_PHY_CNTL3, 0x2ab0ff3b);
+			hhi_write(HHI_HDMI_PHY_CNTL5, 0x00000003);
+		} else {
+			/* 1.485Gbps, and below */
+			hhi_write(HHI_HDMI_PHY_CNTL0, 0x33eb4242);
+			hhi_write(HHI_HDMI_PHY_CNTL3, 0x2ab0ff3b);
+			hhi_write(HHI_HDMI_PHY_CNTL5, 0x00000003);
+		}
 	}
 }
 
@@ -292,7 +328,8 @@ static int meson_dw_hdmi_phy_init(struct dw_hdmi *hdmi, uint pixel_clock)
 
 	/* BIT_INVERT */
 	if (meson_hdmi_is_compatible(priv, HDMI_COMPATIBLE_GXL) ||
-	    meson_hdmi_is_compatible(priv, HDMI_COMPATIBLE_GXM))
+	    meson_hdmi_is_compatible(priv, HDMI_COMPATIBLE_GXM) ||
+	    meson_hdmi_is_compatible(priv, HDMI_COMPATIBLE_G12A))
 		dw_hdmi_hhi_update_bits(priv, HHI_HDMI_PHY_CNTL1, BIT(17), 0);
 	else
 		dw_hdmi_hhi_update_bits(priv, HHI_HDMI_PHY_CNTL1,
@@ -356,8 +393,12 @@ static int meson_dw_hdmi_probe(struct udevice *dev)
 	priv->hdmi.hdmi_data.enc_out_bus_format = MEDIA_BUS_FMT_RGB888_1X24;
 	priv->hdmi.hdmi_data.enc_in_bus_format = MEDIA_BUS_FMT_YUV8_1X24;
 	priv->hdmi.phy_set = meson_dw_hdmi_phy_init;
-	priv->hdmi.write_reg = dw_hdmi_dwc_write;
-	priv->hdmi.read_reg = dw_hdmi_dwc_read;
+	if (meson_hdmi_is_compatible(priv, HDMI_COMPATIBLE_G12A))
+		priv->hdmi.reg_io_width = 1;
+	else {
+		priv->hdmi.write_reg = dw_hdmi_dwc_write;
+		priv->hdmi.read_reg = dw_hdmi_dwc_read;
+	}
 	priv->hdmi.i2c_clk_high = 0x67;
 	priv->hdmi.i2c_clk_low = 0x78;
 
@@ -409,9 +450,13 @@ static int meson_dw_hdmi_probe(struct udevice *dev)
 	if (ret)
 		return ret;
 
-	/* Enable APB3 fail on error */
-	writel_bits(BIT(15), BIT(15), priv->hdmi.ioaddr + HDMITX_TOP_CTRL_REG);
-	writel_bits(BIT(15), BIT(15), priv->hdmi.ioaddr + HDMITX_DWC_CTRL_REG);
+	if (!meson_hdmi_is_compatible(priv, HDMI_COMPATIBLE_G12A)) {
+		/* Enable APB3 fail on error */
+		writel_bits(BIT(15), BIT(15),
+			    priv->hdmi.ioaddr + HDMITX_TOP_CTRL_REG);
+		writel_bits(BIT(15), BIT(15),
+			    priv->hdmi.ioaddr + HDMITX_DWC_CTRL_REG);
+	}
 
 	/* Bring out of reset */
 	dw_hdmi_top_write(&priv->hdmi, HDMITX_TOP_SW_RESET,  0);
@@ -448,6 +493,8 @@ static const struct udevice_id meson_dw_hdmi_ids[] = {
 		.data = HDMI_COMPATIBLE_GXL },
 	{ .compatible = "amlogic,meson-gxm-dw-hdmi",
 		.data = HDMI_COMPATIBLE_GXM },
+	{ .compatible = "amlogic,meson-g12a-dw-hdmi",
+		.data = HDMI_COMPATIBLE_G12A },
 	{ }
 };
 
diff --git a/drivers/video/meson/meson_plane.c b/drivers/video/meson/meson_plane.c
index 63a4bf2d8d..2bc9327e1e 100644
--- a/drivers/video/meson/meson_plane.c
+++ b/drivers/video/meson/meson_plane.c
@@ -108,12 +108,33 @@ void meson_vpu_setup_plane(struct udevice *dev, bool is_interlaced)
 	dest_y1 = src_y1 = 0;
 	dest_y2 = src_y2 = uc_priv->ysize;
 
-	/* Enable VPP Postblend */
-	writel(uc_priv->xsize,
-	       priv->io_base + _REG(VPP_POSTBLEND_H_SIZE));
+	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));
+		writel_bits(VPP_POSTBLEND_ENABLE, VPP_POSTBLEND_ENABLE,
+			    priv->io_base + _REG(VPP_MISC));
+	}
 
 	/* uc_plat->base is the framebuffer */
 
@@ -172,6 +193,18 @@ void meson_vpu_setup_plane(struct udevice *dev, bool is_interlaced)
 			   MESON_CANVAS_BLKMODE_LINEAR);
 
 	/* Enable OSD1 */
-	writel_bits(VPP_OSD1_POSTBLEND, VPP_OSD1_POSTBLEND,
-		    priv->io_base + _REG(VPP_MISC));
+	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));
 }
diff --git a/drivers/video/meson/meson_registers.h b/drivers/video/meson/meson_registers.h
index 01fe7d2431..39e8ec8639 100644
--- a/drivers/video/meson/meson_registers.h
+++ b/drivers/video/meson/meson_registers.h
@@ -136,11 +136,19 @@
 #define VIU_ADDR_START 0x1a00
 #define VIU_ADDR_END 0x1aff
 #define VIU_SW_RESET 0x1a01
+#define		VIU_SW_RESET_OSD1               BIT(0)
 #define VIU_MISC_CTRL0 0x1a06
+#define		VIU_CTRL0_VD1_AFBC_MASK         0x170000
 #define VIU_MISC_CTRL1 0x1a07
 #define D2D3_INTF_LENGTH 0x1a08
 #define D2D3_INTF_CTRL0 0x1a09
 #define VIU_OSD1_CTRL_STAT 0x1a10
+#define		VIU_OSD1_OSD_BLK_ENABLE         BIT(0)
+#define		VIU_OSD1_POSTBLD_SRC_VD1        (1 << 8)
+#define		VIU_OSD1_POSTBLD_SRC_VD2        (2 << 8)
+#define		VIU_OSD1_POSTBLD_SRC_OSD1       (3 << 8)
+#define		VIU_OSD1_POSTBLD_SRC_OSD2       (4 << 8)
+#define		VIU_OSD1_OSD_ENABLE             BIT(21)
 #define VIU_OSD1_CTRL_STAT2 0x1a2d
 #define VIU_OSD1_COLOR_ADDR 0x1a11
 #define VIU_OSD1_COLOR 0x1a12
@@ -206,6 +214,35 @@
 #define VIU_OSD2_FIFO_CTRL_STAT 0x1a4b
 #define VIU_OSD2_TEST_RDDATA 0x1a4c
 #define VIU_OSD2_PROT_CTRL 0x1a4e
+#define VIU_OSD2_MALI_UNPACK_CTRL 0x1abd
+#define VIU_OSD2_DIMM_CTRL 0x1acf
+
+#define VIU_OSD3_CTRL_STAT 0x3d80
+#define VIU_OSD3_CTRL_STAT2 0x3d81
+#define VIU_OSD3_COLOR_ADDR 0x3d82
+#define VIU_OSD3_COLOR 0x3d83
+#define VIU_OSD3_TCOLOR_AG0 0x3d84
+#define VIU_OSD3_TCOLOR_AG1 0x3d85
+#define VIU_OSD3_TCOLOR_AG2 0x3d86
+#define VIU_OSD3_TCOLOR_AG3 0x3d87
+#define VIU_OSD3_BLK0_CFG_W0 0x3d88
+#define VIU_OSD3_BLK0_CFG_W1 0x3d8c
+#define VIU_OSD3_BLK0_CFG_W2 0x3d90
+#define VIU_OSD3_BLK0_CFG_W3 0x3d94
+#define VIU_OSD3_BLK0_CFG_W4 0x3d98
+#define VIU_OSD3_BLK1_CFG_W4 0x3d99
+#define VIU_OSD3_BLK2_CFG_W4 0x3d9a
+#define VIU_OSD3_FIFO_CTRL_STAT 0x3d9c
+#define VIU_OSD3_TEST_RDDATA 0x3d9d
+#define VIU_OSD3_PROT_CTRL 0x3d9e
+#define VIU_OSD3_MALI_UNPACK_CTRL 0x3d9f
+#define VIU_OSD3_DIMM_CTRL 0x3da0
+
+#define VIU_OSD_DDR_PRIORITY_URGENT      BIT(0)
+#define VIU_OSD_HOLD_FIFO_LINES(lines)   ((lines & 0x1f) << 5)
+#define VIU_OSD_FIFO_DEPTH_VAL(val)      ((val & 0x7f) << 12)
+#define VIU_OSD_WORDS_PER_BURST(words)   (((words & 0x4) >> 1) << 22)
+#define VIU_OSD_FIFO_LIMITS(size)        ((size & 0xf) << 24)
 
 #define VD1_IF0_GEN_REG 0x1a50
 #define VD1_IF0_CANVAS0 0x1a51
@@ -277,6 +314,27 @@
 #define VIU_OSD1_MATRIX_COEF31_32 0x1a9e
 #define VIU_OSD1_MATRIX_COEF40_41 0x1a9f
 #define VD1_IF0_GEN_REG3 0x1aa7
+
+#define VIU_OSD_BLENDO_H_START_END 0x1aa9
+#define VIU_OSD_BLENDO_V_START_END 0x1aaa
+#define VIU_OSD_BLEND_GEN_CTRL0 0x1aab
+#define VIU_OSD_BLEND_GEN_CTRL1 0x1aac
+#define VIU_OSD_BLEND_DUMMY_DATA 0x1aad
+#define VIU_OSD_BLEND_CURRENT_XY 0x1aae
+
+#define VIU_OSD2_MATRIX_CTRL 0x1ab0
+#define VIU_OSD2_MATRIX_COEF00_01 0x1ab1
+#define VIU_OSD2_MATRIX_COEF02_10 0x1ab2
+#define VIU_OSD2_MATRIX_COEF11_12 0x1ab3
+#define VIU_OSD2_MATRIX_COEF20_21 0x1ab4
+#define VIU_OSD2_MATRIX_COEF22 0x1ab5
+#define VIU_OSD2_MATRIX_OFFSET0_1 0x1ab6
+#define VIU_OSD2_MATRIX_OFFSET2 0x1ab7
+#define VIU_OSD2_MATRIX_PRE_OFFSET0_1 0x1ab8
+#define VIU_OSD2_MATRIX_PRE_OFFSET2 0x1ab9
+#define VIU_OSD2_MATRIX_PROBE_COLOR 0x1aba
+#define VIU_OSD2_MATRIX_HL_COLOR 0x1abb
+#define VIU_OSD2_MATRIX_PROBE_POS 0x1abc
 #define VIU_OSD1_EOTF_CTL 0x1ad4
 #define VIU_OSD1_EOTF_COEF00_01 0x1ad5
 #define VIU_OSD1_EOTF_COEF02_10 0x1ad6
@@ -295,6 +353,7 @@
 #define VPP_LINE_IN_LENGTH 0x1d01
 #define VPP_PIC_IN_HEIGHT 0x1d02
 #define VPP_SCALE_COEF_IDX 0x1d03
+#define		VPP_SCALE_HORIZONTAL_COEF       BIT(8)
 #define VPP_SCALE_COEF 0x1d04
 #define VPP_VSC_REGION12_STARTP 0x1d05
 #define VPP_VSC_REGION34_STARTP 0x1d06
@@ -316,6 +375,12 @@
 #define VPP_HSC_REGION4_PHASE_SLOPE 0x1d17
 #define VPP_HSC_PHASE_CTRL 0x1d18
 #define VPP_SC_MISC 0x1d19
+#define		VPP_SC_VD_EN_ENABLE             BIT(15)
+#define		VPP_SC_TOP_EN_ENABLE            BIT(16)
+#define		VPP_SC_HSC_EN_ENABLE            BIT(17)
+#define		VPP_SC_VSC_EN_ENABLE            BIT(18)
+#define		VPP_VSC_BANK_LENGTH(length)     (length & 0x7)
+#define		VPP_HSC_BANK_LENGTH(length)     ((length & 0x7) << 8)
 #define VPP_PREBLEND_VD1_H_START_END 0x1d1a
 #define VPP_PREBLEND_VD1_V_START_END 0x1d1b
 #define VPP_POSTBLEND_VD1_H_START_END 0x1d1c
@@ -325,24 +390,28 @@
 #define VPP_PREBLEND_H_SIZE 0x1d20
 #define VPP_POSTBLEND_H_SIZE 0x1d21
 #define VPP_HOLD_LINES 0x1d22
+#define		VPP_POSTBLEND_HOLD_LINES(lines) (lines & 0xf)
+#define		VPP_PREBLEND_HOLD_LINES(lines)  ((lines & 0xf) << 8)
 #define VPP_BLEND_ONECOLOR_CTRL 0x1d23
 #define VPP_PREBLEND_CURRENT_XY 0x1d24
 #define VPP_POSTBLEND_CURRENT_XY 0x1d25
 #define VPP_MISC 0x1d26
-#define		VPP_PREBLEND_ENABLE	BIT(6)
-#define		VPP_POSTBLEND_ENABLE	BIT(7)
-#define		VPP_OSD2_ALPHA_PREMULT	BIT(8)
-#define		VPP_OSD1_ALPHA_PREMULT	BIT(9)
-#define		VPP_VD1_POSTBLEND	BIT(10)
-#define		VPP_VD2_POSTBLEND	BIT(11)
-#define		VPP_OSD1_POSTBLEND	BIT(12)
-#define		VPP_OSD2_POSTBLEND	BIT(13)
-#define		VPP_VD1_PREBLEND	BIT(14)
-#define		VPP_VD2_PREBLEND	BIT(15)
-#define		VPP_OSD1_PREBLEND	BIT(16)
-#define		VPP_OSD2_PREBLEND	BIT(17)
-#define		VPP_COLOR_MNG_ENABLE	BIT(28)
+#define		VPP_PREBLEND_ENABLE             BIT(6)
+#define		VPP_POSTBLEND_ENABLE            BIT(7)
+#define		VPP_OSD2_ALPHA_PREMULT          BIT(8)
+#define		VPP_OSD1_ALPHA_PREMULT          BIT(9)
+#define		VPP_VD1_POSTBLEND               BIT(10)
+#define		VPP_VD2_POSTBLEND               BIT(11)
+#define		VPP_OSD1_POSTBLEND              BIT(12)
+#define		VPP_OSD2_POSTBLEND              BIT(13)
+#define		VPP_VD1_PREBLEND                BIT(14)
+#define		VPP_VD2_PREBLEND                BIT(15)
+#define		VPP_OSD1_PREBLEND               BIT(16)
+#define		VPP_OSD2_PREBLEND               BIT(17)
+#define		VPP_COLOR_MNG_ENABLE            BIT(28)
 #define VPP_OFIFO_SIZE 0x1d27
+#define		VPP_OFIFO_SIZE_MASK             GENMASK(13, 0)
+#define		VPP_OFIFO_SIZE_DEFAULT          (0xfff << 20 | 0x1000)
 #define VPP_FIFO_STATUS 0x1d28
 #define VPP_SMOKE_CTRL 0x1d29
 #define VPP_SMOKE1_VAL 0x1d2a
@@ -358,6 +427,8 @@
 #define VPP_HSC_PHASE_CTRL1 0x1d34
 #define VPP_HSC_INI_PAT_CTRL 0x1d35
 #define VPP_VADJ_CTRL 0x1d40
+#define		VPP_MINUS_BLACK_LVL_VADJ1_ENABLE BIT(1)
+
 #define VPP_VADJ1_Y 0x1d41
 #define VPP_VADJ1_MA_MB 0x1d42
 #define VPP_VADJ1_MC_MD 0x1d43
@@ -417,6 +488,7 @@
 #define VPP_PEAKING_VGAIN 0x1d92
 #define VPP_PEAKING_NLP_1 0x1d93
 #define VPP_DOLBY_CTRL 0x1d93
+#define VPP_PPS_DUMMY_DATA_MODE (1 << 17)
 #define VPP_PEAKING_NLP_2 0x1d94
 #define VPP_PEAKING_NLP_3 0x1d95
 #define VPP_PEAKING_NLP_4 0x1d96
@@ -471,6 +543,83 @@
 #define VPP_OSD_SCALE_COEF 0x1dcd
 #define VPP_INT_LINE_NUM 0x1dce
 
+#define VPP_WRAP_OSD1_MATRIX_COEF00_01 0x3d60
+#define VPP_WRAP_OSD1_MATRIX_COEF02_10 0x3d61
+#define VPP_WRAP_OSD1_MATRIX_COEF11_12 0x3d62
+#define VPP_WRAP_OSD1_MATRIX_COEF20_21 0x3d63
+#define VPP_WRAP_OSD1_MATRIX_COEF22 0x3d64
+#define VPP_WRAP_OSD1_MATRIX_COEF13_14 0x3d65
+#define VPP_WRAP_OSD1_MATRIX_COEF23_24 0x3d66
+#define VPP_WRAP_OSD1_MATRIX_COEF15_25 0x3d67
+#define VPP_WRAP_OSD1_MATRIX_CLIP 0x3d68
+#define VPP_WRAP_OSD1_MATRIX_OFFSET0_1 0x3d69
+#define VPP_WRAP_OSD1_MATRIX_OFFSET2 0x3d6a
+#define VPP_WRAP_OSD1_MATRIX_PRE_OFFSET0_1 0x3d6b
+#define VPP_WRAP_OSD1_MATRIX_PRE_OFFSET2 0x3d6c
+#define VPP_WRAP_OSD1_MATRIX_EN_CTRL 0x3d6d
+
+#define VPP_WRAP_OSD2_MATRIX_COEF00_01 0x3d70
+#define VPP_WRAP_OSD2_MATRIX_COEF02_10 0x3d71
+#define VPP_WRAP_OSD2_MATRIX_COEF11_12 0x3d72
+#define VPP_WRAP_OSD2_MATRIX_COEF20_21 0x3d73
+#define VPP_WRAP_OSD2_MATRIX_COEF22 0x3d74
+#define VPP_WRAP_OSD2_MATRIX_COEF13_14 0x3d75
+#define VPP_WRAP_OSD2_MATRIX_COEF23_24 0x3d76
+#define VPP_WRAP_OSD2_MATRIX_COEF15_25 0x3d77
+#define VPP_WRAP_OSD2_MATRIX_CLIP 0x3d78
+#define VPP_WRAP_OSD2_MATRIX_OFFSET0_1 0x3d79
+#define VPP_WRAP_OSD2_MATRIX_OFFSET2 0x3d7a
+#define VPP_WRAP_OSD2_MATRIX_PRE_OFFSET0_1 0x3d7b
+#define VPP_WRAP_OSD2_MATRIX_PRE_OFFSET2 0x3d7c
+#define VPP_WRAP_OSD2_MATRIX_EN_CTRL 0x3d7d
+
+#define VPP_WRAP_OSD3_MATRIX_COEF00_01 0x3db0
+#define VPP_WRAP_OSD3_MATRIX_COEF02_10 0x3db1
+#define VPP_WRAP_OSD3_MATRIX_COEF11_12 0x3db2
+#define VPP_WRAP_OSD3_MATRIX_COEF20_21 0x3db3
+#define VPP_WRAP_OSD3_MATRIX_COEF22 0x3db4
+#define VPP_WRAP_OSD3_MATRIX_COEF13_14 0x3db5
+#define VPP_WRAP_OSD3_MATRIX_COEF23_24 0x3db6
+#define VPP_WRAP_OSD3_MATRIX_COEF15_25 0x3db7
+#define VPP_WRAP_OSD3_MATRIX_CLIP 0x3db8
+#define VPP_WRAP_OSD3_MATRIX_OFFSET0_1 0x3db9
+#define VPP_WRAP_OSD3_MATRIX_OFFSET2 0x3dba
+#define VPP_WRAP_OSD3_MATRIX_PRE_OFFSET0_1 0x3dbb
+#define VPP_WRAP_OSD3_MATRIX_PRE_OFFSET2 0x3dbc
+#define VPP_WRAP_OSD3_MATRIX_EN_CTRL 0x3dbd
+
+/* osd2 scaler */
+#define OSD2_VSC_PHASE_STEP 0x3d00
+#define OSD2_VSC_INI_PHASE 0x3d01
+#define OSD2_VSC_CTRL0 0x3d02
+#define OSD2_HSC_PHASE_STEP 0x3d03
+#define OSD2_HSC_INI_PHASE 0x3d04
+#define OSD2_HSC_CTRL0 0x3d05
+#define OSD2_HSC_INI_PAT_CTRL 0x3d06
+#define OSD2_SC_DUMMY_DATA 0x3d07
+#define OSD2_SC_CTRL0 0x3d08
+#define OSD2_SCI_WH_M1 0x3d09
+#define OSD2_SCO_H_START_END 0x3d0a
+#define OSD2_SCO_V_START_END 0x3d0b
+#define OSD2_SCALE_COEF_IDX 0x3d18
+#define OSD2_SCALE_COEF 0x3d19
+
+/* osd34 scaler */
+#define OSD34_SCALE_COEF_IDX 0x3d1e
+#define OSD34_SCALE_COEF 0x3d1f
+#define OSD34_VSC_PHASE_STEP 0x3d20
+#define OSD34_VSC_INI_PHASE 0x3d21
+#define OSD34_VSC_CTRL0 0x3d22
+#define OSD34_HSC_PHASE_STEP 0x3d23
+#define OSD34_HSC_INI_PHASE 0x3d24
+#define OSD34_HSC_CTRL0 0x3d25
+#define OSD34_HSC_INI_PAT_CTRL 0x3d26
+#define OSD34_SC_DUMMY_DATA 0x3d27
+#define OSD34_SC_CTRL0 0x3d28
+#define OSD34_SCI_WH_M1 0x3d29
+#define OSD34_SCO_H_START_END 0x3d2a
+#define OSD34_SCO_V_START_END 0x3d2b
+
 /* viu2 */
 #define VIU2_ADDR_START 0x1e00
 #define VIU2_ADDR_END 0x1eff
@@ -584,6 +733,25 @@
 #define VENC_UPSAMPLE_CTRL0 0x1b64
 #define VENC_UPSAMPLE_CTRL1 0x1b65
 #define VENC_UPSAMPLE_CTRL2 0x1b66
+#define		VENC_UPSAMPLE_CTRL_F0_2_CLK_RATIO        BIT(0)
+#define		VENC_UPSAMPLE_CTRL_F1_EN                 BIT(5)
+#define		VENC_UPSAMPLE_CTRL_F1_UPSAMPLE_EN        BIT(6)
+#define		VENC_UPSAMPLE_CTRL_INTERLACE_HIGH_LUMA   (0x0 << 12)
+#define		VENC_UPSAMPLE_CTRL_CVBS                  (0x1 << 12)
+#define		VENC_UPSAMPLE_CTRL_S_VIDEO_LUMA          (0x2 << 12)
+#define		VENC_UPSAMPLE_CTRL_S_VIDEO_CHROMA        (0x3 << 12)
+#define		VENC_UPSAMPLE_CTRL_INTERLACE_PB          (0x4 << 12)
+#define		VENC_UPSAMPLE_CTRL_INTERLACE_PR          (0x5 << 12)
+#define		VENC_UPSAMPLE_CTRL_INTERLACE_R           (0x6 << 12)
+#define		VENC_UPSAMPLE_CTRL_INTERLACE_G           (0x7 << 12)
+#define		VENC_UPSAMPLE_CTRL_INTERLACE_B           (0x8 << 12)
+#define		VENC_UPSAMPLE_CTRL_PROGRESSIVE_Y         (0x9 << 12)
+#define		VENC_UPSAMPLE_CTRL_PROGRESSIVE_PB        (0xa << 12)
+#define		VENC_UPSAMPLE_CTRL_PROGRESSIVE_PR        (0xb << 12)
+#define		VENC_UPSAMPLE_CTRL_PROGRESSIVE_R         (0xc << 12)
+#define		VENC_UPSAMPLE_CTRL_PROGRESSIVE_G         (0xd << 12)
+#define		VENC_UPSAMPLE_CTRL_PROGRESSIVE_B         (0xe << 12)
+#define		VENC_UPSAMPLE_CTRL_VDAC_TEST_VALUE       (0xf << 12)
 #define TCON_INVERT_CTL 0x1b67
 #define VENC_VIDEO_PROG_MODE 0x1b68
 #define VENC_ENCI_LINE 0x1b69
@@ -592,6 +760,7 @@
 #define VENC_ENCP_PIXEL 0x1b6c
 #define VENC_STATA 0x1b6d
 #define VENC_INTCTRL 0x1b6e
+#define		VENC_INTCTRL_ENCI_LNRST_INT_EN  BIT(1)
 #define VENC_INTFLAG 0x1b6f
 #define VENC_VIDEO_TST_EN 0x1b70
 #define VENC_VIDEO_TST_MDSEL 0x1b71
@@ -602,6 +771,7 @@
 #define VENC_VIDEO_TST_CLRBAR_WIDTH 0x1b76
 #define VENC_VIDEO_TST_VDCNT_STSET 0x1b77
 #define VENC_VDAC_DACSEL0 0x1b78
+#define		VENC_VDAC_SEL_ATV_DMD           BIT(5)
 #define VENC_VDAC_DACSEL1 0x1b79
 #define VENC_VDAC_DACSEL2 0x1b7a
 #define VENC_VDAC_DACSEL3 0x1b7b
@@ -622,6 +792,7 @@
 #define VENC_VDAC_DAC5_GAINCTRL 0x1bfa
 #define VENC_VDAC_DAC5_OFFSET 0x1bfb
 #define VENC_VDAC_FIFO_CTRL 0x1bfc
+#define		VENC_VDAC_FIFO_EN_ENCI_ENABLE   BIT(13)
 #define ENCL_TCON_INVERT_CTL 0x1bfd
 #define ENCP_VIDEO_EN 0x1b80
 #define ENCP_VIDEO_SYNC_MODE 0x1b81
@@ -637,6 +808,7 @@
 #define ENCP_VIDEO_SYNC_OFFST 0x1b8b
 #define ENCP_VIDEO_MACV_OFFST 0x1b8c
 #define ENCP_VIDEO_MODE 0x1b8d
+#define		ENCP_VIDEO_MODE_DE_V_HIGH       BIT(14)
 #define ENCP_VIDEO_MODE_ADV 0x1b8e
 #define ENCP_DBG_PX_RST 0x1b90
 #define ENCP_DBG_LN_RST 0x1b91
@@ -715,6 +887,11 @@
 #define C656_FS_LNED 0x1be7
 #define ENCI_VIDEO_MODE 0x1b00
 #define ENCI_VIDEO_MODE_ADV 0x1b01
+#define		ENCI_VIDEO_MODE_ADV_DMXMD(val)          (val & 0x3)
+#define		ENCI_VIDEO_MODE_ADV_VBICTL_LINE_17_22   BIT(2)
+#define		ENCI_VIDEO_MODE_ADV_YBW_MEDIUM          (0 << 4)
+#define		ENCI_VIDEO_MODE_ADV_YBW_LOW             (0x1 << 4)
+#define		ENCI_VIDEO_MODE_ADV_YBW_HIGH            (0x2 << 4)
 #define ENCI_VIDEO_FSC_ADJ 0x1b02
 #define ENCI_VIDEO_BRIGHT 0x1b03
 #define ENCI_VIDEO_CONT 0x1b04
@@ -785,13 +962,17 @@
 #define ENCI_DBG_MAXPX 0x1b4c
 #define ENCI_DBG_MAXLN 0x1b4d
 #define ENCI_MACV_MAX_AMP 0x1b50
+#define		ENCI_MACV_MAX_AMP_ENABLE_CHANGE BIT(15)
+#define		ENCI_MACV_MAX_AMP_VAL(val)      (val & 0x83ff)
 #define ENCI_MACV_PULSE_LO 0x1b51
 #define ENCI_MACV_PULSE_HI 0x1b52
 #define ENCI_MACV_BKP_MAX 0x1b53
 #define ENCI_CFILT_CTRL 0x1b54
+#define		ENCI_CFILT_CMPT_SEL_HIGH        BIT(1)
 #define ENCI_CFILT7 0x1b55
 #define ENCI_YC_DELAY 0x1b56
 #define ENCI_VIDEO_EN 0x1b57
+#define		ENCI_VIDEO_EN_ENABLE            BIT(0)
 #define ENCI_DVI_HSO_BEGIN 0x1c00
 #define ENCI_DVI_HSO_END 0x1c01
 #define ENCI_DVI_VSO_BLINE_EVN 0x1c02
@@ -803,6 +984,10 @@
 #define ENCI_DVI_VSO_END_EVN 0x1c08
 #define ENCI_DVI_VSO_END_ODD 0x1c09
 #define ENCI_CFILT_CTRL2 0x1c0a
+#define		ENCI_CFILT_CMPT_CR_DLY(delay)   (delay & 0xf)
+#define		ENCI_CFILT_CMPT_CB_DLY(delay)   ((delay & 0xf) << 4)
+#define		ENCI_CFILT_CVBS_CR_DLY(delay)   ((delay & 0xf) << 8)
+#define		ENCI_CFILT_CVBS_CB_DLY(delay)   ((delay & 0xf) << 12)
 #define ENCI_DACSEL_0 0x1c0b
 #define ENCI_DACSEL_1 0x1c0c
 #define ENCP_DACSEL_0 0x1c0d
@@ -817,6 +1002,8 @@
 #define ENCI_TST_CLRBAR_WIDTH 0x1c16
 #define ENCI_TST_VDCNT_STSET 0x1c17
 #define ENCI_VFIFO2VD_CTL 0x1c18
+#define		ENCI_VFIFO2VD_CTL_ENABLE        BIT(0)
+#define		ENCI_VFIFO2VD_CTL_VD_SEL(val)   ((val & 0xff) << 8)
 #define ENCI_VFIFO2VD_PIXEL_START 0x1c19
 #define ENCI_VFIFO2VD_PIXEL_END 0x1c1a
 #define ENCI_VFIFO2VD_LINE_TOP_START 0x1c1b
@@ -879,6 +1066,7 @@
 #define VENC_VDAC_DAC5_FILT_CTRL0 0x1c56
 #define VENC_VDAC_DAC5_FILT_CTRL1 0x1c57
 #define VENC_VDAC_DAC0_FILT_CTRL0 0x1c58
+#define		VENC_VDAC_DAC0_FILT_CTRL0_EN    BIT(0)
 #define VENC_VDAC_DAC0_FILT_CTRL1 0x1c59
 #define VENC_VDAC_DAC1_FILT_CTRL0 0x1c5a
 #define VENC_VDAC_DAC1_FILT_CTRL1 0x1c5b
@@ -1284,6 +1472,18 @@
 #define		VIU2_SEL_VENC_ENCP	(2 << 2)
 #define		VIU2_SEL_VENC_ENCT	(3 << 2)
 #define VPU_HDMI_SETTING 0x271b
+#define		VPU_HDMI_ENCI_DATA_TO_HDMI      BIT(0)
+#define		VPU_HDMI_ENCP_DATA_TO_HDMI      BIT(1)
+#define		VPU_HDMI_INV_HSYNC              BIT(2)
+#define		VPU_HDMI_INV_VSYNC              BIT(3)
+#define		VPU_HDMI_OUTPUT_CRYCB           (0 << 5)
+#define		VPU_HDMI_OUTPUT_YCBCR           (1 << 5)
+#define		VPU_HDMI_OUTPUT_YCRCB           (2 << 5)
+#define		VPU_HDMI_OUTPUT_CBCRY           (3 << 5)
+#define		VPU_HDMI_OUTPUT_CBYCR           (4 << 5)
+#define		VPU_HDMI_OUTPUT_CRCBY           (5 << 5)
+#define		VPU_HDMI_WR_RATE(rate)          (((rate & 0x1f) - 1) << 8)
+#define		VPU_HDMI_RD_RATE(rate)          (((rate & 0x1f) - 1) << 12)
 #define ENCI_INFO_READ 0x271c
 #define ENCP_INFO_READ 0x271d
 #define ENCT_INFO_READ 0x271e
@@ -1360,6 +1560,7 @@
 #define VPU_RDARB_MODE_L1C2 0x2799
 #define VPU_RDARB_MODE_L2C1 0x279d
 #define VPU_WRARB_MODE_L2C1 0x27a2
+#define		VPU_RDARB_SLAVE_TO_MASTER_PORT(dc, port) (port << (16 + dc))
 
 /* osd super scale */
 #define OSDSR_HV_SIZEIN 0x3130
@@ -1390,4 +1591,150 @@
 #define OSDSR_YBIC_VCOEF0 0x3149
 #define OSDSR_CBIC_VCOEF0 0x314a
 
+/* osd afbcd on gxtvbb */
+#define OSD1_AFBCD_ENABLE 0x31a0
+#define OSD1_AFBCD_MODE 0x31a1
+#define OSD1_AFBCD_SIZE_IN 0x31a2
+#define OSD1_AFBCD_HDR_PTR 0x31a3
+#define OSD1_AFBCD_FRAME_PTR 0x31a4
+#define OSD1_AFBCD_CHROMA_PTR 0x31a5
+#define OSD1_AFBCD_CONV_CTRL 0x31a6
+#define OSD1_AFBCD_STATUS 0x31a8
+#define OSD1_AFBCD_PIXEL_HSCOPE 0x31a9
+#define OSD1_AFBCD_PIXEL_VSCOPE 0x31aa
+
+/* add for gxm and 962e dv core2 */
+#define DOLBY_CORE2A_SWAP_CTRL1	0x3434
+#define DOLBY_CORE2A_SWAP_CTRL2	0x3435
+
+/* osd afbc on g12a */
+#define VPU_MAFBC_BLOCK_ID 0x3a00
+#define VPU_MAFBC_IRQ_RAW_STATUS 0x3a01
+#define VPU_MAFBC_IRQ_CLEAR 0x3a02
+#define VPU_MAFBC_IRQ_MASK 0x3a03
+#define VPU_MAFBC_IRQ_STATUS 0x3a04
+#define VPU_MAFBC_COMMAND 0x3a05
+#define VPU_MAFBC_STATUS 0x3a06
+#define VPU_MAFBC_SURFACE_CFG 0x3a07
+#define VPU_MAFBC_HEADER_BUF_ADDR_LOW_S0 0x3a10
+#define VPU_MAFBC_HEADER_BUF_ADDR_HIGH_S0 0x3a11
+#define VPU_MAFBC_FORMAT_SPECIFIER_S0 0x3a12
+#define VPU_MAFBC_BUFFER_WIDTH_S0 0x3a13
+#define VPU_MAFBC_BUFFER_HEIGHT_S0 0x3a14
+#define VPU_MAFBC_BOUNDING_BOX_X_START_S0 0x3a15
+#define VPU_MAFBC_BOUNDING_BOX_X_END_S0 0x3a16
+#define VPU_MAFBC_BOUNDING_BOX_Y_START_S0 0x3a17
+#define VPU_MAFBC_BOUNDING_BOX_Y_END_S0 0x3a18
+#define VPU_MAFBC_OUTPUT_BUF_ADDR_LOW_S0 0x3a19
+#define VPU_MAFBC_OUTPUT_BUF_ADDR_HIGH_S0 0x3a1a
+#define VPU_MAFBC_OUTPUT_BUF_STRIDE_S0 0x3a1b
+#define VPU_MAFBC_PREFETCH_CFG_S0 0x3a1c
+
+#define VPU_MAFBC_HEADER_BUF_ADDR_LOW_S1 0x3a30
+#define VPU_MAFBC_HEADER_BUF_ADDR_HIGH_S1 0x3a31
+#define VPU_MAFBC_FORMAT_SPECIFIER_S1 0x3a32
+#define VPU_MAFBC_BUFFER_WIDTH_S1 0x3a33
+#define VPU_MAFBC_BUFFER_HEIGHT_S1 0x3a34
+#define VPU_MAFBC_BOUNDING_BOX_X_START_S1 0x3a35
+#define VPU_MAFBC_BOUNDING_BOX_X_END_S1 0x3a36
+#define VPU_MAFBC_BOUNDING_BOX_Y_START_S1 0x3a37
+#define VPU_MAFBC_BOUNDING_BOX_Y_END_S1 0x3a38
+#define VPU_MAFBC_OUTPUT_BUF_ADDR_LOW_S1 0x3a39
+#define VPU_MAFBC_OUTPUT_BUF_ADDR_HIGH_S1 0x3a3a
+#define VPU_MAFBC_OUTPUT_BUF_STRIDE_S1 0x3a3b
+#define VPU_MAFBC_PREFETCH_CFG_S1 0x3a3c
+
+#define VPU_MAFBC_HEADER_BUF_ADDR_LOW_S2 0x3a50
+#define VPU_MAFBC_HEADER_BUF_ADDR_HIGH_S2 0x3a51
+#define VPU_MAFBC_FORMAT_SPECIFIER_S2 0x3a52
+#define VPU_MAFBC_BUFFER_WIDTH_S2 0x3a53
+#define VPU_MAFBC_BUFFER_HEIGHT_S2 0x3a54
+#define VPU_MAFBC_BOUNDING_BOX_X_START_S2 0x3a55
+#define VPU_MAFBC_BOUNDING_BOX_X_END_S2 0x3a56
+#define VPU_MAFBC_BOUNDING_BOX_Y_START_S2 0x3a57
+#define VPU_MAFBC_BOUNDING_BOX_Y_END_S2 0x3a58
+#define VPU_MAFBC_OUTPUT_BUF_ADDR_LOW_S2 0x3a59
+#define VPU_MAFBC_OUTPUT_BUF_ADDR_HIGH_S2 0x3a5a
+#define VPU_MAFBC_OUTPUT_BUF_STRIDE_S2 0x3a5b
+#define VPU_MAFBC_PREFETCH_CFG_S2 0x3a5c
+
+#define VPU_MAFBC_HEADER_BUF_ADDR_LOW_S3 0x3a70
+#define VPU_MAFBC_HEADER_BUF_ADDR_HIGH_S3 0x3a71
+#define VPU_MAFBC_FORMAT_SPECIFIER_S3 0x3a72
+#define VPU_MAFBC_BUFFER_WIDTH_S3 0x3a73
+#define VPU_MAFBC_BUFFER_HEIGHT_S3 0x3a74
+#define VPU_MAFBC_BOUNDING_BOX_X_START_S3 0x3a75
+#define VPU_MAFBC_BOUNDING_BOX_X_END_S3 0x3a76
+#define VPU_MAFBC_BOUNDING_BOX_Y_START_S3 0x3a77
+#define VPU_MAFBC_BOUNDING_BOX_Y_END_S3 0x3a78
+#define VPU_MAFBC_OUTPUT_BUF_ADDR_LOW_S3 0x3a79
+#define VPU_MAFBC_OUTPUT_BUF_ADDR_HIGH_S3 0x3a7a
+#define VPU_MAFBC_OUTPUT_BUF_STRIDE_S3 0x3a7b
+#define VPU_MAFBC_PREFETCH_CFG_S3 0x3a7c
+
+#define DOLBY_PATH_CTRL 0x1a0c
+#define		DOLBY_BYPASS_EN(val)            (val & 0xf)
+#define OSD_PATH_MISC_CTRL 0x1a0e
+#define MALI_AFBCD_TOP_CTRL 0x1a0f
+
+#define VIU_OSD_BLEND_CTRL 0x39b0
+#define		VIU_OSD_BLEND_REORDER(dest, src)      ((src) << (dest * 4))
+#define		VIU_OSD_BLEND_DIN_EN(bits)            ((bits & 0xf) << 20)
+#define		VIU_OSD_BLEND1_DIN3_BYPASS_TO_DOUT1   BIT(24)
+#define		VIU_OSD_BLEND1_DOUT_BYPASS_TO_BLEND2  BIT(25)
+#define		VIU_OSD_BLEND_DIN0_BYPASS_TO_DOUT0    BIT(26)
+#define		VIU_OSD_BLEND_BLEN2_PREMULT_EN(input) ((input & 0x3) << 27)
+#define		VIU_OSD_BLEND_HOLD_LINES(lines)       ((u32)(lines & 0x7) << 29)
+#define VIU_OSD_BLEND_CTRL1 0x39c0
+#define VIU_OSD_BLEND_DIN0_SCOPE_H 0x39b1
+#define VIU_OSD_BLEND_DIN0_SCOPE_V 0x39b2
+#define VIU_OSD_BLEND_DIN1_SCOPE_H 0x39b3
+#define VIU_OSD_BLEND_DIN1_SCOPE_V 0x39b4
+#define VIU_OSD_BLEND_DIN2_SCOPE_H 0x39b5
+#define VIU_OSD_BLEND_DIN2_SCOPE_V 0x39b6
+#define VIU_OSD_BLEND_DIN3_SCOPE_H 0x39b7
+#define VIU_OSD_BLEND_DIN3_SCOPE_V 0x39b8
+#define VIU_OSD_BLEND_DUMMY_DATA0 0x39b9
+#define VIU_OSD_BLEND_DUMMY_ALPHA 0x39ba
+#define VIU_OSD_BLEND_BLEND0_SIZE 0x39bb
+#define VIU_OSD_BLEND_BLEND1_SIZE 0x39bc
+#define VIU_OSD_BLEND_RO_CURRENT_XY 0x39bf
+
+#define VPP_OUT_H_V_SIZE 0x1da5
+
+#define VPP_VD2_HDR_IN_SIZE 0x1df0
+#define VPP_OSD1_IN_SIZE 0x1df1
+#define VPP_GCLK_CTRL2 0x1df2
+#define VD2_PPS_DUMMY_DATA 0x1df4
+#define VPP_OSD1_BLD_H_SCOPE 0x1df5
+#define VPP_OSD1_BLD_V_SCOPE 0x1df6
+#define VPP_OSD2_BLD_H_SCOPE 0x1df7
+#define VPP_OSD2_BLD_V_SCOPE 0x1df8
+#define VPP_WRBAK_CTRL 0x1df9
+#define VPP_SLEEP_CTRL 0x1dfa
+#define VD1_BLEND_SRC_CTRL 0x1dfb
+#define VD2_BLEND_SRC_CTRL 0x1dfc
+#define		VD_BLEND_PREBLD_SRC_VD1         (1 << 0)
+#define		VD_BLEND_PREBLD_SRC_VD2         (2 << 0)
+#define		VD_BLEND_PREBLD_SRC_OSD1        (3 << 0)
+#define		VD_BLEND_PREBLD_SRC_OSD2        (4 << 0)
+#define		VD_BLEND_PREBLD_PREMULT_EN      BIT(4)
+#define		VD_BLEND_POSTBLD_SRC_VD1        (1 << 8)
+#define		VD_BLEND_POSTBLD_SRC_VD2        (2 << 8)
+#define		VD_BLEND_POSTBLD_SRC_OSD1       (3 << 8)
+#define		VD_BLEND_POSTBLD_SRC_OSD2       (4 << 8)
+#define		VD_BLEND_POSTBLD_PREMULT_EN     BIT(16)
+#define OSD1_BLEND_SRC_CTRL 0x1dfd
+#define OSD2_BLEND_SRC_CTRL 0x1dfe
+#define		OSD_BLEND_POSTBLD_SRC_VD1       (1 << 8)
+#define		OSD_BLEND_POSTBLD_SRC_VD2       (2 << 8)
+#define		OSD_BLEND_POSTBLD_SRC_OSD1      (3 << 8)
+#define		OSD_BLEND_POSTBLD_SRC_OSD2      (4 << 8)
+#define		OSD_BLEND_PATH_SEL_ENABLE       BIT(20)
+
+#define VPP_POST_BLEND_BLEND_DUMMY_DATA 0x3968
+#define VPP_POST_BLEND_DUMMY_ALPHA 0x3969
+#define VPP_RDARB_MODE 0x3978
+#define VPP_RDARB_REQEN_SLV 0x3979
+
 #endif /* __MESON_REGISTERS_H */
diff --git a/drivers/video/meson/meson_vclk.c b/drivers/video/meson/meson_vclk.c
index 693e0ebe39..0f628e920b 100644
--- a/drivers/video/meson/meson_vclk.c
+++ b/drivers/video/meson/meson_vclk.c
@@ -68,14 +68,20 @@ enum {
 #define CTS_HDMI_SYS_EN		BIT(8)
 
 #define HHI_HDMI_PLL_CNTL	0x320 /* 0xc8 offset in data sheet */
+#define HHI_HDMI_PLL_CNTL_EN	BIT(30)
 #define HHI_HDMI_PLL_CNTL2	0x324 /* 0xc9 offset in data sheet */
 #define HHI_HDMI_PLL_CNTL3	0x328 /* 0xca offset in data sheet */
 #define HHI_HDMI_PLL_CNTL4	0x32C /* 0xcb offset in data sheet */
 #define HHI_HDMI_PLL_CNTL5	0x330 /* 0xcc offset in data sheet */
 #define HHI_HDMI_PLL_CNTL6	0x334 /* 0xcd offset in data sheet */
+#define HHI_HDMI_PLL_CNTL7	0x338 /* 0xce offset in data sheet */
 
 #define HDMI_PLL_RESET		BIT(28)
+#define HDMI_PLL_RESET_G12A	BIT(29)
 #define HDMI_PLL_LOCK		BIT(31)
+#define HDMI_PLL_LOCK_G12A	(3 << 30)
+
+#define FREQ_1000_1001(_freq)	DIV_ROUND_CLOSEST(_freq * 1000, 1001)
 
 /* VID PLL Dividers */
 enum {
@@ -206,8 +212,6 @@ static void meson_venci_cvbs_clock_config(struct meson_vpu_priv *priv)
 {
 	unsigned int val;
 
-	debug("%s:%d\n", __func__, __LINE__);
-
 	/* Setup PLL to output 1.485GHz */
 	if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXBB)) {
 		hhi_write(HHI_HDMI_PLL_CNTL, 0x5800023d);
@@ -217,6 +221,10 @@ static void meson_venci_cvbs_clock_config(struct meson_vpu_priv *priv)
 		hhi_write(HHI_HDMI_PLL_CNTL5, 0x71486980);
 		hhi_write(HHI_HDMI_PLL_CNTL6, 0x00000e55);
 		hhi_write(HHI_HDMI_PLL_CNTL, 0x4800023d);
+
+		/* Poll for lock bit */
+		readl_poll_timeout(priv->hhi_base + HHI_HDMI_PLL_CNTL, val,
+				   (val & HDMI_PLL_LOCK), 10);
 	} else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM) ||
 		   meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL)) {
 		hhi_write(HHI_HDMI_PLL_CNTL, 0x4000027b);
@@ -231,13 +239,26 @@ static void meson_venci_cvbs_clock_config(struct meson_vpu_priv *priv)
 				HDMI_PLL_RESET, HDMI_PLL_RESET);
 		hhi_update_bits(HHI_HDMI_PLL_CNTL,
 				HDMI_PLL_RESET, 0);
-	}
 
-	debug("%s:%d\n", __func__, __LINE__);
+		/* Poll for lock bit */
+		readl_poll_timeout(priv->hhi_base + HHI_HDMI_PLL_CNTL, val,
+				   (val & HDMI_PLL_LOCK), 10);
+	} else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
+		hhi_write(HHI_HDMI_PLL_CNTL, 0x1a0504f7);
+		hhi_write(HHI_HDMI_PLL_CNTL2, 0x00010000);
+		hhi_write(HHI_HDMI_PLL_CNTL3, 0x00000000);
+		hhi_write(HHI_HDMI_PLL_CNTL4, 0x6a28dc00);
+		hhi_write(HHI_HDMI_PLL_CNTL5, 0x65771290);
+		hhi_write(HHI_HDMI_PLL_CNTL6, 0x39272000);
+		hhi_write(HHI_HDMI_PLL_CNTL7, 0x56540000);
+		hhi_write(HHI_HDMI_PLL_CNTL, 0x3a0504f7);
+		hhi_write(HHI_HDMI_PLL_CNTL, 0x1a0504f7);
 
-	/* Poll for lock bit */
-	readl_poll_timeout(priv->hhi_base + HHI_HDMI_PLL_CNTL, val,
-			   (val & HDMI_PLL_LOCK), 10);
+		/* Poll for lock bit */
+		readl_poll_timeout(priv->hhi_base + HHI_HDMI_PLL_CNTL, val,
+			((val & HDMI_PLL_LOCK_G12A) == HDMI_PLL_LOCK_G12A),
+			10);
+	}
 
 	/* Disable VCLK2 */
 	hhi_update_bits(HHI_VIID_CLK_CNTL, VCLK2_EN, 0);
@@ -250,8 +271,13 @@ static void meson_venci_cvbs_clock_config(struct meson_vpu_priv *priv)
 			VCLK2_DIV_MASK, (55 - 1));
 
 	/* select vid_pll for vclk2 */
-	hhi_update_bits(HHI_VIID_CLK_CNTL,
-			VCLK2_SEL_MASK, (4 << VCLK2_SEL_SHIFT));
+	if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
+		hhi_update_bits(HHI_VIID_CLK_CNTL,
+				VCLK2_SEL_MASK, (0 << VCLK2_SEL_SHIFT));
+	else
+		hhi_update_bits(HHI_VIID_CLK_CNTL,
+				VCLK2_SEL_MASK, (4 << VCLK2_SEL_SHIFT));
+
 	/* enable vclk2 gate */
 	hhi_update_bits(HHI_VIID_CLK_CNTL, VCLK2_EN, VCLK2_EN);
 
@@ -282,14 +308,12 @@ static void meson_venci_cvbs_clock_config(struct meson_vpu_priv *priv)
 	/* enable vdac_clk */
 	hhi_update_bits(HHI_VID_CLK_CNTL2,
 			CTS_VDAC_EN, CTS_VDAC_EN);
-
-	debug("%s:%d\n", __func__, __LINE__);
 }
 
 enum {
 /* PLL	O1 O2 O3 VP DV     EN TX */
 /* 4320 /4 /4 /1 /5 /1  => /2 /2 */
-	MESON_VCLK_HDMI_ENCI_54000 = 1,
+	MESON_VCLK_HDMI_ENCI_54000 = 0,
 /* 4320 /4 /4 /1 /5 /1  => /1 /2 */
 	MESON_VCLK_HDMI_DDR_54000,
 /* 2970 /4 /1 /1 /5 /1  => /1 /2 */
@@ -305,6 +329,7 @@ enum {
 };
 
 struct meson_vclk_params {
+	unsigned int pixel_freq;
 	unsigned int pll_base_freq;
 	unsigned int pll_od1;
 	unsigned int pll_od2;
@@ -313,6 +338,7 @@ struct meson_vclk_params {
 	unsigned int vclk_div;
 } params[] = {
 	[MESON_VCLK_HDMI_ENCI_54000] = {
+		.pixel_freq = 54000,
 		.pll_base_freq = 4320000,
 		.pll_od1 = 4,
 		.pll_od2 = 4,
@@ -321,6 +347,7 @@ struct meson_vclk_params {
 		.vclk_div = 1,
 	},
 	[MESON_VCLK_HDMI_DDR_54000] = {
+		.pixel_freq = 54000,
 		.pll_base_freq = 4320000,
 		.pll_od1 = 4,
 		.pll_od2 = 4,
@@ -329,6 +356,7 @@ struct meson_vclk_params {
 		.vclk_div = 1,
 	},
 	[MESON_VCLK_HDMI_DDR_148500] = {
+		.pixel_freq = 148500,
 		.pll_base_freq = 2970000,
 		.pll_od1 = 4,
 		.pll_od2 = 1,
@@ -337,6 +365,7 @@ struct meson_vclk_params {
 		.vclk_div = 1,
 	},
 	[MESON_VCLK_HDMI_74250] = {
+		.pixel_freq = 74250,
 		.pll_base_freq = 2970000,
 		.pll_od1 = 2,
 		.pll_od2 = 2,
@@ -345,6 +374,7 @@ struct meson_vclk_params {
 		.vclk_div = 1,
 	},
 	[MESON_VCLK_HDMI_148500] = {
+		.pixel_freq = 148500,
 		.pll_base_freq = 2970000,
 		.pll_od1 = 1,
 		.pll_od2 = 2,
@@ -353,14 +383,16 @@ struct meson_vclk_params {
 		.vclk_div = 1,
 	},
 	[MESON_VCLK_HDMI_297000] = {
-		.pll_base_freq = 2970000,
-		.pll_od1 = 1,
+		.pixel_freq = 297000,
+		.pll_base_freq = 5940000,
+		.pll_od1 = 2,
 		.pll_od2 = 1,
 		.pll_od3 = 1,
 		.vid_pll_div = VID_PLL_DIV_5,
 		.vclk_div = 2,
 	},
 	[MESON_VCLK_HDMI_594000] = {
+		.pixel_freq = 594000,
 		.pll_base_freq = 5940000,
 		.pll_od1 = 1,
 		.pll_od2 = 1,
@@ -368,6 +400,7 @@ struct meson_vclk_params {
 		.vid_pll_div = VID_PLL_DIV_5,
 		.vclk_div = 1,
 	},
+	{ /* sentinel */ },
 };
 
 static inline unsigned int pll_od_to_reg(unsigned int od)
@@ -431,6 +464,50 @@ void meson_hdmi_pll_set_params(struct meson_vpu_priv *priv, unsigned int m,
 		/* Poll for lock bit */
 		readl_poll_timeout(priv->hhi_base + HHI_HDMI_PLL_CNTL, val,
 				   (val & HDMI_PLL_LOCK), 10);
+	} else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
+		hhi_write(HHI_HDMI_PLL_CNTL, 0x0b3a0400 | m);
+
+		/* Enable and reset */
+		hhi_update_bits(HHI_HDMI_PLL_CNTL, 0x3 << 28, 0x3 << 28);
+
+		hhi_write(HHI_HDMI_PLL_CNTL2, frac);
+		hhi_write(HHI_HDMI_PLL_CNTL3, 0x00000000);
+
+		/* G12A HDMI PLL Needs specific parameters for 5.4GHz */
+		if (m >= 0xf7) {
+			if (frac < 0x10000) {
+				hhi_write(HHI_HDMI_PLL_CNTL4, 0x6a685c00);
+				hhi_write(HHI_HDMI_PLL_CNTL5, 0x11551293);
+			} else {
+				hhi_write(HHI_HDMI_PLL_CNTL4, 0xea68dc00);
+				hhi_write(HHI_HDMI_PLL_CNTL5, 0x65771290);
+			}
+			hhi_write(HHI_HDMI_PLL_CNTL6, 0x39272000);
+			hhi_write(HHI_HDMI_PLL_CNTL7, 0x55540000);
+		} else {
+			hhi_write(HHI_HDMI_PLL_CNTL4, 0x0a691c00);
+			hhi_write(HHI_HDMI_PLL_CNTL5, 0x33771290);
+			hhi_write(HHI_HDMI_PLL_CNTL6, 0x39270000);
+			hhi_write(HHI_HDMI_PLL_CNTL7, 0x50540000);
+		}
+
+		do {
+			/* Reset PLL */
+			hhi_update_bits(HHI_HDMI_PLL_CNTL,
+					HDMI_PLL_RESET_G12A,
+					HDMI_PLL_RESET_G12A);
+
+			/* UN-Reset PLL */
+			hhi_update_bits(HHI_HDMI_PLL_CNTL,
+					HDMI_PLL_RESET_G12A, 0);
+
+			/* Poll for lock bits */
+			if (!readl_poll_timeout(
+					priv->hhi_base + HHI_HDMI_PLL_CNTL, val,
+					((val & HDMI_PLL_LOCK_G12A)
+						== HDMI_PLL_LOCK_G12A), 100))
+				break;
+		} while (1);
 	}
 
 	if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXBB))
@@ -440,6 +517,9 @@ void meson_hdmi_pll_set_params(struct meson_vpu_priv *priv, unsigned int m,
 		 meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL))
 		hhi_update_bits(HHI_HDMI_PLL_CNTL3,
 				3 << 21, pll_od_to_reg(od1) << 21);
+	else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
+		hhi_update_bits(HHI_HDMI_PLL_CNTL,
+				3 << 16, pll_od_to_reg(od1) << 16);
 
 	if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXBB))
 		hhi_update_bits(HHI_HDMI_PLL_CNTL2,
@@ -448,6 +528,9 @@ void meson_hdmi_pll_set_params(struct meson_vpu_priv *priv, unsigned int m,
 		 meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL))
 		hhi_update_bits(HHI_HDMI_PLL_CNTL3,
 				3 << 23, pll_od_to_reg(od2) << 23);
+	else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
+		hhi_update_bits(HHI_HDMI_PLL_CNTL,
+				3 << 18, pll_od_to_reg(od2) << 18);
 
 	if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXBB))
 		hhi_update_bits(HHI_HDMI_PLL_CNTL2,
@@ -456,6 +539,9 @@ void meson_hdmi_pll_set_params(struct meson_vpu_priv *priv, unsigned int m,
 		 meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL))
 		hhi_update_bits(HHI_HDMI_PLL_CNTL3,
 				3 << 19, pll_od_to_reg(od3) << 19);
+	else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
+		hhi_update_bits(HHI_HDMI_PLL_CNTL,
+				3 << 20, pll_od_to_reg(od3) << 20);
 }
 
 #define XTAL_FREQ 24000
@@ -472,6 +558,7 @@ static unsigned int meson_hdmi_pll_get_m(struct meson_vpu_priv *priv,
 
 #define HDMI_FRAC_MAX_GXBB	4096
 #define HDMI_FRAC_MAX_GXL	1024
+#define HDMI_FRAC_MAX_G12A	131072
 
 static unsigned int meson_hdmi_pll_get_frac(struct meson_vpu_priv *priv,
 					    unsigned int m,
@@ -488,6 +575,9 @@ static unsigned int meson_hdmi_pll_get_frac(struct meson_vpu_priv *priv,
 		parent_freq *= 2;
 	}
 
+	if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
+		frac_max = HDMI_FRAC_MAX_G12A;
+
 	/* We can have a perfect match !*/
 	if (pll_freq / m == parent_freq &&
 	    pll_freq % m == 0)
@@ -519,6 +609,12 @@ static bool meson_hdmi_pll_validate_params(struct meson_vpu_priv *priv,
 			return false;
 		if (frac >= HDMI_FRAC_MAX_GXL)
 			return false;
+	} else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
+		/* Empiric supported min/max dividers */
+		if (m < 106 || m > 247)
+			return false;
+		if (frac >= HDMI_FRAC_MAX_G12A)
+			return false;
 	}
 
 	return true;
@@ -595,8 +691,10 @@ meson_vclk_set(struct meson_vpu_priv *priv, unsigned int pll_base_freq,
 	       unsigned int od1, unsigned int od2, unsigned int od3,
 	       unsigned int vid_pll_div, unsigned int vclk_div,
 	       unsigned int hdmi_tx_div, unsigned int venc_div,
-	       bool hdmi_use_enci)
+	       bool hdmi_use_enci, bool vic_alternate_clock)
 {
+	unsigned int m = 0, frac = 0;
+
 	/* Set HDMI-TX sys clock */
 	hhi_update_bits(HHI_HDMI_CLK_CNTL,
 			CTS_HDMI_SYS_SEL_MASK, 0);
@@ -611,34 +709,55 @@ meson_vclk_set(struct meson_vpu_priv *priv, unsigned int pll_base_freq,
 	} else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXBB)) {
 		switch (pll_base_freq) {
 		case 2970000:
-			meson_hdmi_pll_set_params(priv, 0x3d, 0xe00,
-						  od1, od2, od3);
+			m = 0x3d;
+			frac = vic_alternate_clock ? 0xd02 : 0xe00;
 			break;
 		case 4320000:
-			meson_hdmi_pll_set_params(priv, 0x5a, 0,
-						  od1, od2, od3);
+			m = vic_alternate_clock ? 0x59 : 0x5a;
+			frac = vic_alternate_clock ? 0xe8f : 0;
 			break;
 		case 5940000:
-			meson_hdmi_pll_set_params(priv, 0x7b, 0xc00,
-						  od1, od2, od3);
+			m = 0x7b;
+			frac = vic_alternate_clock ? 0xa05 : 0xc00;
 			break;
 		}
+
+		meson_hdmi_pll_set_params(priv, m, frac, od1, od2, od3);
 	} else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM) ||
 		   meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL)) {
 		switch (pll_base_freq) {
 		case 2970000:
-			meson_hdmi_pll_set_params(priv, 0x7b, 0x300,
-						  od1, od2, od3);
+			m = 0x7b;
+			frac = vic_alternate_clock ? 0x281 : 0x300;
+			break;
+		case 4320000:
+			m = vic_alternate_clock ? 0xb3 : 0xb4;
+			frac = vic_alternate_clock ? 0x347 : 0;
+			break;
+		case 5940000:
+			m = 0xf7;
+			frac = vic_alternate_clock ? 0x102 : 0x200;
+			break;
+		}
+
+		meson_hdmi_pll_set_params(priv, m, frac, od1, od2, od3);
+	} else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
+		switch (pll_base_freq) {
+		case 2970000:
+			m = 0x7b;
+			frac = vic_alternate_clock ? 0x140b4 : 0x18000;
 			break;
 		case 4320000:
-			meson_hdmi_pll_set_params(priv, 0xb4, 0,
-						  od1, od2, od3);
+			m = vic_alternate_clock ? 0xb3 : 0xb4;
+			frac = vic_alternate_clock ? 0x1a3ee : 0;
 			break;
 		case 5940000:
-			meson_hdmi_pll_set_params(priv, 0xf7, 0x200,
-						  od1, od2, od3);
+			m = 0xf7;
+			frac = vic_alternate_clock ? 0x8148 : 0x10000;
 			break;
 		}
+
+		meson_hdmi_pll_set_params(priv, m, frac, od1, od2, od3);
 	}
 
 	/* Setup vid_pll divider */
@@ -803,6 +922,7 @@ static void meson_vclk_setup(struct meson_vpu_priv *priv, unsigned int target,
 			     unsigned int vclk_freq, unsigned int venc_freq,
 			     unsigned int dac_freq, bool hdmi_use_enci)
 {
+	bool vic_alternate_clock = false;
 	unsigned int freq;
 	unsigned int hdmi_tx_div;
 	unsigned int venc_div;
@@ -820,8 +940,7 @@ static void meson_vclk_setup(struct meson_vpu_priv *priv, unsigned int target,
 		 * - encp encoder
 		 */
 		meson_vclk_set(priv, vclk_freq * 10, 0, 0, 0,
-			       VID_PLL_DIV_5, 2, 1, 1, false);
-
+			       VID_PLL_DIV_5, 2, 1, 1, false, false);
 		return;
 	}
 
@@ -841,31 +960,35 @@ static void meson_vclk_setup(struct meson_vpu_priv *priv, unsigned int target,
 		return;
 	}
 
-	switch (vclk_freq) {
-	case 54000:
-		if (hdmi_use_enci)
-			freq = MESON_VCLK_HDMI_ENCI_54000;
-		else
-			freq = MESON_VCLK_HDMI_DDR_54000;
-		break;
-	case 74250:
-		freq = MESON_VCLK_HDMI_74250;
-		break;
-	case 148500:
-		if (dac_freq != 148500)
-			freq = MESON_VCLK_HDMI_DDR_148500;
-		else
-			freq = MESON_VCLK_HDMI_148500;
-		break;
-	case 297000:
-		freq = MESON_VCLK_HDMI_297000;
-		break;
-	case 594000:
-		freq = MESON_VCLK_HDMI_594000;
-		break;
-	default:
-		printf("Fatal Error, invalid HDMI vclk freq %d\n",
-		       vclk_freq);
+	for (freq = 0 ; params[freq].pixel_freq ; ++freq) {
+		if (vclk_freq == params[freq].pixel_freq ||
+		    vclk_freq == FREQ_1000_1001(params[freq].pixel_freq)) {
+			if (vclk_freq != params[freq].pixel_freq)
+				vic_alternate_clock = true;
+			else
+				vic_alternate_clock = false;
+
+			if (freq == MESON_VCLK_HDMI_ENCI_54000 &&
+			    !hdmi_use_enci)
+				continue;
+
+			if (freq == MESON_VCLK_HDMI_DDR_54000 &&
+			    hdmi_use_enci)
+				continue;
+
+			if (freq == MESON_VCLK_HDMI_DDR_148500 &&
+			    dac_freq == vclk_freq)
+				continue;
+
+			if (freq == MESON_VCLK_HDMI_148500 &&
+			    dac_freq != vclk_freq)
+				continue;
+			break;
+		}
+	}
+
+	if (!params[freq].pixel_freq) {
+		pr_err("Fatal Error, invalid HDMI vclk freq %d\n", vclk_freq);
 		return;
 	}
 
@@ -873,7 +996,7 @@ static void meson_vclk_setup(struct meson_vpu_priv *priv, unsigned int target,
 		       params[freq].pll_od1, params[freq].pll_od2,
 		       params[freq].pll_od3, params[freq].vid_pll_div,
 		       params[freq].vclk_div, hdmi_tx_div, venc_div,
-		       hdmi_use_enci);
+		       hdmi_use_enci, vic_alternate_clock);
 }
 
 void meson_vpu_setup_vclk(struct udevice *dev,
diff --git a/drivers/video/meson/meson_venc.c b/drivers/video/meson/meson_venc.c
index d137dde8e2..5da4b3f096 100644
--- a/drivers/video/meson/meson_venc.c
+++ b/drivers/video/meson/meson_venc.c
@@ -23,7 +23,9 @@ enum meson_venc_source {
 };
 
 #define HHI_VDAC_CNTL0		0x2F4 /* 0xbd offset in data sheet */
+#define HHI_VDAC_CNTL0_G12A	0x2EC /* 0xbb offset in data sheet */
 #define HHI_VDAC_CNTL1		0x2F8 /* 0xbe offset in data sheet */
+#define HHI_VDAC_CNTL1_G12A	0x2F0 /* 0xbc offset in data sheet */
 
 struct meson_cvbs_enci_mode {
 	unsigned int mode_tag;
@@ -175,7 +177,7 @@ union meson_hdmi_venc_mode meson_hdmi_enci_mode_480i = {
 		.hso_end = 129,
 		.vso_even = 3,
 		.vso_odd = 260,
-		.macv_max_amp = 0x810b,
+		.macv_max_amp = 0xb,
 		.video_prog_mode = 0xf0,
 		.video_mode = 0x8,
 		.sch_adjust = 0x20,
@@ -195,7 +197,7 @@ union meson_hdmi_venc_mode meson_hdmi_enci_mode_576i = {
 		.hso_end = 129,
 		.vso_even = 3,
 		.vso_odd = 260,
-		.macv_max_amp = 8107,
+		.macv_max_amp = 0x7,
 		.video_prog_mode = 0xff,
 		.video_mode = 0x13,
 		.sch_adjust = 0x28,
@@ -774,12 +776,13 @@ static void meson_venc_hdmi_mode_set(struct meson_vpu_priv *priv,
 	unsigned int eof_lines;
 	unsigned int sof_lines;
 	unsigned int vsync_lines;
+	u32 reg;
 
 	/* Use VENCI for 480i and 576i and double HDMI pixels */
 	if (mode->flags & DISPLAY_FLAGS_DOUBLECLK) {
-		venc_hdmi_latency = 1;
 		hdmi_repeat = true;
 		use_enci = true;
+		venc_hdmi_latency = 1;
 	}
 
 	meson_venc_hdmi_get_dmt_vmode(mode, &vmode_dmt);
@@ -850,8 +853,11 @@ static void meson_venc_hdmi_mode_set(struct meson_vpu_priv *priv,
 		unsigned int lines_f1;
 
 		/* CVBS Filter settings */
-		writel(0x12, priv->io_base + _REG(ENCI_CFILT_CTRL));
-		writel(0x12, priv->io_base + _REG(ENCI_CFILT_CTRL2));
+		writel(ENCI_CFILT_CMPT_SEL_HIGH | 0x10,
+		       priv->io_base + _REG(ENCI_CFILT_CTRL));
+		writel(ENCI_CFILT_CMPT_CR_DLY(2) |
+		       ENCI_CFILT_CMPT_CB_DLY(1),
+		       priv->io_base + _REG(ENCI_CFILT_CTRL2));
 
 		/* Digital Video Select : Interlace, clk27 clk, external */
 		writel(0, priv->io_base + _REG(VENC_DVI_SETTING));
@@ -873,7 +879,8 @@ static void meson_venc_hdmi_mode_set(struct meson_vpu_priv *priv,
 		       priv->io_base + _REG(ENCI_SYNC_VSO_ODDLN));
 
 		/* Macrovision max amplitude change */
-		writel(vmode->enci.macv_max_amp,
+		writel(ENCI_MACV_MAX_AMP_ENABLE_CHANGE |
+		       ENCI_MACV_MAX_AMP_VAL(vmode->enci.macv_max_amp),
 		       priv->io_base + _REG(ENCI_MACV_MAX_AMP));
 
 		/* Video mode */
@@ -882,7 +889,8 @@ static void meson_venc_hdmi_mode_set(struct meson_vpu_priv *priv,
 		writel(vmode->enci.video_mode,
 		       priv->io_base + _REG(ENCI_VIDEO_MODE));
 
-		/* Advanced Video Mode :
+		/*
+		 * Advanced Video Mode :
 		 * Demux shifting 0x2
 		 * Blank line end at line17/22
 		 * High bandwidth Luma Filter
@@ -890,7 +898,10 @@ static void meson_venc_hdmi_mode_set(struct meson_vpu_priv *priv,
 		 * Bypass luma low pass filter
 		 * No macrovision on CSYNC
 		 */
-		writel(0x26, priv->io_base + _REG(ENCI_VIDEO_MODE_ADV));
+		writel(ENCI_VIDEO_MODE_ADV_DMXMD(2) |
+		       ENCI_VIDEO_MODE_ADV_VBICTL_LINE_17_22 |
+		       ENCI_VIDEO_MODE_ADV_YBW_HIGH,
+		       priv->io_base + _REG(ENCI_VIDEO_MODE_ADV));
 
 		writel(vmode->enci.sch_adjust,
 		       priv->io_base + _REG(ENCI_VIDEO_SCH));
@@ -905,8 +916,17 @@ static void meson_venc_hdmi_mode_set(struct meson_vpu_priv *priv,
 		/* UNreset Interlaced TV Encoder */
 		writel(0, priv->io_base + _REG(ENCI_DBG_PX_RST));
 
-		/* Enable Vfifo2vd, Y_Cb_Y_Cr select */
-		writel(0x4e01, priv->io_base + _REG(ENCI_VFIFO2VD_CTL));
+		/*
+		 * Enable Vfifo2vd and set Y_Cb_Y_Cr:
+		 * Corresponding value:
+		 * Y  => 00 or 10
+		 * Cb => 01
+		 * Cr => 11
+		 * Ex: 0x4e => 01001110 would mean Cb/Y/Cr/Y
+		 */
+		writel(ENCI_VFIFO2VD_CTL_ENABLE |
+		       ENCI_VFIFO2VD_CTL_VD_SEL(0x4e),
+		       priv->io_base + _REG(ENCI_VFIFO2VD_CTL));
 
 		/* Timings */
 		writel(vmode->enci.pixel_start,
@@ -928,7 +948,8 @@ static void meson_venc_hdmi_mode_set(struct meson_vpu_priv *priv,
 		meson_vpp_setup_mux(priv, MESON_VIU_VPP_MUX_ENCI);
 
 		/* Interlace video enable */
-		writel(1, priv->io_base + _REG(ENCI_VIDEO_EN));
+		writel(ENCI_VIDEO_EN_ENABLE,
+		       priv->io_base + _REG(ENCI_VIDEO_EN));
 
 		lines_f0 = mode->vback_porch.typ + mode->vactive.typ +
 			   mode->vback_porch.typ + mode->vsync_len.typ;
@@ -1177,7 +1198,8 @@ static void meson_venc_hdmi_mode_set(struct meson_vpu_priv *priv,
 		writel(1, priv->io_base + _REG(ENCP_VIDEO_EN));
 
 		/* Set DE signal's polarity is active high */
-		writel_bits(BIT(14), BIT(14),
+		writel_bits(ENCP_VIDEO_MODE_DE_V_HIGH,
+			    ENCP_VIDEO_MODE_DE_V_HIGH,
 			    priv->io_base + _REG(ENCP_VIDEO_MODE));
 
 		/* Program DE timing */
@@ -1302,21 +1324,52 @@ static void meson_venc_hdmi_mode_set(struct meson_vpu_priv *priv,
 		meson_vpp_setup_mux(priv, MESON_VIU_VPP_MUX_ENCP);
 	}
 
-	writel((use_enci ? 1 : 2) |
-		       (mode->flags & DISPLAY_FLAGS_HSYNC_HIGH ? 1 << 2 : 0) |
-		       (mode->flags & DISPLAY_FLAGS_VSYNC_HIGH ? 1 << 3 : 0) |
-		       4 << 5 |
-		       (venc_repeat ? 1 << 8 : 0) |
-		       (hdmi_repeat ? 1 << 12 : 0),
-		       priv->io_base + _REG(VPU_HDMI_SETTING));
+	/* Set VPU HDMI setting */
+	/* Select ENCP or ENCI data to HDMI */
+	if (use_enci)
+		reg = VPU_HDMI_ENCI_DATA_TO_HDMI;
+	else
+		reg = VPU_HDMI_ENCP_DATA_TO_HDMI;
+
+	/* Invert polarity of HSYNC from VENC */
+	if (mode->flags & DISPLAY_FLAGS_HSYNC_HIGH)
+		reg |= VPU_HDMI_INV_HSYNC;
+
+	/* Invert polarity of VSYNC from VENC */
+	if (mode->flags & DISPLAY_FLAGS_VSYNC_HIGH)
+		reg |= VPU_HDMI_INV_VSYNC;
+
+	/* Output data format: CbYCr */
+	reg |= VPU_HDMI_OUTPUT_CBYCR;
+
+	/*
+	 * Write rate to the async FIFO between VENC and HDMI.
+	 * One write every 2 wr_clk.
+	 */
+	if (venc_repeat)
+		reg |= VPU_HDMI_WR_RATE(2);
+
+	/*
+	 * Read rate to the async FIFO between VENC and HDMI.
+	 * One read every 2 wr_clk.
+	 */
+	if (hdmi_repeat)
+		reg |= VPU_HDMI_RD_RATE(2);
+
+	writel(reg, priv->io_base + _REG(VPU_HDMI_SETTING));
 }
 
 static void meson_venci_cvbs_mode_set(struct meson_vpu_priv *priv,
 				      struct meson_cvbs_enci_mode *mode)
 {
+	u32 reg;
+
 	/* CVBS Filter settings */
-	writel(0x12, priv->io_base + _REG(ENCI_CFILT_CTRL));
-	writel(0x12, priv->io_base + _REG(ENCI_CFILT_CTRL2));
+	writel(ENCI_CFILT_CMPT_SEL_HIGH | 0x10,
+	       priv->io_base + _REG(ENCI_CFILT_CTRL));
+	writel(ENCI_CFILT_CMPT_CR_DLY(2) |
+	       ENCI_CFILT_CMPT_CB_DLY(1),
+	       priv->io_base + _REG(ENCI_CFILT_CTRL2));
 
 	/* Digital Video Select : Interlace, clk27 clk, external */
 	writel(0, priv->io_base + _REG(VENC_DVI_SETTING));
@@ -1338,7 +1391,8 @@ static void meson_venci_cvbs_mode_set(struct meson_vpu_priv *priv,
 	       priv->io_base + _REG(ENCI_SYNC_VSO_ODDLN));
 
 	/* Macrovision max amplitude change */
-	writel(0x8100 + mode->macv_max_amp,
+	writel(ENCI_MACV_MAX_AMP_ENABLE_CHANGE |
+	       ENCI_MACV_MAX_AMP_VAL(mode->macv_max_amp),
 	       priv->io_base + _REG(ENCI_MACV_MAX_AMP));
 
 	/* Video mode */
@@ -1347,7 +1401,8 @@ static void meson_venci_cvbs_mode_set(struct meson_vpu_priv *priv,
 	writel(mode->video_mode,
 	       priv->io_base + _REG(ENCI_VIDEO_MODE));
 
-	/* Advanced Video Mode :
+	/*
+	 * Advanced Video Mode :
 	 * Demux shifting 0x2
 	 * Blank line end at line17/22
 	 * High bandwidth Luma Filter
@@ -1355,7 +1410,10 @@ static void meson_venci_cvbs_mode_set(struct meson_vpu_priv *priv,
 	 * Bypass luma low pass filter
 	 * No macrovision on CSYNC
 	 */
-	writel(0x26, priv->io_base + _REG(ENCI_VIDEO_MODE_ADV));
+	writel(ENCI_VIDEO_MODE_ADV_DMXMD(2) |
+	       ENCI_VIDEO_MODE_ADV_VBICTL_LINE_17_22 |
+	       ENCI_VIDEO_MODE_ADV_YBW_HIGH,
+	       priv->io_base + _REG(ENCI_VIDEO_MODE_ADV));
 
 	writel(mode->sch_adjust, priv->io_base + _REG(ENCI_VIDEO_SCH));
 
@@ -1387,16 +1445,50 @@ static void meson_venci_cvbs_mode_set(struct meson_vpu_priv *priv,
 	/* UNreset Interlaced TV Encoder */
 	writel(0, priv->io_base + _REG(ENCI_DBG_PX_RST));
 
-	/* Enable Vfifo2vd, Y_Cb_Y_Cr select */
-	writel(0x4e01, priv->io_base + _REG(ENCI_VFIFO2VD_CTL));
+	/*
+	 * Enable Vfifo2vd and set Y_Cb_Y_Cr:
+	 * Corresponding value:
+	 * Y  => 00 or 10
+	 * Cb => 01
+	 * Cr => 11
+	 * Ex: 0x4e => 01001110 would mean Cb/Y/Cr/Y
+	 */
+	writel(ENCI_VFIFO2VD_CTL_ENABLE |
+	       ENCI_VFIFO2VD_CTL_VD_SEL(0x4e),
+	       priv->io_base + _REG(ENCI_VFIFO2VD_CTL));
 
 	/* Power UP Dacs */
 	writel(0, priv->io_base + _REG(VENC_VDAC_SETTING));
 
 	/* Video Upsampling */
-	writel(0x0061, priv->io_base + _REG(VENC_UPSAMPLE_CTRL0));
-	writel(0x4061, priv->io_base + _REG(VENC_UPSAMPLE_CTRL1));
-	writel(0x5061, priv->io_base + _REG(VENC_UPSAMPLE_CTRL2));
+	/*
+	 * CTRL0, CTRL1 and CTRL2:
+	 * Filter0: input data sample every 2 cloks
+	 * Filter1: filtering and upsample enable
+	 */
+	reg = VENC_UPSAMPLE_CTRL_F0_2_CLK_RATIO | VENC_UPSAMPLE_CTRL_F1_EN |
+		VENC_UPSAMPLE_CTRL_F1_UPSAMPLE_EN;
+
+	/*
+	 * Upsample CTRL0:
+	 * Interlace High Bandwidth Luma
+	 */
+	writel(VENC_UPSAMPLE_CTRL_INTERLACE_HIGH_LUMA | reg,
+	       priv->io_base + _REG(VENC_UPSAMPLE_CTRL0));
+
+	/*
+	 * Upsample CTRL1:
+	 * Interlace Pb
+	 */
+	writel(VENC_UPSAMPLE_CTRL_INTERLACE_PB | reg,
+	       priv->io_base + _REG(VENC_UPSAMPLE_CTRL1));
+
+	/*
+	 * Upsample CTRL2:
+	 * Interlace R
+	 */
+	writel(VENC_UPSAMPLE_CTRL_INTERLACE_PR | reg,
+	       priv->io_base + _REG(VENC_UPSAMPLE_CTRL2));
 
 	/* Select Interlace Y DACs */
 	writel(0, priv->io_base + _REG(VENC_VDAC_DACSEL0));
@@ -1410,14 +1502,16 @@ static void meson_venci_cvbs_mode_set(struct meson_vpu_priv *priv,
 	meson_vpp_setup_mux(priv, MESON_VIU_VPP_MUX_ENCI);
 
 	/* Enable ENCI FIFO */
-	writel(0x2000, priv->io_base + _REG(VENC_VDAC_FIFO_CTRL));
+	writel(VENC_VDAC_FIFO_EN_ENCI_ENABLE,
+	       priv->io_base + _REG(VENC_VDAC_FIFO_CTRL));
 
 	/* Select ENCI DACs 0, 1, 4, and 5 */
 	writel(0x11, priv->io_base + _REG(ENCI_DACSEL_0));
 	writel(0x11, priv->io_base + _REG(ENCI_DACSEL_1));
 
 	/* Interlace video enable */
-	writel(1, priv->io_base + _REG(ENCI_VIDEO_EN));
+	writel(ENCI_VIDEO_EN_ENABLE,
+	       priv->io_base + _REG(ENCI_VIDEO_EN));
 
 	/* Configure Video Saturation / Contrast / Brightness / Hue */
 	writel(mode->video_saturation,
@@ -1430,7 +1524,8 @@ static void meson_venci_cvbs_mode_set(struct meson_vpu_priv *priv,
 	       priv->io_base + _REG(ENCI_VIDEO_HUE));
 
 	/* Enable DAC0 Filter */
-	writel(0x1, priv->io_base + _REG(VENC_VDAC_DAC0_FILT_CTRL0));
+	writel(VENC_VDAC_DAC0_FILT_CTRL0_EN,
+	       priv->io_base + _REG(VENC_VDAC_DAC0_FILT_CTRL0));
 	writel(0xfc48, priv->io_base + _REG(VENC_VDAC_DAC0_FILT_CTRL1));
 
 	/* 0 in Macrovision register 0 */
@@ -1441,15 +1536,21 @@ static void meson_venci_cvbs_mode_set(struct meson_vpu_priv *priv,
 	       priv->io_base + _REG(ENCI_SYNC_ADJ));
 
 	/* enable VDAC */
-	writel_bits(BIT(5), 0, priv->io_base + _REG(VENC_VDAC_DACSEL0));
+	writel_bits(VENC_VDAC_SEL_ATV_DMD, 0,
+		    priv->io_base + _REG(VENC_VDAC_DACSEL0));
 
 	if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXBB))
 		hhi_write(HHI_VDAC_CNTL0, 1);
 	else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL) ||
 		 meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM))
 		hhi_write(HHI_VDAC_CNTL0, 0xf0001);
+	else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
+		hhi_write(HHI_VDAC_CNTL0_G12A, 0x906001);
 
-	hhi_write(HHI_VDAC_CNTL1, 0);
+	if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
+		hhi_write(HHI_VDAC_CNTL1_G12A, 0);
+	else
+		hhi_write(HHI_VDAC_CNTL1, 0);
 }
 
 void meson_vpu_setup_venc(struct udevice *dev,
diff --git a/drivers/video/meson/meson_vpu.h b/drivers/video/meson/meson_vpu.h
index ef5f10eae3..3412dac052 100644
--- a/drivers/video/meson/meson_vpu.h
+++ b/drivers/video/meson/meson_vpu.h
@@ -14,6 +14,7 @@
 #include <video.h>
 #include <display.h>
 #include <linux/io.h>
+#include <linux/bitfield.h>
 #include "meson_registers.h"
 
 enum {
diff --git a/drivers/video/meson/meson_vpu_init.c b/drivers/video/meson/meson_vpu_init.c
index 92228b5ceb..12f8c4194a 100644
--- a/drivers/video/meson/meson_vpu_init.c
+++ b/drivers/video/meson/meson_vpu_init.c
@@ -12,7 +12,9 @@
 
 /* HHI Registers */
 #define HHI_VDAC_CNTL0		0x2F4 /* 0xbd offset in data sheet */
+#define HHI_VDAC_CNTL0_G12A	0x2EC /* 0xbd offset in data sheet */
 #define HHI_VDAC_CNTL1		0x2F8 /* 0xbe offset in data sheet */
+#define HHI_VDAC_CNTL1_G12A	0x2F0 /* 0xbe offset in data sheet */
 #define HHI_HDMI_PHY_CNTL0	0x3a0 /* 0xe8 offset in data sheet */
 
 /* OSDx_CTRL_STAT2 */
@@ -42,7 +44,7 @@ static void meson_vpp_write_scaling_filter_coefs(struct meson_vpu_priv *priv,
 {
 	int i;
 
-	writel(is_horizontal ? BIT(8) : 0,
+	writel(is_horizontal ? VPP_SCALE_HORIZONTAL_COEF : 0,
 	       priv->io_base + _REG(VPP_OSD_SCALE_COEF_IDX));
 	for (i = 0; i < 33; i++)
 		writel(coefs[i],
@@ -67,7 +69,7 @@ static void meson_vpp_write_vd_scaling_filter_coefs(struct meson_vpu_priv *priv,
 {
 	int i;
 
-	writel(is_horizontal ? BIT(8) : 0,
+	writel(is_horizontal ? VPP_SCALE_HORIZONTAL_COEF : 0,
 	       priv->io_base + _REG(VPP_SCALE_COEF_IDX));
 	for (i = 0; i < 33; i++)
 		writel(coefs[i],
@@ -112,6 +114,34 @@ static int eotf_bypass_coeff[EOTF_COEFF_SIZE] = {
 	EOTF_COEFF_RIGHTSHIFT /* right shift */
 };
 
+static void meson_viu_set_g12a_osd1_matrix(struct meson_vpu_priv *priv,
+					   int *m, bool csc_on)
+{
+	/* VPP WRAP OSD1 matrix */
+	writel(((m[0] & 0xfff) << 16) | (m[1] & 0xfff),
+	       priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_PRE_OFFSET0_1));
+	writel(m[2] & 0xfff,
+	       priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_PRE_OFFSET2));
+	writel(((m[3] & 0x1fff) << 16) | (m[4] & 0x1fff),
+	       priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF00_01));
+	writel(((m[5] & 0x1fff) << 16) | (m[6] & 0x1fff),
+	       priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF02_10));
+	writel(((m[7] & 0x1fff) << 16) | (m[8] & 0x1fff),
+	       priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF11_12));
+	writel(((m[9] & 0x1fff) << 16) | (m[10] & 0x1fff),
+	       priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF20_21));
+	writel((m[11] & 0x1fff) << 16,
+	       priv->io_base +	_REG(VPP_WRAP_OSD1_MATRIX_COEF22));
+
+	writel(((m[18] & 0xfff) << 16) | (m[19] & 0xfff),
+	       priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_OFFSET0_1));
+	writel(m[20] & 0xfff,
+	       priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_OFFSET2));
+
+	writel_bits(BIT(0), csc_on ? BIT(0) : 0,
+		    priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_EN_CTRL));
+}
+
 static void meson_viu_set_osd_matrix(struct meson_vpu_priv *priv,
 				     enum viu_matrix_sel_e m_select,
 				     int *m, bool csc_on)
@@ -322,20 +352,47 @@ static void meson_viu_load_matrix(struct meson_vpu_priv *priv)
 				 true);
 }
 
+static inline uint32_t meson_viu_osd_burst_length_reg(uint32_t length)
+{
+	u32 val = (((length & 0x80) % 24) / 12);
+
+	return (((val & 0x3) << 10) | (((val & 0x4) >> 2) << 31));
+}
+
 void meson_vpu_init(struct udevice *dev)
 {
 	struct meson_vpu_priv *priv = dev_get_priv(dev);
 	u32 reg;
 
-	/* vpu initialization */
-	writel(0x210000, priv->io_base + _REG(VPU_RDARB_MODE_L1C1));
-	writel(0x10000, priv->io_base + _REG(VPU_RDARB_MODE_L1C2));
-	writel(0x900000, priv->io_base + _REG(VPU_RDARB_MODE_L2C1));
-	writel(0x20000, priv->io_base + _REG(VPU_WRARB_MODE_L2C1));
+	/*
+	 * Slave dc0 and dc5 connected to master port 1.
+	 * By default other slaves are connected to master port 0.
+	 */
+	reg = VPU_RDARB_SLAVE_TO_MASTER_PORT(0, 1) |
+		VPU_RDARB_SLAVE_TO_MASTER_PORT(5, 1);
+	writel(reg, priv->io_base + _REG(VPU_RDARB_MODE_L1C1));
+
+	/* Slave dc0 connected to master port 1 */
+	reg = VPU_RDARB_SLAVE_TO_MASTER_PORT(0, 1);
+	writel(reg, priv->io_base + _REG(VPU_RDARB_MODE_L1C2));
+
+	/* Slave dc4 and dc7 connected to master port 1 */
+	reg = VPU_RDARB_SLAVE_TO_MASTER_PORT(4, 1) |
+		VPU_RDARB_SLAVE_TO_MASTER_PORT(7, 1);
+	writel(reg, priv->io_base + _REG(VPU_RDARB_MODE_L2C1));
+
+	/* Slave dc1 connected to master port 1 */
+	reg = VPU_RDARB_SLAVE_TO_MASTER_PORT(1, 1);
+	writel(reg, priv->io_base + _REG(VPU_WRARB_MODE_L2C1));
 
 	/* Disable CVBS VDAC */
-	hhi_write(HHI_VDAC_CNTL0, 0);
-	hhi_write(HHI_VDAC_CNTL1, 8);
+	if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
+		hhi_write(HHI_VDAC_CNTL0_G12A, 0);
+		hhi_write(HHI_VDAC_CNTL1_G12A, 8);
+	} else {
+		hhi_write(HHI_VDAC_CNTL0, 0);
+		hhi_write(HHI_VDAC_CNTL1, 8);
+	}
 
 	/* Power Down Dacs */
 	writel(0xff, priv->io_base + _REG(VENC_VDAC_SETTING));
@@ -344,7 +401,9 @@ void meson_vpu_init(struct udevice *dev)
 	hhi_write(HHI_HDMI_PHY_CNTL0, 0);
 
 	/* Disable HDMI */
-	writel_bits(0x3, 0, priv->io_base + _REG(VPU_HDMI_SETTING));
+	writel_bits(VPU_HDMI_ENCI_DATA_TO_HDMI |
+		    VPU_HDMI_ENCP_DATA_TO_HDMI, 0,
+		    priv->io_base + _REG(VPU_HDMI_SETTING));
 
 	/* Disable all encoders */
 	writel(0, priv->io_base + _REG(ENCI_VIDEO_EN));
@@ -360,43 +419,58 @@ void meson_vpu_init(struct udevice *dev)
 	} else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM)) {
 		writel_bits(0xff << 16, 0xff << 16,
 			    priv->io_base + _REG(VIU_MISC_CTRL1));
-		writel(0x20000, priv->io_base + _REG(VPP_DOLBY_CTRL));
+		writel(VPP_PPS_DUMMY_DATA_MODE,
+		       priv->io_base + _REG(VPP_DOLBY_CTRL));
 		writel(0x1020080,
 		       priv->io_base + _REG(VPP_DUMMY_DATA1));
-	}
+	} else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
+		writel(0xf, priv->io_base + _REG(DOLBY_PATH_CTRL));
 
 	/* Initialize vpu fifo control registers */
-	writel(readl(priv->io_base + _REG(VPP_OFIFO_SIZE)) |
-			0x77f, priv->io_base + _REG(VPP_OFIFO_SIZE));
-	writel(0x08080808, priv->io_base + _REG(VPP_HOLD_LINES));
-
-	/* Turn off preblend */
-	writel_bits(VPP_PREBLEND_ENABLE, 0,
-		    priv->io_base + _REG(VPP_MISC));
-
-	/* Turn off POSTBLEND */
-	writel_bits(VPP_POSTBLEND_ENABLE, 0,
-		    priv->io_base + _REG(VPP_MISC));
-
-	/* Force all planes off */
-	writel_bits(VPP_OSD1_POSTBLEND | VPP_OSD2_POSTBLEND |
-		    VPP_VD1_POSTBLEND | VPP_VD2_POSTBLEND |
-		    VPP_VD1_PREBLEND | VPP_VD2_PREBLEND, 0,
-		    priv->io_base + _REG(VPP_MISC));
-
-	/* Setup default VD settings */
-	writel(4096,
-	       priv->io_base + _REG(VPP_PREBLEND_VD1_H_START_END));
-	writel(4096,
-	       priv->io_base + _REG(VPP_BLEND_VD2_H_START_END));
+	if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
+		writel(VPP_OFIFO_SIZE_DEFAULT,
+		       priv->io_base + _REG(VPP_OFIFO_SIZE));
+	else
+		writel_bits(VPP_OFIFO_SIZE_MASK, 0x77f,
+			    priv->io_base + _REG(VPP_OFIFO_SIZE));
+	writel(VPP_POSTBLEND_HOLD_LINES(4) | VPP_PREBLEND_HOLD_LINES(4),
+	       priv->io_base + _REG(VPP_HOLD_LINES));
+
+	if (!meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
+		/* Turn off preblend */
+		writel_bits(VPP_PREBLEND_ENABLE, 0,
+			    priv->io_base + _REG(VPP_MISC));
+
+		/* Turn off POSTBLEND */
+		writel_bits(VPP_POSTBLEND_ENABLE, 0,
+			    priv->io_base + _REG(VPP_MISC));
+
+		/* Force all planes off */
+		writel_bits(VPP_OSD1_POSTBLEND | VPP_OSD2_POSTBLEND |
+			    VPP_VD1_POSTBLEND | VPP_VD2_POSTBLEND |
+			    VPP_VD1_PREBLEND | VPP_VD2_PREBLEND, 0,
+			    priv->io_base + _REG(VPP_MISC));
+
+		/* Setup default VD settings */
+		writel(4096,
+		       priv->io_base + _REG(VPP_PREBLEND_VD1_H_START_END));
+		writel(4096,
+		       priv->io_base + _REG(VPP_BLEND_VD2_H_START_END));
+	}
 
 	/* Disable Scalers */
 	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));
-	writel(4 | (4 << 8) | BIT(15),
+
+	writel(VPP_VSC_BANK_LENGTH(4) | VPP_HSC_BANK_LENGTH(4) |
+	       VPP_SC_VD_EN_ENABLE,
 	       priv->io_base + _REG(VPP_SC_MISC));
 
+	/* Enable minus black level for vadj1 */
+	writel(VPP_MINUS_BLACK_LVL_VADJ1_ENABLE,
+	       priv->io_base + _REG(VPP_VADJ_CTRL));
+
 	/* Write in the proper filter coefficients. */
 	meson_vpp_write_scaling_filter_coefs(priv,
 				vpp_filter_coefs_4point_bspline, false);
@@ -410,23 +484,31 @@ void meson_vpu_init(struct udevice *dev)
 						true);
 
 	/* Disable OSDs */
-	writel_bits(BIT(0) | BIT(21), 0,
+	writel_bits(VIU_OSD1_OSD_BLK_ENABLE | VIU_OSD1_OSD_ENABLE, 0,
 		    priv->io_base + _REG(VIU_OSD1_CTRL_STAT));
-	writel_bits(BIT(0) | BIT(21), 0,
+	writel_bits(VIU_OSD1_OSD_BLK_ENABLE | VIU_OSD1_OSD_ENABLE, 0,
 		    priv->io_base + _REG(VIU_OSD2_CTRL_STAT));
 
 	/* On GXL/GXM, Use the 10bit HDR conversion matrix */
 	if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM) ||
 	    meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL))
 		meson_viu_load_matrix(priv);
+	else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
+		meson_viu_set_g12a_osd1_matrix(priv, RGB709_to_YUV709l_coeff,
+					       true);
 
 	/* Initialize OSD1 fifo control register */
-	reg = BIT(0) |	/* Urgent DDR request priority */
-	      (4 << 5) | /* hold_fifo_lines */
-	      (3 << 10) | /* burst length 64 */
-	      (32 << 12) | /* fifo_depth_val: 32*8=256 */
-	      (2 << 22) | /* 4 words in 1 burst */
-	      (2 << 24);
+	reg = VIU_OSD_DDR_PRIORITY_URGENT |
+		VIU_OSD_HOLD_FIFO_LINES(4) |
+		VIU_OSD_FIFO_DEPTH_VAL(32) | /* fifo_depth_val: 32*8=256 */
+		VIU_OSD_WORDS_PER_BURST(4) | /* 4 words in 1 burst */
+		VIU_OSD_FIFO_LIMITS(2);      /* fifo_lim: 2*16=32 */
+
+	if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
+		reg |= meson_viu_osd_burst_length_reg(32);
+	else
+		reg |= meson_viu_osd_burst_length_reg(64);
+
 	writel(reg, priv->io_base + _REG(VIU_OSD1_FIFO_CTRL_STAT));
 	writel(reg, priv->io_base + _REG(VIU_OSD2_FIFO_CTRL_STAT));
 
@@ -437,4 +519,39 @@ void meson_vpu_init(struct udevice *dev)
 	writel_bits(0xff << OSD_REPLACE_SHIFT,
 		    0xff << OSD_REPLACE_SHIFT,
 		    priv->io_base + _REG(VIU_OSD2_CTRL_STAT2));
+
+	/* Disable VD1 AFBC */
+	/* di_mif0_en=0 mif0_to_vpp_en=0 di_mad_en=0 and afbc vd1 set=0*/
+	writel_bits(VIU_CTRL0_VD1_AFBC_MASK, 0,
+		    priv->io_base + _REG(VIU_MISC_CTRL0));
+	writel(0, priv->io_base + _REG(AFBC_ENABLE));
+
+	writel(0x00FF00C0,
+	       priv->io_base + _REG(VD1_IF0_LUMA_FIFO_SIZE));
+	writel(0x00FF00C0,
+	       priv->io_base + _REG(VD2_IF0_LUMA_FIFO_SIZE));
+
+	if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
+		writel(VIU_OSD_BLEND_REORDER(0, 1) |
+		       VIU_OSD_BLEND_REORDER(1, 0) |
+		       VIU_OSD_BLEND_REORDER(2, 0) |
+		       VIU_OSD_BLEND_REORDER(3, 0) |
+		       VIU_OSD_BLEND_DIN_EN(1) |
+		       VIU_OSD_BLEND1_DIN3_BYPASS_TO_DOUT1 |
+		       VIU_OSD_BLEND1_DOUT_BYPASS_TO_BLEND2 |
+		       VIU_OSD_BLEND_DIN0_BYPASS_TO_DOUT0 |
+		       VIU_OSD_BLEND_BLEN2_PREMULT_EN(1) |
+		       VIU_OSD_BLEND_HOLD_LINES(4),
+		       priv->io_base + _REG(VIU_OSD_BLEND_CTRL));
+		writel(OSD_BLEND_PATH_SEL_ENABLE,
+		       priv->io_base + _REG(OSD1_BLEND_SRC_CTRL));
+		writel(OSD_BLEND_PATH_SEL_ENABLE,
+		       priv->io_base + _REG(OSD2_BLEND_SRC_CTRL));
+		writel(0, priv->io_base + _REG(VD1_BLEND_SRC_CTRL));
+		writel(0, priv->io_base + _REG(VD2_BLEND_SRC_CTRL));
+		writel(0, priv->io_base + _REG(VIU_OSD_BLEND_DUMMY_DATA0));
+		writel(0, priv->io_base + _REG(VIU_OSD_BLEND_DUMMY_ALPHA));
+		writel_bits(DOLBY_BYPASS_EN(0xc), DOLBY_BYPASS_EN(0xc),
+			    priv->io_base + _REG(DOLBY_PATH_CTRL));
+	}
 }
-- 
2.22.0

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH 4/8] video: meson: sync with linux drm-misc tree
@ 2019-08-30 12:09   ` Neil Armstrong
  0 siblings, 0 replies; 38+ messages in thread
From: Neil Armstrong @ 2019-08-30 12:09 UTC (permalink / raw)
  To: u-boot-amlogic, agust; +Cc: Neil Armstrong, u-boot

Synchronize the Amlogic Meson Video driver back with the latest
DRM misc tree, adding G12A platform support, from the latest commit:
528a25d040bc ("drm: meson: use match data to detect vpu compatibility")

The sync includes the following changes from Linux adapted to U-Boot:
- Add support for VIC alternate timings
- Switch PLL to 5.94GHz base for 297Mhz pixel clock
- Add registers for G12A SoC
- Add G12A Support for VPP setup
- Add G12A Support for VIU setup
- Add G12A support for OSD1 Plane
- Add G12A support for plane handling in CRTC driver
- Add G12A support for CVBS Encoder
- Add G12A Video Clock setup
- Add G12A support for the DW-HDMI Glue
- fix G12A HDMI PLL settings for 4K60 1000/1001 variations
- fix primary plane disabling
- fix G12A primary plane disabling
- mask value when writing bits relaxed
- crtc: drv: vpp: viu: venc: use proper macros instead of magic constants
- global clean-up
- add macro used to enable HDMI PLL
- venc: set the correct macrovision max amplitude value

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 drivers/video/meson/meson_dw_hdmi.c   |  61 ++++-
 drivers/video/meson/meson_plane.c     |  47 +++-
 drivers/video/meson/meson_registers.h | 373 +++++++++++++++++++++++++-
 drivers/video/meson/meson_vclk.c      | 233 ++++++++++++----
 drivers/video/meson/meson_venc.c      | 169 +++++++++---
 drivers/video/meson/meson_vpu.h       |   1 +
 drivers/video/meson/meson_vpu_init.c  | 205 +++++++++++---
 7 files changed, 929 insertions(+), 160 deletions(-)

diff --git a/drivers/video/meson/meson_dw_hdmi.c b/drivers/video/meson/meson_dw_hdmi.c
index 9831d978fc..ae2e6288f3 100644
--- a/drivers/video/meson/meson_dw_hdmi.c
+++ b/drivers/video/meson/meson_dw_hdmi.c
@@ -24,6 +24,7 @@
 #define HDMITX_TOP_ADDR_REG	0x0
 #define HDMITX_TOP_DATA_REG	0x4
 #define HDMITX_TOP_CTRL_REG	0x8
+#define HDMITX_TOP_G12A_OFFSET	0x8000
 
 /* Controller Communication Channel */
 #define HDMITX_DWC_ADDR_REG	0x10
@@ -37,6 +38,8 @@
 #define HHI_HDMI_PHY_CNTL1	0x3a4 /* 0xe9 */
 #define HHI_HDMI_PHY_CNTL2	0x3a8 /* 0xea */
 #define HHI_HDMI_PHY_CNTL3	0x3ac /* 0xeb */
+#define HHI_HDMI_PHY_CNTL4	0x3b0 /* 0xec */
+#define HHI_HDMI_PHY_CNTL5	0x3b4 /* 0xed */
 
 struct meson_dw_hdmi {
 	struct udevice *dev;
@@ -48,6 +51,7 @@ enum hdmi_compatible {
 	HDMI_COMPATIBLE_GXBB = 0,
 	HDMI_COMPATIBLE_GXL = 1,
 	HDMI_COMPATIBLE_GXM = 2,
+	HDMI_COMPATIBLE_G12A = 3,
 };
 
 static inline bool meson_hdmi_is_compatible(struct meson_dw_hdmi *priv,
@@ -60,8 +64,14 @@ static inline bool meson_hdmi_is_compatible(struct meson_dw_hdmi *priv,
 
 static unsigned int dw_hdmi_top_read(struct dw_hdmi *hdmi, unsigned int addr)
 {
+	struct meson_dw_hdmi *priv = container_of(hdmi, struct meson_dw_hdmi,
+						  hdmi);
 	unsigned int data;
 
+	if (meson_hdmi_is_compatible(priv, HDMI_COMPATIBLE_G12A))
+		return readl(hdmi->ioaddr +
+			     HDMITX_TOP_G12A_OFFSET + (addr << 2));
+
 	/* ADDR must be written twice */
 	writel(addr & 0xffff, hdmi->ioaddr + HDMITX_TOP_ADDR_REG);
 	writel(addr & 0xffff, hdmi->ioaddr + HDMITX_TOP_ADDR_REG);
@@ -76,6 +86,15 @@ static unsigned int dw_hdmi_top_read(struct dw_hdmi *hdmi, unsigned int addr)
 static inline void dw_hdmi_top_write(struct dw_hdmi *hdmi,
 				     unsigned int addr, unsigned int data)
 {
+	struct meson_dw_hdmi *priv = container_of(hdmi, struct meson_dw_hdmi,
+						  hdmi);
+
+	if (meson_hdmi_is_compatible(priv, HDMI_COMPATIBLE_G12A)) {
+		writel(data, hdmi->ioaddr +
+		       HDMITX_TOP_G12A_OFFSET + (addr << 2));
+		return;
+	}
+
 	/* ADDR must be written twice */
 	writel(addr & 0xffff, hdmi->ioaddr + HDMITX_TOP_ADDR_REG);
 	writel(addr & 0xffff, hdmi->ioaddr + HDMITX_TOP_ADDR_REG);
@@ -237,7 +256,7 @@ static void meson_dw_hdmi_phy_setup_mode(struct meson_dw_hdmi *priv,
 			hhi_write(HHI_HDMI_PHY_CNTL0, 0x33604142);
 			hhi_write(HHI_HDMI_PHY_CNTL3, 0x0016315b);
 		}
-	} else {
+	} else if (meson_hdmi_is_compatible(priv, HDMI_COMPATIBLE_GXBB)) {
 		if (pixel_clock >= 371250) {
 			/* 5.94Gbps, 3.7125Gbps */
 			hhi_write(HHI_HDMI_PHY_CNTL0, 0x33353245);
@@ -251,6 +270,23 @@ static void meson_dw_hdmi_phy_setup_mode(struct meson_dw_hdmi *priv,
 			hhi_write(HHI_HDMI_PHY_CNTL0, 0x33632122);
 			hhi_write(HHI_HDMI_PHY_CNTL3, 0x2000115b);
 		}
+	} else if (meson_hdmi_is_compatible(priv, HDMI_COMPATIBLE_G12A)) {
+		if (pixel_clock >= 371250) {
+			/* 5.94Gbps, 3.7125Gbps */
+			hhi_write(HHI_HDMI_PHY_CNTL0, 0x37eb65c4);
+			hhi_write(HHI_HDMI_PHY_CNTL3, 0x2ab0ff3b);
+			hhi_write(HHI_HDMI_PHY_CNTL5, 0x0000080b);
+		} else if (pixel_clock >= 297000) {
+			/* 2.97Gbps */
+			hhi_write(HHI_HDMI_PHY_CNTL0, 0x33eb6262);
+			hhi_write(HHI_HDMI_PHY_CNTL3, 0x2ab0ff3b);
+			hhi_write(HHI_HDMI_PHY_CNTL5, 0x00000003);
+		} else {
+			/* 1.485Gbps, and below */
+			hhi_write(HHI_HDMI_PHY_CNTL0, 0x33eb4242);
+			hhi_write(HHI_HDMI_PHY_CNTL3, 0x2ab0ff3b);
+			hhi_write(HHI_HDMI_PHY_CNTL5, 0x00000003);
+		}
 	}
 }
 
@@ -292,7 +328,8 @@ static int meson_dw_hdmi_phy_init(struct dw_hdmi *hdmi, uint pixel_clock)
 
 	/* BIT_INVERT */
 	if (meson_hdmi_is_compatible(priv, HDMI_COMPATIBLE_GXL) ||
-	    meson_hdmi_is_compatible(priv, HDMI_COMPATIBLE_GXM))
+	    meson_hdmi_is_compatible(priv, HDMI_COMPATIBLE_GXM) ||
+	    meson_hdmi_is_compatible(priv, HDMI_COMPATIBLE_G12A))
 		dw_hdmi_hhi_update_bits(priv, HHI_HDMI_PHY_CNTL1, BIT(17), 0);
 	else
 		dw_hdmi_hhi_update_bits(priv, HHI_HDMI_PHY_CNTL1,
@@ -356,8 +393,12 @@ static int meson_dw_hdmi_probe(struct udevice *dev)
 	priv->hdmi.hdmi_data.enc_out_bus_format = MEDIA_BUS_FMT_RGB888_1X24;
 	priv->hdmi.hdmi_data.enc_in_bus_format = MEDIA_BUS_FMT_YUV8_1X24;
 	priv->hdmi.phy_set = meson_dw_hdmi_phy_init;
-	priv->hdmi.write_reg = dw_hdmi_dwc_write;
-	priv->hdmi.read_reg = dw_hdmi_dwc_read;
+	if (meson_hdmi_is_compatible(priv, HDMI_COMPATIBLE_G12A))
+		priv->hdmi.reg_io_width = 1;
+	else {
+		priv->hdmi.write_reg = dw_hdmi_dwc_write;
+		priv->hdmi.read_reg = dw_hdmi_dwc_read;
+	}
 	priv->hdmi.i2c_clk_high = 0x67;
 	priv->hdmi.i2c_clk_low = 0x78;
 
@@ -409,9 +450,13 @@ static int meson_dw_hdmi_probe(struct udevice *dev)
 	if (ret)
 		return ret;
 
-	/* Enable APB3 fail on error */
-	writel_bits(BIT(15), BIT(15), priv->hdmi.ioaddr + HDMITX_TOP_CTRL_REG);
-	writel_bits(BIT(15), BIT(15), priv->hdmi.ioaddr + HDMITX_DWC_CTRL_REG);
+	if (!meson_hdmi_is_compatible(priv, HDMI_COMPATIBLE_G12A)) {
+		/* Enable APB3 fail on error */
+		writel_bits(BIT(15), BIT(15),
+			    priv->hdmi.ioaddr + HDMITX_TOP_CTRL_REG);
+		writel_bits(BIT(15), BIT(15),
+			    priv->hdmi.ioaddr + HDMITX_DWC_CTRL_REG);
+	}
 
 	/* Bring out of reset */
 	dw_hdmi_top_write(&priv->hdmi, HDMITX_TOP_SW_RESET,  0);
@@ -448,6 +493,8 @@ static const struct udevice_id meson_dw_hdmi_ids[] = {
 		.data = HDMI_COMPATIBLE_GXL },
 	{ .compatible = "amlogic,meson-gxm-dw-hdmi",
 		.data = HDMI_COMPATIBLE_GXM },
+	{ .compatible = "amlogic,meson-g12a-dw-hdmi",
+		.data = HDMI_COMPATIBLE_G12A },
 	{ }
 };
 
diff --git a/drivers/video/meson/meson_plane.c b/drivers/video/meson/meson_plane.c
index 63a4bf2d8d..2bc9327e1e 100644
--- a/drivers/video/meson/meson_plane.c
+++ b/drivers/video/meson/meson_plane.c
@@ -108,12 +108,33 @@ void meson_vpu_setup_plane(struct udevice *dev, bool is_interlaced)
 	dest_y1 = src_y1 = 0;
 	dest_y2 = src_y2 = uc_priv->ysize;
 
-	/* Enable VPP Postblend */
-	writel(uc_priv->xsize,
-	       priv->io_base + _REG(VPP_POSTBLEND_H_SIZE));
+	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));
+		writel_bits(VPP_POSTBLEND_ENABLE, VPP_POSTBLEND_ENABLE,
+			    priv->io_base + _REG(VPP_MISC));
+	}
 
 	/* uc_plat->base is the framebuffer */
 
@@ -172,6 +193,18 @@ void meson_vpu_setup_plane(struct udevice *dev, bool is_interlaced)
 			   MESON_CANVAS_BLKMODE_LINEAR);
 
 	/* Enable OSD1 */
-	writel_bits(VPP_OSD1_POSTBLEND, VPP_OSD1_POSTBLEND,
-		    priv->io_base + _REG(VPP_MISC));
+	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));
 }
diff --git a/drivers/video/meson/meson_registers.h b/drivers/video/meson/meson_registers.h
index 01fe7d2431..39e8ec8639 100644
--- a/drivers/video/meson/meson_registers.h
+++ b/drivers/video/meson/meson_registers.h
@@ -136,11 +136,19 @@
 #define VIU_ADDR_START 0x1a00
 #define VIU_ADDR_END 0x1aff
 #define VIU_SW_RESET 0x1a01
+#define		VIU_SW_RESET_OSD1               BIT(0)
 #define VIU_MISC_CTRL0 0x1a06
+#define		VIU_CTRL0_VD1_AFBC_MASK         0x170000
 #define VIU_MISC_CTRL1 0x1a07
 #define D2D3_INTF_LENGTH 0x1a08
 #define D2D3_INTF_CTRL0 0x1a09
 #define VIU_OSD1_CTRL_STAT 0x1a10
+#define		VIU_OSD1_OSD_BLK_ENABLE         BIT(0)
+#define		VIU_OSD1_POSTBLD_SRC_VD1        (1 << 8)
+#define		VIU_OSD1_POSTBLD_SRC_VD2        (2 << 8)
+#define		VIU_OSD1_POSTBLD_SRC_OSD1       (3 << 8)
+#define		VIU_OSD1_POSTBLD_SRC_OSD2       (4 << 8)
+#define		VIU_OSD1_OSD_ENABLE             BIT(21)
 #define VIU_OSD1_CTRL_STAT2 0x1a2d
 #define VIU_OSD1_COLOR_ADDR 0x1a11
 #define VIU_OSD1_COLOR 0x1a12
@@ -206,6 +214,35 @@
 #define VIU_OSD2_FIFO_CTRL_STAT 0x1a4b
 #define VIU_OSD2_TEST_RDDATA 0x1a4c
 #define VIU_OSD2_PROT_CTRL 0x1a4e
+#define VIU_OSD2_MALI_UNPACK_CTRL 0x1abd
+#define VIU_OSD2_DIMM_CTRL 0x1acf
+
+#define VIU_OSD3_CTRL_STAT 0x3d80
+#define VIU_OSD3_CTRL_STAT2 0x3d81
+#define VIU_OSD3_COLOR_ADDR 0x3d82
+#define VIU_OSD3_COLOR 0x3d83
+#define VIU_OSD3_TCOLOR_AG0 0x3d84
+#define VIU_OSD3_TCOLOR_AG1 0x3d85
+#define VIU_OSD3_TCOLOR_AG2 0x3d86
+#define VIU_OSD3_TCOLOR_AG3 0x3d87
+#define VIU_OSD3_BLK0_CFG_W0 0x3d88
+#define VIU_OSD3_BLK0_CFG_W1 0x3d8c
+#define VIU_OSD3_BLK0_CFG_W2 0x3d90
+#define VIU_OSD3_BLK0_CFG_W3 0x3d94
+#define VIU_OSD3_BLK0_CFG_W4 0x3d98
+#define VIU_OSD3_BLK1_CFG_W4 0x3d99
+#define VIU_OSD3_BLK2_CFG_W4 0x3d9a
+#define VIU_OSD3_FIFO_CTRL_STAT 0x3d9c
+#define VIU_OSD3_TEST_RDDATA 0x3d9d
+#define VIU_OSD3_PROT_CTRL 0x3d9e
+#define VIU_OSD3_MALI_UNPACK_CTRL 0x3d9f
+#define VIU_OSD3_DIMM_CTRL 0x3da0
+
+#define VIU_OSD_DDR_PRIORITY_URGENT      BIT(0)
+#define VIU_OSD_HOLD_FIFO_LINES(lines)   ((lines & 0x1f) << 5)
+#define VIU_OSD_FIFO_DEPTH_VAL(val)      ((val & 0x7f) << 12)
+#define VIU_OSD_WORDS_PER_BURST(words)   (((words & 0x4) >> 1) << 22)
+#define VIU_OSD_FIFO_LIMITS(size)        ((size & 0xf) << 24)
 
 #define VD1_IF0_GEN_REG 0x1a50
 #define VD1_IF0_CANVAS0 0x1a51
@@ -277,6 +314,27 @@
 #define VIU_OSD1_MATRIX_COEF31_32 0x1a9e
 #define VIU_OSD1_MATRIX_COEF40_41 0x1a9f
 #define VD1_IF0_GEN_REG3 0x1aa7
+
+#define VIU_OSD_BLENDO_H_START_END 0x1aa9
+#define VIU_OSD_BLENDO_V_START_END 0x1aaa
+#define VIU_OSD_BLEND_GEN_CTRL0 0x1aab
+#define VIU_OSD_BLEND_GEN_CTRL1 0x1aac
+#define VIU_OSD_BLEND_DUMMY_DATA 0x1aad
+#define VIU_OSD_BLEND_CURRENT_XY 0x1aae
+
+#define VIU_OSD2_MATRIX_CTRL 0x1ab0
+#define VIU_OSD2_MATRIX_COEF00_01 0x1ab1
+#define VIU_OSD2_MATRIX_COEF02_10 0x1ab2
+#define VIU_OSD2_MATRIX_COEF11_12 0x1ab3
+#define VIU_OSD2_MATRIX_COEF20_21 0x1ab4
+#define VIU_OSD2_MATRIX_COEF22 0x1ab5
+#define VIU_OSD2_MATRIX_OFFSET0_1 0x1ab6
+#define VIU_OSD2_MATRIX_OFFSET2 0x1ab7
+#define VIU_OSD2_MATRIX_PRE_OFFSET0_1 0x1ab8
+#define VIU_OSD2_MATRIX_PRE_OFFSET2 0x1ab9
+#define VIU_OSD2_MATRIX_PROBE_COLOR 0x1aba
+#define VIU_OSD2_MATRIX_HL_COLOR 0x1abb
+#define VIU_OSD2_MATRIX_PROBE_POS 0x1abc
 #define VIU_OSD1_EOTF_CTL 0x1ad4
 #define VIU_OSD1_EOTF_COEF00_01 0x1ad5
 #define VIU_OSD1_EOTF_COEF02_10 0x1ad6
@@ -295,6 +353,7 @@
 #define VPP_LINE_IN_LENGTH 0x1d01
 #define VPP_PIC_IN_HEIGHT 0x1d02
 #define VPP_SCALE_COEF_IDX 0x1d03
+#define		VPP_SCALE_HORIZONTAL_COEF       BIT(8)
 #define VPP_SCALE_COEF 0x1d04
 #define VPP_VSC_REGION12_STARTP 0x1d05
 #define VPP_VSC_REGION34_STARTP 0x1d06
@@ -316,6 +375,12 @@
 #define VPP_HSC_REGION4_PHASE_SLOPE 0x1d17
 #define VPP_HSC_PHASE_CTRL 0x1d18
 #define VPP_SC_MISC 0x1d19
+#define		VPP_SC_VD_EN_ENABLE             BIT(15)
+#define		VPP_SC_TOP_EN_ENABLE            BIT(16)
+#define		VPP_SC_HSC_EN_ENABLE            BIT(17)
+#define		VPP_SC_VSC_EN_ENABLE            BIT(18)
+#define		VPP_VSC_BANK_LENGTH(length)     (length & 0x7)
+#define		VPP_HSC_BANK_LENGTH(length)     ((length & 0x7) << 8)
 #define VPP_PREBLEND_VD1_H_START_END 0x1d1a
 #define VPP_PREBLEND_VD1_V_START_END 0x1d1b
 #define VPP_POSTBLEND_VD1_H_START_END 0x1d1c
@@ -325,24 +390,28 @@
 #define VPP_PREBLEND_H_SIZE 0x1d20
 #define VPP_POSTBLEND_H_SIZE 0x1d21
 #define VPP_HOLD_LINES 0x1d22
+#define		VPP_POSTBLEND_HOLD_LINES(lines) (lines & 0xf)
+#define		VPP_PREBLEND_HOLD_LINES(lines)  ((lines & 0xf) << 8)
 #define VPP_BLEND_ONECOLOR_CTRL 0x1d23
 #define VPP_PREBLEND_CURRENT_XY 0x1d24
 #define VPP_POSTBLEND_CURRENT_XY 0x1d25
 #define VPP_MISC 0x1d26
-#define		VPP_PREBLEND_ENABLE	BIT(6)
-#define		VPP_POSTBLEND_ENABLE	BIT(7)
-#define		VPP_OSD2_ALPHA_PREMULT	BIT(8)
-#define		VPP_OSD1_ALPHA_PREMULT	BIT(9)
-#define		VPP_VD1_POSTBLEND	BIT(10)
-#define		VPP_VD2_POSTBLEND	BIT(11)
-#define		VPP_OSD1_POSTBLEND	BIT(12)
-#define		VPP_OSD2_POSTBLEND	BIT(13)
-#define		VPP_VD1_PREBLEND	BIT(14)
-#define		VPP_VD2_PREBLEND	BIT(15)
-#define		VPP_OSD1_PREBLEND	BIT(16)
-#define		VPP_OSD2_PREBLEND	BIT(17)
-#define		VPP_COLOR_MNG_ENABLE	BIT(28)
+#define		VPP_PREBLEND_ENABLE             BIT(6)
+#define		VPP_POSTBLEND_ENABLE            BIT(7)
+#define		VPP_OSD2_ALPHA_PREMULT          BIT(8)
+#define		VPP_OSD1_ALPHA_PREMULT          BIT(9)
+#define		VPP_VD1_POSTBLEND               BIT(10)
+#define		VPP_VD2_POSTBLEND               BIT(11)
+#define		VPP_OSD1_POSTBLEND              BIT(12)
+#define		VPP_OSD2_POSTBLEND              BIT(13)
+#define		VPP_VD1_PREBLEND                BIT(14)
+#define		VPP_VD2_PREBLEND                BIT(15)
+#define		VPP_OSD1_PREBLEND               BIT(16)
+#define		VPP_OSD2_PREBLEND               BIT(17)
+#define		VPP_COLOR_MNG_ENABLE            BIT(28)
 #define VPP_OFIFO_SIZE 0x1d27
+#define		VPP_OFIFO_SIZE_MASK             GENMASK(13, 0)
+#define		VPP_OFIFO_SIZE_DEFAULT          (0xfff << 20 | 0x1000)
 #define VPP_FIFO_STATUS 0x1d28
 #define VPP_SMOKE_CTRL 0x1d29
 #define VPP_SMOKE1_VAL 0x1d2a
@@ -358,6 +427,8 @@
 #define VPP_HSC_PHASE_CTRL1 0x1d34
 #define VPP_HSC_INI_PAT_CTRL 0x1d35
 #define VPP_VADJ_CTRL 0x1d40
+#define		VPP_MINUS_BLACK_LVL_VADJ1_ENABLE BIT(1)
+
 #define VPP_VADJ1_Y 0x1d41
 #define VPP_VADJ1_MA_MB 0x1d42
 #define VPP_VADJ1_MC_MD 0x1d43
@@ -417,6 +488,7 @@
 #define VPP_PEAKING_VGAIN 0x1d92
 #define VPP_PEAKING_NLP_1 0x1d93
 #define VPP_DOLBY_CTRL 0x1d93
+#define VPP_PPS_DUMMY_DATA_MODE (1 << 17)
 #define VPP_PEAKING_NLP_2 0x1d94
 #define VPP_PEAKING_NLP_3 0x1d95
 #define VPP_PEAKING_NLP_4 0x1d96
@@ -471,6 +543,83 @@
 #define VPP_OSD_SCALE_COEF 0x1dcd
 #define VPP_INT_LINE_NUM 0x1dce
 
+#define VPP_WRAP_OSD1_MATRIX_COEF00_01 0x3d60
+#define VPP_WRAP_OSD1_MATRIX_COEF02_10 0x3d61
+#define VPP_WRAP_OSD1_MATRIX_COEF11_12 0x3d62
+#define VPP_WRAP_OSD1_MATRIX_COEF20_21 0x3d63
+#define VPP_WRAP_OSD1_MATRIX_COEF22 0x3d64
+#define VPP_WRAP_OSD1_MATRIX_COEF13_14 0x3d65
+#define VPP_WRAP_OSD1_MATRIX_COEF23_24 0x3d66
+#define VPP_WRAP_OSD1_MATRIX_COEF15_25 0x3d67
+#define VPP_WRAP_OSD1_MATRIX_CLIP 0x3d68
+#define VPP_WRAP_OSD1_MATRIX_OFFSET0_1 0x3d69
+#define VPP_WRAP_OSD1_MATRIX_OFFSET2 0x3d6a
+#define VPP_WRAP_OSD1_MATRIX_PRE_OFFSET0_1 0x3d6b
+#define VPP_WRAP_OSD1_MATRIX_PRE_OFFSET2 0x3d6c
+#define VPP_WRAP_OSD1_MATRIX_EN_CTRL 0x3d6d
+
+#define VPP_WRAP_OSD2_MATRIX_COEF00_01 0x3d70
+#define VPP_WRAP_OSD2_MATRIX_COEF02_10 0x3d71
+#define VPP_WRAP_OSD2_MATRIX_COEF11_12 0x3d72
+#define VPP_WRAP_OSD2_MATRIX_COEF20_21 0x3d73
+#define VPP_WRAP_OSD2_MATRIX_COEF22 0x3d74
+#define VPP_WRAP_OSD2_MATRIX_COEF13_14 0x3d75
+#define VPP_WRAP_OSD2_MATRIX_COEF23_24 0x3d76
+#define VPP_WRAP_OSD2_MATRIX_COEF15_25 0x3d77
+#define VPP_WRAP_OSD2_MATRIX_CLIP 0x3d78
+#define VPP_WRAP_OSD2_MATRIX_OFFSET0_1 0x3d79
+#define VPP_WRAP_OSD2_MATRIX_OFFSET2 0x3d7a
+#define VPP_WRAP_OSD2_MATRIX_PRE_OFFSET0_1 0x3d7b
+#define VPP_WRAP_OSD2_MATRIX_PRE_OFFSET2 0x3d7c
+#define VPP_WRAP_OSD2_MATRIX_EN_CTRL 0x3d7d
+
+#define VPP_WRAP_OSD3_MATRIX_COEF00_01 0x3db0
+#define VPP_WRAP_OSD3_MATRIX_COEF02_10 0x3db1
+#define VPP_WRAP_OSD3_MATRIX_COEF11_12 0x3db2
+#define VPP_WRAP_OSD3_MATRIX_COEF20_21 0x3db3
+#define VPP_WRAP_OSD3_MATRIX_COEF22 0x3db4
+#define VPP_WRAP_OSD3_MATRIX_COEF13_14 0x3db5
+#define VPP_WRAP_OSD3_MATRIX_COEF23_24 0x3db6
+#define VPP_WRAP_OSD3_MATRIX_COEF15_25 0x3db7
+#define VPP_WRAP_OSD3_MATRIX_CLIP 0x3db8
+#define VPP_WRAP_OSD3_MATRIX_OFFSET0_1 0x3db9
+#define VPP_WRAP_OSD3_MATRIX_OFFSET2 0x3dba
+#define VPP_WRAP_OSD3_MATRIX_PRE_OFFSET0_1 0x3dbb
+#define VPP_WRAP_OSD3_MATRIX_PRE_OFFSET2 0x3dbc
+#define VPP_WRAP_OSD3_MATRIX_EN_CTRL 0x3dbd
+
+/* osd2 scaler */
+#define OSD2_VSC_PHASE_STEP 0x3d00
+#define OSD2_VSC_INI_PHASE 0x3d01
+#define OSD2_VSC_CTRL0 0x3d02
+#define OSD2_HSC_PHASE_STEP 0x3d03
+#define OSD2_HSC_INI_PHASE 0x3d04
+#define OSD2_HSC_CTRL0 0x3d05
+#define OSD2_HSC_INI_PAT_CTRL 0x3d06
+#define OSD2_SC_DUMMY_DATA 0x3d07
+#define OSD2_SC_CTRL0 0x3d08
+#define OSD2_SCI_WH_M1 0x3d09
+#define OSD2_SCO_H_START_END 0x3d0a
+#define OSD2_SCO_V_START_END 0x3d0b
+#define OSD2_SCALE_COEF_IDX 0x3d18
+#define OSD2_SCALE_COEF 0x3d19
+
+/* osd34 scaler */
+#define OSD34_SCALE_COEF_IDX 0x3d1e
+#define OSD34_SCALE_COEF 0x3d1f
+#define OSD34_VSC_PHASE_STEP 0x3d20
+#define OSD34_VSC_INI_PHASE 0x3d21
+#define OSD34_VSC_CTRL0 0x3d22
+#define OSD34_HSC_PHASE_STEP 0x3d23
+#define OSD34_HSC_INI_PHASE 0x3d24
+#define OSD34_HSC_CTRL0 0x3d25
+#define OSD34_HSC_INI_PAT_CTRL 0x3d26
+#define OSD34_SC_DUMMY_DATA 0x3d27
+#define OSD34_SC_CTRL0 0x3d28
+#define OSD34_SCI_WH_M1 0x3d29
+#define OSD34_SCO_H_START_END 0x3d2a
+#define OSD34_SCO_V_START_END 0x3d2b
+
 /* viu2 */
 #define VIU2_ADDR_START 0x1e00
 #define VIU2_ADDR_END 0x1eff
@@ -584,6 +733,25 @@
 #define VENC_UPSAMPLE_CTRL0 0x1b64
 #define VENC_UPSAMPLE_CTRL1 0x1b65
 #define VENC_UPSAMPLE_CTRL2 0x1b66
+#define		VENC_UPSAMPLE_CTRL_F0_2_CLK_RATIO        BIT(0)
+#define		VENC_UPSAMPLE_CTRL_F1_EN                 BIT(5)
+#define		VENC_UPSAMPLE_CTRL_F1_UPSAMPLE_EN        BIT(6)
+#define		VENC_UPSAMPLE_CTRL_INTERLACE_HIGH_LUMA   (0x0 << 12)
+#define		VENC_UPSAMPLE_CTRL_CVBS                  (0x1 << 12)
+#define		VENC_UPSAMPLE_CTRL_S_VIDEO_LUMA          (0x2 << 12)
+#define		VENC_UPSAMPLE_CTRL_S_VIDEO_CHROMA        (0x3 << 12)
+#define		VENC_UPSAMPLE_CTRL_INTERLACE_PB          (0x4 << 12)
+#define		VENC_UPSAMPLE_CTRL_INTERLACE_PR          (0x5 << 12)
+#define		VENC_UPSAMPLE_CTRL_INTERLACE_R           (0x6 << 12)
+#define		VENC_UPSAMPLE_CTRL_INTERLACE_G           (0x7 << 12)
+#define		VENC_UPSAMPLE_CTRL_INTERLACE_B           (0x8 << 12)
+#define		VENC_UPSAMPLE_CTRL_PROGRESSIVE_Y         (0x9 << 12)
+#define		VENC_UPSAMPLE_CTRL_PROGRESSIVE_PB        (0xa << 12)
+#define		VENC_UPSAMPLE_CTRL_PROGRESSIVE_PR        (0xb << 12)
+#define		VENC_UPSAMPLE_CTRL_PROGRESSIVE_R         (0xc << 12)
+#define		VENC_UPSAMPLE_CTRL_PROGRESSIVE_G         (0xd << 12)
+#define		VENC_UPSAMPLE_CTRL_PROGRESSIVE_B         (0xe << 12)
+#define		VENC_UPSAMPLE_CTRL_VDAC_TEST_VALUE       (0xf << 12)
 #define TCON_INVERT_CTL 0x1b67
 #define VENC_VIDEO_PROG_MODE 0x1b68
 #define VENC_ENCI_LINE 0x1b69
@@ -592,6 +760,7 @@
 #define VENC_ENCP_PIXEL 0x1b6c
 #define VENC_STATA 0x1b6d
 #define VENC_INTCTRL 0x1b6e
+#define		VENC_INTCTRL_ENCI_LNRST_INT_EN  BIT(1)
 #define VENC_INTFLAG 0x1b6f
 #define VENC_VIDEO_TST_EN 0x1b70
 #define VENC_VIDEO_TST_MDSEL 0x1b71
@@ -602,6 +771,7 @@
 #define VENC_VIDEO_TST_CLRBAR_WIDTH 0x1b76
 #define VENC_VIDEO_TST_VDCNT_STSET 0x1b77
 #define VENC_VDAC_DACSEL0 0x1b78
+#define		VENC_VDAC_SEL_ATV_DMD           BIT(5)
 #define VENC_VDAC_DACSEL1 0x1b79
 #define VENC_VDAC_DACSEL2 0x1b7a
 #define VENC_VDAC_DACSEL3 0x1b7b
@@ -622,6 +792,7 @@
 #define VENC_VDAC_DAC5_GAINCTRL 0x1bfa
 #define VENC_VDAC_DAC5_OFFSET 0x1bfb
 #define VENC_VDAC_FIFO_CTRL 0x1bfc
+#define		VENC_VDAC_FIFO_EN_ENCI_ENABLE   BIT(13)
 #define ENCL_TCON_INVERT_CTL 0x1bfd
 #define ENCP_VIDEO_EN 0x1b80
 #define ENCP_VIDEO_SYNC_MODE 0x1b81
@@ -637,6 +808,7 @@
 #define ENCP_VIDEO_SYNC_OFFST 0x1b8b
 #define ENCP_VIDEO_MACV_OFFST 0x1b8c
 #define ENCP_VIDEO_MODE 0x1b8d
+#define		ENCP_VIDEO_MODE_DE_V_HIGH       BIT(14)
 #define ENCP_VIDEO_MODE_ADV 0x1b8e
 #define ENCP_DBG_PX_RST 0x1b90
 #define ENCP_DBG_LN_RST 0x1b91
@@ -715,6 +887,11 @@
 #define C656_FS_LNED 0x1be7
 #define ENCI_VIDEO_MODE 0x1b00
 #define ENCI_VIDEO_MODE_ADV 0x1b01
+#define		ENCI_VIDEO_MODE_ADV_DMXMD(val)          (val & 0x3)
+#define		ENCI_VIDEO_MODE_ADV_VBICTL_LINE_17_22   BIT(2)
+#define		ENCI_VIDEO_MODE_ADV_YBW_MEDIUM          (0 << 4)
+#define		ENCI_VIDEO_MODE_ADV_YBW_LOW             (0x1 << 4)
+#define		ENCI_VIDEO_MODE_ADV_YBW_HIGH            (0x2 << 4)
 #define ENCI_VIDEO_FSC_ADJ 0x1b02
 #define ENCI_VIDEO_BRIGHT 0x1b03
 #define ENCI_VIDEO_CONT 0x1b04
@@ -785,13 +962,17 @@
 #define ENCI_DBG_MAXPX 0x1b4c
 #define ENCI_DBG_MAXLN 0x1b4d
 #define ENCI_MACV_MAX_AMP 0x1b50
+#define		ENCI_MACV_MAX_AMP_ENABLE_CHANGE BIT(15)
+#define		ENCI_MACV_MAX_AMP_VAL(val)      (val & 0x83ff)
 #define ENCI_MACV_PULSE_LO 0x1b51
 #define ENCI_MACV_PULSE_HI 0x1b52
 #define ENCI_MACV_BKP_MAX 0x1b53
 #define ENCI_CFILT_CTRL 0x1b54
+#define		ENCI_CFILT_CMPT_SEL_HIGH        BIT(1)
 #define ENCI_CFILT7 0x1b55
 #define ENCI_YC_DELAY 0x1b56
 #define ENCI_VIDEO_EN 0x1b57
+#define		ENCI_VIDEO_EN_ENABLE            BIT(0)
 #define ENCI_DVI_HSO_BEGIN 0x1c00
 #define ENCI_DVI_HSO_END 0x1c01
 #define ENCI_DVI_VSO_BLINE_EVN 0x1c02
@@ -803,6 +984,10 @@
 #define ENCI_DVI_VSO_END_EVN 0x1c08
 #define ENCI_DVI_VSO_END_ODD 0x1c09
 #define ENCI_CFILT_CTRL2 0x1c0a
+#define		ENCI_CFILT_CMPT_CR_DLY(delay)   (delay & 0xf)
+#define		ENCI_CFILT_CMPT_CB_DLY(delay)   ((delay & 0xf) << 4)
+#define		ENCI_CFILT_CVBS_CR_DLY(delay)   ((delay & 0xf) << 8)
+#define		ENCI_CFILT_CVBS_CB_DLY(delay)   ((delay & 0xf) << 12)
 #define ENCI_DACSEL_0 0x1c0b
 #define ENCI_DACSEL_1 0x1c0c
 #define ENCP_DACSEL_0 0x1c0d
@@ -817,6 +1002,8 @@
 #define ENCI_TST_CLRBAR_WIDTH 0x1c16
 #define ENCI_TST_VDCNT_STSET 0x1c17
 #define ENCI_VFIFO2VD_CTL 0x1c18
+#define		ENCI_VFIFO2VD_CTL_ENABLE        BIT(0)
+#define		ENCI_VFIFO2VD_CTL_VD_SEL(val)   ((val & 0xff) << 8)
 #define ENCI_VFIFO2VD_PIXEL_START 0x1c19
 #define ENCI_VFIFO2VD_PIXEL_END 0x1c1a
 #define ENCI_VFIFO2VD_LINE_TOP_START 0x1c1b
@@ -879,6 +1066,7 @@
 #define VENC_VDAC_DAC5_FILT_CTRL0 0x1c56
 #define VENC_VDAC_DAC5_FILT_CTRL1 0x1c57
 #define VENC_VDAC_DAC0_FILT_CTRL0 0x1c58
+#define		VENC_VDAC_DAC0_FILT_CTRL0_EN    BIT(0)
 #define VENC_VDAC_DAC0_FILT_CTRL1 0x1c59
 #define VENC_VDAC_DAC1_FILT_CTRL0 0x1c5a
 #define VENC_VDAC_DAC1_FILT_CTRL1 0x1c5b
@@ -1284,6 +1472,18 @@
 #define		VIU2_SEL_VENC_ENCP	(2 << 2)
 #define		VIU2_SEL_VENC_ENCT	(3 << 2)
 #define VPU_HDMI_SETTING 0x271b
+#define		VPU_HDMI_ENCI_DATA_TO_HDMI      BIT(0)
+#define		VPU_HDMI_ENCP_DATA_TO_HDMI      BIT(1)
+#define		VPU_HDMI_INV_HSYNC              BIT(2)
+#define		VPU_HDMI_INV_VSYNC              BIT(3)
+#define		VPU_HDMI_OUTPUT_CRYCB           (0 << 5)
+#define		VPU_HDMI_OUTPUT_YCBCR           (1 << 5)
+#define		VPU_HDMI_OUTPUT_YCRCB           (2 << 5)
+#define		VPU_HDMI_OUTPUT_CBCRY           (3 << 5)
+#define		VPU_HDMI_OUTPUT_CBYCR           (4 << 5)
+#define		VPU_HDMI_OUTPUT_CRCBY           (5 << 5)
+#define		VPU_HDMI_WR_RATE(rate)          (((rate & 0x1f) - 1) << 8)
+#define		VPU_HDMI_RD_RATE(rate)          (((rate & 0x1f) - 1) << 12)
 #define ENCI_INFO_READ 0x271c
 #define ENCP_INFO_READ 0x271d
 #define ENCT_INFO_READ 0x271e
@@ -1360,6 +1560,7 @@
 #define VPU_RDARB_MODE_L1C2 0x2799
 #define VPU_RDARB_MODE_L2C1 0x279d
 #define VPU_WRARB_MODE_L2C1 0x27a2
+#define		VPU_RDARB_SLAVE_TO_MASTER_PORT(dc, port) (port << (16 + dc))
 
 /* osd super scale */
 #define OSDSR_HV_SIZEIN 0x3130
@@ -1390,4 +1591,150 @@
 #define OSDSR_YBIC_VCOEF0 0x3149
 #define OSDSR_CBIC_VCOEF0 0x314a
 
+/* osd afbcd on gxtvbb */
+#define OSD1_AFBCD_ENABLE 0x31a0
+#define OSD1_AFBCD_MODE 0x31a1
+#define OSD1_AFBCD_SIZE_IN 0x31a2
+#define OSD1_AFBCD_HDR_PTR 0x31a3
+#define OSD1_AFBCD_FRAME_PTR 0x31a4
+#define OSD1_AFBCD_CHROMA_PTR 0x31a5
+#define OSD1_AFBCD_CONV_CTRL 0x31a6
+#define OSD1_AFBCD_STATUS 0x31a8
+#define OSD1_AFBCD_PIXEL_HSCOPE 0x31a9
+#define OSD1_AFBCD_PIXEL_VSCOPE 0x31aa
+
+/* add for gxm and 962e dv core2 */
+#define DOLBY_CORE2A_SWAP_CTRL1	0x3434
+#define DOLBY_CORE2A_SWAP_CTRL2	0x3435
+
+/* osd afbc on g12a */
+#define VPU_MAFBC_BLOCK_ID 0x3a00
+#define VPU_MAFBC_IRQ_RAW_STATUS 0x3a01
+#define VPU_MAFBC_IRQ_CLEAR 0x3a02
+#define VPU_MAFBC_IRQ_MASK 0x3a03
+#define VPU_MAFBC_IRQ_STATUS 0x3a04
+#define VPU_MAFBC_COMMAND 0x3a05
+#define VPU_MAFBC_STATUS 0x3a06
+#define VPU_MAFBC_SURFACE_CFG 0x3a07
+#define VPU_MAFBC_HEADER_BUF_ADDR_LOW_S0 0x3a10
+#define VPU_MAFBC_HEADER_BUF_ADDR_HIGH_S0 0x3a11
+#define VPU_MAFBC_FORMAT_SPECIFIER_S0 0x3a12
+#define VPU_MAFBC_BUFFER_WIDTH_S0 0x3a13
+#define VPU_MAFBC_BUFFER_HEIGHT_S0 0x3a14
+#define VPU_MAFBC_BOUNDING_BOX_X_START_S0 0x3a15
+#define VPU_MAFBC_BOUNDING_BOX_X_END_S0 0x3a16
+#define VPU_MAFBC_BOUNDING_BOX_Y_START_S0 0x3a17
+#define VPU_MAFBC_BOUNDING_BOX_Y_END_S0 0x3a18
+#define VPU_MAFBC_OUTPUT_BUF_ADDR_LOW_S0 0x3a19
+#define VPU_MAFBC_OUTPUT_BUF_ADDR_HIGH_S0 0x3a1a
+#define VPU_MAFBC_OUTPUT_BUF_STRIDE_S0 0x3a1b
+#define VPU_MAFBC_PREFETCH_CFG_S0 0x3a1c
+
+#define VPU_MAFBC_HEADER_BUF_ADDR_LOW_S1 0x3a30
+#define VPU_MAFBC_HEADER_BUF_ADDR_HIGH_S1 0x3a31
+#define VPU_MAFBC_FORMAT_SPECIFIER_S1 0x3a32
+#define VPU_MAFBC_BUFFER_WIDTH_S1 0x3a33
+#define VPU_MAFBC_BUFFER_HEIGHT_S1 0x3a34
+#define VPU_MAFBC_BOUNDING_BOX_X_START_S1 0x3a35
+#define VPU_MAFBC_BOUNDING_BOX_X_END_S1 0x3a36
+#define VPU_MAFBC_BOUNDING_BOX_Y_START_S1 0x3a37
+#define VPU_MAFBC_BOUNDING_BOX_Y_END_S1 0x3a38
+#define VPU_MAFBC_OUTPUT_BUF_ADDR_LOW_S1 0x3a39
+#define VPU_MAFBC_OUTPUT_BUF_ADDR_HIGH_S1 0x3a3a
+#define VPU_MAFBC_OUTPUT_BUF_STRIDE_S1 0x3a3b
+#define VPU_MAFBC_PREFETCH_CFG_S1 0x3a3c
+
+#define VPU_MAFBC_HEADER_BUF_ADDR_LOW_S2 0x3a50
+#define VPU_MAFBC_HEADER_BUF_ADDR_HIGH_S2 0x3a51
+#define VPU_MAFBC_FORMAT_SPECIFIER_S2 0x3a52
+#define VPU_MAFBC_BUFFER_WIDTH_S2 0x3a53
+#define VPU_MAFBC_BUFFER_HEIGHT_S2 0x3a54
+#define VPU_MAFBC_BOUNDING_BOX_X_START_S2 0x3a55
+#define VPU_MAFBC_BOUNDING_BOX_X_END_S2 0x3a56
+#define VPU_MAFBC_BOUNDING_BOX_Y_START_S2 0x3a57
+#define VPU_MAFBC_BOUNDING_BOX_Y_END_S2 0x3a58
+#define VPU_MAFBC_OUTPUT_BUF_ADDR_LOW_S2 0x3a59
+#define VPU_MAFBC_OUTPUT_BUF_ADDR_HIGH_S2 0x3a5a
+#define VPU_MAFBC_OUTPUT_BUF_STRIDE_S2 0x3a5b
+#define VPU_MAFBC_PREFETCH_CFG_S2 0x3a5c
+
+#define VPU_MAFBC_HEADER_BUF_ADDR_LOW_S3 0x3a70
+#define VPU_MAFBC_HEADER_BUF_ADDR_HIGH_S3 0x3a71
+#define VPU_MAFBC_FORMAT_SPECIFIER_S3 0x3a72
+#define VPU_MAFBC_BUFFER_WIDTH_S3 0x3a73
+#define VPU_MAFBC_BUFFER_HEIGHT_S3 0x3a74
+#define VPU_MAFBC_BOUNDING_BOX_X_START_S3 0x3a75
+#define VPU_MAFBC_BOUNDING_BOX_X_END_S3 0x3a76
+#define VPU_MAFBC_BOUNDING_BOX_Y_START_S3 0x3a77
+#define VPU_MAFBC_BOUNDING_BOX_Y_END_S3 0x3a78
+#define VPU_MAFBC_OUTPUT_BUF_ADDR_LOW_S3 0x3a79
+#define VPU_MAFBC_OUTPUT_BUF_ADDR_HIGH_S3 0x3a7a
+#define VPU_MAFBC_OUTPUT_BUF_STRIDE_S3 0x3a7b
+#define VPU_MAFBC_PREFETCH_CFG_S3 0x3a7c
+
+#define DOLBY_PATH_CTRL 0x1a0c
+#define		DOLBY_BYPASS_EN(val)            (val & 0xf)
+#define OSD_PATH_MISC_CTRL 0x1a0e
+#define MALI_AFBCD_TOP_CTRL 0x1a0f
+
+#define VIU_OSD_BLEND_CTRL 0x39b0
+#define		VIU_OSD_BLEND_REORDER(dest, src)      ((src) << (dest * 4))
+#define		VIU_OSD_BLEND_DIN_EN(bits)            ((bits & 0xf) << 20)
+#define		VIU_OSD_BLEND1_DIN3_BYPASS_TO_DOUT1   BIT(24)
+#define		VIU_OSD_BLEND1_DOUT_BYPASS_TO_BLEND2  BIT(25)
+#define		VIU_OSD_BLEND_DIN0_BYPASS_TO_DOUT0    BIT(26)
+#define		VIU_OSD_BLEND_BLEN2_PREMULT_EN(input) ((input & 0x3) << 27)
+#define		VIU_OSD_BLEND_HOLD_LINES(lines)       ((u32)(lines & 0x7) << 29)
+#define VIU_OSD_BLEND_CTRL1 0x39c0
+#define VIU_OSD_BLEND_DIN0_SCOPE_H 0x39b1
+#define VIU_OSD_BLEND_DIN0_SCOPE_V 0x39b2
+#define VIU_OSD_BLEND_DIN1_SCOPE_H 0x39b3
+#define VIU_OSD_BLEND_DIN1_SCOPE_V 0x39b4
+#define VIU_OSD_BLEND_DIN2_SCOPE_H 0x39b5
+#define VIU_OSD_BLEND_DIN2_SCOPE_V 0x39b6
+#define VIU_OSD_BLEND_DIN3_SCOPE_H 0x39b7
+#define VIU_OSD_BLEND_DIN3_SCOPE_V 0x39b8
+#define VIU_OSD_BLEND_DUMMY_DATA0 0x39b9
+#define VIU_OSD_BLEND_DUMMY_ALPHA 0x39ba
+#define VIU_OSD_BLEND_BLEND0_SIZE 0x39bb
+#define VIU_OSD_BLEND_BLEND1_SIZE 0x39bc
+#define VIU_OSD_BLEND_RO_CURRENT_XY 0x39bf
+
+#define VPP_OUT_H_V_SIZE 0x1da5
+
+#define VPP_VD2_HDR_IN_SIZE 0x1df0
+#define VPP_OSD1_IN_SIZE 0x1df1
+#define VPP_GCLK_CTRL2 0x1df2
+#define VD2_PPS_DUMMY_DATA 0x1df4
+#define VPP_OSD1_BLD_H_SCOPE 0x1df5
+#define VPP_OSD1_BLD_V_SCOPE 0x1df6
+#define VPP_OSD2_BLD_H_SCOPE 0x1df7
+#define VPP_OSD2_BLD_V_SCOPE 0x1df8
+#define VPP_WRBAK_CTRL 0x1df9
+#define VPP_SLEEP_CTRL 0x1dfa
+#define VD1_BLEND_SRC_CTRL 0x1dfb
+#define VD2_BLEND_SRC_CTRL 0x1dfc
+#define		VD_BLEND_PREBLD_SRC_VD1         (1 << 0)
+#define		VD_BLEND_PREBLD_SRC_VD2         (2 << 0)
+#define		VD_BLEND_PREBLD_SRC_OSD1        (3 << 0)
+#define		VD_BLEND_PREBLD_SRC_OSD2        (4 << 0)
+#define		VD_BLEND_PREBLD_PREMULT_EN      BIT(4)
+#define		VD_BLEND_POSTBLD_SRC_VD1        (1 << 8)
+#define		VD_BLEND_POSTBLD_SRC_VD2        (2 << 8)
+#define		VD_BLEND_POSTBLD_SRC_OSD1       (3 << 8)
+#define		VD_BLEND_POSTBLD_SRC_OSD2       (4 << 8)
+#define		VD_BLEND_POSTBLD_PREMULT_EN     BIT(16)
+#define OSD1_BLEND_SRC_CTRL 0x1dfd
+#define OSD2_BLEND_SRC_CTRL 0x1dfe
+#define		OSD_BLEND_POSTBLD_SRC_VD1       (1 << 8)
+#define		OSD_BLEND_POSTBLD_SRC_VD2       (2 << 8)
+#define		OSD_BLEND_POSTBLD_SRC_OSD1      (3 << 8)
+#define		OSD_BLEND_POSTBLD_SRC_OSD2      (4 << 8)
+#define		OSD_BLEND_PATH_SEL_ENABLE       BIT(20)
+
+#define VPP_POST_BLEND_BLEND_DUMMY_DATA 0x3968
+#define VPP_POST_BLEND_DUMMY_ALPHA 0x3969
+#define VPP_RDARB_MODE 0x3978
+#define VPP_RDARB_REQEN_SLV 0x3979
+
 #endif /* __MESON_REGISTERS_H */
diff --git a/drivers/video/meson/meson_vclk.c b/drivers/video/meson/meson_vclk.c
index 693e0ebe39..0f628e920b 100644
--- a/drivers/video/meson/meson_vclk.c
+++ b/drivers/video/meson/meson_vclk.c
@@ -68,14 +68,20 @@ enum {
 #define CTS_HDMI_SYS_EN		BIT(8)
 
 #define HHI_HDMI_PLL_CNTL	0x320 /* 0xc8 offset in data sheet */
+#define HHI_HDMI_PLL_CNTL_EN	BIT(30)
 #define HHI_HDMI_PLL_CNTL2	0x324 /* 0xc9 offset in data sheet */
 #define HHI_HDMI_PLL_CNTL3	0x328 /* 0xca offset in data sheet */
 #define HHI_HDMI_PLL_CNTL4	0x32C /* 0xcb offset in data sheet */
 #define HHI_HDMI_PLL_CNTL5	0x330 /* 0xcc offset in data sheet */
 #define HHI_HDMI_PLL_CNTL6	0x334 /* 0xcd offset in data sheet */
+#define HHI_HDMI_PLL_CNTL7	0x338 /* 0xce offset in data sheet */
 
 #define HDMI_PLL_RESET		BIT(28)
+#define HDMI_PLL_RESET_G12A	BIT(29)
 #define HDMI_PLL_LOCK		BIT(31)
+#define HDMI_PLL_LOCK_G12A	(3 << 30)
+
+#define FREQ_1000_1001(_freq)	DIV_ROUND_CLOSEST(_freq * 1000, 1001)
 
 /* VID PLL Dividers */
 enum {
@@ -206,8 +212,6 @@ static void meson_venci_cvbs_clock_config(struct meson_vpu_priv *priv)
 {
 	unsigned int val;
 
-	debug("%s:%d\n", __func__, __LINE__);
-
 	/* Setup PLL to output 1.485GHz */
 	if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXBB)) {
 		hhi_write(HHI_HDMI_PLL_CNTL, 0x5800023d);
@@ -217,6 +221,10 @@ static void meson_venci_cvbs_clock_config(struct meson_vpu_priv *priv)
 		hhi_write(HHI_HDMI_PLL_CNTL5, 0x71486980);
 		hhi_write(HHI_HDMI_PLL_CNTL6, 0x00000e55);
 		hhi_write(HHI_HDMI_PLL_CNTL, 0x4800023d);
+
+		/* Poll for lock bit */
+		readl_poll_timeout(priv->hhi_base + HHI_HDMI_PLL_CNTL, val,
+				   (val & HDMI_PLL_LOCK), 10);
 	} else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM) ||
 		   meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL)) {
 		hhi_write(HHI_HDMI_PLL_CNTL, 0x4000027b);
@@ -231,13 +239,26 @@ static void meson_venci_cvbs_clock_config(struct meson_vpu_priv *priv)
 				HDMI_PLL_RESET, HDMI_PLL_RESET);
 		hhi_update_bits(HHI_HDMI_PLL_CNTL,
 				HDMI_PLL_RESET, 0);
-	}
 
-	debug("%s:%d\n", __func__, __LINE__);
+		/* Poll for lock bit */
+		readl_poll_timeout(priv->hhi_base + HHI_HDMI_PLL_CNTL, val,
+				   (val & HDMI_PLL_LOCK), 10);
+	} else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
+		hhi_write(HHI_HDMI_PLL_CNTL, 0x1a0504f7);
+		hhi_write(HHI_HDMI_PLL_CNTL2, 0x00010000);
+		hhi_write(HHI_HDMI_PLL_CNTL3, 0x00000000);
+		hhi_write(HHI_HDMI_PLL_CNTL4, 0x6a28dc00);
+		hhi_write(HHI_HDMI_PLL_CNTL5, 0x65771290);
+		hhi_write(HHI_HDMI_PLL_CNTL6, 0x39272000);
+		hhi_write(HHI_HDMI_PLL_CNTL7, 0x56540000);
+		hhi_write(HHI_HDMI_PLL_CNTL, 0x3a0504f7);
+		hhi_write(HHI_HDMI_PLL_CNTL, 0x1a0504f7);
 
-	/* Poll for lock bit */
-	readl_poll_timeout(priv->hhi_base + HHI_HDMI_PLL_CNTL, val,
-			   (val & HDMI_PLL_LOCK), 10);
+		/* Poll for lock bit */
+		readl_poll_timeout(priv->hhi_base + HHI_HDMI_PLL_CNTL, val,
+			((val & HDMI_PLL_LOCK_G12A) == HDMI_PLL_LOCK_G12A),
+			10);
+	}
 
 	/* Disable VCLK2 */
 	hhi_update_bits(HHI_VIID_CLK_CNTL, VCLK2_EN, 0);
@@ -250,8 +271,13 @@ static void meson_venci_cvbs_clock_config(struct meson_vpu_priv *priv)
 			VCLK2_DIV_MASK, (55 - 1));
 
 	/* select vid_pll for vclk2 */
-	hhi_update_bits(HHI_VIID_CLK_CNTL,
-			VCLK2_SEL_MASK, (4 << VCLK2_SEL_SHIFT));
+	if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
+		hhi_update_bits(HHI_VIID_CLK_CNTL,
+				VCLK2_SEL_MASK, (0 << VCLK2_SEL_SHIFT));
+	else
+		hhi_update_bits(HHI_VIID_CLK_CNTL,
+				VCLK2_SEL_MASK, (4 << VCLK2_SEL_SHIFT));
+
 	/* enable vclk2 gate */
 	hhi_update_bits(HHI_VIID_CLK_CNTL, VCLK2_EN, VCLK2_EN);
 
@@ -282,14 +308,12 @@ static void meson_venci_cvbs_clock_config(struct meson_vpu_priv *priv)
 	/* enable vdac_clk */
 	hhi_update_bits(HHI_VID_CLK_CNTL2,
 			CTS_VDAC_EN, CTS_VDAC_EN);
-
-	debug("%s:%d\n", __func__, __LINE__);
 }
 
 enum {
 /* PLL	O1 O2 O3 VP DV     EN TX */
 /* 4320 /4 /4 /1 /5 /1  => /2 /2 */
-	MESON_VCLK_HDMI_ENCI_54000 = 1,
+	MESON_VCLK_HDMI_ENCI_54000 = 0,
 /* 4320 /4 /4 /1 /5 /1  => /1 /2 */
 	MESON_VCLK_HDMI_DDR_54000,
 /* 2970 /4 /1 /1 /5 /1  => /1 /2 */
@@ -305,6 +329,7 @@ enum {
 };
 
 struct meson_vclk_params {
+	unsigned int pixel_freq;
 	unsigned int pll_base_freq;
 	unsigned int pll_od1;
 	unsigned int pll_od2;
@@ -313,6 +338,7 @@ struct meson_vclk_params {
 	unsigned int vclk_div;
 } params[] = {
 	[MESON_VCLK_HDMI_ENCI_54000] = {
+		.pixel_freq = 54000,
 		.pll_base_freq = 4320000,
 		.pll_od1 = 4,
 		.pll_od2 = 4,
@@ -321,6 +347,7 @@ struct meson_vclk_params {
 		.vclk_div = 1,
 	},
 	[MESON_VCLK_HDMI_DDR_54000] = {
+		.pixel_freq = 54000,
 		.pll_base_freq = 4320000,
 		.pll_od1 = 4,
 		.pll_od2 = 4,
@@ -329,6 +356,7 @@ struct meson_vclk_params {
 		.vclk_div = 1,
 	},
 	[MESON_VCLK_HDMI_DDR_148500] = {
+		.pixel_freq = 148500,
 		.pll_base_freq = 2970000,
 		.pll_od1 = 4,
 		.pll_od2 = 1,
@@ -337,6 +365,7 @@ struct meson_vclk_params {
 		.vclk_div = 1,
 	},
 	[MESON_VCLK_HDMI_74250] = {
+		.pixel_freq = 74250,
 		.pll_base_freq = 2970000,
 		.pll_od1 = 2,
 		.pll_od2 = 2,
@@ -345,6 +374,7 @@ struct meson_vclk_params {
 		.vclk_div = 1,
 	},
 	[MESON_VCLK_HDMI_148500] = {
+		.pixel_freq = 148500,
 		.pll_base_freq = 2970000,
 		.pll_od1 = 1,
 		.pll_od2 = 2,
@@ -353,14 +383,16 @@ struct meson_vclk_params {
 		.vclk_div = 1,
 	},
 	[MESON_VCLK_HDMI_297000] = {
-		.pll_base_freq = 2970000,
-		.pll_od1 = 1,
+		.pixel_freq = 297000,
+		.pll_base_freq = 5940000,
+		.pll_od1 = 2,
 		.pll_od2 = 1,
 		.pll_od3 = 1,
 		.vid_pll_div = VID_PLL_DIV_5,
 		.vclk_div = 2,
 	},
 	[MESON_VCLK_HDMI_594000] = {
+		.pixel_freq = 594000,
 		.pll_base_freq = 5940000,
 		.pll_od1 = 1,
 		.pll_od2 = 1,
@@ -368,6 +400,7 @@ struct meson_vclk_params {
 		.vid_pll_div = VID_PLL_DIV_5,
 		.vclk_div = 1,
 	},
+	{ /* sentinel */ },
 };
 
 static inline unsigned int pll_od_to_reg(unsigned int od)
@@ -431,6 +464,50 @@ void meson_hdmi_pll_set_params(struct meson_vpu_priv *priv, unsigned int m,
 		/* Poll for lock bit */
 		readl_poll_timeout(priv->hhi_base + HHI_HDMI_PLL_CNTL, val,
 				   (val & HDMI_PLL_LOCK), 10);
+	} else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
+		hhi_write(HHI_HDMI_PLL_CNTL, 0x0b3a0400 | m);
+
+		/* Enable and reset */
+		hhi_update_bits(HHI_HDMI_PLL_CNTL, 0x3 << 28, 0x3 << 28);
+
+		hhi_write(HHI_HDMI_PLL_CNTL2, frac);
+		hhi_write(HHI_HDMI_PLL_CNTL3, 0x00000000);
+
+		/* G12A HDMI PLL Needs specific parameters for 5.4GHz */
+		if (m >= 0xf7) {
+			if (frac < 0x10000) {
+				hhi_write(HHI_HDMI_PLL_CNTL4, 0x6a685c00);
+				hhi_write(HHI_HDMI_PLL_CNTL5, 0x11551293);
+			} else {
+				hhi_write(HHI_HDMI_PLL_CNTL4, 0xea68dc00);
+				hhi_write(HHI_HDMI_PLL_CNTL5, 0x65771290);
+			}
+			hhi_write(HHI_HDMI_PLL_CNTL6, 0x39272000);
+			hhi_write(HHI_HDMI_PLL_CNTL7, 0x55540000);
+		} else {
+			hhi_write(HHI_HDMI_PLL_CNTL4, 0x0a691c00);
+			hhi_write(HHI_HDMI_PLL_CNTL5, 0x33771290);
+			hhi_write(HHI_HDMI_PLL_CNTL6, 0x39270000);
+			hhi_write(HHI_HDMI_PLL_CNTL7, 0x50540000);
+		}
+
+		do {
+			/* Reset PLL */
+			hhi_update_bits(HHI_HDMI_PLL_CNTL,
+					HDMI_PLL_RESET_G12A,
+					HDMI_PLL_RESET_G12A);
+
+			/* UN-Reset PLL */
+			hhi_update_bits(HHI_HDMI_PLL_CNTL,
+					HDMI_PLL_RESET_G12A, 0);
+
+			/* Poll for lock bits */
+			if (!readl_poll_timeout(
+					priv->hhi_base + HHI_HDMI_PLL_CNTL, val,
+					((val & HDMI_PLL_LOCK_G12A)
+						== HDMI_PLL_LOCK_G12A), 100))
+				break;
+		} while (1);
 	}
 
 	if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXBB))
@@ -440,6 +517,9 @@ void meson_hdmi_pll_set_params(struct meson_vpu_priv *priv, unsigned int m,
 		 meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL))
 		hhi_update_bits(HHI_HDMI_PLL_CNTL3,
 				3 << 21, pll_od_to_reg(od1) << 21);
+	else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
+		hhi_update_bits(HHI_HDMI_PLL_CNTL,
+				3 << 16, pll_od_to_reg(od1) << 16);
 
 	if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXBB))
 		hhi_update_bits(HHI_HDMI_PLL_CNTL2,
@@ -448,6 +528,9 @@ void meson_hdmi_pll_set_params(struct meson_vpu_priv *priv, unsigned int m,
 		 meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL))
 		hhi_update_bits(HHI_HDMI_PLL_CNTL3,
 				3 << 23, pll_od_to_reg(od2) << 23);
+	else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
+		hhi_update_bits(HHI_HDMI_PLL_CNTL,
+				3 << 18, pll_od_to_reg(od2) << 18);
 
 	if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXBB))
 		hhi_update_bits(HHI_HDMI_PLL_CNTL2,
@@ -456,6 +539,9 @@ void meson_hdmi_pll_set_params(struct meson_vpu_priv *priv, unsigned int m,
 		 meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL))
 		hhi_update_bits(HHI_HDMI_PLL_CNTL3,
 				3 << 19, pll_od_to_reg(od3) << 19);
+	else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
+		hhi_update_bits(HHI_HDMI_PLL_CNTL,
+				3 << 20, pll_od_to_reg(od3) << 20);
 }
 
 #define XTAL_FREQ 24000
@@ -472,6 +558,7 @@ static unsigned int meson_hdmi_pll_get_m(struct meson_vpu_priv *priv,
 
 #define HDMI_FRAC_MAX_GXBB	4096
 #define HDMI_FRAC_MAX_GXL	1024
+#define HDMI_FRAC_MAX_G12A	131072
 
 static unsigned int meson_hdmi_pll_get_frac(struct meson_vpu_priv *priv,
 					    unsigned int m,
@@ -488,6 +575,9 @@ static unsigned int meson_hdmi_pll_get_frac(struct meson_vpu_priv *priv,
 		parent_freq *= 2;
 	}
 
+	if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
+		frac_max = HDMI_FRAC_MAX_G12A;
+
 	/* We can have a perfect match !*/
 	if (pll_freq / m == parent_freq &&
 	    pll_freq % m == 0)
@@ -519,6 +609,12 @@ static bool meson_hdmi_pll_validate_params(struct meson_vpu_priv *priv,
 			return false;
 		if (frac >= HDMI_FRAC_MAX_GXL)
 			return false;
+	} else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
+		/* Empiric supported min/max dividers */
+		if (m < 106 || m > 247)
+			return false;
+		if (frac >= HDMI_FRAC_MAX_G12A)
+			return false;
 	}
 
 	return true;
@@ -595,8 +691,10 @@ meson_vclk_set(struct meson_vpu_priv *priv, unsigned int pll_base_freq,
 	       unsigned int od1, unsigned int od2, unsigned int od3,
 	       unsigned int vid_pll_div, unsigned int vclk_div,
 	       unsigned int hdmi_tx_div, unsigned int venc_div,
-	       bool hdmi_use_enci)
+	       bool hdmi_use_enci, bool vic_alternate_clock)
 {
+	unsigned int m = 0, frac = 0;
+
 	/* Set HDMI-TX sys clock */
 	hhi_update_bits(HHI_HDMI_CLK_CNTL,
 			CTS_HDMI_SYS_SEL_MASK, 0);
@@ -611,34 +709,55 @@ meson_vclk_set(struct meson_vpu_priv *priv, unsigned int pll_base_freq,
 	} else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXBB)) {
 		switch (pll_base_freq) {
 		case 2970000:
-			meson_hdmi_pll_set_params(priv, 0x3d, 0xe00,
-						  od1, od2, od3);
+			m = 0x3d;
+			frac = vic_alternate_clock ? 0xd02 : 0xe00;
 			break;
 		case 4320000:
-			meson_hdmi_pll_set_params(priv, 0x5a, 0,
-						  od1, od2, od3);
+			m = vic_alternate_clock ? 0x59 : 0x5a;
+			frac = vic_alternate_clock ? 0xe8f : 0;
 			break;
 		case 5940000:
-			meson_hdmi_pll_set_params(priv, 0x7b, 0xc00,
-						  od1, od2, od3);
+			m = 0x7b;
+			frac = vic_alternate_clock ? 0xa05 : 0xc00;
 			break;
 		}
+
+		meson_hdmi_pll_set_params(priv, m, frac, od1, od2, od3);
 	} else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM) ||
 		   meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL)) {
 		switch (pll_base_freq) {
 		case 2970000:
-			meson_hdmi_pll_set_params(priv, 0x7b, 0x300,
-						  od1, od2, od3);
+			m = 0x7b;
+			frac = vic_alternate_clock ? 0x281 : 0x300;
+			break;
+		case 4320000:
+			m = vic_alternate_clock ? 0xb3 : 0xb4;
+			frac = vic_alternate_clock ? 0x347 : 0;
+			break;
+		case 5940000:
+			m = 0xf7;
+			frac = vic_alternate_clock ? 0x102 : 0x200;
+			break;
+		}
+
+		meson_hdmi_pll_set_params(priv, m, frac, od1, od2, od3);
+	} else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
+		switch (pll_base_freq) {
+		case 2970000:
+			m = 0x7b;
+			frac = vic_alternate_clock ? 0x140b4 : 0x18000;
 			break;
 		case 4320000:
-			meson_hdmi_pll_set_params(priv, 0xb4, 0,
-						  od1, od2, od3);
+			m = vic_alternate_clock ? 0xb3 : 0xb4;
+			frac = vic_alternate_clock ? 0x1a3ee : 0;
 			break;
 		case 5940000:
-			meson_hdmi_pll_set_params(priv, 0xf7, 0x200,
-						  od1, od2, od3);
+			m = 0xf7;
+			frac = vic_alternate_clock ? 0x8148 : 0x10000;
 			break;
 		}
+
+		meson_hdmi_pll_set_params(priv, m, frac, od1, od2, od3);
 	}
 
 	/* Setup vid_pll divider */
@@ -803,6 +922,7 @@ static void meson_vclk_setup(struct meson_vpu_priv *priv, unsigned int target,
 			     unsigned int vclk_freq, unsigned int venc_freq,
 			     unsigned int dac_freq, bool hdmi_use_enci)
 {
+	bool vic_alternate_clock = false;
 	unsigned int freq;
 	unsigned int hdmi_tx_div;
 	unsigned int venc_div;
@@ -820,8 +940,7 @@ static void meson_vclk_setup(struct meson_vpu_priv *priv, unsigned int target,
 		 * - encp encoder
 		 */
 		meson_vclk_set(priv, vclk_freq * 10, 0, 0, 0,
-			       VID_PLL_DIV_5, 2, 1, 1, false);
-
+			       VID_PLL_DIV_5, 2, 1, 1, false, false);
 		return;
 	}
 
@@ -841,31 +960,35 @@ static void meson_vclk_setup(struct meson_vpu_priv *priv, unsigned int target,
 		return;
 	}
 
-	switch (vclk_freq) {
-	case 54000:
-		if (hdmi_use_enci)
-			freq = MESON_VCLK_HDMI_ENCI_54000;
-		else
-			freq = MESON_VCLK_HDMI_DDR_54000;
-		break;
-	case 74250:
-		freq = MESON_VCLK_HDMI_74250;
-		break;
-	case 148500:
-		if (dac_freq != 148500)
-			freq = MESON_VCLK_HDMI_DDR_148500;
-		else
-			freq = MESON_VCLK_HDMI_148500;
-		break;
-	case 297000:
-		freq = MESON_VCLK_HDMI_297000;
-		break;
-	case 594000:
-		freq = MESON_VCLK_HDMI_594000;
-		break;
-	default:
-		printf("Fatal Error, invalid HDMI vclk freq %d\n",
-		       vclk_freq);
+	for (freq = 0 ; params[freq].pixel_freq ; ++freq) {
+		if (vclk_freq == params[freq].pixel_freq ||
+		    vclk_freq == FREQ_1000_1001(params[freq].pixel_freq)) {
+			if (vclk_freq != params[freq].pixel_freq)
+				vic_alternate_clock = true;
+			else
+				vic_alternate_clock = false;
+
+			if (freq == MESON_VCLK_HDMI_ENCI_54000 &&
+			    !hdmi_use_enci)
+				continue;
+
+			if (freq == MESON_VCLK_HDMI_DDR_54000 &&
+			    hdmi_use_enci)
+				continue;
+
+			if (freq == MESON_VCLK_HDMI_DDR_148500 &&
+			    dac_freq == vclk_freq)
+				continue;
+
+			if (freq == MESON_VCLK_HDMI_148500 &&
+			    dac_freq != vclk_freq)
+				continue;
+			break;
+		}
+	}
+
+	if (!params[freq].pixel_freq) {
+		pr_err("Fatal Error, invalid HDMI vclk freq %d\n", vclk_freq);
 		return;
 	}
 
@@ -873,7 +996,7 @@ static void meson_vclk_setup(struct meson_vpu_priv *priv, unsigned int target,
 		       params[freq].pll_od1, params[freq].pll_od2,
 		       params[freq].pll_od3, params[freq].vid_pll_div,
 		       params[freq].vclk_div, hdmi_tx_div, venc_div,
-		       hdmi_use_enci);
+		       hdmi_use_enci, vic_alternate_clock);
 }
 
 void meson_vpu_setup_vclk(struct udevice *dev,
diff --git a/drivers/video/meson/meson_venc.c b/drivers/video/meson/meson_venc.c
index d137dde8e2..5da4b3f096 100644
--- a/drivers/video/meson/meson_venc.c
+++ b/drivers/video/meson/meson_venc.c
@@ -23,7 +23,9 @@ enum meson_venc_source {
 };
 
 #define HHI_VDAC_CNTL0		0x2F4 /* 0xbd offset in data sheet */
+#define HHI_VDAC_CNTL0_G12A	0x2EC /* 0xbb offset in data sheet */
 #define HHI_VDAC_CNTL1		0x2F8 /* 0xbe offset in data sheet */
+#define HHI_VDAC_CNTL1_G12A	0x2F0 /* 0xbc offset in data sheet */
 
 struct meson_cvbs_enci_mode {
 	unsigned int mode_tag;
@@ -175,7 +177,7 @@ union meson_hdmi_venc_mode meson_hdmi_enci_mode_480i = {
 		.hso_end = 129,
 		.vso_even = 3,
 		.vso_odd = 260,
-		.macv_max_amp = 0x810b,
+		.macv_max_amp = 0xb,
 		.video_prog_mode = 0xf0,
 		.video_mode = 0x8,
 		.sch_adjust = 0x20,
@@ -195,7 +197,7 @@ union meson_hdmi_venc_mode meson_hdmi_enci_mode_576i = {
 		.hso_end = 129,
 		.vso_even = 3,
 		.vso_odd = 260,
-		.macv_max_amp = 8107,
+		.macv_max_amp = 0x7,
 		.video_prog_mode = 0xff,
 		.video_mode = 0x13,
 		.sch_adjust = 0x28,
@@ -774,12 +776,13 @@ static void meson_venc_hdmi_mode_set(struct meson_vpu_priv *priv,
 	unsigned int eof_lines;
 	unsigned int sof_lines;
 	unsigned int vsync_lines;
+	u32 reg;
 
 	/* Use VENCI for 480i and 576i and double HDMI pixels */
 	if (mode->flags & DISPLAY_FLAGS_DOUBLECLK) {
-		venc_hdmi_latency = 1;
 		hdmi_repeat = true;
 		use_enci = true;
+		venc_hdmi_latency = 1;
 	}
 
 	meson_venc_hdmi_get_dmt_vmode(mode, &vmode_dmt);
@@ -850,8 +853,11 @@ static void meson_venc_hdmi_mode_set(struct meson_vpu_priv *priv,
 		unsigned int lines_f1;
 
 		/* CVBS Filter settings */
-		writel(0x12, priv->io_base + _REG(ENCI_CFILT_CTRL));
-		writel(0x12, priv->io_base + _REG(ENCI_CFILT_CTRL2));
+		writel(ENCI_CFILT_CMPT_SEL_HIGH | 0x10,
+		       priv->io_base + _REG(ENCI_CFILT_CTRL));
+		writel(ENCI_CFILT_CMPT_CR_DLY(2) |
+		       ENCI_CFILT_CMPT_CB_DLY(1),
+		       priv->io_base + _REG(ENCI_CFILT_CTRL2));
 
 		/* Digital Video Select : Interlace, clk27 clk, external */
 		writel(0, priv->io_base + _REG(VENC_DVI_SETTING));
@@ -873,7 +879,8 @@ static void meson_venc_hdmi_mode_set(struct meson_vpu_priv *priv,
 		       priv->io_base + _REG(ENCI_SYNC_VSO_ODDLN));
 
 		/* Macrovision max amplitude change */
-		writel(vmode->enci.macv_max_amp,
+		writel(ENCI_MACV_MAX_AMP_ENABLE_CHANGE |
+		       ENCI_MACV_MAX_AMP_VAL(vmode->enci.macv_max_amp),
 		       priv->io_base + _REG(ENCI_MACV_MAX_AMP));
 
 		/* Video mode */
@@ -882,7 +889,8 @@ static void meson_venc_hdmi_mode_set(struct meson_vpu_priv *priv,
 		writel(vmode->enci.video_mode,
 		       priv->io_base + _REG(ENCI_VIDEO_MODE));
 
-		/* Advanced Video Mode :
+		/*
+		 * Advanced Video Mode :
 		 * Demux shifting 0x2
 		 * Blank line end at line17/22
 		 * High bandwidth Luma Filter
@@ -890,7 +898,10 @@ static void meson_venc_hdmi_mode_set(struct meson_vpu_priv *priv,
 		 * Bypass luma low pass filter
 		 * No macrovision on CSYNC
 		 */
-		writel(0x26, priv->io_base + _REG(ENCI_VIDEO_MODE_ADV));
+		writel(ENCI_VIDEO_MODE_ADV_DMXMD(2) |
+		       ENCI_VIDEO_MODE_ADV_VBICTL_LINE_17_22 |
+		       ENCI_VIDEO_MODE_ADV_YBW_HIGH,
+		       priv->io_base + _REG(ENCI_VIDEO_MODE_ADV));
 
 		writel(vmode->enci.sch_adjust,
 		       priv->io_base + _REG(ENCI_VIDEO_SCH));
@@ -905,8 +916,17 @@ static void meson_venc_hdmi_mode_set(struct meson_vpu_priv *priv,
 		/* UNreset Interlaced TV Encoder */
 		writel(0, priv->io_base + _REG(ENCI_DBG_PX_RST));
 
-		/* Enable Vfifo2vd, Y_Cb_Y_Cr select */
-		writel(0x4e01, priv->io_base + _REG(ENCI_VFIFO2VD_CTL));
+		/*
+		 * Enable Vfifo2vd and set Y_Cb_Y_Cr:
+		 * Corresponding value:
+		 * Y  => 00 or 10
+		 * Cb => 01
+		 * Cr => 11
+		 * Ex: 0x4e => 01001110 would mean Cb/Y/Cr/Y
+		 */
+		writel(ENCI_VFIFO2VD_CTL_ENABLE |
+		       ENCI_VFIFO2VD_CTL_VD_SEL(0x4e),
+		       priv->io_base + _REG(ENCI_VFIFO2VD_CTL));
 
 		/* Timings */
 		writel(vmode->enci.pixel_start,
@@ -928,7 +948,8 @@ static void meson_venc_hdmi_mode_set(struct meson_vpu_priv *priv,
 		meson_vpp_setup_mux(priv, MESON_VIU_VPP_MUX_ENCI);
 
 		/* Interlace video enable */
-		writel(1, priv->io_base + _REG(ENCI_VIDEO_EN));
+		writel(ENCI_VIDEO_EN_ENABLE,
+		       priv->io_base + _REG(ENCI_VIDEO_EN));
 
 		lines_f0 = mode->vback_porch.typ + mode->vactive.typ +
 			   mode->vback_porch.typ + mode->vsync_len.typ;
@@ -1177,7 +1198,8 @@ static void meson_venc_hdmi_mode_set(struct meson_vpu_priv *priv,
 		writel(1, priv->io_base + _REG(ENCP_VIDEO_EN));
 
 		/* Set DE signal's polarity is active high */
-		writel_bits(BIT(14), BIT(14),
+		writel_bits(ENCP_VIDEO_MODE_DE_V_HIGH,
+			    ENCP_VIDEO_MODE_DE_V_HIGH,
 			    priv->io_base + _REG(ENCP_VIDEO_MODE));
 
 		/* Program DE timing */
@@ -1302,21 +1324,52 @@ static void meson_venc_hdmi_mode_set(struct meson_vpu_priv *priv,
 		meson_vpp_setup_mux(priv, MESON_VIU_VPP_MUX_ENCP);
 	}
 
-	writel((use_enci ? 1 : 2) |
-		       (mode->flags & DISPLAY_FLAGS_HSYNC_HIGH ? 1 << 2 : 0) |
-		       (mode->flags & DISPLAY_FLAGS_VSYNC_HIGH ? 1 << 3 : 0) |
-		       4 << 5 |
-		       (venc_repeat ? 1 << 8 : 0) |
-		       (hdmi_repeat ? 1 << 12 : 0),
-		       priv->io_base + _REG(VPU_HDMI_SETTING));
+	/* Set VPU HDMI setting */
+	/* Select ENCP or ENCI data to HDMI */
+	if (use_enci)
+		reg = VPU_HDMI_ENCI_DATA_TO_HDMI;
+	else
+		reg = VPU_HDMI_ENCP_DATA_TO_HDMI;
+
+	/* Invert polarity of HSYNC from VENC */
+	if (mode->flags & DISPLAY_FLAGS_HSYNC_HIGH)
+		reg |= VPU_HDMI_INV_HSYNC;
+
+	/* Invert polarity of VSYNC from VENC */
+	if (mode->flags & DISPLAY_FLAGS_VSYNC_HIGH)
+		reg |= VPU_HDMI_INV_VSYNC;
+
+	/* Output data format: CbYCr */
+	reg |= VPU_HDMI_OUTPUT_CBYCR;
+
+	/*
+	 * Write rate to the async FIFO between VENC and HDMI.
+	 * One write every 2 wr_clk.
+	 */
+	if (venc_repeat)
+		reg |= VPU_HDMI_WR_RATE(2);
+
+	/*
+	 * Read rate to the async FIFO between VENC and HDMI.
+	 * One read every 2 wr_clk.
+	 */
+	if (hdmi_repeat)
+		reg |= VPU_HDMI_RD_RATE(2);
+
+	writel(reg, priv->io_base + _REG(VPU_HDMI_SETTING));
 }
 
 static void meson_venci_cvbs_mode_set(struct meson_vpu_priv *priv,
 				      struct meson_cvbs_enci_mode *mode)
 {
+	u32 reg;
+
 	/* CVBS Filter settings */
-	writel(0x12, priv->io_base + _REG(ENCI_CFILT_CTRL));
-	writel(0x12, priv->io_base + _REG(ENCI_CFILT_CTRL2));
+	writel(ENCI_CFILT_CMPT_SEL_HIGH | 0x10,
+	       priv->io_base + _REG(ENCI_CFILT_CTRL));
+	writel(ENCI_CFILT_CMPT_CR_DLY(2) |
+	       ENCI_CFILT_CMPT_CB_DLY(1),
+	       priv->io_base + _REG(ENCI_CFILT_CTRL2));
 
 	/* Digital Video Select : Interlace, clk27 clk, external */
 	writel(0, priv->io_base + _REG(VENC_DVI_SETTING));
@@ -1338,7 +1391,8 @@ static void meson_venci_cvbs_mode_set(struct meson_vpu_priv *priv,
 	       priv->io_base + _REG(ENCI_SYNC_VSO_ODDLN));
 
 	/* Macrovision max amplitude change */
-	writel(0x8100 + mode->macv_max_amp,
+	writel(ENCI_MACV_MAX_AMP_ENABLE_CHANGE |
+	       ENCI_MACV_MAX_AMP_VAL(mode->macv_max_amp),
 	       priv->io_base + _REG(ENCI_MACV_MAX_AMP));
 
 	/* Video mode */
@@ -1347,7 +1401,8 @@ static void meson_venci_cvbs_mode_set(struct meson_vpu_priv *priv,
 	writel(mode->video_mode,
 	       priv->io_base + _REG(ENCI_VIDEO_MODE));
 
-	/* Advanced Video Mode :
+	/*
+	 * Advanced Video Mode :
 	 * Demux shifting 0x2
 	 * Blank line end at line17/22
 	 * High bandwidth Luma Filter
@@ -1355,7 +1410,10 @@ static void meson_venci_cvbs_mode_set(struct meson_vpu_priv *priv,
 	 * Bypass luma low pass filter
 	 * No macrovision on CSYNC
 	 */
-	writel(0x26, priv->io_base + _REG(ENCI_VIDEO_MODE_ADV));
+	writel(ENCI_VIDEO_MODE_ADV_DMXMD(2) |
+	       ENCI_VIDEO_MODE_ADV_VBICTL_LINE_17_22 |
+	       ENCI_VIDEO_MODE_ADV_YBW_HIGH,
+	       priv->io_base + _REG(ENCI_VIDEO_MODE_ADV));
 
 	writel(mode->sch_adjust, priv->io_base + _REG(ENCI_VIDEO_SCH));
 
@@ -1387,16 +1445,50 @@ static void meson_venci_cvbs_mode_set(struct meson_vpu_priv *priv,
 	/* UNreset Interlaced TV Encoder */
 	writel(0, priv->io_base + _REG(ENCI_DBG_PX_RST));
 
-	/* Enable Vfifo2vd, Y_Cb_Y_Cr select */
-	writel(0x4e01, priv->io_base + _REG(ENCI_VFIFO2VD_CTL));
+	/*
+	 * Enable Vfifo2vd and set Y_Cb_Y_Cr:
+	 * Corresponding value:
+	 * Y  => 00 or 10
+	 * Cb => 01
+	 * Cr => 11
+	 * Ex: 0x4e => 01001110 would mean Cb/Y/Cr/Y
+	 */
+	writel(ENCI_VFIFO2VD_CTL_ENABLE |
+	       ENCI_VFIFO2VD_CTL_VD_SEL(0x4e),
+	       priv->io_base + _REG(ENCI_VFIFO2VD_CTL));
 
 	/* Power UP Dacs */
 	writel(0, priv->io_base + _REG(VENC_VDAC_SETTING));
 
 	/* Video Upsampling */
-	writel(0x0061, priv->io_base + _REG(VENC_UPSAMPLE_CTRL0));
-	writel(0x4061, priv->io_base + _REG(VENC_UPSAMPLE_CTRL1));
-	writel(0x5061, priv->io_base + _REG(VENC_UPSAMPLE_CTRL2));
+	/*
+	 * CTRL0, CTRL1 and CTRL2:
+	 * Filter0: input data sample every 2 cloks
+	 * Filter1: filtering and upsample enable
+	 */
+	reg = VENC_UPSAMPLE_CTRL_F0_2_CLK_RATIO | VENC_UPSAMPLE_CTRL_F1_EN |
+		VENC_UPSAMPLE_CTRL_F1_UPSAMPLE_EN;
+
+	/*
+	 * Upsample CTRL0:
+	 * Interlace High Bandwidth Luma
+	 */
+	writel(VENC_UPSAMPLE_CTRL_INTERLACE_HIGH_LUMA | reg,
+	       priv->io_base + _REG(VENC_UPSAMPLE_CTRL0));
+
+	/*
+	 * Upsample CTRL1:
+	 * Interlace Pb
+	 */
+	writel(VENC_UPSAMPLE_CTRL_INTERLACE_PB | reg,
+	       priv->io_base + _REG(VENC_UPSAMPLE_CTRL1));
+
+	/*
+	 * Upsample CTRL2:
+	 * Interlace R
+	 */
+	writel(VENC_UPSAMPLE_CTRL_INTERLACE_PR | reg,
+	       priv->io_base + _REG(VENC_UPSAMPLE_CTRL2));
 
 	/* Select Interlace Y DACs */
 	writel(0, priv->io_base + _REG(VENC_VDAC_DACSEL0));
@@ -1410,14 +1502,16 @@ static void meson_venci_cvbs_mode_set(struct meson_vpu_priv *priv,
 	meson_vpp_setup_mux(priv, MESON_VIU_VPP_MUX_ENCI);
 
 	/* Enable ENCI FIFO */
-	writel(0x2000, priv->io_base + _REG(VENC_VDAC_FIFO_CTRL));
+	writel(VENC_VDAC_FIFO_EN_ENCI_ENABLE,
+	       priv->io_base + _REG(VENC_VDAC_FIFO_CTRL));
 
 	/* Select ENCI DACs 0, 1, 4, and 5 */
 	writel(0x11, priv->io_base + _REG(ENCI_DACSEL_0));
 	writel(0x11, priv->io_base + _REG(ENCI_DACSEL_1));
 
 	/* Interlace video enable */
-	writel(1, priv->io_base + _REG(ENCI_VIDEO_EN));
+	writel(ENCI_VIDEO_EN_ENABLE,
+	       priv->io_base + _REG(ENCI_VIDEO_EN));
 
 	/* Configure Video Saturation / Contrast / Brightness / Hue */
 	writel(mode->video_saturation,
@@ -1430,7 +1524,8 @@ static void meson_venci_cvbs_mode_set(struct meson_vpu_priv *priv,
 	       priv->io_base + _REG(ENCI_VIDEO_HUE));
 
 	/* Enable DAC0 Filter */
-	writel(0x1, priv->io_base + _REG(VENC_VDAC_DAC0_FILT_CTRL0));
+	writel(VENC_VDAC_DAC0_FILT_CTRL0_EN,
+	       priv->io_base + _REG(VENC_VDAC_DAC0_FILT_CTRL0));
 	writel(0xfc48, priv->io_base + _REG(VENC_VDAC_DAC0_FILT_CTRL1));
 
 	/* 0 in Macrovision register 0 */
@@ -1441,15 +1536,21 @@ static void meson_venci_cvbs_mode_set(struct meson_vpu_priv *priv,
 	       priv->io_base + _REG(ENCI_SYNC_ADJ));
 
 	/* enable VDAC */
-	writel_bits(BIT(5), 0, priv->io_base + _REG(VENC_VDAC_DACSEL0));
+	writel_bits(VENC_VDAC_SEL_ATV_DMD, 0,
+		    priv->io_base + _REG(VENC_VDAC_DACSEL0));
 
 	if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXBB))
 		hhi_write(HHI_VDAC_CNTL0, 1);
 	else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL) ||
 		 meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM))
 		hhi_write(HHI_VDAC_CNTL0, 0xf0001);
+	else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
+		hhi_write(HHI_VDAC_CNTL0_G12A, 0x906001);
 
-	hhi_write(HHI_VDAC_CNTL1, 0);
+	if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
+		hhi_write(HHI_VDAC_CNTL1_G12A, 0);
+	else
+		hhi_write(HHI_VDAC_CNTL1, 0);
 }
 
 void meson_vpu_setup_venc(struct udevice *dev,
diff --git a/drivers/video/meson/meson_vpu.h b/drivers/video/meson/meson_vpu.h
index ef5f10eae3..3412dac052 100644
--- a/drivers/video/meson/meson_vpu.h
+++ b/drivers/video/meson/meson_vpu.h
@@ -14,6 +14,7 @@
 #include <video.h>
 #include <display.h>
 #include <linux/io.h>
+#include <linux/bitfield.h>
 #include "meson_registers.h"
 
 enum {
diff --git a/drivers/video/meson/meson_vpu_init.c b/drivers/video/meson/meson_vpu_init.c
index 92228b5ceb..12f8c4194a 100644
--- a/drivers/video/meson/meson_vpu_init.c
+++ b/drivers/video/meson/meson_vpu_init.c
@@ -12,7 +12,9 @@
 
 /* HHI Registers */
 #define HHI_VDAC_CNTL0		0x2F4 /* 0xbd offset in data sheet */
+#define HHI_VDAC_CNTL0_G12A	0x2EC /* 0xbd offset in data sheet */
 #define HHI_VDAC_CNTL1		0x2F8 /* 0xbe offset in data sheet */
+#define HHI_VDAC_CNTL1_G12A	0x2F0 /* 0xbe offset in data sheet */
 #define HHI_HDMI_PHY_CNTL0	0x3a0 /* 0xe8 offset in data sheet */
 
 /* OSDx_CTRL_STAT2 */
@@ -42,7 +44,7 @@ static void meson_vpp_write_scaling_filter_coefs(struct meson_vpu_priv *priv,
 {
 	int i;
 
-	writel(is_horizontal ? BIT(8) : 0,
+	writel(is_horizontal ? VPP_SCALE_HORIZONTAL_COEF : 0,
 	       priv->io_base + _REG(VPP_OSD_SCALE_COEF_IDX));
 	for (i = 0; i < 33; i++)
 		writel(coefs[i],
@@ -67,7 +69,7 @@ static void meson_vpp_write_vd_scaling_filter_coefs(struct meson_vpu_priv *priv,
 {
 	int i;
 
-	writel(is_horizontal ? BIT(8) : 0,
+	writel(is_horizontal ? VPP_SCALE_HORIZONTAL_COEF : 0,
 	       priv->io_base + _REG(VPP_SCALE_COEF_IDX));
 	for (i = 0; i < 33; i++)
 		writel(coefs[i],
@@ -112,6 +114,34 @@ static int eotf_bypass_coeff[EOTF_COEFF_SIZE] = {
 	EOTF_COEFF_RIGHTSHIFT /* right shift */
 };
 
+static void meson_viu_set_g12a_osd1_matrix(struct meson_vpu_priv *priv,
+					   int *m, bool csc_on)
+{
+	/* VPP WRAP OSD1 matrix */
+	writel(((m[0] & 0xfff) << 16) | (m[1] & 0xfff),
+	       priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_PRE_OFFSET0_1));
+	writel(m[2] & 0xfff,
+	       priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_PRE_OFFSET2));
+	writel(((m[3] & 0x1fff) << 16) | (m[4] & 0x1fff),
+	       priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF00_01));
+	writel(((m[5] & 0x1fff) << 16) | (m[6] & 0x1fff),
+	       priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF02_10));
+	writel(((m[7] & 0x1fff) << 16) | (m[8] & 0x1fff),
+	       priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF11_12));
+	writel(((m[9] & 0x1fff) << 16) | (m[10] & 0x1fff),
+	       priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF20_21));
+	writel((m[11] & 0x1fff) << 16,
+	       priv->io_base +	_REG(VPP_WRAP_OSD1_MATRIX_COEF22));
+
+	writel(((m[18] & 0xfff) << 16) | (m[19] & 0xfff),
+	       priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_OFFSET0_1));
+	writel(m[20] & 0xfff,
+	       priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_OFFSET2));
+
+	writel_bits(BIT(0), csc_on ? BIT(0) : 0,
+		    priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_EN_CTRL));
+}
+
 static void meson_viu_set_osd_matrix(struct meson_vpu_priv *priv,
 				     enum viu_matrix_sel_e m_select,
 				     int *m, bool csc_on)
@@ -322,20 +352,47 @@ static void meson_viu_load_matrix(struct meson_vpu_priv *priv)
 				 true);
 }
 
+static inline uint32_t meson_viu_osd_burst_length_reg(uint32_t length)
+{
+	u32 val = (((length & 0x80) % 24) / 12);
+
+	return (((val & 0x3) << 10) | (((val & 0x4) >> 2) << 31));
+}
+
 void meson_vpu_init(struct udevice *dev)
 {
 	struct meson_vpu_priv *priv = dev_get_priv(dev);
 	u32 reg;
 
-	/* vpu initialization */
-	writel(0x210000, priv->io_base + _REG(VPU_RDARB_MODE_L1C1));
-	writel(0x10000, priv->io_base + _REG(VPU_RDARB_MODE_L1C2));
-	writel(0x900000, priv->io_base + _REG(VPU_RDARB_MODE_L2C1));
-	writel(0x20000, priv->io_base + _REG(VPU_WRARB_MODE_L2C1));
+	/*
+	 * Slave dc0 and dc5 connected to master port 1.
+	 * By default other slaves are connected to master port 0.
+	 */
+	reg = VPU_RDARB_SLAVE_TO_MASTER_PORT(0, 1) |
+		VPU_RDARB_SLAVE_TO_MASTER_PORT(5, 1);
+	writel(reg, priv->io_base + _REG(VPU_RDARB_MODE_L1C1));
+
+	/* Slave dc0 connected to master port 1 */
+	reg = VPU_RDARB_SLAVE_TO_MASTER_PORT(0, 1);
+	writel(reg, priv->io_base + _REG(VPU_RDARB_MODE_L1C2));
+
+	/* Slave dc4 and dc7 connected to master port 1 */
+	reg = VPU_RDARB_SLAVE_TO_MASTER_PORT(4, 1) |
+		VPU_RDARB_SLAVE_TO_MASTER_PORT(7, 1);
+	writel(reg, priv->io_base + _REG(VPU_RDARB_MODE_L2C1));
+
+	/* Slave dc1 connected to master port 1 */
+	reg = VPU_RDARB_SLAVE_TO_MASTER_PORT(1, 1);
+	writel(reg, priv->io_base + _REG(VPU_WRARB_MODE_L2C1));
 
 	/* Disable CVBS VDAC */
-	hhi_write(HHI_VDAC_CNTL0, 0);
-	hhi_write(HHI_VDAC_CNTL1, 8);
+	if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
+		hhi_write(HHI_VDAC_CNTL0_G12A, 0);
+		hhi_write(HHI_VDAC_CNTL1_G12A, 8);
+	} else {
+		hhi_write(HHI_VDAC_CNTL0, 0);
+		hhi_write(HHI_VDAC_CNTL1, 8);
+	}
 
 	/* Power Down Dacs */
 	writel(0xff, priv->io_base + _REG(VENC_VDAC_SETTING));
@@ -344,7 +401,9 @@ void meson_vpu_init(struct udevice *dev)
 	hhi_write(HHI_HDMI_PHY_CNTL0, 0);
 
 	/* Disable HDMI */
-	writel_bits(0x3, 0, priv->io_base + _REG(VPU_HDMI_SETTING));
+	writel_bits(VPU_HDMI_ENCI_DATA_TO_HDMI |
+		    VPU_HDMI_ENCP_DATA_TO_HDMI, 0,
+		    priv->io_base + _REG(VPU_HDMI_SETTING));
 
 	/* Disable all encoders */
 	writel(0, priv->io_base + _REG(ENCI_VIDEO_EN));
@@ -360,43 +419,58 @@ void meson_vpu_init(struct udevice *dev)
 	} else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM)) {
 		writel_bits(0xff << 16, 0xff << 16,
 			    priv->io_base + _REG(VIU_MISC_CTRL1));
-		writel(0x20000, priv->io_base + _REG(VPP_DOLBY_CTRL));
+		writel(VPP_PPS_DUMMY_DATA_MODE,
+		       priv->io_base + _REG(VPP_DOLBY_CTRL));
 		writel(0x1020080,
 		       priv->io_base + _REG(VPP_DUMMY_DATA1));
-	}
+	} else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
+		writel(0xf, priv->io_base + _REG(DOLBY_PATH_CTRL));
 
 	/* Initialize vpu fifo control registers */
-	writel(readl(priv->io_base + _REG(VPP_OFIFO_SIZE)) |
-			0x77f, priv->io_base + _REG(VPP_OFIFO_SIZE));
-	writel(0x08080808, priv->io_base + _REG(VPP_HOLD_LINES));
-
-	/* Turn off preblend */
-	writel_bits(VPP_PREBLEND_ENABLE, 0,
-		    priv->io_base + _REG(VPP_MISC));
-
-	/* Turn off POSTBLEND */
-	writel_bits(VPP_POSTBLEND_ENABLE, 0,
-		    priv->io_base + _REG(VPP_MISC));
-
-	/* Force all planes off */
-	writel_bits(VPP_OSD1_POSTBLEND | VPP_OSD2_POSTBLEND |
-		    VPP_VD1_POSTBLEND | VPP_VD2_POSTBLEND |
-		    VPP_VD1_PREBLEND | VPP_VD2_PREBLEND, 0,
-		    priv->io_base + _REG(VPP_MISC));
-
-	/* Setup default VD settings */
-	writel(4096,
-	       priv->io_base + _REG(VPP_PREBLEND_VD1_H_START_END));
-	writel(4096,
-	       priv->io_base + _REG(VPP_BLEND_VD2_H_START_END));
+	if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
+		writel(VPP_OFIFO_SIZE_DEFAULT,
+		       priv->io_base + _REG(VPP_OFIFO_SIZE));
+	else
+		writel_bits(VPP_OFIFO_SIZE_MASK, 0x77f,
+			    priv->io_base + _REG(VPP_OFIFO_SIZE));
+	writel(VPP_POSTBLEND_HOLD_LINES(4) | VPP_PREBLEND_HOLD_LINES(4),
+	       priv->io_base + _REG(VPP_HOLD_LINES));
+
+	if (!meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
+		/* Turn off preblend */
+		writel_bits(VPP_PREBLEND_ENABLE, 0,
+			    priv->io_base + _REG(VPP_MISC));
+
+		/* Turn off POSTBLEND */
+		writel_bits(VPP_POSTBLEND_ENABLE, 0,
+			    priv->io_base + _REG(VPP_MISC));
+
+		/* Force all planes off */
+		writel_bits(VPP_OSD1_POSTBLEND | VPP_OSD2_POSTBLEND |
+			    VPP_VD1_POSTBLEND | VPP_VD2_POSTBLEND |
+			    VPP_VD1_PREBLEND | VPP_VD2_PREBLEND, 0,
+			    priv->io_base + _REG(VPP_MISC));
+
+		/* Setup default VD settings */
+		writel(4096,
+		       priv->io_base + _REG(VPP_PREBLEND_VD1_H_START_END));
+		writel(4096,
+		       priv->io_base + _REG(VPP_BLEND_VD2_H_START_END));
+	}
 
 	/* Disable Scalers */
 	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));
-	writel(4 | (4 << 8) | BIT(15),
+
+	writel(VPP_VSC_BANK_LENGTH(4) | VPP_HSC_BANK_LENGTH(4) |
+	       VPP_SC_VD_EN_ENABLE,
 	       priv->io_base + _REG(VPP_SC_MISC));
 
+	/* Enable minus black level for vadj1 */
+	writel(VPP_MINUS_BLACK_LVL_VADJ1_ENABLE,
+	       priv->io_base + _REG(VPP_VADJ_CTRL));
+
 	/* Write in the proper filter coefficients. */
 	meson_vpp_write_scaling_filter_coefs(priv,
 				vpp_filter_coefs_4point_bspline, false);
@@ -410,23 +484,31 @@ void meson_vpu_init(struct udevice *dev)
 						true);
 
 	/* Disable OSDs */
-	writel_bits(BIT(0) | BIT(21), 0,
+	writel_bits(VIU_OSD1_OSD_BLK_ENABLE | VIU_OSD1_OSD_ENABLE, 0,
 		    priv->io_base + _REG(VIU_OSD1_CTRL_STAT));
-	writel_bits(BIT(0) | BIT(21), 0,
+	writel_bits(VIU_OSD1_OSD_BLK_ENABLE | VIU_OSD1_OSD_ENABLE, 0,
 		    priv->io_base + _REG(VIU_OSD2_CTRL_STAT));
 
 	/* On GXL/GXM, Use the 10bit HDR conversion matrix */
 	if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM) ||
 	    meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL))
 		meson_viu_load_matrix(priv);
+	else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
+		meson_viu_set_g12a_osd1_matrix(priv, RGB709_to_YUV709l_coeff,
+					       true);
 
 	/* Initialize OSD1 fifo control register */
-	reg = BIT(0) |	/* Urgent DDR request priority */
-	      (4 << 5) | /* hold_fifo_lines */
-	      (3 << 10) | /* burst length 64 */
-	      (32 << 12) | /* fifo_depth_val: 32*8=256 */
-	      (2 << 22) | /* 4 words in 1 burst */
-	      (2 << 24);
+	reg = VIU_OSD_DDR_PRIORITY_URGENT |
+		VIU_OSD_HOLD_FIFO_LINES(4) |
+		VIU_OSD_FIFO_DEPTH_VAL(32) | /* fifo_depth_val: 32*8=256 */
+		VIU_OSD_WORDS_PER_BURST(4) | /* 4 words in 1 burst */
+		VIU_OSD_FIFO_LIMITS(2);      /* fifo_lim: 2*16=32 */
+
+	if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
+		reg |= meson_viu_osd_burst_length_reg(32);
+	else
+		reg |= meson_viu_osd_burst_length_reg(64);
+
 	writel(reg, priv->io_base + _REG(VIU_OSD1_FIFO_CTRL_STAT));
 	writel(reg, priv->io_base + _REG(VIU_OSD2_FIFO_CTRL_STAT));
 
@@ -437,4 +519,39 @@ void meson_vpu_init(struct udevice *dev)
 	writel_bits(0xff << OSD_REPLACE_SHIFT,
 		    0xff << OSD_REPLACE_SHIFT,
 		    priv->io_base + _REG(VIU_OSD2_CTRL_STAT2));
+
+	/* Disable VD1 AFBC */
+	/* di_mif0_en=0 mif0_to_vpp_en=0 di_mad_en=0 and afbc vd1 set=0*/
+	writel_bits(VIU_CTRL0_VD1_AFBC_MASK, 0,
+		    priv->io_base + _REG(VIU_MISC_CTRL0));
+	writel(0, priv->io_base + _REG(AFBC_ENABLE));
+
+	writel(0x00FF00C0,
+	       priv->io_base + _REG(VD1_IF0_LUMA_FIFO_SIZE));
+	writel(0x00FF00C0,
+	       priv->io_base + _REG(VD2_IF0_LUMA_FIFO_SIZE));
+
+	if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
+		writel(VIU_OSD_BLEND_REORDER(0, 1) |
+		       VIU_OSD_BLEND_REORDER(1, 0) |
+		       VIU_OSD_BLEND_REORDER(2, 0) |
+		       VIU_OSD_BLEND_REORDER(3, 0) |
+		       VIU_OSD_BLEND_DIN_EN(1) |
+		       VIU_OSD_BLEND1_DIN3_BYPASS_TO_DOUT1 |
+		       VIU_OSD_BLEND1_DOUT_BYPASS_TO_BLEND2 |
+		       VIU_OSD_BLEND_DIN0_BYPASS_TO_DOUT0 |
+		       VIU_OSD_BLEND_BLEN2_PREMULT_EN(1) |
+		       VIU_OSD_BLEND_HOLD_LINES(4),
+		       priv->io_base + _REG(VIU_OSD_BLEND_CTRL));
+		writel(OSD_BLEND_PATH_SEL_ENABLE,
+		       priv->io_base + _REG(OSD1_BLEND_SRC_CTRL));
+		writel(OSD_BLEND_PATH_SEL_ENABLE,
+		       priv->io_base + _REG(OSD2_BLEND_SRC_CTRL));
+		writel(0, priv->io_base + _REG(VD1_BLEND_SRC_CTRL));
+		writel(0, priv->io_base + _REG(VD2_BLEND_SRC_CTRL));
+		writel(0, priv->io_base + _REG(VIU_OSD_BLEND_DUMMY_DATA0));
+		writel(0, priv->io_base + _REG(VIU_OSD_BLEND_DUMMY_ALPHA));
+		writel_bits(DOLBY_BYPASS_EN(0xc), DOLBY_BYPASS_EN(0xc),
+			    priv->io_base + _REG(DOLBY_PATH_CTRL));
+	}
 }
-- 
2.22.0


^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [U-Boot] [PATCH 5/8] video: meson: add compatible for Amlogic G12A
  2019-08-30 12:09 ` Neil Armstrong
@ 2019-08-30 12:09   ` Neil Armstrong
  -1 siblings, 0 replies; 38+ messages in thread
From: Neil Armstrong @ 2019-08-30 12:09 UTC (permalink / raw)
  To: u-boot

Finally add the Amlogic G12A SoC compatible for the VPU driver.

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 drivers/video/meson/meson_vpu.c | 1 +
 drivers/video/meson/meson_vpu.h | 1 +
 2 files changed, 2 insertions(+)

diff --git a/drivers/video/meson/meson_vpu.c b/drivers/video/meson/meson_vpu.c
index 34d35749eb..c3af9b013c 100644
--- a/drivers/video/meson/meson_vpu.c
+++ b/drivers/video/meson/meson_vpu.c
@@ -86,6 +86,7 @@ static const struct udevice_id meson_vpu_ids[] = {
 	{ .compatible = "amlogic,meson-gxbb-vpu", .data = VPU_COMPATIBLE_GXBB },
 	{ .compatible = "amlogic,meson-gxl-vpu", .data = VPU_COMPATIBLE_GXL },
 	{ .compatible = "amlogic,meson-gxm-vpu", .data = VPU_COMPATIBLE_GXM },
+	{ .compatible = "amlogic,meson-g12a-vpu", .data = VPU_COMPATIBLE_G12A },
 	{ }
 };
 
diff --git a/drivers/video/meson/meson_vpu.h b/drivers/video/meson/meson_vpu.h
index 3412dac052..0d9fddad2e 100644
--- a/drivers/video/meson/meson_vpu.h
+++ b/drivers/video/meson/meson_vpu.h
@@ -28,6 +28,7 @@ enum vpu_compatible {
 	VPU_COMPATIBLE_GXBB = 0,
 	VPU_COMPATIBLE_GXL = 1,
 	VPU_COMPATIBLE_GXM = 2,
+	VPU_COMPATIBLE_G12A = 3,
 };
 
 struct meson_vpu_priv {
-- 
2.22.0

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH 5/8] video: meson: add compatible for Amlogic G12A
@ 2019-08-30 12:09   ` Neil Armstrong
  0 siblings, 0 replies; 38+ messages in thread
From: Neil Armstrong @ 2019-08-30 12:09 UTC (permalink / raw)
  To: u-boot-amlogic, agust; +Cc: Neil Armstrong, u-boot

Finally add the Amlogic G12A SoC compatible for the VPU driver.

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 drivers/video/meson/meson_vpu.c | 1 +
 drivers/video/meson/meson_vpu.h | 1 +
 2 files changed, 2 insertions(+)

diff --git a/drivers/video/meson/meson_vpu.c b/drivers/video/meson/meson_vpu.c
index 34d35749eb..c3af9b013c 100644
--- a/drivers/video/meson/meson_vpu.c
+++ b/drivers/video/meson/meson_vpu.c
@@ -86,6 +86,7 @@ static const struct udevice_id meson_vpu_ids[] = {
 	{ .compatible = "amlogic,meson-gxbb-vpu", .data = VPU_COMPATIBLE_GXBB },
 	{ .compatible = "amlogic,meson-gxl-vpu", .data = VPU_COMPATIBLE_GXL },
 	{ .compatible = "amlogic,meson-gxm-vpu", .data = VPU_COMPATIBLE_GXM },
+	{ .compatible = "amlogic,meson-g12a-vpu", .data = VPU_COMPATIBLE_G12A },
 	{ }
 };
 
diff --git a/drivers/video/meson/meson_vpu.h b/drivers/video/meson/meson_vpu.h
index 3412dac052..0d9fddad2e 100644
--- a/drivers/video/meson/meson_vpu.h
+++ b/drivers/video/meson/meson_vpu.h
@@ -28,6 +28,7 @@ enum vpu_compatible {
 	VPU_COMPATIBLE_GXBB = 0,
 	VPU_COMPATIBLE_GXL = 1,
 	VPU_COMPATIBLE_GXM = 2,
+	VPU_COMPATIBLE_G12A = 3,
 };
 
 struct meson_vpu_priv {
-- 
2.22.0


^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [U-Boot] [PATCH 6/8] arm: meson: board-g12a: Setup VPU in fdt
  2019-08-30 12:09 ` Neil Armstrong
@ 2019-08-30 12:09   ` Neil Armstrong
  -1 siblings, 0 replies; 38+ messages in thread
From: Neil Armstrong @ 2019-08-30 12:09 UTC (permalink / raw)
  To: u-boot

If VIDEO_MESON is enabled, we need to setup the fdt for the framebuffer.

Call meson_vpu_rsv_fb() which reserves the framebuffer memory region for
EFI, and sets up simple-framebuffer nodes if simplefb support is
enabled.

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 arch/arm/mach-meson/board-g12a.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/arch/arm/mach-meson/board-g12a.c b/arch/arm/mach-meson/board-g12a.c
index 546b9f6039..24786df6cd 100644
--- a/arch/arm/mach-meson/board-g12a.c
+++ b/arch/arm/mach-meson/board-g12a.c
@@ -9,6 +9,7 @@
 #include <asm/arch/eth.h>
 #include <asm/arch/g12a.h>
 #include <asm/arch/mem.h>
+#include <asm/arch/meson-vpu.h>
 #include <asm/io.h>
 #include <asm/armv8/mmu.h>
 #include <linux/sizes.h>
@@ -57,6 +58,10 @@ void meson_init_reserved_memory(void *fdt)
 	/* Add BL32 reserved zone */
 	if (bl32_start && bl32_size)
 		meson_board_add_reserved_memory(fdt, bl32_start, bl32_size);
+
+#if defined(CONFIG_VIDEO_MESON)
+	meson_vpu_rsv_fb(fdt);
+#endif
 }
 
 phys_size_t get_effective_memsize(void)
-- 
2.22.0

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH 6/8] arm: meson: board-g12a: Setup VPU in fdt
@ 2019-08-30 12:09   ` Neil Armstrong
  0 siblings, 0 replies; 38+ messages in thread
From: Neil Armstrong @ 2019-08-30 12:09 UTC (permalink / raw)
  To: u-boot-amlogic; +Cc: Neil Armstrong, u-boot

If VIDEO_MESON is enabled, we need to setup the fdt for the framebuffer.

Call meson_vpu_rsv_fb() which reserves the framebuffer memory region for
EFI, and sets up simple-framebuffer nodes if simplefb support is
enabled.

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 arch/arm/mach-meson/board-g12a.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/arch/arm/mach-meson/board-g12a.c b/arch/arm/mach-meson/board-g12a.c
index 546b9f6039..24786df6cd 100644
--- a/arch/arm/mach-meson/board-g12a.c
+++ b/arch/arm/mach-meson/board-g12a.c
@@ -9,6 +9,7 @@
 #include <asm/arch/eth.h>
 #include <asm/arch/g12a.h>
 #include <asm/arch/mem.h>
+#include <asm/arch/meson-vpu.h>
 #include <asm/io.h>
 #include <asm/armv8/mmu.h>
 #include <linux/sizes.h>
@@ -57,6 +58,10 @@ void meson_init_reserved_memory(void *fdt)
 	/* Add BL32 reserved zone */
 	if (bl32_start && bl32_size)
 		meson_board_add_reserved_memory(fdt, bl32_start, bl32_size);
+
+#if defined(CONFIG_VIDEO_MESON)
+	meson_vpu_rsv_fb(fdt);
+#endif
 }
 
 phys_size_t get_effective_memsize(void)
-- 
2.22.0


^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [U-Boot] [PATCH 7/8] ARM: dts: meson-g12a: add U-Boot specific DT for graphics
  2019-08-30 12:09 ` Neil Armstrong
@ 2019-08-30 12:09   ` Neil Armstrong
  -1 siblings, 0 replies; 38+ messages in thread
From: Neil Armstrong @ 2019-08-30 12:09 UTC (permalink / raw)
  To: u-boot

Like the meson-gx support, add the U-Boot specific bits in DT
to support graphics on G12A SoCs.

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 arch/arm/dts/meson-g12a-sei510-u-boot.dtsi    |  7 +++++
 arch/arm/dts/meson-g12a-u-boot.dtsi           | 29 +++++++++++++++++++
 arch/arm/dts/meson-g12a-u200-u-boot.dtsi      |  7 +++++
 arch/arm/dts/meson-g12b-odroid-n2-u-boot.dtsi |  7 +++++
 4 files changed, 50 insertions(+)
 create mode 100644 arch/arm/dts/meson-g12a-sei510-u-boot.dtsi
 create mode 100644 arch/arm/dts/meson-g12a-u-boot.dtsi
 create mode 100644 arch/arm/dts/meson-g12a-u200-u-boot.dtsi
 create mode 100644 arch/arm/dts/meson-g12b-odroid-n2-u-boot.dtsi

diff --git a/arch/arm/dts/meson-g12a-sei510-u-boot.dtsi b/arch/arm/dts/meson-g12a-sei510-u-boot.dtsi
new file mode 100644
index 0000000000..fddffd628c
--- /dev/null
+++ b/arch/arm/dts/meson-g12a-sei510-u-boot.dtsi
@@ -0,0 +1,7 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2019 BayLibre, SAS.
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ */
+
+#include "meson-g12a-u-boot.dtsi"
diff --git a/arch/arm/dts/meson-g12a-u-boot.dtsi b/arch/arm/dts/meson-g12a-u-boot.dtsi
new file mode 100644
index 0000000000..38fd3d3feb
--- /dev/null
+++ b/arch/arm/dts/meson-g12a-u-boot.dtsi
@@ -0,0 +1,29 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2019 BayLibre, SAS.
+ * Author: Maxime Jourdan <mjourdan@baylibre.com>
+ */
+
+/ {
+	soc {
+		u-boot,dm-pre-reloc;
+	};
+};
+
+&canvas {
+	status = "disabled";
+};
+
+&vpu {
+	reg = <0x0 0xff900000 0x0 0x100000>,
+	      <0x0 0xff63c000 0x0 0x1000>,
+	      <0x0 0xff638000 0x0 0x400>;
+	reg-names = "vpu", "hhi", "dmc";
+	u-boot,dm-pre-reloc;
+};
+
+&hdmi_tx {
+	reg = <0x0 0x0 0x0 0x10000>,
+	      <0x0 0x3c000 0x0 0x1000>;
+	reg-names = "hdmitx", "hhi";
+};
diff --git a/arch/arm/dts/meson-g12a-u200-u-boot.dtsi b/arch/arm/dts/meson-g12a-u200-u-boot.dtsi
new file mode 100644
index 0000000000..fddffd628c
--- /dev/null
+++ b/arch/arm/dts/meson-g12a-u200-u-boot.dtsi
@@ -0,0 +1,7 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2019 BayLibre, SAS.
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ */
+
+#include "meson-g12a-u-boot.dtsi"
diff --git a/arch/arm/dts/meson-g12b-odroid-n2-u-boot.dtsi b/arch/arm/dts/meson-g12b-odroid-n2-u-boot.dtsi
new file mode 100644
index 0000000000..fddffd628c
--- /dev/null
+++ b/arch/arm/dts/meson-g12b-odroid-n2-u-boot.dtsi
@@ -0,0 +1,7 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2019 BayLibre, SAS.
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ */
+
+#include "meson-g12a-u-boot.dtsi"
-- 
2.22.0

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH 7/8] ARM: dts: meson-g12a: add U-Boot specific DT for graphics
@ 2019-08-30 12:09   ` Neil Armstrong
  0 siblings, 0 replies; 38+ messages in thread
From: Neil Armstrong @ 2019-08-30 12:09 UTC (permalink / raw)
  To: u-boot-amlogic; +Cc: Neil Armstrong, u-boot

Like the meson-gx support, add the U-Boot specific bits in DT
to support graphics on G12A SoCs.

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 arch/arm/dts/meson-g12a-sei510-u-boot.dtsi    |  7 +++++
 arch/arm/dts/meson-g12a-u-boot.dtsi           | 29 +++++++++++++++++++
 arch/arm/dts/meson-g12a-u200-u-boot.dtsi      |  7 +++++
 arch/arm/dts/meson-g12b-odroid-n2-u-boot.dtsi |  7 +++++
 4 files changed, 50 insertions(+)
 create mode 100644 arch/arm/dts/meson-g12a-sei510-u-boot.dtsi
 create mode 100644 arch/arm/dts/meson-g12a-u-boot.dtsi
 create mode 100644 arch/arm/dts/meson-g12a-u200-u-boot.dtsi
 create mode 100644 arch/arm/dts/meson-g12b-odroid-n2-u-boot.dtsi

diff --git a/arch/arm/dts/meson-g12a-sei510-u-boot.dtsi b/arch/arm/dts/meson-g12a-sei510-u-boot.dtsi
new file mode 100644
index 0000000000..fddffd628c
--- /dev/null
+++ b/arch/arm/dts/meson-g12a-sei510-u-boot.dtsi
@@ -0,0 +1,7 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2019 BayLibre, SAS.
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ */
+
+#include "meson-g12a-u-boot.dtsi"
diff --git a/arch/arm/dts/meson-g12a-u-boot.dtsi b/arch/arm/dts/meson-g12a-u-boot.dtsi
new file mode 100644
index 0000000000..38fd3d3feb
--- /dev/null
+++ b/arch/arm/dts/meson-g12a-u-boot.dtsi
@@ -0,0 +1,29 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2019 BayLibre, SAS.
+ * Author: Maxime Jourdan <mjourdan@baylibre.com>
+ */
+
+/ {
+	soc {
+		u-boot,dm-pre-reloc;
+	};
+};
+
+&canvas {
+	status = "disabled";
+};
+
+&vpu {
+	reg = <0x0 0xff900000 0x0 0x100000>,
+	      <0x0 0xff63c000 0x0 0x1000>,
+	      <0x0 0xff638000 0x0 0x400>;
+	reg-names = "vpu", "hhi", "dmc";
+	u-boot,dm-pre-reloc;
+};
+
+&hdmi_tx {
+	reg = <0x0 0x0 0x0 0x10000>,
+	      <0x0 0x3c000 0x0 0x1000>;
+	reg-names = "hdmitx", "hhi";
+};
diff --git a/arch/arm/dts/meson-g12a-u200-u-boot.dtsi b/arch/arm/dts/meson-g12a-u200-u-boot.dtsi
new file mode 100644
index 0000000000..fddffd628c
--- /dev/null
+++ b/arch/arm/dts/meson-g12a-u200-u-boot.dtsi
@@ -0,0 +1,7 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2019 BayLibre, SAS.
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ */
+
+#include "meson-g12a-u-boot.dtsi"
diff --git a/arch/arm/dts/meson-g12b-odroid-n2-u-boot.dtsi b/arch/arm/dts/meson-g12b-odroid-n2-u-boot.dtsi
new file mode 100644
index 0000000000..fddffd628c
--- /dev/null
+++ b/arch/arm/dts/meson-g12b-odroid-n2-u-boot.dtsi
@@ -0,0 +1,7 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2019 BayLibre, SAS.
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ */
+
+#include "meson-g12a-u-boot.dtsi"
-- 
2.22.0


^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [U-Boot] [PATCH 8/8] configs: sei510: enable Video Display support
  2019-08-30 12:09 ` Neil Armstrong
@ 2019-08-30 12:09   ` Neil Armstrong
  -1 siblings, 0 replies; 38+ messages in thread
From: Neil Armstrong @ 2019-08-30 12:09 UTC (permalink / raw)
  To: u-boot

Add the necessary config options to support BMP display over HDMI,
and add a preboot command to load the BMP file from a predefined
eMMC partition.

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 configs/sei510_defconfig | 11 +++++++++++
 include/configs/sei510.h | 12 ++++++++++++
 2 files changed, 23 insertions(+)

diff --git a/configs/sei510_defconfig b/configs/sei510_defconfig
index 5aea81d873..9eb205bc63 100644
--- a/configs/sei510_defconfig
+++ b/configs/sei510_defconfig
@@ -11,6 +11,9 @@ CONFIG_IDENT_STRING=" sei510"
 # CONFIG_PSCI_RESET is not set
 CONFIG_DEBUG_UART=y
 CONFIG_OF_BOARD_SETUP=y
+CONFIG_USE_PREBOOT=y
+CONFIG_PREBOOT="run load_logo"
+# CONFIG_CONSOLE_MUX is not set
 CONFIG_MISC_INIT_R=y
 # CONFIG_DISPLAY_CPUINFO is not set
 # CONFIG_CMD_BDI is not set
@@ -23,6 +26,7 @@ CONFIG_CMD_USB=y
 CONFIG_CMD_USB_MASS_STORAGE=y
 # CONFIG_CMD_SETEXPR is not set
 CONFIG_CMD_REGULATOR=y
+CONFIG_CMD_BMP=y
 CONFIG_OF_CONTROL=y
 CONFIG_DEFAULT_DEVICE_TREE="meson-g12a-sei510"
 CONFIG_ENV_IS_IN_MMC=y
@@ -33,6 +37,7 @@ CONFIG_FASTBOOT_FLASH=y
 CONFIG_FASTBOOT_FLASH_MMC_DEV=2
 CONFIG_FASTBOOT_CMD_OEM_FORMAT=y
 CONFIG_DM_GPIO=y
+# CONFIG_INPUT is not set
 CONFIG_DM_MMC=y
 CONFIG_MMC_MESON_GX=y
 CONFIG_PHY_ADDR_ENABLE=y
@@ -42,6 +47,12 @@ CONFIG_ETH_DESIGNWARE=y
 CONFIG_MESON_G12A_USB_PHY=y
 CONFIG_PINCTRL=y
 CONFIG_PINCTRL_MESON_G12A=y
+CONFIG_POWER_DOMAIN=y
+CONFIG_MESON_GX_VPU_POWER_DOMAIN=y
+CONFIG_DM_VIDEO=y
+CONFIG_SYS_WHITE_ON_BLACK=y
+CONFIG_VIDEO_MESON=y
+CONFIG_VIDEO_DT_SIMPLEFB=y
 CONFIG_DM_REGULATOR=y
 CONFIG_DM_REGULATOR_FIXED=y
 CONFIG_DM_RESET=y
diff --git a/include/configs/sei510.h b/include/configs/sei510.h
index 9957902250..5bf982cada 100644
--- a/include/configs/sei510.h
+++ b/include/configs/sei510.h
@@ -14,6 +14,7 @@
 #define CONFIG_ENV_SIZE		0x10000
 #define CONFIG_ENV_OFFSET	(-0x10000)
 
+#define LOGO_UUID "43a3305d-150f-4cc9-bd3b-38fca8693846;"
 #define CACHE_UUID "99207ae6-5207-11e9-999e-6f77a3612069;"
 #define SYSTEM_UUID "99f9b7ac-5207-11e9-8507-c3c037e393f3;"
 #define VENDOR_UUID "9d082802-5207-11e9-954c-cbbce08ba108;"
@@ -23,6 +24,7 @@
 #define PARTS_DEFAULT                                        \
 	"uuid_disk=${uuid_gpt_disk};"  			\
 	"name=boot,size=64M,bootable,uuid=${uuid_gpt_boot};" \
+	"name=logo,size=2M,uuid=" LOGO_UUID             \
 	"name=cache,size=256M,uuid=" CACHE_UUID             \
 	"name=system,size=1536M,uuid=" SYSTEM_UUID           \
 	"name=vendor,size=256M,uuid=" VENDOR_UUID            \
@@ -113,12 +115,22 @@
 	func(RECOVERY, recovery, na) \
 	func(SYSTEM, system, na) \
 
+#define PREBOOT_LOAD_LOGO \
+	"mmc dev ${mmcdev};" \
+	"part start mmc ${mmcdev} ${logopart} boot_start;" \
+	"part size mmc ${mmcdev} ${logopart} boot_size;" \
+	"if mmc read ${loadaddr} ${boot_start} ${boot_size}; then " \
+			"bmp display ${loadaddr} m m;" \
+	"fi;"
+
 #define CONFIG_EXTRA_ENV_SETTINGS                                     \
 	"partitions=" PARTS_DEFAULT "\0"                              \
 	"mmcdev=2\0"                                                  \
 	"bootpart=1\0"                                                \
+	"logopart=2\0"                                                \
 	"gpio_recovery=88\0"                                          \
 	"check_button=gpio input ${gpio_recovery};test $? -eq 0;\0"   \
+	"load_logo=" PREBOOT_LOAD_LOGO "\0"			      \
 	"console=/dev/ttyAML0\0"                                      \
 	"bootargs=no_console_suspend\0"                               \
 	"stdin=" STDIN_CFG "\0"                                       \
-- 
2.22.0

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH 8/8] configs: sei510: enable Video Display support
@ 2019-08-30 12:09   ` Neil Armstrong
  0 siblings, 0 replies; 38+ messages in thread
From: Neil Armstrong @ 2019-08-30 12:09 UTC (permalink / raw)
  To: u-boot-amlogic; +Cc: Neil Armstrong, u-boot

Add the necessary config options to support BMP display over HDMI,
and add a preboot command to load the BMP file from a predefined
eMMC partition.

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 configs/sei510_defconfig | 11 +++++++++++
 include/configs/sei510.h | 12 ++++++++++++
 2 files changed, 23 insertions(+)

diff --git a/configs/sei510_defconfig b/configs/sei510_defconfig
index 5aea81d873..9eb205bc63 100644
--- a/configs/sei510_defconfig
+++ b/configs/sei510_defconfig
@@ -11,6 +11,9 @@ CONFIG_IDENT_STRING=" sei510"
 # CONFIG_PSCI_RESET is not set
 CONFIG_DEBUG_UART=y
 CONFIG_OF_BOARD_SETUP=y
+CONFIG_USE_PREBOOT=y
+CONFIG_PREBOOT="run load_logo"
+# CONFIG_CONSOLE_MUX is not set
 CONFIG_MISC_INIT_R=y
 # CONFIG_DISPLAY_CPUINFO is not set
 # CONFIG_CMD_BDI is not set
@@ -23,6 +26,7 @@ CONFIG_CMD_USB=y
 CONFIG_CMD_USB_MASS_STORAGE=y
 # CONFIG_CMD_SETEXPR is not set
 CONFIG_CMD_REGULATOR=y
+CONFIG_CMD_BMP=y
 CONFIG_OF_CONTROL=y
 CONFIG_DEFAULT_DEVICE_TREE="meson-g12a-sei510"
 CONFIG_ENV_IS_IN_MMC=y
@@ -33,6 +37,7 @@ CONFIG_FASTBOOT_FLASH=y
 CONFIG_FASTBOOT_FLASH_MMC_DEV=2
 CONFIG_FASTBOOT_CMD_OEM_FORMAT=y
 CONFIG_DM_GPIO=y
+# CONFIG_INPUT is not set
 CONFIG_DM_MMC=y
 CONFIG_MMC_MESON_GX=y
 CONFIG_PHY_ADDR_ENABLE=y
@@ -42,6 +47,12 @@ CONFIG_ETH_DESIGNWARE=y
 CONFIG_MESON_G12A_USB_PHY=y
 CONFIG_PINCTRL=y
 CONFIG_PINCTRL_MESON_G12A=y
+CONFIG_POWER_DOMAIN=y
+CONFIG_MESON_GX_VPU_POWER_DOMAIN=y
+CONFIG_DM_VIDEO=y
+CONFIG_SYS_WHITE_ON_BLACK=y
+CONFIG_VIDEO_MESON=y
+CONFIG_VIDEO_DT_SIMPLEFB=y
 CONFIG_DM_REGULATOR=y
 CONFIG_DM_REGULATOR_FIXED=y
 CONFIG_DM_RESET=y
diff --git a/include/configs/sei510.h b/include/configs/sei510.h
index 9957902250..5bf982cada 100644
--- a/include/configs/sei510.h
+++ b/include/configs/sei510.h
@@ -14,6 +14,7 @@
 #define CONFIG_ENV_SIZE		0x10000
 #define CONFIG_ENV_OFFSET	(-0x10000)
 
+#define LOGO_UUID "43a3305d-150f-4cc9-bd3b-38fca8693846;"
 #define CACHE_UUID "99207ae6-5207-11e9-999e-6f77a3612069;"
 #define SYSTEM_UUID "99f9b7ac-5207-11e9-8507-c3c037e393f3;"
 #define VENDOR_UUID "9d082802-5207-11e9-954c-cbbce08ba108;"
@@ -23,6 +24,7 @@
 #define PARTS_DEFAULT                                        \
 	"uuid_disk=${uuid_gpt_disk};"  			\
 	"name=boot,size=64M,bootable,uuid=${uuid_gpt_boot};" \
+	"name=logo,size=2M,uuid=" LOGO_UUID             \
 	"name=cache,size=256M,uuid=" CACHE_UUID             \
 	"name=system,size=1536M,uuid=" SYSTEM_UUID           \
 	"name=vendor,size=256M,uuid=" VENDOR_UUID            \
@@ -113,12 +115,22 @@
 	func(RECOVERY, recovery, na) \
 	func(SYSTEM, system, na) \
 
+#define PREBOOT_LOAD_LOGO \
+	"mmc dev ${mmcdev};" \
+	"part start mmc ${mmcdev} ${logopart} boot_start;" \
+	"part size mmc ${mmcdev} ${logopart} boot_size;" \
+	"if mmc read ${loadaddr} ${boot_start} ${boot_size}; then " \
+			"bmp display ${loadaddr} m m;" \
+	"fi;"
+
 #define CONFIG_EXTRA_ENV_SETTINGS                                     \
 	"partitions=" PARTS_DEFAULT "\0"                              \
 	"mmcdev=2\0"                                                  \
 	"bootpart=1\0"                                                \
+	"logopart=2\0"                                                \
 	"gpio_recovery=88\0"                                          \
 	"check_button=gpio input ${gpio_recovery};test $? -eq 0;\0"   \
+	"load_logo=" PREBOOT_LOAD_LOGO "\0"			      \
 	"console=/dev/ttyAML0\0"                                      \
 	"bootargs=no_console_suspend\0"                               \
 	"stdin=" STDIN_CFG "\0"                                       \
-- 
2.22.0


^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [U-Boot] [PATCH 4/8] video: meson: sync with linux drm-misc tree
  2019-08-30 12:09   ` Neil Armstrong
@ 2019-10-09 15:12     ` Neil Armstrong
  -1 siblings, 0 replies; 38+ messages in thread
From: Neil Armstrong @ 2019-10-09 15:12 UTC (permalink / raw)
  To: u-boot

Hi Anatolij,

Gentle ping, did you have time to review this patchset ?

Thanks,
Neil
On 30/08/2019 14:09, Neil Armstrong wrote:
> Synchronize the Amlogic Meson Video driver back with the latest
> DRM misc tree, adding G12A platform support, from the latest commit:
> 528a25d040bc ("drm: meson: use match data to detect vpu compatibility")
> 
> The sync includes the following changes from Linux adapted to U-Boot:
> - Add support for VIC alternate timings
> - Switch PLL to 5.94GHz base for 297Mhz pixel clock
> - Add registers for G12A SoC
> - Add G12A Support for VPP setup
> - Add G12A Support for VIU setup
> - Add G12A support for OSD1 Plane
> - Add G12A support for plane handling in CRTC driver
> - Add G12A support for CVBS Encoder
> - Add G12A Video Clock setup
> - Add G12A support for the DW-HDMI Glue
> - fix G12A HDMI PLL settings for 4K60 1000/1001 variations
> - fix primary plane disabling
> - fix G12A primary plane disabling
> - mask value when writing bits relaxed
> - crtc: drv: vpp: viu: venc: use proper macros instead of magic constants
> - global clean-up
> - add macro used to enable HDMI PLL
> - venc: set the correct macrovision max amplitude value
> 
> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
> ---
>  drivers/video/meson/meson_dw_hdmi.c   |  61 ++++-
>  drivers/video/meson/meson_plane.c     |  47 +++-
>  drivers/video/meson/meson_registers.h | 373 +++++++++++++++++++++++++-
>  drivers/video/meson/meson_vclk.c      | 233 ++++++++++++----
>  drivers/video/meson/meson_venc.c      | 169 +++++++++---
>  drivers/video/meson/meson_vpu.h       |   1 +
>  drivers/video/meson/meson_vpu_init.c  | 205 +++++++++++---
>  7 files changed, 929 insertions(+), 160 deletions(-)
> 
> diff --git a/drivers/video/meson/meson_dw_hdmi.c b/drivers/video/meson/meson_dw_hdmi.c
> index 9831d978fc..ae2e6288f3 100644
> --- a/drivers/video/meson/meson_dw_hdmi.c
> +++ b/drivers/video/meson/meson_dw_hdmi.c
> @@ -24,6 +24,7 @@
>  #define HDMITX_TOP_ADDR_REG	0x0
>  #define HDMITX_TOP_DATA_REG	0x4
>  #define HDMITX_TOP_CTRL_REG	0x8
> +#define HDMITX_TOP_G12A_OFFSET	0x8000
>  
>  /* Controller Communication Channel */
>  #define HDMITX_DWC_ADDR_REG	0x10
> @@ -37,6 +38,8 @@
>  #define HHI_HDMI_PHY_CNTL1	0x3a4 /* 0xe9 */
>  #define HHI_HDMI_PHY_CNTL2	0x3a8 /* 0xea */
>  #define HHI_HDMI_PHY_CNTL3	0x3ac /* 0xeb */
> +#define HHI_HDMI_PHY_CNTL4	0x3b0 /* 0xec */
> +#define HHI_HDMI_PHY_CNTL5	0x3b4 /* 0xed */
>  
>  struct meson_dw_hdmi {
>  	struct udevice *dev;
> @@ -48,6 +51,7 @@ enum hdmi_compatible {
>  	HDMI_COMPATIBLE_GXBB = 0,
>  	HDMI_COMPATIBLE_GXL = 1,
>  	HDMI_COMPATIBLE_GXM = 2,
> +	HDMI_COMPATIBLE_G12A = 3,
>  };
>  
>  static inline bool meson_hdmi_is_compatible(struct meson_dw_hdmi *priv,
> @@ -60,8 +64,14 @@ static inline bool meson_hdmi_is_compatible(struct meson_dw_hdmi *priv,
>  
>  static unsigned int dw_hdmi_top_read(struct dw_hdmi *hdmi, unsigned int addr)
>  {
> +	struct meson_dw_hdmi *priv = container_of(hdmi, struct meson_dw_hdmi,
> +						  hdmi);
>  	unsigned int data;
>  
> +	if (meson_hdmi_is_compatible(priv, HDMI_COMPATIBLE_G12A))
> +		return readl(hdmi->ioaddr +
> +			     HDMITX_TOP_G12A_OFFSET + (addr << 2));
> +
>  	/* ADDR must be written twice */
>  	writel(addr & 0xffff, hdmi->ioaddr + HDMITX_TOP_ADDR_REG);
>  	writel(addr & 0xffff, hdmi->ioaddr + HDMITX_TOP_ADDR_REG);
> @@ -76,6 +86,15 @@ static unsigned int dw_hdmi_top_read(struct dw_hdmi *hdmi, unsigned int addr)
>  static inline void dw_hdmi_top_write(struct dw_hdmi *hdmi,
>  				     unsigned int addr, unsigned int data)
>  {
> +	struct meson_dw_hdmi *priv = container_of(hdmi, struct meson_dw_hdmi,
> +						  hdmi);
> +
> +	if (meson_hdmi_is_compatible(priv, HDMI_COMPATIBLE_G12A)) {
> +		writel(data, hdmi->ioaddr +
> +		       HDMITX_TOP_G12A_OFFSET + (addr << 2));
> +		return;
> +	}
> +
>  	/* ADDR must be written twice */
>  	writel(addr & 0xffff, hdmi->ioaddr + HDMITX_TOP_ADDR_REG);
>  	writel(addr & 0xffff, hdmi->ioaddr + HDMITX_TOP_ADDR_REG);
> @@ -237,7 +256,7 @@ static void meson_dw_hdmi_phy_setup_mode(struct meson_dw_hdmi *priv,
>  			hhi_write(HHI_HDMI_PHY_CNTL0, 0x33604142);
>  			hhi_write(HHI_HDMI_PHY_CNTL3, 0x0016315b);
>  		}
> -	} else {
> +	} else if (meson_hdmi_is_compatible(priv, HDMI_COMPATIBLE_GXBB)) {
>  		if (pixel_clock >= 371250) {
>  			/* 5.94Gbps, 3.7125Gbps */
>  			hhi_write(HHI_HDMI_PHY_CNTL0, 0x33353245);
> @@ -251,6 +270,23 @@ static void meson_dw_hdmi_phy_setup_mode(struct meson_dw_hdmi *priv,
>  			hhi_write(HHI_HDMI_PHY_CNTL0, 0x33632122);
>  			hhi_write(HHI_HDMI_PHY_CNTL3, 0x2000115b);
>  		}
> +	} else if (meson_hdmi_is_compatible(priv, HDMI_COMPATIBLE_G12A)) {
> +		if (pixel_clock >= 371250) {
> +			/* 5.94Gbps, 3.7125Gbps */
> +			hhi_write(HHI_HDMI_PHY_CNTL0, 0x37eb65c4);
> +			hhi_write(HHI_HDMI_PHY_CNTL3, 0x2ab0ff3b);
> +			hhi_write(HHI_HDMI_PHY_CNTL5, 0x0000080b);
> +		} else if (pixel_clock >= 297000) {
> +			/* 2.97Gbps */
> +			hhi_write(HHI_HDMI_PHY_CNTL0, 0x33eb6262);
> +			hhi_write(HHI_HDMI_PHY_CNTL3, 0x2ab0ff3b);
> +			hhi_write(HHI_HDMI_PHY_CNTL5, 0x00000003);
> +		} else {
> +			/* 1.485Gbps, and below */
> +			hhi_write(HHI_HDMI_PHY_CNTL0, 0x33eb4242);
> +			hhi_write(HHI_HDMI_PHY_CNTL3, 0x2ab0ff3b);
> +			hhi_write(HHI_HDMI_PHY_CNTL5, 0x00000003);
> +		}
>  	}
>  }
>  
> @@ -292,7 +328,8 @@ static int meson_dw_hdmi_phy_init(struct dw_hdmi *hdmi, uint pixel_clock)
>  
>  	/* BIT_INVERT */
>  	if (meson_hdmi_is_compatible(priv, HDMI_COMPATIBLE_GXL) ||
> -	    meson_hdmi_is_compatible(priv, HDMI_COMPATIBLE_GXM))
> +	    meson_hdmi_is_compatible(priv, HDMI_COMPATIBLE_GXM) ||
> +	    meson_hdmi_is_compatible(priv, HDMI_COMPATIBLE_G12A))
>  		dw_hdmi_hhi_update_bits(priv, HHI_HDMI_PHY_CNTL1, BIT(17), 0);
>  	else
>  		dw_hdmi_hhi_update_bits(priv, HHI_HDMI_PHY_CNTL1,
> @@ -356,8 +393,12 @@ static int meson_dw_hdmi_probe(struct udevice *dev)
>  	priv->hdmi.hdmi_data.enc_out_bus_format = MEDIA_BUS_FMT_RGB888_1X24;
>  	priv->hdmi.hdmi_data.enc_in_bus_format = MEDIA_BUS_FMT_YUV8_1X24;
>  	priv->hdmi.phy_set = meson_dw_hdmi_phy_init;
> -	priv->hdmi.write_reg = dw_hdmi_dwc_write;
> -	priv->hdmi.read_reg = dw_hdmi_dwc_read;
> +	if (meson_hdmi_is_compatible(priv, HDMI_COMPATIBLE_G12A))
> +		priv->hdmi.reg_io_width = 1;
> +	else {
> +		priv->hdmi.write_reg = dw_hdmi_dwc_write;
> +		priv->hdmi.read_reg = dw_hdmi_dwc_read;
> +	}
>  	priv->hdmi.i2c_clk_high = 0x67;
>  	priv->hdmi.i2c_clk_low = 0x78;
>  
> @@ -409,9 +450,13 @@ static int meson_dw_hdmi_probe(struct udevice *dev)
>  	if (ret)
>  		return ret;
>  
> -	/* Enable APB3 fail on error */
> -	writel_bits(BIT(15), BIT(15), priv->hdmi.ioaddr + HDMITX_TOP_CTRL_REG);
> -	writel_bits(BIT(15), BIT(15), priv->hdmi.ioaddr + HDMITX_DWC_CTRL_REG);
> +	if (!meson_hdmi_is_compatible(priv, HDMI_COMPATIBLE_G12A)) {
> +		/* Enable APB3 fail on error */
> +		writel_bits(BIT(15), BIT(15),
> +			    priv->hdmi.ioaddr + HDMITX_TOP_CTRL_REG);
> +		writel_bits(BIT(15), BIT(15),
> +			    priv->hdmi.ioaddr + HDMITX_DWC_CTRL_REG);
> +	}
>  
>  	/* Bring out of reset */
>  	dw_hdmi_top_write(&priv->hdmi, HDMITX_TOP_SW_RESET,  0);
> @@ -448,6 +493,8 @@ static const struct udevice_id meson_dw_hdmi_ids[] = {
>  		.data = HDMI_COMPATIBLE_GXL },
>  	{ .compatible = "amlogic,meson-gxm-dw-hdmi",
>  		.data = HDMI_COMPATIBLE_GXM },
> +	{ .compatible = "amlogic,meson-g12a-dw-hdmi",
> +		.data = HDMI_COMPATIBLE_G12A },
>  	{ }
>  };
>  
> diff --git a/drivers/video/meson/meson_plane.c b/drivers/video/meson/meson_plane.c
> index 63a4bf2d8d..2bc9327e1e 100644
> --- a/drivers/video/meson/meson_plane.c
> +++ b/drivers/video/meson/meson_plane.c
> @@ -108,12 +108,33 @@ void meson_vpu_setup_plane(struct udevice *dev, bool is_interlaced)
>  	dest_y1 = src_y1 = 0;
>  	dest_y2 = src_y2 = uc_priv->ysize;
>  
> -	/* Enable VPP Postblend */
> -	writel(uc_priv->xsize,
> -	       priv->io_base + _REG(VPP_POSTBLEND_H_SIZE));
> +	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));
> +		writel_bits(VPP_POSTBLEND_ENABLE, VPP_POSTBLEND_ENABLE,
> +			    priv->io_base + _REG(VPP_MISC));
> +	}
>  
>  	/* uc_plat->base is the framebuffer */
>  
> @@ -172,6 +193,18 @@ void meson_vpu_setup_plane(struct udevice *dev, bool is_interlaced)
>  			   MESON_CANVAS_BLKMODE_LINEAR);
>  
>  	/* Enable OSD1 */
> -	writel_bits(VPP_OSD1_POSTBLEND, VPP_OSD1_POSTBLEND,
> -		    priv->io_base + _REG(VPP_MISC));
> +	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));
>  }
> diff --git a/drivers/video/meson/meson_registers.h b/drivers/video/meson/meson_registers.h
> index 01fe7d2431..39e8ec8639 100644
> --- a/drivers/video/meson/meson_registers.h
> +++ b/drivers/video/meson/meson_registers.h
> @@ -136,11 +136,19 @@
>  #define VIU_ADDR_START 0x1a00
>  #define VIU_ADDR_END 0x1aff
>  #define VIU_SW_RESET 0x1a01
> +#define		VIU_SW_RESET_OSD1               BIT(0)
>  #define VIU_MISC_CTRL0 0x1a06
> +#define		VIU_CTRL0_VD1_AFBC_MASK         0x170000
>  #define VIU_MISC_CTRL1 0x1a07
>  #define D2D3_INTF_LENGTH 0x1a08
>  #define D2D3_INTF_CTRL0 0x1a09
>  #define VIU_OSD1_CTRL_STAT 0x1a10
> +#define		VIU_OSD1_OSD_BLK_ENABLE         BIT(0)
> +#define		VIU_OSD1_POSTBLD_SRC_VD1        (1 << 8)
> +#define		VIU_OSD1_POSTBLD_SRC_VD2        (2 << 8)
> +#define		VIU_OSD1_POSTBLD_SRC_OSD1       (3 << 8)
> +#define		VIU_OSD1_POSTBLD_SRC_OSD2       (4 << 8)
> +#define		VIU_OSD1_OSD_ENABLE             BIT(21)
>  #define VIU_OSD1_CTRL_STAT2 0x1a2d
>  #define VIU_OSD1_COLOR_ADDR 0x1a11
>  #define VIU_OSD1_COLOR 0x1a12
> @@ -206,6 +214,35 @@
>  #define VIU_OSD2_FIFO_CTRL_STAT 0x1a4b
>  #define VIU_OSD2_TEST_RDDATA 0x1a4c
>  #define VIU_OSD2_PROT_CTRL 0x1a4e
> +#define VIU_OSD2_MALI_UNPACK_CTRL 0x1abd
> +#define VIU_OSD2_DIMM_CTRL 0x1acf
> +
> +#define VIU_OSD3_CTRL_STAT 0x3d80
> +#define VIU_OSD3_CTRL_STAT2 0x3d81
> +#define VIU_OSD3_COLOR_ADDR 0x3d82
> +#define VIU_OSD3_COLOR 0x3d83
> +#define VIU_OSD3_TCOLOR_AG0 0x3d84
> +#define VIU_OSD3_TCOLOR_AG1 0x3d85
> +#define VIU_OSD3_TCOLOR_AG2 0x3d86
> +#define VIU_OSD3_TCOLOR_AG3 0x3d87
> +#define VIU_OSD3_BLK0_CFG_W0 0x3d88
> +#define VIU_OSD3_BLK0_CFG_W1 0x3d8c
> +#define VIU_OSD3_BLK0_CFG_W2 0x3d90
> +#define VIU_OSD3_BLK0_CFG_W3 0x3d94
> +#define VIU_OSD3_BLK0_CFG_W4 0x3d98
> +#define VIU_OSD3_BLK1_CFG_W4 0x3d99
> +#define VIU_OSD3_BLK2_CFG_W4 0x3d9a
> +#define VIU_OSD3_FIFO_CTRL_STAT 0x3d9c
> +#define VIU_OSD3_TEST_RDDATA 0x3d9d
> +#define VIU_OSD3_PROT_CTRL 0x3d9e
> +#define VIU_OSD3_MALI_UNPACK_CTRL 0x3d9f
> +#define VIU_OSD3_DIMM_CTRL 0x3da0
> +
> +#define VIU_OSD_DDR_PRIORITY_URGENT      BIT(0)
> +#define VIU_OSD_HOLD_FIFO_LINES(lines)   ((lines & 0x1f) << 5)
> +#define VIU_OSD_FIFO_DEPTH_VAL(val)      ((val & 0x7f) << 12)
> +#define VIU_OSD_WORDS_PER_BURST(words)   (((words & 0x4) >> 1) << 22)
> +#define VIU_OSD_FIFO_LIMITS(size)        ((size & 0xf) << 24)
>  
>  #define VD1_IF0_GEN_REG 0x1a50
>  #define VD1_IF0_CANVAS0 0x1a51
> @@ -277,6 +314,27 @@
>  #define VIU_OSD1_MATRIX_COEF31_32 0x1a9e
>  #define VIU_OSD1_MATRIX_COEF40_41 0x1a9f
>  #define VD1_IF0_GEN_REG3 0x1aa7
> +
> +#define VIU_OSD_BLENDO_H_START_END 0x1aa9
> +#define VIU_OSD_BLENDO_V_START_END 0x1aaa
> +#define VIU_OSD_BLEND_GEN_CTRL0 0x1aab
> +#define VIU_OSD_BLEND_GEN_CTRL1 0x1aac
> +#define VIU_OSD_BLEND_DUMMY_DATA 0x1aad
> +#define VIU_OSD_BLEND_CURRENT_XY 0x1aae
> +
> +#define VIU_OSD2_MATRIX_CTRL 0x1ab0
> +#define VIU_OSD2_MATRIX_COEF00_01 0x1ab1
> +#define VIU_OSD2_MATRIX_COEF02_10 0x1ab2
> +#define VIU_OSD2_MATRIX_COEF11_12 0x1ab3
> +#define VIU_OSD2_MATRIX_COEF20_21 0x1ab4
> +#define VIU_OSD2_MATRIX_COEF22 0x1ab5
> +#define VIU_OSD2_MATRIX_OFFSET0_1 0x1ab6
> +#define VIU_OSD2_MATRIX_OFFSET2 0x1ab7
> +#define VIU_OSD2_MATRIX_PRE_OFFSET0_1 0x1ab8
> +#define VIU_OSD2_MATRIX_PRE_OFFSET2 0x1ab9
> +#define VIU_OSD2_MATRIX_PROBE_COLOR 0x1aba
> +#define VIU_OSD2_MATRIX_HL_COLOR 0x1abb
> +#define VIU_OSD2_MATRIX_PROBE_POS 0x1abc
>  #define VIU_OSD1_EOTF_CTL 0x1ad4
>  #define VIU_OSD1_EOTF_COEF00_01 0x1ad5
>  #define VIU_OSD1_EOTF_COEF02_10 0x1ad6
> @@ -295,6 +353,7 @@
>  #define VPP_LINE_IN_LENGTH 0x1d01
>  #define VPP_PIC_IN_HEIGHT 0x1d02
>  #define VPP_SCALE_COEF_IDX 0x1d03
> +#define		VPP_SCALE_HORIZONTAL_COEF       BIT(8)
>  #define VPP_SCALE_COEF 0x1d04
>  #define VPP_VSC_REGION12_STARTP 0x1d05
>  #define VPP_VSC_REGION34_STARTP 0x1d06
> @@ -316,6 +375,12 @@
>  #define VPP_HSC_REGION4_PHASE_SLOPE 0x1d17
>  #define VPP_HSC_PHASE_CTRL 0x1d18
>  #define VPP_SC_MISC 0x1d19
> +#define		VPP_SC_VD_EN_ENABLE             BIT(15)
> +#define		VPP_SC_TOP_EN_ENABLE            BIT(16)
> +#define		VPP_SC_HSC_EN_ENABLE            BIT(17)
> +#define		VPP_SC_VSC_EN_ENABLE            BIT(18)
> +#define		VPP_VSC_BANK_LENGTH(length)     (length & 0x7)
> +#define		VPP_HSC_BANK_LENGTH(length)     ((length & 0x7) << 8)
>  #define VPP_PREBLEND_VD1_H_START_END 0x1d1a
>  #define VPP_PREBLEND_VD1_V_START_END 0x1d1b
>  #define VPP_POSTBLEND_VD1_H_START_END 0x1d1c
> @@ -325,24 +390,28 @@
>  #define VPP_PREBLEND_H_SIZE 0x1d20
>  #define VPP_POSTBLEND_H_SIZE 0x1d21
>  #define VPP_HOLD_LINES 0x1d22
> +#define		VPP_POSTBLEND_HOLD_LINES(lines) (lines & 0xf)
> +#define		VPP_PREBLEND_HOLD_LINES(lines)  ((lines & 0xf) << 8)
>  #define VPP_BLEND_ONECOLOR_CTRL 0x1d23
>  #define VPP_PREBLEND_CURRENT_XY 0x1d24
>  #define VPP_POSTBLEND_CURRENT_XY 0x1d25
>  #define VPP_MISC 0x1d26
> -#define		VPP_PREBLEND_ENABLE	BIT(6)
> -#define		VPP_POSTBLEND_ENABLE	BIT(7)
> -#define		VPP_OSD2_ALPHA_PREMULT	BIT(8)
> -#define		VPP_OSD1_ALPHA_PREMULT	BIT(9)
> -#define		VPP_VD1_POSTBLEND	BIT(10)
> -#define		VPP_VD2_POSTBLEND	BIT(11)
> -#define		VPP_OSD1_POSTBLEND	BIT(12)
> -#define		VPP_OSD2_POSTBLEND	BIT(13)
> -#define		VPP_VD1_PREBLEND	BIT(14)
> -#define		VPP_VD2_PREBLEND	BIT(15)
> -#define		VPP_OSD1_PREBLEND	BIT(16)
> -#define		VPP_OSD2_PREBLEND	BIT(17)
> -#define		VPP_COLOR_MNG_ENABLE	BIT(28)
> +#define		VPP_PREBLEND_ENABLE             BIT(6)
> +#define		VPP_POSTBLEND_ENABLE            BIT(7)
> +#define		VPP_OSD2_ALPHA_PREMULT          BIT(8)
> +#define		VPP_OSD1_ALPHA_PREMULT          BIT(9)
> +#define		VPP_VD1_POSTBLEND               BIT(10)
> +#define		VPP_VD2_POSTBLEND               BIT(11)
> +#define		VPP_OSD1_POSTBLEND              BIT(12)
> +#define		VPP_OSD2_POSTBLEND              BIT(13)
> +#define		VPP_VD1_PREBLEND                BIT(14)
> +#define		VPP_VD2_PREBLEND                BIT(15)
> +#define		VPP_OSD1_PREBLEND               BIT(16)
> +#define		VPP_OSD2_PREBLEND               BIT(17)
> +#define		VPP_COLOR_MNG_ENABLE            BIT(28)
>  #define VPP_OFIFO_SIZE 0x1d27
> +#define		VPP_OFIFO_SIZE_MASK             GENMASK(13, 0)
> +#define		VPP_OFIFO_SIZE_DEFAULT          (0xfff << 20 | 0x1000)
>  #define VPP_FIFO_STATUS 0x1d28
>  #define VPP_SMOKE_CTRL 0x1d29
>  #define VPP_SMOKE1_VAL 0x1d2a
> @@ -358,6 +427,8 @@
>  #define VPP_HSC_PHASE_CTRL1 0x1d34
>  #define VPP_HSC_INI_PAT_CTRL 0x1d35
>  #define VPP_VADJ_CTRL 0x1d40
> +#define		VPP_MINUS_BLACK_LVL_VADJ1_ENABLE BIT(1)
> +
>  #define VPP_VADJ1_Y 0x1d41
>  #define VPP_VADJ1_MA_MB 0x1d42
>  #define VPP_VADJ1_MC_MD 0x1d43
> @@ -417,6 +488,7 @@
>  #define VPP_PEAKING_VGAIN 0x1d92
>  #define VPP_PEAKING_NLP_1 0x1d93
>  #define VPP_DOLBY_CTRL 0x1d93
> +#define VPP_PPS_DUMMY_DATA_MODE (1 << 17)
>  #define VPP_PEAKING_NLP_2 0x1d94
>  #define VPP_PEAKING_NLP_3 0x1d95
>  #define VPP_PEAKING_NLP_4 0x1d96
> @@ -471,6 +543,83 @@
>  #define VPP_OSD_SCALE_COEF 0x1dcd
>  #define VPP_INT_LINE_NUM 0x1dce
>  
> +#define VPP_WRAP_OSD1_MATRIX_COEF00_01 0x3d60
> +#define VPP_WRAP_OSD1_MATRIX_COEF02_10 0x3d61
> +#define VPP_WRAP_OSD1_MATRIX_COEF11_12 0x3d62
> +#define VPP_WRAP_OSD1_MATRIX_COEF20_21 0x3d63
> +#define VPP_WRAP_OSD1_MATRIX_COEF22 0x3d64
> +#define VPP_WRAP_OSD1_MATRIX_COEF13_14 0x3d65
> +#define VPP_WRAP_OSD1_MATRIX_COEF23_24 0x3d66
> +#define VPP_WRAP_OSD1_MATRIX_COEF15_25 0x3d67
> +#define VPP_WRAP_OSD1_MATRIX_CLIP 0x3d68
> +#define VPP_WRAP_OSD1_MATRIX_OFFSET0_1 0x3d69
> +#define VPP_WRAP_OSD1_MATRIX_OFFSET2 0x3d6a
> +#define VPP_WRAP_OSD1_MATRIX_PRE_OFFSET0_1 0x3d6b
> +#define VPP_WRAP_OSD1_MATRIX_PRE_OFFSET2 0x3d6c
> +#define VPP_WRAP_OSD1_MATRIX_EN_CTRL 0x3d6d
> +
> +#define VPP_WRAP_OSD2_MATRIX_COEF00_01 0x3d70
> +#define VPP_WRAP_OSD2_MATRIX_COEF02_10 0x3d71
> +#define VPP_WRAP_OSD2_MATRIX_COEF11_12 0x3d72
> +#define VPP_WRAP_OSD2_MATRIX_COEF20_21 0x3d73
> +#define VPP_WRAP_OSD2_MATRIX_COEF22 0x3d74
> +#define VPP_WRAP_OSD2_MATRIX_COEF13_14 0x3d75
> +#define VPP_WRAP_OSD2_MATRIX_COEF23_24 0x3d76
> +#define VPP_WRAP_OSD2_MATRIX_COEF15_25 0x3d77
> +#define VPP_WRAP_OSD2_MATRIX_CLIP 0x3d78
> +#define VPP_WRAP_OSD2_MATRIX_OFFSET0_1 0x3d79
> +#define VPP_WRAP_OSD2_MATRIX_OFFSET2 0x3d7a
> +#define VPP_WRAP_OSD2_MATRIX_PRE_OFFSET0_1 0x3d7b
> +#define VPP_WRAP_OSD2_MATRIX_PRE_OFFSET2 0x3d7c
> +#define VPP_WRAP_OSD2_MATRIX_EN_CTRL 0x3d7d
> +
> +#define VPP_WRAP_OSD3_MATRIX_COEF00_01 0x3db0
> +#define VPP_WRAP_OSD3_MATRIX_COEF02_10 0x3db1
> +#define VPP_WRAP_OSD3_MATRIX_COEF11_12 0x3db2
> +#define VPP_WRAP_OSD3_MATRIX_COEF20_21 0x3db3
> +#define VPP_WRAP_OSD3_MATRIX_COEF22 0x3db4
> +#define VPP_WRAP_OSD3_MATRIX_COEF13_14 0x3db5
> +#define VPP_WRAP_OSD3_MATRIX_COEF23_24 0x3db6
> +#define VPP_WRAP_OSD3_MATRIX_COEF15_25 0x3db7
> +#define VPP_WRAP_OSD3_MATRIX_CLIP 0x3db8
> +#define VPP_WRAP_OSD3_MATRIX_OFFSET0_1 0x3db9
> +#define VPP_WRAP_OSD3_MATRIX_OFFSET2 0x3dba
> +#define VPP_WRAP_OSD3_MATRIX_PRE_OFFSET0_1 0x3dbb
> +#define VPP_WRAP_OSD3_MATRIX_PRE_OFFSET2 0x3dbc
> +#define VPP_WRAP_OSD3_MATRIX_EN_CTRL 0x3dbd
> +
> +/* osd2 scaler */
> +#define OSD2_VSC_PHASE_STEP 0x3d00
> +#define OSD2_VSC_INI_PHASE 0x3d01
> +#define OSD2_VSC_CTRL0 0x3d02
> +#define OSD2_HSC_PHASE_STEP 0x3d03
> +#define OSD2_HSC_INI_PHASE 0x3d04
> +#define OSD2_HSC_CTRL0 0x3d05
> +#define OSD2_HSC_INI_PAT_CTRL 0x3d06
> +#define OSD2_SC_DUMMY_DATA 0x3d07
> +#define OSD2_SC_CTRL0 0x3d08
> +#define OSD2_SCI_WH_M1 0x3d09
> +#define OSD2_SCO_H_START_END 0x3d0a
> +#define OSD2_SCO_V_START_END 0x3d0b
> +#define OSD2_SCALE_COEF_IDX 0x3d18
> +#define OSD2_SCALE_COEF 0x3d19
> +
> +/* osd34 scaler */
> +#define OSD34_SCALE_COEF_IDX 0x3d1e
> +#define OSD34_SCALE_COEF 0x3d1f
> +#define OSD34_VSC_PHASE_STEP 0x3d20
> +#define OSD34_VSC_INI_PHASE 0x3d21
> +#define OSD34_VSC_CTRL0 0x3d22
> +#define OSD34_HSC_PHASE_STEP 0x3d23
> +#define OSD34_HSC_INI_PHASE 0x3d24
> +#define OSD34_HSC_CTRL0 0x3d25
> +#define OSD34_HSC_INI_PAT_CTRL 0x3d26
> +#define OSD34_SC_DUMMY_DATA 0x3d27
> +#define OSD34_SC_CTRL0 0x3d28
> +#define OSD34_SCI_WH_M1 0x3d29
> +#define OSD34_SCO_H_START_END 0x3d2a
> +#define OSD34_SCO_V_START_END 0x3d2b
> +
>  /* viu2 */
>  #define VIU2_ADDR_START 0x1e00
>  #define VIU2_ADDR_END 0x1eff
> @@ -584,6 +733,25 @@
>  #define VENC_UPSAMPLE_CTRL0 0x1b64
>  #define VENC_UPSAMPLE_CTRL1 0x1b65
>  #define VENC_UPSAMPLE_CTRL2 0x1b66
> +#define		VENC_UPSAMPLE_CTRL_F0_2_CLK_RATIO        BIT(0)
> +#define		VENC_UPSAMPLE_CTRL_F1_EN                 BIT(5)
> +#define		VENC_UPSAMPLE_CTRL_F1_UPSAMPLE_EN        BIT(6)
> +#define		VENC_UPSAMPLE_CTRL_INTERLACE_HIGH_LUMA   (0x0 << 12)
> +#define		VENC_UPSAMPLE_CTRL_CVBS                  (0x1 << 12)
> +#define		VENC_UPSAMPLE_CTRL_S_VIDEO_LUMA          (0x2 << 12)
> +#define		VENC_UPSAMPLE_CTRL_S_VIDEO_CHROMA        (0x3 << 12)
> +#define		VENC_UPSAMPLE_CTRL_INTERLACE_PB          (0x4 << 12)
> +#define		VENC_UPSAMPLE_CTRL_INTERLACE_PR          (0x5 << 12)
> +#define		VENC_UPSAMPLE_CTRL_INTERLACE_R           (0x6 << 12)
> +#define		VENC_UPSAMPLE_CTRL_INTERLACE_G           (0x7 << 12)
> +#define		VENC_UPSAMPLE_CTRL_INTERLACE_B           (0x8 << 12)
> +#define		VENC_UPSAMPLE_CTRL_PROGRESSIVE_Y         (0x9 << 12)
> +#define		VENC_UPSAMPLE_CTRL_PROGRESSIVE_PB        (0xa << 12)
> +#define		VENC_UPSAMPLE_CTRL_PROGRESSIVE_PR        (0xb << 12)
> +#define		VENC_UPSAMPLE_CTRL_PROGRESSIVE_R         (0xc << 12)
> +#define		VENC_UPSAMPLE_CTRL_PROGRESSIVE_G         (0xd << 12)
> +#define		VENC_UPSAMPLE_CTRL_PROGRESSIVE_B         (0xe << 12)
> +#define		VENC_UPSAMPLE_CTRL_VDAC_TEST_VALUE       (0xf << 12)
>  #define TCON_INVERT_CTL 0x1b67
>  #define VENC_VIDEO_PROG_MODE 0x1b68
>  #define VENC_ENCI_LINE 0x1b69
> @@ -592,6 +760,7 @@
>  #define VENC_ENCP_PIXEL 0x1b6c
>  #define VENC_STATA 0x1b6d
>  #define VENC_INTCTRL 0x1b6e
> +#define		VENC_INTCTRL_ENCI_LNRST_INT_EN  BIT(1)
>  #define VENC_INTFLAG 0x1b6f
>  #define VENC_VIDEO_TST_EN 0x1b70
>  #define VENC_VIDEO_TST_MDSEL 0x1b71
> @@ -602,6 +771,7 @@
>  #define VENC_VIDEO_TST_CLRBAR_WIDTH 0x1b76
>  #define VENC_VIDEO_TST_VDCNT_STSET 0x1b77
>  #define VENC_VDAC_DACSEL0 0x1b78
> +#define		VENC_VDAC_SEL_ATV_DMD           BIT(5)
>  #define VENC_VDAC_DACSEL1 0x1b79
>  #define VENC_VDAC_DACSEL2 0x1b7a
>  #define VENC_VDAC_DACSEL3 0x1b7b
> @@ -622,6 +792,7 @@
>  #define VENC_VDAC_DAC5_GAINCTRL 0x1bfa
>  #define VENC_VDAC_DAC5_OFFSET 0x1bfb
>  #define VENC_VDAC_FIFO_CTRL 0x1bfc
> +#define		VENC_VDAC_FIFO_EN_ENCI_ENABLE   BIT(13)
>  #define ENCL_TCON_INVERT_CTL 0x1bfd
>  #define ENCP_VIDEO_EN 0x1b80
>  #define ENCP_VIDEO_SYNC_MODE 0x1b81
> @@ -637,6 +808,7 @@
>  #define ENCP_VIDEO_SYNC_OFFST 0x1b8b
>  #define ENCP_VIDEO_MACV_OFFST 0x1b8c
>  #define ENCP_VIDEO_MODE 0x1b8d
> +#define		ENCP_VIDEO_MODE_DE_V_HIGH       BIT(14)
>  #define ENCP_VIDEO_MODE_ADV 0x1b8e
>  #define ENCP_DBG_PX_RST 0x1b90
>  #define ENCP_DBG_LN_RST 0x1b91
> @@ -715,6 +887,11 @@
>  #define C656_FS_LNED 0x1be7
>  #define ENCI_VIDEO_MODE 0x1b00
>  #define ENCI_VIDEO_MODE_ADV 0x1b01
> +#define		ENCI_VIDEO_MODE_ADV_DMXMD(val)          (val & 0x3)
> +#define		ENCI_VIDEO_MODE_ADV_VBICTL_LINE_17_22   BIT(2)
> +#define		ENCI_VIDEO_MODE_ADV_YBW_MEDIUM          (0 << 4)
> +#define		ENCI_VIDEO_MODE_ADV_YBW_LOW             (0x1 << 4)
> +#define		ENCI_VIDEO_MODE_ADV_YBW_HIGH            (0x2 << 4)
>  #define ENCI_VIDEO_FSC_ADJ 0x1b02
>  #define ENCI_VIDEO_BRIGHT 0x1b03
>  #define ENCI_VIDEO_CONT 0x1b04
> @@ -785,13 +962,17 @@
>  #define ENCI_DBG_MAXPX 0x1b4c
>  #define ENCI_DBG_MAXLN 0x1b4d
>  #define ENCI_MACV_MAX_AMP 0x1b50
> +#define		ENCI_MACV_MAX_AMP_ENABLE_CHANGE BIT(15)
> +#define		ENCI_MACV_MAX_AMP_VAL(val)      (val & 0x83ff)
>  #define ENCI_MACV_PULSE_LO 0x1b51
>  #define ENCI_MACV_PULSE_HI 0x1b52
>  #define ENCI_MACV_BKP_MAX 0x1b53
>  #define ENCI_CFILT_CTRL 0x1b54
> +#define		ENCI_CFILT_CMPT_SEL_HIGH        BIT(1)
>  #define ENCI_CFILT7 0x1b55
>  #define ENCI_YC_DELAY 0x1b56
>  #define ENCI_VIDEO_EN 0x1b57
> +#define		ENCI_VIDEO_EN_ENABLE            BIT(0)
>  #define ENCI_DVI_HSO_BEGIN 0x1c00
>  #define ENCI_DVI_HSO_END 0x1c01
>  #define ENCI_DVI_VSO_BLINE_EVN 0x1c02
> @@ -803,6 +984,10 @@
>  #define ENCI_DVI_VSO_END_EVN 0x1c08
>  #define ENCI_DVI_VSO_END_ODD 0x1c09
>  #define ENCI_CFILT_CTRL2 0x1c0a
> +#define		ENCI_CFILT_CMPT_CR_DLY(delay)   (delay & 0xf)
> +#define		ENCI_CFILT_CMPT_CB_DLY(delay)   ((delay & 0xf) << 4)
> +#define		ENCI_CFILT_CVBS_CR_DLY(delay)   ((delay & 0xf) << 8)
> +#define		ENCI_CFILT_CVBS_CB_DLY(delay)   ((delay & 0xf) << 12)
>  #define ENCI_DACSEL_0 0x1c0b
>  #define ENCI_DACSEL_1 0x1c0c
>  #define ENCP_DACSEL_0 0x1c0d
> @@ -817,6 +1002,8 @@
>  #define ENCI_TST_CLRBAR_WIDTH 0x1c16
>  #define ENCI_TST_VDCNT_STSET 0x1c17
>  #define ENCI_VFIFO2VD_CTL 0x1c18
> +#define		ENCI_VFIFO2VD_CTL_ENABLE        BIT(0)
> +#define		ENCI_VFIFO2VD_CTL_VD_SEL(val)   ((val & 0xff) << 8)
>  #define ENCI_VFIFO2VD_PIXEL_START 0x1c19
>  #define ENCI_VFIFO2VD_PIXEL_END 0x1c1a
>  #define ENCI_VFIFO2VD_LINE_TOP_START 0x1c1b
> @@ -879,6 +1066,7 @@
>  #define VENC_VDAC_DAC5_FILT_CTRL0 0x1c56
>  #define VENC_VDAC_DAC5_FILT_CTRL1 0x1c57
>  #define VENC_VDAC_DAC0_FILT_CTRL0 0x1c58
> +#define		VENC_VDAC_DAC0_FILT_CTRL0_EN    BIT(0)
>  #define VENC_VDAC_DAC0_FILT_CTRL1 0x1c59
>  #define VENC_VDAC_DAC1_FILT_CTRL0 0x1c5a
>  #define VENC_VDAC_DAC1_FILT_CTRL1 0x1c5b
> @@ -1284,6 +1472,18 @@
>  #define		VIU2_SEL_VENC_ENCP	(2 << 2)
>  #define		VIU2_SEL_VENC_ENCT	(3 << 2)
>  #define VPU_HDMI_SETTING 0x271b
> +#define		VPU_HDMI_ENCI_DATA_TO_HDMI      BIT(0)
> +#define		VPU_HDMI_ENCP_DATA_TO_HDMI      BIT(1)
> +#define		VPU_HDMI_INV_HSYNC              BIT(2)
> +#define		VPU_HDMI_INV_VSYNC              BIT(3)
> +#define		VPU_HDMI_OUTPUT_CRYCB           (0 << 5)
> +#define		VPU_HDMI_OUTPUT_YCBCR           (1 << 5)
> +#define		VPU_HDMI_OUTPUT_YCRCB           (2 << 5)
> +#define		VPU_HDMI_OUTPUT_CBCRY           (3 << 5)
> +#define		VPU_HDMI_OUTPUT_CBYCR           (4 << 5)
> +#define		VPU_HDMI_OUTPUT_CRCBY           (5 << 5)
> +#define		VPU_HDMI_WR_RATE(rate)          (((rate & 0x1f) - 1) << 8)
> +#define		VPU_HDMI_RD_RATE(rate)          (((rate & 0x1f) - 1) << 12)
>  #define ENCI_INFO_READ 0x271c
>  #define ENCP_INFO_READ 0x271d
>  #define ENCT_INFO_READ 0x271e
> @@ -1360,6 +1560,7 @@
>  #define VPU_RDARB_MODE_L1C2 0x2799
>  #define VPU_RDARB_MODE_L2C1 0x279d
>  #define VPU_WRARB_MODE_L2C1 0x27a2
> +#define		VPU_RDARB_SLAVE_TO_MASTER_PORT(dc, port) (port << (16 + dc))
>  
>  /* osd super scale */
>  #define OSDSR_HV_SIZEIN 0x3130
> @@ -1390,4 +1591,150 @@
>  #define OSDSR_YBIC_VCOEF0 0x3149
>  #define OSDSR_CBIC_VCOEF0 0x314a
>  
> +/* osd afbcd on gxtvbb */
> +#define OSD1_AFBCD_ENABLE 0x31a0
> +#define OSD1_AFBCD_MODE 0x31a1
> +#define OSD1_AFBCD_SIZE_IN 0x31a2
> +#define OSD1_AFBCD_HDR_PTR 0x31a3
> +#define OSD1_AFBCD_FRAME_PTR 0x31a4
> +#define OSD1_AFBCD_CHROMA_PTR 0x31a5
> +#define OSD1_AFBCD_CONV_CTRL 0x31a6
> +#define OSD1_AFBCD_STATUS 0x31a8
> +#define OSD1_AFBCD_PIXEL_HSCOPE 0x31a9
> +#define OSD1_AFBCD_PIXEL_VSCOPE 0x31aa
> +
> +/* add for gxm and 962e dv core2 */
> +#define DOLBY_CORE2A_SWAP_CTRL1	0x3434
> +#define DOLBY_CORE2A_SWAP_CTRL2	0x3435
> +
> +/* osd afbc on g12a */
> +#define VPU_MAFBC_BLOCK_ID 0x3a00
> +#define VPU_MAFBC_IRQ_RAW_STATUS 0x3a01
> +#define VPU_MAFBC_IRQ_CLEAR 0x3a02
> +#define VPU_MAFBC_IRQ_MASK 0x3a03
> +#define VPU_MAFBC_IRQ_STATUS 0x3a04
> +#define VPU_MAFBC_COMMAND 0x3a05
> +#define VPU_MAFBC_STATUS 0x3a06
> +#define VPU_MAFBC_SURFACE_CFG 0x3a07
> +#define VPU_MAFBC_HEADER_BUF_ADDR_LOW_S0 0x3a10
> +#define VPU_MAFBC_HEADER_BUF_ADDR_HIGH_S0 0x3a11
> +#define VPU_MAFBC_FORMAT_SPECIFIER_S0 0x3a12
> +#define VPU_MAFBC_BUFFER_WIDTH_S0 0x3a13
> +#define VPU_MAFBC_BUFFER_HEIGHT_S0 0x3a14
> +#define VPU_MAFBC_BOUNDING_BOX_X_START_S0 0x3a15
> +#define VPU_MAFBC_BOUNDING_BOX_X_END_S0 0x3a16
> +#define VPU_MAFBC_BOUNDING_BOX_Y_START_S0 0x3a17
> +#define VPU_MAFBC_BOUNDING_BOX_Y_END_S0 0x3a18
> +#define VPU_MAFBC_OUTPUT_BUF_ADDR_LOW_S0 0x3a19
> +#define VPU_MAFBC_OUTPUT_BUF_ADDR_HIGH_S0 0x3a1a
> +#define VPU_MAFBC_OUTPUT_BUF_STRIDE_S0 0x3a1b
> +#define VPU_MAFBC_PREFETCH_CFG_S0 0x3a1c
> +
> +#define VPU_MAFBC_HEADER_BUF_ADDR_LOW_S1 0x3a30
> +#define VPU_MAFBC_HEADER_BUF_ADDR_HIGH_S1 0x3a31
> +#define VPU_MAFBC_FORMAT_SPECIFIER_S1 0x3a32
> +#define VPU_MAFBC_BUFFER_WIDTH_S1 0x3a33
> +#define VPU_MAFBC_BUFFER_HEIGHT_S1 0x3a34
> +#define VPU_MAFBC_BOUNDING_BOX_X_START_S1 0x3a35
> +#define VPU_MAFBC_BOUNDING_BOX_X_END_S1 0x3a36
> +#define VPU_MAFBC_BOUNDING_BOX_Y_START_S1 0x3a37
> +#define VPU_MAFBC_BOUNDING_BOX_Y_END_S1 0x3a38
> +#define VPU_MAFBC_OUTPUT_BUF_ADDR_LOW_S1 0x3a39
> +#define VPU_MAFBC_OUTPUT_BUF_ADDR_HIGH_S1 0x3a3a
> +#define VPU_MAFBC_OUTPUT_BUF_STRIDE_S1 0x3a3b
> +#define VPU_MAFBC_PREFETCH_CFG_S1 0x3a3c
> +
> +#define VPU_MAFBC_HEADER_BUF_ADDR_LOW_S2 0x3a50
> +#define VPU_MAFBC_HEADER_BUF_ADDR_HIGH_S2 0x3a51
> +#define VPU_MAFBC_FORMAT_SPECIFIER_S2 0x3a52
> +#define VPU_MAFBC_BUFFER_WIDTH_S2 0x3a53
> +#define VPU_MAFBC_BUFFER_HEIGHT_S2 0x3a54
> +#define VPU_MAFBC_BOUNDING_BOX_X_START_S2 0x3a55
> +#define VPU_MAFBC_BOUNDING_BOX_X_END_S2 0x3a56
> +#define VPU_MAFBC_BOUNDING_BOX_Y_START_S2 0x3a57
> +#define VPU_MAFBC_BOUNDING_BOX_Y_END_S2 0x3a58
> +#define VPU_MAFBC_OUTPUT_BUF_ADDR_LOW_S2 0x3a59
> +#define VPU_MAFBC_OUTPUT_BUF_ADDR_HIGH_S2 0x3a5a
> +#define VPU_MAFBC_OUTPUT_BUF_STRIDE_S2 0x3a5b
> +#define VPU_MAFBC_PREFETCH_CFG_S2 0x3a5c
> +
> +#define VPU_MAFBC_HEADER_BUF_ADDR_LOW_S3 0x3a70
> +#define VPU_MAFBC_HEADER_BUF_ADDR_HIGH_S3 0x3a71
> +#define VPU_MAFBC_FORMAT_SPECIFIER_S3 0x3a72
> +#define VPU_MAFBC_BUFFER_WIDTH_S3 0x3a73
> +#define VPU_MAFBC_BUFFER_HEIGHT_S3 0x3a74
> +#define VPU_MAFBC_BOUNDING_BOX_X_START_S3 0x3a75
> +#define VPU_MAFBC_BOUNDING_BOX_X_END_S3 0x3a76
> +#define VPU_MAFBC_BOUNDING_BOX_Y_START_S3 0x3a77
> +#define VPU_MAFBC_BOUNDING_BOX_Y_END_S3 0x3a78
> +#define VPU_MAFBC_OUTPUT_BUF_ADDR_LOW_S3 0x3a79
> +#define VPU_MAFBC_OUTPUT_BUF_ADDR_HIGH_S3 0x3a7a
> +#define VPU_MAFBC_OUTPUT_BUF_STRIDE_S3 0x3a7b
> +#define VPU_MAFBC_PREFETCH_CFG_S3 0x3a7c
> +
> +#define DOLBY_PATH_CTRL 0x1a0c
> +#define		DOLBY_BYPASS_EN(val)            (val & 0xf)
> +#define OSD_PATH_MISC_CTRL 0x1a0e
> +#define MALI_AFBCD_TOP_CTRL 0x1a0f
> +
> +#define VIU_OSD_BLEND_CTRL 0x39b0
> +#define		VIU_OSD_BLEND_REORDER(dest, src)      ((src) << (dest * 4))
> +#define		VIU_OSD_BLEND_DIN_EN(bits)            ((bits & 0xf) << 20)
> +#define		VIU_OSD_BLEND1_DIN3_BYPASS_TO_DOUT1   BIT(24)
> +#define		VIU_OSD_BLEND1_DOUT_BYPASS_TO_BLEND2  BIT(25)
> +#define		VIU_OSD_BLEND_DIN0_BYPASS_TO_DOUT0    BIT(26)
> +#define		VIU_OSD_BLEND_BLEN2_PREMULT_EN(input) ((input & 0x3) << 27)
> +#define		VIU_OSD_BLEND_HOLD_LINES(lines)       ((u32)(lines & 0x7) << 29)
> +#define VIU_OSD_BLEND_CTRL1 0x39c0
> +#define VIU_OSD_BLEND_DIN0_SCOPE_H 0x39b1
> +#define VIU_OSD_BLEND_DIN0_SCOPE_V 0x39b2
> +#define VIU_OSD_BLEND_DIN1_SCOPE_H 0x39b3
> +#define VIU_OSD_BLEND_DIN1_SCOPE_V 0x39b4
> +#define VIU_OSD_BLEND_DIN2_SCOPE_H 0x39b5
> +#define VIU_OSD_BLEND_DIN2_SCOPE_V 0x39b6
> +#define VIU_OSD_BLEND_DIN3_SCOPE_H 0x39b7
> +#define VIU_OSD_BLEND_DIN3_SCOPE_V 0x39b8
> +#define VIU_OSD_BLEND_DUMMY_DATA0 0x39b9
> +#define VIU_OSD_BLEND_DUMMY_ALPHA 0x39ba
> +#define VIU_OSD_BLEND_BLEND0_SIZE 0x39bb
> +#define VIU_OSD_BLEND_BLEND1_SIZE 0x39bc
> +#define VIU_OSD_BLEND_RO_CURRENT_XY 0x39bf
> +
> +#define VPP_OUT_H_V_SIZE 0x1da5
> +
> +#define VPP_VD2_HDR_IN_SIZE 0x1df0
> +#define VPP_OSD1_IN_SIZE 0x1df1
> +#define VPP_GCLK_CTRL2 0x1df2
> +#define VD2_PPS_DUMMY_DATA 0x1df4
> +#define VPP_OSD1_BLD_H_SCOPE 0x1df5
> +#define VPP_OSD1_BLD_V_SCOPE 0x1df6
> +#define VPP_OSD2_BLD_H_SCOPE 0x1df7
> +#define VPP_OSD2_BLD_V_SCOPE 0x1df8
> +#define VPP_WRBAK_CTRL 0x1df9
> +#define VPP_SLEEP_CTRL 0x1dfa
> +#define VD1_BLEND_SRC_CTRL 0x1dfb
> +#define VD2_BLEND_SRC_CTRL 0x1dfc
> +#define		VD_BLEND_PREBLD_SRC_VD1         (1 << 0)
> +#define		VD_BLEND_PREBLD_SRC_VD2         (2 << 0)
> +#define		VD_BLEND_PREBLD_SRC_OSD1        (3 << 0)
> +#define		VD_BLEND_PREBLD_SRC_OSD2        (4 << 0)
> +#define		VD_BLEND_PREBLD_PREMULT_EN      BIT(4)
> +#define		VD_BLEND_POSTBLD_SRC_VD1        (1 << 8)
> +#define		VD_BLEND_POSTBLD_SRC_VD2        (2 << 8)
> +#define		VD_BLEND_POSTBLD_SRC_OSD1       (3 << 8)
> +#define		VD_BLEND_POSTBLD_SRC_OSD2       (4 << 8)
> +#define		VD_BLEND_POSTBLD_PREMULT_EN     BIT(16)
> +#define OSD1_BLEND_SRC_CTRL 0x1dfd
> +#define OSD2_BLEND_SRC_CTRL 0x1dfe
> +#define		OSD_BLEND_POSTBLD_SRC_VD1       (1 << 8)
> +#define		OSD_BLEND_POSTBLD_SRC_VD2       (2 << 8)
> +#define		OSD_BLEND_POSTBLD_SRC_OSD1      (3 << 8)
> +#define		OSD_BLEND_POSTBLD_SRC_OSD2      (4 << 8)
> +#define		OSD_BLEND_PATH_SEL_ENABLE       BIT(20)
> +
> +#define VPP_POST_BLEND_BLEND_DUMMY_DATA 0x3968
> +#define VPP_POST_BLEND_DUMMY_ALPHA 0x3969
> +#define VPP_RDARB_MODE 0x3978
> +#define VPP_RDARB_REQEN_SLV 0x3979
> +
>  #endif /* __MESON_REGISTERS_H */
> diff --git a/drivers/video/meson/meson_vclk.c b/drivers/video/meson/meson_vclk.c
> index 693e0ebe39..0f628e920b 100644
> --- a/drivers/video/meson/meson_vclk.c
> +++ b/drivers/video/meson/meson_vclk.c
> @@ -68,14 +68,20 @@ enum {
>  #define CTS_HDMI_SYS_EN		BIT(8)
>  
>  #define HHI_HDMI_PLL_CNTL	0x320 /* 0xc8 offset in data sheet */
> +#define HHI_HDMI_PLL_CNTL_EN	BIT(30)
>  #define HHI_HDMI_PLL_CNTL2	0x324 /* 0xc9 offset in data sheet */
>  #define HHI_HDMI_PLL_CNTL3	0x328 /* 0xca offset in data sheet */
>  #define HHI_HDMI_PLL_CNTL4	0x32C /* 0xcb offset in data sheet */
>  #define HHI_HDMI_PLL_CNTL5	0x330 /* 0xcc offset in data sheet */
>  #define HHI_HDMI_PLL_CNTL6	0x334 /* 0xcd offset in data sheet */
> +#define HHI_HDMI_PLL_CNTL7	0x338 /* 0xce offset in data sheet */
>  
>  #define HDMI_PLL_RESET		BIT(28)
> +#define HDMI_PLL_RESET_G12A	BIT(29)
>  #define HDMI_PLL_LOCK		BIT(31)
> +#define HDMI_PLL_LOCK_G12A	(3 << 30)
> +
> +#define FREQ_1000_1001(_freq)	DIV_ROUND_CLOSEST(_freq * 1000, 1001)
>  
>  /* VID PLL Dividers */
>  enum {
> @@ -206,8 +212,6 @@ static void meson_venci_cvbs_clock_config(struct meson_vpu_priv *priv)
>  {
>  	unsigned int val;
>  
> -	debug("%s:%d\n", __func__, __LINE__);
> -
>  	/* Setup PLL to output 1.485GHz */
>  	if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXBB)) {
>  		hhi_write(HHI_HDMI_PLL_CNTL, 0x5800023d);
> @@ -217,6 +221,10 @@ static void meson_venci_cvbs_clock_config(struct meson_vpu_priv *priv)
>  		hhi_write(HHI_HDMI_PLL_CNTL5, 0x71486980);
>  		hhi_write(HHI_HDMI_PLL_CNTL6, 0x00000e55);
>  		hhi_write(HHI_HDMI_PLL_CNTL, 0x4800023d);
> +
> +		/* Poll for lock bit */
> +		readl_poll_timeout(priv->hhi_base + HHI_HDMI_PLL_CNTL, val,
> +				   (val & HDMI_PLL_LOCK), 10);
>  	} else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM) ||
>  		   meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL)) {
>  		hhi_write(HHI_HDMI_PLL_CNTL, 0x4000027b);
> @@ -231,13 +239,26 @@ static void meson_venci_cvbs_clock_config(struct meson_vpu_priv *priv)
>  				HDMI_PLL_RESET, HDMI_PLL_RESET);
>  		hhi_update_bits(HHI_HDMI_PLL_CNTL,
>  				HDMI_PLL_RESET, 0);
> -	}
>  
> -	debug("%s:%d\n", __func__, __LINE__);
> +		/* Poll for lock bit */
> +		readl_poll_timeout(priv->hhi_base + HHI_HDMI_PLL_CNTL, val,
> +				   (val & HDMI_PLL_LOCK), 10);
> +	} else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
> +		hhi_write(HHI_HDMI_PLL_CNTL, 0x1a0504f7);
> +		hhi_write(HHI_HDMI_PLL_CNTL2, 0x00010000);
> +		hhi_write(HHI_HDMI_PLL_CNTL3, 0x00000000);
> +		hhi_write(HHI_HDMI_PLL_CNTL4, 0x6a28dc00);
> +		hhi_write(HHI_HDMI_PLL_CNTL5, 0x65771290);
> +		hhi_write(HHI_HDMI_PLL_CNTL6, 0x39272000);
> +		hhi_write(HHI_HDMI_PLL_CNTL7, 0x56540000);
> +		hhi_write(HHI_HDMI_PLL_CNTL, 0x3a0504f7);
> +		hhi_write(HHI_HDMI_PLL_CNTL, 0x1a0504f7);
>  
> -	/* Poll for lock bit */
> -	readl_poll_timeout(priv->hhi_base + HHI_HDMI_PLL_CNTL, val,
> -			   (val & HDMI_PLL_LOCK), 10);
> +		/* Poll for lock bit */
> +		readl_poll_timeout(priv->hhi_base + HHI_HDMI_PLL_CNTL, val,
> +			((val & HDMI_PLL_LOCK_G12A) == HDMI_PLL_LOCK_G12A),
> +			10);
> +	}
>  
>  	/* Disable VCLK2 */
>  	hhi_update_bits(HHI_VIID_CLK_CNTL, VCLK2_EN, 0);
> @@ -250,8 +271,13 @@ static void meson_venci_cvbs_clock_config(struct meson_vpu_priv *priv)
>  			VCLK2_DIV_MASK, (55 - 1));
>  
>  	/* select vid_pll for vclk2 */
> -	hhi_update_bits(HHI_VIID_CLK_CNTL,
> -			VCLK2_SEL_MASK, (4 << VCLK2_SEL_SHIFT));
> +	if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
> +		hhi_update_bits(HHI_VIID_CLK_CNTL,
> +				VCLK2_SEL_MASK, (0 << VCLK2_SEL_SHIFT));
> +	else
> +		hhi_update_bits(HHI_VIID_CLK_CNTL,
> +				VCLK2_SEL_MASK, (4 << VCLK2_SEL_SHIFT));
> +
>  	/* enable vclk2 gate */
>  	hhi_update_bits(HHI_VIID_CLK_CNTL, VCLK2_EN, VCLK2_EN);
>  
> @@ -282,14 +308,12 @@ static void meson_venci_cvbs_clock_config(struct meson_vpu_priv *priv)
>  	/* enable vdac_clk */
>  	hhi_update_bits(HHI_VID_CLK_CNTL2,
>  			CTS_VDAC_EN, CTS_VDAC_EN);
> -
> -	debug("%s:%d\n", __func__, __LINE__);
>  }
>  
>  enum {
>  /* PLL	O1 O2 O3 VP DV     EN TX */
>  /* 4320 /4 /4 /1 /5 /1  => /2 /2 */
> -	MESON_VCLK_HDMI_ENCI_54000 = 1,
> +	MESON_VCLK_HDMI_ENCI_54000 = 0,
>  /* 4320 /4 /4 /1 /5 /1  => /1 /2 */
>  	MESON_VCLK_HDMI_DDR_54000,
>  /* 2970 /4 /1 /1 /5 /1  => /1 /2 */
> @@ -305,6 +329,7 @@ enum {
>  };
>  
>  struct meson_vclk_params {
> +	unsigned int pixel_freq;
>  	unsigned int pll_base_freq;
>  	unsigned int pll_od1;
>  	unsigned int pll_od2;
> @@ -313,6 +338,7 @@ struct meson_vclk_params {
>  	unsigned int vclk_div;
>  } params[] = {
>  	[MESON_VCLK_HDMI_ENCI_54000] = {
> +		.pixel_freq = 54000,
>  		.pll_base_freq = 4320000,
>  		.pll_od1 = 4,
>  		.pll_od2 = 4,
> @@ -321,6 +347,7 @@ struct meson_vclk_params {
>  		.vclk_div = 1,
>  	},
>  	[MESON_VCLK_HDMI_DDR_54000] = {
> +		.pixel_freq = 54000,
>  		.pll_base_freq = 4320000,
>  		.pll_od1 = 4,
>  		.pll_od2 = 4,
> @@ -329,6 +356,7 @@ struct meson_vclk_params {
>  		.vclk_div = 1,
>  	},
>  	[MESON_VCLK_HDMI_DDR_148500] = {
> +		.pixel_freq = 148500,
>  		.pll_base_freq = 2970000,
>  		.pll_od1 = 4,
>  		.pll_od2 = 1,
> @@ -337,6 +365,7 @@ struct meson_vclk_params {
>  		.vclk_div = 1,
>  	},
>  	[MESON_VCLK_HDMI_74250] = {
> +		.pixel_freq = 74250,
>  		.pll_base_freq = 2970000,
>  		.pll_od1 = 2,
>  		.pll_od2 = 2,
> @@ -345,6 +374,7 @@ struct meson_vclk_params {
>  		.vclk_div = 1,
>  	},
>  	[MESON_VCLK_HDMI_148500] = {
> +		.pixel_freq = 148500,
>  		.pll_base_freq = 2970000,
>  		.pll_od1 = 1,
>  		.pll_od2 = 2,
> @@ -353,14 +383,16 @@ struct meson_vclk_params {
>  		.vclk_div = 1,
>  	},
>  	[MESON_VCLK_HDMI_297000] = {
> -		.pll_base_freq = 2970000,
> -		.pll_od1 = 1,
> +		.pixel_freq = 297000,
> +		.pll_base_freq = 5940000,
> +		.pll_od1 = 2,
>  		.pll_od2 = 1,
>  		.pll_od3 = 1,
>  		.vid_pll_div = VID_PLL_DIV_5,
>  		.vclk_div = 2,
>  	},
>  	[MESON_VCLK_HDMI_594000] = {
> +		.pixel_freq = 594000,
>  		.pll_base_freq = 5940000,
>  		.pll_od1 = 1,
>  		.pll_od2 = 1,
> @@ -368,6 +400,7 @@ struct meson_vclk_params {
>  		.vid_pll_div = VID_PLL_DIV_5,
>  		.vclk_div = 1,
>  	},
> +	{ /* sentinel */ },
>  };
>  
>  static inline unsigned int pll_od_to_reg(unsigned int od)
> @@ -431,6 +464,50 @@ void meson_hdmi_pll_set_params(struct meson_vpu_priv *priv, unsigned int m,
>  		/* Poll for lock bit */
>  		readl_poll_timeout(priv->hhi_base + HHI_HDMI_PLL_CNTL, val,
>  				   (val & HDMI_PLL_LOCK), 10);
> +	} else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
> +		hhi_write(HHI_HDMI_PLL_CNTL, 0x0b3a0400 | m);
> +
> +		/* Enable and reset */
> +		hhi_update_bits(HHI_HDMI_PLL_CNTL, 0x3 << 28, 0x3 << 28);
> +
> +		hhi_write(HHI_HDMI_PLL_CNTL2, frac);
> +		hhi_write(HHI_HDMI_PLL_CNTL3, 0x00000000);
> +
> +		/* G12A HDMI PLL Needs specific parameters for 5.4GHz */
> +		if (m >= 0xf7) {
> +			if (frac < 0x10000) {
> +				hhi_write(HHI_HDMI_PLL_CNTL4, 0x6a685c00);
> +				hhi_write(HHI_HDMI_PLL_CNTL5, 0x11551293);
> +			} else {
> +				hhi_write(HHI_HDMI_PLL_CNTL4, 0xea68dc00);
> +				hhi_write(HHI_HDMI_PLL_CNTL5, 0x65771290);
> +			}
> +			hhi_write(HHI_HDMI_PLL_CNTL6, 0x39272000);
> +			hhi_write(HHI_HDMI_PLL_CNTL7, 0x55540000);
> +		} else {
> +			hhi_write(HHI_HDMI_PLL_CNTL4, 0x0a691c00);
> +			hhi_write(HHI_HDMI_PLL_CNTL5, 0x33771290);
> +			hhi_write(HHI_HDMI_PLL_CNTL6, 0x39270000);
> +			hhi_write(HHI_HDMI_PLL_CNTL7, 0x50540000);
> +		}
> +
> +		do {
> +			/* Reset PLL */
> +			hhi_update_bits(HHI_HDMI_PLL_CNTL,
> +					HDMI_PLL_RESET_G12A,
> +					HDMI_PLL_RESET_G12A);
> +
> +			/* UN-Reset PLL */
> +			hhi_update_bits(HHI_HDMI_PLL_CNTL,
> +					HDMI_PLL_RESET_G12A, 0);
> +
> +			/* Poll for lock bits */
> +			if (!readl_poll_timeout(
> +					priv->hhi_base + HHI_HDMI_PLL_CNTL, val,
> +					((val & HDMI_PLL_LOCK_G12A)
> +						== HDMI_PLL_LOCK_G12A), 100))
> +				break;
> +		} while (1);
>  	}
>  
>  	if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXBB))
> @@ -440,6 +517,9 @@ void meson_hdmi_pll_set_params(struct meson_vpu_priv *priv, unsigned int m,
>  		 meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL))
>  		hhi_update_bits(HHI_HDMI_PLL_CNTL3,
>  				3 << 21, pll_od_to_reg(od1) << 21);
> +	else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
> +		hhi_update_bits(HHI_HDMI_PLL_CNTL,
> +				3 << 16, pll_od_to_reg(od1) << 16);
>  
>  	if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXBB))
>  		hhi_update_bits(HHI_HDMI_PLL_CNTL2,
> @@ -448,6 +528,9 @@ void meson_hdmi_pll_set_params(struct meson_vpu_priv *priv, unsigned int m,
>  		 meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL))
>  		hhi_update_bits(HHI_HDMI_PLL_CNTL3,
>  				3 << 23, pll_od_to_reg(od2) << 23);
> +	else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
> +		hhi_update_bits(HHI_HDMI_PLL_CNTL,
> +				3 << 18, pll_od_to_reg(od2) << 18);
>  
>  	if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXBB))
>  		hhi_update_bits(HHI_HDMI_PLL_CNTL2,
> @@ -456,6 +539,9 @@ void meson_hdmi_pll_set_params(struct meson_vpu_priv *priv, unsigned int m,
>  		 meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL))
>  		hhi_update_bits(HHI_HDMI_PLL_CNTL3,
>  				3 << 19, pll_od_to_reg(od3) << 19);
> +	else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
> +		hhi_update_bits(HHI_HDMI_PLL_CNTL,
> +				3 << 20, pll_od_to_reg(od3) << 20);
>  }
>  
>  #define XTAL_FREQ 24000
> @@ -472,6 +558,7 @@ static unsigned int meson_hdmi_pll_get_m(struct meson_vpu_priv *priv,
>  
>  #define HDMI_FRAC_MAX_GXBB	4096
>  #define HDMI_FRAC_MAX_GXL	1024
> +#define HDMI_FRAC_MAX_G12A	131072
>  
>  static unsigned int meson_hdmi_pll_get_frac(struct meson_vpu_priv *priv,
>  					    unsigned int m,
> @@ -488,6 +575,9 @@ static unsigned int meson_hdmi_pll_get_frac(struct meson_vpu_priv *priv,
>  		parent_freq *= 2;
>  	}
>  
> +	if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
> +		frac_max = HDMI_FRAC_MAX_G12A;
> +
>  	/* We can have a perfect match !*/
>  	if (pll_freq / m == parent_freq &&
>  	    pll_freq % m == 0)
> @@ -519,6 +609,12 @@ static bool meson_hdmi_pll_validate_params(struct meson_vpu_priv *priv,
>  			return false;
>  		if (frac >= HDMI_FRAC_MAX_GXL)
>  			return false;
> +	} else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
> +		/* Empiric supported min/max dividers */
> +		if (m < 106 || m > 247)
> +			return false;
> +		if (frac >= HDMI_FRAC_MAX_G12A)
> +			return false;
>  	}
>  
>  	return true;
> @@ -595,8 +691,10 @@ meson_vclk_set(struct meson_vpu_priv *priv, unsigned int pll_base_freq,
>  	       unsigned int od1, unsigned int od2, unsigned int od3,
>  	       unsigned int vid_pll_div, unsigned int vclk_div,
>  	       unsigned int hdmi_tx_div, unsigned int venc_div,
> -	       bool hdmi_use_enci)
> +	       bool hdmi_use_enci, bool vic_alternate_clock)
>  {
> +	unsigned int m = 0, frac = 0;
> +
>  	/* Set HDMI-TX sys clock */
>  	hhi_update_bits(HHI_HDMI_CLK_CNTL,
>  			CTS_HDMI_SYS_SEL_MASK, 0);
> @@ -611,34 +709,55 @@ meson_vclk_set(struct meson_vpu_priv *priv, unsigned int pll_base_freq,
>  	} else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXBB)) {
>  		switch (pll_base_freq) {
>  		case 2970000:
> -			meson_hdmi_pll_set_params(priv, 0x3d, 0xe00,
> -						  od1, od2, od3);
> +			m = 0x3d;
> +			frac = vic_alternate_clock ? 0xd02 : 0xe00;
>  			break;
>  		case 4320000:
> -			meson_hdmi_pll_set_params(priv, 0x5a, 0,
> -						  od1, od2, od3);
> +			m = vic_alternate_clock ? 0x59 : 0x5a;
> +			frac = vic_alternate_clock ? 0xe8f : 0;
>  			break;
>  		case 5940000:
> -			meson_hdmi_pll_set_params(priv, 0x7b, 0xc00,
> -						  od1, od2, od3);
> +			m = 0x7b;
> +			frac = vic_alternate_clock ? 0xa05 : 0xc00;
>  			break;
>  		}
> +
> +		meson_hdmi_pll_set_params(priv, m, frac, od1, od2, od3);
>  	} else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM) ||
>  		   meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL)) {
>  		switch (pll_base_freq) {
>  		case 2970000:
> -			meson_hdmi_pll_set_params(priv, 0x7b, 0x300,
> -						  od1, od2, od3);
> +			m = 0x7b;
> +			frac = vic_alternate_clock ? 0x281 : 0x300;
> +			break;
> +		case 4320000:
> +			m = vic_alternate_clock ? 0xb3 : 0xb4;
> +			frac = vic_alternate_clock ? 0x347 : 0;
> +			break;
> +		case 5940000:
> +			m = 0xf7;
> +			frac = vic_alternate_clock ? 0x102 : 0x200;
> +			break;
> +		}
> +
> +		meson_hdmi_pll_set_params(priv, m, frac, od1, od2, od3);
> +	} else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
> +		switch (pll_base_freq) {
> +		case 2970000:
> +			m = 0x7b;
> +			frac = vic_alternate_clock ? 0x140b4 : 0x18000;
>  			break;
>  		case 4320000:
> -			meson_hdmi_pll_set_params(priv, 0xb4, 0,
> -						  od1, od2, od3);
> +			m = vic_alternate_clock ? 0xb3 : 0xb4;
> +			frac = vic_alternate_clock ? 0x1a3ee : 0;
>  			break;
>  		case 5940000:
> -			meson_hdmi_pll_set_params(priv, 0xf7, 0x200,
> -						  od1, od2, od3);
> +			m = 0xf7;
> +			frac = vic_alternate_clock ? 0x8148 : 0x10000;
>  			break;
>  		}
> +
> +		meson_hdmi_pll_set_params(priv, m, frac, od1, od2, od3);
>  	}
>  
>  	/* Setup vid_pll divider */
> @@ -803,6 +922,7 @@ static void meson_vclk_setup(struct meson_vpu_priv *priv, unsigned int target,
>  			     unsigned int vclk_freq, unsigned int venc_freq,
>  			     unsigned int dac_freq, bool hdmi_use_enci)
>  {
> +	bool vic_alternate_clock = false;
>  	unsigned int freq;
>  	unsigned int hdmi_tx_div;
>  	unsigned int venc_div;
> @@ -820,8 +940,7 @@ static void meson_vclk_setup(struct meson_vpu_priv *priv, unsigned int target,
>  		 * - encp encoder
>  		 */
>  		meson_vclk_set(priv, vclk_freq * 10, 0, 0, 0,
> -			       VID_PLL_DIV_5, 2, 1, 1, false);
> -
> +			       VID_PLL_DIV_5, 2, 1, 1, false, false);
>  		return;
>  	}
>  
> @@ -841,31 +960,35 @@ static void meson_vclk_setup(struct meson_vpu_priv *priv, unsigned int target,
>  		return;
>  	}
>  
> -	switch (vclk_freq) {
> -	case 54000:
> -		if (hdmi_use_enci)
> -			freq = MESON_VCLK_HDMI_ENCI_54000;
> -		else
> -			freq = MESON_VCLK_HDMI_DDR_54000;
> -		break;
> -	case 74250:
> -		freq = MESON_VCLK_HDMI_74250;
> -		break;
> -	case 148500:
> -		if (dac_freq != 148500)
> -			freq = MESON_VCLK_HDMI_DDR_148500;
> -		else
> -			freq = MESON_VCLK_HDMI_148500;
> -		break;
> -	case 297000:
> -		freq = MESON_VCLK_HDMI_297000;
> -		break;
> -	case 594000:
> -		freq = MESON_VCLK_HDMI_594000;
> -		break;
> -	default:
> -		printf("Fatal Error, invalid HDMI vclk freq %d\n",
> -		       vclk_freq);
> +	for (freq = 0 ; params[freq].pixel_freq ; ++freq) {
> +		if (vclk_freq == params[freq].pixel_freq ||
> +		    vclk_freq == FREQ_1000_1001(params[freq].pixel_freq)) {
> +			if (vclk_freq != params[freq].pixel_freq)
> +				vic_alternate_clock = true;
> +			else
> +				vic_alternate_clock = false;
> +
> +			if (freq == MESON_VCLK_HDMI_ENCI_54000 &&
> +			    !hdmi_use_enci)
> +				continue;
> +
> +			if (freq == MESON_VCLK_HDMI_DDR_54000 &&
> +			    hdmi_use_enci)
> +				continue;
> +
> +			if (freq == MESON_VCLK_HDMI_DDR_148500 &&
> +			    dac_freq == vclk_freq)
> +				continue;
> +
> +			if (freq == MESON_VCLK_HDMI_148500 &&
> +			    dac_freq != vclk_freq)
> +				continue;
> +			break;
> +		}
> +	}
> +
> +	if (!params[freq].pixel_freq) {
> +		pr_err("Fatal Error, invalid HDMI vclk freq %d\n", vclk_freq);
>  		return;
>  	}
>  
> @@ -873,7 +996,7 @@ static void meson_vclk_setup(struct meson_vpu_priv *priv, unsigned int target,
>  		       params[freq].pll_od1, params[freq].pll_od2,
>  		       params[freq].pll_od3, params[freq].vid_pll_div,
>  		       params[freq].vclk_div, hdmi_tx_div, venc_div,
> -		       hdmi_use_enci);
> +		       hdmi_use_enci, vic_alternate_clock);
>  }
>  
>  void meson_vpu_setup_vclk(struct udevice *dev,
> diff --git a/drivers/video/meson/meson_venc.c b/drivers/video/meson/meson_venc.c
> index d137dde8e2..5da4b3f096 100644
> --- a/drivers/video/meson/meson_venc.c
> +++ b/drivers/video/meson/meson_venc.c
> @@ -23,7 +23,9 @@ enum meson_venc_source {
>  };
>  
>  #define HHI_VDAC_CNTL0		0x2F4 /* 0xbd offset in data sheet */
> +#define HHI_VDAC_CNTL0_G12A	0x2EC /* 0xbb offset in data sheet */
>  #define HHI_VDAC_CNTL1		0x2F8 /* 0xbe offset in data sheet */
> +#define HHI_VDAC_CNTL1_G12A	0x2F0 /* 0xbc offset in data sheet */
>  
>  struct meson_cvbs_enci_mode {
>  	unsigned int mode_tag;
> @@ -175,7 +177,7 @@ union meson_hdmi_venc_mode meson_hdmi_enci_mode_480i = {
>  		.hso_end = 129,
>  		.vso_even = 3,
>  		.vso_odd = 260,
> -		.macv_max_amp = 0x810b,
> +		.macv_max_amp = 0xb,
>  		.video_prog_mode = 0xf0,
>  		.video_mode = 0x8,
>  		.sch_adjust = 0x20,
> @@ -195,7 +197,7 @@ union meson_hdmi_venc_mode meson_hdmi_enci_mode_576i = {
>  		.hso_end = 129,
>  		.vso_even = 3,
>  		.vso_odd = 260,
> -		.macv_max_amp = 8107,
> +		.macv_max_amp = 0x7,
>  		.video_prog_mode = 0xff,
>  		.video_mode = 0x13,
>  		.sch_adjust = 0x28,
> @@ -774,12 +776,13 @@ static void meson_venc_hdmi_mode_set(struct meson_vpu_priv *priv,
>  	unsigned int eof_lines;
>  	unsigned int sof_lines;
>  	unsigned int vsync_lines;
> +	u32 reg;
>  
>  	/* Use VENCI for 480i and 576i and double HDMI pixels */
>  	if (mode->flags & DISPLAY_FLAGS_DOUBLECLK) {
> -		venc_hdmi_latency = 1;
>  		hdmi_repeat = true;
>  		use_enci = true;
> +		venc_hdmi_latency = 1;
>  	}
>  
>  	meson_venc_hdmi_get_dmt_vmode(mode, &vmode_dmt);
> @@ -850,8 +853,11 @@ static void meson_venc_hdmi_mode_set(struct meson_vpu_priv *priv,
>  		unsigned int lines_f1;
>  
>  		/* CVBS Filter settings */
> -		writel(0x12, priv->io_base + _REG(ENCI_CFILT_CTRL));
> -		writel(0x12, priv->io_base + _REG(ENCI_CFILT_CTRL2));
> +		writel(ENCI_CFILT_CMPT_SEL_HIGH | 0x10,
> +		       priv->io_base + _REG(ENCI_CFILT_CTRL));
> +		writel(ENCI_CFILT_CMPT_CR_DLY(2) |
> +		       ENCI_CFILT_CMPT_CB_DLY(1),
> +		       priv->io_base + _REG(ENCI_CFILT_CTRL2));
>  
>  		/* Digital Video Select : Interlace, clk27 clk, external */
>  		writel(0, priv->io_base + _REG(VENC_DVI_SETTING));
> @@ -873,7 +879,8 @@ static void meson_venc_hdmi_mode_set(struct meson_vpu_priv *priv,
>  		       priv->io_base + _REG(ENCI_SYNC_VSO_ODDLN));
>  
>  		/* Macrovision max amplitude change */
> -		writel(vmode->enci.macv_max_amp,
> +		writel(ENCI_MACV_MAX_AMP_ENABLE_CHANGE |
> +		       ENCI_MACV_MAX_AMP_VAL(vmode->enci.macv_max_amp),
>  		       priv->io_base + _REG(ENCI_MACV_MAX_AMP));
>  
>  		/* Video mode */
> @@ -882,7 +889,8 @@ static void meson_venc_hdmi_mode_set(struct meson_vpu_priv *priv,
>  		writel(vmode->enci.video_mode,
>  		       priv->io_base + _REG(ENCI_VIDEO_MODE));
>  
> -		/* Advanced Video Mode :
> +		/*
> +		 * Advanced Video Mode :
>  		 * Demux shifting 0x2
>  		 * Blank line end at line17/22
>  		 * High bandwidth Luma Filter
> @@ -890,7 +898,10 @@ static void meson_venc_hdmi_mode_set(struct meson_vpu_priv *priv,
>  		 * Bypass luma low pass filter
>  		 * No macrovision on CSYNC
>  		 */
> -		writel(0x26, priv->io_base + _REG(ENCI_VIDEO_MODE_ADV));
> +		writel(ENCI_VIDEO_MODE_ADV_DMXMD(2) |
> +		       ENCI_VIDEO_MODE_ADV_VBICTL_LINE_17_22 |
> +		       ENCI_VIDEO_MODE_ADV_YBW_HIGH,
> +		       priv->io_base + _REG(ENCI_VIDEO_MODE_ADV));
>  
>  		writel(vmode->enci.sch_adjust,
>  		       priv->io_base + _REG(ENCI_VIDEO_SCH));
> @@ -905,8 +916,17 @@ static void meson_venc_hdmi_mode_set(struct meson_vpu_priv *priv,
>  		/* UNreset Interlaced TV Encoder */
>  		writel(0, priv->io_base + _REG(ENCI_DBG_PX_RST));
>  
> -		/* Enable Vfifo2vd, Y_Cb_Y_Cr select */
> -		writel(0x4e01, priv->io_base + _REG(ENCI_VFIFO2VD_CTL));
> +		/*
> +		 * Enable Vfifo2vd and set Y_Cb_Y_Cr:
> +		 * Corresponding value:
> +		 * Y  => 00 or 10
> +		 * Cb => 01
> +		 * Cr => 11
> +		 * Ex: 0x4e => 01001110 would mean Cb/Y/Cr/Y
> +		 */
> +		writel(ENCI_VFIFO2VD_CTL_ENABLE |
> +		       ENCI_VFIFO2VD_CTL_VD_SEL(0x4e),
> +		       priv->io_base + _REG(ENCI_VFIFO2VD_CTL));
>  
>  		/* Timings */
>  		writel(vmode->enci.pixel_start,
> @@ -928,7 +948,8 @@ static void meson_venc_hdmi_mode_set(struct meson_vpu_priv *priv,
>  		meson_vpp_setup_mux(priv, MESON_VIU_VPP_MUX_ENCI);
>  
>  		/* Interlace video enable */
> -		writel(1, priv->io_base + _REG(ENCI_VIDEO_EN));
> +		writel(ENCI_VIDEO_EN_ENABLE,
> +		       priv->io_base + _REG(ENCI_VIDEO_EN));
>  
>  		lines_f0 = mode->vback_porch.typ + mode->vactive.typ +
>  			   mode->vback_porch.typ + mode->vsync_len.typ;
> @@ -1177,7 +1198,8 @@ static void meson_venc_hdmi_mode_set(struct meson_vpu_priv *priv,
>  		writel(1, priv->io_base + _REG(ENCP_VIDEO_EN));
>  
>  		/* Set DE signal's polarity is active high */
> -		writel_bits(BIT(14), BIT(14),
> +		writel_bits(ENCP_VIDEO_MODE_DE_V_HIGH,
> +			    ENCP_VIDEO_MODE_DE_V_HIGH,
>  			    priv->io_base + _REG(ENCP_VIDEO_MODE));
>  
>  		/* Program DE timing */
> @@ -1302,21 +1324,52 @@ static void meson_venc_hdmi_mode_set(struct meson_vpu_priv *priv,
>  		meson_vpp_setup_mux(priv, MESON_VIU_VPP_MUX_ENCP);
>  	}
>  
> -	writel((use_enci ? 1 : 2) |
> -		       (mode->flags & DISPLAY_FLAGS_HSYNC_HIGH ? 1 << 2 : 0) |
> -		       (mode->flags & DISPLAY_FLAGS_VSYNC_HIGH ? 1 << 3 : 0) |
> -		       4 << 5 |
> -		       (venc_repeat ? 1 << 8 : 0) |
> -		       (hdmi_repeat ? 1 << 12 : 0),
> -		       priv->io_base + _REG(VPU_HDMI_SETTING));
> +	/* Set VPU HDMI setting */
> +	/* Select ENCP or ENCI data to HDMI */
> +	if (use_enci)
> +		reg = VPU_HDMI_ENCI_DATA_TO_HDMI;
> +	else
> +		reg = VPU_HDMI_ENCP_DATA_TO_HDMI;
> +
> +	/* Invert polarity of HSYNC from VENC */
> +	if (mode->flags & DISPLAY_FLAGS_HSYNC_HIGH)
> +		reg |= VPU_HDMI_INV_HSYNC;
> +
> +	/* Invert polarity of VSYNC from VENC */
> +	if (mode->flags & DISPLAY_FLAGS_VSYNC_HIGH)
> +		reg |= VPU_HDMI_INV_VSYNC;
> +
> +	/* Output data format: CbYCr */
> +	reg |= VPU_HDMI_OUTPUT_CBYCR;
> +
> +	/*
> +	 * Write rate to the async FIFO between VENC and HDMI.
> +	 * One write every 2 wr_clk.
> +	 */
> +	if (venc_repeat)
> +		reg |= VPU_HDMI_WR_RATE(2);
> +
> +	/*
> +	 * Read rate to the async FIFO between VENC and HDMI.
> +	 * One read every 2 wr_clk.
> +	 */
> +	if (hdmi_repeat)
> +		reg |= VPU_HDMI_RD_RATE(2);
> +
> +	writel(reg, priv->io_base + _REG(VPU_HDMI_SETTING));
>  }
>  
>  static void meson_venci_cvbs_mode_set(struct meson_vpu_priv *priv,
>  				      struct meson_cvbs_enci_mode *mode)
>  {
> +	u32 reg;
> +
>  	/* CVBS Filter settings */
> -	writel(0x12, priv->io_base + _REG(ENCI_CFILT_CTRL));
> -	writel(0x12, priv->io_base + _REG(ENCI_CFILT_CTRL2));
> +	writel(ENCI_CFILT_CMPT_SEL_HIGH | 0x10,
> +	       priv->io_base + _REG(ENCI_CFILT_CTRL));
> +	writel(ENCI_CFILT_CMPT_CR_DLY(2) |
> +	       ENCI_CFILT_CMPT_CB_DLY(1),
> +	       priv->io_base + _REG(ENCI_CFILT_CTRL2));
>  
>  	/* Digital Video Select : Interlace, clk27 clk, external */
>  	writel(0, priv->io_base + _REG(VENC_DVI_SETTING));
> @@ -1338,7 +1391,8 @@ static void meson_venci_cvbs_mode_set(struct meson_vpu_priv *priv,
>  	       priv->io_base + _REG(ENCI_SYNC_VSO_ODDLN));
>  
>  	/* Macrovision max amplitude change */
> -	writel(0x8100 + mode->macv_max_amp,
> +	writel(ENCI_MACV_MAX_AMP_ENABLE_CHANGE |
> +	       ENCI_MACV_MAX_AMP_VAL(mode->macv_max_amp),
>  	       priv->io_base + _REG(ENCI_MACV_MAX_AMP));
>  
>  	/* Video mode */
> @@ -1347,7 +1401,8 @@ static void meson_venci_cvbs_mode_set(struct meson_vpu_priv *priv,
>  	writel(mode->video_mode,
>  	       priv->io_base + _REG(ENCI_VIDEO_MODE));
>  
> -	/* Advanced Video Mode :
> +	/*
> +	 * Advanced Video Mode :
>  	 * Demux shifting 0x2
>  	 * Blank line end at line17/22
>  	 * High bandwidth Luma Filter
> @@ -1355,7 +1410,10 @@ static void meson_venci_cvbs_mode_set(struct meson_vpu_priv *priv,
>  	 * Bypass luma low pass filter
>  	 * No macrovision on CSYNC
>  	 */
> -	writel(0x26, priv->io_base + _REG(ENCI_VIDEO_MODE_ADV));
> +	writel(ENCI_VIDEO_MODE_ADV_DMXMD(2) |
> +	       ENCI_VIDEO_MODE_ADV_VBICTL_LINE_17_22 |
> +	       ENCI_VIDEO_MODE_ADV_YBW_HIGH,
> +	       priv->io_base + _REG(ENCI_VIDEO_MODE_ADV));
>  
>  	writel(mode->sch_adjust, priv->io_base + _REG(ENCI_VIDEO_SCH));
>  
> @@ -1387,16 +1445,50 @@ static void meson_venci_cvbs_mode_set(struct meson_vpu_priv *priv,
>  	/* UNreset Interlaced TV Encoder */
>  	writel(0, priv->io_base + _REG(ENCI_DBG_PX_RST));
>  
> -	/* Enable Vfifo2vd, Y_Cb_Y_Cr select */
> -	writel(0x4e01, priv->io_base + _REG(ENCI_VFIFO2VD_CTL));
> +	/*
> +	 * Enable Vfifo2vd and set Y_Cb_Y_Cr:
> +	 * Corresponding value:
> +	 * Y  => 00 or 10
> +	 * Cb => 01
> +	 * Cr => 11
> +	 * Ex: 0x4e => 01001110 would mean Cb/Y/Cr/Y
> +	 */
> +	writel(ENCI_VFIFO2VD_CTL_ENABLE |
> +	       ENCI_VFIFO2VD_CTL_VD_SEL(0x4e),
> +	       priv->io_base + _REG(ENCI_VFIFO2VD_CTL));
>  
>  	/* Power UP Dacs */
>  	writel(0, priv->io_base + _REG(VENC_VDAC_SETTING));
>  
>  	/* Video Upsampling */
> -	writel(0x0061, priv->io_base + _REG(VENC_UPSAMPLE_CTRL0));
> -	writel(0x4061, priv->io_base + _REG(VENC_UPSAMPLE_CTRL1));
> -	writel(0x5061, priv->io_base + _REG(VENC_UPSAMPLE_CTRL2));
> +	/*
> +	 * CTRL0, CTRL1 and CTRL2:
> +	 * Filter0: input data sample every 2 cloks
> +	 * Filter1: filtering and upsample enable
> +	 */
> +	reg = VENC_UPSAMPLE_CTRL_F0_2_CLK_RATIO | VENC_UPSAMPLE_CTRL_F1_EN |
> +		VENC_UPSAMPLE_CTRL_F1_UPSAMPLE_EN;
> +
> +	/*
> +	 * Upsample CTRL0:
> +	 * Interlace High Bandwidth Luma
> +	 */
> +	writel(VENC_UPSAMPLE_CTRL_INTERLACE_HIGH_LUMA | reg,
> +	       priv->io_base + _REG(VENC_UPSAMPLE_CTRL0));
> +
> +	/*
> +	 * Upsample CTRL1:
> +	 * Interlace Pb
> +	 */
> +	writel(VENC_UPSAMPLE_CTRL_INTERLACE_PB | reg,
> +	       priv->io_base + _REG(VENC_UPSAMPLE_CTRL1));
> +
> +	/*
> +	 * Upsample CTRL2:
> +	 * Interlace R
> +	 */
> +	writel(VENC_UPSAMPLE_CTRL_INTERLACE_PR | reg,
> +	       priv->io_base + _REG(VENC_UPSAMPLE_CTRL2));
>  
>  	/* Select Interlace Y DACs */
>  	writel(0, priv->io_base + _REG(VENC_VDAC_DACSEL0));
> @@ -1410,14 +1502,16 @@ static void meson_venci_cvbs_mode_set(struct meson_vpu_priv *priv,
>  	meson_vpp_setup_mux(priv, MESON_VIU_VPP_MUX_ENCI);
>  
>  	/* Enable ENCI FIFO */
> -	writel(0x2000, priv->io_base + _REG(VENC_VDAC_FIFO_CTRL));
> +	writel(VENC_VDAC_FIFO_EN_ENCI_ENABLE,
> +	       priv->io_base + _REG(VENC_VDAC_FIFO_CTRL));
>  
>  	/* Select ENCI DACs 0, 1, 4, and 5 */
>  	writel(0x11, priv->io_base + _REG(ENCI_DACSEL_0));
>  	writel(0x11, priv->io_base + _REG(ENCI_DACSEL_1));
>  
>  	/* Interlace video enable */
> -	writel(1, priv->io_base + _REG(ENCI_VIDEO_EN));
> +	writel(ENCI_VIDEO_EN_ENABLE,
> +	       priv->io_base + _REG(ENCI_VIDEO_EN));
>  
>  	/* Configure Video Saturation / Contrast / Brightness / Hue */
>  	writel(mode->video_saturation,
> @@ -1430,7 +1524,8 @@ static void meson_venci_cvbs_mode_set(struct meson_vpu_priv *priv,
>  	       priv->io_base + _REG(ENCI_VIDEO_HUE));
>  
>  	/* Enable DAC0 Filter */
> -	writel(0x1, priv->io_base + _REG(VENC_VDAC_DAC0_FILT_CTRL0));
> +	writel(VENC_VDAC_DAC0_FILT_CTRL0_EN,
> +	       priv->io_base + _REG(VENC_VDAC_DAC0_FILT_CTRL0));
>  	writel(0xfc48, priv->io_base + _REG(VENC_VDAC_DAC0_FILT_CTRL1));
>  
>  	/* 0 in Macrovision register 0 */
> @@ -1441,15 +1536,21 @@ static void meson_venci_cvbs_mode_set(struct meson_vpu_priv *priv,
>  	       priv->io_base + _REG(ENCI_SYNC_ADJ));
>  
>  	/* enable VDAC */
> -	writel_bits(BIT(5), 0, priv->io_base + _REG(VENC_VDAC_DACSEL0));
> +	writel_bits(VENC_VDAC_SEL_ATV_DMD, 0,
> +		    priv->io_base + _REG(VENC_VDAC_DACSEL0));
>  
>  	if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXBB))
>  		hhi_write(HHI_VDAC_CNTL0, 1);
>  	else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL) ||
>  		 meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM))
>  		hhi_write(HHI_VDAC_CNTL0, 0xf0001);
> +	else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
> +		hhi_write(HHI_VDAC_CNTL0_G12A, 0x906001);
>  
> -	hhi_write(HHI_VDAC_CNTL1, 0);
> +	if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
> +		hhi_write(HHI_VDAC_CNTL1_G12A, 0);
> +	else
> +		hhi_write(HHI_VDAC_CNTL1, 0);
>  }
>  
>  void meson_vpu_setup_venc(struct udevice *dev,
> diff --git a/drivers/video/meson/meson_vpu.h b/drivers/video/meson/meson_vpu.h
> index ef5f10eae3..3412dac052 100644
> --- a/drivers/video/meson/meson_vpu.h
> +++ b/drivers/video/meson/meson_vpu.h
> @@ -14,6 +14,7 @@
>  #include <video.h>
>  #include <display.h>
>  #include <linux/io.h>
> +#include <linux/bitfield.h>
>  #include "meson_registers.h"
>  
>  enum {
> diff --git a/drivers/video/meson/meson_vpu_init.c b/drivers/video/meson/meson_vpu_init.c
> index 92228b5ceb..12f8c4194a 100644
> --- a/drivers/video/meson/meson_vpu_init.c
> +++ b/drivers/video/meson/meson_vpu_init.c
> @@ -12,7 +12,9 @@
>  
>  /* HHI Registers */
>  #define HHI_VDAC_CNTL0		0x2F4 /* 0xbd offset in data sheet */
> +#define HHI_VDAC_CNTL0_G12A	0x2EC /* 0xbd offset in data sheet */
>  #define HHI_VDAC_CNTL1		0x2F8 /* 0xbe offset in data sheet */
> +#define HHI_VDAC_CNTL1_G12A	0x2F0 /* 0xbe offset in data sheet */
>  #define HHI_HDMI_PHY_CNTL0	0x3a0 /* 0xe8 offset in data sheet */
>  
>  /* OSDx_CTRL_STAT2 */
> @@ -42,7 +44,7 @@ static void meson_vpp_write_scaling_filter_coefs(struct meson_vpu_priv *priv,
>  {
>  	int i;
>  
> -	writel(is_horizontal ? BIT(8) : 0,
> +	writel(is_horizontal ? VPP_SCALE_HORIZONTAL_COEF : 0,
>  	       priv->io_base + _REG(VPP_OSD_SCALE_COEF_IDX));
>  	for (i = 0; i < 33; i++)
>  		writel(coefs[i],
> @@ -67,7 +69,7 @@ static void meson_vpp_write_vd_scaling_filter_coefs(struct meson_vpu_priv *priv,
>  {
>  	int i;
>  
> -	writel(is_horizontal ? BIT(8) : 0,
> +	writel(is_horizontal ? VPP_SCALE_HORIZONTAL_COEF : 0,
>  	       priv->io_base + _REG(VPP_SCALE_COEF_IDX));
>  	for (i = 0; i < 33; i++)
>  		writel(coefs[i],
> @@ -112,6 +114,34 @@ static int eotf_bypass_coeff[EOTF_COEFF_SIZE] = {
>  	EOTF_COEFF_RIGHTSHIFT /* right shift */
>  };
>  
> +static void meson_viu_set_g12a_osd1_matrix(struct meson_vpu_priv *priv,
> +					   int *m, bool csc_on)
> +{
> +	/* VPP WRAP OSD1 matrix */
> +	writel(((m[0] & 0xfff) << 16) | (m[1] & 0xfff),
> +	       priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_PRE_OFFSET0_1));
> +	writel(m[2] & 0xfff,
> +	       priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_PRE_OFFSET2));
> +	writel(((m[3] & 0x1fff) << 16) | (m[4] & 0x1fff),
> +	       priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF00_01));
> +	writel(((m[5] & 0x1fff) << 16) | (m[6] & 0x1fff),
> +	       priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF02_10));
> +	writel(((m[7] & 0x1fff) << 16) | (m[8] & 0x1fff),
> +	       priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF11_12));
> +	writel(((m[9] & 0x1fff) << 16) | (m[10] & 0x1fff),
> +	       priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF20_21));
> +	writel((m[11] & 0x1fff) << 16,
> +	       priv->io_base +	_REG(VPP_WRAP_OSD1_MATRIX_COEF22));
> +
> +	writel(((m[18] & 0xfff) << 16) | (m[19] & 0xfff),
> +	       priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_OFFSET0_1));
> +	writel(m[20] & 0xfff,
> +	       priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_OFFSET2));
> +
> +	writel_bits(BIT(0), csc_on ? BIT(0) : 0,
> +		    priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_EN_CTRL));
> +}
> +
>  static void meson_viu_set_osd_matrix(struct meson_vpu_priv *priv,
>  				     enum viu_matrix_sel_e m_select,
>  				     int *m, bool csc_on)
> @@ -322,20 +352,47 @@ static void meson_viu_load_matrix(struct meson_vpu_priv *priv)
>  				 true);
>  }
>  
> +static inline uint32_t meson_viu_osd_burst_length_reg(uint32_t length)
> +{
> +	u32 val = (((length & 0x80) % 24) / 12);
> +
> +	return (((val & 0x3) << 10) | (((val & 0x4) >> 2) << 31));
> +}
> +
>  void meson_vpu_init(struct udevice *dev)
>  {
>  	struct meson_vpu_priv *priv = dev_get_priv(dev);
>  	u32 reg;
>  
> -	/* vpu initialization */
> -	writel(0x210000, priv->io_base + _REG(VPU_RDARB_MODE_L1C1));
> -	writel(0x10000, priv->io_base + _REG(VPU_RDARB_MODE_L1C2));
> -	writel(0x900000, priv->io_base + _REG(VPU_RDARB_MODE_L2C1));
> -	writel(0x20000, priv->io_base + _REG(VPU_WRARB_MODE_L2C1));
> +	/*
> +	 * Slave dc0 and dc5 connected to master port 1.
> +	 * By default other slaves are connected to master port 0.
> +	 */
> +	reg = VPU_RDARB_SLAVE_TO_MASTER_PORT(0, 1) |
> +		VPU_RDARB_SLAVE_TO_MASTER_PORT(5, 1);
> +	writel(reg, priv->io_base + _REG(VPU_RDARB_MODE_L1C1));
> +
> +	/* Slave dc0 connected to master port 1 */
> +	reg = VPU_RDARB_SLAVE_TO_MASTER_PORT(0, 1);
> +	writel(reg, priv->io_base + _REG(VPU_RDARB_MODE_L1C2));
> +
> +	/* Slave dc4 and dc7 connected to master port 1 */
> +	reg = VPU_RDARB_SLAVE_TO_MASTER_PORT(4, 1) |
> +		VPU_RDARB_SLAVE_TO_MASTER_PORT(7, 1);
> +	writel(reg, priv->io_base + _REG(VPU_RDARB_MODE_L2C1));
> +
> +	/* Slave dc1 connected to master port 1 */
> +	reg = VPU_RDARB_SLAVE_TO_MASTER_PORT(1, 1);
> +	writel(reg, priv->io_base + _REG(VPU_WRARB_MODE_L2C1));
>  
>  	/* Disable CVBS VDAC */
> -	hhi_write(HHI_VDAC_CNTL0, 0);
> -	hhi_write(HHI_VDAC_CNTL1, 8);
> +	if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
> +		hhi_write(HHI_VDAC_CNTL0_G12A, 0);
> +		hhi_write(HHI_VDAC_CNTL1_G12A, 8);
> +	} else {
> +		hhi_write(HHI_VDAC_CNTL0, 0);
> +		hhi_write(HHI_VDAC_CNTL1, 8);
> +	}
>  
>  	/* Power Down Dacs */
>  	writel(0xff, priv->io_base + _REG(VENC_VDAC_SETTING));
> @@ -344,7 +401,9 @@ void meson_vpu_init(struct udevice *dev)
>  	hhi_write(HHI_HDMI_PHY_CNTL0, 0);
>  
>  	/* Disable HDMI */
> -	writel_bits(0x3, 0, priv->io_base + _REG(VPU_HDMI_SETTING));
> +	writel_bits(VPU_HDMI_ENCI_DATA_TO_HDMI |
> +		    VPU_HDMI_ENCP_DATA_TO_HDMI, 0,
> +		    priv->io_base + _REG(VPU_HDMI_SETTING));
>  
>  	/* Disable all encoders */
>  	writel(0, priv->io_base + _REG(ENCI_VIDEO_EN));
> @@ -360,43 +419,58 @@ void meson_vpu_init(struct udevice *dev)
>  	} else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM)) {
>  		writel_bits(0xff << 16, 0xff << 16,
>  			    priv->io_base + _REG(VIU_MISC_CTRL1));
> -		writel(0x20000, priv->io_base + _REG(VPP_DOLBY_CTRL));
> +		writel(VPP_PPS_DUMMY_DATA_MODE,
> +		       priv->io_base + _REG(VPP_DOLBY_CTRL));
>  		writel(0x1020080,
>  		       priv->io_base + _REG(VPP_DUMMY_DATA1));
> -	}
> +	} else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
> +		writel(0xf, priv->io_base + _REG(DOLBY_PATH_CTRL));
>  
>  	/* Initialize vpu fifo control registers */
> -	writel(readl(priv->io_base + _REG(VPP_OFIFO_SIZE)) |
> -			0x77f, priv->io_base + _REG(VPP_OFIFO_SIZE));
> -	writel(0x08080808, priv->io_base + _REG(VPP_HOLD_LINES));
> -
> -	/* Turn off preblend */
> -	writel_bits(VPP_PREBLEND_ENABLE, 0,
> -		    priv->io_base + _REG(VPP_MISC));
> -
> -	/* Turn off POSTBLEND */
> -	writel_bits(VPP_POSTBLEND_ENABLE, 0,
> -		    priv->io_base + _REG(VPP_MISC));
> -
> -	/* Force all planes off */
> -	writel_bits(VPP_OSD1_POSTBLEND | VPP_OSD2_POSTBLEND |
> -		    VPP_VD1_POSTBLEND | VPP_VD2_POSTBLEND |
> -		    VPP_VD1_PREBLEND | VPP_VD2_PREBLEND, 0,
> -		    priv->io_base + _REG(VPP_MISC));
> -
> -	/* Setup default VD settings */
> -	writel(4096,
> -	       priv->io_base + _REG(VPP_PREBLEND_VD1_H_START_END));
> -	writel(4096,
> -	       priv->io_base + _REG(VPP_BLEND_VD2_H_START_END));
> +	if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
> +		writel(VPP_OFIFO_SIZE_DEFAULT,
> +		       priv->io_base + _REG(VPP_OFIFO_SIZE));
> +	else
> +		writel_bits(VPP_OFIFO_SIZE_MASK, 0x77f,
> +			    priv->io_base + _REG(VPP_OFIFO_SIZE));
> +	writel(VPP_POSTBLEND_HOLD_LINES(4) | VPP_PREBLEND_HOLD_LINES(4),
> +	       priv->io_base + _REG(VPP_HOLD_LINES));
> +
> +	if (!meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
> +		/* Turn off preblend */
> +		writel_bits(VPP_PREBLEND_ENABLE, 0,
> +			    priv->io_base + _REG(VPP_MISC));
> +
> +		/* Turn off POSTBLEND */
> +		writel_bits(VPP_POSTBLEND_ENABLE, 0,
> +			    priv->io_base + _REG(VPP_MISC));
> +
> +		/* Force all planes off */
> +		writel_bits(VPP_OSD1_POSTBLEND | VPP_OSD2_POSTBLEND |
> +			    VPP_VD1_POSTBLEND | VPP_VD2_POSTBLEND |
> +			    VPP_VD1_PREBLEND | VPP_VD2_PREBLEND, 0,
> +			    priv->io_base + _REG(VPP_MISC));
> +
> +		/* Setup default VD settings */
> +		writel(4096,
> +		       priv->io_base + _REG(VPP_PREBLEND_VD1_H_START_END));
> +		writel(4096,
> +		       priv->io_base + _REG(VPP_BLEND_VD2_H_START_END));
> +	}
>  
>  	/* Disable Scalers */
>  	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));
> -	writel(4 | (4 << 8) | BIT(15),
> +
> +	writel(VPP_VSC_BANK_LENGTH(4) | VPP_HSC_BANK_LENGTH(4) |
> +	       VPP_SC_VD_EN_ENABLE,
>  	       priv->io_base + _REG(VPP_SC_MISC));
>  
> +	/* Enable minus black level for vadj1 */
> +	writel(VPP_MINUS_BLACK_LVL_VADJ1_ENABLE,
> +	       priv->io_base + _REG(VPP_VADJ_CTRL));
> +
>  	/* Write in the proper filter coefficients. */
>  	meson_vpp_write_scaling_filter_coefs(priv,
>  				vpp_filter_coefs_4point_bspline, false);
> @@ -410,23 +484,31 @@ void meson_vpu_init(struct udevice *dev)
>  						true);
>  
>  	/* Disable OSDs */
> -	writel_bits(BIT(0) | BIT(21), 0,
> +	writel_bits(VIU_OSD1_OSD_BLK_ENABLE | VIU_OSD1_OSD_ENABLE, 0,
>  		    priv->io_base + _REG(VIU_OSD1_CTRL_STAT));
> -	writel_bits(BIT(0) | BIT(21), 0,
> +	writel_bits(VIU_OSD1_OSD_BLK_ENABLE | VIU_OSD1_OSD_ENABLE, 0,
>  		    priv->io_base + _REG(VIU_OSD2_CTRL_STAT));
>  
>  	/* On GXL/GXM, Use the 10bit HDR conversion matrix */
>  	if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM) ||
>  	    meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL))
>  		meson_viu_load_matrix(priv);
> +	else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
> +		meson_viu_set_g12a_osd1_matrix(priv, RGB709_to_YUV709l_coeff,
> +					       true);
>  
>  	/* Initialize OSD1 fifo control register */
> -	reg = BIT(0) |	/* Urgent DDR request priority */
> -	      (4 << 5) | /* hold_fifo_lines */
> -	      (3 << 10) | /* burst length 64 */
> -	      (32 << 12) | /* fifo_depth_val: 32*8=256 */
> -	      (2 << 22) | /* 4 words in 1 burst */
> -	      (2 << 24);
> +	reg = VIU_OSD_DDR_PRIORITY_URGENT |
> +		VIU_OSD_HOLD_FIFO_LINES(4) |
> +		VIU_OSD_FIFO_DEPTH_VAL(32) | /* fifo_depth_val: 32*8=256 */
> +		VIU_OSD_WORDS_PER_BURST(4) | /* 4 words in 1 burst */
> +		VIU_OSD_FIFO_LIMITS(2);      /* fifo_lim: 2*16=32 */
> +
> +	if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
> +		reg |= meson_viu_osd_burst_length_reg(32);
> +	else
> +		reg |= meson_viu_osd_burst_length_reg(64);
> +
>  	writel(reg, priv->io_base + _REG(VIU_OSD1_FIFO_CTRL_STAT));
>  	writel(reg, priv->io_base + _REG(VIU_OSD2_FIFO_CTRL_STAT));
>  
> @@ -437,4 +519,39 @@ void meson_vpu_init(struct udevice *dev)
>  	writel_bits(0xff << OSD_REPLACE_SHIFT,
>  		    0xff << OSD_REPLACE_SHIFT,
>  		    priv->io_base + _REG(VIU_OSD2_CTRL_STAT2));
> +
> +	/* Disable VD1 AFBC */
> +	/* di_mif0_en=0 mif0_to_vpp_en=0 di_mad_en=0 and afbc vd1 set=0*/
> +	writel_bits(VIU_CTRL0_VD1_AFBC_MASK, 0,
> +		    priv->io_base + _REG(VIU_MISC_CTRL0));
> +	writel(0, priv->io_base + _REG(AFBC_ENABLE));
> +
> +	writel(0x00FF00C0,
> +	       priv->io_base + _REG(VD1_IF0_LUMA_FIFO_SIZE));
> +	writel(0x00FF00C0,
> +	       priv->io_base + _REG(VD2_IF0_LUMA_FIFO_SIZE));
> +
> +	if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
> +		writel(VIU_OSD_BLEND_REORDER(0, 1) |
> +		       VIU_OSD_BLEND_REORDER(1, 0) |
> +		       VIU_OSD_BLEND_REORDER(2, 0) |
> +		       VIU_OSD_BLEND_REORDER(3, 0) |
> +		       VIU_OSD_BLEND_DIN_EN(1) |
> +		       VIU_OSD_BLEND1_DIN3_BYPASS_TO_DOUT1 |
> +		       VIU_OSD_BLEND1_DOUT_BYPASS_TO_BLEND2 |
> +		       VIU_OSD_BLEND_DIN0_BYPASS_TO_DOUT0 |
> +		       VIU_OSD_BLEND_BLEN2_PREMULT_EN(1) |
> +		       VIU_OSD_BLEND_HOLD_LINES(4),
> +		       priv->io_base + _REG(VIU_OSD_BLEND_CTRL));
> +		writel(OSD_BLEND_PATH_SEL_ENABLE,
> +		       priv->io_base + _REG(OSD1_BLEND_SRC_CTRL));
> +		writel(OSD_BLEND_PATH_SEL_ENABLE,
> +		       priv->io_base + _REG(OSD2_BLEND_SRC_CTRL));
> +		writel(0, priv->io_base + _REG(VD1_BLEND_SRC_CTRL));
> +		writel(0, priv->io_base + _REG(VD2_BLEND_SRC_CTRL));
> +		writel(0, priv->io_base + _REG(VIU_OSD_BLEND_DUMMY_DATA0));
> +		writel(0, priv->io_base + _REG(VIU_OSD_BLEND_DUMMY_ALPHA));
> +		writel_bits(DOLBY_BYPASS_EN(0xc), DOLBY_BYPASS_EN(0xc),
> +			    priv->io_base + _REG(DOLBY_PATH_CTRL));
> +	}
>  }
> 

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH 4/8] video: meson: sync with linux drm-misc tree
@ 2019-10-09 15:12     ` Neil Armstrong
  0 siblings, 0 replies; 38+ messages in thread
From: Neil Armstrong @ 2019-10-09 15:12 UTC (permalink / raw)
  To: agust; +Cc: u-boot-amlogic, u-boot

Hi Anatolij,

Gentle ping, did you have time to review this patchset ?

Thanks,
Neil
On 30/08/2019 14:09, Neil Armstrong wrote:
> Synchronize the Amlogic Meson Video driver back with the latest
> DRM misc tree, adding G12A platform support, from the latest commit:
> 528a25d040bc ("drm: meson: use match data to detect vpu compatibility")
> 
> The sync includes the following changes from Linux adapted to U-Boot:
> - Add support for VIC alternate timings
> - Switch PLL to 5.94GHz base for 297Mhz pixel clock
> - Add registers for G12A SoC
> - Add G12A Support for VPP setup
> - Add G12A Support for VIU setup
> - Add G12A support for OSD1 Plane
> - Add G12A support for plane handling in CRTC driver
> - Add G12A support for CVBS Encoder
> - Add G12A Video Clock setup
> - Add G12A support for the DW-HDMI Glue
> - fix G12A HDMI PLL settings for 4K60 1000/1001 variations
> - fix primary plane disabling
> - fix G12A primary plane disabling
> - mask value when writing bits relaxed
> - crtc: drv: vpp: viu: venc: use proper macros instead of magic constants
> - global clean-up
> - add macro used to enable HDMI PLL
> - venc: set the correct macrovision max amplitude value
> 
> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
> ---
>  drivers/video/meson/meson_dw_hdmi.c   |  61 ++++-
>  drivers/video/meson/meson_plane.c     |  47 +++-
>  drivers/video/meson/meson_registers.h | 373 +++++++++++++++++++++++++-
>  drivers/video/meson/meson_vclk.c      | 233 ++++++++++++----
>  drivers/video/meson/meson_venc.c      | 169 +++++++++---
>  drivers/video/meson/meson_vpu.h       |   1 +
>  drivers/video/meson/meson_vpu_init.c  | 205 +++++++++++---
>  7 files changed, 929 insertions(+), 160 deletions(-)
> 
> diff --git a/drivers/video/meson/meson_dw_hdmi.c b/drivers/video/meson/meson_dw_hdmi.c
> index 9831d978fc..ae2e6288f3 100644
> --- a/drivers/video/meson/meson_dw_hdmi.c
> +++ b/drivers/video/meson/meson_dw_hdmi.c
> @@ -24,6 +24,7 @@
>  #define HDMITX_TOP_ADDR_REG	0x0
>  #define HDMITX_TOP_DATA_REG	0x4
>  #define HDMITX_TOP_CTRL_REG	0x8
> +#define HDMITX_TOP_G12A_OFFSET	0x8000
>  
>  /* Controller Communication Channel */
>  #define HDMITX_DWC_ADDR_REG	0x10
> @@ -37,6 +38,8 @@
>  #define HHI_HDMI_PHY_CNTL1	0x3a4 /* 0xe9 */
>  #define HHI_HDMI_PHY_CNTL2	0x3a8 /* 0xea */
>  #define HHI_HDMI_PHY_CNTL3	0x3ac /* 0xeb */
> +#define HHI_HDMI_PHY_CNTL4	0x3b0 /* 0xec */
> +#define HHI_HDMI_PHY_CNTL5	0x3b4 /* 0xed */
>  
>  struct meson_dw_hdmi {
>  	struct udevice *dev;
> @@ -48,6 +51,7 @@ enum hdmi_compatible {
>  	HDMI_COMPATIBLE_GXBB = 0,
>  	HDMI_COMPATIBLE_GXL = 1,
>  	HDMI_COMPATIBLE_GXM = 2,
> +	HDMI_COMPATIBLE_G12A = 3,
>  };
>  
>  static inline bool meson_hdmi_is_compatible(struct meson_dw_hdmi *priv,
> @@ -60,8 +64,14 @@ static inline bool meson_hdmi_is_compatible(struct meson_dw_hdmi *priv,
>  
>  static unsigned int dw_hdmi_top_read(struct dw_hdmi *hdmi, unsigned int addr)
>  {
> +	struct meson_dw_hdmi *priv = container_of(hdmi, struct meson_dw_hdmi,
> +						  hdmi);
>  	unsigned int data;
>  
> +	if (meson_hdmi_is_compatible(priv, HDMI_COMPATIBLE_G12A))
> +		return readl(hdmi->ioaddr +
> +			     HDMITX_TOP_G12A_OFFSET + (addr << 2));
> +
>  	/* ADDR must be written twice */
>  	writel(addr & 0xffff, hdmi->ioaddr + HDMITX_TOP_ADDR_REG);
>  	writel(addr & 0xffff, hdmi->ioaddr + HDMITX_TOP_ADDR_REG);
> @@ -76,6 +86,15 @@ static unsigned int dw_hdmi_top_read(struct dw_hdmi *hdmi, unsigned int addr)
>  static inline void dw_hdmi_top_write(struct dw_hdmi *hdmi,
>  				     unsigned int addr, unsigned int data)
>  {
> +	struct meson_dw_hdmi *priv = container_of(hdmi, struct meson_dw_hdmi,
> +						  hdmi);
> +
> +	if (meson_hdmi_is_compatible(priv, HDMI_COMPATIBLE_G12A)) {
> +		writel(data, hdmi->ioaddr +
> +		       HDMITX_TOP_G12A_OFFSET + (addr << 2));
> +		return;
> +	}
> +
>  	/* ADDR must be written twice */
>  	writel(addr & 0xffff, hdmi->ioaddr + HDMITX_TOP_ADDR_REG);
>  	writel(addr & 0xffff, hdmi->ioaddr + HDMITX_TOP_ADDR_REG);
> @@ -237,7 +256,7 @@ static void meson_dw_hdmi_phy_setup_mode(struct meson_dw_hdmi *priv,
>  			hhi_write(HHI_HDMI_PHY_CNTL0, 0x33604142);
>  			hhi_write(HHI_HDMI_PHY_CNTL3, 0x0016315b);
>  		}
> -	} else {
> +	} else if (meson_hdmi_is_compatible(priv, HDMI_COMPATIBLE_GXBB)) {
>  		if (pixel_clock >= 371250) {
>  			/* 5.94Gbps, 3.7125Gbps */
>  			hhi_write(HHI_HDMI_PHY_CNTL0, 0x33353245);
> @@ -251,6 +270,23 @@ static void meson_dw_hdmi_phy_setup_mode(struct meson_dw_hdmi *priv,
>  			hhi_write(HHI_HDMI_PHY_CNTL0, 0x33632122);
>  			hhi_write(HHI_HDMI_PHY_CNTL3, 0x2000115b);
>  		}
> +	} else if (meson_hdmi_is_compatible(priv, HDMI_COMPATIBLE_G12A)) {
> +		if (pixel_clock >= 371250) {
> +			/* 5.94Gbps, 3.7125Gbps */
> +			hhi_write(HHI_HDMI_PHY_CNTL0, 0x37eb65c4);
> +			hhi_write(HHI_HDMI_PHY_CNTL3, 0x2ab0ff3b);
> +			hhi_write(HHI_HDMI_PHY_CNTL5, 0x0000080b);
> +		} else if (pixel_clock >= 297000) {
> +			/* 2.97Gbps */
> +			hhi_write(HHI_HDMI_PHY_CNTL0, 0x33eb6262);
> +			hhi_write(HHI_HDMI_PHY_CNTL3, 0x2ab0ff3b);
> +			hhi_write(HHI_HDMI_PHY_CNTL5, 0x00000003);
> +		} else {
> +			/* 1.485Gbps, and below */
> +			hhi_write(HHI_HDMI_PHY_CNTL0, 0x33eb4242);
> +			hhi_write(HHI_HDMI_PHY_CNTL3, 0x2ab0ff3b);
> +			hhi_write(HHI_HDMI_PHY_CNTL5, 0x00000003);
> +		}
>  	}
>  }
>  
> @@ -292,7 +328,8 @@ static int meson_dw_hdmi_phy_init(struct dw_hdmi *hdmi, uint pixel_clock)
>  
>  	/* BIT_INVERT */
>  	if (meson_hdmi_is_compatible(priv, HDMI_COMPATIBLE_GXL) ||
> -	    meson_hdmi_is_compatible(priv, HDMI_COMPATIBLE_GXM))
> +	    meson_hdmi_is_compatible(priv, HDMI_COMPATIBLE_GXM) ||
> +	    meson_hdmi_is_compatible(priv, HDMI_COMPATIBLE_G12A))
>  		dw_hdmi_hhi_update_bits(priv, HHI_HDMI_PHY_CNTL1, BIT(17), 0);
>  	else
>  		dw_hdmi_hhi_update_bits(priv, HHI_HDMI_PHY_CNTL1,
> @@ -356,8 +393,12 @@ static int meson_dw_hdmi_probe(struct udevice *dev)
>  	priv->hdmi.hdmi_data.enc_out_bus_format = MEDIA_BUS_FMT_RGB888_1X24;
>  	priv->hdmi.hdmi_data.enc_in_bus_format = MEDIA_BUS_FMT_YUV8_1X24;
>  	priv->hdmi.phy_set = meson_dw_hdmi_phy_init;
> -	priv->hdmi.write_reg = dw_hdmi_dwc_write;
> -	priv->hdmi.read_reg = dw_hdmi_dwc_read;
> +	if (meson_hdmi_is_compatible(priv, HDMI_COMPATIBLE_G12A))
> +		priv->hdmi.reg_io_width = 1;
> +	else {
> +		priv->hdmi.write_reg = dw_hdmi_dwc_write;
> +		priv->hdmi.read_reg = dw_hdmi_dwc_read;
> +	}
>  	priv->hdmi.i2c_clk_high = 0x67;
>  	priv->hdmi.i2c_clk_low = 0x78;
>  
> @@ -409,9 +450,13 @@ static int meson_dw_hdmi_probe(struct udevice *dev)
>  	if (ret)
>  		return ret;
>  
> -	/* Enable APB3 fail on error */
> -	writel_bits(BIT(15), BIT(15), priv->hdmi.ioaddr + HDMITX_TOP_CTRL_REG);
> -	writel_bits(BIT(15), BIT(15), priv->hdmi.ioaddr + HDMITX_DWC_CTRL_REG);
> +	if (!meson_hdmi_is_compatible(priv, HDMI_COMPATIBLE_G12A)) {
> +		/* Enable APB3 fail on error */
> +		writel_bits(BIT(15), BIT(15),
> +			    priv->hdmi.ioaddr + HDMITX_TOP_CTRL_REG);
> +		writel_bits(BIT(15), BIT(15),
> +			    priv->hdmi.ioaddr + HDMITX_DWC_CTRL_REG);
> +	}
>  
>  	/* Bring out of reset */
>  	dw_hdmi_top_write(&priv->hdmi, HDMITX_TOP_SW_RESET,  0);
> @@ -448,6 +493,8 @@ static const struct udevice_id meson_dw_hdmi_ids[] = {
>  		.data = HDMI_COMPATIBLE_GXL },
>  	{ .compatible = "amlogic,meson-gxm-dw-hdmi",
>  		.data = HDMI_COMPATIBLE_GXM },
> +	{ .compatible = "amlogic,meson-g12a-dw-hdmi",
> +		.data = HDMI_COMPATIBLE_G12A },
>  	{ }
>  };
>  
> diff --git a/drivers/video/meson/meson_plane.c b/drivers/video/meson/meson_plane.c
> index 63a4bf2d8d..2bc9327e1e 100644
> --- a/drivers/video/meson/meson_plane.c
> +++ b/drivers/video/meson/meson_plane.c
> @@ -108,12 +108,33 @@ void meson_vpu_setup_plane(struct udevice *dev, bool is_interlaced)
>  	dest_y1 = src_y1 = 0;
>  	dest_y2 = src_y2 = uc_priv->ysize;
>  
> -	/* Enable VPP Postblend */
> -	writel(uc_priv->xsize,
> -	       priv->io_base + _REG(VPP_POSTBLEND_H_SIZE));
> +	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));
> +		writel_bits(VPP_POSTBLEND_ENABLE, VPP_POSTBLEND_ENABLE,
> +			    priv->io_base + _REG(VPP_MISC));
> +	}
>  
>  	/* uc_plat->base is the framebuffer */
>  
> @@ -172,6 +193,18 @@ void meson_vpu_setup_plane(struct udevice *dev, bool is_interlaced)
>  			   MESON_CANVAS_BLKMODE_LINEAR);
>  
>  	/* Enable OSD1 */
> -	writel_bits(VPP_OSD1_POSTBLEND, VPP_OSD1_POSTBLEND,
> -		    priv->io_base + _REG(VPP_MISC));
> +	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));
>  }
> diff --git a/drivers/video/meson/meson_registers.h b/drivers/video/meson/meson_registers.h
> index 01fe7d2431..39e8ec8639 100644
> --- a/drivers/video/meson/meson_registers.h
> +++ b/drivers/video/meson/meson_registers.h
> @@ -136,11 +136,19 @@
>  #define VIU_ADDR_START 0x1a00
>  #define VIU_ADDR_END 0x1aff
>  #define VIU_SW_RESET 0x1a01
> +#define		VIU_SW_RESET_OSD1               BIT(0)
>  #define VIU_MISC_CTRL0 0x1a06
> +#define		VIU_CTRL0_VD1_AFBC_MASK         0x170000
>  #define VIU_MISC_CTRL1 0x1a07
>  #define D2D3_INTF_LENGTH 0x1a08
>  #define D2D3_INTF_CTRL0 0x1a09
>  #define VIU_OSD1_CTRL_STAT 0x1a10
> +#define		VIU_OSD1_OSD_BLK_ENABLE         BIT(0)
> +#define		VIU_OSD1_POSTBLD_SRC_VD1        (1 << 8)
> +#define		VIU_OSD1_POSTBLD_SRC_VD2        (2 << 8)
> +#define		VIU_OSD1_POSTBLD_SRC_OSD1       (3 << 8)
> +#define		VIU_OSD1_POSTBLD_SRC_OSD2       (4 << 8)
> +#define		VIU_OSD1_OSD_ENABLE             BIT(21)
>  #define VIU_OSD1_CTRL_STAT2 0x1a2d
>  #define VIU_OSD1_COLOR_ADDR 0x1a11
>  #define VIU_OSD1_COLOR 0x1a12
> @@ -206,6 +214,35 @@
>  #define VIU_OSD2_FIFO_CTRL_STAT 0x1a4b
>  #define VIU_OSD2_TEST_RDDATA 0x1a4c
>  #define VIU_OSD2_PROT_CTRL 0x1a4e
> +#define VIU_OSD2_MALI_UNPACK_CTRL 0x1abd
> +#define VIU_OSD2_DIMM_CTRL 0x1acf
> +
> +#define VIU_OSD3_CTRL_STAT 0x3d80
> +#define VIU_OSD3_CTRL_STAT2 0x3d81
> +#define VIU_OSD3_COLOR_ADDR 0x3d82
> +#define VIU_OSD3_COLOR 0x3d83
> +#define VIU_OSD3_TCOLOR_AG0 0x3d84
> +#define VIU_OSD3_TCOLOR_AG1 0x3d85
> +#define VIU_OSD3_TCOLOR_AG2 0x3d86
> +#define VIU_OSD3_TCOLOR_AG3 0x3d87
> +#define VIU_OSD3_BLK0_CFG_W0 0x3d88
> +#define VIU_OSD3_BLK0_CFG_W1 0x3d8c
> +#define VIU_OSD3_BLK0_CFG_W2 0x3d90
> +#define VIU_OSD3_BLK0_CFG_W3 0x3d94
> +#define VIU_OSD3_BLK0_CFG_W4 0x3d98
> +#define VIU_OSD3_BLK1_CFG_W4 0x3d99
> +#define VIU_OSD3_BLK2_CFG_W4 0x3d9a
> +#define VIU_OSD3_FIFO_CTRL_STAT 0x3d9c
> +#define VIU_OSD3_TEST_RDDATA 0x3d9d
> +#define VIU_OSD3_PROT_CTRL 0x3d9e
> +#define VIU_OSD3_MALI_UNPACK_CTRL 0x3d9f
> +#define VIU_OSD3_DIMM_CTRL 0x3da0
> +
> +#define VIU_OSD_DDR_PRIORITY_URGENT      BIT(0)
> +#define VIU_OSD_HOLD_FIFO_LINES(lines)   ((lines & 0x1f) << 5)
> +#define VIU_OSD_FIFO_DEPTH_VAL(val)      ((val & 0x7f) << 12)
> +#define VIU_OSD_WORDS_PER_BURST(words)   (((words & 0x4) >> 1) << 22)
> +#define VIU_OSD_FIFO_LIMITS(size)        ((size & 0xf) << 24)
>  
>  #define VD1_IF0_GEN_REG 0x1a50
>  #define VD1_IF0_CANVAS0 0x1a51
> @@ -277,6 +314,27 @@
>  #define VIU_OSD1_MATRIX_COEF31_32 0x1a9e
>  #define VIU_OSD1_MATRIX_COEF40_41 0x1a9f
>  #define VD1_IF0_GEN_REG3 0x1aa7
> +
> +#define VIU_OSD_BLENDO_H_START_END 0x1aa9
> +#define VIU_OSD_BLENDO_V_START_END 0x1aaa
> +#define VIU_OSD_BLEND_GEN_CTRL0 0x1aab
> +#define VIU_OSD_BLEND_GEN_CTRL1 0x1aac
> +#define VIU_OSD_BLEND_DUMMY_DATA 0x1aad
> +#define VIU_OSD_BLEND_CURRENT_XY 0x1aae
> +
> +#define VIU_OSD2_MATRIX_CTRL 0x1ab0
> +#define VIU_OSD2_MATRIX_COEF00_01 0x1ab1
> +#define VIU_OSD2_MATRIX_COEF02_10 0x1ab2
> +#define VIU_OSD2_MATRIX_COEF11_12 0x1ab3
> +#define VIU_OSD2_MATRIX_COEF20_21 0x1ab4
> +#define VIU_OSD2_MATRIX_COEF22 0x1ab5
> +#define VIU_OSD2_MATRIX_OFFSET0_1 0x1ab6
> +#define VIU_OSD2_MATRIX_OFFSET2 0x1ab7
> +#define VIU_OSD2_MATRIX_PRE_OFFSET0_1 0x1ab8
> +#define VIU_OSD2_MATRIX_PRE_OFFSET2 0x1ab9
> +#define VIU_OSD2_MATRIX_PROBE_COLOR 0x1aba
> +#define VIU_OSD2_MATRIX_HL_COLOR 0x1abb
> +#define VIU_OSD2_MATRIX_PROBE_POS 0x1abc
>  #define VIU_OSD1_EOTF_CTL 0x1ad4
>  #define VIU_OSD1_EOTF_COEF00_01 0x1ad5
>  #define VIU_OSD1_EOTF_COEF02_10 0x1ad6
> @@ -295,6 +353,7 @@
>  #define VPP_LINE_IN_LENGTH 0x1d01
>  #define VPP_PIC_IN_HEIGHT 0x1d02
>  #define VPP_SCALE_COEF_IDX 0x1d03
> +#define		VPP_SCALE_HORIZONTAL_COEF       BIT(8)
>  #define VPP_SCALE_COEF 0x1d04
>  #define VPP_VSC_REGION12_STARTP 0x1d05
>  #define VPP_VSC_REGION34_STARTP 0x1d06
> @@ -316,6 +375,12 @@
>  #define VPP_HSC_REGION4_PHASE_SLOPE 0x1d17
>  #define VPP_HSC_PHASE_CTRL 0x1d18
>  #define VPP_SC_MISC 0x1d19
> +#define		VPP_SC_VD_EN_ENABLE             BIT(15)
> +#define		VPP_SC_TOP_EN_ENABLE            BIT(16)
> +#define		VPP_SC_HSC_EN_ENABLE            BIT(17)
> +#define		VPP_SC_VSC_EN_ENABLE            BIT(18)
> +#define		VPP_VSC_BANK_LENGTH(length)     (length & 0x7)
> +#define		VPP_HSC_BANK_LENGTH(length)     ((length & 0x7) << 8)
>  #define VPP_PREBLEND_VD1_H_START_END 0x1d1a
>  #define VPP_PREBLEND_VD1_V_START_END 0x1d1b
>  #define VPP_POSTBLEND_VD1_H_START_END 0x1d1c
> @@ -325,24 +390,28 @@
>  #define VPP_PREBLEND_H_SIZE 0x1d20
>  #define VPP_POSTBLEND_H_SIZE 0x1d21
>  #define VPP_HOLD_LINES 0x1d22
> +#define		VPP_POSTBLEND_HOLD_LINES(lines) (lines & 0xf)
> +#define		VPP_PREBLEND_HOLD_LINES(lines)  ((lines & 0xf) << 8)
>  #define VPP_BLEND_ONECOLOR_CTRL 0x1d23
>  #define VPP_PREBLEND_CURRENT_XY 0x1d24
>  #define VPP_POSTBLEND_CURRENT_XY 0x1d25
>  #define VPP_MISC 0x1d26
> -#define		VPP_PREBLEND_ENABLE	BIT(6)
> -#define		VPP_POSTBLEND_ENABLE	BIT(7)
> -#define		VPP_OSD2_ALPHA_PREMULT	BIT(8)
> -#define		VPP_OSD1_ALPHA_PREMULT	BIT(9)
> -#define		VPP_VD1_POSTBLEND	BIT(10)
> -#define		VPP_VD2_POSTBLEND	BIT(11)
> -#define		VPP_OSD1_POSTBLEND	BIT(12)
> -#define		VPP_OSD2_POSTBLEND	BIT(13)
> -#define		VPP_VD1_PREBLEND	BIT(14)
> -#define		VPP_VD2_PREBLEND	BIT(15)
> -#define		VPP_OSD1_PREBLEND	BIT(16)
> -#define		VPP_OSD2_PREBLEND	BIT(17)
> -#define		VPP_COLOR_MNG_ENABLE	BIT(28)
> +#define		VPP_PREBLEND_ENABLE             BIT(6)
> +#define		VPP_POSTBLEND_ENABLE            BIT(7)
> +#define		VPP_OSD2_ALPHA_PREMULT          BIT(8)
> +#define		VPP_OSD1_ALPHA_PREMULT          BIT(9)
> +#define		VPP_VD1_POSTBLEND               BIT(10)
> +#define		VPP_VD2_POSTBLEND               BIT(11)
> +#define		VPP_OSD1_POSTBLEND              BIT(12)
> +#define		VPP_OSD2_POSTBLEND              BIT(13)
> +#define		VPP_VD1_PREBLEND                BIT(14)
> +#define		VPP_VD2_PREBLEND                BIT(15)
> +#define		VPP_OSD1_PREBLEND               BIT(16)
> +#define		VPP_OSD2_PREBLEND               BIT(17)
> +#define		VPP_COLOR_MNG_ENABLE            BIT(28)
>  #define VPP_OFIFO_SIZE 0x1d27
> +#define		VPP_OFIFO_SIZE_MASK             GENMASK(13, 0)
> +#define		VPP_OFIFO_SIZE_DEFAULT          (0xfff << 20 | 0x1000)
>  #define VPP_FIFO_STATUS 0x1d28
>  #define VPP_SMOKE_CTRL 0x1d29
>  #define VPP_SMOKE1_VAL 0x1d2a
> @@ -358,6 +427,8 @@
>  #define VPP_HSC_PHASE_CTRL1 0x1d34
>  #define VPP_HSC_INI_PAT_CTRL 0x1d35
>  #define VPP_VADJ_CTRL 0x1d40
> +#define		VPP_MINUS_BLACK_LVL_VADJ1_ENABLE BIT(1)
> +
>  #define VPP_VADJ1_Y 0x1d41
>  #define VPP_VADJ1_MA_MB 0x1d42
>  #define VPP_VADJ1_MC_MD 0x1d43
> @@ -417,6 +488,7 @@
>  #define VPP_PEAKING_VGAIN 0x1d92
>  #define VPP_PEAKING_NLP_1 0x1d93
>  #define VPP_DOLBY_CTRL 0x1d93
> +#define VPP_PPS_DUMMY_DATA_MODE (1 << 17)
>  #define VPP_PEAKING_NLP_2 0x1d94
>  #define VPP_PEAKING_NLP_3 0x1d95
>  #define VPP_PEAKING_NLP_4 0x1d96
> @@ -471,6 +543,83 @@
>  #define VPP_OSD_SCALE_COEF 0x1dcd
>  #define VPP_INT_LINE_NUM 0x1dce
>  
> +#define VPP_WRAP_OSD1_MATRIX_COEF00_01 0x3d60
> +#define VPP_WRAP_OSD1_MATRIX_COEF02_10 0x3d61
> +#define VPP_WRAP_OSD1_MATRIX_COEF11_12 0x3d62
> +#define VPP_WRAP_OSD1_MATRIX_COEF20_21 0x3d63
> +#define VPP_WRAP_OSD1_MATRIX_COEF22 0x3d64
> +#define VPP_WRAP_OSD1_MATRIX_COEF13_14 0x3d65
> +#define VPP_WRAP_OSD1_MATRIX_COEF23_24 0x3d66
> +#define VPP_WRAP_OSD1_MATRIX_COEF15_25 0x3d67
> +#define VPP_WRAP_OSD1_MATRIX_CLIP 0x3d68
> +#define VPP_WRAP_OSD1_MATRIX_OFFSET0_1 0x3d69
> +#define VPP_WRAP_OSD1_MATRIX_OFFSET2 0x3d6a
> +#define VPP_WRAP_OSD1_MATRIX_PRE_OFFSET0_1 0x3d6b
> +#define VPP_WRAP_OSD1_MATRIX_PRE_OFFSET2 0x3d6c
> +#define VPP_WRAP_OSD1_MATRIX_EN_CTRL 0x3d6d
> +
> +#define VPP_WRAP_OSD2_MATRIX_COEF00_01 0x3d70
> +#define VPP_WRAP_OSD2_MATRIX_COEF02_10 0x3d71
> +#define VPP_WRAP_OSD2_MATRIX_COEF11_12 0x3d72
> +#define VPP_WRAP_OSD2_MATRIX_COEF20_21 0x3d73
> +#define VPP_WRAP_OSD2_MATRIX_COEF22 0x3d74
> +#define VPP_WRAP_OSD2_MATRIX_COEF13_14 0x3d75
> +#define VPP_WRAP_OSD2_MATRIX_COEF23_24 0x3d76
> +#define VPP_WRAP_OSD2_MATRIX_COEF15_25 0x3d77
> +#define VPP_WRAP_OSD2_MATRIX_CLIP 0x3d78
> +#define VPP_WRAP_OSD2_MATRIX_OFFSET0_1 0x3d79
> +#define VPP_WRAP_OSD2_MATRIX_OFFSET2 0x3d7a
> +#define VPP_WRAP_OSD2_MATRIX_PRE_OFFSET0_1 0x3d7b
> +#define VPP_WRAP_OSD2_MATRIX_PRE_OFFSET2 0x3d7c
> +#define VPP_WRAP_OSD2_MATRIX_EN_CTRL 0x3d7d
> +
> +#define VPP_WRAP_OSD3_MATRIX_COEF00_01 0x3db0
> +#define VPP_WRAP_OSD3_MATRIX_COEF02_10 0x3db1
> +#define VPP_WRAP_OSD3_MATRIX_COEF11_12 0x3db2
> +#define VPP_WRAP_OSD3_MATRIX_COEF20_21 0x3db3
> +#define VPP_WRAP_OSD3_MATRIX_COEF22 0x3db4
> +#define VPP_WRAP_OSD3_MATRIX_COEF13_14 0x3db5
> +#define VPP_WRAP_OSD3_MATRIX_COEF23_24 0x3db6
> +#define VPP_WRAP_OSD3_MATRIX_COEF15_25 0x3db7
> +#define VPP_WRAP_OSD3_MATRIX_CLIP 0x3db8
> +#define VPP_WRAP_OSD3_MATRIX_OFFSET0_1 0x3db9
> +#define VPP_WRAP_OSD3_MATRIX_OFFSET2 0x3dba
> +#define VPP_WRAP_OSD3_MATRIX_PRE_OFFSET0_1 0x3dbb
> +#define VPP_WRAP_OSD3_MATRIX_PRE_OFFSET2 0x3dbc
> +#define VPP_WRAP_OSD3_MATRIX_EN_CTRL 0x3dbd
> +
> +/* osd2 scaler */
> +#define OSD2_VSC_PHASE_STEP 0x3d00
> +#define OSD2_VSC_INI_PHASE 0x3d01
> +#define OSD2_VSC_CTRL0 0x3d02
> +#define OSD2_HSC_PHASE_STEP 0x3d03
> +#define OSD2_HSC_INI_PHASE 0x3d04
> +#define OSD2_HSC_CTRL0 0x3d05
> +#define OSD2_HSC_INI_PAT_CTRL 0x3d06
> +#define OSD2_SC_DUMMY_DATA 0x3d07
> +#define OSD2_SC_CTRL0 0x3d08
> +#define OSD2_SCI_WH_M1 0x3d09
> +#define OSD2_SCO_H_START_END 0x3d0a
> +#define OSD2_SCO_V_START_END 0x3d0b
> +#define OSD2_SCALE_COEF_IDX 0x3d18
> +#define OSD2_SCALE_COEF 0x3d19
> +
> +/* osd34 scaler */
> +#define OSD34_SCALE_COEF_IDX 0x3d1e
> +#define OSD34_SCALE_COEF 0x3d1f
> +#define OSD34_VSC_PHASE_STEP 0x3d20
> +#define OSD34_VSC_INI_PHASE 0x3d21
> +#define OSD34_VSC_CTRL0 0x3d22
> +#define OSD34_HSC_PHASE_STEP 0x3d23
> +#define OSD34_HSC_INI_PHASE 0x3d24
> +#define OSD34_HSC_CTRL0 0x3d25
> +#define OSD34_HSC_INI_PAT_CTRL 0x3d26
> +#define OSD34_SC_DUMMY_DATA 0x3d27
> +#define OSD34_SC_CTRL0 0x3d28
> +#define OSD34_SCI_WH_M1 0x3d29
> +#define OSD34_SCO_H_START_END 0x3d2a
> +#define OSD34_SCO_V_START_END 0x3d2b
> +
>  /* viu2 */
>  #define VIU2_ADDR_START 0x1e00
>  #define VIU2_ADDR_END 0x1eff
> @@ -584,6 +733,25 @@
>  #define VENC_UPSAMPLE_CTRL0 0x1b64
>  #define VENC_UPSAMPLE_CTRL1 0x1b65
>  #define VENC_UPSAMPLE_CTRL2 0x1b66
> +#define		VENC_UPSAMPLE_CTRL_F0_2_CLK_RATIO        BIT(0)
> +#define		VENC_UPSAMPLE_CTRL_F1_EN                 BIT(5)
> +#define		VENC_UPSAMPLE_CTRL_F1_UPSAMPLE_EN        BIT(6)
> +#define		VENC_UPSAMPLE_CTRL_INTERLACE_HIGH_LUMA   (0x0 << 12)
> +#define		VENC_UPSAMPLE_CTRL_CVBS                  (0x1 << 12)
> +#define		VENC_UPSAMPLE_CTRL_S_VIDEO_LUMA          (0x2 << 12)
> +#define		VENC_UPSAMPLE_CTRL_S_VIDEO_CHROMA        (0x3 << 12)
> +#define		VENC_UPSAMPLE_CTRL_INTERLACE_PB          (0x4 << 12)
> +#define		VENC_UPSAMPLE_CTRL_INTERLACE_PR          (0x5 << 12)
> +#define		VENC_UPSAMPLE_CTRL_INTERLACE_R           (0x6 << 12)
> +#define		VENC_UPSAMPLE_CTRL_INTERLACE_G           (0x7 << 12)
> +#define		VENC_UPSAMPLE_CTRL_INTERLACE_B           (0x8 << 12)
> +#define		VENC_UPSAMPLE_CTRL_PROGRESSIVE_Y         (0x9 << 12)
> +#define		VENC_UPSAMPLE_CTRL_PROGRESSIVE_PB        (0xa << 12)
> +#define		VENC_UPSAMPLE_CTRL_PROGRESSIVE_PR        (0xb << 12)
> +#define		VENC_UPSAMPLE_CTRL_PROGRESSIVE_R         (0xc << 12)
> +#define		VENC_UPSAMPLE_CTRL_PROGRESSIVE_G         (0xd << 12)
> +#define		VENC_UPSAMPLE_CTRL_PROGRESSIVE_B         (0xe << 12)
> +#define		VENC_UPSAMPLE_CTRL_VDAC_TEST_VALUE       (0xf << 12)
>  #define TCON_INVERT_CTL 0x1b67
>  #define VENC_VIDEO_PROG_MODE 0x1b68
>  #define VENC_ENCI_LINE 0x1b69
> @@ -592,6 +760,7 @@
>  #define VENC_ENCP_PIXEL 0x1b6c
>  #define VENC_STATA 0x1b6d
>  #define VENC_INTCTRL 0x1b6e
> +#define		VENC_INTCTRL_ENCI_LNRST_INT_EN  BIT(1)
>  #define VENC_INTFLAG 0x1b6f
>  #define VENC_VIDEO_TST_EN 0x1b70
>  #define VENC_VIDEO_TST_MDSEL 0x1b71
> @@ -602,6 +771,7 @@
>  #define VENC_VIDEO_TST_CLRBAR_WIDTH 0x1b76
>  #define VENC_VIDEO_TST_VDCNT_STSET 0x1b77
>  #define VENC_VDAC_DACSEL0 0x1b78
> +#define		VENC_VDAC_SEL_ATV_DMD           BIT(5)
>  #define VENC_VDAC_DACSEL1 0x1b79
>  #define VENC_VDAC_DACSEL2 0x1b7a
>  #define VENC_VDAC_DACSEL3 0x1b7b
> @@ -622,6 +792,7 @@
>  #define VENC_VDAC_DAC5_GAINCTRL 0x1bfa
>  #define VENC_VDAC_DAC5_OFFSET 0x1bfb
>  #define VENC_VDAC_FIFO_CTRL 0x1bfc
> +#define		VENC_VDAC_FIFO_EN_ENCI_ENABLE   BIT(13)
>  #define ENCL_TCON_INVERT_CTL 0x1bfd
>  #define ENCP_VIDEO_EN 0x1b80
>  #define ENCP_VIDEO_SYNC_MODE 0x1b81
> @@ -637,6 +808,7 @@
>  #define ENCP_VIDEO_SYNC_OFFST 0x1b8b
>  #define ENCP_VIDEO_MACV_OFFST 0x1b8c
>  #define ENCP_VIDEO_MODE 0x1b8d
> +#define		ENCP_VIDEO_MODE_DE_V_HIGH       BIT(14)
>  #define ENCP_VIDEO_MODE_ADV 0x1b8e
>  #define ENCP_DBG_PX_RST 0x1b90
>  #define ENCP_DBG_LN_RST 0x1b91
> @@ -715,6 +887,11 @@
>  #define C656_FS_LNED 0x1be7
>  #define ENCI_VIDEO_MODE 0x1b00
>  #define ENCI_VIDEO_MODE_ADV 0x1b01
> +#define		ENCI_VIDEO_MODE_ADV_DMXMD(val)          (val & 0x3)
> +#define		ENCI_VIDEO_MODE_ADV_VBICTL_LINE_17_22   BIT(2)
> +#define		ENCI_VIDEO_MODE_ADV_YBW_MEDIUM          (0 << 4)
> +#define		ENCI_VIDEO_MODE_ADV_YBW_LOW             (0x1 << 4)
> +#define		ENCI_VIDEO_MODE_ADV_YBW_HIGH            (0x2 << 4)
>  #define ENCI_VIDEO_FSC_ADJ 0x1b02
>  #define ENCI_VIDEO_BRIGHT 0x1b03
>  #define ENCI_VIDEO_CONT 0x1b04
> @@ -785,13 +962,17 @@
>  #define ENCI_DBG_MAXPX 0x1b4c
>  #define ENCI_DBG_MAXLN 0x1b4d
>  #define ENCI_MACV_MAX_AMP 0x1b50
> +#define		ENCI_MACV_MAX_AMP_ENABLE_CHANGE BIT(15)
> +#define		ENCI_MACV_MAX_AMP_VAL(val)      (val & 0x83ff)
>  #define ENCI_MACV_PULSE_LO 0x1b51
>  #define ENCI_MACV_PULSE_HI 0x1b52
>  #define ENCI_MACV_BKP_MAX 0x1b53
>  #define ENCI_CFILT_CTRL 0x1b54
> +#define		ENCI_CFILT_CMPT_SEL_HIGH        BIT(1)
>  #define ENCI_CFILT7 0x1b55
>  #define ENCI_YC_DELAY 0x1b56
>  #define ENCI_VIDEO_EN 0x1b57
> +#define		ENCI_VIDEO_EN_ENABLE            BIT(0)
>  #define ENCI_DVI_HSO_BEGIN 0x1c00
>  #define ENCI_DVI_HSO_END 0x1c01
>  #define ENCI_DVI_VSO_BLINE_EVN 0x1c02
> @@ -803,6 +984,10 @@
>  #define ENCI_DVI_VSO_END_EVN 0x1c08
>  #define ENCI_DVI_VSO_END_ODD 0x1c09
>  #define ENCI_CFILT_CTRL2 0x1c0a
> +#define		ENCI_CFILT_CMPT_CR_DLY(delay)   (delay & 0xf)
> +#define		ENCI_CFILT_CMPT_CB_DLY(delay)   ((delay & 0xf) << 4)
> +#define		ENCI_CFILT_CVBS_CR_DLY(delay)   ((delay & 0xf) << 8)
> +#define		ENCI_CFILT_CVBS_CB_DLY(delay)   ((delay & 0xf) << 12)
>  #define ENCI_DACSEL_0 0x1c0b
>  #define ENCI_DACSEL_1 0x1c0c
>  #define ENCP_DACSEL_0 0x1c0d
> @@ -817,6 +1002,8 @@
>  #define ENCI_TST_CLRBAR_WIDTH 0x1c16
>  #define ENCI_TST_VDCNT_STSET 0x1c17
>  #define ENCI_VFIFO2VD_CTL 0x1c18
> +#define		ENCI_VFIFO2VD_CTL_ENABLE        BIT(0)
> +#define		ENCI_VFIFO2VD_CTL_VD_SEL(val)   ((val & 0xff) << 8)
>  #define ENCI_VFIFO2VD_PIXEL_START 0x1c19
>  #define ENCI_VFIFO2VD_PIXEL_END 0x1c1a
>  #define ENCI_VFIFO2VD_LINE_TOP_START 0x1c1b
> @@ -879,6 +1066,7 @@
>  #define VENC_VDAC_DAC5_FILT_CTRL0 0x1c56
>  #define VENC_VDAC_DAC5_FILT_CTRL1 0x1c57
>  #define VENC_VDAC_DAC0_FILT_CTRL0 0x1c58
> +#define		VENC_VDAC_DAC0_FILT_CTRL0_EN    BIT(0)
>  #define VENC_VDAC_DAC0_FILT_CTRL1 0x1c59
>  #define VENC_VDAC_DAC1_FILT_CTRL0 0x1c5a
>  #define VENC_VDAC_DAC1_FILT_CTRL1 0x1c5b
> @@ -1284,6 +1472,18 @@
>  #define		VIU2_SEL_VENC_ENCP	(2 << 2)
>  #define		VIU2_SEL_VENC_ENCT	(3 << 2)
>  #define VPU_HDMI_SETTING 0x271b
> +#define		VPU_HDMI_ENCI_DATA_TO_HDMI      BIT(0)
> +#define		VPU_HDMI_ENCP_DATA_TO_HDMI      BIT(1)
> +#define		VPU_HDMI_INV_HSYNC              BIT(2)
> +#define		VPU_HDMI_INV_VSYNC              BIT(3)
> +#define		VPU_HDMI_OUTPUT_CRYCB           (0 << 5)
> +#define		VPU_HDMI_OUTPUT_YCBCR           (1 << 5)
> +#define		VPU_HDMI_OUTPUT_YCRCB           (2 << 5)
> +#define		VPU_HDMI_OUTPUT_CBCRY           (3 << 5)
> +#define		VPU_HDMI_OUTPUT_CBYCR           (4 << 5)
> +#define		VPU_HDMI_OUTPUT_CRCBY           (5 << 5)
> +#define		VPU_HDMI_WR_RATE(rate)          (((rate & 0x1f) - 1) << 8)
> +#define		VPU_HDMI_RD_RATE(rate)          (((rate & 0x1f) - 1) << 12)
>  #define ENCI_INFO_READ 0x271c
>  #define ENCP_INFO_READ 0x271d
>  #define ENCT_INFO_READ 0x271e
> @@ -1360,6 +1560,7 @@
>  #define VPU_RDARB_MODE_L1C2 0x2799
>  #define VPU_RDARB_MODE_L2C1 0x279d
>  #define VPU_WRARB_MODE_L2C1 0x27a2
> +#define		VPU_RDARB_SLAVE_TO_MASTER_PORT(dc, port) (port << (16 + dc))
>  
>  /* osd super scale */
>  #define OSDSR_HV_SIZEIN 0x3130
> @@ -1390,4 +1591,150 @@
>  #define OSDSR_YBIC_VCOEF0 0x3149
>  #define OSDSR_CBIC_VCOEF0 0x314a
>  
> +/* osd afbcd on gxtvbb */
> +#define OSD1_AFBCD_ENABLE 0x31a0
> +#define OSD1_AFBCD_MODE 0x31a1
> +#define OSD1_AFBCD_SIZE_IN 0x31a2
> +#define OSD1_AFBCD_HDR_PTR 0x31a3
> +#define OSD1_AFBCD_FRAME_PTR 0x31a4
> +#define OSD1_AFBCD_CHROMA_PTR 0x31a5
> +#define OSD1_AFBCD_CONV_CTRL 0x31a6
> +#define OSD1_AFBCD_STATUS 0x31a8
> +#define OSD1_AFBCD_PIXEL_HSCOPE 0x31a9
> +#define OSD1_AFBCD_PIXEL_VSCOPE 0x31aa
> +
> +/* add for gxm and 962e dv core2 */
> +#define DOLBY_CORE2A_SWAP_CTRL1	0x3434
> +#define DOLBY_CORE2A_SWAP_CTRL2	0x3435
> +
> +/* osd afbc on g12a */
> +#define VPU_MAFBC_BLOCK_ID 0x3a00
> +#define VPU_MAFBC_IRQ_RAW_STATUS 0x3a01
> +#define VPU_MAFBC_IRQ_CLEAR 0x3a02
> +#define VPU_MAFBC_IRQ_MASK 0x3a03
> +#define VPU_MAFBC_IRQ_STATUS 0x3a04
> +#define VPU_MAFBC_COMMAND 0x3a05
> +#define VPU_MAFBC_STATUS 0x3a06
> +#define VPU_MAFBC_SURFACE_CFG 0x3a07
> +#define VPU_MAFBC_HEADER_BUF_ADDR_LOW_S0 0x3a10
> +#define VPU_MAFBC_HEADER_BUF_ADDR_HIGH_S0 0x3a11
> +#define VPU_MAFBC_FORMAT_SPECIFIER_S0 0x3a12
> +#define VPU_MAFBC_BUFFER_WIDTH_S0 0x3a13
> +#define VPU_MAFBC_BUFFER_HEIGHT_S0 0x3a14
> +#define VPU_MAFBC_BOUNDING_BOX_X_START_S0 0x3a15
> +#define VPU_MAFBC_BOUNDING_BOX_X_END_S0 0x3a16
> +#define VPU_MAFBC_BOUNDING_BOX_Y_START_S0 0x3a17
> +#define VPU_MAFBC_BOUNDING_BOX_Y_END_S0 0x3a18
> +#define VPU_MAFBC_OUTPUT_BUF_ADDR_LOW_S0 0x3a19
> +#define VPU_MAFBC_OUTPUT_BUF_ADDR_HIGH_S0 0x3a1a
> +#define VPU_MAFBC_OUTPUT_BUF_STRIDE_S0 0x3a1b
> +#define VPU_MAFBC_PREFETCH_CFG_S0 0x3a1c
> +
> +#define VPU_MAFBC_HEADER_BUF_ADDR_LOW_S1 0x3a30
> +#define VPU_MAFBC_HEADER_BUF_ADDR_HIGH_S1 0x3a31
> +#define VPU_MAFBC_FORMAT_SPECIFIER_S1 0x3a32
> +#define VPU_MAFBC_BUFFER_WIDTH_S1 0x3a33
> +#define VPU_MAFBC_BUFFER_HEIGHT_S1 0x3a34
> +#define VPU_MAFBC_BOUNDING_BOX_X_START_S1 0x3a35
> +#define VPU_MAFBC_BOUNDING_BOX_X_END_S1 0x3a36
> +#define VPU_MAFBC_BOUNDING_BOX_Y_START_S1 0x3a37
> +#define VPU_MAFBC_BOUNDING_BOX_Y_END_S1 0x3a38
> +#define VPU_MAFBC_OUTPUT_BUF_ADDR_LOW_S1 0x3a39
> +#define VPU_MAFBC_OUTPUT_BUF_ADDR_HIGH_S1 0x3a3a
> +#define VPU_MAFBC_OUTPUT_BUF_STRIDE_S1 0x3a3b
> +#define VPU_MAFBC_PREFETCH_CFG_S1 0x3a3c
> +
> +#define VPU_MAFBC_HEADER_BUF_ADDR_LOW_S2 0x3a50
> +#define VPU_MAFBC_HEADER_BUF_ADDR_HIGH_S2 0x3a51
> +#define VPU_MAFBC_FORMAT_SPECIFIER_S2 0x3a52
> +#define VPU_MAFBC_BUFFER_WIDTH_S2 0x3a53
> +#define VPU_MAFBC_BUFFER_HEIGHT_S2 0x3a54
> +#define VPU_MAFBC_BOUNDING_BOX_X_START_S2 0x3a55
> +#define VPU_MAFBC_BOUNDING_BOX_X_END_S2 0x3a56
> +#define VPU_MAFBC_BOUNDING_BOX_Y_START_S2 0x3a57
> +#define VPU_MAFBC_BOUNDING_BOX_Y_END_S2 0x3a58
> +#define VPU_MAFBC_OUTPUT_BUF_ADDR_LOW_S2 0x3a59
> +#define VPU_MAFBC_OUTPUT_BUF_ADDR_HIGH_S2 0x3a5a
> +#define VPU_MAFBC_OUTPUT_BUF_STRIDE_S2 0x3a5b
> +#define VPU_MAFBC_PREFETCH_CFG_S2 0x3a5c
> +
> +#define VPU_MAFBC_HEADER_BUF_ADDR_LOW_S3 0x3a70
> +#define VPU_MAFBC_HEADER_BUF_ADDR_HIGH_S3 0x3a71
> +#define VPU_MAFBC_FORMAT_SPECIFIER_S3 0x3a72
> +#define VPU_MAFBC_BUFFER_WIDTH_S3 0x3a73
> +#define VPU_MAFBC_BUFFER_HEIGHT_S3 0x3a74
> +#define VPU_MAFBC_BOUNDING_BOX_X_START_S3 0x3a75
> +#define VPU_MAFBC_BOUNDING_BOX_X_END_S3 0x3a76
> +#define VPU_MAFBC_BOUNDING_BOX_Y_START_S3 0x3a77
> +#define VPU_MAFBC_BOUNDING_BOX_Y_END_S3 0x3a78
> +#define VPU_MAFBC_OUTPUT_BUF_ADDR_LOW_S3 0x3a79
> +#define VPU_MAFBC_OUTPUT_BUF_ADDR_HIGH_S3 0x3a7a
> +#define VPU_MAFBC_OUTPUT_BUF_STRIDE_S3 0x3a7b
> +#define VPU_MAFBC_PREFETCH_CFG_S3 0x3a7c
> +
> +#define DOLBY_PATH_CTRL 0x1a0c
> +#define		DOLBY_BYPASS_EN(val)            (val & 0xf)
> +#define OSD_PATH_MISC_CTRL 0x1a0e
> +#define MALI_AFBCD_TOP_CTRL 0x1a0f
> +
> +#define VIU_OSD_BLEND_CTRL 0x39b0
> +#define		VIU_OSD_BLEND_REORDER(dest, src)      ((src) << (dest * 4))
> +#define		VIU_OSD_BLEND_DIN_EN(bits)            ((bits & 0xf) << 20)
> +#define		VIU_OSD_BLEND1_DIN3_BYPASS_TO_DOUT1   BIT(24)
> +#define		VIU_OSD_BLEND1_DOUT_BYPASS_TO_BLEND2  BIT(25)
> +#define		VIU_OSD_BLEND_DIN0_BYPASS_TO_DOUT0    BIT(26)
> +#define		VIU_OSD_BLEND_BLEN2_PREMULT_EN(input) ((input & 0x3) << 27)
> +#define		VIU_OSD_BLEND_HOLD_LINES(lines)       ((u32)(lines & 0x7) << 29)
> +#define VIU_OSD_BLEND_CTRL1 0x39c0
> +#define VIU_OSD_BLEND_DIN0_SCOPE_H 0x39b1
> +#define VIU_OSD_BLEND_DIN0_SCOPE_V 0x39b2
> +#define VIU_OSD_BLEND_DIN1_SCOPE_H 0x39b3
> +#define VIU_OSD_BLEND_DIN1_SCOPE_V 0x39b4
> +#define VIU_OSD_BLEND_DIN2_SCOPE_H 0x39b5
> +#define VIU_OSD_BLEND_DIN2_SCOPE_V 0x39b6
> +#define VIU_OSD_BLEND_DIN3_SCOPE_H 0x39b7
> +#define VIU_OSD_BLEND_DIN3_SCOPE_V 0x39b8
> +#define VIU_OSD_BLEND_DUMMY_DATA0 0x39b9
> +#define VIU_OSD_BLEND_DUMMY_ALPHA 0x39ba
> +#define VIU_OSD_BLEND_BLEND0_SIZE 0x39bb
> +#define VIU_OSD_BLEND_BLEND1_SIZE 0x39bc
> +#define VIU_OSD_BLEND_RO_CURRENT_XY 0x39bf
> +
> +#define VPP_OUT_H_V_SIZE 0x1da5
> +
> +#define VPP_VD2_HDR_IN_SIZE 0x1df0
> +#define VPP_OSD1_IN_SIZE 0x1df1
> +#define VPP_GCLK_CTRL2 0x1df2
> +#define VD2_PPS_DUMMY_DATA 0x1df4
> +#define VPP_OSD1_BLD_H_SCOPE 0x1df5
> +#define VPP_OSD1_BLD_V_SCOPE 0x1df6
> +#define VPP_OSD2_BLD_H_SCOPE 0x1df7
> +#define VPP_OSD2_BLD_V_SCOPE 0x1df8
> +#define VPP_WRBAK_CTRL 0x1df9
> +#define VPP_SLEEP_CTRL 0x1dfa
> +#define VD1_BLEND_SRC_CTRL 0x1dfb
> +#define VD2_BLEND_SRC_CTRL 0x1dfc
> +#define		VD_BLEND_PREBLD_SRC_VD1         (1 << 0)
> +#define		VD_BLEND_PREBLD_SRC_VD2         (2 << 0)
> +#define		VD_BLEND_PREBLD_SRC_OSD1        (3 << 0)
> +#define		VD_BLEND_PREBLD_SRC_OSD2        (4 << 0)
> +#define		VD_BLEND_PREBLD_PREMULT_EN      BIT(4)
> +#define		VD_BLEND_POSTBLD_SRC_VD1        (1 << 8)
> +#define		VD_BLEND_POSTBLD_SRC_VD2        (2 << 8)
> +#define		VD_BLEND_POSTBLD_SRC_OSD1       (3 << 8)
> +#define		VD_BLEND_POSTBLD_SRC_OSD2       (4 << 8)
> +#define		VD_BLEND_POSTBLD_PREMULT_EN     BIT(16)
> +#define OSD1_BLEND_SRC_CTRL 0x1dfd
> +#define OSD2_BLEND_SRC_CTRL 0x1dfe
> +#define		OSD_BLEND_POSTBLD_SRC_VD1       (1 << 8)
> +#define		OSD_BLEND_POSTBLD_SRC_VD2       (2 << 8)
> +#define		OSD_BLEND_POSTBLD_SRC_OSD1      (3 << 8)
> +#define		OSD_BLEND_POSTBLD_SRC_OSD2      (4 << 8)
> +#define		OSD_BLEND_PATH_SEL_ENABLE       BIT(20)
> +
> +#define VPP_POST_BLEND_BLEND_DUMMY_DATA 0x3968
> +#define VPP_POST_BLEND_DUMMY_ALPHA 0x3969
> +#define VPP_RDARB_MODE 0x3978
> +#define VPP_RDARB_REQEN_SLV 0x3979
> +
>  #endif /* __MESON_REGISTERS_H */
> diff --git a/drivers/video/meson/meson_vclk.c b/drivers/video/meson/meson_vclk.c
> index 693e0ebe39..0f628e920b 100644
> --- a/drivers/video/meson/meson_vclk.c
> +++ b/drivers/video/meson/meson_vclk.c
> @@ -68,14 +68,20 @@ enum {
>  #define CTS_HDMI_SYS_EN		BIT(8)
>  
>  #define HHI_HDMI_PLL_CNTL	0x320 /* 0xc8 offset in data sheet */
> +#define HHI_HDMI_PLL_CNTL_EN	BIT(30)
>  #define HHI_HDMI_PLL_CNTL2	0x324 /* 0xc9 offset in data sheet */
>  #define HHI_HDMI_PLL_CNTL3	0x328 /* 0xca offset in data sheet */
>  #define HHI_HDMI_PLL_CNTL4	0x32C /* 0xcb offset in data sheet */
>  #define HHI_HDMI_PLL_CNTL5	0x330 /* 0xcc offset in data sheet */
>  #define HHI_HDMI_PLL_CNTL6	0x334 /* 0xcd offset in data sheet */
> +#define HHI_HDMI_PLL_CNTL7	0x338 /* 0xce offset in data sheet */
>  
>  #define HDMI_PLL_RESET		BIT(28)
> +#define HDMI_PLL_RESET_G12A	BIT(29)
>  #define HDMI_PLL_LOCK		BIT(31)
> +#define HDMI_PLL_LOCK_G12A	(3 << 30)
> +
> +#define FREQ_1000_1001(_freq)	DIV_ROUND_CLOSEST(_freq * 1000, 1001)
>  
>  /* VID PLL Dividers */
>  enum {
> @@ -206,8 +212,6 @@ static void meson_venci_cvbs_clock_config(struct meson_vpu_priv *priv)
>  {
>  	unsigned int val;
>  
> -	debug("%s:%d\n", __func__, __LINE__);
> -
>  	/* Setup PLL to output 1.485GHz */
>  	if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXBB)) {
>  		hhi_write(HHI_HDMI_PLL_CNTL, 0x5800023d);
> @@ -217,6 +221,10 @@ static void meson_venci_cvbs_clock_config(struct meson_vpu_priv *priv)
>  		hhi_write(HHI_HDMI_PLL_CNTL5, 0x71486980);
>  		hhi_write(HHI_HDMI_PLL_CNTL6, 0x00000e55);
>  		hhi_write(HHI_HDMI_PLL_CNTL, 0x4800023d);
> +
> +		/* Poll for lock bit */
> +		readl_poll_timeout(priv->hhi_base + HHI_HDMI_PLL_CNTL, val,
> +				   (val & HDMI_PLL_LOCK), 10);
>  	} else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM) ||
>  		   meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL)) {
>  		hhi_write(HHI_HDMI_PLL_CNTL, 0x4000027b);
> @@ -231,13 +239,26 @@ static void meson_venci_cvbs_clock_config(struct meson_vpu_priv *priv)
>  				HDMI_PLL_RESET, HDMI_PLL_RESET);
>  		hhi_update_bits(HHI_HDMI_PLL_CNTL,
>  				HDMI_PLL_RESET, 0);
> -	}
>  
> -	debug("%s:%d\n", __func__, __LINE__);
> +		/* Poll for lock bit */
> +		readl_poll_timeout(priv->hhi_base + HHI_HDMI_PLL_CNTL, val,
> +				   (val & HDMI_PLL_LOCK), 10);
> +	} else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
> +		hhi_write(HHI_HDMI_PLL_CNTL, 0x1a0504f7);
> +		hhi_write(HHI_HDMI_PLL_CNTL2, 0x00010000);
> +		hhi_write(HHI_HDMI_PLL_CNTL3, 0x00000000);
> +		hhi_write(HHI_HDMI_PLL_CNTL4, 0x6a28dc00);
> +		hhi_write(HHI_HDMI_PLL_CNTL5, 0x65771290);
> +		hhi_write(HHI_HDMI_PLL_CNTL6, 0x39272000);
> +		hhi_write(HHI_HDMI_PLL_CNTL7, 0x56540000);
> +		hhi_write(HHI_HDMI_PLL_CNTL, 0x3a0504f7);
> +		hhi_write(HHI_HDMI_PLL_CNTL, 0x1a0504f7);
>  
> -	/* Poll for lock bit */
> -	readl_poll_timeout(priv->hhi_base + HHI_HDMI_PLL_CNTL, val,
> -			   (val & HDMI_PLL_LOCK), 10);
> +		/* Poll for lock bit */
> +		readl_poll_timeout(priv->hhi_base + HHI_HDMI_PLL_CNTL, val,
> +			((val & HDMI_PLL_LOCK_G12A) == HDMI_PLL_LOCK_G12A),
> +			10);
> +	}
>  
>  	/* Disable VCLK2 */
>  	hhi_update_bits(HHI_VIID_CLK_CNTL, VCLK2_EN, 0);
> @@ -250,8 +271,13 @@ static void meson_venci_cvbs_clock_config(struct meson_vpu_priv *priv)
>  			VCLK2_DIV_MASK, (55 - 1));
>  
>  	/* select vid_pll for vclk2 */
> -	hhi_update_bits(HHI_VIID_CLK_CNTL,
> -			VCLK2_SEL_MASK, (4 << VCLK2_SEL_SHIFT));
> +	if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
> +		hhi_update_bits(HHI_VIID_CLK_CNTL,
> +				VCLK2_SEL_MASK, (0 << VCLK2_SEL_SHIFT));
> +	else
> +		hhi_update_bits(HHI_VIID_CLK_CNTL,
> +				VCLK2_SEL_MASK, (4 << VCLK2_SEL_SHIFT));
> +
>  	/* enable vclk2 gate */
>  	hhi_update_bits(HHI_VIID_CLK_CNTL, VCLK2_EN, VCLK2_EN);
>  
> @@ -282,14 +308,12 @@ static void meson_venci_cvbs_clock_config(struct meson_vpu_priv *priv)
>  	/* enable vdac_clk */
>  	hhi_update_bits(HHI_VID_CLK_CNTL2,
>  			CTS_VDAC_EN, CTS_VDAC_EN);
> -
> -	debug("%s:%d\n", __func__, __LINE__);
>  }
>  
>  enum {
>  /* PLL	O1 O2 O3 VP DV     EN TX */
>  /* 4320 /4 /4 /1 /5 /1  => /2 /2 */
> -	MESON_VCLK_HDMI_ENCI_54000 = 1,
> +	MESON_VCLK_HDMI_ENCI_54000 = 0,
>  /* 4320 /4 /4 /1 /5 /1  => /1 /2 */
>  	MESON_VCLK_HDMI_DDR_54000,
>  /* 2970 /4 /1 /1 /5 /1  => /1 /2 */
> @@ -305,6 +329,7 @@ enum {
>  };
>  
>  struct meson_vclk_params {
> +	unsigned int pixel_freq;
>  	unsigned int pll_base_freq;
>  	unsigned int pll_od1;
>  	unsigned int pll_od2;
> @@ -313,6 +338,7 @@ struct meson_vclk_params {
>  	unsigned int vclk_div;
>  } params[] = {
>  	[MESON_VCLK_HDMI_ENCI_54000] = {
> +		.pixel_freq = 54000,
>  		.pll_base_freq = 4320000,
>  		.pll_od1 = 4,
>  		.pll_od2 = 4,
> @@ -321,6 +347,7 @@ struct meson_vclk_params {
>  		.vclk_div = 1,
>  	},
>  	[MESON_VCLK_HDMI_DDR_54000] = {
> +		.pixel_freq = 54000,
>  		.pll_base_freq = 4320000,
>  		.pll_od1 = 4,
>  		.pll_od2 = 4,
> @@ -329,6 +356,7 @@ struct meson_vclk_params {
>  		.vclk_div = 1,
>  	},
>  	[MESON_VCLK_HDMI_DDR_148500] = {
> +		.pixel_freq = 148500,
>  		.pll_base_freq = 2970000,
>  		.pll_od1 = 4,
>  		.pll_od2 = 1,
> @@ -337,6 +365,7 @@ struct meson_vclk_params {
>  		.vclk_div = 1,
>  	},
>  	[MESON_VCLK_HDMI_74250] = {
> +		.pixel_freq = 74250,
>  		.pll_base_freq = 2970000,
>  		.pll_od1 = 2,
>  		.pll_od2 = 2,
> @@ -345,6 +374,7 @@ struct meson_vclk_params {
>  		.vclk_div = 1,
>  	},
>  	[MESON_VCLK_HDMI_148500] = {
> +		.pixel_freq = 148500,
>  		.pll_base_freq = 2970000,
>  		.pll_od1 = 1,
>  		.pll_od2 = 2,
> @@ -353,14 +383,16 @@ struct meson_vclk_params {
>  		.vclk_div = 1,
>  	},
>  	[MESON_VCLK_HDMI_297000] = {
> -		.pll_base_freq = 2970000,
> -		.pll_od1 = 1,
> +		.pixel_freq = 297000,
> +		.pll_base_freq = 5940000,
> +		.pll_od1 = 2,
>  		.pll_od2 = 1,
>  		.pll_od3 = 1,
>  		.vid_pll_div = VID_PLL_DIV_5,
>  		.vclk_div = 2,
>  	},
>  	[MESON_VCLK_HDMI_594000] = {
> +		.pixel_freq = 594000,
>  		.pll_base_freq = 5940000,
>  		.pll_od1 = 1,
>  		.pll_od2 = 1,
> @@ -368,6 +400,7 @@ struct meson_vclk_params {
>  		.vid_pll_div = VID_PLL_DIV_5,
>  		.vclk_div = 1,
>  	},
> +	{ /* sentinel */ },
>  };
>  
>  static inline unsigned int pll_od_to_reg(unsigned int od)
> @@ -431,6 +464,50 @@ void meson_hdmi_pll_set_params(struct meson_vpu_priv *priv, unsigned int m,
>  		/* Poll for lock bit */
>  		readl_poll_timeout(priv->hhi_base + HHI_HDMI_PLL_CNTL, val,
>  				   (val & HDMI_PLL_LOCK), 10);
> +	} else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
> +		hhi_write(HHI_HDMI_PLL_CNTL, 0x0b3a0400 | m);
> +
> +		/* Enable and reset */
> +		hhi_update_bits(HHI_HDMI_PLL_CNTL, 0x3 << 28, 0x3 << 28);
> +
> +		hhi_write(HHI_HDMI_PLL_CNTL2, frac);
> +		hhi_write(HHI_HDMI_PLL_CNTL3, 0x00000000);
> +
> +		/* G12A HDMI PLL Needs specific parameters for 5.4GHz */
> +		if (m >= 0xf7) {
> +			if (frac < 0x10000) {
> +				hhi_write(HHI_HDMI_PLL_CNTL4, 0x6a685c00);
> +				hhi_write(HHI_HDMI_PLL_CNTL5, 0x11551293);
> +			} else {
> +				hhi_write(HHI_HDMI_PLL_CNTL4, 0xea68dc00);
> +				hhi_write(HHI_HDMI_PLL_CNTL5, 0x65771290);
> +			}
> +			hhi_write(HHI_HDMI_PLL_CNTL6, 0x39272000);
> +			hhi_write(HHI_HDMI_PLL_CNTL7, 0x55540000);
> +		} else {
> +			hhi_write(HHI_HDMI_PLL_CNTL4, 0x0a691c00);
> +			hhi_write(HHI_HDMI_PLL_CNTL5, 0x33771290);
> +			hhi_write(HHI_HDMI_PLL_CNTL6, 0x39270000);
> +			hhi_write(HHI_HDMI_PLL_CNTL7, 0x50540000);
> +		}
> +
> +		do {
> +			/* Reset PLL */
> +			hhi_update_bits(HHI_HDMI_PLL_CNTL,
> +					HDMI_PLL_RESET_G12A,
> +					HDMI_PLL_RESET_G12A);
> +
> +			/* UN-Reset PLL */
> +			hhi_update_bits(HHI_HDMI_PLL_CNTL,
> +					HDMI_PLL_RESET_G12A, 0);
> +
> +			/* Poll for lock bits */
> +			if (!readl_poll_timeout(
> +					priv->hhi_base + HHI_HDMI_PLL_CNTL, val,
> +					((val & HDMI_PLL_LOCK_G12A)
> +						== HDMI_PLL_LOCK_G12A), 100))
> +				break;
> +		} while (1);
>  	}
>  
>  	if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXBB))
> @@ -440,6 +517,9 @@ void meson_hdmi_pll_set_params(struct meson_vpu_priv *priv, unsigned int m,
>  		 meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL))
>  		hhi_update_bits(HHI_HDMI_PLL_CNTL3,
>  				3 << 21, pll_od_to_reg(od1) << 21);
> +	else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
> +		hhi_update_bits(HHI_HDMI_PLL_CNTL,
> +				3 << 16, pll_od_to_reg(od1) << 16);
>  
>  	if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXBB))
>  		hhi_update_bits(HHI_HDMI_PLL_CNTL2,
> @@ -448,6 +528,9 @@ void meson_hdmi_pll_set_params(struct meson_vpu_priv *priv, unsigned int m,
>  		 meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL))
>  		hhi_update_bits(HHI_HDMI_PLL_CNTL3,
>  				3 << 23, pll_od_to_reg(od2) << 23);
> +	else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
> +		hhi_update_bits(HHI_HDMI_PLL_CNTL,
> +				3 << 18, pll_od_to_reg(od2) << 18);
>  
>  	if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXBB))
>  		hhi_update_bits(HHI_HDMI_PLL_CNTL2,
> @@ -456,6 +539,9 @@ void meson_hdmi_pll_set_params(struct meson_vpu_priv *priv, unsigned int m,
>  		 meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL))
>  		hhi_update_bits(HHI_HDMI_PLL_CNTL3,
>  				3 << 19, pll_od_to_reg(od3) << 19);
> +	else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
> +		hhi_update_bits(HHI_HDMI_PLL_CNTL,
> +				3 << 20, pll_od_to_reg(od3) << 20);
>  }
>  
>  #define XTAL_FREQ 24000
> @@ -472,6 +558,7 @@ static unsigned int meson_hdmi_pll_get_m(struct meson_vpu_priv *priv,
>  
>  #define HDMI_FRAC_MAX_GXBB	4096
>  #define HDMI_FRAC_MAX_GXL	1024
> +#define HDMI_FRAC_MAX_G12A	131072
>  
>  static unsigned int meson_hdmi_pll_get_frac(struct meson_vpu_priv *priv,
>  					    unsigned int m,
> @@ -488,6 +575,9 @@ static unsigned int meson_hdmi_pll_get_frac(struct meson_vpu_priv *priv,
>  		parent_freq *= 2;
>  	}
>  
> +	if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
> +		frac_max = HDMI_FRAC_MAX_G12A;
> +
>  	/* We can have a perfect match !*/
>  	if (pll_freq / m == parent_freq &&
>  	    pll_freq % m == 0)
> @@ -519,6 +609,12 @@ static bool meson_hdmi_pll_validate_params(struct meson_vpu_priv *priv,
>  			return false;
>  		if (frac >= HDMI_FRAC_MAX_GXL)
>  			return false;
> +	} else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
> +		/* Empiric supported min/max dividers */
> +		if (m < 106 || m > 247)
> +			return false;
> +		if (frac >= HDMI_FRAC_MAX_G12A)
> +			return false;
>  	}
>  
>  	return true;
> @@ -595,8 +691,10 @@ meson_vclk_set(struct meson_vpu_priv *priv, unsigned int pll_base_freq,
>  	       unsigned int od1, unsigned int od2, unsigned int od3,
>  	       unsigned int vid_pll_div, unsigned int vclk_div,
>  	       unsigned int hdmi_tx_div, unsigned int venc_div,
> -	       bool hdmi_use_enci)
> +	       bool hdmi_use_enci, bool vic_alternate_clock)
>  {
> +	unsigned int m = 0, frac = 0;
> +
>  	/* Set HDMI-TX sys clock */
>  	hhi_update_bits(HHI_HDMI_CLK_CNTL,
>  			CTS_HDMI_SYS_SEL_MASK, 0);
> @@ -611,34 +709,55 @@ meson_vclk_set(struct meson_vpu_priv *priv, unsigned int pll_base_freq,
>  	} else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXBB)) {
>  		switch (pll_base_freq) {
>  		case 2970000:
> -			meson_hdmi_pll_set_params(priv, 0x3d, 0xe00,
> -						  od1, od2, od3);
> +			m = 0x3d;
> +			frac = vic_alternate_clock ? 0xd02 : 0xe00;
>  			break;
>  		case 4320000:
> -			meson_hdmi_pll_set_params(priv, 0x5a, 0,
> -						  od1, od2, od3);
> +			m = vic_alternate_clock ? 0x59 : 0x5a;
> +			frac = vic_alternate_clock ? 0xe8f : 0;
>  			break;
>  		case 5940000:
> -			meson_hdmi_pll_set_params(priv, 0x7b, 0xc00,
> -						  od1, od2, od3);
> +			m = 0x7b;
> +			frac = vic_alternate_clock ? 0xa05 : 0xc00;
>  			break;
>  		}
> +
> +		meson_hdmi_pll_set_params(priv, m, frac, od1, od2, od3);
>  	} else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM) ||
>  		   meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL)) {
>  		switch (pll_base_freq) {
>  		case 2970000:
> -			meson_hdmi_pll_set_params(priv, 0x7b, 0x300,
> -						  od1, od2, od3);
> +			m = 0x7b;
> +			frac = vic_alternate_clock ? 0x281 : 0x300;
> +			break;
> +		case 4320000:
> +			m = vic_alternate_clock ? 0xb3 : 0xb4;
> +			frac = vic_alternate_clock ? 0x347 : 0;
> +			break;
> +		case 5940000:
> +			m = 0xf7;
> +			frac = vic_alternate_clock ? 0x102 : 0x200;
> +			break;
> +		}
> +
> +		meson_hdmi_pll_set_params(priv, m, frac, od1, od2, od3);
> +	} else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
> +		switch (pll_base_freq) {
> +		case 2970000:
> +			m = 0x7b;
> +			frac = vic_alternate_clock ? 0x140b4 : 0x18000;
>  			break;
>  		case 4320000:
> -			meson_hdmi_pll_set_params(priv, 0xb4, 0,
> -						  od1, od2, od3);
> +			m = vic_alternate_clock ? 0xb3 : 0xb4;
> +			frac = vic_alternate_clock ? 0x1a3ee : 0;
>  			break;
>  		case 5940000:
> -			meson_hdmi_pll_set_params(priv, 0xf7, 0x200,
> -						  od1, od2, od3);
> +			m = 0xf7;
> +			frac = vic_alternate_clock ? 0x8148 : 0x10000;
>  			break;
>  		}
> +
> +		meson_hdmi_pll_set_params(priv, m, frac, od1, od2, od3);
>  	}
>  
>  	/* Setup vid_pll divider */
> @@ -803,6 +922,7 @@ static void meson_vclk_setup(struct meson_vpu_priv *priv, unsigned int target,
>  			     unsigned int vclk_freq, unsigned int venc_freq,
>  			     unsigned int dac_freq, bool hdmi_use_enci)
>  {
> +	bool vic_alternate_clock = false;
>  	unsigned int freq;
>  	unsigned int hdmi_tx_div;
>  	unsigned int venc_div;
> @@ -820,8 +940,7 @@ static void meson_vclk_setup(struct meson_vpu_priv *priv, unsigned int target,
>  		 * - encp encoder
>  		 */
>  		meson_vclk_set(priv, vclk_freq * 10, 0, 0, 0,
> -			       VID_PLL_DIV_5, 2, 1, 1, false);
> -
> +			       VID_PLL_DIV_5, 2, 1, 1, false, false);
>  		return;
>  	}
>  
> @@ -841,31 +960,35 @@ static void meson_vclk_setup(struct meson_vpu_priv *priv, unsigned int target,
>  		return;
>  	}
>  
> -	switch (vclk_freq) {
> -	case 54000:
> -		if (hdmi_use_enci)
> -			freq = MESON_VCLK_HDMI_ENCI_54000;
> -		else
> -			freq = MESON_VCLK_HDMI_DDR_54000;
> -		break;
> -	case 74250:
> -		freq = MESON_VCLK_HDMI_74250;
> -		break;
> -	case 148500:
> -		if (dac_freq != 148500)
> -			freq = MESON_VCLK_HDMI_DDR_148500;
> -		else
> -			freq = MESON_VCLK_HDMI_148500;
> -		break;
> -	case 297000:
> -		freq = MESON_VCLK_HDMI_297000;
> -		break;
> -	case 594000:
> -		freq = MESON_VCLK_HDMI_594000;
> -		break;
> -	default:
> -		printf("Fatal Error, invalid HDMI vclk freq %d\n",
> -		       vclk_freq);
> +	for (freq = 0 ; params[freq].pixel_freq ; ++freq) {
> +		if (vclk_freq == params[freq].pixel_freq ||
> +		    vclk_freq == FREQ_1000_1001(params[freq].pixel_freq)) {
> +			if (vclk_freq != params[freq].pixel_freq)
> +				vic_alternate_clock = true;
> +			else
> +				vic_alternate_clock = false;
> +
> +			if (freq == MESON_VCLK_HDMI_ENCI_54000 &&
> +			    !hdmi_use_enci)
> +				continue;
> +
> +			if (freq == MESON_VCLK_HDMI_DDR_54000 &&
> +			    hdmi_use_enci)
> +				continue;
> +
> +			if (freq == MESON_VCLK_HDMI_DDR_148500 &&
> +			    dac_freq == vclk_freq)
> +				continue;
> +
> +			if (freq == MESON_VCLK_HDMI_148500 &&
> +			    dac_freq != vclk_freq)
> +				continue;
> +			break;
> +		}
> +	}
> +
> +	if (!params[freq].pixel_freq) {
> +		pr_err("Fatal Error, invalid HDMI vclk freq %d\n", vclk_freq);
>  		return;
>  	}
>  
> @@ -873,7 +996,7 @@ static void meson_vclk_setup(struct meson_vpu_priv *priv, unsigned int target,
>  		       params[freq].pll_od1, params[freq].pll_od2,
>  		       params[freq].pll_od3, params[freq].vid_pll_div,
>  		       params[freq].vclk_div, hdmi_tx_div, venc_div,
> -		       hdmi_use_enci);
> +		       hdmi_use_enci, vic_alternate_clock);
>  }
>  
>  void meson_vpu_setup_vclk(struct udevice *dev,
> diff --git a/drivers/video/meson/meson_venc.c b/drivers/video/meson/meson_venc.c
> index d137dde8e2..5da4b3f096 100644
> --- a/drivers/video/meson/meson_venc.c
> +++ b/drivers/video/meson/meson_venc.c
> @@ -23,7 +23,9 @@ enum meson_venc_source {
>  };
>  
>  #define HHI_VDAC_CNTL0		0x2F4 /* 0xbd offset in data sheet */
> +#define HHI_VDAC_CNTL0_G12A	0x2EC /* 0xbb offset in data sheet */
>  #define HHI_VDAC_CNTL1		0x2F8 /* 0xbe offset in data sheet */
> +#define HHI_VDAC_CNTL1_G12A	0x2F0 /* 0xbc offset in data sheet */
>  
>  struct meson_cvbs_enci_mode {
>  	unsigned int mode_tag;
> @@ -175,7 +177,7 @@ union meson_hdmi_venc_mode meson_hdmi_enci_mode_480i = {
>  		.hso_end = 129,
>  		.vso_even = 3,
>  		.vso_odd = 260,
> -		.macv_max_amp = 0x810b,
> +		.macv_max_amp = 0xb,
>  		.video_prog_mode = 0xf0,
>  		.video_mode = 0x8,
>  		.sch_adjust = 0x20,
> @@ -195,7 +197,7 @@ union meson_hdmi_venc_mode meson_hdmi_enci_mode_576i = {
>  		.hso_end = 129,
>  		.vso_even = 3,
>  		.vso_odd = 260,
> -		.macv_max_amp = 8107,
> +		.macv_max_amp = 0x7,
>  		.video_prog_mode = 0xff,
>  		.video_mode = 0x13,
>  		.sch_adjust = 0x28,
> @@ -774,12 +776,13 @@ static void meson_venc_hdmi_mode_set(struct meson_vpu_priv *priv,
>  	unsigned int eof_lines;
>  	unsigned int sof_lines;
>  	unsigned int vsync_lines;
> +	u32 reg;
>  
>  	/* Use VENCI for 480i and 576i and double HDMI pixels */
>  	if (mode->flags & DISPLAY_FLAGS_DOUBLECLK) {
> -		venc_hdmi_latency = 1;
>  		hdmi_repeat = true;
>  		use_enci = true;
> +		venc_hdmi_latency = 1;
>  	}
>  
>  	meson_venc_hdmi_get_dmt_vmode(mode, &vmode_dmt);
> @@ -850,8 +853,11 @@ static void meson_venc_hdmi_mode_set(struct meson_vpu_priv *priv,
>  		unsigned int lines_f1;
>  
>  		/* CVBS Filter settings */
> -		writel(0x12, priv->io_base + _REG(ENCI_CFILT_CTRL));
> -		writel(0x12, priv->io_base + _REG(ENCI_CFILT_CTRL2));
> +		writel(ENCI_CFILT_CMPT_SEL_HIGH | 0x10,
> +		       priv->io_base + _REG(ENCI_CFILT_CTRL));
> +		writel(ENCI_CFILT_CMPT_CR_DLY(2) |
> +		       ENCI_CFILT_CMPT_CB_DLY(1),
> +		       priv->io_base + _REG(ENCI_CFILT_CTRL2));
>  
>  		/* Digital Video Select : Interlace, clk27 clk, external */
>  		writel(0, priv->io_base + _REG(VENC_DVI_SETTING));
> @@ -873,7 +879,8 @@ static void meson_venc_hdmi_mode_set(struct meson_vpu_priv *priv,
>  		       priv->io_base + _REG(ENCI_SYNC_VSO_ODDLN));
>  
>  		/* Macrovision max amplitude change */
> -		writel(vmode->enci.macv_max_amp,
> +		writel(ENCI_MACV_MAX_AMP_ENABLE_CHANGE |
> +		       ENCI_MACV_MAX_AMP_VAL(vmode->enci.macv_max_amp),
>  		       priv->io_base + _REG(ENCI_MACV_MAX_AMP));
>  
>  		/* Video mode */
> @@ -882,7 +889,8 @@ static void meson_venc_hdmi_mode_set(struct meson_vpu_priv *priv,
>  		writel(vmode->enci.video_mode,
>  		       priv->io_base + _REG(ENCI_VIDEO_MODE));
>  
> -		/* Advanced Video Mode :
> +		/*
> +		 * Advanced Video Mode :
>  		 * Demux shifting 0x2
>  		 * Blank line end at line17/22
>  		 * High bandwidth Luma Filter
> @@ -890,7 +898,10 @@ static void meson_venc_hdmi_mode_set(struct meson_vpu_priv *priv,
>  		 * Bypass luma low pass filter
>  		 * No macrovision on CSYNC
>  		 */
> -		writel(0x26, priv->io_base + _REG(ENCI_VIDEO_MODE_ADV));
> +		writel(ENCI_VIDEO_MODE_ADV_DMXMD(2) |
> +		       ENCI_VIDEO_MODE_ADV_VBICTL_LINE_17_22 |
> +		       ENCI_VIDEO_MODE_ADV_YBW_HIGH,
> +		       priv->io_base + _REG(ENCI_VIDEO_MODE_ADV));
>  
>  		writel(vmode->enci.sch_adjust,
>  		       priv->io_base + _REG(ENCI_VIDEO_SCH));
> @@ -905,8 +916,17 @@ static void meson_venc_hdmi_mode_set(struct meson_vpu_priv *priv,
>  		/* UNreset Interlaced TV Encoder */
>  		writel(0, priv->io_base + _REG(ENCI_DBG_PX_RST));
>  
> -		/* Enable Vfifo2vd, Y_Cb_Y_Cr select */
> -		writel(0x4e01, priv->io_base + _REG(ENCI_VFIFO2VD_CTL));
> +		/*
> +		 * Enable Vfifo2vd and set Y_Cb_Y_Cr:
> +		 * Corresponding value:
> +		 * Y  => 00 or 10
> +		 * Cb => 01
> +		 * Cr => 11
> +		 * Ex: 0x4e => 01001110 would mean Cb/Y/Cr/Y
> +		 */
> +		writel(ENCI_VFIFO2VD_CTL_ENABLE |
> +		       ENCI_VFIFO2VD_CTL_VD_SEL(0x4e),
> +		       priv->io_base + _REG(ENCI_VFIFO2VD_CTL));
>  
>  		/* Timings */
>  		writel(vmode->enci.pixel_start,
> @@ -928,7 +948,8 @@ static void meson_venc_hdmi_mode_set(struct meson_vpu_priv *priv,
>  		meson_vpp_setup_mux(priv, MESON_VIU_VPP_MUX_ENCI);
>  
>  		/* Interlace video enable */
> -		writel(1, priv->io_base + _REG(ENCI_VIDEO_EN));
> +		writel(ENCI_VIDEO_EN_ENABLE,
> +		       priv->io_base + _REG(ENCI_VIDEO_EN));
>  
>  		lines_f0 = mode->vback_porch.typ + mode->vactive.typ +
>  			   mode->vback_porch.typ + mode->vsync_len.typ;
> @@ -1177,7 +1198,8 @@ static void meson_venc_hdmi_mode_set(struct meson_vpu_priv *priv,
>  		writel(1, priv->io_base + _REG(ENCP_VIDEO_EN));
>  
>  		/* Set DE signal's polarity is active high */
> -		writel_bits(BIT(14), BIT(14),
> +		writel_bits(ENCP_VIDEO_MODE_DE_V_HIGH,
> +			    ENCP_VIDEO_MODE_DE_V_HIGH,
>  			    priv->io_base + _REG(ENCP_VIDEO_MODE));
>  
>  		/* Program DE timing */
> @@ -1302,21 +1324,52 @@ static void meson_venc_hdmi_mode_set(struct meson_vpu_priv *priv,
>  		meson_vpp_setup_mux(priv, MESON_VIU_VPP_MUX_ENCP);
>  	}
>  
> -	writel((use_enci ? 1 : 2) |
> -		       (mode->flags & DISPLAY_FLAGS_HSYNC_HIGH ? 1 << 2 : 0) |
> -		       (mode->flags & DISPLAY_FLAGS_VSYNC_HIGH ? 1 << 3 : 0) |
> -		       4 << 5 |
> -		       (venc_repeat ? 1 << 8 : 0) |
> -		       (hdmi_repeat ? 1 << 12 : 0),
> -		       priv->io_base + _REG(VPU_HDMI_SETTING));
> +	/* Set VPU HDMI setting */
> +	/* Select ENCP or ENCI data to HDMI */
> +	if (use_enci)
> +		reg = VPU_HDMI_ENCI_DATA_TO_HDMI;
> +	else
> +		reg = VPU_HDMI_ENCP_DATA_TO_HDMI;
> +
> +	/* Invert polarity of HSYNC from VENC */
> +	if (mode->flags & DISPLAY_FLAGS_HSYNC_HIGH)
> +		reg |= VPU_HDMI_INV_HSYNC;
> +
> +	/* Invert polarity of VSYNC from VENC */
> +	if (mode->flags & DISPLAY_FLAGS_VSYNC_HIGH)
> +		reg |= VPU_HDMI_INV_VSYNC;
> +
> +	/* Output data format: CbYCr */
> +	reg |= VPU_HDMI_OUTPUT_CBYCR;
> +
> +	/*
> +	 * Write rate to the async FIFO between VENC and HDMI.
> +	 * One write every 2 wr_clk.
> +	 */
> +	if (venc_repeat)
> +		reg |= VPU_HDMI_WR_RATE(2);
> +
> +	/*
> +	 * Read rate to the async FIFO between VENC and HDMI.
> +	 * One read every 2 wr_clk.
> +	 */
> +	if (hdmi_repeat)
> +		reg |= VPU_HDMI_RD_RATE(2);
> +
> +	writel(reg, priv->io_base + _REG(VPU_HDMI_SETTING));
>  }
>  
>  static void meson_venci_cvbs_mode_set(struct meson_vpu_priv *priv,
>  				      struct meson_cvbs_enci_mode *mode)
>  {
> +	u32 reg;
> +
>  	/* CVBS Filter settings */
> -	writel(0x12, priv->io_base + _REG(ENCI_CFILT_CTRL));
> -	writel(0x12, priv->io_base + _REG(ENCI_CFILT_CTRL2));
> +	writel(ENCI_CFILT_CMPT_SEL_HIGH | 0x10,
> +	       priv->io_base + _REG(ENCI_CFILT_CTRL));
> +	writel(ENCI_CFILT_CMPT_CR_DLY(2) |
> +	       ENCI_CFILT_CMPT_CB_DLY(1),
> +	       priv->io_base + _REG(ENCI_CFILT_CTRL2));
>  
>  	/* Digital Video Select : Interlace, clk27 clk, external */
>  	writel(0, priv->io_base + _REG(VENC_DVI_SETTING));
> @@ -1338,7 +1391,8 @@ static void meson_venci_cvbs_mode_set(struct meson_vpu_priv *priv,
>  	       priv->io_base + _REG(ENCI_SYNC_VSO_ODDLN));
>  
>  	/* Macrovision max amplitude change */
> -	writel(0x8100 + mode->macv_max_amp,
> +	writel(ENCI_MACV_MAX_AMP_ENABLE_CHANGE |
> +	       ENCI_MACV_MAX_AMP_VAL(mode->macv_max_amp),
>  	       priv->io_base + _REG(ENCI_MACV_MAX_AMP));
>  
>  	/* Video mode */
> @@ -1347,7 +1401,8 @@ static void meson_venci_cvbs_mode_set(struct meson_vpu_priv *priv,
>  	writel(mode->video_mode,
>  	       priv->io_base + _REG(ENCI_VIDEO_MODE));
>  
> -	/* Advanced Video Mode :
> +	/*
> +	 * Advanced Video Mode :
>  	 * Demux shifting 0x2
>  	 * Blank line end at line17/22
>  	 * High bandwidth Luma Filter
> @@ -1355,7 +1410,10 @@ static void meson_venci_cvbs_mode_set(struct meson_vpu_priv *priv,
>  	 * Bypass luma low pass filter
>  	 * No macrovision on CSYNC
>  	 */
> -	writel(0x26, priv->io_base + _REG(ENCI_VIDEO_MODE_ADV));
> +	writel(ENCI_VIDEO_MODE_ADV_DMXMD(2) |
> +	       ENCI_VIDEO_MODE_ADV_VBICTL_LINE_17_22 |
> +	       ENCI_VIDEO_MODE_ADV_YBW_HIGH,
> +	       priv->io_base + _REG(ENCI_VIDEO_MODE_ADV));
>  
>  	writel(mode->sch_adjust, priv->io_base + _REG(ENCI_VIDEO_SCH));
>  
> @@ -1387,16 +1445,50 @@ static void meson_venci_cvbs_mode_set(struct meson_vpu_priv *priv,
>  	/* UNreset Interlaced TV Encoder */
>  	writel(0, priv->io_base + _REG(ENCI_DBG_PX_RST));
>  
> -	/* Enable Vfifo2vd, Y_Cb_Y_Cr select */
> -	writel(0x4e01, priv->io_base + _REG(ENCI_VFIFO2VD_CTL));
> +	/*
> +	 * Enable Vfifo2vd and set Y_Cb_Y_Cr:
> +	 * Corresponding value:
> +	 * Y  => 00 or 10
> +	 * Cb => 01
> +	 * Cr => 11
> +	 * Ex: 0x4e => 01001110 would mean Cb/Y/Cr/Y
> +	 */
> +	writel(ENCI_VFIFO2VD_CTL_ENABLE |
> +	       ENCI_VFIFO2VD_CTL_VD_SEL(0x4e),
> +	       priv->io_base + _REG(ENCI_VFIFO2VD_CTL));
>  
>  	/* Power UP Dacs */
>  	writel(0, priv->io_base + _REG(VENC_VDAC_SETTING));
>  
>  	/* Video Upsampling */
> -	writel(0x0061, priv->io_base + _REG(VENC_UPSAMPLE_CTRL0));
> -	writel(0x4061, priv->io_base + _REG(VENC_UPSAMPLE_CTRL1));
> -	writel(0x5061, priv->io_base + _REG(VENC_UPSAMPLE_CTRL2));
> +	/*
> +	 * CTRL0, CTRL1 and CTRL2:
> +	 * Filter0: input data sample every 2 cloks
> +	 * Filter1: filtering and upsample enable
> +	 */
> +	reg = VENC_UPSAMPLE_CTRL_F0_2_CLK_RATIO | VENC_UPSAMPLE_CTRL_F1_EN |
> +		VENC_UPSAMPLE_CTRL_F1_UPSAMPLE_EN;
> +
> +	/*
> +	 * Upsample CTRL0:
> +	 * Interlace High Bandwidth Luma
> +	 */
> +	writel(VENC_UPSAMPLE_CTRL_INTERLACE_HIGH_LUMA | reg,
> +	       priv->io_base + _REG(VENC_UPSAMPLE_CTRL0));
> +
> +	/*
> +	 * Upsample CTRL1:
> +	 * Interlace Pb
> +	 */
> +	writel(VENC_UPSAMPLE_CTRL_INTERLACE_PB | reg,
> +	       priv->io_base + _REG(VENC_UPSAMPLE_CTRL1));
> +
> +	/*
> +	 * Upsample CTRL2:
> +	 * Interlace R
> +	 */
> +	writel(VENC_UPSAMPLE_CTRL_INTERLACE_PR | reg,
> +	       priv->io_base + _REG(VENC_UPSAMPLE_CTRL2));
>  
>  	/* Select Interlace Y DACs */
>  	writel(0, priv->io_base + _REG(VENC_VDAC_DACSEL0));
> @@ -1410,14 +1502,16 @@ static void meson_venci_cvbs_mode_set(struct meson_vpu_priv *priv,
>  	meson_vpp_setup_mux(priv, MESON_VIU_VPP_MUX_ENCI);
>  
>  	/* Enable ENCI FIFO */
> -	writel(0x2000, priv->io_base + _REG(VENC_VDAC_FIFO_CTRL));
> +	writel(VENC_VDAC_FIFO_EN_ENCI_ENABLE,
> +	       priv->io_base + _REG(VENC_VDAC_FIFO_CTRL));
>  
>  	/* Select ENCI DACs 0, 1, 4, and 5 */
>  	writel(0x11, priv->io_base + _REG(ENCI_DACSEL_0));
>  	writel(0x11, priv->io_base + _REG(ENCI_DACSEL_1));
>  
>  	/* Interlace video enable */
> -	writel(1, priv->io_base + _REG(ENCI_VIDEO_EN));
> +	writel(ENCI_VIDEO_EN_ENABLE,
> +	       priv->io_base + _REG(ENCI_VIDEO_EN));
>  
>  	/* Configure Video Saturation / Contrast / Brightness / Hue */
>  	writel(mode->video_saturation,
> @@ -1430,7 +1524,8 @@ static void meson_venci_cvbs_mode_set(struct meson_vpu_priv *priv,
>  	       priv->io_base + _REG(ENCI_VIDEO_HUE));
>  
>  	/* Enable DAC0 Filter */
> -	writel(0x1, priv->io_base + _REG(VENC_VDAC_DAC0_FILT_CTRL0));
> +	writel(VENC_VDAC_DAC0_FILT_CTRL0_EN,
> +	       priv->io_base + _REG(VENC_VDAC_DAC0_FILT_CTRL0));
>  	writel(0xfc48, priv->io_base + _REG(VENC_VDAC_DAC0_FILT_CTRL1));
>  
>  	/* 0 in Macrovision register 0 */
> @@ -1441,15 +1536,21 @@ static void meson_venci_cvbs_mode_set(struct meson_vpu_priv *priv,
>  	       priv->io_base + _REG(ENCI_SYNC_ADJ));
>  
>  	/* enable VDAC */
> -	writel_bits(BIT(5), 0, priv->io_base + _REG(VENC_VDAC_DACSEL0));
> +	writel_bits(VENC_VDAC_SEL_ATV_DMD, 0,
> +		    priv->io_base + _REG(VENC_VDAC_DACSEL0));
>  
>  	if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXBB))
>  		hhi_write(HHI_VDAC_CNTL0, 1);
>  	else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL) ||
>  		 meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM))
>  		hhi_write(HHI_VDAC_CNTL0, 0xf0001);
> +	else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
> +		hhi_write(HHI_VDAC_CNTL0_G12A, 0x906001);
>  
> -	hhi_write(HHI_VDAC_CNTL1, 0);
> +	if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
> +		hhi_write(HHI_VDAC_CNTL1_G12A, 0);
> +	else
> +		hhi_write(HHI_VDAC_CNTL1, 0);
>  }
>  
>  void meson_vpu_setup_venc(struct udevice *dev,
> diff --git a/drivers/video/meson/meson_vpu.h b/drivers/video/meson/meson_vpu.h
> index ef5f10eae3..3412dac052 100644
> --- a/drivers/video/meson/meson_vpu.h
> +++ b/drivers/video/meson/meson_vpu.h
> @@ -14,6 +14,7 @@
>  #include <video.h>
>  #include <display.h>
>  #include <linux/io.h>
> +#include <linux/bitfield.h>
>  #include "meson_registers.h"
>  
>  enum {
> diff --git a/drivers/video/meson/meson_vpu_init.c b/drivers/video/meson/meson_vpu_init.c
> index 92228b5ceb..12f8c4194a 100644
> --- a/drivers/video/meson/meson_vpu_init.c
> +++ b/drivers/video/meson/meson_vpu_init.c
> @@ -12,7 +12,9 @@
>  
>  /* HHI Registers */
>  #define HHI_VDAC_CNTL0		0x2F4 /* 0xbd offset in data sheet */
> +#define HHI_VDAC_CNTL0_G12A	0x2EC /* 0xbd offset in data sheet */
>  #define HHI_VDAC_CNTL1		0x2F8 /* 0xbe offset in data sheet */
> +#define HHI_VDAC_CNTL1_G12A	0x2F0 /* 0xbe offset in data sheet */
>  #define HHI_HDMI_PHY_CNTL0	0x3a0 /* 0xe8 offset in data sheet */
>  
>  /* OSDx_CTRL_STAT2 */
> @@ -42,7 +44,7 @@ static void meson_vpp_write_scaling_filter_coefs(struct meson_vpu_priv *priv,
>  {
>  	int i;
>  
> -	writel(is_horizontal ? BIT(8) : 0,
> +	writel(is_horizontal ? VPP_SCALE_HORIZONTAL_COEF : 0,
>  	       priv->io_base + _REG(VPP_OSD_SCALE_COEF_IDX));
>  	for (i = 0; i < 33; i++)
>  		writel(coefs[i],
> @@ -67,7 +69,7 @@ static void meson_vpp_write_vd_scaling_filter_coefs(struct meson_vpu_priv *priv,
>  {
>  	int i;
>  
> -	writel(is_horizontal ? BIT(8) : 0,
> +	writel(is_horizontal ? VPP_SCALE_HORIZONTAL_COEF : 0,
>  	       priv->io_base + _REG(VPP_SCALE_COEF_IDX));
>  	for (i = 0; i < 33; i++)
>  		writel(coefs[i],
> @@ -112,6 +114,34 @@ static int eotf_bypass_coeff[EOTF_COEFF_SIZE] = {
>  	EOTF_COEFF_RIGHTSHIFT /* right shift */
>  };
>  
> +static void meson_viu_set_g12a_osd1_matrix(struct meson_vpu_priv *priv,
> +					   int *m, bool csc_on)
> +{
> +	/* VPP WRAP OSD1 matrix */
> +	writel(((m[0] & 0xfff) << 16) | (m[1] & 0xfff),
> +	       priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_PRE_OFFSET0_1));
> +	writel(m[2] & 0xfff,
> +	       priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_PRE_OFFSET2));
> +	writel(((m[3] & 0x1fff) << 16) | (m[4] & 0x1fff),
> +	       priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF00_01));
> +	writel(((m[5] & 0x1fff) << 16) | (m[6] & 0x1fff),
> +	       priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF02_10));
> +	writel(((m[7] & 0x1fff) << 16) | (m[8] & 0x1fff),
> +	       priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF11_12));
> +	writel(((m[9] & 0x1fff) << 16) | (m[10] & 0x1fff),
> +	       priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF20_21));
> +	writel((m[11] & 0x1fff) << 16,
> +	       priv->io_base +	_REG(VPP_WRAP_OSD1_MATRIX_COEF22));
> +
> +	writel(((m[18] & 0xfff) << 16) | (m[19] & 0xfff),
> +	       priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_OFFSET0_1));
> +	writel(m[20] & 0xfff,
> +	       priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_OFFSET2));
> +
> +	writel_bits(BIT(0), csc_on ? BIT(0) : 0,
> +		    priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_EN_CTRL));
> +}
> +
>  static void meson_viu_set_osd_matrix(struct meson_vpu_priv *priv,
>  				     enum viu_matrix_sel_e m_select,
>  				     int *m, bool csc_on)
> @@ -322,20 +352,47 @@ static void meson_viu_load_matrix(struct meson_vpu_priv *priv)
>  				 true);
>  }
>  
> +static inline uint32_t meson_viu_osd_burst_length_reg(uint32_t length)
> +{
> +	u32 val = (((length & 0x80) % 24) / 12);
> +
> +	return (((val & 0x3) << 10) | (((val & 0x4) >> 2) << 31));
> +}
> +
>  void meson_vpu_init(struct udevice *dev)
>  {
>  	struct meson_vpu_priv *priv = dev_get_priv(dev);
>  	u32 reg;
>  
> -	/* vpu initialization */
> -	writel(0x210000, priv->io_base + _REG(VPU_RDARB_MODE_L1C1));
> -	writel(0x10000, priv->io_base + _REG(VPU_RDARB_MODE_L1C2));
> -	writel(0x900000, priv->io_base + _REG(VPU_RDARB_MODE_L2C1));
> -	writel(0x20000, priv->io_base + _REG(VPU_WRARB_MODE_L2C1));
> +	/*
> +	 * Slave dc0 and dc5 connected to master port 1.
> +	 * By default other slaves are connected to master port 0.
> +	 */
> +	reg = VPU_RDARB_SLAVE_TO_MASTER_PORT(0, 1) |
> +		VPU_RDARB_SLAVE_TO_MASTER_PORT(5, 1);
> +	writel(reg, priv->io_base + _REG(VPU_RDARB_MODE_L1C1));
> +
> +	/* Slave dc0 connected to master port 1 */
> +	reg = VPU_RDARB_SLAVE_TO_MASTER_PORT(0, 1);
> +	writel(reg, priv->io_base + _REG(VPU_RDARB_MODE_L1C2));
> +
> +	/* Slave dc4 and dc7 connected to master port 1 */
> +	reg = VPU_RDARB_SLAVE_TO_MASTER_PORT(4, 1) |
> +		VPU_RDARB_SLAVE_TO_MASTER_PORT(7, 1);
> +	writel(reg, priv->io_base + _REG(VPU_RDARB_MODE_L2C1));
> +
> +	/* Slave dc1 connected to master port 1 */
> +	reg = VPU_RDARB_SLAVE_TO_MASTER_PORT(1, 1);
> +	writel(reg, priv->io_base + _REG(VPU_WRARB_MODE_L2C1));
>  
>  	/* Disable CVBS VDAC */
> -	hhi_write(HHI_VDAC_CNTL0, 0);
> -	hhi_write(HHI_VDAC_CNTL1, 8);
> +	if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
> +		hhi_write(HHI_VDAC_CNTL0_G12A, 0);
> +		hhi_write(HHI_VDAC_CNTL1_G12A, 8);
> +	} else {
> +		hhi_write(HHI_VDAC_CNTL0, 0);
> +		hhi_write(HHI_VDAC_CNTL1, 8);
> +	}
>  
>  	/* Power Down Dacs */
>  	writel(0xff, priv->io_base + _REG(VENC_VDAC_SETTING));
> @@ -344,7 +401,9 @@ void meson_vpu_init(struct udevice *dev)
>  	hhi_write(HHI_HDMI_PHY_CNTL0, 0);
>  
>  	/* Disable HDMI */
> -	writel_bits(0x3, 0, priv->io_base + _REG(VPU_HDMI_SETTING));
> +	writel_bits(VPU_HDMI_ENCI_DATA_TO_HDMI |
> +		    VPU_HDMI_ENCP_DATA_TO_HDMI, 0,
> +		    priv->io_base + _REG(VPU_HDMI_SETTING));
>  
>  	/* Disable all encoders */
>  	writel(0, priv->io_base + _REG(ENCI_VIDEO_EN));
> @@ -360,43 +419,58 @@ void meson_vpu_init(struct udevice *dev)
>  	} else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM)) {
>  		writel_bits(0xff << 16, 0xff << 16,
>  			    priv->io_base + _REG(VIU_MISC_CTRL1));
> -		writel(0x20000, priv->io_base + _REG(VPP_DOLBY_CTRL));
> +		writel(VPP_PPS_DUMMY_DATA_MODE,
> +		       priv->io_base + _REG(VPP_DOLBY_CTRL));
>  		writel(0x1020080,
>  		       priv->io_base + _REG(VPP_DUMMY_DATA1));
> -	}
> +	} else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
> +		writel(0xf, priv->io_base + _REG(DOLBY_PATH_CTRL));
>  
>  	/* Initialize vpu fifo control registers */
> -	writel(readl(priv->io_base + _REG(VPP_OFIFO_SIZE)) |
> -			0x77f, priv->io_base + _REG(VPP_OFIFO_SIZE));
> -	writel(0x08080808, priv->io_base + _REG(VPP_HOLD_LINES));
> -
> -	/* Turn off preblend */
> -	writel_bits(VPP_PREBLEND_ENABLE, 0,
> -		    priv->io_base + _REG(VPP_MISC));
> -
> -	/* Turn off POSTBLEND */
> -	writel_bits(VPP_POSTBLEND_ENABLE, 0,
> -		    priv->io_base + _REG(VPP_MISC));
> -
> -	/* Force all planes off */
> -	writel_bits(VPP_OSD1_POSTBLEND | VPP_OSD2_POSTBLEND |
> -		    VPP_VD1_POSTBLEND | VPP_VD2_POSTBLEND |
> -		    VPP_VD1_PREBLEND | VPP_VD2_PREBLEND, 0,
> -		    priv->io_base + _REG(VPP_MISC));
> -
> -	/* Setup default VD settings */
> -	writel(4096,
> -	       priv->io_base + _REG(VPP_PREBLEND_VD1_H_START_END));
> -	writel(4096,
> -	       priv->io_base + _REG(VPP_BLEND_VD2_H_START_END));
> +	if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
> +		writel(VPP_OFIFO_SIZE_DEFAULT,
> +		       priv->io_base + _REG(VPP_OFIFO_SIZE));
> +	else
> +		writel_bits(VPP_OFIFO_SIZE_MASK, 0x77f,
> +			    priv->io_base + _REG(VPP_OFIFO_SIZE));
> +	writel(VPP_POSTBLEND_HOLD_LINES(4) | VPP_PREBLEND_HOLD_LINES(4),
> +	       priv->io_base + _REG(VPP_HOLD_LINES));
> +
> +	if (!meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
> +		/* Turn off preblend */
> +		writel_bits(VPP_PREBLEND_ENABLE, 0,
> +			    priv->io_base + _REG(VPP_MISC));
> +
> +		/* Turn off POSTBLEND */
> +		writel_bits(VPP_POSTBLEND_ENABLE, 0,
> +			    priv->io_base + _REG(VPP_MISC));
> +
> +		/* Force all planes off */
> +		writel_bits(VPP_OSD1_POSTBLEND | VPP_OSD2_POSTBLEND |
> +			    VPP_VD1_POSTBLEND | VPP_VD2_POSTBLEND |
> +			    VPP_VD1_PREBLEND | VPP_VD2_PREBLEND, 0,
> +			    priv->io_base + _REG(VPP_MISC));
> +
> +		/* Setup default VD settings */
> +		writel(4096,
> +		       priv->io_base + _REG(VPP_PREBLEND_VD1_H_START_END));
> +		writel(4096,
> +		       priv->io_base + _REG(VPP_BLEND_VD2_H_START_END));
> +	}
>  
>  	/* Disable Scalers */
>  	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));
> -	writel(4 | (4 << 8) | BIT(15),
> +
> +	writel(VPP_VSC_BANK_LENGTH(4) | VPP_HSC_BANK_LENGTH(4) |
> +	       VPP_SC_VD_EN_ENABLE,
>  	       priv->io_base + _REG(VPP_SC_MISC));
>  
> +	/* Enable minus black level for vadj1 */
> +	writel(VPP_MINUS_BLACK_LVL_VADJ1_ENABLE,
> +	       priv->io_base + _REG(VPP_VADJ_CTRL));
> +
>  	/* Write in the proper filter coefficients. */
>  	meson_vpp_write_scaling_filter_coefs(priv,
>  				vpp_filter_coefs_4point_bspline, false);
> @@ -410,23 +484,31 @@ void meson_vpu_init(struct udevice *dev)
>  						true);
>  
>  	/* Disable OSDs */
> -	writel_bits(BIT(0) | BIT(21), 0,
> +	writel_bits(VIU_OSD1_OSD_BLK_ENABLE | VIU_OSD1_OSD_ENABLE, 0,
>  		    priv->io_base + _REG(VIU_OSD1_CTRL_STAT));
> -	writel_bits(BIT(0) | BIT(21), 0,
> +	writel_bits(VIU_OSD1_OSD_BLK_ENABLE | VIU_OSD1_OSD_ENABLE, 0,
>  		    priv->io_base + _REG(VIU_OSD2_CTRL_STAT));
>  
>  	/* On GXL/GXM, Use the 10bit HDR conversion matrix */
>  	if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM) ||
>  	    meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL))
>  		meson_viu_load_matrix(priv);
> +	else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
> +		meson_viu_set_g12a_osd1_matrix(priv, RGB709_to_YUV709l_coeff,
> +					       true);
>  
>  	/* Initialize OSD1 fifo control register */
> -	reg = BIT(0) |	/* Urgent DDR request priority */
> -	      (4 << 5) | /* hold_fifo_lines */
> -	      (3 << 10) | /* burst length 64 */
> -	      (32 << 12) | /* fifo_depth_val: 32*8=256 */
> -	      (2 << 22) | /* 4 words in 1 burst */
> -	      (2 << 24);
> +	reg = VIU_OSD_DDR_PRIORITY_URGENT |
> +		VIU_OSD_HOLD_FIFO_LINES(4) |
> +		VIU_OSD_FIFO_DEPTH_VAL(32) | /* fifo_depth_val: 32*8=256 */
> +		VIU_OSD_WORDS_PER_BURST(4) | /* 4 words in 1 burst */
> +		VIU_OSD_FIFO_LIMITS(2);      /* fifo_lim: 2*16=32 */
> +
> +	if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
> +		reg |= meson_viu_osd_burst_length_reg(32);
> +	else
> +		reg |= meson_viu_osd_burst_length_reg(64);
> +
>  	writel(reg, priv->io_base + _REG(VIU_OSD1_FIFO_CTRL_STAT));
>  	writel(reg, priv->io_base + _REG(VIU_OSD2_FIFO_CTRL_STAT));
>  
> @@ -437,4 +519,39 @@ void meson_vpu_init(struct udevice *dev)
>  	writel_bits(0xff << OSD_REPLACE_SHIFT,
>  		    0xff << OSD_REPLACE_SHIFT,
>  		    priv->io_base + _REG(VIU_OSD2_CTRL_STAT2));
> +
> +	/* Disable VD1 AFBC */
> +	/* di_mif0_en=0 mif0_to_vpp_en=0 di_mad_en=0 and afbc vd1 set=0*/
> +	writel_bits(VIU_CTRL0_VD1_AFBC_MASK, 0,
> +		    priv->io_base + _REG(VIU_MISC_CTRL0));
> +	writel(0, priv->io_base + _REG(AFBC_ENABLE));
> +
> +	writel(0x00FF00C0,
> +	       priv->io_base + _REG(VD1_IF0_LUMA_FIFO_SIZE));
> +	writel(0x00FF00C0,
> +	       priv->io_base + _REG(VD2_IF0_LUMA_FIFO_SIZE));
> +
> +	if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
> +		writel(VIU_OSD_BLEND_REORDER(0, 1) |
> +		       VIU_OSD_BLEND_REORDER(1, 0) |
> +		       VIU_OSD_BLEND_REORDER(2, 0) |
> +		       VIU_OSD_BLEND_REORDER(3, 0) |
> +		       VIU_OSD_BLEND_DIN_EN(1) |
> +		       VIU_OSD_BLEND1_DIN3_BYPASS_TO_DOUT1 |
> +		       VIU_OSD_BLEND1_DOUT_BYPASS_TO_BLEND2 |
> +		       VIU_OSD_BLEND_DIN0_BYPASS_TO_DOUT0 |
> +		       VIU_OSD_BLEND_BLEN2_PREMULT_EN(1) |
> +		       VIU_OSD_BLEND_HOLD_LINES(4),
> +		       priv->io_base + _REG(VIU_OSD_BLEND_CTRL));
> +		writel(OSD_BLEND_PATH_SEL_ENABLE,
> +		       priv->io_base + _REG(OSD1_BLEND_SRC_CTRL));
> +		writel(OSD_BLEND_PATH_SEL_ENABLE,
> +		       priv->io_base + _REG(OSD2_BLEND_SRC_CTRL));
> +		writel(0, priv->io_base + _REG(VD1_BLEND_SRC_CTRL));
> +		writel(0, priv->io_base + _REG(VD2_BLEND_SRC_CTRL));
> +		writel(0, priv->io_base + _REG(VIU_OSD_BLEND_DUMMY_DATA0));
> +		writel(0, priv->io_base + _REG(VIU_OSD_BLEND_DUMMY_ALPHA));
> +		writel_bits(DOLBY_BYPASS_EN(0xc), DOLBY_BYPASS_EN(0xc),
> +			    priv->io_base + _REG(DOLBY_PATH_CTRL));
> +	}
>  }
> 


^ permalink raw reply	[flat|nested] 38+ messages in thread

* [U-Boot] [PATCH 1/8] power: domain: meson-gx-pwrc: add G12A support
  2019-08-30 12:09   ` Neil Armstrong
@ 2019-10-10 18:15     ` Anatolij Gustschin
  -1 siblings, 0 replies; 38+ messages in thread
From: Anatolij Gustschin @ 2019-10-10 18:15 UTC (permalink / raw)
  To: u-boot

On Fri, 30 Aug 2019 14:09:21 +0200
Neil Armstrong narmstrong at baylibre.com wrote:

> Add Amlogic G12A support for the gx-pwrc driver, aligned on the
> Linux v5.2 driver.
> 
> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>

Reviewed-by: Anatolij Gustschin <agust@denx.de>

--
Anatolij

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [U-Boot] [PATCH 1/8] power: domain: meson-gx-pwrc: add G12A support
@ 2019-10-10 18:15     ` Anatolij Gustschin
  0 siblings, 0 replies; 38+ messages in thread
From: Anatolij Gustschin @ 2019-10-10 18:15 UTC (permalink / raw)
  To: Neil Armstrong; +Cc: u-boot-amlogic, jh80.chung, u-boot

On Fri, 30 Aug 2019 14:09:21 +0200
Neil Armstrong narmstrong@baylibre.com wrote:

> Add Amlogic G12A support for the gx-pwrc driver, aligned on the
> Linux v5.2 driver.
> 
> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>

Reviewed-by: Anatolij Gustschin <agust@denx.de>

--
Anatolij

^ permalink raw reply	[flat|nested] 38+ messages in thread

* [U-Boot] [PATCH 2/8] clk: meson: g12a: add support for VPU/HDMI clocks
  2019-08-30 12:09   ` Neil Armstrong
@ 2019-10-10 18:15     ` Anatolij Gustschin
  -1 siblings, 0 replies; 38+ messages in thread
From: Anatolij Gustschin @ 2019-10-10 18:15 UTC (permalink / raw)
  To: u-boot

On Fri, 30 Aug 2019 14:09:22 +0200
Neil Armstrong narmstrong at baylibre.com wrote:

> Add necessary clock support to set up clock for the VPU and
> HDMI support.
> 
> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>

Reviewed-by: Anatolij Gustschin <agust@denx.de>

--
Anatolij

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [U-Boot] [PATCH 2/8] clk: meson: g12a: add support for VPU/HDMI clocks
@ 2019-10-10 18:15     ` Anatolij Gustschin
  0 siblings, 0 replies; 38+ messages in thread
From: Anatolij Gustschin @ 2019-10-10 18:15 UTC (permalink / raw)
  To: Neil Armstrong; +Cc: u-boot-amlogic, lukma, u-boot

On Fri, 30 Aug 2019 14:09:22 +0200
Neil Armstrong narmstrong@baylibre.com wrote:

> Add necessary clock support to set up clock for the VPU and
> HDMI support.
> 
> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>

Reviewed-by: Anatolij Gustschin <agust@denx.de>

--
Anatolij

^ permalink raw reply	[flat|nested] 38+ messages in thread

* [U-Boot] [PATCH 3/8] video: meson: remove power domain get
  2019-08-30 12:09   ` Neil Armstrong
@ 2019-10-10 18:15     ` Anatolij Gustschin
  -1 siblings, 0 replies; 38+ messages in thread
From: Anatolij Gustschin @ 2019-10-10 18:15 UTC (permalink / raw)
  To: u-boot

On Fri, 30 Aug 2019 14:09:23 +0200
Neil Armstrong narmstrong at baylibre.com wrote:

> Remove getting and enabling the node power domain since it's now handled
> by the dm core directly.
> 
> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>

Reviewed-by: Anatolij Gustschin <agust@denx.de>

--
Anatolij

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH 3/8] video: meson: remove power domain get
@ 2019-10-10 18:15     ` Anatolij Gustschin
  0 siblings, 0 replies; 38+ messages in thread
From: Anatolij Gustschin @ 2019-10-10 18:15 UTC (permalink / raw)
  To: Neil Armstrong; +Cc: u-boot-amlogic, jh80.chung, u-boot

On Fri, 30 Aug 2019 14:09:23 +0200
Neil Armstrong narmstrong@baylibre.com wrote:

> Remove getting and enabling the node power domain since it's now handled
> by the dm core directly.
> 
> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>

Reviewed-by: Anatolij Gustschin <agust@denx.de>

--
Anatolij

^ permalink raw reply	[flat|nested] 38+ messages in thread

* [U-Boot] [PATCH 5/8] video: meson: add compatible for Amlogic G12A
  2019-08-30 12:09   ` Neil Armstrong
@ 2019-10-10 18:22     ` Anatolij Gustschin
  -1 siblings, 0 replies; 38+ messages in thread
From: Anatolij Gustschin @ 2019-10-10 18:22 UTC (permalink / raw)
  To: u-boot

On Fri, 30 Aug 2019 14:09:25 +0200
Neil Armstrong narmstrong at baylibre.com wrote:

> Finally add the Amlogic G12A SoC compatible for the VPU driver.
> 
> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>

Reviewed-by: Anatolij Gustschin <agust@denx.de>

--
Anatolij

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH 5/8] video: meson: add compatible for Amlogic G12A
@ 2019-10-10 18:22     ` Anatolij Gustschin
  0 siblings, 0 replies; 38+ messages in thread
From: Anatolij Gustschin @ 2019-10-10 18:22 UTC (permalink / raw)
  To: Neil Armstrong; +Cc: u-boot-amlogic, u-boot

On Fri, 30 Aug 2019 14:09:25 +0200
Neil Armstrong narmstrong@baylibre.com wrote:

> Finally add the Amlogic G12A SoC compatible for the VPU driver.
> 
> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>

Reviewed-by: Anatolij Gustschin <agust@denx.de>

--
Anatolij

^ permalink raw reply	[flat|nested] 38+ messages in thread

* [U-Boot] [PATCH 6/8] arm: meson: board-g12a: Setup VPU in fdt
  2019-08-30 12:09   ` Neil Armstrong
@ 2019-10-10 18:23     ` Anatolij Gustschin
  -1 siblings, 0 replies; 38+ messages in thread
From: Anatolij Gustschin @ 2019-10-10 18:23 UTC (permalink / raw)
  To: u-boot

On Fri, 30 Aug 2019 14:09:26 +0200
Neil Armstrong narmstrong at baylibre.com wrote:

> If VIDEO_MESON is enabled, we need to setup the fdt for the framebuffer.
> 
> Call meson_vpu_rsv_fb() which reserves the framebuffer memory region for
> EFI, and sets up simple-framebuffer nodes if simplefb support is
> enabled.
> 
> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>

Reviewed-by: Anatolij Gustschin <agust@denx.de>

--
Anatolij

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [U-Boot] [PATCH 6/8] arm: meson: board-g12a: Setup VPU in fdt
@ 2019-10-10 18:23     ` Anatolij Gustschin
  0 siblings, 0 replies; 38+ messages in thread
From: Anatolij Gustschin @ 2019-10-10 18:23 UTC (permalink / raw)
  To: Neil Armstrong; +Cc: u-boot-amlogic, u-boot

On Fri, 30 Aug 2019 14:09:26 +0200
Neil Armstrong narmstrong@baylibre.com wrote:

> If VIDEO_MESON is enabled, we need to setup the fdt for the framebuffer.
> 
> Call meson_vpu_rsv_fb() which reserves the framebuffer memory region for
> EFI, and sets up simple-framebuffer nodes if simplefb support is
> enabled.
> 
> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>

Reviewed-by: Anatolij Gustschin <agust@denx.de>

--
Anatolij

^ permalink raw reply	[flat|nested] 38+ messages in thread

* [U-Boot] [PATCH 7/8] ARM: dts: meson-g12a: add U-Boot specific DT for graphics
  2019-08-30 12:09   ` Neil Armstrong
@ 2019-10-10 18:25     ` Anatolij Gustschin
  -1 siblings, 0 replies; 38+ messages in thread
From: Anatolij Gustschin @ 2019-10-10 18:25 UTC (permalink / raw)
  To: u-boot

On Fri, 30 Aug 2019 14:09:27 +0200
Neil Armstrong narmstrong at baylibre.com wrote:

> Like the meson-gx support, add the U-Boot specific bits in DT
> to support graphics on G12A SoCs.
> 
> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>

Reviewed-by: Anatolij Gustschin <agust@denx.de>

--
Anatolij

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [U-Boot] [PATCH 7/8] ARM: dts: meson-g12a: add U-Boot specific DT for graphics
@ 2019-10-10 18:25     ` Anatolij Gustschin
  0 siblings, 0 replies; 38+ messages in thread
From: Anatolij Gustschin @ 2019-10-10 18:25 UTC (permalink / raw)
  To: Neil Armstrong; +Cc: u-boot-amlogic, u-boot

On Fri, 30 Aug 2019 14:09:27 +0200
Neil Armstrong narmstrong@baylibre.com wrote:

> Like the meson-gx support, add the U-Boot specific bits in DT
> to support graphics on G12A SoCs.
> 
> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>

Reviewed-by: Anatolij Gustschin <agust@denx.de>

--
Anatolij

^ permalink raw reply	[flat|nested] 38+ messages in thread

* [U-Boot] [PATCH 8/8] configs: sei510: enable Video Display support
  2019-08-30 12:09   ` Neil Armstrong
@ 2019-10-10 18:28     ` Anatolij Gustschin
  -1 siblings, 0 replies; 38+ messages in thread
From: Anatolij Gustschin @ 2019-10-10 18:28 UTC (permalink / raw)
  To: u-boot

On Fri, 30 Aug 2019 14:09:28 +0200
Neil Armstrong narmstrong at baylibre.com wrote:

> Add the necessary config options to support BMP display over HDMI,
> and add a preboot command to load the BMP file from a predefined
> eMMC partition.
> 
> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>

Reviewed-by: Anatolij Gustschin <agust@denx.de>

--
Anatolij

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [U-Boot] [PATCH 8/8] configs: sei510: enable Video Display support
@ 2019-10-10 18:28     ` Anatolij Gustschin
  0 siblings, 0 replies; 38+ messages in thread
From: Anatolij Gustschin @ 2019-10-10 18:28 UTC (permalink / raw)
  To: Neil Armstrong; +Cc: u-boot-amlogic, u-boot

On Fri, 30 Aug 2019 14:09:28 +0200
Neil Armstrong narmstrong@baylibre.com wrote:

> Add the necessary config options to support BMP display over HDMI,
> and add a preboot command to load the BMP file from a predefined
> eMMC partition.
> 
> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>

Reviewed-by: Anatolij Gustschin <agust@denx.de>

--
Anatolij

^ permalink raw reply	[flat|nested] 38+ messages in thread

* [U-Boot] [PATCH 4/8] video: meson: sync with linux drm-misc tree
  2019-08-30 12:09   ` Neil Armstrong
@ 2019-10-10 20:48     ` Anatolij Gustschin
  -1 siblings, 0 replies; 38+ messages in thread
From: Anatolij Gustschin @ 2019-10-10 20:48 UTC (permalink / raw)
  To: u-boot

On Fri, 30 Aug 2019 14:09:24 +0200
Neil Armstrong narmstrong at baylibre.com wrote:

> Synchronize the Amlogic Meson Video driver back with the latest
> DRM misc tree, adding G12A platform support, from the latest commit:
> 528a25d040bc ("drm: meson: use match data to detect vpu compatibility")
> 
> The sync includes the following changes from Linux adapted to U-Boot:
> - Add support for VIC alternate timings
> - Switch PLL to 5.94GHz base for 297Mhz pixel clock
> - Add registers for G12A SoC
> - Add G12A Support for VPP setup
> - Add G12A Support for VIU setup
> - Add G12A support for OSD1 Plane
> - Add G12A support for plane handling in CRTC driver
> - Add G12A support for CVBS Encoder
> - Add G12A Video Clock setup
> - Add G12A support for the DW-HDMI Glue
> - fix G12A HDMI PLL settings for 4K60 1000/1001 variations
> - fix primary plane disabling
> - fix G12A primary plane disabling
> - mask value when writing bits relaxed
> - crtc: drv: vpp: viu: venc: use proper macros instead of magic constants
> - global clean-up
> - add macro used to enable HDMI PLL
> - venc: set the correct macrovision max amplitude value
> 
> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>

Reviewed-by: Anatolij Gustschin <agust@denx.de>

--
Anatolij

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH 4/8] video: meson: sync with linux drm-misc tree
@ 2019-10-10 20:48     ` Anatolij Gustschin
  0 siblings, 0 replies; 38+ messages in thread
From: Anatolij Gustschin @ 2019-10-10 20:48 UTC (permalink / raw)
  To: Neil Armstrong; +Cc: u-boot-amlogic, u-boot

On Fri, 30 Aug 2019 14:09:24 +0200
Neil Armstrong narmstrong@baylibre.com wrote:

> Synchronize the Amlogic Meson Video driver back with the latest
> DRM misc tree, adding G12A platform support, from the latest commit:
> 528a25d040bc ("drm: meson: use match data to detect vpu compatibility")
> 
> The sync includes the following changes from Linux adapted to U-Boot:
> - Add support for VIC alternate timings
> - Switch PLL to 5.94GHz base for 297Mhz pixel clock
> - Add registers for G12A SoC
> - Add G12A Support for VPP setup
> - Add G12A Support for VIU setup
> - Add G12A support for OSD1 Plane
> - Add G12A support for plane handling in CRTC driver
> - Add G12A support for CVBS Encoder
> - Add G12A Video Clock setup
> - Add G12A support for the DW-HDMI Glue
> - fix G12A HDMI PLL settings for 4K60 1000/1001 variations
> - fix primary plane disabling
> - fix G12A primary plane disabling
> - mask value when writing bits relaxed
> - crtc: drv: vpp: viu: venc: use proper macros instead of magic constants
> - global clean-up
> - add macro used to enable HDMI PLL
> - venc: set the correct macrovision max amplitude value
> 
> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>

Reviewed-by: Anatolij Gustschin <agust@denx.de>

--
Anatolij

^ permalink raw reply	[flat|nested] 38+ messages in thread

* [U-Boot] [PATCH 0/8] arm: meson: add Video support for G12A and SEI510 board
  2019-08-30 12:09 ` Neil Armstrong
@ 2019-10-11 12:57   ` Neil Armstrong
  -1 siblings, 0 replies; 38+ messages in thread
From: Neil Armstrong @ 2019-10-11 12:57 UTC (permalink / raw)
  To: u-boot

On 30/08/2019 14:09, Neil Armstrong wrote:
> This patchset adds Amlogic G12A support for HDMI & Composite video output like
> the Amlogic GXBB/GXL/GXM, by syncing from the latest Linux VPU DRM driver.
> 
> It also adds VPU/VAPB/HDMI Clock & VPU Power Domain support.
> 
> Finally it adds the necessary config to show a logo from a fastboot flashed
> partition on the SEI510 board.
> 
> U200 and Odroid-N2 config support will be added later.
> 
> Neil Armstrong (8):
>   power: domain: meson-gx-pwrc: add G12A support
>   clk: meson: g12a: add support for VPU/HDMI clocks
>   video: meson: remove power domain get
>   video: meson: sync with linux drm-misc tree
>   video: meson: add compatible for Amlogic G12A
>   arm: meson: board-g12a: Setup VPU in fdt
>   ARM: dts: meson-g12a: add U-Boot specific DT for graphics
>   configs: sei510: enable Video Display support
> 
>  arch/arm/dts/meson-g12a-sei510-u-boot.dtsi    |   7 +
>  arch/arm/dts/meson-g12a-u-boot.dtsi           |  29 +
>  arch/arm/dts/meson-g12a-u200-u-boot.dtsi      |   7 +
>  arch/arm/dts/meson-g12b-odroid-n2-u-boot.dtsi |   7 +
>  arch/arm/mach-meson/board-g12a.c              |   5 +
>  configs/sei510_defconfig                      |  11 +
>  drivers/clk/meson/g12a.c                      | 620 +++++++++++++++++-
>  drivers/power/domain/meson-gx-pwrc-vpu.c      | 155 ++++-
>  drivers/video/meson/meson_dw_hdmi.c           |  61 +-
>  drivers/video/meson/meson_plane.c             |  47 +-
>  drivers/video/meson/meson_registers.h         | 373 ++++++++++-
>  drivers/video/meson/meson_vclk.c              | 233 +++++--
>  drivers/video/meson/meson_venc.c              | 169 ++++-
>  drivers/video/meson/meson_vpu.c               |  11 +-
>  drivers/video/meson/meson_vpu.h               |   2 +
>  drivers/video/meson/meson_vpu_init.c          | 205 ++++--
>  include/configs/sei510.h                      |  12 +
>  17 files changed, 1757 insertions(+), 197 deletions(-)
>  create mode 100644 arch/arm/dts/meson-g12a-sei510-u-boot.dtsi
>  create mode 100644 arch/arm/dts/meson-g12a-u-boot.dtsi
>  create mode 100644 arch/arm/dts/meson-g12a-u200-u-boot.dtsi
>  create mode 100644 arch/arm/dts/meson-g12b-odroid-n2-u-boot.dtsi
> 

Applied to u-boot-amlogic !

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH 0/8] arm: meson: add Video support for G12A and SEI510 board
@ 2019-10-11 12:57   ` Neil Armstrong
  0 siblings, 0 replies; 38+ messages in thread
From: Neil Armstrong @ 2019-10-11 12:57 UTC (permalink / raw)
  To: u-boot-amlogic, agust, jh80.chung, lukma; +Cc: u-boot

On 30/08/2019 14:09, Neil Armstrong wrote:
> This patchset adds Amlogic G12A support for HDMI & Composite video output like
> the Amlogic GXBB/GXL/GXM, by syncing from the latest Linux VPU DRM driver.
> 
> It also adds VPU/VAPB/HDMI Clock & VPU Power Domain support.
> 
> Finally it adds the necessary config to show a logo from a fastboot flashed
> partition on the SEI510 board.
> 
> U200 and Odroid-N2 config support will be added later.
> 
> Neil Armstrong (8):
>   power: domain: meson-gx-pwrc: add G12A support
>   clk: meson: g12a: add support for VPU/HDMI clocks
>   video: meson: remove power domain get
>   video: meson: sync with linux drm-misc tree
>   video: meson: add compatible for Amlogic G12A
>   arm: meson: board-g12a: Setup VPU in fdt
>   ARM: dts: meson-g12a: add U-Boot specific DT for graphics
>   configs: sei510: enable Video Display support
> 
>  arch/arm/dts/meson-g12a-sei510-u-boot.dtsi    |   7 +
>  arch/arm/dts/meson-g12a-u-boot.dtsi           |  29 +
>  arch/arm/dts/meson-g12a-u200-u-boot.dtsi      |   7 +
>  arch/arm/dts/meson-g12b-odroid-n2-u-boot.dtsi |   7 +
>  arch/arm/mach-meson/board-g12a.c              |   5 +
>  configs/sei510_defconfig                      |  11 +
>  drivers/clk/meson/g12a.c                      | 620 +++++++++++++++++-
>  drivers/power/domain/meson-gx-pwrc-vpu.c      | 155 ++++-
>  drivers/video/meson/meson_dw_hdmi.c           |  61 +-
>  drivers/video/meson/meson_plane.c             |  47 +-
>  drivers/video/meson/meson_registers.h         | 373 ++++++++++-
>  drivers/video/meson/meson_vclk.c              | 233 +++++--
>  drivers/video/meson/meson_venc.c              | 169 ++++-
>  drivers/video/meson/meson_vpu.c               |  11 +-
>  drivers/video/meson/meson_vpu.h               |   2 +
>  drivers/video/meson/meson_vpu_init.c          | 205 ++++--
>  include/configs/sei510.h                      |  12 +
>  17 files changed, 1757 insertions(+), 197 deletions(-)
>  create mode 100644 arch/arm/dts/meson-g12a-sei510-u-boot.dtsi
>  create mode 100644 arch/arm/dts/meson-g12a-u-boot.dtsi
>  create mode 100644 arch/arm/dts/meson-g12a-u200-u-boot.dtsi
>  create mode 100644 arch/arm/dts/meson-g12b-odroid-n2-u-boot.dtsi
> 

Applied to u-boot-amlogic !

^ permalink raw reply	[flat|nested] 38+ messages in thread

end of thread, other threads:[~2019-10-11 12:57 UTC | newest]

Thread overview: 38+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-08-30 12:09 [U-Boot] [PATCH 0/8] arm: meson: add Video support for G12A and SEI510 board Neil Armstrong
2019-08-30 12:09 ` Neil Armstrong
2019-08-30 12:09 ` [U-Boot] [PATCH 1/8] power: domain: meson-gx-pwrc: add G12A support Neil Armstrong
2019-08-30 12:09   ` Neil Armstrong
2019-10-10 18:15   ` [U-Boot] " Anatolij Gustschin
2019-10-10 18:15     ` Anatolij Gustschin
2019-08-30 12:09 ` [U-Boot] [PATCH 2/8] clk: meson: g12a: add support for VPU/HDMI clocks Neil Armstrong
2019-08-30 12:09   ` Neil Armstrong
2019-10-10 18:15   ` [U-Boot] " Anatolij Gustschin
2019-10-10 18:15     ` Anatolij Gustschin
2019-08-30 12:09 ` [U-Boot] [PATCH 3/8] video: meson: remove power domain get Neil Armstrong
2019-08-30 12:09   ` Neil Armstrong
2019-10-10 18:15   ` [U-Boot] " Anatolij Gustschin
2019-10-10 18:15     ` Anatolij Gustschin
2019-08-30 12:09 ` [U-Boot] [PATCH 4/8] video: meson: sync with linux drm-misc tree Neil Armstrong
2019-08-30 12:09   ` Neil Armstrong
2019-10-09 15:12   ` [U-Boot] " Neil Armstrong
2019-10-09 15:12     ` Neil Armstrong
2019-10-10 20:48   ` [U-Boot] " Anatolij Gustschin
2019-10-10 20:48     ` Anatolij Gustschin
2019-08-30 12:09 ` [U-Boot] [PATCH 5/8] video: meson: add compatible for Amlogic G12A Neil Armstrong
2019-08-30 12:09   ` Neil Armstrong
2019-10-10 18:22   ` [U-Boot] " Anatolij Gustschin
2019-10-10 18:22     ` Anatolij Gustschin
2019-08-30 12:09 ` [U-Boot] [PATCH 6/8] arm: meson: board-g12a: Setup VPU in fdt Neil Armstrong
2019-08-30 12:09   ` Neil Armstrong
2019-10-10 18:23   ` [U-Boot] " Anatolij Gustschin
2019-10-10 18:23     ` Anatolij Gustschin
2019-08-30 12:09 ` [U-Boot] [PATCH 7/8] ARM: dts: meson-g12a: add U-Boot specific DT for graphics Neil Armstrong
2019-08-30 12:09   ` Neil Armstrong
2019-10-10 18:25   ` [U-Boot] " Anatolij Gustschin
2019-10-10 18:25     ` Anatolij Gustschin
2019-08-30 12:09 ` [U-Boot] [PATCH 8/8] configs: sei510: enable Video Display support Neil Armstrong
2019-08-30 12:09   ` Neil Armstrong
2019-10-10 18:28   ` [U-Boot] " Anatolij Gustschin
2019-10-10 18:28     ` Anatolij Gustschin
2019-10-11 12:57 ` [U-Boot] [PATCH 0/8] arm: meson: add Video support for G12A and SEI510 board Neil Armstrong
2019-10-11 12:57   ` Neil Armstrong

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.