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 | ||