/*
* asus_acpi.c - Asus Laptop ACPI Extras
*
*
* Copyright (C) 2002-2005 Julien Lerouge, 2003-2006 Karol Kozimor
*
* 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
*
*
* The development page for this driver is located at
* http://sourceforge.net/projects/acpi4asus/
*
* Credits:
* Pontus Fuchs - Helper functions, cleanup
* Johann Wiesner - Small compile fixes
* John Belmonte - ACPI code for Toshiba laptop was a good starting point.
* �ic Burghard - LED display support for W1N
*
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.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"
#define PROC_ASUS "asus" /* The directory */
#define PROC_MLED "mled"
#define PROC_WLED "wled"
#define PROC_TLED "tled"
#define PROC_BT "bluetooth"
#define PROC_LEDD "ledd"
#define PROC_INFO "info"
#define PROC_LCD "lcd"
#define PROC_BRN "brn"
#define PROC_DISP "disp"
#define ACPI_HOTK_NAME "Asus Laptop ACPI Extras Driver"
#define ACPI_HOTK_CLASS "hotkey"
#define ACPI_HOTK_DEVICE_NAME "Hotkey"
/*
* Some events we use, same for all Asus
*/
#define BR_UP 0x10
#define BR_DOWN 0x20
/*
* Flags for hotk status
*/
#define MLED_ON 0x01 /* Mail LED */
#define WLED_ON 0x02 /* Wireless LED */
#define TLED_ON 0x04 /* Touchpad LED */
#define BT_ON 0x08 /* Internal Bluetooth */
MODULE_AUTHOR("Julien Lerouge, Karol Kozimor");
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");
module_param(asus_gid, uint, 0);
MODULE_PARM_DESC(asus_gid, "GID for entries in /proc/acpi/asus");
/* 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_status; /* node to handle mled reading_______A */
char *mt_wled; /* method to handle wled_____________R */
char *wled_status; /* node to handle wled reading_______A */
char *mt_tled; /* 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 *lcd_status; /* node to read LCD panel state______A */
char *brightness_up; /* method to set brightness up_______A */
char *brightness_down; /* method to set brightness down ____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 *display_set; /* method to set video output________R */
char *display_get; /* method to get video output________R */
};
/*
* This is the main structure, we can use it to store anything interesting
* about the hotk device
*/
struct asus_hotk {
struct acpi_device *device; /* the device we are in */
acpi_handle handle; /* the handle of the hotk device */
char status; /* status of the hotk, for LEDs */
u32 ledd_status; /* status of the LED display */
struct model_data *methods; /* methods available on the laptop */
u8 brightness; /* brightness level */
enum {
A1x = 0, /* A1340D, A1300F */
A2x, /* A2500H */
A4G, /* A4700G */
D1x, /* D1 */
L2D, /* L2000D */
L3C, /* L3800C */
L3D, /* L3400D */
L3H, /* L3H, L2000E, L5D */
L4R, /* L4500R */
L5x, /* L5800C */
L8L, /* L8400L */
M1A, /* M1300A */
M2E, /* M2400E, L4400L */
M6N, /* M6800N, W3400N */
M6R, /* M6700R, A3000G */
P30, /* Samsung P30 */
S1x, /* S1300A, but also L1400B and M2400A (L84F) */
S2x, /* S200 (J1 reported), Victor MP-XP7210 */
W1N, /* W1000N */
W5A, /* W5A */
W3V, /* W3030V */
xxN, /* M2400N, M3700N, M5200N, M6800N,
S1300N, S5200N*/
A4S, /* Z81sp */
F3Sa, /* (Centrino) */
R1F,
END_MODEL
} model; /* Models currently supported */
u16 event_count[128]; /* Count for each event TODO make this better */
};
/* Here we go */
#define A1x_PREFIX "\\_SB.PCI0.ISA.EC0."
#define L3C_PREFIX "\\_SB.PCI0.PX40.ECD0."
#define M1A_PREFIX "\\_SB.PCI0.PX40.EC0."
#define P30_PREFIX "\\_SB.PCI0.LPCB.EC0."
#define S1x_PREFIX "\\_SB.PCI0.PX40."
#define S2x_PREFIX A1x_PREFIX
#define xxN_PREFIX "\\_SB.PCI0.SBRG.EC0."
static struct model_data model_conf[END_MODEL] = {
/*
* TODO I have seen a SWBX and AIBX method on some models, like L1400B,
* it seems to be a kind of switch, but what for ?
*/
{
.name = "A1x",
.mt_mled = "MLED",
.mled_status = "\\MAIL",
.mt_lcd_switch = A1x_PREFIX "_Q10",
.lcd_status = "\\BKLI",
.brightness_up = A1x_PREFIX "_Q0E",
.brightness_down = A1x_PREFIX "_Q0F"},
{
.name = "A2x",
.mt_mled = "MLED",
.mt_wled = "WLED",
.wled_status = "\\SG66",
.mt_lcd_switch = "\\Q10",
.lcd_status = "\\BAOF",
.brightness_set = "SPLV",
.brightness_get = "GPLV",
.display_set = "SDSP",
.display_get = "\\INFB"},
{
.name = "A4G",
.mt_mled = "MLED",
/* WLED present, but not controlled by ACPI */
.mt_lcd_switch = xxN_PREFIX "_Q10",
.brightness_set = "SPLV",
.brightness_get = "GPLV",
.display_set = "SDSP",
.display_get = "\\ADVG"},
{
.name = "D1x",
.mt_mled = "MLED",
.mt_lcd_switch = "\\Q0D",
.lcd_status = "\\GP11",
.brightness_up = "\\Q0C",
.brightness_down = "\\Q0B",
.brightness_status = "\\BLVL",
.display_set = "SDSP",
.display_get = "\\INFB"},
{
.name = "L2D",
.mt_mled = "MLED",
.mled_status = "\\SGP6",
.mt_wled = "WLED",
.wled_status = "\\RCP3",
.mt_lcd_switch = "\\Q10",
.lcd_status = "\\SGP0",
.brightness_up = "\\Q0E",
.brightness_down = "\\Q0F",
.display_set = "SDSP",
.display_get = "\\INFB"},
{
.name = "L3C",
.mt_mled = "MLED",
.mt_wled = "WLED",
.mt_lcd_switch = L3C_PREFIX "_Q10",
.lcd_status = "\\GL32",
.brightness_set = "SPLV",
.brightness_get = "GPLV",
.display_set = "SDSP",
.display_get = "\\_SB.PCI0.PCI1.VGAC.NMAP"},
{
.name = "L3D",
.mt_mled = "MLED",
.mled_status = "\\MALD",
.mt_wled = "WLED",
.mt_lcd_switch = "
|