2 * Acer Laptop ACPI Extras
4 * Copyright (C) 2005-2007 E.M. Smith
5 * Copyright (C) 2007 Carlos Corbacho <cathectic@gmail.com>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 * The devolpment page for this driver is located at
23 * http://code.google.com/p/aceracpi
27 * John Belmonte - the Toshiba ACPI driver originally adapted for this module.
28 * Julien Lerouge & Karol Kozimor - ASUS Acpi driver authors.
29 * Olaf Tauber - developer of acerhk, the inspiration to solve the 64-bit
30 * driver problem for my Aspire 5024.
31 * Mathieu Segaud - solved the ACPI problem that needed a double-modprobe
32 * in version 0.2 and below.
33 * Jim Ramsay - Figured out and added support for WMID interface
36 #define ACER_ACPI_VERSION "0.11.0"
39 * Comment the following line out to remove /proc support
44 #define PROC_ACER "acer"
45 #include <linux/proc_fs.h>
48 #include <linux/kernel.h>
49 #include <linux/module.h>
50 #include <linux/init.h>
51 #include <linux/types.h>
52 #include <linux/delay.h>
53 #include <linux/version.h>
55 #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,17)
56 #include <asm/uaccess.h>
58 #include <linux/uaccess.h>
62 #include <linux/dmi.h>
63 #include <linux/backlight.h>
64 #include <linux/leds.h>
65 #include <linux/platform_device.h>
67 #include <acpi/acpi_drivers.h>
71 /* Workaround needed for older kernels */
76 MODULE_AUTHOR("Mark Smith, Carlos Corbacho");
77 MODULE_DESCRIPTION("Acer Laptop ACPI Extras Driver");
78 MODULE_LICENSE("GPL");
80 MODULE_ALIAS("dmi:*:*Acer*:*:");
82 #define ACER_LOGPREFIX "acer_acpi: "
83 #define ACER_ERR KERN_ERR ACER_LOGPREFIX
84 #define ACER_NOTICE KERN_NOTICE ACER_LOGPREFIX
85 #define ACER_INFO KERN_INFO ACER_LOGPREFIX
87 #define DEBUG(level, message...) { \
89 printk(KERN_DEBUG ACER_LOGPREFIX message);\
93 * The maximum temperature one can set for fan control override.
94 * Doesn't propably make much sense if over 80 degrees celsius though...
96 #define ACER_MAX_TEMPERATURE_OVERRIDE 150
99 * The following defines quirks to get some specific functions to work
100 * which are known to not be supported over ACPI (such as the mail LED
101 * on WMID based Acer's)
110 * Keyboard controller ports
112 #define ACER_KBD_STATUS_REG 0x64 /* Status register (R) */
113 #define ACER_KBD_CNTL_REG 0x64 /* Controller command register (W) */
114 #define ACER_KBD_DATA_REG 0x60 /* Keyboard data register (R/W) */
118 * Meaning is unknown - this number is required for writing to ACPI for AMW0
119 * (it's also used in acerhk when directly accessing the EC)
121 #define ACER_AMW0_WRITE 0x9610
124 * Bit masks for the old AMW0 interface
126 #define ACER_AMW0_WIRELESS_MASK 0x35
127 #define ACER_AMW0_BLUETOOTH_MASK 0x34
128 #define ACER_AMW0_MAILLED_MASK 0x31
131 * Method IDs for new WMID interface
133 #define ACER_WMID_GET_WIRELESS_METHODID 1
134 #define ACER_WMID_GET_BLUETOOTH_METHODID 2
135 #define ACER_WMID_GET_BRIGHTNESS_METHODID 3
136 #define ACER_WMID_SET_WIRELESS_METHODID 4
137 #define ACER_WMID_SET_BLUETOOTH_METHODID 5
138 #define ACER_WMID_SET_BRIGHTNESS_METHODID 6
139 #define ACER_WMID_GET_THREEG_METHODID 10
140 #define ACER_WMID_SET_THREEG_METHODID 11
143 * Acer ACPI method GUIDs
145 #define AMW0_GUID1 "67C3371D-95A3-4C37-BB61-DD47B491DAAB"
146 #define WMID_GUID1 "6AF4F258-B401-42fd-BE91-3D4AC2D7C0D3"
147 #define WMID_GUID2 "95764E09-FB56-4e83-B31A-37761F60994A"
150 * Interface capability flags
152 #define ACER_CAP_MAILLED (1<<0)
153 #define ACER_CAP_WIRELESS (1<<1)
154 #define ACER_CAP_BLUETOOTH (1<<2)
155 #define ACER_CAP_BRIGHTNESS (1<<3)
156 #define ACER_CAP_THREEG (1<<4)
157 #define ACER_CAP_TOUCHPAD_READ (1<<5)
158 #define ACER_CAP_TEMPERATURE_OVERRIDE (1<<6)
159 #define ACER_CAP_ANY (0xFFFFFFFF)
162 * Interface type flags
164 enum interface_flags
{
171 * Presumed start states -
172 * On some AMW0 laptops, we do not yet know how to get the device status from
173 * the EC, so we must store this ourselves.
175 * Plus, we can't tell which features are enabled or disabled on a specific
176 * model - e.g. The 5020 series can _support_ bluetooth; but the 5021 has no
177 * bluetooth, whilst the 5024 does. However, the BIOS identifies both laptops
178 * as 5020, and you can add bluetooth later.
180 * Basically the code works like this:
181 * - On init, any values specified on the commandline are set.
182 * - For interfaces where the current values cannot be detected and which
183 * have not been set on the commandline, we set them to some sane default
186 * See AMW0_init and acer_commandline_init
189 #define ACER_DEFAULT_WIRELESS 0
190 #define ACER_DEFAULT_BLUETOOTH 0
191 #define ACER_DEFAULT_MAILLED 0
192 #define ACER_DEFAULT_THREEG 0
194 static int max_brightness
= 0xF;
196 static int wireless
= -1;
197 static int bluetooth
= -1;
198 static int mailled
= -1;
199 static int brightness
= -1;
200 static int threeg
= -1;
201 static int fan_temperature_override
= -1;
202 static int debug
= 0;
203 static int force_series
;
205 module_param(mailled
, int, 0444);
206 module_param(wireless
, int, 0444);
207 module_param(bluetooth
, int, 0444);
208 module_param(brightness
, int, 0444);
209 module_param(threeg
, int, 0444);
210 module_param(force_series
, int, 0444);
211 module_param(fan_temperature_override
, int, 0444);
212 module_param(debug
, int, 0664);
213 MODULE_PARM_DESC(wireless
, "Set initial state of Wireless hardware");
214 MODULE_PARM_DESC(bluetooth
, "Set initial state of Bluetooth hardware");
215 MODULE_PARM_DESC(mailled
, "Set initial state of Mail LED");
216 MODULE_PARM_DESC(brightness
, "Set initial LCD backlight brightness");
217 MODULE_PARM_DESC(threeg
, "Set initial state of 3G hardware");
218 MODULE_PARM_DESC(fan_temperature_override
, "Set initial state of the 'FAN temperature-override'");
219 MODULE_PARM_DESC(debug
, "Debugging verbosity level (0=least 2=most)");
220 MODULE_PARM_DESC(force_series
, "Force a different laptop series for extra features (5020, 5720 or 2490)");
225 char *(*read_func
) (char *, u32
);
226 unsigned long (*write_func
) (const char *, unsigned long, u32
);
227 unsigned int capability
;
230 static struct proc_dir_entry
*acer_proc_dir
;
234 * Wait for the keyboard controller to become ready
236 static int wait_kbd_write(void)
239 while ((inb(ACER_KBD_STATUS_REG
) & 0x02) && (i
< 10000)) {
243 return -(i
== 10000);
246 static void send_kbd_cmd(u8 cmd
, u8 val
)
249 if (!wait_kbd_write())
250 outb(cmd
, ACER_KBD_CNTL_REG
);
251 if (!wait_kbd_write())
252 outb(val
, ACER_KBD_DATA_REG
);
253 preempt_enable_no_resched();
256 static void set_keyboard_quirk(void)
258 send_kbd_cmd(0x59, 0x90);
269 /* Each low-level interface must define at least some of the following */
271 u32 type
; /* WMI device type */
272 u32 capability
; /* The capabilities this interface provides */
273 struct acer_data data
; /* Private data for interface */
276 /* The static interface pointer, points to the currently detected interface */
277 static struct Interface
*interface
;
280 * Embedded Controller quirks
281 * Some laptops require us to directly access the EC to either enable or query
282 * features that are not available through ACPI.
290 u8 temperature_override
;
295 static struct quirk_entry
*quirks
;
297 static void set_quirks(void)
299 if (quirks
->mailled
!= 0) {
300 interface
->capability
|= ACER_CAP_MAILLED
;
301 DEBUG(1, "Using EC direct-access quirk for mail LED\n");
304 if (quirks
->touchpad
!= 0) {
305 interface
->capability
|= ACER_CAP_TOUCHPAD_READ
;
306 DEBUG(1, "Using EC direct-access quirk for reading touchpad status\n");
309 if (quirks
->temperature_override
!= 0) {
310 interface
->capability
|= ACER_CAP_TEMPERATURE_OVERRIDE
;
311 DEBUG(1, "Using EC direct-access quirk for temperature override setting (fan)\n");
314 if (quirks
->brightness
!= 0) {
315 interface
->capability
|= ACER_CAP_BRIGHTNESS
;
316 DEBUG(1, "Using EC direct-access quirk for backlight brightness\n");
319 if (quirks
->mmkeys
!= 0) {
320 set_keyboard_quirk();
321 printk(ACER_INFO
"Setting keyboard quirk to enable multimedia keys\n");
324 if (quirks
->bluetooth
!= 0) {
325 interface
->capability
|= ACER_CAP_BLUETOOTH
;
326 DEBUG(1, "Using EC direct-access quirk for bluetooth\n");
329 if (quirks
->wireless
!= 0) {
330 interface
->capability
|= ACER_CAP_WIRELESS
;
331 DEBUG(1, "Using EC direct-access quirk for wireless\n");
335 static int dmi_matched(struct dmi_system_id
*dmi
)
337 quirks
= dmi
->driver_data
;
341 static struct quirk_entry quirk_unknown
= {
344 /* Same Mail LED quirk as TM2490, but does not require keyboard quirk */
345 static struct quirk_entry quirk_acer_aspire_5100
= {
349 static struct quirk_entry quirk_acer_travelmate_2490
= {
352 .temperature_override
= 1,
356 static struct quirk_entry quirk_acer_travelmate_5720
= {
360 static struct dmi_system_id acer_quirks
[] = {
362 .callback
= dmi_matched
,
363 .ident
= "Acer Aspire 3100",
365 DMI_MATCH(DMI_SYS_VENDOR
, "Acer"),
366 DMI_MATCH(DMI_PRODUCT_NAME
, "Aspire 3100"),
368 .driver_data
= &quirk_acer_aspire_5100
,
371 .callback
= dmi_matched
,
372 .ident
= "Acer Aspire 5100",
374 DMI_MATCH(DMI_SYS_VENDOR
, "Acer"),
375 DMI_MATCH(DMI_PRODUCT_NAME
, "Aspire 5100"),
377 .driver_data
= &quirk_acer_aspire_5100
,
380 .callback
= dmi_matched
,
381 .ident
= "Acer Aspire 5630",
383 DMI_MATCH(DMI_SYS_VENDOR
, "Acer"),
384 DMI_MATCH(DMI_PRODUCT_NAME
, "Aspire 5630"),
386 .driver_data
= &quirk_acer_travelmate_2490
,
389 .callback
= dmi_matched
,
390 .ident
= "Acer Aspire 5650",
392 DMI_MATCH(DMI_SYS_VENDOR
, "Acer"),
393 DMI_MATCH(DMI_PRODUCT_NAME
, "Aspire 5650"),
395 .driver_data
= &quirk_acer_travelmate_2490
,
398 .callback
= dmi_matched
,
399 .ident
= "Acer Aspire 5680",
401 DMI_MATCH(DMI_SYS_VENDOR
, "Acer"),
402 DMI_MATCH(DMI_PRODUCT_NAME
, "Aspire 5680"),
404 .driver_data
= &quirk_acer_travelmate_2490
,
407 .callback
= dmi_matched
,
408 .ident
= "Acer Extensa 5220",
410 DMI_MATCH(DMI_SYS_VENDOR
, "Acer"),
411 DMI_MATCH(DMI_PRODUCT_NAME
, "Extensa 5220"),
413 .driver_data
= &quirk_acer_travelmate_5720
,
416 .callback
= dmi_matched
,
417 .ident
= "Acer TravelMate 2490",
419 DMI_MATCH(DMI_SYS_VENDOR
, "Acer"),
420 DMI_MATCH(DMI_PRODUCT_NAME
, "TravelMate 2490"),
422 .driver_data
= &quirk_acer_travelmate_2490
,
425 .callback
= dmi_matched
,
426 .ident
= "Acer TravelMate 5720",
428 DMI_MATCH(DMI_SYS_VENDOR
, "Acer"),
429 DMI_MATCH(DMI_PRODUCT_NAME
, "TravelMate 5720"),
431 .driver_data
= &quirk_acer_travelmate_5720
,
436 /* Find which quirks are needed for a particular vendor/ model pair */
437 static void find_quirks(void)
439 DEBUG (1, "Looking for quirks\n");
441 dmi_check_system(acer_quirks
);
442 } else if (force_series
== 2490) {
443 DEBUG(0, "Forcing Acer TravelMate 2490\n");
444 quirks
= &quirk_acer_travelmate_2490
;
447 if (quirks
== NULL
) {
448 DEBUG(1, "No quirks known for this laptop\n");
449 quirks
= &quirk_unknown
;
455 * General interface convenience methods
458 static bool has_cap(u32 cap
)
460 if ((interface
->capability
& cap
) != 0) {
467 * Old interface (now known as the AMW0 interface)
476 static acpi_status
WMAB_execute(struct WMAB_args
*regbuf
, struct acpi_buffer
*result
)
478 struct acpi_buffer input
;
480 input
.length
= sizeof(struct WMAB_args
);
481 input
.pointer
= (u8
*)regbuf
;
483 status
= wmi_acer_evaluate_method(AMW0_GUID1
, 1, 1, &input
, result
);
484 DEBUG(2, " Args: 0x%08x 0x%08x 0x%08x 0x%08x\n", regbuf
->eax
, regbuf
->ebx
, regbuf
->ecx
, regbuf
->edx
);
489 static acpi_status
AMW0_get_u32(u32
*value
, u32 cap
, struct Interface
*iface
)
493 DEBUG(2, " AMW0_get_u32: cap=%d\n", cap
);
495 case ACER_CAP_MAILLED
:
496 switch (quirks
->mailled
) {
498 ec_read(0x0A, &result
);
499 *value
= (result
>> 7) & 0x01;
503 case ACER_CAP_WIRELESS
:
504 switch (quirks
->wireless
) {
506 ec_read(0x0A, &result
);
507 *value
= (result
>> 2) & 0x01;
511 case ACER_CAP_BLUETOOTH
:
512 switch (quirks
->bluetooth
) {
514 ec_read(0x0A, &result
);
515 *value
= (result
>> 4) & 0x01;
519 case ACER_CAP_BRIGHTNESS
:
520 switch (quirks
->brightness
) {
522 ec_read(0x83, &result
);
528 return AE_BAD_ADDRESS
;
533 static acpi_status
AMW0_set_u32(u32 value
, u32 cap
, struct Interface
*iface
)
535 struct WMAB_args args
;
537 args
.eax
= ACER_AMW0_WRITE
;
538 args
.ebx
= value
? (1<<8) : 0;
539 args
.ecx
= args
.edx
= 0;
542 case ACER_CAP_MAILLED
:
544 return AE_BAD_PARAMETER
;
545 args
.ebx
|= ACER_AMW0_MAILLED_MASK
;
547 case ACER_CAP_WIRELESS
:
549 return AE_BAD_PARAMETER
;
550 args
.ebx
|= ACER_AMW0_WIRELESS_MASK
;
552 case ACER_CAP_BLUETOOTH
:
554 return AE_BAD_PARAMETER
;
555 args
.ebx
|= ACER_AMW0_BLUETOOTH_MASK
;
557 case ACER_CAP_BRIGHTNESS
:
558 if (value
> max_brightness
)
559 return AE_BAD_PARAMETER
;
560 switch (quirks
->brightness
) {
562 return ec_write(0x83, value
);
564 return AE_BAD_ADDRESS
;
568 return AE_BAD_ADDRESS
;
571 /* Actually do the set */
572 return WMAB_execute(&args
, NULL
);
575 static struct Interface AMW0_interface
= {
584 static struct Interface AMW0_V2_interface
= {
585 .type
= ACER_AMW0_V2
,
587 ACER_CAP_BRIGHTNESS
|
593 * New interface (The WMID interface)
596 WMI_execute_u32(u32 method_id
, u32 in
, u32
*out
)
598 struct acpi_buffer input
= { (acpi_size
) sizeof(u32
), (void *)(&in
) };
599 struct acpi_buffer result
= { ACPI_ALLOCATE_BUFFER
, NULL
};
600 union acpi_object
*obj
;
604 DEBUG(2, " WMI_execute_u32:\n");
605 status
= wmi_acer_evaluate_method(WMID_GUID1
, 1, method_id
, &input
, &result
);
606 DEBUG(2, " In: 0x%08x\n", in
);
608 if (ACPI_FAILURE(status
))
611 obj
= (union acpi_object
*) result
.pointer
;
612 if (obj
&& obj
->type
== ACPI_TYPE_BUFFER
&& obj
->buffer
.length
== sizeof(u32
)) {
613 tmp
= *((u32
*) obj
->buffer
.pointer
);
614 DEBUG(2, " Out: 0x%08x\n", tmp
);
618 DEBUG(2, " Got unexpected result of type %d\n", obj
->type
);
620 DEBUG(2, " Got unexpected null result\n");
627 if (result
.length
> 0 && result
.pointer
)
628 kfree(result
.pointer
);
630 DEBUG(2, " Returning from WMI_execute_u32:\n");
634 static acpi_status
WMID_get_u32(u32
*value
, u32 cap
, struct Interface
*iface
) {
637 u32 result
, method_id
= 0;
639 DEBUG(2, " WMID_get_u32: cap=%d\n", cap
);
641 case ACER_CAP_WIRELESS
:
642 method_id
= ACER_WMID_GET_WIRELESS_METHODID
;
644 case ACER_CAP_BLUETOOTH
:
645 method_id
= ACER_WMID_GET_BLUETOOTH_METHODID
;
647 case ACER_CAP_BRIGHTNESS
:
648 method_id
= ACER_WMID_GET_BRIGHTNESS_METHODID
;
650 case ACER_CAP_THREEG
:
651 method_id
= ACER_WMID_GET_THREEG_METHODID
;
653 case ACER_CAP_MAILLED
:
654 if (quirks
->mailled
== 1) {
659 case ACER_CAP_TOUCHPAD_READ
:
660 switch (quirks
->touchpad
) {
663 *value
= 1 - ((tmp
>> 3) & 0x01);
667 *value
= ((tmp
>> 3) & 0x01);
672 case ACER_CAP_TEMPERATURE_OVERRIDE
:
673 if (quirks
->temperature_override
== 1) {
679 return AE_BAD_ADDRESS
;
681 status
= WMI_execute_u32(method_id
, 0, &result
);
682 DEBUG(2, " WMI_execute_u32 status=%d:\n", status
);
684 if (ACPI_SUCCESS(status
))
687 DEBUG(2, " Returning from WMID_get_u32:\n");
691 static acpi_status
WMID_set_u32(u32 value
, u32 cap
, struct Interface
*iface
) {
695 case ACER_CAP_BRIGHTNESS
:
696 if (value
> max_brightness
)
697 return AE_BAD_PARAMETER
;
698 method_id
= ACER_WMID_SET_BRIGHTNESS_METHODID
;
700 case ACER_CAP_WIRELESS
:
702 return AE_BAD_PARAMETER
;
703 method_id
= ACER_WMID_SET_WIRELESS_METHODID
;
705 case ACER_CAP_BLUETOOTH
:
707 return AE_BAD_PARAMETER
;
708 method_id
= ACER_WMID_SET_BLUETOOTH_METHODID
;
710 case ACER_CAP_THREEG
:
712 return AE_BAD_PARAMETER
;
713 method_id
= ACER_WMID_SET_THREEG_METHODID
;
715 case ACER_CAP_MAILLED
:
717 return AE_BAD_PARAMETER
;
718 if (quirks
->mailled
== 1) {
719 send_kbd_cmd(0x59, value
? 0x92 : 0x93);
723 case ACER_CAP_TEMPERATURE_OVERRIDE
:
724 if (value
> ACER_MAX_TEMPERATURE_OVERRIDE
)
725 return AE_BAD_PARAMETER
;
727 if (quirks
->temperature_override
== 1) {
728 ec_write(0xa9, value
);
732 return AE_BAD_ADDRESS
;
734 return WMI_execute_u32(method_id
, (u32
)value
, NULL
);
737 static acpi_status
WMID_set_capabilities(void) {
738 struct acpi_buffer out
= {ACPI_ALLOCATE_BUFFER
, NULL
};
739 union acpi_object
*obj
;
743 status
= wmi_acer_query_block(WMID_GUID2
, 1, &out
);
744 if (ACPI_FAILURE(status
))
747 obj
= (union acpi_object
*) out
.pointer
;
748 if (obj
&& obj
->type
== ACPI_TYPE_BUFFER
&& obj
->buffer
.length
== sizeof(u32
)) {
749 devices
= *((u32
*) obj
->buffer
.pointer
);
754 /* Not sure on the meaning of the relevant bits yet */
755 interface
->capability
|= ACER_CAP_WIRELESS
;
756 interface
->capability
|= ACER_CAP_THREEG
;
758 if (devices
& 0x10) {
759 DEBUG(1, "Bluetooth hardware available - enabling\n");
760 interface
->capability
|= ACER_CAP_BLUETOOTH
;
763 if (!(devices
& 0x20)) {
764 DEBUG(1, "Maximum brightness quirk detected - enabling\n");
765 max_brightness
= 0x9;
772 static struct Interface WMID_interface
= {
774 .capability
= ACER_CAP_BRIGHTNESS
,
779 * High-level Procfs file handlers
783 dispatch_read(char *page
, char **start
, off_t off
, int count
, int *eof
,
784 struct ProcItem
*item
)
789 DEBUG(2, " dispatch_read: \n");
791 p
= item
->read_func(p
, item
->capability
);
793 if (len
<= off
+ count
)
805 dispatch_write(struct file
*file
, const char __user
*buffer
,
806 unsigned long count
, struct ProcItem
*item
)
812 * Arg buffer points to userspace memory, which can't be accessed
813 * directly. Since we're making a copy, zero-terminate the
814 * destination so that sscanf can be used on it safely.
816 tmp_buffer
= kmalloc(count
+ 1, GFP_KERNEL
);
817 if (copy_from_user(tmp_buffer
, buffer
, count
)) {
820 tmp_buffer
[count
] = 0;
821 result
= item
->write_func(tmp_buffer
, count
, item
->capability
);
829 * Generic Device (interface-independent)
831 static acpi_status
get_u32(u32
*value
, u32 cap
)
833 acpi_status status
= AE_BAD_ADDRESS
;
835 DEBUG(2, " get_u32: cap=%u, value=%u\n",
836 cap
, interface
->type
);
837 switch (interface
->type
) {
839 status
= AMW0_get_u32(value
, cap
, interface
);
842 if (cap
== ACER_CAP_MAILLED
) {
843 status
= AMW0_get_u32(value
, cap
, interface
);
847 status
= WMID_get_u32(value
, cap
, interface
);
850 DEBUG(2, " Returning from get_u32:\n");
854 static acpi_status
set_u32(u32 value
, u32 cap
)
857 DEBUG(2, " set_u32: cap=%u, value=%u\n", cap
, value
);
859 if (interface
->capability
& cap
) {
860 switch (interface
->type
) {
862 return AMW0_set_u32(value
, cap
, interface
);
865 return WMID_set_u32(value
, cap
, interface
);
867 return AE_BAD_PARAMETER
;
870 return AE_BAD_PARAMETER
;
873 static void __init
acer_commandline_init(void)
875 DEBUG(1, "Commandline args: mailled(%d) wireless(%d) bluetooth(%d) brightness(%d)\n",
876 mailled
, wireless
, bluetooth
, brightness
);
879 * These will all fail silently if the value given is invalid, or the
880 * capability isn't available on the given interface
882 set_u32(mailled
, ACER_CAP_MAILLED
);
883 set_u32(wireless
, ACER_CAP_WIRELESS
);
884 set_u32(bluetooth
, ACER_CAP_BLUETOOTH
);
885 set_u32(threeg
, ACER_CAP_THREEG
);
886 set_u32(fan_temperature_override
, ACER_CAP_TEMPERATURE_OVERRIDE
);
887 set_u32(brightness
, ACER_CAP_BRIGHTNESS
);
892 * Procfs interface (deprecated)
894 static char *read_u32(char *p
, u32 cap
)
899 DEBUG(2, " read_u32: cap=%d\n", cap
);
900 status
= get_u32(&result
, cap
);
901 if (ACPI_SUCCESS(status
))
902 p
+= sprintf(p
, "%u\n", result
);
904 p
+= sprintf(p
, "Read error" );
908 static unsigned long write_u32(const char *buffer
, unsigned long count
, u32 cap
)
912 if (sscanf(buffer
, "%u", &value
) == 1) {
913 acpi_status status
= set_u32(value
, cap
);
914 if (ACPI_FAILURE(status
))
922 static char *read_version(char *p
, u32 cap
)
924 p
+= sprintf(p
, "%s\n", ACER_ACPI_VERSION
);
928 static char *read_interface(char *p
, u32 cap
)
930 p
+= sprintf(p
, "%s\n", (interface
->type
== ACER_AMW0
) ? "AMW0": "WMID");
934 static struct ProcItem proc_items
[] = {
935 {"mailled", read_u32
, write_u32
, ACER_CAP_MAILLED
},
936 {"bluetooth", read_u32
, write_u32
, ACER_CAP_BLUETOOTH
},
937 {"wireless", read_u32
, write_u32
, ACER_CAP_WIRELESS
},
938 {"brightness", read_u32
, write_u32
, ACER_CAP_BRIGHTNESS
},
939 {"threeg", read_u32
, write_u32
, ACER_CAP_THREEG
},
940 {"touchpad", read_u32
, NULL
, ACER_CAP_TOUCHPAD_READ
},
941 {"fan_temperature_override", read_u32
, write_u32
, ACER_CAP_TEMPERATURE_OVERRIDE
},
942 {"version", read_version
, NULL
, ACER_CAP_ANY
},
943 {"interface", read_interface
, NULL
, ACER_CAP_ANY
},
947 static int __init
add_proc_entries(void)
949 struct proc_dir_entry
*proc
;
950 struct ProcItem
*item
;
952 for (item
= proc_items
; item
->name
; ++item
) {
954 * Only add the proc file if the current interface actually
957 if (interface
->capability
& item
->capability
) {
958 proc
= create_proc_read_entry(item
->name
,
959 S_IFREG
| S_IRUGO
| S_IWUSR
,
961 (read_proc_t
*) dispatch_read
,
964 proc
->owner
= THIS_MODULE
;
965 if (proc
&& item
->write_func
)
966 proc
->write_proc
= (write_proc_t
*) dispatch_write
;
973 static int __exit
remove_proc_entries(void)
975 struct ProcItem
*item
;
977 for (item
= proc_items
; item
->name
; ++item
)
978 remove_proc_entry(item
->name
, acer_proc_dir
);
984 * LED device (Mail LED only, no other LEDs known yet)
986 static void mail_led_set(struct led_classdev
*led_cdev
, enum led_brightness value
)
989 set_u32(tmp
, ACER_CAP_MAILLED
);
992 static struct led_classdev mail_led
= {
993 .name
= "acer_acpi:mail",
994 .brightness_set
= mail_led_set
,
997 static void acer_led_init(struct device
*dev
)
999 led_classdev_register(dev
, &mail_led
);
1002 static void acer_led_exit(void)
1004 led_classdev_unregister(&mail_led
);
1007 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18)
1011 static struct backlight_device
*acer_backlight_device
;
1013 static int read_brightness(struct backlight_device
*bd
)
1016 get_u32(&value
, ACER_CAP_BRIGHTNESS
);
1020 #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,20)
1021 static int update_bl_status(struct backlight_device
*bd
)
1023 set_brightness(bd
->props
->brightness
);
1027 static struct backlight_properties acer_backlight_properties
= {
1028 .get_brightness
= read_brightness
,
1029 .update_status
= update_bl_status
,
1032 static int __init
acer_backlight_init(struct device
*dev
)
1034 struct backlight_device
*bd
;
1036 DEBUG(1, "Loading backlight driver\n");
1037 bd
= backlight_device_register("acer_acpi", dev
, NULL
, &acer_backlight_properties
);
1039 printk(ACER_ERR
"Could not register Acer backlight device\n");
1040 acer_backlight_device
= NULL
;
1044 acer_backlight_device
= bd
;
1046 bd
->props
->max_brightness
= max_brightness
;
1050 static int update_bl_status(struct backlight_device
*bd
)
1052 set_u32(bd
->props
.brightness
, ACER_CAP_BRIGHTNESS
);
1056 static struct backlight_ops acer_backlight_ops
= {
1057 .get_brightness
= read_brightness
,
1058 .update_status
= update_bl_status
,
1061 static int __init
acer_backlight_init(struct device
*dev
)
1063 struct backlight_device
*bd
;
1065 DEBUG(1, "Loading backlight driver\n");
1066 bd
= backlight_device_register("acer_acpi", dev
, NULL
, &acer_backlight_ops
);
1068 printk(ACER_ERR
"Could not register Acer backlight device\n");
1069 acer_backlight_device
= NULL
;
1073 acer_backlight_device
= bd
;
1075 bd
->props
.max_brightness
= max_brightness
;
1076 bd
->props
.brightness
= read_brightness(NULL
);
1077 backlight_update_status(bd
);
1082 static void __exit
acer_backlight_exit(void)
1084 backlight_device_unregister(acer_backlight_device
);
1089 * Read/ write bool sysfs macro
1091 #define show_set_bool(value, cap) \
1093 show_bool_##value(struct device *dev, struct device_attribute *attr, \
1097 acpi_status status = get_u32(&result, cap); \
1098 if (ACPI_SUCCESS(status)) \
1099 return sprintf(buf, "%u\n", result); \
1100 return sprintf(buf, "Read error" ); \
1104 set_bool_##value(struct device *dev, struct device_attribute *attr, \
1105 const char *buf, size_t count) \
1107 u32 tmp = simple_strtoul(buf, NULL, 10); \
1108 acpi_status status = set_u32(tmp, cap); \
1109 if (ACPI_FAILURE(status)) \
1113 static DEVICE_ATTR(value, S_IWUGO | S_IRUGO | S_IWUSR, \
1114 show_bool_##value, set_bool_##value);
1116 show_set_bool(wireless
, ACER_CAP_WIRELESS
);
1117 show_set_bool(bluetooth
, ACER_CAP_BLUETOOTH
);
1118 show_set_bool(threeg
, ACER_CAP_THREEG
);
1119 show_set_bool(fan_temperature_override
, ACER_CAP_TEMPERATURE_OVERRIDE
);
1122 * Read-only bool sysfs macro
1124 #define show_bool(value, cap) \
1126 show_bool_##value(struct device *dev, struct device_attribute *attr, \
1130 acpi_status status = get_u32(&result, cap); \
1131 if (ACPI_SUCCESS(status)) \
1132 return sprintf(buf, "%u\n", result); \
1133 return sprintf(buf, "Read error" ); \
1135 static DEVICE_ATTR(value, S_IWUGO | S_IRUGO | S_IWUSR, \
1136 show_bool_##value, NULL);
1138 show_bool(touchpad
, ACER_CAP_TOUCHPAD_READ
);
1141 * Read interface sysfs macro
1143 static ssize_t
show_interface(struct device
*dev
, struct device_attribute
*attr
,
1146 switch (interface
->type
) {
1148 return sprintf(buf
, "AMW0\n");
1150 return sprintf(buf
, "AMW0 v2\n");
1152 return sprintf(buf
, "WMID\n");
1154 return sprintf(buf
, "Error!\n");
1158 static DEVICE_ATTR(interface
, S_IWUGO
| S_IRUGO
| S_IWUSR
, show_interface
, NULL
);
1160 static ssize_t
show_devices(struct device
*dev
, struct device_attribute
*attr
,
1163 struct acpi_buffer out
= {ACPI_ALLOCATE_BUFFER
, NULL
};
1164 union acpi_object
*obj
;
1168 status
= wmi_acer_query_block(WMID_GUID2
, 1, &out
);
1169 if (ACPI_FAILURE(status
))
1170 return sprintf(buf
, "Error\n");
1172 obj
= (union acpi_object
*) out
.pointer
;
1173 if (obj
&& obj
->type
== ACPI_TYPE_BUFFER
&& obj
->buffer
.length
== sizeof(u32
)) {
1174 tmp
= *((u32
*) obj
->buffer
.pointer
);
1176 return sprintf(buf
, "Error\n");
1179 return sprintf(buf
, "%u\n", tmp
);
1182 static DEVICE_ATTR(devices
, S_IWUGO
| S_IRUGO
| S_IWUSR
, show_devices
, NULL
);
1187 static int __devinit
acer_platform_probe(struct platform_device
*device
)
1189 if (has_cap(ACER_CAP_MAILLED
))
1190 acer_led_init(&device
->dev
);
1191 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18)
1192 if (has_cap(ACER_CAP_BRIGHTNESS
))
1193 acer_backlight_init(&device
->dev
);
1198 static int acer_platform_remove(struct platform_device
*device
)
1200 if (has_cap(ACER_CAP_MAILLED
))
1202 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18)
1203 if (has_cap(ACER_CAP_BRIGHTNESS
))
1204 acer_backlight_exit();
1209 static int acer_platform_suspend(struct platform_device
*device
, pm_message_t state
)
1212 * WMID fix for suspend-to-disk - save all current states now so we can
1213 * restore them on resume
1216 struct acer_data
*data
= &interface
->data
;
1218 #define save_device(device, cap) \
1219 if (has_cap(cap)) {\
1220 get_u32(&value, cap);\
1221 data->device = value;\
1224 save_device(wireless
, ACER_CAP_WIRELESS
);
1225 save_device(bluetooth
, ACER_CAP_BLUETOOTH
);
1226 save_device(threeg
, ACER_CAP_THREEG
);
1227 save_device(mailled
, ACER_CAP_MAILLED
);
1228 save_device(brightness
, ACER_CAP_BRIGHTNESS
);
1233 static int acer_platform_resume(struct platform_device
*device
)
1235 struct acer_data
*data
= &interface
->data
;
1237 #define restore_bool_device(device, cap) \
1239 set_u32(data->device, cap);\
1241 restore_bool_device(wireless, ACER_CAP_WIRELESS);
1242 restore_bool_device(bluetooth
, ACER_CAP_BLUETOOTH
);
1243 restore_bool_device(threeg
, ACER_CAP_THREEG
);
1244 restore_bool_device(mailled
, ACER_CAP_MAILLED
);
1245 restore_bool_device(brightness
, ACER_CAP_BRIGHTNESS
);
1247 /* Check if this laptop requires the keyboard quirk */
1248 if (quirks
->mmkeys
!= 0) {
1249 set_keyboard_quirk();
1250 printk(ACER_INFO
"Setting keyboard quirk to enable multimedia keys\n");
1256 static struct platform_driver acer_platform_driver
= {
1258 .name
= "acer_acpi",
1259 .owner
= THIS_MODULE
,
1261 .probe
= acer_platform_probe
,
1262 .remove
= acer_platform_remove
,
1263 .suspend
= acer_platform_suspend
,
1264 .resume
= acer_platform_resume
,
1267 static struct platform_device
*acer_platform_device
;
1269 static int remove_sysfs(struct platform_device
*device
)
1271 #define remove_device_file(value, cap) \
1273 device_remove_file(&device->dev, &dev_attr_##value);
1275 if (wmi_acer_has_guid(WMID_GUID2
)) {
1276 device_remove_file(&device
->dev
, &dev_attr_devices
);
1279 remove_device_file(wireless
, ACER_CAP_WIRELESS
);
1280 remove_device_file(bluetooth
, ACER_CAP_BLUETOOTH
);
1281 remove_device_file(threeg
, ACER_CAP_THREEG
);
1282 remove_device_file(interface
, ACER_CAP_ANY
);
1283 remove_device_file(fan_temperature_override
, ACER_CAP_TEMPERATURE_OVERRIDE
);
1284 remove_device_file(touchpad
, ACER_CAP_TOUCHPAD_READ
);
1288 static int create_sysfs(void)
1290 int retval
= -ENOMEM
;
1292 #define add_device_file(value, cap) \
1293 if (has_cap(cap)) {\
1294 retval = device_create_file(&acer_platform_device->dev, &dev_attr_##value);\
1299 if (wmi_acer_has_guid(WMID_GUID2
)) {
1300 retval
= device_create_file(&acer_platform_device
->dev
, &dev_attr_devices
);
1305 add_device_file(wireless
, ACER_CAP_WIRELESS
);
1306 add_device_file(bluetooth
, ACER_CAP_BLUETOOTH
);
1307 add_device_file(threeg
, ACER_CAP_THREEG
);
1308 add_device_file(interface
, ACER_CAP_ANY
);
1309 add_device_file(fan_temperature_override
, ACER_CAP_TEMPERATURE_OVERRIDE
);
1310 add_device_file(touchpad
, ACER_CAP_TOUCHPAD_READ
);
1315 remove_sysfs(acer_platform_device
);
1319 static int __init
acer_acpi_init(void)
1321 printk(ACER_INFO
"Acer Laptop ACPI Extras version %s\n",
1324 /* Find if this laptop requires any quirks */
1325 DEBUG(1, "Finding quirks\n");
1329 * Detect which WMI interface we're using.
1331 if (wmi_acer_has_guid(AMW0_GUID1
)) {
1332 interface
= &AMW0_interface
;
1334 if (wmi_acer_has_guid(WMID_GUID1
)) {
1335 DEBUG(0, "Detected Acer AMW0 version 2 interface\n");
1336 interface
= &AMW0_V2_interface
;
1338 DEBUG(0, "Detected Acer AMW0 version 1 interface\n");
1339 if (!quirks
->brightness
) {
1340 quirks
->brightness
= 1;
1341 interface
->capability
|= ACER_CAP_BRIGHTNESS
;
1344 } else if (wmi_acer_has_guid(WMID_GUID1
)) {
1345 DEBUG(0, "Detected Acer WMID interface\n");
1346 interface
= &WMID_interface
;
1348 printk(ACER_ERR
"No or unsupported WMI interface, unable to load.\n");
1352 if (wmi_acer_has_guid(WMID_GUID2
)) {
1353 if (ACPI_FAILURE(WMID_set_capabilities())) {
1354 printk(ACER_ERR
"Unable to detect available devices\n");
1360 /* Create the proc entries */
1361 acer_proc_dir
= proc_mkdir(PROC_ACER
, acpi_root_dir
);
1362 if (!acer_proc_dir
) {
1363 printk(ACER_ERR
"Unable to create /proc entries, aborting.\n");
1364 goto error_proc_mkdir
;
1367 acer_proc_dir
->owner
= THIS_MODULE
;
1368 if (add_proc_entries()) {
1369 printk(ACER_ERR
"Unable to create /proc entries, aborting.\n");
1370 goto error_proc_add
;
1375 * Register the driver
1377 if (platform_driver_register(&acer_platform_driver
)) {
1378 printk(ACER_ERR
"Unable to register platform driver, aborting.\n");
1379 goto error_platform_register
;
1381 acer_platform_device
= platform_device_alloc("acer_acpi", -1);
1382 platform_device_add(acer_platform_device
);
1386 DEBUG(1, "Driver registered\n");
1388 /* Override any initial settings with values from the commandline */
1389 acer_commandline_init();
1393 error_platform_register
:
1395 remove_proc_entries();
1398 remove_proc_entry(PROC_ACER
, acpi_root_dir
);
1404 static void __exit
acer_acpi_exit(void)
1406 remove_sysfs(acer_platform_device
);
1407 platform_device_del(acer_platform_device
);
1408 platform_driver_unregister(&acer_platform_driver
);
1411 remove_proc_entries();
1414 remove_proc_entry(PROC_ACER
, acpi_root_dir
);
1416 printk(ACER_INFO
"Acer Laptop ACPI Extras unloaded\n");
1420 module_init(acer_acpi_init
);
1421 module_exit(acer_acpi_exit
);