37 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
39 #include <linux/kernel.h>
40 #include <linux/module.h>
42 #include <linux/types.h>
50 #include <linux/input.h>
53 #include <linux/rfkill.h>
54 #include <linux/slab.h>
59 #define ASUS_LAPTOP_VERSION "0.42"
61 #define ASUS_LAPTOP_NAME "Asus Laptop Support"
62 #define ASUS_LAPTOP_CLASS "hotkey"
63 #define ASUS_LAPTOP_DEVICE_NAME "Hotkey"
64 #define ASUS_LAPTOP_FILE KBUILD_MODNAME
65 #define ASUS_LAPTOP_PREFIX "\\_SB.ATKD."
67 MODULE_AUTHOR(
"Julien Lerouge, Karol Kozimor, Corentin Chary");
84 static char *wled_type =
"unknown";
85 static char *bled_type =
"unknown";
89 "(unknown, led or rfkill). "
90 "default is unknown");
94 "(unknown, led or rfkill). "
95 "default is unknown");
97 static int wlan_status = 1;
98 static int bluetooth_status = 1;
99 static int wimax_status = -1;
100 static int wwan_status = -1;
101 static int als_status;
105 "(0 = disabled, 1 = enabled, -1 = don't do anything). "
110 "(0 = disabled, 1 = enabled, -1 = don't do anything). "
115 "(0 = disabled, 1 = enabled, -1 = don't do anything). "
120 "(0 = disabled, 1 = enabled, -1 = don't do anything). "
125 "(0 = disabled, 1 = enabled). "
131 #define ATKD_BR_UP 0x10
132 #define ATKD_BR_DOWN 0x20
133 #define ATKD_BR_MIN ATKD_BR_UP
134 #define ATKD_BR_MAX (ATKD_BR_DOWN | 0xF)
135 #define ATKD_LCD_ON 0x33
136 #define ATKD_LCD_OFF 0x34
142 #define BT_HWRS 0x100
154 #define TYPE_UNKNOWN 0
156 #define TYPE_RFKILL 2
159 #define METHOD_MLED "MLED"
160 #define METHOD_TLED "TLED"
161 #define METHOD_RLED "RLED"
162 #define METHOD_PLED "PLED"
163 #define METHOD_GLED "GLED"
166 #define METHOD_LEDD "SLCM"
173 #define METHOD_WLAN "WLED"
174 #define METHOD_BLUETOOTH "BLED"
177 #define METHOD_WWAN "GSMC"
178 #define METHOD_WIMAX "WMXC"
180 #define METHOD_WL_STATUS "RSTS"
183 #define METHOD_BRIGHTNESS_SET "SPLV"
184 #define METHOD_BRIGHTNESS_GET "GPLV"
187 #define METHOD_SWITCH_DISPLAY "SDSP"
189 #define METHOD_ALS_CONTROL "ALSC"
190 #define METHOD_ALS_LEVEL "ALSL"
194 #define METHOD_GPS_ON "SDON"
195 #define METHOD_GPS_OFF "SDOF"
196 #define METHOD_GPS_STATUS "GPST"
199 #define METHOD_KBD_LIGHT_SET "SLKB"
200 #define METHOD_KBD_LIGHT_GET "GLKB"
203 #define DEVICE_NAME_PEGA "Lucid"
205 #define METHOD_PEGA_ENABLE "ENPR"
206 #define METHOD_PEGA_DISABLE "DAPR"
207 #define PEGA_WLAN 0x00
208 #define PEGA_BLUETOOTH 0x01
209 #define PEGA_WWAN 0x02
210 #define PEGA_ALS 0x04
211 #define PEGA_ALS_POWER 0x05
213 #define METHOD_PEGA_READ "RDLN"
214 #define PEGA_READ_ALS_H 0x02
215 #define PEGA_READ_ALS_L 0x03
217 #define PEGA_ACCEL_NAME "pega_accel"
218 #define PEGA_ACCEL_DESC "Pegatron Lucid Tablet Accelerometer"
219 #define METHOD_XLRX "XLRX"
220 #define METHOD_XLRY "XLRY"
221 #define METHOD_XLRZ "XLRZ"
222 #define PEGA_ACC_CLAMP 512
223 #define PEGA_ACC_RETRIES 3
295 static const struct key_entry asus_keymap[] = {
362 in_obj.integer.value =
val;
371 static int write_acpi_int(
acpi_handle handle,
const char *method,
int val)
373 return write_acpi_int_ret(handle, method, val,
NULL);
376 static int acpi_check_handle(
acpi_handle handle,
const char *method,
394 if (status !=
AE_OK) {
396 pr_warn(
"Error finding %s\n", method);
402 static bool asus_check_pega_lucid(
struct asus_laptop *asus)
413 return write_acpi_int(asus->
handle, method, unit);
416 static int pega_acc_axis(
struct asus_laptop *asus,
int curr,
char *method)
419 unsigned long long val;
429 delta =
abs(curr - (
short)val);
430 if (delta < 128 && !(val & ~0xffff))
436 static void pega_accel_poll(
struct input_polled_dev *ipd)
447 input_report_abs(ipd->input,
ABS_X, 0);
448 input_report_abs(ipd->input,
ABS_Y, 0);
449 input_report_abs(ipd->input,
ABS_Z, 0);
450 input_sync(ipd->input);
464 input_sync(ipd->input);
467 static void pega_accel_exit(
struct asus_laptop *asus)
476 static int pega_accel_init(
struct asus_laptop *asus)
479 struct input_polled_dev *ipd;
493 ipd->poll = pega_accel_poll;
494 ipd->poll_interval = 125;
495 ipd->poll_interval_min = 50;
496 ipd->poll_interval_max = 2000;
504 input_set_abs_params(ipd->input,
ABS_X,
506 input_set_abs_params(ipd->input,
ABS_Y,
508 input_set_abs_params(ipd->input,
ABS_Z,
524 static int asus_led_set(
struct asus_laptop *asus,
const char *method,
534 return write_acpi_int(asus->
handle, method, value);
541 static void asus_led_cdev_set(
struct led_classdev *led_cdev,
556 asus_led_set(asus, led->
method, led->
wk);
569 unsigned long long kblv;
577 in_obj.integer.value = 2;
582 pr_warn(
"Error reading kled level\n");
588 static int asus_kled_set(
struct asus_laptop *asus,
int kblv)
591 kblv = (1 << 7) | (kblv & 0x7F);
596 pr_warn(
"Keyboard LED display write failed\n");
602 static void asus_kled_cdev_set(
struct led_classdev *led_cdev,
617 asus_kled_set(asus, led->
wk);
625 return asus_kled_lvl(asus);
628 static void asus_led_exit(
struct asus_laptop *asus)
630 if (!IS_ERR_OR_NULL(asus->
wled.led.dev))
632 if (!IS_ERR_OR_NULL(asus->
bled.led.dev))
634 if (!IS_ERR_OR_NULL(asus->
mled.led.dev))
636 if (!IS_ERR_OR_NULL(asus->
tled.led.dev))
638 if (!IS_ERR_OR_NULL(asus->
pled.led.dev))
640 if (!IS_ERR_OR_NULL(asus->
rled.led.dev))
642 if (!IS_ERR_OR_NULL(asus->
gled.led.dev))
644 if (!IS_ERR_OR_NULL(asus->
kled.led.dev))
653 static int asus_led_register(
struct asus_laptop *asus,
655 const char *
name,
const char *method)
659 if (!method || acpi_check_handle(asus->
handle, method,
NULL))
695 r = asus_led_register(asus, &asus->
wled,
"asus::wlan",
700 r = asus_led_register(asus, &asus->
bled,
"asus::bluetooth",
707 r = asus_led_register(asus, &asus->
tled,
"asus::touchpad",
METHOD_TLED);
727 cdev->
name =
"asus::kbd_backlight";
745 unsigned long long value;
751 pr_warn(
"Error reading brightness\n");
761 pr_warn(
"Error changing brightness\n");
769 int value = bd->
props.brightness;
771 return asus_set_brightness(bd, value);
775 .get_brightness = asus_read_brightness,
776 .update_status = update_bl_status,
779 static int asus_backlight_notify(
struct asus_laptop *asus)
782 int old = bd->
props.brightness;
789 static int asus_backlight_init(
struct asus_laptop *asus)
799 props.max_brightness = 15;
804 &asusbl_ops, &props);
806 pr_err(
"Could not register asus backlight device\n");
812 bd->
props.brightness = asus_read_brightness(bd);
814 backlight_update_status(bd);
818 static void asus_backlight_exit(
struct asus_laptop *asus)
839 unsigned long long temp;
849 len +=
sprintf(page + len,
"Model reference : %s\n", asus->
name);
858 len +=
sprintf(page + len,
"SFUN value : %#x\n",
868 len +=
sprintf(page + len,
"HWRS value : %#x\n",
879 len +=
sprintf(page + len,
"ASYM value : %#x\n",
883 len +=
sprintf(page + len,
"DSDT length : %s\n", buf);
885 len +=
sprintf(page + len,
"DSDT checksum : %s\n", buf);
887 len +=
sprintf(page + len,
"DSDT revision : %s\n", buf);
889 len +=
sprintf(page + len,
"OEM id : %s\n", buf);
891 len +=
sprintf(page + len,
"OEM table id : %s\n", buf);
893 len +=
sprintf(page + len,
"OEM revision : 0x%s\n", buf);
895 len +=
sprintf(page + len,
"ASL comp vendor id : %s\n", buf);
897 len +=
sprintf(page + len,
"ASL comp revision : 0x%s\n", buf);
903 static int parse_arg(
const char *buf,
unsigned long count,
int *val)
909 if (
sscanf(buf,
"%i", val) != 1)
915 const char *buf,
size_t count,
921 rv = parse_arg(buf, count, &value);
925 if (write_acpi_int(asus->
handle, method, value))
942 const char *buf,
size_t count)
947 rv = parse_arg(buf, count, &value);
950 pr_warn(
"LED display write failed\n");
963 unsigned long long status;
972 pr_warn(
"Error reading Wireless status\n");
975 return !!(status &
mask);
981 static int asus_wlan_set(
struct asus_laptop *asus,
int status)
984 pr_warn(
"Error setting wlan status to %d\n", status);
999 const char *buf,
size_t count)
1003 return sysfs_acpi_set(asus, buf, count,
METHOD_WLAN);
1009 static int asus_bluetooth_set(
struct asus_laptop *asus,
int status)
1012 pr_warn(
"Error setting bluetooth status to %d\n", status);
1023 return sprintf(buf,
"%d\n", asus_wireless_status(asus,
BT_RSTS));
1038 static int asus_wimax_set(
struct asus_laptop *asus,
int status)
1041 pr_warn(
"Error setting wimax status to %d\n", status);
1052 return sprintf(buf,
"%d\n", asus_wireless_status(asus,
WM_RSTS));
1067 static int asus_wwan_set(
struct asus_laptop *asus,
int status)
1070 pr_warn(
"Error setting wwan status to %d\n", status);
1081 return sprintf(buf,
"%d\n", asus_wireless_status(asus,
WW_RSTS));
1090 return sysfs_acpi_set(asus, buf, count,
METHOD_WWAN);
1096 static void asus_set_display(
struct asus_laptop *asus,
int value)
1100 pr_warn(
"Error setting display\n");
1112 const char *buf,
size_t count)
1117 rv = parse_arg(buf, count, &value);
1119 asus_set_display(asus, value);
1126 static void asus_als_switch(
struct asus_laptop *asus,
int value)
1131 ret = asus_pega_lucid_set(asus,
PEGA_ALS, value);
1138 pr_warning(
"Error setting light sensor switch\n");
1152 const char *buf,
size_t count)
1157 rv = parse_arg(buf, count, &value);
1159 asus_als_switch(asus, value ? 1 : 0);
1164 static void asus_als_level(
struct asus_laptop *asus,
int value)
1167 pr_warn(
"Error setting light sensor level\n");
1180 const char *buf,
size_t count)
1185 rv = parse_arg(buf, count, &value);
1187 value = (0 <
value) ? ((15 < value) ? 15 :
value) : 0;
1189 asus_als_level(asus, value);
1220 return sprintf(buf,
"%d\n", 10 * hi + lo);
1227 static int asus_gps_status(
struct asus_laptop *asus)
1229 unsigned long long status;
1235 pr_warn(
"Error reading GPS status\n");
1241 static int asus_gps_switch(
struct asus_laptop *asus,
int status)
1245 if (write_acpi_int(asus->
handle, meth, 0x02))
1255 return sprintf(buf,
"%d\n", asus_gps_status(asus));
1259 const char *buf,
size_t count)
1265 rv = parse_arg(buf, count, &value);
1268 ret = asus_gps_switch(asus, !!value);
1278 static int asus_gps_rfkill_set(
void *
data,
bool blocked)
1282 return asus_gps_switch(asus, !blocked);
1285 static const struct rfkill_ops asus_gps_rfkill_ops = {
1286 .set_block = asus_gps_rfkill_set,
1289 static int asus_rfkill_set(
void *
data,
bool blocked)
1295 return asus_wlan_set(asus, !blocked);
1297 return asus_bluetooth_set(asus, !blocked);
1299 return asus_wimax_set(asus, !blocked);
1301 return asus_wwan_set(asus, !blocked);
1306 static const struct rfkill_ops asus_rfkill_ops = {
1307 .set_block = asus_rfkill_set,
1310 static void asus_rfkill_terminate(
struct asus_rfkill *rfk)
1320 static void asus_rfkill_exit(
struct asus_laptop *asus)
1322 asus_rfkill_terminate(&asus->
wwan);
1323 asus_rfkill_terminate(&asus->
bluetooth);
1324 asus_rfkill_terminate(&asus->
wlan);
1325 asus_rfkill_terminate(&asus->
gps);
1329 const char *name,
int control_id,
int type,
1350 static int asus_rfkill_init(
struct asus_laptop *asus)
1360 result = asus_rfkill_setup(asus, &asus->
gps,
"asus-gps",
1362 &asus_gps_rfkill_ops);
1369 result = asus_rfkill_setup(asus, &asus->
wlan,
"asus-wlan",
1377 result = asus_rfkill_setup(asus, &asus->
bluetooth,
1385 result = asus_rfkill_setup(asus, &asus->
wwan,
"asus-wwan",
1392 result = asus_rfkill_setup(asus, &asus->
wimax,
"asus-wimax",
1400 asus_rfkill_exit(asus);
1405 static int pega_rfkill_set(
void *data,
bool blocked)
1409 int ret = asus_pega_lucid_set(rfk->
asus, rfk->
control_id, !blocked);
1413 static const struct rfkill_ops pega_rfkill_ops = {
1414 .set_block = pega_rfkill_set,
1420 return asus_rfkill_setup(asus, rfk, name, controlid, rfkill_type,
1424 static int pega_rfkill_init(
struct asus_laptop *asus)
1431 ret = pega_rfkill_setup(asus, &asus->
wlan,
"pega-wlan",
1436 ret = pega_rfkill_setup(asus, &asus->
bluetooth,
"pega-bt",
1441 ret = pega_rfkill_setup(asus, &asus->
wwan,
"pega-wwan",
1446 asus_rfkill_exit(asus);
1458 if (!sparse_keymap_report_event(asus->
inputdev, event, 1,
true))
1459 pr_info(
"Unknown key %x pressed\n", event);
1462 static int asus_input_init(
struct asus_laptop *asus)
1464 struct input_dev *
input;
1467 input = input_allocate_device();
1469 pr_warn(
"Unable to allocate input device\n");
1472 input->name =
"Asus Laptop extra buttons";
1477 error = sparse_keymap_setup(input, asus_keymap,
NULL);
1479 pr_err(
"Unable to setup input device keymap\n");
1482 error = input_register_device(input);
1484 pr_warn(
"Unable to register input device\n");
1485 goto err_free_keymap;
1492 sparse_keymap_free(input);
1494 input_free_device(input);
1498 static void asus_input_exit(
struct asus_laptop *asus)
1501 sparse_keymap_free(asus->
inputdev);
1502 input_unregister_device(asus->
inputdev);
1510 static void asus_acpi_notify(
struct acpi_device *
device,
u32 event)
1512 struct asus_laptop *asus = acpi_driver_data(device);
1517 acpi_bus_generate_proc_event(asus->
device, event, count);
1519 dev_name(&asus->
device->dev), event,
1528 asus_backlight_notify(asus);
1540 asus_input_notify(asus, event);
1546 show_bluetooth, store_bluetooth);
1556 static struct attribute *asus_attributes[] = {
1557 &dev_attr_infos.attr,
1558 &dev_attr_wlan.attr,
1559 &dev_attr_bluetooth.attr,
1560 &dev_attr_wimax.attr,
1561 &dev_attr_wwan.attr,
1562 &dev_attr_display.attr,
1563 &dev_attr_ledd.attr,
1564 &dev_attr_ls_value.attr,
1565 &dev_attr_ls_level.attr,
1566 &dev_attr_ls_switch.attr,
1575 struct device *dev =
container_of(kobj,
struct device, kobj);
1577 struct asus_laptop *asus = platform_get_drvdata(pdev);
1583 if (attr == &dev_attr_ls_switch.attr)
1585 else if (attr == &dev_attr_ls_level.attr)
1594 if (attr == &dev_attr_wlan.attr) {
1597 }
else if (attr == &dev_attr_bluetooth.attr) {
1600 }
else if (attr == &dev_attr_display.attr) {
1603 }
else if (attr == &dev_attr_wimax.attr) {
1607 }
else if (attr == &dev_attr_wwan.attr) {
1610 }
else if (attr == &dev_attr_ledd.attr) {
1613 }
else if (attr == &dev_attr_ls_switch.attr ||
1614 attr == &dev_attr_ls_level.attr) {
1617 }
else if (attr == &dev_attr_ls_value.attr) {
1619 }
else if (attr == &dev_attr_gps.attr) {
1627 return supported ? attr->
mode : 0;
1632 .is_visible = asus_sysfs_is_visible,
1633 .attrs = asus_attributes,
1636 static int asus_platform_init(
struct asus_laptop *asus)
1647 goto fail_platform_device;
1658 fail_platform_device:
1663 static void asus_platform_exit(
struct asus_laptop *asus)
1681 static int asus_laptop_get_info(
struct asus_laptop *asus)
1685 unsigned long long bsts_result, hwrs_result;
1686 char *
string =
NULL;
1698 pr_warn(
"Couldn't get the DSDT table header\n");
1701 if (write_acpi_int_ret(asus->
handle,
"INIT", 0, &buffer)) {
1702 pr_err(
"Hotkey initialization failed\n");
1710 pr_warn(
"Error calling BSTS\n");
1711 else if (bsts_result)
1712 pr_notice(
"BSTS called, 0x%02x returned\n",
1713 (
uint) bsts_result);
1716 if (write_acpi_int(asus->
handle,
"CWAP", wapf))
1717 pr_err(
"Error calling CWAP(%d)\n", wapf);
1726 switch (model->
type) {
1728 string = model->
string.pointer;
1731 string = model->
buffer.pointer;
1745 pr_notice(
" %s model detected\n",
string);
1756 pr_notice(
" HWRS returned %x", (
int)hwrs_result);
1773 if (!asus->
device->status.present) {
1774 pr_err(
"Hotkey device not present, aborting\n");
1778 result = asus_laptop_get_info(asus);
1782 if (!
strcmp(bled_type,
"led"))
1784 else if (!
strcmp(bled_type,
"rfkill"))
1787 if (!
strcmp(wled_type,
"led"))
1789 else if (!
strcmp(wled_type,
"rfkill"))
1792 if (bluetooth_status >= 0)
1793 asus_bluetooth_set(asus, !!bluetooth_status);
1795 if (wlan_status >= 0)
1796 asus_wlan_set(asus, !!wlan_status);
1798 if (wimax_status >= 0)
1799 asus_wimax_set(asus, !!wimax_status);
1801 if (wwan_status >= 0)
1802 asus_wwan_set(asus, !!wwan_status);
1806 asus_kled_set(asus, 1);
1826 static void __devinit asus_dmi_check(
void)
1835 if (
strncmp(model,
"L1400B", 6) == 0) {
1840 static bool asus_device_present;
1842 static int __devinit asus_acpi_add(
struct acpi_device *device)
1847 pr_notice(
"Asus Laptop Support version %s\n",
1852 asus->
handle = device->handle;
1855 device->driver_data = asus;
1860 result = asus_acpi_init(asus);
1869 result = asus_platform_init(asus);
1874 result = asus_backlight_init(asus);
1876 goto fail_backlight;
1878 pr_info(
"Backlight controlled by ACPI video driver\n");
1880 result = asus_input_init(asus);
1884 result = asus_led_init(asus);
1888 result = asus_rfkill_init(asus);
1889 if (result && result != -
ENODEV)
1892 result = pega_accel_init(asus);
1893 if (result && result != -
ENODEV)
1894 goto fail_pega_accel;
1896 result = pega_rfkill_init(asus);
1897 if (result && result != -
ENODEV)
1898 goto fail_pega_rfkill;
1900 asus_device_present =
true;
1904 pega_accel_exit(asus);
1906 asus_rfkill_exit(asus);
1908 asus_led_exit(asus);
1910 asus_input_exit(asus);
1912 asus_backlight_exit(asus);
1914 asus_platform_exit(asus);
1922 static int asus_acpi_remove(
struct acpi_device *device,
int type)
1924 struct asus_laptop *asus = acpi_driver_data(device);
1926 asus_backlight_exit(asus);
1927 asus_rfkill_exit(asus);
1928 asus_led_exit(asus);
1929 asus_input_exit(asus);
1930 pega_accel_exit(asus);
1931 asus_platform_exit(asus);
1945 static struct acpi_driver asus_acpi_driver = {
1949 .ids = asus_device_ids,
1950 .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS,
1952 .add = asus_acpi_add,
1953 .remove = asus_acpi_remove,
1954 .notify = asus_acpi_notify,
1958 static int __init asus_laptop_init(
void)
1968 goto fail_acpi_driver;
1969 if (!asus_device_present) {
1971 goto fail_no_device;
1982 static void __exit asus_laptop_exit(
void)