diff options
author | Francisco Jerez <currojerez@riseup.net> | 2010-09-09 08:33:17 -0400 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2010-09-24 02:25:48 -0400 |
commit | c16c570762bb4419f2bb764f2a7428c249d905d0 (patch) | |
tree | ddd7bbaf6843eed4994997e9f991e8e250526393 | |
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>
-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 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 | ||
133 | static struct nouveau_encoder * | ||
134 | nouveau_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 | |||
133 | static void | 163 | static void |
134 | nouveau_connector_set_encoder(struct drm_connector *connector, | 164 | nouveau_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 | |||
228 | detect_analog: | 264 | detect_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) |