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
nexedi
linux
Commits
b4549a24
Commit
b4549a24
authored
Sep 19, 2009
by
Len Brown
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'asus' into release
parents
3bb29ec1
52cc96bd
Changes
9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
830 additions
and
193 deletions
+830
-193
Documentation/ABI/stable/sysfs-class-backlight
Documentation/ABI/stable/sysfs-class-backlight
+36
-0
Documentation/ABI/testing/sysfs-class-lcd
Documentation/ABI/testing/sysfs-class-lcd
+23
-0
Documentation/ABI/testing/sysfs-class-led
Documentation/ABI/testing/sysfs-class-led
+28
-0
Documentation/ABI/testing/sysfs-platform-asus-laptop
Documentation/ABI/testing/sysfs-platform-asus-laptop
+52
-0
Documentation/ABI/testing/sysfs-platform-eeepc-laptop
Documentation/ABI/testing/sysfs-platform-eeepc-laptop
+50
-0
Documentation/laptops/asus-laptop.txt
Documentation/laptops/asus-laptop.txt
+258
-0
Documentation/leds-class.txt
Documentation/leds-class.txt
+5
-4
drivers/platform/x86/asus-laptop.c
drivers/platform/x86/asus-laptop.c
+173
-54
drivers/platform/x86/eeepc-laptop.c
drivers/platform/x86/eeepc-laptop.c
+205
-135
No files found.
Documentation/ABI/stable/sysfs-class-backlight
0 → 100644
View file @
b4549a24
What: /sys/class/backlight/<backlight>/bl_power
Date: April 2005
KernelVersion: 2.6.12
Contact: Richard Purdie <rpurdie@rpsys.net>
Description:
Control BACKLIGHT power, values are FB_BLANK_* from fb.h
- FB_BLANK_UNBLANK (0) : power on.
- FB_BLANK_POWERDOWN (4) : power off
Users: HAL
What: /sys/class/backlight/<backlight>/brightness
Date: April 2005
KernelVersion: 2.6.12
Contact: Richard Purdie <rpurdie@rpsys.net>
Description:
Control the brightness for this <backlight>. Values
are between 0 and max_brightness. This file will also
show the brightness level stored in the driver, which
may not be the actual brightness (see actual_brightness).
Users: HAL
What: /sys/class/backlight/<backlight>/actual_brightness
Date: March 2006
KernelVersion: 2.6.17
Contact: Richard Purdie <rpurdie@rpsys.net>
Description:
Show the actual brightness by querying the hardware.
Users: HAL
What: /sys/class/backlight/<backlight>/max_brightness
Date: April 2005
KernelVersion: 2.6.12
Contact: Richard Purdie <rpurdie@rpsys.net>
Description:
Maximum brightness for <backlight>.
Users: HAL
Documentation/ABI/testing/sysfs-class-lcd
0 → 100644
View file @
b4549a24
What: /sys/class/lcd/<lcd>/lcd_power
Date: April 2005
KernelVersion: 2.6.12
Contact: Richard Purdie <rpurdie@rpsys.net>
Description:
Control LCD power, values are FB_BLANK_* from fb.h
- FB_BLANK_UNBLANK (0) : power on.
- FB_BLANK_POWERDOWN (4) : power off
What: /sys/class/lcd/<lcd>/contrast
Date: April 2005
KernelVersion: 2.6.12
Contact: Richard Purdie <rpurdie@rpsys.net>
Description:
Current contrast of this LCD device. Value is between 0 and
/sys/class/lcd/<lcd>/max_contrast.
What: /sys/class/lcd/<lcd>/max_contrast
Date: April 2005
KernelVersion: 2.6.12
Contact: Richard Purdie <rpurdie@rpsys.net>
Description:
Maximum contrast for this LCD device.
Documentation/ABI/testing/sysfs-class-led
0 → 100644
View file @
b4549a24
What: /sys/class/leds/<led>/brightness
Date: March 2006
KernelVersion: 2.6.17
Contact: Richard Purdie <rpurdie@rpsys.net>
Description:
Set the brightness of the LED. Most LEDs don't
have hardware brightness support so will just be turned on for
non-zero brightness settings. The value is between 0 and
/sys/class/leds/<led>/max_brightness.
What: /sys/class/leds/<led>/max_brightness
Date: March 2006
KernelVersion: 2.6.17
Contact: Richard Purdie <rpurdie@rpsys.net>
Description:
Maximum brightness level for this led, default is 255 (LED_FULL).
What: /sys/class/leds/<led>/trigger
Date: March 2006
KernelVersion: 2.6.17
Contact: Richard Purdie <rpurdie@rpsys.net>
Description:
Set the trigger for this LED. A trigger is a kernel based source
of led events.
You can change triggers in a similar manner to the way an IO
scheduler is chosen. Trigger specific parameters can appear in
/sys/class/leds/<led> once a given trigger is selected.
Documentation/ABI/testing/sysfs-platform-asus-laptop
0 → 100644
View file @
b4549a24
What: /sys/devices/platform/asus-laptop/display
Date: January 2007
KernelVersion: 2.6.20
Contact: "Corentin Chary" <corentincj@iksaif.net>
Description:
This file allows display switching. The value
is composed by 4 bits and defined as follow:
4321
|||`- LCD
||`-- CRT
|`--- TV
`---- DVI
Ex: - 0 (0000b) means no display
- 3 (0011b) CRT+LCD.
What: /sys/devices/platform/asus-laptop/gps
Date: January 2007
KernelVersion: 2.6.20
Contact: "Corentin Chary" <corentincj@iksaif.net>
Description:
Control the gps device. 1 means on, 0 means off.
Users: Lapsus
What: /sys/devices/platform/asus-laptop/ledd
Date: January 2007
KernelVersion: 2.6.20
Contact: "Corentin Chary" <corentincj@iksaif.net>
Description:
Some models like the W1N have a LED display that can be
used to display several informations.
To control the LED display, use the following :
echo 0x0T000DDD > /sys/devices/platform/asus-laptop/
where T control the 3 letters display, and DDD the 3 digits display.
The DDD table can be found in Documentation/laptops/asus-laptop.txt
What: /sys/devices/platform/asus-laptop/bluetooth
Date: January 2007
KernelVersion: 2.6.20
Contact: "Corentin Chary" <corentincj@iksaif.net>
Description:
Control the bluetooth device. 1 means on, 0 means off.
This may control the led, the device or both.
Users: Lapsus
What: /sys/devices/platform/asus-laptop/wlan
Date: January 2007
KernelVersion: 2.6.20
Contact: "Corentin Chary" <corentincj@iksaif.net>
Description:
Control the bluetooth device. 1 means on, 0 means off.
This may control the led, the device or both.
Users: Lapsus
Documentation/ABI/testing/sysfs-platform-eeepc-laptop
0 → 100644
View file @
b4549a24
What: /sys/devices/platform/eeepc-laptop/disp
Date: May 2008
KernelVersion: 2.6.26
Contact: "Corentin Chary" <corentincj@iksaif.net>
Description:
This file allows display switching.
- 1 = LCD
- 2 = CRT
- 3 = LCD+CRT
If you run X11, you should use xrandr instead.
What: /sys/devices/platform/eeepc-laptop/camera
Date: May 2008
KernelVersion: 2.6.26
Contact: "Corentin Chary" <corentincj@iksaif.net>
Description:
Control the camera. 1 means on, 0 means off.
What: /sys/devices/platform/eeepc-laptop/cardr
Date: May 2008
KernelVersion: 2.6.26
Contact: "Corentin Chary" <corentincj@iksaif.net>
Description:
Control the card reader. 1 means on, 0 means off.
What: /sys/devices/platform/eeepc-laptop/cpufv
Date: Jun 2009
KernelVersion: 2.6.31
Contact: "Corentin Chary" <corentincj@iksaif.net>
Description:
Change CPU clock configuration.
On the Eee PC 1000H there are three available clock configuration:
* 0 -> Super Performance Mode
* 1 -> High Performance Mode
* 2 -> Power Saving Mode
On Eee PC 701 there is only 2 available clock configurations.
Available configuration are listed in available_cpufv file.
Reading this file will show the raw hexadecimal value which
is defined as follow:
| 8 bit | 8 bit |
| `---- Current mode
`------------ Availables modes
For example, 0x301 means: mode 1 selected, 3 available modes.
What: /sys/devices/platform/eeepc-laptop/available_cpufv
Date: Jun 2009
KernelVersion: 2.6.31
Contact: "Corentin Chary" <corentincj@iksaif.net>
Description:
List available cpufv modes.
Documentation/laptops/asus-laptop.txt
0 → 100644
View file @
b4549a24
Asus Laptop Extras
Version 0.1
August 6, 2009
Corentin Chary <corentincj@iksaif.net>
http://acpi4asus.sf.net/
This driver provides support for extra features of ACPI-compatible ASUS laptops.
It may also support some MEDION, JVC or VICTOR laptops (such as MEDION 9675 or
VICTOR XP7210 for example). It makes all the extra buttons generate standard
ACPI events that go through /proc/acpi/events and input events (like keyboards).
On some models adds support for changing the display brightness and output,
switching the LCD backlight on and off, and most importantly, allows you to
blink those fancy LEDs intended for reporting mail and wireless status.
This driver supercedes the old asus_acpi driver.
Requirements
------------
Kernel 2.6.X sources, configured for your computer, with ACPI support.
You also need CONFIG_INPUT and CONFIG_ACPI.
Status
------
The features currently supported are the following (see below for
detailed description):
- Fn key combinations
- Bluetooth enable and disable
- Wlan enable and disable
- GPS enable and disable
- Video output switching
- Ambient Light Sensor on and off
- LED control
- LED Display control
- LCD brightness control
- LCD on and off
A compatibility table by model and feature is maintained on the web
site, http://acpi4asus.sf.net/.
Usage
-----
Try "modprobe asus_acpi". Check your dmesg (simply type dmesg). You should
see some lines like this :
Asus Laptop Extras version 0.42
L2D model detected.
If it is not the output you have on your laptop, send it (and the laptop's
DSDT) to me.
That's all, now, all the events generated by the hotkeys of your laptop
should be reported in your /proc/acpi/event entry. You can check with
"acpi_listen".
Hotkeys are also reported as input keys (like keyboards) you can check
which key are supported using "xev" under X11.
You can get informations on the version of your DSDT table by reading the
/sys/devices/platform/asus-laptop/infos entry. If you have a question or a
bug report to do, please include the output of this entry.
LEDs
----
You can modify LEDs be echoing values to /sys/class/leds/asus::*/brightness :
echo 1 > /sys/class/leds/asus::mail/brightness
will switch the mail LED on.
You can also know if they are on/off by reading their content and use
kernel triggers like ide-disk or heartbeat.
Backlight
---------
You can control lcd backlight power and brightness with
/sys/class/backlight/asus-laptop/. Brightness Values are between 0 and 15.
Wireless devices
---------------
You can turn the internal Bluetooth adapter on/off with the bluetooth entry
(only on models with Bluetooth). This usually controls the associated LED.
Same for Wlan adapter.
Display switching
-----------------
Note: the display switching code is currently considered EXPERIMENTAL.
Switching works for the following models:
L3800C
A2500H
L5800C
M5200N
W1000N (albeit with some glitches)
M6700R
A6JC
F3J
Switching doesn't work for the following:
M3700N
L2X00D (locks the laptop under certain conditions)
To switch the displays, echo values from 0 to 15 to
/sys/devices/platform/asus-laptop/display. The significance of those values
is as follows:
+-------+-----+-----+-----+-----+-----+
| Bin | Val | DVI | TV | CRT | LCD |
+-------+-----+-----+-----+-----+-----+
+ 0000 + 0 + + + + +
+-------+-----+-----+-----+-----+-----+
+ 0001 + 1 + + + + X +
+-------+-----+-----+-----+-----+-----+
+ 0010 + 2 + + + X + +
+-------+-----+-----+-----+-----+-----+
+ 0011 + 3 + + + X + X +
+-------+-----+-----+-----+-----+-----+
+ 0100 + 4 + + X + + +
+-------+-----+-----+-----+-----+-----+
+ 0101 + 5 + + X + + X +
+-------+-----+-----+-----+-----+-----+
+ 0110 + 6 + + X + X + +
+-------+-----+-----+-----+-----+-----+
+ 0111 + 7 + + X + X + X +
+-------+-----+-----+-----+-----+-----+
+ 1000 + 8 + X + + + +
+-------+-----+-----+-----+-----+-----+
+ 1001 + 9 + X + + + X +
+-------+-----+-----+-----+-----+-----+
+ 1010 + 10 + X + + X + +
+-------+-----+-----+-----+-----+-----+
+ 1011 + 11 + X + + X + X +
+-------+-----+-----+-----+-----+-----+
+ 1100 + 12 + X + X + + +
+-------+-----+-----+-----+-----+-----+
+ 1101 + 13 + X + X + + X +
+-------+-----+-----+-----+-----+-----+
+ 1110 + 14 + X + X + X + +
+-------+-----+-----+-----+-----+-----+
+ 1111 + 15 + X + X + X + X +
+-------+-----+-----+-----+-----+-----+
In most cases, the appropriate displays must be plugged in for the above
combinations to work. TV-Out may need to be initialized at boot time.
Debugging:
1) Check whether the Fn+F8 key:
a) does not lock the laptop (try disabling CONFIG_X86_UP_APIC or boot with
noapic / nolapic if it does)
b) generates events (0x6n, where n is the value corresponding to the
configuration above)
c) actually works
Record the disp value at every configuration.
2) Echo values from 0 to 15 to /sys/devices/platform/asus-laptop/display.
Record its value, note any change. If nothing changes, try a broader range,
up to 65535.
3) Send ANY output (both positive and negative reports are needed, unless your
machine is already listed above) to the acpi4asus-user mailing list.
Note: on some machines (e.g. L3C), after the module has been loaded, only 0x6n
events are generated and no actual switching occurs. In such a case, a line
like:
echo $((10#$arg-60)) > /sys/devices/platform/asus-laptop/display
will usually do the trick ($arg is the 0000006n-like event passed to acpid).
Note: there is currently no reliable way to read display status on xxN
(Centrino) models.
LED display
-----------
Some models like the W1N have a LED display that can be used to display
several informations.
LED display works for the following models:
W1000N
W1J
To control the LED display, use the following :
echo 0x0T000DDD > /sys/devices/platform/asus-laptop/
where T control the 3 letters display, and DDD the 3 digits display,
according to the tables below.
DDD (digits)
000 to 999 = display digits
AAA = ---
BBB to FFF = turn-off
T (type)
0 = off
1 = dvd
2 = vcd
3 = mp3
4 = cd
5 = tv
6 = cpu
7 = vol
For example "echo 0x01000001 >/sys/devices/platform/asus-laptop/ledd"
would display "DVD001".
Driver options:
---------------
Options can be passed to the asus-laptop driver using the standard
module argument syntax (<param>=<value> when passing the option to the
module or asus-laptop.<param>=<value> on the kernel boot line when
asus-laptop is statically linked into the kernel).
wapf: WAPF defines the behavior of the Fn+Fx wlan key
The significance of values is yet to be found, but
most of the time:
- 0x0 should do nothing
- 0x1 should allow to control the device with Fn+Fx key.
- 0x4 should send an ACPI event (0x88) while pressing the Fn+Fx key
- 0x5 like 0x1 or 0x4
The default value is 0x1.
Unsupported models
------------------
These models will never be supported by this module, as they use a completely
different mechanism to handle LEDs and extra stuff (meaning we have no clue
how it works):
- ASUS A1300 (A1B), A1370D
- ASUS L7300G
- ASUS L8400
Patches, Errors, Questions:
--------------------------
I appreciate any success or failure
reports, especially if they add to or correct the compatibility table.
Please include the following information in your report:
- Asus model name
- a copy of your ACPI tables, using the "acpidump" utility
- a copy of /sys/devices/platform/asus-laptop/infos
- which driver features work and which don't
- the observed behavior of non-working features
Any other comments or patches are also more than welcome.
acpi4asus-user@lists.sourceforge.net
http://sourceforge.net/projects/acpi4asus
Documentation/leds-class.txt
View file @
b4549a24
LED handling under Linux
========================
...
...
@@ -5,10 +6,10 @@ If you're reading this and thinking about keyboard leds, these are
handled by the input subsystem and the led class is *not* needed.
In its simplest form, the LED class just allows control of LEDs from
userspace. LEDs appear in /sys/class/leds/. The
brightness file will
set the brightness of the LED (taking a value 0-255). Most LEDs don't
have hardware brightness support so will just be turned on for non-zero
brightness settings.
userspace. LEDs appear in /sys/class/leds/. The
maximum brightness of the
LED is defined in max_brightness file. The brightness file will set the brightness
of the LED (taking a value 0-max_brightness). Most LEDs don't have hardware
brightness s
upport so will just be turned on for non-zero brightness s
ettings.
The class also introduces the optional concept of an LED trigger. A trigger
is a kernel based source of led events. Triggers can either be simple or
...
...
drivers/platform/x86/asus-laptop.c
View file @
b4549a24
...
...
@@ -77,15 +77,16 @@
* Flags for hotk status
* WL_ON and BT_ON are also used for wireless_status()
*/
#define WL_ON 0x01 //internal Wifi
#define BT_ON 0x02 //internal Bluetooth
#define MLED_ON 0x04 //mail LED
#define TLED_ON 0x08 //touchpad LED
#define RLED_ON 0x10 //Record LED
#define PLED_ON 0x20 //Phone LED
#define GLED_ON 0x40 //Gaming LED
#define LCD_ON 0x80 //LCD backlight
#define GPS_ON 0x100 //GPS
#define WL_ON 0x01
/* internal Wifi */
#define BT_ON 0x02
/* internal Bluetooth */
#define MLED_ON 0x04
/* mail LED */
#define TLED_ON 0x08
/* touchpad LED */
#define RLED_ON 0x10
/* Record LED */
#define PLED_ON 0x20
/* Phone LED */
#define GLED_ON 0x40
/* Gaming LED */
#define LCD_ON 0x80
/* LCD backlight */
#define GPS_ON 0x100
/* GPS */
#define KEY_ON 0x200
/* Keyboard backlight */
#define ASUS_LOG ASUS_HOTK_FILE ": "
#define ASUS_ERR KERN_ERR ASUS_LOG
...
...
@@ -98,7 +99,8 @@ MODULE_AUTHOR("Julien Lerouge, Karol Kozimor, Corentin Chary");
MODULE_DESCRIPTION
(
ASUS_HOTK_NAME
);
MODULE_LICENSE
(
"GPL"
);
/* WAPF defines the behavior of the Fn+Fx wlan key
/*
* WAPF defines the behavior of the Fn+Fx wlan key
* The significance of values is yet to be found, but
* most of the time:
* 0x0 will do nothing
...
...
@@ -125,7 +127,8 @@ ASUS_HANDLE(gled_set, ASUS_HOTK_PREFIX "GLED"); /* G1, G2 (probably) */
/* LEDD */
ASUS_HANDLE
(
ledd_set
,
ASUS_HOTK_PREFIX
"SLCM"
);
/* Bluetooth and WLAN
/*
* Bluetooth and WLAN
* WLED and BLED are not handled like other XLED, because in some dsdt
* they also control the WLAN/Bluetooth device.
*/
...
...
@@ -149,22 +152,32 @@ ASUS_HANDLE(lcd_switch, "\\_SB.PCI0.SBRG.EC0._Q10", /* All new models */
/* Display */
ASUS_HANDLE
(
display_set
,
ASUS_HOTK_PREFIX
"SDSP"
);
ASUS_HANDLE
(
display_get
,
"
\\
_SB.PCI0.P0P1.VGA.GETD"
,
/* A6B, A6K A6R A7D F3JM L4R M6R A3G
M6A M6V VX-1 V6J V6V W3Z */
"
\\
_SB.PCI0.P0P2.VGA.GETD"
,
/* A3E A4K, A4D A4L A6J A7J A8J Z71V M9V
S5A M5A z33A W1Jc W2V G1 */
"
\\
_SB.PCI0.P0P3.VGA.GETD"
,
/* A6V A6Q */
"
\\
_SB.PCI0.P0PA.VGA.GETD"
,
/* A6T, A6M */
"
\\
_SB.PCI0.PCI1.VGAC.NMAP"
,
/* L3C */
"
\\
_SB.PCI0.VGA.GETD"
,
/* Z96F */
"
\\
ACTD"
,
/* A2D */
"
\\
ADVG"
,
/* A4G Z71A W1N W5A W5F M2N M3N M5N M6N S1N S5N */
"
\\
DNXT"
,
/* P30 */
"
\\
INFB"
,
/* A2H D1 L2D L3D L3H L2E L5D L5C M1A M2E L4L W3V */
"
\\
SSTE"
);
/* A3F A6F A3N A3L M6N W3N W6A */
ASUS_HANDLE
(
ls_switch
,
ASUS_HOTK_PREFIX
"ALSC"
);
/* Z71A Z71V */
ASUS_HANDLE
(
ls_level
,
ASUS_HOTK_PREFIX
"ALSL"
);
/* Z71A Z71V */
ASUS_HANDLE
(
display_get
,
/* A6B, A6K A6R A7D F3JM L4R M6R A3G M6A M6V VX-1 V6J V6V W3Z */
"
\\
_SB.PCI0.P0P1.VGA.GETD"
,
/* A3E A4K, A4D A4L A6J A7J A8J Z71V M9V S5A M5A z33A W1Jc W2V G1 */
"
\\
_SB.PCI0.P0P2.VGA.GETD"
,
/* A6V A6Q */
"
\\
_SB.PCI0.P0P3.VGA.GETD"
,
/* A6T, A6M */
"
\\
_SB.PCI0.P0PA.VGA.GETD"
,
/* L3C */
"
\\
_SB.PCI0.PCI1.VGAC.NMAP"
,
/* Z96F */
"
\\
_SB.PCI0.VGA.GETD"
,
/* A2D */
"
\\
ACTD"
,
/* A4G Z71A W1N W5A W5F M2N M3N M5N M6N S1N S5N */
"
\\
ADVG"
,
/* P30 */
"
\\
DNXT"
,
/* A2H D1 L2D L3D L3H L2E L5D L5C M1A M2E L4L W3V */
"
\\
INFB"
,
/* A3F A6F A3N A3L M6N W3N W6A */
"
\\
SSTE"
);
ASUS_HANDLE
(
ls_switch
,
ASUS_HOTK_PREFIX
"ALSC"
);
/* Z71A Z71V */
ASUS_HANDLE
(
ls_level
,
ASUS_HOTK_PREFIX
"ALSL"
);
/* Z71A Z71V */
/* GPS */
/* R2H use different handle for GPS on/off */
...
...
@@ -172,19 +185,23 @@ ASUS_HANDLE(gps_on, ASUS_HOTK_PREFIX "SDON"); /* R2H */
ASUS_HANDLE
(
gps_off
,
ASUS_HOTK_PREFIX
"SDOF"
);
/* R2H */
ASUS_HANDLE
(
gps_status
,
ASUS_HOTK_PREFIX
"GPST"
);
/* Keyboard light */
ASUS_HANDLE
(
kled_set
,
ASUS_HOTK_PREFIX
"SLKB"
);
ASUS_HANDLE
(
kled_get
,
ASUS_HOTK_PREFIX
"GLKB"
);
/*
* This is the main structure, we can use it to store anything interesting
* about the hotk device
*/
struct
asus_hotk
{
char
*
name
;
/
/laptop name
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
u8
light_level
;
/
/light sensor level
u8
light_switch
;
/
/light sensor switch value
u16
event_count
[
128
];
/
/count for each event TODO make this better
char
*
name
;
/
* laptop name */
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 */
u8
light_level
;
/
* light sensor level */
u8
light_switch
;
/
* light sensor switch value */
u16
event_count
[
128
];
/
* count for each event TODO make this better */
struct
input_dev
*
inputdev
;
u16
*
keycode_map
;
};
...
...
@@ -237,28 +254,35 @@ static struct backlight_ops asusbl_ops = {
.
update_status
=
update_bl_status
,
};
/* These functions actually update the LED's, and are called from a
/*
* These functions actually update the LED's, and are called from a
* workqueue. By doing this as separate work rather than when the LED
* subsystem asks, we avoid messing with the Asus ACPI stuff during a
* potentially bad time, such as a timer interrupt. */
* potentially bad time, such as a timer interrupt.
*/
static
struct
workqueue_struct
*
led_workqueue
;
#define ASUS_LED(object, ledname) \
#define ASUS_LED(object, ledname
, max
) \
static void object##_led_set(struct led_classdev *led_cdev, \
enum led_brightness value); \
static enum led_brightness object##_led_get( \
struct led_classdev *led_cdev); \
static void object##_led_update(struct work_struct *ignored); \
static int object##_led_wk; \
static DECLARE_WORK(object##_led_work, object##_led_update); \
static struct led_classdev object##_led = { \
.name = "asus::" ledname, \
.brightness_set = object##_led_set, \
.brightness_get = object##_led_get, \
.max_brightness = max \
}
ASUS_LED
(
mled
,
"mail"
);
ASUS_LED
(
tled
,
"touchpad"
);
ASUS_LED
(
rled
,
"record"
);
ASUS_LED
(
pled
,
"phone"
);
ASUS_LED
(
gled
,
"gaming"
);
ASUS_LED
(
mled
,
"mail"
,
1
);
ASUS_LED
(
tled
,
"touchpad"
,
1
);
ASUS_LED
(
rled
,
"record"
,
1
);
ASUS_LED
(
pled
,
"phone"
,
1
);
ASUS_LED
(
gled
,
"gaming"
,
1
);
ASUS_LED
(
kled
,
"kbd_backlight"
,
3
);
struct
key_entry
{
char
type
;
...
...
@@ -278,16 +302,23 @@ static struct key_entry asus_keymap[] = {
{
KE_KEY
,
0x41
,
KEY_NEXTSONG
},
{
KE_KEY
,
0x43
,
KEY_STOPCD
},
{
KE_KEY
,
0x45
,
KEY_PLAYPAUSE
},
{
KE_KEY
,
0x4c
,
KEY_MEDIA
},
{
KE_KEY
,
0x50
,
KEY_EMAIL
},
{
KE_KEY
,
0x51
,
KEY_WWW
},
{
KE_KEY
,
0x55
,
KEY_CALC
},
{
KE_KEY
,
0x5C
,
KEY_SCREENLOCK
},
/* Screenlock */
{
KE_KEY
,
0x5D
,
KEY_WLAN
},
{
KE_KEY
,
0x5E
,
KEY_WLAN
},
{
KE_KEY
,
0x5F
,
KEY_WLAN
},
{
KE_KEY
,
0x60
,
KEY_SWITCHVIDEOMODE
},
{
KE_KEY
,
0x61
,
KEY_SWITCHVIDEOMODE
},
{
KE_KEY
,
0x6B
,
BTN_TOUCH
},
/* Lock Mouse */
{
KE_KEY
,
0x82
,
KEY_CAMERA
},
{
KE_KEY
,
0x8A
,
KEY_PROG1
},
{
KE_KEY
,
0x95
,
KEY_MEDIA
},
{
KE_KEY
,
0x99
,
KEY_PHONE
},
{
KE_KEY
,
0xc4
,
KEY_KBDILLUMUP
},
{
KE_KEY
,
0xc5
,
KEY_KBDILLUMDOWN
},
{
KE_END
,
0
},
};
...
...
@@ -301,8 +332,8 @@ static struct key_entry asus_keymap[] = {
static
int
write_acpi_int
(
acpi_handle
handle
,
const
char
*
method
,
int
val
,
struct
acpi_buffer
*
output
)
{
struct
acpi_object_list
params
;
/
/list of input parameters (an int here)
union
acpi_object
in_obj
;
/
/the only param we use
struct
acpi_object_list
params
;
/
* list of input parameters (an int) */
union
acpi_object
in_obj
;
/
* the only param we use */
acpi_status
status
;
if
(
!
handle
)
...
...
@@ -399,6 +430,11 @@ static void write_status(acpi_handle handle, int out, int mask)
{ \
int value = object##_led_wk; \
write_status(object##_set_handle, value, (mask)); \
} \
static enum led_brightness object##_led_get( \
struct led_classdev *led_cdev) \
{ \
return led_cdev->brightness; \
}
ASUS_LED_HANDLER
(
mled
,
MLED_ON
);
...
...
@@ -407,6 +443,60 @@ ASUS_LED_HANDLER(rled, RLED_ON);
ASUS_LED_HANDLER
(
tled
,
TLED_ON
);
ASUS_LED_HANDLER
(
gled
,
GLED_ON
);
/*
* Keyboard backlight
*/
static
int
get_kled_lvl
(
void
)
{
unsigned
long
long
kblv
;
struct
acpi_object_list
params
;
union
acpi_object
in_obj
;
acpi_status
rv
;
params
.
count
=
1
;
params
.
pointer
=
&
in_obj
;
in_obj
.
type
=
ACPI_TYPE_INTEGER
;
in_obj
.
integer
.
value
=
2
;
rv
=
acpi_evaluate_integer
(
kled_get_handle
,
NULL
,
&
params
,
&
kblv
);
if
(
ACPI_FAILURE
(
rv
))
{
pr_warning
(
"Error reading kled level
\n
"
);
return
0
;
}
return
kblv
;
}
static
int
set_kled_lvl
(
int
kblv
)
{
if
(
kblv
>
0
)
kblv
=
(
1
<<
7
)
|
(
kblv
&
0x7F
);
else
kblv
=
0
;
if
(
write_acpi_int
(
kled_set_handle
,
NULL
,
kblv
,
NULL
))
{
pr_warning
(
"Keyboard LED display write failed
\n
"
);
return
-
EINVAL
;
}
return
0
;
}
static
void
kled_led_set
(
struct
led_classdev
*
led_cdev
,
enum
led_brightness
value
)
{
kled_led_wk
=
value
;
queue_work
(
led_workqueue
,
&
kled_led_work
);
}
static
void
kled_led_update
(
struct
work_struct
*
ignored
)
{
set_kled_lvl
(
kled_led_wk
);
}
static
enum
led_brightness
kled_led_get
(
struct
led_classdev
*
led_cdev
)
{
return
get_kled_lvl
();
}
static
int
get_lcd_state
(
void
)
{
return
read_status
(
LCD_ON
);
...
...
@@ -498,7 +588,7 @@ static ssize_t show_infos(struct device *dev,
{
int
len
=
0
;
unsigned
long
long
temp
;
char
buf
[
16
];
/
/enough for all info
char
buf
[
16
];
/
* enough for all info */
acpi_status
rv
=
AE_OK
;
/*
...
...
@@ -516,7 +606,17 @@ static ssize_t show_infos(struct device *dev,
*/
rv
=
acpi_evaluate_integer
(
hotk
->
handle
,
"SFUN"
,
NULL
,
&
temp
);
if
(
!
ACPI_FAILURE
(
rv
))
len
+=
sprintf
(
page
+
len
,
"SFUN value : 0x%04x
\n
"
,
len
+=
sprintf
(
page
+
len
,
"SFUN value : %#x
\n
"
,
(
uint
)
temp
);
/*
* The HWRS method return informations about the hardware.
* 0x80 bit is for WLAN, 0x100 for Bluetooth.
* The significance of others is yet to be found.
* If we don't find the method, we assume the device are present.
*/
rv
=
acpi_evaluate_integer
(
hotk
->
handle
,
"HRWS"
,
NULL
,
&
temp
);
if
(
!
ACPI_FAILURE
(
rv
))
len
+=
sprintf
(
page
+
len
,
"HRWS value : %#x
\n
"
,
(
uint
)
temp
);
/*
* Another value for userspace: the ASYM method returns 0x02 for
...
...
@@ -527,7 +627,7 @@ static ssize_t show_infos(struct device *dev,
*/
rv
=
acpi_evaluate_integer
(
hotk
->
handle
,
"ASYM"
,
NULL
,
&
temp
);
if
(
!
ACPI_FAILURE
(
rv
))
len
+=
sprintf
(
page
+
len
,
"ASYM value :
0x%04
x
\n
"
,
len
+=
sprintf
(
page
+
len
,
"ASYM value :
%#
x
\n
"
,
(
uint
)
temp
);
if
(
asus_info
)
{
snprintf
(
buf
,
16
,
"%d"
,
asus_info
->
length
);
...
...
@@ -648,8 +748,10 @@ static int read_display(void)
unsigned
long
long
value
=
0
;
acpi_status
rv
=
AE_OK
;
/* In most of the case, we know how to set the display, but sometime
we can't read it */
/*
* In most of the case, we know how to set the display, but sometime
* we can't read it
*/
if
(
display_get_handle
)
{
rv
=
acpi_evaluate_integer
(
display_get_handle
,
NULL
,
NULL
,
&
value
);
...
...
@@ -1037,6 +1139,9 @@ static int asus_hotk_get_info(void)
ASUS_HANDLE_INIT
(
ledd_set
);
ASUS_HANDLE_INIT
(
kled_set
);
ASUS_HANDLE_INIT
(
kled_get
);
/*
* The HWRS method return informations about the hardware.
* 0x80 bit is for WLAN, 0x100 for Bluetooth.
...
...
@@ -1063,8 +1168,10 @@ static int asus_hotk_get_info(void)
ASUS_HANDLE_INIT
(
display_set
);
ASUS_HANDLE_INIT
(
display_get
);
/* There is a lot of models with "ALSL", but a few get
a real light sens, so we need to check it. */
/*
* There is a lot of models with "ALSL", but a few get
* a real light sens, so we need to check it.
*/
if
(
!
ASUS_HANDLE_INIT
(
ls_switch
))
ASUS_HANDLE_INIT
(
ls_level
);
...
...
@@ -1168,6 +1275,10 @@ static int asus_hotk_add(struct acpi_device *device)
/* LCD Backlight is on by default */
write_status
(
NULL
,
1
,
LCD_ON
);
/* Keyboard Backlight is on by default */
if
(
kled_set_handle
)
set_kled_lvl
(
1
);
/* LED display is off by default */
hotk
->
ledd_status
=
0xFFF
;
...
...
@@ -1222,6 +1333,7 @@ static void asus_led_exit(void)
ASUS_LED_UNREGISTER
(
pled
);
ASUS_LED_UNREGISTER
(
rled
);
ASUS_LED_UNREGISTER
(
gled
);
ASUS_LED_UNREGISTER
(
kled
);
}
static
void
asus_input_exit
(
void
)
...
...
@@ -1301,13 +1413,20 @@ static int asus_led_init(struct device *dev)
if
(
rv
)
goto
out4
;
if
(
kled_set_handle
&&
kled_get_handle
)
rv
=
ASUS_LED_REGISTER
(
kled
,
dev
);
if
(
rv
)
goto
out5
;
led_workqueue
=
create_singlethread_workqueue
(
"led_workqueue"
);
if
(
!
led_workqueue
)
goto
out
5
;
goto
out
6
;
return
0
;
out
5
:
out
6
:
rv
=
-
ENOMEM
;
ASUS_LED_UNREGISTER
(
kled
);
out5:
ASUS_LED_UNREGISTER
(
gled
);
out4:
ASUS_LED_UNREGISTER
(
pled
);
...
...
drivers/platform/x86/eeepc-laptop.c
View file @
b4549a24
...
...
@@ -142,18 +142,28 @@ struct eeepc_hotk {
struct
rfkill
*
wlan_rfkill
;
struct
rfkill
*
bluetooth_rfkill
;
struct
rfkill
*
wwan3g_rfkill
;
struct
rfkill
*
wimax_rfkill
;
struct
hotplug_slot
*
hotplug_slot
;
struct
work_struct
hotplug_wor
k
;
struct
mutex
hotplug_loc
k
;
};
/* The actual device the driver binds to */
static
struct
eeepc_hotk
*
ehotk
;
/* Platform device/driver */
static
int
eeepc_hotk_thaw
(
struct
device
*
device
);
static
int
eeepc_hotk_restore
(
struct
device
*
device
);
static
struct
dev_pm_ops
eeepc_pm_ops
=
{
.
thaw
=
eeepc_hotk_thaw
,
.
restore
=
eeepc_hotk_restore
,
};
static
struct
platform_driver
platform_driver
=
{
.
driver
=
{
.
name
=
EEEPC_HOTK_FILE
,
.
owner
=
THIS_MODULE
,
.
pm
=
&
eeepc_pm_ops
,
}
};
...
...
@@ -192,7 +202,6 @@ static struct key_entry eeepc_keymap[] = {
*/
static
int
eeepc_hotk_add
(
struct
acpi_device
*
device
);
static
int
eeepc_hotk_remove
(
struct
acpi_device
*
device
,
int
type
);
static
int
eeepc_hotk_resume
(
struct
acpi_device
*
device
);
static
void
eeepc_hotk_notify
(
struct
acpi_device
*
device
,
u32
event
);
static
const
struct
acpi_device_id
eeepc_device_ids
[]
=
{
...
...
@@ -209,7 +218,6 @@ static struct acpi_driver eeepc_hotk_driver = {
.
ops
=
{
.
add
=
eeepc_hotk_add
,
.
remove
=
eeepc_hotk_remove
,
.
resume
=
eeepc_hotk_resume
,
.
notify
=
eeepc_hotk_notify
,
},
};
...
...
@@ -579,7 +587,6 @@ static void cmsg_quirks(void)
static
int
eeepc_hotk_check
(
void
)
{
const
struct
key_entry
*
key
;
struct
acpi_buffer
buffer
=
{
ACPI_ALLOCATE_BUFFER
,
NULL
};
int
result
;
...
...
@@ -604,31 +611,6 @@ static int eeepc_hotk_check(void)
pr_info
(
"Get control methods supported: 0x%x
\n
"
,
ehotk
->
cm_supported
);
}
ehotk
->
inputdev
=
input_allocate_device
();
if
(
!
ehotk
->
inputdev
)
{
pr_info
(
"Unable to allocate input device
\n
"
);
return
0
;
}
ehotk
->
inputdev
->
name
=
"Asus EeePC extra buttons"
;
ehotk
->
inputdev
->
phys
=
EEEPC_HOTK_FILE
"/input0"
;
ehotk
->
inputdev
->
id
.
bustype
=
BUS_HOST
;
ehotk
->
inputdev
->
getkeycode
=
eeepc_getkeycode
;
ehotk
->
inputdev
->
setkeycode
=
eeepc_setkeycode
;
for
(
key
=
eeepc_keymap
;
key
->
type
!=
KE_END
;
key
++
)
{
switch
(
key
->
type
)
{
case
KE_KEY
:
set_bit
(
EV_KEY
,
ehotk
->
inputdev
->
evbit
);
set_bit
(
key
->
keycode
,
ehotk
->
inputdev
->
keybit
);
break
;
}
}
result
=
input_register_device
(
ehotk
->
inputdev
);
if
(
result
)
{
pr_info
(
"Unable to register input device
\n
"
);
input_free_device
(
ehotk
->
inputdev
);
return
0
;
}
}
else
{
pr_err
(
"Hotkey device not present, aborting
\n
"
);
return
-
EINVAL
;
...
...
@@ -661,40 +643,48 @@ static int eeepc_get_adapter_status(struct hotplug_slot *hotplug_slot,
return
0
;
}
static
void
eeepc_
hotplug_work
(
struct
work_struct
*
work
)
static
void
eeepc_
rfkill_hotplug
(
void
)
{
struct
pci_dev
*
dev
;
struct
pci_bus
*
bus
=
pci_find_bus
(
0
,
1
)
;
bool
blocked
;
struct
pci_bus
*
bus
;
bool
blocked
=
eeepc_wlan_rfkill_blocked
()
;
if
(
!
bus
)
{
pr_warning
(
"Unable to find PCI bus 1?
\n
"
);
return
;
}
if
(
ehotk
->
wlan_rfkill
)
rfkill_set_sw_state
(
ehotk
->
wlan_rfkill
,
blocked
);
blocked
=
eeepc_wlan_rfkill_blocked
();
if
(
!
blocked
)
{
dev
=
pci_get_slot
(
bus
,
0
);
if
(
dev
)
{
/* Device already present */
pci_dev_put
(
dev
);
return
;
}
dev
=
pci_scan_single_device
(
bus
,
0
);
if
(
dev
)
{
pci_bus_assign_resources
(
bus
);
if
(
pci_bus_add_device
(
dev
))
pr_err
(
"Unable to hotplug wifi
\n
"
);
mutex_lock
(
&
ehotk
->
hotplug_lock
);
if
(
ehotk
->
hotplug_slot
)
{
bus
=
pci_find_bus
(
0
,
1
);
if
(
!
bus
)
{
pr_warning
(
"Unable to find PCI bus 1?
\n
"
);
goto
out_unlock
;
}
}
else
{
dev
=
pci_get_slot
(
bus
,
0
);
if
(
dev
)
{
pci_remove_bus_device
(
dev
);
pci_dev_put
(
dev
);
if
(
!
blocked
)
{
dev
=
pci_get_slot
(
bus
,
0
);
if
(
dev
)
{
/* Device already present */
pci_dev_put
(
dev
);
goto
out_unlock
;
}
dev
=
pci_scan_single_device
(
bus
,
0
);
if
(
dev
)
{
pci_bus_assign_resources
(
bus
);
if
(
pci_bus_add_device
(
dev
))
pr_err
(
"Unable to hotplug wifi
\n
"
);
}
}
else
{
dev
=
pci_get_slot
(
bus
,
0
);
if
(
dev
)
{
pci_remove_bus_device
(
dev
);
pci_dev_put
(
dev
);
}
}
}
rfkill_set_sw_state
(
ehotk
->
wlan_rfkill
,
blocked
);
out_unlock:
mutex_unlock
(
&
ehotk
->
hotplug_lock
);
}
static
void
eeepc_rfkill_notify
(
acpi_handle
handle
,
u32
event
,
void
*
data
)
...
...
@@ -702,7 +692,7 @@ static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data)
if
(
event
!=
ACPI_NOTIFY_BUS_CHECK
)
return
;
schedule_work
(
&
ehotk
->
hotplug_work
);
eeepc_rfkill_hotplug
(
);
}
static
void
eeepc_hotk_notify
(
struct
acpi_device
*
device
,
u32
event
)
...
...
@@ -839,66 +829,38 @@ static int eeepc_setup_pci_hotplug(void)
return
ret
;
}
static
int
eeepc_hotk_add
(
struct
acpi_device
*
device
)
{
int
result
;
if
(
!
device
)
return
-
EINVAL
;
pr_notice
(
EEEPC_HOTK_NAME
"
\n
"
);
ehotk
=
kzalloc
(
sizeof
(
struct
eeepc_hotk
),
GFP_KERNEL
);
if
(
!
ehotk
)
return
-
ENOMEM
;
ehotk
->
init_flag
=
DISABLE_ASL_WLAN
|
DISABLE_ASL_DISPLAYSWITCH
;
ehotk
->
handle
=
device
->
handle
;
strcpy
(
acpi_device_name
(
device
),
EEEPC_HOTK_DEVICE_NAME
);
strcpy
(
acpi_device_class
(
device
),
EEEPC_HOTK_CLASS
);
device
->
driver_data
=
ehotk
;
ehotk
->
device
=
device
;
result
=
eeepc_hotk_check
();
if
(
result
)
goto
ehotk_fail
;
return
0
;
ehotk_fail:
kfree
(
ehotk
);
ehotk
=
NULL
;
return
result
;
}
static
int
eeepc_hotk_remove
(
struct
acpi_device
*
device
,
int
type
)
{
if
(
!
device
||
!
acpi_driver_data
(
device
))
return
-
EINVAL
;
kfree
(
ehotk
);
return
0
;
}
static
int
eeepc_hotk_resume
(
struct
acpi_device
*
device
)
static
int
eeepc_hotk_thaw
(
struct
device
*
device
)
{
if
(
ehotk
->
wlan_rfkill
)
{
bool
wlan
;
/* Workaround - it seems that _PTS disables the wireless
without notification or changing the value read by WLAN.
Normally this is fine because the correct value is restored
from the non-volatile storage on resume, but we need to do
it ourself if case suspend is aborted, or we lose wireless.
/*
* Work around bios bug - acpi _PTS turns off the wireless led
* during suspend. Normally it restores it on resume, but
* we should kick it ourselves in case hibernation is aborted.
*/
wlan
=
get_acpi
(
CM_ASL_WLAN
);
set_acpi
(
CM_ASL_WLAN
,
wlan
);
}
rfkill_set_sw_state
(
ehotk
->
wlan_rfkill
,
wlan
!=
1
);
return
0
;
}
schedule_work
(
&
ehotk
->
hotplug_work
);
}
static
int
eeepc_hotk_restore
(
struct
device
*
device
)
{
/* Refresh both wlan rfkill state and pci hotplug */
if
(
ehotk
->
wlan_rfkill
)
eeepc_rfkill_hotplug
();
if
(
ehotk
->
bluetooth_rfkill
)
rfkill_set_sw_state
(
ehotk
->
bluetooth_rfkill
,
get_acpi
(
CM_ASL_BLUETOOTH
)
!=
1
);
if
(
ehotk
->
wwan3g_rfkill
)
rfkill_set_sw_state
(
ehotk
->
wwan3g_rfkill
,
get_acpi
(
CM_ASL_3G
)
!=
1
);
if
(
ehotk
->
wimax_rfkill
)
rfkill_set_sw_state
(
ehotk
->
wimax_rfkill
,
get_acpi
(
CM_ASL_WIMAX
)
!=
1
);
return
0
;
}
...
...
@@ -1019,16 +981,37 @@ static void eeepc_backlight_exit(void)
static
void
eeepc_rfkill_exit
(
void
)
{
eeepc_unregister_rfkill_notifier
(
"
\\
_SB.PCI0.P0P5"
);
eeepc_unregister_rfkill_notifier
(
"
\\
_SB.PCI0.P0P6"
);
eeepc_unregister_rfkill_notifier
(
"
\\
_SB.PCI0.P0P7"
);
if
(
ehotk
->
wlan_rfkill
)
if
(
ehotk
->
wlan_rfkill
)
{
rfkill_unregister
(
ehotk
->
wlan_rfkill
);
if
(
ehotk
->
bluetooth_rfkill
)
rfkill_unregister
(
ehotk
->
bluetooth_rfkill
);
if
(
ehotk
->
wwan3g_rfkill
)
rfkill_unregister
(
ehotk
->
wwan3g_rfkill
);
rfkill_destroy
(
ehotk
->
wlan_rfkill
);
ehotk
->
wlan_rfkill
=
NULL
;
}
/*
* Refresh pci hotplug in case the rfkill state was changed after
* eeepc_unregister_rfkill_notifier()
*/
eeepc_rfkill_hotplug
();
if
(
ehotk
->
hotplug_slot
)
pci_hp_deregister
(
ehotk
->
hotplug_slot
);
if
(
ehotk
->
bluetooth_rfkill
)
{
rfkill_unregister
(
ehotk
->
bluetooth_rfkill
);
rfkill_destroy
(
ehotk
->
bluetooth_rfkill
);
ehotk
->
bluetooth_rfkill
=
NULL
;
}
if
(
ehotk
->
wwan3g_rfkill
)
{
rfkill_unregister
(
ehotk
->
wwan3g_rfkill
);
rfkill_destroy
(
ehotk
->
wwan3g_rfkill
);
ehotk
->
wwan3g_rfkill
=
NULL
;
}
if
(
ehotk
->
wimax_rfkill
)
{
rfkill_unregister
(
ehotk
->
wimax_rfkill
);
rfkill_destroy
(
ehotk
->
wimax_rfkill
);
ehotk
->
wimax_rfkill
=
NULL
;
}
}
static
void
eeepc_input_exit
(
void
)
...
...
@@ -1050,19 +1033,6 @@ static void eeepc_hwmon_exit(void)
eeepc_hwmon_device
=
NULL
;
}
static
void
__exit
eeepc_laptop_exit
(
void
)
{
eeepc_backlight_exit
();
eeepc_rfkill_exit
();
eeepc_input_exit
();
eeepc_hwmon_exit
();
acpi_bus_unregister_driver
(
&
eeepc_hotk_driver
);
sysfs_remove_group
(
&
platform_device
->
dev
.
kobj
,
&
platform_attribute_group
);
platform_device_unregister
(
platform_device
);
platform_driver_unregister
(
&
platform_driver
);
}
static
int
eeepc_new_rfkill
(
struct
rfkill
**
rfkill
,
const
char
*
name
,
struct
device
*
dev
,
enum
rfkill_type
type
,
int
cm
)
...
...
@@ -1094,10 +1064,7 @@ static int eeepc_rfkill_init(struct device *dev)
{
int
result
=
0
;
INIT_WORK
(
&
ehotk
->
hotplug_work
,
eeepc_hotplug_work
);
eeepc_register_rfkill_notifier
(
"
\\
_SB.PCI0.P0P6"
);
eeepc_register_rfkill_notifier
(
"
\\
_SB.PCI0.P0P7"
);
mutex_init
(
&
ehotk
->
hotplug_lock
);
result
=
eeepc_new_rfkill
(
&
ehotk
->
wlan_rfkill
,
"eeepc-wlan"
,
dev
,
...
...
@@ -1120,6 +1087,13 @@ static int eeepc_rfkill_init(struct device *dev)
if
(
result
&&
result
!=
-
ENODEV
)
goto
exit
;
result
=
eeepc_new_rfkill
(
&
ehotk
->
wimax_rfkill
,
"eeepc-wimax"
,
dev
,
RFKILL_TYPE_WIMAX
,
CM_ASL_WIMAX
);
if
(
result
&&
result
!=
-
ENODEV
)
goto
exit
;
result
=
eeepc_setup_pci_hotplug
();
/*
* If we get -EBUSY then something else is handling the PCI hotplug -
...
...
@@ -1128,6 +1102,15 @@ static int eeepc_rfkill_init(struct device *dev)
if
(
result
==
-
EBUSY
)
result
=
0
;
eeepc_register_rfkill_notifier
(
"
\\
_SB.PCI0.P0P5"
);
eeepc_register_rfkill_notifier
(
"
\\
_SB.PCI0.P0P6"
);
eeepc_register_rfkill_notifier
(
"
\\
_SB.PCI0.P0P7"
);
/*
* Refresh pci hotplug in case the rfkill state was changed during
* setup.
*/
eeepc_rfkill_hotplug
();
exit:
if
(
result
&&
result
!=
-
ENODEV
)
eeepc_rfkill_exit
();
...
...
@@ -1172,21 +1155,61 @@ static int eeepc_hwmon_init(struct device *dev)
return
result
;
}
static
int
__init
eeepc_laptop_init
(
void
)
static
int
eeepc_input_init
(
struct
device
*
dev
)
{
struct
device
*
dev
;
const
struct
key_entry
*
key
;
int
result
;
if
(
acpi_disabled
)
return
-
ENODEV
;
result
=
acpi_bus_register_driver
(
&
eeepc_hotk_driver
);
if
(
result
<
0
)
ehotk
->
inputdev
=
input_allocate_device
();
if
(
!
ehotk
->
inputdev
)
{
pr_info
(
"Unable to allocate input device
\n
"
);
return
-
ENOMEM
;
}
ehotk
->
inputdev
->
name
=
"Asus EeePC extra buttons"
;
ehotk
->
inputdev
->
dev
.
parent
=
dev
;
ehotk
->
inputdev
->
phys
=
EEEPC_HOTK_FILE
"/input0"
;
ehotk
->
inputdev
->
id
.
bustype
=
BUS_HOST
;
ehotk
->
inputdev
->
getkeycode
=
eeepc_getkeycode
;
ehotk
->
inputdev
->
setkeycode
=
eeepc_setkeycode
;
for
(
key
=
eeepc_keymap
;
key
->
type
!=
KE_END
;
key
++
)
{
switch
(
key
->
type
)
{
case
KE_KEY
:
set_bit
(
EV_KEY
,
ehotk
->
inputdev
->
evbit
);
set_bit
(
key
->
keycode
,
ehotk
->
inputdev
->
keybit
);
break
;
}
}
result
=
input_register_device
(
ehotk
->
inputdev
);
if
(
result
)
{
pr_info
(
"Unable to register input device
\n
"
);
input_free_device
(
ehotk
->
inputdev
);
return
result
;
if
(
!
ehotk
)
{
acpi_bus_unregister_driver
(
&
eeepc_hotk_driver
);
return
-
ENODEV
;
}
return
0
;
}
static
int
eeepc_hotk_add
(
struct
acpi_device
*
device
)
{
struct
device
*
dev
;
int
result
;
if
(
!
device
)
return
-
EINVAL
;
pr_notice
(
EEEPC_HOTK_NAME
"
\n
"
);
ehotk
=
kzalloc
(
sizeof
(
struct
eeepc_hotk
),
GFP_KERNEL
);
if
(
!
ehotk
)
return
-
ENOMEM
;
ehotk
->
init_flag
=
DISABLE_ASL_WLAN
|
DISABLE_ASL_DISPLAYSWITCH
;
ehotk
->
handle
=
device
->
handle
;
strcpy
(
acpi_device_name
(
device
),
EEEPC_HOTK_DEVICE_NAME
);
strcpy
(
acpi_device_class
(
device
),
EEEPC_HOTK_CLASS
);
device
->
driver_data
=
ehotk
;
ehotk
->
device
=
device
;
result
=
eeepc_hotk_check
();
if
(
result
)
goto
fail_platform_driver
;
eeepc_enable_camera
();
/* Register platform stuff */
...
...
@@ -1216,6 +1239,10 @@ static int __init eeepc_laptop_init(void)
pr_info
(
"Backlight controlled by ACPI video "
"driver
\n
"
);
result
=
eeepc_input_init
(
dev
);
if
(
result
)
goto
fail_input
;
result
=
eeepc_hwmon_init
(
dev
);
if
(
result
)
goto
fail_hwmon
;
...
...
@@ -1225,9 +1252,12 @@ static int __init eeepc_laptop_init(void)
goto
fail_rfkill
;
return
0
;
fail_rfkill:
eeepc_hwmon_exit
();
fail_hwmon:
eeepc_input_exit
();
fail_input:
eeepc_backlight_exit
();
fail_backlight:
sysfs_remove_group
(
&
platform_device
->
dev
.
kobj
,
...
...
@@ -1239,9 +1269,49 @@ static int __init eeepc_laptop_init(void)
fail_platform_device1:
platform_driver_unregister
(
&
platform_driver
);
fail_platform_driver:
eeepc_input_exit
();
kfree
(
ehotk
);
return
result
;
}
static
int
eeepc_hotk_remove
(
struct
acpi_device
*
device
,
int
type
)
{
if
(
!
device
||
!
acpi_driver_data
(
device
))
return
-
EINVAL
;
eeepc_backlight_exit
();
eeepc_rfkill_exit
();
eeepc_input_exit
();
eeepc_hwmon_exit
();
sysfs_remove_group
(
&
platform_device
->
dev
.
kobj
,
&
platform_attribute_group
);
platform_device_unregister
(
platform_device
);
platform_driver_unregister
(
&
platform_driver
);
kfree
(
ehotk
);
return
0
;
}
static
int
__init
eeepc_laptop_init
(
void
)
{
int
result
;
if
(
acpi_disabled
)
return
-
ENODEV
;
result
=
acpi_bus_register_driver
(
&
eeepc_hotk_driver
);
if
(
result
<
0
)
return
result
;
if
(
!
ehotk
)
{
acpi_bus_unregister_driver
(
&
eeepc_hotk_driver
);
return
-
ENODEV
;
}
return
0
;
}
static
void
__exit
eeepc_laptop_exit
(
void
)
{
acpi_bus_unregister_driver
(
&
eeepc_hotk_driver
);
}
module_init
(
eeepc_laptop_init
);
module_exit
(
eeepc_laptop_exit
);
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