diff options
author | Zhang Rui <rui.zhang@intel.com> | 2008-01-17 02:51:22 -0500 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2008-02-01 23:18:33 -0500 |
commit | 702ed512de9c8a67a69a981c73b7337c2131f198 (patch) | |
tree | 58ac1266d3e13ae1fcd89e947d19dbf30285e019 /drivers/acpi | |
parent | d9460fd227ed2ce52941b6a12ad4de05c195f6aa (diff) |
ACPI: register ACPI Video LCD as generic thermal cooling device
Register ACPI video device as thermal cooling devices as they may be listed
in _TZD method and the backlight control can be used for throttling.
Signed-off-by: Zhang Rui <rui.zhang@intel.com>
Signed-off-by: Thomas Sujith <sujith.thomas@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi')
-rw-r--r-- | drivers/acpi/video.c | 78 |
1 files changed, 77 insertions, 1 deletions
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index bd77e81e81c1..eab9c4213b49 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include <linux/seq_file.h> | 34 | #include <linux/seq_file.h> |
35 | #include <linux/input.h> | 35 | #include <linux/input.h> |
36 | #include <linux/backlight.h> | 36 | #include <linux/backlight.h> |
37 | #include <linux/thermal.h> | ||
37 | #include <linux/video_output.h> | 38 | #include <linux/video_output.h> |
38 | #include <asm/uaccess.h> | 39 | #include <asm/uaccess.h> |
39 | 40 | ||
@@ -179,6 +180,7 @@ struct acpi_video_device { | |||
179 | struct acpi_device *dev; | 180 | struct acpi_device *dev; |
180 | struct acpi_video_device_brightness *brightness; | 181 | struct acpi_video_device_brightness *brightness; |
181 | struct backlight_device *backlight; | 182 | struct backlight_device *backlight; |
183 | struct thermal_cooling_device *cdev; | ||
182 | struct output_device *output_dev; | 184 | struct output_device *output_dev; |
183 | }; | 185 | }; |
184 | 186 | ||
@@ -334,6 +336,54 @@ static struct output_properties acpi_output_properties = { | |||
334 | .set_state = acpi_video_output_set, | 336 | .set_state = acpi_video_output_set, |
335 | .get_status = acpi_video_output_get, | 337 | .get_status = acpi_video_output_get, |
336 | }; | 338 | }; |
339 | |||
340 | |||
341 | /* thermal cooling device callbacks */ | ||
342 | static int video_get_max_state(struct thermal_cooling_device *cdev, char *buf) | ||
343 | { | ||
344 | struct acpi_device *device = cdev->devdata; | ||
345 | struct acpi_video_device *video = acpi_driver_data(device); | ||
346 | |||
347 | return sprintf(buf, "%d\n", video->brightness->count - 3); | ||
348 | } | ||
349 | |||
350 | static int video_get_cur_state(struct thermal_cooling_device *cdev, char *buf) | ||
351 | { | ||
352 | struct acpi_device *device = cdev->devdata; | ||
353 | struct acpi_video_device *video = acpi_driver_data(device); | ||
354 | unsigned long level; | ||
355 | int state; | ||
356 | |||
357 | acpi_video_device_lcd_get_level_current(video, &level); | ||
358 | for (state = 2; state < video->brightness->count; state++) | ||
359 | if (level == video->brightness->levels[state]) | ||
360 | return sprintf(buf, "%d\n", | ||
361 | video->brightness->count - state - 1); | ||
362 | |||
363 | return -EINVAL; | ||
364 | } | ||
365 | |||
366 | static int | ||
367 | video_set_cur_state(struct thermal_cooling_device *cdev, unsigned int state) | ||
368 | { | ||
369 | struct acpi_device *device = cdev->devdata; | ||
370 | struct acpi_video_device *video = acpi_driver_data(device); | ||
371 | int level; | ||
372 | |||
373 | if ( state >= video->brightness->count - 2) | ||
374 | return -EINVAL; | ||
375 | |||
376 | state = video->brightness->count - state; | ||
377 | level = video->brightness->levels[state -1]; | ||
378 | return acpi_video_device_lcd_set_level(video, level); | ||
379 | } | ||
380 | |||
381 | static struct thermal_cooling_device_ops video_cooling_ops = { | ||
382 | .get_max_state = video_get_max_state, | ||
383 | .get_cur_state = video_get_cur_state, | ||
384 | .set_cur_state = video_set_cur_state, | ||
385 | }; | ||
386 | |||
337 | /* -------------------------------------------------------------------------- | 387 | /* -------------------------------------------------------------------------- |
338 | Video Management | 388 | Video Management |
339 | -------------------------------------------------------------------------- */ | 389 | -------------------------------------------------------------------------- */ |
@@ -653,6 +703,7 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device) | |||
653 | 703 | ||
654 | if (device->cap._BCL && device->cap._BCM && device->cap._BQC && max_level > 0){ | 704 | if (device->cap._BCL && device->cap._BCM && device->cap._BQC && max_level > 0){ |
655 | unsigned long tmp; | 705 | unsigned long tmp; |
706 | int result; | ||
656 | static int count = 0; | 707 | static int count = 0; |
657 | char *name; | 708 | char *name; |
658 | name = kzalloc(MAX_NAME_LEN, GFP_KERNEL); | 709 | name = kzalloc(MAX_NAME_LEN, GFP_KERNEL); |
@@ -666,8 +717,25 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device) | |||
666 | device->backlight->props.max_brightness = max_level; | 717 | device->backlight->props.max_brightness = max_level; |
667 | device->backlight->props.brightness = (int)tmp; | 718 | device->backlight->props.brightness = (int)tmp; |
668 | backlight_update_status(device->backlight); | 719 | backlight_update_status(device->backlight); |
669 | |||
670 | kfree(name); | 720 | kfree(name); |
721 | |||
722 | device->cdev = thermal_cooling_device_register("LCD", | ||
723 | device->dev, &video_cooling_ops); | ||
724 | if (device->cdev) { | ||
725 | printk(KERN_INFO PREFIX | ||
726 | "%s is registered as cooling_device%d\n", | ||
727 | device->dev->dev.bus_id, device->cdev->id); | ||
728 | result = sysfs_create_link(&device->dev->dev.kobj, | ||
729 | &device->cdev->device.kobj, | ||
730 | "thermal_cooling"); | ||
731 | if (result) | ||
732 | printk(KERN_ERR PREFIX "Create sysfs link\n"); | ||
733 | result = sysfs_create_link(&device->cdev->device.kobj, | ||
734 | &device->dev->dev.kobj, | ||
735 | "device"); | ||
736 | if (result) | ||
737 | printk(KERN_ERR PREFIX "Create sysfs link\n"); | ||
738 | } | ||
671 | } | 739 | } |
672 | if (device->cap._DCS && device->cap._DSS){ | 740 | if (device->cap._DCS && device->cap._DSS){ |
673 | static int count = 0; | 741 | static int count = 0; |
@@ -1729,6 +1797,14 @@ static int acpi_video_bus_put_one_device(struct acpi_video_device *device) | |||
1729 | ACPI_DEVICE_NOTIFY, | 1797 | ACPI_DEVICE_NOTIFY, |
1730 | acpi_video_device_notify); | 1798 | acpi_video_device_notify); |
1731 | backlight_device_unregister(device->backlight); | 1799 | backlight_device_unregister(device->backlight); |
1800 | if (device->cdev) { | ||
1801 | sysfs_remove_link(&device->dev->dev.kobj, | ||
1802 | "thermal_cooling"); | ||
1803 | sysfs_remove_link(&device->cdev->device.kobj, | ||
1804 | "device"); | ||
1805 | thermal_cooling_device_unregister(device->cdev); | ||
1806 | device->cdev = NULL; | ||
1807 | } | ||
1732 | video_output_unregister(device->output_dev); | 1808 | video_output_unregister(device->output_dev); |
1733 | 1809 | ||
1734 | return 0; | 1810 | return 0; |