|
@@ -1142,31 +1142,58 @@ nv50_mstm_enable(struct nv50_mstm *mstm, u8 dpcd, int state)
|
|
|
int
|
|
|
nv50_mstm_detect(struct nv50_mstm *mstm, u8 dpcd[8], int allow)
|
|
|
{
|
|
|
- int ret, state = 0;
|
|
|
+ struct drm_dp_aux *aux;
|
|
|
+ int ret;
|
|
|
+ bool old_state, new_state;
|
|
|
+ u8 mstm_ctrl;
|
|
|
|
|
|
if (!mstm)
|
|
|
return 0;
|
|
|
|
|
|
- if (dpcd[0] >= 0x12) {
|
|
|
- ret = drm_dp_dpcd_readb(mstm->mgr.aux, DP_MSTM_CAP, &dpcd[1]);
|
|
|
+ mutex_lock(&mstm->mgr.lock);
|
|
|
+
|
|
|
+ old_state = mstm->mgr.mst_state;
|
|
|
+ new_state = old_state;
|
|
|
+ aux = mstm->mgr.aux;
|
|
|
+
|
|
|
+ if (old_state) {
|
|
|
+ /* Just check that the MST hub is still as we expect it */
|
|
|
+ ret = drm_dp_dpcd_readb(aux, DP_MSTM_CTRL, &mstm_ctrl);
|
|
|
+ if (ret < 0 || !(mstm_ctrl & DP_MST_EN)) {
|
|
|
+ DRM_DEBUG_KMS("Hub gone, disabling MST topology\n");
|
|
|
+ new_state = false;
|
|
|
+ }
|
|
|
+ } else if (dpcd[0] >= 0x12) {
|
|
|
+ ret = drm_dp_dpcd_readb(aux, DP_MSTM_CAP, &dpcd[1]);
|
|
|
if (ret < 0)
|
|
|
- return ret;
|
|
|
+ goto probe_error;
|
|
|
|
|
|
if (!(dpcd[1] & DP_MST_CAP))
|
|
|
dpcd[0] = 0x11;
|
|
|
else
|
|
|
- state = allow;
|
|
|
+ new_state = allow;
|
|
|
}
|
|
|
|
|
|
- ret = nv50_mstm_enable(mstm, dpcd[0], state);
|
|
|
+ if (new_state == old_state) {
|
|
|
+ mutex_unlock(&mstm->mgr.lock);
|
|
|
+ return new_state;
|
|
|
+ }
|
|
|
+
|
|
|
+ ret = nv50_mstm_enable(mstm, dpcd[0], new_state);
|
|
|
if (ret)
|
|
|
- return ret;
|
|
|
+ goto probe_error;
|
|
|
+
|
|
|
+ mutex_unlock(&mstm->mgr.lock);
|
|
|
|
|
|
- ret = drm_dp_mst_topology_mgr_set_mst(&mstm->mgr, state);
|
|
|
+ ret = drm_dp_mst_topology_mgr_set_mst(&mstm->mgr, new_state);
|
|
|
if (ret)
|
|
|
return nv50_mstm_enable(mstm, dpcd[0], 0);
|
|
|
|
|
|
- return mstm->mgr.mst_state;
|
|
|
+ return new_state;
|
|
|
+
|
|
|
+probe_error:
|
|
|
+ mutex_unlock(&mstm->mgr.lock);
|
|
|
+ return ret;
|
|
|
}
|
|
|
|
|
|
static void
|