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 { NULL, 0, NULL } 2179a8b554fSPhilip Paeps }; 2189a8b554fSPhilip Paeps 219*90161e72SJohn Baldwin DRIVER_MODULE(acpi_fujitsu, acpi, acpi_fujitsu_driver, 0, 0); 2209a8b554fSPhilip Paeps MODULE_DEPEND(acpi_fujitsu, acpi, 1, 1, 1); 2219a8b554fSPhilip Paeps MODULE_VERSION(acpi_fujitsu, 1); 2229a8b554fSPhilip Paeps 2239a8b554fSPhilip Paeps static int 2249a8b554fSPhilip Paeps acpi_fujitsu_probe(device_t dev) 2259a8b554fSPhilip Paeps { 226b9abb62dSPhilip Paeps char *name; 227b9abb62dSPhilip Paeps char buffer[64]; 2285efca36fSTakanori Watanabe int rv; 2299a8b554fSPhilip Paeps 2305efca36fSTakanori Watanabe rv = ACPI_ID_PROBE(device_get_parent(dev), dev, fujitsu_ids, &name); 2315efca36fSTakanori Watanabe if (acpi_disabled("fujitsu") || rv > 0 || device_get_unit(dev) > 1) 2329a8b554fSPhilip Paeps return (ENXIO); 233b9abb62dSPhilip Paeps sprintf(buffer, "Fujitsu Function Hotkeys %s", name); 234b9abb62dSPhilip Paeps device_set_desc_copy(dev, buffer); 2359a8b554fSPhilip Paeps 2365efca36fSTakanori Watanabe return (rv); 2379a8b554fSPhilip Paeps } 2389a8b554fSPhilip Paeps 2399a8b554fSPhilip Paeps static int 2409a8b554fSPhilip Paeps acpi_fujitsu_attach(device_t dev) 2419a8b554fSPhilip Paeps { 2429a8b554fSPhilip Paeps struct acpi_fujitsu_softc *sc; 2439a8b554fSPhilip Paeps 2449a8b554fSPhilip Paeps ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); 2459a8b554fSPhilip Paeps 2469a8b554fSPhilip Paeps sc = device_get_softc(dev); 2479a8b554fSPhilip Paeps sc->dev = dev; 2489a8b554fSPhilip Paeps sc->handle = acpi_get_handle(dev); 2499a8b554fSPhilip Paeps 2509a8b554fSPhilip Paeps /* Install notification handler */ 2519a8b554fSPhilip Paeps AcpiInstallNotifyHandler(sc->handle, ACPI_DEVICE_NOTIFY, 2529a8b554fSPhilip Paeps acpi_fujitsu_notify_handler, sc); 2539a8b554fSPhilip Paeps 254d172be1fSEd Schouten /* Snag our default values for the hotkeys / hotkey states. */ 255b308de8bSPhilip Paeps ACPI_SERIAL_BEGIN(fujitsu); 256b308de8bSPhilip Paeps if (!acpi_fujitsu_init(sc)) 257b9abb62dSPhilip Paeps device_printf(dev, "Couldn't initialize hotkey states!\n"); 258b308de8bSPhilip Paeps ACPI_SERIAL_END(fujitsu); 2599a8b554fSPhilip Paeps 2609a8b554fSPhilip Paeps return (0); 2619a8b554fSPhilip Paeps } 2629a8b554fSPhilip Paeps 2639a8b554fSPhilip Paeps /* 2649a8b554fSPhilip Paeps * Called when the system is being suspended, simply 2659a8b554fSPhilip Paeps * set an event to be signalled when we wake up. 2669a8b554fSPhilip Paeps */ 2679a8b554fSPhilip Paeps static int 2689a8b554fSPhilip Paeps acpi_fujitsu_suspend(device_t dev) 2699a8b554fSPhilip Paeps { 2709a8b554fSPhilip Paeps 2719a8b554fSPhilip Paeps return (0); 2729a8b554fSPhilip Paeps } 2739a8b554fSPhilip Paeps 2749a8b554fSPhilip Paeps static int 2759a8b554fSPhilip Paeps acpi_fujitsu_resume(device_t dev) 2769a8b554fSPhilip Paeps { 2779a8b554fSPhilip Paeps struct acpi_fujitsu_softc *sc; 2789a8b554fSPhilip Paeps ACPI_STATUS status; 2799a8b554fSPhilip Paeps 2809a8b554fSPhilip Paeps sc = device_get_softc(dev); 2819a8b554fSPhilip Paeps 2829a8b554fSPhilip Paeps /* 2839a8b554fSPhilip Paeps * The pointer needs to be re-enabled for 2849a8b554fSPhilip Paeps * some revisions of the P series (2120). 2859a8b554fSPhilip Paeps */ 2869a8b554fSPhilip Paeps ACPI_SERIAL_BEGIN(fujitsu); 2879a8b554fSPhilip Paeps 288b9abb62dSPhilip Paeps if(sc->gmou.exists) { 2899a8b554fSPhilip Paeps status = acpi_SetInteger(sc->handle, "SMOU", 1); 2909a8b554fSPhilip Paeps if (ACPI_FAILURE(status)) 2919a8b554fSPhilip Paeps device_printf(sc->dev, "Couldn't enable pointer\n"); 292b9abb62dSPhilip Paeps } 2939a8b554fSPhilip Paeps ACPI_SERIAL_END(fujitsu); 2949a8b554fSPhilip Paeps 2959a8b554fSPhilip Paeps return (0); 2969a8b554fSPhilip Paeps } 2979a8b554fSPhilip Paeps 2989a8b554fSPhilip Paeps static void 2999a8b554fSPhilip Paeps acpi_fujitsu_notify_status_changed(void *arg) 3009a8b554fSPhilip Paeps { 3019a8b554fSPhilip Paeps struct acpi_fujitsu_softc *sc; 3029a8b554fSPhilip Paeps 3039a8b554fSPhilip Paeps ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); 3049a8b554fSPhilip Paeps 3059a8b554fSPhilip Paeps sc = (struct acpi_fujitsu_softc *)arg; 3069a8b554fSPhilip Paeps 3079a8b554fSPhilip Paeps /* 3089a8b554fSPhilip Paeps * Since our notify function is called, we know something has 3099a8b554fSPhilip Paeps * happened. So the only reason for acpi_fujitsu_update to fail 3109a8b554fSPhilip Paeps * is if we can't find what has changed or an error occurs. 3119a8b554fSPhilip Paeps */ 3129a8b554fSPhilip Paeps ACPI_SERIAL_BEGIN(fujitsu); 3139a8b554fSPhilip Paeps acpi_fujitsu_update(sc); 3149a8b554fSPhilip Paeps ACPI_SERIAL_END(fujitsu); 3159a8b554fSPhilip Paeps } 3169a8b554fSPhilip Paeps 3179a8b554fSPhilip Paeps static void 3189a8b554fSPhilip Paeps acpi_fujitsu_notify_handler(ACPI_HANDLE h, uint32_t notify, void *context) 3199a8b554fSPhilip Paeps { 3209a8b554fSPhilip Paeps struct acpi_fujitsu_softc *sc; 3219a8b554fSPhilip Paeps 3229a8b554fSPhilip Paeps ACPI_FUNCTION_TRACE_U32((char *)(uintptr_t)__func__, notify); 3239a8b554fSPhilip Paeps 3249a8b554fSPhilip Paeps sc = (struct acpi_fujitsu_softc *)context; 3259a8b554fSPhilip Paeps 3269a8b554fSPhilip Paeps switch (notify) { 3279a8b554fSPhilip Paeps case ACPI_NOTIFY_STATUS_CHANGED: 3282be4e471SJung-uk Kim AcpiOsExecute(OSL_NOTIFY_HANDLER, 3299a8b554fSPhilip Paeps acpi_fujitsu_notify_status_changed, sc); 3309a8b554fSPhilip Paeps break; 3319a8b554fSPhilip Paeps default: 3329a8b554fSPhilip Paeps /* unknown notification value */ 3339a8b554fSPhilip Paeps break; 3349a8b554fSPhilip Paeps } 3359a8b554fSPhilip Paeps } 3369a8b554fSPhilip Paeps 3379a8b554fSPhilip Paeps static int 3389a8b554fSPhilip Paeps acpi_fujitsu_detach(device_t dev) 3399a8b554fSPhilip Paeps { 3409a8b554fSPhilip Paeps struct acpi_fujitsu_softc *sc; 3419a8b554fSPhilip Paeps 3429a8b554fSPhilip Paeps sc = device_get_softc(dev); 3439a8b554fSPhilip Paeps AcpiRemoveNotifyHandler(sc->handle, ACPI_DEVICE_NOTIFY, 3449a8b554fSPhilip Paeps acpi_fujitsu_notify_handler); 3459a8b554fSPhilip Paeps 3469a8b554fSPhilip Paeps sysctl_ctx_free(&sc->sysctl_ctx); 3479a8b554fSPhilip Paeps 3489a8b554fSPhilip Paeps return (0); 3499a8b554fSPhilip Paeps } 3509a8b554fSPhilip Paeps 3519a8b554fSPhilip Paeps /* 3529a8b554fSPhilip Paeps * Initializes the names of the ACPI control methods and grabs 353b9abb62dSPhilip Paeps * the current state of all of the ACPI hotkeys into the softc. 3549a8b554fSPhilip Paeps */ 3559a8b554fSPhilip Paeps static uint8_t 3569a8b554fSPhilip Paeps acpi_fujitsu_init(struct acpi_fujitsu_softc *sc) 3579a8b554fSPhilip Paeps { 3589a8b554fSPhilip Paeps struct acpi_softc *acpi_sc; 359b9abb62dSPhilip Paeps int i, exists; 3609a8b554fSPhilip Paeps 3619a8b554fSPhilip Paeps ACPI_SERIAL_ASSERT(fujitsu); 3629a8b554fSPhilip Paeps 3639a8b554fSPhilip Paeps /* Setup all of the names for each control method */ 3649a8b554fSPhilip Paeps sc->_sta.name = "_STA"; 3659a8b554fSPhilip Paeps sc->gbll.name = "GBLL"; 366c82eedb4SAndriy Gapon sc->gbls.name = "GBLS"; 3679a8b554fSPhilip Paeps sc->ghks.name = "GHKS"; 3689a8b554fSPhilip Paeps sc->gmou.name = "GMOU"; 3699a8b554fSPhilip Paeps sc->gsif.name = "GSIF"; 3709a8b554fSPhilip Paeps sc->gvol.name = "GVOL"; 371b9abb62dSPhilip Paeps sc->ghks.name = "GHKS"; 372b9abb62dSPhilip Paeps sc->gsif.name = "GSIF"; 3739a8b554fSPhilip Paeps sc->rbll.name = "RBLL"; 3749a8b554fSPhilip Paeps sc->rvol.name = "RVOL"; 3759a8b554fSPhilip Paeps 376b9abb62dSPhilip Paeps /* Determine what hardware functionality is available */ 377b9abb62dSPhilip Paeps acpi_fujitsu_check_hardware(sc); 378b9abb62dSPhilip Paeps 3799a8b554fSPhilip Paeps /* Build the sysctl tree */ 3809a8b554fSPhilip Paeps acpi_sc = acpi_device_get_parent_softc(sc->dev); 3819a8b554fSPhilip Paeps sysctl_ctx_init(&sc->sysctl_ctx); 3829a8b554fSPhilip Paeps sc->sysctl_tree = SYSCTL_ADD_NODE(&sc->sysctl_ctx, 3839a8b554fSPhilip Paeps SYSCTL_CHILDREN(acpi_sc->acpi_sysctl_tree), 3847029da5cSPawel Biernacki OID_AUTO, "fujitsu", CTLFLAG_RD | CTLFLAG_MPSAFE, 0, ""); 3859a8b554fSPhilip Paeps 3869a8b554fSPhilip Paeps for (i = 0; sysctl_table[i].name != NULL; i++) { 387b9abb62dSPhilip Paeps switch(sysctl_table[i].method) { 388b9abb62dSPhilip Paeps case METHOD_GMOU: 389b9abb62dSPhilip Paeps exists = sc->gmou.exists; 390b9abb62dSPhilip Paeps break; 391b9abb62dSPhilip Paeps case METHOD_GBLL: 392b9abb62dSPhilip Paeps exists = sc->gbll.exists; 393b9abb62dSPhilip Paeps break; 394c82eedb4SAndriy Gapon case METHOD_GBLS: 395c82eedb4SAndriy Gapon exists = sc->gbls.exists; 396c82eedb4SAndriy Gapon break; 397b9abb62dSPhilip Paeps case METHOD_GVOL: 398b9abb62dSPhilip Paeps case METHOD_MUTE: 399b9abb62dSPhilip Paeps exists = sc->gvol.exists; 400b9abb62dSPhilip Paeps break; 401b9abb62dSPhilip Paeps case METHOD_RVOL: 402b9abb62dSPhilip Paeps exists = sc->rvol.exists; 403b9abb62dSPhilip Paeps break; 404b9abb62dSPhilip Paeps case METHOD_RBLL: 405b9abb62dSPhilip Paeps exists = sc->rbll.exists; 406b9abb62dSPhilip Paeps break; 407b9abb62dSPhilip Paeps default: 408b9abb62dSPhilip Paeps /* Allow by default */ 409b9abb62dSPhilip Paeps exists = 1; 410b9abb62dSPhilip Paeps break; 411b9abb62dSPhilip Paeps } 412b9abb62dSPhilip Paeps if(!exists) 413b9abb62dSPhilip Paeps continue; 4149a8b554fSPhilip Paeps SYSCTL_ADD_PROC(&sc->sysctl_ctx, 4159a8b554fSPhilip Paeps SYSCTL_CHILDREN(sc->sysctl_tree), OID_AUTO, 4169a8b554fSPhilip Paeps sysctl_table[i].name, 4177029da5cSPawel Biernacki CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY | 4186237a1ccSAlexander Motin CTLFLAG_MPSAFE, sc, i, acpi_fujitsu_sysctl, "I", 4199a8b554fSPhilip Paeps sysctl_table[i].description); 4209a8b554fSPhilip Paeps } 4219a8b554fSPhilip Paeps 422b9abb62dSPhilip Paeps /* Set the hotkeys to their initial states */ 4239a8b554fSPhilip Paeps if (!acpi_fujitsu_update(sc)) { 424b9abb62dSPhilip Paeps device_printf(sc->dev, "Couldn't init hotkey states\n"); 4259a8b554fSPhilip Paeps return (FALSE); 4269a8b554fSPhilip Paeps } 4279a8b554fSPhilip Paeps 4289a8b554fSPhilip Paeps return (TRUE); 4299a8b554fSPhilip Paeps } 4309a8b554fSPhilip Paeps 4319a8b554fSPhilip Paeps static int 4329a8b554fSPhilip Paeps acpi_fujitsu_sysctl(SYSCTL_HANDLER_ARGS) 4339a8b554fSPhilip Paeps { 4349a8b554fSPhilip Paeps struct acpi_fujitsu_softc *sc; 4359a8b554fSPhilip Paeps int method; 4369a8b554fSPhilip Paeps int arg; 4379a8b554fSPhilip Paeps int function_num, error = 0; 4389a8b554fSPhilip Paeps 4399a8b554fSPhilip Paeps sc = (struct acpi_fujitsu_softc *)oidp->oid_arg1; 4409a8b554fSPhilip Paeps function_num = oidp->oid_arg2; 4419a8b554fSPhilip Paeps method = sysctl_table[function_num].method; 4429a8b554fSPhilip Paeps 4439a8b554fSPhilip Paeps ACPI_SERIAL_BEGIN(fujitsu); 4449a8b554fSPhilip Paeps 4459a8b554fSPhilip Paeps /* Get the current value */ 4469a8b554fSPhilip Paeps arg = acpi_fujitsu_method_get(sc, method); 4479a8b554fSPhilip Paeps error = sysctl_handle_int(oidp, &arg, 0, req); 4489a8b554fSPhilip Paeps 4499a8b554fSPhilip Paeps if (error != 0 || req->newptr == NULL) 4509a8b554fSPhilip Paeps goto out; 4519a8b554fSPhilip Paeps 4529a8b554fSPhilip Paeps /* Update the value */ 4539a8b554fSPhilip Paeps error = acpi_fujitsu_method_set(sc, method, arg); 4549a8b554fSPhilip Paeps 4559a8b554fSPhilip Paeps out: 4569a8b554fSPhilip Paeps ACPI_SERIAL_END(fujitsu); 4579a8b554fSPhilip Paeps return (error); 4589a8b554fSPhilip Paeps } 4599a8b554fSPhilip Paeps 4609a8b554fSPhilip Paeps static int 4619a8b554fSPhilip Paeps acpi_fujitsu_method_get(struct acpi_fujitsu_softc *sc, int method) 4629a8b554fSPhilip Paeps { 4639a8b554fSPhilip Paeps struct int_nameval nv; 4649a8b554fSPhilip Paeps ACPI_STATUS status; 4659a8b554fSPhilip Paeps 4669a8b554fSPhilip Paeps ACPI_SERIAL_ASSERT(fujitsu); 4679a8b554fSPhilip Paeps 4689a8b554fSPhilip Paeps switch (method) { 4699a8b554fSPhilip Paeps case METHOD_GBLL: 4709a8b554fSPhilip Paeps nv = sc->gbll; 4719a8b554fSPhilip Paeps break; 472c82eedb4SAndriy Gapon case METHOD_GBLS: 473c82eedb4SAndriy Gapon nv = sc->gbls; 474c82eedb4SAndriy Gapon break; 4759a8b554fSPhilip Paeps case METHOD_GMOU: 4769a8b554fSPhilip Paeps nv = sc->gmou; 4779a8b554fSPhilip Paeps break; 4789a8b554fSPhilip Paeps case METHOD_GVOL: 4799a8b554fSPhilip Paeps case METHOD_MUTE: 4809a8b554fSPhilip Paeps nv = sc->gvol; 4819a8b554fSPhilip Paeps break; 482b9abb62dSPhilip Paeps case METHOD_GHKS: 483b9abb62dSPhilip Paeps nv = sc->ghks; 484b9abb62dSPhilip Paeps break; 485b9abb62dSPhilip Paeps case METHOD_GSIF: 486b9abb62dSPhilip Paeps nv = sc->gsif; 487b9abb62dSPhilip Paeps break; 488b9abb62dSPhilip Paeps case METHOD_RBLL: 489b9abb62dSPhilip Paeps nv = sc->rbll; 490b9abb62dSPhilip Paeps break; 491b9abb62dSPhilip Paeps case METHOD_RVOL: 492b9abb62dSPhilip Paeps nv = sc->rvol; 493b9abb62dSPhilip Paeps break; 4949a8b554fSPhilip Paeps default: 4959a8b554fSPhilip Paeps return (FALSE); 4969a8b554fSPhilip Paeps } 4979a8b554fSPhilip Paeps 498b9abb62dSPhilip Paeps if(!nv.exists) 499b9abb62dSPhilip Paeps return (EINVAL); 500b9abb62dSPhilip Paeps 5019a8b554fSPhilip Paeps status = acpi_GetInteger(sc->handle, nv.name, &nv.value); 5029a8b554fSPhilip Paeps if (ACPI_FAILURE(status)) { 503b9abb62dSPhilip Paeps device_printf(sc->dev, "Couldn't query method (%s)\n", nv.name); 5049a8b554fSPhilip Paeps return (FALSE); 5059a8b554fSPhilip Paeps } 5069a8b554fSPhilip Paeps 5079a8b554fSPhilip Paeps if (method == METHOD_MUTE) { 5089a8b554fSPhilip Paeps sc->bIsMuted = (uint8_t)((nv.value & VOLUME_MUTE_BIT) != 0); 5099a8b554fSPhilip Paeps return (sc->bIsMuted); 5109a8b554fSPhilip Paeps } 5119a8b554fSPhilip Paeps 5129a8b554fSPhilip Paeps nv.value &= GENERAL_SETTING_BITS; 5139a8b554fSPhilip Paeps return (nv.value); 5149a8b554fSPhilip Paeps } 5159a8b554fSPhilip Paeps 5169a8b554fSPhilip Paeps static int 5179a8b554fSPhilip Paeps acpi_fujitsu_method_set(struct acpi_fujitsu_softc *sc, int method, int value) 5189a8b554fSPhilip Paeps { 5199a8b554fSPhilip Paeps struct int_nameval nv; 5209a8b554fSPhilip Paeps ACPI_STATUS status; 5219a8b554fSPhilip Paeps char *control; 5229a8b554fSPhilip Paeps int changed; 5239a8b554fSPhilip Paeps 5249a8b554fSPhilip Paeps ACPI_SERIAL_ASSERT(fujitsu); 5259a8b554fSPhilip Paeps 5269a8b554fSPhilip Paeps switch (method) { 5279a8b554fSPhilip Paeps case METHOD_GBLL: 5289a8b554fSPhilip Paeps changed = BRIGHT_CHANGED; 5299a8b554fSPhilip Paeps control = "SBLL"; 5309a8b554fSPhilip Paeps nv = sc->gbll; 5319a8b554fSPhilip Paeps break; 532c82eedb4SAndriy Gapon case METHOD_GBLS: 533c82eedb4SAndriy Gapon changed = BRIGHT_CHANGED; 534c82eedb4SAndriy Gapon control = "SBL2"; 535c82eedb4SAndriy Gapon nv = sc->gbls; 536c82eedb4SAndriy Gapon break; 5379a8b554fSPhilip Paeps case METHOD_GMOU: 5389a8b554fSPhilip Paeps changed = MOUSE_CHANGED; 5399a8b554fSPhilip Paeps control = "SMOU"; 5409a8b554fSPhilip Paeps nv = sc->gmou; 5419a8b554fSPhilip Paeps break; 5429a8b554fSPhilip Paeps case METHOD_GVOL: 5439a8b554fSPhilip Paeps case METHOD_MUTE: 5449a8b554fSPhilip Paeps changed = VOLUME_CHANGED; 5459a8b554fSPhilip Paeps control = "SVOL"; 5469a8b554fSPhilip Paeps nv = sc->gvol; 5479a8b554fSPhilip Paeps break; 5489a8b554fSPhilip Paeps default: 5499a8b554fSPhilip Paeps return (EINVAL); 5509a8b554fSPhilip Paeps } 5519a8b554fSPhilip Paeps 552b9abb62dSPhilip Paeps if(!nv.exists) 553b9abb62dSPhilip Paeps return (EINVAL); 554b9abb62dSPhilip Paeps 5559a8b554fSPhilip Paeps if (method == METHOD_MUTE) { 5569a8b554fSPhilip Paeps if (value == 1) 5579a8b554fSPhilip Paeps value = nv.value | VOLUME_MUTE_BIT; 5589a8b554fSPhilip Paeps else if (value == 0) 5599a8b554fSPhilip Paeps value = nv.value & ~VOLUME_MUTE_BIT; 5609a8b554fSPhilip Paeps else 5619a8b554fSPhilip Paeps return (EINVAL); 5629a8b554fSPhilip Paeps } 5639a8b554fSPhilip Paeps 5649a8b554fSPhilip Paeps status = acpi_SetInteger(sc->handle, control, value); 5659a8b554fSPhilip Paeps if (ACPI_FAILURE(status)) { 5669a8b554fSPhilip Paeps device_printf(sc->dev, "Couldn't update %s\n", control); 567b9abb62dSPhilip Paeps return (FALSE); 5689a8b554fSPhilip Paeps } 5699a8b554fSPhilip Paeps 5709a8b554fSPhilip Paeps sc->lastValChanged = changed; 5719a8b554fSPhilip Paeps return (0); 5729a8b554fSPhilip Paeps } 5739a8b554fSPhilip Paeps 5749a8b554fSPhilip Paeps /* 575b9abb62dSPhilip Paeps * Query the get methods to determine what functionality is available 576b9abb62dSPhilip Paeps * from the hardware function hotkeys. 577b9abb62dSPhilip Paeps */ 578b9abb62dSPhilip Paeps static uint8_t 579b9abb62dSPhilip Paeps acpi_fujitsu_check_hardware(struct acpi_fujitsu_softc *sc) 580b9abb62dSPhilip Paeps { 581b9abb62dSPhilip Paeps int val; 582b9abb62dSPhilip Paeps 583b9abb62dSPhilip Paeps ACPI_SERIAL_ASSERT(fujitsu); 584b9abb62dSPhilip Paeps /* save the hotkey bitmask */ 585b9abb62dSPhilip Paeps if (ACPI_FAILURE(acpi_GetInteger(sc->handle, 586b9abb62dSPhilip Paeps sc->gsif.name, &(sc->gsif.value)))) { 587b9abb62dSPhilip Paeps sc->gsif.exists = 0; 588b9abb62dSPhilip Paeps device_printf(sc->dev, "Couldn't query bitmask value\n"); 589b9abb62dSPhilip Paeps } else { 590b9abb62dSPhilip Paeps sc->gsif.exists = 1; 591b9abb62dSPhilip Paeps } 592b9abb62dSPhilip Paeps 593b9abb62dSPhilip Paeps /* System Volume Level */ 594b9abb62dSPhilip Paeps if (ACPI_FAILURE(acpi_GetInteger(sc->handle, 595b9abb62dSPhilip Paeps sc->gvol.name, &val))) { 596b9abb62dSPhilip Paeps sc->gvol.exists = 0; 597b9abb62dSPhilip Paeps } else { 598b9abb62dSPhilip Paeps sc->gvol.exists = 1; 599b9abb62dSPhilip Paeps } 600b9abb62dSPhilip Paeps 601b9abb62dSPhilip Paeps if (ACPI_FAILURE(acpi_GetInteger(sc->handle, 602c82eedb4SAndriy Gapon sc->gbls.name, &val))) { 603c82eedb4SAndriy Gapon sc->gbls.exists = 0; 604c82eedb4SAndriy Gapon } else { 605c82eedb4SAndriy Gapon sc->gbls.exists = 1; 606c82eedb4SAndriy Gapon } 607c82eedb4SAndriy Gapon 608c82eedb4SAndriy Gapon // don't add if we can use the new method 609c82eedb4SAndriy Gapon if (sc->gbls.exists || ACPI_FAILURE(acpi_GetInteger(sc->handle, 610b9abb62dSPhilip Paeps sc->gbll.name, &val))) { 611b9abb62dSPhilip Paeps sc->gbll.exists = 0; 612b9abb62dSPhilip Paeps } else { 613b9abb62dSPhilip Paeps sc->gbll.exists = 1; 614b9abb62dSPhilip Paeps } 615b9abb62dSPhilip Paeps 616b9abb62dSPhilip Paeps if (ACPI_FAILURE(acpi_GetInteger(sc->handle, 617b9abb62dSPhilip Paeps sc->ghks.name, &val))) { 618b9abb62dSPhilip Paeps sc->ghks.exists = 0; 619b9abb62dSPhilip Paeps } else { 620b9abb62dSPhilip Paeps sc->ghks.exists = 1; 621b9abb62dSPhilip Paeps } 622b9abb62dSPhilip Paeps 623b9abb62dSPhilip Paeps if (ACPI_FAILURE(acpi_GetInteger(sc->handle, 624b9abb62dSPhilip Paeps sc->gmou.name, &val))) { 625b9abb62dSPhilip Paeps sc->gmou.exists = 0; 626b9abb62dSPhilip Paeps } else { 627b9abb62dSPhilip Paeps sc->gmou.exists = 1; 628b9abb62dSPhilip Paeps } 629b9abb62dSPhilip Paeps 630b9abb62dSPhilip Paeps if (ACPI_FAILURE(acpi_GetInteger(sc->handle, 631b9abb62dSPhilip Paeps sc->rbll.name, &val))) { 632b9abb62dSPhilip Paeps sc->rbll.exists = 0; 633b9abb62dSPhilip Paeps } else { 634b9abb62dSPhilip Paeps sc->rbll.exists = 1; 635b9abb62dSPhilip Paeps } 636b9abb62dSPhilip Paeps 637b9abb62dSPhilip Paeps if (ACPI_FAILURE(acpi_GetInteger(sc->handle, 638b9abb62dSPhilip Paeps sc->rvol.name, &val))) { 639b9abb62dSPhilip Paeps sc->rvol.exists = 0; 640b9abb62dSPhilip Paeps } else { 641b9abb62dSPhilip Paeps sc->rvol.exists = 1; 642b9abb62dSPhilip Paeps } 643b9abb62dSPhilip Paeps 644b9abb62dSPhilip Paeps return (TRUE); 645b9abb62dSPhilip Paeps } 646b9abb62dSPhilip Paeps 647b9abb62dSPhilip Paeps /* 6489a8b554fSPhilip Paeps * Query each of the ACPI control methods that contain information we're 6499a8b554fSPhilip Paeps * interested in. We check the return values from the control methods and 6509a8b554fSPhilip Paeps * adjust any state variables if they should be adjusted. 6519a8b554fSPhilip Paeps */ 6529a8b554fSPhilip Paeps static uint8_t 6539a8b554fSPhilip Paeps acpi_fujitsu_update(struct acpi_fujitsu_softc *sc) 6549a8b554fSPhilip Paeps { 655b9abb62dSPhilip Paeps int changed; 6569a8b554fSPhilip Paeps struct acpi_softc *acpi_sc; 6579a8b554fSPhilip Paeps 6589a8b554fSPhilip Paeps acpi_sc = acpi_device_get_parent_softc(sc->dev); 6599a8b554fSPhilip Paeps 6609a8b554fSPhilip Paeps ACPI_SERIAL_ASSERT(fujitsu); 661b9abb62dSPhilip Paeps if(sc->gsif.exists) 662b9abb62dSPhilip Paeps changed = sc->gsif.value & acpi_fujitsu_method_get(sc,METHOD_GHKS); 663b9abb62dSPhilip Paeps else 664b9abb62dSPhilip Paeps changed = 0; 6659a8b554fSPhilip Paeps 6669a8b554fSPhilip Paeps /* System Volume Level */ 667b9abb62dSPhilip Paeps if(sc->gvol.exists) { 6689a8b554fSPhilip Paeps if (ACPI_FAILURE(acpi_GetInteger(sc->handle, 6699a8b554fSPhilip Paeps sc->gvol.name, &(sc->gvol.value)))) { 6709a8b554fSPhilip Paeps device_printf(sc->dev, "Couldn't query volume level\n"); 6719a8b554fSPhilip Paeps return (FALSE); 6729a8b554fSPhilip Paeps } 6739a8b554fSPhilip Paeps 674b9abb62dSPhilip Paeps if (changed & VOLUME_CHANGED) { 6759a8b554fSPhilip Paeps sc->bIsMuted = 6769a8b554fSPhilip Paeps (uint8_t)((sc->gvol.value & VOLUME_MUTE_BIT) != 0); 6779a8b554fSPhilip Paeps 6789a8b554fSPhilip Paeps /* Clear the modification bit */ 6799a8b554fSPhilip Paeps sc->gvol.value &= VOLUME_SETTING_BITS; 6809a8b554fSPhilip Paeps 6819a8b554fSPhilip Paeps if (sc->bIsMuted) { 6829a8b554fSPhilip Paeps acpi_UserNotify("FUJITSU", sc->handle, FN_MUTE); 6839a8b554fSPhilip Paeps ACPI_VPRINT(sc->dev, acpi_sc, "Volume is now mute\n"); 6849a8b554fSPhilip Paeps } else 6859a8b554fSPhilip Paeps ACPI_VPRINT(sc->dev, acpi_sc, "Volume is now %d\n", 6869a8b554fSPhilip Paeps sc->gvol.value); 6879a8b554fSPhilip Paeps 6889a8b554fSPhilip Paeps acpi_UserNotify("FUJITSU", sc->handle, FN_VOLUME); 689b9abb62dSPhilip Paeps } 6909a8b554fSPhilip Paeps } 6919a8b554fSPhilip Paeps 6929a8b554fSPhilip Paeps /* Internal mouse pointer (eraserhead) */ 693b9abb62dSPhilip Paeps if(sc->gmou.exists) { 6949a8b554fSPhilip Paeps if (ACPI_FAILURE(acpi_GetInteger(sc->handle, 6959a8b554fSPhilip Paeps sc->gmou.name, &(sc->gmou.value)))) { 6969a8b554fSPhilip Paeps device_printf(sc->dev, "Couldn't query pointer state\n"); 6979a8b554fSPhilip Paeps return (FALSE); 6989a8b554fSPhilip Paeps } 6999a8b554fSPhilip Paeps 700b9abb62dSPhilip Paeps if (changed & MOUSE_CHANGED) { 7019a8b554fSPhilip Paeps sc->bIntPtrEnabled = (uint8_t)(sc->gmou.value & 0x1); 7029a8b554fSPhilip Paeps 7039a8b554fSPhilip Paeps /* Clear the modification bit */ 7049a8b554fSPhilip Paeps sc->gmou.value &= MOUSE_SETTING_BITS; 7059a8b554fSPhilip Paeps 706c82eedb4SAndriy Gapon /* Set the value in case it is not hardware controlled */ 707c82eedb4SAndriy Gapon acpi_fujitsu_method_set(sc, METHOD_GMOU, sc->gmou.value); 708c82eedb4SAndriy Gapon 7099a8b554fSPhilip Paeps acpi_UserNotify("FUJITSU", sc->handle, FN_POINTER_ENABLE); 7109a8b554fSPhilip Paeps 7119a8b554fSPhilip Paeps ACPI_VPRINT(sc->dev, acpi_sc, "Internal pointer is now %s\n", 7129a8b554fSPhilip Paeps (sc->bIntPtrEnabled) ? "enabled" : "disabled"); 713b9abb62dSPhilip Paeps } 7149a8b554fSPhilip Paeps } 7159a8b554fSPhilip Paeps 716c82eedb4SAndriy Gapon /* Screen Brightness Level P8XXX */ 717c82eedb4SAndriy Gapon if(sc->gbls.exists) { 718c82eedb4SAndriy Gapon if (ACPI_FAILURE(acpi_GetInteger(sc->handle, 719c82eedb4SAndriy Gapon sc->gbls.name, &(sc->gbls.value)))) { 720c82eedb4SAndriy Gapon device_printf(sc->dev, "Couldn't query P8XXX brightness level\n"); 721c82eedb4SAndriy Gapon return (FALSE); 722c82eedb4SAndriy Gapon } 723c82eedb4SAndriy Gapon if (changed & BRIGHT_CHANGED) { 724c82eedb4SAndriy Gapon /* No state to record here. */ 725c82eedb4SAndriy Gapon 726c82eedb4SAndriy Gapon /* Clear the modification bit */ 727c82eedb4SAndriy Gapon sc->gbls.value &= BRIGHTNESS_SETTING_BITS; 728c82eedb4SAndriy Gapon 729c82eedb4SAndriy Gapon /* Set the value in case it is not hardware controlled */ 730c82eedb4SAndriy Gapon acpi_fujitsu_method_set(sc, METHOD_GBLS, sc->gbls.value); 731c82eedb4SAndriy Gapon 732c82eedb4SAndriy Gapon acpi_UserNotify("FUJITSU", sc->handle, FN_LCD_BRIGHTNESS); 733c82eedb4SAndriy Gapon 734c82eedb4SAndriy Gapon ACPI_VPRINT(sc->dev, acpi_sc, "P8XXX Brightness level is now %d\n", 735c82eedb4SAndriy Gapon sc->gbls.value); 736c82eedb4SAndriy Gapon } 737c82eedb4SAndriy Gapon } 738c82eedb4SAndriy Gapon 7399a8b554fSPhilip Paeps /* Screen Brightness Level */ 740b9abb62dSPhilip Paeps if(sc->gbll.exists) { 7419a8b554fSPhilip Paeps if (ACPI_FAILURE(acpi_GetInteger(sc->handle, 7429a8b554fSPhilip Paeps sc->gbll.name, &(sc->gbll.value)))) { 7439a8b554fSPhilip Paeps device_printf(sc->dev, "Couldn't query brightness level\n"); 7449a8b554fSPhilip Paeps return (FALSE); 7459a8b554fSPhilip Paeps } 7469a8b554fSPhilip Paeps 747b9abb62dSPhilip Paeps if (changed & BRIGHT_CHANGED) { 7489a8b554fSPhilip Paeps /* No state to record here. */ 7499a8b554fSPhilip Paeps 7509a8b554fSPhilip Paeps /* Clear the modification bit */ 7519a8b554fSPhilip Paeps sc->gbll.value &= BRIGHTNESS_SETTING_BITS; 7529a8b554fSPhilip Paeps 7539a8b554fSPhilip Paeps acpi_UserNotify("FUJITSU", sc->handle, FN_LCD_BRIGHTNESS); 7549a8b554fSPhilip Paeps 7559a8b554fSPhilip Paeps ACPI_VPRINT(sc->dev, acpi_sc, "Brightness level is now %d\n", 7569a8b554fSPhilip Paeps sc->gbll.value); 757b9abb62dSPhilip Paeps } 7589a8b554fSPhilip Paeps } 7599a8b554fSPhilip Paeps 760b9abb62dSPhilip Paeps sc->lastValChanged = changed; 7619a8b554fSPhilip Paeps return (TRUE); 7629a8b554fSPhilip Paeps } 763