From: Simon Glass <sjg@chromium.org> Extract the core sync logic from video_sync() into a new video_manual_sync() function that accepts flags directly. This allows callers to perform sync operations with explicit control over the sync behavior. The video_sync() function now: - Determines the appropriate flags (VIDSYNC_FORCE, VIDSYNC_FLUSH, VIDSYNC_COPY) based on the force parameter and timing - Calls video_manual_sync() with those flags The video_manual_sync() function: - Takes explicit flags as a parameter - Handles VIDSYNC_COPY flag to control copy framebuffer flush - Performs the actual sync operations This separation allows manual-sync mode users (and tests) to call video_manual_sync() directly with custom flags while video_sync() continues to work as before for normal scenarios. Add tests for video_manual_sync() to check the behaviour with different flag combinations. Co-developed-by: Claude <noreply@anthropic.com> Signed-off-by: Simon Glass <sjg@chromium.org> --- drivers/video/video-uclass.c | 46 ++++++++++++++++++++++-------------- include/video.h | 16 +++++++++++++ test/dm/video.c | 27 +++++++++++++++++++++ 3 files changed, 71 insertions(+), 18 deletions(-) diff --git a/drivers/video/video-uclass.c b/drivers/video/video-uclass.c index 8f5689a8a51..a8849cf6289 100644 --- a/drivers/video/video-uclass.c +++ b/drivers/video/video-uclass.c @@ -499,28 +499,13 @@ static void video_flush_copy(struct udevice *vid) } } -/* Flush video activity to the caches */ -int video_sync(struct udevice *vid, bool force) +int video_manual_sync(struct udevice *vid, uint flags) { struct video_priv *priv = dev_get_uclass_priv(vid); - struct video_uc_priv *uc_priv = uclass_get_priv(vid->uclass); struct video_ops *ops = video_get_ops(vid); - uint flags = 0; int ret; - /* Skip sync if manual-sync mode is active */ - if (uc_priv->manual_sync) - return 0; - - if (force) - flags |= VIDSYNC_FORCE; - - /* Check if sync should do full flush */ - if (!CONFIG_IS_ENABLED(CYCLIC) || force || - get_timer(priv->last_sync) >= CONFIG_VIDEO_SYNC_MS) - flags |= VIDSYNC_FLUSH; - - if (IS_ENABLED(CONFIG_VIDEO_COPY)) + if (IS_ENABLED(CONFIG_VIDEO_COPY) && (flags & VIDSYNC_COPY)) video_flush_copy(vid); if (ops && ops->sync) { @@ -534,7 +519,7 @@ int video_sync(struct udevice *vid, bool force) video_flush_dcache(vid, false); - if (IS_ENABLED(CONFIG_VIDEO_COPY)) + if (IS_ENABLED(CONFIG_VIDEO_COPY) && (flags & VIDSYNC_COPY)) video_flush_dcache(vid, true); #if defined(CONFIG_VIDEO_SANDBOX_SDL) @@ -555,6 +540,31 @@ int video_sync(struct udevice *vid, bool force) return 0; } +/* 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_uc_priv *uc_priv = uclass_get_priv(vid->uclass); + uint flags = 0; + + /* Skip sync if manual-sync mode is active */ + if (uc_priv->manual_sync) + return 0; + + if (force) + flags |= VIDSYNC_FORCE; + + /* Check if sync should do full flush */ + if (!CONFIG_IS_ENABLED(CYCLIC) || force || + get_timer(priv->last_sync) >= CONFIG_VIDEO_SYNC_MS) + flags |= VIDSYNC_FLUSH; + + if (IS_ENABLED(CONFIG_VIDEO_COPY)) + flags |= VIDSYNC_COPY; + + return video_manual_sync(vid, flags); +} + void video_sync_all(void) { struct udevice *dev; diff --git a/include/video.h b/include/video.h index d08781d3a78..d8ba27ab8a7 100644 --- a/include/video.h +++ b/include/video.h @@ -80,10 +80,12 @@ enum video_format { * * @VIDSYNC_FORCE: Force sync even if recently synced or in manual-sync mode * @VIDSYNC_FLUSH: Flush dcache and perform full sync operations + * @VIDSYNC_COPY: Flush framebuffer to copy buffer */ enum video_sync_flags { VIDSYNC_FORCE = BIT(0), VIDSYNC_FLUSH = BIT(1), + VIDSYNC_COPY = BIT(2), }; /** @@ -341,6 +343,20 @@ int video_fill_part(struct udevice *dev, int xstart, int ystart, int xend, int video_draw_box(struct udevice *dev, int x0, int y0, int x1, int y1, int width, u32 colour, bool fill); +/** + * video_manual_sync() - Manually sync a device's frame buffer with its hardware + * + * @vid: Device to sync + * @flags: Flags for the sync (enum video_sync_flags) + * + * @return: 0 on success, error code otherwise + * + * Performs the actual sync operation with the provided flags. This is called + * by video_sync() after determining the appropriate flags, but can also be + * called directly when manual-sync mode is enabled. + */ +int video_manual_sync(struct udevice *vid, uint flags); + /** * video_sync() - Sync a device's frame buffer with its hardware * diff --git a/test/dm/video.c b/test/dm/video.c index cee9e528689..080297d8350 100644 --- a/test/dm/video.c +++ b/test/dm/video.c @@ -1342,6 +1342,33 @@ static int dm_test_video_manual_sync(struct unit_test_state *uts) ut_asserteq(183, video_compress_fb(uts, dev, true)); } + /* Now test video_manual_sync() directly with VIDSYNC_FORCE and COPY */ + ut_assertok(video_manual_sync(dev, VIDSYNC_FORCE | VIDSYNC_FLUSH | + VIDSYNC_COPY)); + ut_asserteq(183, video_compress_fb(uts, dev, false)); + + /* The copy framebuffer should now match since we forced the sync */ + ut_assertok(video_check_copy_fb(uts, dev)); + + /* Write new text again */ + vidconsole_put_string(con, "Test2"); + + /* without VIDSYNC_FLUSH or COPY - should do nothing */ + ut_assertok(video_manual_sync(dev, 0)); + + /* Copy fb should not match since neither flush nor copy occurred */ + if (IS_ENABLED(CONFIG_VIDEO_COPY)) { + ut_assertf(memcmp(priv->fb, priv->copy_fb, priv->fb_size), + "Copy fb shouldn't match fb w/o VIDSYNC_FLUSH/COPY"); + } + + /* video_manual_sync() with full flags - should perform full sync */ + ut_assertok(video_manual_sync(dev, VIDSYNC_FLUSH | VIDSYNC_COPY)); + ut_assertok(video_check_copy_fb(uts, dev)); + + /* Disable manual-sync mode */ + video_set_manual_sync(false); + return 0; } DM_TEST(dm_test_video_manual_sync, UTF_SCAN_PDATA | UTF_SCAN_FDT); -- 2.43.0