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> 285a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/types.h> 31fdcedbba2f98c94bfbac9f6e712ab765f997b8dcAlexey Starikovskiy#ifdef CONFIG_ACPI_PROCFS_POWER 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/proc_fs.h> 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/seq_file.h> 348a246ee43f4b1df3fa5cbf9c4a3d3dcad0b1e08cAndrey Borzenkov#endif 35d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy#include <linux/power_supply.h> 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <acpi/acpi_bus.h> 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <acpi/acpi_drivers.h> 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 39a192a9580bcc41692be1f36b77c3b681827f566aLen Brown#define PREFIX "ACPI: " 40a192a9580bcc41692be1f36b77c3b681827f566aLen Brown 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); 6548fe112744d1ff2e899a6491633ac58a3229aabfBjorn Helgaasstatic void acpi_ac_notify(struct acpi_device *device, u32 event); 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 67b299c22c8c1024a5a89d19524e24b3e1d67e9eabTobias Klauserstatic const struct acpi_device_id ac_device_ids[] = { 681ba90e3a87c46500623afdc3898573e4a5ebb21bThomas Renninger {"ACPI0003", 0}, 691ba90e3a87c46500623afdc3898573e4a5ebb21bThomas Renninger {"", 0}, 701ba90e3a87c46500623afdc3898573e4a5ebb21bThomas Renninger}; 711ba90e3a87c46500623afdc3898573e4a5ebb21bThomas RenningerMODULE_DEVICE_TABLE(acpi, ac_device_ids); 721ba90e3a87c46500623afdc3898573e4a5ebb21bThomas Renninger 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct acpi_driver acpi_ac_driver = { 74c2b6705b75d9c7aff98a4602a32230639e10891cLen Brown .name = "ac", 754be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown .class = ACPI_AC_CLASS, 761ba90e3a87c46500623afdc3898573e4a5ebb21bThomas Renninger .ids = ac_device_ids, 7748fe112744d1ff2e899a6491633ac58a3229aabfBjorn Helgaas .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS, 784be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown .ops = { 794be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown .add = acpi_ac_add, 804be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown .remove = acpi_ac_remove, 815bfeca3138a6031e38c566d57128ff592eb009a8Alexey Starikovskiy .resume = acpi_ac_resume, 8248fe112744d1ff2e899a6491633ac58a3229aabfBjorn Helgaas .notify = acpi_ac_notify, 834be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown }, 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct acpi_ac { 87d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy struct power_supply charger; 88af96179a8298832cc58be212d0e4988d8a1e11bfPatrick Mochel struct acpi_device * device; 8927663c5855b10af9ec67bc7dfba001426ba21222Matthew Wilcox unsigned long long state; 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 92497888cf69bf607ac1fe061a6437e0a670b0022fPhil Carmody#define to_acpi_ac(x) container_of(x, struct acpi_ac, charger) 93d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy 94fdcedbba2f98c94bfbac9f6e712ab765f997b8dcAlexey Starikovskiy#ifdef CONFIG_ACPI_PROCFS_POWER 95d75080328affb4b268da430b7074cc8139cc662aArjan van de Venstatic const struct file_operations acpi_ac_fops = { 96cf7acfab032ff262f42954328cdfd20a5d9aaaacDenis V. Lunev .owner = THIS_MODULE, 974be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown .open = acpi_ac_open_fs, 984be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown .read = seq_read, 994be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown .llseek = seq_lseek, 1004be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown .release = single_release, 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1028a246ee43f4b1df3fa5cbf9c4a3d3dcad0b1e08cAndrey Borzenkov#endif 103d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* -------------------------------------------------------------------------- 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds AC Adapter Management 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds -------------------------------------------------------------------------- */ 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1084be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownstatic int acpi_ac_get_state(struct acpi_ac *ac) 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1104be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown acpi_status status = AE_OK; 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!ac) 114d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return -EINVAL; 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 116a6ba5ebef91a59fabd45962e576c02468dbcd33fPatrick Mochel status = acpi_evaluate_integer(ac->device->handle, "_PSR", NULL, &ac->state); 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ACPI_FAILURE(status)) { 118a6fc67202e0224e6c9d1d285cc0b444bce887ed5Thomas Renninger ACPI_EXCEPTION((AE_INFO, status, "Error reading AC Adapter state")); 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ac->state = ACPI_AC_STATUS_UNKNOWN; 120d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return -ENODEV; 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1224be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown 123d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return 0; 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1263151dbb04ad5a5bd6358371c0bfb457216d00205Zhang Rui/* -------------------------------------------------------------------------- 1273151dbb04ad5a5bd6358371c0bfb457216d00205Zhang Rui sysfs I/F 1283151dbb04ad5a5bd6358371c0bfb457216d00205Zhang Rui -------------------------------------------------------------------------- */ 1293151dbb04ad5a5bd6358371c0bfb457216d00205Zhang Ruistatic int get_ac_property(struct power_supply *psy, 1303151dbb04ad5a5bd6358371c0bfb457216d00205Zhang Rui enum power_supply_property psp, 1313151dbb04ad5a5bd6358371c0bfb457216d00205Zhang Rui union power_supply_propval *val) 1323151dbb04ad5a5bd6358371c0bfb457216d00205Zhang Rui{ 1333151dbb04ad5a5bd6358371c0bfb457216d00205Zhang Rui struct acpi_ac *ac = to_acpi_ac(psy); 1343151dbb04ad5a5bd6358371c0bfb457216d00205Zhang Rui 1353151dbb04ad5a5bd6358371c0bfb457216d00205Zhang Rui if (!ac) 1363151dbb04ad5a5bd6358371c0bfb457216d00205Zhang Rui return -ENODEV; 1373151dbb04ad5a5bd6358371c0bfb457216d00205Zhang Rui 1383151dbb04ad5a5bd6358371c0bfb457216d00205Zhang Rui if (acpi_ac_get_state(ac)) 1393151dbb04ad5a5bd6358371c0bfb457216d00205Zhang Rui return -ENODEV; 1403151dbb04ad5a5bd6358371c0bfb457216d00205Zhang Rui 1413151dbb04ad5a5bd6358371c0bfb457216d00205Zhang Rui switch (psp) { 1423151dbb04ad5a5bd6358371c0bfb457216d00205Zhang Rui case POWER_SUPPLY_PROP_ONLINE: 1433151dbb04ad5a5bd6358371c0bfb457216d00205Zhang Rui val->intval = ac->state; 1443151dbb04ad5a5bd6358371c0bfb457216d00205Zhang Rui break; 1453151dbb04ad5a5bd6358371c0bfb457216d00205Zhang Rui default: 1463151dbb04ad5a5bd6358371c0bfb457216d00205Zhang Rui return -EINVAL; 1473151dbb04ad5a5bd6358371c0bfb457216d00205Zhang Rui } 1483151dbb04ad5a5bd6358371c0bfb457216d00205Zhang Rui return 0; 1493151dbb04ad5a5bd6358371c0bfb457216d00205Zhang Rui} 1503151dbb04ad5a5bd6358371c0bfb457216d00205Zhang Rui 1513151dbb04ad5a5bd6358371c0bfb457216d00205Zhang Ruistatic enum power_supply_property ac_props[] = { 1523151dbb04ad5a5bd6358371c0bfb457216d00205Zhang Rui POWER_SUPPLY_PROP_ONLINE, 1533151dbb04ad5a5bd6358371c0bfb457216d00205Zhang Rui}; 1543151dbb04ad5a5bd6358371c0bfb457216d00205Zhang Rui 155fdcedbba2f98c94bfbac9f6e712ab765f997b8dcAlexey Starikovskiy#ifdef CONFIG_ACPI_PROCFS_POWER 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* -------------------------------------------------------------------------- 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FS Interface (/proc) 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds -------------------------------------------------------------------------- */ 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1604be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownstatic struct proc_dir_entry *acpi_ac_dir; 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int acpi_ac_seq_show(struct seq_file *seq, void *offset) 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 16450dd096973f1d95aa03c6a6d9e148d706b62b68eJan Engelhardt struct acpi_ac *ac = seq->private; 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!ac) 168d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return 0; 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (acpi_ac_get_state(ac)) { 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds seq_puts(seq, "ERROR: Unable to read AC Adapter state\n"); 172d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return 0; 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds seq_puts(seq, "state: "); 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (ac->state) { 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case ACPI_AC_STATUS_OFFLINE: 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds seq_puts(seq, "off-line\n"); 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case ACPI_AC_STATUS_ONLINE: 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds seq_puts(seq, "on-line\n"); 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds seq_puts(seq, "unknown\n"); 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 188d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return 0; 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1904be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int acpi_ac_open_fs(struct inode *inode, struct file *file) 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return single_open(file, acpi_ac_seq_show, PDE(inode)->data); 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1964be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownstatic int acpi_ac_add_fs(struct acpi_device *device) 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1984be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown struct proc_dir_entry *entry = NULL; 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2006d855fcdd24d2491455527c4999b4d04363f1980Zhang Rui printk(KERN_WARNING PREFIX "Deprecated procfs I/F for AC is loaded," 2016d855fcdd24d2491455527c4999b4d04363f1980Zhang Rui " please retry with CONFIG_ACPI_PROCFS_POWER cleared\n"); 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!acpi_device_dir(device)) { 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), 2044be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown acpi_ac_dir); 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!acpi_device_dir(device)) 206d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return -ENODEV; 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 'state' [R] */ 210cf7acfab032ff262f42954328cdfd20a5d9aaaacDenis V. Lunev entry = proc_create_data(ACPI_AC_FILE_STATE, 211cf7acfab032ff262f42954328cdfd20a5d9aaaacDenis V. Lunev S_IRUGO, acpi_device_dir(device), 212cf7acfab032ff262f42954328cdfd20a5d9aaaacDenis V. Lunev &acpi_ac_fops, acpi_driver_data(device)); 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!entry) 214d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return -ENODEV; 215d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return 0; 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2184be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownstatic int acpi_ac_remove_fs(struct acpi_device *device) 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (acpi_device_dir(device)) { 2224be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown remove_proc_entry(ACPI_AC_FILE_STATE, acpi_device_dir(device)); 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds remove_proc_entry(acpi_device_bid(device), acpi_ac_dir); 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds acpi_device_dir(device) = NULL; 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 228d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return 0; 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2308a246ee43f4b1df3fa5cbf9c4a3d3dcad0b1e08cAndrey Borzenkov#endif 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* -------------------------------------------------------------------------- 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Driver Model 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds -------------------------------------------------------------------------- */ 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 23648fe112744d1ff2e899a6491633ac58a3229aabfBjorn Helgaasstatic void acpi_ac_notify(struct acpi_device *device, u32 event) 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 23848fe112744d1ff2e899a6491633ac58a3229aabfBjorn Helgaas struct acpi_ac *ac = acpi_driver_data(device); 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!ac) 242d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return; 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (event) { 245f163ff5176a8e9c827d8ebe044710d67d40799c3Len Brown default: 246f163ff5176a8e9c827d8ebe044710d67d40799c3Len Brown ACPI_DEBUG_PRINT((ACPI_DB_INFO, 247f163ff5176a8e9c827d8ebe044710d67d40799c3Len Brown "Unsupported event [0x%x]\n", event)); 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case ACPI_AC_NOTIFY_STATUS: 24903d782524e2d0511317769521c8d5daadbab8482Christian Lupien case ACPI_NOTIFY_BUS_CHECK: 25003d782524e2d0511317769521c8d5daadbab8482Christian Lupien case ACPI_NOTIFY_DEVICE_CHECK: 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds acpi_ac_get_state(ac); 25214e04fb34ffa82ee61ae69f98d8fca12d2e8e31cLen Brown acpi_bus_generate_proc_event(device, event, (u32) ac->state); 253962ce8ca0604af0c3c5609f7613d4ec5fcfac623Zhang Rui acpi_bus_generate_netlink_event(device->pnp.device_class, 2540794469da3f7b2093575cbdfc1108308dd3641ceKay Sievers dev_name(&device->dev), event, 255962ce8ca0604af0c3c5609f7613d4ec5fcfac623Zhang Rui (u32) ac->state); 25668b92b567c0c5e6f4d0b264d438f97ee5ccbdcccMark Langsdorf acpi_notifier_call_chain(device, event, (u32) ac->state); 257d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy kobject_uevent(&ac->charger.dev->kobj, KOBJ_CHANGE); 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 260d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return; 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2634be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownstatic int acpi_ac_add(struct acpi_device *device) 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2654be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown int result = 0; 2664be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown struct acpi_ac *ac = NULL; 2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!device) 270d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return -EINVAL; 2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 27236bcbec7ce21e2e8b3143b11a05747330abeca70Burman Yan ac = kzalloc(sizeof(struct acpi_ac), GFP_KERNEL); 2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!ac) 274d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return -ENOMEM; 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 276af96179a8298832cc58be212d0e4988d8a1e11bfPatrick Mochel ac->device = device; 2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds strcpy(acpi_device_name(device), ACPI_AC_DEVICE_NAME); 2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds strcpy(acpi_device_class(device), ACPI_AC_CLASS); 279db89b4f0dbab837d0f3de2c3e9427a8d5393afa3Pavel Machek device->driver_data = ac; 2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds result = acpi_ac_get_state(ac); 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (result) 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto end; 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 285fdcedbba2f98c94bfbac9f6e712ab765f997b8dcAlexey Starikovskiy#ifdef CONFIG_ACPI_PROCFS_POWER 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds result = acpi_ac_add_fs(device); 2878a246ee43f4b1df3fa5cbf9c4a3d3dcad0b1e08cAndrey Borzenkov#endif 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (result) 2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto end; 290d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy ac->charger.name = acpi_device_bid(device); 291d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy ac->charger.type = POWER_SUPPLY_TYPE_MAINS; 292d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy ac->charger.properties = ac_props; 293d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy ac->charger.num_properties = ARRAY_SIZE(ac_props); 294d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy ac->charger.get_property = get_ac_property; 295d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy power_supply_register(&ac->device->dev, &ac->charger); 2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2974be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown printk(KERN_INFO PREFIX "%s [%s] (%s)\n", 2984be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown acpi_device_name(device), acpi_device_bid(device), 2994be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown ac->state ? "on-line" : "off-line"); 3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3014be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown end: 3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (result) { 303fdcedbba2f98c94bfbac9f6e712ab765f997b8dcAlexey Starikovskiy#ifdef CONFIG_ACPI_PROCFS_POWER 3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds acpi_ac_remove_fs(device); 3058a246ee43f4b1df3fa5cbf9c4a3d3dcad0b1e08cAndrey Borzenkov#endif 3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(ac); 3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 309d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return result; 3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3125bfeca3138a6031e38c566d57128ff592eb009a8Alexey Starikovskiystatic int acpi_ac_resume(struct acpi_device *device) 3135bfeca3138a6031e38c566d57128ff592eb009a8Alexey Starikovskiy{ 3145bfeca3138a6031e38c566d57128ff592eb009a8Alexey Starikovskiy struct acpi_ac *ac; 3155bfeca3138a6031e38c566d57128ff592eb009a8Alexey Starikovskiy unsigned old_state; 3165bfeca3138a6031e38c566d57128ff592eb009a8Alexey Starikovskiy if (!device || !acpi_driver_data(device)) 3175bfeca3138a6031e38c566d57128ff592eb009a8Alexey Starikovskiy return -EINVAL; 3185bfeca3138a6031e38c566d57128ff592eb009a8Alexey Starikovskiy ac = acpi_driver_data(device); 3195bfeca3138a6031e38c566d57128ff592eb009a8Alexey Starikovskiy old_state = ac->state; 3205bfeca3138a6031e38c566d57128ff592eb009a8Alexey Starikovskiy if (acpi_ac_get_state(ac)) 3215bfeca3138a6031e38c566d57128ff592eb009a8Alexey Starikovskiy return 0; 3225bfeca3138a6031e38c566d57128ff592eb009a8Alexey Starikovskiy if (old_state != ac->state) 3235bfeca3138a6031e38c566d57128ff592eb009a8Alexey Starikovskiy kobject_uevent(&ac->charger.dev->kobj, KOBJ_CHANGE); 3245bfeca3138a6031e38c566d57128ff592eb009a8Alexey Starikovskiy return 0; 3255bfeca3138a6031e38c566d57128ff592eb009a8Alexey Starikovskiy} 3265bfeca3138a6031e38c566d57128ff592eb009a8Alexey Starikovskiy 3274be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownstatic int acpi_ac_remove(struct acpi_device *device, int type) 3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3294be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown struct acpi_ac *ac = NULL; 3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!device || !acpi_driver_data(device)) 333d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return -EINVAL; 3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 33550dd096973f1d95aa03c6a6d9e148d706b62b68eJan Engelhardt ac = acpi_driver_data(device); 3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 337d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy if (ac->charger.dev) 338d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy power_supply_unregister(&ac->charger); 339fdcedbba2f98c94bfbac9f6e712ab765f997b8dcAlexey Starikovskiy#ifdef CONFIG_ACPI_PROCFS_POWER 3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds acpi_ac_remove_fs(device); 3418a246ee43f4b1df3fa5cbf9c4a3d3dcad0b1e08cAndrey Borzenkov#endif 3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(ac); 3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 345d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return 0; 3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3484be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownstatic int __init acpi_ac_init(void) 3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3503f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend int result; 3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3524d8316d5ea4dcf0bf15d8a06d539ed7c99e9cfbePavel Machek if (acpi_disabled) 3534d8316d5ea4dcf0bf15d8a06d539ed7c99e9cfbePavel Machek return -ENODEV; 3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 355fdcedbba2f98c94bfbac9f6e712ab765f997b8dcAlexey Starikovskiy#ifdef CONFIG_ACPI_PROCFS_POWER 3563f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend acpi_ac_dir = acpi_lock_ac_dir(); 3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!acpi_ac_dir) 358d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return -ENODEV; 3598a246ee43f4b1df3fa5cbf9c4a3d3dcad0b1e08cAndrey Borzenkov#endif 3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds result = acpi_bus_register_driver(&acpi_ac_driver); 3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (result < 0) { 363fdcedbba2f98c94bfbac9f6e712ab765f997b8dcAlexey Starikovskiy#ifdef CONFIG_ACPI_PROCFS_POWER 3643f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend acpi_unlock_ac_dir(acpi_ac_dir); 3658a246ee43f4b1df3fa5cbf9c4a3d3dcad0b1e08cAndrey Borzenkov#endif 366d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return -ENODEV; 3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 369d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return 0; 3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3724be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownstatic void __exit acpi_ac_exit(void) 3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds acpi_bus_unregister_driver(&acpi_ac_driver); 3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 377fdcedbba2f98c94bfbac9f6e712ab765f997b8dcAlexey Starikovskiy#ifdef CONFIG_ACPI_PROCFS_POWER 3783f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend acpi_unlock_ac_dir(acpi_ac_dir); 3798a246ee43f4b1df3fa5cbf9c4a3d3dcad0b1e08cAndrey Borzenkov#endif 3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 381d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return; 3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(acpi_ac_init); 3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(acpi_ac_exit); 386