[Concept,36/36] video: Move context allocation from drivers to uclass

Message ID 20260120231814.2033069-37-sjg@u-boot.org
State New
Headers
Series video: Add multiple-context support to vidconsole (part F) |

Commit Message

Simon Glass Jan. 20, 2026, 11:18 p.m. UTC
  From: Simon Glass <simon.glass@canonical.com>

Currently each driver allocates its own vidconsole context in its
ctx_new() method. This leads to duplication and makes it harder to
ensure consistent context setup.

Move the responsibility for allocating contexts to the uclass. The
ctx_new() ops method now receives an already-allocated context and
just needs to initialise driver-specific fields.

The uclass now handles:
- Allocating memory using plat->ctx_size
- Setting up xsize_frac from the video device
- Allocating the cursor-save buffer if cursor support is enabled
- Calling the driver's ctx_new() for driver-specific initialisation

Move the default context creation from vidconsole_pre_probe() to
vidconsole_post_probe() using vidconsole_ctx_new(). This allows
additional contexts to be set up by calling the same function.

For bitmap font drivers, rename console_probe() to
console_simple_ctx_new() and move struct console_ctx to
vidconsole_internal.h so it can be shared.

For the truetype driver, move font selection from
console_truetype_probe() to truetype_ctx_new(), using the first font
initially.

Also fix vidconsole_set_bitmap_font() to always set xsize_frac
rather than relying on it being set in vidconsole_pre_probe().

This is a rather large 'flag day' change but it has resisted being
broken up further.

Signed-off-by: Simon Glass <simon.glass@canonical.com>

---

 drivers/video/console_core.c        |  5 ++-
 drivers/video/console_normal.c      | 22 ----------
 drivers/video/console_rotate.c      |  6 +--
 drivers/video/console_truetype.c    | 17 +++-----
 drivers/video/vidconsole-uclass.c   | 64 +++++++++++++++++------------
 drivers/video/vidconsole_internal.h | 22 ++++++++++
 include/video_console.h             | 12 +++---
 7 files changed, 77 insertions(+), 71 deletions(-)
  

Patch

diff --git a/drivers/video/console_core.c b/drivers/video/console_core.c
index 6bd7dc263e6..ee07ffc98e4 100644
--- a/drivers/video/console_core.c
+++ b/drivers/video/console_core.c
@@ -305,11 +305,12 @@  void console_free_cursor(struct vidconsole_cursor *curs)
 	free(curs->save_data);
 }
 
-int console_probe(struct udevice *dev)
+int console_simple_ctx_new(struct udevice *dev, void *vctx)
 {
+	struct console_ctx *ctx = vctx;
 	int ret;
 
-	ret = console_set_font(dev, vidconsole_ctx(dev), fonts);
+	ret = console_set_font(dev, &ctx->com, fonts);
 	if (ret)
 		return ret;
 
diff --git a/drivers/video/console_normal.c b/drivers/video/console_normal.c
index c3b7f848b43..d36a5c0ff8f 100644
--- a/drivers/video/console_normal.c
+++ b/drivers/video/console_normal.c
@@ -15,14 +15,6 @@ 
 #include <video_font.h>		/* Get font data, width and height */
 #include "vidconsole_internal.h"
 
-/**
- * struct console_ctx - context for the normal console
- *
- * @com:	Common fields from the vidconsole uclass
- */
-struct console_ctx {
-	struct vidconsole_ctx com;
-};
 
 static int console_set_row(struct udevice *dev, uint row, int clr)
 {
@@ -177,20 +169,6 @@  static int console_putc_xy(struct udevice *dev, void *vctx, uint x_frac,
 	return console_normal_putc_xy(dev, vctx, x_frac, y, cp);
 }
 
-static int console_simple_ctx_new(struct udevice *dev, void **ctxp)
-{
-	struct console_ctx *ctx;
-
-	ctx = malloc(sizeof(*ctx));
-	if (!ctx)
-		return -ENOMEM;
-
-	memset(ctx, '\0', sizeof(*ctx));
-	*ctxp = ctx;
-
-	return 0;
-}
-
 struct vidconsole_ops console_ops = {
 	.putc_xy	= console_putc_xy,
 	.move_rows	= console_move_rows,
diff --git a/drivers/video/console_rotate.c b/drivers/video/console_rotate.c
index 42c9de888d8..77c814fa09e 100644
--- a/drivers/video/console_rotate.c
+++ b/drivers/video/console_rotate.c
@@ -294,6 +294,7 @@  struct vidconsole_ops console_ops_1 = {
 	.get_font_size	= console_simple_get_font_size,
 	.get_font	= console_simple_get_font,
 	.select_font	= console_simple_select_font,
+	.ctx_new	= console_simple_ctx_new,
 };
 
 struct vidconsole_ops console_ops_2 = {
@@ -303,6 +304,7 @@  struct vidconsole_ops console_ops_2 = {
 	.get_font_size	= console_simple_get_font_size,
 	.get_font	= console_simple_get_font,
 	.select_font	= console_simple_select_font,
+	.ctx_new	= console_simple_ctx_new,
 };
 
 struct vidconsole_ops console_ops_3 = {
@@ -312,13 +314,13 @@  struct vidconsole_ops console_ops_3 = {
 	.get_font_size	= console_simple_get_font_size,
 	.get_font	= console_simple_get_font,
 	.select_font	= console_simple_select_font,
+	.ctx_new	= console_simple_ctx_new,
 };
 
 U_BOOT_DRIVER(vidconsole_1) = {
 	.name	= "vidconsole1",
 	.id	= UCLASS_VIDEO_CONSOLE,
 	.ops	= &console_ops_1,
-	.probe	= console_probe,
 	.priv_auto	= sizeof(struct console_simple_priv),
 };
 
@@ -326,7 +328,6 @@  U_BOOT_DRIVER(vidconsole_2) = {
 	.name	= "vidconsole2",
 	.id	= UCLASS_VIDEO_CONSOLE,
 	.ops	= &console_ops_2,
-	.probe	= console_probe,
 	.priv_auto	= sizeof(struct console_simple_priv),
 };
 
@@ -334,6 +335,5 @@  U_BOOT_DRIVER(vidconsole_3) = {
 	.name	= "vidconsole3",
 	.id	= UCLASS_VIDEO_CONSOLE,
 	.ops	= &console_ops_3,
-	.probe	= console_probe,
 	.priv_auto	= sizeof(struct console_simple_priv),
 };
diff --git a/drivers/video/console_truetype.c b/drivers/video/console_truetype.c
index 4cf7ffebef3..25cc8241bf7 100644
--- a/drivers/video/console_truetype.c
+++ b/drivers/video/console_truetype.c
@@ -1143,16 +1143,15 @@  static int truetype_nominal(struct udevice *dev, const char *name, uint size,
 	return 0;
 }
 
-static int truetype_ctx_new(struct udevice *dev, void **ctxp)
+static int truetype_ctx_new(struct udevice *dev, void *vctx)
 {
-	struct console_tt_ctx *ctx;
+	struct console_tt_priv *priv = dev_get_priv(dev);
+	struct console_tt_ctx *ctx = vctx;
 
-	ctx = malloc(sizeof(*ctx));
-	if (!ctx)
-		return -ENOMEM;
+	/* use the first set of metrics by default */
+	ctx->cur_met = &priv->metrics[0];
 
-	memset(ctx, '\0', sizeof(*ctx));
-	*ctxp = ctx;
+	select_metrics(dev, ctx, ctx->cur_met);
 
 	return 0;
 }
@@ -1256,7 +1255,6 @@  static int truetype_mark_start(struct udevice *dev, void *vctx)
 
 static int console_truetype_probe(struct udevice *dev)
 {
-	struct console_tt_ctx *ctx = vidconsole_ctx(dev);
 	struct console_tt_priv *priv = dev_get_priv(dev);
 	struct udevice *vid_dev = dev->parent;
 	struct video_priv *vid_priv = dev_get_uclass_priv(vid_dev);
@@ -1289,9 +1287,6 @@  static int console_truetype_probe(struct udevice *dev)
 	ret = truetype_add_metrics(dev, tab->name, font_size, tab->begin);
 	if (ret < 0)
 		return log_msg_ret("add", ret);
-	ctx->cur_met = &priv->metrics[ret];
-
-	select_metrics(dev, ctx, &priv->metrics[ret]);
 
 	debug("%s: ready\n", __func__);
 
diff --git a/drivers/video/vidconsole-uclass.c b/drivers/video/vidconsole-uclass.c
index 147063c4d38..b6bd3133037 100644
--- a/drivers/video/vidconsole-uclass.c
+++ b/drivers/video/vidconsole-uclass.c
@@ -713,10 +713,14 @@  int vidconsole_nominal(struct udevice *dev, const char *name, uint size,
 
 int vidconsole_ctx_new(struct udevice *dev, void **ctxp)
 {
+	struct udevice *vid = dev->parent;
+	struct video_priv *vid_priv = dev_get_uclass_priv(vid);
+	struct vidconsole_uc_plat *plat = dev_get_uclass_plat(dev);
 	struct vidconsole_priv *priv = dev_get_uclass_priv(dev);
 	struct vidconsole_ops *ops = vidconsole_get_ops(dev);
+	struct vidconsole_ctx *ctx;
+	int ret = -ENOMEM, size;
 	void **ptr;
-	int ret;
 
 	if (!ops->ctx_new)
 		return -ENOSYS;
@@ -726,14 +730,35 @@  int vidconsole_ctx_new(struct udevice *dev, void **ctxp)
 	if (!ptr)
 		return -ENOMEM;
 
-	ret = ops->ctx_new(dev, ptr);
-	if (ret) {
-		priv->ctx_list.count--;
-		return ret;
+	size = plat->ctx_size ?: sizeof(struct vidconsole_ctx);
+	ctx = calloc(1, size);
+	if (!ctx)
+		goto err_alloc;
+	*ptr = ctx;
+
+	if (CONFIG_IS_ENABLED(CURSOR) && xpl_phase() == PHASE_BOARD_R) {
+		ret = console_alloc_cursor(dev, &ctx->curs);
+		if (ret)
+			goto err_curs;
 	}
-	*ctxp = *ptr;
+
+	ctx->xsize_frac = VID_TO_POS(vid_priv->xsize);
+
+	ret = ops->ctx_new(dev, ctx);
+	if (ret)
+		goto err_new;
+	*ctxp = ctx;
 
 	return 0;
+
+err_new:
+	console_free_cursor(&ctx->curs);
+err_curs:
+err_alloc:
+	priv->ctx_list.count--;
+	free(ctx);
+
+	return ret;
 }
 
 /**
@@ -922,23 +947,9 @@  void vidconsole_pop_colour(struct udevice *dev, struct vidconsole_colour *old)
 /* Set up the number of rows and colours (rotated drivers override this) */
 static int vidconsole_pre_probe(struct udevice *dev)
 {
-	struct vidconsole_uc_plat *plat = dev_get_uclass_plat(dev);
 	struct vidconsole_priv *priv = dev_get_uclass_priv(dev);
-	struct udevice *vid = dev->parent;
-	struct video_priv *vid_priv = dev_get_uclass_priv(vid);
-	struct vidconsole_ctx *ctx;
-	uint size;
-
-	size = plat->ctx_size ?: sizeof(struct vidconsole_ctx);
-	ctx = calloc(1, size);
-	if (!ctx)
-		return -ENOMEM;
-	priv->ctx = ctx;
-
-	ctx->xsize_frac = VID_TO_POS(vid_priv->xsize);
 
 	alist_init_struct(&priv->ctx_list, void *);
-	alist_add(&priv->ctx_list, ctx);
 
 	return 0;
 }
@@ -947,15 +958,14 @@  static int vidconsole_pre_probe(struct udevice *dev)
 static int vidconsole_post_probe(struct udevice *dev)
 {
 	struct vidconsole_priv *priv = dev_get_uclass_priv(dev);
-	struct vidconsole_ctx *ctx = vidconsole_ctx_from_priv(priv);
 	struct stdio_dev *sdev = &priv->sdev;
+	struct vidconsole_ctx *ctx;
 	int ret;
 
-	if (CONFIG_IS_ENABLED(CURSOR) && xpl_phase() == PHASE_BOARD_R) {
-		ret = console_alloc_cursor(dev, &ctx->curs);
-		if (ret)
-			return ret;
-	}
+	ret = vidconsole_ctx_new(dev, (void **)&ctx);
+	if (ret)
+		return ret;
+	priv->ctx = ctx;
 
 	if (!ctx->tab_width_frac)
 		ctx->tab_width_frac = VID_TO_POS(ctx->x_charsize) * 8;
@@ -1049,7 +1059,7 @@  void vidconsole_set_bitmap_font(struct udevice *dev, struct vidconsole_ctx *ctx,
 	} else {
 		ctx->cols = vid_priv->xsize / fontdata->width;
 		ctx->rows = vid_priv->ysize / fontdata->height;
-		/* xsize_frac is set in vidconsole_pre_probe() */
+		ctx->xsize_frac = VID_TO_POS(vid_priv->xsize);
 	}
 	ctx->xstart_frac = 0;
 }
diff --git a/drivers/video/vidconsole_internal.h b/drivers/video/vidconsole_internal.h
index b5ffdfad4da..439192ecc1e 100644
--- a/drivers/video/vidconsole_internal.h
+++ b/drivers/video/vidconsole_internal.h
@@ -8,6 +8,7 @@ 
 
 #include <charset.h>
 #include <config.h>
+#include <video_console.h>
 
 struct udevice;
 struct vidconsole_cursor;
@@ -25,6 +26,15 @@  struct console_simple_priv {
 	struct video_fontdata *fontdata;
 };
 
+/**
+ * struct console_ctx - context for the normal console
+ *
+ * @com:	Common fields from the vidconsole uclass
+ */
+struct console_ctx {
+	struct vidconsole_ctx com;
+};
+
 /**
  * Checks if bits per pixel supported.
  *
@@ -237,3 +247,15 @@  static inline u8 console_utf_to_cp437(int codepoint)
 	}
 	return codepoint;
 }
+
+/**
+ * console_simple_ctx_new() - Set up a new context for bitmap-font consoles
+ *
+ * Initialises the context with the default bitmap font. This is the ctx_new()
+ * method for bitmap-font console drivers.
+ *
+ * @dev: Vidconsole device
+ * @ctx: Context to initialise (allocated by the uclass)
+ * Return: 0 on success, -ve on error
+ */
+int console_simple_ctx_new(struct udevice *dev, void *ctx);
diff --git a/include/video_console.h b/include/video_console.h
index 8d2f0510534..c047d45cf53 100644
--- a/include/video_console.h
+++ b/include/video_console.h
@@ -384,16 +384,16 @@  struct vidconsole_ops {
 		       uint num_chars, struct vidconsole_bbox *bbox);
 
 	/**
-	 * ctx_new() - Create a new context for a client
+	 * ctx_new() - Initialise a new context for a client
 	 *
-	 * Allocates and initialises a context for a client of the vidconsole.
-	 * The driver determines what information is stored in the context.
+	 * Initialises driver-specific fields of a pre-allocated context. The
+	 * base vidconsole_ctx fields are already initialised by the uclass.
 	 *
 	 * @dev: Console device to use
-	 * @ctxp: Returns new context, on success
-	 * Return: 0 on success, -ENOMEM if out of memory
+	 * @ctx: Pre-allocated context to initialise
+	 * Return: 0 on success, -ve on error
 	 */
-	int (*ctx_new)(struct udevice *dev, void **ctxp);
+	int (*ctx_new)(struct udevice *dev, void *ctx);
 
 	/**
 	 * ctx_dispose() - Dispose of a context