Skip to content

Commit

Permalink
drm/dp/mst: change MST detection scheme
Browse files Browse the repository at this point in the history
1. Get edid for all connected MST displays, not only on logical ports,
   in the same thread as MST topology detection is done:
     There are displays that have branches inside w/o logical ports.
     So in case another SST display connected downstream system can
     end-up in situation when 3 DOWN requests sent: two for
    ‘remote i2c read’ and one for ‘enum path resources’, making slots full.

2. Call notification callback in one place in the end of topology discovery/update:
     This is done to reduce number of events sent to userspace in case complex
     topology discovery is going, adding multiple number of connectors;

3. Remove notification callback call from short pulse interrupt processing function:
     This is done in order not to block interrupt processing function, in case any
     MST request will be made from it. Notification will be send from topology
     discovery/update work item.

Signed-off-by: Mykola Lysenko <[email protected]>
Reviewed-by: Harry Wentland <[email protected]>
Cc: [email protected]
Acked-by: Alex Deucher <[email protected]>
Signed-off-by: Dave Airlie <[email protected]>
  • Loading branch information
Mykola Lysenko authored and airlied committed Feb 5, 2016
1 parent a9ebb3e commit cfcfa08
Showing 1 changed file with 19 additions and 18 deletions.
37 changes: 19 additions & 18 deletions drivers/gpu/drm/drm_dp_mst_topology.c
Original file line number Diff line number Diff line change
Expand Up @@ -1130,13 +1130,11 @@ static void drm_dp_add_port(struct drm_dp_mst_branch *mstb,
drm_dp_put_port(port);
goto out;
}
if (port->port_num >= DP_MST_LOGICAL_PORT_0) {
port->cached_edid = drm_get_edid(port->connector, &port->aux.ddc);
drm_mode_connector_set_tile_property(port->connector);
}

drm_mode_connector_set_tile_property(port->connector);

(*mstb->mgr->cbs->register_connector)(port->connector);
}

out:
/* put reference to this port */
drm_dp_put_port(port);
Expand All @@ -1161,9 +1159,9 @@ static void drm_dp_update_port(struct drm_dp_mst_branch *mstb,
port->ddps = conn_stat->displayport_device_plug_status;

if (old_ddps != port->ddps) {
dowork = true;
if (port->ddps) {
drm_dp_check_port_guid(mstb, port);
dowork = true;
} else {
port->guid_valid = false;
port->available_pbn = 0;
Expand Down Expand Up @@ -1271,8 +1269,13 @@ static void drm_dp_check_and_send_link_address(struct drm_dp_mst_topology_mgr *m
if (port->input)
continue;

if (!port->ddps)
if (!port->ddps) {
if (port->cached_edid) {
kfree(port->cached_edid);
port->cached_edid = NULL;
}
continue;
}

if (!port->available_pbn)
drm_dp_send_enum_path_resources(mgr, mstb, port);
Expand All @@ -1283,6 +1286,12 @@ static void drm_dp_check_and_send_link_address(struct drm_dp_mst_topology_mgr *m
drm_dp_check_and_send_link_address(mgr, mstb_child);
drm_dp_put_mst_branch_device(mstb_child);
}
} else if (port->pdt == DP_PEER_DEVICE_SST_SINK ||
port->pdt == DP_PEER_DEVICE_DP_LEGACY_CONV) {
if (!port->cached_edid) {
port->cached_edid =
drm_get_edid(port->connector, &port->aux.ddc);
}
}
}
}
Expand All @@ -1302,6 +1311,8 @@ static void drm_dp_mst_link_probe_work(struct work_struct *work)
drm_dp_check_and_send_link_address(mgr, mstb);
drm_dp_put_mst_branch_device(mstb);
}

(*mgr->cbs->hotplug)(mgr);
}

static bool drm_dp_validate_guid(struct drm_dp_mst_topology_mgr *mgr,
Expand Down Expand Up @@ -1558,7 +1569,6 @@ static void drm_dp_send_link_address(struct drm_dp_mst_topology_mgr *mgr,
for (i = 0; i < txmsg->reply.u.link_addr.nports; i++) {
drm_dp_add_port(mstb, mgr->dev, &txmsg->reply.u.link_addr.ports[i]);
}
(*mgr->cbs->hotplug)(mgr);
}
} else {
mstb->link_address_sent = false;
Expand Down Expand Up @@ -2232,8 +2242,6 @@ static int drm_dp_mst_handle_up_req(struct drm_dp_mst_topology_mgr *mgr)

drm_dp_update_port(mstb, &msg.u.conn_stat);
DRM_DEBUG_KMS("Got CSN: pn: %d ldps:%d ddps: %d mcs: %d ip: %d pdt: %d\n", msg.u.conn_stat.port_number, msg.u.conn_stat.legacy_device_plug_status, msg.u.conn_stat.displayport_device_plug_status, msg.u.conn_stat.message_capability_status, msg.u.conn_stat.input_port, msg.u.conn_stat.peer_device_type);
(*mgr->cbs->hotplug)(mgr);

} else if (msg.req_type == DP_RESOURCE_STATUS_NOTIFY) {
drm_dp_send_up_ack_reply(mgr, mgr->mst_primary, msg.req_type, seqno, false);
if (!mstb)
Expand Down Expand Up @@ -2320,10 +2328,6 @@ enum drm_connector_status drm_dp_mst_detect_port(struct drm_connector *connector

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)
Expand Down Expand Up @@ -2378,10 +2382,7 @@ struct edid *drm_dp_mst_get_edid(struct drm_connector *connector, struct drm_dp_

if (port->cached_edid)
edid = drm_edid_duplicate(port->cached_edid);
else {
edid = drm_get_edid(connector, &port->aux.ddc);
drm_mode_connector_set_tile_property(connector);
}

port->has_audio = drm_detect_monitor_audio(edid);
drm_dp_put_port(port);
return edid;
Expand Down

0 comments on commit cfcfa08

Please sign in to comment.