aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/video.c
diff options
context:
space:
mode:
authorDanny Baumann <dannybaumann@web.de>2013-03-19 12:22:50 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-03-24 19:26:54 -0400
commita89803df9c9b2d023227c48503066a728f1fed36 (patch)
tree546abec81aee8db55f712f6ead8cc4d476f34e64 /drivers/acpi/video.c
parente4f5224464739a89e6a6c9169211ef4f76165056 (diff)
ACPI / video: Fix brightness control initialization for some laptops.
In particular, this fixes brightness control initialization for all devices that return index values from _BQC and don't happen to have the initial index set by the BIOS in their _BCL table. One example for that is the Dell Inspiron 15R SE (model number 7520). What happened for those devices is that acpi_init_brightness queried the initial brightness by calling acpi_video_device_lcd_get_level_current. This called _BQC, which returned e.g. 13. As _BQC_use_index isn't determined at this point (and thus has its initial value of 0), the index isn't converted into the actual level. As '13' isn't present in the _BCL list, *level is later overwritten with brightness->curr, which was initialized to max_level (100) before. Later in acpi_init_brightness, level_old (with the value 100) is used as an index into the _BCL table, which causes a value outside of the actual table to be used as input into acpi_video_device_lcd_set_level(). Depending on the (undefined) value of that location, this call will fail, causing the brightness control for the device in question not to be enabled. Fix that by returning the raw value returned by the _BQC call in the initialization case. Signed-off-by: Danny Baumann <dannybaumann@web.de> Reviewed-by: Aaron Lu <aaron.lu@intel.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers/acpi/video.c')
-rw-r--r--drivers/acpi/video.c43
1 files changed, 26 insertions, 17 deletions
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c
index f8a28b39b88a..387b3705279a 100644
--- a/drivers/acpi/video.c
+++ b/drivers/acpi/video.c
@@ -222,7 +222,7 @@ static int acpi_video_device_lcd_set_level(struct acpi_video_device *device,
222 int level); 222 int level);
223static int acpi_video_device_lcd_get_level_current( 223static int acpi_video_device_lcd_get_level_current(
224 struct acpi_video_device *device, 224 struct acpi_video_device *device,
225 unsigned long long *level, int init); 225 unsigned long long *level, bool raw);
226static int acpi_video_get_next_level(struct acpi_video_device *device, 226static int acpi_video_get_next_level(struct acpi_video_device *device,
227 u32 level_current, u32 event); 227 u32 level_current, u32 event);
228static int acpi_video_switch_brightness(struct acpi_video_device *device, 228static int acpi_video_switch_brightness(struct acpi_video_device *device,
@@ -236,7 +236,7 @@ static int acpi_video_get_brightness(struct backlight_device *bd)
236 struct acpi_video_device *vd = 236 struct acpi_video_device *vd =
237 (struct acpi_video_device *)bl_get_data(bd); 237 (struct acpi_video_device *)bl_get_data(bd);
238 238
239 if (acpi_video_device_lcd_get_level_current(vd, &cur_level, 0)) 239 if (acpi_video_device_lcd_get_level_current(vd, &cur_level, false))
240 return -EINVAL; 240 return -EINVAL;
241 for (i = 2; i < vd->brightness->count; i++) { 241 for (i = 2; i < vd->brightness->count; i++) {
242 if (vd->brightness->levels[i] == cur_level) 242 if (vd->brightness->levels[i] == cur_level)
@@ -281,7 +281,7 @@ static int video_get_cur_state(struct thermal_cooling_device *cooling_dev, unsig
281 unsigned long long level; 281 unsigned long long level;
282 int offset; 282 int offset;
283 283
284 if (acpi_video_device_lcd_get_level_current(video, &level, 0)) 284 if (acpi_video_device_lcd_get_level_current(video, &level, false))
285 return -EINVAL; 285 return -EINVAL;
286 for (offset = 2; offset < video->brightness->count; offset++) 286 for (offset = 2; offset < video->brightness->count; offset++)
287 if (level == video->brightness->levels[offset]) { 287 if (level == video->brightness->levels[offset]) {
@@ -460,7 +460,7 @@ static struct dmi_system_id video_dmi_table[] __initdata = {
460 460
461static int 461static int
462acpi_video_device_lcd_get_level_current(struct acpi_video_device *device, 462acpi_video_device_lcd_get_level_current(struct acpi_video_device *device,
463 unsigned long long *level, int init) 463 unsigned long long *level, bool raw)
464{ 464{
465 acpi_status status = AE_OK; 465 acpi_status status = AE_OK;
466 int i; 466 int i;
@@ -471,6 +471,15 @@ acpi_video_device_lcd_get_level_current(struct acpi_video_device *device,
471 status = acpi_evaluate_integer(device->dev->handle, buf, 471 status = acpi_evaluate_integer(device->dev->handle, buf,
472 NULL, level); 472 NULL, level);
473 if (ACPI_SUCCESS(status)) { 473 if (ACPI_SUCCESS(status)) {
474 if (raw) {
475 /*
476 * Caller has indicated he wants the raw
477 * value returned by _BQC, so don't furtherly
478 * mess with the value.
479 */
480 return 0;
481 }
482
474 if (device->brightness->flags._BQC_use_index) { 483 if (device->brightness->flags._BQC_use_index) {
475 if (device->brightness->flags._BCL_reversed) 484 if (device->brightness->flags._BCL_reversed)
476 *level = device->brightness->count 485 *level = device->brightness->count
@@ -484,16 +493,14 @@ acpi_video_device_lcd_get_level_current(struct acpi_video_device *device,
484 device->brightness->curr = *level; 493 device->brightness->curr = *level;
485 return 0; 494 return 0;
486 } 495 }
487 if (!init) { 496 /*
488 /* 497 * BQC returned an invalid level.
489 * BQC returned an invalid level. 498 * Stop using it.
490 * Stop using it. 499 */
491 */ 500 ACPI_WARNING((AE_INFO,
492 ACPI_WARNING((AE_INFO, 501 "%s returned an invalid level",
493 "%s returned an invalid level", 502 buf));
494 buf)); 503 device->cap._BQC = device->cap._BCQ = 0;
495 device->cap._BQC = device->cap._BCQ = 0;
496 }
497 } else { 504 } else {
498 /* Fixme: 505 /* Fixme:
499 * should we return an error or ignore this failure? 506 * should we return an error or ignore this failure?
@@ -711,7 +718,8 @@ acpi_video_init_brightness(struct acpi_video_device *device)
711 if (!device->cap._BQC) 718 if (!device->cap._BQC)
712 goto set_level; 719 goto set_level;
713 720
714 result = acpi_video_device_lcd_get_level_current(device, &level_old, 1); 721 result = acpi_video_device_lcd_get_level_current(device,
722 &level_old, true);
715 if (result) 723 if (result)
716 goto out_free_levels; 724 goto out_free_levels;
717 725
@@ -722,7 +730,7 @@ acpi_video_init_brightness(struct acpi_video_device *device)
722 if (result) 730 if (result)
723 goto out_free_levels; 731 goto out_free_levels;
724 732
725 result = acpi_video_device_lcd_get_level_current(device, &level, 0); 733 result = acpi_video_device_lcd_get_level_current(device, &level, true);
726 if (result) 734 if (result)
727 goto out_free_levels; 735 goto out_free_levels;
728 736
@@ -1276,7 +1284,8 @@ acpi_video_switch_brightness(struct acpi_video_device *device, int event)
1276 goto out; 1284 goto out;
1277 1285
1278 result = acpi_video_device_lcd_get_level_current(device, 1286 result = acpi_video_device_lcd_get_level_current(device,
1279 &level_current, 0); 1287 &level_current,
1288 false);
1280 if (result) 1289 if (result)
1281 goto out; 1290 goto out;
1282 1291