aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFrancisco Jerez <currojerez@riseup.net>2010-09-09 08:33:17 -0400
committerBen Skeggs <bskeggs@redhat.com>2010-09-24 02:25:48 -0400
commitc16c570762bb4419f2bb764f2a7428c249d905d0 (patch)
treeddd7bbaf6843eed4994997e9f991e8e250526393
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>
-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,
130 return NULL; 130 return NULL;
131} 131}
132 132
133static struct nouveau_encoder *
134nouveau_connector_of_detect(struct drm_connector *connector)
135{
136#ifdef __powerpc__
137 struct drm_device *dev = connector->dev;
138 struct nouveau_connector *nv_connector = nouveau_connector(connector);
139 struct nouveau_encoder *nv_encoder;
140 struct device_node *cn, *dn = pci_device_to_OF_node(dev->pdev);
141
142 if (!dn ||
143 !((nv_encoder = find_encoder_by_type(connector, OUTPUT_TMDS)) ||
144 (nv_encoder = find_encoder_by_type(connector, OUTPUT_ANALOG))))
145 return NULL;
146
147 for_each_child_of_node(dn, cn) {
148 const char *name = of_get_property(cn, "name", NULL);
149 const void *edid = of_get_property(cn, "EDID", NULL);
150 int idx = name ? name[strlen(name) - 1] - 'A' : 0;
151
152 if (nv_encoder->dcb->i2c_index == idx && edid) {
153 nv_connector->edid =
154 kmemdup(edid, EDID_LENGTH, GFP_KERNEL);
155 of_node_put(cn);
156 return nv_encoder;
157 }
158 }
159#endif
160 return NULL;
161}
162
133static void 163static void
134nouveau_connector_set_encoder(struct drm_connector *connector, 164nouveau_connector_set_encoder(struct drm_connector *connector,
135 struct nouveau_encoder *nv_encoder) 165 struct nouveau_encoder *nv_encoder)
@@ -225,6 +255,12 @@ nouveau_connector_detect(struct drm_connector *connector, bool force)
225 return connector_status_connected; 255 return connector_status_connected;
226 } 256 }
227 257
258 nv_encoder = nouveau_connector_of_detect(connector);
259 if (nv_encoder) {
260 nouveau_connector_set_encoder(connector, nv_encoder);
261 return connector_status_connected;
262 }
263
228detect_analog: 264detect_analog:
229 nv_encoder = find_encoder_by_type(connector, OUTPUT_ANALOG); 265 nv_encoder = find_encoder_by_type(connector, OUTPUT_ANALOG);
230 if (!nv_encoder && !nouveau_tv_disable) 266 if (!nv_encoder && !nouveau_tv_disable)