Commit 0e6a66e9 authored by Jonathan Woithe's avatar Jonathan Woithe Committed by Len Brown

fujitsu-laptop: better handling of P8010 hotkey

This patch (mostly from Peter Gruber) improves the handling of the hotkeys
for P8010 laptops by passing more accurate input events back to userspace.
This is needed because the P8010 labels these buttons quite differently to
earlier laptops.  As part of this, a P8010-specific DMI callback check has
been implemented.  Finally there's some minor whitespace cleanups from
running the source through Lindent.
Signed-off-by: default avatarPeter Gruber <nokos@gmx.net>
Signed-off-by: default avatarJonathan Woithe <jwoithe@physics.adelaide.edu.au>
Signed-off-by: default avatarLen Brown <len.brown@intel.com>
parent 3fa8749e
...@@ -44,8 +44,9 @@ ...@@ -44,8 +44,9 @@
* Hotkeys present on certain Fujitsu laptops (eg: the S6xxx series) are * Hotkeys present on certain Fujitsu laptops (eg: the S6xxx series) are
* also supported by this driver. * also supported by this driver.
* *
* This driver has been tested on a Fujitsu Lifebook S6410 and S7020. It * This driver has been tested on a Fujitsu Lifebook S6410, S7020 and
* should work on most P-series and S-series Lifebooks, but YMMV. * P8010. It should work on most P-series and S-series Lifebooks, but
* YMMV.
* *
* The module parameter use_alt_lcd_levels switches between different ACPI * The module parameter use_alt_lcd_levels switches between different ACPI
* brightness controls which are used by different Fujitsu laptops. In most * brightness controls which are used by different Fujitsu laptops. In most
...@@ -65,7 +66,7 @@ ...@@ -65,7 +66,7 @@
#include <linux/video_output.h> #include <linux/video_output.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#define FUJITSU_DRIVER_VERSION "0.4.2" #define FUJITSU_DRIVER_VERSION "0.4.3"
#define FUJITSU_LCD_N_LEVELS 8 #define FUJITSU_LCD_N_LEVELS 8
...@@ -83,10 +84,10 @@ ...@@ -83,10 +84,10 @@
#define ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS 0x87 #define ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS 0x87
/* Hotkey details */ /* Hotkey details */
#define LOCK_KEY 0x410 /* codes for the keys in the GIRB register */ #define KEY1_CODE 0x410 /* codes for the keys in the GIRB register */
#define DISPLAY_KEY 0x411 /* keys are mapped to KEY_SCREENLOCK (the key with the key symbol) */ #define KEY2_CODE 0x411
#define ENERGY_KEY 0x412 /* KEY_MEDIA (the key with the laptop symbol, KEY_EMAIL (E key)) */ #define KEY3_CODE 0x412
#define REST_KEY 0x413 /* KEY_SUSPEND (R key) */ #define KEY4_CODE 0x413
#define MAX_HOTKEY_RINGBUFFER_SIZE 100 #define MAX_HOTKEY_RINGBUFFER_SIZE 100
#define RINGBUFFERSIZE 40 #define RINGBUFFERSIZE 40
...@@ -123,6 +124,7 @@ struct fujitsu_t { ...@@ -123,6 +124,7 @@ struct fujitsu_t {
char phys[32]; char phys[32];
struct backlight_device *bl_device; struct backlight_device *bl_device;
struct platform_device *pf_device; struct platform_device *pf_device;
int keycode1, keycode2, keycode3, keycode4;
unsigned int max_brightness; unsigned int max_brightness;
unsigned int brightness_changed; unsigned int brightness_changed;
...@@ -430,7 +432,7 @@ static struct platform_driver fujitsupf_driver = { ...@@ -430,7 +432,7 @@ static struct platform_driver fujitsupf_driver = {
} }
}; };
static int dmi_check_cb_s6410(const struct dmi_system_id *id) static void dmi_check_cb_common(const struct dmi_system_id *id)
{ {
acpi_handle handle; acpi_handle handle;
int have_blnf; int have_blnf;
...@@ -452,24 +454,40 @@ static int dmi_check_cb_s6410(const struct dmi_system_id *id) ...@@ -452,24 +454,40 @@ static int dmi_check_cb_s6410(const struct dmi_system_id *id)
"auto-detecting disable_adjust\n"); "auto-detecting disable_adjust\n");
disable_brightness_adjust = have_blnf ? 0 : 1; disable_brightness_adjust = have_blnf ? 0 : 1;
} }
}
static int dmi_check_cb_s6410(const struct dmi_system_id *id)
{
dmi_check_cb_common(id);
fujitsu->keycode1 = KEY_SCREENLOCK; /* "Lock" */
fujitsu->keycode2 = KEY_HELP; /* "Mobility Center" */
return 0;
}
static int dmi_check_cb_p8010(const struct dmi_system_id *id)
{
dmi_check_cb_common(id);
fujitsu->keycode1 = KEY_HELP; /* "Support" */
fujitsu->keycode3 = KEY_SWITCHVIDEOMODE; /* "Presentation" */
fujitsu->keycode4 = KEY_WWW; /* "Internet" */
return 0; return 0;
} }
static struct dmi_system_id __initdata fujitsu_dmi_table[] = { static struct dmi_system_id __initdata fujitsu_dmi_table[] = {
{ {
.ident = "Fujitsu Siemens", .ident = "Fujitsu Siemens S6410",
.matches = { .matches = {
DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK S6410"), DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK S6410"),
}, },
.callback = dmi_check_cb_s6410}, .callback = dmi_check_cb_s6410},
{ {
.ident = "FUJITSU LifeBook P8010", .ident = "Fujitsu LifeBook P8010",
.matches = { .matches = {
DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook P8010"), DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook P8010"),
}, },
.callback = dmi_check_cb_s6410}, .callback = dmi_check_cb_p8010},
{} {}
}; };
...@@ -547,7 +565,6 @@ static int acpi_fujitsu_add(struct acpi_device *device) ...@@ -547,7 +565,6 @@ static int acpi_fujitsu_add(struct acpi_device *device)
} }
/* do config (detect defaults) */ /* do config (detect defaults) */
dmi_check_system(fujitsu_dmi_table);
use_alt_lcd_levels = use_alt_lcd_levels == 1 ? 1 : 0; use_alt_lcd_levels = use_alt_lcd_levels == 1 ? 1 : 0;
disable_brightness_keys = disable_brightness_keys == 1 ? 1 : 0; disable_brightness_keys = disable_brightness_keys == 1 ? 1 : 0;
disable_brightness_adjust = disable_brightness_adjust == 1 ? 1 : 0; disable_brightness_adjust = disable_brightness_adjust == 1 ? 1 : 0;
...@@ -623,17 +640,17 @@ static void acpi_fujitsu_notify(acpi_handle handle, u32 event, void *data) ...@@ -623,17 +640,17 @@ static void acpi_fujitsu_notify(acpi_handle handle, u32 event, void *data)
keycode = 0; keycode = 0;
if (disable_brightness_keys != 1) { if (disable_brightness_keys != 1) {
if (oldb == 0) { if (oldb == 0) {
acpi_bus_generate_proc_event(fujitsu-> acpi_bus_generate_proc_event
dev, (fujitsu->dev,
ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS, ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS,
0); 0);
keycode = KEY_BRIGHTNESSDOWN; keycode = KEY_BRIGHTNESSDOWN;
} else if (oldb == } else if (oldb ==
(fujitsu->max_brightness) - 1) { (fujitsu->max_brightness) - 1) {
acpi_bus_generate_proc_event(fujitsu-> acpi_bus_generate_proc_event
dev, (fujitsu->dev,
ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS, ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS,
0); 0);
keycode = KEY_BRIGHTNESSUP; keycode = KEY_BRIGHTNESSUP;
} }
} }
...@@ -646,8 +663,7 @@ static void acpi_fujitsu_notify(acpi_handle handle, u32 event, void *data) ...@@ -646,8 +663,7 @@ static void acpi_fujitsu_notify(acpi_handle handle, u32 event, void *data)
} }
if (disable_brightness_keys != 1) { if (disable_brightness_keys != 1) {
acpi_bus_generate_proc_event(fujitsu->dev, acpi_bus_generate_proc_event(fujitsu->dev,
ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS, ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS, 0);
0);
keycode = KEY_BRIGHTNESSUP; keycode = KEY_BRIGHTNESSUP;
} }
} else if (oldb > newb) { } else if (oldb > newb) {
...@@ -659,8 +675,7 @@ static void acpi_fujitsu_notify(acpi_handle handle, u32 event, void *data) ...@@ -659,8 +675,7 @@ static void acpi_fujitsu_notify(acpi_handle handle, u32 event, void *data)
} }
if (disable_brightness_keys != 1) { if (disable_brightness_keys != 1) {
acpi_bus_generate_proc_event(fujitsu->dev, acpi_bus_generate_proc_event(fujitsu->dev,
ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS, ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS, 0);
0);
keycode = KEY_BRIGHTNESSDOWN; keycode = KEY_BRIGHTNESSDOWN;
} }
} else { } else {
...@@ -742,10 +757,10 @@ static int acpi_fujitsu_hotkey_add(struct acpi_device *device) ...@@ -742,10 +757,10 @@ static int acpi_fujitsu_hotkey_add(struct acpi_device *device)
input->id.product = 0x06; input->id.product = 0x06;
input->dev.parent = &device->dev; input->dev.parent = &device->dev;
input->evbit[0] = BIT(EV_KEY); input->evbit[0] = BIT(EV_KEY);
set_bit(KEY_SCREENLOCK, input->keybit); set_bit(fujitsu->keycode1, input->keybit);
set_bit(KEY_MEDIA, input->keybit); set_bit(fujitsu->keycode2, input->keybit);
set_bit(KEY_EMAIL, input->keybit); set_bit(fujitsu->keycode3, input->keybit);
set_bit(KEY_SUSPEND, input->keybit); set_bit(fujitsu->keycode4, input->keybit);
set_bit(KEY_UNKNOWN, input->keybit); set_bit(KEY_UNKNOWN, input->keybit);
error = input_register_device(input); error = input_register_device(input);
...@@ -833,24 +848,24 @@ static void acpi_fujitsu_hotkey_notify(acpi_handle handle, u32 event, ...@@ -833,24 +848,24 @@ static void acpi_fujitsu_hotkey_notify(acpi_handle handle, u32 event,
irb); irb);
switch (irb & 0x4ff) { switch (irb & 0x4ff) {
case LOCK_KEY: case KEY1_CODE:
keycode = KEY_SCREENLOCK; keycode = fujitsu->keycode1;
break; break;
case DISPLAY_KEY: case KEY2_CODE:
keycode = KEY_MEDIA; keycode = fujitsu->keycode2;
break; break;
case ENERGY_KEY: case KEY3_CODE:
keycode = KEY_EMAIL; keycode = fujitsu->keycode3;
break; break;
case REST_KEY: case KEY4_CODE:
keycode = KEY_SUSPEND; keycode = fujitsu->keycode4;
break; break;
case 0: case 0:
keycode = 0; keycode = 0;
break; break;
default: default:
vdbg_printk(FUJLAPTOP_DBG_WARN, vdbg_printk(FUJLAPTOP_DBG_WARN,
"Unknown GIRB result [%x]\n", irb); "Unknown GIRB result [%x]\n", irb);
keycode = -1; keycode = -1;
break; break;
} }
...@@ -859,12 +874,12 @@ static void acpi_fujitsu_hotkey_notify(acpi_handle handle, u32 event, ...@@ -859,12 +874,12 @@ static void acpi_fujitsu_hotkey_notify(acpi_handle handle, u32 event,
"Push keycode into ringbuffer [%d]\n", "Push keycode into ringbuffer [%d]\n",
keycode); keycode);
status = kfifo_put(fujitsu_hotkey->fifo, status = kfifo_put(fujitsu_hotkey->fifo,
(unsigned char *)&keycode, (unsigned char *)&keycode,
sizeof(keycode)); sizeof(keycode));
if (status != sizeof(keycode)) { if (status != sizeof(keycode)) {
vdbg_printk(FUJLAPTOP_DBG_WARN, vdbg_printk(FUJLAPTOP_DBG_WARN,
"Could not push keycode [0x%x]\n", "Could not push keycode [0x%x]\n",
keycode); keycode);
} else { } else {
input_report_key(input, keycode, 1); input_report_key(input, keycode, 1);
input_sync(input); input_sync(input);
...@@ -879,8 +894,8 @@ static void acpi_fujitsu_hotkey_notify(acpi_handle handle, u32 event, ...@@ -879,8 +894,8 @@ static void acpi_fujitsu_hotkey_notify(acpi_handle handle, u32 event,
input_report_key(input, keycode_r, 0); input_report_key(input, keycode_r, 0);
input_sync(input); input_sync(input);
vdbg_printk(FUJLAPTOP_DBG_TRACE, vdbg_printk(FUJLAPTOP_DBG_TRACE,
"Pop keycode from ringbuffer [%d]\n", "Pop keycode from ringbuffer [%d]\n",
keycode_r); keycode_r);
} }
} }
} }
...@@ -943,6 +958,11 @@ static int __init fujitsu_init(void) ...@@ -943,6 +958,11 @@ static int __init fujitsu_init(void)
if (!fujitsu) if (!fujitsu)
return -ENOMEM; return -ENOMEM;
memset(fujitsu, 0, sizeof(struct fujitsu_t)); memset(fujitsu, 0, sizeof(struct fujitsu_t));
fujitsu->keycode1 = KEY_PROG1;
fujitsu->keycode2 = KEY_PROG2;
fujitsu->keycode3 = KEY_PROG3;
fujitsu->keycode4 = KEY_PROG4;
dmi_check_system(fujitsu_dmi_table);
result = acpi_bus_register_driver(&acpi_fujitsu_driver); result = acpi_bus_register_driver(&acpi_fujitsu_driver);
if (result < 0) { if (result < 0) {
...@@ -1076,15 +1096,14 @@ MODULE_DESCRIPTION("Fujitsu laptop extras support"); ...@@ -1076,15 +1096,14 @@ MODULE_DESCRIPTION("Fujitsu laptop extras support");
MODULE_VERSION(FUJITSU_DRIVER_VERSION); MODULE_VERSION(FUJITSU_DRIVER_VERSION);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_ALIAS MODULE_ALIAS("dmi:*:svnFUJITSUSIEMENS:*:pvr:rvnFUJITSU:rnFJNB1D3:*:cvrS6410:*");
("dmi:*:svnFUJITSUSIEMENS:*:pvr:rvnFUJITSU:rnFJNB1D3:*:cvrS6410:*"); MODULE_ALIAS("dmi:*:svnFUJITSU:*:pvr:rvnFUJITSU:rnFJNB19C:*:cvrS7020:*");
MODULE_ALIAS
("dmi:*:svnFUJITSU:*:pvr:rvnFUJITSU:rnFJNB19C:*:cvrS7020:*");
static struct pnp_device_id pnp_ids[] = { static struct pnp_device_id pnp_ids[] = {
{ .id = "FUJ02bf" }, {.id = "FUJ02bf"},
{ .id = "FUJ02B1" }, {.id = "FUJ02B1"},
{ .id = "FUJ02E3" }, {.id = "FUJ02E3"},
{ .id = "" } {.id = ""}
}; };
MODULE_DEVICE_TABLE(pnp, pnp_ids); MODULE_DEVICE_TABLE(pnp, pnp_ids);
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment