* [PATCH v3 01/12] video: rockchip: dw-mipi-dsi: Depend on CONFIG_VIDEO_BRIDGE
2025-04-12 14:27 [PATCH v3 00/12] Rockchip VOP2 support Dang Huynh
@ 2025-04-12 14:27 ` Dang Huynh
2025-04-12 14:27 ` [PATCH v3 02/12] video: rockchip: dw_mipi_dsi: Improve pixel clock calculations Dang Huynh
` (10 subsequent siblings)
11 siblings, 0 replies; 20+ messages in thread
From: Dang Huynh @ 2025-04-12 14:27 UTC (permalink / raw)
To: Anatolij Gustschin, Simon Glass, Philipp Tomsich, Kever Yang,
Tom Rini, Nicolas Frattaroli, Jonas Karlman, Ondrej Jirman,
Dragan Simic, Svyatoslav Ryhel, Lukasz Majewski, Sean Anderson
Cc: Nicolas Frattaroli, u-boot, Piotr Zalewski, Dang Huynh
The driver is in video bridge class, so we must depend on it or
the driver will fail to init.
Reviewed-by: Svyatoslav Ryhel <clamor95@gmail.com>
Signed-off-by: Dang Huynh <danct12@riseup.net>
---
drivers/video/rockchip/Kconfig | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/video/rockchip/Kconfig b/drivers/video/rockchip/Kconfig
index 01804dcb1cc8743e738d32540bea6c8539e51ab4..72fcd6715a69e522f2ba6e8de9c1a923106ca10f 100644
--- a/drivers/video/rockchip/Kconfig
+++ b/drivers/video/rockchip/Kconfig
@@ -71,7 +71,7 @@ config DISPLAY_ROCKCHIP_MIPI
config DISPLAY_ROCKCHIP_DW_MIPI
bool "Rockchip Designware MIPI"
- depends on VIDEO_ROCKCHIP
+ depends on VIDEO_ROCKCHIP && VIDEO_BRIDGE
select VIDEO_DW_MIPI_DSI
help
Select the Designware MIPI DSI controller in use on some Rockchip
--
2.49.0
^ permalink raw reply related [flat|nested] 20+ messages in thread* [PATCH v3 02/12] video: rockchip: dw_mipi_dsi: Improve pixel clock calculations
2025-04-12 14:27 [PATCH v3 00/12] Rockchip VOP2 support Dang Huynh
2025-04-12 14:27 ` [PATCH v3 01/12] video: rockchip: dw-mipi-dsi: Depend on CONFIG_VIDEO_BRIDGE Dang Huynh
@ 2025-04-12 14:27 ` Dang Huynh
2025-04-12 14:27 ` [PATCH v3 03/12] video: rockchip: dw_mipi_dsi: Proceed when external PHY is not defined Dang Huynh
` (9 subsequent siblings)
11 siblings, 0 replies; 20+ messages in thread
From: Dang Huynh @ 2025-04-12 14:27 UTC (permalink / raw)
To: Anatolij Gustschin, Simon Glass, Philipp Tomsich, Kever Yang,
Tom Rini, Nicolas Frattaroli, Jonas Karlman, Ondrej Jirman,
Dragan Simic, Svyatoslav Ryhel, Lukasz Majewski, Sean Anderson
Cc: Nicolas Frattaroli, u-boot, Piotr Zalewski, Dang Huynh
From: Ondrej Jirman <megi@xff.cz>
Calculate burst mode overhead in one place for both internal
and external PHY use case and exit if out of range, instead
of ignoring the wrong value.
Signed-off-by: Ondrej Jirman <megi@xff.cz>
Signed-off-by: Dang Huynh <danct12@riseup.net>
---
drivers/video/rockchip/dw_mipi_dsi_rockchip.c | 24 ++++++++++--------------
1 file changed, 10 insertions(+), 14 deletions(-)
diff --git a/drivers/video/rockchip/dw_mipi_dsi_rockchip.c b/drivers/video/rockchip/dw_mipi_dsi_rockchip.c
index fa512173510b1ee6f51e6269eb249e24d0e980f8..c47992dfb133cda029eba82e842ac824ceead64b 100644
--- a/drivers/video/rockchip/dw_mipi_dsi_rockchip.c
+++ b/drivers/video/rockchip/dw_mipi_dsi_rockchip.c
@@ -526,8 +526,6 @@ dw_mipi_dsi_get_lane_mbps(void *priv_data, struct display_timing *timings,
struct udevice *dev = device->dev;
struct dw_rockchip_dsi_priv *dsi = dev_get_priv(dev);
int bpp;
- unsigned long mpclk, tmp;
- unsigned int target_mbps = 1000;
unsigned int max_mbps = dppa_map[ARRAY_SIZE(dppa_map) - 1].max_mbps;
unsigned long best_freq = 0;
unsigned long fvco_min, fvco_max, fin, fout;
@@ -544,30 +542,28 @@ dw_mipi_dsi_get_lane_mbps(void *priv_data, struct display_timing *timings,
return bpp;
}
- mpclk = DIV_ROUND_UP(timings->pixelclock.typ, 1000);
- if (mpclk) {
- /* take 1 / 0.8, since mbps must big than bandwidth of RGB */
- tmp = (mpclk * (bpp / lanes) * 10 / 8) / 1000;
- if (tmp < max_mbps)
- target_mbps = tmp;
- else
- dev_err(dsi->dsi_host,
- "DPHY clock frequency is out of range\n");
+ fout = timings->pixelclock.typ / MSEC_PER_SEC * bpp / lanes;
+ if (device->mode_flags & MIPI_DSI_MODE_VIDEO_BURST)
+ fout = fout * 12 / 10;
+ fout *= MSEC_PER_SEC;
+
+ if (fout > max_mbps * USEC_PER_SEC) {
+ dev_err(dsi->dsi_host, "DPHY clock frequency is out of range\n");
+ return -EINVAL;
}
/* for external phy only the mipi_dphy_config is necessary */
if (generic_phy_valid(&dsi->phy)) {
- phy_mipi_dphy_get_default_config(timings->pixelclock.typ * 10 / 8,
+ phy_mipi_dphy_get_default_config(fout / bpp * lanes,
bpp, lanes,
&dsi->phy_opts);
- dsi->lane_mbps = target_mbps;
+ dsi->lane_mbps = DIV_ROUND_UP(fout, USEC_PER_SEC);
*lane_mbps = dsi->lane_mbps;
return 0;
}
fin = clk_get_rate(dsi->ref);
- fout = target_mbps * USEC_PER_SEC;
/* constraint: 5Mhz <= Fref / N <= 40MHz */
min_prediv = DIV_ROUND_UP(fin, 40 * USEC_PER_SEC);
--
2.49.0
^ permalink raw reply related [flat|nested] 20+ messages in thread* [PATCH v3 03/12] video: rockchip: dw_mipi_dsi: Proceed when external PHY is not defined
2025-04-12 14:27 [PATCH v3 00/12] Rockchip VOP2 support Dang Huynh
2025-04-12 14:27 ` [PATCH v3 01/12] video: rockchip: dw-mipi-dsi: Depend on CONFIG_VIDEO_BRIDGE Dang Huynh
2025-04-12 14:27 ` [PATCH v3 02/12] video: rockchip: dw_mipi_dsi: Improve pixel clock calculations Dang Huynh
@ 2025-04-12 14:27 ` Dang Huynh
2025-04-12 14:27 ` [PATCH v3 04/12] video: rockchip: dw-mipi-dsi: Add get_display_timing support Dang Huynh
` (8 subsequent siblings)
11 siblings, 0 replies; 20+ messages in thread
From: Dang Huynh @ 2025-04-12 14:27 UTC (permalink / raw)
To: Anatolij Gustschin, Simon Glass, Philipp Tomsich, Kever Yang,
Tom Rini, Nicolas Frattaroli, Jonas Karlman, Ondrej Jirman,
Dragan Simic, Svyatoslav Ryhel, Lukasz Majewski, Sean Anderson
Cc: Nicolas Frattaroli, u-boot, Piotr Zalewski, Dang Huynh
From: Ondrej Jirman <megi@xff.cz>
In this case the DM returns ENOENT, not ENODATA.
Signed-off-by: Ondrej Jirman <megi@xff.cz>
Reviewed-by: Svyatoslav Ryhel <clamor95@gmail.com>
Signed-off-by: Dang Huynh <danct12@riseup.net>
---
drivers/video/rockchip/dw_mipi_dsi_rockchip.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/video/rockchip/dw_mipi_dsi_rockchip.c b/drivers/video/rockchip/dw_mipi_dsi_rockchip.c
index c47992dfb133cda029eba82e842ac824ceead64b..95e825eb3d6de7ef2836fa029927034394486e9c 100644
--- a/drivers/video/rockchip/dw_mipi_dsi_rockchip.c
+++ b/drivers/video/rockchip/dw_mipi_dsi_rockchip.c
@@ -839,7 +839,7 @@ static int dw_mipi_dsi_rockchip_probe(struct udevice *dev)
* NULL if it's not initialized.
*/
ret = generic_phy_get_by_name(dev, "dphy", &priv->phy);
- if (ret && ret != -ENODATA) {
+ if (ret && ret != -ENOENT) {
dev_err(dev, "failed to get mipi dphy: %d\n", ret);
return ret;
}
--
2.49.0
^ permalink raw reply related [flat|nested] 20+ messages in thread* [PATCH v3 04/12] video: rockchip: dw-mipi-dsi: Add get_display_timing support
2025-04-12 14:27 [PATCH v3 00/12] Rockchip VOP2 support Dang Huynh
` (2 preceding siblings ...)
2025-04-12 14:27 ` [PATCH v3 03/12] video: rockchip: dw_mipi_dsi: Proceed when external PHY is not defined Dang Huynh
@ 2025-04-12 14:27 ` Dang Huynh
2025-04-12 14:27 ` [PATCH v3 05/12] video: Add BOE TH101MB31IG002-28A MIPI-DSI panel Dang Huynh
` (7 subsequent siblings)
11 siblings, 0 replies; 20+ messages in thread
From: Dang Huynh @ 2025-04-12 14:27 UTC (permalink / raw)
To: Anatolij Gustschin, Simon Glass, Philipp Tomsich, Kever Yang,
Tom Rini, Nicolas Frattaroli, Jonas Karlman, Ondrej Jirman,
Dragan Simic, Svyatoslav Ryhel, Lukasz Majewski, Sean Anderson
Cc: Nicolas Frattaroli, u-boot, Piotr Zalewski, Dang Huynh
This allows video drivers to obtain display timings from the video
bridge.
Reviewed-by: Svyatoslav Ryhel <clamor95@gmail.com>
Signed-off-by: Dang Huynh <danct12@riseup.net>
---
drivers/video/rockchip/dw_mipi_dsi_rockchip.c | 19 +++++++++++++++----
1 file changed, 15 insertions(+), 4 deletions(-)
diff --git a/drivers/video/rockchip/dw_mipi_dsi_rockchip.c b/drivers/video/rockchip/dw_mipi_dsi_rockchip.c
index 95e825eb3d6de7ef2836fa029927034394486e9c..d21ea7953a6003fa49da3e22220d3312109f600c 100644
--- a/drivers/video/rockchip/dw_mipi_dsi_rockchip.c
+++ b/drivers/video/rockchip/dw_mipi_dsi_rockchip.c
@@ -224,6 +224,7 @@ struct dw_rockchip_dsi_priv {
struct mipi_dsi_device device;
void __iomem *base;
struct udevice *panel;
+ struct display_timing timings;
void __iomem *grf;
/* Optional external dphy */
@@ -709,7 +710,7 @@ static int dw_mipi_dsi_rockchip_attach(struct udevice *dev)
struct dw_rockchip_dsi_priv *priv = dev_get_priv(dev);
struct mipi_dsi_device *device = &priv->device;
struct mipi_dsi_panel_plat *mplat;
- struct display_timing timings;
+ struct display_timing *timings = &priv->timings;
int ret;
ret = uclass_first_device_err(UCLASS_PANEL, &priv->panel);
@@ -724,10 +725,10 @@ static int dw_mipi_dsi_rockchip_attach(struct udevice *dev)
device->format = mplat->format;
device->mode_flags = mplat->mode_flags;
- ret = panel_get_display_timing(priv->panel, &timings);
+ ret = panel_get_display_timing(priv->panel, timings);
if (ret) {
ret = ofnode_decode_display_timing(dev_ofnode(priv->panel),
- 0, &timings);
+ 0, timings);
if (ret) {
dev_err(dev, "decode display timing error %d\n", ret);
return ret;
@@ -740,7 +741,7 @@ static int dw_mipi_dsi_rockchip_attach(struct udevice *dev)
return ret;
}
- ret = dsi_host_init(priv->dsi_host, device, &timings, 4,
+ ret = dsi_host_init(priv->dsi_host, device, timings, 4,
&dsi_rockchip_phy_ops);
if (ret) {
dev_err(dev, "failed to initialize mipi dsi host\n");
@@ -902,9 +903,19 @@ static int dw_mipi_dsi_rockchip_probe(struct udevice *dev)
return 0;
}
+static int dw_mipi_dsi_rockchip_get_dt(struct udevice *dev,
+ struct display_timing *timings)
+{
+ struct dw_rockchip_dsi_priv *priv = dev_get_priv(dev);
+
+ memcpy(timings, &priv->timings, sizeof(*timings));
+ return 0;
+}
+
struct video_bridge_ops dw_mipi_dsi_rockchip_ops = {
.attach = dw_mipi_dsi_rockchip_attach,
.set_backlight = dw_mipi_dsi_rockchip_set_bl,
+ .get_display_timing = dw_mipi_dsi_rockchip_get_dt,
};
static const struct rockchip_dw_dsi_chip_data rk3399_chip_data[] = {
--
2.49.0
^ permalink raw reply related [flat|nested] 20+ messages in thread* [PATCH v3 05/12] video: Add BOE TH101MB31IG002-28A MIPI-DSI panel
2025-04-12 14:27 [PATCH v3 00/12] Rockchip VOP2 support Dang Huynh
` (3 preceding siblings ...)
2025-04-12 14:27 ` [PATCH v3 04/12] video: rockchip: dw-mipi-dsi: Add get_display_timing support Dang Huynh
@ 2025-04-12 14:27 ` Dang Huynh
2025-04-12 14:27 ` [PATCH v3 06/12] video: rockchip: Add VOP2 support Dang Huynh
` (6 subsequent siblings)
11 siblings, 0 replies; 20+ messages in thread
From: Dang Huynh @ 2025-04-12 14:27 UTC (permalink / raw)
To: Anatolij Gustschin, Simon Glass, Philipp Tomsich, Kever Yang,
Tom Rini, Nicolas Frattaroli, Jonas Karlman, Ondrej Jirman,
Dragan Simic, Svyatoslav Ryhel, Lukasz Majewski, Sean Anderson
Cc: Nicolas Frattaroli, u-boot, Piotr Zalewski, Dang Huynh
BOE TH101MB31IG002-28A is a MIPI-DSI panel used in the Pine64
PineTab2.
Reviewed-by: Svyatoslav Ryhel <clamor95@gmail.com>
Signed-off-by: Dang Huynh <danct12@riseup.net>
---
drivers/video/Kconfig | 10 ++
drivers/video/Makefile | 1 +
drivers/video/boe-th101mb31ig002-28a.c | 236 +++++++++++++++++++++++++++++++++
3 files changed, 247 insertions(+)
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index df607303616b626d1e73452787ab6e20cce44d33..3cc1b76bfcb4d9928e36c48ce0d0939f49e6de13 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -510,6 +510,16 @@ config VIDEO_BCM2835
that same resolution (or as near as possible) and 32bpp depth, so
that U-Boot can access it with full colour depth.
+config VIDEO_LCD_BOE_TH101MB31IG002_28A
+ bool "BOE TH101MB31IG002-28A DSI LCD panel support"
+ depends on PANEL && BACKLIGHT
+ select VIDEO_MIPI_DSI
+ help
+ Say Y here if you want to enable support for BOE TH101MB31IG002-28A
+ panel.
+
+ This panel has a 800x1280 resolution and uses 24 bit RGB per pixel.
+
config VIDEO_LCD_ENDEAVORU
tristate "Endeavoru 720x1280 DSI video mode panel"
depends on PANEL && BACKLIGHT
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index bbd5db46553cf8904ee7dfa0bffbeb9f2c086a47..8fc6a52e212c6357843c373f1b69248868da1bdb 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -56,6 +56,7 @@ obj-$(CONFIG_VIDEO_EFI) += efi.o
obj-y += imx/
obj-$(CONFIG_VIDEO_IVYBRIDGE_IGD) += ivybridge_igd.o
obj-$(CONFIG_VIDEO_LCD_ANX9804) += anx9804.o
+obj-$(CONFIG_VIDEO_LCD_BOE_TH101MB31IG002_28A) += boe-th101mb31ig002-28a.o
obj-$(CONFIG_VIDEO_LCD_ENDEAVORU) += endeavoru-panel.o
obj-$(CONFIG_VIDEO_LCD_HIMAX_HX8394) += himax-hx8394.o
obj-$(CONFIG_VIDEO_LCD_HITACHI_TX18D42VM) += hitachi_tx18d42vm_lcd.o
diff --git a/drivers/video/boe-th101mb31ig002-28a.c b/drivers/video/boe-th101mb31ig002-28a.c
new file mode 100644
index 0000000000000000000000000000000000000000..4a6eb99dd80823717ea22b43fc31ed4c937b489a
--- /dev/null
+++ b/drivers/video/boe-th101mb31ig002-28a.c
@@ -0,0 +1,236 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2023 Alexander Warnecke <awarnecke002@hotmail.com>
+ * Copyright (c) 2023 Manuel Traut <manut@mecka.net>
+ * Copyright (c) 2023 Dang Huynh <danct12@riseup.net>
+ */
+
+#include <backlight.h>
+#include <dm.h>
+#include <log.h>
+#include <mipi_dsi.h>
+#include <panel.h>
+#include <asm/gpio.h>
+#include <dm/device_compat.h>
+#include <linux/delay.h>
+#include <power/regulator.h>
+
+struct th101mb31ig002_28a_panel_priv {
+ struct udevice *backlight;
+ struct udevice *reg_power;
+ struct gpio_desc enable;
+ struct gpio_desc reset;
+};
+
+static const struct display_timing boe_th101mb31ig002_default_timing = {
+ .pixelclock.typ = 73500000,
+ .hactive.typ = 800,
+ .hfront_porch.typ = 64,
+ .hback_porch.typ = 64,
+ .hsync_len.typ = 16,
+ .vactive.typ = 1280,
+ .vfront_porch.typ = 2,
+ .vback_porch.typ = 12,
+ .vsync_len.typ = 4,
+};
+
+#define dsi_dcs_write_seq(device, seq...) do { \
+ static const u8 d[] = { seq }; \
+ int ret; \
+ ret = mipi_dsi_dcs_write_buffer(device, d, ARRAY_SIZE(d)); \
+ if (ret < 0) \
+ return ret; \
+ } while (0)
+
+static int th101mb31ig002_28a_init_sequence(struct udevice *dev)
+{
+ struct mipi_dsi_panel_plat *plat = dev_get_plat(dev);
+ struct mipi_dsi_device *device = plat->device;
+ int ret;
+
+ dsi_dcs_write_seq(device, 0xE0, 0xAB, 0xBA);
+ dsi_dcs_write_seq(device, 0xE1, 0xBA, 0xAB);
+ dsi_dcs_write_seq(device, 0xB1, 0x10, 0x01, 0x47, 0xFF);
+ dsi_dcs_write_seq(device, 0xB2, 0x0C, 0x14, 0x04, 0x50, 0x50, 0x14);
+ dsi_dcs_write_seq(device, 0xB3, 0x56, 0x53, 0x00);
+ dsi_dcs_write_seq(device, 0xB4, 0x33, 0x30, 0x04);
+ dsi_dcs_write_seq(device, 0xB6, 0xB0, 0x00, 0x00, 0x10, 0x00, 0x10, 0x00);
+ dsi_dcs_write_seq(device, 0xB8, 0x05, 0x12, 0x29, 0x49, 0x48, 0x00, 0x00);
+ dsi_dcs_write_seq(device, 0xB9, 0x7C, 0x65, 0x55, 0x49, 0x46, 0x36, 0x3B, 0x24, 0x3D,
+ 0x3C, 0x3D, 0x5C, 0x4C, 0x55, 0x47, 0x46, 0x39, 0x26, 0x06, 0x7C, 0x65,
+ 0x55, 0x49, 0x46, 0x36, 0x3B, 0x24, 0x3D, 0x3C, 0x3D, 0x5C, 0x4C, 0x55,
+ 0x47, 0x46, 0x39, 0x26, 0x06);
+ dsi_dcs_write_seq(device, 0xC0, 0xFF, 0x87, 0x12, 0x34, 0x44, 0x44, 0x44,
+ 0x44, 0x98, 0x04, 0x98, 0x04, 0x0F, 0x00, 0x00, 0xC1);
+ dsi_dcs_write_seq(device, 0xC1, 0x54, 0x94, 0x02, 0x85, 0x9F, 0x00, 0x7F, 0x00, 0x54,
+ 0x00);
+ dsi_dcs_write_seq(device, 0xC2, 0x17, 0x09, 0x08, 0x89, 0x08, 0x11, 0x22, 0x20, 0x44,
+ 0xFF, 0x18, 0x00);
+ dsi_dcs_write_seq(device, 0xC3, 0x86, 0x46, 0x05, 0x05, 0x1C, 0x1C, 0x1D, 0x1D, 0x02,
+ 0x1F, 0x1F, 0x1E, 0x1E, 0x0F, 0x0F, 0x0D, 0x0D, 0x13, 0x13, 0x11, 0x11,
+ 0x00);
+ dsi_dcs_write_seq(device, 0xC4, 0x07, 0x07, 0x04, 0x04, 0x1C, 0x1C, 0x1D, 0x1D, 0x02,
+ 0x1F, 0x1F, 0x1E, 0x1E, 0x0E, 0x0E, 0x0C, 0x0C, 0x12, 0x12, 0x10, 0x10,
+ 0x00);
+ dsi_dcs_write_seq(device, 0xC6, 0x2A, 0x2A);
+ dsi_dcs_write_seq(device, 0xC8, 0x21, 0x00, 0x31, 0x42, 0x34, 0x16);
+ dsi_dcs_write_seq(device, 0xCA, 0xCB, 0x43);
+ dsi_dcs_write_seq(device, 0xCD, 0x0E, 0x4B, 0x4B, 0x20, 0x19, 0x6B, 0x06, 0xB3);
+ dsi_dcs_write_seq(device, 0xD2, 0xE3, 0x2B, 0x38, 0x00);
+ dsi_dcs_write_seq(device, 0xD4, 0x00, 0x01, 0x00, 0x0E, 0x04, 0x44, 0x08, 0x10, 0x00,
+ 0x00, 0x00);
+ dsi_dcs_write_seq(device, 0xE6, 0x80, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF);
+ dsi_dcs_write_seq(device, 0xF0, 0x12, 0x03, 0x20, 0x00, 0xFF);
+ dsi_dcs_write_seq(device, 0xF3, 0x00);
+
+ ret = mipi_dsi_dcs_exit_sleep_mode(device);
+ if (ret)
+ return ret;
+
+ mdelay(120);
+
+ ret = mipi_dsi_dcs_set_display_on(device);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int th101mb31ig002_28a_panel_enable_backlight(struct udevice *dev)
+{
+ struct mipi_dsi_panel_plat *plat = dev_get_plat(dev);
+ struct mipi_dsi_device *device = plat->device;
+ struct th101mb31ig002_28a_panel_priv *priv = dev_get_priv(dev);
+ int ret;
+
+ ret = mipi_dsi_attach(device);
+ if (ret < 0) {
+ dev_err(dev, "Failed to attach display: %d\n", ret);
+ return ret;
+ }
+
+ ret = th101mb31ig002_28a_init_sequence(dev);
+ if (ret) {
+ dev_err(dev, "Failed to init display: %d\n", ret);
+ return ret;
+ }
+
+ if (priv->backlight) {
+ ret = backlight_enable(priv->backlight);
+ if (ret) {
+ dev_err(dev, "Failed to enable backlight: %d\n", ret);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+static int th101mb31ig002_28a_panel_set_backlight(struct udevice *dev, int percent)
+{
+ struct th101mb31ig002_28a_panel_priv *priv = dev_get_priv(dev);
+
+ return backlight_set_brightness(priv->backlight, percent);
+}
+
+static int th101mb31ig002_28a_panel_get_display_timing(struct udevice *dev,
+ struct display_timing *timings)
+{
+ memcpy(timings, &boe_th101mb31ig002_default_timing, sizeof(*timings));
+
+ return 0;
+}
+
+static int th101mb31ig002_28a_panel_of_to_plat(struct udevice *dev)
+{
+ struct th101mb31ig002_28a_panel_priv *priv = dev_get_priv(dev);
+ int ret;
+
+ if (CONFIG_IS_ENABLED(DM_REGULATOR)) {
+ ret = device_get_supply_regulator(dev, "power-supply",
+ &priv->reg_power);
+ if (ret && ret != -ENOENT) {
+ dev_err(dev, "Warning: cannot get power supply\n");
+ return ret;
+ }
+ }
+
+ ret = uclass_get_device_by_phandle(UCLASS_PANEL_BACKLIGHT, dev,
+ "backlight", &priv->backlight);
+ if (ret)
+ dev_warn(dev, "failed to get backlight\n");
+
+ ret = gpio_request_by_name(dev, "enable-gpios", 0, &priv->enable,
+ GPIOD_IS_OUT);
+ if (ret) {
+ dev_err(dev, "Failed to get enable GPIO (%d)\n", ret);
+ if (ret != -ENOENT)
+ return ret;
+ }
+
+ ret = gpio_request_by_name(dev, "reset-gpios", 0, &priv->reset,
+ GPIOD_IS_OUT);
+ if (ret) {
+ dev_err(dev, "Failed to get reset GPIO (%d)\n", ret);
+ if (ret != -ENOENT)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int th101mb31ig002_28a_panel_probe(struct udevice *dev)
+{
+ struct th101mb31ig002_28a_panel_priv *priv = dev_get_priv(dev);
+ struct mipi_dsi_panel_plat *plat = dev_get_plat(dev);
+ int ret;
+
+ if (CONFIG_IS_ENABLED(DM_REGULATOR) && priv->reg_power) {
+ ret = regulator_set_enable(priv->reg_power, true);
+ if (ret)
+ return ret;
+ }
+
+ /* enable panel */
+ dm_gpio_set_value(&priv->enable, 1);
+ mdelay(50);
+
+ /* reset panel */
+ dm_gpio_set_value(&priv->reset, 0);
+ udelay(10);
+ dm_gpio_set_value(&priv->reset, 1);
+ udelay(10);
+ dm_gpio_set_value(&priv->reset, 0);
+ mdelay(5);
+
+ plat->lanes = 4;
+ plat->format = MIPI_DSI_FMT_RGB888;
+ plat->mode_flags = MIPI_DSI_MODE_VIDEO |
+ MIPI_DSI_MODE_VIDEO_BURST |
+ MIPI_DSI_MODE_EOT_PACKET |
+ MIPI_DSI_MODE_LPM;
+
+ return 0;
+}
+
+static const struct panel_ops th101mb31ig002_28a_panel_ops = {
+ .enable_backlight = th101mb31ig002_28a_panel_enable_backlight,
+ .set_backlight = th101mb31ig002_28a_panel_set_backlight,
+ .get_display_timing = th101mb31ig002_28a_panel_get_display_timing,
+};
+
+static const struct udevice_id th101mb31ig002_28a_ids[] = {
+ { .compatible = "boe,th101mb31ig002-28a", },
+ { /* sentinel */ }
+};
+
+U_BOOT_DRIVER(th101mb31ig002_28a_panel) = {
+ .name = "th101mb31ig002_28a_panel",
+ .id = UCLASS_PANEL,
+ .of_match = th101mb31ig002_28a_ids,
+ .ops = &th101mb31ig002_28a_panel_ops,
+ .of_to_plat = th101mb31ig002_28a_panel_of_to_plat,
+ .probe = th101mb31ig002_28a_panel_probe,
+ .plat_auto = sizeof(struct mipi_dsi_panel_plat),
+ .priv_auto = sizeof(struct th101mb31ig002_28a_panel_priv),
+};
--
2.49.0
^ permalink raw reply related [flat|nested] 20+ messages in thread* [PATCH v3 06/12] video: rockchip: Add VOP2 support
2025-04-12 14:27 [PATCH v3 00/12] Rockchip VOP2 support Dang Huynh
` (4 preceding siblings ...)
2025-04-12 14:27 ` [PATCH v3 05/12] video: Add BOE TH101MB31IG002-28A MIPI-DSI panel Dang Huynh
@ 2025-04-12 14:27 ` Dang Huynh
2025-04-12 14:27 ` [PATCH v3 07/12] video: rockchip: vop2: Add video bridge support Dang Huynh
` (5 subsequent siblings)
11 siblings, 0 replies; 20+ messages in thread
From: Dang Huynh @ 2025-04-12 14:27 UTC (permalink / raw)
To: Anatolij Gustschin, Simon Glass, Philipp Tomsich, Kever Yang,
Tom Rini, Nicolas Frattaroli, Jonas Karlman, Ondrej Jirman,
Dragan Simic, Svyatoslav Ryhel, Lukasz Majewski, Sean Anderson
Cc: Nicolas Frattaroli, u-boot, Piotr Zalewski, Dang Huynh
VOP2 (Video Output Processor v2) is a display controller on Rockchip
SoCs. It can be found on RK3566/8 and RK3588.
This commit currently only supports RK3566/8.
Signed-off-by: Dang Huynh <danct12@riseup.net>
---
arch/arm/include/asm/arch-rockchip/vop_rk3568.h | 280 +++++++++++++
drivers/video/rockchip/Makefile | 3 +-
drivers/video/rockchip/rk3568_vop.c | 268 ++++++++++++
drivers/video/rockchip/rk_vop2.c | 523 ++++++++++++++++++++++++
drivers/video/rockchip/rk_vop2.h | 76 ++++
5 files changed, 1149 insertions(+), 1 deletion(-)
diff --git a/arch/arm/include/asm/arch-rockchip/vop_rk3568.h b/arch/arm/include/asm/arch-rockchip/vop_rk3568.h
new file mode 100644
index 0000000000000000000000000000000000000000..1474ddbe5df4de10f9655aa53182cf5a2ba30c1e
--- /dev/null
+++ b/arch/arm/include/asm/arch-rockchip/vop_rk3568.h
@@ -0,0 +1,280 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2024 Dang Huynh <danct12@riseup.net>
+ *
+ * Based on vop_rk3288.h:
+ * Copyright (c) 2015 Google, Inc
+ * Copyright 2014 Rockchip Inc.
+ */
+
+#ifndef _ASM_ARCH_VOP_RK3568_H
+#define _ASM_ARCH_VOP_RK3568_H
+
+struct rk3568_vop_sysctrl {
+ u32 reg_cfg_done;
+ u32 version_info;
+ u32 autogating_ctrl;
+ u32 win_reg_cfg_done;
+ u32 axi_ctrl0;
+ u32 axi_hurry_ctrl0;
+ u32 axi_hurry_ctrl1;
+ u32 axi_outstanding_ctrl0;
+ u32 axi_outstanding_ctrl1;
+ u32 axi_lut_ctrl;
+ u32 dsp_en;
+ u32 dsp_ctrl;
+ u32 dsp_pol;
+ u32 pwr_ctrl;
+ u32 var_freq_ctrl;
+ u32 mmu_raddr_range;
+ u32 wb_ctrl0;
+ u32 wb_xspd;
+ u32 wb_yrgb_mst;
+ u32 wb_cbr_mst;
+ u32 otp_win;
+ u32 otp_mirr_ctrl;
+ u32 lut_port_sel;
+ u32 pwr_stable_ctrl;
+ u32 status0;
+ u32 status1;
+ u32 status2;
+ u32 status3;
+ u32 line_flag0;
+ u32 line_flag1;
+ u32 line_flag2;
+ u32 line_flag3;
+ u32 sys0_intr_en;
+ u32 sys0_intr_clr;
+ u32 sys0_intr_status;
+ u32 sys0_intr_status_raw;
+ u32 sys1_intr_en;
+ u32 sys1_intr_clr;
+ u32 sys1_intr_status;
+ u32 sys1_intr_status_raw;
+ u32 port0_intr_en;
+ u32 port0_intr_clr;
+ u32 port0_intr_status;
+ u32 port0_intr_status_raw;
+ u32 port1_intr_en;
+ u32 port1_intr_clr;
+ u32 port1_intr_status;
+ u32 port1_intr_status_raw;
+ u32 port2_intr_en;
+ u32 port2_intr_clr;
+ u32 port2_intr_status;
+ u32 port2_intr_status_raw;
+ u32 port3_intr_en;
+ u32 port3_intr_clr;
+ u32 port3_intr_status;
+ u32 port3_intr_status_raw;
+};
+
+check_member(rk3568_vop_sysctrl, port3_intr_status_raw, 0x00DC);
+
+struct rk3568_vop_overlay {
+ u32 overlay_ctrl;
+ u32 layer_sel;
+ u32 port_sel;
+};
+
+check_member(rk3568_vop_overlay, port_sel, 0x0008);
+
+struct rk3568_vop_post {
+ u32 dsp_ctrl;
+ u32 mipi_ctrl;
+ u32 color_ctrl;
+ u32 reserved2;
+ u32 lut_reserved[4];
+ u32 reserved[3];
+ u32 dsp_bg;
+ u32 prescan_htimings;
+ u32 dsp_hact_info;
+ u32 dsp_vact_info;
+ u32 scl_factor_yrgb;
+ u32 scl_ctrl;
+ u32 dsp_vact_info_f1;
+ u32 dsp_htotal_hs_end;
+ u32 dsp_hact_st_end;
+ u32 dsp_vtotal_vs_end;
+ u32 dsp_vact_st_end;
+ u32 dsp_vs_st_end_f1;
+ u32 dsp_vact_st_end_f1;
+};
+
+check_member(rk3568_vop_post, dsp_vact_st_end_f1, 0x005C);
+
+struct rk3568_vop_cluster {
+ u32 win0_ctrl0;
+ u32 win0_ctrl1;
+ u32 win0_ctrl2;
+ u32 reserved0;
+ u32 win0_mst_yrgb;
+ u32 win0_mst_cbcr;
+ u32 win0_vir;
+ u32 reserved1;
+ u32 win0_act_info;
+ u32 win0_dsp_info;
+ u32 win0_dsp_st;
+ u32 win0_dsp_bg;
+ u32 win0_scl_factor_yrgb;
+ u32 reserved2;
+ u32 win0_scl_offset;
+ u32 win0_transformed_offset;
+ u32 reserved3[4];
+ u32 win0_afbcd_output_ctrl;
+ u32 win0_afbcd_mode;
+ u32 win0_afbcd_hdr_ptr;
+ u32 win0_afbcd_vir_width;
+ u32 win0_afbcd_size;
+ u32 win0_afbcd_pic_offset;
+ u32 win0_afbcd_dis_offset;
+ u32 win0_afbcd_ctrl;
+};
+
+check_member(rk3568_vop_cluster, win0_afbcd_ctrl, 0x006C);
+
+struct rk3568_vop_esmart {
+ u32 esmart_ctrl0;
+ u32 esmart_ctrl1;
+ u32 reserved0[2];
+ u32 esmart_region0_mst_ctl;
+ u32 esmart_region0_mst_yrgb;
+ u32 esmart_region0_mst_cbcr;
+ u32 esmart_region0_vir;
+ u32 esmart_region0_act_info;
+ u32 esmart_region0_dsp_info;
+ u32 esmart_region0_dsp_offset;
+ u32 reserved1[1];
+ u32 esmart_region0_scl_ctrl;
+ u32 esmart_region0_scl_factor_yrgb;
+ u32 esmart_region0_scl_factor_cbcr;
+ u32 esmart_region0_scl_offset;
+};
+
+check_member(rk3568_vop_esmart, esmart_region0_scl_offset, 0x003C);
+
+enum rockchip_fb_data_format_t {
+ ARGB8888 = 0,
+ RGB888 = 1,
+ RGB565 = 2,
+};
+
+enum vop_modes {
+ VOP_MODE_EDP = 0,
+ VOP_MODE_MIPI,
+ VOP_MODE_HDMI,
+ VOP_MODE_LVDS,
+ VOP_MODE_DP,
+};
+
+/* OFFSETS */
+#define VOP2_SYSREG_OFFSET 0x0
+#define VOP2_OVERLAY_OFFSET 0x0600
+#define VOP2_POST_OFFSET(n) 0x0c00 + ((n) * 0x100)
+#define VOP2_CLUSTER_OFFSET(n) 0x1000 + ((n) * 0x200)
+#define VOP2_ESMART_OFFSET(n) 0x1800 + ((n) * 0x200)
+
+/* System Registers */
+/* REG_CFG_DONE */
+#define M_GLOBAL_REGDONE (1 << 15)
+#define M_LOAD_GLOBAL(x) (1 << ((x) & 3))
+
+#define V_GLOBAL_REGDONE(x) (((x) & 1) << 15)
+#define V_LOAD_GLOBAL(x, y) (((y) & 1) << ((x) & 3))
+
+/* VERSION_INFO */
+#define M_FPGA_VERSION (0xffff << 16)
+#define M_RTL_VERSION (0xffff)
+
+/* AUTO_GATING_CTRL */
+#define M_AUTO_GATING (1 << 31)
+#define V_AUTO_GATING(x) (((x) & 1) << 31)
+
+/* DSP_INFACE_POL */
+#define M_DSP_INFACE_REGDONE (1 << 28)
+#define V_DSP_INFACE_REGDONE(x) (((x) & 1) << 28)
+
+/* OTP_WIN_EN */
+#define M_OTP_WIN (1 << 0)
+#define V_OTP_WIN(x) (((x) & 1) << 0)
+
+/* Overlay */
+/* OVERLAY_CTRL */
+#define M_LAYER_SEL_REGDONE_SEL (3 << 30)
+#define M_LAYER_SEL_REGDONE_EN (1 << 28)
+#define M_VP_OVERLAY_MODE(vp) (1 << ((vp) & 3))
+
+#define V_LAYER_SEL_REGDONE_SEL(x) (((x) & 3) << 30)
+#define V_LAYER_SEL_REGDONE_EN(x) (((x) & 1) << 28)
+#define V_VP_OVERLAY_MODE(x, vp) (((x) & 1) << ((vp) & 3))
+
+/* LAYER_SEL */
+#define V_LAYER_SEL(x, port) (((port) & 7) << 4 * ((x) & 7))
+
+/* PORT_SEL */
+#define V_ESMART_SEL_PORT(x, vp) (((vp) & 3) << (24 + (2 * ((x) & 3))))
+#define V_CLUSTER_SEL_PORT(x, vp) (((vp) & 3) << (16 + (2 * ((x) & 3))))
+#define V_PORT_MUX(x, vp) (((x) & 0xf) << 4 * ((vp) & 3))
+
+/* Post processing */
+/* DSP_CTRL */
+#define M_POST_STANDBY (1 << 31)
+#define M_POST_FP_STANDBY (1 << 30)
+#define M_POST_BLACK (1 << 27)
+#define M_POST_OUT_ZERO (1 << 26)
+#define M_POST_LB_MODE (1 << 23)
+#define M_PRE_DITHER_DOWN (1 << 16)
+#define M_DSP_OUT_MODE (0xf)
+
+#define V_POST_STANDBY(x) (((x) & 1) << 31)
+#define V_POST_FP_STANDBY(x) (((x) & 1) << 30)
+#define V_POST_BLACK(x) (((x) & 1) << 27)
+#define V_POST_OUT_ZERO(x) (((x) & 1) << 26)
+#define V_POST_LB_MODE(x) (((x) & 1) << 23)
+#define V_PRE_DITHER_DOWN(x) (((x) & 1) << 16)
+#define V_DSP_OUT_MODE(x) ((x) & 0xf)
+
+/* COLOR_CTRL */
+#define M_POST_COLORBAR_MODE (1 << 1)
+#define M_POST_COLORBAR_EN (1 << 0)
+
+#define V_POST_COLORBAR_MODE(x) (((x) & 1) << 1)
+#define V_POST_COLORBAR_EN(x) (((x) & 1) << 0)
+
+/* DSP_BG */
+#define M_DSP_BG_RED (0x3f << 20)
+#define M_DSP_BG_GREEN (0x3f << 10)
+#define M_DSP_BG_BLUE (0x3f << 0)
+
+#define V_DSP_BG_RED(x) (((x) & 0x3f) << 20)
+#define V_DSP_BG_GREEN(x) (((x) & 0x3f) << 10)
+#define V_DSP_BG_BLUE(x) (((x) & 0x3f) << 0)
+
+/* ESMART */
+#define M_ESMART_REGION0_MST_EN (1 << 0)
+#define V_ESMART_REGION0_DATA_FMT(x) (((x) & 0x16) << 1)
+
+/* VOP2_ESMART_REGION0_VIR */
+#define V_ARGB888_VIRWIDTH(x) (((x) & 0xffff) << 0)
+#define V_RGB888_VIRWIDTH(x) ((((((x) * 3) >> 2) + ((x) % 3)) & 0xffff) << 0)
+#define V_RGB565_VIRWIDTH(x) ((((x) / 2) & 0xffff) << 0)
+#define YUV_VIRWIDTH(x) ((((x) / 4) & 0xffff) << 0)
+
+#define V_ACT_HEIGHT(x) (((x) & 0x1fff) << 16)
+#define V_ACT_WIDTH(x) ((x) & 0x1fff)
+#define V_DSP_HEIGHT(x) (((x) & 0x1fff) << 16)
+#define V_DSP_WIDTH(x) ((x) & 0x1fff)
+#define V_DSP_YST(x) (((x) & 0x1fff) << 16)
+#define V_DSP_XST(x) ((x) & 0x1fff)
+
+#define V_HSYNC(x) (((x) & 0x1fff) << 0) /* hsync pulse width */
+#define V_HORPRD(x) (((x) & 0x1fff) << 16) /* horizontal period */
+#define V_VSYNC(x) (((x) & 0x1fff) << 0)
+#define V_VERPRD(x) (((x) & 0x1fff) << 16)
+
+#define V_HEAP(x) (((x) & 0x1fff) << 0)/* horizontal active end */
+#define V_HASP(x) (((x) & 0x1fff) << 16)/* horizontal active start */
+#define V_VAEP(x) (((x) & 0x1fff) << 0)
+#define V_VASP(x) (((x) & 0x1fff) << 16)
+
+#endif
diff --git a/drivers/video/rockchip/Makefile b/drivers/video/rockchip/Makefile
index f55beceebf118bbfc6f85b9edf7f64eaa13ffe62..2f89a979a2848733be5a6d05817ad76ce3ad3a34 100644
--- a/drivers/video/rockchip/Makefile
+++ b/drivers/video/rockchip/Makefile
@@ -4,10 +4,11 @@
# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
ifdef CONFIG_VIDEO_ROCKCHIP
-obj-y += rk_vop.o
+obj-y += rk_vop.o rk_vop2.o
obj-$(CONFIG_ROCKCHIP_RK3288) += rk3288_vop.o
obj-$(CONFIG_ROCKCHIP_RK3328) += rk3328_vop.o
obj-$(CONFIG_ROCKCHIP_RK3399) += rk3399_vop.o
+obj-$(CONFIG_ROCKCHIP_RK3568) += rk3568_vop.o
obj-$(CONFIG_DISPLAY_ROCKCHIP_EDP) += rk_edp.o
obj-$(CONFIG_DISPLAY_ROCKCHIP_LVDS) += rk_lvds.o
obj-hdmi-$(CONFIG_ROCKCHIP_RK3288) += rk3288_hdmi.o
diff --git a/drivers/video/rockchip/rk3568_vop.c b/drivers/video/rockchip/rk3568_vop.c
new file mode 100644
index 0000000000000000000000000000000000000000..eaa64ee2e73eb02a2e317bab574e4103c9767e07
--- /dev/null
+++ b/drivers/video/rockchip/rk3568_vop.c
@@ -0,0 +1,268 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2024 Dang Huynh <danct12@riseup.net>
+ *
+ * Based on rk3399_vop.c:
+ * Copyright (c) 2017 Theobroma Systems Design und Consulting GmbH
+ * Copyright (c) 2015 Google, Inc
+ * Copyright 2014 Rockchip Inc.
+ */
+
+#include <clk.h>
+#include <display.h>
+#include <dm.h>
+#include <dm/device_compat.h>
+#include <regmap.h>
+#include <video.h>
+#include <asm/arch-rockchip/hardware.h>
+#include <asm/global_data.h>
+#include <linux/bitfield.h>
+#include "rk_vop2.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define M_MIPI1_INFACE_MUX (3 << 21)
+#define M_LVDS_INFACE_MUX (3 << 18)
+#define M_MIPI_INFACE_MUX (3 << 16)
+#define M_EDP_INFACE_MUX (3 << 14)
+#define M_HDMI_INFACE_MUX (3 << 10)
+#define M_RGB_INFACE_MUX (3 << 8)
+
+#define V_MIPI1_INFACE_MUX(x) (((x) & 3) << 21)
+#define V_LVDS_INFACE_MUX(x) (((x) & 3) << 18)
+#define V_MIPI_INFACE_MUX(x) (((x) & 3) << 16)
+#define V_EDP_INFACE_MUX(x) (((x) & 3) << 14)
+#define V_HDMI_INFACE_MUX(x) (((x) & 3) << 10)
+#define V_RGB_INFACE_MUX(x) (((x) & 3) << 8)
+
+#define M_MIPI_POL (0xf << 16)
+#define M_EDP_POL (0xf << 12)
+#define M_HDMI_POL (0xf << 4)
+#define M_RGB_LVDS_POL (0xf << 0)
+
+#define V_MIPI_POL(x) (((x) & 0xf) << 16)
+#define V_EDP_POL(x) (((x) & 0xf) << 12)
+#define V_HDMI_POL(x) (((x) & 0xf) << 4)
+#define V_RGB_LVDS_POL(x) (((x) & 0xf) << 0)
+
+#define M_MIPI1_OUT_EN (1 << 20)
+#define M_BT656_OUT_EN (1 << 7)
+#define M_BT1120_OUT_EN (1 << 6)
+#define M_LVDS_OUT_EN (1 << 5)
+#define M_MIPI_OUT_EN (1 << 4)
+#define M_EDP_OUT_EN (1 << 3)
+#define M_HDMI_OUT_EN (1 << 1)
+#define M_RGB_OUT_EN (1 << 0)
+
+#define M_ALL_OUT_EN (M_MIPI1_OUT_EN | M_BT656_OUT_EN | M_BT1120_OUT_EN | M_LVDS_OUT_EN | \
+ M_MIPI_OUT_EN | M_EDP_OUT_EN | M_HDMI_OUT_EN | M_RGB_OUT_EN)
+
+#define V_MIPI1_OUT_EN(x) (((x) & 1) << 20)
+#define V_BT656_OUT_EN(x) (((x) & 1) << 7)
+#define V_BT1120_OUT_EN(x) (((x) & 1) << 6)
+#define V_LVDS_OUT_EN(x) (((x) & 1) << 5)
+#define V_MIPI_OUT_EN(x) (((x) & 1) << 4)
+#define V_EDP_OUT_EN(x) (((x) & 1) << 3)
+#define V_HDMI_OUT_EN(x) (((x) & 1) << 1)
+#define V_RGB_OUT_EN(x) (((x) & 1) << 0)
+
+static void rk3568_enable_output(struct udevice *dev,
+ enum vop_modes mode, u32 port)
+{
+ struct rk_vop2_priv *priv = dev_get_priv(dev);
+ struct rk3568_vop_sysctrl *sysctrl = priv->regs + VOP2_SYSREG_OFFSET;
+ u32 reg;
+
+ switch (mode) {
+ case VOP_MODE_EDP:
+ reg |= M_EDP_OUT_EN | V_EDP_INFACE_MUX(port);
+ break;
+
+ case VOP_MODE_HDMI:
+ reg |= M_HDMI_OUT_EN | V_HDMI_INFACE_MUX(port);
+ break;
+
+ case VOP_MODE_MIPI:
+ reg |= M_MIPI_OUT_EN | V_MIPI_INFACE_MUX(port);
+ break;
+
+ case VOP_MODE_LVDS:
+ reg |= M_LVDS_OUT_EN | V_LVDS_INFACE_MUX(port);
+ break;
+
+ default:
+ debug("%s: unsupported output mode %x\n", __func__, mode);
+ return;
+ }
+
+ debug("%s: vop output 0x%08x\n", __func__, reg);
+ writel(reg, &sysctrl->dsp_en);
+}
+
+static void rk3568_set_pin_polarity(struct udevice *dev,
+ enum vop_modes mode, u32 polarity)
+{
+ struct rk_vop2_priv *priv = dev_get_priv(dev);
+ struct rk3568_vop_sysctrl *sysctrl = priv->regs + VOP2_SYSREG_OFFSET;
+ u32 reg;
+
+ reg = M_DSP_INFACE_REGDONE;
+
+ switch (mode) {
+ case VOP_MODE_EDP:
+ reg |= V_EDP_POL(polarity);
+ break;
+
+ case VOP_MODE_HDMI:
+ reg |= V_HDMI_POL(polarity);
+ break;
+
+ case VOP_MODE_MIPI:
+ reg |= V_MIPI_POL(polarity);
+ break;
+
+ /* RGB and LVDS shares the same polarity */
+ case VOP_MODE_LVDS:
+ reg |= V_RGB_LVDS_POL(polarity);
+ break;
+
+ default:
+ debug("%s: unsupported output mode %x\n", __func__, mode);
+ return;
+ }
+
+ debug("%s: vop polarity 0x%08x\n", __func__, reg);
+ writel(reg, &sysctrl->dsp_pol);
+}
+
+static int rkvop2_initialize(struct udevice *dev)
+{
+ struct rk_vop2_priv *priv = dev_get_priv(dev);
+ struct rk3568_vop_sysctrl *sysctrl = priv->regs + VOP2_SYSREG_OFFSET;
+ struct clk aclk;
+ int ret;
+
+ ret = clk_get_by_name(dev, "aclk", &aclk);
+ if (ret < 0)
+ return ret;
+
+ ret = clk_enable(&aclk);
+ if (ret < 0) {
+ dev_err(dev, "Failed to enable aclk: %d\n", ret);
+ return ret;
+ }
+
+ debug("aclk rate: %ld\n", clk_get_rate(&aclk));
+
+ /* Enable OTP function */
+ clrsetbits_le32(&sysctrl->otp_win, M_OTP_WIN, V_OTP_WIN(1));
+
+ writel(M_GLOBAL_REGDONE, &sysctrl->reg_cfg_done);
+
+ /* Disable auto gating */
+ clrsetbits_le32(&sysctrl->autogating_ctrl, M_AUTO_GATING, V_AUTO_GATING(0));
+
+ return 0;
+}
+
+/*
+ * FIXME: Booting into Linux with a window plane enabled causes VOP IOMMU
+ * to fail.
+ *
+ * This can be removed when there's a better way to handle MMU under Linux.
+ */
+static int rk3568_vop_remove(struct udevice *dev)
+{
+ struct rk_vop2_priv *priv = dev_get_priv(dev);
+ struct rk3568_vop_sysctrl *sysctrl = priv->regs + VOP2_SYSREG_OFFSET;
+ struct rk3568_vop_esmart *esmart = priv->regs + VOP2_ESMART_OFFSET(priv->layer - 4);
+
+ debug("Removing VOP2 driver (vp=%d, layer=%d)\n", priv->vp, priv->layer);
+
+ /* RK356X appears to only make use of (E)SMARTs */
+ writel(0, &esmart->esmart_region0_mst_ctl);
+
+ /* On RK3568, we don't need to shift the bit by 16. */
+ writel(M_GLOBAL_REGDONE | M_LOAD_GLOBAL(priv->vp),
+ &sysctrl->reg_cfg_done);
+
+ return 0;
+}
+
+static int rk3568_vop_probe(struct udevice *dev)
+{
+ int ret;
+
+ /* Before relocation we don't need to do anything */
+ if (!(gd->flags & GD_FLG_RELOC))
+ return 0;
+
+ ret = rkvop2_initialize(dev);
+ if (ret)
+ return ret;
+
+ return rk_vop2_probe(dev);
+}
+
+/*
+ * RK3566 datasheet omits the VP2, even though it exist in the hardware
+ * so let's not use it.
+ */
+struct rkvop2_platdata rk3566_platdata = {
+ .delay = 20,
+ .bg_dly = {42, 40, -1},
+ /* SMART0, ESMART0 */
+ .vp_lyr = {3, 2, -1},
+ .layers = {ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_RESERVED,
+ ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_SMART0,
+ ROCKCHIP_VOP2_RESERVED, ROCKCHIP_VOP2_RESERVED,
+ ROCKCHIP_VOP2_RESERVED, ROCKCHIP_VOP2_RESERVED},
+};
+
+struct rkvop2_platdata rk3568_platdata = {
+ .delay = 20,
+ .bg_dly = {42, 40, 40},
+ /* SMART0, SMART1, ESMART1 */
+ .vp_lyr = {3, 7, 6},
+ .layers = {ROCKCHIP_VOP2_CLUSTER0, ROCKCHIP_VOP2_CLUSTER1,
+ ROCKCHIP_VOP2_ESMART0, ROCKCHIP_VOP2_SMART0,
+ ROCKCHIP_VOP2_RESERVED, ROCKCHIP_VOP2_RESERVED,
+ ROCKCHIP_VOP2_ESMART1, ROCKCHIP_VOP2_SMART1},
+};
+
+struct rkvop2_driverdata rk3566_driverdata = {
+ .features = VOP_FEATURE_OUTPUT_10BIT,
+ .set_pin_polarity = rk3568_set_pin_polarity,
+ .enable_output = rk3568_enable_output,
+ .platdata = &rk3566_platdata,
+};
+
+struct rkvop2_driverdata rk3568_driverdata = {
+ .features = VOP_FEATURE_OUTPUT_10BIT,
+ .set_pin_polarity = rk3568_set_pin_polarity,
+ .enable_output = rk3568_enable_output,
+ .platdata = &rk3568_platdata,
+};
+
+static const struct udevice_id rk3568_vop_ids[] = {
+ { .compatible = "rockchip,rk3566-vop",
+ .data = (ulong)&rk3566_driverdata },
+ { .compatible = "rockchip,rk3568-vop",
+ .data = (ulong)&rk3568_driverdata },
+ { }
+};
+
+static const struct video_ops rk3568_vop_ops = {
+};
+
+U_BOOT_DRIVER(rk3568_vop) = {
+ .name = "rk3568_vop",
+ .id = UCLASS_VIDEO,
+ .of_match = rk3568_vop_ids,
+ .ops = &rk3568_vop_ops,
+ .bind = rk_vop2_bind,
+ .probe = rk3568_vop_probe,
+ .remove = rk3568_vop_remove,
+ .priv_auto = sizeof(struct rk_vop2_priv),
+ .flags = DM_FLAG_PRE_RELOC | DM_FLAG_OS_PREPARE,
+};
diff --git a/drivers/video/rockchip/rk_vop2.c b/drivers/video/rockchip/rk_vop2.c
new file mode 100644
index 0000000000000000000000000000000000000000..3d64c0a32f8e9a6e479b9bc53afa0736118f08e6
--- /dev/null
+++ b/drivers/video/rockchip/rk_vop2.c
@@ -0,0 +1,523 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2024 Dang Huynh <danct12@riseup.net>
+ *
+ * Based on rk_vop.c:
+ * Copyright (c) 2015 Google, Inc
+ * Copyright 2014 Rockchip Inc.
+ */
+
+#include <clk.h>
+#include <display.h>
+#include <dm.h>
+#include <dm/device_compat.h>
+#include <edid.h>
+#include <log.h>
+#include <regmap.h>
+#include <reset.h>
+#include <syscon.h>
+#include <video.h>
+#include <asm/global_data.h>
+#include <asm/gpio.h>
+#include <asm/io.h>
+#include <asm/arch-rockchip/clock.h>
+#include <asm/arch-rockchip/vop_rk3568.h>
+#include <dm/device-internal.h>
+#include <dm/uclass-internal.h>
+#include <efi.h>
+#include <efi_loader.h>
+#include <linux/bitops.h>
+#include <linux/err.h>
+#include <power/regulator.h>
+
+#include "rk_vop2.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+enum vop_pol {
+ HSYNC_POSITIVE = 0,
+ VSYNC_POSITIVE = 1,
+ DEN_NEGATIVE = 2,
+ DCLK_INVERT = 3
+};
+
+static void rkvop2_cfg_regdone(struct rk3568_vop_sysctrl *sysctrl, int port)
+{
+ u32 reg;
+
+ reg = M_GLOBAL_REGDONE;
+
+ /*
+ * For RK3588, changes will only take effect when the same bit is
+ * leftshifted by 16.
+ */
+ reg |= M_LOAD_GLOBAL(port) | M_LOAD_GLOBAL(port) << 16;
+
+ writel(reg, &sysctrl->reg_cfg_done);
+}
+
+static int rkvop2_enable(struct udevice *dev, ulong fbbase,
+ int fb_bits_per_pixel, const struct display_timing *edid,
+ int port, int win_id, struct rkvop2_platdata *platdata)
+{
+ struct rk_vop2_priv *priv = dev_get_priv(dev);
+ struct rk3568_vop_overlay *overlay = priv->regs + VOP2_OVERLAY_OFFSET;
+ struct rk3568_vop_esmart *esmart;
+ bool is_cluster = false;
+ u8 layer;
+ u32 reg;
+ u32 rgb_mode;
+ u32 hactive = edid->hactive.typ;
+ u32 vactive = edid->vactive.typ;
+
+ switch (platdata->layers[win_id]) {
+ case ROCKCHIP_VOP2_CLUSTER0:
+ case ROCKCHIP_VOP2_CLUSTER1:
+ case ROCKCHIP_VOP2_CLUSTER2:
+ case ROCKCHIP_VOP2_CLUSTER3:
+ is_cluster = true;
+ break;
+ default:
+ break;
+ }
+
+ layer = platdata->layers[win_id];
+
+ debug("(%s, %s): win_id = %d - layer = %d - cluster: %d\n",
+ dev_read_name(dev), __func__, win_id, layer, is_cluster);
+
+ /* TODO: Support VOP2 CLUSTER */
+ if (is_cluster) {
+ dev_err(dev, "win_id is a cluster, not supported.\n");
+ return -EINVAL;
+ }
+
+ esmart = priv->regs + VOP2_ESMART_OFFSET(layer - 4);
+
+ debug("(%s, %s): esmart addr: 0x%p\n", dev_read_name(dev), __func__, esmart);
+
+ writel(V_ACT_WIDTH(hactive - 1) | V_ACT_HEIGHT(vactive - 1),
+ &esmart->esmart_region0_act_info);
+
+ /* Set offset to 0,0 */
+ writel(0, &esmart->esmart_region0_dsp_offset);
+
+ writel(V_DSP_WIDTH(hactive - 1) |
+ V_DSP_HEIGHT(vactive - 1),
+ &esmart->esmart_region0_dsp_info);
+
+ switch (fb_bits_per_pixel) {
+ case 16:
+ rgb_mode = RGB565;
+ writel(V_RGB565_VIRWIDTH(hactive), &esmart->esmart_region0_vir);
+ break;
+ case 24:
+ rgb_mode = RGB888;
+ writel(V_RGB888_VIRWIDTH(hactive), &esmart->esmart_region0_vir);
+ break;
+ case 32:
+ default:
+ rgb_mode = ARGB8888;
+ writel(V_ARGB888_VIRWIDTH(hactive), &esmart->esmart_region0_vir);
+ break;
+ }
+
+ writel(fbbase, &esmart->esmart_region0_mst_yrgb);
+
+ writel(V_ESMART_REGION0_DATA_FMT(rgb_mode) | M_ESMART_REGION0_MST_EN,
+ &esmart->esmart_region0_mst_ctl);
+
+ /* Set esmart to the destination video port */
+ reg = V_ESMART_SEL_PORT(layer - 4, port);
+
+ /*
+ * VOP2 requires every port mux to be configured.
+ *
+ * As U-Boot only supports singledisplay, we'll set all
+ * unused ports to set layer to 8 (disabled).
+ */
+ for (int i = 0; i < 4; i++) {
+ if (i != port)
+ reg |= V_PORT_MUX(8, i);
+ }
+
+ writel(reg, &overlay->port_sel);
+
+ /* Set layer 0 to win_id */
+ writel(V_LAYER_SEL(0, win_id), &overlay->layer_sel);
+
+ reg = readl(&overlay->overlay_ctrl) | M_LAYER_SEL_REGDONE_EN;
+ writel(reg, &overlay->overlay_ctrl);
+
+ priv->layer = layer;
+
+ return 0;
+}
+
+static void rkvop2_set_pin_polarity(struct udevice *dev,
+ enum vop_modes mode, u32 polarity)
+{
+ struct rkvop2_driverdata *ops =
+ (struct rkvop2_driverdata *)dev_get_driver_data(dev);
+
+ if (ops->set_pin_polarity)
+ ops->set_pin_polarity(dev, mode, polarity);
+}
+
+static void rkvop2_enable_output(struct udevice *dev, enum vop_modes mode, u32 port)
+{
+ struct rkvop2_driverdata *ops =
+ (struct rkvop2_driverdata *)dev_get_driver_data(dev);
+
+ if (ops->enable_output)
+ ops->enable_output(dev, mode, port);
+}
+
+static void rkvop2_mode_set(struct udevice *dev,
+ const struct display_timing *edid,
+ enum vop_modes mode, int port,
+ struct rkvop2_platdata *platdata)
+{
+ struct rk_vop2_priv *priv = dev_get_priv(dev);
+ struct rk3568_vop_sysctrl *sysctrl = priv->regs + VOP2_SYSREG_OFFSET;
+ struct rk3568_vop_post *post = priv->regs + VOP2_POST_OFFSET(port);
+ struct rkvop2_driverdata *data =
+ (struct rkvop2_driverdata *)dev_get_driver_data(dev);
+
+ debug("(%s, %s): port addr: 0x%p\n", dev_read_name(dev), __func__, post);
+
+ u32 hactive = edid->hactive.typ;
+ u32 vactive = edid->vactive.typ;
+ u32 hsync_len = edid->hsync_len.typ;
+ u32 hback_porch = edid->hback_porch.typ;
+ u32 vsync_len = edid->vsync_len.typ;
+ u32 vback_porch = edid->vback_porch.typ;
+ u32 hfront_porch = edid->hfront_porch.typ;
+ u32 vfront_porch = edid->vfront_porch.typ;
+ int mode_flags;
+ u32 pin_polarity;
+ u32 reg;
+
+ pin_polarity = BIT(DCLK_INVERT);
+ if (edid->flags & DISPLAY_FLAGS_HSYNC_HIGH)
+ pin_polarity |= BIT(HSYNC_POSITIVE);
+ if (edid->flags & DISPLAY_FLAGS_VSYNC_HIGH)
+ pin_polarity |= BIT(VSYNC_POSITIVE);
+
+ rkvop2_enable_output(dev, mode, port);
+ rkvop2_set_pin_polarity(dev, mode, pin_polarity);
+
+ mode_flags = 0; /* RGB888 */
+ if ((data->features & VOP_FEATURE_OUTPUT_10BIT) &&
+ mode == VOP_MODE_HDMI)
+ mode_flags = 15; /* RGBaaa */
+
+ reg = V_DSP_OUT_MODE(mode_flags);
+
+ debug("(%s, %s): bg_dly: %d\n",
+ dev_read_name(dev), __func__, platdata->bg_dly[port]);
+
+ if (platdata->bg_dly[port] < 0) {
+ dev_err(dev, "bg_dly is zero for vp%d\n", port);
+ return;
+ }
+
+ writel(((platdata->bg_dly[port] + (hactive >> 1) - 1) << 16) | hsync_len,
+ &post->prescan_htimings);
+
+ writel(V_HSYNC(hsync_len) |
+ V_HORPRD(hsync_len + hback_porch + hactive + hfront_porch),
+ &post->dsp_htotal_hs_end);
+
+ writel(V_HEAP(hsync_len + hback_porch + hactive) |
+ V_HASP(hsync_len + hback_porch),
+ &post->dsp_hact_st_end);
+
+ writel(V_VAEP(vsync_len + vback_porch + vactive) |
+ V_VASP(vsync_len + vback_porch),
+ &post->dsp_vact_st_end);
+
+ writel(V_VSYNC(vsync_len) |
+ V_VERPRD(vsync_len + vback_porch + vactive + vfront_porch),
+ &post->dsp_vtotal_vs_end);
+
+ writel(V_HEAP(hsync_len + hback_porch + hactive) |
+ V_HASP(hsync_len + hback_porch),
+ &post->dsp_hact_info);
+
+ writel(V_VAEP(vsync_len + vback_porch + vactive) |
+ V_VASP(vsync_len + vback_porch),
+ &post->dsp_vact_info);
+
+ /* No scaling */
+ writel(0x10001000, &post->scl_factor_yrgb);
+
+ writel(reg, &post->dsp_ctrl);
+
+ rkvop2_cfg_regdone(sysctrl, port);
+}
+
+/**
+ * rk_display_init() - Try to enable the given display device
+ *
+ * This function performs many steps:
+ * - Finds the display device being referenced by @ep_node
+ * - Puts the VOP's ID into its uclass platform data
+ * - Probes the device to set it up
+ * - Reads the timing information (from EDID or panel)
+ * - Sets up the VOP clocks, etc. for the selected pixel clock and display mode
+ * - Enables the display (the display device handles this and will do different
+ * things depending on the display type)
+ * - Tells the uclass about the display resolution so that the console will
+ * appear correctly
+ *
+ * @dev: VOP device that we want to connect to the display
+ * @fbbase: Frame buffer address
+ * @vp_node: Device tree node to process
+ * Return: 0 if OK, -ve if something went wrong
+ */
+static int rk_display_init(struct udevice *dev, ulong fbbase, ofnode vp_node)
+{
+ struct rk_vop2_priv *priv = dev_get_priv(dev);
+ struct video_priv *uc_priv = dev_get_uclass_priv(dev);
+ struct rkvop2_driverdata *drvdata =
+ (struct rkvop2_driverdata *)dev_get_driver_data(dev);
+ struct rkvop2_platdata *platdata =
+ (struct rkvop2_platdata *)drvdata->platdata;
+ ofnode ep_node;
+ int vop_id, port_id, win_id;
+ struct display_timing timing;
+ struct udevice *disp;
+ int ret;
+ u32 remote_phandle;
+ struct display_plat *disp_uc_plat;
+ enum video_log2_bpp l2bpp;
+ ofnode remote;
+ const char *compat;
+ char dclk_name[9];
+ struct clk dclk;
+
+ debug("%s(%s, 0x%lx, %s)\n", __func__,
+ dev_read_name(dev), fbbase, ofnode_get_name(vp_node));
+
+ port_id = ofnode_read_u32_default(vp_node, "reg", -1);
+ if (port_id < 0) {
+ debug("%s(%s): no video port id\n", __func__, dev_read_name(dev));
+ return port_id;
+ }
+
+ ep_node = ofnode_first_subnode(vp_node);
+ if (!ofnode_valid(ep_node)) {
+ debug("%s(%s): no valid subnode\n", __func__, dev_read_name(dev));
+ return -EINVAL;
+ }
+
+ ret = ofnode_read_u32(ep_node, "remote-endpoint", &remote_phandle);
+ if (ret) {
+ debug("%s(%s): no remote-endpoint\n", __func__, dev_read_name(dev));
+ return ret;
+ }
+
+ remote = ofnode_get_by_phandle(remote_phandle);
+ if (!ofnode_valid(remote))
+ return -EINVAL;
+
+ remote = ofnode_get_parent(remote);
+ if (!ofnode_valid(remote))
+ return -EINVAL;
+
+ /*
+ * The remote-endpoint references into a subnode of the encoder
+ * (i.e. HDMI, MIPI, etc.) with the DTS looking something like
+ * the following:
+ *
+ * hdmi: hdmi@fe0a0000 {
+ * ports {
+ * hdmi_in: port {
+ * hdmi_in_vp0: endpoint { ... };
+ * }
+ * }
+ * }
+ *
+ * This isn't any different from how VOP1 works, so we'll adapt
+ * the same method of finding the display from the original code
+ * (find the enclosing device of "UCLASS_DISPLAY")
+ *
+ * We also look for UCLASS_VIDEO_BRIDGE so we can use the existing
+ * DW MIPI DSI driver for Rockchip.
+ */
+ while (ofnode_valid(remote)) {
+ remote = ofnode_get_parent(remote);
+ if (!ofnode_valid(remote)) {
+ debug("%s(%s): no UCLASS_DISPLAY for remote-endpoint\n",
+ __func__, dev_read_name(dev));
+ return -EINVAL;
+ }
+
+ uclass_find_device_by_ofnode(UCLASS_DISPLAY, remote, &disp);
+ if (disp)
+ break;
+ };
+ compat = ofnode_get_property(remote, "compatible", NULL);
+ if (!compat) {
+ debug("%s(%s): Failed to find compatible property\n",
+ __func__, dev_read_name(dev));
+ return -EINVAL;
+ }
+ if (strstr(compat, "edp")) {
+ vop_id = VOP_MODE_EDP;
+ } else if (strstr(compat, "mipi")) {
+ vop_id = VOP_MODE_MIPI;
+ } else if (strstr(compat, "hdmi")) {
+ vop_id = VOP_MODE_HDMI;
+ } else if (strstr(compat, "rk3588-dp")) {
+ vop_id = VOP_MODE_DP;
+ } else if (strstr(compat, "lvds")) {
+ vop_id = VOP_MODE_LVDS;
+ } else {
+ debug("%s(%s): Failed to find vop mode for %s\n",
+ __func__, dev_read_name(dev), compat);
+ return -EINVAL;
+ }
+ debug("vop_id=%d - port=%d\n", vop_id, port_id);
+
+ /* Get the video port clock and enable it */
+ snprintf(dclk_name, sizeof(dclk_name), "dclk_vp%d", port_id);
+ ret = clk_get_by_name(dev, dclk_name, &dclk);
+ if (ret < 0)
+ return ret;
+
+ ret = clk_enable(&dclk);
+ if (ret < 0) {
+ dev_err(dev, "Failed to enable %s: %d\n", dclk_name, ret);
+ return ret;
+ }
+
+ disp_uc_plat = dev_get_uclass_plat(disp);
+ debug("Found device '%s', disp_uc_priv=%p\n", disp->name, disp_uc_plat);
+ if (display_in_use(disp)) {
+ debug(" - device in use\n");
+ return -EBUSY;
+ }
+
+ disp_uc_plat->source_id = vop_id;
+ disp_uc_plat->src_dev = dev;
+
+ ret = device_probe(disp);
+ if (ret) {
+ debug("%s: device '%s' display won't probe (ret=%d)\n",
+ __func__, dev->name, ret);
+ return ret;
+ }
+
+ ret = display_read_timing(disp, &timing);
+ if (ret) {
+ debug("%s: Failed to read timings\n", __func__);
+ return ret;
+ }
+
+ /* Set clock rate on video port to display timings */
+ ret = clk_set_rate(&dclk, timing.pixelclock.typ);
+ if (ret < 0) {
+ dev_err(dev, "Failed to set clock rate: %d\n", ret);
+ return ret;
+ }
+
+ debug("%s(%s): %s clkrate %lu\n", __func__, dev_read_name(dev),
+ dclk_name, clk_get_rate(&dclk));
+
+ /* Set bitwidth for vop display according to vop mode */
+ switch (vop_id) {
+ case VOP_MODE_EDP:
+ case VOP_MODE_MIPI:
+ case VOP_MODE_HDMI:
+ case VOP_MODE_DP:
+ case VOP_MODE_LVDS:
+ l2bpp = VIDEO_BPP32;
+ break;
+ default:
+ l2bpp = VIDEO_BPP16;
+ }
+
+ /*
+ * We'll use the default platform-specific win_id from Linux
+ * so that Linux can take over U-Boot plane when Linux reconfigures
+ * VOP2.
+ */
+ win_id = platdata->vp_lyr[port_id];
+ if (win_id < 0) {
+ dev_err(dev, "win_id is null, don't setup\n");
+ return -EINVAL;
+ }
+
+ ret = rkvop2_enable(dev, fbbase, 1 << l2bpp, &timing, port_id, win_id, platdata);
+ if (ret < 0)
+ return ret;
+
+ rkvop2_mode_set(dev, &timing, vop_id, port_id, platdata);
+
+ ret = display_enable(disp, 1 << l2bpp, &timing);
+ if (ret)
+ return ret;
+
+ uc_priv->xsize = timing.hactive.typ;
+ uc_priv->ysize = timing.vactive.typ;
+ uc_priv->bpix = l2bpp;
+
+ priv->vp = port_id;
+
+ debug("fb=%lx, size=%d %d\n", fbbase,
+ uc_priv->xsize, uc_priv->ysize);
+
+ return 0;
+}
+
+int rk_vop2_probe(struct udevice *dev)
+{
+ struct video_uc_plat *plat = dev_get_uclass_plat(dev);
+ struct rk_vop2_priv *priv = dev_get_priv(dev);
+ int ret = 0;
+ ofnode port, node;
+
+ /* Before relocation we don't need to do anything */
+ if (!(gd->flags & GD_FLG_RELOC))
+ return 0;
+
+ if (IS_ENABLED(CONFIG_EFI_LOADER)) {
+ debug("Adding to EFI map %d @ %lx\n", plat->size, plat->base);
+ efi_add_memory_map(plat->base, plat->size, EFI_RESERVED_MEMORY_TYPE);
+ }
+
+ priv->regs = dev_read_addr_ptr(dev);
+
+ /* Try all the ports until we find one that works. */
+ port = dev_read_subnode(dev, "ports");
+ if (!ofnode_valid(port)) {
+ debug("%s(%s): 'port' subnode not found\n",
+ __func__, dev_read_name(dev));
+ return -EINVAL;
+ }
+
+ for (node = ofnode_first_subnode(port);
+ ofnode_valid(node);
+ node = dev_read_next_subnode(node)) {
+ ret = rk_display_init(dev, plat->base, node);
+ if (ret)
+ debug("Device failed: ret=%d\n", ret);
+ if (!ret)
+ break;
+ }
+ video_set_flush_dcache(dev, true);
+
+ return ret;
+}
+
+int rk_vop2_bind(struct udevice *dev)
+{
+ struct video_uc_plat *plat = dev_get_uclass_plat(dev);
+
+ plat->size = 4 * (CONFIG_VIDEO_ROCKCHIP_MAX_XRES *
+ CONFIG_VIDEO_ROCKCHIP_MAX_YRES);
+
+ return 0;
+}
diff --git a/drivers/video/rockchip/rk_vop2.h b/drivers/video/rockchip/rk_vop2.h
new file mode 100644
index 0000000000000000000000000000000000000000..5d6680700148843d5d6e9a53dcf16a2479305471
--- /dev/null
+++ b/drivers/video/rockchip/rk_vop2.h
@@ -0,0 +1,76 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2017 Theobroma Systems Design und Consulting GmbH
+ */
+
+#ifndef __RK_VOP2_H__
+#define __RK_VOP2_H__
+
+#include <asm/arch-rockchip/vop_rk3568.h>
+
+struct rk_vop2_priv {
+ void *grf;
+ void *regs;
+ int vp;
+ int layer;
+};
+
+enum vop2_features {
+ VOP_FEATURE_OUTPUT_10BIT = (1 << 0),
+};
+
+enum vop2_layer {
+ ROCKCHIP_VOP2_CLUSTER0 = 0,
+ ROCKCHIP_VOP2_CLUSTER1,
+ ROCKCHIP_VOP2_CLUSTER2,
+ ROCKCHIP_VOP2_CLUSTER3,
+ ROCKCHIP_VOP2_ESMART0,
+ ROCKCHIP_VOP2_ESMART1,
+ ROCKCHIP_VOP2_ESMART2,
+ ROCKCHIP_VOP2_ESMART3,
+ ROCKCHIP_VOP2_SMART0 = 6,
+ ROCKCHIP_VOP2_SMART1,
+ ROCKCHIP_VOP2_RESERVED = -1,
+};
+
+struct rkvop2_platdata {
+ const u8 delay;
+ const s8 bg_dly[4]; /* VOP2 supports up to 4 video ports (0-3) */
+ const s8 vp_lyr[4];
+ const s8 layers[8];
+};
+
+struct rkvop2_driverdata {
+ /* configuration */
+ u32 features;
+ void (*platdata);
+ /* block-specific setters/getters */
+ void (*enable_output)(struct udevice *dev, enum vop_modes mode, u32 port);
+ void (*set_pin_polarity)(struct udevice *dev, enum vop_modes mode, u32 port);
+};
+
+/**
+ * rk_vop2_probe() - common probe implementation
+ *
+ * Performs the rk_display_init on each port-subnode until finding a
+ * working port (or returning an error if none of the ports could be
+ * successfully initialised).
+ *
+ * @dev: device
+ * Return: 0 if OK, -ve if something went wrong
+ */
+int rk_vop2_probe(struct udevice *dev);
+
+/**
+ * rk_vop2_bind() - common bind implementation
+ *
+ * Sets the plat->size field to the amount of memory to be reserved for
+ * the framebuffer: this is always
+ * (32 BPP) x VIDEO_ROCKCHIP_MAX_XRES x VIDEO_ROCKCHIP_MAX_YRES
+ *
+ * @dev: device
+ * Return: 0 (always OK)
+ */
+int rk_vop2_bind(struct udevice *dev);
+
+#endif
--
2.49.0
^ permalink raw reply related [flat|nested] 20+ messages in thread* [PATCH v3 07/12] video: rockchip: vop2: Add video bridge support
2025-04-12 14:27 [PATCH v3 00/12] Rockchip VOP2 support Dang Huynh
` (5 preceding siblings ...)
2025-04-12 14:27 ` [PATCH v3 06/12] video: rockchip: Add VOP2 support Dang Huynh
@ 2025-04-12 14:27 ` Dang Huynh
2025-04-12 14:27 ` [PATCH v3 08/12] dts: rockchip: rk356x: Prerelocate VOP in U-Boot proper Dang Huynh
` (4 subsequent siblings)
11 siblings, 0 replies; 20+ messages in thread
From: Dang Huynh @ 2025-04-12 14:27 UTC (permalink / raw)
To: Anatolij Gustschin, Simon Glass, Philipp Tomsich, Kever Yang,
Tom Rini, Nicolas Frattaroli, Jonas Karlman, Ondrej Jirman,
Dragan Simic, Svyatoslav Ryhel, Lukasz Majewski, Sean Anderson
Cc: Nicolas Frattaroli, u-boot, Piotr Zalewski, Dang Huynh
Add support for video bridge to VOP2 so we can use the MIPI DSI
bridge driver that we have.
Reviewed-by: Svyatoslav Ryhel <clamor95@gmail.com>
Signed-off-by: Dang Huynh <danct12@riseup.net>
---
drivers/video/rockchip/rk_vop2.c | 81 +++++++++++++++++++++++++++++-----------
1 file changed, 59 insertions(+), 22 deletions(-)
diff --git a/drivers/video/rockchip/rk_vop2.c b/drivers/video/rockchip/rk_vop2.c
index 3d64c0a32f8e9a6e479b9bc53afa0736118f08e6..01a2ad883923cc9865c85699d2ba2b196e9795f2 100644
--- a/drivers/video/rockchip/rk_vop2.c
+++ b/drivers/video/rockchip/rk_vop2.c
@@ -13,10 +13,12 @@
#include <dm/device_compat.h>
#include <edid.h>
#include <log.h>
+#include <panel.h>
#include <regmap.h>
#include <reset.h>
#include <syscon.h>
#include <video.h>
+#include <video_bridge.h>
#include <asm/global_data.h>
#include <asm/gpio.h>
#include <asm/io.h>
@@ -288,6 +290,7 @@ static int rk_display_init(struct udevice *dev, ulong fbbase, ofnode vp_node)
int vop_id, port_id, win_id;
struct display_timing timing;
struct udevice *disp;
+ struct udevice *bridge;
int ret;
u32 remote_phandle;
struct display_plat *disp_uc_plat;
@@ -354,8 +357,11 @@ static int rk_display_init(struct udevice *dev, ulong fbbase, ofnode vp_node)
return -EINVAL;
}
+ if (IS_ENABLED(CONFIG_VIDEO_BRIDGE))
+ uclass_find_device_by_ofnode(UCLASS_VIDEO_BRIDGE, remote, &bridge);
+
uclass_find_device_by_ofnode(UCLASS_DISPLAY, remote, &disp);
- if (disp)
+ if (disp || bridge)
break;
};
compat = ofnode_get_property(remote, "compatible", NULL);
@@ -393,27 +399,49 @@ static int rk_display_init(struct udevice *dev, ulong fbbase, ofnode vp_node)
return ret;
}
- disp_uc_plat = dev_get_uclass_plat(disp);
- debug("Found device '%s', disp_uc_priv=%p\n", disp->name, disp_uc_plat);
- if (display_in_use(disp)) {
- debug(" - device in use\n");
- return -EBUSY;
- }
+ if (bridge) {
+ /* video bridge detected, probe it */
+ ret = device_probe(bridge);
+ if (ret) {
+ dev_err(dev, "Failed to probe video bridge: %d\n", ret);
+ return ret;
+ }
- disp_uc_plat->source_id = vop_id;
- disp_uc_plat->src_dev = dev;
+ /* Attach the DSI controller and the display to the bridge. */
+ ret = video_bridge_attach(bridge);
+ if (ret) {
+ dev_err(dev, "Failed to attach video bridge: %d\n", ret);
+ return ret;
+ }
- ret = device_probe(disp);
- if (ret) {
- debug("%s: device '%s' display won't probe (ret=%d)\n",
- __func__, dev->name, ret);
- return ret;
- }
+ ret = video_bridge_get_display_timing(bridge, &timing);
+ if (ret) {
+ dev_err(dev, "Failed to read timings: %d\n", ret);
+ return ret;
+ }
+ } else {
+ disp_uc_plat = dev_get_uclass_plat(disp);
+ debug("Found device '%s', disp_uc_priv=%p\n", disp->name, disp_uc_plat);
+ if (display_in_use(disp)) {
+ debug(" - device in use\n");
+ return -EBUSY;
+ }
- ret = display_read_timing(disp, &timing);
- if (ret) {
- debug("%s: Failed to read timings\n", __func__);
- return ret;
+ disp_uc_plat->source_id = vop_id;
+ disp_uc_plat->src_dev = dev;
+
+ ret = device_probe(disp);
+ if (ret) {
+ debug("%s: device '%s' display won't probe (ret=%d)\n",
+ __func__, dev->name, ret);
+ return ret;
+ }
+
+ ret = display_read_timing(disp, &timing);
+ if (ret) {
+ debug("%s: Failed to read timings\n", __func__);
+ return ret;
+ }
}
/* Set clock rate on video port to display timings */
@@ -456,9 +484,18 @@ static int rk_display_init(struct udevice *dev, ulong fbbase, ofnode vp_node)
rkvop2_mode_set(dev, &timing, vop_id, port_id, platdata);
- ret = display_enable(disp, 1 << l2bpp, &timing);
- if (ret)
- return ret;
+ if (bridge) {
+ /* Attach the DSI controller and the display to the bridge. */
+ ret = video_bridge_set_backlight(bridge, 60);
+ if (ret) {
+ dev_err(dev, "Failed to start the video bridge: %d\n", ret);
+ return ret;
+ }
+ } else {
+ ret = display_enable(disp, 1 << l2bpp, &timing);
+ if (ret)
+ return ret;
+ }
uc_priv->xsize = timing.hactive.typ;
uc_priv->ysize = timing.vactive.typ;
--
2.49.0
^ permalink raw reply related [flat|nested] 20+ messages in thread* [PATCH v3 08/12] dts: rockchip: rk356x: Prerelocate VOP in U-Boot proper
2025-04-12 14:27 [PATCH v3 00/12] Rockchip VOP2 support Dang Huynh
` (6 preceding siblings ...)
2025-04-12 14:27 ` [PATCH v3 07/12] video: rockchip: vop2: Add video bridge support Dang Huynh
@ 2025-04-12 14:27 ` Dang Huynh
2025-04-13 14:33 ` Jonas Karlman
2025-04-12 14:27 ` [PATCH v3 09/12] configs: quartz64: Enable vidconsole Dang Huynh
` (3 subsequent siblings)
11 siblings, 1 reply; 20+ messages in thread
From: Dang Huynh @ 2025-04-12 14:27 UTC (permalink / raw)
To: Anatolij Gustschin, Simon Glass, Philipp Tomsich, Kever Yang,
Tom Rini, Nicolas Frattaroli, Jonas Karlman, Ondrej Jirman,
Dragan Simic, Svyatoslav Ryhel, Lukasz Majewski, Sean Anderson
Cc: Nicolas Frattaroli, u-boot, Piotr Zalewski, Dang Huynh
We need to prerelocate VOP2 memory so the driver can work. This
will only support U-Boot proper.
Signed-off-by: Dang Huynh <danct12@riseup.net>
---
arch/arm/dts/rk356x-u-boot.dtsi | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/arch/arm/dts/rk356x-u-boot.dtsi b/arch/arm/dts/rk356x-u-boot.dtsi
index 24a976cf7e21da351cbbb969ba2b4687c344ca6c..1191e2fd567dd18655c88ea1b7a28d160d43c220 100644
--- a/arch/arm/dts/rk356x-u-boot.dtsi
+++ b/arch/arm/dts/rk356x-u-boot.dtsi
@@ -166,6 +166,10 @@
clock-frequency = <24000000>;
};
+&vop {
+ bootph-some-ram;
+};
+
&uart2m0_xfer {
bootph-all;
};
--
2.49.0
^ permalink raw reply related [flat|nested] 20+ messages in thread* Re: [PATCH v3 08/12] dts: rockchip: rk356x: Prerelocate VOP in U-Boot proper
2025-04-12 14:27 ` [PATCH v3 08/12] dts: rockchip: rk356x: Prerelocate VOP in U-Boot proper Dang Huynh
@ 2025-04-13 14:33 ` Jonas Karlman
2025-04-15 13:15 ` Dang Huynh
0 siblings, 1 reply; 20+ messages in thread
From: Jonas Karlman @ 2025-04-13 14:33 UTC (permalink / raw)
To: Dang Huynh
Cc: Anatolij Gustschin, Simon Glass, Philipp Tomsich, Kever Yang,
Tom Rini, Nicolas Frattaroli, Ondrej Jirman, Dragan Simic,
Svyatoslav Ryhel, Lukasz Majewski, Sean Anderson, u-boot,
Piotr Zalewski
Hi,
On 2025-04-12 16:27, Dang Huynh wrote:
> We need to prerelocate VOP2 memory so the driver can work. This
> will only support U-Boot proper.
>
> Signed-off-by: Dang Huynh <danct12@riseup.net>
> ---
> arch/arm/dts/rk356x-u-boot.dtsi | 4 ++++
> 1 file changed, 4 insertions(+)
>
> diff --git a/arch/arm/dts/rk356x-u-boot.dtsi b/arch/arm/dts/rk356x-u-boot.dtsi
> index 24a976cf7e21da351cbbb969ba2b4687c344ca6c..1191e2fd567dd18655c88ea1b7a28d160d43c220 100644
> --- a/arch/arm/dts/rk356x-u-boot.dtsi
> +++ b/arch/arm/dts/rk356x-u-boot.dtsi
> @@ -166,6 +166,10 @@
> clock-frequency = <24000000>;
> };
>
> +&vop {
> + bootph-some-ram;
> +};
This node should be sorted after &uart2m0_xfer to be in alphabetical
order, and not put between &uart2 and &uart2m0_xfer.
On a related note, I do not understand why U-Boot must allocated its
framebuffer in pre-reloc phase, but that may be something to change/fix
in a different series.
Regards,
Jonas
> +
> &uart2m0_xfer {
> bootph-all;
> };
>
^ permalink raw reply [flat|nested] 20+ messages in thread* Re: [PATCH v3 08/12] dts: rockchip: rk356x: Prerelocate VOP in U-Boot proper
2025-04-13 14:33 ` Jonas Karlman
@ 2025-04-15 13:15 ` Dang Huynh
0 siblings, 0 replies; 20+ messages in thread
From: Dang Huynh @ 2025-04-15 13:15 UTC (permalink / raw)
To: Jonas Karlman
Cc: Anatolij Gustschin, Simon Glass, Philipp Tomsich, Kever Yang,
Tom Rini, Nicolas Frattaroli, Ondrej Jirman, Dragan Simic,
Svyatoslav Ryhel, Lukasz Majewski, Sean Anderson, u-boot,
Piotr Zalewski
On Sun, Apr 13, 2025 at 04:33:25PM +0200, Jonas Karlman wrote:
> Hi,
>
> On 2025-04-12 16:27, Dang Huynh wrote:
> > We need to prerelocate VOP2 memory so the driver can work. This
> > will only support U-Boot proper.
> >
> > Signed-off-by: Dang Huynh <danct12@riseup.net>
> > ---
> > arch/arm/dts/rk356x-u-boot.dtsi | 4 ++++
> > 1 file changed, 4 insertions(+)
> >
> > diff --git a/arch/arm/dts/rk356x-u-boot.dtsi b/arch/arm/dts/rk356x-u-boot.dtsi
> > index 24a976cf7e21da351cbbb969ba2b4687c344ca6c..1191e2fd567dd18655c88ea1b7a28d160d43c220 100644
> > --- a/arch/arm/dts/rk356x-u-boot.dtsi
> > +++ b/arch/arm/dts/rk356x-u-boot.dtsi
> > @@ -166,6 +166,10 @@
> > clock-frequency = <24000000>;
> > };
> >
> > +&vop {
> > + bootph-some-ram;
> > +};
>
> This node should be sorted after &uart2m0_xfer to be in alphabetical
> order, and not put between &uart2 and &uart2m0_xfer.
Whoops. I'll fix this in the next revision.
>
> On a related note, I do not understand why U-Boot must allocated its
> framebuffer in pre-reloc phase, but that may be something to change/fix
> in a different series.
>
> Regards,
> Jonas
>
> > +
> > &uart2m0_xfer {
> > bootph-all;
> > };
> >
>
^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH v3 09/12] configs: quartz64: Enable vidconsole
2025-04-12 14:27 [PATCH v3 00/12] Rockchip VOP2 support Dang Huynh
` (7 preceding siblings ...)
2025-04-12 14:27 ` [PATCH v3 08/12] dts: rockchip: rk356x: Prerelocate VOP in U-Boot proper Dang Huynh
@ 2025-04-12 14:27 ` Dang Huynh
2025-04-12 14:27 ` [PATCH v3 10/12] video: rockchip: Add HDMI support for RK3568 Dang Huynh
` (2 subsequent siblings)
11 siblings, 0 replies; 20+ messages in thread
From: Dang Huynh @ 2025-04-12 14:27 UTC (permalink / raw)
To: Anatolij Gustschin, Simon Glass, Philipp Tomsich, Kever Yang,
Tom Rini, Nicolas Frattaroli, Jonas Karlman, Ondrej Jirman,
Dragan Simic, Svyatoslav Ryhel, Lukasz Majewski, Sean Anderson
Cc: Nicolas Frattaroli, u-boot, Piotr Zalewski, Dang Huynh
Now that we have VOP2 support, we should enable vidconsole.
Signed-off-by: Dang Huynh <danct12@riseup.net>
---
include/configs/quartz64_rk3566.h | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/include/configs/quartz64_rk3566.h b/include/configs/quartz64_rk3566.h
index dfe0fee94cdb043cbca558e90fb203245534509a..bf391458219b4f2371626d0ccf98af2a3bc279ce 100644
--- a/include/configs/quartz64_rk3566.h
+++ b/include/configs/quartz64_rk3566.h
@@ -3,7 +3,10 @@
#ifndef __QUARTZ64_RK3566_H
#define __QUARTZ64_RK3566_H
-#define ROCKCHIP_DEVICE_SETTINGS
+#define ROCKCHIP_DEVICE_SETTINGS \
+ "stdin=serial,usbkbd\0" \
+ "stdout=serial,vidconsole\0" \
+ "stderr=serial,vidconsole\0"
#include <configs/rk3568_common.h>
--
2.49.0
^ permalink raw reply related [flat|nested] 20+ messages in thread* [PATCH v3 10/12] video: rockchip: Add HDMI support for RK3568
2025-04-12 14:27 [PATCH v3 00/12] Rockchip VOP2 support Dang Huynh
` (8 preceding siblings ...)
2025-04-12 14:27 ` [PATCH v3 09/12] configs: quartz64: Enable vidconsole Dang Huynh
@ 2025-04-12 14:27 ` Dang Huynh
2025-04-13 15:10 ` Jonas Karlman
2025-04-12 14:27 ` [PATCH v3 11/12] configs: pinetab2-rk3566: Enable video and USB keyboard Dang Huynh
2025-04-12 14:27 ` [PATCH v3 12/12] clk: rockchip: rk3568: Use assigned VPLL clock when possible Dang Huynh
11 siblings, 1 reply; 20+ messages in thread
From: Dang Huynh @ 2025-04-12 14:27 UTC (permalink / raw)
To: Anatolij Gustschin, Simon Glass, Philipp Tomsich, Kever Yang,
Tom Rini, Nicolas Frattaroli, Jonas Karlman, Ondrej Jirman,
Dragan Simic, Svyatoslav Ryhel, Lukasz Majewski, Sean Anderson
Cc: Nicolas Frattaroli, u-boot, Piotr Zalewski, Dang Huynh
HDMI on RK3568 is mostly simplified, all this does is enabling
DDC for display timings and HPD.
Signed-off-by: Dang Huynh <danct12@riseup.net>
---
drivers/video/rockchip/Makefile | 1 +
drivers/video/rockchip/rk3568_hdmi.c | 71 ++++++++++++++++++++++++++++++++++++
2 files changed, 72 insertions(+)
diff --git a/drivers/video/rockchip/Makefile b/drivers/video/rockchip/Makefile
index 2f89a979a2848733be5a6d05817ad76ce3ad3a34..b751c969b46f1933e91a6c0434f31227a709d8e5 100644
--- a/drivers/video/rockchip/Makefile
+++ b/drivers/video/rockchip/Makefile
@@ -14,6 +14,7 @@ obj-$(CONFIG_DISPLAY_ROCKCHIP_LVDS) += rk_lvds.o
obj-hdmi-$(CONFIG_ROCKCHIP_RK3288) += rk3288_hdmi.o
obj-hdmi-$(CONFIG_ROCKCHIP_RK3328) += rk3328_hdmi.o
obj-hdmi-$(CONFIG_ROCKCHIP_RK3399) += rk3399_hdmi.o
+obj-hdmi-$(CONFIG_ROCKCHIP_RK3568) += rk3568_hdmi.o
obj-$(CONFIG_DISPLAY_ROCKCHIP_HDMI) += rk_hdmi.o $(obj-hdmi-y)
obj-mipi-$(CONFIG_ROCKCHIP_RK3288) += rk3288_mipi.o
obj-mipi-$(CONFIG_ROCKCHIP_RK3399) += rk3399_mipi.o
diff --git a/drivers/video/rockchip/rk3568_hdmi.c b/drivers/video/rockchip/rk3568_hdmi.c
new file mode 100644
index 0000000000000000000000000000000000000000..5578ea37243a5735713d92572639cdc8ba9865cf
--- /dev/null
+++ b/drivers/video/rockchip/rk3568_hdmi.c
@@ -0,0 +1,71 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2024 Dang Huynh <danct12@riseup.net>
+ */
+
+#include <display.h>
+#include <dm.h>
+#include <dw_hdmi.h>
+#include <edid.h>
+#include <asm/arch-rockchip/hardware.h>
+#include <asm/arch-rockchip/grf_rk3568.h>
+#include "rk_hdmi.h"
+
+#define RK3568_IO_DDC_IN_MSK ((3 << 14) | (3 << (14 + 16)))
+
+static int rk3568_hdmi_enable(struct udevice *dev, int panel_bpp,
+ const struct display_timing *edid)
+{
+ struct rk_hdmi_priv *priv = dev_get_priv(dev);
+
+ return dw_hdmi_enable(&priv->hdmi, edid);
+}
+
+static int rk3568_hdmi_of_to_plat(struct udevice *dev)
+{
+ struct rk_hdmi_priv *priv = dev_get_priv(dev);
+ struct dw_hdmi *hdmi = &priv->hdmi;
+
+ hdmi->i2c_clk_high = 0x71;
+ hdmi->i2c_clk_low = 0x76;
+
+ return rk_hdmi_of_to_plat(dev);
+}
+
+static const char * const rk3568_hdmi_reg_names[] = {
+ "avdd-0v9",
+ "avdd-1v8"
+};
+
+static int rk3568_hdmi_probe(struct udevice *dev)
+{
+ struct rk_hdmi_priv *priv = dev_get_priv(dev);
+ struct rk3568_grf *grf = priv->grf;
+
+ rk_hdmi_probe_regulators(dev, rk3568_hdmi_reg_names,
+ ARRAY_SIZE(rk3568_hdmi_reg_names));
+
+ writel(RK3568_IO_DDC_IN_MSK, &grf->vo_con1);
+
+ return rk_hdmi_probe(dev);
+}
+
+static const struct dm_display_ops rk3568_hdmi_ops = {
+ .read_edid = rk_hdmi_read_edid,
+ .enable = rk3568_hdmi_enable,
+};
+
+static const struct udevice_id rk3568_hdmi_ids[] = {
+ { .compatible = "rockchip,rk3568-dw-hdmi" },
+ { }
+};
+
+U_BOOT_DRIVER(rk3568_hdmi_rockchip) = {
+ .name = "rk3568_hdmi_rockchip",
+ .id = UCLASS_DISPLAY,
+ .of_match = rk3568_hdmi_ids,
+ .ops = &rk3568_hdmi_ops,
+ .of_to_plat = rk3568_hdmi_of_to_plat,
+ .probe = rk3568_hdmi_probe,
+ .priv_auto = sizeof(struct rk_hdmi_priv),
+};
--
2.49.0
^ permalink raw reply related [flat|nested] 20+ messages in thread* Re: [PATCH v3 10/12] video: rockchip: Add HDMI support for RK3568
2025-04-12 14:27 ` [PATCH v3 10/12] video: rockchip: Add HDMI support for RK3568 Dang Huynh
@ 2025-04-13 15:10 ` Jonas Karlman
0 siblings, 0 replies; 20+ messages in thread
From: Jonas Karlman @ 2025-04-13 15:10 UTC (permalink / raw)
To: Dang Huynh
Cc: Anatolij Gustschin, Simon Glass, Philipp Tomsich, Kever Yang,
Tom Rini, Nicolas Frattaroli, Ondrej Jirman, Dragan Simic,
Svyatoslav Ryhel, Lukasz Majewski, Sean Anderson, u-boot,
Piotr Zalewski
Hi,
On 2025-04-12 16:27, Dang Huynh wrote:
> HDMI on RK3568 is mostly simplified, all this does is enabling
> DDC for display timings and HPD.
>
> Signed-off-by: Dang Huynh <danct12@riseup.net>
> ---
> drivers/video/rockchip/Makefile | 1 +
> drivers/video/rockchip/rk3568_hdmi.c | 71 ++++++++++++++++++++++++++++++++++++
> 2 files changed, 72 insertions(+)
>
> diff --git a/drivers/video/rockchip/Makefile b/drivers/video/rockchip/Makefile
> index 2f89a979a2848733be5a6d05817ad76ce3ad3a34..b751c969b46f1933e91a6c0434f31227a709d8e5 100644
> --- a/drivers/video/rockchip/Makefile
> +++ b/drivers/video/rockchip/Makefile
> @@ -14,6 +14,7 @@ obj-$(CONFIG_DISPLAY_ROCKCHIP_LVDS) += rk_lvds.o
> obj-hdmi-$(CONFIG_ROCKCHIP_RK3288) += rk3288_hdmi.o
> obj-hdmi-$(CONFIG_ROCKCHIP_RK3328) += rk3328_hdmi.o
> obj-hdmi-$(CONFIG_ROCKCHIP_RK3399) += rk3399_hdmi.o
> +obj-hdmi-$(CONFIG_ROCKCHIP_RK3568) += rk3568_hdmi.o
> obj-$(CONFIG_DISPLAY_ROCKCHIP_HDMI) += rk_hdmi.o $(obj-hdmi-y)
> obj-mipi-$(CONFIG_ROCKCHIP_RK3288) += rk3288_mipi.o
> obj-mipi-$(CONFIG_ROCKCHIP_RK3399) += rk3399_mipi.o
> diff --git a/drivers/video/rockchip/rk3568_hdmi.c b/drivers/video/rockchip/rk3568_hdmi.c
> new file mode 100644
> index 0000000000000000000000000000000000000000..5578ea37243a5735713d92572639cdc8ba9865cf
> --- /dev/null
> +++ b/drivers/video/rockchip/rk3568_hdmi.c
> @@ -0,0 +1,71 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Copyright (c) 2024 Dang Huynh <danct12@riseup.net>
> + */
> +
> +#include <display.h>
> +#include <dm.h>
> +#include <dw_hdmi.h>
> +#include <edid.h>
> +#include <asm/arch-rockchip/hardware.h>
> +#include <asm/arch-rockchip/grf_rk3568.h>
> +#include "rk_hdmi.h"
> +
> +#define RK3568_IO_DDC_IN_MSK ((3 << 14) | (3 << (14 + 16)))
> +
> +static int rk3568_hdmi_enable(struct udevice *dev, int panel_bpp,
> + const struct display_timing *edid)
> +{
> + struct rk_hdmi_priv *priv = dev_get_priv(dev);
> +
> + return dw_hdmi_enable(&priv->hdmi, edid);
> +}
> +
> +static int rk3568_hdmi_of_to_plat(struct udevice *dev)
> +{
> + struct rk_hdmi_priv *priv = dev_get_priv(dev);
> + struct dw_hdmi *hdmi = &priv->hdmi;
> +
> + hdmi->i2c_clk_high = 0x71;
> + hdmi->i2c_clk_low = 0x76;
It is interesting that U-Boot will do I2C clock configuration, something
that Linux will not do.
Where did you get these values? According to the dw-hdmi databook these
should be configured similar to following:
Minimum High and Minimum Low @100 kbps:
MIN_SCL_*time Variable Specification Value Compliance Value
MIN_SCL_HIGHtime 4000 ns 4500 ns
MIN_SCL_LOWtime 4500 ns 5200 ns
SFR Clock Frequency (Hz) = SFRFREQ
SFRFREQ = 27 MHz
I2Cmode = standard, 100 kbit/s
MIN_SCL_HIGHtime = 4000 ns.
MIN_SCL_LOWtime = 4700 ns.
IC_xCNT = (ROUNDUP(MIN_SCL_HIGH_LOWtime*SFRFREQ,0))
IC_HCNT = (ROUNDUP(4000 ns * 27 MHz,0))
IC_HCNTSCL PERIOD = 108 (0x6c)
IC_LCNT = (ROUNDUP(4700 ns * 27 MHz,0))
IC_LCNTSCL PERIOD = 127 (0x7f)
Above are the defaults for a 27 MHz source clock, however Rockchip use a
24 MHz source clock.
With current values the difference between high and low seem rather low:
i2c_clk_high = 0x71 (4708 ns)
i2c_clk_low = 0x76 (4916 ns)
I would expect these to possible be better options:
i2c_clk_high = 0x6c (4500 ns)
i2c_clk_low = 0x7d (5208 ns)
As that more closer matches the recommended values for compliance test.
> +
> + return rk_hdmi_of_to_plat(dev);
> +}
> +
> +static const char * const rk3568_hdmi_reg_names[] = {
> + "avdd-0v9",
> + "avdd-1v8"
> +};
> +
> +static int rk3568_hdmi_probe(struct udevice *dev)
> +{
> + struct rk_hdmi_priv *priv = dev_get_priv(dev);
> + struct rk3568_grf *grf = priv->grf;
> +
> + rk_hdmi_probe_regulators(dev, rk3568_hdmi_reg_names,
> + ARRAY_SIZE(rk3568_hdmi_reg_names));
> +
> + writel(RK3568_IO_DDC_IN_MSK, &grf->vo_con1);
> +
> + return rk_hdmi_probe(dev);
> +}
> +
> +static const struct dm_display_ops rk3568_hdmi_ops = {
> + .read_edid = rk_hdmi_read_edid,
> + .enable = rk3568_hdmi_enable,
> +};
> +
> +static const struct udevice_id rk3568_hdmi_ids[] = {
> + { .compatible = "rockchip,rk3568-dw-hdmi" },
> + { }
> +};
> +
> +U_BOOT_DRIVER(rk3568_hdmi_rockchip) = {
> + .name = "rk3568_hdmi_rockchip",
> + .id = UCLASS_DISPLAY,
> + .of_match = rk3568_hdmi_ids,
> + .ops = &rk3568_hdmi_ops,
> + .of_to_plat = rk3568_hdmi_of_to_plat,
> + .probe = rk3568_hdmi_probe,
> + .priv_auto = sizeof(struct rk_hdmi_priv),
No need to add a tab here since none of the values are aligned, please
replace the tab with a space.
Regards,
Jonas
> +};
>
^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH v3 11/12] configs: pinetab2-rk3566: Enable video and USB keyboard
2025-04-12 14:27 [PATCH v3 00/12] Rockchip VOP2 support Dang Huynh
` (9 preceding siblings ...)
2025-04-12 14:27 ` [PATCH v3 10/12] video: rockchip: Add HDMI support for RK3568 Dang Huynh
@ 2025-04-12 14:27 ` Dang Huynh
2025-04-13 15:26 ` Jonas Karlman
2025-04-12 14:27 ` [PATCH v3 12/12] clk: rockchip: rk3568: Use assigned VPLL clock when possible Dang Huynh
11 siblings, 1 reply; 20+ messages in thread
From: Dang Huynh @ 2025-04-12 14:27 UTC (permalink / raw)
To: Anatolij Gustschin, Simon Glass, Philipp Tomsich, Kever Yang,
Tom Rini, Nicolas Frattaroli, Jonas Karlman, Ondrej Jirman,
Dragan Simic, Svyatoslav Ryhel, Lukasz Majewski, Sean Anderson
Cc: Nicolas Frattaroli, u-boot, Piotr Zalewski, Dang Huynh
Now that we have VOP2 support, let's enable it and support the
built in USB keyboard.
Signed-off-by: Dang Huynh <danct12@riseup.net>
---
configs/pinetab2-rk3566_defconfig | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/configs/pinetab2-rk3566_defconfig b/configs/pinetab2-rk3566_defconfig
index 45e63b42d192dc172f24e071b09c8203675965d8..792ec0ec119437fd7a920558a149363c886c87de 100644
--- a/configs/pinetab2-rk3566_defconfig
+++ b/configs/pinetab2-rk3566_defconfig
@@ -57,6 +57,7 @@ CONFIG_BUTTON=y
CONFIG_BUTTON_ADC=y
CONFIG_BUTTON_GPIO=y
CONFIG_SPL_CLK=y
+CONFIG_CLK_CCF=y
# CONFIG_USB_FUNCTION_FASTBOOT is not set
CONFIG_ROCKCHIP_GPIO=y
CONFIG_SYS_I2C_ROCKCHIP=y
@@ -69,6 +70,7 @@ CONFIG_MMC_SDHCI_SDMA=y
CONFIG_MMC_SDHCI_ROCKCHIP=y
CONFIG_SPI_FLASH_SFDP_SUPPORT=y
CONFIG_SPI_FLASH_SILICONKAISER=y
+CONFIG_PHY_ROCKCHIP_INNO_DSIDPHY=y
CONFIG_PHY_ROCKCHIP_INNO_USB2=y
CONFIG_PHY_ROCKCHIP_NANENG_COMBOPHY=y
CONFIG_SPL_PINCTRL=y
@@ -94,6 +96,7 @@ CONFIG_USB_OHCI_HCD=y
CONFIG_USB_OHCI_GENERIC=y
CONFIG_USB_DWC3=y
CONFIG_USB_DWC3_GENERIC=y
+CONFIG_USB_KEYBOARD=y
CONFIG_USB_HOST_ETHER=y
CONFIG_USB_ETHER_ASIX=y
CONFIG_USB_ETHER_ASIX88179=y
@@ -101,4 +104,12 @@ CONFIG_USB_ETHER_RTL8152=y
CONFIG_USB_GADGET=y
CONFIG_USB_GADGET_DOWNLOAD=y
CONFIG_USB_FUNCTION_ROCKUSB=y
+CONFIG_VIDEO=y
+CONFIG_VIDEO_LCD_BOE_TH101MB31IG002_28A=y
+CONFIG_DISPLAY=y
+CONFIG_VIDEO_ROCKCHIP=y
+CONFIG_DISPLAY_ROCKCHIP_HDMI=y
+CONFIG_DISPLAY_ROCKCHIP_DW_MIPI=y
+CONFIG_VIDEO_BRIDGE=y
+CONFIG_VIDEO_REMOVE=y
CONFIG_ERRNO_STR=y
--
2.49.0
^ permalink raw reply related [flat|nested] 20+ messages in thread* Re: [PATCH v3 11/12] configs: pinetab2-rk3566: Enable video and USB keyboard
2025-04-12 14:27 ` [PATCH v3 11/12] configs: pinetab2-rk3566: Enable video and USB keyboard Dang Huynh
@ 2025-04-13 15:26 ` Jonas Karlman
2025-04-15 13:29 ` Dang Huynh
0 siblings, 1 reply; 20+ messages in thread
From: Jonas Karlman @ 2025-04-13 15:26 UTC (permalink / raw)
To: Dang Huynh
Cc: Anatolij Gustschin, Simon Glass, Philipp Tomsich, Kever Yang,
Tom Rini, Nicolas Frattaroli, Ondrej Jirman, Dragan Simic,
Svyatoslav Ryhel, Lukasz Majewski, Sean Anderson, u-boot,
Piotr Zalewski
Hi,
On 2025-04-12 16:27, Dang Huynh wrote:
> Now that we have VOP2 support, let's enable it and support the
> built in USB keyboard.
>
> Signed-off-by: Dang Huynh <danct12@riseup.net>
> ---
> configs/pinetab2-rk3566_defconfig | 11 +++++++++++
> 1 file changed, 11 insertions(+)
>
> diff --git a/configs/pinetab2-rk3566_defconfig b/configs/pinetab2-rk3566_defconfig
> index 45e63b42d192dc172f24e071b09c8203675965d8..792ec0ec119437fd7a920558a149363c886c87de 100644
> --- a/configs/pinetab2-rk3566_defconfig
> +++ b/configs/pinetab2-rk3566_defconfig
> @@ -57,6 +57,7 @@ CONFIG_BUTTON=y
> CONFIG_BUTTON_ADC=y
> CONFIG_BUTTON_GPIO=y
> CONFIG_SPL_CLK=y
> +CONFIG_CLK_CCF=y
Rockchip clk drivers does not use this, and I do not see any new clock
driver being added in this series.
Why is this needed?
Regards,
Jonas
> # CONFIG_USB_FUNCTION_FASTBOOT is not set
> CONFIG_ROCKCHIP_GPIO=y
> CONFIG_SYS_I2C_ROCKCHIP=y
> @@ -69,6 +70,7 @@ CONFIG_MMC_SDHCI_SDMA=y
> CONFIG_MMC_SDHCI_ROCKCHIP=y
> CONFIG_SPI_FLASH_SFDP_SUPPORT=y
> CONFIG_SPI_FLASH_SILICONKAISER=y
> +CONFIG_PHY_ROCKCHIP_INNO_DSIDPHY=y
> CONFIG_PHY_ROCKCHIP_INNO_USB2=y
> CONFIG_PHY_ROCKCHIP_NANENG_COMBOPHY=y
> CONFIG_SPL_PINCTRL=y
> @@ -94,6 +96,7 @@ CONFIG_USB_OHCI_HCD=y
> CONFIG_USB_OHCI_GENERIC=y
> CONFIG_USB_DWC3=y
> CONFIG_USB_DWC3_GENERIC=y
> +CONFIG_USB_KEYBOARD=y
> CONFIG_USB_HOST_ETHER=y
> CONFIG_USB_ETHER_ASIX=y
> CONFIG_USB_ETHER_ASIX88179=y
> @@ -101,4 +104,12 @@ CONFIG_USB_ETHER_RTL8152=y
> CONFIG_USB_GADGET=y
> CONFIG_USB_GADGET_DOWNLOAD=y
> CONFIG_USB_FUNCTION_ROCKUSB=y
> +CONFIG_VIDEO=y
> +CONFIG_VIDEO_LCD_BOE_TH101MB31IG002_28A=y
> +CONFIG_DISPLAY=y
> +CONFIG_VIDEO_ROCKCHIP=y
> +CONFIG_DISPLAY_ROCKCHIP_HDMI=y
> +CONFIG_DISPLAY_ROCKCHIP_DW_MIPI=y
> +CONFIG_VIDEO_BRIDGE=y
> +CONFIG_VIDEO_REMOVE=y
> CONFIG_ERRNO_STR=y
>
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v3 11/12] configs: pinetab2-rk3566: Enable video and USB keyboard
2025-04-13 15:26 ` Jonas Karlman
@ 2025-04-15 13:29 ` Dang Huynh
2025-04-15 15:52 ` Jonas Karlman
0 siblings, 1 reply; 20+ messages in thread
From: Dang Huynh @ 2025-04-15 13:29 UTC (permalink / raw)
To: Jonas Karlman
Cc: Anatolij Gustschin, Simon Glass, Philipp Tomsich, Kever Yang,
Tom Rini, Nicolas Frattaroli, Ondrej Jirman, Dragan Simic,
Svyatoslav Ryhel, Lukasz Majewski, Sean Anderson, u-boot,
Piotr Zalewski
On Sun, Apr 13, 2025 at 05:26:03PM +0200, Jonas Karlman wrote:
> Hi,
>
> On 2025-04-12 16:27, Dang Huynh wrote:
> > Now that we have VOP2 support, let's enable it and support the
> > built in USB keyboard.
> >
> > Signed-off-by: Dang Huynh <danct12@riseup.net>
> > ---
> > configs/pinetab2-rk3566_defconfig | 11 +++++++++++
> > 1 file changed, 11 insertions(+)
> >
> > diff --git a/configs/pinetab2-rk3566_defconfig b/configs/pinetab2-rk3566_defconfig
> > index 45e63b42d192dc172f24e071b09c8203675965d8..792ec0ec119437fd7a920558a149363c886c87de 100644
> > --- a/configs/pinetab2-rk3566_defconfig
> > +++ b/configs/pinetab2-rk3566_defconfig
> > @@ -57,6 +57,7 @@ CONFIG_BUTTON=y
> > CONFIG_BUTTON_ADC=y
> > CONFIG_BUTTON_GPIO=y
> > CONFIG_SPL_CLK=y
> > +CONFIG_CLK_CCF=y
>
> Rockchip clk drivers does not use this, and I do not see any new clock
> driver being added in this series.
>
> Why is this needed?
I initially added this to get around clk_enable error, but it seems like
you don't need to enable VOP clocks.
However, I noticed that enabling CCF will give us clock rate that are
pretty close to how it's configured on Linux.
>
> Regards,
> Jonas
>
> > # CONFIG_USB_FUNCTION_FASTBOOT is not set
> > CONFIG_ROCKCHIP_GPIO=y
> > CONFIG_SYS_I2C_ROCKCHIP=y
> > @@ -69,6 +70,7 @@ CONFIG_MMC_SDHCI_SDMA=y
> > CONFIG_MMC_SDHCI_ROCKCHIP=y
> > CONFIG_SPI_FLASH_SFDP_SUPPORT=y
> > CONFIG_SPI_FLASH_SILICONKAISER=y
> > +CONFIG_PHY_ROCKCHIP_INNO_DSIDPHY=y
> > CONFIG_PHY_ROCKCHIP_INNO_USB2=y
> > CONFIG_PHY_ROCKCHIP_NANENG_COMBOPHY=y
> > CONFIG_SPL_PINCTRL=y
> > @@ -94,6 +96,7 @@ CONFIG_USB_OHCI_HCD=y
> > CONFIG_USB_OHCI_GENERIC=y
> > CONFIG_USB_DWC3=y
> > CONFIG_USB_DWC3_GENERIC=y
> > +CONFIG_USB_KEYBOARD=y
> > CONFIG_USB_HOST_ETHER=y
> > CONFIG_USB_ETHER_ASIX=y
> > CONFIG_USB_ETHER_ASIX88179=y
> > @@ -101,4 +104,12 @@ CONFIG_USB_ETHER_RTL8152=y
> > CONFIG_USB_GADGET=y
> > CONFIG_USB_GADGET_DOWNLOAD=y
> > CONFIG_USB_FUNCTION_ROCKUSB=y
> > +CONFIG_VIDEO=y
> > +CONFIG_VIDEO_LCD_BOE_TH101MB31IG002_28A=y
> > +CONFIG_DISPLAY=y
> > +CONFIG_VIDEO_ROCKCHIP=y
> > +CONFIG_DISPLAY_ROCKCHIP_HDMI=y
> > +CONFIG_DISPLAY_ROCKCHIP_DW_MIPI=y
> > +CONFIG_VIDEO_BRIDGE=y
> > +CONFIG_VIDEO_REMOVE=y
> > CONFIG_ERRNO_STR=y
> >
>
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v3 11/12] configs: pinetab2-rk3566: Enable video and USB keyboard
2025-04-15 13:29 ` Dang Huynh
@ 2025-04-15 15:52 ` Jonas Karlman
2025-04-19 4:22 ` Dang Huynh
0 siblings, 1 reply; 20+ messages in thread
From: Jonas Karlman @ 2025-04-15 15:52 UTC (permalink / raw)
To: Dang Huynh
Cc: Anatolij Gustschin, Simon Glass, Philipp Tomsich, Kever Yang,
Tom Rini, Nicolas Frattaroli, Ondrej Jirman, Dragan Simic,
Svyatoslav Ryhel, Lukasz Majewski, Sean Anderson, u-boot,
Piotr Zalewski
On 2025-04-15 15:29, Dang Huynh wrote:
> On Sun, Apr 13, 2025 at 05:26:03PM +0200, Jonas Karlman wrote:
>> Hi,
>>
>> On 2025-04-12 16:27, Dang Huynh wrote:
>>> Now that we have VOP2 support, let's enable it and support the
>>> built in USB keyboard.
>>>
>>> Signed-off-by: Dang Huynh <danct12@riseup.net>
>>> ---
>>> configs/pinetab2-rk3566_defconfig | 11 +++++++++++
>>> 1 file changed, 11 insertions(+)
>>>
>>> diff --git a/configs/pinetab2-rk3566_defconfig b/configs/pinetab2-rk3566_defconfig
>>> index 45e63b42d192dc172f24e071b09c8203675965d8..792ec0ec119437fd7a920558a149363c886c87de 100644
>>> --- a/configs/pinetab2-rk3566_defconfig
>>> +++ b/configs/pinetab2-rk3566_defconfig
>>> @@ -57,6 +57,7 @@ CONFIG_BUTTON=y
>>> CONFIG_BUTTON_ADC=y
>>> CONFIG_BUTTON_GPIO=y
>>> CONFIG_SPL_CLK=y
>>> +CONFIG_CLK_CCF=y
>>
>> Rockchip clk drivers does not use this, and I do not see any new clock
>> driver being added in this series.
>>
>> Why is this needed?
> I initially added this to get around clk_enable error, but it seems like
> you don't need to enable VOP clocks.
>
> However, I noticed that enabling CCF will give us clock rate that are
> pretty close to how it's configured on Linux.
As mentioned on IRC with CCF enabled the clk enable() ops does not need
to be enabled however without CFF the enable() ops must be enable or the
set_parent() ops is just ignored.
So I expect the issue with different rates is that some clock is never
changing parent as requested by DT or driver code.
Please try following diff with CCF disabled:
diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c
index 4b3d812f9c65..93dd32ebe74d 100644
--- a/drivers/clk/clk-uclass.c
+++ b/drivers/clk/clk-uclass.c
@@ -624,7 +624,7 @@ int clk_set_parent(struct clk *clk, struct clk *parent)
return -ENOSYS;
ret = clk_enable(parent);
- if (ret) {
+ if (ret && ret != -ENOSYS) {
printf("Cannot enable parent %s\n", parent->dev->name);
return ret;
}
Not sure this is a good solution or if it will be better to let the
clk_rk3568.c driver just implement a dummy enable() ops.
Regards,
Jonas
>
>>
>> Regards,
>> Jonas
>>
>>> # CONFIG_USB_FUNCTION_FASTBOOT is not set
>>> CONFIG_ROCKCHIP_GPIO=y
>>> CONFIG_SYS_I2C_ROCKCHIP=y
>>> @@ -69,6 +70,7 @@ CONFIG_MMC_SDHCI_SDMA=y
>>> CONFIG_MMC_SDHCI_ROCKCHIP=y
>>> CONFIG_SPI_FLASH_SFDP_SUPPORT=y
>>> CONFIG_SPI_FLASH_SILICONKAISER=y
>>> +CONFIG_PHY_ROCKCHIP_INNO_DSIDPHY=y
>>> CONFIG_PHY_ROCKCHIP_INNO_USB2=y
>>> CONFIG_PHY_ROCKCHIP_NANENG_COMBOPHY=y
>>> CONFIG_SPL_PINCTRL=y
>>> @@ -94,6 +96,7 @@ CONFIG_USB_OHCI_HCD=y
>>> CONFIG_USB_OHCI_GENERIC=y
>>> CONFIG_USB_DWC3=y
>>> CONFIG_USB_DWC3_GENERIC=y
>>> +CONFIG_USB_KEYBOARD=y
>>> CONFIG_USB_HOST_ETHER=y
>>> CONFIG_USB_ETHER_ASIX=y
>>> CONFIG_USB_ETHER_ASIX88179=y
>>> @@ -101,4 +104,12 @@ CONFIG_USB_ETHER_RTL8152=y
>>> CONFIG_USB_GADGET=y
>>> CONFIG_USB_GADGET_DOWNLOAD=y
>>> CONFIG_USB_FUNCTION_ROCKUSB=y
>>> +CONFIG_VIDEO=y
>>> +CONFIG_VIDEO_LCD_BOE_TH101MB31IG002_28A=y
>>> +CONFIG_DISPLAY=y
>>> +CONFIG_VIDEO_ROCKCHIP=y
>>> +CONFIG_DISPLAY_ROCKCHIP_HDMI=y
>>> +CONFIG_DISPLAY_ROCKCHIP_DW_MIPI=y
>>> +CONFIG_VIDEO_BRIDGE=y
>>> +CONFIG_VIDEO_REMOVE=y
>>> CONFIG_ERRNO_STR=y
>>>
>>
^ permalink raw reply related [flat|nested] 20+ messages in thread* Re: [PATCH v3 11/12] configs: pinetab2-rk3566: Enable video and USB keyboard
2025-04-15 15:52 ` Jonas Karlman
@ 2025-04-19 4:22 ` Dang Huynh
0 siblings, 0 replies; 20+ messages in thread
From: Dang Huynh @ 2025-04-19 4:22 UTC (permalink / raw)
To: Jonas Karlman
Cc: Anatolij Gustschin, Simon Glass, Philipp Tomsich, Kever Yang,
Tom Rini, Nicolas Frattaroli, Ondrej Jirman, Dragan Simic,
Svyatoslav Ryhel, Lukasz Majewski, Sean Anderson, u-boot,
Piotr Zalewski
Hi Jonas,
On Tue, Apr 15, 2025 at 05:52:55PM +0200, Jonas Karlman wrote:
> On 2025-04-15 15:29, Dang Huynh wrote:
> > On Sun, Apr 13, 2025 at 05:26:03PM +0200, Jonas Karlman wrote:
> >> Hi,
> >>
> >> On 2025-04-12 16:27, Dang Huynh wrote:
> >>> Now that we have VOP2 support, let's enable it and support the
> >>> built in USB keyboard.
> >>>
> >>> Signed-off-by: Dang Huynh <danct12@riseup.net>
> >>> ---
> >>> configs/pinetab2-rk3566_defconfig | 11 +++++++++++
> >>> 1 file changed, 11 insertions(+)
> >>>
> >>> diff --git a/configs/pinetab2-rk3566_defconfig b/configs/pinetab2-rk3566_defconfig
> >>> index 45e63b42d192dc172f24e071b09c8203675965d8..792ec0ec119437fd7a920558a149363c886c87de 100644
> >>> --- a/configs/pinetab2-rk3566_defconfig
> >>> +++ b/configs/pinetab2-rk3566_defconfig
> >>> @@ -57,6 +57,7 @@ CONFIG_BUTTON=y
> >>> CONFIG_BUTTON_ADC=y
> >>> CONFIG_BUTTON_GPIO=y
> >>> CONFIG_SPL_CLK=y
> >>> +CONFIG_CLK_CCF=y
> >>
> >> Rockchip clk drivers does not use this, and I do not see any new clock
> >> driver being added in this series.
> >>
> >> Why is this needed?
> > I initially added this to get around clk_enable error, but it seems like
> > you don't need to enable VOP clocks.
> >
> > However, I noticed that enabling CCF will give us clock rate that are
> > pretty close to how it's configured on Linux.
>
> As mentioned on IRC with CCF enabled the clk enable() ops does not need
> to be enabled however without CFF the enable() ops must be enable or the
> set_parent() ops is just ignored.
>
> So I expect the issue with different rates is that some clock is never
> changing parent as requested by DT or driver code.
>
> Please try following diff with CCF disabled:
>
> diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c
> index 4b3d812f9c65..93dd32ebe74d 100644
> --- a/drivers/clk/clk-uclass.c
> +++ b/drivers/clk/clk-uclass.c
> @@ -624,7 +624,7 @@ int clk_set_parent(struct clk *clk, struct clk *parent)
> return -ENOSYS;
>
> ret = clk_enable(parent);
> - if (ret) {
> + if (ret && ret != -ENOSYS) {
> printf("Cannot enable parent %s\n", parent->dev->name);
> return ret;
> }
>
>
> Not sure this is a good solution or if it will be better to let the
> clk_rk3568.c driver just implement a dummy enable() ops.
>
Applying the diff does appear to make the clock rate show up correctly
and the mentioned "Cannot enable parent" error disappeared.
Before:
rk_display_init(vop@fe040000): dclk_vp1 clkrate 73000000
After:
rk_display_init(vop@fe040000): dclk_vp1 clkrate 73428571
> Regards,
> Jonas
>
> >
> >>
> >> Regards,
> >> Jonas
> >>
> >>> # CONFIG_USB_FUNCTION_FASTBOOT is not set
> >>> CONFIG_ROCKCHIP_GPIO=y
> >>> CONFIG_SYS_I2C_ROCKCHIP=y
> >>> @@ -69,6 +70,7 @@ CONFIG_MMC_SDHCI_SDMA=y
> >>> CONFIG_MMC_SDHCI_ROCKCHIP=y
> >>> CONFIG_SPI_FLASH_SFDP_SUPPORT=y
> >>> CONFIG_SPI_FLASH_SILICONKAISER=y
> >>> +CONFIG_PHY_ROCKCHIP_INNO_DSIDPHY=y
> >>> CONFIG_PHY_ROCKCHIP_INNO_USB2=y
> >>> CONFIG_PHY_ROCKCHIP_NANENG_COMBOPHY=y
> >>> CONFIG_SPL_PINCTRL=y
> >>> @@ -94,6 +96,7 @@ CONFIG_USB_OHCI_HCD=y
> >>> CONFIG_USB_OHCI_GENERIC=y
> >>> CONFIG_USB_DWC3=y
> >>> CONFIG_USB_DWC3_GENERIC=y
> >>> +CONFIG_USB_KEYBOARD=y
> >>> CONFIG_USB_HOST_ETHER=y
> >>> CONFIG_USB_ETHER_ASIX=y
> >>> CONFIG_USB_ETHER_ASIX88179=y
> >>> @@ -101,4 +104,12 @@ CONFIG_USB_ETHER_RTL8152=y
> >>> CONFIG_USB_GADGET=y
> >>> CONFIG_USB_GADGET_DOWNLOAD=y
> >>> CONFIG_USB_FUNCTION_ROCKUSB=y
> >>> +CONFIG_VIDEO=y
> >>> +CONFIG_VIDEO_LCD_BOE_TH101MB31IG002_28A=y
> >>> +CONFIG_DISPLAY=y
> >>> +CONFIG_VIDEO_ROCKCHIP=y
> >>> +CONFIG_DISPLAY_ROCKCHIP_HDMI=y
> >>> +CONFIG_DISPLAY_ROCKCHIP_DW_MIPI=y
> >>> +CONFIG_VIDEO_BRIDGE=y
> >>> +CONFIG_VIDEO_REMOVE=y
> >>> CONFIG_ERRNO_STR=y
> >>>
> >>
>
Best regards,
Dang
^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH v3 12/12] clk: rockchip: rk3568: Use assigned VPLL clock when possible
2025-04-12 14:27 [PATCH v3 00/12] Rockchip VOP2 support Dang Huynh
` (10 preceding siblings ...)
2025-04-12 14:27 ` [PATCH v3 11/12] configs: pinetab2-rk3566: Enable video and USB keyboard Dang Huynh
@ 2025-04-12 14:27 ` Dang Huynh
11 siblings, 0 replies; 20+ messages in thread
From: Dang Huynh @ 2025-04-12 14:27 UTC (permalink / raw)
To: Anatolij Gustschin, Simon Glass, Philipp Tomsich, Kever Yang,
Tom Rini, Nicolas Frattaroli, Jonas Karlman, Ondrej Jirman,
Dragan Simic, Svyatoslav Ryhel, Lukasz Majewski, Sean Anderson
Cc: Nicolas Frattaroli, u-boot, Piotr Zalewski, Dang Huynh
This matches how VPLL is configured under Linux and avoid weird
behaviors when VPLL is reconfigured under Linux.
Signed-off-by: Dang Huynh <danct12@riseup.net>
---
drivers/clk/rockchip/clk_rk3568.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/drivers/clk/rockchip/clk_rk3568.c b/drivers/clk/rockchip/clk_rk3568.c
index 533031caead6818fe41774c9efee969fdd428dbc..cd0e24d77dcc5ce69b75f23eb6d62582b452a986 100644
--- a/drivers/clk/rockchip/clk_rk3568.c
+++ b/drivers/clk/rockchip/clk_rk3568.c
@@ -1820,7 +1820,11 @@ static ulong rk3568_dclk_vop_set_clk(struct rk3568_clk_priv *priv,
((div - 1) << DCLK0_VOP_DIV_SHIFT));
rk3568_pmu_pll_set_rate(priv, HPLL, div * rate);
} else if (sel == DCLK_VOP_SEL_VPLL) {
- div = DIV_ROUND_UP(RK3568_VOP_PLL_LIMIT_FREQ, rate);
+ if (priv->vpll_hz)
+ div = DIV_ROUND_UP(priv->vpll_hz, rate);
+ else
+ div = DIV_ROUND_UP(RK3568_VOP_PLL_LIMIT_FREQ, rate);
+
rk_clrsetreg(&cru->clksel_con[conid],
DCLK0_VOP_DIV_MASK | DCLK0_VOP_SEL_MASK,
(DCLK_VOP_SEL_VPLL << DCLK0_VOP_SEL_SHIFT) |
--
2.49.0
^ permalink raw reply related [flat|nested] 20+ messages in thread