On Tue, 2008-12-16 at 10:12 +1030, Jonathan Woithe wrote: > It's probably sensible for me to pick up on the next > version of your patch. There won't be a next version for a while. Please test the attached version that uses simple platform files. Regards, Tony V.
--- linux-2.6/drivers/misc/fujitsu-laptop.c.orig 2008-12-09 15:19:19.000000000 +0000 +++ linux-2.6/drivers/misc/fujitsu-laptop.c 2008-12-13 13:40:44.000000000 +0000 @@ -3,6 +3,7 @@ /* Copyright (C) 2007,2008 Jonathan Woithe <jwoithe@xxxxxxxxxxxxxxxxxxxxxxx> Copyright (C) 2008 Peter Gruber <nokos@xxxxxxx> + Copyright (C) 2008 Tony Vroon <tony@xxxxxxxx> Based on earlier work: Copyright (C) 2003 Shane Spencer <shane@xxxxxxxxxxx> Adrian Yee <brewt-fujitsu@xxxxxxxxx> @@ -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");
Attachment:
signature.asc
Description: This is a digitally signed message part