Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
0979ec20
Commit
0979ec20
authored
Feb 05, 2004
by
Len Brown
Browse files
Options
Browse Files
Download
Plain Diff
Merge intel.com:/home/lenb/src/linux-acpi-test-2.6.1
into intel.com:/home/lenb/src/linux-acpi-test-2.6.2
parents
cbd884c9
651f8c98
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
527 additions
and
319 deletions
+527
-319
drivers/acpi/asus_acpi.c
drivers/acpi/asus_acpi.c
+464
-289
drivers/acpi/pci_irq.c
drivers/acpi/pci_irq.c
+7
-5
drivers/acpi/toshiba_acpi.c
drivers/acpi/toshiba_acpi.c
+56
-25
No files found.
drivers/acpi/asus_acpi.c
View file @
0979ec20
...
...
@@ -2,7 +2,7 @@
* asus_acpi.c - Asus Laptop ACPI Extras
*
*
* Copyright (C) 2002, 2003 Julien Lerouge, Karol Kozimor
* Copyright (C) 2002, 2003
, 2004
Julien Lerouge, 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
...
...
@@ -23,16 +23,16 @@
* 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.
*
* TODO:
* add Fn key status
* Add mode selection on module loading (parameter) -> still necessary?
* Complete display switching -- may require dirty hacks?
* Complete display switching -- may require dirty hacks
or calling _DOS
?
*/
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
...
...
@@ -41,12 +41,13 @@
#include <acpi/acpi_drivers.h>
#include <acpi/acpi_bus.h>
#define ASUS_ACPI_VERSION "0.2
6
"
#define ASUS_ACPI_VERSION "0.2
7
"
#define PROC_ASUS "asus" //the directory
#define PROC_MLED "mled"
#define PROC_WLED "wled"
#define PROC_INFOS "info"
#define PROC_TLED "tled"
#define PROC_INFO "info"
#define PROC_LCD "lcd"
#define PROC_BRN "brn"
#define PROC_DISP "disp"
...
...
@@ -67,6 +68,7 @@
*/
#define MLED_ON 0x01 //is MLED ON ?
#define WLED_ON 0x02
#define TLED_ON 0x04
MODULE_AUTHOR
(
"Julien Lerouge, Karol Kozimor"
);
MODULE_DESCRIPTION
(
ACPI_HOTK_NAME
);
...
...
@@ -81,22 +83,25 @@ MODULE_PARM(asus_gid, "i");
MODULE_PARM_DESC
(
gid
,
"GID for entries in /proc/acpi/asus.
\n
"
);
/* For each model, all features implemented */
/* 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
char
*
mt_mled
;
//method to handle mled
char
*
mled_status
;
//node to handle mled reading
char
*
mt_wled
;
//method to handle wled
char
*
wled_status
;
//node to handle wled reading
char
*
mt_lcd_switch
;
//method to turn LCD ON/OFF
char
*
lcd_status
;
//node to read LCD panel state
char
*
brightness_up
;
//method to set brightness up
char
*
brightness_down
;
//guess what ?
char
*
brightness_set
;
//method to set absolute brightness
char
*
brightness_get
;
//method to get absolute brightness
char
*
brightness_status
;
//node to get brightness
char
*
display_set
;
//method to set video output
char
*
display_get
;
//method to get video output
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_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
*
display_set
;
//method to set video output________R
char
*
display_get
;
//method to get video output________R
};
/*
...
...
@@ -104,91 +109,239 @@ struct model_data {
* 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, ...
struct
model_data
*
methods
;
//methods available on the laptop
u8
brightness
;
//brigh
ness level
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, ...
struct
model_data
*
methods
;
//methods available on the laptop
u8
brightness
;
//bright
ness level
enum
{
A1X
=
0
,
//A1340D, A1300F
A2X
,
//A2500H
D1X
,
//D1
L1X
,
//L1400B
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 seem to have an ATK device
// L8400 model doesn't have ATK
A1x
=
0
,
//A1340D, A1300F
A2x
,
//A2500H
D1x
,
//D1
L2D
,
//L2000D
L3C
,
//L3800C
L3D
,
//L3400D
L3H
,
//L3H, but also L2000E
L5x
,
//L5800C
L8L
,
//L8400L
M1A
,
//M1300A
M2E
,
//M2400E
S1x
,
//S1300A, but also L1400B and M2400A (L84F)
S2x
,
//S200 (J1 reported), Victor MP-XP7210
//TODO A1370D does not seem to have an ATK device
// L8400 model doesn't have ATK
xxN
,
//M2400N, M3700N, S1300N (Centrino)
END_MODEL
}
model
;
//Models currently supported
u16
event_count
[
128
];
//count for each event TODO make this better
}
model
;
//Models currently supported
u16
event_count
[
128
];
//count for each event TODO make this better
};
/* Here we go */
#define
L3X_PREFIX "\\_SB.PCI0.PX40.ECD
0."
#define
S1X_PREFIX "\\_SB.PCI0.PX4
0."
#define
L1X_PREFIX S1X_PREFIX
#define
A1X_PREFIX "\\_SB.PCI0.ISA.EC
0."
#define S2
X_PREFIX A1X
_PREFIX
#define
M3
N_PREFIX "\\_SB.PCI0.SBRG.EC0."
#define
A1x_PREFIX "\\_SB.PCI0.ISA.EC
0."
#define
L3C_PREFIX "\\_SB.PCI0.PX40.ECD
0."
#define
M1A_PREFIX "\\_SB.PCI0.PX40.EC0."
#define
S1x_PREFIX "\\_SB.PCI0.PX4
0."
#define S2
x_PREFIX A1x
_PREFIX
#define
xx
N_PREFIX "\\_SB.PCI0.SBRG.EC0."
static
struct
model_data
model_conf
[
END_MODEL
]
=
{
/*
* name| mled |mled read| wled |wled read| lcd sw |lcd read |
* br up|br down | br set | br read | br status|set disp | get disp
*
* br set and read shall be in hotk device !
* same for set disp
* Those pathnames are relative to the HOTK / ATKD device :
* - mt_mled
* - mt_wled
* - brightness_set
* - brightness_get
* - display_set
* - display_get
*
* 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 ?
*
*/
{
"A1X"
,
"MLED"
,
"
\\
MAIL"
,
NULL
,
NULL
,
A1X_PREFIX
"_Q10"
,
"
\\
BKLI"
,
A1X_PREFIX
"_Q0E"
,
A1X_PREFIX
"_Q0F"
,
NULL
,
NULL
,
NULL
,
NULL
,
NULL
},
{
"A2X"
,
"MLED"
,
NULL
,
"WLED"
,
"
\\
SG66"
,
"
\\
Q10"
,
"
\\
BAOF"
,
"
\\
Q0E"
,
"
\\
Q0F"
,
"SPLV"
,
"GPLV"
,
"
\\
CMOD"
,
"SDSP"
,
"
\\
INFB"
},
{
"D1X"
,
"MLED"
,
NULL
,
NULL
,
NULL
,
"
\\
Q0D"
,
"
\\
GP11"
,
"
\\
Q0C"
,
"
\\
Q0B"
,
NULL
,
NULL
,
"
\\
BLVL"
,
"SDSP"
,
"
\\
INFB"
},
{
"L1X"
,
"MLED"
,
NULL
,
"WLED"
,
NULL
,
L1X_PREFIX
"Q10"
,
"
\\
PNOF"
,
L1X_PREFIX
"Q0F"
,
L1X_PREFIX
"Q0E"
,
"SPLV"
,
"GPLV"
,
"
\\
BRIT"
,
NULL
,
NULL
},
{
"L2X"
,
"MLED"
,
"
\\
SGP6"
,
"WLED"
,
"
\\
RCP3"
,
"
\\
Q10"
,
"
\\
SGP0"
,
"
\\
Q0E"
,
"
\\
Q0F"
,
NULL
,
NULL
,
NULL
,
"SDSP"
,
"
\\
INFB"
},
{
"L3D"
,
"MLED"
,
"
\\
MALD"
,
"WLED"
,
NULL
,
"
\\
Q10"
,
"
\\
BKLG"
,
"
\\
Q0E"
,
"
\\
Q0F"
,
"SPLV"
,
"GPLV"
,
"
\\
BLVL"
,
"SDSP"
,
"
\\
INFB"
},
{
"L3X"
,
"MLED"
,
NULL
,
"WLED"
,
NULL
,
L3X_PREFIX
"_Q10"
,
"
\\
GL32"
,
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"
},
{
"M3N"
,
"MLED"
,
NULL
,
"WLED"
,
"
\\
PO33"
,
M3N_PREFIX
"_Q10"
,
"
\\
BKLT"
,
M3N_PREFIX
"_Q0F"
,
M3N_PREFIX
"_Q0E"
,
"SPLV"
,
"GPLV"
,
"
\\
LBTN"
,
"SDSP"
,
"
\\
ADVG"
},
{
"S1X"
,
"MLED"
,
"
\\
EMLE"
,
"WLED"
,
NULL
,
S1X_PREFIX
"Q10"
,
"
\\
PNOF"
,
S1X_PREFIX
"Q0F"
,
S1X_PREFIX
"Q0E"
,
"SPLV"
,
"GPLV"
,
"
\\
BRIT"
,
NULL
,
NULL
},
{
"S2X"
,
"MLED"
,
"
\\
MAIL"
,
NULL
,
NULL
,
S2X_PREFIX
"_Q10"
,
"
\\
BKLI"
,
S2X_PREFIX
"_Q0B"
,
S2X_PREFIX
"_Q0A"
,
NULL
,
NULL
,
NULL
,
NULL
,
NULL
}
{
.
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_up
=
"
\\
Q0E"
,
.
brightness_down
=
"
\\
Q0F"
,
.
brightness_set
=
"SPLV"
,
.
brightness_get
=
"GPLV"
,
.
brightness_status
=
"
\\
CMOD"
,
.
display_set
=
"SDSP"
,
.
display_get
=
"
\\
INFB"
},
{
.
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_up
=
L3C_PREFIX
"_Q0F"
,
.
brightness_down
=
L3C_PREFIX
"_Q0E"
,
.
brightness_set
=
"SPLV"
,
.
brightness_get
=
"GPLV"
,
.
brightness_status
=
"
\\
BLVL"
,
.
display_set
=
"SDSP"
,
.
display_get
=
"
\\
_SB.PCI0.PCI1.VGAC.NMAP"
},
{
.
name
=
"L3D"
,
.
mt_mled
=
"MLED"
,
.
mled_status
=
"
\\
MALD"
,
.
mt_wled
=
"WLED"
,
.
mt_lcd_switch
=
"
\\
Q10"
,
.
lcd_status
=
"
\\
BKLG"
,
.
brightness_up
=
"
\\
Q0E"
,
.
brightness_down
=
"
\\
Q0F"
,
.
brightness_set
=
"SPLV"
,
.
brightness_get
=
"GPLV"
,
.
brightness_status
=
"
\\
BLVL"
,
.
display_set
=
"SDSP"
,
.
display_get
=
"
\\
INFB"
},
{
.
name
=
"L3H"
,
.
mt_mled
=
"MLED"
,
.
mt_wled
=
"WLED"
,
.
mt_lcd_switch
=
"EHK"
,
.
lcd_status
=
"
\\
_SB.PCI0.PM.PBC"
,
.
brightness_set
=
"SPLV"
,
.
brightness_get
=
"GPLV"
,
.
display_set
=
"SDSP"
,
.
display_get
=
"
\\
INFB"
},
{
.
name
=
"L5x"
,
.
mt_mled
=
"MLED"
,
// .mt_wled = "WLED",
// .wled_status = "\\WRED",
/* Present, but not controlled by ACPI */
.
mt_tled
=
"TLED"
,
.
mt_lcd_switch
=
"
\\
Q0D"
,
.
lcd_status
=
"
\\
BAOF"
,
.
brightness_up
=
"
\\
Q0C"
,
.
brightness_down
=
"
\\
Q0B"
,
.
brightness_set
=
"SPLV"
,
.
brightness_get
=
"GPLV"
,
.
display_set
=
"SDSP"
,
.
display_get
=
"
\\
INFB"
},
{
.
name
=
"L8L"
/* No features, but at least support the hotkeys */
},
{
.
name
=
"M1A"
,
.
mt_mled
=
"MLED"
,
.
mt_lcd_switch
=
M1A_PREFIX
"Q10"
,
.
lcd_status
=
"
\\
PNOF"
,
.
brightness_up
=
M1A_PREFIX
"Q0E"
,
.
brightness_down
=
M1A_PREFIX
"Q0F"
,
.
brightness_status
=
"
\\
BRIT"
,
.
display_set
=
"SDSP"
,
.
display_get
=
"
\\
INFB"
},
{
.
name
=
"M2E"
,
.
mt_mled
=
"MLED"
,
.
mt_wled
=
"WLED"
,
.
mt_lcd_switch
=
"
\\
Q10"
,
.
lcd_status
=
"
\\
GP06"
,
.
brightness_up
=
"
\\
Q0E"
,
.
brightness_down
=
"
\\
Q0F"
,
.
brightness_set
=
"SPLV"
,
.
brightness_get
=
"GPLV"
,
.
display_set
=
"SDSP"
,
.
display_get
=
"
\\
INFB"
},
{
.
name
=
"S1x"
,
.
mt_mled
=
"MLED"
,
.
mled_status
=
"
\\
EMLE"
,
.
mt_wled
=
"WLED"
,
.
mt_lcd_switch
=
S1x_PREFIX
"Q10"
,
.
lcd_status
=
"
\\
PNOF"
,
.
brightness_up
=
S1x_PREFIX
"Q0F"
,
.
brightness_down
=
S1x_PREFIX
"Q0E"
,
.
brightness_set
=
"SPLV"
,
.
brightness_get
=
"GPLV"
,
.
brightness_status
=
"
\\
BRIT"
,
},
{
.
name
=
"S2x"
,
.
mt_mled
=
"MLED"
,
.
mled_status
=
"
\\
MAIL"
,
.
mt_lcd_switch
=
S2x_PREFIX
"_Q10"
,
.
lcd_status
=
"
\\
BKLI"
,
.
brightness_up
=
S2x_PREFIX
"_Q0B"
,
.
brightness_down
=
S2x_PREFIX
"_Q0A"
,
},
{
.
name
=
"xxN"
,
.
mt_mled
=
"MLED"
,
// .mt_wled = "WLED",
// .wled_status = "\\PO33",
/* Present, but not controlled by ACPI */
.
mt_lcd_switch
=
xxN_PREFIX
"_Q10"
,
.
lcd_status
=
"
\\
BKLT"
,
.
brightness_up
=
xxN_PREFIX
"_Q0F"
,
.
brightness_down
=
xxN_PREFIX
"_Q0E"
,
.
brightness_set
=
"SPLV"
,
.
brightness_get
=
"GPLV"
,
.
brightness_status
=
"
\\
LBTN"
,
.
display_set
=
"SDSP"
,
.
display_get
=
"
\\
ADVG"
}
};
/* procdir we use */
...
...
@@ -264,7 +417,7 @@ proc_read_info(char *page, char **start, off_t off, int count, int *eof,
void
*
data
)
{
int
len
=
0
;
int
sfun
;
int
temp
;
struct
asus_hotk
*
hotk
=
(
struct
asus_hotk
*
)
data
;
char
buf
[
16
];
//enough for all info
/*
...
...
@@ -275,8 +428,23 @@ proc_read_info(char *page, char **start, off_t off, int count, int *eof,
len
+=
sprintf
(
page
,
ACPI_HOTK_NAME
" "
ASUS_ACPI_VERSION
"
\n
"
);
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
);
/*
* 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
))
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, it's readings tend to be
* 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
))
len
+=
sprintf
(
page
+
len
,
"ASYM value : 0x%04x
\n
"
,
temp
);
if
(
asus_info
)
{
snprintf
(
buf
,
16
,
"%d"
,
asus_info
->
length
);
len
+=
sprintf
(
page
+
len
,
"DSDT length : %s
\n
"
,
buf
);
...
...
@@ -300,128 +468,179 @@ proc_read_info(char *page, char **start, off_t off, int count, int *eof,
}
/*
* proc file handlers
/*
* /proc handlers
* We write our info in page, we begin at offset off and cannot write more
* than count bytes. We set eof to 1 if we handle those 2 values. We return the
* number of bytes written in page
*/
/* Generic LED functions */
static
int
proc_read_mled
(
char
*
page
,
char
**
start
,
off_t
off
,
int
count
,
int
*
eof
,
void
*
data
)
read_led
(
struct
asus_hotk
*
hotk
,
const
char
*
ledname
,
int
ledmask
)
{
int
len
=
0
;
struct
asus_hotk
*
hotk
=
(
struct
asus_hotk
*
)
data
;
int
led_status
=
0
;
/*
* We use the easy way, we don't care of off and count, so we don't set eof
* to 1
*/
if
(
hotk
->
methods
->
mled_status
)
{
if
(
read_acpi_int
(
NULL
,
hotk
->
methods
->
mled_status
,
&
led_status
))
len
=
sprintf
(
page
,
"%d
\n
"
,
led_status
);
if
(
ledname
)
{
int
led_status
;
if
(
read_acpi_int
(
NULL
,
ledname
,
&
led_status
))
return
led_status
;
else
printk
(
KERN_WARNING
"Asus ACPI: Error reading
M
LED "
printk
(
KERN_WARNING
"Asus ACPI: Error reading LED "
"status
\n
"
);
}
else
{
len
=
sprintf
(
page
,
"%d
\n
"
,
(
hotk
->
status
&
MLED_ON
)
?
1
:
0
);
}
return
len
;
return
(
hotk
->
status
&
ledmask
)
?
1
:
0
;
}
/* FIXME: kill extraneous args so it can be called independently */
static
int
proc_write_mled
(
struct
file
*
file
,
const
char
*
buffer
,
unsigned
long
count
,
void
*
data
)
write_led
(
const
char
*
buffer
,
unsigned
long
count
,
struct
asus_hotk
*
hotk
,
char
*
ledname
,
int
ledmask
,
int
invert
)
{
int
value
;
int
led_out
=
0
;
struct
asus_hotk
*
hotk
=
(
struct
asus_hotk
*
)
data
;
/* scan expression. Multiple expressions may be delimited with ; */
if
(
sscanf
(
buffer
,
"%i"
,
&
value
)
==
1
)
led_out
=
~
value
&
1
;
led_out
=
value
?
1
:
0
;
hotk
->
status
=
(
value
)
?
(
hotk
->
status
|
MLED_ON
)
:
(
hotk
->
status
&
~
MLED_ON
);
/* 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_WARNING
"Asus ACPI: MLED write failed
\n
"
);
(
led_out
)
?
(
hotk
->
status
|
ledmask
)
:
(
hotk
->
status
&
~
ledmask
);
if
(
invert
)
/* invert target value */
led_out
=
!
led_out
&
0x1
;
if
(
!
write_acpi_int
(
hotk
->
handle
,
ledname
,
led_out
,
NULL
))
printk
(
KERN_WARNING
"Asus ACPI: LED (%s) write failed
\n
"
,
ledname
);
return
count
;
}
/*
* We write our info in page, we begin at offset off and cannot write more
* than count bytes. We set eof to 1 if we handle those 2 values. We return the
* number of bytes written in page
* Proc handlers for MLED
*/
static
int
proc_read_
w
led
(
char
*
page
,
char
**
start
,
off_t
off
,
int
count
,
int
*
eof
,
proc_read_
m
led
(
char
*
page
,
char
**
start
,
off_t
off
,
int
count
,
int
*
eof
,
void
*
data
)
{
int
len
=
0
;
struct
asus_hotk
*
hotk
=
(
struct
asus_hotk
*
)
data
;
int
led_status
;
return
sprintf
(
page
,
"%d
\n
"
,
read_led
(
hotk
,
hotk
->
methods
->
mled_status
,
MLED_ON
));
}
if
(
hotk
->
methods
->
wled_status
)
{
if
(
read_acpi_int
(
NULL
,
hotk
->
methods
->
wled_status
,
&
led_status
))
len
=
sprintf
(
page
,
"%d
\n
"
,
led_status
);
else
printk
(
KERN_WARNING
"Asus ACPI: Error reading WLED "
"status
\n
"
);
}
else
{
len
=
sprintf
(
page
,
"%d
\n
"
,
(
hotk
->
status
&
WLED_ON
)
?
1
:
0
);
}
return
len
;
static
int
proc_write_mled
(
struct
file
*
file
,
const
char
*
buffer
,
unsigned
long
count
,
void
*
data
)
{
struct
asus_hotk
*
hotk
=
(
struct
asus_hotk
*
)
data
;
return
write_led
(
buffer
,
count
,
hotk
,
hotk
->
methods
->
mt_mled
,
MLED_ON
,
1
);
}
/*
* Proc handlers for WLED
*/
static
int
proc_read_wled
(
char
*
page
,
char
**
start
,
off_t
off
,
int
count
,
int
*
eof
,
void
*
data
)
{
struct
asus_hotk
*
hotk
=
(
struct
asus_hotk
*
)
data
;
return
sprintf
(
page
,
"%d
\n
"
,
read_led
(
hotk
,
hotk
->
methods
->
wled_status
,
WLED_ON
));
}
static
int
proc_write_wled
(
struct
file
*
file
,
const
char
*
buffer
,
unsigned
long
count
,
void
*
data
)
{
int
value
;
int
led_out
=
0
;
struct
asus_hotk
*
hotk
=
(
struct
asus_hotk
*
)
data
;
return
write_led
(
buffer
,
count
,
hotk
,
hotk
->
methods
->
mt_wled
,
WLED_ON
,
0
);
}
/* scan expression. Multiple expressions may be delimited with ; */
if
(
sscanf
(
buffer
,
"%i"
,
&
value
)
==
1
)
led_out
=
value
&
1
;
hotk
->
status
=
(
value
)
?
(
hotk
->
status
|
WLED_ON
)
:
(
hotk
->
status
&
~
WLED_ON
);
/* 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_WARNING
"Asus ACPI: WLED write failed
\n
"
);
/*
* Proc handlers for TLED
*/
static
int
proc_read_tled
(
char
*
page
,
char
**
start
,
off_t
off
,
int
count
,
int
*
eof
,
void
*
data
)
{
struct
asus_hotk
*
hotk
=
(
struct
asus_hotk
*
)
data
;
return
sprintf
(
page
,
"%d
\n
"
,
read_led
(
hotk
,
hotk
->
methods
->
tled_status
,
TLED_ON
));
}
return
count
;
static
int
proc_write_tled
(
struct
file
*
file
,
const
char
*
buffer
,
unsigned
long
count
,
void
*
data
)
{
struct
asus_hotk
*
hotk
=
(
struct
asus_hotk
*
)
data
;
return
write_led
(
buffer
,
count
,
hotk
,
hotk
->
methods
->
mt_tled
,
TLED_ON
,
0
);
}
static
int
get_lcd_state
(
struct
asus_hotk
*
hotk
)
{
int
lcd
=
0
;
/* 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
(
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
(
hotk
->
model
==
L2X
)
lcd
=
~
lcd
;
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
;
output
.
length
=
sizeof
(
out_obj
);
output
.
pointer
=
&
out_obj
;
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
(
struct
asus_hotk
*
hotk
,
int
value
)
{
int
lcd
=
0
;
acpi_status
status
=
0
;
lcd
=
value
?
1
:
0
;
if
(
lcd
!=
get_lcd_state
(
hotk
))
{
/* 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
(
ACPI_FAILURE
(
status
))
printk
(
KERN_WARNING
"Asus ACPI: Error switching LCD
\n
"
);
}
return
0
;
}
static
int
proc_read_lcd
(
char
*
page
,
char
**
start
,
off_t
off
,
int
count
,
int
*
eof
,
...
...
@@ -436,26 +655,10 @@ proc_write_lcd(struct file *file, const char *buffer,
unsigned
long
count
,
void
*
data
)
{
int
value
;
int
lcd
=
0
;
acpi_status
status
=
0
;
int
lcd_status
=
0
;
struct
asus_hotk
*
hotk
=
(
struct
asus_hotk
*
)
data
;
/* scan expression. Multiple expressions may be delimited with ; */
if
(
sscanf
(
buffer
,
"%i"
,
&
value
)
==
1
)
lcd
=
value
&
1
;
lcd_status
=
get_lcd_state
(
hotk
);
if
(
lcd_status
!=
lcd
)
{
/* switch */
status
=
acpi_evaluate_object
(
NULL
,
hotk
->
methods
->
mt_lcd_switch
,
NULL
,
NULL
);
if
(
ACPI_FAILURE
(
status
))
printk
(
KERN_WARNING
"Asus ACPI: Error switching LCD
\n
"
);
}
set_lcd_state
(
hotk
,
value
);
return
count
;
}
...
...
@@ -521,7 +724,6 @@ proc_write_brn(struct file *file, const char *buffer,
int
value
;
struct
asus_hotk
*
hotk
=
(
struct
asus_hotk
*
)
data
;
/* scan expression. Multiple expressions may be delimited with ; */
if
(
sscanf
(
buffer
,
"%d"
,
&
value
)
==
1
)
{
value
=
(
0
<
value
)
?
((
15
<
value
)
?
15
:
value
)
:
0
;
/* 0 <= value <= 15 */
...
...
@@ -546,7 +748,6 @@ static void set_display(int value, struct asus_hotk *hotk)
* 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
proc_read_disp
(
char
*
page
,
char
**
start
,
off_t
off
,
int
count
,
int
*
eof
,
void
*
data
)
...
...
@@ -560,12 +761,11 @@ proc_read_disp(char *page, char **start, off_t off, int count, int *eof,
}
/*
* Experimental support for display switching. As of now:
0x0
1 should activate
* the LCD output,
0x02 should do for CRT, and 0x0
4 for TV-Out. Any combination
* 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.
* simultaneously, so be warned.
See the acpi4asus README for more info.
*/
static
int
proc_write_disp
(
struct
file
*
file
,
const
char
*
buffer
,
unsigned
long
count
,
void
*
data
)
...
...
@@ -573,7 +773,6 @@ proc_write_disp(struct file *file, const char *buffer,
int
value
;
struct
asus_hotk
*
hotk
=
(
struct
asus_hotk
*
)
data
;
/* scan expression. Multiple expressions may be delimited with ; */
if
(
sscanf
(
buffer
,
"%d"
,
&
value
)
==
1
)
set_display
(
value
,
hotk
);
else
{
...
...
@@ -583,6 +782,31 @@ proc_write_disp(struct file *file, const char *buffer,
return
count
;
}
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
*
buffer
,
unsigned
long
count
,
void
*
data
);
static
int
__init
asus_proc_add
(
char
*
name
,
proc_writefunc
*
writefunc
,
proc_readfunc
*
readfunc
,
mode_t
mode
,
struct
acpi_device
*
device
)
{
struct
proc_dir_entry
*
proc
=
create_proc_entry
(
name
,
mode
,
acpi_device_dir
(
device
));
if
(
!
proc
)
{
printk
(
KERN_WARNING
" Unable to create %s fs entry
\n
"
,
name
);
return
-
1
;
}
proc
->
write_proc
=
writefunc
;
proc
->
read_proc
=
readfunc
;
proc
->
data
=
acpi_driver_data
(
device
);
proc
->
owner
=
THIS_MODULE
;
proc
->
uid
=
asus_uid
;
proc
->
gid
=
asus_gid
;
return
0
;
}
static
int
__init
asus_hotk_add_fs
(
struct
acpi_device
*
device
)
{
struct
proc_dir_entry
*
proc
;
...
...
@@ -605,46 +829,28 @@ static int __init asus_hotk_add_fs(struct acpi_device *device)
if
(
!
acpi_device_dir
(
device
))
return
(
-
ENODEV
);
proc
=
create_proc_entry
(
PROC_INFO
S
,
mode
,
acpi_device_dir
(
device
));
proc
=
create_proc_entry
(
PROC_INFO
,
mode
,
acpi_device_dir
(
device
));
if
(
proc
)
{
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
->
gid
=
asus_gid
;
}
else
{
printk
(
KERN_WARNING
" Unable to create "
PROC_INFO
S
printk
(
KERN_WARNING
" Unable to create "
PROC_INFO
" fs entry
\n
"
);
}
if
(
hotk
->
methods
->
mt_wled
)
{
proc
=
create_proc_entry
(
PROC_WLED
,
mode
,
acpi_device_dir
(
device
));
if
(
proc
)
{
proc
->
write_proc
=
proc_write_wled
;
proc
->
read_proc
=
proc_read_wled
;
proc
->
data
=
acpi_driver_data
(
device
);
proc
->
owner
=
THIS_MODULE
;
proc
->
uid
=
asus_uid
;
proc
->
gid
=
asus_gid
;;
}
else
{
printk
(
KERN_WARNING
" Unable to create "
PROC_WLED
" fs entry
\n
"
);
}
asus_proc_add
(
PROC_WLED
,
&
proc_write_wled
,
&
proc_read_wled
,
mode
,
device
);
}
if
(
hotk
->
methods
->
mt_mled
)
{
proc
=
create_proc_entry
(
PROC_MLED
,
mode
,
acpi_device_dir
(
device
));
if
(
proc
)
{
proc
->
write_proc
=
proc_write_mled
;
proc
->
read_proc
=
proc_read_mled
;
proc
->
data
=
acpi_driver_data
(
device
);
proc
->
owner
=
THIS_MODULE
;
proc
->
uid
=
asus_uid
;
proc
->
gid
=
asus_gid
;;
}
else
{
printk
(
KERN_WARNING
" Unable to create "
PROC_MLED
" fs entry
\n
"
);
}
asus_proc_add
(
PROC_MLED
,
&
proc_write_mled
,
&
proc_read_mled
,
mode
,
device
);
}
if
(
hotk
->
methods
->
mt_tled
)
{
asus_proc_add
(
PROC_TLED
,
&
proc_write_tled
,
&
proc_read_tled
,
mode
,
device
);
}
/*
...
...
@@ -652,49 +858,17 @@ static int __init asus_hotk_add_fs(struct acpi_device *device)
* from keyboard
*/
if
(
hotk
->
methods
->
mt_lcd_switch
&&
hotk
->
methods
->
lcd_status
)
{
proc
=
create_proc_entry
(
PROC_LCD
,
mode
,
acpi_device_dir
(
device
));
if
(
proc
)
{
proc
->
write_proc
=
proc_write_lcd
;
proc
->
read_proc
=
proc_read_lcd
;
proc
->
data
=
acpi_driver_data
(
device
);
proc
->
owner
=
THIS_MODULE
;
proc
->
uid
=
asus_uid
;
proc
->
gid
=
asus_gid
;;
}
else
{
printk
(
KERN_WARNING
" Unable to create "
PROC_LCD
" fs entry
\n
"
);
}
asus_proc_add
(
PROC_LCD
,
&
proc_write_lcd
,
&
proc_read_lcd
,
mode
,
device
);
}
if
((
hotk
->
methods
->
brightness_up
&&
hotk
->
methods
->
brightness_down
)
||
(
hotk
->
methods
->
brightness_get
&&
hotk
->
methods
->
brightness_get
))
{
proc
=
create_proc_entry
(
PROC_BRN
,
mode
,
acpi_device_dir
(
device
));
if
(
proc
)
{
proc
->
write_proc
=
proc_write_brn
;
proc
->
read_proc
=
proc_read_brn
;
proc
->
data
=
acpi_driver_data
(
device
);
proc
->
owner
=
THIS_MODULE
;
proc
->
uid
=
asus_uid
;
proc
->
gid
=
asus_gid
;;
}
else
{
printk
(
KERN_WARNING
" Unable to create "
PROC_BRN
" fs entry
\n
"
);
}
asus_proc_add
(
PROC_BRN
,
&
proc_write_brn
,
&
proc_read_brn
,
mode
,
device
);
}
if
(
hotk
->
methods
->
display_set
)
{
proc
=
create_proc_entry
(
PROC_DISP
,
mode
,
acpi_device_dir
(
device
));
if
(
proc
)
{
proc
->
write_proc
=
proc_write_disp
;
proc
->
read_proc
=
proc_read_disp
;
proc
->
data
=
acpi_driver_data
(
device
);
proc
->
owner
=
THIS_MODULE
;
proc
->
uid
=
asus_uid
;
proc
->
gid
=
asus_gid
;;
}
else
{
printk
(
KERN_WARNING
" Unable to create "
PROC_DISP
" fs entry
\n
"
);
}
asus_proc_add
(
PROC_DISP
,
&
proc_write_disp
,
&
proc_read_disp
,
mode
,
device
);
}
return
0
;
...
...
@@ -761,11 +935,6 @@ static int __init asus_hotk_get_info(struct asus_hotk *hotk)
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
* have the same methods (L1X has WLED, S1X don't)
*/
model
=
(
union
acpi_object
*
)
buffer
.
pointer
;
if
(
model
->
type
==
ACPI_TYPE_STRING
)
{
printk
(
KERN_NOTICE
" %s model detected, "
,
model
->
string
.
pointer
);
...
...
@@ -774,52 +943,63 @@ static int __init asus_hotk_get_info(struct asus_hotk *hotk)
hotk
->
model
=
END_MODEL
;
if
(
strncmp
(
model
->
string
.
pointer
,
"L3D"
,
3
)
==
0
)
hotk
->
model
=
L3D
;
/*
* L2B has same settings that L3X, except for GL32, but as
* there is no node to get the LCD status, and as GL32 is never
* used anywhere else, I assume it's safe, even if lcd get is
* broken for this model (TODO fix it ?)
*/
else
if
(
strncmp
(
model
->
string
.
pointer
,
"L3H"
,
3
)
==
0
||
strncmp
(
model
->
string
.
pointer
,
"L2E"
,
3
)
==
0
)
hotk
->
model
=
L3H
;
else
if
(
strncmp
(
model
->
string
.
pointer
,
"L3"
,
2
)
==
0
||
strncmp
(
model
->
string
.
pointer
,
"L2B"
,
3
)
==
0
)
hotk
->
model
=
L3X
;
hotk
->
model
=
L3C
;
else
if
(
strncmp
(
model
->
string
.
pointer
,
"L8L"
,
3
)
==
0
)
hotk
->
model
=
L8L
;
else
if
(
strncmp
(
model
->
string
.
pointer
,
"M2N"
,
3
)
==
0
||
strncmp
(
model
->
string
.
pointer
,
"M3N"
,
3
)
==
0
||
strncmp
(
model
->
string
.
pointer
,
"S1N"
,
3
)
==
0
||
strncmp
(
model
->
string
.
pointer
,
"S5N"
,
3
)
==
0
)
hotk
->
model
=
xxN
;
else
if
(
strncmp
(
model
->
string
.
pointer
,
"M1"
,
2
)
==
0
)
hotk
->
model
=
M1A
;
else
if
(
strncmp
(
model
->
string
.
pointer
,
"M2"
,
2
)
==
0
)
hotk
->
model
=
M2X
;
else
if
(
strncmp
(
model
->
string
.
pointer
,
"M3N"
,
3
)
==
0
||
strncmp
(
model
->
string
.
pointer
,
"S1N"
,
3
)
==
0
)
hotk
->
model
=
M3N
;
/* S1300N is similar enough */
hotk
->
model
=
M2E
;
else
if
(
strncmp
(
model
->
string
.
pointer
,
"L2"
,
2
)
==
0
)
hotk
->
model
=
L2X
;
else
if
(
strncmp
(
model
->
string
.
pointer
,
"L8"
,
2
)
==
0
)
{
/* S1300A reports L84F, but L1400B too */
if
(
asus_info
)
{
if
(
strncmp
(
asus_info
->
oem_table_id
,
"L1"
,
2
)
==
0
)
hotk
->
model
=
L1X
;
}
else
hotk
->
model
=
S1X
;
}
hotk
->
model
=
L2D
;
else
if
(
strncmp
(
model
->
string
.
pointer
,
"L8"
,
2
)
==
0
)
hotk
->
model
=
S1x
;
else
if
(
strncmp
(
model
->
string
.
pointer
,
"D1"
,
2
)
==
0
)
hotk
->
model
=
D1
X
;
hotk
->
model
=
D1
x
;
else
if
(
strncmp
(
model
->
string
.
pointer
,
"A1"
,
2
)
==
0
)
hotk
->
model
=
A1
X
;
hotk
->
model
=
A1
x
;
else
if
(
strncmp
(
model
->
string
.
pointer
,
"A2"
,
2
)
==
0
)
hotk
->
model
=
A2
X
;
hotk
->
model
=
A2
x
;
else
if
(
strncmp
(
model
->
string
.
pointer
,
"J1"
,
2
)
==
0
)
hotk
->
model
=
S2
X
;
hotk
->
model
=
S2
x
;
else
if
(
strncmp
(
model
->
string
.
pointer
,
"L5"
,
2
)
==
0
)
hotk
->
model
=
L5
X
;
hotk
->
model
=
L5
x
;
if
(
hotk
->
model
==
END_MODEL
)
{
/* By default use the same values, as I don't know others */
printk
(
"unsupported, trying default values, supply the "
"developers with your DSDT
\n
"
);
hotk
->
model
=
L2X
;
hotk
->
model
=
M2E
;
}
else
{
printk
(
"supported
\n
"
);
}
hotk
->
methods
=
&
model_conf
[
hotk
->
model
];
/* Sort of per-model blacklist */
if
(
strncmp
(
model
->
string
.
pointer
,
"L2B"
,
3
)
==
0
)
hotk
->
methods
->
lcd_status
=
NULL
;
/* L2B is similar enough to L3C to use its settings, with this only
exception */
else
if
(
strncmp
(
model
->
string
.
pointer
,
"S5N"
,
3
)
==
0
)
hotk
->
methods
->
mt_mled
=
NULL
;
/* S5N has no MLED */
else
if
(
asus_info
)
{
if
(
strncmp
(
asus_info
->
oem_table_id
,
"L1"
,
2
)
==
0
)
hotk
->
methods
->
mled_status
=
NULL
;
/* S1300A reports L84F, but L1400B too, account for that */
}
acpi_os_free
(
model
);
return
AE_OK
;
...
...
@@ -917,8 +1097,6 @@ static int __init asus_hotk_add(struct acpi_device *device)
}
static
int
asus_hotk_remove
(
struct
acpi_device
*
device
,
int
type
)
{
acpi_status
status
=
0
;
...
...
@@ -940,15 +1118,13 @@ static int asus_hotk_remove(struct acpi_device *device, int type)
}
static
int
__init
asus_acpi_init
(
void
)
{
int
result
;
asus_proc_dir
=
proc_mkdir
(
PROC_ASUS
,
acpi_root_dir
);
if
(
!
asus_proc_dir
)
{
printk
(
KERN_ERR
"Asus ACPI: Unable to create /proc entry"
);
printk
(
KERN_ERR
"Asus ACPI: Unable to create /proc entry
\n
"
);
return
(
-
ENODEV
);
}
asus_proc_dir
->
owner
=
THIS_MODULE
;
...
...
@@ -963,7 +1139,6 @@ static int __init asus_acpi_init(void)
}
static
void
__exit
asus_acpi_exit
(
void
)
{
acpi_bus_unregister_driver
(
&
asus_hotk_driver
);
...
...
drivers/acpi/pci_irq.c
View file @
0979ec20
...
...
@@ -315,7 +315,6 @@ acpi_pci_irq_enable (
{
int
irq
=
0
;
u8
pin
=
0
;
static
u16
irq_mask
=
0
;
ACPI_FUNCTION_TRACE
(
"acpi_pci_irq_enable"
);
...
...
@@ -372,10 +371,13 @@ acpi_pci_irq_enable (
* Make sure all (legacy) PCI IRQs are set as level-triggered.
*/
#ifdef CONFIG_X86
if
((
dev
->
irq
<
16
)
&&
!
((
1
<<
dev
->
irq
)
&
irq_mask
))
{
ACPI_DEBUG_PRINT
((
ACPI_DB_INFO
,
"Setting IRQ %d as level-triggered
\n
"
,
dev
->
irq
));
irq_mask
|=
(
1
<<
dev
->
irq
);
eisa_set_level_irq
(
dev
->
irq
);
{
static
u16
irq_mask
;
if
((
dev
->
irq
<
16
)
&&
!
((
1
<<
dev
->
irq
)
&
irq_mask
))
{
ACPI_DEBUG_PRINT
((
ACPI_DB_INFO
,
"Setting IRQ %d as level-triggered
\n
"
,
dev
->
irq
));
irq_mask
|=
(
1
<<
dev
->
irq
);
eisa_set_level_irq
(
dev
->
irq
);
}
}
#endif
#ifdef CONFIG_IOSAPIC
...
...
drivers/acpi/toshiba_acpi.c
View file @
0979ec20
...
...
@@ -2,7 +2,7 @@
* toshiba_acpi.c - Toshiba Laptop ACPI Extras
*
*
* Copyright (C) 2002-200
3
John Belmonte
* Copyright (C) 2002-200
4
John Belmonte
*
* 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
...
...
@@ -33,7 +33,7 @@
*
*/
#define TOSHIBA_ACPI_VERSION "0.1
6
"
#define TOSHIBA_ACPI_VERSION "0.1
7
"
#define PROC_INTERFACE_VERSION 1
#include <linux/kernel.h>
...
...
@@ -48,9 +48,15 @@ MODULE_AUTHOR("John Belmonte");
MODULE_DESCRIPTION
(
"Toshiba Laptop ACPI Extras Driver"
);
MODULE_LICENSE
(
"GPL"
);
#define MY_LOGPREFIX "toshiba_acpi: "
#define MY_ERR KERN_ERR MY_LOGPREFIX
#define MY_NOTICE KERN_NOTICE MY_LOGPREFIX
#define MY_INFO KERN_INFO MY_LOGPREFIX
/* Toshiba ACPI method paths */
#define METHOD_LCD_BRIGHTNESS "\\_SB_.PCI0.VGA_.LCD_._BCM"
#define METHOD_HCI "\\_SB_.VALD.GHCI"
#define METHOD_HCI_1 "\\_SB_.VALD.GHCI"
#define METHOD_HCI_2 "\\_SB_.VALZ.GHCI"
#define METHOD_VIDEO_OUT "\\_SB_.VALX.DSSX"
/* Toshiba HCI interface definitions
...
...
@@ -120,6 +126,16 @@ snscanf(const char* str, int n, const char* format, ...)
/* acpi interface wrappers
*/
static
int
is_valid_acpi_path
(
const
char
*
methodName
)
{
acpi_handle
handle
;
acpi_status
status
;
status
=
acpi_get_handle
(
0
,
(
char
*
)
methodName
,
&
handle
);
return
!
ACPI_FAILURE
(
status
);
}
static
int
write_acpi_int
(
const
char
*
methodName
,
int
val
)
{
...
...
@@ -154,6 +170,8 @@ read_acpi_int(const char* methodName, int* pVal)
}
#endif
static
const
char
*
method_hci
/*= 0*/
;
/* Perform a raw HCI call. Here we don't care about input or output buffer
* format.
*/
...
...
@@ -177,7 +195,7 @@ hci_raw(const u32 in[HCI_WORDS], u32 out[HCI_WORDS])
results
.
length
=
sizeof
(
out_objs
);
results
.
pointer
=
out_objs
;
status
=
acpi_evaluate_object
(
0
,
METHOD_HCI
,
&
params
,
status
=
acpi_evaluate_object
(
0
,
(
char
*
)
method_hci
,
&
params
,
&
results
);
if
((
status
==
AE_OK
)
&&
(
out_objs
->
package
.
count
<=
HCI_WORDS
))
{
for
(
i
=
0
;
i
<
out_objs
->
package
.
count
;
++
i
)
{
...
...
@@ -215,7 +233,7 @@ hci_read1(u32 reg, u32* out1, u32* result)
return
status
;
}
static
struct
proc_dir_entry
*
toshiba_proc_dir
;
static
struct
proc_dir_entry
*
toshiba_proc_dir
/*= 0*/
;
static
int
force_fan
;
static
int
last_key_event
;
static
int
key_event_valid
;
...
...
@@ -270,7 +288,7 @@ read_lcd(char* p)
p
+=
sprintf
(
p
,
"brightness_levels: %d
\n
"
,
HCI_LCD_BRIGHTNESS_LEVELS
);
}
else
{
p
+=
sprintf
(
p
,
"ERROR
\n
"
);
p
rintk
(
MY_ERR
"Error reading LCD brightness
\n
"
);
}
return
p
;
...
...
@@ -310,7 +328,7 @@ read_video(char* p)
p
+=
sprintf
(
p
,
"crt_out: %d
\n
"
,
is_crt
);
p
+=
sprintf
(
p
,
"tv_out: %d
\n
"
,
is_tv
);
}
else
{
p
+=
sprintf
(
p
,
"ERROR
\n
"
);
p
rintk
(
MY_ERR
"Error reading video out status
\n
"
);
}
return
p
;
...
...
@@ -320,25 +338,31 @@ static unsigned long
write_video
(
const
char
*
buffer
,
unsigned
long
count
)
{
int
value
;
const
char
*
buffer_end
=
buffer
+
count
;
int
remain
=
count
;
int
lcd_out
=
-
1
;
int
crt_out
=
-
1
;
int
tv_out
=
-
1
;
u32
hci_result
;
int
video_out
;
/* scan expression. Multiple expressions may be delimited with ; */
do
{
if
(
snscanf
(
buffer
,
count
,
" lcd_out : %i"
,
&
value
)
==
1
)
/* scan expression. Multiple expressions may be delimited with ;
*
* NOTE: to keep scanning simple, invalid fields are ignored
*/
while
(
remain
)
{
if
(
snscanf
(
buffer
,
remain
,
" lcd_out : %i"
,
&
value
)
==
1
)
lcd_out
=
value
&
1
;
else
if
(
snscanf
(
buffer
,
count
,
" crt_out : %i"
,
&
value
)
==
1
)
else
if
(
snscanf
(
buffer
,
remain
,
" crt_out : %i"
,
&
value
)
==
1
)
crt_out
=
value
&
1
;
else
if
(
snscanf
(
buffer
,
count
,
" tv_out : %i"
,
&
value
)
==
1
)
else
if
(
snscanf
(
buffer
,
remain
,
" tv_out : %i"
,
&
value
)
==
1
)
tv_out
=
value
&
1
;
/* advance to one character past the next ; */
do
++
buffer
;
while
((
buffer
<
buffer_end
)
&&
(
*
(
buffer
-
1
)
!=
';'
));
}
while
(
buffer
<
buffer_end
);
do
{
++
buffer
;
--
remain
;
}
while
(
remain
&&
*
(
buffer
-
1
)
!=
';'
);
}
hci_read1
(
HCI_VIDEO_OUT
,
&
video_out
,
&
hci_result
);
if
(
hci_result
==
HCI_SUCCESS
)
{
...
...
@@ -353,6 +377,8 @@ write_video(const char* buffer, unsigned long count)
* video setting if something changed. */
if
(
new_video_out
!=
video_out
)
write_acpi_int
(
METHOD_VIDEO_OUT
,
new_video_out
);
}
else
{
return
-
EFAULT
;
}
return
count
;
...
...
@@ -369,7 +395,7 @@ read_fan(char* p)
p
+=
sprintf
(
p
,
"running: %d
\n
"
,
(
value
>
0
));
p
+=
sprintf
(
p
,
"force_on: %d
\n
"
,
force_fan
);
}
else
{
p
+=
sprintf
(
p
,
"ERROR
\n
"
);
p
rintk
(
MY_ERR
"Error reading fan status
\n
"
);
}
return
p
;
...
...
@@ -413,8 +439,9 @@ read_keys(char* p)
* some machines where system events sporadically
* become disabled. */
hci_write1
(
HCI_SYSTEM_EVENT
,
1
,
&
hci_result
);
printk
(
MY_NOTICE
"Re-enabled hotkeys
\n
"
);
}
else
{
p
+=
sprintf
(
p
,
"ERROR
\n
"
);
p
rintk
(
MY_ERR
"Error reading hotkey status
\n
"
);
goto
end
;
}
}
...
...
@@ -465,7 +492,7 @@ ProcItem proc_items[] =
{
0
,
0
,
0
},
};
static
acpi_status
static
acpi_status
__init
add_device
(
void
)
{
struct
proc_dir_entry
*
proc
;
...
...
@@ -483,7 +510,7 @@ add_device(void)
return
(
AE_OK
);
}
static
acpi_status
static
acpi_status
__exit
remove_device
(
void
)
{
ProcItem
*
item
;
...
...
@@ -497,15 +524,19 @@ static int __init
toshiba_acpi_init
(
void
)
{
acpi_status
status
=
AE_OK
;
int
value
;
u32
hci_result
;
/* simple device detection: try reading an HCI register */
hci_read1
(
HCI_LCD_BRIGHTNESS
,
&
value
,
&
hci_result
);
if
(
hci_result
!=
HCI_SUCCESS
)
/* simple device detection: look for HCI method */
if
(
is_valid_acpi_path
(
METHOD_HCI_1
))
method_hci
=
METHOD_HCI_1
;
else
if
(
is_valid_acpi_path
(
METHOD_HCI_2
))
method_hci
=
METHOD_HCI_2
;
else
return
-
ENODEV
;
printk
(
"Toshiba Laptop ACPI Extras version %s
\n
"
,
TOSHIBA_ACPI_VERSION
);
printk
(
MY_INFO
"Toshiba Laptop ACPI Extras version %s
\n
"
,
TOSHIBA_ACPI_VERSION
);
printk
(
MY_INFO
" HCI method: %s
\n
"
,
method_hci
);
force_fan
=
0
;
key_event_valid
=
0
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment