Commit 53e0a3e7 authored by Ben Skeggs's avatar Ben Skeggs

drm/nouveau/kms/nv50-: simplify tracking of channel interlocks

Instead of windows returning their core channel interlock mask if they
know core has been modified, it's recorded unconditionally and used if
required when update methods are emitted.

This will be required to support Volta.
Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent 34508f9d
...@@ -29,9 +29,12 @@ nouveau-y += dispnv50/base907c.o ...@@ -29,9 +29,12 @@ nouveau-y += dispnv50/base907c.o
nouveau-y += dispnv50/curs.o nouveau-y += dispnv50/curs.o
nouveau-y += dispnv50/curs507a.o nouveau-y += dispnv50/curs507a.o
nouveau-y += dispnv50/curs907a.o
nouveau-y += dispnv50/oimm.o nouveau-y += dispnv50/oimm.o
nouveau-y += dispnv50/oimm507b.o nouveau-y += dispnv50/oimm507b.o
nouveau-y += dispnv50/ovly.o nouveau-y += dispnv50/ovly.o
nouveau-y += dispnv50/ovly507e.o nouveau-y += dispnv50/ovly507e.o
nouveau-y += dispnv50/ovly827e.o
nouveau-y += dispnv50/ovly907e.o
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
int base507c_new(struct nouveau_drm *, int, s32, struct nv50_wndw **); int base507c_new(struct nouveau_drm *, int, s32, struct nv50_wndw **);
int base507c_new_(const struct nv50_wndw_func *, const u32 *format, int base507c_new_(const struct nv50_wndw_func *, const u32 *format,
struct nouveau_drm *, int head, s32 oclass, struct nouveau_drm *, int head, s32 oclass,
struct nv50_wndw **); u32 interlock_data, struct nv50_wndw **);
extern const u32 base507c_format[]; extern const u32 base507c_format[];
int base507c_acquire(struct nv50_wndw *, struct nv50_wndw_atom *, int base507c_acquire(struct nv50_wndw *, struct nv50_wndw_atom *,
struct nv50_head_atom *); struct nv50_head_atom *);
...@@ -19,7 +19,7 @@ void base507c_ntfy_clr(struct nv50_wndw *); ...@@ -19,7 +19,7 @@ void base507c_ntfy_clr(struct nv50_wndw *);
int base507c_ntfy_wait_begun(struct nouveau_bo *, u32, struct nvif_device *); int base507c_ntfy_wait_begun(struct nouveau_bo *, u32, struct nvif_device *);
void base507c_image_clr(struct nv50_wndw *); void base507c_image_clr(struct nv50_wndw *);
void base507c_lut(struct nv50_wndw *, struct nv50_wndw_atom *); void base507c_lut(struct nv50_wndw *, struct nv50_wndw_atom *);
u32 base507c_update(struct nv50_wndw *, u32); void base507c_update(struct nv50_wndw *, u32 *);
int base827c_new(struct nouveau_drm *, int, s32, struct nv50_wndw **); int base827c_new(struct nouveau_drm *, int, s32, struct nv50_wndw **);
......
...@@ -28,17 +28,15 @@ ...@@ -28,17 +28,15 @@
#include <drm/drm_plane_helper.h> #include <drm/drm_plane_helper.h>
#include "nouveau_bo.h" #include "nouveau_bo.h"
u32 void
base507c_update(struct nv50_wndw *wndw, u32 interlock) base507c_update(struct nv50_wndw *wndw, u32 *interlock)
{ {
u32 *push; u32 *push;
if ((push = evo_wait(&wndw->wndw, 2))) { if ((push = evo_wait(&wndw->wndw, 2))) {
evo_mthd(push, 0x0080, 1); evo_mthd(push, 0x0080, 1);
evo_data(push, interlock); evo_data(push, interlock[NV50_DISP_INTERLOCK_CORE]);
evo_kick(push, &wndw->wndw); evo_kick(push, &wndw->wndw);
return interlock ? 2 << (wndw->id * 8) : 0;
} }
return 0;
} }
void void
...@@ -224,7 +222,7 @@ base507c = { ...@@ -224,7 +222,7 @@ base507c = {
int int
base507c_new_(const struct nv50_wndw_func *func, const u32 *format, base507c_new_(const struct nv50_wndw_func *func, const u32 *format,
struct nouveau_drm *drm, int head, s32 oclass, struct nouveau_drm *drm, int head, s32 oclass, u32 interlock_data,
struct nv50_wndw **pwndw) struct nv50_wndw **pwndw)
{ {
struct nv50_disp_base_channel_dma_v0 args = { struct nv50_disp_base_channel_dma_v0 args = {
...@@ -235,7 +233,8 @@ base507c_new_(const struct nv50_wndw_func *func, const u32 *format, ...@@ -235,7 +233,8 @@ base507c_new_(const struct nv50_wndw_func *func, const u32 *format,
int ret; int ret;
ret = nv50_wndw_new_(func, drm->dev, DRM_PLANE_TYPE_PRIMARY, ret = nv50_wndw_new_(func, drm->dev, DRM_PLANE_TYPE_PRIMARY,
"base", head, format, BIT(head), &wndw); "base", head, format, BIT(head),
NV50_DISP_INTERLOCK_BASE, interlock_data, &wndw);
if (*pwndw = wndw, ret) if (*pwndw = wndw, ret)
return ret; return ret;
...@@ -266,5 +265,6 @@ int ...@@ -266,5 +265,6 @@ int
base507c_new(struct nouveau_drm *drm, int head, s32 oclass, base507c_new(struct nouveau_drm *drm, int head, s32 oclass,
struct nv50_wndw **pwndw) struct nv50_wndw **pwndw)
{ {
return base507c_new_(&base507c, base507c_format, drm, head, oclass, pwndw); return base507c_new_(&base507c, base507c_format, drm, head, oclass,
0x00000002 << (head * 8), pwndw);
} }
...@@ -63,5 +63,6 @@ int ...@@ -63,5 +63,6 @@ int
base827c_new(struct nouveau_drm *drm, int head, s32 oclass, base827c_new(struct nouveau_drm *drm, int head, s32 oclass,
struct nv50_wndw **pwndw) struct nv50_wndw **pwndw)
{ {
return base507c_new_(&base827c, base507c_format, drm, head, oclass, pwndw); return base507c_new_(&base827c, base507c_format, drm, head, oclass,
0x00000002 << (head * 8), pwndw);
} }
...@@ -21,19 +21,6 @@ ...@@ -21,19 +21,6 @@
*/ */
#include "base.h" #include "base.h"
static u32
base907c_update(struct nv50_wndw *wndw, u32 interlock)
{
u32 *push;
if ((push = evo_wait(&wndw->wndw, 2))) {
evo_mthd(push, 0x0080, 1);
evo_data(push, interlock);
evo_kick(push, &wndw->wndw);
return interlock ? 2 << (wndw->id * 4) : 0;
}
return 0;
}
static void static void
base907c_image_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) base907c_image_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
{ {
...@@ -69,12 +56,13 @@ base907c = { ...@@ -69,12 +56,13 @@ base907c = {
.image_set = base907c_image_set, .image_set = base907c_image_set,
.image_clr = base507c_image_clr, .image_clr = base507c_image_clr,
.lut = base507c_lut, .lut = base507c_lut,
.update = base907c_update, .update = base507c_update,
}; };
int int
base907c_new(struct nouveau_drm *drm, int head, s32 oclass, base907c_new(struct nouveau_drm *drm, int head, s32 oclass,
struct nv50_wndw **pwndw) struct nv50_wndw **pwndw)
{ {
return base507c_new_(&base907c, base507c_format, drm, head, oclass, pwndw); return base507c_new_(&base907c, base507c_format, drm, head, oclass,
0x00000002 << (head * 4), pwndw);
} }
...@@ -16,7 +16,7 @@ struct nv50_core_func { ...@@ -16,7 +16,7 @@ struct nv50_core_func {
void (*ntfy_init)(struct nouveau_bo *, u32 offset); void (*ntfy_init)(struct nouveau_bo *, u32 offset);
int (*ntfy_wait_done)(struct nouveau_bo *, u32 offset, int (*ntfy_wait_done)(struct nouveau_bo *, u32 offset,
struct nvif_device *); struct nvif_device *);
void (*update)(struct nv50_core *, u32 interlock, bool ntfy); void (*update)(struct nv50_core *, u32 *interlock, bool ntfy);
const struct nv50_head_func *head; const struct nv50_head_func *head;
const struct nv50_outp_func { const struct nv50_outp_func {
...@@ -31,7 +31,8 @@ int core507d_new_(const struct nv50_core_func *, struct nouveau_drm *, s32, ...@@ -31,7 +31,8 @@ int core507d_new_(const struct nv50_core_func *, struct nouveau_drm *, s32,
void core507d_init(struct nv50_core *); void core507d_init(struct nv50_core *);
void core507d_ntfy_init(struct nouveau_bo *, u32); void core507d_ntfy_init(struct nouveau_bo *, u32);
int core507d_ntfy_wait_done(struct nouveau_bo *, u32, struct nvif_device *); int core507d_ntfy_wait_done(struct nouveau_bo *, u32, struct nvif_device *);
void core507d_update(struct nv50_core *, u32, bool); void core507d_update(struct nv50_core *, u32 *, bool);
extern const struct nv50_outp_func dac507d; extern const struct nv50_outp_func dac507d;
extern const struct nv50_outp_func sor507d; extern const struct nv50_outp_func sor507d;
extern const struct nv50_outp_func pior507d; extern const struct nv50_outp_func pior507d;
......
...@@ -27,7 +27,7 @@ ...@@ -27,7 +27,7 @@
#include "nouveau_bo.h" #include "nouveau_bo.h"
void void
core507d_update(struct nv50_core *core, u32 interlock, bool ntfy) core507d_update(struct nv50_core *core, u32 *interlock, bool ntfy)
{ {
u32 *push; u32 *push;
if ((push = evo_wait(&core->chan, 5))) { if ((push = evo_wait(&core->chan, 5))) {
...@@ -36,7 +36,8 @@ core507d_update(struct nv50_core *core, u32 interlock, bool ntfy) ...@@ -36,7 +36,8 @@ core507d_update(struct nv50_core *core, u32 interlock, bool ntfy)
evo_data(push, 0x80000000 | NV50_DISP_CORE_NTFY); evo_data(push, 0x80000000 | NV50_DISP_CORE_NTFY);
} }
evo_mthd(push, 0x0080, 2); evo_mthd(push, 0x0080, 2);
evo_data(push, interlock); evo_data(push, interlock[NV50_DISP_INTERLOCK_BASE] |
interlock[NV50_DISP_INTERLOCK_OVLY]);
evo_data(push, 0x00000000); evo_data(push, 0x00000000);
evo_kick(push, &core->chan); evo_kick(push, &core->chan);
} }
......
...@@ -31,8 +31,8 @@ nv50_curs_new(struct nouveau_drm *drm, int head, struct nv50_wndw **pwndw) ...@@ -31,8 +31,8 @@ nv50_curs_new(struct nouveau_drm *drm, int head, struct nv50_wndw **pwndw)
int version; int version;
int (*new)(struct nouveau_drm *, int, s32, struct nv50_wndw **); int (*new)(struct nouveau_drm *, int, s32, struct nv50_wndw **);
} curses[] = { } curses[] = {
{ GK104_DISP_CURSOR, 0, curs507a_new }, { GK104_DISP_CURSOR, 0, curs907a_new },
{ GF110_DISP_CURSOR, 0, curs507a_new }, { GF110_DISP_CURSOR, 0, curs907a_new },
{ GT214_DISP_CURSOR, 0, curs507a_new }, { GT214_DISP_CURSOR, 0, curs507a_new },
{ G82_DISP_CURSOR, 0, curs507a_new }, { G82_DISP_CURSOR, 0, curs507a_new },
{ NV50_DISP_CURSOR, 0, curs507a_new }, { NV50_DISP_CURSOR, 0, curs507a_new },
......
...@@ -3,6 +3,12 @@ ...@@ -3,6 +3,12 @@
#include "wndw.h" #include "wndw.h"
int curs507a_new(struct nouveau_drm *, int, s32, struct nv50_wndw **); int curs507a_new(struct nouveau_drm *, int, s32, struct nv50_wndw **);
int curs507a_new_(const struct nv50_wimm_func *, struct nouveau_drm *,
int head, s32 oclass, u32 interlock_data,
struct nv50_wndw **);
extern const struct nv50_wimm_func curs507a;
int curs907a_new(struct nouveau_drm *, int, s32, struct nv50_wndw **);
int nv50_curs_new(struct nouveau_drm *, int head, struct nv50_wndw **); int nv50_curs_new(struct nouveau_drm *, int head, struct nv50_wndw **);
#endif #endif
...@@ -27,11 +27,10 @@ ...@@ -27,11 +27,10 @@
#include <drm/drm_atomic_helper.h> #include <drm/drm_atomic_helper.h>
#include <drm/drm_plane_helper.h> #include <drm/drm_plane_helper.h>
static u32 static void
curs507a_update(struct nv50_wndw *wndw, u32 interlock) curs507a_update(struct nv50_wndw *wndw, u32 *interlock)
{ {
nvif_wr32(&wndw->wimm.base.user, 0x0080, 0x00000000); nvif_wr32(&wndw->wimm.base.user, 0x0080, 0x00000000);
return 0;
} }
static void static void
...@@ -41,7 +40,7 @@ curs507a_point(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) ...@@ -41,7 +40,7 @@ curs507a_point(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
asyw->point.x); asyw->point.x);
} }
static const struct nv50_wimm_func const struct nv50_wimm_func
curs507a = { curs507a = {
.point = curs507a_point, .point = curs507a_point,
.update = curs507a_update, .update = curs507a_update,
...@@ -114,9 +113,10 @@ curs507a_wndw = { ...@@ -114,9 +113,10 @@ curs507a_wndw = {
.prepare = curs507a_prepare, .prepare = curs507a_prepare,
}; };
static int int
curs507a_new_(const struct nv50_wimm_func *func, struct nouveau_drm *drm, curs507a_new_(const struct nv50_wimm_func *func, struct nouveau_drm *drm,
int head, s32 oclass, struct nv50_wndw **pwndw) int head, s32 oclass, u32 interlock_data,
struct nv50_wndw **pwndw)
{ {
struct nv50_disp_cursor_v0 args = { struct nv50_disp_cursor_v0 args = {
.head = head, .head = head,
...@@ -126,7 +126,8 @@ curs507a_new_(const struct nv50_wimm_func *func, struct nouveau_drm *drm, ...@@ -126,7 +126,8 @@ curs507a_new_(const struct nv50_wimm_func *func, struct nouveau_drm *drm,
int ret; int ret;
ret = nv50_wndw_new_(&curs507a_wndw, drm->dev, DRM_PLANE_TYPE_CURSOR, ret = nv50_wndw_new_(&curs507a_wndw, drm->dev, DRM_PLANE_TYPE_CURSOR,
"curs", head, curs507a_format, BIT(head), &wndw); "curs", head, curs507a_format, BIT(head),
NV50_DISP_INTERLOCK_CURS, interlock_data, &wndw);
if (*pwndw = wndw, ret) if (*pwndw = wndw, ret)
return ret; return ret;
...@@ -147,5 +148,6 @@ int ...@@ -147,5 +148,6 @@ int
curs507a_new(struct nouveau_drm *drm, int head, s32 oclass, curs507a_new(struct nouveau_drm *drm, int head, s32 oclass,
struct nv50_wndw **pwndw) struct nv50_wndw **pwndw)
{ {
return curs507a_new_(&curs507a, drm, head, oclass, pwndw); return curs507a_new_(&curs507a, drm, head, oclass,
0x00000001 << (head * 8), pwndw);
} }
/*
* Copyright 2018 Red Hat Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#include "curs.h"
int
curs907a_new(struct nouveau_drm *drm, int head, s32 oclass,
struct nv50_wndw **pwndw)
{
return curs507a_new_(&curs507a, drm, head, oclass,
0x00000001 << (head * 4), pwndw);
}
...@@ -1582,14 +1582,14 @@ nv50_pior_create(struct drm_connector *connector, struct dcb_output *dcbe) ...@@ -1582,14 +1582,14 @@ nv50_pior_create(struct drm_connector *connector, struct dcb_output *dcbe)
*****************************************************************************/ *****************************************************************************/
static void static void
nv50_disp_atomic_commit_core(struct nouveau_drm *drm, u32 interlock) nv50_disp_atomic_commit_core(struct nouveau_drm *drm, u32 *interlock)
{ {
struct nv50_disp *disp = nv50_disp(drm->dev); struct nv50_disp *disp = nv50_disp(drm->dev);
struct nv50_core *core = disp->core; struct nv50_core *core = disp->core;
struct nv50_mstm *mstm; struct nv50_mstm *mstm;
struct drm_encoder *encoder; struct drm_encoder *encoder;
NV_ATOMIC(drm, "commit core %08x\n", interlock); NV_ATOMIC(drm, "commit core %08x\n", interlock[NV50_DISP_INTERLOCK_BASE]);
drm_for_each_encoder(encoder, drm->dev) { drm_for_each_encoder(encoder, drm->dev) {
if (encoder->encoder_type != DRM_MODE_ENCODER_DPMST) { if (encoder->encoder_type != DRM_MODE_ENCODER_DPMST) {
...@@ -1626,8 +1626,7 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state *state) ...@@ -1626,8 +1626,7 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state *state)
struct nv50_disp *disp = nv50_disp(dev); struct nv50_disp *disp = nv50_disp(dev);
struct nv50_atom *atom = nv50_atom(state); struct nv50_atom *atom = nv50_atom(state);
struct nv50_outp_atom *outp, *outt; struct nv50_outp_atom *outp, *outt;
u32 interlock_core = 0; u32 interlock[NV50_DISP_INTERLOCK__SIZE] = {};
u32 interlock_chan = 0;
int i; int i;
NV_ATOMIC(drm, "commit %d %d\n", atom->lock_core, atom->flush_disable); NV_ATOMIC(drm, "commit %d %d\n", atom->lock_core, atom->flush_disable);
...@@ -1650,7 +1649,7 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state *state) ...@@ -1650,7 +1649,7 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state *state)
if (asyh->clr.mask) { if (asyh->clr.mask) {
nv50_head_flush_clr(head, asyh, atom->flush_disable); nv50_head_flush_clr(head, asyh, atom->flush_disable);
interlock_core |= 1; interlock[NV50_DISP_INTERLOCK_CORE] |= 1;
} }
} }
...@@ -1664,9 +1663,7 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state *state) ...@@ -1664,9 +1663,7 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state *state)
if (!asyw->clr.mask) if (!asyw->clr.mask)
continue; continue;
interlock_chan |= nv50_wndw_flush_clr(wndw, interlock_core, nv50_wndw_flush_clr(wndw, interlock, atom->flush_disable, asyw);
atom->flush_disable,
asyw);
} }
/* Disable output path(s). */ /* Disable output path(s). */
...@@ -1682,21 +1679,19 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state *state) ...@@ -1682,21 +1679,19 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state *state)
if (outp->clr.mask) { if (outp->clr.mask) {
help->disable(encoder); help->disable(encoder);
interlock_core |= 1; interlock[NV50_DISP_INTERLOCK_CORE] |= 1;
if (outp->flush_disable) { if (outp->flush_disable) {
nv50_disp_atomic_commit_core(drm, interlock_chan); nv50_disp_atomic_commit_core(drm, interlock);
interlock_core = 0; memset(interlock, 0x00, sizeof(interlock));
interlock_chan = 0;
} }
} }
} }
/* Flush disable. */ /* Flush disable. */
if (interlock_core) { if (interlock[NV50_DISP_INTERLOCK_CORE]) {
if (atom->flush_disable) { if (atom->flush_disable) {
nv50_disp_atomic_commit_core(drm, interlock_chan); nv50_disp_atomic_commit_core(drm, interlock);
interlock_core = 0; memset(interlock, 0x00, sizeof(interlock));
interlock_chan = 0;
} }
} }
...@@ -1713,7 +1708,7 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state *state) ...@@ -1713,7 +1708,7 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state *state)
if (outp->set.mask) { if (outp->set.mask) {
help->enable(encoder); help->enable(encoder);
interlock_core = 1; interlock[NV50_DISP_INTERLOCK_CORE] = 1;
} }
list_del(&outp->head); list_del(&outp->head);
...@@ -1730,7 +1725,7 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state *state) ...@@ -1730,7 +1725,7 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state *state)
if (asyh->set.mask) { if (asyh->set.mask) {
nv50_head_flush_set(head, asyh); nv50_head_flush_set(head, asyh);
interlock_core = 1; interlock[NV50_DISP_INTERLOCK_CORE] = 1;
} }
if (new_crtc_state->active) { if (new_crtc_state->active) {
...@@ -1752,15 +1747,16 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state *state) ...@@ -1752,15 +1747,16 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state *state)
(!asyw->clr.mask || atom->flush_disable)) (!asyw->clr.mask || atom->flush_disable))
continue; continue;
interlock_chan |= nv50_wndw_flush_set(wndw, interlock_core, asyw); nv50_wndw_flush_set(wndw, interlock, asyw);
} }
/* Flush update. */ /* Flush update. */
if (interlock_core) { if (interlock[NV50_DISP_INTERLOCK_CORE]) {
if (interlock_chan || !atom->state.legacy_cursor_update) if (interlock[NV50_DISP_INTERLOCK_BASE] ||
nv50_disp_atomic_commit_core(drm, interlock_chan); !atom->state.legacy_cursor_update)
nv50_disp_atomic_commit_core(drm, interlock);
else else
disp->core->func->update(disp->core, 0, false); disp->core->func->update(disp->core, interlock, false);
} }
if (atom->lock_core) if (atom->lock_core)
......
...@@ -27,6 +27,17 @@ nv50_disp(struct drm_device *dev) ...@@ -27,6 +27,17 @@ nv50_disp(struct drm_device *dev)
return nouveau_display(dev)->priv; return nouveau_display(dev)->priv;
} }
struct nv50_disp_interlock {
enum nv50_disp_interlock_type {
NV50_DISP_INTERLOCK_CORE = 0,
NV50_DISP_INTERLOCK_CURS,
NV50_DISP_INTERLOCK_BASE,
NV50_DISP_INTERLOCK_OVLY,
NV50_DISP_INTERLOCK__SIZE
} type;
u32 data;
};
struct nv50_chan { struct nv50_chan {
struct nvif_object user; struct nvif_object user;
struct nvif_device *device; struct nvif_device *device;
......
...@@ -32,11 +32,11 @@ nv50_ovly_new(struct nouveau_drm *drm, int head, struct nv50_wndw **pwndw) ...@@ -32,11 +32,11 @@ nv50_ovly_new(struct nouveau_drm *drm, int head, struct nv50_wndw **pwndw)
int version; int version;
int (*new)(struct nouveau_drm *, int, s32, struct nv50_wndw **); int (*new)(struct nouveau_drm *, int, s32, struct nv50_wndw **);
} ovlys[] = { } ovlys[] = {
{ GK104_DISP_OVERLAY_CONTROL_DMA, 0, ovly507e_new }, { GK104_DISP_OVERLAY_CONTROL_DMA, 0, ovly907e_new },
{ GF110_DISP_OVERLAY_CONTROL_DMA, 0, ovly507e_new }, { GF110_DISP_OVERLAY_CONTROL_DMA, 0, ovly907e_new },
{ GT214_DISP_OVERLAY_CHANNEL_DMA, 0, ovly507e_new }, { GT214_DISP_OVERLAY_CHANNEL_DMA, 0, ovly827e_new },
{ GT200_DISP_OVERLAY_CHANNEL_DMA, 0, ovly507e_new }, { GT200_DISP_OVERLAY_CHANNEL_DMA, 0, ovly827e_new },
{ G82_DISP_OVERLAY_CHANNEL_DMA, 0, ovly507e_new }, { G82_DISP_OVERLAY_CHANNEL_DMA, 0, ovly827e_new },
{ NV50_DISP_OVERLAY_CHANNEL_DMA, 0, ovly507e_new }, { NV50_DISP_OVERLAY_CHANNEL_DMA, 0, ovly507e_new },
{} {}
}; };
......
...@@ -3,6 +3,14 @@ ...@@ -3,6 +3,14 @@
#include "wndw.h" #include "wndw.h"
int ovly507e_new(struct nouveau_drm *, int, s32, struct nv50_wndw **); int ovly507e_new(struct nouveau_drm *, int, s32, struct nv50_wndw **);
int ovly507e_new_(const struct nv50_wndw_func *, const u32 *format,
struct nouveau_drm *, int head, s32 oclass,
u32 interlock_data, struct nv50_wndw **);
extern const u32 ovly827e_format[];
int ovly827e_new(struct nouveau_drm *, int, s32, struct nv50_wndw **);
int ovly907e_new(struct nouveau_drm *, int, s32, struct nv50_wndw **);
int nv50_ovly_new(struct nouveau_drm *, int head, struct nv50_wndw **); int nv50_ovly_new(struct nouveau_drm *, int head, struct nv50_wndw **);
#endif #endif
...@@ -34,9 +34,9 @@ ovly507e_format[] = { ...@@ -34,9 +34,9 @@ ovly507e_format[] = {
0 0
}; };
static int int
ovly507e_new_(const struct nv50_wndw_func *func, const u32 *format, ovly507e_new_(const struct nv50_wndw_func *func, const u32 *format,
struct nouveau_drm *drm, int head, s32 oclass, struct nouveau_drm *drm, int head, s32 oclass, u32 interlock_data,
struct nv50_wndw **pwndw) struct nv50_wndw **pwndw)
{ {
struct nv50_disp_overlay_channel_dma_v0 args = { struct nv50_disp_overlay_channel_dma_v0 args = {
...@@ -47,7 +47,9 @@ ovly507e_new_(const struct nv50_wndw_func *func, const u32 *format, ...@@ -47,7 +47,9 @@ ovly507e_new_(const struct nv50_wndw_func *func, const u32 *format,
int ret; int ret;
ret = nv50_wndw_new_(func, drm->dev, DRM_PLANE_TYPE_OVERLAY, ret = nv50_wndw_new_(func, drm->dev, DRM_PLANE_TYPE_OVERLAY,
"ovly", head, format, BIT(head), &wndw); "ovly", head, format, BIT(head),
NV50_DISP_INTERLOCK_OVLY, interlock_data,
&wndw);
if (*pwndw = wndw, ret) if (*pwndw = wndw, ret)
return ret; return ret;
...@@ -66,5 +68,6 @@ int ...@@ -66,5 +68,6 @@ int
ovly507e_new(struct nouveau_drm *drm, int head, s32 oclass, ovly507e_new(struct nouveau_drm *drm, int head, s32 oclass,
struct nv50_wndw **pwndw) struct nv50_wndw **pwndw)
{ {
return ovly507e_new_(&ovly507e, ovly507e_format, drm, head, oclass, pwndw); return ovly507e_new_(&ovly507e, ovly507e_format, drm, head, oclass,
0x00000004 << (head * 8), pwndw);
} }
/*
* Copyright 2018 Red Hat Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#include "ovly.h"
#include <nouveau_bo.h>
#include <nvif/cl507e.h>
static const struct nv50_wndw_func
ovly827e = {
};
const u32
ovly827e_format[] = {
0
};
int
ovly827e_new(struct nouveau_drm *drm, int head, s32 oclass,
struct nv50_wndw **pwndw)
{
return ovly507e_new_(&ovly827e, ovly827e_format, drm, head, oclass,
0x00000004 << (head * 8), pwndw);
}
/*
* Copyright 2018 Red Hat Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#include "ovly.h"
static const struct nv50_wndw_func
ovly907e = {
};
int
ovly907e_new(struct nouveau_drm *drm, int head, s32 oclass,
struct nv50_wndw **pwndw)
{
return ovly507e_new_(&ovly907e, ovly827e_format, drm, head, oclass,
0x00000004 << (head * 4), pwndw);
}
...@@ -107,8 +107,8 @@ nv50_wndw_wait_armed(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) ...@@ -107,8 +107,8 @@ nv50_wndw_wait_armed(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
return 0; return 0;
} }
u32 void
nv50_wndw_flush_clr(struct nv50_wndw *wndw, u32 interlock, bool flush, nv50_wndw_flush_clr(struct nv50_wndw *wndw, u32 *interlock, bool flush,
struct nv50_wndw_atom *asyw) struct nv50_wndw_atom *asyw)
{ {
union nv50_wndw_atom_mask clr = { union nv50_wndw_atom_mask clr = {
...@@ -118,11 +118,13 @@ nv50_wndw_flush_clr(struct nv50_wndw *wndw, u32 interlock, bool flush, ...@@ -118,11 +118,13 @@ nv50_wndw_flush_clr(struct nv50_wndw *wndw, u32 interlock, bool flush,
if (clr.ntfy ) wndw->func-> ntfy_clr(wndw); if (clr.ntfy ) wndw->func-> ntfy_clr(wndw);
if (clr.image) wndw->func->image_clr(wndw); if (clr.image) wndw->func->image_clr(wndw);
return flush ? wndw->func->update(wndw, interlock) : 0; interlock[wndw->interlock.type] |= wndw->interlock.data;
if (flush)
wndw->func->update(wndw, interlock);
} }
u32 void
nv50_wndw_flush_set(struct nv50_wndw *wndw, u32 interlock, nv50_wndw_flush_set(struct nv50_wndw *wndw, u32 *interlock,
struct nv50_wndw_atom *asyw) struct nv50_wndw_atom *asyw)
{ {
if (interlock) { if (interlock) {
...@@ -139,7 +141,9 @@ nv50_wndw_flush_set(struct nv50_wndw *wndw, u32 interlock, ...@@ -139,7 +141,9 @@ nv50_wndw_flush_set(struct nv50_wndw *wndw, u32 interlock,
wndw->immd->update(wndw, interlock); wndw->immd->update(wndw, interlock);
} }
return wndw->func->update ? wndw->func->update(wndw, interlock) : 0; interlock[wndw->interlock.type] |= wndw->interlock.data;
if (wndw->func->update)
wndw->func->update(wndw, interlock);
} }
void void
...@@ -445,7 +449,9 @@ nv50_wndw_init(struct nv50_wndw *wndw) ...@@ -445,7 +449,9 @@ nv50_wndw_init(struct nv50_wndw *wndw)
int int
nv50_wndw_new_(const struct nv50_wndw_func *func, struct drm_device *dev, nv50_wndw_new_(const struct nv50_wndw_func *func, struct drm_device *dev,
enum drm_plane_type type, const char *name, int index, enum drm_plane_type type, const char *name, int index,
const u32 *format, u32 heads, struct nv50_wndw **pwndw) const u32 *format, u32 heads,
enum nv50_disp_interlock_type interlock_type, u32 interlock_data,
struct nv50_wndw **pwndw)
{ {
struct nv50_wndw *wndw; struct nv50_wndw *wndw;
int nformat; int nformat;
...@@ -455,6 +461,9 @@ nv50_wndw_new_(const struct nv50_wndw_func *func, struct drm_device *dev, ...@@ -455,6 +461,9 @@ nv50_wndw_new_(const struct nv50_wndw_func *func, struct drm_device *dev,
return -ENOMEM; return -ENOMEM;
wndw->func = func; wndw->func = func;
wndw->id = index; wndw->id = index;
wndw->interlock.type = interlock_type;
wndw->interlock.data = interlock_data;
wndw->ctxdma.parent = &wndw->wndw.base.user;
wndw->ctxdma.parent = &wndw->wndw.base.user; wndw->ctxdma.parent = &wndw->wndw.base.user;
INIT_LIST_HEAD(&wndw->ctxdma.list); INIT_LIST_HEAD(&wndw->ctxdma.list);
......
...@@ -15,6 +15,7 @@ struct nv50_wndw { ...@@ -15,6 +15,7 @@ struct nv50_wndw {
const struct nv50_wndw_func *func; const struct nv50_wndw_func *func;
const struct nv50_wimm_func *immd; const struct nv50_wimm_func *immd;
int id; int id;
struct nv50_disp_interlock interlock;
struct { struct {
struct nvif_object *parent; struct nvif_object *parent;
...@@ -34,13 +35,14 @@ struct nv50_wndw { ...@@ -34,13 +35,14 @@ struct nv50_wndw {
int nv50_wndw_new_(const struct nv50_wndw_func *, struct drm_device *, int nv50_wndw_new_(const struct nv50_wndw_func *, struct drm_device *,
enum drm_plane_type, const char *name, int index, enum drm_plane_type, const char *name, int index,
const u32 *format, u32 heads, struct nv50_wndw **); const u32 *format, enum nv50_disp_interlock_type,
u32 interlock_data, u32 heads, struct nv50_wndw **);
void nv50_wndw_init(struct nv50_wndw *); void nv50_wndw_init(struct nv50_wndw *);
void nv50_wndw_fini(struct nv50_wndw *); void nv50_wndw_fini(struct nv50_wndw *);
u32 nv50_wndw_flush_set(struct nv50_wndw *, u32 interlock, void nv50_wndw_flush_set(struct nv50_wndw *, u32 *interlock,
struct nv50_wndw_atom *); struct nv50_wndw_atom *);
u32 nv50_wndw_flush_clr(struct nv50_wndw *, u32 interlock, bool flush, void nv50_wndw_flush_clr(struct nv50_wndw *, u32 *interlock, bool flush,
struct nv50_wndw_atom *); struct nv50_wndw_atom *);
void nv50_wndw_ntfy_enable(struct nv50_wndw *, struct nv50_wndw_atom *); void nv50_wndw_ntfy_enable(struct nv50_wndw *, struct nv50_wndw_atom *);
int nv50_wndw_wait_armed(struct nv50_wndw *, struct nv50_wndw_atom *); int nv50_wndw_wait_armed(struct nv50_wndw *, struct nv50_wndw_atom *);
...@@ -63,7 +65,7 @@ struct nv50_wndw_func { ...@@ -63,7 +65,7 @@ struct nv50_wndw_func {
void (*image_clr)(struct nv50_wndw *); void (*image_clr)(struct nv50_wndw *);
void (*lut)(struct nv50_wndw *, struct nv50_wndw_atom *); void (*lut)(struct nv50_wndw *, struct nv50_wndw_atom *);
u32 (*update)(struct nv50_wndw *, u32 interlock); void (*update)(struct nv50_wndw *, u32 *interlock);
}; };
extern const struct drm_plane_funcs nv50_wndw; extern const struct drm_plane_funcs nv50_wndw;
...@@ -71,6 +73,6 @@ extern const struct drm_plane_funcs nv50_wndw; ...@@ -71,6 +73,6 @@ extern const struct drm_plane_funcs nv50_wndw;
struct nv50_wimm_func { struct nv50_wimm_func {
void (*point)(struct nv50_wndw *, struct nv50_wndw_atom *); void (*point)(struct nv50_wndw *, struct nv50_wndw_atom *);
u32 (*update)(struct nv50_wndw *, u32 interlock); void (*update)(struct nv50_wndw *, u32 *interlock);
}; };
#endif #endif
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