提交 17e8d03c 编写于 作者: R Rafael J. Wysocki

Merge back earlier 'acpi-assorted' material.

...@@ -745,7 +745,7 @@ static int __init acpi_parse_sbf(struct acpi_table_header *table) ...@@ -745,7 +745,7 @@ static int __init acpi_parse_sbf(struct acpi_table_header *table)
#ifdef CONFIG_HPET_TIMER #ifdef CONFIG_HPET_TIMER
#include <asm/hpet.h> #include <asm/hpet.h>
static struct __initdata resource *hpet_res; static struct resource *hpet_res __initdata;
static int __init acpi_parse_hpet(struct acpi_table_header *table) static int __init acpi_parse_hpet(struct acpi_table_header *table)
{ {
......
...@@ -30,10 +30,7 @@ ...@@ -30,10 +30,7 @@
#include <linux/types.h> #include <linux/types.h>
#include <linux/dmi.h> #include <linux/dmi.h>
#include <linux/delay.h> #include <linux/delay.h>
#ifdef CONFIG_ACPI_PROCFS_POWER #include <linux/platform_device.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#endif
#include <linux/power_supply.h> #include <linux/power_supply.h>
#include <acpi/acpi_bus.h> #include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h> #include <acpi/acpi_drivers.h>
...@@ -55,75 +52,30 @@ MODULE_AUTHOR("Paul Diefenbaugh"); ...@@ -55,75 +52,30 @@ MODULE_AUTHOR("Paul Diefenbaugh");
MODULE_DESCRIPTION("ACPI AC Adapter Driver"); MODULE_DESCRIPTION("ACPI AC Adapter Driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
#ifdef CONFIG_ACPI_PROCFS_POWER
extern struct proc_dir_entry *acpi_lock_ac_dir(void);
extern void *acpi_unlock_ac_dir(struct proc_dir_entry *acpi_ac_dir);
static int acpi_ac_open_fs(struct inode *inode, struct file *file);
#endif
static int acpi_ac_add(struct acpi_device *device);
static int acpi_ac_remove(struct acpi_device *device);
static void acpi_ac_notify(struct acpi_device *device, u32 event);
static const struct acpi_device_id ac_device_ids[] = {
{"ACPI0003", 0},
{"", 0},
};
MODULE_DEVICE_TABLE(acpi, ac_device_ids);
#ifdef CONFIG_PM_SLEEP
static int acpi_ac_resume(struct device *dev);
#endif
static SIMPLE_DEV_PM_OPS(acpi_ac_pm, NULL, acpi_ac_resume);
static int ac_sleep_before_get_state_ms; static int ac_sleep_before_get_state_ms;
static struct acpi_driver acpi_ac_driver = {
.name = "ac",
.class = ACPI_AC_CLASS,
.ids = ac_device_ids,
.flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS,
.ops = {
.add = acpi_ac_add,
.remove = acpi_ac_remove,
.notify = acpi_ac_notify,
},
.drv.pm = &acpi_ac_pm,
};
struct acpi_ac { struct acpi_ac {
struct power_supply charger; struct power_supply charger;
struct acpi_device * device; struct acpi_device *adev;
struct platform_device *pdev;
unsigned long long state; unsigned long long state;
}; };
#define to_acpi_ac(x) container_of(x, struct acpi_ac, charger) #define to_acpi_ac(x) container_of(x, struct acpi_ac, charger)
#ifdef CONFIG_ACPI_PROCFS_POWER
static const struct file_operations acpi_ac_fops = {
.owner = THIS_MODULE,
.open = acpi_ac_open_fs,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
#endif
/* -------------------------------------------------------------------------- /* --------------------------------------------------------------------------
AC Adapter Management AC Adapter Management
-------------------------------------------------------------------------- */ -------------------------------------------------------------------------- */
static int acpi_ac_get_state(struct acpi_ac *ac) static int acpi_ac_get_state(struct acpi_ac *ac)
{ {
acpi_status status = AE_OK; acpi_status status;
status = acpi_evaluate_integer(ac->adev->handle, "_PSR", NULL,
if (!ac) &ac->state);
return -EINVAL;
status = acpi_evaluate_integer(ac->device->handle, "_PSR", NULL, &ac->state);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, status, "Error reading AC Adapter state")); ACPI_EXCEPTION((AE_INFO, status,
"Error reading AC Adapter state"));
ac->state = ACPI_AC_STATUS_UNKNOWN; ac->state = ACPI_AC_STATUS_UNKNOWN;
return -ENODEV; return -ENODEV;
} }
...@@ -160,91 +112,13 @@ static enum power_supply_property ac_props[] = { ...@@ -160,91 +112,13 @@ static enum power_supply_property ac_props[] = {
POWER_SUPPLY_PROP_ONLINE, POWER_SUPPLY_PROP_ONLINE,
}; };
#ifdef CONFIG_ACPI_PROCFS_POWER
/* --------------------------------------------------------------------------
FS Interface (/proc)
-------------------------------------------------------------------------- */
static struct proc_dir_entry *acpi_ac_dir;
static int acpi_ac_seq_show(struct seq_file *seq, void *offset)
{
struct acpi_ac *ac = seq->private;
if (!ac)
return 0;
if (acpi_ac_get_state(ac)) {
seq_puts(seq, "ERROR: Unable to read AC Adapter state\n");
return 0;
}
seq_puts(seq, "state: ");
switch (ac->state) {
case ACPI_AC_STATUS_OFFLINE:
seq_puts(seq, "off-line\n");
break;
case ACPI_AC_STATUS_ONLINE:
seq_puts(seq, "on-line\n");
break;
default:
seq_puts(seq, "unknown\n");
break;
}
return 0;
}
static int acpi_ac_open_fs(struct inode *inode, struct file *file)
{
return single_open(file, acpi_ac_seq_show, PDE_DATA(inode));
}
static int acpi_ac_add_fs(struct acpi_device *device)
{
struct proc_dir_entry *entry = NULL;
printk(KERN_WARNING PREFIX "Deprecated procfs I/F for AC is loaded,"
" please retry with CONFIG_ACPI_PROCFS_POWER cleared\n");
if (!acpi_device_dir(device)) {
acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
acpi_ac_dir);
if (!acpi_device_dir(device))
return -ENODEV;
}
/* 'state' [R] */
entry = proc_create_data(ACPI_AC_FILE_STATE,
S_IRUGO, acpi_device_dir(device),
&acpi_ac_fops, acpi_driver_data(device));
if (!entry)
return -ENODEV;
return 0;
}
static int acpi_ac_remove_fs(struct acpi_device *device)
{
if (acpi_device_dir(device)) {
remove_proc_entry(ACPI_AC_FILE_STATE, acpi_device_dir(device));
remove_proc_entry(acpi_device_bid(device), acpi_ac_dir);
acpi_device_dir(device) = NULL;
}
return 0;
}
#endif
/* -------------------------------------------------------------------------- /* --------------------------------------------------------------------------
Driver Model Driver Model
-------------------------------------------------------------------------- */ -------------------------------------------------------------------------- */
static void acpi_ac_notify(struct acpi_device *device, u32 event) static void acpi_ac_notify_handler(acpi_handle handle, u32 event, void *data)
{ {
struct acpi_ac *ac = acpi_driver_data(device); struct acpi_ac *ac = data;
if (!ac) if (!ac)
return; return;
...@@ -267,10 +141,10 @@ static void acpi_ac_notify(struct acpi_device *device, u32 event) ...@@ -267,10 +141,10 @@ static void acpi_ac_notify(struct acpi_device *device, u32 event)
msleep(ac_sleep_before_get_state_ms); msleep(ac_sleep_before_get_state_ms);
acpi_ac_get_state(ac); acpi_ac_get_state(ac);
acpi_bus_generate_netlink_event(device->pnp.device_class, acpi_bus_generate_netlink_event(ac->adev->pnp.device_class,
dev_name(&device->dev), event, dev_name(&ac->pdev->dev),
(u32) ac->state); event, (u32) ac->state);
acpi_notifier_call_chain(device, event, (u32) ac->state); acpi_notifier_call_chain(ac->adev, event, (u32) ac->state);
kobject_uevent(&ac->charger.dev->kobj, KOBJ_CHANGE); kobject_uevent(&ac->charger.dev->kobj, KOBJ_CHANGE);
} }
...@@ -295,53 +169,55 @@ static struct dmi_system_id ac_dmi_table[] = { ...@@ -295,53 +169,55 @@ static struct dmi_system_id ac_dmi_table[] = {
{}, {},
}; };
static int acpi_ac_add(struct acpi_device *device) static int acpi_ac_probe(struct platform_device *pdev)
{ {
int result = 0; int result = 0;
struct acpi_ac *ac = NULL; struct acpi_ac *ac = NULL;
struct acpi_device *adev;
if (!pdev)
if (!device)
return -EINVAL; return -EINVAL;
result = acpi_bus_get_device(ACPI_HANDLE(&pdev->dev), &adev);
if (result)
return -ENODEV;
ac = kzalloc(sizeof(struct acpi_ac), GFP_KERNEL); ac = kzalloc(sizeof(struct acpi_ac), GFP_KERNEL);
if (!ac) if (!ac)
return -ENOMEM; return -ENOMEM;
ac->device = device; strcpy(acpi_device_name(adev), ACPI_AC_DEVICE_NAME);
strcpy(acpi_device_name(device), ACPI_AC_DEVICE_NAME); strcpy(acpi_device_class(adev), ACPI_AC_CLASS);
strcpy(acpi_device_class(device), ACPI_AC_CLASS); ac->adev = adev;
device->driver_data = ac; ac->pdev = pdev;
platform_set_drvdata(pdev, ac);
result = acpi_ac_get_state(ac); result = acpi_ac_get_state(ac);
if (result) if (result)
goto end; goto end;
#ifdef CONFIG_ACPI_PROCFS_POWER ac->charger.name = acpi_device_bid(adev);
result = acpi_ac_add_fs(device);
#endif
if (result)
goto end;
ac->charger.name = acpi_device_bid(device);
ac->charger.type = POWER_SUPPLY_TYPE_MAINS; ac->charger.type = POWER_SUPPLY_TYPE_MAINS;
ac->charger.properties = ac_props; ac->charger.properties = ac_props;
ac->charger.num_properties = ARRAY_SIZE(ac_props); ac->charger.num_properties = ARRAY_SIZE(ac_props);
ac->charger.get_property = get_ac_property; ac->charger.get_property = get_ac_property;
result = power_supply_register(&ac->device->dev, &ac->charger); result = power_supply_register(&pdev->dev, &ac->charger);
if (result) if (result)
goto end; goto end;
result = acpi_install_notify_handler(ACPI_HANDLE(&pdev->dev),
ACPI_DEVICE_NOTIFY, acpi_ac_notify_handler, ac);
if (result) {
power_supply_unregister(&ac->charger);
goto end;
}
printk(KERN_INFO PREFIX "%s [%s] (%s)\n", printk(KERN_INFO PREFIX "%s [%s] (%s)\n",
acpi_device_name(device), acpi_device_bid(device), acpi_device_name(adev), acpi_device_bid(adev),
ac->state ? "on-line" : "off-line"); ac->state ? "on-line" : "off-line");
end: end:
if (result) { if (result)
#ifdef CONFIG_ACPI_PROCFS_POWER
acpi_ac_remove_fs(device);
#endif
kfree(ac); kfree(ac);
}
dmi_check_system(ac_dmi_table); dmi_check_system(ac_dmi_table);
return result; return result;
...@@ -356,7 +232,7 @@ static int acpi_ac_resume(struct device *dev) ...@@ -356,7 +232,7 @@ static int acpi_ac_resume(struct device *dev)
if (!dev) if (!dev)
return -EINVAL; return -EINVAL;
ac = acpi_driver_data(to_acpi_device(dev)); ac = platform_get_drvdata(to_platform_device(dev));
if (!ac) if (!ac)
return -EINVAL; return -EINVAL;
...@@ -368,28 +244,44 @@ static int acpi_ac_resume(struct device *dev) ...@@ -368,28 +244,44 @@ static int acpi_ac_resume(struct device *dev)
return 0; return 0;
} }
#endif #endif
static SIMPLE_DEV_PM_OPS(acpi_ac_pm_ops, NULL, acpi_ac_resume);
static int acpi_ac_remove(struct acpi_device *device) static int acpi_ac_remove(struct platform_device *pdev)
{ {
struct acpi_ac *ac = NULL; struct acpi_ac *ac;
if (!device || !acpi_driver_data(device)) if (!pdev)
return -EINVAL; return -EINVAL;
ac = acpi_driver_data(device); acpi_remove_notify_handler(ACPI_HANDLE(&pdev->dev),
ACPI_DEVICE_NOTIFY, acpi_ac_notify_handler);
ac = platform_get_drvdata(pdev);
if (ac->charger.dev) if (ac->charger.dev)
power_supply_unregister(&ac->charger); power_supply_unregister(&ac->charger);
#ifdef CONFIG_ACPI_PROCFS_POWER
acpi_ac_remove_fs(device);
#endif
kfree(ac); kfree(ac);
return 0; return 0;
} }
static const struct acpi_device_id acpi_ac_match[] = {
{ "ACPI0003", 0 },
{ }
};
MODULE_DEVICE_TABLE(acpi, acpi_ac_match);
static struct platform_driver acpi_ac_driver = {
.probe = acpi_ac_probe,
.remove = acpi_ac_remove,
.driver = {
.name = "acpi-ac",
.owner = THIS_MODULE,
.pm = &acpi_ac_pm_ops,
.acpi_match_table = ACPI_PTR(acpi_ac_match),
},
};
static int __init acpi_ac_init(void) static int __init acpi_ac_init(void)
{ {
int result; int result;
...@@ -397,34 +289,16 @@ static int __init acpi_ac_init(void) ...@@ -397,34 +289,16 @@ static int __init acpi_ac_init(void)
if (acpi_disabled) if (acpi_disabled)
return -ENODEV; return -ENODEV;
#ifdef CONFIG_ACPI_PROCFS_POWER result = platform_driver_register(&acpi_ac_driver);
acpi_ac_dir = acpi_lock_ac_dir(); if (result < 0)
if (!acpi_ac_dir)
return -ENODEV;
#endif
result = acpi_bus_register_driver(&acpi_ac_driver);
if (result < 0) {
#ifdef CONFIG_ACPI_PROCFS_POWER
acpi_unlock_ac_dir(acpi_ac_dir);
#endif
return -ENODEV; return -ENODEV;
}
return 0; return 0;
} }
static void __exit acpi_ac_exit(void) static void __exit acpi_ac_exit(void)
{ {
platform_driver_unregister(&acpi_ac_driver);
acpi_bus_unregister_driver(&acpi_ac_driver);
#ifdef CONFIG_ACPI_PROCFS_POWER
acpi_unlock_ac_dir(acpi_ac_dir);
#endif
return;
} }
module_init(acpi_ac_init); module_init(acpi_ac_init);
module_exit(acpi_ac_exit); module_exit(acpi_ac_exit);
...@@ -30,6 +30,7 @@ ACPI_MODULE_NAME("acpi_lpss"); ...@@ -30,6 +30,7 @@ ACPI_MODULE_NAME("acpi_lpss");
/* Offsets relative to LPSS_PRIVATE_OFFSET */ /* Offsets relative to LPSS_PRIVATE_OFFSET */
#define LPSS_GENERAL 0x08 #define LPSS_GENERAL 0x08
#define LPSS_GENERAL_LTR_MODE_SW BIT(2) #define LPSS_GENERAL_LTR_MODE_SW BIT(2)
#define LPSS_GENERAL_UART_RTS_OVRD BIT(3)
#define LPSS_SW_LTR 0x10 #define LPSS_SW_LTR 0x10
#define LPSS_AUTO_LTR 0x14 #define LPSS_AUTO_LTR 0x14
#define LPSS_TX_INT 0x20 #define LPSS_TX_INT 0x20
...@@ -68,11 +69,16 @@ struct lpss_private_data { ...@@ -68,11 +69,16 @@ struct lpss_private_data {
static void lpss_uart_setup(struct lpss_private_data *pdata) static void lpss_uart_setup(struct lpss_private_data *pdata)
{ {
unsigned int tx_int_offset = pdata->dev_desc->prv_offset + LPSS_TX_INT; unsigned int offset;
u32 reg; u32 reg;
reg = readl(pdata->mmio_base + tx_int_offset); offset = pdata->dev_desc->prv_offset + LPSS_TX_INT;
writel(reg | LPSS_TX_INT_MASK, pdata->mmio_base + tx_int_offset); reg = readl(pdata->mmio_base + offset);
writel(reg | LPSS_TX_INT_MASK, pdata->mmio_base + offset);
offset = pdata->dev_desc->prv_offset + LPSS_GENERAL;
reg = readl(pdata->mmio_base + offset);
writel(reg | LPSS_GENERAL_UART_RTS_OVRD, pdata->mmio_base + offset);
} }
static struct lpss_device_desc lpt_dev_desc = { static struct lpss_device_desc lpt_dev_desc = {
......
...@@ -29,6 +29,13 @@ ACPI_MODULE_NAME("platform"); ...@@ -29,6 +29,13 @@ ACPI_MODULE_NAME("platform");
static const struct acpi_device_id acpi_platform_device_ids[] = { static const struct acpi_device_id acpi_platform_device_ids[] = {
{ "PNP0D40" }, { "PNP0D40" },
{ "ACPI0003" },
{ "VPC2004" },
{ "BCM4752" },
/* Intel Smart Sound Technology */
{ "INT33C8" },
{ "80860F28" },
{ } { }
}; };
......
...@@ -383,18 +383,15 @@ static int acpi_button_add(struct acpi_device *device) ...@@ -383,18 +383,15 @@ static int acpi_button_add(struct acpi_device *device)
switch (button->type) { switch (button->type) {
case ACPI_BUTTON_TYPE_POWER: case ACPI_BUTTON_TYPE_POWER:
input->evbit[0] = BIT_MASK(EV_KEY); input_set_capability(input, EV_KEY, KEY_POWER);
set_bit(KEY_POWER, input->keybit);
break; break;
case ACPI_BUTTON_TYPE_SLEEP: case ACPI_BUTTON_TYPE_SLEEP:
input->evbit[0] = BIT_MASK(EV_KEY); input_set_capability(input, EV_KEY, KEY_SLEEP);
set_bit(KEY_SLEEP, input->keybit);
break; break;
case ACPI_BUTTON_TYPE_LID: case ACPI_BUTTON_TYPE_LID:
input->evbit[0] = BIT_MASK(EV_SW); input_set_capability(input, EV_SW, SW_LID);
set_bit(SW_LID, input->swbit);
break; break;
} }
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
/* Uncomment next line to get verbose printout */ /* Uncomment next line to get verbose printout */
/* #define DEBUG */ /* #define DEBUG */
#define pr_fmt(fmt) "ACPI : EC: " fmt
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
...@@ -49,9 +50,6 @@ ...@@ -49,9 +50,6 @@
#define ACPI_EC_DEVICE_NAME "Embedded Controller" #define ACPI_EC_DEVICE_NAME "Embedded Controller"
#define ACPI_EC_FILE_INFO "info" #define ACPI_EC_FILE_INFO "info"
#undef PREFIX
#define PREFIX "ACPI: EC: "
/* EC status register */ /* EC status register */
#define ACPI_EC_FLAG_OBF 0x01 /* Output buffer full */ #define ACPI_EC_FLAG_OBF 0x01 /* Output buffer full */
#define ACPI_EC_FLAG_IBF 0x02 /* Input buffer full */ #define ACPI_EC_FLAG_IBF 0x02 /* Input buffer full */
...@@ -131,26 +129,26 @@ static int EC_FLAGS_SKIP_DSDT_SCAN; /* Not all BIOS survive early DSDT scan */ ...@@ -131,26 +129,26 @@ static int EC_FLAGS_SKIP_DSDT_SCAN; /* Not all BIOS survive early DSDT scan */
static inline u8 acpi_ec_read_status(struct acpi_ec *ec) static inline u8 acpi_ec_read_status(struct acpi_ec *ec)
{ {
u8 x = inb(ec->command_addr); u8 x = inb(ec->command_addr);
pr_debug(PREFIX "---> status = 0x%2.2x\n", x); pr_debug("---> status = 0x%2.2x\n", x);
return x; return x;
} }
static inline u8 acpi_ec_read_data(struct acpi_ec *ec) static inline u8 acpi_ec_read_data(struct acpi_ec *ec)
{ {
u8 x = inb(ec->data_addr); u8 x = inb(ec->data_addr);
pr_debug(PREFIX "---> data = 0x%2.2x\n", x); pr_debug("---> data = 0x%2.2x\n", x);
return x; return x;
} }
static inline void acpi_ec_write_cmd(struct acpi_ec *ec, u8 command) static inline void acpi_ec_write_cmd(struct acpi_ec *ec, u8 command)
{ {
pr_debug(PREFIX "<--- command = 0x%2.2x\n", command); pr_debug("<--- command = 0x%2.2x\n", command);
outb(command, ec->command_addr); outb(command, ec->command_addr);
} }
static inline void acpi_ec_write_data(struct acpi_ec *ec, u8 data) static inline void acpi_ec_write_data(struct acpi_ec *ec, u8 data)
{ {
pr_debug(PREFIX "<--- data = 0x%2.2x\n", data); pr_debug("<--- data = 0x%2.2x\n", data);
outb(data, ec->data_addr); outb(data, ec->data_addr);
} }
...@@ -241,7 +239,7 @@ static int ec_poll(struct acpi_ec *ec) ...@@ -241,7 +239,7 @@ static int ec_poll(struct acpi_ec *ec)
} }
advance_transaction(ec, acpi_ec_read_status(ec)); advance_transaction(ec, acpi_ec_read_status(ec));
} while (time_before(jiffies, delay)); } while (time_before(jiffies, delay));
pr_debug(PREFIX "controller reset, restart transaction\n"); pr_debug("controller reset, restart transaction\n");
spin_lock_irqsave(&ec->lock, flags); spin_lock_irqsave(&ec->lock, flags);
start_transaction(ec); start_transaction(ec);
spin_unlock_irqrestore(&ec->lock, flags); spin_unlock_irqrestore(&ec->lock, flags);
...@@ -309,12 +307,12 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t) ...@@ -309,12 +307,12 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t)
} }
} }
if (ec_wait_ibf0(ec)) { if (ec_wait_ibf0(ec)) {
pr_err(PREFIX "input buffer is not empty, " pr_err("input buffer is not empty, "
"aborting transaction\n"); "aborting transaction\n");
status = -ETIME; status = -ETIME;
goto end; goto end;
} }
pr_debug(PREFIX "transaction start (cmd=0x%02x, addr=0x%02x)\n", pr_debug("transaction start (cmd=0x%02x, addr=0x%02x)\n",
t->command, t->wdata ? t->wdata[0] : 0); t->command, t->wdata ? t->wdata[0] : 0);
/* disable GPE during transaction if storm is detected */ /* disable GPE during transaction if storm is detected */
if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) { if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) {
...@@ -331,12 +329,12 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t) ...@@ -331,12 +329,12 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t)
/* It is safe to enable the GPE outside of the transaction. */ /* It is safe to enable the GPE outside of the transaction. */
acpi_enable_gpe(NULL, ec->gpe); acpi_enable_gpe(NULL, ec->gpe);
} else if (t->irq_count > ec_storm_threshold) { } else if (t->irq_count > ec_storm_threshold) {
pr_info(PREFIX "GPE storm detected(%d GPEs), " pr_info("GPE storm detected(%d GPEs), "
"transactions will use polling mode\n", "transactions will use polling mode\n",
t->irq_count); t->irq_count);
set_bit(EC_FLAGS_GPE_STORM, &ec->flags); set_bit(EC_FLAGS_GPE_STORM, &ec->flags);
} }
pr_debug(PREFIX "transaction end\n"); pr_debug("transaction end\n");
end: end:
if (ec->global_lock) if (ec->global_lock)
acpi_release_global_lock(glk); acpi_release_global_lock(glk);
...@@ -570,12 +568,12 @@ static void acpi_ec_run(void *cxt) ...@@ -570,12 +568,12 @@ static void acpi_ec_run(void *cxt)
struct acpi_ec_query_handler *handler = cxt; struct acpi_ec_query_handler *handler = cxt;
if (!handler) if (!handler)
return; return;
pr_debug(PREFIX "start query execution\n"); pr_debug("start query execution\n");
if (handler->func) if (handler->func)
handler->func(handler->data); handler->func(handler->data);
else if (handler->handle) else if (handler->handle)
acpi_evaluate_object(handler->handle, NULL, NULL, NULL); acpi_evaluate_object(handler->handle, NULL, NULL, NULL);
pr_debug(PREFIX "stop query execution\n"); pr_debug("stop query execution\n");
kfree(handler); kfree(handler);
} }
...@@ -593,7 +591,8 @@ static int acpi_ec_sync_query(struct acpi_ec *ec) ...@@ -593,7 +591,8 @@ static int acpi_ec_sync_query(struct acpi_ec *ec)
if (!copy) if (!copy)
return -ENOMEM; return -ENOMEM;
memcpy(copy, handler, sizeof(*copy)); memcpy(copy, handler, sizeof(*copy));
pr_debug(PREFIX "push query execution (0x%2x) on queue\n", value); pr_debug("push query execution (0x%2x) on queue\n",
value);
return acpi_os_execute((copy->func) ? return acpi_os_execute((copy->func) ?
OSL_NOTIFY_HANDLER : OSL_GPE_HANDLER, OSL_NOTIFY_HANDLER : OSL_GPE_HANDLER,
acpi_ec_run, copy); acpi_ec_run, copy);
...@@ -616,7 +615,7 @@ static int ec_check_sci(struct acpi_ec *ec, u8 state) ...@@ -616,7 +615,7 @@ static int ec_check_sci(struct acpi_ec *ec, u8 state)
{ {
if (state & ACPI_EC_FLAG_SCI) { if (state & ACPI_EC_FLAG_SCI) {
if (!test_and_set_bit(EC_FLAGS_QUERY_PENDING, &ec->flags)) { if (!test_and_set_bit(EC_FLAGS_QUERY_PENDING, &ec->flags)) {
pr_debug(PREFIX "push gpe query to the queue\n"); pr_debug("push gpe query to the queue\n");
return acpi_os_execute(OSL_NOTIFY_HANDLER, return acpi_os_execute(OSL_NOTIFY_HANDLER,
acpi_ec_gpe_query, ec); acpi_ec_gpe_query, ec);
} }
...@@ -630,7 +629,7 @@ static u32 acpi_ec_gpe_handler(acpi_handle gpe_device, ...@@ -630,7 +629,7 @@ static u32 acpi_ec_gpe_handler(acpi_handle gpe_device,
struct acpi_ec *ec = data; struct acpi_ec *ec = data;
u8 status = acpi_ec_read_status(ec); u8 status = acpi_ec_read_status(ec);
pr_debug(PREFIX "~~~> interrupt, status:0x%02x\n", status); pr_debug("~~~> interrupt, status:0x%02x\n", status);
advance_transaction(ec, status); advance_transaction(ec, status);
if (ec_transaction_done(ec) && if (ec_transaction_done(ec) &&
...@@ -776,7 +775,7 @@ static int ec_install_handlers(struct acpi_ec *ec) ...@@ -776,7 +775,7 @@ static int ec_install_handlers(struct acpi_ec *ec)
* The AE_NOT_FOUND error will be ignored and OS * The AE_NOT_FOUND error will be ignored and OS
* continue to initialize EC. * continue to initialize EC.
*/ */
printk(KERN_ERR "Fail in evaluating the _REG object" pr_err("Fail in evaluating the _REG object"
" of EC device. Broken bios is suspected.\n"); " of EC device. Broken bios is suspected.\n");
} else { } else {
acpi_remove_gpe_handler(NULL, ec->gpe, acpi_remove_gpe_handler(NULL, ec->gpe,
...@@ -795,10 +794,10 @@ static void ec_remove_handlers(struct acpi_ec *ec) ...@@ -795,10 +794,10 @@ static void ec_remove_handlers(struct acpi_ec *ec)
acpi_disable_gpe(NULL, ec->gpe); acpi_disable_gpe(NULL, ec->gpe);
if (ACPI_FAILURE(acpi_remove_address_space_handler(ec->handle, if (ACPI_FAILURE(acpi_remove_address_space_handler(ec->handle,
ACPI_ADR_SPACE_EC, &acpi_ec_space_handler))) ACPI_ADR_SPACE_EC, &acpi_ec_space_handler)))
pr_err(PREFIX "failed to remove space handler\n"); pr_err("failed to remove space handler\n");
if (ACPI_FAILURE(acpi_remove_gpe_handler(NULL, ec->gpe, if (ACPI_FAILURE(acpi_remove_gpe_handler(NULL, ec->gpe,
&acpi_ec_gpe_handler))) &acpi_ec_gpe_handler)))
pr_err(PREFIX "failed to remove gpe handler\n"); pr_err("failed to remove gpe handler\n");
clear_bit(EC_FLAGS_HANDLERS_INSTALLED, &ec->flags); clear_bit(EC_FLAGS_HANDLERS_INSTALLED, &ec->flags);
} }
...@@ -840,7 +839,7 @@ static int acpi_ec_add(struct acpi_device *device) ...@@ -840,7 +839,7 @@ static int acpi_ec_add(struct acpi_device *device)
ret = !!request_region(ec->command_addr, 1, "EC cmd"); ret = !!request_region(ec->command_addr, 1, "EC cmd");
WARN(!ret, "Could not request EC cmd io port 0x%lx", ec->command_addr); WARN(!ret, "Could not request EC cmd io port 0x%lx", ec->command_addr);
pr_info(PREFIX "GPE = 0x%lx, I/O: command/status = 0x%lx, data = 0x%lx\n", pr_info("GPE = 0x%lx, I/O: command/status = 0x%lx, data = 0x%lx\n",
ec->gpe, ec->command_addr, ec->data_addr); ec->gpe, ec->command_addr, ec->data_addr);
ret = ec_install_handlers(ec); ret = ec_install_handlers(ec);
...@@ -931,7 +930,7 @@ static int ec_validate_ecdt(const struct dmi_system_id *id) ...@@ -931,7 +930,7 @@ static int ec_validate_ecdt(const struct dmi_system_id *id)
/* MSI EC needs special treatment, enable it */ /* MSI EC needs special treatment, enable it */
static int ec_flag_msi(const struct dmi_system_id *id) static int ec_flag_msi(const struct dmi_system_id *id)
{ {
printk(KERN_DEBUG PREFIX "Detected MSI hardware, enabling workarounds.\n"); pr_debug("Detected MSI hardware, enabling workarounds.\n");
EC_FLAGS_MSI = 1; EC_FLAGS_MSI = 1;
EC_FLAGS_VALIDATE_ECDT = 1; EC_FLAGS_VALIDATE_ECDT = 1;
return 0; return 0;
...@@ -1010,7 +1009,7 @@ int __init acpi_ec_ecdt_probe(void) ...@@ -1010,7 +1009,7 @@ int __init acpi_ec_ecdt_probe(void)
status = acpi_get_table(ACPI_SIG_ECDT, 1, status = acpi_get_table(ACPI_SIG_ECDT, 1,
(struct acpi_table_header **)&ecdt_ptr); (struct acpi_table_header **)&ecdt_ptr);
if (ACPI_SUCCESS(status)) { if (ACPI_SUCCESS(status)) {
pr_info(PREFIX "EC description table is found, configuring boot EC\n"); pr_info("EC description table is found, configuring boot EC\n");
boot_ec->command_addr = ecdt_ptr->control.address; boot_ec->command_addr = ecdt_ptr->control.address;
boot_ec->data_addr = ecdt_ptr->data.address; boot_ec->data_addr = ecdt_ptr->data.address;
boot_ec->gpe = ecdt_ptr->gpe; boot_ec->gpe = ecdt_ptr->gpe;
...@@ -1030,7 +1029,7 @@ int __init acpi_ec_ecdt_probe(void) ...@@ -1030,7 +1029,7 @@ int __init acpi_ec_ecdt_probe(void)
/* This workaround is needed only on some broken machines, /* This workaround is needed only on some broken machines,
* which require early EC, but fail to provide ECDT */ * which require early EC, but fail to provide ECDT */
printk(KERN_DEBUG PREFIX "Look up EC in DSDT\n"); pr_debug("Look up EC in DSDT\n");
status = acpi_get_devices(ec_device_ids[0].id, ec_parse_device, status = acpi_get_devices(ec_device_ids[0].id, ec_parse_device,
boot_ec, NULL); boot_ec, NULL);
/* Check that acpi_get_devices actually find something */ /* Check that acpi_get_devices actually find something */
...@@ -1042,7 +1041,7 @@ int __init acpi_ec_ecdt_probe(void) ...@@ -1042,7 +1041,7 @@ int __init acpi_ec_ecdt_probe(void)
saved_ec->data_addr != boot_ec->data_addr || saved_ec->data_addr != boot_ec->data_addr ||
saved_ec->gpe != boot_ec->gpe || saved_ec->gpe != boot_ec->gpe ||
saved_ec->handle != boot_ec->handle) saved_ec->handle != boot_ec->handle)
pr_info(PREFIX "ASUSTek keeps feeding us with broken " pr_info("ASUSTek keeps feeding us with broken "
"ECDT tables, which are very hard to workaround. " "ECDT tables, which are very hard to workaround. "
"Trying to use DSDT EC info instead. Please send " "Trying to use DSDT EC info instead. Please send "
"output of acpidump to linux-acpi@vger.kernel.org\n"); "output of acpidump to linux-acpi@vger.kernel.org\n");
......
...@@ -820,7 +820,7 @@ acpi_status acpi_os_remove_interrupt_handler(u32 irq, acpi_osd_handler handler) ...@@ -820,7 +820,7 @@ acpi_status acpi_os_remove_interrupt_handler(u32 irq, acpi_osd_handler handler)
void acpi_os_sleep(u64 ms) void acpi_os_sleep(u64 ms)
{ {
schedule_timeout_interruptible(msecs_to_jiffies(ms)); msleep(ms);
} }
void acpi_os_stall(u32 us) void acpi_os_stall(u32 us)
...@@ -1335,7 +1335,7 @@ static int __init acpi_os_name_setup(char *str) ...@@ -1335,7 +1335,7 @@ static int __init acpi_os_name_setup(char *str)
if (!str || !*str) if (!str || !*str)
return 0; return 0;
for (; count-- && str && *str; str++) { for (; count-- && *str; str++) {
if (isalnum(*str) || *str == ' ' || *str == ':') if (isalnum(*str) || *str == ' ' || *str == ':')
*p++ = *str; *p++ = *str;
else if (*str == '\'' || *str == '"') else if (*str == '\'' || *str == '"')
......
...@@ -564,6 +564,7 @@ static ssize_t counter_set(struct kobject *kobj, ...@@ -564,6 +564,7 @@ static ssize_t counter_set(struct kobject *kobj,
acpi_event_status status; acpi_event_status status;
acpi_handle handle; acpi_handle handle;
int result = 0; int result = 0;
unsigned long tmp;
if (index == num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_SCI) { if (index == num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_SCI) {
int i; int i;
...@@ -596,8 +597,10 @@ static ssize_t counter_set(struct kobject *kobj, ...@@ -596,8 +597,10 @@ static ssize_t counter_set(struct kobject *kobj,
else if (!strcmp(buf, "clear\n") && else if (!strcmp(buf, "clear\n") &&
(status & ACPI_EVENT_FLAG_SET)) (status & ACPI_EVENT_FLAG_SET))
result = acpi_clear_gpe(handle, index); result = acpi_clear_gpe(handle, index);
else if (!kstrtoul(buf, 0, &tmp))
all_counters[index].count = tmp;
else else
all_counters[index].count = strtoul(buf, NULL, 0); result = -EINVAL;
} else if (index < num_gpes + ACPI_NUM_FIXED_EVENTS) { } else if (index < num_gpes + ACPI_NUM_FIXED_EVENTS) {
int event = index - num_gpes; int event = index - num_gpes;
if (!strcmp(buf, "disable\n") && if (!strcmp(buf, "disable\n") &&
...@@ -609,8 +612,10 @@ static ssize_t counter_set(struct kobject *kobj, ...@@ -609,8 +612,10 @@ static ssize_t counter_set(struct kobject *kobj,
else if (!strcmp(buf, "clear\n") && else if (!strcmp(buf, "clear\n") &&
(status & ACPI_EVENT_FLAG_SET)) (status & ACPI_EVENT_FLAG_SET))
result = acpi_clear_event(event); result = acpi_clear_event(event);
else if (!kstrtoul(buf, 0, &tmp))
all_counters[index].count = tmp;
else else
all_counters[index].count = strtoul(buf, NULL, 0); result = -EINVAL;
} else } else
all_counters[index].count = strtoul(buf, NULL, 0); all_counters[index].count = strtoul(buf, NULL, 0);
......
...@@ -299,8 +299,8 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag) ...@@ -299,8 +299,8 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
ACPI_DEBUG_PRINT((ACPI_DB_INFO, ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"No critical threshold\n")); "No critical threshold\n"));
} else if (tmp <= 2732) { } else if (tmp <= 2732) {
printk(KERN_WARNING FW_BUG "Invalid critical threshold " pr_warn(FW_BUG "Invalid critical threshold (%llu)\n",
"(%llu)\n", tmp); tmp);
tz->trips.critical.flags.valid = 0; tz->trips.critical.flags.valid = 0;
} else { } else {
tz->trips.critical.flags.valid = 1; tz->trips.critical.flags.valid = 1;
...@@ -317,8 +317,8 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag) ...@@ -317,8 +317,8 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
* Allow override critical threshold * Allow override critical threshold
*/ */
if (crt_k > tz->trips.critical.temperature) if (crt_k > tz->trips.critical.temperature)
printk(KERN_WARNING PREFIX pr_warn(PREFIX "Critical threshold %d C\n",
"Critical threshold %d C\n", crt); crt);
tz->trips.critical.temperature = crt_k; tz->trips.critical.temperature = crt_k;
} }
} }
...@@ -390,8 +390,7 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag) ...@@ -390,8 +390,7 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
status = acpi_evaluate_reference(tz->device->handle, "_PSL", status = acpi_evaluate_reference(tz->device->handle, "_PSL",
NULL, &devices); NULL, &devices);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
printk(KERN_WARNING PREFIX pr_warn(PREFIX "Invalid passive threshold\n");
"Invalid passive threshold\n");
tz->trips.passive.flags.valid = 0; tz->trips.passive.flags.valid = 0;
} }
else else
...@@ -453,8 +452,8 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag) ...@@ -453,8 +452,8 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
status = acpi_evaluate_reference(tz->device->handle, status = acpi_evaluate_reference(tz->device->handle,
name, NULL, &devices); name, NULL, &devices);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
printk(KERN_WARNING PREFIX pr_warn(PREFIX "Invalid active%d threshold\n",
"Invalid active%d threshold\n", i); i);
tz->trips.active[i].flags.valid = 0; tz->trips.active[i].flags.valid = 0;
} }
else else
...@@ -505,7 +504,7 @@ static int acpi_thermal_get_trip_points(struct acpi_thermal *tz) ...@@ -505,7 +504,7 @@ static int acpi_thermal_get_trip_points(struct acpi_thermal *tz)
valid |= tz->trips.active[i].flags.valid; valid |= tz->trips.active[i].flags.valid;
if (!valid) { if (!valid) {
printk(KERN_WARNING FW_BUG "No valid trip found\n"); pr_warn(FW_BUG "No valid trip found\n");
return -ENODEV; return -ENODEV;
} }
return 0; return 0;
...@@ -923,8 +922,7 @@ static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz) ...@@ -923,8 +922,7 @@ static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz)
acpi_bus_private_data_handler, acpi_bus_private_data_handler,
tz->thermal_zone); tz->thermal_zone);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
printk(KERN_ERR PREFIX pr_err(PREFIX "Error attaching device data\n");
"Error attaching device data\n");
return -ENODEV; return -ENODEV;
} }
...@@ -1094,9 +1092,8 @@ static int acpi_thermal_add(struct acpi_device *device) ...@@ -1094,9 +1092,8 @@ static int acpi_thermal_add(struct acpi_device *device)
if (result) if (result)
goto free_memory; goto free_memory;
printk(KERN_INFO PREFIX "%s [%s] (%ld C)\n", pr_info(PREFIX "%s [%s] (%ld C)\n", acpi_device_name(device),
acpi_device_name(device), acpi_device_bid(device), acpi_device_bid(device), KELVIN_TO_CELSIUS(tz->temperature));
KELVIN_TO_CELSIUS(tz->temperature));
goto end; goto end;
free_memory: free_memory:
...@@ -1159,7 +1156,7 @@ static int acpi_thermal_resume(struct device *dev) ...@@ -1159,7 +1156,7 @@ static int acpi_thermal_resume(struct device *dev)
static int thermal_act(const struct dmi_system_id *d) { static int thermal_act(const struct dmi_system_id *d) {
if (act == 0) { if (act == 0) {
printk(KERN_NOTICE "ACPI: %s detected: " pr_notice(PREFIX "%s detected: "
"disabling all active thermal trip points\n", d->ident); "disabling all active thermal trip points\n", d->ident);
act = -1; act = -1;
} }
...@@ -1167,7 +1164,7 @@ static int thermal_act(const struct dmi_system_id *d) { ...@@ -1167,7 +1164,7 @@ static int thermal_act(const struct dmi_system_id *d) {
} }
static int thermal_nocrt(const struct dmi_system_id *d) { static int thermal_nocrt(const struct dmi_system_id *d) {
printk(KERN_NOTICE "ACPI: %s detected: " pr_notice(PREFIX "%s detected: "
"disabling all critical thermal trip point actions.\n", d->ident); "disabling all critical thermal trip point actions.\n", d->ident);
nocrt = 1; nocrt = 1;
return 0; return 0;
...@@ -1175,7 +1172,7 @@ static int thermal_nocrt(const struct dmi_system_id *d) { ...@@ -1175,7 +1172,7 @@ static int thermal_nocrt(const struct dmi_system_id *d) {
static int thermal_tzp(const struct dmi_system_id *d) { static int thermal_tzp(const struct dmi_system_id *d) {
if (tzp == 0) { if (tzp == 0) {
printk(KERN_NOTICE "ACPI: %s detected: " pr_notice(PREFIX "%s detected: "
"enabling thermal zone polling\n", d->ident); "enabling thermal zone polling\n", d->ident);
tzp = 300; /* 300 dS = 30 Seconds */ tzp = 300; /* 300 dS = 30 Seconds */
} }
...@@ -1184,7 +1181,7 @@ static int thermal_tzp(const struct dmi_system_id *d) { ...@@ -1184,7 +1181,7 @@ static int thermal_tzp(const struct dmi_system_id *d) {
static int thermal_psv(const struct dmi_system_id *d) { static int thermal_psv(const struct dmi_system_id *d) {
if (psv == 0) { if (psv == 0) {
printk(KERN_NOTICE "ACPI: %s detected: " pr_notice(PREFIX "%s detected: "
"disabling all passive thermal trip points\n", d->ident); "disabling all passive thermal trip points\n", d->ident);
psv = -1; psv = -1;
} }
...@@ -1238,7 +1235,7 @@ static int __init acpi_thermal_init(void) ...@@ -1238,7 +1235,7 @@ static int __init acpi_thermal_init(void)
dmi_check_system(thermal_dmi_table); dmi_check_system(thermal_dmi_table);
if (off) { if (off) {
printk(KERN_NOTICE "ACPI: thermal control disabled\n"); pr_notice(PREFIX "thermal control disabled\n");
return -ENODEV; return -ENODEV;
} }
......
...@@ -169,12 +169,21 @@ acpi_extract_package(union acpi_object *package, ...@@ -169,12 +169,21 @@ acpi_extract_package(union acpi_object *package,
/* /*
* Validate output buffer. * Validate output buffer.
*/ */
if (buffer->length == ACPI_ALLOCATE_BUFFER) {
buffer->pointer = ACPI_ALLOCATE(size_required);
if (!buffer->pointer)
return AE_NO_MEMORY;
buffer->length = size_required;
memset(buffer->pointer, 0, size_required);
} else {
if (buffer->length < size_required) { if (buffer->length < size_required) {
buffer->length = size_required; buffer->length = size_required;
return AE_BUFFER_OVERFLOW; return AE_BUFFER_OVERFLOW;
} else if (buffer->length != size_required || !buffer->pointer) { } else if (buffer->length != size_required ||
!buffer->pointer) {
return AE_BAD_PARAMETER; return AE_BAD_PARAMETER;
} }
}
head = buffer->pointer; head = buffer->pointer;
tail = buffer->pointer + tail_offset; tail = buffer->pointer + tail_offset;
......
...@@ -72,8 +72,15 @@ enum { ...@@ -72,8 +72,15 @@ enum {
VPCCMD_W_BL_POWER = 0x33, VPCCMD_W_BL_POWER = 0x33,
}; };
struct ideapad_rfk_priv {
int dev;
struct ideapad_private *priv;
};
struct ideapad_private { struct ideapad_private {
struct acpi_device *adev;
struct rfkill *rfk[IDEAPAD_RFKILL_DEV_NUM]; struct rfkill *rfk[IDEAPAD_RFKILL_DEV_NUM];
struct ideapad_rfk_priv rfk_priv[IDEAPAD_RFKILL_DEV_NUM];
struct platform_device *platform_device; struct platform_device *platform_device;
struct input_dev *inputdev; struct input_dev *inputdev;
struct backlight_device *blightdev; struct backlight_device *blightdev;
...@@ -81,8 +88,6 @@ struct ideapad_private { ...@@ -81,8 +88,6 @@ struct ideapad_private {
unsigned long cfg; unsigned long cfg;
}; };
static acpi_handle ideapad_handle;
static struct ideapad_private *ideapad_priv;
static bool no_bt_rfkill; static bool no_bt_rfkill;
module_param(no_bt_rfkill, bool, 0444); module_param(no_bt_rfkill, bool, 0444);
MODULE_PARM_DESC(no_bt_rfkill, "No rfkill for bluetooth."); MODULE_PARM_DESC(no_bt_rfkill, "No rfkill for bluetooth.");
...@@ -200,34 +205,38 @@ static int write_ec_cmd(acpi_handle handle, int cmd, unsigned long data) ...@@ -200,34 +205,38 @@ static int write_ec_cmd(acpi_handle handle, int cmd, unsigned long data)
*/ */
static int debugfs_status_show(struct seq_file *s, void *data) static int debugfs_status_show(struct seq_file *s, void *data)
{ {
struct ideapad_private *priv = s->private;
unsigned long value; unsigned long value;
if (!read_ec_data(ideapad_handle, VPCCMD_R_BL_MAX, &value)) if (!priv)
return -EINVAL;
if (!read_ec_data(priv->adev->handle, VPCCMD_R_BL_MAX, &value))
seq_printf(s, "Backlight max:\t%lu\n", value); seq_printf(s, "Backlight max:\t%lu\n", value);
if (!read_ec_data(ideapad_handle, VPCCMD_R_BL, &value)) if (!read_ec_data(priv->adev->handle, VPCCMD_R_BL, &value))
seq_printf(s, "Backlight now:\t%lu\n", value); seq_printf(s, "Backlight now:\t%lu\n", value);
if (!read_ec_data(ideapad_handle, VPCCMD_R_BL_POWER, &value)) if (!read_ec_data(priv->adev->handle, VPCCMD_R_BL_POWER, &value))
seq_printf(s, "BL power value:\t%s\n", value ? "On" : "Off"); seq_printf(s, "BL power value:\t%s\n", value ? "On" : "Off");
seq_printf(s, "=====================\n"); seq_printf(s, "=====================\n");
if (!read_ec_data(ideapad_handle, VPCCMD_R_RF, &value)) if (!read_ec_data(priv->adev->handle, VPCCMD_R_RF, &value))
seq_printf(s, "Radio status:\t%s(%lu)\n", seq_printf(s, "Radio status:\t%s(%lu)\n",
value ? "On" : "Off", value); value ? "On" : "Off", value);
if (!read_ec_data(ideapad_handle, VPCCMD_R_WIFI, &value)) if (!read_ec_data(priv->adev->handle, VPCCMD_R_WIFI, &value))
seq_printf(s, "Wifi status:\t%s(%lu)\n", seq_printf(s, "Wifi status:\t%s(%lu)\n",
value ? "On" : "Off", value); value ? "On" : "Off", value);
if (!read_ec_data(ideapad_handle, VPCCMD_R_BT, &value)) if (!read_ec_data(priv->adev->handle, VPCCMD_R_BT, &value))
seq_printf(s, "BT status:\t%s(%lu)\n", seq_printf(s, "BT status:\t%s(%lu)\n",
value ? "On" : "Off", value); value ? "On" : "Off", value);
if (!read_ec_data(ideapad_handle, VPCCMD_R_3G, &value)) if (!read_ec_data(priv->adev->handle, VPCCMD_R_3G, &value))
seq_printf(s, "3G status:\t%s(%lu)\n", seq_printf(s, "3G status:\t%s(%lu)\n",
value ? "On" : "Off", value); value ? "On" : "Off", value);
seq_printf(s, "=====================\n"); seq_printf(s, "=====================\n");
if (!read_ec_data(ideapad_handle, VPCCMD_R_TOUCHPAD, &value)) if (!read_ec_data(priv->adev->handle, VPCCMD_R_TOUCHPAD, &value))
seq_printf(s, "Touchpad status:%s(%lu)\n", seq_printf(s, "Touchpad status:%s(%lu)\n",
value ? "On" : "Off", value); value ? "On" : "Off", value);
if (!read_ec_data(ideapad_handle, VPCCMD_R_CAMERA, &value)) if (!read_ec_data(priv->adev->handle, VPCCMD_R_CAMERA, &value))
seq_printf(s, "Camera status:\t%s(%lu)\n", seq_printf(s, "Camera status:\t%s(%lu)\n",
value ? "On" : "Off", value); value ? "On" : "Off", value);
...@@ -236,7 +245,7 @@ static int debugfs_status_show(struct seq_file *s, void *data) ...@@ -236,7 +245,7 @@ static int debugfs_status_show(struct seq_file *s, void *data)
static int debugfs_status_open(struct inode *inode, struct file *file) static int debugfs_status_open(struct inode *inode, struct file *file)
{ {
return single_open(file, debugfs_status_show, NULL); return single_open(file, debugfs_status_show, inode->i_private);
} }
static const struct file_operations debugfs_status_fops = { static const struct file_operations debugfs_status_fops = {
...@@ -249,21 +258,23 @@ static const struct file_operations debugfs_status_fops = { ...@@ -249,21 +258,23 @@ static const struct file_operations debugfs_status_fops = {
static int debugfs_cfg_show(struct seq_file *s, void *data) static int debugfs_cfg_show(struct seq_file *s, void *data)
{ {
if (!ideapad_priv) { struct ideapad_private *priv = s->private;
if (!priv) {
seq_printf(s, "cfg: N/A\n"); seq_printf(s, "cfg: N/A\n");
} else { } else {
seq_printf(s, "cfg: 0x%.8lX\n\nCapability: ", seq_printf(s, "cfg: 0x%.8lX\n\nCapability: ",
ideapad_priv->cfg); priv->cfg);
if (test_bit(CFG_BT_BIT, &ideapad_priv->cfg)) if (test_bit(CFG_BT_BIT, &priv->cfg))
seq_printf(s, "Bluetooth "); seq_printf(s, "Bluetooth ");
if (test_bit(CFG_3G_BIT, &ideapad_priv->cfg)) if (test_bit(CFG_3G_BIT, &priv->cfg))
seq_printf(s, "3G "); seq_printf(s, "3G ");
if (test_bit(CFG_WIFI_BIT, &ideapad_priv->cfg)) if (test_bit(CFG_WIFI_BIT, &priv->cfg))
seq_printf(s, "Wireless "); seq_printf(s, "Wireless ");
if (test_bit(CFG_CAMERA_BIT, &ideapad_priv->cfg)) if (test_bit(CFG_CAMERA_BIT, &priv->cfg))
seq_printf(s, "Camera "); seq_printf(s, "Camera ");
seq_printf(s, "\nGraphic: "); seq_printf(s, "\nGraphic: ");
switch ((ideapad_priv->cfg)&0x700) { switch ((priv->cfg)&0x700) {
case 0x100: case 0x100:
seq_printf(s, "Intel"); seq_printf(s, "Intel");
break; break;
...@@ -287,7 +298,7 @@ static int debugfs_cfg_show(struct seq_file *s, void *data) ...@@ -287,7 +298,7 @@ static int debugfs_cfg_show(struct seq_file *s, void *data)
static int debugfs_cfg_open(struct inode *inode, struct file *file) static int debugfs_cfg_open(struct inode *inode, struct file *file)
{ {
return single_open(file, debugfs_cfg_show, NULL); return single_open(file, debugfs_cfg_show, inode->i_private);
} }
static const struct file_operations debugfs_cfg_fops = { static const struct file_operations debugfs_cfg_fops = {
...@@ -308,14 +319,14 @@ static int ideapad_debugfs_init(struct ideapad_private *priv) ...@@ -308,14 +319,14 @@ static int ideapad_debugfs_init(struct ideapad_private *priv)
goto errout; goto errout;
} }
node = debugfs_create_file("cfg", S_IRUGO, priv->debug, NULL, node = debugfs_create_file("cfg", S_IRUGO, priv->debug, priv,
&debugfs_cfg_fops); &debugfs_cfg_fops);
if (!node) { if (!node) {
pr_err("failed to create cfg in debugfs"); pr_err("failed to create cfg in debugfs");
goto errout; goto errout;
} }
node = debugfs_create_file("status", S_IRUGO, priv->debug, NULL, node = debugfs_create_file("status", S_IRUGO, priv->debug, priv,
&debugfs_status_fops); &debugfs_status_fops);
if (!node) { if (!node) {
pr_err("failed to create status in debugfs"); pr_err("failed to create status in debugfs");
...@@ -342,8 +353,9 @@ static ssize_t show_ideapad_cam(struct device *dev, ...@@ -342,8 +353,9 @@ static ssize_t show_ideapad_cam(struct device *dev,
char *buf) char *buf)
{ {
unsigned long result; unsigned long result;
struct ideapad_private *priv = dev_get_drvdata(dev);
if (read_ec_data(ideapad_handle, VPCCMD_R_CAMERA, &result)) if (read_ec_data(priv->adev->handle, VPCCMD_R_CAMERA, &result))
return sprintf(buf, "-1\n"); return sprintf(buf, "-1\n");
return sprintf(buf, "%lu\n", result); return sprintf(buf, "%lu\n", result);
} }
...@@ -353,12 +365,13 @@ static ssize_t store_ideapad_cam(struct device *dev, ...@@ -353,12 +365,13 @@ static ssize_t store_ideapad_cam(struct device *dev,
const char *buf, size_t count) const char *buf, size_t count)
{ {
int ret, state; int ret, state;
struct ideapad_private *priv = dev_get_drvdata(dev);
if (!count) if (!count)
return 0; return 0;
if (sscanf(buf, "%i", &state) != 1) if (sscanf(buf, "%i", &state) != 1)
return -EINVAL; return -EINVAL;
ret = write_ec_cmd(ideapad_handle, VPCCMD_W_CAMERA, state); ret = write_ec_cmd(priv->adev->handle, VPCCMD_W_CAMERA, state);
if (ret < 0) if (ret < 0)
return -EIO; return -EIO;
return count; return count;
...@@ -371,8 +384,9 @@ static ssize_t show_ideapad_fan(struct device *dev, ...@@ -371,8 +384,9 @@ static ssize_t show_ideapad_fan(struct device *dev,
char *buf) char *buf)
{ {
unsigned long result; unsigned long result;
struct ideapad_private *priv = dev_get_drvdata(dev);
if (read_ec_data(ideapad_handle, VPCCMD_R_FAN, &result)) if (read_ec_data(priv->adev->handle, VPCCMD_R_FAN, &result))
return sprintf(buf, "-1\n"); return sprintf(buf, "-1\n");
return sprintf(buf, "%lu\n", result); return sprintf(buf, "%lu\n", result);
} }
...@@ -382,6 +396,7 @@ static ssize_t store_ideapad_fan(struct device *dev, ...@@ -382,6 +396,7 @@ static ssize_t store_ideapad_fan(struct device *dev,
const char *buf, size_t count) const char *buf, size_t count)
{ {
int ret, state; int ret, state;
struct ideapad_private *priv = dev_get_drvdata(dev);
if (!count) if (!count)
return 0; return 0;
...@@ -389,7 +404,7 @@ static ssize_t store_ideapad_fan(struct device *dev, ...@@ -389,7 +404,7 @@ static ssize_t store_ideapad_fan(struct device *dev,
return -EINVAL; return -EINVAL;
if (state < 0 || state > 4 || state == 3) if (state < 0 || state > 4 || state == 3)
return -EINVAL; return -EINVAL;
ret = write_ec_cmd(ideapad_handle, VPCCMD_W_FAN, state); ret = write_ec_cmd(priv->adev->handle, VPCCMD_W_FAN, state);
if (ret < 0) if (ret < 0)
return -EIO; return -EIO;
return count; return count;
...@@ -415,7 +430,8 @@ static umode_t ideapad_is_visible(struct kobject *kobj, ...@@ -415,7 +430,8 @@ static umode_t ideapad_is_visible(struct kobject *kobj,
supported = test_bit(CFG_CAMERA_BIT, &(priv->cfg)); supported = test_bit(CFG_CAMERA_BIT, &(priv->cfg));
else if (attr == &dev_attr_fan_mode.attr) { else if (attr == &dev_attr_fan_mode.attr) {
unsigned long value; unsigned long value;
supported = !read_ec_data(ideapad_handle, VPCCMD_R_FAN, &value); supported = !read_ec_data(priv->adev->handle, VPCCMD_R_FAN,
&value);
} else } else
supported = true; supported = true;
...@@ -445,9 +461,9 @@ const struct ideapad_rfk_data ideapad_rfk_data[] = { ...@@ -445,9 +461,9 @@ const struct ideapad_rfk_data ideapad_rfk_data[] = {
static int ideapad_rfk_set(void *data, bool blocked) static int ideapad_rfk_set(void *data, bool blocked)
{ {
unsigned long opcode = (unsigned long)data; struct ideapad_rfk_priv *priv = data;
return write_ec_cmd(ideapad_handle, opcode, !blocked); return write_ec_cmd(priv->priv->adev->handle, priv->dev, !blocked);
} }
static struct rfkill_ops ideapad_rfk_ops = { static struct rfkill_ops ideapad_rfk_ops = {
...@@ -459,7 +475,7 @@ static void ideapad_sync_rfk_state(struct ideapad_private *priv) ...@@ -459,7 +475,7 @@ static void ideapad_sync_rfk_state(struct ideapad_private *priv)
unsigned long hw_blocked; unsigned long hw_blocked;
int i; int i;
if (read_ec_data(ideapad_handle, VPCCMD_R_RF, &hw_blocked)) if (read_ec_data(priv->adev->handle, VPCCMD_R_RF, &hw_blocked))
return; return;
hw_blocked = !hw_blocked; hw_blocked = !hw_blocked;
...@@ -468,27 +484,30 @@ static void ideapad_sync_rfk_state(struct ideapad_private *priv) ...@@ -468,27 +484,30 @@ static void ideapad_sync_rfk_state(struct ideapad_private *priv)
rfkill_set_hw_state(priv->rfk[i], hw_blocked); rfkill_set_hw_state(priv->rfk[i], hw_blocked);
} }
static int ideapad_register_rfkill(struct acpi_device *adevice, int dev) static int ideapad_register_rfkill(struct ideapad_private *priv, int dev)
{ {
struct ideapad_private *priv = dev_get_drvdata(&adevice->dev);
int ret; int ret;
unsigned long sw_blocked; unsigned long sw_blocked;
if (no_bt_rfkill && if (no_bt_rfkill &&
(ideapad_rfk_data[dev].type == RFKILL_TYPE_BLUETOOTH)) { (ideapad_rfk_data[dev].type == RFKILL_TYPE_BLUETOOTH)) {
/* Force to enable bluetooth when no_bt_rfkill=1 */ /* Force to enable bluetooth when no_bt_rfkill=1 */
write_ec_cmd(ideapad_handle, write_ec_cmd(priv->adev->handle,
ideapad_rfk_data[dev].opcode, 1); ideapad_rfk_data[dev].opcode, 1);
return 0; return 0;
} }
priv->rfk_priv[dev].dev = dev;
priv->rfk_priv[dev].priv = priv;
priv->rfk[dev] = rfkill_alloc(ideapad_rfk_data[dev].name, &adevice->dev, priv->rfk[dev] = rfkill_alloc(ideapad_rfk_data[dev].name,
ideapad_rfk_data[dev].type, &ideapad_rfk_ops, &priv->platform_device->dev,
(void *)(long)dev); ideapad_rfk_data[dev].type,
&ideapad_rfk_ops,
&priv->rfk_priv[dev]);
if (!priv->rfk[dev]) if (!priv->rfk[dev])
return -ENOMEM; return -ENOMEM;
if (read_ec_data(ideapad_handle, ideapad_rfk_data[dev].opcode-1, if (read_ec_data(priv->adev->handle, ideapad_rfk_data[dev].opcode-1,
&sw_blocked)) { &sw_blocked)) {
rfkill_init_sw_state(priv->rfk[dev], 0); rfkill_init_sw_state(priv->rfk[dev], 0);
} else { } else {
...@@ -504,10 +523,8 @@ static int ideapad_register_rfkill(struct acpi_device *adevice, int dev) ...@@ -504,10 +523,8 @@ static int ideapad_register_rfkill(struct acpi_device *adevice, int dev)
return 0; return 0;
} }
static void ideapad_unregister_rfkill(struct acpi_device *adevice, int dev) static void ideapad_unregister_rfkill(struct ideapad_private *priv, int dev)
{ {
struct ideapad_private *priv = dev_get_drvdata(&adevice->dev);
if (!priv->rfk[dev]) if (!priv->rfk[dev])
return; return;
...@@ -518,37 +535,16 @@ static void ideapad_unregister_rfkill(struct acpi_device *adevice, int dev) ...@@ -518,37 +535,16 @@ static void ideapad_unregister_rfkill(struct acpi_device *adevice, int dev)
/* /*
* Platform device * Platform device
*/ */
static int ideapad_platform_init(struct ideapad_private *priv) static int ideapad_sysfs_init(struct ideapad_private *priv)
{ {
int result; return sysfs_create_group(&priv->platform_device->dev.kobj,
priv->platform_device = platform_device_alloc("ideapad", -1);
if (!priv->platform_device)
return -ENOMEM;
platform_set_drvdata(priv->platform_device, priv);
result = platform_device_add(priv->platform_device);
if (result)
goto fail_platform_device;
result = sysfs_create_group(&priv->platform_device->dev.kobj,
&ideapad_attribute_group); &ideapad_attribute_group);
if (result)
goto fail_sysfs;
return 0;
fail_sysfs:
platform_device_del(priv->platform_device);
fail_platform_device:
platform_device_put(priv->platform_device);
return result;
} }
static void ideapad_platform_exit(struct ideapad_private *priv) static void ideapad_sysfs_exit(struct ideapad_private *priv)
{ {
sysfs_remove_group(&priv->platform_device->dev.kobj, sysfs_remove_group(&priv->platform_device->dev.kobj,
&ideapad_attribute_group); &ideapad_attribute_group);
platform_device_unregister(priv->platform_device);
} }
/* /*
...@@ -623,7 +619,7 @@ static void ideapad_input_novokey(struct ideapad_private *priv) ...@@ -623,7 +619,7 @@ static void ideapad_input_novokey(struct ideapad_private *priv)
{ {
unsigned long long_pressed; unsigned long long_pressed;
if (read_ec_data(ideapad_handle, VPCCMD_R_NOVO, &long_pressed)) if (read_ec_data(priv->adev->handle, VPCCMD_R_NOVO, &long_pressed))
return; return;
if (long_pressed) if (long_pressed)
ideapad_input_report(priv, 17); ideapad_input_report(priv, 17);
...@@ -635,7 +631,7 @@ static void ideapad_check_special_buttons(struct ideapad_private *priv) ...@@ -635,7 +631,7 @@ static void ideapad_check_special_buttons(struct ideapad_private *priv)
{ {
unsigned long bit, value; unsigned long bit, value;
read_ec_data(ideapad_handle, VPCCMD_R_SPECIAL_BUTTONS, &value); read_ec_data(priv->adev->handle, VPCCMD_R_SPECIAL_BUTTONS, &value);
for (bit = 0; bit < 16; bit++) { for (bit = 0; bit < 16; bit++) {
if (test_bit(bit, &value)) { if (test_bit(bit, &value)) {
...@@ -662,19 +658,28 @@ static void ideapad_check_special_buttons(struct ideapad_private *priv) ...@@ -662,19 +658,28 @@ static void ideapad_check_special_buttons(struct ideapad_private *priv)
*/ */
static int ideapad_backlight_get_brightness(struct backlight_device *blightdev) static int ideapad_backlight_get_brightness(struct backlight_device *blightdev)
{ {
struct ideapad_private *priv = bl_get_data(blightdev);
unsigned long now; unsigned long now;
if (read_ec_data(ideapad_handle, VPCCMD_R_BL, &now)) if (!priv)
return -EINVAL;
if (read_ec_data(priv->adev->handle, VPCCMD_R_BL, &now))
return -EIO; return -EIO;
return now; return now;
} }
static int ideapad_backlight_update_status(struct backlight_device *blightdev) static int ideapad_backlight_update_status(struct backlight_device *blightdev)
{ {
if (write_ec_cmd(ideapad_handle, VPCCMD_W_BL, struct ideapad_private *priv = bl_get_data(blightdev);
if (!priv)
return -EINVAL;
if (write_ec_cmd(priv->adev->handle, VPCCMD_W_BL,
blightdev->props.brightness)) blightdev->props.brightness))
return -EIO; return -EIO;
if (write_ec_cmd(ideapad_handle, VPCCMD_W_BL_POWER, if (write_ec_cmd(priv->adev->handle, VPCCMD_W_BL_POWER,
blightdev->props.power == FB_BLANK_POWERDOWN ? 0 : 1)) blightdev->props.power == FB_BLANK_POWERDOWN ? 0 : 1))
return -EIO; return -EIO;
...@@ -692,11 +697,11 @@ static int ideapad_backlight_init(struct ideapad_private *priv) ...@@ -692,11 +697,11 @@ static int ideapad_backlight_init(struct ideapad_private *priv)
struct backlight_properties props; struct backlight_properties props;
unsigned long max, now, power; unsigned long max, now, power;
if (read_ec_data(ideapad_handle, VPCCMD_R_BL_MAX, &max)) if (read_ec_data(priv->adev->handle, VPCCMD_R_BL_MAX, &max))
return -EIO; return -EIO;
if (read_ec_data(ideapad_handle, VPCCMD_R_BL, &now)) if (read_ec_data(priv->adev->handle, VPCCMD_R_BL, &now))
return -EIO; return -EIO;
if (read_ec_data(ideapad_handle, VPCCMD_R_BL_POWER, &power)) if (read_ec_data(priv->adev->handle, VPCCMD_R_BL_POWER, &power))
return -EIO; return -EIO;
memset(&props, 0, sizeof(struct backlight_properties)); memset(&props, 0, sizeof(struct backlight_properties));
...@@ -734,7 +739,7 @@ static void ideapad_backlight_notify_power(struct ideapad_private *priv) ...@@ -734,7 +739,7 @@ static void ideapad_backlight_notify_power(struct ideapad_private *priv)
if (!blightdev) if (!blightdev)
return; return;
if (read_ec_data(ideapad_handle, VPCCMD_R_BL_POWER, &power)) if (read_ec_data(priv->adev->handle, VPCCMD_R_BL_POWER, &power))
return; return;
blightdev->props.power = power ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN; blightdev->props.power = power ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN;
} }
...@@ -745,7 +750,7 @@ static void ideapad_backlight_notify_brightness(struct ideapad_private *priv) ...@@ -745,7 +750,7 @@ static void ideapad_backlight_notify_brightness(struct ideapad_private *priv)
/* if we control brightness via acpi video driver */ /* if we control brightness via acpi video driver */
if (priv->blightdev == NULL) { if (priv->blightdev == NULL) {
read_ec_data(ideapad_handle, VPCCMD_R_BL, &now); read_ec_data(priv->adev->handle, VPCCMD_R_BL, &now);
return; return;
} }
...@@ -755,19 +760,12 @@ static void ideapad_backlight_notify_brightness(struct ideapad_private *priv) ...@@ -755,19 +760,12 @@ static void ideapad_backlight_notify_brightness(struct ideapad_private *priv)
/* /*
* module init/exit * module init/exit
*/ */
static const struct acpi_device_id ideapad_device_ids[] = { static void ideapad_sync_touchpad_state(struct ideapad_private *priv)
{ "VPC2004", 0},
{ "", 0},
};
MODULE_DEVICE_TABLE(acpi, ideapad_device_ids);
static void ideapad_sync_touchpad_state(struct acpi_device *adevice)
{ {
struct ideapad_private *priv = dev_get_drvdata(&adevice->dev);
unsigned long value; unsigned long value;
/* Without reading from EC touchpad LED doesn't switch state */ /* Without reading from EC touchpad LED doesn't switch state */
if (!read_ec_data(adevice->handle, VPCCMD_R_TOUCHPAD, &value)) { if (!read_ec_data(priv->adev->handle, VPCCMD_R_TOUCHPAD, &value)) {
/* Some IdeaPads don't really turn off touchpad - they only /* Some IdeaPads don't really turn off touchpad - they only
* switch the LED state. We (de)activate KBC AUX port to turn * switch the LED state. We (de)activate KBC AUX port to turn
* touchpad off and on. We send KEY_TOUCHPAD_OFF and * touchpad off and on. We send KEY_TOUCHPAD_OFF and
...@@ -779,26 +777,77 @@ static void ideapad_sync_touchpad_state(struct acpi_device *adevice) ...@@ -779,26 +777,77 @@ static void ideapad_sync_touchpad_state(struct acpi_device *adevice)
} }
} }
static int ideapad_acpi_add(struct acpi_device *adevice) static void ideapad_acpi_notify(acpi_handle handle, u32 event, void *data)
{
struct ideapad_private *priv = data;
unsigned long vpc1, vpc2, vpc_bit;
if (read_ec_data(handle, VPCCMD_R_VPC1, &vpc1))
return;
if (read_ec_data(handle, VPCCMD_R_VPC2, &vpc2))
return;
vpc1 = (vpc2 << 8) | vpc1;
for (vpc_bit = 0; vpc_bit < 16; vpc_bit++) {
if (test_bit(vpc_bit, &vpc1)) {
switch (vpc_bit) {
case 9:
ideapad_sync_rfk_state(priv);
break;
case 13:
case 11:
case 7:
case 6:
ideapad_input_report(priv, vpc_bit);
break;
case 5:
ideapad_sync_touchpad_state(priv);
break;
case 4:
ideapad_backlight_notify_brightness(priv);
break;
case 3:
ideapad_input_novokey(priv);
break;
case 2:
ideapad_backlight_notify_power(priv);
break;
case 0:
ideapad_check_special_buttons(priv);
break;
default:
pr_info("Unknown event: %lu\n", vpc_bit);
}
}
}
}
static int ideapad_acpi_add(struct platform_device *pdev)
{ {
int ret, i; int ret, i;
int cfg; int cfg;
struct ideapad_private *priv; struct ideapad_private *priv;
struct acpi_device *adev;
if (read_method_int(adevice->handle, "_CFG", &cfg)) ret = acpi_bus_get_device(ACPI_HANDLE(&pdev->dev), &adev);
if (ret)
return -ENODEV;
if (read_method_int(adev->handle, "_CFG", &cfg))
return -ENODEV; return -ENODEV;
priv = kzalloc(sizeof(*priv), GFP_KERNEL); priv = kzalloc(sizeof(*priv), GFP_KERNEL);
if (!priv) if (!priv)
return -ENOMEM; return -ENOMEM;
dev_set_drvdata(&adevice->dev, priv);
ideapad_priv = priv; dev_set_drvdata(&pdev->dev, priv);
ideapad_handle = adevice->handle;
priv->cfg = cfg; priv->cfg = cfg;
priv->adev = adev;
priv->platform_device = pdev;
ret = ideapad_platform_init(priv); ret = ideapad_sysfs_init(priv);
if (ret) if (ret)
goto platform_failed; goto sysfs_failed;
ret = ideapad_debugfs_init(priv); ret = ideapad_debugfs_init(priv);
if (ret) if (ret)
...@@ -810,117 +859,92 @@ static int ideapad_acpi_add(struct acpi_device *adevice) ...@@ -810,117 +859,92 @@ static int ideapad_acpi_add(struct acpi_device *adevice)
for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++) { for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++) {
if (test_bit(ideapad_rfk_data[i].cfgbit, &priv->cfg)) if (test_bit(ideapad_rfk_data[i].cfgbit, &priv->cfg))
ideapad_register_rfkill(adevice, i); ideapad_register_rfkill(priv, i);
else else
priv->rfk[i] = NULL; priv->rfk[i] = NULL;
} }
ideapad_sync_rfk_state(priv); ideapad_sync_rfk_state(priv);
ideapad_sync_touchpad_state(adevice); ideapad_sync_touchpad_state(priv);
if (!acpi_video_backlight_support()) { if (!acpi_video_backlight_support()) {
ret = ideapad_backlight_init(priv); ret = ideapad_backlight_init(priv);
if (ret && ret != -ENODEV) if (ret && ret != -ENODEV)
goto backlight_failed; goto backlight_failed;
} }
ret = acpi_install_notify_handler(adev->handle,
ACPI_DEVICE_NOTIFY, ideapad_acpi_notify, priv);
if (ret)
goto notification_failed;
return 0; return 0;
notification_failed:
ideapad_backlight_exit(priv);
backlight_failed: backlight_failed:
for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++) for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++)
ideapad_unregister_rfkill(adevice, i); ideapad_unregister_rfkill(priv, i);
ideapad_input_exit(priv); ideapad_input_exit(priv);
input_failed: input_failed:
ideapad_debugfs_exit(priv); ideapad_debugfs_exit(priv);
debugfs_failed: debugfs_failed:
ideapad_platform_exit(priv); ideapad_sysfs_exit(priv);
platform_failed: sysfs_failed:
kfree(priv); kfree(priv);
return ret; return ret;
} }
static int ideapad_acpi_remove(struct acpi_device *adevice) static int ideapad_acpi_remove(struct platform_device *pdev)
{ {
struct ideapad_private *priv = dev_get_drvdata(&adevice->dev); struct ideapad_private *priv = dev_get_drvdata(&pdev->dev);
int i; int i;
acpi_remove_notify_handler(priv->adev->handle,
ACPI_DEVICE_NOTIFY, ideapad_acpi_notify);
ideapad_backlight_exit(priv); ideapad_backlight_exit(priv);
for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++) for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++)
ideapad_unregister_rfkill(adevice, i); ideapad_unregister_rfkill(priv, i);
ideapad_input_exit(priv); ideapad_input_exit(priv);
ideapad_debugfs_exit(priv); ideapad_debugfs_exit(priv);
ideapad_platform_exit(priv); ideapad_sysfs_exit(priv);
dev_set_drvdata(&adevice->dev, NULL); dev_set_drvdata(&pdev->dev, NULL);
kfree(priv); kfree(priv);
return 0; return 0;
} }
static void ideapad_acpi_notify(struct acpi_device *adevice, u32 event) #ifdef CONFIG_PM_SLEEP
static int ideapad_acpi_resume(struct device *device)
{ {
struct ideapad_private *priv = dev_get_drvdata(&adevice->dev); struct ideapad_private *priv;
acpi_handle handle = adevice->handle;
unsigned long vpc1, vpc2, vpc_bit;
if (read_ec_data(handle, VPCCMD_R_VPC1, &vpc1)) if (!device)
return; return -EINVAL;
if (read_ec_data(handle, VPCCMD_R_VPC2, &vpc2)) priv = dev_get_drvdata(device);
return;
vpc1 = (vpc2 << 8) | vpc1;
for (vpc_bit = 0; vpc_bit < 16; vpc_bit++) {
if (test_bit(vpc_bit, &vpc1)) {
switch (vpc_bit) {
case 9:
ideapad_sync_rfk_state(priv); ideapad_sync_rfk_state(priv);
break; ideapad_sync_touchpad_state(priv);
case 13:
case 11:
case 7:
case 6:
ideapad_input_report(priv, vpc_bit);
break;
case 5:
ideapad_sync_touchpad_state(adevice);
break;
case 4:
ideapad_backlight_notify_brightness(priv);
break;
case 3:
ideapad_input_novokey(priv);
break;
case 2:
ideapad_backlight_notify_power(priv);
break;
case 0:
ideapad_check_special_buttons(priv);
break;
default:
pr_info("Unknown event: %lu\n", vpc_bit);
}
}
}
}
static int ideapad_acpi_resume(struct device *device)
{
ideapad_sync_rfk_state(ideapad_priv);
ideapad_sync_touchpad_state(to_acpi_device(device));
return 0; return 0;
} }
#endif
static SIMPLE_DEV_PM_OPS(ideapad_pm, NULL, ideapad_acpi_resume); static SIMPLE_DEV_PM_OPS(ideapad_pm, NULL, ideapad_acpi_resume);
static struct acpi_driver ideapad_acpi_driver = { static const struct acpi_device_id ideapad_device_ids[] = {
{ "VPC2004", 0},
{ "", 0},
};
MODULE_DEVICE_TABLE(acpi, ideapad_device_ids);
static struct platform_driver ideapad_acpi_driver = {
.probe = ideapad_acpi_add,
.remove = ideapad_acpi_remove,
.driver = {
.name = "ideapad_acpi", .name = "ideapad_acpi",
.class = "IdeaPad",
.ids = ideapad_device_ids,
.ops.add = ideapad_acpi_add,
.ops.remove = ideapad_acpi_remove,
.ops.notify = ideapad_acpi_notify,
.drv.pm = &ideapad_pm,
.owner = THIS_MODULE, .owner = THIS_MODULE,
.pm = &ideapad_pm,
.acpi_match_table = ACPI_PTR(ideapad_device_ids),
},
}; };
module_acpi_driver(ideapad_acpi_driver);
module_platform_driver(ideapad_acpi_driver);
MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>"); MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
MODULE_DESCRIPTION("IdeaPad ACPI Extras"); MODULE_DESCRIPTION("IdeaPad ACPI Extras");
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册