rpms/kernel/F-13 drm-nouveau-acpi-edid-fallback.patch, NONE, 1.1 linux-2.6-acpi-video-export-edid.patch, NONE, 1.1 kernel.spec, 1.1977, 1.1978

Matthew Garrett mjg59 at fedoraproject.org
Mon Apr 12 18:11:29 UTC 2010


Author: mjg59

Update of /cvs/pkgs/rpms/kernel/F-13
In directory cvs01.phx2.fedoraproject.org:/tmp/cvs-serv23281

Modified Files:
	kernel.spec 
Added Files:
	drm-nouveau-acpi-edid-fallback.patch 
	linux-2.6-acpi-video-export-edid.patch 
Log Message:
* Mon Apr 12 2010 Matthew Garrett <mjg at redhat.com>
- linux-2.6-acpi-video-export-edid.patch:
  drm-nouveau-acpi-edid-fallback.patch: Let nouveau get an EDID from ACPI


drm-nouveau-acpi-edid-fallback.patch:
 nouveau_acpi.c      |   83 +++++++++++++++++++++++++++++++++++++++++++++++-----
 nouveau_connector.c |    8 +++++
 nouveau_connector.h |    3 +
 nouveau_drv.h       |   18 ++++++++---
 nouveau_state.c     |    5 ---
 5 files changed, 101 insertions(+), 16 deletions(-)

--- NEW FILE drm-nouveau-acpi-edid-fallback.patch ---
diff -up linux-2.6.33.noarch/drivers/gpu/drm/nouveau/nouveau_acpi.c.orig linux-2.6.33.noarch/drivers/gpu/drm/nouveau/nouveau_acpi.c
--- linux-2.6.33.noarch/drivers/gpu/drm/nouveau/nouveau_acpi.c.orig	2010-02-24 13:52:17.000000000 -0500
+++ linux-2.6.33.noarch/drivers/gpu/drm/nouveau/nouveau_acpi.c	2010-04-12 13:46:28.005967983 -0400
@@ -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
 		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
 	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;
@@ -61,7 +63,7 @@ static int nouveau_dsm(struct drm_device
 	params[3].integer.value = arg;
 
 	err = acpi_evaluate_object(handle, "_DSM", &input, &output);
-	if (err) {
+	if (err && err != AE_NOT_FOUND) {
 		NV_INFO(dev, "failed to evaluate _DSM: %d\n", err);
 		return err;
 	}
@@ -86,7 +88,7 @@ static int nouveau_dsm(struct drm_device
 	return 0;
 }
 
-int nouveau_hybrid_setup(struct drm_device *dev)
+static int nouveau_hybrid_setup(struct drm_device *dev)
 {
 	int result;
 
@@ -110,7 +112,7 @@ int nouveau_hybrid_setup(struct drm_devi
 	return 0;
 }
 
-bool nouveau_dsm_probe(struct drm_device *dev)
+static bool nouveau_dsm_probe(struct drm_device *dev)
 {
 	int support = 0;
 
@@ -123,3 +125,70 @@ bool nouveau_dsm_probe(struct drm_device
 
 	return true;
 }
+
+int nouveau_acpi_get_edid(struct drm_device *dev,
+			  struct drm_connector *connector)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_connector *nv_connector = nouveau_connector(connector);
+	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;
+
+	memcpy(&nv_connector->acpi_edid, edid, ret);
+
+	kfree(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 -up linux-2.6.33.noarch/drivers/gpu/drm/nouveau/nouveau_connector.c.orig linux-2.6.33.noarch/drivers/gpu/drm/nouveau/nouveau_connector.c
--- linux-2.6.33.noarch/drivers/gpu/drm/nouveau/nouveau_connector.c.orig	2010-04-12 13:46:07.994840490 -0400
+++ linux-2.6.33.noarch/drivers/gpu/drm/nouveau/nouveau_connector.c	2010-04-12 13:46:28.007966209 -0400
@@ -718,6 +718,14 @@ nouveau_connector_create_lvds(struct drm
 		}
 	}
 
+	/* Let's try ACPI */
+	if (!nv_connector->edid && !nv_connector->native_mode &&
+	    !dev_priv->vbios.fp_no_ddc &&
+	    !nouveau_acpi_get_edid(dev,connector)) {
+		    nv_connector->edid =
+			    (struct edid *)&nv_connector->acpi_edid;
+	}
+
 	if (!nv_connector->edid)
 		goto out;
 
diff -up linux-2.6.33.noarch/drivers/gpu/drm/nouveau/nouveau_connector.h.orig linux-2.6.33.noarch/drivers/gpu/drm/nouveau/nouveau_connector.h
--- linux-2.6.33.noarch/drivers/gpu/drm/nouveau/nouveau_connector.h.orig	2010-04-12 13:46:07.995840093 -0400
+++ linux-2.6.33.noarch/drivers/gpu/drm/nouveau/nouveau_connector.h	2010-04-12 13:46:28.008966510 -0400
@@ -41,6 +41,9 @@ struct nouveau_connector {
 	struct nouveau_encoder *detected_encoder;
 	struct edid *edid;
 	struct drm_display_mode *native_mode;
+#ifdef CONFIG_ACPI
+	char acpi_edid[256];
+#endif
 };
 
 static inline struct nouveau_connector *nouveau_connector(
diff -up linux-2.6.33.noarch/drivers/gpu/drm/nouveau/nouveau_drv.h.orig linux-2.6.33.noarch/drivers/gpu/drm/nouveau/nouveau_drv.h
--- linux-2.6.33.noarch/drivers/gpu/drm/nouveau/nouveau_drv.h.orig	2010-04-12 13:46:07.998840717 -0400
+++ linux-2.6.33.noarch/drivers/gpu/drm/nouveau/nouveau_drv.h	2010-04-12 13:46:28.010965995 -0400
@@ -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,18 @@ extern int  nouveau_dma_wait(struct nouv
 
 /* 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);
 #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)
 {
-	return false;
+	return -ENODEV;
 }
 #endif
 
diff -up linux-2.6.33.noarch/drivers/gpu/drm/nouveau/nouveau_state.c.orig linux-2.6.33.noarch/drivers/gpu/drm/nouveau/nouveau_state.c
--- linux-2.6.33.noarch/drivers/gpu/drm/nouveau/nouveau_state.c.orig	2010-04-12 13:46:08.009840047 -0400
+++ linux-2.6.33.noarch/drivers/gpu/drm/nouveau/nouveau_state.c	2010-04-12 13:46:28.011966227 -0400
@@ -627,10 +627,7 @@ int nouveau_load(struct drm_device *dev,
 	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)

linux-2.6-acpi-video-export-edid.patch:
 drivers/acpi/video.c |  110 +++++++++++++++++++++++++++++++++++++++++++++++----
 include/acpi/video.h |   16 +++++++
 2 files changed, 118 insertions(+), 8 deletions(-)

--- NEW FILE linux-2.6-acpi-video-export-edid.patch ---
diff -up linux-2.6.33.noarch/drivers/acpi/video.c.orig linux-2.6.33.noarch/drivers/acpi/video.c
--- linux-2.6.33.noarch/drivers/acpi/video.c.orig	2010-04-12 13:42:53.637966231 -0400
+++ linux-2.6.33.noarch/drivers/acpi/video.c	2010-04-12 13:43:07.290978352 -0400
@@ -43,6 +43,7 @@
 #include <linux/dmi.h>
 #include <acpi/acpi_bus.h>
 #include <acpi/acpi_drivers.h>
+#include <acpi/video.h>
 
 #define PREFIX "ACPI: "
 
@@ -63,11 +64,6 @@
 
 #define MAX_NAME_LEN	20
 
-#define ACPI_VIDEO_DISPLAY_CRT	1
-#define ACPI_VIDEO_DISPLAY_TV	2
-#define ACPI_VIDEO_DISPLAY_DVI	3
-#define ACPI_VIDEO_DISPLAY_LCD	4
-
 #define _COMPONENT		ACPI_VIDEO_COMPONENT
 ACPI_MODULE_NAME("video");
 
@@ -1731,11 +1727,27 @@ acpi_video_get_device_attr(struct acpi_v
 }
 
 static int
+acpi_video_get_device_type(struct acpi_video_bus *video,
+			   unsigned long device_id)
+{
+	struct acpi_video_enumerated_device *ids;
+	int i;
+
+	for (i = 0; i < video->attached_count; i++) {
+		ids = &video->attached_array[i];
+		if ((ids->value.int_val & 0xffff) == device_id)
+			return ids->value.int_val;
+	}
+
+	return 0;
+}
+
+static int
 acpi_video_bus_get_one_device(struct acpi_device *device,
 			      struct acpi_video_bus *video)
 {
 	unsigned long long device_id;
-	int status;
+	int status, device_type;
 	struct acpi_video_device *data;
 	struct acpi_video_device_attrib* attribute;
 
@@ -1780,8 +1792,25 @@ acpi_video_bus_get_one_device(struct acp
 			}
 			if(attribute->bios_can_detect)
 				data->flags.bios = 1;
-		} else
-			data->flags.unknown = 1;
+		} else {
+			/* Check for legacy IDs */
+			device_type = acpi_video_get_device_type(video,
+								 device_id);
+			/* Ignore bits 16 and 18-20 */
+			switch (device_type & 0xffe2ffff) {
+			case ACPI_VIDEO_DISPLAY_LEGACY_MONITOR:
+				data->flags.crt = 1;
+				break;
+			case ACPI_VIDEO_DISPLAY_LEGACY_PANEL:
+				data->flags.lcd = 1;
+				break;
+			case ACPI_VIDEO_DISPLAY_LEGACY_TV:
+				data->flags.tvout = 1;
+				break;
+			default:
+				data->flags.unknown = 1;
+			}
+		}
 
 		acpi_video_device_bind(video, data);
 		acpi_video_device_find_cap(data);
@@ -2015,6 +2044,71 @@ out:
 	return result;
 }
 
+int acpi_video_get_edid(struct acpi_device *device, int type, int device_id,
+			void **edid)
+{
+	struct acpi_video_bus *video;
+	struct acpi_video_device *video_device;
+	union acpi_object *buffer = NULL;
+	acpi_status status;
+	int i, length;
+
+	if (!device || !acpi_driver_data(device))
+		return -EINVAL;
+
+	video = acpi_driver_data(device);
+
+	for (i = 0; i < video->attached_count; i++) {
+		video_device = video->attached_array[i].bind_info;
+		length = 256;
+
+		if (!video_device)
+			continue;
+
+		if (type) {
+			switch (type) {
+			case ACPI_VIDEO_DISPLAY_CRT:
+				if (!video_device->flags.crt)
+					continue;
+				break;
+			case ACPI_VIDEO_DISPLAY_TV:
+				if (!video_device->flags.tvout)
+					continue;
+				break;
+			case ACPI_VIDEO_DISPLAY_DVI:
+				if (!video_device->flags.dvi)
+					continue;
+				break;
+			case ACPI_VIDEO_DISPLAY_LCD:
+				if (!video_device->flags.lcd)
+					continue;
+				break;
+			}
+		} else if (video_device->device_id != device_id) {
+			continue;
+		}
+
+		status = acpi_video_device_EDID(video_device, &buffer, length);
+
+		if (ACPI_FAILURE(status) || !buffer ||
+		    buffer->type != ACPI_TYPE_BUFFER) {
+			length = 128;
+			status = acpi_video_device_EDID(video_device, &buffer,
+							length);
+			if (ACPI_FAILURE(status) || !buffer ||
+			    buffer->type != ACPI_TYPE_BUFFER) {
+				continue;
+			}
+		}
+
+		*edid = buffer->buffer.pointer;
+		return length;
+	}
+
+	return -ENODEV;
+}
+EXPORT_SYMBOL(acpi_video_get_edid);
+
 static int
 acpi_video_bus_get_devices(struct acpi_video_bus *video,
 			   struct acpi_device *device)
diff -up linux-2.6.33.noarch/include/acpi/video.h.orig linux-2.6.33.noarch/include/acpi/video.h
--- linux-2.6.33.noarch/include/acpi/video.h.orig	2010-04-12 13:42:53.638966251 -0400
+++ linux-2.6.33.noarch/include/acpi/video.h	2010-04-12 13:43:07.292841571 -0400
@@ -1,12 +1,28 @@
 #ifndef __ACPI_VIDEO_H
 #define __ACPI_VIDEO_H
 
+#define ACPI_VIDEO_DISPLAY_CRT  1
+#define ACPI_VIDEO_DISPLAY_TV   2
+#define ACPI_VIDEO_DISPLAY_DVI  3
+#define ACPI_VIDEO_DISPLAY_LCD  4
+
+#define ACPI_VIDEO_DISPLAY_LEGACY_MONITOR 0x0100
+#define ACPI_VIDEO_DISPLAY_LEGACY_PANEL   0x0110
+#define ACPI_VIDEO_DISPLAY_LEGACY_TV      0x0200
+
 #if (defined CONFIG_ACPI_VIDEO || defined CONFIG_ACPI_VIDEO_MODULE)
 extern int acpi_video_register(void);
 extern void acpi_video_unregister(void);
+extern int acpi_video_get_edid(struct acpi_device *device, int type,
+			       int device_id, void **edid);
 #else
 static inline int acpi_video_register(void) { return 0; }
 static inline void acpi_video_unregister(void) { return; }
+static inline int acpi_video_get_edid(struct acpi_device *device, int type,
+				      int device_id, void **edid)
+{
+	return -ENODEV;
+}
 #endif
 
 #endif


Index: kernel.spec
===================================================================
RCS file: /cvs/pkgs/rpms/kernel/F-13/kernel.spec,v
retrieving revision 1.1977
retrieving revision 1.1978
diff -u -p -r1.1977 -r1.1978
--- kernel.spec	12 Apr 2010 13:49:39 -0000	1.1977
+++ kernel.spec	12 Apr 2010 18:11:29 -0000	1.1978
@@ -667,6 +667,7 @@ Patch382: linux-2.6-defaults-pciehp.patc
 Patch383: linux-2.6-defaults-aspm.patch
 Patch390: linux-2.6-defaults-acpi-video.patch
 Patch391: linux-2.6-acpi-video-dos.patch
+Patch392: linux-2.6-acpi-video-export-edid.patch
 Patch450: linux-2.6-input-kill-stupid-messages.patch
 Patch451: linux-2.6-input-fix-toshiba-hotkeys.patch
 Patch452: linux-2.6.30-no-pcspkr-modalias.patch
@@ -714,8 +715,10 @@ Patch1700: linux-2.6-x86-64-fbdev-primar
 Patch1810: drm-radeon-evergreen.patch
 # nouveau fixes
 # - these not until 2.6.34
-Patch1817: drm-nouveau-abi16.patch
-Patch1818: drm-nouveau-updates.patch
+Patch1815: drm-nouveau-abi16.patch
+Patch1816: drm-nouveau-updates.patch
+# requires code that hasn't been merged upstream yet
+Patch1817: drm-nouveau-acpi-edid-fallback.patch
 
 # drm fixes
 Patch1819: drm-intel-big-hammer.patch
@@ -1264,6 +1267,7 @@ ApplyPatch linux-2.6-acpi-video-dos.patc
 # Breaks boot on lenovo t410
 #ApplyPatch acpi-ec-add-delay-before-write.patch
 ApplyPatch acpi-ec-allow-multibyte-access-to-ec.patch
+ApplyPatch linux-2.6-acpi-video-export-edid.patch
 
 # Various low-impact patches to aid debugging.
 ApplyPatch linux-2.6-debug-sizeof-structs.patch
@@ -1371,6 +1375,7 @@ ApplyPatch linux-2.6-x86-64-fbdev-primar
 ApplyPatch drm-radeon-evergreen.patch
 ApplyPatch drm-nouveau-abi16.patch
 ApplyPatch drm-nouveau-updates.patch
+ApplyPatch drm-nouveau-acpi-edid-fallback.patch
 # pm broken on my thinkpad t60p - airlied
 ApplyPatch drm-intel-big-hammer.patch
 ApplyOptionalPatch drm-intel-next.patch
@@ -2062,6 +2067,10 @@ fi
 # and build.
 
 %changelog
+* Mon Apr 12 2010 Matthew Garrett <mjg at redhat.com>
+- linux-2.6-acpi-video-export-edid.patch:
+  drm-nouveau-acpi-edid-fallback.patch: Let nouveau get an EDID from ACPI
+   
 * Fri Apr 09 2010 John W. Linville <linville at redhat.com> 2.6.33.2-41
 - b43: Allow PIO mode to be selected at module load
 - b43: fall back gracefully to PIO mode after fatal DMA errors



More information about the scm-commits mailing list