Files
build/patch/u-boot/v2024.01/board_rk3318-box/rk3328-vop-driver.patch
Paolo Sabatino 3c649d2e9d rockchip64: cleanup rk3318-box hdmi patches
* remove phy functions to avoid future clashes
 * use existing phy .configure function
2024-04-26 15:21:56 +08:00

340 lines
9.8 KiB
Diff

From 32a6e8629d11cfa79d33fa733d1b845e36eadaef Mon Sep 17 00:00:00 2001
From: Jagan Teki <jagan@edgeble.ai>
Date: Mon, 20 Feb 2023 00:58:55 +0530
Subject: [PATCH] video: rockchip: Add rk3328 vop support
Signed-off-by: Jagan Teki <jagan@edgeble.ai>
---
drivers/video/rockchip/Makefile | 1 +
drivers/video/rockchip/rk3328_vop.c | 66 +++++++++++++++++++++++++++++
2 files changed, 67 insertions(+)
create mode 100644 drivers/video/rockchip/rk3328_vop.c
diff --git a/drivers/video/rockchip/Makefile b/drivers/video/rockchip/Makefile
index 9aced5ef3f4..2a23a1a447f 100644
--- a/drivers/video/rockchip/Makefile
+++ b/drivers/video/rockchip/Makefile
@@ -6,6 +6,7 @@
ifdef CONFIG_VIDEO_ROCKCHIP
obj-y += rk_vop.o
obj-$(CONFIG_ROCKCHIP_RK3288) += rk3288_vop.o
+obj-$(CONFIG_ROCKCHIP_RK3328) += rk3328_vop.o
obj-$(CONFIG_ROCKCHIP_RK3399) += rk3399_vop.o
obj-$(CONFIG_DISPLAY_ROCKCHIP_EDP) += rk_edp.o
obj-$(CONFIG_DISPLAY_ROCKCHIP_LVDS) += rk_lvds.o
diff --git a/drivers/video/rockchip/rk3328_vop.c b/drivers/video/rockchip/rk3328_vop.c
new file mode 100644
index 0000000000..5275d65417
--- /dev/null
+++ b/drivers/video/rockchip/rk3328_vop.c
@@ -0,0 +1,111 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2023 Edgeble AI Technologies Pvt. Ltd.
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <video.h>
+#include <asm/io.h>
+#include <reset.h>
+#include <clk.h>
+#include <linux/delay.h>
+#include "rk_vop.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static void rk3328_set_pin_polarity(struct udevice *dev,
+ enum vop_modes mode, u32 polarity)
+{
+ struct rk_vop_priv *priv = dev_get_priv(dev);
+ struct rk3288_vop *regs = priv->regs;
+
+ switch (mode) {
+ case VOP_MODE_HDMI:
+ clrsetbits_le32(&regs->dsp_ctrl1,
+ M_RK3399_DSP_HDMI_POL,
+ V_RK3399_DSP_HDMI_POL(polarity));
+ break;
+ default:
+ debug("%s: unsupported output mode %x\n", __func__, mode);
+ }
+}
+
+static int rk3328_vop_probe(struct udevice *dev)
+{
+ /* Before relocation we don't need to do anything */
+ if (!(gd->flags & GD_FLG_RELOC))
+ return 0;
+
+ return rk_vop_probe(dev);
+}
+
+/**
+ * Remove the device deasserting the dclk, thus disabling the VOP.
+ * This is essential to avoid iommu complaining later during kernel boot
+ * @see https://lore.kernel.org/linux-arm-kernel/20230330131746.1475514-1-jagan@amarulasolutions.com/
+ */
+static int rk3328_vop_remove(struct udevice *dev)
+{
+ struct rk_vop_priv *priv = dev_get_priv(dev);
+ struct rk3288_vop *regs = priv->regs;
+ struct reset_ctl dclk_rst;
+
+ int ret;
+
+ debug("%s\n", __func__);
+
+ /* set to standby */
+ setbits_le32(&regs->sys_ctrl, V_STANDBY_EN(1));
+ clrsetbits_le32(&regs->sys_ctrl, M_ALL_OUT_EN, 0x0);
+
+ ret = reset_get_by_name(dev, "dclk", &dclk_rst);
+ if (ret) {
+ printf("failed to get dclk reset (ret=%d)\n", ret);
+ }
+
+ /* assert and deassert reset */
+ ret = reset_assert(&dclk_rst);
+ if (ret) {
+ printf("failed to assert dclk reset (ret=%d)\n", ret);
+ }
+ udelay(20);
+
+ ret = reset_deassert(&dclk_rst);
+ if (ret) {
+ printf("failed to deassert dclk reset (ret=%d)\n", ret);
+ }
+
+ return 0;
+
+}
+
+struct rkvop_driverdata rk3328_driverdata = {
+ .dsp_offset = 0x490,
+ .win_offset = 0xd0,
+ .features = VOP_FEATURE_OUTPUT_10BIT,
+ .set_pin_polarity = rk3328_set_pin_polarity,
+};
+
+static const struct udevice_id rk3328_vop_ids[] = {
+ {
+ .compatible = "rockchip,rk3328-vop",
+ .data = (ulong)&rk3328_driverdata
+ },
+ { /* sentile */ }
+};
+
+static const struct video_ops rk3328_vop_ops = {
+};
+
+U_BOOT_DRIVER(rockchip_rk3328_vop) = {
+ .name = "rockchip_rk3328_vop",
+ .id = UCLASS_VIDEO,
+ .of_match = rk3328_vop_ids,
+ .ops = &rk3328_vop_ops,
+ .bind = rk_vop_bind,
+ .probe = rk3328_vop_probe,
+ .remove = rk3328_vop_remove,
+ .priv_auto = sizeof(struct rk_vop_priv),
+ .flags = DM_FLAG_OS_PREPARE
+};
From 192910962f05ea174e3f30cc1ef182981bf8ef71 Mon Sep 17 00:00:00 2001
From: Jagan Teki <jagan@edgeble.ai>
Date: Thu, 16 Feb 2023 22:48:09 +0530
Subject: [PATCH] ARM: dts: rk3328: Enable VOP for u-boot,dm-pre-reloc
Model: Firefly roc-rk3328-cc
DRAM: 1 GiB (effective 1022 MiB)
Video device 'vop@ff370000' cannot allocate frame buffer memory -ensure the device is set up before relocation
Error binding driver 'rockchip_rk3328_vop': -28
Some drivers failed to bind
initcall sequence 000000003ffcd5e8 failed at call 000000000021a5c4 (err=-28)
### ERROR ### Please RESET the board ###
Signed-off-by: Jagan Teki <jagan@edgeble.ai>
---
arch/arm/dts/rk3328-u-boot.dtsi | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/arch/arm/dts/rk3328-u-boot.dtsi b/arch/arm/dts/rk3328-u-boot.dtsi
index d4a7540a92c..bd6702dedc7 100644
--- a/arch/arm/dts/rk3328-u-boot.dtsi
+++ b/arch/arm/dts/rk3328-u-boot.dtsi
@@ -73,3 +73,7 @@
&spi0 {
u-boot,dm-pre-reloc;
};
+
+&vop {
+ bootph-all;
+};
From ac6442b276b1aef478e1b701e3f4754d98ca61ab Mon Sep 17 00:00:00 2001
From: Jagan Teki <jagan@amarulasolutions.com>
Date: Thu, 16 Feb 2023 10:48:48 +0530
Subject: [PATCH] clk: rockchip: rk3328: Add VOP clk support
Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
---
.../include/asm/arch-rockchip/cru_rk3328.h | 34 ++++++++
drivers/clk/rockchip/clk_rk3328.c | 83 ++++++++++++++++++-
2 files changed, 115 insertions(+), 2 deletions(-)
diff --git a/arch/arm/include/asm/arch-rockchip/cru_rk3328.h b/arch/arm/include/asm/arch-rockchip/cru_rk3328.h
index 226744d67d9..4ad1d33e056 100644
--- a/arch/arm/include/asm/arch-rockchip/cru_rk3328.h
+++ b/arch/arm/include/asm/arch-rockchip/cru_rk3328.h
@@ -62,6 +62,40 @@ check_member(rk3328_cru, sdmmc_ext_con[1], 0x39c);
enum apll_frequencies {
APLL_816_MHZ,
APLL_600_MHZ,
+
+ /* CRU_CLK_SEL37_CON */
+ ACLK_VIO_PLL_SEL_CPLL = 0,
+ ACLK_VIO_PLL_SEL_GPLL = 1,
+ ACLK_VIO_PLL_SEL_HDMIPHY = 2,
+ ACLK_VIO_PLL_SEL_USB480M = 3,
+ ACLK_VIO_PLL_SEL_SHIFT = 6,
+ ACLK_VIO_PLL_SEL_MASK = 3 << ACLK_VIO_PLL_SEL_SHIFT,
+ ACLK_VIO_DIV_CON_SHIFT = 0,
+ ACLK_VIO_DIV_CON_MASK = 0x1f << ACLK_VIO_DIV_CON_SHIFT,
+ HCLK_VIO_DIV_CON_SHIFT = 8,
+ HCLK_VIO_DIV_CON_MASK = 0x1f << HCLK_VIO_DIV_CON_SHIFT,
+
+ /* CRU_CLK_SEL39_CON */
+ ACLK_VOP_PLL_SEL_CPLL = 0,
+ ACLK_VOP_PLL_SEL_GPLL = 1,
+ ACLK_VOP_PLL_SEL_HDMIPHY = 2,
+ ACLK_VOP_PLL_SEL_USB480M = 3,
+ ACLK_VOP_PLL_SEL_SHIFT = 6,
+ ACLK_VOP_PLL_SEL_MASK = 3 << ACLK_VOP_PLL_SEL_SHIFT,
+ ACLK_VOP_DIV_CON_SHIFT = 0,
+ ACLK_VOP_DIV_CON_MASK = 0x1f << ACLK_VOP_DIV_CON_SHIFT,
+
+ /* CRU_CLK_SEL40_CON */
+ DCLK_LCDC_PLL_SEL_GPLL = 0,
+ DCLK_LCDC_PLL_SEL_CPLL = 1,
+ DCLK_LCDC_PLL_SEL_SHIFT = 0,
+ DCLK_LCDC_PLL_SEL_MASK = 1 << DCLK_LCDC_PLL_SEL_SHIFT,
+ DCLK_LCDC_SEL_HDMIPHY = 0,
+ DCLK_LCDC_SEL_PLL = 1,
+ DCLK_LCDC_SEL_SHIFT = 1,
+ DCLK_LCDC_SEL_MASK = 1 << DCLK_LCDC_SEL_SHIFT,
+ DCLK_LCDC_DIV_CON_SHIFT = 8,
+ DCLK_LCDC_DIV_CON_MASK = 0xFf << DCLK_LCDC_DIV_CON_SHIFT,
};
void rk3328_configure_cpu(struct rk3328_cru *cru,
diff --git a/drivers/clk/rockchip/clk_rk3328.c b/drivers/clk/rockchip/clk_rk3328.c
index b825ff4cf83..195247d9e02 100644
--- a/drivers/clk/rockchip/clk_rk3328.c
+++ b/drivers/clk/rockchip/clk_rk3328.c
@@ -581,6 +581,81 @@ static ulong rk3328_spi_set_clk(struct rk3328_cru *cru, uint hz)
return rk3328_spi_get_clk(cru);
}
+#ifndef CONFIG_SPL_BUILD
+static ulong rk3328_vop_get_clk(struct rk3328_clk_priv *priv, ulong clk_id)
+{
+ struct rk3328_cru *cru = priv->cru;
+ u32 div, con, parent;
+
+ switch (clk_id) {
+ case ACLK_VOP_PRE:
+ con = readl(&cru->clksel_con[39]);
+ div = (con & ACLK_VOP_DIV_CON_MASK) >> ACLK_VOP_DIV_CON_SHIFT;
+ parent = GPLL_HZ;
+ break;
+ case ACLK_VIO_PRE:
+ con = readl(&cru->clksel_con[37]);
+ div = (con & ACLK_VIO_DIV_CON_MASK) >> ACLK_VIO_DIV_CON_SHIFT;
+ parent = GPLL_HZ;
+ break;
+ default:
+ debug("%s: Unsupported vop get clk#%ld\n", __func__, clk_id);
+ return -ENOENT;
+ }
+
+ return DIV_TO_RATE(parent, div);
+}
+
+static ulong rk3328_vop_set_clk(struct rk3328_clk_priv *priv,
+ ulong clk_id, uint hz)
+{
+ struct rk3328_cru *cru = priv->cru;
+ int src_clk_div;
+ u32 con, parent;
+
+ src_clk_div = DIV_ROUND_UP(GPLL_HZ, hz);
+ assert(src_clk_div - 1 < 31);
+
+ switch (clk_id) {
+ case ACLK_VOP_PRE:
+ rk_clrsetreg(&cru->clksel_con[39],
+ ACLK_VOP_PLL_SEL_MASK | ACLK_VOP_DIV_CON_MASK,
+ ACLK_VOP_PLL_SEL_CPLL << ACLK_VOP_PLL_SEL_SHIFT |
+ (src_clk_div - 1) << ACLK_VOP_DIV_CON_SHIFT);
+ break;
+ case ACLK_VIO_PRE:
+ rk_clrsetreg(&cru->clksel_con[37],
+ ACLK_VIO_PLL_SEL_MASK | ACLK_VIO_DIV_CON_MASK,
+ ACLK_VIO_PLL_SEL_CPLL << ACLK_VIO_PLL_SEL_SHIFT |
+ (src_clk_div - 1) << ACLK_VIO_DIV_CON_SHIFT);
+ break;
+ case DCLK_LCDC:
+ con = readl(&cru->clksel_con[40]);
+ con = (con & DCLK_LCDC_SEL_MASK) >> DCLK_LCDC_SEL_SHIFT;
+ if (con) {
+ parent = readl(&cru->clksel_con[40]);
+ parent = (parent & DCLK_LCDC_PLL_SEL_MASK) >>
+ DCLK_LCDC_PLL_SEL_SHIFT;
+ if (parent)
+ src_clk_div = DIV_ROUND_UP(GPLL_HZ, hz);
+ else
+ src_clk_div = DIV_ROUND_UP(GPLL_HZ, hz);
+
+ rk_clrsetreg(&cru->clksel_con[40],
+ DCLK_LCDC_DIV_CON_MASK,
+ (src_clk_div - 1) <<
+ DCLK_LCDC_DIV_CON_SHIFT);
+ }
+ break;
+ default:
+ printf("%s: Unable to set vop clk#%ld\n", __func__, clk_id);
+ return -EINVAL;
+ }
+
+ return rk3328_vop_get_clk(priv, clk_id);
+}
+#endif
+
static ulong rk3328_clk_get_rate(struct clk *clk)
{
struct rk3328_clk_priv *priv = dev_get_priv(clk->dev);
@@ -649,7 +724,13 @@ static ulong rk3328_clk_set_rate(struct clk *clk, ulong rate)
case SCLK_SPI:
ret = rk3328_spi_set_clk(priv->cru, rate);
break;
+#ifndef CONFIG_SPL_BUILD
case DCLK_LCDC:
+ case ACLK_VOP_PRE:
+ case ACLK_VIO_PRE:
+ rate = rk3328_vop_set_clk(priv, clk->id, rate);
+ break;
+#endif
case SCLK_PDM:
case SCLK_RTC32K:
case SCLK_UART0:
@@ -664,11 +745,9 @@ static ulong rk3328_clk_set_rate(struct clk *clk, ulong rate)
case ACLK_PERI_PRE:
case HCLK_PERI:
case PCLK_PERI:
- case ACLK_VIO_PRE:
case HCLK_VIO_PRE:
case ACLK_RGA_PRE:
case SCLK_RGA:
- case ACLK_VOP_PRE:
case ACLK_RKVDEC_PRE:
case ACLK_RKVENC:
case ACLK_VPU_PRE: