mirror of
https://github.com/u-boot/u-boot.git
synced 2025-04-25 14:56:03 +00:00
- improve video sync performance with background syncing (cyclic)
- fix dropping characters when pasting commands over the UART - enable background syncing by default for boards using VIDEO - make sandbox video more responsive -----BEGIN PGP SIGNATURE----- iGwEABECACwWIQSC4hxrSoIUVfFO0kRM6ATMmsalXAUCZqqD3w4cYWd1c3RAZGVu eC5kZQAKCRBM6ATMmsalXBXOAJ4+YXVj/tqYfGzbYgMvmQjdpHs3XQCfX6hJwBWG gfdZp+gqv/FnVjeDCVQ= =0ThR -----END PGP SIGNATURE----- Merge tag 'video-20240731' of https://source.denx.de/u-boot/custodians/u-boot-video - improve video sync performance with background syncing (cyclic) - fix dropping characters when pasting commands over the UART - enable background syncing by default for boards using VIDEO - make sandbox video more responsive
This commit is contained in:
commit
7010f22eba
9 changed files with 96 additions and 15 deletions
|
@ -626,8 +626,17 @@ config CYCLIC
|
||||||
|
|
||||||
if CYCLIC
|
if CYCLIC
|
||||||
|
|
||||||
|
config SPL_CYCLIC
|
||||||
|
bool "General-purpose cyclic execution mechanism (SPL)"
|
||||||
|
help
|
||||||
|
This enables a general-purpose cyclic execution infrastructure in SPL,
|
||||||
|
to allow "small" (run-time wise) functions to be executed at
|
||||||
|
a specified frequency. Things like LED blinking or watchdog
|
||||||
|
triggering are examples for such tasks.
|
||||||
|
|
||||||
config CYCLIC_MAX_CPU_TIME_US
|
config CYCLIC_MAX_CPU_TIME_US
|
||||||
int "Sets the max allowed time for a cyclic function in us"
|
int "Sets the max allowed time for a cyclic function in us"
|
||||||
|
default 100000 if SANDBOX # sandbox video is quite slow
|
||||||
default 5000
|
default 5000
|
||||||
help
|
help
|
||||||
The max allowed time for a cyclic function in us. If a functions
|
The max allowed time for a cyclic function in us. If a functions
|
||||||
|
|
|
@ -79,7 +79,7 @@ obj-$(CONFIG_CROS_EC) += cros_ec.o
|
||||||
obj-y += dlmalloc.o
|
obj-y += dlmalloc.o
|
||||||
obj-$(CONFIG_$(SPL_TPL_)SYS_MALLOC_F) += malloc_simple.o
|
obj-$(CONFIG_$(SPL_TPL_)SYS_MALLOC_F) += malloc_simple.o
|
||||||
|
|
||||||
obj-$(CONFIG_CYCLIC) += cyclic.o
|
obj-$(CONFIG_$(SPL_TPL_)CYCLIC) += cyclic.o
|
||||||
obj-$(CONFIG_$(SPL_TPL_)EVENT) += event.o
|
obj-$(CONFIG_$(SPL_TPL_)EVENT) += event.o
|
||||||
|
|
||||||
obj-$(CONFIG_$(SPL_TPL_)HASH) += hash.o
|
obj-$(CONFIG_$(SPL_TPL_)HASH) += hash.o
|
||||||
|
|
|
@ -138,8 +138,6 @@ static int sandbox_serial_pending(struct udevice *dev, bool input)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
os_usleep(100);
|
os_usleep(100);
|
||||||
if (IS_ENABLED(CONFIG_VIDEO) && !IS_ENABLED(CONFIG_SPL_BUILD))
|
|
||||||
video_sync_all();
|
|
||||||
avail = membuff_putraw(&priv->buf, 100, false, &data);
|
avail = membuff_putraw(&priv->buf, 100, false, &data);
|
||||||
if (!avail)
|
if (!avail)
|
||||||
return 1; /* buffer full */
|
return 1; /* buffer full */
|
||||||
|
|
|
@ -7,6 +7,7 @@ menu "Graphics support"
|
||||||
config VIDEO
|
config VIDEO
|
||||||
bool "Enable driver model support for LCD/video"
|
bool "Enable driver model support for LCD/video"
|
||||||
depends on DM
|
depends on DM
|
||||||
|
imply CYCLIC
|
||||||
help
|
help
|
||||||
This enables driver model for LCD and video devices. These support
|
This enables driver model for LCD and video devices. These support
|
||||||
a bitmap display of various sizes and depths which can be drawn on
|
a bitmap display of various sizes and depths which can be drawn on
|
||||||
|
@ -14,6 +15,11 @@ config VIDEO
|
||||||
option compiles in the video uclass and routes all LCD/video access
|
option compiles in the video uclass and routes all LCD/video access
|
||||||
through this.
|
through this.
|
||||||
|
|
||||||
|
If CYCLIC is enabled (which it is by default), the cyclic subsystem
|
||||||
|
is used to flush pending output to the display periodically, rather
|
||||||
|
than this happening with every chunk of output. This allows for more
|
||||||
|
efficient operation and faster display output.
|
||||||
|
|
||||||
if VIDEO
|
if VIDEO
|
||||||
|
|
||||||
config VIDEO_FONT_4X6
|
config VIDEO_FONT_4X6
|
||||||
|
@ -232,6 +238,35 @@ config NO_FB_CLEAR
|
||||||
loads takes over the screen. This, for example, can be used to
|
loads takes over the screen. This, for example, can be used to
|
||||||
keep splash image on screen until grub graphical boot menu starts.
|
keep splash image on screen until grub graphical boot menu starts.
|
||||||
|
|
||||||
|
config VIDEO_SYNC_MS
|
||||||
|
int "Video-sync period in milliseconds for foreground processing"
|
||||||
|
default 300 if SANDBOX
|
||||||
|
default 100
|
||||||
|
help
|
||||||
|
This sets the requested, maximum time before a video sync will take
|
||||||
|
place, in milliseconds. Note that the time between video syncs
|
||||||
|
may be longer than this, since syncs only happen when the video system
|
||||||
|
is used, e.g. by outputting a character to the console.
|
||||||
|
|
||||||
|
It may also be shorter, since the video uclass will automatically
|
||||||
|
force a sync in certain situations.
|
||||||
|
|
||||||
|
Many video-output systems require a sync operation before any output
|
||||||
|
is visible. This may flush the CPU cache or perhaps copy the
|
||||||
|
display contents to a hardware framebuffer. Without this, change to
|
||||||
|
the video may never be displayed.
|
||||||
|
|
||||||
|
config VIDEO_SYNC_CYCLIC_MS
|
||||||
|
int "Video-sync period in milliseconds for cyclic processing"
|
||||||
|
depends on CYCLIC
|
||||||
|
default 100 if SANDBOX
|
||||||
|
default 10
|
||||||
|
help
|
||||||
|
This sets the frequency of cyclic video syncs. The cyclic system is
|
||||||
|
used to ensure that when U-Boot is idle, it syncs the video. This
|
||||||
|
improves the responsiveness of the command line to new characters
|
||||||
|
being entered.
|
||||||
|
|
||||||
config PANEL
|
config PANEL
|
||||||
bool "Enable panel uclass support"
|
bool "Enable panel uclass support"
|
||||||
default y
|
default y
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include <bloblist.h>
|
#include <bloblist.h>
|
||||||
#include <console.h>
|
#include <console.h>
|
||||||
#include <cpu_func.h>
|
#include <cpu_func.h>
|
||||||
|
#include <cyclic.h>
|
||||||
#include <dm.h>
|
#include <dm.h>
|
||||||
#include <log.h>
|
#include <log.h>
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
|
@ -52,6 +53,8 @@
|
||||||
*/
|
*/
|
||||||
DECLARE_GLOBAL_DATA_PTR;
|
DECLARE_GLOBAL_DATA_PTR;
|
||||||
|
|
||||||
|
struct cyclic_info;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct video_uc_priv - Information for the video uclass
|
* struct video_uc_priv - Information for the video uclass
|
||||||
*
|
*
|
||||||
|
@ -60,9 +63,12 @@ DECLARE_GLOBAL_DATA_PTR;
|
||||||
* available address to use for a device's framebuffer. It starts at
|
* available address to use for a device's framebuffer. It starts at
|
||||||
* gd->video_top and works downwards, running out of space when it hits
|
* gd->video_top and works downwards, running out of space when it hits
|
||||||
* gd->video_bottom.
|
* gd->video_bottom.
|
||||||
|
* @cyc: handle for cyclic-execution function, or NULL if none
|
||||||
*/
|
*/
|
||||||
struct video_uc_priv {
|
struct video_uc_priv {
|
||||||
ulong video_ptr;
|
ulong video_ptr;
|
||||||
|
bool cyc_active;
|
||||||
|
struct cyclic_info cyc;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** struct vid_rgb - Describes a video colour */
|
/** struct vid_rgb - Describes a video colour */
|
||||||
|
@ -349,6 +355,7 @@ void video_set_default_colors(struct udevice *dev, bool invert)
|
||||||
/* Flush video activity to the caches */
|
/* Flush video activity to the caches */
|
||||||
int video_sync(struct udevice *vid, bool force)
|
int video_sync(struct udevice *vid, bool force)
|
||||||
{
|
{
|
||||||
|
struct video_priv *priv = dev_get_uclass_priv(vid);
|
||||||
struct video_ops *ops = video_get_ops(vid);
|
struct video_ops *ops = video_get_ops(vid);
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
@ -358,28 +365,26 @@ int video_sync(struct udevice *vid, bool force)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (CONFIG_IS_ENABLED(CYCLIC) && !force &&
|
||||||
|
get_timer(priv->last_sync) < CONFIG_VIDEO_SYNC_MS)
|
||||||
|
return 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* flush_dcache_range() is declared in common.h but it seems that some
|
* flush_dcache_range() is declared in common.h but it seems that some
|
||||||
* architectures do not actually implement it. Is there a way to find
|
* architectures do not actually implement it. Is there a way to find
|
||||||
* out whether it exists? For now, ARM is safe.
|
* out whether it exists? For now, ARM is safe.
|
||||||
*/
|
*/
|
||||||
#if defined(CONFIG_ARM) && !CONFIG_IS_ENABLED(SYS_DCACHE_OFF)
|
#if defined(CONFIG_ARM) && !CONFIG_IS_ENABLED(SYS_DCACHE_OFF)
|
||||||
struct video_priv *priv = dev_get_uclass_priv(vid);
|
|
||||||
|
|
||||||
if (priv->flush_dcache) {
|
if (priv->flush_dcache) {
|
||||||
flush_dcache_range((ulong)priv->fb,
|
flush_dcache_range((ulong)priv->fb,
|
||||||
ALIGN((ulong)priv->fb + priv->fb_size,
|
ALIGN((ulong)priv->fb + priv->fb_size,
|
||||||
CONFIG_SYS_CACHELINE_SIZE));
|
CONFIG_SYS_CACHELINE_SIZE));
|
||||||
}
|
}
|
||||||
#elif defined(CONFIG_VIDEO_SANDBOX_SDL)
|
#elif defined(CONFIG_VIDEO_SANDBOX_SDL)
|
||||||
struct video_priv *priv = dev_get_uclass_priv(vid);
|
sandbox_sdl_sync(priv->fb);
|
||||||
static ulong last_sync;
|
|
||||||
|
|
||||||
if (force || get_timer(last_sync) > 100) {
|
|
||||||
sandbox_sdl_sync(priv->fb);
|
|
||||||
last_sync = get_timer(0);
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
priv->last_sync = get_timer(0);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -528,10 +533,16 @@ int video_default_font_height(struct udevice *dev)
|
||||||
return vc_priv->y_charsize;
|
return vc_priv->y_charsize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void video_idle(struct cyclic_info *cyc)
|
||||||
|
{
|
||||||
|
video_sync_all();
|
||||||
|
}
|
||||||
|
|
||||||
/* Set up the display ready for use */
|
/* Set up the display ready for use */
|
||||||
static int video_post_probe(struct udevice *dev)
|
static int video_post_probe(struct udevice *dev)
|
||||||
{
|
{
|
||||||
struct video_uc_plat *plat = dev_get_uclass_plat(dev);
|
struct video_uc_plat *plat = dev_get_uclass_plat(dev);
|
||||||
|
struct video_uc_priv *uc_priv = uclass_get_priv(dev->uclass);
|
||||||
struct video_priv *priv = dev_get_uclass_priv(dev);
|
struct video_priv *priv = dev_get_uclass_priv(dev);
|
||||||
char name[30], drv[15], *str;
|
char name[30], drv[15], *str;
|
||||||
const char *drv_name = drv;
|
const char *drv_name = drv;
|
||||||
|
@ -622,6 +633,16 @@ static int video_post_probe(struct udevice *dev)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* register cyclic as soon as the first video device is probed */
|
||||||
|
if (CONFIG_IS_ENABLED(CYCLIC) && (gd->flags && GD_FLG_RELOC) &&
|
||||||
|
!uc_priv->cyc_active) {
|
||||||
|
uint ms = CONFIG_IF_ENABLED_INT(CYCLIC, VIDEO_SYNC_CYCLIC_MS);
|
||||||
|
|
||||||
|
cyclic_register(&uc_priv->cyc, video_idle, ms * 1000,
|
||||||
|
"video_init");
|
||||||
|
uc_priv->cyc_active = true;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -661,6 +682,18 @@ static int video_post_bind(struct udevice *dev)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
__maybe_unused static int video_destroy(struct uclass *uc)
|
||||||
|
{
|
||||||
|
struct video_uc_priv *uc_priv = uclass_get_priv(uc);
|
||||||
|
|
||||||
|
if (uc_priv->cyc_active) {
|
||||||
|
cyclic_unregister(&uc_priv->cyc);
|
||||||
|
uc_priv->cyc_active = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
UCLASS_DRIVER(video) = {
|
UCLASS_DRIVER(video) = {
|
||||||
.id = UCLASS_VIDEO,
|
.id = UCLASS_VIDEO,
|
||||||
.name = "video",
|
.name = "video",
|
||||||
|
@ -670,4 +703,5 @@ UCLASS_DRIVER(video) = {
|
||||||
.priv_auto = sizeof(struct video_uc_priv),
|
.priv_auto = sizeof(struct video_uc_priv),
|
||||||
.per_device_auto = sizeof(struct video_priv),
|
.per_device_auto = sizeof(struct video_priv),
|
||||||
.per_device_plat_auto = sizeof(struct video_uc_plat),
|
.per_device_plat_auto = sizeof(struct video_uc_plat),
|
||||||
|
CONFIG_IS_ENABLED(CYCLIC, (.destroy = video_destroy, ))
|
||||||
};
|
};
|
||||||
|
|
|
@ -4,6 +4,7 @@ config WATCHDOG
|
||||||
bool "Enable U-Boot watchdog reset"
|
bool "Enable U-Boot watchdog reset"
|
||||||
depends on !HW_WATCHDOG
|
depends on !HW_WATCHDOG
|
||||||
select CYCLIC
|
select CYCLIC
|
||||||
|
imply SPL_CYCLIC if SPL
|
||||||
help
|
help
|
||||||
This option enables U-Boot watchdog support where U-Boot is using
|
This option enables U-Boot watchdog support where U-Boot is using
|
||||||
watchdog_reset function to service watchdog device in U-Boot. Enable
|
watchdog_reset function to service watchdog device in U-Boot. Enable
|
||||||
|
@ -408,6 +409,7 @@ config WDT_ARM_SMC
|
||||||
config SPL_WDT
|
config SPL_WDT
|
||||||
bool "Enable driver model for watchdog timer drivers in SPL"
|
bool "Enable driver model for watchdog timer drivers in SPL"
|
||||||
depends on SPL_DM
|
depends on SPL_DM
|
||||||
|
select SPL_CYCLIC if CYCLIC
|
||||||
help
|
help
|
||||||
Enable driver model for watchdog timer in SPL.
|
Enable driver model for watchdog timer in SPL.
|
||||||
This is similar to CONFIG_WDT in U-Boot.
|
This is similar to CONFIG_WDT in U-Boot.
|
||||||
|
|
|
@ -481,7 +481,7 @@ struct global_data {
|
||||||
*/
|
*/
|
||||||
struct event_state event_state;
|
struct event_state event_state;
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_CYCLIC
|
#if CONFIG_IS_ENABLED(CYCLIC)
|
||||||
/**
|
/**
|
||||||
* @cyclic_list: list of registered cyclic functions
|
* @cyclic_list: list of registered cyclic functions
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -46,7 +46,8 @@ struct cyclic_info {
|
||||||
/** Function type for cyclic functions */
|
/** Function type for cyclic functions */
|
||||||
typedef void (*cyclic_func_t)(struct cyclic_info *c);
|
typedef void (*cyclic_func_t)(struct cyclic_info *c);
|
||||||
|
|
||||||
#if defined(CONFIG_CYCLIC)
|
#if CONFIG_IS_ENABLED(CYCLIC)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* cyclic_register - Register a new cyclic function
|
* cyclic_register - Register a new cyclic function
|
||||||
*
|
*
|
||||||
|
@ -123,6 +124,6 @@ static inline int cyclic_unregister_all(void)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif /* CYCLIC */
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -97,6 +97,7 @@ enum video_format {
|
||||||
* the LCD is updated
|
* the LCD is updated
|
||||||
* @fg_col_idx: Foreground color code (bit 3 = bold, bit 0-2 = color)
|
* @fg_col_idx: Foreground color code (bit 3 = bold, bit 0-2 = color)
|
||||||
* @bg_col_idx: Background color code (bit 3 = bold, bit 0-2 = color)
|
* @bg_col_idx: Background color code (bit 3 = bold, bit 0-2 = color)
|
||||||
|
* @last_sync: Monotonic time of last video sync
|
||||||
*/
|
*/
|
||||||
struct video_priv {
|
struct video_priv {
|
||||||
/* Things set up by the driver: */
|
/* Things set up by the driver: */
|
||||||
|
@ -121,6 +122,7 @@ struct video_priv {
|
||||||
bool flush_dcache;
|
bool flush_dcache;
|
||||||
u8 fg_col_idx;
|
u8 fg_col_idx;
|
||||||
u8 bg_col_idx;
|
u8 bg_col_idx;
|
||||||
|
ulong last_sync;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Add table
Reference in a new issue