Skip to content

Commit

Permalink
thinkpad-acpi: find ACPI video device by synthetic HID
Browse files Browse the repository at this point in the history
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 <[email protected]>
Signed-off-by: Matthew Garrett <[email protected]>
  • Loading branch information
hmh authored and Matthew Garrett committed Aug 16, 2010
1 parent 52d7ee5 commit 122f267
Showing 1 changed file with 12 additions and 40 deletions.
52 changes: 12 additions & 40 deletions drivers/platform/x86/thinkpad_acpi.c
Original file line number Diff line number Diff line change
Expand Up @@ -6080,13 +6080,18 @@ static struct backlight_ops ibm_backlight_data = {

/* --------------------------------------------------------------------- */

/*
* Call _BCL method of video device. On some ThinkPads this will
* switch the firmware to the ACPI brightness control mode.
*/

static int __init tpacpi_query_bcl_levels(acpi_handle handle)
{
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
union acpi_object *obj;
int rc;

if (ACPI_SUCCESS(acpi_evaluate_object(handle, NULL, NULL, &buffer))) {
if (ACPI_SUCCESS(acpi_evaluate_object(handle, "_BCL", NULL, &buffer))) {
obj = (union acpi_object *)buffer.pointer;
if (!obj || (obj->type != ACPI_TYPE_PACKAGE)) {
printk(TPACPI_ERR "Unknown _BCL data, "
Expand All @@ -6103,55 +6108,22 @@ static int __init tpacpi_query_bcl_levels(acpi_handle handle)
return rc;
}

static acpi_status __init tpacpi_acpi_walk_find_bcl(acpi_handle handle,
u32 lvl, void *context, void **rv)
{
char name[ACPI_PATH_SEGMENT_LENGTH];
struct acpi_buffer buffer = { sizeof(name), &name };

if (ACPI_SUCCESS(acpi_get_name(handle, ACPI_SINGLE_NAME, &buffer)) &&
!strncmp("_BCL", name, sizeof(name) - 1)) {
BUG_ON(!rv || !*rv);
**(int **)rv = tpacpi_query_bcl_levels(handle);
return AE_CTRL_TERMINATE;
} else {
return AE_OK;
}
}

/*
* Returns 0 (no ACPI _BCL or _BCL invalid), or size of brightness map
*/
static unsigned int __init tpacpi_check_std_acpi_brightness_support(void)
{
int status;
acpi_handle video_device;
int bcl_levels = 0;
void *bcl_ptr = &bcl_levels;

if (!vid_handle)
TPACPI_ACPIHANDLE_INIT(vid);
tpacpi_acpi_handle_locate("video", ACPI_VIDEO_HID, &video_device);
if (video_device)
bcl_levels = tpacpi_query_bcl_levels(video_device);

if (!vid_handle)
return 0;

/*
* Search for a _BCL method, and execute it. This is safe on all
* ThinkPads, and as a side-effect, _BCL will place a Lenovo Vista
* BIOS in ACPI backlight control mode. We do NOT have to care
* about calling the _BCL method in an enabled video device, any
* will do for our purposes.
*/
tp_features.bright_acpimode = (bcl_levels > 0);

status = acpi_walk_namespace(ACPI_TYPE_METHOD, vid_handle, 3,
tpacpi_acpi_walk_find_bcl, NULL, NULL,
&bcl_ptr);

if (ACPI_SUCCESS(status) && bcl_levels > 2) {
tp_features.bright_acpimode = 1;
return bcl_levels - 2;
}

return 0;
return (bcl_levels > 2) ? (bcl_levels - 2) : 0;
}

/*
Expand Down

0 comments on commit 122f267

Please sign in to comment.