mirror of
https://github.com/armbian/build
synced 2025-09-24 19:47:06 +07:00
340 lines
9.8 KiB
Diff
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(®s->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(®s->sys_ctrl, V_STANDBY_EN(1));
|
|
+ clrsetbits_le32(®s->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:
|