mirror of https://gitee.com/openkylin/linux.git
drm/nouveau/kms/gv100-: move window ownership setup into modesetting path
For various complicated reasons, we need to avoid sending a core update method during display init. Something, which we've been required to do on GV100 and up because we've been assigning windows to heads there and the HW is rather picky about when that's allowed. This moves window assignment into the modesetting path at a point where it's much safer to send our first update methods to NVDisplay. Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
This commit is contained in:
parent
58ae5284f6
commit
5bb88d0794
|
@ -6,6 +6,7 @@
|
|||
struct nv50_core {
|
||||
const struct nv50_core_func *func;
|
||||
struct nv50_dmac chan;
|
||||
bool assign_windows;
|
||||
};
|
||||
|
||||
int nv50_core_new(struct nouveau_drm *, struct nv50_core **);
|
||||
|
@ -18,6 +19,10 @@ struct nv50_core_func {
|
|||
struct nvif_device *);
|
||||
void (*update)(struct nv50_core *, u32 *interlock, bool ntfy);
|
||||
|
||||
struct {
|
||||
void (*owner)(struct nv50_core *);
|
||||
} wndw;
|
||||
|
||||
const struct nv50_head_func *head;
|
||||
const struct nv50_outp_func {
|
||||
void (*ctrl)(struct nv50_core *, int or, u32 ctrl,
|
||||
|
@ -48,6 +53,7 @@ int core917d_new(struct nouveau_drm *, s32, struct nv50_core **);
|
|||
int corec37d_new(struct nouveau_drm *, s32, struct nv50_core **);
|
||||
int corec37d_ntfy_wait_done(struct nouveau_bo *, u32, struct nvif_device *);
|
||||
void corec37d_update(struct nv50_core *, u32 *, bool);
|
||||
void corec37d_wndw_owner(struct nv50_core *);
|
||||
extern const struct nv50_outp_func sorc37d;
|
||||
|
||||
int corec57d_new(struct nouveau_drm *, s32, struct nv50_core **);
|
||||
|
|
|
@ -24,6 +24,20 @@
|
|||
|
||||
#include <nouveau_bo.h>
|
||||
|
||||
void
|
||||
corec37d_wndw_owner(struct nv50_core *core)
|
||||
{
|
||||
const u32 windows = 8; /*XXX*/
|
||||
u32 *push, i;
|
||||
if ((push = evo_wait(&core->chan, 2 * windows))) {
|
||||
for (i = 0; i < windows; i++) {
|
||||
evo_mthd(push, 0x1000 + (i * 0x080), 1);
|
||||
evo_data(push, i >> 1);
|
||||
}
|
||||
evo_kick(push, &core->chan);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
corec37d_update(struct nv50_core *core, u32 *interlock, bool ntfy)
|
||||
{
|
||||
|
@ -76,12 +90,11 @@ corec37d_init(struct nv50_core *core)
|
|||
{
|
||||
const u32 windows = 8; /*XXX*/
|
||||
u32 *push, i;
|
||||
if ((push = evo_wait(&core->chan, 2 + 6 * windows + 2))) {
|
||||
if ((push = evo_wait(&core->chan, 2 + 5 * windows + 2))) {
|
||||
evo_mthd(push, 0x0208, 1);
|
||||
evo_data(push, core->chan.sync.handle);
|
||||
for (i = 0; i < windows; i++) {
|
||||
evo_mthd(push, 0x1000 + (i * 0x080), 3);
|
||||
evo_data(push, i >> 1);
|
||||
evo_mthd(push, 0x1004 + (i * 0x080), 2);
|
||||
evo_data(push, 0x0000001f);
|
||||
evo_data(push, 0x00000000);
|
||||
evo_mthd(push, 0x1010 + (i * 0x080), 1);
|
||||
|
@ -90,6 +103,7 @@ corec37d_init(struct nv50_core *core)
|
|||
evo_mthd(push, 0x0200, 1);
|
||||
evo_data(push, 0x00000001);
|
||||
evo_kick(push, &core->chan);
|
||||
core->assign_windows = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -99,6 +113,7 @@ corec37d = {
|
|||
.ntfy_init = corec37d_ntfy_init,
|
||||
.ntfy_wait_done = corec37d_ntfy_wait_done,
|
||||
.update = corec37d_update,
|
||||
.wndw.owner = corec37d_wndw_owner,
|
||||
.head = &headc37d,
|
||||
.sor = &sorc37d,
|
||||
};
|
||||
|
|
|
@ -27,12 +27,11 @@ corec57d_init(struct nv50_core *core)
|
|||
{
|
||||
const u32 windows = 8; /*XXX*/
|
||||
u32 *push, i;
|
||||
if ((push = evo_wait(&core->chan, 2 + 6 * windows + 2))) {
|
||||
if ((push = evo_wait(&core->chan, 2 + 5 * windows + 2))) {
|
||||
evo_mthd(push, 0x0208, 1);
|
||||
evo_data(push, core->chan.sync.handle);
|
||||
for (i = 0; i < windows; i++) {
|
||||
evo_mthd(push, 0x1000 + (i * 0x080), 3);
|
||||
evo_data(push, i >> 1);
|
||||
evo_mthd(push, 0x1004 + (i * 0x080), 2);
|
||||
evo_data(push, 0x0000000f);
|
||||
evo_data(push, 0x00000000);
|
||||
evo_mthd(push, 0x1010 + (i * 0x080), 1);
|
||||
|
@ -41,6 +40,7 @@ corec57d_init(struct nv50_core *core)
|
|||
evo_mthd(push, 0x0200, 1);
|
||||
evo_data(push, 0x00000001);
|
||||
evo_kick(push, &core->chan);
|
||||
core->assign_windows = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -50,6 +50,7 @@ corec57d = {
|
|||
.ntfy_init = corec37d_ntfy_init,
|
||||
.ntfy_wait_done = corec37d_ntfy_wait_done,
|
||||
.update = corec37d_update,
|
||||
.wndw.owner = corec37d_wndw_owner,
|
||||
.head = &headc57d,
|
||||
.sor = &sorc37d,
|
||||
};
|
||||
|
|
|
@ -1933,6 +1933,7 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state *state)
|
|||
struct nouveau_drm *drm = nouveau_drm(dev);
|
||||
struct nv50_disp *disp = nv50_disp(dev);
|
||||
struct nv50_atom *atom = nv50_atom(state);
|
||||
struct nv50_core *core = disp->core;
|
||||
struct nv50_outp_atom *outp, *outt;
|
||||
u32 interlock[NV50_DISP_INTERLOCK__SIZE] = {};
|
||||
int i;
|
||||
|
@ -2051,6 +2052,21 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state *state)
|
|||
}
|
||||
}
|
||||
|
||||
/* Update window->head assignment.
|
||||
*
|
||||
* This has to happen in an update that's not interlocked with
|
||||
* any window channels to avoid hitting HW error checks.
|
||||
*
|
||||
*TODO: Proper handling of window ownership (Turing apparently
|
||||
* supports non-fixed mappings).
|
||||
*/
|
||||
if (core->assign_windows) {
|
||||
core->func->wndw.owner(core);
|
||||
core->func->update(core, interlock, false);
|
||||
core->assign_windows = false;
|
||||
interlock[NV50_DISP_INTERLOCK_CORE] = 0;
|
||||
}
|
||||
|
||||
/* 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);
|
||||
|
|
Loading…
Reference in New Issue