drm/nouveau/kms/nv50: workaround EFI GOP window channel format differences
[ Upstream commit e78b1b545c6cfe9f87fc577128e00026fff230ba ] Should fix some initial modeset failures on (at least) Ampere boards. Signed-off-by: Ben Skeggs <bskeggs@redhat.com> Reviewed-by: Lyude Paul <lyude@redhat.com> Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:

committed by
Greg Kroah-Hartman

parent
7f422cda03
commit
b882dda2bf
@@ -2202,6 +2202,33 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state *state)
|
|||||||
interlock[NV50_DISP_INTERLOCK_CORE] = 0;
|
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). */
|
/* Update plane(s). */
|
||||||
for_each_new_plane_in_state(state, plane, new_plane_state, i) {
|
for_each_new_plane_in_state(state, plane, new_plane_state, i) {
|
||||||
struct nv50_wndw_atom *asyw = nv50_wndw_atom(new_plane_state);
|
struct nv50_wndw_atom *asyw = nv50_wndw_atom(new_plane_state);
|
||||||
|
@@ -49,11 +49,8 @@ nv50_head_flush_clr(struct nv50_head *head,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
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 ) {
|
if (asyh->set.olut ) {
|
||||||
asyh->olut.offset = nv50_lut_load(&head->olut,
|
asyh->olut.offset = nv50_lut_load(&head->olut,
|
||||||
asyh->olut.buffer,
|
asyh->olut.buffer,
|
||||||
@@ -61,6 +58,14 @@ nv50_head_flush_set(struct nv50_head *head, struct nv50_head_atom *asyh)
|
|||||||
asyh->olut.load);
|
asyh->olut.load);
|
||||||
head->func->olut_set(head, asyh);
|
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.curs ) head->func->curs_set(head, asyh);
|
||||||
if (asyh->set.base ) head->func->base (head, asyh);
|
if (asyh->set.base ) head->func->base (head, asyh);
|
||||||
if (asyh->set.ovly ) head->func->ovly (head, asyh);
|
if (asyh->set.ovly ) head->func->ovly (head, asyh);
|
||||||
|
@@ -21,6 +21,7 @@ struct nv50_head {
|
|||||||
|
|
||||||
struct nv50_head *nv50_head_create(struct drm_device *, int index);
|
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(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,
|
void nv50_head_flush_clr(struct nv50_head *head,
|
||||||
struct nv50_head_atom *asyh, bool flush);
|
struct nv50_head_atom *asyh, bool flush);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user