Commit e19b20bb authored by Ben Skeggs's avatar Ben Skeggs

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: default avatarBen Skeggs <bskeggs@redhat.com>
parent f0d07d6e
...@@ -40,7 +40,7 @@ ...@@ -40,7 +40,7 @@
static void nouveau_connector_hotplug(void *, int); static void nouveau_connector_hotplug(void *, int);
static struct nouveau_encoder * static struct nouveau_encoder *
find_encoder_by_type(struct drm_connector *connector, int type) find_encoder(struct drm_connector *connector, int type)
{ {
struct drm_device *dev = connector->dev; struct drm_device *dev = connector->dev;
struct nouveau_encoder *nv_encoder; struct nouveau_encoder *nv_encoder;
...@@ -170,8 +170,8 @@ nouveau_connector_of_detect(struct drm_connector *connector) ...@@ -170,8 +170,8 @@ nouveau_connector_of_detect(struct drm_connector *connector)
struct device_node *cn, *dn = pci_device_to_OF_node(dev->pdev); struct device_node *cn, *dn = pci_device_to_OF_node(dev->pdev);
if (!dn || if (!dn ||
!((nv_encoder = find_encoder_by_type(connector, OUTPUT_TMDS)) || !((nv_encoder = find_encoder(connector, OUTPUT_TMDS)) ||
(nv_encoder = find_encoder_by_type(connector, OUTPUT_ANALOG)))) (nv_encoder = find_encoder(connector, OUTPUT_ANALOG))))
return NULL; return NULL;
for_each_child_of_node(dn, cn) { for_each_child_of_node(dn, cn) {
...@@ -233,6 +233,7 @@ nouveau_connector_detect(struct drm_connector *connector, bool force) ...@@ -233,6 +233,7 @@ nouveau_connector_detect(struct drm_connector *connector, bool force)
struct drm_device *dev = connector->dev; struct drm_device *dev = connector->dev;
struct nouveau_connector *nv_connector = nouveau_connector(connector); struct nouveau_connector *nv_connector = nouveau_connector(connector);
struct nouveau_encoder *nv_encoder = NULL; struct nouveau_encoder *nv_encoder = NULL;
struct nouveau_encoder *nv_partner;
struct nouveau_i2c_chan *i2c; struct nouveau_i2c_chan *i2c;
int type; int type;
...@@ -266,19 +267,22 @@ nouveau_connector_detect(struct drm_connector *connector, bool force) ...@@ -266,19 +267,22 @@ nouveau_connector_detect(struct drm_connector *connector, bool force)
* same i2c channel so the value returned from ddc_detect * same i2c channel so the value returned from ddc_detect
* isn't necessarily correct. * isn't necessarily correct.
*/ */
if (nv_connector->dcb->type == DCB_CONNECTOR_DVI_I) { nv_partner = NULL;
if (nv_encoder->dcb->type == OUTPUT_TMDS)
nv_partner = find_encoder(connector, OUTPUT_ANALOG);
if (nv_encoder->dcb->type == OUTPUT_ANALOG)
nv_partner = find_encoder(connector, OUTPUT_TMDS);
if (nv_partner && ((nv_encoder->dcb->type == OUTPUT_ANALOG &&
nv_partner->dcb->type == OUTPUT_TMDS) ||
(nv_encoder->dcb->type == OUTPUT_TMDS &&
nv_partner->dcb->type == OUTPUT_ANALOG))) {
if (nv_connector->edid->input & DRM_EDID_INPUT_DIGITAL) if (nv_connector->edid->input & DRM_EDID_INPUT_DIGITAL)
type = OUTPUT_TMDS; type = OUTPUT_TMDS;
else else
type = OUTPUT_ANALOG; type = OUTPUT_ANALOG;
nv_encoder = find_encoder_by_type(connector, type); nv_encoder = find_encoder(connector, type);
if (!nv_encoder) {
NV_ERROR(dev, "Detected %d encoder on %s, "
"but no object!\n", type,
drm_get_connector_name(connector));
return connector_status_disconnected;
}
} }
nouveau_connector_set_encoder(connector, nv_encoder); nouveau_connector_set_encoder(connector, nv_encoder);
...@@ -292,9 +296,9 @@ nouveau_connector_detect(struct drm_connector *connector, bool force) ...@@ -292,9 +296,9 @@ nouveau_connector_detect(struct drm_connector *connector, bool force)
} }
detect_analog: detect_analog:
nv_encoder = find_encoder_by_type(connector, OUTPUT_ANALOG); nv_encoder = find_encoder(connector, OUTPUT_ANALOG);
if (!nv_encoder && !nouveau_tv_disable) if (!nv_encoder && !nouveau_tv_disable)
nv_encoder = find_encoder_by_type(connector, OUTPUT_TV); nv_encoder = find_encoder(connector, OUTPUT_TV);
if (nv_encoder && force) { if (nv_encoder && force) {
struct drm_encoder *encoder = to_drm_encoder(nv_encoder); struct drm_encoder *encoder = to_drm_encoder(nv_encoder);
struct drm_encoder_helper_funcs *helper = struct drm_encoder_helper_funcs *helper =
...@@ -327,7 +331,7 @@ nouveau_connector_detect_lvds(struct drm_connector *connector, bool force) ...@@ -327,7 +331,7 @@ nouveau_connector_detect_lvds(struct drm_connector *connector, bool force)
nv_connector->edid = NULL; nv_connector->edid = NULL;
} }
nv_encoder = find_encoder_by_type(connector, OUTPUT_LVDS); nv_encoder = find_encoder(connector, OUTPUT_LVDS);
if (!nv_encoder) if (!nv_encoder)
return connector_status_disconnected; return connector_status_disconnected;
...@@ -405,7 +409,7 @@ nouveau_connector_force(struct drm_connector *connector) ...@@ -405,7 +409,7 @@ nouveau_connector_force(struct drm_connector *connector)
} else } else
type = OUTPUT_ANY; type = OUTPUT_ANY;
nv_encoder = find_encoder_by_type(connector, type); nv_encoder = find_encoder(connector, type);
if (!nv_encoder) { if (!nv_encoder) {
NV_ERROR(connector->dev, "can't find encoder to force %s on!\n", NV_ERROR(connector->dev, "can't find encoder to force %s on!\n",
drm_get_connector_name(connector)); drm_get_connector_name(connector));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment