2010-02-02 07:47:17

by Corentin Chary

[permalink] [raw]
Subject: [PATCH 00/28] acpi4asus: asus-laptop rewrite for 2.6.33

Hi Len,
Here is a big series of patchs, only for asus-laptop.

It cleans asus-laptop like Alan Jenkins did for eeepc-laptop: no
more global context, and the driver *could* support multiple
acpi device (that will never happen, but it's not a reason to do
ugly code).

This has some side effects: bugs where the device path was \SB.HOTK
instead of \SB.ATKD are fixed, because a static path is no more used :).

It also adds some features like an rfkill handler for the gps, rewrite
the input code to use sparse_keymap library and add new backlight notifications.

The last patch is a checkpatch-cleanup.

Thanks,

Corentin Chary (28):
asus-laptop: add wireless and bluetooth status parameter
asus-laptop: set the right paths in the documentation
asus-laptop: no need to check argument of set_brightness()
asus-laptop: simplify write_acpi_int
asus-laptop: use tabs to indent macros and remove unused ones
asus-laptop: remove unecessary hotk != NULL check
asus-laptop: change initialization order
asus-laptop: revise names
asus-laptop: move backlight and dsdt info inside asus_laptop struct
asus-laptop: callbacks should use "driver data" parameter or field
asus-laptop: code movement
asus-laptop: stop using read_status for bluetooth and wlan
asus-laptop: stop using read_status and store_status for GPS
asus-laptop: stop using read_status for lcd
asus-laptop: removing read_status/store_status/write_status and
asus->status
asus-laptop: rename function talking directly to acpi with asus_xxx
scheme
asus-laptop: stop using ASUS_HANDLE and use relative methods instead
asus-laptop: add error check for write_acpi_int calls
asus-laptop: rename wireless_status to wlan_status to avoid confusion
asus-laptop: switch to sparse keymap library
asus-laptop: add bluetooth keys found on M9V
asus-laptop: add backlight changes notifications
asus-laptop: leds, remove dead code and fix
asus_led_exit()/asus_led_init()
asus-laptop: set initial lcd state
asus-laptop: add gps rfkill
asus-laptop: clean led code
asus-laptop: use device_create_file() instead of platform_group
asus-laptop: fix style problems reported by checkpath.pl

.../ABI/testing/sysfs-platform-asus-laptop | 12 +-
drivers/platform/x86/Kconfig | 2 +
drivers/platform/x86/asus-laptop.c | 1741 ++++++++++----------
3 files changed, 914 insertions(+), 841 deletions(-)


2010-02-02 07:47:12

by Corentin Chary

[permalink] [raw]
Subject: [PATCH 04/28] asus-laptop: simplify write_acpi_int

We only need a buffer for "INIT". Adds write_acpi_init_ret for it.

Signed-off-by: Corentin Chary <[email protected]>
---
drivers/platform/x86/asus-laptop.c | 27 ++++++++++++++++-----------
1 files changed, 16 insertions(+), 11 deletions(-)

diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c
index 013ab86..7058cb5 100644
--- a/drivers/platform/x86/asus-laptop.c
+++ b/drivers/platform/x86/asus-laptop.c
@@ -352,8 +352,8 @@ static struct key_entry asus_keymap[] = {
*
* returns 0 if write is successful, -1 else.
*/
-static int write_acpi_int(acpi_handle handle, const char *method, int val,
- struct acpi_buffer *output)
+static int write_acpi_int_ret(acpi_handle handle, const char *method, int val,
+ struct acpi_buffer *output)
{
struct acpi_object_list params; /* list of input parameters (an int) */
union acpi_object in_obj; /* the only param we use */
@@ -374,6 +374,11 @@ static int write_acpi_int(acpi_handle handle, const char *method, int val,
return -1;
}

+static int write_acpi_int(acpi_handle handle, const char *method, int val)
+{
+ return write_acpi_int_ret(handle, method, val, NULL);
+}
+
static int read_wireless_status(int mask)
{
unsigned long long status;
@@ -437,7 +442,7 @@ static void write_status(acpi_handle handle, int out, int mask)
break;
}

- if (write_acpi_int(handle, NULL, out, NULL))
+ if (write_acpi_int(handle, NULL, out))
pr_warning(" write failed %x\n", mask);
}

@@ -496,7 +501,7 @@ static int set_kled_lvl(int kblv)
else
kblv = 0;

- if (write_acpi_int(kled_set_handle, NULL, kblv, NULL)) {
+ if (write_acpi_int(kled_set_handle, NULL, kblv)) {
pr_warning("Keyboard LED display write failed\n");
return -EINVAL;
}
@@ -571,7 +576,7 @@ static int read_brightness(struct backlight_device *bd)

static int set_brightness(struct backlight_device *bd, int value)
{
- if (write_acpi_int(brightness_set_handle, NULL, value, NULL)) {
+ if (write_acpi_int(brightness_set_handle, NULL, value)) {
pr_warning("Error changing brightness\n");
return -EIO;
}
@@ -710,7 +715,7 @@ static ssize_t store_ledd(struct device *dev, struct device_attribute *attr,

rv = parse_arg(buf, count, &value);
if (rv > 0) {
- if (write_acpi_int(ledd_set_handle, NULL, value, NULL))
+ if (write_acpi_int(ledd_set_handle, NULL, value))
pr_warning("LED display write failed\n");
else
hotk->ledd_status = (u32) value;
@@ -755,7 +760,7 @@ static ssize_t store_bluetooth(struct device *dev,
static void set_display(int value)
{
/* no sanity check needed for now */
- if (write_acpi_int(display_set_handle, NULL, value, NULL))
+ if (write_acpi_int(display_set_handle, NULL, value))
pr_warning("Error setting display\n");
return;
}
@@ -814,7 +819,7 @@ static ssize_t store_disp(struct device *dev, struct device_attribute *attr,
*/
static void set_light_sens_switch(int value)
{
- if (write_acpi_int(ls_switch_handle, NULL, value, NULL))
+ if (write_acpi_int(ls_switch_handle, NULL, value))
pr_warning("Error setting light sensor switch\n");
hotk->light_switch = value;
}
@@ -839,7 +844,7 @@ static ssize_t store_lssw(struct device *dev, struct device_attribute *attr,

static void set_light_sens_level(int value)
{
- if (write_acpi_int(ls_level_handle, NULL, value, NULL))
+ if (write_acpi_int(ls_level_handle, NULL, value))
pr_warning("Error setting light sensor level\n");
hotk->light_level = value;
}
@@ -1104,7 +1109,7 @@ static int asus_hotk_get_info(void)
pr_warning("Couldn't get the DSDT table header\n");

/* We have to write 0 on init this far for all ASUS models */
- if (write_acpi_int(hotk->handle, "INIT", 0, &buffer)) {
+ if (write_acpi_int_ret(hotk->handle, "INIT", 0, &buffer)) {
pr_err("Hotkey initialization failed\n");
return -ENODEV;
}
@@ -1119,7 +1124,7 @@ static int asus_hotk_get_info(void)
(uint) bsts_result);

/* This too ... */
- write_acpi_int(hotk->handle, "CWAP", wapf, NULL);
+ write_acpi_int(hotk->handle, "CWAP", wapf);

/*
* Try to match the object returned by INIT to the specific model.
--
1.6.6.1

2010-02-02 07:47:15

by Corentin Chary

[permalink] [raw]
Subject: [PATCH 01/28] asus-laptop: add wireless and bluetooth status parameter

These to parameter allow to set the status of wlan and bluetooth
device when the module load. On some models, the device will
always be down on boot, so the default behavior is to always
enable these devices.

Signed-off-by: Corentin Chary <[email protected]>
---
drivers/platform/x86/asus-laptop.c | 19 +++++++++++++++++--
1 files changed, 17 insertions(+), 2 deletions(-)

diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c
index 61a1c75..1d799b3 100644
--- a/drivers/platform/x86/asus-laptop.c
+++ b/drivers/platform/x86/asus-laptop.c
@@ -113,6 +113,19 @@ static uint wapf = 1;
module_param(wapf, uint, 0644);
MODULE_PARM_DESC(wapf, "WAPF value");

+static uint wireless_status = 1;
+static uint bluetooth_status = 1;
+
+module_param(wireless_status, uint, 0644);
+MODULE_PARM_DESC(wireless_status, "Set the wireless status on boot "
+ "(0 = disabled, 1 = enabled, -1 = don't do anything). "
+ "default is 1");
+
+module_param(bluetooth_status, uint, 0644);
+MODULE_PARM_DESC(bluetooth_status, "Set the wireless status on boot "
+ "(0 = disabled, 1 = enabled, -1 = don't do anything). "
+ "default is 1");
+
#define ASUS_HANDLE(object, paths...) \
static acpi_handle object##_handle = NULL; \
static char *object##_paths[] = { paths }
@@ -1272,8 +1285,10 @@ static int asus_hotk_add(struct acpi_device *device)
asus_hotk_found = 1;

/* WLED and BLED are on by default */
- write_status(bt_switch_handle, 1, BT_ON);
- write_status(wl_switch_handle, 1, WL_ON);
+ if (bluetooth_status != -1)
+ write_status(bt_switch_handle, !!bluetooth_status, BT_ON);
+ if (wireless_status != -1)
+ write_status(wl_switch_handle, !!wireless_status, WL_ON);

/* If the h/w switch is off, we need to check the real status */
write_status(NULL, read_status(BT_ON), BT_ON);
--
1.6.6.1

2010-02-02 07:47:11

by Corentin Chary

[permalink] [raw]
Subject: [PATCH 02/28] asus-laptop: set the right paths in the documentation

Signed-off-by: Corentin Chary <[email protected]>
---
.../ABI/testing/sysfs-platform-asus-laptop | 12 ++++++------
1 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-platform-asus-laptop b/Documentation/ABI/testing/sysfs-platform-asus-laptop
index a1cb660..1d77539 100644
--- a/Documentation/ABI/testing/sysfs-platform-asus-laptop
+++ b/Documentation/ABI/testing/sysfs-platform-asus-laptop
@@ -1,4 +1,4 @@
-What: /sys/devices/platform/asus-laptop/display
+What: /sys/devices/platform/asus_laptop/display
Date: January 2007
KernelVersion: 2.6.20
Contact: "Corentin Chary" <[email protected]>
@@ -13,7 +13,7 @@ Description:
Ex: - 0 (0000b) means no display
- 3 (0011b) CRT+LCD.

-What: /sys/devices/platform/asus-laptop/gps
+What: /sys/devices/platform/asus_laptop/gps
Date: January 2007
KernelVersion: 2.6.20
Contact: "Corentin Chary" <[email protected]>
@@ -21,7 +21,7 @@ Description:
Control the gps device. 1 means on, 0 means off.
Users: Lapsus

-What: /sys/devices/platform/asus-laptop/ledd
+What: /sys/devices/platform/asus_laptop/ledd
Date: January 2007
KernelVersion: 2.6.20
Contact: "Corentin Chary" <[email protected]>
@@ -29,11 +29,11 @@ Description:
Some models like the W1N have a LED display that can be
used to display several informations.
To control the LED display, use the following :
- echo 0x0T000DDD > /sys/devices/platform/asus-laptop/
+ echo 0x0T000DDD > /sys/devices/platform/asus_laptop/
where T control the 3 letters display, and DDD the 3 digits display.
The DDD table can be found in Documentation/laptops/asus-laptop.txt

-What: /sys/devices/platform/asus-laptop/bluetooth
+What: /sys/devices/platform/asus_laptop/bluetooth
Date: January 2007
KernelVersion: 2.6.20
Contact: "Corentin Chary" <[email protected]>
@@ -42,7 +42,7 @@ Description:
This may control the led, the device or both.
Users: Lapsus

-What: /sys/devices/platform/asus-laptop/wlan
+What: /sys/devices/platform/asus_laptop/wlan
Date: January 2007
KernelVersion: 2.6.20
Contact: "Corentin Chary" <[email protected]>
--
1.6.6.1

2010-02-02 07:47:09

by Corentin Chary

[permalink] [raw]
Subject: [PATCH 03/28] asus-laptop: no need to check argument of set_brightness()

We already tell the backlight class our maximum brightness value; it
will validate the user requested values for us.

Signed-off-by: Corentin Chary <[email protected]>
---
drivers/platform/x86/asus-laptop.c | 10 ++--------
1 files changed, 2 insertions(+), 8 deletions(-)

diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c
index 1d799b3..013ab86 100644
--- a/drivers/platform/x86/asus-laptop.c
+++ b/drivers/platform/x86/asus-laptop.c
@@ -571,17 +571,11 @@ static int read_brightness(struct backlight_device *bd)

static int set_brightness(struct backlight_device *bd, int value)
{
- int ret = 0;
-
- value = (0 < value) ? ((15 < value) ? 15 : value) : 0;
- /* 0 <= value <= 15 */
-
if (write_acpi_int(brightness_set_handle, NULL, value, NULL)) {
pr_warning("Error changing brightness\n");
- ret = -EIO;
+ return -EIO;
}
-
- return ret;
+ return 0;
}

static int update_bl_status(struct backlight_device *bd)
--
1.6.6.1

2010-02-02 07:52:20

by Corentin Chary

[permalink] [raw]
Subject: [PATCH 28/28] asus-laptop: fix style problems reported by checkpath.pl

Signed-off-by: Corentin Chary <[email protected]>
---
drivers/platform/x86/asus-laptop.c | 94 ++++++++++++++++++------------------
1 files changed, 47 insertions(+), 47 deletions(-)

diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c
index d0d117b..791fcf3 100644
--- a/drivers/platform/x86/asus-laptop.c
+++ b/drivers/platform/x86/asus-laptop.c
@@ -45,12 +45,12 @@
#include <linux/fb.h>
#include <linux/leds.h>
#include <linux/platform_device.h>
-#include <acpi/acpi_drivers.h>
-#include <acpi/acpi_bus.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#include <linux/input.h>
#include <linux/input/sparse-keymap.h>
#include <linux/rfkill.h>
+#include <acpi/acpi_drivers.h>
+#include <acpi/acpi_bus.h>

#define ASUS_LAPTOP_VERSION "0.42"

@@ -94,10 +94,10 @@ MODULE_PARM_DESC(bluetooth_status, "Set the wireless status on boot "
/*
* Some events we use, same for all Asus
*/
-#define ATKD_BR_UP 0x10 // (event & ~ATKD_BR_UP) = brightness level
-#define ATKD_BR_DOWN 0x20 // (event & ~ATKD_BR_DOWN) = britghness level
+#define ATKD_BR_UP 0x10 /* (event & ~ATKD_BR_UP) = brightness level */
+#define ATKD_BR_DOWN 0x20 /* (event & ~ATKD_BR_DOWN) = britghness level */
#define ATKD_BR_MIN ATKD_BR_UP
-#define ATKD_BR_MAX (ATKD_BR_DOWN | 0xF) // 0x2f
+#define ATKD_BR_MAX (ATKD_BR_DOWN | 0xF) /* 0x2f */
#define ATKD_LCD_ON 0x33
#define ATKD_LCD_OFF 0x34

@@ -114,10 +114,6 @@ MODULE_PARM_DESC(bluetooth_status, "Set the wireless status on boot "
#define WL_RSTS 0x01 /* internal Wifi */
#define BT_RSTS 0x02 /* internal Bluetooth */

-#define ASUS_HANDLE(object, paths...) \
- static acpi_handle object##_handle = NULL; \
- static char *object##_paths[] = { paths }
-
/* LED */
#define METHOD_MLED "MLED"
#define METHOD_TLED "TLED"
@@ -142,40 +138,44 @@ MODULE_PARM_DESC(bluetooth_status, "Set the wireless status on boot "
#define METHOD_BRIGHTNESS_GET "GPLV"

/* Backlight */
-ASUS_HANDLE(lcd_switch, "\\_SB.PCI0.SBRG.EC0._Q10", /* All new models */
- "\\_SB.PCI0.ISA.EC0._Q10", /* A1x */
- "\\_SB.PCI0.PX40.ECD0._Q10", /* L3C */
- "\\_SB.PCI0.PX40.EC0.Q10", /* M1A */
- "\\_SB.PCI0.LPCB.EC0._Q10", /* P30 */
- "\\_SB.PCI0.LPCB.EC0._Q0E", /* P30/P35 */
- "\\_SB.PCI0.PX40.Q10", /* S1x */
- "\\Q10"); /* A2x, L2D, L3D, M2E */
+static acpi_handle lcd_switch_handle;
+static const char *lcd_switch_paths[] = {
+ "\\_SB.PCI0.SBRG.EC0._Q10", /* All new models */
+ "\\_SB.PCI0.ISA.EC0._Q10", /* A1x */
+ "\\_SB.PCI0.PX40.ECD0._Q10", /* L3C */
+ "\\_SB.PCI0.PX40.EC0.Q10", /* M1A */
+ "\\_SB.PCI0.LPCB.EC0._Q10", /* P30 */
+ "\\_SB.PCI0.LPCB.EC0._Q0E", /* P30/P35 */
+ "\\_SB.PCI0.PX40.Q10", /* S1x */
+ "\\Q10"}; /* A2x, L2D, L3D, M2E */

/* Display */
#define METHOD_SWITCH_DISPLAY "SDSP"
-ASUS_HANDLE(display_get,
- /* A6B, A6K A6R A7D F3JM L4R M6R A3G M6A M6V VX-1 V6J V6V W3Z */
- "\\_SB.PCI0.P0P1.VGA.GETD",
- /* A3E A4K, A4D A4L A6J A7J A8J Z71V M9V S5A M5A z33A W1Jc W2V G1 */
- "\\_SB.PCI0.P0P2.VGA.GETD",
- /* A6V A6Q */
- "\\_SB.PCI0.P0P3.VGA.GETD",
- /* A6T, A6M */
- "\\_SB.PCI0.P0PA.VGA.GETD",
- /* L3C */
- "\\_SB.PCI0.PCI1.VGAC.NMAP",
- /* Z96F */
- "\\_SB.PCI0.VGA.GETD",
- /* A2D */
- "\\ACTD",
- /* A4G Z71A W1N W5A W5F M2N M3N M5N M6N S1N S5N */
- "\\ADVG",
- /* P30 */
- "\\DNXT",
- /* A2H D1 L2D L3D L3H L2E L5D L5C M1A M2E L4L W3V */
- "\\INFB",
- /* A3F A6F A3N A3L M6N W3N W6A */
- "\\SSTE");
+
+static acpi_handle display_get_handle;
+static const char *display_get_paths[] = {
+ /* A6B, A6K A6R A7D F3JM L4R M6R A3G M6A M6V VX-1 V6J V6V W3Z */
+ "\\_SB.PCI0.P0P1.VGA.GETD",
+ /* A3E A4K, A4D A4L A6J A7J A8J Z71V M9V S5A M5A z33A W1Jc W2V G1 */
+ "\\_SB.PCI0.P0P2.VGA.GETD",
+ /* A6V A6Q */
+ "\\_SB.PCI0.P0P3.VGA.GETD",
+ /* A6T, A6M */
+ "\\_SB.PCI0.P0PA.VGA.GETD",
+ /* L3C */
+ "\\_SB.PCI0.PCI1.VGAC.NMAP",
+ /* Z96F */
+ "\\_SB.PCI0.VGA.GETD",
+ /* A2D */
+ "\\ACTD",
+ /* A4G Z71A W1N W5A W5F M2N M3N M5N M6N S1N S5N */
+ "\\ADVG",
+ /* P30 */
+ "\\DNXT",
+ /* A2H D1 L2D L3D L3H L2E L5D L5C M1A M2E L4L W3V */
+ "\\INFB",
+ /* A3F A6F A3N A3L M6N W3N W6A */
+ "\\SSTE"};

#define METHOD_ALS_CONTROL "ALSC" /* Z71A Z71V */
#define METHOD_ALS_LEVEL "ALSL" /* Z71A Z71V */
@@ -426,7 +426,7 @@ static void asus_kled_cdev_set(struct led_classdev *led_cdev,
struct asus_led *led = container_of(led_cdev, struct asus_led, led);
struct asus_laptop *asus = led->asus;

- led->wk = value;
+ led->wk = value;
queue_work(asus->led_workqueue, &led->work);
}

@@ -474,7 +474,7 @@ static int asus_led_register(struct asus_laptop *asus,
struct led_classdev *led_cdev = &led->led;

if (!method || acpi_check_handle(asus->handle, method, NULL))
- return 0; /* Led not present */
+ return 0; /* Led not present */

led->asus = asus;
led->method = method;
@@ -687,8 +687,8 @@ static ssize_t show_infos(struct device *dev,
acpi_status rv = AE_OK;

/*
- * We use the easy way, we don't care of off and count, so we don't set eof
- * to 1
+ * We use the easy way, we don't care of off and count,
+ * so we don't set eof to 1
*/

len += sprintf(page, ASUS_LAPTOP_NAME " " ASUS_LAPTOP_VERSION "\n");
@@ -904,7 +904,7 @@ static int read_display(struct asus_laptop *asus)
pr_warning("Error reading display status\n");
}

- value &= 0x0F; /* needed for some models, shouldn't hurt others */
+ value &= 0x0F; /* needed for some models, shouldn't hurt others */

return value;
}
@@ -1041,7 +1041,7 @@ static ssize_t show_gps(struct device *dev,
static ssize_t store_gps(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
- struct asus_laptop *asus = dev_get_drvdata(dev);
+ struct asus_laptop *asus = dev_get_drvdata(dev);
int rv, value;
int ret;

--
1.6.6.1

2010-02-02 07:52:28

by Corentin Chary

[permalink] [raw]
Subject: [PATCH 12/28] asus-laptop: stop using read_status for bluetooth and wlan

Signed-off-by: Corentin Chary <[email protected]>
---
drivers/platform/x86/asus-laptop.c | 55 +++++++++++++++++++-----------------
1 files changed, 29 insertions(+), 26 deletions(-)

diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c
index 940ce3d..cee751e 100644
--- a/drivers/platform/x86/asus-laptop.c
+++ b/drivers/platform/x86/asus-laptop.c
@@ -239,6 +239,9 @@ struct asus_laptop {

struct asus_laptop_leds leds;

+ int wireless_status;
+ bool have_rsts;
+
acpi_handle handle; /* the handle of the hotk device */
char status; /* status of the hotk, for LEDs, ... */
u32 ledd_status; /* status of the LED display */
@@ -328,23 +331,6 @@ static int write_acpi_int(acpi_handle handle, const char *method, int val)
return write_acpi_int_ret(handle, method, val, NULL);
}

-static int read_wireless_status(struct asus_laptop *asus, int mask)
-{
- unsigned long long status;
- acpi_status rv = AE_OK;
-
- if (!wireless_status_handle)
- return (asus->status & mask) ? 1 : 0;
-
- rv = acpi_evaluate_integer(wireless_status_handle, NULL, NULL, &status);
- if (ACPI_FAILURE(rv))
- pr_warning("Error reading Wireless status\n");
- else
- return (status & mask) ? 1 : 0;
-
- return (asus->status & mask) ? 1 : 0;
-}
-
static int read_gps_status(struct asus_laptop *asus)
{
unsigned long long status;
@@ -362,10 +348,7 @@ static int read_gps_status(struct asus_laptop *asus)
/* Generic LED functions */
static int read_status(struct asus_laptop *asus, int mask)
{
- /* There is a special method for both wireless devices */
- if (mask == BT_ON || mask == WL_ON)
- return read_wireless_status(asus, mask);
- else if (mask == GPS_ON)
+ if (mask == GPS_ON)
return read_gps_status(asus);

return (asus->status & mask) ? 1 : 0;
@@ -812,6 +795,25 @@ static ssize_t store_ledd(struct device *dev, struct device_attribute *attr,
}

/*
+ * Wireless
+ */
+static int asus_wireless_status(struct asus_laptop *asus, int mask)
+{
+ unsigned long long status;
+ acpi_status rv = AE_OK;
+
+ if (!asus->have_rsts)
+ return (asus->wireless_status & mask) ? 1 : 0;
+
+ rv = acpi_evaluate_integer(wireless_status_handle, NULL, NULL, &status);
+ if (ACPI_FAILURE(rv)) {
+ pr_warning("Error reading Wireless status\n");
+ return -EINVAL;
+ }
+ return !!(status & mask);
+}
+
+/*
* WLAN
*/
static ssize_t show_wlan(struct device *dev,
@@ -819,7 +821,7 @@ static ssize_t show_wlan(struct device *dev,
{
struct asus_laptop *asus = dev_get_drvdata(dev);

- return sprintf(buf, "%d\n", read_status(asus, WL_ON));
+ return sprintf(buf, "%d\n", asus_wireless_status(asus, WL_ON));
}

static ssize_t store_wlan(struct device *dev, struct device_attribute *attr,
@@ -838,7 +840,7 @@ static ssize_t show_bluetooth(struct device *dev,
{
struct asus_laptop *asus = dev_get_drvdata(dev);

- return sprintf(buf, "%d\n", read_status(asus, BT_ON));
+ return sprintf(buf, "%d\n", asus_wireless_status(asus, BT_ON));
}

static ssize_t store_bluetooth(struct device *dev,
@@ -1371,7 +1373,8 @@ static int asus_laptop_get_info(struct asus_laptop *asus)
if (hwrs_result & BT_HWRS)
ASUS_HANDLE_INIT(bt_switch);

- ASUS_HANDLE_INIT(wireless_status);
+ if (!ASUS_HANDLE_INIT(wireless_status))
+ asus->have_rsts = true;

ASUS_HANDLE_INIT(brightness_set);
ASUS_HANDLE_INIT(brightness_get);
@@ -1424,8 +1427,8 @@ static int __devinit asus_acpi_init(struct asus_laptop *asus)
write_status(asus, wl_switch_handle, !!wireless_status, WL_ON);

/* If the h/w switch is off, we need to check the real status */
- write_status(asus, NULL, read_status(asus, BT_ON), BT_ON);
- write_status(asus, NULL, read_status(asus, WL_ON), WL_ON);
+ write_status(asus, NULL, asus_wireless_status(asus, BT_ON), BT_ON);
+ write_status(asus, NULL, asus_wireless_status(asus, WL_ON), WL_ON);

/* LCD Backlight is on by default */
write_status(asus, NULL, 1, LCD_ON);
--
1.6.6.1

2010-02-02 07:52:39

by Corentin Chary

[permalink] [raw]
Subject: [PATCH 24/28] asus-laptop: set initial lcd state

From: Corentin Chary <[email protected]>

There is no way to find the initial lcd state. A quick workaround
is to set it "on" by default. Anyway this feature is scheduled for removal.

Signed-off-by: Corentin Chary <[email protected]>
---
drivers/platform/x86/asus-laptop.c | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c
index ca144d2..1d61094 100644
--- a/drivers/platform/x86/asus-laptop.c
+++ b/drivers/platform/x86/asus-laptop.c
@@ -1421,6 +1421,8 @@ static int __devinit asus_acpi_init(struct asus_laptop *asus)
!acpi_check_handle(asus->handle, METHOD_GPS_OFF, NULL) &&
!acpi_check_handle(asus->handle, METHOD_GPS_STATUS, NULL))
asus_gps_switch(asus, 1);
+
+ asus->lcd_state = 1; /* LCD should be on when the module load */
return result;
}

--
1.6.6.1

2010-02-02 07:52:36

by Corentin Chary

[permalink] [raw]
Subject: [PATCH 07/28] asus-laptop: change initialization order

Clean asus-laptop initialization to match new eeepc-laptop code.

Signed-off-by: Corentin Chary <[email protected]>
---
drivers/platform/x86/asus-laptop.c | 369 ++++++++++++++++++------------------
1 files changed, 180 insertions(+), 189 deletions(-)

diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c
index 74463a0..8834405 100644
--- a/drivers/platform/x86/asus-laptop.c
+++ b/drivers/platform/x86/asus-laptop.c
@@ -201,6 +201,8 @@ ASUS_HANDLE(kled_get, ASUS_HOTK_PREFIX "GLKB");
*/
struct asus_hotk {
char *name; /* laptop name */
+
+ struct platform_device *platform_device;
struct acpi_device *device; /* the device we are in */
acpi_handle handle; /* the handle of the hotk device */
char status; /* status of the hotk, for LEDs, ... */
@@ -222,33 +224,6 @@ static struct acpi_table_header *asus_info;
/* The actual device the driver binds to */
static struct asus_hotk *hotk;

-/*
- * The hotkey driver declaration
- */
-static const struct acpi_device_id asus_device_ids[] = {
- {"ATK0100", 0},
- {"ATK0101", 0},
- {"", 0},
-};
-MODULE_DEVICE_TABLE(acpi, asus_device_ids);
-
-static int asus_hotk_add(struct acpi_device *device);
-static int asus_hotk_remove(struct acpi_device *device, int type);
-static void asus_hotk_notify(struct acpi_device *device, u32 event);
-
-static struct acpi_driver asus_hotk_driver = {
- .name = ASUS_HOTK_NAME,
- .class = ASUS_HOTK_CLASS,
- .owner = THIS_MODULE,
- .ids = asus_device_ids,
- .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS,
- .ops = {
- .add = asus_hotk_add,
- .remove = asus_hotk_remove,
- .notify = asus_hotk_notify,
- },
-};
-
/* The backlight device /sys/class/backlight */
static struct backlight_device *asus_backlight_device;

@@ -936,7 +911,7 @@ static int asus_setkeycode(struct input_dev *dev, int scancode, int keycode)
return -EINVAL;
}

-static void asus_hotk_notify(struct acpi_device *device, u32 event)
+static void asus_acpi_notify(struct acpi_device *device, u32 event)
{
static struct key_entry *key;
u16 count;
@@ -1013,19 +988,49 @@ static struct attribute *asuspf_attributes[] = {
NULL
};

-static struct attribute_group asuspf_attribute_group = {
+static struct attribute_group platform_attribute_group = {
.attrs = asuspf_attributes
};

-static struct platform_driver asuspf_driver = {
+static int asus_platform_init(void)
+{
+ int result;
+
+ hotk->platform_device = platform_device_alloc(ASUS_HOTK_FILE, -1);
+ if (!hotk->platform_device)
+ return -ENOMEM;
+
+ result = platform_device_add(hotk->platform_device);
+ if (result)
+ goto fail_platform_device;
+
+ result = sysfs_create_group(&hotk->platform_device->dev.kobj,
+ &platform_attribute_group);
+ if (result)
+ goto fail_sysfs;
+ return 0;
+
+fail_sysfs:
+ platform_device_del(hotk->platform_device);
+fail_platform_device:
+ platform_device_put(hotk->platform_device);
+ return result;
+}
+
+static void asus_platform_exit(void)
+{
+ sysfs_remove_group(&hotk->platform_device->dev.kobj,
+ &platform_attribute_group);
+ platform_device_unregister(hotk->platform_device);
+}
+
+static struct platform_driver platform_driver = {
.driver = {
.name = ASUS_HOTK_FILE,
.owner = THIS_MODULE,
}
};

-static struct platform_device *asuspf_device;
-
static void asus_hotk_add_fs(void)
{
ASUS_SET_DEVICE_ATTR(infos, 0444, show_infos, NULL);
@@ -1196,7 +1201,7 @@ static int asus_hotk_get_info(void)
return AE_OK;
}

-static int asus_input_init(void)
+static int asus_input_init(struct device *dev)
{
const struct key_entry *key;
int result;
@@ -1207,6 +1212,7 @@ static int asus_input_init(void)
return 0;
}
hotk->inputdev->name = "Asus Laptop extra buttons";
+ hotk->inputdev->dev.parent = dev;
hotk->inputdev->phys = ASUS_HOTK_FILE "/input0";
hotk->inputdev->id.bustype = BUS_HOST;
hotk->inputdev->getkeycode = asus_getkeycode;
@@ -1228,101 +1234,6 @@ static int asus_input_init(void)
return result;
}

-static int asus_hotk_check(void)
-{
- int result = 0;
-
- result = acpi_bus_get_status(hotk->device);
- if (result)
- return result;
-
- if (hotk->device->status.present) {
- result = asus_hotk_get_info();
- } else {
- pr_err("Hotkey device not present, aborting\n");
- return -EINVAL;
- }
-
- return result;
-}
-
-static int asus_hotk_found;
-
-static int asus_hotk_add(struct acpi_device *device)
-{
- int result;
-
- pr_notice("Asus Laptop Support version %s\n",
- ASUS_LAPTOP_VERSION);
-
- hotk = kzalloc(sizeof(struct asus_hotk), GFP_KERNEL);
- if (!hotk)
- return -ENOMEM;
-
- hotk->handle = device->handle;
- strcpy(acpi_device_name(device), ASUS_HOTK_DEVICE_NAME);
- strcpy(acpi_device_class(device), ASUS_HOTK_CLASS);
- device->driver_data = hotk;
- hotk->device = device;
-
- result = asus_hotk_check();
- if (result)
- goto end;
-
- asus_hotk_add_fs();
-
- asus_hotk_found = 1;
-
- /* WLED and BLED are on by default */
- if (bluetooth_status != -1)
- write_status(bt_switch_handle, !!bluetooth_status, BT_ON);
- if (wireless_status != -1)
- write_status(wl_switch_handle, !!wireless_status, WL_ON);
-
- /* If the h/w switch is off, we need to check the real status */
- write_status(NULL, read_status(BT_ON), BT_ON);
- write_status(NULL, read_status(WL_ON), WL_ON);
-
- /* LCD Backlight is on by default */
- write_status(NULL, 1, LCD_ON);
-
- /* Keyboard Backlight is on by default */
- if (kled_set_handle)
- set_kled_lvl(1);
-
- /* LED display is off by default */
- hotk->ledd_status = 0xFFF;
-
- /* Set initial values of light sensor and level */
- hotk->light_switch = 0; /* Default to light sensor disabled */
- hotk->light_level = 5; /* level 5 for sensor sensitivity */
-
- if (ls_switch_handle)
- set_light_sens_switch(hotk->light_switch);
-
- if (ls_level_handle)
- set_light_sens_level(hotk->light_level);
-
- /* GPS is on by default */
- write_status(NULL, 1, GPS_ON);
-
-end:
- if (result) {
- kfree(hotk->name);
- kfree(hotk);
- }
-
- return result;
-}
-
-static int asus_hotk_remove(struct acpi_device *device, int type)
-{
- kfree(hotk->name);
- kfree(hotk);
-
- return 0;
-}
-
static void asus_backlight_exit(void)
{
if (asus_backlight_device)
@@ -1350,18 +1261,6 @@ static void asus_input_exit(void)
input_unregister_device(hotk->inputdev);
}

-static void __exit asus_laptop_exit(void)
-{
- asus_backlight_exit();
- asus_led_exit();
- asus_input_exit();
-
- acpi_bus_unregister_driver(&asus_hotk_driver);
- sysfs_remove_group(&asuspf_device->dev.kobj, &asuspf_attribute_group);
- platform_device_unregister(asuspf_device);
- platform_driver_unregister(&asuspf_driver);
-}
-
static int asus_backlight_init(struct device *dev)
{
struct backlight_device *bd;
@@ -1448,87 +1347,179 @@ out:
return rv;
}

-static int __init asus_laptop_init(void)
+
+static bool asus_device_present;
+
+static int __devinit asus_acpi_init(struct acpi_device *device)
{
- int result;
+ int result = 0;

- result = acpi_bus_register_driver(&asus_hotk_driver);
- if (result < 0)
+ result = acpi_bus_get_status(hotk->device);
+ if (result)
return result;
-
- /*
- * This is a bit of a kludge. We only want this module loaded
- * for ASUS systems, but there's currently no way to probe the
- * ACPI namespace for ASUS HIDs. So we just return failure if
- * we didn't find one, which will cause the module to be
- * unloaded.
- */
- if (!asus_hotk_found) {
- acpi_bus_unregister_driver(&asus_hotk_driver);
+ if (!hotk->device->status.present) {
+ pr_err("Hotkey device not present, aborting\n");
return -ENODEV;
}

- result = asus_input_init();
+ result = asus_hotk_get_info();
if (result)
- goto fail_input;
+ return result;

- /* Register platform stuff */
- result = platform_driver_register(&asuspf_driver);
- if (result)
- goto fail_platform_driver;
+ asus_hotk_add_fs();

- asuspf_device = platform_device_alloc(ASUS_HOTK_FILE, -1);
- if (!asuspf_device) {
- result = -ENOMEM;
- goto fail_platform_device1;
- }
+ /* WLED and BLED are on by default */
+ write_status(bt_switch_handle, 1, BT_ON);
+ write_status(wl_switch_handle, 1, WL_ON);

- result = platform_device_add(asuspf_device);
- if (result)
- goto fail_platform_device2;
+ /* If the h/w switch is off, we need to check the real status */
+ write_status(NULL, read_status(BT_ON), BT_ON);
+ write_status(NULL, read_status(WL_ON), WL_ON);
+
+ /* LCD Backlight is on by default */
+ write_status(NULL, 1, LCD_ON);

- result = sysfs_create_group(&asuspf_device->dev.kobj,
- &asuspf_attribute_group);
+ /* Keyboard Backlight is on by default */
+ if (kled_set_handle)
+ set_kled_lvl(1);
+
+ /* LED display is off by default */
+ hotk->ledd_status = 0xFFF;
+
+ /* Set initial values of light sensor and level */
+ hotk->light_switch = 0; /* Default to light sensor disabled */
+ hotk->light_level = 5; /* level 5 for sensor sensitivity */
+
+ if (ls_switch_handle)
+ set_light_sens_switch(hotk->light_switch);
+
+ if (ls_level_handle)
+ set_light_sens_level(hotk->light_level);
+
+ /* GPS is on by default */
+ write_status(NULL, 1, GPS_ON);
+ return result;
+}
+
+static int __devinit asus_acpi_add(struct acpi_device *device)
+{
+ int result;
+
+ pr_notice("Asus Laptop Support version %s\n",
+ ASUS_LAPTOP_VERSION);
+ hotk = kzalloc(sizeof(struct asus_hotk), GFP_KERNEL);
+ if (!hotk)
+ return -ENOMEM;
+ hotk->handle = device->handle;
+ strcpy(acpi_device_name(device), ASUS_HOTK_DEVICE_NAME);
+ strcpy(acpi_device_class(device), ASUS_HOTK_CLASS);
+ device->driver_data = hotk;
+ hotk->device = device;
+
+ result = asus_acpi_init(device);
if (result)
- goto fail_sysfs;
+ goto fail_platform;

- result = asus_led_init(&asuspf_device->dev);
+ /*
+ * Register the platform device first. It is used as a parent for the
+ * sub-devices below.
+ */
+ result = asus_platform_init();
if (result)
- goto fail_led;
+ goto fail_platform;

if (!acpi_video_backlight_support()) {
- result = asus_backlight_init(&asuspf_device->dev);
+ result = asus_backlight_init(&hotk->platform_device->dev);
if (result)
goto fail_backlight;
} else
- pr_info("Brightness ignored, must be controlled by "
- "ACPI video driver\n");
+ pr_info("Backlight controlled by ACPI video driver\n");

+ result = asus_input_init(&hotk->platform_device->dev);
+ if (result)
+ goto fail_input;
+
+ result = asus_led_init(&hotk->platform_device->dev);
+ if (result)
+ goto fail_led;
+
+ asus_device_present = true;
return 0;

+fail_led:
+ asus_input_exit();
+fail_input:
+ asus_backlight_exit();
fail_backlight:
- asus_led_exit();
+ asus_platform_exit();
+fail_platform:
+ kfree(hotk->name);
+ kfree(hotk);

-fail_led:
- sysfs_remove_group(&asuspf_device->dev.kobj,
- &asuspf_attribute_group);
+ return result;
+}

-fail_sysfs:
- platform_device_del(asuspf_device);
+static int asus_acpi_remove(struct acpi_device *device, int type)
+{
+ asus_backlight_exit();
+ asus_led_exit();
+ asus_input_exit();
+ asus_platform_exit();
+
+ kfree(hotk->name);
+ kfree(hotk);
+ return 0;
+}
+
+static const struct acpi_device_id asus_device_ids[] = {
+ {"ATK0100", 0},
+ {"ATK0101", 0},
+ {"", 0},
+};
+MODULE_DEVICE_TABLE(acpi, asus_device_ids);

-fail_platform_device2:
- platform_device_put(asuspf_device);
+static struct acpi_driver asus_acpi_driver = {
+ .name = ASUS_HOTK_NAME,
+ .class = ASUS_HOTK_CLASS,
+ .owner = THIS_MODULE,
+ .ids = asus_device_ids,
+ .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS,
+ .ops = {
+ .add = asus_acpi_add,
+ .remove = asus_acpi_remove,
+ .notify = asus_acpi_notify,
+ },
+};

-fail_platform_device1:
- platform_driver_unregister(&asuspf_driver);
+static int __init asus_laptop_init(void)
+{
+ int result;

-fail_platform_driver:
- asus_input_exit();
+ result = platform_driver_register(&platform_driver);
+ if (result < 0)
+ return result;

-fail_input:
+ result = acpi_bus_register_driver(&asus_acpi_driver);
+ if (result < 0)
+ goto fail_acpi_driver;
+ if (!asus_device_present) {
+ result = -ENODEV;
+ goto fail_no_device;
+ }
+ return 0;

+fail_no_device:
+ acpi_bus_unregister_driver(&asus_acpi_driver);
+fail_acpi_driver:
+ platform_driver_unregister(&platform_driver);
return result;
}

+static void __exit asus_laptop_exit(void)
+{
+ acpi_bus_unregister_driver(&asus_acpi_driver);
+ platform_driver_unregister(&platform_driver);
+}
+
module_init(asus_laptop_init);
module_exit(asus_laptop_exit);
--
1.6.6.1

2010-02-02 07:52:33

by Corentin Chary

[permalink] [raw]
Subject: [PATCH 16/28] asus-laptop: rename function talking directly to acpi with asus_xxx scheme

Signed-off-by: Corentin Chary <[email protected]>
---
drivers/platform/x86/asus-laptop.c | 38 ++++++++++++++++++------------------
1 files changed, 19 insertions(+), 19 deletions(-)

diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c
index 2349e88..ae4f808 100644
--- a/drivers/platform/x86/asus-laptop.c
+++ b/drivers/platform/x86/asus-laptop.c
@@ -394,7 +394,7 @@ ASUS_LED_HANDLER(gled, GLED_ON);
/*
* Keyboard backlight (also a LED)
*/
-static int get_kled_lvl(void)
+static int asus_kled_lvl(void)
{
unsigned long long kblv;
struct acpi_object_list params;
@@ -409,12 +409,12 @@ static int get_kled_lvl(void)
rv = acpi_evaluate_integer(kled_get_handle, NULL, &params, &kblv);
if (ACPI_FAILURE(rv)) {
pr_warning("Error reading kled level\n");
- return 0;
+ return -ENODEV;
}
return kblv;
}

-static int set_kled_lvl(struct asus_laptop *asus, int kblv)
+static int asus_kled_set(struct asus_laptop *asus, int kblv)
{
if (kblv > 0)
kblv = (1 << 7) | (kblv & 0x7F);
@@ -441,12 +441,12 @@ static void kled_led_update(struct work_struct *work)
{
struct asus_laptop *asus = work_to_asus(work, kled);

- set_kled_lvl(asus, asus->leds.kled_wk);
+ asus_kled_set(asus, asus->leds.kled_wk);
}

static enum led_brightness kled_led_get(struct led_classdev *led_cdev)
{
- return get_kled_lvl();
+ return asus_kled_lvl();
}

#define ASUS_LED_UNREGISTER(object) \
@@ -555,7 +555,7 @@ static void lcd_blank(struct asus_laptop *asus, int blank)
}
}

-static int read_brightness(struct backlight_device *bd)
+static int asus_read_brightness(struct backlight_device *bd)
{
unsigned long long value;
acpi_status rv = AE_OK;
@@ -567,7 +567,7 @@ static int read_brightness(struct backlight_device *bd)
return value;
}

-static int set_brightness(struct backlight_device *bd, int value)
+static int asus_set_brightness(struct backlight_device *bd, int value)
{
if (write_acpi_int(brightness_set_handle, NULL, value)) {
pr_warning("Error changing brightness\n");
@@ -582,7 +582,7 @@ static int update_bl_status(struct backlight_device *bd)
int rv;
int value = bd->props.brightness;

- rv = set_brightness(bd, value);
+ rv = asus_set_brightness(bd, value);
if (rv)
return rv;

@@ -591,7 +591,7 @@ static int update_bl_status(struct backlight_device *bd)
}

static struct backlight_ops asusbl_ops = {
- .get_brightness = read_brightness,
+ .get_brightness = asus_read_brightness,
.update_status = update_bl_status,
};

@@ -612,7 +612,7 @@ static int asus_backlight_init(struct asus_laptop *asus)
asus->backlight_device = bd;

bd->props.max_brightness = 15;
- bd->props.brightness = read_brightness(NULL);
+ bd->props.brightness = asus_read_brightness(NULL);
bd->props.power = FB_BLANK_UNBLANK;
backlight_update_status(bd);
}
@@ -818,7 +818,7 @@ static ssize_t store_bluetooth(struct device *dev,
/*
* Display
*/
-static void set_display(struct asus_laptop *asus, int value)
+static void asus_set_display(struct asus_laptop *asus, int value)
{
/* no sanity check needed for now */
if (write_acpi_int(display_set_handle, NULL, value))
@@ -874,14 +874,14 @@ static ssize_t store_disp(struct device *dev, struct device_attribute *attr,

rv = parse_arg(buf, count, &value);
if (rv > 0)
- set_display(asus, value);
+ asus_set_display(asus, value);
return rv;
}

/*
* Light Sens
*/
-static void set_light_sens_switch(struct asus_laptop *asus, int value)
+static void asus_als_switch(struct asus_laptop *asus, int value)
{
if (write_acpi_int(ls_switch_handle, NULL, value))
pr_warning("Error setting light sensor switch\n");
@@ -904,12 +904,12 @@ static ssize_t store_lssw(struct device *dev, struct device_attribute *attr,

rv = parse_arg(buf, count, &value);
if (rv > 0)
- set_light_sens_switch(asus, value ? 1 : 0);
+ asus_als_switch(asus, value ? 1 : 0);

return rv;
}

-static void set_light_sens_level(struct asus_laptop *asus, int value)
+static void asus_als_level(struct asus_laptop *asus, int value)
{
if (write_acpi_int(ls_level_handle, NULL, value))
pr_warning("Error setting light sensor level\n");
@@ -934,7 +934,7 @@ static ssize_t store_lslvl(struct device *dev, struct device_attribute *attr,
if (rv > 0) {
value = (0 < value) ? ((15 < value) ? 15 : value) : 0;
/* 0 <= value <= 15 */
- set_light_sens_level(asus, value);
+ asus_als_level(asus, value);
}

return rv;
@@ -1419,7 +1419,7 @@ static int __devinit asus_acpi_init(struct asus_laptop *asus)

/* Keyboard Backlight is on by default */
if (kled_set_handle)
- set_kled_lvl(asus, 1);
+ asus_kled_set(asus, 1);

/* LED display is off by default */
asus->ledd_status = 0xFFF;
@@ -1429,10 +1429,10 @@ static int __devinit asus_acpi_init(struct asus_laptop *asus)
asus->light_level = 5; /* level 5 for sensor sensitivity */

if (ls_switch_handle)
- set_light_sens_switch(asus, asus->light_switch);
+ asus_als_switch(asus, asus->light_switch);

if (ls_level_handle)
- set_light_sens_level(asus, asus->light_level);
+ asus_als_level(asus, asus->light_level);

/* GPS is on by default */
asus_gps_switch(asus, 1);
--
1.6.6.1

2010-02-02 07:52:14

by Corentin Chary

[permalink] [raw]
Subject: [PATCH 11/28] asus-laptop: code movement

The asus-laptop driver implements a number of interfaces like the
backlight class driver. This change makes it easier to examine the
implementation of one interface at at a time, without having to search
through the file to find init() and exit() functions etc.

Signed-off-by: Corentin Chary <[email protected]>
---
drivers/platform/x86/asus-laptop.c | 440 ++++++++++++++++++------------------
1 files changed, 223 insertions(+), 217 deletions(-)

diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c
index 58a4864..940ce3d 100644
--- a/drivers/platform/x86/asus-laptop.c
+++ b/drivers/platform/x86/asus-laptop.c
@@ -58,36 +58,6 @@
#define ASUS_LAPTOP_FILE KBUILD_MODNAME
#define ASUS_LAPTOP_PREFIX "\\_SB.ATKD."

-
-/*
- * Some events we use, same for all Asus
- */
-#define ATKD_BR_UP 0x10
-#define ATKD_BR_DOWN 0x20
-#define ATKD_LCD_ON 0x33
-#define ATKD_LCD_OFF 0x34
-
-/*
- * Known bits returned by \_SB.ATKD.HWRS
- */
-#define WL_HWRS 0x80
-#define BT_HWRS 0x100
-
-/*
- * Flags for hotk status
- * WL_ON and BT_ON are also used for wireless_status()
- */
-#define WL_ON 0x01 /* internal Wifi */
-#define BT_ON 0x02 /* internal Bluetooth */
-#define MLED_ON 0x04 /* mail LED */
-#define TLED_ON 0x08 /* touchpad LED */
-#define RLED_ON 0x10 /* Record LED */
-#define PLED_ON 0x20 /* Phone LED */
-#define GLED_ON 0x40 /* Gaming LED */
-#define LCD_ON 0x80 /* LCD backlight */
-#define GPS_ON 0x100 /* GPS */
-#define KEY_ON 0x200 /* Keyboard backlight */
-
MODULE_AUTHOR("Julien Lerouge, Karol Kozimor, Corentin Chary");
MODULE_DESCRIPTION(ASUS_LAPTOP_NAME);
MODULE_LICENSE("GPL");
@@ -119,6 +89,35 @@ MODULE_PARM_DESC(bluetooth_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
+ */
+#define ATKD_BR_UP 0x10
+#define ATKD_BR_DOWN 0x20
+#define ATKD_LCD_ON 0x33
+#define ATKD_LCD_OFF 0x34
+
+/*
+ * Known bits returned by \_SB.ATKD.HWRS
+ */
+#define WL_HWRS 0x80
+#define BT_HWRS 0x100
+
+/*
+ * Flags for hotk status
+ * WL_ON and BT_ON are also used for wireless_status()
+ */
+#define WL_ON 0x01 /* internal Wifi */
+#define BT_ON 0x02 /* internal Bluetooth */
+#define MLED_ON 0x04 /* mail LED */
+#define TLED_ON 0x08 /* touchpad LED */
+#define RLED_ON 0x10 /* Record LED */
+#define PLED_ON 0x20 /* Phone LED */
+#define GLED_ON 0x40 /* Gaming LED */
+#define LCD_ON 0x80 /* LCD backlight */
+#define GPS_ON 0x100 /* GPS */
+#define KEY_ON 0x200 /* Keyboard backlight */
+
#define ASUS_HANDLE(object, paths...) \
static acpi_handle object##_handle = NULL; \
static char *object##_paths[] = { paths }
@@ -249,36 +248,6 @@ struct asus_laptop {
u16 *keycode_map;
};

-/*
- * The backlight class declaration
- */
-static int read_brightness(struct backlight_device *bd);
-static int update_bl_status(struct backlight_device *bd);
-static struct backlight_ops asusbl_ops = {
- .get_brightness = read_brightness,
- .update_status = update_bl_status,
-};
-
-#define ASUS_LED(object, ledname, max) \
- static void object##_led_set(struct led_classdev *led_cdev, \
- enum led_brightness value); \
- static enum led_brightness object##_led_get( \
- struct led_classdev *led_cdev); \
- static void object##_led_update(struct work_struct *ignored); \
- static struct led_classdev object##_led = { \
- .name = "asus::" ledname, \
- .brightness_set = object##_led_set, \
- .brightness_get = object##_led_get, \
- .max_brightness = max \
- }
-
-ASUS_LED(mled, "mail", 1);
-ASUS_LED(tled, "touchpad", 1);
-ASUS_LED(rled, "record", 1);
-ASUS_LED(pled, "phone", 1);
-ASUS_LED(gled, "gaming", 1);
-ASUS_LED(kled, "kbd_backlight", 3);
-
struct key_entry {
char type;
u8 code;
@@ -427,6 +396,29 @@ static void write_status(struct asus_laptop *asus, acpi_handle handle,
pr_warning(" write failed %x\n", mask);
}

+/*
+ * LEDs
+ */
+#define ASUS_LED(object, ledname, max) \
+ static void object##_led_set(struct led_classdev *led_cdev, \
+ enum led_brightness value); \
+ static enum led_brightness object##_led_get( \
+ struct led_classdev *led_cdev); \
+ static void object##_led_update(struct work_struct *ignored); \
+ static struct led_classdev object##_led = { \
+ .name = "asus::" ledname, \
+ .brightness_set = object##_led_set, \
+ .brightness_get = object##_led_get, \
+ .max_brightness = max \
+ }
+
+ASUS_LED(mled, "mail", 1);
+ASUS_LED(tled, "touchpad", 1);
+ASUS_LED(rled, "record", 1);
+ASUS_LED(pled, "phone", 1);
+ASUS_LED(gled, "gaming", 1);
+ASUS_LED(kled, "kbd_backlight", 3);
+
/* /sys/class/led handlers */
#define ASUS_LED_HANDLER(object, mask) \
static void object##_led_set(struct led_classdev *led_cdev, \
@@ -459,7 +451,7 @@ ASUS_LED_HANDLER(tled, TLED_ON);
ASUS_LED_HANDLER(gled, GLED_ON);

/*
- * Keyboard backlight
+ * Keyboard backlight (also a LED)
*/
static int get_kled_lvl(void)
{
@@ -516,6 +508,70 @@ static enum led_brightness kled_led_get(struct led_classdev *led_cdev)
return get_kled_lvl();
}

+#define ASUS_LED_UNREGISTER(object) \
+ if (object##_led.dev) \
+ led_classdev_unregister(&object##_led)
+
+static void asus_led_exit(struct asus_laptop *asus)
+{
+ ASUS_LED_UNREGISTER(mled);
+ ASUS_LED_UNREGISTER(tled);
+ ASUS_LED_UNREGISTER(pled);
+ ASUS_LED_UNREGISTER(rled);
+ ASUS_LED_UNREGISTER(gled);
+ ASUS_LED_UNREGISTER(kled);
+ if (asus->leds.workqueue) {
+ destroy_workqueue(asus->leds.workqueue);
+ asus->leds.workqueue = NULL;
+ }
+}
+
+/* Ugly macro, need to fix that later */
+#define ASUS_LED_REGISTER(asus, object, _name, max) \
+ do { \
+ struct led_classdev *ldev = &asus->leds.object; \
+ if (!object##_set_handle) \
+ break ; \
+ \
+ INIT_WORK(&asus->leds.object##_work, object##_led_update); \
+ ldev->name = "asus::" _name; \
+ ldev->brightness_set = object##_led_set; \
+ ldev->max_brightness = max; \
+ rv = led_classdev_register(&asus->platform_device->dev, ldev); \
+ if (rv) \
+ goto error; \
+ } while (0)
+
+static int asus_led_init(struct asus_laptop *asus)
+{
+ int rv;
+
+ /*
+ * Functions that actually update the LED's are called from a
+ * workqueue. By doing this as separate work rather than when the LED
+ * subsystem asks, we avoid messing with the Asus ACPI stuff during a
+ * potentially bad time, such as a timer interrupt.
+ */
+ asus->leds.workqueue = create_singlethread_workqueue("led_workqueue");
+ if (!asus->leds.workqueue)
+ return -ENOMEM;
+
+ ASUS_LED_REGISTER(asus, mled, "mail", 1);
+ ASUS_LED_REGISTER(asus, tled, "touchpad", 1);
+ ASUS_LED_REGISTER(asus, rled, "record", 1);
+ ASUS_LED_REGISTER(asus, pled, "phone", 1);
+ ASUS_LED_REGISTER(asus, gled, "gaming", 1);
+ if (kled_set_handle && kled_get_handle)
+ ASUS_LED_REGISTER(asus, kled, "kbd_backlight", 3);
+error:
+ if (rv)
+ asus_led_exit(asus);
+ return rv;
+}
+
+/*
+ * Backlight device
+ */
static int get_lcd_state(struct asus_laptop *asus)
{
return read_status(asus, LCD_ON);
@@ -588,6 +644,41 @@ static int update_bl_status(struct backlight_device *bd)
return set_lcd_state(asus, value);
}

+static struct backlight_ops asusbl_ops = {
+ .get_brightness = read_brightness,
+ .update_status = update_bl_status,
+};
+
+static int asus_backlight_init(struct asus_laptop *asus)
+{
+ struct backlight_device *bd;
+ struct device *dev = &asus->platform_device->dev;
+
+ if (brightness_set_handle && lcd_switch_handle) {
+ bd = backlight_device_register(ASUS_LAPTOP_FILE, dev,
+ asus, &asusbl_ops);
+ 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.max_brightness = 15;
+ bd->props.brightness = read_brightness(NULL);
+ bd->props.power = FB_BLANK_UNBLANK;
+ backlight_update_status(bd);
+ }
+ return 0;
+}
+
+static void asus_backlight_exit(struct asus_laptop *asus)
+{
+ if (asus->backlight_device)
+ backlight_device_unregister(asus->backlight_device);
+}
+
/*
* Platform device handlers
*/
@@ -904,7 +995,7 @@ static ssize_t store_gps(struct device *dev, struct device_attribute *attr,
}

/*
- * Hotkey functions
+ * Input device (i.e. hotkeys)
*/
static struct key_entry *asus_get_entry_by_scancode(struct asus_laptop *asus,
int code)
@@ -965,10 +1056,72 @@ static int asus_setkeycode(struct input_dev *dev, int scancode, int keycode)
return -EINVAL;
}

+static void asus_input_notify(struct asus_laptop *asus, int event)
+{
+ struct key_entry *key;
+
+ key = asus_get_entry_by_scancode(asus, event);
+ if (!key)
+ return ;
+
+ switch (key->type) {
+ case KE_KEY:
+ input_report_key(asus->inputdev, key->keycode, 1);
+ input_sync(asus->inputdev);
+ input_report_key(asus->inputdev, key->keycode, 0);
+ input_sync(asus->inputdev);
+ break;
+ }
+}
+
+static int asus_input_init(struct asus_laptop *asus)
+{
+ const struct key_entry *key;
+ int result;
+
+ asus->inputdev = input_allocate_device();
+ if (!asus->inputdev) {
+ pr_info("Unable to allocate input device\n");
+ return 0;
+ }
+ asus->inputdev->name = "Asus Laptop extra buttons";
+ asus->inputdev->dev.parent = &asus->platform_device->dev;
+ asus->inputdev->phys = ASUS_LAPTOP_FILE "/input0";
+ asus->inputdev->id.bustype = BUS_HOST;
+ asus->inputdev->getkeycode = asus_getkeycode;
+ asus->inputdev->setkeycode = asus_setkeycode;
+ input_set_drvdata(asus->inputdev, asus);
+
+ asus->keymap = kmemdup(asus_keymap, sizeof(asus_keymap),
+ GFP_KERNEL);
+ for (key = asus->keymap; key->type != KE_END; key++) {
+ switch (key->type) {
+ case KE_KEY:
+ set_bit(EV_KEY, asus->inputdev->evbit);
+ set_bit(key->keycode, asus->inputdev->keybit);
+ break;
+ }
+ }
+ result = input_register_device(asus->inputdev);
+ if (result) {
+ pr_info("Unable to register input device\n");
+ input_free_device(asus->inputdev);
+ }
+ return result;
+}
+
+static void asus_input_exit(struct asus_laptop *asus)
+{
+ if (asus->inputdev)
+ input_unregister_device(asus->inputdev);
+}
+
+/*
+ * ACPI driver
+ */
static void asus_acpi_notify(struct acpi_device *device, u32 event)
{
struct asus_laptop *asus = acpi_driver_data(device);
- static struct key_entry *key;
u16 count;

/*
@@ -990,20 +1143,7 @@ static void asus_acpi_notify(struct acpi_device *device, u32 event)
dev_name(&asus->device->dev), event,
count);

- if (asus->inputdev) {
- key = asus_get_entry_by_scancode(asus, event);
- if (!key)
- return ;
-
- switch (key->type) {
- case KE_KEY:
- input_report_key(asus->inputdev, key->keycode, 1);
- input_sync(asus->inputdev);
- input_report_key(asus->inputdev, key->keycode, 0);
- input_sync(asus->inputdev);
- break;
- }
- }
+ asus_input_notify(asus, event);
}

#define ASUS_CREATE_DEVICE_ATTR(_name) \
@@ -1257,142 +1397,6 @@ static int asus_laptop_get_info(struct asus_laptop *asus)
return AE_OK;
}

-static int asus_input_init(struct asus_laptop *asus)
-{
- const struct key_entry *key;
- int result;
-
- asus->inputdev = input_allocate_device();
- if (!asus->inputdev) {
- pr_info("Unable to allocate input device\n");
- return 0;
- }
- asus->inputdev->name = "Asus Laptop extra buttons";
- asus->inputdev->dev.parent = &asus->platform_device->dev;
- asus->inputdev->phys = ASUS_LAPTOP_FILE "/input0";
- asus->inputdev->id.bustype = BUS_HOST;
- asus->inputdev->getkeycode = asus_getkeycode;
- asus->inputdev->setkeycode = asus_setkeycode;
- input_set_drvdata(asus->inputdev, asus);
-
- asus->keymap = kmemdup(asus_keymap, sizeof(asus_keymap),
- GFP_KERNEL);
- for (key = asus->keymap; key->type != KE_END; key++) {
- switch (key->type) {
- case KE_KEY:
- set_bit(EV_KEY, asus->inputdev->evbit);
- set_bit(key->keycode, asus->inputdev->keybit);
- break;
- }
- }
- result = input_register_device(asus->inputdev);
- if (result) {
- pr_info("Unable to register input device\n");
- input_free_device(asus->inputdev);
- }
- return result;
-}
-
-static void asus_backlight_exit(struct asus_laptop *asus)
-{
- if (asus->backlight_device)
- backlight_device_unregister(asus->backlight_device);
-}
-
-#define ASUS_LED_UNREGISTER(object) \
- if (object##_led.dev) \
- led_classdev_unregister(&object##_led)
-
-static void asus_led_exit(struct asus_laptop *asus)
-{
- ASUS_LED_UNREGISTER(mled);
- ASUS_LED_UNREGISTER(tled);
- ASUS_LED_UNREGISTER(pled);
- ASUS_LED_UNREGISTER(rled);
- ASUS_LED_UNREGISTER(gled);
- ASUS_LED_UNREGISTER(kled);
- if (asus->leds.workqueue) {
- destroy_workqueue(asus->leds.workqueue);
- asus->leds.workqueue = NULL;
- }
-}
-
-static void asus_input_exit(struct asus_laptop *asus)
-{
- if (asus->inputdev)
- input_unregister_device(asus->inputdev);
-}
-
-static int asus_backlight_init(struct asus_laptop *asus)
-{
- struct backlight_device *bd;
- struct device *dev = &asus->platform_device->dev;
-
- if (brightness_set_handle && lcd_switch_handle) {
- bd = backlight_device_register(ASUS_LAPTOP_FILE, dev,
- asus, &asusbl_ops);
- 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.max_brightness = 15;
- bd->props.brightness = read_brightness(NULL);
- bd->props.power = FB_BLANK_UNBLANK;
- backlight_update_status(bd);
- }
- return 0;
-}
-
-/*
- * Ugly macro, need to fix that later
- */
-#define ASUS_LED_REGISTER(asus, object, _name, max) \
- do { \
- struct led_classdev *ldev = &asus->leds.object; \
- if (!object##_set_handle) \
- break ; \
- \
- INIT_WORK(&asus->leds.object##_work, object##_led_update); \
- ldev->name = "asus::" _name; \
- ldev->brightness_set = object##_led_set; \
- ldev->max_brightness = max; \
- rv = led_classdev_register(&asus->platform_device->dev, ldev); \
- if (rv) \
- goto error; \
- } while (0)
-
-static int asus_led_init(struct asus_laptop *asus)
-{
- int rv;
-
- /*
- * Functions that actually update the LED's are called from a
- * workqueue. By doing this as separate work rather than when the LED
- * subsystem asks, we avoid messing with the Asus ACPI stuff during a
- * potentially bad time, such as a timer interrupt.
- */
- asus->leds.workqueue = create_singlethread_workqueue("led_workqueue");
- if (!asus->leds.workqueue)
- return -ENOMEM;
-
- ASUS_LED_REGISTER(asus, mled, "mail", 1);
- ASUS_LED_REGISTER(asus, tled, "touchpad", 1);
- ASUS_LED_REGISTER(asus, rled, "record", 1);
- ASUS_LED_REGISTER(asus, pled, "phone", 1);
- ASUS_LED_REGISTER(asus, gled, "gaming", 1);
- if (kled_set_handle && kled_get_handle)
- ASUS_LED_REGISTER(asus, kled, "kbd_backlight", 3);
-error:
- if (rv)
- asus_led_exit(asus);
- return rv;
-}
-
-
static bool asus_device_present;

static int __devinit asus_acpi_init(struct asus_laptop *asus)
@@ -1414,8 +1418,10 @@ static int __devinit asus_acpi_init(struct asus_laptop *asus)
asus_laptop_add_fs(asus);

/* WLED and BLED are on by default */
- write_status(asus, bt_switch_handle, 1, BT_ON);
- write_status(asus, wl_switch_handle, 1, WL_ON);
+ if (bluetooth_status >= 0)
+ write_status(asus, bt_switch_handle, !!bluetooth_status, BT_ON);
+ if (wireless_status >= 0)
+ write_status(asus, wl_switch_handle, !!wireless_status, WL_ON);

/* If the h/w switch is off, we need to check the real status */
write_status(asus, NULL, read_status(asus, BT_ON), BT_ON);
@@ -1432,8 +1438,8 @@ static int __devinit asus_acpi_init(struct asus_laptop *asus)
asus->ledd_status = 0xFFF;

/* Set initial values of light sensor and level */
- hotk->light_switch = 0; /* Default to light sensor disabled */
- hotk->light_level = 5; /* level 5 for sensor sensitivity */
+ asus->light_switch = 0; /* Default to light sensor disabled */
+ asus->light_level = 5; /* level 5 for sensor sensitivity */

if (ls_switch_handle)
set_light_sens_switch(asus, asus->light_switch);
--
1.6.6.1

2010-02-02 07:53:49

by Corentin Chary

[permalink] [raw]
Subject: [PATCH 08/28] asus-laptop: revise names

asus-laptop now does a lot more than just hotkeys. Replace the "hotk"
names used throughout the driver with some slightly more appropriate
names. The actual strings used in kernel messages and sysfs are left
unchanged.

Signed-off-by: Corentin Chary <[email protected]>
---
drivers/platform/x86/asus-laptop.c | 221 ++++++++++++++++++------------------
1 files changed, 111 insertions(+), 110 deletions(-)

diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c
index 8834405..2505f15 100644
--- a/drivers/platform/x86/asus-laptop.c
+++ b/drivers/platform/x86/asus-laptop.c
@@ -52,11 +52,11 @@

#define ASUS_LAPTOP_VERSION "0.42"

-#define ASUS_HOTK_NAME "Asus Laptop Support"
-#define ASUS_HOTK_CLASS "hotkey"
-#define ASUS_HOTK_DEVICE_NAME "Hotkey"
-#define ASUS_HOTK_FILE KBUILD_MODNAME
-#define ASUS_HOTK_PREFIX "\\_SB.ATKD."
+#define ASUS_LAPTOP_NAME "Asus Laptop Support"
+#define ASUS_LAPTOP_CLASS "hotkey"
+#define ASUS_LAPTOP_DEVICE_NAME "Hotkey"
+#define ASUS_LAPTOP_FILE KBUILD_MODNAME
+#define ASUS_LAPTOP_PREFIX "\\_SB.ATKD."


/*
@@ -89,7 +89,7 @@
#define KEY_ON 0x200 /* Keyboard backlight */

MODULE_AUTHOR("Julien Lerouge, Karol Kozimor, Corentin Chary");
-MODULE_DESCRIPTION(ASUS_HOTK_NAME);
+MODULE_DESCRIPTION(ASUS_LAPTOP_NAME);
MODULE_LICENSE("GPL");

/*
@@ -124,27 +124,27 @@ MODULE_PARM_DESC(bluetooth_status, "Set the wireless status on boot "
static char *object##_paths[] = { paths }

/* LED */
-ASUS_HANDLE(mled_set, ASUS_HOTK_PREFIX "MLED");
-ASUS_HANDLE(tled_set, ASUS_HOTK_PREFIX "TLED");
-ASUS_HANDLE(rled_set, ASUS_HOTK_PREFIX "RLED"); /* W1JC */
-ASUS_HANDLE(pled_set, ASUS_HOTK_PREFIX "PLED"); /* A7J */
-ASUS_HANDLE(gled_set, ASUS_HOTK_PREFIX "GLED"); /* G1, G2 (probably) */
+ASUS_HANDLE(mled_set, ASUS_LAPTOP_PREFIX "MLED");
+ASUS_HANDLE(tled_set, ASUS_LAPTOP_PREFIX "TLED");
+ASUS_HANDLE(rled_set, ASUS_LAPTOP_PREFIX "RLED"); /* W1JC */
+ASUS_HANDLE(pled_set, ASUS_LAPTOP_PREFIX "PLED"); /* A7J */
+ASUS_HANDLE(gled_set, ASUS_LAPTOP_PREFIX "GLED"); /* G1, G2 (probably) */

/* LEDD */
-ASUS_HANDLE(ledd_set, ASUS_HOTK_PREFIX "SLCM");
+ASUS_HANDLE(ledd_set, ASUS_LAPTOP_PREFIX "SLCM");

/*
* Bluetooth and WLAN
* WLED and BLED are not handled like other XLED, because in some dsdt
* they also control the WLAN/Bluetooth device.
*/
-ASUS_HANDLE(wl_switch, ASUS_HOTK_PREFIX "WLED");
-ASUS_HANDLE(bt_switch, ASUS_HOTK_PREFIX "BLED");
-ASUS_HANDLE(wireless_status, ASUS_HOTK_PREFIX "RSTS"); /* All new models */
+ASUS_HANDLE(wl_switch, ASUS_LAPTOP_PREFIX "WLED");
+ASUS_HANDLE(bt_switch, ASUS_LAPTOP_PREFIX "BLED");
+ASUS_HANDLE(wireless_status, ASUS_LAPTOP_PREFIX "RSTS"); /* All new models */

/* Brightness */
-ASUS_HANDLE(brightness_set, ASUS_HOTK_PREFIX "SPLV");
-ASUS_HANDLE(brightness_get, ASUS_HOTK_PREFIX "GPLV");
+ASUS_HANDLE(brightness_set, ASUS_LAPTOP_PREFIX "SPLV");
+ASUS_HANDLE(brightness_get, ASUS_LAPTOP_PREFIX "GPLV");

/* Backlight */
ASUS_HANDLE(lcd_switch, "\\_SB.PCI0.SBRG.EC0._Q10", /* All new models */
@@ -157,7 +157,7 @@ ASUS_HANDLE(lcd_switch, "\\_SB.PCI0.SBRG.EC0._Q10", /* All new models */
"\\Q10"); /* A2x, L2D, L3D, M2E */

/* Display */
-ASUS_HANDLE(display_set, ASUS_HOTK_PREFIX "SDSP");
+ASUS_HANDLE(display_set, ASUS_LAPTOP_PREFIX "SDSP");
ASUS_HANDLE(display_get,
/* A6B, A6K A6R A7D F3JM L4R M6R A3G M6A M6V VX-1 V6J V6V W3Z */
"\\_SB.PCI0.P0P1.VGA.GETD",
@@ -182,24 +182,24 @@ ASUS_HANDLE(display_get,
/* A3F A6F A3N A3L M6N W3N W6A */
"\\SSTE");

-ASUS_HANDLE(ls_switch, ASUS_HOTK_PREFIX "ALSC"); /* Z71A Z71V */
-ASUS_HANDLE(ls_level, ASUS_HOTK_PREFIX "ALSL"); /* Z71A Z71V */
+ASUS_HANDLE(ls_switch, ASUS_LAPTOP_PREFIX "ALSC"); /* Z71A Z71V */
+ASUS_HANDLE(ls_level, ASUS_LAPTOP_PREFIX "ALSL"); /* Z71A Z71V */

/* GPS */
/* R2H use different handle for GPS on/off */
-ASUS_HANDLE(gps_on, ASUS_HOTK_PREFIX "SDON"); /* R2H */
-ASUS_HANDLE(gps_off, ASUS_HOTK_PREFIX "SDOF"); /* R2H */
-ASUS_HANDLE(gps_status, ASUS_HOTK_PREFIX "GPST");
+ASUS_HANDLE(gps_on, ASUS_LAPTOP_PREFIX "SDON"); /* R2H */
+ASUS_HANDLE(gps_off, ASUS_LAPTOP_PREFIX "SDOF"); /* R2H */
+ASUS_HANDLE(gps_status, ASUS_LAPTOP_PREFIX "GPST");

/* Keyboard light */
-ASUS_HANDLE(kled_set, ASUS_HOTK_PREFIX "SLKB");
-ASUS_HANDLE(kled_get, ASUS_HOTK_PREFIX "GLKB");
+ASUS_HANDLE(kled_set, ASUS_LAPTOP_PREFIX "SLKB");
+ASUS_HANDLE(kled_get, ASUS_LAPTOP_PREFIX "GLKB");

/*
* This is the main structure, we can use it to store anything interesting
* about the hotk device
*/
-struct asus_hotk {
+struct asus_laptop {
char *name; /* laptop name */

struct platform_device *platform_device;
@@ -216,13 +216,13 @@ struct asus_hotk {

/*
* This header is made available to allow proper configuration given model,
- * revision number , ... this info cannot go in struct asus_hotk because it is
+ * revision number , ... this info cannot go in struct asus_laptop because it is
* available before the hotk
*/
static struct acpi_table_header *asus_info;

/* The actual device the driver binds to */
-static struct asus_hotk *hotk;
+static struct asus_laptop *asus;

/* The backlight device /sys/class/backlight */
static struct backlight_device *asus_backlight_device;
@@ -353,7 +353,7 @@ static int read_wireless_status(int mask)
acpi_status rv = AE_OK;

if (!wireless_status_handle)
- return (hotk->status & mask) ? 1 : 0;
+ return (asus->status & mask) ? 1 : 0;

rv = acpi_evaluate_integer(wireless_status_handle, NULL, NULL, &status);
if (ACPI_FAILURE(rv))
@@ -361,7 +361,7 @@ static int read_wireless_status(int mask)
else
return (status & mask) ? 1 : 0;

- return (hotk->status & mask) ? 1 : 0;
+ return (asus->status & mask) ? 1 : 0;
}

static int read_gps_status(void)
@@ -375,7 +375,7 @@ static int read_gps_status(void)
else
return status ? 1 : 0;

- return (hotk->status & GPS_ON) ? 1 : 0;
+ return (asus->status & GPS_ON) ? 1 : 0;
}

/* Generic LED functions */
@@ -387,12 +387,12 @@ static int read_status(int mask)
else if (mask == GPS_ON)
return read_gps_status();

- return (hotk->status & mask) ? 1 : 0;
+ return (asus->status & mask) ? 1 : 0;
}

static void write_status(acpi_handle handle, int out, int mask)
{
- hotk->status = (out) ? (hotk->status | mask) : (hotk->status & ~mask);
+ asus->status = (out) ? (asus->status | mask) : (asus->status & ~mask);

switch (mask) {
case MLED_ON:
@@ -586,15 +586,15 @@ static ssize_t show_infos(struct device *dev,
* to 1
*/

- len += sprintf(page, ASUS_HOTK_NAME " " ASUS_LAPTOP_VERSION "\n");
- len += sprintf(page + len, "Model reference : %s\n", hotk->name);
+ len += sprintf(page, ASUS_LAPTOP_NAME " " ASUS_LAPTOP_VERSION "\n");
+ len += sprintf(page + len, "Model reference : %s\n", asus->name);
/*
* The SFUN method probably allows the original driver to get the list
* of features supported by a given model. For now, 0x0100 or 0x0800
* bit signifies that the laptop is equipped with a Wi-Fi MiniPCI card.
* The significance of others is yet to be found.
*/
- rv = acpi_evaluate_integer(hotk->handle, "SFUN", NULL, &temp);
+ rv = acpi_evaluate_integer(asus->handle, "SFUN", NULL, &temp);
if (!ACPI_FAILURE(rv))
len += sprintf(page + len, "SFUN value : %#x\n",
(uint) temp);
@@ -604,7 +604,7 @@ static ssize_t show_infos(struct device *dev,
* The significance of others is yet to be found.
* If we don't find the method, we assume the device are present.
*/
- rv = acpi_evaluate_integer(hotk->handle, "HRWS", NULL, &temp);
+ rv = acpi_evaluate_integer(asus->handle, "HRWS", NULL, &temp);
if (!ACPI_FAILURE(rv))
len += sprintf(page + len, "HRWS value : %#x\n",
(uint) temp);
@@ -615,7 +615,7 @@ static ssize_t show_infos(struct device *dev,
* Note: since not all the laptops provide this method, errors are
* silently ignored.
*/
- rv = acpi_evaluate_integer(hotk->handle, "ASYM", NULL, &temp);
+ rv = acpi_evaluate_integer(asus->handle, "ASYM", NULL, &temp);
if (!ACPI_FAILURE(rv))
len += sprintf(page + len, "ASYM value : %#x\n",
(uint) temp);
@@ -673,7 +673,7 @@ static ssize_t store_status(const char *buf, size_t count,
static ssize_t show_ledd(struct device *dev,
struct device_attribute *attr, char *buf)
{
- return sprintf(buf, "0x%08x\n", hotk->ledd_status);
+ return sprintf(buf, "0x%08x\n", asus->ledd_status);
}

static ssize_t store_ledd(struct device *dev, struct device_attribute *attr,
@@ -686,7 +686,7 @@ static ssize_t store_ledd(struct device *dev, struct device_attribute *attr,
if (write_acpi_int(ledd_set_handle, NULL, value))
pr_warning("LED display write failed\n");
else
- hotk->ledd_status = (u32) value;
+ asus->ledd_status = (u32) value;
}
return rv;
}
@@ -789,13 +789,13 @@ static void set_light_sens_switch(int value)
{
if (write_acpi_int(ls_switch_handle, NULL, value))
pr_warning("Error setting light sensor switch\n");
- hotk->light_switch = value;
+ asus->light_switch = value;
}

static ssize_t show_lssw(struct device *dev,
struct device_attribute *attr, char *buf)
{
- return sprintf(buf, "%d\n", hotk->light_switch);
+ return sprintf(buf, "%d\n", asus->light_switch);
}

static ssize_t store_lssw(struct device *dev, struct device_attribute *attr,
@@ -814,13 +814,13 @@ static void set_light_sens_level(int value)
{
if (write_acpi_int(ls_level_handle, NULL, value))
pr_warning("Error setting light sensor level\n");
- hotk->light_level = value;
+ asus->light_level = value;
}

static ssize_t show_lslvl(struct device *dev,
struct device_attribute *attr, char *buf)
{
- return sprintf(buf, "%d\n", hotk->light_level);
+ return sprintf(buf, "%d\n", asus->light_level);
}

static ssize_t store_lslvl(struct device *dev, struct device_attribute *attr,
@@ -929,23 +929,23 @@ static void asus_acpi_notify(struct acpi_device *device, u32 event)
}

/* TODO Find a better way to handle events count. */
- count = hotk->event_count[event % 128]++;
- acpi_bus_generate_proc_event(hotk->device, event, count);
- acpi_bus_generate_netlink_event(hotk->device->pnp.device_class,
- dev_name(&hotk->device->dev), event,
+ count = asus->event_count[event % 128]++;
+ acpi_bus_generate_proc_event(asus->device, event, count);
+ acpi_bus_generate_netlink_event(asus->device->pnp.device_class,
+ dev_name(&asus->device->dev), event,
count);

- if (hotk->inputdev) {
+ if (asus->inputdev) {
key = asus_get_entry_by_scancode(event);
if (!key)
return ;

switch (key->type) {
case KE_KEY:
- input_report_key(hotk->inputdev, key->keycode, 1);
- input_sync(hotk->inputdev);
- input_report_key(hotk->inputdev, key->keycode, 0);
- input_sync(hotk->inputdev);
+ input_report_key(asus->inputdev, key->keycode, 1);
+ input_sync(asus->inputdev);
+ input_report_key(asus->inputdev, key->keycode, 0);
+ input_sync(asus->inputdev);
break;
}
}
@@ -996,42 +996,42 @@ static int asus_platform_init(void)
{
int result;

- hotk->platform_device = platform_device_alloc(ASUS_HOTK_FILE, -1);
- if (!hotk->platform_device)
+ asus->platform_device = platform_device_alloc(ASUS_LAPTOP_FILE, -1);
+ if (!asus->platform_device)
return -ENOMEM;

- result = platform_device_add(hotk->platform_device);
+ result = platform_device_add(asus->platform_device);
if (result)
goto fail_platform_device;

- result = sysfs_create_group(&hotk->platform_device->dev.kobj,
+ result = sysfs_create_group(&asus->platform_device->dev.kobj,
&platform_attribute_group);
if (result)
goto fail_sysfs;
return 0;

fail_sysfs:
- platform_device_del(hotk->platform_device);
+ platform_device_del(asus->platform_device);
fail_platform_device:
- platform_device_put(hotk->platform_device);
+ platform_device_put(asus->platform_device);
return result;
}

static void asus_platform_exit(void)
{
- sysfs_remove_group(&hotk->platform_device->dev.kobj,
+ sysfs_remove_group(&asus->platform_device->dev.kobj,
&platform_attribute_group);
- platform_device_unregister(hotk->platform_device);
+ platform_device_unregister(asus->platform_device);
}

static struct platform_driver platform_driver = {
.driver = {
- .name = ASUS_HOTK_FILE,
+ .name = ASUS_LAPTOP_FILE,
.owner = THIS_MODULE,
}
};

-static void asus_hotk_add_fs(void)
+static void asus_laptop_add_fs(void)
{
ASUS_SET_DEVICE_ATTR(infos, 0444, show_infos, NULL);

@@ -1080,10 +1080,11 @@ static int asus_handle_init(char *name, acpi_handle * handle,
ARRAY_SIZE(object##_paths))

/*
- * This function is used to initialize the hotk with right values. In this
- * method, we can make all the detection we want, and modify the hotk struct
+ * This function is used to initialize the context with right values. In this
+ * method, we can make all the detection we want, and modify the asus_laptop
+ * struct
*/
-static int asus_hotk_get_info(void)
+static int asus_laptop_get_info(void)
{
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
union acpi_object *model = NULL;
@@ -1104,14 +1105,14 @@ static int asus_hotk_get_info(void)
pr_warning("Couldn't get the DSDT table header\n");

/* We have to write 0 on init this far for all ASUS models */
- if (write_acpi_int_ret(hotk->handle, "INIT", 0, &buffer)) {
+ if (write_acpi_int_ret(asus->handle, "INIT", 0, &buffer)) {
pr_err("Hotkey initialization failed\n");
return -ENODEV;
}

/* This needs to be called for some laptops to init properly */
status =
- acpi_evaluate_integer(hotk->handle, "BSTS", NULL, &bsts_result);
+ acpi_evaluate_integer(asus->handle, "BSTS", NULL, &bsts_result);
if (ACPI_FAILURE(status))
pr_warning("Error calling BSTS\n");
else if (bsts_result)
@@ -1119,7 +1120,7 @@ static int asus_hotk_get_info(void)
(uint) bsts_result);

/* This too ... */
- write_acpi_int(hotk->handle, "CWAP", wapf);
+ write_acpi_int(asus->handle, "CWAP", wapf);

/*
* Try to match the object returned by INIT to the specific model.
@@ -1141,8 +1142,8 @@ static int asus_hotk_get_info(void)
break;
}
}
- hotk->name = kstrdup(string, GFP_KERNEL);
- if (!hotk->name)
+ asus->name = kstrdup(string, GFP_KERNEL);
+ if (!asus->name)
return -ENOMEM;

if (*string)
@@ -1166,7 +1167,7 @@ static int asus_hotk_get_info(void)
* If we don't find the method, we assume the device are present.
*/
status =
- acpi_evaluate_integer(hotk->handle, "HRWS", NULL, &hwrs_result);
+ acpi_evaluate_integer(asus->handle, "HRWS", NULL, &hwrs_result);
if (ACPI_FAILURE(status))
hwrs_result = WL_HWRS | BT_HWRS;

@@ -1206,30 +1207,30 @@ static int asus_input_init(struct device *dev)
const struct key_entry *key;
int result;

- hotk->inputdev = input_allocate_device();
- if (!hotk->inputdev) {
+ asus->inputdev = input_allocate_device();
+ if (!asus->inputdev) {
pr_info("Unable to allocate input device\n");
return 0;
}
- hotk->inputdev->name = "Asus Laptop extra buttons";
- hotk->inputdev->dev.parent = dev;
- hotk->inputdev->phys = ASUS_HOTK_FILE "/input0";
- hotk->inputdev->id.bustype = BUS_HOST;
- hotk->inputdev->getkeycode = asus_getkeycode;
- hotk->inputdev->setkeycode = asus_setkeycode;
+ asus->inputdev->name = "Asus Laptop extra buttons";
+ asus->inputdev->dev.parent = dev;
+ asus->inputdev->phys = ASUS_LAPTOP_FILE "/input0";
+ asus->inputdev->id.bustype = BUS_HOST;
+ asus->inputdev->getkeycode = asus_getkeycode;
+ asus->inputdev->setkeycode = asus_setkeycode;

for (key = asus_keymap; key->type != KE_END; key++) {
switch (key->type) {
case KE_KEY:
- set_bit(EV_KEY, hotk->inputdev->evbit);
- set_bit(key->keycode, hotk->inputdev->keybit);
+ set_bit(EV_KEY, asus->inputdev->evbit);
+ set_bit(key->keycode, asus->inputdev->keybit);
break;
}
}
- result = input_register_device(hotk->inputdev);
+ result = input_register_device(asus->inputdev);
if (result) {
pr_info("Unable to register input device\n");
- input_free_device(hotk->inputdev);
+ input_free_device(asus->inputdev);
}
return result;
}
@@ -1257,8 +1258,8 @@ static void asus_led_exit(void)

static void asus_input_exit(void)
{
- if (hotk->inputdev)
- input_unregister_device(hotk->inputdev);
+ if (asus->inputdev)
+ input_unregister_device(asus->inputdev);
}

static int asus_backlight_init(struct device *dev)
@@ -1266,7 +1267,7 @@ static int asus_backlight_init(struct device *dev)
struct backlight_device *bd;

if (brightness_set_handle && lcd_switch_handle) {
- bd = backlight_device_register(ASUS_HOTK_FILE, dev,
+ bd = backlight_device_register(ASUS_LAPTOP_FILE, dev,
NULL, &asusbl_ops);
if (IS_ERR(bd)) {
pr_err("Could not register asus backlight device\n");
@@ -1354,19 +1355,19 @@ static int __devinit asus_acpi_init(struct acpi_device *device)
{
int result = 0;

- result = acpi_bus_get_status(hotk->device);
+ result = acpi_bus_get_status(asus->device);
if (result)
return result;
- if (!hotk->device->status.present) {
+ if (!asus->device->status.present) {
pr_err("Hotkey device not present, aborting\n");
return -ENODEV;
}

- result = asus_hotk_get_info();
+ result = asus_laptop_get_info();
if (result)
return result;

- asus_hotk_add_fs();
+ asus_laptop_add_fs();

/* WLED and BLED are on by default */
write_status(bt_switch_handle, 1, BT_ON);
@@ -1384,17 +1385,17 @@ static int __devinit asus_acpi_init(struct acpi_device *device)
set_kled_lvl(1);

/* LED display is off by default */
- hotk->ledd_status = 0xFFF;
+ asus->ledd_status = 0xFFF;

/* Set initial values of light sensor and level */
hotk->light_switch = 0; /* Default to light sensor disabled */
hotk->light_level = 5; /* level 5 for sensor sensitivity */

if (ls_switch_handle)
- set_light_sens_switch(hotk->light_switch);
+ set_light_sens_switch(asus->light_switch);

if (ls_level_handle)
- set_light_sens_level(hotk->light_level);
+ set_light_sens_level(asus->light_level);

/* GPS is on by default */
write_status(NULL, 1, GPS_ON);
@@ -1407,14 +1408,14 @@ static int __devinit asus_acpi_add(struct acpi_device *device)

pr_notice("Asus Laptop Support version %s\n",
ASUS_LAPTOP_VERSION);
- hotk = kzalloc(sizeof(struct asus_hotk), GFP_KERNEL);
- if (!hotk)
+ asus = kzalloc(sizeof(struct asus_laptop), GFP_KERNEL);
+ if (!asus)
return -ENOMEM;
- hotk->handle = device->handle;
- strcpy(acpi_device_name(device), ASUS_HOTK_DEVICE_NAME);
- strcpy(acpi_device_class(device), ASUS_HOTK_CLASS);
- device->driver_data = hotk;
- hotk->device = device;
+ asus->handle = device->handle;
+ strcpy(acpi_device_name(device), ASUS_LAPTOP_DEVICE_NAME);
+ strcpy(acpi_device_class(device), ASUS_LAPTOP_CLASS);
+ device->driver_data = asus;
+ asus->device = device;

result = asus_acpi_init(device);
if (result)
@@ -1429,17 +1430,17 @@ static int __devinit asus_acpi_add(struct acpi_device *device)
goto fail_platform;

if (!acpi_video_backlight_support()) {
- result = asus_backlight_init(&hotk->platform_device->dev);
+ result = asus_backlight_init(&asus->platform_device->dev);
if (result)
goto fail_backlight;
} else
pr_info("Backlight controlled by ACPI video driver\n");

- result = asus_input_init(&hotk->platform_device->dev);
+ result = asus_input_init(&asus->platform_device->dev);
if (result)
goto fail_input;

- result = asus_led_init(&hotk->platform_device->dev);
+ result = asus_led_init(&asus->platform_device->dev);
if (result)
goto fail_led;

@@ -1453,8 +1454,8 @@ fail_input:
fail_backlight:
asus_platform_exit();
fail_platform:
- kfree(hotk->name);
- kfree(hotk);
+ kfree(asus->name);
+ kfree(asus);

return result;
}
@@ -1466,8 +1467,8 @@ static int asus_acpi_remove(struct acpi_device *device, int type)
asus_input_exit();
asus_platform_exit();

- kfree(hotk->name);
- kfree(hotk);
+ kfree(asus->name);
+ kfree(asus);
return 0;
}

@@ -1479,8 +1480,8 @@ static const struct acpi_device_id asus_device_ids[] = {
MODULE_DEVICE_TABLE(acpi, asus_device_ids);

static struct acpi_driver asus_acpi_driver = {
- .name = ASUS_HOTK_NAME,
- .class = ASUS_HOTK_CLASS,
+ .name = ASUS_LAPTOP_NAME,
+ .class = ASUS_LAPTOP_CLASS,
.owner = THIS_MODULE,
.ids = asus_device_ids,
.flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS,
--
1.6.6.1

2010-02-02 07:54:17

by Corentin Chary

[permalink] [raw]
Subject: [PATCH 22/28] asus-laptop: add backlight changes notifications

We don't want to send KEY_BRIGHTNESSDOWN or KEY_BRIGHTNESSUP
because it would be a lie to tell userspace that we want
to change the brightness while it's actually done by the
firmware.

Signed-off-by: Corentin Chary <[email protected]>
---
drivers/platform/x86/asus-laptop.c | 29 +++++++++++++++++++++++++++--
1 files changed, 27 insertions(+), 2 deletions(-)

diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c
index 4f3c467..516add3 100644
--- a/drivers/platform/x86/asus-laptop.c
+++ b/drivers/platform/x86/asus-laptop.c
@@ -93,8 +93,10 @@ MODULE_PARM_DESC(bluetooth_status, "Set the wireless status on boot "
/*
* Some events we use, same for all Asus
*/
-#define ATKD_BR_UP 0x10
-#define ATKD_BR_DOWN 0x20
+#define ATKD_BR_UP 0x10 // (event & ~ATKD_BR_UP) = brightness level
+#define ATKD_BR_DOWN 0x20 // (event & ~ATKD_BR_DOWN) = britghness level
+#define ATKD_BR_MIN ATKD_BR_UP
+#define ATKD_BR_MAX (ATKD_BR_DOWN | 0xF) // 0x2f
#define ATKD_LCD_ON 0x33
#define ATKD_LCD_OFF 0x34

@@ -245,11 +247,13 @@ struct asus_laptop {
};

static const struct key_entry asus_keymap[] = {
+ /* Lenovo SL Specific keycodes */
{KE_KEY, 0x02, { KEY_SCREENLOCK } },
{KE_KEY, 0x05, { KEY_WLAN } },
{KE_KEY, 0x08, { KEY_F13 } },
{KE_KEY, 0x17, { KEY_ZOOM } },
{KE_KEY, 0x1f, { KEY_BATTERY } },
+ /* End of Lenovo SL Specific keycodes */
{KE_KEY, 0x30, { KEY_VOLUMEUP } },
{KE_KEY, 0x31, { KEY_VOLUMEDOWN } },
{KE_KEY, 0x32, { KEY_MUTE } },
@@ -626,6 +630,16 @@ static struct backlight_ops asusbl_ops = {
.update_status = update_bl_status,
};

+static int asus_backlight_notify(struct asus_laptop *asus)
+{
+ struct backlight_device *bd = asus->backlight_device;
+ int old = bd->props.brightness;
+
+ backlight_force_update(bd, BACKLIGHT_UPDATE_HOTKEY);
+
+ return old;
+}
+
static int asus_backlight_init(struct asus_laptop *asus)
{
struct backlight_device *bd;
@@ -656,6 +670,7 @@ static void asus_backlight_exit(struct asus_laptop *asus)
{
if (asus->backlight_device)
backlight_device_unregister(asus->backlight_device);
+ asus->backlight_device = NULL;
}

/*
@@ -1121,6 +1136,16 @@ static void asus_acpi_notify(struct acpi_device *device, u32 event)
dev_name(&asus->device->dev), event,
count);

+ /* Brightness events are special */
+ if (event >= ATKD_BR_MIN && event <= ATKD_BR_MAX) {
+
+ /* Ignore them completely if the acpi video driver is used */
+ if (asus->backlight_device != NULL) {
+ /* Update the backlight device. */
+ asus_backlight_notify(asus);
+ }
+ return ;
+ }
asus_input_notify(asus, event);
}

--
1.6.6.1

2010-02-02 07:53:55

by Corentin Chary

[permalink] [raw]
Subject: [PATCH 05/28] asus-laptop: use tabs to indent macros and remove unused ones

Signed-off-by: Corentin Chary <[email protected]>
---
drivers/platform/x86/asus-laptop.c | 51 +++++++++++++++--------------------
1 files changed, 22 insertions(+), 29 deletions(-)

diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c
index 7058cb5..5889bda 100644
--- a/drivers/platform/x86/asus-laptop.c
+++ b/drivers/platform/x86/asus-laptop.c
@@ -50,50 +50,43 @@
#include <asm/uaccess.h>
#include <linux/input.h>

-#define ASUS_LAPTOP_VERSION "0.42"
+#define ASUS_LAPTOP_VERSION "0.42"

-#define ASUS_HOTK_NAME "Asus Laptop Support"
-#define ASUS_HOTK_CLASS "hotkey"
-#define ASUS_HOTK_DEVICE_NAME "Hotkey"
-#define ASUS_HOTK_FILE KBUILD_MODNAME
-#define ASUS_HOTK_PREFIX "\\_SB.ATKD."
+#define ASUS_HOTK_NAME "Asus Laptop Support"
+#define ASUS_HOTK_CLASS "hotkey"
+#define ASUS_HOTK_DEVICE_NAME "Hotkey"
+#define ASUS_HOTK_FILE KBUILD_MODNAME
+#define ASUS_HOTK_PREFIX "\\_SB.ATKD."


/*
* Some events we use, same for all Asus
*/
-#define ATKD_BR_UP 0x10
-#define ATKD_BR_DOWN 0x20
-#define ATKD_LCD_ON 0x33
-#define ATKD_LCD_OFF 0x34
+#define ATKD_BR_UP 0x10
+#define ATKD_BR_DOWN 0x20
+#define ATKD_LCD_ON 0x33
+#define ATKD_LCD_OFF 0x34

/*
* Known bits returned by \_SB.ATKD.HWRS
*/
-#define WL_HWRS 0x80
-#define BT_HWRS 0x100
+#define WL_HWRS 0x80
+#define BT_HWRS 0x100

/*
* Flags for hotk status
* WL_ON and BT_ON are also used for wireless_status()
*/
-#define WL_ON 0x01 /* internal Wifi */
-#define BT_ON 0x02 /* internal Bluetooth */
-#define MLED_ON 0x04 /* mail LED */
-#define TLED_ON 0x08 /* touchpad LED */
-#define RLED_ON 0x10 /* Record LED */
-#define PLED_ON 0x20 /* Phone LED */
-#define GLED_ON 0x40 /* Gaming LED */
-#define LCD_ON 0x80 /* LCD backlight */
-#define GPS_ON 0x100 /* GPS */
-#define KEY_ON 0x200 /* Keyboard backlight */
-
-#define ASUS_LOG ASUS_HOTK_FILE ": "
-#define ASUS_ERR KERN_ERR ASUS_LOG
-#define ASUS_WARNING KERN_WARNING ASUS_LOG
-#define ASUS_NOTICE KERN_NOTICE ASUS_LOG
-#define ASUS_INFO KERN_INFO ASUS_LOG
-#define ASUS_DEBUG KERN_DEBUG ASUS_LOG
+#define WL_ON 0x01 /* internal Wifi */
+#define BT_ON 0x02 /* internal Bluetooth */
+#define MLED_ON 0x04 /* mail LED */
+#define TLED_ON 0x08 /* touchpad LED */
+#define RLED_ON 0x10 /* Record LED */
+#define PLED_ON 0x20 /* Phone LED */
+#define GLED_ON 0x40 /* Gaming LED */
+#define LCD_ON 0x80 /* LCD backlight */
+#define GPS_ON 0x100 /* GPS */
+#define KEY_ON 0x200 /* Keyboard backlight */

MODULE_AUTHOR("Julien Lerouge, Karol Kozimor, Corentin Chary");
MODULE_DESCRIPTION(ASUS_HOTK_NAME);
--
1.6.6.1

2010-02-02 07:54:42

by Corentin Chary

[permalink] [raw]
Subject: [PATCH 21/28] asus-laptop: add bluetooth keys found on M9V

Reported by Andrey F. Ilchuk

Signed-off-by: Corentin Chary <[email protected]>
---
drivers/platform/x86/asus-laptop.c | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c
index 8042568..4f3c467 100644
--- a/drivers/platform/x86/asus-laptop.c
+++ b/drivers/platform/x86/asus-laptop.c
@@ -272,6 +272,8 @@ static const struct key_entry asus_keymap[] = {
{KE_KEY, 0x62, { KEY_SWITCHVIDEOMODE } },
{KE_KEY, 0x63, { KEY_SWITCHVIDEOMODE } },
{KE_KEY, 0x6B, { KEY_F13 } }, /* Lock Touchpad */
+ {KE_KEY, 0x7E, { KEY_BLUETOOTH } },
+ {KE_KEY, 0x7D, { KEY_BLUETOOTH } },
{KE_KEY, 0x82, { KEY_CAMERA } },
{KE_KEY, 0x88, { KEY_WLAN } },
{KE_KEY, 0x8A, { KEY_PROG1 } },
--
1.6.6.1

2010-02-02 07:52:18

by Corentin Chary

[permalink] [raw]
Subject: [PATCH 06/28] asus-laptop: remove unecessary hotk != NULL check

Signed-off-by: Corentin Chary <[email protected]>
---
drivers/platform/x86/asus-laptop.c | 5 +----
1 files changed, 1 insertions(+), 4 deletions(-)

diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c
index 5889bda..74463a0 100644
--- a/drivers/platform/x86/asus-laptop.c
+++ b/drivers/platform/x86/asus-laptop.c
@@ -941,10 +941,6 @@ static void asus_hotk_notify(struct acpi_device *device, u32 event)
static struct key_entry *key;
u16 count;

- /* TODO Find a better way to handle events count. */
- if (!hotk)
- return;
-
/*
* We need to tell the backlight device when the backlight power is
* switched
@@ -957,6 +953,7 @@ static void asus_hotk_notify(struct acpi_device *device, u32 event)
lcd_blank(FB_BLANK_POWERDOWN);
}

+ /* TODO Find a better way to handle events count. */
count = hotk->event_count[event % 128]++;
acpi_bus_generate_proc_event(hotk->device, event, count);
acpi_bus_generate_netlink_event(hotk->device->pnp.device_class,
--
1.6.6.1

2010-02-02 07:52:12

by Corentin Chary

[permalink] [raw]
Subject: [PATCH 18/28] asus-laptop: add error check for write_acpi_int calls

Also add to helpers for bluetooth and wlan.

Signed-off-by: Corentin Chary <[email protected]>
---
drivers/platform/x86/asus-laptop.c | 33 +++++++++++++++++++++++++--------
1 files changed, 25 insertions(+), 8 deletions(-)

diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c
index 671fad9..aad6b93 100644
--- a/drivers/platform/x86/asus-laptop.c
+++ b/drivers/platform/x86/asus-laptop.c
@@ -350,7 +350,7 @@ static int acpi_check_handle(acpi_handle handle, const char *method,
}

/* Generic LED function */
-static void asus_led_set(struct asus_laptop *asus, char *method,
+static int asus_led_set(struct asus_laptop *asus, char *method,
int value)
{
if (!strcmp(method, METHOD_MLED))
@@ -360,7 +360,7 @@ static void asus_led_set(struct asus_laptop *asus, char *method,
else
value = !!value;

- write_acpi_int(asus->handle, method, value);
+ return write_acpi_int(asus->handle, method, value);
}

/*
@@ -817,6 +817,15 @@ static int asus_wireless_status(struct asus_laptop *asus, int mask)
/*
* WLAN
*/
+static int asus_wlan_set(struct asus_laptop *asus, int status)
+{
+ if (write_acpi_int(asus->handle, METHOD_WLAN, !!status)) {
+ pr_warning("Error setting wlan status to %d", status);
+ return -EIO;
+ }
+ return 0;
+}
+
static ssize_t show_wlan(struct device *dev,
struct device_attribute *attr, char *buf)
{
@@ -836,6 +845,15 @@ static ssize_t store_wlan(struct device *dev, struct device_attribute *attr,
/*
* Bluetooth
*/
+static int asus_bluetooth_set(struct asus_laptop *asus, int status)
+{
+ if (write_acpi_int(asus->handle, METHOD_BLUETOOTH, !!status)) {
+ pr_warning("Error setting bluetooth status to %d", status);
+ return -EIO;
+ }
+ return 0;
+}
+
static ssize_t show_bluetooth(struct device *dev,
struct device_attribute *attr, char *buf)
{
@@ -1353,8 +1371,8 @@ static int asus_laptop_get_info(struct asus_laptop *asus)
(uint) bsts_result);

/* This too ... */
- write_acpi_int(asus->handle, "CWAP", wapf);
-
+ if (write_acpi_int(asus->handle, "CWAP", wapf))
+ pr_err("Error calling CWAP(%d)\n", wapf);
/*
* Try to match the object returned by INIT to the specific model.
* Handle every possible object (or the lack of thereof) the DSDT
@@ -1426,11 +1444,10 @@ static int __devinit asus_acpi_init(struct asus_laptop *asus)

/* WLED and BLED are on by default */
if (bluetooth_status >= 0)
- write_acpi_int(asus->handle, METHOD_BLUETOOTH,
- !!bluetooth_status);
+ asus_bluetooth_set(asus, !!bluetooth_status);
+
if (wireless_status >= 0)
- write_acpi_int(asus->handle, METHOD_WLAN,
- !!wireless_status);
+ asus_wlan_set(asus, !!wireless_status);

/* Keyboard Backlight is on by default */
if (!acpi_check_handle(asus->handle, METHOD_KBD_LIGHT_SET, NULL))
--
1.6.6.1

2010-02-02 07:54:45

by Corentin Chary

[permalink] [raw]
Subject: [PATCH 20/28] asus-laptop: switch to sparse keymap library

This patch is based on Dmitry Torokhov's patch with
some modifications and cleanups.

Signed-off-by: Corentin Chary <[email protected]>
---
drivers/platform/x86/Kconfig | 1 +
drivers/platform/x86/asus-laptop.c | 208 ++++++++++++------------------------
2 files changed, 68 insertions(+), 141 deletions(-)

diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index f526e73..7f5a222 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -59,6 +59,7 @@ config ASUS_LAPTOP
select NEW_LEDS
select BACKLIGHT_CLASS_DEVICE
depends on INPUT
+ select INPUT_SPARSEKMAP
---help---
This is the new Linux driver for Asus laptops. It may also support some
MEDION, JVC or VICTOR laptops. It makes all the extra buttons generate
diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c
index bb8fb45..8042568 100644
--- a/drivers/platform/x86/asus-laptop.c
+++ b/drivers/platform/x86/asus-laptop.c
@@ -49,6 +49,7 @@
#include <acpi/acpi_bus.h>
#include <asm/uaccess.h>
#include <linux/input.h>
+#include <linux/input/sparse-keymap.h>

#define ASUS_LAPTOP_VERSION "0.42"

@@ -243,52 +244,45 @@ struct asus_laptop {
u16 *keycode_map;
};

-struct key_entry {
- char type;
- u8 code;
- u16 keycode;
-};
-
-enum { KE_KEY, KE_END };
-
static const struct key_entry asus_keymap[] = {
- {KE_KEY, 0x02, KEY_SCREENLOCK},
- {KE_KEY, 0x05, KEY_WLAN},
- {KE_KEY, 0x08, KEY_F13},
- {KE_KEY, 0x17, KEY_ZOOM},
- {KE_KEY, 0x1f, KEY_BATTERY},
- {KE_KEY, 0x30, KEY_VOLUMEUP},
- {KE_KEY, 0x31, KEY_VOLUMEDOWN},
- {KE_KEY, 0x32, KEY_MUTE},
- {KE_KEY, 0x33, KEY_SWITCHVIDEOMODE},
- {KE_KEY, 0x34, KEY_SWITCHVIDEOMODE},
- {KE_KEY, 0x40, KEY_PREVIOUSSONG},
- {KE_KEY, 0x41, KEY_NEXTSONG},
- {KE_KEY, 0x43, KEY_STOPCD},
- {KE_KEY, 0x45, KEY_PLAYPAUSE},
- {KE_KEY, 0x4c, KEY_MEDIA},
- {KE_KEY, 0x50, KEY_EMAIL},
- {KE_KEY, 0x51, KEY_WWW},
- {KE_KEY, 0x55, KEY_CALC},
- {KE_KEY, 0x5C, KEY_SCREENLOCK}, /* Screenlock */
- {KE_KEY, 0x5D, KEY_WLAN},
- {KE_KEY, 0x5E, KEY_WLAN},
- {KE_KEY, 0x5F, KEY_WLAN},
- {KE_KEY, 0x60, KEY_SWITCHVIDEOMODE},
- {KE_KEY, 0x61, KEY_SWITCHVIDEOMODE},
- {KE_KEY, 0x62, KEY_SWITCHVIDEOMODE},
- {KE_KEY, 0x63, KEY_SWITCHVIDEOMODE},
- {KE_KEY, 0x6B, KEY_F13}, /* Lock Touchpad */
- {KE_KEY, 0x82, KEY_CAMERA},
- {KE_KEY, 0x88, KEY_WLAN },
- {KE_KEY, 0x8A, KEY_PROG1},
- {KE_KEY, 0x95, KEY_MEDIA},
- {KE_KEY, 0x99, KEY_PHONE},
- {KE_KEY, 0xc4, KEY_KBDILLUMUP},
- {KE_KEY, 0xc5, KEY_KBDILLUMDOWN},
+ {KE_KEY, 0x02, { KEY_SCREENLOCK } },
+ {KE_KEY, 0x05, { KEY_WLAN } },
+ {KE_KEY, 0x08, { KEY_F13 } },
+ {KE_KEY, 0x17, { KEY_ZOOM } },
+ {KE_KEY, 0x1f, { KEY_BATTERY } },
+ {KE_KEY, 0x30, { KEY_VOLUMEUP } },
+ {KE_KEY, 0x31, { KEY_VOLUMEDOWN } },
+ {KE_KEY, 0x32, { KEY_MUTE } },
+ {KE_KEY, 0x33, { KEY_SWITCHVIDEOMODE } },
+ {KE_KEY, 0x34, { KEY_SWITCHVIDEOMODE } },
+ {KE_KEY, 0x40, { KEY_PREVIOUSSONG } },
+ {KE_KEY, 0x41, { KEY_NEXTSONG } },
+ {KE_KEY, 0x43, { KEY_STOPCD } },
+ {KE_KEY, 0x45, { KEY_PLAYPAUSE } },
+ {KE_KEY, 0x4c, { KEY_MEDIA } },
+ {KE_KEY, 0x50, { KEY_EMAIL } },
+ {KE_KEY, 0x51, { KEY_WWW } },
+ {KE_KEY, 0x55, { KEY_CALC } },
+ {KE_KEY, 0x5C, { KEY_SCREENLOCK } }, /* Screenlock */
+ {KE_KEY, 0x5D, { KEY_WLAN } },
+ {KE_KEY, 0x5E, { KEY_WLAN } },
+ {KE_KEY, 0x5F, { KEY_WLAN } },
+ {KE_KEY, 0x60, { KEY_SWITCHVIDEOMODE } },
+ {KE_KEY, 0x61, { KEY_SWITCHVIDEOMODE } },
+ {KE_KEY, 0x62, { KEY_SWITCHVIDEOMODE } },
+ {KE_KEY, 0x63, { KEY_SWITCHVIDEOMODE } },
+ {KE_KEY, 0x6B, { KEY_F13 } }, /* Lock Touchpad */
+ {KE_KEY, 0x82, { KEY_CAMERA } },
+ {KE_KEY, 0x88, { KEY_WLAN } },
+ {KE_KEY, 0x8A, { KEY_PROG1 } },
+ {KE_KEY, 0x95, { KEY_MEDIA } },
+ {KE_KEY, 0x99, { KEY_PHONE } },
+ {KE_KEY, 0xc4, { KEY_KBDILLUMUP } },
+ {KE_KEY, 0xc5, { KEY_KBDILLUMDOWN } },
{KE_END, 0},
};

+
/*
* This function evaluates an ACPI method, given an int as parameter, the
* method is searched within the scope of the handle, can be NULL. The output
@@ -1050,123 +1044,55 @@ static ssize_t store_gps(struct device *dev, struct device_attribute *attr,
/*
* Input device (i.e. hotkeys)
*/
-static struct key_entry *asus_get_entry_by_scancode(struct asus_laptop *asus,
- int code)
-{
- struct key_entry *key;
-
- for (key = asus->keymap; key->type != KE_END; key++)
- if (code == key->code)
- return key;
-
- return NULL;
-}
-
-static struct key_entry *asus_get_entry_by_keycode(struct asus_laptop *asus,
- int code)
-{
- struct key_entry *key;
-
- for (key = asus->keymap; key->type != KE_END; key++)
- if (code == key->keycode && key->type == KE_KEY)
- return key;
-
- return NULL;
-}
-
-static int asus_getkeycode(struct input_dev *dev, int scancode, int *keycode)
-{
- struct asus_laptop *asus = input_get_drvdata(dev);
- struct key_entry *key = asus_get_entry_by_scancode(asus, scancode);
-
- if (key && key->type == KE_KEY) {
- *keycode = key->keycode;
- return 0;
- }
-
- return -EINVAL;
-}
-
-static int asus_setkeycode(struct input_dev *dev, int scancode, int keycode)
-{
- struct asus_laptop *asus = input_get_drvdata(dev);
- struct key_entry *key;
- int old_keycode;
-
- if (keycode < 0 || keycode > KEY_MAX)
- return -EINVAL;
-
- key = asus_get_entry_by_scancode(asus, scancode);
- if (key && key->type == KE_KEY) {
- old_keycode = key->keycode;
- key->keycode = keycode;
- set_bit(keycode, dev->keybit);
- if (!asus_get_entry_by_keycode(asus, old_keycode))
- clear_bit(old_keycode, dev->keybit);
- return 0;
- }
-
- return -EINVAL;
-}
-
static void asus_input_notify(struct asus_laptop *asus, int event)
{
- struct key_entry *key;
-
- key = asus_get_entry_by_scancode(asus, event);
- if (!key)
- return ;
-
- switch (key->type) {
- case KE_KEY:
- input_report_key(asus->inputdev, key->keycode, 1);
- input_sync(asus->inputdev);
- input_report_key(asus->inputdev, key->keycode, 0);
- input_sync(asus->inputdev);
- break;
- }
+ if (asus->inputdev)
+ sparse_keymap_report_event(asus->inputdev, event, 1, true);
}

static int asus_input_init(struct asus_laptop *asus)
{
- const struct key_entry *key;
- int result;
+ struct input_dev *input;
+ int error;

- asus->inputdev = input_allocate_device();
- if (!asus->inputdev) {
+ input = input_allocate_device();
+ if (!input) {
pr_info("Unable to allocate input device\n");
return 0;
}
- asus->inputdev->name = "Asus Laptop extra buttons";
- asus->inputdev->dev.parent = &asus->platform_device->dev;
- asus->inputdev->phys = ASUS_LAPTOP_FILE "/input0";
- asus->inputdev->id.bustype = BUS_HOST;
- asus->inputdev->getkeycode = asus_getkeycode;
- asus->inputdev->setkeycode = asus_setkeycode;
- input_set_drvdata(asus->inputdev, asus);
-
- asus->keymap = kmemdup(asus_keymap, sizeof(asus_keymap),
- GFP_KERNEL);
- for (key = asus->keymap; key->type != KE_END; key++) {
- switch (key->type) {
- case KE_KEY:
- set_bit(EV_KEY, asus->inputdev->evbit);
- set_bit(key->keycode, asus->inputdev->keybit);
- break;
- }
+ input->name = "Asus Laptop extra buttons";
+ 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) {
+ pr_err("Unable to setup input device keymap\n");
+ goto err_keymap;
}
- result = input_register_device(asus->inputdev);
- if (result) {
+ error = input_register_device(input);
+ if (error) {
pr_info("Unable to register input device\n");
- input_free_device(asus->inputdev);
+ goto err_device;
}
- return result;
+
+ asus->inputdev = input;
+ return 0;
+
+err_keymap:
+ sparse_keymap_free(input);
+err_device:
+ input_free_device(input);
+ return error;
}

static void asus_input_exit(struct asus_laptop *asus)
{
- if (asus->inputdev)
+ if (asus->inputdev) {
+ sparse_keymap_free(asus->inputdev);
input_unregister_device(asus->inputdev);
+ }
}

/*
--
1.6.6.1

2010-02-02 07:54:39

by Corentin Chary

[permalink] [raw]
Subject: [PATCH 13/28] asus-laptop: stop using read_status and store_status for GPS

Signed-off-by: Corentin Chary <[email protected]>
---
drivers/platform/x86/asus-laptop.c | 56 ++++++++++++++++++++++-------------
1 files changed, 35 insertions(+), 21 deletions(-)

diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c
index cee751e..ea51d7e 100644
--- a/drivers/platform/x86/asus-laptop.c
+++ b/drivers/platform/x86/asus-laptop.c
@@ -331,26 +331,9 @@ static int write_acpi_int(acpi_handle handle, const char *method, int val)
return write_acpi_int_ret(handle, method, val, NULL);
}

-static int read_gps_status(struct asus_laptop *asus)
-{
- unsigned long long status;
- acpi_status rv = AE_OK;
-
- rv = acpi_evaluate_integer(gps_status_handle, NULL, NULL, &status);
- if (ACPI_FAILURE(rv))
- pr_warning("Error reading GPS status\n");
- else
- return status ? 1 : 0;
-
- return (asus->status & GPS_ON) ? 1 : 0;
-}
-
/* Generic LED functions */
static int read_status(struct asus_laptop *asus, int mask)
{
- if (mask == GPS_ON)
- return read_gps_status(asus);
-
return (asus->status & mask) ? 1 : 0;
}

@@ -979,21 +962,52 @@ static ssize_t store_lslvl(struct device *dev, struct device_attribute *attr,

/*
* GPS
+ * TODO: use rfkill
*/
+static int asus_gps_status(struct asus_laptop *asus)
+{
+ unsigned long long status;
+ acpi_status rv = AE_OK;
+
+ rv = acpi_evaluate_integer(gps_status_handle, NULL, NULL, &status);
+ if (ACPI_FAILURE(rv)) {
+ pr_warning("Error reading GPS status\n");
+ return -ENODEV;
+ }
+ return !!status;
+}
+
+static int asus_gps_switch(struct asus_laptop *asus, int status)
+{
+ acpi_handle handle = status ? gps_on_handle : gps_off_handle;
+
+ if (write_acpi_int(handle, NULL, 0x02))
+ return -ENODEV;
+ return 0;
+}
+
static ssize_t show_gps(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct asus_laptop *asus = dev_get_drvdata(dev);

- return sprintf(buf, "%d\n", read_status(asus, GPS_ON));
+ return sprintf(buf, "%d\n", asus_gps_status(asus));
}

static ssize_t store_gps(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
- struct asus_laptop *asus = dev_get_drvdata(dev);
+ struct asus_laptop *asus = dev_get_drvdata(dev);
+ int rv, value;
+ int ret;

- return store_status(asus, buf, count, NULL, GPS_ON);
+ rv = parse_arg(buf, count, &value);
+ if (rv <= 0)
+ return -EINVAL;
+ ret = asus_gps_switch(asus, !!value);
+ if (ret)
+ return ret;
+ return rv;
}

/*
@@ -1451,7 +1465,7 @@ static int __devinit asus_acpi_init(struct asus_laptop *asus)
set_light_sens_level(asus, asus->light_level);

/* GPS is on by default */
- write_status(asus, NULL, 1, GPS_ON);
+ asus_gps_switch(asus, 1);
return result;
}

--
1.6.6.1

2010-02-02 07:52:22

by Corentin Chary

[permalink] [raw]
Subject: [PATCH 27/28] asus-laptop: use device_create_file() instead of platform_group

There is two reason to do that:
- we don't want a "gps" file if the model doesn't have a gps
- we don't want to use global variables anymore

Signed-off-by: Corentin Chary <[email protected]>
---
drivers/platform/x86/asus-laptop.c | 166 ++++++++++++++++++------------------
1 files changed, 84 insertions(+), 82 deletions(-)

diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c
index ae53026..d0d117b 100644
--- a/drivers/platform/x86/asus-laptop.c
+++ b/drivers/platform/x86/asus-laptop.c
@@ -918,6 +918,8 @@ static ssize_t show_disp(struct device *dev,
{
struct asus_laptop *asus = dev_get_drvdata(dev);

+ if (!display_get_handle)
+ return -ENODEV;
return sprintf(buf, "%d\n", read_display(asus));
}

@@ -1191,77 +1193,113 @@ static void asus_acpi_notify(struct acpi_device *device, u32 event)
asus_input_notify(asus, event);
}

-#define ASUS_CREATE_DEVICE_ATTR(_name) \
- struct device_attribute dev_attr_##_name = { \
- .attr = { \
- .name = __stringify(_name), \
- .mode = 0 }, \
- .show = NULL, \
- .store = NULL, \
+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(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 int asus_sysfs_init(struct asus_laptop *asus)
+{
+ struct platform_device *device = asus->platform_device;
+ int err;
+
+ err = device_create_file(&device->dev, &dev_attr_infos);
+ if (err)
+ return err;
+
+ if (!acpi_check_handle(asus->handle, METHOD_WLAN, NULL)) {
+ err = device_create_file(&device->dev, &dev_attr_wlan);
+ if (err)
+ return err;
}

-#define ASUS_SET_DEVICE_ATTR(_name, _mode, _show, _store) \
- do { \
- dev_attr_##_name.attr.mode = _mode; \
- dev_attr_##_name.show = _show; \
- dev_attr_##_name.store = _store; \
- } while(0)
-
-static ASUS_CREATE_DEVICE_ATTR(infos);
-static ASUS_CREATE_DEVICE_ATTR(wlan);
-static ASUS_CREATE_DEVICE_ATTR(bluetooth);
-static ASUS_CREATE_DEVICE_ATTR(display);
-static ASUS_CREATE_DEVICE_ATTR(ledd);
-static ASUS_CREATE_DEVICE_ATTR(ls_switch);
-static ASUS_CREATE_DEVICE_ATTR(ls_level);
-static ASUS_CREATE_DEVICE_ATTR(gps);
-
-static struct attribute *asuspf_attributes[] = {
- &dev_attr_infos.attr,
- &dev_attr_wlan.attr,
- &dev_attr_bluetooth.attr,
- &dev_attr_display.attr,
- &dev_attr_ledd.attr,
- &dev_attr_ls_switch.attr,
- &dev_attr_ls_level.attr,
- &dev_attr_gps.attr,
- NULL
-};
+ if (!acpi_check_handle(asus->handle, METHOD_BLUETOOTH, NULL)) {
+ err = device_create_file(&device->dev, &dev_attr_bluetooth);
+ if (err)
+ return err;
+ }

-static struct attribute_group platform_attribute_group = {
- .attrs = asuspf_attributes
-};
+ if (!acpi_check_handle(asus->handle, METHOD_SWITCH_DISPLAY, NULL)) {
+ err = device_create_file(&device->dev, &dev_attr_display);
+ if (err)
+ return err;
+ }
+
+ if (!acpi_check_handle(asus->handle, METHOD_LEDD, NULL)) {
+ err = device_create_file(&device->dev, &dev_attr_ledd);
+ if (err)
+ return err;
+ }
+
+ 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;
+ }
+
+ 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;
+ }
+
+ return err;
+}

static int asus_platform_init(struct asus_laptop *asus)
{
- int result;
+ int err;

asus->platform_device = platform_device_alloc(ASUS_LAPTOP_FILE, -1);
if (!asus->platform_device)
return -ENOMEM;
platform_set_drvdata(asus->platform_device, asus);

- result = platform_device_add(asus->platform_device);
- if (result)
+ err = platform_device_add(asus->platform_device);
+ if (err)
goto fail_platform_device;

- result = sysfs_create_group(&asus->platform_device->dev.kobj,
- &platform_attribute_group);
- if (result)
+ err = asus_sysfs_init(asus);
+ if (err)
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 result;
+ return err;
}

static void asus_platform_exit(struct asus_laptop *asus)
{
- sysfs_remove_group(&asus->platform_device->dev.kobj,
- &platform_attribute_group);
+ asus_sysfs_exit(asus);
platform_device_unregister(asus->platform_device);
}

@@ -1272,40 +1310,6 @@ static struct platform_driver platform_driver = {
}
};

-static void asus_laptop_add_fs(struct asus_laptop *asus)
-{
- ASUS_SET_DEVICE_ATTR(infos, 0444, show_infos, NULL);
-
- if (!acpi_check_handle(asus->handle, METHOD_WLAN, NULL))
- ASUS_SET_DEVICE_ATTR(wlan, 0644, show_wlan, store_wlan);
-
- if (!acpi_check_handle(asus->handle, METHOD_BLUETOOTH, NULL))
- ASUS_SET_DEVICE_ATTR(bluetooth, 0644,
- show_bluetooth, store_bluetooth);
-
- if (!acpi_check_handle(asus->handle, METHOD_SWITCH_DISPLAY, NULL)) {
- if (display_get_handle)
- ASUS_SET_DEVICE_ATTR(display, 0644, show_disp,
- store_disp);
- else
- ASUS_SET_DEVICE_ATTR(display, 0200, NULL, store_disp);
- }
-
- if (!acpi_check_handle(asus->handle, METHOD_LEDD, NULL))
- ASUS_SET_DEVICE_ATTR(ledd, 0644, show_ledd, store_ledd);
-
- if (!acpi_check_handle(asus->handle, METHOD_ALS_CONTROL, NULL) &&
- !acpi_check_handle(asus->handle, METHOD_ALS_LEVEL, NULL)) {
- ASUS_SET_DEVICE_ATTR(ls_level, 0644, show_lslvl, store_lslvl);
- ASUS_SET_DEVICE_ATTR(ls_switch, 0644, show_lssw, store_lssw);
- }
-
- 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))
- ASUS_SET_DEVICE_ATTR(gps, 0644, show_gps, store_gps);
-}
-
static int asus_handle_init(char *name, acpi_handle * handle,
char **paths, int num_paths)
{
@@ -1435,8 +1439,6 @@ static int __devinit asus_acpi_init(struct asus_laptop *asus)
if (result)
return result;

- asus_laptop_add_fs(asus);
-
/* WLED and BLED are on by default */
if (bluetooth_status >= 0)
asus_bluetooth_set(asus, !!bluetooth_status);
--
1.6.6.1

2010-02-02 07:54:13

by Corentin Chary

[permalink] [raw]
Subject: [PATCH 14/28] asus-laptop: stop using read_status for lcd

(anyway lcd code is scheduled for removal)

Signed-off-by: Corentin Chary <[email protected]>
---
drivers/platform/x86/asus-laptop.c | 37 +++++++++++++++++++----------------
1 files changed, 20 insertions(+), 17 deletions(-)

diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c
index ea51d7e..d726db3 100644
--- a/drivers/platform/x86/asus-laptop.c
+++ b/drivers/platform/x86/asus-laptop.c
@@ -241,6 +241,7 @@ struct asus_laptop {

int wireless_status;
bool have_rsts;
+ int lcd_state;

acpi_handle handle; /* the handle of the hotk device */
char status; /* status of the hotk, for LEDs, ... */
@@ -538,30 +539,33 @@ error:
/*
* Backlight device
*/
-static int get_lcd_state(struct asus_laptop *asus)
+static int asus_lcd_status(struct asus_laptop *asus)
{
- return read_status(asus, LCD_ON);
+ return asus->lcd_state;
}

-static int set_lcd_state(struct asus_laptop *asus, int value)
+static int asus_lcd_set(struct asus_laptop *asus, int value)
{
int lcd = 0;
acpi_status status = 0;

- lcd = value ? 1 : 0;
+ lcd = !!value;

- if (lcd == get_lcd_state(asus))
+ if (lcd == asus_lcd_status(asus))
return 0;

- if (lcd_switch_handle) {
- status = acpi_evaluate_object(lcd_switch_handle,
- NULL, NULL, NULL);
+ if (!lcd_switch_handle)
+ return -ENODEV;
+
+ status = acpi_evaluate_object(lcd_switch_handle,
+ NULL, NULL, NULL);

- if (ACPI_FAILURE(status))
- pr_warning("Error switching LCD\n");
+ if (ACPI_FAILURE(status)) {
+ pr_warning("Error switching LCD\n");
+ return -ENODEV;
}

- write_status(asus, NULL, lcd, LCD_ON);
+ asus->lcd_state = lcd;
return 0;
}

@@ -569,6 +573,8 @@ static void lcd_blank(struct asus_laptop *asus, int blank)
{
struct backlight_device *bd = asus->backlight_device;

+ asus->lcd_state = (blank == FB_BLANK_UNBLANK);
+
if (bd) {
bd->props.power = blank;
backlight_update_status(bd);
@@ -607,7 +613,7 @@ static int update_bl_status(struct backlight_device *bd)
return rv;

value = (bd->props.power == FB_BLANK_UNBLANK) ? 1 : 0;
- return set_lcd_state(asus, value);
+ return asus_lcd_set(asus, value);
}

static struct backlight_ops asusbl_ops = {
@@ -1144,13 +1150,10 @@ static void asus_acpi_notify(struct acpi_device *device, u32 event)
* We need to tell the backlight device when the backlight power is
* switched
*/
- if (event == ATKD_LCD_ON) {
- write_status(asus, NULL, 1, LCD_ON);
+ if (event == ATKD_LCD_ON)
lcd_blank(asus, FB_BLANK_UNBLANK);
- } else if (event == ATKD_LCD_OFF) {
- write_status(asus, NULL, 0, LCD_ON);
+ else if (event == ATKD_LCD_OFF)
lcd_blank(asus, FB_BLANK_POWERDOWN);
- }

/* TODO Find a better way to handle events count. */
count = asus->event_count[event % 128]++;
--
1.6.6.1

2010-02-02 07:52:24

by Corentin Chary

[permalink] [raw]
Subject: [PATCH 26/28] asus-laptop: clean led code

Remove all "templates" and add a generic struct asus_led instead.

Signed-off-by: Corentin Chary <[email protected]>
---
drivers/platform/x86/asus-laptop.c | 235 ++++++++++++++++++------------------
1 files changed, 115 insertions(+), 120 deletions(-)

diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c
index e1df92a..ae53026 100644
--- a/drivers/platform/x86/asus-laptop.c
+++ b/drivers/platform/x86/asus-laptop.c
@@ -193,29 +193,12 @@ ASUS_HANDLE(display_get,
/*
* Define a specific led structure to keep the main structure clean
*/
-#define ASUS_DEFINE_LED(object) \
- int object##_wk; \
- struct work_struct object##_work; \
- struct led_classdev object;
-
-
-#define led_to_asus(led_cdev, led) \
- container_of(container_of(led_cdev, struct asus_laptop_leds, \
- led), \
- struct asus_laptop, leds)
-#define work_to_asus(work, led) \
- container_of(container_of(work, struct asus_laptop_leds, \
- led##_work), \
- struct asus_laptop, leds)
-
-struct asus_laptop_leds {
- ASUS_DEFINE_LED(mled)
- ASUS_DEFINE_LED(tled)
- ASUS_DEFINE_LED(rled)
- ASUS_DEFINE_LED(pled)
- ASUS_DEFINE_LED(gled)
- ASUS_DEFINE_LED(kled)
- struct workqueue_struct *workqueue;
+struct asus_led {
+ int wk;
+ struct work_struct work;
+ struct led_classdev led;
+ struct asus_laptop *asus;
+ const char *method;
};

/*
@@ -233,7 +216,13 @@ struct asus_laptop {
struct input_dev *inputdev;
struct key_entry *keymap;

- struct asus_laptop_leds leds;
+ struct asus_led mled;
+ struct asus_led tled;
+ struct asus_led rled;
+ struct asus_led pled;
+ struct asus_led gled;
+ struct asus_led kled;
+ struct workqueue_struct *led_workqueue;

int wireless_status;
bool have_rsts;
@@ -353,7 +342,7 @@ static int acpi_check_handle(acpi_handle handle, const char *method,
}

/* Generic LED function */
-static int asus_led_set(struct asus_laptop *asus, char *method,
+static int asus_led_set(struct asus_laptop *asus, const char *method,
int value)
{
if (!strcmp(method, METHOD_MLED))
@@ -369,50 +358,29 @@ static int asus_led_set(struct asus_laptop *asus, char *method,
/*
* LEDs
*/
-#define ASUS_LED(object, ledname, max) \
- static void object##_led_set(struct led_classdev *led_cdev, \
- enum led_brightness value); \
- static enum led_brightness object##_led_get( \
- struct led_classdev *led_cdev); \
- static void object##_led_update(struct work_struct *ignored);
-
-ASUS_LED(mled, "mail", 1);
-ASUS_LED(tled, "touchpad", 1);
-ASUS_LED(rled, "record", 1);
-ASUS_LED(pled, "phone", 1);
-ASUS_LED(gled, "gaming", 1);
-ASUS_LED(kled, "kbd_backlight", 3);
-
/* /sys/class/led handlers */
-#define ASUS_LED_HANDLER(object, method) \
- static void object##_led_set(struct led_classdev *led_cdev, \
- enum led_brightness value) \
- { \
- struct asus_laptop *asus = \
- led_to_asus(led_cdev, object); \
- \
- asus->leds.object##_wk = (value > 0) ? 1 : 0; \
- queue_work(asus->leds.workqueue, \
- &asus->leds.object##_work); \
- } \
- static void object##_led_update(struct work_struct *work) \
- { \
- struct asus_laptop *asus = work_to_asus(work, object); \
- \
- int value = asus->leds.object##_wk; \
- asus_led_set(asus, method, value); \
- } \
- static enum led_brightness object##_led_get( \
- struct led_classdev *led_cdev) \
- { \
- return led_cdev->brightness; \
- }
+static void asus_led_cdev_set(struct led_classdev *led_cdev,
+ enum led_brightness value)
+{
+ struct asus_led *led = container_of(led_cdev, struct asus_led, led);
+ struct asus_laptop *asus = led->asus;
+
+ led->wk = !!value;
+ queue_work(asus->led_workqueue, &led->work);
+}
+
+static void asus_led_cdev_update(struct work_struct *work)
+{
+ struct asus_led *led = container_of(work, struct asus_led, work);
+ struct asus_laptop *asus = led->asus;

-ASUS_LED_HANDLER(mled, METHOD_MLED);
-ASUS_LED_HANDLER(pled, METHOD_PLED);
-ASUS_LED_HANDLER(rled, METHOD_RLED);
-ASUS_LED_HANDLER(tled, METHOD_TLED);
-ASUS_LED_HANDLER(gled, METHOD_GLED);
+ asus_led_set(asus, led->method, led->wk);
+}
+
+static enum led_brightness asus_led_cdev_get(struct led_classdev *led_cdev)
+{
+ return led_cdev->brightness;
+}

/*
* Keyboard backlight (also a LED)
@@ -452,70 +420,76 @@ static int asus_kled_set(struct asus_laptop *asus, int kblv)
return 0;
}

-static void kled_led_set(struct led_classdev *led_cdev,
- enum led_brightness value)
+static void asus_kled_cdev_set(struct led_classdev *led_cdev,
+ enum led_brightness value)
{
- struct asus_laptop *asus = led_to_asus(led_cdev, kled);
+ struct asus_led *led = container_of(led_cdev, struct asus_led, led);
+ struct asus_laptop *asus = led->asus;

- asus->leds.kled_wk = value;
- queue_work(asus->leds.workqueue, &asus->leds.kled_work);
+ led->wk = value;
+ queue_work(asus->led_workqueue, &led->work);
}

-static void kled_led_update(struct work_struct *work)
+static void asus_kled_cdev_update(struct work_struct *work)
{
- struct asus_laptop *asus = work_to_asus(work, kled);
+ struct asus_led *led = container_of(work, struct asus_led, work);
+ struct asus_laptop *asus = led->asus;

- asus_kled_set(asus, asus->leds.kled_wk);
+ asus_kled_set(asus, led->wk);
}

-static enum led_brightness kled_led_get(struct led_classdev *led_cdev)
+static enum led_brightness asus_kled_cdev_get(struct led_classdev *led_cdev)
{
- struct asus_laptop *asus = led_to_asus(led_cdev, kled);
+ struct asus_led *led = container_of(led_cdev, struct asus_led, led);
+ struct asus_laptop *asus = led->asus;

return asus_kled_lvl(asus);
}

static void asus_led_exit(struct asus_laptop *asus)
{
- if (asus->leds.mled.dev)
- led_classdev_unregister(&asus->leds.mled);
- if (asus->leds.tled.dev)
- led_classdev_unregister(&asus->leds.tled);
- if (asus->leds.pled.dev)
- led_classdev_unregister(&asus->leds.pled);
- if (asus->leds.rled.dev)
- led_classdev_unregister(&asus->leds.rled);
- if (asus->leds.gled.dev)
- led_classdev_unregister(&asus->leds.gled);
- if (asus->leds.kled.dev)
- led_classdev_unregister(&asus->leds.kled);
- if (asus->leds.workqueue) {
- destroy_workqueue(asus->leds.workqueue);
- asus->leds.workqueue = NULL;
+ if (asus->mled.led.dev)
+ led_classdev_unregister(&asus->mled.led);
+ if (asus->tled.led.dev)
+ led_classdev_unregister(&asus->tled.led);
+ if (asus->pled.led.dev)
+ led_classdev_unregister(&asus->pled.led);
+ if (asus->rled.led.dev)
+ led_classdev_unregister(&asus->rled.led);
+ if (asus->gled.led.dev)
+ led_classdev_unregister(&asus->gled.led);
+ if (asus->kled.led.dev)
+ led_classdev_unregister(&asus->kled.led);
+ if (asus->led_workqueue) {
+ destroy_workqueue(asus->led_workqueue);
+ asus->led_workqueue = NULL;
}
}

/* Ugly macro, need to fix that later */
-#define ASUS_LED_REGISTER(asus, object, _name, max, method) \
- do { \
- struct led_classdev *ldev = &asus->leds.object; \
- \
- if (method && acpi_check_handle(asus->handle, method, NULL)) \
- break ; \
- \
- INIT_WORK(&asus->leds.object##_work, object##_led_update); \
- ldev->name = "asus::" _name; \
- ldev->brightness_set = object##_led_set; \
- ldev->brightness_get = object##_led_get; \
- ldev->max_brightness = max; \
- rv = led_classdev_register(&asus->platform_device->dev, ldev); \
- if (rv) \
- goto error; \
- } while (0)
+static int asus_led_register(struct asus_laptop *asus,
+ struct asus_led *led,
+ const char *name, const char *method)
+{
+ struct led_classdev *led_cdev = &led->led;
+
+ if (!method || acpi_check_handle(asus->handle, method, NULL))
+ return 0; /* Led not present */
+
+ led->asus = asus;
+ led->method = method;
+
+ INIT_WORK(&led->work, asus_led_cdev_update);
+ led_cdev->name = name;
+ led_cdev->brightness_set = asus_led_cdev_set;
+ led_cdev->brightness_get = asus_led_cdev_get;
+ led_cdev->max_brightness = 1;
+ return led_classdev_register(&asus->platform_device->dev, led_cdev);
+}

static int asus_led_init(struct asus_laptop *asus)
{
- int rv;
+ int r;

/*
* Functions that actually update the LED's are called from a
@@ -523,22 +497,43 @@ static int asus_led_init(struct asus_laptop *asus)
* subsystem asks, we avoid messing with the Asus ACPI stuff during a
* potentially bad time, such as a timer interrupt.
*/
- asus->leds.workqueue = create_singlethread_workqueue("led_workqueue");
- if (!asus->leds.workqueue)
+ asus->led_workqueue = create_singlethread_workqueue("led_workqueue");
+ if (!asus->led_workqueue)
return -ENOMEM;

- ASUS_LED_REGISTER(asus, mled, "mail", 1, METHOD_MLED);
- ASUS_LED_REGISTER(asus, tled, "touchpad", 1, METHOD_TLED);
- ASUS_LED_REGISTER(asus, rled, "record", 1, METHOD_RLED);
- ASUS_LED_REGISTER(asus, pled, "phone", 1, METHOD_PLED);
- ASUS_LED_REGISTER(asus, gled, "gaming", 1, METHOD_GLED);
+ r = asus_led_register(asus, &asus->mled, "asus::mail", METHOD_MLED);
+ if (r)
+ goto error;
+ r = asus_led_register(asus, &asus->tled, "asus::touchpad", METHOD_TLED);
+ if (r)
+ goto error;
+ r = asus_led_register(asus, &asus->rled, "asus::record", METHOD_RLED);
+ if (r)
+ goto error;
+ r = asus_led_register(asus, &asus->pled, "asus::phone", METHOD_PLED);
+ if (r)
+ goto error;
+ r = asus_led_register(asus, &asus->gled, "asus::gaming", METHOD_GLED);
+ if (r)
+ goto error;
if (!acpi_check_handle(asus->handle, METHOD_KBD_LIGHT_SET, NULL) &&
- !acpi_check_handle(asus->handle, METHOD_KBD_LIGHT_GET, NULL))
- ASUS_LED_REGISTER(asus, kled, "kbd_backlight", 3, NULL);
+ !acpi_check_handle(asus->handle, METHOD_KBD_LIGHT_GET, NULL)) {
+ struct asus_led *led = &asus->kled;
+ struct led_classdev *cdev = &led->led;
+
+ led->asus = asus;
+
+ INIT_WORK(&led->work, asus_kled_cdev_update);
+ cdev->name = "asus::kbd_backlight";
+ cdev->brightness_set = asus_kled_cdev_set;
+ cdev->brightness_get = asus_kled_cdev_get;
+ cdev->max_brightness = 3;
+ r = led_classdev_register(&asus->platform_device->dev, cdev);
+ }
error:
- if (rv)
+ if (r)
asus_led_exit(asus);
- return rv;
+ return r;
}

/*
--
1.6.6.1

2010-02-02 07:55:15

by Corentin Chary

[permalink] [raw]
Subject: [PATCH 17/28] asus-laptop: stop using ASUS_HANDLE and use relative methods instead

From: Corentin Chary <[email protected]>

Stop using ASUS_HANDLE because most of the time it is not needed.
This macro was introduced to display_get and lcd_switch which are not
part of the interface provided by Asus, and are scheduled for removal.

Signed-off-by: Corentin Chary <[email protected]>
---
drivers/platform/x86/asus-laptop.c | 240 +++++++++++++++++++-----------------
1 files changed, 129 insertions(+), 111 deletions(-)

diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c
index ae4f808..671fad9 100644
--- a/drivers/platform/x86/asus-laptop.c
+++ b/drivers/platform/x86/asus-laptop.c
@@ -115,27 +115,27 @@ MODULE_PARM_DESC(bluetooth_status, "Set the wireless status on boot "
static char *object##_paths[] = { paths }

/* LED */
-ASUS_HANDLE(mled_set, ASUS_LAPTOP_PREFIX "MLED");
-ASUS_HANDLE(tled_set, ASUS_LAPTOP_PREFIX "TLED");
-ASUS_HANDLE(rled_set, ASUS_LAPTOP_PREFIX "RLED"); /* W1JC */
-ASUS_HANDLE(pled_set, ASUS_LAPTOP_PREFIX "PLED"); /* A7J */
-ASUS_HANDLE(gled_set, ASUS_LAPTOP_PREFIX "GLED"); /* G1, G2 (probably) */
+#define METHOD_MLED "MLED"
+#define METHOD_TLED "TLED"
+#define METHOD_RLED "RLED" /* W1JC */
+#define METHOD_PLED "PLED" /* A7J */
+#define METHOD_GLED "GLED" /* G1, G2 (probably) */

/* LEDD */
-ASUS_HANDLE(ledd_set, ASUS_LAPTOP_PREFIX "SLCM");
+#define METHOD_LEDD "SLCM"

/*
* Bluetooth and WLAN
* WLED and BLED are not handled like other XLED, because in some dsdt
* they also control the WLAN/Bluetooth device.
*/
-ASUS_HANDLE(wl_switch, ASUS_LAPTOP_PREFIX "WLED");
-ASUS_HANDLE(bt_switch, ASUS_LAPTOP_PREFIX "BLED");
-ASUS_HANDLE(wireless_status, ASUS_LAPTOP_PREFIX "RSTS"); /* All new models */
+#define METHOD_WLAN "WLED"
+#define METHOD_BLUETOOTH "BLED"
+#define METHOD_WL_STATUS "RSTS"

/* Brightness */
-ASUS_HANDLE(brightness_set, ASUS_LAPTOP_PREFIX "SPLV");
-ASUS_HANDLE(brightness_get, ASUS_LAPTOP_PREFIX "GPLV");
+#define METHOD_BRIGHTNESS_SET "SPLV"
+#define METHOD_BRIGHTNESS_GET "GPLV"

/* Backlight */
ASUS_HANDLE(lcd_switch, "\\_SB.PCI0.SBRG.EC0._Q10", /* All new models */
@@ -148,7 +148,7 @@ ASUS_HANDLE(lcd_switch, "\\_SB.PCI0.SBRG.EC0._Q10", /* All new models */
"\\Q10"); /* A2x, L2D, L3D, M2E */

/* Display */
-ASUS_HANDLE(display_set, ASUS_LAPTOP_PREFIX "SDSP");
+#define METHOD_SWITCH_DISPLAY "SDSP"
ASUS_HANDLE(display_get,
/* A6B, A6K A6R A7D F3JM L4R M6R A3G M6A M6V VX-1 V6J V6V W3Z */
"\\_SB.PCI0.P0P1.VGA.GETD",
@@ -173,18 +173,18 @@ ASUS_HANDLE(display_get,
/* A3F A6F A3N A3L M6N W3N W6A */
"\\SSTE");

-ASUS_HANDLE(ls_switch, ASUS_LAPTOP_PREFIX "ALSC"); /* Z71A Z71V */
-ASUS_HANDLE(ls_level, ASUS_LAPTOP_PREFIX "ALSL"); /* Z71A Z71V */
+#define METHOD_ALS_CONTROL "ALSC" /* Z71A Z71V */
+#define METHOD_ALS_LEVEL "ALSL" /* Z71A Z71V */

/* GPS */
/* R2H use different handle for GPS on/off */
-ASUS_HANDLE(gps_on, ASUS_LAPTOP_PREFIX "SDON"); /* R2H */
-ASUS_HANDLE(gps_off, ASUS_LAPTOP_PREFIX "SDOF"); /* R2H */
-ASUS_HANDLE(gps_status, ASUS_LAPTOP_PREFIX "GPST");
+#define METHOD_GPS_ON "SDON"
+#define METHOD_GPS_OFF "SDOF"
+#define METHOD_GPS_STATUS "GPST"

/* Keyboard light */
-ASUS_HANDLE(kled_set, ASUS_LAPTOP_PREFIX "SLKB");
-ASUS_HANDLE(kled_get, ASUS_LAPTOP_PREFIX "GLKB");
+#define METHOD_KBD_LIGHT_SET "SLKB"
+#define METHOD_KBD_LIGHT_GET "GLKB"

/*
* Define a specific led structure to keep the main structure clean
@@ -323,18 +323,44 @@ static int write_acpi_int(acpi_handle handle, const char *method, int val)
return write_acpi_int_ret(handle, method, val, NULL);
}

+static int acpi_check_handle(acpi_handle handle, const char *method,
+ acpi_handle *ret)
+{
+ acpi_status status;
+
+ if (method == NULL)
+ return -ENODEV;
+
+ if (ret)
+ status = acpi_get_handle(handle, (char *)method,
+ ret);
+ else {
+ acpi_handle dummy;
+
+ status = acpi_get_handle(handle, (char *)method,
+ &dummy);
+ }
+
+ if (status != AE_OK) {
+ if (ret)
+ pr_warning("Error finding %s\n", method);
+ return -ENODEV;
+ }
+ return 0;
+}
+
/* Generic LED function */
-static void asus_led_set(struct asus_laptop *asus, acpi_handle handle,
+static void asus_led_set(struct asus_laptop *asus, char *method,
int value)
{
- if (handle == mled_set_handle)
+ if (!strcmp(method, METHOD_MLED))
value = !value;
- else if (handle == gled_set_handle)
+ else if (!strcmp(method, METHOD_GLED))
value = !value + 1;
else
value = !!value;

- write_acpi_int(handle, NULL, value);
+ write_acpi_int(asus->handle, method, value);
}

/*
@@ -361,7 +387,7 @@ ASUS_LED(gled, "gaming", 1);
ASUS_LED(kled, "kbd_backlight", 3);

/* /sys/class/led handlers */
-#define ASUS_LED_HANDLER(object, mask) \
+#define ASUS_LED_HANDLER(object, method) \
static void object##_led_set(struct led_classdev *led_cdev, \
enum led_brightness value) \
{ \
@@ -377,7 +403,7 @@ ASUS_LED(kled, "kbd_backlight", 3);
struct asus_laptop *asus = work_to_asus(work, object); \
\
int value = asus->leds.object##_wk; \
- asus_led_set(asus, object##_set_handle, value); \
+ asus_led_set(asus, method, value); \
} \
static enum led_brightness object##_led_get( \
struct led_classdev *led_cdev) \
@@ -385,16 +411,16 @@ ASUS_LED(kled, "kbd_backlight", 3);
return led_cdev->brightness; \
}

-ASUS_LED_HANDLER(mled, MLED_ON);
-ASUS_LED_HANDLER(pled, PLED_ON);
-ASUS_LED_HANDLER(rled, RLED_ON);
-ASUS_LED_HANDLER(tled, TLED_ON);
-ASUS_LED_HANDLER(gled, GLED_ON);
+ASUS_LED_HANDLER(mled, METHOD_MLED);
+ASUS_LED_HANDLER(pled, METHOD_PLED);
+ASUS_LED_HANDLER(rled, METHOD_RLED);
+ASUS_LED_HANDLER(tled, METHOD_TLED);
+ASUS_LED_HANDLER(gled, METHOD_GLED);

/*
* Keyboard backlight (also a LED)
*/
-static int asus_kled_lvl(void)
+static int asus_kled_lvl(struct asus_laptop *asus)
{
unsigned long long kblv;
struct acpi_object_list params;
@@ -406,7 +432,8 @@ static int asus_kled_lvl(void)
in_obj.type = ACPI_TYPE_INTEGER;
in_obj.integer.value = 2;

- rv = acpi_evaluate_integer(kled_get_handle, NULL, &params, &kblv);
+ rv = acpi_evaluate_integer(asus->handle, METHOD_KBD_LIGHT_GET,
+ &params, &kblv);
if (ACPI_FAILURE(rv)) {
pr_warning("Error reading kled level\n");
return -ENODEV;
@@ -421,7 +448,7 @@ static int asus_kled_set(struct asus_laptop *asus, int kblv)
else
kblv = 0;

- if (write_acpi_int(kled_set_handle, NULL, kblv)) {
+ if (write_acpi_int(asus->handle, METHOD_KBD_LIGHT_SET, kblv)) {
pr_warning("Keyboard LED display write failed\n");
return -EINVAL;
}
@@ -446,7 +473,9 @@ static void kled_led_update(struct work_struct *work)

static enum led_brightness kled_led_get(struct led_classdev *led_cdev)
{
- return asus_kled_lvl();
+ struct asus_laptop *asus = led_to_asus(led_cdev, kled);
+
+ return asus_kled_lvl(asus);
}

#define ASUS_LED_UNREGISTER(object) \
@@ -468,10 +497,11 @@ static void asus_led_exit(struct asus_laptop *asus)
}

/* Ugly macro, need to fix that later */
-#define ASUS_LED_REGISTER(asus, object, _name, max) \
+#define ASUS_LED_REGISTER(asus, object, _name, max, method) \
do { \
struct led_classdev *ldev = &asus->leds.object; \
- if (!object##_set_handle) \
+ \
+ if (method && acpi_check_handle(asus->handle, method, NULL)) \
break ; \
\
INIT_WORK(&asus->leds.object##_work, object##_led_update); \
@@ -497,13 +527,14 @@ static int asus_led_init(struct asus_laptop *asus)
if (!asus->leds.workqueue)
return -ENOMEM;

- ASUS_LED_REGISTER(asus, mled, "mail", 1);
- ASUS_LED_REGISTER(asus, tled, "touchpad", 1);
- ASUS_LED_REGISTER(asus, rled, "record", 1);
- ASUS_LED_REGISTER(asus, pled, "phone", 1);
- ASUS_LED_REGISTER(asus, gled, "gaming", 1);
- if (kled_set_handle && kled_get_handle)
- ASUS_LED_REGISTER(asus, kled, "kbd_backlight", 3);
+ ASUS_LED_REGISTER(asus, mled, "mail", 1, METHOD_MLED);
+ ASUS_LED_REGISTER(asus, tled, "touchpad", 1, METHOD_TLED);
+ ASUS_LED_REGISTER(asus, rled, "record", 1, METHOD_RLED);
+ ASUS_LED_REGISTER(asus, pled, "phone", 1, METHOD_PLED);
+ ASUS_LED_REGISTER(asus, gled, "gaming", 1, METHOD_GLED);
+ if (!acpi_check_handle(asus->handle, METHOD_KBD_LIGHT_SET, NULL) &&
+ !acpi_check_handle(asus->handle, METHOD_KBD_LIGHT_GET, NULL))
+ ASUS_LED_REGISTER(asus, kled, "kbd_backlight", 3, NULL);
error:
if (rv)
asus_led_exit(asus);
@@ -557,10 +588,12 @@ static void lcd_blank(struct asus_laptop *asus, int blank)

static int asus_read_brightness(struct backlight_device *bd)
{
+ struct asus_laptop *asus = bl_get_data(bd);
unsigned long long value;
acpi_status rv = AE_OK;

- rv = acpi_evaluate_integer(brightness_get_handle, NULL, NULL, &value);
+ rv = acpi_evaluate_integer(asus->handle, METHOD_BRIGHTNESS_GET,
+ NULL, &value);
if (ACPI_FAILURE(rv))
pr_warning("Error reading brightness\n");

@@ -569,7 +602,9 @@ static int asus_read_brightness(struct backlight_device *bd)

static int asus_set_brightness(struct backlight_device *bd, int value)
{
- if (write_acpi_int(brightness_set_handle, NULL, value)) {
+ struct asus_laptop *asus = bl_get_data(bd);
+
+ if (write_acpi_int(asus->handle, METHOD_BRIGHTNESS_SET, value)) {
pr_warning("Error changing brightness\n");
return -EIO;
}
@@ -600,7 +635,9 @@ static int asus_backlight_init(struct asus_laptop *asus)
struct backlight_device *bd;
struct device *dev = &asus->platform_device->dev;

- if (brightness_set_handle && lcd_switch_handle) {
+ if (!acpi_check_handle(asus->handle, METHOD_BRIGHTNESS_GET, NULL) &&
+ !acpi_check_handle(asus->handle, METHOD_BRIGHTNESS_SET, NULL) &&
+ lcd_switch_handle) {
bd = backlight_device_register(ASUS_LAPTOP_FILE, dev,
asus, &asusbl_ops);
if (IS_ERR(bd)) {
@@ -612,8 +649,8 @@ static int asus_backlight_init(struct asus_laptop *asus)
asus->backlight_device = bd;

bd->props.max_brightness = 15;
- bd->props.brightness = asus_read_brightness(NULL);
bd->props.power = FB_BLANK_UNBLANK;
+ bd->props.brightness = asus_read_brightness(bd);
backlight_update_status(bd);
}
return 0;
@@ -716,7 +753,7 @@ static int parse_arg(const char *buf, unsigned long count, int *val)

static ssize_t sysfs_acpi_set(struct asus_laptop *asus,
const char *buf, size_t count,
- acpi_handle handle)
+ const char *method)
{
int rv, value;
int out = 0;
@@ -725,7 +762,7 @@ static ssize_t sysfs_acpi_set(struct asus_laptop *asus,
if (rv > 0)
out = value ? 1 : 0;

- if (write_acpi_int(handle, NULL, value))
+ if (write_acpi_int(asus->handle, method, value))
return -ENODEV;
return rv;
}
@@ -749,7 +786,7 @@ static ssize_t store_ledd(struct device *dev, struct device_attribute *attr,

rv = parse_arg(buf, count, &value);
if (rv > 0) {
- if (write_acpi_int(ledd_set_handle, NULL, value))
+ if (write_acpi_int(asus->handle, METHOD_LEDD, value))
pr_warning("LED display write failed\n");
else
asus->ledd_status = (u32) value;
@@ -768,7 +805,8 @@ static int asus_wireless_status(struct asus_laptop *asus, int mask)
if (!asus->have_rsts)
return (asus->wireless_status & mask) ? 1 : 0;

- rv = acpi_evaluate_integer(wireless_status_handle, NULL, NULL, &status);
+ rv = acpi_evaluate_integer(asus->handle, METHOD_WL_STATUS,
+ NULL, &status);
if (ACPI_FAILURE(rv)) {
pr_warning("Error reading Wireless status\n");
return -EINVAL;
@@ -792,7 +830,7 @@ static ssize_t store_wlan(struct device *dev, struct device_attribute *attr,
{
struct asus_laptop *asus = dev_get_drvdata(dev);

- return sysfs_acpi_set(asus, buf, count, wl_switch_handle);
+ return sysfs_acpi_set(asus, buf, count, METHOD_WLAN);
}

/*
@@ -812,7 +850,7 @@ static ssize_t store_bluetooth(struct device *dev,
{
struct asus_laptop *asus = dev_get_drvdata(dev);

- return sysfs_acpi_set(asus, buf, count, bt_switch_handle);
+ return sysfs_acpi_set(asus, buf, count, METHOD_BLUETOOTH);
}

/*
@@ -821,7 +859,7 @@ static ssize_t store_bluetooth(struct device *dev,
static void asus_set_display(struct asus_laptop *asus, int value)
{
/* no sanity check needed for now */
- if (write_acpi_int(display_set_handle, NULL, value))
+ if (write_acpi_int(asus->handle, METHOD_SWITCH_DISPLAY, value))
pr_warning("Error setting display\n");
return;
}
@@ -883,7 +921,7 @@ static ssize_t store_disp(struct device *dev, struct device_attribute *attr,
*/
static void asus_als_switch(struct asus_laptop *asus, int value)
{
- if (write_acpi_int(ls_switch_handle, NULL, value))
+ if (write_acpi_int(asus->handle, METHOD_ALS_CONTROL, value))
pr_warning("Error setting light sensor switch\n");
asus->light_switch = value;
}
@@ -911,7 +949,7 @@ static ssize_t store_lssw(struct device *dev, struct device_attribute *attr,

static void asus_als_level(struct asus_laptop *asus, int value)
{
- if (write_acpi_int(ls_level_handle, NULL, value))
+ if (write_acpi_int(asus->handle, METHOD_ALS_LEVEL, value))
pr_warning("Error setting light sensor level\n");
asus->light_level = value;
}
@@ -949,7 +987,8 @@ static int asus_gps_status(struct asus_laptop *asus)
unsigned long long status;
acpi_status rv = AE_OK;

- rv = acpi_evaluate_integer(gps_status_handle, NULL, NULL, &status);
+ rv = acpi_evaluate_integer(asus->handle, METHOD_GPS_STATUS,
+ NULL, &status);
if (ACPI_FAILURE(rv)) {
pr_warning("Error reading GPS status\n");
return -ENODEV;
@@ -959,9 +998,9 @@ static int asus_gps_status(struct asus_laptop *asus)

static int asus_gps_switch(struct asus_laptop *asus, int status)
{
- acpi_handle handle = status ? gps_on_handle : gps_off_handle;
+ const char *meth = status ? METHOD_GPS_ON : METHOD_GPS_OFF;

- if (write_acpi_int(handle, NULL, 0x02))
+ if (write_acpi_int(asus->handle, meth, 0x02))
return -ENODEV;
return 0;
}
@@ -1224,27 +1263,33 @@ static void asus_laptop_add_fs(struct asus_laptop *asus)
{
ASUS_SET_DEVICE_ATTR(infos, 0444, show_infos, NULL);

- if (wl_switch_handle)
+ if (!acpi_check_handle(asus->handle, METHOD_WLAN, NULL))
ASUS_SET_DEVICE_ATTR(wlan, 0644, show_wlan, store_wlan);

- if (bt_switch_handle)
+ if (!acpi_check_handle(asus->handle, METHOD_BLUETOOTH, NULL))
ASUS_SET_DEVICE_ATTR(bluetooth, 0644,
show_bluetooth, store_bluetooth);

- if (display_set_handle && display_get_handle)
- ASUS_SET_DEVICE_ATTR(display, 0644, show_disp, store_disp);
- else if (display_set_handle)
- ASUS_SET_DEVICE_ATTR(display, 0200, NULL, store_disp);
+ if (!acpi_check_handle(asus->handle, METHOD_SWITCH_DISPLAY, NULL)) {
+ if (display_get_handle)
+ ASUS_SET_DEVICE_ATTR(display, 0644, show_disp,
+ store_disp);
+ else
+ ASUS_SET_DEVICE_ATTR(display, 0200, NULL, store_disp);
+ }

- if (ledd_set_handle)
+ if (!acpi_check_handle(asus->handle, METHOD_LEDD, NULL))
ASUS_SET_DEVICE_ATTR(ledd, 0644, show_ledd, store_ledd);

- if (ls_switch_handle && ls_level_handle) {
+ if (!acpi_check_handle(asus->handle, METHOD_ALS_CONTROL, NULL) &&
+ !acpi_check_handle(asus->handle, METHOD_ALS_LEVEL, NULL)) {
ASUS_SET_DEVICE_ATTR(ls_level, 0644, show_lslvl, store_lslvl);
ASUS_SET_DEVICE_ATTR(ls_switch, 0644, show_lssw, store_lssw);
}

- if (gps_status_handle && gps_on_handle && gps_off_handle)
+ 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))
ASUS_SET_DEVICE_ATTR(gps, 0644, show_gps, store_gps);
}

@@ -1337,55 +1382,23 @@ static int asus_laptop_get_info(struct asus_laptop *asus)
if (*string)
pr_notice(" %s model detected\n", string);

- ASUS_HANDLE_INIT(mled_set);
- ASUS_HANDLE_INIT(tled_set);
- ASUS_HANDLE_INIT(rled_set);
- ASUS_HANDLE_INIT(pled_set);
- ASUS_HANDLE_INIT(gled_set);
-
- ASUS_HANDLE_INIT(ledd_set);
-
- ASUS_HANDLE_INIT(kled_set);
- ASUS_HANDLE_INIT(kled_get);
-
/*
* The HWRS method return informations about the hardware.
* 0x80 bit is for WLAN, 0x100 for Bluetooth.
* The significance of others is yet to be found.
- * If we don't find the method, we assume the device are present.
*/
status =
acpi_evaluate_integer(asus->handle, "HRWS", NULL, &hwrs_result);
- if (ACPI_FAILURE(status))
- hwrs_result = WL_HWRS | BT_HWRS;
+ if (!ACPI_FAILURE(status))
+ pr_notice(" HRWS returned %x", (int)hwrs_result);

- if (hwrs_result & WL_HWRS)
- ASUS_HANDLE_INIT(wl_switch);
- if (hwrs_result & BT_HWRS)
- ASUS_HANDLE_INIT(bt_switch);
-
- if (!ASUS_HANDLE_INIT(wireless_status))
+ if (!acpi_check_handle(asus->handle, METHOD_WL_STATUS, NULL))
asus->have_rsts = true;

- ASUS_HANDLE_INIT(brightness_set);
- ASUS_HANDLE_INIT(brightness_get);
-
+ /* Scheduled for removal */
ASUS_HANDLE_INIT(lcd_switch);
-
- ASUS_HANDLE_INIT(display_set);
ASUS_HANDLE_INIT(display_get);

- /*
- * There is a lot of models with "ALSL", but a few get
- * a real light sens, so we need to check it.
- */
- if (!ASUS_HANDLE_INIT(ls_switch))
- ASUS_HANDLE_INIT(ls_level);
-
- ASUS_HANDLE_INIT(gps_on);
- ASUS_HANDLE_INIT(gps_off);
- ASUS_HANDLE_INIT(gps_status);
-
kfree(model);

return AE_OK;
@@ -1413,12 +1426,14 @@ static int __devinit asus_acpi_init(struct asus_laptop *asus)

/* WLED and BLED are on by default */
if (bluetooth_status >= 0)
- write_acpi_int(bt_switch_handle, NULL, !!bluetooth_status);
+ write_acpi_int(asus->handle, METHOD_BLUETOOTH,
+ !!bluetooth_status);
if (wireless_status >= 0)
- write_acpi_int(wl_switch_handle, NULL, !!wireless_status);
+ write_acpi_int(asus->handle, METHOD_WLAN,
+ !!wireless_status);

/* Keyboard Backlight is on by default */
- if (kled_set_handle)
+ if (!acpi_check_handle(asus->handle, METHOD_KBD_LIGHT_SET, NULL))
asus_kled_set(asus, 1);

/* LED display is off by default */
@@ -1428,14 +1443,17 @@ static int __devinit asus_acpi_init(struct asus_laptop *asus)
asus->light_switch = 0; /* Default to light sensor disabled */
asus->light_level = 5; /* level 5 for sensor sensitivity */

- if (ls_switch_handle)
+ if (!acpi_check_handle(asus->handle, METHOD_ALS_CONTROL, NULL) &&
+ !acpi_check_handle(asus->handle, METHOD_ALS_LEVEL, NULL)) {
asus_als_switch(asus, asus->light_switch);
-
- if (ls_level_handle)
asus_als_level(asus, asus->light_level);
+ }

/* GPS is on by default */
- asus_gps_switch(asus, 1);
+ 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))
+ asus_gps_switch(asus, 1);
return result;
}

--
1.6.6.1

2010-02-02 07:56:31

by Corentin Chary

[permalink] [raw]
Subject: [PATCH 15/28] asus-laptop: removing read_status/store_status/write_status and asus->status

Signed-off-by: Corentin Chary <[email protected]>
---
drivers/platform/x86/asus-laptop.c | 81 +++++++++++-------------------------
1 files changed, 24 insertions(+), 57 deletions(-)

diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c
index d726db3..2349e88 100644
--- a/drivers/platform/x86/asus-laptop.c
+++ b/drivers/platform/x86/asus-laptop.c
@@ -107,16 +107,8 @@ MODULE_PARM_DESC(bluetooth_status, "Set the wireless status on boot "
* Flags for hotk status
* WL_ON and BT_ON are also used for wireless_status()
*/
-#define WL_ON 0x01 /* internal Wifi */
-#define BT_ON 0x02 /* internal Bluetooth */
-#define MLED_ON 0x04 /* mail LED */
-#define TLED_ON 0x08 /* touchpad LED */
-#define RLED_ON 0x10 /* Record LED */
-#define PLED_ON 0x20 /* Phone LED */
-#define GLED_ON 0x40 /* Gaming LED */
-#define LCD_ON 0x80 /* LCD backlight */
-#define GPS_ON 0x100 /* GPS */
-#define KEY_ON 0x200 /* Keyboard backlight */
+#define WL_RSTS 0x01 /* internal Wifi */
+#define BT_RSTS 0x02 /* internal Bluetooth */

#define ASUS_HANDLE(object, paths...) \
static acpi_handle object##_handle = NULL; \
@@ -244,7 +236,6 @@ struct asus_laptop {
int lcd_state;

acpi_handle handle; /* the handle of the hotk device */
- char status; /* status of the hotk, for LEDs, ... */
u32 ledd_status; /* status of the LED display */
u8 light_level; /* light sensor level */
u8 light_switch; /* light sensor switch value */
@@ -332,35 +323,18 @@ static int write_acpi_int(acpi_handle handle, const char *method, int val)
return write_acpi_int_ret(handle, method, val, NULL);
}

-/* Generic LED functions */
-static int read_status(struct asus_laptop *asus, int mask)
+/* Generic LED function */
+static void asus_led_set(struct asus_laptop *asus, acpi_handle handle,
+ int value)
{
- return (asus->status & mask) ? 1 : 0;
-}
-
-static void write_status(struct asus_laptop *asus, acpi_handle handle,
- int out, int mask)
-{
- asus->status = (out) ? (asus->status | mask) : (asus->status & ~mask);
-
- switch (mask) {
- case MLED_ON:
- out = !(out & 0x1);
- break;
- case GLED_ON:
- out = (out & 0x1) + 1;
- break;
- case GPS_ON:
- handle = (out) ? gps_on_handle : gps_off_handle;
- out = 0x02;
- break;
- default:
- out &= 0x1;
- break;
- }
+ if (handle == mled_set_handle)
+ value = !value;
+ else if (handle == gled_set_handle)
+ value = !value + 1;
+ else
+ value = !!value;

- if (write_acpi_int(handle, NULL, out))
- pr_warning(" write failed %x\n", mask);
+ write_acpi_int(handle, NULL, value);
}

/*
@@ -403,7 +377,7 @@ ASUS_LED(kled, "kbd_backlight", 3);
struct asus_laptop *asus = work_to_asus(work, object); \
\
int value = asus->leds.object##_wk; \
- write_status(asus, object##_set_handle, value, (mask)); \
+ asus_led_set(asus, object##_set_handle, value); \
} \
static enum led_brightness object##_led_get( \
struct led_classdev *led_cdev) \
@@ -740,9 +714,9 @@ static int parse_arg(const char *buf, unsigned long count, int *val)
return count;
}

-static ssize_t store_status(struct asus_laptop *asus,
- const char *buf, size_t count,
- acpi_handle handle, int mask)
+static ssize_t sysfs_acpi_set(struct asus_laptop *asus,
+ const char *buf, size_t count,
+ acpi_handle handle)
{
int rv, value;
int out = 0;
@@ -751,8 +725,8 @@ static ssize_t store_status(struct asus_laptop *asus,
if (rv > 0)
out = value ? 1 : 0;

- write_status(asus, handle, out, mask);
-
+ if (write_acpi_int(handle, NULL, value))
+ return -ENODEV;
return rv;
}

@@ -810,7 +784,7 @@ static ssize_t show_wlan(struct device *dev,
{
struct asus_laptop *asus = dev_get_drvdata(dev);

- return sprintf(buf, "%d\n", asus_wireless_status(asus, WL_ON));
+ return sprintf(buf, "%d\n", asus_wireless_status(asus, WL_RSTS));
}

static ssize_t store_wlan(struct device *dev, struct device_attribute *attr,
@@ -818,7 +792,7 @@ static ssize_t store_wlan(struct device *dev, struct device_attribute *attr,
{
struct asus_laptop *asus = dev_get_drvdata(dev);

- return store_status(asus, buf, count, wl_switch_handle, WL_ON);
+ return sysfs_acpi_set(asus, buf, count, wl_switch_handle);
}

/*
@@ -829,7 +803,7 @@ static ssize_t show_bluetooth(struct device *dev,
{
struct asus_laptop *asus = dev_get_drvdata(dev);

- return sprintf(buf, "%d\n", asus_wireless_status(asus, BT_ON));
+ return sprintf(buf, "%d\n", asus_wireless_status(asus, BT_RSTS));
}

static ssize_t store_bluetooth(struct device *dev,
@@ -838,7 +812,7 @@ static ssize_t store_bluetooth(struct device *dev,
{
struct asus_laptop *asus = dev_get_drvdata(dev);

- return store_status(asus, buf, count, bt_switch_handle, BT_ON);
+ return sysfs_acpi_set(asus, buf, count, bt_switch_handle);
}

/*
@@ -1439,16 +1413,9 @@ static int __devinit asus_acpi_init(struct asus_laptop *asus)

/* WLED and BLED are on by default */
if (bluetooth_status >= 0)
- write_status(asus, bt_switch_handle, !!bluetooth_status, BT_ON);
+ write_acpi_int(bt_switch_handle, NULL, !!bluetooth_status);
if (wireless_status >= 0)
- write_status(asus, wl_switch_handle, !!wireless_status, WL_ON);
-
- /* If the h/w switch is off, we need to check the real status */
- write_status(asus, NULL, asus_wireless_status(asus, BT_ON), BT_ON);
- write_status(asus, NULL, asus_wireless_status(asus, WL_ON), WL_ON);
-
- /* LCD Backlight is on by default */
- write_status(asus, NULL, 1, LCD_ON);
+ write_acpi_int(wl_switch_handle, NULL, !!wireless_status);

/* Keyboard Backlight is on by default */
if (kled_set_handle)
--
1.6.6.1

2010-02-02 07:55:36

by Corentin Chary

[permalink] [raw]
Subject: [PATCH 10/28] asus-laptop: callbacks should use "driver data" parameter or field

(Changelog stolen from Alan's patch for eeepc-laptop, but this patch
does the same thing for asus-laptop)

Callback methods should not refer to a variable like "asus" (formally
"hotk"). Instead, they should extract the data they need either from
a "driver data" parameter, or the "driver data" field of the object
which they operate on. The "asus" variable can then be removed.

In practice, drivers under "drivers/platform" can get away without using
driver data, because it doesn't make sense to have more than one
instance of them. However this makes it harder to review them for
correctness. This is especially true for core ACPI developers who have
not previously been exposed to this anti-pattern :-).

This will serve as an example of best practice for new driver writers
(whether they find it themselves, or have it pointed out during review
:-).

Signed-off-by: Corentin Chary <[email protected]>
---
drivers/platform/x86/asus-laptop.c | 362 +++++++++++++++++++++---------------
1 files changed, 209 insertions(+), 153 deletions(-)

diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c
index 4ff30ca..58a4864 100644
--- a/drivers/platform/x86/asus-laptop.c
+++ b/drivers/platform/x86/asus-laptop.c
@@ -196,6 +196,34 @@ ASUS_HANDLE(kled_set, ASUS_LAPTOP_PREFIX "SLKB");
ASUS_HANDLE(kled_get, ASUS_LAPTOP_PREFIX "GLKB");

/*
+ * Define a specific led structure to keep the main structure clean
+ */
+#define ASUS_DEFINE_LED(object) \
+ int object##_wk; \
+ struct work_struct object##_work; \
+ struct led_classdev object;
+
+
+#define led_to_asus(led_cdev, led) \
+ container_of(container_of(led_cdev, struct asus_laptop_leds, \
+ led), \
+ struct asus_laptop, leds)
+#define work_to_asus(work, led) \
+ container_of(container_of(work, struct asus_laptop_leds, \
+ led##_work), \
+ struct asus_laptop, leds)
+
+struct asus_laptop_leds {
+ ASUS_DEFINE_LED(mled)
+ ASUS_DEFINE_LED(tled)
+ ASUS_DEFINE_LED(rled)
+ ASUS_DEFINE_LED(pled)
+ ASUS_DEFINE_LED(gled)
+ ASUS_DEFINE_LED(kled)
+ struct workqueue_struct *workqueue;
+};
+
+/*
* This is the main structure, we can use it to store anything interesting
* about the hotk device
*/
@@ -206,7 +234,11 @@ struct asus_laptop {
struct platform_device *platform_device;
struct acpi_device *device; /* the device we are in */
struct backlight_device *backlight_device;
+
struct input_dev *inputdev;
+ struct key_entry *keymap;
+
+ struct asus_laptop_leds leds;

acpi_handle handle; /* the handle of the hotk device */
char status; /* status of the hotk, for LEDs, ... */
@@ -217,10 +249,6 @@ struct asus_laptop {
u16 *keycode_map;
};

-static struct asus_laptop *asus;
-
-static struct workqueue_struct *led_workqueue;
-
/*
* The backlight class declaration
*/
@@ -237,8 +265,6 @@ static struct backlight_ops asusbl_ops = {
static enum led_brightness object##_led_get( \
struct led_classdev *led_cdev); \
static void object##_led_update(struct work_struct *ignored); \
- static int object##_led_wk; \
- static DECLARE_WORK(object##_led_work, object##_led_update); \
static struct led_classdev object##_led = { \
.name = "asus::" ledname, \
.brightness_set = object##_led_set, \
@@ -261,7 +287,7 @@ struct key_entry {

enum { KE_KEY, KE_END };

-static struct key_entry asus_keymap[] = {
+static const struct key_entry asus_keymap[] = {
{KE_KEY, 0x02, KEY_SCREENLOCK},
{KE_KEY, 0x05, KEY_WLAN},
{KE_KEY, 0x08, KEY_F13},
@@ -333,7 +359,7 @@ static int write_acpi_int(acpi_handle handle, const char *method, int val)
return write_acpi_int_ret(handle, method, val, NULL);
}

-static int read_wireless_status(int mask)
+static int read_wireless_status(struct asus_laptop *asus, int mask)
{
unsigned long long status;
acpi_status rv = AE_OK;
@@ -350,7 +376,7 @@ static int read_wireless_status(int mask)
return (asus->status & mask) ? 1 : 0;
}

-static int read_gps_status(void)
+static int read_gps_status(struct asus_laptop *asus)
{
unsigned long long status;
acpi_status rv = AE_OK;
@@ -365,18 +391,19 @@ static int read_gps_status(void)
}

/* Generic LED functions */
-static int read_status(int mask)
+static int read_status(struct asus_laptop *asus, int mask)
{
/* There is a special method for both wireless devices */
if (mask == BT_ON || mask == WL_ON)
- return read_wireless_status(mask);
+ return read_wireless_status(asus, mask);
else if (mask == GPS_ON)
- return read_gps_status();
+ return read_gps_status(asus);

return (asus->status & mask) ? 1 : 0;
}

-static void write_status(acpi_handle handle, int out, int mask)
+static void write_status(struct asus_laptop *asus, acpi_handle handle,
+ int out, int mask)
{
asus->status = (out) ? (asus->status | mask) : (asus->status & ~mask);

@@ -405,13 +432,19 @@ static void write_status(acpi_handle handle, int out, int mask)
static void object##_led_set(struct led_classdev *led_cdev, \
enum led_brightness value) \
{ \
- object##_led_wk = (value > 0) ? 1 : 0; \
- queue_work(led_workqueue, &object##_led_work); \
+ struct asus_laptop *asus = \
+ led_to_asus(led_cdev, object); \
+ \
+ asus->leds.object##_wk = (value > 0) ? 1 : 0; \
+ queue_work(asus->leds.workqueue, \
+ &asus->leds.object##_work); \
} \
- static void object##_led_update(struct work_struct *ignored) \
+ static void object##_led_update(struct work_struct *work) \
{ \
- int value = object##_led_wk; \
- write_status(object##_set_handle, value, (mask)); \
+ struct asus_laptop *asus = work_to_asus(work, object); \
+ \
+ int value = asus->leds.object##_wk; \
+ write_status(asus, object##_set_handle, value, (mask)); \
} \
static enum led_brightness object##_led_get( \
struct led_classdev *led_cdev) \
@@ -448,7 +481,7 @@ static int get_kled_lvl(void)
return kblv;
}

-static int set_kled_lvl(int kblv)
+static int set_kled_lvl(struct asus_laptop *asus, int kblv)
{
if (kblv > 0)
kblv = (1 << 7) | (kblv & 0x7F);
@@ -465,13 +498,17 @@ static int set_kled_lvl(int kblv)
static void kled_led_set(struct led_classdev *led_cdev,
enum led_brightness value)
{
- kled_led_wk = value;
- queue_work(led_workqueue, &kled_led_work);
+ struct asus_laptop *asus = led_to_asus(led_cdev, kled);
+
+ asus->leds.kled_wk = value;
+ queue_work(asus->leds.workqueue, &asus->leds.kled_work);
}

-static void kled_led_update(struct work_struct *ignored)
+static void kled_led_update(struct work_struct *work)
{
- set_kled_lvl(kled_led_wk);
+ struct asus_laptop *asus = work_to_asus(work, kled);
+
+ set_kled_lvl(asus, asus->leds.kled_wk);
}

static enum led_brightness kled_led_get(struct led_classdev *led_cdev)
@@ -479,19 +516,19 @@ static enum led_brightness kled_led_get(struct led_classdev *led_cdev)
return get_kled_lvl();
}

-static int get_lcd_state(void)
+static int get_lcd_state(struct asus_laptop *asus)
{
- return read_status(LCD_ON);
+ return read_status(asus, LCD_ON);
}

-static int set_lcd_state(int value)
+static int set_lcd_state(struct asus_laptop *asus, int value)
{
int lcd = 0;
acpi_status status = 0;

lcd = value ? 1 : 0;

- if (lcd == get_lcd_state())
+ if (lcd == get_lcd_state(asus))
return 0;

if (lcd_switch_handle) {
@@ -502,11 +539,11 @@ static int set_lcd_state(int value)
pr_warning("Error switching LCD\n");
}

- write_status(NULL, lcd, LCD_ON);
+ write_status(asus, NULL, lcd, LCD_ON);
return 0;
}

-static void lcd_blank(int blank)
+static void lcd_blank(struct asus_laptop *asus, int blank)
{
struct backlight_device *bd = asus->backlight_device;

@@ -539,6 +576,7 @@ static int set_brightness(struct backlight_device *bd, int value)

static int update_bl_status(struct backlight_device *bd)
{
+ struct asus_laptop *asus = bl_get_data(bd);
int rv;
int value = bd->props.brightness;

@@ -547,7 +585,7 @@ static int update_bl_status(struct backlight_device *bd)
return rv;

value = (bd->props.power == FB_BLANK_UNBLANK) ? 1 : 0;
- return set_lcd_state(value);
+ return set_lcd_state(asus, value);
}

/*
@@ -562,6 +600,7 @@ static int update_bl_status(struct backlight_device *bd)
static ssize_t show_infos(struct device *dev,
struct device_attribute *attr, char *page)
{
+ struct asus_laptop *asus = dev_get_drvdata(dev);
int len = 0;
unsigned long long temp;
char buf[16]; /* enough for all info */
@@ -638,7 +677,8 @@ static int parse_arg(const char *buf, unsigned long count, int *val)
return count;
}

-static ssize_t store_status(const char *buf, size_t count,
+static ssize_t store_status(struct asus_laptop *asus,
+ const char *buf, size_t count,
acpi_handle handle, int mask)
{
int rv, value;
@@ -648,7 +688,7 @@ static ssize_t store_status(const char *buf, size_t count,
if (rv > 0)
out = value ? 1 : 0;

- write_status(handle, out, mask);
+ write_status(asus, handle, out, mask);

return rv;
}
@@ -659,12 +699,15 @@ static ssize_t store_status(const char *buf, size_t count,
static ssize_t show_ledd(struct device *dev,
struct device_attribute *attr, char *buf)
{
+ struct asus_laptop *asus = dev_get_drvdata(dev);
+
return sprintf(buf, "0x%08x\n", asus->ledd_status);
}

static ssize_t store_ledd(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
+ struct asus_laptop *asus = dev_get_drvdata(dev);
int rv, value;

rv = parse_arg(buf, count, &value);
@@ -683,13 +726,17 @@ static ssize_t store_ledd(struct device *dev, struct device_attribute *attr,
static ssize_t show_wlan(struct device *dev,
struct device_attribute *attr, char *buf)
{
- return sprintf(buf, "%d\n", read_status(WL_ON));
+ struct asus_laptop *asus = dev_get_drvdata(dev);
+
+ return sprintf(buf, "%d\n", read_status(asus, WL_ON));
}

static ssize_t store_wlan(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
- return store_status(buf, count, wl_switch_handle, WL_ON);
+ struct asus_laptop *asus = dev_get_drvdata(dev);
+
+ return store_status(asus, buf, count, wl_switch_handle, WL_ON);
}

/*
@@ -698,20 +745,24 @@ static ssize_t store_wlan(struct device *dev, struct device_attribute *attr,
static ssize_t show_bluetooth(struct device *dev,
struct device_attribute *attr, char *buf)
{
- return sprintf(buf, "%d\n", read_status(BT_ON));
+ struct asus_laptop *asus = dev_get_drvdata(dev);
+
+ return sprintf(buf, "%d\n", read_status(asus, BT_ON));
}

static ssize_t store_bluetooth(struct device *dev,
struct device_attribute *attr, const char *buf,
size_t count)
{
- return store_status(buf, count, bt_switch_handle, BT_ON);
+ struct asus_laptop *asus = dev_get_drvdata(dev);
+
+ return store_status(asus, buf, count, bt_switch_handle, BT_ON);
}

/*
* Display
*/
-static void set_display(int value)
+static void set_display(struct asus_laptop *asus, int value)
{
/* no sanity check needed for now */
if (write_acpi_int(display_set_handle, NULL, value))
@@ -719,7 +770,7 @@ static void set_display(int value)
return;
}

-static int read_display(void)
+static int read_display(struct asus_laptop *asus)
{
unsigned long long value = 0;
acpi_status rv = AE_OK;
@@ -747,7 +798,9 @@ static int read_display(void)
static ssize_t show_disp(struct device *dev,
struct device_attribute *attr, char *buf)
{
- return sprintf(buf, "%d\n", read_display());
+ struct asus_laptop *asus = dev_get_drvdata(dev);
+
+ return sprintf(buf, "%d\n", read_display(asus));
}

/*
@@ -760,18 +813,19 @@ static ssize_t show_disp(struct device *dev,
static ssize_t store_disp(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
+ struct asus_laptop *asus = dev_get_drvdata(dev);
int rv, value;

rv = parse_arg(buf, count, &value);
if (rv > 0)
- set_display(value);
+ set_display(asus, value);
return rv;
}

/*
* Light Sens
*/
-static void set_light_sens_switch(int value)
+static void set_light_sens_switch(struct asus_laptop *asus, int value)
{
if (write_acpi_int(ls_switch_handle, NULL, value))
pr_warning("Error setting light sensor switch\n");
@@ -781,22 +835,25 @@ static void set_light_sens_switch(int value)
static ssize_t show_lssw(struct device *dev,
struct device_attribute *attr, char *buf)
{
+ struct asus_laptop *asus = dev_get_drvdata(dev);
+
return sprintf(buf, "%d\n", asus->light_switch);
}

static ssize_t store_lssw(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
+ struct asus_laptop *asus = dev_get_drvdata(dev);
int rv, value;

rv = parse_arg(buf, count, &value);
if (rv > 0)
- set_light_sens_switch(value ? 1 : 0);
+ set_light_sens_switch(asus, value ? 1 : 0);

return rv;
}

-static void set_light_sens_level(int value)
+static void set_light_sens_level(struct asus_laptop *asus, int value)
{
if (write_acpi_int(ls_level_handle, NULL, value))
pr_warning("Error setting light sensor level\n");
@@ -806,19 +863,22 @@ static void set_light_sens_level(int value)
static ssize_t show_lslvl(struct device *dev,
struct device_attribute *attr, char *buf)
{
+ struct asus_laptop *asus = dev_get_drvdata(dev);
+
return sprintf(buf, "%d\n", asus->light_level);
}

static ssize_t store_lslvl(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
+ struct asus_laptop *asus = dev_get_drvdata(dev);
int rv, value;

rv = parse_arg(buf, count, &value);
if (rv > 0) {
value = (0 < value) ? ((15 < value) ? 15 : value) : 0;
/* 0 <= value <= 15 */
- set_light_sens_level(value);
+ set_light_sens_level(asus, value);
}

return rv;
@@ -830,34 +890,40 @@ static ssize_t store_lslvl(struct device *dev, struct device_attribute *attr,
static ssize_t show_gps(struct device *dev,
struct device_attribute *attr, char *buf)
{
- return sprintf(buf, "%d\n", read_status(GPS_ON));
+ struct asus_laptop *asus = dev_get_drvdata(dev);
+
+ return sprintf(buf, "%d\n", read_status(asus, GPS_ON));
}

static ssize_t store_gps(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
- return store_status(buf, count, NULL, GPS_ON);
+ struct asus_laptop *asus = dev_get_drvdata(dev);
+
+ return store_status(asus, buf, count, NULL, GPS_ON);
}

/*
* Hotkey functions
*/
-static struct key_entry *asus_get_entry_by_scancode(int code)
+static struct key_entry *asus_get_entry_by_scancode(struct asus_laptop *asus,
+ int code)
{
struct key_entry *key;

- for (key = asus_keymap; key->type != KE_END; key++)
+ for (key = asus->keymap; key->type != KE_END; key++)
if (code == key->code)
return key;

return NULL;
}

-static struct key_entry *asus_get_entry_by_keycode(int code)
+static struct key_entry *asus_get_entry_by_keycode(struct asus_laptop *asus,
+ int code)
{
struct key_entry *key;

- for (key = asus_keymap; key->type != KE_END; key++)
+ for (key = asus->keymap; key->type != KE_END; key++)
if (code == key->keycode && key->type == KE_KEY)
return key;

@@ -866,7 +932,8 @@ static struct key_entry *asus_get_entry_by_keycode(int code)

static int asus_getkeycode(struct input_dev *dev, int scancode, int *keycode)
{
- struct key_entry *key = asus_get_entry_by_scancode(scancode);
+ struct asus_laptop *asus = input_get_drvdata(dev);
+ struct key_entry *key = asus_get_entry_by_scancode(asus, scancode);

if (key && key->type == KE_KEY) {
*keycode = key->keycode;
@@ -878,18 +945,19 @@ static int asus_getkeycode(struct input_dev *dev, int scancode, int *keycode)

static int asus_setkeycode(struct input_dev *dev, int scancode, int keycode)
{
+ struct asus_laptop *asus = input_get_drvdata(dev);
struct key_entry *key;
int old_keycode;

if (keycode < 0 || keycode > KEY_MAX)
return -EINVAL;

- key = asus_get_entry_by_scancode(scancode);
+ key = asus_get_entry_by_scancode(asus, scancode);
if (key && key->type == KE_KEY) {
old_keycode = key->keycode;
key->keycode = keycode;
set_bit(keycode, dev->keybit);
- if (!asus_get_entry_by_keycode(old_keycode))
+ if (!asus_get_entry_by_keycode(asus, old_keycode))
clear_bit(old_keycode, dev->keybit);
return 0;
}
@@ -899,6 +967,7 @@ static int asus_setkeycode(struct input_dev *dev, int scancode, int keycode)

static void asus_acpi_notify(struct acpi_device *device, u32 event)
{
+ struct asus_laptop *asus = acpi_driver_data(device);
static struct key_entry *key;
u16 count;

@@ -907,11 +976,11 @@ static void asus_acpi_notify(struct acpi_device *device, u32 event)
* switched
*/
if (event == ATKD_LCD_ON) {
- write_status(NULL, 1, LCD_ON);
- lcd_blank(FB_BLANK_UNBLANK);
+ write_status(asus, NULL, 1, LCD_ON);
+ lcd_blank(asus, FB_BLANK_UNBLANK);
} else if (event == ATKD_LCD_OFF) {
- write_status(NULL, 0, LCD_ON);
- lcd_blank(FB_BLANK_POWERDOWN);
+ write_status(asus, NULL, 0, LCD_ON);
+ lcd_blank(asus, FB_BLANK_POWERDOWN);
}

/* TODO Find a better way to handle events count. */
@@ -922,7 +991,7 @@ static void asus_acpi_notify(struct acpi_device *device, u32 event)
count);

if (asus->inputdev) {
- key = asus_get_entry_by_scancode(event);
+ key = asus_get_entry_by_scancode(asus, event);
if (!key)
return ;

@@ -978,13 +1047,14 @@ static struct attribute_group platform_attribute_group = {
.attrs = asuspf_attributes
};

-static int asus_platform_init(void)
+static int asus_platform_init(struct asus_laptop *asus)
{
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);

result = platform_device_add(asus->platform_device);
if (result)
@@ -1003,7 +1073,7 @@ fail_platform_device:
return result;
}

-static void asus_platform_exit(void)
+static void asus_platform_exit(struct asus_laptop *asus)
{
sysfs_remove_group(&asus->platform_device->dev.kobj,
&platform_attribute_group);
@@ -1012,12 +1082,12 @@ static void asus_platform_exit(void)

static struct platform_driver platform_driver = {
.driver = {
- .name = ASUS_LAPTOP_FILE,
- .owner = THIS_MODULE,
- }
+ .name = ASUS_LAPTOP_FILE,
+ .owner = THIS_MODULE,
+ }
};

-static void asus_laptop_add_fs(void)
+static void asus_laptop_add_fs(struct asus_laptop *asus)
{
ASUS_SET_DEVICE_ATTR(infos, 0444, show_infos, NULL);

@@ -1187,7 +1257,7 @@ static int asus_laptop_get_info(struct asus_laptop *asus)
return AE_OK;
}

-static int asus_input_init(struct device *dev)
+static int asus_input_init(struct asus_laptop *asus)
{
const struct key_entry *key;
int result;
@@ -1198,13 +1268,16 @@ static int asus_input_init(struct device *dev)
return 0;
}
asus->inputdev->name = "Asus Laptop extra buttons";
- asus->inputdev->dev.parent = dev;
+ asus->inputdev->dev.parent = &asus->platform_device->dev;
asus->inputdev->phys = ASUS_LAPTOP_FILE "/input0";
asus->inputdev->id.bustype = BUS_HOST;
asus->inputdev->getkeycode = asus_getkeycode;
asus->inputdev->setkeycode = asus_setkeycode;
+ input_set_drvdata(asus->inputdev, asus);

- for (key = asus_keymap; key->type != KE_END; key++) {
+ asus->keymap = kmemdup(asus_keymap, sizeof(asus_keymap),
+ GFP_KERNEL);
+ for (key = asus->keymap; key->type != KE_END; key++) {
switch (key->type) {
case KE_KEY:
set_bit(EV_KEY, asus->inputdev->evbit);
@@ -1220,40 +1293,44 @@ static int asus_input_init(struct device *dev)
return result;
}

-static void asus_backlight_exit(void)
+static void asus_backlight_exit(struct asus_laptop *asus)
{
if (asus->backlight_device)
backlight_device_unregister(asus->backlight_device);
}

-#define ASUS_LED_UNREGISTER(object) \
+#define ASUS_LED_UNREGISTER(object) \
if (object##_led.dev) \
led_classdev_unregister(&object##_led)

-static void asus_led_exit(void)
+static void asus_led_exit(struct asus_laptop *asus)
{
- destroy_workqueue(led_workqueue);
ASUS_LED_UNREGISTER(mled);
ASUS_LED_UNREGISTER(tled);
ASUS_LED_UNREGISTER(pled);
ASUS_LED_UNREGISTER(rled);
ASUS_LED_UNREGISTER(gled);
ASUS_LED_UNREGISTER(kled);
+ if (asus->leds.workqueue) {
+ destroy_workqueue(asus->leds.workqueue);
+ asus->leds.workqueue = NULL;
+ }
}

-static void asus_input_exit(void)
+static void asus_input_exit(struct asus_laptop *asus)
{
if (asus->inputdev)
input_unregister_device(asus->inputdev);
}

-static int asus_backlight_init(struct device *dev)
+static int asus_backlight_init(struct asus_laptop *asus)
{
struct backlight_device *bd;
+ struct device *dev = &asus->platform_device->dev;

if (brightness_set_handle && lcd_switch_handle) {
bd = backlight_device_register(ASUS_LAPTOP_FILE, dev,
- NULL, &asusbl_ops);
+ asus, &asusbl_ops);
if (IS_ERR(bd)) {
pr_err("Could not register asus backlight device\n");
asus->backlight_device = NULL;
@@ -1270,79 +1347,55 @@ static int asus_backlight_init(struct device *dev)
return 0;
}

-static int asus_led_register(acpi_handle handle,
- struct led_classdev *ldev, struct device *dev)
-{
- if (!handle)
- return 0;
-
- return led_classdev_register(dev, ldev);
-}
-
-#define ASUS_LED_REGISTER(object, device) \
- asus_led_register(object##_set_handle, &object##_led, device)
-
-static int asus_led_init(struct device *dev)
+/*
+ * Ugly macro, need to fix that later
+ */
+#define ASUS_LED_REGISTER(asus, object, _name, max) \
+ do { \
+ struct led_classdev *ldev = &asus->leds.object; \
+ if (!object##_set_handle) \
+ break ; \
+ \
+ INIT_WORK(&asus->leds.object##_work, object##_led_update); \
+ ldev->name = "asus::" _name; \
+ ldev->brightness_set = object##_led_set; \
+ ldev->max_brightness = max; \
+ rv = led_classdev_register(&asus->platform_device->dev, ldev); \
+ if (rv) \
+ goto error; \
+ } while (0)
+
+static int asus_led_init(struct asus_laptop *asus)
{
int rv;

- rv = ASUS_LED_REGISTER(mled, dev);
- if (rv)
- goto out;
-
- rv = ASUS_LED_REGISTER(tled, dev);
- if (rv)
- goto out1;
-
- rv = ASUS_LED_REGISTER(rled, dev);
- if (rv)
- goto out2;
-
- rv = ASUS_LED_REGISTER(pled, dev);
- if (rv)
- goto out3;
-
- rv = ASUS_LED_REGISTER(gled, dev);
- if (rv)
- goto out4;
-
- if (kled_set_handle && kled_get_handle)
- rv = ASUS_LED_REGISTER(kled, dev);
- if (rv)
- goto out5;
-
/*
* Functions that actually update the LED's are called from a
* workqueue. By doing this as separate work rather than when the LED
* subsystem asks, we avoid messing with the Asus ACPI stuff during a
* potentially bad time, such as a timer interrupt.
*/
- led_workqueue = create_singlethread_workqueue("led_workqueue");
- if (!led_workqueue)
- goto out6;
+ asus->leds.workqueue = create_singlethread_workqueue("led_workqueue");
+ if (!asus->leds.workqueue)
+ return -ENOMEM;

- return 0;
-out6:
- rv = -ENOMEM;
- ASUS_LED_UNREGISTER(kled);
-out5:
- ASUS_LED_UNREGISTER(gled);
-out4:
- ASUS_LED_UNREGISTER(pled);
-out3:
- ASUS_LED_UNREGISTER(rled);
-out2:
- ASUS_LED_UNREGISTER(tled);
-out1:
- ASUS_LED_UNREGISTER(mled);
-out:
+ ASUS_LED_REGISTER(asus, mled, "mail", 1);
+ ASUS_LED_REGISTER(asus, tled, "touchpad", 1);
+ ASUS_LED_REGISTER(asus, rled, "record", 1);
+ ASUS_LED_REGISTER(asus, pled, "phone", 1);
+ ASUS_LED_REGISTER(asus, gled, "gaming", 1);
+ if (kled_set_handle && kled_get_handle)
+ ASUS_LED_REGISTER(asus, kled, "kbd_backlight", 3);
+error:
+ if (rv)
+ asus_led_exit(asus);
return rv;
}


static bool asus_device_present;

-static int __devinit asus_acpi_init(struct acpi_device *device)
+static int __devinit asus_acpi_init(struct asus_laptop *asus)
{
int result = 0;

@@ -1358,22 +1411,22 @@ static int __devinit asus_acpi_init(struct acpi_device *device)
if (result)
return result;

- asus_laptop_add_fs();
+ asus_laptop_add_fs(asus);

/* WLED and BLED are on by default */
- write_status(bt_switch_handle, 1, BT_ON);
- write_status(wl_switch_handle, 1, WL_ON);
+ write_status(asus, bt_switch_handle, 1, BT_ON);
+ write_status(asus, wl_switch_handle, 1, WL_ON);

/* If the h/w switch is off, we need to check the real status */
- write_status(NULL, read_status(BT_ON), BT_ON);
- write_status(NULL, read_status(WL_ON), WL_ON);
+ write_status(asus, NULL, read_status(asus, BT_ON), BT_ON);
+ write_status(asus, NULL, read_status(asus, WL_ON), WL_ON);

/* LCD Backlight is on by default */
- write_status(NULL, 1, LCD_ON);
+ write_status(asus, NULL, 1, LCD_ON);

/* Keyboard Backlight is on by default */
if (kled_set_handle)
- set_kled_lvl(1);
+ set_kled_lvl(asus, 1);

/* LED display is off by default */
asus->ledd_status = 0xFFF;
@@ -1383,18 +1436,19 @@ static int __devinit asus_acpi_init(struct acpi_device *device)
hotk->light_level = 5; /* level 5 for sensor sensitivity */

if (ls_switch_handle)
- set_light_sens_switch(asus->light_switch);
+ set_light_sens_switch(asus, asus->light_switch);

if (ls_level_handle)
- set_light_sens_level(asus->light_level);
+ set_light_sens_level(asus, asus->light_level);

/* GPS is on by default */
- write_status(NULL, 1, GPS_ON);
+ write_status(asus, NULL, 1, GPS_ON);
return result;
}

static int __devinit asus_acpi_add(struct acpi_device *device)
{
+ struct asus_laptop *asus;
int result;

pr_notice("Asus Laptop Support version %s\n",
@@ -1408,7 +1462,7 @@ static int __devinit asus_acpi_add(struct acpi_device *device)
device->driver_data = asus;
asus->device = device;

- result = asus_acpi_init(device);
+ result = asus_acpi_init(asus);
if (result)
goto fail_platform;

@@ -1416,22 +1470,22 @@ static int __devinit asus_acpi_add(struct acpi_device *device)
* Register the platform device first. It is used as a parent for the
* sub-devices below.
*/
- result = asus_platform_init();
+ result = asus_platform_init(asus);
if (result)
goto fail_platform;

if (!acpi_video_backlight_support()) {
- result = asus_backlight_init(&asus->platform_device->dev);
+ result = asus_backlight_init(asus);
if (result)
goto fail_backlight;
} else
pr_info("Backlight controlled by ACPI video driver\n");

- result = asus_input_init(&asus->platform_device->dev);
+ result = asus_input_init(asus);
if (result)
goto fail_input;

- result = asus_led_init(&asus->platform_device->dev);
+ result = asus_led_init(asus);
if (result)
goto fail_led;

@@ -1439,11 +1493,11 @@ static int __devinit asus_acpi_add(struct acpi_device *device)
return 0;

fail_led:
- asus_input_exit();
+ asus_input_exit(asus);
fail_input:
- asus_backlight_exit();
+ asus_backlight_exit(asus);
fail_backlight:
- asus_platform_exit();
+ asus_platform_exit(asus);
fail_platform:
kfree(asus->name);
kfree(asus);
@@ -1453,10 +1507,12 @@ fail_platform:

static int asus_acpi_remove(struct acpi_device *device, int type)
{
- asus_backlight_exit();
- asus_led_exit();
- asus_input_exit();
- asus_platform_exit();
+ struct asus_laptop *asus = acpi_driver_data(device);
+
+ asus_backlight_exit(asus);
+ asus_led_exit(asus);
+ asus_input_exit(asus);
+ asus_platform_exit(asus);

kfree(asus->name);
kfree(asus);
--
1.6.6.1

2010-02-02 07:55:30

by Corentin Chary

[permalink] [raw]
Subject: [PATCH 19/28] asus-laptop: rename wireless_status to wlan_status to avoid confusion

Signed-off-by: Corentin Chary <[email protected]>
---
drivers/platform/x86/asus-laptop.c | 10 +++++-----
1 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c
index aad6b93..bb8fb45 100644
--- a/drivers/platform/x86/asus-laptop.c
+++ b/drivers/platform/x86/asus-laptop.c
@@ -76,11 +76,11 @@ static uint wapf = 1;
module_param(wapf, uint, 0644);
MODULE_PARM_DESC(wapf, "WAPF value");

-static uint wireless_status = 1;
+static uint wlan_status = 1;
static uint bluetooth_status = 1;

-module_param(wireless_status, uint, 0644);
-MODULE_PARM_DESC(wireless_status, "Set the wireless status on boot "
+module_param(wlan_status, uint, 0644);
+MODULE_PARM_DESC(wlan_status, "Set the wireless status on boot "
"(0 = disabled, 1 = enabled, -1 = don't do anything). "
"default is 1");

@@ -1446,8 +1446,8 @@ static int __devinit asus_acpi_init(struct asus_laptop *asus)
if (bluetooth_status >= 0)
asus_bluetooth_set(asus, !!bluetooth_status);

- if (wireless_status >= 0)
- asus_wlan_set(asus, !!wireless_status);
+ if (wlan_status >= 0)
+ asus_wlan_set(asus, !!wlan_status);

/* Keyboard Backlight is on by default */
if (!acpi_check_handle(asus->handle, METHOD_KBD_LIGHT_SET, NULL))
--
1.6.6.1

2010-02-02 07:55:19

by Corentin Chary

[permalink] [raw]
Subject: [PATCH 25/28] asus-laptop: add gps rfkill

The rfkill subsystem will enable gps by default.

Signed-off-by: Corentin Chary <[email protected]>
---
drivers/platform/x86/Kconfig | 1 +
drivers/platform/x86/asus-laptop.c | 65 ++++++++++++++++++++++++++++++++----
2 files changed, 59 insertions(+), 7 deletions(-)

diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index 7f5a222..527abf1 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -59,6 +59,7 @@ config ASUS_LAPTOP
select NEW_LEDS
select BACKLIGHT_CLASS_DEVICE
depends on INPUT
+ depends on RFKILL || RFKILL = n
select INPUT_SPARSEKMAP
---help---
This is the new Linux driver for Asus laptops. It may also support some
diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c
index 1d61094..e1df92a 100644
--- a/drivers/platform/x86/asus-laptop.c
+++ b/drivers/platform/x86/asus-laptop.c
@@ -50,6 +50,7 @@
#include <asm/uaccess.h>
#include <linux/input.h>
#include <linux/input/sparse-keymap.h>
+#include <linux/rfkill.h>

#define ASUS_LAPTOP_VERSION "0.42"

@@ -238,6 +239,8 @@ struct asus_laptop {
bool have_rsts;
int lcd_state;

+ struct rfkill *gps_rfkill;
+
acpi_handle handle; /* the handle of the hotk device */
u32 ledd_status; /* status of the LED display */
u8 light_level; /* light sensor level */
@@ -1006,7 +1009,6 @@ static ssize_t store_lslvl(struct device *dev, struct device_attribute *attr,

/*
* GPS
- * TODO: use rfkill
*/
static int asus_gps_status(struct asus_laptop *asus)
{
@@ -1052,10 +1054,58 @@ static ssize_t store_gps(struct device *dev, struct device_attribute *attr,
ret = asus_gps_switch(asus, !!value);
if (ret)
return ret;
+ rfkill_set_sw_state(asus->gps_rfkill, !value);
return rv;
}

/*
+ * rfkill
+ */
+static int asus_gps_rfkill_set(void *data, bool blocked)
+{
+ acpi_handle handle = data;
+
+ return asus_gps_switch(handle, !blocked);
+}
+
+static const struct rfkill_ops asus_gps_rfkill_ops = {
+ .set_block = asus_gps_rfkill_set,
+};
+
+static void asus_rfkill_exit(struct asus_laptop *asus)
+{
+ if (asus->gps_rfkill) {
+ rfkill_unregister(asus->gps_rfkill);
+ rfkill_destroy(asus->gps_rfkill);
+ asus->gps_rfkill = NULL;
+ }
+}
+
+static int asus_rfkill_init(struct asus_laptop *asus)
+{
+ int result;
+
+ 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))
+ return 0;
+
+ asus->gps_rfkill = rfkill_alloc("asus-gps", &asus->platform_device->dev,
+ RFKILL_TYPE_GPS,
+ &asus_gps_rfkill_ops, NULL);
+ if (!asus->gps_rfkill)
+ return -EINVAL;
+
+ result = rfkill_register(asus->gps_rfkill);
+ if (result) {
+ rfkill_destroy(asus->gps_rfkill);
+ asus->gps_rfkill = NULL;
+ }
+
+ return result;
+}
+
+/*
* Input device (i.e. hotkeys)
*/
static void asus_input_notify(struct asus_laptop *asus, int event)
@@ -1416,12 +1466,6 @@ static int __devinit asus_acpi_init(struct asus_laptop *asus)
asus_als_level(asus, asus->light_level);
}

- /* GPS is on by default */
- 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))
- asus_gps_switch(asus, 1);
-
asus->lcd_state = 1; /* LCD should be on when the module load */
return result;
}
@@ -1469,9 +1513,15 @@ static int __devinit asus_acpi_add(struct acpi_device *device)
if (result)
goto fail_led;

+ result = asus_rfkill_init(asus);
+ if (result)
+ goto fail_rfkill;
+
asus_device_present = true;
return 0;

+fail_rfkill:
+ asus_led_exit(asus);
fail_led:
asus_input_exit(asus);
fail_input:
@@ -1490,6 +1540,7 @@ static int asus_acpi_remove(struct acpi_device *device, int type)
struct asus_laptop *asus = acpi_driver_data(device);

asus_backlight_exit(asus);
+ asus_rfkill_exit(asus);
asus_led_exit(asus);
asus_input_exit(asus);
asus_platform_exit(asus);
--
1.6.6.1

2010-02-02 07:55:40

by Corentin Chary

[permalink] [raw]
Subject: [PATCH 23/28] asus-laptop: leds, remove dead code and fix asus_led_exit()/asus_led_init()

From: Corentin Chary <[email protected]>

These bug where introduced in "asus-laptop: code movement".

Signed-off-by: Corentin Chary <[email protected]>
---
drivers/platform/x86/asus-laptop.c | 31 ++++++++++++++-----------------
1 files changed, 14 insertions(+), 17 deletions(-)

diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c
index 516add3..ca144d2 100644
--- a/drivers/platform/x86/asus-laptop.c
+++ b/drivers/platform/x86/asus-laptop.c
@@ -371,13 +371,7 @@ static int asus_led_set(struct asus_laptop *asus, char *method,
enum led_brightness value); \
static enum led_brightness object##_led_get( \
struct led_classdev *led_cdev); \
- static void object##_led_update(struct work_struct *ignored); \
- static struct led_classdev object##_led = { \
- .name = "asus::" ledname, \
- .brightness_set = object##_led_set, \
- .brightness_get = object##_led_get, \
- .max_brightness = max \
- }
+ static void object##_led_update(struct work_struct *ignored);

ASUS_LED(mled, "mail", 1);
ASUS_LED(tled, "touchpad", 1);
@@ -478,18 +472,20 @@ static enum led_brightness kled_led_get(struct led_classdev *led_cdev)
return asus_kled_lvl(asus);
}

-#define ASUS_LED_UNREGISTER(object) \
- if (object##_led.dev) \
- led_classdev_unregister(&object##_led)
-
static void asus_led_exit(struct asus_laptop *asus)
{
- ASUS_LED_UNREGISTER(mled);
- ASUS_LED_UNREGISTER(tled);
- ASUS_LED_UNREGISTER(pled);
- ASUS_LED_UNREGISTER(rled);
- ASUS_LED_UNREGISTER(gled);
- ASUS_LED_UNREGISTER(kled);
+ if (asus->leds.mled.dev)
+ led_classdev_unregister(&asus->leds.mled);
+ if (asus->leds.tled.dev)
+ led_classdev_unregister(&asus->leds.tled);
+ if (asus->leds.pled.dev)
+ led_classdev_unregister(&asus->leds.pled);
+ if (asus->leds.rled.dev)
+ led_classdev_unregister(&asus->leds.rled);
+ if (asus->leds.gled.dev)
+ led_classdev_unregister(&asus->leds.gled);
+ if (asus->leds.kled.dev)
+ led_classdev_unregister(&asus->leds.kled);
if (asus->leds.workqueue) {
destroy_workqueue(asus->leds.workqueue);
asus->leds.workqueue = NULL;
@@ -507,6 +503,7 @@ static void asus_led_exit(struct asus_laptop *asus)
INIT_WORK(&asus->leds.object##_work, object##_led_update); \
ldev->name = "asus::" _name; \
ldev->brightness_set = object##_led_set; \
+ ldev->brightness_get = object##_led_get; \
ldev->max_brightness = max; \
rv = led_classdev_register(&asus->platform_device->dev, ldev); \
if (rv) \
--
1.6.6.1

2010-02-02 07:55:22

by Corentin Chary

[permalink] [raw]
Subject: [PATCH 09/28] asus-laptop: move backlight and dsdt info inside asus_laptop struct

Prepare the use of "driver data" for callbacks.

Signed-off-by: Corentin Chary <[email protected]>
---
drivers/platform/x86/asus-laptop.c | 69 +++++++++++++++--------------------
1 files changed, 30 insertions(+), 39 deletions(-)

diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c
index 2505f15..4ff30ca 100644
--- a/drivers/platform/x86/asus-laptop.c
+++ b/drivers/platform/x86/asus-laptop.c
@@ -202,30 +202,24 @@ ASUS_HANDLE(kled_get, ASUS_LAPTOP_PREFIX "GLKB");
struct asus_laptop {
char *name; /* laptop name */

+ struct acpi_table_header *dsdt_info;
struct platform_device *platform_device;
- struct acpi_device *device; /* the device we are in */
+ struct acpi_device *device; /* the device we are in */
+ struct backlight_device *backlight_device;
+ struct input_dev *inputdev;
+
acpi_handle handle; /* the handle of the hotk device */
char status; /* status of the hotk, for LEDs, ... */
u32 ledd_status; /* status of the LED display */
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 */
- struct input_dev *inputdev;
u16 *keycode_map;
};

-/*
- * This header is made available to allow proper configuration given model,
- * revision number , ... this info cannot go in struct asus_laptop because it is
- * available before the hotk
- */
-static struct acpi_table_header *asus_info;
-
-/* The actual device the driver binds to */
static struct asus_laptop *asus;

-/* The backlight device /sys/class/backlight */
-static struct backlight_device *asus_backlight_device;
+static struct workqueue_struct *led_workqueue;

/*
* The backlight class declaration
@@ -237,14 +231,6 @@ static struct backlight_ops asusbl_ops = {
.update_status = update_bl_status,
};

-/*
- * These functions actually update the LED's, and are called from a
- * workqueue. By doing this as separate work rather than when the LED
- * subsystem asks, we avoid messing with the Asus ACPI stuff during a
- * potentially bad time, such as a timer interrupt.
- */
-static struct workqueue_struct *led_workqueue;
-
#define ASUS_LED(object, ledname, max) \
static void object##_led_set(struct led_classdev *led_cdev, \
enum led_brightness value); \
@@ -522,7 +508,7 @@ static int set_lcd_state(int value)

static void lcd_blank(int blank)
{
- struct backlight_device *bd = asus_backlight_device;
+ struct backlight_device *bd = asus->backlight_device;

if (bd) {
bd->props.power = blank;
@@ -619,22 +605,22 @@ static ssize_t show_infos(struct device *dev,
if (!ACPI_FAILURE(rv))
len += sprintf(page + len, "ASYM value : %#x\n",
(uint) temp);
- if (asus_info) {
- snprintf(buf, 16, "%d", asus_info->length);
+ if (asus->dsdt_info) {
+ snprintf(buf, 16, "%d", asus->dsdt_info->length);
len += sprintf(page + len, "DSDT length : %s\n", buf);
- snprintf(buf, 16, "%d", asus_info->checksum);
+ snprintf(buf, 16, "%d", asus->dsdt_info->checksum);
len += sprintf(page + len, "DSDT checksum : %s\n", buf);
- snprintf(buf, 16, "%d", asus_info->revision);
+ snprintf(buf, 16, "%d", asus->dsdt_info->revision);
len += sprintf(page + len, "DSDT revision : %s\n", buf);
- snprintf(buf, 7, "%s", asus_info->oem_id);
+ snprintf(buf, 7, "%s", asus->dsdt_info->oem_id);
len += sprintf(page + len, "OEM id : %s\n", buf);
- snprintf(buf, 9, "%s", asus_info->oem_table_id);
+ snprintf(buf, 9, "%s", asus->dsdt_info->oem_table_id);
len += sprintf(page + len, "OEM table id : %s\n", buf);
- snprintf(buf, 16, "%x", asus_info->oem_revision);
+ snprintf(buf, 16, "%x", asus->dsdt_info->oem_revision);
len += sprintf(page + len, "OEM revision : 0x%s\n", buf);
- snprintf(buf, 5, "%s", asus_info->asl_compiler_id);
+ snprintf(buf, 5, "%s", asus->dsdt_info->asl_compiler_id);
len += sprintf(page + len, "ASL comp vendor id : %s\n", buf);
- snprintf(buf, 16, "%x", asus_info->asl_compiler_revision);
+ snprintf(buf, 16, "%x", asus->dsdt_info->asl_compiler_revision);
len += sprintf(page + len, "ASL comp revision : 0x%s\n", buf);
}

@@ -1084,7 +1070,7 @@ static int asus_handle_init(char *name, acpi_handle * handle,
* method, we can make all the detection we want, and modify the asus_laptop
* struct
*/
-static int asus_laptop_get_info(void)
+static int asus_laptop_get_info(struct asus_laptop *asus)
{
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
union acpi_object *model = NULL;
@@ -1097,10 +1083,9 @@ static int asus_laptop_get_info(void)
* models, but late enough to allow acpi_bus_register_driver() to fail
* before doing anything ACPI-specific. Should we encounter a machine,
* which needs special handling (i.e. its hotkey device has a different
- * HID), this bit will be moved. A global variable asus_info contains
- * the DSDT header.
+ * HID), this bit will be moved.
*/
- status = acpi_get_table(ACPI_SIG_DSDT, 1, &asus_info);
+ status = acpi_get_table(ACPI_SIG_DSDT, 1, &asus->dsdt_info);
if (ACPI_FAILURE(status))
pr_warning("Couldn't get the DSDT table header\n");

@@ -1237,8 +1222,8 @@ static int asus_input_init(struct device *dev)

static void asus_backlight_exit(void)
{
- if (asus_backlight_device)
- backlight_device_unregister(asus_backlight_device);
+ if (asus->backlight_device)
+ backlight_device_unregister(asus->backlight_device);
}

#define ASUS_LED_UNREGISTER(object) \
@@ -1271,11 +1256,11 @@ static int asus_backlight_init(struct device *dev)
NULL, &asusbl_ops);
if (IS_ERR(bd)) {
pr_err("Could not register asus backlight device\n");
- asus_backlight_device = NULL;
+ asus->backlight_device = NULL;
return PTR_ERR(bd);
}

- asus_backlight_device = bd;
+ asus->backlight_device = bd;

bd->props.max_brightness = 15;
bd->props.brightness = read_brightness(NULL);
@@ -1326,6 +1311,12 @@ static int asus_led_init(struct device *dev)
if (rv)
goto out5;

+ /*
+ * Functions that actually update the LED's are called from a
+ * workqueue. By doing this as separate work rather than when the LED
+ * subsystem asks, we avoid messing with the Asus ACPI stuff during a
+ * potentially bad time, such as a timer interrupt.
+ */
led_workqueue = create_singlethread_workqueue("led_workqueue");
if (!led_workqueue)
goto out6;
@@ -1363,7 +1354,7 @@ static int __devinit asus_acpi_init(struct acpi_device *device)
return -ENODEV;
}

- result = asus_laptop_get_info();
+ result = asus_laptop_get_info(asus);
if (result)
return result;

--
1.6.6.1