aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/platform
diff options
context:
space:
mode:
authorCorentin Chary <corentincj@iksaif.net>2009-12-01 16:39:41 -0500
committerCorentin Chary <corentincj@iksaif.net>2010-02-28 13:35:10 -0500
commit9129d14d297e78bc21caffa44d55a5920a74862c (patch)
tree0f7a6006d36e9130de46a4a7989a03aaa1d184f9 /drivers/platform
parent7c247645f305da2bb309fa439fd6cc0aa26f8722 (diff)
asus-laptop: callbacks should use "driver data" parameter or field
(Changelog stolen from Alan's patch for eeepc-laptop, but this patch does the same thing for asus-laptop) Callback methods should not refer to a variable like "asus" (formally "hotk"). Instead, they should extract the data they need either from a "driver data" parameter, or the "driver data" field of the object which they operate on. The "asus" variable can then be removed. In practice, drivers under "drivers/platform" can get away without using driver data, because it doesn't make sense to have more than one instance of them. However this makes it harder to review them for correctness. This is especially true for core ACPI developers who have not previously been exposed to this anti-pattern :-). This will serve as an example of best practice for new driver writers (whether they find it themselves, or have it pointed out during review :-). Signed-off-by: Corentin Chary <corentincj@iksaif.net>
Diffstat (limited to 'drivers/platform')
-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);