aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/i915_opregion.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/i915/i915_opregion.c')
-rw-r--r--drivers/gpu/drm/i915/i915_opregion.c65
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
139static u32 asle_set_backlight(struct drm_device *dev, u32 bclp) 146static 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
285int 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
298static 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
343int 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;