diff options
| -rw-r--r-- | drivers/misc/asus-laptop.c | 66 |
1 files changed, 60 insertions, 6 deletions
diff --git a/drivers/misc/asus-laptop.c b/drivers/misc/asus-laptop.c index 65c32a95e121..4f9060a2a2f2 100644 --- a/drivers/misc/asus-laptop.c +++ b/drivers/misc/asus-laptop.c | |||
| @@ -30,7 +30,7 @@ | |||
| 30 | * Eric Burghard - LED display support for W1N | 30 | * Eric Burghard - LED display support for W1N |
| 31 | * Josh Green - Light Sens support | 31 | * Josh Green - Light Sens support |
| 32 | * Thomas Tuttle - His first patch for led support was very helpfull | 32 | * Thomas Tuttle - His first patch for led support was very helpfull |
| 33 | * | 33 | * Sam Lin - GPS support |
| 34 | */ | 34 | */ |
| 35 | 35 | ||
| 36 | #include <linux/autoconf.h> | 36 | #include <linux/autoconf.h> |
| @@ -48,7 +48,7 @@ | |||
| 48 | #include <acpi/acpi_bus.h> | 48 | #include <acpi/acpi_bus.h> |
| 49 | #include <asm/uaccess.h> | 49 | #include <asm/uaccess.h> |
| 50 | 50 | ||
| 51 | #define ASUS_LAPTOP_VERSION "0.41" | 51 | #define ASUS_LAPTOP_VERSION "0.42" |
| 52 | 52 | ||
| 53 | #define ASUS_HOTK_NAME "Asus Laptop Support" | 53 | #define ASUS_HOTK_NAME "Asus Laptop Support" |
| 54 | #define ASUS_HOTK_CLASS "hotkey" | 54 | #define ASUS_HOTK_CLASS "hotkey" |
| @@ -83,6 +83,7 @@ | |||
| 83 | #define PLED_ON 0x20 //Phone LED | 83 | #define PLED_ON 0x20 //Phone LED |
| 84 | #define GLED_ON 0x40 //Gaming LED | 84 | #define GLED_ON 0x40 //Gaming LED |
| 85 | #define LCD_ON 0x80 //LCD backlight | 85 | #define LCD_ON 0x80 //LCD backlight |
| 86 | #define GPS_ON 0x100 //GPS | ||
| 86 | 87 | ||
| 87 | #define ASUS_LOG ASUS_HOTK_FILE ": " | 88 | #define ASUS_LOG ASUS_HOTK_FILE ": " |
| 88 | #define ASUS_ERR KERN_ERR ASUS_LOG | 89 | #define ASUS_ERR KERN_ERR ASUS_LOG |
| @@ -148,7 +149,7 @@ ASUS_HANDLE(display_set, ASUS_HOTK_PREFIX "SDSP"); | |||
| 148 | ASUS_HANDLE(display_get, "\\_SB.PCI0.P0P1.VGA.GETD", /* A6B, A6K A6R A7D F3JM L4R M6R A3G | 149 | ASUS_HANDLE(display_get, "\\_SB.PCI0.P0P1.VGA.GETD", /* A6B, A6K A6R A7D F3JM L4R M6R A3G |
| 149 | M6A M6V VX-1 V6J V6V W3Z */ | 150 | M6A M6V VX-1 V6J V6V W3Z */ |
| 150 | "\\_SB.PCI0.P0P2.VGA.GETD", /* A3E A4K, A4D A4L A6J A7J A8J Z71V M9V | 151 | "\\_SB.PCI0.P0P2.VGA.GETD", /* A3E A4K, A4D A4L A6J A7J A8J Z71V M9V |
| 151 | S5A M5A z33A W1Jc W2V */ | 152 | S5A M5A z33A W1Jc W2V G1 */ |
| 152 | "\\_SB.PCI0.P0P3.VGA.GETD", /* A6V A6Q */ | 153 | "\\_SB.PCI0.P0P3.VGA.GETD", /* A6V A6Q */ |
| 153 | "\\_SB.PCI0.P0PA.VGA.GETD", /* A6T, A6M */ | 154 | "\\_SB.PCI0.P0PA.VGA.GETD", /* A6T, A6M */ |
| 154 | "\\_SB.PCI0.PCI1.VGAC.NMAP", /* L3C */ | 155 | "\\_SB.PCI0.PCI1.VGAC.NMAP", /* L3C */ |
| @@ -162,6 +163,12 @@ ASUS_HANDLE(display_get, "\\_SB.PCI0.P0P1.VGA.GETD", /* A6B, A6K A6R A7D F3JM L | |||
| 162 | ASUS_HANDLE(ls_switch, ASUS_HOTK_PREFIX "ALSC"); /* Z71A Z71V */ | 163 | ASUS_HANDLE(ls_switch, ASUS_HOTK_PREFIX "ALSC"); /* Z71A Z71V */ |
| 163 | ASUS_HANDLE(ls_level, ASUS_HOTK_PREFIX "ALSL"); /* Z71A Z71V */ | 164 | ASUS_HANDLE(ls_level, ASUS_HOTK_PREFIX "ALSL"); /* Z71A Z71V */ |
| 164 | 165 | ||
| 166 | /* GPS */ | ||
| 167 | /* R2H use different handle for GPS on/off */ | ||
| 168 | ASUS_HANDLE(gps_on, ASUS_HOTK_PREFIX "SDON"); /* R2H */ | ||
| 169 | ASUS_HANDLE(gps_off, ASUS_HOTK_PREFIX "SDOF"); /* R2H */ | ||
| 170 | ASUS_HANDLE(gps_status, ASUS_HOTK_PREFIX "GPST"); | ||
| 171 | |||
| 165 | /* | 172 | /* |
| 166 | * This is the main structure, we can use it to store anything interesting | 173 | * This is the main structure, we can use it to store anything interesting |
| 167 | * about the hotk device | 174 | * about the hotk device |
| @@ -278,12 +285,28 @@ static int read_wireless_status(int mask) | |||
| 278 | return (hotk->status & mask) ? 1 : 0; | 285 | return (hotk->status & mask) ? 1 : 0; |
| 279 | } | 286 | } |
| 280 | 287 | ||
| 288 | static int read_gps_status(void) | ||
| 289 | { | ||
| 290 | ulong status; | ||
| 291 | acpi_status rv = AE_OK; | ||
| 292 | |||
| 293 | rv = acpi_evaluate_integer(gps_status_handle, NULL, NULL, &status); | ||
| 294 | if (ACPI_FAILURE(rv)) | ||
| 295 | printk(ASUS_WARNING "Error reading GPS status\n"); | ||
| 296 | else | ||
| 297 | return status ? 1 : 0; | ||
| 298 | |||
| 299 | return (hotk->status & GPS_ON) ? 1 : 0; | ||
| 300 | } | ||
| 301 | |||
| 281 | /* Generic LED functions */ | 302 | /* Generic LED functions */ |
| 282 | static int read_status(int mask) | 303 | static int read_status(int mask) |
| 283 | { | 304 | { |
| 284 | /* There is a special method for both wireless devices */ | 305 | /* There is a special method for both wireless devices */ |
| 285 | if (mask == BT_ON || mask == WL_ON) | 306 | if (mask == BT_ON || mask == WL_ON) |
| 286 | return read_wireless_status(mask); | 307 | return read_wireless_status(mask); |
| 308 | else if (mask == GPS_ON) | ||
| 309 | return read_gps_status(); | ||
| 287 | 310 | ||
| 288 | return (hotk->status & mask) ? 1 : 0; | 311 | return (hotk->status & mask) ? 1 : 0; |
| 289 | } | 312 | } |
| @@ -299,6 +322,10 @@ static void write_status(acpi_handle handle, int out, int mask) | |||
| 299 | case GLED_ON: | 322 | case GLED_ON: |
| 300 | out = (out & 0x1) + 1; | 323 | out = (out & 0x1) + 1; |
| 301 | break; | 324 | break; |
| 325 | case GPS_ON: | ||
| 326 | handle = (out) ? gps_on_handle : gps_off_handle; | ||
| 327 | out = 0x02; | ||
| 328 | break; | ||
| 302 | default: | 329 | default: |
| 303 | out &= 0x1; | 330 | out &= 0x1; |
| 304 | break; | 331 | break; |
| @@ -667,6 +694,21 @@ static ssize_t store_lslvl(struct device *dev, struct device_attribute *attr, | |||
| 667 | return rv; | 694 | return rv; |
| 668 | } | 695 | } |
| 669 | 696 | ||
| 697 | /* | ||
| 698 | * GPS | ||
| 699 | */ | ||
| 700 | static ssize_t show_gps(struct device *dev, | ||
| 701 | struct device_attribute *attr, char *buf) | ||
| 702 | { | ||
| 703 | return sprintf(buf, "%d\n", read_status(GPS_ON)); | ||
| 704 | } | ||
| 705 | |||
| 706 | static ssize_t store_gps(struct device *dev, struct device_attribute *attr, | ||
| 707 | const char *buf, size_t count) | ||
| 708 | { | ||
| 709 | return store_status(buf, count, NULL, GPS_ON); | ||
| 710 | } | ||
| 711 | |||
| 670 | static void asus_hotk_notify(acpi_handle handle, u32 event, void *data) | 712 | static void asus_hotk_notify(acpi_handle handle, u32 event, void *data) |
| 671 | { | 713 | { |
| 672 | /* TODO Find a better way to handle events count. */ | 714 | /* TODO Find a better way to handle events count. */ |
| @@ -715,6 +757,7 @@ static ASUS_CREATE_DEVICE_ATTR(display); | |||
| 715 | static ASUS_CREATE_DEVICE_ATTR(ledd); | 757 | static ASUS_CREATE_DEVICE_ATTR(ledd); |
| 716 | static ASUS_CREATE_DEVICE_ATTR(ls_switch); | 758 | static ASUS_CREATE_DEVICE_ATTR(ls_switch); |
| 717 | static ASUS_CREATE_DEVICE_ATTR(ls_level); | 759 | static ASUS_CREATE_DEVICE_ATTR(ls_level); |
| 760 | static ASUS_CREATE_DEVICE_ATTR(gps); | ||
| 718 | 761 | ||
| 719 | static struct attribute *asuspf_attributes[] = { | 762 | static struct attribute *asuspf_attributes[] = { |
| 720 | &dev_attr_infos.attr, | 763 | &dev_attr_infos.attr, |
| @@ -724,6 +767,7 @@ static struct attribute *asuspf_attributes[] = { | |||
| 724 | &dev_attr_ledd.attr, | 767 | &dev_attr_ledd.attr, |
| 725 | &dev_attr_ls_switch.attr, | 768 | &dev_attr_ls_switch.attr, |
| 726 | &dev_attr_ls_level.attr, | 769 | &dev_attr_ls_level.attr, |
| 770 | &dev_attr_gps.attr, | ||
| 727 | NULL | 771 | NULL |
| 728 | }; | 772 | }; |
| 729 | 773 | ||
| @@ -763,6 +807,9 @@ static void asus_hotk_add_fs(void) | |||
| 763 | ASUS_SET_DEVICE_ATTR(ls_level, 0644, show_lslvl, store_lslvl); | 807 | ASUS_SET_DEVICE_ATTR(ls_level, 0644, show_lslvl, store_lslvl); |
| 764 | ASUS_SET_DEVICE_ATTR(ls_switch, 0644, show_lssw, store_lssw); | 808 | ASUS_SET_DEVICE_ATTR(ls_switch, 0644, show_lssw, store_lssw); |
| 765 | } | 809 | } |
| 810 | |||
| 811 | if (gps_status_handle && gps_on_handle && gps_off_handle) | ||
| 812 | ASUS_SET_DEVICE_ATTR(gps, 0644, show_gps, store_gps); | ||
| 766 | } | 813 | } |
| 767 | 814 | ||
| 768 | static int asus_handle_init(char *name, acpi_handle * handle, | 815 | static int asus_handle_init(char *name, acpi_handle * handle, |
| @@ -890,9 +937,13 @@ static int asus_hotk_get_info(void) | |||
| 890 | 937 | ||
| 891 | /* There is a lot of models with "ALSL", but a few get | 938 | /* There is a lot of models with "ALSL", but a few get |
| 892 | a real light sens, so we need to check it. */ | 939 | a real light sens, so we need to check it. */ |
| 893 | if (ASUS_HANDLE_INIT(ls_switch)) | 940 | if (!ASUS_HANDLE_INIT(ls_switch)) |
| 894 | ASUS_HANDLE_INIT(ls_level); | 941 | ASUS_HANDLE_INIT(ls_level); |
| 895 | 942 | ||
| 943 | ASUS_HANDLE_INIT(gps_on); | ||
| 944 | ASUS_HANDLE_INIT(gps_off); | ||
| 945 | ASUS_HANDLE_INIT(gps_status); | ||
| 946 | |||
| 896 | kfree(model); | 947 | kfree(model); |
| 897 | 948 | ||
| 898 | return AE_OK; | 949 | return AE_OK; |
| @@ -950,7 +1001,7 @@ static int asus_hotk_add(struct acpi_device *device) | |||
| 950 | * We install the handler, it will receive the hotk in parameter, so, we | 1001 | * We install the handler, it will receive the hotk in parameter, so, we |
| 951 | * could add other data to the hotk struct | 1002 | * could add other data to the hotk struct |
| 952 | */ | 1003 | */ |
| 953 | status = acpi_install_notify_handler(hotk->handle, ACPI_SYSTEM_NOTIFY, | 1004 | status = acpi_install_notify_handler(hotk->handle, ACPI_ALL_NOTIFY, |
| 954 | asus_hotk_notify, hotk); | 1005 | asus_hotk_notify, hotk); |
| 955 | if (ACPI_FAILURE(status)) | 1006 | if (ACPI_FAILURE(status)) |
| 956 | printk(ASUS_ERR "Error installing notify handler\n"); | 1007 | printk(ASUS_ERR "Error installing notify handler\n"); |
| @@ -981,6 +1032,9 @@ static int asus_hotk_add(struct acpi_device *device) | |||
| 981 | if (ls_level_handle) | 1032 | if (ls_level_handle) |
| 982 | set_light_sens_level(hotk->light_level); | 1033 | set_light_sens_level(hotk->light_level); |
| 983 | 1034 | ||
| 1035 | /* GPS is on by default */ | ||
| 1036 | write_status(NULL, 1, GPS_ON); | ||
| 1037 | |||
| 984 | end: | 1038 | end: |
| 985 | if (result) { | 1039 | if (result) { |
| 986 | kfree(hotk->name); | 1040 | kfree(hotk->name); |
| @@ -997,7 +1051,7 @@ static int asus_hotk_remove(struct acpi_device *device, int type) | |||
| 997 | if (!device || !acpi_driver_data(device)) | 1051 | if (!device || !acpi_driver_data(device)) |
| 998 | return -EINVAL; | 1052 | return -EINVAL; |
| 999 | 1053 | ||
| 1000 | status = acpi_remove_notify_handler(hotk->handle, ACPI_SYSTEM_NOTIFY, | 1054 | status = acpi_remove_notify_handler(hotk->handle, ACPI_ALL_NOTIFY, |
| 1001 | asus_hotk_notify); | 1055 | asus_hotk_notify); |
| 1002 | if (ACPI_FAILURE(status)) | 1056 | if (ACPI_FAILURE(status)) |
| 1003 | printk(ASUS_ERR "Error removing notify handler\n"); | 1057 | printk(ASUS_ERR "Error removing notify handler\n"); |
