diff options
author | Henrique de Moraes Holschuh <hmh@hmh.eng.br> | 2010-08-09 22:48:18 -0400 |
---|---|---|
committer | Matthew Garrett <mjg@redhat.com> | 2010-08-16 11:54:47 -0400 |
commit | 122f26726b5e16174bf8a707df14be1d93c49d62 (patch) | |
tree | 7e71e1fa0c2dda912796f1cb9fd1f1f71bb872e4 /drivers | |
parent | 52d7ee558d3babb4918eed6769f593adc1b6616e (diff) |
thinkpad-acpi: find ACPI video device by synthetic HID
The Linux ACPI core locates the ACPI video devices for us and marks them
with ACPI_VIDEO_HID. Use that information to locate the video device
instead of a half-baked hunt for _BCL.
This uncouples the detection of the number of backlight brightness
levels on ThinkPads from the ACPI paths in vid_handle.
With this change, the driver should be able to always detect whether the
ThinkPad uses a 8-level or 16-level brightness scale even on newer
models for which the vid_handle paths have not been updated yet.
It will skip deactivated devices in the ACPI device tree, which is a
change in behaviour.
Signed-off-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
Signed-off-by: Matthew Garrett <mjg@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/platform/x86/thinkpad_acpi.c | 52 |
1 files changed, 12 insertions, 40 deletions
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index 5d6119bed00c..9d6fc4c7c08e 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c | |||
@@ -6080,13 +6080,18 @@ static struct backlight_ops ibm_backlight_data = { | |||
6080 | 6080 | ||
6081 | /* --------------------------------------------------------------------- */ | 6081 | /* --------------------------------------------------------------------- */ |
6082 | 6082 | ||
6083 | /* | ||
6084 | * Call _BCL method of video device. On some ThinkPads this will | ||
6085 | * switch the firmware to the ACPI brightness control mode. | ||
6086 | */ | ||
6087 | |||
6083 | static int __init tpacpi_query_bcl_levels(acpi_handle handle) | 6088 | static int __init tpacpi_query_bcl_levels(acpi_handle handle) |
6084 | { | 6089 | { |
6085 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | 6090 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; |
6086 | union acpi_object *obj; | 6091 | union acpi_object *obj; |
6087 | int rc; | 6092 | int rc; |
6088 | 6093 | ||
6089 | if (ACPI_SUCCESS(acpi_evaluate_object(handle, NULL, NULL, &buffer))) { | 6094 | if (ACPI_SUCCESS(acpi_evaluate_object(handle, "_BCL", NULL, &buffer))) { |
6090 | obj = (union acpi_object *)buffer.pointer; | 6095 | obj = (union acpi_object *)buffer.pointer; |
6091 | if (!obj || (obj->type != ACPI_TYPE_PACKAGE)) { | 6096 | if (!obj || (obj->type != ACPI_TYPE_PACKAGE)) { |
6092 | printk(TPACPI_ERR "Unknown _BCL data, " | 6097 | printk(TPACPI_ERR "Unknown _BCL data, " |
@@ -6103,55 +6108,22 @@ static int __init tpacpi_query_bcl_levels(acpi_handle handle) | |||
6103 | return rc; | 6108 | return rc; |
6104 | } | 6109 | } |
6105 | 6110 | ||
6106 | static acpi_status __init tpacpi_acpi_walk_find_bcl(acpi_handle handle, | ||
6107 | u32 lvl, void *context, void **rv) | ||
6108 | { | ||
6109 | char name[ACPI_PATH_SEGMENT_LENGTH]; | ||
6110 | struct acpi_buffer buffer = { sizeof(name), &name }; | ||
6111 | |||
6112 | if (ACPI_SUCCESS(acpi_get_name(handle, ACPI_SINGLE_NAME, &buffer)) && | ||
6113 | !strncmp("_BCL", name, sizeof(name) - 1)) { | ||
6114 | BUG_ON(!rv || !*rv); | ||
6115 | **(int **)rv = tpacpi_query_bcl_levels(handle); | ||
6116 | return AE_CTRL_TERMINATE; | ||
6117 | } else { | ||
6118 | return AE_OK; | ||
6119 | } | ||
6120 | } | ||
6121 | 6111 | ||
6122 | /* | 6112 | /* |
6123 | * Returns 0 (no ACPI _BCL or _BCL invalid), or size of brightness map | 6113 | * Returns 0 (no ACPI _BCL or _BCL invalid), or size of brightness map |
6124 | */ | 6114 | */ |
6125 | static unsigned int __init tpacpi_check_std_acpi_brightness_support(void) | 6115 | static unsigned int __init tpacpi_check_std_acpi_brightness_support(void) |
6126 | { | 6116 | { |
6127 | int status; | 6117 | acpi_handle video_device; |
6128 | int bcl_levels = 0; | 6118 | int bcl_levels = 0; |
6129 | void *bcl_ptr = &bcl_levels; | ||
6130 | 6119 | ||
6131 | if (!vid_handle) | 6120 | tpacpi_acpi_handle_locate("video", ACPI_VIDEO_HID, &video_device); |
6132 | TPACPI_ACPIHANDLE_INIT(vid); | 6121 | if (video_device) |
6122 | bcl_levels = tpacpi_query_bcl_levels(video_device); | ||
6133 | 6123 | ||
6134 | if (!vid_handle) | 6124 | tp_features.bright_acpimode = (bcl_levels > 0); |
6135 | return 0; | ||
6136 | |||
6137 | /* | ||
6138 | * Search for a _BCL method, and execute it. This is safe on all | ||
6139 | * ThinkPads, and as a side-effect, _BCL will place a Lenovo Vista | ||
6140 | * BIOS in ACPI backlight control mode. We do NOT have to care | ||
6141 | * about calling the _BCL method in an enabled video device, any | ||
6142 | * will do for our purposes. | ||
6143 | */ | ||
6144 | 6125 | ||
6145 | status = acpi_walk_namespace(ACPI_TYPE_METHOD, vid_handle, 3, | 6126 | return (bcl_levels > 2) ? (bcl_levels - 2) : 0; |
6146 | tpacpi_acpi_walk_find_bcl, NULL, NULL, | ||
6147 | &bcl_ptr); | ||
6148 | |||
6149 | if (ACPI_SUCCESS(status) && bcl_levels > 2) { | ||
6150 | tp_features.bright_acpimode = 1; | ||
6151 | return bcl_levels - 2; | ||
6152 | } | ||
6153 | |||
6154 | return 0; | ||
6155 | } | 6127 | } |
6156 | 6128 | ||
6157 | /* | 6129 | /* |