Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 141918
b: refs/heads/master
c: 74a365b
h: refs/heads/master
v: v3
  • Loading branch information
Matthew Garrett authored and Len Brown committed Mar 28, 2009
1 parent 25abd8f commit 4e816c0
Show file tree
Hide file tree
Showing 7 changed files with 120 additions and 7 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: c60d638e29c780b75b648283a197d0226e3576c3
refs/heads/master: 74a365b3f354fafc537efa5867deb7a9fadbfe27
40 changes: 39 additions & 1 deletion trunk/drivers/acpi/video.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@
#include <linux/thermal.h>
#include <linux/video_output.h>
#include <linux/sort.h>
#include <linux/pci.h>
#include <linux/pci_ids.h>
#include <asm/uaccess.h>

#include <acpi/acpi_bus.h>
Expand Down Expand Up @@ -2251,7 +2253,27 @@ static int acpi_video_bus_remove(struct acpi_device *device, int type)
return 0;
}

static int __init acpi_video_init(void)
static int __init intel_opregion_present(void)
{
#if defined(CONFIG_DRM_I915) || defined(CONFIG_DRM_I915_MODULE)
struct pci_dev *dev = NULL;
u32 address;

for_each_pci_dev(dev) {
if ((dev->class >> 8) != PCI_CLASS_DISPLAY_VGA)
continue;
if (dev->vendor != PCI_VENDOR_ID_INTEL)
continue;
pci_read_config_dword(dev, 0xfc, &address);
if (!address)
continue;
return 1;
}
#endif
return 0;
}

int acpi_video_register(void)
{
int result = 0;

Expand All @@ -2268,6 +2290,22 @@ static int __init acpi_video_init(void)

return 0;
}
EXPORT_SYMBOL(acpi_video_register);

/*
* This is kind of nasty. Hardware using Intel chipsets may require
* the video opregion code to be run first in order to initialise
* state before any ACPI video calls are made. To handle this we defer
* registration of the video class until the opregion code has run.
*/

static int __init acpi_video_init(void)
{
if (intel_opregion_present())
return 0;

return acpi_video_register();
}

static void __exit acpi_video_exit(void)
{
Expand Down
5 changes: 3 additions & 2 deletions trunk/drivers/gpu/drm/i915/i915_dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -1144,8 +1144,6 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
if (!IS_I945G(dev) && !IS_I945GM(dev))
pci_enable_msi(dev->pdev);

intel_opregion_init(dev);

spin_lock_init(&dev_priv->user_irq_lock);
dev_priv->user_irq_refcount = 0;

Expand All @@ -1164,6 +1162,9 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
}
}

/* Must be done after probing outputs */
intel_opregion_init(dev, 0);

return 0;

out_iomapfree:
Expand Down
2 changes: 1 addition & 1 deletion trunk/drivers/gpu/drm/i915/i915_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ static int i915_resume(struct drm_device *dev)

i915_restore_state(dev);

intel_opregion_init(dev);
intel_opregion_init(dev, 1);

/* KMS EnterVT equivalent */
if (drm_core_check_feature(dev, DRIVER_MODESET)) {
Expand Down
2 changes: 1 addition & 1 deletion trunk/drivers/gpu/drm/i915/i915_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -659,7 +659,7 @@ extern int i915_restore_state(struct drm_device *dev);

#ifdef CONFIG_ACPI
/* i915_opregion.c */
extern int intel_opregion_init(struct drm_device *dev);
extern int intel_opregion_init(struct drm_device *dev, int resume);
extern void intel_opregion_free(struct drm_device *dev);
extern void opregion_asle_intr(struct drm_device *dev);
extern void opregion_enable_asle(struct drm_device *dev);
Expand Down
65 changes: 64 additions & 1 deletion trunk/drivers/gpu/drm/i915/i915_opregion.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
*/

#include <linux/acpi.h>
#include <acpi/video.h>

#include "drmP.h"
#include "i915_drm.h"
Expand Down Expand Up @@ -136,6 +137,12 @@ struct opregion_asle {

#define ASLE_CBLV_VALID (1<<31)

#define ACPI_OTHER_OUTPUT (0<<8)
#define ACPI_VGA_OUTPUT (1<<8)
#define ACPI_TV_OUTPUT (2<<8)
#define ACPI_DIGITAL_OUTPUT (3<<8)
#define ACPI_LVDS_OUTPUT (4<<8)

static u32 asle_set_backlight(struct drm_device *dev, u32 bclp)
{
struct drm_i915_private *dev_priv = dev->dev_private;
Expand Down Expand Up @@ -282,7 +289,58 @@ static struct notifier_block intel_opregion_notifier = {
.notifier_call = intel_opregion_video_event,
};

int intel_opregion_init(struct drm_device *dev)
/*
* Initialise the DIDL field in opregion. This passes a list of devices to
* the firmware. Values are defined by section B.4.2 of the ACPI specification
* (version 3)
*/

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;
int i = 0;

list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
int output_type = ACPI_OTHER_OUTPUT;
if (i >= 8) {
dev_printk (KERN_ERR, &dev->pdev->dev,
"More than 8 outputs detected\n");
return;
}
switch (connector->connector_type) {
case DRM_MODE_CONNECTOR_VGA:
case DRM_MODE_CONNECTOR_DVIA:
output_type = ACPI_VGA_OUTPUT;
break;
case DRM_MODE_CONNECTOR_Composite:
case DRM_MODE_CONNECTOR_SVIDEO:
case DRM_MODE_CONNECTOR_Component:
case DRM_MODE_CONNECTOR_9PinDIN:
output_type = ACPI_TV_OUTPUT;
break;
case DRM_MODE_CONNECTOR_DVII:
case DRM_MODE_CONNECTOR_DVID:
case DRM_MODE_CONNECTOR_DisplayPort:
case DRM_MODE_CONNECTOR_HDMIA:
case DRM_MODE_CONNECTOR_HDMIB:
output_type = ACPI_DIGITAL_OUTPUT;
break;
case DRM_MODE_CONNECTOR_LVDS:
output_type = ACPI_LVDS_OUTPUT;
break;
}
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;
}

int intel_opregion_init(struct drm_device *dev, int resume)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_opregion *opregion = &dev_priv->opregion;
Expand Down Expand Up @@ -312,6 +370,11 @@ int intel_opregion_init(struct drm_device *dev)
if (mboxes & MBOX_ACPI) {
DRM_DEBUG("Public ACPI methods supported\n");
opregion->acpi = base + OPREGION_ACPI_OFFSET;
if (drm_core_check_feature(dev, DRIVER_MODESET)) {
intel_didl_outputs(dev);
if (!resume)
acpi_video_register();
}
} else {
DRM_DEBUG("Public ACPI methods not supported\n");
err = -ENOTSUPP;
Expand Down
11 changes: 11 additions & 0 deletions trunk/include/acpi/video.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#ifndef __ACPI_VIDEO_H
#define __ACPI_VIDEO_H

#if (defined CONFIG_ACPI_VIDEO || defined CONFIG_ACPI_VIDEO_MODULE)
extern int acpi_video_register(void);
#else
static inline int acpi_video_register(void) { return 0; }
#endif

#endif

0 comments on commit 4e816c0

Please sign in to comment.