asus-laptop: clean led code
authorCorentin Chary <corentincj@iksaif.net>
Tue, 26 Jan 2010 20:01:34 +0000 (21:01 +0100)
committerCorentin Chary <corentincj@iksaif.net>
Sun, 28 Feb 2010 18:35:13 +0000 (19:35 +0100)
Remove all "templates" and add a generic struct asus_led instead.

Signed-off-by: Corentin Chary <corentincj@iksaif.net>
drivers/platform/x86/asus-laptop.c

index e1df92a..ae53026 100644 (file)
@@ -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;
 }
 
 /*