diff options
author | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2013-04-27 19:54:08 -0400 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2013-04-27 19:54:08 -0400 |
commit | c940c8ce1db3ed3909d31c02aef01a864565519c (patch) | |
tree | 725597abd9bd910792410ddfe89cc0857d7667b2 /drivers | |
parent | 34bdb1a458baaf3e56843c36deb04283c26a8099 (diff) | |
parent | 94a409319561ec1847fd9bf996a2d5843ad00932 (diff) |
Merge branch 'acpi-assorted'
* acpi-assorted: (21 commits)
ACPI / thermal: do not always return THERMAL_TREND_RAISING for active trip points
ACPI: video: correct acpi_video_bus_add error processing
ACPI: Fix wrong parameter passed to memblock_reserve
acpi: video: enhance the quirk detect logic of _BQC
ACPI: update comments for acpi_event_status
ACPI: remove "config ACPI_DEBUG_FUNC_TRACE"
PCI / ACPI: Don't query OSC support with all possible controls
ACPI / processor_thermal: avoid null pointer deference error
ACPI / fan: avoid null pointer deference error
ACPI / video: Fix applying indexed initial brightness value.
ACPI / video: Make logic a little easier to understand.
ACPI / video: Fix brightness control initialization for some laptops.
ACPI: Use resource_size() in osl.c
ACPI / acpi_pad: Used PTR_RET
ACPI: suppress compiler warning in container.c
ACPI: suppress compiler warning in battery.c
ACPI: suppress compiler warnings in processor_throttling.c
ACPI: suppress compiler warnings in button.c
ACPI: replace kmalloc+memcpy with kmemdup
ACPI: Remove acpi_pci_bind_root() definition
...
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/acpi/Kconfig | 8 | ||||
-rw-r--r-- | drivers/acpi/acpi_pad.c | 2 | ||||
-rw-r--r-- | drivers/acpi/battery.c | 2 | ||||
-rw-r--r-- | drivers/acpi/bus.c | 5 | ||||
-rw-r--r-- | drivers/acpi/button.c | 1 | ||||
-rw-r--r-- | drivers/acpi/container.c | 2 | ||||
-rw-r--r-- | drivers/acpi/fan.c | 8 | ||||
-rw-r--r-- | drivers/acpi/osl.c | 4 | ||||
-rw-r--r-- | drivers/acpi/pci_root.c | 4 | ||||
-rw-r--r-- | drivers/acpi/processor_thermal.c | 24 | ||||
-rw-r--r-- | drivers/acpi/processor_throttling.c | 3 | ||||
-rw-r--r-- | drivers/acpi/thermal.c | 16 | ||||
-rw-r--r-- | drivers/acpi/video.c | 318 |
13 files changed, 243 insertions, 154 deletions
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 8fcae6df0a42..100bd724f648 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig | |||
@@ -298,14 +298,6 @@ config ACPI_DEBUG | |||
298 | Documentation/kernel-parameters.txt to control the type and | 298 | Documentation/kernel-parameters.txt to control the type and |
299 | amount of debug output. | 299 | amount of debug output. |
300 | 300 | ||
301 | config ACPI_DEBUG_FUNC_TRACE | ||
302 | bool "Additionally enable ACPI function tracing" | ||
303 | default n | ||
304 | depends on ACPI_DEBUG | ||
305 | help | ||
306 | ACPI Debug Statements slow down ACPI processing. Function trace | ||
307 | is about half of the penalty and is rarely useful. | ||
308 | |||
309 | config ACPI_PCI_SLOT | 301 | config ACPI_PCI_SLOT |
310 | bool "PCI slot detection driver" | 302 | bool "PCI slot detection driver" |
311 | depends on SYSFS | 303 | depends on SYSFS |
diff --git a/drivers/acpi/acpi_pad.c b/drivers/acpi/acpi_pad.c index 31de1043eea0..27bb6a91de5f 100644 --- a/drivers/acpi/acpi_pad.c +++ b/drivers/acpi/acpi_pad.c | |||
@@ -236,7 +236,7 @@ static int create_power_saving_task(void) | |||
236 | ps_tsks[ps_tsk_num] = kthread_run(power_saving_thread, | 236 | ps_tsks[ps_tsk_num] = kthread_run(power_saving_thread, |
237 | (void *)(unsigned long)ps_tsk_num, | 237 | (void *)(unsigned long)ps_tsk_num, |
238 | "acpi_pad/%d", ps_tsk_num); | 238 | "acpi_pad/%d", ps_tsk_num); |
239 | rc = IS_ERR(ps_tsks[ps_tsk_num]) ? PTR_ERR(ps_tsks[ps_tsk_num]) : 0; | 239 | rc = PTR_RET(ps_tsks[ps_tsk_num]); |
240 | if (!rc) | 240 | if (!rc) |
241 | ps_tsk_num++; | 241 | ps_tsk_num++; |
242 | else | 242 | else |
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index c5cd5b5513e6..0cc384b72943 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c | |||
@@ -146,7 +146,7 @@ struct acpi_battery { | |||
146 | 146 | ||
147 | #define to_acpi_battery(x) container_of(x, struct acpi_battery, bat) | 147 | #define to_acpi_battery(x) container_of(x, struct acpi_battery, bat) |
148 | 148 | ||
149 | inline int acpi_battery_present(struct acpi_battery *battery) | 149 | static inline int acpi_battery_present(struct acpi_battery *battery) |
150 | { | 150 | { |
151 | return battery->device->status.battery_present; | 151 | return battery->device->status.battery_present; |
152 | } | 152 | } |
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 01708a165368..292de3cab9cc 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c | |||
@@ -288,13 +288,12 @@ acpi_status acpi_run_osc(acpi_handle handle, struct acpi_osc_context *context) | |||
288 | } | 288 | } |
289 | out_success: | 289 | out_success: |
290 | context->ret.length = out_obj->buffer.length; | 290 | context->ret.length = out_obj->buffer.length; |
291 | context->ret.pointer = kmalloc(context->ret.length, GFP_KERNEL); | 291 | context->ret.pointer = kmemdup(out_obj->buffer.pointer, |
292 | context->ret.length, GFP_KERNEL); | ||
292 | if (!context->ret.pointer) { | 293 | if (!context->ret.pointer) { |
293 | status = AE_NO_MEMORY; | 294 | status = AE_NO_MEMORY; |
294 | goto out_kfree; | 295 | goto out_kfree; |
295 | } | 296 | } |
296 | memcpy(context->ret.pointer, out_obj->buffer.pointer, | ||
297 | context->ret.length); | ||
298 | status = AE_OK; | 297 | status = AE_OK; |
299 | 298 | ||
300 | out_kfree: | 299 | out_kfree: |
diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c index 86c7d5445c38..92a659aa6396 100644 --- a/drivers/acpi/button.c +++ b/drivers/acpi/button.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <linux/slab.h> | 33 | #include <linux/slab.h> |
34 | #include <acpi/acpi_bus.h> | 34 | #include <acpi/acpi_bus.h> |
35 | #include <acpi/acpi_drivers.h> | 35 | #include <acpi/acpi_drivers.h> |
36 | #include <acpi/button.h> | ||
36 | 37 | ||
37 | #define PREFIX "ACPI: " | 38 | #define PREFIX "ACPI: " |
38 | 39 | ||
diff --git a/drivers/acpi/container.c b/drivers/acpi/container.c index f9f8a08827fa..e23151667655 100644 --- a/drivers/acpi/container.c +++ b/drivers/acpi/container.c | |||
@@ -30,6 +30,8 @@ | |||
30 | 30 | ||
31 | #include "internal.h" | 31 | #include "internal.h" |
32 | 32 | ||
33 | #include "internal.h" | ||
34 | |||
33 | #define PREFIX "ACPI: " | 35 | #define PREFIX "ACPI: " |
34 | 36 | ||
35 | #define _COMPONENT ACPI_CONTAINER_COMPONENT | 37 | #define _COMPONENT ACPI_CONTAINER_COMPONENT |
diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c index f815da82c765..8d1c0105e113 100644 --- a/drivers/acpi/fan.c +++ b/drivers/acpi/fan.c | |||
@@ -174,9 +174,13 @@ static int acpi_fan_add(struct acpi_device *device) | |||
174 | 174 | ||
175 | static int acpi_fan_remove(struct acpi_device *device) | 175 | static int acpi_fan_remove(struct acpi_device *device) |
176 | { | 176 | { |
177 | struct thermal_cooling_device *cdev = acpi_driver_data(device); | 177 | struct thermal_cooling_device *cdev; |
178 | |||
179 | if (!device) | ||
180 | return -EINVAL; | ||
178 | 181 | ||
179 | if (!device || !cdev) | 182 | cdev = acpi_driver_data(device); |
183 | if (!cdev) | ||
180 | return -EINVAL; | 184 | return -EINVAL; |
181 | 185 | ||
182 | sysfs_remove_link(&device->dev.kobj, "thermal_cooling"); | 186 | sysfs_remove_link(&device->dev.kobj, "thermal_cooling"); |
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 586e7e993d3d..e72186340fec 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c | |||
@@ -641,7 +641,7 @@ void __init acpi_initrd_override(void *data, size_t size) | |||
641 | * Both memblock_reserve and e820_add_region (via arch_reserve_mem_area) | 641 | * Both memblock_reserve and e820_add_region (via arch_reserve_mem_area) |
642 | * works fine. | 642 | * works fine. |
643 | */ | 643 | */ |
644 | memblock_reserve(acpi_tables_addr, acpi_tables_addr + all_tables_size); | 644 | memblock_reserve(acpi_tables_addr, all_tables_size); |
645 | arch_reserve_mem_area(acpi_tables_addr, all_tables_size); | 645 | arch_reserve_mem_area(acpi_tables_addr, all_tables_size); |
646 | 646 | ||
647 | p = early_ioremap(acpi_tables_addr, all_tables_size); | 647 | p = early_ioremap(acpi_tables_addr, all_tables_size); |
@@ -1555,7 +1555,7 @@ int acpi_check_resource_conflict(const struct resource *res) | |||
1555 | else | 1555 | else |
1556 | space_id = ACPI_ADR_SPACE_SYSTEM_MEMORY; | 1556 | space_id = ACPI_ADR_SPACE_SYSTEM_MEMORY; |
1557 | 1557 | ||
1558 | length = res->end - res->start + 1; | 1558 | length = resource_size(res); |
1559 | if (acpi_enforce_resources != ENFORCE_RESOURCES_NO) | 1559 | if (acpi_enforce_resources != ENFORCE_RESOURCES_NO) |
1560 | warn = 1; | 1560 | warn = 1; |
1561 | clash = acpi_check_address_range(space_id, res->start, length, warn); | 1561 | clash = acpi_check_address_range(space_id, res->start, length, warn); |
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 6ae5e440436e..4241b8d844eb 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c | |||
@@ -201,8 +201,8 @@ static acpi_status acpi_pci_query_osc(struct acpi_pci_root *root, | |||
201 | *control &= OSC_PCI_CONTROL_MASKS; | 201 | *control &= OSC_PCI_CONTROL_MASKS; |
202 | capbuf[OSC_CONTROL_TYPE] = *control | root->osc_control_set; | 202 | capbuf[OSC_CONTROL_TYPE] = *control | root->osc_control_set; |
203 | } else { | 203 | } else { |
204 | /* Run _OSC query for all possible controls. */ | 204 | /* Run _OSC query only with existing controls. */ |
205 | capbuf[OSC_CONTROL_TYPE] = OSC_PCI_CONTROL_MASKS; | 205 | capbuf[OSC_CONTROL_TYPE] = root->osc_control_set; |
206 | } | 206 | } |
207 | 207 | ||
208 | status = acpi_pci_run_osc(root->device->handle, capbuf, &result); | 208 | status = acpi_pci_run_osc(root->device->handle, capbuf, &result); |
diff --git a/drivers/acpi/processor_thermal.c b/drivers/acpi/processor_thermal.c index 641b5450a0db..e8e652710e65 100644 --- a/drivers/acpi/processor_thermal.c +++ b/drivers/acpi/processor_thermal.c | |||
@@ -218,9 +218,13 @@ processor_get_max_state(struct thermal_cooling_device *cdev, | |||
218 | unsigned long *state) | 218 | unsigned long *state) |
219 | { | 219 | { |
220 | struct acpi_device *device = cdev->devdata; | 220 | struct acpi_device *device = cdev->devdata; |
221 | struct acpi_processor *pr = acpi_driver_data(device); | 221 | struct acpi_processor *pr; |
222 | 222 | ||
223 | if (!device || !pr) | 223 | if (!device) |
224 | return -EINVAL; | ||
225 | |||
226 | pr = acpi_driver_data(device); | ||
227 | if (!pr) | ||
224 | return -EINVAL; | 228 | return -EINVAL; |
225 | 229 | ||
226 | *state = acpi_processor_max_state(pr); | 230 | *state = acpi_processor_max_state(pr); |
@@ -232,9 +236,13 @@ processor_get_cur_state(struct thermal_cooling_device *cdev, | |||
232 | unsigned long *cur_state) | 236 | unsigned long *cur_state) |
233 | { | 237 | { |
234 | struct acpi_device *device = cdev->devdata; | 238 | struct acpi_device *device = cdev->devdata; |
235 | struct acpi_processor *pr = acpi_driver_data(device); | 239 | struct acpi_processor *pr; |
236 | 240 | ||
237 | if (!device || !pr) | 241 | if (!device) |
242 | return -EINVAL; | ||
243 | |||
244 | pr = acpi_driver_data(device); | ||
245 | if (!pr) | ||
238 | return -EINVAL; | 246 | return -EINVAL; |
239 | 247 | ||
240 | *cur_state = cpufreq_get_cur_state(pr->id); | 248 | *cur_state = cpufreq_get_cur_state(pr->id); |
@@ -248,11 +256,15 @@ processor_set_cur_state(struct thermal_cooling_device *cdev, | |||
248 | unsigned long state) | 256 | unsigned long state) |
249 | { | 257 | { |
250 | struct acpi_device *device = cdev->devdata; | 258 | struct acpi_device *device = cdev->devdata; |
251 | struct acpi_processor *pr = acpi_driver_data(device); | 259 | struct acpi_processor *pr; |
252 | int result = 0; | 260 | int result = 0; |
253 | int max_pstate; | 261 | int max_pstate; |
254 | 262 | ||
255 | if (!device || !pr) | 263 | if (!device) |
264 | return -EINVAL; | ||
265 | |||
266 | pr = acpi_driver_data(device); | ||
267 | if (!pr) | ||
256 | return -EINVAL; | 268 | return -EINVAL; |
257 | 269 | ||
258 | max_pstate = cpufreq_get_max_state(pr->id); | 270 | max_pstate = cpufreq_get_max_state(pr->id); |
diff --git a/drivers/acpi/processor_throttling.c b/drivers/acpi/processor_throttling.c index 1d02b7b5ade0..e7dd2c1fee79 100644 --- a/drivers/acpi/processor_throttling.c +++ b/drivers/acpi/processor_throttling.c | |||
@@ -211,9 +211,10 @@ err_ret: | |||
211 | */ | 211 | */ |
212 | void acpi_processor_throttling_init(void) | 212 | void acpi_processor_throttling_init(void) |
213 | { | 213 | { |
214 | if (acpi_processor_update_tsd_coord()) | 214 | if (acpi_processor_update_tsd_coord()) { |
215 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 215 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
216 | "Assume no T-state coordination\n")); | 216 | "Assume no T-state coordination\n")); |
217 | } | ||
217 | 218 | ||
218 | return; | 219 | return; |
219 | } | 220 | } |
diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index 8470771e5eae..a33821ca3895 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c | |||
@@ -723,9 +723,19 @@ static int thermal_get_trend(struct thermal_zone_device *thermal, | |||
723 | return -EINVAL; | 723 | return -EINVAL; |
724 | 724 | ||
725 | if (type == THERMAL_TRIP_ACTIVE) { | 725 | if (type == THERMAL_TRIP_ACTIVE) { |
726 | /* aggressive active cooling */ | 726 | unsigned long trip_temp; |
727 | *trend = THERMAL_TREND_RAISING; | 727 | unsigned long temp = KELVIN_TO_MILLICELSIUS(tz->temperature, |
728 | return 0; | 728 | tz->kelvin_offset); |
729 | if (thermal_get_trip_temp(thermal, trip, &trip_temp)) | ||
730 | return -EINVAL; | ||
731 | |||
732 | if (temp > trip_temp) { | ||
733 | *trend = THERMAL_TREND_RAISING; | ||
734 | return 0; | ||
735 | } else { | ||
736 | /* Fall back on default trend */ | ||
737 | return -EINVAL; | ||
738 | } | ||
729 | } | 739 | } |
730 | 740 | ||
731 | /* | 741 | /* |
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 313f959413dc..c3932d0876e0 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c | |||
@@ -167,7 +167,8 @@ struct acpi_video_device_flags { | |||
167 | u8 dvi:1; | 167 | u8 dvi:1; |
168 | u8 bios:1; | 168 | u8 bios:1; |
169 | u8 unknown:1; | 169 | u8 unknown:1; |
170 | u8 reserved:2; | 170 | u8 notify:1; |
171 | u8 reserved:1; | ||
171 | }; | 172 | }; |
172 | 173 | ||
173 | struct acpi_video_device_cap { | 174 | struct acpi_video_device_cap { |
@@ -222,7 +223,7 @@ static int acpi_video_device_lcd_set_level(struct acpi_video_device *device, | |||
222 | int level); | 223 | int level); |
223 | static int acpi_video_device_lcd_get_level_current( | 224 | static int acpi_video_device_lcd_get_level_current( |
224 | struct acpi_video_device *device, | 225 | struct acpi_video_device *device, |
225 | unsigned long long *level, int init); | 226 | unsigned long long *level, bool raw); |
226 | static int acpi_video_get_next_level(struct acpi_video_device *device, | 227 | static int acpi_video_get_next_level(struct acpi_video_device *device, |
227 | u32 level_current, u32 event); | 228 | u32 level_current, u32 event); |
228 | static int acpi_video_switch_brightness(struct acpi_video_device *device, | 229 | static int acpi_video_switch_brightness(struct acpi_video_device *device, |
@@ -236,7 +237,7 @@ static int acpi_video_get_brightness(struct backlight_device *bd) | |||
236 | struct acpi_video_device *vd = | 237 | struct acpi_video_device *vd = |
237 | (struct acpi_video_device *)bl_get_data(bd); | 238 | (struct acpi_video_device *)bl_get_data(bd); |
238 | 239 | ||
239 | if (acpi_video_device_lcd_get_level_current(vd, &cur_level, 0)) | 240 | if (acpi_video_device_lcd_get_level_current(vd, &cur_level, false)) |
240 | return -EINVAL; | 241 | return -EINVAL; |
241 | for (i = 2; i < vd->brightness->count; i++) { | 242 | for (i = 2; i < vd->brightness->count; i++) { |
242 | if (vd->brightness->levels[i] == cur_level) | 243 | if (vd->brightness->levels[i] == cur_level) |
@@ -281,7 +282,7 @@ static int video_get_cur_state(struct thermal_cooling_device *cooling_dev, unsig | |||
281 | unsigned long long level; | 282 | unsigned long long level; |
282 | int offset; | 283 | int offset; |
283 | 284 | ||
284 | if (acpi_video_device_lcd_get_level_current(video, &level, 0)) | 285 | if (acpi_video_device_lcd_get_level_current(video, &level, false)) |
285 | return -EINVAL; | 286 | return -EINVAL; |
286 | for (offset = 2; offset < video->brightness->count; offset++) | 287 | for (offset = 2; offset < video->brightness->count; offset++) |
287 | if (level == video->brightness->levels[offset]) { | 288 | if (level == video->brightness->levels[offset]) { |
@@ -447,12 +448,45 @@ static struct dmi_system_id video_dmi_table[] __initdata = { | |||
447 | DMI_MATCH(DMI_PRODUCT_NAME, "HP Folio 13 - 2000 Notebook PC"), | 448 | DMI_MATCH(DMI_PRODUCT_NAME, "HP Folio 13 - 2000 Notebook PC"), |
448 | }, | 449 | }, |
449 | }, | 450 | }, |
451 | { | ||
452 | .callback = video_ignore_initial_backlight, | ||
453 | .ident = "HP Pavilion dm4", | ||
454 | .matches = { | ||
455 | DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"), | ||
456 | DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dm4 Notebook PC"), | ||
457 | }, | ||
458 | }, | ||
450 | {} | 459 | {} |
451 | }; | 460 | }; |
452 | 461 | ||
462 | static unsigned long long | ||
463 | acpi_video_bqc_value_to_level(struct acpi_video_device *device, | ||
464 | unsigned long long bqc_value) | ||
465 | { | ||
466 | unsigned long long level; | ||
467 | |||
468 | if (device->brightness->flags._BQC_use_index) { | ||
469 | /* | ||
470 | * _BQC returns an index that doesn't account for | ||
471 | * the first 2 items with special meaning, so we need | ||
472 | * to compensate for that by offsetting ourselves | ||
473 | */ | ||
474 | if (device->brightness->flags._BCL_reversed) | ||
475 | bqc_value = device->brightness->count - 3 - bqc_value; | ||
476 | |||
477 | level = device->brightness->levels[bqc_value + 2]; | ||
478 | } else { | ||
479 | level = bqc_value; | ||
480 | } | ||
481 | |||
482 | level += bqc_offset_aml_bug_workaround; | ||
483 | |||
484 | return level; | ||
485 | } | ||
486 | |||
453 | static int | 487 | static int |
454 | acpi_video_device_lcd_get_level_current(struct acpi_video_device *device, | 488 | acpi_video_device_lcd_get_level_current(struct acpi_video_device *device, |
455 | unsigned long long *level, int init) | 489 | unsigned long long *level, bool raw) |
456 | { | 490 | { |
457 | acpi_status status = AE_OK; | 491 | acpi_status status = AE_OK; |
458 | int i; | 492 | int i; |
@@ -463,29 +497,30 @@ acpi_video_device_lcd_get_level_current(struct acpi_video_device *device, | |||
463 | status = acpi_evaluate_integer(device->dev->handle, buf, | 497 | status = acpi_evaluate_integer(device->dev->handle, buf, |
464 | NULL, level); | 498 | NULL, level); |
465 | if (ACPI_SUCCESS(status)) { | 499 | if (ACPI_SUCCESS(status)) { |
466 | if (device->brightness->flags._BQC_use_index) { | 500 | if (raw) { |
467 | if (device->brightness->flags._BCL_reversed) | 501 | /* |
468 | *level = device->brightness->count | 502 | * Caller has indicated he wants the raw |
469 | - 3 - (*level); | 503 | * value returned by _BQC, so don't furtherly |
470 | *level = device->brightness->levels[*level + 2]; | 504 | * mess with the value. |
471 | 505 | */ | |
506 | return 0; | ||
472 | } | 507 | } |
473 | *level += bqc_offset_aml_bug_workaround; | 508 | |
509 | *level = acpi_video_bqc_value_to_level(device, *level); | ||
510 | |||
474 | for (i = 2; i < device->brightness->count; i++) | 511 | for (i = 2; i < device->brightness->count; i++) |
475 | if (device->brightness->levels[i] == *level) { | 512 | if (device->brightness->levels[i] == *level) { |
476 | device->brightness->curr = *level; | 513 | device->brightness->curr = *level; |
477 | return 0; | 514 | return 0; |
478 | } | 515 | } |
479 | if (!init) { | 516 | /* |
480 | /* | 517 | * BQC returned an invalid level. |
481 | * BQC returned an invalid level. | 518 | * Stop using it. |
482 | * Stop using it. | 519 | */ |
483 | */ | 520 | ACPI_WARNING((AE_INFO, |
484 | ACPI_WARNING((AE_INFO, | 521 | "%s returned an invalid level", |
485 | "%s returned an invalid level", | 522 | buf)); |
486 | buf)); | 523 | device->cap._BQC = device->cap._BCQ = 0; |
487 | device->cap._BQC = device->cap._BCQ = 0; | ||
488 | } | ||
489 | } else { | 524 | } else { |
490 | /* Fixme: | 525 | /* Fixme: |
491 | * should we return an error or ignore this failure? | 526 | * should we return an error or ignore this failure? |
@@ -598,6 +633,56 @@ acpi_video_cmp_level(const void *a, const void *b) | |||
598 | } | 633 | } |
599 | 634 | ||
600 | /* | 635 | /* |
636 | * Decides if _BQC/_BCQ for this system is usable | ||
637 | * | ||
638 | * We do this by changing the level first and then read out the current | ||
639 | * brightness level, if the value does not match, find out if it is using | ||
640 | * index. If not, clear the _BQC/_BCQ capability. | ||
641 | */ | ||
642 | static int acpi_video_bqc_quirk(struct acpi_video_device *device, | ||
643 | int max_level, int current_level) | ||
644 | { | ||
645 | struct acpi_video_device_brightness *br = device->brightness; | ||
646 | int result; | ||
647 | unsigned long long level; | ||
648 | int test_level; | ||
649 | |||
650 | /* don't mess with existing known broken systems */ | ||
651 | if (bqc_offset_aml_bug_workaround) | ||
652 | return 0; | ||
653 | |||
654 | /* | ||
655 | * Some systems always report current brightness level as maximum | ||
656 | * through _BQC, we need to test another value for them. | ||
657 | */ | ||
658 | test_level = current_level == max_level ? br->levels[2] : max_level; | ||
659 | |||
660 | result = acpi_video_device_lcd_set_level(device, test_level); | ||
661 | if (result) | ||
662 | return result; | ||
663 | |||
664 | result = acpi_video_device_lcd_get_level_current(device, &level, true); | ||
665 | if (result) | ||
666 | return result; | ||
667 | |||
668 | if (level != test_level) { | ||
669 | /* buggy _BQC found, need to find out if it uses index */ | ||
670 | if (level < br->count) { | ||
671 | if (br->flags._BCL_reversed) | ||
672 | level = br->count - 3 - level; | ||
673 | if (br->levels[level + 2] == test_level) | ||
674 | br->flags._BQC_use_index = 1; | ||
675 | } | ||
676 | |||
677 | if (!br->flags._BQC_use_index) | ||
678 | device->cap._BQC = device->cap._BCQ = 0; | ||
679 | } | ||
680 | |||
681 | return 0; | ||
682 | } | ||
683 | |||
684 | |||
685 | /* | ||
601 | * Arg: | 686 | * Arg: |
602 | * device : video output device (LCD, CRT, ..) | 687 | * device : video output device (LCD, CRT, ..) |
603 | * | 688 | * |
@@ -703,42 +788,36 @@ acpi_video_init_brightness(struct acpi_video_device *device) | |||
703 | if (!device->cap._BQC) | 788 | if (!device->cap._BQC) |
704 | goto set_level; | 789 | goto set_level; |
705 | 790 | ||
706 | result = acpi_video_device_lcd_get_level_current(device, &level_old, 1); | 791 | result = acpi_video_device_lcd_get_level_current(device, |
707 | if (result) | 792 | &level_old, true); |
708 | goto out_free_levels; | ||
709 | |||
710 | /* | ||
711 | * Set the level to maximum and check if _BQC uses indexed value | ||
712 | */ | ||
713 | result = acpi_video_device_lcd_set_level(device, max_level); | ||
714 | if (result) | 793 | if (result) |
715 | goto out_free_levels; | 794 | goto out_free_levels; |
716 | 795 | ||
717 | result = acpi_video_device_lcd_get_level_current(device, &level, 0); | 796 | result = acpi_video_bqc_quirk(device, max_level, level_old); |
718 | if (result) | 797 | if (result) |
719 | goto out_free_levels; | 798 | goto out_free_levels; |
799 | /* | ||
800 | * cap._BQC may get cleared due to _BQC is found to be broken | ||
801 | * in acpi_video_bqc_quirk, so check again here. | ||
802 | */ | ||
803 | if (!device->cap._BQC) | ||
804 | goto set_level; | ||
720 | 805 | ||
721 | br->flags._BQC_use_index = (level == max_level ? 0 : 1); | 806 | if (use_bios_initial_backlight) { |
722 | 807 | level = acpi_video_bqc_value_to_level(device, level_old); | |
723 | if (!br->flags._BQC_use_index) { | ||
724 | /* | 808 | /* |
725 | * Set the backlight to the initial state. | 809 | * On some buggy laptops, _BQC returns an uninitialized |
726 | * On some buggy laptops, _BQC returns an uninitialized value | 810 | * value when invoked for the first time, i.e. |
727 | * when invoked for the first time, i.e. level_old is invalid. | 811 | * level_old is invalid (no matter whether it's a level |
728 | * set the backlight to max_level in this case | 812 | * or an index). Set the backlight to max_level in this case. |
729 | */ | 813 | */ |
730 | if (use_bios_initial_backlight) { | 814 | for (i = 2; i < br->count; i++) |
731 | for (i = 2; i < br->count; i++) | 815 | if (level_old == br->levels[i]) |
732 | if (level_old == br->levels[i]) | 816 | break; |
733 | level = level_old; | 817 | if (i == br->count) |
734 | } | 818 | level = max_level; |
735 | goto set_level; | ||
736 | } | 819 | } |
737 | 820 | ||
738 | if (br->flags._BCL_reversed) | ||
739 | level_old = (br->count - 1) - level_old; | ||
740 | level = br->levels[level_old]; | ||
741 | |||
742 | set_level: | 821 | set_level: |
743 | result = acpi_video_device_lcd_set_level(device, level); | 822 | result = acpi_video_device_lcd_set_level(device, level); |
744 | if (result) | 823 | if (result) |
@@ -996,53 +1075,51 @@ acpi_video_bus_get_one_device(struct acpi_device *device, | |||
996 | struct acpi_video_device *data; | 1075 | struct acpi_video_device *data; |
997 | struct acpi_video_device_attrib* attribute; | 1076 | struct acpi_video_device_attrib* attribute; |
998 | 1077 | ||
999 | if (!device || !video) | ||
1000 | return -EINVAL; | ||
1001 | |||
1002 | status = | 1078 | status = |
1003 | acpi_evaluate_integer(device->handle, "_ADR", NULL, &device_id); | 1079 | acpi_evaluate_integer(device->handle, "_ADR", NULL, &device_id); |
1004 | if (ACPI_SUCCESS(status)) { | 1080 | /* Some device omits _ADR, we skip them instead of fail */ |
1005 | 1081 | if (ACPI_FAILURE(status)) | |
1006 | data = kzalloc(sizeof(struct acpi_video_device), GFP_KERNEL); | 1082 | return 0; |
1007 | if (!data) | ||
1008 | return -ENOMEM; | ||
1009 | |||
1010 | strcpy(acpi_device_name(device), ACPI_VIDEO_DEVICE_NAME); | ||
1011 | strcpy(acpi_device_class(device), ACPI_VIDEO_CLASS); | ||
1012 | device->driver_data = data; | ||
1013 | |||
1014 | data->device_id = device_id; | ||
1015 | data->video = video; | ||
1016 | data->dev = device; | ||
1017 | 1083 | ||
1018 | attribute = acpi_video_get_device_attr(video, device_id); | 1084 | data = kzalloc(sizeof(struct acpi_video_device), GFP_KERNEL); |
1085 | if (!data) | ||
1086 | return -ENOMEM; | ||
1019 | 1087 | ||
1020 | if((attribute != NULL) && attribute->device_id_scheme) { | 1088 | strcpy(acpi_device_name(device), ACPI_VIDEO_DEVICE_NAME); |
1021 | switch (attribute->display_type) { | 1089 | strcpy(acpi_device_class(device), ACPI_VIDEO_CLASS); |
1022 | case ACPI_VIDEO_DISPLAY_CRT: | 1090 | device->driver_data = data; |
1023 | data->flags.crt = 1; | 1091 | |
1024 | break; | 1092 | data->device_id = device_id; |
1025 | case ACPI_VIDEO_DISPLAY_TV: | 1093 | data->video = video; |
1026 | data->flags.tvout = 1; | 1094 | data->dev = device; |
1027 | break; | 1095 | |
1028 | case ACPI_VIDEO_DISPLAY_DVI: | 1096 | attribute = acpi_video_get_device_attr(video, device_id); |
1029 | data->flags.dvi = 1; | 1097 | |
1030 | break; | 1098 | if((attribute != NULL) && attribute->device_id_scheme) { |
1031 | case ACPI_VIDEO_DISPLAY_LCD: | 1099 | switch (attribute->display_type) { |
1032 | data->flags.lcd = 1; | 1100 | case ACPI_VIDEO_DISPLAY_CRT: |
1033 | break; | 1101 | data->flags.crt = 1; |
1034 | default: | 1102 | break; |
1035 | data->flags.unknown = 1; | 1103 | case ACPI_VIDEO_DISPLAY_TV: |
1036 | break; | 1104 | data->flags.tvout = 1; |
1037 | } | 1105 | break; |
1038 | if(attribute->bios_can_detect) | 1106 | case ACPI_VIDEO_DISPLAY_DVI: |
1039 | data->flags.bios = 1; | 1107 | data->flags.dvi = 1; |
1040 | } else { | 1108 | break; |
1041 | /* Check for legacy IDs */ | 1109 | case ACPI_VIDEO_DISPLAY_LCD: |
1042 | device_type = acpi_video_get_device_type(video, | 1110 | data->flags.lcd = 1; |
1043 | device_id); | 1111 | break; |
1044 | /* Ignore bits 16 and 18-20 */ | 1112 | default: |
1045 | switch (device_type & 0xffe2ffff) { | 1113 | data->flags.unknown = 1; |
1114 | break; | ||
1115 | } | ||
1116 | if(attribute->bios_can_detect) | ||
1117 | data->flags.bios = 1; | ||
1118 | } else { | ||
1119 | /* Check for legacy IDs */ | ||
1120 | device_type = acpi_video_get_device_type(video, device_id); | ||
1121 | /* Ignore bits 16 and 18-20 */ | ||
1122 | switch (device_type & 0xffe2ffff) { | ||
1046 | case ACPI_VIDEO_DISPLAY_LEGACY_MONITOR: | 1123 | case ACPI_VIDEO_DISPLAY_LEGACY_MONITOR: |
1047 | data->flags.crt = 1; | 1124 | data->flags.crt = 1; |
1048 | break; | 1125 | break; |
@@ -1054,34 +1131,24 @@ acpi_video_bus_get_one_device(struct acpi_device *device, | |||
1054 | break; | 1131 | break; |
1055 | default: | 1132 | default: |
1056 | data->flags.unknown = 1; | 1133 | data->flags.unknown = 1; |
1057 | } | ||
1058 | } | 1134 | } |
1135 | } | ||
1059 | 1136 | ||
1060 | acpi_video_device_bind(video, data); | 1137 | acpi_video_device_bind(video, data); |
1061 | acpi_video_device_find_cap(data); | 1138 | acpi_video_device_find_cap(data); |
1062 | |||
1063 | status = acpi_install_notify_handler(device->handle, | ||
1064 | ACPI_DEVICE_NOTIFY, | ||
1065 | acpi_video_device_notify, | ||
1066 | data); | ||
1067 | if (ACPI_FAILURE(status)) { | ||
1068 | printk(KERN_ERR PREFIX | ||
1069 | "Error installing notify handler\n"); | ||
1070 | if(data->brightness) | ||
1071 | kfree(data->brightness->levels); | ||
1072 | kfree(data->brightness); | ||
1073 | kfree(data); | ||
1074 | return -ENODEV; | ||
1075 | } | ||
1076 | 1139 | ||
1077 | mutex_lock(&video->device_list_lock); | 1140 | status = acpi_install_notify_handler(device->handle, ACPI_DEVICE_NOTIFY, |
1078 | list_add_tail(&data->entry, &video->video_device_list); | 1141 | acpi_video_device_notify, data); |
1079 | mutex_unlock(&video->device_list_lock); | 1142 | if (ACPI_FAILURE(status)) |
1143 | dev_err(&device->dev, "Error installing notify handler\n"); | ||
1144 | else | ||
1145 | data->flags.notify = 1; | ||
1080 | 1146 | ||
1081 | return 0; | 1147 | mutex_lock(&video->device_list_lock); |
1082 | } | 1148 | list_add_tail(&data->entry, &video->video_device_list); |
1149 | mutex_unlock(&video->device_list_lock); | ||
1083 | 1150 | ||
1084 | return -ENOENT; | 1151 | return status; |
1085 | } | 1152 | } |
1086 | 1153 | ||
1087 | /* | 1154 | /* |
@@ -1268,7 +1335,8 @@ acpi_video_switch_brightness(struct acpi_video_device *device, int event) | |||
1268 | goto out; | 1335 | goto out; |
1269 | 1336 | ||
1270 | result = acpi_video_device_lcd_get_level_current(device, | 1337 | result = acpi_video_device_lcd_get_level_current(device, |
1271 | &level_current, 0); | 1338 | &level_current, |
1339 | false); | ||
1272 | if (result) | 1340 | if (result) |
1273 | goto out; | 1341 | goto out; |
1274 | 1342 | ||
@@ -1373,9 +1441,8 @@ acpi_video_bus_get_devices(struct acpi_video_bus *video, | |||
1373 | 1441 | ||
1374 | status = acpi_video_bus_get_one_device(dev, video); | 1442 | status = acpi_video_bus_get_one_device(dev, video); |
1375 | if (status) { | 1443 | if (status) { |
1376 | printk(KERN_WARNING PREFIX | 1444 | dev_err(&dev->dev, "Can't attach device\n"); |
1377 | "Can't attach device\n"); | 1445 | break; |
1378 | continue; | ||
1379 | } | 1446 | } |
1380 | } | 1447 | } |
1381 | return status; | 1448 | return status; |
@@ -1388,13 +1455,14 @@ static int acpi_video_bus_put_one_device(struct acpi_video_device *device) | |||
1388 | if (!device || !device->video) | 1455 | if (!device || !device->video) |
1389 | return -ENOENT; | 1456 | return -ENOENT; |
1390 | 1457 | ||
1391 | status = acpi_remove_notify_handler(device->dev->handle, | 1458 | if (device->flags.notify) { |
1392 | ACPI_DEVICE_NOTIFY, | 1459 | status = acpi_remove_notify_handler(device->dev->handle, |
1393 | acpi_video_device_notify); | 1460 | ACPI_DEVICE_NOTIFY, acpi_video_device_notify); |
1394 | if (ACPI_FAILURE(status)) { | 1461 | if (ACPI_FAILURE(status)) |
1395 | printk(KERN_WARNING PREFIX | 1462 | dev_err(&device->dev->dev, |
1396 | "Can't remove video notify handler\n"); | 1463 | "Can't remove video notify handler\n"); |
1397 | } | 1464 | } |
1465 | |||
1398 | if (device->backlight) { | 1466 | if (device->backlight) { |
1399 | backlight_device_unregister(device->backlight); | 1467 | backlight_device_unregister(device->backlight); |
1400 | device->backlight = NULL; | 1468 | device->backlight = NULL; |
@@ -1676,7 +1744,7 @@ static int acpi_video_bus_add(struct acpi_device *device) | |||
1676 | 1744 | ||
1677 | error = acpi_video_bus_get_devices(video, device); | 1745 | error = acpi_video_bus_get_devices(video, device); |
1678 | if (error) | 1746 | if (error) |
1679 | goto err_free_video; | 1747 | goto err_put_video; |
1680 | 1748 | ||
1681 | video->input = input = input_allocate_device(); | 1749 | video->input = input = input_allocate_device(); |
1682 | if (!input) { | 1750 | if (!input) { |