diff options
-rw-r--r-- | drivers/misc/thinkpad_acpi.c | 130 | ||||
-rw-r--r-- | drivers/misc/thinkpad_acpi.h | 20 |
2 files changed, 108 insertions, 42 deletions
diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c index 344eb551c443..a77368f90181 100644 --- a/drivers/misc/thinkpad_acpi.c +++ b/drivers/misc/thinkpad_acpi.c | |||
@@ -681,6 +681,8 @@ static struct ibm_struct hotkey_driver_data = { | |||
681 | 681 | ||
682 | static int __init bluetooth_init(struct ibm_init_struct *iibm) | 682 | static int __init bluetooth_init(struct ibm_init_struct *iibm) |
683 | { | 683 | { |
684 | int status = 0; | ||
685 | |||
684 | vdbg_printk(TPACPI_DBG_INIT, "initializing bluetooth subdriver\n"); | 686 | vdbg_printk(TPACPI_DBG_INIT, "initializing bluetooth subdriver\n"); |
685 | 687 | ||
686 | IBM_ACPIHANDLE_INIT(hkey); | 688 | IBM_ACPIHANDLE_INIT(hkey); |
@@ -688,36 +690,65 @@ static int __init bluetooth_init(struct ibm_init_struct *iibm) | |||
688 | /* bluetooth not supported on 570, 600e/x, 770e, 770x, A21e, A2xm/p, | 690 | /* bluetooth not supported on 570, 600e/x, 770e, 770x, A21e, A2xm/p, |
689 | G4x, R30, R31, R40e, R50e, T20-22, X20-21 */ | 691 | G4x, R30, R31, R40e, R50e, T20-22, X20-21 */ |
690 | tp_features.bluetooth = hkey_handle && | 692 | tp_features.bluetooth = hkey_handle && |
691 | acpi_evalf(hkey_handle, NULL, "GBDC", "qv"); | 693 | acpi_evalf(hkey_handle, &status, "GBDC", "qd"); |
692 | 694 | ||
693 | vdbg_printk(TPACPI_DBG_INIT, "bluetooth is %s\n", | 695 | vdbg_printk(TPACPI_DBG_INIT, "bluetooth is %s, status 0x%02x\n", |
694 | str_supported(tp_features.bluetooth)); | 696 | str_supported(tp_features.bluetooth), |
697 | status); | ||
698 | |||
699 | if (tp_features.bluetooth && | ||
700 | !(status & TP_ACPI_BLUETOOTH_HWPRESENT)) { | ||
701 | /* no bluetooth hardware present in system */ | ||
702 | tp_features.bluetooth = 0; | ||
703 | dbg_printk(TPACPI_DBG_INIT, | ||
704 | "bluetooth hardware not installed\n"); | ||
705 | } | ||
695 | 706 | ||
696 | return (tp_features.bluetooth)? 0 : 1; | 707 | return (tp_features.bluetooth)? 0 : 1; |
697 | } | 708 | } |
698 | 709 | ||
699 | static int bluetooth_status(void) | 710 | static int bluetooth_get_radiosw(void) |
700 | { | 711 | { |
701 | int status; | 712 | int status; |
702 | 713 | ||
703 | if (!tp_features.bluetooth || | 714 | if (!tp_features.bluetooth) |
704 | !acpi_evalf(hkey_handle, &status, "GBDC", "d")) | 715 | return -ENODEV; |
705 | status = 0; | ||
706 | 716 | ||
707 | return status; | 717 | if (!acpi_evalf(hkey_handle, &status, "GBDC", "d")) |
718 | return -EIO; | ||
719 | |||
720 | return ((status & TP_ACPI_BLUETOOTH_RADIOSSW) != 0); | ||
721 | } | ||
722 | |||
723 | static int bluetooth_set_radiosw(int radio_on) | ||
724 | { | ||
725 | int status; | ||
726 | |||
727 | if (!tp_features.bluetooth) | ||
728 | return -ENODEV; | ||
729 | |||
730 | if (!acpi_evalf(hkey_handle, &status, "GBDC", "d")) | ||
731 | return -EIO; | ||
732 | if (radio_on) | ||
733 | status |= TP_ACPI_BLUETOOTH_RADIOSSW; | ||
734 | else | ||
735 | status &= ~TP_ACPI_BLUETOOTH_RADIOSSW; | ||
736 | if (!acpi_evalf(hkey_handle, NULL, "SBDC", "vd", status)) | ||
737 | return -EIO; | ||
738 | |||
739 | return 0; | ||
708 | } | 740 | } |
709 | 741 | ||
710 | static int bluetooth_read(char *p) | 742 | static int bluetooth_read(char *p) |
711 | { | 743 | { |
712 | int len = 0; | 744 | int len = 0; |
713 | int status = bluetooth_status(); | 745 | int status = bluetooth_get_radiosw(); |
714 | 746 | ||
715 | if (!tp_features.bluetooth) | 747 | if (!tp_features.bluetooth) |
716 | len += sprintf(p + len, "status:\t\tnot supported\n"); | 748 | len += sprintf(p + len, "status:\t\tnot supported\n"); |
717 | else if (!(status & 1)) | ||
718 | len += sprintf(p + len, "status:\t\tnot installed\n"); | ||
719 | else { | 749 | else { |
720 | len += sprintf(p + len, "status:\t\t%s\n", enabled(status, 1)); | 750 | len += sprintf(p + len, "status:\t\t%s\n", |
751 | (status)? "enabled" : "disabled"); | ||
721 | len += sprintf(p + len, "commands:\tenable, disable\n"); | 752 | len += sprintf(p + len, "commands:\tenable, disable\n"); |
722 | } | 753 | } |
723 | 754 | ||
@@ -726,26 +757,20 @@ static int bluetooth_read(char *p) | |||
726 | 757 | ||
727 | static int bluetooth_write(char *buf) | 758 | static int bluetooth_write(char *buf) |
728 | { | 759 | { |
729 | int status = bluetooth_status(); | ||
730 | char *cmd; | 760 | char *cmd; |
731 | int do_cmd = 0; | ||
732 | 761 | ||
733 | if (!tp_features.bluetooth) | 762 | if (!tp_features.bluetooth) |
734 | return -ENODEV; | 763 | return -ENODEV; |
735 | 764 | ||
736 | while ((cmd = next_cmd(&buf))) { | 765 | while ((cmd = next_cmd(&buf))) { |
737 | if (strlencmp(cmd, "enable") == 0) { | 766 | if (strlencmp(cmd, "enable") == 0) { |
738 | status |= 2; | 767 | bluetooth_set_radiosw(1); |
739 | } else if (strlencmp(cmd, "disable") == 0) { | 768 | } else if (strlencmp(cmd, "disable") == 0) { |
740 | status &= ~2; | 769 | bluetooth_set_radiosw(0); |
741 | } else | 770 | } else |
742 | return -EINVAL; | 771 | return -EINVAL; |
743 | do_cmd = 1; | ||
744 | } | 772 | } |
745 | 773 | ||
746 | if (do_cmd && !acpi_evalf(hkey_handle, NULL, "SBDC", "vd", status)) | ||
747 | return -EIO; | ||
748 | |||
749 | return 0; | 774 | return 0; |
750 | } | 775 | } |
751 | 776 | ||
@@ -761,41 +786,72 @@ static struct ibm_struct bluetooth_driver_data = { | |||
761 | 786 | ||
762 | static int __init wan_init(struct ibm_init_struct *iibm) | 787 | static int __init wan_init(struct ibm_init_struct *iibm) |
763 | { | 788 | { |
789 | int status = 0; | ||
790 | |||
764 | vdbg_printk(TPACPI_DBG_INIT, "initializing wan subdriver\n"); | 791 | vdbg_printk(TPACPI_DBG_INIT, "initializing wan subdriver\n"); |
765 | 792 | ||
766 | IBM_ACPIHANDLE_INIT(hkey); | 793 | IBM_ACPIHANDLE_INIT(hkey); |
767 | 794 | ||
768 | tp_features.wan = hkey_handle && | 795 | tp_features.wan = hkey_handle && |
769 | acpi_evalf(hkey_handle, NULL, "GWAN", "qv"); | 796 | acpi_evalf(hkey_handle, &status, "GWAN", "qd"); |
770 | 797 | ||
771 | vdbg_printk(TPACPI_DBG_INIT, "wan is %s\n", | 798 | vdbg_printk(TPACPI_DBG_INIT, "wan is %s, status 0x%02x\n", |
772 | str_supported(tp_features.wan)); | 799 | str_supported(tp_features.wan), |
800 | status); | ||
801 | |||
802 | if (tp_features.wan && | ||
803 | !(status & TP_ACPI_WANCARD_HWPRESENT)) { | ||
804 | /* no wan hardware present in system */ | ||
805 | tp_features.wan = 0; | ||
806 | dbg_printk(TPACPI_DBG_INIT, | ||
807 | "wan hardware not installed\n"); | ||
808 | } | ||
773 | 809 | ||
774 | return (tp_features.wan)? 0 : 1; | 810 | return (tp_features.wan)? 0 : 1; |
775 | } | 811 | } |
776 | 812 | ||
777 | static int wan_status(void) | 813 | static int wan_get_radiosw(void) |
778 | { | 814 | { |
779 | int status; | 815 | int status; |
780 | 816 | ||
781 | if (!tp_features.wan || | 817 | if (!tp_features.wan) |
782 | !acpi_evalf(hkey_handle, &status, "GWAN", "d")) | 818 | return -ENODEV; |
783 | status = 0; | ||
784 | 819 | ||
785 | return status; | 820 | if (!acpi_evalf(hkey_handle, &status, "GWAN", "d")) |
821 | return -EIO; | ||
822 | |||
823 | return ((status & TP_ACPI_WANCARD_RADIOSSW) != 0); | ||
824 | } | ||
825 | |||
826 | static int wan_set_radiosw(int radio_on) | ||
827 | { | ||
828 | int status; | ||
829 | |||
830 | if (!tp_features.wan) | ||
831 | return -ENODEV; | ||
832 | |||
833 | if (!acpi_evalf(hkey_handle, &status, "GWAN", "d")) | ||
834 | return -EIO; | ||
835 | if (radio_on) | ||
836 | status |= TP_ACPI_WANCARD_RADIOSSW; | ||
837 | else | ||
838 | status &= ~TP_ACPI_WANCARD_RADIOSSW; | ||
839 | if (!acpi_evalf(hkey_handle, NULL, "SWAN", "vd", status)) | ||
840 | return -EIO; | ||
841 | |||
842 | return 0; | ||
786 | } | 843 | } |
787 | 844 | ||
788 | static int wan_read(char *p) | 845 | static int wan_read(char *p) |
789 | { | 846 | { |
790 | int len = 0; | 847 | int len = 0; |
791 | int status = wan_status(); | 848 | int status = wan_get_radiosw(); |
792 | 849 | ||
793 | if (!tp_features.wan) | 850 | if (!tp_features.wan) |
794 | len += sprintf(p + len, "status:\t\tnot supported\n"); | 851 | len += sprintf(p + len, "status:\t\tnot supported\n"); |
795 | else if (!(status & 1)) | ||
796 | len += sprintf(p + len, "status:\t\tnot installed\n"); | ||
797 | else { | 852 | else { |
798 | len += sprintf(p + len, "status:\t\t%s\n", enabled(status, 1)); | 853 | len += sprintf(p + len, "status:\t\t%s\n", |
854 | (status)? "enabled" : "disabled"); | ||
799 | len += sprintf(p + len, "commands:\tenable, disable\n"); | 855 | len += sprintf(p + len, "commands:\tenable, disable\n"); |
800 | } | 856 | } |
801 | 857 | ||
@@ -804,26 +860,20 @@ static int wan_read(char *p) | |||
804 | 860 | ||
805 | static int wan_write(char *buf) | 861 | static int wan_write(char *buf) |
806 | { | 862 | { |
807 | int status = wan_status(); | ||
808 | char *cmd; | 863 | char *cmd; |
809 | int do_cmd = 0; | ||
810 | 864 | ||
811 | if (!tp_features.wan) | 865 | if (!tp_features.wan) |
812 | return -ENODEV; | 866 | return -ENODEV; |
813 | 867 | ||
814 | while ((cmd = next_cmd(&buf))) { | 868 | while ((cmd = next_cmd(&buf))) { |
815 | if (strlencmp(cmd, "enable") == 0) { | 869 | if (strlencmp(cmd, "enable") == 0) { |
816 | status |= 2; | 870 | wan_set_radiosw(1); |
817 | } else if (strlencmp(cmd, "disable") == 0) { | 871 | } else if (strlencmp(cmd, "disable") == 0) { |
818 | status &= ~2; | 872 | wan_set_radiosw(0); |
819 | } else | 873 | } else |
820 | return -EINVAL; | 874 | return -EINVAL; |
821 | do_cmd = 1; | ||
822 | } | 875 | } |
823 | 876 | ||
824 | if (do_cmd && !acpi_evalf(hkey_handle, NULL, "SWAN", "vd", status)) | ||
825 | return -EIO; | ||
826 | |||
827 | return 0; | 877 | return 0; |
828 | } | 878 | } |
829 | 879 | ||
diff --git a/drivers/misc/thinkpad_acpi.h b/drivers/misc/thinkpad_acpi.h index 1b4cd167ebd2..e06bad5c8fe4 100644 --- a/drivers/misc/thinkpad_acpi.h +++ b/drivers/misc/thinkpad_acpi.h | |||
@@ -241,8 +241,16 @@ static int beep_write(char *buf); | |||
241 | * Bluetooth subdriver | 241 | * Bluetooth subdriver |
242 | */ | 242 | */ |
243 | 243 | ||
244 | enum { | ||
245 | /* ACPI GBDC/SBDC bits */ | ||
246 | TP_ACPI_BLUETOOTH_HWPRESENT = 0x01, /* Bluetooth hw available */ | ||
247 | TP_ACPI_BLUETOOTH_RADIOSSW = 0x02, /* Bluetooth radio enabled */ | ||
248 | TP_ACPI_BLUETOOTH_UNK = 0x04, /* unknown function */ | ||
249 | }; | ||
250 | |||
244 | static int bluetooth_init(struct ibm_init_struct *iibm); | 251 | static int bluetooth_init(struct ibm_init_struct *iibm); |
245 | static int bluetooth_status(void); | 252 | static int bluetooth_get_radiosw(void); |
253 | static int bluetooth_set_radiosw(int radio_on); | ||
246 | static int bluetooth_read(char *p); | 254 | static int bluetooth_read(char *p); |
247 | static int bluetooth_write(char *buf); | 255 | static int bluetooth_write(char *buf); |
248 | 256 | ||
@@ -467,8 +475,16 @@ static int volume_write(char *buf); | |||
467 | * Wan subdriver | 475 | * Wan subdriver |
468 | */ | 476 | */ |
469 | 477 | ||
478 | enum { | ||
479 | /* ACPI GWAN/SWAN bits */ | ||
480 | TP_ACPI_WANCARD_HWPRESENT = 0x01, /* Wan hw available */ | ||
481 | TP_ACPI_WANCARD_RADIOSSW = 0x02, /* Wan radio enabled */ | ||
482 | TP_ACPI_WANCARD_UNK = 0x04, /* unknown function */ | ||
483 | }; | ||
484 | |||
470 | static int wan_init(struct ibm_init_struct *iibm); | 485 | static int wan_init(struct ibm_init_struct *iibm); |
471 | static int wan_status(void); | 486 | static int wan_get_radiosw(void); |
487 | static int wan_set_radiosw(int radio_on); | ||
472 | static int wan_read(char *p); | 488 | static int wan_read(char *p); |
473 | static int wan_write(char *buf); | 489 | static int wan_write(char *buf); |
474 | 490 | ||