19a1fc77eSPhilip Paeps /*-
218d92cd8SPhilip Paeps * Copyright (c) 2004, 2005 Philip Paeps <philip@FreeBSD.org>
39a1fc77eSPhilip Paeps * All rights reserved.
49a1fc77eSPhilip Paeps *
59a1fc77eSPhilip Paeps * Redistribution and use in source and binary forms, with or without
69a1fc77eSPhilip Paeps * modification, are permitted provided that the following conditions
79a1fc77eSPhilip Paeps * are met:
89a1fc77eSPhilip Paeps * 1. Redistributions of source code must retain the above copyright
99a1fc77eSPhilip Paeps * notice, this list of conditions and the following disclaimer.
109a1fc77eSPhilip Paeps * 2. Redistributions in binary form must reproduce the above copyright
119a1fc77eSPhilip Paeps * notice, this list of conditions and the following disclaimer in the
129a1fc77eSPhilip Paeps * documentation and/or other materials provided with the distribution.
139a1fc77eSPhilip Paeps *
149a1fc77eSPhilip Paeps * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
159a1fc77eSPhilip Paeps * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
169a1fc77eSPhilip Paeps * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
179a1fc77eSPhilip Paeps * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
189a1fc77eSPhilip Paeps * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
199a1fc77eSPhilip Paeps * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
209a1fc77eSPhilip Paeps * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
219a1fc77eSPhilip Paeps * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
229a1fc77eSPhilip Paeps * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
239a1fc77eSPhilip Paeps * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
249a1fc77eSPhilip Paeps * SUCH DAMAGE.
259a1fc77eSPhilip Paeps */
269a1fc77eSPhilip Paeps
279a1fc77eSPhilip Paeps #include <sys/cdefs.h>
289a1fc77eSPhilip Paeps /*
299a1fc77eSPhilip Paeps * Driver for extra ACPI-controlled gadgets (hotkeys, leds, etc) found on
30f5296c93SPhilip Paeps * recent Asus (and Medion) laptops. Inspired by the acpi4asus project which
319a1fc77eSPhilip Paeps * implements these features in the Linux kernel.
329a1fc77eSPhilip Paeps *
339a1fc77eSPhilip Paeps * <http://sourceforge.net/projects/acpi4asus/>
349a1fc77eSPhilip Paeps *
359a1fc77eSPhilip Paeps * Currently should support most features, but could use some more testing.
369a1fc77eSPhilip Paeps * Particularly the display-switching stuff is a bit hairy. If you have an
379a1fc77eSPhilip Paeps * Asus laptop which doesn't appear to be supported, or strange things happen
389a1fc77eSPhilip Paeps * when using this driver, please report to <acpi@FreeBSD.org>.
399a1fc77eSPhilip Paeps */
409a1fc77eSPhilip Paeps
419a1fc77eSPhilip Paeps #include "opt_acpi.h"
429a1fc77eSPhilip Paeps #include <sys/param.h>
439a1fc77eSPhilip Paeps #include <sys/kernel.h>
4477409fe1SPoul-Henning Kamp #include <sys/module.h>
459a1fc77eSPhilip Paeps #include <sys/bus.h>
469a1fc77eSPhilip Paeps
47129d3046SJung-uk Kim #include <contrib/dev/acpica/include/acpi.h>
48129d3046SJung-uk Kim #include <contrib/dev/acpica/include/accommon.h>
49129d3046SJung-uk Kim
509a1fc77eSPhilip Paeps #include <dev/acpica/acpivar.h>
519a1fc77eSPhilip Paeps #include <dev/led/led.h>
529a1fc77eSPhilip Paeps
53d8e0b9e1SPhilip Paeps /* Methods */
54d8e0b9e1SPhilip Paeps #define ACPI_ASUS_METHOD_BRN 1
55d8e0b9e1SPhilip Paeps #define ACPI_ASUS_METHOD_DISP 2
56d8e0b9e1SPhilip Paeps #define ACPI_ASUS_METHOD_LCD 3
57aea61887SRui Paulo #define ACPI_ASUS_METHOD_CAMERA 4
58aea61887SRui Paulo #define ACPI_ASUS_METHOD_CARDRD 5
590fc34be4SRui Paulo #define ACPI_ASUS_METHOD_WLAN 6
60d8e0b9e1SPhilip Paeps
61276cd921SNate Lawson #define _COMPONENT ACPI_OEM
629a1fc77eSPhilip Paeps ACPI_MODULE_NAME("ASUS")
639a1fc77eSPhilip Paeps
649a1fc77eSPhilip Paeps struct acpi_asus_model {
659a1fc77eSPhilip Paeps char *name;
669a1fc77eSPhilip Paeps
67caac4996SPhilip Paeps char *bled_set;
68824d24a8SJung-uk Kim char *dled_set;
69824d24a8SJung-uk Kim char *gled_set;
709a1fc77eSPhilip Paeps char *mled_set;
719a1fc77eSPhilip Paeps char *tled_set;
729a1fc77eSPhilip Paeps char *wled_set;
739a1fc77eSPhilip Paeps
749a1fc77eSPhilip Paeps char *brn_get;
759a1fc77eSPhilip Paeps char *brn_set;
769a1fc77eSPhilip Paeps char *brn_up;
779a1fc77eSPhilip Paeps char *brn_dn;
789a1fc77eSPhilip Paeps
799a1fc77eSPhilip Paeps char *lcd_get;
809a1fc77eSPhilip Paeps char *lcd_set;
819a1fc77eSPhilip Paeps
829a1fc77eSPhilip Paeps char *disp_get;
839a1fc77eSPhilip Paeps char *disp_set;
84aea61887SRui Paulo
85aea61887SRui Paulo char *cam_get;
86aea61887SRui Paulo char *cam_set;
87aea61887SRui Paulo
88aea61887SRui Paulo char *crd_get;
89aea61887SRui Paulo char *crd_set;
90aea61887SRui Paulo
910fc34be4SRui Paulo char *wlan_get;
920fc34be4SRui Paulo char *wlan_set;
930fc34be4SRui Paulo
94aea61887SRui Paulo void (*n_func)(ACPI_HANDLE, UINT32, void *);
9531fb9906SRui Paulo
9631fb9906SRui Paulo char *lcdd;
9731fb9906SRui Paulo void (*lcdd_n_func)(ACPI_HANDLE, UINT32, void *);
989a1fc77eSPhilip Paeps };
999a1fc77eSPhilip Paeps
100f5296c93SPhilip Paeps struct acpi_asus_led {
1014d2743aeSPhilip Paeps struct acpi_asus_softc *sc;
102f5296c93SPhilip Paeps struct cdev *cdev;
1034d2743aeSPhilip Paeps int busy;
1044d2743aeSPhilip Paeps int state;
105f5296c93SPhilip Paeps enum {
106caac4996SPhilip Paeps ACPI_ASUS_LED_BLED,
107824d24a8SJung-uk Kim ACPI_ASUS_LED_DLED,
108824d24a8SJung-uk Kim ACPI_ASUS_LED_GLED,
109f5296c93SPhilip Paeps ACPI_ASUS_LED_MLED,
110f5296c93SPhilip Paeps ACPI_ASUS_LED_TLED,
111f5296c93SPhilip Paeps ACPI_ASUS_LED_WLED,
112f5296c93SPhilip Paeps } type;
113f5296c93SPhilip Paeps };
114f5296c93SPhilip Paeps
1159a1fc77eSPhilip Paeps struct acpi_asus_softc {
1169a1fc77eSPhilip Paeps device_t dev;
1179a1fc77eSPhilip Paeps ACPI_HANDLE handle;
11831fb9906SRui Paulo ACPI_HANDLE lcdd_handle;
1199a1fc77eSPhilip Paeps
1209a1fc77eSPhilip Paeps struct acpi_asus_model *model;
1219a1fc77eSPhilip Paeps struct sysctl_ctx_list sysctl_ctx;
1229a1fc77eSPhilip Paeps struct sysctl_oid *sysctl_tree;
1239a1fc77eSPhilip Paeps
124caac4996SPhilip Paeps struct acpi_asus_led s_bled;
125824d24a8SJung-uk Kim struct acpi_asus_led s_dled;
126824d24a8SJung-uk Kim struct acpi_asus_led s_gled;
127f5296c93SPhilip Paeps struct acpi_asus_led s_mled;
128f5296c93SPhilip Paeps struct acpi_asus_led s_tled;
129f5296c93SPhilip Paeps struct acpi_asus_led s_wled;
1309a1fc77eSPhilip Paeps
1319a1fc77eSPhilip Paeps int s_brn;
1329a1fc77eSPhilip Paeps int s_disp;
1339a1fc77eSPhilip Paeps int s_lcd;
134aea61887SRui Paulo int s_cam;
135aea61887SRui Paulo int s_crd;
1360fc34be4SRui Paulo int s_wlan;
1379a1fc77eSPhilip Paeps };
1389a1fc77eSPhilip Paeps
13931fb9906SRui Paulo static void acpi_asus_lcdd_notify(ACPI_HANDLE h, UINT32 notify,
14031fb9906SRui Paulo void *context);
14131fb9906SRui Paulo
142706bd68cSPhilip Paeps /*
143706bd68cSPhilip Paeps * We can identify Asus laptops from the string they return
144706bd68cSPhilip Paeps * as a result of calling the ATK0100 'INIT' method.
145706bd68cSPhilip Paeps */
1469a1fc77eSPhilip Paeps static struct acpi_asus_model acpi_asus_models[] = {
1479a1fc77eSPhilip Paeps {
14818d92cd8SPhilip Paeps .name = "xxN",
14918d92cd8SPhilip Paeps .mled_set = "MLED",
15018d92cd8SPhilip Paeps .wled_set = "WLED",
15118d92cd8SPhilip Paeps .lcd_get = "\\BKLT",
15218d92cd8SPhilip Paeps .lcd_set = "\\_SB.PCI0.SBRG.EC0._Q10",
15318d92cd8SPhilip Paeps .brn_get = "GPLV",
15418d92cd8SPhilip Paeps .brn_set = "SPLV",
15518d92cd8SPhilip Paeps .disp_get = "\\ADVG",
15618d92cd8SPhilip Paeps .disp_set = "SDSP"
15718d92cd8SPhilip Paeps },
15818d92cd8SPhilip Paeps {
15918d92cd8SPhilip Paeps .name = "A1x",
16018d92cd8SPhilip Paeps .mled_set = "MLED",
16118d92cd8SPhilip Paeps .lcd_get = "\\BKLI",
16218d92cd8SPhilip Paeps .lcd_set = "\\_SB.PCI0.ISA.EC0._Q10",
16318d92cd8SPhilip Paeps .brn_up = "\\_SB.PCI0.ISA.EC0._Q0E",
16418d92cd8SPhilip Paeps .brn_dn = "\\_SB.PCI0.ISA.EC0._Q0F"
16518d92cd8SPhilip Paeps },
16618d92cd8SPhilip Paeps {
16718d92cd8SPhilip Paeps .name = "A2x",
16818d92cd8SPhilip Paeps .mled_set = "MLED",
16918d92cd8SPhilip Paeps .wled_set = "WLED",
17018d92cd8SPhilip Paeps .lcd_get = "\\BAOF",
17118d92cd8SPhilip Paeps .lcd_set = "\\Q10",
17218d92cd8SPhilip Paeps .brn_get = "GPLV",
17318d92cd8SPhilip Paeps .brn_set = "SPLV",
17418d92cd8SPhilip Paeps .disp_get = "\\INFB",
17518d92cd8SPhilip Paeps .disp_set = "SDSP"
17618d92cd8SPhilip Paeps },
17718d92cd8SPhilip Paeps {
1784060f1bbSAttilio Rao .name = "A3E",
1794060f1bbSAttilio Rao .mled_set = "MLED",
1804060f1bbSAttilio Rao .wled_set = "WLED",
1814060f1bbSAttilio Rao .lcd_get = "\\_SB.PCI0.SBRG.EC0.RPIN(0x67)",
1824060f1bbSAttilio Rao .lcd_set = "\\_SB.PCI0.SBRG.EC0._Q10",
1834060f1bbSAttilio Rao .brn_get = "GPLV",
1844060f1bbSAttilio Rao .brn_set = "SPLV",
1854060f1bbSAttilio Rao .disp_get = "\\_SB.PCI0.P0P2.VGA.GETD",
1864060f1bbSAttilio Rao .disp_set = "SDSP"
1874060f1bbSAttilio Rao },
1884060f1bbSAttilio Rao {
1894060f1bbSAttilio Rao .name = "A3F",
1904060f1bbSAttilio Rao .mled_set = "MLED",
1914060f1bbSAttilio Rao .wled_set = "WLED",
1924060f1bbSAttilio Rao .bled_set = "BLED",
1934060f1bbSAttilio Rao .lcd_get = "\\_SB.PCI0.SBRG.EC0.RPIN(0x11)",
1944060f1bbSAttilio Rao .lcd_set = "\\_SB.PCI0.SBRG.EC0._Q10",
1954060f1bbSAttilio Rao .brn_get = "GPLV",
1964060f1bbSAttilio Rao .brn_set = "SPLV",
1974060f1bbSAttilio Rao .disp_get = "\\SSTE",
1984060f1bbSAttilio Rao .disp_set = "SDSP"
1994060f1bbSAttilio Rao },
2004060f1bbSAttilio Rao {
20118d725a0SPhilip Paeps .name = "A3N",
20218d725a0SPhilip Paeps .mled_set = "MLED",
20318d725a0SPhilip Paeps .bled_set = "BLED",
20418d725a0SPhilip Paeps .wled_set = "WLED",
2054060f1bbSAttilio Rao .lcd_get = "\\BKLT",
20618d725a0SPhilip Paeps .lcd_set = "\\_SB.PCI0.SBRG.EC0._Q10",
2074060f1bbSAttilio Rao .brn_get = "GPLV",
20818d725a0SPhilip Paeps .brn_set = "SPLV",
2094060f1bbSAttilio Rao .disp_get = "\\_SB.PCI0.P0P3.VGA.GETD",
2104060f1bbSAttilio Rao .disp_set = "SDSP"
21118d725a0SPhilip Paeps },
21218d725a0SPhilip Paeps {
213f50bf401SPhilip Paeps .name = "A4D",
214f50bf401SPhilip Paeps .mled_set = "MLED",
215f50bf401SPhilip Paeps .brn_up = "\\_SB_.PCI0.SBRG.EC0._Q0E",
216f50bf401SPhilip Paeps .brn_dn = "\\_SB_.PCI0.SBRG.EC0._Q0F",
217f50bf401SPhilip Paeps .brn_get = "GPLV",
218f50bf401SPhilip Paeps .brn_set = "SPLV",
219f50bf401SPhilip Paeps #ifdef notyet
220f50bf401SPhilip Paeps .disp_get = "\\_SB_.PCI0.SBRG.EC0._Q10",
221f50bf401SPhilip Paeps .disp_set = "\\_SB_.PCI0.SBRG.EC0._Q11"
222f50bf401SPhilip Paeps #endif
223f50bf401SPhilip Paeps },
224f50bf401SPhilip Paeps {
225e691fe45SPhilip Paeps .name = "A6V",
226e691fe45SPhilip Paeps .bled_set = "BLED",
227e691fe45SPhilip Paeps .mled_set = "MLED",
228e691fe45SPhilip Paeps .wled_set = "WLED",
229e691fe45SPhilip Paeps .lcd_get = NULL,
230e691fe45SPhilip Paeps .lcd_set = "\\_SB.PCI0.SBRG.EC0._Q10",
231e691fe45SPhilip Paeps .brn_get = "GPLV",
232e691fe45SPhilip Paeps .brn_set = "SPLV",
233e691fe45SPhilip Paeps .disp_get = "\\_SB.PCI0.P0P3.VGA.GETD",
234e691fe45SPhilip Paeps .disp_set = "SDSP"
235e691fe45SPhilip Paeps },
236e691fe45SPhilip Paeps {
23731fb9906SRui Paulo .name = "A8SR",
23831fb9906SRui Paulo .bled_set = "BLED",
23931fb9906SRui Paulo .mled_set = "MLED",
24031fb9906SRui Paulo .wled_set = "WLED",
24131fb9906SRui Paulo .lcd_get = NULL,
24231fb9906SRui Paulo .lcd_set = "\\_SB.PCI0.SBRG.EC0._Q10",
24331fb9906SRui Paulo .brn_get = "GPLV",
24431fb9906SRui Paulo .brn_set = "SPLV",
24531fb9906SRui Paulo .disp_get = "\\_SB.PCI0.P0P1.VGA.GETD",
24631fb9906SRui Paulo .disp_set = "SDSP",
24731fb9906SRui Paulo .lcdd = "\\_SB.PCI0.P0P1.VGA.LCDD",
24831fb9906SRui Paulo .lcdd_n_func = acpi_asus_lcdd_notify
24931fb9906SRui Paulo },
25031fb9906SRui Paulo {
25118d92cd8SPhilip Paeps .name = "D1x",
25218d92cd8SPhilip Paeps .mled_set = "MLED",
25318d92cd8SPhilip Paeps .lcd_get = "\\GP11",
25418d92cd8SPhilip Paeps .lcd_set = "\\Q0D",
25518d92cd8SPhilip Paeps .brn_up = "\\Q0C",
25618d92cd8SPhilip Paeps .brn_dn = "\\Q0B",
25718d92cd8SPhilip Paeps .disp_get = "\\INFB",
25818d92cd8SPhilip Paeps .disp_set = "SDSP"
25918d92cd8SPhilip Paeps },
26018d92cd8SPhilip Paeps {
261824d24a8SJung-uk Kim .name = "G2K",
262824d24a8SJung-uk Kim .bled_set = "BLED",
263824d24a8SJung-uk Kim .dled_set = "DLED",
264824d24a8SJung-uk Kim .gled_set = "GLED",
265824d24a8SJung-uk Kim .mled_set = "MLED",
266824d24a8SJung-uk Kim .tled_set = "TLED",
267824d24a8SJung-uk Kim .wled_set = "WLED",
268824d24a8SJung-uk Kim .brn_get = "GPLV",
269824d24a8SJung-uk Kim .brn_set = "SPLV",
270f67f8ffdSJung-uk Kim .lcd_get = "GBTL",
271f67f8ffdSJung-uk Kim .lcd_set = "SBTL",
272824d24a8SJung-uk Kim .disp_get = "\\_SB.PCI0.PCE2.VGA.GETD",
273824d24a8SJung-uk Kim .disp_set = "SDSP",
274824d24a8SJung-uk Kim },
275824d24a8SJung-uk Kim {
2769a1fc77eSPhilip Paeps .name = "L2D",
2779a1fc77eSPhilip Paeps .mled_set = "MLED",
2789a1fc77eSPhilip Paeps .wled_set = "WLED",
2799a1fc77eSPhilip Paeps .brn_up = "\\Q0E",
2809a1fc77eSPhilip Paeps .brn_dn = "\\Q0F",
2819a1fc77eSPhilip Paeps .lcd_get = "\\SGP0",
2829a1fc77eSPhilip Paeps .lcd_set = "\\Q10"
2839a1fc77eSPhilip Paeps },
2849a1fc77eSPhilip Paeps {
2859a1fc77eSPhilip Paeps .name = "L3C",
2869a1fc77eSPhilip Paeps .mled_set = "MLED",
2879a1fc77eSPhilip Paeps .wled_set = "WLED",
2889a1fc77eSPhilip Paeps .brn_get = "GPLV",
2899a1fc77eSPhilip Paeps .brn_set = "SPLV",
2909a1fc77eSPhilip Paeps .lcd_get = "\\GL32",
2919a1fc77eSPhilip Paeps .lcd_set = "\\_SB.PCI0.PX40.ECD0._Q10"
2929a1fc77eSPhilip Paeps },
2939a1fc77eSPhilip Paeps {
2949a1fc77eSPhilip Paeps .name = "L3D",
2959a1fc77eSPhilip Paeps .mled_set = "MLED",
2969a1fc77eSPhilip Paeps .wled_set = "WLED",
2979a1fc77eSPhilip Paeps .brn_get = "GPLV",
2989a1fc77eSPhilip Paeps .brn_set = "SPLV",
2999a1fc77eSPhilip Paeps .lcd_get = "\\BKLG",
3009a1fc77eSPhilip Paeps .lcd_set = "\\Q10"
3019a1fc77eSPhilip Paeps },
3029a1fc77eSPhilip Paeps {
3039a1fc77eSPhilip Paeps .name = "L3H",
3049a1fc77eSPhilip Paeps .mled_set = "MLED",
3059a1fc77eSPhilip Paeps .wled_set = "WLED",
3069a1fc77eSPhilip Paeps .brn_get = "GPLV",
3079a1fc77eSPhilip Paeps .brn_set = "SPLV",
3089a1fc77eSPhilip Paeps .lcd_get = "\\_SB.PCI0.PM.PBC",
3099a1fc77eSPhilip Paeps .lcd_set = "EHK",
3109a1fc77eSPhilip Paeps .disp_get = "\\_SB.INFB",
3119a1fc77eSPhilip Paeps .disp_set = "SDSP"
3129a1fc77eSPhilip Paeps },
3139a1fc77eSPhilip Paeps {
3149923cf22SPhilip Paeps .name = "L4R",
3159923cf22SPhilip Paeps .mled_set = "MLED",
3169923cf22SPhilip Paeps .wled_set = "WLED",
3179923cf22SPhilip Paeps .brn_get = "GPLV",
3189923cf22SPhilip Paeps .brn_set = "SPLV",
3199923cf22SPhilip Paeps .lcd_get = "\\_SB.PCI0.SBSM.SEO4",
3209923cf22SPhilip Paeps .lcd_set = "\\_SB.PCI0.SBRG.EC0._Q10",
3219923cf22SPhilip Paeps .disp_get = "\\_SB.PCI0.P0P1.VGA.GETD",
3229923cf22SPhilip Paeps .disp_set = "SDSP"
3239923cf22SPhilip Paeps },
3249923cf22SPhilip Paeps {
32518d92cd8SPhilip Paeps .name = "L5x",
32618d92cd8SPhilip Paeps .mled_set = "MLED",
32718d92cd8SPhilip Paeps .tled_set = "TLED",
32818d92cd8SPhilip Paeps .lcd_get = "\\BAOF",
32918d92cd8SPhilip Paeps .lcd_set = "\\Q0D",
33018d92cd8SPhilip Paeps .brn_get = "GPLV",
33118d92cd8SPhilip Paeps .brn_set = "SPLV",
33218d92cd8SPhilip Paeps .disp_get = "\\INFB",
33318d92cd8SPhilip Paeps .disp_set = "SDSP"
33418d92cd8SPhilip Paeps },
33518d92cd8SPhilip Paeps {
3369a1fc77eSPhilip Paeps .name = "L8L"
337de326158SRui Paulo /* Only has hotkeys, apparently */
3389a1fc77eSPhilip Paeps },
3399a1fc77eSPhilip Paeps {
3409a1fc77eSPhilip Paeps .name = "M1A",
3419a1fc77eSPhilip Paeps .mled_set = "MLED",
3429a1fc77eSPhilip Paeps .brn_up = "\\_SB.PCI0.PX40.EC0.Q0E",
3439a1fc77eSPhilip Paeps .brn_dn = "\\_SB.PCI0.PX40.EC0.Q0F",
3449a1fc77eSPhilip Paeps .lcd_get = "\\PNOF",
3459a1fc77eSPhilip Paeps .lcd_set = "\\_SB.PCI0.PX40.EC0.Q10"
3469a1fc77eSPhilip Paeps },
3479a1fc77eSPhilip Paeps {
3489a1fc77eSPhilip Paeps .name = "M2E",
3499a1fc77eSPhilip Paeps .mled_set = "MLED",
3509a1fc77eSPhilip Paeps .wled_set = "WLED",
3519a1fc77eSPhilip Paeps .brn_get = "GPLV",
3529a1fc77eSPhilip Paeps .brn_set = "SPLV",
3539a1fc77eSPhilip Paeps .lcd_get = "\\GP06",
3549a1fc77eSPhilip Paeps .lcd_set = "\\Q10"
3559a1fc77eSPhilip Paeps },
3569a1fc77eSPhilip Paeps {
35717520557SPhilip Paeps .name = "M6N",
35817520557SPhilip Paeps .mled_set = "MLED",
35917520557SPhilip Paeps .wled_set = "WLED",
36017520557SPhilip Paeps .lcd_set = "\\_SB.PCI0.SBRG.EC0._Q10",
36117520557SPhilip Paeps .lcd_get = "\\_SB.BKLT",
36217520557SPhilip Paeps .brn_set = "SPLV",
36317520557SPhilip Paeps .brn_get = "GPLV",
36417520557SPhilip Paeps .disp_set = "SDSP",
36517520557SPhilip Paeps .disp_get = "\\SSTE"
36617520557SPhilip Paeps },
3679923cf22SPhilip Paeps {
3689923cf22SPhilip Paeps .name = "M6R",
3699923cf22SPhilip Paeps .mled_set = "MLED",
3709923cf22SPhilip Paeps .wled_set = "WLED",
3719923cf22SPhilip Paeps .brn_get = "GPLV",
3729923cf22SPhilip Paeps .brn_set = "SPLV",
3739923cf22SPhilip Paeps .lcd_get = "\\_SB.PCI0.SBSM.SEO4",
3749923cf22SPhilip Paeps .lcd_set = "\\_SB.PCI0.SBRG.EC0._Q10",
3759923cf22SPhilip Paeps .disp_get = "\\SSTE",
3769923cf22SPhilip Paeps .disp_set = "SDSP"
3779923cf22SPhilip Paeps },
378caac4996SPhilip Paeps {
37918d92cd8SPhilip Paeps .name = "S1x",
38018d92cd8SPhilip Paeps .mled_set = "MLED",
38118d92cd8SPhilip Paeps .wled_set = "WLED",
38218d92cd8SPhilip Paeps .lcd_get = "\\PNOF",
38318d92cd8SPhilip Paeps .lcd_set = "\\_SB.PCI0.PX40.Q10",
38418d92cd8SPhilip Paeps .brn_get = "GPLV",
38518d92cd8SPhilip Paeps .brn_set = "SPLV"
38618d92cd8SPhilip Paeps },
38718d92cd8SPhilip Paeps {
38818d92cd8SPhilip Paeps .name = "S2x",
38918d92cd8SPhilip Paeps .mled_set = "MLED",
39018d92cd8SPhilip Paeps .lcd_get = "\\BKLI",
39118d92cd8SPhilip Paeps .lcd_set = "\\_SB.PCI0.ISA.EC0._Q10",
39218d92cd8SPhilip Paeps .brn_up = "\\_SB.PCI0.ISA.EC0._Q0B",
39318d92cd8SPhilip Paeps .brn_dn = "\\_SB.PCI0.ISA.EC0._Q0A"
39418d92cd8SPhilip Paeps },
39518d92cd8SPhilip Paeps {
396caac4996SPhilip Paeps .name = "V6V",
397caac4996SPhilip Paeps .bled_set = "BLED",
398caac4996SPhilip Paeps .tled_set = "TLED",
399caac4996SPhilip Paeps .wled_set = "WLED",
400caac4996SPhilip Paeps .lcd_get = "\\BKLT",
401caac4996SPhilip Paeps .lcd_set = "\\_SB.PCI0.SBRG.EC0._Q10",
402caac4996SPhilip Paeps .brn_get = "GPLV",
403caac4996SPhilip Paeps .brn_set = "SPLV",
404caac4996SPhilip Paeps .disp_get = "\\_SB.PCI0.P0P1.VGA.GETD",
405caac4996SPhilip Paeps .disp_set = "SDSP"
406caac4996SPhilip Paeps },
407e13d4201SPhilip Paeps {
408e13d4201SPhilip Paeps .name = "W5A",
409e13d4201SPhilip Paeps .bled_set = "BLED",
410e13d4201SPhilip Paeps .lcd_get = "\\BKLT",
411e13d4201SPhilip Paeps .lcd_set = "\\_SB.PCI0.SBRG.EC0._Q10",
412e13d4201SPhilip Paeps .brn_get = "GPLV",
413e13d4201SPhilip Paeps .brn_set = "SPLV",
414e13d4201SPhilip Paeps .disp_get = "\\_SB.PCI0.P0P2.VGA.GETD",
415e13d4201SPhilip Paeps .disp_set = "SDSP"
416e13d4201SPhilip Paeps },
417706bd68cSPhilip Paeps { .name = NULL }
418706bd68cSPhilip Paeps };
419706bd68cSPhilip Paeps
420706bd68cSPhilip Paeps /*
421706bd68cSPhilip Paeps * Samsung P30/P35 laptops have an Asus ATK0100 gadget interface,
422706bd68cSPhilip Paeps * but they can't be probed quite the same way as Asus laptops.
423706bd68cSPhilip Paeps */
424706bd68cSPhilip Paeps static struct acpi_asus_model acpi_samsung_models[] = {
42517520557SPhilip Paeps {
4269a1fc77eSPhilip Paeps .name = "P30",
4279a1fc77eSPhilip Paeps .wled_set = "WLED",
4289a1fc77eSPhilip Paeps .brn_up = "\\_SB.PCI0.LPCB.EC0._Q68",
4299a1fc77eSPhilip Paeps .brn_dn = "\\_SB.PCI0.LPCB.EC0._Q69",
4309a1fc77eSPhilip Paeps .lcd_get = "\\BKLT",
4319a1fc77eSPhilip Paeps .lcd_set = "\\_SB.PCI0.LPCB.EC0._Q0E"
4329a1fc77eSPhilip Paeps },
4339a1fc77eSPhilip Paeps { .name = NULL }
4349a1fc77eSPhilip Paeps };
4359a1fc77eSPhilip Paeps
436aea61887SRui Paulo static void acpi_asus_eeepc_notify(ACPI_HANDLE h, UINT32 notify, void *context);
437aea61887SRui Paulo
438fea0f7ccSRui Paulo /*
439fea0f7ccSRui Paulo * EeePC have an Asus ASUS010 gadget interface,
440fea0f7ccSRui Paulo * but they can't be probed quite the same way as Asus laptops.
441fea0f7ccSRui Paulo */
442fea0f7ccSRui Paulo static struct acpi_asus_model acpi_eeepc_models[] = {
443fea0f7ccSRui Paulo {
444fea0f7ccSRui Paulo .name = "EEE",
445fea0f7ccSRui Paulo .brn_get = "\\_SB.ATKD.PBLG",
446aea61887SRui Paulo .brn_set = "\\_SB.ATKD.PBLS",
447aea61887SRui Paulo .cam_get = "\\_SB.ATKD.CAMG",
448aea61887SRui Paulo .cam_set = "\\_SB.ATKD.CAMS",
449aea61887SRui Paulo .crd_set = "\\_SB.ATKD.CRDS",
450aea61887SRui Paulo .crd_get = "\\_SB.ATKD.CRDG",
4510fc34be4SRui Paulo .wlan_get = "\\_SB.ATKD.WLDG",
4520fc34be4SRui Paulo .wlan_set = "\\_SB.ATKD.WLDS",
453aea61887SRui Paulo .n_func = acpi_asus_eeepc_notify
454fea0f7ccSRui Paulo },
455fea0f7ccSRui Paulo { .name = NULL }
456fea0f7ccSRui Paulo };
457fea0f7ccSRui Paulo
458d8e0b9e1SPhilip Paeps static struct {
459d8e0b9e1SPhilip Paeps char *name;
460d8e0b9e1SPhilip Paeps char *description;
461d8e0b9e1SPhilip Paeps int method;
462f0188618SHans Petter Selasky int flag_anybody;
463d8e0b9e1SPhilip Paeps } acpi_asus_sysctls[] = {
464d8e0b9e1SPhilip Paeps {
465d8e0b9e1SPhilip Paeps .name = "lcd_backlight",
466d8e0b9e1SPhilip Paeps .method = ACPI_ASUS_METHOD_LCD,
467aea61887SRui Paulo .description = "state of the lcd backlight",
468f0188618SHans Petter Selasky .flag_anybody = 1
469d8e0b9e1SPhilip Paeps },
470d8e0b9e1SPhilip Paeps {
471d8e0b9e1SPhilip Paeps .name = "lcd_brightness",
472d8e0b9e1SPhilip Paeps .method = ACPI_ASUS_METHOD_BRN,
473aea61887SRui Paulo .description = "brightness of the lcd panel",
474f0188618SHans Petter Selasky .flag_anybody = 1
475d8e0b9e1SPhilip Paeps },
476d8e0b9e1SPhilip Paeps {
477d8e0b9e1SPhilip Paeps .name = "video_output",
478d8e0b9e1SPhilip Paeps .method = ACPI_ASUS_METHOD_DISP,
479aea61887SRui Paulo .description = "display output state",
480aea61887SRui Paulo },
481aea61887SRui Paulo {
482aea61887SRui Paulo .name = "camera",
483aea61887SRui Paulo .method = ACPI_ASUS_METHOD_CAMERA,
484aea61887SRui Paulo .description = "internal camera state",
485aea61887SRui Paulo },
486aea61887SRui Paulo {
487aea61887SRui Paulo .name = "cardreader",
488aea61887SRui Paulo .method = ACPI_ASUS_METHOD_CARDRD,
489aea61887SRui Paulo .description = "internal card reader state",
490d8e0b9e1SPhilip Paeps },
4910fc34be4SRui Paulo {
4920fc34be4SRui Paulo .name = "wlan",
4930fc34be4SRui Paulo .method = ACPI_ASUS_METHOD_WLAN,
4940fc34be4SRui Paulo .description = "wireless lan state",
4950fc34be4SRui Paulo },
496d8e0b9e1SPhilip Paeps { .name = NULL }
497d8e0b9e1SPhilip Paeps };
498d8e0b9e1SPhilip Paeps
4991051a7c2SNate Lawson ACPI_SERIAL_DECL(asus, "ACPI ASUS extras");
5001051a7c2SNate Lawson
5019a1fc77eSPhilip Paeps /* Function prototypes */
5029a1fc77eSPhilip Paeps static int acpi_asus_probe(device_t dev);
5039a1fc77eSPhilip Paeps static int acpi_asus_attach(device_t dev);
5049a1fc77eSPhilip Paeps static int acpi_asus_detach(device_t dev);
5059a1fc77eSPhilip Paeps
506f5296c93SPhilip Paeps static void acpi_asus_led(struct acpi_asus_led *led, int state);
5074d2743aeSPhilip Paeps static void acpi_asus_led_task(struct acpi_asus_led *led, int pending __unused);
5089a1fc77eSPhilip Paeps
509d8e0b9e1SPhilip Paeps static int acpi_asus_sysctl(SYSCTL_HANDLER_ARGS);
510d8e0b9e1SPhilip Paeps static int acpi_asus_sysctl_init(struct acpi_asus_softc *sc, int method);
511d8e0b9e1SPhilip Paeps static int acpi_asus_sysctl_get(struct acpi_asus_softc *sc, int method);
512d8e0b9e1SPhilip Paeps static int acpi_asus_sysctl_set(struct acpi_asus_softc *sc, int method, int val);
5139a1fc77eSPhilip Paeps
5149a1fc77eSPhilip Paeps static void acpi_asus_notify(ACPI_HANDLE h, UINT32 notify, void *context);
5159a1fc77eSPhilip Paeps
5169a1fc77eSPhilip Paeps static device_method_t acpi_asus_methods[] = {
5179a1fc77eSPhilip Paeps DEVMETHOD(device_probe, acpi_asus_probe),
5189a1fc77eSPhilip Paeps DEVMETHOD(device_attach, acpi_asus_attach),
5199a1fc77eSPhilip Paeps DEVMETHOD(device_detach, acpi_asus_detach),
5209a1fc77eSPhilip Paeps { 0, 0 }
5219a1fc77eSPhilip Paeps };
5229a1fc77eSPhilip Paeps
5239a1fc77eSPhilip Paeps static driver_t acpi_asus_driver = {
5249a1fc77eSPhilip Paeps "acpi_asus",
5259a1fc77eSPhilip Paeps acpi_asus_methods,
5269a1fc77eSPhilip Paeps sizeof(struct acpi_asus_softc)
5279a1fc77eSPhilip Paeps };
5289a1fc77eSPhilip Paeps
52990161e72SJohn Baldwin DRIVER_MODULE(acpi_asus, acpi, acpi_asus_driver, 0, 0);
5309a1fc77eSPhilip Paeps MODULE_DEPEND(acpi_asus, acpi, 1, 1, 1);
5319a1fc77eSPhilip Paeps
5329a1fc77eSPhilip Paeps static int
acpi_asus_probe(device_t dev)5339a1fc77eSPhilip Paeps acpi_asus_probe(device_t dev)
5349a1fc77eSPhilip Paeps {
5359a1fc77eSPhilip Paeps struct acpi_asus_model *model;
5369a1fc77eSPhilip Paeps struct acpi_asus_softc *sc;
5379a1fc77eSPhilip Paeps ACPI_BUFFER Buf;
5389a1fc77eSPhilip Paeps ACPI_OBJECT Arg, *Obj;
5399a1fc77eSPhilip Paeps ACPI_OBJECT_LIST Args;
540fea0f7ccSRui Paulo static char *asus_ids[] = { "ATK0100", "ASUS010", NULL };
5415efca36fSTakanori Watanabe int rv;
542fea0f7ccSRui Paulo char *rstr;
5439a1fc77eSPhilip Paeps
5449a1fc77eSPhilip Paeps ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
5459a1fc77eSPhilip Paeps
546fea0f7ccSRui Paulo if (acpi_disabled("asus"))
547078080c9SPhilip Paeps return (ENXIO);
5485efca36fSTakanori Watanabe rv = ACPI_ID_PROBE(device_get_parent(dev), dev, asus_ids, &rstr);
5495efca36fSTakanori Watanabe if (rv > 0) {
5505efca36fSTakanori Watanabe return (rv);
551fea0f7ccSRui Paulo }
552078080c9SPhilip Paeps
5539a1fc77eSPhilip Paeps sc = device_get_softc(dev);
5549a1fc77eSPhilip Paeps sc->dev = dev;
5559a1fc77eSPhilip Paeps sc->handle = acpi_get_handle(dev);
5569a1fc77eSPhilip Paeps
5579a1fc77eSPhilip Paeps Arg.Type = ACPI_TYPE_INTEGER;
5589a1fc77eSPhilip Paeps Arg.Integer.Value = 0;
5599a1fc77eSPhilip Paeps
5609a1fc77eSPhilip Paeps Args.Count = 1;
5619a1fc77eSPhilip Paeps Args.Pointer = &Arg;
5629a1fc77eSPhilip Paeps
5639a1fc77eSPhilip Paeps Buf.Pointer = NULL;
5649a1fc77eSPhilip Paeps Buf.Length = ACPI_ALLOCATE_BUFFER;
5659a1fc77eSPhilip Paeps
5669a1fc77eSPhilip Paeps AcpiEvaluateObject(sc->handle, "INIT", &Args, &Buf);
5679a1fc77eSPhilip Paeps Obj = Buf.Pointer;
5689a1fc77eSPhilip Paeps
569706bd68cSPhilip Paeps /*
570706bd68cSPhilip Paeps * The Samsung P30 returns a null-pointer from INIT, we
571706bd68cSPhilip Paeps * can identify it from the 'ODEM' string in the DSDT.
572706bd68cSPhilip Paeps */
573706bd68cSPhilip Paeps if (Obj->String.Pointer == NULL) {
574706bd68cSPhilip Paeps ACPI_STATUS status;
575706bd68cSPhilip Paeps ACPI_TABLE_HEADER th;
576706bd68cSPhilip Paeps
5772be4e471SJung-uk Kim status = AcpiGetTableHeader(ACPI_SIG_DSDT, 0, &th);
578706bd68cSPhilip Paeps if (ACPI_FAILURE(status)) {
579078080c9SPhilip Paeps device_printf(dev, "Unsupported (Samsung?) laptop\n");
580706bd68cSPhilip Paeps AcpiOsFree(Buf.Pointer);
581706bd68cSPhilip Paeps return (ENXIO);
582706bd68cSPhilip Paeps }
583706bd68cSPhilip Paeps
584706bd68cSPhilip Paeps if (strncmp("ODEM", th.OemTableId, 4) == 0) {
585706bd68cSPhilip Paeps sc->model = &acpi_samsung_models[0];
586078080c9SPhilip Paeps device_set_desc(dev, "Samsung P30 Laptop Extras");
587706bd68cSPhilip Paeps AcpiOsFree(Buf.Pointer);
5885efca36fSTakanori Watanabe return (rv);
589706bd68cSPhilip Paeps }
590fea0f7ccSRui Paulo
5914060f1bbSAttilio Rao /* EeePC */
592fea0f7ccSRui Paulo if (strncmp("ASUS010", rstr, 7) == 0) {
593fea0f7ccSRui Paulo sc->model = &acpi_eeepc_models[0];
594fea0f7ccSRui Paulo device_set_desc(dev, "ASUS EeePC");
595fea0f7ccSRui Paulo AcpiOsFree(Buf.Pointer);
5965efca36fSTakanori Watanabe return (rv);
597fea0f7ccSRui Paulo }
598706bd68cSPhilip Paeps }
599706bd68cSPhilip Paeps
600706bd68cSPhilip Paeps /*
601706bd68cSPhilip Paeps * Asus laptops are simply identified by name, easy!
602706bd68cSPhilip Paeps */
60318d92cd8SPhilip Paeps for (model = acpi_asus_models; model->name != NULL; model++) {
604078080c9SPhilip Paeps if (strncmp(Obj->String.Pointer, model->name, 3) == 0) {
60518d92cd8SPhilip Paeps good:
6069a1fc77eSPhilip Paeps sc->model = model;
6079a1fc77eSPhilip Paeps
608*bad36a49SMark Johnston device_set_descf(dev, "Asus %s Laptop Extras",
609*bad36a49SMark Johnston Obj->String.Pointer);
610*bad36a49SMark Johnston
6119a1fc77eSPhilip Paeps AcpiOsFree(Buf.Pointer);
6125efca36fSTakanori Watanabe return (rv);
6139a1fc77eSPhilip Paeps }
6149a1fc77eSPhilip Paeps
61518d92cd8SPhilip Paeps /*
61618d92cd8SPhilip Paeps * Some models look exactly the same as other models, but have
61718d92cd8SPhilip Paeps * their own ids. If we spot these, set them up with the same
61818d92cd8SPhilip Paeps * details as the models they're like, possibly dealing with
61918d92cd8SPhilip Paeps * small differences.
62018d92cd8SPhilip Paeps *
62118d92cd8SPhilip Paeps * XXX: there must be a prettier way to do this!
62218d92cd8SPhilip Paeps */
62318d92cd8SPhilip Paeps else if (strncmp(model->name, "xxN", 3) == 0 &&
62418d92cd8SPhilip Paeps (strncmp(Obj->String.Pointer, "M3N", 3) == 0 ||
62518d92cd8SPhilip Paeps strncmp(Obj->String.Pointer, "S1N", 3) == 0))
62618d92cd8SPhilip Paeps goto good;
62718d92cd8SPhilip Paeps else if (strncmp(model->name, "A1x", 3) == 0 &&
62818d92cd8SPhilip Paeps strncmp(Obj->String.Pointer, "A1", 2) == 0)
62918d92cd8SPhilip Paeps goto good;
63018d92cd8SPhilip Paeps else if (strncmp(model->name, "A2x", 3) == 0 &&
63118d92cd8SPhilip Paeps strncmp(Obj->String.Pointer, "A2", 2) == 0)
63218d92cd8SPhilip Paeps goto good;
6334060f1bbSAttilio Rao else if (strncmp(model->name, "A3F", 3) == 0 &&
6344060f1bbSAttilio Rao strncmp(Obj->String.Pointer, "A6F", 3) == 0)
6354060f1bbSAttilio Rao goto good;
63618d92cd8SPhilip Paeps else if (strncmp(model->name, "D1x", 3) == 0 &&
63718d92cd8SPhilip Paeps strncmp(Obj->String.Pointer, "D1", 2) == 0)
63818d92cd8SPhilip Paeps goto good;
63918d92cd8SPhilip Paeps else if (strncmp(model->name, "L3H", 3) == 0 &&
64018d92cd8SPhilip Paeps strncmp(Obj->String.Pointer, "L2E", 3) == 0)
64118d92cd8SPhilip Paeps goto good;
64218d92cd8SPhilip Paeps else if (strncmp(model->name, "L5x", 3) == 0 &&
64318d92cd8SPhilip Paeps strncmp(Obj->String.Pointer, "L5", 2) == 0)
64418d92cd8SPhilip Paeps goto good;
64518d92cd8SPhilip Paeps else if (strncmp(model->name, "M2E", 3) == 0 &&
64618d92cd8SPhilip Paeps (strncmp(Obj->String.Pointer, "M2", 2) == 0 ||
64718d92cd8SPhilip Paeps strncmp(Obj->String.Pointer, "L4E", 3) == 0))
64818d92cd8SPhilip Paeps goto good;
64918d92cd8SPhilip Paeps else if (strncmp(model->name, "S1x", 3) == 0 &&
65018d92cd8SPhilip Paeps (strncmp(Obj->String.Pointer, "L8", 2) == 0 ||
65118d92cd8SPhilip Paeps strncmp(Obj->String.Pointer, "S1", 2) == 0))
65218d92cd8SPhilip Paeps goto good;
65318d92cd8SPhilip Paeps else if (strncmp(model->name, "S2x", 3) == 0 &&
65418d92cd8SPhilip Paeps (strncmp(Obj->String.Pointer, "J1", 2) == 0 ||
65518d92cd8SPhilip Paeps strncmp(Obj->String.Pointer, "S2", 2) == 0))
65618d92cd8SPhilip Paeps goto good;
65718d92cd8SPhilip Paeps
65818d92cd8SPhilip Paeps /* L2B is like L3C but has no lcd_get method */
65918d92cd8SPhilip Paeps else if (strncmp(model->name, "L3C", 3) == 0 &&
66018d92cd8SPhilip Paeps strncmp(Obj->String.Pointer, "L2B", 3) == 0) {
66118d92cd8SPhilip Paeps model->lcd_get = NULL;
66218d92cd8SPhilip Paeps goto good;
66318d92cd8SPhilip Paeps }
66418d92cd8SPhilip Paeps
66518d92cd8SPhilip Paeps /* A3G is like M6R but with a different lcd_get method */
66618d92cd8SPhilip Paeps else if (strncmp(model->name, "M6R", 3) == 0 &&
66718d92cd8SPhilip Paeps strncmp(Obj->String.Pointer, "A3G", 3) == 0) {
66818d92cd8SPhilip Paeps model->lcd_get = "\\BLFG";
66918d92cd8SPhilip Paeps goto good;
67018d92cd8SPhilip Paeps }
67118d92cd8SPhilip Paeps
67218d92cd8SPhilip Paeps /* M2N and W1N are like xxN with added WLED */
67318d92cd8SPhilip Paeps else if (strncmp(model->name, "xxN", 3) == 0 &&
67418d92cd8SPhilip Paeps (strncmp(Obj->String.Pointer, "M2N", 3) == 0 ||
67518d92cd8SPhilip Paeps strncmp(Obj->String.Pointer, "W1N", 3) == 0)) {
67618d92cd8SPhilip Paeps model->wled_set = "WLED";
67718d92cd8SPhilip Paeps goto good;
67818d92cd8SPhilip Paeps }
67918d92cd8SPhilip Paeps
68018d92cd8SPhilip Paeps /* M5N and S5N are like xxN without MLED */
68118d92cd8SPhilip Paeps else if (strncmp(model->name, "xxN", 3) == 0 &&
68218d92cd8SPhilip Paeps (strncmp(Obj->String.Pointer, "M5N", 3) == 0 ||
68318d92cd8SPhilip Paeps strncmp(Obj->String.Pointer, "S5N", 3) == 0)) {
68418d92cd8SPhilip Paeps model->mled_set = NULL;
68518d92cd8SPhilip Paeps goto good;
68618d92cd8SPhilip Paeps }
68718d92cd8SPhilip Paeps }
68818d92cd8SPhilip Paeps
689*bad36a49SMark Johnston device_printf(dev, "Unsupported Asus laptop: %s\n",
690*bad36a49SMark Johnston Obj->String.Pointer);
6919a1fc77eSPhilip Paeps
6929a1fc77eSPhilip Paeps AcpiOsFree(Buf.Pointer);
6939a1fc77eSPhilip Paeps
6949a1fc77eSPhilip Paeps return (ENXIO);
6959a1fc77eSPhilip Paeps }
6969a1fc77eSPhilip Paeps
6979a1fc77eSPhilip Paeps static int
acpi_asus_attach(device_t dev)6989a1fc77eSPhilip Paeps acpi_asus_attach(device_t dev)
6999a1fc77eSPhilip Paeps {
7009a1fc77eSPhilip Paeps struct acpi_asus_softc *sc;
7019a1fc77eSPhilip Paeps struct acpi_softc *acpi_sc;
7029a1fc77eSPhilip Paeps
7039a1fc77eSPhilip Paeps ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
7049a1fc77eSPhilip Paeps
7059a1fc77eSPhilip Paeps sc = device_get_softc(dev);
7069a1fc77eSPhilip Paeps acpi_sc = acpi_device_get_parent_softc(dev);
7079a1fc77eSPhilip Paeps
7089a1fc77eSPhilip Paeps /* Build sysctl tree */
7099a1fc77eSPhilip Paeps sysctl_ctx_init(&sc->sysctl_ctx);
7109a1fc77eSPhilip Paeps sc->sysctl_tree = SYSCTL_ADD_NODE(&sc->sysctl_ctx,
7119a1fc77eSPhilip Paeps SYSCTL_CHILDREN(acpi_sc->acpi_sysctl_tree),
7127029da5cSPawel Biernacki OID_AUTO, "asus", CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "");
7139a1fc77eSPhilip Paeps
714d8e0b9e1SPhilip Paeps /* Hook up nodes */
715d8e0b9e1SPhilip Paeps for (int i = 0; acpi_asus_sysctls[i].name != NULL; i++) {
716d8e0b9e1SPhilip Paeps if (!acpi_asus_sysctl_init(sc, acpi_asus_sysctls[i].method))
717d8e0b9e1SPhilip Paeps continue;
718d8e0b9e1SPhilip Paeps
719f0188618SHans Petter Selasky if (acpi_asus_sysctls[i].flag_anybody != 0) {
720d8e0b9e1SPhilip Paeps SYSCTL_ADD_PROC(&sc->sysctl_ctx,
721d8e0b9e1SPhilip Paeps SYSCTL_CHILDREN(sc->sysctl_tree), OID_AUTO,
722d8e0b9e1SPhilip Paeps acpi_asus_sysctls[i].name,
7237029da5cSPawel Biernacki CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY |
7246237a1ccSAlexander Motin CTLFLAG_MPSAFE, sc, i, acpi_asus_sysctl, "I",
725d8e0b9e1SPhilip Paeps acpi_asus_sysctls[i].description);
726f0188618SHans Petter Selasky } else {
727f0188618SHans Petter Selasky SYSCTL_ADD_PROC(&sc->sysctl_ctx,
728f0188618SHans Petter Selasky SYSCTL_CHILDREN(sc->sysctl_tree), OID_AUTO,
729f0188618SHans Petter Selasky acpi_asus_sysctls[i].name,
7306237a1ccSAlexander Motin CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE,
731f0188618SHans Petter Selasky sc, i, acpi_asus_sysctl, "I",
732f0188618SHans Petter Selasky acpi_asus_sysctls[i].description);
733f0188618SHans Petter Selasky }
734d8e0b9e1SPhilip Paeps }
735d8e0b9e1SPhilip Paeps
7369a1fc77eSPhilip Paeps /* Attach leds */
737caac4996SPhilip Paeps if (sc->model->bled_set) {
738caac4996SPhilip Paeps sc->s_bled.busy = 0;
739caac4996SPhilip Paeps sc->s_bled.sc = sc;
740caac4996SPhilip Paeps sc->s_bled.type = ACPI_ASUS_LED_BLED;
741caac4996SPhilip Paeps sc->s_bled.cdev =
742824d24a8SJung-uk Kim led_create_state((led_t *)acpi_asus_led, &sc->s_bled,
743824d24a8SJung-uk Kim "bled", 1);
744824d24a8SJung-uk Kim }
745824d24a8SJung-uk Kim
746824d24a8SJung-uk Kim if (sc->model->dled_set) {
747824d24a8SJung-uk Kim sc->s_dled.busy = 0;
748824d24a8SJung-uk Kim sc->s_dled.sc = sc;
749824d24a8SJung-uk Kim sc->s_dled.type = ACPI_ASUS_LED_DLED;
750824d24a8SJung-uk Kim sc->s_dled.cdev =
751824d24a8SJung-uk Kim led_create((led_t *)acpi_asus_led, &sc->s_dled, "dled");
752824d24a8SJung-uk Kim }
753824d24a8SJung-uk Kim
754824d24a8SJung-uk Kim if (sc->model->gled_set) {
755824d24a8SJung-uk Kim sc->s_gled.busy = 0;
756824d24a8SJung-uk Kim sc->s_gled.sc = sc;
757824d24a8SJung-uk Kim sc->s_gled.type = ACPI_ASUS_LED_GLED;
758824d24a8SJung-uk Kim sc->s_gled.cdev =
759824d24a8SJung-uk Kim led_create((led_t *)acpi_asus_led, &sc->s_gled, "gled");
760caac4996SPhilip Paeps }
761caac4996SPhilip Paeps
762f5296c93SPhilip Paeps if (sc->model->mled_set) {
7634d2743aeSPhilip Paeps sc->s_mled.busy = 0;
7644d2743aeSPhilip Paeps sc->s_mled.sc = sc;
765f5296c93SPhilip Paeps sc->s_mled.type = ACPI_ASUS_LED_MLED;
766f5296c93SPhilip Paeps sc->s_mled.cdev =
767f5296c93SPhilip Paeps led_create((led_t *)acpi_asus_led, &sc->s_mled, "mled");
768f5296c93SPhilip Paeps }
7699a1fc77eSPhilip Paeps
770f5296c93SPhilip Paeps if (sc->model->tled_set) {
7714d2743aeSPhilip Paeps sc->s_tled.busy = 0;
7724d2743aeSPhilip Paeps sc->s_tled.sc = sc;
773f5296c93SPhilip Paeps sc->s_tled.type = ACPI_ASUS_LED_TLED;
774f5296c93SPhilip Paeps sc->s_tled.cdev =
775824d24a8SJung-uk Kim led_create_state((led_t *)acpi_asus_led, &sc->s_tled,
776824d24a8SJung-uk Kim "tled", 1);
777f5296c93SPhilip Paeps }
7789a1fc77eSPhilip Paeps
779f5296c93SPhilip Paeps if (sc->model->wled_set) {
7804d2743aeSPhilip Paeps sc->s_wled.busy = 0;
7814d2743aeSPhilip Paeps sc->s_wled.sc = sc;
782f5296c93SPhilip Paeps sc->s_wled.type = ACPI_ASUS_LED_WLED;
783f5296c93SPhilip Paeps sc->s_wled.cdev =
784824d24a8SJung-uk Kim led_create_state((led_t *)acpi_asus_led, &sc->s_wled,
785824d24a8SJung-uk Kim "wled", 1);
786f5296c93SPhilip Paeps }
7879a1fc77eSPhilip Paeps
7889a1fc77eSPhilip Paeps /* Activate hotkeys */
7899a1fc77eSPhilip Paeps AcpiEvaluateObject(sc->handle, "BSTS", NULL, NULL);
7909a1fc77eSPhilip Paeps
7919a1fc77eSPhilip Paeps /* Handle notifies */
792aea61887SRui Paulo if (sc->model->n_func == NULL)
793aea61887SRui Paulo sc->model->n_func = acpi_asus_notify;
794aea61887SRui Paulo
795b4cb1402SNate Lawson AcpiInstallNotifyHandler(sc->handle, ACPI_SYSTEM_NOTIFY,
796aea61887SRui Paulo sc->model->n_func, dev);
7979a1fc77eSPhilip Paeps
79831fb9906SRui Paulo /* Find and hook the 'LCDD' object */
79931fb9906SRui Paulo if (sc->model->lcdd != NULL && sc->model->lcdd_n_func != NULL) {
80031fb9906SRui Paulo ACPI_STATUS res;
80131fb9906SRui Paulo
80231fb9906SRui Paulo sc->lcdd_handle = NULL;
80331fb9906SRui Paulo res = AcpiGetHandle((sc->model->lcdd[0] == '\\' ?
80431fb9906SRui Paulo NULL : sc->handle), sc->model->lcdd, &(sc->lcdd_handle));
80531fb9906SRui Paulo if (ACPI_SUCCESS(res)) {
80631fb9906SRui Paulo AcpiInstallNotifyHandler((sc->lcdd_handle),
80731fb9906SRui Paulo ACPI_DEVICE_NOTIFY, sc->model->lcdd_n_func, dev);
80831fb9906SRui Paulo } else {
80931fb9906SRui Paulo printf("%s: unable to find LCD device '%s'\n",
81031fb9906SRui Paulo __func__, sc->model->lcdd);
81131fb9906SRui Paulo }
81231fb9906SRui Paulo }
81331fb9906SRui Paulo
8149a1fc77eSPhilip Paeps return (0);
8159a1fc77eSPhilip Paeps }
8169a1fc77eSPhilip Paeps
8179a1fc77eSPhilip Paeps static int
acpi_asus_detach(device_t dev)8189a1fc77eSPhilip Paeps acpi_asus_detach(device_t dev)
8199a1fc77eSPhilip Paeps {
8209a1fc77eSPhilip Paeps struct acpi_asus_softc *sc;
8219a1fc77eSPhilip Paeps
8229a1fc77eSPhilip Paeps ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
8239a1fc77eSPhilip Paeps
8249a1fc77eSPhilip Paeps sc = device_get_softc(dev);
8259a1fc77eSPhilip Paeps
8269a1fc77eSPhilip Paeps /* Turn the lights off */
827caac4996SPhilip Paeps if (sc->model->bled_set)
828caac4996SPhilip Paeps led_destroy(sc->s_bled.cdev);
829caac4996SPhilip Paeps
830824d24a8SJung-uk Kim if (sc->model->dled_set)
831824d24a8SJung-uk Kim led_destroy(sc->s_dled.cdev);
832824d24a8SJung-uk Kim
833824d24a8SJung-uk Kim if (sc->model->gled_set)
834824d24a8SJung-uk Kim led_destroy(sc->s_gled.cdev);
835824d24a8SJung-uk Kim
8369a1fc77eSPhilip Paeps if (sc->model->mled_set)
837f5296c93SPhilip Paeps led_destroy(sc->s_mled.cdev);
8389a1fc77eSPhilip Paeps
8399a1fc77eSPhilip Paeps if (sc->model->tled_set)
840f5296c93SPhilip Paeps led_destroy(sc->s_tled.cdev);
8419a1fc77eSPhilip Paeps
8429a1fc77eSPhilip Paeps if (sc->model->wled_set)
843f5296c93SPhilip Paeps led_destroy(sc->s_wled.cdev);
8449a1fc77eSPhilip Paeps
8459a1fc77eSPhilip Paeps /* Remove notify handler */
846b4cb1402SNate Lawson AcpiRemoveNotifyHandler(sc->handle, ACPI_SYSTEM_NOTIFY,
847b4cb1402SNate Lawson acpi_asus_notify);
8489a1fc77eSPhilip Paeps
84931fb9906SRui Paulo if (sc->lcdd_handle) {
85031fb9906SRui Paulo KASSERT(sc->model->lcdd_n_func != NULL,
85131fb9906SRui Paulo ("model->lcdd_n_func is NULL, but lcdd_handle is non-zero"));
85231fb9906SRui Paulo AcpiRemoveNotifyHandler((sc->lcdd_handle),
85331fb9906SRui Paulo ACPI_DEVICE_NOTIFY, sc->model->lcdd_n_func);
85431fb9906SRui Paulo }
85531fb9906SRui Paulo
8569a1fc77eSPhilip Paeps /* Free sysctl tree */
8579a1fc77eSPhilip Paeps sysctl_ctx_free(&sc->sysctl_ctx);
8589a1fc77eSPhilip Paeps
8599a1fc77eSPhilip Paeps return (0);
8609a1fc77eSPhilip Paeps }
8619a1fc77eSPhilip Paeps
8629a1fc77eSPhilip Paeps static void
acpi_asus_led_task(struct acpi_asus_led * led,int pending __unused)8634d2743aeSPhilip Paeps acpi_asus_led_task(struct acpi_asus_led *led, int pending __unused)
8649a1fc77eSPhilip Paeps {
8659a1fc77eSPhilip Paeps struct acpi_asus_softc *sc;
866f5296c93SPhilip Paeps char *method;
8674d2743aeSPhilip Paeps int state;
8689a1fc77eSPhilip Paeps
8699a1fc77eSPhilip Paeps ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
8709a1fc77eSPhilip Paeps
8714d2743aeSPhilip Paeps sc = led->sc;
872f5296c93SPhilip Paeps
873f5296c93SPhilip Paeps switch (led->type) {
874caac4996SPhilip Paeps case ACPI_ASUS_LED_BLED:
875caac4996SPhilip Paeps method = sc->model->bled_set;
876caac4996SPhilip Paeps state = led->state;
877caac4996SPhilip Paeps break;
878824d24a8SJung-uk Kim case ACPI_ASUS_LED_DLED:
879824d24a8SJung-uk Kim method = sc->model->dled_set;
880824d24a8SJung-uk Kim state = led->state;
881824d24a8SJung-uk Kim break;
882824d24a8SJung-uk Kim case ACPI_ASUS_LED_GLED:
883824d24a8SJung-uk Kim method = sc->model->gled_set;
884824d24a8SJung-uk Kim state = led->state + 1; /* 1: off, 2: on */
885824d24a8SJung-uk Kim break;
886f5296c93SPhilip Paeps case ACPI_ASUS_LED_MLED:
887f5296c93SPhilip Paeps method = sc->model->mled_set;
888824d24a8SJung-uk Kim state = !led->state; /* inverted */
889f5296c93SPhilip Paeps break;
890f5296c93SPhilip Paeps case ACPI_ASUS_LED_TLED:
891f5296c93SPhilip Paeps method = sc->model->tled_set;
8924d2743aeSPhilip Paeps state = led->state;
893f5296c93SPhilip Paeps break;
894f5296c93SPhilip Paeps case ACPI_ASUS_LED_WLED:
895f5296c93SPhilip Paeps method = sc->model->wled_set;
8964d2743aeSPhilip Paeps state = led->state;
897f5296c93SPhilip Paeps break;
89809003ac3SPhilip Paeps default:
89909003ac3SPhilip Paeps printf("acpi_asus_led: invalid LED type %d\n",
90009003ac3SPhilip Paeps (int)led->type);
90109003ac3SPhilip Paeps return;
9029a1fc77eSPhilip Paeps }
9039a1fc77eSPhilip Paeps
904f5296c93SPhilip Paeps acpi_SetInteger(sc->handle, method, state);
9054d2743aeSPhilip Paeps led->busy = 0;
9064d2743aeSPhilip Paeps }
9074d2743aeSPhilip Paeps
9084d2743aeSPhilip Paeps static void
acpi_asus_led(struct acpi_asus_led * led,int state)9094d2743aeSPhilip Paeps acpi_asus_led(struct acpi_asus_led *led, int state)
9104d2743aeSPhilip Paeps {
9114d2743aeSPhilip Paeps
9124d2743aeSPhilip Paeps ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
9134d2743aeSPhilip Paeps
9144d2743aeSPhilip Paeps if (led->busy)
9154d2743aeSPhilip Paeps return;
9164d2743aeSPhilip Paeps
9174d2743aeSPhilip Paeps led->busy = 1;
9184d2743aeSPhilip Paeps led->state = state;
9194d2743aeSPhilip Paeps
9202be4e471SJung-uk Kim AcpiOsExecute(OSL_NOTIFY_HANDLER, (void *)acpi_asus_led_task, led);
9219a1fc77eSPhilip Paeps }
9229a1fc77eSPhilip Paeps
9239a1fc77eSPhilip Paeps static int
acpi_asus_sysctl(SYSCTL_HANDLER_ARGS)924d8e0b9e1SPhilip Paeps acpi_asus_sysctl(SYSCTL_HANDLER_ARGS)
9259a1fc77eSPhilip Paeps {
9269a1fc77eSPhilip Paeps struct acpi_asus_softc *sc;
927d8e0b9e1SPhilip Paeps int arg;
928d8e0b9e1SPhilip Paeps int error = 0;
929d8e0b9e1SPhilip Paeps int function;
930d8e0b9e1SPhilip Paeps int method;
9319a1fc77eSPhilip Paeps
9329a1fc77eSPhilip Paeps ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
9339a1fc77eSPhilip Paeps
9349a1fc77eSPhilip Paeps sc = (struct acpi_asus_softc *)oidp->oid_arg1;
935d8e0b9e1SPhilip Paeps function = oidp->oid_arg2;
936d8e0b9e1SPhilip Paeps method = acpi_asus_sysctls[function].method;
937d8e0b9e1SPhilip Paeps
9381051a7c2SNate Lawson ACPI_SERIAL_BEGIN(asus);
939d8e0b9e1SPhilip Paeps arg = acpi_asus_sysctl_get(sc, method);
940d8e0b9e1SPhilip Paeps error = sysctl_handle_int(oidp, &arg, 0, req);
9419a1fc77eSPhilip Paeps
9429a1fc77eSPhilip Paeps /* Sanity check */
943d8e0b9e1SPhilip Paeps if (error != 0 || req->newptr == NULL)
9448390cfe8SNate Lawson goto out;
9459a1fc77eSPhilip Paeps
946d8e0b9e1SPhilip Paeps /* Update */
947d8e0b9e1SPhilip Paeps error = acpi_asus_sysctl_set(sc, method, arg);
948d8e0b9e1SPhilip Paeps
949d8e0b9e1SPhilip Paeps out:
950d8e0b9e1SPhilip Paeps ACPI_SERIAL_END(asus);
951d8e0b9e1SPhilip Paeps return (error);
9528390cfe8SNate Lawson }
9539a1fc77eSPhilip Paeps
954d8e0b9e1SPhilip Paeps static int
acpi_asus_sysctl_get(struct acpi_asus_softc * sc,int method)955d8e0b9e1SPhilip Paeps acpi_asus_sysctl_get(struct acpi_asus_softc *sc, int method)
956d8e0b9e1SPhilip Paeps {
957d8e0b9e1SPhilip Paeps int val = 0;
958d8e0b9e1SPhilip Paeps
959d8e0b9e1SPhilip Paeps ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
960d8e0b9e1SPhilip Paeps ACPI_SERIAL_ASSERT(asus);
961d8e0b9e1SPhilip Paeps
962d8e0b9e1SPhilip Paeps switch (method) {
963d8e0b9e1SPhilip Paeps case ACPI_ASUS_METHOD_BRN:
964d8e0b9e1SPhilip Paeps val = sc->s_brn;
965d8e0b9e1SPhilip Paeps break;
966d8e0b9e1SPhilip Paeps case ACPI_ASUS_METHOD_DISP:
967d8e0b9e1SPhilip Paeps val = sc->s_disp;
968d8e0b9e1SPhilip Paeps break;
969d8e0b9e1SPhilip Paeps case ACPI_ASUS_METHOD_LCD:
970d8e0b9e1SPhilip Paeps val = sc->s_lcd;
971d8e0b9e1SPhilip Paeps break;
972aea61887SRui Paulo case ACPI_ASUS_METHOD_CAMERA:
973aea61887SRui Paulo val = sc->s_cam;
974aea61887SRui Paulo break;
975aea61887SRui Paulo case ACPI_ASUS_METHOD_CARDRD:
976aea61887SRui Paulo val = sc->s_crd;
977aea61887SRui Paulo break;
9780fc34be4SRui Paulo case ACPI_ASUS_METHOD_WLAN:
9790fc34be4SRui Paulo val = sc->s_wlan;
9800fc34be4SRui Paulo break;
981d8e0b9e1SPhilip Paeps }
982d8e0b9e1SPhilip Paeps
983d8e0b9e1SPhilip Paeps return (val);
984d8e0b9e1SPhilip Paeps }
985d8e0b9e1SPhilip Paeps
986d8e0b9e1SPhilip Paeps static int
acpi_asus_sysctl_set(struct acpi_asus_softc * sc,int method,int arg)987d8e0b9e1SPhilip Paeps acpi_asus_sysctl_set(struct acpi_asus_softc *sc, int method, int arg)
988d8e0b9e1SPhilip Paeps {
9894b0eb6a7SPhilip Paeps ACPI_STATUS status = AE_OK;
9900fc34be4SRui Paulo ACPI_OBJECT_LIST acpiargs;
991d85f3935SStanislav Sedov ACPI_OBJECT acpiarg[1];
992d8e0b9e1SPhilip Paeps
993d8e0b9e1SPhilip Paeps ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
994d8e0b9e1SPhilip Paeps ACPI_SERIAL_ASSERT(asus);
995d8e0b9e1SPhilip Paeps
9960fc34be4SRui Paulo acpiargs.Count = 1;
9970fc34be4SRui Paulo acpiargs.Pointer = acpiarg;
9980fc34be4SRui Paulo acpiarg[0].Type = ACPI_TYPE_INTEGER;
9990fc34be4SRui Paulo acpiarg[0].Integer.Value = arg;
10000fc34be4SRui Paulo
1001d8e0b9e1SPhilip Paeps switch (method) {
1002d8e0b9e1SPhilip Paeps case ACPI_ASUS_METHOD_BRN:
1003d8e0b9e1SPhilip Paeps if (arg < 0 || arg > 15)
1004d8e0b9e1SPhilip Paeps return (EINVAL);
10059a1fc77eSPhilip Paeps
10069a1fc77eSPhilip Paeps if (sc->model->brn_set)
1007d8e0b9e1SPhilip Paeps status = acpi_SetInteger(sc->handle,
1008d8e0b9e1SPhilip Paeps sc->model->brn_set, arg);
10099a1fc77eSPhilip Paeps else {
1010d8e0b9e1SPhilip Paeps while (arg != 0) {
1011d8e0b9e1SPhilip Paeps status = AcpiEvaluateObject(sc->handle,
1012d8e0b9e1SPhilip Paeps (arg > 0) ? sc->model->brn_up :
1013d8e0b9e1SPhilip Paeps sc->model->brn_dn, NULL, NULL);
1014d8e0b9e1SPhilip Paeps (arg > 0) ? arg-- : arg++;
10159a1fc77eSPhilip Paeps }
10169a1fc77eSPhilip Paeps }
10179a1fc77eSPhilip Paeps
1018d8e0b9e1SPhilip Paeps if (ACPI_SUCCESS(status))
1019d8e0b9e1SPhilip Paeps sc->s_brn = arg;
10209a1fc77eSPhilip Paeps
1021d8e0b9e1SPhilip Paeps break;
1022d8e0b9e1SPhilip Paeps case ACPI_ASUS_METHOD_DISP:
1023d8e0b9e1SPhilip Paeps if (arg < 0 || arg > 7)
1024d8e0b9e1SPhilip Paeps return (EINVAL);
10259a1fc77eSPhilip Paeps
1026d8e0b9e1SPhilip Paeps status = acpi_SetInteger(sc->handle,
1027d8e0b9e1SPhilip Paeps sc->model->disp_set, arg);
10289a1fc77eSPhilip Paeps
1029d8e0b9e1SPhilip Paeps if (ACPI_SUCCESS(status))
1030d8e0b9e1SPhilip Paeps sc->s_disp = arg;
10319a1fc77eSPhilip Paeps
1032d8e0b9e1SPhilip Paeps break;
1033d8e0b9e1SPhilip Paeps case ACPI_ASUS_METHOD_LCD:
1034d8e0b9e1SPhilip Paeps if (arg < 0 || arg > 1)
1035d8e0b9e1SPhilip Paeps return (EINVAL);
10369a1fc77eSPhilip Paeps
10379a1fc77eSPhilip Paeps if (strncmp(sc->model->name, "L3H", 3) != 0)
1038d8e0b9e1SPhilip Paeps status = AcpiEvaluateObject(sc->handle,
1039d8e0b9e1SPhilip Paeps sc->model->lcd_set, NULL, NULL);
10408390cfe8SNate Lawson else
1041d8e0b9e1SPhilip Paeps status = acpi_SetInteger(sc->handle,
1042d8e0b9e1SPhilip Paeps sc->model->lcd_set, 0x7);
10439a1fc77eSPhilip Paeps
1044d8e0b9e1SPhilip Paeps if (ACPI_SUCCESS(status))
1045d8e0b9e1SPhilip Paeps sc->s_lcd = arg;
1046d8e0b9e1SPhilip Paeps
1047d8e0b9e1SPhilip Paeps break;
1048aea61887SRui Paulo case ACPI_ASUS_METHOD_CAMERA:
1049aea61887SRui Paulo if (arg < 0 || arg > 1)
1050aea61887SRui Paulo return (EINVAL);
1051aea61887SRui Paulo
1052aea61887SRui Paulo status = AcpiEvaluateObject(sc->handle,
10530fc34be4SRui Paulo sc->model->cam_set, &acpiargs, NULL);
1054aea61887SRui Paulo
1055aea61887SRui Paulo if (ACPI_SUCCESS(status))
1056aea61887SRui Paulo sc->s_cam = arg;
1057aea61887SRui Paulo break;
1058aea61887SRui Paulo case ACPI_ASUS_METHOD_CARDRD:
1059aea61887SRui Paulo if (arg < 0 || arg > 1)
1060aea61887SRui Paulo return (EINVAL);
1061aea61887SRui Paulo
1062aea61887SRui Paulo status = AcpiEvaluateObject(sc->handle,
10630fc34be4SRui Paulo sc->model->crd_set, &acpiargs, NULL);
1064aea61887SRui Paulo
1065aea61887SRui Paulo if (ACPI_SUCCESS(status))
1066aea61887SRui Paulo sc->s_crd = arg;
1067aea61887SRui Paulo break;
10680fc34be4SRui Paulo case ACPI_ASUS_METHOD_WLAN:
10690fc34be4SRui Paulo if (arg < 0 || arg > 1)
10700fc34be4SRui Paulo return (EINVAL);
10710fc34be4SRui Paulo
10720fc34be4SRui Paulo status = AcpiEvaluateObject(sc->handle,
10730fc34be4SRui Paulo sc->model->wlan_set, &acpiargs, NULL);
10740fc34be4SRui Paulo
10750fc34be4SRui Paulo if (ACPI_SUCCESS(status))
10760fc34be4SRui Paulo sc->s_wlan = arg;
10770fc34be4SRui Paulo break;
1078d8e0b9e1SPhilip Paeps }
1079d8e0b9e1SPhilip Paeps
1080d8e0b9e1SPhilip Paeps return (0);
10819a1fc77eSPhilip Paeps }
10829a1fc77eSPhilip Paeps
10839a1fc77eSPhilip Paeps static int
acpi_asus_sysctl_init(struct acpi_asus_softc * sc,int method)1084d8e0b9e1SPhilip Paeps acpi_asus_sysctl_init(struct acpi_asus_softc *sc, int method)
10859a1fc77eSPhilip Paeps {
1086d8e0b9e1SPhilip Paeps ACPI_STATUS status;
10879a1fc77eSPhilip Paeps
1088d8e0b9e1SPhilip Paeps switch (method) {
1089d8e0b9e1SPhilip Paeps case ACPI_ASUS_METHOD_BRN:
1090d8e0b9e1SPhilip Paeps if (sc->model->brn_get) {
1091d8e0b9e1SPhilip Paeps /* GPLV/SPLV models */
1092d8e0b9e1SPhilip Paeps status = acpi_GetInteger(sc->handle,
1093d8e0b9e1SPhilip Paeps sc->model->brn_get, &sc->s_brn);
1094d8e0b9e1SPhilip Paeps if (ACPI_SUCCESS(status))
1095d8e0b9e1SPhilip Paeps return (TRUE);
1096d8e0b9e1SPhilip Paeps } else if (sc->model->brn_up) {
1097d8e0b9e1SPhilip Paeps /* Relative models */
1098d8e0b9e1SPhilip Paeps status = AcpiEvaluateObject(sc->handle,
1099d8e0b9e1SPhilip Paeps sc->model->brn_up, NULL, NULL);
1100d8e0b9e1SPhilip Paeps if (ACPI_FAILURE(status))
1101d8e0b9e1SPhilip Paeps return (FALSE);
11029a1fc77eSPhilip Paeps
1103d8e0b9e1SPhilip Paeps status = AcpiEvaluateObject(sc->handle,
1104d8e0b9e1SPhilip Paeps sc->model->brn_dn, NULL, NULL);
1105d8e0b9e1SPhilip Paeps if (ACPI_FAILURE(status))
1106d8e0b9e1SPhilip Paeps return (FALSE);
11079a1fc77eSPhilip Paeps
1108d8e0b9e1SPhilip Paeps return (TRUE);
11098390cfe8SNate Lawson }
1110d8e0b9e1SPhilip Paeps return (FALSE);
1111d8e0b9e1SPhilip Paeps case ACPI_ASUS_METHOD_DISP:
1112d8e0b9e1SPhilip Paeps if (sc->model->disp_get) {
1113d8e0b9e1SPhilip Paeps status = acpi_GetInteger(sc->handle,
1114d8e0b9e1SPhilip Paeps sc->model->disp_get, &sc->s_disp);
1115d8e0b9e1SPhilip Paeps if (ACPI_SUCCESS(status))
1116d8e0b9e1SPhilip Paeps return (TRUE);
1117d8e0b9e1SPhilip Paeps }
1118d8e0b9e1SPhilip Paeps return (FALSE);
1119d8e0b9e1SPhilip Paeps case ACPI_ASUS_METHOD_LCD:
1120824d24a8SJung-uk Kim if (sc->model->lcd_get) {
1121f67f8ffdSJung-uk Kim if (strncmp(sc->model->name, "L3H", 3) == 0) {
1122d8e0b9e1SPhilip Paeps ACPI_BUFFER Buf;
1123d8e0b9e1SPhilip Paeps ACPI_OBJECT Arg[2], Obj;
1124d8e0b9e1SPhilip Paeps ACPI_OBJECT_LIST Args;
11259a1fc77eSPhilip Paeps
1126d8e0b9e1SPhilip Paeps /* L3H is a bit special */
1127d8e0b9e1SPhilip Paeps Arg[0].Type = ACPI_TYPE_INTEGER;
1128d8e0b9e1SPhilip Paeps Arg[0].Integer.Value = 0x02;
1129d8e0b9e1SPhilip Paeps Arg[1].Type = ACPI_TYPE_INTEGER;
1130d8e0b9e1SPhilip Paeps Arg[1].Integer.Value = 0x03;
11319a1fc77eSPhilip Paeps
1132d8e0b9e1SPhilip Paeps Args.Count = 2;
1133d8e0b9e1SPhilip Paeps Args.Pointer = Arg;
1134d8e0b9e1SPhilip Paeps
1135d8e0b9e1SPhilip Paeps Buf.Length = sizeof(Obj);
1136d8e0b9e1SPhilip Paeps Buf.Pointer = &Obj;
1137d8e0b9e1SPhilip Paeps
1138d8e0b9e1SPhilip Paeps status = AcpiEvaluateObject(sc->handle,
1139d8e0b9e1SPhilip Paeps sc->model->lcd_get, &Args, &Buf);
1140d8e0b9e1SPhilip Paeps if (ACPI_SUCCESS(status) &&
1141d8e0b9e1SPhilip Paeps Obj.Type == ACPI_TYPE_INTEGER) {
1142d8e0b9e1SPhilip Paeps sc->s_lcd = Obj.Integer.Value >> 8;
1143d8e0b9e1SPhilip Paeps return (TRUE);
1144d8e0b9e1SPhilip Paeps }
1145824d24a8SJung-uk Kim } else {
1146824d24a8SJung-uk Kim status = acpi_GetInteger(sc->handle,
1147824d24a8SJung-uk Kim sc->model->lcd_get, &sc->s_lcd);
1148824d24a8SJung-uk Kim if (ACPI_SUCCESS(status))
1149824d24a8SJung-uk Kim return (TRUE);
1150824d24a8SJung-uk Kim }
1151d8e0b9e1SPhilip Paeps }
1152d8e0b9e1SPhilip Paeps return (FALSE);
1153aea61887SRui Paulo case ACPI_ASUS_METHOD_CAMERA:
1154aea61887SRui Paulo if (sc->model->cam_get) {
1155aea61887SRui Paulo status = acpi_GetInteger(sc->handle,
1156aea61887SRui Paulo sc->model->cam_get, &sc->s_cam);
1157aea61887SRui Paulo if (ACPI_SUCCESS(status))
1158aea61887SRui Paulo return (TRUE);
1159aea61887SRui Paulo }
1160aea61887SRui Paulo return (FALSE);
1161aea61887SRui Paulo case ACPI_ASUS_METHOD_CARDRD:
1162aea61887SRui Paulo if (sc->model->crd_get) {
1163aea61887SRui Paulo status = acpi_GetInteger(sc->handle,
1164aea61887SRui Paulo sc->model->crd_get, &sc->s_crd);
1165aea61887SRui Paulo if (ACPI_SUCCESS(status))
1166aea61887SRui Paulo return (TRUE);
1167aea61887SRui Paulo }
1168aea61887SRui Paulo return (FALSE);
11690fc34be4SRui Paulo case ACPI_ASUS_METHOD_WLAN:
11700fc34be4SRui Paulo if (sc->model->wlan_get) {
11710fc34be4SRui Paulo status = acpi_GetInteger(sc->handle,
11720fc34be4SRui Paulo sc->model->wlan_get, &sc->s_wlan);
11730fc34be4SRui Paulo if (ACPI_SUCCESS(status))
11740fc34be4SRui Paulo return (TRUE);
11750fc34be4SRui Paulo }
11760fc34be4SRui Paulo return (FALSE);
1177d8e0b9e1SPhilip Paeps }
1178d8e0b9e1SPhilip Paeps return (FALSE);
11799a1fc77eSPhilip Paeps }
11809a1fc77eSPhilip Paeps
11819a1fc77eSPhilip Paeps static void
acpi_asus_notify(ACPI_HANDLE h,UINT32 notify,void * context)11829a1fc77eSPhilip Paeps acpi_asus_notify(ACPI_HANDLE h, UINT32 notify, void *context)
11839a1fc77eSPhilip Paeps {
11849a1fc77eSPhilip Paeps struct acpi_asus_softc *sc;
11859a1fc77eSPhilip Paeps struct acpi_softc *acpi_sc;
11869a1fc77eSPhilip Paeps
11879a1fc77eSPhilip Paeps ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
11889a1fc77eSPhilip Paeps
11899a1fc77eSPhilip Paeps sc = device_get_softc((device_t)context);
11909a1fc77eSPhilip Paeps acpi_sc = acpi_device_get_parent_softc(sc->dev);
11919a1fc77eSPhilip Paeps
11921051a7c2SNate Lawson ACPI_SERIAL_BEGIN(asus);
11939a1fc77eSPhilip Paeps if ((notify & ~0x10) <= 15) {
1194b4cb1402SNate Lawson sc->s_brn = notify & ~0x10;
11959a1fc77eSPhilip Paeps ACPI_VPRINT(sc->dev, acpi_sc, "Brightness increased\n");
11969a1fc77eSPhilip Paeps } else if ((notify & ~0x20) <= 15) {
1197b4cb1402SNate Lawson sc->s_brn = notify & ~0x20;
11989a1fc77eSPhilip Paeps ACPI_VPRINT(sc->dev, acpi_sc, "Brightness decreased\n");
11999a1fc77eSPhilip Paeps } else if (notify == 0x33) {
12009a1fc77eSPhilip Paeps sc->s_lcd = 1;
12019a1fc77eSPhilip Paeps ACPI_VPRINT(sc->dev, acpi_sc, "LCD turned on\n");
12029a1fc77eSPhilip Paeps } else if (notify == 0x34) {
12039a1fc77eSPhilip Paeps sc->s_lcd = 0;
12049a1fc77eSPhilip Paeps ACPI_VPRINT(sc->dev, acpi_sc, "LCD turned off\n");
120531fb9906SRui Paulo } else if (notify == 0x86) {
120631fb9906SRui Paulo acpi_asus_sysctl_set(sc, ACPI_ASUS_METHOD_BRN, sc->s_brn-1);
120731fb9906SRui Paulo ACPI_VPRINT(sc->dev, acpi_sc, "Brightness decreased\n");
120831fb9906SRui Paulo } else if (notify == 0x87) {
120931fb9906SRui Paulo acpi_asus_sysctl_set(sc, ACPI_ASUS_METHOD_BRN, sc->s_brn+1);
121031fb9906SRui Paulo ACPI_VPRINT(sc->dev, acpi_sc, "Brightness increased\n");
12119a1fc77eSPhilip Paeps } else {
12129a1fc77eSPhilip Paeps /* Notify devd(8) */
12139a1fc77eSPhilip Paeps acpi_UserNotify("ASUS", h, notify);
12149a1fc77eSPhilip Paeps }
12151051a7c2SNate Lawson ACPI_SERIAL_END(asus);
12169a1fc77eSPhilip Paeps }
1217aea61887SRui Paulo
1218aea61887SRui Paulo static void
acpi_asus_lcdd_notify(ACPI_HANDLE h,UINT32 notify,void * context)121931fb9906SRui Paulo acpi_asus_lcdd_notify(ACPI_HANDLE h, UINT32 notify, void *context)
122031fb9906SRui Paulo {
122131fb9906SRui Paulo struct acpi_asus_softc *sc;
122231fb9906SRui Paulo struct acpi_softc *acpi_sc;
122331fb9906SRui Paulo
122431fb9906SRui Paulo ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
122531fb9906SRui Paulo
122631fb9906SRui Paulo sc = device_get_softc((device_t)context);
122731fb9906SRui Paulo acpi_sc = acpi_device_get_parent_softc(sc->dev);
122831fb9906SRui Paulo
122931fb9906SRui Paulo ACPI_SERIAL_BEGIN(asus);
123031fb9906SRui Paulo switch (notify) {
123131fb9906SRui Paulo case 0x87:
123231fb9906SRui Paulo acpi_asus_sysctl_set(sc, ACPI_ASUS_METHOD_BRN, sc->s_brn-1);
123331fb9906SRui Paulo ACPI_VPRINT(sc->dev, acpi_sc, "Brightness decreased\n");
123431fb9906SRui Paulo break;
123531fb9906SRui Paulo case 0x86:
123631fb9906SRui Paulo acpi_asus_sysctl_set(sc, ACPI_ASUS_METHOD_BRN, sc->s_brn+1);
123731fb9906SRui Paulo ACPI_VPRINT(sc->dev, acpi_sc, "Brightness increased\n");
123831fb9906SRui Paulo break;
123931fb9906SRui Paulo }
124031fb9906SRui Paulo ACPI_SERIAL_END(asus);
124131fb9906SRui Paulo }
124231fb9906SRui Paulo
124331fb9906SRui Paulo static void
acpi_asus_eeepc_notify(ACPI_HANDLE h,UINT32 notify,void * context)1244aea61887SRui Paulo acpi_asus_eeepc_notify(ACPI_HANDLE h, UINT32 notify, void *context)
1245aea61887SRui Paulo {
1246aea61887SRui Paulo struct acpi_asus_softc *sc;
1247aea61887SRui Paulo struct acpi_softc *acpi_sc;
1248aea61887SRui Paulo
1249aea61887SRui Paulo ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
1250aea61887SRui Paulo
1251aea61887SRui Paulo sc = device_get_softc((device_t)context);
1252aea61887SRui Paulo acpi_sc = acpi_device_get_parent_softc(sc->dev);
1253aea61887SRui Paulo
1254aea61887SRui Paulo ACPI_SERIAL_BEGIN(asus);
1255aea61887SRui Paulo if ((notify & ~0x20) <= 15) {
1256aea61887SRui Paulo sc->s_brn = notify & ~0x20;
1257aea61887SRui Paulo ACPI_VPRINT(sc->dev, acpi_sc,
1258aea61887SRui Paulo "Brightness increased/decreased\n");
1259aea61887SRui Paulo } else {
1260aea61887SRui Paulo /* Notify devd(8) */
1261aea61887SRui Paulo acpi_UserNotify("ASUS-Eee", h, notify);
1262aea61887SRui Paulo }
1263aea61887SRui Paulo ACPI_SERIAL_END(asus);
1264aea61887SRui Paulo }
1265