diff options
-rw-r--r-- | common/Kconfig | 9 | ||||
-rw-r--r-- | common/Makefile | 2 | ||||
-rw-r--r-- | drivers/serial/sandbox.c | 2 | ||||
-rw-r--r-- | drivers/video/Kconfig | 35 | ||||
-rw-r--r-- | drivers/video/video-uclass.c | 52 | ||||
-rw-r--r-- | drivers/watchdog/Kconfig | 2 | ||||
-rw-r--r-- | include/asm-generic/global_data.h | 2 | ||||
-rw-r--r-- | include/cyclic.h | 5 | ||||
-rw-r--r-- | include/video.h | 2 |
9 files changed, 96 insertions, 15 deletions
diff --git a/common/Kconfig b/common/Kconfig index 4bb9f08977a..83c81edac20 100644 --- a/common/Kconfig +++ b/common/Kconfig @@ -626,8 +626,17 @@ config 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 int "Sets the max allowed time for a cyclic function in us" + default 100000 if SANDBOX # sandbox video is quite slow default 5000 help The max allowed time for a cyclic function in us. If a functions diff --git a/common/Makefile b/common/Makefile index e9835473420..d871113cbb9 100644 --- a/common/Makefile +++ b/common/Makefile @@ -79,7 +79,7 @@ obj-$(CONFIG_CROS_EC) += cros_ec.o obj-y += dlmalloc.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_)HASH) += hash.o diff --git a/drivers/serial/sandbox.c b/drivers/serial/sandbox.c index ec0068e33d3..77a1558db68 100644 --- a/drivers/serial/sandbox.c +++ b/drivers/serial/sandbox.c @@ -138,8 +138,6 @@ static int sandbox_serial_pending(struct udevice *dev, bool input) return 0; os_usleep(100); - if (IS_ENABLED(CONFIG_VIDEO) && !IS_ENABLED(CONFIG_SPL_BUILD)) - video_sync_all(); avail = membuff_putraw(&priv->buf, 100, false, &data); if (!avail) return 1; /* buffer full */ diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 7808ae7919e..6e79694fd19 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -7,6 +7,7 @@ menu "Graphics support" config VIDEO bool "Enable driver model support for LCD/video" depends on DM + imply CYCLIC help This enables driver model for LCD and video devices. These support 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 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 config VIDEO_FONT_4X6 @@ -232,6 +238,35 @@ config NO_FB_CLEAR loads takes over the screen. This, for example, can be used to 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 bool "Enable panel uclass support" default y diff --git a/drivers/video/video-uclass.c b/drivers/video/video-uclass.c index ff1382f4a43..a5aa8dd5295 100644 --- a/drivers/video/video-uclass.c +++ b/drivers/video/video-uclass.c @@ -8,6 +8,7 @@ #include <bloblist.h> #include <console.h> #include <cpu_func.h> +#include <cyclic.h> #include <dm.h> #include <log.h> #include <malloc.h> @@ -52,6 +53,8 @@ */ DECLARE_GLOBAL_DATA_PTR; +struct cyclic_info; + /** * 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 * gd->video_top and works downwards, running out of space when it hits * gd->video_bottom. + * @cyc: handle for cyclic-execution function, or NULL if none */ struct video_uc_priv { ulong video_ptr; + bool cyc_active; + struct cyclic_info cyc; }; /** 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 */ 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); int ret; @@ -358,28 +365,26 @@ int video_sync(struct udevice *vid, bool force) 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 * architectures do not actually implement it. Is there a way to find * out whether it exists? For now, ARM is safe. */ #if defined(CONFIG_ARM) && !CONFIG_IS_ENABLED(SYS_DCACHE_OFF) - struct video_priv *priv = dev_get_uclass_priv(vid); - if (priv->flush_dcache) { flush_dcache_range((ulong)priv->fb, ALIGN((ulong)priv->fb + priv->fb_size, CONFIG_SYS_CACHELINE_SIZE)); } #elif defined(CONFIG_VIDEO_SANDBOX_SDL) - struct video_priv *priv = dev_get_uclass_priv(vid); - static ulong last_sync; - - if (force || get_timer(last_sync) > 100) { - sandbox_sdl_sync(priv->fb); - last_sync = get_timer(0); - } + sandbox_sdl_sync(priv->fb); #endif + priv->last_sync = get_timer(0); + return 0; } @@ -528,10 +533,16 @@ int video_default_font_height(struct udevice *dev) return vc_priv->y_charsize; } +static void video_idle(struct cyclic_info *cyc) +{ + video_sync_all(); +} + /* Set up the display ready for use */ static int video_post_probe(struct udevice *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); char name[30], drv[15], *str; 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; }; @@ -661,6 +682,18 @@ static int video_post_bind(struct udevice *dev) 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) = { .id = UCLASS_VIDEO, .name = "video", @@ -670,4 +703,5 @@ UCLASS_DRIVER(video) = { .priv_auto = sizeof(struct video_uc_priv), .per_device_auto = sizeof(struct video_priv), .per_device_plat_auto = sizeof(struct video_uc_plat), + CONFIG_IS_ENABLED(CYCLIC, (.destroy = video_destroy, )) }; diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 8318fd77a32..0c3e9913318 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -4,6 +4,7 @@ config WATCHDOG bool "Enable U-Boot watchdog reset" depends on !HW_WATCHDOG select CYCLIC + imply SPL_CYCLIC if SPL help This option enables U-Boot watchdog support where U-Boot is using watchdog_reset function to service watchdog device in U-Boot. Enable @@ -408,6 +409,7 @@ config WDT_ARM_SMC config SPL_WDT bool "Enable driver model for watchdog timer drivers in SPL" depends on SPL_DM + select SPL_CYCLIC if CYCLIC help Enable driver model for watchdog timer in SPL. This is similar to CONFIG_WDT in U-Boot. diff --git a/include/asm-generic/global_data.h b/include/asm-generic/global_data.h index aa336d63e3a..27aa75e7036 100644 --- a/include/asm-generic/global_data.h +++ b/include/asm-generic/global_data.h @@ -481,7 +481,7 @@ struct global_data { */ struct event_state event_state; #endif -#ifdef CONFIG_CYCLIC +#if CONFIG_IS_ENABLED(CYCLIC) /** * @cyclic_list: list of registered cyclic functions */ diff --git a/include/cyclic.h b/include/cyclic.h index 2c3d383c5ef..cd95b691d48 100644 --- a/include/cyclic.h +++ b/include/cyclic.h @@ -46,7 +46,8 @@ struct cyclic_info { /** Function type for cyclic functions */ 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 * @@ -123,6 +124,6 @@ static inline int cyclic_unregister_all(void) { return 0; } -#endif +#endif /* CYCLIC */ #endif diff --git a/include/video.h b/include/video.h index 4d8df9baaad..4013a949983 100644 --- a/include/video.h +++ b/include/video.h @@ -97,6 +97,7 @@ enum video_format { * the LCD is updated * @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) + * @last_sync: Monotonic time of last video sync */ struct video_priv { /* Things set up by the driver: */ @@ -121,6 +122,7 @@ struct video_priv { bool flush_dcache; u8 fg_col_idx; u8 bg_col_idx; + ulong last_sync; }; /** |