diff options
Diffstat (limited to 'drivers/video/video-uclass.c')
| -rw-r--r-- | drivers/video/video-uclass.c | 69 |
1 files changed, 57 insertions, 12 deletions
diff --git a/drivers/video/video-uclass.c b/drivers/video/video-uclass.c index 7b5d1dfbb3b..41bb7647fda 100644 --- a/drivers/video/video-uclass.c +++ b/drivers/video/video-uclass.c @@ -5,10 +5,10 @@ #define LOG_CATEGORY UCLASS_VIDEO -#include <common.h> #include <bloblist.h> #include <console.h> #include <cpu_func.h> +#include <cyclic.h> #include <dm.h> #include <log.h> #include <malloc.h> @@ -53,6 +53,8 @@ */ DECLARE_GLOBAL_DATA_PTR; +struct cyclic_info; + /** * struct video_uc_priv - Information for the video uclass * @@ -61,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 */ @@ -140,13 +145,26 @@ int video_reserve(ulong *addrp) *addrp -= CONFIG_VAL(VIDEO_PCI_DEFAULT_FB_SIZE); gd->video_bottom = *addrp; - gd->fb_base = *addrp; debug("Video frame buffers from %lx to %lx\n", gd->video_bottom, gd->video_top); return 0; } +ulong video_get_fb(void) +{ + struct udevice *dev; + + uclass_find_first_device(UCLASS_VIDEO, &dev); + if (dev) { + const struct video_uc_plat *uc_plat = dev_get_uclass_plat(dev); + + return uc_plat->base; + } + + return 0; +} + int video_fill_part(struct udevice *dev, int xstart, int ystart, int xend, int yend, u32 colour) { @@ -205,7 +223,6 @@ int video_reserve_from_bloblist(struct video_handoff *ho) return -ENOENT; gd->video_bottom = ho->fb; - gd->fb_base = ho->fb; gd->video_top = ho->fb + ho->size; debug("%s: Reserving %lx bytes at %08x as per bloblist received\n", __func__, (unsigned long)ho->size, (u32)ho->fb); @@ -350,6 +367,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; @@ -359,28 +377,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; } @@ -529,10 +545,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; @@ -623,6 +645,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; }; @@ -662,6 +694,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", @@ -671,4 +715,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, )) }; |
