Skip to content

Commit

Permalink
asus-laptop: Add rfkill support for Pegatron Lucid tablet
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Anisse Astier authored and Matthew Garrett committed Oct 24, 2011
1 parent b93f828 commit 1490839
Showing 1 changed file with 103 additions and 0 deletions.
103 changes: 103 additions & 0 deletions drivers/platform/x86/asus-laptop.c
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,9 @@ MODULE_PARM_DESC(als_status, "Set the ALS status on boot "

#define METHOD_PEGA_ENABLE "ENPR"
#define METHOD_PEGA_DISABLE "DAPR"
#define PEGA_WLAN 0x00
#define PEGA_BLUETOOTH 0x01
#define PEGA_WWAN 0x02
#define PEGA_ALS 0x04
#define PEGA_ALS_POWER 0x05

Expand All @@ -212,6 +215,15 @@ struct asus_led {
const char *method;
};

/*
* Same thing for rfkill
*/
struct asus_pega_rfkill {
int control_id; /* type of control. Maps to PEGA_* values */
struct rfkill *rfkill;
struct asus_laptop *asus;
};

/*
* This is the main structure, we can use it to store anything interesting
* about the hotk device
Expand Down Expand Up @@ -246,6 +258,10 @@ struct asus_laptop {

struct rfkill *gps_rfkill;

struct asus_pega_rfkill wlanrfk;
struct asus_pega_rfkill btrfk;
struct asus_pega_rfkill wwanrfk;

acpi_handle handle; /* the handle of the hotk device */
u32 ledd_status; /* status of the LED display */
u8 light_level; /* light sensor level */
Expand Down Expand Up @@ -1263,6 +1279,86 @@ static int asus_rfkill_init(struct asus_laptop *asus)
return result;
}

static int pega_rfkill_set(void *data, bool blocked)
{
struct asus_pega_rfkill *pega_rfk = data;

int ret = asus_pega_lucid_set(pega_rfk->asus, pega_rfk->control_id, !blocked);
pr_warn("Setting rfkill %d, to %d; returned %d\n", pega_rfk->control_id, !blocked, ret);

return ret;
}

static const struct rfkill_ops pega_rfkill_ops = {
.set_block = pega_rfkill_set,
};

static void pega_rfkill_terminate(struct asus_pega_rfkill *pega_rfk)
{
pr_warn("Terminating %d\n", pega_rfk->control_id);
if (pega_rfk->rfkill) {
rfkill_unregister(pega_rfk->rfkill);
rfkill_destroy(pega_rfk->rfkill);
pega_rfk->rfkill = NULL;
}
}

static void pega_rfkill_exit(struct asus_laptop *asus)
{
pega_rfkill_terminate(&asus->wwanrfk);
pega_rfkill_terminate(&asus->btrfk);
pega_rfkill_terminate(&asus->wlanrfk);
}

static int pega_rfkill_setup(struct asus_laptop *asus, struct asus_pega_rfkill *pega_rfk,
const char *name, int controlid, int rfkill_type)
{
int result;

pr_warn("Setting up rfk %s, control %d, type %d\n", name, controlid, rfkill_type);
pega_rfk->control_id = controlid;
pega_rfk->asus = asus;
pega_rfk->rfkill = rfkill_alloc(name, &asus->platform_device->dev,
rfkill_type, &pega_rfkill_ops, pega_rfk);
if (!pega_rfk->rfkill)
return -EINVAL;

result = rfkill_register(pega_rfk->rfkill);
if (result) {
rfkill_destroy(pega_rfk->rfkill);
pega_rfk->rfkill = NULL;
}

return result;
}

static int pega_rfkill_init(struct asus_laptop *asus)
{
int ret = 0;

if(!asus->is_pega_lucid)
return -ENODEV;

ret = pega_rfkill_setup(asus, &asus->wlanrfk, "pega-wlan", PEGA_WLAN, RFKILL_TYPE_WLAN);
if(ret)
return ret;
ret = pega_rfkill_setup(asus, &asus->btrfk, "pega-bt", PEGA_BLUETOOTH, RFKILL_TYPE_BLUETOOTH);
if(ret)
goto err_btrfk;
ret = pega_rfkill_setup(asus, &asus->wwanrfk, "pega-wwan", PEGA_WWAN, RFKILL_TYPE_WWAN);
if(ret)
goto err_wwanrfk;

pr_warn("Pega rfkill init succeeded\n");
return 0;
err_wwanrfk:
pega_rfkill_terminate(&asus->btrfk);
err_btrfk:
pega_rfkill_terminate(&asus->wlanrfk);

return ret;
}

/*
* Input device (i.e. hotkeys)
*/
Expand Down Expand Up @@ -1697,9 +1793,15 @@ static int __devinit asus_acpi_add(struct acpi_device *device)
if (result && result != -ENODEV)
goto fail_pega_accel;

result = pega_rfkill_init(asus);
if (result && result != -ENODEV)
goto fail_pega_rfkill;

asus_device_present = true;
return 0;

fail_pega_rfkill:
pega_accel_exit(asus);
fail_pega_accel:
asus_rfkill_exit(asus);
fail_rfkill:
Expand All @@ -1726,6 +1828,7 @@ static int asus_acpi_remove(struct acpi_device *device, int type)
asus_led_exit(asus);
asus_input_exit(asus);
pega_accel_exit(asus);
pega_rfkill_exit(asus);
asus_platform_exit(asus);

kfree(asus->name);
Expand Down

0 comments on commit 1490839

Please sign in to comment.