summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/nouveau/dispnv50/disp.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/nouveau/dispnv50/disp.c')
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/disp.c31
1 files changed, 18 insertions, 13 deletions
diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c
index 2e8a5fd9b262..e8bb35f6d015 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
@@ -659,8 +659,6 @@ struct nv50_mstc {
struct drm_display_mode *native;
struct edid *edid;
-
- int pbn;
};
struct nv50_msto {
@@ -765,18 +763,26 @@ nv50_msto_atomic_check(struct drm_encoder *encoder,
struct drm_connector *connector = conn_state->connector;
struct nv50_mstc *mstc = nv50_mstc(connector);
struct nv50_mstm *mstm = mstc->mstm;
- int bpp = connector->display_info.bpc * 3;
+ struct nv50_head_atom *asyh = nv50_head_atom(crtc_state);
int slots;
- mstc->pbn = drm_dp_calc_pbn_mode(crtc_state->adjusted_mode.clock,
- bpp);
+ /* When restoring duplicated states, we need to make sure that the
+ * bw remains the same and avoid recalculating it, as the connector's
+ * bpc may have changed after the state was duplicated
+ */
+ if (!state->duplicated)
+ asyh->dp.pbn =
+ drm_dp_calc_pbn_mode(crtc_state->adjusted_mode.clock,
+ connector->display_info.bpc * 3);
- if (drm_atomic_crtc_needs_modeset(crtc_state) &&
- !drm_connector_is_unregistered(connector)) {
+ if (drm_atomic_crtc_needs_modeset(crtc_state)) {
slots = drm_dp_atomic_find_vcpi_slots(state, &mstm->mgr,
- mstc->port, mstc->pbn);
+ mstc->port,
+ asyh->dp.pbn);
if (slots < 0)
return slots;
+
+ asyh->dp.tu = slots;
}
return nv50_outp_atomic_check_view(encoder, crtc_state, conn_state,
@@ -787,13 +793,13 @@ static void
nv50_msto_enable(struct drm_encoder *encoder)
{
struct nv50_head *head = nv50_head(encoder->crtc);
+ struct nv50_head_atom *armh = nv50_head_atom(head->base.base.state);
struct nv50_msto *msto = nv50_msto(encoder);
struct nv50_mstc *mstc = NULL;
struct nv50_mstm *mstm = NULL;
struct drm_connector *connector;
struct drm_connector_list_iter conn_iter;
u8 proto, depth;
- int slots;
bool r;
drm_connector_list_iter_begin(encoder->dev, &conn_iter);
@@ -809,8 +815,8 @@ nv50_msto_enable(struct drm_encoder *encoder)
if (WARN_ON(!mstc))
return;
- slots = drm_dp_find_vcpi_slots(&mstm->mgr, mstc->pbn);
- r = drm_dp_mst_allocate_vcpi(&mstm->mgr, mstc->port, mstc->pbn, slots);
+ r = drm_dp_mst_allocate_vcpi(&mstm->mgr, mstc->port, armh->dp.pbn,
+ armh->dp.tu);
WARN_ON(!r);
if (!mstm->links++)
@@ -828,8 +834,7 @@ nv50_msto_enable(struct drm_encoder *encoder)
default: depth = 0x6; break;
}
- mstm->outp->update(mstm->outp, head->base.index,
- nv50_head_atom(head->base.base.state), proto, depth);
+ mstm->outp->update(mstm->outp, head->base.index, armh, proto, depth);
msto->head = head;
msto->mstc = mstc;