Ben, do we even have Ampere support in 5.10? On Mon, 2021-08-23 at 20:54 -0400, Sasha Levin wrote: > From: Ben Skeggs <bskeggs@xxxxxxxxxx> > > [ Upstream commit e78b1b545c6cfe9f87fc577128e00026fff230ba ] > > Should fix some initial modeset failures on (at least) Ampere boards. > > Signed-off-by: Ben Skeggs <bskeggs@xxxxxxxxxx> > Reviewed-by: Lyude Paul <lyude@xxxxxxxxxx> > Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx> > --- > drivers/gpu/drm/nouveau/dispnv50/disp.c | 27 +++++++++++++++++++++++++ > drivers/gpu/drm/nouveau/dispnv50/head.c | 13 ++++++++---- > drivers/gpu/drm/nouveau/dispnv50/head.h | 1 + > 3 files changed, 37 insertions(+), 4 deletions(-) > > diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c > b/drivers/gpu/drm/nouveau/dispnv50/disp.c > index 5b8cabb099eb..c2d34c91e840 100644 > --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c > +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c > @@ -2202,6 +2202,33 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state > *state) > interlock[NV50_DISP_INTERLOCK_CORE] = 0; > } > > + /* Finish updating head(s)... > + * > + * NVD is rather picky about both where window assignments can > change, > + * *and* about certain core and window channel states matching. > + * > + * The EFI GOP driver on newer GPUs configures window channels with > a > + * different output format to what we do, and the core channel > update > + * in the assign_windows case above would result in a state > mismatch. > + * > + * Delay some of the head update until after that point to > workaround > + * the issue. This only affects the initial modeset. > + * > + * TODO: handle this better when adding flexible window mapping > + */ > + for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, > new_crtc_state, i) { > + struct nv50_head_atom *asyh = > nv50_head_atom(new_crtc_state); > + struct nv50_head *head = nv50_head(crtc); > + > + NV_ATOMIC(drm, "%s: set %04x (clr %04x)\n", crtc->name, > + asyh->set.mask, asyh->clr.mask); > + > + if (asyh->set.mask) { > + nv50_head_flush_set_wndw(head, asyh); > + interlock[NV50_DISP_INTERLOCK_CORE] = 1; > + } > + } > + > /* Update plane(s). */ > for_each_new_plane_in_state(state, plane, new_plane_state, i) { > struct nv50_wndw_atom *asyw = > nv50_wndw_atom(new_plane_state); > diff --git a/drivers/gpu/drm/nouveau/dispnv50/head.c > b/drivers/gpu/drm/nouveau/dispnv50/head.c > index 841edfaf5b9d..61826cac3061 100644 > --- a/drivers/gpu/drm/nouveau/dispnv50/head.c > +++ b/drivers/gpu/drm/nouveau/dispnv50/head.c > @@ -49,11 +49,8 @@ nv50_head_flush_clr(struct nv50_head *head, > } > > void > -nv50_head_flush_set(struct nv50_head *head, struct nv50_head_atom *asyh) > +nv50_head_flush_set_wndw(struct nv50_head *head, struct nv50_head_atom > *asyh) > { > - if (asyh->set.view ) head->func->view (head, asyh); > - if (asyh->set.mode ) head->func->mode (head, asyh); > - if (asyh->set.core ) head->func->core_set(head, asyh); > if (asyh->set.olut ) { > asyh->olut.offset = nv50_lut_load(&head->olut, > asyh->olut.buffer, > @@ -61,6 +58,14 @@ nv50_head_flush_set(struct nv50_head *head, struct > nv50_head_atom *asyh) > asyh->olut.load); > head->func->olut_set(head, asyh); > } > +} > + > +void > +nv50_head_flush_set(struct nv50_head *head, struct nv50_head_atom *asyh) > +{ > + if (asyh->set.view ) head->func->view (head, asyh); > + if (asyh->set.mode ) head->func->mode (head, asyh); > + if (asyh->set.core ) head->func->core_set(head, asyh); > if (asyh->set.curs ) head->func->curs_set(head, asyh); > if (asyh->set.base ) head->func->base (head, asyh); > if (asyh->set.ovly ) head->func->ovly (head, asyh); > diff --git a/drivers/gpu/drm/nouveau/dispnv50/head.h > b/drivers/gpu/drm/nouveau/dispnv50/head.h > index dae841dc05fd..0bac6be9ba34 100644 > --- a/drivers/gpu/drm/nouveau/dispnv50/head.h > +++ b/drivers/gpu/drm/nouveau/dispnv50/head.h > @@ -21,6 +21,7 @@ struct nv50_head { > > struct nv50_head *nv50_head_create(struct drm_device *, int index); > void nv50_head_flush_set(struct nv50_head *head, struct nv50_head_atom > *asyh); > +void nv50_head_flush_set_wndw(struct nv50_head *head, struct nv50_head_atom > *asyh); > void nv50_head_flush_clr(struct nv50_head *head, > struct nv50_head_atom *asyh, bool flush); > -- Cheers, Lyude Paul (she/her) Software Engineer at Red Hat