mirror of
https://github.com/u-boot/u-boot.git
synced 2024-11-25 13:14:19 +08:00
- 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 -----BEGIN PGP SIGNATURE----- iGwEABECACwWIQSC4hxrSoIUVfFO0kRM6ATMmsalXAUCZFS44Q4cYWd1c3RAZGVu eC5kZQAKCRBM6ATMmsalXPcDAJ9JjtVNvOUbS8mW51dHvmCYIP/tFwCfbfYTNVmq jvfn5+wAnkARJxcU6G8= =zXBt -----END PGP SIGNATURE----- Merge tag 'video-for-v2023.07-rc2' of https://source.denx.de/u-boot/custodians/u-boot-video - 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
This commit is contained in:
commit
ab75996ba4
@ -19,8 +19,14 @@
|
||||
|
||||
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,
|
||||
|
162
cmd/bmp.c
162
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;
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
149
common/bmp.c
Normal file
149
common/bmp.c
Normal file
@ -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;
|
||||
}
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
520
drivers/video/bridge/ssd2825.c
Normal file
520
drivers/video/bridge/ssd2825.c
Normal file
@ -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),
|
||||
};
|
@ -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;
|
||||
|
252
drivers/video/endeavoru-panel.c
Normal file
252
drivers/video/endeavoru-panel.c
Normal file
@ -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),
|
||||
};
|
134
drivers/video/lm3533_backlight.c
Normal file
134
drivers/video/lm3533_backlight.c
Normal file
@ -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),
|
||||
};
|
302
drivers/video/renesas-r61307.c
Normal file
302
drivers/video/renesas-r61307.c
Normal file
@ -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),
|
||||
};
|
238
drivers/video/renesas-r69328.c
Normal file
238
drivers/video/renesas-r69328.c
Normal file
@ -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),
|
||||
};
|
@ -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.
|
||||
|
@ -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
|
||||
|
156
drivers/video/tegra20/tegra-pwm-backlight.c
Normal file
156
drivers/video/tegra20/tegra-pwm-backlight.c
Normal file
@ -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),
|
||||
};
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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");
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user