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 **);
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,
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 **);
#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)
{
{
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);
evo_mthd(push, 0x0200, 1);
evo_data(push, 0x00000001);
evo_kick(push, &core->chan);
+ core->assign_windows = true;
}
}
.ntfy_init = corec37d_ntfy_init,
.ntfy_wait_done = corec37d_ntfy_wait_done,
.update = corec37d_update,
+ .wndw.owner = corec37d_wndw_owner,
.head = &headc37d,
.sor = &sorc37d,
};
{
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);
evo_mthd(push, 0x0200, 1);
evo_data(push, 0x00000001);
evo_kick(push, &core->chan);
+ core->assign_windows = true;
}
}
.ntfy_init = corec37d_ntfy_init,
.ntfy_wait_done = corec37d_ntfy_wait_done,
.update = corec37d_update,
+ .wndw.owner = corec37d_wndw_owner,
.head = &headc57d,
.sor = &sorc37d,
};
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;
}
}
+ /* 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);