Loading drivers/platform/x86/Kconfig +1 −0 Original line number Original line Diff line number Diff line Loading @@ -165,6 +165,7 @@ config SONY_LAPTOP depends on ACPI depends on ACPI select BACKLIGHT_CLASS_DEVICE select BACKLIGHT_CLASS_DEVICE depends on INPUT depends on INPUT depends on RFKILL ---help--- ---help--- This mini-driver drives the SNC and SPIC devices present in the ACPI This mini-driver drives the SNC and SPIC devices present in the ACPI BIOS of the Sony Vaio laptops. BIOS of the Sony Vaio laptops. Loading drivers/platform/x86/sony-laptop.c +393 −138 Original line number Original line Diff line number Diff line Loading @@ -2,7 +2,7 @@ * ACPI Sony Notebook Control Driver (SNC and SPIC) * ACPI Sony Notebook Control Driver (SNC and SPIC) * * * Copyright (C) 2004-2005 Stelian Pop <stelian@popies.net> * Copyright (C) 2004-2005 Stelian Pop <stelian@popies.net> * Copyright (C) 2007 Mattia Dongili <malattia@linux.it> * Copyright (C) 2007-2009 Mattia Dongili <malattia@linux.it> * * * Parts of this driver inspired from asus_acpi.c and ibm_acpi.c * Parts of this driver inspired from asus_acpi.c and ibm_acpi.c * which are copyrighted by their respective authors. * which are copyrighted by their respective authors. Loading Loading @@ -46,7 +46,6 @@ #include <linux/module.h> #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/moduleparam.h> #include <linux/init.h> #include <linux/init.h> #include <linux/smp_lock.h> #include <linux/types.h> #include <linux/types.h> #include <linux/backlight.h> #include <linux/backlight.h> #include <linux/platform_device.h> #include <linux/platform_device.h> Loading @@ -64,6 +63,7 @@ #include <asm/uaccess.h> #include <asm/uaccess.h> #include <linux/sonypi.h> #include <linux/sonypi.h> #include <linux/sony-laptop.h> #include <linux/sony-laptop.h> #include <linux/rfkill.h> #ifdef CONFIG_SONYPI_COMPAT #ifdef CONFIG_SONYPI_COMPAT #include <linux/poll.h> #include <linux/poll.h> #include <linux/miscdevice.h> #include <linux/miscdevice.h> Loading Loading @@ -123,6 +123,18 @@ MODULE_PARM_DESC(minor, "default is -1 (automatic)"); "default is -1 (automatic)"); #endif #endif enum sony_nc_rfkill { SONY_WIFI, SONY_BLUETOOTH, SONY_WWAN, SONY_WIMAX, SONY_RFKILL_MAX, }; static struct rfkill *sony_rfkill_devices[SONY_RFKILL_MAX]; static int sony_rfkill_address[SONY_RFKILL_MAX] = {0x300, 0x500, 0x700, 0x900}; static void sony_nc_rfkill_update(void); /*********** Input Devices ***********/ /*********** Input Devices ***********/ #define SONY_LAPTOP_BUF_SIZE 128 #define SONY_LAPTOP_BUF_SIZE 128 Loading @@ -134,6 +146,7 @@ struct sony_laptop_input_s { spinlock_t fifo_lock; spinlock_t fifo_lock; struct workqueue_struct *wq; struct workqueue_struct *wq; }; }; static struct sony_laptop_input_s sony_laptop_input = { static struct sony_laptop_input_s sony_laptop_input = { .users = ATOMIC_INIT(0), .users = ATOMIC_INIT(0), }; }; Loading Loading @@ -211,6 +224,14 @@ static int sony_laptop_input_index[] = { 48, /* 61 SONYPI_EVENT_WIRELESS_OFF */ 48, /* 61 SONYPI_EVENT_WIRELESS_OFF */ 49, /* 62 SONYPI_EVENT_ZOOM_IN_PRESSED */ 49, /* 62 SONYPI_EVENT_ZOOM_IN_PRESSED */ 50, /* 63 SONYPI_EVENT_ZOOM_OUT_PRESSED */ 50, /* 63 SONYPI_EVENT_ZOOM_OUT_PRESSED */ 51, /* 64 SONYPI_EVENT_CD_EJECT_PRESSED */ 52, /* 65 SONYPI_EVENT_MODEKEY_PRESSED */ 53, /* 66 SONYPI_EVENT_PKEY_P4 */ 54, /* 67 SONYPI_EVENT_PKEY_P5 */ 55, /* 68 SONYPI_EVENT_SETTINGKEY_PRESSED */ 56, /* 69 SONYPI_EVENT_VOLUME_INC_PRESSED */ 57, /* 70 SONYPI_EVENT_VOLUME_DEC_PRESSED */ -1, /* 71 SONYPI_EVENT_BRIGHTNESS_PRESSED */ }; }; static int sony_laptop_input_keycode_map[] = { static int sony_laptop_input_keycode_map[] = { Loading Loading @@ -264,7 +285,14 @@ static int sony_laptop_input_keycode_map[] = { KEY_WLAN, /* 47 SONYPI_EVENT_WIRELESS_ON */ KEY_WLAN, /* 47 SONYPI_EVENT_WIRELESS_ON */ KEY_WLAN, /* 48 SONYPI_EVENT_WIRELESS_OFF */ KEY_WLAN, /* 48 SONYPI_EVENT_WIRELESS_OFF */ KEY_ZOOMIN, /* 49 SONYPI_EVENT_ZOOM_IN_PRESSED */ KEY_ZOOMIN, /* 49 SONYPI_EVENT_ZOOM_IN_PRESSED */ KEY_ZOOMOUT /* 50 SONYPI_EVENT_ZOOM_OUT_PRESSED */ KEY_ZOOMOUT, /* 50 SONYPI_EVENT_ZOOM_OUT_PRESSED */ KEY_EJECTCD, /* 51 SONYPI_EVENT_CD_EJECT_PRESSED */ KEY_F13, /* 52 SONYPI_EVENT_MODEKEY_PRESSED */ KEY_PROG4, /* 53 SONYPI_EVENT_PKEY_P4 */ KEY_F14, /* 54 SONYPI_EVENT_PKEY_P5 */ KEY_F15, /* 55 SONYPI_EVENT_SETTINGKEY_PRESSED */ KEY_VOLUMEUP, /* 56 SONYPI_EVENT_VOLUME_INC_PRESSED */ KEY_VOLUMEDOWN, /* 57 SONYPI_EVENT_VOLUME_DEC_PRESSED */ }; }; /* release buttons after a short delay if pressed */ /* release buttons after a short delay if pressed */ Loading Loading @@ -369,7 +397,7 @@ static int sony_laptop_setup_input(struct acpi_device *acpi_device) sony_laptop_input.wq = create_singlethread_workqueue("sony-laptop"); sony_laptop_input.wq = create_singlethread_workqueue("sony-laptop"); if (!sony_laptop_input.wq) { if (!sony_laptop_input.wq) { printk(KERN_ERR DRV_PFX printk(KERN_ERR DRV_PFX "Unabe to create workqueue.\n"); "Unable to create workqueue.\n"); error = -ENXIO; error = -ENXIO; goto err_free_kfifo; goto err_free_kfifo; } } Loading Loading @@ -689,6 +717,31 @@ static int acpi_callsetfunc(acpi_handle handle, char *name, int value, return -1; return -1; } } static int sony_find_snc_handle(int handle) { int i; int result; for (i = 0x20; i < 0x30; i++) { acpi_callsetfunc(sony_nc_acpi_handle, "SN00", i, &result); if (result == handle) return i-0x20; } return -1; } static int sony_call_snc_handle(int handle, int argument, int *result) { int offset = sony_find_snc_handle(handle); if (offset < 0) return -1; return acpi_callsetfunc(sony_nc_acpi_handle, "SN07", offset | argument, result); } /* /* * sony_nc_values input/output validate functions * sony_nc_values input/output validate functions */ */ Loading Loading @@ -809,87 +862,53 @@ struct sony_nc_event { u8 event; u8 event; }; }; static struct sony_nc_event *sony_nc_events; static struct sony_nc_event sony_100_events[] = { { 0x90, SONYPI_EVENT_PKEY_P1 }, /* Vaio C* --maybe also FE*, N* and AR* ?-- special init sequence { 0x10, SONYPI_EVENT_ANYBUTTON_RELEASED }, * for Fn keys { 0x91, SONYPI_EVENT_PKEY_P2 }, */ { 0x11, SONYPI_EVENT_ANYBUTTON_RELEASED }, static int sony_nc_C_enable(const struct dmi_system_id *id) { int result = 0; printk(KERN_NOTICE DRV_PFX "detected %s\n", id->ident); sony_nc_events = id->driver_data; if (acpi_callsetfunc(sony_nc_acpi_handle, "SN02", 0x4, &result) < 0 || acpi_callsetfunc(sony_nc_acpi_handle, "SN07", 0x2, &result) < 0 || acpi_callsetfunc(sony_nc_acpi_handle, "SN02", 0x10, &result) < 0 || acpi_callsetfunc(sony_nc_acpi_handle, "SN07", 0x0, &result) < 0 || acpi_callsetfunc(sony_nc_acpi_handle, "SN03", 0x2, &result) < 0 || acpi_callsetfunc(sony_nc_acpi_handle, "SN07", 0x101, &result) < 0) { printk(KERN_WARNING DRV_PFX "failed to initialize SNC, some " "functionalities may be missing\n"); return 1; } return 0; } static struct sony_nc_event sony_C_events[] = { { 0x81, SONYPI_EVENT_FNKEY_F1 }, { 0x81, SONYPI_EVENT_FNKEY_F1 }, { 0x01, SONYPI_EVENT_FNKEY_RELEASED }, { 0x01, SONYPI_EVENT_FNKEY_RELEASED }, { 0x82, SONYPI_EVENT_FNKEY_F2 }, { 0x02, SONYPI_EVENT_FNKEY_RELEASED }, { 0x83, SONYPI_EVENT_FNKEY_F3 }, { 0x03, SONYPI_EVENT_FNKEY_RELEASED }, { 0x84, SONYPI_EVENT_FNKEY_F4 }, { 0x04, SONYPI_EVENT_FNKEY_RELEASED }, { 0x85, SONYPI_EVENT_FNKEY_F5 }, { 0x85, SONYPI_EVENT_FNKEY_F5 }, { 0x05, SONYPI_EVENT_FNKEY_RELEASED }, { 0x05, SONYPI_EVENT_FNKEY_RELEASED }, { 0x86, SONYPI_EVENT_FNKEY_F6 }, { 0x86, SONYPI_EVENT_FNKEY_F6 }, { 0x06, SONYPI_EVENT_FNKEY_RELEASED }, { 0x06, SONYPI_EVENT_FNKEY_RELEASED }, { 0x87, SONYPI_EVENT_FNKEY_F7 }, { 0x87, SONYPI_EVENT_FNKEY_F7 }, { 0x07, SONYPI_EVENT_FNKEY_RELEASED }, { 0x07, SONYPI_EVENT_FNKEY_RELEASED }, { 0x89, SONYPI_EVENT_FNKEY_F9 }, { 0x09, SONYPI_EVENT_FNKEY_RELEASED }, { 0x8A, SONYPI_EVENT_FNKEY_F10 }, { 0x8A, SONYPI_EVENT_FNKEY_F10 }, { 0x0A, SONYPI_EVENT_FNKEY_RELEASED }, { 0x0A, SONYPI_EVENT_FNKEY_RELEASED }, { 0x8C, SONYPI_EVENT_FNKEY_F12 }, { 0x8C, SONYPI_EVENT_FNKEY_F12 }, { 0x0C, SONYPI_EVENT_FNKEY_RELEASED }, { 0x0C, SONYPI_EVENT_FNKEY_RELEASED }, { 0x9f, SONYPI_EVENT_CD_EJECT_PRESSED }, { 0x1f, SONYPI_EVENT_ANYBUTTON_RELEASED }, { 0, 0 }, { 0, 0 }, }; }; /* SNC-only model map */ static struct sony_nc_event sony_127_events[] = { static const struct dmi_system_id sony_nc_ids[] = { { 0x81, SONYPI_EVENT_MODEKEY_PRESSED }, { { 0x01, SONYPI_EVENT_ANYBUTTON_RELEASED }, .ident = "Sony Vaio FE Series", { 0x82, SONYPI_EVENT_PKEY_P1 }, .callback = sony_nc_C_enable, { 0x02, SONYPI_EVENT_ANYBUTTON_RELEASED }, .driver_data = sony_C_events, { 0x83, SONYPI_EVENT_PKEY_P2 }, .matches = { { 0x03, SONYPI_EVENT_ANYBUTTON_RELEASED }, DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), { 0x84, SONYPI_EVENT_PKEY_P3 }, DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FE"), { 0x04, SONYPI_EVENT_ANYBUTTON_RELEASED }, }, { 0x85, SONYPI_EVENT_PKEY_P4 }, }, { 0x05, SONYPI_EVENT_ANYBUTTON_RELEASED }, { { 0x86, SONYPI_EVENT_PKEY_P5 }, .ident = "Sony Vaio FZ Series", { 0x06, SONYPI_EVENT_ANYBUTTON_RELEASED }, .callback = sony_nc_C_enable, { 0x06, SONYPI_EVENT_ANYBUTTON_RELEASED }, .driver_data = sony_C_events, { 0x87, SONYPI_EVENT_SETTINGKEY_PRESSED }, .matches = { { 0x07, SONYPI_EVENT_ANYBUTTON_RELEASED }, DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), { 0, 0 }, DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FZ"), }, }, { .ident = "Sony Vaio C Series", .callback = sony_nc_C_enable, .driver_data = sony_C_events, .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), DMI_MATCH(DMI_PRODUCT_NAME, "VGN-C"), }, }, { .ident = "Sony Vaio N Series", .callback = sony_nc_C_enable, .driver_data = sony_C_events, .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), DMI_MATCH(DMI_PRODUCT_NAME, "VGN-N"), }, }, { } }; }; /* /* Loading @@ -897,38 +916,59 @@ static const struct dmi_system_id sony_nc_ids[] = { */ */ static void sony_acpi_notify(acpi_handle handle, u32 event, void *data) static void sony_acpi_notify(acpi_handle handle, u32 event, void *data) { { struct sony_nc_event *evmap; u32 ev = event; u32 ev = event; if (ev >= 0x90) { /* New-style event */ int result; int result; int key_handle = 0; ev -= 0x90; if (sony_find_snc_handle(0x100) == ev) key_handle = 0x100; if (sony_find_snc_handle(0x127) == ev) key_handle = 0x127; if (key_handle) { struct sony_nc_event *key_event; if (sony_call_snc_handle(key_handle, 0x200, &result)) { dprintk("sony_acpi_notify, unable to decode" " event 0x%.2x 0x%.2x\n", key_handle, ev); /* restore the original event */ ev = event; } else { ev = result & 0xFF; if (ev == 0x92) { if (key_handle == 0x100) /* read the key pressed from EC.GECR key_event = sony_100_events; * A call to SN07 with 0x0202 will do it as well respecting * the current protocol on different OSes * * Note: the path for GECR may be * \_SB.PCI0.LPCB.EC (C, FE, AR, N and friends) * \_SB.PCI0.PIB.EC0 (VGN-FR notifications are sent directly, no GECR) * * TODO: we may want to do the same for the older GHKE -need * dmi list- so this snippet may become one more callback. */ if (acpi_callsetfunc(handle, "SN07", 0x0202, &result) < 0) dprintk("sony_acpi_notify, unable to decode event 0x%.2x\n", ev); else else ev = result & 0xFF; key_event = sony_127_events; } if (sony_nc_events) for (; key_event->data; key_event++) { for (evmap = sony_nc_events; evmap->event; evmap++) { if (key_event->data == ev) { if (evmap->data == ev) { ev = key_event->event; ev = evmap->event; break; break; } } } } dprintk("sony_acpi_notify, event: 0x%.2x\n", ev); if (!key_event->data) printk(KERN_INFO DRV_PFX "Unknown event: 0x%x 0x%x\n", key_handle, ev); else sony_laptop_report_input_event(ev); } } else if (sony_find_snc_handle(0x124) == ev) { sony_nc_rfkill_update(); return; } } else sony_laptop_report_input_event(ev); sony_laptop_report_input_event(ev); dprintk("sony_acpi_notify, event: 0x%.2x\n", ev); acpi_bus_generate_proc_event(sony_nc_acpi_device, 1, ev); acpi_bus_generate_proc_event(sony_nc_acpi_device, 1, ev); } } Loading @@ -953,9 +993,25 @@ static acpi_status sony_walk_callback(acpi_handle handle, u32 level, /* /* * ACPI device * ACPI device */ */ static int sony_nc_function_setup(struct acpi_device *device) { int result; /* Enable all events */ acpi_callsetfunc(sony_nc_acpi_handle, "SN02", 0xffff, &result); /* Setup hotkeys */ sony_call_snc_handle(0x0100, 0, &result); sony_call_snc_handle(0x0101, 0, &result); sony_call_snc_handle(0x0102, 0x100, &result); return 0; } static int sony_nc_resume(struct acpi_device *device) static int sony_nc_resume(struct acpi_device *device) { { struct sony_nc_value *item; struct sony_nc_value *item; acpi_handle handle; for (item = sony_nc_values; item->name; item++) { for (item = sony_nc_values; item->name; item++) { int ret; int ret; Loading @@ -970,13 +1026,188 @@ static int sony_nc_resume(struct acpi_device *device) } } } } if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "ECON", &handle))) { if (acpi_callsetfunc(sony_nc_acpi_handle, "ECON", 1, NULL)) dprintk("ECON Method failed\n"); } if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "SN00", &handle))) { dprintk("Doing SNC setup\n"); sony_nc_function_setup(device); } /* set the last requested brightness level */ /* set the last requested brightness level */ if (sony_backlight_device && if (sony_backlight_device && !sony_backlight_update_status(sony_backlight_device)) !sony_backlight_update_status(sony_backlight_device)) printk(KERN_WARNING DRV_PFX "unable to restore brightness level\n"); printk(KERN_WARNING DRV_PFX "unable to restore brightness level\n"); /* re-initialize models with specific requirements */ return 0; dmi_check_system(sony_nc_ids); } static void sony_nc_rfkill_cleanup(void) { int i; for (i = 0; i < SONY_RFKILL_MAX; i++) { if (sony_rfkill_devices[i]) rfkill_unregister(sony_rfkill_devices[i]); } } static int sony_nc_rfkill_get(void *data, enum rfkill_state *state) { int result; int argument = sony_rfkill_address[(long) data]; sony_call_snc_handle(0x124, 0x200, &result); if (result & 0x1) { sony_call_snc_handle(0x124, argument, &result); if (result & 0xf) *state = RFKILL_STATE_UNBLOCKED; else *state = RFKILL_STATE_SOFT_BLOCKED; } else { *state = RFKILL_STATE_HARD_BLOCKED; } return 0; } static int sony_nc_rfkill_set(void *data, enum rfkill_state state) { int result; int argument = sony_rfkill_address[(long) data] + 0x100; if (state == RFKILL_STATE_UNBLOCKED) argument |= 0xff0000; return sony_call_snc_handle(0x124, argument, &result); } static int sony_nc_setup_wifi_rfkill(struct acpi_device *device) { int err = 0; struct rfkill *sony_wifi_rfkill; sony_wifi_rfkill = rfkill_allocate(&device->dev, RFKILL_TYPE_WLAN); if (!sony_wifi_rfkill) return -1; sony_wifi_rfkill->name = "sony-wifi"; sony_wifi_rfkill->toggle_radio = sony_nc_rfkill_set; sony_wifi_rfkill->get_state = sony_nc_rfkill_get; sony_wifi_rfkill->user_claim_unsupported = 1; sony_wifi_rfkill->data = (void *)SONY_WIFI; err = rfkill_register(sony_wifi_rfkill); if (err) rfkill_free(sony_wifi_rfkill); else sony_rfkill_devices[SONY_WIFI] = sony_wifi_rfkill; return err; } static int sony_nc_setup_bluetooth_rfkill(struct acpi_device *device) { int err = 0; struct rfkill *sony_bluetooth_rfkill; sony_bluetooth_rfkill = rfkill_allocate(&device->dev, RFKILL_TYPE_BLUETOOTH); if (!sony_bluetooth_rfkill) return -1; sony_bluetooth_rfkill->name = "sony-bluetooth"; sony_bluetooth_rfkill->toggle_radio = sony_nc_rfkill_set; sony_bluetooth_rfkill->get_state = sony_nc_rfkill_get; sony_bluetooth_rfkill->user_claim_unsupported = 1; sony_bluetooth_rfkill->data = (void *)SONY_BLUETOOTH; err = rfkill_register(sony_bluetooth_rfkill); if (err) rfkill_free(sony_bluetooth_rfkill); else sony_rfkill_devices[SONY_BLUETOOTH] = sony_bluetooth_rfkill; return err; } static int sony_nc_setup_wwan_rfkill(struct acpi_device *device) { int err = 0; struct rfkill *sony_wwan_rfkill; sony_wwan_rfkill = rfkill_allocate(&device->dev, RFKILL_TYPE_WWAN); if (!sony_wwan_rfkill) return -1; sony_wwan_rfkill->name = "sony-wwan"; sony_wwan_rfkill->toggle_radio = sony_nc_rfkill_set; sony_wwan_rfkill->get_state = sony_nc_rfkill_get; sony_wwan_rfkill->user_claim_unsupported = 1; sony_wwan_rfkill->data = (void *)SONY_WWAN; err = rfkill_register(sony_wwan_rfkill); if (err) rfkill_free(sony_wwan_rfkill); else sony_rfkill_devices[SONY_WWAN] = sony_wwan_rfkill; return err; } static int sony_nc_setup_wimax_rfkill(struct acpi_device *device) { int err = 0; struct rfkill *sony_wimax_rfkill; sony_wimax_rfkill = rfkill_allocate(&device->dev, RFKILL_TYPE_WIMAX); if (!sony_wimax_rfkill) return -1; sony_wimax_rfkill->name = "sony-wimax"; sony_wimax_rfkill->toggle_radio = sony_nc_rfkill_set; sony_wimax_rfkill->get_state = sony_nc_rfkill_get; sony_wimax_rfkill->user_claim_unsupported = 1; sony_wimax_rfkill->data = (void *)SONY_WIMAX; err = rfkill_register(sony_wimax_rfkill); if (err) rfkill_free(sony_wimax_rfkill); else sony_rfkill_devices[SONY_WIMAX] = sony_wimax_rfkill; return err; } static void sony_nc_rfkill_update() { int i; enum rfkill_state state; for (i = 0; i < SONY_RFKILL_MAX; i++) { if (sony_rfkill_devices[i]) { sony_rfkill_devices[i]-> get_state(sony_rfkill_devices[i]->data, &state); rfkill_force_state(sony_rfkill_devices[i], state); } } } static int sony_nc_rfkill_setup(struct acpi_device *device) { int result, ret; if (sony_find_snc_handle(0x124) == -1) return -1; ret = sony_call_snc_handle(0x124, 0xb00, &result); if (ret) { printk(KERN_INFO DRV_PFX "Unable to enumerate rfkill devices: %x\n", ret); return ret; } if (result & 0x1) sony_nc_setup_wifi_rfkill(device); if (result & 0x2) sony_nc_setup_bluetooth_rfkill(device); if (result & 0x1c) sony_nc_setup_wwan_rfkill(device); if (result & 0x20) sony_nc_setup_wimax_rfkill(device); return 0; return 0; } } Loading Loading @@ -1024,11 +1255,24 @@ static int sony_nc_add(struct acpi_device *device) dprintk("_INI Method failed\n"); dprintk("_INI Method failed\n"); } } if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "ECON", &handle))) { if (acpi_callsetfunc(sony_nc_acpi_handle, "ECON", 1, NULL)) dprintk("ECON Method failed\n"); } if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "SN00", &handle))) { dprintk("Doing SNC setup\n"); sony_nc_function_setup(device); sony_nc_rfkill_setup(device); } /* setup input devices and helper fifo */ /* setup input devices and helper fifo */ result = sony_laptop_setup_input(device); result = sony_laptop_setup_input(device); if (result) { if (result) { printk(KERN_ERR DRV_PFX printk(KERN_ERR DRV_PFX "Unabe to create input devices.\n"); "Unable to create input devices.\n"); goto outwalk; goto outwalk; } } Loading Loading @@ -1063,9 +1307,6 @@ static int sony_nc_add(struct acpi_device *device) } } /* initialize models with specific requirements */ dmi_check_system(sony_nc_ids); result = sony_pf_add(); result = sony_pf_add(); if (result) if (result) goto outbacklight; goto outbacklight; Loading Loading @@ -1131,6 +1372,7 @@ static int sony_nc_add(struct acpi_device *device) sony_laptop_remove_input(); sony_laptop_remove_input(); outwalk: outwalk: sony_nc_rfkill_cleanup(); return result; return result; } } Loading @@ -1156,6 +1398,7 @@ static int sony_nc_remove(struct acpi_device *device, int type) sony_pf_remove(); sony_pf_remove(); sony_laptop_remove_input(); sony_laptop_remove_input(); sony_nc_rfkill_cleanup(); dprintk(SONY_NC_DRIVER_NAME " removed.\n"); dprintk(SONY_NC_DRIVER_NAME " removed.\n"); return 0; return 0; Loading Loading @@ -1195,7 +1438,6 @@ static struct acpi_driver sony_nc_driver = { #define SONYPI_TYPE1_OFFSET 0x04 #define SONYPI_TYPE1_OFFSET 0x04 #define SONYPI_TYPE2_OFFSET 0x12 #define SONYPI_TYPE2_OFFSET 0x12 #define SONYPI_TYPE3_OFFSET 0x12 #define SONYPI_TYPE3_OFFSET 0x12 #define SONYPI_TYPE4_OFFSET 0x12 struct sony_pic_ioport { struct sony_pic_ioport { struct acpi_resource_io io1; struct acpi_resource_io io1; Loading Loading @@ -1328,6 +1570,7 @@ static struct sonypi_event sonypi_pkeyev[] = { { 0x01, SONYPI_EVENT_PKEY_P1 }, { 0x01, SONYPI_EVENT_PKEY_P1 }, { 0x02, SONYPI_EVENT_PKEY_P2 }, { 0x02, SONYPI_EVENT_PKEY_P2 }, { 0x04, SONYPI_EVENT_PKEY_P3 }, { 0x04, SONYPI_EVENT_PKEY_P3 }, { 0x20, SONYPI_EVENT_PKEY_P1 }, { 0, 0 } { 0, 0 } }; }; Loading Loading @@ -1371,6 +1614,7 @@ static struct sonypi_event sonypi_zoomev[] = { { 0x39, SONYPI_EVENT_ZOOM_PRESSED }, { 0x39, SONYPI_EVENT_ZOOM_PRESSED }, { 0x10, SONYPI_EVENT_ZOOM_IN_PRESSED }, { 0x10, SONYPI_EVENT_ZOOM_IN_PRESSED }, { 0x20, SONYPI_EVENT_ZOOM_OUT_PRESSED }, { 0x20, SONYPI_EVENT_ZOOM_OUT_PRESSED }, { 0x04, SONYPI_EVENT_ZOOM_PRESSED }, { 0, 0 } { 0, 0 } }; }; Loading Loading @@ -1401,6 +1645,19 @@ static struct sonypi_event sonypi_batteryev[] = { { 0, 0 } { 0, 0 } }; }; /* The set of possible volume events */ static struct sonypi_event sonypi_volumeev[] = { { 0x01, SONYPI_EVENT_VOLUME_INC_PRESSED }, { 0x02, SONYPI_EVENT_VOLUME_DEC_PRESSED }, { 0, 0 } }; /* The set of possible brightness events */ static struct sonypi_event sonypi_brightnessev[] = { { 0x80, SONYPI_EVENT_BRIGHTNESS_PRESSED }, { 0, 0 } }; static struct sonypi_eventtypes type1_events[] = { static struct sonypi_eventtypes type1_events[] = { { 0, 0xffffffff, sonypi_releaseev }, { 0, 0xffffffff, sonypi_releaseev }, { 0x70, SONYPI_MEYE_MASK, sonypi_meyeev }, { 0x70, SONYPI_MEYE_MASK, sonypi_meyeev }, Loading Loading @@ -1438,17 +1695,11 @@ static struct sonypi_eventtypes type3_events[] = { { 0x31, SONYPI_MEMORYSTICK_MASK, sonypi_memorystickev }, { 0x31, SONYPI_MEMORYSTICK_MASK, sonypi_memorystickev }, { 0x41, SONYPI_BATTERY_MASK, sonypi_batteryev }, { 0x41, SONYPI_BATTERY_MASK, sonypi_batteryev }, { 0x31, SONYPI_PKEY_MASK, sonypi_pkeyev }, { 0x31, SONYPI_PKEY_MASK, sonypi_pkeyev }, { 0 }, }; static struct sonypi_eventtypes type4_events[] = { { 0, 0xffffffff, sonypi_releaseev }, { 0x21, SONYPI_FNKEY_MASK, sonypi_fnkeyev }, { 0x31, SONYPI_WIRELESS_MASK, sonypi_wlessev }, { 0x31, SONYPI_MEMORYSTICK_MASK, sonypi_memorystickev }, { 0x41, SONYPI_BATTERY_MASK, sonypi_batteryev }, { 0x05, SONYPI_PKEY_MASK, sonypi_pkeyev }, { 0x05, SONYPI_PKEY_MASK, sonypi_pkeyev }, { 0x05, SONYPI_ZOOM_MASK, sonypi_zoomev }, { 0x05, SONYPI_ZOOM_MASK, sonypi_zoomev }, { 0x05, SONYPI_CAPTURE_MASK, sonypi_captureev }, { 0x05, SONYPI_CAPTURE_MASK, sonypi_captureev }, { 0x05, SONYPI_PKEY_MASK, sonypi_volumeev }, { 0x05, SONYPI_PKEY_MASK, sonypi_brightnessev }, { 0 }, { 0 }, }; }; Loading Loading @@ -1511,11 +1762,11 @@ static u8 sony_pic_call3(u8 dev, u8 fn, u8 v) /* /* * minidrivers for SPIC models * minidrivers for SPIC models */ */ static int type4_handle_irq(const u8 data_mask, const u8 ev) static int type3_handle_irq(const u8 data_mask, const u8 ev) { { /* /* * 0x31 could mean we have to take some extra action and wait for * 0x31 could mean we have to take some extra action and wait for * the next irq for some Type4 models, it will generate a new * the next irq for some Type3 models, it will generate a new * irq and we can read new data from the device: * irq and we can read new data from the device: * - 0x5c and 0x5f requires 0xA0 * - 0x5c and 0x5f requires 0xA0 * - 0x61 requires 0xB3 * - 0x61 requires 0xB3 Loading Loading @@ -1545,16 +1796,10 @@ static struct device_ctrl spic_types[] = { }, }, { { .model = SONYPI_DEVICE_TYPE3, .model = SONYPI_DEVICE_TYPE3, .handle_irq = NULL, .handle_irq = type3_handle_irq, .evport_offset = SONYPI_TYPE3_OFFSET, .evport_offset = SONYPI_TYPE3_OFFSET, .event_types = type3_events, .event_types = type3_events, }, }, { .model = SONYPI_DEVICE_TYPE4, .handle_irq = type4_handle_irq, .evport_offset = SONYPI_TYPE4_OFFSET, .event_types = type4_events, }, }; }; static void sony_pic_detect_device_type(struct sony_pic_dev *dev) static void sony_pic_detect_device_type(struct sony_pic_dev *dev) Loading @@ -1578,14 +1823,21 @@ static void sony_pic_detect_device_type(struct sony_pic_dev *dev) pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_1, NULL); PCI_DEVICE_ID_INTEL_ICH7_1, NULL); if (pcidev) { if (pcidev) { dev->control = &spic_types[3]; dev->control = &spic_types[2]; goto out; goto out; } } pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_4, NULL); PCI_DEVICE_ID_INTEL_ICH8_4, NULL); if (pcidev) { if (pcidev) { dev->control = &spic_types[3]; dev->control = &spic_types[2]; goto out; } pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_1, NULL); if (pcidev) { dev->control = &spic_types[2]; goto out; goto out; } } Loading @@ -1598,8 +1850,7 @@ out: printk(KERN_INFO DRV_PFX "detected Type%d model\n", printk(KERN_INFO DRV_PFX "detected Type%d model\n", dev->control->model == SONYPI_DEVICE_TYPE1 ? 1 : dev->control->model == SONYPI_DEVICE_TYPE1 ? 1 : dev->control->model == SONYPI_DEVICE_TYPE2 ? 2 : dev->control->model == SONYPI_DEVICE_TYPE2 ? 2 : 3); dev->control->model == SONYPI_DEVICE_TYPE3 ? 3 : 4); } } /* camera tests and poweron/poweroff */ /* camera tests and poweron/poweroff */ Loading Loading @@ -1754,17 +2005,14 @@ int sony_pic_camera_command(int command, u8 value) EXPORT_SYMBOL(sony_pic_camera_command); EXPORT_SYMBOL(sony_pic_camera_command); /* gprs/edge modem (SZ460N and SZ210P), thanks to Joshua Wise */ /* gprs/edge modem (SZ460N and SZ210P), thanks to Joshua Wise */ static void sony_pic_set_wwanpower(u8 state) static void __sony_pic_set_wwanpower(u8 state) { { state = !!state; state = !!state; mutex_lock(&spic_dev.lock); if (spic_dev.wwan_power == state) if (spic_dev.wwan_power == state) { mutex_unlock(&spic_dev.lock); return; return; } sony_pic_call2(0xB0, state); sony_pic_call2(0xB0, state); sony_pic_call1(0x82); spic_dev.wwan_power = state; spic_dev.wwan_power = state; mutex_unlock(&spic_dev.lock); } } static ssize_t sony_pic_wwanpower_store(struct device *dev, static ssize_t sony_pic_wwanpower_store(struct device *dev, Loading @@ -1776,7 +2024,9 @@ static ssize_t sony_pic_wwanpower_store(struct device *dev, return -EINVAL; return -EINVAL; value = simple_strtoul(buffer, NULL, 10); value = simple_strtoul(buffer, NULL, 10); sony_pic_set_wwanpower(value); mutex_lock(&spic_dev.lock); __sony_pic_set_wwanpower(value); mutex_unlock(&spic_dev.lock); return count; return count; } } Loading Loading @@ -1934,10 +2184,15 @@ static int sonypi_misc_release(struct inode *inode, struct file *file) static int sonypi_misc_open(struct inode *inode, struct file *file) static int sonypi_misc_open(struct inode *inode, struct file *file) { { /* Flush input queue on first open */ /* Flush input queue on first open */ lock_kernel(); unsigned long flags; spin_lock_irqsave(sonypi_compat.fifo->lock, flags); if (atomic_inc_return(&sonypi_compat.open_count) == 1) if (atomic_inc_return(&sonypi_compat.open_count) == 1) kfifo_reset(sonypi_compat.fifo); __kfifo_reset(sonypi_compat.fifo); unlock_kernel(); spin_unlock_irqrestore(sonypi_compat.fifo->lock, flags); return 0; return 0; } } Loading Loading @@ -1990,8 +2245,8 @@ static int ec_read16(u8 addr, u16 *value) return 0; return 0; } } static int sonypi_misc_ioctl(struct inode *ip, struct file *fp, static long sonypi_misc_ioctl(struct file *fp, unsigned int cmd, unsigned int cmd, unsigned long arg) unsigned long arg) { { int ret = 0; int ret = 0; void __user *argp = (void __user *)arg; void __user *argp = (void __user *)arg; Loading Loading @@ -2125,7 +2380,7 @@ static const struct file_operations sonypi_misc_fops = { .open = sonypi_misc_open, .open = sonypi_misc_open, .release = sonypi_misc_release, .release = sonypi_misc_release, .fasync = sonypi_misc_fasync, .fasync = sonypi_misc_fasync, .ioctl = sonypi_misc_ioctl, .unlocked_ioctl = sonypi_misc_ioctl, }; }; static struct miscdevice sonypi_misc_device = { static struct miscdevice sonypi_misc_device = { Loading Loading @@ -2566,7 +2821,7 @@ static int sony_pic_add(struct acpi_device *device) result = sony_pic_possible_resources(device); result = sony_pic_possible_resources(device); if (result) { if (result) { printk(KERN_ERR DRV_PFX printk(KERN_ERR DRV_PFX "Unabe to read possible resources.\n"); "Unable to read possible resources.\n"); goto err_free_resources; goto err_free_resources; } } Loading @@ -2574,7 +2829,7 @@ static int sony_pic_add(struct acpi_device *device) result = sony_laptop_setup_input(device); result = sony_laptop_setup_input(device); if (result) { if (result) { printk(KERN_ERR DRV_PFX printk(KERN_ERR DRV_PFX "Unabe to create input devices.\n"); "Unable to create input devices.\n"); goto err_free_resources; goto err_free_resources; } } Loading include/linux/sonypi.h +8 −0 Original line number Original line Diff line number Diff line Loading @@ -103,6 +103,14 @@ #define SONYPI_EVENT_WIRELESS_OFF 61 #define SONYPI_EVENT_WIRELESS_OFF 61 #define SONYPI_EVENT_ZOOM_IN_PRESSED 62 #define SONYPI_EVENT_ZOOM_IN_PRESSED 62 #define SONYPI_EVENT_ZOOM_OUT_PRESSED 63 #define SONYPI_EVENT_ZOOM_OUT_PRESSED 63 #define SONYPI_EVENT_CD_EJECT_PRESSED 64 #define SONYPI_EVENT_MODEKEY_PRESSED 65 #define SONYPI_EVENT_PKEY_P4 66 #define SONYPI_EVENT_PKEY_P5 67 #define SONYPI_EVENT_SETTINGKEY_PRESSED 68 #define SONYPI_EVENT_VOLUME_INC_PRESSED 69 #define SONYPI_EVENT_VOLUME_DEC_PRESSED 70 #define SONYPI_EVENT_BRIGHTNESS_PRESSED 71 /* get/set brightness */ /* get/set brightness */ #define SONYPI_IOCGBRT _IOR('v', 0, __u8) #define SONYPI_IOCGBRT _IOR('v', 0, __u8) Loading Loading
drivers/platform/x86/Kconfig +1 −0 Original line number Original line Diff line number Diff line Loading @@ -165,6 +165,7 @@ config SONY_LAPTOP depends on ACPI depends on ACPI select BACKLIGHT_CLASS_DEVICE select BACKLIGHT_CLASS_DEVICE depends on INPUT depends on INPUT depends on RFKILL ---help--- ---help--- This mini-driver drives the SNC and SPIC devices present in the ACPI This mini-driver drives the SNC and SPIC devices present in the ACPI BIOS of the Sony Vaio laptops. BIOS of the Sony Vaio laptops. Loading
drivers/platform/x86/sony-laptop.c +393 −138 Original line number Original line Diff line number Diff line Loading @@ -2,7 +2,7 @@ * ACPI Sony Notebook Control Driver (SNC and SPIC) * ACPI Sony Notebook Control Driver (SNC and SPIC) * * * Copyright (C) 2004-2005 Stelian Pop <stelian@popies.net> * Copyright (C) 2004-2005 Stelian Pop <stelian@popies.net> * Copyright (C) 2007 Mattia Dongili <malattia@linux.it> * Copyright (C) 2007-2009 Mattia Dongili <malattia@linux.it> * * * Parts of this driver inspired from asus_acpi.c and ibm_acpi.c * Parts of this driver inspired from asus_acpi.c and ibm_acpi.c * which are copyrighted by their respective authors. * which are copyrighted by their respective authors. Loading Loading @@ -46,7 +46,6 @@ #include <linux/module.h> #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/moduleparam.h> #include <linux/init.h> #include <linux/init.h> #include <linux/smp_lock.h> #include <linux/types.h> #include <linux/types.h> #include <linux/backlight.h> #include <linux/backlight.h> #include <linux/platform_device.h> #include <linux/platform_device.h> Loading @@ -64,6 +63,7 @@ #include <asm/uaccess.h> #include <asm/uaccess.h> #include <linux/sonypi.h> #include <linux/sonypi.h> #include <linux/sony-laptop.h> #include <linux/sony-laptop.h> #include <linux/rfkill.h> #ifdef CONFIG_SONYPI_COMPAT #ifdef CONFIG_SONYPI_COMPAT #include <linux/poll.h> #include <linux/poll.h> #include <linux/miscdevice.h> #include <linux/miscdevice.h> Loading Loading @@ -123,6 +123,18 @@ MODULE_PARM_DESC(minor, "default is -1 (automatic)"); "default is -1 (automatic)"); #endif #endif enum sony_nc_rfkill { SONY_WIFI, SONY_BLUETOOTH, SONY_WWAN, SONY_WIMAX, SONY_RFKILL_MAX, }; static struct rfkill *sony_rfkill_devices[SONY_RFKILL_MAX]; static int sony_rfkill_address[SONY_RFKILL_MAX] = {0x300, 0x500, 0x700, 0x900}; static void sony_nc_rfkill_update(void); /*********** Input Devices ***********/ /*********** Input Devices ***********/ #define SONY_LAPTOP_BUF_SIZE 128 #define SONY_LAPTOP_BUF_SIZE 128 Loading @@ -134,6 +146,7 @@ struct sony_laptop_input_s { spinlock_t fifo_lock; spinlock_t fifo_lock; struct workqueue_struct *wq; struct workqueue_struct *wq; }; }; static struct sony_laptop_input_s sony_laptop_input = { static struct sony_laptop_input_s sony_laptop_input = { .users = ATOMIC_INIT(0), .users = ATOMIC_INIT(0), }; }; Loading Loading @@ -211,6 +224,14 @@ static int sony_laptop_input_index[] = { 48, /* 61 SONYPI_EVENT_WIRELESS_OFF */ 48, /* 61 SONYPI_EVENT_WIRELESS_OFF */ 49, /* 62 SONYPI_EVENT_ZOOM_IN_PRESSED */ 49, /* 62 SONYPI_EVENT_ZOOM_IN_PRESSED */ 50, /* 63 SONYPI_EVENT_ZOOM_OUT_PRESSED */ 50, /* 63 SONYPI_EVENT_ZOOM_OUT_PRESSED */ 51, /* 64 SONYPI_EVENT_CD_EJECT_PRESSED */ 52, /* 65 SONYPI_EVENT_MODEKEY_PRESSED */ 53, /* 66 SONYPI_EVENT_PKEY_P4 */ 54, /* 67 SONYPI_EVENT_PKEY_P5 */ 55, /* 68 SONYPI_EVENT_SETTINGKEY_PRESSED */ 56, /* 69 SONYPI_EVENT_VOLUME_INC_PRESSED */ 57, /* 70 SONYPI_EVENT_VOLUME_DEC_PRESSED */ -1, /* 71 SONYPI_EVENT_BRIGHTNESS_PRESSED */ }; }; static int sony_laptop_input_keycode_map[] = { static int sony_laptop_input_keycode_map[] = { Loading Loading @@ -264,7 +285,14 @@ static int sony_laptop_input_keycode_map[] = { KEY_WLAN, /* 47 SONYPI_EVENT_WIRELESS_ON */ KEY_WLAN, /* 47 SONYPI_EVENT_WIRELESS_ON */ KEY_WLAN, /* 48 SONYPI_EVENT_WIRELESS_OFF */ KEY_WLAN, /* 48 SONYPI_EVENT_WIRELESS_OFF */ KEY_ZOOMIN, /* 49 SONYPI_EVENT_ZOOM_IN_PRESSED */ KEY_ZOOMIN, /* 49 SONYPI_EVENT_ZOOM_IN_PRESSED */ KEY_ZOOMOUT /* 50 SONYPI_EVENT_ZOOM_OUT_PRESSED */ KEY_ZOOMOUT, /* 50 SONYPI_EVENT_ZOOM_OUT_PRESSED */ KEY_EJECTCD, /* 51 SONYPI_EVENT_CD_EJECT_PRESSED */ KEY_F13, /* 52 SONYPI_EVENT_MODEKEY_PRESSED */ KEY_PROG4, /* 53 SONYPI_EVENT_PKEY_P4 */ KEY_F14, /* 54 SONYPI_EVENT_PKEY_P5 */ KEY_F15, /* 55 SONYPI_EVENT_SETTINGKEY_PRESSED */ KEY_VOLUMEUP, /* 56 SONYPI_EVENT_VOLUME_INC_PRESSED */ KEY_VOLUMEDOWN, /* 57 SONYPI_EVENT_VOLUME_DEC_PRESSED */ }; }; /* release buttons after a short delay if pressed */ /* release buttons after a short delay if pressed */ Loading Loading @@ -369,7 +397,7 @@ static int sony_laptop_setup_input(struct acpi_device *acpi_device) sony_laptop_input.wq = create_singlethread_workqueue("sony-laptop"); sony_laptop_input.wq = create_singlethread_workqueue("sony-laptop"); if (!sony_laptop_input.wq) { if (!sony_laptop_input.wq) { printk(KERN_ERR DRV_PFX printk(KERN_ERR DRV_PFX "Unabe to create workqueue.\n"); "Unable to create workqueue.\n"); error = -ENXIO; error = -ENXIO; goto err_free_kfifo; goto err_free_kfifo; } } Loading Loading @@ -689,6 +717,31 @@ static int acpi_callsetfunc(acpi_handle handle, char *name, int value, return -1; return -1; } } static int sony_find_snc_handle(int handle) { int i; int result; for (i = 0x20; i < 0x30; i++) { acpi_callsetfunc(sony_nc_acpi_handle, "SN00", i, &result); if (result == handle) return i-0x20; } return -1; } static int sony_call_snc_handle(int handle, int argument, int *result) { int offset = sony_find_snc_handle(handle); if (offset < 0) return -1; return acpi_callsetfunc(sony_nc_acpi_handle, "SN07", offset | argument, result); } /* /* * sony_nc_values input/output validate functions * sony_nc_values input/output validate functions */ */ Loading Loading @@ -809,87 +862,53 @@ struct sony_nc_event { u8 event; u8 event; }; }; static struct sony_nc_event *sony_nc_events; static struct sony_nc_event sony_100_events[] = { { 0x90, SONYPI_EVENT_PKEY_P1 }, /* Vaio C* --maybe also FE*, N* and AR* ?-- special init sequence { 0x10, SONYPI_EVENT_ANYBUTTON_RELEASED }, * for Fn keys { 0x91, SONYPI_EVENT_PKEY_P2 }, */ { 0x11, SONYPI_EVENT_ANYBUTTON_RELEASED }, static int sony_nc_C_enable(const struct dmi_system_id *id) { int result = 0; printk(KERN_NOTICE DRV_PFX "detected %s\n", id->ident); sony_nc_events = id->driver_data; if (acpi_callsetfunc(sony_nc_acpi_handle, "SN02", 0x4, &result) < 0 || acpi_callsetfunc(sony_nc_acpi_handle, "SN07", 0x2, &result) < 0 || acpi_callsetfunc(sony_nc_acpi_handle, "SN02", 0x10, &result) < 0 || acpi_callsetfunc(sony_nc_acpi_handle, "SN07", 0x0, &result) < 0 || acpi_callsetfunc(sony_nc_acpi_handle, "SN03", 0x2, &result) < 0 || acpi_callsetfunc(sony_nc_acpi_handle, "SN07", 0x101, &result) < 0) { printk(KERN_WARNING DRV_PFX "failed to initialize SNC, some " "functionalities may be missing\n"); return 1; } return 0; } static struct sony_nc_event sony_C_events[] = { { 0x81, SONYPI_EVENT_FNKEY_F1 }, { 0x81, SONYPI_EVENT_FNKEY_F1 }, { 0x01, SONYPI_EVENT_FNKEY_RELEASED }, { 0x01, SONYPI_EVENT_FNKEY_RELEASED }, { 0x82, SONYPI_EVENT_FNKEY_F2 }, { 0x02, SONYPI_EVENT_FNKEY_RELEASED }, { 0x83, SONYPI_EVENT_FNKEY_F3 }, { 0x03, SONYPI_EVENT_FNKEY_RELEASED }, { 0x84, SONYPI_EVENT_FNKEY_F4 }, { 0x04, SONYPI_EVENT_FNKEY_RELEASED }, { 0x85, SONYPI_EVENT_FNKEY_F5 }, { 0x85, SONYPI_EVENT_FNKEY_F5 }, { 0x05, SONYPI_EVENT_FNKEY_RELEASED }, { 0x05, SONYPI_EVENT_FNKEY_RELEASED }, { 0x86, SONYPI_EVENT_FNKEY_F6 }, { 0x86, SONYPI_EVENT_FNKEY_F6 }, { 0x06, SONYPI_EVENT_FNKEY_RELEASED }, { 0x06, SONYPI_EVENT_FNKEY_RELEASED }, { 0x87, SONYPI_EVENT_FNKEY_F7 }, { 0x87, SONYPI_EVENT_FNKEY_F7 }, { 0x07, SONYPI_EVENT_FNKEY_RELEASED }, { 0x07, SONYPI_EVENT_FNKEY_RELEASED }, { 0x89, SONYPI_EVENT_FNKEY_F9 }, { 0x09, SONYPI_EVENT_FNKEY_RELEASED }, { 0x8A, SONYPI_EVENT_FNKEY_F10 }, { 0x8A, SONYPI_EVENT_FNKEY_F10 }, { 0x0A, SONYPI_EVENT_FNKEY_RELEASED }, { 0x0A, SONYPI_EVENT_FNKEY_RELEASED }, { 0x8C, SONYPI_EVENT_FNKEY_F12 }, { 0x8C, SONYPI_EVENT_FNKEY_F12 }, { 0x0C, SONYPI_EVENT_FNKEY_RELEASED }, { 0x0C, SONYPI_EVENT_FNKEY_RELEASED }, { 0x9f, SONYPI_EVENT_CD_EJECT_PRESSED }, { 0x1f, SONYPI_EVENT_ANYBUTTON_RELEASED }, { 0, 0 }, { 0, 0 }, }; }; /* SNC-only model map */ static struct sony_nc_event sony_127_events[] = { static const struct dmi_system_id sony_nc_ids[] = { { 0x81, SONYPI_EVENT_MODEKEY_PRESSED }, { { 0x01, SONYPI_EVENT_ANYBUTTON_RELEASED }, .ident = "Sony Vaio FE Series", { 0x82, SONYPI_EVENT_PKEY_P1 }, .callback = sony_nc_C_enable, { 0x02, SONYPI_EVENT_ANYBUTTON_RELEASED }, .driver_data = sony_C_events, { 0x83, SONYPI_EVENT_PKEY_P2 }, .matches = { { 0x03, SONYPI_EVENT_ANYBUTTON_RELEASED }, DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), { 0x84, SONYPI_EVENT_PKEY_P3 }, DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FE"), { 0x04, SONYPI_EVENT_ANYBUTTON_RELEASED }, }, { 0x85, SONYPI_EVENT_PKEY_P4 }, }, { 0x05, SONYPI_EVENT_ANYBUTTON_RELEASED }, { { 0x86, SONYPI_EVENT_PKEY_P5 }, .ident = "Sony Vaio FZ Series", { 0x06, SONYPI_EVENT_ANYBUTTON_RELEASED }, .callback = sony_nc_C_enable, { 0x06, SONYPI_EVENT_ANYBUTTON_RELEASED }, .driver_data = sony_C_events, { 0x87, SONYPI_EVENT_SETTINGKEY_PRESSED }, .matches = { { 0x07, SONYPI_EVENT_ANYBUTTON_RELEASED }, DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), { 0, 0 }, DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FZ"), }, }, { .ident = "Sony Vaio C Series", .callback = sony_nc_C_enable, .driver_data = sony_C_events, .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), DMI_MATCH(DMI_PRODUCT_NAME, "VGN-C"), }, }, { .ident = "Sony Vaio N Series", .callback = sony_nc_C_enable, .driver_data = sony_C_events, .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), DMI_MATCH(DMI_PRODUCT_NAME, "VGN-N"), }, }, { } }; }; /* /* Loading @@ -897,38 +916,59 @@ static const struct dmi_system_id sony_nc_ids[] = { */ */ static void sony_acpi_notify(acpi_handle handle, u32 event, void *data) static void sony_acpi_notify(acpi_handle handle, u32 event, void *data) { { struct sony_nc_event *evmap; u32 ev = event; u32 ev = event; if (ev >= 0x90) { /* New-style event */ int result; int result; int key_handle = 0; ev -= 0x90; if (sony_find_snc_handle(0x100) == ev) key_handle = 0x100; if (sony_find_snc_handle(0x127) == ev) key_handle = 0x127; if (key_handle) { struct sony_nc_event *key_event; if (sony_call_snc_handle(key_handle, 0x200, &result)) { dprintk("sony_acpi_notify, unable to decode" " event 0x%.2x 0x%.2x\n", key_handle, ev); /* restore the original event */ ev = event; } else { ev = result & 0xFF; if (ev == 0x92) { if (key_handle == 0x100) /* read the key pressed from EC.GECR key_event = sony_100_events; * A call to SN07 with 0x0202 will do it as well respecting * the current protocol on different OSes * * Note: the path for GECR may be * \_SB.PCI0.LPCB.EC (C, FE, AR, N and friends) * \_SB.PCI0.PIB.EC0 (VGN-FR notifications are sent directly, no GECR) * * TODO: we may want to do the same for the older GHKE -need * dmi list- so this snippet may become one more callback. */ if (acpi_callsetfunc(handle, "SN07", 0x0202, &result) < 0) dprintk("sony_acpi_notify, unable to decode event 0x%.2x\n", ev); else else ev = result & 0xFF; key_event = sony_127_events; } if (sony_nc_events) for (; key_event->data; key_event++) { for (evmap = sony_nc_events; evmap->event; evmap++) { if (key_event->data == ev) { if (evmap->data == ev) { ev = key_event->event; ev = evmap->event; break; break; } } } } dprintk("sony_acpi_notify, event: 0x%.2x\n", ev); if (!key_event->data) printk(KERN_INFO DRV_PFX "Unknown event: 0x%x 0x%x\n", key_handle, ev); else sony_laptop_report_input_event(ev); } } else if (sony_find_snc_handle(0x124) == ev) { sony_nc_rfkill_update(); return; } } else sony_laptop_report_input_event(ev); sony_laptop_report_input_event(ev); dprintk("sony_acpi_notify, event: 0x%.2x\n", ev); acpi_bus_generate_proc_event(sony_nc_acpi_device, 1, ev); acpi_bus_generate_proc_event(sony_nc_acpi_device, 1, ev); } } Loading @@ -953,9 +993,25 @@ static acpi_status sony_walk_callback(acpi_handle handle, u32 level, /* /* * ACPI device * ACPI device */ */ static int sony_nc_function_setup(struct acpi_device *device) { int result; /* Enable all events */ acpi_callsetfunc(sony_nc_acpi_handle, "SN02", 0xffff, &result); /* Setup hotkeys */ sony_call_snc_handle(0x0100, 0, &result); sony_call_snc_handle(0x0101, 0, &result); sony_call_snc_handle(0x0102, 0x100, &result); return 0; } static int sony_nc_resume(struct acpi_device *device) static int sony_nc_resume(struct acpi_device *device) { { struct sony_nc_value *item; struct sony_nc_value *item; acpi_handle handle; for (item = sony_nc_values; item->name; item++) { for (item = sony_nc_values; item->name; item++) { int ret; int ret; Loading @@ -970,13 +1026,188 @@ static int sony_nc_resume(struct acpi_device *device) } } } } if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "ECON", &handle))) { if (acpi_callsetfunc(sony_nc_acpi_handle, "ECON", 1, NULL)) dprintk("ECON Method failed\n"); } if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "SN00", &handle))) { dprintk("Doing SNC setup\n"); sony_nc_function_setup(device); } /* set the last requested brightness level */ /* set the last requested brightness level */ if (sony_backlight_device && if (sony_backlight_device && !sony_backlight_update_status(sony_backlight_device)) !sony_backlight_update_status(sony_backlight_device)) printk(KERN_WARNING DRV_PFX "unable to restore brightness level\n"); printk(KERN_WARNING DRV_PFX "unable to restore brightness level\n"); /* re-initialize models with specific requirements */ return 0; dmi_check_system(sony_nc_ids); } static void sony_nc_rfkill_cleanup(void) { int i; for (i = 0; i < SONY_RFKILL_MAX; i++) { if (sony_rfkill_devices[i]) rfkill_unregister(sony_rfkill_devices[i]); } } static int sony_nc_rfkill_get(void *data, enum rfkill_state *state) { int result; int argument = sony_rfkill_address[(long) data]; sony_call_snc_handle(0x124, 0x200, &result); if (result & 0x1) { sony_call_snc_handle(0x124, argument, &result); if (result & 0xf) *state = RFKILL_STATE_UNBLOCKED; else *state = RFKILL_STATE_SOFT_BLOCKED; } else { *state = RFKILL_STATE_HARD_BLOCKED; } return 0; } static int sony_nc_rfkill_set(void *data, enum rfkill_state state) { int result; int argument = sony_rfkill_address[(long) data] + 0x100; if (state == RFKILL_STATE_UNBLOCKED) argument |= 0xff0000; return sony_call_snc_handle(0x124, argument, &result); } static int sony_nc_setup_wifi_rfkill(struct acpi_device *device) { int err = 0; struct rfkill *sony_wifi_rfkill; sony_wifi_rfkill = rfkill_allocate(&device->dev, RFKILL_TYPE_WLAN); if (!sony_wifi_rfkill) return -1; sony_wifi_rfkill->name = "sony-wifi"; sony_wifi_rfkill->toggle_radio = sony_nc_rfkill_set; sony_wifi_rfkill->get_state = sony_nc_rfkill_get; sony_wifi_rfkill->user_claim_unsupported = 1; sony_wifi_rfkill->data = (void *)SONY_WIFI; err = rfkill_register(sony_wifi_rfkill); if (err) rfkill_free(sony_wifi_rfkill); else sony_rfkill_devices[SONY_WIFI] = sony_wifi_rfkill; return err; } static int sony_nc_setup_bluetooth_rfkill(struct acpi_device *device) { int err = 0; struct rfkill *sony_bluetooth_rfkill; sony_bluetooth_rfkill = rfkill_allocate(&device->dev, RFKILL_TYPE_BLUETOOTH); if (!sony_bluetooth_rfkill) return -1; sony_bluetooth_rfkill->name = "sony-bluetooth"; sony_bluetooth_rfkill->toggle_radio = sony_nc_rfkill_set; sony_bluetooth_rfkill->get_state = sony_nc_rfkill_get; sony_bluetooth_rfkill->user_claim_unsupported = 1; sony_bluetooth_rfkill->data = (void *)SONY_BLUETOOTH; err = rfkill_register(sony_bluetooth_rfkill); if (err) rfkill_free(sony_bluetooth_rfkill); else sony_rfkill_devices[SONY_BLUETOOTH] = sony_bluetooth_rfkill; return err; } static int sony_nc_setup_wwan_rfkill(struct acpi_device *device) { int err = 0; struct rfkill *sony_wwan_rfkill; sony_wwan_rfkill = rfkill_allocate(&device->dev, RFKILL_TYPE_WWAN); if (!sony_wwan_rfkill) return -1; sony_wwan_rfkill->name = "sony-wwan"; sony_wwan_rfkill->toggle_radio = sony_nc_rfkill_set; sony_wwan_rfkill->get_state = sony_nc_rfkill_get; sony_wwan_rfkill->user_claim_unsupported = 1; sony_wwan_rfkill->data = (void *)SONY_WWAN; err = rfkill_register(sony_wwan_rfkill); if (err) rfkill_free(sony_wwan_rfkill); else sony_rfkill_devices[SONY_WWAN] = sony_wwan_rfkill; return err; } static int sony_nc_setup_wimax_rfkill(struct acpi_device *device) { int err = 0; struct rfkill *sony_wimax_rfkill; sony_wimax_rfkill = rfkill_allocate(&device->dev, RFKILL_TYPE_WIMAX); if (!sony_wimax_rfkill) return -1; sony_wimax_rfkill->name = "sony-wimax"; sony_wimax_rfkill->toggle_radio = sony_nc_rfkill_set; sony_wimax_rfkill->get_state = sony_nc_rfkill_get; sony_wimax_rfkill->user_claim_unsupported = 1; sony_wimax_rfkill->data = (void *)SONY_WIMAX; err = rfkill_register(sony_wimax_rfkill); if (err) rfkill_free(sony_wimax_rfkill); else sony_rfkill_devices[SONY_WIMAX] = sony_wimax_rfkill; return err; } static void sony_nc_rfkill_update() { int i; enum rfkill_state state; for (i = 0; i < SONY_RFKILL_MAX; i++) { if (sony_rfkill_devices[i]) { sony_rfkill_devices[i]-> get_state(sony_rfkill_devices[i]->data, &state); rfkill_force_state(sony_rfkill_devices[i], state); } } } static int sony_nc_rfkill_setup(struct acpi_device *device) { int result, ret; if (sony_find_snc_handle(0x124) == -1) return -1; ret = sony_call_snc_handle(0x124, 0xb00, &result); if (ret) { printk(KERN_INFO DRV_PFX "Unable to enumerate rfkill devices: %x\n", ret); return ret; } if (result & 0x1) sony_nc_setup_wifi_rfkill(device); if (result & 0x2) sony_nc_setup_bluetooth_rfkill(device); if (result & 0x1c) sony_nc_setup_wwan_rfkill(device); if (result & 0x20) sony_nc_setup_wimax_rfkill(device); return 0; return 0; } } Loading Loading @@ -1024,11 +1255,24 @@ static int sony_nc_add(struct acpi_device *device) dprintk("_INI Method failed\n"); dprintk("_INI Method failed\n"); } } if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "ECON", &handle))) { if (acpi_callsetfunc(sony_nc_acpi_handle, "ECON", 1, NULL)) dprintk("ECON Method failed\n"); } if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "SN00", &handle))) { dprintk("Doing SNC setup\n"); sony_nc_function_setup(device); sony_nc_rfkill_setup(device); } /* setup input devices and helper fifo */ /* setup input devices and helper fifo */ result = sony_laptop_setup_input(device); result = sony_laptop_setup_input(device); if (result) { if (result) { printk(KERN_ERR DRV_PFX printk(KERN_ERR DRV_PFX "Unabe to create input devices.\n"); "Unable to create input devices.\n"); goto outwalk; goto outwalk; } } Loading Loading @@ -1063,9 +1307,6 @@ static int sony_nc_add(struct acpi_device *device) } } /* initialize models with specific requirements */ dmi_check_system(sony_nc_ids); result = sony_pf_add(); result = sony_pf_add(); if (result) if (result) goto outbacklight; goto outbacklight; Loading Loading @@ -1131,6 +1372,7 @@ static int sony_nc_add(struct acpi_device *device) sony_laptop_remove_input(); sony_laptop_remove_input(); outwalk: outwalk: sony_nc_rfkill_cleanup(); return result; return result; } } Loading @@ -1156,6 +1398,7 @@ static int sony_nc_remove(struct acpi_device *device, int type) sony_pf_remove(); sony_pf_remove(); sony_laptop_remove_input(); sony_laptop_remove_input(); sony_nc_rfkill_cleanup(); dprintk(SONY_NC_DRIVER_NAME " removed.\n"); dprintk(SONY_NC_DRIVER_NAME " removed.\n"); return 0; return 0; Loading Loading @@ -1195,7 +1438,6 @@ static struct acpi_driver sony_nc_driver = { #define SONYPI_TYPE1_OFFSET 0x04 #define SONYPI_TYPE1_OFFSET 0x04 #define SONYPI_TYPE2_OFFSET 0x12 #define SONYPI_TYPE2_OFFSET 0x12 #define SONYPI_TYPE3_OFFSET 0x12 #define SONYPI_TYPE3_OFFSET 0x12 #define SONYPI_TYPE4_OFFSET 0x12 struct sony_pic_ioport { struct sony_pic_ioport { struct acpi_resource_io io1; struct acpi_resource_io io1; Loading Loading @@ -1328,6 +1570,7 @@ static struct sonypi_event sonypi_pkeyev[] = { { 0x01, SONYPI_EVENT_PKEY_P1 }, { 0x01, SONYPI_EVENT_PKEY_P1 }, { 0x02, SONYPI_EVENT_PKEY_P2 }, { 0x02, SONYPI_EVENT_PKEY_P2 }, { 0x04, SONYPI_EVENT_PKEY_P3 }, { 0x04, SONYPI_EVENT_PKEY_P3 }, { 0x20, SONYPI_EVENT_PKEY_P1 }, { 0, 0 } { 0, 0 } }; }; Loading Loading @@ -1371,6 +1614,7 @@ static struct sonypi_event sonypi_zoomev[] = { { 0x39, SONYPI_EVENT_ZOOM_PRESSED }, { 0x39, SONYPI_EVENT_ZOOM_PRESSED }, { 0x10, SONYPI_EVENT_ZOOM_IN_PRESSED }, { 0x10, SONYPI_EVENT_ZOOM_IN_PRESSED }, { 0x20, SONYPI_EVENT_ZOOM_OUT_PRESSED }, { 0x20, SONYPI_EVENT_ZOOM_OUT_PRESSED }, { 0x04, SONYPI_EVENT_ZOOM_PRESSED }, { 0, 0 } { 0, 0 } }; }; Loading Loading @@ -1401,6 +1645,19 @@ static struct sonypi_event sonypi_batteryev[] = { { 0, 0 } { 0, 0 } }; }; /* The set of possible volume events */ static struct sonypi_event sonypi_volumeev[] = { { 0x01, SONYPI_EVENT_VOLUME_INC_PRESSED }, { 0x02, SONYPI_EVENT_VOLUME_DEC_PRESSED }, { 0, 0 } }; /* The set of possible brightness events */ static struct sonypi_event sonypi_brightnessev[] = { { 0x80, SONYPI_EVENT_BRIGHTNESS_PRESSED }, { 0, 0 } }; static struct sonypi_eventtypes type1_events[] = { static struct sonypi_eventtypes type1_events[] = { { 0, 0xffffffff, sonypi_releaseev }, { 0, 0xffffffff, sonypi_releaseev }, { 0x70, SONYPI_MEYE_MASK, sonypi_meyeev }, { 0x70, SONYPI_MEYE_MASK, sonypi_meyeev }, Loading Loading @@ -1438,17 +1695,11 @@ static struct sonypi_eventtypes type3_events[] = { { 0x31, SONYPI_MEMORYSTICK_MASK, sonypi_memorystickev }, { 0x31, SONYPI_MEMORYSTICK_MASK, sonypi_memorystickev }, { 0x41, SONYPI_BATTERY_MASK, sonypi_batteryev }, { 0x41, SONYPI_BATTERY_MASK, sonypi_batteryev }, { 0x31, SONYPI_PKEY_MASK, sonypi_pkeyev }, { 0x31, SONYPI_PKEY_MASK, sonypi_pkeyev }, { 0 }, }; static struct sonypi_eventtypes type4_events[] = { { 0, 0xffffffff, sonypi_releaseev }, { 0x21, SONYPI_FNKEY_MASK, sonypi_fnkeyev }, { 0x31, SONYPI_WIRELESS_MASK, sonypi_wlessev }, { 0x31, SONYPI_MEMORYSTICK_MASK, sonypi_memorystickev }, { 0x41, SONYPI_BATTERY_MASK, sonypi_batteryev }, { 0x05, SONYPI_PKEY_MASK, sonypi_pkeyev }, { 0x05, SONYPI_PKEY_MASK, sonypi_pkeyev }, { 0x05, SONYPI_ZOOM_MASK, sonypi_zoomev }, { 0x05, SONYPI_ZOOM_MASK, sonypi_zoomev }, { 0x05, SONYPI_CAPTURE_MASK, sonypi_captureev }, { 0x05, SONYPI_CAPTURE_MASK, sonypi_captureev }, { 0x05, SONYPI_PKEY_MASK, sonypi_volumeev }, { 0x05, SONYPI_PKEY_MASK, sonypi_brightnessev }, { 0 }, { 0 }, }; }; Loading Loading @@ -1511,11 +1762,11 @@ static u8 sony_pic_call3(u8 dev, u8 fn, u8 v) /* /* * minidrivers for SPIC models * minidrivers for SPIC models */ */ static int type4_handle_irq(const u8 data_mask, const u8 ev) static int type3_handle_irq(const u8 data_mask, const u8 ev) { { /* /* * 0x31 could mean we have to take some extra action and wait for * 0x31 could mean we have to take some extra action and wait for * the next irq for some Type4 models, it will generate a new * the next irq for some Type3 models, it will generate a new * irq and we can read new data from the device: * irq and we can read new data from the device: * - 0x5c and 0x5f requires 0xA0 * - 0x5c and 0x5f requires 0xA0 * - 0x61 requires 0xB3 * - 0x61 requires 0xB3 Loading Loading @@ -1545,16 +1796,10 @@ static struct device_ctrl spic_types[] = { }, }, { { .model = SONYPI_DEVICE_TYPE3, .model = SONYPI_DEVICE_TYPE3, .handle_irq = NULL, .handle_irq = type3_handle_irq, .evport_offset = SONYPI_TYPE3_OFFSET, .evport_offset = SONYPI_TYPE3_OFFSET, .event_types = type3_events, .event_types = type3_events, }, }, { .model = SONYPI_DEVICE_TYPE4, .handle_irq = type4_handle_irq, .evport_offset = SONYPI_TYPE4_OFFSET, .event_types = type4_events, }, }; }; static void sony_pic_detect_device_type(struct sony_pic_dev *dev) static void sony_pic_detect_device_type(struct sony_pic_dev *dev) Loading @@ -1578,14 +1823,21 @@ static void sony_pic_detect_device_type(struct sony_pic_dev *dev) pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_1, NULL); PCI_DEVICE_ID_INTEL_ICH7_1, NULL); if (pcidev) { if (pcidev) { dev->control = &spic_types[3]; dev->control = &spic_types[2]; goto out; goto out; } } pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_4, NULL); PCI_DEVICE_ID_INTEL_ICH8_4, NULL); if (pcidev) { if (pcidev) { dev->control = &spic_types[3]; dev->control = &spic_types[2]; goto out; } pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_1, NULL); if (pcidev) { dev->control = &spic_types[2]; goto out; goto out; } } Loading @@ -1598,8 +1850,7 @@ out: printk(KERN_INFO DRV_PFX "detected Type%d model\n", printk(KERN_INFO DRV_PFX "detected Type%d model\n", dev->control->model == SONYPI_DEVICE_TYPE1 ? 1 : dev->control->model == SONYPI_DEVICE_TYPE1 ? 1 : dev->control->model == SONYPI_DEVICE_TYPE2 ? 2 : dev->control->model == SONYPI_DEVICE_TYPE2 ? 2 : 3); dev->control->model == SONYPI_DEVICE_TYPE3 ? 3 : 4); } } /* camera tests and poweron/poweroff */ /* camera tests and poweron/poweroff */ Loading Loading @@ -1754,17 +2005,14 @@ int sony_pic_camera_command(int command, u8 value) EXPORT_SYMBOL(sony_pic_camera_command); EXPORT_SYMBOL(sony_pic_camera_command); /* gprs/edge modem (SZ460N and SZ210P), thanks to Joshua Wise */ /* gprs/edge modem (SZ460N and SZ210P), thanks to Joshua Wise */ static void sony_pic_set_wwanpower(u8 state) static void __sony_pic_set_wwanpower(u8 state) { { state = !!state; state = !!state; mutex_lock(&spic_dev.lock); if (spic_dev.wwan_power == state) if (spic_dev.wwan_power == state) { mutex_unlock(&spic_dev.lock); return; return; } sony_pic_call2(0xB0, state); sony_pic_call2(0xB0, state); sony_pic_call1(0x82); spic_dev.wwan_power = state; spic_dev.wwan_power = state; mutex_unlock(&spic_dev.lock); } } static ssize_t sony_pic_wwanpower_store(struct device *dev, static ssize_t sony_pic_wwanpower_store(struct device *dev, Loading @@ -1776,7 +2024,9 @@ static ssize_t sony_pic_wwanpower_store(struct device *dev, return -EINVAL; return -EINVAL; value = simple_strtoul(buffer, NULL, 10); value = simple_strtoul(buffer, NULL, 10); sony_pic_set_wwanpower(value); mutex_lock(&spic_dev.lock); __sony_pic_set_wwanpower(value); mutex_unlock(&spic_dev.lock); return count; return count; } } Loading Loading @@ -1934,10 +2184,15 @@ static int sonypi_misc_release(struct inode *inode, struct file *file) static int sonypi_misc_open(struct inode *inode, struct file *file) static int sonypi_misc_open(struct inode *inode, struct file *file) { { /* Flush input queue on first open */ /* Flush input queue on first open */ lock_kernel(); unsigned long flags; spin_lock_irqsave(sonypi_compat.fifo->lock, flags); if (atomic_inc_return(&sonypi_compat.open_count) == 1) if (atomic_inc_return(&sonypi_compat.open_count) == 1) kfifo_reset(sonypi_compat.fifo); __kfifo_reset(sonypi_compat.fifo); unlock_kernel(); spin_unlock_irqrestore(sonypi_compat.fifo->lock, flags); return 0; return 0; } } Loading Loading @@ -1990,8 +2245,8 @@ static int ec_read16(u8 addr, u16 *value) return 0; return 0; } } static int sonypi_misc_ioctl(struct inode *ip, struct file *fp, static long sonypi_misc_ioctl(struct file *fp, unsigned int cmd, unsigned int cmd, unsigned long arg) unsigned long arg) { { int ret = 0; int ret = 0; void __user *argp = (void __user *)arg; void __user *argp = (void __user *)arg; Loading Loading @@ -2125,7 +2380,7 @@ static const struct file_operations sonypi_misc_fops = { .open = sonypi_misc_open, .open = sonypi_misc_open, .release = sonypi_misc_release, .release = sonypi_misc_release, .fasync = sonypi_misc_fasync, .fasync = sonypi_misc_fasync, .ioctl = sonypi_misc_ioctl, .unlocked_ioctl = sonypi_misc_ioctl, }; }; static struct miscdevice sonypi_misc_device = { static struct miscdevice sonypi_misc_device = { Loading Loading @@ -2566,7 +2821,7 @@ static int sony_pic_add(struct acpi_device *device) result = sony_pic_possible_resources(device); result = sony_pic_possible_resources(device); if (result) { if (result) { printk(KERN_ERR DRV_PFX printk(KERN_ERR DRV_PFX "Unabe to read possible resources.\n"); "Unable to read possible resources.\n"); goto err_free_resources; goto err_free_resources; } } Loading @@ -2574,7 +2829,7 @@ static int sony_pic_add(struct acpi_device *device) result = sony_laptop_setup_input(device); result = sony_laptop_setup_input(device); if (result) { if (result) { printk(KERN_ERR DRV_PFX printk(KERN_ERR DRV_PFX "Unabe to create input devices.\n"); "Unable to create input devices.\n"); goto err_free_resources; goto err_free_resources; } } Loading
include/linux/sonypi.h +8 −0 Original line number Original line Diff line number Diff line Loading @@ -103,6 +103,14 @@ #define SONYPI_EVENT_WIRELESS_OFF 61 #define SONYPI_EVENT_WIRELESS_OFF 61 #define SONYPI_EVENT_ZOOM_IN_PRESSED 62 #define SONYPI_EVENT_ZOOM_IN_PRESSED 62 #define SONYPI_EVENT_ZOOM_OUT_PRESSED 63 #define SONYPI_EVENT_ZOOM_OUT_PRESSED 63 #define SONYPI_EVENT_CD_EJECT_PRESSED 64 #define SONYPI_EVENT_MODEKEY_PRESSED 65 #define SONYPI_EVENT_PKEY_P4 66 #define SONYPI_EVENT_PKEY_P5 67 #define SONYPI_EVENT_SETTINGKEY_PRESSED 68 #define SONYPI_EVENT_VOLUME_INC_PRESSED 69 #define SONYPI_EVENT_VOLUME_DEC_PRESSED 70 #define SONYPI_EVENT_BRIGHTNESS_PRESSED 71 /* get/set brightness */ /* get/set brightness */ #define SONYPI_IOCGBRT _IOR('v', 0, __u8) #define SONYPI_IOCGBRT _IOR('v', 0, __u8) Loading