aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Rini <trini@konsulko.com>2023-05-05 09:36:08 -0400
committerTom Rini <trini@konsulko.com>2023-05-05 09:36:08 -0400
commitab75996ba49c140c529f14b5c40d0d16430feefb (patch)
treeacedbf783e9db8b8b7d0adadb3aa14565d7c646b
parenteb59ece5204fe06bd037fe64944bfbb3b85864ea (diff)
parentdef72d5c6265bde4e9eb7976db53a77fabc4808a (diff)
downloadu-boot-WIP/05May2023.zip
u-boot-WIP/05May2023.tar.gz
u-boot-WIP/05May2023.tar.bz2
Merge tag 'video-for-v2023.07-rc2' of https://source.denx.de/u-boot/custodians/u-boot-videoWIP/05May2023
- enable video support in SPL - support splash screen for TI am62x - replace #ifdef and #if with if's in bmp/splash - add lm3533 backlight driver - add Solomon SSD2825 DSI/LVDS bridge driver - add Renesas R61307 and R69328 MIPI DSI panel drivers - add tegra DC based PWM backlight driver - add generic endeavoru (HTC One X) panel driver
-rw-r--r--board/ti/am62x/evm.c8
-rw-r--r--cmd/bmp.c162
-rw-r--r--common/Kconfig12
-rw-r--r--common/Makefile3
-rw-r--r--common/bmp.c149
-rw-r--r--common/splash.c20
-rw-r--r--drivers/Makefile1
-rw-r--r--drivers/video/Kconfig261
-rw-r--r--drivers/video/Makefile20
-rw-r--r--drivers/video/bridge/Kconfig7
-rw-r--r--drivers/video/bridge/Makefile1
-rw-r--r--drivers/video/bridge/ssd2825.c520
-rw-r--r--drivers/video/console_core.c6
-rw-r--r--drivers/video/endeavoru-panel.c252
-rw-r--r--drivers/video/lm3533_backlight.c134
-rw-r--r--drivers/video/renesas-r61307.c302
-rw-r--r--drivers/video/renesas-r69328.c238
-rw-r--r--drivers/video/tegra20/Kconfig7
-rw-r--r--drivers/video/tegra20/Makefile1
-rw-r--r--drivers/video/tegra20/tegra-pwm-backlight.c156
-rw-r--r--drivers/video/tidss/Kconfig6
-rw-r--r--drivers/video/tidss/Makefile2
-rw-r--r--drivers/video/vidconsole-uclass.c2
-rw-r--r--drivers/video/video-uclass.c14
-rw-r--r--drivers/video/video_bmp.c8
-rw-r--r--include/asm-generic/global_data.h4
-rw-r--r--include/splash.h15
-rw-r--r--include/video.h8
28 files changed, 2107 insertions, 212 deletions
diff --git a/board/ti/am62x/evm.c b/board/ti/am62x/evm.c
index 034fbed..e00e42e 100644
--- a/board/ti/am62x/evm.c
+++ b/board/ti/am62x/evm.c
@@ -19,9 +19,15 @@
DECLARE_GLOBAL_DATA_PTR;
-#ifdef CONFIG_SPLASH_SCREEN
+#if CONFIG_IS_ENABLED(SPLASH_SCREEN)
static struct splash_location default_splash_locations[] = {
{
+ .name = "sf",
+ .storage = SPLASH_STORAGE_SF,
+ .flags = SPLASH_STORAGE_RAW,
+ .offset = 0x700000,
+ },
+ {
.name = "mmc",
.storage = SPLASH_STORAGE_MMC,
.flags = SPLASH_STORAGE_FS,
diff --git a/cmd/bmp.c b/cmd/bmp.c
index 46d0d91..8f43a40 100644
--- a/cmd/bmp.c
+++ b/cmd/bmp.c
@@ -9,84 +9,12 @@
*/
#include <common.h>
-#include <bmp_layout.h>
#include <command.h>
-#include <dm.h>
-#include <gzip.h>
#include <image.h>
-#include <log.h>
-#include <malloc.h>
#include <mapmem.h>
#include <splash.h>
#include <video.h>
-#include <asm/byteorder.h>
-
-static int bmp_info (ulong addr);
-
-/*
- * Allocate and decompress a BMP image using gunzip().
- *
- * Returns a pointer to the decompressed image data. This pointer is
- * aligned to 32-bit-aligned-address + 2.
- * See doc/README.displaying-bmps for explanation.
- *
- * The allocation address is passed to 'alloc_addr' and must be freed
- * by the caller after use.
- *
- * Returns NULL if decompression failed, or if the decompressed data
- * didn't contain a valid BMP signature.
- */
-#ifdef CONFIG_VIDEO_BMP_GZIP
-struct bmp_image *gunzip_bmp(unsigned long addr, unsigned long *lenp,
- void **alloc_addr)
-{
- void *dst;
- unsigned long len;
- struct bmp_image *bmp;
-
- /*
- * Decompress bmp image
- */
- len = CONFIG_VIDEO_LOGO_MAX_SIZE;
- /* allocate extra 3 bytes for 32-bit-aligned-address + 2 alignment */
- dst = malloc(CONFIG_VIDEO_LOGO_MAX_SIZE + 3);
- if (!dst) {
- puts("Error: malloc in gunzip failed!\n");
- return NULL;
- }
-
- /* align to 32-bit-aligned-address + 2 */
- bmp = dst + 2;
-
- if (gunzip(bmp, CONFIG_VIDEO_LOGO_MAX_SIZE, map_sysmem(addr, 0),
- &len)) {
- free(dst);
- return NULL;
- }
- if (len == CONFIG_VIDEO_LOGO_MAX_SIZE)
- puts("Image could be truncated (increase CONFIG_VIDEO_LOGO_MAX_SIZE)!\n");
-
- /*
- * Check for bmp mark 'BM'
- */
- if (!((bmp->header.signature[0] == 'B') &&
- (bmp->header.signature[1] == 'M'))) {
- free(dst);
- return NULL;
- }
-
- debug("Gzipped BMP image detected!\n");
-
- *alloc_addr = dst;
- return bmp;
-}
-#else
-struct bmp_image *gunzip_bmp(unsigned long addr, unsigned long *lenp,
- void **alloc_addr)
-{
- return NULL;
-}
-#endif
+#include <stdlib.h>
static int do_bmp_info(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[])
@@ -137,7 +65,7 @@ static int do_bmp_display(struct cmd_tbl *cmdtp, int flag, int argc,
return CMD_RET_USAGE;
}
- return (bmp_display(addr, x, y));
+ return (bmp_display(addr, x, y));
}
static struct cmd_tbl cmd_bmp_sub[] = {
@@ -145,22 +73,6 @@ static struct cmd_tbl cmd_bmp_sub[] = {
U_BOOT_CMD_MKENT(display, 5, 0, do_bmp_display, "", ""),
};
-#ifdef CONFIG_NEEDS_MANUAL_RELOC
-void bmp_reloc(void) {
- fixup_cmdtable(cmd_bmp_sub, ARRAY_SIZE(cmd_bmp_sub));
-}
-#endif
-
-/*
- * Subroutine: do_bmp
- *
- * Description: Handler for 'bmp' command..
- *
- * Inputs: argv[1] contains the subcommand
- *
- * Return: None
- *
- */
static int do_bmp(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
{
struct cmd_tbl *c;
@@ -183,73 +95,3 @@ U_BOOT_CMD(
"info <imageAddr> - display image info\n"
"bmp display <imageAddr> [x y] - display image at x,y"
);
-
-/*
- * Subroutine: bmp_info
- *
- * Description: Show information about bmp file in memory
- *
- * Inputs: addr address of the bmp file
- *
- * Return: None
- *
- */
-static int bmp_info(ulong addr)
-{
- struct bmp_image *bmp = (struct bmp_image *)map_sysmem(addr, 0);
- void *bmp_alloc_addr = NULL;
- unsigned long len;
-
- if (!((bmp->header.signature[0]=='B') &&
- (bmp->header.signature[1]=='M')))
- bmp = gunzip_bmp(addr, &len, &bmp_alloc_addr);
-
- if (bmp == NULL) {
- printf("There is no valid bmp file at the given address\n");
- return 1;
- }
-
- printf("Image size : %d x %d\n", le32_to_cpu(bmp->header.width),
- le32_to_cpu(bmp->header.height));
- printf("Bits per pixel: %d\n", le16_to_cpu(bmp->header.bit_count));
- printf("Compression : %d\n", le32_to_cpu(bmp->header.compression));
-
- if (bmp_alloc_addr)
- free(bmp_alloc_addr);
-
- return(0);
-}
-
-int bmp_display(ulong addr, int x, int y)
-{
- struct udevice *dev;
- int ret;
- struct bmp_image *bmp = map_sysmem(addr, 0);
- void *bmp_alloc_addr = NULL;
- unsigned long len;
-
- if (!((bmp->header.signature[0]=='B') &&
- (bmp->header.signature[1]=='M')))
- bmp = gunzip_bmp(addr, &len, &bmp_alloc_addr);
-
- if (!bmp) {
- printf("There is no valid bmp file at the given address\n");
- return 1;
- }
- addr = map_to_sysmem(bmp);
-
- ret = uclass_first_device_err(UCLASS_VIDEO, &dev);
- if (!ret) {
- bool align = false;
-
- if (x == BMP_ALIGN_CENTER || y == BMP_ALIGN_CENTER)
- align = true;
-
- ret = video_bmp_display(dev, addr, x, y, align);
- }
-
- if (bmp_alloc_addr)
- free(bmp_alloc_addr);
-
- return ret ? CMD_RET_FAILURE : 0;
-}
diff --git a/common/Kconfig b/common/Kconfig
index a19d82f..bbabadb 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -1154,3 +1154,15 @@ config FDT_SIMPLEFB
config IO_TRACE
bool
+
+config BMP
+ bool "Enable bmp image display"
+ default y if CMD_BMP
+ help
+ Enable bmp functions to display bmp image and get bmp info.
+
+config SPL_BMP
+ bool "Enable bmp image display at SPL"
+ depends on SPL_VIDEO
+ help
+ Enable bmp functions to display bmp image and get bmp info at SPL.
diff --git a/common/Makefile b/common/Makefile
index a50302d..c87bb2e 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -45,6 +45,7 @@ endif # !CONFIG_SPL_BUILD
obj-$(CONFIG_$(SPL_TPL_)BOOTSTAGE) += bootstage.o
obj-$(CONFIG_$(SPL_TPL_)BLOBLIST) += bloblist.o
+obj-$(CONFIG_$(SPL_)BMP) += bmp.o
ifdef CONFIG_SPL_BUILD
ifdef CONFIG_SPL_DFU
@@ -56,6 +57,8 @@ obj-$(CONFIG_$(SPL_TPL_)OF_LIBFDT) += fdt_support.o
obj-$(CONFIG_SPL_USB_HOST) += usb.o usb_hub.o
obj-$(CONFIG_SPL_USB_STORAGE) += usb_storage.o
obj-$(CONFIG_SPL_MUSB_NEW) += usb.o
+obj-$(CONFIG_SPL_SPLASH_SCREEN) += splash.o
+obj-$(CONFIG_SPL_SPLASH_SOURCE) += splash_source.o
endif # CONFIG_SPL_BUILD
#others
diff --git a/common/bmp.c b/common/bmp.c
new file mode 100644
index 0000000..57764f3
--- /dev/null
+++ b/common/bmp.c
@@ -0,0 +1,149 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2002
+ * Detlev Zundel, DENX Software Engineering, dzu@denx.de.
+ */
+
+/*
+ * BMP handling routines
+ */
+
+#include <common.h>
+#include <bmp_layout.h>
+#include <command.h>
+#include <dm.h>
+#include <gzip.h>
+#include <log.h>
+#include <malloc.h>
+#include <mapmem.h>
+#include <splash.h>
+#include <video.h>
+#include <asm/byteorder.h>
+
+/*
+ * Allocate and decompress a BMP image using gunzip().
+ *
+ * Returns a pointer to the decompressed image data. This pointer is
+ * aligned to 32-bit-aligned-address + 2.
+ * See doc/README.displaying-bmps for explanation.
+ *
+ * The allocation address is passed to 'alloc_addr' and must be freed
+ * by the caller after use.
+ *
+ * Returns NULL if decompression failed, or if the decompressed data
+ * didn't contain a valid BMP signature or decompression is not enabled in
+ * Kconfig.
+ */
+struct bmp_image *gunzip_bmp(unsigned long addr, unsigned long *lenp,
+ void **alloc_addr)
+{
+ void *dst;
+ unsigned long len;
+ struct bmp_image *bmp;
+
+ if (!CONFIG_IS_ENABLED(VIDEO_BMP_GZIP))
+ return NULL;
+
+ /*
+ * Decompress bmp image
+ */
+ len = CONFIG_VAL(VIDEO_LOGO_MAX_SIZE);
+ /* allocate extra 3 bytes for 32-bit-aligned-address + 2 alignment */
+ dst = malloc(CONFIG_VAL(VIDEO_LOGO_MAX_SIZE) + 3);
+ if (!dst) {
+ puts("Error: malloc in gunzip failed!\n");
+ return NULL;
+ }
+
+ /* align to 32-bit-aligned-address + 2 */
+ bmp = dst + 2;
+
+ if (gunzip(bmp, CONFIG_VAL(VIDEO_LOGO_MAX_SIZE), map_sysmem(addr, 0),
+ &len)) {
+ free(dst);
+ return NULL;
+ }
+ if (len == CONFIG_VAL(VIDEO_LOGO_MAX_SIZE))
+ puts("Image could be truncated (increase CONFIG_VIDEO_LOGO_MAX_SIZE)!\n");
+
+ /*
+ * Check for bmp mark 'BM'
+ */
+ if (!((bmp->header.signature[0] == 'B') &&
+ (bmp->header.signature[1] == 'M'))) {
+ free(dst);
+ return NULL;
+ }
+
+ debug("Gzipped BMP image detected!\n");
+
+ *alloc_addr = dst;
+ return bmp;
+}
+
+#ifdef CONFIG_NEEDS_MANUAL_RELOC
+void bmp_reloc(void)
+{
+ fixup_cmdtable(cmd_bmp_sub, ARRAY_SIZE(cmd_bmp_sub));
+}
+#endif
+
+int bmp_info(ulong addr)
+{
+ struct bmp_image *bmp = (struct bmp_image *)map_sysmem(addr, 0);
+ void *bmp_alloc_addr = NULL;
+ unsigned long len;
+
+ if (!((bmp->header.signature[0] == 'B') &&
+ (bmp->header.signature[1] == 'M')))
+ bmp = gunzip_bmp(addr, &len, &bmp_alloc_addr);
+
+ if (!bmp) {
+ printf("There is no valid bmp file at the given address\n");
+ return 1;
+ }
+
+ printf("Image size : %d x %d\n", le32_to_cpu(bmp->header.width),
+ le32_to_cpu(bmp->header.height));
+ printf("Bits per pixel: %d\n", le16_to_cpu(bmp->header.bit_count));
+ printf("Compression : %d\n", le32_to_cpu(bmp->header.compression));
+
+ if (bmp_alloc_addr)
+ free(bmp_alloc_addr);
+
+ return 0;
+}
+
+int bmp_display(ulong addr, int x, int y)
+{
+ struct udevice *dev;
+ int ret;
+ struct bmp_image *bmp = map_sysmem(addr, 0);
+ void *bmp_alloc_addr = NULL;
+ unsigned long len;
+
+ if (!((bmp->header.signature[0] == 'B') &&
+ (bmp->header.signature[1] == 'M')))
+ bmp = gunzip_bmp(addr, &len, &bmp_alloc_addr);
+
+ if (!bmp) {
+ printf("There is no valid bmp file at the given address\n");
+ return 1;
+ }
+ addr = map_to_sysmem(bmp);
+
+ ret = uclass_first_device_err(UCLASS_VIDEO, &dev);
+ if (!ret) {
+ bool align = false;
+
+ if (x == BMP_ALIGN_CENTER || y == BMP_ALIGN_CENTER)
+ align = true;
+
+ ret = video_bmp_display(dev, addr, x, y, align);
+ }
+
+ if (bmp_alloc_addr)
+ free(bmp_alloc_addr);
+
+ return ret ? CMD_RET_FAILURE : 0;
+}
diff --git a/common/splash.c b/common/splash.c
index 4bc54b1..6820db6 100644
--- a/common/splash.c
+++ b/common/splash.c
@@ -89,19 +89,18 @@ static inline int splash_video_logo_load(void) { return -ENOSYS; }
__weak int splash_screen_prepare(void)
{
- if (IS_ENABLED(CONFIG_SPLASH_SOURCE))
+ if (CONFIG_IS_ENABLED(SPLASH_SOURCE))
return splash_source_load(default_splash_locations,
ARRAY_SIZE(default_splash_locations));
return splash_video_logo_load();
}
-#ifdef CONFIG_SPLASH_SCREEN_ALIGN
void splash_get_pos(int *x, int *y)
{
char *s = env_get("splashpos");
- if (!s)
+ if (!CONFIG_IS_ENABLED(SPLASH_SCREEN_ALIGN) || !s)
return;
if (s[0] == 'm')
@@ -117,9 +116,8 @@ void splash_get_pos(int *x, int *y)
*y = simple_strtol(s + 1, NULL, 0);
}
}
-#endif /* CONFIG_SPLASH_SCREEN_ALIGN */
-#if defined(CONFIG_VIDEO) && !defined(CONFIG_HIDE_LOGO_VERSION)
+#if CONFIG_IS_ENABLED(VIDEO) && !CONFIG_IS_ENABLED(HIDE_LOGO_VERSION)
#ifdef CONFIG_VIDEO_LOGO
#include <bmp_logo.h>
@@ -159,13 +157,13 @@ void splash_display_banner(void)
* Common function to show a splash image if env("splashimage") is set.
* For additional details please refer to doc/README.splashprepare.
*/
-#if defined(CONFIG_SPLASH_SCREEN) && defined(CONFIG_CMD_BMP)
int splash_display(void)
{
ulong addr;
char *s;
int x = 0, y = 0, ret;
-
+ if (!CONFIG_IS_ENABLED(SPLASH_SCREEN))
+ return -ENOSYS;
s = env_get("splashimage");
if (!s)
return -EINVAL;
@@ -177,16 +175,18 @@ int splash_display(void)
splash_get_pos(&x, &y);
- ret = bmp_display(addr, x, y);
+ if (CONFIG_IS_ENABLED(BMP))
+ ret = bmp_display(addr, x, y);
+ else
+ return -ENOSYS;
/* Skip banner output on video console if the logo is not at 0,0 */
if (x || y)
goto end;
-#if defined(CONFIG_VIDEO) && !defined(CONFIG_HIDE_LOGO_VERSION)
+#if CONFIG_IS_ENABLED(VIDEO) && !CONFIG_IS_ENABLED(HIDE_LOGO_VERSION)
splash_display_banner();
#endif
end:
return ret;
}
-#endif
diff --git a/drivers/Makefile b/drivers/Makefile
index ed1e71c..29be78a 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -62,6 +62,7 @@ obj-$(CONFIG_SPL_USB_HOST) += usb/host/
obj-$(CONFIG_SPL_SATA) += ata/ scsi/
obj-$(CONFIG_SPL_LEGACY_BLOCK) += block/
obj-$(CONFIG_SPL_THERMAL) += thermal/
+obj-$(CONFIG_SPL_VIDEO) +=video/
endif
endif
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 334d64c..fcc0e85 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -466,6 +466,17 @@ 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_ENDEAVORU
+ tristate "Endeavoru 720x1280 DSI video mode panel"
+ depends on PANEL && BACKLIGHT
+ select VIDEO_MIPI_DSI
+ help
+ Say Y here if you want to enable support for the IPS-LCD panel
+ module for HTC One X. Driver supports a family of panels,
+ made at least by 3 vendors (Sharp, Sony and AUO), but set up
+ using the same DSI command sequence. The panel has a 720x1280
+ resolution and uses 24 bit RGB per pixel.
+
config VIDEO_LCD_ORISETECH_OTM8009A
bool "OTM8009A DSI LCD panel support"
select VIDEO_MIPI_DSI
@@ -480,6 +491,24 @@ config VIDEO_LCD_RAYDIUM_RM68200
Say Y here if you want to enable support for Raydium RM68200
720x1280 DSI video mode panel.
+config VIDEO_LCD_RENESAS_R61307
+ tristate "Renesas R61307 DSI video mode panel"
+ depends on PANEL && BACKLIGHT
+ select VIDEO_MIPI_DSI
+ help
+ Say Y here if you want to enable support for KOE tx13d100vm0eaa
+ IPS-LCD module with Renesas R69328 IC. The panel has a 1024x768
+ resolution and uses 24 bit RGB per pixel.
+
+config VIDEO_LCD_RENESAS_R69328
+ tristate "Renesas R69328 720x1280 DSI video mode panel"
+ depends on PANEL && BACKLIGHT
+ select VIDEO_MIPI_DSI
+ help
+ Say Y here if you want to enable support for JDI dx12d100vm0eaa
+ IPS-LCD module with Renesas R69328 IC. The panel has a 720x1280
+ resolution and uses 24 bit RGB per pixel.
+
config VIDEO_LCD_SSD2828
bool "SSD2828 bridge chip"
---help---
@@ -606,6 +635,15 @@ config ATMEL_HLCD
help
HLCDC supports video output to an attached LCD panel.
+config BACKLIGHT_LM3533
+ bool "Backlight Driver for LM3533"
+ depends on BACKLIGHT
+ select DM_I2C
+ help
+ Say Y to enable the backlight driver for National Semiconductor / TI
+ LM3533 Lighting Power chip. Only Bank A is supported as for now.
+ Supported backlight level range is from 2 to 255 with step of 1.
+
source "drivers/video/ti/Kconfig"
source "drivers/video/exynos/Kconfig"
@@ -886,7 +924,7 @@ endif # SPLASH_SCREEN
config VIDEO_BMP_GZIP
bool "Gzip compressed BMP image support"
- depends on CMD_BMP || SPLASH_SCREEN
+ depends on BMP || SPLASH_SCREEN
help
If this option is set, additionally to standard BMP
images, gzipped BMP images can be displayed via the
@@ -923,4 +961,225 @@ config BMP_32BPP
endif # VIDEO
+config SPL_VIDEO
+ bool "Enable driver model support for LCD/video"
+ depends on SPL_DM
+ help
+ The video subsystem adds a small amount of overhead to the image.
+ If this is acceptable and you have a need to use video drivers in
+ SPL, enable this option. It might provide a cleaner interface to
+ setting up video within SPL, and allows the same drivers to be
+ used as U-Boot proper.
+
+if SPL_VIDEO
+source "drivers/video/tidss/Kconfig"
+
+config SPL_VIDEO_LOGO
+ bool "Show the U-Boot logo on the display at SPL"
+ default y if !SPL_SPLASH_SCREEN
+ select SPL_VIDEO_BMP_RLE8
+ help
+ This enables showing the U-Boot logo on the display when a video
+ device is probed. It appears at the top right. The logo itself is at
+ tools/logos/u-boot_logo.bmp and looks best when the display has a
+ black background.
+
+config SPL_SPLASH_SCREEN
+ bool "Show a splash-screen image at SPL"
+ help
+ If this option is set, the environment is checked for a variable
+ "splashimage" at spl stage.
+
+config SPL_SYS_WHITE_ON_BLACK
+ bool "Display console as white on a black background at SPL"
+ help
+ Normally the display is black on a white background, Enable this
+ option to invert this, i.e. white on a black background at spl stage.
+ This can be better in low-light situations or to reduce eye strain in
+ some cases.
+
+config SPL_VIDEO_PCI_DEFAULT_FB_SIZE
+ hex "Default framebuffer size to use if no drivers request it at SPL"
+ default 0x1000000 if X86 && PCI
+ default 0 if !(X86 && PCI)
+ help
+ Generally, video drivers request the amount of memory they need for
+ the frame buffer when they are bound, by setting the size field in
+ struct video_uc_plat. That memory is then reserved for use after
+ relocation. But PCI drivers cannot be bound before relocation unless
+ they are mentioned in the devicetree.
+
+ With this value set appropriately, it is possible for PCI video
+ devices to have a framebuffer allocated by U-Boot.
+
+ Note: the framebuffer needs to be large enough to store all pixels at
+ maximum resolution. For example, at 1920 x 1200 with 32 bits per
+ pixel, 2560 * 1600 * 32 / 8 = 0xfa0000 bytes are needed.
+
+config SPL_CONSOLE_SCROLL_LINES
+ int "Number of lines to scroll the console by at SPL"
+ default 1
+ help
+ When the console need to be scrolled, this is the number of
+ lines to scroll by. It defaults to 1. Increasing this makes the
+ console jump but can help speed up operation when scrolling
+ is slow.
+
+config SPL_CONSOLE_NORMAL
+ bool "Support a simple text console at SPL"
+ default y
+ help
+ Support drawing text on the frame buffer console so that it can be
+ used as a console. Rotation is not supported by this driver (see
+ CONFIG_CONSOLE_ROTATION for that). A built-in 8x16 font is used
+ for the display.
+
+config SPL_BACKLIGHT
+ bool "Enable panel backlight uclass support at SPL"
+ default y
+ help
+ This provides backlight uclass driver that enables basic panel
+ backlight support.
+
+config SPL_PANEL
+ bool "Enable panel uclass support at SPL"
+ default y
+ help
+ This provides panel uclass driver that enables basic panel support.
+
+config SPL_SIMPLE_PANEL
+ bool "Enable simple panel support at SPL"
+ depends on SPL_PANEL && SPL_BACKLIGHT && SPL_DM_GPIO
+ default y
+ help
+ This turns on a simple panel driver that enables a compatible
+ video panel.
+
+config SPL_SYS_WHITE_ON_BLACK
+ bool "Display console as white on a black background at SPL"
+ help
+ Normally the display is black on a white background, Enable this
+ option to invert this, i.e. white on a black background at spl stage.
+ This can be better in low-light situations or to reduce eye strain in
+ some cases.
+
+if SPL_SPLASH_SCREEN
+
+config SPL_SPLASH_SCREEN_ALIGN
+ bool "Allow positioning the splash image anywhere on the display at SPL"
+ help
+ If this option is set the splash image can be freely positioned
+ on the screen only at SPL. Environment variable "splashpos" specifies
+ the position as "x,y". If a positive number is given it is used as
+ number of pixel from left/top. If a negative number is given it
+ is used as number of pixel from right/bottom.
+
+config SPL_SPLASH_SOURCE
+ bool "Control the source of the splash image at SPL"
+ help
+ Use the splash_source.c library. This library provides facilities to
+ declare board specific splash image locations, routines for loading
+ splash image from supported locations, and a way of controlling the
+ selected splash location using the "splashsource" environment
+ variable.
+
+ This CONFIG works as follows:
+
+ - If splashsource is set to a supported location name as defined by
+ board code, use that splash location.
+ - If splashsource is undefined, use the first splash location as
+ default.
+ - If splashsource is set to an unsupported value, do not load a splash
+ screen.
+
+ A splash source location can describe either storage with raw data, a
+ storage formatted with a file system or a FIT image. In case of a
+ filesystem, the splash screen data is loaded as a file. The name of
+ the splash screen file can be controlled with the environment variable
+ "splashfile".
+
+ To enable loading the splash image from a FIT image, CONFIG_FIT must
+ be enabled. The FIT image has to start at the 'offset' field address
+ in the selected splash location. The name of splash image within the
+ FIT shall be specified by the environment variable "splashfile".
+
+ In case the environment variable "splashfile" is not defined the
+ default name 'splash.bmp' will be used.
+
+endif # SPL_SPLASH_SCREEN
+
+config SPL_VIDEO_BMP_GZIP
+ bool "Gzip compressed BMP image support at SPL"
+ depends on SPL_SPLASH_SCREEN || SPL_BMP
+ help
+ If this option is set, additionally to standard BMP
+ images, gzipped BMP images can be displayed via the
+ splashscreen supportat SPL stage.
+
+config SPL_VIDEO_LOGO_MAX_SIZE
+ hex "Maximum size of the bitmap logo in bytes at SPL"
+ default 0x100000
+ help
+ Sets the maximum uncompressed size of the logo. This is needed when
+ decompressing a BMP file using the gzip algorithm, since it cannot
+ read the size from the bitmap header.
+
+config SPL_VIDEO_BMP_RLE8
+ bool "Run length encoded BMP image (RLE8) support at SPL"
+ help
+ If this option is set, the 8-bit RLE compressed BMP images
+ is supported.
+
+config SPL_BMP_16BPP
+ bool "16-bit-per-pixel BMP image support at SPL"
+ help
+ Support display of bitmaps file with 16-bit-per-pixel
+
+config SPL_BMP_24BPP
+ bool "24-bit-per-pixel BMP image support at SPL"
+ help
+ Support display of bitmaps file with 24-bit-per-pixel.
+
+config SPL_BMP_32BPP
+ bool "32-bit-per-pixel BMP image support at SPL"
+ help
+ Support display of bitmaps file with 32-bit-per-pixel.
+
+config SPL_VIDEO_BPP8
+ bool "Support 8-bit-per-pixel displays at SPL"
+ default y
+ help
+ Support drawing text and bitmaps onto a 8-bit-per-pixel display.
+ Enabling this will include code to support this display. Without
+ this option, such displays will not be supported and console output
+ will be empty.
+
+config SPL_VIDEO_BPP16
+ bool "Support 16-bit-per-pixel displays at SPL"
+ default y
+ help
+ Support drawing text and bitmaps onto a 16-bit-per-pixel display.
+ Enabling this will include code to support this display. Without
+ this option, such displays will not be supported and console output
+ will be empty.
+
+config SPL_VIDEO_BPP32
+ bool "Support 32-bit-per-pixel displays at SPL"
+ default y
+ help
+ Support drawing text and bitmaps onto a 32-bit-per-pixel display.
+ Enabling this will include code to support this display. Without
+ this option, such displays will not be supported and console output
+ will be empty.
+
+config SPL_HIDE_LOGO_VERSION
+ bool "Hide the version information on the splash screen at SPL"
+ help
+ Normally the U-Boot version string is shown on the display when the
+ splash screen is enabled. This information is not otherwise visible
+ since video starts up after U-Boot has displayed the initial banner.
+
+ Enable this option to hide this information.
+endif
+
endmenu
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 4d75771..9a53cd1 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -4,12 +4,12 @@
# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
ifdef CONFIG_DM
-obj-$(CONFIG_BACKLIGHT) += backlight-uclass.o
+obj-$(CONFIG_$(SPL_TPL_)BACKLIGHT) += backlight-uclass.o
obj-$(CONFIG_BACKLIGHT_GPIO) += backlight_gpio.o
obj-$(CONFIG_BACKLIGHT_PWM) += pwm_backlight.o
-obj-$(CONFIG_CONSOLE_NORMAL) += console_normal.o
+obj-$(CONFIG_$(SPL_TPL_)CONSOLE_NORMAL) += console_normal.o
obj-$(CONFIG_CONSOLE_ROTATION) += console_rotate.o
-ifdef CONFIG_CONSOLE_NORMAL
+ifdef CONFIG_$(SPL_TPL_)CONSOLE_NORMAL
obj-y += console_core.o
else ifdef CONFIG_CONSOLE_ROTATION
obj-y += console_core.o
@@ -18,21 +18,22 @@ obj-$(CONFIG_CONSOLE_ROTATION) += console_core.o
obj-$(CONFIG_CONSOLE_TRUETYPE) += console_truetype.o fonts/
obj-$(CONFIG_DISPLAY) += display-uclass.o
obj-$(CONFIG_VIDEO_MIPI_DSI) += dsi-host-uclass.o
-obj-$(CONFIG_VIDEO) += video-uclass.o vidconsole-uclass.o
-obj-$(CONFIG_VIDEO) += video_bmp.o
-obj-$(CONFIG_PANEL) += panel-uclass.o
+obj-$(CONFIG_$(SPL_TPL_)VIDEO) += video-uclass.o vidconsole-uclass.o
+obj-$(CONFIG_$(SPL_TPL_)VIDEO) += video_bmp.o
+obj-$(CONFIG_$(SPL_TPL_)PANEL) += panel-uclass.o
obj-$(CONFIG_PANEL_HX8238D) += hx8238d.o
-obj-$(CONFIG_SIMPLE_PANEL) += simple_panel.o
+obj-$(CONFIG_$(SPL_TPL_)SIMPLE_PANEL) += simple_panel.o
obj-$(CONFIG_VIDEO_LOGO) += u_boot_logo.o
endif
+obj-$(CONFIG_BACKLIGHT_LM3533) += lm3533_backlight.o
obj-${CONFIG_EXYNOS_FB} += exynos/
obj-${CONFIG_VIDEO_ROCKCHIP} += rockchip/
obj-${CONFIG_VIDEO_STM32} += stm32/
obj-${CONFIG_VIDEO_TEGRA124} += tegra124/
-obj-${CONFIG_VIDEO_TIDSS} += tidss/
+obj-${CONFIG_$(SPL_)VIDEO_TIDSS} += tidss/
obj-y += ti/
obj-$(CONFIG_ATMEL_HLCD) += atmel_hlcdfb.o
@@ -52,9 +53,12 @@ obj-$(CONFIG_VIDEO_EFI) += efi.o
obj-$(CONFIG_VIDEO_IPUV3) += imx/
obj-$(CONFIG_VIDEO_IVYBRIDGE_IGD) += ivybridge_igd.o
obj-$(CONFIG_VIDEO_LCD_ANX9804) += anx9804.o
+obj-$(CONFIG_VIDEO_LCD_ENDEAVORU) += endeavoru-panel.o
obj-$(CONFIG_VIDEO_LCD_HITACHI_TX18D42VM) += hitachi_tx18d42vm_lcd.o
obj-$(CONFIG_VIDEO_LCD_ORISETECH_OTM8009A) += orisetech_otm8009a.o
obj-$(CONFIG_VIDEO_LCD_RAYDIUM_RM68200) += raydium-rm68200.o
+obj-$(CONFIG_VIDEO_LCD_RENESAS_R61307) += renesas-r61307.o
+obj-$(CONFIG_VIDEO_LCD_RENESAS_R69328) += renesas-r69328.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
diff --git a/drivers/video/bridge/Kconfig b/drivers/video/bridge/Kconfig
index 765f738..2311ca2 100644
--- a/drivers/video/bridge/Kconfig
+++ b/drivers/video/bridge/Kconfig
@@ -33,3 +33,10 @@ config VIDEO_BRIDGE_ANALOGIX_ANX6345
help
The Analogix ANX6345 is RGB-to-DP converter. It enables an eDP LCD
panel to be connected to an parallel LCD interface.
+
+config VIDEO_BRIDGE_SOLOMON_SSD2825
+ bool "Solomon SSD2825 bridge driver"
+ depends on PANEL && DM_GPIO
+ select VIDEO_MIPI_DSI
+ help
+ Solomon SSD2824 SPI RGB-DSI bridge driver wrapped into panel uClass.
diff --git a/drivers/video/bridge/Makefile b/drivers/video/bridge/Makefile
index 45e54ac..22625c8 100644
--- a/drivers/video/bridge/Makefile
+++ b/drivers/video/bridge/Makefile
@@ -7,3 +7,4 @@ obj-$(CONFIG_VIDEO_BRIDGE) += video-bridge-uclass.o
obj-$(CONFIG_VIDEO_BRIDGE_PARADE_PS862X) += ps862x.o
obj-$(CONFIG_VIDEO_BRIDGE_NXP_PTN3460) += ptn3460.o
obj-$(CONFIG_VIDEO_BRIDGE_ANALOGIX_ANX6345) += anx6345.o
+obj-$(CONFIG_VIDEO_BRIDGE_SOLOMON_SSD2825) += ssd2825.o
diff --git a/drivers/video/bridge/ssd2825.c b/drivers/video/bridge/ssd2825.c
new file mode 100644
index 0000000..cea20dc
--- /dev/null
+++ b/drivers/video/bridge/ssd2825.c
@@ -0,0 +1,520 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2022 Svyatoslav Ryhel <clamor95@gmail.com>
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <log.h>
+#include <misc.h>
+#include <mipi_display.h>
+#include <mipi_dsi.h>
+#include <backlight.h>
+#include <panel.h>
+#include <spi.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <asm/gpio.h>
+
+#define SSD2825_DEVICE_ID_REG 0xB0
+#define SSD2825_RGB_INTERFACE_CTRL_REG_1 0xB1
+#define SSD2825_RGB_INTERFACE_CTRL_REG_2 0xB2
+#define SSD2825_RGB_INTERFACE_CTRL_REG_3 0xB3
+#define SSD2825_RGB_INTERFACE_CTRL_REG_4 0xB4
+#define SSD2825_RGB_INTERFACE_CTRL_REG_5 0xB5
+#define SSD2825_RGB_INTERFACE_CTRL_REG_6 0xB6
+#define SSD2825_NON_BURST BIT(2)
+#define SSD2825_BURST BIT(3)
+#define SSD2825_PCKL_HIGH BIT(13)
+#define SSD2825_HSYNC_HIGH BIT(14)
+#define SSD2825_VSYNC_HIGH BIT(15)
+#define SSD2825_CONFIGURATION_REG 0xB7
+#define SSD2825_CONF_REG_HS BIT(0)
+#define SSD2825_CONF_REG_CKE BIT(1)
+#define SSD2825_CONF_REG_SLP BIT(2)
+#define SSD2825_CONF_REG_VEN BIT(3)
+#define SSD2825_CONF_REG_HCLK BIT(4)
+#define SSD2825_CONF_REG_CSS BIT(5)
+#define SSD2825_CONF_REG_DCS BIT(6)
+#define SSD2825_CONF_REG_REN BIT(7)
+#define SSD2825_CONF_REG_ECD BIT(8)
+#define SSD2825_CONF_REG_EOT BIT(9)
+#define SSD2825_CONF_REG_LPE BIT(10)
+#define SSD2825_VC_CTRL_REG 0xB8
+#define SSD2825_PLL_CTRL_REG 0xB9
+#define SSD2825_PLL_CONFIGURATION_REG 0xBA
+#define SSD2825_CLOCK_CTRL_REG 0xBB
+#define SSD2825_PACKET_SIZE_CTRL_REG_1 0xBC
+#define SSD2825_PACKET_SIZE_CTRL_REG_2 0xBD
+#define SSD2825_PACKET_SIZE_CTRL_REG_3 0xBE
+#define SSD2825_PACKET_DROP_REG 0xBF
+#define SSD2825_OPERATION_CTRL_REG 0xC0
+#define SSD2825_MAX_RETURN_SIZE_REG 0xC1
+#define SSD2825_RETURN_DATA_COUNT_REG 0xC2
+#define SSD2825_ACK_RESPONSE_REG 0xC3
+#define SSD2825_LINE_CTRL_REG 0xC4
+#define SSD2825_INTERRUPT_CTRL_REG 0xC5
+#define SSD2825_INTERRUPT_STATUS_REG 0xC6
+#define SSD2825_ERROR_STATUS_REG 0xC7
+#define SSD2825_DATA_FORMAT_REG 0xC8
+#define SSD2825_DELAY_ADJ_REG_1 0xC9
+#define SSD2825_DELAY_ADJ_REG_2 0xCA
+#define SSD2825_DELAY_ADJ_REG_3 0xCB
+#define SSD2825_DELAY_ADJ_REG_4 0xCC
+#define SSD2825_DELAY_ADJ_REG_5 0xCD
+#define SSD2825_DELAY_ADJ_REG_6 0xCE
+#define SSD2825_HS_TX_TIMER_REG_1 0xCF
+#define SSD2825_HS_TX_TIMER_REG_2 0xD0
+#define SSD2825_LP_RX_TIMER_REG_1 0xD1
+#define SSD2825_LP_RX_TIMER_REG_2 0xD2
+#define SSD2825_TE_STATUS_REG 0xD3
+#define SSD2825_SPI_READ_REG 0xD4
+#define SSD2825_PLL_LOCK_REG 0xD5
+#define SSD2825_TEST_REG 0xD6
+#define SSD2825_TE_COUNT_REG 0xD7
+#define SSD2825_ANALOG_CTRL_REG_1 0xD8
+#define SSD2825_ANALOG_CTRL_REG_2 0xD9
+#define SSD2825_ANALOG_CTRL_REG_3 0xDA
+#define SSD2825_ANALOG_CTRL_REG_4 0xDB
+#define SSD2825_INTERRUPT_OUT_CTRL_REG 0xDC
+#define SSD2825_RGB_INTERFACE_CTRL_REG_7 0xDD
+#define SSD2825_LANE_CONFIGURATION_REG 0xDE
+#define SSD2825_DELAY_ADJ_REG_7 0xDF
+#define SSD2825_INPUT_PIN_CTRL_REG_1 0xE0
+#define SSD2825_INPUT_PIN_CTRL_REG_2 0xE1
+#define SSD2825_BIDIR_PIN_CTRL_REG_1 0xE2
+#define SSD2825_BIDIR_PIN_CTRL_REG_2 0xE3
+#define SSD2825_BIDIR_PIN_CTRL_REG_3 0xE4
+#define SSD2825_BIDIR_PIN_CTRL_REG_4 0xE5
+#define SSD2825_BIDIR_PIN_CTRL_REG_5 0xE6
+#define SSD2825_BIDIR_PIN_CTRL_REG_6 0xE7
+#define SSD2825_BIDIR_PIN_CTRL_REG_7 0xE8
+#define SSD2825_CABC_BRIGHTNESS_CTRL_REG_1 0xE9
+#define SSD2825_CABC_BRIGHTNESS_CTRL_REG_2 0xEA
+#define SSD2825_CABC_BRIGHTNESS_STATUS_REG 0xEB
+#define SSD2825_READ_REG 0xFF
+#define SSD2825_SPI_READ_REG_RESET 0xFA
+
+#define SSD2825_CMD_MASK 0x00
+#define SSD2825_DAT_MASK 0x01
+
+#define SSD2825_CMD_SEND BIT(0)
+#define SSD2825_DAT_SEND BIT(1)
+#define SSD2825_DSI_SEND BIT(2)
+
+#define SSD2828_LP_CLOCK_DIVIDER(n) (((n) - 1) & 0x3F)
+#define SSD2825_LP_MIN_CLK 5000 /* KHz */
+#define SSD2825_REF_MIN_CLK 2000 /* KHz */
+
+struct ssd2825_bridge_priv {
+ struct mipi_dsi_host host;
+ struct mipi_dsi_device device;
+
+ struct udevice *panel;
+ struct display_timing timing;
+
+ struct gpio_desc power_gpio;
+ struct gpio_desc reset_gpio;
+
+ struct clk *tx_clk;
+
+ u32 pll_freq_kbps; /* PLL in kbps */
+};
+
+static int ssd2825_spi_write(struct udevice *dev, int reg,
+ const void *buf, int flags)
+{
+ u8 command[2];
+
+ if (flags & SSD2825_CMD_SEND) {
+ command[0] = SSD2825_CMD_MASK;
+ command[1] = reg;
+ dm_spi_xfer(dev, 9, &command,
+ NULL, SPI_XFER_ONCE);
+ }
+
+ if (flags & SSD2825_DAT_SEND) {
+ u16 data = *(u16 *)buf;
+ u8 cmd1, cmd2;
+
+ /* send low byte first and then high byte */
+ cmd1 = (data & 0x00FF);
+ cmd2 = (data & 0xFF00) >> 8;
+
+ command[0] = SSD2825_DAT_MASK;
+ command[1] = cmd1;
+ dm_spi_xfer(dev, 9, &command,
+ NULL, SPI_XFER_ONCE);
+
+ command[0] = SSD2825_DAT_MASK;
+ command[1] = cmd2;
+ dm_spi_xfer(dev, 9, &command,
+ NULL, SPI_XFER_ONCE);
+ }
+
+ if (flags & SSD2825_DSI_SEND) {
+ u16 data = *(u16 *)buf;
+ data &= 0x00FF;
+
+ debug("%s: dsi command (0x%x)\n",
+ __func__, data);
+
+ command[0] = SSD2825_DAT_MASK;
+ command[1] = data;
+ dm_spi_xfer(dev, 9, &command,
+ NULL, SPI_XFER_ONCE);
+ }
+
+ return 0;
+}
+
+static int ssd2825_spi_read(struct udevice *dev, int reg,
+ void *data, int flags)
+{
+ u8 command[2];
+
+ command[0] = SSD2825_CMD_MASK;
+ command[1] = SSD2825_SPI_READ_REG;
+ dm_spi_xfer(dev, 9, &command,
+ NULL, SPI_XFER_ONCE);
+
+ command[0] = SSD2825_DAT_MASK;
+ command[1] = SSD2825_SPI_READ_REG_RESET;
+ dm_spi_xfer(dev, 9, &command,
+ NULL, SPI_XFER_ONCE);
+
+ command[0] = SSD2825_DAT_MASK;
+ command[1] = 0;
+ dm_spi_xfer(dev, 9, &command,
+ NULL, SPI_XFER_ONCE);
+
+ command[0] = SSD2825_CMD_MASK;
+ command[1] = reg;
+ dm_spi_xfer(dev, 9, &command,
+ NULL, SPI_XFER_ONCE);
+
+ command[0] = SSD2825_CMD_MASK;
+ command[1] = SSD2825_SPI_READ_REG_RESET;
+ dm_spi_xfer(dev, 9, &command,
+ NULL, SPI_XFER_ONCE);
+
+ dm_spi_xfer(dev, 16, NULL,
+ (u8 *)data, SPI_XFER_ONCE);
+
+ return 0;
+}
+
+static void ssd2825_write_register(struct udevice *dev, u8 reg,
+ u16 command)
+{
+ ssd2825_spi_write(dev, reg, &command,
+ SSD2825_CMD_SEND |
+ SSD2825_DAT_SEND);
+}
+
+static void ssd2825_write_dsi(struct udevice *dev, const u8 *command,
+ int len)
+{
+ int i;
+
+ ssd2825_spi_write(dev, SSD2825_PACKET_SIZE_CTRL_REG_1, &len,
+ SSD2825_CMD_SEND | SSD2825_DAT_SEND);
+
+ ssd2825_spi_write(dev, SSD2825_PACKET_DROP_REG, NULL,
+ SSD2825_CMD_SEND);
+
+ for (i = 0; i < len; i++)
+ ssd2825_spi_write(dev, 0, &command[i], SSD2825_DSI_SEND);
+}
+
+static ssize_t ssd2825_bridge_transfer(struct mipi_dsi_host *host,
+ const struct mipi_dsi_msg *msg)
+{
+ struct udevice *dev = (struct udevice *)host->dev;
+ u8 buf = *(u8 *)msg->tx_buf;
+ u16 config;
+ int ret;
+
+ ret = ssd2825_spi_read(dev, SSD2825_CONFIGURATION_REG,
+ &config, 0);
+ if (ret)
+ return ret;
+
+ switch (msg->type) {
+ case MIPI_DSI_DCS_SHORT_WRITE:
+ case MIPI_DSI_DCS_SHORT_WRITE_PARAM:
+ case MIPI_DSI_DCS_LONG_WRITE:
+ config |= SSD2825_CONF_REG_DCS;
+ break;
+ case MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM:
+ case MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM:
+ case MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM:
+ case MIPI_DSI_GENERIC_LONG_WRITE:
+ config &= ~SSD2825_CONF_REG_DCS;
+ break;
+ default:
+ return 0;
+ }
+
+ ssd2825_write_register(dev, SSD2825_CONFIGURATION_REG, config);
+ ssd2825_write_register(dev, SSD2825_VC_CTRL_REG, 0x0000);
+ ssd2825_write_dsi(dev, msg->tx_buf, msg->tx_len);
+
+ if (buf == MIPI_DCS_SET_DISPLAY_ON) {
+ ssd2825_write_register(dev, SSD2825_CONFIGURATION_REG,
+ SSD2825_CONF_REG_HS | SSD2825_CONF_REG_VEN |
+ SSD2825_CONF_REG_DCS | SSD2825_CONF_REG_ECD |
+ SSD2825_CONF_REG_EOT);
+ ssd2825_write_register(dev, SSD2825_PLL_CTRL_REG, 0x0001);
+ ssd2825_write_register(dev, SSD2825_VC_CTRL_REG, 0x0000);
+ }
+
+ return 0;
+}
+
+static const struct mipi_dsi_host_ops ssd2825_bridge_host_ops = {
+ .transfer = ssd2825_bridge_transfer,
+};
+
+/*
+ * PLL configuration register settings.
+ *
+ * See the "PLL Configuration Register Description" in the SSD2825 datasheet.
+ */
+static u16 construct_pll_config(struct ssd2825_bridge_priv *priv,
+ u32 desired_pll_freq_kbps, u32 reference_freq_khz)
+{
+ u32 div_factor = 1, mul_factor, fr = 0;
+
+ while (reference_freq_khz / (div_factor + 1) >= SSD2825_REF_MIN_CLK)
+ div_factor++;
+ if (div_factor > 31)
+ div_factor = 31;
+
+ mul_factor = DIV_ROUND_UP(desired_pll_freq_kbps * div_factor,
+ reference_freq_khz);
+
+ priv->pll_freq_kbps = reference_freq_khz * mul_factor / div_factor;
+
+ if (priv->pll_freq_kbps >= 501000)
+ fr = 3;
+ else if (priv->pll_freq_kbps >= 251000)
+ fr = 2;
+ else if (priv->pll_freq_kbps >= 126000)
+ fr = 1;
+
+ return (fr << 14) | (div_factor << 8) | mul_factor;
+}
+
+static void ssd2825_setup_pll(struct udevice *dev)
+{
+ struct ssd2825_bridge_priv *priv = dev_get_priv(dev);
+ struct mipi_dsi_device *device = &priv->device;
+ struct display_timing *dt = &priv->timing;
+ u16 pll_config, lp_div;
+ u32 pclk_mult, tx_freq_khz, pd_lines;
+
+ tx_freq_khz = clk_get_rate(priv->tx_clk) / 1000;
+ pd_lines = mipi_dsi_pixel_format_to_bpp(device->format);
+ pclk_mult = pd_lines / device->lanes + 1;
+
+ pll_config = construct_pll_config(priv, pclk_mult *
+ dt->pixelclock.typ / 1000,
+ tx_freq_khz);
+
+ lp_div = priv->pll_freq_kbps / (SSD2825_LP_MIN_CLK * 8);
+
+ /* Disable PLL */
+ ssd2825_write_register(dev, SSD2825_PLL_CTRL_REG, 0x0000);
+ ssd2825_write_register(dev, SSD2825_LINE_CTRL_REG, 0x0001);
+
+ /* Set delays */
+ ssd2825_write_register(dev, SSD2825_DELAY_ADJ_REG_1, 0x2103);
+
+ /* Set PLL coeficients */
+ ssd2825_write_register(dev, SSD2825_PLL_CONFIGURATION_REG, pll_config);
+
+ /* Clock Control Register */
+ ssd2825_write_register(dev, SSD2825_CLOCK_CTRL_REG,
+ SSD2828_LP_CLOCK_DIVIDER(lp_div));
+
+ /* Enable PLL */
+ ssd2825_write_register(dev, SSD2825_PLL_CTRL_REG, 0x0001);
+ ssd2825_write_register(dev, SSD2825_VC_CTRL_REG, 0x0000);
+}
+
+static int ssd2825_bridge_enable_panel(struct udevice *dev)
+{
+ struct ssd2825_bridge_priv *priv = dev_get_priv(dev);
+ struct mipi_dsi_device *device = &priv->device;
+ struct display_timing *dt = &priv->timing;
+ int ret;
+
+ ret = clk_prepare_enable(priv->tx_clk);
+ if (ret) {
+ log_err("error enabling tx_clk (%d)\n", ret);
+ return ret;
+ }
+
+ ret = dm_gpio_set_value(&priv->power_gpio, 1);
+ if (ret) {
+ log_err("error changing power-gpios (%d)\n", ret);
+ return ret;
+ }
+ mdelay(10);
+
+ ret = dm_gpio_set_value(&priv->reset_gpio, 0);
+ if (ret) {
+ log_err("error changing reset-gpios (%d)\n", ret);
+ return ret;
+ }
+ mdelay(10);
+
+ ret = dm_gpio_set_value(&priv->reset_gpio, 1);
+ if (ret) {
+ log_err("error changing reset-gpios (%d)\n", ret);
+ return ret;
+ }
+ mdelay(10);
+
+ /* Perform panel HW setup */
+ ret = panel_enable_backlight(priv->panel);
+ if (ret)
+ return ret;
+
+ /* Perform SW reset */
+ ssd2825_write_register(dev, SSD2825_OPERATION_CTRL_REG, 0x0100);
+
+ /* Set panel timings */
+ ssd2825_write_register(dev, SSD2825_RGB_INTERFACE_CTRL_REG_1,
+ dt->vsync_len.typ << 8 | dt->hsync_len.typ);
+ ssd2825_write_register(dev, SSD2825_RGB_INTERFACE_CTRL_REG_2,
+ (dt->vsync_len.typ + dt->vback_porch.typ) << 8 |
+ (dt->hsync_len.typ + dt->hback_porch.typ));
+ ssd2825_write_register(dev, SSD2825_RGB_INTERFACE_CTRL_REG_3,
+ dt->vfront_porch.typ << 8 | dt->hfront_porch.typ);
+ ssd2825_write_register(dev, SSD2825_RGB_INTERFACE_CTRL_REG_4,
+ dt->hactive.typ);
+ ssd2825_write_register(dev, SSD2825_RGB_INTERFACE_CTRL_REG_5,
+ dt->vactive.typ);
+ ssd2825_write_register(dev, SSD2825_RGB_INTERFACE_CTRL_REG_6,
+ SSD2825_HSYNC_HIGH | SSD2825_VSYNC_HIGH |
+ SSD2825_PCKL_HIGH | SSD2825_NON_BURST |
+ (3 - device->format));
+ ssd2825_write_register(dev, SSD2825_LANE_CONFIGURATION_REG,
+ device->lanes - 1);
+ ssd2825_write_register(dev, SSD2825_TEST_REG, 0x0004);
+
+ /* Call PLL configuration */
+ ssd2825_setup_pll(dev);
+
+ mdelay(10);
+
+ /* Initial DSI configuration register set */
+ ssd2825_write_register(dev, SSD2825_CONFIGURATION_REG,
+ SSD2825_CONF_REG_CKE | SSD2825_CONF_REG_DCS |
+ SSD2825_CONF_REG_ECD | SSD2825_CONF_REG_EOT);
+ ssd2825_write_register(dev, SSD2825_VC_CTRL_REG, 0x0000);
+
+ /* Set up SW panel configuration */
+ ret = panel_set_backlight(priv->panel, BACKLIGHT_DEFAULT);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int ssd2825_bridge_set_panel(struct udevice *dev, int percent)
+{
+ return 0;
+}
+
+static int ssd2825_bridge_panel_timings(struct udevice *dev,
+ struct display_timing *timing)
+{
+ struct ssd2825_bridge_priv *priv = dev_get_priv(dev);
+
+ memcpy(timing, &priv->timing, sizeof(*timing));
+
+ return 0;
+}
+
+static int ssd2825_bridge_probe(struct udevice *dev)
+{
+ struct ssd2825_bridge_priv *priv = dev_get_priv(dev);
+ struct spi_slave *slave = dev_get_parent_priv(dev);
+ struct mipi_dsi_device *device = &priv->device;
+ struct mipi_dsi_panel_plat *mipi_plat;
+ int ret;
+
+ ret = spi_claim_bus(slave);
+ if (ret) {
+ log_err("SPI bus allocation failed (%d)\n", ret);
+ return ret;
+ }
+
+ ret = uclass_get_device_by_phandle(UCLASS_PANEL, dev,
+ "panel", &priv->panel);
+ if (ret) {
+ log_err("cannot get panel: ret=%d\n", ret);
+ return ret;
+ }
+
+ panel_get_display_timing(priv->panel, &priv->timing);
+
+ mipi_plat = dev_get_plat(priv->panel);
+ mipi_plat->device = device;
+
+ priv->host.dev = (struct device *)dev;
+ priv->host.ops = &ssd2825_bridge_host_ops;
+
+ device->host = &priv->host;
+ device->lanes = mipi_plat->lanes;
+ device->format = mipi_plat->format;
+ device->mode_flags = mipi_plat->mode_flags;
+
+ /* get panel gpios */
+ ret = gpio_request_by_name(dev, "power-gpios", 0,
+ &priv->power_gpio, GPIOD_IS_OUT);
+ if (ret) {
+ log_err("could not decode power-gpios (%d)\n", ret);
+ return ret;
+ }
+
+ ret = gpio_request_by_name(dev, "reset-gpios", 0,
+ &priv->reset_gpio, GPIOD_IS_OUT);
+ if (ret) {
+ log_err("could not decode reset-gpios (%d)\n", ret);
+ return ret;
+ }
+
+ /* get clk */
+ priv->tx_clk = devm_clk_get(dev, "tx_clk");
+ if (IS_ERR(priv->tx_clk)) {
+ log_err("cannot get tx_clk: %ld\n", PTR_ERR(priv->tx_clk));
+ return PTR_ERR(priv->tx_clk);
+ }
+
+ return 0;
+}
+
+static const struct panel_ops ssd2825_bridge_ops = {
+ .enable_backlight = ssd2825_bridge_enable_panel,
+ .set_backlight = ssd2825_bridge_set_panel,
+ .get_display_timing = ssd2825_bridge_panel_timings,
+};
+
+static const struct udevice_id ssd2825_bridge_ids[] = {
+ { .compatible = "solomon,ssd2825" },
+ { }
+};
+
+U_BOOT_DRIVER(ssd2825) = {
+ .name = "ssd2825",
+ .id = UCLASS_PANEL,
+ .of_match = ssd2825_bridge_ids,
+ .ops = &ssd2825_bridge_ops,
+ .probe = ssd2825_bridge_probe,
+ .priv_auto = sizeof(struct ssd2825_bridge_priv),
+};
diff --git a/drivers/video/console_core.c b/drivers/video/console_core.c
index d4f79c6..1f93b1b 100644
--- a/drivers/video/console_core.c
+++ b/drivers/video/console_core.c
@@ -46,11 +46,11 @@ static int console_set_font(struct udevice *dev, struct video_fontdata *fontdata
int check_bpix_support(int bpix)
{
- if (bpix == VIDEO_BPP8 && IS_ENABLED(CONFIG_VIDEO_BPP8))
+ if (bpix == VIDEO_BPP8 && CONFIG_IS_ENABLED(VIDEO_BPP8))
return 0;
- else if (bpix == VIDEO_BPP16 && IS_ENABLED(CONFIG_VIDEO_BPP16))
+ else if (bpix == VIDEO_BPP16 && CONFIG_IS_ENABLED(VIDEO_BPP16))
return 0;
- else if (bpix == VIDEO_BPP32 && IS_ENABLED(CONFIG_VIDEO_BPP32))
+ else if (bpix == VIDEO_BPP32 && CONFIG_IS_ENABLED(VIDEO_BPP32))
return 0;
else
return -ENOSYS;
diff --git a/drivers/video/endeavoru-panel.c b/drivers/video/endeavoru-panel.c
new file mode 100644
index 0000000..79a2721
--- /dev/null
+++ b/drivers/video/endeavoru-panel.c
@@ -0,0 +1,252 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2022 Svyatoslav Ryhel <clamor95@gmail.com>
+ */
+
+#include <common.h>
+#include <backlight.h>
+#include <dm.h>
+#include <panel.h>
+#include <log.h>
+#include <misc.h>
+#include <mipi_display.h>
+#include <mipi_dsi.h>
+#include <asm/gpio.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <power/regulator.h>
+
+struct endeavoru_panel_priv {
+ struct udevice *vdd;
+ struct udevice *vddio;
+
+ struct udevice *backlight;
+
+ struct gpio_desc reset_gpio;
+};
+
+static struct display_timing default_timing = {
+ .pixelclock.typ = 63200000,
+ .hactive.typ = 720,
+ .hfront_porch.typ = 55,
+ .hback_porch.typ = 29,
+ .hsync_len.typ = 16,
+ .vactive.typ = 1280,
+ .vfront_porch.typ = 2,
+ .vback_porch.typ = 1,
+ .vsync_len.typ = 1,
+};
+
+static void dcs_write_one(struct mipi_dsi_device *dsi, u8 cmd, u8 data)
+{
+ mipi_dsi_dcs_write(dsi, cmd, &data, 1);
+}
+
+/*
+ * This panel is not able to auto-increment all cmd addresses so for some of
+ * them, we need to send them one by one...
+ */
+#define dcs_write_seq(dsi, cmd, seq...) \
+({ \
+ static const u8 d[] = { seq }; \
+ unsigned int i; \
+ \
+ for (i = 0; i < ARRAY_SIZE(d) ; i++) \
+ dcs_write_one(dsi, cmd + i, d[i]); \
+})
+
+static int endeavoru_panel_enable_backlight(struct udevice *dev)
+{
+ struct endeavoru_panel_priv *priv = dev_get_priv(dev);
+ int ret;
+
+ ret = dm_gpio_set_value(&priv->reset_gpio, 1);
+ if (ret) {
+ log_err("error changing reset-gpios (%d)\n", ret);
+ return ret;
+ }
+ mdelay(5);
+
+ ret = regulator_set_enable_if_allowed(priv->vddio, 1);
+ if (ret) {
+ log_err("error enabling iovcc-supply (%d)\n", ret);
+ return ret;
+ }
+ mdelay(1);
+
+ ret = regulator_set_enable_if_allowed(priv->vdd, 1);
+ if (ret) {
+ log_err("error enabling vcc-supply (%d)\n", ret);
+ return ret;
+ }
+ mdelay(20);
+
+ ret = dm_gpio_set_value(&priv->reset_gpio, 0);
+ if (ret) {
+ log_err("error changing reset-gpios (%d)\n", ret);
+ return ret;
+ }
+ mdelay(2);
+
+ /* Reset panel */
+ ret = dm_gpio_set_value(&priv->reset_gpio, 1);
+ if (ret) {
+ log_err("error changing reset-gpios (%d)\n", ret);
+ return ret;
+ }
+ mdelay(1);
+
+ ret = dm_gpio_set_value(&priv->reset_gpio, 0);
+ if (ret) {
+ log_err("error changing reset-gpios (%d)\n", ret);
+ return ret;
+ }
+ mdelay(25);
+
+ return 0;
+}
+
+static int endeavoru_panel_set_backlight(struct udevice *dev, int percent)
+{
+ struct endeavoru_panel_priv *priv = dev_get_priv(dev);
+ struct mipi_dsi_panel_plat *plat = dev_get_plat(dev);
+ struct mipi_dsi_device *dsi = plat->device;
+ int ret;
+
+ dcs_write_one(dsi, 0xc2, 0x08);
+
+ /* color enhancement 2.2 */
+ dcs_write_one(dsi, 0xff, 0x03);
+ dcs_write_one(dsi, 0xfe, 0x08);
+ dcs_write_one(dsi, 0x18, 0x00);
+ dcs_write_one(dsi, 0x19, 0x00);
+ dcs_write_one(dsi, 0x1a, 0x00);
+ dcs_write_one(dsi, 0x25, 0x26);
+
+ dcs_write_seq(dsi, 0x00, 0x00, 0x05, 0x10, 0x17,
+ 0x22, 0x26, 0x29, 0x29, 0x26, 0x23,
+ 0x17, 0x12, 0x06, 0x02, 0x01, 0x00);
+
+ dcs_write_one(dsi, 0xfb, 0x01);
+ dcs_write_one(dsi, 0xff, 0x00);
+ dcs_write_one(dsi, 0xfe, 0x01);
+
+ mipi_dsi_dcs_exit_sleep_mode(dsi);
+
+ mdelay(105);
+
+ dcs_write_one(dsi, 0x35, 0x00);
+
+ /* PWM frequency adjust */
+ dcs_write_one(dsi, 0xff, 0x04);
+ dcs_write_one(dsi, 0x0a, 0x07);
+ dcs_write_one(dsi, 0x09, 0x20);
+ dcs_write_one(dsi, 0xff, 0x00);
+
+ dcs_write_one(dsi, 0xff, 0xee);
+ dcs_write_one(dsi, 0x12, 0x50);
+ dcs_write_one(dsi, 0x13, 0x02);
+ dcs_write_one(dsi, 0x6a, 0x60);
+ dcs_write_one(dsi, 0xfb, 0x01);
+ dcs_write_one(dsi, 0xff, 0x00);
+
+ mipi_dsi_dcs_set_display_on(dsi);
+
+ mdelay(42);
+
+ dcs_write_one(dsi, 0xba, 0x01);
+
+ dcs_write_one(dsi, 0x53, 0x24);
+ dcs_write_one(dsi, 0x55, 0x80);
+ dcs_write_one(dsi, 0x5e, 0x06);
+
+ ret = backlight_enable(priv->backlight);
+ if (ret)
+ return ret;
+
+ /* Set backlight */
+ dcs_write_one(dsi, 0x51, 0x96);
+
+ ret = backlight_set_brightness(priv->backlight, percent);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int endeavoru_panel_timings(struct udevice *dev,
+ struct display_timing *timing)
+{
+ memcpy(timing, &default_timing, sizeof(*timing));
+ return 0;
+}
+
+static int endeavoru_panel_of_to_plat(struct udevice *dev)
+{
+ struct endeavoru_panel_priv *priv = dev_get_priv(dev);
+ int ret;
+
+ ret = uclass_get_device_by_phandle(UCLASS_PANEL_BACKLIGHT, dev,
+ "backlight", &priv->backlight);
+ if (ret) {
+ log_err("cannot get backlight: ret = %d\n", ret);
+ return ret;
+ }
+
+ ret = uclass_get_device_by_phandle(UCLASS_REGULATOR, dev,
+ "vdd-supply", &priv->vdd);
+ if (ret) {
+ log_err("cannot get vdd-supply: ret = %d\n", ret);
+ return ret;
+ }
+
+ ret = uclass_get_device_by_phandle(UCLASS_REGULATOR, dev,
+ "vddio-supply", &priv->vddio);
+ if (ret) {
+ log_err("cannot get vddio-supply: ret = %d\n", ret);
+ return ret;
+ }
+
+ ret = gpio_request_by_name(dev, "reset-gpios", 0,
+ &priv->reset_gpio, GPIOD_IS_OUT);
+ if (ret) {
+ log_err("could not decode reser-gpios (%d)\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int endeavoru_panel_probe(struct udevice *dev)
+{
+ struct mipi_dsi_panel_plat *plat = dev_get_plat(dev);
+
+ /* fill characteristics of DSI data link */
+ plat->lanes = 2;
+ plat->format = MIPI_DSI_FMT_RGB888;
+ plat->mode_flags = MIPI_DSI_MODE_VIDEO;
+
+ return 0;
+}
+
+static const struct panel_ops endeavoru_panel_ops = {
+ .enable_backlight = endeavoru_panel_enable_backlight,
+ .set_backlight = endeavoru_panel_set_backlight,
+ .get_display_timing = endeavoru_panel_timings,
+};
+
+static const struct udevice_id endeavoru_panel_ids[] = {
+ { .compatible = "htc,edge-panel" },
+ { }
+};
+
+U_BOOT_DRIVER(endeavoru_panel) = {
+ .name = "endeavoru_panel",
+ .id = UCLASS_PANEL,
+ .of_match = endeavoru_panel_ids,
+ .ops = &endeavoru_panel_ops,
+ .of_to_plat = endeavoru_panel_of_to_plat,
+ .probe = endeavoru_panel_probe,
+ .plat_auto = sizeof(struct mipi_dsi_panel_plat),
+ .priv_auto = sizeof(struct endeavoru_panel_priv),
+};
diff --git a/drivers/video/lm3533_backlight.c b/drivers/video/lm3533_backlight.c
new file mode 100644
index 0000000..00297a0
--- /dev/null
+++ b/drivers/video/lm3533_backlight.c
@@ -0,0 +1,134 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2022 Svyatoslav Ryhel <clamor95@gmail.com>
+ */
+
+#define LOG_CATEGORY UCLASS_PANEL_BACKLIGHT
+
+#include <backlight.h>
+#include <common.h>
+#include <dm.h>
+#include <i2c.h>
+#include <log.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <asm/gpio.h>
+
+#define LM3533_BL_MIN_BRIGHTNESS 0x02
+#define LM3533_BL_MAX_BRIGHTNESS 0xFF
+
+#define LM3533_SINK_OUTPUT_CONFIG_1 0x10
+#define LM3533_CONTROL_BANK_A_PWM 0x14
+#define LM3533_CONTROL_BANK_AB_BRIGHTNESS 0x1A
+#define LM3533_CONTROL_BANK_A_FULLSCALE_CURRENT 0x1F
+#define LM3533_CONTROL_BANK_ENABLE 0x27
+#define LM3533_OVP_FREQUENCY_PWM_POLARITY 0x2C
+#define LM3533_BRIGHTNESS_REGISTER_A 0x40
+
+struct lm3533_backlight_priv {
+ struct gpio_desc enable_gpio;
+ u32 def_bl_lvl;
+};
+
+static int lm3533_backlight_enable(struct udevice *dev)
+{
+ struct lm3533_backlight_priv *priv = dev_get_priv(dev);
+ int ret;
+
+ dm_gpio_set_value(&priv->enable_gpio, 1);
+ mdelay(5);
+
+ /* HVLED 1 & 2 are controlled by Bank A */
+ ret = dm_i2c_reg_write(dev, LM3533_SINK_OUTPUT_CONFIG_1, 0x00);
+ if (ret)
+ return ret;
+
+ /* PWM input is disabled for CABC */
+ ret = dm_i2c_reg_write(dev, LM3533_CONTROL_BANK_A_PWM, 0x00);
+ if (ret)
+ return ret;
+
+ /* Linear & Control Bank A is configured for register Current control */
+ ret = dm_i2c_reg_write(dev, LM3533_CONTROL_BANK_AB_BRIGHTNESS, 0x02);
+ if (ret)
+ return ret;
+
+ /* Full-Scale Current (20.2mA) */
+ ret = dm_i2c_reg_write(dev, LM3533_CONTROL_BANK_A_FULLSCALE_CURRENT, 0x13);
+ if (ret)
+ return ret;
+
+ /* Control Bank A is enable */
+ ret = dm_i2c_reg_write(dev, LM3533_CONTROL_BANK_ENABLE, 0x01);
+ if (ret)
+ return ret;
+
+ ret = dm_i2c_reg_write(dev, LM3533_OVP_FREQUENCY_PWM_POLARITY, 0x0A);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int lm3533_backlight_set_brightness(struct udevice *dev, int percent)
+{
+ struct lm3533_backlight_priv *priv = dev_get_priv(dev);
+ int ret;
+
+ if (percent == BACKLIGHT_DEFAULT)
+ percent = priv->def_bl_lvl;
+
+ if (percent < LM3533_BL_MIN_BRIGHTNESS)
+ percent = LM3533_BL_MIN_BRIGHTNESS;
+
+ if (percent > LM3533_BL_MAX_BRIGHTNESS)
+ percent = LM3533_BL_MAX_BRIGHTNESS;
+
+ /* Set brightness level */
+ ret = dm_i2c_reg_write(dev, LM3533_BRIGHTNESS_REGISTER_A,
+ percent);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int lm3533_backlight_probe(struct udevice *dev)
+{
+ struct lm3533_backlight_priv *priv = dev_get_priv(dev);
+ int ret;
+
+ if (device_get_uclass_id(dev->parent) != UCLASS_I2C)
+ return -EPROTONOSUPPORT;
+
+ ret = gpio_request_by_name(dev, "enable-gpios", 0,
+ &priv->enable_gpio, GPIOD_IS_OUT);
+ if (ret) {
+ log_err("Could not decode enable-gpios (%d)\n", ret);
+ return ret;
+ }
+
+ priv->def_bl_lvl = dev_read_u32_default(dev, "default-brightness-level",
+ LM3533_BL_MAX_BRIGHTNESS);
+
+ return 0;
+}
+
+static const struct backlight_ops lm3533_backlight_ops = {
+ .enable = lm3533_backlight_enable,
+ .set_brightness = lm3533_backlight_set_brightness,
+};
+
+static const struct udevice_id lm3533_backlight_ids[] = {
+ { .compatible = "ti,lm3533" },
+ { }
+};
+
+U_BOOT_DRIVER(lm3533_backlight) = {
+ .name = "lm3533_backlight",
+ .id = UCLASS_PANEL_BACKLIGHT,
+ .of_match = lm3533_backlight_ids,
+ .probe = lm3533_backlight_probe,
+ .ops = &lm3533_backlight_ops,
+ .priv_auto = sizeof(struct lm3533_backlight_priv),
+};
diff --git a/drivers/video/renesas-r61307.c b/drivers/video/renesas-r61307.c
new file mode 100644
index 0000000..426fdc6
--- /dev/null
+++ b/drivers/video/renesas-r61307.c
@@ -0,0 +1,302 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Renesas R61307 panel driver
+ *
+ * Copyright (c) 2022 Svyatoslav Ryhel <clamor95@gmail.com>
+ */
+
+#include <common.h>
+#include <backlight.h>
+#include <dm.h>
+#include <panel.h>
+#include <log.h>
+#include <misc.h>
+#include <mipi_display.h>
+#include <mipi_dsi.h>
+#include <asm/gpio.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <power/regulator.h>
+
+/*
+ * The datasheet is not publicly available, all values are
+ * taken from the downstream. If you have access to datasheets,
+ * corrections are welcome.
+ */
+
+#define R61307_MACP 0xB0 /* Manufacturer CMD Protect */
+
+#define R61307_INVERSION 0xC1
+#define R61307_GAMMA_SET_A 0xC8 /* Gamma Setting A */
+#define R61307_GAMMA_SET_B 0xC9 /* Gamma Setting B */
+#define R61307_GAMMA_SET_C 0xCA /* Gamma Setting C */
+#define R61307_CONTRAST_SET 0xCC
+
+struct renesas_r61307_priv {
+ struct udevice *vcc;
+ struct udevice *iovcc;
+
+ struct udevice *backlight;
+
+ struct gpio_desc reset_gpio;
+
+ bool dig_cont_adj;
+ bool inversion;
+ u32 gamma;
+};
+
+static const u8 macp_on[] = {
+ R61307_MACP, 0x03
+};
+
+static const u8 macp_off[] = {
+ R61307_MACP, 0x04
+};
+
+static const u8 address_mode[] = {
+ MIPI_DCS_SET_ADDRESS_MODE
+};
+
+static const u8 contrast_setting[] = {
+ R61307_CONTRAST_SET,
+ 0xdc, 0xb4, 0xff
+};
+
+static const u8 column_inversion[] = {
+ R61307_INVERSION,
+ 0x00, 0x50, 0x03, 0x22,
+ 0x16, 0x06, 0x60, 0x11
+};
+
+static const u8 line_inversion[] = {
+ R61307_INVERSION,
+ 0x00, 0x10, 0x03, 0x22,
+ 0x16, 0x06, 0x60, 0x01
+};
+
+static const u8 gamma_setting[][25] = {
+ {},
+ {
+ R61307_GAMMA_SET_A,
+ 0x00, 0x06, 0x0a, 0x0f,
+ 0x14, 0x1f, 0x1f, 0x17,
+ 0x12, 0x0c, 0x09, 0x06,
+ 0x00, 0x06, 0x0a, 0x0f,
+ 0x14, 0x1f, 0x1f, 0x17,
+ 0x12, 0x0c, 0x09, 0x06
+ },
+ {
+ R61307_GAMMA_SET_A,
+ 0x00, 0x05, 0x0b, 0x0f,
+ 0x11, 0x1d, 0x20, 0x18,
+ 0x18, 0x09, 0x07, 0x06,
+ 0x00, 0x05, 0x0b, 0x0f,
+ 0x11, 0x1d, 0x20, 0x18,
+ 0x18, 0x09, 0x07, 0x06
+ },
+ {
+ R61307_GAMMA_SET_A,
+ 0x0b, 0x0d, 0x10, 0x14,
+ 0x13, 0x1d, 0x20, 0x18,
+ 0x12, 0x09, 0x07, 0x06,
+ 0x0a, 0x0c, 0x10, 0x14,
+ 0x13, 0x1d, 0x20, 0x18,
+ 0x12, 0x09, 0x07, 0x06
+ },
+};
+
+static struct display_timing default_timing = {
+ .pixelclock.typ = 62000000,
+ .hactive.typ = 768,
+ .hfront_porch.typ = 116,
+ .hback_porch.typ = 81,
+ .hsync_len.typ = 5,
+ .vactive.typ = 1024,
+ .vfront_porch.typ = 24,
+ .vback_porch.typ = 8,
+ .vsync_len.typ = 2,
+};
+
+static int renesas_r61307_enable_backlight(struct udevice *dev)
+{
+ struct renesas_r61307_priv *priv = dev_get_priv(dev);
+ int ret;
+
+ ret = regulator_set_enable_if_allowed(priv->vcc, 1);
+ if (ret) {
+ log_err("enabling vcc-supply failed (%d)\n", ret);
+ return ret;
+ }
+ mdelay(5);
+
+ ret = regulator_set_enable_if_allowed(priv->iovcc, 1);
+ if (ret) {
+ log_err("enabling iovcc-supply failed (%d)\n", ret);
+ return ret;
+ }
+
+ ret = dm_gpio_set_value(&priv->reset_gpio, 0);
+ if (ret) {
+ log_err("changing reset-gpio failed (%d)\n", ret);
+ return ret;
+ }
+ mdelay(5);
+
+ ret = dm_gpio_set_value(&priv->reset_gpio, 1);
+ if (ret) {
+ log_err("changing reset-gpio failed (%d)\n", ret);
+ return ret;
+ }
+
+ mdelay(5);
+
+ return 0;
+}
+
+static int renesas_r61307_set_backlight(struct udevice *dev, int percent)
+{
+ struct renesas_r61307_priv *priv = dev_get_priv(dev);
+ struct mipi_dsi_panel_plat *plat = dev_get_plat(dev);
+ struct mipi_dsi_device *dsi = plat->device;
+ int ret;
+
+ ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
+ if (ret < 0) {
+ log_err("failed to exit sleep mode: %d\n", ret);
+ return ret;
+ }
+
+ mdelay(80);
+
+ mipi_dsi_dcs_write_buffer(dsi, address_mode,
+ sizeof(address_mode));
+
+ mdelay(20);
+
+ ret = mipi_dsi_dcs_set_pixel_format(dsi, MIPI_DCS_PIXEL_FMT_24BIT << 4);
+ if (ret < 0) {
+ log_err("failed to set pixel format: %d\n", ret);
+ return ret;
+ }
+
+ /* MACP Off */
+ mipi_dsi_generic_write(dsi, macp_off, sizeof(macp_off));
+
+ if (priv->dig_cont_adj)
+ mipi_dsi_generic_write(dsi, contrast_setting,
+ sizeof(contrast_setting));
+
+ if (priv->gamma)
+ mipi_dsi_generic_write(dsi, gamma_setting[priv->gamma],
+ sizeof(gamma_setting[priv->gamma]));
+
+ if (priv->inversion)
+ mipi_dsi_generic_write(dsi, column_inversion,
+ sizeof(column_inversion));
+ else
+ mipi_dsi_generic_write(dsi, line_inversion,
+ sizeof(line_inversion));
+
+ /* MACP On */
+ mipi_dsi_generic_write(dsi, macp_on, sizeof(macp_on));
+
+ ret = mipi_dsi_dcs_set_display_on(dsi);
+ if (ret < 0) {
+ log_err("failed to set display on: %d\n", ret);
+ return ret;
+ }
+
+ mdelay(50);
+
+ ret = backlight_enable(priv->backlight);
+ if (ret)
+ return ret;
+
+ ret = backlight_set_brightness(priv->backlight, percent);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int renesas_r61307_timings(struct udevice *dev,
+ struct display_timing *timing)
+{
+ memcpy(timing, &default_timing, sizeof(*timing));
+ return 0;
+}
+
+static int renesas_r61307_of_to_plat(struct udevice *dev)
+{
+ struct renesas_r61307_priv *priv = dev_get_priv(dev);
+ int ret;
+
+ ret = uclass_get_device_by_phandle(UCLASS_PANEL_BACKLIGHT, dev,
+ "backlight", &priv->backlight);
+ if (ret) {
+ log_err("Cannot get backlight: ret = %d\n", ret);
+ return ret;
+ }
+
+ ret = uclass_get_device_by_phandle(UCLASS_REGULATOR, dev,
+ "vcc-supply", &priv->vcc);
+ if (ret) {
+ log_err("Cannot get vcc-supply: ret = %d\n", ret);
+ return ret;
+ }
+
+ ret = uclass_get_device_by_phandle(UCLASS_REGULATOR, dev,
+ "iovcc-supply", &priv->iovcc);
+ if (ret) {
+ log_err("Cannot get iovcc-supply: ret = %d\n", ret);
+ return ret;
+ }
+
+ ret = gpio_request_by_name(dev, "reset-gpios", 0,
+ &priv->reset_gpio, GPIOD_IS_OUT);
+ if (ret) {
+ log_err("Could not decode reser-gpios (%d)\n", ret);
+ return ret;
+ }
+
+ priv->dig_cont_adj = dev_read_bool(dev, "renesas,contrast");
+ priv->inversion = dev_read_bool(dev, "renesas,inversion");
+ priv->gamma = dev_read_u32_default(dev, "renesas,gamma", 0);
+
+ return 0;
+}
+
+static int renesas_r61307_probe(struct udevice *dev)
+{
+ struct mipi_dsi_panel_plat *plat = dev_get_plat(dev);
+
+ /* fill characteristics of DSI data link */
+ plat->lanes = 4;
+ plat->format = MIPI_DSI_FMT_RGB888;
+ plat->mode_flags = MIPI_DSI_MODE_VIDEO;
+
+ return 0;
+}
+
+static const struct panel_ops renesas_r61307_ops = {
+ .enable_backlight = renesas_r61307_enable_backlight,
+ .set_backlight = renesas_r61307_set_backlight,
+ .get_display_timing = renesas_r61307_timings,
+};
+
+static const struct udevice_id renesas_r61307_ids[] = {
+ { .compatible = "koe,tx13d100vm0eaa" },
+ { .compatible = "hitachi,tx13d100vm0eaa" },
+ { }
+};
+
+U_BOOT_DRIVER(renesas_r61307) = {
+ .name = "renesas_r61307",
+ .id = UCLASS_PANEL,
+ .of_match = renesas_r61307_ids,
+ .ops = &renesas_r61307_ops,
+ .of_to_plat = renesas_r61307_of_to_plat,
+ .probe = renesas_r61307_probe,
+ .plat_auto = sizeof(struct mipi_dsi_panel_plat),
+ .priv_auto = sizeof(struct renesas_r61307_priv),
+};
diff --git a/drivers/video/renesas-r69328.c b/drivers/video/renesas-r69328.c
new file mode 100644
index 0000000..d2f7169
--- /dev/null
+++ b/drivers/video/renesas-r69328.c
@@ -0,0 +1,238 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Renesas R69328 panel driver
+ *
+ * Copyright (c) 2022 Svyatoslav Ryhel <clamor95@gmail.com>
+ */
+
+#include <common.h>
+#include <backlight.h>
+#include <dm.h>
+#include <panel.h>
+#include <log.h>
+#include <misc.h>
+#include <mipi_display.h>
+#include <mipi_dsi.h>
+#include <asm/gpio.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <power/regulator.h>
+
+/*
+ * The datasheet is not publicly available, all values are
+ * taken from the downstream. If you have access to datasheets,
+ * corrections are welcome.
+ */
+
+#define R69328_MACP 0xB0 /* Manufacturer Command Access Protect */
+
+#define R69328_GAMMA_SET_A 0xC8 /* Gamma Setting A */
+#define R69328_GAMMA_SET_B 0xC9 /* Gamma Setting B */
+#define R69328_GAMMA_SET_C 0xCA /* Gamma Setting C */
+
+#define R69328_POWER_SET 0xD1
+
+struct renesas_r69328_priv {
+ struct udevice *backlight;
+
+ struct gpio_desc enable_gpio;
+ struct gpio_desc reset_gpio;
+};
+
+static const u8 address_mode[] = {
+ MIPI_DCS_SET_ADDRESS_MODE
+};
+
+#define dsi_generic_write_seq(dsi, cmd, seq...) do { \
+ static const u8 b[] = { cmd, seq }; \
+ int ret; \
+ ret = mipi_dsi_dcs_write_buffer(dsi, b, ARRAY_SIZE(b)); \
+ if (ret < 0) \
+ return ret; \
+ } while (0)
+
+static struct display_timing default_timing = {
+ .pixelclock.typ = 68000000,
+ .hactive.typ = 720,
+ .hfront_porch.typ = 92,
+ .hback_porch.typ = 62,
+ .hsync_len.typ = 4,
+ .vactive.typ = 1280,
+ .vfront_porch.typ = 6,
+ .vback_porch.typ = 3,
+ .vsync_len.typ = 1,
+};
+
+static int renesas_r69328_enable_backlight(struct udevice *dev)
+{
+ struct renesas_r69328_priv *priv = dev_get_priv(dev);
+ int ret;
+
+ ret = dm_gpio_set_value(&priv->enable_gpio, 1);
+ if (ret) {
+ log_err("error changing enable-gpios (%d)\n", ret);
+ return ret;
+ }
+ mdelay(5);
+
+ ret = dm_gpio_set_value(&priv->reset_gpio, 0);
+ if (ret) {
+ log_err("error changing reset-gpios (%d)\n", ret);
+ return ret;
+ }
+ mdelay(5);
+
+ ret = dm_gpio_set_value(&priv->reset_gpio, 1);
+ if (ret) {
+ log_err("error changing reset-gpios (%d)\n", ret);
+ return ret;
+ }
+
+ mdelay(5);
+
+ return 0;
+}
+
+static int renesas_r69328_set_backlight(struct udevice *dev, int percent)
+{
+ struct renesas_r69328_priv *priv = dev_get_priv(dev);
+ struct mipi_dsi_panel_plat *plat = dev_get_plat(dev);
+ struct mipi_dsi_device *dsi = plat->device;
+ int ret;
+
+ mipi_dsi_dcs_write_buffer(dsi, address_mode,
+ sizeof(address_mode));
+
+ ret = mipi_dsi_dcs_set_pixel_format(dsi, MIPI_DCS_PIXEL_FMT_24BIT << 4);
+ if (ret < 0) {
+ log_err("failed to set pixel format: %d\n", ret);
+ return ret;
+ }
+
+ ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
+ if (ret < 0) {
+ log_err("failed to exit sleep mode: %d\n", ret);
+ return ret;
+ }
+
+ mdelay(100);
+
+ /* MACP Off */
+ dsi_generic_write_seq(dsi, R69328_MACP, 0x04);
+
+ dsi_generic_write_seq(dsi, R69328_POWER_SET, 0x14,
+ 0x1d, 0x21, 0x67, 0x11, 0x9a);
+
+ dsi_generic_write_seq(dsi, R69328_GAMMA_SET_A, 0x00,
+ 0x1a, 0x20, 0x28, 0x25, 0x24,
+ 0x26, 0x15, 0x13, 0x11, 0x18,
+ 0x1e, 0x1c, 0x00, 0x00, 0x1a,
+ 0x20, 0x28, 0x25, 0x24, 0x26,
+ 0x15, 0x13, 0x11, 0x18, 0x1e,
+ 0x1c, 0x00);
+ dsi_generic_write_seq(dsi, R69328_GAMMA_SET_B, 0x00,
+ 0x1a, 0x20, 0x28, 0x25, 0x24,
+ 0x26, 0x15, 0x13, 0x11, 0x18,
+ 0x1e, 0x1c, 0x00, 0x00, 0x1a,
+ 0x20, 0x28, 0x25, 0x24, 0x26,
+ 0x15, 0x13, 0x11, 0x18, 0x1e,
+ 0x1c, 0x00);
+ dsi_generic_write_seq(dsi, R69328_GAMMA_SET_C, 0x00,
+ 0x1a, 0x20, 0x28, 0x25, 0x24,
+ 0x26, 0x15, 0x13, 0x11, 0x18,
+ 0x1e, 0x1c, 0x00, 0x00, 0x1a,
+ 0x20, 0x28, 0x25, 0x24, 0x26,
+ 0x15, 0x13, 0x11, 0x18, 0x1e,
+ 0x1c, 0x00);
+
+ /* MACP On */
+ dsi_generic_write_seq(dsi, R69328_MACP, 0x03);
+
+ ret = mipi_dsi_dcs_set_display_on(dsi);
+ if (ret < 0) {
+ log_err("failed to set display on: %d\n", ret);
+ return ret;
+ }
+
+ mdelay(50);
+
+ ret = backlight_enable(priv->backlight);
+ if (ret)
+ return ret;
+
+ ret = backlight_set_brightness(priv->backlight, percent);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int renesas_r69328_timings(struct udevice *dev,
+ struct display_timing *timing)
+{
+ memcpy(timing, &default_timing, sizeof(*timing));
+ return 0;
+}
+
+static int renesas_r69328_of_to_plat(struct udevice *dev)
+{
+ struct renesas_r69328_priv *priv = dev_get_priv(dev);
+ int ret;
+
+ ret = uclass_get_device_by_phandle(UCLASS_PANEL_BACKLIGHT, dev,
+ "backlight", &priv->backlight);
+ if (ret) {
+ log_err("cannot get backlight: ret = %d\n", ret);
+ return ret;
+ }
+
+ ret = gpio_request_by_name(dev, "enable-gpios", 0,
+ &priv->enable_gpio, GPIOD_IS_OUT);
+ if (ret) {
+ log_err("could not decode enable-gpios (%d)\n", ret);
+ return ret;
+ }
+
+ ret = gpio_request_by_name(dev, "reset-gpios", 0,
+ &priv->reset_gpio, GPIOD_IS_OUT);
+ if (ret) {
+ log_err("could not decode reser-gpios (%d)\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int renesas_r69328_probe(struct udevice *dev)
+{
+ struct mipi_dsi_panel_plat *plat = dev_get_plat(dev);
+
+ /* fill characteristics of DSI data link */
+ plat->lanes = 4;
+ plat->format = MIPI_DSI_FMT_RGB888;
+ plat->mode_flags = MIPI_DSI_MODE_VIDEO;
+
+ return 0;
+}
+
+static const struct panel_ops renesas_r69328_ops = {
+ .enable_backlight = renesas_r69328_enable_backlight,
+ .set_backlight = renesas_r69328_set_backlight,
+ .get_display_timing = renesas_r69328_timings,
+};
+
+static const struct udevice_id renesas_r69328_ids[] = {
+ { .compatible = "jdi,dx12d100vm0eaa" },
+ { }
+};
+
+U_BOOT_DRIVER(renesas_r69328) = {
+ .name = "renesas_r69328",
+ .id = UCLASS_PANEL,
+ .of_match = renesas_r69328_ids,
+ .ops = &renesas_r69328_ops,
+ .of_to_plat = renesas_r69328_of_to_plat,
+ .probe = renesas_r69328_probe,
+ .plat_auto = sizeof(struct mipi_dsi_panel_plat),
+ .priv_auto = sizeof(struct renesas_r69328_priv),
+};
diff --git a/drivers/video/tegra20/Kconfig b/drivers/video/tegra20/Kconfig
index 5b1dfbf..f5c4843 100644
--- a/drivers/video/tegra20/Kconfig
+++ b/drivers/video/tegra20/Kconfig
@@ -15,3 +15,10 @@ config VIDEO_DSI_TEGRA30
help
T30 has native support for DSI panels. This option enables support
for such panels which can be used on endeavoru and tf600t.
+
+config TEGRA_BACKLIGHT_PWM
+ bool "Enable Tegra DC PWM backlight support"
+ depends on BACKLIGHT
+ select VIDEO_TEGRA20
+ help
+ Tegra DC dependent backlight.
diff --git a/drivers/video/tegra20/Makefile b/drivers/video/tegra20/Makefile
index e82ee96..f0b534c 100644
--- a/drivers/video/tegra20/Makefile
+++ b/drivers/video/tegra20/Makefile
@@ -2,3 +2,4 @@
obj-$(CONFIG_VIDEO_TEGRA20) += tegra-dc.o
obj-$(CONFIG_VIDEO_DSI_TEGRA30) += tegra-dsi.o mipi-phy.o
+obj-$(CONFIG_TEGRA_BACKLIGHT_PWM) += tegra-pwm-backlight.o
diff --git a/drivers/video/tegra20/tegra-pwm-backlight.c b/drivers/video/tegra20/tegra-pwm-backlight.c
new file mode 100644
index 0000000..bb677da
--- /dev/null
+++ b/drivers/video/tegra20/tegra-pwm-backlight.c
@@ -0,0 +1,156 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2022 Svyatoslav Ryhel <clamor95@gmail.com>
+ */
+
+#define LOG_CATEGORY UCLASS_PANEL_BACKLIGHT
+
+#include <backlight.h>
+#include <common.h>
+#include <dm.h>
+#include <i2c.h>
+#include <log.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+
+#include <asm/io.h>
+#include <asm/gpio.h>
+#include <asm/arch/display.h>
+
+#define TEGRA_DISPLAY_A_BASE 0x54200000
+#define TEGRA_DISPLAY_B_BASE 0x54240000
+
+#define TEGRA_PWM_BL_MIN_BRIGHTNESS 0x10
+#define TEGRA_PWM_BL_MAX_BRIGHTNESS 0xFF
+
+#define TEGRA_PWM_BL_PERIOD 0xFF
+#define TEGRA_PWM_BL_CLK_DIV 0x14
+#define TEGRA_PWM_BL_CLK_SELECT 0x00
+
+#define PM_PERIOD_SHIFT 18
+#define PM_CLK_DIVIDER_SHIFT 4
+
+#define TEGRA_PWM_PM0 0
+#define TEGRA_PWM_PM1 1
+
+struct tegra_pwm_backlight_priv {
+ struct dc_ctlr *dc; /* Display controller regmap */
+
+ u32 pwm_source;
+ u32 period;
+ u32 clk_div;
+ u32 clk_select;
+ u32 dft_brightness;
+};
+
+static int tegra_pwm_backlight_set_brightness(struct udevice *dev, int percent)
+{
+ struct tegra_pwm_backlight_priv *priv = dev_get_priv(dev);
+ struct dc_cmd_reg *cmd = &priv->dc->cmd;
+ struct dc_com_reg *com = &priv->dc->com;
+ unsigned int ctrl;
+ unsigned long out_sel;
+ unsigned long cmd_state;
+
+ if (percent == BACKLIGHT_DEFAULT)
+ percent = priv->dft_brightness;
+
+ if (percent < TEGRA_PWM_BL_MIN_BRIGHTNESS)
+ percent = TEGRA_PWM_BL_MIN_BRIGHTNESS;
+
+ if (percent > TEGRA_PWM_BL_MAX_BRIGHTNESS)
+ percent = TEGRA_PWM_BL_MAX_BRIGHTNESS;
+
+ ctrl = ((priv->period << PM_PERIOD_SHIFT) |
+ (priv->clk_div << PM_CLK_DIVIDER_SHIFT) |
+ priv->clk_select);
+
+ /* The new value should be effected immediately */
+ cmd_state = readl(&cmd->state_access);
+ writel((cmd_state | (1 << 2)), &cmd->state_access);
+
+ switch (priv->pwm_source) {
+ case TEGRA_PWM_PM0:
+ /* Select the LM0 on PM0 */
+ out_sel = readl(&com->pin_output_sel[5]);
+ out_sel &= ~(7 << 0);
+ out_sel |= (3 << 0);
+ writel(out_sel, &com->pin_output_sel[5]);
+ writel(ctrl, &com->pm0_ctrl);
+ writel(percent, &com->pm0_duty_cycle);
+ break;
+ case TEGRA_PWM_PM1:
+ /* Select the LM1 on PM1 */
+ out_sel = readl(&com->pin_output_sel[5]);
+ out_sel &= ~(7 << 4);
+ out_sel |= (3 << 4);
+ writel(out_sel, &com->pin_output_sel[5]);
+ writel(ctrl, &com->pm1_ctrl);
+ writel(percent, &com->pm1_duty_cycle);
+ break;
+ default:
+ break;
+ }
+
+ writel(cmd_state, &cmd->state_access);
+ return 0;
+}
+
+static int tegra_pwm_backlight_enable(struct udevice *dev)
+{
+ struct tegra_pwm_backlight_priv *priv = dev_get_priv(dev);
+
+ return tegra_pwm_backlight_set_brightness(dev, priv->dft_brightness);
+}
+
+static int tegra_pwm_backlight_probe(struct udevice *dev)
+{
+ struct tegra_pwm_backlight_priv *priv = dev_get_priv(dev);
+
+ if (dev_read_bool(dev, "nvidia,display-b-base"))
+ priv->dc = (struct dc_ctlr *)TEGRA_DISPLAY_B_BASE;
+ else
+ priv->dc = (struct dc_ctlr *)TEGRA_DISPLAY_A_BASE;
+
+ if (!priv->dc) {
+ log_err("no display controller address\n");
+ return -EINVAL;
+ }
+
+ priv->pwm_source =
+ dev_read_u32_default(dev, "nvidia,pwm-source",
+ TEGRA_PWM_PM0);
+ priv->period =
+ dev_read_u32_default(dev, "nvidia,period",
+ TEGRA_PWM_BL_PERIOD);
+ priv->clk_div =
+ dev_read_u32_default(dev, "nvidia,clock-div",
+ TEGRA_PWM_BL_CLK_DIV);
+ priv->clk_select =
+ dev_read_u32_default(dev, "nvidia,clock-select",
+ TEGRA_PWM_BL_CLK_SELECT);
+ priv->dft_brightness =
+ dev_read_u32_default(dev, "nvidia,default-brightness",
+ TEGRA_PWM_BL_MAX_BRIGHTNESS);
+
+ return 0;
+}
+
+static const struct backlight_ops tegra_pwm_backlight_ops = {
+ .enable = tegra_pwm_backlight_enable,
+ .set_brightness = tegra_pwm_backlight_set_brightness,
+};
+
+static const struct udevice_id tegra_pwm_backlight_ids[] = {
+ { .compatible = "nvidia,tegra-pwm-backlight" },
+ { }
+};
+
+U_BOOT_DRIVER(tegra_pwm_backlight) = {
+ .name = "tegra_pwm_backlight",
+ .id = UCLASS_PANEL_BACKLIGHT,
+ .of_match = tegra_pwm_backlight_ids,
+ .probe = tegra_pwm_backlight_probe,
+ .ops = &tegra_pwm_backlight_ops,
+ .priv_auto = sizeof(struct tegra_pwm_backlight_priv),
+};
diff --git a/drivers/video/tidss/Kconfig b/drivers/video/tidss/Kconfig
index 2a5e56e..95086f3 100644
--- a/drivers/video/tidss/Kconfig
+++ b/drivers/video/tidss/Kconfig
@@ -16,3 +16,9 @@ menuconfig VIDEO_TIDSS
DPI . This option enables these supports which can be used on
devices which have OLDI or HDMI display connected.
+config SPL_VIDEO_TIDSS
+ bool "Enable TIDSS video support in SPL Stage"
+ depends on SPL_VIDEO
+ help
+ This options enables tidss driver in SPL stage. If
+ you need to use tidss at SPL stage use this config.
diff --git a/drivers/video/tidss/Makefile b/drivers/video/tidss/Makefile
index f4f8c6c..a29cee2 100644
--- a/drivers/video/tidss/Makefile
+++ b/drivers/video/tidss/Makefile
@@ -9,4 +9,4 @@
# Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
-obj-${CONFIG_VIDEO_TIDSS} = tidss_drv.o
+obj-${CONFIG_$(SPL_)VIDEO_TIDSS} = tidss_drv.o
diff --git a/drivers/video/vidconsole-uclass.c b/drivers/video/vidconsole-uclass.c
index 1225de2..a21fde0 100644
--- a/drivers/video/vidconsole-uclass.c
+++ b/drivers/video/vidconsole-uclass.c
@@ -86,7 +86,7 @@ static void vidconsole_newline(struct udevice *dev)
struct vidconsole_priv *priv = dev_get_uclass_priv(dev);
struct udevice *vid_dev = dev->parent;
struct video_priv *vid_priv = dev_get_uclass_priv(vid_dev);
- const int rows = CONFIG_CONSOLE_SCROLL_LINES;
+ const int rows = CONFIG_VAL(CONSOLE_SCROLL_LINES);
int i, ret;
priv->xcur_frac = priv->xstart_frac;
diff --git a/drivers/video/video-uclass.c b/drivers/video/video-uclass.c
index da89f43..8396bdf 100644
--- a/drivers/video/video-uclass.c
+++ b/drivers/video/video-uclass.c
@@ -132,7 +132,7 @@ int video_reserve(ulong *addrp)
/* Allocate space for PCI video devices in case there were not bound */
if (*addrp == gd->video_top)
- *addrp -= CONFIG_VIDEO_PCI_DEFAULT_FB_SIZE;
+ *addrp -= CONFIG_VAL(VIDEO_PCI_DEFAULT_FB_SIZE);
gd->video_bottom = *addrp;
gd->fb_base = *addrp;
@@ -149,7 +149,7 @@ int video_fill(struct udevice *dev, u32 colour)
switch (priv->bpix) {
case VIDEO_BPP16:
- if (IS_ENABLED(CONFIG_VIDEO_BPP16)) {
+ if (CONFIG_IS_ENABLED(VIDEO_BPP16)) {
u16 *ppix = priv->fb;
u16 *end = priv->fb + priv->fb_size;
@@ -158,7 +158,7 @@ int video_fill(struct udevice *dev, u32 colour)
break;
}
case VIDEO_BPP32:
- if (IS_ENABLED(CONFIG_VIDEO_BPP32)) {
+ if (CONFIG_IS_ENABLED(VIDEO_BPP32)) {
u32 *ppix = priv->fb;
u32 *end = priv->fb + priv->fb_size;
@@ -212,14 +212,14 @@ u32 video_index_to_colour(struct video_priv *priv, unsigned int idx)
{
switch (priv->bpix) {
case VIDEO_BPP16:
- if (IS_ENABLED(CONFIG_VIDEO_BPP16)) {
+ if (CONFIG_IS_ENABLED(VIDEO_BPP16)) {
return ((colours[idx].r >> 3) << 11) |
((colours[idx].g >> 2) << 5) |
((colours[idx].b >> 3) << 0);
}
break;
case VIDEO_BPP32:
- if (IS_ENABLED(CONFIG_VIDEO_BPP32)) {
+ if (CONFIG_IS_ENABLED(VIDEO_BPP32)) {
if (priv->format == VIDEO_X2R10G10B10)
return (colours[idx].r << 22) |
(colours[idx].g << 12) |
@@ -513,8 +513,8 @@ static int video_post_probe(struct udevice *dev)
return ret;
}
- if (IS_ENABLED(CONFIG_VIDEO_LOGO) &&
- !IS_ENABLED(CONFIG_SPLASH_SCREEN) && !plat->hide_logo) {
+ if (CONFIG_IS_ENABLED(VIDEO_LOGO) &&
+ !CONFIG_IS_ENABLED(SPLASH_SCREEN) && !plat->hide_logo) {
ret = show_splash(dev);
if (ret) {
log_debug("Cannot show splash screen\n");
diff --git a/drivers/video/video_bmp.c b/drivers/video/video_bmp.c
index 6188a13..47e52c4 100644
--- a/drivers/video/video_bmp.c
+++ b/drivers/video/video_bmp.c
@@ -320,7 +320,7 @@ int video_bmp_display(struct udevice *dev, ulong bmp_image, int x, int y,
switch (bmp_bpix) {
case 1:
case 8:
- if (IS_ENABLED(CONFIG_VIDEO_BMP_RLE8)) {
+ if (CONFIG_IS_ENABLED(VIDEO_BMP_RLE8)) {
u32 compression = get_unaligned_le32(
&bmp->header.compression);
debug("compressed %d %d\n", compression, BMP_BI_RLE8);
@@ -348,7 +348,7 @@ int video_bmp_display(struct udevice *dev, ulong bmp_image, int x, int y,
}
break;
case 16:
- if (IS_ENABLED(CONFIG_BMP_16BPP)) {
+ if (CONFIG_IS_ENABLED(BMP_16BPP)) {
for (i = 0; i < height; ++i) {
schedule();
for (j = 0; j < width; j++) {
@@ -361,7 +361,7 @@ int video_bmp_display(struct udevice *dev, ulong bmp_image, int x, int y,
}
break;
case 24:
- if (IS_ENABLED(CONFIG_BMP_24BPP)) {
+ if (CONFIG_IS_ENABLED(BMP_24BPP)) {
for (i = 0; i < height; ++i) {
for (j = 0; j < width; j++) {
if (bpix == 16) {
@@ -395,7 +395,7 @@ int video_bmp_display(struct udevice *dev, ulong bmp_image, int x, int y,
}
break;
case 32:
- if (IS_ENABLED(CONFIG_BMP_32BPP)) {
+ if (CONFIG_IS_ENABLED(BMP_32BPP)) {
for (i = 0; i < height; ++i) {
for (j = 0; j < width; j++) {
if (eformat == VIDEO_X2R10G10B10) {
diff --git a/include/asm-generic/global_data.h b/include/asm-generic/global_data.h
index 987fb66..65bf8df 100644
--- a/include/asm-generic/global_data.h
+++ b/include/asm-generic/global_data.h
@@ -68,7 +68,7 @@ struct global_data {
* @mem_clk: memory clock rate in Hz
*/
unsigned long mem_clk;
-#if defined(CONFIG_VIDEO)
+#if CONFIG_IS_ENABLED(VIDEO)
/**
* @fb_base: base address of frame buffer memory
*/
@@ -359,7 +359,7 @@ struct global_data {
*/
struct membuff console_in;
#endif
-#ifdef CONFIG_VIDEO
+#if CONFIG_IS_ENABLED(VIDEO)
/**
* @video_top: top of video frame buffer area
*/
diff --git a/include/splash.h b/include/splash.h
index 33e45e6..c392237 100644
--- a/include/splash.h
+++ b/include/splash.h
@@ -49,7 +49,7 @@ struct splash_location {
char *ubivol; /* UBI volume-name for ubifsmount */
};
-#ifdef CONFIG_SPLASH_SOURCE
+#if CONFIG_IS_ENABLED(SPLASH_SOURCE)
int splash_source_load(struct splash_location *locations, uint size);
#else
static inline int splash_source_load(struct splash_location *locations,
@@ -60,21 +60,8 @@ static inline int splash_source_load(struct splash_location *locations,
#endif
int splash_screen_prepare(void);
-
-#ifdef CONFIG_SPLASH_SCREEN_ALIGN
void splash_get_pos(int *x, int *y);
-#else
-static inline void splash_get_pos(int *x, int *y) { }
-#endif
-
-#if defined(CONFIG_SPLASH_SCREEN) && defined(CONFIG_CMD_BMP)
int splash_display(void);
-#else
-static inline int splash_display(void)
-{
- return -ENOSYS;
-}
-#endif
#define BMP_ALIGN_CENTER 0x7FFF
diff --git a/include/video.h b/include/video.h
index 4d99e5d..29c4f51 100644
--- a/include/video.h
+++ b/include/video.h
@@ -357,4 +357,12 @@ void *video_get_u_boot_logo(void);
*/
int bmp_display(ulong addr, int x, int y);
+/*
+ * bmp_info() - Show information about bmp file
+ *
+ * @addr: address of bmp file
+ * Returns: 0 if OK, else 1 if bmp image not found
+ */
+int bmp_info(ulong addr);
+
#endif