aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/platform
diff options
context:
space:
mode:
authorAnisse Astier <anisse@astier.eu>2011-10-14 05:13:42 -0400
committerMatthew Garrett <mjg@redhat.com>2011-10-24 10:52:41 -0400
commit149083996e52c640fdfd73ad92550be4b803f349 (patch)
treee14d1ba2571034a621fe59d370795e4f770de3ba /drivers/platform
parentb93f82816c9ee4868c5aa1c8e06259233916d988 (diff)
asus-laptop: Add rfkill support for Pegatron Lucid tablet
Add three new rfkill switches in this driver that are specific to Pegatron Lucid tablet. Please note that you might not need all three switches. For example if you don't have a 3G module inside your tablet. Also, on my device, the gpio for the wifi/bt module is connected to the bluetooth line. Therefore to activate your wireless lan interface, you need to use the "pega-bt" rfkill switch. Finally, the rfkill switch only works before the wireless module is loaded the first time. Unloading ath9k doesn't help, a reboot is necessary. Signed-off-by: Anisse Astier <anisse@astier.eu> Signed-off-by: Corentin Chary <corentincj@iksaif.net> Signed-off-by: Matthew Garrett <mjg@redhat.com>
Diffstat (limited to 'drivers/platform')
-rw-r--r--drivers/platform/x86/asus-laptop.c103
1 files changed, 103 insertions, 0 deletions
diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c
index 05c0e594c036..edaccad9b5bf 100644
--- a/drivers/platform/x86/asus-laptop.c
+++ b/drivers/platform/x86/asus-laptop.c
@@ -186,6 +186,9 @@ MODULE_PARM_DESC(als_status, "Set the ALS status on boot "
186 186
187#define METHOD_PEGA_ENABLE "ENPR" 187#define METHOD_PEGA_ENABLE "ENPR"
188#define METHOD_PEGA_DISABLE "DAPR" 188#define METHOD_PEGA_DISABLE "DAPR"
189#define PEGA_WLAN 0x00
190#define PEGA_BLUETOOTH 0x01
191#define PEGA_WWAN 0x02
189#define PEGA_ALS 0x04 192#define PEGA_ALS 0x04
190#define PEGA_ALS_POWER 0x05 193#define PEGA_ALS_POWER 0x05
191 194
@@ -213,6 +216,15 @@ struct asus_led {
213}; 216};
214 217
215/* 218/*
219 * Same thing for rfkill
220 */
221struct asus_pega_rfkill {
222 int control_id; /* type of control. Maps to PEGA_* values */
223 struct rfkill *rfkill;
224 struct asus_laptop *asus;
225};
226
227/*
216 * This is the main structure, we can use it to store anything interesting 228 * This is the main structure, we can use it to store anything interesting
217 * about the hotk device 229 * about the hotk device
218 */ 230 */
@@ -246,6 +258,10 @@ struct asus_laptop {
246 258
247 struct rfkill *gps_rfkill; 259 struct rfkill *gps_rfkill;
248 260
261 struct asus_pega_rfkill wlanrfk;
262 struct asus_pega_rfkill btrfk;
263 struct asus_pega_rfkill wwanrfk;
264
249 acpi_handle handle; /* the handle of the hotk device */ 265 acpi_handle handle; /* the handle of the hotk device */
250 u32 ledd_status; /* status of the LED display */ 266 u32 ledd_status; /* status of the LED display */
251 u8 light_level; /* light sensor level */ 267 u8 light_level; /* light sensor level */
@@ -1263,6 +1279,86 @@ static int asus_rfkill_init(struct asus_laptop *asus)
1263 return result; 1279 return result;
1264} 1280}
1265 1281
1282static int pega_rfkill_set(void *data, bool blocked)
1283{
1284 struct asus_pega_rfkill *pega_rfk = data;
1285
1286 int ret = asus_pega_lucid_set(pega_rfk->asus, pega_rfk->control_id, !blocked);
1287 pr_warn("Setting rfkill %d, to %d; returned %d\n", pega_rfk->control_id, !blocked, ret);
1288
1289 return ret;
1290}
1291
1292static const struct rfkill_ops pega_rfkill_ops = {
1293 .set_block = pega_rfkill_set,
1294};
1295
1296static void pega_rfkill_terminate(struct asus_pega_rfkill *pega_rfk)
1297{
1298 pr_warn("Terminating %d\n", pega_rfk->control_id);
1299 if (pega_rfk->rfkill) {
1300 rfkill_unregister(pega_rfk->rfkill);
1301 rfkill_destroy(pega_rfk->rfkill);
1302 pega_rfk->rfkill = NULL;
1303 }
1304}
1305
1306static void pega_rfkill_exit(struct asus_laptop *asus)
1307{
1308 pega_rfkill_terminate(&asus->wwanrfk);
1309 pega_rfkill_terminate(&asus->btrfk);
1310 pega_rfkill_terminate(&asus->wlanrfk);
1311}
1312
1313static int pega_rfkill_setup(struct asus_laptop *asus, struct asus_pega_rfkill *pega_rfk,
1314 const char *name, int controlid, int rfkill_type)
1315{
1316 int result;
1317
1318 pr_warn("Setting up rfk %s, control %d, type %d\n", name, controlid, rfkill_type);
1319 pega_rfk->control_id = controlid;
1320 pega_rfk->asus = asus;
1321 pega_rfk->rfkill = rfkill_alloc(name, &asus->platform_device->dev,
1322 rfkill_type, &pega_rfkill_ops, pega_rfk);
1323 if (!pega_rfk->rfkill)
1324 return -EINVAL;
1325
1326 result = rfkill_register(pega_rfk->rfkill);
1327 if (result) {
1328 rfkill_destroy(pega_rfk->rfkill);
1329 pega_rfk->rfkill = NULL;
1330 }
1331
1332 return result;
1333}
1334
1335static int pega_rfkill_init(struct asus_laptop *asus)
1336{
1337 int ret = 0;
1338
1339 if(!asus->is_pega_lucid)
1340 return -ENODEV;
1341
1342 ret = pega_rfkill_setup(asus, &asus->wlanrfk, "pega-wlan", PEGA_WLAN, RFKILL_TYPE_WLAN);
1343 if(ret)
1344 return ret;
1345 ret = pega_rfkill_setup(asus, &asus->btrfk, "pega-bt", PEGA_BLUETOOTH, RFKILL_TYPE_BLUETOOTH);
1346 if(ret)
1347 goto err_btrfk;
1348 ret = pega_rfkill_setup(asus, &asus->wwanrfk, "pega-wwan", PEGA_WWAN, RFKILL_TYPE_WWAN);
1349 if(ret)
1350 goto err_wwanrfk;
1351
1352 pr_warn("Pega rfkill init succeeded\n");
1353 return 0;
1354err_wwanrfk:
1355 pega_rfkill_terminate(&asus->btrfk);
1356err_btrfk:
1357 pega_rfkill_terminate(&asus->wlanrfk);
1358
1359 return ret;
1360}
1361
1266/* 1362/*
1267 * Input device (i.e. hotkeys) 1363 * Input device (i.e. hotkeys)
1268 */ 1364 */
@@ -1697,9 +1793,15 @@ static int __devinit asus_acpi_add(struct acpi_device *device)
1697 if (result && result != -ENODEV) 1793 if (result && result != -ENODEV)
1698 goto fail_pega_accel; 1794 goto fail_pega_accel;
1699 1795
1796 result = pega_rfkill_init(asus);
1797 if (result && result != -ENODEV)
1798 goto fail_pega_rfkill;
1799
1700 asus_device_present = true; 1800 asus_device_present = true;
1701 return 0; 1801 return 0;
1702 1802
1803fail_pega_rfkill:
1804 pega_accel_exit(asus);
1703fail_pega_accel: 1805fail_pega_accel:
1704 asus_rfkill_exit(asus); 1806 asus_rfkill_exit(asus);
1705fail_rfkill: 1807fail_rfkill:
@@ -1726,6 +1828,7 @@ static int asus_acpi_remove(struct acpi_device *device, int type)
1726 asus_led_exit(asus); 1828 asus_led_exit(asus);
1727 asus_input_exit(asus); 1829 asus_input_exit(asus);
1728 pega_accel_exit(asus); 1830 pega_accel_exit(asus);
1831 pega_rfkill_exit(asus);
1729 asus_platform_exit(asus); 1832 asus_platform_exit(asus);
1730 1833
1731 kfree(asus->name); 1834 kfree(asus->name);