diff options
author | Francisco Jerez <currojerez@riseup.net> | 2010-09-09 14:33:17 +0200 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2010-09-24 16:25:48 +1000 |
commit | c16c570762bb4419f2bb764f2a7428c249d905d0 (patch) | |
tree | ddd7bbaf6843eed4994997e9f991e8e250526393 /drivers/gpu/drm/nouveau/nouveau_connector.c | |
parent | 9f56b1265d66f6698e3155529e6c5d0c34b37afa (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.c | 36 |
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 87186a4bbf0..98c214c3492 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) |