summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/nouveau/nouveau_connector.c
diff options
context:
space:
mode:
authorFrancisco Jerez <currojerez@riseup.net>2010-09-09 14:33:17 +0200
committerBen Skeggs <bskeggs@redhat.com>2010-09-24 16:25:48 +1000
commitc16c570762bb4419f2bb764f2a7428c249d905d0 (patch)
treeddd7bbaf6843eed4994997e9f991e8e250526393 /drivers/gpu/drm/nouveau/nouveau_connector.c
parent9f56b1265d66f6698e3155529e6c5d0c34b37afa (diff)
drm/nouveau: Try to fetch an EDID from OF if DDC fails.
More Apple brain damage, it fixes the modesetting failure on an eMac G4 (fdo bug 29810). Reported-by: Zoltan Varnagy <doi@freemail.hu> Signed-off-by: Francisco Jerez <currojerez@riseup.net> Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/nouveau/nouveau_connector.c')
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_connector.c36
1 files changed, 36 insertions, 0 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c
index 87186a4bbf03..98c214c34922 100644
--- a/drivers/gpu/drm/nouveau/nouveau_connector.c
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.c
@@ -130,6 +130,36 @@ nouveau_connector_ddc_detect(struct drm_connector *connector,
return NULL;
}
+static struct nouveau_encoder *
+nouveau_connector_of_detect(struct drm_connector *connector)
+{
+#ifdef __powerpc__
+ struct drm_device *dev = connector->dev;
+ struct nouveau_connector *nv_connector = nouveau_connector(connector);
+ struct nouveau_encoder *nv_encoder;
+ struct device_node *cn, *dn = pci_device_to_OF_node(dev->pdev);
+
+ if (!dn ||
+ !((nv_encoder = find_encoder_by_type(connector, OUTPUT_TMDS)) ||
+ (nv_encoder = find_encoder_by_type(connector, OUTPUT_ANALOG))))
+ return NULL;
+
+ for_each_child_of_node(dn, cn) {
+ const char *name = of_get_property(cn, "name", NULL);
+ const void *edid = of_get_property(cn, "EDID", NULL);
+ int idx = name ? name[strlen(name) - 1] - 'A' : 0;
+
+ if (nv_encoder->dcb->i2c_index == idx && edid) {
+ nv_connector->edid =
+ kmemdup(edid, EDID_LENGTH, GFP_KERNEL);
+ of_node_put(cn);
+ return nv_encoder;
+ }
+ }
+#endif
+ return NULL;
+}
+
static void
nouveau_connector_set_encoder(struct drm_connector *connector,
struct nouveau_encoder *nv_encoder)
@@ -225,6 +255,12 @@ nouveau_connector_detect(struct drm_connector *connector, bool force)
return connector_status_connected;
}
+ nv_encoder = nouveau_connector_of_detect(connector);
+ if (nv_encoder) {
+ nouveau_connector_set_encoder(connector, nv_encoder);
+ return connector_status_connected;
+ }
+
detect_analog:
nv_encoder = find_encoder_by_type(connector, OUTPUT_ANALOG);
if (!nv_encoder && !nouveau_tv_disable)