aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc/acer-wmi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/misc/acer-wmi.c')
-rw-r--r--drivers/misc/acer-wmi.c145
1 files changed, 135 insertions, 10 deletions
diff --git a/drivers/misc/acer-wmi.c b/drivers/misc/acer-wmi.c
index dd13a3749927..e7a3fe508dff 100644
--- a/drivers/misc/acer-wmi.c
+++ b/drivers/misc/acer-wmi.c
@@ -22,18 +22,18 @@
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 */ 23 */
24 24
25#define ACER_WMI_VERSION "0.1"
26
27#include <linux/kernel.h> 25#include <linux/kernel.h>
28#include <linux/module.h> 26#include <linux/module.h>
29#include <linux/init.h> 27#include <linux/init.h>
30#include <linux/types.h> 28#include <linux/types.h>
31#include <linux/dmi.h> 29#include <linux/dmi.h>
30#include <linux/fb.h>
32#include <linux/backlight.h> 31#include <linux/backlight.h>
33#include <linux/leds.h> 32#include <linux/leds.h>
34#include <linux/platform_device.h> 33#include <linux/platform_device.h>
35#include <linux/acpi.h> 34#include <linux/acpi.h>
36#include <linux/i8042.h> 35#include <linux/i8042.h>
36#include <linux/debugfs.h>
37 37
38#include <acpi/acpi_drivers.h> 38#include <acpi/acpi_drivers.h>
39 39
@@ -87,6 +87,7 @@ struct acer_quirks {
87 * Acer ACPI method GUIDs 87 * Acer ACPI method GUIDs
88 */ 88 */
89#define AMW0_GUID1 "67C3371D-95A3-4C37-BB61-DD47B491DAAB" 89#define AMW0_GUID1 "67C3371D-95A3-4C37-BB61-DD47B491DAAB"
90#define AMW0_GUID2 "431F16ED-0C2B-444C-B267-27DEB140CF9C"
90#define WMID_GUID1 "6AF4F258-B401-42fd-BE91-3D4AC2D7C0D3" 91#define WMID_GUID1 "6AF4F258-B401-42fd-BE91-3D4AC2D7C0D3"
91#define WMID_GUID2 "95764E09-FB56-4e83-B31A-37761F60994A" 92#define WMID_GUID2 "95764E09-FB56-4e83-B31A-37761F60994A"
92 93
@@ -150,6 +151,12 @@ struct acer_data {
150 int brightness; 151 int brightness;
151}; 152};
152 153
154struct acer_debug {
155 struct dentry *root;
156 struct dentry *devices;
157 u32 wmid_devices;
158};
159
153/* Each low-level interface must define at least some of the following */ 160/* Each low-level interface must define at least some of the following */
154struct wmi_interface { 161struct wmi_interface {
155 /* The WMI device type */ 162 /* The WMI device type */
@@ -160,6 +167,9 @@ struct wmi_interface {
160 167
161 /* Private data for the current interface */ 168 /* Private data for the current interface */
162 struct acer_data data; 169 struct acer_data data;
170
171 /* debugfs entries associated with this interface */
172 struct acer_debug debug;
163}; 173};
164 174
165/* The static interface pointer, points to the currently detected interface */ 175/* The static interface pointer, points to the currently detected interface */
@@ -174,7 +184,7 @@ static struct wmi_interface *interface;
174struct quirk_entry { 184struct quirk_entry {
175 u8 wireless; 185 u8 wireless;
176 u8 mailled; 186 u8 mailled;
177 u8 brightness; 187 s8 brightness;
178 u8 bluetooth; 188 u8 bluetooth;
179}; 189};
180 190
@@ -198,6 +208,10 @@ static int dmi_matched(const struct dmi_system_id *dmi)
198static struct quirk_entry quirk_unknown = { 208static struct quirk_entry quirk_unknown = {
199}; 209};
200 210
211static struct quirk_entry quirk_acer_aspire_1520 = {
212 .brightness = -1,
213};
214
201static struct quirk_entry quirk_acer_travelmate_2490 = { 215static struct quirk_entry quirk_acer_travelmate_2490 = {
202 .mailled = 1, 216 .mailled = 1,
203}; 217};
@@ -207,9 +221,31 @@ static struct quirk_entry quirk_medion_md_98300 = {
207 .wireless = 1, 221 .wireless = 1,
208}; 222};
209 223
224static struct quirk_entry quirk_fujitsu_amilo_li_1718 = {
225 .wireless = 2,
226};
227
210static struct dmi_system_id acer_quirks[] = { 228static struct dmi_system_id acer_quirks[] = {
211 { 229 {
212 .callback = dmi_matched, 230 .callback = dmi_matched,
231 .ident = "Acer Aspire 1360",
232 .matches = {
233 DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
234 DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 1360"),
235 },
236 .driver_data = &quirk_acer_aspire_1520,
237 },
238 {
239 .callback = dmi_matched,
240 .ident = "Acer Aspire 1520",
241 .matches = {
242 DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
243 DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 1520"),
244 },
245 .driver_data = &quirk_acer_aspire_1520,
246 },
247 {
248 .callback = dmi_matched,
213 .ident = "Acer Aspire 3100", 249 .ident = "Acer Aspire 3100",
214 .matches = { 250 .matches = {
215 DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 251 DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
@@ -300,6 +336,15 @@ static struct dmi_system_id acer_quirks[] = {
300 }, 336 },
301 { 337 {
302 .callback = dmi_matched, 338 .callback = dmi_matched,
339 .ident = "Fujitsu Siemens Amilo Li 1718",
340 .matches = {
341 DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
342 DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Li 1718"),
343 },
344 .driver_data = &quirk_fujitsu_amilo_li_1718,
345 },
346 {
347 .callback = dmi_matched,
303 .ident = "Medion MD 98300", 348 .ident = "Medion MD 98300",
304 .matches = { 349 .matches = {
305 DMI_MATCH(DMI_SYS_VENDOR, "MEDION"), 350 DMI_MATCH(DMI_SYS_VENDOR, "MEDION"),
@@ -393,6 +438,12 @@ struct wmi_interface *iface)
393 return AE_ERROR; 438 return AE_ERROR;
394 *value = result & 0x1; 439 *value = result & 0x1;
395 return AE_OK; 440 return AE_OK;
441 case 2:
442 err = ec_read(0x71, &result);
443 if (err)
444 return AE_ERROR;
445 *value = result & 0x1;
446 return AE_OK;
396 default: 447 default:
397 err = ec_read(0xA, &result); 448 err = ec_read(0xA, &result);
398 if (err) 449 if (err)
@@ -506,6 +557,15 @@ static acpi_status AMW0_set_capabilities(void)
506 struct acpi_buffer out = { ACPI_ALLOCATE_BUFFER, NULL }; 557 struct acpi_buffer out = { ACPI_ALLOCATE_BUFFER, NULL };
507 union acpi_object *obj; 558 union acpi_object *obj;
508 559
560 /*
561 * On laptops with this strange GUID (non Acer), normal probing doesn't
562 * work.
563 */
564 if (wmi_has_guid(AMW0_GUID2)) {
565 interface->capability |= ACER_CAP_WIRELESS;
566 return AE_OK;
567 }
568
509 args.eax = ACER_AMW0_WRITE; 569 args.eax = ACER_AMW0_WRITE;
510 args.ecx = args.edx = 0; 570 args.ecx = args.edx = 0;
511 571
@@ -552,7 +612,8 @@ static acpi_status AMW0_set_capabilities(void)
552 * appear to use the same EC register for brightness, even if they 612 * appear to use the same EC register for brightness, even if they
553 * differ for wireless, etc 613 * differ for wireless, etc
554 */ 614 */
555 interface->capability |= ACER_CAP_BRIGHTNESS; 615 if (quirks->brightness >= 0)
616 interface->capability |= ACER_CAP_BRIGHTNESS;
556 617
557 return AE_OK; 618 return AE_OK;
558} 619}
@@ -807,7 +868,15 @@ static int read_brightness(struct backlight_device *bd)
807 868
808static int update_bl_status(struct backlight_device *bd) 869static int update_bl_status(struct backlight_device *bd)
809{ 870{
810 set_u32(bd->props.brightness, ACER_CAP_BRIGHTNESS); 871 int intensity = bd->props.brightness;
872
873 if (bd->props.power != FB_BLANK_UNBLANK)
874 intensity = 0;
875 if (bd->props.fb_blank != FB_BLANK_UNBLANK)
876 intensity = 0;
877
878 set_u32(intensity, ACER_CAP_BRIGHTNESS);
879
811 return 0; 880 return 0;
812} 881}
813 882
@@ -829,8 +898,9 @@ static int __devinit acer_backlight_init(struct device *dev)
829 898
830 acer_backlight_device = bd; 899 acer_backlight_device = bd;
831 900
901 bd->props.power = FB_BLANK_UNBLANK;
902 bd->props.brightness = max_brightness;
832 bd->props.max_brightness = max_brightness; 903 bd->props.max_brightness = max_brightness;
833 bd->props.brightness = read_brightness(NULL);
834 backlight_update_status(bd); 904 backlight_update_status(bd);
835 return 0; 905 return 0;
836} 906}
@@ -894,6 +964,28 @@ static DEVICE_ATTR(interface, S_IWUGO | S_IRUGO | S_IWUSR,
894 show_interface, NULL); 964 show_interface, NULL);
895 965
896/* 966/*
967 * debugfs functions
968 */
969static u32 get_wmid_devices(void)
970{
971 struct acpi_buffer out = {ACPI_ALLOCATE_BUFFER, NULL};
972 union acpi_object *obj;
973 acpi_status status;
974
975 status = wmi_query_block(WMID_GUID2, 1, &out);
976 if (ACPI_FAILURE(status))
977 return 0;
978
979 obj = (union acpi_object *) out.pointer;
980 if (obj && obj->type == ACPI_TYPE_BUFFER &&
981 obj->buffer.length == sizeof(u32)) {
982 return *((u32 *) obj->buffer.pointer);
983 } else {
984 return 0;
985 }
986}
987
988/*
897 * Platform device 989 * Platform device
898 */ 990 */
899static int __devinit acer_platform_probe(struct platform_device *device) 991static int __devinit acer_platform_probe(struct platform_device *device)
@@ -1052,12 +1144,40 @@ error_sysfs:
1052 return retval; 1144 return retval;
1053} 1145}
1054 1146
1147static void remove_debugfs(void)
1148{
1149 debugfs_remove(interface->debug.devices);
1150 debugfs_remove(interface->debug.root);
1151}
1152
1153static int create_debugfs(void)
1154{
1155 interface->debug.root = debugfs_create_dir("acer-wmi", NULL);
1156 if (!interface->debug.root) {
1157 printk(ACER_ERR "Failed to create debugfs directory");
1158 return -ENOMEM;
1159 }
1160
1161 interface->debug.devices = debugfs_create_u32("devices", S_IRUGO,
1162 interface->debug.root,
1163 &interface->debug.wmid_devices);
1164 if (!interface->debug.devices)
1165 goto error_debugfs;
1166
1167 return 0;
1168
1169error_debugfs:
1170 remove_debugfs();
1171 return -ENOMEM;
1172}
1173
1055static int __init acer_wmi_init(void) 1174static int __init acer_wmi_init(void)
1056{ 1175{
1057 int err; 1176 int err;
1058 1177
1059 printk(ACER_INFO "Acer Laptop ACPI-WMI Extras version %s\n", 1178 printk(ACER_INFO "Acer Laptop ACPI-WMI Extras\n");
1060 ACER_WMI_VERSION); 1179
1180 find_quirks();
1061 1181
1062 /* 1182 /*
1063 * Detect which ACPI-WMI interface we're using. 1183 * Detect which ACPI-WMI interface we're using.
@@ -1092,8 +1212,6 @@ static int __init acer_wmi_init(void)
1092 if (wmi_has_guid(AMW0_GUID1)) 1212 if (wmi_has_guid(AMW0_GUID1))
1093 AMW0_find_mailled(); 1213 AMW0_find_mailled();
1094 1214
1095 find_quirks();
1096
1097 if (!interface) { 1215 if (!interface) {
1098 printk(ACER_ERR "No or unsupported WMI interface, unable to " 1216 printk(ACER_ERR "No or unsupported WMI interface, unable to "
1099 "load\n"); 1217 "load\n");
@@ -1111,6 +1229,13 @@ static int __init acer_wmi_init(void)
1111 if (err) 1229 if (err)
1112 return err; 1230 return err;
1113 1231
1232 if (wmi_has_guid(WMID_GUID2)) {
1233 interface->debug.wmid_devices = get_wmid_devices();
1234 err = create_debugfs();
1235 if (err)
1236 return err;
1237 }
1238
1114 /* Override any initial settings with values from the commandline */ 1239 /* Override any initial settings with values from the commandline */
1115 acer_commandline_init(); 1240 acer_commandline_init();
1116 1241