Commit c6a0aed4 authored by Dave Airlie's avatar Dave Airlie

drm/mst: cached EDID for logical ports (v2)

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: default avatarDave Airlie <airlied@redhat.com>
parent 138f9ebb
...@@ -861,6 +861,8 @@ static void drm_dp_destroy_port(struct kref *kref) ...@@ -861,6 +861,8 @@ static void drm_dp_destroy_port(struct kref *kref)
struct drm_dp_mst_topology_mgr *mgr = port->mgr; struct drm_dp_mst_topology_mgr *mgr = port->mgr;
if (!port->input) { if (!port->input) {
port->vcpi.num_slots = 0; port->vcpi.num_slots = 0;
kfree(port->cached_edid);
if (port->connector) if (port->connector)
(*port->mgr->cbs->destroy_connector)(mgr, port->connector); (*port->mgr->cbs->destroy_connector)(mgr, port->connector);
drm_dp_port_teardown_pdt(port, port->pdt); drm_dp_port_teardown_pdt(port, port->pdt);
...@@ -1100,6 +1102,10 @@ static void drm_dp_add_port(struct drm_dp_mst_branch *mstb, ...@@ -1100,6 +1102,10 @@ static void drm_dp_add_port(struct drm_dp_mst_branch *mstb,
char proppath[255]; char proppath[255];
build_mst_prop_path(port, mstb, proppath, sizeof(proppath)); build_mst_prop_path(port, mstb, proppath, sizeof(proppath));
port->connector = (*mstb->mgr->cbs->add_connector)(mstb->mgr, port, 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 */ /* put reference to this port */
...@@ -2170,7 +2176,8 @@ EXPORT_SYMBOL(drm_dp_mst_hpd_irq); ...@@ -2170,7 +2176,8 @@ EXPORT_SYMBOL(drm_dp_mst_hpd_irq);
* This returns the current connection state for a port. It validates the * This returns the current connection state for a port. It validates the
* port pointer still exists so the caller doesn't require a reference * 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; 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 ...@@ -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: case DP_PEER_DEVICE_SST_SINK:
status = connector_status_connected; 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; break;
case DP_PEER_DEVICE_DP_LEGACY_CONV: case DP_PEER_DEVICE_DP_LEGACY_CONV:
if (port->ldps) if (port->ldps)
...@@ -2220,7 +2231,11 @@ struct edid *drm_dp_mst_get_edid(struct drm_connector *connector, struct drm_dp_ ...@@ -2220,7 +2231,11 @@ struct edid *drm_dp_mst_get_edid(struct drm_connector *connector, struct drm_dp_
if (!port) if (!port)
return NULL; 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); drm_dp_put_port(port);
return edid; return edid;
} }
......
...@@ -283,7 +283,7 @@ intel_dp_mst_detect(struct drm_connector *connector, bool force) ...@@ -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_connector *intel_connector = to_intel_connector(connector);
struct intel_dp *intel_dp = intel_connector->mst_port; 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 static int
......
...@@ -92,6 +92,8 @@ struct drm_dp_mst_port { ...@@ -92,6 +92,8 @@ struct drm_dp_mst_port {
struct drm_dp_vcpi vcpi; struct drm_dp_vcpi vcpi;
struct drm_connector *connector; struct drm_connector *connector;
struct drm_dp_mst_topology_mgr *mgr; 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 ...@@ -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); 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); struct edid *drm_dp_mst_get_edid(struct drm_connector *connector, struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port);
......
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