diff options
Diffstat (limited to 'drivers/gpu/drm/nouveau/nvkm')
91 files changed, 5150 insertions, 6821 deletions
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild b/drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild index 314e68c750a4..4b24c1eade5f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild @@ -1,5 +1,14 @@ # SPDX-License-Identifier: MIT nvkm-y += nvkm/engine/disp/base.o +nvkm-y += nvkm/engine/disp/chan.o +nvkm-y += nvkm/engine/disp/conn.o +nvkm-y += nvkm/engine/disp/dp.o +nvkm-y += nvkm/engine/disp/hdmi.o +nvkm-y += nvkm/engine/disp/head.o +nvkm-y += nvkm/engine/disp/ior.o +nvkm-y += nvkm/engine/disp/outp.o +nvkm-y += nvkm/engine/disp/vga.o + nvkm-y += nvkm/engine/disp/nv04.o nvkm-y += nvkm/engine/disp/nv50.o nvkm-y += nvkm/engine/disp/g84.o @@ -18,98 +27,8 @@ nvkm-y += nvkm/engine/disp/gp102.o nvkm-y += nvkm/engine/disp/gv100.o nvkm-y += nvkm/engine/disp/tu102.o nvkm-y += nvkm/engine/disp/ga102.o -nvkm-y += nvkm/engine/disp/vga.o - -nvkm-y += nvkm/engine/disp/head.o -nvkm-y += nvkm/engine/disp/headnv04.o -nvkm-y += nvkm/engine/disp/headnv50.o -nvkm-y += nvkm/engine/disp/headgf119.o -nvkm-y += nvkm/engine/disp/headgv100.o - -nvkm-y += nvkm/engine/disp/ior.o -nvkm-y += nvkm/engine/disp/dacnv50.o -nvkm-y += nvkm/engine/disp/dacgf119.o -nvkm-y += nvkm/engine/disp/piornv50.o -nvkm-y += nvkm/engine/disp/sornv50.o -nvkm-y += nvkm/engine/disp/sorg84.o -nvkm-y += nvkm/engine/disp/sorg94.o -nvkm-y += nvkm/engine/disp/sormcp77.o -nvkm-y += nvkm/engine/disp/sorgt215.o -nvkm-y += nvkm/engine/disp/sormcp89.o -nvkm-y += nvkm/engine/disp/sorgf119.o -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/sorgp100.o -nvkm-y += nvkm/engine/disp/sorgv100.o -nvkm-y += nvkm/engine/disp/sortu102.o -nvkm-y += nvkm/engine/disp/sorga102.o - -nvkm-y += nvkm/engine/disp/outp.o -nvkm-y += nvkm/engine/disp/dp.o - -nvkm-y += nvkm/engine/disp/hdagt215.o -nvkm-y += nvkm/engine/disp/hdagf119.o -nvkm-y += nvkm/engine/disp/hdagv100.o - -nvkm-y += nvkm/engine/disp/hdmi.o -nvkm-y += nvkm/engine/disp/hdmig84.o -nvkm-y += nvkm/engine/disp/hdmigt215.o -nvkm-y += nvkm/engine/disp/hdmigf119.o -nvkm-y += nvkm/engine/disp/hdmigk104.o -nvkm-y += nvkm/engine/disp/hdmigm200.o -nvkm-y += nvkm/engine/disp/hdmigv100.o - -nvkm-y += nvkm/engine/disp/conn.o nvkm-y += nvkm/engine/disp/rootnv04.o nvkm-y += nvkm/engine/disp/rootnv50.o -nvkm-y += nvkm/engine/disp/capsgv100.o - -nvkm-y += nvkm/engine/disp/channv50.o -nvkm-y += nvkm/engine/disp/changf119.o -nvkm-y += nvkm/engine/disp/changv100.o - -nvkm-y += nvkm/engine/disp/dmacnv50.o -nvkm-y += nvkm/engine/disp/dmacgf119.o -nvkm-y += nvkm/engine/disp/dmacgp102.o -nvkm-y += nvkm/engine/disp/dmacgv100.o - -nvkm-y += nvkm/engine/disp/basenv50.o -nvkm-y += nvkm/engine/disp/baseg84.o -nvkm-y += nvkm/engine/disp/basegf119.o -nvkm-y += nvkm/engine/disp/basegp102.o - -nvkm-y += nvkm/engine/disp/corenv50.o -nvkm-y += nvkm/engine/disp/coreg84.o -nvkm-y += nvkm/engine/disp/coreg94.o -nvkm-y += nvkm/engine/disp/coregf119.o -nvkm-y += nvkm/engine/disp/coregk104.o -nvkm-y += nvkm/engine/disp/coregp102.o -nvkm-y += nvkm/engine/disp/coregv100.o - -nvkm-y += nvkm/engine/disp/ovlynv50.o -nvkm-y += nvkm/engine/disp/ovlyg84.o -nvkm-y += nvkm/engine/disp/ovlygt200.o -nvkm-y += nvkm/engine/disp/ovlygf119.o -nvkm-y += nvkm/engine/disp/ovlygk104.o -nvkm-y += nvkm/engine/disp/ovlygp102.o - -nvkm-y += nvkm/engine/disp/wimmgv100.o - -nvkm-y += nvkm/engine/disp/wndwgv100.o - -nvkm-y += nvkm/engine/disp/piocnv50.o -nvkm-y += nvkm/engine/disp/piocgf119.o - -nvkm-y += nvkm/engine/disp/cursnv50.o -nvkm-y += nvkm/engine/disp/cursgf119.o -nvkm-y += nvkm/engine/disp/cursgp102.o -nvkm-y += nvkm/engine/disp/cursgv100.o - -nvkm-y += nvkm/engine/disp/oimmnv50.o -nvkm-y += nvkm/engine/disp/oimmgf119.o -nvkm-y += nvkm/engine/disp/oimmgp102.o - nvkm-y += nvkm/engine/disp/udisp.o diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/baseg84.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/baseg84.c deleted file mode 100644 index 8848a0fc5069..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/baseg84.c +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright 2012 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. - * - * Authors: Ben Skeggs - */ -#include "channv50.h" - -static const struct nv50_disp_mthd_list -g84_disp_base_mthd_base = { - .mthd = 0x0000, - .addr = 0x000000, - .data = { - { 0x0080, 0x000000 }, - { 0x0084, 0x0008c4 }, - { 0x0088, 0x0008d0 }, - { 0x008c, 0x0008dc }, - { 0x0090, 0x0008e4 }, - { 0x0094, 0x610884 }, - { 0x00a0, 0x6108a0 }, - { 0x00a4, 0x610878 }, - { 0x00c0, 0x61086c }, - { 0x00c4, 0x610800 }, - { 0x00c8, 0x61080c }, - { 0x00cc, 0x610818 }, - { 0x00e0, 0x610858 }, - { 0x00e4, 0x610860 }, - { 0x00e8, 0x6108ac }, - { 0x00ec, 0x6108b4 }, - { 0x00fc, 0x610824 }, - { 0x0100, 0x610894 }, - { 0x0104, 0x61082c }, - { 0x0110, 0x6108bc }, - { 0x0114, 0x61088c }, - {} - } -}; - -static const struct nv50_disp_chan_mthd -g84_disp_base_mthd = { - .name = "Base", - .addr = 0x000540, - .prev = 0x000004, - .data = { - { "Global", 1, &g84_disp_base_mthd_base }, - { "Image", 2, &nv50_disp_base_mthd_image }, - {} - } -}; - -int -g84_disp_base_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nvkm_disp *disp, struct nvkm_object **pobject) -{ - return nv50_disp_base_new_(&nv50_disp_dmac_func, &g84_disp_base_mthd, - disp, 1, oclass, argv, argc, pobject); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/basegf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/basegf119.c deleted file mode 100644 index 721868d15739..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/basegf119.c +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright 2012 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. - * - * Authors: Ben Skeggs - */ -#include "channv50.h" - -static const struct nv50_disp_mthd_list -gf119_disp_base_mthd_base = { - .mthd = 0x0000, - .addr = 0x000000, - .data = { - { 0x0080, 0x661080 }, - { 0x0084, 0x661084 }, - { 0x0088, 0x661088 }, - { 0x008c, 0x66108c }, - { 0x0090, 0x661090 }, - { 0x0094, 0x661094 }, - { 0x00a0, 0x6610a0 }, - { 0x00a4, 0x6610a4 }, - { 0x00c0, 0x6610c0 }, - { 0x00c4, 0x6610c4 }, - { 0x00c8, 0x6610c8 }, - { 0x00cc, 0x6610cc }, - { 0x00e0, 0x6610e0 }, - { 0x00e4, 0x6610e4 }, - { 0x00e8, 0x6610e8 }, - { 0x00ec, 0x6610ec }, - { 0x00fc, 0x6610fc }, - { 0x0100, 0x661100 }, - { 0x0104, 0x661104 }, - { 0x0108, 0x661108 }, - { 0x010c, 0x66110c }, - { 0x0110, 0x661110 }, - { 0x0114, 0x661114 }, - { 0x0118, 0x661118 }, - { 0x011c, 0x66111c }, - { 0x0130, 0x661130 }, - { 0x0134, 0x661134 }, - { 0x0138, 0x661138 }, - { 0x013c, 0x66113c }, - { 0x0140, 0x661140 }, - { 0x0144, 0x661144 }, - { 0x0148, 0x661148 }, - { 0x014c, 0x66114c }, - { 0x0150, 0x661150 }, - { 0x0154, 0x661154 }, - { 0x0158, 0x661158 }, - { 0x015c, 0x66115c }, - { 0x0160, 0x661160 }, - { 0x0164, 0x661164 }, - { 0x0168, 0x661168 }, - { 0x016c, 0x66116c }, - {} - } -}; - -static const struct nv50_disp_mthd_list -gf119_disp_base_mthd_image = { - .mthd = 0x0020, - .addr = 0x000020, - .data = { - { 0x0400, 0x661400 }, - { 0x0404, 0x661404 }, - { 0x0408, 0x661408 }, - { 0x040c, 0x66140c }, - { 0x0410, 0x661410 }, - {} - } -}; - -const struct nv50_disp_chan_mthd -gf119_disp_base_mthd = { - .name = "Base", - .addr = 0x001000, - .prev = -0x020000, - .data = { - { "Global", 1, &gf119_disp_base_mthd_base }, - { "Image", 2, &gf119_disp_base_mthd_image }, - {} - } -}; - -int -gf119_disp_base_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nvkm_disp *disp, struct nvkm_object **pobject) -{ - return nv50_disp_base_new_(&gf119_disp_dmac_func, &gf119_disp_base_mthd, - disp, 1, oclass, argv, argc, pobject); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/basegp102.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/basegp102.c deleted file mode 100644 index 7afd99b7e832..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/basegp102.c +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2016 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. - * - * Authors: Ben Skeggs <bskeggs@redhat.com> - */ -#include "channv50.h" - -int -gp102_disp_base_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nvkm_disp *disp, struct nvkm_object **pobject) -{ - return nv50_disp_base_new_(&gp102_disp_dmac_func, &gf119_disp_base_mthd, - disp, 1, oclass, argv, argc, pobject); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/basenv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/basenv50.c deleted file mode 100644 index 0693eae7f291..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/basenv50.c +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright 2012 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. - * - * Authors: Ben Skeggs - */ -#include "channv50.h" -#include "head.h" - -#include <core/client.h> - -#include <nvif/cl507c.h> -#include <nvif/unpack.h> - -int -nv50_disp_base_new_(const struct nv50_disp_chan_func *func, - const struct nv50_disp_chan_mthd *mthd, - struct nvkm_disp *disp, int chid, - const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nvkm_object **pobject) -{ - union { - struct nv50_disp_base_channel_dma_v0 v0; - } *args = argv; - struct nvkm_object *parent = oclass->parent; - int head, ret = -ENOSYS; - u64 push; - - nvif_ioctl(parent, "create disp base channel dma size %d\n", argc); - if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, false))) { - nvif_ioctl(parent, "create disp base channel dma vers %d " - "pushbuf %016llx head %d\n", - args->v0.version, args->v0.pushbuf, args->v0.head); - if (!nvkm_head_find(disp, args->v0.head)) - return -EINVAL; - push = args->v0.pushbuf; - head = args->v0.head; - } else - return ret; - - return nv50_disp_dmac_new_(func, mthd, disp, chid + head, - head, push, oclass, pobject); -} - -static const struct nv50_disp_mthd_list -nv50_disp_base_mthd_base = { - .mthd = 0x0000, - .addr = 0x000000, - .data = { - { 0x0080, 0x000000 }, - { 0x0084, 0x0008c4 }, - { 0x0088, 0x0008d0 }, - { 0x008c, 0x0008dc }, - { 0x0090, 0x0008e4 }, - { 0x0094, 0x610884 }, - { 0x00a0, 0x6108a0 }, - { 0x00a4, 0x610878 }, - { 0x00c0, 0x61086c }, - { 0x00e0, 0x610858 }, - { 0x00e4, 0x610860 }, - { 0x00e8, 0x6108ac }, - { 0x00ec, 0x6108b4 }, - { 0x0100, 0x610894 }, - { 0x0110, 0x6108bc }, - { 0x0114, 0x61088c }, - {} - } -}; - -const struct nv50_disp_mthd_list -nv50_disp_base_mthd_image = { - .mthd = 0x0400, - .addr = 0x000000, - .data = { - { 0x0800, 0x6108f0 }, - { 0x0804, 0x6108fc }, - { 0x0808, 0x61090c }, - { 0x080c, 0x610914 }, - { 0x0810, 0x610904 }, - {} - } -}; - -static const struct nv50_disp_chan_mthd -nv50_disp_base_mthd = { - .name = "Base", - .addr = 0x000540, - .prev = 0x000004, - .data = { - { "Global", 1, &nv50_disp_base_mthd_base }, - { "Image", 2, &nv50_disp_base_mthd_image }, - {} - } -}; - -int -nv50_disp_base_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nvkm_disp *disp, struct nvkm_object **pobject) -{ - return nv50_disp_base_new_(&nv50_disp_dmac_func, &nv50_disp_base_mthd, - disp, 1, oclass, argv, argc, pobject); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/capsgv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/capsgv100.c deleted file mode 100644 index d7b3a5092434..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/capsgv100.c +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright 2020 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. - */ -#define gv100_disp_caps(p) container_of((p), struct gv100_disp_caps, object) -#include "priv.h" - -struct gv100_disp_caps { - struct nvkm_object object; - struct nvkm_disp *disp; -}; - -static int -gv100_disp_caps_map(struct nvkm_object *object, void *argv, u32 argc, - enum nvkm_object_map *type, u64 *addr, u64 *size) -{ - struct gv100_disp_caps *caps = gv100_disp_caps(object); - struct nvkm_device *device = caps->disp->engine.subdev.device; - *type = NVKM_OBJECT_MAP_IO; - *addr = 0x640000 + device->func->resource_addr(device, 0); - *size = 0x1000; - return 0; -} - -static const struct nvkm_object_func -gv100_disp_caps = { - .map = gv100_disp_caps_map, -}; - -int -gv100_disp_caps_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nvkm_disp *disp, struct nvkm_object **pobject) -{ - struct gv100_disp_caps *caps; - - if (!(caps = kzalloc(sizeof(*caps), GFP_KERNEL))) - return -ENOMEM; - *pobject = &caps->object; - - nvkm_object_ctor(&gv100_disp_caps, oclass, &caps->object); - caps->disp = disp; - return 0; -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/chan.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/chan.c new file mode 100644 index 000000000000..fac9fc41847c --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/chan.c @@ -0,0 +1,223 @@ +/* + * Copyright 2021 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 "chan.h" + +#include <core/oproxy.h> +#include <core/ramht.h> + +#include <nvif/cl507d.h> + +static int +nvkm_disp_chan_rd32(struct nvkm_object *object, u64 addr, u32 *data) +{ + struct nvkm_disp_chan *chan = nvkm_disp_chan(object); + struct nvkm_device *device = chan->disp->engine.subdev.device; + u64 size, base = chan->func->user(chan, &size); + + *data = nvkm_rd32(device, base + addr); + return 0; +} + +static int +nvkm_disp_chan_wr32(struct nvkm_object *object, u64 addr, u32 data) +{ + struct nvkm_disp_chan *chan = nvkm_disp_chan(object); + struct nvkm_device *device = chan->disp->engine.subdev.device; + u64 size, base = chan->func->user(chan, &size); + + nvkm_wr32(device, base + addr, data); + return 0; +} + +static int +nvkm_disp_chan_ntfy(struct nvkm_object *object, u32 type, struct nvkm_event **pevent) +{ + struct nvkm_disp_chan *chan = nvkm_disp_chan(object); + struct nvkm_disp *disp = chan->disp; + + switch (type) { + case NV50_DISP_CORE_CHANNEL_DMA_V0_NTFY_UEVENT: + *pevent = &disp->uevent; + return 0; + default: + break; + } + + return -EINVAL; +} + +static int +nvkm_disp_chan_map(struct nvkm_object *object, void *argv, u32 argc, + enum nvkm_object_map *type, u64 *addr, u64 *size) +{ + struct nvkm_disp_chan *chan = nvkm_disp_chan(object); + struct nvkm_device *device = chan->disp->engine.subdev.device; + const u64 base = device->func->resource_addr(device, 0); + + *type = NVKM_OBJECT_MAP_IO; + *addr = base + chan->func->user(chan, size); + return 0; +} + +struct nvkm_disp_chan_object { + struct nvkm_oproxy oproxy; + struct nvkm_disp *disp; + int hash; +}; + +static void +nvkm_disp_chan_child_del_(struct nvkm_oproxy *base) +{ + struct nvkm_disp_chan_object *object = container_of(base, typeof(*object), oproxy); + + nvkm_ramht_remove(object->disp->ramht, object->hash); +} + +static const struct nvkm_oproxy_func +nvkm_disp_chan_child_func_ = { + .dtor[0] = nvkm_disp_chan_child_del_, +}; + +static int +nvkm_disp_chan_child_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, + struct nvkm_object **pobject) +{ + struct nvkm_disp_chan *chan = nvkm_disp_chan(oclass->parent); + struct nvkm_disp *disp = chan->disp; + struct nvkm_device *device = disp->engine.subdev.device; + const struct nvkm_device_oclass *sclass = oclass->priv; + struct nvkm_disp_chan_object *object; + int ret; + + if (!(object = kzalloc(sizeof(*object), GFP_KERNEL))) + return -ENOMEM; + nvkm_oproxy_ctor(&nvkm_disp_chan_child_func_, oclass, &object->oproxy); + object->disp = disp; + *pobject = &object->oproxy.base; + + ret = sclass->ctor(device, oclass, argv, argc, &object->oproxy.object); + if (ret) + return ret; + + object->hash = chan->func->bind(chan, object->oproxy.object, oclass->handle); + if (object->hash < 0) + return object->hash; + + return 0; +} + +static int +nvkm_disp_chan_child_get(struct nvkm_object *object, int index, struct nvkm_oclass *sclass) +{ + struct nvkm_disp_chan *chan = nvkm_disp_chan(object); + struct nvkm_device *device = chan->disp->engine.subdev.device; + const struct nvkm_device_oclass *oclass = NULL; + + if (chan->func->bind) + sclass->engine = nvkm_device_engine(device, NVKM_ENGINE_DMAOBJ, 0); + else + sclass->engine = NULL; + + if (sclass->engine && sclass->engine->func->base.sclass) { + sclass->engine->func->base.sclass(sclass, index, &oclass); + if (oclass) { + sclass->ctor = nvkm_disp_chan_child_new; + sclass->priv = oclass; + return 0; + } + } + + return -EINVAL; +} + +static int +nvkm_disp_chan_fini(struct nvkm_object *object, bool suspend) +{ + struct nvkm_disp_chan *chan = nvkm_disp_chan(object); + + chan->func->fini(chan); + chan->func->intr(chan, false); + return 0; +} + +static int +nvkm_disp_chan_init(struct nvkm_object *object) +{ + struct nvkm_disp_chan *chan = nvkm_disp_chan(object); + + chan->func->intr(chan, true); + return chan->func->init(chan); +} + +static void * +nvkm_disp_chan_dtor(struct nvkm_object *object) +{ + struct nvkm_disp_chan *chan = nvkm_disp_chan(object); + struct nvkm_disp *disp = chan->disp; + + if (chan->chid.user >= 0) + disp->chan[chan->chid.user] = NULL; + + nvkm_memory_unref(&chan->memory); + return chan; +} + +static const struct nvkm_object_func +nvkm_disp_chan = { + .dtor = nvkm_disp_chan_dtor, + .init = nvkm_disp_chan_init, + .fini = nvkm_disp_chan_fini, + .rd32 = nvkm_disp_chan_rd32, + .wr32 = nvkm_disp_chan_wr32, + .ntfy = nvkm_disp_chan_ntfy, + .map = nvkm_disp_chan_map, + .sclass = nvkm_disp_chan_child_get, +}; + +int +nvkm_disp_chan_new_(const struct nvkm_disp_chan_func *func, + const struct nvkm_disp_chan_mthd *mthd, + struct nvkm_disp *disp, int ctrl, int user, int head, + const struct nvkm_oclass *oclass, + struct nvkm_object **pobject) +{ + struct nvkm_disp_chan *chan; + + if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL))) + return -ENOMEM; + *pobject = &chan->object; + + nvkm_object_ctor(&nvkm_disp_chan, oclass, &chan->object); + chan->func = func; + chan->mthd = mthd; + chan->disp = disp; + chan->chid.ctrl = ctrl; + chan->chid.user = user; + chan->head = head; + + if (disp->chan[chan->chid.user]) { + chan->chid.user = -1; + return -EBUSY; + } + disp->chan[chan->chid.user] = chan; + return 0; +} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/chan.h index 50850de1e609..b7394b6a0fb8 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/chan.h @@ -1,14 +1,13 @@ /* SPDX-License-Identifier: MIT */ -#ifndef __NV50_DISP_CHAN_H__ -#define __NV50_DISP_CHAN_H__ -#define nv50_disp_chan(p) container_of((p), struct nv50_disp_chan, object) +#ifndef __NVKM_DISP_CHAN_H__ +#define __NVKM_DISP_CHAN_H__ +#define nvkm_disp_chan(p) container_of((p), struct nvkm_disp_chan, object) #include <core/object.h> #include "priv.h" -struct nv50_disp_root; -struct nv50_disp_chan { - const struct nv50_disp_chan_func *func; - const struct nv50_disp_chan_mthd *mthd; +struct nvkm_disp_chan { + const struct nvkm_disp_chan_func *func; + const struct nvkm_disp_chan_mthd *mthd; struct nvkm_disp *disp; struct { @@ -25,65 +24,65 @@ struct nv50_disp_chan { u32 suspend_put; }; -struct nv50_disp_chan_func { - int (*init)(struct nv50_disp_chan *); - void (*fini)(struct nv50_disp_chan *); - void (*intr)(struct nv50_disp_chan *, bool en); - u64 (*user)(struct nv50_disp_chan *, u64 *size); - int (*bind)(struct nv50_disp_chan *, struct nvkm_object *, u32 handle); +struct nvkm_disp_chan_func { + int (*init)(struct nvkm_disp_chan *); + void (*fini)(struct nvkm_disp_chan *); + void (*intr)(struct nvkm_disp_chan *, bool en); + u64 (*user)(struct nvkm_disp_chan *, u64 *size); + int (*bind)(struct nvkm_disp_chan *, struct nvkm_object *, u32 handle); }; -int nv50_disp_chan_new_(const struct nv50_disp_chan_func *, - const struct nv50_disp_chan_mthd *, +int nvkm_disp_chan_new_(const struct nvkm_disp_chan_func *, + const struct nvkm_disp_chan_mthd *, struct nvkm_disp *, int ctrl, int user, int head, const struct nvkm_oclass *, struct nvkm_object **); -int nv50_disp_dmac_new_(const struct nv50_disp_chan_func *, - const struct nv50_disp_chan_mthd *, +int nv50_disp_dmac_new_(const struct nvkm_disp_chan_func *, + const struct nvkm_disp_chan_mthd *, struct nvkm_disp *, int chid, int head, u64 push, const struct nvkm_oclass *, struct nvkm_object **); -void nv50_disp_chan_intr(struct nv50_disp_chan *, bool); -u64 nv50_disp_chan_user(struct nv50_disp_chan *, u64 *); -extern const struct nv50_disp_chan_func nv50_disp_pioc_func; -extern const struct nv50_disp_chan_func nv50_disp_dmac_func; -int nv50_disp_dmac_bind(struct nv50_disp_chan *, struct nvkm_object *, u32); -extern const struct nv50_disp_chan_func nv50_disp_core_func; - -void gf119_disp_chan_intr(struct nv50_disp_chan *, bool); -extern const struct nv50_disp_chan_func gf119_disp_pioc_func; -extern const struct nv50_disp_chan_func gf119_disp_dmac_func; -void gf119_disp_dmac_fini(struct nv50_disp_chan *); -int gf119_disp_dmac_bind(struct nv50_disp_chan *, struct nvkm_object *, u32); -extern const struct nv50_disp_chan_func gf119_disp_core_func; -void gf119_disp_core_fini(struct nv50_disp_chan *); - -extern const struct nv50_disp_chan_func gp102_disp_dmac_func; - -u64 gv100_disp_chan_user(struct nv50_disp_chan *, u64 *); -int gv100_disp_dmac_init(struct nv50_disp_chan *); -void gv100_disp_dmac_fini(struct nv50_disp_chan *); -int gv100_disp_dmac_bind(struct nv50_disp_chan *, struct nvkm_object *, u32); - -int nv50_disp_curs_new_(const struct nv50_disp_chan_func *, +void nv50_disp_chan_intr(struct nvkm_disp_chan *, bool); +u64 nv50_disp_chan_user(struct nvkm_disp_chan *, u64 *); +extern const struct nvkm_disp_chan_func nv50_disp_pioc_func; +extern const struct nvkm_disp_chan_func nv50_disp_dmac_func; +int nv50_disp_dmac_bind(struct nvkm_disp_chan *, struct nvkm_object *, u32); +extern const struct nvkm_disp_chan_func nv50_disp_core_func; + +void gf119_disp_chan_intr(struct nvkm_disp_chan *, bool); +extern const struct nvkm_disp_chan_func gf119_disp_pioc_func; +extern const struct nvkm_disp_chan_func gf119_disp_dmac_func; +void gf119_disp_dmac_fini(struct nvkm_disp_chan *); +int gf119_disp_dmac_bind(struct nvkm_disp_chan *, struct nvkm_object *, u32); +extern const struct nvkm_disp_chan_func gf119_disp_core_func; +void gf119_disp_core_fini(struct nvkm_disp_chan *); + +extern const struct nvkm_disp_chan_func gp102_disp_dmac_func; + +u64 gv100_disp_chan_user(struct nvkm_disp_chan *, u64 *); +int gv100_disp_dmac_init(struct nvkm_disp_chan *); +void gv100_disp_dmac_fini(struct nvkm_disp_chan *); +int gv100_disp_dmac_bind(struct nvkm_disp_chan *, struct nvkm_object *, u32); + +int nv50_disp_curs_new_(const struct nvkm_disp_chan_func *, struct nvkm_disp *, int ctrl, int user, const struct nvkm_oclass *, void *argv, u32 argc, struct nvkm_object **); -int nv50_disp_oimm_new_(const struct nv50_disp_chan_func *, +int nv50_disp_oimm_new_(const struct nvkm_disp_chan_func *, struct nvkm_disp *, int ctrl, int user, const struct nvkm_oclass *, void *argv, u32 argc, struct nvkm_object **); -int nv50_disp_base_new_(const struct nv50_disp_chan_func *, - const struct nv50_disp_chan_mthd *, +int nv50_disp_base_new_(const struct nvkm_disp_chan_func *, + const struct nvkm_disp_chan_mthd *, struct nvkm_disp *, int chid, const struct nvkm_oclass *, void *argv, u32 argc, struct nvkm_object **); -int nv50_disp_core_new_(const struct nv50_disp_chan_func *, - const struct nv50_disp_chan_mthd *, +int nv50_disp_core_new_(const struct nvkm_disp_chan_func *, + const struct nvkm_disp_chan_mthd *, struct nvkm_disp *, int chid, const struct nvkm_oclass *oclass, void *argv, u32 argc, struct nvkm_object **); -int nv50_disp_ovly_new_(const struct nv50_disp_chan_func *, - const struct nv50_disp_chan_mthd *, +int nv50_disp_ovly_new_(const struct nvkm_disp_chan_func *, + const struct nvkm_disp_chan_mthd *, struct nvkm_disp *, int chid, const struct nvkm_oclass *, void *argv, u32 argc, struct nvkm_object **); @@ -148,7 +147,7 @@ int gv100_disp_core_new(const struct nvkm_oclass *, void *, u32, int gv100_disp_wndw_new(const struct nvkm_oclass *, void *, u32, struct nvkm_disp *, struct nvkm_object **); -struct nv50_disp_mthd_list { +struct nvkm_disp_mthd_list { u32 mthd; u32 addr; struct { @@ -158,36 +157,36 @@ struct nv50_disp_mthd_list { } data[]; }; -struct nv50_disp_chan_mthd { +struct nvkm_disp_chan_mthd { const char *name; u32 addr; s32 prev; struct { const char *name; int nr; - const struct nv50_disp_mthd_list *mthd; + const struct nvkm_disp_mthd_list *mthd; } data[]; }; -void nv50_disp_chan_mthd(struct nv50_disp_chan *, int debug); +void nv50_disp_chan_mthd(struct nvkm_disp_chan *, int debug); -extern const struct nv50_disp_mthd_list nv50_disp_core_mthd_base; -extern const struct nv50_disp_mthd_list nv50_disp_core_mthd_sor; -extern const struct nv50_disp_mthd_list nv50_disp_core_mthd_pior; -extern const struct nv50_disp_mthd_list nv50_disp_base_mthd_image; +extern const struct nvkm_disp_mthd_list nv50_disp_core_mthd_base; +extern const struct nvkm_disp_mthd_list nv50_disp_core_mthd_sor; +extern const struct nvkm_disp_mthd_list nv50_disp_core_mthd_pior; +extern const struct nvkm_disp_mthd_list nv50_disp_base_mthd_image; -extern const struct nv50_disp_chan_mthd g84_disp_core_mthd; -extern const struct nv50_disp_mthd_list g84_disp_core_mthd_dac; -extern const struct nv50_disp_mthd_list g84_disp_core_mthd_head; +extern const struct nvkm_disp_chan_mthd g84_disp_core_mthd; +extern const struct nvkm_disp_mthd_list g84_disp_core_mthd_dac; +extern const struct nvkm_disp_mthd_list g84_disp_core_mthd_head; -extern const struct nv50_disp_chan_mthd g94_disp_core_mthd; +extern const struct nvkm_disp_chan_mthd g94_disp_core_mthd; -extern const struct nv50_disp_mthd_list gf119_disp_core_mthd_base; -extern const struct nv50_disp_mthd_list gf119_disp_core_mthd_dac; -extern const struct nv50_disp_mthd_list gf119_disp_core_mthd_sor; -extern const struct nv50_disp_mthd_list gf119_disp_core_mthd_pior; -extern const struct nv50_disp_chan_mthd gf119_disp_base_mthd; +extern const struct nvkm_disp_mthd_list gf119_disp_core_mthd_base; +extern const struct nvkm_disp_mthd_list gf119_disp_core_mthd_dac; +extern const struct nvkm_disp_mthd_list gf119_disp_core_mthd_sor; +extern const struct nvkm_disp_mthd_list gf119_disp_core_mthd_pior; +extern const struct nvkm_disp_chan_mthd gf119_disp_base_mthd; -extern const struct nv50_disp_chan_mthd gk104_disp_core_mthd; -extern const struct nv50_disp_chan_mthd gk104_disp_ovly_mthd; +extern const struct nvkm_disp_chan_mthd gk104_disp_core_mthd; +extern const struct nvkm_disp_chan_mthd gk104_disp_ovly_mthd; #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/changf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/changf119.c deleted file mode 100644 index 1812b4f7cc8b..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/changf119.c +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2012 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. - * - * Authors: Ben Skeggs - */ -#include "channv50.h" - -static void -gf119_disp_chan_uevent_fini(struct nvkm_event *event, int type, int index) -{ - struct nvkm_disp *disp = container_of(event, typeof(*disp), uevent); - struct nvkm_device *device = disp->engine.subdev.device; - nvkm_mask(device, 0x610090, 0x00000001 << index, 0x00000000 << index); - nvkm_wr32(device, 0x61008c, 0x00000001 << index); -} - -static void -gf119_disp_chan_uevent_init(struct nvkm_event *event, int types, int index) -{ - struct nvkm_disp *disp = container_of(event, typeof(*disp), uevent); - struct nvkm_device *device = disp->engine.subdev.device; - nvkm_wr32(device, 0x61008c, 0x00000001 << index); - nvkm_mask(device, 0x610090, 0x00000001 << index, 0x00000001 << index); -} - -const struct nvkm_event_func -gf119_disp_chan_uevent = { - .ctor = nv50_disp_chan_uevent_ctor, - .init = gf119_disp_chan_uevent_init, - .fini = gf119_disp_chan_uevent_fini, -}; - -void -gf119_disp_chan_intr(struct nv50_disp_chan *chan, bool en) -{ - struct nvkm_device *device = chan->disp->engine.subdev.device; - const u32 mask = 0x00000001 << chan->chid.user; - if (!en) { - nvkm_mask(device, 0x610090, mask, 0x00000000); - nvkm_mask(device, 0x6100a0, mask, 0x00000000); - } else { - nvkm_mask(device, 0x6100a0, mask, mask); - } -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/changv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/changv100.c deleted file mode 100644 index 75247c9c7e10..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/changv100.c +++ /dev/null @@ -1,34 +0,0 @@ -/* - * 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 "channv50.h" - -const struct nvkm_event_func -gv100_disp_chan_uevent = { - .ctor = nv50_disp_chan_uevent_ctor, -}; - -u64 -gv100_disp_chan_user(struct nv50_disp_chan *chan, u64 *psize) -{ - *psize = 0x1000; - return 0x690000 + ((chan->chid.user - 1) * 0x1000); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.c deleted file mode 100644 index 0f042d59289e..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.c +++ /dev/null @@ -1,363 +0,0 @@ -/* - * Copyright 2012 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. - * - * Authors: Ben Skeggs - */ -#include "channv50.h" - -#include <core/client.h> -#include <core/notify.h> -#include <core/oproxy.h> -#include <core/ramht.h> -#include <engine/dma.h> - -#include <nvif/cl507d.h> -#include <nvif/event.h> -#include <nvif/unpack.h> - -static void -nv50_disp_mthd_list(struct nvkm_disp *disp, int debug, u32 base, int c, - const struct nv50_disp_mthd_list *list, int inst) -{ - struct nvkm_subdev *subdev = &disp->engine.subdev; - struct nvkm_device *device = subdev->device; - int i; - - for (i = 0; list->data[i].mthd; i++) { - if (list->data[i].addr) { - u32 next = nvkm_rd32(device, list->data[i].addr + base + 0); - u32 prev = nvkm_rd32(device, list->data[i].addr + base + c); - u32 mthd = list->data[i].mthd + (list->mthd * inst); - const char *name = list->data[i].name; - char mods[16]; - - if (prev != next) - snprintf(mods, sizeof(mods), "-> %08x", next); - else - snprintf(mods, sizeof(mods), "%13c", ' '); - - nvkm_printk_(subdev, debug, info, - "\t%04x: %08x %s%s%s\n", - mthd, prev, mods, name ? " // " : "", - name ? name : ""); - } - } -} - -void -nv50_disp_chan_mthd(struct nv50_disp_chan *chan, int debug) -{ - struct nvkm_disp *disp = chan->disp; - struct nvkm_subdev *subdev = &disp->engine.subdev; - const struct nv50_disp_chan_mthd *mthd = chan->mthd; - const struct nv50_disp_mthd_list *list; - int i, j; - - if (debug > subdev->debug) - return; - if (!mthd) - return; - - for (i = 0; (list = mthd->data[i].mthd) != NULL; i++) { - u32 base = chan->head * mthd->addr; - for (j = 0; j < mthd->data[i].nr; j++, base += list->addr) { - const char *cname = mthd->name; - const char *sname = ""; - char cname_[16], sname_[16]; - - if (mthd->addr) { - snprintf(cname_, sizeof(cname_), "%s %d", - mthd->name, chan->chid.user); - cname = cname_; - } - - if (mthd->data[i].nr > 1) { - snprintf(sname_, sizeof(sname_), " - %s %d", - mthd->data[i].name, j); - sname = sname_; - } - - nvkm_printk_(subdev, debug, info, "%s%s:\n", cname, sname); - nv50_disp_mthd_list(disp, debug, base, mthd->prev, - list, j); - } - } -} - -static void -nv50_disp_chan_uevent_fini(struct nvkm_event *event, int type, int index) -{ - struct nvkm_disp *disp = container_of(event, typeof(*disp), uevent); - struct nvkm_device *device = disp->engine.subdev.device; - nvkm_mask(device, 0x610028, 0x00000001 << index, 0x00000000 << index); - nvkm_wr32(device, 0x610020, 0x00000001 << index); -} - -static void -nv50_disp_chan_uevent_init(struct nvkm_event *event, int types, int index) -{ - struct nvkm_disp *disp = container_of(event, typeof(*disp), uevent); - struct nvkm_device *device = disp->engine.subdev.device; - nvkm_wr32(device, 0x610020, 0x00000001 << index); - nvkm_mask(device, 0x610028, 0x00000001 << index, 0x00000001 << index); -} - -void -nv50_disp_chan_uevent_send(struct nvkm_disp *disp, int chid) -{ - struct nvif_notify_uevent_rep { - } rep; - - nvkm_event_send(&disp->uevent, 1, chid, &rep, sizeof(rep)); -} - -int -nv50_disp_chan_uevent_ctor(struct nvkm_object *object, void *data, u32 size, - struct nvkm_notify *notify) -{ - struct nv50_disp_chan *chan = nv50_disp_chan(object); - union { - struct nvif_notify_uevent_req none; - } *args = data; - int ret = -ENOSYS; - - if (!(ret = nvif_unvers(ret, &data, &size, args->none))) { - notify->size = sizeof(struct nvif_notify_uevent_rep); - notify->types = 1; - notify->index = chan->chid.user; - return 0; - } - - return ret; -} - -const struct nvkm_event_func -nv50_disp_chan_uevent = { - .ctor = nv50_disp_chan_uevent_ctor, - .init = nv50_disp_chan_uevent_init, - .fini = nv50_disp_chan_uevent_fini, -}; - -u64 -nv50_disp_chan_user(struct nv50_disp_chan *chan, u64 *psize) -{ - *psize = 0x1000; - return 0x640000 + (chan->chid.user * 0x1000); -} - -void -nv50_disp_chan_intr(struct nv50_disp_chan *chan, bool en) -{ - struct nvkm_device *device = chan->disp->engine.subdev.device; - const u32 mask = 0x00010001 << chan->chid.user; - const u32 data = en ? 0x00010000 << chan->chid.user : 0x00000000; - nvkm_mask(device, 0x610028, mask, data); -} - -static int -nv50_disp_chan_rd32(struct nvkm_object *object, u64 addr, u32 *data) -{ - struct nv50_disp_chan *chan = nv50_disp_chan(object); - struct nvkm_device *device = chan->disp->engine.subdev.device; - u64 size, base = chan->func->user(chan, &size); - *data = nvkm_rd32(device, base + addr); - return 0; -} - -static int -nv50_disp_chan_wr32(struct nvkm_object *object, u64 addr, u32 data) -{ - struct nv50_disp_chan *chan = nv50_disp_chan(object); - struct nvkm_device *device = chan->disp->engine.subdev.device; - u64 size, base = chan->func->user(chan, &size); - nvkm_wr32(device, base + addr, data); - return 0; -} - -static int -nv50_disp_chan_ntfy(struct nvkm_object *object, u32 type, - struct nvkm_event **pevent) -{ - struct nv50_disp_chan *chan = nv50_disp_chan(object); - struct nvkm_disp *disp = chan->disp; - switch (type) { - case NV50_DISP_CORE_CHANNEL_DMA_V0_NTFY_UEVENT: - *pevent = &disp->uevent; - return 0; - default: - break; - } - return -EINVAL; -} - -static int -nv50_disp_chan_map(struct nvkm_object *object, void *argv, u32 argc, - enum nvkm_object_map *type, u64 *addr, u64 *size) -{ - struct nv50_disp_chan *chan = nv50_disp_chan(object); - struct nvkm_device *device = chan->disp->engine.subdev.device; - const u64 base = device->func->resource_addr(device, 0); - *type = NVKM_OBJECT_MAP_IO; - *addr = base + chan->func->user(chan, size); - return 0; -} - -struct nv50_disp_chan_object { - struct nvkm_oproxy oproxy; - struct nvkm_disp *disp; - int hash; -}; - -static void -nv50_disp_chan_child_del_(struct nvkm_oproxy *base) -{ - struct nv50_disp_chan_object *object = - container_of(base, typeof(*object), oproxy); - nvkm_ramht_remove(object->disp->ramht, object->hash); -} - -static const struct nvkm_oproxy_func -nv50_disp_chan_child_func_ = { - .dtor[0] = nv50_disp_chan_child_del_, -}; - -static int -nv50_disp_chan_child_new(const struct nvkm_oclass *oclass, - void *argv, u32 argc, struct nvkm_object **pobject) -{ - struct nv50_disp_chan *chan = nv50_disp_chan(oclass->parent); - struct nvkm_disp *disp = chan->disp; - struct nvkm_device *device = disp->engine.subdev.device; - const struct nvkm_device_oclass *sclass = oclass->priv; - struct nv50_disp_chan_object *object; - int ret; - - if (!(object = kzalloc(sizeof(*object), GFP_KERNEL))) - return -ENOMEM; - nvkm_oproxy_ctor(&nv50_disp_chan_child_func_, oclass, &object->oproxy); - object->disp = disp; - *pobject = &object->oproxy.base; - - ret = sclass->ctor(device, oclass, argv, argc, &object->oproxy.object); - if (ret) - return ret; - - object->hash = chan->func->bind(chan, object->oproxy.object, - oclass->handle); - if (object->hash < 0) - return object->hash; - - return 0; -} - -static int -nv50_disp_chan_child_get(struct nvkm_object *object, int index, - struct nvkm_oclass *sclass) -{ - struct nv50_disp_chan *chan = nv50_disp_chan(object); - struct nvkm_device *device = chan->disp->engine.subdev.device; - const struct nvkm_device_oclass *oclass = NULL; - - if (chan->func->bind) - sclass->engine = nvkm_device_engine(device, NVKM_ENGINE_DMAOBJ, 0); - else - sclass->engine = NULL; - - if (sclass->engine && sclass->engine->func->base.sclass) { - sclass->engine->func->base.sclass(sclass, index, &oclass); - if (oclass) { - sclass->ctor = nv50_disp_chan_child_new, - sclass->priv = oclass; - return 0; - } - } - - return -EINVAL; -} - -static int -nv50_disp_chan_fini(struct nvkm_object *object, bool suspend) -{ - struct nv50_disp_chan *chan = nv50_disp_chan(object); - chan->func->fini(chan); - chan->func->intr(chan, false); - return 0; -} - -static int -nv50_disp_chan_init(struct nvkm_object *object) -{ - struct nv50_disp_chan *chan = nv50_disp_chan(object); - chan->func->intr(chan, true); - return chan->func->init(chan); -} - -static void * -nv50_disp_chan_dtor(struct nvkm_object *object) -{ - struct nv50_disp_chan *chan = nv50_disp_chan(object); - struct nvkm_disp *disp = chan->disp; - if (chan->chid.user >= 0) - disp->chan[chan->chid.user] = NULL; - nvkm_memory_unref(&chan->memory); - return chan; -} - -static const struct nvkm_object_func -nv50_disp_chan = { - .dtor = nv50_disp_chan_dtor, - .init = nv50_disp_chan_init, - .fini = nv50_disp_chan_fini, - .rd32 = nv50_disp_chan_rd32, - .wr32 = nv50_disp_chan_wr32, - .ntfy = nv50_disp_chan_ntfy, - .map = nv50_disp_chan_map, - .sclass = nv50_disp_chan_child_get, -}; - -int -nv50_disp_chan_new_(const struct nv50_disp_chan_func *func, - const struct nv50_disp_chan_mthd *mthd, - struct nvkm_disp *disp, int ctrl, int user, int head, - const struct nvkm_oclass *oclass, - struct nvkm_object **pobject) -{ - struct nv50_disp_chan *chan; - - if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL))) - return -ENOMEM; - *pobject = &chan->object; - - nvkm_object_ctor(&nv50_disp_chan, oclass, &chan->object); - chan->func = func; - chan->mthd = mthd; - chan->disp = disp; - chan->chid.ctrl = ctrl; - chan->chid.user = user; - chan->head = head; - - if (disp->chan[chan->chid.user]) { - chan->chid.user = -1; - return -EBUSY; - } - disp->chan[chan->chid.user] = chan; - return 0; -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/coreg84.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/coreg84.c deleted file mode 100644 index 0290041fe8f0..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/coreg84.c +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright 2012 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. - * - * Authors: Ben Skeggs - */ -#include "channv50.h" - -const struct nv50_disp_mthd_list -g84_disp_core_mthd_dac = { - .mthd = 0x0080, - .addr = 0x000008, - .data = { - { 0x0400, 0x610b58 }, - { 0x0404, 0x610bdc }, - { 0x0420, 0x610bc4 }, - {} - } -}; - -const struct nv50_disp_mthd_list -g84_disp_core_mthd_head = { - .mthd = 0x0400, - .addr = 0x000540, - .data = { - { 0x0800, 0x610ad8 }, - { 0x0804, 0x610ad0 }, - { 0x0808, 0x610a48 }, - { 0x080c, 0x610a78 }, - { 0x0810, 0x610ac0 }, - { 0x0814, 0x610af8 }, - { 0x0818, 0x610b00 }, - { 0x081c, 0x610ae8 }, - { 0x0820, 0x610af0 }, - { 0x0824, 0x610b08 }, - { 0x0828, 0x610b10 }, - { 0x082c, 0x610a68 }, - { 0x0830, 0x610a60 }, - { 0x0834, 0x000000 }, - { 0x0838, 0x610a40 }, - { 0x0840, 0x610a24 }, - { 0x0844, 0x610a2c }, - { 0x0848, 0x610aa8 }, - { 0x084c, 0x610ab0 }, - { 0x085c, 0x610c5c }, - { 0x0860, 0x610a84 }, - { 0x0864, 0x610a90 }, - { 0x0868, 0x610b18 }, - { 0x086c, 0x610b20 }, - { 0x0870, 0x610ac8 }, - { 0x0874, 0x610a38 }, - { 0x0878, 0x610c50 }, - { 0x0880, 0x610a58 }, - { 0x0884, 0x610a9c }, - { 0x089c, 0x610c68 }, - { 0x08a0, 0x610a70 }, - { 0x08a4, 0x610a50 }, - { 0x08a8, 0x610ae0 }, - { 0x08c0, 0x610b28 }, - { 0x08c4, 0x610b30 }, - { 0x08c8, 0x610b40 }, - { 0x08d4, 0x610b38 }, - { 0x08d8, 0x610b48 }, - { 0x08dc, 0x610b50 }, - { 0x0900, 0x610a18 }, - { 0x0904, 0x610ab8 }, - { 0x0910, 0x610c70 }, - { 0x0914, 0x610c78 }, - {} - } -}; - -const struct nv50_disp_chan_mthd -g84_disp_core_mthd = { - .name = "Core", - .addr = 0x000000, - .prev = 0x000004, - .data = { - { "Global", 1, &nv50_disp_core_mthd_base }, - { "DAC", 3, &g84_disp_core_mthd_dac }, - { "SOR", 2, &nv50_disp_core_mthd_sor }, - { "PIOR", 3, &nv50_disp_core_mthd_pior }, - { "HEAD", 2, &g84_disp_core_mthd_head }, - {} - } -}; - -int -g84_disp_core_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nvkm_disp *disp, struct nvkm_object **pobject) -{ - return nv50_disp_core_new_(&nv50_disp_core_func, &g84_disp_core_mthd, - disp, 0, oclass, argv, argc, pobject); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/coreg94.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/coreg94.c deleted file mode 100644 index 8d42ce3fcf97..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/coreg94.c +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2012 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. - * - * Authors: Ben Skeggs - */ -#include "channv50.h" - -static const struct nv50_disp_mthd_list -g94_disp_core_mthd_sor = { - .mthd = 0x0040, - .addr = 0x000008, - .data = { - { 0x0600, 0x610794 }, - {} - } -}; - -const struct nv50_disp_chan_mthd -g94_disp_core_mthd = { - .name = "Core", - .addr = 0x000000, - .prev = 0x000004, - .data = { - { "Global", 1, &nv50_disp_core_mthd_base }, - { "DAC", 3, &g84_disp_core_mthd_dac }, - { "SOR", 4, &g94_disp_core_mthd_sor }, - { "PIOR", 3, &nv50_disp_core_mthd_pior }, - { "HEAD", 2, &g84_disp_core_mthd_head }, - {} - } -}; - -int -g94_disp_core_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nvkm_disp *disp, struct nvkm_object **pobject) -{ - return nv50_disp_core_new_(&nv50_disp_core_func, &g94_disp_core_mthd, - disp, 0, oclass, argv, argc, pobject); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregf119.c deleted file mode 100644 index b7e540f9d39c..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregf119.c +++ /dev/null @@ -1,231 +0,0 @@ -/* - * Copyright 2012 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. - * - * Authors: Ben Skeggs - */ -#include "channv50.h" - -#include <subdev/timer.h> - -const struct nv50_disp_mthd_list -gf119_disp_core_mthd_base = { - .mthd = 0x0000, - .addr = 0x000000, - .data = { - { 0x0080, 0x660080 }, - { 0x0084, 0x660084 }, - { 0x0088, 0x660088 }, - { 0x008c, 0x000000 }, - {} - } -}; - -const struct nv50_disp_mthd_list -gf119_disp_core_mthd_dac = { - .mthd = 0x0020, - .addr = 0x000020, - .data = { - { 0x0180, 0x660180 }, - { 0x0184, 0x660184 }, - { 0x0188, 0x660188 }, - { 0x0190, 0x660190 }, - {} - } -}; - -const struct nv50_disp_mthd_list -gf119_disp_core_mthd_sor = { - .mthd = 0x0020, - .addr = 0x000020, - .data = { - { 0x0200, 0x660200 }, - { 0x0204, 0x660204 }, - { 0x0208, 0x660208 }, - { 0x0210, 0x660210 }, - {} - } -}; - -const struct nv50_disp_mthd_list -gf119_disp_core_mthd_pior = { - .mthd = 0x0020, - .addr = 0x000020, - .data = { - { 0x0300, 0x660300 }, - { 0x0304, 0x660304 }, - { 0x0308, 0x660308 }, - { 0x0310, 0x660310 }, - {} - } -}; - -static const struct nv50_disp_mthd_list -gf119_disp_core_mthd_head = { - .mthd = 0x0300, - .addr = 0x000300, - .data = { - { 0x0400, 0x660400 }, - { 0x0404, 0x660404 }, - { 0x0408, 0x660408 }, - { 0x040c, 0x66040c }, - { 0x0410, 0x660410 }, - { 0x0414, 0x660414 }, - { 0x0418, 0x660418 }, - { 0x041c, 0x66041c }, - { 0x0420, 0x660420 }, - { 0x0424, 0x660424 }, - { 0x0428, 0x660428 }, - { 0x042c, 0x66042c }, - { 0x0430, 0x660430 }, - { 0x0434, 0x660434 }, - { 0x0438, 0x660438 }, - { 0x0440, 0x660440 }, - { 0x0444, 0x660444 }, - { 0x0448, 0x660448 }, - { 0x044c, 0x66044c }, - { 0x0450, 0x660450 }, - { 0x0454, 0x660454 }, - { 0x0458, 0x660458 }, - { 0x045c, 0x66045c }, - { 0x0460, 0x660460 }, - { 0x0468, 0x660468 }, - { 0x046c, 0x66046c }, - { 0x0470, 0x660470 }, - { 0x0474, 0x660474 }, - { 0x0480, 0x660480 }, - { 0x0484, 0x660484 }, - { 0x048c, 0x66048c }, - { 0x0490, 0x660490 }, - { 0x0494, 0x660494 }, - { 0x0498, 0x660498 }, - { 0x04b0, 0x6604b0 }, - { 0x04b8, 0x6604b8 }, - { 0x04bc, 0x6604bc }, - { 0x04c0, 0x6604c0 }, - { 0x04c4, 0x6604c4 }, - { 0x04c8, 0x6604c8 }, - { 0x04d0, 0x6604d0 }, - { 0x04d4, 0x6604d4 }, - { 0x04e0, 0x6604e0 }, - { 0x04e4, 0x6604e4 }, - { 0x04e8, 0x6604e8 }, - { 0x04ec, 0x6604ec }, - { 0x04f0, 0x6604f0 }, - { 0x04f4, 0x6604f4 }, - { 0x04f8, 0x6604f8 }, - { 0x04fc, 0x6604fc }, - { 0x0500, 0x660500 }, - { 0x0504, 0x660504 }, - { 0x0508, 0x660508 }, - { 0x050c, 0x66050c }, - { 0x0510, 0x660510 }, - { 0x0514, 0x660514 }, - { 0x0518, 0x660518 }, - { 0x051c, 0x66051c }, - { 0x052c, 0x66052c }, - { 0x0530, 0x660530 }, - { 0x054c, 0x66054c }, - { 0x0550, 0x660550 }, - { 0x0554, 0x660554 }, - { 0x0558, 0x660558 }, - { 0x055c, 0x66055c }, - {} - } -}; - -static const struct nv50_disp_chan_mthd -gf119_disp_core_mthd = { - .name = "Core", - .addr = 0x000000, - .prev = -0x020000, - .data = { - { "Global", 1, &gf119_disp_core_mthd_base }, - { "DAC", 3, &gf119_disp_core_mthd_dac }, - { "SOR", 8, &gf119_disp_core_mthd_sor }, - { "PIOR", 4, &gf119_disp_core_mthd_pior }, - { "HEAD", 4, &gf119_disp_core_mthd_head }, - {} - } -}; - -void -gf119_disp_core_fini(struct nv50_disp_chan *chan) -{ - struct nvkm_subdev *subdev = &chan->disp->engine.subdev; - struct nvkm_device *device = subdev->device; - - /* deactivate channel */ - nvkm_mask(device, 0x610490, 0x00000010, 0x00000000); - nvkm_mask(device, 0x610490, 0x00000003, 0x00000000); - if (nvkm_msec(device, 2000, - if (!(nvkm_rd32(device, 0x610490) & 0x001e0000)) - break; - ) < 0) { - nvkm_error(subdev, "core fini: %08x\n", - nvkm_rd32(device, 0x610490)); - } - - chan->suspend_put = nvkm_rd32(device, 0x640000); -} - -static int -gf119_disp_core_init(struct nv50_disp_chan *chan) -{ - struct nvkm_subdev *subdev = &chan->disp->engine.subdev; - struct nvkm_device *device = subdev->device; - - /* initialise channel for dma command submission */ - nvkm_wr32(device, 0x610494, chan->push); - nvkm_wr32(device, 0x610498, 0x00010000); - nvkm_wr32(device, 0x61049c, 0x00000001); - nvkm_mask(device, 0x610490, 0x00000010, 0x00000010); - nvkm_wr32(device, 0x640000, chan->suspend_put); - nvkm_wr32(device, 0x610490, 0x01000013); - - /* wait for it to go inactive */ - if (nvkm_msec(device, 2000, - if (!(nvkm_rd32(device, 0x610490) & 0x80000000)) - break; - ) < 0) { - nvkm_error(subdev, "core init: %08x\n", - nvkm_rd32(device, 0x610490)); - return -EBUSY; - } - - return 0; -} - -const struct nv50_disp_chan_func -gf119_disp_core_func = { - .init = gf119_disp_core_init, - .fini = gf119_disp_core_fini, - .intr = gf119_disp_chan_intr, - .user = nv50_disp_chan_user, - .bind = gf119_disp_dmac_bind, -}; - -int -gf119_disp_core_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nvkm_disp *disp, struct nvkm_object **pobject) -{ - return nv50_disp_core_new_(&gf119_disp_core_func, &gf119_disp_core_mthd, - disp, 0, oclass, argv, argc, pobject); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregk104.c deleted file mode 100644 index 97a050840ff7..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregk104.c +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright 2012 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. - * - * Authors: Ben Skeggs - */ -#include "channv50.h" - -static const struct nv50_disp_mthd_list -gk104_disp_core_mthd_head = { - .mthd = 0x0300, - .addr = 0x000300, - .data = { - { 0x0400, 0x660400 }, - { 0x0404, 0x660404 }, - { 0x0408, 0x660408 }, - { 0x040c, 0x66040c }, - { 0x0410, 0x660410 }, - { 0x0414, 0x660414 }, - { 0x0418, 0x660418 }, - { 0x041c, 0x66041c }, - { 0x0420, 0x660420 }, - { 0x0424, 0x660424 }, - { 0x0428, 0x660428 }, - { 0x042c, 0x66042c }, - { 0x0430, 0x660430 }, - { 0x0434, 0x660434 }, - { 0x0438, 0x660438 }, - { 0x0440, 0x660440 }, - { 0x0444, 0x660444 }, - { 0x0448, 0x660448 }, - { 0x044c, 0x66044c }, - { 0x0450, 0x660450 }, - { 0x0454, 0x660454 }, - { 0x0458, 0x660458 }, - { 0x045c, 0x66045c }, - { 0x0460, 0x660460 }, - { 0x0468, 0x660468 }, - { 0x046c, 0x66046c }, - { 0x0470, 0x660470 }, - { 0x0474, 0x660474 }, - { 0x047c, 0x66047c }, - { 0x0480, 0x660480 }, - { 0x0484, 0x660484 }, - { 0x0488, 0x660488 }, - { 0x048c, 0x66048c }, - { 0x0490, 0x660490 }, - { 0x0494, 0x660494 }, - { 0x0498, 0x660498 }, - { 0x04a0, 0x6604a0 }, - { 0x04b0, 0x6604b0 }, - { 0x04b8, 0x6604b8 }, - { 0x04bc, 0x6604bc }, - { 0x04c0, 0x6604c0 }, - { 0x04c4, 0x6604c4 }, - { 0x04c8, 0x6604c8 }, - { 0x04d0, 0x6604d0 }, - { 0x04d4, 0x6604d4 }, - { 0x04e0, 0x6604e0 }, - { 0x04e4, 0x6604e4 }, - { 0x04e8, 0x6604e8 }, - { 0x04ec, 0x6604ec }, - { 0x04f0, 0x6604f0 }, - { 0x04f4, 0x6604f4 }, - { 0x04f8, 0x6604f8 }, - { 0x04fc, 0x6604fc }, - { 0x0500, 0x660500 }, - { 0x0504, 0x660504 }, - { 0x0508, 0x660508 }, - { 0x050c, 0x66050c }, - { 0x0510, 0x660510 }, - { 0x0514, 0x660514 }, - { 0x0518, 0x660518 }, - { 0x051c, 0x66051c }, - { 0x0520, 0x660520 }, - { 0x0524, 0x660524 }, - { 0x052c, 0x66052c }, - { 0x0530, 0x660530 }, - { 0x054c, 0x66054c }, - { 0x0550, 0x660550 }, - { 0x0554, 0x660554 }, - { 0x0558, 0x660558 }, - { 0x055c, 0x66055c }, - {} - } -}; - -const struct nv50_disp_chan_mthd -gk104_disp_core_mthd = { - .name = "Core", - .addr = 0x000000, - .prev = -0x020000, - .data = { - { "Global", 1, &gf119_disp_core_mthd_base }, - { "DAC", 3, &gf119_disp_core_mthd_dac }, - { "SOR", 8, &gf119_disp_core_mthd_sor }, - { "PIOR", 4, &gf119_disp_core_mthd_pior }, - { "HEAD", 4, &gk104_disp_core_mthd_head }, - {} - } -}; - -int -gk104_disp_core_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nvkm_disp *disp, struct nvkm_object **pobject) -{ - return nv50_disp_core_new_(&gf119_disp_core_func, &gk104_disp_core_mthd, - disp, 0, oclass, argv, argc, pobject); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregp102.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregp102.c deleted file mode 100644 index 85ad60797bf7..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregp102.c +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 2016 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. - * - * Authors: Ben Skeggs <bskeggs@redhat.com> - */ -#include "channv50.h" - -#include <subdev/timer.h> - -static int -gp102_disp_core_init(struct nv50_disp_chan *chan) -{ - struct nvkm_subdev *subdev = &chan->disp->engine.subdev; - struct nvkm_device *device = subdev->device; - - /* initialise channel for dma command submission */ - nvkm_wr32(device, 0x611494, chan->push); - nvkm_wr32(device, 0x611498, 0x00010000); - nvkm_wr32(device, 0x61149c, 0x00000001); - nvkm_mask(device, 0x610490, 0x00000010, 0x00000010); - nvkm_wr32(device, 0x640000, chan->suspend_put); - nvkm_wr32(device, 0x610490, 0x01000013); - - /* wait for it to go inactive */ - if (nvkm_msec(device, 2000, - if (!(nvkm_rd32(device, 0x610490) & 0x80000000)) - break; - ) < 0) { - nvkm_error(subdev, "core init: %08x\n", - nvkm_rd32(device, 0x610490)); - return -EBUSY; - } - - return 0; -} - -static const struct nv50_disp_chan_func -gp102_disp_core_func = { - .init = gp102_disp_core_init, - .fini = gf119_disp_core_fini, - .intr = gf119_disp_chan_intr, - .user = nv50_disp_chan_user, - .bind = gf119_disp_dmac_bind, -}; - -int -gp102_disp_core_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nvkm_disp *disp, struct nvkm_object **pobject) -{ - return nv50_disp_core_new_(&gp102_disp_core_func, &gk104_disp_core_mthd, - disp, 0, oclass, argv, argc, pobject); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregv100.c deleted file mode 100644 index 73179bd3ea96..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregv100.c +++ /dev/null @@ -1,207 +0,0 @@ -/* - * 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 "channv50.h" - -#include <subdev/timer.h> - -static const struct nv50_disp_mthd_list -gv100_disp_core_mthd_base = { - .mthd = 0x0000, - .addr = 0x000000, - .data = { - { 0x0200, 0x680200 }, - { 0x0208, 0x680208 }, - { 0x020c, 0x68020c }, - { 0x0210, 0x680210 }, - { 0x0214, 0x680214 }, - { 0x0218, 0x680218 }, - { 0x021c, 0x68021c }, - {} - } -}; - -static const struct nv50_disp_mthd_list -gv100_disp_core_mthd_sor = { - .mthd = 0x0020, - .addr = 0x000020, - .data = { - { 0x0300, 0x680300 }, - { 0x0304, 0x680304 }, - { 0x0308, 0x680308 }, - { 0x030c, 0x68030c }, - {} - } -}; - -static const struct nv50_disp_mthd_list -gv100_disp_core_mthd_wndw = { - .mthd = 0x0080, - .addr = 0x000080, - .data = { - { 0x1000, 0x681000 }, - { 0x1004, 0x681004 }, - { 0x1008, 0x681008 }, - { 0x100c, 0x68100c }, - { 0x1010, 0x681010 }, - {} - } -}; - -static const struct nv50_disp_mthd_list -gv100_disp_core_mthd_head = { - .mthd = 0x0400, - .addr = 0x000400, - .data = { - { 0x2000, 0x682000 }, - { 0x2004, 0x682004 }, - { 0x2008, 0x682008 }, - { 0x200c, 0x68200c }, - { 0x2014, 0x682014 }, - { 0x2018, 0x682018 }, - { 0x201c, 0x68201c }, - { 0x2020, 0x682020 }, - { 0x2028, 0x682028 }, - { 0x202c, 0x68202c }, - { 0x2030, 0x682030 }, - { 0x2038, 0x682038 }, - { 0x203c, 0x68203c }, - { 0x2048, 0x682048 }, - { 0x204c, 0x68204c }, - { 0x2050, 0x682050 }, - { 0x2054, 0x682054 }, - { 0x2058, 0x682058 }, - { 0x205c, 0x68205c }, - { 0x2060, 0x682060 }, - { 0x2064, 0x682064 }, - { 0x2068, 0x682068 }, - { 0x206c, 0x68206c }, - { 0x2070, 0x682070 }, - { 0x2074, 0x682074 }, - { 0x2078, 0x682078 }, - { 0x207c, 0x68207c }, - { 0x2080, 0x682080 }, - { 0x2088, 0x682088 }, - { 0x2090, 0x682090 }, - { 0x209c, 0x68209c }, - { 0x20a0, 0x6820a0 }, - { 0x20a4, 0x6820a4 }, - { 0x20a8, 0x6820a8 }, - { 0x20ac, 0x6820ac }, - { 0x2180, 0x682180 }, - { 0x2184, 0x682184 }, - { 0x218c, 0x68218c }, - { 0x2194, 0x682194 }, - { 0x2198, 0x682198 }, - { 0x219c, 0x68219c }, - { 0x21a0, 0x6821a0 }, - { 0x21a4, 0x6821a4 }, - { 0x2214, 0x682214 }, - { 0x2218, 0x682218 }, - {} - } -}; - -static const struct nv50_disp_chan_mthd -gv100_disp_core_mthd = { - .name = "Core", - .addr = 0x000000, - .prev = 0x008000, - .data = { - { "Global", 1, &gv100_disp_core_mthd_base }, - { "SOR", 4, &gv100_disp_core_mthd_sor }, - { "WINDOW", 8, &gv100_disp_core_mthd_wndw }, - { "HEAD", 4, &gv100_disp_core_mthd_head }, - {} - } -}; - -static int -gv100_disp_core_idle(struct nv50_disp_chan *chan) -{ - struct nvkm_device *device = chan->disp->engine.subdev.device; - nvkm_msec(device, 2000, - u32 stat = nvkm_rd32(device, 0x610630); - if ((stat & 0x001f0000) == 0x000b0000) - return 0; - ); - return -EBUSY; -} - -static u64 -gv100_disp_core_user(struct nv50_disp_chan *chan, u64 *psize) -{ - *psize = 0x10000; - return 0x680000; -} - -static void -gv100_disp_core_intr(struct nv50_disp_chan *chan, bool en) -{ - struct nvkm_device *device = chan->disp->engine.subdev.device; - const u32 mask = 0x00000001; - const u32 data = en ? mask : 0; - nvkm_mask(device, 0x611dac, mask, data); -} - -static void -gv100_disp_core_fini(struct nv50_disp_chan *chan) -{ - struct nvkm_device *device = chan->disp->engine.subdev.device; - nvkm_mask(device, 0x6104e0, 0x00000010, 0x00000000); - gv100_disp_core_idle(chan); - nvkm_mask(device, 0x6104e0, 0x00000002, 0x00000000); - chan->suspend_put = nvkm_rd32(device, 0x680000); -} - -static int -gv100_disp_core_init(struct nv50_disp_chan *chan) -{ - struct nvkm_subdev *subdev = &chan->disp->engine.subdev; - struct nvkm_device *device = subdev->device; - - nvkm_wr32(device, 0x610b24, lower_32_bits(chan->push)); - nvkm_wr32(device, 0x610b20, upper_32_bits(chan->push)); - nvkm_wr32(device, 0x610b28, 0x00000001); - nvkm_wr32(device, 0x610b2c, 0x00000040); - - nvkm_mask(device, 0x6104e0, 0x00000010, 0x00000010); - nvkm_wr32(device, 0x680000, chan->suspend_put); - nvkm_wr32(device, 0x6104e0, 0x00000013); - return gv100_disp_core_idle(chan); -} - -static const struct nv50_disp_chan_func -gv100_disp_core = { - .init = gv100_disp_core_init, - .fini = gv100_disp_core_fini, - .intr = gv100_disp_core_intr, - .user = gv100_disp_core_user, - .bind = gv100_disp_dmac_bind, -}; - -int -gv100_disp_core_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nvkm_disp *disp, struct nvkm_object **pobject) -{ - return nv50_disp_core_new_(&gv100_disp_core, &gv100_disp_core_mthd, - disp, 0, oclass, argv, argc, pobject); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/corenv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/corenv50.c deleted file mode 100644 index 4bf04a254267..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/corenv50.c +++ /dev/null @@ -1,234 +0,0 @@ -/* - * Copyright 2012 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. - * - * Authors: Ben Skeggs - */ -#include "channv50.h" - -#include <core/client.h> -#include <subdev/timer.h> - -#include <nvif/cl507d.h> -#include <nvif/unpack.h> - -int -nv50_disp_core_new_(const struct nv50_disp_chan_func *func, - const struct nv50_disp_chan_mthd *mthd, - struct nvkm_disp *disp, int chid, - const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nvkm_object **pobject) -{ - union { - struct nv50_disp_core_channel_dma_v0 v0; - } *args = argv; - struct nvkm_object *parent = oclass->parent; - u64 push; - int ret = -ENOSYS; - - nvif_ioctl(parent, "create disp core channel dma size %d\n", argc); - if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, false))) { - nvif_ioctl(parent, "create disp core channel dma vers %d " - "pushbuf %016llx\n", - args->v0.version, args->v0.pushbuf); - push = args->v0.pushbuf; - } else - return ret; - - return nv50_disp_dmac_new_(func, mthd, disp, chid, 0, - push, oclass, pobject); -} - -const struct nv50_disp_mthd_list -nv50_disp_core_mthd_base = { - .mthd = 0x0000, - .addr = 0x000000, - .data = { - { 0x0080, 0x000000 }, - { 0x0084, 0x610bb8 }, - { 0x0088, 0x610b9c }, - { 0x008c, 0x000000 }, - {} - } -}; - -static const struct nv50_disp_mthd_list -nv50_disp_core_mthd_dac = { - .mthd = 0x0080, - .addr = 0x000008, - .data = { - { 0x0400, 0x610b58 }, - { 0x0404, 0x610bdc }, - { 0x0420, 0x610828 }, - {} - } -}; - -const struct nv50_disp_mthd_list -nv50_disp_core_mthd_sor = { - .mthd = 0x0040, - .addr = 0x000008, - .data = { - { 0x0600, 0x610b70 }, - {} - } -}; - -const struct nv50_disp_mthd_list -nv50_disp_core_mthd_pior = { - .mthd = 0x0040, - .addr = 0x000008, - .data = { - { 0x0700, 0x610b80 }, - {} - } -}; - -static const struct nv50_disp_mthd_list -nv50_disp_core_mthd_head = { - .mthd = 0x0400, - .addr = 0x000540, - .data = { - { 0x0800, 0x610ad8 }, - { 0x0804, 0x610ad0 }, - { 0x0808, 0x610a48 }, - { 0x080c, 0x610a78 }, - { 0x0810, 0x610ac0 }, - { 0x0814, 0x610af8 }, - { 0x0818, 0x610b00 }, - { 0x081c, 0x610ae8 }, - { 0x0820, 0x610af0 }, - { 0x0824, 0x610b08 }, - { 0x0828, 0x610b10 }, - { 0x082c, 0x610a68 }, - { 0x0830, 0x610a60 }, - { 0x0834, 0x000000 }, - { 0x0838, 0x610a40 }, - { 0x0840, 0x610a24 }, - { 0x0844, 0x610a2c }, - { 0x0848, 0x610aa8 }, - { 0x084c, 0x610ab0 }, - { 0x0860, 0x610a84 }, - { 0x0864, 0x610a90 }, - { 0x0868, 0x610b18 }, - { 0x086c, 0x610b20 }, - { 0x0870, 0x610ac8 }, - { 0x0874, 0x610a38 }, - { 0x0880, 0x610a58 }, - { 0x0884, 0x610a9c }, - { 0x08a0, 0x610a70 }, - { 0x08a4, 0x610a50 }, - { 0x08a8, 0x610ae0 }, - { 0x08c0, 0x610b28 }, - { 0x08c4, 0x610b30 }, - { 0x08c8, 0x610b40 }, - { 0x08d4, 0x610b38 }, - { 0x08d8, 0x610b48 }, - { 0x08dc, 0x610b50 }, - { 0x0900, 0x610a18 }, - { 0x0904, 0x610ab8 }, - {} - } -}; - -static const struct nv50_disp_chan_mthd -nv50_disp_core_mthd = { - .name = "Core", - .addr = 0x000000, - .prev = 0x000004, - .data = { - { "Global", 1, &nv50_disp_core_mthd_base }, - { "DAC", 3, &nv50_disp_core_mthd_dac }, - { "SOR", 2, &nv50_disp_core_mthd_sor }, - { "PIOR", 3, &nv50_disp_core_mthd_pior }, - { "HEAD", 2, &nv50_disp_core_mthd_head }, - {} - } -}; - -static void -nv50_disp_core_fini(struct nv50_disp_chan *chan) -{ - struct nvkm_subdev *subdev = &chan->disp->engine.subdev; - struct nvkm_device *device = subdev->device; - - /* deactivate channel */ - nvkm_mask(device, 0x610200, 0x00000010, 0x00000000); - nvkm_mask(device, 0x610200, 0x00000003, 0x00000000); - if (nvkm_msec(device, 2000, - if (!(nvkm_rd32(device, 0x610200) & 0x001e0000)) - break; - ) < 0) { - nvkm_error(subdev, "core fini: %08x\n", - nvkm_rd32(device, 0x610200)); - } - - chan->suspend_put = nvkm_rd32(device, 0x640000); -} - -static int -nv50_disp_core_init(struct nv50_disp_chan *chan) -{ - struct nvkm_subdev *subdev = &chan->disp->engine.subdev; - struct nvkm_device *device = subdev->device; - - /* attempt to unstick channel from some unknown state */ - if ((nvkm_rd32(device, 0x610200) & 0x009f0000) == 0x00020000) - nvkm_mask(device, 0x610200, 0x00800000, 0x00800000); - if ((nvkm_rd32(device, 0x610200) & 0x003f0000) == 0x00030000) - nvkm_mask(device, 0x610200, 0x00600000, 0x00600000); - - /* initialise channel for dma command submission */ - nvkm_wr32(device, 0x610204, chan->push); - nvkm_wr32(device, 0x610208, 0x00010000); - nvkm_wr32(device, 0x61020c, 0x00000000); - nvkm_mask(device, 0x610200, 0x00000010, 0x00000010); - nvkm_wr32(device, 0x640000, chan->suspend_put); - nvkm_wr32(device, 0x610200, 0x01000013); - - /* wait for it to go inactive */ - if (nvkm_msec(device, 2000, - if (!(nvkm_rd32(device, 0x610200) & 0x80000000)) - break; - ) < 0) { - nvkm_error(subdev, "core init: %08x\n", - nvkm_rd32(device, 0x610200)); - return -EBUSY; - } - - return 0; -} - -const struct nv50_disp_chan_func -nv50_disp_core_func = { - .init = nv50_disp_core_init, - .fini = nv50_disp_core_fini, - .intr = nv50_disp_chan_intr, - .user = nv50_disp_chan_user, - .bind = nv50_disp_dmac_bind, -}; - -int -nv50_disp_core_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nvkm_disp *disp, struct nvkm_object **pobject) -{ - return nv50_disp_core_new_(&nv50_disp_core_func, &nv50_disp_core_mthd, - disp, 0, oclass, argv, argc, pobject); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgf119.c deleted file mode 100644 index 274bb8055295..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgf119.c +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2012 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. - * - * Authors: Ben Skeggs - */ -#include "channv50.h" - -int -gf119_disp_curs_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nvkm_disp *disp, struct nvkm_object **pobject) -{ - return nv50_disp_curs_new_(&gf119_disp_pioc_func, disp, 13, 13, - oclass, argv, argc, pobject); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgp102.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgp102.c deleted file mode 100644 index 17c798ffe54c..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgp102.c +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2016 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. - * - * Authors: Ben Skeggs <bskeggs@redhat.com> - */ -#include "channv50.h" - -int -gp102_disp_curs_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nvkm_disp *disp, struct nvkm_object **pobject) -{ - return nv50_disp_curs_new_(&gf119_disp_pioc_func, disp, 13, 17, - oclass, argv, argc, pobject); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgv100.c deleted file mode 100644 index 5b96dbe75a83..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgv100.c +++ /dev/null @@ -1,81 +0,0 @@ -/* - * 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 "channv50.h" - -#include <subdev/timer.h> - -static int -gv100_disp_curs_idle(struct nv50_disp_chan *chan) -{ - struct nvkm_device *device = chan->disp->engine.subdev.device; - const u32 soff = (chan->chid.ctrl - 1) * 0x04; - nvkm_msec(device, 2000, - u32 stat = nvkm_rd32(device, 0x610664 + soff); - if ((stat & 0x00070000) == 0x00040000) - return 0; - ); - return -EBUSY; -} - -static void -gv100_disp_curs_intr(struct nv50_disp_chan *chan, bool en) -{ - struct nvkm_device *device = chan->disp->engine.subdev.device; - const u32 mask = 0x00010000 << chan->head; - const u32 data = en ? mask : 0; - nvkm_mask(device, 0x611dac, mask, data); -} - -static void -gv100_disp_curs_fini(struct nv50_disp_chan *chan) -{ - struct nvkm_device *device = chan->disp->engine.subdev.device; - const u32 hoff = chan->chid.ctrl * 4; - nvkm_mask(device, 0x6104e0 + hoff, 0x00000010, 0x00000010); - gv100_disp_curs_idle(chan); - nvkm_mask(device, 0x6104e0 + hoff, 0x00000001, 0x00000000); -} - -static int -gv100_disp_curs_init(struct nv50_disp_chan *chan) -{ - struct nvkm_subdev *subdev = &chan->disp->engine.subdev; - struct nvkm_device *device = subdev->device; - nvkm_wr32(device, 0x6104e0 + chan->chid.ctrl * 4, 0x00000001); - return gv100_disp_curs_idle(chan); -} - -static const struct nv50_disp_chan_func -gv100_disp_curs = { - .init = gv100_disp_curs_init, - .fini = gv100_disp_curs_fini, - .intr = gv100_disp_curs_intr, - .user = gv100_disp_chan_user, -}; - -int -gv100_disp_curs_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nvkm_disp *disp, struct nvkm_object **pobject) -{ - return nv50_disp_curs_new_(&gv100_disp_curs, disp, 73, 73, - oclass, argv, argc, pobject); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursnv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursnv50.c deleted file mode 100644 index 3cd6a3f36cf7..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursnv50.c +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright 2012 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. - * - * Authors: Ben Skeggs - */ -#include "channv50.h" -#include "head.h" - -#include <core/client.h> - -#include <nvif/cl507a.h> -#include <nvif/unpack.h> - -int -nv50_disp_curs_new_(const struct nv50_disp_chan_func *func, - struct nvkm_disp *disp, int ctrl, int user, - const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nvkm_object **pobject) -{ - union { - struct nv50_disp_cursor_v0 v0; - } *args = argv; - struct nvkm_object *parent = oclass->parent; - int head, ret = -ENOSYS; - - nvif_ioctl(parent, "create disp cursor size %d\n", argc); - if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, false))) { - nvif_ioctl(parent, "create disp cursor vers %d head %d\n", - args->v0.version, args->v0.head); - if (!nvkm_head_find(disp, args->v0.head)) - return -EINVAL; - head = args->v0.head; - } else - return ret; - - return nv50_disp_chan_new_(func, NULL, disp, ctrl + head, user + head, - head, oclass, pobject); -} - -int -nv50_disp_curs_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nvkm_disp *disp, struct nvkm_object **pobject) -{ - return nv50_disp_curs_new_(&nv50_disp_pioc_func, disp, 7, 7, - oclass, argv, argc, pobject); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dacgf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dacgf119.c deleted file mode 100644 index 71a94777ea2e..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dacgf119.c +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 2017 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" - -static void -gf119_dac_clock(struct nvkm_ior *dac) -{ - struct nvkm_device *device = dac->disp->engine.subdev.device; - const u32 doff = nv50_ior_base(dac); - nvkm_mask(device, 0x612280 + doff, 0x07070707, 0x00000000); -} - -static void -gf119_dac_state(struct nvkm_ior *dac, struct nvkm_ior_state *state) -{ - struct nvkm_device *device = dac->disp->engine.subdev.device; - const u32 coff = (state == &dac->asy) * 0x20000 + dac->id * 0x20; - u32 ctrl = nvkm_rd32(device, 0x640180 + coff); - - state->proto_evo = (ctrl & 0x00000f00) >> 8; - switch (state->proto_evo) { - case 0: state->proto = CRT; break; - default: - state->proto = UNKNOWN; - break; - } - - state->head = ctrl & 0x0000000f; -} - -static const struct nvkm_ior_func -gf119_dac = { - .state = gf119_dac_state, - .power = nv50_dac_power, - .sense = nv50_dac_sense, - .clock = gf119_dac_clock, -}; - -int -gf119_dac_new(struct nvkm_disp *disp, int id) -{ - return nvkm_ior_new_(&gf119_dac, disp, DAC, id); -} - -int -gf119_dac_cnt(struct nvkm_disp *disp, unsigned long *pmask) -{ - struct nvkm_device *device = disp->engine.subdev.device; - *pmask = (nvkm_rd32(device, 0x612004) & 0x000000f0) >> 4; - return 4; -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dacnv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dacnv50.c deleted file mode 100644 index 558012db35f8..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dacnv50.c +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright 2012 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. - * - * Authors: Ben Skeggs - */ -#include "ior.h" - -#include <subdev/timer.h> - -static void -nv50_dac_clock(struct nvkm_ior *dac) -{ - struct nvkm_device *device = dac->disp->engine.subdev.device; - const u32 doff = nv50_ior_base(dac); - nvkm_mask(device, 0x614280 + doff, 0x07070707, 0x00000000); -} - -int -nv50_dac_sense(struct nvkm_ior *dac, u32 loadval) -{ - struct nvkm_device *device = dac->disp->engine.subdev.device; - const u32 doff = nv50_ior_base(dac); - - dac->func->power(dac, false, true, false, false, false); - - nvkm_wr32(device, 0x61a00c + doff, 0x00100000 | loadval); - mdelay(9); - udelay(500); - loadval = nvkm_mask(device, 0x61a00c + doff, 0xffffffff, 0x00000000); - - dac->func->power(dac, false, false, false, false, false); - if (!(loadval & 0x80000000)) - return -ETIMEDOUT; - - return (loadval & 0x38000000) >> 27; -} - -static void -nv50_dac_power_wait(struct nvkm_device *device, const u32 doff) -{ - nvkm_msec(device, 2000, - if (!(nvkm_rd32(device, 0x61a004 + doff) & 0x80000000)) - break; - ); -} - -void -nv50_dac_power(struct nvkm_ior *dac, bool normal, bool pu, - bool data, bool vsync, bool hsync) -{ - struct nvkm_device *device = dac->disp->engine.subdev.device; - const u32 doff = nv50_ior_base(dac); - const u32 shift = normal ? 0 : 16; - const u32 state = 0x80000000 | (0x00000040 * ! pu | - 0x00000010 * ! data | - 0x00000004 * ! vsync | - 0x00000001 * ! hsync) << shift; - const u32 field = 0xc0000000 | (0x00000055 << shift); - - nv50_dac_power_wait(device, doff); - nvkm_mask(device, 0x61a004 + doff, field, state); - nv50_dac_power_wait(device, doff); -} - -static void -nv50_dac_state(struct nvkm_ior *dac, struct nvkm_ior_state *state) -{ - struct nvkm_device *device = dac->disp->engine.subdev.device; - const u32 coff = dac->id * 8 + (state == &dac->arm) * 4; - u32 ctrl = nvkm_rd32(device, 0x610b58 + coff); - - state->proto_evo = (ctrl & 0x00000f00) >> 8; - switch (state->proto_evo) { - case 0: state->proto = CRT; break; - default: - state->proto = UNKNOWN; - break; - } - - state->head = ctrl & 0x00000003; -} - -static const struct nvkm_ior_func -nv50_dac = { - .state = nv50_dac_state, - .power = nv50_dac_power, - .sense = nv50_dac_sense, - .clock = nv50_dac_clock, -}; - -int -nv50_dac_new(struct nvkm_disp *disp, int id) -{ - return nvkm_ior_new_(&nv50_dac, disp, DAC, id); -} - -int -nv50_dac_cnt(struct nvkm_disp *disp, unsigned long *pmask) -{ - struct nvkm_device *device = disp->engine.subdev.device; - *pmask = (nvkm_rd32(device, 0x610184) & 0x00700000) >> 20; - return 3; -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgf119.c deleted file mode 100644 index 5f9fa8af1f83..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgf119.c +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright 2012 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. - * - * Authors: Ben Skeggs - */ -#include "channv50.h" - -#include <core/ramht.h> -#include <subdev/timer.h> - -int -gf119_disp_dmac_bind(struct nv50_disp_chan *chan, - struct nvkm_object *object, u32 handle) -{ - return nvkm_ramht_insert(chan->disp->ramht, object, - chan->chid.user, -9, handle, - chan->chid.user << 27 | 0x00000001); -} - -void -gf119_disp_dmac_fini(struct nv50_disp_chan *chan) -{ - struct nvkm_subdev *subdev = &chan->disp->engine.subdev; - struct nvkm_device *device = subdev->device; - int ctrl = chan->chid.ctrl; - int user = chan->chid.user; - - /* deactivate channel */ - nvkm_mask(device, 0x610490 + (ctrl * 0x0010), 0x00001010, 0x00001000); - nvkm_mask(device, 0x610490 + (ctrl * 0x0010), 0x00000003, 0x00000000); - if (nvkm_msec(device, 2000, - if (!(nvkm_rd32(device, 0x610490 + (ctrl * 0x10)) & 0x001e0000)) - break; - ) < 0) { - nvkm_error(subdev, "ch %d fini: %08x\n", user, - nvkm_rd32(device, 0x610490 + (ctrl * 0x10))); - } - - chan->suspend_put = nvkm_rd32(device, 0x640000 + (ctrl * 0x1000)); -} - -static int -gf119_disp_dmac_init(struct nv50_disp_chan *chan) -{ - struct nvkm_subdev *subdev = &chan->disp->engine.subdev; - struct nvkm_device *device = subdev->device; - int ctrl = chan->chid.ctrl; - int user = chan->chid.user; - - /* initialise channel for dma command submission */ - nvkm_wr32(device, 0x610494 + (ctrl * 0x0010), chan->push); - nvkm_wr32(device, 0x610498 + (ctrl * 0x0010), 0x00010000); - nvkm_wr32(device, 0x61049c + (ctrl * 0x0010), 0x00000001); - nvkm_mask(device, 0x610490 + (ctrl * 0x0010), 0x00000010, 0x00000010); - nvkm_wr32(device, 0x640000 + (ctrl * 0x1000), chan->suspend_put); - nvkm_wr32(device, 0x610490 + (ctrl * 0x0010), 0x00000013); - - /* wait for it to go inactive */ - if (nvkm_msec(device, 2000, - if (!(nvkm_rd32(device, 0x610490 + (ctrl * 0x10)) & 0x80000000)) - break; - ) < 0) { - nvkm_error(subdev, "ch %d init: %08x\n", user, - nvkm_rd32(device, 0x610490 + (ctrl * 0x10))); - return -EBUSY; - } - - return 0; -} - -const struct nv50_disp_chan_func -gf119_disp_dmac_func = { - .init = gf119_disp_dmac_init, - .fini = gf119_disp_dmac_fini, - .intr = gf119_disp_chan_intr, - .user = nv50_disp_chan_user, - .bind = gf119_disp_dmac_bind, -}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgp102.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgp102.c deleted file mode 100644 index f8fd2bbca46a..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgp102.c +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright 2016 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. - * - * Authors: Ben Skeggs <bskeggs@redhat.com> - */ -#include "channv50.h" - -#include <subdev/timer.h> - -static int -gp102_disp_dmac_init(struct nv50_disp_chan *chan) -{ - struct nvkm_subdev *subdev = &chan->disp->engine.subdev; - struct nvkm_device *device = subdev->device; - int ctrl = chan->chid.ctrl; - int user = chan->chid.user; - - /* initialise channel for dma command submission */ - nvkm_wr32(device, 0x611494 + (ctrl * 0x0010), chan->push); - nvkm_wr32(device, 0x611498 + (ctrl * 0x0010), 0x00010000); - nvkm_wr32(device, 0x61149c + (ctrl * 0x0010), 0x00000001); - nvkm_mask(device, 0x610490 + (ctrl * 0x0010), 0x00000010, 0x00000010); - nvkm_wr32(device, 0x640000 + (ctrl * 0x1000), chan->suspend_put); - nvkm_wr32(device, 0x610490 + (ctrl * 0x0010), 0x00000013); - - /* wait for it to go inactive */ - if (nvkm_msec(device, 2000, - if (!(nvkm_rd32(device, 0x610490 + (ctrl * 0x10)) & 0x80000000)) - break; - ) < 0) { - nvkm_error(subdev, "ch %d init: %08x\n", user, - nvkm_rd32(device, 0x610490 + (ctrl * 0x10))); - return -EBUSY; - } - - return 0; -} - -const struct nv50_disp_chan_func -gp102_disp_dmac_func = { - .init = gp102_disp_dmac_init, - .fini = gf119_disp_dmac_fini, - .intr = gf119_disp_chan_intr, - .user = nv50_disp_chan_user, - .bind = gf119_disp_dmac_bind, -}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgv100.c deleted file mode 100644 index 2bc976c106f8..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgv100.c +++ /dev/null @@ -1,79 +0,0 @@ -/* - * 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 "channv50.h" - -#include <core/ramht.h> -#include <subdev/timer.h> - -static int -gv100_disp_dmac_idle(struct nv50_disp_chan *chan) -{ - struct nvkm_device *device = chan->disp->engine.subdev.device; - const u32 soff = (chan->chid.ctrl - 1) * 0x04; - nvkm_msec(device, 2000, - u32 stat = nvkm_rd32(device, 0x610664 + soff); - if ((stat & 0x000f0000) == 0x00040000) - return 0; - ); - return -EBUSY; -} - -int -gv100_disp_dmac_bind(struct nv50_disp_chan *chan, - struct nvkm_object *object, u32 handle) -{ - return nvkm_ramht_insert(chan->disp->ramht, object, - chan->chid.user, -9, handle, - chan->chid.user << 25 | 0x00000040); -} - -void -gv100_disp_dmac_fini(struct nv50_disp_chan *chan) -{ - struct nvkm_device *device = chan->disp->engine.subdev.device; - const u32 uoff = (chan->chid.ctrl - 1) * 0x1000; - const u32 coff = chan->chid.ctrl * 0x04; - nvkm_mask(device, 0x6104e0 + coff, 0x00000010, 0x00000000); - gv100_disp_dmac_idle(chan); - nvkm_mask(device, 0x6104e0 + coff, 0x00000002, 0x00000000); - chan->suspend_put = nvkm_rd32(device, 0x690000 + uoff); -} - -int -gv100_disp_dmac_init(struct nv50_disp_chan *chan) -{ - struct nvkm_subdev *subdev = &chan->disp->engine.subdev; - struct nvkm_device *device = subdev->device; - const u32 uoff = (chan->chid.ctrl - 1) * 0x1000; - const u32 poff = chan->chid.ctrl * 0x10; - const u32 coff = chan->chid.ctrl * 0x04; - - nvkm_wr32(device, 0x610b24 + poff, lower_32_bits(chan->push)); - nvkm_wr32(device, 0x610b20 + poff, upper_32_bits(chan->push)); - nvkm_wr32(device, 0x610b28 + poff, 0x00000001); - nvkm_wr32(device, 0x610b2c + poff, 0x00000040); - - nvkm_mask(device, 0x6104e0 + coff, 0x00000010, 0x00000010); - nvkm_wr32(device, 0x690000 + uoff, chan->suspend_put); - nvkm_wr32(device, 0x6104e0 + coff, 0x00000013); - return gv100_disp_dmac_idle(chan); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacnv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacnv50.c deleted file mode 100644 index cf44d471c1c6..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacnv50.c +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright 2012 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. - * - * Authors: Ben Skeggs - */ -#include "channv50.h" - -#include <core/client.h> -#include <core/ramht.h> -#include <subdev/fb.h> -#include <subdev/mmu.h> -#include <subdev/timer.h> -#include <engine/dma.h> - -int -nv50_disp_dmac_new_(const struct nv50_disp_chan_func *func, - const struct nv50_disp_chan_mthd *mthd, - struct nvkm_disp *disp, int chid, int head, u64 push, - const struct nvkm_oclass *oclass, - struct nvkm_object **pobject) -{ - struct nvkm_client *client = oclass->client; - struct nv50_disp_chan *chan; - int ret; - - ret = nv50_disp_chan_new_(func, mthd, disp, chid, chid, head, oclass, - pobject); - chan = nv50_disp_chan(*pobject); - if (ret) - return ret; - - chan->memory = nvkm_umem_search(client, push); - if (IS_ERR(chan->memory)) - return PTR_ERR(chan->memory); - - if (nvkm_memory_size(chan->memory) < 0x1000) - return -EINVAL; - - switch (nvkm_memory_target(chan->memory)) { - case NVKM_MEM_TARGET_VRAM: chan->push = 0x00000001; break; - case NVKM_MEM_TARGET_NCOH: chan->push = 0x00000002; break; - case NVKM_MEM_TARGET_HOST: chan->push = 0x00000003; break; - default: - return -EINVAL; - } - - chan->push |= nvkm_memory_addr(chan->memory) >> 8; - return 0; -} - -int -nv50_disp_dmac_bind(struct nv50_disp_chan *chan, - struct nvkm_object *object, u32 handle) -{ - return nvkm_ramht_insert(chan->disp->ramht, object, - chan->chid.user, -10, handle, - chan->chid.user << 28 | - chan->chid.user); -} - -static void -nv50_disp_dmac_fini(struct nv50_disp_chan *chan) -{ - struct nvkm_subdev *subdev = &chan->disp->engine.subdev; - struct nvkm_device *device = subdev->device; - int ctrl = chan->chid.ctrl; - int user = chan->chid.user; - - /* deactivate channel */ - nvkm_mask(device, 0x610200 + (ctrl * 0x0010), 0x00001010, 0x00001000); - nvkm_mask(device, 0x610200 + (ctrl * 0x0010), 0x00000003, 0x00000000); - if (nvkm_msec(device, 2000, - if (!(nvkm_rd32(device, 0x610200 + (ctrl * 0x10)) & 0x001e0000)) - break; - ) < 0) { - nvkm_error(subdev, "ch %d fini timeout, %08x\n", user, - nvkm_rd32(device, 0x610200 + (ctrl * 0x10))); - } - - chan->suspend_put = nvkm_rd32(device, 0x640000 + (ctrl * 0x1000)); -} - -static int -nv50_disp_dmac_init(struct nv50_disp_chan *chan) -{ - struct nvkm_subdev *subdev = &chan->disp->engine.subdev; - struct nvkm_device *device = subdev->device; - int ctrl = chan->chid.ctrl; - int user = chan->chid.user; - - /* initialise channel for dma command submission */ - nvkm_wr32(device, 0x610204 + (ctrl * 0x0010), chan->push); - nvkm_wr32(device, 0x610208 + (ctrl * 0x0010), 0x00010000); - nvkm_wr32(device, 0x61020c + (ctrl * 0x0010), ctrl); - nvkm_mask(device, 0x610200 + (ctrl * 0x0010), 0x00000010, 0x00000010); - nvkm_wr32(device, 0x640000 + (ctrl * 0x1000), chan->suspend_put); - nvkm_wr32(device, 0x610200 + (ctrl * 0x0010), 0x00000013); - - /* wait for it to go inactive */ - if (nvkm_msec(device, 2000, - if (!(nvkm_rd32(device, 0x610200 + (ctrl * 0x10)) & 0x80000000)) - break; - ) < 0) { - nvkm_error(subdev, "ch %d init timeout, %08x\n", user, - nvkm_rd32(device, 0x610200 + (ctrl * 0x10))); - return -EBUSY; - } - - return 0; -} - -const struct nv50_disp_chan_func -nv50_disp_dmac_func = { - .init = nv50_disp_dmac_init, - .fini = nv50_disp_dmac_fini, - .intr = nv50_disp_chan_intr, - .user = nv50_disp_chan_user, - .bind = nv50_disp_dmac_bind, -}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/g84.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/g84.c index 752753d84de5..69ef40fe57d0 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/g84.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/g84.c @@ -22,16 +22,284 @@ * Authors: Ben Skeggs */ #include "priv.h" +#include "chan.h" +#include "hdmi.h" #include "head.h" #include "ior.h" -#include "channv50.h" #include <nvif/class.h> +void +g84_sor_hdmi_ctrl(struct nvkm_ior *ior, int head, bool enable, u8 max_ac_packet, + u8 rekey, u8 *avi, u8 avi_size, u8 *vendor, u8 vendor_size) +{ + struct nvkm_device *device = ior->disp->engine.subdev.device; + const u32 ctrl = 0x40000000 * enable | + 0x1f000000 /* ??? */ | + max_ac_packet << 16 | + rekey; + const u32 hoff = head * 0x800; + struct packed_hdmi_infoframe avi_infoframe; + struct packed_hdmi_infoframe vendor_infoframe; + + pack_hdmi_infoframe(&avi_infoframe, avi, avi_size); + pack_hdmi_infoframe(&vendor_infoframe, vendor, vendor_size); + + if (!(ctrl & 0x40000000)) { + nvkm_mask(device, 0x6165a4 + hoff, 0x40000000, 0x00000000); + nvkm_mask(device, 0x61653c + hoff, 0x00000001, 0x00000000); + nvkm_mask(device, 0x616520 + hoff, 0x00000001, 0x00000000); + nvkm_mask(device, 0x616500 + hoff, 0x00000001, 0x00000000); + return; + } + + /* AVI InfoFrame */ + nvkm_mask(device, 0x616520 + hoff, 0x00000001, 0x00000000); + if (avi_size) { + nvkm_wr32(device, 0x616528 + hoff, avi_infoframe.header); + nvkm_wr32(device, 0x61652c + hoff, avi_infoframe.subpack0_low); + nvkm_wr32(device, 0x616530 + hoff, avi_infoframe.subpack0_high); + nvkm_wr32(device, 0x616534 + hoff, avi_infoframe.subpack1_low); + nvkm_wr32(device, 0x616538 + hoff, avi_infoframe.subpack1_high); + nvkm_mask(device, 0x616520 + hoff, 0x00000001, 0x00000001); + } + + /* Audio InfoFrame */ + nvkm_mask(device, 0x616500 + hoff, 0x00000001, 0x00000000); + nvkm_wr32(device, 0x616508 + hoff, 0x000a0184); + nvkm_wr32(device, 0x61650c + hoff, 0x00000071); + nvkm_wr32(device, 0x616510 + hoff, 0x00000000); + nvkm_mask(device, 0x616500 + hoff, 0x00000001, 0x00000001); + + /* Vendor InfoFrame */ + nvkm_mask(device, 0x61653c + hoff, 0x00010001, 0x00010000); + if (vendor_size) { + nvkm_wr32(device, 0x616544 + hoff, vendor_infoframe.header); + nvkm_wr32(device, 0x616548 + hoff, vendor_infoframe.subpack0_low); + nvkm_wr32(device, 0x61654c + hoff, vendor_infoframe.subpack0_high); + /* Is there a second (or up to fourth?) set of subpack registers here? */ + /* nvkm_wr32(device, 0x616550 + hoff, vendor_infoframe->subpack1_low); */ + /* nvkm_wr32(device, 0x616554 + hoff, vendor_infoframe->subpack1_high); */ + nvkm_mask(device, 0x61653c + hoff, 0x00010001, 0x00010001); + } + + nvkm_mask(device, 0x6165d0 + hoff, 0x00070001, 0x00010001); /* SPARE, HW_CTS */ + nvkm_mask(device, 0x616568 + hoff, 0x00010101, 0x00000000); /* ACR_CTRL, ?? */ + nvkm_mask(device, 0x616578 + hoff, 0x80000000, 0x80000000); /* ACR_0441_ENABLE */ + + /* ??? */ + nvkm_mask(device, 0x61733c, 0x00100000, 0x00100000); /* RESETF */ + nvkm_mask(device, 0x61733c, 0x10000000, 0x10000000); /* LOOKUP_EN */ + nvkm_mask(device, 0x61733c, 0x00100000, 0x00000000); /* !RESETF */ + + /* HDMI_CTRL */ + nvkm_mask(device, 0x6165a4 + hoff, 0x5f1f007f, ctrl); +} + +static const struct nvkm_ior_func +g84_sor = { + .state = nv50_sor_state, + .power = nv50_sor_power, + .clock = nv50_sor_clock, + .hdmi = { + .ctrl = g84_sor_hdmi_ctrl, + }, +}; + +int +g84_sor_new(struct nvkm_disp *disp, int id) +{ + return nvkm_ior_new_(&g84_sor, disp, SOR, id); +} + +static const struct nvkm_disp_mthd_list +g84_disp_ovly_mthd_base = { + .mthd = 0x0000, + .addr = 0x000000, + .data = { + { 0x0080, 0x000000 }, + { 0x0084, 0x6109a0 }, + { 0x0088, 0x6109c0 }, + { 0x008c, 0x6109c8 }, + { 0x0090, 0x6109b4 }, + { 0x0094, 0x610970 }, + { 0x00a0, 0x610998 }, + { 0x00a4, 0x610964 }, + { 0x00c0, 0x610958 }, + { 0x00e0, 0x6109a8 }, + { 0x00e4, 0x6109d0 }, + { 0x00e8, 0x6109d8 }, + { 0x0100, 0x61094c }, + { 0x0104, 0x610984 }, + { 0x0108, 0x61098c }, + { 0x0800, 0x6109f8 }, + { 0x0808, 0x610a08 }, + { 0x080c, 0x610a10 }, + { 0x0810, 0x610a00 }, + {} + } +}; + +static const struct nvkm_disp_chan_mthd +g84_disp_ovly_mthd = { + .name = "Overlay", + .addr = 0x000540, + .prev = 0x000004, + .data = { + { "Global", 1, &g84_disp_ovly_mthd_base }, + {} + } +}; + +int +g84_disp_ovly_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, + struct nvkm_disp *disp, struct nvkm_object **pobject) +{ + return nv50_disp_ovly_new_(&nv50_disp_dmac_func, &g84_disp_ovly_mthd, + disp, 3, oclass, argv, argc, pobject); +} + +static const struct nvkm_disp_mthd_list +g84_disp_base_mthd_base = { + .mthd = 0x0000, + .addr = 0x000000, + .data = { + { 0x0080, 0x000000 }, + { 0x0084, 0x0008c4 }, + { 0x0088, 0x0008d0 }, + { 0x008c, 0x0008dc }, + { 0x0090, 0x0008e4 }, + { 0x0094, 0x610884 }, + { 0x00a0, 0x6108a0 }, + { 0x00a4, 0x610878 }, + { 0x00c0, 0x61086c }, + { 0x00c4, 0x610800 }, + { 0x00c8, 0x61080c }, + { 0x00cc, 0x610818 }, + { 0x00e0, 0x610858 }, + { 0x00e4, 0x610860 }, + { 0x00e8, 0x6108ac }, + { 0x00ec, 0x6108b4 }, + { 0x00fc, 0x610824 }, + { 0x0100, 0x610894 }, + { 0x0104, 0x61082c }, + { 0x0110, 0x6108bc }, + { 0x0114, 0x61088c }, + {} + } +}; + +static const struct nvkm_disp_chan_mthd +g84_disp_base_mthd = { + .name = "Base", + .addr = 0x000540, + .prev = 0x000004, + .data = { + { "Global", 1, &g84_disp_base_mthd_base }, + { "Image", 2, &nv50_disp_base_mthd_image }, + {} + } +}; + +int +g84_disp_base_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, + struct nvkm_disp *disp, struct nvkm_object **pobject) +{ + return nv50_disp_base_new_(&nv50_disp_dmac_func, &g84_disp_base_mthd, + disp, 1, oclass, argv, argc, pobject); +} + +const struct nvkm_disp_mthd_list +g84_disp_core_mthd_dac = { + .mthd = 0x0080, + .addr = 0x000008, + .data = { + { 0x0400, 0x610b58 }, + { 0x0404, 0x610bdc }, + { 0x0420, 0x610bc4 }, + {} + } +}; + +const struct nvkm_disp_mthd_list +g84_disp_core_mthd_head = { + .mthd = 0x0400, + .addr = 0x000540, + .data = { + { 0x0800, 0x610ad8 }, + { 0x0804, 0x610ad0 }, + { 0x0808, 0x610a48 }, + { 0x080c, 0x610a78 }, + { 0x0810, 0x610ac0 }, + { 0x0814, 0x610af8 }, + { 0x0818, 0x610b00 }, + { 0x081c, 0x610ae8 }, + { 0x0820, 0x610af0 }, + { 0x0824, 0x610b08 }, + { 0x0828, 0x610b10 }, + { 0x082c, 0x610a68 }, + { 0x0830, 0x610a60 }, + { 0x0834, 0x000000 }, + { 0x0838, 0x610a40 }, + { 0x0840, 0x610a24 }, + { 0x0844, 0x610a2c }, + { 0x0848, 0x610aa8 }, + { 0x084c, 0x610ab0 }, + { 0x085c, 0x610c5c }, + { 0x0860, 0x610a84 }, + { 0x0864, 0x610a90 }, + { 0x0868, 0x610b18 }, + { 0x086c, 0x610b20 }, + { 0x0870, 0x610ac8 }, + { 0x0874, 0x610a38 }, + { 0x0878, 0x610c50 }, + { 0x0880, 0x610a58 }, + { 0x0884, 0x610a9c }, + { 0x089c, 0x610c68 }, + { 0x08a0, 0x610a70 }, + { 0x08a4, 0x610a50 }, + { 0x08a8, 0x610ae0 }, + { 0x08c0, 0x610b28 }, + { 0x08c4, 0x610b30 }, + { 0x08c8, 0x610b40 }, + { 0x08d4, 0x610b38 }, + { 0x08d8, 0x610b48 }, + { 0x08dc, 0x610b50 }, + { 0x0900, 0x610a18 }, + { 0x0904, 0x610ab8 }, + { 0x0910, 0x610c70 }, + { 0x0914, 0x610c78 }, + {} + } +}; + +const struct nvkm_disp_chan_mthd +g84_disp_core_mthd = { + .name = "Core", + .addr = 0x000000, + .prev = 0x000004, + .data = { + { "Global", 1, &nv50_disp_core_mthd_base }, + { "DAC", 3, &g84_disp_core_mthd_dac }, + { "SOR", 2, &nv50_disp_core_mthd_sor }, + { "PIOR", 3, &nv50_disp_core_mthd_pior }, + { "HEAD", 2, &g84_disp_core_mthd_head }, + {} + } +}; + +int +g84_disp_core_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, + struct nvkm_disp *disp, struct nvkm_object **pobject) +{ + return nv50_disp_core_new_(&nv50_disp_core_func, &g84_disp_core_mthd, + disp, 0, oclass, argv, argc, pobject); +} + static const struct nvkm_disp_func g84_disp = { - .dtor = nv50_disp_dtor_, - .oneinit = nv50_disp_oneinit_, + .dtor = nv50_disp_dtor, + .oneinit = nv50_disp_oneinit, .init = nv50_disp_init, .fini = nv50_disp_fini, .intr = nv50_disp_intr, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/g94.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/g94.c index 33af38f3b5ff..6d5fd5c41704 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/g94.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/g94.c @@ -22,16 +22,331 @@ * Authors: Ben Skeggs */ #include "priv.h" +#include "chan.h" #include "head.h" #include "ior.h" -#include "channv50.h" + +#include <subdev/timer.h> #include <nvif/class.h> +void +g94_sor_dp_watermark(struct nvkm_ior *sor, int head, u8 watermark) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 loff = nv50_sor_link(sor); + + nvkm_mask(device, 0x61c128 + loff, 0x0000003f, watermark); +} + +void +g94_sor_dp_activesym(struct nvkm_ior *sor, int head, + u8 TU, u8 VTUa, u8 VTUf, u8 VTUi) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 loff = nv50_sor_link(sor); + + nvkm_mask(device, 0x61c10c + loff, 0x000001fc, TU << 2); + nvkm_mask(device, 0x61c128 + loff, 0x010f7f00, VTUa << 24 | VTUf << 16 | VTUi << 8); +} + +void +g94_sor_dp_audio_sym(struct nvkm_ior *sor, int head, u16 h, u32 v) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 soff = nv50_ior_base(sor); + + nvkm_mask(device, 0x61c1e8 + soff, 0x0000ffff, h); + nvkm_mask(device, 0x61c1ec + soff, 0x00ffffff, v); +} + +void +g94_sor_dp_drive(struct nvkm_ior *sor, int ln, int pc, int dc, int pe, int pu) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 loff = nv50_sor_link(sor); + const u32 shift = sor->func->dp.lanes[ln] * 8; + u32 data[3]; + + data[0] = nvkm_rd32(device, 0x61c118 + loff) & ~(0x000000ff << shift); + data[1] = nvkm_rd32(device, 0x61c120 + loff) & ~(0x000000ff << shift); + data[2] = nvkm_rd32(device, 0x61c130 + loff); + if ((data[2] & 0x0000ff00) < (pu << 8) || ln == 0) + data[2] = (data[2] & ~0x0000ff00) | (pu << 8); + + nvkm_wr32(device, 0x61c118 + loff, data[0] | (dc << shift)); + nvkm_wr32(device, 0x61c120 + loff, data[1] | (pe << shift)); + nvkm_wr32(device, 0x61c130 + loff, data[2]); +} + +void +g94_sor_dp_pattern(struct nvkm_ior *sor, int pattern) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 loff = nv50_sor_link(sor); + u32 data; + + switch (pattern) { + case 0: data = 0x00001000; break; + case 1: data = 0x01000000; break; + case 2: data = 0x02000000; break; + default: + WARN_ON(1); + return; + } + + nvkm_mask(device, 0x61c10c + loff, 0x0f001000, data); +} + +void +g94_sor_dp_power(struct nvkm_ior *sor, int nr) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 soff = nv50_ior_base(sor); + const u32 loff = nv50_sor_link(sor); + u32 mask = 0, i; + + for (i = 0; i < nr; i++) + mask |= 1 << sor->func->dp.lanes[i]; + + nvkm_mask(device, 0x61c130 + loff, 0x0000000f, mask); + nvkm_mask(device, 0x61c034 + soff, 0x80000000, 0x80000000); + nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x61c034 + soff) & 0x80000000)) + break; + ); +} + +int +g94_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; + + dpctrl |= ((1 << sor->dp.nr) - 1) << 16; + if (sor->dp.ef) + dpctrl |= 0x00004000; + if (sor->dp.bw > 0x06) + clksor |= 0x00040000; + + nvkm_mask(device, 0x614300 + soff, 0x000c0000, clksor); + nvkm_mask(device, 0x61c10c + loff, 0x001f4000, dpctrl); + return 0; +} + +static bool +g94_sor_war_needed(struct nvkm_ior *sor) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 soff = nv50_ior_base(sor); + + if (sor->asy.proto == TMDS) { + switch (nvkm_rd32(device, 0x614300 + soff) & 0x00030000) { + case 0x00000000: + case 0x00030000: + return true; + default: + break; + } + } + + return false; +} + +static void +g94_sor_war_update_sppll1(struct nvkm_disp *disp) +{ + struct nvkm_device *device = disp->engine.subdev.device; + struct nvkm_ior *ior; + bool used = false; + u32 clksor; + + list_for_each_entry(ior, &disp->iors, head) { + if (ior->type != SOR) + continue; + + clksor = nvkm_rd32(device, 0x614300 + nv50_ior_base(ior)); + switch (clksor & 0x03000000) { + case 0x02000000: + case 0x03000000: + used = true; + break; + default: + break; + } + } + + if (used) + return; + + nvkm_mask(device, 0x00e840, 0x80000000, 0x00000000); +} + +static void +g94_sor_war_3(struct nvkm_ior *sor) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 soff = nv50_ior_base(sor); + u32 sorpwr; + + if (!g94_sor_war_needed(sor)) + return; + + sorpwr = nvkm_rd32(device, 0x61c004 + soff); + if (sorpwr & 0x00000001) { + u32 seqctl = nvkm_rd32(device, 0x61c030 + soff); + u32 pd_pc = (seqctl & 0x00000f00) >> 8; + u32 pu_pc = seqctl & 0x0000000f; + + nvkm_wr32(device, 0x61c040 + soff + pd_pc * 4, 0x1f008000); + + nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x61c030 + soff) & 0x10000000)) + break; + ); + nvkm_mask(device, 0x61c004 + soff, 0x80000001, 0x80000000); + nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x61c030 + soff) & 0x10000000)) + break; + ); + + nvkm_wr32(device, 0x61c040 + soff + pd_pc * 4, 0x00002000); + nvkm_wr32(device, 0x61c040 + soff + pu_pc * 4, 0x1f000000); + } + + nvkm_mask(device, 0x61c10c + soff, 0x00000001, 0x00000000); + nvkm_mask(device, 0x614300 + soff, 0x03000000, 0x00000000); + + if (sorpwr & 0x00000001) + nvkm_mask(device, 0x61c004 + soff, 0x80000001, 0x80000001); + + g94_sor_war_update_sppll1(sor->disp); +} + +static void +g94_sor_war_2(struct nvkm_ior *sor) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 soff = nv50_ior_base(sor); + + if (!g94_sor_war_needed(sor)) + return; + + nvkm_mask(device, 0x00e840, 0x80000000, 0x80000000); + nvkm_mask(device, 0x614300 + soff, 0x03000000, 0x03000000); + nvkm_mask(device, 0x61c10c + soff, 0x00000001, 0x00000001); + + nvkm_mask(device, 0x61c00c + soff, 0x0f000000, 0x00000000); + nvkm_mask(device, 0x61c008 + soff, 0xff000000, 0x14000000); + nvkm_usec(device, 400, NVKM_DELAY); + nvkm_mask(device, 0x61c008 + soff, 0xff000000, 0x00000000); + nvkm_mask(device, 0x61c00c + soff, 0x0f000000, 0x01000000); + + if (nvkm_rd32(device, 0x61c004 + soff) & 0x00000001) { + u32 seqctl = nvkm_rd32(device, 0x61c030 + soff); + u32 pu_pc = seqctl & 0x0000000f; + nvkm_wr32(device, 0x61c040 + soff + pu_pc * 4, 0x1f008000); + } +} + +void +g94_sor_state(struct nvkm_ior *sor, struct nvkm_ior_state *state) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 coff = sor->id * 8 + (state == &sor->arm) * 4; + u32 ctrl = nvkm_rd32(device, 0x610794 + coff); + + state->proto_evo = (ctrl & 0x00000f00) >> 8; + switch (state->proto_evo) { + case 0: state->proto = LVDS; state->link = 1; break; + case 1: state->proto = TMDS; state->link = 1; break; + case 2: state->proto = TMDS; state->link = 2; break; + case 5: state->proto = TMDS; state->link = 3; break; + case 8: state->proto = DP; state->link = 1; break; + case 9: state->proto = DP; state->link = 2; break; + default: + state->proto = UNKNOWN; + break; + } + + state->head = ctrl & 0x00000003; + nv50_pior_depth(sor, state, ctrl); +} + +static const struct nvkm_ior_func +g94_sor = { + .state = g94_sor_state, + .power = nv50_sor_power, + .clock = nv50_sor_clock, + .war_2 = g94_sor_war_2, + .war_3 = g94_sor_war_3, + .dp = { + .lanes = { 2, 1, 0, 3}, + .links = g94_sor_dp_links, + .power = g94_sor_dp_power, + .pattern = g94_sor_dp_pattern, + .drive = g94_sor_dp_drive, + .audio_sym = g94_sor_dp_audio_sym, + .activesym = g94_sor_dp_activesym, + .watermark = g94_sor_dp_watermark, + }, +}; + +static int +g94_sor_new(struct nvkm_disp *disp, int id) +{ + return nvkm_ior_new_(&g94_sor, disp, SOR, id); +} + +int +g94_sor_cnt(struct nvkm_disp *disp, unsigned long *pmask) +{ + struct nvkm_device *device = disp->engine.subdev.device; + + *pmask = (nvkm_rd32(device, 0x610184) & 0x0f000000) >> 24; + return 4; +} + +static const struct nvkm_disp_mthd_list +g94_disp_core_mthd_sor = { + .mthd = 0x0040, + .addr = 0x000008, + .data = { + { 0x0600, 0x610794 }, + {} + } +}; + +const struct nvkm_disp_chan_mthd +g94_disp_core_mthd = { + .name = "Core", + .addr = 0x000000, + .prev = 0x000004, + .data = { + { "Global", 1, &nv50_disp_core_mthd_base }, + { "DAC", 3, &g84_disp_core_mthd_dac }, + { "SOR", 4, &g94_disp_core_mthd_sor }, + { "PIOR", 3, &nv50_disp_core_mthd_pior }, + { "HEAD", 2, &g84_disp_core_mthd_head }, + {} + } +}; + +int +g94_disp_core_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, + struct nvkm_disp *disp, struct nvkm_object **pobject) +{ + return nv50_disp_core_new_(&nv50_disp_core_func, &g94_disp_core_mthd, + disp, 0, oclass, argv, argc, pobject); +} + static const struct nvkm_disp_func g94_disp = { - .dtor = nv50_disp_dtor_, - .oneinit = nv50_disp_oneinit_, + .dtor = nv50_disp_dtor, + .oneinit = nv50_disp_oneinit, .init = nv50_disp_init, .fini = nv50_disp_fini, .intr = nv50_disp_intr, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ga102.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ga102.c index 600add5defbe..b3cfed2035d8 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ga102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ga102.c @@ -20,16 +20,140 @@ * OTHER DEALINGS IN THE SOFTWARE. */ #include "priv.h" +#include "chan.h" #include "head.h" #include "ior.h" -#include "channv50.h" + +#include <subdev/timer.h> #include <nvif/class.h> +static int +ga102_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; + + switch (sor->dp.bw) { + case 0x06: clksor |= 0x00000000; break; + case 0x0a: clksor |= 0x00040000; break; + case 0x14: clksor |= 0x00080000; break; + case 0x1e: clksor |= 0x000c0000; break; + case 0x08: clksor |= 0x00100000; break; + case 0x09: clksor |= 0x00140000; break; + case 0x0c: clksor |= 0x00180000; break; + case 0x10: clksor |= 0x001c0000; break; + default: + WARN_ON(1); + return -EINVAL; + } + + 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 void +ga102_sor_clock(struct nvkm_ior *sor) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + u32 div2 = 0; + + if (sor->asy.proto == TMDS) { + if (sor->tmds.high_speed) + div2 = 1; + } + + nvkm_wr32(device, 0x00ec08 + (sor->id * 0x10), 0x00000000); + nvkm_wr32(device, 0x00ec04 + (sor->id * 0x10), div2); +} + +static const struct nvkm_ior_func +ga102_sor_hda = { + .route = { + .get = gm200_sor_route_get, + .set = gm200_sor_route_set, + }, + .state = gv100_sor_state, + .power = nv50_sor_power, + .clock = ga102_sor_clock, + .hdmi = { + .ctrl = gv100_sor_hdmi_ctrl, + .scdc = gm200_sor_hdmi_scdc, + }, + .dp = { + .lanes = { 0, 1, 2, 3 }, + .links = ga102_sor_dp_links, + .power = g94_sor_dp_power, + .pattern = gm107_sor_dp_pattern, + .drive = gm200_sor_dp_drive, + .vcpi = tu102_sor_dp_vcpi, + .audio = gv100_sor_dp_audio, + .audio_sym = gv100_sor_dp_audio_sym, + .watermark = gv100_sor_dp_watermark, + }, + .hda = { + .hpd = gf119_sor_hda_hpd, + .eld = gf119_sor_hda_eld, + .device_entry = gv100_sor_hda_device_entry, + }, +}; + +static const struct nvkm_ior_func +ga102_sor = { + .route = { + .get = gm200_sor_route_get, + .set = gm200_sor_route_set, + }, + .state = gv100_sor_state, + .power = nv50_sor_power, + .clock = ga102_sor_clock, + .hdmi = { + .ctrl = gv100_sor_hdmi_ctrl, + .scdc = gm200_sor_hdmi_scdc, + }, + .dp = { + .lanes = { 0, 1, 2, 3 }, + .links = ga102_sor_dp_links, + .power = g94_sor_dp_power, + .pattern = gm107_sor_dp_pattern, + .drive = gm200_sor_dp_drive, + .vcpi = tu102_sor_dp_vcpi, + .audio = gv100_sor_dp_audio, + .audio_sym = gv100_sor_dp_audio_sym, + .watermark = gv100_sor_dp_watermark, + }, +}; + +static int +ga102_sor_new(struct nvkm_disp *disp, int id) +{ + struct nvkm_device *device = disp->engine.subdev.device; + u32 hda = nvkm_rd32(device, 0x08a15c); + if (hda & BIT(id)) + return nvkm_ior_new_(&ga102_sor_hda, disp, SOR, id); + return nvkm_ior_new_(&ga102_sor, disp, SOR, id); +} + static const struct nvkm_disp_func ga102_disp = { - .dtor = nv50_disp_dtor_, - .oneinit = nv50_disp_oneinit_, + .dtor = nv50_disp_dtor, + .oneinit = nv50_disp_oneinit, .init = tu102_disp_init, .fini = gv100_disp_fini, .intr = gv100_disp_intr, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c index 1d81816498f9..de9bc351169d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c @@ -22,10 +22,11 @@ * Authors: Ben Skeggs */ #include "priv.h" +#include "chan.h" +#include "hdmi.h" #include "head.h" #include "ior.h" #include "outp.h" -#include "channv50.h" #include <core/ramht.h> #include <subdev/timer.h> @@ -33,6 +34,953 @@ #include <nvif/class.h> void +gf119_sor_hda_device_entry(struct nvkm_ior *ior, int head) +{ + struct nvkm_device *device = ior->disp->engine.subdev.device; + const u32 hoff = 0x800 * head; + + nvkm_mask(device, 0x616548 + hoff, 0x00000070, head << 4); +} + +void +gf119_sor_hda_eld(struct nvkm_ior *ior, int head, u8 *data, u8 size) +{ + struct nvkm_device *device = ior->disp->engine.subdev.device; + const u32 soff = 0x030 * ior->id + (head * 0x04); + int i; + + for (i = 0; i < size; i++) + nvkm_wr32(device, 0x10ec00 + soff, (i << 8) | data[i]); + for (; i < 0x60; i++) + nvkm_wr32(device, 0x10ec00 + soff, (i << 8)); + nvkm_mask(device, 0x10ec10 + soff, 0x80000002, 0x80000002); +} + +void +gf119_sor_hda_hpd(struct nvkm_ior *ior, int head, bool present) +{ + struct nvkm_device *device = ior->disp->engine.subdev.device; + const u32 soff = 0x030 * ior->id + (head * 0x04); + u32 data = 0x80000000; + u32 mask = 0x80000001; + + if (present) { + ior->func->hda.device_entry(ior, head); + data |= 0x00000001; + } else { + mask |= 0x00000002; + } + + nvkm_mask(device, 0x10ec10 + soff, mask, data); +} + +void +gf119_sor_dp_watermark(struct nvkm_ior *sor, int head, u8 watermark) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 hoff = head * 0x800; + + nvkm_mask(device, 0x616610 + hoff, 0x0800003f, 0x08000000 | watermark); +} + +void +gf119_sor_dp_audio_sym(struct nvkm_ior *sor, int head, u16 h, u32 v) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 hoff = head * 0x800; + + nvkm_mask(device, 0x616620 + hoff, 0x0000ffff, h); + nvkm_mask(device, 0x616624 + hoff, 0x00ffffff, v); +} + +void +gf119_sor_dp_audio(struct nvkm_ior *sor, int head, bool enable) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 hoff = 0x800 * head; + const u32 data = 0x80000000 | (0x00000001 * enable); + const u32 mask = 0x8000000d; + + nvkm_mask(device, 0x616618 + hoff, mask, data); + nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x616618 + hoff) & 0x80000000)) + break; + ); +} + +void +gf119_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, 0x616588 + hoff, 0x00003f3f, (slot_nr << 8) | slot); + nvkm_mask(device, 0x61658c + hoff, 0xffffffff, (aligned << 16) | pbn); +} + +void +gf119_sor_dp_drive(struct nvkm_ior *sor, int ln, int pc, int dc, int pe, int pu) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 loff = nv50_sor_link(sor); + const u32 shift = sor->func->dp.lanes[ln] * 8; + u32 data[4]; + + data[0] = nvkm_rd32(device, 0x61c118 + loff) & ~(0x000000ff << shift); + data[1] = nvkm_rd32(device, 0x61c120 + loff) & ~(0x000000ff << shift); + data[2] = nvkm_rd32(device, 0x61c130 + loff); + if ((data[2] & 0x0000ff00) < (pu << 8) || ln == 0) + data[2] = (data[2] & ~0x0000ff00) | (pu << 8); + + nvkm_wr32(device, 0x61c118 + loff, data[0] | (dc << shift)); + nvkm_wr32(device, 0x61c120 + loff, data[1] | (pe << shift)); + nvkm_wr32(device, 0x61c130 + loff, data[2]); + + data[3] = nvkm_rd32(device, 0x61c13c + loff) & ~(0x000000ff << shift); + nvkm_wr32(device, 0x61c13c + loff, data[3] | (pc << shift)); +} + +void +gf119_sor_dp_pattern(struct nvkm_ior *sor, int pattern) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 soff = nv50_ior_base(sor); + u32 data; + + switch (pattern) { + case 0: data = 0x10101010; break; + case 1: data = 0x01010101; break; + case 2: data = 0x02020202; break; + case 3: data = 0x03030303; break; + default: + WARN_ON(1); + return; + } + + nvkm_mask(device, 0x61c110 + soff, 0x1f1f1f1f, data); +} + +int +gf119_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); + nvkm_mask(device, 0x61c10c + loff, 0x401f4000, dpctrl); + return 0; +} + +static void +gf119_sor_hdmi_ctrl(struct nvkm_ior *ior, int head, bool enable, u8 max_ac_packet, + u8 rekey, u8 *avi, u8 avi_size, u8 *vendor, u8 vendor_size) +{ + struct nvkm_device *device = ior->disp->engine.subdev.device; + const u32 ctrl = 0x40000000 * enable | + max_ac_packet << 16 | + rekey; + const u32 hoff = head * 0x800; + struct packed_hdmi_infoframe avi_infoframe; + struct packed_hdmi_infoframe vendor_infoframe; + + pack_hdmi_infoframe(&avi_infoframe, avi, avi_size); + pack_hdmi_infoframe(&vendor_infoframe, vendor, vendor_size); + + if (!(ctrl & 0x40000000)) { + nvkm_mask(device, 0x616798 + hoff, 0x40000000, 0x00000000); + nvkm_mask(device, 0x616730 + hoff, 0x00000001, 0x00000000); + nvkm_mask(device, 0x6167a4 + hoff, 0x00000001, 0x00000000); + nvkm_mask(device, 0x616714 + hoff, 0x00000001, 0x00000000); + return; + } + + /* AVI InfoFrame */ + nvkm_mask(device, 0x616714 + hoff, 0x00000001, 0x00000000); + if (avi_size) { + nvkm_wr32(device, 0x61671c + hoff, avi_infoframe.header); + nvkm_wr32(device, 0x616720 + hoff, avi_infoframe.subpack0_low); + nvkm_wr32(device, 0x616724 + hoff, avi_infoframe.subpack0_high); + nvkm_wr32(device, 0x616728 + hoff, avi_infoframe.subpack1_low); + nvkm_wr32(device, 0x61672c + hoff, avi_infoframe.subpack1_high); + nvkm_mask(device, 0x616714 + hoff, 0x00000001, 0x00000001); + } + + /* GENERIC(?) / Vendor InfoFrame? */ + nvkm_mask(device, 0x616730 + hoff, 0x00010001, 0x00010000); + if (vendor_size) { + /* + * These appear to be the audio infoframe registers, + * but no other set of infoframe registers has yet + * been found. + */ + nvkm_wr32(device, 0x616738 + hoff, vendor_infoframe.header); + nvkm_wr32(device, 0x61673c + hoff, vendor_infoframe.subpack0_low); + nvkm_wr32(device, 0x616740 + hoff, vendor_infoframe.subpack0_high); + /* Is there a second (or further?) set of subpack registers here? */ + nvkm_mask(device, 0x616730 + hoff, 0x00000001, 0x00000001); + } + + /* ??? InfoFrame? */ + nvkm_mask(device, 0x6167a4 + hoff, 0x00000001, 0x00000000); + nvkm_wr32(device, 0x6167ac + hoff, 0x00000010); + nvkm_mask(device, 0x6167a4 + hoff, 0x00000001, 0x00000001); + + /* HDMI_CTRL */ + nvkm_mask(device, 0x616798 + hoff, 0x401f007f, ctrl); +} + +void +gf119_sor_clock(struct nvkm_ior *sor) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 soff = nv50_ior_base(sor); + u32 div1 = sor->asy.link == 3; + u32 div2 = sor->asy.link == 3; + + if (sor->asy.proto == TMDS) { + const u32 speed = sor->tmds.high_speed ? 0x14 : 0x0a; + nvkm_mask(device, 0x612300 + soff, 0x007c0000, speed << 18); + if (sor->tmds.high_speed) + div2 = 1; + } + + nvkm_mask(device, 0x612300 + soff, 0x00000707, (div2 << 8) | div1); +} + +void +gf119_sor_state(struct nvkm_ior *sor, struct nvkm_ior_state *state) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 coff = (state == &sor->asy) * 0x20000 + sor->id * 0x20; + u32 ctrl = nvkm_rd32(device, 0x640200 + coff); + + state->proto_evo = (ctrl & 0x00000f00) >> 8; + switch (state->proto_evo) { + case 0: state->proto = LVDS; state->link = 1; break; + case 1: state->proto = TMDS; state->link = 1; break; + case 2: state->proto = TMDS; state->link = 2; break; + case 5: state->proto = TMDS; state->link = 3; break; + case 8: state->proto = DP; state->link = 1; break; + case 9: state->proto = DP; state->link = 2; break; + default: + state->proto = UNKNOWN; + break; + } + + state->head = ctrl & 0x0000000f; +} + +static const struct nvkm_ior_func +gf119_sor = { + .state = gf119_sor_state, + .power = nv50_sor_power, + .clock = gf119_sor_clock, + .hdmi = { + .ctrl = gf119_sor_hdmi_ctrl, + }, + .dp = { + .lanes = { 2, 1, 0, 3 }, + .links = gf119_sor_dp_links, + .power = g94_sor_dp_power, + .pattern = gf119_sor_dp_pattern, + .drive = gf119_sor_dp_drive, + .vcpi = gf119_sor_dp_vcpi, + .audio = gf119_sor_dp_audio, + .audio_sym = gf119_sor_dp_audio_sym, + .watermark = gf119_sor_dp_watermark, + }, + .hda = { + .hpd = gf119_sor_hda_hpd, + .eld = gf119_sor_hda_eld, + .device_entry = gf119_sor_hda_device_entry, + }, +}; + +static int +gf119_sor_new(struct nvkm_disp *disp, int id) +{ + return nvkm_ior_new_(&gf119_sor, disp, SOR, id); +} + +int +gf119_sor_cnt(struct nvkm_disp *disp, unsigned long *pmask) +{ + struct nvkm_device *device = disp->engine.subdev.device; + *pmask = (nvkm_rd32(device, 0x612004) & 0x0000ff00) >> 8; + return 8; +} + +static void +gf119_dac_clock(struct nvkm_ior *dac) +{ + struct nvkm_device *device = dac->disp->engine.subdev.device; + const u32 doff = nv50_ior_base(dac); + nvkm_mask(device, 0x612280 + doff, 0x07070707, 0x00000000); +} + +static void +gf119_dac_state(struct nvkm_ior *dac, struct nvkm_ior_state *state) +{ + struct nvkm_device *device = dac->disp->engine.subdev.device; + const u32 coff = (state == &dac->asy) * 0x20000 + dac->id * 0x20; + u32 ctrl = nvkm_rd32(device, 0x640180 + coff); + + state->proto_evo = (ctrl & 0x00000f00) >> 8; + switch (state->proto_evo) { + case 0: state->proto = CRT; break; + default: + state->proto = UNKNOWN; + break; + } + + state->head = ctrl & 0x0000000f; +} + +static const struct nvkm_ior_func +gf119_dac = { + .state = gf119_dac_state, + .power = nv50_dac_power, + .sense = nv50_dac_sense, + .clock = gf119_dac_clock, +}; + +int +gf119_dac_new(struct nvkm_disp *disp, int id) +{ + return nvkm_ior_new_(&gf119_dac, disp, DAC, id); +} + +int +gf119_dac_cnt(struct nvkm_disp *disp, unsigned long *pmask) +{ + struct nvkm_device *device = disp->engine.subdev.device; + *pmask = (nvkm_rd32(device, 0x612004) & 0x000000f0) >> 4; + return 4; +} + +static void +gf119_head_vblank_put(struct nvkm_head *head) +{ + struct nvkm_device *device = head->disp->engine.subdev.device; + const u32 hoff = head->id * 0x800; + nvkm_mask(device, 0x6100c0 + hoff, 0x00000001, 0x00000000); +} + +static void +gf119_head_vblank_get(struct nvkm_head *head) +{ + struct nvkm_device *device = head->disp->engine.subdev.device; + const u32 hoff = head->id * 0x800; + nvkm_mask(device, 0x6100c0 + hoff, 0x00000001, 0x00000001); +} + +void +gf119_head_rgclk(struct nvkm_head *head, int div) +{ + struct nvkm_device *device = head->disp->engine.subdev.device; + nvkm_mask(device, 0x612200 + (head->id * 0x800), 0x0000000f, div); +} + +static void +gf119_head_state(struct nvkm_head *head, struct nvkm_head_state *state) +{ + struct nvkm_device *device = head->disp->engine.subdev.device; + const u32 hoff = (state == &head->asy) * 0x20000 + head->id * 0x300; + u32 data; + + data = nvkm_rd32(device, 0x640414 + hoff); + state->vtotal = (data & 0xffff0000) >> 16; + state->htotal = (data & 0x0000ffff); + data = nvkm_rd32(device, 0x640418 + hoff); + state->vsynce = (data & 0xffff0000) >> 16; + state->hsynce = (data & 0x0000ffff); + data = nvkm_rd32(device, 0x64041c + hoff); + state->vblanke = (data & 0xffff0000) >> 16; + state->hblanke = (data & 0x0000ffff); + data = nvkm_rd32(device, 0x640420 + hoff); + state->vblanks = (data & 0xffff0000) >> 16; + state->hblanks = (data & 0x0000ffff); + state->hz = nvkm_rd32(device, 0x640450 + hoff); + + data = nvkm_rd32(device, 0x640404 + hoff); + switch ((data & 0x000003c0) >> 6) { + case 6: state->or.depth = 30; break; + case 5: state->or.depth = 24; break; + case 2: state->or.depth = 18; break; + case 0: state->or.depth = 18; break; /*XXX: "default" */ + default: + state->or.depth = 18; + WARN_ON(1); + break; + } +} + +static const struct nvkm_head_func +gf119_head = { + .state = gf119_head_state, + .rgpos = nv50_head_rgpos, + .rgclk = gf119_head_rgclk, + .vblank_get = gf119_head_vblank_get, + .vblank_put = gf119_head_vblank_put, +}; + +int +gf119_head_new(struct nvkm_disp *disp, int id) +{ + return nvkm_head_new_(&gf119_head, disp, id); +} + +int +gf119_head_cnt(struct nvkm_disp *disp, unsigned long *pmask) +{ + struct nvkm_device *device = disp->engine.subdev.device; + *pmask = nvkm_rd32(device, 0x612004) & 0x0000000f; + return nvkm_rd32(device, 0x022448); +} + +static void +gf119_disp_chan_uevent_fini(struct nvkm_event *event, int type, int index) +{ + struct nvkm_disp *disp = container_of(event, typeof(*disp), uevent); + struct nvkm_device *device = disp->engine.subdev.device; + nvkm_mask(device, 0x610090, 0x00000001 << index, 0x00000000 << index); + nvkm_wr32(device, 0x61008c, 0x00000001 << index); +} + +static void +gf119_disp_chan_uevent_init(struct nvkm_event *event, int types, int index) +{ + struct nvkm_disp *disp = container_of(event, typeof(*disp), uevent); + struct nvkm_device *device = disp->engine.subdev.device; + nvkm_wr32(device, 0x61008c, 0x00000001 << index); + nvkm_mask(device, 0x610090, 0x00000001 << index, 0x00000001 << index); +} + +const struct nvkm_event_func +gf119_disp_chan_uevent = { + .ctor = nv50_disp_chan_uevent_ctor, + .init = gf119_disp_chan_uevent_init, + .fini = gf119_disp_chan_uevent_fini, +}; + +void +gf119_disp_chan_intr(struct nvkm_disp_chan *chan, bool en) +{ + struct nvkm_device *device = chan->disp->engine.subdev.device; + const u32 mask = 0x00000001 << chan->chid.user; + if (!en) { + nvkm_mask(device, 0x610090, mask, 0x00000000); + nvkm_mask(device, 0x6100a0, mask, 0x00000000); + } else { + nvkm_mask(device, 0x6100a0, mask, mask); + } +} + +static void +gf119_disp_pioc_fini(struct nvkm_disp_chan *chan) +{ + struct nvkm_disp *disp = chan->disp; + struct nvkm_subdev *subdev = &disp->engine.subdev; + struct nvkm_device *device = subdev->device; + int ctrl = chan->chid.ctrl; + int user = chan->chid.user; + + nvkm_mask(device, 0x610490 + (ctrl * 0x10), 0x00000001, 0x00000000); + if (nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x610490 + (ctrl * 0x10)) & 0x00030000)) + break; + ) < 0) { + nvkm_error(subdev, "ch %d fini: %08x\n", user, + nvkm_rd32(device, 0x610490 + (ctrl * 0x10))); + } +} + +static int +gf119_disp_pioc_init(struct nvkm_disp_chan *chan) +{ + struct nvkm_disp *disp = chan->disp; + struct nvkm_subdev *subdev = &disp->engine.subdev; + struct nvkm_device *device = subdev->device; + int ctrl = chan->chid.ctrl; + int user = chan->chid.user; + + /* activate channel */ + nvkm_wr32(device, 0x610490 + (ctrl * 0x10), 0x00000001); + if (nvkm_msec(device, 2000, + u32 tmp = nvkm_rd32(device, 0x610490 + (ctrl * 0x10)); + if ((tmp & 0x00030000) == 0x00010000) + break; + ) < 0) { + nvkm_error(subdev, "ch %d init: %08x\n", user, + nvkm_rd32(device, 0x610490 + (ctrl * 0x10))); + return -EBUSY; + } + + return 0; +} + +const struct nvkm_disp_chan_func +gf119_disp_pioc_func = { + .init = gf119_disp_pioc_init, + .fini = gf119_disp_pioc_fini, + .intr = gf119_disp_chan_intr, + .user = nv50_disp_chan_user, +}; + +int +gf119_disp_dmac_bind(struct nvkm_disp_chan *chan, struct nvkm_object *object, u32 handle) +{ + return nvkm_ramht_insert(chan->disp->ramht, object, chan->chid.user, -9, handle, + chan->chid.user << 27 | 0x00000001); +} + +void +gf119_disp_dmac_fini(struct nvkm_disp_chan *chan) +{ + struct nvkm_subdev *subdev = &chan->disp->engine.subdev; + struct nvkm_device *device = subdev->device; + int ctrl = chan->chid.ctrl; + int user = chan->chid.user; + + /* deactivate channel */ + nvkm_mask(device, 0x610490 + (ctrl * 0x0010), 0x00001010, 0x00001000); + nvkm_mask(device, 0x610490 + (ctrl * 0x0010), 0x00000003, 0x00000000); + if (nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x610490 + (ctrl * 0x10)) & 0x001e0000)) + break; + ) < 0) { + nvkm_error(subdev, "ch %d fini: %08x\n", user, + nvkm_rd32(device, 0x610490 + (ctrl * 0x10))); + } + + chan->suspend_put = nvkm_rd32(device, 0x640000 + (ctrl * 0x1000)); +} + +static int +gf119_disp_dmac_init(struct nvkm_disp_chan *chan) +{ + struct nvkm_subdev *subdev = &chan->disp->engine.subdev; + struct nvkm_device *device = subdev->device; + int ctrl = chan->chid.ctrl; + int user = chan->chid.user; + + /* initialise channel for dma command submission */ + nvkm_wr32(device, 0x610494 + (ctrl * 0x0010), chan->push); + nvkm_wr32(device, 0x610498 + (ctrl * 0x0010), 0x00010000); + nvkm_wr32(device, 0x61049c + (ctrl * 0x0010), 0x00000001); + nvkm_mask(device, 0x610490 + (ctrl * 0x0010), 0x00000010, 0x00000010); + nvkm_wr32(device, 0x640000 + (ctrl * 0x1000), chan->suspend_put); + nvkm_wr32(device, 0x610490 + (ctrl * 0x0010), 0x00000013); + + /* wait for it to go inactive */ + if (nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x610490 + (ctrl * 0x10)) & 0x80000000)) + break; + ) < 0) { + nvkm_error(subdev, "ch %d init: %08x\n", user, + nvkm_rd32(device, 0x610490 + (ctrl * 0x10))); + return -EBUSY; + } + + return 0; +} + +const struct nvkm_disp_chan_func +gf119_disp_dmac_func = { + .init = gf119_disp_dmac_init, + .fini = gf119_disp_dmac_fini, + .intr = gf119_disp_chan_intr, + .user = nv50_disp_chan_user, + .bind = gf119_disp_dmac_bind, +}; + +int +gf119_disp_curs_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, + struct nvkm_disp *disp, struct nvkm_object **pobject) +{ + return nv50_disp_curs_new_(&gf119_disp_pioc_func, disp, 13, 13, + oclass, argv, argc, pobject); +} + +int +gf119_disp_oimm_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, + struct nvkm_disp *disp, struct nvkm_object **pobject) +{ + return nv50_disp_oimm_new_(&gf119_disp_pioc_func, disp, 9, 9, + oclass, argv, argc, pobject); +} + +static const struct nvkm_disp_mthd_list +gf119_disp_ovly_mthd_base = { + .mthd = 0x0000, + .data = { + { 0x0080, 0x665080 }, + { 0x0084, 0x665084 }, + { 0x0088, 0x665088 }, + { 0x008c, 0x66508c }, + { 0x0090, 0x665090 }, + { 0x0094, 0x665094 }, + { 0x00a0, 0x6650a0 }, + { 0x00a4, 0x6650a4 }, + { 0x00b0, 0x6650b0 }, + { 0x00b4, 0x6650b4 }, + { 0x00b8, 0x6650b8 }, + { 0x00c0, 0x6650c0 }, + { 0x00e0, 0x6650e0 }, + { 0x00e4, 0x6650e4 }, + { 0x00e8, 0x6650e8 }, + { 0x0100, 0x665100 }, + { 0x0104, 0x665104 }, + { 0x0108, 0x665108 }, + { 0x010c, 0x66510c }, + { 0x0110, 0x665110 }, + { 0x0118, 0x665118 }, + { 0x011c, 0x66511c }, + { 0x0120, 0x665120 }, + { 0x0124, 0x665124 }, + { 0x0130, 0x665130 }, + { 0x0134, 0x665134 }, + { 0x0138, 0x665138 }, + { 0x013c, 0x66513c }, + { 0x0140, 0x665140 }, + { 0x0144, 0x665144 }, + { 0x0148, 0x665148 }, + { 0x014c, 0x66514c }, + { 0x0150, 0x665150 }, + { 0x0154, 0x665154 }, + { 0x0158, 0x665158 }, + { 0x015c, 0x66515c }, + { 0x0160, 0x665160 }, + { 0x0164, 0x665164 }, + { 0x0168, 0x665168 }, + { 0x016c, 0x66516c }, + { 0x0400, 0x665400 }, + { 0x0408, 0x665408 }, + { 0x040c, 0x66540c }, + { 0x0410, 0x665410 }, + {} + } +}; + +static const struct nvkm_disp_chan_mthd +gf119_disp_ovly_mthd = { + .name = "Overlay", + .addr = 0x001000, + .prev = -0x020000, + .data = { + { "Global", 1, &gf119_disp_ovly_mthd_base }, + {} + } +}; + +int +gf119_disp_ovly_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, + struct nvkm_disp *disp, struct nvkm_object **pobject) +{ + return nv50_disp_ovly_new_(&gf119_disp_dmac_func, &gf119_disp_ovly_mthd, + disp, 5, oclass, argv, argc, pobject); +} + +static const struct nvkm_disp_mthd_list +gf119_disp_base_mthd_base = { + .mthd = 0x0000, + .addr = 0x000000, + .data = { + { 0x0080, 0x661080 }, + { 0x0084, 0x661084 }, + { 0x0088, 0x661088 }, + { 0x008c, 0x66108c }, + { 0x0090, 0x661090 }, + { 0x0094, 0x661094 }, + { 0x00a0, 0x6610a0 }, + { 0x00a4, 0x6610a4 }, + { 0x00c0, 0x6610c0 }, + { 0x00c4, 0x6610c4 }, + { 0x00c8, 0x6610c8 }, + { 0x00cc, 0x6610cc }, + { 0x00e0, 0x6610e0 }, + { 0x00e4, 0x6610e4 }, + { 0x00e8, 0x6610e8 }, + { 0x00ec, 0x6610ec }, + { 0x00fc, 0x6610fc }, + { 0x0100, 0x661100 }, + { 0x0104, 0x661104 }, + { 0x0108, 0x661108 }, + { 0x010c, 0x66110c }, + { 0x0110, 0x661110 }, + { 0x0114, 0x661114 }, + { 0x0118, 0x661118 }, + { 0x011c, 0x66111c }, + { 0x0130, 0x661130 }, + { 0x0134, 0x661134 }, + { 0x0138, 0x661138 }, + { 0x013c, 0x66113c }, + { 0x0140, 0x661140 }, + { 0x0144, 0x661144 }, + { 0x0148, 0x661148 }, + { 0x014c, 0x66114c }, + { 0x0150, 0x661150 }, + { 0x0154, 0x661154 }, + { 0x0158, 0x661158 }, + { 0x015c, 0x66115c }, + { 0x0160, 0x661160 }, + { 0x0164, 0x661164 }, + { 0x0168, 0x661168 }, + { 0x016c, 0x66116c }, + {} + } +}; + +static const struct nvkm_disp_mthd_list +gf119_disp_base_mthd_image = { + .mthd = 0x0020, + .addr = 0x000020, + .data = { + { 0x0400, 0x661400 }, + { 0x0404, 0x661404 }, + { 0x0408, 0x661408 }, + { 0x040c, 0x66140c }, + { 0x0410, 0x661410 }, + {} + } +}; + +const struct nvkm_disp_chan_mthd +gf119_disp_base_mthd = { + .name = "Base", + .addr = 0x001000, + .prev = -0x020000, + .data = { + { "Global", 1, &gf119_disp_base_mthd_base }, + { "Image", 2, &gf119_disp_base_mthd_image }, + {} + } +}; + +int +gf119_disp_base_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, + struct nvkm_disp *disp, struct nvkm_object **pobject) +{ + return nv50_disp_base_new_(&gf119_disp_dmac_func, &gf119_disp_base_mthd, + disp, 1, oclass, argv, argc, pobject); +} + +const struct nvkm_disp_mthd_list +gf119_disp_core_mthd_base = { + .mthd = 0x0000, + .addr = 0x000000, + .data = { + { 0x0080, 0x660080 }, + { 0x0084, 0x660084 }, + { 0x0088, 0x660088 }, + { 0x008c, 0x000000 }, + {} + } +}; + +const struct nvkm_disp_mthd_list +gf119_disp_core_mthd_dac = { + .mthd = 0x0020, + .addr = 0x000020, + .data = { + { 0x0180, 0x660180 }, + { 0x0184, 0x660184 }, + { 0x0188, 0x660188 }, + { 0x0190, 0x660190 }, + {} + } +}; + +const struct nvkm_disp_mthd_list +gf119_disp_core_mthd_sor = { + .mthd = 0x0020, + .addr = 0x000020, + .data = { + { 0x0200, 0x660200 }, + { 0x0204, 0x660204 }, + { 0x0208, 0x660208 }, + { 0x0210, 0x660210 }, + {} + } +}; + +const struct nvkm_disp_mthd_list +gf119_disp_core_mthd_pior = { + .mthd = 0x0020, + .addr = 0x000020, + .data = { + { 0x0300, 0x660300 }, + { 0x0304, 0x660304 }, + { 0x0308, 0x660308 }, + { 0x0310, 0x660310 }, + {} + } +}; + +static const struct nvkm_disp_mthd_list +gf119_disp_core_mthd_head = { + .mthd = 0x0300, + .addr = 0x000300, + .data = { + { 0x0400, 0x660400 }, + { 0x0404, 0x660404 }, + { 0x0408, 0x660408 }, + { 0x040c, 0x66040c }, + { 0x0410, 0x660410 }, + { 0x0414, 0x660414 }, + { 0x0418, 0x660418 }, + { 0x041c, 0x66041c }, + { 0x0420, 0x660420 }, + { 0x0424, 0x660424 }, + { 0x0428, 0x660428 }, + { 0x042c, 0x66042c }, + { 0x0430, 0x660430 }, + { 0x0434, 0x660434 }, + { 0x0438, 0x660438 }, + { 0x0440, 0x660440 }, + { 0x0444, 0x660444 }, + { 0x0448, 0x660448 }, + { 0x044c, 0x66044c }, + { 0x0450, 0x660450 }, + { 0x0454, 0x660454 }, + { 0x0458, 0x660458 }, + { 0x045c, 0x66045c }, + { 0x0460, 0x660460 }, + { 0x0468, 0x660468 }, + { 0x046c, 0x66046c }, + { 0x0470, 0x660470 }, + { 0x0474, 0x660474 }, + { 0x0480, 0x660480 }, + { 0x0484, 0x660484 }, + { 0x048c, 0x66048c }, + { 0x0490, 0x660490 }, + { 0x0494, 0x660494 }, + { 0x0498, 0x660498 }, + { 0x04b0, 0x6604b0 }, + { 0x04b8, 0x6604b8 }, + { 0x04bc, 0x6604bc }, + { 0x04c0, 0x6604c0 }, + { 0x04c4, 0x6604c4 }, + { 0x04c8, 0x6604c8 }, + { 0x04d0, 0x6604d0 }, + { 0x04d4, 0x6604d4 }, + { 0x04e0, 0x6604e0 }, + { 0x04e4, 0x6604e4 }, + { 0x04e8, 0x6604e8 }, + { 0x04ec, 0x6604ec }, + { 0x04f0, 0x6604f0 }, + { 0x04f4, 0x6604f4 }, + { 0x04f8, 0x6604f8 }, + { 0x04fc, 0x6604fc }, + { 0x0500, 0x660500 }, + { 0x0504, 0x660504 }, + { 0x0508, 0x660508 }, + { 0x050c, 0x66050c }, + { 0x0510, 0x660510 }, + { 0x0514, 0x660514 }, + { 0x0518, 0x660518 }, + { 0x051c, 0x66051c }, + { 0x052c, 0x66052c }, + { 0x0530, 0x660530 }, + { 0x054c, 0x66054c }, + { 0x0550, 0x660550 }, + { 0x0554, 0x660554 }, + { 0x0558, 0x660558 }, + { 0x055c, 0x66055c }, + {} + } +}; + +static const struct nvkm_disp_chan_mthd +gf119_disp_core_mthd = { + .name = "Core", + .addr = 0x000000, + .prev = -0x020000, + .data = { + { "Global", 1, &gf119_disp_core_mthd_base }, + { "DAC", 3, &gf119_disp_core_mthd_dac }, + { "SOR", 8, &gf119_disp_core_mthd_sor }, + { "PIOR", 4, &gf119_disp_core_mthd_pior }, + { "HEAD", 4, &gf119_disp_core_mthd_head }, + {} + } +}; + +void +gf119_disp_core_fini(struct nvkm_disp_chan *chan) +{ + struct nvkm_subdev *subdev = &chan->disp->engine.subdev; + struct nvkm_device *device = subdev->device; + + /* deactivate channel */ + nvkm_mask(device, 0x610490, 0x00000010, 0x00000000); + nvkm_mask(device, 0x610490, 0x00000003, 0x00000000); + if (nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x610490) & 0x001e0000)) + break; + ) < 0) { + nvkm_error(subdev, "core fini: %08x\n", + nvkm_rd32(device, 0x610490)); + } + + chan->suspend_put = nvkm_rd32(device, 0x640000); +} + +static int +gf119_disp_core_init(struct nvkm_disp_chan *chan) +{ + struct nvkm_subdev *subdev = &chan->disp->engine.subdev; + struct nvkm_device *device = subdev->device; + + /* initialise channel for dma command submission */ + nvkm_wr32(device, 0x610494, chan->push); + nvkm_wr32(device, 0x610498, 0x00010000); + nvkm_wr32(device, 0x61049c, 0x00000001); + nvkm_mask(device, 0x610490, 0x00000010, 0x00000010); + nvkm_wr32(device, 0x640000, chan->suspend_put); + nvkm_wr32(device, 0x610490, 0x01000013); + + /* wait for it to go inactive */ + if (nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x610490) & 0x80000000)) + break; + ) < 0) { + nvkm_error(subdev, "core init: %08x\n", + nvkm_rd32(device, 0x610490)); + return -EBUSY; + } + + return 0; +} + +const struct nvkm_disp_chan_func +gf119_disp_core_func = { + .init = gf119_disp_core_init, + .fini = gf119_disp_core_fini, + .intr = gf119_disp_chan_intr, + .user = nv50_disp_chan_user, + .bind = gf119_disp_dmac_bind, +}; + +int +gf119_disp_core_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, + struct nvkm_disp *disp, struct nvkm_object **pobject) +{ + return nv50_disp_core_new_(&gf119_disp_core_func, &gf119_disp_core_mthd, + disp, 0, oclass, argv, argc, pobject); +} + +void gf119_disp_super(struct work_struct *work) { struct nvkm_disp *disp = container_of(work, struct nvkm_disp, supervisor); @@ -254,8 +1202,8 @@ gf119_disp_init(struct nvkm_disp *disp) static const struct nvkm_disp_func gf119_disp = { - .dtor = nv50_disp_dtor_, - .oneinit = nv50_disp_oneinit_, + .dtor = nv50_disp_dtor, + .oneinit = nv50_disp_oneinit, .init = gf119_disp_init, .fini = gf119_disp_fini, .intr = gf119_disp_intr, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gk104.c index 1c1bc25e6340..b7b7a0c230e1 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gk104.c @@ -22,16 +22,282 @@ * Authors: Ben Skeggs */ #include "priv.h" +#include "chan.h" +#include "hdmi.h" #include "head.h" #include "ior.h" -#include "channv50.h" #include <nvif/class.h> +void +gk104_sor_hdmi_ctrl(struct nvkm_ior *ior, int head, bool enable, u8 max_ac_packet, + u8 rekey, u8 *avi, u8 avi_size, u8 *vendor, u8 vendor_size) +{ + struct nvkm_device *device = ior->disp->engine.subdev.device; + const u32 ctrl = 0x40000000 * enable | + max_ac_packet << 16 | + rekey; + const u32 hoff = head * 0x800; + const u32 hdmi = head * 0x400; + struct packed_hdmi_infoframe avi_infoframe; + struct packed_hdmi_infoframe vendor_infoframe; + + pack_hdmi_infoframe(&avi_infoframe, avi, avi_size); + pack_hdmi_infoframe(&vendor_infoframe, vendor, vendor_size); + + if (!(ctrl & 0x40000000)) { + nvkm_mask(device, 0x616798 + hoff, 0x40000000, 0x00000000); + nvkm_mask(device, 0x690100 + hdmi, 0x00000001, 0x00000000); + nvkm_mask(device, 0x6900c0 + hdmi, 0x00000001, 0x00000000); + nvkm_mask(device, 0x690000 + hdmi, 0x00000001, 0x00000000); + return; + } + + /* AVI InfoFrame */ + nvkm_mask(device, 0x690000 + hdmi, 0x00000001, 0x00000000); + if (avi_size) { + nvkm_wr32(device, 0x690008 + hdmi, avi_infoframe.header); + nvkm_wr32(device, 0x69000c + hdmi, avi_infoframe.subpack0_low); + nvkm_wr32(device, 0x690010 + hdmi, avi_infoframe.subpack0_high); + nvkm_wr32(device, 0x690014 + hdmi, avi_infoframe.subpack1_low); + nvkm_wr32(device, 0x690018 + hdmi, avi_infoframe.subpack1_high); + nvkm_mask(device, 0x690000 + hdmi, 0x00000001, 0x00000001); + } + + /* GENERIC(?) / Vendor InfoFrame? */ + nvkm_mask(device, 0x690100 + hdmi, 0x00010001, 0x00000000); + if (vendor_size) { + nvkm_wr32(device, 0x690108 + hdmi, vendor_infoframe.header); + nvkm_wr32(device, 0x69010c + hdmi, vendor_infoframe.subpack0_low); + nvkm_wr32(device, 0x690110 + hdmi, vendor_infoframe.subpack0_high); + /* Is there a second (or further?) set of subpack registers here? */ + nvkm_mask(device, 0x690100 + hdmi, 0x00000001, 0x00000001); + } + + + /* ??? InfoFrame? */ + nvkm_mask(device, 0x6900c0 + hdmi, 0x00000001, 0x00000000); + nvkm_wr32(device, 0x6900cc + hdmi, 0x00000010); + nvkm_mask(device, 0x6900c0 + hdmi, 0x00000001, 0x00000001); + + /* ??? */ + nvkm_wr32(device, 0x690080 + hdmi, 0x82000000); + + /* HDMI_CTRL */ + nvkm_mask(device, 0x616798 + hoff, 0x401f007f, ctrl); +} + +static const struct nvkm_ior_func +gk104_sor = { + .state = gf119_sor_state, + .power = nv50_sor_power, + .clock = gf119_sor_clock, + .hdmi = { + .ctrl = gk104_sor_hdmi_ctrl, + }, + .dp = { + .lanes = { 2, 1, 0, 3 }, + .links = gf119_sor_dp_links, + .power = g94_sor_dp_power, + .pattern = gf119_sor_dp_pattern, + .drive = gf119_sor_dp_drive, + .vcpi = gf119_sor_dp_vcpi, + .audio = gf119_sor_dp_audio, + .audio_sym = gf119_sor_dp_audio_sym, + .watermark = gf119_sor_dp_watermark, + }, + .hda = { + .hpd = gf119_sor_hda_hpd, + .eld = gf119_sor_hda_eld, + .device_entry = gf119_sor_hda_device_entry, + }, +}; + +int +gk104_sor_new(struct nvkm_disp *disp, int id) +{ + return nvkm_ior_new_(&gk104_sor, disp, SOR, id); +} + +static const struct nvkm_disp_mthd_list +gk104_disp_ovly_mthd_base = { + .mthd = 0x0000, + .data = { + { 0x0080, 0x665080 }, + { 0x0084, 0x665084 }, + { 0x0088, 0x665088 }, + { 0x008c, 0x66508c }, + { 0x0090, 0x665090 }, + { 0x0094, 0x665094 }, + { 0x00a0, 0x6650a0 }, + { 0x00a4, 0x6650a4 }, + { 0x00b0, 0x6650b0 }, + { 0x00b4, 0x6650b4 }, + { 0x00b8, 0x6650b8 }, + { 0x00c0, 0x6650c0 }, + { 0x00c4, 0x6650c4 }, + { 0x00e0, 0x6650e0 }, + { 0x00e4, 0x6650e4 }, + { 0x00e8, 0x6650e8 }, + { 0x0100, 0x665100 }, + { 0x0104, 0x665104 }, + { 0x0108, 0x665108 }, + { 0x010c, 0x66510c }, + { 0x0110, 0x665110 }, + { 0x0118, 0x665118 }, + { 0x011c, 0x66511c }, + { 0x0120, 0x665120 }, + { 0x0124, 0x665124 }, + { 0x0130, 0x665130 }, + { 0x0134, 0x665134 }, + { 0x0138, 0x665138 }, + { 0x013c, 0x66513c }, + { 0x0140, 0x665140 }, + { 0x0144, 0x665144 }, + { 0x0148, 0x665148 }, + { 0x014c, 0x66514c }, + { 0x0150, 0x665150 }, + { 0x0154, 0x665154 }, + { 0x0158, 0x665158 }, + { 0x015c, 0x66515c }, + { 0x0160, 0x665160 }, + { 0x0164, 0x665164 }, + { 0x0168, 0x665168 }, + { 0x016c, 0x66516c }, + { 0x0400, 0x665400 }, + { 0x0404, 0x665404 }, + { 0x0408, 0x665408 }, + { 0x040c, 0x66540c }, + { 0x0410, 0x665410 }, + {} + } +}; + +const struct nvkm_disp_chan_mthd +gk104_disp_ovly_mthd = { + .name = "Overlay", + .addr = 0x001000, + .prev = -0x020000, + .data = { + { "Global", 1, &gk104_disp_ovly_mthd_base }, + {} + } +}; + +int +gk104_disp_ovly_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, + struct nvkm_disp *disp, struct nvkm_object **pobject) +{ + return nv50_disp_ovly_new_(&gf119_disp_dmac_func, &gk104_disp_ovly_mthd, + disp, 5, oclass, argv, argc, pobject); +} + +static const struct nvkm_disp_mthd_list +gk104_disp_core_mthd_head = { + .mthd = 0x0300, + .addr = 0x000300, + .data = { + { 0x0400, 0x660400 }, + { 0x0404, 0x660404 }, + { 0x0408, 0x660408 }, + { 0x040c, 0x66040c }, + { 0x0410, 0x660410 }, + { 0x0414, 0x660414 }, + { 0x0418, 0x660418 }, + { 0x041c, 0x66041c }, + { 0x0420, 0x660420 }, + { 0x0424, 0x660424 }, + { 0x0428, 0x660428 }, + { 0x042c, 0x66042c }, + { 0x0430, 0x660430 }, + { 0x0434, 0x660434 }, + { 0x0438, 0x660438 }, + { 0x0440, 0x660440 }, + { 0x0444, 0x660444 }, + { 0x0448, 0x660448 }, + { 0x044c, 0x66044c }, + { 0x0450, 0x660450 }, + { 0x0454, 0x660454 }, + { 0x0458, 0x660458 }, + { 0x045c, 0x66045c }, + { 0x0460, 0x660460 }, + { 0x0468, 0x660468 }, + { 0x046c, 0x66046c }, + { 0x0470, 0x660470 }, + { 0x0474, 0x660474 }, + { 0x047c, 0x66047c }, + { 0x0480, 0x660480 }, + { 0x0484, 0x660484 }, + { 0x0488, 0x660488 }, + { 0x048c, 0x66048c }, + { 0x0490, 0x660490 }, + { 0x0494, 0x660494 }, + { 0x0498, 0x660498 }, + { 0x04a0, 0x6604a0 }, + { 0x04b0, 0x6604b0 }, + { 0x04b8, 0x6604b8 }, + { 0x04bc, 0x6604bc }, + { 0x04c0, 0x6604c0 }, + { 0x04c4, 0x6604c4 }, + { 0x04c8, 0x6604c8 }, + { 0x04d0, 0x6604d0 }, + { 0x04d4, 0x6604d4 }, + { 0x04e0, 0x6604e0 }, + { 0x04e4, 0x6604e4 }, + { 0x04e8, 0x6604e8 }, + { 0x04ec, 0x6604ec }, + { 0x04f0, 0x6604f0 }, + { 0x04f4, 0x6604f4 }, + { 0x04f8, 0x6604f8 }, + { 0x04fc, 0x6604fc }, + { 0x0500, 0x660500 }, + { 0x0504, 0x660504 }, + { 0x0508, 0x660508 }, + { 0x050c, 0x66050c }, + { 0x0510, 0x660510 }, + { 0x0514, 0x660514 }, + { 0x0518, 0x660518 }, + { 0x051c, 0x66051c }, + { 0x0520, 0x660520 }, + { 0x0524, 0x660524 }, + { 0x052c, 0x66052c }, + { 0x0530, 0x660530 }, + { 0x054c, 0x66054c }, + { 0x0550, 0x660550 }, + { 0x0554, 0x660554 }, + { 0x0558, 0x660558 }, + { 0x055c, 0x66055c }, + {} + } +}; + +const struct nvkm_disp_chan_mthd +gk104_disp_core_mthd = { + .name = "Core", + .addr = 0x000000, + .prev = -0x020000, + .data = { + { "Global", 1, &gf119_disp_core_mthd_base }, + { "DAC", 3, &gf119_disp_core_mthd_dac }, + { "SOR", 8, &gf119_disp_core_mthd_sor }, + { "PIOR", 4, &gf119_disp_core_mthd_pior }, + { "HEAD", 4, &gk104_disp_core_mthd_head }, + {} + } +}; + +int +gk104_disp_core_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, + struct nvkm_disp *disp, struct nvkm_object **pobject) +{ + return nv50_disp_core_new_(&gf119_disp_core_func, &gk104_disp_core_mthd, + disp, 0, oclass, argv, argc, pobject); +} + static const struct nvkm_disp_func gk104_disp = { - .dtor = nv50_disp_dtor_, - .oneinit = nv50_disp_oneinit_, + .dtor = nv50_disp_dtor, + .oneinit = nv50_disp_oneinit, .init = gf119_disp_init, .fini = gf119_disp_fini, .intr = gf119_disp_intr, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gk110.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gk110.c index 491d931cbd6e..d4097d3c0858 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gk110.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gk110.c @@ -22,16 +22,16 @@ * Authors: Ben Skeggs */ #include "priv.h" +#include "chan.h" #include "head.h" #include "ior.h" -#include "channv50.h" #include <nvif/class.h> static const struct nvkm_disp_func gk110_disp = { - .dtor = nv50_disp_dtor_, - .oneinit = nv50_disp_oneinit_, + .dtor = nv50_disp_dtor, + .oneinit = nv50_disp_oneinit, .init = gf119_disp_init, .fini = gf119_disp_fini, .intr = gf119_disp_intr, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm107.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm107.c index 613e1692b61f..9a0a519e280f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm107.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm107.c @@ -22,16 +22,72 @@ * Authors: Ben Skeggs */ #include "priv.h" +#include "chan.h" #include "head.h" #include "ior.h" -#include "channv50.h" #include <nvif/class.h> +void +gm107_sor_dp_pattern(struct nvkm_ior *sor, int pattern) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 soff = nv50_ior_base(sor); + u32 mask = 0x1f1f1f1f, data; + + switch (pattern) { + case 0: data = 0x10101010; break; + case 1: data = 0x01010101; break; + case 2: data = 0x02020202; break; + case 3: data = 0x03030303; break; + case 4: data = 0x1b1b1b1b; break; + default: + WARN_ON(1); + return; + } + + if (sor->asy.link & 1) + nvkm_mask(device, 0x61c110 + soff, mask, data); + else + nvkm_mask(device, 0x61c12c + soff, mask, data); +} + +static const struct nvkm_ior_func +gm107_sor = { + .state = gf119_sor_state, + .power = nv50_sor_power, + .clock = gf119_sor_clock, + .hdmi = { + .ctrl = gk104_sor_hdmi_ctrl, + }, + .dp = { + .lanes = { 0, 1, 2, 3 }, + .links = gf119_sor_dp_links, + .power = g94_sor_dp_power, + .pattern = gm107_sor_dp_pattern, + .drive = gf119_sor_dp_drive, + .vcpi = gf119_sor_dp_vcpi, + .audio = gf119_sor_dp_audio, + .audio_sym = gf119_sor_dp_audio_sym, + .watermark = gf119_sor_dp_watermark, + }, + .hda = { + .hpd = gf119_sor_hda_hpd, + .eld = gf119_sor_hda_eld, + .device_entry = gf119_sor_hda_device_entry, + }, +}; + +static int +gm107_sor_new(struct nvkm_disp *disp, int id) +{ + return nvkm_ior_new_(&gm107_sor, disp, SOR, id); +} + static const struct nvkm_disp_func gm107_disp = { - .dtor = nv50_disp_dtor_, - .oneinit = nv50_disp_oneinit_, + .dtor = nv50_disp_dtor, + .oneinit = nv50_disp_oneinit, .init = gf119_disp_init, .fini = gf119_disp_fini, .intr = gf119_disp_intr, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm200.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm200.c index a039195abae2..242c939e5715 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm200.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm200.c @@ -22,16 +22,169 @@ * Authors: Ben Skeggs */ #include "priv.h" +#include "chan.h" +#include "hdmi.h" #include "head.h" #include "ior.h" -#include "channv50.h" +#include "outp.h" #include <nvif/class.h> +void +gm200_sor_dp_drive(struct nvkm_ior *sor, int ln, int pc, int dc, int pe, int pu) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 loff = nv50_sor_link(sor); + const u32 shift = sor->func->dp.lanes[ln] * 8; + u32 data[4]; + + pu &= 0x0f; + + data[0] = nvkm_rd32(device, 0x61c118 + loff) & ~(0x000000ff << shift); + data[1] = nvkm_rd32(device, 0x61c120 + loff) & ~(0x000000ff << shift); + data[2] = nvkm_rd32(device, 0x61c130 + loff); + if ((data[2] & 0x00000f00) < (pu << 8) || ln == 0) + data[2] = (data[2] & ~0x00000f00) | (pu << 8); + + nvkm_wr32(device, 0x61c118 + loff, data[0] | (dc << shift)); + nvkm_wr32(device, 0x61c120 + loff, data[1] | (pe << shift)); + nvkm_wr32(device, 0x61c130 + loff, data[2]); + + data[3] = nvkm_rd32(device, 0x61c13c + loff) & ~(0x000000ff << shift); + nvkm_wr32(device, 0x61c13c + loff, data[3] | (pc << shift)); +} + +void +gm200_sor_hdmi_scdc(struct nvkm_ior *ior, u8 scdc) +{ + struct nvkm_device *device = ior->disp->engine.subdev.device; + const u32 soff = nv50_ior_base(ior); + const u32 ctrl = scdc & 0x3; + + nvkm_mask(device, 0x61c5bc + soff, 0x00000003, ctrl); + + ior->tmds.high_speed = !!(scdc & 0x2); +} + +void +gm200_sor_route_set(struct nvkm_outp *outp, struct nvkm_ior *ior) +{ + struct nvkm_device *device = outp->disp->engine.subdev.device; + const u32 moff = __ffs(outp->info.or) * 0x100; + const u32 sor = ior ? ior->id + 1 : 0; + u32 link = ior ? (ior->asy.link == 2) : 0; + + if (outp->info.sorconf.link & 1) { + nvkm_mask(device, 0x612308 + moff, 0x0000001f, link << 4 | sor); + link++; + } + + if (outp->info.sorconf.link & 2) + nvkm_mask(device, 0x612388 + moff, 0x0000001f, link << 4 | sor); +} + +int +gm200_sor_route_get(struct nvkm_outp *outp, int *link) +{ + struct nvkm_device *device = outp->disp->engine.subdev.device; + const int sublinks = outp->info.sorconf.link; + int lnk[2], sor[2], m, s; + + for (*link = 0, m = __ffs(outp->info.or) * 2, s = 0; s < 2; m++, s++) { + if (sublinks & BIT(s)) { + u32 data = nvkm_rd32(device, 0x612308 + (m * 0x80)); + lnk[s] = (data & 0x00000010) >> 4; + sor[s] = (data & 0x0000000f); + if (!sor[s]) + return -1; + *link |= lnk[s]; + } + } + + if (sublinks == 3) { + if (sor[0] != sor[1] || WARN_ON(lnk[0] || !lnk[1])) + return -1; + } + + return ((sublinks & 1) ? sor[0] : sor[1]) - 1; +} + +static const struct nvkm_ior_func +gm200_sor_hda = { + .route = { + .get = gm200_sor_route_get, + .set = gm200_sor_route_set, + }, + .state = gf119_sor_state, + .power = nv50_sor_power, + .clock = gf119_sor_clock, + .hdmi = { + .ctrl = gk104_sor_hdmi_ctrl, + .scdc = gm200_sor_hdmi_scdc, + }, + .dp = { + .lanes = { 0, 1, 2, 3 }, + .links = gf119_sor_dp_links, + .power = g94_sor_dp_power, + .pattern = gm107_sor_dp_pattern, + .drive = gm200_sor_dp_drive, + .vcpi = gf119_sor_dp_vcpi, + .audio = gf119_sor_dp_audio, + .audio_sym = gf119_sor_dp_audio_sym, + .watermark = gf119_sor_dp_watermark, + }, + .hda = { + .hpd = gf119_sor_hda_hpd, + .eld = gf119_sor_hda_eld, + .device_entry = gf119_sor_hda_device_entry, + }, +}; + +static const struct nvkm_ior_func +gm200_sor = { + .route = { + .get = gm200_sor_route_get, + .set = gm200_sor_route_set, + }, + .state = gf119_sor_state, + .power = nv50_sor_power, + .clock = gf119_sor_clock, + .hdmi = { + .ctrl = gk104_sor_hdmi_ctrl, + .scdc = gm200_sor_hdmi_scdc, + }, + .dp = { + .lanes = { 0, 1, 2, 3 }, + .links = gf119_sor_dp_links, + .power = g94_sor_dp_power, + .pattern = gm107_sor_dp_pattern, + .drive = gm200_sor_dp_drive, + .vcpi = gf119_sor_dp_vcpi, + .audio = gf119_sor_dp_audio, + .audio_sym = gf119_sor_dp_audio_sym, + .watermark = gf119_sor_dp_watermark, + }, +}; + +static int +gm200_sor_new(struct nvkm_disp *disp, int id) +{ + struct nvkm_device *device = disp->engine.subdev.device; + u32 hda; + + if (!((hda = nvkm_rd32(device, 0x08a15c)) & 0x40000000)) + hda = nvkm_rd32(device, 0x101034); + + if (hda & BIT(id)) + return nvkm_ior_new_(&gm200_sor_hda, disp, SOR, id); + + return nvkm_ior_new_(&gm200_sor, disp, SOR, id); +} + static const struct nvkm_disp_func gm200_disp = { - .dtor = nv50_disp_dtor_, - .oneinit = nv50_disp_oneinit_, + .dtor = nv50_disp_dtor, + .oneinit = nv50_disp_oneinit, .init = gf119_disp_init, .fini = gf119_disp_fini, .intr = gf119_disp_intr, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gp100.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gp100.c index 3da98e8f8427..8b9effddbabd 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gp100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gp100.c @@ -22,16 +22,87 @@ * Authors: Ben Skeggs <bskeggs@redhat.com> */ #include "priv.h" +#include "chan.h" #include "head.h" #include "ior.h" -#include "channv50.h" #include <nvif/class.h> +static const struct nvkm_ior_func +gp100_sor_hda = { + .route = { + .get = gm200_sor_route_get, + .set = gm200_sor_route_set, + }, + .state = gf119_sor_state, + .power = nv50_sor_power, + .clock = gf119_sor_clock, + .hdmi = { + .ctrl = gk104_sor_hdmi_ctrl, + .scdc = gm200_sor_hdmi_scdc, + }, + .dp = { + .lanes = { 0, 1, 2, 3 }, + .links = gf119_sor_dp_links, + .power = g94_sor_dp_power, + .pattern = gm107_sor_dp_pattern, + .drive = gm200_sor_dp_drive, + .vcpi = gf119_sor_dp_vcpi, + .audio = gf119_sor_dp_audio, + .audio_sym = gf119_sor_dp_audio_sym, + .watermark = gf119_sor_dp_watermark, + }, + .hda = { + .hpd = gf119_sor_hda_hpd, + .eld = gf119_sor_hda_eld, + .device_entry = gf119_sor_hda_device_entry, + }, +}; + +static const struct nvkm_ior_func +gp100_sor = { + .route = { + .get = gm200_sor_route_get, + .set = gm200_sor_route_set, + }, + .state = gf119_sor_state, + .power = nv50_sor_power, + .clock = gf119_sor_clock, + .hdmi = { + .ctrl = gk104_sor_hdmi_ctrl, + .scdc = gm200_sor_hdmi_scdc, + }, + .dp = { + .lanes = { 0, 1, 2, 3 }, + .links = gf119_sor_dp_links, + .power = g94_sor_dp_power, + .pattern = gm107_sor_dp_pattern, + .drive = gm200_sor_dp_drive, + .vcpi = gf119_sor_dp_vcpi, + .audio = gf119_sor_dp_audio, + .audio_sym = gf119_sor_dp_audio_sym, + .watermark = gf119_sor_dp_watermark, + }, +}; + +int +gp100_sor_new(struct nvkm_disp *disp, int id) +{ + struct nvkm_device *device = disp->engine.subdev.device; + u32 hda; + + if (!((hda = nvkm_rd32(device, 0x08a15c)) & 0x40000000)) + hda = nvkm_rd32(device, 0x10ebb0) >> 8; + + if (hda & BIT(id)) + return nvkm_ior_new_(&gp100_sor_hda, disp, SOR, id); + return nvkm_ior_new_(&gp100_sor, disp, SOR, id); +} + static const struct nvkm_disp_func gp100_disp = { - .dtor = nv50_disp_dtor_, - .oneinit = nv50_disp_oneinit_, + .dtor = nv50_disp_dtor, + .oneinit = nv50_disp_oneinit, .init = gf119_disp_init, .fini = gf119_disp_fini, .intr = gf119_disp_intr, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gp102.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gp102.c index 3e3acb8b7c43..5b8ca2d9eefa 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gp102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gp102.c @@ -22,12 +22,128 @@ * Authors: Ben Skeggs <bskeggs@redhat.com> */ #include "priv.h" +#include "chan.h" #include "head.h" #include "ior.h" -#include "channv50.h" + +#include <subdev/timer.h> #include <nvif/class.h> +static int +gp102_disp_dmac_init(struct nvkm_disp_chan *chan) +{ + struct nvkm_subdev *subdev = &chan->disp->engine.subdev; + struct nvkm_device *device = subdev->device; + int ctrl = chan->chid.ctrl; + int user = chan->chid.user; + + /* initialise channel for dma command submission */ + nvkm_wr32(device, 0x611494 + (ctrl * 0x0010), chan->push); + nvkm_wr32(device, 0x611498 + (ctrl * 0x0010), 0x00010000); + nvkm_wr32(device, 0x61149c + (ctrl * 0x0010), 0x00000001); + nvkm_mask(device, 0x610490 + (ctrl * 0x0010), 0x00000010, 0x00000010); + nvkm_wr32(device, 0x640000 + (ctrl * 0x1000), chan->suspend_put); + nvkm_wr32(device, 0x610490 + (ctrl * 0x0010), 0x00000013); + + /* wait for it to go inactive */ + if (nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x610490 + (ctrl * 0x10)) & 0x80000000)) + break; + ) < 0) { + nvkm_error(subdev, "ch %d init: %08x\n", user, + nvkm_rd32(device, 0x610490 + (ctrl * 0x10))); + return -EBUSY; + } + + return 0; +} + +const struct nvkm_disp_chan_func +gp102_disp_dmac_func = { + .init = gp102_disp_dmac_init, + .fini = gf119_disp_dmac_fini, + .intr = gf119_disp_chan_intr, + .user = nv50_disp_chan_user, + .bind = gf119_disp_dmac_bind, +}; + +int +gp102_disp_curs_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, + struct nvkm_disp *disp, struct nvkm_object **pobject) +{ + return nv50_disp_curs_new_(&gf119_disp_pioc_func, disp, 13, 17, + oclass, argv, argc, pobject); +} + +int +gp102_disp_oimm_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, + struct nvkm_disp *disp, struct nvkm_object **pobject) +{ + return nv50_disp_oimm_new_(&gf119_disp_pioc_func, disp, 9, 13, + oclass, argv, argc, pobject); +} + +int +gp102_disp_ovly_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, + struct nvkm_disp *disp, struct nvkm_object **pobject) +{ + return nv50_disp_ovly_new_(&gp102_disp_dmac_func, &gk104_disp_ovly_mthd, + disp, 5, oclass, argv, argc, pobject); +} + +int +gp102_disp_base_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, + struct nvkm_disp *disp, struct nvkm_object **pobject) +{ + return nv50_disp_base_new_(&gp102_disp_dmac_func, &gf119_disp_base_mthd, + disp, 1, oclass, argv, argc, pobject); +} + +static int +gp102_disp_core_init(struct nvkm_disp_chan *chan) +{ + struct nvkm_subdev *subdev = &chan->disp->engine.subdev; + struct nvkm_device *device = subdev->device; + + /* initialise channel for dma command submission */ + nvkm_wr32(device, 0x611494, chan->push); + nvkm_wr32(device, 0x611498, 0x00010000); + nvkm_wr32(device, 0x61149c, 0x00000001); + nvkm_mask(device, 0x610490, 0x00000010, 0x00000010); + nvkm_wr32(device, 0x640000, chan->suspend_put); + nvkm_wr32(device, 0x610490, 0x01000013); + + /* wait for it to go inactive */ + if (nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x610490) & 0x80000000)) + break; + ) < 0) { + nvkm_error(subdev, "core init: %08x\n", + nvkm_rd32(device, 0x610490)); + return -EBUSY; + } + + return 0; +} + +static const struct nvkm_disp_chan_func +gp102_disp_core_func = { + .init = gp102_disp_core_init, + .fini = gf119_disp_core_fini, + .intr = gf119_disp_chan_intr, + .user = nv50_disp_chan_user, + .bind = gf119_disp_dmac_bind, +}; + +int +gp102_disp_core_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, + struct nvkm_disp *disp, struct nvkm_object **pobject) +{ + return nv50_disp_core_new_(&gp102_disp_core_func, &gk104_disp_core_mthd, + disp, 0, oclass, argv, argc, pobject); +} + static void gp102_disp_intr_error(struct nvkm_disp *disp, int chid) { @@ -56,8 +172,8 @@ gp102_disp_intr_error(struct nvkm_disp *disp, int chid) static const struct nvkm_disp_func gp102_disp = { - .dtor = nv50_disp_dtor_, - .oneinit = nv50_disp_oneinit_, + .dtor = nv50_disp_dtor, + .oneinit = nv50_disp_oneinit, .init = gf119_disp_init, .fini = gf119_disp_fini, .intr = gf119_disp_intr, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gt200.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gt200.c index 3daad1154ca6..d7f9d141c091 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gt200.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gt200.c @@ -22,16 +22,66 @@ * Authors: Ben Skeggs */ #include "priv.h" +#include "chan.h" #include "head.h" #include "ior.h" -#include "channv50.h" #include <nvif/class.h> +static const struct nvkm_disp_mthd_list +gt200_disp_ovly_mthd_base = { + .mthd = 0x0000, + .addr = 0x000000, + .data = { + { 0x0080, 0x000000 }, + { 0x0084, 0x6109a0 }, + { 0x0088, 0x6109c0 }, + { 0x008c, 0x6109c8 }, + { 0x0090, 0x6109b4 }, + { 0x0094, 0x610970 }, + { 0x00a0, 0x610998 }, + { 0x00a4, 0x610964 }, + { 0x00b0, 0x610c98 }, + { 0x00b4, 0x610ca4 }, + { 0x00b8, 0x610cac }, + { 0x00c0, 0x610958 }, + { 0x00e0, 0x6109a8 }, + { 0x00e4, 0x6109d0 }, + { 0x00e8, 0x6109d8 }, + { 0x0100, 0x61094c }, + { 0x0104, 0x610984 }, + { 0x0108, 0x61098c }, + { 0x0800, 0x6109f8 }, + { 0x0808, 0x610a08 }, + { 0x080c, 0x610a10 }, + { 0x0810, 0x610a00 }, + {} + } +}; + +static const struct nvkm_disp_chan_mthd +gt200_disp_ovly_mthd = { + .name = "Overlay", + .addr = 0x000540, + .prev = 0x000004, + .data = { + { "Global", 1, >200_disp_ovly_mthd_base }, + {} + } +}; + +int +gt200_disp_ovly_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, + struct nvkm_disp *disp, struct nvkm_object **pobject) +{ + return nv50_disp_ovly_new_(&nv50_disp_dmac_func, >200_disp_ovly_mthd, + disp, 3, oclass, argv, argc, pobject); +} + static const struct nvkm_disp_func gt200_disp = { - .dtor = nv50_disp_dtor_, - .oneinit = nv50_disp_oneinit_, + .dtor = nv50_disp_dtor, + .oneinit = nv50_disp_oneinit, .init = nv50_disp_init, .fini = nv50_disp_fini, .intr = nv50_disp_intr, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gt215.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gt215.c index 885ad44fddb3..42cc17d7116a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gt215.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gt215.c @@ -22,16 +22,159 @@ * Authors: Ben Skeggs */ #include "priv.h" +#include "chan.h" +#include "hdmi.h" #include "head.h" #include "ior.h" -#include "channv50.h" + +#include <subdev/timer.h> #include <nvif/class.h> +void +gt215_sor_hda_eld(struct nvkm_ior *ior, int head, u8 *data, u8 size) +{ + struct nvkm_device *device = ior->disp->engine.subdev.device; + const u32 soff = ior->id * 0x800; + int i; + + for (i = 0; i < size; i++) + nvkm_wr32(device, 0x61c440 + soff, (i << 8) | data[i]); + for (; i < 0x60; i++) + nvkm_wr32(device, 0x61c440 + soff, (i << 8)); + nvkm_mask(device, 0x61c448 + soff, 0x80000002, 0x80000002); +} + +void +gt215_sor_hda_hpd(struct nvkm_ior *ior, int head, bool present) +{ + struct nvkm_device *device = ior->disp->engine.subdev.device; + u32 data = 0x80000000; + u32 mask = 0x80000001; + if (present) + data |= 0x00000001; + else + mask |= 0x00000002; + nvkm_mask(device, 0x61c448 + ior->id * 0x800, mask, data); +} + +void +gt215_sor_dp_audio(struct nvkm_ior *sor, int head, bool enable) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 soff = nv50_ior_base(sor); + const u32 data = 0x80000000 | (0x00000001 * enable); + const u32 mask = 0x8000000d; + + nvkm_mask(device, 0x61c1e0 + soff, mask, data); + nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x61c1e0 + soff) & 0x80000000)) + break; + ); +} + +void +gt215_sor_hdmi_ctrl(struct nvkm_ior *ior, int head, bool enable, u8 max_ac_packet, + u8 rekey, u8 *avi, u8 avi_size, u8 *vendor, u8 vendor_size) +{ + struct nvkm_device *device = ior->disp->engine.subdev.device; + const u32 ctrl = 0x40000000 * enable | + 0x1f000000 /* ??? */ | + max_ac_packet << 16 | + rekey; + const u32 soff = nv50_ior_base(ior); + struct packed_hdmi_infoframe avi_infoframe; + struct packed_hdmi_infoframe vendor_infoframe; + + pack_hdmi_infoframe(&avi_infoframe, avi, avi_size); + pack_hdmi_infoframe(&vendor_infoframe, vendor, vendor_size); + + if (!(ctrl & 0x40000000)) { + nvkm_mask(device, 0x61c5a4 + soff, 0x40000000, 0x00000000); + nvkm_mask(device, 0x61c53c + soff, 0x00000001, 0x00000000); + nvkm_mask(device, 0x61c520 + soff, 0x00000001, 0x00000000); + nvkm_mask(device, 0x61c500 + soff, 0x00000001, 0x00000000); + return; + } + + /* AVI InfoFrame */ + nvkm_mask(device, 0x61c520 + soff, 0x00000001, 0x00000000); + if (avi_size) { + nvkm_wr32(device, 0x61c528 + soff, avi_infoframe.header); + nvkm_wr32(device, 0x61c52c + soff, avi_infoframe.subpack0_low); + nvkm_wr32(device, 0x61c530 + soff, avi_infoframe.subpack0_high); + nvkm_wr32(device, 0x61c534 + soff, avi_infoframe.subpack1_low); + nvkm_wr32(device, 0x61c538 + soff, avi_infoframe.subpack1_high); + nvkm_mask(device, 0x61c520 + soff, 0x00000001, 0x00000001); + } + + /* Audio InfoFrame */ + nvkm_mask(device, 0x61c500 + soff, 0x00000001, 0x00000000); + nvkm_wr32(device, 0x61c508 + soff, 0x000a0184); + nvkm_wr32(device, 0x61c50c + soff, 0x00000071); + nvkm_wr32(device, 0x61c510 + soff, 0x00000000); + nvkm_mask(device, 0x61c500 + soff, 0x00000001, 0x00000001); + + /* Vendor InfoFrame */ + nvkm_mask(device, 0x61c53c + soff, 0x00010001, 0x00010000); + if (vendor_size) { + nvkm_wr32(device, 0x61c544 + soff, vendor_infoframe.header); + nvkm_wr32(device, 0x61c548 + soff, vendor_infoframe.subpack0_low); + nvkm_wr32(device, 0x61c54c + soff, vendor_infoframe.subpack0_high); + /* Is there a second (or up to fourth?) set of subpack registers here? */ + /* nvkm_wr32(device, 0x61c550 + soff, vendor_infoframe.subpack1_low); */ + /* nvkm_wr32(device, 0x61c554 + soff, vendor_infoframe.subpack1_high); */ + nvkm_mask(device, 0x61c53c + soff, 0x00010001, 0x00010001); + } + + nvkm_mask(device, 0x61c5d0 + soff, 0x00070001, 0x00010001); /* SPARE, HW_CTS */ + nvkm_mask(device, 0x61c568 + soff, 0x00010101, 0x00000000); /* ACR_CTRL, ?? */ + nvkm_mask(device, 0x61c578 + soff, 0x80000000, 0x80000000); /* ACR_0441_ENABLE */ + + /* ??? */ + nvkm_mask(device, 0x61733c, 0x00100000, 0x00100000); /* RESETF */ + nvkm_mask(device, 0x61733c, 0x10000000, 0x10000000); /* LOOKUP_EN */ + nvkm_mask(device, 0x61733c, 0x00100000, 0x00000000); /* !RESETF */ + + /* HDMI_CTRL */ + nvkm_mask(device, 0x61c5a4 + soff, 0x5f1f007f, ctrl); +} + +static const struct nvkm_ior_func +gt215_sor = { + .state = g94_sor_state, + .power = nv50_sor_power, + .clock = nv50_sor_clock, + .hdmi = { + .ctrl = gt215_sor_hdmi_ctrl, + }, + .dp = { + .lanes = { 2, 1, 0, 3 }, + .links = g94_sor_dp_links, + .power = g94_sor_dp_power, + .pattern = g94_sor_dp_pattern, + .drive = g94_sor_dp_drive, + .audio = gt215_sor_dp_audio, + .audio_sym = g94_sor_dp_audio_sym, + .activesym = g94_sor_dp_activesym, + .watermark = g94_sor_dp_watermark, + }, + .hda = { + .hpd = gt215_sor_hda_hpd, + .eld = gt215_sor_hda_eld, + }, +}; + +static int +gt215_sor_new(struct nvkm_disp *disp, int id) +{ + return nvkm_ior_new_(>215_sor, disp, SOR, id); +} + static const struct nvkm_disp_func gt215_disp = { - .dtor = nv50_disp_dtor_, - .oneinit = nv50_disp_oneinit_, + .dtor = nv50_disp_dtor, + .oneinit = nv50_disp_oneinit, .init = nv50_disp_init, .fini = nv50_disp_fini, .intr = nv50_disp_intr, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gv100.c index fcd4d81d2a90..953ebc6af03f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gv100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gv100.c @@ -20,24 +20,880 @@ * OTHER DEALINGS IN THE SOFTWARE. */ #include "priv.h" +#include "chan.h" +#include "hdmi.h" #include "head.h" #include "ior.h" #include "outp.h" -#include "channv50.h" +#include <core/client.h> #include <core/gpuobj.h> +#include <core/ramht.h> #include <subdev/timer.h> #include <nvif/class.h> +#include <nvif/clc37b.h> +#include <nvif/clc37e.h> +#include <nvif/unpack.h> + +void +gv100_sor_hda_device_entry(struct nvkm_ior *ior, int head) +{ + struct nvkm_device *device = ior->disp->engine.subdev.device; + const u32 hoff = 0x800 * head; + + nvkm_mask(device, 0x616528 + hoff, 0x00000070, head << 4); +} + +void +gv100_sor_dp_watermark(struct nvkm_ior *sor, int head, u8 watermark) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 hoff = head * 0x800; + + nvkm_mask(device, 0x616550 + hoff, 0x0c00003f, 0x08000000 | watermark); +} + +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; + const u32 hoff = head * 0x800; + + nvkm_mask(device, 0x616568 + hoff, 0x0000ffff, h); + nvkm_mask(device, 0x61656c + hoff, 0x00ffffff, v); +} + +void +gv100_sor_dp_audio(struct nvkm_ior *sor, int head, bool enable) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 hoff = 0x800 * head; + const u32 data = 0x80000000 | (0x00000001 * enable); + const u32 mask = 0x8000000d; + + nvkm_mask(device, 0x616560 + hoff, mask, data); + nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x616560 + hoff) & 0x80000000)) + break; + ); +} + +void +gv100_sor_hdmi_ctrl(struct nvkm_ior *ior, int head, bool enable, u8 max_ac_packet, + u8 rekey, u8 *avi, u8 avi_size, u8 *vendor, u8 vendor_size) +{ + struct nvkm_device *device = ior->disp->engine.subdev.device; + const u32 ctrl = 0x40000000 * enable | + max_ac_packet << 16 | + rekey; + const u32 hoff = head * 0x800; + const u32 hdmi = head * 0x400; + struct packed_hdmi_infoframe avi_infoframe; + struct packed_hdmi_infoframe vendor_infoframe; + + pack_hdmi_infoframe(&avi_infoframe, avi, avi_size); + pack_hdmi_infoframe(&vendor_infoframe, vendor, vendor_size); + + if (!(ctrl & 0x40000000)) { + nvkm_mask(device, 0x6165c0 + hoff, 0x40000000, 0x00000000); + nvkm_mask(device, 0x6f0100 + hdmi, 0x00000001, 0x00000000); + nvkm_mask(device, 0x6f00c0 + hdmi, 0x00000001, 0x00000000); + nvkm_mask(device, 0x6f0000 + hdmi, 0x00000001, 0x00000000); + return; + } + + /* AVI InfoFrame (AVI). */ + nvkm_mask(device, 0x6f0000 + hdmi, 0x00000001, 0x00000000); + if (avi_size) { + nvkm_wr32(device, 0x6f0008 + hdmi, avi_infoframe.header); + nvkm_wr32(device, 0x6f000c + hdmi, avi_infoframe.subpack0_low); + nvkm_wr32(device, 0x6f0010 + hdmi, avi_infoframe.subpack0_high); + nvkm_wr32(device, 0x6f0014 + hdmi, avi_infoframe.subpack1_low); + nvkm_wr32(device, 0x6f0018 + hdmi, avi_infoframe.subpack1_high); + nvkm_mask(device, 0x6f0000 + hdmi, 0x00000001, 0x00000001); + } + + /* Vendor-specific InfoFrame (VSI). */ + nvkm_mask(device, 0x6f0100 + hdmi, 0x00010001, 0x00000000); + if (vendor_size) { + nvkm_wr32(device, 0x6f0108 + hdmi, vendor_infoframe.header); + nvkm_wr32(device, 0x6f010c + hdmi, vendor_infoframe.subpack0_low); + nvkm_wr32(device, 0x6f0110 + hdmi, vendor_infoframe.subpack0_high); + nvkm_wr32(device, 0x6f0114 + hdmi, 0x00000000); + nvkm_wr32(device, 0x6f0118 + hdmi, 0x00000000); + nvkm_wr32(device, 0x6f011c + hdmi, 0x00000000); + nvkm_wr32(device, 0x6f0120 + hdmi, 0x00000000); + nvkm_wr32(device, 0x6f0124 + hdmi, 0x00000000); + nvkm_mask(device, 0x6f0100 + hdmi, 0x00000001, 0x00000001); + } + + + /* General Control (GCP). */ + nvkm_mask(device, 0x6f00c0 + hdmi, 0x00000001, 0x00000000); + nvkm_wr32(device, 0x6f00cc + hdmi, 0x00000010); + nvkm_mask(device, 0x6f00c0 + hdmi, 0x00000001, 0x00000001); + + /* Audio Clock Regeneration (ACR). */ + nvkm_wr32(device, 0x6f0080 + hdmi, 0x82000000); + + /* NV_PDISP_SF_HDMI_CTRL. */ + nvkm_mask(device, 0x6165c0 + hoff, 0x401f007f, ctrl); +} + +void +gv100_sor_state(struct nvkm_ior *sor, struct nvkm_ior_state *state) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 coff = (state == &sor->arm) * 0x8000 + sor->id * 0x20; + u32 ctrl = nvkm_rd32(device, 0x680300 + coff); + + state->proto_evo = (ctrl & 0x00000f00) >> 8; + switch (state->proto_evo) { + case 0: state->proto = LVDS; state->link = 1; break; + case 1: state->proto = TMDS; state->link = 1; break; + case 2: state->proto = TMDS; state->link = 2; break; + case 5: state->proto = TMDS; state->link = 3; break; + case 8: state->proto = DP; state->link = 1; break; + case 9: state->proto = DP; state->link = 2; break; + default: + state->proto = UNKNOWN; + break; + } + + state->head = ctrl & 0x000000ff; +} + +static const struct nvkm_ior_func +gv100_sor_hda = { + .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_sor_hdmi_ctrl, + .scdc = gm200_sor_hdmi_scdc, + }, + .dp = { + .lanes = { 0, 1, 2, 3 }, + .links = gf119_sor_dp_links, + .power = g94_sor_dp_power, + .pattern = gm107_sor_dp_pattern, + .drive = gm200_sor_dp_drive, + .audio = gv100_sor_dp_audio, + .audio_sym = gv100_sor_dp_audio_sym, + .watermark = gv100_sor_dp_watermark, + }, + .hda = { + .hpd = gf119_sor_hda_hpd, + .eld = gf119_sor_hda_eld, + .device_entry = gv100_sor_hda_device_entry, + }, +}; + +static const struct nvkm_ior_func +gv100_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_sor_hdmi_ctrl, + .scdc = gm200_sor_hdmi_scdc, + }, + .dp = { + .lanes = { 0, 1, 2, 3 }, + .links = gf119_sor_dp_links, + .power = g94_sor_dp_power, + .pattern = gm107_sor_dp_pattern, + .drive = gm200_sor_dp_drive, + .audio = gv100_sor_dp_audio, + .audio_sym = gv100_sor_dp_audio_sym, + .watermark = gv100_sor_dp_watermark, + }, +}; + +static int +gv100_sor_new(struct nvkm_disp *disp, int id) +{ + struct nvkm_device *device = disp->engine.subdev.device; + u32 hda; + + if (!((hda = nvkm_rd32(device, 0x08a15c)) & 0x40000000)) + hda = nvkm_rd32(device, 0x118fb0) >> 8; + + if (hda & BIT(id)) + return nvkm_ior_new_(&gv100_sor_hda, disp, SOR, id); + + return nvkm_ior_new_(&gv100_sor, disp, SOR, id); +} + +int +gv100_sor_cnt(struct nvkm_disp *disp, unsigned long *pmask) +{ + struct nvkm_device *device = disp->engine.subdev.device; + + *pmask = (nvkm_rd32(device, 0x610060) & 0x0000ff00) >> 8; + return (nvkm_rd32(device, 0x610074) & 0x00000f00) >> 8; +} + +static void +gv100_head_vblank_put(struct nvkm_head *head) +{ + struct nvkm_device *device = head->disp->engine.subdev.device; + nvkm_mask(device, 0x611d80 + (head->id * 4), 0x00000004, 0x00000000); +} + +static void +gv100_head_vblank_get(struct nvkm_head *head) +{ + struct nvkm_device *device = head->disp->engine.subdev.device; + nvkm_mask(device, 0x611d80 + (head->id * 4), 0x00000004, 0x00000004); +} + +static void +gv100_head_rgpos(struct nvkm_head *head, u16 *hline, u16 *vline) +{ + struct nvkm_device *device = head->disp->engine.subdev.device; + const u32 hoff = head->id * 0x800; + /* vline read locks hline. */ + *vline = nvkm_rd32(device, 0x616330 + hoff) & 0x0000ffff; + *hline = nvkm_rd32(device, 0x616334 + hoff) & 0x0000ffff; +} + +static void +gv100_head_state(struct nvkm_head *head, struct nvkm_head_state *state) +{ + struct nvkm_device *device = head->disp->engine.subdev.device; + const u32 hoff = (state == &head->arm) * 0x8000 + head->id * 0x400; + u32 data; + + data = nvkm_rd32(device, 0x682064 + hoff); + state->vtotal = (data & 0xffff0000) >> 16; + state->htotal = (data & 0x0000ffff); + data = nvkm_rd32(device, 0x682068 + hoff); + state->vsynce = (data & 0xffff0000) >> 16; + state->hsynce = (data & 0x0000ffff); + data = nvkm_rd32(device, 0x68206c + hoff); + state->vblanke = (data & 0xffff0000) >> 16; + state->hblanke = (data & 0x0000ffff); + data = nvkm_rd32(device, 0x682070 + hoff); + state->vblanks = (data & 0xffff0000) >> 16; + state->hblanks = (data & 0x0000ffff); + state->hz = nvkm_rd32(device, 0x68200c + hoff); + + data = nvkm_rd32(device, 0x682004 + hoff); + switch ((data & 0x000000f0) >> 4) { + case 5: state->or.depth = 30; break; + case 4: state->or.depth = 24; break; + case 1: state->or.depth = 18; break; + default: + state->or.depth = 18; + WARN_ON(1); + break; + } +} + +static const struct nvkm_head_func +gv100_head = { + .state = gv100_head_state, + .rgpos = gv100_head_rgpos, + .rgclk = gf119_head_rgclk, + .vblank_get = gv100_head_vblank_get, + .vblank_put = gv100_head_vblank_put, +}; + +int +gv100_head_new(struct nvkm_disp *disp, int id) +{ + struct nvkm_device *device = disp->engine.subdev.device; + + if (!(nvkm_rd32(device, 0x610060) & (0x00000001 << id))) + return 0; + + return nvkm_head_new_(&gv100_head, disp, id); +} + +int +gv100_head_cnt(struct nvkm_disp *disp, unsigned long *pmask) +{ + struct nvkm_device *device = disp->engine.subdev.device; + + *pmask = nvkm_rd32(device, 0x610060) & 0x000000ff; + return nvkm_rd32(device, 0x610074) & 0x0000000f; +} + +const struct nvkm_event_func +gv100_disp_chan_uevent = { + .ctor = nv50_disp_chan_uevent_ctor, +}; + +u64 +gv100_disp_chan_user(struct nvkm_disp_chan *chan, u64 *psize) +{ + *psize = 0x1000; + return 0x690000 + ((chan->chid.user - 1) * 0x1000); +} + +static int +gv100_disp_dmac_idle(struct nvkm_disp_chan *chan) +{ + struct nvkm_device *device = chan->disp->engine.subdev.device; + const u32 soff = (chan->chid.ctrl - 1) * 0x04; + nvkm_msec(device, 2000, + u32 stat = nvkm_rd32(device, 0x610664 + soff); + if ((stat & 0x000f0000) == 0x00040000) + return 0; + ); + return -EBUSY; +} + +int +gv100_disp_dmac_bind(struct nvkm_disp_chan *chan, + struct nvkm_object *object, u32 handle) +{ + return nvkm_ramht_insert(chan->disp->ramht, object, chan->chid.user, -9, handle, + chan->chid.user << 25 | 0x00000040); +} + +void +gv100_disp_dmac_fini(struct nvkm_disp_chan *chan) +{ + struct nvkm_device *device = chan->disp->engine.subdev.device; + const u32 uoff = (chan->chid.ctrl - 1) * 0x1000; + const u32 coff = chan->chid.ctrl * 0x04; + nvkm_mask(device, 0x6104e0 + coff, 0x00000010, 0x00000000); + gv100_disp_dmac_idle(chan); + nvkm_mask(device, 0x6104e0 + coff, 0x00000002, 0x00000000); + chan->suspend_put = nvkm_rd32(device, 0x690000 + uoff); +} + +int +gv100_disp_dmac_init(struct nvkm_disp_chan *chan) +{ + struct nvkm_subdev *subdev = &chan->disp->engine.subdev; + struct nvkm_device *device = subdev->device; + const u32 uoff = (chan->chid.ctrl - 1) * 0x1000; + const u32 poff = chan->chid.ctrl * 0x10; + const u32 coff = chan->chid.ctrl * 0x04; + + nvkm_wr32(device, 0x610b24 + poff, lower_32_bits(chan->push)); + nvkm_wr32(device, 0x610b20 + poff, upper_32_bits(chan->push)); + nvkm_wr32(device, 0x610b28 + poff, 0x00000001); + nvkm_wr32(device, 0x610b2c + poff, 0x00000040); + + nvkm_mask(device, 0x6104e0 + coff, 0x00000010, 0x00000010); + nvkm_wr32(device, 0x690000 + uoff, chan->suspend_put); + nvkm_wr32(device, 0x6104e0 + coff, 0x00000013); + return gv100_disp_dmac_idle(chan); +} + +static void +gv100_disp_wimm_intr(struct nvkm_disp_chan *chan, bool en) +{ + struct nvkm_device *device = chan->disp->engine.subdev.device; + const u32 mask = 0x00000001 << chan->head; + const u32 data = en ? mask : 0; + nvkm_mask(device, 0x611da8, mask, data); +} + +static const struct nvkm_disp_chan_func +gv100_disp_wimm = { + .init = gv100_disp_dmac_init, + .fini = gv100_disp_dmac_fini, + .intr = gv100_disp_wimm_intr, + .user = gv100_disp_chan_user, +}; + +static int +gv100_disp_wimm_new_(const struct nvkm_disp_chan_func *func, + const struct nvkm_disp_chan_mthd *mthd, + struct nvkm_disp *disp, int chid, + const struct nvkm_oclass *oclass, void *argv, u32 argc, + struct nvkm_object **pobject) +{ + union { + struct nvc37b_window_imm_channel_dma_v0 v0; + } *args = argv; + struct nvkm_object *parent = oclass->parent; + int wndw, ret = -ENOSYS; + u64 push; + + nvif_ioctl(parent, "create window imm channel dma size %d\n", argc); + if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, false))) { + nvif_ioctl(parent, "create window imm channel dma vers %d " + "pushbuf %016llx index %d\n", + args->v0.version, args->v0.pushbuf, args->v0.index); + if (!(disp->wndw.mask & BIT(args->v0.index))) + return -EINVAL; + push = args->v0.pushbuf; + wndw = args->v0.index; + } else + return ret; + + return nv50_disp_dmac_new_(func, mthd, disp, chid + wndw, + wndw, push, oclass, pobject); +} + +int +gv100_disp_wimm_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, + struct nvkm_disp *disp, struct nvkm_object **pobject) +{ + return gv100_disp_wimm_new_(&gv100_disp_wimm, NULL, disp, 33, + oclass, argv, argc, pobject); +} + +static const struct nvkm_disp_mthd_list +gv100_disp_wndw_mthd_base = { + .mthd = 0x0000, + .addr = 0x000000, + .data = { + { 0x0200, 0x690200 }, + { 0x020c, 0x69020c }, + { 0x0210, 0x690210 }, + { 0x0214, 0x690214 }, + { 0x0218, 0x690218 }, + { 0x021c, 0x69021c }, + { 0x0220, 0x690220 }, + { 0x0224, 0x690224 }, + { 0x0228, 0x690228 }, + { 0x022c, 0x69022c }, + { 0x0230, 0x690230 }, + { 0x0234, 0x690234 }, + { 0x0238, 0x690238 }, + { 0x0240, 0x690240 }, + { 0x0244, 0x690244 }, + { 0x0248, 0x690248 }, + { 0x024c, 0x69024c }, + { 0x0250, 0x690250 }, + { 0x0254, 0x690254 }, + { 0x0260, 0x690260 }, + { 0x0264, 0x690264 }, + { 0x0268, 0x690268 }, + { 0x026c, 0x69026c }, + { 0x0270, 0x690270 }, + { 0x0274, 0x690274 }, + { 0x0280, 0x690280 }, + { 0x0284, 0x690284 }, + { 0x0288, 0x690288 }, + { 0x028c, 0x69028c }, + { 0x0290, 0x690290 }, + { 0x0298, 0x690298 }, + { 0x029c, 0x69029c }, + { 0x02a0, 0x6902a0 }, + { 0x02a4, 0x6902a4 }, + { 0x02a8, 0x6902a8 }, + { 0x02ac, 0x6902ac }, + { 0x02b0, 0x6902b0 }, + { 0x02b4, 0x6902b4 }, + { 0x02b8, 0x6902b8 }, + { 0x02bc, 0x6902bc }, + { 0x02c0, 0x6902c0 }, + { 0x02c4, 0x6902c4 }, + { 0x02c8, 0x6902c8 }, + { 0x02cc, 0x6902cc }, + { 0x02d0, 0x6902d0 }, + { 0x02d4, 0x6902d4 }, + { 0x02d8, 0x6902d8 }, + { 0x02dc, 0x6902dc }, + { 0x02e0, 0x6902e0 }, + { 0x02e4, 0x6902e4 }, + { 0x02e8, 0x6902e8 }, + { 0x02ec, 0x6902ec }, + { 0x02f0, 0x6902f0 }, + { 0x02f4, 0x6902f4 }, + { 0x02f8, 0x6902f8 }, + { 0x02fc, 0x6902fc }, + { 0x0300, 0x690300 }, + { 0x0304, 0x690304 }, + { 0x0308, 0x690308 }, + { 0x0310, 0x690310 }, + { 0x0314, 0x690314 }, + { 0x0318, 0x690318 }, + { 0x031c, 0x69031c }, + { 0x0320, 0x690320 }, + { 0x0324, 0x690324 }, + { 0x0328, 0x690328 }, + { 0x032c, 0x69032c }, + { 0x033c, 0x69033c }, + { 0x0340, 0x690340 }, + { 0x0344, 0x690344 }, + { 0x0348, 0x690348 }, + { 0x034c, 0x69034c }, + { 0x0350, 0x690350 }, + { 0x0354, 0x690354 }, + { 0x0358, 0x690358 }, + { 0x0364, 0x690364 }, + { 0x0368, 0x690368 }, + { 0x036c, 0x69036c }, + { 0x0370, 0x690370 }, + { 0x0374, 0x690374 }, + { 0x0380, 0x690380 }, + {} + } +}; + +static const struct nvkm_disp_chan_mthd +gv100_disp_wndw_mthd = { + .name = "Window", + .addr = 0x001000, + .prev = 0x000800, + .data = { + { "Global", 1, &gv100_disp_wndw_mthd_base }, + {} + } +}; + +static void +gv100_disp_wndw_intr(struct nvkm_disp_chan *chan, bool en) +{ + struct nvkm_device *device = chan->disp->engine.subdev.device; + const u32 mask = 0x00000001 << chan->head; + const u32 data = en ? mask : 0; + nvkm_mask(device, 0x611da4, mask, data); +} + +static const struct nvkm_disp_chan_func +gv100_disp_wndw = { + .init = gv100_disp_dmac_init, + .fini = gv100_disp_dmac_fini, + .intr = gv100_disp_wndw_intr, + .user = gv100_disp_chan_user, + .bind = gv100_disp_dmac_bind, +}; + +static int +gv100_disp_wndw_new_(const struct nvkm_disp_chan_func *func, + const struct nvkm_disp_chan_mthd *mthd, + struct nvkm_disp *disp, int chid, + const struct nvkm_oclass *oclass, void *argv, u32 argc, + struct nvkm_object **pobject) +{ + union { + struct nvc37e_window_channel_dma_v0 v0; + } *args = argv; + struct nvkm_object *parent = oclass->parent; + int wndw, ret = -ENOSYS; + u64 push; + + nvif_ioctl(parent, "create window channel dma size %d\n", argc); + if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, false))) { + nvif_ioctl(parent, "create window channel dma vers %d " + "pushbuf %016llx index %d\n", + args->v0.version, args->v0.pushbuf, args->v0.index); + if (!(disp->wndw.mask & BIT(args->v0.index))) + return -EINVAL; + push = args->v0.pushbuf; + wndw = args->v0.index; + } else + return ret; + + return nv50_disp_dmac_new_(func, mthd, disp, chid + wndw, + wndw, push, oclass, pobject); +} + +int +gv100_disp_wndw_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, + struct nvkm_disp *disp, struct nvkm_object **pobject) +{ + return gv100_disp_wndw_new_(&gv100_disp_wndw, &gv100_disp_wndw_mthd, + disp, 1, oclass, argv, argc, pobject); +} int gv100_disp_wndw_cnt(struct nvkm_disp *disp, unsigned long *pmask) { struct nvkm_device *device = disp->engine.subdev.device; + *pmask = nvkm_rd32(device, 0x610064); return (nvkm_rd32(device, 0x610074) & 0x03f00000) >> 20; } +static int +gv100_disp_curs_idle(struct nvkm_disp_chan *chan) +{ + struct nvkm_device *device = chan->disp->engine.subdev.device; + const u32 soff = (chan->chid.ctrl - 1) * 0x04; + nvkm_msec(device, 2000, + u32 stat = nvkm_rd32(device, 0x610664 + soff); + if ((stat & 0x00070000) == 0x00040000) + return 0; + ); + return -EBUSY; +} + +static void +gv100_disp_curs_intr(struct nvkm_disp_chan *chan, bool en) +{ + struct nvkm_device *device = chan->disp->engine.subdev.device; + const u32 mask = 0x00010000 << chan->head; + const u32 data = en ? mask : 0; + nvkm_mask(device, 0x611dac, mask, data); +} + +static void +gv100_disp_curs_fini(struct nvkm_disp_chan *chan) +{ + struct nvkm_device *device = chan->disp->engine.subdev.device; + const u32 hoff = chan->chid.ctrl * 4; + nvkm_mask(device, 0x6104e0 + hoff, 0x00000010, 0x00000010); + gv100_disp_curs_idle(chan); + nvkm_mask(device, 0x6104e0 + hoff, 0x00000001, 0x00000000); +} + +static int +gv100_disp_curs_init(struct nvkm_disp_chan *chan) +{ + struct nvkm_subdev *subdev = &chan->disp->engine.subdev; + struct nvkm_device *device = subdev->device; + nvkm_wr32(device, 0x6104e0 + chan->chid.ctrl * 4, 0x00000001); + return gv100_disp_curs_idle(chan); +} + +static const struct nvkm_disp_chan_func +gv100_disp_curs = { + .init = gv100_disp_curs_init, + .fini = gv100_disp_curs_fini, + .intr = gv100_disp_curs_intr, + .user = gv100_disp_chan_user, +}; + +int +gv100_disp_curs_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, + struct nvkm_disp *disp, struct nvkm_object **pobject) +{ + return nv50_disp_curs_new_(&gv100_disp_curs, disp, 73, 73, + oclass, argv, argc, pobject); +} + +const struct nvkm_disp_mthd_list +gv100_disp_core_mthd_base = { + .mthd = 0x0000, + .addr = 0x000000, + .data = { + { 0x0200, 0x680200 }, + { 0x0208, 0x680208 }, + { 0x020c, 0x68020c }, + { 0x0210, 0x680210 }, + { 0x0214, 0x680214 }, + { 0x0218, 0x680218 }, + { 0x021c, 0x68021c }, + {} + } +}; + +static const struct nvkm_disp_mthd_list +gv100_disp_core_mthd_sor = { + .mthd = 0x0020, + .addr = 0x000020, + .data = { + { 0x0300, 0x680300 }, + { 0x0304, 0x680304 }, + { 0x0308, 0x680308 }, + { 0x030c, 0x68030c }, + {} + } +}; + +static const struct nvkm_disp_mthd_list +gv100_disp_core_mthd_wndw = { + .mthd = 0x0080, + .addr = 0x000080, + .data = { + { 0x1000, 0x681000 }, + { 0x1004, 0x681004 }, + { 0x1008, 0x681008 }, + { 0x100c, 0x68100c }, + { 0x1010, 0x681010 }, + {} + } +}; + +static const struct nvkm_disp_mthd_list +gv100_disp_core_mthd_head = { + .mthd = 0x0400, + .addr = 0x000400, + .data = { + { 0x2000, 0x682000 }, + { 0x2004, 0x682004 }, + { 0x2008, 0x682008 }, + { 0x200c, 0x68200c }, + { 0x2014, 0x682014 }, + { 0x2018, 0x682018 }, + { 0x201c, 0x68201c }, + { 0x2020, 0x682020 }, + { 0x2028, 0x682028 }, + { 0x202c, 0x68202c }, + { 0x2030, 0x682030 }, + { 0x2038, 0x682038 }, + { 0x203c, 0x68203c }, + { 0x2048, 0x682048 }, + { 0x204c, 0x68204c }, + { 0x2050, 0x682050 }, + { 0x2054, 0x682054 }, + { 0x2058, 0x682058 }, + { 0x205c, 0x68205c }, + { 0x2060, 0x682060 }, + { 0x2064, 0x682064 }, + { 0x2068, 0x682068 }, + { 0x206c, 0x68206c }, + { 0x2070, 0x682070 }, + { 0x2074, 0x682074 }, + { 0x2078, 0x682078 }, + { 0x207c, 0x68207c }, + { 0x2080, 0x682080 }, + { 0x2088, 0x682088 }, + { 0x2090, 0x682090 }, + { 0x209c, 0x68209c }, + { 0x20a0, 0x6820a0 }, + { 0x20a4, 0x6820a4 }, + { 0x20a8, 0x6820a8 }, + { 0x20ac, 0x6820ac }, + { 0x2180, 0x682180 }, + { 0x2184, 0x682184 }, + { 0x218c, 0x68218c }, + { 0x2194, 0x682194 }, + { 0x2198, 0x682198 }, + { 0x219c, 0x68219c }, + { 0x21a0, 0x6821a0 }, + { 0x21a4, 0x6821a4 }, + { 0x2214, 0x682214 }, + { 0x2218, 0x682218 }, + {} + } +}; + +static const struct nvkm_disp_chan_mthd +gv100_disp_core_mthd = { + .name = "Core", + .addr = 0x000000, + .prev = 0x008000, + .data = { + { "Global", 1, &gv100_disp_core_mthd_base }, + { "SOR", 4, &gv100_disp_core_mthd_sor }, + { "WINDOW", 8, &gv100_disp_core_mthd_wndw }, + { "HEAD", 4, &gv100_disp_core_mthd_head }, + {} + } +}; + +static int +gv100_disp_core_idle(struct nvkm_disp_chan *chan) +{ + struct nvkm_device *device = chan->disp->engine.subdev.device; + nvkm_msec(device, 2000, + u32 stat = nvkm_rd32(device, 0x610630); + if ((stat & 0x001f0000) == 0x000b0000) + return 0; + ); + return -EBUSY; +} + +static u64 +gv100_disp_core_user(struct nvkm_disp_chan *chan, u64 *psize) +{ + *psize = 0x10000; + return 0x680000; +} + +static void +gv100_disp_core_intr(struct nvkm_disp_chan *chan, bool en) +{ + struct nvkm_device *device = chan->disp->engine.subdev.device; + const u32 mask = 0x00000001; + const u32 data = en ? mask : 0; + nvkm_mask(device, 0x611dac, mask, data); +} + +static void +gv100_disp_core_fini(struct nvkm_disp_chan *chan) +{ + struct nvkm_device *device = chan->disp->engine.subdev.device; + nvkm_mask(device, 0x6104e0, 0x00000010, 0x00000000); + gv100_disp_core_idle(chan); + nvkm_mask(device, 0x6104e0, 0x00000002, 0x00000000); + chan->suspend_put = nvkm_rd32(device, 0x680000); +} + +static int +gv100_disp_core_init(struct nvkm_disp_chan *chan) +{ + struct nvkm_subdev *subdev = &chan->disp->engine.subdev; + struct nvkm_device *device = subdev->device; + + nvkm_wr32(device, 0x610b24, lower_32_bits(chan->push)); + nvkm_wr32(device, 0x610b20, upper_32_bits(chan->push)); + nvkm_wr32(device, 0x610b28, 0x00000001); + nvkm_wr32(device, 0x610b2c, 0x00000040); + + nvkm_mask(device, 0x6104e0, 0x00000010, 0x00000010); + nvkm_wr32(device, 0x680000, chan->suspend_put); + nvkm_wr32(device, 0x6104e0, 0x00000013); + return gv100_disp_core_idle(chan); +} + +static const struct nvkm_disp_chan_func +gv100_disp_core = { + .init = gv100_disp_core_init, + .fini = gv100_disp_core_fini, + .intr = gv100_disp_core_intr, + .user = gv100_disp_core_user, + .bind = gv100_disp_dmac_bind, +}; + +int +gv100_disp_core_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, + struct nvkm_disp *disp, struct nvkm_object **pobject) +{ + return nv50_disp_core_new_(&gv100_disp_core, &gv100_disp_core_mthd, + disp, 0, oclass, argv, argc, pobject); +} + +#define gv100_disp_caps(p) container_of((p), struct gv100_disp_caps, object) + +struct gv100_disp_caps { + struct nvkm_object object; + struct nvkm_disp *disp; +}; + +static int +gv100_disp_caps_map(struct nvkm_object *object, void *argv, u32 argc, + enum nvkm_object_map *type, u64 *addr, u64 *size) +{ + struct gv100_disp_caps *caps = gv100_disp_caps(object); + struct nvkm_device *device = caps->disp->engine.subdev.device; + *type = NVKM_OBJECT_MAP_IO; + *addr = 0x640000 + device->func->resource_addr(device, 0); + *size = 0x1000; + return 0; +} + +static const struct nvkm_object_func +gv100_disp_caps = { + .map = gv100_disp_caps_map, +}; + +int +gv100_disp_caps_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, + struct nvkm_disp *disp, struct nvkm_object **pobject) +{ + struct gv100_disp_caps *caps; + + if (!(caps = kzalloc(sizeof(*caps), GFP_KERNEL))) + return -ENOMEM; + *pobject = &caps->object; + + nvkm_object_ctor(&gv100_disp_caps, oclass, &caps->object); + caps->disp = disp; + return 0; +} + void gv100_disp_super(struct work_struct *work) { @@ -429,8 +1285,8 @@ gv100_disp_init(struct nvkm_disp *disp) static const struct nvkm_disp_func gv100_disp = { - .dtor = nv50_disp_dtor_, - .oneinit = nv50_disp_oneinit_, + .dtor = nv50_disp_dtor, + .oneinit = nv50_disp_oneinit, .init = gv100_disp_init, .fini = gv100_disp_fini, .intr = gv100_disp_intr, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdagf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdagf119.c deleted file mode 100644 index 19d2d58344e4..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdagf119.c +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2012 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. - * - * Authors: Ben Skeggs - */ -#include "ior.h" - -void -gf119_hda_device_entry(struct nvkm_ior *ior, int head) -{ - struct nvkm_device *device = ior->disp->engine.subdev.device; - const u32 hoff = 0x800 * head; - nvkm_mask(device, 0x616548 + hoff, 0x00000070, head << 4); -} - -void -gf119_hda_eld(struct nvkm_ior *ior, int head, u8 *data, u8 size) -{ - struct nvkm_device *device = ior->disp->engine.subdev.device; - const u32 soff = 0x030 * ior->id + (head * 0x04); - int i; - - for (i = 0; i < size; i++) - nvkm_wr32(device, 0x10ec00 + soff, (i << 8) | data[i]); - for (; i < 0x60; i++) - nvkm_wr32(device, 0x10ec00 + soff, (i << 8)); - nvkm_mask(device, 0x10ec10 + soff, 0x80000002, 0x80000002); -} - -void -gf119_hda_hpd(struct nvkm_ior *ior, int head, bool present) -{ - struct nvkm_device *device = ior->disp->engine.subdev.device; - const u32 soff = 0x030 * ior->id + (head * 0x04); - u32 data = 0x80000000; - u32 mask = 0x80000001; - if (present) { - ior->func->hda.device_entry(ior, head); - data |= 0x00000001; - } else { - mask |= 0x00000002; - } - nvkm_mask(device, 0x10ec10 + soff, mask, data); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdagt215.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdagt215.c deleted file mode 100644 index 0d1b81fe1093..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdagt215.c +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2012 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. - * - * Authors: Ben Skeggs - */ -#include "ior.h" - -void -gt215_hda_eld(struct nvkm_ior *ior, int head, u8 *data, u8 size) -{ - struct nvkm_device *device = ior->disp->engine.subdev.device; - const u32 soff = ior->id * 0x800; - int i; - - for (i = 0; i < size; i++) - nvkm_wr32(device, 0x61c440 + soff, (i << 8) | data[i]); - for (; i < 0x60; i++) - nvkm_wr32(device, 0x61c440 + soff, (i << 8)); - nvkm_mask(device, 0x61c448 + soff, 0x80000002, 0x80000002); -} - -void -gt215_hda_hpd(struct nvkm_ior *ior, int head, bool present) -{ - struct nvkm_device *device = ior->disp->engine.subdev.device; - u32 data = 0x80000000; - u32 mask = 0x80000001; - if (present) - data |= 0x00000001; - else - mask |= 0x00000002; - nvkm_mask(device, 0x61c448 + ior->id * 0x800, mask, data); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdagv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdagv100.c deleted file mode 100644 index 57d374ecfeef..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdagv100.c +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2020 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" - -void -gv100_hda_device_entry(struct nvkm_ior *ior, int head) -{ - struct nvkm_device *device = ior->disp->engine.subdev.device; - const u32 hoff = 0x800 * head; - nvkm_mask(device, 0x616528 + hoff, 0x00000070, head << 4); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmig84.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmig84.c deleted file mode 100644 index 661410f9b457..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmig84.c +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright 2012 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. - * - * Authors: Ben Skeggs - */ -#include "hdmi.h" - -void -g84_hdmi_ctrl(struct nvkm_ior *ior, int head, bool enable, u8 max_ac_packet, - u8 rekey, u8 *avi, u8 avi_size, u8 *vendor, u8 vendor_size) -{ - struct nvkm_device *device = ior->disp->engine.subdev.device; - const u32 ctrl = 0x40000000 * enable | - 0x1f000000 /* ??? */ | - max_ac_packet << 16 | - rekey; - const u32 hoff = head * 0x800; - struct packed_hdmi_infoframe avi_infoframe; - struct packed_hdmi_infoframe vendor_infoframe; - - pack_hdmi_infoframe(&avi_infoframe, avi, avi_size); - pack_hdmi_infoframe(&vendor_infoframe, vendor, vendor_size); - - if (!(ctrl & 0x40000000)) { - nvkm_mask(device, 0x6165a4 + hoff, 0x40000000, 0x00000000); - nvkm_mask(device, 0x61653c + hoff, 0x00000001, 0x00000000); - nvkm_mask(device, 0x616520 + hoff, 0x00000001, 0x00000000); - nvkm_mask(device, 0x616500 + hoff, 0x00000001, 0x00000000); - return; - } - - /* AVI InfoFrame */ - nvkm_mask(device, 0x616520 + hoff, 0x00000001, 0x00000000); - if (avi_size) { - nvkm_wr32(device, 0x616528 + hoff, avi_infoframe.header); - nvkm_wr32(device, 0x61652c + hoff, avi_infoframe.subpack0_low); - nvkm_wr32(device, 0x616530 + hoff, avi_infoframe.subpack0_high); - nvkm_wr32(device, 0x616534 + hoff, avi_infoframe.subpack1_low); - nvkm_wr32(device, 0x616538 + hoff, avi_infoframe.subpack1_high); - nvkm_mask(device, 0x616520 + hoff, 0x00000001, 0x00000001); - } - - /* Audio InfoFrame */ - nvkm_mask(device, 0x616500 + hoff, 0x00000001, 0x00000000); - nvkm_wr32(device, 0x616508 + hoff, 0x000a0184); - nvkm_wr32(device, 0x61650c + hoff, 0x00000071); - nvkm_wr32(device, 0x616510 + hoff, 0x00000000); - nvkm_mask(device, 0x616500 + hoff, 0x00000001, 0x00000001); - - /* Vendor InfoFrame */ - nvkm_mask(device, 0x61653c + hoff, 0x00010001, 0x00010000); - if (vendor_size) { - nvkm_wr32(device, 0x616544 + hoff, vendor_infoframe.header); - nvkm_wr32(device, 0x616548 + hoff, vendor_infoframe.subpack0_low); - nvkm_wr32(device, 0x61654c + hoff, vendor_infoframe.subpack0_high); - /* Is there a second (or up to fourth?) set of subpack registers here? */ - /* nvkm_wr32(device, 0x616550 + hoff, vendor_infoframe->subpack1_low); */ - /* nvkm_wr32(device, 0x616554 + hoff, vendor_infoframe->subpack1_high); */ - nvkm_mask(device, 0x61653c + hoff, 0x00010001, 0x00010001); - } - - nvkm_mask(device, 0x6165d0 + hoff, 0x00070001, 0x00010001); /* SPARE, HW_CTS */ - nvkm_mask(device, 0x616568 + hoff, 0x00010101, 0x00000000); /* ACR_CTRL, ?? */ - nvkm_mask(device, 0x616578 + hoff, 0x80000000, 0x80000000); /* ACR_0441_ENABLE */ - - /* ??? */ - nvkm_mask(device, 0x61733c, 0x00100000, 0x00100000); /* RESETF */ - nvkm_mask(device, 0x61733c, 0x10000000, 0x10000000); /* LOOKUP_EN */ - nvkm_mask(device, 0x61733c, 0x00100000, 0x00000000); /* !RESETF */ - - /* HDMI_CTRL */ - nvkm_mask(device, 0x6165a4 + hoff, 0x5f1f007f, ctrl); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigf119.c deleted file mode 100644 index 6cac0e72b4cc..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigf119.c +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright 2012 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. - * - * Authors: Ben Skeggs - */ -#include "hdmi.h" - -void -gf119_hdmi_ctrl(struct nvkm_ior *ior, int head, bool enable, u8 max_ac_packet, - u8 rekey, u8 *avi, u8 avi_size, u8 *vendor, u8 vendor_size) -{ - struct nvkm_device *device = ior->disp->engine.subdev.device; - const u32 ctrl = 0x40000000 * enable | - max_ac_packet << 16 | - rekey; - const u32 hoff = head * 0x800; - struct packed_hdmi_infoframe avi_infoframe; - struct packed_hdmi_infoframe vendor_infoframe; - - pack_hdmi_infoframe(&avi_infoframe, avi, avi_size); - pack_hdmi_infoframe(&vendor_infoframe, vendor, vendor_size); - - if (!(ctrl & 0x40000000)) { - nvkm_mask(device, 0x616798 + hoff, 0x40000000, 0x00000000); - nvkm_mask(device, 0x616730 + hoff, 0x00000001, 0x00000000); - nvkm_mask(device, 0x6167a4 + hoff, 0x00000001, 0x00000000); - nvkm_mask(device, 0x616714 + hoff, 0x00000001, 0x00000000); - return; - } - - /* AVI InfoFrame */ - nvkm_mask(device, 0x616714 + hoff, 0x00000001, 0x00000000); - if (avi_size) { - nvkm_wr32(device, 0x61671c + hoff, avi_infoframe.header); - nvkm_wr32(device, 0x616720 + hoff, avi_infoframe.subpack0_low); - nvkm_wr32(device, 0x616724 + hoff, avi_infoframe.subpack0_high); - nvkm_wr32(device, 0x616728 + hoff, avi_infoframe.subpack1_low); - nvkm_wr32(device, 0x61672c + hoff, avi_infoframe.subpack1_high); - nvkm_mask(device, 0x616714 + hoff, 0x00000001, 0x00000001); - } - - /* GENERIC(?) / Vendor InfoFrame? */ - nvkm_mask(device, 0x616730 + hoff, 0x00010001, 0x00010000); - if (vendor_size) { - /* - * These appear to be the audio infoframe registers, - * but no other set of infoframe registers has yet - * been found. - */ - nvkm_wr32(device, 0x616738 + hoff, vendor_infoframe.header); - nvkm_wr32(device, 0x61673c + hoff, vendor_infoframe.subpack0_low); - nvkm_wr32(device, 0x616740 + hoff, vendor_infoframe.subpack0_high); - /* Is there a second (or further?) set of subpack registers here? */ - nvkm_mask(device, 0x616730 + hoff, 0x00000001, 0x00000001); - } - - /* ??? InfoFrame? */ - nvkm_mask(device, 0x6167a4 + hoff, 0x00000001, 0x00000000); - nvkm_wr32(device, 0x6167ac + hoff, 0x00000010); - nvkm_mask(device, 0x6167a4 + hoff, 0x00000001, 0x00000001); - - /* HDMI_CTRL */ - nvkm_mask(device, 0x616798 + hoff, 0x401f007f, ctrl); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigk104.c deleted file mode 100644 index ed0a6100d76b..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigk104.c +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright 2014 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. - * - * Authors: Ben Skeggs - */ -#include "hdmi.h" - -void -gk104_hdmi_ctrl(struct nvkm_ior *ior, int head, bool enable, u8 max_ac_packet, - u8 rekey, u8 *avi, u8 avi_size, u8 *vendor, u8 vendor_size) -{ - struct nvkm_device *device = ior->disp->engine.subdev.device; - const u32 ctrl = 0x40000000 * enable | - max_ac_packet << 16 | - rekey; - const u32 hoff = head * 0x800; - const u32 hdmi = head * 0x400; - struct packed_hdmi_infoframe avi_infoframe; - struct packed_hdmi_infoframe vendor_infoframe; - - pack_hdmi_infoframe(&avi_infoframe, avi, avi_size); - pack_hdmi_infoframe(&vendor_infoframe, vendor, vendor_size); - - if (!(ctrl & 0x40000000)) { - nvkm_mask(device, 0x616798 + hoff, 0x40000000, 0x00000000); - nvkm_mask(device, 0x690100 + hdmi, 0x00000001, 0x00000000); - nvkm_mask(device, 0x6900c0 + hdmi, 0x00000001, 0x00000000); - nvkm_mask(device, 0x690000 + hdmi, 0x00000001, 0x00000000); - return; - } - - /* AVI InfoFrame */ - nvkm_mask(device, 0x690000 + hdmi, 0x00000001, 0x00000000); - if (avi_size) { - nvkm_wr32(device, 0x690008 + hdmi, avi_infoframe.header); - nvkm_wr32(device, 0x69000c + hdmi, avi_infoframe.subpack0_low); - nvkm_wr32(device, 0x690010 + hdmi, avi_infoframe.subpack0_high); - nvkm_wr32(device, 0x690014 + hdmi, avi_infoframe.subpack1_low); - nvkm_wr32(device, 0x690018 + hdmi, avi_infoframe.subpack1_high); - nvkm_mask(device, 0x690000 + hdmi, 0x00000001, 0x00000001); - } - - /* GENERIC(?) / Vendor InfoFrame? */ - nvkm_mask(device, 0x690100 + hdmi, 0x00010001, 0x00000000); - if (vendor_size) { - nvkm_wr32(device, 0x690108 + hdmi, vendor_infoframe.header); - nvkm_wr32(device, 0x69010c + hdmi, vendor_infoframe.subpack0_low); - nvkm_wr32(device, 0x690110 + hdmi, vendor_infoframe.subpack0_high); - /* Is there a second (or further?) set of subpack registers here? */ - nvkm_mask(device, 0x690100 + hdmi, 0x00000001, 0x00000001); - } - - - /* ??? InfoFrame? */ - nvkm_mask(device, 0x6900c0 + hdmi, 0x00000001, 0x00000000); - nvkm_wr32(device, 0x6900cc + hdmi, 0x00000010); - nvkm_mask(device, 0x6900c0 + hdmi, 0x00000001, 0x00000001); - - /* ??? */ - nvkm_wr32(device, 0x690080 + hdmi, 0x82000000); - - /* HDMI_CTRL */ - nvkm_mask(device, 0x616798 + hoff, 0x401f007f, ctrl); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigm200.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigm200.c deleted file mode 100644 index bb32befa6ad4..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigm200.c +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2018 Ilia Mirkin - * - * 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. - * - * Authors: Ilia Mirkin - */ -#include "hdmi.h" - -void -gm200_hdmi_scdc(struct nvkm_ior *ior, u8 scdc) -{ - struct nvkm_device *device = ior->disp->engine.subdev.device; - const u32 soff = nv50_ior_base(ior); - const u32 ctrl = scdc & 0x3; - - nvkm_mask(device, 0x61c5bc + soff, 0x00000003, ctrl); - - ior->tmds.high_speed = !!(scdc & 0x2); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigt215.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigt215.c deleted file mode 100644 index 0993d223bb9c..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigt215.c +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright 2012 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. - * - * Authors: Ben Skeggs - */ -#include "hdmi.h" - -void -gt215_hdmi_ctrl(struct nvkm_ior *ior, int head, bool enable, u8 max_ac_packet, - u8 rekey, u8 *avi, u8 avi_size, u8 *vendor, u8 vendor_size) -{ - struct nvkm_device *device = ior->disp->engine.subdev.device; - const u32 ctrl = 0x40000000 * enable | - 0x1f000000 /* ??? */ | - max_ac_packet << 16 | - rekey; - const u32 soff = nv50_ior_base(ior); - struct packed_hdmi_infoframe avi_infoframe; - struct packed_hdmi_infoframe vendor_infoframe; - - pack_hdmi_infoframe(&avi_infoframe, avi, avi_size); - pack_hdmi_infoframe(&vendor_infoframe, vendor, vendor_size); - - if (!(ctrl & 0x40000000)) { - nvkm_mask(device, 0x61c5a4 + soff, 0x40000000, 0x00000000); - nvkm_mask(device, 0x61c53c + soff, 0x00000001, 0x00000000); - nvkm_mask(device, 0x61c520 + soff, 0x00000001, 0x00000000); - nvkm_mask(device, 0x61c500 + soff, 0x00000001, 0x00000000); - return; - } - - /* AVI InfoFrame */ - nvkm_mask(device, 0x61c520 + soff, 0x00000001, 0x00000000); - if (avi_size) { - nvkm_wr32(device, 0x61c528 + soff, avi_infoframe.header); - nvkm_wr32(device, 0x61c52c + soff, avi_infoframe.subpack0_low); - nvkm_wr32(device, 0x61c530 + soff, avi_infoframe.subpack0_high); - nvkm_wr32(device, 0x61c534 + soff, avi_infoframe.subpack1_low); - nvkm_wr32(device, 0x61c538 + soff, avi_infoframe.subpack1_high); - nvkm_mask(device, 0x61c520 + soff, 0x00000001, 0x00000001); - } - - /* Audio InfoFrame */ - nvkm_mask(device, 0x61c500 + soff, 0x00000001, 0x00000000); - nvkm_wr32(device, 0x61c508 + soff, 0x000a0184); - nvkm_wr32(device, 0x61c50c + soff, 0x00000071); - nvkm_wr32(device, 0x61c510 + soff, 0x00000000); - nvkm_mask(device, 0x61c500 + soff, 0x00000001, 0x00000001); - - /* Vendor InfoFrame */ - nvkm_mask(device, 0x61c53c + soff, 0x00010001, 0x00010000); - if (vendor_size) { - nvkm_wr32(device, 0x61c544 + soff, vendor_infoframe.header); - nvkm_wr32(device, 0x61c548 + soff, vendor_infoframe.subpack0_low); - nvkm_wr32(device, 0x61c54c + soff, vendor_infoframe.subpack0_high); - /* Is there a second (or up to fourth?) set of subpack registers here? */ - /* nvkm_wr32(device, 0x61c550 + soff, vendor_infoframe.subpack1_low); */ - /* nvkm_wr32(device, 0x61c554 + soff, vendor_infoframe.subpack1_high); */ - nvkm_mask(device, 0x61c53c + soff, 0x00010001, 0x00010001); - } - - nvkm_mask(device, 0x61c5d0 + soff, 0x00070001, 0x00010001); /* SPARE, HW_CTS */ - nvkm_mask(device, 0x61c568 + soff, 0x00010101, 0x00000000); /* ACR_CTRL, ?? */ - nvkm_mask(device, 0x61c578 + soff, 0x80000000, 0x80000000); /* ACR_0441_ENABLE */ - - /* ??? */ - nvkm_mask(device, 0x61733c, 0x00100000, 0x00100000); /* RESETF */ - nvkm_mask(device, 0x61733c, 0x10000000, 0x10000000); /* LOOKUP_EN */ - nvkm_mask(device, 0x61733c, 0x00100000, 0x00000000); /* !RESETF */ - - /* HDMI_CTRL */ - nvkm_mask(device, 0x61c5a4 + soff, 0x5f1f007f, ctrl); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigv100.c deleted file mode 100644 index 3ff49344abc7..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigv100.c +++ /dev/null @@ -1,84 +0,0 @@ -/* - * 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 "hdmi.h" - -void -gv100_hdmi_ctrl(struct nvkm_ior *ior, int head, bool enable, u8 max_ac_packet, - u8 rekey, u8 *avi, u8 avi_size, u8 *vendor, u8 vendor_size) -{ - struct nvkm_device *device = ior->disp->engine.subdev.device; - const u32 ctrl = 0x40000000 * enable | - max_ac_packet << 16 | - rekey; - const u32 hoff = head * 0x800; - const u32 hdmi = head * 0x400; - struct packed_hdmi_infoframe avi_infoframe; - struct packed_hdmi_infoframe vendor_infoframe; - - pack_hdmi_infoframe(&avi_infoframe, avi, avi_size); - pack_hdmi_infoframe(&vendor_infoframe, vendor, vendor_size); - - if (!(ctrl & 0x40000000)) { - nvkm_mask(device, 0x6165c0 + hoff, 0x40000000, 0x00000000); - nvkm_mask(device, 0x6f0100 + hdmi, 0x00000001, 0x00000000); - nvkm_mask(device, 0x6f00c0 + hdmi, 0x00000001, 0x00000000); - nvkm_mask(device, 0x6f0000 + hdmi, 0x00000001, 0x00000000); - return; - } - - /* AVI InfoFrame (AVI). */ - nvkm_mask(device, 0x6f0000 + hdmi, 0x00000001, 0x00000000); - if (avi_size) { - nvkm_wr32(device, 0x6f0008 + hdmi, avi_infoframe.header); - nvkm_wr32(device, 0x6f000c + hdmi, avi_infoframe.subpack0_low); - nvkm_wr32(device, 0x6f0010 + hdmi, avi_infoframe.subpack0_high); - nvkm_wr32(device, 0x6f0014 + hdmi, avi_infoframe.subpack1_low); - nvkm_wr32(device, 0x6f0018 + hdmi, avi_infoframe.subpack1_high); - nvkm_mask(device, 0x6f0000 + hdmi, 0x00000001, 0x00000001); - } - - /* Vendor-specific InfoFrame (VSI). */ - nvkm_mask(device, 0x6f0100 + hdmi, 0x00010001, 0x00000000); - if (vendor_size) { - nvkm_wr32(device, 0x6f0108 + hdmi, vendor_infoframe.header); - nvkm_wr32(device, 0x6f010c + hdmi, vendor_infoframe.subpack0_low); - nvkm_wr32(device, 0x6f0110 + hdmi, vendor_infoframe.subpack0_high); - nvkm_wr32(device, 0x6f0114 + hdmi, 0x00000000); - nvkm_wr32(device, 0x6f0118 + hdmi, 0x00000000); - nvkm_wr32(device, 0x6f011c + hdmi, 0x00000000); - nvkm_wr32(device, 0x6f0120 + hdmi, 0x00000000); - nvkm_wr32(device, 0x6f0124 + hdmi, 0x00000000); - nvkm_mask(device, 0x6f0100 + hdmi, 0x00000001, 0x00000001); - } - - - /* General Control (GCP). */ - nvkm_mask(device, 0x6f00c0 + hdmi, 0x00000001, 0x00000000); - nvkm_wr32(device, 0x6f00cc + hdmi, 0x00000010); - nvkm_mask(device, 0x6f00c0 + hdmi, 0x00000001, 0x00000001); - - /* Audio Clock Regeneration (ACR). */ - nvkm_wr32(device, 0x6f0080 + hdmi, 0x82000000); - - /* NV_PDISP_SF_HDMI_CTRL. */ - nvkm_mask(device, 0x6165c0 + hoff, 0x401f007f, ctrl); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/head.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/head.h index 7dde6237441d..84a2989193cf 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/head.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/head.h @@ -42,19 +42,9 @@ struct nvkm_head_func { void (*vblank_put)(struct nvkm_head *); }; -void nv50_head_rgpos(struct nvkm_head *, u16 *, u16 *); - -#define HEAD_MSG(h,l,f,a...) do { \ - struct nvkm_head *_h = (h); \ - nvkm_##l(&_h->disp->engine.subdev, "head-%d: "f"\n", _h->id, ##a); \ -} while(0) -#define HEAD_WARN(h,f,a...) HEAD_MSG((h), warn, f, ##a) -#define HEAD_DBG(h,f,a...) HEAD_MSG((h), debug, f, ##a) - -int nv04_head_new(struct nvkm_disp *, int id); - int nv50_head_cnt(struct nvkm_disp *, unsigned long *); int nv50_head_new(struct nvkm_disp *, int id); +void nv50_head_rgpos(struct nvkm_head *, u16 *, u16 *); int gf119_head_cnt(struct nvkm_disp *, unsigned long *); int gf119_head_new(struct nvkm_disp *, int id); @@ -62,4 +52,11 @@ void gf119_head_rgclk(struct nvkm_head *, int); int gv100_head_cnt(struct nvkm_disp *, unsigned long *); int gv100_head_new(struct nvkm_disp *, int id); + +#define HEAD_MSG(h,l,f,a...) do { \ + struct nvkm_head *_h = (h); \ + nvkm_##l(&_h->disp->engine.subdev, "head-%d: "f"\n", _h->id, ##a); \ +} while(0) +#define HEAD_WARN(h,f,a...) HEAD_MSG((h), warn, f, ##a) +#define HEAD_DBG(h,f,a...) HEAD_MSG((h), debug, f, ##a) #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/headgf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/headgf119.c deleted file mode 100644 index e86298b35902..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/headgf119.c +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright 2017 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. - * - * Authors: Ben Skeggs <bskeggs@redhat.com> - */ -#include "head.h" - -static void -gf119_head_vblank_put(struct nvkm_head *head) -{ - struct nvkm_device *device = head->disp->engine.subdev.device; - const u32 hoff = head->id * 0x800; - nvkm_mask(device, 0x6100c0 + hoff, 0x00000001, 0x00000000); -} - -static void -gf119_head_vblank_get(struct nvkm_head *head) -{ - struct nvkm_device *device = head->disp->engine.subdev.device; - const u32 hoff = head->id * 0x800; - nvkm_mask(device, 0x6100c0 + hoff, 0x00000001, 0x00000001); -} - -void -gf119_head_rgclk(struct nvkm_head *head, int div) -{ - struct nvkm_device *device = head->disp->engine.subdev.device; - nvkm_mask(device, 0x612200 + (head->id * 0x800), 0x0000000f, div); -} - -static void -gf119_head_state(struct nvkm_head *head, struct nvkm_head_state *state) -{ - struct nvkm_device *device = head->disp->engine.subdev.device; - const u32 hoff = (state == &head->asy) * 0x20000 + head->id * 0x300; - u32 data; - - data = nvkm_rd32(device, 0x640414 + hoff); - state->vtotal = (data & 0xffff0000) >> 16; - state->htotal = (data & 0x0000ffff); - data = nvkm_rd32(device, 0x640418 + hoff); - state->vsynce = (data & 0xffff0000) >> 16; - state->hsynce = (data & 0x0000ffff); - data = nvkm_rd32(device, 0x64041c + hoff); - state->vblanke = (data & 0xffff0000) >> 16; - state->hblanke = (data & 0x0000ffff); - data = nvkm_rd32(device, 0x640420 + hoff); - state->vblanks = (data & 0xffff0000) >> 16; - state->hblanks = (data & 0x0000ffff); - state->hz = nvkm_rd32(device, 0x640450 + hoff); - - data = nvkm_rd32(device, 0x640404 + hoff); - switch ((data & 0x000003c0) >> 6) { - case 6: state->or.depth = 30; break; - case 5: state->or.depth = 24; break; - case 2: state->or.depth = 18; break; - case 0: state->or.depth = 18; break; /*XXX: "default" */ - default: - state->or.depth = 18; - WARN_ON(1); - break; - } -} - -static const struct nvkm_head_func -gf119_head = { - .state = gf119_head_state, - .rgpos = nv50_head_rgpos, - .rgclk = gf119_head_rgclk, - .vblank_get = gf119_head_vblank_get, - .vblank_put = gf119_head_vblank_put, -}; - -int -gf119_head_new(struct nvkm_disp *disp, int id) -{ - return nvkm_head_new_(&gf119_head, disp, id); -} - -int -gf119_head_cnt(struct nvkm_disp *disp, unsigned long *pmask) -{ - struct nvkm_device *device = disp->engine.subdev.device; - *pmask = nvkm_rd32(device, 0x612004) & 0x0000000f; - return nvkm_rd32(device, 0x022448); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/headgv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/headgv100.c deleted file mode 100644 index 1a061b42ae5c..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/headgv100.c +++ /dev/null @@ -1,105 +0,0 @@ -/* - * 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" - -static void -gv100_head_vblank_put(struct nvkm_head *head) -{ - struct nvkm_device *device = head->disp->engine.subdev.device; - nvkm_mask(device, 0x611d80 + (head->id * 4), 0x00000004, 0x00000000); -} - -static void -gv100_head_vblank_get(struct nvkm_head *head) -{ - struct nvkm_device *device = head->disp->engine.subdev.device; - nvkm_mask(device, 0x611d80 + (head->id * 4), 0x00000004, 0x00000004); -} - -static void -gv100_head_rgpos(struct nvkm_head *head, u16 *hline, u16 *vline) -{ - struct nvkm_device *device = head->disp->engine.subdev.device; - const u32 hoff = head->id * 0x800; - /* vline read locks hline. */ - *vline = nvkm_rd32(device, 0x616330 + hoff) & 0x0000ffff; - *hline = nvkm_rd32(device, 0x616334 + hoff) & 0x0000ffff; -} - -static void -gv100_head_state(struct nvkm_head *head, struct nvkm_head_state *state) -{ - struct nvkm_device *device = head->disp->engine.subdev.device; - const u32 hoff = (state == &head->arm) * 0x8000 + head->id * 0x400; - u32 data; - - data = nvkm_rd32(device, 0x682064 + hoff); - state->vtotal = (data & 0xffff0000) >> 16; - state->htotal = (data & 0x0000ffff); - data = nvkm_rd32(device, 0x682068 + hoff); - state->vsynce = (data & 0xffff0000) >> 16; - state->hsynce = (data & 0x0000ffff); - data = nvkm_rd32(device, 0x68206c + hoff); - state->vblanke = (data & 0xffff0000) >> 16; - state->hblanke = (data & 0x0000ffff); - data = nvkm_rd32(device, 0x682070 + hoff); - state->vblanks = (data & 0xffff0000) >> 16; - state->hblanks = (data & 0x0000ffff); - state->hz = nvkm_rd32(device, 0x68200c + hoff); - - data = nvkm_rd32(device, 0x682004 + hoff); - switch ((data & 0x000000f0) >> 4) { - case 5: state->or.depth = 30; break; - case 4: state->or.depth = 24; break; - case 1: state->or.depth = 18; break; - default: - state->or.depth = 18; - WARN_ON(1); - break; - } -} - -static const struct nvkm_head_func -gv100_head = { - .state = gv100_head_state, - .rgpos = gv100_head_rgpos, - .rgclk = gf119_head_rgclk, - .vblank_get = gv100_head_vblank_get, - .vblank_put = gv100_head_vblank_put, -}; - -int -gv100_head_new(struct nvkm_disp *disp, int id) -{ - struct nvkm_device *device = disp->engine.subdev.device; - if (!(nvkm_rd32(device, 0x610060) & (0x00000001 << id))) - return 0; - return nvkm_head_new_(&gv100_head, disp, id); -} - -int -gv100_head_cnt(struct nvkm_disp *disp, unsigned long *pmask) -{ - struct nvkm_device *device = disp->engine.subdev.device; - *pmask = nvkm_rd32(device, 0x610060) & 0x000000ff; - return nvkm_rd32(device, 0x610074) & 0x0000000f; -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/headnv04.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/headnv04.c deleted file mode 100644 index dcf459282aa1..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/headnv04.c +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright 2017 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. - * - * Authors: Ben Skeggs <bskeggs@redhat.com> - */ -#include "head.h" - -static void -nv04_head_vblank_put(struct nvkm_head *head) -{ - struct nvkm_device *device = head->disp->engine.subdev.device; - nvkm_wr32(device, 0x600140 + (head->id * 0x2000) , 0x00000000); -} - -static void -nv04_head_vblank_get(struct nvkm_head *head) -{ - struct nvkm_device *device = head->disp->engine.subdev.device; - nvkm_wr32(device, 0x600140 + (head->id * 0x2000) , 0x00000001); -} - -static void -nv04_head_rgpos(struct nvkm_head *head, u16 *hline, u16 *vline) -{ - struct nvkm_device *device = head->disp->engine.subdev.device; - u32 data = nvkm_rd32(device, 0x600868 + (head->id * 0x2000)); - *hline = (data & 0xffff0000) >> 16; - *vline = (data & 0x0000ffff); -} - -static void -nv04_head_state(struct nvkm_head *head, struct nvkm_head_state *state) -{ - struct nvkm_device *device = head->disp->engine.subdev.device; - const u32 hoff = head->id * 0x0200; - state->vblanks = nvkm_rd32(device, 0x680800 + hoff) & 0x0000ffff; - state->vtotal = nvkm_rd32(device, 0x680804 + hoff) & 0x0000ffff; - state->vblanke = state->vtotal - 1; - state->hblanks = nvkm_rd32(device, 0x680820 + hoff) & 0x0000ffff; - state->htotal = nvkm_rd32(device, 0x680824 + hoff) & 0x0000ffff; - state->hblanke = state->htotal - 1; -} - -static const struct nvkm_head_func -nv04_head = { - .state = nv04_head_state, - .rgpos = nv04_head_rgpos, - .vblank_get = nv04_head_vblank_get, - .vblank_put = nv04_head_vblank_put, -}; - -int -nv04_head_new(struct nvkm_disp *disp, int id) -{ - return nvkm_head_new_(&nv04_head, disp, id); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/headnv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/headnv50.c deleted file mode 100644 index e7d5c397cd29..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/headnv50.c +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright 2017 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. - * - * Authors: Ben Skeggs <bskeggs@redhat.com> - */ -#include "head.h" - -static void -nv50_head_vblank_put(struct nvkm_head *head) -{ - struct nvkm_device *device = head->disp->engine.subdev.device; - nvkm_mask(device, 0x61002c, (4 << head->id), 0); -} - -static void -nv50_head_vblank_get(struct nvkm_head *head) -{ - struct nvkm_device *device = head->disp->engine.subdev.device; - nvkm_mask(device, 0x61002c, (4 << head->id), (4 << head->id)); -} - -static void -nv50_head_rgclk(struct nvkm_head *head, int div) -{ - struct nvkm_device *device = head->disp->engine.subdev.device; - nvkm_mask(device, 0x614200 + (head->id * 0x800), 0x0000000f, div); -} - -void -nv50_head_rgpos(struct nvkm_head *head, u16 *hline, u16 *vline) -{ - struct nvkm_device *device = head->disp->engine.subdev.device; - const u32 hoff = head->id * 0x800; - /* vline read locks hline. */ - *vline = nvkm_rd32(device, 0x616340 + hoff) & 0x0000ffff; - *hline = nvkm_rd32(device, 0x616344 + hoff) & 0x0000ffff; -} - -static void -nv50_head_state(struct nvkm_head *head, struct nvkm_head_state *state) -{ - struct nvkm_device *device = head->disp->engine.subdev.device; - const u32 hoff = head->id * 0x540 + (state == &head->arm) * 4; - u32 data; - - data = nvkm_rd32(device, 0x610ae8 + hoff); - state->vblanke = (data & 0xffff0000) >> 16; - state->hblanke = (data & 0x0000ffff); - data = nvkm_rd32(device, 0x610af0 + hoff); - state->vblanks = (data & 0xffff0000) >> 16; - state->hblanks = (data & 0x0000ffff); - data = nvkm_rd32(device, 0x610af8 + hoff); - state->vtotal = (data & 0xffff0000) >> 16; - state->htotal = (data & 0x0000ffff); - data = nvkm_rd32(device, 0x610b00 + hoff); - state->vsynce = (data & 0xffff0000) >> 16; - state->hsynce = (data & 0x0000ffff); - state->hz = (nvkm_rd32(device, 0x610ad0 + hoff) & 0x003fffff) * 1000; -} - -static const struct nvkm_head_func -nv50_head = { - .state = nv50_head_state, - .rgpos = nv50_head_rgpos, - .rgclk = nv50_head_rgclk, - .vblank_get = nv50_head_vblank_get, - .vblank_put = nv50_head_vblank_put, -}; - -int -nv50_head_new(struct nvkm_disp *disp, int id) -{ - return nvkm_head_new_(&nv50_head, disp, id); -} - -int -nv50_head_cnt(struct nvkm_disp *disp, unsigned long *pmask) -{ - *pmask = 3; - return 2; -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h index 9f0bb7c6b010..a8bd12a6bbf9 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h @@ -103,10 +103,13 @@ nv50_ior_base(struct nvkm_ior *ior) return ior->id * 0x800; } +int nv50_dac_cnt(struct nvkm_disp *, unsigned long *); +int nv50_dac_new(struct nvkm_disp *, int); void nv50_dac_power(struct nvkm_ior *, bool, bool, bool, bool, bool); int nv50_dac_sense(struct nvkm_ior *, u32); -void nv50_pior_depth(struct nvkm_ior *, struct nvkm_ior_state *, u32 ctrl); +int gf119_dac_cnt(struct nvkm_disp *, unsigned long *); +int gf119_dac_new(struct nvkm_disp *, int); static inline u32 nv50_sor_link(struct nvkm_ior *ior) @@ -114,10 +117,15 @@ nv50_sor_link(struct nvkm_ior *ior) return nv50_ior_base(ior) + ((ior->asy.link == 2) * 0x80); } +int nv50_sor_cnt(struct nvkm_disp *, unsigned long *); void nv50_sor_state(struct nvkm_ior *, struct nvkm_ior_state *); void nv50_sor_power(struct nvkm_ior *, bool, bool, bool, bool, bool); void nv50_sor_clock(struct nvkm_ior *); +int g84_sor_new(struct nvkm_disp *, int); +void g84_sor_hdmi_ctrl(struct nvkm_ior *, int, bool, u8, u8, u8 *, u8 , u8 *, u8); + +int g94_sor_cnt(struct nvkm_disp *, unsigned long *); void g94_sor_state(struct nvkm_ior *, struct nvkm_ior_state *); int g94_sor_dp_links(struct nvkm_ior *, struct nvkm_i2c_aux *); void g94_sor_dp_power(struct nvkm_ior *, int); @@ -127,8 +135,12 @@ void g94_sor_dp_audio_sym(struct nvkm_ior *, int, u16, u32); void g94_sor_dp_activesym(struct nvkm_ior *, int, u8, u8, u8, u8); void g94_sor_dp_watermark(struct nvkm_ior *, int, u8); +void gt215_sor_hdmi_ctrl(struct nvkm_ior *, int, bool, u8, u8, u8 *, u8 , u8 *, u8); void gt215_sor_dp_audio(struct nvkm_ior *, int, bool); +void gt215_sor_hda_hpd(struct nvkm_ior *, int, bool); +void gt215_sor_hda_eld(struct nvkm_ior *, int, u8 *, u8); +int gf119_sor_cnt(struct nvkm_disp *, unsigned long *); void gf119_sor_state(struct nvkm_ior *, struct nvkm_ior_state *); void gf119_sor_clock(struct nvkm_ior *); int gf119_sor_dp_links(struct nvkm_ior *, struct nvkm_i2c_aux *); @@ -138,36 +150,35 @@ void gf119_sor_dp_vcpi(struct nvkm_ior *, int, u8, u8, u16, u16); void gf119_sor_dp_audio(struct nvkm_ior *, int, bool); void gf119_sor_dp_audio_sym(struct nvkm_ior *, int, u16, u32); void gf119_sor_dp_watermark(struct nvkm_ior *, int, u8); +void gf119_sor_hda_hpd(struct nvkm_ior *, int, bool); +void gf119_sor_hda_eld(struct nvkm_ior *, int, u8 *, u8); +void gf119_sor_hda_device_entry(struct nvkm_ior *, int); + +int gk104_sor_new(struct nvkm_disp *, int); +void gk104_sor_hdmi_ctrl(struct nvkm_ior *, int, bool, u8, u8, u8 *, u8 , u8 *, u8); void gm107_sor_dp_pattern(struct nvkm_ior *, int); void gm200_sor_route_set(struct nvkm_outp *, struct nvkm_ior *); int gm200_sor_route_get(struct nvkm_outp *, int *); +void gm200_sor_hdmi_scdc(struct nvkm_ior *, u8); void gm200_sor_dp_drive(struct nvkm_ior *, int, int, int, int, int); +int gp100_sor_new(struct nvkm_disp *, int); + +int gv100_sor_cnt(struct nvkm_disp *, unsigned long *); void gv100_sor_state(struct nvkm_ior *, struct nvkm_ior_state *); +void gv100_sor_hdmi_ctrl(struct nvkm_ior *, int, bool, u8, u8, u8 *, u8 , u8 *, u8); 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 gv100_sor_hda_device_entry(struct nvkm_ior *, int); void tu102_sor_dp_vcpi(struct nvkm_ior *, int, u8, u8, u16, u16); -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); -void gk104_hdmi_ctrl(struct nvkm_ior *, int, bool, u8, u8, u8 *, u8 , u8 *, u8); -void gv100_hdmi_ctrl(struct nvkm_ior *, int, bool, u8, u8, u8 *, u8 , u8 *, u8); - -void gm200_hdmi_scdc(struct nvkm_ior *, u8); - -void gt215_hda_hpd(struct nvkm_ior *, int, bool); -void gt215_hda_eld(struct nvkm_ior *, int, u8 *, u8); - -void gf119_hda_hpd(struct nvkm_ior *, int, bool); -void gf119_hda_eld(struct nvkm_ior *, int, u8 *, u8); -void gf119_hda_device_entry(struct nvkm_ior *, int); - -void gv100_hda_device_entry(struct nvkm_ior *, int); +int nv50_pior_cnt(struct nvkm_disp *, unsigned long *); +int nv50_pior_new(struct nvkm_disp *, int); +void nv50_pior_depth(struct nvkm_ior *, struct nvkm_ior_state *, u32 ctrl); #define IOR_MSG(i,l,f,a...) do { \ struct nvkm_ior *_ior = (i); \ @@ -175,40 +186,4 @@ void gv100_hda_device_entry(struct nvkm_ior *, int); } while(0) #define IOR_WARN(i,f,a...) IOR_MSG((i), warn, f, ##a) #define IOR_DBG(i,f,a...) IOR_MSG((i), debug, f, ##a) - -int nv50_dac_cnt(struct nvkm_disp *, unsigned long *); -int nv50_dac_new(struct nvkm_disp *, int); - -int gf119_dac_cnt(struct nvkm_disp *, unsigned long *); -int gf119_dac_new(struct nvkm_disp *, int); - -int nv50_pior_cnt(struct nvkm_disp *, unsigned long *); -int nv50_pior_new(struct nvkm_disp *, int); - -int nv50_sor_cnt(struct nvkm_disp *, unsigned long *); -int nv50_sor_new(struct nvkm_disp *, int); - -int g84_sor_new(struct nvkm_disp *, int); - -int g94_sor_cnt(struct nvkm_disp *, unsigned long *); -int g94_sor_new(struct nvkm_disp *, int); - -int mcp77_sor_new(struct nvkm_disp *, int); -int gt215_sor_new(struct nvkm_disp *, int); -int mcp89_sor_new(struct nvkm_disp *, int); - -int gf119_sor_cnt(struct nvkm_disp *, unsigned long *); -int gf119_sor_new(struct nvkm_disp *, int); - -int gk104_sor_new(struct nvkm_disp *, int); -int gm107_sor_new(struct nvkm_disp *, int); -int gm200_sor_new(struct nvkm_disp *, int); -int gp100_sor_new(struct nvkm_disp *, int); - -int gv100_sor_cnt(struct nvkm_disp *, unsigned long *); -int gv100_sor_new(struct nvkm_disp *, int); - -int tu102_sor_new(struct nvkm_disp *, int); - -int ga102_sor_new(struct nvkm_disp *, int); #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/mcp77.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/mcp77.c index 01fd421f1399..e23e3b80817f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/mcp77.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/mcp77.c @@ -20,16 +20,42 @@ * OTHER DEALINGS IN THE SOFTWARE. */ #include "priv.h" +#include "chan.h" #include "head.h" #include "ior.h" -#include "channv50.h" #include <nvif/class.h> +static const struct nvkm_ior_func +mcp77_sor = { + .state = g94_sor_state, + .power = nv50_sor_power, + .clock = nv50_sor_clock, + .hdmi = { + .ctrl = g84_sor_hdmi_ctrl, + }, + .dp = { + .lanes = { 2, 1, 0, 3}, + .links = g94_sor_dp_links, + .power = g94_sor_dp_power, + .pattern = g94_sor_dp_pattern, + .drive = g94_sor_dp_drive, + .audio_sym = g94_sor_dp_audio_sym, + .activesym = g94_sor_dp_activesym, + .watermark = g94_sor_dp_watermark, + }, +}; + +static int +mcp77_sor_new(struct nvkm_disp *disp, int id) +{ + return nvkm_ior_new_(&mcp77_sor, disp, SOR, id); +} + static const struct nvkm_disp_func mcp77_disp = { - .dtor = nv50_disp_dtor_, - .oneinit = nv50_disp_oneinit_, + .dtor = nv50_disp_dtor, + .oneinit = nv50_disp_oneinit, .init = nv50_disp_init, .fini = nv50_disp_fini, .intr = nv50_disp_intr, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/mcp89.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/mcp89.c index 825274b5a8f8..2dc99897dc67 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/mcp89.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/mcp89.c @@ -20,16 +20,47 @@ * OTHER DEALINGS IN THE SOFTWARE. */ #include "priv.h" +#include "chan.h" #include "head.h" #include "ior.h" -#include "channv50.h" #include <nvif/class.h> +static const struct nvkm_ior_func +mcp89_sor = { + .state = g94_sor_state, + .power = nv50_sor_power, + .clock = nv50_sor_clock, + .hdmi = { + .ctrl = gt215_sor_hdmi_ctrl, + }, + .dp = { + .lanes = { 3, 2, 1, 0 }, + .links = g94_sor_dp_links, + .power = g94_sor_dp_power, + .pattern = g94_sor_dp_pattern, + .drive = g94_sor_dp_drive, + .audio = gt215_sor_dp_audio, + .audio_sym = g94_sor_dp_audio_sym, + .activesym = g94_sor_dp_activesym, + .watermark = g94_sor_dp_watermark, + }, + .hda = { + .hpd = gt215_sor_hda_hpd, + .eld = gt215_sor_hda_eld, + }, +}; + +static int +mcp89_sor_new(struct nvkm_disp *disp, int id) +{ + return nvkm_ior_new_(&mcp89_sor, disp, SOR, id); +} + static const struct nvkm_disp_func mcp89_disp = { - .dtor = nv50_disp_dtor_, - .oneinit = nv50_disp_oneinit_, + .dtor = nv50_disp_dtor, + .oneinit = nv50_disp_oneinit, .init = nv50_disp_init, .fini = nv50_disp_fini, .intr = nv50_disp_intr, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv04.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv04.c index 02bfc52b5b14..e4cf11a33969 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv04.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv04.c @@ -27,6 +27,56 @@ #include <nvif/class.h> static void +nv04_head_vblank_put(struct nvkm_head *head) +{ + struct nvkm_device *device = head->disp->engine.subdev.device; + nvkm_wr32(device, 0x600140 + (head->id * 0x2000) , 0x00000000); +} + +static void +nv04_head_vblank_get(struct nvkm_head *head) +{ + struct nvkm_device *device = head->disp->engine.subdev.device; + nvkm_wr32(device, 0x600140 + (head->id * 0x2000) , 0x00000001); +} + +static void +nv04_head_rgpos(struct nvkm_head *head, u16 *hline, u16 *vline) +{ + struct nvkm_device *device = head->disp->engine.subdev.device; + u32 data = nvkm_rd32(device, 0x600868 + (head->id * 0x2000)); + *hline = (data & 0xffff0000) >> 16; + *vline = (data & 0x0000ffff); +} + +static void +nv04_head_state(struct nvkm_head *head, struct nvkm_head_state *state) +{ + struct nvkm_device *device = head->disp->engine.subdev.device; + const u32 hoff = head->id * 0x0200; + state->vblanks = nvkm_rd32(device, 0x680800 + hoff) & 0x0000ffff; + state->vtotal = nvkm_rd32(device, 0x680804 + hoff) & 0x0000ffff; + state->vblanke = state->vtotal - 1; + state->hblanks = nvkm_rd32(device, 0x680820 + hoff) & 0x0000ffff; + state->htotal = nvkm_rd32(device, 0x680824 + hoff) & 0x0000ffff; + state->hblanke = state->htotal - 1; +} + +static const struct nvkm_head_func +nv04_head = { + .state = nv04_head_state, + .rgpos = nv04_head_rgpos, + .vblank_get = nv04_head_vblank_get, + .vblank_put = nv04_head_vblank_put, +}; + +static int +nv04_head_new(struct nvkm_disp *disp, int id) +{ + return nvkm_head_new_(&nv04_head, disp, id); +} + +static void nv04_disp_intr(struct nvkm_disp *disp) { struct nvkm_subdev *subdev = &disp->engine.subdev; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c index 0e8c0413d887..130e1db95032 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c @@ -22,10 +22,10 @@ * Authors: Ben Skeggs */ #include "priv.h" +#include "chan.h" #include "head.h" #include "ior.h" #include "outp.h" -#include "channv50.h" #include <core/client.h> #include <core/ramht.h> @@ -34,110 +34,1126 @@ #include <subdev/bios/init.h> #include <subdev/bios/pll.h> #include <subdev/devinit.h> +#include <subdev/i2c.h> +#include <subdev/mmu.h> #include <subdev/timer.h> #include <nvif/class.h> +#include <nvif/cl507a.h> +#include <nvif/cl507b.h> +#include <nvif/cl507c.h> +#include <nvif/cl507d.h> +#include <nvif/cl507e.h> +#include <nvif/event.h> +#include <nvif/unpack.h> -void * -nv50_disp_dtor_(struct nvkm_disp *disp) +static void +nv50_pior_clock(struct nvkm_ior *pior) { - nvkm_ramht_del(&disp->ramht); - nvkm_gpuobj_del(&disp->inst); + struct nvkm_device *device = pior->disp->engine.subdev.device; + const u32 poff = nv50_ior_base(pior); - nvkm_event_fini(&disp->uevent); - if (disp->wq) - destroy_workqueue(disp->wq); + nvkm_mask(device, 0x614380 + poff, 0x00000707, 0x00000001); +} - return disp; +static int +nv50_pior_dp_links(struct nvkm_ior *pior, struct nvkm_i2c_aux *aux) +{ + int ret = nvkm_i2c_aux_lnk_ctl(aux, pior->dp.nr, pior->dp.bw, pior->dp.ef); + if (ret) + return ret; + + return 1; +} + +static void +nv50_pior_power_wait(struct nvkm_device *device, u32 poff) +{ + nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x61e004 + poff) & 0x80000000)) + break; + ); +} + +static void +nv50_pior_power(struct nvkm_ior *pior, bool normal, bool pu, bool data, bool vsync, bool hsync) +{ + struct nvkm_device *device = pior->disp->engine.subdev.device; + const u32 poff = nv50_ior_base(pior); + const u32 shift = normal ? 0 : 16; + const u32 state = 0x80000000 | (0x00000001 * !!pu) << shift; + const u32 field = 0x80000000 | (0x00000101 << shift); + + nv50_pior_power_wait(device, poff); + nvkm_mask(device, 0x61e004 + poff, field, state); + nv50_pior_power_wait(device, poff); +} + +void +nv50_pior_depth(struct nvkm_ior *ior, struct nvkm_ior_state *state, u32 ctrl) +{ + /* GF119 moves this information to per-head methods, which is + * a lot more convenient, and where our shared code expect it. + */ + if (state->head && state == &ior->asy) { + struct nvkm_head *head = nvkm_head_find(ior->disp, __ffs(state->head)); + + if (!WARN_ON(!head)) { + struct nvkm_head_state *state = &head->asy; + switch ((ctrl & 0x000f0000) >> 16) { + case 6: state->or.depth = 30; break; + case 5: state->or.depth = 24; break; + case 2: state->or.depth = 18; break; + case 0: state->or.depth = 18; break; /*XXX*/ + default: + state->or.depth = 18; + WARN_ON(1); + break; + } + } + } } +static void +nv50_pior_state(struct nvkm_ior *pior, struct nvkm_ior_state *state) +{ + struct nvkm_device *device = pior->disp->engine.subdev.device; + const u32 coff = pior->id * 8 + (state == &pior->arm) * 4; + u32 ctrl = nvkm_rd32(device, 0x610b80 + coff); + + state->proto_evo = (ctrl & 0x00000f00) >> 8; + state->rgdiv = 1; + switch (state->proto_evo) { + case 0: state->proto = TMDS; break; + default: + state->proto = UNKNOWN; + break; + } + + state->head = ctrl & 0x00000003; + nv50_pior_depth(pior, state, ctrl); +} + +static const struct nvkm_ior_func +nv50_pior = { + .state = nv50_pior_state, + .power = nv50_pior_power, + .clock = nv50_pior_clock, + .dp = { + .links = nv50_pior_dp_links, + }, +}; + int -nv50_disp_oneinit_(struct nvkm_disp *disp) +nv50_pior_new(struct nvkm_disp *disp, int id) { - const struct nvkm_disp_func *func = disp->func; - struct nvkm_subdev *subdev = &disp->engine.subdev; - struct nvkm_device *device = subdev->device; - int ret, i; + return nvkm_ior_new_(&nv50_pior, disp, PIOR, id); +} - if (func->wndw.cnt) { - disp->wndw.nr = func->wndw.cnt(disp, &disp->wndw.mask); - nvkm_debug(subdev, "Window(s): %d (%08lx)\n", - disp->wndw.nr, disp->wndw.mask); +int +nv50_pior_cnt(struct nvkm_disp *disp, unsigned long *pmask) +{ + struct nvkm_device *device = disp->engine.subdev.device; + + *pmask = (nvkm_rd32(device, 0x610184) & 0x70000000) >> 28; + return 3; +} + +void +nv50_sor_clock(struct nvkm_ior *sor) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const int div = sor->asy.link == 3; + const u32 soff = nv50_ior_base(sor); + + nvkm_mask(device, 0x614300 + soff, 0x00000707, (div << 8) | div); +} + +static void +nv50_sor_power_wait(struct nvkm_device *device, u32 soff) +{ + nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x61c004 + soff) & 0x80000000)) + break; + ); +} + +void +nv50_sor_power(struct nvkm_ior *sor, bool normal, bool pu, bool data, bool vsync, bool hsync) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 soff = nv50_ior_base(sor); + const u32 shift = normal ? 0 : 16; + const u32 state = 0x80000000 | (0x00000001 * !!pu) << shift; + const u32 field = 0x80000000 | (0x00000001 << shift); + + nv50_sor_power_wait(device, soff); + nvkm_mask(device, 0x61c004 + soff, field, state); + nv50_sor_power_wait(device, soff); + + nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x61c030 + soff) & 0x10000000)) + break; + ); +} + +void +nv50_sor_state(struct nvkm_ior *sor, struct nvkm_ior_state *state) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 coff = sor->id * 8 + (state == &sor->arm) * 4; + u32 ctrl = nvkm_rd32(device, 0x610b70 + coff); + + state->proto_evo = (ctrl & 0x00000f00) >> 8; + switch (state->proto_evo) { + case 0: state->proto = LVDS; state->link = 1; break; + case 1: state->proto = TMDS; state->link = 1; break; + case 2: state->proto = TMDS; state->link = 2; break; + case 5: state->proto = TMDS; state->link = 3; break; + default: + state->proto = UNKNOWN; + break; } - disp->head.nr = func->head.cnt(disp, &disp->head.mask); - nvkm_debug(subdev, " Head(s): %d (%02lx)\n", - disp->head.nr, disp->head.mask); - for_each_set_bit(i, &disp->head.mask, disp->head.nr) { - ret = func->head.new(disp, i); - if (ret) - return ret; + state->head = ctrl & 0x00000003; +} + +static const struct nvkm_ior_func +nv50_sor = { + .state = nv50_sor_state, + .power = nv50_sor_power, + .clock = nv50_sor_clock, +}; + +static int +nv50_sor_new(struct nvkm_disp *disp, int id) +{ + return nvkm_ior_new_(&nv50_sor, disp, SOR, id); +} + +int +nv50_sor_cnt(struct nvkm_disp *disp, unsigned long *pmask) +{ + struct nvkm_device *device = disp->engine.subdev.device; + + *pmask = (nvkm_rd32(device, 0x610184) & 0x03000000) >> 24; + return 2; +} + +static void +nv50_dac_clock(struct nvkm_ior *dac) +{ + struct nvkm_device *device = dac->disp->engine.subdev.device; + const u32 doff = nv50_ior_base(dac); + + nvkm_mask(device, 0x614280 + doff, 0x07070707, 0x00000000); +} + +int +nv50_dac_sense(struct nvkm_ior *dac, u32 loadval) +{ + struct nvkm_device *device = dac->disp->engine.subdev.device; + const u32 doff = nv50_ior_base(dac); + + dac->func->power(dac, false, true, false, false, false); + + nvkm_wr32(device, 0x61a00c + doff, 0x00100000 | loadval); + mdelay(9); + udelay(500); + loadval = nvkm_mask(device, 0x61a00c + doff, 0xffffffff, 0x00000000); + + dac->func->power(dac, false, false, false, false, false); + if (!(loadval & 0x80000000)) + return -ETIMEDOUT; + + return (loadval & 0x38000000) >> 27; +} + +static void +nv50_dac_power_wait(struct nvkm_device *device, const u32 doff) +{ + nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x61a004 + doff) & 0x80000000)) + break; + ); +} + +void +nv50_dac_power(struct nvkm_ior *dac, bool normal, bool pu, bool data, bool vsync, bool hsync) +{ + struct nvkm_device *device = dac->disp->engine.subdev.device; + const u32 doff = nv50_ior_base(dac); + const u32 shift = normal ? 0 : 16; + const u32 state = 0x80000000 | (0x00000040 * ! pu | + 0x00000010 * ! data | + 0x00000004 * ! vsync | + 0x00000001 * ! hsync) << shift; + const u32 field = 0xc0000000 | (0x00000055 << shift); + + nv50_dac_power_wait(device, doff); + nvkm_mask(device, 0x61a004 + doff, field, state); + nv50_dac_power_wait(device, doff); +} + +static void +nv50_dac_state(struct nvkm_ior *dac, struct nvkm_ior_state *state) +{ + struct nvkm_device *device = dac->disp->engine.subdev.device; + const u32 coff = dac->id * 8 + (state == &dac->arm) * 4; + u32 ctrl = nvkm_rd32(device, 0x610b58 + coff); + + state->proto_evo = (ctrl & 0x00000f00) >> 8; + switch (state->proto_evo) { + case 0: state->proto = CRT; break; + default: + state->proto = UNKNOWN; + break; } - if (func->dac.cnt) { - disp->dac.nr = func->dac.cnt(disp, &disp->dac.mask); - nvkm_debug(subdev, " DAC(s): %d (%02lx)\n", - disp->dac.nr, disp->dac.mask); - for_each_set_bit(i, &disp->dac.mask, disp->dac.nr) { - ret = func->dac.new(disp, i); - if (ret) - return ret; + state->head = ctrl & 0x00000003; +} + +static const struct nvkm_ior_func +nv50_dac = { + .state = nv50_dac_state, + .power = nv50_dac_power, + .sense = nv50_dac_sense, + .clock = nv50_dac_clock, +}; + +int +nv50_dac_new(struct nvkm_disp *disp, int id) +{ + return nvkm_ior_new_(&nv50_dac, disp, DAC, id); +} + +int +nv50_dac_cnt(struct nvkm_disp *disp, unsigned long *pmask) +{ + struct nvkm_device *device = disp->engine.subdev.device; + + *pmask = (nvkm_rd32(device, 0x610184) & 0x00700000) >> 20; + return 3; +} + +static void +nv50_head_vblank_put(struct nvkm_head *head) +{ + struct nvkm_device *device = head->disp->engine.subdev.device; + + nvkm_mask(device, 0x61002c, (4 << head->id), 0); +} + +static void +nv50_head_vblank_get(struct nvkm_head *head) +{ + struct nvkm_device *device = head->disp->engine.subdev.device; + + nvkm_mask(device, 0x61002c, (4 << head->id), (4 << head->id)); +} + +static void +nv50_head_rgclk(struct nvkm_head *head, int div) +{ + struct nvkm_device *device = head->disp->engine.subdev.device; + + nvkm_mask(device, 0x614200 + (head->id * 0x800), 0x0000000f, div); +} + +void +nv50_head_rgpos(struct nvkm_head *head, u16 *hline, u16 *vline) +{ + struct nvkm_device *device = head->disp->engine.subdev.device; + const u32 hoff = head->id * 0x800; + + /* vline read locks hline. */ + *vline = nvkm_rd32(device, 0x616340 + hoff) & 0x0000ffff; + *hline = nvkm_rd32(device, 0x616344 + hoff) & 0x0000ffff; +} + +static void +nv50_head_state(struct nvkm_head *head, struct nvkm_head_state *state) +{ + struct nvkm_device *device = head->disp->engine.subdev.device; + const u32 hoff = head->id * 0x540 + (state == &head->arm) * 4; + u32 data; + + data = nvkm_rd32(device, 0x610ae8 + hoff); + state->vblanke = (data & 0xffff0000) >> 16; + state->hblanke = (data & 0x0000ffff); + data = nvkm_rd32(device, 0x610af0 + hoff); + state->vblanks = (data & 0xffff0000) >> 16; + state->hblanks = (data & 0x0000ffff); + data = nvkm_rd32(device, 0x610af8 + hoff); + state->vtotal = (data & 0xffff0000) >> 16; + state->htotal = (data & 0x0000ffff); + data = nvkm_rd32(device, 0x610b00 + hoff); + state->vsynce = (data & 0xffff0000) >> 16; + state->hsynce = (data & 0x0000ffff); + state->hz = (nvkm_rd32(device, 0x610ad0 + hoff) & 0x003fffff) * 1000; +} + +static const struct nvkm_head_func +nv50_head = { + .state = nv50_head_state, + .rgpos = nv50_head_rgpos, + .rgclk = nv50_head_rgclk, + .vblank_get = nv50_head_vblank_get, + .vblank_put = nv50_head_vblank_put, +}; + +int +nv50_head_new(struct nvkm_disp *disp, int id) +{ + return nvkm_head_new_(&nv50_head, disp, id); +} + +int +nv50_head_cnt(struct nvkm_disp *disp, unsigned long *pmask) +{ + *pmask = 3; + return 2; +} + + +static void +nv50_disp_mthd_list(struct nvkm_disp *disp, int debug, u32 base, int c, + const struct nvkm_disp_mthd_list *list, int inst) +{ + struct nvkm_subdev *subdev = &disp->engine.subdev; + struct nvkm_device *device = subdev->device; + int i; + + for (i = 0; list->data[i].mthd; i++) { + if (list->data[i].addr) { + u32 next = nvkm_rd32(device, list->data[i].addr + base + 0); + u32 prev = nvkm_rd32(device, list->data[i].addr + base + c); + u32 mthd = list->data[i].mthd + (list->mthd * inst); + const char *name = list->data[i].name; + char mods[16]; + + if (prev != next) + snprintf(mods, sizeof(mods), "-> %08x", next); + else + snprintf(mods, sizeof(mods), "%13c", ' '); + + nvkm_printk_(subdev, debug, info, + "\t%04x: %08x %s%s%s\n", + mthd, prev, mods, name ? " // " : "", + name ? name : ""); } } +} - if (func->pior.cnt) { - disp->pior.nr = func->pior.cnt(disp, &disp->pior.mask); - nvkm_debug(subdev, " PIOR(s): %d (%02lx)\n", - disp->pior.nr, disp->pior.mask); - for_each_set_bit(i, &disp->pior.mask, disp->pior.nr) { - ret = func->pior.new(disp, i); - if (ret) - return ret; +void +nv50_disp_chan_mthd(struct nvkm_disp_chan *chan, int debug) +{ + struct nvkm_disp *disp = chan->disp; + struct nvkm_subdev *subdev = &disp->engine.subdev; + const struct nvkm_disp_chan_mthd *mthd = chan->mthd; + const struct nvkm_disp_mthd_list *list; + int i, j; + + if (debug > subdev->debug) + return; + if (!mthd) + return; + + for (i = 0; (list = mthd->data[i].mthd) != NULL; i++) { + u32 base = chan->head * mthd->addr; + for (j = 0; j < mthd->data[i].nr; j++, base += list->addr) { + const char *cname = mthd->name; + const char *sname = ""; + char cname_[16], sname_[16]; + + if (mthd->addr) { + snprintf(cname_, sizeof(cname_), "%s %d", + mthd->name, chan->chid.user); + cname = cname_; + } + + if (mthd->data[i].nr > 1) { + snprintf(sname_, sizeof(sname_), " - %s %d", + mthd->data[i].name, j); + sname = sname_; + } + + nvkm_printk_(subdev, debug, info, "%s%s:\n", cname, sname); + nv50_disp_mthd_list(disp, debug, base, mthd->prev, + list, j); } } +} - disp->sor.nr = func->sor.cnt(disp, &disp->sor.mask); - nvkm_debug(subdev, " SOR(s): %d (%02lx)\n", - disp->sor.nr, disp->sor.mask); - for_each_set_bit(i, &disp->sor.mask, disp->sor.nr) { - ret = func->sor.new(disp, i); - if (ret) - return ret; +static void +nv50_disp_chan_uevent_fini(struct nvkm_event *event, int type, int index) +{ + struct nvkm_disp *disp = container_of(event, typeof(*disp), uevent); + struct nvkm_device *device = disp->engine.subdev.device; + nvkm_mask(device, 0x610028, 0x00000001 << index, 0x00000000 << index); + nvkm_wr32(device, 0x610020, 0x00000001 << index); +} + +static void +nv50_disp_chan_uevent_init(struct nvkm_event *event, int types, int index) +{ + struct nvkm_disp *disp = container_of(event, typeof(*disp), uevent); + struct nvkm_device *device = disp->engine.subdev.device; + nvkm_wr32(device, 0x610020, 0x00000001 << index); + nvkm_mask(device, 0x610028, 0x00000001 << index, 0x00000001 << index); +} + +void +nv50_disp_chan_uevent_send(struct nvkm_disp *disp, int chid) +{ + struct nvif_notify_uevent_rep { + } rep; + + nvkm_event_send(&disp->uevent, 1, chid, &rep, sizeof(rep)); +} + +int +nv50_disp_chan_uevent_ctor(struct nvkm_object *object, void *data, u32 size, + struct nvkm_notify *notify) +{ + struct nvkm_disp_chan *chan = nvkm_disp_chan(object); + union { + struct nvif_notify_uevent_req none; + } *args = data; + int ret = -ENOSYS; + + if (!(ret = nvif_unvers(ret, &data, &size, args->none))) { + notify->size = sizeof(struct nvif_notify_uevent_rep); + notify->types = 1; + notify->index = chan->chid.user; + return 0; + } + + return ret; +} + +const struct nvkm_event_func +nv50_disp_chan_uevent = { + .ctor = nv50_disp_chan_uevent_ctor, + .init = nv50_disp_chan_uevent_init, + .fini = nv50_disp_chan_uevent_fini, +}; + +u64 +nv50_disp_chan_user(struct nvkm_disp_chan *chan, u64 *psize) +{ + *psize = 0x1000; + return 0x640000 + (chan->chid.user * 0x1000); +} + +void +nv50_disp_chan_intr(struct nvkm_disp_chan *chan, bool en) +{ + struct nvkm_device *device = chan->disp->engine.subdev.device; + const u32 mask = 0x00010001 << chan->chid.user; + const u32 data = en ? 0x00010000 << chan->chid.user : 0x00000000; + nvkm_mask(device, 0x610028, mask, data); +} + +static void +nv50_disp_pioc_fini(struct nvkm_disp_chan *chan) +{ + struct nvkm_disp *disp = chan->disp; + struct nvkm_subdev *subdev = &disp->engine.subdev; + struct nvkm_device *device = subdev->device; + int ctrl = chan->chid.ctrl; + int user = chan->chid.user; + + nvkm_mask(device, 0x610200 + (ctrl * 0x10), 0x00000001, 0x00000000); + if (nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x610200 + (ctrl * 0x10)) & 0x00030000)) + break; + ) < 0) { + nvkm_error(subdev, "ch %d timeout: %08x\n", user, + nvkm_rd32(device, 0x610200 + (ctrl * 0x10))); + } +} + +static int +nv50_disp_pioc_init(struct nvkm_disp_chan *chan) +{ + struct nvkm_disp *disp = chan->disp; + struct nvkm_subdev *subdev = &disp->engine.subdev; + struct nvkm_device *device = subdev->device; + int ctrl = chan->chid.ctrl; + int user = chan->chid.user; + + nvkm_wr32(device, 0x610200 + (ctrl * 0x10), 0x00002000); + if (nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x610200 + (ctrl * 0x10)) & 0x00030000)) + break; + ) < 0) { + nvkm_error(subdev, "ch %d timeout0: %08x\n", user, + nvkm_rd32(device, 0x610200 + (ctrl * 0x10))); + return -EBUSY; + } + + nvkm_wr32(device, 0x610200 + (ctrl * 0x10), 0x00000001); + if (nvkm_msec(device, 2000, + u32 tmp = nvkm_rd32(device, 0x610200 + (ctrl * 0x10)); + if ((tmp & 0x00030000) == 0x00010000) + break; + ) < 0) { + nvkm_error(subdev, "ch %d timeout1: %08x\n", user, + nvkm_rd32(device, 0x610200 + (ctrl * 0x10))); + return -EBUSY; + } + + return 0; +} + +const struct nvkm_disp_chan_func +nv50_disp_pioc_func = { + .init = nv50_disp_pioc_init, + .fini = nv50_disp_pioc_fini, + .intr = nv50_disp_chan_intr, + .user = nv50_disp_chan_user, +}; + +int +nv50_disp_dmac_bind(struct nvkm_disp_chan *chan, struct nvkm_object *object, u32 handle) +{ + return nvkm_ramht_insert(chan->disp->ramht, object, chan->chid.user, -10, handle, + chan->chid.user << 28 | chan->chid.user); +} + +static void +nv50_disp_dmac_fini(struct nvkm_disp_chan *chan) +{ + struct nvkm_subdev *subdev = &chan->disp->engine.subdev; + struct nvkm_device *device = subdev->device; + int ctrl = chan->chid.ctrl; + int user = chan->chid.user; + + /* deactivate channel */ + nvkm_mask(device, 0x610200 + (ctrl * 0x0010), 0x00001010, 0x00001000); + nvkm_mask(device, 0x610200 + (ctrl * 0x0010), 0x00000003, 0x00000000); + if (nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x610200 + (ctrl * 0x10)) & 0x001e0000)) + break; + ) < 0) { + nvkm_error(subdev, "ch %d fini timeout, %08x\n", user, + nvkm_rd32(device, 0x610200 + (ctrl * 0x10))); + } + + chan->suspend_put = nvkm_rd32(device, 0x640000 + (ctrl * 0x1000)); +} + +static int +nv50_disp_dmac_init(struct nvkm_disp_chan *chan) +{ + struct nvkm_subdev *subdev = &chan->disp->engine.subdev; + struct nvkm_device *device = subdev->device; + int ctrl = chan->chid.ctrl; + int user = chan->chid.user; + + /* initialise channel for dma command submission */ + nvkm_wr32(device, 0x610204 + (ctrl * 0x0010), chan->push); + nvkm_wr32(device, 0x610208 + (ctrl * 0x0010), 0x00010000); + nvkm_wr32(device, 0x61020c + (ctrl * 0x0010), ctrl); + nvkm_mask(device, 0x610200 + (ctrl * 0x0010), 0x00000010, 0x00000010); + nvkm_wr32(device, 0x640000 + (ctrl * 0x1000), chan->suspend_put); + nvkm_wr32(device, 0x610200 + (ctrl * 0x0010), 0x00000013); + + /* wait for it to go inactive */ + if (nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x610200 + (ctrl * 0x10)) & 0x80000000)) + break; + ) < 0) { + nvkm_error(subdev, "ch %d init timeout, %08x\n", user, + nvkm_rd32(device, 0x610200 + (ctrl * 0x10))); + return -EBUSY; } - ret = nvkm_gpuobj_new(device, 0x10000, 0x10000, false, NULL, - &disp->inst); + return 0; +} + +int +nv50_disp_dmac_new_(const struct nvkm_disp_chan_func *func, + const struct nvkm_disp_chan_mthd *mthd, + struct nvkm_disp *disp, int chid, int head, u64 push, + const struct nvkm_oclass *oclass, + struct nvkm_object **pobject) +{ + struct nvkm_client *client = oclass->client; + struct nvkm_disp_chan *chan; + int ret; + + ret = nvkm_disp_chan_new_(func, mthd, disp, chid, chid, head, oclass, + pobject); + chan = nvkm_disp_chan(*pobject); if (ret) return ret; - return nvkm_ramht_new(device, func->ramht_size ? func->ramht_size : - 0x1000, 0, disp->inst, &disp->ramht); + chan->memory = nvkm_umem_search(client, push); + if (IS_ERR(chan->memory)) + return PTR_ERR(chan->memory); + + if (nvkm_memory_size(chan->memory) < 0x1000) + return -EINVAL; + + switch (nvkm_memory_target(chan->memory)) { + case NVKM_MEM_TARGET_VRAM: chan->push = 0x00000001; break; + case NVKM_MEM_TARGET_NCOH: chan->push = 0x00000002; break; + case NVKM_MEM_TARGET_HOST: chan->push = 0x00000003; break; + default: + return -EINVAL; + } + + chan->push |= nvkm_memory_addr(chan->memory) >> 8; + return 0; } +const struct nvkm_disp_chan_func +nv50_disp_dmac_func = { + .init = nv50_disp_dmac_init, + .fini = nv50_disp_dmac_fini, + .intr = nv50_disp_chan_intr, + .user = nv50_disp_chan_user, + .bind = nv50_disp_dmac_bind, +}; + int -nv50_disp_new_(const struct nvkm_disp_func *func, struct nvkm_device *device, - enum nvkm_subdev_type type, int inst, struct nvkm_disp **pdisp) +nv50_disp_curs_new_(const struct nvkm_disp_chan_func *func, + struct nvkm_disp *disp, int ctrl, int user, + const struct nvkm_oclass *oclass, void *argv, u32 argc, + struct nvkm_object **pobject) { - struct nvkm_disp *disp; - int ret; + union { + struct nv50_disp_cursor_v0 v0; + } *args = argv; + struct nvkm_object *parent = oclass->parent; + int head, ret = -ENOSYS; + + nvif_ioctl(parent, "create disp cursor size %d\n", argc); + if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, false))) { + nvif_ioctl(parent, "create disp cursor vers %d head %d\n", + args->v0.version, args->v0.head); + if (!nvkm_head_find(disp, args->v0.head)) + return -EINVAL; + head = args->v0.head; + } else + return ret; - if (!(disp = kzalloc(sizeof(*disp), GFP_KERNEL))) - return -ENOMEM; - disp->func = func; - *pdisp = disp; + return nvkm_disp_chan_new_(func, NULL, disp, ctrl + head, user + head, + head, oclass, pobject); +} - ret = nvkm_disp_ctor(func, device, type, inst, disp); - if (ret) +int +nv50_disp_curs_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, + struct nvkm_disp *disp, struct nvkm_object **pobject) +{ + return nv50_disp_curs_new_(&nv50_disp_pioc_func, disp, 7, 7, + oclass, argv, argc, pobject); +} + +int +nv50_disp_oimm_new_(const struct nvkm_disp_chan_func *func, + struct nvkm_disp *disp, int ctrl, int user, + const struct nvkm_oclass *oclass, void *argv, u32 argc, + struct nvkm_object **pobject) +{ + union { + struct nv50_disp_overlay_v0 v0; + } *args = argv; + struct nvkm_object *parent = oclass->parent; + int head, ret = -ENOSYS; + + nvif_ioctl(parent, "create disp overlay size %d\n", argc); + if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, false))) { + nvif_ioctl(parent, "create disp overlay vers %d head %d\n", + args->v0.version, args->v0.head); + if (!nvkm_head_find(disp, args->v0.head)) + return -EINVAL; + head = args->v0.head; + } else return ret; - disp->wq = create_singlethread_workqueue("nvkm-disp"); - if (!disp->wq) - return -ENOMEM; + return nvkm_disp_chan_new_(func, NULL, disp, ctrl + head, user + head, + head, oclass, pobject); +} - INIT_WORK(&disp->supervisor, func->super); +int +nv50_disp_oimm_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, + struct nvkm_disp *disp, struct nvkm_object **pobject) +{ + return nv50_disp_oimm_new_(&nv50_disp_pioc_func, disp, 5, 5, + oclass, argv, argc, pobject); +} - return nvkm_event_init(func->uevent, 1, ARRAY_SIZE(disp->chan), - &disp->uevent); +int +nv50_disp_ovly_new_(const struct nvkm_disp_chan_func *func, + const struct nvkm_disp_chan_mthd *mthd, + struct nvkm_disp *disp, int chid, + const struct nvkm_oclass *oclass, void *argv, u32 argc, + struct nvkm_object **pobject) +{ + union { + struct nv50_disp_overlay_channel_dma_v0 v0; + } *args = argv; + struct nvkm_object *parent = oclass->parent; + int head, ret = -ENOSYS; + u64 push; + + nvif_ioctl(parent, "create disp overlay channel dma size %d\n", argc); + if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, false))) { + nvif_ioctl(parent, "create disp overlay channel dma vers %d " + "pushbuf %016llx head %d\n", + args->v0.version, args->v0.pushbuf, args->v0.head); + if (!nvkm_head_find(disp, args->v0.head)) + return -EINVAL; + push = args->v0.pushbuf; + head = args->v0.head; + } else + return ret; + + return nv50_disp_dmac_new_(func, mthd, disp, chid + head, + head, push, oclass, pobject); +} + +static const struct nvkm_disp_mthd_list +nv50_disp_ovly_mthd_base = { + .mthd = 0x0000, + .addr = 0x000000, + .data = { + { 0x0080, 0x000000 }, + { 0x0084, 0x0009a0 }, + { 0x0088, 0x0009c0 }, + { 0x008c, 0x0009c8 }, + { 0x0090, 0x6109b4 }, + { 0x0094, 0x610970 }, + { 0x00a0, 0x610998 }, + { 0x00a4, 0x610964 }, + { 0x00c0, 0x610958 }, + { 0x00e0, 0x6109a8 }, + { 0x00e4, 0x6109d0 }, + { 0x00e8, 0x6109d8 }, + { 0x0100, 0x61094c }, + { 0x0104, 0x610984 }, + { 0x0108, 0x61098c }, + { 0x0800, 0x6109f8 }, + { 0x0808, 0x610a08 }, + { 0x080c, 0x610a10 }, + { 0x0810, 0x610a00 }, + {} + } +}; + +static const struct nvkm_disp_chan_mthd +nv50_disp_ovly_mthd = { + .name = "Overlay", + .addr = 0x000540, + .prev = 0x000004, + .data = { + { "Global", 1, &nv50_disp_ovly_mthd_base }, + {} + } +}; + +int +nv50_disp_ovly_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, + struct nvkm_disp *disp, struct nvkm_object **pobject) +{ + return nv50_disp_ovly_new_(&nv50_disp_dmac_func, &nv50_disp_ovly_mthd, + disp, 3, oclass, argv, argc, pobject); +} + +int +nv50_disp_base_new_(const struct nvkm_disp_chan_func *func, + const struct nvkm_disp_chan_mthd *mthd, + struct nvkm_disp *disp, int chid, + const struct nvkm_oclass *oclass, void *argv, u32 argc, + struct nvkm_object **pobject) +{ + union { + struct nv50_disp_base_channel_dma_v0 v0; + } *args = argv; + struct nvkm_object *parent = oclass->parent; + int head, ret = -ENOSYS; + u64 push; + + nvif_ioctl(parent, "create disp base channel dma size %d\n", argc); + if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, false))) { + nvif_ioctl(parent, "create disp base channel dma vers %d " + "pushbuf %016llx head %d\n", + args->v0.version, args->v0.pushbuf, args->v0.head); + if (!nvkm_head_find(disp, args->v0.head)) + return -EINVAL; + push = args->v0.pushbuf; + head = args->v0.head; + } else + return ret; + + return nv50_disp_dmac_new_(func, mthd, disp, chid + head, + head, push, oclass, pobject); +} + +static const struct nvkm_disp_mthd_list +nv50_disp_base_mthd_base = { + .mthd = 0x0000, + .addr = 0x000000, + .data = { + { 0x0080, 0x000000 }, + { 0x0084, 0x0008c4 }, + { 0x0088, 0x0008d0 }, + { 0x008c, 0x0008dc }, + { 0x0090, 0x0008e4 }, + { 0x0094, 0x610884 }, + { 0x00a0, 0x6108a0 }, + { 0x00a4, 0x610878 }, + { 0x00c0, 0x61086c }, + { 0x00e0, 0x610858 }, + { 0x00e4, 0x610860 }, + { 0x00e8, 0x6108ac }, + { 0x00ec, 0x6108b4 }, + { 0x0100, 0x610894 }, + { 0x0110, 0x6108bc }, + { 0x0114, 0x61088c }, + {} + } +}; + +const struct nvkm_disp_mthd_list +nv50_disp_base_mthd_image = { + .mthd = 0x0400, + .addr = 0x000000, + .data = { + { 0x0800, 0x6108f0 }, + { 0x0804, 0x6108fc }, + { 0x0808, 0x61090c }, + { 0x080c, 0x610914 }, + { 0x0810, 0x610904 }, + {} + } +}; + +static const struct nvkm_disp_chan_mthd +nv50_disp_base_mthd = { + .name = "Base", + .addr = 0x000540, + .prev = 0x000004, + .data = { + { "Global", 1, &nv50_disp_base_mthd_base }, + { "Image", 2, &nv50_disp_base_mthd_image }, + {} + } +}; + +int +nv50_disp_base_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, + struct nvkm_disp *disp, struct nvkm_object **pobject) +{ + return nv50_disp_base_new_(&nv50_disp_dmac_func, &nv50_disp_base_mthd, + disp, 1, oclass, argv, argc, pobject); +} + +int +nv50_disp_core_new_(const struct nvkm_disp_chan_func *func, + const struct nvkm_disp_chan_mthd *mthd, + struct nvkm_disp *disp, int chid, + const struct nvkm_oclass *oclass, void *argv, u32 argc, + struct nvkm_object **pobject) +{ + union { + struct nv50_disp_core_channel_dma_v0 v0; + } *args = argv; + struct nvkm_object *parent = oclass->parent; + u64 push; + int ret = -ENOSYS; + + nvif_ioctl(parent, "create disp core channel dma size %d\n", argc); + if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, false))) { + nvif_ioctl(parent, "create disp core channel dma vers %d " + "pushbuf %016llx\n", + args->v0.version, args->v0.pushbuf); + push = args->v0.pushbuf; + } else + return ret; + + return nv50_disp_dmac_new_(func, mthd, disp, chid, 0, + push, oclass, pobject); +} + +const struct nvkm_disp_mthd_list +nv50_disp_core_mthd_base = { + .mthd = 0x0000, + .addr = 0x000000, + .data = { + { 0x0080, 0x000000 }, + { 0x0084, 0x610bb8 }, + { 0x0088, 0x610b9c }, + { 0x008c, 0x000000 }, + {} + } +}; + +static const struct nvkm_disp_mthd_list +nv50_disp_core_mthd_dac = { + .mthd = 0x0080, + .addr = 0x000008, + .data = { + { 0x0400, 0x610b58 }, + { 0x0404, 0x610bdc }, + { 0x0420, 0x610828 }, + {} + } +}; + +const struct nvkm_disp_mthd_list +nv50_disp_core_mthd_sor = { + .mthd = 0x0040, + .addr = 0x000008, + .data = { + { 0x0600, 0x610b70 }, + {} + } +}; + +const struct nvkm_disp_mthd_list +nv50_disp_core_mthd_pior = { + .mthd = 0x0040, + .addr = 0x000008, + .data = { + { 0x0700, 0x610b80 }, + {} + } +}; + +static const struct nvkm_disp_mthd_list +nv50_disp_core_mthd_head = { + .mthd = 0x0400, + .addr = 0x000540, + .data = { + { 0x0800, 0x610ad8 }, + { 0x0804, 0x610ad0 }, + { 0x0808, 0x610a48 }, + { 0x080c, 0x610a78 }, + { 0x0810, 0x610ac0 }, + { 0x0814, 0x610af8 }, + { 0x0818, 0x610b00 }, + { 0x081c, 0x610ae8 }, + { 0x0820, 0x610af0 }, + { 0x0824, 0x610b08 }, + { 0x0828, 0x610b10 }, + { 0x082c, 0x610a68 }, + { 0x0830, 0x610a60 }, + { 0x0834, 0x000000 }, + { 0x0838, 0x610a40 }, + { 0x0840, 0x610a24 }, + { 0x0844, 0x610a2c }, + { 0x0848, 0x610aa8 }, + { 0x084c, 0x610ab0 }, + { 0x0860, 0x610a84 }, + { 0x0864, 0x610a90 }, + { 0x0868, 0x610b18 }, + { 0x086c, 0x610b20 }, + { 0x0870, 0x610ac8 }, + { 0x0874, 0x610a38 }, + { 0x0880, 0x610a58 }, + { 0x0884, 0x610a9c }, + { 0x08a0, 0x610a70 }, + { 0x08a4, 0x610a50 }, + { 0x08a8, 0x610ae0 }, + { 0x08c0, 0x610b28 }, + { 0x08c4, 0x610b30 }, + { 0x08c8, 0x610b40 }, + { 0x08d4, 0x610b38 }, + { 0x08d8, 0x610b48 }, + { 0x08dc, 0x610b50 }, + { 0x0900, 0x610a18 }, + { 0x0904, 0x610ab8 }, + {} + } +}; + +static const struct nvkm_disp_chan_mthd +nv50_disp_core_mthd = { + .name = "Core", + .addr = 0x000000, + .prev = 0x000004, + .data = { + { "Global", 1, &nv50_disp_core_mthd_base }, + { "DAC", 3, &nv50_disp_core_mthd_dac }, + { "SOR", 2, &nv50_disp_core_mthd_sor }, + { "PIOR", 3, &nv50_disp_core_mthd_pior }, + { "HEAD", 2, &nv50_disp_core_mthd_head }, + {} + } +}; + +static void +nv50_disp_core_fini(struct nvkm_disp_chan *chan) +{ + struct nvkm_subdev *subdev = &chan->disp->engine.subdev; + struct nvkm_device *device = subdev->device; + + /* deactivate channel */ + nvkm_mask(device, 0x610200, 0x00000010, 0x00000000); + nvkm_mask(device, 0x610200, 0x00000003, 0x00000000); + if (nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x610200) & 0x001e0000)) + break; + ) < 0) { + nvkm_error(subdev, "core fini: %08x\n", + nvkm_rd32(device, 0x610200)); + } + + chan->suspend_put = nvkm_rd32(device, 0x640000); +} + +static int +nv50_disp_core_init(struct nvkm_disp_chan *chan) +{ + struct nvkm_subdev *subdev = &chan->disp->engine.subdev; + struct nvkm_device *device = subdev->device; + + /* attempt to unstick channel from some unknown state */ + if ((nvkm_rd32(device, 0x610200) & 0x009f0000) == 0x00020000) + nvkm_mask(device, 0x610200, 0x00800000, 0x00800000); + if ((nvkm_rd32(device, 0x610200) & 0x003f0000) == 0x00030000) + nvkm_mask(device, 0x610200, 0x00600000, 0x00600000); + + /* initialise channel for dma command submission */ + nvkm_wr32(device, 0x610204, chan->push); + nvkm_wr32(device, 0x610208, 0x00010000); + nvkm_wr32(device, 0x61020c, 0x00000000); + nvkm_mask(device, 0x610200, 0x00000010, 0x00000010); + nvkm_wr32(device, 0x640000, chan->suspend_put); + nvkm_wr32(device, 0x610200, 0x01000013); + + /* wait for it to go inactive */ + if (nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x610200) & 0x80000000)) + break; + ) < 0) { + nvkm_error(subdev, "core init: %08x\n", + nvkm_rd32(device, 0x610200)); + return -EBUSY; + } + + return 0; +} + +const struct nvkm_disp_chan_func +nv50_disp_core_func = { + .init = nv50_disp_core_init, + .fini = nv50_disp_core_fini, + .intr = nv50_disp_chan_intr, + .user = nv50_disp_chan_user, + .bind = nv50_disp_dmac_bind, +}; + +int +nv50_disp_core_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, + struct nvkm_disp *disp, struct nvkm_object **pobject) +{ + return nv50_disp_core_new_(&nv50_disp_core_func, &nv50_disp_core_mthd, + disp, 0, oclass, argv, argc, pobject); } static u32 @@ -715,10 +1731,80 @@ nv50_disp_init(struct nvkm_disp *disp) return 0; } +int +nv50_disp_oneinit(struct nvkm_disp *disp) +{ + const struct nvkm_disp_func *func = disp->func; + struct nvkm_subdev *subdev = &disp->engine.subdev; + struct nvkm_device *device = subdev->device; + int ret, i; + + if (func->wndw.cnt) { + disp->wndw.nr = func->wndw.cnt(disp, &disp->wndw.mask); + nvkm_debug(subdev, "Window(s): %d (%08lx)\n", disp->wndw.nr, disp->wndw.mask); + } + + disp->head.nr = func->head.cnt(disp, &disp->head.mask); + nvkm_debug(subdev, " Head(s): %d (%02lx)\n", disp->head.nr, disp->head.mask); + for_each_set_bit(i, &disp->head.mask, disp->head.nr) { + ret = func->head.new(disp, i); + if (ret) + return ret; + } + + if (func->dac.cnt) { + disp->dac.nr = func->dac.cnt(disp, &disp->dac.mask); + nvkm_debug(subdev, " DAC(s): %d (%02lx)\n", disp->dac.nr, disp->dac.mask); + for_each_set_bit(i, &disp->dac.mask, disp->dac.nr) { + ret = func->dac.new(disp, i); + if (ret) + return ret; + } + } + + if (func->pior.cnt) { + disp->pior.nr = func->pior.cnt(disp, &disp->pior.mask); + nvkm_debug(subdev, " PIOR(s): %d (%02lx)\n", disp->pior.nr, disp->pior.mask); + for_each_set_bit(i, &disp->pior.mask, disp->pior.nr) { + ret = func->pior.new(disp, i); + if (ret) + return ret; + } + } + + disp->sor.nr = func->sor.cnt(disp, &disp->sor.mask); + nvkm_debug(subdev, " SOR(s): %d (%02lx)\n", disp->sor.nr, disp->sor.mask); + for_each_set_bit(i, &disp->sor.mask, disp->sor.nr) { + ret = func->sor.new(disp, i); + if (ret) + return ret; + } + + ret = nvkm_gpuobj_new(device, 0x10000, 0x10000, false, NULL, &disp->inst); + if (ret) + return ret; + + return nvkm_ramht_new(device, func->ramht_size ? func->ramht_size : + 0x1000, 0, disp->inst, &disp->ramht); +} + +void * +nv50_disp_dtor(struct nvkm_disp *disp) +{ + nvkm_ramht_del(&disp->ramht); + nvkm_gpuobj_del(&disp->inst); + + nvkm_event_fini(&disp->uevent); + if (disp->wq) + destroy_workqueue(disp->wq); + + return disp; +} + static const struct nvkm_disp_func nv50_disp = { - .dtor = nv50_disp_dtor_, - .oneinit = nv50_disp_oneinit_, + .dtor = nv50_disp_dtor, + .oneinit = nv50_disp_oneinit, .init = nv50_disp_init, .fini = nv50_disp_fini, .intr = nv50_disp_intr, @@ -740,6 +1826,32 @@ nv50_disp = { }; int +nv50_disp_new_(const struct nvkm_disp_func *func, struct nvkm_device *device, + enum nvkm_subdev_type type, int inst, struct nvkm_disp **pdisp) +{ + struct nvkm_disp *disp; + int ret; + + if (!(disp = kzalloc(sizeof(*disp), GFP_KERNEL))) + return -ENOMEM; + disp->func = func; + *pdisp = disp; + + ret = nvkm_disp_ctor(func, device, type, inst, disp); + if (ret) + return ret; + + disp->wq = create_singlethread_workqueue("nvkm-disp"); + if (!disp->wq) + return -ENOMEM; + + INIT_WORK(&disp->supervisor, func->super); + + return nvkm_event_init(func->uevent, 1, ARRAY_SIZE(disp->chan), + &disp->uevent); +} + +int nv50_disp_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_disp **pdisp) { diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgf119.c deleted file mode 100644 index 1f87ce852ce3..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgf119.c +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2012 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. - * - * Authors: Ben Skeggs - */ -#include "channv50.h" - -int -gf119_disp_oimm_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nvkm_disp *disp, struct nvkm_object **pobject) -{ - return nv50_disp_oimm_new_(&gf119_disp_pioc_func, disp, 9, 9, - oclass, argv, argc, pobject); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgp102.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgp102.c deleted file mode 100644 index 0edb37b529da..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgp102.c +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2016 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. - * - * Authors: Ben Skeggs <bskeggs@redhat.com> - */ -#include "channv50.h" - -int -gp102_disp_oimm_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nvkm_disp *disp, struct nvkm_object **pobject) -{ - return nv50_disp_oimm_new_(&gf119_disp_pioc_func, disp, 9, 13, - oclass, argv, argc, pobject); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmnv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmnv50.c deleted file mode 100644 index 26a44a3f71a4..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmnv50.c +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright 2012 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. - * - * Authors: Ben Skeggs - */ -#include "channv50.h" -#include "head.h" - -#include <core/client.h> - -#include <nvif/cl507b.h> -#include <nvif/unpack.h> - -int -nv50_disp_oimm_new_(const struct nv50_disp_chan_func *func, - struct nvkm_disp *disp, int ctrl, int user, - const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nvkm_object **pobject) -{ - union { - struct nv50_disp_overlay_v0 v0; - } *args = argv; - struct nvkm_object *parent = oclass->parent; - int head, ret = -ENOSYS; - - nvif_ioctl(parent, "create disp overlay size %d\n", argc); - if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, false))) { - nvif_ioctl(parent, "create disp overlay vers %d head %d\n", - args->v0.version, args->v0.head); - if (!nvkm_head_find(disp, args->v0.head)) - return -EINVAL; - head = args->v0.head; - } else - return ret; - - return nv50_disp_chan_new_(func, NULL, disp, ctrl + head, user + head, - head, oclass, pobject); -} - -int -nv50_disp_oimm_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nvkm_disp *disp, struct nvkm_object **pobject) -{ - return nv50_disp_oimm_new_(&nv50_disp_pioc_func, disp, 5, 5, - oclass, argv, argc, pobject); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlyg84.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlyg84.c deleted file mode 100644 index dad648a26ba6..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlyg84.c +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright 2012 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. - * - * Authors: Ben Skeggs - */ -#include "channv50.h" - -static const struct nv50_disp_mthd_list -g84_disp_ovly_mthd_base = { - .mthd = 0x0000, - .addr = 0x000000, - .data = { - { 0x0080, 0x000000 }, - { 0x0084, 0x6109a0 }, - { 0x0088, 0x6109c0 }, - { 0x008c, 0x6109c8 }, - { 0x0090, 0x6109b4 }, - { 0x0094, 0x610970 }, - { 0x00a0, 0x610998 }, - { 0x00a4, 0x610964 }, - { 0x00c0, 0x610958 }, - { 0x00e0, 0x6109a8 }, - { 0x00e4, 0x6109d0 }, - { 0x00e8, 0x6109d8 }, - { 0x0100, 0x61094c }, - { 0x0104, 0x610984 }, - { 0x0108, 0x61098c }, - { 0x0800, 0x6109f8 }, - { 0x0808, 0x610a08 }, - { 0x080c, 0x610a10 }, - { 0x0810, 0x610a00 }, - {} - } -}; - -static const struct nv50_disp_chan_mthd -g84_disp_ovly_mthd = { - .name = "Overlay", - .addr = 0x000540, - .prev = 0x000004, - .data = { - { "Global", 1, &g84_disp_ovly_mthd_base }, - {} - } -}; - -int -g84_disp_ovly_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nvkm_disp *disp, struct nvkm_object **pobject) -{ - return nv50_disp_ovly_new_(&nv50_disp_dmac_func, &g84_disp_ovly_mthd, - disp, 3, oclass, argv, argc, pobject); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygf119.c deleted file mode 100644 index eb0cb60ba75c..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygf119.c +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright 2012 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. - * - * Authors: Ben Skeggs - */ -#include "channv50.h" - -static const struct nv50_disp_mthd_list -gf119_disp_ovly_mthd_base = { - .mthd = 0x0000, - .data = { - { 0x0080, 0x665080 }, - { 0x0084, 0x665084 }, - { 0x0088, 0x665088 }, - { 0x008c, 0x66508c }, - { 0x0090, 0x665090 }, - { 0x0094, 0x665094 }, - { 0x00a0, 0x6650a0 }, - { 0x00a4, 0x6650a4 }, - { 0x00b0, 0x6650b0 }, - { 0x00b4, 0x6650b4 }, - { 0x00b8, 0x6650b8 }, - { 0x00c0, 0x6650c0 }, - { 0x00e0, 0x6650e0 }, - { 0x00e4, 0x6650e4 }, - { 0x00e8, 0x6650e8 }, - { 0x0100, 0x665100 }, - { 0x0104, 0x665104 }, - { 0x0108, 0x665108 }, - { 0x010c, 0x66510c }, - { 0x0110, 0x665110 }, - { 0x0118, 0x665118 }, - { 0x011c, 0x66511c }, - { 0x0120, 0x665120 }, - { 0x0124, 0x665124 }, - { 0x0130, 0x665130 }, - { 0x0134, 0x665134 }, - { 0x0138, 0x665138 }, - { 0x013c, 0x66513c }, - { 0x0140, 0x665140 }, - { 0x0144, 0x665144 }, - { 0x0148, 0x665148 }, - { 0x014c, 0x66514c }, - { 0x0150, 0x665150 }, - { 0x0154, 0x665154 }, - { 0x0158, 0x665158 }, - { 0x015c, 0x66515c }, - { 0x0160, 0x665160 }, - { 0x0164, 0x665164 }, - { 0x0168, 0x665168 }, - { 0x016c, 0x66516c }, - { 0x0400, 0x665400 }, - { 0x0408, 0x665408 }, - { 0x040c, 0x66540c }, - { 0x0410, 0x665410 }, - {} - } -}; - -static const struct nv50_disp_chan_mthd -gf119_disp_ovly_mthd = { - .name = "Overlay", - .addr = 0x001000, - .prev = -0x020000, - .data = { - { "Global", 1, &gf119_disp_ovly_mthd_base }, - {} - } -}; - -int -gf119_disp_ovly_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nvkm_disp *disp, struct nvkm_object **pobject) -{ - return nv50_disp_ovly_new_(&gf119_disp_dmac_func, &gf119_disp_ovly_mthd, - disp, 5, oclass, argv, argc, pobject); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygk104.c deleted file mode 100644 index 24ca2ca6fda1..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygk104.c +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright 2012 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. - * - * Authors: Ben Skeggs - */ -#include "channv50.h" - -static const struct nv50_disp_mthd_list -gk104_disp_ovly_mthd_base = { - .mthd = 0x0000, - .data = { - { 0x0080, 0x665080 }, - { 0x0084, 0x665084 }, - { 0x0088, 0x665088 }, - { 0x008c, 0x66508c }, - { 0x0090, 0x665090 }, - { 0x0094, 0x665094 }, - { 0x00a0, 0x6650a0 }, - { 0x00a4, 0x6650a4 }, - { 0x00b0, 0x6650b0 }, - { 0x00b4, 0x6650b4 }, - { 0x00b8, 0x6650b8 }, - { 0x00c0, 0x6650c0 }, - { 0x00c4, 0x6650c4 }, - { 0x00e0, 0x6650e0 }, - { 0x00e4, 0x6650e4 }, - { 0x00e8, 0x6650e8 }, - { 0x0100, 0x665100 }, - { 0x0104, 0x665104 }, - { 0x0108, 0x665108 }, - { 0x010c, 0x66510c }, - { 0x0110, 0x665110 }, - { 0x0118, 0x665118 }, - { 0x011c, 0x66511c }, - { 0x0120, 0x665120 }, - { 0x0124, 0x665124 }, - { 0x0130, 0x665130 }, - { 0x0134, 0x665134 }, - { 0x0138, 0x665138 }, - { 0x013c, 0x66513c }, - { 0x0140, 0x665140 }, - { 0x0144, 0x665144 }, - { 0x0148, 0x665148 }, - { 0x014c, 0x66514c }, - { 0x0150, 0x665150 }, - { 0x0154, 0x665154 }, - { 0x0158, 0x665158 }, - { 0x015c, 0x66515c }, - { 0x0160, 0x665160 }, - { 0x0164, 0x665164 }, - { 0x0168, 0x665168 }, - { 0x016c, 0x66516c }, - { 0x0400, 0x665400 }, - { 0x0404, 0x665404 }, - { 0x0408, 0x665408 }, - { 0x040c, 0x66540c }, - { 0x0410, 0x665410 }, - {} - } -}; - -const struct nv50_disp_chan_mthd -gk104_disp_ovly_mthd = { - .name = "Overlay", - .addr = 0x001000, - .prev = -0x020000, - .data = { - { "Global", 1, &gk104_disp_ovly_mthd_base }, - {} - } -}; - -int -gk104_disp_ovly_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nvkm_disp *disp, struct nvkm_object **pobject) -{ - return nv50_disp_ovly_new_(&gf119_disp_dmac_func, &gk104_disp_ovly_mthd, - disp, 5, oclass, argv, argc, pobject); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygp102.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygp102.c deleted file mode 100644 index 3eff5c5ab3bf..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygp102.c +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2012 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. - * - * Authors: Ben Skeggs - */ -#include "channv50.h" - -int -gp102_disp_ovly_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nvkm_disp *disp, struct nvkm_object **pobject) -{ - return nv50_disp_ovly_new_(&gp102_disp_dmac_func, &gk104_disp_ovly_mthd, - disp, 5, oclass, argv, argc, pobject); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygt200.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygt200.c deleted file mode 100644 index 68afb9dc578a..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygt200.c +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright 2012 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. - * - * Authors: Ben Skeggs - */ -#include "channv50.h" - -static const struct nv50_disp_mthd_list -gt200_disp_ovly_mthd_base = { - .mthd = 0x0000, - .addr = 0x000000, - .data = { - { 0x0080, 0x000000 }, - { 0x0084, 0x6109a0 }, - { 0x0088, 0x6109c0 }, - { 0x008c, 0x6109c8 }, - { 0x0090, 0x6109b4 }, - { 0x0094, 0x610970 }, - { 0x00a0, 0x610998 }, - { 0x00a4, 0x610964 }, - { 0x00b0, 0x610c98 }, - { 0x00b4, 0x610ca4 }, - { 0x00b8, 0x610cac }, - { 0x00c0, 0x610958 }, - { 0x00e0, 0x6109a8 }, - { 0x00e4, 0x6109d0 }, - { 0x00e8, 0x6109d8 }, - { 0x0100, 0x61094c }, - { 0x0104, 0x610984 }, - { 0x0108, 0x61098c }, - { 0x0800, 0x6109f8 }, - { 0x0808, 0x610a08 }, - { 0x080c, 0x610a10 }, - { 0x0810, 0x610a00 }, - {} - } -}; - -static const struct nv50_disp_chan_mthd -gt200_disp_ovly_mthd = { - .name = "Overlay", - .addr = 0x000540, - .prev = 0x000004, - .data = { - { "Global", 1, >200_disp_ovly_mthd_base }, - {} - } -}; - -int -gt200_disp_ovly_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nvkm_disp *disp, struct nvkm_object **pobject) -{ - return nv50_disp_ovly_new_(&nv50_disp_dmac_func, >200_disp_ovly_mthd, - disp, 3, oclass, argv, argc, pobject); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlynv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlynv50.c deleted file mode 100644 index 42be34b45da4..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlynv50.c +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright 2012 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. - * - * Authors: Ben Skeggs - */ -#include "channv50.h" -#include "head.h" - -#include <core/client.h> - -#include <nvif/cl507e.h> -#include <nvif/unpack.h> - -int -nv50_disp_ovly_new_(const struct nv50_disp_chan_func *func, - const struct nv50_disp_chan_mthd *mthd, - struct nvkm_disp *disp, int chid, - const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nvkm_object **pobject) -{ - union { - struct nv50_disp_overlay_channel_dma_v0 v0; - } *args = argv; - struct nvkm_object *parent = oclass->parent; - int head, ret = -ENOSYS; - u64 push; - - nvif_ioctl(parent, "create disp overlay channel dma size %d\n", argc); - if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, false))) { - nvif_ioctl(parent, "create disp overlay channel dma vers %d " - "pushbuf %016llx head %d\n", - args->v0.version, args->v0.pushbuf, args->v0.head); - if (!nvkm_head_find(disp, args->v0.head)) - return -EINVAL; - push = args->v0.pushbuf; - head = args->v0.head; - } else - return ret; - - return nv50_disp_dmac_new_(func, mthd, disp, chid + head, - head, push, oclass, pobject); -} - -static const struct nv50_disp_mthd_list -nv50_disp_ovly_mthd_base = { - .mthd = 0x0000, - .addr = 0x000000, - .data = { - { 0x0080, 0x000000 }, - { 0x0084, 0x0009a0 }, - { 0x0088, 0x0009c0 }, - { 0x008c, 0x0009c8 }, - { 0x0090, 0x6109b4 }, - { 0x0094, 0x610970 }, - { 0x00a0, 0x610998 }, - { 0x00a4, 0x610964 }, - { 0x00c0, 0x610958 }, - { 0x00e0, 0x6109a8 }, - { 0x00e4, 0x6109d0 }, - { 0x00e8, 0x6109d8 }, - { 0x0100, 0x61094c }, - { 0x0104, 0x610984 }, - { 0x0108, 0x61098c }, - { 0x0800, 0x6109f8 }, - { 0x0808, 0x610a08 }, - { 0x080c, 0x610a10 }, - { 0x0810, 0x610a00 }, - {} - } -}; - -static const struct nv50_disp_chan_mthd -nv50_disp_ovly_mthd = { - .name = "Overlay", - .addr = 0x000540, - .prev = 0x000004, - .data = { - { "Global", 1, &nv50_disp_ovly_mthd_base }, - {} - } -}; - -int -nv50_disp_ovly_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nvkm_disp *disp, struct nvkm_object **pobject) -{ - return nv50_disp_ovly_new_(&nv50_disp_dmac_func, &nv50_disp_ovly_mthd, - disp, 3, oclass, argv, argc, pobject); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/piocgf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/piocgf119.c deleted file mode 100644 index e562930264e2..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/piocgf119.c +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright 2012 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. - * - * Authors: Ben Skeggs - */ -#include "channv50.h" - -#include <subdev/timer.h> - -static void -gf119_disp_pioc_fini(struct nv50_disp_chan *chan) -{ - struct nvkm_disp *disp = chan->disp; - struct nvkm_subdev *subdev = &disp->engine.subdev; - struct nvkm_device *device = subdev->device; - int ctrl = chan->chid.ctrl; - int user = chan->chid.user; - - nvkm_mask(device, 0x610490 + (ctrl * 0x10), 0x00000001, 0x00000000); - if (nvkm_msec(device, 2000, - if (!(nvkm_rd32(device, 0x610490 + (ctrl * 0x10)) & 0x00030000)) - break; - ) < 0) { - nvkm_error(subdev, "ch %d fini: %08x\n", user, - nvkm_rd32(device, 0x610490 + (ctrl * 0x10))); - } -} - -static int -gf119_disp_pioc_init(struct nv50_disp_chan *chan) -{ - struct nvkm_disp *disp = chan->disp; - struct nvkm_subdev *subdev = &disp->engine.subdev; - struct nvkm_device *device = subdev->device; - int ctrl = chan->chid.ctrl; - int user = chan->chid.user; - - /* activate channel */ - nvkm_wr32(device, 0x610490 + (ctrl * 0x10), 0x00000001); - if (nvkm_msec(device, 2000, - u32 tmp = nvkm_rd32(device, 0x610490 + (ctrl * 0x10)); - if ((tmp & 0x00030000) == 0x00010000) - break; - ) < 0) { - nvkm_error(subdev, "ch %d init: %08x\n", user, - nvkm_rd32(device, 0x610490 + (ctrl * 0x10))); - return -EBUSY; - } - - return 0; -} - -const struct nv50_disp_chan_func -gf119_disp_pioc_func = { - .init = gf119_disp_pioc_init, - .fini = gf119_disp_pioc_fini, - .intr = gf119_disp_chan_intr, - .user = nv50_disp_chan_user, -}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/piocnv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/piocnv50.c deleted file mode 100644 index 8190134f258b..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/piocnv50.c +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright 2012 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. - * - * Authors: Ben Skeggs - */ -#include "channv50.h" - -#include <subdev/timer.h> - -static void -nv50_disp_pioc_fini(struct nv50_disp_chan *chan) -{ - struct nvkm_disp *disp = chan->disp; - struct nvkm_subdev *subdev = &disp->engine.subdev; - struct nvkm_device *device = subdev->device; - int ctrl = chan->chid.ctrl; - int user = chan->chid.user; - - nvkm_mask(device, 0x610200 + (ctrl * 0x10), 0x00000001, 0x00000000); - if (nvkm_msec(device, 2000, - if (!(nvkm_rd32(device, 0x610200 + (ctrl * 0x10)) & 0x00030000)) - break; - ) < 0) { - nvkm_error(subdev, "ch %d timeout: %08x\n", user, - nvkm_rd32(device, 0x610200 + (ctrl * 0x10))); - } -} - -static int -nv50_disp_pioc_init(struct nv50_disp_chan *chan) -{ - struct nvkm_disp *disp = chan->disp; - struct nvkm_subdev *subdev = &disp->engine.subdev; - struct nvkm_device *device = subdev->device; - int ctrl = chan->chid.ctrl; - int user = chan->chid.user; - - nvkm_wr32(device, 0x610200 + (ctrl * 0x10), 0x00002000); - if (nvkm_msec(device, 2000, - if (!(nvkm_rd32(device, 0x610200 + (ctrl * 0x10)) & 0x00030000)) - break; - ) < 0) { - nvkm_error(subdev, "ch %d timeout0: %08x\n", user, - nvkm_rd32(device, 0x610200 + (ctrl * 0x10))); - return -EBUSY; - } - - nvkm_wr32(device, 0x610200 + (ctrl * 0x10), 0x00000001); - if (nvkm_msec(device, 2000, - u32 tmp = nvkm_rd32(device, 0x610200 + (ctrl * 0x10)); - if ((tmp & 0x00030000) == 0x00010000) - break; - ) < 0) { - nvkm_error(subdev, "ch %d timeout1: %08x\n", user, - nvkm_rd32(device, 0x610200 + (ctrl * 0x10))); - return -EBUSY; - } - - return 0; -} - -const struct nv50_disp_chan_func -nv50_disp_pioc_func = { - .init = nv50_disp_pioc_init, - .fini = nv50_disp_pioc_fini, - .intr = nv50_disp_chan_intr, - .user = nv50_disp_chan_user, -}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/piornv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/piornv50.c deleted file mode 100644 index e997a207f546..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/piornv50.c +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright 2012 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. - * - * Authors: Ben Skeggs - */ -#include "ior.h" -#include "head.h" - -#include <subdev/i2c.h> -#include <subdev/timer.h> - -static void -nv50_pior_clock(struct nvkm_ior *pior) -{ - struct nvkm_device *device = pior->disp->engine.subdev.device; - const u32 poff = nv50_ior_base(pior); - nvkm_mask(device, 0x614380 + poff, 0x00000707, 0x00000001); -} - -static int -nv50_pior_dp_links(struct nvkm_ior *pior, struct nvkm_i2c_aux *aux) -{ - int ret = nvkm_i2c_aux_lnk_ctl(aux, pior->dp.nr, pior->dp.bw, - pior->dp.ef); - if (ret) - return ret; - return 1; -} - -static void -nv50_pior_power_wait(struct nvkm_device *device, u32 poff) -{ - nvkm_msec(device, 2000, - if (!(nvkm_rd32(device, 0x61e004 + poff) & 0x80000000)) - break; - ); -} - -static void -nv50_pior_power(struct nvkm_ior *pior, bool normal, bool pu, - bool data, bool vsync, bool hsync) -{ - struct nvkm_device *device = pior->disp->engine.subdev.device; - const u32 poff = nv50_ior_base(pior); - const u32 shift = normal ? 0 : 16; - const u32 state = 0x80000000 | (0x00000001 * !!pu) << shift; - const u32 field = 0x80000000 | (0x00000101 << shift); - - nv50_pior_power_wait(device, poff); - nvkm_mask(device, 0x61e004 + poff, field, state); - nv50_pior_power_wait(device, poff); -} - -void -nv50_pior_depth(struct nvkm_ior *ior, struct nvkm_ior_state *state, u32 ctrl) -{ - /* GF119 moves this information to per-head methods, which is - * a lot more convenient, and where our shared code expect it. - */ - if (state->head && state == &ior->asy) { - struct nvkm_head *head = - nvkm_head_find(ior->disp, __ffs(state->head)); - if (!WARN_ON(!head)) { - struct nvkm_head_state *state = &head->asy; - switch ((ctrl & 0x000f0000) >> 16) { - case 6: state->or.depth = 30; break; - case 5: state->or.depth = 24; break; - case 2: state->or.depth = 18; break; - case 0: state->or.depth = 18; break; /*XXX*/ - default: - state->or.depth = 18; - WARN_ON(1); - break; - } - } - } -} - -static void -nv50_pior_state(struct nvkm_ior *pior, struct nvkm_ior_state *state) -{ - struct nvkm_device *device = pior->disp->engine.subdev.device; - const u32 coff = pior->id * 8 + (state == &pior->arm) * 4; - u32 ctrl = nvkm_rd32(device, 0x610b80 + coff); - - state->proto_evo = (ctrl & 0x00000f00) >> 8; - state->rgdiv = 1; - switch (state->proto_evo) { - case 0: state->proto = TMDS; break; - default: - state->proto = UNKNOWN; - break; - } - - state->head = ctrl & 0x00000003; - nv50_pior_depth(pior, state, ctrl); -} - -static const struct nvkm_ior_func -nv50_pior = { - .state = nv50_pior_state, - .power = nv50_pior_power, - .clock = nv50_pior_clock, - .dp = { - .links = nv50_pior_dp_links, - }, -}; - -int -nv50_pior_new(struct nvkm_disp *disp, int id) -{ - return nvkm_ior_new_(&nv50_pior, disp, PIOR, id); -} - -int -nv50_pior_cnt(struct nvkm_disp *disp, unsigned long *pmask) -{ - struct nvkm_device *device = disp->engine.subdev.device; - *pmask = (nvkm_rd32(device, 0x610184) & 0x70000000) >> 28; - return 3; -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/priv.h index c63c067319f5..472ff32d7879 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/priv.h @@ -46,27 +46,21 @@ int nvkm_disp_ntfy(struct nvkm_object *, u32, struct nvkm_event **); int nv04_disp_mthd(struct nvkm_object *, u32, void *, u32); int nv50_disp_root_mthd_(struct nvkm_object *, u32, void *, u32); -void *nv50_disp_dtor_(struct nvkm_disp *); -int nv50_disp_oneinit_(struct nvkm_disp *); -int nv50_disp_init_(struct nvkm_disp *); -void nv50_disp_fini_(struct nvkm_disp *); -void nv50_disp_intr_(struct nvkm_disp *); - -void nv50_disp_super_1(struct nvkm_disp *); -void nv50_disp_super_1_0(struct nvkm_disp *, struct nvkm_head *); -void nv50_disp_super_2_0(struct nvkm_disp *, struct nvkm_head *); -void nv50_disp_super_2_1(struct nvkm_disp *, struct nvkm_head *); -void nv50_disp_super_2_2(struct nvkm_disp *, struct nvkm_head *); -void nv50_disp_super_3_0(struct nvkm_disp *, struct nvkm_head *); - int nv50_disp_new_(const struct nvkm_disp_func *, struct nvkm_device *, enum nvkm_subdev_type, int, struct nvkm_disp **); - +void *nv50_disp_dtor(struct nvkm_disp *); +int nv50_disp_oneinit(struct nvkm_disp *); int nv50_disp_init(struct nvkm_disp *); void nv50_disp_fini(struct nvkm_disp *); void nv50_disp_intr(struct nvkm_disp *); -void nv50_disp_super(struct work_struct *); extern const struct nvkm_enum nv50_disp_intr_error_type[]; +void nv50_disp_super(struct work_struct *); +void nv50_disp_super_1(struct nvkm_disp *); +void nv50_disp_super_1_0(struct nvkm_disp *, struct nvkm_head *); +void nv50_disp_super_2_0(struct nvkm_disp *, struct nvkm_head *); +void nv50_disp_super_2_1(struct nvkm_disp *, struct nvkm_head *); +void nv50_disp_super_2_2(struct nvkm_disp *, struct nvkm_head *); +void nv50_disp_super_3_0(struct nvkm_disp *, struct nvkm_head *); int gf119_disp_init(struct nvkm_disp *); void gf119_disp_fini(struct nvkm_disp *); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c index 8821bf128685..9d231b07f752 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c @@ -21,7 +21,7 @@ * * Authors: Ben Skeggs */ -#include "channv50.h" +#include "chan.h" #include "head.h" #include "ior.h" #include "outp.h" diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorg84.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorg84.c deleted file mode 100644 index ec3a7db08118..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorg84.c +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2017 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" - -static const struct nvkm_ior_func -g84_sor = { - .state = nv50_sor_state, - .power = nv50_sor_power, - .clock = nv50_sor_clock, - .hdmi = { - .ctrl = g84_hdmi_ctrl, - }, -}; - -int -g84_sor_new(struct nvkm_disp *disp, int id) -{ - return nvkm_ior_new_(&g84_sor, disp, SOR, id); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorg94.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorg94.c deleted file mode 100644 index 43a824f2bc4a..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorg94.c +++ /dev/null @@ -1,302 +0,0 @@ -/* - * Copyright 2012 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. - * - * Authors: Ben Skeggs - */ -#include "ior.h" - -#include <subdev/timer.h> - -void -g94_sor_dp_watermark(struct nvkm_ior *sor, int head, u8 watermark) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - const u32 loff = nv50_sor_link(sor); - nvkm_mask(device, 0x61c128 + loff, 0x0000003f, watermark); -} - -void -g94_sor_dp_activesym(struct nvkm_ior *sor, int head, - u8 TU, u8 VTUa, u8 VTUf, u8 VTUi) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - const u32 loff = nv50_sor_link(sor); - nvkm_mask(device, 0x61c10c + loff, 0x000001fc, TU << 2); - nvkm_mask(device, 0x61c128 + loff, 0x010f7f00, VTUa << 24 | - VTUf << 16 | - VTUi << 8); -} - -void -g94_sor_dp_audio_sym(struct nvkm_ior *sor, int head, u16 h, u32 v) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - const u32 soff = nv50_ior_base(sor); - nvkm_mask(device, 0x61c1e8 + soff, 0x0000ffff, h); - nvkm_mask(device, 0x61c1ec + soff, 0x00ffffff, v); -} - -void -g94_sor_dp_drive(struct nvkm_ior *sor, int ln, int pc, int dc, int pe, int pu) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - const u32 loff = nv50_sor_link(sor); - const u32 shift = sor->func->dp.lanes[ln] * 8; - u32 data[3]; - - data[0] = nvkm_rd32(device, 0x61c118 + loff) & ~(0x000000ff << shift); - data[1] = nvkm_rd32(device, 0x61c120 + loff) & ~(0x000000ff << shift); - data[2] = nvkm_rd32(device, 0x61c130 + loff); - if ((data[2] & 0x0000ff00) < (pu << 8) || ln == 0) - data[2] = (data[2] & ~0x0000ff00) | (pu << 8); - nvkm_wr32(device, 0x61c118 + loff, data[0] | (dc << shift)); - nvkm_wr32(device, 0x61c120 + loff, data[1] | (pe << shift)); - nvkm_wr32(device, 0x61c130 + loff, data[2]); -} - -void -g94_sor_dp_pattern(struct nvkm_ior *sor, int pattern) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - const u32 loff = nv50_sor_link(sor); - u32 data; - - switch (pattern) { - case 0: data = 0x00001000; break; - case 1: data = 0x01000000; break; - case 2: data = 0x02000000; break; - default: - WARN_ON(1); - return; - } - - nvkm_mask(device, 0x61c10c + loff, 0x0f001000, data); -} - -void -g94_sor_dp_power(struct nvkm_ior *sor, int nr) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - const u32 soff = nv50_ior_base(sor); - const u32 loff = nv50_sor_link(sor); - u32 mask = 0, i; - - for (i = 0; i < nr; i++) - mask |= 1 << sor->func->dp.lanes[i]; - - nvkm_mask(device, 0x61c130 + loff, 0x0000000f, mask); - nvkm_mask(device, 0x61c034 + soff, 0x80000000, 0x80000000); - nvkm_msec(device, 2000, - if (!(nvkm_rd32(device, 0x61c034 + soff) & 0x80000000)) - break; - ); -} - -int -g94_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; - - dpctrl |= ((1 << sor->dp.nr) - 1) << 16; - if (sor->dp.ef) - dpctrl |= 0x00004000; - if (sor->dp.bw > 0x06) - clksor |= 0x00040000; - - nvkm_mask(device, 0x614300 + soff, 0x000c0000, clksor); - nvkm_mask(device, 0x61c10c + loff, 0x001f4000, dpctrl); - return 0; -} - -static bool -g94_sor_war_needed(struct nvkm_ior *sor) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - const u32 soff = nv50_ior_base(sor); - if (sor->asy.proto == TMDS) { - switch (nvkm_rd32(device, 0x614300 + soff) & 0x00030000) { - case 0x00000000: - case 0x00030000: - return true; - default: - break; - } - } - return false; -} - -static void -g94_sor_war_update_sppll1(struct nvkm_disp *disp) -{ - struct nvkm_device *device = disp->engine.subdev.device; - struct nvkm_ior *ior; - bool used = false; - u32 clksor; - - list_for_each_entry(ior, &disp->iors, head) { - if (ior->type != SOR) - continue; - - clksor = nvkm_rd32(device, 0x614300 + nv50_ior_base(ior)); - switch (clksor & 0x03000000) { - case 0x02000000: - case 0x03000000: - used = true; - break; - default: - break; - } - } - - if (used) - return; - - nvkm_mask(device, 0x00e840, 0x80000000, 0x00000000); -} - -static void -g94_sor_war_3(struct nvkm_ior *sor) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - const u32 soff = nv50_ior_base(sor); - u32 sorpwr; - - if (!g94_sor_war_needed(sor)) - return; - - sorpwr = nvkm_rd32(device, 0x61c004 + soff); - if (sorpwr & 0x00000001) { - u32 seqctl = nvkm_rd32(device, 0x61c030 + soff); - u32 pd_pc = (seqctl & 0x00000f00) >> 8; - u32 pu_pc = seqctl & 0x0000000f; - - nvkm_wr32(device, 0x61c040 + soff + pd_pc * 4, 0x1f008000); - - nvkm_msec(device, 2000, - if (!(nvkm_rd32(device, 0x61c030 + soff) & 0x10000000)) - break; - ); - nvkm_mask(device, 0x61c004 + soff, 0x80000001, 0x80000000); - nvkm_msec(device, 2000, - if (!(nvkm_rd32(device, 0x61c030 + soff) & 0x10000000)) - break; - ); - - nvkm_wr32(device, 0x61c040 + soff + pd_pc * 4, 0x00002000); - nvkm_wr32(device, 0x61c040 + soff + pu_pc * 4, 0x1f000000); - } - - nvkm_mask(device, 0x61c10c + soff, 0x00000001, 0x00000000); - nvkm_mask(device, 0x614300 + soff, 0x03000000, 0x00000000); - - if (sorpwr & 0x00000001) { - nvkm_mask(device, 0x61c004 + soff, 0x80000001, 0x80000001); - } - - g94_sor_war_update_sppll1(sor->disp); -} - -static void -g94_sor_war_2(struct nvkm_ior *sor) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - const u32 soff = nv50_ior_base(sor); - - if (!g94_sor_war_needed(sor)) - return; - - nvkm_mask(device, 0x00e840, 0x80000000, 0x80000000); - nvkm_mask(device, 0x614300 + soff, 0x03000000, 0x03000000); - nvkm_mask(device, 0x61c10c + soff, 0x00000001, 0x00000001); - - nvkm_mask(device, 0x61c00c + soff, 0x0f000000, 0x00000000); - nvkm_mask(device, 0x61c008 + soff, 0xff000000, 0x14000000); - nvkm_usec(device, 400, NVKM_DELAY); - nvkm_mask(device, 0x61c008 + soff, 0xff000000, 0x00000000); - nvkm_mask(device, 0x61c00c + soff, 0x0f000000, 0x01000000); - - if (nvkm_rd32(device, 0x61c004 + soff) & 0x00000001) { - u32 seqctl = nvkm_rd32(device, 0x61c030 + soff); - u32 pu_pc = seqctl & 0x0000000f; - nvkm_wr32(device, 0x61c040 + soff + pu_pc * 4, 0x1f008000); - } -} - -void -g94_sor_state(struct nvkm_ior *sor, struct nvkm_ior_state *state) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - const u32 coff = sor->id * 8 + (state == &sor->arm) * 4; - u32 ctrl = nvkm_rd32(device, 0x610794 + coff); - - state->proto_evo = (ctrl & 0x00000f00) >> 8; - switch (state->proto_evo) { - case 0: state->proto = LVDS; state->link = 1; break; - case 1: state->proto = TMDS; state->link = 1; break; - case 2: state->proto = TMDS; state->link = 2; break; - case 5: state->proto = TMDS; state->link = 3; break; - case 8: state->proto = DP; state->link = 1; break; - case 9: state->proto = DP; state->link = 2; break; - default: - state->proto = UNKNOWN; - break; - } - - state->head = ctrl & 0x00000003; - nv50_pior_depth(sor, state, ctrl); -} - -static const struct nvkm_ior_func -g94_sor = { - .state = g94_sor_state, - .power = nv50_sor_power, - .clock = nv50_sor_clock, - .war_2 = g94_sor_war_2, - .war_3 = g94_sor_war_3, - .dp = { - .lanes = { 2, 1, 0, 3}, - .links = g94_sor_dp_links, - .power = g94_sor_dp_power, - .pattern = g94_sor_dp_pattern, - .drive = g94_sor_dp_drive, - .audio_sym = g94_sor_dp_audio_sym, - .activesym = g94_sor_dp_activesym, - .watermark = g94_sor_dp_watermark, - }, -}; - -int -g94_sor_new(struct nvkm_disp *disp, int id) -{ - return nvkm_ior_new_(&g94_sor, disp, SOR, id); -} - -int -g94_sor_cnt(struct nvkm_disp *disp, unsigned long *pmask) -{ - struct nvkm_device *device = disp->engine.subdev.device; - *pmask = (nvkm_rd32(device, 0x610184) & 0x0f000000) >> 24; - return 4; -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorga102.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorga102.c deleted file mode 100644 index d2c05f5c4aa0..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorga102.c +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright 2021 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 int -ga102_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; - - switch (sor->dp.bw) { - case 0x06: clksor |= 0x00000000; break; - case 0x0a: clksor |= 0x00040000; break; - case 0x14: clksor |= 0x00080000; break; - case 0x1e: clksor |= 0x000c0000; break; - case 0x08: clksor |= 0x00100000; break; - case 0x09: clksor |= 0x00140000; break; - case 0x0c: clksor |= 0x00180000; break; - case 0x10: clksor |= 0x001c0000; break; - default: - WARN_ON(1); - return -EINVAL; - } - - 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 void -ga102_sor_clock(struct nvkm_ior *sor) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - u32 div2 = 0; - if (sor->asy.proto == TMDS) { - if (sor->tmds.high_speed) - div2 = 1; - } - nvkm_wr32(device, 0x00ec08 + (sor->id * 0x10), 0x00000000); - nvkm_wr32(device, 0x00ec04 + (sor->id * 0x10), div2); -} - -static const struct nvkm_ior_func -ga102_sor_hda = { - .route = { - .get = gm200_sor_route_get, - .set = gm200_sor_route_set, - }, - .state = gv100_sor_state, - .power = nv50_sor_power, - .clock = ga102_sor_clock, - .hdmi = { - .ctrl = gv100_hdmi_ctrl, - .scdc = gm200_hdmi_scdc, - }, - .dp = { - .lanes = { 0, 1, 2, 3 }, - .links = ga102_sor_dp_links, - .power = g94_sor_dp_power, - .pattern = gm107_sor_dp_pattern, - .drive = gm200_sor_dp_drive, - .vcpi = tu102_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, - .device_entry = gv100_hda_device_entry, - }, -}; - -static const struct nvkm_ior_func -ga102_sor = { - .route = { - .get = gm200_sor_route_get, - .set = gm200_sor_route_set, - }, - .state = gv100_sor_state, - .power = nv50_sor_power, - .clock = ga102_sor_clock, - .hdmi = { - .ctrl = gv100_hdmi_ctrl, - .scdc = gm200_hdmi_scdc, - }, - .dp = { - .lanes = { 0, 1, 2, 3 }, - .links = ga102_sor_dp_links, - .power = g94_sor_dp_power, - .pattern = gm107_sor_dp_pattern, - .drive = gm200_sor_dp_drive, - .vcpi = tu102_sor_dp_vcpi, - .audio = gv100_sor_dp_audio, - .audio_sym = gv100_sor_dp_audio_sym, - .watermark = gv100_sor_dp_watermark, - }, -}; - -int -ga102_sor_new(struct nvkm_disp *disp, int id) -{ - struct nvkm_device *device = disp->engine.subdev.device; - u32 hda = nvkm_rd32(device, 0x08a15c); - if (hda & BIT(id)) - return nvkm_ior_new_(&ga102_sor_hda, disp, SOR, id); - return nvkm_ior_new_(&ga102_sor, disp, SOR, id); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgf119.c deleted file mode 100644 index c431e0b9fc11..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgf119.c +++ /dev/null @@ -1,208 +0,0 @@ -/* - * Copyright 2012 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. - * - * Authors: Ben Skeggs - */ -#include "ior.h" - -#include <subdev/timer.h> - -void -gf119_sor_dp_watermark(struct nvkm_ior *sor, int head, u8 watermark) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - const u32 hoff = head * 0x800; - nvkm_mask(device, 0x616610 + hoff, 0x0800003f, 0x08000000 | watermark); -} - -void -gf119_sor_dp_audio_sym(struct nvkm_ior *sor, int head, u16 h, u32 v) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - const u32 hoff = head * 0x800; - nvkm_mask(device, 0x616620 + hoff, 0x0000ffff, h); - nvkm_mask(device, 0x616624 + hoff, 0x00ffffff, v); -} - -void -gf119_sor_dp_audio(struct nvkm_ior *sor, int head, bool enable) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - const u32 hoff = 0x800 * head; - const u32 data = 0x80000000 | (0x00000001 * enable); - const u32 mask = 0x8000000d; - nvkm_mask(device, 0x616618 + hoff, mask, data); - nvkm_msec(device, 2000, - if (!(nvkm_rd32(device, 0x616618 + hoff) & 0x80000000)) - break; - ); -} - -void -gf119_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, 0x616588 + hoff, 0x00003f3f, (slot_nr << 8) | slot); - nvkm_mask(device, 0x61658c + hoff, 0xffffffff, (aligned << 16) | pbn); -} - -void -gf119_sor_dp_drive(struct nvkm_ior *sor, int ln, int pc, int dc, int pe, int pu) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - const u32 loff = nv50_sor_link(sor); - const u32 shift = sor->func->dp.lanes[ln] * 8; - u32 data[4]; - - data[0] = nvkm_rd32(device, 0x61c118 + loff) & ~(0x000000ff << shift); - data[1] = nvkm_rd32(device, 0x61c120 + loff) & ~(0x000000ff << shift); - data[2] = nvkm_rd32(device, 0x61c130 + loff); - if ((data[2] & 0x0000ff00) < (pu << 8) || ln == 0) - data[2] = (data[2] & ~0x0000ff00) | (pu << 8); - nvkm_wr32(device, 0x61c118 + loff, data[0] | (dc << shift)); - nvkm_wr32(device, 0x61c120 + loff, data[1] | (pe << shift)); - nvkm_wr32(device, 0x61c130 + loff, data[2]); - data[3] = nvkm_rd32(device, 0x61c13c + loff) & ~(0x000000ff << shift); - nvkm_wr32(device, 0x61c13c + loff, data[3] | (pc << shift)); -} - -void -gf119_sor_dp_pattern(struct nvkm_ior *sor, int pattern) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - const u32 soff = nv50_ior_base(sor); - u32 data; - - switch (pattern) { - case 0: data = 0x10101010; break; - case 1: data = 0x01010101; break; - case 2: data = 0x02020202; break; - case 3: data = 0x03030303; break; - default: - WARN_ON(1); - return; - } - - nvkm_mask(device, 0x61c110 + soff, 0x1f1f1f1f, data); -} - -int -gf119_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); - nvkm_mask(device, 0x61c10c + loff, 0x401f4000, dpctrl); - return 0; -} - -void -gf119_sor_clock(struct nvkm_ior *sor) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - const u32 soff = nv50_ior_base(sor); - u32 div1 = sor->asy.link == 3; - u32 div2 = sor->asy.link == 3; - if (sor->asy.proto == TMDS) { - const u32 speed = sor->tmds.high_speed ? 0x14 : 0x0a; - nvkm_mask(device, 0x612300 + soff, 0x007c0000, speed << 18); - if (sor->tmds.high_speed) - div2 = 1; - } - nvkm_mask(device, 0x612300 + soff, 0x00000707, (div2 << 8) | div1); -} - -void -gf119_sor_state(struct nvkm_ior *sor, struct nvkm_ior_state *state) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - const u32 coff = (state == &sor->asy) * 0x20000 + sor->id * 0x20; - u32 ctrl = nvkm_rd32(device, 0x640200 + coff); - - state->proto_evo = (ctrl & 0x00000f00) >> 8; - switch (state->proto_evo) { - case 0: state->proto = LVDS; state->link = 1; break; - case 1: state->proto = TMDS; state->link = 1; break; - case 2: state->proto = TMDS; state->link = 2; break; - case 5: state->proto = TMDS; state->link = 3; break; - case 8: state->proto = DP; state->link = 1; break; - case 9: state->proto = DP; state->link = 2; break; - default: - state->proto = UNKNOWN; - break; - } - - state->head = ctrl & 0x0000000f; -} - -static const struct nvkm_ior_func -gf119_sor = { - .state = gf119_sor_state, - .power = nv50_sor_power, - .clock = gf119_sor_clock, - .hdmi = { - .ctrl = gf119_hdmi_ctrl, - }, - .dp = { - .lanes = { 2, 1, 0, 3 }, - .links = gf119_sor_dp_links, - .power = g94_sor_dp_power, - .pattern = gf119_sor_dp_pattern, - .drive = gf119_sor_dp_drive, - .vcpi = gf119_sor_dp_vcpi, - .audio = gf119_sor_dp_audio, - .audio_sym = gf119_sor_dp_audio_sym, - .watermark = gf119_sor_dp_watermark, - }, - .hda = { - .hpd = gf119_hda_hpd, - .eld = gf119_hda_eld, - .device_entry = gf119_hda_device_entry, - }, -}; - -int -gf119_sor_new(struct nvkm_disp *disp, int id) -{ - return nvkm_ior_new_(&gf119_sor, disp, SOR, id); -} - -int -gf119_sor_cnt(struct nvkm_disp *disp, unsigned long *pmask) -{ - struct nvkm_device *device = disp->engine.subdev.device; - *pmask = (nvkm_rd32(device, 0x612004) & 0x0000ff00) >> 8; - return 8; -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgk104.c deleted file mode 100644 index 0c0925680790..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgk104.c +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2017 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" - -static const struct nvkm_ior_func -gk104_sor = { - .state = gf119_sor_state, - .power = nv50_sor_power, - .clock = gf119_sor_clock, - .hdmi = { - .ctrl = gk104_hdmi_ctrl, - }, - .dp = { - .lanes = { 2, 1, 0, 3 }, - .links = gf119_sor_dp_links, - .power = g94_sor_dp_power, - .pattern = gf119_sor_dp_pattern, - .drive = gf119_sor_dp_drive, - .vcpi = gf119_sor_dp_vcpi, - .audio = gf119_sor_dp_audio, - .audio_sym = gf119_sor_dp_audio_sym, - .watermark = gf119_sor_dp_watermark, - }, - .hda = { - .hpd = gf119_hda_hpd, - .eld = gf119_hda_eld, - .device_entry = gf119_hda_device_entry, - }, -}; - -int -gk104_sor_new(struct nvkm_disp *disp, int id) -{ - return nvkm_ior_new_(&gk104_sor, disp, SOR, id); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm107.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm107.c deleted file mode 100644 index 3696bfd3bfd7..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm107.c +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright 2016 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. - * - * Authors: Ben Skeggs <bskeggs@redhat.com> - */ -#include "ior.h" - -void -gm107_sor_dp_pattern(struct nvkm_ior *sor, int pattern) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - const u32 soff = nv50_ior_base(sor); - u32 mask = 0x1f1f1f1f, data; - - switch (pattern) { - case 0: data = 0x10101010; break; - case 1: data = 0x01010101; break; - case 2: data = 0x02020202; break; - case 3: data = 0x03030303; break; - case 4: data = 0x1b1b1b1b; break; - default: - WARN_ON(1); - return; - } - - if (sor->asy.link & 1) - nvkm_mask(device, 0x61c110 + soff, mask, data); - else - nvkm_mask(device, 0x61c12c + soff, mask, data); -} - -static const struct nvkm_ior_func -gm107_sor = { - .state = gf119_sor_state, - .power = nv50_sor_power, - .clock = gf119_sor_clock, - .hdmi = { - .ctrl = gk104_hdmi_ctrl, - }, - .dp = { - .lanes = { 0, 1, 2, 3 }, - .links = gf119_sor_dp_links, - .power = g94_sor_dp_power, - .pattern = gm107_sor_dp_pattern, - .drive = gf119_sor_dp_drive, - .vcpi = gf119_sor_dp_vcpi, - .audio = gf119_sor_dp_audio, - .audio_sym = gf119_sor_dp_audio_sym, - .watermark = gf119_sor_dp_watermark, - }, - .hda = { - .hpd = gf119_hda_hpd, - .eld = gf119_hda_eld, - .device_entry = gf119_hda_device_entry, - }, -}; - -int -gm107_sor_new(struct nvkm_disp *disp, int id) -{ - return nvkm_ior_new_(&gm107_sor, disp, SOR, id); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm200.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm200.c deleted file mode 100644 index c041e210df8d..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm200.c +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright 2012 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. - * - * Authors: Ben Skeggs - */ -#include "ior.h" -#include "outp.h" - -void -gm200_sor_dp_drive(struct nvkm_ior *sor, int ln, int pc, int dc, int pe, int pu) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - const u32 loff = nv50_sor_link(sor); - const u32 shift = sor->func->dp.lanes[ln] * 8; - u32 data[4]; - - pu &= 0x0f; - - data[0] = nvkm_rd32(device, 0x61c118 + loff) & ~(0x000000ff << shift); - data[1] = nvkm_rd32(device, 0x61c120 + loff) & ~(0x000000ff << shift); - data[2] = nvkm_rd32(device, 0x61c130 + loff); - if ((data[2] & 0x00000f00) < (pu << 8) || ln == 0) - data[2] = (data[2] & ~0x00000f00) | (pu << 8); - nvkm_wr32(device, 0x61c118 + loff, data[0] | (dc << shift)); - nvkm_wr32(device, 0x61c120 + loff, data[1] | (pe << shift)); - nvkm_wr32(device, 0x61c130 + loff, data[2]); - data[3] = nvkm_rd32(device, 0x61c13c + loff) & ~(0x000000ff << shift); - nvkm_wr32(device, 0x61c13c + loff, data[3] | (pc << shift)); -} - -void -gm200_sor_route_set(struct nvkm_outp *outp, struct nvkm_ior *ior) -{ - struct nvkm_device *device = outp->disp->engine.subdev.device; - const u32 moff = __ffs(outp->info.or) * 0x100; - const u32 sor = ior ? ior->id + 1 : 0; - u32 link = ior ? (ior->asy.link == 2) : 0; - - if (outp->info.sorconf.link & 1) { - nvkm_mask(device, 0x612308 + moff, 0x0000001f, link << 4 | sor); - link++; - } - - if (outp->info.sorconf.link & 2) - nvkm_mask(device, 0x612388 + moff, 0x0000001f, link << 4 | sor); -} - -int -gm200_sor_route_get(struct nvkm_outp *outp, int *link) -{ - struct nvkm_device *device = outp->disp->engine.subdev.device; - const int sublinks = outp->info.sorconf.link; - int lnk[2], sor[2], m, s; - - for (*link = 0, m = __ffs(outp->info.or) * 2, s = 0; s < 2; m++, s++) { - if (sublinks & BIT(s)) { - u32 data = nvkm_rd32(device, 0x612308 + (m * 0x80)); - lnk[s] = (data & 0x00000010) >> 4; - sor[s] = (data & 0x0000000f); - if (!sor[s]) - return -1; - *link |= lnk[s]; - } - } - - if (sublinks == 3) { - if (sor[0] != sor[1] || WARN_ON(lnk[0] || !lnk[1])) - return -1; - } - - return ((sublinks & 1) ? sor[0] : sor[1]) - 1; -} - -static const struct nvkm_ior_func -gm200_sor_hda = { - .route = { - .get = gm200_sor_route_get, - .set = gm200_sor_route_set, - }, - .state = gf119_sor_state, - .power = nv50_sor_power, - .clock = gf119_sor_clock, - .hdmi = { - .ctrl = gk104_hdmi_ctrl, - .scdc = gm200_hdmi_scdc, - }, - .dp = { - .lanes = { 0, 1, 2, 3 }, - .links = gf119_sor_dp_links, - .power = g94_sor_dp_power, - .pattern = gm107_sor_dp_pattern, - .drive = gm200_sor_dp_drive, - .vcpi = gf119_sor_dp_vcpi, - .audio = gf119_sor_dp_audio, - .audio_sym = gf119_sor_dp_audio_sym, - .watermark = gf119_sor_dp_watermark, - }, - .hda = { - .hpd = gf119_hda_hpd, - .eld = gf119_hda_eld, - .device_entry = gf119_hda_device_entry, - }, -}; - -static const struct nvkm_ior_func -gm200_sor = { - .route = { - .get = gm200_sor_route_get, - .set = gm200_sor_route_set, - }, - .state = gf119_sor_state, - .power = nv50_sor_power, - .clock = gf119_sor_clock, - .hdmi = { - .ctrl = gk104_hdmi_ctrl, - .scdc = gm200_hdmi_scdc, - }, - .dp = { - .lanes = { 0, 1, 2, 3 }, - .links = gf119_sor_dp_links, - .power = g94_sor_dp_power, - .pattern = gm107_sor_dp_pattern, - .drive = gm200_sor_dp_drive, - .vcpi = gf119_sor_dp_vcpi, - .audio = gf119_sor_dp_audio, - .audio_sym = gf119_sor_dp_audio_sym, - .watermark = gf119_sor_dp_watermark, - }, -}; - -int -gm200_sor_new(struct nvkm_disp *disp, int id) -{ - struct nvkm_device *device = disp->engine.subdev.device; - u32 hda; - - if (!((hda = nvkm_rd32(device, 0x08a15c)) & 0x40000000)) - hda = nvkm_rd32(device, 0x101034); - - if (hda & BIT(id)) - return nvkm_ior_new_(&gm200_sor_hda, disp, SOR, id); - return nvkm_ior_new_(&gm200_sor, disp, SOR, id); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgp100.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgp100.c deleted file mode 100644 index c54f88317a07..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgp100.c +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright 2020 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" - -static const struct nvkm_ior_func -gp100_sor_hda = { - .route = { - .get = gm200_sor_route_get, - .set = gm200_sor_route_set, - }, - .state = gf119_sor_state, - .power = nv50_sor_power, - .clock = gf119_sor_clock, - .hdmi = { - .ctrl = gk104_hdmi_ctrl, - .scdc = gm200_hdmi_scdc, - }, - .dp = { - .lanes = { 0, 1, 2, 3 }, - .links = gf119_sor_dp_links, - .power = g94_sor_dp_power, - .pattern = gm107_sor_dp_pattern, - .drive = gm200_sor_dp_drive, - .vcpi = gf119_sor_dp_vcpi, - .audio = gf119_sor_dp_audio, - .audio_sym = gf119_sor_dp_audio_sym, - .watermark = gf119_sor_dp_watermark, - }, - .hda = { - .hpd = gf119_hda_hpd, - .eld = gf119_hda_eld, - .device_entry = gf119_hda_device_entry, - }, -}; - -static const struct nvkm_ior_func -gp100_sor = { - .route = { - .get = gm200_sor_route_get, - .set = gm200_sor_route_set, - }, - .state = gf119_sor_state, - .power = nv50_sor_power, - .clock = gf119_sor_clock, - .hdmi = { - .ctrl = gk104_hdmi_ctrl, - .scdc = gm200_hdmi_scdc, - }, - .dp = { - .lanes = { 0, 1, 2, 3 }, - .links = gf119_sor_dp_links, - .power = g94_sor_dp_power, - .pattern = gm107_sor_dp_pattern, - .drive = gm200_sor_dp_drive, - .vcpi = gf119_sor_dp_vcpi, - .audio = gf119_sor_dp_audio, - .audio_sym = gf119_sor_dp_audio_sym, - .watermark = gf119_sor_dp_watermark, - }, -}; - -int -gp100_sor_new(struct nvkm_disp *disp, int id) -{ - struct nvkm_device *device = disp->engine.subdev.device; - u32 hda; - - if (!((hda = nvkm_rd32(device, 0x08a15c)) & 0x40000000)) - hda = nvkm_rd32(device, 0x10ebb0) >> 8; - - if (hda & BIT(id)) - return nvkm_ior_new_(&gp100_sor_hda, disp, SOR, id); - return nvkm_ior_new_(&gp100_sor, disp, SOR, id); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgt215.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgt215.c deleted file mode 100644 index 54d134d4ca1d..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgt215.c +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright 2017 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> - -void -gt215_sor_dp_audio(struct nvkm_ior *sor, int head, bool enable) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - const u32 soff = nv50_ior_base(sor); - const u32 data = 0x80000000 | (0x00000001 * enable); - const u32 mask = 0x8000000d; - nvkm_mask(device, 0x61c1e0 + soff, mask, data); - nvkm_msec(device, 2000, - if (!(nvkm_rd32(device, 0x61c1e0 + soff) & 0x80000000)) - break; - ); -} - -static const struct nvkm_ior_func -gt215_sor = { - .state = g94_sor_state, - .power = nv50_sor_power, - .clock = nv50_sor_clock, - .hdmi = { - .ctrl = gt215_hdmi_ctrl, - }, - .dp = { - .lanes = { 2, 1, 0, 3 }, - .links = g94_sor_dp_links, - .power = g94_sor_dp_power, - .pattern = g94_sor_dp_pattern, - .drive = g94_sor_dp_drive, - .audio = gt215_sor_dp_audio, - .audio_sym = g94_sor_dp_audio_sym, - .activesym = g94_sor_dp_activesym, - .watermark = g94_sor_dp_watermark, - }, - .hda = { - .hpd = gt215_hda_hpd, - .eld = gt215_hda_eld, - }, -}; - -int -gt215_sor_new(struct nvkm_disp *disp, int id) -{ - return nvkm_ior_new_(>215_sor, disp, SOR, id); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgv100.c deleted file mode 100644 index 4441187e8ec9..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgv100.c +++ /dev/null @@ -1,155 +0,0 @@ -/* - * 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> - -void -gv100_sor_dp_watermark(struct nvkm_ior *sor, int head, u8 watermark) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - const u32 hoff = head * 0x800; - nvkm_mask(device, 0x616550 + hoff, 0x0c00003f, 0x08000000 | watermark); -} - -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; - const u32 hoff = head * 0x800; - nvkm_mask(device, 0x616568 + hoff, 0x0000ffff, h); - nvkm_mask(device, 0x61656c + hoff, 0x00ffffff, v); -} - -void -gv100_sor_dp_audio(struct nvkm_ior *sor, int head, bool enable) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - const u32 hoff = 0x800 * head; - const u32 data = 0x80000000 | (0x00000001 * enable); - const u32 mask = 0x8000000d; - nvkm_mask(device, 0x616560 + hoff, mask, data); - nvkm_msec(device, 2000, - if (!(nvkm_rd32(device, 0x616560 + hoff) & 0x80000000)) - break; - ); -} - -void -gv100_sor_state(struct nvkm_ior *sor, struct nvkm_ior_state *state) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - const u32 coff = (state == &sor->arm) * 0x8000 + sor->id * 0x20; - u32 ctrl = nvkm_rd32(device, 0x680300 + coff); - - state->proto_evo = (ctrl & 0x00000f00) >> 8; - switch (state->proto_evo) { - case 0: state->proto = LVDS; state->link = 1; break; - case 1: state->proto = TMDS; state->link = 1; break; - case 2: state->proto = TMDS; state->link = 2; break; - case 5: state->proto = TMDS; state->link = 3; break; - case 8: state->proto = DP; state->link = 1; break; - case 9: state->proto = DP; state->link = 2; break; - default: - state->proto = UNKNOWN; - break; - } - - state->head = ctrl & 0x000000ff; -} - -static const struct nvkm_ior_func -gv100_sor_hda = { - .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, - .scdc = gm200_hdmi_scdc, - }, - .dp = { - .lanes = { 0, 1, 2, 3 }, - .links = gf119_sor_dp_links, - .power = g94_sor_dp_power, - .pattern = gm107_sor_dp_pattern, - .drive = gm200_sor_dp_drive, - .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, - .device_entry = gv100_hda_device_entry, - }, -}; - -static const struct nvkm_ior_func -gv100_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, - .scdc = gm200_hdmi_scdc, - }, - .dp = { - .lanes = { 0, 1, 2, 3 }, - .links = gf119_sor_dp_links, - .power = g94_sor_dp_power, - .pattern = gm107_sor_dp_pattern, - .drive = gm200_sor_dp_drive, - .audio = gv100_sor_dp_audio, - .audio_sym = gv100_sor_dp_audio_sym, - .watermark = gv100_sor_dp_watermark, - }, -}; - -int -gv100_sor_new(struct nvkm_disp *disp, int id) -{ - struct nvkm_device *device = disp->engine.subdev.device; - u32 hda; - - if (!((hda = nvkm_rd32(device, 0x08a15c)) & 0x40000000)) - hda = nvkm_rd32(device, 0x118fb0) >> 8; - - if (hda & BIT(id)) - return nvkm_ior_new_(&gv100_sor_hda, disp, SOR, id); - return nvkm_ior_new_(&gv100_sor, disp, SOR, id); -} - -int -gv100_sor_cnt(struct nvkm_disp *disp, unsigned long *pmask) -{ - struct nvkm_device *device = disp->engine.subdev.device; - *pmask = (nvkm_rd32(device, 0x610060) & 0x0000ff00) >> 8; - return (nvkm_rd32(device, 0x610074) & 0x00000f00) >> 8; -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sormcp77.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sormcp77.c deleted file mode 100644 index 8a70dd25b13a..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sormcp77.c +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2017 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" - -static const struct nvkm_ior_func -mcp77_sor = { - .state = g94_sor_state, - .power = nv50_sor_power, - .clock = nv50_sor_clock, - .hdmi = { - .ctrl = g84_hdmi_ctrl, - }, - .dp = { - .lanes = { 2, 1, 0, 3}, - .links = g94_sor_dp_links, - .power = g94_sor_dp_power, - .pattern = g94_sor_dp_pattern, - .drive = g94_sor_dp_drive, - .audio_sym = g94_sor_dp_audio_sym, - .activesym = g94_sor_dp_activesym, - .watermark = g94_sor_dp_watermark, - }, -}; - -int -mcp77_sor_new(struct nvkm_disp *disp, int id) -{ - return nvkm_ior_new_(&mcp77_sor, disp, SOR, id); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sormcp89.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sormcp89.c deleted file mode 100644 index eac9c5be9166..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sormcp89.c +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2017 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" - -static const struct nvkm_ior_func -mcp89_sor = { - .state = g94_sor_state, - .power = nv50_sor_power, - .clock = nv50_sor_clock, - .hdmi = { - .ctrl = gt215_hdmi_ctrl, - }, - .dp = { - .lanes = { 3, 2, 1, 0 }, - .links = g94_sor_dp_links, - .power = g94_sor_dp_power, - .pattern = g94_sor_dp_pattern, - .drive = g94_sor_dp_drive, - .audio = gt215_sor_dp_audio, - .audio_sym = g94_sor_dp_audio_sym, - .activesym = g94_sor_dp_activesym, - .watermark = g94_sor_dp_watermark, - }, - .hda = { - .hpd = gt215_hda_hpd, - .eld = gt215_hda_eld, - }, -}; - -int -mcp89_sor_new(struct nvkm_disp *disp, int id) -{ - return nvkm_ior_new_(&mcp89_sor, disp, SOR, id); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sornv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sornv50.c deleted file mode 100644 index b4729f8798af..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sornv50.c +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright 2012 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. - * - * Authors: Ben Skeggs - */ -#include "ior.h" - -#include <subdev/timer.h> - -void -nv50_sor_clock(struct nvkm_ior *sor) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - const int div = sor->asy.link == 3; - const u32 soff = nv50_ior_base(sor); - nvkm_mask(device, 0x614300 + soff, 0x00000707, (div << 8) | div); -} - -static void -nv50_sor_power_wait(struct nvkm_device *device, u32 soff) -{ - nvkm_msec(device, 2000, - if (!(nvkm_rd32(device, 0x61c004 + soff) & 0x80000000)) - break; - ); -} - -void -nv50_sor_power(struct nvkm_ior *sor, bool normal, bool pu, - bool data, bool vsync, bool hsync) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - const u32 soff = nv50_ior_base(sor); - const u32 shift = normal ? 0 : 16; - const u32 state = 0x80000000 | (0x00000001 * !!pu) << shift; - const u32 field = 0x80000000 | (0x00000001 << shift); - - nv50_sor_power_wait(device, soff); - nvkm_mask(device, 0x61c004 + soff, field, state); - nv50_sor_power_wait(device, soff); - - nvkm_msec(device, 2000, - if (!(nvkm_rd32(device, 0x61c030 + soff) & 0x10000000)) - break; - ); -} - -void -nv50_sor_state(struct nvkm_ior *sor, struct nvkm_ior_state *state) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - const u32 coff = sor->id * 8 + (state == &sor->arm) * 4; - u32 ctrl = nvkm_rd32(device, 0x610b70 + coff); - - state->proto_evo = (ctrl & 0x00000f00) >> 8; - switch (state->proto_evo) { - case 0: state->proto = LVDS; state->link = 1; break; - case 1: state->proto = TMDS; state->link = 1; break; - case 2: state->proto = TMDS; state->link = 2; break; - case 5: state->proto = TMDS; state->link = 3; break; - default: - state->proto = UNKNOWN; - break; - } - - state->head = ctrl & 0x00000003; -} - -static const struct nvkm_ior_func -nv50_sor = { - .state = nv50_sor_state, - .power = nv50_sor_power, - .clock = nv50_sor_clock, -}; - -int -nv50_sor_new(struct nvkm_disp *disp, int id) -{ - return nvkm_ior_new_(&nv50_sor, disp, SOR, id); -} - -int -nv50_sor_cnt(struct nvkm_disp *disp, unsigned long *pmask) -{ - struct nvkm_device *device = disp->engine.subdev.device; - *pmask = (nvkm_rd32(device, 0x610184) & 0x03000000) >> 24; - return 2; -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sortu102.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sortu102.c deleted file mode 100644 index 0cf9e8752d25..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sortu102.c +++ /dev/null @@ -1,129 +0,0 @@ -/* - * 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> - -void -tu102_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 -tu102_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 -tu102_sor_hda = { - .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, - .scdc = gm200_hdmi_scdc, - }, - .dp = { - .lanes = { 0, 1, 2, 3 }, - .links = tu102_sor_dp_links, - .power = g94_sor_dp_power, - .pattern = gm107_sor_dp_pattern, - .drive = gm200_sor_dp_drive, - .vcpi = tu102_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, - .device_entry = gv100_hda_device_entry, - }, -}; - -static const struct nvkm_ior_func -tu102_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, - .scdc = gm200_hdmi_scdc, - }, - .dp = { - .lanes = { 0, 1, 2, 3 }, - .links = tu102_sor_dp_links, - .power = g94_sor_dp_power, - .pattern = gm107_sor_dp_pattern, - .drive = gm200_sor_dp_drive, - .vcpi = tu102_sor_dp_vcpi, - .audio = gv100_sor_dp_audio, - .audio_sym = gv100_sor_dp_audio_sym, - .watermark = gv100_sor_dp_watermark, - }, -}; - -int -tu102_sor_new(struct nvkm_disp *disp, int id) -{ - struct nvkm_device *device = disp->engine.subdev.device; - u32 hda = nvkm_rd32(device, 0x08a15c); - if (hda & BIT(id)) - return nvkm_ior_new_(&tu102_sor_hda, disp, SOR, id); - return nvkm_ior_new_(&tu102_sor, disp, SOR, id); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/tu102.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/tu102.c index d904a9b19fec..2c0a10d6af8c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/tu102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/tu102.c @@ -19,16 +19,120 @@ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ +#include "chan.h" #include "priv.h" #include "head.h" #include "ior.h" -#include "channv50.h" #include <core/gpuobj.h> #include <subdev/timer.h> #include <nvif/class.h> +void +tu102_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 +tu102_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 +tu102_sor_hda = { + .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_sor_hdmi_ctrl, + .scdc = gm200_sor_hdmi_scdc, + }, + .dp = { + .lanes = { 0, 1, 2, 3 }, + .links = tu102_sor_dp_links, + .power = g94_sor_dp_power, + .pattern = gm107_sor_dp_pattern, + .drive = gm200_sor_dp_drive, + .vcpi = tu102_sor_dp_vcpi, + .audio = gv100_sor_dp_audio, + .audio_sym = gv100_sor_dp_audio_sym, + .watermark = gv100_sor_dp_watermark, + }, + .hda = { + .hpd = gf119_sor_hda_hpd, + .eld = gf119_sor_hda_eld, + .device_entry = gv100_sor_hda_device_entry, + }, +}; + +static const struct nvkm_ior_func +tu102_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_sor_hdmi_ctrl, + .scdc = gm200_sor_hdmi_scdc, + }, + .dp = { + .lanes = { 0, 1, 2, 3 }, + .links = tu102_sor_dp_links, + .power = g94_sor_dp_power, + .pattern = gm107_sor_dp_pattern, + .drive = gm200_sor_dp_drive, + .vcpi = tu102_sor_dp_vcpi, + .audio = gv100_sor_dp_audio, + .audio_sym = gv100_sor_dp_audio_sym, + .watermark = gv100_sor_dp_watermark, + }, +}; + +static int +tu102_sor_new(struct nvkm_disp *disp, int id) +{ + struct nvkm_device *device = disp->engine.subdev.device; + u32 hda = nvkm_rd32(device, 0x08a15c); + if (hda & BIT(id)) + return nvkm_ior_new_(&tu102_sor_hda, disp, SOR, id); + return nvkm_ior_new_(&tu102_sor, disp, SOR, id); +} + int tu102_disp_init(struct nvkm_disp *disp) { @@ -134,8 +238,8 @@ tu102_disp_init(struct nvkm_disp *disp) static const struct nvkm_disp_func tu102_disp = { - .dtor = nv50_disp_dtor_, - .oneinit = nv50_disp_oneinit_, + .dtor = nv50_disp_dtor, + .oneinit = nv50_disp_oneinit, .init = tu102_disp_init, .fini = gv100_disp_fini, .intr = gv100_disp_intr, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/wimmgv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/wimmgv100.c deleted file mode 100644 index 49070727545e..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/wimmgv100.c +++ /dev/null @@ -1,82 +0,0 @@ -/* - * 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 "channv50.h" - -#include <core/client.h> - -#include <nvif/clc37b.h> -#include <nvif/unpack.h> - -static void -gv100_disp_wimm_intr(struct nv50_disp_chan *chan, bool en) -{ - struct nvkm_device *device = chan->disp->engine.subdev.device; - const u32 mask = 0x00000001 << chan->head; - const u32 data = en ? mask : 0; - nvkm_mask(device, 0x611da8, mask, data); -} - -static const struct nv50_disp_chan_func -gv100_disp_wimm = { - .init = gv100_disp_dmac_init, - .fini = gv100_disp_dmac_fini, - .intr = gv100_disp_wimm_intr, - .user = gv100_disp_chan_user, -}; - -static int -gv100_disp_wimm_new_(const struct nv50_disp_chan_func *func, - const struct nv50_disp_chan_mthd *mthd, - struct nvkm_disp *disp, int chid, - const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nvkm_object **pobject) -{ - union { - struct nvc37b_window_imm_channel_dma_v0 v0; - } *args = argv; - struct nvkm_object *parent = oclass->parent; - int wndw, ret = -ENOSYS; - u64 push; - - nvif_ioctl(parent, "create window imm channel dma size %d\n", argc); - if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, false))) { - nvif_ioctl(parent, "create window imm channel dma vers %d " - "pushbuf %016llx index %d\n", - args->v0.version, args->v0.pushbuf, args->v0.index); - if (!(disp->wndw.mask & BIT(args->v0.index))) - return -EINVAL; - push = args->v0.pushbuf; - wndw = args->v0.index; - } else - return ret; - - return nv50_disp_dmac_new_(func, mthd, disp, chid + wndw, - wndw, push, oclass, pobject); -} - -int -gv100_disp_wimm_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nvkm_disp *disp, struct nvkm_object **pobject) -{ - return gv100_disp_wimm_new_(&gv100_disp_wimm, NULL, disp, 33, - oclass, argv, argc, pobject); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/wndwgv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/wndwgv100.c deleted file mode 100644 index 26e029805cda..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/wndwgv100.c +++ /dev/null @@ -1,184 +0,0 @@ -/* - * 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 "channv50.h" - -#include <core/client.h> - -#include <nvif/clc37e.h> -#include <nvif/unpack.h> - -static const struct nv50_disp_mthd_list -gv100_disp_wndw_mthd_base = { - .mthd = 0x0000, - .addr = 0x000000, - .data = { - { 0x0200, 0x690200 }, - { 0x020c, 0x69020c }, - { 0x0210, 0x690210 }, - { 0x0214, 0x690214 }, - { 0x0218, 0x690218 }, - { 0x021c, 0x69021c }, - { 0x0220, 0x690220 }, - { 0x0224, 0x690224 }, - { 0x0228, 0x690228 }, - { 0x022c, 0x69022c }, - { 0x0230, 0x690230 }, - { 0x0234, 0x690234 }, - { 0x0238, 0x690238 }, - { 0x0240, 0x690240 }, - { 0x0244, 0x690244 }, - { 0x0248, 0x690248 }, - { 0x024c, 0x69024c }, - { 0x0250, 0x690250 }, - { 0x0254, 0x690254 }, - { 0x0260, 0x690260 }, - { 0x0264, 0x690264 }, - { 0x0268, 0x690268 }, - { 0x026c, 0x69026c }, - { 0x0270, 0x690270 }, - { 0x0274, 0x690274 }, - { 0x0280, 0x690280 }, - { 0x0284, 0x690284 }, - { 0x0288, 0x690288 }, - { 0x028c, 0x69028c }, - { 0x0290, 0x690290 }, - { 0x0298, 0x690298 }, - { 0x029c, 0x69029c }, - { 0x02a0, 0x6902a0 }, - { 0x02a4, 0x6902a4 }, - { 0x02a8, 0x6902a8 }, - { 0x02ac, 0x6902ac }, - { 0x02b0, 0x6902b0 }, - { 0x02b4, 0x6902b4 }, - { 0x02b8, 0x6902b8 }, - { 0x02bc, 0x6902bc }, - { 0x02c0, 0x6902c0 }, - { 0x02c4, 0x6902c4 }, - { 0x02c8, 0x6902c8 }, - { 0x02cc, 0x6902cc }, - { 0x02d0, 0x6902d0 }, - { 0x02d4, 0x6902d4 }, - { 0x02d8, 0x6902d8 }, - { 0x02dc, 0x6902dc }, - { 0x02e0, 0x6902e0 }, - { 0x02e4, 0x6902e4 }, - { 0x02e8, 0x6902e8 }, - { 0x02ec, 0x6902ec }, - { 0x02f0, 0x6902f0 }, - { 0x02f4, 0x6902f4 }, - { 0x02f8, 0x6902f8 }, - { 0x02fc, 0x6902fc }, - { 0x0300, 0x690300 }, - { 0x0304, 0x690304 }, - { 0x0308, 0x690308 }, - { 0x0310, 0x690310 }, - { 0x0314, 0x690314 }, - { 0x0318, 0x690318 }, - { 0x031c, 0x69031c }, - { 0x0320, 0x690320 }, - { 0x0324, 0x690324 }, - { 0x0328, 0x690328 }, - { 0x032c, 0x69032c }, - { 0x033c, 0x69033c }, - { 0x0340, 0x690340 }, - { 0x0344, 0x690344 }, - { 0x0348, 0x690348 }, - { 0x034c, 0x69034c }, - { 0x0350, 0x690350 }, - { 0x0354, 0x690354 }, - { 0x0358, 0x690358 }, - { 0x0364, 0x690364 }, - { 0x0368, 0x690368 }, - { 0x036c, 0x69036c }, - { 0x0370, 0x690370 }, - { 0x0374, 0x690374 }, - { 0x0380, 0x690380 }, - {} - } -}; - -static const struct nv50_disp_chan_mthd -gv100_disp_wndw_mthd = { - .name = "Window", - .addr = 0x001000, - .prev = 0x000800, - .data = { - { "Global", 1, &gv100_disp_wndw_mthd_base }, - {} - } -}; - -static void -gv100_disp_wndw_intr(struct nv50_disp_chan *chan, bool en) -{ - struct nvkm_device *device = chan->disp->engine.subdev.device; - const u32 mask = 0x00000001 << chan->head; - const u32 data = en ? mask : 0; - nvkm_mask(device, 0x611da4, mask, data); -} - -static const struct nv50_disp_chan_func -gv100_disp_wndw = { - .init = gv100_disp_dmac_init, - .fini = gv100_disp_dmac_fini, - .intr = gv100_disp_wndw_intr, - .user = gv100_disp_chan_user, - .bind = gv100_disp_dmac_bind, -}; - -static int -gv100_disp_wndw_new_(const struct nv50_disp_chan_func *func, - const struct nv50_disp_chan_mthd *mthd, - struct nvkm_disp *disp, int chid, - const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nvkm_object **pobject) -{ - union { - struct nvc37e_window_channel_dma_v0 v0; - } *args = argv; - struct nvkm_object *parent = oclass->parent; - int wndw, ret = -ENOSYS; - u64 push; - - nvif_ioctl(parent, "create window channel dma size %d\n", argc); - if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, false))) { - nvif_ioctl(parent, "create window channel dma vers %d " - "pushbuf %016llx index %d\n", - args->v0.version, args->v0.pushbuf, args->v0.index); - if (!(disp->wndw.mask & BIT(args->v0.index))) - return -EINVAL; - push = args->v0.pushbuf; - wndw = args->v0.index; - } else - return ret; - - return nv50_disp_dmac_new_(func, mthd, disp, chid + wndw, - wndw, push, oclass, pobject); -} - -int -gv100_disp_wndw_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nvkm_disp *disp, struct nvkm_object **pobject) -{ - return gv100_disp_wndw_new_(&gv100_disp_wndw, &gv100_disp_wndw_mthd, - disp, 1, oclass, argv, argc, pobject); -} |