diff options
Diffstat (limited to 'drivers/gpu/drm/display')
-rw-r--r-- | drivers/gpu/drm/display/drm_dp_mst_topology.c | 59 |
1 files changed, 59 insertions, 0 deletions
diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c index 2f7c43f88d74..97e8f8a83ed4 100644 --- a/drivers/gpu/drm/display/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c @@ -4598,6 +4598,65 @@ void drm_dp_mst_atomic_wait_for_dependencies(struct drm_atomic_state *state) EXPORT_SYMBOL(drm_dp_mst_atomic_wait_for_dependencies); /** + * drm_dp_mst_root_conn_atomic_check() - Serialize CRTC commits on MST-capable connectors operating + * in SST mode + * @new_conn_state: The new connector state of the &drm_connector + * @mgr: The MST topology manager for the &drm_connector + * + * Since MST uses fake &drm_encoder structs, the generic atomic modesetting code isn't able to + * serialize non-blocking commits happening on the real DP connector of an MST topology switching + * into/away from MST mode - as the CRTC on the real DP connector and the CRTCs on the connector's + * MST topology will never share the same &drm_encoder. + * + * This function takes care of this serialization issue, by checking a root MST connector's atomic + * state to determine if it is about to have a modeset - and then pulling in the MST topology state + * if so, along with adding any relevant CRTCs to &drm_dp_mst_topology_state.pending_crtc_mask. + * + * Drivers implementing MST must call this function from the + * &drm_connector_helper_funcs.atomic_check hook of any physical DP &drm_connector capable of + * driving MST sinks. + * + * Returns: + * 0 on success, negative error code otherwise + */ +int drm_dp_mst_root_conn_atomic_check(struct drm_connector_state *new_conn_state, + struct drm_dp_mst_topology_mgr *mgr) +{ + struct drm_atomic_state *state = new_conn_state->state; + struct drm_connector_state *old_conn_state = + drm_atomic_get_old_connector_state(state, new_conn_state->connector); + struct drm_crtc_state *crtc_state; + struct drm_dp_mst_topology_state *mst_state = NULL; + + if (new_conn_state->crtc) { + crtc_state = drm_atomic_get_new_crtc_state(state, new_conn_state->crtc); + if (crtc_state && drm_atomic_crtc_needs_modeset(crtc_state)) { + mst_state = drm_atomic_get_mst_topology_state(state, mgr); + if (IS_ERR(mst_state)) + return PTR_ERR(mst_state); + + mst_state->pending_crtc_mask |= drm_crtc_mask(new_conn_state->crtc); + } + } + + if (old_conn_state->crtc) { + crtc_state = drm_atomic_get_new_crtc_state(state, old_conn_state->crtc); + if (crtc_state && drm_atomic_crtc_needs_modeset(crtc_state)) { + if (!mst_state) { + mst_state = drm_atomic_get_mst_topology_state(state, mgr); + if (IS_ERR(mst_state)) + return PTR_ERR(mst_state); + } + + mst_state->pending_crtc_mask |= drm_crtc_mask(old_conn_state->crtc); + } + } + + return 0; +} +EXPORT_SYMBOL(drm_dp_mst_root_conn_atomic_check); + +/** * drm_dp_mst_update_slots() - updates the slot info depending on the DP ecoding format * @mst_state: mst_state to update * @link_encoding_cap: the ecoding format on the link |