From 21a151a79d51839ab0a08a7e2ca2ee4c9f79ab1c Mon Sep 17 00:00:00 2001 From: Stephan Gerhold Date: Fri, 2 Jul 2021 19:21:56 +0200 Subject: video: Add simple driver for ST-Ericsson MCDE with pre-configured display The U-Boot port for ST-Ericsson Ux500 is currently only used on the "stemmy" board, where U-Boot runs after firmware that already sets up a boot splash screen. This means that the display is already on and we can just continue using it for U-Boot. Add a simple driver that simplifies this by reading the display configuration (e.g. screen size, bpp) from the hardware registers. It also checks the configured "source synchronization" - for some displays (usually DSI command mode displays) we need to explicitly trigger a software sync. This is done through the video_sync() callback that triggers the sync and wait for completion. Cc: Linus Walleij Signed-off-by: Stephan Gerhold Reviewed-by: Linus Walleij --- drivers/video/Kconfig | 12 ++++ drivers/video/Makefile | 1 + drivers/video/mcde_simple.c | 141 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 154 insertions(+) create mode 100644 drivers/video/mcde_simple.c diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index b69ffcae4b..e614a04aab 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -854,6 +854,18 @@ config VIDEO_DT_SIMPLEFB The video output is initialized by U-Boot, and kept by the kernel. +config VIDEO_MCDE_SIMPLE + bool "Simple driver for ST-Ericsson MCDE with preconfigured display" + depends on DM_VIDEO + help + Enables a simple display driver for ST-Ericsson MCDE + (Multichannel Display Engine), which reads the configuration from + the MCDE registers. + + This driver assumes that the display hardware has been initialized + before u-boot starts, and u-boot will simply render to the pre- + allocated frame buffer surface. + config OSD bool "Enable OSD support" depends on DM diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 1c534a6f9a..7ae0ab2b35 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -58,6 +58,7 @@ obj-$(CONFIG_VIDEO_LCD_ORISETECH_OTM8009A) += orisetech_otm8009a.o obj-$(CONFIG_VIDEO_LCD_RAYDIUM_RM68200) += raydium-rm68200.o obj-$(CONFIG_VIDEO_LCD_SSD2828) += ssd2828.o obj-$(CONFIG_VIDEO_LCD_TDO_TL070WSH30) += tdo-tl070wsh30.o +obj-$(CONFIG_VIDEO_MCDE_SIMPLE) += mcde_simple.o obj-${CONFIG_VIDEO_MESON} += meson/ obj-${CONFIG_VIDEO_MIPI_DSI} += mipi_dsi.o obj-$(CONFIG_VIDEO_MVEBU) += mvebu_lcd.o diff --git a/drivers/video/mcde_simple.c b/drivers/video/mcde_simple.c new file mode 100644 index 0000000000..0924ceee30 --- /dev/null +++ b/drivers/video/mcde_simple.c @@ -0,0 +1,141 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* Copyright (C) 2019 Stephan Gerhold */ + +#include +#include +#include +#include +#include +#include +#include + +#define MCDE_EXTSRC0A0 0x200 +#define MCDE_EXTSRC0CONF 0x20C +#define MCDE_EXTSRC0CONF_BPP GENMASK(11, 8) +#define MCDE_OVL0CONF 0x404 +#define MCDE_OVL0CONF_PPL GENMASK(10, 0) +#define MCDE_OVL0CONF_LPF GENMASK(26, 16) +#define MCDE_CHNL0SYNCHMOD 0x608 +#define MCDE_CHNL0SYNCHMOD_SRC_SYNCH GENMASK(1, 0) +#define MCDE_CHNL0SYNCHSW 0x60C +#define MCDE_CHNL0SYNCHSW_SW_TRIG BIT(0) +#define MCDE_CRA0 0x800 +#define MCDE_CRA0_FLOEN BIT(0) + +#define MCDE_FLOW_COMPLETION_TIMEOUT 200000 /* us */ + +enum mcde_bpp { + MCDE_EXTSRC0CONF_BPP_1BPP_PAL, + MCDE_EXTSRC0CONF_BPP_2BPP_PAL, + MCDE_EXTSRC0CONF_BPP_4BPP_PAL, + MCDE_EXTSRC0CONF_BPP_8BPP_PAL, + MCDE_EXTSRC0CONF_BPP_RGB444, + MCDE_EXTSRC0CONF_BPP_ARGB4444, + MCDE_EXTSRC0CONF_BPP_IRGB1555, + MCDE_EXTSRC0CONF_BPP_RGB565, + MCDE_EXTSRC0CONF_BPP_RGB888, + MCDE_EXTSRC0CONF_BPP_XRGB8888, + MCDE_EXTSRC0CONF_BPP_ARGB8888, + MCDE_EXTSRC0CONF_BPP_YCBCR422, +}; + +enum mcde_src_synch { + MCDE_CHNL0SYNCHMOD_SRC_SYNCH_HARDWARE, + MCDE_CHNL0SYNCHMOD_SRC_SYNCH_NO_SYNCH, + MCDE_CHNL0SYNCHMOD_SRC_SYNCH_SOFTWARE, +}; + +struct mcde_simple_priv { + fdt_addr_t base; + enum mcde_src_synch src_synch; +}; + +static int mcde_simple_probe(struct udevice *dev) +{ + struct mcde_simple_priv *priv = dev_get_priv(dev); + struct video_uc_plat *plat = dev_get_uclass_plat(dev); + struct video_priv *uc_priv = dev_get_uclass_priv(dev); + u32 val; + + priv->base = dev_read_addr(dev); + if (priv->base == FDT_ADDR_T_NONE) + return -EINVAL; + + plat->base = readl(priv->base + MCDE_EXTSRC0A0); + if (!plat->base) + return -ENODEV; + + val = readl(priv->base + MCDE_OVL0CONF); + uc_priv->xsize = FIELD_GET(MCDE_OVL0CONF_PPL, val); + uc_priv->ysize = FIELD_GET(MCDE_OVL0CONF_LPF, val); + uc_priv->rot = 0; + + val = readl(priv->base + MCDE_EXTSRC0CONF); + switch (FIELD_GET(MCDE_EXTSRC0CONF_BPP, val)) { + case MCDE_EXTSRC0CONF_BPP_RGB565: + uc_priv->bpix = VIDEO_BPP16; + break; + case MCDE_EXTSRC0CONF_BPP_XRGB8888: + case MCDE_EXTSRC0CONF_BPP_ARGB8888: + uc_priv->bpix = VIDEO_BPP32; + break; + default: + printf("unsupported format: %#x\n", val); + return -EINVAL; + } + + val = readl(priv->base + MCDE_CHNL0SYNCHMOD); + priv->src_synch = FIELD_GET(MCDE_CHNL0SYNCHMOD_SRC_SYNCH, val); + + plat->size = uc_priv->xsize * uc_priv->ysize * VNBYTES(uc_priv->bpix); + debug("MCDE base: %#lx, xsize: %d, ysize: %d, bpp: %d\n", + plat->base, uc_priv->xsize, uc_priv->ysize, VNBITS(uc_priv->bpix)); + + video_set_flush_dcache(dev, true); + return 0; +} + +static int mcde_simple_video_sync(struct udevice *dev) +{ + struct mcde_simple_priv *priv = dev_get_priv(dev); + unsigned int val; + + if (priv->src_synch != MCDE_CHNL0SYNCHMOD_SRC_SYNCH_SOFTWARE) + return 0; + + /* Enable flow */ + val = readl(priv->base + MCDE_CRA0); + val |= MCDE_CRA0_FLOEN; + writel(val, priv->base + MCDE_CRA0); + + /* Trigger a software sync */ + writel(MCDE_CHNL0SYNCHSW_SW_TRIG, priv->base + MCDE_CHNL0SYNCHSW); + + /* Disable flow */ + val = readl(priv->base + MCDE_CRA0); + val &= ~MCDE_CRA0_FLOEN; + writel(val, priv->base + MCDE_CRA0); + + /* Wait for completion */ + return readl_poll_timeout(priv->base + MCDE_CRA0, val, + !(val & MCDE_CRA0_FLOEN), + MCDE_FLOW_COMPLETION_TIMEOUT); +} + +static struct video_ops mcde_simple_ops = { + .video_sync = mcde_simple_video_sync, +}; + +static const struct udevice_id mcde_simple_ids[] = { + { .compatible = "ste,mcde" }, + { } +}; + +U_BOOT_DRIVER(mcde_simple) = { + .name = "mcde_simple", + .id = UCLASS_VIDEO, + .ops = &mcde_simple_ops, + .of_match = mcde_simple_ids, + .probe = mcde_simple_probe, + .priv_auto = sizeof(struct mcde_simple_priv), +}; -- cgit v1.2.3 From 845d71ce999936ab5ae2cef4542b221851cde199 Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Tue, 27 Jul 2021 15:47:50 +0100 Subject: video: Hitachi panel: Drop bogus dependency on CONFIG_VIDEO The Hitachi tx18d42vm LCD panel driver is really just initialising the device, using bitbanged SPI, during operation there is nothing to do. This makes the driver self contained, so drop the bogus dependency on the legacy CONFIG_VIDEO. This avoids the warning when building Chuwi_V7_CW0825_defconfig, since we switched to DM_VIDEO recently. Signed-off-by: Andre Przywara --- drivers/video/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index e614a04aab..8b940d70eb 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -470,7 +470,6 @@ config VIDEO_LCD_TDO_TL070WSH30 config VIDEO_LCD_HITACHI_TX18D42VM bool "Hitachi tx18d42vm LVDS LCD panel support" - depends on VIDEO default n ---help--- Support for Hitachi tx18d42vm LVDS LCD panels, these panels have a -- cgit v1.2.3