[Concept,19/22] video: Refactor video_sync() to use video_manual_sync()

Message ID 20251003165525.440173-20-sjg@u-boot.org
State New
Headers
Series video: Enhancements to support a pointer |

Commit Message

Simon Glass Oct. 3, 2025, 4:55 p.m. UTC
  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(-)
  

Patch

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);