Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+19 -15
+19 -15
drivers/gpu/drm/nouveau/nouveau_connector.c
··· 40 40 static void nouveau_connector_hotplug(void *, int); 41 41 42 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 45 struct drm_device *dev = connector->dev; 46 46 struct nouveau_encoder *nv_encoder; ··· 170 170 struct device_node *cn, *dn = pci_device_to_OF_node(dev->pdev); 171 171 172 172 if (!dn || 173 - !((nv_encoder = find_encoder_by_type(connector, OUTPUT_TMDS)) || 174 - (nv_encoder = find_encoder_by_type(connector, OUTPUT_ANALOG)))) 173 + !((nv_encoder = find_encoder(connector, OUTPUT_TMDS)) || 174 + (nv_encoder = find_encoder(connector, OUTPUT_ANALOG)))) 175 175 return NULL; 176 176 177 177 for_each_child_of_node(dn, cn) { ··· 233 233 struct drm_device *dev = connector->dev; 234 234 struct nouveau_connector *nv_connector = nouveau_connector(connector); 235 235 struct nouveau_encoder *nv_encoder = NULL; 236 + struct nouveau_encoder *nv_partner; 236 237 struct nouveau_i2c_chan *i2c; 237 238 int type; 238 239 ··· 267 266 * same i2c channel so the value returned from ddc_detect 268 267 * isn't necessarily correct. 269 268 */ 270 - if (nv_connector->dcb->type == DCB_CONNECTOR_DVI_I) { 269 + nv_partner = NULL; 270 + if (nv_encoder->dcb->type == OUTPUT_TMDS) 271 + nv_partner = find_encoder(connector, OUTPUT_ANALOG); 272 + if (nv_encoder->dcb->type == OUTPUT_ANALOG) 273 + nv_partner = find_encoder(connector, OUTPUT_TMDS); 274 + 275 + if (nv_partner && ((nv_encoder->dcb->type == OUTPUT_ANALOG && 276 + nv_partner->dcb->type == OUTPUT_TMDS) || 277 + (nv_encoder->dcb->type == OUTPUT_TMDS && 278 + nv_partner->dcb->type == OUTPUT_ANALOG))) { 271 279 if (nv_connector->edid->input & DRM_EDID_INPUT_DIGITAL) 272 280 type = OUTPUT_TMDS; 273 281 else 274 282 type = OUTPUT_ANALOG; 275 283 276 - nv_encoder = find_encoder_by_type(connector, type); 277 - if (!nv_encoder) { 278 - NV_ERROR(dev, "Detected %d encoder on %s, " 279 - "but no object!\n", type, 280 - drm_get_connector_name(connector)); 281 - return connector_status_disconnected; 282 - } 284 + nv_encoder = find_encoder(connector, type); 283 285 } 284 286 285 287 nouveau_connector_set_encoder(connector, nv_encoder); ··· 296 292 } 297 293 298 294 detect_analog: 299 - nv_encoder = find_encoder_by_type(connector, OUTPUT_ANALOG); 295 + nv_encoder = find_encoder(connector, OUTPUT_ANALOG); 300 296 if (!nv_encoder && !nouveau_tv_disable) 301 - nv_encoder = find_encoder_by_type(connector, OUTPUT_TV); 297 + nv_encoder = find_encoder(connector, OUTPUT_TV); 302 298 if (nv_encoder && force) { 303 299 struct drm_encoder *encoder = to_drm_encoder(nv_encoder); 304 300 struct drm_encoder_helper_funcs *helper = ··· 331 327 nv_connector->edid = NULL; 332 328 } 333 329 334 - nv_encoder = find_encoder_by_type(connector, OUTPUT_LVDS); 330 + nv_encoder = find_encoder(connector, OUTPUT_LVDS); 335 331 if (!nv_encoder) 336 332 return connector_status_disconnected; 337 333 ··· 409 405 } else 410 406 type = OUTPUT_ANY; 411 407 412 - nv_encoder = find_encoder_by_type(connector, type); 408 + nv_encoder = find_encoder(connector, type); 413 409 if (!nv_encoder) { 414 410 NV_ERROR(connector->dev, "can't find encoder to force %s on!\n", 415 411 drm_get_connector_name(connector));