aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/platform/x86/eeepc-laptop.c
diff options
context:
space:
mode:
authorAlan Jenkins <alan-jenkins@tuffmail.co.uk>2009-12-03 02:45:07 -0500
committerLen Brown <len.brown@intel.com>2009-12-09 15:54:32 -0500
commit52bbe3c7b413d656833686f9f08e5dcab3786eeb (patch)
tree6e3335f26e95ca3043176ac4074ce18606033b1d /drivers/platform/x86/eeepc-laptop.c
parent9db106be554288df5a0a7c56c20257a4391b9738 (diff)
eeepc-laptop: code movement
Move e.g. backlight_init() and backlight_exit() together along with the other backlight functions, instead of grouping init() and exit() functions. Move e.g. backlight_ops to follow the functions it refers to, and remove the forward declarations. The code itself should remain unchanged. The eeepc-laptop driver implements a number of interfaces like the backlight class driver. This change makes it easier to examine the implementation of one interface at at a time, without having to search through the file to find init() and exit() functions etc. Signed-off-by: Alan Jenkins <alan-jenkins@tuffmail.co.uk> Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/platform/x86/eeepc-laptop.c')
-rw-r--r--drivers/platform/x86/eeepc-laptop.c934
1 files changed, 462 insertions, 472 deletions
diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c
index f4f67967aae2..f457587e64d3 100644
--- a/drivers/platform/x86/eeepc-laptop.c
+++ b/drivers/platform/x86/eeepc-laptop.c
@@ -44,6 +44,9 @@
44#define EEEPC_HOTK_DEVICE_NAME "Hotkey" 44#define EEEPC_HOTK_DEVICE_NAME "Hotkey"
45#define EEEPC_HOTK_HID "ASUS010" 45#define EEEPC_HOTK_HID "ASUS010"
46 46
47MODULE_AUTHOR("Corentin Chary, Eric Cooper");
48MODULE_DESCRIPTION(EEEPC_HOTK_NAME);
49MODULE_LICENSE("GPL");
47 50
48/* 51/*
49 * Definitions for Asus EeePC 52 * Definitions for Asus EeePC
@@ -118,57 +121,6 @@ static const char *cm_setv[] = {
118 NULL, NULL, "PBPS", "TPDS" 121 NULL, NULL, "PBPS", "TPDS"
119}; 122};
120 123
121#define EEEPC_EC_SC00 0x61
122#define EEEPC_EC_FAN_PWM (EEEPC_EC_SC00 + 2) /* Fan PWM duty cycle (%) */
123#define EEEPC_EC_FAN_HRPM (EEEPC_EC_SC00 + 5) /* High byte, fan speed (RPM) */
124#define EEEPC_EC_FAN_LRPM (EEEPC_EC_SC00 + 6) /* Low byte, fan speed (RPM) */
125
126#define EEEPC_EC_SFB0 0xD0
127#define EEEPC_EC_FAN_CTRL (EEEPC_EC_SFB0 + 3) /* Byte containing SF25 */
128
129
130/*
131 * This is the main structure, we can use it to store useful information
132 * about the hotk device
133 */
134struct eeepc_hotk {
135 struct acpi_device *device; /* the device we are in */
136 acpi_handle handle; /* the handle of the hotk device */
137 u32 cm_supported; /* the control methods supported
138 by this BIOS */
139 u16 event_count[128]; /* count for each event */
140 struct input_dev *inputdev;
141 u16 *keycode_map;
142 struct rfkill *wlan_rfkill;
143 struct rfkill *bluetooth_rfkill;
144 struct rfkill *wwan3g_rfkill;
145 struct rfkill *wimax_rfkill;
146 struct hotplug_slot *hotplug_slot;
147 struct mutex hotplug_lock;
148};
149
150/* The actual device the driver binds to */
151static struct eeepc_hotk *ehotk;
152
153/* Platform device/driver */
154static int eeepc_hotk_thaw(struct device *device);
155static int eeepc_hotk_restore(struct device *device);
156
157static struct dev_pm_ops eeepc_pm_ops = {
158 .thaw = eeepc_hotk_thaw,
159 .restore = eeepc_hotk_restore,
160};
161
162static struct platform_driver platform_driver = {
163 .driver = {
164 .name = EEEPC_HOTK_FILE,
165 .owner = THIS_MODULE,
166 .pm = &eeepc_pm_ops,
167 }
168};
169
170static struct platform_device *platform_device;
171
172struct key_entry { 124struct key_entry {
173 char type; 125 char type;
174 u8 code; 126 u8 code;
@@ -189,48 +141,40 @@ static struct key_entry eeepc_keymap[] = {
189 {KE_KEY, 0x1b, KEY_ZOOM }, 141 {KE_KEY, 0x1b, KEY_ZOOM },
190 {KE_KEY, 0x1c, KEY_PROG2 }, 142 {KE_KEY, 0x1c, KEY_PROG2 },
191 {KE_KEY, 0x1d, KEY_PROG3 }, 143 {KE_KEY, 0x1d, KEY_PROG3 },
192 {KE_KEY, NOTIFY_BRN_MIN, KEY_BRIGHTNESSDOWN }, 144 {KE_KEY, NOTIFY_BRN_MIN, KEY_BRIGHTNESSDOWN },
193 {KE_KEY, NOTIFY_BRN_MIN + 2, KEY_BRIGHTNESSUP }, 145 {KE_KEY, NOTIFY_BRN_MAX, KEY_BRIGHTNESSUP },
194 {KE_KEY, 0x30, KEY_SWITCHVIDEOMODE }, 146 {KE_KEY, 0x30, KEY_SWITCHVIDEOMODE },
195 {KE_KEY, 0x31, KEY_SWITCHVIDEOMODE }, 147 {KE_KEY, 0x31, KEY_SWITCHVIDEOMODE },
196 {KE_KEY, 0x32, KEY_SWITCHVIDEOMODE }, 148 {KE_KEY, 0x32, KEY_SWITCHVIDEOMODE },
197 {KE_END, 0}, 149 {KE_END, 0},
198}; 150};
199 151
152
200/* 153/*
201 * The hotkey driver declaration 154 * This is the main structure, we can use it to store useful information
155 * about the hotk device
202 */ 156 */
203static int eeepc_hotk_add(struct acpi_device *device); 157struct eeepc_hotk {
204static int eeepc_hotk_remove(struct acpi_device *device, int type); 158 struct acpi_device *device; /* the device we are in */
205static void eeepc_hotk_notify(struct acpi_device *device, u32 event); 159 acpi_handle handle; /* the handle of the hotk device */
206 160 u32 cm_supported; /* the control methods supported
207static const struct acpi_device_id eeepc_device_ids[] = { 161 by this BIOS */
208 {EEEPC_HOTK_HID, 0}, 162 u16 event_count[128]; /* count for each event */
209 {"", 0}, 163 struct input_dev *inputdev;
210}; 164 u16 *keycode_map;
211MODULE_DEVICE_TABLE(acpi, eeepc_device_ids); 165 struct rfkill *wlan_rfkill;
212 166 struct rfkill *bluetooth_rfkill;
213static struct acpi_driver eeepc_hotk_driver = { 167 struct rfkill *wwan3g_rfkill;
214 .name = EEEPC_HOTK_NAME, 168 struct rfkill *wimax_rfkill;
215 .class = EEEPC_HOTK_CLASS, 169 struct hotplug_slot *hotplug_slot;
216 .owner = THIS_MODULE, 170 struct mutex hotplug_lock;
217 .ids = eeepc_device_ids,
218 .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS,
219 .ops = {
220 .add = eeepc_hotk_add,
221 .remove = eeepc_hotk_remove,
222 .notify = eeepc_hotk_notify,
223 },
224}; 171};
225 172
226/* PCI hotplug ops */ 173/* The actual device the driver binds to */
227static int eeepc_get_adapter_status(struct hotplug_slot *slot, u8 *value); 174static struct eeepc_hotk *ehotk;
228 175
229static struct hotplug_slot_ops eeepc_hotplug_slot_ops = { 176/* The platform device */
230 .owner = THIS_MODULE, 177static struct platform_device *platform_device;
231 .get_adapter_status = eeepc_get_adapter_status,
232 .get_power_status = eeepc_get_adapter_status,
233};
234 178
235/* The backlight device /sys/class/backlight */ 179/* The backlight device /sys/class/backlight */
236static struct backlight_device *eeepc_backlight_device; 180static struct backlight_device *eeepc_backlight_device;
@@ -238,19 +182,6 @@ static struct backlight_device *eeepc_backlight_device;
238/* The hwmon device */ 182/* The hwmon device */
239static struct device *eeepc_hwmon_device; 183static struct device *eeepc_hwmon_device;
240 184
241/*
242 * The backlight class declaration
243 */
244static int read_brightness(struct backlight_device *bd);
245static int update_bl_status(struct backlight_device *bd);
246static struct backlight_ops eeepcbl_ops = {
247 .get_brightness = read_brightness,
248 .update_status = update_bl_status,
249};
250
251MODULE_AUTHOR("Corentin Chary, Eric Cooper");
252MODULE_DESCRIPTION(EEEPC_HOTK_NAME);
253MODULE_LICENSE("GPL");
254 185
255/* 186/*
256 * ACPI Helpers 187 * ACPI Helpers
@@ -315,55 +246,6 @@ static int get_acpi(int cm)
315} 246}
316 247
317/* 248/*
318 * Backlight
319 */
320static int read_brightness(struct backlight_device *bd)
321{
322 return get_acpi(CM_ASL_PANELBRIGHT);
323}
324
325static int set_brightness(struct backlight_device *bd, int value)
326{
327 return set_acpi(CM_ASL_PANELBRIGHT, value);
328}
329
330static int update_bl_status(struct backlight_device *bd)
331{
332 return set_brightness(bd, bd->props.brightness);
333}
334
335/*
336 * Rfkill helpers
337 */
338
339static bool eeepc_wlan_rfkill_blocked(void)
340{
341 if (get_acpi(CM_ASL_WLAN) == 1)
342 return false;
343 return true;
344}
345
346static int eeepc_rfkill_set(void *data, bool blocked)
347{
348 unsigned long asl = (unsigned long)data;
349 return set_acpi(asl, !blocked);
350}
351
352static const struct rfkill_ops eeepc_rfkill_ops = {
353 .set_block = eeepc_rfkill_set,
354};
355
356static void __devinit eeepc_enable_camera(void)
357{
358 /*
359 * If the following call to set_acpi() fails, it's because there's no
360 * camera so we can ignore the error.
361 */
362 if (get_acpi(CM_ASL_CAMERA) == 0)
363 set_acpi(CM_ASL_CAMERA, 1);
364}
365
366/*
367 * Sys helpers 249 * Sys helpers
368 */ 250 */
369static int parse_arg(const char *buf, unsigned long count, int *val) 251static int parse_arg(const char *buf, unsigned long count, int *val)
@@ -574,140 +456,43 @@ static struct led_classdev tpd_led = {
574 .max_brightness = 1 456 .max_brightness = 1
575}; 457};
576 458
577/* 459static int eeepc_led_init(struct device *dev)
578 * Hotkey functions
579 */
580static struct key_entry *eepc_get_entry_by_scancode(int code)
581{
582 struct key_entry *key;
583
584 for (key = eeepc_keymap; key->type != KE_END; key++)
585 if (code == key->code)
586 return key;
587
588 return NULL;
589}
590
591static struct key_entry *eepc_get_entry_by_keycode(int code)
592{
593 struct key_entry *key;
594
595 for (key = eeepc_keymap; key->type != KE_END; key++)
596 if (code == key->keycode && key->type == KE_KEY)
597 return key;
598
599 return NULL;
600}
601
602static int eeepc_getkeycode(struct input_dev *dev, int scancode, int *keycode)
603{
604 struct key_entry *key = eepc_get_entry_by_scancode(scancode);
605
606 if (key && key->type == KE_KEY) {
607 *keycode = key->keycode;
608 return 0;
609 }
610
611 return -EINVAL;
612}
613
614static int eeepc_setkeycode(struct input_dev *dev, int scancode, int keycode)
615{ 460{
616 struct key_entry *key; 461 int rv;
617 int old_keycode;
618
619 if (keycode < 0 || keycode > KEY_MAX)
620 return -EINVAL;
621 462
622 key = eepc_get_entry_by_scancode(scancode); 463 if (get_acpi(CM_ASL_TPD) == -ENODEV)
623 if (key && key->type == KE_KEY) {
624 old_keycode = key->keycode;
625 key->keycode = keycode;
626 set_bit(keycode, dev->keybit);
627 if (!eepc_get_entry_by_keycode(old_keycode))
628 clear_bit(old_keycode, dev->keybit);
629 return 0; 464 return 0;
630 }
631
632 return -EINVAL;
633}
634
635static void cmsg_quirk(int cm, const char *name)
636{
637 int dummy;
638
639 /* Some BIOSes do not report cm although it is avaliable.
640 Check if cm_getv[cm] works and, if yes, assume cm should be set. */
641 if (!(ehotk->cm_supported & (1 << cm))
642 && !read_acpi_int(ehotk->handle, cm_getv[cm], &dummy)) {
643 pr_info("%s (%x) not reported by BIOS,"
644 " enabling anyway\n", name, 1 << cm);
645 ehotk->cm_supported |= 1 << cm;
646 }
647}
648 465
649static void cmsg_quirks(void) 466 led_workqueue = create_singlethread_workqueue("led_workqueue");
650{ 467 if (!led_workqueue)
651 cmsg_quirk(CM_ASL_LID, "LID"); 468 return -ENOMEM;
652 cmsg_quirk(CM_ASL_TYPE, "TYPE");
653 cmsg_quirk(CM_ASL_PANELPOWER, "PANELPOWER");
654 cmsg_quirk(CM_ASL_TPD, "TPD");
655}
656
657static int eeepc_hotk_init(void)
658{
659 unsigned int init_flags;
660 int result;
661
662 result = acpi_bus_get_status(ehotk->device);
663 if (result)
664 return result;
665 if (!ehotk->device->status.present) {
666 pr_err("Hotkey device not present, aborting\n");
667 return -ENODEV;
668 }
669
670 init_flags = DISABLE_ASL_WLAN | DISABLE_ASL_DISPLAYSWITCH;
671 pr_notice("Hotkey init flags 0x%x\n", init_flags);
672
673 if (write_acpi_int(ehotk->handle, "INIT", init_flags)) {
674 pr_err("Hotkey initialization failed\n");
675 return -ENODEV;
676 }
677 469
678 /* get control methods supported */ 470 rv = led_classdev_register(dev, &tpd_led);
679 if (read_acpi_int(ehotk->handle, "CMSG", 471 if (rv) {
680 &ehotk->cm_supported)) { 472 destroy_workqueue(led_workqueue);
681 pr_err("Get control methods supported failed\n"); 473 return rv;
682 return -ENODEV;
683 } 474 }
684 cmsg_quirks();
685 pr_info("Get control methods supported: 0x%x\n", ehotk->cm_supported);
686 475
687 return 0; 476 return 0;
688} 477}
689 478
690static int eeepc_backlight_notify(void) 479static void eeepc_led_exit(void)
691{ 480{
692 struct backlight_device *bd = eeepc_backlight_device; 481 if (tpd_led.dev)
693 int old = bd->props.brightness; 482 led_classdev_unregister(&tpd_led);
694 483 if (led_workqueue)
695 backlight_force_update(bd, BACKLIGHT_UPDATE_HOTKEY); 484 destroy_workqueue(led_workqueue);
696
697 return old;
698} 485}
699 486
700static int eeepc_get_adapter_status(struct hotplug_slot *hotplug_slot,
701 u8 *value)
702{
703 int val = get_acpi(CM_ASL_WLAN);
704
705 if (val == 1 || val == 0)
706 *value = val;
707 else
708 return -EINVAL;
709 487
710 return 0; 488/*
489 * PCI hotplug (for wlan rfkill)
490 */
491static bool eeepc_wlan_rfkill_blocked(void)
492{
493 if (get_acpi(CM_ASL_WLAN) == 1)
494 return false;
495 return true;
711} 496}
712 497
713static void eeepc_rfkill_hotplug(void) 498static void eeepc_rfkill_hotplug(void)
@@ -762,60 +547,6 @@ static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data)
762 eeepc_rfkill_hotplug(); 547 eeepc_rfkill_hotplug();
763} 548}
764 549
765static void eeepc_input_notify(int event)
766{
767 static struct key_entry *key;
768
769 key = eepc_get_entry_by_scancode(event);
770 if (key) {
771 switch (key->type) {
772 case KE_KEY:
773 input_report_key(ehotk->inputdev, key->keycode,
774 1);
775 input_sync(ehotk->inputdev);
776 input_report_key(ehotk->inputdev, key->keycode,
777 0);
778 input_sync(ehotk->inputdev);
779 break;
780 }
781 }
782}
783
784static void eeepc_hotk_notify(struct acpi_device *device, u32 event)
785{
786 u16 count;
787
788 if (event > ACPI_MAX_SYS_NOTIFY)
789 return;
790 count = ehotk->event_count[event % 128]++;
791 acpi_bus_generate_proc_event(ehotk->device, event, count);
792 acpi_bus_generate_netlink_event(ehotk->device->pnp.device_class,
793 dev_name(&ehotk->device->dev), event,
794 count);
795
796 if (event >= NOTIFY_BRN_MIN && event <= NOTIFY_BRN_MAX) {
797 int old_brightness, new_brightness;
798
799 /* Update backlight device. */
800 old_brightness = eeepc_backlight_notify();
801
802 /* Convert brightness event to keypress (obsolescent hack). */
803 new_brightness = event - NOTIFY_BRN_MIN;
804
805 if (new_brightness < old_brightness) {
806 event = NOTIFY_BRN_MIN; /* brightness down */
807 } else if (new_brightness > old_brightness) {
808 event = NOTIFY_BRN_MAX; /* brightness up */
809 } else {
810 /*
811 * no change in brightness - already at min/max,
812 * event will be desired value (or else ignored).
813 */
814 }
815 }
816 eeepc_input_notify(event);
817}
818
819static int eeepc_register_rfkill_notifier(char *node) 550static int eeepc_register_rfkill_notifier(char *node)
820{ 551{
821 acpi_status status = AE_OK; 552 acpi_status status = AE_OK;
@@ -853,12 +584,31 @@ static void eeepc_unregister_rfkill_notifier(char *node)
853 } 584 }
854} 585}
855 586
587static int eeepc_get_adapter_status(struct hotplug_slot *hotplug_slot,
588 u8 *value)
589{
590 int val = get_acpi(CM_ASL_WLAN);
591
592 if (val == 1 || val == 0)
593 *value = val;
594 else
595 return -EINVAL;
596
597 return 0;
598}
599
856static void eeepc_cleanup_pci_hotplug(struct hotplug_slot *hotplug_slot) 600static void eeepc_cleanup_pci_hotplug(struct hotplug_slot *hotplug_slot)
857{ 601{
858 kfree(hotplug_slot->info); 602 kfree(hotplug_slot->info);
859 kfree(hotplug_slot); 603 kfree(hotplug_slot);
860} 604}
861 605
606static struct hotplug_slot_ops eeepc_hotplug_slot_ops = {
607 .owner = THIS_MODULE,
608 .get_adapter_status = eeepc_get_adapter_status,
609 .get_power_status = eeepc_get_adapter_status,
610};
611
862static int eeepc_setup_pci_hotplug(void) 612static int eeepc_setup_pci_hotplug(void)
863{ 613{
864 int ret = -ENOMEM; 614 int ret = -ENOMEM;
@@ -901,6 +651,140 @@ error_slot:
901 return ret; 651 return ret;
902} 652}
903 653
654/*
655 * Rfkill devices
656 */
657static int eeepc_rfkill_set(void *data, bool blocked)
658{
659 unsigned long asl = (unsigned long)data;
660 return set_acpi(asl, !blocked);
661}
662
663static const struct rfkill_ops eeepc_rfkill_ops = {
664 .set_block = eeepc_rfkill_set,
665};
666
667static int eeepc_new_rfkill(struct rfkill **rfkill,
668 const char *name, struct device *dev,
669 enum rfkill_type type, int cm)
670{
671 int result;
672
673 result = get_acpi(cm);
674 if (result < 0)
675 return result;
676
677 *rfkill = rfkill_alloc(name, dev, type,
678 &eeepc_rfkill_ops, (void *)(unsigned long)cm);
679
680 if (!*rfkill)
681 return -EINVAL;
682
683 rfkill_init_sw_state(*rfkill, get_acpi(cm) != 1);
684 result = rfkill_register(*rfkill);
685 if (result) {
686 rfkill_destroy(*rfkill);
687 *rfkill = NULL;
688 return result;
689 }
690 return 0;
691}
692
693static void eeepc_rfkill_exit(void)
694{
695 eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P5");
696 eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P6");
697 eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P7");
698 if (ehotk->wlan_rfkill) {
699 rfkill_unregister(ehotk->wlan_rfkill);
700 rfkill_destroy(ehotk->wlan_rfkill);
701 ehotk->wlan_rfkill = NULL;
702 }
703 /*
704 * Refresh pci hotplug in case the rfkill state was changed after
705 * eeepc_unregister_rfkill_notifier()
706 */
707 eeepc_rfkill_hotplug();
708 if (ehotk->hotplug_slot)
709 pci_hp_deregister(ehotk->hotplug_slot);
710
711 if (ehotk->bluetooth_rfkill) {
712 rfkill_unregister(ehotk->bluetooth_rfkill);
713 rfkill_destroy(ehotk->bluetooth_rfkill);
714 ehotk->bluetooth_rfkill = NULL;
715 }
716 if (ehotk->wwan3g_rfkill) {
717 rfkill_unregister(ehotk->wwan3g_rfkill);
718 rfkill_destroy(ehotk->wwan3g_rfkill);
719 ehotk->wwan3g_rfkill = NULL;
720 }
721 if (ehotk->wimax_rfkill) {
722 rfkill_unregister(ehotk->wimax_rfkill);
723 rfkill_destroy(ehotk->wimax_rfkill);
724 ehotk->wimax_rfkill = NULL;
725 }
726}
727
728static int eeepc_rfkill_init(struct device *dev)
729{
730 int result = 0;
731
732 mutex_init(&ehotk->hotplug_lock);
733
734 result = eeepc_new_rfkill(&ehotk->wlan_rfkill,
735 "eeepc-wlan", dev,
736 RFKILL_TYPE_WLAN, CM_ASL_WLAN);
737
738 if (result && result != -ENODEV)
739 goto exit;
740
741 result = eeepc_new_rfkill(&ehotk->bluetooth_rfkill,
742 "eeepc-bluetooth", dev,
743 RFKILL_TYPE_BLUETOOTH, CM_ASL_BLUETOOTH);
744
745 if (result && result != -ENODEV)
746 goto exit;
747
748 result = eeepc_new_rfkill(&ehotk->wwan3g_rfkill,
749 "eeepc-wwan3g", dev,
750 RFKILL_TYPE_WWAN, CM_ASL_3G);
751
752 if (result && result != -ENODEV)
753 goto exit;
754
755 result = eeepc_new_rfkill(&ehotk->wimax_rfkill,
756 "eeepc-wimax", dev,
757 RFKILL_TYPE_WIMAX, CM_ASL_WIMAX);
758
759 if (result && result != -ENODEV)
760 goto exit;
761
762 result = eeepc_setup_pci_hotplug();
763 /*
764 * If we get -EBUSY then something else is handling the PCI hotplug -
765 * don't fail in this case
766 */
767 if (result == -EBUSY)
768 result = 0;
769
770 eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P5");
771 eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P6");
772 eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P7");
773 /*
774 * Refresh pci hotplug in case the rfkill state was changed during
775 * setup.
776 */
777 eeepc_rfkill_hotplug();
778
779exit:
780 if (result && result != -ENODEV)
781 eeepc_rfkill_exit();
782 return result;
783}
784
785/*
786 * Platform driver - hibernate/resume callbacks
787 */
904static int eeepc_hotk_thaw(struct device *device) 788static int eeepc_hotk_thaw(struct device *device)
905{ 789{
906 if (ehotk->wlan_rfkill) { 790 if (ehotk->wlan_rfkill) {
@@ -937,9 +821,31 @@ static int eeepc_hotk_restore(struct device *device)
937 return 0; 821 return 0;
938} 822}
939 823
824static struct dev_pm_ops eeepc_pm_ops = {
825 .thaw = eeepc_hotk_thaw,
826 .restore = eeepc_hotk_restore,
827};
828
829static struct platform_driver platform_driver = {
830 .driver = {
831 .name = EEEPC_HOTK_FILE,
832 .owner = THIS_MODULE,
833 .pm = &eeepc_pm_ops,
834 }
835};
836
940/* 837/*
941 * Hwmon 838 * Hwmon device
942 */ 839 */
840
841#define EEEPC_EC_SC00 0x61
842#define EEEPC_EC_FAN_PWM (EEEPC_EC_SC00 + 2) /* Fan PWM duty cycle (%) */
843#define EEEPC_EC_FAN_HRPM (EEEPC_EC_SC00 + 5) /* High byte, fan speed (RPM) */
844#define EEEPC_EC_FAN_LRPM (EEEPC_EC_SC00 + 6) /* Low byte, fan speed (RPM) */
845
846#define EEEPC_EC_SFB0 0xD0
847#define EEEPC_EC_FAN_CTRL (EEEPC_EC_SFB0 + 3) /* Byte containing SF25 */
848
943static int eeepc_get_fan_pwm(void) 849static int eeepc_get_fan_pwm(void)
944{ 850{
945 u8 value = 0; 851 u8 value = 0;
@@ -1043,57 +949,6 @@ static struct attribute_group hwmon_attribute_group = {
1043 .attrs = hwmon_attributes 949 .attrs = hwmon_attributes
1044}; 950};
1045 951
1046/*
1047 * exit/init
1048 */
1049static void eeepc_backlight_exit(void)
1050{
1051 if (eeepc_backlight_device)
1052 backlight_device_unregister(eeepc_backlight_device);
1053 eeepc_backlight_device = NULL;
1054}
1055
1056static void eeepc_rfkill_exit(void)
1057{
1058 eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P5");
1059 eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P6");
1060 eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P7");
1061 if (ehotk->wlan_rfkill) {
1062 rfkill_unregister(ehotk->wlan_rfkill);
1063 rfkill_destroy(ehotk->wlan_rfkill);
1064 ehotk->wlan_rfkill = NULL;
1065 }
1066 /*
1067 * Refresh pci hotplug in case the rfkill state was changed after
1068 * eeepc_unregister_rfkill_notifier()
1069 */
1070 eeepc_rfkill_hotplug();
1071 if (ehotk->hotplug_slot)
1072 pci_hp_deregister(ehotk->hotplug_slot);
1073
1074 if (ehotk->bluetooth_rfkill) {
1075 rfkill_unregister(ehotk->bluetooth_rfkill);
1076 rfkill_destroy(ehotk->bluetooth_rfkill);
1077 ehotk->bluetooth_rfkill = NULL;
1078 }
1079 if (ehotk->wwan3g_rfkill) {
1080 rfkill_unregister(ehotk->wwan3g_rfkill);
1081 rfkill_destroy(ehotk->wwan3g_rfkill);
1082 ehotk->wwan3g_rfkill = NULL;
1083 }
1084 if (ehotk->wimax_rfkill) {
1085 rfkill_unregister(ehotk->wimax_rfkill);
1086 rfkill_destroy(ehotk->wimax_rfkill);
1087 ehotk->wimax_rfkill = NULL;
1088 }
1089}
1090
1091static void eeepc_input_exit(void)
1092{
1093 if (ehotk->inputdev)
1094 input_unregister_device(ehotk->inputdev);
1095}
1096
1097static void eeepc_hwmon_exit(void) 952static void eeepc_hwmon_exit(void)
1098{ 953{
1099 struct device *hwmon; 954 struct device *hwmon;
@@ -1107,96 +962,56 @@ static void eeepc_hwmon_exit(void)
1107 eeepc_hwmon_device = NULL; 962 eeepc_hwmon_device = NULL;
1108} 963}
1109 964
1110static void eeepc_led_exit(void) 965static int eeepc_hwmon_init(struct device *dev)
1111{
1112 if (tpd_led.dev)
1113 led_classdev_unregister(&tpd_led);
1114 if (led_workqueue)
1115 destroy_workqueue(led_workqueue);
1116}
1117
1118static int eeepc_new_rfkill(struct rfkill **rfkill,
1119 const char *name, struct device *dev,
1120 enum rfkill_type type, int cm)
1121{ 966{
967 struct device *hwmon;
1122 int result; 968 int result;
1123 969
1124 result = get_acpi(cm); 970 hwmon = hwmon_device_register(dev);
1125 if (result < 0) 971 if (IS_ERR(hwmon)) {
1126 return result; 972 pr_err("Could not register eeepc hwmon device\n");
1127 973 eeepc_hwmon_device = NULL;
1128 *rfkill = rfkill_alloc(name, dev, type, 974 return PTR_ERR(hwmon);
1129 &eeepc_rfkill_ops, (void *)(unsigned long)cm);
1130
1131 if (!*rfkill)
1132 return -EINVAL;
1133
1134 rfkill_init_sw_state(*rfkill, get_acpi(cm) != 1);
1135 result = rfkill_register(*rfkill);
1136 if (result) {
1137 rfkill_destroy(*rfkill);
1138 *rfkill = NULL;
1139 return result;
1140 } 975 }
1141 return 0; 976 eeepc_hwmon_device = hwmon;
977 result = sysfs_create_group(&hwmon->kobj,
978 &hwmon_attribute_group);
979 if (result)
980 eeepc_hwmon_exit();
981 return result;
1142} 982}
1143 983
1144 984/*
1145static int eeepc_rfkill_init(struct device *dev) 985 * Backlight device
986 */
987static int read_brightness(struct backlight_device *bd)
1146{ 988{
1147 int result = 0; 989 return get_acpi(CM_ASL_PANELBRIGHT);
1148 990}
1149 mutex_init(&ehotk->hotplug_lock);
1150
1151 result = eeepc_new_rfkill(&ehotk->wlan_rfkill,
1152 "eeepc-wlan", dev,
1153 RFKILL_TYPE_WLAN, CM_ASL_WLAN);
1154
1155 if (result && result != -ENODEV)
1156 goto exit;
1157
1158 result = eeepc_new_rfkill(&ehotk->bluetooth_rfkill,
1159 "eeepc-bluetooth", dev,
1160 RFKILL_TYPE_BLUETOOTH, CM_ASL_BLUETOOTH);
1161
1162 if (result && result != -ENODEV)
1163 goto exit;
1164
1165 result = eeepc_new_rfkill(&ehotk->wwan3g_rfkill,
1166 "eeepc-wwan3g", dev,
1167 RFKILL_TYPE_WWAN, CM_ASL_3G);
1168 991
1169 if (result && result != -ENODEV) 992static int set_brightness(struct backlight_device *bd, int value)
1170 goto exit; 993{
994 return set_acpi(CM_ASL_PANELBRIGHT, value);
995}
1171 996
1172 result = eeepc_new_rfkill(&ehotk->wimax_rfkill, 997static int update_bl_status(struct backlight_device *bd)
1173 "eeepc-wimax", dev, 998{
1174 RFKILL_TYPE_WIMAX, CM_ASL_WIMAX); 999 return set_brightness(bd, bd->props.brightness);
1000}
1175 1001
1176 if (result && result != -ENODEV) 1002static struct backlight_ops eeepcbl_ops = {
1177 goto exit; 1003 .get_brightness = read_brightness,
1004 .update_status = update_bl_status,
1005};
1178 1006
1179 result = eeepc_setup_pci_hotplug(); 1007static int eeepc_backlight_notify(void)
1180 /* 1008{
1181 * If we get -EBUSY then something else is handling the PCI hotplug - 1009 struct backlight_device *bd = eeepc_backlight_device;
1182 * don't fail in this case 1010 int old = bd->props.brightness;
1183 */
1184 if (result == -EBUSY)
1185 result = 0;
1186 1011
1187 eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P5"); 1012 backlight_force_update(bd, BACKLIGHT_UPDATE_HOTKEY);
1188 eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P6");
1189 eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P7");
1190 /*
1191 * Refresh pci hotplug in case the rfkill state was changed during
1192 * setup.
1193 */
1194 eeepc_rfkill_hotplug();
1195 1013
1196exit: 1014 return old;
1197 if (result && result != -ENODEV)
1198 eeepc_rfkill_exit();
1199 return result;
1200} 1015}
1201 1016
1202static int eeepc_backlight_init(struct device *dev) 1017static int eeepc_backlight_init(struct device *dev)
@@ -1218,23 +1033,89 @@ static int eeepc_backlight_init(struct device *dev)
1218 return 0; 1033 return 0;
1219} 1034}
1220 1035
1221static int eeepc_hwmon_init(struct device *dev) 1036static void eeepc_backlight_exit(void)
1222{ 1037{
1223 struct device *hwmon; 1038 if (eeepc_backlight_device)
1224 int result; 1039 backlight_device_unregister(eeepc_backlight_device);
1040 eeepc_backlight_device = NULL;
1041}
1225 1042
1226 hwmon = hwmon_device_register(dev); 1043
1227 if (IS_ERR(hwmon)) { 1044/*
1228 pr_err("Could not register eeepc hwmon device\n"); 1045 * Input device (i.e. hotkeys)
1229 eeepc_hwmon_device = NULL; 1046 */
1230 return PTR_ERR(hwmon); 1047static struct key_entry *eeepc_get_entry_by_scancode(int code)
1048{
1049 struct key_entry *key;
1050
1051 for (key = eeepc_keymap; key->type != KE_END; key++)
1052 if (code == key->code)
1053 return key;
1054
1055 return NULL;
1056}
1057
1058static void eeepc_input_notify(int event)
1059{
1060 static struct key_entry *key;
1061
1062 key = eeepc_get_entry_by_scancode(event);
1063 if (key) {
1064 switch (key->type) {
1065 case KE_KEY:
1066 input_report_key(ehotk->inputdev, key->keycode,
1067 1);
1068 input_sync(ehotk->inputdev);
1069 input_report_key(ehotk->inputdev, key->keycode,
1070 0);
1071 input_sync(ehotk->inputdev);
1072 break;
1073 }
1231 } 1074 }
1232 eeepc_hwmon_device = hwmon; 1075}
1233 result = sysfs_create_group(&hwmon->kobj, 1076
1234 &hwmon_attribute_group); 1077static struct key_entry *eepc_get_entry_by_keycode(int code)
1235 if (result) 1078{
1236 eeepc_hwmon_exit(); 1079 struct key_entry *key;
1237 return result; 1080
1081 for (key = eeepc_keymap; key->type != KE_END; key++)
1082 if (code == key->keycode && key->type == KE_KEY)
1083 return key;
1084
1085 return NULL;
1086}
1087
1088static int eeepc_getkeycode(struct input_dev *dev, int scancode, int *keycode)
1089{
1090 struct key_entry *key = eeepc_get_entry_by_scancode(scancode);
1091
1092 if (key && key->type == KE_KEY) {
1093 *keycode = key->keycode;
1094 return 0;
1095 }
1096
1097 return -EINVAL;
1098}
1099
1100static int eeepc_setkeycode(struct input_dev *dev, int scancode, int keycode)
1101{
1102 struct key_entry *key;
1103 int old_keycode;
1104
1105 if (keycode < 0 || keycode > KEY_MAX)
1106 return -EINVAL;
1107
1108 key = eeepc_get_entry_by_scancode(scancode);
1109 if (key && key->type == KE_KEY) {
1110 old_keycode = key->keycode;
1111 key->keycode = keycode;
1112 set_bit(keycode, dev->keybit);
1113 if (!eepc_get_entry_by_keycode(old_keycode))
1114 clear_bit(old_keycode, dev->keybit);
1115 return 0;
1116 }
1117
1118 return -EINVAL;
1238} 1119}
1239 1120
1240static int eeepc_input_init(struct device *dev) 1121static int eeepc_input_init(struct device *dev)
@@ -1271,26 +1152,114 @@ static int eeepc_input_init(struct device *dev)
1271 return 0; 1152 return 0;
1272} 1153}
1273 1154
1274static int eeepc_led_init(struct device *dev) 1155static void eeepc_input_exit(void)
1275{ 1156{
1276 int rv; 1157 if (ehotk->inputdev)
1158 input_unregister_device(ehotk->inputdev);
1159}
1277 1160
1278 if (get_acpi(CM_ASL_TPD) == -ENODEV) 1161/*
1279 return 0; 1162 * ACPI driver
1163 */
1164static void eeepc_hotk_notify(struct acpi_device *device, u32 event)
1165{
1166 u16 count;
1280 1167
1281 led_workqueue = create_singlethread_workqueue("led_workqueue"); 1168 if (event > ACPI_MAX_SYS_NOTIFY)
1282 if (!led_workqueue) 1169 return;
1283 return -ENOMEM; 1170 count = ehotk->event_count[event % 128]++;
1171 acpi_bus_generate_proc_event(ehotk->device, event, count);
1172 acpi_bus_generate_netlink_event(ehotk->device->pnp.device_class,
1173 dev_name(&ehotk->device->dev), event,
1174 count);
1284 1175
1285 rv = led_classdev_register(dev, &tpd_led); 1176 if (event >= NOTIFY_BRN_MIN && event <= NOTIFY_BRN_MAX) {
1286 if (rv) { 1177 int old_brightness, new_brightness;
1287 destroy_workqueue(led_workqueue); 1178
1288 return rv; 1179 /* Update backlight device. */
1180 old_brightness = eeepc_backlight_notify();
1181
1182 /* Convert brightness event to keypress (obsolescent hack). */
1183 new_brightness = event - NOTIFY_BRN_MIN;
1184
1185 if (new_brightness < old_brightness) {
1186 event = NOTIFY_BRN_MIN; /* brightness down */
1187 } else if (new_brightness > old_brightness) {
1188 event = NOTIFY_BRN_MAX; /* brightness up */
1189 } else {
1190 /*
1191 * no change in brightness - already at min/max,
1192 * event will be desired value (or else ignored).
1193 */
1194 }
1289 } 1195 }
1196 eeepc_input_notify(event);
1197}
1198
1199static void cmsg_quirk(int cm, const char *name)
1200{
1201 int dummy;
1202
1203 /* Some BIOSes do not report cm although it is avaliable.
1204 Check if cm_getv[cm] works and, if yes, assume cm should be set. */
1205 if (!(ehotk->cm_supported & (1 << cm))
1206 && !read_acpi_int(ehotk->handle, cm_getv[cm], &dummy)) {
1207 pr_info("%s (%x) not reported by BIOS,"
1208 " enabling anyway\n", name, 1 << cm);
1209 ehotk->cm_supported |= 1 << cm;
1210 }
1211}
1212
1213static void cmsg_quirks(void)
1214{
1215 cmsg_quirk(CM_ASL_LID, "LID");
1216 cmsg_quirk(CM_ASL_TYPE, "TYPE");
1217 cmsg_quirk(CM_ASL_PANELPOWER, "PANELPOWER");
1218 cmsg_quirk(CM_ASL_TPD, "TPD");
1219}
1220
1221static int eeepc_hotk_init(void)
1222{
1223 unsigned int init_flags;
1224 int result;
1225
1226 result = acpi_bus_get_status(ehotk->device);
1227 if (result)
1228 return result;
1229 if (!ehotk->device->status.present) {
1230 pr_err("Hotkey device not present, aborting\n");
1231 return -ENODEV;
1232 }
1233
1234 init_flags = DISABLE_ASL_WLAN | DISABLE_ASL_DISPLAYSWITCH;
1235 pr_notice("Hotkey init flags 0x%x\n", init_flags);
1236
1237 if (write_acpi_int(ehotk->handle, "INIT", init_flags)) {
1238 pr_err("Hotkey initialization failed\n");
1239 return -ENODEV;
1240 }
1241
1242 /* get control methods supported */
1243 if (read_acpi_int(ehotk->handle, "CMSG", &ehotk->cm_supported)) {
1244 pr_err("Get control methods supported failed\n");
1245 return -ENODEV;
1246 }
1247 cmsg_quirks();
1248 pr_info("Get control methods supported: 0x%x\n", ehotk->cm_supported);
1290 1249
1291 return 0; 1250 return 0;
1292} 1251}
1293 1252
1253static void __devinit eeepc_enable_camera(void)
1254{
1255 /*
1256 * If the following call to set_acpi() fails, it's because there's no
1257 * camera so we can ignore the error.
1258 */
1259 if (get_acpi(CM_ASL_CAMERA) == 0)
1260 set_acpi(CM_ASL_CAMERA, 1);
1261}
1262
1294static int __devinit eeepc_hotk_add(struct acpi_device *device) 1263static int __devinit eeepc_hotk_add(struct acpi_device *device)
1295{ 1264{
1296 struct device *dev; 1265 struct device *dev;
@@ -1371,6 +1340,27 @@ static int eeepc_hotk_remove(struct acpi_device *device, int type)
1371 return 0; 1340 return 0;
1372} 1341}
1373 1342
1343
1344static const struct acpi_device_id eeepc_device_ids[] = {
1345 {EEEPC_HOTK_HID, 0},
1346 {"", 0},
1347};
1348MODULE_DEVICE_TABLE(acpi, eeepc_device_ids);
1349
1350static struct acpi_driver eeepc_hotk_driver = {
1351 .name = EEEPC_HOTK_NAME,
1352 .class = EEEPC_HOTK_CLASS,
1353 .owner = THIS_MODULE,
1354 .ids = eeepc_device_ids,
1355 .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS,
1356 .ops = {
1357 .add = eeepc_hotk_add,
1358 .remove = eeepc_hotk_remove,
1359 .notify = eeepc_hotk_notify,
1360 },
1361};
1362
1363
1374static int __init eeepc_laptop_init(void) 1364static int __init eeepc_laptop_init(void)
1375{ 1365{
1376 int result; 1366 int result;