summaryrefslogtreecommitdiff
path: root/drivers/platform/x86/asus-laptop.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/platform/x86/asus-laptop.c')
-rw-r--r--drivers/platform/x86/asus-laptop.c266
1 files changed, 175 insertions, 91 deletions
diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c
index b756e07d41b4..d235f44fd7a3 100644
--- a/drivers/platform/x86/asus-laptop.c
+++ b/drivers/platform/x86/asus-laptop.c
@@ -81,6 +81,8 @@ MODULE_PARM_DESC(wapf, "WAPF value");
static int wlan_status = 1;
static int bluetooth_status = 1;
+static int wimax_status = -1;
+static int wwan_status = -1;
module_param(wlan_status, int, 0444);
MODULE_PARM_DESC(wlan_status, "Set the wireless status on boot "
@@ -92,6 +94,16 @@ MODULE_PARM_DESC(bluetooth_status, "Set the wireless status on boot "
"(0 = disabled, 1 = enabled, -1 = don't do anything). "
"default is 1");
+module_param(wimax_status, int, 0444);
+MODULE_PARM_DESC(wimax_status, "Set the wireless status on boot "
+ "(0 = disabled, 1 = enabled, -1 = don't do anything). "
+ "default is 1");
+
+module_param(wwan_status, int, 0444);
+MODULE_PARM_DESC(wwan_status, "Set the wireless status on boot "
+ "(0 = disabled, 1 = enabled, -1 = don't do anything). "
+ "default is 1");
+
/*
* Some events we use, same for all Asus
*/
@@ -114,6 +126,8 @@ MODULE_PARM_DESC(bluetooth_status, "Set the wireless status on boot "
*/
#define WL_RSTS 0x01 /* internal Wifi */
#define BT_RSTS 0x02 /* internal Bluetooth */
+#define WM_RSTS 0x08 /* internal wimax */
+#define WW_RSTS 0x20 /* internal wwan */
/* LED */
#define METHOD_MLED "MLED"
@@ -132,6 +146,11 @@ MODULE_PARM_DESC(bluetooth_status, "Set the wireless status on boot "
*/
#define METHOD_WLAN "WLED"
#define METHOD_BLUETOOTH "BLED"
+
+/* WWAN and WIMAX */
+#define METHOD_WWAN "GSMC"
+#define METHOD_WIMAX "WMXC"
+
#define METHOD_WL_STATUS "RSTS"
/* Brightness */
@@ -236,7 +255,6 @@ struct asus_laptop {
u8 light_level; /* light sensor level */
u8 light_switch; /* light sensor switch value */
u16 event_count[128]; /* count for each event TODO make this better */
- u16 *keycode_map;
};
static const struct key_entry asus_keymap[] = {
@@ -278,6 +296,7 @@ static const struct key_entry asus_keymap[] = {
{KE_KEY, 0x99, { KEY_PHONE } },
{KE_KEY, 0xc4, { KEY_KBDILLUMUP } },
{KE_KEY, 0xc5, { KEY_KBDILLUMDOWN } },
+ {KE_KEY, 0xb5, { KEY_CALC } },
{KE_END, 0},
};
@@ -639,29 +658,29 @@ static int asus_backlight_notify(struct asus_laptop *asus)
static int asus_backlight_init(struct asus_laptop *asus)
{
struct backlight_device *bd;
- struct device *dev = &asus->platform_device->dev;
struct backlight_properties props;
- if (!acpi_check_handle(asus->handle, METHOD_BRIGHTNESS_GET, NULL) &&
- !acpi_check_handle(asus->handle, METHOD_BRIGHTNESS_SET, NULL) &&
- lcd_switch_handle) {
- memset(&props, 0, sizeof(struct backlight_properties));
- props.max_brightness = 15;
-
- bd = backlight_device_register(ASUS_LAPTOP_FILE, dev,
- asus, &asusbl_ops, &props);
- if (IS_ERR(bd)) {
- pr_err("Could not register asus backlight device\n");
- asus->backlight_device = NULL;
- return PTR_ERR(bd);
- }
+ if (acpi_check_handle(asus->handle, METHOD_BRIGHTNESS_GET, NULL) ||
+ acpi_check_handle(asus->handle, METHOD_BRIGHTNESS_SET, NULL) ||
+ !lcd_switch_handle)
+ return 0;
- asus->backlight_device = bd;
+ memset(&props, 0, sizeof(struct backlight_properties));
+ props.max_brightness = 15;
- bd->props.power = FB_BLANK_UNBLANK;
- bd->props.brightness = asus_read_brightness(bd);
- backlight_update_status(bd);
+ bd = backlight_device_register(ASUS_LAPTOP_FILE,
+ &asus->platform_device->dev, asus,
+ &asusbl_ops, &props);
+ if (IS_ERR(bd)) {
+ pr_err("Could not register asus backlight device\n");
+ asus->backlight_device = NULL;
+ return PTR_ERR(bd);
}
+
+ asus->backlight_device = bd;
+ bd->props.brightness = asus_read_brightness(bd);
+ bd->props.power = FB_BLANK_UNBLANK;
+ backlight_update_status(bd);
return 0;
}
@@ -883,6 +902,64 @@ static ssize_t store_bluetooth(struct device *dev,
}
/*
+ * Wimax
+ */
+static int asus_wimax_set(struct asus_laptop *asus, int status)
+{
+ if (write_acpi_int(asus->handle, METHOD_WIMAX, !!status)) {
+ pr_warning("Error setting wimax status to %d", status);
+ return -EIO;
+ }
+ return 0;
+}
+
+static ssize_t show_wimax(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct asus_laptop *asus = dev_get_drvdata(dev);
+
+ return sprintf(buf, "%d\n", asus_wireless_status(asus, WM_RSTS));
+}
+
+static ssize_t store_wimax(struct device *dev,
+ struct device_attribute *attr, const char *buf,
+ size_t count)
+{
+ struct asus_laptop *asus = dev_get_drvdata(dev);
+
+ return sysfs_acpi_set(asus, buf, count, METHOD_WIMAX);
+}
+
+/*
+ * Wwan
+ */
+static int asus_wwan_set(struct asus_laptop *asus, int status)
+{
+ if (write_acpi_int(asus->handle, METHOD_WWAN, !!status)) {
+ pr_warning("Error setting wwan status to %d", status);
+ return -EIO;
+ }
+ return 0;
+}
+
+static ssize_t show_wwan(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct asus_laptop *asus = dev_get_drvdata(dev);
+
+ return sprintf(buf, "%d\n", asus_wireless_status(asus, WW_RSTS));
+}
+
+static ssize_t store_wwan(struct device *dev,
+ struct device_attribute *attr, const char *buf,
+ size_t count)
+{
+ struct asus_laptop *asus = dev_get_drvdata(dev);
+
+ return sysfs_acpi_set(asus, buf, count, METHOD_WWAN);
+}
+
+/*
* Display
*/
static void asus_set_display(struct asus_laptop *asus, int value)
@@ -1065,9 +1142,9 @@ static ssize_t store_gps(struct device *dev, struct device_attribute *attr,
*/
static int asus_gps_rfkill_set(void *data, bool blocked)
{
- acpi_handle handle = data;
+ struct asus_laptop *asus = data;
- return asus_gps_switch(handle, !blocked);
+ return asus_gps_switch(asus, !blocked);
}
static const struct rfkill_ops asus_gps_rfkill_ops = {
@@ -1094,7 +1171,7 @@ static int asus_rfkill_init(struct asus_laptop *asus)
asus->gps_rfkill = rfkill_alloc("asus-gps", &asus->platform_device->dev,
RFKILL_TYPE_GPS,
- &asus_gps_rfkill_ops, NULL);
+ &asus_gps_rfkill_ops, asus);
if (!asus->gps_rfkill)
return -EINVAL;
@@ -1130,7 +1207,6 @@ static int asus_input_init(struct asus_laptop *asus)
input->phys = ASUS_LAPTOP_FILE "/input0";
input->id.bustype = BUS_HOST;
input->dev.parent = &asus->platform_device->dev;
- input_set_drvdata(input, asus);
error = sparse_keymap_setup(input, asus_keymap, NULL);
if (error) {
@@ -1159,6 +1235,7 @@ static void asus_input_exit(struct asus_laptop *asus)
sparse_keymap_free(asus->inputdev);
input_unregister_device(asus->inputdev);
}
+ asus->inputdev = NULL;
}
/*
@@ -1200,111 +1277,111 @@ static void asus_acpi_notify(struct acpi_device *device, u32 event)
static DEVICE_ATTR(infos, S_IRUGO, show_infos, NULL);
static DEVICE_ATTR(wlan, S_IRUGO | S_IWUSR, show_wlan, store_wlan);
-static DEVICE_ATTR(bluetooth, S_IRUGO | S_IWUSR, show_bluetooth,
- store_bluetooth);
+static DEVICE_ATTR(bluetooth, S_IRUGO | S_IWUSR,
+ show_bluetooth, store_bluetooth);
+static DEVICE_ATTR(wimax, S_IRUGO | S_IWUSR, show_wimax, store_wimax);
+static DEVICE_ATTR(wwan, S_IRUGO | S_IWUSR, show_wwan, store_wwan);
static DEVICE_ATTR(display, S_IRUGO | S_IWUSR, show_disp, store_disp);
static DEVICE_ATTR(ledd, S_IRUGO | S_IWUSR, show_ledd, store_ledd);
static DEVICE_ATTR(ls_level, S_IRUGO | S_IWUSR, show_lslvl, store_lslvl);
static DEVICE_ATTR(ls_switch, S_IRUGO | S_IWUSR, show_lssw, store_lssw);
static DEVICE_ATTR(gps, S_IRUGO | S_IWUSR, show_gps, store_gps);
-static void asus_sysfs_exit(struct asus_laptop *asus)
-{
- struct platform_device *device = asus->platform_device;
-
- device_remove_file(&device->dev, &dev_attr_infos);
- device_remove_file(&device->dev, &dev_attr_wlan);
- device_remove_file(&device->dev, &dev_attr_bluetooth);
- device_remove_file(&device->dev, &dev_attr_display);
- device_remove_file(&device->dev, &dev_attr_ledd);
- device_remove_file(&device->dev, &dev_attr_ls_switch);
- device_remove_file(&device->dev, &dev_attr_ls_level);
- device_remove_file(&device->dev, &dev_attr_gps);
-}
+static struct attribute *asus_attributes[] = {
+ &dev_attr_infos.attr,
+ &dev_attr_wlan.attr,
+ &dev_attr_bluetooth.attr,
+ &dev_attr_wimax.attr,
+ &dev_attr_wwan.attr,
+ &dev_attr_display.attr,
+ &dev_attr_ledd.attr,
+ &dev_attr_ls_level.attr,
+ &dev_attr_ls_switch.attr,
+ &dev_attr_gps.attr,
+ NULL
+};
-static int asus_sysfs_init(struct asus_laptop *asus)
+static mode_t asus_sysfs_is_visible(struct kobject *kobj,
+ struct attribute *attr,
+ int idx)
{
- struct platform_device *device = asus->platform_device;
- int err;
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct platform_device *pdev = to_platform_device(dev);
+ struct asus_laptop *asus = platform_get_drvdata(pdev);
+ acpi_handle handle = asus->handle;
+ bool supported;
- err = device_create_file(&device->dev, &dev_attr_infos);
- if (err)
- return err;
+ if (attr == &dev_attr_wlan.attr) {
+ supported = !acpi_check_handle(handle, METHOD_WLAN, NULL);
- if (!acpi_check_handle(asus->handle, METHOD_WLAN, NULL)) {
- err = device_create_file(&device->dev, &dev_attr_wlan);
- if (err)
- return err;
- }
+ } else if (attr == &dev_attr_bluetooth.attr) {
+ supported = !acpi_check_handle(handle, METHOD_BLUETOOTH, NULL);
- if (!acpi_check_handle(asus->handle, METHOD_BLUETOOTH, NULL)) {
- err = device_create_file(&device->dev, &dev_attr_bluetooth);
- if (err)
- return err;
- }
+ } else if (attr == &dev_attr_display.attr) {
+ supported = !acpi_check_handle(handle, METHOD_SWITCH_DISPLAY, NULL);
- if (!acpi_check_handle(asus->handle, METHOD_SWITCH_DISPLAY, NULL)) {
- err = device_create_file(&device->dev, &dev_attr_display);
- if (err)
- return err;
- }
+ } else if (attr == &dev_attr_wimax.attr) {
+ supported =
+ !acpi_check_handle(asus->handle, METHOD_WIMAX, NULL);
- if (!acpi_check_handle(asus->handle, METHOD_LEDD, NULL)) {
- err = device_create_file(&device->dev, &dev_attr_ledd);
- if (err)
- return err;
- }
+ } else if (attr == &dev_attr_wwan.attr) {
+ supported = !acpi_check_handle(asus->handle, METHOD_WWAN, NULL);
- if (!acpi_check_handle(asus->handle, METHOD_ALS_CONTROL, NULL) &&
- !acpi_check_handle(asus->handle, METHOD_ALS_LEVEL, NULL)) {
- err = device_create_file(&device->dev, &dev_attr_ls_switch);
- if (err)
- return err;
- err = device_create_file(&device->dev, &dev_attr_ls_level);
- if (err)
- return err;
- }
+ } else if (attr == &dev_attr_ledd.attr) {
+ supported = !acpi_check_handle(handle, METHOD_LEDD, NULL);
+
+ } else if (attr == &dev_attr_ls_switch.attr ||
+ attr == &dev_attr_ls_level.attr) {
+ supported = !acpi_check_handle(handle, METHOD_ALS_CONTROL, NULL) &&
+ !acpi_check_handle(handle, METHOD_ALS_LEVEL, NULL);
- if (!acpi_check_handle(asus->handle, METHOD_GPS_ON, NULL) &&
- !acpi_check_handle(asus->handle, METHOD_GPS_OFF, NULL) &&
- !acpi_check_handle(asus->handle, METHOD_GPS_STATUS, NULL)) {
- err = device_create_file(&device->dev, &dev_attr_gps);
- if (err)
- return err;
+ } else if (attr == &dev_attr_gps.attr) {
+ supported = !acpi_check_handle(handle, METHOD_GPS_ON, NULL) &&
+ !acpi_check_handle(handle, METHOD_GPS_OFF, NULL) &&
+ !acpi_check_handle(handle, METHOD_GPS_STATUS, NULL);
+ } else {
+ supported = true;
}
- return err;
+ return supported ? attr->mode : 0;
}
+
+static const struct attribute_group asus_attr_group = {
+ .is_visible = asus_sysfs_is_visible,
+ .attrs = asus_attributes,
+};
+
static int asus_platform_init(struct asus_laptop *asus)
{
- int err;
+ int result;
asus->platform_device = platform_device_alloc(ASUS_LAPTOP_FILE, -1);
if (!asus->platform_device)
return -ENOMEM;
platform_set_drvdata(asus->platform_device, asus);
- err = platform_device_add(asus->platform_device);
- if (err)
+ result = platform_device_add(asus->platform_device);
+ if (result)
goto fail_platform_device;
- err = asus_sysfs_init(asus);
- if (err)
+ result = sysfs_create_group(&asus->platform_device->dev.kobj,
+ &asus_attr_group);
+ if (result)
goto fail_sysfs;
+
return 0;
fail_sysfs:
- asus_sysfs_exit(asus);
platform_device_del(asus->platform_device);
fail_platform_device:
platform_device_put(asus->platform_device);
- return err;
+ return result;
}
static void asus_platform_exit(struct asus_laptop *asus)
{
- asus_sysfs_exit(asus);
+ sysfs_remove_group(&asus->platform_device->dev.kobj, &asus_attr_group);
platform_device_unregister(asus->platform_device);
}
@@ -1408,7 +1485,8 @@ static int asus_laptop_get_info(struct asus_laptop *asus)
/*
* The HWRS method return informations about the hardware.
- * 0x80 bit is for WLAN, 0x100 for Bluetooth.
+ * 0x80 bit is for WLAN, 0x100 for Bluetooth,
+ * 0x40 for WWAN, 0x10 for WIMAX.
* The significance of others is yet to be found.
*/
status =
@@ -1428,8 +1506,6 @@ static int asus_laptop_get_info(struct asus_laptop *asus)
return AE_OK;
}
-static bool asus_device_present;
-
static int __devinit asus_acpi_init(struct asus_laptop *asus)
{
int result = 0;
@@ -1453,6 +1529,12 @@ static int __devinit asus_acpi_init(struct asus_laptop *asus)
if (wlan_status >= 0)
asus_wlan_set(asus, !!wlan_status);
+ if (wimax_status >= 0)
+ asus_wimax_set(asus, !!wimax_status);
+
+ if (wwan_status >= 0)
+ asus_wwan_set(asus, !!wwan_status);
+
/* Keyboard Backlight is on by default */
if (!acpi_check_handle(asus->handle, METHOD_KBD_LIGHT_SET, NULL))
asus_kled_set(asus, 1);
@@ -1474,6 +1556,8 @@ static int __devinit asus_acpi_init(struct asus_laptop *asus)
return result;
}
+static bool asus_device_present;
+
static int __devinit asus_acpi_add(struct acpi_device *device)
{
struct asus_laptop *asus;