Skip to content

Commit

Permalink
drm/i915: set DIDL using the ACPI video output device _ADR method ret…
Browse files Browse the repository at this point in the history
…urn.

we used to set the DIDL in the output device detected order.
But some BIOSes requires it to be initialized in the ACPI device order.
e.g. the value of the first field in DIDL stands for the first
ACPI video output device in ACPI namespace.

Now we initialize the DIDL using the device id, i.e. _ADR return value,
of each ACPI video device, if it is not 0.
https://bugzilla.kernel.org/show_bug.cgi?id=15054

Signed-off-by: Zhang Rui <rui.zhang@intel.com>
Signed-off-by: Eric Anholt <eric@anholt.net>
  • Loading branch information
Zhang Rui authored and Eric Anholt committed Apr 19, 2010
1 parent 5ce8ba7 commit 3143751
Showing 1 changed file with 50 additions and 4 deletions.
54 changes: 50 additions & 4 deletions drivers/gpu/drm/i915/i915_opregion.c
Original file line number Diff line number Diff line change
Expand Up @@ -382,8 +382,57 @@ static void intel_didl_outputs(struct drm_device *dev)
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_opregion *opregion = &dev_priv->opregion;
struct drm_connector *connector;
acpi_handle handle;
struct acpi_device *acpi_dev, *acpi_cdev, *acpi_video_bus = NULL;
unsigned long long device_id;
acpi_status status;
int i = 0;

handle = DEVICE_ACPI_HANDLE(&dev->pdev->dev);
if (!handle || ACPI_FAILURE(acpi_bus_get_device(handle, &acpi_dev)))
return;

if (acpi_is_video_device(acpi_dev))
acpi_video_bus = acpi_dev;
else {
list_for_each_entry(acpi_cdev, &acpi_dev->children, node) {
if (acpi_is_video_device(acpi_cdev)) {
acpi_video_bus = acpi_cdev;
break;
}
}
}

if (!acpi_video_bus) {
printk(KERN_WARNING "No ACPI video bus found\n");
return;
}

list_for_each_entry(acpi_cdev, &acpi_video_bus->children, node) {
if (i >= 8) {
dev_printk (KERN_ERR, &dev->pdev->dev,
"More than 8 outputs detected\n");
return;
}
status =
acpi_evaluate_integer(acpi_cdev->handle, "_ADR",
NULL, &device_id);
if (ACPI_SUCCESS(status)) {
if (!device_id)
goto blind_set;
opregion->acpi->didl[i] = (u32)(device_id & 0x0f0f);
i++;
}
}

end:
/* If fewer than 8 outputs, the list must be null terminated */
if (i < 8)
opregion->acpi->didl[i] = 0;
return;

blind_set:
i = 0;
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
int output_type = ACPI_OTHER_OUTPUT;
if (i >= 8) {
Expand Down Expand Up @@ -416,10 +465,7 @@ static void intel_didl_outputs(struct drm_device *dev)
opregion->acpi->didl[i] |= (1<<31) | output_type | i;
i++;
}

/* If fewer than 8 outputs, the list must be null terminated */
if (i < 8)
opregion->acpi->didl[i] = 0;
goto end;
}

int intel_opregion_init(struct drm_device *dev, int resume)
Expand Down

0 comments on commit 3143751

Please sign in to comment.