- add display driver for ST-Ericsson MCDE

- drop legacy CONFIG_VIDEO dependency for Hitachi tx18d42vm
 -----BEGIN PGP SIGNATURE-----
 
 iGwEABECACwWIQSC4hxrSoIUVfFO0kRM6ATMmsalXAUCYQxSug4cYWd1c3RAZGVu
 eC5kZQAKCRBM6ATMmsalXEcdAJ4yWCMX2fxbY8qTFR5ovC7lKFTi9QCdHr+BM+jS
 2//ErMcUxdSPKbrwZ5E=
 =O0cV
 -----END PGP SIGNATURE-----

Merge tag 'video-2021-08-05' of https://source.denx.de/u-boot/custodians/u-boot-video

 - add display driver for ST-Ericsson MCDE
 - drop legacy CONFIG_VIDEO dependency for Hitachi tx18d42vm
This commit is contained in:
Tom Rini 2021-08-06 13:46:40 -04:00
commit 8f07f5376a
3 changed files with 154 additions and 1 deletions

View file

@ -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
@ -854,6 +853,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

View file

@ -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

141
drivers/video/mcde_simple.c Normal file
View file

@ -0,0 +1,141 @@
// SPDX-License-Identifier: GPL-2.0+
/* Copyright (C) 2019 Stephan Gerhold */
#include <common.h>
#include <dm.h>
#include <log.h>
#include <video.h>
#include <asm/io.h>
#include <linux/bitfield.h>
#include <linux/iopoll.h>
#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),
};