diff options
author | Ben Skeggs <bskeggs@redhat.com> | 2011-07-11 23:32:07 -0400 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2011-07-24 19:41:34 -0400 |
commit | e19b20bbd291f13581975bd0bdc1d92ce2385cc4 (patch) | |
tree | f4c89e039114e1698632a86044a6b0394ee4acc3 /drivers/gpu | |
parent | f0d07d6e89e1abe75748dd506dee3df8f6b86864 (diff) |
drm/nouveau: ignore connector type when deciding digital/analog on DVI-I
If the connector table is lying, which it often does on the boards of a
particular manufacturer, we may end up doing the wrong thing. Listen
to the encoder table instead, it's more reliable.
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu')
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_connector.c | 34 |
1 files changed, 19 insertions, 15 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index 1595d0b6e815..939d4df07777 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c | |||
@@ -40,7 +40,7 @@ | |||
40 | static void nouveau_connector_hotplug(void *, int); | 40 | static void nouveau_connector_hotplug(void *, int); |
41 | 41 | ||
42 | static struct nouveau_encoder * | 42 | static struct nouveau_encoder * |
43 | find_encoder_by_type(struct drm_connector *connector, int type) | 43 | find_encoder(struct drm_connector *connector, int type) |
44 | { | 44 | { |
45 | struct drm_device *dev = connector->dev; | 45 | struct drm_device *dev = connector->dev; |
46 | struct nouveau_encoder *nv_encoder; | 46 | struct nouveau_encoder *nv_encoder; |
@@ -170,8 +170,8 @@ nouveau_connector_of_detect(struct drm_connector *connector) | |||
170 | struct device_node *cn, *dn = pci_device_to_OF_node(dev->pdev); | 170 | struct device_node *cn, *dn = pci_device_to_OF_node(dev->pdev); |
171 | 171 | ||
172 | if (!dn || | 172 | if (!dn || |
173 | !((nv_encoder = find_encoder_by_type(connector, OUTPUT_TMDS)) || | 173 | !((nv_encoder = find_encoder(connector, OUTPUT_TMDS)) || |
174 | (nv_encoder = find_encoder_by_type(connector, OUTPUT_ANALOG)))) | 174 | (nv_encoder = find_encoder(connector, OUTPUT_ANALOG)))) |
175 | return NULL; | 175 | return NULL; |
176 | 176 | ||
177 | for_each_child_of_node(dn, cn) { | 177 | for_each_child_of_node(dn, cn) { |
@@ -233,6 +233,7 @@ nouveau_connector_detect(struct drm_connector *connector, bool force) | |||
233 | struct drm_device *dev = connector->dev; | 233 | struct drm_device *dev = connector->dev; |
234 | struct nouveau_connector *nv_connector = nouveau_connector(connector); | 234 | struct nouveau_connector *nv_connector = nouveau_connector(connector); |
235 | struct nouveau_encoder *nv_encoder = NULL; | 235 | struct nouveau_encoder *nv_encoder = NULL; |
236 | struct nouveau_encoder *nv_partner; | ||
236 | struct nouveau_i2c_chan *i2c; | 237 | struct nouveau_i2c_chan *i2c; |
237 | int type; | 238 | int type; |
238 | 239 | ||
@@ -266,19 +267,22 @@ nouveau_connector_detect(struct drm_connector *connector, bool force) | |||
266 | * same i2c channel so the value returned from ddc_detect | 267 | * same i2c channel so the value returned from ddc_detect |
267 | * isn't necessarily correct. | 268 | * isn't necessarily correct. |
268 | */ | 269 | */ |
269 | if (nv_connector->dcb->type == DCB_CONNECTOR_DVI_I) { | 270 | nv_partner = NULL; |
271 | if (nv_encoder->dcb->type == OUTPUT_TMDS) | ||
272 | nv_partner = find_encoder(connector, OUTPUT_ANALOG); | ||
273 | if (nv_encoder->dcb->type == OUTPUT_ANALOG) | ||
274 | nv_partner = find_encoder(connector, OUTPUT_TMDS); | ||
275 | |||
276 | if (nv_partner && ((nv_encoder->dcb->type == OUTPUT_ANALOG && | ||
277 | nv_partner->dcb->type == OUTPUT_TMDS) || | ||
278 | (nv_encoder->dcb->type == OUTPUT_TMDS && | ||
279 | nv_partner->dcb->type == OUTPUT_ANALOG))) { | ||
270 | if (nv_connector->edid->input & DRM_EDID_INPUT_DIGITAL) | 280 | if (nv_connector->edid->input & DRM_EDID_INPUT_DIGITAL) |
271 | type = OUTPUT_TMDS; | 281 | type = OUTPUT_TMDS; |
272 | else | 282 | else |
273 | type = OUTPUT_ANALOG; | 283 | type = OUTPUT_ANALOG; |
274 | 284 | ||
275 | nv_encoder = find_encoder_by_type(connector, type); | 285 | nv_encoder = find_encoder(connector, type); |
276 | if (!nv_encoder) { | ||
277 | NV_ERROR(dev, "Detected %d encoder on %s, " | ||
278 | "but no object!\n", type, | ||
279 | drm_get_connector_name(connector)); | ||
280 | return connector_status_disconnected; | ||
281 | } | ||
282 | } | 286 | } |
283 | 287 | ||
284 | nouveau_connector_set_encoder(connector, nv_encoder); | 288 | nouveau_connector_set_encoder(connector, nv_encoder); |
@@ -292,9 +296,9 @@ nouveau_connector_detect(struct drm_connector *connector, bool force) | |||
292 | } | 296 | } |
293 | 297 | ||
294 | detect_analog: | 298 | detect_analog: |
295 | nv_encoder = find_encoder_by_type(connector, OUTPUT_ANALOG); | 299 | nv_encoder = find_encoder(connector, OUTPUT_ANALOG); |
296 | if (!nv_encoder && !nouveau_tv_disable) | 300 | if (!nv_encoder && !nouveau_tv_disable) |
297 | nv_encoder = find_encoder_by_type(connector, OUTPUT_TV); | 301 | nv_encoder = find_encoder(connector, OUTPUT_TV); |
298 | if (nv_encoder && force) { | 302 | if (nv_encoder && force) { |
299 | struct drm_encoder *encoder = to_drm_encoder(nv_encoder); | 303 | struct drm_encoder *encoder = to_drm_encoder(nv_encoder); |
300 | struct drm_encoder_helper_funcs *helper = | 304 | struct drm_encoder_helper_funcs *helper = |
@@ -327,7 +331,7 @@ nouveau_connector_detect_lvds(struct drm_connector *connector, bool force) | |||
327 | nv_connector->edid = NULL; | 331 | nv_connector->edid = NULL; |
328 | } | 332 | } |
329 | 333 | ||
330 | nv_encoder = find_encoder_by_type(connector, OUTPUT_LVDS); | 334 | nv_encoder = find_encoder(connector, OUTPUT_LVDS); |
331 | if (!nv_encoder) | 335 | if (!nv_encoder) |
332 | return connector_status_disconnected; | 336 | return connector_status_disconnected; |
333 | 337 | ||
@@ -405,7 +409,7 @@ nouveau_connector_force(struct drm_connector *connector) | |||
405 | } else | 409 | } else |
406 | type = OUTPUT_ANY; | 410 | type = OUTPUT_ANY; |
407 | 411 | ||
408 | nv_encoder = find_encoder_by_type(connector, type); | 412 | nv_encoder = find_encoder(connector, type); |
409 | if (!nv_encoder) { | 413 | if (!nv_encoder) { |
410 | NV_ERROR(connector->dev, "can't find encoder to force %s on!\n", | 414 | NV_ERROR(connector->dev, "can't find encoder to force %s on!\n", |
411 | drm_get_connector_name(connector)); | 415 | drm_get_connector_name(connector)); |