diff options
author | Alan Jenkins <alan-jenkins@tuffmail.co.uk> | 2009-12-03 02:45:07 -0500 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2009-12-09 15:54:32 -0500 |
commit | 52bbe3c7b413d656833686f9f08e5dcab3786eeb (patch) | |
tree | 6e3335f26e95ca3043176ac4074ce18606033b1d /drivers/platform/x86/eeepc-laptop.c | |
parent | 9db106be554288df5a0a7c56c20257a4391b9738 (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.c | 934 |
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 | ||
47 | MODULE_AUTHOR("Corentin Chary, Eric Cooper"); | ||
48 | MODULE_DESCRIPTION(EEEPC_HOTK_NAME); | ||
49 | MODULE_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 | */ | ||
134 | struct 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 */ | ||
151 | static struct eeepc_hotk *ehotk; | ||
152 | |||
153 | /* Platform device/driver */ | ||
154 | static int eeepc_hotk_thaw(struct device *device); | ||
155 | static int eeepc_hotk_restore(struct device *device); | ||
156 | |||
157 | static struct dev_pm_ops eeepc_pm_ops = { | ||
158 | .thaw = eeepc_hotk_thaw, | ||
159 | .restore = eeepc_hotk_restore, | ||
160 | }; | ||
161 | |||
162 | static struct platform_driver platform_driver = { | ||
163 | .driver = { | ||
164 | .name = EEEPC_HOTK_FILE, | ||
165 | .owner = THIS_MODULE, | ||
166 | .pm = &eeepc_pm_ops, | ||
167 | } | ||
168 | }; | ||
169 | |||
170 | static struct platform_device *platform_device; | ||
171 | |||
172 | struct key_entry { | 124 | struct 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 | */ |
203 | static int eeepc_hotk_add(struct acpi_device *device); | 157 | struct eeepc_hotk { |
204 | static int eeepc_hotk_remove(struct acpi_device *device, int type); | 158 | struct acpi_device *device; /* the device we are in */ |
205 | static 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 | |
207 | static 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; |
211 | MODULE_DEVICE_TABLE(acpi, eeepc_device_ids); | 165 | struct rfkill *wlan_rfkill; |
212 | 166 | struct rfkill *bluetooth_rfkill; | |
213 | static 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 */ |
227 | static int eeepc_get_adapter_status(struct hotplug_slot *slot, u8 *value); | 174 | static struct eeepc_hotk *ehotk; |
228 | 175 | ||
229 | static struct hotplug_slot_ops eeepc_hotplug_slot_ops = { | 176 | /* The platform device */ |
230 | .owner = THIS_MODULE, | 177 | static 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 */ |
236 | static struct backlight_device *eeepc_backlight_device; | 180 | static 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 */ |
239 | static struct device *eeepc_hwmon_device; | 183 | static struct device *eeepc_hwmon_device; |
240 | 184 | ||
241 | /* | ||
242 | * The backlight class declaration | ||
243 | */ | ||
244 | static int read_brightness(struct backlight_device *bd); | ||
245 | static int update_bl_status(struct backlight_device *bd); | ||
246 | static struct backlight_ops eeepcbl_ops = { | ||
247 | .get_brightness = read_brightness, | ||
248 | .update_status = update_bl_status, | ||
249 | }; | ||
250 | |||
251 | MODULE_AUTHOR("Corentin Chary, Eric Cooper"); | ||
252 | MODULE_DESCRIPTION(EEEPC_HOTK_NAME); | ||
253 | MODULE_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 | */ | ||
320 | static int read_brightness(struct backlight_device *bd) | ||
321 | { | ||
322 | return get_acpi(CM_ASL_PANELBRIGHT); | ||
323 | } | ||
324 | |||
325 | static int set_brightness(struct backlight_device *bd, int value) | ||
326 | { | ||
327 | return set_acpi(CM_ASL_PANELBRIGHT, value); | ||
328 | } | ||
329 | |||
330 | static 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 | |||
339 | static bool eeepc_wlan_rfkill_blocked(void) | ||
340 | { | ||
341 | if (get_acpi(CM_ASL_WLAN) == 1) | ||
342 | return false; | ||
343 | return true; | ||
344 | } | ||
345 | |||
346 | static int eeepc_rfkill_set(void *data, bool blocked) | ||
347 | { | ||
348 | unsigned long asl = (unsigned long)data; | ||
349 | return set_acpi(asl, !blocked); | ||
350 | } | ||
351 | |||
352 | static const struct rfkill_ops eeepc_rfkill_ops = { | ||
353 | .set_block = eeepc_rfkill_set, | ||
354 | }; | ||
355 | |||
356 | static 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 | */ |
369 | static int parse_arg(const char *buf, unsigned long count, int *val) | 251 | static 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 | /* | 459 | static int eeepc_led_init(struct device *dev) |
578 | * Hotkey functions | ||
579 | */ | ||
580 | static 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 | |||
591 | static 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 | |||
602 | static 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 | |||
614 | static 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 | |||
635 | static 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 | ||
649 | static 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 | |||
657 | static 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 | ||
690 | static int eeepc_backlight_notify(void) | 479 | static 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 | ||
700 | static 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 | */ | ||
491 | static 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 | ||
713 | static void eeepc_rfkill_hotplug(void) | 498 | static 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 | ||
765 | static 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 | |||
784 | static 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 | |||
819 | static int eeepc_register_rfkill_notifier(char *node) | 550 | static 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 | ||
587 | static 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 | |||
856 | static void eeepc_cleanup_pci_hotplug(struct hotplug_slot *hotplug_slot) | 600 | static 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 | ||
606 | static 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 | |||
862 | static int eeepc_setup_pci_hotplug(void) | 612 | static 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 | */ | ||
657 | static int eeepc_rfkill_set(void *data, bool blocked) | ||
658 | { | ||
659 | unsigned long asl = (unsigned long)data; | ||
660 | return set_acpi(asl, !blocked); | ||
661 | } | ||
662 | |||
663 | static const struct rfkill_ops eeepc_rfkill_ops = { | ||
664 | .set_block = eeepc_rfkill_set, | ||
665 | }; | ||
666 | |||
667 | static 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 | |||
693 | static 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 | |||
728 | static 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 | |||
779 | exit: | ||
780 | if (result && result != -ENODEV) | ||
781 | eeepc_rfkill_exit(); | ||
782 | return result; | ||
783 | } | ||
784 | |||
785 | /* | ||
786 | * Platform driver - hibernate/resume callbacks | ||
787 | */ | ||
904 | static int eeepc_hotk_thaw(struct device *device) | 788 | static 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 | ||
824 | static struct dev_pm_ops eeepc_pm_ops = { | ||
825 | .thaw = eeepc_hotk_thaw, | ||
826 | .restore = eeepc_hotk_restore, | ||
827 | }; | ||
828 | |||
829 | static 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 | |||
943 | static int eeepc_get_fan_pwm(void) | 849 | static 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 | */ | ||
1049 | static 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 | |||
1056 | static 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 | |||
1091 | static void eeepc_input_exit(void) | ||
1092 | { | ||
1093 | if (ehotk->inputdev) | ||
1094 | input_unregister_device(ehotk->inputdev); | ||
1095 | } | ||
1096 | |||
1097 | static void eeepc_hwmon_exit(void) | 952 | static 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 | ||
1110 | static void eeepc_led_exit(void) | 965 | static 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 | |||
1118 | static 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 | /* | |
1145 | static int eeepc_rfkill_init(struct device *dev) | 985 | * Backlight device |
986 | */ | ||
987 | static 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) | 992 | static 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, | 997 | static 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) | 1002 | static 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(); | 1007 | static 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 | ||
1196 | exit: | 1014 | return old; |
1197 | if (result && result != -ENODEV) | ||
1198 | eeepc_rfkill_exit(); | ||
1199 | return result; | ||
1200 | } | 1015 | } |
1201 | 1016 | ||
1202 | static int eeepc_backlight_init(struct device *dev) | 1017 | static 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 | ||
1221 | static int eeepc_hwmon_init(struct device *dev) | 1036 | static 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); | 1047 | static 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 | |||
1058 | static 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); | 1077 | static 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 | |||
1088 | static 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 | |||
1100 | static 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 | ||
1240 | static int eeepc_input_init(struct device *dev) | 1121 | static 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 | ||
1274 | static int eeepc_led_init(struct device *dev) | 1155 | static 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 | */ | ||
1164 | static 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 | |||
1199 | static 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 | |||
1213 | static 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 | |||
1221 | static 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 | ||
1253 | static 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 | |||
1294 | static int __devinit eeepc_hotk_add(struct acpi_device *device) | 1263 | static 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 | |||
1344 | static const struct acpi_device_id eeepc_device_ids[] = { | ||
1345 | {EEEPC_HOTK_HID, 0}, | ||
1346 | {"", 0}, | ||
1347 | }; | ||
1348 | MODULE_DEVICE_TABLE(acpi, eeepc_device_ids); | ||
1349 | |||
1350 | static 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 | |||
1374 | static int __init eeepc_laptop_init(void) | 1364 | static int __init eeepc_laptop_init(void) |
1375 | { | 1365 | { |
1376 | int result; | 1366 | int result; |