fujitsu-laptop: docked/lid/radios support
Subsystems (2)
PATCH 1/1 fujitsu-laptop: docked/lid/radios support
The DSDT describes a FUNC interface that exposes currently unused functionality. This patch adds 3 read-only files to the platform device containing docked, lid & radio state.
Please test whether this returns appropriate information on your specific laptop. Also, please enable debugging and supply me with:
- your exact laptop type (such as Lifebook S6420)
- the icons on your 4 application panel buttons
- your BTNI value (such as 0xff0101)
- your LEDI value (such as 0x100)
- your DSDT, available from /sys/firmware/acpi/tables/DSDT
Regards,
Tony V.
P.S. Apologies if you got a duplicate message, the mail didn't seem to have made it out to linux-acpi after 6 hours.
drivers/misc/fujitsu-laptop.c renamed from drivers/misc/fujitsu-laptop.c.orig +109 -25
@@ -3,6 +3,7 @@/* Copyright (C) 2007,2008 Jonathan Woithe <[email protected]> Copyright (C) 2008 Peter Gruber <[email protected]> +Copyright (C) 2008 Tony Vroon <[email protected]> Based on earlier work: Copyright (C) 2003 Shane Spencer <[email protected]> Adrian Yee <[email protected]>
@@ -66,7 +67,7 @@#include <linux/video_output.h> #include <linux/platform_device.h> -#define FUJITSU_DRIVER_VERSION "0.4.3" +#define FUJITSU_DRIVER_VERSION "0.5.0"#define FUJITSU_LCD_N_LEVELS 8
@@ -83,6 +84,12 @@#define ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS 0x86#define ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS 0x87 +/* FUNC interface - command values */ +#define FUNC_RFKILL 0x1000 +#define FUNC_LEDS 0x1001 +#define FUNC_BUTTONS 0x1002 +#define FUNC_BACKLIGHT 0x1004 +/* Hotkey details */ #define KEY1_CODE 0x410/* codes for the keys in the GIRB register */ #define KEY2_CODE 0x411
@@ -145,8 +152,7 @@struct platform_device *pf_device;struct kfifo *fifo;spinlock_t fifo_lock; - -unsigned int irb;/* info about the pressed buttons */ +int rfkill_state; };static struct fujitsu_hotkey_t *fujitsu_hotkey;
@@ -160,6 +166,54 @@static void acpi_fujitsu_notify (acpi_handle handle,u32 event,void *data); +/* Fujitsu ACPI interface function */ + +static int call_fujex_func (int cmd,int arg0,int arg1,int arg2) +{ +acpi_status status =AE_OK ; +union acpi_object params[4 ] = { + { .type =ACPI_TYPE_INTEGER }, + { .type =ACPI_TYPE_INTEGER }, + { .type =ACPI_TYPE_INTEGER }, + { .type =ACPI_TYPE_INTEGER } + }; +struct acpi_object_list arg_list = {4 , ¶ms[0 ] }; +struct acpi_buffer output; +union acpi_object out_obj; +acpi_handle handle =NULL ; + + status =acpi_get_handle (fujitsu_hotkey->acpi_handle,"FUNC" , &handle); +if (ACPI_FAILURE (status)) { +vdbg_printk (FUJLAPTOP_DBG_ERROR ,"FUNC interface is not present\n" ); +return -ENODEV ; + } + + params[0 ].integer.value = cmd; + params[1 ].integer.value = arg0; + params[2 ].integer.value = arg1; + params[3 ].integer.value = arg2; + + output.length =sizeof (out_obj); + output.pointer = &out_obj; + + status =acpi_evaluate_object (handle,NULL , &arg_list, &output); +if (ACPI_FAILURE (status)) { +vdbg_printk (FUJLAPTOP_DBG_WARN ,"FUNC 0x%x (args 0x%x, 0x%x, 0x%x) call failed\n" , + cmd, arg0, arg1, arg2); +return -ENODEV ; + } + +if (out_obj.type !=ACPI_TYPE_INTEGER ) { +vdbg_printk (FUJLAPTOP_DBG_WARN ,"FUNC 0x%x (args 0x%x, 0x%x, 0x%x) did not return an integer\n" , + cmd, arg0, arg1, arg2); +return -ENODEV ; + } + +vdbg_printk (FUJLAPTOP_DBG_TRACE ,"FUNC 0x%x (args 0x%x, 0x%x, 0x%x) returned 0x%x\n" , cmd, arg0, arg1, + arg2, (int )out_obj.integer.value); +return out_obj.integer.value; +} +/* Hardware access for LCD brightness control */ static int set_lcd_level (int level)
@@ -382,42 +436,59 @@return count; } -/* Hardware access for hotkey device */ - -static int get_irb (void ) +static ssize_t +ignore_store (struct device *dev, +struct device_attribute *attr,const char *buf,size_t count) { -unsigned long long state =0 ; -acpi_status status =AE_OK ; +return count; +} -vdbg_printk (FUJLAPTOP_DBG_TRACE ,"Get irb\n" ); - status = -acpi_evaluate_integer (fujitsu_hotkey->acpi_handle,"GIRB" ,NULL , - &state); -if (status <0 ) -return status; - - fujitsu_hotkey->irb = state; +static ssize_t +show_lid_state (struct device *dev, +struct device_attribute *attr,char *buf) +{ +if (fujitsu_hotkey->rfkill_state &0x100 ) +return sprintf (buf,"open\n" ); +else +return sprintf (buf,"closed\n" ); +} -return fujitsu_hotkey->irb; +static ssize_t +show_dock_state (struct device *dev, +struct device_attribute *attr,char *buf) +{ +if (fujitsu_hotkey->rfkill_state &0x200 ) +return sprintf (buf,"docked\n" ); +else +return sprintf (buf,"undocked\n" ); }static ssize_t -ignore_store (struct device *dev, -struct device_attribute *attr,const char *buf,size_t count) +show_radios_state (struct device *dev, +struct device_attribute *attr,char *buf) { -return count; +if (fujitsu_hotkey->rfkill_state &0x20 ) +return sprintf (buf,"on\n" ); +else +return sprintf (buf,"killed\n" ); } static DEVICE_ATTR(max_brightness, 0444, show_max_brightness, ignore_store); static DEVICE_ATTR(brightness_changed, 0444, show_brightness_changed, ignore_store); static DEVICE_ATTR(lcd_level, 0644, show_lcd_level, store_lcd_level); +static DEVICE_ATTR(lid, 0444, show_lid_state, ignore_store); +static DEVICE_ATTR(dock, 0444, show_dock_state, ignore_store); +static DEVICE_ATTR(radios, 0444, show_radios_state, ignore_store);static struct attribute *fujitsupf_attributes[] = { &dev_attr_brightness_changed.attr, &dev_attr_max_brightness.attr, &dev_attr_lcd_level.attr, + &dev_attr_lid.attr, + &dev_attr_dock.attr, + &dev_attr_radios.attr,NULL };
@@ -771,7 +842,8 @@ input->id.bustype =BUS_HOST ; input->id.product =0x06 ; input->dev.parent = &device->dev; - input->evbit[0 ] =BIT (EV_KEY ); + +set_bit (EV_KEY , input->evbit);set_bit (fujitsu->keycode1, input->keybit);set_bit (fujitsu->keycode2, input->keybit);set_bit (fujitsu->keycode3, input->keybit);
@@ -804,9 +876,21 @@ } i =0 ;/* Discard hotkey ringbuffer */ -while (get_irb () !=0 && (i++) <MAX_HOTKEY_RINGBUFFER_SIZE ) ; +while (call_fujex_func (FUNC_BUTTONS ,0x01 ,0x0 ,0x0 ) !=0 && (i++) <MAX_HOTKEY_RINGBUFFER_SIZE ) ;vdbg_printk (FUJLAPTOP_DBG_INFO ,"Discarded %i ringbuffer entries\n" , i); +/* Sync RFKILL state */ + fujitsu_hotkey->rfkill_state = +call_fujex_func (FUNC_RFKILL ,0x04 ,0x0 ,0x0 ); + +/* Suspect this is a keymap of the application panel, print it */ +vdbg_printk (FUJLAPTOP_DBG_INFO ,"BTNI: [0x%x]\n" , +call_fujex_func (FUNC_BUTTONS ,0x0 ,0x0 ,0x0 )); + +/* We will need this for LED control later, print it */ +vdbg_printk (FUJLAPTOP_DBG_INFO ,"LEDI: [0x%x]\n" , +call_fujex_func (FUNC_LEDS ,0x0 ,0x0 ,0x0 )); +return result; end:
@@ -852,12 +936,12 @@ input = fujitsu_hotkey->input; -vdbg_printk (FUJLAPTOP_DBG_TRACE ,"Hotkey event\n" ); + fujitsu_hotkey->rfkill_state =call_fujex_func (FUNC_RFKILL ,0x04 ,0x0 ,0x0 );switch (event) {case ACPI_FUJITSU_NOTIFY_CODE1 : i =0 ; -while ((irb =get_irb ()) !=0 +while ((irb =call_fujex_func (FUNC_BUTTONS ,0x01 ,0x0 ,0x0 )) !=0 && (i++) <MAX_HOTKEY_RINGBUFFER_SIZE ) {vdbg_printk (FUJLAPTOP_DBG_TRACE ,"GIRB result [%x]\n" , irb);
@@ -1108,7 +1192,7 @@MODULE_PARM_DESC (debug,"Sets debug level bit-mask" );#endif -MODULE_AUTHOR ("Jonathan Woithe, Peter Gruber" ); +MODULE_AUTHOR ("Jonathan Woithe, Peter Gruber, Tony Vroon" );MODULE_DESCRIPTION ("Fujitsu laptop extras support" );MODULE_VERSION (FUJITSU_DRIVER_VERSION );MODULE_LICENSE ("GPL" );