Merge branch 'linux-4.21' of git://github.com/skeggsb/linux into drm-next
authorDave Airlie <airlied@redhat.com>
Thu, 13 Dec 2018 00:21:31 +0000 (10:21 +1000)
committerDave Airlie <airlied@redhat.com>
Thu, 13 Dec 2018 00:25:25 +0000 (10:25 +1000)
Mostly just initial support for Turing TU104/TU106 chipsets.  Support
for TU102 is missing as I don't yet have HW, but it should be trivial
to add in later in the merge window (in theory).

It's a bit of a rough first pass that'll get improved in future
releases as a finish figuring out some of the other HW changes, but
it's good enough as it stands for modesetting and suspend/resume etc.

Acceleration bring-up is incomplete due to NVIDIA not yet having
provided FW images for me to use, though command submission and copy
engines are functional already.

Signed-off-by: Dave Airlie <airlied@redhat.com>
From: Ben Skeggs <skeggsb@gmail.com>
Link: https://patchwork.freedesktop.org/patch/msgid/CACAvsv7KmfcQqZcx+wh_1UKjTovp4PH_5UVMfeyxUu-M9WLZfw@mail.gmail.com
119 files changed:
drivers/gpu/drm/nouveau/dispnv04/disp.c
drivers/gpu/drm/nouveau/dispnv50/Kbuild
drivers/gpu/drm/nouveau/dispnv50/atom.h
drivers/gpu/drm/nouveau/dispnv50/base907c.c
drivers/gpu/drm/nouveau/dispnv50/core.c
drivers/gpu/drm/nouveau/dispnv50/core.h
drivers/gpu/drm/nouveau/dispnv50/corec37d.c
drivers/gpu/drm/nouveau/dispnv50/corec57d.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/dispnv50/curs.c
drivers/gpu/drm/nouveau/dispnv50/disp.c
drivers/gpu/drm/nouveau/dispnv50/disp.h
drivers/gpu/drm/nouveau/dispnv50/head.c
drivers/gpu/drm/nouveau/dispnv50/head.h
drivers/gpu/drm/nouveau/dispnv50/head507d.c
drivers/gpu/drm/nouveau/dispnv50/head907d.c
drivers/gpu/drm/nouveau/dispnv50/headc37d.c
drivers/gpu/drm/nouveau/dispnv50/headc57d.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/dispnv50/lut.c
drivers/gpu/drm/nouveau/dispnv50/lut.h
drivers/gpu/drm/nouveau/dispnv50/wimm.c
drivers/gpu/drm/nouveau/dispnv50/wndw.c
drivers/gpu/drm/nouveau/dispnv50/wndw.h
drivers/gpu/drm/nouveau/dispnv50/wndwc37e.c
drivers/gpu/drm/nouveau/dispnv50/wndwc57e.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/include/nvif/cl0080.h
drivers/gpu/drm/nouveau/include/nvif/cla06f.h
drivers/gpu/drm/nouveau/include/nvif/class.h
drivers/gpu/drm/nouveau/include/nvif/clc36f.h [new file with mode: 0644]
drivers/gpu/drm/nouveau/include/nvkm/core/device.h
drivers/gpu/drm/nouveau/include/nvkm/core/memory.h
drivers/gpu/drm/nouveau/include/nvkm/engine/ce.h
drivers/gpu/drm/nouveau/include/nvkm/engine/disp.h
drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h
drivers/gpu/drm/nouveau/include/nvkm/subdev/bar.h
drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/M0203.h
drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/conn.h
drivers/gpu/drm/nouveau/include/nvkm/subdev/devinit.h
drivers/gpu/drm/nouveau/include/nvkm/subdev/fault.h
drivers/gpu/drm/nouveau/include/nvkm/subdev/fb.h
drivers/gpu/drm/nouveau/include/nvkm/subdev/mc.h
drivers/gpu/drm/nouveau/include/nvkm/subdev/mmu.h
drivers/gpu/drm/nouveau/include/nvkm/subdev/timer.h
drivers/gpu/drm/nouveau/nouveau_abi16.c
drivers/gpu/drm/nouveau/nouveau_bo.c
drivers/gpu/drm/nouveau/nouveau_chan.c
drivers/gpu/drm/nouveau/nouveau_chan.h
drivers/gpu/drm/nouveau/nouveau_connector.c
drivers/gpu/drm/nouveau/nouveau_connector.h
drivers/gpu/drm/nouveau/nouveau_debugfs.c
drivers/gpu/drm/nouveau/nouveau_dma.c
drivers/gpu/drm/nouveau/nouveau_drm.c
drivers/gpu/drm/nouveau/nouveau_vmm.h
drivers/gpu/drm/nouveau/nvif/disp.c
drivers/gpu/drm/nouveau/nvkm/core/subdev.c
drivers/gpu/drm/nouveau/nvkm/engine/ce/Kbuild
drivers/gpu/drm/nouveau/nvkm/engine/ce/tu104.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/nvkm/engine/device/base.c
drivers/gpu/drm/nouveau/nvkm/engine/device/user.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild
drivers/gpu/drm/nouveau/nvkm/engine/disp/gv100.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h
drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.h
drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.h
drivers/gpu/drm/nouveau/nvkm/engine/disp/roottu104.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgv100.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/sortu104.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/nvkm/engine/disp/tu104.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/nvkm/engine/disp/wndwgv100.c
drivers/gpu/drm/nouveau/nvkm/engine/fifo/Kbuild
drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h
drivers/gpu/drm/nouveau/nvkm/engine/fifo/changk104.h
drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c
drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c
drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h
drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c
drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c
drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c
drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c
drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c
drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm20b.c
drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c
drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp10b.c
drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c
drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogv100.c
drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifotu104.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c
drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu104.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/nvkm/engine/fifo/user.h
drivers/gpu/drm/nouveau/nvkm/engine/fifo/usertu104.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/nvkm/falcon/base.c
drivers/gpu/drm/nouveau/nvkm/subdev/bar/Kbuild
drivers/gpu/drm/nouveau/nvkm/subdev/bar/base.c
drivers/gpu/drm/nouveau/nvkm/subdev/bar/tu104.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/nvkm/subdev/devinit/Kbuild
drivers/gpu/drm/nouveau/nvkm/subdev/devinit/gm200.c
drivers/gpu/drm/nouveau/nvkm/subdev/devinit/nv50.h
drivers/gpu/drm/nouveau/nvkm/subdev/devinit/tu104.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/nvkm/subdev/fault/Kbuild
drivers/gpu/drm/nouveau/nvkm/subdev/fault/base.c
drivers/gpu/drm/nouveau/nvkm/subdev/fault/gp100.c
drivers/gpu/drm/nouveau/nvkm/subdev/fault/gv100.c
drivers/gpu/drm/nouveau/nvkm/subdev/fault/priv.h
drivers/gpu/drm/nouveau/nvkm/subdev/fault/tu104.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/nvkm/subdev/fb/base.c
drivers/gpu/drm/nouveau/nvkm/subdev/fb/ram.c
drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv50.c
drivers/gpu/drm/nouveau/nvkm/subdev/mc/Kbuild
drivers/gpu/drm/nouveau/nvkm/subdev/mc/base.c
drivers/gpu/drm/nouveau/nvkm/subdev/mc/priv.h
drivers/gpu/drm/nouveau/nvkm/subdev/mc/tu104.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/nvkm/subdev/mmu/Kbuild
drivers/gpu/drm/nouveau/nvkm/subdev/mmu/tu104.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/nvkm/subdev/mmu/uvmm.c
drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c
drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.h
drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmtu104.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gp102.c
drivers/gpu/drm/nouveau/nvkm/subdev/timer/base.c
drivers/gpu/drm/nouveau/nvkm/subdev/top/gk104.c

index 70dce54..1727d39 100644 (file)
@@ -67,7 +67,7 @@ nv04_display_create(struct drm_device *dev)
        for (i = 0; i < dcb->entries; i++) {
                struct dcb_output *dcbent = &dcb->entry[i];
 
-               connector = nouveau_connector_create(dev, dcbent->connector);
+               connector = nouveau_connector_create(dev, dcbent);
                if (IS_ERR(connector))
                        continue;
 
index 849b0f4..3d074aa 100644 (file)
@@ -7,6 +7,7 @@ nouveau-y += dispnv50/core827d.o
 nouveau-y += dispnv50/core907d.o
 nouveau-y += dispnv50/core917d.o
 nouveau-y += dispnv50/corec37d.o
+nouveau-y += dispnv50/corec57d.o
 
 nouveau-y += dispnv50/dac507d.o
 nouveau-y += dispnv50/dac907d.o
@@ -23,12 +24,14 @@ nouveau-y += dispnv50/head827d.o
 nouveau-y += dispnv50/head907d.o
 nouveau-y += dispnv50/head917d.o
 nouveau-y += dispnv50/headc37d.o
+nouveau-y += dispnv50/headc57d.o
 
 nouveau-y += dispnv50/wimm.o
 nouveau-y += dispnv50/wimmc37b.o
 
 nouveau-y += dispnv50/wndw.o
 nouveau-y += dispnv50/wndwc37e.o
+nouveau-y += dispnv50/wndwc57e.o
 
 nouveau-y += dispnv50/base.o
 nouveau-y += dispnv50/base507c.o
index 908feb1..a194990 100644 (file)
@@ -54,9 +54,10 @@ struct nv50_head_atom {
                u64 offset:40;
                u8 buffer:1;
                u8 mode:4;
-               u8 size:2;
+               u16 size:11;
                u8 range:2;
                u8 output_mode:2;
+               void (*load)(struct drm_color_lut *, int size, void __iomem *);
        } olut;
 
        struct {
@@ -169,9 +170,11 @@ struct nv50_wndw_atom {
                        u8  buffer:1;
                        u8  enable:2;
                        u8  mode:4;
-                       u8  size:2;
+                       u16 size:11;
                        u8  range:2;
                        u8  output_mode:2;
+                       void (*load)(struct drm_color_lut *, int size,
+                                    void __iomem *);
                } i;
        } xlut;
 
index a562fc9..049ce6d 100644 (file)
@@ -80,6 +80,7 @@ base907c_ilut(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
 {
        asyw->xlut.i.mode = 7;
        asyw->xlut.i.enable = 2;
+       asyw->xlut.i.load = head907d_olut_load;
 }
 
 const struct nv50_wndw_func
index f3c49ad..c25e0eb 100644 (file)
@@ -42,6 +42,7 @@ nv50_core_new(struct nouveau_drm *drm, struct nv50_core **pcore)
                int version;
                int (*new)(struct nouveau_drm *, s32, struct nv50_core **);
        } cores[] = {
+               { TU104_DISP_CORE_CHANNEL_DMA, 0, corec57d_new },
                { GV100_DISP_CORE_CHANNEL_DMA, 0, corec37d_new },
                { GP102_DISP_CORE_CHANNEL_DMA, 0, core917d_new },
                { GP100_DISP_CORE_CHANNEL_DMA, 0, core917d_new },
index 8470df9..df8336b 100644 (file)
@@ -46,5 +46,9 @@ extern const struct nv50_outp_func sor907d;
 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);
 extern const struct nv50_outp_func sorc37d;
+
+int corec57d_new(struct nouveau_drm *, s32, struct nv50_core **);
 #endif
index b5c17c9..7860774 100644 (file)
@@ -24,7 +24,7 @@
 
 #include <nouveau_bo.h>
 
-static void
+void
 corec37d_update(struct nv50_core *core, u32 *interlock, bool ntfy)
 {
        u32 *push;
@@ -71,7 +71,7 @@ corec37d_ntfy_init(struct nouveau_bo *bo, u32 offset)
        nouveau_bo_wr32(bo, offset / 4 + 3, 0x00000000);
 }
 
-void
+static void
 corec37d_init(struct nv50_core *core)
 {
        const u32 windows = 8; /*XXX*/
diff --git a/drivers/gpu/drm/nouveau/dispnv50/corec57d.c b/drivers/gpu/drm/nouveau/dispnv50/corec57d.c
new file mode 100644 (file)
index 0000000..b606d68
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * 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 "core.h"
+#include "head.h"
+
+static void
+corec57d_init(struct nv50_core *core)
+{
+       const u32 windows = 8; /*XXX*/
+       u32 *push, i;
+       if ((push = evo_wait(&core->chan, 2 + 6 * 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_data(push, 0x0000000f);
+                       evo_data(push, 0x00000000);
+                       evo_mthd(push, 0x1010 + (i * 0x080), 1);
+                       evo_data(push, 0x00117fff);
+               }
+               evo_mthd(push, 0x0200, 1);
+               evo_data(push, 0x00000001);
+               evo_kick(push, &core->chan);
+       }
+}
+
+static const struct nv50_core_func
+corec57d = {
+       .init = corec57d_init,
+       .ntfy_init = corec37d_ntfy_init,
+       .ntfy_wait_done = corec37d_ntfy_wait_done,
+       .update = corec37d_update,
+       .head = &headc57d,
+       .sor = &sorc37d,
+};
+
+int
+corec57d_new(struct nouveau_drm *drm, s32 oclass, struct nv50_core **pcore)
+{
+       return core507d_new_(&corec57d, drm, oclass, pcore);
+}
index f592087..cb6e4d2 100644 (file)
@@ -31,6 +31,7 @@ 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[] = {
+               { TU104_DISP_CURSOR, 0, cursc37a_new },
                { GV100_DISP_CURSOR, 0, cursc37a_new },
                { GK104_DISP_CURSOR, 0, curs907a_new },
                { GF110_DISP_CURSOR, 0, curs907a_new },
index 6cbbae3..00add3b 100644 (file)
@@ -1255,8 +1255,16 @@ nv50_mstm_fini(struct nv50_mstm *mstm)
 static void
 nv50_mstm_init(struct nv50_mstm *mstm)
 {
-       if (mstm && mstm->mgr.mst_state)
-               drm_dp_mst_topology_mgr_resume(&mstm->mgr);
+       int ret;
+
+       if (!mstm || !mstm->mgr.mst_state)
+               return;
+
+       ret = drm_dp_mst_topology_mgr_resume(&mstm->mgr);
+       if (ret == -1) {
+               drm_dp_mst_topology_mgr_set_mst(&mstm->mgr, false);
+               drm_kms_helper_hotplug_event(mstm->mgr.dev);
+       }
 }
 
 static void
@@ -2293,7 +2301,7 @@ nv50_display_create(struct drm_device *dev)
 
        /* create encoder/connector objects based on VBIOS DCB table */
        for (i = 0, dcbe = &dcb->entry[0]; i < dcb->entries; i++, dcbe++) {
-               connector = nouveau_connector_create(dev, dcbe->connector);
+               connector = nouveau_connector_create(dev, dcbe);
                if (IS_ERR(connector))
                        continue;
 
index e48c5eb..2216c58 100644 (file)
@@ -45,6 +45,8 @@ struct nv50_disp_interlock {
 
 void corec37d_ntfy_init(struct nouveau_bo *, u32);
 
+void head907d_olut_load(struct drm_color_lut *, int size, void __iomem *);
+
 struct nv50_chan {
        struct nvif_object user;
        struct nvif_device *device;
index 4f57e53..ac97ebc 100644 (file)
@@ -50,9 +50,9 @@ nv50_head_flush_set(struct nv50_head *head, struct nv50_head_atom *asyh)
        if (asyh->set.core   ) head->func->core_set(head, asyh);
        if (asyh->set.olut   ) {
                asyh->olut.offset = nv50_lut_load(&head->olut,
-                                                 asyh->olut.mode <= 1,
                                                  asyh->olut.buffer,
-                                                 asyh->state.gamma_lut);
+                                                 asyh->state.gamma_lut,
+                                                 asyh->olut.load);
                head->func->olut_set(head, asyh);
        }
        if (asyh->set.curs   ) head->func->curs_set(head, asyh);
@@ -210,7 +210,7 @@ nv50_head_atomic_check_lut(struct nv50_head *head,
                }
        }
 
-       if (!olut) {
+       if (!olut && !head->func->olut_identity) {
                asyh->olut.handle = 0;
                return 0;
        }
index 37b3248..d1c002f 100644 (file)
@@ -21,6 +21,7 @@ struct nv50_head_func {
        void (*view)(struct nv50_head *, struct nv50_head_atom *);
        void (*mode)(struct nv50_head *, struct nv50_head_atom *);
        void (*olut)(struct nv50_head *, struct nv50_head_atom *);
+       bool olut_identity;
        void (*olut_set)(struct nv50_head *, struct nv50_head_atom *);
        void (*olut_clr)(struct nv50_head *);
        void (*core_calc)(struct nv50_head *, struct nv50_head_atom *);
@@ -75,4 +76,14 @@ int head917d_curs_layout(struct nv50_head *, struct nv50_wndw_atom *,
                         struct nv50_head_atom *);
 
 extern const struct nv50_head_func headc37d;
+void headc37d_view(struct nv50_head *, struct nv50_head_atom *);
+void headc37d_core_set(struct nv50_head *, struct nv50_head_atom *);
+void headc37d_core_clr(struct nv50_head *);
+int headc37d_curs_format(struct nv50_head *, struct nv50_wndw_atom *,
+                        struct nv50_head_atom *);
+void headc37d_curs_set(struct nv50_head *, struct nv50_head_atom *);
+void headc37d_curs_clr(struct nv50_head *);
+void headc37d_dither(struct nv50_head *, struct nv50_head_atom *);
+
+extern const struct nv50_head_func headc57d;
 #endif
index 51bc599..7561be5 100644 (file)
@@ -254,6 +254,23 @@ head507d_olut_set(struct nv50_head *head, struct nv50_head_atom *asyh)
        }
 }
 
+static void
+head507d_olut_load(struct drm_color_lut *in, int size, void __iomem *mem)
+{
+       for (; size--; in++, mem += 8) {
+               writew(drm_color_lut_extract(in->  red, 11) << 3, mem + 0);
+               writew(drm_color_lut_extract(in->green, 11) << 3, mem + 2);
+               writew(drm_color_lut_extract(in-> blue, 11) << 3, mem + 4);
+       }
+
+       /* INTERPOLATE modes require a "next" entry to interpolate with,
+        * so we replicate the last entry to deal with this for now.
+        */
+       writew(readw(mem - 8), mem + 0);
+       writew(readw(mem - 6), mem + 2);
+       writew(readw(mem - 4), mem + 4);
+}
+
 void
 head507d_olut(struct nv50_head *head, struct nv50_head_atom *asyh)
 {
@@ -261,6 +278,8 @@ head507d_olut(struct nv50_head *head, struct nv50_head_atom *asyh)
                asyh->olut.mode = 0;
        else
                asyh->olut.mode = 1;
+
+       asyh->olut.load = head507d_olut_load;
 }
 
 void
index 6339071..c2d09dd 100644 (file)
@@ -213,10 +213,28 @@ head907d_olut_set(struct nv50_head *head, struct nv50_head_atom *asyh)
        }
 }
 
+void
+head907d_olut_load(struct drm_color_lut *in, int size, void __iomem *mem)
+{
+       for (; size--; in++, mem += 8) {
+               writew(drm_color_lut_extract(in->  red, 14) + 0x6000, mem + 0);
+               writew(drm_color_lut_extract(in->green, 14) + 0x6000, mem + 2);
+               writew(drm_color_lut_extract(in-> blue, 14) + 0x6000, mem + 4);
+       }
+
+       /* INTERPOLATE modes require a "next" entry to interpolate with,
+        * so we replicate the last entry to deal with this for now.
+        */
+       writew(readw(mem - 8), mem + 0);
+       writew(readw(mem - 6), mem + 2);
+       writew(readw(mem - 4), mem + 4);
+}
+
 void
 head907d_olut(struct nv50_head *head, struct nv50_head_atom *asyh)
 {
        asyh->olut.mode = 7;
+       asyh->olut.load = head907d_olut_load;
 }
 
 void
index 989c140..ef6a99d 100644 (file)
@@ -65,7 +65,7 @@ headc37d_procamp(struct nv50_head *head, struct nv50_head_atom *asyh)
        }
 }
 
-static void
+void
 headc37d_dither(struct nv50_head *head, struct nv50_head_atom *asyh)
 {
        struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan;
@@ -79,7 +79,7 @@ headc37d_dither(struct nv50_head *head, struct nv50_head_atom *asyh)
        }
 }
 
-static void
+void
 headc37d_curs_clr(struct nv50_head *head)
 {
        struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan;
@@ -93,7 +93,7 @@ headc37d_curs_clr(struct nv50_head *head)
        }
 }
 
-static void
+void
 headc37d_curs_set(struct nv50_head *head, struct nv50_head_atom *asyh)
 {
        struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan;
@@ -112,7 +112,7 @@ headc37d_curs_set(struct nv50_head *head, struct nv50_head_atom *asyh)
        }
 }
 
-static int
+int
 headc37d_curs_format(struct nv50_head *head, struct nv50_wndw_atom *asyw,
                     struct nv50_head_atom *asyh)
 {
@@ -155,6 +155,7 @@ headc37d_olut(struct nv50_head *head, struct nv50_head_atom *asyh)
        asyh->olut.size = 0;
        asyh->olut.range = 0;
        asyh->olut.output_mode = 1;
+       asyh->olut.load = head907d_olut_load;
 }
 
 static void
@@ -181,7 +182,7 @@ headc37d_mode(struct nv50_head *head, struct nv50_head_atom *asyh)
        }
 }
 
-static void
+void
 headc37d_view(struct nv50_head *head, struct nv50_head_atom *asyh)
 {
        struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan;
diff --git a/drivers/gpu/drm/nouveau/dispnv50/headc57d.c b/drivers/gpu/drm/nouveau/dispnv50/headc57d.c
new file mode 100644 (file)
index 0000000..32a7f9e
--- /dev/null
@@ -0,0 +1,206 @@
+/*
+ * 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 "head.h"
+#include "atom.h"
+#include "core.h"
+
+static void
+headc57d_or(struct nv50_head *head, struct nv50_head_atom *asyh)
+{
+       struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan;
+       u32 *push;
+       if ((push = evo_wait(core, 2))) {
+               /*XXX: This is a dirty hack until OR depth handling is
+                *     improved later for deep colour etc.
+                */
+               switch (asyh->or.depth) {
+               case 6: asyh->or.depth = 5; break;
+               case 5: asyh->or.depth = 4; break;
+               case 2: asyh->or.depth = 1; break;
+               case 0: asyh->or.depth = 4; break;
+               default:
+                       WARN_ON(1);
+                       break;
+               }
+
+               evo_mthd(push, 0x2004 + (head->base.index * 0x400), 1);
+               evo_data(push, 0xfc000001 |
+                              asyh->or.depth << 4 |
+                              asyh->or.nvsync << 3 |
+                              asyh->or.nhsync << 2);
+               evo_kick(push, core);
+       }
+}
+
+static void
+headc57d_procamp(struct nv50_head *head, struct nv50_head_atom *asyh)
+{
+       struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan;
+       u32 *push;
+       if ((push = evo_wait(core, 2))) {
+               evo_mthd(push, 0x2000 + (head->base.index * 0x400), 1);
+#if 0
+               evo_data(push, 0x80000000 |
+                              asyh->procamp.sat.sin << 16 |
+                              asyh->procamp.sat.cos << 4);
+#else
+               evo_data(push, 0);
+#endif
+               evo_kick(push, core);
+       }
+}
+
+void
+headc57d_olut_clr(struct nv50_head *head)
+{
+       struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan;
+       u32 *push;
+       if ((push = evo_wait(core, 2))) {
+               evo_mthd(push, 0x2288 + (head->base.index * 0x400), 1);
+               evo_data(push, 0x00000000);
+               evo_kick(push, core);
+       }
+}
+
+void
+headc57d_olut_set(struct nv50_head *head, struct nv50_head_atom *asyh)
+{
+       struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan;
+       u32 *push;
+       if ((push = evo_wait(core, 4))) {
+               evo_mthd(push, 0x2280 + (head->base.index * 0x400), 4);
+               evo_data(push, asyh->olut.size << 8 |
+                              asyh->olut.mode << 2 |
+                              asyh->olut.output_mode);
+               evo_data(push, 0xffffffff); /* FP_NORM_SCALE. */
+               evo_data(push, asyh->olut.handle);
+               evo_data(push, asyh->olut.offset >> 8);
+               evo_kick(push, core);
+       }
+}
+
+static void
+headc57d_olut_load_8(struct drm_color_lut *in, int size, void __iomem *mem)
+{
+       memset_io(mem, 0x00, 0x20); /* VSS header. */
+       mem += 0x20;
+
+       while (size--) {
+               u16 r = drm_color_lut_extract(in->  red + 0, 16);
+               u16 g = drm_color_lut_extract(in->green + 0, 16);
+               u16 b = drm_color_lut_extract(in-> blue + 0, 16);
+               u16 ri = 0, gi = 0, bi = 0, i;
+
+               if (in++, size) {
+                       ri = (drm_color_lut_extract(in->  red, 16) - r) / 4;
+                       gi = (drm_color_lut_extract(in->green, 16) - g) / 4;
+                       bi = (drm_color_lut_extract(in-> blue, 16) - b) / 4;
+               }
+
+               for (i = 0; i < 4; i++, mem += 8) {
+                       writew(r + ri * i, mem + 0);
+                       writew(g + gi * i, mem + 2);
+                       writew(b + bi * i, mem + 4);
+               }
+       }
+
+       /* INTERPOLATE modes require a "next" entry to interpolate with,
+        * so we replicate the last entry to deal with this for now.
+        */
+       writew(readw(mem - 8), mem + 0);
+       writew(readw(mem - 6), mem + 2);
+       writew(readw(mem - 4), mem + 4);
+}
+
+static void
+headc57d_olut_load(struct drm_color_lut *in, int size, void __iomem *mem)
+{
+       memset_io(mem, 0x00, 0x20); /* VSS header. */
+       mem += 0x20;
+
+       for (; size--; in++, mem += 0x08) {
+               writew(drm_color_lut_extract(in->  red, 16), mem + 0);
+               writew(drm_color_lut_extract(in->green, 16), mem + 2);
+               writew(drm_color_lut_extract(in-> blue, 16), mem + 4);
+       }
+
+       /* INTERPOLATE modes require a "next" entry to interpolate with,
+        * so we replicate the last entry to deal with this for now.
+        */
+       writew(readw(mem - 8), mem + 0);
+       writew(readw(mem - 6), mem + 2);
+       writew(readw(mem - 4), mem + 4);
+}
+
+void
+headc57d_olut(struct nv50_head *head, struct nv50_head_atom *asyh)
+{
+       asyh->olut.mode = 2; /* DIRECT10 */
+       asyh->olut.size = 4 /* VSS header. */ + 1024 + 1 /* Entries. */;
+       asyh->olut.output_mode = 1; /* INTERPOLATE_ENABLE. */
+       if (asyh->state.gamma_lut &&
+           asyh->state.gamma_lut->length / sizeof(struct drm_color_lut) == 256)
+               asyh->olut.load = headc57d_olut_load_8;
+       else
+               asyh->olut.load = headc57d_olut_load;
+}
+
+static void
+headc57d_mode(struct nv50_head *head, struct nv50_head_atom *asyh)
+{
+       struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan;
+       struct nv50_head_mode *m = &asyh->mode;
+       u32 *push;
+       if ((push = evo_wait(core, 12))) {
+               evo_mthd(push, 0x2064 + (head->base.index * 0x400), 5);
+               evo_data(push, (m->v.active  << 16) | m->h.active );
+               evo_data(push, (m->v.synce   << 16) | m->h.synce  );
+               evo_data(push, (m->v.blanke  << 16) | m->h.blanke );
+               evo_data(push, (m->v.blanks  << 16) | m->h.blanks );
+               evo_data(push, (m->v.blank2e << 16) | m->v.blank2s);
+               evo_mthd(push, 0x200c + (head->base.index * 0x400), 1);
+               evo_data(push, m->clock * 1000);
+               evo_mthd(push, 0x2028 + (head->base.index * 0x400), 1);
+               evo_data(push, m->clock * 1000);
+               /*XXX: HEAD_USAGE_BOUNDS, doesn't belong here. */
+               evo_mthd(push, 0x2030 + (head->base.index * 0x400), 1);
+               evo_data(push, 0x00001014);
+               evo_kick(push, core);
+       }
+}
+
+const struct nv50_head_func
+headc57d = {
+       .view = headc37d_view,
+       .mode = headc57d_mode,
+       .olut = headc57d_olut,
+       .olut_identity = true,
+       .olut_set = headc57d_olut_set,
+       .olut_clr = headc57d_olut_clr,
+       .curs_layout = head917d_curs_layout,
+       .curs_format = headc37d_curs_format,
+       .curs_set = headc37d_curs_set,
+       .curs_clr = headc37d_curs_clr,
+       .dither = headc37d_dither,
+       .procamp = headc57d_procamp,
+       .or = headc57d_or,
+};
index a6b96ae..994def4 100644 (file)
 #include <nvif/class.h>
 
 u32
-nv50_lut_load(struct nv50_lut *lut, bool legacy, int buffer,
-             struct drm_property_blob *blob)
+nv50_lut_load(struct nv50_lut *lut, int buffer, struct drm_property_blob *blob,
+             void (*load)(struct drm_color_lut *, int, void __iomem *))
 {
-       struct drm_color_lut *in = (struct drm_color_lut *)blob->data;
+       struct drm_color_lut *in = blob ? blob->data : NULL;
        void __iomem *mem = lut->mem[buffer].object.map.ptr;
-       const int size = blob->length / sizeof(*in);
-       int bits, shift, i;
-       u16 zero, r, g, b;
-       u32 addr = lut->mem[buffer].addr;
-
-       /* This can't happen.. But it shuts the compiler up. */
-       if (WARN_ON(size != 256))
-               return 0;
+       const u32 addr = lut->mem[buffer].addr;
+       int i;
 
-       if (legacy) {
-               bits = 11;
-               shift = 3;
-               zero = 0x0000;
+       if (!in) {
+               in = kvmalloc_array(1024, sizeof(*in), GFP_KERNEL);
+               if (!WARN_ON(!in)) {
+                       for (i = 0; i < 1024; i++) {
+                               in[i].red   =
+                               in[i].green =
+                               in[i].blue  = (i << 16) >> 10;
+                       }
+                       load(in, 1024, mem);
+                       kvfree(in);
+               }
        } else {
-               bits = 14;
-               shift = 0;
-               zero = 0x6000;
-       }
-
-       for (i = 0; i < size; i++) {
-               r = (drm_color_lut_extract(in[i].  red, bits) + zero) << shift;
-               g = (drm_color_lut_extract(in[i].green, bits) + zero) << shift;
-               b = (drm_color_lut_extract(in[i]. blue, bits) + zero) << shift;
-               writew(r, mem + (i * 0x08) + 0);
-               writew(g, mem + (i * 0x08) + 2);
-               writew(b, mem + (i * 0x08) + 4);
+               load(in, blob->length / sizeof(*in), mem);
        }
 
-       /* INTERPOLATE modes require a "next" entry to interpolate with,
-        * so we replicate the last entry to deal with this for now.
-        */
-       writew(r, mem + (i * 0x08) + 0);
-       writew(g, mem + (i * 0x08) + 2);
-       writew(b, mem + (i * 0x08) + 4);
        return addr;
 }
 
index 6d7b835..b3b9040 100644 (file)
@@ -2,6 +2,7 @@
 #define __NV50_KMS_LUT_H__
 #include <nvif/mem.h>
 struct drm_property_blob;
+struct drm_color_lut;
 struct nv50_disp;
 
 struct nv50_lut {
@@ -10,6 +11,6 @@ struct nv50_lut {
 
 int nv50_lut_init(struct nv50_disp *, struct nvif_mmu *, struct nv50_lut *);
 void nv50_lut_fini(struct nv50_lut *);
-u32 nv50_lut_load(struct nv50_lut *, bool legacy, int buffer,
-                 struct drm_property_blob *);
+u32 nv50_lut_load(struct nv50_lut *, int buffer, struct drm_property_blob *,
+                 void (*)(struct drm_color_lut *, int size, void __iomem *));
 #endif
index fc36e06..bc9eeaf 100644 (file)
@@ -31,6 +31,7 @@ nv50_wimm_init(struct nouveau_drm *drm, struct nv50_wndw *wndw)
                int version;
                int (*init)(struct nouveau_drm *, s32, struct nv50_wndw *);
        } wimms[] = {
+               { TU104_DISP_WINDOW_IMM_CHANNEL_DMA, 0, wimmc37b_init },
                { GV100_DISP_WINDOW_IMM_CHANNEL_DMA, 0, wimmc37b_init },
                {}
        };
index 2187922..ba9eea2 100644 (file)
@@ -139,10 +139,8 @@ nv50_wndw_flush_set(struct nv50_wndw *wndw, u32 *interlock,
        if (asyw->set.xlut ) {
                if (asyw->ilut) {
                        asyw->xlut.i.offset =
-                               nv50_lut_load(&wndw->ilut,
-                                             asyw->xlut.i.mode <= 1,
-                                             asyw->xlut.i.buffer,
-                                             asyw->ilut);
+                               nv50_lut_load(&wndw->ilut, asyw->xlut.i.buffer,
+                                             asyw->ilut, asyw->xlut.i.load);
                }
                wndw->func->xlut_set(wndw, asyw);
        }
@@ -322,6 +320,11 @@ nv50_wndw_atomic_check_lut(struct nv50_wndw *wndw,
                asyh->wndw.olut &= ~BIT(wndw->id);
        }
 
+       if (!ilut && wndw->func->ilut_identity) {
+               static struct drm_property_blob dummy = {};
+               ilut = &dummy;
+       }
+
        /* Recalculate LUT state. */
        memset(&asyw->xlut, 0x00, sizeof(asyw->xlut));
        if ((asyw->ilut = wndw->func->ilut ? ilut : NULL)) {
@@ -623,6 +626,7 @@ nv50_wndw_new(struct nouveau_drm *drm, enum drm_plane_type type, int index,
                int (*new)(struct nouveau_drm *, enum drm_plane_type,
                           int, s32, struct nv50_wndw **);
        } wndws[] = {
+               { TU104_DISP_WINDOW_CHANNEL_DMA, 0, wndwc57e_new },
                { GV100_DISP_WINDOW_CHANNEL_DMA, 0, wndwc37e_new },
                {}
        };
index b0b6428..03f3d8d 100644 (file)
@@ -65,6 +65,7 @@ struct nv50_wndw_func {
        int (*ntfy_wait_begun)(struct nouveau_bo *, u32 offset,
                               struct nvif_device *);
        void (*ilut)(struct nv50_wndw *, struct nv50_wndw_atom *);
+       bool ilut_identity;
        bool olut_core;
        void (*xlut_set)(struct nv50_wndw *, struct nv50_wndw_atom *);
        void (*xlut_clr)(struct nv50_wndw *);
@@ -90,6 +91,23 @@ extern const struct nv50_wimm_func curs507a;
 
 int wndwc37e_new(struct nouveau_drm *, enum drm_plane_type, int, s32,
                 struct nv50_wndw **);
+int wndwc37e_new_(const struct nv50_wndw_func *, struct nouveau_drm *,
+                 enum drm_plane_type type, int index, s32 oclass, u32 heads,
+                 struct nv50_wndw **);
+int wndwc37e_acquire(struct nv50_wndw *, struct nv50_wndw_atom *,
+                    struct nv50_head_atom *);
+void wndwc37e_release(struct nv50_wndw *, struct nv50_wndw_atom *,
+                     struct nv50_head_atom *);
+void wndwc37e_sema_set(struct nv50_wndw *, struct nv50_wndw_atom *);
+void wndwc37e_sema_clr(struct nv50_wndw *);
+void wndwc37e_ntfy_set(struct nv50_wndw *, struct nv50_wndw_atom *);
+void wndwc37e_ntfy_clr(struct nv50_wndw *);
+void wndwc37e_image_set(struct nv50_wndw *, struct nv50_wndw_atom *);
+void wndwc37e_image_clr(struct nv50_wndw *);
+void wndwc37e_update(struct nv50_wndw *, u32 *);
+
+int wndwc57e_new(struct nouveau_drm *, enum drm_plane_type, int, s32,
+                struct nv50_wndw **);
 
 int nv50_wndw_new(struct nouveau_drm *, enum drm_plane_type, int index,
                  struct nv50_wndw **);
index 44afb0f..e52a85c 100644 (file)
@@ -61,9 +61,10 @@ wndwc37e_ilut(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
        asyw->xlut.i.size = 0;
        asyw->xlut.i.range = 0;
        asyw->xlut.i.output_mode = 1;
+       asyw->xlut.i.load = head907d_olut_load;
 }
 
-static void
+void
 wndwc37e_image_clr(struct nv50_wndw *wndw)
 {
        u32 *push;
@@ -76,7 +77,7 @@ wndwc37e_image_clr(struct nv50_wndw *wndw)
        }
 }
 
-static void
+void
 wndwc37e_image_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
 {
        u32 *push;
@@ -117,7 +118,7 @@ wndwc37e_image_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
        evo_kick(push, &wndw->wndw);
 }
 
-static void
+void
 wndwc37e_ntfy_clr(struct nv50_wndw *wndw)
 {
        u32 *push;
@@ -128,7 +129,7 @@ wndwc37e_ntfy_clr(struct nv50_wndw *wndw)
        }
 }
 
-static void
+void
 wndwc37e_ntfy_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
 {
        u32 *push;
@@ -140,7 +141,7 @@ wndwc37e_ntfy_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
        }
 }
 
-static void
+void
 wndwc37e_sema_clr(struct nv50_wndw *wndw)
 {
        u32 *push;
@@ -151,7 +152,7 @@ wndwc37e_sema_clr(struct nv50_wndw *wndw)
        }
 }
 
-static void
+void
 wndwc37e_sema_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
 {
        u32 *push;
@@ -165,7 +166,7 @@ wndwc37e_sema_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
        }
 }
 
-static void
+void
 wndwc37e_update(struct nv50_wndw *wndw, u32 *interlock)
 {
        u32 *push;
@@ -183,13 +184,13 @@ wndwc37e_update(struct nv50_wndw *wndw, u32 *interlock)
        }
 }
 
-static void
+void
 wndwc37e_release(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw,
                 struct nv50_head_atom *asyh)
 {
 }
 
-static int
+int
 wndwc37e_acquire(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw,
                 struct nv50_head_atom *asyh)
 {
@@ -236,7 +237,7 @@ wndwc37e = {
        .update = wndwc37e_update,
 };
 
-static int
+int
 wndwc37e_new_(const struct nv50_wndw_func *func, struct nouveau_drm *drm,
              enum drm_plane_type type, int index, s32 oclass, u32 heads,
              struct nv50_wndw **pwndw)
diff --git a/drivers/gpu/drm/nouveau/dispnv50/wndwc57e.c b/drivers/gpu/drm/nouveau/dispnv50/wndwc57e.c
new file mode 100644 (file)
index 0000000..ba89f1a
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ * 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 "wndw.h"
+#include "atom.h"
+
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_plane_helper.h>
+#include <nouveau_bo.h>
+
+#include <nvif/clc37e.h>
+
+static void
+wndwc57e_ilut_clr(struct nv50_wndw *wndw)
+{
+       u32 *push;
+       if ((push = evo_wait(&wndw->wndw, 2))) {
+               evo_mthd(push, 0x0444, 1);
+               evo_data(push, 0x00000000);
+               evo_kick(push, &wndw->wndw);
+       }
+}
+
+static void
+wndwc57e_ilut_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
+{
+       u32 *push;
+       if ((push = evo_wait(&wndw->wndw, 4))) {
+               evo_mthd(push, 0x0440, 3);
+               evo_data(push, asyw->xlut.i.size << 8 |
+                              asyw->xlut.i.mode << 2 |
+                              asyw->xlut.i.output_mode);
+               evo_data(push, asyw->xlut.handle);
+               evo_data(push, asyw->xlut.i.offset >> 8);
+               evo_kick(push, &wndw->wndw);
+       }
+}
+
+static u16
+fixedU0_16_FP16(u16 fixed)
+{
+        int sign = 0, exp = 0, man = 0;
+        if (fixed) {
+                while (--exp && !(fixed & 0x8000))
+                        fixed <<= 1;
+                man = ((fixed << 1) & 0xffc0) >> 6;
+                exp += 15;
+        }
+        return (sign << 15) | (exp << 10) | man;
+}
+
+static void
+wndwc57e_ilut_load(struct drm_color_lut *in, int size, void __iomem *mem)
+{
+       memset_io(mem, 0x00, 0x20); /* VSS header. */
+       mem += 0x20;
+
+       for (; size--; in++, mem += 0x08) {
+               u16 r = fixedU0_16_FP16(drm_color_lut_extract(in->  red, 16));
+               u16 g = fixedU0_16_FP16(drm_color_lut_extract(in->green, 16));
+               u16 b = fixedU0_16_FP16(drm_color_lut_extract(in-> blue, 16));
+               writew(r, mem + 0);
+               writew(g, mem + 2);
+               writew(b, mem + 4);
+       }
+
+       /* INTERPOLATE modes require a "next" entry to interpolate with,
+        * so we replicate the last entry to deal with this for now.
+        */
+       writew(readw(mem - 8), mem + 0);
+       writew(readw(mem - 6), mem + 2);
+       writew(readw(mem - 4), mem + 4);
+}
+
+static void
+wndwc57e_ilut(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
+{
+       u16 size = asyw->ilut->length / sizeof(struct drm_color_lut);
+       if (size == 256) {
+               asyw->xlut.i.mode = 1; /* DIRECT8. */
+       } else {
+               asyw->xlut.i.mode = 2; /* DIRECT10. */
+               size = 1024;
+       }
+       asyw->xlut.i.size = 4 /* VSS header. */ + size + 1 /* Entries. */;
+       asyw->xlut.i.output_mode = 0; /* INTERPOLATE_DISABLE. */
+       asyw->xlut.i.load = wndwc57e_ilut_load;
+}
+
+static const struct nv50_wndw_func
+wndwc57e = {
+       .acquire = wndwc37e_acquire,
+       .release = wndwc37e_release,
+       .sema_set = wndwc37e_sema_set,
+       .sema_clr = wndwc37e_sema_clr,
+       .ntfy_set = wndwc37e_ntfy_set,
+       .ntfy_clr = wndwc37e_ntfy_clr,
+       .ntfy_reset = corec37d_ntfy_init,
+       .ntfy_wait_begun = base507c_ntfy_wait_begun,
+       .ilut = wndwc57e_ilut,
+       .ilut_identity = true,
+       .xlut_set = wndwc57e_ilut_set,
+       .xlut_clr = wndwc57e_ilut_clr,
+       .image_set = wndwc37e_image_set,
+       .image_clr = wndwc37e_image_clr,
+       .update = wndwc37e_update,
+};
+
+int
+wndwc57e_new(struct nouveau_drm *drm, enum drm_plane_type type, int index,
+            s32 oclass, struct nv50_wndw **pwndw)
+{
+       return wndwc37e_new_(&wndwc57e, drm, type, index, oclass,
+                            BIT(index >> 1), pwndw);
+}
index 4f52331..4cbed03 100644 (file)
@@ -32,6 +32,7 @@ struct nv_device_info_v0 {
 #define NV_DEVICE_INFO_V0_MAXWELL                                          0x09
 #define NV_DEVICE_INFO_V0_PASCAL                                           0x0a
 #define NV_DEVICE_INFO_V0_VOLTA                                            0x0b
+#define NV_DEVICE_INFO_V0_TURING                                           0x0c
        __u8  family;
        __u8  pad06[2];
        __u64 ram_size;
index fbfcffc..81401eb 100644 (file)
@@ -4,12 +4,13 @@
 
 struct kepler_channel_gpfifo_a_v0 {
        __u8  version;
-       __u8  pad01[1];
+       __u8  priv;
        __u16 chid;
        __u32 ilength;
        __u64 ioffset;
        __u64 runlist;
        __u64 vmm;
+       __u64 inst;
 };
 
 #define NVA06F_V0_NTFY_NON_STALL_INTERRUPT                                 0x00
index 6db56bd..1d82cbf 100644 (file)
@@ -68,7 +68,8 @@
 #define KEPLER_CHANNEL_GPFIFO_B                       /* cla06f.h */ 0x0000a16f
 #define MAXWELL_CHANNEL_GPFIFO_A                      /* cla06f.h */ 0x0000b06f
 #define PASCAL_CHANNEL_GPFIFO_A                       /* cla06f.h */ 0x0000c06f
-#define VOLTA_CHANNEL_GPFIFO_A                        /* cla06f.h */ 0x0000c36f
+#define VOLTA_CHANNEL_GPFIFO_A                        /* clc36f.h */ 0x0000c36f
+#define TURING_CHANNEL_GPFIFO_A                       /* clc36f.h */ 0x0000c46f
 
 #define NV50_DISP                                     /* cl5070.h */ 0x00005070
 #define G82_DISP                                      /* cl5070.h */ 0x00008270
@@ -83,6 +84,7 @@
 #define GP100_DISP                                    /* cl5070.h */ 0x00009770
 #define GP102_DISP                                    /* cl5070.h */ 0x00009870
 #define GV100_DISP                                    /* cl5070.h */ 0x0000c370
+#define TU104_DISP                                    /* cl5070.h */ 0x0000c570
 
 #define NV31_MPEG                                                    0x00003174
 #define G82_MPEG                                                     0x00008274
@@ -95,6 +97,7 @@
 #define GF110_DISP_CURSOR                             /* cl507a.h */ 0x0000907a
 #define GK104_DISP_CURSOR                             /* cl507a.h */ 0x0000917a
 #define GV100_DISP_CURSOR                             /* cl507a.h */ 0x0000c37a
+#define TU104_DISP_CURSOR                             /* cl507a.h */ 0x0000c57a
 
 #define NV50_DISP_OVERLAY                             /* cl507b.h */ 0x0000507b
 #define G82_DISP_OVERLAY                              /* cl507b.h */ 0x0000827b
 #define GK104_DISP_OVERLAY                            /* cl507b.h */ 0x0000917b
 
 #define GV100_DISP_WINDOW_IMM_CHANNEL_DMA             /* clc37b.h */ 0x0000c37b
+#define TU104_DISP_WINDOW_IMM_CHANNEL_DMA             /* clc37b.h */ 0x0000c57b
 
 #define NV50_DISP_BASE_CHANNEL_DMA                    /* cl507c.h */ 0x0000507c
 #define G82_DISP_BASE_CHANNEL_DMA                     /* cl507c.h */ 0x0000827c
 #define GP100_DISP_CORE_CHANNEL_DMA                   /* cl507d.h */ 0x0000977d
 #define GP102_DISP_CORE_CHANNEL_DMA                   /* cl507d.h */ 0x0000987d
 #define GV100_DISP_CORE_CHANNEL_DMA                   /* cl507d.h */ 0x0000c37d
+#define TU104_DISP_CORE_CHANNEL_DMA                   /* cl507d.h */ 0x0000c57d
 
 #define NV50_DISP_OVERLAY_CHANNEL_DMA                 /* cl507e.h */ 0x0000507e
 #define G82_DISP_OVERLAY_CHANNEL_DMA                  /* cl507e.h */ 0x0000827e
 #define GK104_DISP_OVERLAY_CONTROL_DMA                /* cl507e.h */ 0x0000917e
 
 #define GV100_DISP_WINDOW_CHANNEL_DMA                 /* clc37e.h */ 0x0000c37e
+#define TU104_DISP_WINDOW_CHANNEL_DMA                 /* clc37e.h */ 0x0000c57e
 
 #define NV50_TESLA                                                   0x00005097
 #define G82_TESLA                                                    0x00008297
 #define PASCAL_DMA_COPY_A                                            0x0000c0b5
 #define PASCAL_DMA_COPY_B                                            0x0000c1b5
 #define VOLTA_DMA_COPY_A                                             0x0000c3b5
+#define TURING_DMA_COPY_A                                            0x0000c5b5
 
 #define FERMI_DECOMPRESS                                             0x000090b8
 
diff --git a/drivers/gpu/drm/nouveau/include/nvif/clc36f.h b/drivers/gpu/drm/nouveau/include/nvif/clc36f.h
new file mode 100644 (file)
index 0000000..6b14d7e
--- /dev/null
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __NVIF_CLC36F_H__
+#define __NVIF_CLC36F_H__
+
+struct volta_channel_gpfifo_a_v0 {
+       __u8  version;
+       __u8  priv;
+       __u16 chid;
+       __u32 ilength;
+       __u64 ioffset;
+       __u64 runlist;
+       __u64 vmm;
+       __u64 inst;
+       __u32 token;
+};
+
+#define NVC36F_V0_NTFY_NON_STALL_INTERRUPT                                 0x00
+#define NVC36F_V0_NTFY_KILLED                                              0x01
+#endif
index d83d834..72e4dc1 100644 (file)
@@ -61,7 +61,11 @@ enum nvkm_devidx {
        NVKM_ENGINE_NVENC2,
        NVKM_ENGINE_NVENC_LAST = NVKM_ENGINE_NVENC2,
 
-       NVKM_ENGINE_NVDEC,
+       NVKM_ENGINE_NVDEC0,
+       NVKM_ENGINE_NVDEC1,
+       NVKM_ENGINE_NVDEC2,
+       NVKM_ENGINE_NVDEC_LAST = NVKM_ENGINE_NVDEC2,
+
        NVKM_ENGINE_PM,
        NVKM_ENGINE_SEC,
        NVKM_ENGINE_SEC2,
@@ -114,6 +118,7 @@ struct nvkm_device {
                GM100    = 0x110,
                GP100    = 0x130,
                GV100    = 0x140,
+               TU100    = 0x160,
        } card_type;
        u32 chipset;
        u8  chiprev;
@@ -163,7 +168,7 @@ struct nvkm_device {
        struct nvkm_engine *msppp;
        struct nvkm_engine *msvld;
        struct nvkm_engine *nvenc[3];
-       struct nvkm_nvdec *nvdec;
+       struct nvkm_nvdec *nvdec[3];
        struct nvkm_pm *pm;
        struct nvkm_engine *sec;
        struct nvkm_sec2 *sec2;
@@ -235,7 +240,7 @@ struct nvkm_device_chip {
        int (*msppp   )(struct nvkm_device *, int idx, struct nvkm_engine **);
        int (*msvld   )(struct nvkm_device *, int idx, struct nvkm_engine **);
        int (*nvenc[3])(struct nvkm_device *, int idx, struct nvkm_engine **);
-       int (*nvdec   )(struct nvkm_device *, int idx, struct nvkm_nvdec **);
+       int (*nvdec[3])(struct nvkm_device *, int idx, struct nvkm_nvdec **);
        int (*pm      )(struct nvkm_device *, int idx, struct nvkm_pm **);
        int (*sec     )(struct nvkm_device *, int idx, struct nvkm_engine **);
        int (*sec2    )(struct nvkm_device *, int idx, struct nvkm_sec2 **);
index 05f505d..f34c803 100644 (file)
@@ -29,6 +29,7 @@ struct nvkm_memory_func {
        void *(*dtor)(struct nvkm_memory *);
        enum nvkm_memory_target (*target)(struct nvkm_memory *);
        u8 (*page)(struct nvkm_memory *);
+       u64 (*bar2)(struct nvkm_memory *);
        u64 (*addr)(struct nvkm_memory *);
        u64 (*size)(struct nvkm_memory *);
        void (*boot)(struct nvkm_memory *, struct nvkm_vmm *);
@@ -56,6 +57,7 @@ void nvkm_memory_tags_put(struct nvkm_memory *, struct nvkm_device *,
 
 #define nvkm_memory_target(p) (p)->func->target(p)
 #define nvkm_memory_page(p) (p)->func->page(p)
+#define nvkm_memory_bar2(p) (p)->func->bar2(p)
 #define nvkm_memory_addr(p) (p)->func->addr(p)
 #define nvkm_memory_size(p) (p)->func->size(p)
 #define nvkm_memory_boot(p,v) (p)->func->boot((p),(v))
index fc295e1..86abe76 100644 (file)
@@ -11,4 +11,5 @@ int gm200_ce_new(struct nvkm_device *, int, struct nvkm_engine **);
 int gp100_ce_new(struct nvkm_device *, int, struct nvkm_engine **);
 int gp102_ce_new(struct nvkm_device *, int, struct nvkm_engine **);
 int gv100_ce_new(struct nvkm_device *, int, struct nvkm_engine **);
+int tu104_ce_new(struct nvkm_device *, int, struct nvkm_engine **);
 #endif
index ef7dc08..5ca86e1 100644 (file)
@@ -36,4 +36,5 @@ int gm200_disp_new(struct nvkm_device *, int, struct nvkm_disp **);
 int gp100_disp_new(struct nvkm_device *, int, struct nvkm_disp **);
 int gp102_disp_new(struct nvkm_device *, int, struct nvkm_disp **);
 int gv100_disp_new(struct nvkm_device *, int, struct nvkm_disp **);
+int tu104_disp_new(struct nvkm_device *, int, struct nvkm_disp **);
 #endif
index 7e39fbe..3b2b685 100644 (file)
@@ -74,4 +74,5 @@ int gm20b_fifo_new(struct nvkm_device *, int, struct nvkm_fifo **);
 int gp100_fifo_new(struct nvkm_device *, int, struct nvkm_fifo **);
 int gp10b_fifo_new(struct nvkm_device *, int, struct nvkm_fifo **);
 int gv100_fifo_new(struct nvkm_device *, int, struct nvkm_fifo **);
+int tu104_fifo_new(struct nvkm_device *, int, struct nvkm_fifo **);
 #endif
index f6bd94c..fd9d713 100644 (file)
@@ -16,8 +16,10 @@ struct nvkm_bar {
 };
 
 struct nvkm_vmm *nvkm_bar_bar1_vmm(struct nvkm_device *);
+void nvkm_bar_bar1_reset(struct nvkm_device *);
 void nvkm_bar_bar2_init(struct nvkm_device *);
 void nvkm_bar_bar2_fini(struct nvkm_device *);
+void nvkm_bar_bar2_reset(struct nvkm_device *);
 struct nvkm_vmm *nvkm_bar_bar2_vmm(struct nvkm_device *);
 void nvkm_bar_flush(struct nvkm_bar *);
 
@@ -27,4 +29,5 @@ int gf100_bar_new(struct nvkm_device *, int, struct nvkm_bar **);
 int gk20a_bar_new(struct nvkm_device *, int, struct nvkm_bar **);
 int gm107_bar_new(struct nvkm_device *, int, struct nvkm_bar **);
 int gm20b_bar_new(struct nvkm_device *, int, struct nvkm_bar **);
+int tu104_bar_new(struct nvkm_device *, int, struct nvkm_bar **);
 #endif
index 703a5b5..425ccc4 100644 (file)
@@ -12,11 +12,14 @@ u32 nvbios_M0203Tp(struct nvkm_bios *, u8 *ver, u8 *hdr, u8 *cnt, u8 *len,
                   struct nvbios_M0203T *);
 
 struct nvbios_M0203E {
-#define M0203E_TYPE_DDR2  0x0
-#define M0203E_TYPE_DDR3  0x1
-#define M0203E_TYPE_GDDR3 0x2
-#define M0203E_TYPE_GDDR5 0x3
-#define M0203E_TYPE_SKIP  0xf
+#define M0203E_TYPE_DDR2   0x0
+#define M0203E_TYPE_DDR3   0x1
+#define M0203E_TYPE_GDDR3  0x2
+#define M0203E_TYPE_GDDR5  0x3
+#define M0203E_TYPE_HBM2   0x6
+#define M0203E_TYPE_GDDR5X 0x8
+#define M0203E_TYPE_GDDR6  0x9
+#define M0203E_TYPE_SKIP   0xf
        u8 type;
        u8 strap;
        u8 group;
index ed9e0a6..8463b42 100644 (file)
@@ -20,6 +20,7 @@ enum dcb_connector_type {
        DCB_CONNECTOR_DMS59_DP0 = 0x64,
        DCB_CONNECTOR_DMS59_DP1 = 0x65,
        DCB_CONNECTOR_WFD       = 0x70,
+       DCB_CONNECTOR_USB_C = 0x71,
        DCB_CONNECTOR_NONE = 0xff
 };
 
index 486e763..1b71812 100644 (file)
@@ -31,4 +31,5 @@ int gf100_devinit_new(struct nvkm_device *, int, struct nvkm_devinit **);
 int gm107_devinit_new(struct nvkm_device *, int, struct nvkm_devinit **);
 int gm200_devinit_new(struct nvkm_device *, int, struct nvkm_devinit **);
 int gv100_devinit_new(struct nvkm_device *, int, struct nvkm_devinit **);
+int tu104_devinit_new(struct nvkm_device *, int, struct nvkm_devinit **);
 #endif
index 5a77498..127f480 100644 (file)
@@ -30,4 +30,5 @@ struct nvkm_fault_data {
 
 int gp100_fault_new(struct nvkm_device *, int, struct nvkm_fault **);
 int gv100_fault_new(struct nvkm_device *, int, struct nvkm_fault **);
+int tu104_fault_new(struct nvkm_device *, int, struct nvkm_fault **);
 #endif
index 96ccc62..27298f8 100644 (file)
@@ -105,7 +105,10 @@ enum nvkm_ram_type {
        NVKM_RAM_TYPE_GDDR2,
        NVKM_RAM_TYPE_GDDR3,
        NVKM_RAM_TYPE_GDDR4,
-       NVKM_RAM_TYPE_GDDR5
+       NVKM_RAM_TYPE_GDDR5,
+       NVKM_RAM_TYPE_GDDR5X,
+       NVKM_RAM_TYPE_GDDR6,
+       NVKM_RAM_TYPE_HBM2,
 };
 
 struct nvkm_ram {
index 61c93c8..b66dedd 100644 (file)
@@ -31,4 +31,5 @@ int gk104_mc_new(struct nvkm_device *, int, struct nvkm_mc **);
 int gk20a_mc_new(struct nvkm_device *, int, struct nvkm_mc **);
 int gp100_mc_new(struct nvkm_device *, int, struct nvkm_mc **);
 int gp10b_mc_new(struct nvkm_device *, int, struct nvkm_mc **);
+int tu104_mc_new(struct nvkm_device *, int, struct nvkm_mc **);
 #endif
index 6885955..0a0e064 100644 (file)
@@ -130,4 +130,5 @@ int gm20b_mmu_new(struct nvkm_device *, int, struct nvkm_mmu **);
 int gp100_mmu_new(struct nvkm_device *, int, struct nvkm_mmu **);
 int gp10b_mmu_new(struct nvkm_device *, int, struct nvkm_mmu **);
 int gv100_mmu_new(struct nvkm_device *, int, struct nvkm_mmu **);
+int tu104_mmu_new(struct nvkm_device *, int, struct nvkm_mmu **);
 #endif
index e9b0746..3693ebf 100644 (file)
@@ -28,6 +28,18 @@ struct nvkm_timer {
 u64 nvkm_timer_read(struct nvkm_timer *);
 void nvkm_timer_alarm(struct nvkm_timer *, u32 nsec, struct nvkm_alarm *);
 
+struct nvkm_timer_wait {
+       struct nvkm_timer *tmr;
+       u64 limit;
+       u64 time0;
+       u64 time1;
+       int reads;
+};
+
+void nvkm_timer_wait_init(struct nvkm_device *, u64 nsec,
+                         struct nvkm_timer_wait *);
+s64 nvkm_timer_wait_test(struct nvkm_timer_wait *);
+
 /* Delay based on GPU time (ie. PTIMER).
  *
  * Will return -ETIMEDOUT unless the loop was terminated with 'break',
@@ -38,21 +50,17 @@ void nvkm_timer_alarm(struct nvkm_timer *, u32 nsec, struct nvkm_alarm *);
  */
 #define NVKM_DELAY _warn = false;
 #define nvkm_nsec(d,n,cond...) ({                                              \
-       struct nvkm_device *_device = (d);                                     \
-       struct nvkm_timer *_tmr = _device->timer;                              \
-       u64 _nsecs = (n), _time0 = nvkm_timer_read(_tmr);                      \
-       s64 _taken = 0;                                                        \
+       struct nvkm_timer_wait _wait;                                          \
        bool _warn = true;                                                     \
+       s64 _taken = 0;                                                        \
                                                                                \
+       nvkm_timer_wait_init((d), (n), &_wait);                                \
        do {                                                                   \
                cond                                                           \
-       } while (_taken = nvkm_timer_read(_tmr) - _time0, _taken < _nsecs);    \
+       } while ((_taken = nvkm_timer_wait_test(&_wait)) >= 0);                \
                                                                                \
-       if (_taken >= _nsecs) {                                                \
-               if (_warn)                                                     \
-                       dev_WARN(_device->dev, "timeout\n");                   \
-               _taken = -ETIMEDOUT;                                           \
-       }                                                                      \
+       if (_warn && _taken < 0)                                               \
+               dev_WARN(_wait.tmr->subdev.device->dev, "timeout\n");          \
        _taken;                                                                \
 })
 #define nvkm_usec(d,u,cond...) nvkm_nsec((d), (u) * 1000, ##cond)
index e67a471..b06cdac 100644 (file)
@@ -306,7 +306,7 @@ nouveau_abi16_ioctl_channel_alloc(ABI16_IOCTL_ARGS)
 
        /* create channel object and initialise dma and fence management */
        ret = nouveau_channel_new(drm, device, init->fb_ctxdma_handle,
-                                 init->tt_ctxdma_handle, &chan->chan);
+                                 init->tt_ctxdma_handle, false, &chan->chan);
        if (ret)
                goto done;
 
index 7214022..73eff52 100644 (file)
@@ -1141,6 +1141,8 @@ nouveau_bo_move_init(struct nouveau_drm *drm)
                            struct ttm_mem_reg *, struct ttm_mem_reg *);
                int (*init)(struct nouveau_channel *, u32 handle);
        } _methods[] = {
+               {  "COPY", 4, 0xc5b5, nve0_bo_move_copy, nve0_bo_move_init },
+               {  "GRCE", 0, 0xc5b5, nve0_bo_move_copy, nvc0_bo_move_init },
                {  "COPY", 4, 0xc3b5, nve0_bo_move_copy, nve0_bo_move_init },
                {  "GRCE", 0, 0xc3b5, nve0_bo_move_copy, nvc0_bo_move_init },
                {  "COPY", 4, 0xc1b5, nve0_bo_move_copy, nve0_bo_move_init },
index 92d3115..668afbc 100644 (file)
@@ -29,6 +29,7 @@
 #include <nvif/cl506f.h>
 #include <nvif/cl906f.h>
 #include <nvif/cla06f.h>
+#include <nvif/clc36f.h>
 #include <nvif/ioctl.h>
 
 /*XXX*/
@@ -217,10 +218,11 @@ nouveau_channel_prep(struct nouveau_drm *drm, struct nvif_device *device,
 
 static int
 nouveau_channel_ind(struct nouveau_drm *drm, struct nvif_device *device,
-                   u64 runlist, struct nouveau_channel **pchan)
+                   u64 runlist, bool priv, struct nouveau_channel **pchan)
 {
        struct nouveau_cli *cli = (void *)device->object.client;
-       static const u16 oclasses[] = { VOLTA_CHANNEL_GPFIFO_A,
+       static const u16 oclasses[] = { TURING_CHANNEL_GPFIFO_A,
+                                       VOLTA_CHANNEL_GPFIFO_A,
                                        PASCAL_CHANNEL_GPFIFO_A,
                                        MAXWELL_CHANNEL_GPFIFO_A,
                                        KEPLER_CHANNEL_GPFIFO_B,
@@ -234,6 +236,7 @@ nouveau_channel_ind(struct nouveau_drm *drm, struct nvif_device *device,
                struct nv50_channel_gpfifo_v0 nv50;
                struct fermi_channel_gpfifo_v0 fermi;
                struct kepler_channel_gpfifo_a_v0 kepler;
+               struct volta_channel_gpfifo_a_v0 volta;
        } args;
        struct nouveau_channel *chan;
        u32 size;
@@ -247,12 +250,22 @@ nouveau_channel_ind(struct nouveau_drm *drm, struct nvif_device *device,
 
        /* create channel object */
        do {
+               if (oclass[0] >= VOLTA_CHANNEL_GPFIFO_A) {
+                       args.volta.version = 0;
+                       args.volta.ilength = 0x02000;
+                       args.volta.ioffset = 0x10000 + chan->push.addr;
+                       args.volta.runlist = runlist;
+                       args.volta.vmm = nvif_handle(&cli->vmm.vmm.object);
+                       args.volta.priv = priv;
+                       size = sizeof(args.volta);
+               } else
                if (oclass[0] >= KEPLER_CHANNEL_GPFIFO_A) {
                        args.kepler.version = 0;
                        args.kepler.ilength = 0x02000;
                        args.kepler.ioffset = 0x10000 + chan->push.addr;
                        args.kepler.runlist = runlist;
                        args.kepler.vmm = nvif_handle(&cli->vmm.vmm.object);
+                       args.kepler.priv = priv;
                        size = sizeof(args.kepler);
                } else
                if (oclass[0] >= FERMI_CHANNEL_GPFIFO) {
@@ -273,13 +286,20 @@ nouveau_channel_ind(struct nouveau_drm *drm, struct nvif_device *device,
                ret = nvif_object_init(&device->object, 0, *oclass++,
                                       &args, size, &chan->user);
                if (ret == 0) {
-                       if (chan->user.oclass >= KEPLER_CHANNEL_GPFIFO_A)
+                       if (chan->user.oclass >= VOLTA_CHANNEL_GPFIFO_A) {
+                               chan->chid = args.volta.chid;
+                               chan->inst = args.volta.inst;
+                               chan->token = args.volta.token;
+                       } else
+                       if (chan->user.oclass >= KEPLER_CHANNEL_GPFIFO_A) {
                                chan->chid = args.kepler.chid;
-                       else
-                       if (chan->user.oclass >= FERMI_CHANNEL_GPFIFO)
+                               chan->inst = args.kepler.inst;
+                       } else
+                       if (chan->user.oclass >= FERMI_CHANNEL_GPFIFO) {
                                chan->chid = args.fermi.chid;
-                       else
+                       } else {
                                chan->chid = args.nv50.chid;
+                       }
                        return ret;
                }
        } while (*oclass);
@@ -448,7 +468,8 @@ nouveau_channel_init(struct nouveau_channel *chan, u32 vram, u32 gart)
 
 int
 nouveau_channel_new(struct nouveau_drm *drm, struct nvif_device *device,
-                   u32 arg0, u32 arg1, struct nouveau_channel **pchan)
+                   u32 arg0, u32 arg1, bool priv,
+                   struct nouveau_channel **pchan)
 {
        struct nouveau_cli *cli = (void *)device->object.client;
        bool super;
@@ -458,7 +479,7 @@ nouveau_channel_new(struct nouveau_drm *drm, struct nvif_device *device,
        super = cli->base.super;
        cli->base.super = true;
 
-       ret = nouveau_channel_ind(drm, device, arg0, pchan);
+       ret = nouveau_channel_ind(drm, device, arg0, priv, pchan);
        if (ret) {
                NV_PRINTK(dbg, cli, "ib channel create, %d\n", ret);
                ret = nouveau_channel_dma(drm, device, pchan);
index 64454c2..28418f4 100644 (file)
@@ -10,6 +10,8 @@ struct nouveau_channel {
        struct nouveau_drm *drm;
 
        int chid;
+       u64 inst;
+       u32 token;
 
        struct nvif_object vram;
        struct nvif_object gart;
@@ -48,7 +50,8 @@ struct nouveau_channel {
 int nouveau_channels_init(struct nouveau_drm *);
 
 int  nouveau_channel_new(struct nouveau_drm *, struct nvif_device *,
-                        u32 arg0, u32 arg1, struct nouveau_channel **);
+                        u32 arg0, u32 arg1, bool priv,
+                        struct nouveau_channel **);
 void nouveau_channel_del(struct nouveau_channel **);
 int  nouveau_channel_idle(struct nouveau_channel *);
 
index fd80661..3f463c9 100644 (file)
@@ -403,6 +403,7 @@ nouveau_connector_destroy(struct drm_connector *connector)
        if (nv_connector->aux.transfer) {
                drm_dp_cec_unregister_connector(&nv_connector->aux);
                drm_dp_aux_unregister(&nv_connector->aux);
+               kfree(nv_connector->aux.name);
        }
        kfree(connector);
 }
@@ -1218,7 +1219,8 @@ drm_conntype_from_dcb(enum dcb_connector_type dcb)
        case DCB_CONNECTOR_LVDS_SPWG: return DRM_MODE_CONNECTOR_LVDS;
        case DCB_CONNECTOR_DMS59_DP0:
        case DCB_CONNECTOR_DMS59_DP1:
-       case DCB_CONNECTOR_DP       : return DRM_MODE_CONNECTOR_DisplayPort;
+       case DCB_CONNECTOR_DP       :
+       case DCB_CONNECTOR_USB_C    : return DRM_MODE_CONNECTOR_DisplayPort;
        case DCB_CONNECTOR_eDP      : return DRM_MODE_CONNECTOR_eDP;
        case DCB_CONNECTOR_HDMI_0   :
        case DCB_CONNECTOR_HDMI_1   :
@@ -1232,7 +1234,8 @@ drm_conntype_from_dcb(enum dcb_connector_type dcb)
 }
 
 struct drm_connector *
-nouveau_connector_create(struct drm_device *dev, int index)
+nouveau_connector_create(struct drm_device *dev,
+                        const struct dcb_output *dcbe)
 {
        const struct drm_connector_funcs *funcs = &nouveau_connector_funcs;
        struct nouveau_drm *drm = nouveau_drm(dev);
@@ -1240,6 +1243,8 @@ nouveau_connector_create(struct drm_device *dev, int index)
        struct nouveau_connector *nv_connector = NULL;
        struct drm_connector *connector;
        struct drm_connector_list_iter conn_iter;
+       char aux_name[48] = {0};
+       int index = dcbe->connector;
        int type, ret = 0;
        bool dummy;
 
@@ -1342,6 +1347,9 @@ nouveau_connector_create(struct drm_device *dev, int index)
        case DRM_MODE_CONNECTOR_eDP:
                nv_connector->aux.dev = dev->dev;
                nv_connector->aux.transfer = nouveau_connector_aux_xfer;
+               snprintf(aux_name, sizeof(aux_name), "sor-%04x-%04x",
+                        dcbe->hasht, dcbe->hashm);
+               nv_connector->aux.name = kstrdup(aux_name, GFP_KERNEL);
                ret = drm_dp_aux_register(&nv_connector->aux);
                if (ret) {
                        NV_ERROR(drm, "failed to register aux channel\n");
index f57ef35..f43a8d6 100644 (file)
@@ -38,6 +38,7 @@
 #include "nouveau_encoder.h"
 
 struct nvkm_i2c_port;
+struct dcb_output;
 
 #ifdef CONFIG_DRM_NOUVEAU_BACKLIGHT
 struct nouveau_backlight;
@@ -113,7 +114,7 @@ nouveau_crtc_connector_get(struct nouveau_crtc *nv_crtc)
 }
 
 struct drm_connector *
-nouveau_connector_create(struct drm_device *, int index);
+nouveau_connector_create(struct drm_device *, const struct dcb_output *);
 
 extern int nouveau_tv_disable;
 extern int nouveau_ignorelid;
index 9109b69..88a52f6 100644 (file)
@@ -46,6 +46,26 @@ nouveau_debugfs_vbios_image(struct seq_file *m, void *data)
        return 0;
 }
 
+static int
+nouveau_debugfs_strap_peek(struct seq_file *m, void *data)
+{
+       struct drm_info_node *node = m->private;
+       struct nouveau_drm *drm = nouveau_drm(node->minor->dev);
+       int ret;
+
+       ret = pm_runtime_get_sync(drm->dev->dev);
+       if (ret < 0 && ret != -EACCES)
+               return ret;
+
+       seq_printf(m, "0x%08x\n",
+                  nvif_rd32(&drm->client.device.object, 0x101000));
+
+       pm_runtime_mark_last_busy(drm->dev->dev);
+       pm_runtime_put_autosuspend(drm->dev->dev);
+
+       return 0;
+}
+
 static int
 nouveau_debugfs_pstate_get(struct seq_file *m, void *data)
 {
@@ -185,7 +205,8 @@ static const struct file_operations nouveau_pstate_fops = {
 };
 
 static struct drm_info_list nouveau_debugfs_list[] = {
-       { "vbios.rom", nouveau_debugfs_vbios_image, 0, NULL },
+       { "vbios.rom",  nouveau_debugfs_vbios_image, 0, NULL },
+       { "strap_peek", nouveau_debugfs_strap_peek, 0, NULL },
 };
 #define NOUVEAU_DEBUGFS_ENTRIES ARRAY_SIZE(nouveau_debugfs_list)
 
@@ -199,8 +220,9 @@ static const struct nouveau_debugfs_files {
 int
 nouveau_drm_debugfs_init(struct drm_minor *minor)
 {
+       struct nouveau_drm *drm = nouveau_drm(minor->dev);
        struct dentry *dentry;
-       int i;
+       int i, ret;
 
        for (i = 0; i < ARRAY_SIZE(nouveau_debugfs_files); i++) {
                dentry = debugfs_create_file(nouveau_debugfs_files[i].name,
@@ -211,9 +233,23 @@ nouveau_drm_debugfs_init(struct drm_minor *minor)
                        return -ENOMEM;
        }
 
-       return drm_debugfs_create_files(nouveau_debugfs_list,
-                                       NOUVEAU_DEBUGFS_ENTRIES,
-                                       minor->debugfs_root, minor);
+       ret = drm_debugfs_create_files(nouveau_debugfs_list,
+                                      NOUVEAU_DEBUGFS_ENTRIES,
+                                      minor->debugfs_root, minor);
+       if (ret)
+               return ret;
+
+       /* Set the size of the vbios since we know it, and it's confusing to
+        * userspace if it wants to seek() but the file has a length of 0
+        */
+       dentry = debugfs_lookup("vbios.rom", minor->debugfs_root);
+       if (!dentry)
+               return 0;
+
+       d_inode(dentry)->i_size = drm->vbios.length;
+       dput(dentry);
+
+       return 0;
 }
 
 int
index 945afd3..078f65d 100644 (file)
@@ -101,7 +101,7 @@ nv50_dma_push(struct nouveau_channel *chan, u64 offset, int length)
 
        nvif_wr32(&chan->user, 0x8c, chan->dma.ib_put);
        if (user->func && user->func->doorbell)
-               user->func->doorbell(user, chan->chid);
+               user->func->doorbell(user, chan->token);
        chan->dma.ib_free--;
 }
 
index 2b2baf6..232c3f6 100644 (file)
@@ -353,6 +353,7 @@ nouveau_accel_init(struct nouveau_drm *drm)
                case MAXWELL_CHANNEL_GPFIFO_A:
                case PASCAL_CHANNEL_GPFIFO_A:
                case VOLTA_CHANNEL_GPFIFO_A:
+               case TURING_CHANNEL_GPFIFO_A:
                        ret = nvc0_fence_create(drm);
                        break;
                default:
@@ -370,7 +371,7 @@ nouveau_accel_init(struct nouveau_drm *drm)
        if (device->info.family >= NV_DEVICE_INFO_V0_KEPLER) {
                ret = nouveau_channel_new(drm, &drm->client.device,
                                          nvif_fifo_runlist_ce(device), 0,
-                                         &drm->cechan);
+                                         true, &drm->cechan);
                if (ret)
                        NV_ERROR(drm, "failed to create ce channel, %d\n", ret);
 
@@ -381,7 +382,8 @@ nouveau_accel_init(struct nouveau_drm *drm)
            device->info.chipset != 0xaa &&
            device->info.chipset != 0xac) {
                ret = nouveau_channel_new(drm, &drm->client.device,
-                                         NvDmaFB, NvDmaTT, &drm->cechan);
+                                         NvDmaFB, NvDmaTT, false,
+                                         &drm->cechan);
                if (ret)
                        NV_ERROR(drm, "failed to create ce channel, %d\n", ret);
 
@@ -393,7 +395,7 @@ nouveau_accel_init(struct nouveau_drm *drm)
        }
 
        ret = nouveau_channel_new(drm, &drm->client.device,
-                                 arg0, arg1, &drm->channel);
+                                 arg0, arg1, false, &drm->channel);
        if (ret) {
                NV_ERROR(drm, "failed to create kernel channel, %d\n", ret);
                nouveau_accel_fini(drm);
index 7e3b118..ede872f 100644 (file)
@@ -25,7 +25,6 @@ void nouveau_vma_unmap(struct nouveau_vma *);
 struct nouveau_vmm {
        struct nouveau_cli *cli;
        struct nvif_vmm vmm;
-       struct nvkm_vm *vm;
 };
 
 int nouveau_vmm_init(struct nouveau_cli *, s32 oclass, struct nouveau_vmm *);
index 18c7d06..ef97dd2 100644 (file)
@@ -34,6 +34,7 @@ int
 nvif_disp_ctor(struct nvif_device *device, s32 oclass, struct nvif_disp *disp)
 {
        static const struct nvif_mclass disps[] = {
+               { TU104_DISP, -1 },
                { GV100_DISP, -1 },
                { GP102_DISP, -1 },
                { GP100_DISP, -1 },
index 03f676c..c61b467 100644 (file)
@@ -79,7 +79,9 @@ nvkm_subdev_name[NVKM_SUBDEV_NR] = {
        [NVKM_ENGINE_NVENC0  ] = "nvenc0",
        [NVKM_ENGINE_NVENC1  ] = "nvenc1",
        [NVKM_ENGINE_NVENC2  ] = "nvenc2",
-       [NVKM_ENGINE_NVDEC   ] = "nvdec",
+       [NVKM_ENGINE_NVDEC0  ] = "nvdec0",
+       [NVKM_ENGINE_NVDEC1  ] = "nvdec1",
+       [NVKM_ENGINE_NVDEC2  ] = "nvdec2",
        [NVKM_ENGINE_PM      ] = "pm",
        [NVKM_ENGINE_SEC     ] = "sec",
        [NVKM_ENGINE_SEC2    ] = "sec2",
index 80d7844..177a233 100644 (file)
@@ -6,3 +6,4 @@ nvkm-y += nvkm/engine/ce/gm200.o
 nvkm-y += nvkm/engine/ce/gp100.o
 nvkm-y += nvkm/engine/ce/gp102.o
 nvkm-y += nvkm/engine/ce/gv100.o
+nvkm-y += nvkm/engine/ce/tu104.o
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/ce/tu104.c b/drivers/gpu/drm/nouveau/nvkm/engine/ce/tu104.c
new file mode 100644 (file)
index 0000000..3c25043
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * 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 "priv.h"
+
+#include <nvif/class.h>
+
+static const struct nvkm_engine_func
+tu104_ce = {
+       .intr = gp100_ce_intr,
+       .sclass = {
+               { -1, -1, TURING_DMA_COPY_A },
+               {}
+       }
+};
+
+int
+tu104_ce_new(struct nvkm_device *device, int index,
+            struct nvkm_engine **pengine)
+{
+       return nvkm_engine_new_(&tu104_ce, device, index, true, pengine);
+}
index e294013..bfbc934 100644 (file)
@@ -2221,7 +2221,7 @@ nv132_chipset = {
        .dma = gf119_dma_new,
        .fifo = gp100_fifo_new,
        .gr = gp102_gr_new,
-       .nvdec = gp102_nvdec_new,
+       .nvdec[0] = gp102_nvdec_new,
        .sec2 = gp102_sec2_new,
        .sw = gf100_sw_new,
 };
@@ -2257,7 +2257,7 @@ nv134_chipset = {
        .dma = gf119_dma_new,
        .fifo = gp100_fifo_new,
        .gr = gp104_gr_new,
-       .nvdec = gp102_nvdec_new,
+       .nvdec[0] = gp102_nvdec_new,
        .sec2 = gp102_sec2_new,
        .sw = gf100_sw_new,
 };
@@ -2293,7 +2293,7 @@ nv136_chipset = {
        .dma = gf119_dma_new,
        .fifo = gp100_fifo_new,
        .gr = gp104_gr_new,
-       .nvdec = gp102_nvdec_new,
+       .nvdec[0] = gp102_nvdec_new,
        .sec2 = gp102_sec2_new,
        .sw = gf100_sw_new,
 };
@@ -2329,7 +2329,7 @@ nv137_chipset = {
        .dma = gf119_dma_new,
        .fifo = gp100_fifo_new,
        .gr = gp107_gr_new,
-       .nvdec = gp102_nvdec_new,
+       .nvdec[0] = gp102_nvdec_new,
        .sec2 = gp102_sec2_new,
        .sw = gf100_sw_new,
 };
@@ -2365,7 +2365,7 @@ nv138_chipset = {
        .dma = gf119_dma_new,
        .fifo = gp100_fifo_new,
        .gr = gp107_gr_new,
-       .nvdec = gp102_nvdec_new,
+       .nvdec[0] = gp102_nvdec_new,
        .sec2 = gp102_sec2_new,
        .sw = gf100_sw_new,
 };
@@ -2430,10 +2430,74 @@ nv140_chipset = {
        .dma = gv100_dma_new,
        .fifo = gv100_fifo_new,
        .gr = gv100_gr_new,
-       .nvdec = gp102_nvdec_new,
+       .nvdec[0] = gp102_nvdec_new,
        .sec2 = gp102_sec2_new,
 };
 
+static const struct nvkm_device_chip
+nv164_chipset = {
+       .name = "TU104",
+       .bar = tu104_bar_new,
+       .bios = nvkm_bios_new,
+       .bus = gf100_bus_new,
+       .devinit = tu104_devinit_new,
+       .fault = tu104_fault_new,
+       .fb = gv100_fb_new,
+       .fuse = gm107_fuse_new,
+       .gpio = gk104_gpio_new,
+       .i2c = gm200_i2c_new,
+       .ibus = gm200_ibus_new,
+       .imem = nv50_instmem_new,
+       .ltc = gp102_ltc_new,
+       .mc = tu104_mc_new,
+       .mmu = tu104_mmu_new,
+       .pci = gp100_pci_new,
+       .pmu = gp102_pmu_new,
+       .therm = gp100_therm_new,
+       .timer = gk20a_timer_new,
+       .top = gk104_top_new,
+       .ce[0] = tu104_ce_new,
+       .ce[1] = tu104_ce_new,
+       .ce[2] = tu104_ce_new,
+       .ce[3] = tu104_ce_new,
+       .ce[4] = tu104_ce_new,
+       .disp = tu104_disp_new,
+       .dma = gv100_dma_new,
+       .fifo = tu104_fifo_new,
+};
+
+static const struct nvkm_device_chip
+nv166_chipset = {
+       .name = "TU106",
+       .bar = tu104_bar_new,
+       .bios = nvkm_bios_new,
+       .bus = gf100_bus_new,
+       .devinit = tu104_devinit_new,
+       .fault = tu104_fault_new,
+       .fb = gv100_fb_new,
+       .fuse = gm107_fuse_new,
+       .gpio = gk104_gpio_new,
+       .i2c = gm200_i2c_new,
+       .ibus = gm200_ibus_new,
+       .imem = nv50_instmem_new,
+       .ltc = gp102_ltc_new,
+       .mc = tu104_mc_new,
+       .mmu = tu104_mmu_new,
+       .pci = gp100_pci_new,
+       .pmu = gp102_pmu_new,
+       .therm = gp100_therm_new,
+       .timer = gk20a_timer_new,
+       .top = gk104_top_new,
+       .ce[0] = tu104_ce_new,
+       .ce[1] = tu104_ce_new,
+       .ce[2] = tu104_ce_new,
+       .ce[3] = tu104_ce_new,
+       .ce[4] = tu104_ce_new,
+       .disp = tu104_disp_new,
+       .dma = gv100_dma_new,
+       .fifo = tu104_fifo_new,
+};
+
 static int
 nvkm_device_event_ctor(struct nvkm_object *object, void *data, u32 size,
                       struct nvkm_notify *notify)
@@ -2529,7 +2593,9 @@ nvkm_device_engine(struct nvkm_device *device, int index)
        _(NVENC0 , device->nvenc[0],  device->nvenc[0]);
        _(NVENC1 , device->nvenc[1],  device->nvenc[1]);
        _(NVENC2 , device->nvenc[2],  device->nvenc[2]);
-       _(NVDEC  , device->nvdec   , &device->nvdec->engine);
+       _(NVDEC0 , device->nvdec[0], &device->nvdec[0]->engine);
+       _(NVDEC1 , device->nvdec[1], &device->nvdec[1]->engine);
+       _(NVDEC2 , device->nvdec[2], &device->nvdec[2]->engine);
        _(PM     , device->pm      , &device->pm->engine);
        _(SEC    , device->sec     ,  device->sec);
        _(SEC2   , device->sec2    , &device->sec2->engine);
@@ -2791,6 +2857,7 @@ nvkm_device_ctor(const struct nvkm_device_func *func,
                        case 0x120: device->card_type = GM100; break;
                        case 0x130: device->card_type = GP100; break;
                        case 0x140: device->card_type = GV100; break;
+                       case 0x160: device->card_type = TU100; break;
                        default:
                                break;
                        }
@@ -2883,6 +2950,8 @@ nvkm_device_ctor(const struct nvkm_device_func *func,
                case 0x138: device->chip = &nv138_chipset; break;
                case 0x13b: device->chip = &nv13b_chipset; break;
                case 0x140: device->chip = &nv140_chipset; break;
+               case 0x164: device->chip = &nv164_chipset; break;
+               case 0x166: device->chip = &nv166_chipset; break;
                default:
                        nvdev_error(device, "unknown chipset (%08x)\n", boot0);
                        goto done;
@@ -2988,7 +3057,9 @@ nvkm_device_ctor(const struct nvkm_device_func *func,
                _(NVKM_ENGINE_NVENC0  , nvenc[0]);
                _(NVKM_ENGINE_NVENC1  , nvenc[1]);
                _(NVKM_ENGINE_NVENC2  , nvenc[2]);
-               _(NVKM_ENGINE_NVDEC   ,    nvdec);
+               _(NVKM_ENGINE_NVDEC0  , nvdec[0]);
+               _(NVKM_ENGINE_NVDEC1  , nvdec[1]);
+               _(NVKM_ENGINE_NVDEC2  , nvdec[2]);
                _(NVKM_ENGINE_PM      ,       pm);
                _(NVKM_ENGINE_SEC     ,      sec);
                _(NVKM_ENGINE_SEC2    ,     sec2);
index dde6bba..092ddc4 100644 (file)
@@ -91,7 +91,7 @@ nvkm_udevice_info_v1(struct nvkm_device *device,
        case ENGINE_A(MSENC ); break;
        case ENGINE_A(VIC   ); break;
        case ENGINE_A(SEC2  ); break;
-       case ENGINE_A(NVDEC ); break;
+       case ENGINE_B(NVDEC ); break;
        case ENGINE_B(NVENC ); break;
        default:
                args->mthd = NV_DEVICE_INFO_INVALID;
@@ -175,6 +175,7 @@ nvkm_udevice_info(struct nvkm_udevice *udev, void *data, u32 size)
        case GM100: args->v0.family = NV_DEVICE_INFO_V0_MAXWELL; break;
        case GP100: args->v0.family = NV_DEVICE_INFO_V0_PASCAL; break;
        case GV100: args->v0.family = NV_DEVICE_INFO_V0_VOLTA; break;
+       case TU100: args->v0.family = NV_DEVICE_INFO_V0_TURING; break;
        default:
                args->v0.family = 0;
                break;
index 8089ac9..c6a257b 100644 (file)
@@ -15,6 +15,7 @@ nvkm-y += nvkm/engine/disp/gm200.o
 nvkm-y += nvkm/engine/disp/gp100.o
 nvkm-y += nvkm/engine/disp/gp102.o
 nvkm-y += nvkm/engine/disp/gv100.o
+nvkm-y += nvkm/engine/disp/tu104.o
 nvkm-y += nvkm/engine/disp/vga.o
 
 nvkm-y += nvkm/engine/disp/head.o
@@ -38,6 +39,7 @@ nvkm-y += nvkm/engine/disp/sorgk104.o
 nvkm-y += nvkm/engine/disp/sorgm107.o
 nvkm-y += nvkm/engine/disp/sorgm200.o
 nvkm-y += nvkm/engine/disp/sorgv100.o
+nvkm-y += nvkm/engine/disp/sortu104.o
 
 nvkm-y += nvkm/engine/disp/outp.o
 nvkm-y += nvkm/engine/disp/dp.o
@@ -69,6 +71,7 @@ nvkm-y += nvkm/engine/disp/rootgm200.o
 nvkm-y += nvkm/engine/disp/rootgp100.o
 nvkm-y += nvkm/engine/disp/rootgp102.o
 nvkm-y += nvkm/engine/disp/rootgv100.o
+nvkm-y += nvkm/engine/disp/roottu104.o
 
 nvkm-y += nvkm/engine/disp/channv50.o
 nvkm-y += nvkm/engine/disp/changf119.o
index d0a7e34..47be0ba 100644 (file)
@@ -28,7 +28,7 @@
 #include <core/gpuobj.h>
 #include <subdev/timer.h>
 
-static int
+int
 gv100_disp_wndw_cnt(struct nvkm_disp *disp, unsigned long *pmask)
 {
        struct nvkm_device *device = disp->engine.subdev.device;
@@ -36,7 +36,7 @@ gv100_disp_wndw_cnt(struct nvkm_disp *disp, unsigned long *pmask)
        return (nvkm_rd32(device, 0x610074) & 0x03f00000) >> 20;
 }
 
-static void
+void
 gv100_disp_super(struct work_struct *work)
 {
        struct nv50_disp *disp =
@@ -257,7 +257,7 @@ gv100_disp_intr_head_timing(struct nv50_disp *disp, int head)
        }
 }
 
-static void
+void
 gv100_disp_intr(struct nv50_disp *disp)
 {
        struct nvkm_subdev *subdev = &disp->base.engine.subdev;
@@ -297,7 +297,7 @@ gv100_disp_intr(struct nv50_disp *disp)
                nvkm_warn(subdev, "intr %08x\n", stat);
 }
 
-static void
+void
 gv100_disp_fini(struct nv50_disp *disp)
 {
        struct nvkm_device *device = disp->base.engine.subdev.device;
index 0f0c86c..790e42f 100644 (file)
@@ -144,6 +144,11 @@ void gm200_sor_route_set(struct nvkm_outp *, struct nvkm_ior *);
 int gm200_sor_route_get(struct nvkm_outp *, int *);
 void gm200_sor_dp_drive(struct nvkm_ior *, int, int, int, int, int);
 
+void gv100_sor_state(struct nvkm_ior *, struct nvkm_ior_state *);
+void gv100_sor_dp_audio(struct nvkm_ior *, int, bool);
+void gv100_sor_dp_audio_sym(struct nvkm_ior *, int, u16, u32);
+void gv100_sor_dp_watermark(struct nvkm_ior *, int, u8);
+
 void g84_hdmi_ctrl(struct nvkm_ior *, int, bool, u8, u8, u8 *, u8 , u8 *, u8);
 void gt215_hdmi_ctrl(struct nvkm_ior *, int, bool, u8, u8, u8 *, u8 , u8 *, u8);
 void gf119_hdmi_ctrl(struct nvkm_ior *, int, bool, u8, u8, u8 *, u8 , u8 *, u8);
@@ -195,4 +200,6 @@ int gm200_sor_new(struct nvkm_disp *, int);
 
 int gv100_sor_cnt(struct nvkm_disp *, unsigned long *);
 int gv100_sor_new(struct nvkm_disp *, int);
+
+int tu104_sor_new(struct nvkm_disp *, int);
 #endif
index 8580382..c36a8a7 100644 (file)
@@ -78,6 +78,11 @@ void gf119_disp_intr(struct nv50_disp *);
 void gf119_disp_super(struct work_struct *);
 void gf119_disp_intr_error(struct nv50_disp *, int);
 
+void gv100_disp_fini(struct nv50_disp *);
+void gv100_disp_intr(struct nv50_disp *);
+void gv100_disp_super(struct work_struct *);
+int gv100_disp_wndw_cnt(struct nvkm_disp *, unsigned long *);
+
 void nv50_disp_dptmds_war_2(struct nv50_disp *, struct dcb_output *);
 void nv50_disp_dptmds_war_3(struct nv50_disp *, struct dcb_output *);
 void nv50_disp_update_sppll1(struct nv50_disp *);
index 6ca4f91..97de928 100644 (file)
@@ -37,4 +37,5 @@ extern const struct nvkm_disp_oclass gm200_disp_root_oclass;
 extern const struct nvkm_disp_oclass gp100_disp_root_oclass;
 extern const struct nvkm_disp_oclass gp102_disp_root_oclass;
 extern const struct nvkm_disp_oclass gv100_disp_root_oclass;
+extern const struct nvkm_disp_oclass tu104_disp_root_oclass;
 #endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/roottu104.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/roottu104.c
new file mode 100644 (file)
index 0000000..ad438c6
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * 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 "rootnv50.h"
+#include "channv50.h"
+
+#include <nvif/class.h>
+
+static const struct nv50_disp_root_func
+tu104_disp_root = {
+       .user = {
+               {{0,0,TU104_DISP_CURSOR                }, gv100_disp_curs_new },
+               {{0,0,TU104_DISP_WINDOW_IMM_CHANNEL_DMA}, gv100_disp_wimm_new },
+               {{0,0,TU104_DISP_CORE_CHANNEL_DMA      }, gv100_disp_core_new },
+               {{0,0,TU104_DISP_WINDOW_CHANNEL_DMA    }, gv100_disp_wndw_new },
+               {}
+       },
+};
+
+static int
+tu104_disp_root_new(struct nvkm_disp *disp, const struct nvkm_oclass *oclass,
+                   void *data, u32 size, struct nvkm_object **pobject)
+{
+       return nv50_disp_root_new_(&tu104_disp_root, disp, oclass,
+                                  data, size, pobject);
+}
+
+const struct nvkm_disp_oclass
+tu104_disp_root_oclass = {
+       .base.oclass = TU104_DISP,
+       .base.minver = -1,
+       .base.maxver = -1,
+       .ctor = tu104_disp_root_new,
+};
index 8ba881a..b0597ff 100644 (file)
@@ -23,7 +23,7 @@
 
 #include <subdev/timer.h>
 
-static void
+void
 gv100_sor_dp_watermark(struct nvkm_ior *sor, int head, u8 watermark)
 {
        struct nvkm_device *device = sor->disp->engine.subdev.device;
@@ -31,7 +31,7 @@ gv100_sor_dp_watermark(struct nvkm_ior *sor, int head, u8 watermark)
        nvkm_mask(device, 0x616550 + hoff, 0x0c00003f, 0x08000000 | watermark);
 }
 
-static void
+void
 gv100_sor_dp_audio_sym(struct nvkm_ior *sor, int head, u16 h, u32 v)
 {
        struct nvkm_device *device = sor->disp->engine.subdev.device;
@@ -40,7 +40,7 @@ gv100_sor_dp_audio_sym(struct nvkm_ior *sor, int head, u16 h, u32 v)
        nvkm_mask(device, 0x61656c + hoff, 0x00ffffff, v);
 }
 
-static void
+void
 gv100_sor_dp_audio(struct nvkm_ior *sor, int head, bool enable)
 {
        struct nvkm_device *device = sor->disp->engine.subdev.device;
@@ -54,7 +54,7 @@ gv100_sor_dp_audio(struct nvkm_ior *sor, int head, bool enable)
        );
 }
 
-static void
+void
 gv100_sor_state(struct nvkm_ior *sor, struct nvkm_ior_state *state)
 {
        struct nvkm_device *device = sor->disp->engine.subdev.device;
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sortu104.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sortu104.c
new file mode 100644 (file)
index 0000000..df026a5
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * 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 "ior.h"
+
+#include <subdev/timer.h>
+
+static void
+tu104_sor_dp_vcpi(struct nvkm_ior *sor, int head,
+                 u8 slot, u8 slot_nr, u16 pbn, u16 aligned)
+{
+       struct nvkm_device *device = sor->disp->engine.subdev.device;
+       const u32 hoff = head * 0x800;
+
+       nvkm_mask(device, 0x61657c + hoff, 0xffffffff, (aligned << 16) | pbn);
+       nvkm_mask(device, 0x616578 + hoff, 0x00003f3f, (slot_nr << 8) | slot);
+}
+
+static int
+tu104_sor_dp_links(struct nvkm_ior *sor, struct nvkm_i2c_aux *aux)
+{
+       struct nvkm_device *device = sor->disp->engine.subdev.device;
+       const u32 soff = nv50_ior_base(sor);
+       const u32 loff = nv50_sor_link(sor);
+       u32 dpctrl = 0x00000000;
+       u32 clksor = 0x00000000;
+
+       clksor |= sor->dp.bw << 18;
+       dpctrl |= ((1 << sor->dp.nr) - 1) << 16;
+       if (sor->dp.mst)
+               dpctrl |= 0x40000000;
+       if (sor->dp.ef)
+               dpctrl |= 0x00004000;
+
+       nvkm_mask(device, 0x612300 + soff, 0x007c0000, clksor);
+
+       /*XXX*/
+       nvkm_msec(device, 40, NVKM_DELAY);
+       nvkm_mask(device, 0x612300 + soff, 0x00030000, 0x00010000);
+       nvkm_mask(device, 0x61c10c + loff, 0x00000003, 0x00000001);
+
+       nvkm_mask(device, 0x61c10c + loff, 0x401f4000, dpctrl);
+       return 0;
+}
+
+static const struct nvkm_ior_func
+tu104_sor = {
+       .route = {
+               .get = gm200_sor_route_get,
+               .set = gm200_sor_route_set,
+       },
+       .state = gv100_sor_state,
+       .power = nv50_sor_power,
+       .clock = gf119_sor_clock,
+       .hdmi = {
+               .ctrl = gv100_hdmi_ctrl,
+       },
+       .dp = {
+               .lanes = { 0, 1, 2, 3 },
+               .links = tu104_sor_dp_links,
+               .power = g94_sor_dp_power,
+               .pattern = gm107_sor_dp_pattern,
+               .drive = gm200_sor_dp_drive,
+               .vcpi = tu104_sor_dp_vcpi,
+               .audio = gv100_sor_dp_audio,
+               .audio_sym = gv100_sor_dp_audio_sym,
+               .watermark = gv100_sor_dp_watermark,
+       },
+       .hda = {
+               .hpd = gf119_hda_hpd,
+               .eld = gf119_hda_eld,
+       },
+};
+
+int
+tu104_sor_new(struct nvkm_disp *disp, int id)
+{
+       return nvkm_ior_new_(&tu104_sor, disp, SOR, id);
+}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/tu104.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/tu104.c
new file mode 100644 (file)
index 0000000..13fa214
--- /dev/null
@@ -0,0 +1,152 @@
+/*
+ * 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 "nv50.h"
+#include "head.h"
+#include "ior.h"
+#include "channv50.h"
+#include "rootnv50.h"
+
+#include <core/gpuobj.h>
+#include <subdev/timer.h>
+
+static int
+tu104_disp_init(struct nv50_disp *disp)
+{
+       struct nvkm_device *device = disp->base.engine.subdev.device;
+       struct nvkm_head *head;
+       int i, j;
+       u32 tmp;
+
+       /* Claim ownership of display. */
+       if (nvkm_rd32(device, 0x6254e8) & 0x00000002) {
+               nvkm_mask(device, 0x6254e8, 0x00000001, 0x00000000);
+               if (nvkm_msec(device, 2000,
+                       if (!(nvkm_rd32(device, 0x6254e8) & 0x00000002))
+                               break;
+               ) < 0)
+                       return -EBUSY;
+       }
+
+       /* Lock pin capabilities. */
+       tmp = 0x00000021; /*XXX*/
+       nvkm_wr32(device, 0x640008, tmp);
+
+       /* SOR capabilities. */
+       for (i = 0; i < disp->sor.nr; i++) {
+               tmp = nvkm_rd32(device, 0x61c000 + (i * 0x800));
+               nvkm_mask(device, 0x640000, 0x00000100 << i, 0x00000100 << i);
+               nvkm_wr32(device, 0x640144 + (i * 0x08), tmp);
+       }
+
+       /* Head capabilities. */
+       list_for_each_entry(head, &disp->base.head, head) {
+               const int id = head->id;
+
+               /* RG. */
+               tmp = nvkm_rd32(device, 0x616300 + (id * 0x800));
+               nvkm_wr32(device, 0x640048 + (id * 0x020), tmp);
+
+               /* POSTCOMP. */
+               for (j = 0; j < 5 * 4; j += 4) {
+                       tmp = nvkm_rd32(device, 0x616140 + (id * 0x800) + j);
+                       nvkm_wr32(device, 0x640680 + (id * 0x20) + j, tmp);
+               }
+       }
+
+       /* Window capabilities. */
+       for (i = 0; i < disp->wndw.nr; i++) {
+               nvkm_mask(device, 0x640004, 1 << i, 1 << i);
+               for (j = 0; j < 6 * 4; j += 4) {
+                       tmp = nvkm_rd32(device, 0x630100 + (i * 0x800) + j);
+                       nvkm_mask(device, 0x640780 + (i * 0x20) + j, 0xffffffff, tmp);
+               }
+               nvkm_mask(device, 0x64000c, 0x00000100, 0x00000100);
+       }
+
+       /* IHUB capabilities. */
+       for (i = 0; i < 3; i++) {
+               tmp = nvkm_rd32(device, 0x62e000 + (i * 0x04));
+               nvkm_wr32(device, 0x640010 + (i * 0x04), tmp);
+       }
+
+       nvkm_mask(device, 0x610078, 0x00000001, 0x00000001);
+
+       /* Setup instance memory. */
+       switch (nvkm_memory_target(disp->inst->memory)) {
+       case NVKM_MEM_TARGET_VRAM: tmp = 0x00000001; break;
+       case NVKM_MEM_TARGET_NCOH: tmp = 0x00000002; break;
+       case NVKM_MEM_TARGET_HOST: tmp = 0x00000003; break;
+       default:
+               break;
+       }
+       nvkm_wr32(device, 0x610010, 0x00000008 | tmp);
+       nvkm_wr32(device, 0x610014, disp->inst->addr >> 16);
+
+       /* CTRL_DISP: AWAKEN, ERROR, SUPERVISOR[1-3]. */
+       nvkm_wr32(device, 0x611cf0, 0x00000187); /* MSK. */
+       nvkm_wr32(device, 0x611db0, 0x00000187); /* EN. */
+
+       /* EXC_OTHER: CURSn, CORE. */
+       nvkm_wr32(device, 0x611cec, disp->head.mask << 16 |
+                                   0x00000001); /* MSK. */
+       nvkm_wr32(device, 0x611dac, 0x00000000); /* EN. */
+
+       /* EXC_WINIM. */
+       nvkm_wr32(device, 0x611ce8, disp->wndw.mask); /* MSK. */
+       nvkm_wr32(device, 0x611da8, 0x00000000); /* EN. */
+
+       /* EXC_WIN. */
+       nvkm_wr32(device, 0x611ce4, disp->wndw.mask); /* MSK. */
+       nvkm_wr32(device, 0x611da4, 0x00000000); /* EN. */
+
+       /* HEAD_TIMING(n): VBLANK. */
+       list_for_each_entry(head, &disp->base.head, head) {
+               const u32 hoff = head->id * 4;
+               nvkm_wr32(device, 0x611cc0 + hoff, 0x00000004); /* MSK. */
+               nvkm_wr32(device, 0x611d80 + hoff, 0x00000000); /* EN. */
+       }
+
+       /* OR. */
+       nvkm_wr32(device, 0x611cf4, 0x00000000); /* MSK. */
+       nvkm_wr32(device, 0x611db4, 0x00000000); /* EN. */
+       return 0;
+}
+
+static const struct nv50_disp_func
+tu104_disp = {
+       .init = tu104_disp_init,
+       .fini = gv100_disp_fini,
+       .intr = gv100_disp_intr,
+       .uevent = &gv100_disp_chan_uevent,
+       .super = gv100_disp_super,
+       .root = &tu104_disp_root_oclass,
+       .wndw = { .cnt = gv100_disp_wndw_cnt },
+       .head = { .cnt = gv100_head_cnt, .new = gv100_head_new },
+       .sor = { .cnt = gv100_sor_cnt, .new = tu104_sor_new },
+       .ramht_size = 0x2000,
+};
+
+int
+tu104_disp_new(struct nvkm_device *device, int index, struct nvkm_disp **pdisp)
+{
+       return nv50_disp_new_(&tu104_disp, device, index, pdisp);
+}
index 9891180..5d3b641 100644 (file)
@@ -118,7 +118,7 @@ gv100_disp_wndw_mthd_base = {
 
 const struct nv50_disp_chan_mthd
 gv100_disp_wndw_mthd = {
-       .name = "Base",
+       .name = "Window",
        .addr = 0x001000,
        .prev = 0x000800,
        .data = {
index f004085..87d8e05 100644 (file)
@@ -16,6 +16,7 @@ nvkm-y += nvkm/engine/fifo/gm20b.o
 nvkm-y += nvkm/engine/fifo/gp100.o
 nvkm-y += nvkm/engine/fifo/gp10b.o
 nvkm-y += nvkm/engine/fifo/gv100.o
+nvkm-y += nvkm/engine/fifo/tu104.o
 
 nvkm-y += nvkm/engine/fifo/chan.o
 nvkm-y += nvkm/engine/fifo/channv50.o
@@ -33,5 +34,7 @@ nvkm-y += nvkm/engine/fifo/gpfifog84.o
 nvkm-y += nvkm/engine/fifo/gpfifogf100.o
 nvkm-y += nvkm/engine/fifo/gpfifogk104.o
 nvkm-y += nvkm/engine/fifo/gpfifogv100.o
+nvkm-y += nvkm/engine/fifo/gpfifotu104.o
 
 nvkm-y += nvkm/engine/fifo/usergv100.o
+nvkm-y += nvkm/engine/fifo/usertu104.o
index 3ffef23..2c7c5af 100644 (file)
@@ -17,6 +17,7 @@ struct nvkm_fifo_chan_func {
                            bool suspend);
        int  (*object_ctor)(struct nvkm_fifo_chan *, struct nvkm_object *);
        void (*object_dtor)(struct nvkm_fifo_chan *, int);
+       u32 (*submit_token)(struct nvkm_fifo_chan *);
 };
 
 int nvkm_fifo_chan_ctor(const struct nvkm_fifo_chan_func *, struct nvkm_fifo *,
index 8e28ba6..a14545d 100644 (file)
@@ -14,6 +14,8 @@ struct gk104_fifo_chan {
        struct list_head head;
        bool killed;
 
+       struct nvkm_memory *mthd;
+
        struct {
                struct nvkm_gpuobj *inst;
                struct nvkm_vma *vma;
@@ -36,4 +38,15 @@ int gk104_fifo_gpfifo_kick_locked(struct gk104_fifo_chan *);
 
 int gv100_fifo_gpfifo_new(struct gk104_fifo *, const struct nvkm_oclass *,
                          void *data, u32 size, struct nvkm_object **);
+int gv100_fifo_gpfifo_new_(const struct nvkm_fifo_chan_func *,
+                          struct gk104_fifo *, u64 *, u16 *, u64, u64, u64,
+                          u64 *, bool, u32 *, const struct nvkm_oclass *,
+                          struct nvkm_object **);
+int gv100_fifo_gpfifo_engine_init(struct nvkm_fifo_chan *,
+                                 struct nvkm_engine *);
+int gv100_fifo_gpfifo_engine_fini(struct nvkm_fifo_chan *,
+                                 struct nvkm_engine *, bool);
+
+int tu104_fifo_gpfifo_new(struct gk104_fifo *, const struct nvkm_oclass *,
+                         void *data, u32 size, struct nvkm_object **);
 #endif
index f695768..10a2e70 100644 (file)
@@ -346,10 +346,10 @@ gf100_fifo_intr_fault(struct gf100_fifo *fifo, int unit)
        if (eu && eu->data2) {
                switch (eu->data2) {
                case NVKM_SUBDEV_BAR:
-                       nvkm_mask(device, 0x001704, 0x00000000, 0x00000000);
+                       nvkm_bar_bar1_reset(device);
                        break;
                case NVKM_SUBDEV_INSTMEM:
-                       nvkm_mask(device, 0x001714, 0x00000000, 0x00000000);
+                       nvkm_bar_bar2_reset(device);
                        break;
                case NVKM_ENGINE_IFB:
                        nvkm_mask(device, 0x001718, 0x00000000, 0x00000000);
index afccf97..1053fe7 100644 (file)
@@ -149,16 +149,41 @@ gk104_fifo_uevent_init(struct nvkm_fifo *fifo)
 }
 
 void
-gk104_fifo_runlist_commit(struct gk104_fifo *fifo, int runl)
+gk104_fifo_runlist_commit(struct gk104_fifo *fifo, int runl,
+                         struct nvkm_memory *mem, int nr)
+{
+       struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
+       struct nvkm_device *device = subdev->device;
+       int target;
+
+       switch (nvkm_memory_target(mem)) {
+       case NVKM_MEM_TARGET_VRAM: target = 0; break;
+       case NVKM_MEM_TARGET_NCOH: target = 3; break;
+       default:
+               WARN_ON(1);
+               return;
+       }
+
+       nvkm_wr32(device, 0x002270, (nvkm_memory_addr(mem) >> 12) |
+                                   (target << 28));
+       nvkm_wr32(device, 0x002274, (runl << 20) | nr);
+
+       if (nvkm_msec(device, 2000,
+               if (!(nvkm_rd32(device, 0x002284 + (runl * 0x08)) & 0x00100000))
+                       break;
+       ) < 0)
+               nvkm_error(subdev, "runlist %d update timeout\n", runl);
+}
+
+void
+gk104_fifo_runlist_update(struct gk104_fifo *fifo, int runl)
 {
        const struct gk104_fifo_runlist_func *func = fifo->func->runlist;
        struct gk104_fifo_chan *chan;
        struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
-       struct nvkm_device *device = subdev->device;
        struct nvkm_memory *mem;
        struct nvkm_fifo_cgrp *cgrp;
        int nr = 0;
-       int target;
 
        mutex_lock(&subdev->mutex);
        mem = fifo->runlist[runl].mem[fifo->runlist[runl].next];
@@ -177,24 +202,7 @@ gk104_fifo_runlist_commit(struct gk104_fifo *fifo, int runl)
        }
        nvkm_done(mem);
 
-       switch (nvkm_memory_target(mem)) {
-       case NVKM_MEM_TARGET_VRAM: target = 0; break;
-       case NVKM_MEM_TARGET_NCOH: target = 3; break;
-       default:
-               WARN_ON(1);
-               goto unlock;
-       }
-
-       nvkm_wr32(device, 0x002270, (nvkm_memory_addr(mem) >> 12) |
-                                   (target << 28));
-       nvkm_wr32(device, 0x002274, (runl << 20) | nr);
-
-       if (nvkm_msec(device, 2000,
-               if (!(nvkm_rd32(device, 0x002284 + (runl * 0x08)) & 0x00100000))
-                       break;
-       ) < 0)
-               nvkm_error(subdev, "runlist %d update timeout\n", runl);
-unlock:
+       func->commit(fifo, runl, mem, nr);
        mutex_unlock(&subdev->mutex);
 }
 
@@ -238,6 +246,29 @@ const struct gk104_fifo_runlist_func
 gk104_fifo_runlist = {
        .size = 8,
        .chan = gk104_fifo_runlist_chan,
+       .commit = gk104_fifo_runlist_commit,
+};
+
+void
+gk104_fifo_pbdma_init(struct gk104_fifo *fifo)
+{
+       struct nvkm_device *device = fifo->base.engine.subdev.device;
+       nvkm_wr32(device, 0x000204, (1 << fifo->pbdma_nr) - 1);
+}
+
+int
+gk104_fifo_pbdma_nr(struct gk104_fifo *fifo)
+{
+       struct nvkm_device *device = fifo->base.engine.subdev.device;
+       /* Determine number of PBDMAs by checking valid enable bits. */
+       nvkm_wr32(device, 0x000204, 0xffffffff);
+       return hweight32(nvkm_rd32(device, 0x000204));
+}
+
+const struct gk104_fifo_pbdma_func
+gk104_fifo_pbdma = {
+       .nr = gk104_fifo_pbdma_nr,
+       .init = gk104_fifo_pbdma_init,
 };
 
 static void
@@ -267,7 +298,7 @@ gk104_fifo_recover_work(struct work_struct *w)
        }
 
        for (todo = runm; runl = __ffs(todo), todo; todo &= ~BIT(runl))
-               gk104_fifo_runlist_commit(fifo, runl);
+               gk104_fifo_runlist_update(fifo, runl);
 
        nvkm_wr32(device, 0x00262c, runm);
        nvkm_mask(device, 0x002630, runm, 0x00000000);
@@ -456,10 +487,10 @@ gk104_fifo_fault(struct nvkm_fifo *base, struct nvkm_fault_data *info)
        if (ee && ee->data2) {
                switch (ee->data2) {
                case NVKM_SUBDEV_BAR:
-                       nvkm_mask(device, 0x001704, 0x00000000, 0x00000000);
+                       nvkm_bar_bar1_reset(device);
                        break;
                case NVKM_SUBDEV_INSTMEM:
-                       nvkm_mask(device, 0x001714, 0x00000000, 0x00000000);
+                       nvkm_bar_bar2_reset(device);
                        break;
                case NVKM_ENGINE_IFB:
                        nvkm_mask(device, 0x001718, 0x00000000, 0x00000000);
@@ -904,9 +935,7 @@ gk104_fifo_oneinit(struct nvkm_fifo *base)
        enum nvkm_devidx engidx;
        u32 *map;
 
-       /* Determine number of PBDMAs by checking valid enable bits. */
-       nvkm_wr32(device, 0x000204, 0xffffffff);
-       fifo->pbdma_nr = hweight32(nvkm_rd32(device, 0x000204));
+       fifo->pbdma_nr = fifo->func->pbdma->nr(fifo);
        nvkm_debug(subdev, "%d PBDMA(s)\n", fifo->pbdma_nr);
 
        /* Read PBDMA->runlist(s) mapping from HW. */
@@ -978,7 +1007,7 @@ gk104_fifo_init(struct nvkm_fifo *base)
        int i;
 
        /* Enable PBDMAs. */
-       nvkm_wr32(device, 0x000204, (1 << fifo->pbdma_nr) - 1);
+       fifo->func->pbdma->init(fifo);
 
        /* PBDMA[n] */
        for (i = 0; i < fifo->pbdma_nr; i++) {
@@ -995,8 +1024,8 @@ gk104_fifo_init(struct nvkm_fifo *base)
 
        nvkm_wr32(device, 0x002254, 0x10000000 | fifo->user.bar->addr >> 12);
 
-       if (fifo->func->init_pbdma_timeout)
-               fifo->func->init_pbdma_timeout(fifo);
+       if (fifo->func->pbdma->init_timeout)
+               fifo->func->pbdma->init_timeout(fifo);
 
        nvkm_wr32(device, 0x002100, 0xffffffff);
        nvkm_wr32(device, 0x002140, 0x7fffffff);
@@ -1175,6 +1204,7 @@ gk104_fifo_fault_gpcclient[] = {
 
 static const struct gk104_fifo_func
 gk104_fifo = {
+       .pbdma = &gk104_fifo_pbdma,
        .fault.access = gk104_fifo_fault_access,
        .fault.engine = gk104_fifo_fault_engine,
        .fault.reason = gk104_fifo_fault_reason,
index d295b81..d4e5656 100644 (file)
@@ -45,7 +45,11 @@ struct gk104_fifo {
 };
 
 struct gk104_fifo_func {
-       void (*init_pbdma_timeout)(struct gk104_fifo *);
+       const struct gk104_fifo_pbdma_func {
+               int (*nr)(struct gk104_fifo *);
+               void (*init)(struct gk104_fifo *);
+               void (*init_timeout)(struct gk104_fifo *);
+       } *pbdma;
 
        struct {
                const struct nvkm_enum *access;
@@ -61,6 +65,8 @@ struct gk104_fifo_func {
                             struct nvkm_memory *, u32 offset);
                void (*chan)(struct gk104_fifo_chan *,
                             struct nvkm_memory *, u32 offset);
+               void (*commit)(struct gk104_fifo *, int runl,
+                              struct nvkm_memory *, int entries);
        } *runlist;
 
        struct gk104_fifo_user_user {
@@ -81,8 +87,11 @@ int gk104_fifo_new_(const struct gk104_fifo_func *, struct nvkm_device *,
                    int index, int nr, struct nvkm_fifo **);
 void gk104_fifo_runlist_insert(struct gk104_fifo *, struct gk104_fifo_chan *);
 void gk104_fifo_runlist_remove(struct gk104_fifo *, struct gk104_fifo_chan *);
-void gk104_fifo_runlist_commit(struct gk104_fifo *, int runl);
+void gk104_fifo_runlist_update(struct gk104_fifo *, int runl);
 
+extern const struct gk104_fifo_pbdma_func gk104_fifo_pbdma;
+int gk104_fifo_pbdma_nr(struct gk104_fifo *);
+void gk104_fifo_pbdma_init(struct gk104_fifo *);
 extern const struct nvkm_enum gk104_fifo_fault_access[];
 extern const struct nvkm_enum gk104_fifo_fault_engine[];
 extern const struct nvkm_enum gk104_fifo_fault_reason[];
@@ -91,15 +100,30 @@ extern const struct nvkm_enum gk104_fifo_fault_gpcclient[];
 extern const struct gk104_fifo_runlist_func gk104_fifo_runlist;
 void gk104_fifo_runlist_chan(struct gk104_fifo_chan *,
                             struct nvkm_memory *, u32);
+void gk104_fifo_runlist_commit(struct gk104_fifo *, int runl,
+                              struct nvkm_memory *, int);
 
 extern const struct gk104_fifo_runlist_func gk110_fifo_runlist;
 void gk110_fifo_runlist_cgrp(struct nvkm_fifo_cgrp *,
                             struct nvkm_memory *, u32);
 
-void gk208_fifo_init_pbdma_timeout(struct gk104_fifo *);
+extern const struct gk104_fifo_pbdma_func gk208_fifo_pbdma;
+void gk208_fifo_pbdma_init_timeout(struct gk104_fifo *);
 
 extern const struct nvkm_enum gm107_fifo_fault_engine[];
 extern const struct gk104_fifo_runlist_func gm107_fifo_runlist;
 
+extern const struct gk104_fifo_pbdma_func gm200_fifo_pbdma;
+int gm200_fifo_pbdma_nr(struct gk104_fifo *);
+
 extern const struct nvkm_enum gp100_fifo_fault_engine[];
+
+extern const struct nvkm_enum gv100_fifo_fault_access[];
+extern const struct nvkm_enum gv100_fifo_fault_reason[];
+extern const struct nvkm_enum gv100_fifo_fault_hubclient[];
+extern const struct nvkm_enum gv100_fifo_fault_gpcclient[];
+void gv100_fifo_runlist_cgrp(struct nvkm_fifo_cgrp *,
+                            struct nvkm_memory *, u32);
+void gv100_fifo_runlist_chan(struct gk104_fifo_chan *,
+                            struct nvkm_memory *, u32);
 #endif
index ac7655a..8adfa6b 100644 (file)
@@ -43,10 +43,12 @@ gk110_fifo_runlist = {
        .size = 8,
        .cgrp = gk110_fifo_runlist_cgrp,
        .chan = gk104_fifo_runlist_chan,
+       .commit = gk104_fifo_runlist_commit,
 };
 
 static const struct gk104_fifo_func
 gk110_fifo = {
+       .pbdma = &gk104_fifo_pbdma,
        .fault.access = gk104_fifo_fault_access,
        .fault.engine = gk104_fifo_fault_engine,
        .fault.reason = gk104_fifo_fault_reason,
index 5ea7e45..9553fb4 100644 (file)
@@ -27,7 +27,7 @@
 #include <nvif/class.h>
 
 void
-gk208_fifo_init_pbdma_timeout(struct gk104_fifo *fifo)
+gk208_fifo_pbdma_init_timeout(struct gk104_fifo *fifo)
 {
        struct nvkm_device *device = fifo->base.engine.subdev.device;
        int i;
@@ -36,9 +36,16 @@ gk208_fifo_init_pbdma_timeout(struct gk104_fifo *fifo)
                nvkm_wr32(device, 0x04012c + (i * 0x2000), 0x0000ffff);
 }
 
+const struct gk104_fifo_pbdma_func
+gk208_fifo_pbdma = {
+       .nr = gk104_fifo_pbdma_nr,
+       .init = gk104_fifo_pbdma_init,
+       .init_timeout = gk208_fifo_pbdma_init_timeout,
+};
+
 static const struct gk104_fifo_func
 gk208_fifo = {
-       .init_pbdma_timeout = gk208_fifo_init_pbdma_timeout,
+       .pbdma = &gk208_fifo_pbdma,
        .fault.access = gk104_fifo_fault_access,
        .fault.engine = gk104_fifo_fault_engine,
        .fault.reason = gk104_fifo_fault_reason,
index 535a0eb..a4c6ac3 100644 (file)
@@ -26,7 +26,7 @@
 
 static const struct gk104_fifo_func
 gk20a_fifo = {
-       .init_pbdma_timeout = gk208_fifo_init_pbdma_timeout,
+       .pbdma = &gk208_fifo_pbdma,
        .fault.access = gk104_fifo_fault_access,
        .fault.engine = gk104_fifo_fault_engine,
        .fault.reason = gk104_fifo_fault_reason,
index 79ae19b..acf2307 100644 (file)
@@ -41,6 +41,7 @@ gm107_fifo_runlist = {
        .size = 8,
        .cgrp = gk110_fifo_runlist_cgrp,
        .chan = gm107_fifo_runlist_chan,
+       .commit = gk104_fifo_runlist_commit,
 };
 
 const struct nvkm_enum
@@ -68,7 +69,7 @@ gm107_fifo_fault_engine[] = {
 
 static const struct gk104_fifo_func
 gm107_fifo = {
-       .init_pbdma_timeout = gk208_fifo_init_pbdma_timeout,
+       .pbdma = &gk208_fifo_pbdma,
        .fault.access = gk104_fifo_fault_access,
        .fault.engine = gm107_fifo_fault_engine,
        .fault.reason = gk104_fifo_fault_reason,
index 49565fa..b96c1c5 100644 (file)
 
 #include <nvif/class.h>
 
+int
+gm200_fifo_pbdma_nr(struct gk104_fifo *fifo)
+{
+       struct nvkm_device *device = fifo->base.engine.subdev.device;
+       return nvkm_rd32(device, 0x002004) & 0x000000ff;
+}
+
+const struct gk104_fifo_pbdma_func
+gm200_fifo_pbdma = {
+       .nr = gm200_fifo_pbdma_nr,
+       .init = gk104_fifo_pbdma_init,
+       .init_timeout = gk208_fifo_pbdma_init_timeout,
+};
+
 static const struct gk104_fifo_func
 gm200_fifo = {
-       .init_pbdma_timeout = gk208_fifo_init_pbdma_timeout,
+       .pbdma = &gm200_fifo_pbdma,
        .fault.access = gk104_fifo_fault_access,
        .fault.engine = gm107_fifo_fault_engine,
        .fault.reason = gk104_fifo_fault_reason,
index 4673651..a49539b 100644 (file)
@@ -26,7 +26,7 @@
 
 static const struct gk104_fifo_func
 gm20b_fifo = {
-       .init_pbdma_timeout = gk208_fifo_init_pbdma_timeout,
+       .pbdma = &gm200_fifo_pbdma,
        .fault.access = gk104_fifo_fault_access,
        .fault.engine = gm107_fifo_fault_engine,
        .fault.reason = gk104_fifo_fault_reason,
index e2f8f90..54377e0 100644 (file)
@@ -52,7 +52,7 @@ gp100_fifo_fault_engine[] = {
 
 static const struct gk104_fifo_func
 gp100_fifo = {
-       .init_pbdma_timeout = gk208_fifo_init_pbdma_timeout,
+       .pbdma = &gm200_fifo_pbdma,
        .fault.access = gk104_fifo_fault_access,
        .fault.engine = gp100_fifo_fault_engine,
        .fault.reason = gk104_fifo_fault_reason,
index 7733bf7..778ba7e 100644 (file)
@@ -26,7 +26,7 @@
 
 static const struct gk104_fifo_func
 gp10b_fifo = {
-       .init_pbdma_timeout = gk208_fifo_init_pbdma_timeout,
+       .pbdma = &gm200_fifo_pbdma,
        .fault.access = gk104_fifo_fault_access,
        .fault.engine = gp100_fifo_fault_engine,
        .fault.reason = gk104_fifo_fault_reason,
index 118b37a..728a1ed 100644 (file)
@@ -85,7 +85,7 @@ gk104_fifo_gpfifo_engine_addr(struct nvkm_engine *engine)
        case NVKM_ENGINE_MSVLD : return 0x0270;
        case NVKM_ENGINE_VIC   : return 0x0280;
        case NVKM_ENGINE_MSENC : return 0x0290;
-       case NVKM_ENGINE_NVDEC : return 0x02100270;
+       case NVKM_ENGINE_NVDEC0: return 0x02100270;
        case NVKM_ENGINE_NVENC0: return 0x02100290;
        case NVKM_ENGINE_NVENC1: return 0x0210;
        default:
@@ -192,7 +192,7 @@ gk104_fifo_gpfifo_fini(struct nvkm_fifo_chan *base)
                gk104_fifo_runlist_remove(fifo, chan);
                nvkm_mask(device, 0x800004 + coff, 0x00000800, 0x00000800);
                gk104_fifo_gpfifo_kick(chan);
-               gk104_fifo_runlist_commit(fifo, chan->runl);
+               gk104_fifo_runlist_update(fifo, chan->runl);
        }
 
        nvkm_wr32(device, 0x800000 + coff, 0x00000000);
@@ -213,7 +213,7 @@ gk104_fifo_gpfifo_init(struct nvkm_fifo_chan *base)
        if (list_empty(&chan->head) && !chan->killed) {
                gk104_fifo_runlist_insert(fifo, chan);
                nvkm_mask(device, 0x800004 + coff, 0x00000400, 0x00000400);
-               gk104_fifo_runlist_commit(fifo, chan->runl);
+               gk104_fifo_runlist_update(fifo, chan->runl);
                nvkm_mask(device, 0x800004 + coff, 0x00000400, 0x00000400);
        }
 }
@@ -222,6 +222,7 @@ void *
 gk104_fifo_gpfifo_dtor(struct nvkm_fifo_chan *base)
 {
        struct gk104_fifo_chan *chan = gk104_fifo_chan(base);
+       nvkm_memory_unref(&chan->mthd);
        kfree(chan->cgrp);
        return chan;
 }
@@ -240,7 +241,7 @@ gk104_fifo_gpfifo_func = {
 
 static int
 gk104_fifo_gpfifo_new_(struct gk104_fifo *fifo, u64 *runlists, u16 *chid,
-                      u64 vmm, u64 ioffset, u64 ilength,
+                      u64 vmm, u64 ioffset, u64 ilength, u64 *inst, bool priv,
                       const struct nvkm_oclass *oclass,
                       struct nvkm_object **pobject)
 {
@@ -279,6 +280,7 @@ gk104_fifo_gpfifo_new_(struct gk104_fifo *fifo, u64 *runlists, u16 *chid,
                return ret;
 
        *chid = chan->base.chid;
+       *inst = chan->base.inst->addr;
 
        /* Hack to support GPUs where even individual channels should be
         * part of a channel group.
@@ -315,6 +317,7 @@ gk104_fifo_gpfifo_new_(struct gk104_fifo *fifo, u64 *runlists, u16 *chid,
        nvkm_wo32(chan->base.inst, 0x94, 0x30000001);
        nvkm_wo32(chan->base.inst, 0x9c, 0x00000100);
        nvkm_wo32(chan->base.inst, 0xac, 0x0000001f);
+       nvkm_wo32(chan->base.inst, 0xe4, priv ? 0x00000020 : 0x00000000);
        nvkm_wo32(chan->base.inst, 0xe8, chan->base.chid);
        nvkm_wo32(chan->base.inst, 0xb8, 0xf8000000);
        nvkm_wo32(chan->base.inst, 0xf8, 0x10003080); /* 0x002310 */
@@ -337,15 +340,19 @@ gk104_fifo_gpfifo_new(struct gk104_fifo *fifo, const struct nvkm_oclass *oclass,
        if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
                nvif_ioctl(parent, "create channel gpfifo vers %d vmm %llx "
                                   "ioffset %016llx ilength %08x "
-                                  "runlist %016llx\n",
+                                  "runlist %016llx priv %d\n",
                           args->v0.version, args->v0.vmm, args->v0.ioffset,
-                          args->v0.ilength, args->v0.runlist);
+                          args->v0.ilength, args->v0.runlist, args->v0.priv);
+               if (args->v0.priv && !oclass->client->super)
+                       return -EINVAL;
                return gk104_fifo_gpfifo_new_(fifo,
                                              &args->v0.runlist,
                                              &args->v0.chid,
                                               args->v0.vmm,
                                               args->v0.ioffset,
                                               args->v0.ilength,
+                                             &args->v0.inst,
+                                              args->v0.priv,
                                              oclass, pobject);
        }
 
index 9598853..a7462cf 100644 (file)
 #include <core/client.h>
 #include <core/gpuobj.h>
 
-#include <nvif/cla06f.h>
+#include <nvif/clc36f.h>
 #include <nvif/unpack.h>
 
+static u32
+gv100_fifo_gpfifo_submit_token(struct nvkm_fifo_chan *chan)
+{
+       return chan->chid;
+}
+
 static int
 gv100_fifo_gpfifo_engine_valid(struct gk104_fifo_chan *chan, bool ce, bool valid)
 {
@@ -56,7 +62,7 @@ gv100_fifo_gpfifo_engine_valid(struct gk104_fifo_chan *chan, bool ce, bool valid
        return ret;
 }
 
-static int
+int
 gv100_fifo_gpfifo_engine_fini(struct nvkm_fifo_chan *base,
                              struct nvkm_engine *engine, bool suspend)
 {
@@ -79,7 +85,7 @@ gv100_fifo_gpfifo_engine_fini(struct nvkm_fifo_chan *base,
        return ret;
 }
 
-static int
+int
 gv100_fifo_gpfifo_engine_init(struct nvkm_fifo_chan *base,
                              struct nvkm_engine *engine)
 {
@@ -100,8 +106,8 @@ gv100_fifo_gpfifo_engine_init(struct nvkm_fifo_chan *base,
        return gv100_fifo_gpfifo_engine_valid(chan, false, true);
 }
 
-const struct nvkm_fifo_chan_func
-gv100_fifo_gpfifo_func = {
+static const struct nvkm_fifo_chan_func
+gv100_fifo_gpfifo = {
        .dtor = gk104_fifo_gpfifo_dtor,
        .init = gk104_fifo_gpfifo_init,
        .fini = gk104_fifo_gpfifo_fini,
@@ -110,19 +116,23 @@ gv100_fifo_gpfifo_func = {
        .engine_dtor = gk104_fifo_gpfifo_engine_dtor,
        .engine_init = gv100_fifo_gpfifo_engine_init,
        .engine_fini = gv100_fifo_gpfifo_engine_fini,
+       .submit_token = gv100_fifo_gpfifo_submit_token,
 };
 
-static int
-gv100_fifo_gpfifo_new_(struct gk104_fifo *fifo, u64 *runlists, u16 *chid,
-                      u64 vmm, u64 ioffset, u64 ilength,
-                      const struct nvkm_oclass *oclass,
+int
+gv100_fifo_gpfifo_new_(const struct nvkm_fifo_chan_func *func,
+                      struct gk104_fifo *fifo, u64 *runlists, u16 *chid,
+                      u64 vmm, u64 ioffset, u64 ilength, u64 *inst, bool priv,
+                      u32 *token, const struct nvkm_oclass *oclass,
                       struct nvkm_object **pobject)
 {
+       struct nvkm_device *device = fifo->base.engine.subdev.device;
        struct gk104_fifo_chan *chan;
        int runlist = ffs(*runlists) -1, ret, i;
        unsigned long engm;
        u64 subdevs = 0;
-       u64 usermem;
+       u64 usermem, mthd;
+       u32 size;
 
        if (!vmm || runlist < 0 || runlist >= fifo->runlist_nr)
                return -EINVAL;
@@ -142,14 +152,15 @@ gv100_fifo_gpfifo_new_(struct gk104_fifo *fifo, u64 *runlists, u16 *chid,
        chan->runl = runlist;
        INIT_LIST_HEAD(&chan->head);
 
-       ret = nvkm_fifo_chan_ctor(&gv100_fifo_gpfifo_func, &fifo->base,
-                                 0x1000, 0x1000, true, vmm, 0, subdevs,
-                                 1, fifo->user.bar->addr, 0x200,
+       ret = nvkm_fifo_chan_ctor(func, &fifo->base, 0x1000, 0x1000, true, vmm,
+                                 0, subdevs, 1, fifo->user.bar->addr, 0x200,
                                  oclass, &chan->base);
        if (ret)
                return ret;
 
        *chid = chan->base.chid;
+       *inst = chan->base.inst->addr;
+       *token = chan->base.func->submit_token(&chan->base);
 
        /* Hack to support GPUs where even individual channels should be
         * part of a channel group.
@@ -173,6 +184,20 @@ gv100_fifo_gpfifo_new_(struct gk104_fifo *fifo, u64 *runlists, u16 *chid,
        nvkm_done(fifo->user.mem);
        usermem = nvkm_memory_addr(fifo->user.mem) + usermem;
 
+       /* Allocate fault method buffer (magics come from nvgpu). */
+       size = nvkm_rd32(device, 0x104028); /* NV_PCE_PCE_MAP */
+       size = 27 * 5 * (((9 + 1 + 3) * hweight32(size)) + 2);
+       size = roundup(size, PAGE_SIZE);
+
+       ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, size, 0x1000, true,
+                             &chan->mthd);
+       if (ret)
+               return ret;
+
+       mthd = nvkm_memory_bar2(chan->mthd);
+       if (mthd == ~0ULL)
+               return -EFAULT;
+
        /* RAMFC */
        nvkm_kmap(chan->base.inst);
        nvkm_wo32(chan->base.inst, 0x008, lower_32_bits(usermem));
@@ -184,13 +209,13 @@ gv100_fifo_gpfifo_new_(struct gk104_fifo *fifo, u64 *runlists, u16 *chid,
                                          (ilength << 16));
        nvkm_wo32(chan->base.inst, 0x084, 0x20400000);
        nvkm_wo32(chan->base.inst, 0x094, 0x30000001);
-       nvkm_wo32(chan->base.inst, 0x0e4, 0x00000020);
+       nvkm_wo32(chan->base.inst, 0x0e4, priv ? 0x00000020 : 0x00000000);
        nvkm_wo32(chan->base.inst, 0x0e8, chan->base.chid);
-       nvkm_wo32(chan->base.inst, 0x0f4, 0x00001100);
+       nvkm_wo32(chan->base.inst, 0x0f4, 0x00001000);
        nvkm_wo32(chan->base.inst, 0x0f8, 0x10003080);
        nvkm_mo32(chan->base.inst, 0x218, 0x00000000, 0x00000000);
-       nvkm_wo32(chan->base.inst, 0x220, 0x020a1000);
-       nvkm_wo32(chan->base.inst, 0x224, 0x00000000);
+       nvkm_wo32(chan->base.inst, 0x220, lower_32_bits(mthd));
+       nvkm_wo32(chan->base.inst, 0x224, upper_32_bits(mthd));
        nvkm_done(chan->base.inst);
        return gv100_fifo_gpfifo_engine_valid(chan, true, true);
 }
@@ -201,7 +226,7 @@ gv100_fifo_gpfifo_new(struct gk104_fifo *fifo, const struct nvkm_oclass *oclass,
 {
        struct nvkm_object *parent = oclass->parent;
        union {
-               struct kepler_channel_gpfifo_a_v0 v0;
+               struct volta_channel_gpfifo_a_v0 v0;
        } *args = data;
        int ret = -ENOSYS;
 
@@ -209,15 +234,20 @@ gv100_fifo_gpfifo_new(struct gk104_fifo *fifo, const struct nvkm_oclass *oclass,
        if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
                nvif_ioctl(parent, "create channel gpfifo vers %d vmm %llx "
                                   "ioffset %016llx ilength %08x "
-                                  "runlist %016llx\n",
+                                  "runlist %016llx priv %d\n",
                           args->v0.version, args->v0.vmm, args->v0.ioffset,
-                          args->v0.ilength, args->v0.runlist);
-               return gv100_fifo_gpfifo_new_(fifo,
+                          args->v0.ilength, args->v0.runlist, args->v0.priv);
+               if (args->v0.priv && !oclass->client->super)
+                       return -EINVAL;
+               return gv100_fifo_gpfifo_new_(&gv100_fifo_gpfifo, fifo,
                                              &args->v0.runlist,
                                              &args->v0.chid,
                                               args->v0.vmm,
                                               args->v0.ioffset,
                                               args->v0.ilength,
+                                             &args->v0.inst,
+                                              args->v0.priv,
+                                             &args->v0.token,
                                              oclass, pobject);
        }
 
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifotu104.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifotu104.c
new file mode 100644 (file)
index 0000000..ff70484
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * 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 "changk104.h"
+#include "cgrp.h"
+
+#include <core/client.h>
+#include <core/gpuobj.h>
+
+#include <nvif/clc36f.h>
+#include <nvif/unpack.h>
+
+static u32
+tu104_fifo_gpfifo_submit_token(struct nvkm_fifo_chan *base)
+{
+       struct gk104_fifo_chan *chan = gk104_fifo_chan(base);
+       return (chan->runl << 16) | chan->base.chid;
+}
+
+static const struct nvkm_fifo_chan_func
+tu104_fifo_gpfifo = {
+       .dtor = gk104_fifo_gpfifo_dtor,
+       .init = gk104_fifo_gpfifo_init,
+       .fini = gk104_fifo_gpfifo_fini,
+       .ntfy = gf100_fifo_chan_ntfy,
+       .engine_ctor = gk104_fifo_gpfifo_engine_ctor,
+       .engine_dtor = gk104_fifo_gpfifo_engine_dtor,
+       .engine_init = gv100_fifo_gpfifo_engine_init,
+       .engine_fini = gv100_fifo_gpfifo_engine_fini,
+       .submit_token = tu104_fifo_gpfifo_submit_token,
+};
+
+int
+tu104_fifo_gpfifo_new(struct gk104_fifo *fifo, const struct nvkm_oclass *oclass,
+                     void *data, u32 size, struct nvkm_object **pobject)
+{
+       struct nvkm_object *parent = oclass->parent;
+       union {
+               struct volta_channel_gpfifo_a_v0 v0;
+       } *args = data;
+       int ret = -ENOSYS;
+
+       nvif_ioctl(parent, "create channel gpfifo size %d\n", size);
+       if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
+               nvif_ioctl(parent, "create channel gpfifo vers %d vmm %llx "
+                                  "ioffset %016llx ilength %08x "
+                                  "runlist %016llx priv %d\n",
+                          args->v0.version, args->v0.vmm, args->v0.ioffset,
+                          args->v0.ilength, args->v0.runlist, args->v0.priv);
+               if (args->v0.priv && !oclass->client->super)
+                       return -EINVAL;
+               return gv100_fifo_gpfifo_new_(&tu104_fifo_gpfifo, fifo,
+                                             &args->v0.runlist,
+                                             &args->v0.chid,
+                                              args->v0.vmm,
+                                              args->v0.ioffset,
+                                              args->v0.ilength,
+                                             &args->v0.inst,
+                                              args->v0.priv,
+                                             &args->v0.token,
+                                             oclass, pobject);
+       }
+
+       return ret;
+}
index 4e1d159..6ee1bb3 100644 (file)
@@ -28,7 +28,7 @@
 
 #include <nvif/class.h>
 
-static void
+void
 gv100_fifo_runlist_chan(struct gk104_fifo_chan *chan,
                        struct nvkm_memory *memory, u32 offset)
 {
@@ -42,7 +42,7 @@ gv100_fifo_runlist_chan(struct gk104_fifo_chan *chan,
        nvkm_wo32(memory, offset + 0xc, upper_32_bits(inst));
 }
 
-static void
+void
 gv100_fifo_runlist_cgrp(struct nvkm_fifo_cgrp *cgrp,
                        struct nvkm_memory *memory, u32 offset)
 {
@@ -57,9 +57,10 @@ gv100_fifo_runlist = {
        .size = 16,
        .cgrp = gv100_fifo_runlist_cgrp,
        .chan = gv100_fifo_runlist_chan,
+       .commit = gk104_fifo_runlist_commit,
 };
 
-static const struct nvkm_enum
+const struct nvkm_enum
 gv100_fifo_fault_gpcclient[] = {
        { 0x00, "T1_0" },
        { 0x01, "T1_1" },
@@ -161,7 +162,7 @@ gv100_fifo_fault_gpcclient[] = {
        {}
 };
 
-static const struct nvkm_enum
+const struct nvkm_enum
 gv100_fifo_fault_hubclient[] = {
        { 0x00, "VIP" },
        { 0x01, "CE0" },
@@ -223,7 +224,7 @@ gv100_fifo_fault_hubclient[] = {
        {}
 };
 
-static const struct nvkm_enum
+const struct nvkm_enum
 gv100_fifo_fault_reason[] = {
        { 0x00, "PDE" },
        { 0x01, "PDE_SIZE" },
@@ -271,7 +272,7 @@ gv100_fifo_fault_engine[] = {
        {}
 };
 
-static const struct nvkm_enum
+const struct nvkm_enum
 gv100_fifo_fault_access[] = {
        { 0x0, "VIRT_READ" },
        { 0x1, "VIRT_WRITE" },
@@ -287,7 +288,7 @@ gv100_fifo_fault_access[] = {
 
 static const struct gk104_fifo_func
 gv100_fifo = {
-       .init_pbdma_timeout = gk208_fifo_init_pbdma_timeout,
+       .pbdma = &gm200_fifo_pbdma,
        .fault.access = gv100_fifo_fault_access,
        .fault.engine = gv100_fifo_fault_engine,
        .fault.reason = gv100_fifo_fault_reason,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu104.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu104.c
new file mode 100644 (file)
index 0000000..98c8070
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * 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 "gk104.h"
+#include "cgrp.h"
+#include "changk104.h"
+#include "user.h"
+
+#include <core/gpuobj.h>
+
+#include <nvif/class.h>
+
+static void
+tu104_fifo_runlist_commit(struct gk104_fifo *fifo, int runl,
+                         struct nvkm_memory *mem, int nr)
+{
+       struct nvkm_device *device = fifo->base.engine.subdev.device;
+       u64 addr = nvkm_memory_addr(mem);
+       /*XXX: target? */
+
+       nvkm_wr32(device, 0x002b00 + (runl * 0x10), lower_32_bits(addr));
+       nvkm_wr32(device, 0x002b04 + (runl * 0x10), upper_32_bits(addr));
+       nvkm_wr32(device, 0x002b08 + (runl * 0x10), nr);
+
+       /*XXX: how to wait? can you even wait? */
+}
+
+const struct gk104_fifo_runlist_func
+tu104_fifo_runlist = {
+       .size = 16,
+       .cgrp = gv100_fifo_runlist_cgrp,
+       .chan = gv100_fifo_runlist_chan,
+       .commit = tu104_fifo_runlist_commit,
+};
+
+static const struct nvkm_enum
+tu104_fifo_fault_engine[] = {
+       { 0x01, "DISPLAY" },
+       { 0x03, "PTP" },
+       { 0x06, "PWR_PMU" },
+       { 0x08, "IFB", NULL, NVKM_ENGINE_IFB },
+       { 0x09, "PERF" },
+       { 0x1f, "PHYSICAL" },
+       { 0x20, "HOST0" },
+       { 0x21, "HOST1" },
+       { 0x22, "HOST2" },
+       { 0x23, "HOST3" },
+       { 0x24, "HOST4" },
+       { 0x25, "HOST5" },
+       { 0x26, "HOST6" },
+       { 0x27, "HOST7" },
+       { 0x28, "HOST8" },
+       { 0x29, "HOST9" },
+       { 0x2a, "HOST10" },
+       { 0x2b, "HOST11" },
+       { 0x2c, "HOST12" },
+       { 0x2d, "HOST13" },
+       { 0x2e, "HOST14" },
+       { 0x80, "BAR1", NULL, NVKM_SUBDEV_BAR },
+       { 0xc0, "BAR2", NULL, NVKM_SUBDEV_INSTMEM },
+       {}
+};
+
+static void
+tu104_fifo_pbdma_init(struct gk104_fifo *fifo)
+{
+       struct nvkm_device *device = fifo->base.engine.subdev.device;
+       const u32 mask = (1 << fifo->pbdma_nr) - 1;
+       /*XXX: this is a bit of a guess at this point in time. */
+       nvkm_mask(device, 0xb65000, 0x80000fff, 0x80000000 | mask);
+}
+
+static const struct gk104_fifo_pbdma_func
+tu104_fifo_pbdma = {
+       .nr = gm200_fifo_pbdma_nr,
+       .init = tu104_fifo_pbdma_init,
+       .init_timeout = gk208_fifo_pbdma_init_timeout,
+};
+
+static const struct gk104_fifo_func
+tu104_fifo = {
+       .pbdma = &tu104_fifo_pbdma,
+       .fault.access = gv100_fifo_fault_access,
+       .fault.engine = tu104_fifo_fault_engine,
+       .fault.reason = gv100_fifo_fault_reason,
+       .fault.hubclient = gv100_fifo_fault_hubclient,
+       .fault.gpcclient = gv100_fifo_fault_gpcclient,
+       .runlist = &tu104_fifo_runlist,
+       .user = {{-1,-1,VOLTA_USERMODE_A       }, tu104_fifo_user_new   },
+       .chan = {{ 0, 0,TURING_CHANNEL_GPFIFO_A}, tu104_fifo_gpfifo_new },
+       .cgrp_force = true,
+};
+
+int
+tu104_fifo_new(struct nvkm_device *device, int index, struct nvkm_fifo **pfifo)
+{
+       return gk104_fifo_new_(&tu104_fifo, device, index, 4096, pfifo);
+}
index ed84092..14b0c6b 100644 (file)
@@ -3,4 +3,6 @@
 #include "priv.h"
 int gv100_fifo_user_new(const struct nvkm_oclass *, void *, u32,
                        struct nvkm_object **);
+int tu104_fifo_user_new(const struct nvkm_oclass *, void *, u32,
+                       struct nvkm_object **);
 #endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/usertu104.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/usertu104.c
new file mode 100644 (file)
index 0000000..8f98548
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * 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 "user.h"
+
+static int
+tu104_fifo_user_map(struct nvkm_object *object, void *argv, u32 argc,
+                   enum nvkm_object_map *type, u64 *addr, u64 *size)
+{
+       struct nvkm_device *device = object->engine->subdev.device;
+       *addr = 0xbb0000 + device->func->resource_addr(device, 0);
+       *size = 0x010000;
+       *type = NVKM_OBJECT_MAP_IO;
+       return 0;
+}
+
+static const struct nvkm_object_func
+tu104_fifo_user = {
+       .map = tu104_fifo_user_map,
+};
+
+int
+tu104_fifo_user_new(const struct nvkm_oclass *oclass, void *argv, u32 argc,
+                   struct nvkm_object **pobject)
+{
+       return nvkm_object_new_(&tu104_fifo_user, oclass, argv, argc, pobject);
+}
index 14be41f..4273401 100644 (file)
@@ -197,7 +197,7 @@ nvkm_falcon_ctor(const struct nvkm_falcon_func *func,
        case NVKM_SUBDEV_PMU:
                debug_reg = 0xc08;
                break;
-       case NVKM_ENGINE_NVDEC:
+       case NVKM_ENGINE_NVDEC0:
                debug_reg = 0xd00;
                break;
        case NVKM_ENGINE_SEC2:
index e583045..ab0282d 100644 (file)
@@ -5,3 +5,4 @@ nvkm-y += nvkm/subdev/bar/gf100.o
 nvkm-y += nvkm/subdev/bar/gk20a.o
 nvkm-y += nvkm/subdev/bar/gm107.o
 nvkm-y += nvkm/subdev/bar/gm20b.o
+nvkm-y += nvkm/subdev/bar/tu104.o
index 243f0a5..209a6a4 100644 (file)
@@ -36,6 +36,16 @@ nvkm_bar_bar1_vmm(struct nvkm_device *device)
        return device->bar->func->bar1.vmm(device->bar);
 }
 
+void
+nvkm_bar_bar1_reset(struct nvkm_device *device)
+{
+       struct nvkm_bar *bar = device->bar;
+       if (bar) {
+               bar->func->bar1.init(bar);
+               bar->func->bar1.wait(bar);
+       }
+}
+
 struct nvkm_vmm *
 nvkm_bar_bar2_vmm(struct nvkm_device *device)
 {
@@ -48,6 +58,16 @@ nvkm_bar_bar2_vmm(struct nvkm_device *device)
        return NULL;
 }
 
+void
+nvkm_bar_bar2_reset(struct nvkm_device *device)
+{
+       struct nvkm_bar *bar = device->bar;
+       if (bar && bar->bar2) {
+               bar->func->bar2.init(bar);
+               bar->func->bar2.wait(bar);
+       }
+}
+
 void
 nvkm_bar_bar2_fini(struct nvkm_device *device)
 {
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bar/tu104.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bar/tu104.c
new file mode 100644 (file)
index 0000000..ecaead1
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * 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 "gf100.h"
+
+#include <core/memory.h>
+#include <subdev/timer.h>
+
+static void
+tu104_bar_bar2_wait(struct nvkm_bar *bar)
+{
+       struct nvkm_device *device = bar->subdev.device;
+       nvkm_msec(device, 2000,
+               if (!(nvkm_rd32(device, 0xb80f50) & 0x0000000c))
+                       break;
+       );
+}
+
+static void
+tu104_bar_bar2_fini(struct nvkm_bar *bar)
+{
+       nvkm_mask(bar->subdev.device, 0xb80f48, 0x80000000, 0x00000000);
+}
+
+static void
+tu104_bar_bar2_init(struct nvkm_bar *base)
+{
+       struct nvkm_device *device = base->subdev.device;
+       struct gf100_bar *bar = gf100_bar(base);
+       u32 addr = nvkm_memory_addr(bar->bar[0].inst) >> 12;
+       if (bar->bar2_halve)
+               addr |= 0x40000000;
+       nvkm_wr32(device, 0xb80f48, 0x80000000 | addr);
+}
+
+static void
+tu104_bar_bar1_wait(struct nvkm_bar *bar)
+{
+       struct nvkm_device *device = bar->subdev.device;
+       nvkm_msec(device, 2000,
+               if (!(nvkm_rd32(device, 0xb80f50) & 0x00000003))
+                       break;
+       );
+}
+
+static void
+tu104_bar_bar1_fini(struct nvkm_bar *bar)
+{
+       nvkm_mask(bar->subdev.device, 0xb80f40, 0x80000000, 0x00000000);
+}
+
+static void
+tu104_bar_bar1_init(struct nvkm_bar *base)
+{
+       struct nvkm_device *device = base->subdev.device;
+       struct gf100_bar *bar = gf100_bar(base);
+       const u32 addr = nvkm_memory_addr(bar->bar[1].inst) >> 12;
+       nvkm_wr32(device, 0xb80f40, 0x80000000 | addr);
+}
+
+static const struct nvkm_bar_func
+tu104_bar = {
+       .dtor = gf100_bar_dtor,
+       .oneinit = gf100_bar_oneinit,
+       .bar1.init = tu104_bar_bar1_init,
+       .bar1.fini = tu104_bar_bar1_fini,
+       .bar1.wait = tu104_bar_bar1_wait,
+       .bar1.vmm = gf100_bar_bar1_vmm,
+       .bar2.init = tu104_bar_bar2_init,
+       .bar2.fini = tu104_bar_bar2_fini,
+       .bar2.wait = tu104_bar_bar2_wait,
+       .bar2.vmm = gf100_bar_bar2_vmm,
+       .flush = g84_bar_flush,
+};
+
+int
+tu104_bar_new(struct nvkm_device *device, int index, struct nvkm_bar **pbar)
+{
+       return gf100_bar_new_(&tu104_bar, device, index, pbar);
+}
index 50a4369..3ef505a 100644 (file)
@@ -13,3 +13,4 @@ nvkm-y += nvkm/subdev/devinit/gf100.o
 nvkm-y += nvkm/subdev/devinit/gm107.o
 nvkm-y += nvkm/subdev/devinit/gm200.o
 nvkm-y += nvkm/subdev/devinit/gv100.o
+nvkm-y += nvkm/subdev/devinit/tu104.o
index 17235e9..59940da 100644 (file)
@@ -105,6 +105,15 @@ pmu_load(struct nv50_devinit *init, u8 type, bool post,
        return pmu_exec(init, pmu.init_addr_pmu), 0;
 }
 
+void
+gm200_devinit_preos(struct nv50_devinit *init, bool post)
+{
+       /* Optional: Execute PRE_OS application on PMU, which should at
+        * least take care of fans until a full PMU has been loaded.
+        */
+       pmu_load(init, 0x01, post, NULL, NULL);
+}
+
 int
 gm200_devinit_post(struct nvkm_devinit *base, bool post)
 {
@@ -156,10 +165,7 @@ gm200_devinit_post(struct nvkm_devinit *base, bool post)
                        return -ETIMEDOUT;
        }
 
-       /* Optional: Execute PRE_OS application on PMU, which should at
-        * least take care of fans until a full PMU has been loaded.
-        */
-       pmu_load(init, 0x01, post, NULL, NULL);
+       gm200_devinit_preos(init, post);
        return 0;
 }
 
index 9b9f0dc..72d130b 100644 (file)
@@ -26,4 +26,5 @@ void gf100_devinit_preinit(struct nvkm_devinit *);
 u64  gm107_devinit_disable(struct nvkm_devinit *);
 
 int gm200_devinit_post(struct nvkm_devinit *, bool);
+void gm200_devinit_preos(struct nv50_devinit *, bool);
 #endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/tu104.c b/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/tu104.c
new file mode 100644 (file)
index 0000000..aae87b3
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * 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 "nv50.h"
+
+#include <subdev/bios.h>
+#include <subdev/bios/pll.h>
+#include <subdev/clk/pll.h>
+
+static int
+tu104_devinit_pll_set(struct nvkm_devinit *init, u32 type, u32 freq)
+{
+       struct nvkm_subdev *subdev = &init->subdev;
+       struct nvkm_device *device = subdev->device;
+       struct nvbios_pll info;
+       int head = type - PLL_VPLL0;
+       int N, fN, M, P;
+       int ret;
+
+       ret = nvbios_pll_parse(device->bios, type, &info);
+       if (ret)
+               return ret;
+
+       ret = gt215_pll_calc(subdev, &info, freq, &N, &fN, &M, &P);
+       if (ret < 0)
+               return ret;
+
+       switch (info.type) {
+       case PLL_VPLL0:
+       case PLL_VPLL1:
+       case PLL_VPLL2:
+       case PLL_VPLL3:
+               nvkm_wr32(device, 0x00ef10 + (head * 0x40), fN << 16);
+               nvkm_wr32(device, 0x00ef04 + (head * 0x40), (P << 16) |
+                                                           (N <<  8) |
+                                                           (M <<  0));
+               /*XXX*/
+               nvkm_wr32(device, 0x00ef0c + (head * 0x40), 0x00000900);
+               nvkm_wr32(device, 0x00ef00 + (head * 0x40), 0x02000014);
+               break;
+       default:
+               nvkm_warn(subdev, "%08x/%dKhz unimplemented\n", type, freq);
+               ret = -EINVAL;
+               break;
+       }
+
+       return ret;
+}
+
+static int
+tu104_devinit_post(struct nvkm_devinit *base, bool post)
+{
+       struct nv50_devinit *init = nv50_devinit(base);
+       gm200_devinit_preos(init, post);
+       return 0;
+}
+
+static const struct nvkm_devinit_func
+tu104_devinit = {
+       .init = nv50_devinit_init,
+       .post = tu104_devinit_post,
+       .pll_set = tu104_devinit_pll_set,
+       .disable = gm107_devinit_disable,
+};
+
+int
+tu104_devinit_new(struct nvkm_device *device, int index,
+               struct nvkm_devinit **pinit)
+{
+       return nv50_devinit_new_(&tu104_devinit, device, index, pinit);
+}
index 45bb46f..794eb17 100644 (file)
@@ -1,3 +1,4 @@
 nvkm-y += nvkm/subdev/fault/base.o
 nvkm-y += nvkm/subdev/fault/gp100.o
 nvkm-y += nvkm/subdev/fault/gv100.o
+nvkm-y += nvkm/subdev/fault/tu104.o
index 16ad91c..4ba1e21 100644 (file)
 
 #include <core/memory.h>
 #include <core/notify.h>
-#include <subdev/bar.h>
-#include <subdev/mmu.h>
 
 static void
 nvkm_fault_ntfy_fini(struct nvkm_event *event, int type, int index)
 {
        struct nvkm_fault *fault = container_of(event, typeof(*fault), event);
-       fault->func->buffer.fini(fault->buffer[index]);
+       fault->func->buffer.intr(fault->buffer[index], false);
 }
 
 static void
 nvkm_fault_ntfy_init(struct nvkm_event *event, int type, int index)
 {
        struct nvkm_fault *fault = container_of(event, typeof(*fault), event);
-       fault->func->buffer.init(fault->buffer[index]);
+       fault->func->buffer.intr(fault->buffer[index], true);
 }
 
 static int
@@ -91,7 +89,6 @@ nvkm_fault_oneinit_buffer(struct nvkm_fault *fault, int id)
 {
        struct nvkm_subdev *subdev = &fault->subdev;
        struct nvkm_device *device = subdev->device;
-       struct nvkm_vmm *bar2 = nvkm_bar_bar2_vmm(device);
        struct nvkm_fault_buffer *buffer;
        int ret;
 
@@ -99,7 +96,7 @@ nvkm_fault_oneinit_buffer(struct nvkm_fault *fault, int id)
                return -ENOMEM;
        buffer->fault = fault;
        buffer->id = id;
-       buffer->entries = fault->func->buffer.entries(buffer);
+       fault->func->buffer.info(buffer);
        fault->buffer[id] = buffer;
 
        nvkm_debug(subdev, "buffer %d: %d entries\n", id, buffer->entries);
@@ -110,12 +107,12 @@ nvkm_fault_oneinit_buffer(struct nvkm_fault *fault, int id)
        if (ret)
                return ret;
 
-       ret = nvkm_vmm_get(bar2, 12, nvkm_memory_size(buffer->mem),
-                          &buffer->vma);
-       if (ret)
-               return ret;
+       /* Pin fault buffer in BAR2. */
+       buffer->addr = nvkm_memory_bar2(buffer->mem);
+       if (buffer->addr == ~0ULL)
+               return -EFAULT;
 
-       return nvkm_memory_map(buffer->mem, 0, bar2, buffer->vma, NULL, 0);
+       return 0;
 }
 
 static int
@@ -146,7 +143,6 @@ nvkm_fault_oneinit(struct nvkm_subdev *subdev)
 static void *
 nvkm_fault_dtor(struct nvkm_subdev *subdev)
 {
-       struct nvkm_vmm *bar2 = nvkm_bar_bar2_vmm(subdev->device);
        struct nvkm_fault *fault = nvkm_fault(subdev);
        int i;
 
@@ -154,7 +150,6 @@ nvkm_fault_dtor(struct nvkm_subdev *subdev)
 
        for (i = 0; i < fault->buffer_nr; i++) {
                if (fault->buffer[i]) {
-                       nvkm_vmm_put(bar2, &fault->buffer[i]->vma);
                        nvkm_memory_unref(&fault->buffer[i]->mem);
                        kfree(fault->buffer[i]);
                }
index 5e71db2..8fb96fe 100644 (file)
  */
 #include "priv.h"
 
-#include <subdev/mmu.h>
+#include <subdev/mc.h>
+
+static void
+gp100_fault_buffer_intr(struct nvkm_fault_buffer *buffer, bool enable)
+{
+       struct nvkm_device *device = buffer->fault->subdev.device;
+       nvkm_mc_intr_mask(device, NVKM_SUBDEV_FAULT, enable);
+}
 
 static void
 gp100_fault_buffer_fini(struct nvkm_fault_buffer *buffer)
@@ -34,15 +41,17 @@ static void
 gp100_fault_buffer_init(struct nvkm_fault_buffer *buffer)
 {
        struct nvkm_device *device = buffer->fault->subdev.device;
-       nvkm_wr32(device, 0x002a74, upper_32_bits(buffer->vma->addr));
-       nvkm_wr32(device, 0x002a70, lower_32_bits(buffer->vma->addr));
+       nvkm_wr32(device, 0x002a74, upper_32_bits(buffer->addr));
+       nvkm_wr32(device, 0x002a70, lower_32_bits(buffer->addr));
        nvkm_mask(device, 0x002a70, 0x00000001, 0x00000001);
 }
 
-static u32
-gp100_fault_buffer_entries(struct nvkm_fault_buffer *buffer)
+static void
+gp100_fault_buffer_info(struct nvkm_fault_buffer *buffer)
 {
-       return nvkm_rd32(buffer->fault->subdev.device, 0x002a78);
+       buffer->entries = nvkm_rd32(buffer->fault->subdev.device, 0x002a78);
+       buffer->get = 0x002a7c;
+       buffer->put = 0x002a80;
 }
 
 static void
@@ -56,9 +65,10 @@ gp100_fault = {
        .intr = gp100_fault_intr,
        .buffer.nr = 1,
        .buffer.entry_size = 32,
-       .buffer.entries = gp100_fault_buffer_entries,
+       .buffer.info = gp100_fault_buffer_info,
        .buffer.init = gp100_fault_buffer_init,
        .buffer.fini = gp100_fault_buffer_fini,
+       .buffer.intr = gp100_fault_buffer_intr,
 };
 
 int
index 3cd610d..6fc54e1 100644 (file)
@@ -30,9 +30,8 @@ gv100_fault_buffer_process(struct nvkm_fault_buffer *buffer)
 {
        struct nvkm_device *device = buffer->fault->subdev.device;
        struct nvkm_memory *mem = buffer->mem;
-       const u32 foff = buffer->id * 0x14;
-       u32 get = nvkm_rd32(device, 0x100e2c + foff);
-       u32 put = nvkm_rd32(device, 0x100e30 + foff);
+       u32 get = nvkm_rd32(device, buffer->get);
+       u32 put = nvkm_rd32(device, buffer->put);
        if (put == get)
                return;
 
@@ -51,7 +50,7 @@ gv100_fault_buffer_process(struct nvkm_fault_buffer *buffer)
 
                if (++get == buffer->entries)
                        get = 0;
-               nvkm_wr32(device, 0x100e2c + foff, get);
+               nvkm_wr32(device, buffer->get, get);
 
                info.addr   = ((u64)addrhi << 32) | addrlo;
                info.inst   = ((u64)insthi << 32) | instlo;
@@ -70,13 +69,21 @@ gv100_fault_buffer_process(struct nvkm_fault_buffer *buffer)
 }
 
 static void
-gv100_fault_buffer_fini(struct nvkm_fault_buffer *buffer)
+gv100_fault_buffer_intr(struct nvkm_fault_buffer *buffer, bool enable)
 {
        struct nvkm_device *device = buffer->fault->subdev.device;
        const u32 intr = buffer->id ? 0x08000000 : 0x20000000;
-       const u32 foff = buffer->id * 0x14;
+       if (enable)
+               nvkm_mask(device, 0x100a2c, intr, intr);
+       else
+               nvkm_mask(device, 0x100a34, intr, intr);
+}
 
-       nvkm_mask(device, 0x100a34, intr, intr);
+static void
+gv100_fault_buffer_fini(struct nvkm_fault_buffer *buffer)
+{
+       struct nvkm_device *device = buffer->fault->subdev.device;
+       const u32 foff = buffer->id * 0x14;
        nvkm_mask(device, 0x100e34 + foff, 0x80000000, 0x00000000);
 }
 
@@ -84,23 +91,25 @@ static void
 gv100_fault_buffer_init(struct nvkm_fault_buffer *buffer)
 {
        struct nvkm_device *device = buffer->fault->subdev.device;
-       const u32 intr = buffer->id ? 0x08000000 : 0x20000000;
        const u32 foff = buffer->id * 0x14;
 
        nvkm_mask(device, 0x100e34 + foff, 0xc0000000, 0x40000000);
-       nvkm_wr32(device, 0x100e28 + foff, upper_32_bits(buffer->vma->addr));
-       nvkm_wr32(device, 0x100e24 + foff, lower_32_bits(buffer->vma->addr));
+       nvkm_wr32(device, 0x100e28 + foff, upper_32_bits(buffer->addr));
+       nvkm_wr32(device, 0x100e24 + foff, lower_32_bits(buffer->addr));
        nvkm_mask(device, 0x100e34 + foff, 0x80000000, 0x80000000);
-       nvkm_mask(device, 0x100a2c, intr, intr);
 }
 
-static u32
-gv100_fault_buffer_entries(struct nvkm_fault_buffer *buffer)
+static void
+gv100_fault_buffer_info(struct nvkm_fault_buffer *buffer)
 {
        struct nvkm_device *device = buffer->fault->subdev.device;
        const u32 foff = buffer->id * 0x14;
+
        nvkm_mask(device, 0x100e34 + foff, 0x40000000, 0x40000000);
-       return nvkm_rd32(device, 0x100e34 + foff) & 0x000fffff;
+
+       buffer->entries = nvkm_rd32(device, 0x100e34 + foff) & 0x000fffff;
+       buffer->get = 0x100e2c + foff;
+       buffer->put = 0x100e30 + foff;
 }
 
 static int
@@ -166,6 +175,8 @@ static void
 gv100_fault_fini(struct nvkm_fault *fault)
 {
        nvkm_notify_put(&fault->nrpfb);
+       if (fault->buffer[0])
+               fault->func->buffer.fini(fault->buffer[0]);
        nvkm_mask(fault->subdev.device, 0x100a34, 0x80000000, 0x80000000);
 }
 
@@ -173,14 +184,15 @@ static void
 gv100_fault_init(struct nvkm_fault *fault)
 {
        nvkm_mask(fault->subdev.device, 0x100a2c, 0x80000000, 0x80000000);
+       fault->func->buffer.init(fault->buffer[0]);
        nvkm_notify_get(&fault->nrpfb);
 }
 
-static int
+int
 gv100_fault_oneinit(struct nvkm_fault *fault)
 {
        return nvkm_notify_init(&fault->buffer[0]->object, &fault->event,
-                               gv100_fault_ntfy_nrpfb, false, NULL, 0, 0,
+                               gv100_fault_ntfy_nrpfb, true, NULL, 0, 0,
                                &fault->nrpfb);
 }
 
@@ -192,9 +204,10 @@ gv100_fault = {
        .intr = gv100_fault_intr,
        .buffer.nr = 2,
        .buffer.entry_size = 32,
-       .buffer.entries = gv100_fault_buffer_entries,
+       .buffer.info = gv100_fault_buffer_info,
        .buffer.init = gv100_fault_buffer_init,
        .buffer.fini = gv100_fault_buffer_fini,
+       .buffer.intr = gv100_fault_buffer_intr,
 };
 
 int
index e4d2f52..8ca8b28 100644 (file)
@@ -12,8 +12,10 @@ struct nvkm_fault_buffer {
        struct nvkm_fault *fault;
        int id;
        int entries;
+       u32 get;
+       u32 put;
        struct nvkm_memory *mem;
-       struct nvkm_vma *vma;
+       u64 addr;
 };
 
 int nvkm_fault_new_(const struct nvkm_fault_func *, struct nvkm_device *,
@@ -27,9 +29,12 @@ struct nvkm_fault_func {
        struct {
                int nr;
                u32 entry_size;
-               u32 (*entries)(struct nvkm_fault_buffer *);
+               void (*info)(struct nvkm_fault_buffer *);
                void (*init)(struct nvkm_fault_buffer *);
                void (*fini)(struct nvkm_fault_buffer *);
+               void (*intr)(struct nvkm_fault_buffer *, bool enable);
        } buffer;
 };
+
+int gv100_fault_oneinit(struct nvkm_fault *);
 #endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fault/tu104.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fault/tu104.c
new file mode 100644 (file)
index 0000000..9c8a3ad
--- /dev/null
@@ -0,0 +1,167 @@
+/*
+ * 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 "priv.h"
+
+#include <core/memory.h>
+#include <subdev/mmu.h>
+#include <engine/fifo.h>
+
+#include <nvif/class.h>
+
+static void
+tu104_fault_buffer_intr(struct nvkm_fault_buffer *buffer, bool enable)
+{
+       /*XXX: Earlier versions of RM touched the old regs on Turing,
+        *     which don't appear to actually work anymore, but newer
+        *     versions of RM don't appear to touch anything at all..
+        */
+}
+
+static void
+tu104_fault_buffer_fini(struct nvkm_fault_buffer *buffer)
+{
+       struct nvkm_device *device = buffer->fault->subdev.device;
+       const u32 foff = buffer->id * 0x20;
+       nvkm_mask(device, 0xb83010 + foff, 0x80000000, 0x00000000);
+}
+
+static void
+tu104_fault_buffer_init(struct nvkm_fault_buffer *buffer)
+{
+       struct nvkm_device *device = buffer->fault->subdev.device;
+       const u32 foff = buffer->id * 0x20;
+
+       nvkm_mask(device, 0xb83010 + foff, 0xc0000000, 0x40000000);
+       nvkm_wr32(device, 0xb83004 + foff, upper_32_bits(buffer->addr));
+       nvkm_wr32(device, 0xb83000 + foff, lower_32_bits(buffer->addr));
+       nvkm_mask(device, 0xb83010 + foff, 0x80000000, 0x80000000);
+}
+
+static void
+tu104_fault_buffer_info(struct nvkm_fault_buffer *buffer)
+{
+       struct nvkm_device *device = buffer->fault->subdev.device;
+       const u32 foff = buffer->id * 0x20;
+
+       nvkm_mask(device, 0xb83010 + foff, 0x40000000, 0x40000000);
+
+       buffer->entries = nvkm_rd32(device, 0xb83010 + foff) & 0x000fffff;
+       buffer->get = 0xb83008 + foff;
+       buffer->put = 0xb8300c + foff;
+}
+
+static void
+tu104_fault_intr_fault(struct nvkm_fault *fault)
+{
+       struct nvkm_subdev *subdev = &fault->subdev;
+       struct nvkm_device *device = subdev->device;
+       struct nvkm_fault_data info;
+       const u32 addrlo = nvkm_rd32(device, 0xb83080);
+       const u32 addrhi = nvkm_rd32(device, 0xb83084);
+       const u32  info0 = nvkm_rd32(device, 0xb83088);
+       const u32 insthi = nvkm_rd32(device, 0xb8308c);
+       const u32  info1 = nvkm_rd32(device, 0xb83090);
+
+       info.addr = ((u64)addrhi << 32) | addrlo;
+       info.inst = ((u64)insthi << 32) | (info0 & 0xfffff000);
+       info.time = 0;
+       info.engine = (info0 & 0x000000ff);
+       info.valid  = (info1 & 0x80000000) >> 31;
+       info.gpc    = (info1 & 0x1f000000) >> 24;
+       info.hub    = (info1 & 0x00100000) >> 20;
+       info.access = (info1 & 0x000f0000) >> 16;
+       info.client = (info1 & 0x00007f00) >> 8;
+       info.reason = (info1 & 0x0000001f);
+
+       nvkm_fifo_fault(device->fifo, &info);
+}
+
+static void
+tu104_fault_intr(struct nvkm_fault *fault)
+{
+       struct nvkm_subdev *subdev = &fault->subdev;
+       struct nvkm_device *device = subdev->device;
+       u32 stat = nvkm_rd32(device, 0xb83094);
+
+       if (stat & 0x80000000) {
+               tu104_fault_intr_fault(fault);
+               nvkm_wr32(device, 0xb83094, 0x80000000);
+               stat &= ~0x80000000;
+       }
+
+       if (stat & 0x00000200) {
+               if (fault->buffer[0]) {
+                       nvkm_event_send(&fault->event, 1, 0, NULL, 0);
+                       stat &= ~0x00000200;
+               }
+       }
+
+       /*XXX: guess, can't confirm until we get fw... */
+       if (stat & 0x00000100) {
+               if (fault->buffer[1]) {
+                       nvkm_event_send(&fault->event, 1, 1, NULL, 0);
+                       stat &= ~0x00000100;
+               }
+       }
+
+       if (stat) {
+               nvkm_debug(subdev, "intr %08x\n", stat);
+       }
+}
+
+static void
+tu104_fault_fini(struct nvkm_fault *fault)
+{
+       nvkm_notify_put(&fault->nrpfb);
+       if (fault->buffer[0])
+               fault->func->buffer.fini(fault->buffer[0]);
+       /*XXX: disable priv faults */
+}
+
+static void
+tu104_fault_init(struct nvkm_fault *fault)
+{
+       /*XXX: enable priv faults */
+       fault->func->buffer.init(fault->buffer[0]);
+       nvkm_notify_get(&fault->nrpfb);
+}
+
+static const struct nvkm_fault_func
+tu104_fault = {
+       .oneinit = gv100_fault_oneinit,
+       .init = tu104_fault_init,
+       .fini = tu104_fault_fini,
+       .intr = tu104_fault_intr,
+       .buffer.nr = 2,
+       .buffer.entry_size = 32,
+       .buffer.info = tu104_fault_buffer_info,
+       .buffer.init = tu104_fault_buffer_init,
+       .buffer.fini = tu104_fault_buffer_fini,
+       .buffer.intr = tu104_fault_buffer_intr,
+};
+
+int
+tu104_fault_new(struct nvkm_device *device, int index,
+               struct nvkm_fault **pfault)
+{
+       return nvkm_fault_new_(&tu104_fault, device, index, pfault);
+}
index 434d2fc..b2bb5a3 100644 (file)
@@ -68,10 +68,13 @@ nvkm_fb_bios_memtype(struct nvkm_bios *bios)
 
        if (nvbios_M0203Em(bios, ramcfg, &ver, &hdr, &M0203E)) {
                switch (M0203E.type) {
-               case M0203E_TYPE_DDR2 : return NVKM_RAM_TYPE_DDR2;
-               case M0203E_TYPE_DDR3 : return NVKM_RAM_TYPE_DDR3;
-               case M0203E_TYPE_GDDR3: return NVKM_RAM_TYPE_GDDR3;
-               case M0203E_TYPE_GDDR5: return NVKM_RAM_TYPE_GDDR5;
+               case M0203E_TYPE_DDR2  : return NVKM_RAM_TYPE_DDR2;
+               case M0203E_TYPE_DDR3  : return NVKM_RAM_TYPE_DDR3;
+               case M0203E_TYPE_GDDR3 : return NVKM_RAM_TYPE_GDDR3;
+               case M0203E_TYPE_GDDR5 : return NVKM_RAM_TYPE_GDDR5;
+               case M0203E_TYPE_GDDR5X: return NVKM_RAM_TYPE_GDDR5X;
+               case M0203E_TYPE_GDDR6 : return NVKM_RAM_TYPE_GDDR6;
+               case M0203E_TYPE_HBM2  : return NVKM_RAM_TYPE_HBM2;
                default:
                        nvkm_warn(subdev, "M0203E type %02x\n", M0203E.type);
                        return NVKM_RAM_TYPE_UNKNOWN;
index 24c7bd5..b11867f 100644 (file)
@@ -184,6 +184,9 @@ nvkm_ram_ctor(const struct nvkm_ram_func *func, struct nvkm_fb *fb,
                [NVKM_RAM_TYPE_GDDR3  ] = "GDDR3",
                [NVKM_RAM_TYPE_GDDR4  ] = "GDDR4",
                [NVKM_RAM_TYPE_GDDR5  ] = "GDDR5",
+               [NVKM_RAM_TYPE_GDDR5X ] = "GDDR5X",
+               [NVKM_RAM_TYPE_GDDR6  ] = "GDDR6",
+               [NVKM_RAM_TYPE_HBM2   ] = "HBM2",
        };
        struct nvkm_subdev *subdev = &fb->subdev;
        int ret;
index db48a1d..02c4eb2 100644 (file)
@@ -288,6 +288,19 @@ nv50_instobj_addr(struct nvkm_memory *memory)
        return nvkm_memory_addr(nv50_instobj(memory)->ram);
 }
 
+static u64
+nv50_instobj_bar2(struct nvkm_memory *memory)
+{
+       struct nv50_instobj *iobj = nv50_instobj(memory);
+       u64 addr = ~0ULL;
+       if (nv50_instobj_acquire(&iobj->base.memory)) {
+               iobj->lru.next = NULL; /* Exclude from eviction. */
+               addr = iobj->bar->addr;
+       }
+       nv50_instobj_release(&iobj->base.memory);
+       return addr;
+}
+
 static enum nvkm_memory_target
 nv50_instobj_target(struct nvkm_memory *memory)
 {
@@ -325,8 +338,9 @@ static const struct nvkm_memory_func
 nv50_instobj_func = {
        .dtor = nv50_instobj_dtor,
        .target = nv50_instobj_target,
-       .size = nv50_instobj_size,
+       .bar2 = nv50_instobj_bar2,
        .addr = nv50_instobj_addr,
+       .size = nv50_instobj_size,
        .boot = nv50_instobj_boot,
        .acquire = nv50_instobj_acquire,
        .release = nv50_instobj_release,
index 2befbe3..f3b0632 100644 (file)
@@ -12,3 +12,4 @@ nvkm-y += nvkm/subdev/mc/gk104.o
 nvkm-y += nvkm/subdev/mc/gk20a.o
 nvkm-y += nvkm/subdev/mc/gp100.o
 nvkm-y += nvkm/subdev/mc/gp10b.o
+nvkm-y += nvkm/subdev/mc/tu104.o
index 09f669a..0e57ab2 100644 (file)
@@ -108,6 +108,9 @@ nvkm_mc_intr(struct nvkm_device *device, bool *handled)
        if (stat)
                nvkm_error(&mc->subdev, "intr %08x\n", stat);
        *handled = intr != 0;
+
+       if (mc->func->intr_hack)
+               mc->func->intr_hack(mc, handled);
 }
 
 static u32
index d9e3691..eb91a4c 100644 (file)
@@ -26,6 +26,7 @@ struct nvkm_mc_func {
        void (*intr_mask)(struct nvkm_mc *, u32 mask, u32 stat);
        /* retrieve pending interrupt mask (NV_PMC_INTR) */
        u32 (*intr_stat)(struct nvkm_mc *);
+       void (*intr_hack)(struct nvkm_mc *, bool *handled);
        const struct nvkm_mc_map *reset;
        void (*unk260)(struct nvkm_mc *, u32);
 };
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/tu104.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/tu104.c
new file mode 100644 (file)
index 0000000..b7165bd
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * 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 "priv.h"
+
+static void
+tu104_mc_intr_hack(struct nvkm_mc *mc, bool *handled)
+{
+       struct nvkm_device *device = mc->subdev.device;
+       u32 stat = nvkm_rd32(device, 0xb81010);
+       if (stat & 0x00000050) {
+               struct nvkm_subdev *subdev =
+                       nvkm_device_subdev(device, NVKM_SUBDEV_FAULT);
+               nvkm_wr32(device, 0xb81010, stat & 0x00000050);
+               if (subdev)
+                       nvkm_subdev_intr(subdev);
+               *handled = true;
+       }
+}
+
+static const struct nvkm_mc_func
+tu104_mc = {
+       .init = nv50_mc_init,
+       .intr = gp100_mc_intr,
+       .intr_unarm = gp100_mc_intr_unarm,
+       .intr_rearm = gp100_mc_intr_rearm,
+       .intr_mask = gp100_mc_intr_mask,
+       .intr_stat = gf100_mc_intr_stat,
+       .intr_hack = tu104_mc_intr_hack,
+       .reset = gk104_mc_reset,
+};
+
+int
+tu104_mc_new(struct nvkm_device *device, int index, struct nvkm_mc **pmc)
+{
+       return gp100_mc_new_(&tu104_mc, device, index, pmc);
+}
index 58a24e3..8966180 100644 (file)
@@ -13,6 +13,7 @@ nvkm-y += nvkm/subdev/mmu/gm20b.o
 nvkm-y += nvkm/subdev/mmu/gp100.o
 nvkm-y += nvkm/subdev/mmu/gp10b.o
 nvkm-y += nvkm/subdev/mmu/gv100.o
+nvkm-y += nvkm/subdev/mmu/tu104.o
 
 nvkm-y += nvkm/subdev/mmu/mem.o
 nvkm-y += nvkm/subdev/mmu/memnv04.o
@@ -33,6 +34,7 @@ nvkm-y += nvkm/subdev/mmu/vmmgm20b.o
 nvkm-y += nvkm/subdev/mmu/vmmgp100.o
 nvkm-y += nvkm/subdev/mmu/vmmgp10b.o
 nvkm-y += nvkm/subdev/mmu/vmmgv100.o
+nvkm-y += nvkm/subdev/mmu/vmmtu104.o
 
 nvkm-y += nvkm/subdev/mmu/umem.o
 nvkm-y += nvkm/subdev/mmu/ummu.o
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/tu104.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/tu104.c
new file mode 100644 (file)
index 0000000..8e6f409
--- /dev/null
@@ -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 "mem.h"
+#include "vmm.h"
+
+#include <core/option.h>
+
+#include <nvif/class.h>
+
+static const struct nvkm_mmu_func
+tu104_mmu = {
+       .dma_bits = 47,
+       .mmu = {{ -1, -1, NVIF_CLASS_MMU_GF100}},
+       .mem = {{ -1,  0, NVIF_CLASS_MEM_GF100}, gf100_mem_new, gf100_mem_map },
+       .vmm = {{ -1,  0, NVIF_CLASS_VMM_GP100}, tu104_vmm_new },
+       .kind = gm200_mmu_kind,
+       .kind_sys = true,
+};
+
+int
+tu104_mmu_new(struct nvkm_device *device, int index, struct nvkm_mmu **pmmu)
+{
+       return nvkm_mmu_new_(&tu104_mmu, device, index, pmmu);
+}
index 37b201b..6889076 100644 (file)
@@ -134,23 +134,10 @@ nvkm_uvmm_mthd_map(struct nvkm_uvmm *uvmm, void *argv, u32 argc)
                        goto fail;
                }
 
-               if (vma->addr != addr) {
-                       const u64 tail = vma->size + vma->addr - addr;
-                       if (ret = -ENOMEM, !(vma = nvkm_vma_tail(vma, tail)))
-                               goto fail;
-                       vma->part = true;
-                       nvkm_vmm_node_insert(vmm, vma);
-               }
-
-               if (vma->size != size) {
-                       const u64 tail = vma->size - size;
-                       struct nvkm_vma *tmp;
-                       if (ret = -ENOMEM, !(tmp = nvkm_vma_tail(vma, tail))) {
-                               nvkm_vmm_unmap_region(vmm, vma);
-                               goto fail;
-                       }
-                       tmp->part = true;
-                       nvkm_vmm_node_insert(vmm, tmp);
+               vma = nvkm_vmm_node_split(vmm, vma, addr, size);
+               if (!vma) {
+                       ret = -ENOMEM;
+                       goto fail;
                }
        }
        vma->busy = true;
index 7459def..6b87fff 100644 (file)
@@ -767,6 +767,20 @@ nvkm_vma_tail(struct nvkm_vma *vma, u64 tail)
        return new;
 }
 
+static inline void
+nvkm_vmm_free_remove(struct nvkm_vmm *vmm, struct nvkm_vma *vma)
+{
+       rb_erase(&vma->tree, &vmm->free);
+}
+
+static inline void
+nvkm_vmm_free_delete(struct nvkm_vmm *vmm, struct nvkm_vma *vma)
+{
+       nvkm_vmm_free_remove(vmm, vma);
+       list_del(&vma->head);
+       kfree(vma);
+}
+
 static void
 nvkm_vmm_free_insert(struct nvkm_vmm *vmm, struct nvkm_vma *vma)
 {
@@ -795,7 +809,21 @@ nvkm_vmm_free_insert(struct nvkm_vmm *vmm, struct nvkm_vma *vma)
        rb_insert_color(&vma->tree, &vmm->free);
 }
 
-void
+static inline void
+nvkm_vmm_node_remove(struct nvkm_vmm *vmm, struct nvkm_vma *vma)
+{
+       rb_erase(&vma->tree, &vmm->root);
+}
+
+static inline void
+nvkm_vmm_node_delete(struct nvkm_vmm *vmm, struct nvkm_vma *vma)
+{
+       nvkm_vmm_node_remove(vmm, vma);
+       list_del(&vma->head);
+       kfree(vma);
+}
+
+static void
 nvkm_vmm_node_insert(struct nvkm_vmm *vmm, struct nvkm_vma *vma)
 {
        struct rb_node **ptr = &vmm->root.rb_node;
@@ -834,6 +862,78 @@ nvkm_vmm_node_search(struct nvkm_vmm *vmm, u64 addr)
        return NULL;
 }
 
+#define node(root, dir) (((root)->head.dir == &vmm->list) ? NULL :             \
+       list_entry((root)->head.dir, struct nvkm_vma, head))
+
+static struct nvkm_vma *
+nvkm_vmm_node_merge(struct nvkm_vmm *vmm, struct nvkm_vma *prev,
+                   struct nvkm_vma *vma, struct nvkm_vma *next, u64 size)
+{
+       if (next) {
+               if (vma->size == size) {
+                       vma->size += next->size;
+                       nvkm_vmm_node_delete(vmm, next);
+                       if (prev) {
+                               prev->size += vma->size;
+                               nvkm_vmm_node_delete(vmm, vma);
+                               return prev;
+                       }
+                       return vma;
+               }
+               BUG_ON(prev);
+
+               nvkm_vmm_node_remove(vmm, next);
+               vma->size -= size;
+               next->addr -= size;
+               next->size += size;
+               nvkm_vmm_node_insert(vmm, next);
+               return next;
+       }
+
+       if (prev) {
+               if (vma->size != size) {
+                       nvkm_vmm_node_remove(vmm, vma);
+                       prev->size += size;
+                       vma->addr += size;
+                       vma->size -= size;
+                       nvkm_vmm_node_insert(vmm, vma);
+               } else {
+                       prev->size += vma->size;
+                       nvkm_vmm_node_delete(vmm, vma);
+               }
+               return prev;
+       }
+
+       return vma;
+}
+
+struct nvkm_vma *
+nvkm_vmm_node_split(struct nvkm_vmm *vmm,
+                   struct nvkm_vma *vma, u64 addr, u64 size)
+{
+       struct nvkm_vma *prev = NULL;
+
+       if (vma->addr != addr) {
+               prev = vma;
+               if (!(vma = nvkm_vma_tail(vma, vma->size + vma->addr - addr)))
+                       return NULL;
+               vma->part = true;
+               nvkm_vmm_node_insert(vmm, vma);
+       }
+
+       if (vma->size != size) {
+               struct nvkm_vma *tmp;
+               if (!(tmp = nvkm_vma_tail(vma, vma->size - size))) {
+                       nvkm_vmm_node_merge(vmm, prev, vma, NULL, vma->size);
+                       return NULL;
+               }
+               tmp->part = true;
+               nvkm_vmm_node_insert(vmm, tmp);
+       }
+
+       return vma;
+}
+
 static void
 nvkm_vmm_dtor(struct nvkm_vmm *vmm)
 {
@@ -954,37 +1054,20 @@ nvkm_vmm_new_(const struct nvkm_vmm_func *func, struct nvkm_mmu *mmu,
        return nvkm_vmm_ctor(func, mmu, hdr, addr, size, key, name, *pvmm);
 }
 
-#define node(root, dir) ((root)->head.dir == &vmm->list) ? NULL :              \
-       list_entry((root)->head.dir, struct nvkm_vma, head)
-
 void
 nvkm_vmm_unmap_region(struct nvkm_vmm *vmm, struct nvkm_vma *vma)
 {
-       struct nvkm_vma *next;
+       struct nvkm_vma *next = node(vma, next);
+       struct nvkm_vma *prev = NULL;
 
        nvkm_memory_tags_put(vma->memory, vmm->mmu->subdev.device, &vma->tags);
        nvkm_memory_unref(&vma->memory);
 
-       if (vma->part) {
-               struct nvkm_vma *prev = node(vma, prev);
-               if (!prev->memory) {
-                       prev->size += vma->size;
-                       rb_erase(&vma->tree, &vmm->root);
-                       list_del(&vma->head);
-                       kfree(vma);
-                       vma = prev;
-               }
-       }
-
-       next = node(vma, next);
-       if (next && next->part) {
-               if (!next->memory) {
-                       vma->size += next->size;
-                       rb_erase(&next->tree, &vmm->root);
-                       list_del(&next->head);
-                       kfree(next);
-               }
-       }
+       if (!vma->part || ((prev = node(vma, prev)), prev->memory))
+               prev = NULL;
+       if (!next->part || next->memory)
+               next = NULL;
+       nvkm_vmm_node_merge(vmm, prev, vma, next, vma->size);
 }
 
 void
@@ -1163,18 +1246,14 @@ nvkm_vmm_put_region(struct nvkm_vmm *vmm, struct nvkm_vma *vma)
        struct nvkm_vma *prev, *next;
 
        if ((prev = node(vma, prev)) && !prev->used) {
-               rb_erase(&prev->tree, &vmm->free);
-               list_del(&prev->head);
                vma->addr  = prev->addr;
                vma->size += prev->size;
-               kfree(prev);
+               nvkm_vmm_free_delete(vmm, prev);
        }
 
        if ((next = node(vma, next)) && !next->used) {
-               rb_erase(&next->tree, &vmm->free);
-               list_del(&next->head);
                vma->size += next->size;
-               kfree(next);
+               nvkm_vmm_free_delete(vmm, next);
        }
 
        nvkm_vmm_free_insert(vmm, vma);
@@ -1250,7 +1329,7 @@ nvkm_vmm_put_locked(struct nvkm_vmm *vmm, struct nvkm_vma *vma)
        }
 
        /* Remove VMA from the list of allocated nodes. */
-       rb_erase(&vma->tree, &vmm->root);
+       nvkm_vmm_node_remove(vmm, vma);
 
        /* Merge VMA back into the free list. */
        vma->page = NVKM_VMA_PAGE_NONE;
@@ -1357,7 +1436,7 @@ nvkm_vmm_get_locked(struct nvkm_vmm *vmm, bool getref, bool mapref, bool sparse,
                        tail = ALIGN_DOWN(tail, vmm->func->page_block);
 
                if (addr <= tail && tail - addr >= size) {
-                       rb_erase(&this->tree, &vmm->free);
+                       nvkm_vmm_free_remove(vmm, this);
                        vma = this;
                        break;
                }
index 1a3b0a3..42ad326 100644 (file)
@@ -157,6 +157,8 @@ int nvkm_vmm_ctor(const struct nvkm_vmm_func *, struct nvkm_mmu *,
                  u32 pd_header, u64 addr, u64 size, struct lock_class_key *,
                  const char *name, struct nvkm_vmm *);
 struct nvkm_vma *nvkm_vmm_node_search(struct nvkm_vmm *, u64 addr);
+struct nvkm_vma *nvkm_vmm_node_split(struct nvkm_vmm *, struct nvkm_vma *,
+                                    u64 addr, u64 size);
 int nvkm_vmm_get_locked(struct nvkm_vmm *, bool getref, bool mapref,
                        bool sparse, u8 page, u8 align, u64 size,
                        struct nvkm_vma **pvma);
@@ -165,7 +167,6 @@ void nvkm_vmm_unmap_locked(struct nvkm_vmm *, struct nvkm_vma *);
 void nvkm_vmm_unmap_region(struct nvkm_vmm *vmm, struct nvkm_vma *vma);
 
 struct nvkm_vma *nvkm_vma_tail(struct nvkm_vma *, u64 tail);
-void nvkm_vmm_node_insert(struct nvkm_vmm *, struct nvkm_vma *);
 
 int nv04_vmm_new_(const struct nvkm_vmm_func *, struct nvkm_mmu *, u32,
                  u64, u64, void *, u32, struct lock_class_key *,
@@ -200,6 +201,8 @@ int gp100_vmm_join(struct nvkm_vmm *, struct nvkm_memory *);
 int gp100_vmm_valid(struct nvkm_vmm *, void *, u32, struct nvkm_vmm_map *);
 void gp100_vmm_flush(struct nvkm_vmm *, int);
 
+int gv100_vmm_join(struct nvkm_vmm *, struct nvkm_memory *);
+
 int nv04_vmm_new(struct nvkm_mmu *, u64, u64, void *, u32,
                 struct lock_class_key *, const char *, struct nvkm_vmm **);
 int nv41_vmm_new(struct nvkm_mmu *, u64, u64, void *, u32,
@@ -239,6 +242,9 @@ int gp10b_vmm_new(struct nvkm_mmu *, u64, u64, void *, u32,
 int gv100_vmm_new(struct nvkm_mmu *, u64, u64, void *, u32,
                  struct lock_class_key *, const char *,
                  struct nvkm_vmm **);
+int tu104_vmm_new(struct nvkm_mmu *, u64, u64, void *, u32,
+                 struct lock_class_key *, const char *,
+                 struct nvkm_vmm **);
 
 #define VMM_PRINT(l,v,p,f,a...) do {                                           \
        struct nvkm_vmm *_vmm = (v);                                           \
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmtu104.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmtu104.c
new file mode 100644 (file)
index 0000000..adaadd9
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * 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 "vmm.h"
+
+#include <subdev/timer.h>
+
+static void
+tu104_vmm_flush(struct nvkm_vmm *vmm, int depth)
+{
+       struct nvkm_subdev *subdev = &vmm->mmu->subdev;
+       struct nvkm_device *device = subdev->device;
+       u32 type = depth << 24; /*XXX: not confirmed */
+
+       type = 0x00000001; /* PAGE_ALL */
+       if (atomic_read(&vmm->engref[NVKM_SUBDEV_BAR]))
+               type |= 0x00000004; /* HUB_ONLY */
+
+       mutex_lock(&subdev->mutex);
+
+       nvkm_wr32(device, 0xb830a0, vmm->pd->pt[0]->addr >> 8);
+       nvkm_wr32(device, 0xb830a4, 0x00000000);
+       nvkm_wr32(device, 0x100e68, 0x00000000);
+       nvkm_wr32(device, 0xb830b0, 0x80000000 | type);
+
+       nvkm_msec(device, 2000,
+               if (!(nvkm_rd32(device, 0xb830b0) & 0x80000000))
+                       break;
+       );
+
+       mutex_unlock(&subdev->mutex);
+}
+
+static const struct nvkm_vmm_func
+tu104_vmm = {
+       .join = gv100_vmm_join,
+       .part = gf100_vmm_part,
+       .aper = gf100_vmm_aper,
+       .valid = gp100_vmm_valid,
+       .flush = tu104_vmm_flush,
+       .page = {
+               { 47, &gp100_vmm_desc_16[4], NVKM_VMM_PAGE_Sxxx },
+               { 38, &gp100_vmm_desc_16[3], NVKM_VMM_PAGE_Sxxx },
+               { 29, &gp100_vmm_desc_16[2], NVKM_VMM_PAGE_Sxxx },
+               { 21, &gp100_vmm_desc_16[1], NVKM_VMM_PAGE_SVxC },
+               { 16, &gp100_vmm_desc_16[0], NVKM_VMM_PAGE_SVxC },
+               { 12, &gp100_vmm_desc_12[0], NVKM_VMM_PAGE_SVHx },
+               {}
+       }
+};
+
+int
+tu104_vmm_new(struct nvkm_mmu *mmu, u64 addr, u64 size,
+             void *argv, u32 argc, struct lock_class_key *key,
+             const char *name, struct nvkm_vmm **pvmm)
+{
+       return nv04_vmm_new_(&tu104_vmm, mmu, 0, addr, size,
+                            argv, argc, key, name, pvmm);
+}
index 1f7a3c1..84a2f24 100644 (file)
@@ -59,10 +59,10 @@ gp102_run_secure_scrub(struct nvkm_secboot *sb)
 
        nvkm_debug(subdev, "running VPR scrubber binary on NVDEC...\n");
 
-       engine = nvkm_engine_ref(&device->nvdec->engine);
+       engine = nvkm_engine_ref(&device->nvdec[0]->engine);
        if (IS_ERR(engine))
                return PTR_ERR(engine);
-       falcon = device->nvdec->falcon;
+       falcon = device->nvdec[0]->falcon;
 
        nvkm_falcon_get(falcon, &sb->subdev);
 
index 36de23d..dd92203 100644 (file)
  */
 #include "priv.h"
 
+s64
+nvkm_timer_wait_test(struct nvkm_timer_wait *wait)
+{
+       struct nvkm_subdev *subdev = &wait->tmr->subdev;
+       u64 time = nvkm_timer_read(wait->tmr);
+
+       if (wait->reads == 0) {
+               wait->time0 = time;
+               wait->time1 = time;
+       }
+
+       if (wait->time1 == time) {
+               if (wait->reads++ == 16) {
+                       nvkm_fatal(subdev, "stalled at %016llx\n", time);
+                       return -ETIMEDOUT;
+               }
+       } else {
+               wait->time1 = time;
+               wait->reads = 1;
+       }
+
+       if (wait->time1 - wait->time0 > wait->limit)
+               return -ETIMEDOUT;
+
+       return wait->time1 - wait->time0;
+}
+
+void
+nvkm_timer_wait_init(struct nvkm_device *device, u64 nsec,
+                    struct nvkm_timer_wait *wait)
+{
+       wait->tmr = device->timer;
+       wait->limit = nsec;
+       wait->reads = 0;
+}
+
 u64
 nvkm_timer_read(struct nvkm_timer *tmr)
 {
index 4f1f3e8..39081ea 100644 (file)
@@ -86,7 +86,7 @@ gk104_top_oneinit(struct nvkm_top *top)
                case 0x0000000d: A_(SEC2  ); break;
                case 0x0000000e: B_(NVENC ); break;
                case 0x0000000f: A_(NVENC1); break;
-               case 0x00000010: A_(NVDEC ); break;
+               case 0x00000010: B_(NVDEC ); break;
                case 0x00000013: B_(CE    ); break;
                        break;
                default: