aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/platform/x86/sony-laptop.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/platform/x86/sony-laptop.c')
-rw-r--r--drivers/platform/x86/sony-laptop.c191
1 files changed, 71 insertions, 120 deletions
diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c
index f1963b05175b..aec0b27fd774 100644
--- a/drivers/platform/x86/sony-laptop.c
+++ b/drivers/platform/x86/sony-laptop.c
@@ -128,11 +128,11 @@ enum sony_nc_rfkill {
128 SONY_BLUETOOTH, 128 SONY_BLUETOOTH,
129 SONY_WWAN, 129 SONY_WWAN,
130 SONY_WIMAX, 130 SONY_WIMAX,
131 SONY_RFKILL_MAX, 131 N_SONY_RFKILL,
132}; 132};
133 133
134static struct rfkill *sony_rfkill_devices[SONY_RFKILL_MAX]; 134static struct rfkill *sony_rfkill_devices[N_SONY_RFKILL];
135static int sony_rfkill_address[SONY_RFKILL_MAX] = {0x300, 0x500, 0x700, 0x900}; 135static int sony_rfkill_address[N_SONY_RFKILL] = {0x300, 0x500, 0x700, 0x900};
136static void sony_nc_rfkill_update(void); 136static void sony_nc_rfkill_update(void);
137 137
138/*********** Input Devices ***********/ 138/*********** Input Devices ***********/
@@ -1051,147 +1051,98 @@ static void sony_nc_rfkill_cleanup(void)
1051{ 1051{
1052 int i; 1052 int i;
1053 1053
1054 for (i = 0; i < SONY_RFKILL_MAX; i++) { 1054 for (i = 0; i < N_SONY_RFKILL; i++) {
1055 if (sony_rfkill_devices[i]) 1055 if (sony_rfkill_devices[i]) {
1056 rfkill_unregister(sony_rfkill_devices[i]); 1056 rfkill_unregister(sony_rfkill_devices[i]);
1057 rfkill_destroy(sony_rfkill_devices[i]);
1058 }
1057 } 1059 }
1058} 1060}
1059 1061
1060static int sony_nc_rfkill_get(void *data, enum rfkill_state *state) 1062static int sony_nc_rfkill_set(void *data, bool blocked)
1061{
1062 int result;
1063 int argument = sony_rfkill_address[(long) data];
1064
1065 sony_call_snc_handle(0x124, 0x200, &result);
1066 if (result & 0x1) {
1067 sony_call_snc_handle(0x124, argument, &result);
1068 if (result & 0xf)
1069 *state = RFKILL_STATE_UNBLOCKED;
1070 else
1071 *state = RFKILL_STATE_SOFT_BLOCKED;
1072 } else {
1073 *state = RFKILL_STATE_HARD_BLOCKED;
1074 }
1075
1076 return 0;
1077}
1078
1079static int sony_nc_rfkill_set(void *data, enum rfkill_state state)
1080{ 1063{
1081 int result; 1064 int result;
1082 int argument = sony_rfkill_address[(long) data] + 0x100; 1065 int argument = sony_rfkill_address[(long) data] + 0x100;
1083 1066
1084 if (state == RFKILL_STATE_UNBLOCKED) 1067 if (!blocked)
1085 argument |= 0xff0000; 1068 argument |= 0xff0000;
1086 1069
1087 return sony_call_snc_handle(0x124, argument, &result); 1070 return sony_call_snc_handle(0x124, argument, &result);
1088} 1071}
1089 1072
1090static int sony_nc_setup_wifi_rfkill(struct acpi_device *device) 1073static const struct rfkill_ops sony_rfkill_ops = {
1091{ 1074 .set_block = sony_nc_rfkill_set,
1092 int err = 0; 1075};
1093 struct rfkill *sony_wifi_rfkill;
1094
1095 sony_wifi_rfkill = rfkill_allocate(&device->dev, RFKILL_TYPE_WLAN);
1096 if (!sony_wifi_rfkill)
1097 return -1;
1098 sony_wifi_rfkill->name = "sony-wifi";
1099 sony_wifi_rfkill->toggle_radio = sony_nc_rfkill_set;
1100 sony_wifi_rfkill->get_state = sony_nc_rfkill_get;
1101 sony_wifi_rfkill->data = (void *)SONY_WIFI;
1102 err = rfkill_register(sony_wifi_rfkill);
1103 if (err)
1104 rfkill_free(sony_wifi_rfkill);
1105 else {
1106 sony_rfkill_devices[SONY_WIFI] = sony_wifi_rfkill;
1107 sony_nc_rfkill_set(sony_wifi_rfkill->data,
1108 RFKILL_STATE_UNBLOCKED);
1109 }
1110 return err;
1111}
1112 1076
1113static int sony_nc_setup_bluetooth_rfkill(struct acpi_device *device) 1077static int sony_nc_setup_rfkill(struct acpi_device *device,
1078 enum sony_nc_rfkill nc_type)
1114{ 1079{
1115 int err = 0; 1080 int err = 0;
1116 struct rfkill *sony_bluetooth_rfkill; 1081 struct rfkill *rfk;
1117 1082 enum rfkill_type type;
1118 sony_bluetooth_rfkill = rfkill_allocate(&device->dev, 1083 const char *name;
1119 RFKILL_TYPE_BLUETOOTH); 1084
1120 if (!sony_bluetooth_rfkill) 1085 switch (nc_type) {
1121 return -1; 1086 case SONY_WIFI:
1122 sony_bluetooth_rfkill->name = "sony-bluetooth"; 1087 type = RFKILL_TYPE_WLAN;
1123 sony_bluetooth_rfkill->toggle_radio = sony_nc_rfkill_set; 1088 name = "sony-wifi";
1124 sony_bluetooth_rfkill->get_state = sony_nc_rfkill_get; 1089 break;
1125 sony_bluetooth_rfkill->data = (void *)SONY_BLUETOOTH; 1090 case SONY_BLUETOOTH:
1126 err = rfkill_register(sony_bluetooth_rfkill); 1091 type = RFKILL_TYPE_BLUETOOTH;
1127 if (err) 1092 name = "sony-bluetooth";
1128 rfkill_free(sony_bluetooth_rfkill); 1093 break;
1129 else { 1094 case SONY_WWAN:
1130 sony_rfkill_devices[SONY_BLUETOOTH] = sony_bluetooth_rfkill; 1095 type = RFKILL_TYPE_WWAN;
1131 sony_nc_rfkill_set(sony_bluetooth_rfkill->data, 1096 name = "sony-wwan";
1132 RFKILL_STATE_UNBLOCKED); 1097 break;
1098 case SONY_WIMAX:
1099 type = RFKILL_TYPE_WIMAX;
1100 name = "sony-wimax";
1101 break;
1102 default:
1103 return -EINVAL;
1133 } 1104 }
1134 return err;
1135}
1136 1105
1137static int sony_nc_setup_wwan_rfkill(struct acpi_device *device) 1106 rfk = rfkill_alloc(name, &device->dev, type,
1138{ 1107 &sony_rfkill_ops, (void *)nc_type);
1139 int err = 0; 1108 if (!rfk)
1140 struct rfkill *sony_wwan_rfkill; 1109 return -ENOMEM;
1141 1110
1142 sony_wwan_rfkill = rfkill_allocate(&device->dev, RFKILL_TYPE_WWAN); 1111 err = rfkill_register(rfk);
1143 if (!sony_wwan_rfkill) 1112 if (err) {
1144 return -1; 1113 rfkill_destroy(rfk);
1145 sony_wwan_rfkill->name = "sony-wwan"; 1114 return err;
1146 sony_wwan_rfkill->toggle_radio = sony_nc_rfkill_set;
1147 sony_wwan_rfkill->get_state = sony_nc_rfkill_get;
1148 sony_wwan_rfkill->data = (void *)SONY_WWAN;
1149 err = rfkill_register(sony_wwan_rfkill);
1150 if (err)
1151 rfkill_free(sony_wwan_rfkill);
1152 else {
1153 sony_rfkill_devices[SONY_WWAN] = sony_wwan_rfkill;
1154 sony_nc_rfkill_set(sony_wwan_rfkill->data,
1155 RFKILL_STATE_UNBLOCKED);
1156 } 1115 }
1116 sony_rfkill_devices[nc_type] = rfk;
1117 sony_nc_rfkill_set((void *)nc_type, false);
1157 return err; 1118 return err;
1158} 1119}
1159 1120
1160static int sony_nc_setup_wimax_rfkill(struct acpi_device *device) 1121static void sony_nc_rfkill_update()
1161{ 1122{
1162 int err = 0; 1123 enum sony_nc_rfkill i;
1163 struct rfkill *sony_wimax_rfkill; 1124 int result;
1125 bool hwblock;
1164 1126
1165 sony_wimax_rfkill = rfkill_allocate(&device->dev, RFKILL_TYPE_WIMAX); 1127 sony_call_snc_handle(0x124, 0x200, &result);
1166 if (!sony_wimax_rfkill) 1128 hwblock = !(result & 0x1);
1167 return -1;
1168 sony_wimax_rfkill->name = "sony-wimax";
1169 sony_wimax_rfkill->toggle_radio = sony_nc_rfkill_set;
1170 sony_wimax_rfkill->get_state = sony_nc_rfkill_get;
1171 sony_wimax_rfkill->data = (void *)SONY_WIMAX;
1172 err = rfkill_register(sony_wimax_rfkill);
1173 if (err)
1174 rfkill_free(sony_wimax_rfkill);
1175 else {
1176 sony_rfkill_devices[SONY_WIMAX] = sony_wimax_rfkill;
1177 sony_nc_rfkill_set(sony_wimax_rfkill->data,
1178 RFKILL_STATE_UNBLOCKED);
1179 }
1180 return err;
1181}
1182 1129
1183static void sony_nc_rfkill_update() 1130 for (i = 0; i < N_SONY_RFKILL; i++) {
1184{ 1131 int argument = sony_rfkill_address[i];
1185 int i;
1186 enum rfkill_state state;
1187 1132
1188 for (i = 0; i < SONY_RFKILL_MAX; i++) { 1133 if (!sony_rfkill_devices[i])
1189 if (sony_rfkill_devices[i]) { 1134 continue;
1190 sony_rfkill_devices[i]-> 1135
1191 get_state(sony_rfkill_devices[i]->data, 1136 if (hwblock) {
1192 &state); 1137 if (rfkill_set_hw_state(sony_rfkill_devices[i], true))
1193 rfkill_force_state(sony_rfkill_devices[i], state); 1138 sony_nc_rfkill_set(sony_rfkill_devices[i],
1139 true);
1140 continue;
1194 } 1141 }
1142
1143 sony_call_snc_handle(0x124, argument, &result);
1144 rfkill_set_states(sony_rfkill_devices[i],
1145 !(result & 0xf), false);
1195 } 1146 }
1196} 1147}
1197 1148
@@ -1210,13 +1161,13 @@ static int sony_nc_rfkill_setup(struct acpi_device *device)
1210 } 1161 }
1211 1162
1212 if (result & 0x1) 1163 if (result & 0x1)
1213 sony_nc_setup_wifi_rfkill(device); 1164 sony_nc_setup_rfkill(device, SONY_WIFI);
1214 if (result & 0x2) 1165 if (result & 0x2)
1215 sony_nc_setup_bluetooth_rfkill(device); 1166 sony_nc_setup_rfkill(device, SONY_BLUETOOTH);
1216 if (result & 0x1c) 1167 if (result & 0x1c)
1217 sony_nc_setup_wwan_rfkill(device); 1168 sony_nc_setup_rfkill(device, SONY_WWAN);
1218 if (result & 0x20) 1169 if (result & 0x20)
1219 sony_nc_setup_wimax_rfkill(device); 1170 sony_nc_setup_rfkill(device, SONY_WIMAX);
1220 1171
1221 return 0; 1172 return 0;
1222} 1173}