aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/platform
diff options
context:
space:
mode:
authorAzael Avalos <coproscefalo@gmail.com>2015-11-23 12:49:10 -0500
committerDarren Hart <dvhart@linux.intel.com>2015-11-23 15:58:32 -0500
commit6873f46a630c48a1fa5ef09ec830c9bb2b2de8dd (patch)
tree074e7fb0a43a82ea1282e38a056b4f4e81441448 /drivers/platform
parentbae5336f0aaedffa115dab9cb3d8a4e4aed3a26a (diff)
toshiba_acpi: Add support for WWAN devices
Toshiba laptops with WWAN devices installed cannot use the device unless it is attached and powered, similar to how Toshiba Bluetooth devices work. This patch adds support to WWAN devices, introducing three functions, one to query the overall status of the wireless devices (RFKill, WLAN, BT, WWAN), the second queries WWAN support, and finally the third (de)activates the device. Signed-off-by: Fabian Koester <fabian.koester@bringnow.com> Signed-off-by: Azael Avalos <coproscefalo@gmail.com>ZZ Signed-off-by: Darren Hart <dvhart@linux.intel.com>
Diffstat (limited to 'drivers/platform')
-rw-r--r--drivers/platform/x86/toshiba_acpi.c109
1 files changed, 109 insertions, 0 deletions
diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c
index 4f722aa0c7b3..3884bdd1e9fe 100644
--- a/drivers/platform/x86/toshiba_acpi.c
+++ b/drivers/platform/x86/toshiba_acpi.c
@@ -114,6 +114,7 @@ MODULE_LICENSE("GPL");
114#define HCI_VIDEO_OUT 0x001c 114#define HCI_VIDEO_OUT 0x001c
115#define HCI_HOTKEY_EVENT 0x001e 115#define HCI_HOTKEY_EVENT 0x001e
116#define HCI_LCD_BRIGHTNESS 0x002a 116#define HCI_LCD_BRIGHTNESS 0x002a
117#define HCI_WIRELESS 0x0056
117#define HCI_ACCELEROMETER 0x006d 118#define HCI_ACCELEROMETER 0x006d
118#define HCI_KBD_ILLUMINATION 0x0095 119#define HCI_KBD_ILLUMINATION 0x0095
119#define HCI_ECO_MODE 0x0097 120#define HCI_ECO_MODE 0x0097
@@ -148,6 +149,10 @@ MODULE_LICENSE("GPL");
148#define SCI_KBD_MODE_ON 0x8 149#define SCI_KBD_MODE_ON 0x8
149#define SCI_KBD_MODE_OFF 0x10 150#define SCI_KBD_MODE_OFF 0x10
150#define SCI_KBD_TIME_MAX 0x3c001a 151#define SCI_KBD_TIME_MAX 0x3c001a
152#define HCI_WIRELESS_STATUS 0x1
153#define HCI_WIRELESS_WWAN 0x3
154#define HCI_WIRELESS_WWAN_STATUS 0x2000
155#define HCI_WIRELESS_WWAN_POWER 0x4000
151#define SCI_USB_CHARGE_MODE_MASK 0xff 156#define SCI_USB_CHARGE_MODE_MASK 0xff
152#define SCI_USB_CHARGE_DISABLED 0x00 157#define SCI_USB_CHARGE_DISABLED 0x00
153#define SCI_USB_CHARGE_ALTERNATE 0x09 158#define SCI_USB_CHARGE_ALTERNATE 0x09
@@ -197,12 +202,14 @@ struct toshiba_acpi_dev {
197 unsigned int kbd_function_keys_supported:1; 202 unsigned int kbd_function_keys_supported:1;
198 unsigned int panel_power_on_supported:1; 203 unsigned int panel_power_on_supported:1;
199 unsigned int usb_three_supported:1; 204 unsigned int usb_three_supported:1;
205 unsigned int wwan_supported:1;
200 unsigned int sysfs_created:1; 206 unsigned int sysfs_created:1;
201 unsigned int special_functions; 207 unsigned int special_functions;
202 208
203 bool kbd_led_registered; 209 bool kbd_led_registered;
204 bool illumination_led_registered; 210 bool illumination_led_registered;
205 bool eco_led_registered; 211 bool eco_led_registered;
212 bool killswitch;
206}; 213};
207 214
208static struct toshiba_acpi_dev *toshiba_acpi; 215static struct toshiba_acpi_dev *toshiba_acpi;
@@ -1085,6 +1092,104 @@ static int toshiba_hotkey_event_type_get(struct toshiba_acpi_dev *dev,
1085 return -EIO; 1092 return -EIO;
1086} 1093}
1087 1094
1095/* Wireless status (RFKill, WLAN, BT, WWAN) */
1096static int toshiba_wireless_status(struct toshiba_acpi_dev *dev)
1097{
1098 u32 in[TCI_WORDS] = { HCI_GET, HCI_WIRELESS, 0, 0, 0, 0 };
1099 u32 out[TCI_WORDS];
1100 acpi_status status;
1101
1102 in[3] = HCI_WIRELESS_STATUS;
1103 status = tci_raw(dev, in, out);
1104
1105 if (ACPI_FAILURE(status)) {
1106 pr_err("ACPI call to get Wireless status failed\n");
1107 return -EIO;
1108 }
1109
1110 if (out[0] == TOS_NOT_SUPPORTED)
1111 return -ENODEV;
1112
1113 if (out[0] != TOS_SUCCESS)
1114 return -EIO;
1115
1116 dev->killswitch = !!(out[2] & HCI_WIRELESS_STATUS);
1117
1118 return 0;
1119}
1120
1121/* WWAN */
1122static void toshiba_wwan_available(struct toshiba_acpi_dev *dev)
1123{
1124 u32 in[TCI_WORDS] = { HCI_GET, HCI_WIRELESS, 0, 0, 0, 0 };
1125 u32 out[TCI_WORDS];
1126 acpi_status status;
1127
1128 dev->wwan_supported = 0;
1129
1130 /*
1131 * WWAN support can be queried by setting the in[3] value to
1132 * HCI_WIRELESS_WWAN (0x03).
1133 *
1134 * If supported, out[0] contains TOS_SUCCESS and out[2] contains
1135 * HCI_WIRELESS_WWAN_STATUS (0x2000).
1136 *
1137 * If not supported, out[0] contains TOS_INPUT_DATA_ERROR (0x8300)
1138 * or TOS_NOT_SUPPORTED (0x8000).
1139 */
1140 in[3] = HCI_WIRELESS_WWAN;
1141 status = tci_raw(dev, in, out);
1142
1143 if (ACPI_FAILURE(status)) {
1144 pr_err("ACPI call to get WWAN status failed\n");
1145 return;
1146 }
1147
1148 if (out[0] != TOS_SUCCESS)
1149 return;
1150
1151 dev->wwan_supported = (out[2] == HCI_WIRELESS_WWAN_STATUS);
1152}
1153
1154static int toshiba_wwan_set(struct toshiba_acpi_dev *dev, u32 state)
1155{
1156 u32 in[TCI_WORDS] = { HCI_SET, HCI_WIRELESS, state, 0, 0, 0 };
1157 u32 out[TCI_WORDS];
1158 acpi_status status;
1159
1160 in[3] = HCI_WIRELESS_WWAN_STATUS;
1161 status = tci_raw(dev, in, out);
1162
1163 if (ACPI_FAILURE(status)) {
1164 pr_err("ACPI call to set WWAN status failed\n");
1165 return -EIO;
1166 }
1167
1168 if (out[0] == TOS_NOT_SUPPORTED)
1169 return -ENODEV;
1170
1171 if (out[0] != TOS_SUCCESS)
1172 return -EIO;
1173
1174 /*
1175 * Some devices only need to call HCI_WIRELESS_WWAN_STATUS to
1176 * (de)activate the device, but some others need the
1177 * HCI_WIRELESS_WWAN_POWER call as well.
1178 */
1179 in[3] = HCI_WIRELESS_WWAN_POWER;
1180 status = tci_raw(dev, in, out);
1181
1182 if (ACPI_FAILURE(status)) {
1183 pr_err("ACPI call to set WWAN power failed\n");
1184 return -EIO;
1185 }
1186
1187 if (out[0] == TOS_NOT_SUPPORTED)
1188 return -ENODEV;
1189
1190 return out[0] == TOS_SUCCESS ? 0 : -EIO;
1191}
1192
1088/* Transflective Backlight */ 1193/* Transflective Backlight */
1089static int get_tr_backlight_status(struct toshiba_acpi_dev *dev, u32 *status) 1194static int get_tr_backlight_status(struct toshiba_acpi_dev *dev, u32 *status)
1090{ 1195{
@@ -2569,6 +2674,8 @@ static void print_supported_features(struct toshiba_acpi_dev *dev)
2569 pr_cont(" panel-power-on"); 2674 pr_cont(" panel-power-on");
2570 if (dev->usb_three_supported) 2675 if (dev->usb_three_supported)
2571 pr_cont(" usb3"); 2676 pr_cont(" usb3");
2677 if (dev->wwan_supported)
2678 pr_cont(" wwan");
2572 2679
2573 pr_cont("\n"); 2680 pr_cont("\n");
2574} 2681}
@@ -2744,6 +2851,8 @@ static int toshiba_acpi_add(struct acpi_device *acpi_dev)
2744 ret = get_fan_status(dev, &dummy); 2851 ret = get_fan_status(dev, &dummy);
2745 dev->fan_supported = !ret; 2852 dev->fan_supported = !ret;
2746 2853
2854 toshiba_wwan_available(dev);
2855
2747 print_supported_features(dev); 2856 print_supported_features(dev);
2748 2857
2749 ret = sysfs_create_group(&dev->acpi_dev->dev.kobj, 2858 ret = sysfs_create_group(&dev->acpi_dev->dev.kobj,