1d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe/*-*-linux-c-*-*/ 2d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe 3d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe/* 4409a3e98132c3a4f2aa2854995f8a9dd16cf11acJonathan Woithe Copyright (C) 2007,2008 Jonathan Woithe <jwoithe@just42.net> 520b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe Copyright (C) 2008 Peter Gruber <nokos@gmx.net> 63a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon Copyright (C) 2008 Tony Vroon <tony@linx.net> 7d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe Based on earlier work: 8d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe Copyright (C) 2003 Shane Spencer <shane@bogomip.com> 9d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe Adrian Yee <brewt-fujitsu@brewt.org> 10d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe 1120b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe Templated from msi-laptop.c and thinkpad_acpi.c which is copyright 1220b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe by its respective authors. 13d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe 14d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe This program is free software; you can redistribute it and/or modify 15d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe it under the terms of the GNU General Public License as published by 16d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe the Free Software Foundation; either version 2 of the License, or 17d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe (at your option) any later version. 18d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe 19d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe This program is distributed in the hope that it will be useful, but 20d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe WITHOUT ANY WARRANTY; without even the implied warranty of 21d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 22d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe General Public License for more details. 23d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe 24d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe You should have received a copy of the GNU General Public License 25d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe along with this program; if not, write to the Free Software 26d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 27d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe 02110-1301, USA. 28d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe */ 29d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe 30d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe/* 31d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe * fujitsu-laptop.c - Fujitsu laptop support, providing access to additional 32d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe * features made available on a range of Fujitsu laptops including the 33d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe * P2xxx/P5xxx/S6xxx/S7xxx series. 34d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe * 35d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe * This driver exports a few files in /sys/devices/platform/fujitsu-laptop/; 36d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe * others may be added at a later date. 37d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe * 38d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe * lcd_level - Screen brightness: contains a single integer in the 39d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe * range 0..7. (rw) 40d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe * 41d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe * In addition to these platform device attributes the driver 42d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe * registers itself in the Linux backlight control subsystem and is 43d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe * available to userspace under /sys/class/backlight/fujitsu-laptop/. 44d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe * 4520b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe * Hotkeys present on certain Fujitsu laptops (eg: the S6xxx series) are 4620b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe * also supported by this driver. 4720b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe * 480e6a66e9cf231140d2e49064d48162728edb7746Jonathan Woithe * This driver has been tested on a Fujitsu Lifebook S6410, S7020 and 490e6a66e9cf231140d2e49064d48162728edb7746Jonathan Woithe * P8010. It should work on most P-series and S-series Lifebooks, but 500e6a66e9cf231140d2e49064d48162728edb7746Jonathan Woithe * YMMV. 5120b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe * 5220b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe * The module parameter use_alt_lcd_levels switches between different ACPI 5320b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe * brightness controls which are used by different Fujitsu laptops. In most 5420b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe * cases the correct method is automatically detected. "use_alt_lcd_levels=1" 5520b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe * is applicable for a Fujitsu Lifebook S6410 if autodetection fails. 5620b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe * 57d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe */ 58d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe 5977bad7c830e20085deba6a760ce85c13ecb12f4dJoe Perches#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 6077bad7c830e20085deba6a760ce85c13ecb12f4dJoe Perches 61d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe#include <linux/module.h> 62d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe#include <linux/kernel.h> 63d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe#include <linux/init.h> 64d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe#include <linux/acpi.h> 65d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe#include <linux/dmi.h> 66d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe#include <linux/backlight.h> 6720b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe#include <linux/input.h> 6820b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe#include <linux/kfifo.h> 69d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe#include <linux/platform_device.h> 705a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 711e384cb0f9a940f2a431d1708f963987e61d71e3Stephen Gildea#if defined(CONFIG_LEDS_CLASS) || defined(CONFIG_LEDS_CLASS_MODULE) 723a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon#include <linux/leds.h> 733a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon#endif 74d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe 7584a6ce267296dabdf427ea4aff73dc58164863bbJonathan Woithe#define FUJITSU_DRIVER_VERSION "0.6.0" 76d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe 77d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe#define FUJITSU_LCD_N_LEVELS 8 78d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe 79d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe#define ACPI_FUJITSU_CLASS "fujitsu" 80d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe#define ACPI_FUJITSU_HID "FUJ02B1" 8120b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe#define ACPI_FUJITSU_DRIVER_NAME "Fujitsu laptop FUJ02B1 ACPI brightness driver" 82d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe#define ACPI_FUJITSU_DEVICE_NAME "Fujitsu FUJ02B1" 8320b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe#define ACPI_FUJITSU_HOTKEY_HID "FUJ02E3" 8420b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe#define ACPI_FUJITSU_HOTKEY_DRIVER_NAME "Fujitsu laptop FUJ02E3 ACPI hotkeys driver" 8520b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe#define ACPI_FUJITSU_HOTKEY_DEVICE_NAME "Fujitsu FUJ02E3" 8620b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 8720b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe#define ACPI_FUJITSU_NOTIFY_CODE1 0x80 8820b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 8920b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe#define ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS 0x86 9020b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe#define ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS 0x87 9120b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 923a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon/* FUNC interface - command values */ 933a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon#define FUNC_RFKILL 0x1000 943a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon#define FUNC_LEDS 0x1001 953a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon#define FUNC_BUTTONS 0x1002 963a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon#define FUNC_BACKLIGHT 0x1004 973a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon 983a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon/* FUNC interface - responses */ 993a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon#define UNSUPPORTED_CMD 0x80000000 1003a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon 1011e384cb0f9a940f2a431d1708f963987e61d71e3Stephen Gildea#if defined(CONFIG_LEDS_CLASS) || defined(CONFIG_LEDS_CLASS_MODULE) 1023a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon/* FUNC interface - LED control */ 1033a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon#define FUNC_LED_OFF 0x1 1043a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon#define FUNC_LED_ON 0x30001 1053a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon#define KEYBOARD_LAMPS 0x100 1063a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon#define LOGOLAMP_POWERON 0x2000 1073a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon#define LOGOLAMP_ALWAYS 0x4000 1083a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon#endif 1093a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon 11020b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe/* Hotkey details */ 1110e6a66e9cf231140d2e49064d48162728edb7746Jonathan Woithe#define KEY1_CODE 0x410 /* codes for the keys in the GIRB register */ 1120e6a66e9cf231140d2e49064d48162728edb7746Jonathan Woithe#define KEY2_CODE 0x411 1130e6a66e9cf231140d2e49064d48162728edb7746Jonathan Woithe#define KEY3_CODE 0x412 1140e6a66e9cf231140d2e49064d48162728edb7746Jonathan Woithe#define KEY4_CODE 0x413 11520b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 11620b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe#define MAX_HOTKEY_RINGBUFFER_SIZE 100 11720b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe#define RINGBUFFERSIZE 40 11820b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 11920b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe/* Debugging */ 12020b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe#define FUJLAPTOP_LOG ACPI_FUJITSU_HID ": " 12120b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe#define FUJLAPTOP_ERR KERN_ERR FUJLAPTOP_LOG 12220b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe#define FUJLAPTOP_NOTICE KERN_NOTICE FUJLAPTOP_LOG 12320b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe#define FUJLAPTOP_INFO KERN_INFO FUJLAPTOP_LOG 12420b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe#define FUJLAPTOP_DEBUG KERN_DEBUG FUJLAPTOP_LOG 12520b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 12620b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe#define FUJLAPTOP_DBG_ALL 0xffff 12720b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe#define FUJLAPTOP_DBG_ERROR 0x0001 12820b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe#define FUJLAPTOP_DBG_WARN 0x0002 12920b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe#define FUJLAPTOP_DBG_INFO 0x0004 13020b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe#define FUJLAPTOP_DBG_TRACE 0x0008 13120b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 132c4960cf01f70d86c6440ad5dd540d0c82381785dJean Delvare#ifdef CONFIG_FUJITSU_LAPTOP_DEBUG 133c4960cf01f70d86c6440ad5dd540d0c82381785dJean Delvare#define vdbg_printk(a_dbg_level, format, arg...) \ 13420b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe do { if (dbg_level & a_dbg_level) \ 13520b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe printk(FUJLAPTOP_DEBUG "%s: " format, __func__ , ## arg); \ 13620b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe } while (0) 13720b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe#else 138c4960cf01f70d86c6440ad5dd540d0c82381785dJean Delvare#define vdbg_printk(a_dbg_level, format, arg...) \ 139c4960cf01f70d86c6440ad5dd540d0c82381785dJean Delvare do { } while (0) 14020b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe#endif 14120b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 14220b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe/* Device controlling the backlight and associated keys */ 143d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithestruct fujitsu_t { 144d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe acpi_handle acpi_handle; 14520b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe struct acpi_device *dev; 14620b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe struct input_dev *input; 14720b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe char phys[32]; 148d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe struct backlight_device *bl_device; 149d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe struct platform_device *pf_device; 1500e6a66e9cf231140d2e49064d48162728edb7746Jonathan Woithe int keycode1, keycode2, keycode3, keycode4; 151d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe 15220b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe unsigned int max_brightness; 153d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe unsigned int brightness_changed; 154d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe unsigned int brightness_level; 155d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe}; 156d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe 157d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithestatic struct fujitsu_t *fujitsu; 15820b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithestatic int use_alt_lcd_levels = -1; 15920b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithestatic int disable_brightness_adjust = -1; 16020b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 16120b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe/* Device used to access other hotkeys on the laptop */ 16220b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithestruct fujitsu_hotkey_t { 16320b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe acpi_handle acpi_handle; 16420b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe struct acpi_device *dev; 16520b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe struct input_dev *input; 16620b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe char phys[32]; 16720b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe struct platform_device *pf_device; 16845465487897a1c6d508b14b904dc5777f7ec7e04Stefani Seibold struct kfifo fifo; 16920b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe spinlock_t fifo_lock; 1704898c2b2f04051e19f4230683c0f0b15f71af887Tony Vroon int rfkill_supported; 1713a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon int rfkill_state; 1723a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon int logolamp_registered; 1733a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon int kblamps_registered; 17420b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe}; 175d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe 17620b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithestatic struct fujitsu_hotkey_t *fujitsu_hotkey; 17720b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 178b4ec0275464756f4fd4108b4a4ca7aff61358ad3Bjorn Helgaasstatic void acpi_fujitsu_hotkey_notify(struct acpi_device *device, u32 event); 17920b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 1801e384cb0f9a940f2a431d1708f963987e61d71e3Stephen Gildea#if defined(CONFIG_LEDS_CLASS) || defined(CONFIG_LEDS_CLASS_MODULE) 1813a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroonstatic enum led_brightness logolamp_get(struct led_classdev *cdev); 1823a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroonstatic void logolamp_set(struct led_classdev *cdev, 1833a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon enum led_brightness brightness); 1843a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon 18567af7111689b0b615d27b1a5fcc553bee4639831Axel Linstatic struct led_classdev logolamp_led = { 1863a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon .name = "fujitsu::logolamp", 1873a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon .brightness_get = logolamp_get, 1883a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon .brightness_set = logolamp_set 1893a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon}; 1903a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon 1913a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroonstatic enum led_brightness kblamps_get(struct led_classdev *cdev); 1923a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroonstatic void kblamps_set(struct led_classdev *cdev, 1933a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon enum led_brightness brightness); 1943a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon 19567af7111689b0b615d27b1a5fcc553bee4639831Axel Linstatic struct led_classdev kblamps_led = { 1963a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon .name = "fujitsu::kblamps", 1973a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon .brightness_get = kblamps_get, 1983a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon .brightness_set = kblamps_set 1993a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon}; 2003a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon#endif 2013a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon 20220b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe#ifdef CONFIG_FUJITSU_LAPTOP_DEBUG 20320b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithestatic u32 dbg_level = 0x03; 20420b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe#endif 20520b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 206700b6721cd1b891b67c2dcee046be12154a21fd6Bjorn Helgaasstatic void acpi_fujitsu_notify(struct acpi_device *device, u32 event); 20720b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 2083a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon/* Fujitsu ACPI interface function */ 2093a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon 2103a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroonstatic int call_fext_func(int cmd, int arg0, int arg1, int arg2) 2113a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon{ 2123a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon acpi_status status = AE_OK; 2133a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon union acpi_object params[4] = { 2143a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon { .type = ACPI_TYPE_INTEGER }, 2153a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon { .type = ACPI_TYPE_INTEGER }, 2163a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon { .type = ACPI_TYPE_INTEGER }, 2173a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon { .type = ACPI_TYPE_INTEGER } 2183a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon }; 2193a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon struct acpi_object_list arg_list = { 4, ¶ms[0] }; 22029c29a9bb4d5abdb92480375e42e48a9190306e8Zhang Rui unsigned long long value; 2213a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon acpi_handle handle = NULL; 2223a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon 2233a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon status = acpi_get_handle(fujitsu_hotkey->acpi_handle, "FUNC", &handle); 2243a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon if (ACPI_FAILURE(status)) { 2253a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon vdbg_printk(FUJLAPTOP_DBG_ERROR, 2263a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon "FUNC interface is not present\n"); 2273a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon return -ENODEV; 2283a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon } 2293a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon 2303a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon params[0].integer.value = cmd; 2313a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon params[1].integer.value = arg0; 2323a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon params[2].integer.value = arg1; 2333a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon params[3].integer.value = arg2; 2343a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon 23529c29a9bb4d5abdb92480375e42e48a9190306e8Zhang Rui status = acpi_evaluate_integer(handle, NULL, &arg_list, &value); 2363a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon if (ACPI_FAILURE(status)) { 2373a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon vdbg_printk(FUJLAPTOP_DBG_WARN, 2383a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon "FUNC 0x%x (args 0x%x, 0x%x, 0x%x) call failed\n", 2393a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon cmd, arg0, arg1, arg2); 2403a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon return -ENODEV; 2413a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon } 2423a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon 2433a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon vdbg_printk(FUJLAPTOP_DBG_TRACE, 2443a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon "FUNC 0x%x (args 0x%x, 0x%x, 0x%x) returned 0x%x\n", 24529c29a9bb4d5abdb92480375e42e48a9190306e8Zhang Rui cmd, arg0, arg1, arg2, (int)value); 24629c29a9bb4d5abdb92480375e42e48a9190306e8Zhang Rui return value; 2473a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon} 2483a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon 2491e384cb0f9a940f2a431d1708f963987e61d71e3Stephen Gildea#if defined(CONFIG_LEDS_CLASS) || defined(CONFIG_LEDS_CLASS_MODULE) 2503a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon/* LED class callbacks */ 2513a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon 2523a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroonstatic void logolamp_set(struct led_classdev *cdev, 2533a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon enum led_brightness brightness) 2543a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon{ 2553a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon if (brightness >= LED_FULL) { 2563a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon call_fext_func(FUNC_LEDS, 0x1, LOGOLAMP_POWERON, FUNC_LED_ON); 2573a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon call_fext_func(FUNC_LEDS, 0x1, LOGOLAMP_ALWAYS, FUNC_LED_ON); 2583a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon } else if (brightness >= LED_HALF) { 2593a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon call_fext_func(FUNC_LEDS, 0x1, LOGOLAMP_POWERON, FUNC_LED_ON); 2603a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon call_fext_func(FUNC_LEDS, 0x1, LOGOLAMP_ALWAYS, FUNC_LED_OFF); 2613a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon } else { 2623a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon call_fext_func(FUNC_LEDS, 0x1, LOGOLAMP_POWERON, FUNC_LED_OFF); 2633a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon } 2643a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon} 2653a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon 2663a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroonstatic void kblamps_set(struct led_classdev *cdev, 2673a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon enum led_brightness brightness) 2683a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon{ 2693a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon if (brightness >= LED_FULL) 2703a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon call_fext_func(FUNC_LEDS, 0x1, KEYBOARD_LAMPS, FUNC_LED_ON); 2713a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon else 2723a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon call_fext_func(FUNC_LEDS, 0x1, KEYBOARD_LAMPS, FUNC_LED_OFF); 2733a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon} 2743a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon 2753a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroonstatic enum led_brightness logolamp_get(struct led_classdev *cdev) 2763a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon{ 2773a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon enum led_brightness brightness = LED_OFF; 2783a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon int poweron, always; 2793a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon 2803a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon poweron = call_fext_func(FUNC_LEDS, 0x2, LOGOLAMP_POWERON, 0x0); 2813a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon if (poweron == FUNC_LED_ON) { 2823a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon brightness = LED_HALF; 2833a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon always = call_fext_func(FUNC_LEDS, 0x2, LOGOLAMP_ALWAYS, 0x0); 2843a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon if (always == FUNC_LED_ON) 2853a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon brightness = LED_FULL; 2863a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon } 2873a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon return brightness; 2883a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon} 2893a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon 2903a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroonstatic enum led_brightness kblamps_get(struct led_classdev *cdev) 2913a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon{ 2923a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon enum led_brightness brightness = LED_OFF; 2933a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon 2943a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon if (call_fext_func(FUNC_LEDS, 0x2, KEYBOARD_LAMPS, 0x0) == FUNC_LED_ON) 2953a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon brightness = LED_FULL; 2963a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon 2973a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon return brightness; 2983a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon} 2993a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon#endif 3003a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon 30120b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe/* Hardware access for LCD brightness control */ 302d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe 303d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithestatic int set_lcd_level(int level) 304d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe{ 305d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe acpi_status status = AE_OK; 306d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe acpi_handle handle = NULL; 307d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe 30820b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe vdbg_printk(FUJLAPTOP_DBG_TRACE, "set lcd level via SBLL [%d]\n", 30920b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe level); 31020b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 31120b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe if (level < 0 || level >= fujitsu->max_brightness) 312d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe return -EINVAL; 313d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe 314d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe status = acpi_get_handle(fujitsu->acpi_handle, "SBLL", &handle); 315d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe if (ACPI_FAILURE(status)) { 31620b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe vdbg_printk(FUJLAPTOP_DBG_ERROR, "SBLL not present\n"); 31720b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe return -ENODEV; 31820b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe } 31920b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 32020b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 3216c7fe47a4a3c6e243830ba5f9c6908a38f5ee3edZhang Rui status = acpi_execute_simple_method(handle, NULL, level); 32220b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe if (ACPI_FAILURE(status)) 32320b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe return -ENODEV; 32420b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 32520b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe return 0; 32620b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe} 32720b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 32820b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithestatic int set_lcd_level_alt(int level) 32920b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe{ 33020b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe acpi_status status = AE_OK; 33120b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe acpi_handle handle = NULL; 33220b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 33320b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe vdbg_printk(FUJLAPTOP_DBG_TRACE, "set lcd level via SBL2 [%d]\n", 33420b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe level); 33520b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 33620b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe if (level < 0 || level >= fujitsu->max_brightness) 33720b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe return -EINVAL; 33820b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 33920b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe status = acpi_get_handle(fujitsu->acpi_handle, "SBL2", &handle); 34020b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe if (ACPI_FAILURE(status)) { 34120b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe vdbg_printk(FUJLAPTOP_DBG_ERROR, "SBL2 not present\n"); 342d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe return -ENODEV; 343d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe } 344d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe 3456c7fe47a4a3c6e243830ba5f9c6908a38f5ee3edZhang Rui status = acpi_execute_simple_method(handle, NULL, level); 346d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe if (ACPI_FAILURE(status)) 347d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe return -ENODEV; 348d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe 349d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe return 0; 350d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe} 351d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe 352d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithestatic int get_lcd_level(void) 353d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe{ 35427663c5855b10af9ec67bc7dfba001426ba21222Matthew Wilcox unsigned long long state = 0; 355d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe acpi_status status = AE_OK; 356d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe 35720b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe vdbg_printk(FUJLAPTOP_DBG_TRACE, "get lcd level via GBLL\n"); 35820b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 359d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe status = 360d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe acpi_evaluate_integer(fujitsu->acpi_handle, "GBLL", NULL, &state); 3613b1c37cab3765b87efbd4ed40301ceaf72b9f5c2Jonathan Woithe if (ACPI_FAILURE(status)) 3623b1c37cab3765b87efbd4ed40301ceaf72b9f5c2Jonathan Woithe return 0; 363d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe 36420b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe fujitsu->brightness_level = state & 0x0fffffff; 36520b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 36620b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe if (state & 0x80000000) 36720b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe fujitsu->brightness_changed = 1; 36820b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe else 36920b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe fujitsu->brightness_changed = 0; 37020b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 37120b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe return fujitsu->brightness_level; 37220b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe} 37320b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 37420b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithestatic int get_max_brightness(void) 37520b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe{ 37627663c5855b10af9ec67bc7dfba001426ba21222Matthew Wilcox unsigned long long state = 0; 37720b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe acpi_status status = AE_OK; 37820b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 37920b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe vdbg_printk(FUJLAPTOP_DBG_TRACE, "get max lcd level via RBLL\n"); 38020b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 38120b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe status = 38220b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe acpi_evaluate_integer(fujitsu->acpi_handle, "RBLL", NULL, &state); 3833b1c37cab3765b87efbd4ed40301ceaf72b9f5c2Jonathan Woithe if (ACPI_FAILURE(status)) 3843b1c37cab3765b87efbd4ed40301ceaf72b9f5c2Jonathan Woithe return -1; 38520b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 38620b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe fujitsu->max_brightness = state; 38720b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 38820b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe return fujitsu->max_brightness; 38920b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe} 39020b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 391d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe/* Backlight device stuff */ 392d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe 393d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithestatic int bl_get_brightness(struct backlight_device *b) 394d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe{ 395f87a1a5f6cdaff6232fed2ef0ae0479df9e781e8Tony Vroon return get_lcd_level(); 396d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe} 397d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe 398d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithestatic int bl_update_status(struct backlight_device *b) 399d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe{ 4003a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon int ret; 4013a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon if (b->props.power == 4) 4023a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon ret = call_fext_func(FUNC_BACKLIGHT, 0x1, 0x4, 0x3); 4033a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon else 4043a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon ret = call_fext_func(FUNC_BACKLIGHT, 0x1, 0x4, 0x0); 4053a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon if (ret != 0) 4063a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon vdbg_printk(FUJLAPTOP_DBG_ERROR, 4073a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon "Unable to adjust backlight power, error code %i\n", 4083a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon ret); 4093a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon 41020b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe if (use_alt_lcd_levels) 4113a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon ret = set_lcd_level_alt(b->props.brightness); 41220b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe else 4133a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon ret = set_lcd_level(b->props.brightness); 4143a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon if (ret != 0) 4153a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon vdbg_printk(FUJLAPTOP_DBG_ERROR, 4163a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon "Unable to adjust LCD brightness, error code %i\n", 4173a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon ret); 4183a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon return ret; 419d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe} 420d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe 421acc2472ed33fc5e72482cc3b3b846077d97c2f8bLionel Debrouxstatic const struct backlight_ops fujitsubl_ops = { 422d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe .get_brightness = bl_get_brightness, 423d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe .update_status = bl_update_status, 424d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe}; 425d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe 42620b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe/* Platform LCD brightness device */ 42720b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 42820b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithestatic ssize_t 42920b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woitheshow_max_brightness(struct device *dev, 43020b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe struct device_attribute *attr, char *buf) 43120b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe{ 43220b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 43320b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe int ret; 43420b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 43520b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe ret = get_max_brightness(); 43620b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe if (ret < 0) 43720b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe return ret; 43820b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 43920b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe return sprintf(buf, "%i\n", ret); 44020b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe} 44120b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 44220b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithestatic ssize_t 44320b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woitheshow_brightness_changed(struct device *dev, 44420b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe struct device_attribute *attr, char *buf) 44520b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe{ 44620b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 44720b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe int ret; 44820b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 44920b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe ret = fujitsu->brightness_changed; 45020b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe if (ret < 0) 45120b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe return ret; 45220b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 45320b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe return sprintf(buf, "%i\n", ret); 45420b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe} 455d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe 456d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithestatic ssize_t show_lcd_level(struct device *dev, 457d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe struct device_attribute *attr, char *buf) 458d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe{ 459d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe 460d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe int ret; 461d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe 462f87a1a5f6cdaff6232fed2ef0ae0479df9e781e8Tony Vroon ret = get_lcd_level(); 463d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe if (ret < 0) 464d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe return ret; 465d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe 466d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe return sprintf(buf, "%i\n", ret); 467d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe} 468d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe 469d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithestatic ssize_t store_lcd_level(struct device *dev, 470d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe struct device_attribute *attr, const char *buf, 471d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe size_t count) 472d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe{ 473d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe 474d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe int level, ret; 475d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe 476d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe if (sscanf(buf, "%i", &level) != 1 47720b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe || (level < 0 || level >= fujitsu->max_brightness)) 478d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe return -EINVAL; 479d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe 48020b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe if (use_alt_lcd_levels) 48120b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe ret = set_lcd_level_alt(level); 48220b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe else 48320b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe ret = set_lcd_level(level); 48420b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe if (ret < 0) 48520b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe return ret; 48620b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 487f87a1a5f6cdaff6232fed2ef0ae0479df9e781e8Tony Vroon ret = get_lcd_level(); 488d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe if (ret < 0) 489d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe return ret; 490d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe 491d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe return count; 492d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe} 493d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe 4943a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroonstatic ssize_t 4953a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroonignore_store(struct device *dev, 4963a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon struct device_attribute *attr, const char *buf, size_t count) 49720b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe{ 4983a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon return count; 4993a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon} 50020b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 5013a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroonstatic ssize_t 5023a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroonshow_lid_state(struct device *dev, 5033a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon struct device_attribute *attr, char *buf) 5043a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon{ 5054898c2b2f04051e19f4230683c0f0b15f71af887Tony Vroon if (!(fujitsu_hotkey->rfkill_supported & 0x100)) 5063a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon return sprintf(buf, "unknown\n"); 5073a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon if (fujitsu_hotkey->rfkill_state & 0x100) 5083a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon return sprintf(buf, "open\n"); 5093a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon else 5103a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon return sprintf(buf, "closed\n"); 5113a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon} 51220b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 5133a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroonstatic ssize_t 5143a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroonshow_dock_state(struct device *dev, 5153a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon struct device_attribute *attr, char *buf) 5163a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon{ 5174898c2b2f04051e19f4230683c0f0b15f71af887Tony Vroon if (!(fujitsu_hotkey->rfkill_supported & 0x200)) 5183a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon return sprintf(buf, "unknown\n"); 5193a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon if (fujitsu_hotkey->rfkill_state & 0x200) 5203a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon return sprintf(buf, "docked\n"); 5213a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon else 5223a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon return sprintf(buf, "undocked\n"); 52320b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe} 52420b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 52520b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithestatic ssize_t 5263a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroonshow_radios_state(struct device *dev, 5273a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon struct device_attribute *attr, char *buf) 52820b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe{ 5294898c2b2f04051e19f4230683c0f0b15f71af887Tony Vroon if (!(fujitsu_hotkey->rfkill_supported & 0x20)) 5303a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon return sprintf(buf, "unknown\n"); 5313a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon if (fujitsu_hotkey->rfkill_state & 0x20) 5323a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon return sprintf(buf, "on\n"); 5333a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon else 5343a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon return sprintf(buf, "killed\n"); 53520b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe} 53620b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 53720b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithestatic DEVICE_ATTR(max_brightness, 0444, show_max_brightness, ignore_store); 53820b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithestatic DEVICE_ATTR(brightness_changed, 0444, show_brightness_changed, 53920b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe ignore_store); 540d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithestatic DEVICE_ATTR(lcd_level, 0644, show_lcd_level, store_lcd_level); 5413a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroonstatic DEVICE_ATTR(lid, 0444, show_lid_state, ignore_store); 5423a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroonstatic DEVICE_ATTR(dock, 0444, show_dock_state, ignore_store); 5433a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroonstatic DEVICE_ATTR(radios, 0444, show_radios_state, ignore_store); 544d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe 545d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithestatic struct attribute *fujitsupf_attributes[] = { 54620b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe &dev_attr_brightness_changed.attr, 54720b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe &dev_attr_max_brightness.attr, 548d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe &dev_attr_lcd_level.attr, 5493a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon &dev_attr_lid.attr, 5503a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon &dev_attr_dock.attr, 5513a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon &dev_attr_radios.attr, 552d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe NULL 553d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe}; 554d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe 555d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithestatic struct attribute_group fujitsupf_attribute_group = { 556d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe .attrs = fujitsupf_attributes 557d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe}; 558d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe 559d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithestatic struct platform_driver fujitsupf_driver = { 560d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe .driver = { 561d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe .name = "fujitsu-laptop", 562d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe .owner = THIS_MODULE, 563d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe } 564d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe}; 565d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe 566fbe9b79f8c574de1dfbd9eb933f4065af8738357Mathias Krausestatic void __init dmi_check_cb_common(const struct dmi_system_id *id) 56720b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe{ 56877bad7c830e20085deba6a760ce85c13ecb12f4dJoe Perches pr_info("Identified laptop model '%s'\n", id->ident); 56920b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe if (use_alt_lcd_levels == -1) { 570dd13b9a6d58d15a2cc596e1eb0baa043705c7bc8Zhang Rui if (acpi_has_method(NULL, 571dd13b9a6d58d15a2cc596e1eb0baa043705c7bc8Zhang Rui "\\_SB.PCI0.LPCB.FJEX.SBL2")) 572f87a1a5f6cdaff6232fed2ef0ae0479df9e781e8Tony Vroon use_alt_lcd_levels = 1; 573f87a1a5f6cdaff6232fed2ef0ae0479df9e781e8Tony Vroon else 574f87a1a5f6cdaff6232fed2ef0ae0479df9e781e8Tony Vroon use_alt_lcd_levels = 0; 575f87a1a5f6cdaff6232fed2ef0ae0479df9e781e8Tony Vroon vdbg_printk(FUJLAPTOP_DBG_TRACE, "auto-detected usealt as " 576f87a1a5f6cdaff6232fed2ef0ae0479df9e781e8Tony Vroon "%i\n", use_alt_lcd_levels); 57720b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe } 5780e6a66e9cf231140d2e49064d48162728edb7746Jonathan Woithe} 5790e6a66e9cf231140d2e49064d48162728edb7746Jonathan Woithe 580fbe9b79f8c574de1dfbd9eb933f4065af8738357Mathias Krausestatic int __init dmi_check_cb_s6410(const struct dmi_system_id *id) 5810e6a66e9cf231140d2e49064d48162728edb7746Jonathan Woithe{ 5820e6a66e9cf231140d2e49064d48162728edb7746Jonathan Woithe dmi_check_cb_common(id); 5830e6a66e9cf231140d2e49064d48162728edb7746Jonathan Woithe fujitsu->keycode1 = KEY_SCREENLOCK; /* "Lock" */ 5840e6a66e9cf231140d2e49064d48162728edb7746Jonathan Woithe fujitsu->keycode2 = KEY_HELP; /* "Mobility Center" */ 58580183a4b637982d56965e4a27b823c9a29d185b3Axel Lin return 1; 5860e6a66e9cf231140d2e49064d48162728edb7746Jonathan Woithe} 5870e6a66e9cf231140d2e49064d48162728edb7746Jonathan Woithe 588fbe9b79f8c574de1dfbd9eb933f4065af8738357Mathias Krausestatic int __init dmi_check_cb_s6420(const struct dmi_system_id *id) 58956960b546a88844a6f5295a9f81aab9e6b81edc9Tony Vroon{ 59056960b546a88844a6f5295a9f81aab9e6b81edc9Tony Vroon dmi_check_cb_common(id); 59156960b546a88844a6f5295a9f81aab9e6b81edc9Tony Vroon fujitsu->keycode1 = KEY_SCREENLOCK; /* "Lock" */ 59256960b546a88844a6f5295a9f81aab9e6b81edc9Tony Vroon fujitsu->keycode2 = KEY_HELP; /* "Mobility Center" */ 59380183a4b637982d56965e4a27b823c9a29d185b3Axel Lin return 1; 59456960b546a88844a6f5295a9f81aab9e6b81edc9Tony Vroon} 59556960b546a88844a6f5295a9f81aab9e6b81edc9Tony Vroon 596fbe9b79f8c574de1dfbd9eb933f4065af8738357Mathias Krausestatic int __init dmi_check_cb_p8010(const struct dmi_system_id *id) 5970e6a66e9cf231140d2e49064d48162728edb7746Jonathan Woithe{ 5980e6a66e9cf231140d2e49064d48162728edb7746Jonathan Woithe dmi_check_cb_common(id); 5990e6a66e9cf231140d2e49064d48162728edb7746Jonathan Woithe fujitsu->keycode1 = KEY_HELP; /* "Support" */ 6000e6a66e9cf231140d2e49064d48162728edb7746Jonathan Woithe fujitsu->keycode3 = KEY_SWITCHVIDEOMODE; /* "Presentation" */ 6010e6a66e9cf231140d2e49064d48162728edb7746Jonathan Woithe fujitsu->keycode4 = KEY_WWW; /* "Internet" */ 60280183a4b637982d56965e4a27b823c9a29d185b3Axel Lin return 1; 60320b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe} 60420b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 605fbe9b79f8c574de1dfbd9eb933f4065af8738357Mathias Krausestatic const struct dmi_system_id fujitsu_dmi_table[] __initconst = { 60620b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe { 6070e6a66e9cf231140d2e49064d48162728edb7746Jonathan Woithe .ident = "Fujitsu Siemens S6410", 60820b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe .matches = { 60920b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), 61020b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK S6410"), 61120b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe }, 61220b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe .callback = dmi_check_cb_s6410}, 613d8196a93b1ce9a5abb410f39f9375912c9e53675Jonathan Woithe { 61456960b546a88844a6f5295a9f81aab9e6b81edc9Tony Vroon .ident = "Fujitsu Siemens S6420", 61556960b546a88844a6f5295a9f81aab9e6b81edc9Tony Vroon .matches = { 61656960b546a88844a6f5295a9f81aab9e6b81edc9Tony Vroon DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), 61756960b546a88844a6f5295a9f81aab9e6b81edc9Tony Vroon DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK S6420"), 61856960b546a88844a6f5295a9f81aab9e6b81edc9Tony Vroon }, 61956960b546a88844a6f5295a9f81aab9e6b81edc9Tony Vroon .callback = dmi_check_cb_s6420}, 62056960b546a88844a6f5295a9f81aab9e6b81edc9Tony Vroon { 6210e6a66e9cf231140d2e49064d48162728edb7746Jonathan Woithe .ident = "Fujitsu LifeBook P8010", 622d8196a93b1ce9a5abb410f39f9375912c9e53675Jonathan Woithe .matches = { 623d8196a93b1ce9a5abb410f39f9375912c9e53675Jonathan Woithe DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), 624d8196a93b1ce9a5abb410f39f9375912c9e53675Jonathan Woithe DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook P8010"), 6250e6a66e9cf231140d2e49064d48162728edb7746Jonathan Woithe }, 6260e6a66e9cf231140d2e49064d48162728edb7746Jonathan Woithe .callback = dmi_check_cb_p8010}, 62720b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe {} 62820b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe}; 62920b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 63020b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe/* ACPI device for LCD brightness control */ 631d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe 632b6f03ae6defb61bb4b8e7a8e4b9081a1dd1d3ef9Adrian Bunkstatic int acpi_fujitsu_add(struct acpi_device *device) 633d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe{ 634d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe int state = 0; 63520b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe struct input_dev *input; 63620b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe int error; 637d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe 638d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe if (!device) 639d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe return -EINVAL; 640d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe 641d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe fujitsu->acpi_handle = device->handle; 642d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe sprintf(acpi_device_name(device), "%s", ACPI_FUJITSU_DEVICE_NAME); 643d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe sprintf(acpi_device_class(device), "%s", ACPI_FUJITSU_CLASS); 644db89b4f0dbab837d0f3de2c3e9427a8d5393afa3Pavel Machek device->driver_data = fujitsu; 645d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe 64620b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe fujitsu->input = input = input_allocate_device(); 64720b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe if (!input) { 64820b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe error = -ENOMEM; 649700b6721cd1b891b67c2dcee046be12154a21fd6Bjorn Helgaas goto err_stop; 65020b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe } 65120b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 65220b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe snprintf(fujitsu->phys, sizeof(fujitsu->phys), 65320b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe "%s/video/input0", acpi_device_hid(device)); 65420b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 65520b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe input->name = acpi_device_name(device); 65620b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe input->phys = fujitsu->phys; 65720b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe input->id.bustype = BUS_HOST; 65820b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe input->id.product = 0x06; 65920b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe input->dev.parent = &device->dev; 66020b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe input->evbit[0] = BIT(EV_KEY); 66120b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe set_bit(KEY_BRIGHTNESSUP, input->keybit); 66220b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe set_bit(KEY_BRIGHTNESSDOWN, input->keybit); 66320b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe set_bit(KEY_UNKNOWN, input->keybit); 66420b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 66520b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe error = input_register_device(input); 66620b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe if (error) 66720b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe goto err_free_input_dev; 66820b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 669b30bb89f0fb29502f573d01419391a1e2a4cc4f1Julia Lawall error = acpi_bus_update_power(fujitsu->acpi_handle, &state); 670b30bb89f0fb29502f573d01419391a1e2a4cc4f1Julia Lawall if (error) { 67177bad7c830e20085deba6a760ce85c13ecb12f4dJoe Perches pr_err("Error reading power state\n"); 67272afeeafe54853881a4e53dc78d538e249130ad8Bartlomiej Zolnierkiewicz goto err_unregister_input_dev; 673d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe } 674d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe 67577bad7c830e20085deba6a760ce85c13ecb12f4dJoe Perches pr_info("ACPI: %s [%s] (%s)\n", 676d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe acpi_device_name(device), acpi_device_bid(device), 677d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe !device->power.state ? "on" : "off"); 678d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe 67920b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe fujitsu->dev = device; 68020b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 681dd13b9a6d58d15a2cc596e1eb0baa043705c7bc8Zhang Rui if (acpi_has_method(device->handle, METHOD_NAME__INI)) { 68220b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe vdbg_printk(FUJLAPTOP_DBG_INFO, "Invoking _INI\n"); 68320b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe if (ACPI_FAILURE 68420b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe (acpi_evaluate_object 68520b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe (device->handle, METHOD_NAME__INI, NULL, NULL))) 68677bad7c830e20085deba6a760ce85c13ecb12f4dJoe Perches pr_err("_INI Method failed\n"); 68720b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe } 68820b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 68920b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe /* do config (detect defaults) */ 69020b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe use_alt_lcd_levels = use_alt_lcd_levels == 1 ? 1 : 0; 69120b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe disable_brightness_adjust = disable_brightness_adjust == 1 ? 1 : 0; 69220b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe vdbg_printk(FUJLAPTOP_DBG_INFO, 693f87a1a5f6cdaff6232fed2ef0ae0479df9e781e8Tony Vroon "config: [alt interface: %d], [adjust disable: %d]\n", 694f87a1a5f6cdaff6232fed2ef0ae0479df9e781e8Tony Vroon use_alt_lcd_levels, disable_brightness_adjust); 69520b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 69620b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe if (get_max_brightness() <= 0) 69720b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe fujitsu->max_brightness = FUJITSU_LCD_N_LEVELS; 698f87a1a5f6cdaff6232fed2ef0ae0479df9e781e8Tony Vroon get_lcd_level(); 69920b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 700b30bb89f0fb29502f573d01419391a1e2a4cc4f1Julia Lawall return 0; 70120b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 70272afeeafe54853881a4e53dc78d538e249130ad8Bartlomiej Zolnierkiewiczerr_unregister_input_dev: 70372afeeafe54853881a4e53dc78d538e249130ad8Bartlomiej Zolnierkiewicz input_unregister_device(input); 7048e4e2efdfab5448b0a01be8883d62fc90cce2a7eAxel Lin input = NULL; 70520b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woitheerr_free_input_dev: 70620b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe input_free_device(input); 70720b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woitheerr_stop: 708b30bb89f0fb29502f573d01419391a1e2a4cc4f1Julia Lawall return error; 709d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe} 710d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe 71151fac8388a0325a43f0ae67453ece2c373e2ec28Rafael J. Wysockistatic int acpi_fujitsu_remove(struct acpi_device *device) 712d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe{ 71372afeeafe54853881a4e53dc78d538e249130ad8Bartlomiej Zolnierkiewicz struct fujitsu_t *fujitsu = acpi_driver_data(device); 71472afeeafe54853881a4e53dc78d538e249130ad8Bartlomiej Zolnierkiewicz struct input_dev *input = fujitsu->input; 715d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe 71672afeeafe54853881a4e53dc78d538e249130ad8Bartlomiej Zolnierkiewicz input_unregister_device(input); 71720b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 7185cf83b9b1279dbcdbcf91522bf766c998270ec44Al Viro fujitsu->acpi_handle = NULL; 719d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe 720d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe return 0; 721d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe} 722d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe 72320b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe/* Brightness notify */ 72420b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 725700b6721cd1b891b67c2dcee046be12154a21fd6Bjorn Helgaasstatic void acpi_fujitsu_notify(struct acpi_device *device, u32 event) 72620b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe{ 72720b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe struct input_dev *input; 72820b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe int keycode; 72920b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe int oldb, newb; 73020b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 73120b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe input = fujitsu->input; 73220b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 73320b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe switch (event) { 73420b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe case ACPI_FUJITSU_NOTIFY_CODE1: 73520b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe keycode = 0; 73620b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe oldb = fujitsu->brightness_level; 737f87a1a5f6cdaff6232fed2ef0ae0479df9e781e8Tony Vroon get_lcd_level(); 73820b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe newb = fujitsu->brightness_level; 73920b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 74020b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe vdbg_printk(FUJLAPTOP_DBG_TRACE, 74120b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe "brightness button event [%i -> %i (%i)]\n", 74220b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe oldb, newb, fujitsu->brightness_changed); 74320b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 744f87a1a5f6cdaff6232fed2ef0ae0479df9e781e8Tony Vroon if (oldb < newb) { 74520b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe if (disable_brightness_adjust != 1) { 74620b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe if (use_alt_lcd_levels) 74720b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe set_lcd_level_alt(newb); 74820b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe else 74920b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe set_lcd_level(newb); 75020b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe } 751f87a1a5f6cdaff6232fed2ef0ae0479df9e781e8Tony Vroon keycode = KEY_BRIGHTNESSUP; 75220b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe } else if (oldb > newb) { 75320b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe if (disable_brightness_adjust != 1) { 75420b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe if (use_alt_lcd_levels) 75520b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe set_lcd_level_alt(newb); 75620b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe else 75720b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe set_lcd_level(newb); 75820b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe } 759f87a1a5f6cdaff6232fed2ef0ae0479df9e781e8Tony Vroon keycode = KEY_BRIGHTNESSDOWN; 76020b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe } 76120b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe break; 76220b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe default: 76320b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe keycode = KEY_UNKNOWN; 76420b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe vdbg_printk(FUJLAPTOP_DBG_WARN, 76520b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe "unsupported event [0x%x]\n", event); 76620b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe break; 76720b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe } 76820b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 76920b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe if (keycode != 0) { 77020b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe input_report_key(input, keycode, 1); 77120b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe input_sync(input); 77220b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe input_report_key(input, keycode, 0); 77320b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe input_sync(input); 77420b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe } 77520b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe} 77620b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 77720b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe/* ACPI device for hotkey handling */ 77820b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 77920b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithestatic int acpi_fujitsu_hotkey_add(struct acpi_device *device) 78020b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe{ 78120b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe int result = 0; 78220b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe int state = 0; 78320b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe struct input_dev *input; 78420b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe int error; 78520b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe int i; 78620b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 78720b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe if (!device) 78820b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe return -EINVAL; 78920b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 79020b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe fujitsu_hotkey->acpi_handle = device->handle; 79120b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe sprintf(acpi_device_name(device), "%s", 79220b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe ACPI_FUJITSU_HOTKEY_DEVICE_NAME); 79320b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe sprintf(acpi_device_class(device), "%s", ACPI_FUJITSU_CLASS); 794db89b4f0dbab837d0f3de2c3e9427a8d5393afa3Pavel Machek device->driver_data = fujitsu_hotkey; 79520b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 79620b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe /* kfifo */ 79720b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe spin_lock_init(&fujitsu_hotkey->fifo_lock); 79845465487897a1c6d508b14b904dc5777f7ec7e04Stefani Seibold error = kfifo_alloc(&fujitsu_hotkey->fifo, RINGBUFFERSIZE * sizeof(int), 799c1e13f25674ed564948ecb7dfe5f83e578892896Stefani Seibold GFP_KERNEL); 80045465487897a1c6d508b14b904dc5777f7ec7e04Stefani Seibold if (error) { 80177bad7c830e20085deba6a760ce85c13ecb12f4dJoe Perches pr_err("kfifo_alloc failed\n"); 80220b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe goto err_stop; 80320b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe } 80420b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 80520b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe fujitsu_hotkey->input = input = input_allocate_device(); 80620b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe if (!input) { 80720b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe error = -ENOMEM; 808b4ec0275464756f4fd4108b4a4ca7aff61358ad3Bjorn Helgaas goto err_free_fifo; 80920b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe } 81020b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 81120b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe snprintf(fujitsu_hotkey->phys, sizeof(fujitsu_hotkey->phys), 81220b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe "%s/video/input0", acpi_device_hid(device)); 81320b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 81420b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe input->name = acpi_device_name(device); 81520b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe input->phys = fujitsu_hotkey->phys; 81620b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe input->id.bustype = BUS_HOST; 81720b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe input->id.product = 0x06; 81820b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe input->dev.parent = &device->dev; 8193a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon 8203a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon set_bit(EV_KEY, input->evbit); 8210e6a66e9cf231140d2e49064d48162728edb7746Jonathan Woithe set_bit(fujitsu->keycode1, input->keybit); 8220e6a66e9cf231140d2e49064d48162728edb7746Jonathan Woithe set_bit(fujitsu->keycode2, input->keybit); 8230e6a66e9cf231140d2e49064d48162728edb7746Jonathan Woithe set_bit(fujitsu->keycode3, input->keybit); 8240e6a66e9cf231140d2e49064d48162728edb7746Jonathan Woithe set_bit(fujitsu->keycode4, input->keybit); 82520b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe set_bit(KEY_UNKNOWN, input->keybit); 82620b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 82720b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe error = input_register_device(input); 82820b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe if (error) 82920b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe goto err_free_input_dev; 83020b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 831b30bb89f0fb29502f573d01419391a1e2a4cc4f1Julia Lawall error = acpi_bus_update_power(fujitsu_hotkey->acpi_handle, &state); 832b30bb89f0fb29502f573d01419391a1e2a4cc4f1Julia Lawall if (error) { 83377bad7c830e20085deba6a760ce85c13ecb12f4dJoe Perches pr_err("Error reading power state\n"); 83472afeeafe54853881a4e53dc78d538e249130ad8Bartlomiej Zolnierkiewicz goto err_unregister_input_dev; 83520b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe } 83620b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 83777bad7c830e20085deba6a760ce85c13ecb12f4dJoe Perches pr_info("ACPI: %s [%s] (%s)\n", 83877bad7c830e20085deba6a760ce85c13ecb12f4dJoe Perches acpi_device_name(device), acpi_device_bid(device), 83977bad7c830e20085deba6a760ce85c13ecb12f4dJoe Perches !device->power.state ? "on" : "off"); 84020b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 84120b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe fujitsu_hotkey->dev = device; 84220b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 843dd13b9a6d58d15a2cc596e1eb0baa043705c7bc8Zhang Rui if (acpi_has_method(device->handle, METHOD_NAME__INI)) { 84420b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe vdbg_printk(FUJLAPTOP_DBG_INFO, "Invoking _INI\n"); 84520b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe if (ACPI_FAILURE 84620b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe (acpi_evaluate_object 84720b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe (device->handle, METHOD_NAME__INI, NULL, NULL))) 84877bad7c830e20085deba6a760ce85c13ecb12f4dJoe Perches pr_err("_INI Method failed\n"); 84920b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe } 85020b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 8513a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon i = 0; 8523a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon while (call_fext_func(FUNC_BUTTONS, 0x1, 0x0, 0x0) != 0 8533a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon && (i++) < MAX_HOTKEY_RINGBUFFER_SIZE) 8543a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon ; /* No action, result is discarded */ 85520b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe vdbg_printk(FUJLAPTOP_DBG_INFO, "Discarded %i ringbuffer entries\n", i); 85620b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 8574898c2b2f04051e19f4230683c0f0b15f71af887Tony Vroon fujitsu_hotkey->rfkill_supported = 8584898c2b2f04051e19f4230683c0f0b15f71af887Tony Vroon call_fext_func(FUNC_RFKILL, 0x0, 0x0, 0x0); 8594898c2b2f04051e19f4230683c0f0b15f71af887Tony Vroon 8604898c2b2f04051e19f4230683c0f0b15f71af887Tony Vroon /* Make sure our bitmask of supported functions is cleared if the 8614898c2b2f04051e19f4230683c0f0b15f71af887Tony Vroon RFKILL function block is not implemented, like on the S7020. */ 8624898c2b2f04051e19f4230683c0f0b15f71af887Tony Vroon if (fujitsu_hotkey->rfkill_supported == UNSUPPORTED_CMD) 8634898c2b2f04051e19f4230683c0f0b15f71af887Tony Vroon fujitsu_hotkey->rfkill_supported = 0; 8644898c2b2f04051e19f4230683c0f0b15f71af887Tony Vroon 8654898c2b2f04051e19f4230683c0f0b15f71af887Tony Vroon if (fujitsu_hotkey->rfkill_supported) 8664898c2b2f04051e19f4230683c0f0b15f71af887Tony Vroon fujitsu_hotkey->rfkill_state = 8674898c2b2f04051e19f4230683c0f0b15f71af887Tony Vroon call_fext_func(FUNC_RFKILL, 0x4, 0x0, 0x0); 8683a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon 8693a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon /* Suspect this is a keymap of the application panel, print it */ 87077bad7c830e20085deba6a760ce85c13ecb12f4dJoe Perches pr_info("BTNI: [0x%x]\n", call_fext_func(FUNC_BUTTONS, 0x0, 0x0, 0x0)); 8713a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon 87272afeeafe54853881a4e53dc78d538e249130ad8Bartlomiej Zolnierkiewicz#if defined(CONFIG_LEDS_CLASS) || defined(CONFIG_LEDS_CLASS_MODULE) 8733a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon if (call_fext_func(FUNC_LEDS, 0x0, 0x0, 0x0) & LOGOLAMP_POWERON) { 8743a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon result = led_classdev_register(&fujitsu->pf_device->dev, 8753a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon &logolamp_led); 8763a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon if (result == 0) { 8773a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon fujitsu_hotkey->logolamp_registered = 1; 8783a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon } else { 87977bad7c830e20085deba6a760ce85c13ecb12f4dJoe Perches pr_err("Could not register LED handler for logo lamp, error %i\n", 88077bad7c830e20085deba6a760ce85c13ecb12f4dJoe Perches result); 8813a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon } 8823a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon } 8833a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon 8843a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon if ((call_fext_func(FUNC_LEDS, 0x0, 0x0, 0x0) & KEYBOARD_LAMPS) && 8853a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon (call_fext_func(FUNC_BUTTONS, 0x0, 0x0, 0x0) == 0x0)) { 8863a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon result = led_classdev_register(&fujitsu->pf_device->dev, 8873a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon &kblamps_led); 8883a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon if (result == 0) { 8893a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon fujitsu_hotkey->kblamps_registered = 1; 8903a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon } else { 89177bad7c830e20085deba6a760ce85c13ecb12f4dJoe Perches pr_err("Could not register LED handler for keyboard lamps, error %i\n", 89277bad7c830e20085deba6a760ce85c13ecb12f4dJoe Perches result); 8933a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon } 8943a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon } 89572afeeafe54853881a4e53dc78d538e249130ad8Bartlomiej Zolnierkiewicz#endif 8963a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon 89720b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe return result; 89820b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 89972afeeafe54853881a4e53dc78d538e249130ad8Bartlomiej Zolnierkiewiczerr_unregister_input_dev: 90072afeeafe54853881a4e53dc78d538e249130ad8Bartlomiej Zolnierkiewicz input_unregister_device(input); 9018e4e2efdfab5448b0a01be8883d62fc90cce2a7eAxel Lin input = NULL; 90220b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woitheerr_free_input_dev: 90320b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe input_free_device(input); 904b4ec0275464756f4fd4108b4a4ca7aff61358ad3Bjorn Helgaaserr_free_fifo: 90545465487897a1c6d508b14b904dc5777f7ec7e04Stefani Seibold kfifo_free(&fujitsu_hotkey->fifo); 90620b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woitheerr_stop: 907b30bb89f0fb29502f573d01419391a1e2a4cc4f1Julia Lawall return error; 90820b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe} 90920b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 91051fac8388a0325a43f0ae67453ece2c373e2ec28Rafael J. Wysockistatic int acpi_fujitsu_hotkey_remove(struct acpi_device *device) 91120b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe{ 91272afeeafe54853881a4e53dc78d538e249130ad8Bartlomiej Zolnierkiewicz struct fujitsu_hotkey_t *fujitsu_hotkey = acpi_driver_data(device); 91372afeeafe54853881a4e53dc78d538e249130ad8Bartlomiej Zolnierkiewicz struct input_dev *input = fujitsu_hotkey->input; 91420b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 9152906206350b7e13e2047467cc29a0a2d78d71cb2Jonathan Woithe#if defined(CONFIG_LEDS_CLASS) || defined(CONFIG_LEDS_CLASS_MODULE) 91672afeeafe54853881a4e53dc78d538e249130ad8Bartlomiej Zolnierkiewicz if (fujitsu_hotkey->logolamp_registered) 91772afeeafe54853881a4e53dc78d538e249130ad8Bartlomiej Zolnierkiewicz led_classdev_unregister(&logolamp_led); 91820b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 91972afeeafe54853881a4e53dc78d538e249130ad8Bartlomiej Zolnierkiewicz if (fujitsu_hotkey->kblamps_registered) 92072afeeafe54853881a4e53dc78d538e249130ad8Bartlomiej Zolnierkiewicz led_classdev_unregister(&kblamps_led); 92172afeeafe54853881a4e53dc78d538e249130ad8Bartlomiej Zolnierkiewicz#endif 92220b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 92372afeeafe54853881a4e53dc78d538e249130ad8Bartlomiej Zolnierkiewicz input_unregister_device(input); 92420b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 92545465487897a1c6d508b14b904dc5777f7ec7e04Stefani Seibold kfifo_free(&fujitsu_hotkey->fifo); 92620b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 92772afeeafe54853881a4e53dc78d538e249130ad8Bartlomiej Zolnierkiewicz fujitsu_hotkey->acpi_handle = NULL; 92872afeeafe54853881a4e53dc78d538e249130ad8Bartlomiej Zolnierkiewicz 92920b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe return 0; 93020b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe} 93120b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 932b4ec0275464756f4fd4108b4a4ca7aff61358ad3Bjorn Helgaasstatic void acpi_fujitsu_hotkey_notify(struct acpi_device *device, u32 event) 93320b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe{ 93420b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe struct input_dev *input; 93520b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe int keycode, keycode_r; 93620b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe unsigned int irb = 1; 93720b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe int i, status; 93820b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 93920b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe input = fujitsu_hotkey->input; 94020b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 9414898c2b2f04051e19f4230683c0f0b15f71af887Tony Vroon if (fujitsu_hotkey->rfkill_supported) 9424898c2b2f04051e19f4230683c0f0b15f71af887Tony Vroon fujitsu_hotkey->rfkill_state = 9434898c2b2f04051e19f4230683c0f0b15f71af887Tony Vroon call_fext_func(FUNC_RFKILL, 0x4, 0x0, 0x0); 94420b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 94520b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe switch (event) { 94620b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe case ACPI_FUJITSU_NOTIFY_CODE1: 94720b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe i = 0; 9483a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon while ((irb = 9493a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon call_fext_func(FUNC_BUTTONS, 0x1, 0x0, 0x0)) != 0 9503a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon && (i++) < MAX_HOTKEY_RINGBUFFER_SIZE) { 95120b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe switch (irb & 0x4ff) { 9520e6a66e9cf231140d2e49064d48162728edb7746Jonathan Woithe case KEY1_CODE: 9530e6a66e9cf231140d2e49064d48162728edb7746Jonathan Woithe keycode = fujitsu->keycode1; 95420b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe break; 9550e6a66e9cf231140d2e49064d48162728edb7746Jonathan Woithe case KEY2_CODE: 9560e6a66e9cf231140d2e49064d48162728edb7746Jonathan Woithe keycode = fujitsu->keycode2; 95720b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe break; 9580e6a66e9cf231140d2e49064d48162728edb7746Jonathan Woithe case KEY3_CODE: 9590e6a66e9cf231140d2e49064d48162728edb7746Jonathan Woithe keycode = fujitsu->keycode3; 96020b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe break; 9610e6a66e9cf231140d2e49064d48162728edb7746Jonathan Woithe case KEY4_CODE: 9620e6a66e9cf231140d2e49064d48162728edb7746Jonathan Woithe keycode = fujitsu->keycode4; 96320b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe break; 96420b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe case 0: 96520b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe keycode = 0; 96620b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe break; 96720b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe default: 96820b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe vdbg_printk(FUJLAPTOP_DBG_WARN, 9690e6a66e9cf231140d2e49064d48162728edb7746Jonathan Woithe "Unknown GIRB result [%x]\n", irb); 97020b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe keycode = -1; 97120b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe break; 97220b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe } 97320b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe if (keycode > 0) { 97420b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe vdbg_printk(FUJLAPTOP_DBG_TRACE, 97520b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe "Push keycode into ringbuffer [%d]\n", 97620b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe keycode); 9777acd72eb85f1c7a15e8b5eb554994949241737f1Stefani Seibold status = kfifo_in_locked(&fujitsu_hotkey->fifo, 9780e6a66e9cf231140d2e49064d48162728edb7746Jonathan Woithe (unsigned char *)&keycode, 979c1e13f25674ed564948ecb7dfe5f83e578892896Stefani Seibold sizeof(keycode), 980c1e13f25674ed564948ecb7dfe5f83e578892896Stefani Seibold &fujitsu_hotkey->fifo_lock); 98120b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe if (status != sizeof(keycode)) { 98220b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe vdbg_printk(FUJLAPTOP_DBG_WARN, 9830e6a66e9cf231140d2e49064d48162728edb7746Jonathan Woithe "Could not push keycode [0x%x]\n", 9840e6a66e9cf231140d2e49064d48162728edb7746Jonathan Woithe keycode); 98520b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe } else { 98620b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe input_report_key(input, keycode, 1); 98720b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe input_sync(input); 98820b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe } 98920b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe } else if (keycode == 0) { 99020b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe while ((status = 9917acd72eb85f1c7a15e8b5eb554994949241737f1Stefani Seibold kfifo_out_locked( 992c1e13f25674ed564948ecb7dfe5f83e578892896Stefani Seibold &fujitsu_hotkey->fifo, 993c1e13f25674ed564948ecb7dfe5f83e578892896Stefani Seibold (unsigned char *) &keycode_r, 994c1e13f25674ed564948ecb7dfe5f83e578892896Stefani Seibold sizeof(keycode_r), 995c1e13f25674ed564948ecb7dfe5f83e578892896Stefani Seibold &fujitsu_hotkey->fifo_lock)) 996c1e13f25674ed564948ecb7dfe5f83e578892896Stefani Seibold == sizeof(keycode_r)) { 99720b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe input_report_key(input, keycode_r, 0); 99820b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe input_sync(input); 99920b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe vdbg_printk(FUJLAPTOP_DBG_TRACE, 10000e6a66e9cf231140d2e49064d48162728edb7746Jonathan Woithe "Pop keycode from ringbuffer [%d]\n", 10010e6a66e9cf231140d2e49064d48162728edb7746Jonathan Woithe keycode_r); 100220b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe } 100320b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe } 100420b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe } 100520b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 100620b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe break; 100720b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe default: 100820b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe keycode = KEY_UNKNOWN; 100920b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe vdbg_printk(FUJLAPTOP_DBG_WARN, 101020b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe "Unsupported event [0x%x]\n", event); 101120b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe input_report_key(input, keycode, 1); 101220b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe input_sync(input); 101320b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe input_report_key(input, keycode, 0); 101420b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe input_sync(input); 101520b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe break; 101620b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe } 101720b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe} 101820b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 101920b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe/* Initialization */ 102020b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 1021d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithestatic const struct acpi_device_id fujitsu_device_ids[] = { 1022d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe {ACPI_FUJITSU_HID, 0}, 1023d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe {"", 0}, 1024d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe}; 1025d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe 1026d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithestatic struct acpi_driver acpi_fujitsu_driver = { 1027d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe .name = ACPI_FUJITSU_DRIVER_NAME, 1028d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe .class = ACPI_FUJITSU_CLASS, 1029d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe .ids = fujitsu_device_ids, 1030d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe .ops = { 1031d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe .add = acpi_fujitsu_add, 1032d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe .remove = acpi_fujitsu_remove, 1033700b6721cd1b891b67c2dcee046be12154a21fd6Bjorn Helgaas .notify = acpi_fujitsu_notify, 1034d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe }, 1035d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe}; 1036d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe 103720b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithestatic const struct acpi_device_id fujitsu_hotkey_device_ids[] = { 103820b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe {ACPI_FUJITSU_HOTKEY_HID, 0}, 103920b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe {"", 0}, 104020b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe}; 104120b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 104220b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithestatic struct acpi_driver acpi_fujitsu_hotkey_driver = { 104320b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe .name = ACPI_FUJITSU_HOTKEY_DRIVER_NAME, 104420b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe .class = ACPI_FUJITSU_CLASS, 104520b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe .ids = fujitsu_hotkey_device_ids, 104620b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe .ops = { 104720b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe .add = acpi_fujitsu_hotkey_add, 104820b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe .remove = acpi_fujitsu_hotkey_remove, 1049b4ec0275464756f4fd4108b4a4ca7aff61358ad3Bjorn Helgaas .notify = acpi_fujitsu_hotkey_notify, 105020b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe }, 105120b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe}; 1052d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe 10534990141496b82f91cb96b37100ac882ea5cee8b7Zhang Ruistatic const struct acpi_device_id fujitsu_ids[] __used = { 10544990141496b82f91cb96b37100ac882ea5cee8b7Zhang Rui {ACPI_FUJITSU_HID, 0}, 10554990141496b82f91cb96b37100ac882ea5cee8b7Zhang Rui {ACPI_FUJITSU_HOTKEY_HID, 0}, 10564990141496b82f91cb96b37100ac882ea5cee8b7Zhang Rui {"", 0} 10574990141496b82f91cb96b37100ac882ea5cee8b7Zhang Rui}; 10584990141496b82f91cb96b37100ac882ea5cee8b7Zhang RuiMODULE_DEVICE_TABLE(acpi, fujitsu_ids); 10594990141496b82f91cb96b37100ac882ea5cee8b7Zhang Rui 1060d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithestatic int __init fujitsu_init(void) 1061d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe{ 106220b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe int ret, result, max_brightness; 1063d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe 1064d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe if (acpi_disabled) 1065d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe return -ENODEV; 1066d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe 10676c75dd0f965b7b3480d0e0e9b8d9747988dfe815Julia Lawall fujitsu = kzalloc(sizeof(struct fujitsu_t), GFP_KERNEL); 1068d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe if (!fujitsu) 1069d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe return -ENOMEM; 10700e6a66e9cf231140d2e49064d48162728edb7746Jonathan Woithe fujitsu->keycode1 = KEY_PROG1; 10710e6a66e9cf231140d2e49064d48162728edb7746Jonathan Woithe fujitsu->keycode2 = KEY_PROG2; 10720e6a66e9cf231140d2e49064d48162728edb7746Jonathan Woithe fujitsu->keycode3 = KEY_PROG3; 10730e6a66e9cf231140d2e49064d48162728edb7746Jonathan Woithe fujitsu->keycode4 = KEY_PROG4; 10740e6a66e9cf231140d2e49064d48162728edb7746Jonathan Woithe dmi_check_system(fujitsu_dmi_table); 1075d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe 1076d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe result = acpi_bus_register_driver(&acpi_fujitsu_driver); 1077d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe if (result < 0) { 1078d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe ret = -ENODEV; 1079d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe goto fail_acpi; 1080d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe } 1081d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe 1082d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe /* Register platform stuff */ 1083d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe 1084d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe fujitsu->pf_device = platform_device_alloc("fujitsu-laptop", -1); 1085d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe if (!fujitsu->pf_device) { 1086d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe ret = -ENOMEM; 1087d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe goto fail_platform_driver; 1088d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe } 1089d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe 1090d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe ret = platform_device_add(fujitsu->pf_device); 1091d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe if (ret) 1092d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe goto fail_platform_device1; 1093d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe 1094d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe ret = 1095d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe sysfs_create_group(&fujitsu->pf_device->dev.kobj, 1096d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe &fujitsupf_attribute_group); 1097d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe if (ret) 1098d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe goto fail_platform_device2; 1099d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe 110020b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe /* Register backlight stuff */ 110120b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 11027d5c89a615c5dae039094a3cf4a56fe6aab81765Thomas Renninger if (!acpi_video_backlight_support()) { 1103a19a6ee6cad2b20292a774c2f56ba8039b0fac9cMatthew Garrett struct backlight_properties props; 1104a19a6ee6cad2b20292a774c2f56ba8039b0fac9cMatthew Garrett 1105a19a6ee6cad2b20292a774c2f56ba8039b0fac9cMatthew Garrett memset(&props, 0, sizeof(struct backlight_properties)); 1106a19a6ee6cad2b20292a774c2f56ba8039b0fac9cMatthew Garrett max_brightness = fujitsu->max_brightness; 1107bb7ca747f8d6243b3943c5b133048652020f4a50Matthew Garrett props.type = BACKLIGHT_PLATFORM; 1108a19a6ee6cad2b20292a774c2f56ba8039b0fac9cMatthew Garrett props.max_brightness = max_brightness - 1; 1109a19a6ee6cad2b20292a774c2f56ba8039b0fac9cMatthew Garrett fujitsu->bl_device = backlight_device_register("fujitsu-laptop", 1110a19a6ee6cad2b20292a774c2f56ba8039b0fac9cMatthew Garrett NULL, NULL, 1111a19a6ee6cad2b20292a774c2f56ba8039b0fac9cMatthew Garrett &fujitsubl_ops, 1112a19a6ee6cad2b20292a774c2f56ba8039b0fac9cMatthew Garrett &props); 111372afeeafe54853881a4e53dc78d538e249130ad8Bartlomiej Zolnierkiewicz if (IS_ERR(fujitsu->bl_device)) { 111472afeeafe54853881a4e53dc78d538e249130ad8Bartlomiej Zolnierkiewicz ret = PTR_ERR(fujitsu->bl_device); 111572afeeafe54853881a4e53dc78d538e249130ad8Bartlomiej Zolnierkiewicz fujitsu->bl_device = NULL; 111672afeeafe54853881a4e53dc78d538e249130ad8Bartlomiej Zolnierkiewicz goto fail_sysfs_group; 111772afeeafe54853881a4e53dc78d538e249130ad8Bartlomiej Zolnierkiewicz } 11187d5c89a615c5dae039094a3cf4a56fe6aab81765Thomas Renninger fujitsu->bl_device->props.brightness = fujitsu->brightness_level; 11197d5c89a615c5dae039094a3cf4a56fe6aab81765Thomas Renninger } 112020b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 112120b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe ret = platform_driver_register(&fujitsupf_driver); 112220b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe if (ret) 112320b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe goto fail_backlight; 112420b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 112520b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe /* Register hotkey driver */ 112620b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 11276c75dd0f965b7b3480d0e0e9b8d9747988dfe815Julia Lawall fujitsu_hotkey = kzalloc(sizeof(struct fujitsu_hotkey_t), GFP_KERNEL); 112820b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe if (!fujitsu_hotkey) { 112920b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe ret = -ENOMEM; 113020b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe goto fail_hotkey; 113120b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe } 113220b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 113320b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe result = acpi_bus_register_driver(&acpi_fujitsu_hotkey_driver); 113420b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe if (result < 0) { 113520b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe ret = -ENODEV; 113620b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe goto fail_hotkey1; 113720b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe } 113820b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 11393a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon /* Sync backlight power status (needs FUJ02E3 device, hence deferred) */ 11403a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon 11413a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon if (!acpi_video_backlight_support()) { 11423a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon if (call_fext_func(FUNC_BACKLIGHT, 0x2, 0x4, 0x0) == 3) 11433a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon fujitsu->bl_device->props.power = 4; 11443a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon else 11453a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon fujitsu->bl_device->props.power = 0; 11463a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon } 11473a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon 114877bad7c830e20085deba6a760ce85c13ecb12f4dJoe Perches pr_info("driver " FUJITSU_DRIVER_VERSION " successfully loaded\n"); 1149d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe 1150d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe return 0; 1151d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe 115220b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithefail_hotkey1: 115320b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe kfree(fujitsu_hotkey); 115420b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithefail_hotkey: 1155d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe platform_driver_unregister(&fujitsupf_driver); 115620b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithefail_backlight: 11577d5c89a615c5dae039094a3cf4a56fe6aab81765Thomas Renninger if (fujitsu->bl_device) 11587d5c89a615c5dae039094a3cf4a56fe6aab81765Thomas Renninger backlight_device_unregister(fujitsu->bl_device); 115972afeeafe54853881a4e53dc78d538e249130ad8Bartlomiej Zolnierkiewiczfail_sysfs_group: 116072afeeafe54853881a4e53dc78d538e249130ad8Bartlomiej Zolnierkiewicz sysfs_remove_group(&fujitsu->pf_device->dev.kobj, 116172afeeafe54853881a4e53dc78d538e249130ad8Bartlomiej Zolnierkiewicz &fujitsupf_attribute_group); 116220b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithefail_platform_device2: 116320b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe platform_device_del(fujitsu->pf_device); 116420b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithefail_platform_device1: 116520b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe platform_device_put(fujitsu->pf_device); 116620b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithefail_platform_driver: 116720b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe acpi_bus_unregister_driver(&acpi_fujitsu_driver); 116820b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithefail_acpi: 1169d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe kfree(fujitsu); 1170d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe 1171d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe return ret; 1172d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe} 1173d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe 1174d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithestatic void __exit fujitsu_cleanup(void) 1175d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe{ 117672afeeafe54853881a4e53dc78d538e249130ad8Bartlomiej Zolnierkiewicz acpi_bus_unregister_driver(&acpi_fujitsu_hotkey_driver); 11773a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon 117872afeeafe54853881a4e53dc78d538e249130ad8Bartlomiej Zolnierkiewicz kfree(fujitsu_hotkey); 11793a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony Vroon 1180d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe platform_driver_unregister(&fujitsupf_driver); 118172afeeafe54853881a4e53dc78d538e249130ad8Bartlomiej Zolnierkiewicz 11827d5c89a615c5dae039094a3cf4a56fe6aab81765Thomas Renninger if (fujitsu->bl_device) 11837d5c89a615c5dae039094a3cf4a56fe6aab81765Thomas Renninger backlight_device_unregister(fujitsu->bl_device); 1184d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe 118572afeeafe54853881a4e53dc78d538e249130ad8Bartlomiej Zolnierkiewicz sysfs_remove_group(&fujitsu->pf_device->dev.kobj, 118672afeeafe54853881a4e53dc78d538e249130ad8Bartlomiej Zolnierkiewicz &fujitsupf_attribute_group); 1187d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe 118872afeeafe54853881a4e53dc78d538e249130ad8Bartlomiej Zolnierkiewicz platform_device_unregister(fujitsu->pf_device); 1189d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe 119072afeeafe54853881a4e53dc78d538e249130ad8Bartlomiej Zolnierkiewicz acpi_bus_unregister_driver(&acpi_fujitsu_driver); 119120b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 119272afeeafe54853881a4e53dc78d538e249130ad8Bartlomiej Zolnierkiewicz kfree(fujitsu); 119320b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 119477bad7c830e20085deba6a760ce85c13ecb12f4dJoe Perches pr_info("driver unloaded\n"); 1195d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe} 1196d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe 1197d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithemodule_init(fujitsu_init); 1198d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithemodule_exit(fujitsu_cleanup); 1199d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan Woithe 120020b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithemodule_param(use_alt_lcd_levels, uint, 0644); 120120b937343e55c16e37b1a4ad2176760b4a11002cJonathan WoitheMODULE_PARM_DESC(use_alt_lcd_levels, 120220b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe "Use alternative interface for lcd_levels (needed for Lifebook s6410)."); 120320b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithemodule_param(disable_brightness_adjust, uint, 0644); 120420b937343e55c16e37b1a4ad2176760b4a11002cJonathan WoitheMODULE_PARM_DESC(disable_brightness_adjust, "Disable brightness adjustment ."); 120520b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe#ifdef CONFIG_FUJITSU_LAPTOP_DEBUG 120620b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithemodule_param_named(debug, dbg_level, uint, 0644); 120720b937343e55c16e37b1a4ad2176760b4a11002cJonathan WoitheMODULE_PARM_DESC(debug, "Sets debug level bit-mask"); 120820b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe#endif 120920b937343e55c16e37b1a4ad2176760b4a11002cJonathan Woithe 12103a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony VroonMODULE_AUTHOR("Jonathan Woithe, Peter Gruber, Tony Vroon"); 1211d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan WoitheMODULE_DESCRIPTION("Fujitsu laptop extras support"); 1212d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan WoitheMODULE_VERSION(FUJITSU_DRIVER_VERSION); 1213d0482533c73a8685f7ce0951a10280cfd58b8825Jonathan WoitheMODULE_LICENSE("GPL"); 1214a361a82c10c20eff402d72ce83b66913d04894eeDan Williams 12150e6a66e9cf231140d2e49064d48162728edb7746Jonathan WoitheMODULE_ALIAS("dmi:*:svnFUJITSUSIEMENS:*:pvr:rvnFUJITSU:rnFJNB1D3:*:cvrS6410:*"); 12163a407086090bb4fa1908d4dc3739c9ebc8ad6686Tony VroonMODULE_ALIAS("dmi:*:svnFUJITSUSIEMENS:*:pvr:rvnFUJITSU:rnFJNB1E6:*:cvrS6420:*"); 12170e6a66e9cf231140d2e49064d48162728edb7746Jonathan WoitheMODULE_ALIAS("dmi:*:svnFUJITSU:*:pvr:rvnFUJITSU:rnFJNB19C:*:cvrS7020:*"); 1218