1 /* $OpenBSD: acpiasus.c,v 1.19 2018/07/01 19:40:49 mlarkin Exp $ */ 2 /* $NetBSD: asus_acpi.c,v 1.2.2.2 2008/04/03 12:42:37 mjf Exp $ */ 3 /* 4 * Copyright (c) 2007, 2008 Jared D. McNeill <jmcneill@invisible.ca> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 /* 30 * ASUS ACPI hotkeys driver. 31 */ 32 33 #include <sys/param.h> 34 #include <sys/device.h> 35 #include <sys/systm.h> 36 37 #include <dev/acpi/acpireg.h> 38 #include <dev/acpi/acpivar.h> 39 #include <dev/acpi/acpidev.h> 40 #include <dev/acpi/amltypes.h> 41 #include <dev/acpi/dsdt.h> 42 43 #include "audio.h" 44 #include "wskbd.h" 45 46 struct acpiasus_softc { 47 struct device sc_dev; 48 49 struct acpi_softc *sc_acpi; 50 struct aml_node *sc_devnode; 51 }; 52 53 #define ASUS_NOTIFY_WIRELESSON 0x10 54 #define ASUS_NOTIFY_WIRELESSOFF 0x11 55 #define ASUS_NOTIFY_TASKSWITCH 0x12 56 #define ASUS_NOTIFY_VOLUMEMUTE 0x13 57 #define ASUS_NOTIFY_VOLUMEDOWN 0x14 58 #define ASUS_NOTIFY_VOLUMEUP 0x15 59 #define ASUS_NOTIFY_LCDSWITCHOFF0 0x16 60 #define ASUS_NOTIFY_LCDSWITCHOFF1 0x1a 61 #define ASUS_NOTIFY_LCDCHANGERES 0x1b 62 #define ASUS_NOTIFY_USERDEF0 0x1c 63 #define ASUS_NOTIFY_USERDEF1 0x1d 64 #define ASUS_NOTIFY_BRIGHTNESSLOW 0x20 65 #define ASUS_NOTIFY_BRIGHTNESSHIGH 0x2f 66 #define ASUS_NOTIFY_DISPLAYCYCLEDOWN 0x30 67 #define ASUS_NOTIFY_DISPLAYCYCLEUP 0x32 68 69 #define ASUS_NOTIFY_POWERCONNECT 0x50 70 #define ASUS_NOTIFY_POWERDISCONNECT 0x51 71 72 #define ASUS_SDSP_LCD 0x01 73 #define ASUS_SDSP_CRT 0x02 74 #define ASUS_SDSP_TV 0x04 75 #define ASUS_SDSP_DVI 0x08 76 #define ASUS_SDSP_ALL \ 77 (ASUS_SDSP_LCD | ASUS_SDSP_CRT | ASUS_SDSP_TV | ASUS_SDSP_DVI) 78 79 int acpiasus_match(struct device *, void *, void *); 80 void acpiasus_attach(struct device *, struct device *, void *); 81 void acpiasus_init(struct device *); 82 int acpiasus_notify(struct aml_node *, int, void *); 83 int acpiasus_activate(struct device *, int); 84 85 #if NAUDIO > 0 && NWSKBD > 0 86 extern int wskbd_set_mixervolume(long, long); 87 #endif 88 89 struct cfattach acpiasus_ca = { 90 sizeof(struct acpiasus_softc), acpiasus_match, acpiasus_attach, 91 NULL, acpiasus_activate 92 }; 93 94 struct cfdriver acpiasus_cd = { 95 NULL, "acpiasus", DV_DULL 96 }; 97 98 const char *acpiasus_hids[] = { 99 "ASUS010", 100 NULL 101 }; 102 103 int 104 acpiasus_match(struct device *parent, void *match, void *aux) 105 { 106 struct acpi_attach_args *aa = aux; 107 struct cfdata *cf = match; 108 109 return (acpi_matchhids(aa, acpiasus_hids, cf->cf_driver->cd_name)); 110 } 111 112 void 113 acpiasus_attach(struct device *parent, struct device *self, void *aux) 114 { 115 struct acpiasus_softc *sc = (struct acpiasus_softc *)self; 116 struct acpi_attach_args *aa = aux; 117 118 sc->sc_acpi = (struct acpi_softc *)parent; 119 sc->sc_devnode = aa->aaa_node; 120 121 printf("\n"); 122 123 acpiasus_init(self); 124 125 aml_register_notify(sc->sc_devnode, aa->aaa_dev, 126 acpiasus_notify, sc, ACPIDEV_NOPOLL); 127 } 128 129 void 130 acpiasus_init(struct device *self) 131 { 132 struct acpiasus_softc *sc = (struct acpiasus_softc *)self; 133 struct aml_value cmd; 134 struct aml_value ret; 135 136 bzero(&cmd, sizeof(cmd)); 137 cmd.type = AML_OBJTYPE_INTEGER; 138 cmd.v_integer = 0x40; /* Disable ASL display switching. */ 139 140 if (aml_evalname(sc->sc_acpi, sc->sc_devnode, "INIT", 1, &cmd, &ret)) 141 printf("%s: no INIT\n", DEVNAME(sc)); 142 else 143 aml_freevalue(&ret); 144 } 145 146 int 147 acpiasus_notify(struct aml_node *node, int notify, void *arg) 148 { 149 struct acpiasus_softc *sc = arg; 150 151 if (notify >= ASUS_NOTIFY_BRIGHTNESSLOW && 152 notify <= ASUS_NOTIFY_BRIGHTNESSHIGH) { 153 #ifdef ACPIASUS_DEBUG 154 printf("%s: brightness %d percent\n", DEVNAME(sc), 155 (notify & 0xf) * 100 / 0xf); 156 #endif 157 return 0; 158 } 159 160 switch (notify) { 161 case ASUS_NOTIFY_WIRELESSON: /* Handled by AML. */ 162 case ASUS_NOTIFY_WIRELESSOFF: /* Handled by AML. */ 163 break; 164 case ASUS_NOTIFY_TASKSWITCH: 165 break; 166 case ASUS_NOTIFY_DISPLAYCYCLEDOWN: 167 case ASUS_NOTIFY_DISPLAYCYCLEUP: 168 break; 169 #if NAUDIO > 0 && NWSKBD > 0 170 case ASUS_NOTIFY_VOLUMEMUTE: 171 wskbd_set_mixervolume(0, 1); 172 break; 173 case ASUS_NOTIFY_VOLUMEDOWN: 174 wskbd_set_mixervolume(-1, 1); 175 break; 176 case ASUS_NOTIFY_VOLUMEUP: 177 wskbd_set_mixervolume(1, 1); 178 break; 179 #else 180 case ASUS_NOTIFY_VOLUMEMUTE: 181 case ASUS_NOTIFY_VOLUMEDOWN: 182 case ASUS_NOTIFY_VOLUMEUP: 183 break; 184 #endif 185 case ASUS_NOTIFY_POWERCONNECT: 186 case ASUS_NOTIFY_POWERDISCONNECT: 187 break; 188 189 case ASUS_NOTIFY_LCDSWITCHOFF0: 190 case ASUS_NOTIFY_LCDSWITCHOFF1: 191 break; 192 193 case ASUS_NOTIFY_LCDCHANGERES: 194 break; 195 196 case ASUS_NOTIFY_USERDEF0: 197 case ASUS_NOTIFY_USERDEF1: 198 break; 199 200 default: 201 printf("%s: unknown event 0x%02x\n", DEVNAME(sc), notify); 202 break; 203 } 204 205 return 0; 206 } 207 208 int 209 acpiasus_activate(struct device *self, int act) 210 { 211 struct acpiasus_softc *sc = (struct acpiasus_softc *)self; 212 struct aml_value cmd; 213 struct aml_value ret; 214 215 switch (act) { 216 case DVACT_WAKEUP: 217 acpiasus_init(self); 218 219 bzero(&cmd, sizeof(cmd)); 220 cmd.type = AML_OBJTYPE_INTEGER; 221 cmd.v_integer = ASUS_SDSP_LCD; 222 223 if (aml_evalname(sc->sc_acpi, sc->sc_devnode, "SDSP", 1, 224 &cmd, &ret)) 225 printf("%s: no SDSP\n", DEVNAME(sc)); 226 else 227 aml_freevalue(&ret); 228 break; 229 } 230 return (0); 231 } 232