diff options
Diffstat (limited to 'drivers/misc')
-rw-r--r-- | drivers/misc/thinkpad_acpi.c | 57 |
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 | ||
3283 | static 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 | |||
3292 | static 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 | |||
3303 | static enum led_brightness light_sysfs_get(struct led_classdev *led_cdev) | ||
3304 | { | ||
3305 | return (light_get_status() == 1)? LED_FULL : LED_OFF; | ||
3306 | } | ||
3307 | |||
3308 | static 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 | |||
3283 | static int __init light_init(struct ibm_init_struct *iibm) | 3316 | static 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 | |||
3353 | static 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 | ||
3306 | static int light_read(char *p) | 3360 | static 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 | /************************************************************************* |