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 #include "opt_acpi.h" 329a8b554fSPhilip Paeps #include <sys/param.h> 339a8b554fSPhilip Paeps #include <sys/kernel.h> 349a8b554fSPhilip Paeps #include <sys/bus.h> 359a8b554fSPhilip Paeps #include <sys/module.h> 369a8b554fSPhilip Paeps #include <sys/sysctl.h> 379a8b554fSPhilip Paeps 38129d3046SJung-uk Kim #include <contrib/dev/acpica/include/acpi.h> 39129d3046SJung-uk Kim #include <contrib/dev/acpica/include/accommon.h> 40129d3046SJung-uk Kim 419a8b554fSPhilip Paeps #include <dev/acpica/acpivar.h> 429a8b554fSPhilip Paeps 439a8b554fSPhilip Paeps /* Hooks for the ACPI CA debugging infrastructure */ 449a8b554fSPhilip Paeps #define _COMPONENT ACPI_OEM 459a8b554fSPhilip Paeps ACPI_MODULE_NAME("Fujitsu") 469a8b554fSPhilip Paeps 47b9abb62dSPhilip Paeps /* Change and update bits for the hotkeys */ 489a8b554fSPhilip Paeps #define VOLUME_MUTE_BIT 0x40000000 499a8b554fSPhilip Paeps 509a8b554fSPhilip Paeps /* Values of settings */ 519a8b554fSPhilip Paeps #define GENERAL_SETTING_BITS 0x0fffffff 529a8b554fSPhilip Paeps #define MOUSE_SETTING_BITS GENERAL_SETTING_BITS 539a8b554fSPhilip Paeps #define VOLUME_SETTING_BITS GENERAL_SETTING_BITS 549a8b554fSPhilip Paeps #define BRIGHTNESS_SETTING_BITS GENERAL_SETTING_BITS 559a8b554fSPhilip Paeps 569a8b554fSPhilip Paeps /* Possible state changes */ 57b9abb62dSPhilip Paeps /* 58b9abb62dSPhilip Paeps * These are NOT arbitrary values. They are the 59b9abb62dSPhilip Paeps * GHKS return value from the device that says which 60b9abb62dSPhilip Paeps * hotkey is active. They should match up with a bit 61b9abb62dSPhilip Paeps * from the GSIF bitmask. 62b9abb62dSPhilip Paeps */ 63b9abb62dSPhilip Paeps #define BRIGHT_CHANGED 0x01 64b9abb62dSPhilip Paeps #define VOLUME_CHANGED 0x04 65b9abb62dSPhilip Paeps #define MOUSE_CHANGED 0x08 66b9abb62dSPhilip Paeps /* 67b9abb62dSPhilip Paeps * It is unknown which hotkey this bit is supposed to indicate, but 68b9abb62dSPhilip Paeps * according to values from GSIF this is a valid flag. 69b9abb62dSPhilip Paeps */ 70b9abb62dSPhilip Paeps #define UNKNOWN_CHANGED 0x10 719a8b554fSPhilip Paeps 729a8b554fSPhilip Paeps /* sysctl values */ 739a8b554fSPhilip Paeps #define FN_MUTE 0 749a8b554fSPhilip Paeps #define FN_POINTER_ENABLE 1 759a8b554fSPhilip Paeps #define FN_LCD_BRIGHTNESS 2 769a8b554fSPhilip Paeps #define FN_VOLUME 3 779a8b554fSPhilip Paeps 789a8b554fSPhilip Paeps /* Methods */ 799a8b554fSPhilip Paeps #define METHOD_GBLL 1 809a8b554fSPhilip Paeps #define METHOD_GMOU 2 819a8b554fSPhilip Paeps #define METHOD_GVOL 3 829a8b554fSPhilip Paeps #define METHOD_MUTE 4 83b9abb62dSPhilip Paeps #define METHOD_RBLL 5 84b9abb62dSPhilip Paeps #define METHOD_RVOL 6 85b9abb62dSPhilip Paeps #define METHOD_GSIF 7 86b9abb62dSPhilip Paeps #define METHOD_GHKS 8 87c82eedb4SAndriy Gapon #define METHOD_GBLS 9 889a8b554fSPhilip Paeps 899a8b554fSPhilip Paeps /* Notify event */ 909a8b554fSPhilip Paeps #define ACPI_NOTIFY_STATUS_CHANGED 0x80 919a8b554fSPhilip Paeps 929a8b554fSPhilip Paeps /* 939a8b554fSPhilip Paeps * Holds a control method name and its associated integer value. 949a8b554fSPhilip Paeps * Only used for no-argument control methods which return a value. 959a8b554fSPhilip Paeps */ 969a8b554fSPhilip Paeps struct int_nameval { 979a8b554fSPhilip Paeps char *name; 989a8b554fSPhilip Paeps int value; 99b9abb62dSPhilip Paeps int exists; 1009a8b554fSPhilip Paeps }; 1019a8b554fSPhilip Paeps 1029a8b554fSPhilip Paeps /* 1039a8b554fSPhilip Paeps * Driver extension for the FUJITSU ACPI driver. 1049a8b554fSPhilip Paeps */ 1059a8b554fSPhilip Paeps struct acpi_fujitsu_softc { 1069a8b554fSPhilip Paeps device_t dev; 1079a8b554fSPhilip Paeps ACPI_HANDLE handle; 1089a8b554fSPhilip Paeps 1099a8b554fSPhilip Paeps /* Control methods */ 1109a8b554fSPhilip Paeps struct int_nameval _sta, /* unused */ 1119a8b554fSPhilip Paeps gbll, /* brightness */ 112c82eedb4SAndriy Gapon gbls, /* get brightness state */ 113b9abb62dSPhilip Paeps ghks, /* hotkey selector */ 114b9abb62dSPhilip Paeps gbuf, /* unused (buffer?) */ 1159a8b554fSPhilip Paeps gmou, /* mouse */ 116b9abb62dSPhilip Paeps gsif, /* function key bitmask */ 1179a8b554fSPhilip Paeps gvol, /* volume */ 118b9abb62dSPhilip Paeps rbll, /* number of brightness levels (radix) */ 119b9abb62dSPhilip Paeps rvol; /* number of volume levels (radix) */ 1209a8b554fSPhilip Paeps 1219a8b554fSPhilip Paeps /* State variables */ 1229a8b554fSPhilip Paeps uint8_t bIsMuted; /* Is volume muted */ 1239a8b554fSPhilip Paeps uint8_t bIntPtrEnabled; /* Is internal ptr enabled */ 1249a8b554fSPhilip Paeps uint32_t lastValChanged; /* The last value updated */ 1259a8b554fSPhilip Paeps 1269a8b554fSPhilip Paeps /* sysctl tree */ 1279a8b554fSPhilip Paeps struct sysctl_ctx_list sysctl_ctx; 1289a8b554fSPhilip Paeps struct sysctl_oid *sysctl_tree; 1299a8b554fSPhilip Paeps }; 1309a8b554fSPhilip Paeps 1319a8b554fSPhilip Paeps /* Driver entry point forward declarations. */ 1329a8b554fSPhilip Paeps static int acpi_fujitsu_probe(device_t dev); 1339a8b554fSPhilip Paeps static int acpi_fujitsu_attach(device_t dev); 1349a8b554fSPhilip Paeps static int acpi_fujitsu_detach(device_t dev); 1359a8b554fSPhilip Paeps static int acpi_fujitsu_suspend(device_t dev); 1369a8b554fSPhilip Paeps static int acpi_fujitsu_resume(device_t dev); 1379a8b554fSPhilip Paeps 1389a8b554fSPhilip Paeps static void acpi_fujitsu_notify_status_changed(void *arg); 1399a8b554fSPhilip Paeps static void acpi_fujitsu_notify_handler(ACPI_HANDLE h, uint32_t notify, void *context); 1409a8b554fSPhilip Paeps static int acpi_fujitsu_sysctl(SYSCTL_HANDLER_ARGS); 1419a8b554fSPhilip Paeps 1429a8b554fSPhilip Paeps /* Utility function declarations */ 1439a8b554fSPhilip Paeps static uint8_t acpi_fujitsu_update(struct acpi_fujitsu_softc *sc); 1449a8b554fSPhilip Paeps static uint8_t acpi_fujitsu_init(struct acpi_fujitsu_softc *sc); 145b9abb62dSPhilip Paeps static uint8_t acpi_fujitsu_check_hardware(struct acpi_fujitsu_softc *sc); 1469a8b554fSPhilip Paeps 1479a8b554fSPhilip Paeps /* Driver/Module specific structure definitions. */ 1489a8b554fSPhilip Paeps static device_method_t acpi_fujitsu_methods[] = { 1499a8b554fSPhilip Paeps /* Device interface */ 1509a8b554fSPhilip Paeps DEVMETHOD(device_probe, acpi_fujitsu_probe), 1519a8b554fSPhilip Paeps DEVMETHOD(device_attach, acpi_fujitsu_attach), 1529a8b554fSPhilip Paeps DEVMETHOD(device_detach, acpi_fujitsu_detach), 1539a8b554fSPhilip Paeps DEVMETHOD(device_suspend, acpi_fujitsu_suspend), 1549a8b554fSPhilip Paeps DEVMETHOD(device_resume, acpi_fujitsu_resume), 15561bfd867SSofian Brabez 15661bfd867SSofian Brabez DEVMETHOD_END 1579a8b554fSPhilip Paeps }; 1589a8b554fSPhilip Paeps 1599a8b554fSPhilip Paeps static driver_t acpi_fujitsu_driver = { 1609a8b554fSPhilip Paeps "acpi_fujitsu", 1619a8b554fSPhilip Paeps acpi_fujitsu_methods, 1629a8b554fSPhilip Paeps sizeof(struct acpi_fujitsu_softc), 1639a8b554fSPhilip Paeps }; 1649a8b554fSPhilip Paeps 165b9abb62dSPhilip Paeps /* Prototype for function hotkeys for getting/setting a value. */ 1669a8b554fSPhilip Paeps static int acpi_fujitsu_method_get(struct acpi_fujitsu_softc *sc, int method); 1679a8b554fSPhilip Paeps static int acpi_fujitsu_method_set(struct acpi_fujitsu_softc *sc, int method, int value); 1689a8b554fSPhilip Paeps 1699a8b554fSPhilip Paeps static char *fujitsu_ids[] = { "FUJ02B1", NULL }; 1709a8b554fSPhilip Paeps 171b9abb62dSPhilip Paeps ACPI_SERIAL_DECL(fujitsu, "Fujitsu Function Hotkeys"); 1729a8b554fSPhilip Paeps 1739a8b554fSPhilip Paeps /* sysctl names and function calls */ 1749a8b554fSPhilip Paeps static struct { 1759a8b554fSPhilip Paeps char *name; 1769a8b554fSPhilip Paeps int method; 1779a8b554fSPhilip Paeps char *description; 1789a8b554fSPhilip Paeps } sysctl_table[] = { 1799a8b554fSPhilip Paeps { 1809a8b554fSPhilip Paeps .name = "mute", 1819a8b554fSPhilip Paeps .method = METHOD_MUTE, 1829a8b554fSPhilip Paeps .description = "Speakers/headphones mute status" 1839a8b554fSPhilip Paeps }, 1849a8b554fSPhilip Paeps { 1859a8b554fSPhilip Paeps .name = "pointer_enable", 1869a8b554fSPhilip Paeps .method = METHOD_GMOU, 1879a8b554fSPhilip Paeps .description = "Enable and disable the internal pointer" 1889a8b554fSPhilip Paeps }, 1899a8b554fSPhilip Paeps { 1909a8b554fSPhilip Paeps .name = "lcd_brightness", 1919a8b554fSPhilip Paeps .method = METHOD_GBLL, 1929a8b554fSPhilip Paeps .description = "Brightness level of the LCD panel" 1939a8b554fSPhilip Paeps }, 1949a8b554fSPhilip Paeps { 195c82eedb4SAndriy Gapon .name = "lcd_brightness", 196c82eedb4SAndriy Gapon .method = METHOD_GBLS, 197c82eedb4SAndriy Gapon .description = "Brightness level of the LCD panel" 198c82eedb4SAndriy Gapon }, 199c82eedb4SAndriy Gapon { 2009a8b554fSPhilip Paeps .name = "volume", 2019a8b554fSPhilip Paeps .method = METHOD_GVOL, 2029a8b554fSPhilip Paeps .description = "Speakers/headphones volume level" 2039a8b554fSPhilip Paeps }, 204b9abb62dSPhilip Paeps { 205b9abb62dSPhilip Paeps .name = "volume_radix", 206b9abb62dSPhilip Paeps .method = METHOD_RVOL, 207b9abb62dSPhilip Paeps .description = "Number of volume level steps" 208b9abb62dSPhilip Paeps }, 209b9abb62dSPhilip Paeps { 210b9abb62dSPhilip Paeps .name = "lcd_brightness_radix", 211b9abb62dSPhilip Paeps .method = METHOD_RBLL, 212b9abb62dSPhilip Paeps .description = "Number of brightness level steps" 213b9abb62dSPhilip Paeps }, 2149a8b554fSPhilip Paeps { NULL, 0, NULL } 2159a8b554fSPhilip Paeps }; 2169a8b554fSPhilip Paeps 21790161e72SJohn Baldwin DRIVER_MODULE(acpi_fujitsu, acpi, acpi_fujitsu_driver, 0, 0); 2189a8b554fSPhilip Paeps MODULE_DEPEND(acpi_fujitsu, acpi, 1, 1, 1); 2199a8b554fSPhilip Paeps MODULE_VERSION(acpi_fujitsu, 1); 2209a8b554fSPhilip Paeps 2219a8b554fSPhilip Paeps static int 2229a8b554fSPhilip Paeps acpi_fujitsu_probe(device_t dev) 2239a8b554fSPhilip Paeps { 224b9abb62dSPhilip Paeps char *name; 2255efca36fSTakanori Watanabe int rv; 2269a8b554fSPhilip Paeps 2275efca36fSTakanori Watanabe rv = ACPI_ID_PROBE(device_get_parent(dev), dev, fujitsu_ids, &name); 2285efca36fSTakanori Watanabe if (acpi_disabled("fujitsu") || rv > 0 || device_get_unit(dev) > 1) 2299a8b554fSPhilip Paeps return (ENXIO); 230*bad36a49SMark Johnston device_set_descf(dev, "Fujitsu Function Hotkeys %s", name); 2319a8b554fSPhilip Paeps 2325efca36fSTakanori Watanabe return (rv); 2339a8b554fSPhilip Paeps } 2349a8b554fSPhilip Paeps 2359a8b554fSPhilip Paeps static int 2369a8b554fSPhilip Paeps acpi_fujitsu_attach(device_t dev) 2379a8b554fSPhilip Paeps { 2389a8b554fSPhilip Paeps struct acpi_fujitsu_softc *sc; 2399a8b554fSPhilip Paeps 2409a8b554fSPhilip Paeps ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); 2419a8b554fSPhilip Paeps 2429a8b554fSPhilip Paeps sc = device_get_softc(dev); 2439a8b554fSPhilip Paeps sc->dev = dev; 2449a8b554fSPhilip Paeps sc->handle = acpi_get_handle(dev); 2459a8b554fSPhilip Paeps 2469a8b554fSPhilip Paeps /* Install notification handler */ 2479a8b554fSPhilip Paeps AcpiInstallNotifyHandler(sc->handle, ACPI_DEVICE_NOTIFY, 2489a8b554fSPhilip Paeps acpi_fujitsu_notify_handler, sc); 2499a8b554fSPhilip Paeps 250d172be1fSEd Schouten /* Snag our default values for the hotkeys / hotkey states. */ 251b308de8bSPhilip Paeps ACPI_SERIAL_BEGIN(fujitsu); 252b308de8bSPhilip Paeps if (!acpi_fujitsu_init(sc)) 253b9abb62dSPhilip Paeps device_printf(dev, "Couldn't initialize hotkey states!\n"); 254b308de8bSPhilip Paeps ACPI_SERIAL_END(fujitsu); 2559a8b554fSPhilip Paeps 2569a8b554fSPhilip Paeps return (0); 2579a8b554fSPhilip Paeps } 2589a8b554fSPhilip Paeps 2599a8b554fSPhilip Paeps /* 2609a8b554fSPhilip Paeps * Called when the system is being suspended, simply 2619a8b554fSPhilip Paeps * set an event to be signalled when we wake up. 2629a8b554fSPhilip Paeps */ 2639a8b554fSPhilip Paeps static int 2649a8b554fSPhilip Paeps acpi_fujitsu_suspend(device_t dev) 2659a8b554fSPhilip Paeps { 2669a8b554fSPhilip Paeps 2679a8b554fSPhilip Paeps return (0); 2689a8b554fSPhilip Paeps } 2699a8b554fSPhilip Paeps 2709a8b554fSPhilip Paeps static int 2719a8b554fSPhilip Paeps acpi_fujitsu_resume(device_t dev) 2729a8b554fSPhilip Paeps { 2739a8b554fSPhilip Paeps struct acpi_fujitsu_softc *sc; 2749a8b554fSPhilip Paeps ACPI_STATUS status; 2759a8b554fSPhilip Paeps 2769a8b554fSPhilip Paeps sc = device_get_softc(dev); 2779a8b554fSPhilip Paeps 2789a8b554fSPhilip Paeps /* 2799a8b554fSPhilip Paeps * The pointer needs to be re-enabled for 2809a8b554fSPhilip Paeps * some revisions of the P series (2120). 2819a8b554fSPhilip Paeps */ 2829a8b554fSPhilip Paeps ACPI_SERIAL_BEGIN(fujitsu); 2839a8b554fSPhilip Paeps 284b9abb62dSPhilip Paeps if(sc->gmou.exists) { 2859a8b554fSPhilip Paeps status = acpi_SetInteger(sc->handle, "SMOU", 1); 2869a8b554fSPhilip Paeps if (ACPI_FAILURE(status)) 2879a8b554fSPhilip Paeps device_printf(sc->dev, "Couldn't enable pointer\n"); 288b9abb62dSPhilip Paeps } 2899a8b554fSPhilip Paeps ACPI_SERIAL_END(fujitsu); 2909a8b554fSPhilip Paeps 2919a8b554fSPhilip Paeps return (0); 2929a8b554fSPhilip Paeps } 2939a8b554fSPhilip Paeps 2949a8b554fSPhilip Paeps static void 2959a8b554fSPhilip Paeps acpi_fujitsu_notify_status_changed(void *arg) 2969a8b554fSPhilip Paeps { 2979a8b554fSPhilip Paeps struct acpi_fujitsu_softc *sc; 2989a8b554fSPhilip Paeps 2999a8b554fSPhilip Paeps ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); 3009a8b554fSPhilip Paeps 3019a8b554fSPhilip Paeps sc = (struct acpi_fujitsu_softc *)arg; 3029a8b554fSPhilip Paeps 3039a8b554fSPhilip Paeps /* 3049a8b554fSPhilip Paeps * Since our notify function is called, we know something has 3059a8b554fSPhilip Paeps * happened. So the only reason for acpi_fujitsu_update to fail 3069a8b554fSPhilip Paeps * is if we can't find what has changed or an error occurs. 3079a8b554fSPhilip Paeps */ 3089a8b554fSPhilip Paeps ACPI_SERIAL_BEGIN(fujitsu); 3099a8b554fSPhilip Paeps acpi_fujitsu_update(sc); 3109a8b554fSPhilip Paeps ACPI_SERIAL_END(fujitsu); 3119a8b554fSPhilip Paeps } 3129a8b554fSPhilip Paeps 3139a8b554fSPhilip Paeps static void 3149a8b554fSPhilip Paeps acpi_fujitsu_notify_handler(ACPI_HANDLE h, uint32_t notify, void *context) 3159a8b554fSPhilip Paeps { 3169a8b554fSPhilip Paeps struct acpi_fujitsu_softc *sc; 3179a8b554fSPhilip Paeps 3189a8b554fSPhilip Paeps ACPI_FUNCTION_TRACE_U32((char *)(uintptr_t)__func__, notify); 3199a8b554fSPhilip Paeps 3209a8b554fSPhilip Paeps sc = (struct acpi_fujitsu_softc *)context; 3219a8b554fSPhilip Paeps 3229a8b554fSPhilip Paeps switch (notify) { 3239a8b554fSPhilip Paeps case ACPI_NOTIFY_STATUS_CHANGED: 3242be4e471SJung-uk Kim AcpiOsExecute(OSL_NOTIFY_HANDLER, 3259a8b554fSPhilip Paeps acpi_fujitsu_notify_status_changed, sc); 3269a8b554fSPhilip Paeps break; 3279a8b554fSPhilip Paeps default: 3289a8b554fSPhilip Paeps /* unknown notification value */ 3299a8b554fSPhilip Paeps break; 3309a8b554fSPhilip Paeps } 3319a8b554fSPhilip Paeps } 3329a8b554fSPhilip Paeps 3339a8b554fSPhilip Paeps static int 3349a8b554fSPhilip Paeps acpi_fujitsu_detach(device_t dev) 3359a8b554fSPhilip Paeps { 3369a8b554fSPhilip Paeps struct acpi_fujitsu_softc *sc; 3379a8b554fSPhilip Paeps 3389a8b554fSPhilip Paeps sc = device_get_softc(dev); 3399a8b554fSPhilip Paeps AcpiRemoveNotifyHandler(sc->handle, ACPI_DEVICE_NOTIFY, 3409a8b554fSPhilip Paeps acpi_fujitsu_notify_handler); 3419a8b554fSPhilip Paeps 3429a8b554fSPhilip Paeps sysctl_ctx_free(&sc->sysctl_ctx); 3439a8b554fSPhilip Paeps 3449a8b554fSPhilip Paeps return (0); 3459a8b554fSPhilip Paeps } 3469a8b554fSPhilip Paeps 3479a8b554fSPhilip Paeps /* 3489a8b554fSPhilip Paeps * Initializes the names of the ACPI control methods and grabs 349b9abb62dSPhilip Paeps * the current state of all of the ACPI hotkeys into the softc. 3509a8b554fSPhilip Paeps */ 3519a8b554fSPhilip Paeps static uint8_t 3529a8b554fSPhilip Paeps acpi_fujitsu_init(struct acpi_fujitsu_softc *sc) 3539a8b554fSPhilip Paeps { 3549a8b554fSPhilip Paeps struct acpi_softc *acpi_sc; 355b9abb62dSPhilip Paeps int i, exists; 3569a8b554fSPhilip Paeps 3579a8b554fSPhilip Paeps ACPI_SERIAL_ASSERT(fujitsu); 3589a8b554fSPhilip Paeps 3599a8b554fSPhilip Paeps /* Setup all of the names for each control method */ 3609a8b554fSPhilip Paeps sc->_sta.name = "_STA"; 3619a8b554fSPhilip Paeps sc->gbll.name = "GBLL"; 362c82eedb4SAndriy Gapon sc->gbls.name = "GBLS"; 3639a8b554fSPhilip Paeps sc->ghks.name = "GHKS"; 3649a8b554fSPhilip Paeps sc->gmou.name = "GMOU"; 3659a8b554fSPhilip Paeps sc->gsif.name = "GSIF"; 3669a8b554fSPhilip Paeps sc->gvol.name = "GVOL"; 367b9abb62dSPhilip Paeps sc->ghks.name = "GHKS"; 368b9abb62dSPhilip Paeps sc->gsif.name = "GSIF"; 3699a8b554fSPhilip Paeps sc->rbll.name = "RBLL"; 3709a8b554fSPhilip Paeps sc->rvol.name = "RVOL"; 3719a8b554fSPhilip Paeps 372b9abb62dSPhilip Paeps /* Determine what hardware functionality is available */ 373b9abb62dSPhilip Paeps acpi_fujitsu_check_hardware(sc); 374b9abb62dSPhilip Paeps 3759a8b554fSPhilip Paeps /* Build the sysctl tree */ 3769a8b554fSPhilip Paeps acpi_sc = acpi_device_get_parent_softc(sc->dev); 3779a8b554fSPhilip Paeps sysctl_ctx_init(&sc->sysctl_ctx); 3789a8b554fSPhilip Paeps sc->sysctl_tree = SYSCTL_ADD_NODE(&sc->sysctl_ctx, 3799a8b554fSPhilip Paeps SYSCTL_CHILDREN(acpi_sc->acpi_sysctl_tree), 3807029da5cSPawel Biernacki OID_AUTO, "fujitsu", CTLFLAG_RD | CTLFLAG_MPSAFE, 0, ""); 3819a8b554fSPhilip Paeps 3829a8b554fSPhilip Paeps for (i = 0; sysctl_table[i].name != NULL; i++) { 383b9abb62dSPhilip Paeps switch(sysctl_table[i].method) { 384b9abb62dSPhilip Paeps case METHOD_GMOU: 385b9abb62dSPhilip Paeps exists = sc->gmou.exists; 386b9abb62dSPhilip Paeps break; 387b9abb62dSPhilip Paeps case METHOD_GBLL: 388b9abb62dSPhilip Paeps exists = sc->gbll.exists; 389b9abb62dSPhilip Paeps break; 390c82eedb4SAndriy Gapon case METHOD_GBLS: 391c82eedb4SAndriy Gapon exists = sc->gbls.exists; 392c82eedb4SAndriy Gapon break; 393b9abb62dSPhilip Paeps case METHOD_GVOL: 394b9abb62dSPhilip Paeps case METHOD_MUTE: 395b9abb62dSPhilip Paeps exists = sc->gvol.exists; 396b9abb62dSPhilip Paeps break; 397b9abb62dSPhilip Paeps case METHOD_RVOL: 398b9abb62dSPhilip Paeps exists = sc->rvol.exists; 399b9abb62dSPhilip Paeps break; 400b9abb62dSPhilip Paeps case METHOD_RBLL: 401b9abb62dSPhilip Paeps exists = sc->rbll.exists; 402b9abb62dSPhilip Paeps break; 403b9abb62dSPhilip Paeps default: 404b9abb62dSPhilip Paeps /* Allow by default */ 405b9abb62dSPhilip Paeps exists = 1; 406b9abb62dSPhilip Paeps break; 407b9abb62dSPhilip Paeps } 408b9abb62dSPhilip Paeps if(!exists) 409b9abb62dSPhilip Paeps continue; 4109a8b554fSPhilip Paeps SYSCTL_ADD_PROC(&sc->sysctl_ctx, 4119a8b554fSPhilip Paeps SYSCTL_CHILDREN(sc->sysctl_tree), OID_AUTO, 4129a8b554fSPhilip Paeps sysctl_table[i].name, 4137029da5cSPawel Biernacki CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY | 4146237a1ccSAlexander Motin CTLFLAG_MPSAFE, sc, i, acpi_fujitsu_sysctl, "I", 4159a8b554fSPhilip Paeps sysctl_table[i].description); 4169a8b554fSPhilip Paeps } 4179a8b554fSPhilip Paeps 418b9abb62dSPhilip Paeps /* Set the hotkeys to their initial states */ 4199a8b554fSPhilip Paeps if (!acpi_fujitsu_update(sc)) { 420b9abb62dSPhilip Paeps device_printf(sc->dev, "Couldn't init hotkey states\n"); 4219a8b554fSPhilip Paeps return (FALSE); 4229a8b554fSPhilip Paeps } 4239a8b554fSPhilip Paeps 4249a8b554fSPhilip Paeps return (TRUE); 4259a8b554fSPhilip Paeps } 4269a8b554fSPhilip Paeps 4279a8b554fSPhilip Paeps static int 4289a8b554fSPhilip Paeps acpi_fujitsu_sysctl(SYSCTL_HANDLER_ARGS) 4299a8b554fSPhilip Paeps { 4309a8b554fSPhilip Paeps struct acpi_fujitsu_softc *sc; 4319a8b554fSPhilip Paeps int method; 4329a8b554fSPhilip Paeps int arg; 4339a8b554fSPhilip Paeps int function_num, error = 0; 4349a8b554fSPhilip Paeps 4359a8b554fSPhilip Paeps sc = (struct acpi_fujitsu_softc *)oidp->oid_arg1; 4369a8b554fSPhilip Paeps function_num = oidp->oid_arg2; 4379a8b554fSPhilip Paeps method = sysctl_table[function_num].method; 4389a8b554fSPhilip Paeps 4399a8b554fSPhilip Paeps ACPI_SERIAL_BEGIN(fujitsu); 4409a8b554fSPhilip Paeps 4419a8b554fSPhilip Paeps /* Get the current value */ 4429a8b554fSPhilip Paeps arg = acpi_fujitsu_method_get(sc, method); 4439a8b554fSPhilip Paeps error = sysctl_handle_int(oidp, &arg, 0, req); 4449a8b554fSPhilip Paeps 4459a8b554fSPhilip Paeps if (error != 0 || req->newptr == NULL) 4469a8b554fSPhilip Paeps goto out; 4479a8b554fSPhilip Paeps 4489a8b554fSPhilip Paeps /* Update the value */ 4499a8b554fSPhilip Paeps error = acpi_fujitsu_method_set(sc, method, arg); 4509a8b554fSPhilip Paeps 4519a8b554fSPhilip Paeps out: 4529a8b554fSPhilip Paeps ACPI_SERIAL_END(fujitsu); 4539a8b554fSPhilip Paeps return (error); 4549a8b554fSPhilip Paeps } 4559a8b554fSPhilip Paeps 4569a8b554fSPhilip Paeps static int 4579a8b554fSPhilip Paeps acpi_fujitsu_method_get(struct acpi_fujitsu_softc *sc, int method) 4589a8b554fSPhilip Paeps { 4599a8b554fSPhilip Paeps struct int_nameval nv; 4609a8b554fSPhilip Paeps ACPI_STATUS status; 4619a8b554fSPhilip Paeps 4629a8b554fSPhilip Paeps ACPI_SERIAL_ASSERT(fujitsu); 4639a8b554fSPhilip Paeps 4649a8b554fSPhilip Paeps switch (method) { 4659a8b554fSPhilip Paeps case METHOD_GBLL: 4669a8b554fSPhilip Paeps nv = sc->gbll; 4679a8b554fSPhilip Paeps break; 468c82eedb4SAndriy Gapon case METHOD_GBLS: 469c82eedb4SAndriy Gapon nv = sc->gbls; 470c82eedb4SAndriy Gapon break; 4719a8b554fSPhilip Paeps case METHOD_GMOU: 4729a8b554fSPhilip Paeps nv = sc->gmou; 4739a8b554fSPhilip Paeps break; 4749a8b554fSPhilip Paeps case METHOD_GVOL: 4759a8b554fSPhilip Paeps case METHOD_MUTE: 4769a8b554fSPhilip Paeps nv = sc->gvol; 4779a8b554fSPhilip Paeps break; 478b9abb62dSPhilip Paeps case METHOD_GHKS: 479b9abb62dSPhilip Paeps nv = sc->ghks; 480b9abb62dSPhilip Paeps break; 481b9abb62dSPhilip Paeps case METHOD_GSIF: 482b9abb62dSPhilip Paeps nv = sc->gsif; 483b9abb62dSPhilip Paeps break; 484b9abb62dSPhilip Paeps case METHOD_RBLL: 485b9abb62dSPhilip Paeps nv = sc->rbll; 486b9abb62dSPhilip Paeps break; 487b9abb62dSPhilip Paeps case METHOD_RVOL: 488b9abb62dSPhilip Paeps nv = sc->rvol; 489b9abb62dSPhilip Paeps break; 4909a8b554fSPhilip Paeps default: 4919a8b554fSPhilip Paeps return (FALSE); 4929a8b554fSPhilip Paeps } 4939a8b554fSPhilip Paeps 494b9abb62dSPhilip Paeps if(!nv.exists) 495b9abb62dSPhilip Paeps return (EINVAL); 496b9abb62dSPhilip Paeps 4979a8b554fSPhilip Paeps status = acpi_GetInteger(sc->handle, nv.name, &nv.value); 4989a8b554fSPhilip Paeps if (ACPI_FAILURE(status)) { 499b9abb62dSPhilip Paeps device_printf(sc->dev, "Couldn't query method (%s)\n", nv.name); 5009a8b554fSPhilip Paeps return (FALSE); 5019a8b554fSPhilip Paeps } 5029a8b554fSPhilip Paeps 5039a8b554fSPhilip Paeps if (method == METHOD_MUTE) { 5049a8b554fSPhilip Paeps sc->bIsMuted = (uint8_t)((nv.value & VOLUME_MUTE_BIT) != 0); 5059a8b554fSPhilip Paeps return (sc->bIsMuted); 5069a8b554fSPhilip Paeps } 5079a8b554fSPhilip Paeps 5089a8b554fSPhilip Paeps nv.value &= GENERAL_SETTING_BITS; 5099a8b554fSPhilip Paeps return (nv.value); 5109a8b554fSPhilip Paeps } 5119a8b554fSPhilip Paeps 5129a8b554fSPhilip Paeps static int 5139a8b554fSPhilip Paeps acpi_fujitsu_method_set(struct acpi_fujitsu_softc *sc, int method, int value) 5149a8b554fSPhilip Paeps { 5159a8b554fSPhilip Paeps struct int_nameval nv; 5169a8b554fSPhilip Paeps ACPI_STATUS status; 5179a8b554fSPhilip Paeps char *control; 5189a8b554fSPhilip Paeps int changed; 5199a8b554fSPhilip Paeps 5209a8b554fSPhilip Paeps ACPI_SERIAL_ASSERT(fujitsu); 5219a8b554fSPhilip Paeps 5229a8b554fSPhilip Paeps switch (method) { 5239a8b554fSPhilip Paeps case METHOD_GBLL: 5249a8b554fSPhilip Paeps changed = BRIGHT_CHANGED; 5259a8b554fSPhilip Paeps control = "SBLL"; 5269a8b554fSPhilip Paeps nv = sc->gbll; 5279a8b554fSPhilip Paeps break; 528c82eedb4SAndriy Gapon case METHOD_GBLS: 529c82eedb4SAndriy Gapon changed = BRIGHT_CHANGED; 530c82eedb4SAndriy Gapon control = "SBL2"; 531c82eedb4SAndriy Gapon nv = sc->gbls; 532c82eedb4SAndriy Gapon break; 5339a8b554fSPhilip Paeps case METHOD_GMOU: 5349a8b554fSPhilip Paeps changed = MOUSE_CHANGED; 5359a8b554fSPhilip Paeps control = "SMOU"; 5369a8b554fSPhilip Paeps nv = sc->gmou; 5379a8b554fSPhilip Paeps break; 5389a8b554fSPhilip Paeps case METHOD_GVOL: 5399a8b554fSPhilip Paeps case METHOD_MUTE: 5409a8b554fSPhilip Paeps changed = VOLUME_CHANGED; 5419a8b554fSPhilip Paeps control = "SVOL"; 5429a8b554fSPhilip Paeps nv = sc->gvol; 5439a8b554fSPhilip Paeps break; 5449a8b554fSPhilip Paeps default: 5459a8b554fSPhilip Paeps return (EINVAL); 5469a8b554fSPhilip Paeps } 5479a8b554fSPhilip Paeps 548b9abb62dSPhilip Paeps if(!nv.exists) 549b9abb62dSPhilip Paeps return (EINVAL); 550b9abb62dSPhilip Paeps 5519a8b554fSPhilip Paeps if (method == METHOD_MUTE) { 5529a8b554fSPhilip Paeps if (value == 1) 5539a8b554fSPhilip Paeps value = nv.value | VOLUME_MUTE_BIT; 5549a8b554fSPhilip Paeps else if (value == 0) 5559a8b554fSPhilip Paeps value = nv.value & ~VOLUME_MUTE_BIT; 5569a8b554fSPhilip Paeps else 5579a8b554fSPhilip Paeps return (EINVAL); 5589a8b554fSPhilip Paeps } 5599a8b554fSPhilip Paeps 5609a8b554fSPhilip Paeps status = acpi_SetInteger(sc->handle, control, value); 5619a8b554fSPhilip Paeps if (ACPI_FAILURE(status)) { 5629a8b554fSPhilip Paeps device_printf(sc->dev, "Couldn't update %s\n", control); 563b9abb62dSPhilip Paeps return (FALSE); 5649a8b554fSPhilip Paeps } 5659a8b554fSPhilip Paeps 5669a8b554fSPhilip Paeps sc->lastValChanged = changed; 5679a8b554fSPhilip Paeps return (0); 5689a8b554fSPhilip Paeps } 5699a8b554fSPhilip Paeps 5709a8b554fSPhilip Paeps /* 571b9abb62dSPhilip Paeps * Query the get methods to determine what functionality is available 572b9abb62dSPhilip Paeps * from the hardware function hotkeys. 573b9abb62dSPhilip Paeps */ 574b9abb62dSPhilip Paeps static uint8_t 575b9abb62dSPhilip Paeps acpi_fujitsu_check_hardware(struct acpi_fujitsu_softc *sc) 576b9abb62dSPhilip Paeps { 577b9abb62dSPhilip Paeps int val; 578b9abb62dSPhilip Paeps 579b9abb62dSPhilip Paeps ACPI_SERIAL_ASSERT(fujitsu); 580b9abb62dSPhilip Paeps /* save the hotkey bitmask */ 581b9abb62dSPhilip Paeps if (ACPI_FAILURE(acpi_GetInteger(sc->handle, 582b9abb62dSPhilip Paeps sc->gsif.name, &(sc->gsif.value)))) { 583b9abb62dSPhilip Paeps sc->gsif.exists = 0; 584b9abb62dSPhilip Paeps device_printf(sc->dev, "Couldn't query bitmask value\n"); 585b9abb62dSPhilip Paeps } else { 586b9abb62dSPhilip Paeps sc->gsif.exists = 1; 587b9abb62dSPhilip Paeps } 588b9abb62dSPhilip Paeps 589b9abb62dSPhilip Paeps /* System Volume Level */ 590b9abb62dSPhilip Paeps if (ACPI_FAILURE(acpi_GetInteger(sc->handle, 591b9abb62dSPhilip Paeps sc->gvol.name, &val))) { 592b9abb62dSPhilip Paeps sc->gvol.exists = 0; 593b9abb62dSPhilip Paeps } else { 594b9abb62dSPhilip Paeps sc->gvol.exists = 1; 595b9abb62dSPhilip Paeps } 596b9abb62dSPhilip Paeps 597b9abb62dSPhilip Paeps if (ACPI_FAILURE(acpi_GetInteger(sc->handle, 598c82eedb4SAndriy Gapon sc->gbls.name, &val))) { 599c82eedb4SAndriy Gapon sc->gbls.exists = 0; 600c82eedb4SAndriy Gapon } else { 601c82eedb4SAndriy Gapon sc->gbls.exists = 1; 602c82eedb4SAndriy Gapon } 603c82eedb4SAndriy Gapon 604c82eedb4SAndriy Gapon // don't add if we can use the new method 605c82eedb4SAndriy Gapon if (sc->gbls.exists || ACPI_FAILURE(acpi_GetInteger(sc->handle, 606b9abb62dSPhilip Paeps sc->gbll.name, &val))) { 607b9abb62dSPhilip Paeps sc->gbll.exists = 0; 608b9abb62dSPhilip Paeps } else { 609b9abb62dSPhilip Paeps sc->gbll.exists = 1; 610b9abb62dSPhilip Paeps } 611b9abb62dSPhilip Paeps 612b9abb62dSPhilip Paeps if (ACPI_FAILURE(acpi_GetInteger(sc->handle, 613b9abb62dSPhilip Paeps sc->ghks.name, &val))) { 614b9abb62dSPhilip Paeps sc->ghks.exists = 0; 615b9abb62dSPhilip Paeps } else { 616b9abb62dSPhilip Paeps sc->ghks.exists = 1; 617b9abb62dSPhilip Paeps } 618b9abb62dSPhilip Paeps 619b9abb62dSPhilip Paeps if (ACPI_FAILURE(acpi_GetInteger(sc->handle, 620b9abb62dSPhilip Paeps sc->gmou.name, &val))) { 621b9abb62dSPhilip Paeps sc->gmou.exists = 0; 622b9abb62dSPhilip Paeps } else { 623b9abb62dSPhilip Paeps sc->gmou.exists = 1; 624b9abb62dSPhilip Paeps } 625b9abb62dSPhilip Paeps 626b9abb62dSPhilip Paeps if (ACPI_FAILURE(acpi_GetInteger(sc->handle, 627b9abb62dSPhilip Paeps sc->rbll.name, &val))) { 628b9abb62dSPhilip Paeps sc->rbll.exists = 0; 629b9abb62dSPhilip Paeps } else { 630b9abb62dSPhilip Paeps sc->rbll.exists = 1; 631b9abb62dSPhilip Paeps } 632b9abb62dSPhilip Paeps 633b9abb62dSPhilip Paeps if (ACPI_FAILURE(acpi_GetInteger(sc->handle, 634b9abb62dSPhilip Paeps sc->rvol.name, &val))) { 635b9abb62dSPhilip Paeps sc->rvol.exists = 0; 636b9abb62dSPhilip Paeps } else { 637b9abb62dSPhilip Paeps sc->rvol.exists = 1; 638b9abb62dSPhilip Paeps } 639b9abb62dSPhilip Paeps 640b9abb62dSPhilip Paeps return (TRUE); 641b9abb62dSPhilip Paeps } 642b9abb62dSPhilip Paeps 643b9abb62dSPhilip Paeps /* 6449a8b554fSPhilip Paeps * Query each of the ACPI control methods that contain information we're 6459a8b554fSPhilip Paeps * interested in. We check the return values from the control methods and 6469a8b554fSPhilip Paeps * adjust any state variables if they should be adjusted. 6479a8b554fSPhilip Paeps */ 6489a8b554fSPhilip Paeps static uint8_t 6499a8b554fSPhilip Paeps acpi_fujitsu_update(struct acpi_fujitsu_softc *sc) 6509a8b554fSPhilip Paeps { 651b9abb62dSPhilip Paeps int changed; 6529a8b554fSPhilip Paeps struct acpi_softc *acpi_sc; 6539a8b554fSPhilip Paeps 6549a8b554fSPhilip Paeps acpi_sc = acpi_device_get_parent_softc(sc->dev); 6559a8b554fSPhilip Paeps 6569a8b554fSPhilip Paeps ACPI_SERIAL_ASSERT(fujitsu); 657b9abb62dSPhilip Paeps if(sc->gsif.exists) 658b9abb62dSPhilip Paeps changed = sc->gsif.value & acpi_fujitsu_method_get(sc,METHOD_GHKS); 659b9abb62dSPhilip Paeps else 660b9abb62dSPhilip Paeps changed = 0; 6619a8b554fSPhilip Paeps 6629a8b554fSPhilip Paeps /* System Volume Level */ 663b9abb62dSPhilip Paeps if(sc->gvol.exists) { 6649a8b554fSPhilip Paeps if (ACPI_FAILURE(acpi_GetInteger(sc->handle, 6659a8b554fSPhilip Paeps sc->gvol.name, &(sc->gvol.value)))) { 6669a8b554fSPhilip Paeps device_printf(sc->dev, "Couldn't query volume level\n"); 6679a8b554fSPhilip Paeps return (FALSE); 6689a8b554fSPhilip Paeps } 6699a8b554fSPhilip Paeps 670b9abb62dSPhilip Paeps if (changed & VOLUME_CHANGED) { 6719a8b554fSPhilip Paeps sc->bIsMuted = 6729a8b554fSPhilip Paeps (uint8_t)((sc->gvol.value & VOLUME_MUTE_BIT) != 0); 6739a8b554fSPhilip Paeps 6749a8b554fSPhilip Paeps /* Clear the modification bit */ 6759a8b554fSPhilip Paeps sc->gvol.value &= VOLUME_SETTING_BITS; 6769a8b554fSPhilip Paeps 6779a8b554fSPhilip Paeps if (sc->bIsMuted) { 6789a8b554fSPhilip Paeps acpi_UserNotify("FUJITSU", sc->handle, FN_MUTE); 6799a8b554fSPhilip Paeps ACPI_VPRINT(sc->dev, acpi_sc, "Volume is now mute\n"); 6809a8b554fSPhilip Paeps } else 6819a8b554fSPhilip Paeps ACPI_VPRINT(sc->dev, acpi_sc, "Volume is now %d\n", 6829a8b554fSPhilip Paeps sc->gvol.value); 6839a8b554fSPhilip Paeps 6849a8b554fSPhilip Paeps acpi_UserNotify("FUJITSU", sc->handle, FN_VOLUME); 685b9abb62dSPhilip Paeps } 6869a8b554fSPhilip Paeps } 6879a8b554fSPhilip Paeps 6889a8b554fSPhilip Paeps /* Internal mouse pointer (eraserhead) */ 689b9abb62dSPhilip Paeps if(sc->gmou.exists) { 6909a8b554fSPhilip Paeps if (ACPI_FAILURE(acpi_GetInteger(sc->handle, 6919a8b554fSPhilip Paeps sc->gmou.name, &(sc->gmou.value)))) { 6929a8b554fSPhilip Paeps device_printf(sc->dev, "Couldn't query pointer state\n"); 6939a8b554fSPhilip Paeps return (FALSE); 6949a8b554fSPhilip Paeps } 6959a8b554fSPhilip Paeps 696b9abb62dSPhilip Paeps if (changed & MOUSE_CHANGED) { 6979a8b554fSPhilip Paeps sc->bIntPtrEnabled = (uint8_t)(sc->gmou.value & 0x1); 6989a8b554fSPhilip Paeps 6999a8b554fSPhilip Paeps /* Clear the modification bit */ 7009a8b554fSPhilip Paeps sc->gmou.value &= MOUSE_SETTING_BITS; 7019a8b554fSPhilip Paeps 702c82eedb4SAndriy Gapon /* Set the value in case it is not hardware controlled */ 703c82eedb4SAndriy Gapon acpi_fujitsu_method_set(sc, METHOD_GMOU, sc->gmou.value); 704c82eedb4SAndriy Gapon 7059a8b554fSPhilip Paeps acpi_UserNotify("FUJITSU", sc->handle, FN_POINTER_ENABLE); 7069a8b554fSPhilip Paeps 7079a8b554fSPhilip Paeps ACPI_VPRINT(sc->dev, acpi_sc, "Internal pointer is now %s\n", 7089a8b554fSPhilip Paeps (sc->bIntPtrEnabled) ? "enabled" : "disabled"); 709b9abb62dSPhilip Paeps } 7109a8b554fSPhilip Paeps } 7119a8b554fSPhilip Paeps 712c82eedb4SAndriy Gapon /* Screen Brightness Level P8XXX */ 713c82eedb4SAndriy Gapon if(sc->gbls.exists) { 714c82eedb4SAndriy Gapon if (ACPI_FAILURE(acpi_GetInteger(sc->handle, 715c82eedb4SAndriy Gapon sc->gbls.name, &(sc->gbls.value)))) { 716c82eedb4SAndriy Gapon device_printf(sc->dev, "Couldn't query P8XXX brightness level\n"); 717c82eedb4SAndriy Gapon return (FALSE); 718c82eedb4SAndriy Gapon } 719c82eedb4SAndriy Gapon if (changed & BRIGHT_CHANGED) { 720c82eedb4SAndriy Gapon /* No state to record here. */ 721c82eedb4SAndriy Gapon 722c82eedb4SAndriy Gapon /* Clear the modification bit */ 723c82eedb4SAndriy Gapon sc->gbls.value &= BRIGHTNESS_SETTING_BITS; 724c82eedb4SAndriy Gapon 725c82eedb4SAndriy Gapon /* Set the value in case it is not hardware controlled */ 726c82eedb4SAndriy Gapon acpi_fujitsu_method_set(sc, METHOD_GBLS, sc->gbls.value); 727c82eedb4SAndriy Gapon 728c82eedb4SAndriy Gapon acpi_UserNotify("FUJITSU", sc->handle, FN_LCD_BRIGHTNESS); 729c82eedb4SAndriy Gapon 730c82eedb4SAndriy Gapon ACPI_VPRINT(sc->dev, acpi_sc, "P8XXX Brightness level is now %d\n", 731c82eedb4SAndriy Gapon sc->gbls.value); 732c82eedb4SAndriy Gapon } 733c82eedb4SAndriy Gapon } 734c82eedb4SAndriy Gapon 7359a8b554fSPhilip Paeps /* Screen Brightness Level */ 736b9abb62dSPhilip Paeps if(sc->gbll.exists) { 7379a8b554fSPhilip Paeps if (ACPI_FAILURE(acpi_GetInteger(sc->handle, 7389a8b554fSPhilip Paeps sc->gbll.name, &(sc->gbll.value)))) { 7399a8b554fSPhilip Paeps device_printf(sc->dev, "Couldn't query brightness level\n"); 7409a8b554fSPhilip Paeps return (FALSE); 7419a8b554fSPhilip Paeps } 7429a8b554fSPhilip Paeps 743b9abb62dSPhilip Paeps if (changed & BRIGHT_CHANGED) { 7449a8b554fSPhilip Paeps /* No state to record here. */ 7459a8b554fSPhilip Paeps 7469a8b554fSPhilip Paeps /* Clear the modification bit */ 7479a8b554fSPhilip Paeps sc->gbll.value &= BRIGHTNESS_SETTING_BITS; 7489a8b554fSPhilip Paeps 7499a8b554fSPhilip Paeps acpi_UserNotify("FUJITSU", sc->handle, FN_LCD_BRIGHTNESS); 7509a8b554fSPhilip Paeps 7519a8b554fSPhilip Paeps ACPI_VPRINT(sc->dev, acpi_sc, "Brightness level is now %d\n", 7529a8b554fSPhilip Paeps sc->gbll.value); 753b9abb62dSPhilip Paeps } 7549a8b554fSPhilip Paeps } 7559a8b554fSPhilip Paeps 756b9abb62dSPhilip Paeps sc->lastValChanged = changed; 7579a8b554fSPhilip Paeps return (TRUE); 7589a8b554fSPhilip Paeps } 759