drm/nouveau/dp: probe dpcd to determine connectedness
authorBen Skeggs <bskeggs@redhat.com>
Fri, 6 Jun 2014 08:09:55 +0000 (18:09 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Wed, 11 Jun 2014 06:11:42 +0000 (16:11 +1000)
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
drivers/gpu/drm/nouveau/nouveau_connector.c
drivers/gpu/drm/nouveau/nouveau_dp.c
drivers/gpu/drm/nouveau/nouveau_encoder.h

index 7dac5e21679998786c17584cb6c75d9c79fce260..1fa222e8f007ba5e0b8f94a8bfcf911bee34a49d 100644 (file)
@@ -111,15 +111,15 @@ nouveau_connector_destroy(struct drm_connector *connector)
        kfree(connector);
 }
 
-static struct nouveau_i2c_port *
-nouveau_connector_ddc_detect(struct drm_connector *connector,
-                            struct nouveau_encoder **pnv_encoder)
+static struct nouveau_encoder *
+nouveau_connector_ddc_detect(struct drm_connector *connector)
 {
        struct drm_device *dev = connector->dev;
        struct nouveau_connector *nv_connector = nouveau_connector(connector);
        struct nouveau_drm *drm = nouveau_drm(dev);
        struct nouveau_gpio *gpio = nouveau_gpio(drm->device);
-       struct nouveau_i2c_port *port = NULL;
+       struct nouveau_encoder *nv_encoder;
+       struct drm_mode_object *obj;
        int i, panel = -ENODEV;
 
        /* eDP panels need powering on by us (if the VBIOS doesn't default it
@@ -134,13 +134,9 @@ nouveau_connector_ddc_detect(struct drm_connector *connector,
                }
        }
 
-       for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
-               struct nouveau_encoder *nv_encoder;
-               struct drm_mode_object *obj;
-               int id;
-
-               id = connector->encoder_ids[i];
-               if (!id)
+       for (i = 0; nv_encoder = NULL, i < DRM_CONNECTOR_MAX_ENCODER; i++) {
+               int id = connector->encoder_ids[i];
+               if (id == 0)
                        break;
 
                obj = drm_mode_object_find(dev, id, DRM_MODE_OBJECT_ENCODER);
@@ -148,22 +144,24 @@ nouveau_connector_ddc_detect(struct drm_connector *connector,
                        continue;
                nv_encoder = nouveau_encoder(obj_to_encoder(obj));
 
-               port = nv_encoder->i2c;
-               if (port && nv_probe_i2c(port, 0x50)) {
-                       *pnv_encoder = nv_encoder;
-                       break;
+               if (nv_encoder->dcb->type == DCB_OUTPUT_DP) {
+                       int ret = nouveau_dp_detect(nv_encoder);
+                       if (ret == 0)
+                               break;
+               } else
+               if (nv_encoder->i2c) {
+                       if (nv_probe_i2c(nv_encoder->i2c, 0x50))
+                               break;
                }
-
-               port = NULL;
        }
 
        /* eDP panel not detected, restore panel power GPIO to previous
         * state to avoid confusing the SOR for other output types.
         */
-       if (!port && panel == 0)
+       if (!nv_encoder && panel == 0)
                gpio->set(gpio, 0, DCB_GPIO_PANEL_POWER, 0xff, panel);
 
-       return port;
+       return nv_encoder;
 }
 
 static struct nouveau_encoder *
@@ -262,8 +260,8 @@ nouveau_connector_detect(struct drm_connector *connector, bool force)
        if (ret < 0 && ret != -EACCES)
                return conn_status;
 
-       i2c = nouveau_connector_ddc_detect(connector, &nv_encoder);
-       if (i2c) {
+       nv_encoder = nouveau_connector_ddc_detect(connector);
+       if (nv_encoder && (i2c = nv_encoder->i2c) != NULL) {
                nv_connector->edid = drm_get_edid(connector, &i2c->adapter);
                drm_mode_connector_update_edid_property(connector,
                                                        nv_connector->edid);
@@ -273,14 +271,6 @@ nouveau_connector_detect(struct drm_connector *connector, bool force)
                        goto detect_analog;
                }
 
-               if (nv_encoder->dcb->type == DCB_OUTPUT_DP &&
-                   !nouveau_dp_detect(to_drm_encoder(nv_encoder))) {
-                       NV_ERROR(drm, "Detected %s, but failed init\n",
-                                connector->name);
-                       conn_status = connector_status_disconnected;
-                       goto out;
-               }
-
                /* Override encoder type for DVI-I based on whether EDID
                 * says the display is digital or analog, both use the
                 * same i2c channel so the value returned from ddc_detect
index 36fd22500569541505870dc1e185eddc138627db..5675ffc175aed933711a5acef1ffe34e86fd9059 100644 (file)
@@ -55,11 +55,10 @@ nouveau_dp_probe_oui(struct drm_device *dev, struct nouveau_i2c_port *auxch,
 
 }
 
-bool
-nouveau_dp_detect(struct drm_encoder *encoder)
+int
+nouveau_dp_detect(struct nouveau_encoder *nv_encoder)
 {
-       struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
-       struct drm_device *dev = encoder->dev;
+       struct drm_device *dev = nv_encoder->base.base.dev;
        struct nouveau_drm *drm = nouveau_drm(dev);
        struct nouveau_i2c_port *auxch;
        u8 *dpcd = nv_encoder->dp.dpcd;
@@ -67,11 +66,11 @@ nouveau_dp_detect(struct drm_encoder *encoder)
 
        auxch = nv_encoder->i2c;
        if (!auxch)
-               return false;
+               return -ENODEV;
 
        ret = nv_rdaux(auxch, DP_DPCD_REV, dpcd, 8);
        if (ret)
-               return false;
+               return ret;
 
        nv_encoder->dp.link_bw = 27000 * dpcd[1];
        nv_encoder->dp.link_nr = dpcd[2] & DP_MAX_LANE_COUNT_MASK;
@@ -91,6 +90,5 @@ nouveau_dp_detect(struct drm_encoder *encoder)
                     nv_encoder->dp.link_nr, nv_encoder->dp.link_bw);
 
        nouveau_dp_probe_oui(dev, auxch, dpcd);
-
-       return true;
+       return 0;
 }
index fcf89c8c67b780c3f1884187fc8e9dd5b05d94b2..5f0e37fc28490901a96f6f6dc1228d02e6bb7b98 100644 (file)
@@ -85,9 +85,7 @@ get_slave_funcs(struct drm_encoder *enc)
 }
 
 /* nouveau_dp.c */
-bool nouveau_dp_detect(struct drm_encoder *);
-void nouveau_dp_dpms(struct drm_encoder *, int mode, u32 datarate,
-                    struct nouveau_object *);
+int nouveau_dp_detect(struct nouveau_encoder *);
 
 struct nouveau_connector *
 nouveau_encoder_connector_get(struct nouveau_encoder *encoder);