mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH v2 0/7] vt: Simplify console-blanking interface
@ 2026-10-16  9:11 Thomas Zimmermann
  2026-10-16  9:11 ` [PATCH v2 1/7] vt: Add con_unblank callback to struct consw Thomas Zimmermann
                   ` (6 more replies)
  0 siblings, 7 replies; 8+ messages in thread
From: Thomas Zimmermann @ 2026-10-16  9:11 UTC (permalink / raw)
  To: gregkh, jirislaby, deller, James.Bottomley, simona
  Cc: linux-kernel, linux-serial, linux-fbdev, linux-parisc,
	sashiko-reviews, Thomas Zimmermann

Update con_blank from struct consw to use enum vesa_blank_mode according
to its intented semantics. Handle unblanking in the separate new callback
con_unblank. Update all consoles.

Some background: the vt subsystem calls con_blank with what at first
appears to be non-sensical value. This is because the blank value and the
type of the blank parameter do not match: con_blank mixes up console blank
state and monitor DPMS levels for power saving in the same argument.
The implementation of con_blank in various consoles suffers from a similar
problem: their interpretation of the given blank value often disagrees with
what the value's type suggests.

Patch 1 adds a new helper con_unblank, which handles all unblanking. This
allows for changing con_blank to only handle blanking. There's support
for both semantics while consoles are being converted.

Patches 2 to 6 implement con_unblank for the individual consoles. With
this, con_blank changes to its new semantics. Each console gets a single
callback for blanking and a single callback for unblanking. Switching a
console between text and graphics mode is currently tied to the blanking
helpers. The mode_switch parameter controls this. As suggested in the
earlier reviews, rather detect a mode switch from the existing state.
The mode_switch parameter is deprecated. A later series might rework the
mode switching entirely.

With all consoles updated, patch 7 removes the old semantics and the
mode_switch parameter.

Tested with vgacon on a SiS 6202 VGA and with fbcon on a Matrox G200
VGA device. The latter also ran fbcon via DRM fbdev emulation. It's easy
to test this with setterm, like this:

  setterm --blank force          # blank
  setterm --blank poke           # unblank
  setterm --powersave powerdown  # set VESA DPMS level 3
  setterm --blank force          # blank and turn off monitor
  setterm --blank poke           # unblank

Blanking and unblanking still works in all tested cases.

Newport and sticon are built-only, due to a lack of test equipment.

v2:
- rewrite series with con_unblank (GregKH)
- drop mode_switch from console implementations

Thomas Zimmermann (7):
  vt: Add con_unblank callback to struct consw
  dummycon: Implement struct consw.con_unblank
  fbcon: Implement struct consw.con_unblank
  newport_con: Implement struct consw.con_unblank
  sticon: Implement struct consw.con_unblank
  vgacon: Implement struct consw.con_unblank
  vt: Remove old-style con_blank

 drivers/tty/vt/vt.c                 |  9 ++---
 drivers/video/console/dummycon.c    | 18 +++++++--
 drivers/video/console/newport_con.c | 27 ++++++-------
 drivers/video/console/sticon.c      | 27 ++++++++-----
 drivers/video/console/vgacon.c      | 60 +++++++++++++++++------------
 drivers/video/fbdev/core/fbcon.c    | 60 ++++++++++++++++++++---------
 include/linux/console.h             | 12 +++---
 7 files changed, 132 insertions(+), 81 deletions(-)


base-commit: b0bd9fb9e92aae2a653efa1d0407daa2aabe99d0
-- 
2.55.0


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH v2 1/7] vt: Add con_unblank callback to struct consw
  2026-10-16  9:11 [PATCH v2 0/7] vt: Simplify console-blanking interface Thomas Zimmermann
@ 2026-10-16  9:11 ` Thomas Zimmermann
  2026-10-16  9:11 ` [PATCH v2 2/7] dummycon: Implement struct consw.con_unblank Thomas Zimmermann
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Thomas Zimmermann @ 2026-10-16  9:11 UTC (permalink / raw)
  To: gregkh, jirislaby, deller, James.Bottomley, simona
  Cc: linux-kernel, linux-serial, linux-fbdev, linux-parisc,
	sashiko-reviews, Thomas Zimmermann

Add struct consw.con_unblank as inverse operation to con_black.

If implemented invoke con_blank to turn the console from blanked to
unblanked. Also update the semantics of con_blank in this case: The
blank parameter of con_blank receives a VESA blank mode from enum
vesa_blank_mode instead of the hybrid unblank/blank values it has
used so far.

With con_unblank not implemented, invoke con_blank for blanking and
unblanking as before.

The old semantics of con_blank will be removed when all consoles
implement con_unblank.

Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
---
 drivers/tty/vt/vt.c     | 30 +++++++++++++++++++++++-------
 include/linux/console.h |  9 ++++++---
 2 files changed, 29 insertions(+), 10 deletions(-)

diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
index 57edf37495a8..04e28166b78d 100644
--- a/drivers/tty/vt/vt.c
+++ b/drivers/tty/vt/vt.c
@@ -4671,7 +4671,10 @@ void do_blank_screen(int entering_gfx)
 	if (console_blanked) {
 		if (blank_state == blank_vesa_wait) {
 			blank_state = blank_off;
-			vc->vc_sw->con_blank(vc, vesa_blank_mode + 1, 0);
+			if (vc->vc_sw->con_unblank)
+				vc->vc_sw->con_blank(vc, vesa_blank_mode, 0);
+			else
+				vc->vc_sw->con_blank(vc, vesa_blank_mode + 1, 0);
 		}
 		return;
 	}
@@ -4680,7 +4683,10 @@ void do_blank_screen(int entering_gfx)
 	if (entering_gfx) {
 		hide_cursor(vc);
 		save_screen(vc);
-		vc->vc_sw->con_blank(vc, VESA_VSYNC_SUSPEND, 1);
+		if (vc->vc_sw->con_unblank)
+			vc->vc_sw->con_blank(vc, VESA_NO_BLANKING, 1);
+		else
+			vc->vc_sw->con_blank(vc, VESA_VSYNC_SUSPEND, 1);
 		console_blanked = fg_console + 1;
 		blank_state = blank_off;
 		set_origin(vc);
@@ -4701,8 +4707,12 @@ void do_blank_screen(int entering_gfx)
 
 	save_screen(vc);
 	/* In case we need to reset origin, blanking hook returns 1 */
-	i = vc->vc_sw->con_blank(vc, vesa_off_interval ? VESA_VSYNC_SUSPEND :
-				 (vesa_blank_mode + 1), 0);
+	if (vc->vc_sw->con_unblank)
+		i = vc->vc_sw->con_blank(vc, vesa_off_interval ? VESA_NO_BLANKING :
+					 vesa_blank_mode, 0);
+	else
+		i = vc->vc_sw->con_blank(vc, vesa_off_interval ? VESA_VSYNC_SUSPEND :
+					 (vesa_blank_mode + 1), 0);
 	console_blanked = fg_console + 1;
 	if (i)
 		set_origin(vc);
@@ -4753,9 +4763,15 @@ void do_unblank_screen(int leaving_gfx)
 	}
 
 	console_blanked = 0;
-	if (vc->vc_sw->con_blank(vc, VESA_NO_BLANKING, leaving_gfx))
-		/* Low-level driver cannot restore -> do it ourselves */
-		update_screen(vc);
+	if (vc->vc_sw->con_unblank) {
+		if (vc->vc_sw->con_unblank(vc))
+			/* Low-level driver cannot restore -> do it ourselves */
+			update_screen(vc);
+	} else {
+		if (vc->vc_sw->con_blank(vc, VESA_NO_BLANKING, leaving_gfx))
+			/* Low-level driver cannot restore -> do it ourselves */
+			update_screen(vc);
+	}
 	if (console_blank_hook)
 		console_blank_hook(0);
 	set_palette(vc);
diff --git a/include/linux/console.h b/include/linux/console.h
index 502d1abe3f50..aadcb6053cb0 100644
--- a/include/linux/console.h
+++ b/include/linux/console.h
@@ -55,9 +55,11 @@ enum vc_intensity;
  *		Invoked by csi_M and printing to the console.
  * @con_switch: notifier about the console switch; it is supposed to return
  *		true if a redraw is needed.
- * @con_blank:  blank/unblank the console. The target mode is passed in @blank.
- *		@mode_switch is set if changing from/to text/graphics. The hook
- *		is supposed to return true if a redraw is needed.
+ * @con_blank:  blank the console. The preferred VESA blank mode is passed in
+ *		@blank. @mode_switch is set if changing from/to text/graphics.
+ *		The hook is supposed to return true if a redraw is needed.
+ * @con_unblank:  unblank the console. The hook is supposed to return true if
+ *		a redraw is needed.
  * @con_font_set: set console @vc font to @font with height @vpitch. @flags can
  *		be %KD_FONT_FLAG_DONT_RECALC. (optional)
  * @con_font_get: fetch the current font on @vc of height @vpitch into @font.
@@ -99,6 +101,7 @@ struct consw {
 	bool	(*con_switch)(struct vc_data *vc);
 	bool	(*con_blank)(struct vc_data *vc, enum vesa_blank_mode blank,
 			     bool mode_switch);
+	bool	(*con_unblank)(struct vc_data *vc);
 	int	(*con_font_set)(struct vc_data *vc,
 				const struct console_font *font,
 				unsigned int vpitch, unsigned int flags);
-- 
2.55.0


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH v2 2/7] dummycon: Implement struct consw.con_unblank
  2026-10-16  9:11 [PATCH v2 0/7] vt: Simplify console-blanking interface Thomas Zimmermann
  2026-10-16  9:11 ` [PATCH v2 1/7] vt: Add con_unblank callback to struct consw Thomas Zimmermann
@ 2026-10-16  9:11 ` Thomas Zimmermann
  2026-10-16  9:11 ` [PATCH v2 3/7] fbcon: " Thomas Zimmermann
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Thomas Zimmermann @ 2026-10-16  9:11 UTC (permalink / raw)
  To: gregkh, jirislaby, deller, James.Bottomley, simona
  Cc: linux-kernel, linux-serial, linux-fbdev, linux-parisc,
	sashiko-reviews, Thomas Zimmermann

Implement con_unblank from struct consw as a duplicate of con_blank.
As dummycon does not do anything, the implementation only returns
true or false to trigger a redraw (or not).

Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
---
 drivers/video/console/dummycon.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/drivers/video/console/dummycon.c b/drivers/video/console/dummycon.c
index 7d02470f19b9..ea34a7e84472 100644
--- a/drivers/video/console/dummycon.c
+++ b/drivers/video/console/dummycon.c
@@ -86,6 +86,11 @@ static bool dummycon_blank(struct vc_data *vc, enum vesa_blank_mode blank,
 	return true;
 }
 
+static bool dummycon_unblank(struct vc_data *vc)
+{
+	return true;
+}
+
 static bool dummycon_switch(struct vc_data *vc)
 {
 	/*
@@ -104,6 +109,12 @@ static bool dummycon_blank(struct vc_data *vc, enum vesa_blank_mode blank,
 {
 	return false;
 }
+
+static bool dummycon_unblank(struct vc_data *vc)
+{
+	return false;
+}
+
 static bool dummycon_switch(struct vc_data *vc)
 {
 	return false;
@@ -155,5 +166,6 @@ const struct consw dummy_con = {
 	.con_scroll =	dummycon_scroll,
 	.con_switch =	dummycon_switch,
 	.con_blank =	dummycon_blank,
+	.con_unblank =	dummycon_unblank,
 };
 EXPORT_SYMBOL_GPL(dummy_con);
-- 
2.55.0


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH v2 3/7] fbcon: Implement struct consw.con_unblank
  2026-10-16  9:11 [PATCH v2 0/7] vt: Simplify console-blanking interface Thomas Zimmermann
  2026-10-16  9:11 ` [PATCH v2 1/7] vt: Add con_unblank callback to struct consw Thomas Zimmermann
  2026-10-16  9:11 ` [PATCH v2 2/7] dummycon: Implement struct consw.con_unblank Thomas Zimmermann
@ 2026-10-16  9:11 ` Thomas Zimmermann
  2026-10-16  9:11 ` [PATCH v2 4/7] newport_con: " Thomas Zimmermann
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Thomas Zimmermann @ 2026-10-16  9:11 UTC (permalink / raw)
  To: gregkh, jirislaby, deller, James.Bottomley, simona
  Cc: linux-kernel, linux-serial, linux-fbdev, linux-parisc,
	sashiko-reviews, Thomas Zimmermann

Implement con_unblank from struct consw with the !blank branches from
fbcon_blank(). The new function is called fbcon_unblank(). Remove the
duplicated code from fbcon_blank().

Fbcon tracks fbdev blank state in par->blank_state using fbdev's FB_BLANK
constants. In fbcon_unblank() the stored value is always FB_BLANK_UNBLANK.
In fbcon_blank(), the new blank state is 1 + plus the VESA blank mode
given in the parameter blank.

fbcon_blank() now disables the cursor worker unconditionally.

Unblanking while switching the console from graphics to text mode
requires setting the display with fb_set_var(). fbcon_unblank() does not
receive the mode_switch flag from its caller, so track the flag with the
par->graphics and vc->vc_num fields. A later update might add a mode-
switching callback to simplify this logic.

Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
---
 drivers/video/fbdev/core/fbcon.c | 56 ++++++++++++++++++++++----------
 1 file changed, 39 insertions(+), 17 deletions(-)

diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c
index 615fa596b7cc..6d564111ebd0 100644
--- a/drivers/video/fbdev/core/fbcon.c
+++ b/drivers/video/fbdev/core/fbcon.c
@@ -2293,32 +2293,53 @@ static bool fbcon_blank(struct vc_data *vc, enum vesa_blank_mode blank,
 	struct fb_info *info = fbcon_info_from_console(vc->vc_num);
 	struct fbcon_par *par = info->fbcon_par;
 
-	if (mode_switch) {
-		struct fb_var_screeninfo var = info->var;
+	if (mode_switch)
+		par->graphics = true;
 
-		par->graphics = 1;
+	if (fbcon_is_active(vc, info)) {
+		int blank_state = 1 + blank; /* convert VESA to FB_BLANK constant */
 
-		if (!blank) {
-			var.activate = FB_ACTIVATE_NOW | FB_ACTIVATE_FORCE |
-				FB_ACTIVATE_KD_TEXT;
-			fb_set_var(info, &var);
-			par->graphics = 0;
-			par->var = info->var;
+		if (par->blank_state != blank_state) {
+			par->blank_state = blank_state;
+			fbcon_cursor(vc, false);
+			par->cursor_flash = false;
+
+			if (fb_blank(info, blank_state))
+				fbcon_generic_blank(vc, info, true);
 		}
 	}
 
+	fbcon_del_cursor_work(info);
+
+	return false;
+}
+
+static bool fbcon_unblank(struct vc_data *vc)
+{
+	struct fb_info *info = fbcon_info_from_console(vc->vc_num);
+	struct fbcon_par *par = info->fbcon_par;
+	bool mode_switch = par->graphics && vc->vc_mode == KD_TEXT;
+
+	if (mode_switch) {
+		struct fb_var_screeninfo var = info->var;
+
+		var.activate = FB_ACTIVATE_NOW | FB_ACTIVATE_FORCE | FB_ACTIVATE_KD_TEXT;
+		fb_set_var(info, &var);
+		par->graphics = false;
+		par->var = info->var;
+	}
+
 	if (fbcon_is_active(vc, info)) {
-		if (par->blank_state != blank) {
-			par->blank_state = blank;
-			fbcon_cursor(vc, !blank);
-			par->cursor_flash = (!blank);
+		if (par->blank_state != FB_BLANK_UNBLANK) {
+			par->blank_state = FB_BLANK_UNBLANK;
+			fbcon_cursor(vc, true);
+			par->cursor_flash = true;
 
-			if (fb_blank(info, blank))
-				fbcon_generic_blank(vc, info, blank);
+			if (fb_blank(info, FB_BLANK_UNBLANK))
+				fbcon_generic_blank(vc, info, false);
 		}
 
-		if (!blank)
-			update_screen(vc);
+		update_screen(vc);
 	}
 
 	if (mode_switch || !fbcon_is_active(vc, info) || par->blank_state != FB_BLANK_UNBLANK)
@@ -3168,6 +3189,7 @@ static const struct consw fb_con = {
 	.con_scroll 		= fbcon_scroll,
 	.con_switch 		= fbcon_switch,
 	.con_blank 		= fbcon_blank,
+	.con_unblank		= fbcon_unblank,
 	.con_font_set 		= fbcon_set_font,
 	.con_font_get 		= fbcon_get_font,
 	.con_font_default	= fbcon_set_def_font,
-- 
2.55.0


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH v2 4/7] newport_con: Implement struct consw.con_unblank
  2026-10-16  9:11 [PATCH v2 0/7] vt: Simplify console-blanking interface Thomas Zimmermann
                   ` (2 preceding siblings ...)
  2026-10-16  9:11 ` [PATCH v2 3/7] fbcon: " Thomas Zimmermann
@ 2026-10-16  9:11 ` Thomas Zimmermann
  2026-10-16  9:11 ` [PATCH v2 5/7] sticon: " Thomas Zimmermann
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Thomas Zimmermann @ 2026-10-16  9:11 UTC (permalink / raw)
  To: gregkh, jirislaby, deller, James.Bottomley, simona
  Cc: linux-kernel, linux-serial, linux-fbdev, linux-parisc,
	sashiko-reviews, Thomas Zimmermann

Implement con_unblank from struct consw with the VESA_NO_BLANKING
branch from newport_blank(). Remove that code from the blank helper.

Both helpers, newport_blank() and newport_unbank(), clear or set
a single flag in a hardware register. No further VESA DPMS blanking
is supported.

Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
---
 drivers/video/console/newport_con.c | 24 +++++++++++++-----------
 1 file changed, 13 insertions(+), 11 deletions(-)

diff --git a/drivers/video/console/newport_con.c b/drivers/video/console/newport_con.c
index ecbbe2e4e2a6..c617a9a27e4c 100644
--- a/drivers/video/console/newport_con.c
+++ b/drivers/video/console/newport_con.c
@@ -481,17 +481,18 @@ static bool newport_blank(struct vc_data *c, enum vesa_blank_mode blank,
 {
 	unsigned short treg;
 
-	if (blank == VESA_NO_BLANKING) {
-		/* unblank console */
-		treg = newport_vc2_get(npregs, VC2_IREG_CONTROL);
-		newport_vc2_set(npregs, VC2_IREG_CONTROL,
-				(treg | VC2_CTRL_EDISP));
-	} else {
-		/* blank console */
-		treg = newport_vc2_get(npregs, VC2_IREG_CONTROL);
-		newport_vc2_set(npregs, VC2_IREG_CONTROL,
-				(treg & ~(VC2_CTRL_EDISP)));
-	}
+	treg = newport_vc2_get(npregs, VC2_IREG_CONTROL);
+	newport_vc2_set(npregs, VC2_IREG_CONTROL, (treg & ~(VC2_CTRL_EDISP)));
+
+	return true;
+}
+
+static bool newport_unblank(struct vc_data *c)
+{
+	unsigned short treg;
+
+	treg = newport_vc2_get(npregs, VC2_IREG_CONTROL);
+	newport_vc2_set(npregs, VC2_IREG_CONTROL, (treg | VC2_CTRL_EDISP));
 
 	return true;
 }
@@ -666,6 +667,7 @@ const struct consw newport_con = {
 	.con_scroll	  = newport_scroll,
 	.con_switch	  = newport_switch,
 	.con_blank	  = newport_blank,
+	.con_unblank	  = newport_unblank,
 	.con_font_set	  = newport_font_set,
 	.con_font_default = newport_font_default,
 	.con_save_screen  = newport_save_screen
-- 
2.55.0


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH v2 5/7] sticon: Implement struct consw.con_unblank
  2026-10-16  9:11 [PATCH v2 0/7] vt: Simplify console-blanking interface Thomas Zimmermann
                   ` (3 preceding siblings ...)
  2026-10-16  9:11 ` [PATCH v2 4/7] newport_con: " Thomas Zimmermann
@ 2026-10-16  9:11 ` Thomas Zimmermann
  2026-10-16  9:11 ` [PATCH v2 6/7] vgacon: " Thomas Zimmermann
  2026-10-16  9:11 ` [PATCH v2 7/7] vt: Remove old-style con_blank Thomas Zimmermann
  6 siblings, 0 replies; 8+ messages in thread
From: Thomas Zimmermann @ 2026-10-16  9:11 UTC (permalink / raw)
  To: gregkh, jirislaby, deller, James.Bottomley, simona
  Cc: linux-kernel, linux-serial, linux-fbdev, linux-parisc,
	sashiko-reviews, Thomas Zimmermann

Implement con_unblank from struct consw. The new function is called
sticon_unblank(). Remove the related code from sticon_blank().

Sticon uses the global state vga_is_gfx in several places to test if
the console runs in text or graphics mode. Track the mode switches in
sticon_blank() and sticon_unblank(). As sticon_unblank() does not have
a mode_switch parameter, derive the value from vga_is_gfx and vc_mode.

There is no display unblanking in sticon: only return true to redraw
the console.

Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
---
 drivers/video/console/sticon.c | 22 ++++++++++++++--------
 1 file changed, 14 insertions(+), 8 deletions(-)

diff --git a/drivers/video/console/sticon.c b/drivers/video/console/sticon.c
index 6f58e6a9e76a..0d882ea6b37f 100644
--- a/drivers/video/console/sticon.c
+++ b/drivers/video/console/sticon.c
@@ -302,17 +302,22 @@ static bool sticon_switch(struct vc_data *conp)
 static bool sticon_blank(struct vc_data *c, enum vesa_blank_mode blank,
 			 bool mode_switch)
 {
-    if (blank == VESA_NO_BLANKING) {
+	sti_clear(sticon_sti, 0, 0, c->vc_rows, c->vc_cols, BLANK, font_data[c->vc_num]);
+
 	if (mode_switch)
-	    vga_is_gfx = 0;
+		vga_is_gfx = 1;
+
 	return true;
-    }
-    sti_clear(sticon_sti, 0, 0, c->vc_rows, c->vc_cols, BLANK,
-	      font_data[c->vc_num]);
-    if (mode_switch)
-	vga_is_gfx = 1;
+}
 
-    return true;
+static bool sticon_unblank(struct vc_data *c)
+{
+	bool mode_switch = vga_is_gfx && c->vc_mode == KD_TEXT;
+
+	if (mode_switch)
+		vga_is_gfx = 0;
+
+	return true;
 }
 
 static u8 sticon_build_attr(struct vc_data *conp, u8 color,
@@ -356,6 +361,7 @@ static const struct consw sti_con = {
 	.con_scroll		= sticon_scroll,
 	.con_switch		= sticon_switch,
 	.con_blank		= sticon_blank,
+	.con_unblank		= sticon_unblank,
 	.con_font_set		= sticon_font_set,
 	.con_font_default	= sticon_font_default,
 	.con_build_attr		= sticon_build_attr,
-- 
2.55.0


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH v2 6/7] vgacon: Implement struct consw.con_unblank
  2026-10-16  9:11 [PATCH v2 0/7] vt: Simplify console-blanking interface Thomas Zimmermann
                   ` (4 preceding siblings ...)
  2026-10-16  9:11 ` [PATCH v2 5/7] sticon: " Thomas Zimmermann
@ 2026-10-16  9:11 ` Thomas Zimmermann
  2026-10-16  9:11 ` [PATCH v2 7/7] vt: Remove old-style con_blank Thomas Zimmermann
  6 siblings, 0 replies; 8+ messages in thread
From: Thomas Zimmermann @ 2026-10-16  9:11 UTC (permalink / raw)
  To: gregkh, jirislaby, deller, James.Bottomley, simona
  Cc: linux-kernel, linux-serial, linux-fbdev, linux-parisc,
	sashiko-reviews, Thomas Zimmermann

Implement con_unblank from struct consw with the VESA_NO_BLANKING
case from vgacon_blank(). The new function is called vgacon_unblank().
Remove the duplicated code from vgacon_blank().

Vgacon uses the global state vga_is_gfx in several places to test if
the console runs on text or graphics mode. Track the mode switches in
vgacon_blank() and vga_unblank(). As vgacon_unblank() does not have
a mode_switch parameter, derive the value from vga_is_gfx and vc_mode.

Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
---
 drivers/video/console/vgacon.c | 53 ++++++++++++++++++++--------------
 1 file changed, 31 insertions(+), 22 deletions(-)

diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index 536e7fe4d142..7f52164c30af 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -800,39 +800,47 @@ static void vga_pal_blank(struct vgastate *state)
 static bool vgacon_blank(struct vc_data *c, enum vesa_blank_mode blank,
 			 bool mode_switch)
 {
+	if (mode_switch)
+		vga_is_gfx = true;
+
 	switch (blank) {
-	case VESA_NO_BLANKING:		/* Unblank */
-		if (vga_vesa_blanked) {
-			vga_vesa_unblank(&vgastate);
-			vga_vesa_blanked = VESA_NO_BLANKING;
-		}
-		if (vga_palette_blanked) {
-			vga_set_palette(c, color_table);
-			vga_palette_blanked = false;
-			return 0;
-		}
-		vga_is_gfx = false;
-		/* Tell console.c that it has to restore the screen itself */
-		return 1;
-	case VESA_VSYNC_SUSPEND:	/* Normal blanking */
+	case VESA_NO_BLANKING:	/* Normal blanking */
 		if (!mode_switch && vga_video_type == VIDEO_TYPE_VGAC) {
 			vga_pal_blank(&vgastate);
 			vga_palette_blanked = true;
-			return 0;
+			return false;
 		}
 		vgacon_set_origin(c);
-		scr_memsetw((void *) vga_vram_base, BLANK,
-			    c->vc_screenbuf_size);
-		if (mode_switch)
-			vga_is_gfx = true;
-		return 1;
+		scr_memsetw((void *)vga_vram_base, BLANK, c->vc_screenbuf_size);
+		return true;
 	default:		/* VESA blanking */
 		if (vga_video_type == VIDEO_TYPE_VGAC) {
-			vga_vesa_blank(&vgastate, blank - 1);
+			vga_vesa_blank(&vgastate, blank);
 			vga_vesa_blanked = blank;
 		}
-		return 0;
+		return false;
+	}
+}
+
+static bool vgacon_unblank(struct vc_data *c)
+{
+	bool mode_switch = vga_is_gfx && c->vc_mode == KD_TEXT;
+
+	if (mode_switch)
+		vga_is_gfx = false;
+
+	if (vga_vesa_blanked) {
+		vga_vesa_unblank(&vgastate);
+		vga_vesa_blanked = VESA_NO_BLANKING;
 	}
+
+	if (vga_palette_blanked) {
+		vga_set_palette(c, color_table);
+		vga_palette_blanked = false;
+		return false;
+	}
+
+	return true;
 }
 
 /*
@@ -1201,6 +1209,7 @@ const struct consw vga_con = {
 	.con_scroll = vgacon_scroll,
 	.con_switch = vgacon_switch,
 	.con_blank = vgacon_blank,
+	.con_unblank = vgacon_unblank,
 	.con_font_set = vgacon_font_set,
 	.con_font_get = vgacon_font_get,
 	.con_resize = vgacon_resize,
-- 
2.55.0


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH v2 7/7] vt: Remove old-style con_blank
  2026-10-16  9:11 [PATCH v2 0/7] vt: Simplify console-blanking interface Thomas Zimmermann
                   ` (5 preceding siblings ...)
  2026-10-16  9:11 ` [PATCH v2 6/7] vgacon: " Thomas Zimmermann
@ 2026-10-16  9:11 ` Thomas Zimmermann
  6 siblings, 0 replies; 8+ messages in thread
From: Thomas Zimmermann @ 2026-10-16  9:11 UTC (permalink / raw)
  To: gregkh, jirislaby, deller, James.Bottomley, simona
  Cc: linux-kernel, linux-serial, linux-fbdev, linux-parisc,
	sashiko-reviews, Thomas Zimmermann

All consoles implement the new con_blank plus con_unblank. Remove
the old semantics from con_blank. Always pass a VESA blank mode to
the blank parameter. Remove the mode_switch parameter. For unblanking
call con_unblank unconditionally.

Most consoles handle switches from text to graphics mode in their
con_blank callback. With the mode_switch parameter removed, detect
mode switches from console state plus vc_mode. A later change might
add a callback for switching modes to struct consw.

Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
---
 drivers/tty/vt/vt.c                 | 29 ++++++-----------------------
 drivers/video/console/dummycon.c    |  6 ++----
 drivers/video/console/newport_con.c |  3 +--
 drivers/video/console/sticon.c      |  5 +++--
 drivers/video/console/vgacon.c      |  7 ++++---
 drivers/video/fbdev/core/fbcon.c    |  4 ++--
 include/linux/console.h             |  7 +++----
 7 files changed, 21 insertions(+), 40 deletions(-)

diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
index 04e28166b78d..13914b582cef 100644
--- a/drivers/tty/vt/vt.c
+++ b/drivers/tty/vt/vt.c
@@ -4671,10 +4671,7 @@ void do_blank_screen(int entering_gfx)
 	if (console_blanked) {
 		if (blank_state == blank_vesa_wait) {
 			blank_state = blank_off;
-			if (vc->vc_sw->con_unblank)
-				vc->vc_sw->con_blank(vc, vesa_blank_mode, 0);
-			else
-				vc->vc_sw->con_blank(vc, vesa_blank_mode + 1, 0);
+			vc->vc_sw->con_blank(vc, vesa_blank_mode);
 		}
 		return;
 	}
@@ -4683,10 +4680,7 @@ void do_blank_screen(int entering_gfx)
 	if (entering_gfx) {
 		hide_cursor(vc);
 		save_screen(vc);
-		if (vc->vc_sw->con_unblank)
-			vc->vc_sw->con_blank(vc, VESA_NO_BLANKING, 1);
-		else
-			vc->vc_sw->con_blank(vc, VESA_VSYNC_SUSPEND, 1);
+		vc->vc_sw->con_blank(vc, VESA_NO_BLANKING);
 		console_blanked = fg_console + 1;
 		blank_state = blank_off;
 		set_origin(vc);
@@ -4707,12 +4701,7 @@ void do_blank_screen(int entering_gfx)
 
 	save_screen(vc);
 	/* In case we need to reset origin, blanking hook returns 1 */
-	if (vc->vc_sw->con_unblank)
-		i = vc->vc_sw->con_blank(vc, vesa_off_interval ? VESA_NO_BLANKING :
-					 vesa_blank_mode, 0);
-	else
-		i = vc->vc_sw->con_blank(vc, vesa_off_interval ? VESA_VSYNC_SUSPEND :
-					 (vesa_blank_mode + 1), 0);
+	i = vc->vc_sw->con_blank(vc, vesa_off_interval ? VESA_NO_BLANKING : vesa_blank_mode);
 	console_blanked = fg_console + 1;
 	if (i)
 		set_origin(vc);
@@ -4763,15 +4752,9 @@ void do_unblank_screen(int leaving_gfx)
 	}
 
 	console_blanked = 0;
-	if (vc->vc_sw->con_unblank) {
-		if (vc->vc_sw->con_unblank(vc))
-			/* Low-level driver cannot restore -> do it ourselves */
-			update_screen(vc);
-	} else {
-		if (vc->vc_sw->con_blank(vc, VESA_NO_BLANKING, leaving_gfx))
-			/* Low-level driver cannot restore -> do it ourselves */
-			update_screen(vc);
-	}
+	if (vc->vc_sw->con_unblank(vc))
+		/* Low-level driver cannot restore -> do it ourselves */
+		update_screen(vc);
 	if (console_blank_hook)
 		console_blank_hook(0);
 	set_palette(vc);
diff --git a/drivers/video/console/dummycon.c b/drivers/video/console/dummycon.c
index ea34a7e84472..a206a3de9f4d 100644
--- a/drivers/video/console/dummycon.c
+++ b/drivers/video/console/dummycon.c
@@ -79,8 +79,7 @@ static void dummycon_putcs(struct vc_data *vc, const u16 *s, unsigned int count,
 	raw_notifier_call_chain(&dummycon_output_nh, 0, NULL);
 }
 
-static bool dummycon_blank(struct vc_data *vc, enum vesa_blank_mode blank,
-			   bool mode_switch)
+static bool dummycon_blank(struct vc_data *vc, enum vesa_blank_mode blank)
 {
 	/* Redraw, so that we get putc(s) for output done while blanked */
 	return true;
@@ -104,8 +103,7 @@ static void dummycon_putc(struct vc_data *vc, u16 c, unsigned int y,
 			  unsigned int x) { }
 static void dummycon_putcs(struct vc_data *vc, const u16 *s, unsigned int count,
 			   unsigned int ypos, unsigned int xpos) { }
-static bool dummycon_blank(struct vc_data *vc, enum vesa_blank_mode blank,
-			   bool mode_switch)
+static bool dummycon_blank(struct vc_data *vc, enum vesa_blank_mode blank)
 {
 	return false;
 }
diff --git a/drivers/video/console/newport_con.c b/drivers/video/console/newport_con.c
index c617a9a27e4c..5b2d927fccbc 100644
--- a/drivers/video/console/newport_con.c
+++ b/drivers/video/console/newport_con.c
@@ -476,8 +476,7 @@ static bool newport_switch(struct vc_data *vc)
 	return true;
 }
 
-static bool newport_blank(struct vc_data *c, enum vesa_blank_mode blank,
-			  bool mode_switch)
+static bool newport_blank(struct vc_data *c, enum vesa_blank_mode blank)
 {
 	unsigned short treg;
 
diff --git a/drivers/video/console/sticon.c b/drivers/video/console/sticon.c
index 0d882ea6b37f..fb0a8aa4c2bc 100644
--- a/drivers/video/console/sticon.c
+++ b/drivers/video/console/sticon.c
@@ -299,9 +299,10 @@ static bool sticon_switch(struct vc_data *conp)
     return true;	/* needs refreshing */
 }
 
-static bool sticon_blank(struct vc_data *c, enum vesa_blank_mode blank,
-			 bool mode_switch)
+static bool sticon_blank(struct vc_data *c, enum vesa_blank_mode blank)
 {
+	bool mode_switch = !vga_is_gfx && c->vc_mode == KD_GRAPHICS;
+
 	sti_clear(sticon_sti, 0, 0, c->vc_rows, c->vc_cols, BLANK, font_data[c->vc_num]);
 
 	if (mode_switch)
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index 7f52164c30af..6463fb7676c5 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -797,15 +797,16 @@ static void vga_pal_blank(struct vgastate *state)
 	}
 }
 
-static bool vgacon_blank(struct vc_data *c, enum vesa_blank_mode blank,
-			 bool mode_switch)
+static bool vgacon_blank(struct vc_data *c, enum vesa_blank_mode blank)
 {
+	bool mode_switch = !vga_is_gfx && c->vc_mode == KD_GRAPHICS;
+
 	if (mode_switch)
 		vga_is_gfx = true;
 
 	switch (blank) {
 	case VESA_NO_BLANKING:	/* Normal blanking */
-		if (!mode_switch && vga_video_type == VIDEO_TYPE_VGAC) {
+		if (c->vc_mode == KD_TEXT && vga_video_type == VIDEO_TYPE_VGAC) {
 			vga_pal_blank(&vgastate);
 			vga_palette_blanked = true;
 			return false;
diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c
index 6d564111ebd0..c9a8fb49c06b 100644
--- a/drivers/video/fbdev/core/fbcon.c
+++ b/drivers/video/fbdev/core/fbcon.c
@@ -2287,11 +2287,11 @@ static void fbcon_generic_blank(struct vc_data *vc, struct fb_info *info,
 	}
 }
 
-static bool fbcon_blank(struct vc_data *vc, enum vesa_blank_mode blank,
-			bool mode_switch)
+static bool fbcon_blank(struct vc_data *vc, enum vesa_blank_mode blank)
 {
 	struct fb_info *info = fbcon_info_from_console(vc->vc_num);
 	struct fbcon_par *par = info->fbcon_par;
+	bool mode_switch = !par->graphics && vc->vc_mode == KD_GRAPHICS;
 
 	if (mode_switch)
 		par->graphics = true;
diff --git a/include/linux/console.h b/include/linux/console.h
index aadcb6053cb0..b59b6ac0c01e 100644
--- a/include/linux/console.h
+++ b/include/linux/console.h
@@ -56,8 +56,8 @@ enum vc_intensity;
  * @con_switch: notifier about the console switch; it is supposed to return
  *		true if a redraw is needed.
  * @con_blank:  blank the console. The preferred VESA blank mode is passed in
- *		@blank. @mode_switch is set if changing from/to text/graphics.
- *		The hook is supposed to return true if a redraw is needed.
+ *		@blank. The hook is supposed to return true if a redraw is
+ *		needed.
  * @con_unblank:  unblank the console. The hook is supposed to return true if
  *		a redraw is needed.
  * @con_font_set: set console @vc font to @font with height @vpitch. @flags can
@@ -99,8 +99,7 @@ struct consw {
 			unsigned int bottom, enum con_scroll dir,
 			unsigned int lines);
 	bool	(*con_switch)(struct vc_data *vc);
-	bool	(*con_blank)(struct vc_data *vc, enum vesa_blank_mode blank,
-			     bool mode_switch);
+	bool	(*con_blank)(struct vc_data *vc, enum vesa_blank_mode blank);
 	bool	(*con_unblank)(struct vc_data *vc);
 	int	(*con_font_set)(struct vc_data *vc,
 				const struct console_font *font,
-- 
2.55.0


^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2026-10-16  9:34 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-16  9:11 [PATCH v2 0/7] vt: Simplify console-blanking interface Thomas Zimmermann
2026-10-16  9:11 ` [PATCH v2 1/7] vt: Add con_unblank callback to struct consw Thomas Zimmermann
2026-10-16  9:11 ` [PATCH v2 2/7] dummycon: Implement struct consw.con_unblank Thomas Zimmermann
2026-10-16  9:11 ` [PATCH v2 3/7] fbcon: " Thomas Zimmermann
2026-10-16  9:11 ` [PATCH v2 4/7] newport_con: " Thomas Zimmermann
2026-10-16  9:11 ` [PATCH v2 5/7] sticon: " Thomas Zimmermann
2026-10-16  9:11 ` [PATCH v2 6/7] vgacon: " Thomas Zimmermann
2026-10-16  9:11 ` [PATCH v2 7/7] vt: Remove old-style con_blank Thomas Zimmermann

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®