Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 27 Feb 2005 04:31:25 +0000
From:      Ian Dowse <iedowse@maths.tcd.ie>
To:        freebsd-mobile@freebsd.org
Subject:   Using VESA to restore display settings on resume
Message-ID:  <200502270431.aa10917@salmon.maths.tcd.ie>

next in thread | raw e-mail | index | archive | help

It's possible that the experimantal patch below may help on some
notebooks where the display does not recover from a suspend-resume
cycle. It makes use of the VESA BIOS to save the display settings
before the system suspends and then restores them on resume. The
patch is against -CURRENT, but might apply against RELENG_5 without
too much trouble.

I have a JVC laptop here where this is the only way I have found
so far to bring the LCD back to life after resuming, so maybe it
will help on other systems too.

To test it, apply the patch and rebuild your kernel + modules. You
need to either have 'options VESA' in the kernel config or else
load the vesa module. It may also be worth trying with the
hw.acpi.reset_video sysctl set to 0, since rerunning the VGA POST
should be unnecessary.

Ian

Patch also at: http://people.freebsd.org/~iedowse/vesa_restore.diff

Index: dev/fb/vgareg.h
===================================================================
RCS file: /dump/FreeBSD-CVS/src/sys/dev/fb/vgareg.h,v
retrieving revision 1.7
diff -u -r1.7 vgareg.h
--- dev/fb/vgareg.h	16 Jun 2004 09:46:43 -0000	1.7
+++ dev/fb/vgareg.h	27 Feb 2005 02:37:20 -0000
@@ -69,6 +69,7 @@
 struct video_adapter;
 typedef struct vga_softc {
 	struct video_adapter	*adp;
+	void			*state_buf;
 #ifdef FB_INSTALL_CDEV
 	genfb_softc_t		gensc;
 #endif
Index: isa/vga_isa.c
===================================================================
RCS file: /dump/FreeBSD-CVS/src/sys/isa/vga_isa.c,v
retrieving revision 1.31
diff -u -r1.31 vga_isa.c
--- isa/vga_isa.c	3 Nov 2004 09:07:44 -0000	1.31
+++ isa/vga_isa.c	27 Feb 2005 03:12:08 -0000
@@ -34,6 +34,7 @@
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/kernel.h>
+#include <sys/malloc.h>
 #include <sys/module.h>
 #include <sys/conf.h>
 #include <sys/bus.h>
@@ -160,6 +161,55 @@
 	return 0;
 }
 
+static int
+isavga_suspend(device_t dev)
+{
+	vga_softc_t *sc;
+	int err, nbytes;
+
+	sc = device_get_softc(dev);
+	err = bus_generic_suspend(dev);
+	if (err)
+		return (err);
+
+	/* Save the video state across the suspend. */
+	if (sc->state_buf != NULL) {
+		free(sc->state_buf, M_TEMP);
+		sc->state_buf = NULL;
+	}
+	nbytes = (*vidsw[sc->adp->va_index]->save_state)(sc->adp, NULL, 0);
+	if (nbytes <= 0)
+		return (0);
+	sc->state_buf = malloc(nbytes, M_TEMP, M_NOWAIT | M_ZERO);
+	if (sc->state_buf == NULL)
+		return (0);
+	if ((*vidsw[sc->adp->va_index]->save_state)(sc->adp, sc->state_buf,
+	    nbytes) != 0) {
+		device_printf(dev, "failed to save state\n");
+		free(sc->state_buf, M_TEMP);
+		sc->state_buf = NULL;
+	} else 
+		device_printf(dev, "saved %d bytes of state\n", nbytes);
+	return (0);
+}
+
+static int
+isavga_resume(device_t dev)
+{
+	vga_softc_t *sc;
+
+	sc = device_get_softc(dev);
+	if (sc->state_buf != NULL) {
+		device_printf(dev, "restoring state\n");
+		(*vidsw[sc->adp->va_index]->load_state)(sc->adp, sc->state_buf);
+		free(sc->state_buf, M_TEMP);
+		sc->state_buf = NULL;
+	}
+
+	bus_generic_resume(dev);
+	return 0;
+}
+
 #ifdef FB_INSTALL_CDEV
 
 static int
@@ -204,6 +254,8 @@
 	DEVMETHOD(device_identify,	isavga_identify),
 	DEVMETHOD(device_probe,		isavga_probe),
 	DEVMETHOD(device_attach,	isavga_attach),
+	DEVMETHOD(device_suspend,	isavga_suspend),
+	DEVMETHOD(device_resume,	isavga_resume),
 
 	DEVMETHOD(bus_print_child,	bus_generic_print_child),
 	{ 0, 0 }
Index: i386/isa/vesa.c
===================================================================
RCS file: /dump/FreeBSD-CVS/src/sys/i386/isa/vesa.c,v
retrieving revision 1.47
diff -u -r1.47 vesa.c
--- i386/isa/vesa.c	15 Jul 2004 08:26:05 -0000	1.47
+++ i386/isa/vesa.c	27 Feb 2005 03:54:02 -0000
@@ -423,7 +423,7 @@
 
 	bzero(&vmf, sizeof(vmf));
 	vmf.vmf_eax = 0x4f04; 
-	vmf.vmf_ecx = STATE_MOST;
+	vmf.vmf_ecx = STATE_ALL;
 	vmf.vmf_edx = STATE_SIZE;
 	err = vm86_intcall(0x10, &vmf);
 	if ((err != 0) || (vmf.vmf_ax != 0x4f))
@@ -440,13 +440,14 @@
 
 	bzero(&vmf, sizeof(vmf));
 	vmf.vmf_eax = 0x4f04; 
-	vmf.vmf_ecx = STATE_MOST;
+	vmf.vmf_ecx = STATE_ALL;
 	vmf.vmf_edx = code;	/* STATE_SAVE/STATE_LOAD */
 	buf = (u_char *)vm86_getpage(&vesa_vmcontext, 1);
 	vm86_getptr(&vesa_vmcontext, (vm_offset_t)buf, &vmf.vmf_es, &vmf.vmf_bx);
 	bcopy(p, buf, size);
 
 	err = vm86_datacall(0x10, &vmf, &vesa_vmcontext);
+	bcopy(buf, p, size);
 	return ((err != 0) || (vmf.vmf_ax != 0x4f));
 }




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200502270431.aa10917>