diff options
| author | Aaron Lu <aaron.lu@intel.com> | 2013-10-11 09:27:46 -0400 |
|---|---|---|
| committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2013-10-15 19:16:05 -0400 |
| commit | 46445b6b896fd6b9fd8261f1747801dc520d2968 (patch) | |
| tree | 83d99636cbdb09c671df636aa293591de4d8a23e /drivers/platform | |
| parent | fbc9fe1b4f222a7c575e3bd8e9defe59c6190a04 (diff) | |
thinkpad-acpi: fix handle locate for video and query of _BCL
The tpacpi_acpi_handle_locate function makes use of acpi_get_devices to
locate handle for ACPI video by HID, the problem is, ACPI video node
doesn't really have HID defined(i.e. no _HID control method is defined
for video device), so.. that function would fail. This can be solved by
enhancing the callback function for acpi_get_devices, where we can use
acpi_device_hid function to check if the ACPI node corresponds to a
video controller.
In addition to that, the _BCL control method only exists under a video
output device node, not a video controller device node. So to evaluate
_BCL, we need the handle of a video output device node, which is child
of the located video controller node from tpacpi_acpi_handle_locate.
The two fix are necessary for some Thinkpad models to emit notification
on backlight hotkey press as a result of evaluation of _BCL.
Signed-off-by: Aaron Lu <aaron.lu@intel.com>
Tested-by: Igor Gnatenko <i.gnatenko.brain@gmail.com>
Acked-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers/platform')
| -rw-r--r-- | drivers/platform/x86/thinkpad_acpi.c | 31 |
1 files changed, 24 insertions, 7 deletions
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index 03ca6c139f1a..170f2788ee67 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c | |||
| @@ -700,6 +700,14 @@ static void __init drv_acpi_handle_init(const char *name, | |||
| 700 | static acpi_status __init tpacpi_acpi_handle_locate_callback(acpi_handle handle, | 700 | static acpi_status __init tpacpi_acpi_handle_locate_callback(acpi_handle handle, |
| 701 | u32 level, void *context, void **return_value) | 701 | u32 level, void *context, void **return_value) |
| 702 | { | 702 | { |
| 703 | struct acpi_device *dev; | ||
| 704 | if (!strcmp(context, "video")) { | ||
| 705 | if (acpi_bus_get_device(handle, &dev)) | ||
| 706 | return AE_OK; | ||
| 707 | if (strcmp(ACPI_VIDEO_HID, acpi_device_hid(dev))) | ||
| 708 | return AE_OK; | ||
| 709 | } | ||
| 710 | |||
| 703 | *(acpi_handle *)return_value = handle; | 711 | *(acpi_handle *)return_value = handle; |
| 704 | 712 | ||
| 705 | return AE_CTRL_TERMINATE; | 713 | return AE_CTRL_TERMINATE; |
| @@ -712,10 +720,10 @@ static void __init tpacpi_acpi_handle_locate(const char *name, | |||
| 712 | acpi_status status; | 720 | acpi_status status; |
| 713 | acpi_handle device_found; | 721 | acpi_handle device_found; |
| 714 | 722 | ||
| 715 | BUG_ON(!name || !hid || !handle); | 723 | BUG_ON(!name || !handle); |
| 716 | vdbg_printk(TPACPI_DBG_INIT, | 724 | vdbg_printk(TPACPI_DBG_INIT, |
| 717 | "trying to locate ACPI handle for %s, using HID %s\n", | 725 | "trying to locate ACPI handle for %s, using HID %s\n", |
| 718 | name, hid); | 726 | name, hid ? hid : "NULL"); |
| 719 | 727 | ||
| 720 | memset(&device_found, 0, sizeof(device_found)); | 728 | memset(&device_found, 0, sizeof(device_found)); |
| 721 | status = acpi_get_devices(hid, tpacpi_acpi_handle_locate_callback, | 729 | status = acpi_get_devices(hid, tpacpi_acpi_handle_locate_callback, |
| @@ -6090,19 +6098,28 @@ static int __init tpacpi_query_bcl_levels(acpi_handle handle) | |||
| 6090 | { | 6098 | { |
| 6091 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | 6099 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; |
| 6092 | union acpi_object *obj; | 6100 | union acpi_object *obj; |
| 6101 | struct acpi_device *device, *child; | ||
| 6093 | int rc; | 6102 | int rc; |
| 6094 | 6103 | ||
| 6095 | if (ACPI_SUCCESS(acpi_evaluate_object(handle, "_BCL", NULL, &buffer))) { | 6104 | if (acpi_bus_get_device(handle, &device)) |
| 6105 | return 0; | ||
| 6106 | |||
| 6107 | rc = 0; | ||
| 6108 | list_for_each_entry(child, &device->children, node) { | ||
| 6109 | acpi_status status = acpi_evaluate_object(child->handle, "_BCL", | ||
| 6110 | NULL, &buffer); | ||
| 6111 | if (ACPI_FAILURE(status)) | ||
| 6112 | continue; | ||
| 6113 | |||
| 6096 | obj = (union acpi_object *)buffer.pointer; | 6114 | obj = (union acpi_object *)buffer.pointer; |
| 6097 | if (!obj || (obj->type != ACPI_TYPE_PACKAGE)) { | 6115 | if (!obj || (obj->type != ACPI_TYPE_PACKAGE)) { |
| 6098 | pr_err("Unknown _BCL data, please report this to %s\n", | 6116 | pr_err("Unknown _BCL data, please report this to %s\n", |
| 6099 | TPACPI_MAIL); | 6117 | TPACPI_MAIL); |
| 6100 | rc = 0; | 6118 | rc = 0; |
| 6101 | } else { | 6119 | } else { |
| 6102 | rc = obj->package.count; | 6120 | rc = obj->package.count; |
| 6103 | } | 6121 | } |
| 6104 | } else { | 6122 | break; |
| 6105 | return 0; | ||
| 6106 | } | 6123 | } |
| 6107 | 6124 | ||
| 6108 | kfree(buffer.pointer); | 6125 | kfree(buffer.pointer); |
| @@ -6118,7 +6135,7 @@ static unsigned int __init tpacpi_check_std_acpi_brightness_support(void) | |||
| 6118 | acpi_handle video_device; | 6135 | acpi_handle video_device; |
| 6119 | int bcl_levels = 0; | 6136 | int bcl_levels = 0; |
| 6120 | 6137 | ||
| 6121 | tpacpi_acpi_handle_locate("video", ACPI_VIDEO_HID, &video_device); | 6138 | tpacpi_acpi_handle_locate("video", NULL, &video_device); |
| 6122 | if (video_device) | 6139 | if (video_device) |
| 6123 | bcl_levels = tpacpi_query_bcl_levels(video_device); | 6140 | bcl_levels = tpacpi_query_bcl_levels(video_device); |
| 6124 | 6141 | ||
