From owner-freebsd-mobile@FreeBSD.ORG Sun Feb 27 04:31:27 2005 Return-Path: Delivered-To: freebsd-mobile@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 6A6C116A4CF for ; Sun, 27 Feb 2005 04:31:27 +0000 (GMT) Received: from salmon.maths.tcd.ie (salmon.maths.tcd.ie [134.226.81.11]) by mx1.FreeBSD.org (Postfix) with SMTP id 8CF2243D49 for ; Sun, 27 Feb 2005 04:31:26 +0000 (GMT) (envelope-from iedowse@maths.tcd.ie) Received: from walton.maths.tcd.ie by salmon.maths.tcd.ie with SMTP id ; 27 Feb 2005 04:31:25 +0000 (GMT) To: freebsd-mobile@freebsd.org Date: Sun, 27 Feb 2005 04:31:25 +0000 From: Ian Dowse Message-ID: <200502270431.aa10917@salmon.maths.tcd.ie> Subject: Using VESA to restore display settings on resume X-BeenThere: freebsd-mobile@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: Mobile computing with FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 27 Feb 2005 04:31:27 -0000 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 #include #include +#include #include #include #include @@ -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)); }