Commit 443e6221 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for_linus' of...

Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mjg59/platform-drivers-x86

* 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mjg59/platform-drivers-x86: (36 commits)
  sony-laptop: support new hotkeys on the P, Z and EC series
  platform/x86: Consistently select LEDS Kconfig options
  sony-laptop: fix sparse non-ANSI function warning
  intel_ips: fix sparse non-ANSI function warning
  Support KHLB2 in the compal laptop driver
  acer-wmi: Enabled Acer Launch Manager mode
  [PATCH] intel_pmic_gpio: modify EOI handling following change of kernel irq subsystem
  ACPI Thinkpad: We must always call va_end() after va_start() but do not do so in thinkpad_acpi.c::acpi_evalf()
  acer-wmi: Initialize wlan/bluetooth/wwan rfkill software block state
  acer-wmi: Detect the WiFi/Bluetooth/3G devices available
  acer-wmi: Add 3G rfkill sysfs file
  acer-wmi: Add acer wmi hotkey events support
  platform/x86: Kconfig: Replace select by depends on ACPI_WMI
  ideapad: pass ideapad_priv as argument (part 2)
  ideapad: pass ideapad_priv as argument (part 1)
  ideapad: add markups, unify comments and return result when init
  ideapad: add hotkey support
  ideapad: let camera power control entry under platform driver
  ideapad: add platform driver for ideapad
  fujitsu-laptop: fix compiler warning on pnp_ids
  ...
parents 0caca697 1a7d9469
What: /sys/devices/platform/ideapad/camera_power
Date: Dec 2010
KernelVersion: 2.6.37
Contact: "Ike Panhc <ike.pan@canonical.com>"
Description:
Control the power of camera module. 1 means on, 0 means off.
...@@ -2271,6 +2271,14 @@ W: http://acpi4asus.sf.net ...@@ -2271,6 +2271,14 @@ W: http://acpi4asus.sf.net
S: Maintained S: Maintained
F: drivers/platform/x86/eeepc-laptop.c F: drivers/platform/x86/eeepc-laptop.c
EEEPC WMI EXTRAS DRIVER
M: Corentin Chary <corentincj@iksaif.net>
L: acpi4asus-user@lists.sourceforge.net
L: platform-driver-x86@vger.kernel.org
W: http://acpi4asus.sf.net
S: Maintained
F: drivers/platform/x86/eeepc-wmi.c
EFIFB FRAMEBUFFER DRIVER EFIFB FRAMEBUFFER DRIVER
L: linux-fbdev@vger.kernel.org L: linux-fbdev@vger.kernel.org
M: Peter Jones <pjones@redhat.com> M: Peter Jones <pjones@redhat.com>
......
...@@ -18,12 +18,14 @@ if X86_PLATFORM_DEVICES ...@@ -18,12 +18,14 @@ if X86_PLATFORM_DEVICES
config ACER_WMI config ACER_WMI
tristate "Acer WMI Laptop Extras" tristate "Acer WMI Laptop Extras"
depends on ACPI depends on ACPI
depends on LEDS_CLASS select LEDS_CLASS
depends on NEW_LEDS select NEW_LEDS
depends on BACKLIGHT_CLASS_DEVICE depends on BACKLIGHT_CLASS_DEVICE
depends on SERIO_I8042 depends on SERIO_I8042
depends on INPUT
depends on RFKILL || RFKILL = n depends on RFKILL || RFKILL = n
select ACPI_WMI depends on ACPI_WMI
select INPUT_SPARSEKMAP
---help--- ---help---
This is a driver for newer Acer (and Wistron) laptops. It adds This is a driver for newer Acer (and Wistron) laptops. It adds
wireless radio and bluetooth control, and on some laptops, wireless radio and bluetooth control, and on some laptops,
...@@ -131,7 +133,7 @@ config TC1100_WMI ...@@ -131,7 +133,7 @@ config TC1100_WMI
depends on !X86_64 depends on !X86_64
depends on EXPERIMENTAL depends on EXPERIMENTAL
depends on ACPI depends on ACPI
select ACPI_WMI depends on ACPI_WMI
---help--- ---help---
This is a driver for the WMI extensions (wireless and bluetooth power This is a driver for the WMI extensions (wireless and bluetooth power
control) of the HP Compaq TC1100 tablet. control) of the HP Compaq TC1100 tablet.
...@@ -226,6 +228,7 @@ config IDEAPAD_LAPTOP ...@@ -226,6 +228,7 @@ config IDEAPAD_LAPTOP
tristate "Lenovo IdeaPad Laptop Extras" tristate "Lenovo IdeaPad Laptop Extras"
depends on ACPI depends on ACPI
depends on RFKILL depends on RFKILL
select INPUT_SPARSEKMAP
help help
This is a driver for the rfkill switches on Lenovo IdeaPad netbooks. This is a driver for the rfkill switches on Lenovo IdeaPad netbooks.
...@@ -425,7 +428,10 @@ config EEEPC_WMI ...@@ -425,7 +428,10 @@ config EEEPC_WMI
depends on INPUT depends on INPUT
depends on EXPERIMENTAL depends on EXPERIMENTAL
depends on BACKLIGHT_CLASS_DEVICE depends on BACKLIGHT_CLASS_DEVICE
depends on RFKILL || RFKILL = n
select INPUT_SPARSEKMAP select INPUT_SPARSEKMAP
select LEDS_CLASS
select NEW_LEDS
---help--- ---help---
Say Y here if you want to support WMI-based hotkeys on Eee PC laptops. Say Y here if you want to support WMI-based hotkeys on Eee PC laptops.
...@@ -510,8 +516,8 @@ config TOPSTAR_LAPTOP ...@@ -510,8 +516,8 @@ config TOPSTAR_LAPTOP
config ACPI_TOSHIBA config ACPI_TOSHIBA
tristate "Toshiba Laptop Extras" tristate "Toshiba Laptop Extras"
depends on ACPI depends on ACPI
depends on LEDS_CLASS select LEDS_CLASS
depends on NEW_LEDS select NEW_LEDS
depends on BACKLIGHT_CLASS_DEVICE depends on BACKLIGHT_CLASS_DEVICE
depends on INPUT depends on INPUT
depends on RFKILL || RFKILL = n depends on RFKILL || RFKILL = n
...@@ -576,6 +582,15 @@ config INTEL_SCU_IPC ...@@ -576,6 +582,15 @@ config INTEL_SCU_IPC
some embedded Intel x86 platforms. This is not needed for PC-type some embedded Intel x86 platforms. This is not needed for PC-type
machines. machines.
config INTEL_SCU_IPC_UTIL
tristate "Intel SCU IPC utility driver"
depends on INTEL_SCU_IPC
default y
---help---
The IPC Util driver provides an interface with the SCU enabling
low level access for debug work and updating the firmware. Say
N unless you will be doing this on an Intel MID platform.
config GPIO_INTEL_PMIC config GPIO_INTEL_PMIC
bool "Intel PMIC GPIO support" bool "Intel PMIC GPIO support"
depends on INTEL_SCU_IPC && GPIOLIB depends on INTEL_SCU_IPC && GPIOLIB
......
...@@ -28,6 +28,7 @@ obj-$(CONFIG_TOPSTAR_LAPTOP) += topstar-laptop.o ...@@ -28,6 +28,7 @@ obj-$(CONFIG_TOPSTAR_LAPTOP) += topstar-laptop.o
obj-$(CONFIG_ACPI_TOSHIBA) += toshiba_acpi.o obj-$(CONFIG_ACPI_TOSHIBA) += toshiba_acpi.o
obj-$(CONFIG_TOSHIBA_BT_RFKILL) += toshiba_bluetooth.o obj-$(CONFIG_TOSHIBA_BT_RFKILL) += toshiba_bluetooth.o
obj-$(CONFIG_INTEL_SCU_IPC) += intel_scu_ipc.o obj-$(CONFIG_INTEL_SCU_IPC) += intel_scu_ipc.o
obj-$(CONFIG_INTEL_SCU_IPC_UTIL)+= intel_scu_ipcutil.o
obj-$(CONFIG_RAR_REGISTER) += intel_rar_register.o obj-$(CONFIG_RAR_REGISTER) += intel_rar_register.o
obj-$(CONFIG_INTEL_IPS) += intel_ips.o obj-$(CONFIG_INTEL_IPS) += intel_ips.o
obj-$(CONFIG_GPIO_INTEL_PMIC) += intel_pmic_gpio.o obj-$(CONFIG_GPIO_INTEL_PMIC) += intel_pmic_gpio.o
......
This diff is collapsed.
...@@ -522,18 +522,20 @@ static int cmpc_rfkill_block(void *data, bool blocked) ...@@ -522,18 +522,20 @@ static int cmpc_rfkill_block(void *data, bool blocked)
acpi_status status; acpi_status status;
acpi_handle handle; acpi_handle handle;
unsigned long long state; unsigned long long state;
bool is_blocked;
handle = data; handle = data;
status = cmpc_get_rfkill_wlan(handle, &state); status = cmpc_get_rfkill_wlan(handle, &state);
if (ACPI_FAILURE(status)) if (ACPI_FAILURE(status))
return -ENODEV; return -ENODEV;
if (blocked) /* Check if we really need to call cmpc_set_rfkill_wlan */
state &= ~1; is_blocked = state & 1 ? false : true;
else if (is_blocked != blocked) {
state |= 1; state = blocked ? 0 : 1;
status = cmpc_set_rfkill_wlan(handle, state); status = cmpc_set_rfkill_wlan(handle, state);
if (ACPI_FAILURE(status)) if (ACPI_FAILURE(status))
return -ENODEV; return -ENODEV;
}
return 0; return 0;
} }
...@@ -653,8 +655,9 @@ static void cmpc_keys_handler(struct acpi_device *dev, u32 event) ...@@ -653,8 +655,9 @@ static void cmpc_keys_handler(struct acpi_device *dev, u32 event)
if ((event & 0x0F) < ARRAY_SIZE(cmpc_keys_codes)) if ((event & 0x0F) < ARRAY_SIZE(cmpc_keys_codes))
code = cmpc_keys_codes[event & 0x0F]; code = cmpc_keys_codes[event & 0x0F];
inputdev = dev_get_drvdata(&dev->dev);; inputdev = dev_get_drvdata(&dev->dev);
input_report_key(inputdev, code, !(event & 0x10)); input_report_key(inputdev, code, !(event & 0x10));
input_sync(inputdev);
} }
static void cmpc_keys_idev_init(struct input_dev *inputdev) static void cmpc_keys_idev_init(struct input_dev *inputdev)
......
...@@ -872,6 +872,14 @@ static struct dmi_system_id __initdata compal_dmi_table[] = { ...@@ -872,6 +872,14 @@ static struct dmi_system_id __initdata compal_dmi_table[] = {
}, },
.callback = dmi_check_cb_extra .callback = dmi_check_cb_extra
}, },
{
.ident = "KHLB2",
.matches = {
DMI_MATCH(DMI_BOARD_NAME, "KHLB2"),
DMI_MATCH(DMI_BOARD_VERSION, "REFERENCE"),
},
.callback = dmi_check_cb_extra
},
{ } { }
}; };
......
...@@ -529,6 +529,15 @@ static void tpd_led_set(struct led_classdev *led_cdev, ...@@ -529,6 +529,15 @@ static void tpd_led_set(struct led_classdev *led_cdev,
queue_work(eeepc->led_workqueue, &eeepc->tpd_led_work); queue_work(eeepc->led_workqueue, &eeepc->tpd_led_work);
} }
static enum led_brightness tpd_led_get(struct led_classdev *led_cdev)
{
struct eeepc_laptop *eeepc;
eeepc = container_of(led_cdev, struct eeepc_laptop, tpd_led);
return get_acpi(eeepc, CM_ASL_TPD);
}
static int eeepc_led_init(struct eeepc_laptop *eeepc) static int eeepc_led_init(struct eeepc_laptop *eeepc)
{ {
int rv; int rv;
...@@ -543,6 +552,8 @@ static int eeepc_led_init(struct eeepc_laptop *eeepc) ...@@ -543,6 +552,8 @@ static int eeepc_led_init(struct eeepc_laptop *eeepc)
eeepc->tpd_led.name = "eeepc::touchpad"; eeepc->tpd_led.name = "eeepc::touchpad";
eeepc->tpd_led.brightness_set = tpd_led_set; eeepc->tpd_led.brightness_set = tpd_led_set;
if (get_acpi(eeepc, CM_ASL_TPD) >= 0) /* if method is available */
eeepc->tpd_led.brightness_get = tpd_led_get;
eeepc->tpd_led.max_brightness = 1; eeepc->tpd_led.max_brightness = 1;
rv = led_classdev_register(&eeepc->platform_device->dev, rv = led_classdev_register(&eeepc->platform_device->dev,
......
This diff is collapsed.
...@@ -1240,7 +1240,7 @@ MODULE_ALIAS("dmi:*:svnFUJITSUSIEMENS:*:pvr:rvnFUJITSU:rnFJNB1D3:*:cvrS6410:*"); ...@@ -1240,7 +1240,7 @@ MODULE_ALIAS("dmi:*:svnFUJITSUSIEMENS:*:pvr:rvnFUJITSU:rnFJNB1D3:*:cvrS6410:*");
MODULE_ALIAS("dmi:*:svnFUJITSUSIEMENS:*:pvr:rvnFUJITSU:rnFJNB1E6:*:cvrS6420:*"); MODULE_ALIAS("dmi:*:svnFUJITSUSIEMENS:*:pvr:rvnFUJITSU:rnFJNB1E6:*:cvrS6420:*");
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[] __used = {
{.id = "FUJ02bf"}, {.id = "FUJ02bf"},
{.id = "FUJ02B1"}, {.id = "FUJ02B1"},
{.id = "FUJ02E3"}, {.id = "FUJ02E3"},
......
This diff is collapsed.
...@@ -1474,7 +1474,7 @@ ips_gpu_turbo_enabled(struct ips_driver *ips) ...@@ -1474,7 +1474,7 @@ ips_gpu_turbo_enabled(struct ips_driver *ips)
} }
void void
ips_link_to_i915_driver() ips_link_to_i915_driver(void)
{ {
/* We can't cleanly get at the various ips_driver structs from /* We can't cleanly get at the various ips_driver structs from
* this caller (the i915 driver), so just set a flag saying * this caller (the i915 driver), so just set a flag saying
......
...@@ -244,7 +244,11 @@ static void pmic_irq_handler(unsigned irq, struct irq_desc *desc) ...@@ -244,7 +244,11 @@ static void pmic_irq_handler(unsigned irq, struct irq_desc *desc)
generic_handle_irq(pg->irq_base + gpio); generic_handle_irq(pg->irq_base + gpio);
} }
} }
desc->chip->eoi(irq);
if (desc->chip->irq_eoi)
desc->chip->irq_eoi(irq_get_irq_data(irq));
else
dev_warn(pg->chip.dev, "missing EOI handler for irq %d\n", irq);
} }
static int __devinit platform_pmic_gpio_probe(struct platform_device *pdev) static int __devinit platform_pmic_gpio_probe(struct platform_device *pdev)
......
...@@ -497,7 +497,7 @@ int intel_scu_ipc_i2c_cntrl(u32 addr, u32 *data) ...@@ -497,7 +497,7 @@ int intel_scu_ipc_i2c_cntrl(u32 addr, u32 *data)
"intel_scu_ipc: I2C INVALID_CMD = 0x%x\n", cmd); "intel_scu_ipc: I2C INVALID_CMD = 0x%x\n", cmd);
mutex_unlock(&ipclock); mutex_unlock(&ipclock);
return -1; return -EIO;
} }
mutex_unlock(&ipclock); mutex_unlock(&ipclock);
return 0; return 0;
...@@ -642,7 +642,7 @@ int intel_scu_ipc_fw_update(u8 *buffer, u32 length) ...@@ -642,7 +642,7 @@ int intel_scu_ipc_fw_update(u8 *buffer, u32 length)
if (status == IPC_FW_UPDATE_SUCCESS) if (status == IPC_FW_UPDATE_SUCCESS)
return 0; return 0;
return -1; return -EIO;
} }
EXPORT_SYMBOL(intel_scu_ipc_fw_update); EXPORT_SYMBOL(intel_scu_ipc_fw_update);
......
/*
* intel_scu_ipc.c: Driver for the Intel SCU IPC mechanism
*
* (C) Copyright 2008-2010 Intel Corporation
* Author: Sreedhara DS (sreedhara.ds@intel.com)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; version 2
* of the License.
*
* This driver provides ioctl interfaces to call intel scu ipc driver api
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/fcntl.h>
#include <linux/sched.h>
#include <linux/uaccess.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <asm/intel_scu_ipc.h>
static u32 major;
#define MAX_FW_SIZE 264192
/* ioctl commnds */
#define INTE_SCU_IPC_REGISTER_READ 0
#define INTE_SCU_IPC_REGISTER_WRITE 1
#define INTE_SCU_IPC_REGISTER_UPDATE 2
#define INTE_SCU_IPC_FW_UPDATE 0xA2
struct scu_ipc_data {
u32 count; /* No. of registers */
u16 addr[5]; /* Register addresses */
u8 data[5]; /* Register data */
u8 mask; /* Valid for read-modify-write */
};
/**
* scu_reg_access - implement register access ioctls
* @cmd: command we are doing (read/write/update)
* @data: kernel copy of ioctl data
*
* Allow the user to perform register accesses on the SCU via the
* kernel interface
*/
static int scu_reg_access(u32 cmd, struct scu_ipc_data *data)
{
int count = data->count;
if (count == 0 || count == 3 || count > 4)
return -EINVAL;
switch (cmd) {
case INTE_SCU_IPC_REGISTER_READ:
return intel_scu_ipc_readv(data->addr, data->data, count);
case INTE_SCU_IPC_REGISTER_WRITE:
return intel_scu_ipc_writev(data->addr, data->data, count);
case INTE_SCU_IPC_REGISTER_UPDATE:
return intel_scu_ipc_update_register(data->addr[0],
data->data[0], data->mask);
default:
return -ENOTTY;
}
}
/**
* scu_ipc_ioctl - control ioctls for the SCU
* @fp: file handle of the SCU device
* @cmd: ioctl coce
* @arg: pointer to user passed structure
*
* Support the I/O and firmware flashing interfaces of the SCU
*/
static long scu_ipc_ioctl(struct file *fp, unsigned int cmd,
unsigned long arg)
{
int ret;
struct scu_ipc_data data;
void __user *argp = (void __user *)arg;
if (!capable(CAP_SYS_RAWIO))
return -EPERM;
if (cmd == INTE_SCU_IPC_FW_UPDATE) {
u8 *fwbuf = kmalloc(MAX_FW_SIZE, GFP_KERNEL);
if (fwbuf == NULL)
return -ENOMEM;
if (copy_from_user(fwbuf, (u8 *)arg, MAX_FW_SIZE)) {
kfree(fwbuf);
return -EFAULT;
}
ret = intel_scu_ipc_fw_update(fwbuf, MAX_FW_SIZE);
kfree(fwbuf);
return ret;
} else {
if (copy_from_user(&data, argp, sizeof(struct scu_ipc_data)))
return -EFAULT;
ret = scu_reg_access(cmd, &data);
if (ret < 0)
return ret;
if (copy_to_user(argp, &data, sizeof(struct scu_ipc_data)))
return -EFAULT;
return 0;
}
}
static const struct file_operations scu_ipc_fops = {
.unlocked_ioctl = scu_ipc_ioctl,
};
static int __init ipc_module_init(void)
{
return register_chrdev(0, "intel_mid_scu", &scu_ipc_fops);
}
static void __exit ipc_module_exit(void)
{
unregister_chrdev(major, "intel_mid_scu");
}
module_init(ipc_module_init);
module_exit(ipc_module_exit);
MODULE_LICENSE("GPL V2");
MODULE_DESCRIPTION("Utility driver for intel scu ipc");
MODULE_AUTHOR("Sreedhara <sreedhara.ds@intel.com>");
...@@ -235,6 +235,7 @@ static int sony_laptop_input_index[] = { ...@@ -235,6 +235,7 @@ static int sony_laptop_input_index[] = {
57, /* 70 SONYPI_EVENT_VOLUME_DEC_PRESSED */ 57, /* 70 SONYPI_EVENT_VOLUME_DEC_PRESSED */
-1, /* 71 SONYPI_EVENT_BRIGHTNESS_PRESSED */ -1, /* 71 SONYPI_EVENT_BRIGHTNESS_PRESSED */
58, /* 72 SONYPI_EVENT_MEDIA_PRESSED */ 58, /* 72 SONYPI_EVENT_MEDIA_PRESSED */
59, /* 72 SONYPI_EVENT_VENDOR_PRESSED */
}; };
static int sony_laptop_input_keycode_map[] = { static int sony_laptop_input_keycode_map[] = {
...@@ -297,6 +298,7 @@ static int sony_laptop_input_keycode_map[] = { ...@@ -297,6 +298,7 @@ static int sony_laptop_input_keycode_map[] = {
KEY_VOLUMEUP, /* 56 SONYPI_EVENT_VOLUME_INC_PRESSED */ KEY_VOLUMEUP, /* 56 SONYPI_EVENT_VOLUME_INC_PRESSED */
KEY_VOLUMEDOWN, /* 57 SONYPI_EVENT_VOLUME_DEC_PRESSED */ KEY_VOLUMEDOWN, /* 57 SONYPI_EVENT_VOLUME_DEC_PRESSED */
KEY_MEDIA, /* 58 SONYPI_EVENT_MEDIA_PRESSED */ KEY_MEDIA, /* 58 SONYPI_EVENT_MEDIA_PRESSED */
KEY_VENDOR, /* 59 SONYPI_EVENT_VENDOR_PRESSED */
}; };
/* release buttons after a short delay if pressed */ /* release buttons after a short delay if pressed */
...@@ -894,10 +896,18 @@ static struct sony_nc_event sony_100_events[] = { ...@@ -894,10 +896,18 @@ static struct sony_nc_event sony_100_events[] = {
{ 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 },
{ 0x9d, SONYPI_EVENT_ZOOM_PRESSED },
{ 0x1d, SONYPI_EVENT_ANYBUTTON_RELEASED },
{ 0x9f, SONYPI_EVENT_CD_EJECT_PRESSED }, { 0x9f, SONYPI_EVENT_CD_EJECT_PRESSED },
{ 0x1f, SONYPI_EVENT_ANYBUTTON_RELEASED }, { 0x1f, SONYPI_EVENT_ANYBUTTON_RELEASED },
{ 0xa1, SONYPI_EVENT_MEDIA_PRESSED }, { 0xa1, SONYPI_EVENT_MEDIA_PRESSED },
{ 0x21, SONYPI_EVENT_ANYBUTTON_RELEASED }, { 0x21, SONYPI_EVENT_ANYBUTTON_RELEASED },
{ 0xa4, SONYPI_EVENT_CD_EJECT_PRESSED },
{ 0x24, SONYPI_EVENT_ANYBUTTON_RELEASED },
{ 0xa5, SONYPI_EVENT_VENDOR_PRESSED },
{ 0x25, SONYPI_EVENT_ANYBUTTON_RELEASED },
{ 0xa6, SONYPI_EVENT_HELP_PRESSED },
{ 0x26, SONYPI_EVENT_ANYBUTTON_RELEASED },
{ 0, 0 }, { 0, 0 },
}; };
...@@ -1131,7 +1141,7 @@ static int sony_nc_setup_rfkill(struct acpi_device *device, ...@@ -1131,7 +1141,7 @@ static int sony_nc_setup_rfkill(struct acpi_device *device,
return err; return err;
} }
static void sony_nc_rfkill_update() static void sony_nc_rfkill_update(void)
{ {
enum sony_nc_rfkill i; enum sony_nc_rfkill i;
int result; int result;
......
...@@ -589,6 +589,7 @@ static int acpi_evalf(acpi_handle handle, ...@@ -589,6 +589,7 @@ static int acpi_evalf(acpi_handle handle,
default: default:
printk(TPACPI_ERR "acpi_evalf() called " printk(TPACPI_ERR "acpi_evalf() called "
"with invalid format character '%c'\n", c); "with invalid format character '%c'\n", c);
va_end(ap);
return 0; return 0;
} }
} }
...@@ -6345,7 +6346,7 @@ static int __init brightness_init(struct ibm_init_struct *iibm) ...@@ -6345,7 +6346,7 @@ static int __init brightness_init(struct ibm_init_struct *iibm)
"as change notification\n"); "as change notification\n");
tpacpi_hotkey_driver_mask_set(hotkey_driver_mask tpacpi_hotkey_driver_mask_set(hotkey_driver_mask
| TP_ACPI_HKEY_BRGHTUP_MASK | TP_ACPI_HKEY_BRGHTUP_MASK
| TP_ACPI_HKEY_BRGHTDWN_MASK);; | TP_ACPI_HKEY_BRGHTDWN_MASK);
return 0; return 0;
} }
......
...@@ -549,21 +549,34 @@ acpi_status wmi_install_notify_handler(const char *guid, ...@@ -549,21 +549,34 @@ acpi_status wmi_install_notify_handler(const char *guid,
wmi_notify_handler handler, void *data) wmi_notify_handler handler, void *data)
{ {
struct wmi_block *block; struct wmi_block *block;
acpi_status status; acpi_status status = AE_NOT_EXIST;
char tmp[16], guid_input[16];
struct list_head *p;
if (!guid || !handler) if (!guid || !handler)
return AE_BAD_PARAMETER; return AE_BAD_PARAMETER;
if (!find_guid(guid, &block)) wmi_parse_guid(guid, tmp);
return AE_NOT_EXIST; wmi_swap_bytes(tmp, guid_input);
if (block->handler && block->handler != wmi_notify_debug) list_for_each(p, &wmi_block_list) {
return AE_ALREADY_ACQUIRED; acpi_status wmi_status;
block = list_entry(p, struct wmi_block, list);
block->handler = handler; if (memcmp(block->gblock.guid, guid_input, 16) == 0) {
block->handler_data = data; if (block->handler &&
block->handler != wmi_notify_debug)
return AE_ALREADY_ACQUIRED;
status = wmi_method_enable(block, 1); block->handler = handler;
block->handler_data = data;
wmi_status = wmi_method_enable(block, 1);
if ((wmi_status != AE_OK) ||
((wmi_status == AE_OK) && (status == AE_NOT_EXIST)))
status = wmi_status;
}
}
return status; return status;
} }
...@@ -577,24 +590,40 @@ EXPORT_SYMBOL_GPL(wmi_install_notify_handler); ...@@ -577,24 +590,40 @@ EXPORT_SYMBOL_GPL(wmi_install_notify_handler);
acpi_status wmi_remove_notify_handler(const char *guid) acpi_status wmi_remove_notify_handler(const char *guid)
{ {
struct wmi_block *block; struct wmi_block *block;
acpi_status status = AE_OK; acpi_status status = AE_NOT_EXIST;
char tmp[16], guid_input[16];
struct list_head *p;
if (!guid) if (!guid)
return AE_BAD_PARAMETER; return AE_BAD_PARAMETER;
if (!find_guid(guid, &block)) wmi_parse_guid(guid, tmp);
return AE_NOT_EXIST; wmi_swap_bytes(tmp, guid_input);
if (!block->handler || block->handler == wmi_notify_debug) list_for_each(p, &wmi_block_list) {
return AE_NULL_ENTRY; acpi_status wmi_status;
block = list_entry(p, struct wmi_block, list);
if (debug_event) { if (memcmp(block->gblock.guid, guid_input, 16) == 0) {
block->handler = wmi_notify_debug; if (!block->handler ||
} else { block->handler == wmi_notify_debug)
status = wmi_method_enable(block, 0); return AE_NULL_ENTRY;
block->handler = NULL;
block->handler_data = NULL; if (debug_event) {
block->handler = wmi_notify_debug;
status = AE_OK;
} else {
wmi_status = wmi_method_enable(block, 0);
block->handler = NULL;
block->handler_data = NULL;
if ((wmi_status != AE_OK) ||
((wmi_status == AE_OK) &&
(status == AE_NOT_EXIST)))
status = wmi_status;
}
}
} }
return status; return status;
} }
EXPORT_SYMBOL_GPL(wmi_remove_notify_handler); EXPORT_SYMBOL_GPL(wmi_remove_notify_handler);
...@@ -705,22 +734,11 @@ static struct class wmi_class = { ...@@ -705,22 +734,11 @@ static struct class wmi_class = {
.dev_attrs = wmi_dev_attrs, .dev_attrs = wmi_dev_attrs,
}; };
static struct wmi_block *wmi_create_device(const struct guid_block *gblock, static int wmi_create_device(const struct guid_block *gblock,
acpi_handle handle) struct wmi_block *wblock, acpi_handle handle)
{ {
struct wmi_block *wblock;
int error;
char guid_string[37]; char guid_string[37];
wblock = kzalloc(sizeof(struct wmi_block), GFP_KERNEL);
if (!wblock) {
error = -ENOMEM;
goto err_out;
}
wblock->handle = handle;
wblock->gblock = *gblock;
wblock->dev.class = &wmi_class; wblock->dev.class = &wmi_class;
wmi_gtoa(gblock->guid, guid_string); wmi_gtoa(gblock->guid, guid_string);
...@@ -728,17 +746,7 @@ static struct wmi_block *wmi_create_device(const struct guid_block *gblock, ...@@ -728,17 +746,7 @@ static struct wmi_block *wmi_create_device(const struct guid_block *gblock,
dev_set_drvdata(&wblock->dev, wblock); dev_set_drvdata(&wblock->dev, wblock);
error = device_register(&wblock->dev); return device_register(&wblock->dev);
if (error)
goto err_free;
list_add_tail(&wblock->list, &wmi_block_list);
return wblock;
err_free:
kfree(wblock);
err_out:
return ERR_PTR(error);
} }
static void wmi_free_devices(void) static void wmi_free_devices(void)
...@@ -747,7 +755,8 @@ static void wmi_free_devices(void) ...@@ -747,7 +755,8 @@ static void wmi_free_devices(void)
/* Delete devices for all the GUIDs */ /* Delete devices for all the GUIDs */
list_for_each_entry_safe(wblock, next, &wmi_block_list, list) list_for_each_entry_safe(wblock, next, &wmi_block_list, list)
device_unregister(&wblock->dev); if (wblock->dev.class)
device_unregister(&wblock->dev);
} }
static bool guid_already_parsed(const char *guid_string) static bool guid_already_parsed(const char *guid_string)
...@@ -770,7 +779,6 @@ static acpi_status parse_wdg(acpi_handle handle) ...@@ -770,7 +779,6 @@ static acpi_status parse_wdg(acpi_handle handle)
union acpi_object *obj; union acpi_object *obj;
const struct guid_block *gblock; const struct guid_block *gblock;
struct wmi_block *wblock; struct wmi_block *wblock;
char guid_string[37];
acpi_status status; acpi_status status;
int retval; int retval;
u32 i, total; u32 i, total;
...@@ -792,28 +800,31 @@ static acpi_status parse_wdg(acpi_handle handle) ...@@ -792,28 +800,31 @@ static acpi_status parse_wdg(acpi_handle handle)
total = obj->buffer.length / sizeof(struct guid_block); total = obj->buffer.length / sizeof(struct guid_block);
for (i = 0; i < total; i++) { for (i = 0; i < total; i++) {
if (debug_dump_wdg)
wmi_dump_wdg(&gblock[i]);
wblock = kzalloc(sizeof(struct wmi_block), GFP_KERNEL);
if (!wblock)
return AE_NO_MEMORY;
wblock->handle = handle;
wblock->gblock = gblock[i];
/* /*
Some WMI devices, like those for nVidia hooks, have a Some WMI devices, like those for nVidia hooks, have a
duplicate GUID. It's not clear what we should do in this duplicate GUID. It's not clear what we should do in this
case yet, so for now, we'll just ignore the duplicate. case yet, so for now, we'll just ignore the duplicate
Anyone who wants to add support for that device can come for device creation.
up with a better workaround for the mess then.
*/ */
if (guid_already_parsed(gblock[i].guid) == true) { if (!guid_already_parsed(gblock[i].guid)) {
wmi_gtoa(gblock[i].guid, guid_string); retval = wmi_create_device(&gblock[i], wblock, handle);
pr_info("Skipping duplicate GUID %s\n", guid_string); if (retval) {
continue; wmi_free_devices();
goto out_free_pointer;
}
} }
if (debug_dump_wdg) list_add_tail(&wblock->list, &wmi_block_list);
wmi_dump_wdg(&gblock[i]);
wblock = wmi_create_device(&gblock[i], handle);
if (IS_ERR(wblock)) {
retval = PTR_ERR(wblock);
wmi_free_devices();
break;
}
if (debug_event) { if (debug_event) {
wblock->handler = wmi_notify_debug; wblock->handler = wmi_notify_debug;
......
...@@ -112,6 +112,7 @@ ...@@ -112,6 +112,7 @@
#define SONYPI_EVENT_VOLUME_DEC_PRESSED 70 #define SONYPI_EVENT_VOLUME_DEC_PRESSED 70
#define SONYPI_EVENT_BRIGHTNESS_PRESSED 71 #define SONYPI_EVENT_BRIGHTNESS_PRESSED 71
#define SONYPI_EVENT_MEDIA_PRESSED 72 #define SONYPI_EVENT_MEDIA_PRESSED 72
#define SONYPI_EVENT_VENDOR_PRESSED 73
/* get/set brightness */ /* get/set brightness */
#define SONYPI_IOCGBRT _IOR('v', 0, __u8) #define SONYPI_IOCGBRT _IOR('v', 0, __u8)
......
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