drm/mst: cached EDID for logical ports (v2)
authorDave Airlie <airlied@redhat.com>
Mon, 20 Oct 2014 06:28:02 +0000 (16:28 +1000)
committerDave Airlie <airlied@redhat.com>
Mon, 8 Dec 2014 23:56:47 +0000 (09:56 +1000)
Logical ports are never going to have EDID changes,
they are used for the internal ports on MST monitors.

We cache the EDIDs from these to save time at MST probe.

v2: drop misplace tile property line, meant for other patch.

Signed-off-by: Dave Airlie <airlied@redhat.com>
drivers/gpu/drm/drm_dp_mst_topology.c
drivers/gpu/drm/i915/intel_dp_mst.c
include/drm/drm_dp_mst_helper.h

index 9798bb79fe596e24c5176fe6f1180c66e271fa97..0a9d3aad3cbae2d97be0d86f5f652513c5ad900c 100644 (file)
@@ -861,6 +861,8 @@ static void drm_dp_destroy_port(struct kref *kref)
        struct drm_dp_mst_topology_mgr *mgr = port->mgr;
        if (!port->input) {
                port->vcpi.num_slots = 0;
+
+               kfree(port->cached_edid);
                if (port->connector)
                        (*port->mgr->cbs->destroy_connector)(mgr, port->connector);
                drm_dp_port_teardown_pdt(port, port->pdt);
@@ -1100,6 +1102,10 @@ static void drm_dp_add_port(struct drm_dp_mst_branch *mstb,
                char proppath[255];
                build_mst_prop_path(port, mstb, proppath, sizeof(proppath));
                port->connector = (*mstb->mgr->cbs->add_connector)(mstb->mgr, port, proppath);
+
+               if (port->port_num >= 8) {
+                       port->cached_edid = drm_get_edid(port->connector, &port->aux.ddc);
+               }
        }
 
        /* put reference to this port */
@@ -2170,7 +2176,8 @@ EXPORT_SYMBOL(drm_dp_mst_hpd_irq);
  * This returns the current connection state for a port. It validates the
  * port pointer still exists so the caller doesn't require a reference
  */
-enum drm_connector_status drm_dp_mst_detect_port(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port)
+enum drm_connector_status drm_dp_mst_detect_port(struct drm_connector *connector,
+                                                struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port)
 {
        enum drm_connector_status status = connector_status_disconnected;
 
@@ -2189,6 +2196,10 @@ enum drm_connector_status drm_dp_mst_detect_port(struct drm_dp_mst_topology_mgr
 
        case DP_PEER_DEVICE_SST_SINK:
                status = connector_status_connected;
+               /* for logical ports - cache the EDID */
+               if (port->port_num >= 8 && !port->cached_edid) {
+                       port->cached_edid = drm_get_edid(connector, &port->aux.ddc);
+               }
                break;
        case DP_PEER_DEVICE_DP_LEGACY_CONV:
                if (port->ldps)
@@ -2220,7 +2231,11 @@ struct edid *drm_dp_mst_get_edid(struct drm_connector *connector, struct drm_dp_
        if (!port)
                return NULL;
 
-       edid = drm_get_edid(connector, &port->aux.ddc);
+       if (port->cached_edid)
+               edid = drm_edid_duplicate(port->cached_edid);
+       else
+               edid = drm_get_edid(connector, &port->aux.ddc);
+
        drm_dp_put_port(port);
        return edid;
 }
index bfe359506377852154b43c0307fb7e61c300277c..428bb3041621f2058d12d85bea56d291d6e7a643 100644 (file)
@@ -283,7 +283,7 @@ intel_dp_mst_detect(struct drm_connector *connector, bool force)
        struct intel_connector *intel_connector = to_intel_connector(connector);
        struct intel_dp *intel_dp = intel_connector->mst_port;
 
-       return drm_dp_mst_detect_port(&intel_dp->mst_mgr, intel_connector->port);
+       return drm_dp_mst_detect_port(connector, &intel_dp->mst_mgr, intel_connector->port);
 }
 
 static int
index cec6383bbdb8afbdd092ff0a869446070a37adfe..00c1da9272456e8e9bdec207affa286028664421 100644 (file)
@@ -92,6 +92,8 @@ struct drm_dp_mst_port {
        struct drm_dp_vcpi vcpi;
        struct drm_connector *connector;
        struct drm_dp_mst_topology_mgr *mgr;
+
+       struct edid *cached_edid; /* for DP logical ports - make tiling work */
 };
 
 /**
@@ -474,7 +476,7 @@ int drm_dp_mst_topology_mgr_set_mst(struct drm_dp_mst_topology_mgr *mgr, bool ms
 int drm_dp_mst_hpd_irq(struct drm_dp_mst_topology_mgr *mgr, u8 *esi, bool *handled);
 
 
-enum drm_connector_status drm_dp_mst_detect_port(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port);
+enum drm_connector_status drm_dp_mst_detect_port(struct drm_connector *connector, struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port);
 
 struct edid *drm_dp_mst_get_edid(struct drm_connector *connector, struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port);