19a8b554fSPhilip Paeps /*- 29a8b554fSPhilip Paeps * Copyright (c) 2002 Sean Bullington <seanATstalker.org> 3c82eedb4SAndriy Gapon * 2003-2008 Anish Mistry <amistry@am-productions.biz> 49a8b554fSPhilip Paeps * 2004 Mark Santcroos <marks@ripe.net> 59a8b554fSPhilip Paeps * All Rights Reserved. 69a8b554fSPhilip Paeps * 79a8b554fSPhilip Paeps * Redistribution and use in source and binary forms, with or without 89a8b554fSPhilip Paeps * modification, are permitted provided that the following conditions 99a8b554fSPhilip Paeps * are met: 109a8b554fSPhilip Paeps * 1. Redistributions of source code must retain the above copyright 119a8b554fSPhilip Paeps * notice, this list of conditions and the following disclaimer. 129a8b554fSPhilip Paeps * 2. Redistributions in binary form must reproduce the above copyright 139a8b554fSPhilip Paeps * notice, this list of conditions and the following disclaimer in the 149a8b554fSPhilip Paeps * documentation and/or other materials provided with the distribution. 159a8b554fSPhilip Paeps * 169a8b554fSPhilip Paeps * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 179a8b554fSPhilip Paeps * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 189a8b554fSPhilip Paeps * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 199a8b554fSPhilip Paeps * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 209a8b554fSPhilip Paeps * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 219a8b554fSPhilip Paeps * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 229a8b554fSPhilip Paeps * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 239a8b554fSPhilip Paeps * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 249a8b554fSPhilip Paeps * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 259a8b554fSPhilip Paeps * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 269a8b554fSPhilip Paeps * SUCH DAMAGE. 279a8b554fSPhilip Paeps * 289a8b554fSPhilip Paeps */ 299a8b554fSPhilip Paeps 309a8b554fSPhilip Paeps #include <sys/cdefs.h> 319a8b554fSPhilip Paeps __FBSDID("$FreeBSD$"); 329a8b554fSPhilip Paeps 339a8b554fSPhilip Paeps #include "opt_acpi.h" 349a8b554fSPhilip Paeps #include <sys/param.h> 359a8b554fSPhilip Paeps #include <sys/kernel.h> 369a8b554fSPhilip Paeps #include <sys/bus.h> 379a8b554fSPhilip Paeps #include <sys/module.h> 389a8b554fSPhilip Paeps #include <sys/sysctl.h> 399a8b554fSPhilip Paeps 40129d3046SJung-uk Kim #include <contrib/dev/acpica/include/acpi.h> 41129d3046SJung-uk Kim #include <contrib/dev/acpica/include/accommon.h> 42129d3046SJung-uk Kim 439a8b554fSPhilip Paeps #include <dev/acpica/acpivar.h> 449a8b554fSPhilip Paeps 459a8b554fSPhilip Paeps /* Hooks for the ACPI CA debugging infrastructure */ 469a8b554fSPhilip Paeps #define _COMPONENT ACPI_OEM 479a8b554fSPhilip Paeps ACPI_MODULE_NAME("Fujitsu") 489a8b554fSPhilip Paeps 49b9abb62dSPhilip Paeps /* Change and update bits for the hotkeys */ 509a8b554fSPhilip Paeps #define VOLUME_MUTE_BIT 0x40000000 519a8b554fSPhilip Paeps 529a8b554fSPhilip Paeps /* Values of settings */ 539a8b554fSPhilip Paeps #define GENERAL_SETTING_BITS 0x0fffffff 549a8b554fSPhilip Paeps #define MOUSE_SETTING_BITS GENERAL_SETTING_BITS 559a8b554fSPhilip Paeps #define VOLUME_SETTING_BITS GENERAL_SETTING_BITS 569a8b554fSPhilip Paeps #define BRIGHTNESS_SETTING_BITS GENERAL_SETTING_BITS 579a8b554fSPhilip Paeps 589a8b554fSPhilip Paeps /* Possible state changes */ 59b9abb62dSPhilip Paeps /* 60b9abb62dSPhilip Paeps * These are NOT arbitrary values. They are the 61b9abb62dSPhilip Paeps * GHKS return value from the device that says which 62b9abb62dSPhilip Paeps * hotkey is active. They should match up with a bit 63b9abb62dSPhilip Paeps * from the GSIF bitmask. 64b9abb62dSPhilip Paeps */ 65b9abb62dSPhilip Paeps #define BRIGHT_CHANGED 0x01 66b9abb62dSPhilip Paeps #define VOLUME_CHANGED 0x04 67b9abb62dSPhilip Paeps #define MOUSE_CHANGED 0x08 68b9abb62dSPhilip Paeps /* 69b9abb62dSPhilip Paeps * It is unknown which hotkey this bit is supposed to indicate, but 70b9abb62dSPhilip Paeps * according to values from GSIF this is a valid flag. 71b9abb62dSPhilip Paeps */ 72b9abb62dSPhilip Paeps #define UNKNOWN_CHANGED 0x10 739a8b554fSPhilip Paeps 749a8b554fSPhilip Paeps /* sysctl values */ 759a8b554fSPhilip Paeps #define FN_MUTE 0 769a8b554fSPhilip Paeps #define FN_POINTER_ENABLE 1 779a8b554fSPhilip Paeps #define FN_LCD_BRIGHTNESS 2 789a8b554fSPhilip Paeps #define FN_VOLUME 3 799a8b554fSPhilip Paeps 809a8b554fSPhilip Paeps /* Methods */ 819a8b554fSPhilip Paeps #define METHOD_GBLL 1 829a8b554fSPhilip Paeps #define METHOD_GMOU 2 839a8b554fSPhilip Paeps #define METHOD_GVOL 3 849a8b554fSPhilip Paeps #define METHOD_MUTE 4 85b9abb62dSPhilip Paeps #define METHOD_RBLL 5 86b9abb62dSPhilip Paeps #define METHOD_RVOL 6 87b9abb62dSPhilip Paeps #define METHOD_GSIF 7 88b9abb62dSPhilip Paeps #define METHOD_GHKS 8 89c82eedb4SAndriy Gapon #define METHOD_GBLS 9 909a8b554fSPhilip Paeps 919a8b554fSPhilip Paeps /* Notify event */ 929a8b554fSPhilip Paeps #define ACPI_NOTIFY_STATUS_CHANGED 0x80 939a8b554fSPhilip Paeps 949a8b554fSPhilip Paeps /* 959a8b554fSPhilip Paeps * Holds a control method name and its associated integer value. 969a8b554fSPhilip Paeps * Only used for no-argument control methods which return a value. 979a8b554fSPhilip Paeps */ 989a8b554fSPhilip Paeps struct int_nameval { 999a8b554fSPhilip Paeps char *name; 1009a8b554fSPhilip Paeps int value; 101b9abb62dSPhilip Paeps int exists; 1029a8b554fSPhilip Paeps }; 1039a8b554fSPhilip Paeps 1049a8b554fSPhilip Paeps /* 1059a8b554fSPhilip Paeps * Driver extension for the FUJITSU ACPI driver. 1069a8b554fSPhilip Paeps */ 1079a8b554fSPhilip Paeps struct acpi_fujitsu_softc { 1089a8b554fSPhilip Paeps device_t dev; 1099a8b554fSPhilip Paeps ACPI_HANDLE handle; 1109a8b554fSPhilip Paeps 1119a8b554fSPhilip Paeps /* Control methods */ 1129a8b554fSPhilip Paeps struct int_nameval _sta, /* unused */ 1139a8b554fSPhilip Paeps gbll, /* brightness */ 114c82eedb4SAndriy Gapon gbls, /* get brightness state */ 115b9abb62dSPhilip Paeps ghks, /* hotkey selector */ 116b9abb62dSPhilip Paeps gbuf, /* unused (buffer?) */ 1179a8b554fSPhilip Paeps gmou, /* mouse */ 118b9abb62dSPhilip Paeps gsif, /* function key bitmask */ 1199a8b554fSPhilip Paeps gvol, /* volume */ 120b9abb62dSPhilip Paeps rbll, /* number of brightness levels (radix) */ 121b9abb62dSPhilip Paeps rvol; /* number of volume levels (radix) */ 1229a8b554fSPhilip Paeps 1239a8b554fSPhilip Paeps /* State variables */ 1249a8b554fSPhilip Paeps uint8_t bIsMuted; /* Is volume muted */ 1259a8b554fSPhilip Paeps uint8_t bIntPtrEnabled; /* Is internal ptr enabled */ 1269a8b554fSPhilip Paeps uint32_t lastValChanged; /* The last value updated */ 1279a8b554fSPhilip Paeps 1289a8b554fSPhilip Paeps /* sysctl tree */ 1299a8b554fSPhilip Paeps struct sysctl_ctx_list sysctl_ctx; 1309a8b554fSPhilip Paeps struct sysctl_oid *sysctl_tree; 1319a8b554fSPhilip Paeps }; 1329a8b554fSPhilip Paeps 1339a8b554fSPhilip Paeps /* Driver entry point forward declarations. */ 1349a8b554fSPhilip Paeps static int acpi_fujitsu_probe(device_t dev); 1359a8b554fSPhilip Paeps static int acpi_fujitsu_attach(device_t dev); 1369a8b554fSPhilip Paeps static int acpi_fujitsu_detach(device_t dev); 1379a8b554fSPhilip Paeps static int acpi_fujitsu_suspend(device_t dev); 1389a8b554fSPhilip Paeps static int acpi_fujitsu_resume(device_t dev); 1399a8b554fSPhilip Paeps 1409a8b554fSPhilip Paeps static void acpi_fujitsu_notify_status_changed(void *arg); 1419a8b554fSPhilip Paeps static void acpi_fujitsu_notify_handler(ACPI_HANDLE h, uint32_t notify, void *context); 1429a8b554fSPhilip Paeps static int acpi_fujitsu_sysctl(SYSCTL_HANDLER_ARGS); 1439a8b554fSPhilip Paeps 1449a8b554fSPhilip Paeps /* Utility function declarations */ 1459a8b554fSPhilip Paeps static uint8_t acpi_fujitsu_update(struct acpi_fujitsu_softc *sc); 1469a8b554fSPhilip Paeps static uint8_t acpi_fujitsu_init(struct acpi_fujitsu_softc *sc); 147b9abb62dSPhilip Paeps static uint8_t acpi_fujitsu_check_hardware(struct acpi_fujitsu_softc *sc); 1489a8b554fSPhilip Paeps 1499a8b554fSPhilip Paeps /* Driver/Module specific structure definitions. */ 1509a8b554fSPhilip Paeps static device_method_t acpi_fujitsu_methods[] = { 1519a8b554fSPhilip Paeps /* Device interface */ 1529a8b554fSPhilip Paeps DEVMETHOD(device_probe, acpi_fujitsu_probe), 1539a8b554fSPhilip Paeps DEVMETHOD(device_attach, acpi_fujitsu_attach), 1549a8b554fSPhilip Paeps DEVMETHOD(device_detach, acpi_fujitsu_detach), 1559a8b554fSPhilip Paeps DEVMETHOD(device_suspend, acpi_fujitsu_suspend), 1569a8b554fSPhilip Paeps DEVMETHOD(device_resume, acpi_fujitsu_resume), 15761bfd867SSofian Brabez 15861bfd867SSofian Brabez DEVMETHOD_END 1599a8b554fSPhilip Paeps }; 1609a8b554fSPhilip Paeps 1619a8b554fSPhilip Paeps static driver_t acpi_fujitsu_driver = { 1629a8b554fSPhilip Paeps "acpi_fujitsu", 1639a8b554fSPhilip Paeps acpi_fujitsu_methods, 1649a8b554fSPhilip Paeps sizeof(struct acpi_fujitsu_softc), 1659a8b554fSPhilip Paeps }; 1669a8b554fSPhilip Paeps 167b9abb62dSPhilip Paeps /* Prototype for function hotkeys for getting/setting a value. */ 1689a8b554fSPhilip Paeps static int acpi_fujitsu_method_get(struct acpi_fujitsu_softc *sc, int method); 1699a8b554fSPhilip Paeps static int acpi_fujitsu_method_set(struct acpi_fujitsu_softc *sc, int method, int value); 1709a8b554fSPhilip Paeps 1719a8b554fSPhilip Paeps static char *fujitsu_ids[] = { "FUJ02B1", NULL }; 1729a8b554fSPhilip Paeps 173b9abb62dSPhilip Paeps ACPI_SERIAL_DECL(fujitsu, "Fujitsu Function Hotkeys"); 1749a8b554fSPhilip Paeps 1759a8b554fSPhilip Paeps /* sysctl names and function calls */ 1769a8b554fSPhilip Paeps static struct { 1779a8b554fSPhilip Paeps char *name; 1789a8b554fSPhilip Paeps int method; 1799a8b554fSPhilip Paeps char *description; 1809a8b554fSPhilip Paeps } sysctl_table[] = { 1819a8b554fSPhilip Paeps { 1829a8b554fSPhilip Paeps .name = "mute", 1839a8b554fSPhilip Paeps .method = METHOD_MUTE, 1849a8b554fSPhilip Paeps .description = "Speakers/headphones mute status" 1859a8b554fSPhilip Paeps }, 1869a8b554fSPhilip Paeps { 1879a8b554fSPhilip Paeps .name = "pointer_enable", 1889a8b554fSPhilip Paeps .method = METHOD_GMOU, 1899a8b554fSPhilip Paeps .description = "Enable and disable the internal pointer" 1909a8b554fSPhilip Paeps }, 1919a8b554fSPhilip Paeps { 1929a8b554fSPhilip Paeps .name = "lcd_brightness", 1939a8b554fSPhilip Paeps .method = METHOD_GBLL, 1949a8b554fSPhilip Paeps .description = "Brightness level of the LCD panel" 1959a8b554fSPhilip Paeps }, 1969a8b554fSPhilip Paeps { 197c82eedb4SAndriy Gapon .name = "lcd_brightness", 198c82eedb4SAndriy Gapon .method = METHOD_GBLS, 199c82eedb4SAndriy Gapon .description = "Brightness level of the LCD panel" 200c82eedb4SAndriy Gapon }, 201c82eedb4SAndriy Gapon { 2029a8b554fSPhilip Paeps .name = "volume", 2039a8b554fSPhilip Paeps .method = METHOD_GVOL, 2049a8b554fSPhilip Paeps .description = "Speakers/headphones volume level" 2059a8b554fSPhilip Paeps }, 206b9abb62dSPhilip Paeps { 207b9abb62dSPhilip Paeps .name = "volume_radix", 208b9abb62dSPhilip Paeps .method = METHOD_RVOL, 209b9abb62dSPhilip Paeps .description = "Number of volume level steps" 210b9abb62dSPhilip Paeps }, 211b9abb62dSPhilip Paeps { 212b9abb62dSPhilip Paeps .name = "lcd_brightness_radix", 213b9abb62dSPhilip Paeps .method = METHOD_RBLL, 214b9abb62dSPhilip Paeps .description = "Number of brightness level steps" 215b9abb62dSPhilip Paeps }, 2169a8b554fSPhilip Paeps 2179a8b554fSPhilip Paeps { NULL, 0, NULL } 2189a8b554fSPhilip Paeps }; 2199a8b554fSPhilip Paeps 2209a8b554fSPhilip Paeps static devclass_t acpi_fujitsu_devclass; 2219a8b554fSPhilip Paeps DRIVER_MODULE(acpi_fujitsu, acpi, acpi_fujitsu_driver, 2229a8b554fSPhilip Paeps acpi_fujitsu_devclass, 0, 0); 2239a8b554fSPhilip Paeps MODULE_DEPEND(acpi_fujitsu, acpi, 1, 1, 1); 2249a8b554fSPhilip Paeps MODULE_VERSION(acpi_fujitsu, 1); 2259a8b554fSPhilip Paeps 2269a8b554fSPhilip Paeps static int 2279a8b554fSPhilip Paeps acpi_fujitsu_probe(device_t dev) 2289a8b554fSPhilip Paeps { 229b9abb62dSPhilip Paeps char *name; 230b9abb62dSPhilip Paeps char buffer[64]; 231*5efca36fSTakanori Watanabe int rv; 2329a8b554fSPhilip Paeps 233*5efca36fSTakanori Watanabe rv = ACPI_ID_PROBE(device_get_parent(dev), dev, fujitsu_ids, &name); 234*5efca36fSTakanori Watanabe if (acpi_disabled("fujitsu") || rv > 0 || device_get_unit(dev) > 1) 2359a8b554fSPhilip Paeps return (ENXIO); 236b9abb62dSPhilip Paeps sprintf(buffer, "Fujitsu Function Hotkeys %s", name); 237b9abb62dSPhilip Paeps device_set_desc_copy(dev, buffer); 2389a8b554fSPhilip Paeps 239*5efca36fSTakanori Watanabe return (rv); 2409a8b554fSPhilip Paeps } 2419a8b554fSPhilip Paeps 2429a8b554fSPhilip Paeps static int 2439a8b554fSPhilip Paeps acpi_fujitsu_attach(device_t dev) 2449a8b554fSPhilip Paeps { 2459a8b554fSPhilip Paeps struct acpi_fujitsu_softc *sc; 2469a8b554fSPhilip Paeps 2479a8b554fSPhilip Paeps ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); 2489a8b554fSPhilip Paeps 2499a8b554fSPhilip Paeps sc = device_get_softc(dev); 2509a8b554fSPhilip Paeps sc->dev = dev; 2519a8b554fSPhilip Paeps sc->handle = acpi_get_handle(dev); 2529a8b554fSPhilip Paeps 2539a8b554fSPhilip Paeps /* Install notification handler */ 2549a8b554fSPhilip Paeps AcpiInstallNotifyHandler(sc->handle, ACPI_DEVICE_NOTIFY, 2559a8b554fSPhilip Paeps acpi_fujitsu_notify_handler, sc); 2569a8b554fSPhilip Paeps 257d172be1fSEd Schouten /* Snag our default values for the hotkeys / hotkey states. */ 258b308de8bSPhilip Paeps ACPI_SERIAL_BEGIN(fujitsu); 259b308de8bSPhilip Paeps if (!acpi_fujitsu_init(sc)) 260b9abb62dSPhilip Paeps device_printf(dev, "Couldn't initialize hotkey states!\n"); 261b308de8bSPhilip Paeps ACPI_SERIAL_END(fujitsu); 2629a8b554fSPhilip Paeps 2639a8b554fSPhilip Paeps return (0); 2649a8b554fSPhilip Paeps } 2659a8b554fSPhilip Paeps 2669a8b554fSPhilip Paeps /* 2679a8b554fSPhilip Paeps * Called when the system is being suspended, simply 2689a8b554fSPhilip Paeps * set an event to be signalled when we wake up. 2699a8b554fSPhilip Paeps */ 2709a8b554fSPhilip Paeps static int 2719a8b554fSPhilip Paeps acpi_fujitsu_suspend(device_t dev) 2729a8b554fSPhilip Paeps { 2739a8b554fSPhilip Paeps 2749a8b554fSPhilip Paeps return (0); 2759a8b554fSPhilip Paeps } 2769a8b554fSPhilip Paeps 2779a8b554fSPhilip Paeps static int 2789a8b554fSPhilip Paeps acpi_fujitsu_resume(device_t dev) 2799a8b554fSPhilip Paeps { 2809a8b554fSPhilip Paeps struct acpi_fujitsu_softc *sc; 2819a8b554fSPhilip Paeps ACPI_STATUS status; 2829a8b554fSPhilip Paeps 2839a8b554fSPhilip Paeps sc = device_get_softc(dev); 2849a8b554fSPhilip Paeps 2859a8b554fSPhilip Paeps /* 2869a8b554fSPhilip Paeps * The pointer needs to be re-enabled for 2879a8b554fSPhilip Paeps * some revisions of the P series (2120). 2889a8b554fSPhilip Paeps */ 2899a8b554fSPhilip Paeps ACPI_SERIAL_BEGIN(fujitsu); 2909a8b554fSPhilip Paeps 291b9abb62dSPhilip Paeps if(sc->gmou.exists) { 2929a8b554fSPhilip Paeps status = acpi_SetInteger(sc->handle, "SMOU", 1); 2939a8b554fSPhilip Paeps if (ACPI_FAILURE(status)) 2949a8b554fSPhilip Paeps device_printf(sc->dev, "Couldn't enable pointer\n"); 295b9abb62dSPhilip Paeps } 2969a8b554fSPhilip Paeps ACPI_SERIAL_END(fujitsu); 2979a8b554fSPhilip Paeps 2989a8b554fSPhilip Paeps return (0); 2999a8b554fSPhilip Paeps } 3009a8b554fSPhilip Paeps 3019a8b554fSPhilip Paeps static void 3029a8b554fSPhilip Paeps acpi_fujitsu_notify_status_changed(void *arg) 3039a8b554fSPhilip Paeps { 3049a8b554fSPhilip Paeps struct acpi_fujitsu_softc *sc; 3059a8b554fSPhilip Paeps 3069a8b554fSPhilip Paeps ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); 3079a8b554fSPhilip Paeps 3089a8b554fSPhilip Paeps sc = (struct acpi_fujitsu_softc *)arg; 3099a8b554fSPhilip Paeps 3109a8b554fSPhilip Paeps /* 3119a8b554fSPhilip Paeps * Since our notify function is called, we know something has 3129a8b554fSPhilip Paeps * happened. So the only reason for acpi_fujitsu_update to fail 3139a8b554fSPhilip Paeps * is if we can't find what has changed or an error occurs. 3149a8b554fSPhilip Paeps */ 3159a8b554fSPhilip Paeps ACPI_SERIAL_BEGIN(fujitsu); 3169a8b554fSPhilip Paeps acpi_fujitsu_update(sc); 3179a8b554fSPhilip Paeps ACPI_SERIAL_END(fujitsu); 3189a8b554fSPhilip Paeps } 3199a8b554fSPhilip Paeps 3209a8b554fSPhilip Paeps 3219a8b554fSPhilip Paeps static void 3229a8b554fSPhilip Paeps acpi_fujitsu_notify_handler(ACPI_HANDLE h, uint32_t notify, void *context) 3239a8b554fSPhilip Paeps { 3249a8b554fSPhilip Paeps struct acpi_fujitsu_softc *sc; 3259a8b554fSPhilip Paeps 3269a8b554fSPhilip Paeps ACPI_FUNCTION_TRACE_U32((char *)(uintptr_t)__func__, notify); 3279a8b554fSPhilip Paeps 3289a8b554fSPhilip Paeps sc = (struct acpi_fujitsu_softc *)context; 3299a8b554fSPhilip Paeps 3309a8b554fSPhilip Paeps switch (notify) { 3319a8b554fSPhilip Paeps case ACPI_NOTIFY_STATUS_CHANGED: 3322be4e471SJung-uk Kim AcpiOsExecute(OSL_NOTIFY_HANDLER, 3339a8b554fSPhilip Paeps acpi_fujitsu_notify_status_changed, sc); 3349a8b554fSPhilip Paeps break; 3359a8b554fSPhilip Paeps default: 3369a8b554fSPhilip Paeps /* unknown notification value */ 3379a8b554fSPhilip Paeps break; 3389a8b554fSPhilip Paeps } 3399a8b554fSPhilip Paeps } 3409a8b554fSPhilip Paeps 3419a8b554fSPhilip Paeps static int 3429a8b554fSPhilip Paeps acpi_fujitsu_detach(device_t dev) 3439a8b554fSPhilip Paeps { 3449a8b554fSPhilip Paeps struct acpi_fujitsu_softc *sc; 3459a8b554fSPhilip Paeps 3469a8b554fSPhilip Paeps sc = device_get_softc(dev); 3479a8b554fSPhilip Paeps AcpiRemoveNotifyHandler(sc->handle, ACPI_DEVICE_NOTIFY, 3489a8b554fSPhilip Paeps acpi_fujitsu_notify_handler); 3499a8b554fSPhilip Paeps 3509a8b554fSPhilip Paeps sysctl_ctx_free(&sc->sysctl_ctx); 3519a8b554fSPhilip Paeps 3529a8b554fSPhilip Paeps return (0); 3539a8b554fSPhilip Paeps } 3549a8b554fSPhilip Paeps 3559a8b554fSPhilip Paeps /* 3569a8b554fSPhilip Paeps * Initializes the names of the ACPI control methods and grabs 357b9abb62dSPhilip Paeps * the current state of all of the ACPI hotkeys into the softc. 3589a8b554fSPhilip Paeps */ 3599a8b554fSPhilip Paeps static uint8_t 3609a8b554fSPhilip Paeps acpi_fujitsu_init(struct acpi_fujitsu_softc *sc) 3619a8b554fSPhilip Paeps { 3629a8b554fSPhilip Paeps struct acpi_softc *acpi_sc; 363b9abb62dSPhilip Paeps int i, exists; 3649a8b554fSPhilip Paeps 3659a8b554fSPhilip Paeps ACPI_SERIAL_ASSERT(fujitsu); 3669a8b554fSPhilip Paeps 3679a8b554fSPhilip Paeps /* Setup all of the names for each control method */ 3689a8b554fSPhilip Paeps sc->_sta.name = "_STA"; 3699a8b554fSPhilip Paeps sc->gbll.name = "GBLL"; 370c82eedb4SAndriy Gapon sc->gbls.name = "GBLS"; 3719a8b554fSPhilip Paeps sc->ghks.name = "GHKS"; 3729a8b554fSPhilip Paeps sc->gmou.name = "GMOU"; 3739a8b554fSPhilip Paeps sc->gsif.name = "GSIF"; 3749a8b554fSPhilip Paeps sc->gvol.name = "GVOL"; 375b9abb62dSPhilip Paeps sc->ghks.name = "GHKS"; 376b9abb62dSPhilip Paeps sc->gsif.name = "GSIF"; 3779a8b554fSPhilip Paeps sc->rbll.name = "RBLL"; 3789a8b554fSPhilip Paeps sc->rvol.name = "RVOL"; 3799a8b554fSPhilip Paeps 380b9abb62dSPhilip Paeps /* Determine what hardware functionality is available */ 381b9abb62dSPhilip Paeps acpi_fujitsu_check_hardware(sc); 382b9abb62dSPhilip Paeps 3839a8b554fSPhilip Paeps /* Build the sysctl tree */ 3849a8b554fSPhilip Paeps acpi_sc = acpi_device_get_parent_softc(sc->dev); 3859a8b554fSPhilip Paeps sysctl_ctx_init(&sc->sysctl_ctx); 3869a8b554fSPhilip Paeps sc->sysctl_tree = SYSCTL_ADD_NODE(&sc->sysctl_ctx, 3879a8b554fSPhilip Paeps SYSCTL_CHILDREN(acpi_sc->acpi_sysctl_tree), 3889a8b554fSPhilip Paeps OID_AUTO, "fujitsu", CTLFLAG_RD, 0, ""); 3899a8b554fSPhilip Paeps 3909a8b554fSPhilip Paeps for (i = 0; sysctl_table[i].name != NULL; i++) { 391b9abb62dSPhilip Paeps switch(sysctl_table[i].method) { 392b9abb62dSPhilip Paeps case METHOD_GMOU: 393b9abb62dSPhilip Paeps exists = sc->gmou.exists; 394b9abb62dSPhilip Paeps break; 395b9abb62dSPhilip Paeps case METHOD_GBLL: 396b9abb62dSPhilip Paeps exists = sc->gbll.exists; 397b9abb62dSPhilip Paeps break; 398c82eedb4SAndriy Gapon case METHOD_GBLS: 399c82eedb4SAndriy Gapon exists = sc->gbls.exists; 400c82eedb4SAndriy Gapon break; 401b9abb62dSPhilip Paeps case METHOD_GVOL: 402b9abb62dSPhilip Paeps case METHOD_MUTE: 403b9abb62dSPhilip Paeps exists = sc->gvol.exists; 404b9abb62dSPhilip Paeps break; 405b9abb62dSPhilip Paeps case METHOD_RVOL: 406b9abb62dSPhilip Paeps exists = sc->rvol.exists; 407b9abb62dSPhilip Paeps break; 408b9abb62dSPhilip Paeps case METHOD_RBLL: 409b9abb62dSPhilip Paeps exists = sc->rbll.exists; 410b9abb62dSPhilip Paeps break; 411b9abb62dSPhilip Paeps default: 412b9abb62dSPhilip Paeps /* Allow by default */ 413b9abb62dSPhilip Paeps exists = 1; 414b9abb62dSPhilip Paeps break; 415b9abb62dSPhilip Paeps } 416b9abb62dSPhilip Paeps if(!exists) 417b9abb62dSPhilip Paeps continue; 4189a8b554fSPhilip Paeps SYSCTL_ADD_PROC(&sc->sysctl_ctx, 4199a8b554fSPhilip Paeps SYSCTL_CHILDREN(sc->sysctl_tree), OID_AUTO, 4209a8b554fSPhilip Paeps sysctl_table[i].name, 4219a8b554fSPhilip Paeps CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY, 4229a8b554fSPhilip Paeps sc, i, acpi_fujitsu_sysctl, "I", 4239a8b554fSPhilip Paeps sysctl_table[i].description); 4249a8b554fSPhilip Paeps } 4259a8b554fSPhilip Paeps 426b9abb62dSPhilip Paeps 427b9abb62dSPhilip Paeps /* Set the hotkeys to their initial states */ 4289a8b554fSPhilip Paeps if (!acpi_fujitsu_update(sc)) { 429b9abb62dSPhilip Paeps device_printf(sc->dev, "Couldn't init hotkey states\n"); 4309a8b554fSPhilip Paeps return (FALSE); 4319a8b554fSPhilip Paeps } 4329a8b554fSPhilip Paeps 4339a8b554fSPhilip Paeps return (TRUE); 4349a8b554fSPhilip Paeps } 4359a8b554fSPhilip Paeps 4369a8b554fSPhilip Paeps static int 4379a8b554fSPhilip Paeps acpi_fujitsu_sysctl(SYSCTL_HANDLER_ARGS) 4389a8b554fSPhilip Paeps { 4399a8b554fSPhilip Paeps struct acpi_fujitsu_softc *sc; 4409a8b554fSPhilip Paeps int method; 4419a8b554fSPhilip Paeps int arg; 4429a8b554fSPhilip Paeps int function_num, error = 0; 4439a8b554fSPhilip Paeps 4449a8b554fSPhilip Paeps sc = (struct acpi_fujitsu_softc *)oidp->oid_arg1; 4459a8b554fSPhilip Paeps function_num = oidp->oid_arg2; 4469a8b554fSPhilip Paeps method = sysctl_table[function_num].method; 4479a8b554fSPhilip Paeps 4489a8b554fSPhilip Paeps ACPI_SERIAL_BEGIN(fujitsu); 4499a8b554fSPhilip Paeps 4509a8b554fSPhilip Paeps /* Get the current value */ 4519a8b554fSPhilip Paeps arg = acpi_fujitsu_method_get(sc, method); 4529a8b554fSPhilip Paeps error = sysctl_handle_int(oidp, &arg, 0, req); 4539a8b554fSPhilip Paeps 4549a8b554fSPhilip Paeps if (error != 0 || req->newptr == NULL) 4559a8b554fSPhilip Paeps goto out; 4569a8b554fSPhilip Paeps 4579a8b554fSPhilip Paeps /* Update the value */ 4589a8b554fSPhilip Paeps error = acpi_fujitsu_method_set(sc, method, arg); 4599a8b554fSPhilip Paeps 4609a8b554fSPhilip Paeps out: 4619a8b554fSPhilip Paeps ACPI_SERIAL_END(fujitsu); 4629a8b554fSPhilip Paeps return (error); 4639a8b554fSPhilip Paeps } 4649a8b554fSPhilip Paeps 4659a8b554fSPhilip Paeps static int 4669a8b554fSPhilip Paeps acpi_fujitsu_method_get(struct acpi_fujitsu_softc *sc, int method) 4679a8b554fSPhilip Paeps { 4689a8b554fSPhilip Paeps struct int_nameval nv; 4699a8b554fSPhilip Paeps ACPI_STATUS status; 4709a8b554fSPhilip Paeps 4719a8b554fSPhilip Paeps ACPI_SERIAL_ASSERT(fujitsu); 4729a8b554fSPhilip Paeps 4739a8b554fSPhilip Paeps switch (method) { 4749a8b554fSPhilip Paeps case METHOD_GBLL: 4759a8b554fSPhilip Paeps nv = sc->gbll; 4769a8b554fSPhilip Paeps break; 477c82eedb4SAndriy Gapon case METHOD_GBLS: 478c82eedb4SAndriy Gapon nv = sc->gbls; 479c82eedb4SAndriy Gapon break; 4809a8b554fSPhilip Paeps case METHOD_GMOU: 4819a8b554fSPhilip Paeps nv = sc->gmou; 4829a8b554fSPhilip Paeps break; 4839a8b554fSPhilip Paeps case METHOD_GVOL: 4849a8b554fSPhilip Paeps case METHOD_MUTE: 4859a8b554fSPhilip Paeps nv = sc->gvol; 4869a8b554fSPhilip Paeps break; 487b9abb62dSPhilip Paeps case METHOD_GHKS: 488b9abb62dSPhilip Paeps nv = sc->ghks; 489b9abb62dSPhilip Paeps break; 490b9abb62dSPhilip Paeps case METHOD_GSIF: 491b9abb62dSPhilip Paeps nv = sc->gsif; 492b9abb62dSPhilip Paeps break; 493b9abb62dSPhilip Paeps case METHOD_RBLL: 494b9abb62dSPhilip Paeps nv = sc->rbll; 495b9abb62dSPhilip Paeps break; 496b9abb62dSPhilip Paeps case METHOD_RVOL: 497b9abb62dSPhilip Paeps nv = sc->rvol; 498b9abb62dSPhilip Paeps break; 4999a8b554fSPhilip Paeps default: 5009a8b554fSPhilip Paeps return (FALSE); 5019a8b554fSPhilip Paeps } 5029a8b554fSPhilip Paeps 503b9abb62dSPhilip Paeps if(!nv.exists) 504b9abb62dSPhilip Paeps return (EINVAL); 505b9abb62dSPhilip Paeps 5069a8b554fSPhilip Paeps status = acpi_GetInteger(sc->handle, nv.name, &nv.value); 5079a8b554fSPhilip Paeps if (ACPI_FAILURE(status)) { 508b9abb62dSPhilip Paeps device_printf(sc->dev, "Couldn't query method (%s)\n", nv.name); 5099a8b554fSPhilip Paeps return (FALSE); 5109a8b554fSPhilip Paeps } 5119a8b554fSPhilip Paeps 5129a8b554fSPhilip Paeps if (method == METHOD_MUTE) { 5139a8b554fSPhilip Paeps sc->bIsMuted = (uint8_t)((nv.value & VOLUME_MUTE_BIT) != 0); 5149a8b554fSPhilip Paeps return (sc->bIsMuted); 5159a8b554fSPhilip Paeps } 5169a8b554fSPhilip Paeps 5179a8b554fSPhilip Paeps nv.value &= GENERAL_SETTING_BITS; 5189a8b554fSPhilip Paeps return (nv.value); 5199a8b554fSPhilip Paeps } 5209a8b554fSPhilip Paeps 5219a8b554fSPhilip Paeps static int 5229a8b554fSPhilip Paeps acpi_fujitsu_method_set(struct acpi_fujitsu_softc *sc, int method, int value) 5239a8b554fSPhilip Paeps { 5249a8b554fSPhilip Paeps struct int_nameval nv; 5259a8b554fSPhilip Paeps ACPI_STATUS status; 5269a8b554fSPhilip Paeps char *control; 5279a8b554fSPhilip Paeps int changed; 5289a8b554fSPhilip Paeps 5299a8b554fSPhilip Paeps ACPI_SERIAL_ASSERT(fujitsu); 5309a8b554fSPhilip Paeps 5319a8b554fSPhilip Paeps switch (method) { 5329a8b554fSPhilip Paeps case METHOD_GBLL: 5339a8b554fSPhilip Paeps changed = BRIGHT_CHANGED; 5349a8b554fSPhilip Paeps control = "SBLL"; 5359a8b554fSPhilip Paeps nv = sc->gbll; 5369a8b554fSPhilip Paeps break; 537c82eedb4SAndriy Gapon case METHOD_GBLS: 538c82eedb4SAndriy Gapon changed = BRIGHT_CHANGED; 539c82eedb4SAndriy Gapon control = "SBL2"; 540c82eedb4SAndriy Gapon nv = sc->gbls; 541c82eedb4SAndriy Gapon break; 5429a8b554fSPhilip Paeps case METHOD_GMOU: 5439a8b554fSPhilip Paeps changed = MOUSE_CHANGED; 5449a8b554fSPhilip Paeps control = "SMOU"; 5459a8b554fSPhilip Paeps nv = sc->gmou; 5469a8b554fSPhilip Paeps break; 5479a8b554fSPhilip Paeps case METHOD_GVOL: 5489a8b554fSPhilip Paeps case METHOD_MUTE: 5499a8b554fSPhilip Paeps changed = VOLUME_CHANGED; 5509a8b554fSPhilip Paeps control = "SVOL"; 5519a8b554fSPhilip Paeps nv = sc->gvol; 5529a8b554fSPhilip Paeps break; 5539a8b554fSPhilip Paeps default: 5549a8b554fSPhilip Paeps return (EINVAL); 5559a8b554fSPhilip Paeps } 5569a8b554fSPhilip Paeps 557b9abb62dSPhilip Paeps if(!nv.exists) 558b9abb62dSPhilip Paeps return (EINVAL); 559b9abb62dSPhilip Paeps 5609a8b554fSPhilip Paeps if (method == METHOD_MUTE) { 5619a8b554fSPhilip Paeps if (value == 1) 5629a8b554fSPhilip Paeps value = nv.value | VOLUME_MUTE_BIT; 5639a8b554fSPhilip Paeps else if (value == 0) 5649a8b554fSPhilip Paeps value = nv.value & ~VOLUME_MUTE_BIT; 5659a8b554fSPhilip Paeps else 5669a8b554fSPhilip Paeps return (EINVAL); 5679a8b554fSPhilip Paeps } 5689a8b554fSPhilip Paeps 5699a8b554fSPhilip Paeps status = acpi_SetInteger(sc->handle, control, value); 5709a8b554fSPhilip Paeps if (ACPI_FAILURE(status)) { 5719a8b554fSPhilip Paeps device_printf(sc->dev, "Couldn't update %s\n", control); 572b9abb62dSPhilip Paeps return (FALSE); 5739a8b554fSPhilip Paeps } 5749a8b554fSPhilip Paeps 5759a8b554fSPhilip Paeps sc->lastValChanged = changed; 5769a8b554fSPhilip Paeps return (0); 5779a8b554fSPhilip Paeps } 5789a8b554fSPhilip Paeps 5799a8b554fSPhilip Paeps /* 580b9abb62dSPhilip Paeps * Query the get methods to determine what functionality is available 581b9abb62dSPhilip Paeps * from the hardware function hotkeys. 582b9abb62dSPhilip Paeps */ 583b9abb62dSPhilip Paeps static uint8_t 584b9abb62dSPhilip Paeps acpi_fujitsu_check_hardware(struct acpi_fujitsu_softc *sc) 585b9abb62dSPhilip Paeps { 586b9abb62dSPhilip Paeps int val; 587b9abb62dSPhilip Paeps 588b9abb62dSPhilip Paeps ACPI_SERIAL_ASSERT(fujitsu); 589b9abb62dSPhilip Paeps /* save the hotkey bitmask */ 590b9abb62dSPhilip Paeps if (ACPI_FAILURE(acpi_GetInteger(sc->handle, 591b9abb62dSPhilip Paeps sc->gsif.name, &(sc->gsif.value)))) { 592b9abb62dSPhilip Paeps sc->gsif.exists = 0; 593b9abb62dSPhilip Paeps device_printf(sc->dev, "Couldn't query bitmask value\n"); 594b9abb62dSPhilip Paeps } else { 595b9abb62dSPhilip Paeps sc->gsif.exists = 1; 596b9abb62dSPhilip Paeps } 597b9abb62dSPhilip Paeps 598b9abb62dSPhilip Paeps /* System Volume Level */ 599b9abb62dSPhilip Paeps if (ACPI_FAILURE(acpi_GetInteger(sc->handle, 600b9abb62dSPhilip Paeps sc->gvol.name, &val))) { 601b9abb62dSPhilip Paeps sc->gvol.exists = 0; 602b9abb62dSPhilip Paeps } else { 603b9abb62dSPhilip Paeps sc->gvol.exists = 1; 604b9abb62dSPhilip Paeps } 605b9abb62dSPhilip Paeps 606b9abb62dSPhilip Paeps if (ACPI_FAILURE(acpi_GetInteger(sc->handle, 607c82eedb4SAndriy Gapon sc->gbls.name, &val))) { 608c82eedb4SAndriy Gapon sc->gbls.exists = 0; 609c82eedb4SAndriy Gapon } else { 610c82eedb4SAndriy Gapon sc->gbls.exists = 1; 611c82eedb4SAndriy Gapon } 612c82eedb4SAndriy Gapon 613c82eedb4SAndriy Gapon // don't add if we can use the new method 614c82eedb4SAndriy Gapon if (sc->gbls.exists || ACPI_FAILURE(acpi_GetInteger(sc->handle, 615b9abb62dSPhilip Paeps sc->gbll.name, &val))) { 616b9abb62dSPhilip Paeps sc->gbll.exists = 0; 617b9abb62dSPhilip Paeps } else { 618b9abb62dSPhilip Paeps sc->gbll.exists = 1; 619b9abb62dSPhilip Paeps } 620b9abb62dSPhilip Paeps 621b9abb62dSPhilip Paeps if (ACPI_FAILURE(acpi_GetInteger(sc->handle, 622b9abb62dSPhilip Paeps sc->ghks.name, &val))) { 623b9abb62dSPhilip Paeps sc->ghks.exists = 0; 624b9abb62dSPhilip Paeps } else { 625b9abb62dSPhilip Paeps sc->ghks.exists = 1; 626b9abb62dSPhilip Paeps } 627b9abb62dSPhilip Paeps 628b9abb62dSPhilip Paeps if (ACPI_FAILURE(acpi_GetInteger(sc->handle, 629b9abb62dSPhilip Paeps sc->gmou.name, &val))) { 630b9abb62dSPhilip Paeps sc->gmou.exists = 0; 631b9abb62dSPhilip Paeps } else { 632b9abb62dSPhilip Paeps sc->gmou.exists = 1; 633b9abb62dSPhilip Paeps } 634b9abb62dSPhilip Paeps 635b9abb62dSPhilip Paeps if (ACPI_FAILURE(acpi_GetInteger(sc->handle, 636b9abb62dSPhilip Paeps sc->rbll.name, &val))) { 637b9abb62dSPhilip Paeps sc->rbll.exists = 0; 638b9abb62dSPhilip Paeps } else { 639b9abb62dSPhilip Paeps sc->rbll.exists = 1; 640b9abb62dSPhilip Paeps } 641b9abb62dSPhilip Paeps 642b9abb62dSPhilip Paeps if (ACPI_FAILURE(acpi_GetInteger(sc->handle, 643b9abb62dSPhilip Paeps sc->rvol.name, &val))) { 644b9abb62dSPhilip Paeps sc->rvol.exists = 0; 645b9abb62dSPhilip Paeps } else { 646b9abb62dSPhilip Paeps sc->rvol.exists = 1; 647b9abb62dSPhilip Paeps } 648b9abb62dSPhilip Paeps 649b9abb62dSPhilip Paeps return (TRUE); 650b9abb62dSPhilip Paeps } 651b9abb62dSPhilip Paeps 652b9abb62dSPhilip Paeps /* 6539a8b554fSPhilip Paeps * Query each of the ACPI control methods that contain information we're 6549a8b554fSPhilip Paeps * interested in. We check the return values from the control methods and 6559a8b554fSPhilip Paeps * adjust any state variables if they should be adjusted. 6569a8b554fSPhilip Paeps */ 6579a8b554fSPhilip Paeps static uint8_t 6589a8b554fSPhilip Paeps acpi_fujitsu_update(struct acpi_fujitsu_softc *sc) 6599a8b554fSPhilip Paeps { 660b9abb62dSPhilip Paeps int changed; 6619a8b554fSPhilip Paeps struct acpi_softc *acpi_sc; 6629a8b554fSPhilip Paeps 6639a8b554fSPhilip Paeps acpi_sc = acpi_device_get_parent_softc(sc->dev); 6649a8b554fSPhilip Paeps 6659a8b554fSPhilip Paeps ACPI_SERIAL_ASSERT(fujitsu); 666b9abb62dSPhilip Paeps if(sc->gsif.exists) 667b9abb62dSPhilip Paeps changed = sc->gsif.value & acpi_fujitsu_method_get(sc,METHOD_GHKS); 668b9abb62dSPhilip Paeps else 669b9abb62dSPhilip Paeps changed = 0; 6709a8b554fSPhilip Paeps 6719a8b554fSPhilip Paeps /* System Volume Level */ 672b9abb62dSPhilip Paeps if(sc->gvol.exists) { 6739a8b554fSPhilip Paeps if (ACPI_FAILURE(acpi_GetInteger(sc->handle, 6749a8b554fSPhilip Paeps sc->gvol.name, &(sc->gvol.value)))) { 6759a8b554fSPhilip Paeps device_printf(sc->dev, "Couldn't query volume level\n"); 6769a8b554fSPhilip Paeps return (FALSE); 6779a8b554fSPhilip Paeps } 6789a8b554fSPhilip Paeps 679b9abb62dSPhilip Paeps if (changed & VOLUME_CHANGED) { 6809a8b554fSPhilip Paeps sc->bIsMuted = 6819a8b554fSPhilip Paeps (uint8_t)((sc->gvol.value & VOLUME_MUTE_BIT) != 0); 6829a8b554fSPhilip Paeps 6839a8b554fSPhilip Paeps /* Clear the modification bit */ 6849a8b554fSPhilip Paeps sc->gvol.value &= VOLUME_SETTING_BITS; 6859a8b554fSPhilip Paeps 6869a8b554fSPhilip Paeps if (sc->bIsMuted) { 6879a8b554fSPhilip Paeps acpi_UserNotify("FUJITSU", sc->handle, FN_MUTE); 6889a8b554fSPhilip Paeps ACPI_VPRINT(sc->dev, acpi_sc, "Volume is now mute\n"); 6899a8b554fSPhilip Paeps } else 6909a8b554fSPhilip Paeps ACPI_VPRINT(sc->dev, acpi_sc, "Volume is now %d\n", 6919a8b554fSPhilip Paeps sc->gvol.value); 6929a8b554fSPhilip Paeps 6939a8b554fSPhilip Paeps acpi_UserNotify("FUJITSU", sc->handle, FN_VOLUME); 694b9abb62dSPhilip Paeps } 6959a8b554fSPhilip Paeps } 6969a8b554fSPhilip Paeps 6979a8b554fSPhilip Paeps /* Internal mouse pointer (eraserhead) */ 698b9abb62dSPhilip Paeps if(sc->gmou.exists) { 6999a8b554fSPhilip Paeps if (ACPI_FAILURE(acpi_GetInteger(sc->handle, 7009a8b554fSPhilip Paeps sc->gmou.name, &(sc->gmou.value)))) { 7019a8b554fSPhilip Paeps device_printf(sc->dev, "Couldn't query pointer state\n"); 7029a8b554fSPhilip Paeps return (FALSE); 7039a8b554fSPhilip Paeps } 7049a8b554fSPhilip Paeps 705b9abb62dSPhilip Paeps if (changed & MOUSE_CHANGED) { 7069a8b554fSPhilip Paeps sc->bIntPtrEnabled = (uint8_t)(sc->gmou.value & 0x1); 7079a8b554fSPhilip Paeps 7089a8b554fSPhilip Paeps /* Clear the modification bit */ 7099a8b554fSPhilip Paeps sc->gmou.value &= MOUSE_SETTING_BITS; 7109a8b554fSPhilip Paeps 711c82eedb4SAndriy Gapon /* Set the value in case it is not hardware controlled */ 712c82eedb4SAndriy Gapon acpi_fujitsu_method_set(sc, METHOD_GMOU, sc->gmou.value); 713c82eedb4SAndriy Gapon 7149a8b554fSPhilip Paeps acpi_UserNotify("FUJITSU", sc->handle, FN_POINTER_ENABLE); 7159a8b554fSPhilip Paeps 7169a8b554fSPhilip Paeps ACPI_VPRINT(sc->dev, acpi_sc, "Internal pointer is now %s\n", 7179a8b554fSPhilip Paeps (sc->bIntPtrEnabled) ? "enabled" : "disabled"); 718b9abb62dSPhilip Paeps } 7199a8b554fSPhilip Paeps } 7209a8b554fSPhilip Paeps 721c82eedb4SAndriy Gapon /* Screen Brightness Level P8XXX */ 722c82eedb4SAndriy Gapon if(sc->gbls.exists) { 723c82eedb4SAndriy Gapon if (ACPI_FAILURE(acpi_GetInteger(sc->handle, 724c82eedb4SAndriy Gapon sc->gbls.name, &(sc->gbls.value)))) { 725c82eedb4SAndriy Gapon device_printf(sc->dev, "Couldn't query P8XXX brightness level\n"); 726c82eedb4SAndriy Gapon return (FALSE); 727c82eedb4SAndriy Gapon } 728c82eedb4SAndriy Gapon if (changed & BRIGHT_CHANGED) { 729c82eedb4SAndriy Gapon /* No state to record here. */ 730c82eedb4SAndriy Gapon 731c82eedb4SAndriy Gapon /* Clear the modification bit */ 732c82eedb4SAndriy Gapon sc->gbls.value &= BRIGHTNESS_SETTING_BITS; 733c82eedb4SAndriy Gapon 734c82eedb4SAndriy Gapon /* Set the value in case it is not hardware controlled */ 735c82eedb4SAndriy Gapon acpi_fujitsu_method_set(sc, METHOD_GBLS, sc->gbls.value); 736c82eedb4SAndriy Gapon 737c82eedb4SAndriy Gapon acpi_UserNotify("FUJITSU", sc->handle, FN_LCD_BRIGHTNESS); 738c82eedb4SAndriy Gapon 739c82eedb4SAndriy Gapon ACPI_VPRINT(sc->dev, acpi_sc, "P8XXX Brightness level is now %d\n", 740c82eedb4SAndriy Gapon sc->gbls.value); 741c82eedb4SAndriy Gapon } 742c82eedb4SAndriy Gapon } 743c82eedb4SAndriy Gapon 7449a8b554fSPhilip Paeps /* Screen Brightness Level */ 745b9abb62dSPhilip Paeps if(sc->gbll.exists) { 7469a8b554fSPhilip Paeps if (ACPI_FAILURE(acpi_GetInteger(sc->handle, 7479a8b554fSPhilip Paeps sc->gbll.name, &(sc->gbll.value)))) { 7489a8b554fSPhilip Paeps device_printf(sc->dev, "Couldn't query brightness level\n"); 7499a8b554fSPhilip Paeps return (FALSE); 7509a8b554fSPhilip Paeps } 7519a8b554fSPhilip Paeps 752b9abb62dSPhilip Paeps if (changed & BRIGHT_CHANGED) { 7539a8b554fSPhilip Paeps /* No state to record here. */ 7549a8b554fSPhilip Paeps 7559a8b554fSPhilip Paeps /* Clear the modification bit */ 7569a8b554fSPhilip Paeps sc->gbll.value &= BRIGHTNESS_SETTING_BITS; 7579a8b554fSPhilip Paeps 7589a8b554fSPhilip Paeps acpi_UserNotify("FUJITSU", sc->handle, FN_LCD_BRIGHTNESS); 7599a8b554fSPhilip Paeps 7609a8b554fSPhilip Paeps ACPI_VPRINT(sc->dev, acpi_sc, "Brightness level is now %d\n", 7619a8b554fSPhilip Paeps sc->gbll.value); 762b9abb62dSPhilip Paeps } 7639a8b554fSPhilip Paeps } 7649a8b554fSPhilip Paeps 765b9abb62dSPhilip Paeps sc->lastValChanged = changed; 7669a8b554fSPhilip Paeps return (TRUE); 7679a8b554fSPhilip Paeps } 768