diff options
Diffstat (limited to 'drivers/gpu/drm/i915/i915_opregion.c')
-rw-r--r-- | drivers/gpu/drm/i915/i915_opregion.c | 65 |
1 files changed, 64 insertions, 1 deletions
diff --git a/drivers/gpu/drm/i915/i915_opregion.c b/drivers/gpu/drm/i915/i915_opregion.c index ff012835a386..69427722d20e 100644 --- a/drivers/gpu/drm/i915/i915_opregion.c +++ b/drivers/gpu/drm/i915/i915_opregion.c | |||
@@ -26,6 +26,7 @@ | |||
26 | */ | 26 | */ |
27 | 27 | ||
28 | #include <linux/acpi.h> | 28 | #include <linux/acpi.h> |
29 | #include <acpi/video.h> | ||
29 | 30 | ||
30 | #include "drmP.h" | 31 | #include "drmP.h" |
31 | #include "i915_drm.h" | 32 | #include "i915_drm.h" |
@@ -136,6 +137,12 @@ struct opregion_asle { | |||
136 | 137 | ||
137 | #define ASLE_CBLV_VALID (1<<31) | 138 | #define ASLE_CBLV_VALID (1<<31) |
138 | 139 | ||
140 | #define ACPI_OTHER_OUTPUT (0<<8) | ||
141 | #define ACPI_VGA_OUTPUT (1<<8) | ||
142 | #define ACPI_TV_OUTPUT (2<<8) | ||
143 | #define ACPI_DIGITAL_OUTPUT (3<<8) | ||
144 | #define ACPI_LVDS_OUTPUT (4<<8) | ||
145 | |||
139 | static u32 asle_set_backlight(struct drm_device *dev, u32 bclp) | 146 | static u32 asle_set_backlight(struct drm_device *dev, u32 bclp) |
140 | { | 147 | { |
141 | struct drm_i915_private *dev_priv = dev->dev_private; | 148 | struct drm_i915_private *dev_priv = dev->dev_private; |
@@ -282,7 +289,58 @@ static struct notifier_block intel_opregion_notifier = { | |||
282 | .notifier_call = intel_opregion_video_event, | 289 | .notifier_call = intel_opregion_video_event, |
283 | }; | 290 | }; |
284 | 291 | ||
285 | int intel_opregion_init(struct drm_device *dev) | 292 | /* |
293 | * Initialise the DIDL field in opregion. This passes a list of devices to | ||
294 | * the firmware. Values are defined by section B.4.2 of the ACPI specification | ||
295 | * (version 3) | ||
296 | */ | ||
297 | |||
298 | static void intel_didl_outputs(struct drm_device *dev) | ||
299 | { | ||
300 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
301 | struct intel_opregion *opregion = &dev_priv->opregion; | ||
302 | struct drm_connector *connector; | ||
303 | int i = 0; | ||
304 | |||
305 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | ||
306 | int output_type = ACPI_OTHER_OUTPUT; | ||
307 | if (i >= 8) { | ||
308 | dev_printk (KERN_ERR, &dev->pdev->dev, | ||
309 | "More than 8 outputs detected\n"); | ||
310 | return; | ||
311 | } | ||
312 | switch (connector->connector_type) { | ||
313 | case DRM_MODE_CONNECTOR_VGA: | ||
314 | case DRM_MODE_CONNECTOR_DVIA: | ||
315 | output_type = ACPI_VGA_OUTPUT; | ||
316 | break; | ||
317 | case DRM_MODE_CONNECTOR_Composite: | ||
318 | case DRM_MODE_CONNECTOR_SVIDEO: | ||
319 | case DRM_MODE_CONNECTOR_Component: | ||
320 | case DRM_MODE_CONNECTOR_9PinDIN: | ||
321 | output_type = ACPI_TV_OUTPUT; | ||
322 | break; | ||
323 | case DRM_MODE_CONNECTOR_DVII: | ||
324 | case DRM_MODE_CONNECTOR_DVID: | ||
325 | case DRM_MODE_CONNECTOR_DisplayPort: | ||
326 | case DRM_MODE_CONNECTOR_HDMIA: | ||
327 | case DRM_MODE_CONNECTOR_HDMIB: | ||
328 | output_type = ACPI_DIGITAL_OUTPUT; | ||
329 | break; | ||
330 | case DRM_MODE_CONNECTOR_LVDS: | ||
331 | output_type = ACPI_LVDS_OUTPUT; | ||
332 | break; | ||
333 | } | ||
334 | opregion->acpi->didl[i] |= (1<<31) | output_type | i; | ||
335 | i++; | ||
336 | } | ||
337 | |||
338 | /* If fewer than 8 outputs, the list must be null terminated */ | ||
339 | if (i < 8) | ||
340 | opregion->acpi->didl[i] = 0; | ||
341 | } | ||
342 | |||
343 | int intel_opregion_init(struct drm_device *dev, int resume) | ||
286 | { | 344 | { |
287 | struct drm_i915_private *dev_priv = dev->dev_private; | 345 | struct drm_i915_private *dev_priv = dev->dev_private; |
288 | struct intel_opregion *opregion = &dev_priv->opregion; | 346 | struct intel_opregion *opregion = &dev_priv->opregion; |
@@ -312,6 +370,11 @@ int intel_opregion_init(struct drm_device *dev) | |||
312 | if (mboxes & MBOX_ACPI) { | 370 | if (mboxes & MBOX_ACPI) { |
313 | DRM_DEBUG("Public ACPI methods supported\n"); | 371 | DRM_DEBUG("Public ACPI methods supported\n"); |
314 | opregion->acpi = base + OPREGION_ACPI_OFFSET; | 372 | opregion->acpi = base + OPREGION_ACPI_OFFSET; |
373 | if (drm_core_check_feature(dev, DRIVER_MODESET)) { | ||
374 | intel_didl_outputs(dev); | ||
375 | if (!resume) | ||
376 | acpi_video_register(); | ||
377 | } | ||
315 | } else { | 378 | } else { |
316 | DRM_DEBUG("Public ACPI methods not supported\n"); | 379 | DRM_DEBUG("Public ACPI methods not supported\n"); |
317 | err = -ENOTSUPP; | 380 | err = -ENOTSUPP; |