dpms.c revision 199230
1139749Simp/*- 21817Sdg * Copyright (c) 2008 Yahoo!, Inc. 31817Sdg * All rights reserved. 41817Sdg * Written by: John Baldwin <jhb@FreeBSD.org> 51817Sdg * 61817Sdg * Redistribution and use in source and binary forms, with or without 71817Sdg * modification, are permitted provided that the following conditions 81817Sdg * are met: 950477Speter * 1. Redistributions of source code must retain the above copyright 101817Sdg * notice, this list of conditions and the following disclaimer. 111817Sdg * 2. Redistributions in binary form must reproduce the above copyright 128876Srgrimes * notice, this list of conditions and the following disclaimer in the 1343Sdg * documentation and/or other materials provided with the distribution. 14498Sdg * 3. Neither the name of the author nor the names of any co-contributors 15498Sdg * may be used to endorse or promote products derived from this software 16498Sdg * without specific prior written permission. 17808Sdg * 18808Sdg * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19808Sdg * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20808Sdg * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21791Sdg * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22791Sdg * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23791Sdg * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24791Sdg * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25520Sdg * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26520Sdg * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27520Sdg * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28520Sdg * SUCH DAMAGE. 298876Srgrimes */ 3043Sdg 3143Sdg/* 328876Srgrimes * Copyright (c) 2004 Benjamin Close <Benjamin.Close@clearchain.com> 336Sdg * All rights reserved. 346Sdg * 356Sdg * Redistribution and use in source and binary forms, with or without 366Sdg * modification, are permitted provided that the following conditions 376Sdg * are met: 386Sdg * 1. Redistributions of source code must retain the above copyright 396Sdg * notice, this list of conditions and the following disclaimer. 406Sdg * 2. Redistributions in binary form must reproduce the above copyright 416Sdg * notice, this list of conditions and the following disclaimer in the 426Sdg * documentation and/or other materials provided with the distribution. 436Sdg * 446Sdg * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 456Sdg * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 466Sdg * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 476Sdg * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 486Sdg * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 496Sdg * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 506Sdg * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 516Sdg * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 526Sdg * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 536Sdg * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 546Sdg * SUCH DAMAGE. 556Sdg */ 566Sdg 576Sdg/* 586Sdg * Support for managing the display via DPMS for suspend/resume. 596Sdg */ 606Sdg 616Sdg#include <sys/cdefs.h> 626Sdg__FBSDID("$FreeBSD: head/sys/dev/dpms/dpms.c 199230 2009-11-12 18:16:35Z jkim $"); 636Sdg 646Sdg#include <sys/param.h> 656Sdg#include <sys/bus.h> 666Sdg#include <sys/kernel.h> 676Sdg#include <sys/libkern.h> 686Sdg#include <sys/module.h> 696Sdg 706Sdg#include <compat/x86bios/x86bios.h> 716Sdg 726Sdg/* 736Sdg * VESA DPMS States 746Sdg */ 756Sdg#define DPMS_ON 0x00 766Sdg#define DPMS_STANDBY 0x01 776Sdg#define DPMS_SUSPEND 0x02 786Sdg#define DPMS_OFF 0x04 796Sdg#define DPMS_REDUCEDON 0x08 806Sdg 816Sdg#define VBE_DPMS_FUNCTION 0x4F10 826Sdg#define VBE_DPMS_GET_SUPPORTED_STATES 0x00 836Sdg#define VBE_DPMS_GET_STATE 0x02 846Sdg#define VBE_DPMS_SET_STATE 0x01 856Sdg#define VBE_MAJORVERSION_MASK 0x0F 866Sdg#define VBE_MINORVERSION_MASK 0xF0 876Sdg 886Sdgstruct dpms_softc { 896Sdg int dpms_supported_states; 906Sdg int dpms_initial_state; 9150808Skato}; 926Sdg 936Sdgstatic int dpms_attach(device_t); 946Sdgstatic int dpms_detach(device_t); 956Sdgstatic int dpms_get_supported_states(int *); 966Sdgstatic int dpms_get_current_state(int *); 976Sdgstatic void dpms_identify(driver_t *, device_t); 986Sdgstatic int dpms_probe(device_t); 996Sdgstatic int dpms_resume(device_t); 1006Sdgstatic int dpms_set_state(int); 10150808Skatostatic int dpms_suspend(device_t); 1026Sdg 1036Sdgstatic device_method_t dpms_methods[] = { 1046Sdg DEVMETHOD(device_identify, dpms_identify), 1056Sdg DEVMETHOD(device_probe, dpms_probe), 1066Sdg DEVMETHOD(device_attach, dpms_attach), 1076Sdg DEVMETHOD(device_detach, dpms_detach), 1086Sdg DEVMETHOD(device_suspend, dpms_suspend), 1096Sdg DEVMETHOD(device_resume, dpms_resume), 1106Sdg { 0, 0 } 1116Sdg}; 1126Sdg 1136Sdgstatic driver_t dpms_driver = { 1146Sdg "dpms", 1156Sdg dpms_methods, 1166Sdg sizeof(struct dpms_softc), 1176Sdg}; 1186Sdg 1196Sdgstatic devclass_t dpms_devclass; 1206Sdg 1216SdgDRIVER_MODULE(dpms, vgapci, dpms_driver, dpms_devclass, NULL, NULL); 1226SdgMODULE_DEPEND(dpms, x86bios, 1, 1, 1); 1236Sdg 1246Sdgstatic void 1256Sdgdpms_identify(driver_t *driver, device_t parent) 1266Sdg{ 1276Sdg 1286Sdg if (device_get_flags(parent) != 0 && 1296Sdg x86bios_match_device(0xc0000, parent)) 1306Sdg device_add_child(parent, "dpms", 0); 1316Sdg} 1326Sdg 1336Sdgstatic int 1346Sdgdpms_probe(device_t dev) 1356Sdg{ 1366Sdg int error, states; 1376Sdg 1386Sdg error = dpms_get_supported_states(&states); 1396Sdg if (error) 1406Sdg return (error); 1416Sdg device_set_desc(dev, "DPMS suspend/resume"); 1426Sdg device_quiet(dev); 1436Sdg return (BUS_PROBE_DEFAULT); 1446Sdg} 1456Sdg 1466Sdgstatic int 1476Sdgdpms_attach(device_t dev) 1486Sdg{ 1496Sdg struct dpms_softc *sc; 1506Sdg int error; 1516Sdg 1526Sdg sc = device_get_softc(dev); 1536Sdg error = dpms_get_supported_states(&sc->dpms_supported_states); 1546Sdg if (error) 1556Sdg return (error); 1566Sdg error = dpms_get_current_state(&sc->dpms_initial_state); 1576Sdg return (error); 1586Sdg} 1596Sdg 1606Sdgstatic int 1616Sdgdpms_detach(device_t dev) 1626Sdg{ 1636Sdg 1646Sdg return (0); 1656Sdg} 1666Sdg 1676Sdgstatic int 1686Sdgdpms_suspend(device_t dev) 1696Sdg{ 1706Sdg struct dpms_softc *sc; 1716Sdg 1726Sdg sc = device_get_softc(dev); 1736Sdg if ((sc->dpms_supported_states & DPMS_OFF) != 0) 1746Sdg dpms_set_state(DPMS_OFF); 1756Sdg return (0); 1766Sdg} 177150957Simp 1786Sdgstatic int 1796Sdgdpms_resume(device_t dev) 1806Sdg{ 1816Sdg struct dpms_softc *sc; 1826Sdg 1836Sdg sc = device_get_softc(dev); 1846Sdg dpms_set_state(sc->dpms_initial_state); 185150957Simp return (0); 1866Sdg} 1876Sdg 1886Sdgstatic int 1896Sdgdpms_call_bios(int subfunction, int *bh) 1906Sdg{ 1916Sdg x86regs_t regs; 1926Sdg 1936Sdg if (x86bios_get_intr(0x10) == 0) 1946Sdg return (ENXIO); 1956Sdg 1966Sdg x86bios_init_regs(®s); 1976Sdg regs.R_AX = VBE_DPMS_FUNCTION; 1986Sdg regs.R_BL = subfunction; 1996Sdg regs.R_BH = *bh; 2006Sdg x86bios_intr(®s, 0x10); 2016Sdg 2026Sdg if (regs.R_AX != 0x004f) 2036Sdg return (ENXIO); 2046Sdg 2056Sdg *bh = regs.R_BH; 2066Sdg 2076Sdg return (0); 2086Sdg} 2096Sdg 2106Sdgstatic int 2116Sdgdpms_get_supported_states(int *states) 2126Sdg{ 2136Sdg 2146Sdg *states = 0; 2156Sdg return (dpms_call_bios(VBE_DPMS_GET_SUPPORTED_STATES, states)); 2166Sdg} 21713765Smpp 2186Sdgstatic int 2196Sdgdpms_get_current_state(int *state) 2206Sdg{ 2216Sdg 2226Sdg *state = 0; 2236Sdg return (dpms_call_bios(VBE_DPMS_GET_STATE, state)); 2246Sdg} 2256Sdg 2266Sdgstatic int 2276Sdgdpms_set_state(int state) 2286Sdg{ 2296Sdg 2306Sdg return (dpms_call_bios(VBE_DPMS_SET_STATE, &state)); 2316Sdg} 2326Sdg