mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-11-30 13:46:47 +07:00
Merge branch 'acpi-conversion'
* acpi-conversion: ACPI / AC: Remove AC's proc directory. ideapad_laptop: convert ideapad device/driver to platform bus ideapad_laptop: remove ideapad_handle and ideapad_priv ideapad_laptop: convert internal function calls to use ideapad_private as parameter ideapad_laptop: introduce struct acpi_device pointer to ideapad_private structure ideapad_laptop: introduce #ifdef CONFIG_PM_SLEEP for PM specific code ACPI / AC: convert ACPI ac driver to platform bus
This commit is contained in:
commit
31c466c1af
@ -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");
|
|||||||
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[] = {
|
|||||||
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)
|
|||||||
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[] = {
|
|||||||
{},
|
{},
|
||||||
};
|
};
|
||||||
|
|
||||||
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)
|
|||||||
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)
|
|||||||
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 (!pdev)
|
||||||
if (!device || !acpi_driver_data(device))
|
|
||||||
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)
|
|||||||
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;
|
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 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);
|
||||||
|
@ -29,7 +29,8 @@ 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" },
|
||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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 {
|
|||||||
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)
|
|||||||
*/
|
*/
|
||||||
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)
|
|||||||
|
|
||||||
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 = {
|
|||||||
|
|
||||||
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)
|
|||||||
|
|
||||||
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)
|
|||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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[] = {
|
|||||||
|
|
||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
/*
|
/*
|
||||||
* 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)
|
|||||||
{
|
{
|
||||||
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)
|
|||||||
{
|
{
|
||||||
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)
|
|||||||
*/
|
*/
|
||||||
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)
|
|||||||
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)
|
|||||||
|
|
||||||
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)
|
|||||||
|
|
||||||
/* 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)
|
|||||||
/*
|
/*
|
||||||
* 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,86 +777,9 @@ 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)
|
||||||
{
|
{
|
||||||
int ret, i;
|
struct ideapad_private *priv = data;
|
||||||
int cfg;
|
|
||||||
struct ideapad_private *priv;
|
|
||||||
|
|
||||||
if (read_method_int(adevice->handle, "_CFG", &cfg))
|
|
||||||
return -ENODEV;
|
|
||||||
|
|
||||||
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
|
|
||||||
if (!priv)
|
|
||||||
return -ENOMEM;
|
|
||||||
dev_set_drvdata(&adevice->dev, priv);
|
|
||||||
ideapad_priv = priv;
|
|
||||||
ideapad_handle = adevice->handle;
|
|
||||||
priv->cfg = cfg;
|
|
||||||
|
|
||||||
ret = ideapad_platform_init(priv);
|
|
||||||
if (ret)
|
|
||||||
goto platform_failed;
|
|
||||||
|
|
||||||
ret = ideapad_debugfs_init(priv);
|
|
||||||
if (ret)
|
|
||||||
goto debugfs_failed;
|
|
||||||
|
|
||||||
ret = ideapad_input_init(priv);
|
|
||||||
if (ret)
|
|
||||||
goto input_failed;
|
|
||||||
|
|
||||||
for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++) {
|
|
||||||
if (test_bit(ideapad_rfk_data[i].cfgbit, &priv->cfg))
|
|
||||||
ideapad_register_rfkill(adevice, i);
|
|
||||||
else
|
|
||||||
priv->rfk[i] = NULL;
|
|
||||||
}
|
|
||||||
ideapad_sync_rfk_state(priv);
|
|
||||||
ideapad_sync_touchpad_state(adevice);
|
|
||||||
|
|
||||||
if (!acpi_video_backlight_support()) {
|
|
||||||
ret = ideapad_backlight_init(priv);
|
|
||||||
if (ret && ret != -ENODEV)
|
|
||||||
goto backlight_failed;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
backlight_failed:
|
|
||||||
for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++)
|
|
||||||
ideapad_unregister_rfkill(adevice, i);
|
|
||||||
ideapad_input_exit(priv);
|
|
||||||
input_failed:
|
|
||||||
ideapad_debugfs_exit(priv);
|
|
||||||
debugfs_failed:
|
|
||||||
ideapad_platform_exit(priv);
|
|
||||||
platform_failed:
|
|
||||||
kfree(priv);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int ideapad_acpi_remove(struct acpi_device *adevice)
|
|
||||||
{
|
|
||||||
struct ideapad_private *priv = dev_get_drvdata(&adevice->dev);
|
|
||||||
int i;
|
|
||||||
|
|
||||||
ideapad_backlight_exit(priv);
|
|
||||||
for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++)
|
|
||||||
ideapad_unregister_rfkill(adevice, i);
|
|
||||||
ideapad_input_exit(priv);
|
|
||||||
ideapad_debugfs_exit(priv);
|
|
||||||
ideapad_platform_exit(priv);
|
|
||||||
dev_set_drvdata(&adevice->dev, NULL);
|
|
||||||
kfree(priv);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ideapad_acpi_notify(struct acpi_device *adevice, u32 event)
|
|
||||||
{
|
|
||||||
struct ideapad_private *priv = dev_get_drvdata(&adevice->dev);
|
|
||||||
acpi_handle handle = adevice->handle;
|
|
||||||
unsigned long vpc1, vpc2, vpc_bit;
|
unsigned long vpc1, vpc2, vpc_bit;
|
||||||
|
|
||||||
if (read_ec_data(handle, VPCCMD_R_VPC1, &vpc1))
|
if (read_ec_data(handle, VPCCMD_R_VPC1, &vpc1))
|
||||||
@ -880,7 +801,7 @@ static void ideapad_acpi_notify(struct acpi_device *adevice, u32 event)
|
|||||||
ideapad_input_report(priv, vpc_bit);
|
ideapad_input_report(priv, vpc_bit);
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
ideapad_sync_touchpad_state(adevice);
|
ideapad_sync_touchpad_state(priv);
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
ideapad_backlight_notify_brightness(priv);
|
ideapad_backlight_notify_brightness(priv);
|
||||||
@ -901,26 +822,129 @@ static void ideapad_acpi_notify(struct acpi_device *adevice, u32 event)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ideapad_acpi_resume(struct device *device)
|
static int ideapad_acpi_add(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
ideapad_sync_rfk_state(ideapad_priv);
|
int ret, i;
|
||||||
ideapad_sync_touchpad_state(to_acpi_device(device));
|
int cfg;
|
||||||
|
struct ideapad_private *priv;
|
||||||
|
struct acpi_device *adev;
|
||||||
|
|
||||||
|
ret = acpi_bus_get_device(ACPI_HANDLE(&pdev->dev), &adev);
|
||||||
|
if (ret)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
if (read_method_int(adev->handle, "_CFG", &cfg))
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
|
||||||
|
if (!priv)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
dev_set_drvdata(&pdev->dev, priv);
|
||||||
|
priv->cfg = cfg;
|
||||||
|
priv->adev = adev;
|
||||||
|
priv->platform_device = pdev;
|
||||||
|
|
||||||
|
ret = ideapad_sysfs_init(priv);
|
||||||
|
if (ret)
|
||||||
|
goto sysfs_failed;
|
||||||
|
|
||||||
|
ret = ideapad_debugfs_init(priv);
|
||||||
|
if (ret)
|
||||||
|
goto debugfs_failed;
|
||||||
|
|
||||||
|
ret = ideapad_input_init(priv);
|
||||||
|
if (ret)
|
||||||
|
goto input_failed;
|
||||||
|
|
||||||
|
for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++) {
|
||||||
|
if (test_bit(ideapad_rfk_data[i].cfgbit, &priv->cfg))
|
||||||
|
ideapad_register_rfkill(priv, i);
|
||||||
|
else
|
||||||
|
priv->rfk[i] = NULL;
|
||||||
|
}
|
||||||
|
ideapad_sync_rfk_state(priv);
|
||||||
|
ideapad_sync_touchpad_state(priv);
|
||||||
|
|
||||||
|
if (!acpi_video_backlight_support()) {
|
||||||
|
ret = ideapad_backlight_init(priv);
|
||||||
|
if (ret && ret != -ENODEV)
|
||||||
|
goto backlight_failed;
|
||||||
|
}
|
||||||
|
ret = acpi_install_notify_handler(adev->handle,
|
||||||
|
ACPI_DEVICE_NOTIFY, ideapad_acpi_notify, priv);
|
||||||
|
if (ret)
|
||||||
|
goto notification_failed;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
notification_failed:
|
||||||
|
ideapad_backlight_exit(priv);
|
||||||
|
backlight_failed:
|
||||||
|
for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++)
|
||||||
|
ideapad_unregister_rfkill(priv, i);
|
||||||
|
ideapad_input_exit(priv);
|
||||||
|
input_failed:
|
||||||
|
ideapad_debugfs_exit(priv);
|
||||||
|
debugfs_failed:
|
||||||
|
ideapad_sysfs_exit(priv);
|
||||||
|
sysfs_failed:
|
||||||
|
kfree(priv);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ideapad_acpi_remove(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
struct ideapad_private *priv = dev_get_drvdata(&pdev->dev);
|
||||||
|
int i;
|
||||||
|
|
||||||
|
acpi_remove_notify_handler(priv->adev->handle,
|
||||||
|
ACPI_DEVICE_NOTIFY, ideapad_acpi_notify);
|
||||||
|
ideapad_backlight_exit(priv);
|
||||||
|
for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++)
|
||||||
|
ideapad_unregister_rfkill(priv, i);
|
||||||
|
ideapad_input_exit(priv);
|
||||||
|
ideapad_debugfs_exit(priv);
|
||||||
|
ideapad_sysfs_exit(priv);
|
||||||
|
dev_set_drvdata(&pdev->dev, NULL);
|
||||||
|
kfree(priv);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_PM_SLEEP
|
||||||
|
static int ideapad_acpi_resume(struct device *device)
|
||||||
|
{
|
||||||
|
struct ideapad_private *priv;
|
||||||
|
|
||||||
|
if (!device)
|
||||||
|
return -EINVAL;
|
||||||
|
priv = dev_get_drvdata(device);
|
||||||
|
|
||||||
|
ideapad_sync_rfk_state(priv);
|
||||||
|
ideapad_sync_touchpad_state(priv);
|
||||||
|
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[] = {
|
||||||
.name = "ideapad_acpi",
|
{ "VPC2004", 0},
|
||||||
.class = "IdeaPad",
|
{ "", 0},
|
||||||
.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,
|
|
||||||
};
|
};
|
||||||
module_acpi_driver(ideapad_acpi_driver);
|
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",
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
.pm = &ideapad_pm,
|
||||||
|
.acpi_match_table = ACPI_PTR(ideapad_device_ids),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
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");
|
||||||
|
Loading…
Reference in New Issue
Block a user