diff options
| -rw-r--r-- | drivers/misc/asus-laptop.c | 55 |
1 files changed, 54 insertions, 1 deletions
diff --git a/drivers/misc/asus-laptop.c b/drivers/misc/asus-laptop.c index dfec565ffa82..f1bab721ff55 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> |
| @@ -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 |
| @@ -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,27 @@ 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 | ulong status; | ||
| 290 | acpi_status rv = AE_OK; | ||
| 291 | |||
| 292 | rv = acpi_evaluate_integer(gps_status_handle, NULL, NULL, &status); | ||
| 293 | if (ACPI_FAILURE(rv)) | ||
| 294 | printk(ASUS_WARNING "Error reading GPS status\n"); | ||
| 295 | else | ||
| 296 | return status ? 1 : 0; | ||
| 297 | |||
| 298 | return (hotk->status & GPS_ON) ? 1 : 0; | ||
| 299 | } | ||
| 300 | |||
| 281 | /* Generic LED functions */ | 301 | /* Generic LED functions */ |
| 282 | static int read_status(int mask) | 302 | static int read_status(int mask) |
| 283 | { | 303 | { |
| 284 | /* There is a special method for both wireless devices */ | 304 | /* There is a special method for both wireless devices */ |
| 285 | if (mask == BT_ON || mask == WL_ON) | 305 | if (mask == BT_ON || mask == WL_ON) |
| 286 | return read_wireless_status(mask); | 306 | return read_wireless_status(mask); |
| 307 | else if(mask == GPS_ON) | ||
| 308 | return read_gps_status(); | ||
| 287 | 309 | ||
| 288 | return (hotk->status & mask) ? 1 : 0; | 310 | return (hotk->status & mask) ? 1 : 0; |
| 289 | } | 311 | } |
| @@ -299,6 +321,10 @@ static void write_status(acpi_handle handle, int out, int mask) | |||
| 299 | case GLED_ON: | 321 | case GLED_ON: |
| 300 | out = (out & 0x1) + 1; | 322 | out = (out & 0x1) + 1; |
| 301 | break; | 323 | break; |
| 324 | case GPS_ON: | ||
| 325 | handle = (out) ? gps_on_handle : gps_off_handle; | ||
| 326 | out = 0x02; | ||
| 327 | break; | ||
| 302 | default: | 328 | default: |
| 303 | out &= 0x1; | 329 | out &= 0x1; |
| 304 | break; | 330 | break; |
| @@ -667,6 +693,21 @@ static ssize_t store_lslvl(struct device *dev, struct device_attribute *attr, | |||
| 667 | return rv; | 693 | return rv; |
| 668 | } | 694 | } |
| 669 | 695 | ||
| 696 | /* | ||
| 697 | * GPS | ||
| 698 | */ | ||
| 699 | static ssize_t show_gps(struct device *dev, | ||
| 700 | struct device_attribute *attr, char *buf) | ||
| 701 | { | ||
| 702 | return sprintf(buf, "%d\n", read_status(GPS_ON)); | ||
| 703 | } | ||
| 704 | |||
| 705 | static ssize_t store_gps(struct device *dev, struct device_attribute *attr, | ||
| 706 | const char *buf, size_t count) | ||
| 707 | { | ||
| 708 | return store_status(buf, count, NULL, GPS_ON); | ||
| 709 | } | ||
| 710 | |||
| 670 | static void asus_hotk_notify(acpi_handle handle, u32 event, void *data) | 711 | static void asus_hotk_notify(acpi_handle handle, u32 event, void *data) |
| 671 | { | 712 | { |
| 672 | /* TODO Find a better way to handle events count. */ | 713 | /* TODO Find a better way to handle events count. */ |
| @@ -715,6 +756,7 @@ static ASUS_CREATE_DEVICE_ATTR(display); | |||
| 715 | static ASUS_CREATE_DEVICE_ATTR(ledd); | 756 | static ASUS_CREATE_DEVICE_ATTR(ledd); |
| 716 | static ASUS_CREATE_DEVICE_ATTR(ls_switch); | 757 | static ASUS_CREATE_DEVICE_ATTR(ls_switch); |
| 717 | static ASUS_CREATE_DEVICE_ATTR(ls_level); | 758 | static ASUS_CREATE_DEVICE_ATTR(ls_level); |
| 759 | static ASUS_CREATE_DEVICE_ATTR(gps); | ||
| 718 | 760 | ||
| 719 | static struct attribute *asuspf_attributes[] = { | 761 | static struct attribute *asuspf_attributes[] = { |
| 720 | &dev_attr_infos.attr, | 762 | &dev_attr_infos.attr, |
| @@ -724,6 +766,7 @@ static struct attribute *asuspf_attributes[] = { | |||
| 724 | &dev_attr_ledd.attr, | 766 | &dev_attr_ledd.attr, |
| 725 | &dev_attr_ls_switch.attr, | 767 | &dev_attr_ls_switch.attr, |
| 726 | &dev_attr_ls_level.attr, | 768 | &dev_attr_ls_level.attr, |
| 769 | &dev_attr_gps.attr, | ||
| 727 | NULL | 770 | NULL |
| 728 | }; | 771 | }; |
| 729 | 772 | ||
| @@ -763,6 +806,9 @@ static void asus_hotk_add_fs(void) | |||
| 763 | ASUS_SET_DEVICE_ATTR(ls_level, 0644, show_lslvl, store_lslvl); | 806 | ASUS_SET_DEVICE_ATTR(ls_level, 0644, show_lslvl, store_lslvl); |
| 764 | ASUS_SET_DEVICE_ATTR(ls_switch, 0644, show_lssw, store_lssw); | 807 | ASUS_SET_DEVICE_ATTR(ls_switch, 0644, show_lssw, store_lssw); |
| 765 | } | 808 | } |
| 809 | |||
| 810 | if(gps_status_handle && gps_on_handle && gps_off_handle) | ||
| 811 | ASUS_SET_DEVICE_ATTR(gps, 0644, show_gps, store_gps); | ||
| 766 | } | 812 | } |
| 767 | 813 | ||
| 768 | static int asus_handle_init(char *name, acpi_handle * handle, | 814 | static int asus_handle_init(char *name, acpi_handle * handle, |
| @@ -893,6 +939,10 @@ static int asus_hotk_get_info(void) | |||
| 893 | if (ASUS_HANDLE_INIT(ls_switch)) | 939 | if (ASUS_HANDLE_INIT(ls_switch)) |
| 894 | ASUS_HANDLE_INIT(ls_level); | 940 | ASUS_HANDLE_INIT(ls_level); |
| 895 | 941 | ||
| 942 | ASUS_HANDLE_INIT(gps_on); | ||
| 943 | ASUS_HANDLE_INIT(gps_off); | ||
| 944 | ASUS_HANDLE_INIT(gps_status); | ||
| 945 | |||
| 896 | kfree(model); | 946 | kfree(model); |
| 897 | 947 | ||
| 898 | return AE_OK; | 948 | return AE_OK; |
| @@ -981,6 +1031,9 @@ static int asus_hotk_add(struct acpi_device *device) | |||
| 981 | if (ls_level_handle) | 1031 | if (ls_level_handle) |
| 982 | set_light_sens_level(hotk->light_level); | 1032 | set_light_sens_level(hotk->light_level); |
| 983 | 1033 | ||
| 1034 | /* GPS is on by default */ | ||
| 1035 | write_status(NULL, 1, GPS_ON); | ||
| 1036 | |||
| 984 | end: | 1037 | end: |
| 985 | if (result) { | 1038 | if (result) { |
| 986 | kfree(hotk->name); | 1039 | kfree(hotk->name); |
