summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/nouveau
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2018-05-08 13:39:47 +0300
committerBen Skeggs <bskeggs@redhat.com>2018-05-18 08:01:29 +0300
commit53e0a3e70de69dc9f498d26c6b5495b2771ee374 (patch)
treedace6fc2c8adfe40459ddcaa6731a69842a1b665 /drivers/gpu/drm/nouveau
parent34508f9d260cbd7b91f988c858f50ad956750ee3 (diff)
downloadlinux-53e0a3e70de69dc9f498d26c6b5495b2771ee374.tar.xz
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: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/nouveau')
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/Kbuild3
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/base.h4
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/base507c.c16
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/base827c.c3
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/base907c.c18
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/core.h5
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/core507d.c5
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/curs.c4
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/curs.h6
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/curs507a.c18
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/curs907a.c30
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/disp.c42
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/disp.h11
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/ovly.c10
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/ovly.h8
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/ovly507e.c11
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/ovly827e.c43
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/ovly907e.c34
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/wndw.c23
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/wndw.h16
20 files changed, 224 insertions, 86 deletions
diff --git a/drivers/gpu/drm/nouveau/dispnv50/Kbuild b/drivers/gpu/drm/nouveau/dispnv50/Kbuild
index 674221dea7a1..3e53484b4589 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/Kbuild
+++ b/drivers/gpu/drm/nouveau/dispnv50/Kbuild
@@ -29,9 +29,12 @@ nouveau-y += dispnv50/base907c.o
nouveau-y += dispnv50/curs.o
nouveau-y += dispnv50/curs507a.o
+nouveau-y += dispnv50/curs907a.o
nouveau-y += dispnv50/oimm.o
nouveau-y += dispnv50/oimm507b.o
nouveau-y += dispnv50/ovly.o
nouveau-y += dispnv50/ovly507e.o
+nouveau-y += dispnv50/ovly827e.o
+nouveau-y += dispnv50/ovly907e.o
diff --git a/drivers/gpu/drm/nouveau/dispnv50/base.h b/drivers/gpu/drm/nouveau/dispnv50/base.h
index edf96a8d645f..71fc10369b37 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/base.h
+++ b/drivers/gpu/drm/nouveau/dispnv50/base.h
@@ -5,7 +5,7 @@
int base507c_new(struct nouveau_drm *, int, s32, struct nv50_wndw **);
int base507c_new_(const struct nv50_wndw_func *, const u32 *format,
struct nouveau_drm *, int head, s32 oclass,
- struct nv50_wndw **);
+ u32 interlock_data, struct nv50_wndw **);
extern const u32 base507c_format[];
int base507c_acquire(struct nv50_wndw *, struct nv50_wndw_atom *,
struct nv50_head_atom *);
@@ -19,7 +19,7 @@ void base507c_ntfy_clr(struct nv50_wndw *);
int base507c_ntfy_wait_begun(struct nouveau_bo *, u32, struct nvif_device *);
void base507c_image_clr(struct nv50_wndw *);
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 **);
diff --git a/drivers/gpu/drm/nouveau/dispnv50/base507c.c b/drivers/gpu/drm/nouveau/dispnv50/base507c.c
index 1c65ddc4747e..819403f4b958 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/base507c.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/base507c.c
@@ -28,17 +28,15 @@
#include <drm/drm_plane_helper.h>
#include "nouveau_bo.h"
-u32
-base507c_update(struct nv50_wndw *wndw, u32 interlock)
+void
+base507c_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_data(push, interlock[NV50_DISP_INTERLOCK_CORE]);
evo_kick(push, &wndw->wndw);
- return interlock ? 2 << (wndw->id * 8) : 0;
}
- return 0;
}
void
@@ -224,7 +222,7 @@ base507c = {
int
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_disp_base_channel_dma_v0 args = {
@@ -235,7 +233,8 @@ base507c_new_(const struct nv50_wndw_func *func, const u32 *format,
int ret;
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)
return ret;
@@ -266,5 +265,6 @@ int
base507c_new(struct nouveau_drm *drm, int head, s32 oclass,
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);
}
diff --git a/drivers/gpu/drm/nouveau/dispnv50/base827c.c b/drivers/gpu/drm/nouveau/dispnv50/base827c.c
index 9dc968c83c66..240a6409329d 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/base827c.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/base827c.c
@@ -63,5 +63,6 @@ int
base827c_new(struct nouveau_drm *drm, int head, s32 oclass,
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);
}
diff --git a/drivers/gpu/drm/nouveau/dispnv50/base907c.c b/drivers/gpu/drm/nouveau/dispnv50/base907c.c
index 5321c55951b9..6c32a4e5cb7d 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/base907c.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/base907c.c
@@ -21,19 +21,6 @@
*/
#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
base907c_image_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
{
@@ -69,12 +56,13 @@ base907c = {
.image_set = base907c_image_set,
.image_clr = base507c_image_clr,
.lut = base507c_lut,
- .update = base907c_update,
+ .update = base507c_update,
};
int
base907c_new(struct nouveau_drm *drm, int head, s32 oclass,
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);
}
diff --git a/drivers/gpu/drm/nouveau/dispnv50/core.h b/drivers/gpu/drm/nouveau/dispnv50/core.h
index 5fd7ddd31e5e..c490d7d497b2 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/core.h
+++ b/drivers/gpu/drm/nouveau/dispnv50/core.h
@@ -16,7 +16,7 @@ struct nv50_core_func {
void (*ntfy_init)(struct nouveau_bo *, u32 offset);
int (*ntfy_wait_done)(struct nouveau_bo *, u32 offset,
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_outp_func {
@@ -31,7 +31,8 @@ int core507d_new_(const struct nv50_core_func *, struct nouveau_drm *, s32,
void core507d_init(struct nv50_core *);
void core507d_ntfy_init(struct nouveau_bo *, u32);
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 sor507d;
extern const struct nv50_outp_func pior507d;
diff --git a/drivers/gpu/drm/nouveau/dispnv50/core507d.c b/drivers/gpu/drm/nouveau/dispnv50/core507d.c
index 96d7d8fde669..e7fcfa6e6467 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/core507d.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/core507d.c
@@ -27,7 +27,7 @@
#include "nouveau_bo.h"
void
-core507d_update(struct nv50_core *core, u32 interlock, bool ntfy)
+core507d_update(struct nv50_core *core, u32 *interlock, bool ntfy)
{
u32 *push;
if ((push = evo_wait(&core->chan, 5))) {
@@ -36,7 +36,8 @@ core507d_update(struct nv50_core *core, u32 interlock, bool ntfy)
evo_data(push, 0x80000000 | NV50_DISP_CORE_NTFY);
}
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_kick(push, &core->chan);
}
diff --git a/drivers/gpu/drm/nouveau/dispnv50/curs.c b/drivers/gpu/drm/nouveau/dispnv50/curs.c
index 6d60e978db69..fb842ed2592f 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/curs.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/curs.c
@@ -31,8 +31,8 @@ nv50_curs_new(struct nouveau_drm *drm, int head, struct nv50_wndw **pwndw)
int version;
int (*new)(struct nouveau_drm *, int, s32, struct nv50_wndw **);
} curses[] = {
- { GK104_DISP_CURSOR, 0, curs507a_new },
- { GF110_DISP_CURSOR, 0, curs507a_new },
+ { GK104_DISP_CURSOR, 0, curs907a_new },
+ { GF110_DISP_CURSOR, 0, curs907a_new },
{ GT214_DISP_CURSOR, 0, curs507a_new },
{ G82_DISP_CURSOR, 0, curs507a_new },
{ NV50_DISP_CURSOR, 0, curs507a_new },
diff --git a/drivers/gpu/drm/nouveau/dispnv50/curs.h b/drivers/gpu/drm/nouveau/dispnv50/curs.h
index b85ca9fa419c..2285247dc2a3 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/curs.h
+++ b/drivers/gpu/drm/nouveau/dispnv50/curs.h
@@ -3,6 +3,12 @@
#include "wndw.h"
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 **);
#endif
diff --git a/drivers/gpu/drm/nouveau/dispnv50/curs507a.c b/drivers/gpu/drm/nouveau/dispnv50/curs507a.c
index 589c75c22b3a..ba05bcb13ae7 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/curs507a.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/curs507a.c
@@ -27,11 +27,10 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_plane_helper.h>
-static u32
-curs507a_update(struct nv50_wndw *wndw, u32 interlock)
+static void
+curs507a_update(struct nv50_wndw *wndw, u32 *interlock)
{
nvif_wr32(&wndw->wimm.base.user, 0x0080, 0x00000000);
- return 0;
}
static void
@@ -41,7 +40,7 @@ curs507a_point(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
asyw->point.x);
}
-static const struct nv50_wimm_func
+const struct nv50_wimm_func
curs507a = {
.point = curs507a_point,
.update = curs507a_update,
@@ -114,9 +113,10 @@ curs507a_wndw = {
.prepare = curs507a_prepare,
};
-static int
+int
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 = {
.head = head,
@@ -126,7 +126,8 @@ curs507a_new_(const struct nv50_wimm_func *func, struct nouveau_drm *drm,
int ret;
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)
return ret;
@@ -147,5 +148,6 @@ int
curs507a_new(struct nouveau_drm *drm, int head, s32 oclass,
struct nv50_wndw **pwndw)
{
- return curs507a_new_(&curs507a, drm, head, oclass, pwndw);
+ return curs507a_new_(&curs507a, drm, head, oclass,
+ 0x00000001 << (head * 8), pwndw);
}
diff --git a/drivers/gpu/drm/nouveau/dispnv50/curs907a.c b/drivers/gpu/drm/nouveau/dispnv50/curs907a.c
new file mode 100644
index 000000000000..d742362de03e
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/dispnv50/curs907a.c
@@ -0,0 +1,30 @@
+/*
+ * 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);
+}
diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c
index eaa63b43282b..e80d11c9a456 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
@@ -1582,14 +1582,14 @@ nv50_pior_create(struct drm_connector *connector, struct dcb_output *dcbe)
*****************************************************************************/
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_core *core = disp->core;
struct nv50_mstm *mstm;
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) {
if (encoder->encoder_type != DRM_MODE_ENCODER_DPMST) {
@@ -1626,8 +1626,7 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state *state)
struct nv50_disp *disp = nv50_disp(dev);
struct nv50_atom *atom = nv50_atom(state);
struct nv50_outp_atom *outp, *outt;
- u32 interlock_core = 0;
- u32 interlock_chan = 0;
+ u32 interlock[NV50_DISP_INTERLOCK__SIZE] = {};
int i;
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)
if (asyh->clr.mask) {
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)
if (!asyw->clr.mask)
continue;
- interlock_chan |= nv50_wndw_flush_clr(wndw, interlock_core,
- atom->flush_disable,
- asyw);
+ nv50_wndw_flush_clr(wndw, interlock, atom->flush_disable, asyw);
}
/* Disable output path(s). */
@@ -1682,21 +1679,19 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state *state)
if (outp->clr.mask) {
help->disable(encoder);
- interlock_core |= 1;
+ interlock[NV50_DISP_INTERLOCK_CORE] |= 1;
if (outp->flush_disable) {
- nv50_disp_atomic_commit_core(drm, interlock_chan);
- interlock_core = 0;
- interlock_chan = 0;
+ nv50_disp_atomic_commit_core(drm, interlock);
+ memset(interlock, 0x00, sizeof(interlock));
}
}
}
/* Flush disable. */
- if (interlock_core) {
+ if (interlock[NV50_DISP_INTERLOCK_CORE]) {
if (atom->flush_disable) {
- nv50_disp_atomic_commit_core(drm, interlock_chan);
- interlock_core = 0;
- interlock_chan = 0;
+ nv50_disp_atomic_commit_core(drm, interlock);
+ memset(interlock, 0x00, sizeof(interlock));
}
}
@@ -1713,7 +1708,7 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state *state)
if (outp->set.mask) {
help->enable(encoder);
- interlock_core = 1;
+ interlock[NV50_DISP_INTERLOCK_CORE] = 1;
}
list_del(&outp->head);
@@ -1730,7 +1725,7 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state *state)
if (asyh->set.mask) {
nv50_head_flush_set(head, asyh);
- interlock_core = 1;
+ interlock[NV50_DISP_INTERLOCK_CORE] = 1;
}
if (new_crtc_state->active) {
@@ -1752,15 +1747,16 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state *state)
(!asyw->clr.mask || atom->flush_disable))
continue;
- interlock_chan |= nv50_wndw_flush_set(wndw, interlock_core, asyw);
+ nv50_wndw_flush_set(wndw, interlock, asyw);
}
/* Flush update. */
- if (interlock_core) {
- if (interlock_chan || !atom->state.legacy_cursor_update)
- nv50_disp_atomic_commit_core(drm, interlock_chan);
+ if (interlock[NV50_DISP_INTERLOCK_CORE]) {
+ if (interlock[NV50_DISP_INTERLOCK_BASE] ||
+ !atom->state.legacy_cursor_update)
+ nv50_disp_atomic_commit_core(drm, interlock);
else
- disp->core->func->update(disp->core, 0, false);
+ disp->core->func->update(disp->core, interlock, false);
}
if (atom->lock_core)
diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.h b/drivers/gpu/drm/nouveau/dispnv50/disp.h
index 7cbd66849743..f3a963b0ab77 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/disp.h
+++ b/drivers/gpu/drm/nouveau/dispnv50/disp.h
@@ -27,6 +27,17 @@ nv50_disp(struct drm_device *dev)
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 nvif_object user;
struct nvif_device *device;
diff --git a/drivers/gpu/drm/nouveau/dispnv50/ovly.c b/drivers/gpu/drm/nouveau/dispnv50/ovly.c
index ac2d3b64f186..be0f16fdcd5b 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/ovly.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/ovly.c
@@ -32,11 +32,11 @@ nv50_ovly_new(struct nouveau_drm *drm, int head, struct nv50_wndw **pwndw)
int version;
int (*new)(struct nouveau_drm *, int, s32, struct nv50_wndw **);
} ovlys[] = {
- { GK104_DISP_OVERLAY_CONTROL_DMA, 0, ovly507e_new },
- { GF110_DISP_OVERLAY_CONTROL_DMA, 0, ovly507e_new },
- { GT214_DISP_OVERLAY_CHANNEL_DMA, 0, ovly507e_new },
- { GT200_DISP_OVERLAY_CHANNEL_DMA, 0, ovly507e_new },
- { G82_DISP_OVERLAY_CHANNEL_DMA, 0, ovly507e_new },
+ { GK104_DISP_OVERLAY_CONTROL_DMA, 0, ovly907e_new },
+ { GF110_DISP_OVERLAY_CONTROL_DMA, 0, ovly907e_new },
+ { GT214_DISP_OVERLAY_CHANNEL_DMA, 0, ovly827e_new },
+ { GT200_DISP_OVERLAY_CHANNEL_DMA, 0, ovly827e_new },
+ { G82_DISP_OVERLAY_CHANNEL_DMA, 0, ovly827e_new },
{ NV50_DISP_OVERLAY_CHANNEL_DMA, 0, ovly507e_new },
{}
};
diff --git a/drivers/gpu/drm/nouveau/dispnv50/ovly.h b/drivers/gpu/drm/nouveau/dispnv50/ovly.h
index 90af1f2f0aa0..d149ef6f957e 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/ovly.h
+++ b/drivers/gpu/drm/nouveau/dispnv50/ovly.h
@@ -3,6 +3,14 @@
#include "wndw.h"
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 **);
#endif
diff --git a/drivers/gpu/drm/nouveau/dispnv50/ovly507e.c b/drivers/gpu/drm/nouveau/dispnv50/ovly507e.c
index 1b85262bf23b..732eea39e4de 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/ovly507e.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/ovly507e.c
@@ -34,9 +34,9 @@ ovly507e_format[] = {
0
};
-static int
+int
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_disp_overlay_channel_dma_v0 args = {
@@ -47,7 +47,9 @@ ovly507e_new_(const struct nv50_wndw_func *func, const u32 *format,
int ret;
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)
return ret;
@@ -66,5 +68,6 @@ int
ovly507e_new(struct nouveau_drm *drm, int head, s32 oclass,
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);
}
diff --git a/drivers/gpu/drm/nouveau/dispnv50/ovly827e.c b/drivers/gpu/drm/nouveau/dispnv50/ovly827e.c
new file mode 100644
index 000000000000..a8115f13406e
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/dispnv50/ovly827e.c
@@ -0,0 +1,43 @@
+/*
+ * 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);
+}
diff --git a/drivers/gpu/drm/nouveau/dispnv50/ovly907e.c b/drivers/gpu/drm/nouveau/dispnv50/ovly907e.c
new file mode 100644
index 000000000000..f50da6461d41
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/dispnv50/ovly907e.c
@@ -0,0 +1,34 @@
+/*
+ * 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);
+}
diff --git a/drivers/gpu/drm/nouveau/dispnv50/wndw.c b/drivers/gpu/drm/nouveau/dispnv50/wndw.c
index 4b64f64b7891..8f62c2a811ff 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/wndw.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/wndw.c
@@ -107,8 +107,8 @@ nv50_wndw_wait_armed(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
return 0;
}
-u32
-nv50_wndw_flush_clr(struct nv50_wndw *wndw, u32 interlock, bool flush,
+void
+nv50_wndw_flush_clr(struct nv50_wndw *wndw, u32 *interlock, bool flush,
struct nv50_wndw_atom *asyw)
{
union nv50_wndw_atom_mask clr = {
@@ -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.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
-nv50_wndw_flush_set(struct nv50_wndw *wndw, u32 interlock,
+void
+nv50_wndw_flush_set(struct nv50_wndw *wndw, u32 *interlock,
struct nv50_wndw_atom *asyw)
{
if (interlock) {
@@ -139,7 +141,9 @@ nv50_wndw_flush_set(struct nv50_wndw *wndw, u32 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
@@ -445,7 +449,9 @@ nv50_wndw_init(struct nv50_wndw *wndw)
int
nv50_wndw_new_(const struct nv50_wndw_func *func, struct drm_device *dev,
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;
int nformat;
@@ -455,6 +461,9 @@ nv50_wndw_new_(const struct nv50_wndw_func *func, struct drm_device *dev,
return -ENOMEM;
wndw->func = func;
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;
INIT_LIST_HEAD(&wndw->ctxdma.list);
diff --git a/drivers/gpu/drm/nouveau/dispnv50/wndw.h b/drivers/gpu/drm/nouveau/dispnv50/wndw.h
index 8672c280a6a4..c26796c612f6 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/wndw.h
+++ b/drivers/gpu/drm/nouveau/dispnv50/wndw.h
@@ -15,6 +15,7 @@ struct nv50_wndw {
const struct nv50_wndw_func *func;
const struct nv50_wimm_func *immd;
int id;
+ struct nv50_disp_interlock interlock;
struct {
struct nvif_object *parent;
@@ -34,13 +35,14 @@ struct nv50_wndw {
int nv50_wndw_new_(const struct nv50_wndw_func *, struct drm_device *,
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_fini(struct nv50_wndw *);
-u32 nv50_wndw_flush_set(struct nv50_wndw *, u32 interlock,
- struct nv50_wndw_atom *);
-u32 nv50_wndw_flush_clr(struct nv50_wndw *, u32 interlock, bool flush,
- struct nv50_wndw_atom *);
+void nv50_wndw_flush_set(struct nv50_wndw *, u32 *interlock,
+ struct nv50_wndw_atom *);
+void nv50_wndw_flush_clr(struct nv50_wndw *, u32 *interlock, bool flush,
+ 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 *);
@@ -63,7 +65,7 @@ struct nv50_wndw_func {
void (*image_clr)(struct nv50_wndw *);
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;
@@ -71,6 +73,6 @@ extern const struct drm_plane_funcs nv50_wndw;
struct nv50_wimm_func {
void (*point)(struct nv50_wndw *, struct nv50_wndw_atom *);
- u32 (*update)(struct nv50_wndw *, u32 interlock);
+ void (*update)(struct nv50_wndw *, u32 *interlock);
};
#endif