aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/toshiba_acpi.c
diff options
context:
space:
mode:
authorLen Brown <len.brown@intel.com>2008-10-22 23:57:26 -0400
committerLen Brown <len.brown@intel.com>2008-10-23 00:11:07 -0400
commit057316cc6a5b521b332a1d7ccc871cd60c904c74 (patch)
tree4333e608da237c73ff69b10878025cca96dcb4c8 /drivers/acpi/toshiba_acpi.c
parent3e2dab9a1c2deb03c311eb3f83466009147ed4d3 (diff)
parent2515ddc6db8eb49a79f0fe5e67ff09ac7c81eab4 (diff)
Merge branch 'linus' into test
Conflicts: MAINTAINERS arch/x86/kernel/acpi/boot.c arch/x86/kernel/acpi/sleep.c drivers/acpi/Kconfig drivers/pnp/Makefile drivers/pnp/quirks.c Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi/toshiba_acpi.c')
-rw-r--r--drivers/acpi/toshiba_acpi.c261
1 files changed, 253 insertions, 8 deletions
diff --git a/drivers/acpi/toshiba_acpi.c b/drivers/acpi/toshiba_acpi.c
index 4172d290f275..2a632f8b7a05 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
102static const struct acpi_device_id toshiba_device_ids[] = { 111static 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
231static 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
240static 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
251struct 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
264static 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
272static 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
286static 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
301static 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
314static 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
348static 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
221static struct proc_dir_entry *toshiba_proc_dir /*= 0*/ ; 377static struct proc_dir_entry *toshiba_proc_dir /*= 0*/ ;
222static struct backlight_device *toshiba_backlight_device; 378static struct backlight_device *toshiba_backlight_device;
223static int force_fan; 379static int force_fan;
@@ -547,6 +703,14 @@ static struct backlight_ops toshiba_backlight_data = {
547 703
548static void toshiba_acpi_exit(void) 704static 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
613module_init(toshiba_acpi_init); 858module_init(toshiba_acpi_init);