Le lundi 4 décembre 2006 22:39, Panagiotis Papadakos a écrit : > Hello everybody. > > This patch is based on > http://www.mail-archive.com/linux-acpi@xxxxxxxxxxxxxxx/msg02277.html > and adds support for ASUS A6VA, M6V, W5F and V6V laptops in asus-acpi. > Also some trailing spaces cleanups. > > Regards > Papadakos Panagiotis You should take a look at acpi4asus cvs http://acpi4asus.sourceforge.net There is a lot of new models supported, /sys/class/backlight support, fix the bad defaults values problems, a lot of cleanups, light sens support, etc ... Patch against 2.6.19 attached. -- CHARY 'Iksaif' Corentin http://xf.iksaif.net
--- /usr/src/linux/drivers/acpi/asus_acpi.c 2006-12-02 11:50:05.000000000 +0100 +++ acpi4asus/driver/asus_acpi.c 2006-12-05 08:25:06.000000000 +0100 @@ -3,6 +3,7 @@ * * * Copyright (C) 2002-2005 Julien Lerouge, 2003-2006 Karol Kozimor + * Copyright (C) 2006 Corentin Chary * * 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 @@ -26,20 +27,37 @@ * Pontus Fuchs - Helper functions, cleanup * Johann Wiesner - Small compile fixes * John Belmonte - ACPI code for Toshiba laptop was a good starting point. - * Éric Burghard - LED display support for W1N - * + * Eric Burghard - LED display support for W1N + * Josh Green - Light Sens support + * Brice Arnould - Some help for parse_method() */ +#include <linux/version.h> + +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,18) +# include <linux/config.h> +#else +# include <linux/autoconf.h> +#endif + #include <linux/kernel.h> #include <linux/module.h> #include <linux/init.h> +#include <linux/platform_device.h> #include <linux/types.h> +#include <linux/err.h> #include <linux/proc_fs.h> +#include <linux/backlight.h> #include <acpi/acpi_drivers.h> #include <acpi/acpi_bus.h> #include <asm/uaccess.h> -#define ASUS_ACPI_VERSION "0.30" +#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE +# define CONFIG_ACPI_ASUS_NEW_BACKLIGHT +#endif + + +#define ASUS_ACPI_VERSION "0.31b2" #define PROC_ASUS "asus" //the directory #define PROC_MLED "mled" @@ -51,6 +69,8 @@ #define PROC_LCD "lcd" #define PROC_BRN "brn" #define PROC_DISP "disp" +#define PROC_LSSW "lssw" +#define PROC_LSLVL "lslvl" #define ACPI_HOTK_NAME "Asus Laptop ACPI Extras Driver" #define ACPI_HOTK_CLASS "hotkey" @@ -71,39 +91,53 @@ #define TLED_ON 0x04 //touchpad LED #define BT_ON 0x08 //internal Bluetooth -MODULE_AUTHOR("Julien Lerouge, Karol Kozimor"); +/* + * Methods configuration + */ +#define MT_MAX_ARGS 3 + +MODULE_AUTHOR("Julien Lerouge, Karol Kozimor, Corentin Chary"); MODULE_DESCRIPTION(ACPI_HOTK_NAME); MODULE_LICENSE("GPL"); -static uid_t asus_uid; -static gid_t asus_gid; -module_param(asus_uid, uint, 0); -MODULE_PARM_DESC(asus_uid, "UID for entries in /proc/acpi/asus.\n"); -module_param(asus_gid, uint, 0); -MODULE_PARM_DESC(asus_gid, "GID for entries in /proc/acpi/asus.\n"); +static uint unsupported; +module_param(unsupported, uint, 0); +MODULE_PARM_DESC(unsupported, "Allow the use of default values for an unsupported model.\n"); + -/* For each model, all features implemented, - * those marked with R are relative to HOTK, A for absolute */ +/* For each model, all features implemented, + * those marked with R are relative to HOTK, A for absolute. + */ struct model_data { char *name; //name of the laptop________________A - char *mt_mled; //method to handle mled_____________R + char *mled_set; //method to handle mled_____________R char *mled_status; //node to handle mled reading_______A - char *mt_wled; //method to handle wled_____________R + char *wled_set; //method to handle wled_____________R char *wled_status; //node to handle wled reading_______A - char *mt_tled; //method to handle tled_____________R + char *tled_set; //method to handle tled_____________R char *tled_status; //node to handle tled reading_______A - char *mt_ledd; //method to handle LED display______R - char *mt_bt_switch; //method to switch Bluetooth on/off_R - char *bt_status; //no model currently supports this__? - char *mt_lcd_switch; //method to turn LCD on/off_________A + char *ledd_set; //method to handle LED display______R + char *bt_switch; //method to switch Bluetooth on/off_R + char *bt_status; //method to read Bluetooth stat_____A + char *lcd_switch; //method to turn LCD on/off_________A char *lcd_status; //node to read LCD panel state______A char *brightness_up; //method to set brightness up_______A char *brightness_down; //guess what ?______________________A char *brightness_set; //method to set absolute brightness_R char *brightness_get; //method to get absolute brightness_R - char *brightness_status; //node to get brightness____________A + char *brightness_status; //node to get brightness____________A + char *light_sens_switch; //light sensor toggle method________R + char *light_sens_level; //light sensor level set method_____R char *display_set; //method to set video output________R char *display_get; //method to get video output________R + +}; + +/* A method have a name, and from 0 to MT_MAX_ARGS params ... */ +struct method { + const char * name; + struct acpi_object_list input; + union acpi_object params[MT_MAX_ARGS]; }; /* @@ -117,30 +151,53 @@ u32 ledd_status; //status of the LED display struct model_data *methods; //methods available on the laptop u8 brightness; //brightness level + u8 lcd_status; // status of the lcd + u8 disp_status; // guess what ? + u8 light_level; //light sensor level + u8 light_switch; //light sensor switch value enum { A1x = 0, //A1340D, A1300F + A2D, //A2D A2x, //A2500H + A3E, //A3E + A3F, //A3F, A6F + A3N, //A3N, A3L A4G, //A4700G + A6B, //A6B, A6K + A6J, //A6J + A6R, //A6R + A6T, //A6T, A6M + A6V, //A6V, A6Q + A8J, //A8J D1x, //D1 + F3J, //F3JM L2D, //L2000D L3C, //L3800C L3D, //L3400D L3H, //L3H, L2000E, L5D L4R, //L4500R - L5x, //L5800C + L5x, //L5800C L8L, //L8400L M1A, //M1300A M2E, //M2400E, L4400L M6N, //M6800N, W3400N M6R, //M6700R, A3000G + M6V, //M6A, M6V-B022P, M6V-8012P + M7A, //Z71A + M7V, //Z71V P30, //Samsung P30 S1x, //S1300A, but also L1400B and M2400A (L84F) S2x, //S200 (J1 reported), Victor MP-XP7210 + V6J, //V6J + V6V, //V6V W1N, //W1000N - W5A, //W5A W3V, //W3030V + W5A, //W5A + W5F, //W5F xxN, //M2400N, M3700N, M5200N, M6800N, S1300N, S5200N + Z96, //Z96F //(Centrino) + DEF, //Default values END_MODEL } model; //Models currently supported u16 event_count[128]; //count for each event TODO make this better @@ -154,6 +211,7 @@ #define S1x_PREFIX "\\_SB.PCI0.PX40." #define S2x_PREFIX A1x_PREFIX #define xxN_PREFIX "\\_SB.PCI0.SBRG.EC0." +#define A6x_PREFIX xxN_PREFIX static struct model_data model_conf[END_MODEL] = { /* @@ -163,39 +221,166 @@ { .name = "A1x", - .mt_mled = "MLED", + .mled_set = "MLED", .mled_status = "\\MAIL", - .mt_lcd_switch = A1x_PREFIX "_Q10", + .lcd_switch = A1x_PREFIX "_Q10", .lcd_status = "\\BKLI", .brightness_up = A1x_PREFIX "_Q0E", .brightness_down = A1x_PREFIX "_Q0F"}, { + .name = "A2D", + .mled_set = "MLED", + .wled_set = "WLED", + .lcd_switch = xxN_PREFIX "_Q10", + .lcd_status = "\\_SB.PCI0.SBRG.GO18", + .brightness_set = "SPLV", + .brightness_get = "GPLV", + .display_set = "SDSP", + .display_get = "\\ACTD"}, + + { .name = "A2x", - .mt_mled = "MLED", - .mt_wled = "WLED", + .mled_set = "MLED", + .wled_set = "WLED", .wled_status = "\\SG66", - .mt_lcd_switch = "\\Q10", + .lcd_switch = "\\Q10", .lcd_status = "\\BAOF", .brightness_set = "SPLV", .brightness_get = "GPLV", .display_set = "SDSP", - .display_get = "\\INFB"}, + .display_get = "\\INFB"}, + + { + .name = "A3E", + .mled_set = "MLED", + .wled_set = "WLED", + .lcd_switch = xxN_PREFIX "_Q10", + .lcd_status = xxN_PREFIX "RPIN(0x67)", + .brightness_set = "SPLV", + .brightness_get = "GPLV", + .display_set = "SDSP", + .display_get = "\\_SB.PCI0.P0P2.VGA.GETD"}, + + { + .name = "A3F", + .mled_set = "MLED", + .wled_set = "WLED", + .wled_status = "\\WRST", + .bt_switch = "BLED", + .bt_status = "\\BRST", + .lcd_switch = xxN_PREFIX "_Q10", + .lcd_status = xxN_PREFIX "RPIN(0x11)", + .brightness_set = "SPLV", + .brightness_get = "GPLV", + .display_set = "SDSP", + .display_get = "\\SSTE"}, + + { + .name = "A3N", + .mled_set = "MLED", + .wled_set = "WLED", + .wled_status = "\\WLDC", + .lcd_switch = xxN_PREFIX "_Q10", + .lcd_status = "\\BKLT", + .brightness_set = "SPLV", + .brightness_get = "GPLV", + .display_set = "SDSP", + .display_get = "\\SSTE"}, { .name = "A4G", - .mt_mled = "MLED", + .mled_set = "MLED", /* WLED present, but not controlled by ACPI */ - .mt_lcd_switch = xxN_PREFIX "_Q10", + .lcd_switch = xxN_PREFIX "_Q10", .brightness_set = "SPLV", .brightness_get = "GPLV", .display_set = "SDSP", .display_get = "\\ADVG"}, { + .name = "A6B", + .mled_set = "MLED", + .wled_set = "WLED", + .lcd_switch = A6x_PREFIX "_Q10", + .lcd_status = "\\RGPL(0x07,0x01)", + .brightness_set = "SPLV", + .brightness_get = "GPLV", + .display_set = "SDSP", + .display_get = "\\_SB.PCI0.P0P1.VGA.GETD"}, + + { + .name = "A6J", + .mled_set = "MLED", + .wled_set = "WLED", + .wled_status = "\\WRST", + .bt_switch = "BLED", + .bt_status = "\\BRST", + .lcd_switch = A6x_PREFIX "_Q10", + .lcd_status = "\\RGP0(0x06)", + .brightness_set = "SPLV", + .brightness_get = "GPLV", + .display_set = "SDSP", + .display_get = "\\_SB.PCI0.P0P2.VGA.GETD"}, + + { + .name = "A6R", + .mled_set = "MLED", + .wled_set = "WLED", + .wled_status = "\\WRST", + .bt_switch = "BLED", + .bt_status = "\\BRST", + .lcd_switch = A6x_PREFIX "_Q10", + .lcd_status = A6x_PREFIX "RPIN(0x11)", + .brightness_set = "SPLV", + .brightness_get = "GPLV", + .display_set = "SDSP", + .display_get = "\\_SB.PCI0.P0P1.VGA.GETD"}, + + { + .name = "A6T", + .mled_set = "MLED", + .wled_set = "WLED", + .wled_status = "\\WWED", + .bt_switch = "BLED", + .bt_status = "\\BLTH", + .lcd_switch = A6x_PREFIX "_Q10", + .lcd_status = "\\BKLT", + .brightness_set = "SPLV", + .brightness_get = "GPLV", + .display_set = "SDSP", + .display_get = "\\_SB.PCI0.P0PA.VGA.GETD"}, + + { + .name = "A6V", + .mled_set = "MLED", + .wled_set = "WLED", + .bt_switch = "BLED", + .lcd_switch = A6x_PREFIX "_Q10", + .lcd_status = "\\RGPL(0x15,0x01)", + .brightness_set = "SPLV", + .brightness_get = "GPLV", + .display_set = "SDSP", + .display_get = "\\_SB.PCI0.P0P3.VGA.GETD"}, + + { + .name = "A8J", + .mled_set = "MLED", + .wled_set = "WLED", + .wled_status = "\\WRST", + .bt_switch = "BLED", + .bt_status = "\\BRST", + .lcd_switch = A6x_PREFIX "_Q10", + .lcd_status = "\\RGPL(0x06,0x01)", + .brightness_set = "SPLV", + .brightness_get = "GPLV", + .display_set = "SDSP", + .display_get = "\\_SB.PCI0.P0P2.VGA.GETD"}, + + { .name = "D1x", - .mt_mled = "MLED", - .mt_lcd_switch = "\\Q0D", + .mled_set = "MLED", + .lcd_switch = "\\Q0D", .lcd_status = "\\GP11", .brightness_up = "\\Q0C", .brightness_down = "\\Q0B", @@ -204,12 +389,27 @@ .display_get = "\\INFB"}, { + .name = "F3J", + .mled_set = "MLED", + .wled_set = "WLED", + .wled_status = "\\WRST", + .bt_switch = "BLED", + .bt_status = "\\BRST", + .tled_set = "TLED", + .lcd_switch = A6x_PREFIX "_Q10", + .lcd_status = A6x_PREFIX "RPIN(0x11)", + .brightness_set = "SPLV", + .brightness_get = "GPLV", + .display_set = "SDSP", + .display_get = "\\_SB.PCI0.P0P1.VGA.GETD"}, + + { .name = "L2D", - .mt_mled = "MLED", + .mled_set = "MLED", .mled_status = "\\SGP6", - .mt_wled = "WLED", + .wled_set = "WLED", .wled_status = "\\RCP3", - .mt_lcd_switch = "\\Q10", + .lcd_switch = "\\Q10", .lcd_status = "\\SGP0", .brightness_up = "\\Q0E", .brightness_down = "\\Q0F", @@ -218,9 +418,9 @@ { .name = "L3C", - .mt_mled = "MLED", - .mt_wled = "WLED", - .mt_lcd_switch = L3C_PREFIX "_Q10", + .mled_set = "MLED", + .wled_set = "WLED", + .lcd_switch = L3C_PREFIX "_Q10", .lcd_status = "\\GL32", .brightness_set = "SPLV", .brightness_get = "GPLV", @@ -229,10 +429,10 @@ { .name = "L3D", - .mt_mled = "MLED", + .mled_set = "MLED", .mled_status = "\\MALD", - .mt_wled = "WLED", - .mt_lcd_switch = "\\Q10", + .wled_set = "WLED", + .lcd_switch = "\\Q10", .lcd_status = "\\BKLG", .brightness_set = "SPLV", .brightness_get = "GPLV", @@ -241,10 +441,10 @@ { .name = "L3H", - .mt_mled = "MLED", - .mt_wled = "WLED", - .mt_lcd_switch = "EHK", - .lcd_status = "\\_SB.PCI0.PM.PBC", + .mled_set = "MLED", + .wled_set = "WLED", + .lcd_switch = "EHK(0x07)", + .lcd_status = "\\_SB.PCI0.PM.PBC(0x02,0x02)", .brightness_set = "SPLV", .brightness_get = "GPLV", .display_set = "SDSP", @@ -252,10 +452,10 @@ { .name = "L4R", - .mt_mled = "MLED", - .mt_wled = "WLED", + .mled_set = "MLED", + .wled_set = "WLED", .wled_status = "\\_SB.PCI0.SBRG.SG13", - .mt_lcd_switch = xxN_PREFIX "_Q10", + .lcd_switch = xxN_PREFIX "_Q10", .lcd_status = "\\_SB.PCI0.SBSM.SEO4", .brightness_set = "SPLV", .brightness_get = "GPLV", @@ -264,10 +464,10 @@ { .name = "L5x", - .mt_mled = "MLED", + .mled_set = "MLED", /* WLED present, but not controlled by ACPI */ - .mt_tled = "TLED", - .mt_lcd_switch = "\\Q0D", + .tled_set = "TLED", + .lcd_switch = "\\Q0D", .lcd_status = "\\BAOF", .brightness_set = "SPLV", .brightness_get = "GPLV", @@ -281,8 +481,8 @@ { .name = "M1A", - .mt_mled = "MLED", - .mt_lcd_switch = M1A_PREFIX "Q10", + .mled_set = "MLED", + .lcd_switch = M1A_PREFIX "Q10", .lcd_status = "\\PNOF", .brightness_up = M1A_PREFIX "Q0E", .brightness_down = M1A_PREFIX "Q0F", @@ -292,9 +492,9 @@ { .name = "M2E", - .mt_mled = "MLED", - .mt_wled = "WLED", - .mt_lcd_switch = "\\Q10", + .mled_set = "MLED", + .wled_set = "WLED", + .lcd_switch = "\\Q10", .lcd_status = "\\GP06", .brightness_set = "SPLV", .brightness_get = "GPLV", @@ -303,10 +503,10 @@ { .name = "M6N", - .mt_mled = "MLED", - .mt_wled = "WLED", + .mled_set = "MLED", + .wled_set = "WLED", .wled_status = "\\_SB.PCI0.SBRG.SG13", - .mt_lcd_switch = xxN_PREFIX "_Q10", + .lcd_switch = xxN_PREFIX "_Q10", .lcd_status = "\\_SB.BKLT", .brightness_set = "SPLV", .brightness_get = "GPLV", @@ -315,19 +515,57 @@ { .name = "M6R", - .mt_mled = "MLED", - .mt_wled = "WLED", - .mt_lcd_switch = xxN_PREFIX "_Q10", + .mled_set = "MLED", + .wled_set = "WLED", + .lcd_switch = xxN_PREFIX "_Q10", .lcd_status = "\\_SB.PCI0.SBSM.SEO4", .brightness_set = "SPLV", .brightness_get = "GPLV", .display_set = "SDSP", + .display_get = "\\ACTD"}, + + { + .name = "M6V", + .mled_set = "MLED", + .wled_set = "WLED", + .mled_status = "\\WLSF", + .bt_switch = "BLED", + .bt_status = "\\BTST", + .lcd_switch = xxN_PREFIX "_Q10", + .lcd_status = "\\RGPL(0x15,0x01)", + .brightness_set = "SPLV", + .brightness_get = "GPLV", + .display_set = "SDSP", .display_get = "\\_SB.PCI0.P0P1.VGA.GETD"}, { + .name = "M7A", + .mled_set = "MLED", + .lcd_switch = xxN_PREFIX "_Q10", + .lcd_status = xxN_PREFIX "RPIN(0x56)", + .brightness_set = "SPLV", + .brightness_get = "GPLV", + .light_sens_switch = "ALSC", + .light_sens_level = "ALSL", + .display_set = "SDSP", + .display_get = "\\ADVG"}, + + { + .name = "M7V", + .mled_set = "MLED", + .lcd_switch = xxN_PREFIX "_Q10", + .lcd_status = xxN_PREFIX "RPIN(0x56)", + .brightness_set = "SPLV", + .brightness_get = "GPLV", + .light_sens_switch = "ALSC", + .light_sens_level = "ALSL", + .display_set = "SDSP", + .display_get = "\\_SB.PCI0.P0P2.VGA.GETD"}, + + { .name = "P30", - .mt_wled = "WLED", - .mt_lcd_switch = P30_PREFIX "_Q0E", + .wled_set = "WLED", + .lcd_switch = P30_PREFIX "_Q0E", .lcd_status = "\\BKLT", .brightness_up = P30_PREFIX "_Q68", .brightness_down = P30_PREFIX "_Q69", @@ -337,40 +575,55 @@ { .name = "S1x", - .mt_mled = "MLED", + .mled_set = "MLED", .mled_status = "\\EMLE", - .mt_wled = "WLED", - .mt_lcd_switch = S1x_PREFIX "Q10", + .wled_set = "WLED", + .lcd_switch = S1x_PREFIX "Q10", .lcd_status = "\\PNOF", .brightness_set = "SPLV", .brightness_get = "GPLV"}, { .name = "S2x", - .mt_mled = "MLED", + .mled_set = "MLED", .mled_status = "\\MAIL", - .mt_lcd_switch = S2x_PREFIX "_Q10", + .lcd_switch = S2x_PREFIX "_Q10", .lcd_status = "\\BKLI", .brightness_up = S2x_PREFIX "_Q0B", .brightness_down = S2x_PREFIX "_Q0A"}, { - .name = "W1N", - .mt_mled = "MLED", - .mt_wled = "WLED", - .mt_ledd = "SLCM", - .mt_lcd_switch = xxN_PREFIX "_Q10", + .name = "V6J", + .wled_set = "WLED", + .bt_switch = "BLED", + .tled_set = "TLED", + .lcd_switch = xxN_PREFIX "_Q10", + .lcd_status = "\\RGPL(0x06,0x01)", + .display_get = "\\_SB.PCI0.P0P1.VGA.GETD", + .display_set = "SDSP", + .brightness_set = "SPLV", + .brightness_get = "GPLV"}, + + { + .name = "V6V", + .bt_switch = "BLED", + .bt_status = "\\_SB.PCI0.SBRG.BLTS", + .wled_set = "WLED", + .tled_set = "TLED", + .lcd_switch = xxN_PREFIX "_Q10", .lcd_status = "\\BKLT", .brightness_set = "SPLV", .brightness_get = "GPLV", - .display_set = "SDSP", - .display_get = "\\ADVG"}, + .display_get = "\\_SB.PCI0.POP1.VGA.GETD", + .display_set = "SDSP"}, { - .name = "W5A", - .mt_bt_switch = "BLED", - .mt_wled = "WLED", - .mt_lcd_switch = xxN_PREFIX "_Q10", + .name = "W1N", + .mled_set = "MLED", + .wled_set = "WLED", + .ledd_set = "SLCM", + .lcd_switch = xxN_PREFIX "_Q10", + .lcd_status = "\\BKLT", .brightness_set = "SPLV", .brightness_get = "GPLV", .display_set = "SDSP", @@ -378,26 +631,65 @@ { .name = "W3V", - .mt_mled = "MLED", - .mt_wled = "WLED", - .mt_lcd_switch = xxN_PREFIX "_Q10", + .mled_set = "MLED", + .wled_set = "WLED", + .lcd_switch = xxN_PREFIX "_Q10", .lcd_status = "\\BKLT", .brightness_set = "SPLV", .brightness_get = "GPLV", .display_set = "SDSP", .display_get = "\\INFB"}, - { + { + .name = "W5A", + .bt_switch = "BLED", + .wled_set = "WLED", + .lcd_switch = xxN_PREFIX "_Q10", + .brightness_set = "SPLV", + .brightness_get = "GPLV", + .display_set = "SDSP", + .display_get = "\\ADVG"}, + + { + .name = "W5F", + .bt_switch = "BLED", + .wled_set = "WLED", + .tled_set = "TLED", + .lcd_switch = xxN_PREFIX "_Q10", + .brightness_set = "SPLV", + .brightness_get = "GPLV", + .display_set = "SDSP", + .display_get = "\\ADVG"}, + + { .name = "xxN", - .mt_mled = "MLED", + .mled_set = "MLED", /* WLED present, but not controlled by ACPI */ - .mt_lcd_switch = xxN_PREFIX "_Q10", + .lcd_switch = xxN_PREFIX "_Q10", .lcd_status = "\\BKLT", .brightness_set = "SPLV", .brightness_get = "GPLV", .display_set = "SDSP", - .display_get = "\\ADVG"} -}; + .display_get = "\\ADVG"}, + + { + .name = "Z96", + .mled_set = "MLED", + .wled_set = "WLED", + .bt_switch = "BLED", + .brightness_set = "SPLV", + .brightness_get = "GPLV", + .display_set = "SDSP", + .display_get = "\\_SB.PCI0.VGA.GETD"}, + + { + .name = "???", + .mled_set = "MLED", + .wled_set = "WLED", + .brightness_set = "SPLV", + .brightness_get = "GPLV", + .display_set = "SDSP"} +}; /* End methods configuration */ /* procdir we use */ static struct proc_dir_entry *asus_proc_dir; @@ -427,12 +719,55 @@ }, }; -/* +#ifdef CONFIG_ACPI_ASUS_NEW_BACKLIGHT +/* The backlight device /sys/class/backlight */ +static struct backlight_device *backlight; + +/* + * The backlight class declaration + */ +static int read_brightness(struct backlight_device *bd); +static int update_bl_status(struct backlight_device *bd); +static struct backlight_properties asusbl_data = { + .owner = THIS_MODULE, + .get_brightness = read_brightness, + .update_status = update_bl_status, + .max_brightness = 15, +}; +#endif + +/* + * Take a string describing a method, + * parse it, and store the result into mt + */ +static void parse_method(char *orig, struct method *mt) +{ + char *args = orig; + uint argc = 0; + + mt->name = strsep(&args, "("); + mt->input.count = 0; + mt->input.pointer = mt->params; + + while(args && *args && argc < MT_MAX_ARGS) { + char *tmp; + tmp = strsep(&args, ","); + + mt->params[argc].type = ACPI_TYPE_INTEGER; + mt->params[argc].integer.value = simple_strtoul(tmp, NULL, 0); + + argc++; + } + + mt->input.count = argc; +} + +/* * This function evaluates an ACPI method, given an int as parameter, the * method is searched within the scope of the handle, can be NULL. The output * of the method is written is output, which can also be NULL * - * returns 1 if write is successful, 0 else. + * returns 1 if write is successful, 0 else. */ static int write_acpi_int(acpi_handle handle, const char *method, int val, struct acpi_buffer *output) @@ -450,7 +785,8 @@ return (status == AE_OK); } -static int read_acpi_int(acpi_handle handle, const char *method, int *val) +static int read_acpi_int(acpi_handle handle, const char *method, int *val, + struct acpi_object_list *params) { struct acpi_buffer output; union acpi_object out_obj; @@ -459,7 +795,7 @@ output.length = sizeof(out_obj); output.pointer = &out_obj; - status = acpi_evaluate_object(handle, (char *)method, NULL, &output); + status = acpi_evaluate_object(handle, (char *)method, params, &output); *val = out_obj.integer.value; return (status == AE_OK) && (out_obj.type == ACPI_TYPE_INTEGER); } @@ -484,23 +820,23 @@ len += sprintf(page, ACPI_HOTK_NAME " " ASUS_ACPI_VERSION "\n"); len += sprintf(page + len, "Model reference : %s\n", hotk->methods->name); - /* - * The SFUN method probably allows the original driver to get the list - * of features supported by a given model. For now, 0x0100 or 0x0800 + /* + * The SFUN method probably allows the original driver to get the list + * of features supported by a given model. For now, 0x0100 or 0x0800 * bit signifies that the laptop is equipped with a Wi-Fi MiniPCI card. * The significance of others is yet to be found. */ - if (read_acpi_int(hotk->handle, "SFUN", &temp)) + if (read_acpi_int(hotk->handle, "SFUN", &temp, NULL)) len += sprintf(page + len, "SFUN value : 0x%04x\n", temp); /* * Another value for userspace: the ASYM method returns 0x02 for * battery low and 0x04 for battery critical, its readings tend to be - * more accurate than those provided by _BST. + * more accurate than those provided by _BST. * Note: since not all the laptops provide this method, errors are * silently ignored. */ - if (read_acpi_int(hotk->handle, "ASYM", &temp)) + if (read_acpi_int(hotk->handle, "ASYM", &temp, NULL)) len += sprintf(page + len, "ASYM value : 0x%04x\n", temp); if (asus_info) { @@ -538,12 +874,13 @@ if (ledname) { int led_status; - if (read_acpi_int(NULL, ledname, &led_status)) + if (read_acpi_int(NULL, ledname, &led_status, NULL)) return led_status; else printk(KERN_WARNING "Asus ACPI: Error reading LED " "status\n"); } + return (hotk->status & ledmask) ? 1 : 0; } @@ -602,7 +939,7 @@ proc_write_mled(struct file *file, const char __user * buffer, unsigned long count, void *data) { - return write_led(buffer, count, hotk->methods->mt_mled, MLED_ON, 1); + return write_led(buffer, count, hotk->methods->mled_set, MLED_ON, 1); } /* @@ -624,7 +961,7 @@ rv = parse_arg(buffer, count, &value); if (rv > 0) { if (!write_acpi_int - (hotk->handle, hotk->methods->mt_ledd, value, NULL)) + (hotk->handle, hotk->methods->ledd_set, value, NULL)) printk(KERN_WARNING "Asus ACPI: LED display write failed\n"); else @@ -648,7 +985,7 @@ proc_write_wled(struct file *file, const char __user * buffer, unsigned long count, void *data) { - return write_led(buffer, count, hotk->methods->mt_wled, WLED_ON, 0); + return write_led(buffer, count, hotk->methods->wled_set, WLED_ON, 0); } /* @@ -665,9 +1002,9 @@ proc_write_bluetooth(struct file *file, const char __user * buffer, unsigned long count, void *data) { - /* Note: mt_bt_switch controls both internal Bluetooth adapter's + /* Note: bt_switch controls both internal Bluetooth adapter's presence and its LED */ - return write_led(buffer, count, hotk->methods->mt_bt_switch, BT_ON, 0); + return write_led(buffer, count, hotk->methods->bt_switch, BT_ON, 0); } /* @@ -685,76 +1022,58 @@ proc_write_tled(struct file *file, const char __user * buffer, unsigned long count, void *data) { - return write_led(buffer, count, hotk->methods->mt_tled, TLED_ON, 0); + return write_led(buffer, count, hotk->methods->tled_set, TLED_ON, 0); } static int get_lcd_state(void) { + static struct method mt = { .name = NULL }; int lcd = 0; - if (hotk->model != L3H) { - /* We don't have to check anything if we are here */ - if (!read_acpi_int(NULL, hotk->methods->lcd_status, &lcd)) - printk(KERN_WARNING - "Asus ACPI: Error reading LCD status\n"); + if(mt.name != hotk->methods->lcd_status) + parse_method(hotk->methods->lcd_status, &mt); - if (hotk->model == L2D) - lcd = ~lcd; - } else { /* L3H and the like have to be handled differently */ - acpi_status status = 0; - struct acpi_object_list input; - union acpi_object mt_params[2]; - struct acpi_buffer output; - union acpi_object out_obj; - - input.count = 2; - input.pointer = mt_params; - /* Note: the following values are partly guessed up, but - otherwise they seem to work */ - mt_params[0].type = ACPI_TYPE_INTEGER; - mt_params[0].integer.value = 0x02; - mt_params[1].type = ACPI_TYPE_INTEGER; - mt_params[1].integer.value = 0x02; + if(!mt.name) { /* Not methods to get lcd status */ + hotk->lcd_status = !hotk->lcd_status; + return hotk->lcd_status; + } - output.length = sizeof(out_obj); - output.pointer = &out_obj; + if (!read_acpi_int(NULL, mt.name, &lcd, &mt.input)) + printk(KERN_WARNING + "Asus ACPI: Error reading LCD status\n"); + + if (hotk->model == L2D) + lcd = ~lcd; + else if(hotk->model == L3H) /* That's what the AML code does */ + lcd = lcd >> 8; - status = - acpi_evaluate_object(NULL, hotk->methods->lcd_status, - &input, &output); - if (status != AE_OK) - return -1; - if (out_obj.type == ACPI_TYPE_INTEGER) - /* That's what the AML code does */ - lcd = out_obj.integer.value >> 8; - } return (lcd & 1); } static int set_lcd_state(int value) { + static struct method mt = { .name = NULL }; int lcd = 0; acpi_status status = 0; + if(mt.name != hotk->methods->lcd_switch) + parse_method(hotk->methods->lcd_switch, &mt); + lcd = value ? 1 : 0; if (lcd != get_lcd_state()) { - /* switch */ - if (hotk->model != L3H) { - status = - acpi_evaluate_object(NULL, - hotk->methods->mt_lcd_switch, - NULL, NULL); - } else { /* L3H and the like have to be handled differently */ - if (!write_acpi_int - (hotk->handle, hotk->methods->mt_lcd_switch, 0x07, - NULL)) - status = AE_ERROR; - /* L3H's AML executes EHK (0x07) upon Fn+F7 keypress, - the exact behaviour is simulated here */ - } + if(hotk->model == L3H) /* L3H is special .. */ + status = + acpi_evaluate_object(hotk->handle, + (char *)mt.name, + &mt.input, NULL); + else + status = acpi_evaluate_object(NULL, (char *)mt.name, + &mt.input, NULL); + if (ACPI_FAILURE(status)) - printk(KERN_WARNING "Asus ACPI: Error switching LCD\n"); + printk(KERN_WARNING + "Asus ACPI: Error switching LCD\n"); } return 0; @@ -779,18 +1098,18 @@ return rv; } -static int read_brightness(void) +static int read_brightness(struct backlight_device *bd) { int value; if (hotk->methods->brightness_get) { /* SPLV/GPLV laptop */ if (!read_acpi_int(hotk->handle, hotk->methods->brightness_get, - &value)) + &value, NULL)) 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)) + &value, NULL)) printk(KERN_WARNING "Asus ACPI: Error reading brightness\n"); } else /* No GPLV method */ @@ -801,39 +1120,61 @@ /* * Change the brightness level */ -static void set_brightness(int value) +static int set_brightness(struct backlight_device *bd, int value) { acpi_status status = 0; + value = (0 < value) ? ((15 < value) ? 15 : value) : 0; + /* 0 <= value <= 15 */ + /* SPLV laptop */ if (hotk->methods->brightness_set) { if (!write_acpi_int(hotk->handle, hotk->methods->brightness_set, - value, NULL)) + value, NULL)) { printk(KERN_WARNING "Asus ACPI: Error changing brightness\n"); - return; + return -EINVAL; + } + } else { + /* No SPLV method if we are here, act as appropriate */ + value -= read_brightness(NULL); + while (value != 0) { + status = acpi_evaluate_object(NULL, (value > 0) ? + hotk->methods->brightness_up : + hotk->methods->brightness_down, + NULL, NULL); + (value > 0) ? value-- : value++; + if (ACPI_FAILURE(status)) { + printk(KERN_WARNING + "Asus ACPI: Error changing brightness\n"); + return -EINVAL; + } + } } - /* No SPLV method if we are here, act as appropriate */ - value -= read_brightness(); - while (value != 0) { - status = acpi_evaluate_object(NULL, (value > 0) ? - hotk->methods->brightness_up : - hotk->methods->brightness_down, - NULL, NULL); - (value > 0) ? value-- : value++; - if (ACPI_FAILURE(status)) - printk(KERN_WARNING - "Asus ACPI: Error changing brightness\n"); - } - return; + return 0; } +#ifdef CONFIG_ACPI_ASUS_NEW_BACKLIGHT +static int update_bl_status(struct backlight_device *bd) +{ + int value = bd->props->brightness; + int power = bd->props->power; + int rv; + + rv = set_brightness(bd, value); + if(rv > 0) + return rv; + + return set_lcd_state(power); +} +#endif + static int proc_read_brn(char *page, char **start, off_t off, int count, int *eof, void *data) { - return sprintf(page, "%d\n", read_brightness()); + return sprintf(page, "%d\n", read_brightness(NULL)); } static int @@ -844,9 +1185,7 @@ rv = parse_arg(buffer, count, &value); if (rv > 0) { - value = (0 < value) ? ((15 < value) ? 15 : value) : 0; - /* 0 <= value <= 15 */ - set_brightness(value); + set_brightness(NULL, value); } return rv; } @@ -854,6 +1193,7 @@ static void set_display(int value) { /* no sanity check needed for now */ + hotk->disp_status = value; if (!write_acpi_int(hotk->handle, hotk->methods->display_set, value, NULL)) printk(KERN_WARNING "Asus ACPI: Error setting display\n"); @@ -861,7 +1201,7 @@ } /* - * Now, *this* one could be more user-friendly, but so far, no-one has + * Now, *this* one could be more user-friendly, but so far, no-one has * complained. The significance of bits is the same as in proc_write_disp() */ static int @@ -870,18 +1210,25 @@ { int value = 0; - if (!read_acpi_int(hotk->handle, hotk->methods->display_get, &value)) + if(!hotk->methods->display_get) + return hotk->disp_status; + + if (!read_acpi_int(hotk->handle, hotk->methods->display_get, + &value, NULL)) printk(KERN_WARNING "Asus ACPI: Error reading display status\n"); - value &= 0x07; /* needed for some models, shouldn't hurt others */ + + value &= 0x0F; /* needed for some models, shouldn't hurt others */ + return sprintf(page, "%d\n", value); } /* - * Experimental support for display switching. As of now: 1 should activate - * the LCD output, 2 should do for CRT, and 4 for TV-Out. Any combination - * (bitwise) of these will suffice. I never actually tested 3 displays hooked up - * simultaneously, so be warned. See the acpi4asus README for more info. + * Experimental support for display switching. As of now: 1 should activate + * the LCD output, 2 should do for CRT, 4 for TV-Out and 8 for DVI. + * Any combination (bitwise) of these will suffice. I never actually tested 4 + * displays hooked up simultaneously, so be warned. See the acpi4asus README + * for more info. */ static int proc_write_disp(struct file *file, const char __user * buffer, @@ -895,6 +1242,65 @@ return rv; } +static void set_light_sens_switch(int value) +{ + if (!write_acpi_int(hotk->handle, hotk->methods->light_sens_switch, + value, NULL)) + printk(KERN_WARNING "Asus ACPI: Error setting light sensor " + " switch\n"); + hotk->light_switch = value; +} + +static int proc_read_lssw(char *page, char **start, off_t off, int count, + int *eof, void *data) +{ + return sprintf(page, "%d\n", hotk->light_switch); +} + +static int proc_write_lssw(struct file *file, const char __user *buffer, + unsigned long count, void *data) +{ + int rv, value; + + rv = parse_arg(buffer, count, &value); + if (rv > 0) + set_light_sens_switch(value ? 1 : 0); + + return rv; +} + +static void set_light_sens_level(int value) +{ + if (!write_acpi_int(hotk->handle, hotk->methods->light_sens_level, + value, NULL)) + printk(KERN_WARNING "Asus ACPI: Error setting light sensor" + " level\n"); + hotk->light_level = value; +} + +static int +proc_read_lslvl(char *page, char **start, off_t off, int count, int *eof, + void *data) +{ + return sprintf(page, "%d\n", hotk->light_level); +} + +static int +proc_write_lslvl(struct file *file, const char __user *buffer, + unsigned long count, void *data) +{ + int rv, value; + + rv = parse_arg(buffer, count, &value); + if (rv > 0) { + value = (0 < value) ? ((15 < value) ? 15 : value) : 0; + /* 0 <= value <= 15 */ + set_light_sens_level(value); + } + + return rv; +} + typedef int (proc_readfunc) (char *page, char **start, off_t off, int count, int *eof, void *data); typedef int (proc_writefunc) (struct file * file, const char __user * buffer, @@ -915,8 +1321,8 @@ proc->read_proc = readfunc; proc->data = acpi_driver_data(device); proc->owner = THIS_MODULE; - proc->uid = asus_uid; - proc->gid = asus_gid; + proc->uid = 0; + proc->gid = 0; return 0; } @@ -925,19 +1331,7 @@ struct proc_dir_entry *proc; mode_t mode; - /* - * If parameter uid or gid is not changed, keep the default setting for - * our proc entries (-rw-rw-rw-) else, it means we care about security, - * and then set to -rw-rw---- - */ - - if ((asus_uid == 0) && (asus_gid == 0)) { - mode = S_IFREG | S_IRUGO | S_IWUGO; - } else { - mode = S_IFREG | S_IRUSR | S_IRGRP | S_IWUSR | S_IWGRP; - printk(KERN_WARNING " asus_uid and asus_gid parameters are " - "deprecated, use chown and chmod instead!\n"); - } + mode = S_IFREG | S_IRUGO | S_IWUGO; acpi_device_dir(device) = asus_proc_dir; if (!acpi_device_dir(device)) @@ -948,43 +1342,43 @@ proc->read_proc = proc_read_info; proc->data = acpi_driver_data(device); proc->owner = THIS_MODULE; - proc->uid = asus_uid; - proc->gid = asus_gid; + proc->uid = 0; + proc->gid = 0; } else { printk(KERN_WARNING " Unable to create " PROC_INFO " fs entry\n"); } - if (hotk->methods->mt_wled) { + if (hotk->methods->wled_set) { asus_proc_add(PROC_WLED, &proc_write_wled, &proc_read_wled, mode, device); } - if (hotk->methods->mt_ledd) { + if (hotk->methods->ledd_set) { asus_proc_add(PROC_LEDD, &proc_write_ledd, &proc_read_ledd, mode, device); } - if (hotk->methods->mt_mled) { + if (hotk->methods->mled_set) { asus_proc_add(PROC_MLED, &proc_write_mled, &proc_read_mled, mode, device); } - if (hotk->methods->mt_tled) { + if (hotk->methods->tled_set) { asus_proc_add(PROC_TLED, &proc_write_tled, &proc_read_tled, mode, device); } - if (hotk->methods->mt_bt_switch) { + if (hotk->methods->bt_switch) { asus_proc_add(PROC_BT, &proc_write_bluetooth, &proc_read_bluetooth, mode, device); } - /* - * We need both read node and write method as LCD switch is also accessible - * from keyboard + /* + * We need both read node and write method as LCD switch is also + * accessible from keyboard */ - if (hotk->methods->mt_lcd_switch && hotk->methods->lcd_status) { + if (hotk->methods->lcd_switch && hotk->methods->lcd_status) { asus_proc_add(PROC_LCD, &proc_write_lcd, &proc_read_lcd, mode, device); } @@ -1000,6 +1394,14 @@ mode, device); } + if (hotk->methods->light_sens_switch) + asus_proc_add(PROC_LSSW, &proc_write_lssw, &proc_read_lssw, + mode, device); + + if (hotk->methods->light_sens_level) + asus_proc_add(PROC_LSLVL, &proc_write_lslvl, &proc_read_lslvl, + mode, device); + return 0; } @@ -1007,17 +1409,17 @@ { if (acpi_device_dir(device)) { remove_proc_entry(PROC_INFO, acpi_device_dir(device)); - if (hotk->methods->mt_wled) + if (hotk->methods->wled_set) remove_proc_entry(PROC_WLED, acpi_device_dir(device)); - if (hotk->methods->mt_mled) + if (hotk->methods->mled_set) remove_proc_entry(PROC_MLED, acpi_device_dir(device)); - if (hotk->methods->mt_tled) + if (hotk->methods->tled_set) remove_proc_entry(PROC_TLED, acpi_device_dir(device)); - if (hotk->methods->mt_ledd) + if (hotk->methods->ledd_set) remove_proc_entry(PROC_LEDD, acpi_device_dir(device)); - if (hotk->methods->mt_bt_switch) + if (hotk->methods->bt_switch) remove_proc_entry(PROC_BT, acpi_device_dir(device)); - if (hotk->methods->mt_lcd_switch && hotk->methods->lcd_status) + if (hotk->methods->lcd_switch && hotk->methods->lcd_status) remove_proc_entry(PROC_LCD, acpi_device_dir(device)); if ((hotk->methods->brightness_up && hotk->methods->brightness_down) @@ -1026,6 +1428,10 @@ remove_proc_entry(PROC_BRN, acpi_device_dir(device)); if (hotk->methods->display_set) remove_proc_entry(PROC_DISP, acpi_device_dir(device)); + if (hotk->methods->light_sens_switch) + remove_proc_entry(PROC_LSSW, acpi_device_dir(device)); + if (hotk->methods->light_sens_level) + remove_proc_entry(PROC_LSLVL, acpi_device_dir(device)); } return 0; } @@ -1070,6 +1476,8 @@ return L4R; else if (strncmp(model, "M6N", 3) == 0 || strncmp(model, "W3N", 3) == 0) return M6N; + else if (strncmp(model, "M6V", 3) == 0 || strncmp(model, "M6A", 3) == 0) + return M6V; else if (strncmp(model, "M6R", 3) == 0 || strncmp(model, "A3G", 3) == 0) return M6R; else if (strncmp(model, "M2N", 3) == 0 || @@ -1079,6 +1487,8 @@ strncmp(model, "S1N", 3) == 0 || strncmp(model, "S5N", 3) == 0 || strncmp(model, "W1N", 3) == 0) return xxN; + else if (strncmp(model, "Z96", 3) == 0) + return Z96; else if (strncmp(model, "M1", 2) == 0) return M1A; else if (strncmp(model, "M2", 2) == 0 || strncmp(model, "L4E", 3) == 0) @@ -1091,20 +1501,54 @@ return D1x; else if (strncmp(model, "A1", 2) == 0) return A1x; + else if (strncmp(model, "A2D", 3) == 0) + return A2D; else if (strncmp(model, "A2", 2) == 0) return A2x; + else if (strncmp(model, "A3N", 3) == 0 && strncmp(model, "A3L", 2) == 0) + return A3N; + else if (strncmp(model, "A3E", 3) == 0) + return A3E; + else if (strncmp(model, "A3F", 3) == 0) + return A3F; + else if (strncmp(model, "A6F", 3) == 0) + return A3F; else if (strncmp(model, "J1", 2) == 0) return S2x; else if (strncmp(model, "L5", 2) == 0) return L5x; else if (strncmp(model, "A4G", 3) == 0) return A4G; + else if (strncmp(model, "A6J", 3) == 0) + return A6J; + else if (strncmp(model, "A8J", 3) == 0) + return A8J; + else if (strncmp(model, "A6R", 3) == 0) + return A6R; + else if (strncmp(model, "A6V", 3) == 0 || strncmp(model, "A6Q", 3) == 0) + return A6V; + else if (strncmp(model, "A6T", 3) == 0 || strncmp(model, "A6M", 3) == 0) + return A6T; + else if (strncmp(model, "A6B", 3) == 0 || strncmp(model, "A6K", 3) == 0) + return A6B; + else if (strncmp(model, "F3J", 3) == 0) + return F3J; else if (strncmp(model, "W1N", 3) == 0) return W1N; else if (strncmp(model, "W3V", 3) == 0) return W3V; else if (strncmp(model, "W5A", 3) == 0) return W5A; + else if (strncmp(model, "W5F", 3) == 0) + return W5F; + else if (strncmp(model, "M7V", 3) == 0) + return M7V; + else if (strncmp(model, "M7A", 3) == 0) + return M7A; + else if (strncmp(model, "V6V", 3) == 0) + return V6V; + else if (strncmp(model, "V6J", 3) == 0) + return V6J; else return END_MODEL; } @@ -1123,8 +1567,8 @@ acpi_status status; /* - * Get DSDT headers early enough to allow for differentiating between - * models, but late enough to allow acpi_bus_register_driver() to fail + * 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 @@ -1143,7 +1587,7 @@ } /* This needs to be called for some laptops to init properly */ - if (!read_acpi_int(hotk->handle, "BSTS", &bsts_result)) + if (!read_acpi_int(hotk->handle, "BSTS", &bsts_result, NULL)) printk(KERN_WARNING " Error calling BSTS\n"); else if (bsts_result) printk(KERN_NOTICE " BSTS called, 0x%02x returned\n", @@ -1151,8 +1595,8 @@ /* * Try to match the object returned by INIT to the specific model. - * Handle every possible object (or the lack of thereof) the DSDT - * writers might throw at us. When in trouble, we pass NULL to + * Handle every possible object (or the lack of thereof) the DSDT + * writers might throw at us. When in trouble, we pass NULL to * asus_model_match() and try something completely different. */ if (buffer.pointer) { @@ -1176,12 +1620,21 @@ hotk->model = P30; printk(KERN_NOTICE " Samsung P30 detected, supported\n"); - } else { - hotk->model = M2E; + } else if(unsupported) { printk(KERN_NOTICE " unsupported model %s, trying " "default values\n", string); printk(KERN_NOTICE " send /proc/acpi/dsdt to the developers\n"); + hotk->model = DEF; + + } else { + printk(KERN_NOTICE " unsupported model %s\n", string); + printk(KERN_NOTICE + " send /proc/acpi/dsdt to the developers\n"); + printk(KERN_NOTICE + " you can use the \"unsupported=1\" " + "parameter to have a minimal support\n"); + return -ENODEV; } hotk->methods = &model_conf[hotk->model]; return AE_OK; @@ -1192,7 +1645,7 @@ /* Sort of per-model blacklist */ if (strncmp(string, "L2B", 3) == 0) hotk->methods->lcd_status = NULL; - /* L2B is similar enough to L3C to use its settings, with this only + /* L2B is similar enough to L3C to use its settings, with this only exception */ else if (strncmp(string, "A3G", 3) == 0) hotk->methods->lcd_status = "\\BLFG"; @@ -1200,15 +1653,15 @@ else if (strncmp(string, "S5N", 3) == 0 || strncmp(string, "M5N", 3) == 0 || strncmp(string, "W3N", 3) == 0) - hotk->methods->mt_mled = NULL; + hotk->methods->mled_set = NULL; /* S5N, M5N and W3N have no MLED */ else if (strncmp(string, "L5D", 3) == 0) - hotk->methods->mt_wled = NULL; + hotk->methods->wled_set = NULL; /* L5D's WLED is not controlled by ACPI */ else if (strncmp(string, "M2N", 3) == 0 || strncmp(string, "W3V", 3) == 0 || strncmp(string, "S1N", 3) == 0) - hotk->methods->mt_wled = "WLED"; + hotk->methods->wled_set = "WLED"; /* M2N, S1N and W3V have a usable WLED */ else if (asus_info) { if (strncmp(asus_info->oem_table_id, "L1", 2) == 0) @@ -1301,11 +1754,26 @@ } } + /* Backlight is probably on at boot time, but it's only used + if we don't have a method to get lcd status */ + hotk->lcd_status = 1; + hotk->disp_status = 1; + asus_hotk_found = 1; /* LED display is off by default */ hotk->ledd_status = 0xFFF; + /* Set initial values of light sensor and level */ + hotk->light_switch = 1;/* Default to light sensor disabled */ + hotk->light_level = 0;/* level 5 for sensor sensitivity */ + + if (hotk->methods->light_sens_switch) + set_light_sens_switch(hotk->light_switch); + + if (hotk->methods->light_sens_level) + set_light_sens_level(hotk->light_level); + end: if (result) { kfree(hotk); @@ -1333,7 +1801,8 @@ return 0; } -static int __init asus_acpi_init(void) + +static int __init asus_acpi_probe(struct platform_device *dev) { int result; @@ -1370,18 +1839,79 @@ return result; } +#ifdef CONFIG_ACPI_ASUS_NEW_BACKLIGHT + backlight = backlight_device_register ("asus", NULL, + &asusbl_data); + + if (IS_ERR (backlight)) { + printk(KERN_ERR "Unable to register backlight\n"); + backlight_device_unregister(backlight); + acpi_bus_unregister_driver(&asus_hotk_driver); + remove_proc_entry(PROC_ASUS, acpi_root_dir); + return -ENODEV; + } + + backlight->props->brightness = read_brightness(NULL); + backlight->props->power = get_lcd_state(); + +#endif + return 0; } -static void __exit asus_acpi_exit(void) +static int asus_acpi_remove(struct platform_device *dev) { +#ifdef CONFIG_ACPI_ASUS_NEW_BACKLIGHT + /* Ugly Hack ...*/ + if(backlight) { + backlight->props->update_status = NULL; + backlight_device_unregister(backlight); + } +#endif acpi_bus_unregister_driver(&asus_hotk_driver); remove_proc_entry(PROC_ASUS, acpi_root_dir); kfree(asus_info); - return; + return 0; +} + +static struct platform_driver asus_acpi_driver = { + .probe = asus_acpi_probe, + .remove = asus_acpi_remove, + .driver = { + .name = "asus_acpi", + }, +}; + +static struct platform_device *asus_acpi_device; + +static int __init asus_acpi_init(void) +{ + int ret; + + ret = platform_driver_register(&asus_acpi_driver); + if (!ret) { + asus_acpi_device = platform_device_alloc("asus_acpi", -1); + if (!asus_acpi_device) + return -ENOMEM; + + ret = platform_device_add(asus_acpi_device); + + if (ret) { + platform_device_put(asus_acpi_device); + platform_driver_unregister(&asus_acpi_driver); + } + } + return ret; +} + +static void __exit asus_acpi_exit(void) +{ + platform_device_unregister(asus_acpi_device); + platform_driver_unregister(&asus_acpi_driver); } + module_init(asus_acpi_init); module_exit(asus_acpi_exit);