acpiasus.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. /* $OpenBSD: acpiasus.c,v 1.17 2014/02/21 18:49:06 deraadt 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. * ASUS ACPI hotkeys driver.
  30. */
  31. #include <sys/param.h>
  32. #include <sys/device.h>
  33. #include <sys/systm.h>
  34. #include <dev/acpi/acpireg.h>
  35. #include <dev/acpi/acpivar.h>
  36. #include <dev/acpi/acpidev.h>
  37. #include <dev/acpi/amltypes.h>
  38. #include <dev/acpi/dsdt.h>
  39. #include "audio.h"
  40. #include "wskbd.h"
  41. struct acpiasus_softc {
  42. struct device sc_dev;
  43. struct acpi_softc *sc_acpi;
  44. struct aml_node *sc_devnode;
  45. };
  46. #define ASUS_NOTIFY_WIRELESSON 0x10
  47. #define ASUS_NOTIFY_WIRELESSOFF 0x11
  48. #define ASUS_NOTIFY_TASKSWITCH 0x12
  49. #define ASUS_NOTIFY_VOLUMEMUTE 0x13
  50. #define ASUS_NOTIFY_VOLUMEDOWN 0x14
  51. #define ASUS_NOTIFY_VOLUMEUP 0x15
  52. #define ASUS_NOTIFY_LCDSWITCHOFF0 0x16
  53. #define ASUS_NOTIFY_LCDSWITCHOFF1 0x1a
  54. #define ASUS_NOTIFY_LCDCHANGERES 0x1b
  55. #define ASUS_NOTIFY_USERDEF0 0x1c
  56. #define ASUS_NOTIFY_USERDEF1 0x1d
  57. #define ASUS_NOTIFY_BRIGHTNESSLOW 0x20
  58. #define ASUS_NOTIFY_BRIGHTNESSHIGH 0x2f
  59. #define ASUS_NOTIFY_DISPLAYCYCLEDOWN 0x30
  60. #define ASUS_NOTIFY_DISPLAYCYCLEUP 0x32
  61. #define ASUS_NOTIFY_POWERCONNECT 0x50
  62. #define ASUS_NOTIFY_POWERDISCONNECT 0x51
  63. #define ASUS_SDSP_LCD 0x01
  64. #define ASUS_SDSP_CRT 0x02
  65. #define ASUS_SDSP_TV 0x04
  66. #define ASUS_SDSP_DVI 0x08
  67. #define ASUS_SDSP_ALL \
  68. (ASUS_SDSP_LCD | ASUS_SDSP_CRT | ASUS_SDSP_TV | ASUS_SDSP_DVI)
  69. int acpiasus_match(struct device *, void *, void *);
  70. void acpiasus_attach(struct device *, struct device *, void *);
  71. void acpiasus_init(struct device *);
  72. int acpiasus_notify(struct aml_node *, int, void *);
  73. int acpiasus_activate(struct device *, int);
  74. #if NAUDIO > 0 && NWSKBD > 0
  75. extern int wskbd_set_mixervolume(long, long);
  76. #endif
  77. struct cfattach acpiasus_ca = {
  78. sizeof(struct acpiasus_softc), acpiasus_match, acpiasus_attach,
  79. NULL, acpiasus_activate
  80. };
  81. struct cfdriver acpiasus_cd = {
  82. NULL, "acpiasus", DV_DULL
  83. };
  84. const char *acpiasus_hids[] = { ACPI_DEV_ASUS, 0 };
  85. int
  86. acpiasus_match(struct device *parent, void *match, void *aux)
  87. {
  88. struct acpi_attach_args *aa = aux;
  89. struct cfdata *cf = match;
  90. return (acpi_matchhids(aa, acpiasus_hids, cf->cf_driver->cd_name));
  91. }
  92. void
  93. acpiasus_attach(struct device *parent, struct device *self, void *aux)
  94. {
  95. struct acpiasus_softc *sc = (struct acpiasus_softc *)self;
  96. struct acpi_attach_args *aa = aux;
  97. sc->sc_acpi = (struct acpi_softc *)parent;
  98. sc->sc_devnode = aa->aaa_node;
  99. printf("\n");
  100. acpiasus_init(self);
  101. aml_register_notify(sc->sc_devnode, aa->aaa_dev,
  102. acpiasus_notify, sc, ACPIDEV_NOPOLL);
  103. }
  104. void
  105. acpiasus_init(struct device *self)
  106. {
  107. struct acpiasus_softc *sc = (struct acpiasus_softc *)self;
  108. struct aml_value cmd;
  109. struct aml_value ret;
  110. bzero(&cmd, sizeof(cmd));
  111. cmd.type = AML_OBJTYPE_INTEGER;
  112. cmd.v_integer = 0x40; /* Disable ASL display switching. */
  113. if (aml_evalname(sc->sc_acpi, sc->sc_devnode, "INIT", 1, &cmd, &ret))
  114. printf("%s: no INIT\n", DEVNAME(sc));
  115. else
  116. aml_freevalue(&ret);
  117. }
  118. int
  119. acpiasus_notify(struct aml_node *node, int notify, void *arg)
  120. {
  121. struct acpiasus_softc *sc = arg;
  122. if (notify >= ASUS_NOTIFY_BRIGHTNESSLOW &&
  123. notify <= ASUS_NOTIFY_BRIGHTNESSHIGH) {
  124. #ifdef ACPIASUS_DEBUG
  125. printf("%s: brightness %d percent\n", DEVNAME(sc),
  126. (notify & 0xf) * 100 / 0xf);
  127. #endif
  128. return 0;
  129. }
  130. switch (notify) {
  131. case ASUS_NOTIFY_WIRELESSON: /* Handled by AML. */
  132. case ASUS_NOTIFY_WIRELESSOFF: /* Handled by AML. */
  133. break;
  134. case ASUS_NOTIFY_TASKSWITCH:
  135. break;
  136. case ASUS_NOTIFY_DISPLAYCYCLEDOWN:
  137. case ASUS_NOTIFY_DISPLAYCYCLEUP:
  138. break;
  139. #if NAUDIO > 0 && NWSKBD > 0
  140. case ASUS_NOTIFY_VOLUMEMUTE:
  141. wskbd_set_mixervolume(0, 1);
  142. break;
  143. case ASUS_NOTIFY_VOLUMEDOWN:
  144. wskbd_set_mixervolume(-1, 1);
  145. break;
  146. case ASUS_NOTIFY_VOLUMEUP:
  147. wskbd_set_mixervolume(1, 1);
  148. break;
  149. #else
  150. case ASUS_NOTIFY_VOLUMEMUTE:
  151. case ASUS_NOTIFY_VOLUMEDOWN:
  152. case ASUS_NOTIFY_VOLUMEUP:
  153. break;
  154. #endif
  155. case ASUS_NOTIFY_POWERCONNECT:
  156. case ASUS_NOTIFY_POWERDISCONNECT:
  157. break;
  158. case ASUS_NOTIFY_LCDSWITCHOFF0:
  159. case ASUS_NOTIFY_LCDSWITCHOFF1:
  160. break;
  161. case ASUS_NOTIFY_LCDCHANGERES:
  162. break;
  163. case ASUS_NOTIFY_USERDEF0:
  164. case ASUS_NOTIFY_USERDEF1:
  165. break;
  166. default:
  167. printf("%s: unknown event 0x%02x\n", DEVNAME(sc), notify);
  168. break;
  169. }
  170. return 0;
  171. }
  172. int
  173. acpiasus_activate(struct device *self, int act)
  174. {
  175. struct acpiasus_softc *sc = (struct acpiasus_softc *)self;
  176. struct aml_value cmd;
  177. struct aml_value ret;
  178. switch (act) {
  179. case DVACT_WAKEUP:
  180. acpiasus_init(self);
  181. bzero(&cmd, sizeof(cmd));
  182. cmd.type = AML_OBJTYPE_INTEGER;
  183. cmd.v_integer = ASUS_SDSP_LCD;
  184. if (aml_evalname(sc->sc_acpi, sc->sc_devnode, "SDSP", 1,
  185. &cmd, &ret))
  186. printf("%s: no SDSP\n", DEVNAME(sc));
  187. else
  188. aml_freevalue(&ret);
  189. break;
  190. }
  191. return (0);
  192. }