diff options
author | Thomas Gleixner <tglx@linutronix.de> | 2008-10-20 07:28:56 -0400 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2008-10-20 07:28:56 -0400 |
commit | b6a4b7de4cb45ccf7157fc58de09c96f84d67108 (patch) | |
tree | 016630974bdcb00fe529b673f96d389e0fd6dc94 /drivers/acpi | |
parent | 2778d0d51dd5007c4909c1d9874f5e9097785a7a (diff) | |
parent | 651dab4264e4ba0e563f5ff56f748127246e9065 (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/arjan/linux-2.6-hrtimer into timers/range-hrtimers
Diffstat (limited to 'drivers/acpi')
-rw-r--r-- | drivers/acpi/Kconfig | 5 | ||||
-rw-r--r-- | drivers/acpi/glue.c | 118 | ||||
-rw-r--r-- | drivers/acpi/sleep/proc.c | 10 | ||||
-rw-r--r-- | drivers/acpi/toshiba_acpi.c | 261 |
4 files changed, 271 insertions, 123 deletions
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 735f5ea17473..da49b006bcc5 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig | |||
@@ -259,7 +259,10 @@ config ACPI_ASUS | |||
259 | 259 | ||
260 | config ACPI_TOSHIBA | 260 | config ACPI_TOSHIBA |
261 | tristate "Toshiba Laptop Extras" | 261 | tristate "Toshiba Laptop Extras" |
262 | depends on X86 | 262 | depends on X86 && INPUT |
263 | select INPUT_POLLDEV | ||
264 | select NET | ||
265 | select RFKILL | ||
263 | select BACKLIGHT_CLASS_DEVICE | 266 | select BACKLIGHT_CLASS_DEVICE |
264 | ---help--- | 267 | ---help--- |
265 | This driver adds support for access to certain system settings | 268 | This driver adds support for access to certain system settings |
diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c index 084109507c9f..24649ada08df 100644 --- a/drivers/acpi/glue.c +++ b/drivers/acpi/glue.c | |||
@@ -165,8 +165,11 @@ static int acpi_bind_one(struct device *dev, acpi_handle handle) | |||
165 | "firmware_node"); | 165 | "firmware_node"); |
166 | ret = sysfs_create_link(&acpi_dev->dev.kobj, &dev->kobj, | 166 | ret = sysfs_create_link(&acpi_dev->dev.kobj, &dev->kobj, |
167 | "physical_node"); | 167 | "physical_node"); |
168 | if (acpi_dev->wakeup.flags.valid) | 168 | if (acpi_dev->wakeup.flags.valid) { |
169 | device_set_wakeup_capable(dev, true); | 169 | device_set_wakeup_capable(dev, true); |
170 | device_set_wakeup_enable(dev, | ||
171 | acpi_dev->wakeup.state.enabled); | ||
172 | } | ||
170 | } | 173 | } |
171 | 174 | ||
172 | return 0; | 175 | return 0; |
@@ -257,116 +260,3 @@ static int __init init_acpi_device_notify(void) | |||
257 | } | 260 | } |
258 | 261 | ||
259 | arch_initcall(init_acpi_device_notify); | 262 | arch_initcall(init_acpi_device_notify); |
260 | |||
261 | |||
262 | #if defined(CONFIG_RTC_DRV_CMOS) || defined(CONFIG_RTC_DRV_CMOS_MODULE) | ||
263 | |||
264 | #ifdef CONFIG_PM | ||
265 | static u32 rtc_handler(void *context) | ||
266 | { | ||
267 | acpi_clear_event(ACPI_EVENT_RTC); | ||
268 | acpi_disable_event(ACPI_EVENT_RTC, 0); | ||
269 | return ACPI_INTERRUPT_HANDLED; | ||
270 | } | ||
271 | |||
272 | static inline void rtc_wake_setup(void) | ||
273 | { | ||
274 | acpi_install_fixed_event_handler(ACPI_EVENT_RTC, rtc_handler, NULL); | ||
275 | /* | ||
276 | * After the RTC handler is installed, the Fixed_RTC event should | ||
277 | * be disabled. Only when the RTC alarm is set will it be enabled. | ||
278 | */ | ||
279 | acpi_clear_event(ACPI_EVENT_RTC); | ||
280 | acpi_disable_event(ACPI_EVENT_RTC, 0); | ||
281 | } | ||
282 | |||
283 | static void rtc_wake_on(struct device *dev) | ||
284 | { | ||
285 | acpi_clear_event(ACPI_EVENT_RTC); | ||
286 | acpi_enable_event(ACPI_EVENT_RTC, 0); | ||
287 | } | ||
288 | |||
289 | static void rtc_wake_off(struct device *dev) | ||
290 | { | ||
291 | acpi_disable_event(ACPI_EVENT_RTC, 0); | ||
292 | } | ||
293 | #else | ||
294 | #define rtc_wake_setup() do{}while(0) | ||
295 | #define rtc_wake_on NULL | ||
296 | #define rtc_wake_off NULL | ||
297 | #endif | ||
298 | |||
299 | /* Every ACPI platform has a mc146818 compatible "cmos rtc". Here we find | ||
300 | * its device node and pass extra config data. This helps its driver use | ||
301 | * capabilities that the now-obsolete mc146818 didn't have, and informs it | ||
302 | * that this board's RTC is wakeup-capable (per ACPI spec). | ||
303 | */ | ||
304 | #include <linux/mc146818rtc.h> | ||
305 | |||
306 | static struct cmos_rtc_board_info rtc_info; | ||
307 | |||
308 | |||
309 | /* PNP devices are registered in a subsys_initcall(); | ||
310 | * ACPI specifies the PNP IDs to use. | ||
311 | */ | ||
312 | #include <linux/pnp.h> | ||
313 | |||
314 | static int __init pnp_match(struct device *dev, void *data) | ||
315 | { | ||
316 | static const char *ids[] = { "PNP0b00", "PNP0b01", "PNP0b02", }; | ||
317 | struct pnp_dev *pnp = to_pnp_dev(dev); | ||
318 | int i; | ||
319 | |||
320 | for (i = 0; i < ARRAY_SIZE(ids); i++) { | ||
321 | if (compare_pnp_id(pnp->id, ids[i]) != 0) | ||
322 | return 1; | ||
323 | } | ||
324 | return 0; | ||
325 | } | ||
326 | |||
327 | static struct device *__init get_rtc_dev(void) | ||
328 | { | ||
329 | return bus_find_device(&pnp_bus_type, NULL, NULL, pnp_match); | ||
330 | } | ||
331 | |||
332 | static int __init acpi_rtc_init(void) | ||
333 | { | ||
334 | struct device *dev = get_rtc_dev(); | ||
335 | |||
336 | if (acpi_disabled) | ||
337 | return 0; | ||
338 | |||
339 | if (dev) { | ||
340 | rtc_wake_setup(); | ||
341 | rtc_info.wake_on = rtc_wake_on; | ||
342 | rtc_info.wake_off = rtc_wake_off; | ||
343 | |||
344 | /* workaround bug in some ACPI tables */ | ||
345 | if (acpi_gbl_FADT.month_alarm && !acpi_gbl_FADT.day_alarm) { | ||
346 | DBG("bogus FADT month_alarm\n"); | ||
347 | acpi_gbl_FADT.month_alarm = 0; | ||
348 | } | ||
349 | |||
350 | rtc_info.rtc_day_alarm = acpi_gbl_FADT.day_alarm; | ||
351 | rtc_info.rtc_mon_alarm = acpi_gbl_FADT.month_alarm; | ||
352 | rtc_info.rtc_century = acpi_gbl_FADT.century; | ||
353 | |||
354 | /* NOTE: S4_RTC_WAKE is NOT currently useful to Linux */ | ||
355 | if (acpi_gbl_FADT.flags & ACPI_FADT_S4_RTC_WAKE) | ||
356 | printk(PREFIX "RTC can wake from S4\n"); | ||
357 | |||
358 | |||
359 | dev->platform_data = &rtc_info; | ||
360 | |||
361 | /* RTC always wakes from S1/S2/S3, and often S4/STD */ | ||
362 | device_init_wakeup(dev, 1); | ||
363 | |||
364 | put_device(dev); | ||
365 | } else | ||
366 | DBG("RTC unavailable?\n"); | ||
367 | return 0; | ||
368 | } | ||
369 | /* do this between RTC subsys_initcall() and rtc_cmos driver_initcall() */ | ||
370 | fs_initcall(acpi_rtc_init); | ||
371 | |||
372 | #endif | ||
diff --git a/drivers/acpi/sleep/proc.c b/drivers/acpi/sleep/proc.c index 4ebbba2b6b19..bf5b04de02d1 100644 --- a/drivers/acpi/sleep/proc.c +++ b/drivers/acpi/sleep/proc.c | |||
@@ -377,6 +377,14 @@ acpi_system_wakeup_device_seq_show(struct seq_file *seq, void *offset) | |||
377 | return 0; | 377 | return 0; |
378 | } | 378 | } |
379 | 379 | ||
380 | static void physical_device_enable_wakeup(struct acpi_device *adev) | ||
381 | { | ||
382 | struct device *dev = acpi_get_physical_device(adev->handle); | ||
383 | |||
384 | if (dev && device_can_wakeup(dev)) | ||
385 | device_set_wakeup_enable(dev, adev->wakeup.state.enabled); | ||
386 | } | ||
387 | |||
380 | static ssize_t | 388 | static ssize_t |
381 | acpi_system_write_wakeup_device(struct file *file, | 389 | acpi_system_write_wakeup_device(struct file *file, |
382 | const char __user * buffer, | 390 | const char __user * buffer, |
@@ -411,6 +419,7 @@ acpi_system_write_wakeup_device(struct file *file, | |||
411 | } | 419 | } |
412 | } | 420 | } |
413 | if (found_dev) { | 421 | if (found_dev) { |
422 | physical_device_enable_wakeup(found_dev); | ||
414 | list_for_each_safe(node, next, &acpi_wakeup_device_list) { | 423 | list_for_each_safe(node, next, &acpi_wakeup_device_list) { |
415 | struct acpi_device *dev = container_of(node, | 424 | struct acpi_device *dev = container_of(node, |
416 | struct | 425 | struct |
@@ -428,6 +437,7 @@ acpi_system_write_wakeup_device(struct file *file, | |||
428 | dev->pnp.bus_id, found_dev->pnp.bus_id); | 437 | dev->pnp.bus_id, found_dev->pnp.bus_id); |
429 | dev->wakeup.state.enabled = | 438 | dev->wakeup.state.enabled = |
430 | found_dev->wakeup.state.enabled; | 439 | found_dev->wakeup.state.enabled; |
440 | physical_device_enable_wakeup(dev); | ||
431 | } | 441 | } |
432 | } | 442 | } |
433 | } | 443 | } |
diff --git a/drivers/acpi/toshiba_acpi.c b/drivers/acpi/toshiba_acpi.c index 0a43c8e0eff3..8a649f40d162 100644 --- a/drivers/acpi/toshiba_acpi.c +++ b/drivers/acpi/toshiba_acpi.c | |||
@@ -3,6 +3,7 @@ | |||
3 | * | 3 | * |
4 | * | 4 | * |
5 | * Copyright (C) 2002-2004 John Belmonte | 5 | * Copyright (C) 2002-2004 John Belmonte |
6 | * Copyright (C) 2008 Philip Langdale | ||
6 | * | 7 | * |
7 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
8 | * it under the terms of the GNU General Public License as published by | 9 | * it under the terms of the GNU General Public License as published by |
@@ -33,7 +34,7 @@ | |||
33 | * | 34 | * |
34 | */ | 35 | */ |
35 | 36 | ||
36 | #define TOSHIBA_ACPI_VERSION "0.18" | 37 | #define TOSHIBA_ACPI_VERSION "0.19" |
37 | #define PROC_INTERFACE_VERSION 1 | 38 | #define PROC_INTERFACE_VERSION 1 |
38 | 39 | ||
39 | #include <linux/kernel.h> | 40 | #include <linux/kernel.h> |
@@ -42,6 +43,9 @@ | |||
42 | #include <linux/types.h> | 43 | #include <linux/types.h> |
43 | #include <linux/proc_fs.h> | 44 | #include <linux/proc_fs.h> |
44 | #include <linux/backlight.h> | 45 | #include <linux/backlight.h> |
46 | #include <linux/platform_device.h> | ||
47 | #include <linux/rfkill.h> | ||
48 | #include <linux/input-polldev.h> | ||
45 | 49 | ||
46 | #include <asm/uaccess.h> | 50 | #include <asm/uaccess.h> |
47 | 51 | ||
@@ -90,6 +94,7 @@ MODULE_LICENSE("GPL"); | |||
90 | #define HCI_VIDEO_OUT 0x001c | 94 | #define HCI_VIDEO_OUT 0x001c |
91 | #define HCI_HOTKEY_EVENT 0x001e | 95 | #define HCI_HOTKEY_EVENT 0x001e |
92 | #define HCI_LCD_BRIGHTNESS 0x002a | 96 | #define HCI_LCD_BRIGHTNESS 0x002a |
97 | #define HCI_WIRELESS 0x0056 | ||
93 | 98 | ||
94 | /* field definitions */ | 99 | /* field definitions */ |
95 | #define HCI_LCD_BRIGHTNESS_BITS 3 | 100 | #define HCI_LCD_BRIGHTNESS_BITS 3 |
@@ -98,9 +103,14 @@ MODULE_LICENSE("GPL"); | |||
98 | #define HCI_VIDEO_OUT_LCD 0x1 | 103 | #define HCI_VIDEO_OUT_LCD 0x1 |
99 | #define HCI_VIDEO_OUT_CRT 0x2 | 104 | #define HCI_VIDEO_OUT_CRT 0x2 |
100 | #define HCI_VIDEO_OUT_TV 0x4 | 105 | #define HCI_VIDEO_OUT_TV 0x4 |
106 | #define HCI_WIRELESS_KILL_SWITCH 0x01 | ||
107 | #define HCI_WIRELESS_BT_PRESENT 0x0f | ||
108 | #define HCI_WIRELESS_BT_ATTACH 0x40 | ||
109 | #define HCI_WIRELESS_BT_POWER 0x80 | ||
101 | 110 | ||
102 | static const struct acpi_device_id toshiba_device_ids[] = { | 111 | static const struct acpi_device_id toshiba_device_ids[] = { |
103 | {"TOS6200", 0}, | 112 | {"TOS6200", 0}, |
113 | {"TOS6208", 0}, | ||
104 | {"TOS1900", 0}, | 114 | {"TOS1900", 0}, |
105 | {"", 0}, | 115 | {"", 0}, |
106 | }; | 116 | }; |
@@ -193,7 +203,7 @@ static acpi_status hci_raw(const u32 in[HCI_WORDS], u32 out[HCI_WORDS]) | |||
193 | return status; | 203 | return status; |
194 | } | 204 | } |
195 | 205 | ||
196 | /* common hci tasks (get or set one value) | 206 | /* common hci tasks (get or set one or two value) |
197 | * | 207 | * |
198 | * In addition to the ACPI status, the HCI system returns a result which | 208 | * In addition to the ACPI status, the HCI system returns a result which |
199 | * may be useful (such as "not supported"). | 209 | * may be useful (such as "not supported"). |
@@ -218,6 +228,152 @@ static acpi_status hci_read1(u32 reg, u32 * out1, u32 * result) | |||
218 | return status; | 228 | return status; |
219 | } | 229 | } |
220 | 230 | ||
231 | static acpi_status hci_write2(u32 reg, u32 in1, u32 in2, u32 *result) | ||
232 | { | ||
233 | u32 in[HCI_WORDS] = { HCI_SET, reg, in1, in2, 0, 0 }; | ||
234 | u32 out[HCI_WORDS]; | ||
235 | acpi_status status = hci_raw(in, out); | ||
236 | *result = (status == AE_OK) ? out[0] : HCI_FAILURE; | ||
237 | return status; | ||
238 | } | ||
239 | |||
240 | static acpi_status hci_read2(u32 reg, u32 *out1, u32 *out2, u32 *result) | ||
241 | { | ||
242 | u32 in[HCI_WORDS] = { HCI_GET, reg, *out1, *out2, 0, 0 }; | ||
243 | u32 out[HCI_WORDS]; | ||
244 | acpi_status status = hci_raw(in, out); | ||
245 | *out1 = out[2]; | ||
246 | *out2 = out[3]; | ||
247 | *result = (status == AE_OK) ? out[0] : HCI_FAILURE; | ||
248 | return status; | ||
249 | } | ||
250 | |||
251 | struct toshiba_acpi_dev { | ||
252 | struct platform_device *p_dev; | ||
253 | struct rfkill *rfk_dev; | ||
254 | struct input_polled_dev *poll_dev; | ||
255 | |||
256 | const char *bt_name; | ||
257 | const char *rfk_name; | ||
258 | |||
259 | bool last_rfk_state; | ||
260 | |||
261 | struct mutex mutex; | ||
262 | }; | ||
263 | |||
264 | static struct toshiba_acpi_dev toshiba_acpi = { | ||
265 | .bt_name = "Toshiba Bluetooth", | ||
266 | .rfk_name = "Toshiba RFKill Switch", | ||
267 | .last_rfk_state = false, | ||
268 | }; | ||
269 | |||
270 | /* Bluetooth rfkill handlers */ | ||
271 | |||
272 | static u32 hci_get_bt_present(bool *present) | ||
273 | { | ||
274 | u32 hci_result; | ||
275 | u32 value, value2; | ||
276 | |||
277 | value = 0; | ||
278 | value2 = 0; | ||
279 | hci_read2(HCI_WIRELESS, &value, &value2, &hci_result); | ||
280 | if (hci_result == HCI_SUCCESS) | ||
281 | *present = (value & HCI_WIRELESS_BT_PRESENT) ? true : false; | ||
282 | |||
283 | return hci_result; | ||
284 | } | ||
285 | |||
286 | static u32 hci_get_bt_on(bool *on) | ||
287 | { | ||
288 | u32 hci_result; | ||
289 | u32 value, value2; | ||
290 | |||
291 | value = 0; | ||
292 | value2 = 0x0001; | ||
293 | hci_read2(HCI_WIRELESS, &value, &value2, &hci_result); | ||
294 | if (hci_result == HCI_SUCCESS) | ||
295 | *on = (value & HCI_WIRELESS_BT_POWER) && | ||
296 | (value & HCI_WIRELESS_BT_ATTACH); | ||
297 | |||
298 | return hci_result; | ||
299 | } | ||
300 | |||
301 | static u32 hci_get_radio_state(bool *radio_state) | ||
302 | { | ||
303 | u32 hci_result; | ||
304 | u32 value, value2; | ||
305 | |||
306 | value = 0; | ||
307 | value2 = 0x0001; | ||
308 | hci_read2(HCI_WIRELESS, &value, &value2, &hci_result); | ||
309 | |||
310 | *radio_state = value & HCI_WIRELESS_KILL_SWITCH; | ||
311 | return hci_result; | ||
312 | } | ||
313 | |||
314 | static int bt_rfkill_toggle_radio(void *data, enum rfkill_state state) | ||
315 | { | ||
316 | u32 result1, result2; | ||
317 | u32 value; | ||
318 | bool radio_state; | ||
319 | struct toshiba_acpi_dev *dev = data; | ||
320 | |||
321 | value = (state == RFKILL_STATE_UNBLOCKED); | ||
322 | |||
323 | if (hci_get_radio_state(&radio_state) != HCI_SUCCESS) | ||
324 | return -EFAULT; | ||
325 | |||
326 | switch (state) { | ||
327 | case RFKILL_STATE_UNBLOCKED: | ||
328 | if (!radio_state) | ||
329 | return -EPERM; | ||
330 | break; | ||
331 | case RFKILL_STATE_SOFT_BLOCKED: | ||
332 | break; | ||
333 | default: | ||
334 | return -EINVAL; | ||
335 | } | ||
336 | |||
337 | mutex_lock(&dev->mutex); | ||
338 | hci_write2(HCI_WIRELESS, value, HCI_WIRELESS_BT_POWER, &result1); | ||
339 | hci_write2(HCI_WIRELESS, value, HCI_WIRELESS_BT_ATTACH, &result2); | ||
340 | mutex_unlock(&dev->mutex); | ||
341 | |||
342 | if (result1 != HCI_SUCCESS || result2 != HCI_SUCCESS) | ||
343 | return -EFAULT; | ||
344 | |||
345 | return 0; | ||
346 | } | ||
347 | |||
348 | static void bt_poll_rfkill(struct input_polled_dev *poll_dev) | ||
349 | { | ||
350 | bool state_changed; | ||
351 | bool new_rfk_state; | ||
352 | bool value; | ||
353 | u32 hci_result; | ||
354 | struct toshiba_acpi_dev *dev = poll_dev->private; | ||
355 | |||
356 | hci_result = hci_get_radio_state(&value); | ||
357 | if (hci_result != HCI_SUCCESS) | ||
358 | return; /* Can't do anything useful */ | ||
359 | |||
360 | new_rfk_state = value; | ||
361 | |||
362 | mutex_lock(&dev->mutex); | ||
363 | state_changed = new_rfk_state != dev->last_rfk_state; | ||
364 | dev->last_rfk_state = new_rfk_state; | ||
365 | mutex_unlock(&dev->mutex); | ||
366 | |||
367 | if (unlikely(state_changed)) { | ||
368 | rfkill_force_state(dev->rfk_dev, | ||
369 | new_rfk_state ? | ||
370 | RFKILL_STATE_SOFT_BLOCKED : | ||
371 | RFKILL_STATE_HARD_BLOCKED); | ||
372 | input_report_switch(poll_dev->input, SW_RFKILL_ALL, | ||
373 | new_rfk_state); | ||
374 | } | ||
375 | } | ||
376 | |||
221 | static struct proc_dir_entry *toshiba_proc_dir /*= 0*/ ; | 377 | static struct proc_dir_entry *toshiba_proc_dir /*= 0*/ ; |
222 | static struct backlight_device *toshiba_backlight_device; | 378 | static struct backlight_device *toshiba_backlight_device; |
223 | static int force_fan; | 379 | static int force_fan; |
@@ -547,6 +703,14 @@ static struct backlight_ops toshiba_backlight_data = { | |||
547 | 703 | ||
548 | static void toshiba_acpi_exit(void) | 704 | static void toshiba_acpi_exit(void) |
549 | { | 705 | { |
706 | if (toshiba_acpi.poll_dev) { | ||
707 | input_unregister_polled_device(toshiba_acpi.poll_dev); | ||
708 | input_free_polled_device(toshiba_acpi.poll_dev); | ||
709 | } | ||
710 | |||
711 | if (toshiba_acpi.rfk_dev) | ||
712 | rfkill_unregister(toshiba_acpi.rfk_dev); | ||
713 | |||
550 | if (toshiba_backlight_device) | 714 | if (toshiba_backlight_device) |
551 | backlight_device_unregister(toshiba_backlight_device); | 715 | backlight_device_unregister(toshiba_backlight_device); |
552 | 716 | ||
@@ -555,6 +719,8 @@ static void toshiba_acpi_exit(void) | |||
555 | if (toshiba_proc_dir) | 719 | if (toshiba_proc_dir) |
556 | remove_proc_entry(PROC_TOSHIBA, acpi_root_dir); | 720 | remove_proc_entry(PROC_TOSHIBA, acpi_root_dir); |
557 | 721 | ||
722 | platform_device_unregister(toshiba_acpi.p_dev); | ||
723 | |||
558 | return; | 724 | return; |
559 | } | 725 | } |
560 | 726 | ||
@@ -562,6 +728,10 @@ static int __init toshiba_acpi_init(void) | |||
562 | { | 728 | { |
563 | acpi_status status = AE_OK; | 729 | acpi_status status = AE_OK; |
564 | u32 hci_result; | 730 | u32 hci_result; |
731 | bool bt_present; | ||
732 | bool bt_on; | ||
733 | bool radio_on; | ||
734 | int ret = 0; | ||
565 | 735 | ||
566 | if (acpi_disabled) | 736 | if (acpi_disabled) |
567 | return -ENODEV; | 737 | return -ENODEV; |
@@ -578,6 +748,18 @@ static int __init toshiba_acpi_init(void) | |||
578 | TOSHIBA_ACPI_VERSION); | 748 | TOSHIBA_ACPI_VERSION); |
579 | printk(MY_INFO " HCI method: %s\n", method_hci); | 749 | printk(MY_INFO " HCI method: %s\n", method_hci); |
580 | 750 | ||
751 | mutex_init(&toshiba_acpi.mutex); | ||
752 | |||
753 | toshiba_acpi.p_dev = platform_device_register_simple("toshiba_acpi", | ||
754 | -1, NULL, 0); | ||
755 | if (IS_ERR(toshiba_acpi.p_dev)) { | ||
756 | ret = PTR_ERR(toshiba_acpi.p_dev); | ||
757 | printk(MY_ERR "unable to register platform device\n"); | ||
758 | toshiba_acpi.p_dev = NULL; | ||
759 | toshiba_acpi_exit(); | ||
760 | return ret; | ||
761 | } | ||
762 | |||
581 | force_fan = 0; | 763 | force_fan = 0; |
582 | key_event_valid = 0; | 764 | key_event_valid = 0; |
583 | 765 | ||
@@ -586,19 +768,23 @@ static int __init toshiba_acpi_init(void) | |||
586 | 768 | ||
587 | toshiba_proc_dir = proc_mkdir(PROC_TOSHIBA, acpi_root_dir); | 769 | toshiba_proc_dir = proc_mkdir(PROC_TOSHIBA, acpi_root_dir); |
588 | if (!toshiba_proc_dir) { | 770 | if (!toshiba_proc_dir) { |
589 | status = AE_ERROR; | 771 | toshiba_acpi_exit(); |
772 | return -ENODEV; | ||
590 | } else { | 773 | } else { |
591 | toshiba_proc_dir->owner = THIS_MODULE; | 774 | toshiba_proc_dir->owner = THIS_MODULE; |
592 | status = add_device(); | 775 | status = add_device(); |
593 | if (ACPI_FAILURE(status)) | 776 | if (ACPI_FAILURE(status)) { |
594 | remove_proc_entry(PROC_TOSHIBA, acpi_root_dir); | 777 | toshiba_acpi_exit(); |
778 | return -ENODEV; | ||
779 | } | ||
595 | } | 780 | } |
596 | 781 | ||
597 | toshiba_backlight_device = backlight_device_register("toshiba",NULL, | 782 | toshiba_backlight_device = backlight_device_register("toshiba", |
783 | &toshiba_acpi.p_dev->dev, | ||
598 | NULL, | 784 | NULL, |
599 | &toshiba_backlight_data); | 785 | &toshiba_backlight_data); |
600 | if (IS_ERR(toshiba_backlight_device)) { | 786 | if (IS_ERR(toshiba_backlight_device)) { |
601 | int ret = PTR_ERR(toshiba_backlight_device); | 787 | ret = PTR_ERR(toshiba_backlight_device); |
602 | 788 | ||
603 | printk(KERN_ERR "Could not register toshiba backlight device\n"); | 789 | printk(KERN_ERR "Could not register toshiba backlight device\n"); |
604 | toshiba_backlight_device = NULL; | 790 | toshiba_backlight_device = NULL; |
@@ -607,7 +793,66 @@ static int __init toshiba_acpi_init(void) | |||
607 | } | 793 | } |
608 | toshiba_backlight_device->props.max_brightness = HCI_LCD_BRIGHTNESS_LEVELS - 1; | 794 | toshiba_backlight_device->props.max_brightness = HCI_LCD_BRIGHTNESS_LEVELS - 1; |
609 | 795 | ||
610 | return (ACPI_SUCCESS(status)) ? 0 : -ENODEV; | 796 | /* Register rfkill switch for Bluetooth */ |
797 | if (hci_get_bt_present(&bt_present) == HCI_SUCCESS && bt_present) { | ||
798 | toshiba_acpi.rfk_dev = rfkill_allocate(&toshiba_acpi.p_dev->dev, | ||
799 | RFKILL_TYPE_BLUETOOTH); | ||
800 | if (!toshiba_acpi.rfk_dev) { | ||
801 | printk(MY_ERR "unable to allocate rfkill device\n"); | ||
802 | toshiba_acpi_exit(); | ||
803 | return -ENOMEM; | ||
804 | } | ||
805 | |||
806 | toshiba_acpi.rfk_dev->name = toshiba_acpi.bt_name; | ||
807 | toshiba_acpi.rfk_dev->toggle_radio = bt_rfkill_toggle_radio; | ||
808 | toshiba_acpi.rfk_dev->user_claim_unsupported = 1; | ||
809 | toshiba_acpi.rfk_dev->data = &toshiba_acpi; | ||
810 | |||
811 | if (hci_get_bt_on(&bt_on) == HCI_SUCCESS && bt_on) { | ||
812 | toshiba_acpi.rfk_dev->state = RFKILL_STATE_UNBLOCKED; | ||
813 | } else if (hci_get_radio_state(&radio_on) == HCI_SUCCESS && | ||
814 | radio_on) { | ||
815 | toshiba_acpi.rfk_dev->state = RFKILL_STATE_SOFT_BLOCKED; | ||
816 | } else { | ||
817 | toshiba_acpi.rfk_dev->state = RFKILL_STATE_HARD_BLOCKED; | ||
818 | } | ||
819 | |||
820 | ret = rfkill_register(toshiba_acpi.rfk_dev); | ||
821 | if (ret) { | ||
822 | printk(MY_ERR "unable to register rfkill device\n"); | ||
823 | toshiba_acpi_exit(); | ||
824 | return -ENOMEM; | ||
825 | } | ||
826 | } | ||
827 | |||
828 | /* Register input device for kill switch */ | ||
829 | toshiba_acpi.poll_dev = input_allocate_polled_device(); | ||
830 | if (!toshiba_acpi.poll_dev) { | ||
831 | printk(MY_ERR "unable to allocate kill-switch input device\n"); | ||
832 | toshiba_acpi_exit(); | ||
833 | return -ENOMEM; | ||
834 | } | ||
835 | toshiba_acpi.poll_dev->private = &toshiba_acpi; | ||
836 | toshiba_acpi.poll_dev->poll = bt_poll_rfkill; | ||
837 | toshiba_acpi.poll_dev->poll_interval = 1000; /* msecs */ | ||
838 | |||
839 | toshiba_acpi.poll_dev->input->name = toshiba_acpi.rfk_name; | ||
840 | toshiba_acpi.poll_dev->input->id.bustype = BUS_HOST; | ||
841 | toshiba_acpi.poll_dev->input->id.vendor = 0x0930; /* Toshiba USB ID */ | ||
842 | set_bit(EV_SW, toshiba_acpi.poll_dev->input->evbit); | ||
843 | set_bit(SW_RFKILL_ALL, toshiba_acpi.poll_dev->input->swbit); | ||
844 | input_report_switch(toshiba_acpi.poll_dev->input, SW_RFKILL_ALL, TRUE); | ||
845 | |||
846 | ret = input_register_polled_device(toshiba_acpi.poll_dev); | ||
847 | if (ret) { | ||
848 | printk(MY_ERR "unable to register kill-switch input device\n"); | ||
849 | rfkill_free(toshiba_acpi.rfk_dev); | ||
850 | toshiba_acpi.rfk_dev = NULL; | ||
851 | toshiba_acpi_exit(); | ||
852 | return ret; | ||
853 | } | ||
854 | |||
855 | return 0; | ||
611 | } | 856 | } |
612 | 857 | ||
613 | module_init(toshiba_acpi_init); | 858 | module_init(toshiba_acpi_init); |