Commit ea8ee390 authored by Ben Skeggs's avatar Ben Skeggs

drm/nouveau/kms/nv50: separate out cursor surface commit

This commit separates the calculation of EVO state from the commit, in
order to make the same code useful for atomic modesetting.

The legacy interfaces have been wrapped on top of them.
Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent a7ae1561
...@@ -54,7 +54,6 @@ struct nouveau_crtc { ...@@ -54,7 +54,6 @@ struct nouveau_crtc {
struct { struct {
struct nouveau_bo *nvbo; struct nouveau_bo *nvbo;
bool visible;
uint32_t offset; uint32_t offset;
void (*set_offset)(struct nouveau_crtc *, uint32_t offset); void (*set_offset)(struct nouveau_crtc *, uint32_t offset);
void (*set_pos)(struct nouveau_crtc *, int x, int y); void (*set_pos)(struct nouveau_crtc *, int x, int y);
......
...@@ -111,6 +111,14 @@ struct nv50_head_atom { ...@@ -111,6 +111,14 @@ struct nv50_head_atom {
u16 h; u16 h;
} core; } core;
struct {
bool visible;
u32 handle;
u64 offset:40;
u8 layout:1;
u8 format:1;
} curs;
struct { struct {
u8 depth; u8 depth;
u8 cpp; u8 cpp;
...@@ -123,6 +131,7 @@ struct nv50_head_atom { ...@@ -123,6 +131,7 @@ struct nv50_head_atom {
union { union {
struct { struct {
bool core:1; bool core:1;
bool curs:1;
}; };
u8 mask; u8 mask;
} clr; } clr;
...@@ -130,6 +139,7 @@ struct nv50_head_atom { ...@@ -130,6 +139,7 @@ struct nv50_head_atom {
union { union {
struct { struct {
bool core:1; bool core:1;
bool curs:1;
bool view:1; bool view:1;
bool mode:1; bool mode:1;
}; };
...@@ -775,6 +785,62 @@ nv50_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb, ...@@ -775,6 +785,62 @@ nv50_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb,
/****************************************************************************** /******************************************************************************
* Head * Head
*****************************************************************************/ *****************************************************************************/
static void
nv50_head_curs_clr(struct nv50_head *head)
{
struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->mast.base;
u32 *push;
if ((push = evo_wait(core, 4))) {
if (core->base.user.oclass < G82_DISP_CORE_CHANNEL_DMA) {
evo_mthd(push, 0x0880 + head->base.index * 0x400, 1);
evo_data(push, 0x05000000);
} else
if (core->base.user.oclass < GF110_DISP_CORE_CHANNEL_DMA) {
evo_mthd(push, 0x0880 + head->base.index * 0x400, 1);
evo_data(push, 0x05000000);
evo_mthd(push, 0x089c + head->base.index * 0x400, 1);
evo_data(push, 0x00000000);
} else {
evo_mthd(push, 0x0480 + head->base.index * 0x300, 1);
evo_data(push, 0x05000000);
evo_mthd(push, 0x048c + head->base.index * 0x300, 1);
evo_data(push, 0x00000000);
}
evo_kick(push, core);
}
}
static void
nv50_head_curs_set(struct nv50_head *head, struct nv50_head_atom *asyh)
{
struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->mast.base;
u32 *push;
if ((push = evo_wait(core, 5))) {
if (core->base.user.oclass < G82_DISP_BASE_CHANNEL_DMA) {
evo_mthd(push, 0x0880 + head->base.index * 0x400, 2);
evo_data(push, 0x80000000 | (asyh->curs.layout << 26) |
(asyh->curs.format << 24));
evo_data(push, asyh->curs.offset >> 8);
} else
if (core->base.user.oclass < GF110_DISP_BASE_CHANNEL_DMA) {
evo_mthd(push, 0x0880 + head->base.index * 0x400, 2);
evo_data(push, 0x80000000 | (asyh->curs.layout << 26) |
(asyh->curs.format << 24));
evo_data(push, asyh->curs.offset >> 8);
evo_mthd(push, 0x089c + head->base.index * 0x400, 1);
evo_data(push, asyh->curs.handle);
} else {
evo_mthd(push, 0x0480 + head->base.index * 0x300, 2);
evo_data(push, 0x80000000 | (asyh->curs.layout << 26) |
(asyh->curs.format << 24));
evo_data(push, asyh->curs.offset >> 8);
evo_mthd(push, 0x048c + head->base.index * 0x300, 1);
evo_data(push, asyh->curs.handle);
}
evo_kick(push, core);
}
}
static void static void
nv50_head_core_clr(struct nv50_head *head) nv50_head_core_clr(struct nv50_head *head)
{ {
...@@ -941,6 +1007,8 @@ nv50_head_flush_clr(struct nv50_head *head, struct nv50_head_atom *asyh, bool y) ...@@ -941,6 +1007,8 @@ nv50_head_flush_clr(struct nv50_head *head, struct nv50_head_atom *asyh, bool y)
nv50_head_lut_clr(head); nv50_head_lut_clr(head);
if (asyh->clr.core && (!asyh->set.core || y)) if (asyh->clr.core && (!asyh->set.core || y))
nv50_head_core_clr(head); nv50_head_core_clr(head);
if (asyh->clr.curs && (!asyh->set.curs || y))
nv50_head_curs_clr(head);
} }
static void static void
...@@ -949,6 +1017,7 @@ nv50_head_flush_set(struct nv50_head *head, struct nv50_head_atom *asyh) ...@@ -949,6 +1017,7 @@ nv50_head_flush_set(struct nv50_head *head, struct nv50_head_atom *asyh)
if (asyh->set.mode ) nv50_head_mode (head, asyh); if (asyh->set.mode ) nv50_head_mode (head, asyh);
if (asyh->set.core ) nv50_head_lut_set (head, asyh); if (asyh->set.core ) nv50_head_lut_set (head, asyh);
if (asyh->set.core ) nv50_head_core_set(head, asyh); if (asyh->set.core ) nv50_head_core_set(head, asyh);
if (asyh->set.curs ) nv50_head_curs_set(head, asyh);
} }
static void static void
...@@ -1017,7 +1086,7 @@ nv50_head_atomic_check(struct drm_crtc *crtc, struct drm_crtc_state *state) ...@@ -1017,7 +1086,7 @@ nv50_head_atomic_check(struct drm_crtc *crtc, struct drm_crtc_state *state)
asyh->core.w = asyh->base.w; asyh->core.w = asyh->base.w;
asyh->core.h = asyh->base.h; asyh->core.h = asyh->base.h;
} else } else
if ((asyh->core.visible = true)) { if ((asyh->core.visible = asyh->curs.visible)) {
/*XXX: We need to either find some way of having the /*XXX: We need to either find some way of having the
* primary base layer appear black, while still * primary base layer appear black, while still
* being able to display the other layers, or we * being able to display the other layers, or we
...@@ -1039,6 +1108,7 @@ nv50_head_atomic_check(struct drm_crtc *crtc, struct drm_crtc_state *state) ...@@ -1039,6 +1108,7 @@ nv50_head_atomic_check(struct drm_crtc *crtc, struct drm_crtc_state *state)
asyh->lut.offset = head->base.lut.nvbo->bo.offset; asyh->lut.offset = head->base.lut.nvbo->bo.offset;
} else { } else {
asyh->core.visible = false; asyh->core.visible = false;
asyh->curs.visible = false;
} }
if (!drm_atomic_crtc_needs_modeset(&asyh->state)) { if (!drm_atomic_crtc_needs_modeset(&asyh->state)) {
...@@ -1049,9 +1119,19 @@ nv50_head_atomic_check(struct drm_crtc *crtc, struct drm_crtc_state *state) ...@@ -1049,9 +1119,19 @@ nv50_head_atomic_check(struct drm_crtc *crtc, struct drm_crtc_state *state)
if (armh->core.visible) { if (armh->core.visible) {
asyh->clr.core = true; asyh->clr.core = true;
} }
if (asyh->curs.visible) {
if (memcmp(&armh->curs, &asyh->curs, sizeof(asyh->curs)))
asyh->set.curs = true;
} else
if (armh->curs.visible) {
asyh->clr.curs = true;
}
} else { } else {
asyh->clr.core = armh->core.visible; asyh->clr.core = armh->core.visible;
asyh->clr.curs = armh->curs.visible;
asyh->set.core = asyh->core.visible; asyh->set.core = asyh->core.visible;
asyh->set.curs = asyh->curs.visible;
} }
memcpy(armh, asyh, sizeof(*asyh)); memcpy(armh, asyh, sizeof(*asyh));
...@@ -1304,55 +1384,27 @@ static void ...@@ -1304,55 +1384,27 @@ static void
nv50_crtc_cursor_show(struct nouveau_crtc *nv_crtc) nv50_crtc_cursor_show(struct nouveau_crtc *nv_crtc)
{ {
struct nv50_mast *mast = nv50_mast(nv_crtc->base.dev); struct nv50_mast *mast = nv50_mast(nv_crtc->base.dev);
u32 *push = evo_wait(mast, 16); struct nv50_head *head = nv50_head(&nv_crtc->base);
if (push) { struct nv50_head_atom *asyh = &head->asy;
if (nv50_vers(mast) < G82_DISP_CORE_CHANNEL_DMA) {
evo_mthd(push, 0x0880 + (nv_crtc->index * 0x400), 2); asyh->curs.visible = true;
evo_data(push, 0x85000000); asyh->curs.handle = mast->base.vram.handle;
evo_data(push, nv_crtc->cursor.nvbo->bo.offset >> 8); asyh->curs.offset = nv_crtc->cursor.nvbo->bo.offset;
} else asyh->curs.layout = 1;
if (nv50_vers(mast) < GF110_DISP_CORE_CHANNEL_DMA) { asyh->curs.format = 1;
evo_mthd(push, 0x0880 + (nv_crtc->index * 0x400), 2); nv50_head_atomic_check(&head->base.base, &asyh->state);
evo_data(push, 0x85000000); nv50_head_flush_set(head, asyh);
evo_data(push, nv_crtc->cursor.nvbo->bo.offset >> 8);
evo_mthd(push, 0x089c + (nv_crtc->index * 0x400), 1);
evo_data(push, mast->base.vram.handle);
} else {
evo_mthd(push, 0x0480 + (nv_crtc->index * 0x300), 2);
evo_data(push, 0x85000000);
evo_data(push, nv_crtc->cursor.nvbo->bo.offset >> 8);
evo_mthd(push, 0x048c + (nv_crtc->index * 0x300), 1);
evo_data(push, mast->base.vram.handle);
}
evo_kick(push, mast);
}
nv_crtc->cursor.visible = true;
} }
static void static void
nv50_crtc_cursor_hide(struct nouveau_crtc *nv_crtc) nv50_crtc_cursor_hide(struct nouveau_crtc *nv_crtc)
{ {
struct nv50_mast *mast = nv50_mast(nv_crtc->base.dev); struct nv50_head *head = nv50_head(&nv_crtc->base);
u32 *push = evo_wait(mast, 16); struct nv50_head_atom *asyh = &head->asy;
if (push) {
if (nv50_vers(mast) < G82_DISP_CORE_CHANNEL_DMA) { asyh->curs.visible = false;
evo_mthd(push, 0x0880 + (nv_crtc->index * 0x400), 1); nv50_head_atomic_check(&head->base.base, &asyh->state);
evo_data(push, 0x05000000); nv50_head_flush_clr(head, asyh, false);
} else
if (nv50_vers(mast) < GF110_DISP_CORE_CHANNEL_DMA) {
evo_mthd(push, 0x0880 + (nv_crtc->index * 0x400), 1);
evo_data(push, 0x05000000);
evo_mthd(push, 0x089c + (nv_crtc->index * 0x400), 1);
evo_data(push, 0x00000000);
} else {
evo_mthd(push, 0x0480 + (nv_crtc->index * 0x300), 1);
evo_data(push, 0x05000000);
evo_mthd(push, 0x048c + (nv_crtc->index * 0x300), 1);
evo_data(push, 0x00000000);
}
evo_kick(push, mast);
}
nv_crtc->cursor.visible = false;
} }
static void static void
...@@ -1383,7 +1435,6 @@ nv50_crtc_dpms(struct drm_crtc *crtc, int mode) ...@@ -1383,7 +1435,6 @@ nv50_crtc_dpms(struct drm_crtc *crtc, int mode)
static void static void
nv50_crtc_prepare(struct drm_crtc *crtc) nv50_crtc_prepare(struct drm_crtc *crtc)
{ {
struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
struct nv50_head *head = nv50_head(crtc); struct nv50_head *head = nv50_head(crtc);
struct nv50_head_atom *asyh = &head->asy; struct nv50_head_atom *asyh = &head->asy;
...@@ -1392,14 +1443,11 @@ nv50_crtc_prepare(struct drm_crtc *crtc) ...@@ -1392,14 +1443,11 @@ nv50_crtc_prepare(struct drm_crtc *crtc)
asyh->state.active = false; asyh->state.active = false;
nv50_head_atomic_check(&head->base.base, &asyh->state); nv50_head_atomic_check(&head->base.base, &asyh->state);
nv50_head_flush_clr(head, asyh, false); nv50_head_flush_clr(head, asyh, false);
nv50_crtc_cursor_show_hide(nv_crtc, false, false);
} }
static void static void
nv50_crtc_commit(struct drm_crtc *crtc) nv50_crtc_commit(struct drm_crtc *crtc)
{ {
struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
struct nv50_head *head = nv50_head(crtc); struct nv50_head *head = nv50_head(crtc);
struct nv50_head_atom *asyh = &head->asy; struct nv50_head_atom *asyh = &head->asy;
...@@ -1407,7 +1455,6 @@ nv50_crtc_commit(struct drm_crtc *crtc) ...@@ -1407,7 +1455,6 @@ nv50_crtc_commit(struct drm_crtc *crtc)
nv50_head_atomic_check(&head->base.base, &asyh->state); nv50_head_atomic_check(&head->base.base, &asyh->state);
nv50_head_flush_set(head, asyh); nv50_head_flush_set(head, asyh);
nv50_crtc_cursor_show_hide(nv_crtc, true, true);
nv50_display_flip_next(crtc, crtc->primary->fb, NULL, 1); nv50_display_flip_next(crtc, crtc->primary->fb, NULL, 1);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment