ac.c revision 27663c5855b10af9ec67bc7dfba001426ba21222
11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * acpi_ac.c - ACPI AC Adapter Driver ($Revision: 27 $) 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com> 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is free software; you can redistribute it and/or modify 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * it under the terms of the GNU General Public License as published by 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the Free Software Foundation; either version 2 of the License, or (at 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * your option) any later version. 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is distributed in the hope that it will be useful, but 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * WITHOUT ANY WARRANTY; without even the implied warranty of 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * General Public License for more details. 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * You should have received a copy of the GNU General Public License along 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * with this program; if not, write to the Free Software Foundation, Inc., 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h> 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/types.h> 30fdcedbba2f98c94bfbac9f6e712ab765f997b8dcAlexey Starikovskiy#ifdef CONFIG_ACPI_PROCFS_POWER 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/proc_fs.h> 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/seq_file.h> 338a246ee43f4b1df3fa5cbf9c4a3d3dcad0b1e08cAndrey Borzenkov#endif 3497749cd9adbb2985e4b2aee1a59d6b970fe9c3a7Alexey Starikovskiy#ifdef CONFIG_ACPI_SYSFS_POWER 35d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy#include <linux/power_supply.h> 3697749cd9adbb2985e4b2aee1a59d6b970fe9c3a7Alexey Starikovskiy#endif 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <acpi/acpi_bus.h> 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <acpi/acpi_drivers.h> 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ACPI_AC_COMPONENT 0x00020000 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ACPI_AC_CLASS "ac_adapter" 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ACPI_AC_DEVICE_NAME "AC Adapter" 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ACPI_AC_FILE_STATE "state" 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ACPI_AC_NOTIFY_STATUS 0x80 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ACPI_AC_STATUS_OFFLINE 0x00 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ACPI_AC_STATUS_ONLINE 0x01 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ACPI_AC_STATUS_UNKNOWN 0xFF 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define _COMPONENT ACPI_AC_COMPONENT 50f52fd66d2ea794010c2d7536cf8e6abed0ac4947Len BrownACPI_MODULE_NAME("ac"); 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 52f52fd66d2ea794010c2d7536cf8e6abed0ac4947Len BrownMODULE_AUTHOR("Paul Diefenbaugh"); 537cda93e008e1a477970adbf82dba81a5d4f0ae40Len BrownMODULE_DESCRIPTION("ACPI AC Adapter Driver"); 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL"); 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 56fdcedbba2f98c94bfbac9f6e712ab765f997b8dcAlexey Starikovskiy#ifdef CONFIG_ACPI_PROCFS_POWER 573f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsendextern struct proc_dir_entry *acpi_lock_ac_dir(void); 583f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsendextern void *acpi_unlock_ac_dir(struct proc_dir_entry *acpi_ac_dir); 598a246ee43f4b1df3fa5cbf9c4a3d3dcad0b1e08cAndrey Borzenkovstatic int acpi_ac_open_fs(struct inode *inode, struct file *file); 608a246ee43f4b1df3fa5cbf9c4a3d3dcad0b1e08cAndrey Borzenkov#endif 613f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend 624be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownstatic int acpi_ac_add(struct acpi_device *device); 634be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownstatic int acpi_ac_remove(struct acpi_device *device, int type); 645bfeca3138a6031e38c566d57128ff592eb009a8Alexey Starikovskiystatic int acpi_ac_resume(struct acpi_device *device); 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 66b299c22c8c1024a5a89d19524e24b3e1d67e9eabTobias Klauserstatic const struct acpi_device_id ac_device_ids[] = { 671ba90e3a87c46500623afdc3898573e4a5ebb21bThomas Renninger {"ACPI0003", 0}, 681ba90e3a87c46500623afdc3898573e4a5ebb21bThomas Renninger {"", 0}, 691ba90e3a87c46500623afdc3898573e4a5ebb21bThomas Renninger}; 701ba90e3a87c46500623afdc3898573e4a5ebb21bThomas RenningerMODULE_DEVICE_TABLE(acpi, ac_device_ids); 711ba90e3a87c46500623afdc3898573e4a5ebb21bThomas Renninger 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct acpi_driver acpi_ac_driver = { 73c2b6705b75d9c7aff98a4602a32230639e10891cLen Brown .name = "ac", 744be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown .class = ACPI_AC_CLASS, 751ba90e3a87c46500623afdc3898573e4a5ebb21bThomas Renninger .ids = ac_device_ids, 764be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown .ops = { 774be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown .add = acpi_ac_add, 784be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown .remove = acpi_ac_remove, 795bfeca3138a6031e38c566d57128ff592eb009a8Alexey Starikovskiy .resume = acpi_ac_resume, 804be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown }, 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct acpi_ac { 8497749cd9adbb2985e4b2aee1a59d6b970fe9c3a7Alexey Starikovskiy#ifdef CONFIG_ACPI_SYSFS_POWER 85d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy struct power_supply charger; 8697749cd9adbb2985e4b2aee1a59d6b970fe9c3a7Alexey Starikovskiy#endif 87af96179a8298832cc58be212d0e4988d8a1e11bfPatrick Mochel struct acpi_device * device; 8827663c5855b10af9ec67bc7dfba001426ba21222Matthew Wilcox unsigned long long state; 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 91d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy#define to_acpi_ac(x) container_of(x, struct acpi_ac, charger); 92d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy 93fdcedbba2f98c94bfbac9f6e712ab765f997b8dcAlexey Starikovskiy#ifdef CONFIG_ACPI_PROCFS_POWER 94d75080328affb4b268da430b7074cc8139cc662aArjan van de Venstatic const struct file_operations acpi_ac_fops = { 95cf7acfab032ff262f42954328cdfd20a5d9aaaacDenis V. Lunev .owner = THIS_MODULE, 964be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown .open = acpi_ac_open_fs, 974be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown .read = seq_read, 984be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown .llseek = seq_lseek, 994be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown .release = single_release, 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1018a246ee43f4b1df3fa5cbf9c4a3d3dcad0b1e08cAndrey Borzenkov#endif 10297749cd9adbb2985e4b2aee1a59d6b970fe9c3a7Alexey Starikovskiy#ifdef CONFIG_ACPI_SYSFS_POWER 103d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiystatic int get_ac_property(struct power_supply *psy, 104d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy enum power_supply_property psp, 105d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy union power_supply_propval *val) 106d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy{ 107d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy struct acpi_ac *ac = to_acpi_ac(psy); 108d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy switch (psp) { 109d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy case POWER_SUPPLY_PROP_ONLINE: 110d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy val->intval = ac->state; 111d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy break; 112d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy default: 113d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy return -EINVAL; 114d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy } 115d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy return 0; 116d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy} 117d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy 118d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiystatic enum power_supply_property ac_props[] = { 119d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy POWER_SUPPLY_PROP_ONLINE, 120d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy}; 12197749cd9adbb2985e4b2aee1a59d6b970fe9c3a7Alexey Starikovskiy#endif 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* -------------------------------------------------------------------------- 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds AC Adapter Management 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds -------------------------------------------------------------------------- */ 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1264be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownstatic int acpi_ac_get_state(struct acpi_ac *ac) 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1284be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown acpi_status status = AE_OK; 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!ac) 132d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return -EINVAL; 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 134a6ba5ebef91a59fabd45962e576c02468dbcd33fPatrick Mochel status = acpi_evaluate_integer(ac->device->handle, "_PSR", NULL, &ac->state); 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ACPI_FAILURE(status)) { 136a6fc67202e0224e6c9d1d285cc0b444bce887ed5Thomas Renninger ACPI_EXCEPTION((AE_INFO, status, "Error reading AC Adapter state")); 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ac->state = ACPI_AC_STATUS_UNKNOWN; 138d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return -ENODEV; 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1404be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown 141d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return 0; 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 144fdcedbba2f98c94bfbac9f6e712ab765f997b8dcAlexey Starikovskiy#ifdef CONFIG_ACPI_PROCFS_POWER 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* -------------------------------------------------------------------------- 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FS Interface (/proc) 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds -------------------------------------------------------------------------- */ 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1494be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownstatic struct proc_dir_entry *acpi_ac_dir; 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int acpi_ac_seq_show(struct seq_file *seq, void *offset) 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 15350dd096973f1d95aa03c6a6d9e148d706b62b68eJan Engelhardt struct acpi_ac *ac = seq->private; 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!ac) 157d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return 0; 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (acpi_ac_get_state(ac)) { 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds seq_puts(seq, "ERROR: Unable to read AC Adapter state\n"); 161d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return 0; 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds seq_puts(seq, "state: "); 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (ac->state) { 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case ACPI_AC_STATUS_OFFLINE: 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds seq_puts(seq, "off-line\n"); 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case ACPI_AC_STATUS_ONLINE: 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds seq_puts(seq, "on-line\n"); 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds seq_puts(seq, "unknown\n"); 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 177d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return 0; 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1794be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int acpi_ac_open_fs(struct inode *inode, struct file *file) 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return single_open(file, acpi_ac_seq_show, PDE(inode)->data); 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1854be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownstatic int acpi_ac_add_fs(struct acpi_device *device) 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1874be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown struct proc_dir_entry *entry = NULL; 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!acpi_device_dir(device)) { 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), 1924be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown acpi_ac_dir); 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!acpi_device_dir(device)) 194d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return -ENODEV; 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds acpi_device_dir(device)->owner = THIS_MODULE; 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 'state' [R] */ 199cf7acfab032ff262f42954328cdfd20a5d9aaaacDenis V. Lunev entry = proc_create_data(ACPI_AC_FILE_STATE, 200cf7acfab032ff262f42954328cdfd20a5d9aaaacDenis V. Lunev S_IRUGO, acpi_device_dir(device), 201cf7acfab032ff262f42954328cdfd20a5d9aaaacDenis V. Lunev &acpi_ac_fops, acpi_driver_data(device)); 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!entry) 203d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return -ENODEV; 204d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return 0; 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2074be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownstatic int acpi_ac_remove_fs(struct acpi_device *device) 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (acpi_device_dir(device)) { 2114be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown remove_proc_entry(ACPI_AC_FILE_STATE, acpi_device_dir(device)); 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds remove_proc_entry(acpi_device_bid(device), acpi_ac_dir); 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds acpi_device_dir(device) = NULL; 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 217d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return 0; 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2198a246ee43f4b1df3fa5cbf9c4a3d3dcad0b1e08cAndrey Borzenkov#endif 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* -------------------------------------------------------------------------- 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Driver Model 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds -------------------------------------------------------------------------- */ 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2254be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownstatic void acpi_ac_notify(acpi_handle handle, u32 event, void *data) 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 22750dd096973f1d95aa03c6a6d9e148d706b62b68eJan Engelhardt struct acpi_ac *ac = data; 2284be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown struct acpi_device *device = NULL; 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!ac) 232d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return; 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 234af96179a8298832cc58be212d0e4988d8a1e11bfPatrick Mochel device = ac->device; 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (event) { 236f163ff5176a8e9c827d8ebe044710d67d40799c3Len Brown default: 237f163ff5176a8e9c827d8ebe044710d67d40799c3Len Brown ACPI_DEBUG_PRINT((ACPI_DB_INFO, 238f163ff5176a8e9c827d8ebe044710d67d40799c3Len Brown "Unsupported event [0x%x]\n", event)); 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case ACPI_AC_NOTIFY_STATUS: 24003d782524e2d0511317769521c8d5daadbab8482Christian Lupien case ACPI_NOTIFY_BUS_CHECK: 24103d782524e2d0511317769521c8d5daadbab8482Christian Lupien case ACPI_NOTIFY_DEVICE_CHECK: 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds acpi_ac_get_state(ac); 24314e04fb34ffa82ee61ae69f98d8fca12d2e8e31cLen Brown acpi_bus_generate_proc_event(device, event, (u32) ac->state); 244962ce8ca0604af0c3c5609f7613d4ec5fcfac623Zhang Rui acpi_bus_generate_netlink_event(device->pnp.device_class, 245962ce8ca0604af0c3c5609f7613d4ec5fcfac623Zhang Rui device->dev.bus_id, event, 246962ce8ca0604af0c3c5609f7613d4ec5fcfac623Zhang Rui (u32) ac->state); 24797749cd9adbb2985e4b2aee1a59d6b970fe9c3a7Alexey Starikovskiy#ifdef CONFIG_ACPI_SYSFS_POWER 248d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy kobject_uevent(&ac->charger.dev->kobj, KOBJ_CHANGE); 24997749cd9adbb2985e4b2aee1a59d6b970fe9c3a7Alexey Starikovskiy#endif 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 252d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return; 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2554be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownstatic int acpi_ac_add(struct acpi_device *device) 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2574be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown int result = 0; 2584be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown acpi_status status = AE_OK; 2594be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown struct acpi_ac *ac = NULL; 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!device) 263d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return -EINVAL; 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 26536bcbec7ce21e2e8b3143b11a05747330abeca70Burman Yan ac = kzalloc(sizeof(struct acpi_ac), GFP_KERNEL); 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!ac) 267d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return -ENOMEM; 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 269af96179a8298832cc58be212d0e4988d8a1e11bfPatrick Mochel ac->device = device; 2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds strcpy(acpi_device_name(device), ACPI_AC_DEVICE_NAME); 2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds strcpy(acpi_device_class(device), ACPI_AC_CLASS); 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds acpi_driver_data(device) = ac; 2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds result = acpi_ac_get_state(ac); 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (result) 2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto end; 2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 278fdcedbba2f98c94bfbac9f6e712ab765f997b8dcAlexey Starikovskiy#ifdef CONFIG_ACPI_PROCFS_POWER 2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds result = acpi_ac_add_fs(device); 2808a246ee43f4b1df3fa5cbf9c4a3d3dcad0b1e08cAndrey Borzenkov#endif 2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (result) 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto end; 28397749cd9adbb2985e4b2aee1a59d6b970fe9c3a7Alexey Starikovskiy#ifdef CONFIG_ACPI_SYSFS_POWER 284d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy ac->charger.name = acpi_device_bid(device); 285d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy ac->charger.type = POWER_SUPPLY_TYPE_MAINS; 286d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy ac->charger.properties = ac_props; 287d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy ac->charger.num_properties = ARRAY_SIZE(ac_props); 288d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy ac->charger.get_property = get_ac_property; 289d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy power_supply_register(&ac->device->dev, &ac->charger); 29097749cd9adbb2985e4b2aee1a59d6b970fe9c3a7Alexey Starikovskiy#endif 291a6ba5ebef91a59fabd45962e576c02468dbcd33fPatrick Mochel status = acpi_install_notify_handler(device->handle, 29203d782524e2d0511317769521c8d5daadbab8482Christian Lupien ACPI_ALL_NOTIFY, acpi_ac_notify, 2934be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown ac); 2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ACPI_FAILURE(status)) { 2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds result = -ENODEV; 2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto end; 2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2994be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown printk(KERN_INFO PREFIX "%s [%s] (%s)\n", 3004be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown acpi_device_name(device), acpi_device_bid(device), 3014be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown ac->state ? "on-line" : "off-line"); 3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3034be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown end: 3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (result) { 305fdcedbba2f98c94bfbac9f6e712ab765f997b8dcAlexey Starikovskiy#ifdef CONFIG_ACPI_PROCFS_POWER 3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds acpi_ac_remove_fs(device); 3078a246ee43f4b1df3fa5cbf9c4a3d3dcad0b1e08cAndrey Borzenkov#endif 3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(ac); 3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 311d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return result; 3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3145bfeca3138a6031e38c566d57128ff592eb009a8Alexey Starikovskiystatic int acpi_ac_resume(struct acpi_device *device) 3155bfeca3138a6031e38c566d57128ff592eb009a8Alexey Starikovskiy{ 3165bfeca3138a6031e38c566d57128ff592eb009a8Alexey Starikovskiy struct acpi_ac *ac; 3175bfeca3138a6031e38c566d57128ff592eb009a8Alexey Starikovskiy unsigned old_state; 3185bfeca3138a6031e38c566d57128ff592eb009a8Alexey Starikovskiy if (!device || !acpi_driver_data(device)) 3195bfeca3138a6031e38c566d57128ff592eb009a8Alexey Starikovskiy return -EINVAL; 3205bfeca3138a6031e38c566d57128ff592eb009a8Alexey Starikovskiy ac = acpi_driver_data(device); 3215bfeca3138a6031e38c566d57128ff592eb009a8Alexey Starikovskiy old_state = ac->state; 3225bfeca3138a6031e38c566d57128ff592eb009a8Alexey Starikovskiy if (acpi_ac_get_state(ac)) 3235bfeca3138a6031e38c566d57128ff592eb009a8Alexey Starikovskiy return 0; 32497749cd9adbb2985e4b2aee1a59d6b970fe9c3a7Alexey Starikovskiy#ifdef CONFIG_ACPI_SYSFS_POWER 3255bfeca3138a6031e38c566d57128ff592eb009a8Alexey Starikovskiy if (old_state != ac->state) 3265bfeca3138a6031e38c566d57128ff592eb009a8Alexey Starikovskiy kobject_uevent(&ac->charger.dev->kobj, KOBJ_CHANGE); 32797749cd9adbb2985e4b2aee1a59d6b970fe9c3a7Alexey Starikovskiy#endif 3285bfeca3138a6031e38c566d57128ff592eb009a8Alexey Starikovskiy return 0; 3295bfeca3138a6031e38c566d57128ff592eb009a8Alexey Starikovskiy} 3305bfeca3138a6031e38c566d57128ff592eb009a8Alexey Starikovskiy 3314be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownstatic int acpi_ac_remove(struct acpi_device *device, int type) 3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3334be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown acpi_status status = AE_OK; 3344be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown struct acpi_ac *ac = NULL; 3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!device || !acpi_driver_data(device)) 338d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return -EINVAL; 3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 34050dd096973f1d95aa03c6a6d9e148d706b62b68eJan Engelhardt ac = acpi_driver_data(device); 3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 342a6ba5ebef91a59fabd45962e576c02468dbcd33fPatrick Mochel status = acpi_remove_notify_handler(device->handle, 34303d782524e2d0511317769521c8d5daadbab8482Christian Lupien ACPI_ALL_NOTIFY, acpi_ac_notify); 34497749cd9adbb2985e4b2aee1a59d6b970fe9c3a7Alexey Starikovskiy#ifdef CONFIG_ACPI_SYSFS_POWER 345d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy if (ac->charger.dev) 346d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy power_supply_unregister(&ac->charger); 34797749cd9adbb2985e4b2aee1a59d6b970fe9c3a7Alexey Starikovskiy#endif 348fdcedbba2f98c94bfbac9f6e712ab765f997b8dcAlexey Starikovskiy#ifdef CONFIG_ACPI_PROCFS_POWER 3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds acpi_ac_remove_fs(device); 3508a246ee43f4b1df3fa5cbf9c4a3d3dcad0b1e08cAndrey Borzenkov#endif 3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(ac); 3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 354d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return 0; 3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3574be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownstatic int __init acpi_ac_init(void) 3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3593f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend int result; 3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3614d8316d5ea4dcf0bf15d8a06d539ed7c99e9cfbePavel Machek if (acpi_disabled) 3624d8316d5ea4dcf0bf15d8a06d539ed7c99e9cfbePavel Machek return -ENODEV; 3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 364fdcedbba2f98c94bfbac9f6e712ab765f997b8dcAlexey Starikovskiy#ifdef CONFIG_ACPI_PROCFS_POWER 3653f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend acpi_ac_dir = acpi_lock_ac_dir(); 3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!acpi_ac_dir) 367d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return -ENODEV; 3688a246ee43f4b1df3fa5cbf9c4a3d3dcad0b1e08cAndrey Borzenkov#endif 3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds result = acpi_bus_register_driver(&acpi_ac_driver); 3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (result < 0) { 372fdcedbba2f98c94bfbac9f6e712ab765f997b8dcAlexey Starikovskiy#ifdef CONFIG_ACPI_PROCFS_POWER 3733f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend acpi_unlock_ac_dir(acpi_ac_dir); 3748a246ee43f4b1df3fa5cbf9c4a3d3dcad0b1e08cAndrey Borzenkov#endif 375d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return -ENODEV; 3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 378d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return 0; 3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3814be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownstatic void __exit acpi_ac_exit(void) 3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds acpi_bus_unregister_driver(&acpi_ac_driver); 3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 386fdcedbba2f98c94bfbac9f6e712ab765f997b8dcAlexey Starikovskiy#ifdef CONFIG_ACPI_PROCFS_POWER 3873f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend acpi_unlock_ac_dir(acpi_ac_dir); 3888a246ee43f4b1df3fa5cbf9c4a3d3dcad0b1e08cAndrey Borzenkov#endif 3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 390d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return; 3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(acpi_ac_init); 3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(acpi_ac_exit); 395