mirror of
https://github.com/edk2-porting/linux-next.git
synced 2025-01-11 07:04:04 +08:00
drm/nouveau/kms/nv50: workaround EFI GOP window channel format differences
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>
This commit is contained in:
parent
6eaa1f3c59
commit
e78b1b545c
@ -2237,6 +2237,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);
|
||||
|
@ -50,11 +50,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,
|
||||
@ -62,6 +59,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);
|
||||
|
@ -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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user