ASOC From: Alexey Starikovskiy --- drivers/acpi/Makefile | 1 drivers/acpi/asoc.c | 154 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 155 insertions(+), 0 deletions(-) diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index d4336f1..0e61225 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -60,3 +60,4 @@ obj-$(CONFIG_ACPI_TOSHIBA) += toshiba_acpi.o obj-$(CONFIG_ACPI_HOTPLUG_MEMORY) += acpi_memhotplug.o obj-y += cm_sbs.o obj-$(CONFIG_ACPI_SBS) += sbs.o +obj-m += asoc.o diff --git a/drivers/acpi/asoc.c b/drivers/acpi/asoc.c new file mode 100644 index 0000000..996ca9e --- /dev/null +++ b/drivers/acpi/asoc.c @@ -0,0 +1,154 @@ +/* + * acpi_ac.c - ACPI ASUS hwmon driver + * + * Copyright (C) 2007 Alexey Starikovskiy + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + */ + +#include +#include +#include +#include +#include +#include +#include +#include + + +MODULE_AUTHOR("Alexey Starikovskiy"); +MODULE_DESCRIPTION("ACPI ASUS hwmon Driver"); +MODULE_LICENSE("GPL"); + +static int acpi_asoc_add(struct acpi_device *device); +static int acpi_asoc_remove(struct acpi_device *device, int type); + +static struct acpi_driver acpi_asoc_driver = { + .name = "asoc", + .class = "ACPI ASUS hwmon", + .ids = "ATK0110", + .ops = { + .add = acpi_asoc_add, + .remove = acpi_asoc_remove, + }, +}; + +struct acpi_asoc { + struct acpi_device * device; +}; + +static acpi_status asoc_read_sif(struct acpi_device *device, char prefix) +{ + int i, ret = 0; + unsigned long value; + acpi_status status = 0; + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; + struct acpi_buffer buffer2 = { ACPI_ALLOCATE_BUFFER, NULL }; + union acpi_object *fsif = NULL; + union acpi_object *fdesc = NULL; + union acpi_object arg = {.type = ACPI_TYPE_INTEGER}; + struct acpi_object_list arglist = {.count = 1, .pointer = &arg}; + char name[5]; + + snprintf(name, 5, "%cSIF", prefix); + status = acpi_evaluate_object(device->handle, name, NULL, &buffer); + if (ACPI_FAILURE(status)) { + printk(KERN_ERR PREFIX "Evaluating %s failed, status = %d\n", name, (int)status); + return -ENODEV; + } + + fsif = buffer.pointer; + if (!fsif || (fsif->type != ACPI_TYPE_PACKAGE) || (!fsif->package.count)) { + printk(KERN_ERR PREFIX "Invalid data\n"); + ret = -EFAULT; + goto error; + } + for (i = 1; i < fsif->package.count; ++i) { + status = acpi_evaluate_object(fsif->package.elements[i].reference.handle, NULL, NULL, &buffer2); + if (ACPI_FAILURE(status)) { + printk("element evaluation failed, status = %d\n", (int)status); + ret = -EFAULT; + goto error; + } + fdesc = buffer2.pointer; + snprintf(name, 5, "%cGET", prefix); + arg.integer.value = i - 1; + status = acpi_evaluate_integer(device->handle, name, &arglist, &value); + if (ACPI_FAILURE(status)) { + printk("%s evaluation failed, status = %d\n", name, (int)status); + ret = -EFAULT; + kfree(buffer2.pointer); + goto error; + } + printk(KERN_INFO PREFIX "\"%s\" [%d,%d] = %ld\n", + fdesc->package.elements[1].string.pointer, + (int)fdesc->package.elements[2].integer.value, + (int)fdesc->package.elements[3].integer.value, + value); + kfree(fdesc); + buffer2.pointer = NULL; + buffer2.length = ACPI_ALLOCATE_BUFFER; + } +error: + kfree(buffer.pointer); + return ret; +} + +static int acpi_asoc_add(struct acpi_device *device) +{ + int i, result = 0; + acpi_status status = AE_OK; + struct acpi_ac *ac = NULL; + char prefix[] = {'V', 'T', 'F'}; + + if (!device) + return -EINVAL; + for (i = 0; i < 3; ++i) { + result = asoc_read_sif(device, prefix[i]); + if (result) + return result; + } + return result; +} + +static int acpi_asoc_remove(struct acpi_device *device, int type) +{ + acpi_status status = AE_OK; + + if (!device) + return -EINVAL; + + return 0; +} + +static int __init acpi_asoc_init(void) +{ + if (acpi_disabled) + return -ENODEV; + acpi_bus_register_driver(&acpi_asoc_driver); + return 0; +} + +static void __exit acpi_asoc_exit(void) +{ + acpi_bus_unregister_driver(&acpi_asoc_driver); +} + +module_init(acpi_asoc_init); +module_exit(acpi_asoc_exit);