diff options
Diffstat (limited to 'drivers/platform/x86/toshiba_acpi.c')
-rw-r--r-- | drivers/platform/x86/toshiba_acpi.c | 160 |
1 files changed, 45 insertions, 115 deletions
diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c index 9f187265db8..81d31ea507d 100644 --- a/drivers/platform/x86/toshiba_acpi.c +++ b/drivers/platform/x86/toshiba_acpi.c | |||
@@ -45,7 +45,6 @@ | |||
45 | #include <linux/backlight.h> | 45 | #include <linux/backlight.h> |
46 | #include <linux/platform_device.h> | 46 | #include <linux/platform_device.h> |
47 | #include <linux/rfkill.h> | 47 | #include <linux/rfkill.h> |
48 | #include <linux/input-polldev.h> | ||
49 | 48 | ||
50 | #include <asm/uaccess.h> | 49 | #include <asm/uaccess.h> |
51 | 50 | ||
@@ -250,21 +249,15 @@ static acpi_status hci_read2(u32 reg, u32 *out1, u32 *out2, u32 *result) | |||
250 | 249 | ||
251 | struct toshiba_acpi_dev { | 250 | struct toshiba_acpi_dev { |
252 | struct platform_device *p_dev; | 251 | struct platform_device *p_dev; |
253 | struct rfkill *rfk_dev; | 252 | struct rfkill *bt_rfk; |
254 | struct input_polled_dev *poll_dev; | ||
255 | 253 | ||
256 | const char *bt_name; | 254 | const char *bt_name; |
257 | const char *rfk_name; | ||
258 | |||
259 | bool last_rfk_state; | ||
260 | 255 | ||
261 | struct mutex mutex; | 256 | struct mutex mutex; |
262 | }; | 257 | }; |
263 | 258 | ||
264 | static struct toshiba_acpi_dev toshiba_acpi = { | 259 | static struct toshiba_acpi_dev toshiba_acpi = { |
265 | .bt_name = "Toshiba Bluetooth", | 260 | .bt_name = "Toshiba Bluetooth", |
266 | .rfk_name = "Toshiba RFKill Switch", | ||
267 | .last_rfk_state = false, | ||
268 | }; | 261 | }; |
269 | 262 | ||
270 | /* Bluetooth rfkill handlers */ | 263 | /* Bluetooth rfkill handlers */ |
@@ -283,21 +276,6 @@ static u32 hci_get_bt_present(bool *present) | |||
283 | return hci_result; | 276 | return hci_result; |
284 | } | 277 | } |
285 | 278 | ||
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) | 279 | static u32 hci_get_radio_state(bool *radio_state) |
302 | { | 280 | { |
303 | u32 hci_result; | 281 | u32 hci_result; |
@@ -311,70 +289,67 @@ static u32 hci_get_radio_state(bool *radio_state) | |||
311 | return hci_result; | 289 | return hci_result; |
312 | } | 290 | } |
313 | 291 | ||
314 | static int bt_rfkill_toggle_radio(void *data, enum rfkill_state state) | 292 | static int bt_rfkill_set_block(void *data, bool blocked) |
315 | { | 293 | { |
294 | struct toshiba_acpi_dev *dev = data; | ||
316 | u32 result1, result2; | 295 | u32 result1, result2; |
317 | u32 value; | 296 | u32 value; |
297 | int err; | ||
318 | bool radio_state; | 298 | bool radio_state; |
319 | struct toshiba_acpi_dev *dev = data; | ||
320 | 299 | ||
321 | value = (state == RFKILL_STATE_UNBLOCKED); | 300 | value = (blocked == false); |
322 | 301 | ||
323 | if (hci_get_radio_state(&radio_state) != HCI_SUCCESS) | 302 | mutex_lock(&dev->mutex); |
324 | return -EFAULT; | 303 | if (hci_get_radio_state(&radio_state) != HCI_SUCCESS) { |
304 | err = -EBUSY; | ||
305 | goto out; | ||
306 | } | ||
325 | 307 | ||
326 | switch (state) { | 308 | if (!radio_state) { |
327 | case RFKILL_STATE_UNBLOCKED: | 309 | err = 0; |
328 | if (!radio_state) | 310 | goto out; |
329 | return -EPERM; | ||
330 | break; | ||
331 | case RFKILL_STATE_SOFT_BLOCKED: | ||
332 | break; | ||
333 | default: | ||
334 | return -EINVAL; | ||
335 | } | 311 | } |
336 | 312 | ||
337 | mutex_lock(&dev->mutex); | ||
338 | hci_write2(HCI_WIRELESS, value, HCI_WIRELESS_BT_POWER, &result1); | 313 | hci_write2(HCI_WIRELESS, value, HCI_WIRELESS_BT_POWER, &result1); |
339 | hci_write2(HCI_WIRELESS, value, HCI_WIRELESS_BT_ATTACH, &result2); | 314 | hci_write2(HCI_WIRELESS, value, HCI_WIRELESS_BT_ATTACH, &result2); |
340 | mutex_unlock(&dev->mutex); | ||
341 | 315 | ||
342 | if (result1 != HCI_SUCCESS || result2 != HCI_SUCCESS) | 316 | if (result1 != HCI_SUCCESS || result2 != HCI_SUCCESS) |
343 | return -EFAULT; | 317 | err = -EBUSY; |
344 | 318 | else | |
345 | return 0; | 319 | err = 0; |
320 | out: | ||
321 | mutex_unlock(&dev->mutex); | ||
322 | return err; | ||
346 | } | 323 | } |
347 | 324 | ||
348 | static void bt_poll_rfkill(struct input_polled_dev *poll_dev) | 325 | static void bt_rfkill_poll(struct rfkill *rfkill, void *data) |
349 | { | 326 | { |
350 | bool state_changed; | ||
351 | bool new_rfk_state; | 327 | bool new_rfk_state; |
352 | bool value; | 328 | bool value; |
353 | u32 hci_result; | 329 | u32 hci_result; |
354 | struct toshiba_acpi_dev *dev = poll_dev->private; | 330 | struct toshiba_acpi_dev *dev = data; |
331 | |||
332 | mutex_lock(&dev->mutex); | ||
355 | 333 | ||
356 | hci_result = hci_get_radio_state(&value); | 334 | hci_result = hci_get_radio_state(&value); |
357 | if (hci_result != HCI_SUCCESS) | 335 | if (hci_result != HCI_SUCCESS) { |
358 | return; /* Can't do anything useful */ | 336 | /* Can't do anything useful */ |
337 | mutex_unlock(&dev->mutex); | ||
338 | } | ||
359 | 339 | ||
360 | new_rfk_state = value; | 340 | new_rfk_state = value; |
361 | 341 | ||
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); | 342 | mutex_unlock(&dev->mutex); |
366 | 343 | ||
367 | if (unlikely(state_changed)) { | 344 | if (rfkill_set_hw_state(rfkill, !new_rfk_state)) |
368 | rfkill_force_state(dev->rfk_dev, | 345 | bt_rfkill_set_block(data, true); |
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 | input_sync(poll_dev->input); | ||
375 | } | ||
376 | } | 346 | } |
377 | 347 | ||
348 | static const struct rfkill_ops toshiba_rfk_ops = { | ||
349 | .set_block = bt_rfkill_set_block, | ||
350 | .poll = bt_rfkill_poll, | ||
351 | }; | ||
352 | |||
378 | static struct proc_dir_entry *toshiba_proc_dir /*= 0*/ ; | 353 | static struct proc_dir_entry *toshiba_proc_dir /*= 0*/ ; |
379 | static struct backlight_device *toshiba_backlight_device; | 354 | static struct backlight_device *toshiba_backlight_device; |
380 | static int force_fan; | 355 | static int force_fan; |
@@ -702,14 +677,11 @@ static struct backlight_ops toshiba_backlight_data = { | |||
702 | 677 | ||
703 | static void toshiba_acpi_exit(void) | 678 | static void toshiba_acpi_exit(void) |
704 | { | 679 | { |
705 | if (toshiba_acpi.poll_dev) { | 680 | if (toshiba_acpi.bt_rfk) { |
706 | input_unregister_polled_device(toshiba_acpi.poll_dev); | 681 | rfkill_unregister(toshiba_acpi.bt_rfk); |
707 | input_free_polled_device(toshiba_acpi.poll_dev); | 682 | rfkill_destroy(toshiba_acpi.bt_rfk); |
708 | } | 683 | } |
709 | 684 | ||
710 | if (toshiba_acpi.rfk_dev) | ||
711 | rfkill_unregister(toshiba_acpi.rfk_dev); | ||
712 | |||
713 | if (toshiba_backlight_device) | 685 | if (toshiba_backlight_device) |
714 | backlight_device_unregister(toshiba_backlight_device); | 686 | backlight_device_unregister(toshiba_backlight_device); |
715 | 687 | ||
@@ -728,8 +700,6 @@ static int __init toshiba_acpi_init(void) | |||
728 | acpi_status status = AE_OK; | 700 | acpi_status status = AE_OK; |
729 | u32 hci_result; | 701 | u32 hci_result; |
730 | bool bt_present; | 702 | bool bt_present; |
731 | bool bt_on; | ||
732 | bool radio_on; | ||
733 | int ret = 0; | 703 | int ret = 0; |
734 | 704 | ||
735 | if (acpi_disabled) | 705 | if (acpi_disabled) |
@@ -793,61 +763,21 @@ static int __init toshiba_acpi_init(void) | |||
793 | 763 | ||
794 | /* Register rfkill switch for Bluetooth */ | 764 | /* Register rfkill switch for Bluetooth */ |
795 | if (hci_get_bt_present(&bt_present) == HCI_SUCCESS && bt_present) { | 765 | if (hci_get_bt_present(&bt_present) == HCI_SUCCESS && bt_present) { |
796 | toshiba_acpi.rfk_dev = rfkill_allocate(&toshiba_acpi.p_dev->dev, | 766 | toshiba_acpi.bt_rfk = rfkill_alloc(toshiba_acpi.bt_name, |
797 | RFKILL_TYPE_BLUETOOTH); | 767 | &toshiba_acpi.p_dev->dev, |
798 | if (!toshiba_acpi.rfk_dev) { | 768 | RFKILL_TYPE_BLUETOOTH, |
769 | &toshiba_rfk_ops, | ||
770 | &toshiba_acpi); | ||
771 | if (!toshiba_acpi.bt_rfk) { | ||
799 | printk(MY_ERR "unable to allocate rfkill device\n"); | 772 | printk(MY_ERR "unable to allocate rfkill device\n"); |
800 | toshiba_acpi_exit(); | 773 | toshiba_acpi_exit(); |
801 | return -ENOMEM; | 774 | return -ENOMEM; |
802 | } | 775 | } |
803 | 776 | ||
804 | toshiba_acpi.rfk_dev->name = toshiba_acpi.bt_name; | 777 | ret = rfkill_register(toshiba_acpi.bt_rfk); |
805 | toshiba_acpi.rfk_dev->toggle_radio = bt_rfkill_toggle_radio; | ||
806 | toshiba_acpi.rfk_dev->user_claim_unsupported = 1; | ||
807 | toshiba_acpi.rfk_dev->data = &toshiba_acpi; | ||
808 | |||
809 | if (hci_get_bt_on(&bt_on) == HCI_SUCCESS && bt_on) { | ||
810 | toshiba_acpi.rfk_dev->state = RFKILL_STATE_UNBLOCKED; | ||
811 | } else if (hci_get_radio_state(&radio_on) == HCI_SUCCESS && | ||
812 | radio_on) { | ||
813 | toshiba_acpi.rfk_dev->state = RFKILL_STATE_SOFT_BLOCKED; | ||
814 | } else { | ||
815 | toshiba_acpi.rfk_dev->state = RFKILL_STATE_HARD_BLOCKED; | ||
816 | } | ||
817 | |||
818 | ret = rfkill_register(toshiba_acpi.rfk_dev); | ||
819 | if (ret) { | 778 | if (ret) { |
820 | printk(MY_ERR "unable to register rfkill device\n"); | 779 | printk(MY_ERR "unable to register rfkill device\n"); |
821 | toshiba_acpi_exit(); | 780 | rfkill_destroy(toshiba_acpi.bt_rfk); |
822 | return -ENOMEM; | ||
823 | } | ||
824 | |||
825 | /* Register input device for kill switch */ | ||
826 | toshiba_acpi.poll_dev = input_allocate_polled_device(); | ||
827 | if (!toshiba_acpi.poll_dev) { | ||
828 | printk(MY_ERR | ||
829 | "unable to allocate kill-switch input device\n"); | ||
830 | toshiba_acpi_exit(); | ||
831 | return -ENOMEM; | ||
832 | } | ||
833 | toshiba_acpi.poll_dev->private = &toshiba_acpi; | ||
834 | toshiba_acpi.poll_dev->poll = bt_poll_rfkill; | ||
835 | toshiba_acpi.poll_dev->poll_interval = 1000; /* msecs */ | ||
836 | |||
837 | toshiba_acpi.poll_dev->input->name = toshiba_acpi.rfk_name; | ||
838 | toshiba_acpi.poll_dev->input->id.bustype = BUS_HOST; | ||
839 | /* Toshiba USB ID */ | ||
840 | toshiba_acpi.poll_dev->input->id.vendor = 0x0930; | ||
841 | set_bit(EV_SW, toshiba_acpi.poll_dev->input->evbit); | ||
842 | set_bit(SW_RFKILL_ALL, toshiba_acpi.poll_dev->input->swbit); | ||
843 | input_report_switch(toshiba_acpi.poll_dev->input, | ||
844 | SW_RFKILL_ALL, TRUE); | ||
845 | input_sync(toshiba_acpi.poll_dev->input); | ||
846 | |||
847 | ret = input_register_polled_device(toshiba_acpi.poll_dev); | ||
848 | if (ret) { | ||
849 | printk(MY_ERR | ||
850 | "unable to register kill-switch input device\n"); | ||
851 | toshiba_acpi_exit(); | 781 | toshiba_acpi_exit(); |
852 | return ret; | 782 | return ret; |
853 | } | 783 | } |