summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoriedowse <iedowse@FreeBSD.org>2005-02-28 21:06:14 +0000
committeriedowse <iedowse@FreeBSD.org>2005-02-28 21:06:14 +0000
commitd89679b3edb0937fc7ea9449b2fa1ba70233425d (patch)
treef4f23fb6d6f4eebcdd80ad07ed575125d706e712
parentbdce8917686dee18808e2f8f1774daa8b290c49b (diff)
downloadFreeBSD-src-d89679b3edb0937fc7ea9449b2fa1ba70233425d.zip
FreeBSD-src-d89679b3edb0937fc7ea9449b2fa1ba70233425d.tar.gz
Save and restore the VGA state across a suspend-resume cycle. This
is particularly useful when VESA is available (either `options VESA' or load the vesa module), as BIOSes in some notebooks may correctly save and restore LCD panel settings using VESA in cases where calling the video BIOS POST is not effective. On some systems it may also be necessary to set the hw.acpi.reset_video sysctl to 0.
-rw-r--r--sys/dev/fb/vgareg.h1
-rw-r--r--sys/isa/vga_isa.c55
2 files changed, 56 insertions, 0 deletions
diff --git a/sys/dev/fb/vgareg.h b/sys/dev/fb/vgareg.h
index e26c214..4ccef40 100644
--- a/sys/dev/fb/vgareg.h
+++ b/sys/dev/fb/vgareg.h
@@ -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
diff --git a/sys/isa/vga_isa.c b/sys/isa/vga_isa.c
index 033882d..594e3d0 100644
--- a/sys/isa/vga_isa.c
+++ b/sys/isa/vga_isa.c
@@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$");
#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>
@@ -159,6 +160,58 @@ isavga_attach(device_t dev)
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 (bootverbose)
+ device_printf(dev, "saving %d bytes of video state\n", nbytes);
+ if ((*vidsw[sc->adp->va_index]->save_state)(sc->adp, sc->state_buf,
+ nbytes) != 0) {
+ device_printf(dev, "failed to save state (nbytes=%d)\n",
+ nbytes);
+ free(sc->state_buf, M_TEMP);
+ sc->state_buf = NULL;
+ }
+ return (0);
+}
+
+static int
+isavga_resume(device_t dev)
+{
+ vga_softc_t *sc;
+
+ sc = device_get_softc(dev);
+ if (sc->state_buf != NULL) {
+ if ((*vidsw[sc->adp->va_index]->load_state)(sc->adp,
+ sc->state_buf) != 0)
+ device_printf(dev, "failed to reload state\n");
+ free(sc->state_buf, M_TEMP);
+ sc->state_buf = NULL;
+ }
+
+ bus_generic_resume(dev);
+ return 0;
+}
+
#ifdef FB_INSTALL_CDEV
static int
@@ -203,6 +256,8 @@ static device_method_t isavga_methods[] = {
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 }
OpenPOWER on IntegriCloud