Commit 46445b6b authored by Aaron Lu's avatar Aaron Lu Committed by Rafael J. Wysocki

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: default avatarAaron Lu <aaron.lu@intel.com>
Tested-by: default avatarIgor Gnatenko <i.gnatenko.brain@gmail.com>
Acked-by: default avatarHenrique de Moraes Holschuh <hmh@hmh.eng.br>
Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
parent fbc9fe1b
...@@ -700,6 +700,14 @@ static void __init drv_acpi_handle_init(const char *name, ...@@ -700,6 +700,14 @@ static void __init drv_acpi_handle_init(const char *name,
static acpi_status __init tpacpi_acpi_handle_locate_callback(acpi_handle handle, static acpi_status __init tpacpi_acpi_handle_locate_callback(acpi_handle handle,
u32 level, void *context, void **return_value) u32 level, void *context, void **return_value)
{ {
struct acpi_device *dev;
if (!strcmp(context, "video")) {
if (acpi_bus_get_device(handle, &dev))
return AE_OK;
if (strcmp(ACPI_VIDEO_HID, acpi_device_hid(dev)))
return AE_OK;
}
*(acpi_handle *)return_value = handle; *(acpi_handle *)return_value = handle;
return AE_CTRL_TERMINATE; return AE_CTRL_TERMINATE;
...@@ -712,10 +720,10 @@ static void __init tpacpi_acpi_handle_locate(const char *name, ...@@ -712,10 +720,10 @@ static void __init tpacpi_acpi_handle_locate(const char *name,
acpi_status status; acpi_status status;
acpi_handle device_found; acpi_handle device_found;
BUG_ON(!name || !hid || !handle); BUG_ON(!name || !handle);
vdbg_printk(TPACPI_DBG_INIT, vdbg_printk(TPACPI_DBG_INIT,
"trying to locate ACPI handle for %s, using HID %s\n", "trying to locate ACPI handle for %s, using HID %s\n",
name, hid); name, hid ? hid : "NULL");
memset(&device_found, 0, sizeof(device_found)); memset(&device_found, 0, sizeof(device_found));
status = acpi_get_devices(hid, tpacpi_acpi_handle_locate_callback, 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,19 +6098,28 @@ static int __init tpacpi_query_bcl_levels(acpi_handle handle)
{ {
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
union acpi_object *obj; union acpi_object *obj;
struct acpi_device *device, *child;
int rc; int rc;
if (ACPI_SUCCESS(acpi_evaluate_object(handle, "_BCL", NULL, &buffer))) { if (acpi_bus_get_device(handle, &device))
return 0;
rc = 0;
list_for_each_entry(child, &device->children, node) {
acpi_status status = acpi_evaluate_object(child->handle, "_BCL",
NULL, &buffer);
if (ACPI_FAILURE(status))
continue;
obj = (union acpi_object *)buffer.pointer; obj = (union acpi_object *)buffer.pointer;
if (!obj || (obj->type != ACPI_TYPE_PACKAGE)) { if (!obj || (obj->type != ACPI_TYPE_PACKAGE)) {
pr_err("Unknown _BCL data, please report this to %s\n", pr_err("Unknown _BCL data, please report this to %s\n",
TPACPI_MAIL); TPACPI_MAIL);
rc = 0; rc = 0;
} else { } else {
rc = obj->package.count; rc = obj->package.count;
} }
} else { break;
return 0;
} }
kfree(buffer.pointer); kfree(buffer.pointer);
...@@ -6118,7 +6135,7 @@ static unsigned int __init tpacpi_check_std_acpi_brightness_support(void) ...@@ -6118,7 +6135,7 @@ static unsigned int __init tpacpi_check_std_acpi_brightness_support(void)
acpi_handle video_device; acpi_handle video_device;
int bcl_levels = 0; int bcl_levels = 0;
tpacpi_acpi_handle_locate("video", ACPI_VIDEO_HID, &video_device); tpacpi_acpi_handle_locate("video", NULL, &video_device);
if (video_device) if (video_device)
bcl_levels = tpacpi_query_bcl_levels(video_device); bcl_levels = tpacpi_query_bcl_levels(video_device);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment