drm/nouveau/kms/nv50-: split core implementation by hardware class
authorBen Skeggs <bskeggs@redhat.com>
Tue, 8 May 2018 10:39:47 +0000 (20:39 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Fri, 18 May 2018 05:01:28 +0000 (15:01 +1000)
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
19 files changed:
drivers/gpu/drm/nouveau/dispnv50/Kbuild
drivers/gpu/drm/nouveau/dispnv50/core.c
drivers/gpu/drm/nouveau/dispnv50/core.h
drivers/gpu/drm/nouveau/dispnv50/core507d.c
drivers/gpu/drm/nouveau/dispnv50/core827d.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/dispnv50/core907d.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/dispnv50/core917d.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/dispnv50/dac507d.c
drivers/gpu/drm/nouveau/dispnv50/dac907d.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/dispnv50/disp.c
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/head827d.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/dispnv50/head907d.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/dispnv50/head917d.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/dispnv50/pior507d.c
drivers/gpu/drm/nouveau/dispnv50/sor507d.c
drivers/gpu/drm/nouveau/dispnv50/sor907d.c [new file with mode: 0644]

index f3877d2d884077824e0719a824b878a0d0e48f80..cde3ae98191a02cea899b7791d2bc7a2716b624d 100644 (file)
@@ -2,15 +2,23 @@ nouveau-y += dispnv50/disp.o
 
 nouveau-y += dispnv50/core.o
 nouveau-y += dispnv50/core507d.o
+nouveau-y += dispnv50/core827d.o
+nouveau-y += dispnv50/core907d.o
+nouveau-y += dispnv50/core917d.o
 
 nouveau-y += dispnv50/dac507d.o
+nouveau-y += dispnv50/dac907d.o
 
 nouveau-y += dispnv50/pior507d.o
 
 nouveau-y += dispnv50/sor507d.o
+nouveau-y += dispnv50/sor907d.o
 
 nouveau-y += dispnv50/head.o
 nouveau-y += dispnv50/head507d.o
+nouveau-y += dispnv50/head827d.o
+nouveau-y += dispnv50/head907d.o
+nouveau-y += dispnv50/head917d.o
 
 nouveau-y += dispnv50/wndw.o
 
index b12899fe052a4a9d8faec6a62dcde2bf16b56c14..f87cbaa4f8ecac95a9cb14e3d923d78cf44603f6 100644 (file)
@@ -42,17 +42,17 @@ nv50_core_new(struct nouveau_drm *drm, struct nv50_core **pcore)
                int version;
                int (*new)(struct nouveau_drm *, s32, struct nv50_core **);
        } cores[] = {
-               { GP102_DISP_CORE_CHANNEL_DMA, 0, core507d_new },
-               { GP100_DISP_CORE_CHANNEL_DMA, 0, core507d_new },
-               { GM200_DISP_CORE_CHANNEL_DMA, 0, core507d_new },
-               { GM107_DISP_CORE_CHANNEL_DMA, 0, core507d_new },
-               { GK110_DISP_CORE_CHANNEL_DMA, 0, core507d_new },
-               { GK104_DISP_CORE_CHANNEL_DMA, 0, core507d_new },
-               { GF110_DISP_CORE_CHANNEL_DMA, 0, core507d_new },
-               { GT214_DISP_CORE_CHANNEL_DMA, 0, core507d_new },
-               { GT206_DISP_CORE_CHANNEL_DMA, 0, core507d_new },
-               { GT200_DISP_CORE_CHANNEL_DMA, 0, core507d_new },
-               {   G82_DISP_CORE_CHANNEL_DMA, 0, core507d_new },
+               { GP102_DISP_CORE_CHANNEL_DMA, 0, core917d_new },
+               { GP100_DISP_CORE_CHANNEL_DMA, 0, core917d_new },
+               { GM200_DISP_CORE_CHANNEL_DMA, 0, core917d_new },
+               { GM107_DISP_CORE_CHANNEL_DMA, 0, core917d_new },
+               { GK110_DISP_CORE_CHANNEL_DMA, 0, core917d_new },
+               { GK104_DISP_CORE_CHANNEL_DMA, 0, core917d_new },
+               { GF110_DISP_CORE_CHANNEL_DMA, 0, core907d_new },
+               { GT214_DISP_CORE_CHANNEL_DMA, 0, core827d_new },
+               { GT206_DISP_CORE_CHANNEL_DMA, 0, core827d_new },
+               { GT200_DISP_CORE_CHANNEL_DMA, 0, core827d_new },
+               {   G82_DISP_CORE_CHANNEL_DMA, 0, core827d_new },
                {  NV50_DISP_CORE_CHANNEL_DMA, 0, core507d_new },
                {}
        };
index 3cd54469311aa5644e543ca64fcb005ea1918318..5fd7ddd31e5e44840210c5725796bbd930ae5b0f 100644 (file)
@@ -12,6 +12,12 @@ int nv50_core_new(struct nouveau_drm *, struct nv50_core **);
 void nv50_core_del(struct nv50_core **);
 
 struct nv50_core_func {
+       void (*init)(struct nv50_core *);
+       void (*ntfy_init)(struct nouveau_bo *, u32 offset);
+       int (*ntfy_wait_done)(struct nouveau_bo *, u32 offset,
+                             struct nvif_device *);
+       void (*update)(struct nv50_core *, u32 interlock, bool ntfy);
+
        const struct nv50_head_func *head;
        const struct nv50_outp_func {
                void (*ctrl)(struct nv50_core *, int or, u32 ctrl,
@@ -20,7 +26,21 @@ struct nv50_core_func {
 };
 
 int core507d_new(struct nouveau_drm *, s32, struct nv50_core **);
+int core507d_new_(const struct nv50_core_func *, struct nouveau_drm *, s32,
+                 struct nv50_core **);
+void core507d_init(struct nv50_core *);
+void core507d_ntfy_init(struct nouveau_bo *, u32);
+int core507d_ntfy_wait_done(struct nouveau_bo *, u32, struct nvif_device *);
+void core507d_update(struct nv50_core *, u32, bool);
 extern const struct nv50_outp_func dac507d;
 extern const struct nv50_outp_func sor507d;
 extern const struct nv50_outp_func pior507d;
+
+int core827d_new(struct nouveau_drm *, s32, struct nv50_core **);
+
+int core907d_new(struct nouveau_drm *, s32, struct nv50_core **);
+extern const struct nv50_outp_func dac907d;
+extern const struct nv50_outp_func sor907d;
+
+int core917d_new(struct nouveau_drm *, s32, struct nv50_core **);
 #endif
index b0325f69a26f6bafc8e3cbbfaf0f264ef255b021..96d7d8fde669c6b1dae6baac12a55b885c4a334b 100644 (file)
 
 #include "nouveau_bo.h"
 
+void
+core507d_update(struct nv50_core *core, u32 interlock, bool ntfy)
+{
+       u32 *push;
+       if ((push = evo_wait(&core->chan, 5))) {
+               if (ntfy) {
+                       evo_mthd(push, 0x0084, 1);
+                       evo_data(push, 0x80000000 | NV50_DISP_CORE_NTFY);
+               }
+               evo_mthd(push, 0x0080, 2);
+               evo_data(push, interlock);
+               evo_data(push, 0x00000000);
+               evo_kick(push, &core->chan);
+       }
+}
+
+int
+core507d_ntfy_wait_done(struct nouveau_bo *bo, u32 offset,
+                       struct nvif_device *device)
+{
+       s64 time = nvif_msec(device, 2000ULL,
+               if (nouveau_bo_rd32(bo, offset / 4))
+                       break;
+               usleep_range(1, 2);
+       );
+       return time < 0 ? time : 0;
+}
+
+void
+core507d_ntfy_init(struct nouveau_bo *bo, u32 offset)
+{
+       nouveau_bo_wr32(bo, offset / 4, 0x00000000);
+}
+
+void
+core507d_init(struct nv50_core *core)
+{
+       u32 *push;
+       if ((push = evo_wait(&core->chan, 2))) {
+               evo_mthd(push, 0x0088, 1);
+               evo_data(push, core->chan.sync.handle);
+               evo_kick(push, &core->chan);
+       }
+}
+
 static const struct nv50_core_func
 core507d = {
+       .init = core507d_init,
+       .ntfy_init = core507d_ntfy_init,
+       .ntfy_wait_done = core507d_ntfy_wait_done,
+       .update = core507d_update,
        .head = &head507d,
        .dac = &dac507d,
        .sor = &sor507d,
        .pior = &pior507d,
 };
 
-static int
+int
 core507d_new_(const struct nv50_core_func *func, struct nouveau_drm *drm,
              s32 oclass, struct nv50_core **pcore)
 {
diff --git a/drivers/gpu/drm/nouveau/dispnv50/core827d.c b/drivers/gpu/drm/nouveau/dispnv50/core827d.c
new file mode 100644 (file)
index 0000000..6123a06
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * 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 const struct nv50_core_func
+core827d = {
+       .init = core507d_init,
+       .ntfy_init = core507d_ntfy_init,
+       .ntfy_wait_done = core507d_ntfy_wait_done,
+       .update = core507d_update,
+       .head = &head827d,
+       .dac = &dac507d,
+       .sor = &sor507d,
+       .pior = &pior507d,
+};
+
+int
+core827d_new(struct nouveau_drm *drm, s32 oclass, struct nv50_core **pcore)
+{
+       return core507d_new_(&core827d, drm, oclass, pcore);
+}
diff --git a/drivers/gpu/drm/nouveau/dispnv50/core907d.c b/drivers/gpu/drm/nouveau/dispnv50/core907d.c
new file mode 100644 (file)
index 0000000..ef822f8
--- /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 "core.h"
+#include "head.h"
+
+static const struct nv50_core_func
+core907d = {
+       .init = core507d_init,
+       .ntfy_init = core507d_ntfy_init,
+       .ntfy_wait_done = core507d_ntfy_wait_done,
+       .update = core507d_update,
+       .head = &head907d,
+       .dac = &dac907d,
+       .sor = &sor907d,
+};
+
+int
+core907d_new(struct nouveau_drm *drm, s32 oclass, struct nv50_core **pcore)
+{
+       return core507d_new_(&core907d, drm, oclass, pcore);
+}
diff --git a/drivers/gpu/drm/nouveau/dispnv50/core917d.c b/drivers/gpu/drm/nouveau/dispnv50/core917d.c
new file mode 100644 (file)
index 0000000..392338d
--- /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 "core.h"
+#include "head.h"
+
+static const struct nv50_core_func
+core917d = {
+       .init = core507d_init,
+       .ntfy_init = core507d_ntfy_init,
+       .ntfy_wait_done = core507d_ntfy_wait_done,
+       .update = core507d_update,
+       .head = &head917d,
+       .dac = &dac907d,
+       .sor = &sor907d,
+};
+
+int
+core917d_new(struct nouveau_drm *drm, s32 oclass, struct nv50_core **pcore)
+{
+       return core507d_new_(&core917d, drm, oclass, pcore);
+}
index 28b6025a80f3d2cf86922ffe2f2a246a38dd5aa6..2a10ef7d30a8062a2018ec35fe042da673bbc798 100644 (file)
  */
 #include "core.h"
 
-#include <nvif/class.h>
-
 static void
 dac507d_ctrl(struct nv50_core *core, int or, u32 ctrl,
             struct nv50_head_atom *asyh)
 {
        u32 *push, sync = 0;
        if ((push = evo_wait(&core->chan, 3))) {
-               if (core->chan.base.user.oclass < GF110_DISP_CORE_CHANNEL_DMA) {
-                       if (asyh) {
-                               sync |= asyh->or.nvsync << 1;
-                               sync |= asyh->or.nhsync;
-                       }
-                       evo_mthd(push, 0x0400 + (or * 0x080), 2);
-                       evo_data(push, ctrl);
-                       evo_data(push, sync);
-               } else {
-                       evo_mthd(push, 0x0180 + (or * 0x020), 1);
-                       evo_data(push, ctrl);
+               if (asyh) {
+                       sync |= asyh->or.nvsync << 1;
+                       sync |= asyh->or.nhsync;
                }
+               evo_mthd(push, 0x0400 + (or * 0x080), 2);
+               evo_data(push, ctrl);
+               evo_data(push, sync);
                evo_kick(push, &core->chan);
        }
 }
diff --git a/drivers/gpu/drm/nouveau/dispnv50/dac907d.c b/drivers/gpu/drm/nouveau/dispnv50/dac907d.c
new file mode 100644 (file)
index 0000000..11e87fa
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * 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"
+
+static void
+dac907d_ctrl(struct nv50_core *core, int or, u32 ctrl,
+            struct nv50_head_atom *asyh)
+{
+       u32 *push;
+       if ((push = evo_wait(&core->chan, 2))) {
+               evo_mthd(push, 0x0180 + (or * 0x020), 1);
+               evo_data(push, ctrl);
+               evo_kick(push, &core->chan);
+       }
+}
+
+const struct nv50_outp_func
+dac907d = {
+       .ctrl = dac907d_ctrl,
+};
index a8367c5d4691b0dd8b7f5f2f08ada6a5c4cbd827..6136beeba3fcfcd8d671e43c5b8097ee86e2ff57 100644 (file)
@@ -1587,10 +1587,9 @@ static void
 nv50_disp_atomic_commit_core(struct nouveau_drm *drm, u32 interlock)
 {
        struct nv50_disp *disp = nv50_disp(drm->dev);
-       struct nv50_dmac *core = &disp->core->chan;
+       struct nv50_core *core = disp->core;
        struct nv50_mstm *mstm;
        struct drm_encoder *encoder;
-       u32 *push;
 
        NV_ATOMIC(drm, "commit core %08x\n", interlock);
 
@@ -1602,21 +1601,11 @@ nv50_disp_atomic_commit_core(struct nouveau_drm *drm, u32 interlock)
                }
        }
 
-       if ((push = evo_wait(core, 5))) {
-               evo_mthd(push, 0x0084, 1);
-               evo_data(push, 0x80000000);
-               evo_mthd(push, 0x0080, 2);
-               evo_data(push, interlock);
-               evo_data(push, 0x00000000);
-               nouveau_bo_wr32(disp->sync, 0, 0x00000000);
-               evo_kick(push, core);
-               if (nvif_msec(&drm->client.device, 2000ULL,
-                       if (nouveau_bo_rd32(disp->sync, 0))
-                               break;
-                       usleep_range(1, 2);
-               ) < 0)
-                       NV_ERROR(drm, "EVO timeout\n");
-       }
+       core->func->ntfy_init(disp->sync, NV50_DISP_CORE_NTFY);
+       core->func->update(core, interlock, true);
+       if (core->func->ntfy_wait_done(disp->sync, NV50_DISP_CORE_NTFY,
+                                      disp->core->chan.base.device))
+               NV_ERROR(drm, "core notifier timeout\n");
 
        drm_for_each_encoder(encoder, drm->dev) {
                if (encoder->encoder_type != DRM_MODE_ENCODER_DPMST) {
@@ -1770,16 +1759,10 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state *state)
 
        /* Flush update. */
        if (interlock_core) {
-               if (!interlock_chan && atom->state.legacy_cursor_update) {
-                       u32 *push = evo_wait(&disp->core->chan, 2);
-                       if (push) {
-                               evo_mthd(push, 0x0080, 1);
-                               evo_data(push, 0x00000000);
-                               evo_kick(push, &disp->core->chan);
-                       }
-               } else {
+               if (interlock_chan || !atom->state.legacy_cursor_update)
                        nv50_disp_atomic_commit_core(drm, interlock_chan);
-               }
+               else
+                       disp->core->func->update(disp->core, 0, false);
        }
 
        if (atom->lock_core)
@@ -2079,18 +2062,11 @@ nv50_display_fini(struct drm_device *dev)
 int
 nv50_display_init(struct drm_device *dev)
 {
-       struct nv50_dmac *core = &nv50_disp(dev)->core->chan;
+       struct nv50_core *core = nv50_disp(dev)->core;
        struct drm_encoder *encoder;
        struct drm_plane *plane;
-       u32 *push;
-
-       push = evo_wait(core, 32);
-       if (!push)
-               return -EBUSY;
 
-       evo_mthd(push, 0x0088, 1);
-       evo_data(push, core->sync.handle);
-       evo_kick(push, core);
+       core->func->init(core);
 
        list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
                if (encoder->encoder_type != DRM_MODE_ENCODER_DPMST) {
index 6a809ff24e145b92ad5915b84ec8ea03193bc86d..1335c00500d165dff3724a4e94e2cc78026d3d22 100644 (file)
@@ -324,7 +324,6 @@ static int
 nv50_head_atomic_check(struct drm_crtc *crtc, struct drm_crtc_state *state)
 {
        struct nouveau_drm *drm = nouveau_drm(crtc->dev);
-       struct nv50_disp *disp = nv50_disp(crtc->dev);
        struct nv50_head *head = nv50_head(crtc);
        struct nv50_head_atom *armh = nv50_head_atom(crtc->state);
        struct nv50_head_atom *asyh = nv50_head_atom(state);
@@ -373,31 +372,9 @@ nv50_head_atomic_check(struct drm_crtc *crtc, struct drm_crtc_state *state)
                                nv50_head_atomic_check_procamp(armh, asyh, asyc);
                }
 
-               if ((asyh->core.visible = (asyh->base.cpp != 0))) {
-                       asyh->core.x = asyh->base.x;
-                       asyh->core.y = asyh->base.y;
-                       asyh->core.w = asyh->base.w;
-                       asyh->core.h = asyh->base.h;
-               } else
-               if ((asyh->core.visible = asyh->curs.visible) ||
-                   (asyh->core.visible = asyh->ilut.visible)) {
-                       /*XXX: We need to either find some way of having the
-                        *     primary base layer appear black, while still
-                        *     being able to display the other layers, or we
-                        *     need to allocate a dummy black surface here.
-                        */
-                       asyh->core.x = 0;
-                       asyh->core.y = 0;
-                       asyh->core.w = asyh->state.mode.hdisplay;
-                       asyh->core.h = asyh->state.mode.vdisplay;
-               }
-               asyh->core.handle = disp->core->chan.vram.handle;
-               asyh->core.offset = 0;
-               asyh->core.format = 0xcf;
-               asyh->core.kind = 0;
-               asyh->core.layout = 1;
-               asyh->core.block = 0;
-               asyh->core.pitch = ALIGN(asyh->core.w, 64) * 4;
+               if (head->func->core_calc)
+                       head->func->core_calc(head, asyh);
+
                asyh->set.base = armh->base.cpp != asyh->base.cpp;
                asyh->set.ovly = armh->ovly.cpp != asyh->ovly.cpp;
        } else {
index 23099a82883b1cda9bef6eec2a3de3a41fa8b3a8..d00cebdbd2600674230fe17da4ff885135e815fa 100644 (file)
@@ -24,6 +24,7 @@ struct nv50_head_func {
        void (*mode)(struct nv50_head *, struct nv50_head_atom *);
        void (*ilut_set)(struct nv50_head *, struct nv50_head_atom *);
        void (*ilut_clr)(struct nv50_head *);
+       void (*core_calc)(struct nv50_head *, struct nv50_head_atom *);
        void (*core_set)(struct nv50_head *, struct nv50_head_atom *);
        void (*core_clr)(struct nv50_head *);
        void (*curs_set)(struct nv50_head *, struct nv50_head_atom *);
@@ -36,4 +37,30 @@ struct nv50_head_func {
 };
 
 extern const struct nv50_head_func head507d;
+void head507d_view(struct nv50_head *, struct nv50_head_atom *);
+void head507d_mode(struct nv50_head *, struct nv50_head_atom *);
+void head507d_core_calc(struct nv50_head *, struct nv50_head_atom *);
+void head507d_core_clr(struct nv50_head *);
+void head507d_base(struct nv50_head *, struct nv50_head_atom *);
+void head507d_ovly(struct nv50_head *, struct nv50_head_atom *);
+void head507d_dither(struct nv50_head *, struct nv50_head_atom *);
+void head507d_procamp(struct nv50_head *, struct nv50_head_atom *);
+
+extern const struct nv50_head_func head827d;
+
+extern const struct nv50_head_func head907d;
+void head907d_view(struct nv50_head *, struct nv50_head_atom *);
+void head907d_mode(struct nv50_head *, struct nv50_head_atom *);
+void head907d_ilut_set(struct nv50_head *, struct nv50_head_atom *);
+void head907d_ilut_clr(struct nv50_head *);
+void head907d_core_set(struct nv50_head *, struct nv50_head_atom *);
+void head907d_core_clr(struct nv50_head *);
+void head907d_curs_set(struct nv50_head *, struct nv50_head_atom *);
+void head907d_curs_clr(struct nv50_head *);
+void head907d_base(struct nv50_head *, struct nv50_head_atom *);
+void head907d_ovly(struct nv50_head *, struct nv50_head_atom *);
+void head907d_procamp(struct nv50_head *, struct nv50_head_atom *);
+void head907d_or(struct nv50_head *, struct nv50_head_atom *);
+
+extern const struct nv50_head_func head917d;
 #endif
index 92fa249ba72fcf8cfda32e9cb9b8c7be75554e53..5f06fa174832f0806f422fcb439f5488a3b78bdf 100644 (file)
 #include "head.h"
 #include "core.h"
 
-#include <nvif/class.h>
-
-static void
-head907d_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 (core->base.user.oclass >= GF110_DISP_CORE_CHANNEL_DMA &&
-           (push = evo_wait(core, 3))) {
-               evo_mthd(push, 0x0404 + (head->base.index * 0x300), 2);
-               evo_data(push, 0x00000001 | (asyh->or.depth  << 6) |
-                                           (asyh->or.nvsync << 4) |
-                                           (asyh->or.nhsync << 3));
-               evo_data(push, 0x31ec6000 | (head->base.index << 25) |
-                                            asyh->mode.interlace);
-               evo_kick(push, core);
-       }
-}
-
-static void
+void
 head507d_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))) {
-               if (core->base.user.oclass < GF110_DISP_CORE_CHANNEL_DMA)
-                       evo_mthd(push, 0x08a8 + (head->base.index * 0x400), 1);
-               else
-                       evo_mthd(push, 0x0498 + (head->base.index * 0x300), 1);
-               evo_data(push, (asyh->procamp.sat.sin << 20) |
-                              (asyh->procamp.sat.cos << 8));
+               evo_mthd(push, 0x08a8 + (head->base.index * 0x400), 1);
+               evo_data(push, asyh->procamp.sat.sin << 20 |
+                              asyh->procamp.sat.cos << 8);
                evo_kick(push, core);
        }
 }
 
-static void
+void
 head507d_dither(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))) {
-               if (core->base.user.oclass < GF110_DISP_CORE_CHANNEL_DMA)
-                       evo_mthd(push, 0x08a0 + (head->base.index * 0x0400), 1);
-               else
-               if (core->base.user.oclass < GK104_DISP_CORE_CHANNEL_DMA)
-                       evo_mthd(push, 0x0490 + (head->base.index * 0x0300), 1);
-               else
-                       evo_mthd(push, 0x04a0 + (head->base.index * 0x0300), 1);
-               evo_data(push, (asyh->dither.mode << 3) |
-                              (asyh->dither.bits << 1) |
-                               asyh->dither.enable);
+               evo_mthd(push, 0x08a0 + (head->base.index * 0x0400), 1);
+               evo_data(push, asyh->dither.mode << 3 |
+                              asyh->dither.bits << 1 |
+                              asyh->dither.enable);
                evo_kick(push, core);
        }
 }
 
-static void
+void
 head507d_ovly(struct nv50_head *head, struct nv50_head_atom *asyh)
 {
        struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan;
@@ -97,16 +69,13 @@ head507d_ovly(struct nv50_head *head, struct nv50_head_atom *asyh)
        }
 
        if ((push = evo_wait(core, 2))) {
-               if (core->base.user.oclass < GF110_DISP_CORE_CHANNEL_DMA)
-                       evo_mthd(push, 0x0904 + head->base.index * 0x400, 1);
-               else
-                       evo_mthd(push, 0x04d4 + head->base.index * 0x300, 1);
+               evo_mthd(push, 0x0904 + head->base.index * 0x400, 1);
                evo_data(push, bounds);
                evo_kick(push, core);
        }
 }
 
-static void
+void
 head507d_base(struct nv50_head *head, struct nv50_head_atom *asyh)
 {
        struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan;
@@ -127,10 +96,7 @@ head507d_base(struct nv50_head *head, struct nv50_head_atom *asyh)
        }
 
        if ((push = evo_wait(core, 2))) {
-               if (core->base.user.oclass < GF110_DISP_CORE_CHANNEL_DMA)
-                       evo_mthd(push, 0x0900 + head->base.index * 0x400, 1);
-               else
-                       evo_mthd(push, 0x04d0 + head->base.index * 0x300, 1);
+               evo_mthd(push, 0x0900 + head->base.index * 0x400, 1);
                evo_data(push, bounds);
                evo_kick(push, core);
        }
@@ -141,22 +107,9 @@ head507d_curs_clr(struct nv50_head *head)
 {
        struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan;
        u32 *push;
-       if ((push = evo_wait(core, 4))) {
-               if (core->base.user.oclass < G82_DISP_CORE_CHANNEL_DMA) {
-                       evo_mthd(push, 0x0880 + head->base.index * 0x400, 1);
-                       evo_data(push, 0x05000000);
-               } else
-               if (core->base.user.oclass < GF110_DISP_CORE_CHANNEL_DMA) {
-                       evo_mthd(push, 0x0880 + head->base.index * 0x400, 1);
-                       evo_data(push, 0x05000000);
-                       evo_mthd(push, 0x089c + head->base.index * 0x400, 1);
-                       evo_data(push, 0x00000000);
-               } else {
-                       evo_mthd(push, 0x0480 + head->base.index * 0x300, 1);
-                       evo_data(push, 0x05000000);
-                       evo_mthd(push, 0x048c + head->base.index * 0x300, 1);
-                       evo_data(push, 0x00000000);
-               }
+       if ((push = evo_wait(core, 2))) {
+               evo_mthd(push, 0x0880 + head->base.index * 0x400, 1);
+               evo_data(push, 0x05000000);
                evo_kick(push, core);
        }
 }
@@ -166,42 +119,22 @@ head507d_curs_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, 5))) {
-               if (core->base.user.oclass < G82_DISP_BASE_CHANNEL_DMA) {
-                       evo_mthd(push, 0x0880 + head->base.index * 0x400, 2);
-                       evo_data(push, 0x80000000 | (asyh->curs.layout << 26) |
-                                                   (asyh->curs.format << 24));
-                       evo_data(push, asyh->curs.offset >> 8);
-               } else
-               if (core->base.user.oclass < GF110_DISP_BASE_CHANNEL_DMA) {
-                       evo_mthd(push, 0x0880 + head->base.index * 0x400, 2);
-                       evo_data(push, 0x80000000 | (asyh->curs.layout << 26) |
-                                                   (asyh->curs.format << 24));
-                       evo_data(push, asyh->curs.offset >> 8);
-                       evo_mthd(push, 0x089c + head->base.index * 0x400, 1);
-                       evo_data(push, asyh->curs.handle);
-               } else {
-                       evo_mthd(push, 0x0480 + head->base.index * 0x300, 2);
-                       evo_data(push, 0x80000000 | (asyh->curs.layout << 26) |
-                                                   (asyh->curs.format << 24));
-                       evo_data(push, asyh->curs.offset >> 8);
-                       evo_mthd(push, 0x048c + head->base.index * 0x300, 1);
-                       evo_data(push, asyh->curs.handle);
-               }
+       if ((push = evo_wait(core, 3))) {
+               evo_mthd(push, 0x0880 + head->base.index * 0x400, 2);
+               evo_data(push, 0x80000000 | asyh->curs.layout << 26 |
+                                           asyh->curs.format << 24);
+               evo_data(push, asyh->curs.offset >> 8);
                evo_kick(push, core);
        }
 }
 
-static void
+void
 head507d_core_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))) {
-               if (core->base.user.oclass < GF110_DISP_CORE_CHANNEL_DMA)
-                       evo_mthd(push, 0x0874 + head->base.index * 0x400, 1);
-               else
-                       evo_mthd(push, 0x0474 + head->base.index * 0x300, 1);
+               evo_mthd(push, 0x0874 + head->base.index * 0x400, 1);
                evo_data(push, 0x00000000);
                evo_kick(push, core);
        }
@@ -213,52 +146,57 @@ head507d_core_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, 9))) {
-               if (core->base.user.oclass < G82_DISP_CORE_CHANNEL_DMA) {
-                       evo_mthd(push, 0x0860 + head->base.index * 0x400, 1);
-                       evo_data(push, asyh->core.offset >> 8);
-                       evo_mthd(push, 0x0868 + head->base.index * 0x400, 4);
-                       evo_data(push, (asyh->core.h << 16) | asyh->core.w);
-                       evo_data(push, asyh->core.layout << 20 |
-                                      (asyh->core.pitch >> 8) << 8 |
-                                      asyh->core.block);
-                       evo_data(push, asyh->core.kind << 16 |
-                                      asyh->core.format << 8);
-                       evo_data(push, asyh->core.handle);
-                       evo_mthd(push, 0x08c0 + head->base.index * 0x400, 1);
-                       evo_data(push, (asyh->core.y << 16) | asyh->core.x);
-                       /* EVO will complain with INVALID_STATE if we have an
-                        * active cursor and (re)specify HeadSetContextDmaIso
-                        * without also updating HeadSetOffsetCursor.
-                        */
-                       asyh->set.curs = asyh->curs.visible;
-               } else
-               if (core->base.user.oclass < GF110_DISP_CORE_CHANNEL_DMA) {
-                       evo_mthd(push, 0x0860 + head->base.index * 0x400, 1);
-                       evo_data(push, asyh->core.offset >> 8);
-                       evo_mthd(push, 0x0868 + head->base.index * 0x400, 4);
-                       evo_data(push, (asyh->core.h << 16) | asyh->core.w);
-                       evo_data(push, asyh->core.layout << 20 |
-                                      (asyh->core.pitch >> 8) << 8 |
-                                      asyh->core.block);
-                       evo_data(push, asyh->core.format << 8);
-                       evo_data(push, asyh->core.handle);
-                       evo_mthd(push, 0x08c0 + head->base.index * 0x400, 1);
-                       evo_data(push, (asyh->core.y << 16) | asyh->core.x);
-               } else {
-                       evo_mthd(push, 0x0460 + head->base.index * 0x300, 1);
-                       evo_data(push, asyh->core.offset >> 8);
-                       evo_mthd(push, 0x0468 + head->base.index * 0x300, 4);
-                       evo_data(push, (asyh->core.h << 16) | asyh->core.w);
-                       evo_data(push, asyh->core.layout << 24 |
-                                      (asyh->core.pitch >> 8) << 8 |
-                                      asyh->core.block);
-                       evo_data(push, asyh->core.format << 8);
-                       evo_data(push, asyh->core.handle);
-                       evo_mthd(push, 0x04b0 + head->base.index * 0x300, 1);
-                       evo_data(push, (asyh->core.y << 16) | asyh->core.x);
-               }
+               evo_mthd(push, 0x0860 + head->base.index * 0x400, 1);
+               evo_data(push, asyh->core.offset >> 8);
+               evo_mthd(push, 0x0868 + head->base.index * 0x400, 4);
+               evo_data(push, asyh->core.h << 16 | asyh->core.w);
+               evo_data(push, asyh->core.layout << 20 |
+                              asyh->core.pitch >> 8 << 8 |
+                              asyh->core.block);
+               evo_data(push, asyh->core.kind << 16 |
+                              asyh->core.format << 8);
+               evo_data(push, asyh->core.handle);
+               evo_mthd(push, 0x08c0 + head->base.index * 0x400, 1);
+               evo_data(push, asyh->core.y << 16 | asyh->core.x);
                evo_kick(push, core);
+
+               /* EVO will complain with INVALID_STATE if we have an
+                * active cursor and (re)specify HeadSetContextDmaIso
+                * without also updating HeadSetOffsetCursor.
+                */
+               asyh->set.curs = asyh->curs.visible;
+       }
+}
+
+void
+head507d_core_calc(struct nv50_head *head, struct nv50_head_atom *asyh)
+{
+       struct nv50_disp *disp = nv50_disp(head->base.base.dev);
+       if ((asyh->core.visible = (asyh->base.cpp != 0))) {
+               asyh->core.x = asyh->base.x;
+               asyh->core.y = asyh->base.y;
+               asyh->core.w = asyh->base.w;
+               asyh->core.h = asyh->base.h;
+       } else
+       if ((asyh->core.visible = asyh->curs.visible) ||
+           (asyh->core.visible = asyh->ilut.visible)) {
+               /*XXX: We need to either find some way of having the
+                *     primary base layer appear black, while still
+                *     being able to display the other layers, or we
+                *     need to allocate a dummy black surface here.
+                */
+               asyh->core.x = 0;
+               asyh->core.y = 0;
+               asyh->core.w = asyh->state.mode.hdisplay;
+               asyh->core.h = asyh->state.mode.vdisplay;
        }
+       asyh->core.handle = disp->core->chan.vram.handle;
+       asyh->core.offset = 0;
+       asyh->core.format = 0xcf;
+       asyh->core.kind = 0;
+       asyh->core.layout = 1;
+       asyh->core.block = 0;
+       asyh->core.pitch = ALIGN(asyh->core.w, 64) * 4;
 }
 
 static void
@@ -266,22 +204,9 @@ head507d_ilut_clr(struct nv50_head *head)
 {
        struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan;
        u32 *push;
-       if ((push = evo_wait(core, 4))) {
-               if (core->base.user.oclass < G82_DISP_CORE_CHANNEL_DMA) {
-                       evo_mthd(push, 0x0840 + (head->base.index * 0x400), 1);
-                       evo_data(push, 0x40000000);
-               } else
-               if (core->base.user.oclass < GF110_DISP_CORE_CHANNEL_DMA) {
-                       evo_mthd(push, 0x0840 + (head->base.index * 0x400), 1);
-                       evo_data(push, 0x40000000);
-                       evo_mthd(push, 0x085c + (head->base.index * 0x400), 1);
-                       evo_data(push, 0x00000000);
-               } else {
-                       evo_mthd(push, 0x0440 + (head->base.index * 0x300), 1);
-                       evo_data(push, 0x03000000);
-                       evo_mthd(push, 0x045c + (head->base.index * 0x300), 1);
-                       evo_data(push, 0x00000000);
-               }
+       if ((push = evo_wait(core, 2))) {
+               evo_mthd(push, 0x0840 + (head->base.index * 0x400), 1);
+               evo_data(push, 0x40000000);
                evo_kick(push, core);
        }
 }
@@ -291,96 +216,51 @@ head507d_ilut_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, 7))) {
-               if (core->base.user.oclass < G82_DISP_CORE_CHANNEL_DMA) {
-                       evo_mthd(push, 0x0840 + (head->base.index * 0x400), 2);
-                       evo_data(push, 0x80000000 | asyh->ilut.mode << 30);
-                       evo_data(push, asyh->ilut.offset >> 8);
-               } else
-               if (core->base.user.oclass < GF110_DISP_CORE_CHANNEL_DMA) {
-                       evo_mthd(push, 0x0840 + (head->base.index * 0x400), 2);
-                       evo_data(push, 0x80000000 | asyh->ilut.mode << 30);
-                       evo_data(push, asyh->ilut.offset >> 8);
-                       evo_mthd(push, 0x085c + (head->base.index * 0x400), 1);
-                       evo_data(push, asyh->ilut.handle);
-               } else {
-                       evo_mthd(push, 0x0440 + (head->base.index * 0x300), 4);
-                       evo_data(push, 0x80000000 | asyh->ilut.mode << 24);
-                       evo_data(push, asyh->ilut.offset >> 8);
-                       evo_data(push, 0x00000000);
-                       evo_data(push, 0x00000000);
-                       evo_mthd(push, 0x045c + (head->base.index * 0x300), 1);
-                       evo_data(push, asyh->ilut.handle);
-               }
+       if ((push = evo_wait(core, 3))) {
+               evo_mthd(push, 0x0840 + (head->base.index * 0x400), 2);
+               evo_data(push, 0x80000000 | asyh->ilut.mode << 30);
+               evo_data(push, asyh->ilut.offset >> 8);
                evo_kick(push, core);
        }
 }
 
-static void
+void
 head507d_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, 14))) {
-               if (core->base.user.oclass < GF110_DISP_CORE_CHANNEL_DMA) {
-                       evo_mthd(push, 0x0804 + (head->base.index * 0x400), 2);
-                       evo_data(push, 0x00800000 | m->clock);
-                       evo_data(push, m->interlace ? 0x00000002 : 0x00000000);
-                       evo_mthd(push, 0x0810 + (head->base.index * 0x400), 7);
-                       evo_data(push, 0x00000000);
-                       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_data(push, asyh->mode.v.blankus);
-                       evo_mthd(push, 0x082c + (head->base.index * 0x400), 1);
-                       evo_data(push, 0x00000000);
-               } else {
-                       evo_mthd(push, 0x0410 + (head->base.index * 0x300), 6);
-                       evo_data(push, 0x00000000);
-                       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, 0x042c + (head->base.index * 0x300), 2);
-                       evo_data(push, 0x00000000); /* ??? */
-                       evo_data(push, 0xffffff00);
-                       evo_mthd(push, 0x0450 + (head->base.index * 0x300), 3);
-                       evo_data(push, m->clock * 1000);
-                       evo_data(push, 0x00200000); /* ??? */
-                       evo_data(push, m->clock * 1000);
-               }
+       if ((push = evo_wait(core, 13))) {
+               evo_mthd(push, 0x0804 + (head->base.index * 0x400), 2);
+               evo_data(push, 0x00800000 | m->clock);
+               evo_data(push, m->interlace ? 0x00000002 : 0x00000000);
+               evo_mthd(push, 0x0810 + (head->base.index * 0x400), 7);
+               evo_data(push, 0x00000000);
+               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_data(push, asyh->mode.v.blankus);
+               evo_mthd(push, 0x082c + (head->base.index * 0x400), 1);
+               evo_data(push, 0x00000000);
                evo_kick(push, core);
        }
 }
 
-static void
+void
 head507d_view(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, 10))) {
-               if (core->base.user.oclass < GF110_DISP_CORE_CHANNEL_DMA) {
-                       evo_mthd(push, 0x08a4 + (head->base.index * 0x400), 1);
-                       evo_data(push, 0x00000000);
-                       evo_mthd(push, 0x08c8 + (head->base.index * 0x400), 1);
-                       evo_data(push, (asyh->view.iH << 16) | asyh->view.iW);
-                       evo_mthd(push, 0x08d8 + (head->base.index * 0x400), 2);
-                       evo_data(push, (asyh->view.oH << 16) | asyh->view.oW);
-                       evo_data(push, (asyh->view.oH << 16) | asyh->view.oW);
-               } else {
-                       evo_mthd(push, 0x0494 + (head->base.index * 0x300), 1);
-                       evo_data(push, 0x00000000);
-                       evo_mthd(push, 0x04b8 + (head->base.index * 0x300), 1);
-                       evo_data(push, (asyh->view.iH << 16) | asyh->view.iW);
-                       evo_mthd(push, 0x04c0 + (head->base.index * 0x300), 3);
-                       evo_data(push, (asyh->view.oH << 16) | asyh->view.oW);
-                       evo_data(push, (asyh->view.oH << 16) | asyh->view.oW);
-                       evo_data(push, (asyh->view.oH << 16) | asyh->view.oW);
-               }
+       if ((push = evo_wait(core, 7))) {
+               evo_mthd(push, 0x08a4 + (head->base.index * 0x400), 1);
+               evo_data(push, 0x00000000);
+               evo_mthd(push, 0x08c8 + (head->base.index * 0x400), 1);
+               evo_data(push, asyh->view.iH << 16 | asyh->view.iW);
+               evo_mthd(push, 0x08d8 + (head->base.index * 0x400), 2);
+               evo_data(push, asyh->view.oH << 16 | asyh->view.oW);
+               evo_data(push, asyh->view.oH << 16 | asyh->view.oW);
                evo_kick(push, core);
        }
 }
@@ -391,6 +271,7 @@ head507d = {
        .mode = head507d_mode,
        .ilut_set = head507d_ilut_set,
        .ilut_clr = head507d_ilut_clr,
+       .core_calc = head507d_core_calc,
        .core_set = head507d_core_set,
        .core_clr = head507d_core_clr,
        .curs_set = head507d_curs_set,
@@ -399,5 +280,4 @@ head507d = {
        .ovly = head507d_ovly,
        .dither = head507d_dither,
        .procamp = head507d_procamp,
-       .or = head907d_or,
 };
diff --git a/drivers/gpu/drm/nouveau/dispnv50/head827d.c b/drivers/gpu/drm/nouveau/dispnv50/head827d.c
new file mode 100644 (file)
index 0000000..84ce595
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ * 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 "core.h"
+
+static void
+head827d_curs_clr(struct nv50_head *head)
+{
+       struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan;
+       u32 *push;
+       if ((push = evo_wait(core, 4))) {
+               evo_mthd(push, 0x0880 + head->base.index * 0x400, 1);
+               evo_data(push, 0x05000000);
+               evo_mthd(push, 0x089c + head->base.index * 0x400, 1);
+               evo_data(push, 0x00000000);
+               evo_kick(push, core);
+       }
+}
+
+static void
+head827d_curs_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, 5))) {
+               evo_mthd(push, 0x0880 + head->base.index * 0x400, 2);
+               evo_data(push, 0x80000000 | asyh->curs.layout << 26 |
+                                           asyh->curs.format << 24);
+               evo_data(push, asyh->curs.offset >> 8);
+               evo_mthd(push, 0x089c + head->base.index * 0x400, 1);
+               evo_data(push, asyh->curs.handle);
+               evo_kick(push, core);
+       }
+}
+
+static void
+head827d_core_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, 9))) {
+               evo_mthd(push, 0x0860 + head->base.index * 0x400, 1);
+               evo_data(push, asyh->core.offset >> 8);
+               evo_mthd(push, 0x0868 + head->base.index * 0x400, 4);
+               evo_data(push, asyh->core.h << 16 | asyh->core.w);
+               evo_data(push, asyh->core.layout << 20 |
+                              (asyh->core.pitch >> 8) << 8 |
+                              asyh->core.block);
+               evo_data(push, asyh->core.format << 8);
+               evo_data(push, asyh->core.handle);
+               evo_mthd(push, 0x08c0 + head->base.index * 0x400, 1);
+               evo_data(push, asyh->core.y << 16 | asyh->core.x);
+               evo_kick(push, core);
+       }
+}
+
+static void
+head827d_ilut_clr(struct nv50_head *head)
+{
+       struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan;
+       u32 *push;
+       if ((push = evo_wait(core, 4))) {
+               evo_mthd(push, 0x0840 + (head->base.index * 0x400), 1);
+               evo_data(push, 0x40000000);
+               evo_mthd(push, 0x085c + (head->base.index * 0x400), 1);
+               evo_data(push, 0x00000000);
+               evo_kick(push, core);
+       }
+}
+
+static void
+head827d_ilut_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, 5))) {
+               evo_mthd(push, 0x0840 + (head->base.index * 0x400), 2);
+               evo_data(push, 0x80000000 | asyh->ilut.mode << 30);
+               evo_data(push, asyh->ilut.offset >> 8);
+               evo_mthd(push, 0x085c + (head->base.index * 0x400), 1);
+               evo_data(push, asyh->ilut.handle);
+               evo_kick(push, core);
+       }
+}
+
+const struct nv50_head_func
+head827d = {
+       .view = head507d_view,
+       .mode = head507d_mode,
+       .ilut_set = head827d_ilut_set,
+       .ilut_clr = head827d_ilut_clr,
+       .core_calc = head507d_core_calc,
+       .core_set = head827d_core_set,
+       .core_clr = head507d_core_clr,
+       .curs_set = head827d_curs_set,
+       .curs_clr = head827d_curs_clr,
+       .base = head507d_base,
+       .ovly = head507d_ovly,
+       .dither = head507d_dither,
+       .procamp = head507d_procamp,
+};
diff --git a/drivers/gpu/drm/nouveau/dispnv50/head907d.c b/drivers/gpu/drm/nouveau/dispnv50/head907d.c
new file mode 100644 (file)
index 0000000..0035ecc
--- /dev/null
@@ -0,0 +1,274 @@
+/*
+ * 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 "core.h"
+
+void
+head907d_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, 3))) {
+               evo_mthd(push, 0x0404 + (head->base.index * 0x300), 2);
+               evo_data(push, 0x00000001 | asyh->or.depth  << 6 |
+                                           asyh->or.nvsync << 4 |
+                                           asyh->or.nhsync << 3);
+               evo_data(push, 0x31ec6000 | head->base.index << 25 |
+                                           asyh->mode.interlace);
+               evo_kick(push, core);
+       }
+}
+
+void
+head907d_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, 0x0498 + (head->base.index * 0x300), 1);
+               evo_data(push, asyh->procamp.sat.sin << 20 |
+                              asyh->procamp.sat.cos << 8);
+               evo_kick(push, core);
+       }
+}
+
+static void
+head907d_dither(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, 0x0490 + (head->base.index * 0x0300), 1);
+               evo_data(push, asyh->dither.mode << 3 |
+                              asyh->dither.bits << 1 |
+                              asyh->dither.enable);
+               evo_kick(push, core);
+       }
+}
+
+void
+head907d_ovly(struct nv50_head *head, struct nv50_head_atom *asyh)
+{
+       struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan;
+       u32 bounds = 0;
+       u32 *push;
+
+       if (asyh->ovly.cpp) {
+               switch (asyh->ovly.cpp) {
+               case 8: bounds |= 0x00000500; break;
+               case 4: bounds |= 0x00000300; break;
+               case 2: bounds |= 0x00000100; break;
+               default:
+                       WARN_ON(1);
+                       break;
+               }
+               bounds |= 0x00000001;
+       }
+
+       if ((push = evo_wait(core, 2))) {
+               evo_mthd(push, 0x04d4 + head->base.index * 0x300, 1);
+               evo_data(push, bounds);
+               evo_kick(push, core);
+       }
+}
+
+void
+head907d_base(struct nv50_head *head, struct nv50_head_atom *asyh)
+{
+       struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan;
+       u32 bounds = 0;
+       u32 *push;
+
+       if (asyh->base.cpp) {
+               switch (asyh->base.cpp) {
+               case 8: bounds |= 0x00000500; break;
+               case 4: bounds |= 0x00000300; break;
+               case 2: bounds |= 0x00000100; break;
+               case 1: bounds |= 0x00000000; break;
+               default:
+                       WARN_ON(1);
+                       break;
+               }
+               bounds |= 0x00000001;
+       }
+
+       if ((push = evo_wait(core, 2))) {
+               evo_mthd(push, 0x04d0 + head->base.index * 0x300, 1);
+               evo_data(push, bounds);
+               evo_kick(push, core);
+       }
+}
+
+void
+head907d_curs_clr(struct nv50_head *head)
+{
+       struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan;
+       u32 *push;
+       if ((push = evo_wait(core, 4))) {
+               evo_mthd(push, 0x0480 + head->base.index * 0x300, 1);
+               evo_data(push, 0x05000000);
+               evo_mthd(push, 0x048c + head->base.index * 0x300, 1);
+               evo_data(push, 0x00000000);
+               evo_kick(push, core);
+       }
+}
+
+void
+head907d_curs_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, 5))) {
+               evo_mthd(push, 0x0480 + head->base.index * 0x300, 2);
+               evo_data(push, 0x80000000 | asyh->curs.layout << 26 |
+                                           asyh->curs.format << 24);
+               evo_data(push, asyh->curs.offset >> 8);
+               evo_mthd(push, 0x048c + head->base.index * 0x300, 1);
+               evo_data(push, asyh->curs.handle);
+               evo_kick(push, core);
+       }
+}
+
+void
+head907d_core_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, 0x0474 + head->base.index * 0x300, 1);
+               evo_data(push, 0x00000000);
+               evo_kick(push, core);
+       }
+}
+
+void
+head907d_core_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, 9))) {
+               evo_mthd(push, 0x0460 + head->base.index * 0x300, 1);
+               evo_data(push, asyh->core.offset >> 8);
+               evo_mthd(push, 0x0468 + head->base.index * 0x300, 4);
+               evo_data(push, asyh->core.h << 16 | asyh->core.w);
+               evo_data(push, asyh->core.layout << 24 |
+                              (asyh->core.pitch >> 8) << 8 |
+                              asyh->core.block);
+               evo_data(push, asyh->core.format << 8);
+               evo_data(push, asyh->core.handle);
+               evo_mthd(push, 0x04b0 + head->base.index * 0x300, 1);
+               evo_data(push, asyh->core.y << 16 | asyh->core.x);
+               evo_kick(push, core);
+       }
+}
+
+void
+head907d_ilut_clr(struct nv50_head *head)
+{
+       struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan;
+       u32 *push;
+       if ((push = evo_wait(core, 4))) {
+               evo_mthd(push, 0x0440 + (head->base.index * 0x300), 1);
+               evo_data(push, 0x03000000);
+               evo_mthd(push, 0x045c + (head->base.index * 0x300), 1);
+               evo_data(push, 0x00000000);
+               evo_kick(push, core);
+       }
+}
+
+void
+head907d_ilut_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, 7))) {
+               evo_mthd(push, 0x0440 + (head->base.index * 0x300), 4);
+               evo_data(push, 0x80000000 | asyh->ilut.mode << 24);
+               evo_data(push, asyh->ilut.offset >> 8);
+               evo_data(push, 0x00000000);
+               evo_data(push, 0x00000000);
+               evo_mthd(push, 0x045c + (head->base.index * 0x300), 1);
+               evo_data(push, asyh->ilut.handle);
+               evo_kick(push, core);
+       }
+}
+
+void
+head907d_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, 14))) {
+               evo_mthd(push, 0x0410 + (head->base.index * 0x300), 6);
+               evo_data(push, 0x00000000);
+               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, 0x042c + (head->base.index * 0x300), 2);
+               evo_data(push, 0x00000000); /* ??? */
+               evo_data(push, 0xffffff00);
+               evo_mthd(push, 0x0450 + (head->base.index * 0x300), 3);
+               evo_data(push, m->clock * 1000);
+               evo_data(push, 0x00200000); /* ??? */
+               evo_data(push, m->clock * 1000);
+               evo_kick(push, core);
+       }
+}
+
+void
+head907d_view(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, 8))) {
+               evo_mthd(push, 0x0494 + (head->base.index * 0x300), 1);
+               evo_data(push, 0x00000000);
+               evo_mthd(push, 0x04b8 + (head->base.index * 0x300), 1);
+               evo_data(push, asyh->view.iH << 16 | asyh->view.iW);
+               evo_mthd(push, 0x04c0 + (head->base.index * 0x300), 3);
+               evo_data(push, asyh->view.oH << 16 | asyh->view.oW);
+               evo_data(push, asyh->view.oH << 16 | asyh->view.oW);
+               evo_data(push, asyh->view.oH << 16 | asyh->view.oW);
+               evo_kick(push, core);
+       }
+}
+
+const struct nv50_head_func
+head907d = {
+       .view = head907d_view,
+       .mode = head907d_mode,
+       .ilut_set = head907d_ilut_set,
+       .ilut_clr = head907d_ilut_clr,
+       .core_calc = head507d_core_calc,
+       .core_set = head907d_core_set,
+       .core_clr = head907d_core_clr,
+       .curs_set = head907d_curs_set,
+       .curs_clr = head907d_curs_clr,
+       .base = head907d_base,
+       .ovly = head907d_ovly,
+       .dither = head907d_dither,
+       .procamp = head907d_procamp,
+       .or = head907d_or,
+};
diff --git a/drivers/gpu/drm/nouveau/dispnv50/head917d.c b/drivers/gpu/drm/nouveau/dispnv50/head917d.c
new file mode 100644 (file)
index 0000000..5341ea3
--- /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 "head.h"
+#include "core.h"
+
+static void
+head917d_dither(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, 0x04a0 + (head->base.index * 0x0300), 1);
+               evo_data(push, asyh->dither.mode << 3 |
+                              asyh->dither.bits << 1 |
+                              asyh->dither.enable);
+               evo_kick(push, core);
+       }
+}
+
+const struct nv50_head_func
+head917d = {
+       .view = head907d_view,
+       .mode = head907d_mode,
+       .ilut_set = head907d_ilut_set,
+       .ilut_clr = head907d_ilut_clr,
+       .core_calc = head507d_core_calc,
+       .core_set = head907d_core_set,
+       .core_clr = head907d_core_clr,
+       .curs_set = head907d_curs_set,
+       .curs_clr = head907d_curs_clr,
+       .base = head907d_base,
+       .ovly = head907d_ovly,
+       .dither = head917d_dither,
+       .procamp = head907d_procamp,
+       .or = head907d_or,
+};
index a99ba6a7216f5cef9d9b3f11e08121eaf6fb5515..d2bac6a341dcb696204016f1c17fd00dd4357d77 100644 (file)
  */
 #include "core.h"
 
-#include <nvif/class.h>
-
 static void
 pior507d_ctrl(struct nv50_core *core, int or, u32 ctrl,
              struct nv50_head_atom *asyh)
 {
        u32 *push;
-       if ((push = evo_wait(&core->chan, 8))) {
-               if (core->chan.base.user.oclass < GF110_DISP_CORE_CHANNEL_DMA) {
-                       if (asyh) {
-                               ctrl |= asyh->or.depth  << 16;
-                               ctrl |= asyh->or.nvsync << 13;
-                               ctrl |= asyh->or.nhsync << 12;
-                       }
-                       evo_mthd(push, 0x0700 + (or * 0x040), 1);
-                       evo_data(push, ctrl);
+       if ((push = evo_wait(&core->chan, 2))) {
+               if (asyh) {
+                       ctrl |= asyh->or.depth  << 16;
+                       ctrl |= asyh->or.nvsync << 13;
+                       ctrl |= asyh->or.nhsync << 12;
                }
+               evo_mthd(push, 0x0700 + (or * 0x040), 1);
+               evo_data(push, ctrl);
                evo_kick(push, &core->chan);
        }
 }
index 2d540de27f5924fb0b3ff5016d3cce81770d5e7f..5222fe6a9b21cd4ca1e7e064af14c2c3d94c8a82 100644 (file)
  */
 #include "core.h"
 
-#include <nvif/class.h>
-
 static void
 sor507d_ctrl(struct nv50_core *core, int or, u32 ctrl,
             struct nv50_head_atom *asyh)
 {
        u32 *push;
-       if ((push = evo_wait(&core->chan, 6))) {
-               if (core->chan.base.user.oclass < GF110_DISP_CORE_CHANNEL_DMA) {
-                       if (asyh) {
-                               ctrl |= asyh->or.depth  << 16;
-                               ctrl |= asyh->or.nvsync << 13;
-                               ctrl |= asyh->or.nhsync << 12;
-                       }
-                       evo_mthd(push, 0x0600 + (or * 0x40), 1);
-               } else {
-                       evo_mthd(push, 0x0200 + (or * 0x20), 1);
+       if ((push = evo_wait(&core->chan, 2))) {
+               if (asyh) {
+                       ctrl |= asyh->or.depth  << 16;
+                       ctrl |= asyh->or.nvsync << 13;
+                       ctrl |= asyh->or.nhsync << 12;
                }
+               evo_mthd(push, 0x0600 + (or * 0x40), 1);
                evo_data(push, ctrl);
                evo_kick(push, &core->chan);
        }
diff --git a/drivers/gpu/drm/nouveau/dispnv50/sor907d.c b/drivers/gpu/drm/nouveau/dispnv50/sor907d.c
new file mode 100644 (file)
index 0000000..b0314ec
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * 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 <nvif/class.h>
+
+static void
+sor907d_ctrl(struct nv50_core *core, int or, u32 ctrl,
+            struct nv50_head_atom *asyh)
+{
+       u32 *push;
+       if ((push = evo_wait(&core->chan, 2))) {
+               evo_mthd(push, 0x0200 + (or * 0x20), 1);
+               evo_data(push, ctrl);
+               evo_kick(push, &core->chan);
+       }
+}
+
+const struct nv50_outp_func
+sor907d = {
+       .ctrl = sor907d_ctrl,
+};