aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/platform/x86/asus-laptop.c362
1 files changed, 209 insertions, 153 deletions
diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c
index 4ff30ca4df12..58a4864096d9 100644
--- a/drivers/platform/x86/asus-laptop.c
+++ b/drivers/platform/x86/asus-laptop.c
@@ -196,6 +196,34 @@ ASUS_HANDLE(kled_set, ASUS_LAPTOP_PREFIX "SLKB");
196ASUS_HANDLE(kled_get, ASUS_LAPTOP_PREFIX "GLKB"); 196ASUS_HANDLE(kled_get, ASUS_LAPTOP_PREFIX "GLKB");
197 197
198/* 198/*
199 * Define a specific led structure to keep the main structure clean
200 */
201#define ASUS_DEFINE_LED(object) \
202 int object##_wk; \
203 struct work_struct object##_work; \
204 struct led_classdev object;
205
206
207#define led_to_asus(led_cdev, led) \
208 container_of(container_of(led_cdev, struct asus_laptop_leds, \
209 led), \
210 struct asus_laptop, leds)
211#define work_to_asus(work, led) \
212 container_of(container_of(work, struct asus_laptop_leds, \
213 led##_work), \
214 struct asus_laptop, leds)
215
216struct asus_laptop_leds {
217 ASUS_DEFINE_LED(mled)
218 ASUS_DEFINE_LED(tled)
219 ASUS_DEFINE_LED(rled)
220 ASUS_DEFINE_LED(pled)
221 ASUS_DEFINE_LED(gled)
222 ASUS_DEFINE_LED(kled)
223 struct workqueue_struct *workqueue;
224};
225
226/*
199 * This is the main structure, we can use it to store anything interesting 227 * This is the main structure, we can use it to store anything interesting
200 * about the hotk device 228 * about the hotk device
201 */ 229 */
@@ -206,7 +234,11 @@ struct asus_laptop {
206 struct platform_device *platform_device; 234 struct platform_device *platform_device;
207 struct acpi_device *device; /* the device we are in */ 235 struct acpi_device *device; /* the device we are in */
208 struct backlight_device *backlight_device; 236 struct backlight_device *backlight_device;
237
209 struct input_dev *inputdev; 238 struct input_dev *inputdev;
239 struct key_entry *keymap;
240
241 struct asus_laptop_leds leds;
210 242
211 acpi_handle handle; /* the handle of the hotk device */ 243 acpi_handle handle; /* the handle of the hotk device */
212 char status; /* status of the hotk, for LEDs, ... */ 244 char status; /* status of the hotk, for LEDs, ... */
@@ -217,10 +249,6 @@ struct asus_laptop {
217 u16 *keycode_map; 249 u16 *keycode_map;
218}; 250};
219 251
220static struct asus_laptop *asus;
221
222static struct workqueue_struct *led_workqueue;
223
224/* 252/*
225 * The backlight class declaration 253 * The backlight class declaration
226 */ 254 */
@@ -237,8 +265,6 @@ static struct backlight_ops asusbl_ops = {
237 static enum led_brightness object##_led_get( \ 265 static enum led_brightness object##_led_get( \
238 struct led_classdev *led_cdev); \ 266 struct led_classdev *led_cdev); \
239 static void object##_led_update(struct work_struct *ignored); \ 267 static void object##_led_update(struct work_struct *ignored); \
240 static int object##_led_wk; \
241 static DECLARE_WORK(object##_led_work, object##_led_update); \
242 static struct led_classdev object##_led = { \ 268 static struct led_classdev object##_led = { \
243 .name = "asus::" ledname, \ 269 .name = "asus::" ledname, \
244 .brightness_set = object##_led_set, \ 270 .brightness_set = object##_led_set, \
@@ -261,7 +287,7 @@ struct key_entry {
261 287
262enum { KE_KEY, KE_END }; 288enum { KE_KEY, KE_END };
263 289
264static struct key_entry asus_keymap[] = { 290static const struct key_entry asus_keymap[] = {
265 {KE_KEY, 0x02, KEY_SCREENLOCK}, 291 {KE_KEY, 0x02, KEY_SCREENLOCK},
266 {KE_KEY, 0x05, KEY_WLAN}, 292 {KE_KEY, 0x05, KEY_WLAN},
267 {KE_KEY, 0x08, KEY_F13}, 293 {KE_KEY, 0x08, KEY_F13},
@@ -333,7 +359,7 @@ static int write_acpi_int(acpi_handle handle, const char *method, int val)
333 return write_acpi_int_ret(handle, method, val, NULL); 359 return write_acpi_int_ret(handle, method, val, NULL);
334} 360}
335 361
336static int read_wireless_status(int mask) 362static int read_wireless_status(struct asus_laptop *asus, int mask)
337{ 363{
338 unsigned long long status; 364 unsigned long long status;
339 acpi_status rv = AE_OK; 365 acpi_status rv = AE_OK;
@@ -350,7 +376,7 @@ static int read_wireless_status(int mask)
350 return (asus->status & mask) ? 1 : 0; 376 return (asus->status & mask) ? 1 : 0;
351} 377}
352 378
353static int read_gps_status(void) 379static int read_gps_status(struct asus_laptop *asus)
354{ 380{
355 unsigned long long status; 381 unsigned long long status;
356 acpi_status rv = AE_OK; 382 acpi_status rv = AE_OK;
@@ -365,18 +391,19 @@ static int read_gps_status(void)
365} 391}
366 392
367/* Generic LED functions */ 393/* Generic LED functions */
368static int read_status(int mask) 394static int read_status(struct asus_laptop *asus, int mask)
369{ 395{
370 /* There is a special method for both wireless devices */ 396 /* There is a special method for both wireless devices */
371 if (mask == BT_ON || mask == WL_ON) 397 if (mask == BT_ON || mask == WL_ON)
372 return read_wireless_status(mask); 398 return read_wireless_status(asus, mask);
373 else if (mask == GPS_ON) 399 else if (mask == GPS_ON)
374 return read_gps_status(); 400 return read_gps_status(asus);
375 401
376 return (asus->status & mask) ? 1 : 0; 402 return (asus->status & mask) ? 1 : 0;
377} 403}
378 404
379static void write_status(acpi_handle handle, int out, int mask) 405static void write_status(struct asus_laptop *asus, acpi_handle handle,
406 int out, int mask)
380{ 407{
381 asus->status = (out) ? (asus->status | mask) : (asus->status & ~mask); 408 asus->status = (out) ? (asus->status | mask) : (asus->status & ~mask);
382 409
@@ -405,13 +432,19 @@ static void write_status(acpi_handle handle, int out, int mask)
405 static void object##_led_set(struct led_classdev *led_cdev, \ 432 static void object##_led_set(struct led_classdev *led_cdev, \
406 enum led_brightness value) \ 433 enum led_brightness value) \
407 { \ 434 { \
408 object##_led_wk = (value > 0) ? 1 : 0; \ 435 struct asus_laptop *asus = \
409 queue_work(led_workqueue, &object##_led_work); \ 436 led_to_asus(led_cdev, object); \
437 \
438 asus->leds.object##_wk = (value > 0) ? 1 : 0; \
439 queue_work(asus->leds.workqueue, \
440 &asus->leds.object##_work); \
410 } \ 441 } \
411 static void object##_led_update(struct work_struct *ignored) \ 442 static void object##_led_update(struct work_struct *work) \
412 { \ 443 { \
413 int value = object##_led_wk; \ 444 struct asus_laptop *asus = work_to_asus(work, object); \
414 write_status(object##_set_handle, value, (mask)); \ 445 \
446 int value = asus->leds.object##_wk; \
447 write_status(asus, object##_set_handle, value, (mask)); \
415 } \ 448 } \
416 static enum led_brightness object##_led_get( \ 449 static enum led_brightness object##_led_get( \
417 struct led_classdev *led_cdev) \ 450 struct led_classdev *led_cdev) \
@@ -448,7 +481,7 @@ static int get_kled_lvl(void)
448 return kblv; 481 return kblv;
449} 482}
450 483
451static int set_kled_lvl(int kblv) 484static int set_kled_lvl(struct asus_laptop *asus, int kblv)
452{ 485{
453 if (kblv > 0) 486 if (kblv > 0)
454 kblv = (1 << 7) | (kblv & 0x7F); 487 kblv = (1 << 7) | (kblv & 0x7F);
@@ -465,13 +498,17 @@ static int set_kled_lvl(int kblv)
465static void kled_led_set(struct led_classdev *led_cdev, 498static void kled_led_set(struct led_classdev *led_cdev,
466 enum led_brightness value) 499 enum led_brightness value)
467{ 500{
468 kled_led_wk = value; 501 struct asus_laptop *asus = led_to_asus(led_cdev, kled);
469 queue_work(led_workqueue, &kled_led_work); 502
503 asus->leds.kled_wk = value;
504 queue_work(asus->leds.workqueue, &asus->leds.kled_work);
470} 505}
471 506
472static void kled_led_update(struct work_struct *ignored) 507static void kled_led_update(struct work_struct *work)
473{ 508{
474 set_kled_lvl(kled_led_wk); 509 struct asus_laptop *asus = work_to_asus(work, kled);
510
511 set_kled_lvl(asus, asus->leds.kled_wk);
475} 512}
476 513
477static enum led_brightness kled_led_get(struct led_classdev *led_cdev) 514static enum led_brightness kled_led_get(struct led_classdev *led_cdev)
@@ -479,19 +516,19 @@ static enum led_brightness kled_led_get(struct led_classdev *led_cdev)
479 return get_kled_lvl(); 516 return get_kled_lvl();
480} 517}
481 518
482static int get_lcd_state(void) 519static int get_lcd_state(struct asus_laptop *asus)
483{ 520{
484 return read_status(LCD_ON); 521 return read_status(asus, LCD_ON);
485} 522}
486 523
487static int set_lcd_state(int value) 524static int set_lcd_state(struct asus_laptop *asus, int value)
488{ 525{
489 int lcd = 0; 526 int lcd = 0;
490 acpi_status status = 0; 527 acpi_status status = 0;
491 528
492 lcd = value ? 1 : 0; 529 lcd = value ? 1 : 0;
493 530
494 if (lcd == get_lcd_state()) 531 if (lcd == get_lcd_state(asus))
495 return 0; 532 return 0;
496 533
497 if (lcd_switch_handle) { 534 if (lcd_switch_handle) {
@@ -502,11 +539,11 @@ static int set_lcd_state(int value)
502 pr_warning("Error switching LCD\n"); 539 pr_warning("Error switching LCD\n");
503 } 540 }
504 541
505 write_status(NULL, lcd, LCD_ON); 542 write_status(asus, NULL, lcd, LCD_ON);
506 return 0; 543 return 0;
507} 544}
508 545
509static void lcd_blank(int blank) 546static void lcd_blank(struct asus_laptop *asus, int blank)
510{ 547{
511 struct backlight_device *bd = asus->backlight_device; 548 struct backlight_device *bd = asus->backlight_device;
512 549
@@ -539,6 +576,7 @@ static int set_brightness(struct backlight_device *bd, int value)
539 576
540static int update_bl_status(struct backlight_device *bd) 577static int update_bl_status(struct backlight_device *bd)
541{ 578{
579 struct asus_laptop *asus = bl_get_data(bd);
542 int rv; 580 int rv;
543 int value = bd->props.brightness; 581 int value = bd->props.brightness;
544 582
@@ -547,7 +585,7 @@ static int update_bl_status(struct backlight_device *bd)
547 return rv; 585 return rv;
548 586
549 value = (bd->props.power == FB_BLANK_UNBLANK) ? 1 : 0; 587 value = (bd->props.power == FB_BLANK_UNBLANK) ? 1 : 0;
550 return set_lcd_state(value); 588 return set_lcd_state(asus, value);
551} 589}
552 590
553/* 591/*
@@ -562,6 +600,7 @@ static int update_bl_status(struct backlight_device *bd)
562static ssize_t show_infos(struct device *dev, 600static ssize_t show_infos(struct device *dev,
563 struct device_attribute *attr, char *page) 601 struct device_attribute *attr, char *page)
564{ 602{
603 struct asus_laptop *asus = dev_get_drvdata(dev);
565 int len = 0; 604 int len = 0;
566 unsigned long long temp; 605 unsigned long long temp;
567 char buf[16]; /* enough for all info */ 606 char buf[16]; /* enough for all info */
@@ -638,7 +677,8 @@ static int parse_arg(const char *buf, unsigned long count, int *val)
638 return count; 677 return count;
639} 678}
640 679
641static ssize_t store_status(const char *buf, size_t count, 680static ssize_t store_status(struct asus_laptop *asus,
681 const char *buf, size_t count,
642 acpi_handle handle, int mask) 682 acpi_handle handle, int mask)
643{ 683{
644 int rv, value; 684 int rv, value;
@@ -648,7 +688,7 @@ static ssize_t store_status(const char *buf, size_t count,
648 if (rv > 0) 688 if (rv > 0)
649 out = value ? 1 : 0; 689 out = value ? 1 : 0;
650 690
651 write_status(handle, out, mask); 691 write_status(asus, handle, out, mask);
652 692
653 return rv; 693 return rv;
654} 694}
@@ -659,12 +699,15 @@ static ssize_t store_status(const char *buf, size_t count,
659static ssize_t show_ledd(struct device *dev, 699static ssize_t show_ledd(struct device *dev,
660 struct device_attribute *attr, char *buf) 700 struct device_attribute *attr, char *buf)
661{ 701{
702 struct asus_laptop *asus = dev_get_drvdata(dev);
703
662 return sprintf(buf, "0x%08x\n", asus->ledd_status); 704 return sprintf(buf, "0x%08x\n", asus->ledd_status);
663} 705}
664 706
665static ssize_t store_ledd(struct device *dev, struct device_attribute *attr, 707static ssize_t store_ledd(struct device *dev, struct device_attribute *attr,
666 const char *buf, size_t count) 708 const char *buf, size_t count)
667{ 709{
710 struct asus_laptop *asus = dev_get_drvdata(dev);
668 int rv, value; 711 int rv, value;
669 712
670 rv = parse_arg(buf, count, &value); 713 rv = parse_arg(buf, count, &value);
@@ -683,13 +726,17 @@ static ssize_t store_ledd(struct device *dev, struct device_attribute *attr,
683static ssize_t show_wlan(struct device *dev, 726static ssize_t show_wlan(struct device *dev,
684 struct device_attribute *attr, char *buf) 727 struct device_attribute *attr, char *buf)
685{ 728{
686 return sprintf(buf, "%d\n", read_status(WL_ON)); 729 struct asus_laptop *asus = dev_get_drvdata(dev);
730
731 return sprintf(buf, "%d\n", read_status(asus, WL_ON));
687} 732}
688 733
689static ssize_t store_wlan(struct device *dev, struct device_attribute *attr, 734static ssize_t store_wlan(struct device *dev, struct device_attribute *attr,
690 const char *buf, size_t count) 735 const char *buf, size_t count)
691{ 736{
692 return store_status(buf, count, wl_switch_handle, WL_ON); 737 struct asus_laptop *asus = dev_get_drvdata(dev);
738
739 return store_status(asus, buf, count, wl_switch_handle, WL_ON);
693} 740}
694 741
695/* 742/*
@@ -698,20 +745,24 @@ static ssize_t store_wlan(struct device *dev, struct device_attribute *attr,
698static ssize_t show_bluetooth(struct device *dev, 745static ssize_t show_bluetooth(struct device *dev,
699 struct device_attribute *attr, char *buf) 746 struct device_attribute *attr, char *buf)
700{ 747{
701 return sprintf(buf, "%d\n", read_status(BT_ON)); 748 struct asus_laptop *asus = dev_get_drvdata(dev);
749
750 return sprintf(buf, "%d\n", read_status(asus, BT_ON));
702} 751}
703 752
704static ssize_t store_bluetooth(struct device *dev, 753static ssize_t store_bluetooth(struct device *dev,
705 struct device_attribute *attr, const char *buf, 754 struct device_attribute *attr, const char *buf,
706 size_t count) 755 size_t count)
707{ 756{
708 return store_status(buf, count, bt_switch_handle, BT_ON); 757 struct asus_laptop *asus = dev_get_drvdata(dev);
758
759 return store_status(asus, buf, count, bt_switch_handle, BT_ON);
709} 760}
710 761
711/* 762/*
712 * Display 763 * Display
713 */ 764 */
714static void set_display(int value) 765static void set_display(struct asus_laptop *asus, int value)
715{ 766{
716 /* no sanity check needed for now */ 767 /* no sanity check needed for now */
717 if (write_acpi_int(display_set_handle, NULL, value)) 768 if (write_acpi_int(display_set_handle, NULL, value))
@@ -719,7 +770,7 @@ static void set_display(int value)
719 return; 770 return;
720} 771}
721 772
722static int read_display(void) 773static int read_display(struct asus_laptop *asus)
723{ 774{
724 unsigned long long value = 0; 775 unsigned long long value = 0;
725 acpi_status rv = AE_OK; 776 acpi_status rv = AE_OK;
@@ -747,7 +798,9 @@ static int read_display(void)
747static ssize_t show_disp(struct device *dev, 798static ssize_t show_disp(struct device *dev,
748 struct device_attribute *attr, char *buf) 799 struct device_attribute *attr, char *buf)
749{ 800{
750 return sprintf(buf, "%d\n", read_display()); 801 struct asus_laptop *asus = dev_get_drvdata(dev);
802
803 return sprintf(buf, "%d\n", read_display(asus));
751} 804}
752 805
753/* 806/*
@@ -760,18 +813,19 @@ static ssize_t show_disp(struct device *dev,
760static ssize_t store_disp(struct device *dev, struct device_attribute *attr, 813static ssize_t store_disp(struct device *dev, struct device_attribute *attr,
761 const char *buf, size_t count) 814 const char *buf, size_t count)
762{ 815{
816 struct asus_laptop *asus = dev_get_drvdata(dev);
763 int rv, value; 817 int rv, value;
764 818
765 rv = parse_arg(buf, count, &value); 819 rv = parse_arg(buf, count, &value);
766 if (rv > 0) 820 if (rv > 0)
767 set_display(value); 821 set_display(asus, value);
768 return rv; 822 return rv;
769} 823}
770 824
771/* 825/*
772 * Light Sens 826 * Light Sens
773 */ 827 */
774static void set_light_sens_switch(int value) 828static void set_light_sens_switch(struct asus_laptop *asus, int value)
775{ 829{
776 if (write_acpi_int(ls_switch_handle, NULL, value)) 830 if (write_acpi_int(ls_switch_handle, NULL, value))
777 pr_warning("Error setting light sensor switch\n"); 831 pr_warning("Error setting light sensor switch\n");
@@ -781,22 +835,25 @@ static void set_light_sens_switch(int value)
781static ssize_t show_lssw(struct device *dev, 835static ssize_t show_lssw(struct device *dev,
782 struct device_attribute *attr, char *buf) 836 struct device_attribute *attr, char *buf)
783{ 837{
838 struct asus_laptop *asus = dev_get_drvdata(dev);
839
784 return sprintf(buf, "%d\n", asus->light_switch); 840 return sprintf(buf, "%d\n", asus->light_switch);
785} 841}
786 842
787static ssize_t store_lssw(struct device *dev, struct device_attribute *attr, 843static ssize_t store_lssw(struct device *dev, struct device_attribute *attr,
788 const char *buf, size_t count) 844 const char *buf, size_t count)
789{ 845{
846 struct asus_laptop *asus = dev_get_drvdata(dev);
790 int rv, value; 847 int rv, value;
791 848
792 rv = parse_arg(buf, count, &value); 849 rv = parse_arg(buf, count, &value);
793 if (rv > 0) 850 if (rv > 0)
794 set_light_sens_switch(value ? 1 : 0); 851 set_light_sens_switch(asus, value ? 1 : 0);
795 852
796 return rv; 853 return rv;
797} 854}
798 855
799static void set_light_sens_level(int value) 856static void set_light_sens_level(struct asus_laptop *asus, int value)
800{ 857{
801 if (write_acpi_int(ls_level_handle, NULL, value)) 858 if (write_acpi_int(ls_level_handle, NULL, value))
802 pr_warning("Error setting light sensor level\n"); 859 pr_warning("Error setting light sensor level\n");
@@ -806,19 +863,22 @@ static void set_light_sens_level(int value)
806static ssize_t show_lslvl(struct device *dev, 863static ssize_t show_lslvl(struct device *dev,
807 struct device_attribute *attr, char *buf) 864 struct device_attribute *attr, char *buf)
808{ 865{
866 struct asus_laptop *asus = dev_get_drvdata(dev);
867
809 return sprintf(buf, "%d\n", asus->light_level); 868 return sprintf(buf, "%d\n", asus->light_level);
810} 869}
811 870
812static ssize_t store_lslvl(struct device *dev, struct device_attribute *attr, 871static ssize_t store_lslvl(struct device *dev, struct device_attribute *attr,
813 const char *buf, size_t count) 872 const char *buf, size_t count)
814{ 873{
874 struct asus_laptop *asus = dev_get_drvdata(dev);
815 int rv, value; 875 int rv, value;
816 876
817 rv = parse_arg(buf, count, &value); 877 rv = parse_arg(buf, count, &value);
818 if (rv > 0) { 878 if (rv > 0) {
819 value = (0 < value) ? ((15 < value) ? 15 : value) : 0; 879 value = (0 < value) ? ((15 < value) ? 15 : value) : 0;
820 /* 0 <= value <= 15 */ 880 /* 0 <= value <= 15 */
821 set_light_sens_level(value); 881 set_light_sens_level(asus, value);
822 } 882 }
823 883
824 return rv; 884 return rv;
@@ -830,34 +890,40 @@ static ssize_t store_lslvl(struct device *dev, struct device_attribute *attr,
830static ssize_t show_gps(struct device *dev, 890static ssize_t show_gps(struct device *dev,
831 struct device_attribute *attr, char *buf) 891 struct device_attribute *attr, char *buf)
832{ 892{
833 return sprintf(buf, "%d\n", read_status(GPS_ON)); 893 struct asus_laptop *asus = dev_get_drvdata(dev);
894
895 return sprintf(buf, "%d\n", read_status(asus, GPS_ON));
834} 896}
835 897
836static ssize_t store_gps(struct device *dev, struct device_attribute *attr, 898static ssize_t store_gps(struct device *dev, struct device_attribute *attr,
837 const char *buf, size_t count) 899 const char *buf, size_t count)
838{ 900{
839 return store_status(buf, count, NULL, GPS_ON); 901 struct asus_laptop *asus = dev_get_drvdata(dev);
902
903 return store_status(asus, buf, count, NULL, GPS_ON);
840} 904}
841 905
842/* 906/*
843 * Hotkey functions 907 * Hotkey functions
844 */ 908 */
845static struct key_entry *asus_get_entry_by_scancode(int code) 909static struct key_entry *asus_get_entry_by_scancode(struct asus_laptop *asus,
910 int code)
846{ 911{
847 struct key_entry *key; 912 struct key_entry *key;
848 913
849 for (key = asus_keymap; key->type != KE_END; key++) 914 for (key = asus->keymap; key->type != KE_END; key++)
850 if (code == key->code) 915 if (code == key->code)
851 return key; 916 return key;
852 917
853 return NULL; 918 return NULL;
854} 919}
855 920
856static struct key_entry *asus_get_entry_by_keycode(int code) 921static struct key_entry *asus_get_entry_by_keycode(struct asus_laptop *asus,
922 int code)
857{ 923{
858 struct key_entry *key; 924 struct key_entry *key;
859 925
860 for (key = asus_keymap; key->type != KE_END; key++) 926 for (key = asus->keymap; key->type != KE_END; key++)
861 if (code == key->keycode && key->type == KE_KEY) 927 if (code == key->keycode && key->type == KE_KEY)
862 return key; 928 return key;
863 929
@@ -866,7 +932,8 @@ static struct key_entry *asus_get_entry_by_keycode(int code)
866 932
867static int asus_getkeycode(struct input_dev *dev, int scancode, int *keycode) 933static int asus_getkeycode(struct input_dev *dev, int scancode, int *keycode)
868{ 934{
869 struct key_entry *key = asus_get_entry_by_scancode(scancode); 935 struct asus_laptop *asus = input_get_drvdata(dev);
936 struct key_entry *key = asus_get_entry_by_scancode(asus, scancode);
870 937
871 if (key && key->type == KE_KEY) { 938 if (key && key->type == KE_KEY) {
872 *keycode = key->keycode; 939 *keycode = key->keycode;
@@ -878,18 +945,19 @@ static int asus_getkeycode(struct input_dev *dev, int scancode, int *keycode)
878 945
879static int asus_setkeycode(struct input_dev *dev, int scancode, int keycode) 946static int asus_setkeycode(struct input_dev *dev, int scancode, int keycode)
880{ 947{
948 struct asus_laptop *asus = input_get_drvdata(dev);
881 struct key_entry *key; 949 struct key_entry *key;
882 int old_keycode; 950 int old_keycode;
883 951
884 if (keycode < 0 || keycode > KEY_MAX) 952 if (keycode < 0 || keycode > KEY_MAX)
885 return -EINVAL; 953 return -EINVAL;
886 954
887 key = asus_get_entry_by_scancode(scancode); 955 key = asus_get_entry_by_scancode(asus, scancode);
888 if (key && key->type == KE_KEY) { 956 if (key && key->type == KE_KEY) {
889 old_keycode = key->keycode; 957 old_keycode = key->keycode;
890 key->keycode = keycode; 958 key->keycode = keycode;
891 set_bit(keycode, dev->keybit); 959 set_bit(keycode, dev->keybit);
892 if (!asus_get_entry_by_keycode(old_keycode)) 960 if (!asus_get_entry_by_keycode(asus, old_keycode))
893 clear_bit(old_keycode, dev->keybit); 961 clear_bit(old_keycode, dev->keybit);
894 return 0; 962 return 0;
895 } 963 }
@@ -899,6 +967,7 @@ static int asus_setkeycode(struct input_dev *dev, int scancode, int keycode)
899 967
900static void asus_acpi_notify(struct acpi_device *device, u32 event) 968static void asus_acpi_notify(struct acpi_device *device, u32 event)
901{ 969{
970 struct asus_laptop *asus = acpi_driver_data(device);
902 static struct key_entry *key; 971 static struct key_entry *key;
903 u16 count; 972 u16 count;
904 973
@@ -907,11 +976,11 @@ static void asus_acpi_notify(struct acpi_device *device, u32 event)
907 * switched 976 * switched
908 */ 977 */
909 if (event == ATKD_LCD_ON) { 978 if (event == ATKD_LCD_ON) {
910 write_status(NULL, 1, LCD_ON); 979 write_status(asus, NULL, 1, LCD_ON);
911 lcd_blank(FB_BLANK_UNBLANK); 980 lcd_blank(asus, FB_BLANK_UNBLANK);
912 } else if (event == ATKD_LCD_OFF) { 981 } else if (event == ATKD_LCD_OFF) {
913 write_status(NULL, 0, LCD_ON); 982 write_status(asus, NULL, 0, LCD_ON);
914 lcd_blank(FB_BLANK_POWERDOWN); 983 lcd_blank(asus, FB_BLANK_POWERDOWN);
915 } 984 }
916 985
917 /* TODO Find a better way to handle events count. */ 986 /* TODO Find a better way to handle events count. */
@@ -922,7 +991,7 @@ static void asus_acpi_notify(struct acpi_device *device, u32 event)
922 count); 991 count);
923 992
924 if (asus->inputdev) { 993 if (asus->inputdev) {
925 key = asus_get_entry_by_scancode(event); 994 key = asus_get_entry_by_scancode(asus, event);
926 if (!key) 995 if (!key)
927 return ; 996 return ;
928 997
@@ -978,13 +1047,14 @@ static struct attribute_group platform_attribute_group = {
978 .attrs = asuspf_attributes 1047 .attrs = asuspf_attributes
979}; 1048};
980 1049
981static int asus_platform_init(void) 1050static int asus_platform_init(struct asus_laptop *asus)
982{ 1051{
983 int result; 1052 int result;
984 1053
985 asus->platform_device = platform_device_alloc(ASUS_LAPTOP_FILE, -1); 1054 asus->platform_device = platform_device_alloc(ASUS_LAPTOP_FILE, -1);
986 if (!asus->platform_device) 1055 if (!asus->platform_device)
987 return -ENOMEM; 1056 return -ENOMEM;
1057 platform_set_drvdata(asus->platform_device, asus);
988 1058
989 result = platform_device_add(asus->platform_device); 1059 result = platform_device_add(asus->platform_device);
990 if (result) 1060 if (result)
@@ -1003,7 +1073,7 @@ fail_platform_device:
1003 return result; 1073 return result;
1004} 1074}
1005 1075
1006static void asus_platform_exit(void) 1076static void asus_platform_exit(struct asus_laptop *asus)
1007{ 1077{
1008 sysfs_remove_group(&asus->platform_device->dev.kobj, 1078 sysfs_remove_group(&asus->platform_device->dev.kobj,
1009 &platform_attribute_group); 1079 &platform_attribute_group);
@@ -1012,12 +1082,12 @@ static void asus_platform_exit(void)
1012 1082
1013static struct platform_driver platform_driver = { 1083static struct platform_driver platform_driver = {
1014 .driver = { 1084 .driver = {
1015 .name = ASUS_LAPTOP_FILE, 1085 .name = ASUS_LAPTOP_FILE,
1016 .owner = THIS_MODULE, 1086 .owner = THIS_MODULE,
1017 } 1087 }
1018}; 1088};
1019 1089
1020static void asus_laptop_add_fs(void) 1090static void asus_laptop_add_fs(struct asus_laptop *asus)
1021{ 1091{
1022 ASUS_SET_DEVICE_ATTR(infos, 0444, show_infos, NULL); 1092 ASUS_SET_DEVICE_ATTR(infos, 0444, show_infos, NULL);
1023 1093
@@ -1187,7 +1257,7 @@ static int asus_laptop_get_info(struct asus_laptop *asus)
1187 return AE_OK; 1257 return AE_OK;
1188} 1258}
1189 1259
1190static int asus_input_init(struct device *dev) 1260static int asus_input_init(struct asus_laptop *asus)
1191{ 1261{
1192 const struct key_entry *key; 1262 const struct key_entry *key;
1193 int result; 1263 int result;
@@ -1198,13 +1268,16 @@ static int asus_input_init(struct device *dev)
1198 return 0; 1268 return 0;
1199 } 1269 }
1200 asus->inputdev->name = "Asus Laptop extra buttons"; 1270 asus->inputdev->name = "Asus Laptop extra buttons";
1201 asus->inputdev->dev.parent = dev; 1271 asus->inputdev->dev.parent = &asus->platform_device->dev;
1202 asus->inputdev->phys = ASUS_LAPTOP_FILE "/input0"; 1272 asus->inputdev->phys = ASUS_LAPTOP_FILE "/input0";
1203 asus->inputdev->id.bustype = BUS_HOST; 1273 asus->inputdev->id.bustype = BUS_HOST;
1204 asus->inputdev->getkeycode = asus_getkeycode; 1274 asus->inputdev->getkeycode = asus_getkeycode;
1205 asus->inputdev->setkeycode = asus_setkeycode; 1275 asus->inputdev->setkeycode = asus_setkeycode;
1276 input_set_drvdata(asus->inputdev, asus);
1206 1277
1207 for (key = asus_keymap; key->type != KE_END; key++) { 1278 asus->keymap = kmemdup(asus_keymap, sizeof(asus_keymap),
1279 GFP_KERNEL);
1280 for (key = asus->keymap; key->type != KE_END; key++) {
1208 switch (key->type) { 1281 switch (key->type) {
1209 case KE_KEY: 1282 case KE_KEY:
1210 set_bit(EV_KEY, asus->inputdev->evbit); 1283 set_bit(EV_KEY, asus->inputdev->evbit);
@@ -1220,40 +1293,44 @@ static int asus_input_init(struct device *dev)
1220 return result; 1293 return result;
1221} 1294}
1222 1295
1223static void asus_backlight_exit(void) 1296static void asus_backlight_exit(struct asus_laptop *asus)
1224{ 1297{
1225 if (asus->backlight_device) 1298 if (asus->backlight_device)
1226 backlight_device_unregister(asus->backlight_device); 1299 backlight_device_unregister(asus->backlight_device);
1227} 1300}
1228 1301
1229#define ASUS_LED_UNREGISTER(object) \ 1302#define ASUS_LED_UNREGISTER(object) \
1230 if (object##_led.dev) \ 1303 if (object##_led.dev) \
1231 led_classdev_unregister(&object##_led) 1304 led_classdev_unregister(&object##_led)
1232 1305
1233static void asus_led_exit(void) 1306static void asus_led_exit(struct asus_laptop *asus)
1234{ 1307{
1235 destroy_workqueue(led_workqueue);
1236 ASUS_LED_UNREGISTER(mled); 1308 ASUS_LED_UNREGISTER(mled);
1237 ASUS_LED_UNREGISTER(tled); 1309 ASUS_LED_UNREGISTER(tled);
1238 ASUS_LED_UNREGISTER(pled); 1310 ASUS_LED_UNREGISTER(pled);
1239 ASUS_LED_UNREGISTER(rled); 1311 ASUS_LED_UNREGISTER(rled);
1240 ASUS_LED_UNREGISTER(gled); 1312 ASUS_LED_UNREGISTER(gled);
1241 ASUS_LED_UNREGISTER(kled); 1313 ASUS_LED_UNREGISTER(kled);
1314 if (asus->leds.workqueue) {
1315 destroy_workqueue(asus->leds.workqueue);
1316 asus->leds.workqueue = NULL;
1317 }
1242} 1318}
1243 1319
1244static void asus_input_exit(void) 1320static void asus_input_exit(struct asus_laptop *asus)
1245{ 1321{
1246 if (asus->inputdev) 1322 if (asus->inputdev)
1247 input_unregister_device(asus->inputdev); 1323 input_unregister_device(asus->inputdev);
1248} 1324}
1249 1325
1250static int asus_backlight_init(struct device *dev) 1326static int asus_backlight_init(struct asus_laptop *asus)
1251{ 1327{
1252 struct backlight_device *bd; 1328 struct backlight_device *bd;
1329 struct device *dev = &asus->platform_device->dev;
1253 1330
1254 if (brightness_set_handle && lcd_switch_handle) { 1331 if (brightness_set_handle && lcd_switch_handle) {
1255 bd = backlight_device_register(ASUS_LAPTOP_FILE, dev, 1332 bd = backlight_device_register(ASUS_LAPTOP_FILE, dev,
1256 NULL, &asusbl_ops); 1333 asus, &asusbl_ops);
1257 if (IS_ERR(bd)) { 1334 if (IS_ERR(bd)) {
1258 pr_err("Could not register asus backlight device\n"); 1335 pr_err("Could not register asus backlight device\n");
1259 asus->backlight_device = NULL; 1336 asus->backlight_device = NULL;
@@ -1270,79 +1347,55 @@ static int asus_backlight_init(struct device *dev)
1270 return 0; 1347 return 0;
1271} 1348}
1272 1349
1273static int asus_led_register(acpi_handle handle, 1350/*
1274 struct led_classdev *ldev, struct device *dev) 1351 * Ugly macro, need to fix that later
1275{ 1352 */
1276 if (!handle) 1353#define ASUS_LED_REGISTER(asus, object, _name, max) \
1277 return 0; 1354 do { \
1278 1355 struct led_classdev *ldev = &asus->leds.object; \
1279 return led_classdev_register(dev, ldev); 1356 if (!object##_set_handle) \
1280} 1357 break ; \
1281 1358 \
1282#define ASUS_LED_REGISTER(object, device) \ 1359 INIT_WORK(&asus->leds.object##_work, object##_led_update); \
1283 asus_led_register(object##_set_handle, &object##_led, device) 1360 ldev->name = "asus::" _name; \
1284 1361 ldev->brightness_set = object##_led_set; \
1285static int asus_led_init(struct device *dev) 1362 ldev->max_brightness = max; \
1363 rv = led_classdev_register(&asus->platform_device->dev, ldev); \
1364 if (rv) \
1365 goto error; \
1366 } while (0)
1367
1368static int asus_led_init(struct asus_laptop *asus)
1286{ 1369{
1287 int rv; 1370 int rv;
1288 1371
1289 rv = ASUS_LED_REGISTER(mled, dev);
1290 if (rv)
1291 goto out;
1292
1293 rv = ASUS_LED_REGISTER(tled, dev);
1294 if (rv)
1295 goto out1;
1296
1297 rv = ASUS_LED_REGISTER(rled, dev);
1298 if (rv)
1299 goto out2;
1300
1301 rv = ASUS_LED_REGISTER(pled, dev);
1302 if (rv)
1303 goto out3;
1304
1305 rv = ASUS_LED_REGISTER(gled, dev);
1306 if (rv)
1307 goto out4;
1308
1309 if (kled_set_handle && kled_get_handle)
1310 rv = ASUS_LED_REGISTER(kled, dev);
1311 if (rv)
1312 goto out5;
1313
1314 /* 1372 /*
1315 * Functions that actually update the LED's are called from a 1373 * Functions that actually update the LED's are called from a
1316 * workqueue. By doing this as separate work rather than when the LED 1374 * workqueue. By doing this as separate work rather than when the LED
1317 * subsystem asks, we avoid messing with the Asus ACPI stuff during a 1375 * subsystem asks, we avoid messing with the Asus ACPI stuff during a
1318 * potentially bad time, such as a timer interrupt. 1376 * potentially bad time, such as a timer interrupt.
1319 */ 1377 */
1320 led_workqueue = create_singlethread_workqueue("led_workqueue"); 1378 asus->leds.workqueue = create_singlethread_workqueue("led_workqueue");
1321 if (!led_workqueue) 1379 if (!asus->leds.workqueue)
1322 goto out6; 1380 return -ENOMEM;
1323 1381
1324 return 0; 1382 ASUS_LED_REGISTER(asus, mled, "mail", 1);
1325out6: 1383 ASUS_LED_REGISTER(asus, tled, "touchpad", 1);
1326 rv = -ENOMEM; 1384 ASUS_LED_REGISTER(asus, rled, "record", 1);
1327 ASUS_LED_UNREGISTER(kled); 1385 ASUS_LED_REGISTER(asus, pled, "phone", 1);
1328out5: 1386 ASUS_LED_REGISTER(asus, gled, "gaming", 1);
1329 ASUS_LED_UNREGISTER(gled); 1387 if (kled_set_handle && kled_get_handle)
1330out4: 1388 ASUS_LED_REGISTER(asus, kled, "kbd_backlight", 3);
1331 ASUS_LED_UNREGISTER(pled); 1389error:
1332out3: 1390 if (rv)
1333 ASUS_LED_UNREGISTER(rled); 1391 asus_led_exit(asus);
1334out2:
1335 ASUS_LED_UNREGISTER(tled);
1336out1:
1337 ASUS_LED_UNREGISTER(mled);
1338out:
1339 return rv; 1392 return rv;
1340} 1393}
1341 1394
1342 1395
1343static bool asus_device_present; 1396static bool asus_device_present;
1344 1397
1345static int __devinit asus_acpi_init(struct acpi_device *device) 1398static int __devinit asus_acpi_init(struct asus_laptop *asus)
1346{ 1399{
1347 int result = 0; 1400 int result = 0;
1348 1401
@@ -1358,22 +1411,22 @@ static int __devinit asus_acpi_init(struct acpi_device *device)
1358 if (result) 1411 if (result)
1359 return result; 1412 return result;
1360 1413
1361 asus_laptop_add_fs(); 1414 asus_laptop_add_fs(asus);
1362 1415
1363 /* WLED and BLED are on by default */ 1416 /* WLED and BLED are on by default */
1364 write_status(bt_switch_handle, 1, BT_ON); 1417 write_status(asus, bt_switch_handle, 1, BT_ON);
1365 write_status(wl_switch_handle, 1, WL_ON); 1418 write_status(asus, wl_switch_handle, 1, WL_ON);
1366 1419
1367 /* If the h/w switch is off, we need to check the real status */ 1420 /* If the h/w switch is off, we need to check the real status */
1368 write_status(NULL, read_status(BT_ON), BT_ON); 1421 write_status(asus, NULL, read_status(asus, BT_ON), BT_ON);
1369 write_status(NULL, read_status(WL_ON), WL_ON); 1422 write_status(asus, NULL, read_status(asus, WL_ON), WL_ON);
1370 1423
1371 /* LCD Backlight is on by default */ 1424 /* LCD Backlight is on by default */
1372 write_status(NULL, 1, LCD_ON); 1425 write_status(asus, NULL, 1, LCD_ON);
1373 1426
1374 /* Keyboard Backlight is on by default */ 1427 /* Keyboard Backlight is on by default */
1375 if (kled_set_handle) 1428 if (kled_set_handle)
1376 set_kled_lvl(1); 1429 set_kled_lvl(asus, 1);
1377 1430
1378 /* LED display is off by default */ 1431 /* LED display is off by default */
1379 asus->ledd_status = 0xFFF; 1432 asus->ledd_status = 0xFFF;
@@ -1383,18 +1436,19 @@ static int __devinit asus_acpi_init(struct acpi_device *device)
1383 hotk->light_level = 5; /* level 5 for sensor sensitivity */ 1436 hotk->light_level = 5; /* level 5 for sensor sensitivity */
1384 1437
1385 if (ls_switch_handle) 1438 if (ls_switch_handle)
1386 set_light_sens_switch(asus->light_switch); 1439 set_light_sens_switch(asus, asus->light_switch);
1387 1440
1388 if (ls_level_handle) 1441 if (ls_level_handle)
1389 set_light_sens_level(asus->light_level); 1442 set_light_sens_level(asus, asus->light_level);
1390 1443
1391 /* GPS is on by default */ 1444 /* GPS is on by default */
1392 write_status(NULL, 1, GPS_ON); 1445 write_status(asus, NULL, 1, GPS_ON);
1393 return result; 1446 return result;
1394} 1447}
1395 1448
1396static int __devinit asus_acpi_add(struct acpi_device *device) 1449static int __devinit asus_acpi_add(struct acpi_device *device)
1397{ 1450{
1451 struct asus_laptop *asus;
1398 int result; 1452 int result;
1399 1453
1400 pr_notice("Asus Laptop Support version %s\n", 1454 pr_notice("Asus Laptop Support version %s\n",
@@ -1408,7 +1462,7 @@ static int __devinit asus_acpi_add(struct acpi_device *device)
1408 device->driver_data = asus; 1462 device->driver_data = asus;
1409 asus->device = device; 1463 asus->device = device;
1410 1464
1411 result = asus_acpi_init(device); 1465 result = asus_acpi_init(asus);
1412 if (result) 1466 if (result)
1413 goto fail_platform; 1467 goto fail_platform;
1414 1468
@@ -1416,22 +1470,22 @@ static int __devinit asus_acpi_add(struct acpi_device *device)
1416 * Register the platform device first. It is used as a parent for the 1470 * Register the platform device first. It is used as a parent for the
1417 * sub-devices below. 1471 * sub-devices below.
1418 */ 1472 */
1419 result = asus_platform_init(); 1473 result = asus_platform_init(asus);
1420 if (result) 1474 if (result)
1421 goto fail_platform; 1475 goto fail_platform;
1422 1476
1423 if (!acpi_video_backlight_support()) { 1477 if (!acpi_video_backlight_support()) {
1424 result = asus_backlight_init(&asus->platform_device->dev); 1478 result = asus_backlight_init(asus);
1425 if (result) 1479 if (result)
1426 goto fail_backlight; 1480 goto fail_backlight;
1427 } else 1481 } else
1428 pr_info("Backlight controlled by ACPI video driver\n"); 1482 pr_info("Backlight controlled by ACPI video driver\n");
1429 1483
1430 result = asus_input_init(&asus->platform_device->dev); 1484 result = asus_input_init(asus);
1431 if (result) 1485 if (result)
1432 goto fail_input; 1486 goto fail_input;
1433 1487
1434 result = asus_led_init(&asus->platform_device->dev); 1488 result = asus_led_init(asus);
1435 if (result) 1489 if (result)
1436 goto fail_led; 1490 goto fail_led;
1437 1491
@@ -1439,11 +1493,11 @@ static int __devinit asus_acpi_add(struct acpi_device *device)
1439 return 0; 1493 return 0;
1440 1494
1441fail_led: 1495fail_led:
1442 asus_input_exit(); 1496 asus_input_exit(asus);
1443fail_input: 1497fail_input:
1444 asus_backlight_exit(); 1498 asus_backlight_exit(asus);
1445fail_backlight: 1499fail_backlight:
1446 asus_platform_exit(); 1500 asus_platform_exit(asus);
1447fail_platform: 1501fail_platform:
1448 kfree(asus->name); 1502 kfree(asus->name);
1449 kfree(asus); 1503 kfree(asus);
@@ -1453,10 +1507,12 @@ fail_platform:
1453 1507
1454static int asus_acpi_remove(struct acpi_device *device, int type) 1508static int asus_acpi_remove(struct acpi_device *device, int type)
1455{ 1509{
1456 asus_backlight_exit(); 1510 struct asus_laptop *asus = acpi_driver_data(device);
1457 asus_led_exit(); 1511
1458 asus_input_exit(); 1512 asus_backlight_exit(asus);
1459 asus_platform_exit(); 1513 asus_led_exit(asus);
1514 asus_input_exit(asus);
1515 asus_platform_exit(asus);
1460 1516
1461 kfree(asus->name); 1517 kfree(asus->name);
1462 kfree(asus); 1518 kfree(asus);