240 lines
6.8 KiB
Diff
240 lines
6.8 KiB
Diff
From 782468d6a9fb865677c166ceffc2271e1f709cc5 Mon Sep 17 00:00:00 2001
|
|
From: Ben Skeggs <bskeggs@redhat.com>
|
|
Date: Fri, 16 Apr 2010 08:12:34 +1000
|
|
Subject: [PATCH 2/3] drm-nouveau-acpi-edid-fallback
|
|
|
|
---
|
|
drivers/gpu/drm/nouveau/nouveau_acpi.c | 81 ++++++++++++++++++++++++--
|
|
drivers/gpu/drm/nouveau/nouveau_connector.c | 8 +++
|
|
drivers/gpu/drm/nouveau/nouveau_drv.h | 20 +++++--
|
|
drivers/gpu/drm/nouveau/nouveau_state.c | 5 +-
|
|
4 files changed, 98 insertions(+), 16 deletions(-)
|
|
|
|
diff --git a/drivers/gpu/drm/nouveau/nouveau_acpi.c b/drivers/gpu/drm/nouveau/nouveau_acpi.c
|
|
index 48227e7..ac7fd04 100644
|
|
--- a/drivers/gpu/drm/nouveau/nouveau_acpi.c
|
|
+++ b/drivers/gpu/drm/nouveau/nouveau_acpi.c
|
|
@@ -2,11 +2,13 @@
|
|
#include <linux/acpi.h>
|
|
#include <acpi/acpi_drivers.h>
|
|
#include <acpi/acpi_bus.h>
|
|
+#include <acpi/video.h>
|
|
|
|
#include "drmP.h"
|
|
#include "drm.h"
|
|
#include "drm_sarea.h"
|
|
#include "drm_crtc_helper.h"
|
|
+#include "nouveau_connector.h"
|
|
#include "nouveau_drv.h"
|
|
#include "nouveau_drm.h"
|
|
#include "nv50_display.h"
|
|
@@ -35,7 +37,7 @@ static int nouveau_dsm(struct drm_device *dev, int func, int arg, int *result)
|
|
0xB3, 0x4D, 0x7E, 0x5F, 0xEA, 0x12, 0x9F, 0xD4,
|
|
};
|
|
|
|
- struct pci_dev *pdev = dev->pdev;
|
|
+ struct drm_nouveau_private *dev_priv = dev->dev_private;
|
|
struct acpi_handle *handle;
|
|
struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
|
|
struct acpi_object_list input;
|
|
@@ -43,11 +45,11 @@ static int nouveau_dsm(struct drm_device *dev, int func, int arg, int *result)
|
|
union acpi_object *obj;
|
|
int err;
|
|
|
|
- handle = DEVICE_ACPI_HANDLE(&pdev->dev);
|
|
-
|
|
- if (!handle)
|
|
+ if (!dev_priv->acpi_device)
|
|
return -ENODEV;
|
|
|
|
+ handle = dev_priv->acpi_device->handle;
|
|
+
|
|
input.count = 4;
|
|
input.pointer = params;
|
|
params[0].type = ACPI_TYPE_BUFFER;
|
|
@@ -62,7 +64,8 @@ static int nouveau_dsm(struct drm_device *dev, int func, int arg, int *result)
|
|
|
|
err = acpi_evaluate_object(handle, "_DSM", &input, &output);
|
|
if (err) {
|
|
- NV_INFO(dev, "failed to evaluate _DSM: %d\n", err);
|
|
+ if (err != AE_NOT_FOUND)
|
|
+ NV_INFO(dev, "failed to evaluate _DSM: %d\n", err);
|
|
return err;
|
|
}
|
|
|
|
@@ -86,7 +89,7 @@ static int nouveau_dsm(struct drm_device *dev, int func, int arg, int *result)
|
|
return 0;
|
|
}
|
|
|
|
-int nouveau_hybrid_setup(struct drm_device *dev)
|
|
+static int nouveau_hybrid_setup(struct drm_device *dev)
|
|
{
|
|
int result;
|
|
|
|
@@ -110,7 +113,7 @@ int nouveau_hybrid_setup(struct drm_device *dev)
|
|
return 0;
|
|
}
|
|
|
|
-bool nouveau_dsm_probe(struct drm_device *dev)
|
|
+static bool nouveau_dsm_probe(struct drm_device *dev)
|
|
{
|
|
int support = 0;
|
|
|
|
@@ -123,3 +126,67 @@ bool nouveau_dsm_probe(struct drm_device *dev)
|
|
|
|
return true;
|
|
}
|
|
+
|
|
+int nouveau_acpi_get_edid(struct drm_device *dev,
|
|
+ struct drm_connector *connector,
|
|
+ struct edid **pedid)
|
|
+{
|
|
+ struct drm_nouveau_private *dev_priv = dev->dev_private;
|
|
+ void *edid;
|
|
+ int connector_type = 0;
|
|
+ int ret;
|
|
+
|
|
+ switch (connector->connector_type) {
|
|
+ case DRM_MODE_CONNECTOR_VGA:
|
|
+ connector_type = ACPI_VIDEO_DISPLAY_CRT;
|
|
+ break;
|
|
+ case DRM_MODE_CONNECTOR_Composite:
|
|
+ case DRM_MODE_CONNECTOR_SVIDEO:
|
|
+ case DRM_MODE_CONNECTOR_Component:
|
|
+ case DRM_MODE_CONNECTOR_9PinDIN:
|
|
+ connector_type = ACPI_VIDEO_DISPLAY_TV;
|
|
+ break;
|
|
+ case DRM_MODE_CONNECTOR_DVII:
|
|
+ case DRM_MODE_CONNECTOR_DVID:
|
|
+ case DRM_MODE_CONNECTOR_HDMIA:
|
|
+ case DRM_MODE_CONNECTOR_HDMIB:
|
|
+ case DRM_MODE_CONNECTOR_DisplayPort:
|
|
+ connector_type = ACPI_VIDEO_DISPLAY_DVI;
|
|
+ break;
|
|
+ case DRM_MODE_CONNECTOR_LVDS:
|
|
+ connector_type = ACPI_VIDEO_DISPLAY_LCD;
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ ret = acpi_video_get_edid(dev_priv->acpi_device, connector_type, -1, &edid);
|
|
+
|
|
+ if (ret < 0)
|
|
+ return ret;
|
|
+
|
|
+ *pedid = edid;
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+int nouveau_acpi_setup(struct drm_device *dev)
|
|
+{
|
|
+ struct pci_dev *pdev = dev->pdev;
|
|
+ struct drm_nouveau_private *dev_priv = dev->dev_private;
|
|
+ acpi_handle handle;
|
|
+ struct acpi_device *acpi_dev;
|
|
+
|
|
+ handle = DEVICE_ACPI_HANDLE(&pdev->dev);
|
|
+
|
|
+ if (!handle)
|
|
+ return -ENODEV;
|
|
+
|
|
+ if (acpi_bus_get_device(handle, &acpi_dev))
|
|
+ return -ENODEV;
|
|
+
|
|
+ dev_priv->acpi_device = acpi_dev;
|
|
+ dev_priv->acpi_dsm = nouveau_dsm_probe(dev);
|
|
+
|
|
+ if (dev_priv->acpi_dsm)
|
|
+ nouveau_hybrid_setup(dev);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c
|
|
index fb51958..5832b60 100644
|
|
--- a/drivers/gpu/drm/nouveau/nouveau_connector.c
|
|
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.c
|
|
@@ -356,6 +356,14 @@ nouveau_connector_detect_lvds(struct drm_connector *connector)
|
|
}
|
|
}
|
|
|
|
+ /* Let's try ACPI */
|
|
+ if (status != connector_status_connected &&
|
|
+ !dev_priv->vbios.fp_no_ddc) {
|
|
+ nouveau_acpi_get_edid(dev, connector, &nv_connector->edid);
|
|
+ if (nv_connector->edid)
|
|
+ status = connector_status_connected;
|
|
+ }
|
|
+
|
|
out:
|
|
#ifdef CONFIG_ACPI
|
|
if (status == connector_status_connected &&
|
|
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h
|
|
index c31159a..675d7ac 100644
|
|
--- a/drivers/gpu/drm/nouveau/nouveau_drv.h
|
|
+++ b/drivers/gpu/drm/nouveau/nouveau_drv.h
|
|
@@ -39,6 +39,8 @@
|
|
#define NOUVEAU_FAMILY 0x0000FFFF
|
|
#define NOUVEAU_FLAGS 0xFFFF0000
|
|
|
|
+#include <linux/acpi.h>
|
|
+
|
|
#include "ttm/ttm_bo_api.h"
|
|
#include "ttm/ttm_bo_driver.h"
|
|
#include "ttm/ttm_placement.h"
|
|
@@ -615,7 +617,11 @@ struct drm_nouveau_private {
|
|
} susres;
|
|
|
|
struct backlight_device *backlight;
|
|
+
|
|
+#ifdef CONFIG_ACPI
|
|
bool acpi_dsm;
|
|
+ struct acpi_device *acpi_device;
|
|
+#endif
|
|
|
|
struct nouveau_channel *evo;
|
|
|
|
@@ -846,16 +852,20 @@ extern int nouveau_dma_wait(struct nouveau_channel *, int slots, int size);
|
|
|
|
/* nouveau_acpi.c */
|
|
#ifdef CONFIG_ACPI
|
|
-extern int nouveau_hybrid_setup(struct drm_device *dev);
|
|
-extern bool nouveau_dsm_probe(struct drm_device *dev);
|
|
+extern int nouveau_acpi_setup(struct drm_device *dev);
|
|
+extern int nouveau_acpi_get_edid(struct drm_device *dev,
|
|
+ struct drm_connector *connector,
|
|
+ struct edid **edid);
|
|
#else
|
|
-static inline int nouveau_hybrid_setup(struct drm_device *dev)
|
|
+static inline int nouveau_acpi_setup(struct drm_device *dev)
|
|
{
|
|
return 0;
|
|
}
|
|
-static inline bool nouveau_dsm_probe(struct drm_device *dev)
|
|
+static inline int nouveau_acpi_get_edid(struct drm_device *dev,
|
|
+ struct drm_connector *connector,
|
|
+ struct edid **edid)
|
|
{
|
|
- return false;
|
|
+ return -ENODEV;
|
|
}
|
|
#endif
|
|
|
|
diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c
|
|
index 7c1d252..7ca9465 100644
|
|
--- a/drivers/gpu/drm/nouveau/nouveau_state.c
|
|
+++ b/drivers/gpu/drm/nouveau/nouveau_state.c
|
|
@@ -627,10 +627,7 @@ int nouveau_load(struct drm_device *dev, unsigned long flags)
|
|
NV_DEBUG(dev, "vendor: 0x%X device: 0x%X class: 0x%X\n",
|
|
dev->pci_vendor, dev->pci_device, dev->pdev->class);
|
|
|
|
- dev_priv->acpi_dsm = nouveau_dsm_probe(dev);
|
|
-
|
|
- if (dev_priv->acpi_dsm)
|
|
- nouveau_hybrid_setup(dev);
|
|
+ nouveau_acpi_setup(dev);
|
|
|
|
dev_priv->wq = create_workqueue("nouveau");
|
|
if (!dev_priv->wq)
|
|
--
|
|
1.7.1
|
|
|