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(-)
@@ -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;
@@ -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
*
@@ -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);