Commit 8e1b56a4 authored by Jani Nikula's avatar Jani Nikula

drm/i915: make i915 the source of acpi device ids for _DOD

The graphics driver is supposed to define the DIDL, which are used for
_DOD, not the BIOS. Restore that behaviour.

This is basically a revert of

commit 3143751f
Author: Zhang Rui <rui.zhang@intel.com>
Date:   Mon Mar 29 15:12:16 2010 +0800

    drm/i915: set DIDL using the ACPI video output device _ADR method return.

which went out of its way to cater to a specific BIOS, setting up DIDL
based on _ADR method. Perhaps that approach worked on that specific
machine, but on the machines I checked the _ADR method invents the
device identifiers out of thin air if DIDL has not been set. The source
for _ADR is also supposed to be the DIDL set by the driver, not the
other way around.

With this, we'll also limit the number of outputs to what the driver
actually has.

A side effect of this change is that the DIDL, and by proxy CADL, will
be initialized in the order of the connector list. That, in turn, has
internal panels in front, ensuring they're included in the DIDL and CADL
lists. Hopefully this ensures the BIOS does not block backlight hotkey
events, thinking the internal panel is off.

v2: do not set ACPI_DEVICE_ID_SCHEME in the device id (Peter Wu)

v3: Rebase

Cc: Peter Wu <peter@lekensteyn.nl>
Cc: Rainer Koenig <Rainer.Koenig@ts.fujitsu.com>
Cc: Jan-Marek Glogowski <glogow@fbihome.de>
Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Cc: Marcos Paulo de Souza <marcos.souza.org@gmail.com>
Cc: Paolo Stivanin <paolostivanin@fastmail.fm>
Tested-by: default avatarRainer Koenig <Rainer.Koenig@ts.fujitsu.com>
Tested-by: default avatarPaolo Stivanin <paolostivanin@fastmail.fm>
Tested-by: default avatarMarcos Paulo de Souza <marcos.souza.org@gmail.com>
Reviewed-and-tested-by: default avatarPeter Wu <peter@lekensteyn.nl>
Signed-off-by: default avatarJani Nikula <jani.nikula@intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/9660d29cf310c17bbf4d58c0e09d5b047446e2d5.1479295490.git.jani.nikula@intel.com
parent d7ab992c
...@@ -294,6 +294,9 @@ struct intel_connector { ...@@ -294,6 +294,9 @@ struct intel_connector {
*/ */
struct intel_encoder *encoder; struct intel_encoder *encoder;
/* ACPI device id for ACPI and driver cooperation */
u32 acpi_device_id;
/* Reads out the current hw, returning true if the connector is enabled /* Reads out the current hw, returning true if the connector is enabled
* and active (i.e. dpms ON state). */ * and active (i.e. dpms ON state). */
bool (*get_hw_state)(struct intel_connector *); bool (*get_hw_state)(struct intel_connector *);
......
...@@ -674,11 +674,11 @@ static void set_did(struct intel_opregion *opregion, int i, u32 val) ...@@ -674,11 +674,11 @@ static void set_did(struct intel_opregion *opregion, int i, u32 val)
} }
} }
static u32 acpi_display_type(struct drm_connector *connector) static u32 acpi_display_type(struct intel_connector *connector)
{ {
u32 display_type; u32 display_type;
switch (connector->connector_type) { switch (connector->base.connector_type) {
case DRM_MODE_CONNECTOR_VGA: case DRM_MODE_CONNECTOR_VGA:
case DRM_MODE_CONNECTOR_DVIA: case DRM_MODE_CONNECTOR_DVIA:
display_type = ACPI_DISPLAY_TYPE_VGA; display_type = ACPI_DISPLAY_TYPE_VGA;
...@@ -707,7 +707,7 @@ static u32 acpi_display_type(struct drm_connector *connector) ...@@ -707,7 +707,7 @@ static u32 acpi_display_type(struct drm_connector *connector)
display_type = ACPI_DISPLAY_TYPE_OTHER; display_type = ACPI_DISPLAY_TYPE_OTHER;
break; break;
default: default:
MISSING_CASE(connector->connector_type); MISSING_CASE(connector->base.connector_type);
display_type = ACPI_DISPLAY_TYPE_OTHER; display_type = ACPI_DISPLAY_TYPE_OTHER;
break; break;
} }
...@@ -718,34 +718,9 @@ static u32 acpi_display_type(struct drm_connector *connector) ...@@ -718,34 +718,9 @@ static u32 acpi_display_type(struct drm_connector *connector)
static void intel_didl_outputs(struct drm_i915_private *dev_priv) static void intel_didl_outputs(struct drm_i915_private *dev_priv)
{ {
struct intel_opregion *opregion = &dev_priv->opregion; struct intel_opregion *opregion = &dev_priv->opregion;
struct pci_dev *pdev = dev_priv->drm.pdev; struct intel_connector *connector;
struct drm_connector *connector; int i = 0, max_outputs;
acpi_handle handle; int display_index[16] = {};
struct acpi_device *acpi_dev, *acpi_cdev, *acpi_video_bus = NULL;
unsigned long long device_id;
acpi_status status;
u32 temp, max_outputs;
int i = 0;
handle = ACPI_HANDLE(&pdev->dev);
if (!handle || acpi_bus_get_device(handle, &acpi_dev))
return;
if (acpi_is_video_device(handle))
acpi_video_bus = acpi_dev;
else {
list_for_each_entry(acpi_cdev, &acpi_dev->children, node) {
if (acpi_is_video_device(acpi_cdev->handle)) {
acpi_video_bus = acpi_cdev;
break;
}
}
}
if (!acpi_video_bus) {
DRM_DEBUG_KMS("No ACPI video bus found\n");
return;
}
/* /*
* In theory, did2, the extended didl, gets added at opregion version * In theory, did2, the extended didl, gets added at opregion version
...@@ -757,46 +732,31 @@ static void intel_didl_outputs(struct drm_i915_private *dev_priv) ...@@ -757,46 +732,31 @@ static void intel_didl_outputs(struct drm_i915_private *dev_priv)
max_outputs = ARRAY_SIZE(opregion->acpi->didl) + max_outputs = ARRAY_SIZE(opregion->acpi->didl) +
ARRAY_SIZE(opregion->acpi->did2); ARRAY_SIZE(opregion->acpi->did2);
list_for_each_entry(acpi_cdev, &acpi_video_bus->children, node) { for_each_intel_connector(&dev_priv->drm, connector) {
if (i >= max_outputs) { u32 device_id, type;
DRM_DEBUG_KMS("More than %u outputs detected via ACPI\n",
max_outputs);
return;
}
status = acpi_evaluate_integer(acpi_cdev->handle, "_ADR",
NULL, &device_id);
if (ACPI_SUCCESS(status)) {
if (!device_id)
goto blind_set;
set_did(opregion, i++, (u32)(device_id & 0x0f0f));
}
}
end: device_id = acpi_display_type(connector);
DRM_DEBUG_KMS("%d outputs detected\n", i);
/* If fewer than max outputs, the list must be null terminated */ /* Use display type specific display index. */
type = (device_id & ACPI_DISPLAY_TYPE_MASK)
>> ACPI_DISPLAY_TYPE_SHIFT;
device_id |= display_index[type]++ << ACPI_DISPLAY_INDEX_SHIFT;
connector->acpi_device_id = device_id;
if (i < max_outputs) if (i < max_outputs)
set_did(opregion, i, 0); set_did(opregion, i, device_id);
return; i++;
}
blind_set: DRM_DEBUG_KMS("%d outputs detected\n", i);
i = 0;
list_for_each_entry(connector,
&dev_priv->drm.mode_config.connector_list, head) {
int display_type = acpi_display_type(connector);
if (i >= max_outputs) { if (i > max_outputs)
DRM_DEBUG_KMS("More than %u outputs in connector list\n", DRM_ERROR("More than %d outputs in connector list\n",
max_outputs); max_outputs);
return;
}
temp = get_did(opregion, i); /* If fewer than max outputs, the list must be null terminated */
set_did(opregion, i, temp | (1 << 31) | display_type | i); if (i < max_outputs)
i++; set_did(opregion, i, 0);
}
goto end;
} }
static void intel_setup_cadls(struct drm_i915_private *dev_priv) static void intel_setup_cadls(struct drm_i915_private *dev_priv)
......
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