aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc/thinkpad_acpi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/misc/thinkpad_acpi.c')
-rw-r--r--drivers/misc/thinkpad_acpi.c57
1 files changed, 56 insertions, 1 deletions
diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c
index 5a3fb09f10d3..38a119bd931e 100644
--- a/drivers/misc/thinkpad_acpi.c
+++ b/drivers/misc/thinkpad_acpi.c
@@ -3280,13 +3280,49 @@ static int light_set_status(int status)
3280 return -ENXIO; 3280 return -ENXIO;
3281} 3281}
3282 3282
3283static void light_set_status_worker(struct work_struct *work)
3284{
3285 struct tpacpi_led_classdev *data =
3286 container_of(work, struct tpacpi_led_classdev, work);
3287
3288 if (likely(tpacpi_lifecycle == TPACPI_LIFE_RUNNING))
3289 light_set_status((data->new_brightness != LED_OFF));
3290}
3291
3292static void light_sysfs_set(struct led_classdev *led_cdev,
3293 enum led_brightness brightness)
3294{
3295 struct tpacpi_led_classdev *data =
3296 container_of(led_cdev,
3297 struct tpacpi_led_classdev,
3298 led_classdev);
3299 data->new_brightness = brightness;
3300 schedule_work(&data->work);
3301}
3302
3303static enum led_brightness light_sysfs_get(struct led_classdev *led_cdev)
3304{
3305 return (light_get_status() == 1)? LED_FULL : LED_OFF;
3306}
3307
3308static struct tpacpi_led_classdev tpacpi_led_thinklight = {
3309 .led_classdev = {
3310 .name = "tpacpi::thinklight",
3311 .brightness_set = &light_sysfs_set,
3312 .brightness_get = &light_sysfs_get,
3313 }
3314};
3315
3283static int __init light_init(struct ibm_init_struct *iibm) 3316static int __init light_init(struct ibm_init_struct *iibm)
3284{ 3317{
3318 int rc = 0;
3319
3285 vdbg_printk(TPACPI_DBG_INIT, "initializing light subdriver\n"); 3320 vdbg_printk(TPACPI_DBG_INIT, "initializing light subdriver\n");
3286 3321
3287 TPACPI_ACPIHANDLE_INIT(ledb); 3322 TPACPI_ACPIHANDLE_INIT(ledb);
3288 TPACPI_ACPIHANDLE_INIT(lght); 3323 TPACPI_ACPIHANDLE_INIT(lght);
3289 TPACPI_ACPIHANDLE_INIT(cmos); 3324 TPACPI_ACPIHANDLE_INIT(cmos);
3325 INIT_WORK(&tpacpi_led_thinklight.work, light_set_status_worker);
3290 3326
3291 /* light not supported on 570, 600e/x, 770e, 770x, G4x, R30, R31 */ 3327 /* light not supported on 570, 600e/x, 770e, 770x, G4x, R30, R31 */
3292 tp_features.light = (cmos_handle || lght_handle) && !ledb_handle; 3328 tp_features.light = (cmos_handle || lght_handle) && !ledb_handle;
@@ -3300,7 +3336,25 @@ static int __init light_init(struct ibm_init_struct *iibm)
3300 vdbg_printk(TPACPI_DBG_INIT, "light is %s\n", 3336 vdbg_printk(TPACPI_DBG_INIT, "light is %s\n",
3301 str_supported(tp_features.light)); 3337 str_supported(tp_features.light));
3302 3338
3303 return (tp_features.light)? 0 : 1; 3339 if (tp_features.light) {
3340 rc = led_classdev_register(&tpacpi_pdev->dev,
3341 &tpacpi_led_thinklight.led_classdev);
3342 }
3343
3344 if (rc < 0) {
3345 tp_features.light = 0;
3346 tp_features.light_status = 0;
3347 } else {
3348 rc = (tp_features.light)? 0 : 1;
3349 }
3350 return rc;
3351}
3352
3353static void light_exit(void)
3354{
3355 led_classdev_unregister(&tpacpi_led_thinklight.led_classdev);
3356 if (work_pending(&tpacpi_led_thinklight.work))
3357 flush_scheduled_work();
3304} 3358}
3305 3359
3306static int light_read(char *p) 3360static int light_read(char *p)
@@ -3348,6 +3402,7 @@ static struct ibm_struct light_driver_data = {
3348 .name = "light", 3402 .name = "light",
3349 .read = light_read, 3403 .read = light_read,
3350 .write = light_write, 3404 .write = light_write,
3405 .exit = light_exit,
3351}; 3406};
3352 3407
3353/************************************************************************* 3408/*************************************************************************