# This is a BitKeeper generated patch for the following project: # Project Name: Linux kernel tree # This patch format is intended for GNU patch command version 2.5 or higher. # This patch includes the following deltas: # ChangeSet 1.1117 -> 1.1118 # drivers/acpi/asus_acpi.c 1.2 -> 1.3 # # The following is the BitKeeper ChangeSet Log # -------------------------------------------- # 03/09/30 len.brown@intel.com 1.1118 # [ACPI] acpi4asus-0.25-0.26 (Karol Kozimor) # -------------------------------------------- # diff -Nru a/drivers/acpi/asus_acpi.c b/drivers/acpi/asus_acpi.c --- a/drivers/acpi/asus_acpi.c Tue Sep 30 16:51:29 2003 +++ b/drivers/acpi/asus_acpi.c Tue Sep 30 16:51:29 2003 @@ -30,10 +30,6 @@ * add Fn key status * Add mode selection on module loading (parameter) -> still necessary? * Complete display switching -- may require dirty hacks? - * Complete support for Centrino laptops - * Reading certain fields (e.g. \SG66 in A2500H) consistently fails, while - * reading others (\BAOF, the same machine) succeeds. Why? - * */ #include @@ -49,7 +45,7 @@ #include #include -#define ASUS_ACPI_VERSION "0.25" +#define ASUS_ACPI_VERSION "0.26" #define PROC_ASUS "asus" //the directory #define PROC_MLED "mled" @@ -123,16 +119,18 @@ A2X, //A2500H D1X, //D1 L1X, //L1400B - L2X, //L200D -> TODO check Q11 (Fn+F8) + L2X, //L2000D -> TODO check Q11 (Fn+F8) // Calling this method simply hangs the // computer, ISMI method hangs the laptop. L3D, //L3400D L3X, //L3C + L5X, //L5C TODO this model seems to have one more + // LED, add support M2X, //M2400E M3N, //M3700N, but also S1300N -> TODO WLED S1X, //S1300A -> TODO special keys do not work ? S2X, //S200 (J1 reported), Victor MP-XP7210 - //TODO A1370D does not seems to have a ATK device + //TODO A1370D does not seem to have an ATK device // L8400 model doesn't have ATK END_MODEL } model; //Models currently supported @@ -181,6 +179,9 @@ L3X_PREFIX "_Q0F", L3X_PREFIX "_Q0E", "SPLV", "GPLV", "\\BLVL", "SDSP", "\\_SB.PCI0.PCI1.VGAC.NMAP"}, + {"L5X", "MLED", NULL, "WLED", "WRED", "\\Q0D", "\\BAOF", + "\\Q0C","\\Q0B", "SPLV", "GPLV", NULL, "SDSP", "\\INFB"}, + {"M2X", "MLED", NULL, "WLED", NULL, "\\Q10", "\\GP06", "\\Q0E","\\Q0F", "SPLV", "GPLV", NULL, "SDSP", "\\INFB"}, @@ -268,6 +269,7 @@ void *data) { int len = 0; + int sfun; struct asus_hotk *hotk = (struct asus_hotk *) data; char buf[16]; //enough for all info /* @@ -276,28 +278,27 @@ */ len += sprintf(page, ACPI_HOTK_NAME " " ASUS_ACPI_VERSION "\n"); - len += - sprintf(page + len, "Model reference : %s\n", - hotk->methods->name); + len += sprintf(page + len, "Model reference : %s\n", + hotk->methods->name); + if(read_acpi_int(hotk->handle, "SFUN", &sfun)) + len += sprintf(page + len, "SFUN value : 0x%04x\n", sfun); if (asus_info) { - snprintf(buf, 5, "%s", asus_info->signature); - len += sprintf(page + len, "ACPI signature : %s\n", buf); snprintf(buf, 16, "%d", asus_info->length); - len += sprintf(page + len, "Table length : %s\n", buf); - snprintf(buf, 16, "%d", asus_info->revision); - len += sprintf(page + len, "ACPI minor version : %s\n", buf); + len += sprintf(page + len, "DSDT length : %s\n", buf); snprintf(buf, 16, "%d", asus_info->checksum); - len += sprintf(page + len, "Checksum : %s\n", buf); + len += sprintf(page + len, "DSDT checksum : %s\n", buf); + snprintf(buf, 16, "%d", asus_info->revision); + len += sprintf(page + len, "DSDT revision : %s\n", buf); snprintf(buf, 7, "%s", asus_info->oem_id); - len += sprintf(page + len, "OEM identification : %s\n", buf); + len += sprintf(page + len, "OEM id : %s\n", buf); snprintf(buf, 9, "%s", asus_info->oem_table_id); len += sprintf(page + len, "OEM table id : %s\n", buf); snprintf(buf, 16, "%x", asus_info->oem_revision); - len += sprintf(page + len, "OEM rev number : 0x%s\n", buf); + len += sprintf(page + len, "OEM revision : 0x%s\n", buf); snprintf(buf, 5, "%s", asus_info->asl_compiler_id); - len += sprintf(page + len, "ASL comp vendor ID : %s\n", buf); + len += sprintf(page + len, "ASL comp vendor id : %s\n", buf); snprintf(buf, 16, "%x", asus_info->asl_compiler_revision); - len += sprintf(page + len, "ASL comp rev number: 0x%s\n", buf); + len += sprintf(page + len, "ASL comp revision : 0x%s\n", buf); } return len; @@ -323,7 +324,7 @@ &led_status)) len = sprintf(page, "%d\n", led_status); else - printk(KERN_NOTICE "Asus ACPI: Error reading MLED " + printk(KERN_WARNING "Asus ACPI: Error reading MLED " "status\n"); } else { len = sprintf(page, "%d\n", (hotk->status & MLED_ON) ? 1 : 0); @@ -353,7 +354,7 @@ /* We don't have to check mt_mled exists if we are here :) */ if (!write_acpi_int(hotk->handle, hotk->methods->mt_mled, led_out, NULL)) - printk(KERN_NOTICE "Asus ACPI: MLED write failed\n"); + printk(KERN_WARNING "Asus ACPI: MLED write failed\n"); @@ -374,11 +375,11 @@ int led_status; if (hotk->methods->wled_status) { - if (read_acpi_int(NULL, hotk->methods->mled_status, + if (read_acpi_int(NULL, hotk->methods->wled_status, &led_status)) len = sprintf(page, "%d\n", led_status); else - printk(KERN_NOTICE "Asus ACPI: Error reading WLED " + printk(KERN_WARNING "Asus ACPI: Error reading WLED " "status\n"); } else { len = sprintf(page, "%d\n", (hotk->status & WLED_ON) ? 1 : 0); @@ -405,7 +406,7 @@ /* We don't have to check if mt_wled exists if we are here :) */ if (!write_acpi_int(hotk->handle, hotk->methods->mt_wled, led_out, NULL)) - printk(KERN_NOTICE "Asus ACPI: WLED write failed\n"); + printk(KERN_WARNING "Asus ACPI: WLED write failed\n"); return count; @@ -418,7 +419,7 @@ /* We don't have to check anything, if we are here */ if (!read_acpi_int(NULL, hotk->methods->lcd_status, &lcd)) - printk(KERN_NOTICE "Asus ACPI: Error reading LCD status\n"); + printk(KERN_WARNING "Asus ACPI: Error reading LCD status\n"); if (hotk->model == L2X) lcd = ~lcd; @@ -457,7 +458,7 @@ acpi_evaluate_object(NULL, hotk->methods->mt_lcd_switch, NULL, NULL); if (ACPI_FAILURE(status)) - printk(KERN_NOTICE "Asus ACPI: Error switching LCD\n"); + printk(KERN_WARNING "Asus ACPI: Error switching LCD\n"); } return count; @@ -475,7 +476,7 @@ if(hotk->methods->brightness_set) { if (!write_acpi_int(hotk->handle, hotk->methods->brightness_set, value, NULL)) - printk(KERN_NOTICE "Asus ACPI: Error changing brightness\n"); + printk(KERN_WARNING "Asus ACPI: Error changing brightness\n"); return; } @@ -488,7 +489,7 @@ NULL, NULL); (value > 0) ? value-- : value++; if (ACPI_FAILURE(status)) - printk(KERN_NOTICE "Asus ACPI: Error changing brightness\n"); + printk(KERN_WARNING "Asus ACPI: Error changing brightness\n"); } return; } @@ -500,11 +501,11 @@ if(hotk->methods->brightness_get) { /* SPLV/GPLV laptop */ if (!read_acpi_int(hotk->handle, hotk->methods->brightness_get, &value)) - printk(KERN_NOTICE "Asus ACPI: Error reading brightness\n"); + printk(KERN_WARNING "Asus ACPI: Error reading brightness\n"); } else if (hotk->methods->brightness_status) { /* For D1 for example */ if (!read_acpi_int(NULL, hotk->methods->brightness_status, &value)) - printk(KERN_NOTICE "Asus ACPI: Error reading brightness\n"); + printk(KERN_WARNING "Asus ACPI: Error reading brightness\n"); } else /* No GPLV method */ value = hotk->brightness; return value; @@ -531,7 +532,7 @@ /* 0 <= value <= 15 */ set_brightness(value, hotk); } else { - printk(KERN_NOTICE "Asus ACPI: Error reading user input\n"); + printk(KERN_WARNING "Asus ACPI: Error reading user input\n"); } return count; @@ -542,7 +543,7 @@ /* no sanity check needed for now */ if (!write_acpi_int(hotk->handle, hotk->methods->display_set, value, NULL)) - printk(KERN_NOTICE "Asus ACPI: Error setting display\n"); + printk(KERN_WARNING "Asus ACPI: Error setting display\n"); return; } @@ -559,7 +560,7 @@ struct asus_hotk *hotk = (struct asus_hotk *) data; if (!read_acpi_int(hotk->handle, hotk->methods->display_get, &value)) - printk(KERN_NOTICE "Asus ACPI: Error reading display status\n"); + printk(KERN_WARNING "Asus ACPI: Error reading display status\n"); return sprintf(page, "%d\n", value); } @@ -581,13 +582,13 @@ if (sscanf(buffer, "%d", &value) == 1) set_display(value, hotk); else { - printk(KERN_NOTICE "Asus ACPI: Error reading user input\n"); + printk(KERN_WARNING "Asus ACPI: Error reading user input\n"); } return count; } -static int asus_hotk_add_fs(struct acpi_device *device) +static int __init asus_hotk_add_fs(struct acpi_device *device) { struct proc_dir_entry *proc; struct asus_hotk *hotk = acpi_driver_data(device); @@ -601,7 +602,7 @@ if ((asus_uid == 0) && (asus_gid == 0)){ mode = S_IFREG | S_IRUGO | S_IWUGO; - }else{ + } else { mode = S_IFREG | S_IRUSR | S_IRGRP | S_IWUSR | S_IWGRP; } @@ -617,7 +618,7 @@ proc->uid = asus_uid; proc->gid = asus_gid;; } else { - printk(KERN_NOTICE " Unable to create " PROC_INFOS + printk(KERN_WARNING " Unable to create " PROC_INFOS " fs entry\n"); } @@ -631,7 +632,7 @@ proc->uid = asus_uid; proc->gid = asus_gid;; } else { - printk(KERN_NOTICE " Unable to create " PROC_WLED + printk(KERN_WARNING " Unable to create " PROC_WLED " fs entry\n"); } } @@ -646,7 +647,7 @@ proc->uid = asus_uid; proc->gid = asus_gid;; } else { - printk(KERN_NOTICE " Unable to create " PROC_MLED + printk(KERN_WARNING " Unable to create " PROC_MLED " fs entry\n"); } } @@ -665,7 +666,7 @@ proc->uid = asus_uid; proc->gid = asus_gid;; } else { - printk(KERN_NOTICE " Unable to create " PROC_LCD + printk(KERN_WARNING " Unable to create " PROC_LCD " fs entry\n"); } } @@ -681,7 +682,7 @@ proc->uid = asus_uid; proc->gid = asus_gid;; } else { - printk(KERN_NOTICE " Unable to create " PROC_BRN + printk(KERN_WARNING " Unable to create " PROC_BRN " fs entry\n"); } } @@ -696,12 +697,12 @@ proc->uid = asus_uid; proc->gid = asus_gid;; } else { - printk(KERN_NOTICE " Unable to create " PROC_DISP + printk(KERN_WARNING " Unable to create " PROC_DISP " fs entry\n"); } } - return (AE_OK); + return 0; } @@ -731,19 +732,40 @@ * This function is used to initialize the hotk with right values. In this * method, we can make all the detection we want, and modify the hotk struct */ -static int asus_hotk_get_info(struct asus_hotk *hotk) +static int __init asus_hotk_get_info(struct asus_hotk *hotk) { struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; + struct acpi_buffer dsdt = { ACPI_ALLOCATE_BUFFER, NULL }; union acpi_object *model = NULL; + int bsts_result; + acpi_status status; - /* - * We have to write 0 on init this far for all ASUS models + /* + * Get DSDT headers early enough to allow for differentiating between + * models, but late enough to allow acpi_bus_register_driver() to fail + * before doing anything ACPI-specific. Should we encounter a machine, + * which needs special handling (i.e. its hotkey device has a different + * HID), this bit will be moved. A global variable asus_info contains + * the DSDT header. */ + status = acpi_get_table(ACPI_TABLE_DSDT, 1, &dsdt); + if (ACPI_FAILURE(status)) + printk(KERN_WARNING " Couldn't get the DSDT table header\n"); + else + asus_info = (struct acpi_table_header *) dsdt.pointer; + + /* We have to write 0 on init this far for all ASUS models */ if (!write_acpi_int(hotk->handle, "INIT", 0, &buffer)) { - printk(KERN_NOTICE " Hotkey initialization failed\n"); + printk(KERN_ERR " Hotkey initialization failed\n"); return -ENODEV; } + /* For testing purposes */ + if (!read_acpi_int(hotk->handle, "BSTS", &bsts_result)) + printk(KERN_WARNING " Error calling BSTS\n"); + else if (bsts_result) + printk(KERN_NOTICE " BSTS called, 0x%02x returned\n", bsts_result); + /* * Here, we also use asus_info to make decision. For example, on INIT * method, S1X and L1X models both reports to be L84F, but they don't @@ -773,12 +795,14 @@ hotk->model = M3N; /* S1300N is similar enough */ else if (strncmp(model->string.pointer, "L2", 2) == 0) hotk->model = L2X; - else if (strncmp(model->string.pointer, "L8", 2) == 0) + else if (strncmp(model->string.pointer, "L8", 2) == 0) { /* S1300A reports L84F, but L1400B too */ - if (strncmp(asus_info->oem_table_id, "L1", 2) == 0) - hotk->model = L1X; - else + if (asus_info) { + if (strncmp(asus_info->oem_table_id, "L1", 2) == 0) + hotk->model = L1X; + } else hotk->model = S1X; + } else if (strncmp(model->string.pointer, "D1", 2) == 0) hotk->model = D1X; else if (strncmp(model->string.pointer, "A1", 2) == 0) @@ -787,12 +811,13 @@ hotk->model = A2X; else if (strncmp(model->string.pointer, "J1", 2) == 0) hotk->model = S2X; - + else if (strncmp(model->string.pointer, "L5", 2) == 0) + hotk->model = L5X; if (hotk->model == END_MODEL) { /* By default use the same values, as I don't know others */ - printk("unsupported, trying default values, contact the " - "developers\n"); + printk("unsupported, trying default values, supply the " + "developers with your DSDT\n"); hotk->model = L2X; } else { printk("supported\n"); @@ -807,7 +832,7 @@ -static int asus_hotk_check(struct asus_hotk *hotk) +static int __init asus_hotk_check(struct asus_hotk *hotk) { int result = 0; @@ -821,7 +846,7 @@ if (hotk->device->status.present) { result = asus_hotk_get_info(hotk); } else { - printk(KERN_NOTICE " Hotkey device not present, aborting\n"); + printk(KERN_ERR " Hotkey device not present, aborting\n"); return(-EINVAL); } @@ -830,7 +855,7 @@ -static int asus_hotk_add(struct acpi_device *device) +static int __init asus_hotk_add(struct acpi_device *device) { struct asus_hotk *hotk = NULL; acpi_status status = AE_OK; @@ -839,6 +864,9 @@ if (!device) return(-EINVAL); + printk(KERN_NOTICE "Asus Laptop ACPI Extras version %s\n", + ASUS_ACPI_VERSION); + hotk = (struct asus_hotk *) kmalloc(sizeof(struct asus_hotk), GFP_KERNEL); if (!hotk) @@ -866,13 +894,8 @@ */ status = acpi_install_notify_handler(hotk->handle, ACPI_SYSTEM_NOTIFY, asus_hotk_notify, hotk); - if (ACPI_FAILURE(status)) { - printk(KERN_NOTICE - " Error installing notify handler\n"); - } else { - printk(KERN_DEBUG - " Notify Handler installed successfully\n"); - } + if (ACPI_FAILURE(status)) + printk(KERN_ERR " Error installing notify handler\n"); /* For laptops without GPLV: init the hotk->brightness value */ if ((!hotk->methods->brightness_get) && (!hotk->methods->brightness_status) && @@ -880,12 +903,12 @@ status = acpi_evaluate_object(NULL, hotk->methods->brightness_down, NULL, NULL); if (ACPI_FAILURE(status)) - printk(KERN_NOTICE " Error changing brightness\n"); + printk(KERN_WARNING " Error changing brightness\n"); else { status = acpi_evaluate_object(NULL, hotk->methods->brightness_up, NULL, NULL); if (ACPI_FAILURE(status)) - printk(KERN_NOTICE " Strange, error changing" + printk(KERN_WARNING " Strange, error changing" " brightness\n"); } } @@ -901,7 +924,7 @@ -static int asus_hotk_remove(struct acpi_device *device, int type) +static int __exit asus_hotk_remove(struct acpi_device *device, int type) { acpi_status status = 0; struct asus_hotk *hotk = NULL; @@ -914,7 +937,7 @@ status = acpi_remove_notify_handler(hotk->handle, ACPI_SYSTEM_NOTIFY, asus_hotk_notify); if (ACPI_FAILURE(status)) - printk(KERN_NOTICE "Error removing notify handler\n"); + printk(KERN_ERR "Asus ACPI: Error removing notify handler\n"); kfree(hotk); @@ -926,35 +949,17 @@ static int __init asus_acpi_init(void) { - int result = 0; - acpi_status status = 0; - struct acpi_buffer dsdt = { ACPI_ALLOCATE_BUFFER, NULL }; - - printk(KERN_NOTICE "Asus Laptop ACPI Extras version %s\n", - ASUS_ACPI_VERSION); - /* - * Here is the code to know the model we are running on. We need to - * know this before calling the acpi_bus_register_driver function, in - * case the HID for the laptop we are running on is different from - * ACPI_HOTK_HID, which I have never seen yet :) - * - * This information is then available in the global var asus_info - */ - status = acpi_get_table(ACPI_TABLE_DSDT, 1, &dsdt); - if (ACPI_FAILURE(status)) { - printk(KERN_NOTICE " Couldn't get the DSDT table header\n"); - } else { - asus_info = (struct acpi_table_header *) dsdt.pointer; - } + int result; asus_proc_dir = proc_mkdir(PROC_ASUS, acpi_root_dir); - if (!asus_proc_dir) + if (!asus_proc_dir) { + printk(KERN_ERR "Asus ACPI: Unable to create /proc entry"); return(-ENODEV); + } asus_proc_dir->owner = THIS_MODULE; result = acpi_bus_register_driver(&asus_hotk_driver); if (result < 0) { - printk(KERN_NOTICE " Error registering " ACPI_HOTK_NAME " \n"); remove_proc_entry(PROC_ASUS, acpi_root_dir); return(-ENODEV); }