diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-06-06 08:16:33 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-06-06 08:16:33 -0700 |
commit | 135c5504a600ff9b06e321694fbcac78a9530cd4 (patch) | |
tree | 8d22ed739b0e85954010a964a9aeadf3c692c977 /drivers/gpu/drm/nouveau/nvkm/engine/disp | |
parent | af6c5d5e01ad9f2c9ca38cccaae6b5d67ddd241f (diff) | |
parent | 568cf2e6aa0c762f14d2d0d481a006f93c63ab7a (diff) | |
download | linux-next-135c5504a600ff9b06e321694fbcac78a9530cd4.tar.gz |
Merge tag 'drm-next-2018-06-06-1' of git://anongit.freedesktop.org/drm/drm
Pull drm updates from Dave Airlie:
"This starts to support NVIDIA volta hardware with nouveau, and adds
amdgpu support for the GPU in the Kabylake-G (the intel + radeon
single package chip), along with some initial Intel icelake enabling.
Summary:
New Drivers:
- v3d - driver for broadcom V3D V3.x+ hardware
- xen-front - XEN PV display frontend
core:
- handle zpos normalization in the core
- stop looking at legacy pointers in atomic paths
- improved scheduler documentation
- improved aspect ratio validation
- aspect ratio support for 64:27 and 256:135
- drop unused control node code.
i915:
- Icelake (ICL) enabling
- GuC/HuC refactoring
- PSR/PSR2 enabling and fixes
- DPLL management refactoring
- DP MST fixes
- NV12 enabling
- HDCP improvements
- GEM/Execlist/reset improvements
- GVT improvements
- stolen memory first 4k fix
amdgpu:
- Vega 20 support
- VEGAM support (Kabylake-G)
- preOS scanout buffer reservation
- power management gfxoff support for raven
- SR-IOV fixes
- Vega10 power profiles and clock voltage control
- scatter/gather display support on CZ/ST
amdkfd:
- GFX9 dGPU support
- userptr memory mapping
nouveau:
- major refactoring for Volta GV100 support
tda998x:
- HDMI i2c CEC support
etnaviv:
- removed unused logging code
- license text cleanups
- MMU handling improvements
- timeout fence fix for 50 days uptime
tegra:
- IOMMU support in gr2d/gr3d drivers
- zpos support
vc4:
- syncobj support
- CTM, plane alpha and async cursor support
analogix_dp:
- HPD and aux chan fixes
sun4i:
- MIPI DSI support
tilcdc:
- clock divider fixes for OMAP-l138 LCDK board
rcar-du:
- R8A77965 support
- dma-buf fences fixes
- hardware indexed crtc/du group handling
- generic zplane property support
atmel-hclcdc:
- generic zplane property support
mediatek:
- use generic video mode function
exynos:
- S5PV210 FIMD variant support
- IPP v2 framework
- more HW overlays support"
* tag 'drm-next-2018-06-06-1' of git://anongit.freedesktop.org/drm/drm: (1286 commits)
drm/amdgpu: fix 32-bit build warning
drm/exynos: fimc: signedness bug in fimc_setup_clocks()
drm/exynos: scaler: fix static checker warning
drm/amdgpu: Use dev_info() to report amdkfd is not supported for this ASIC
drm/amd/display: Remove use of division operator for long longs
drm/amdgpu: Update GFX info structure to match what vega20 used
drm/amdgpu/pp: remove duplicate assignment
drm/sched: add rcu_barrier after entity fini
drm/amdgpu: move VM BOs on LRU again
drm/amdgpu: consistenly use VM moved flag
drm/amdgpu: kmap PDs/PTs in amdgpu_vm_update_directories
drm/amdgpu: further optimize amdgpu_vm_handle_moved
drm/amdgpu: cleanup amdgpu_vm_validate_pt_bos v2
drm/amdgpu: rework VM state machine lock handling v2
drm/amdgpu: Add runtime VCN PG support
drm/amdgpu: Enable VCN static PG by default on RV
drm/amdgpu: Add VCN static PG support on RV
drm/amdgpu: Enable VCN CG by default on RV
drm/amdgpu: Add static CG control for VCN on RV
drm/exynos: Fix default value for zpos plane property
...
Diffstat (limited to 'drivers/gpu/drm/nouveau/nvkm/engine/disp')
105 files changed, 2573 insertions, 1942 deletions
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild b/drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild index 48ce6699183e..3d485dbf310a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild @@ -14,12 +14,14 @@ nvkm-y += nvkm/engine/disp/gm107.o nvkm-y += nvkm/engine/disp/gm200.o nvkm-y += nvkm/engine/disp/gp100.o nvkm-y += nvkm/engine/disp/gp102.o +nvkm-y += nvkm/engine/disp/gv100.o nvkm-y += nvkm/engine/disp/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 @@ -35,6 +37,7 @@ 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/sorgv100.o nvkm-y += nvkm/engine/disp/outp.o nvkm-y += nvkm/engine/disp/dp.o @@ -47,6 +50,7 @@ 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/hdmigv100.o nvkm-y += nvkm/engine/disp/conn.o @@ -63,57 +67,49 @@ nvkm-y += nvkm/engine/disp/rootgm107.o nvkm-y += nvkm/engine/disp/rootgm200.o nvkm-y += nvkm/engine/disp/rootgp100.o nvkm-y += nvkm/engine/disp/rootgp102.o +nvkm-y += nvkm/engine/disp/rootgv100.o nvkm-y += nvkm/engine/disp/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/basegt200.o -nvkm-y += nvkm/engine/disp/basegt215.o nvkm-y += nvkm/engine/disp/basegf119.o -nvkm-y += nvkm/engine/disp/basegk104.o -nvkm-y += nvkm/engine/disp/basegk110.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/coregt200.o -nvkm-y += nvkm/engine/disp/coregt215.o nvkm-y += nvkm/engine/disp/coregf119.o nvkm-y += nvkm/engine/disp/coregk104.o -nvkm-y += nvkm/engine/disp/coregk110.o -nvkm-y += nvkm/engine/disp/coregm107.o -nvkm-y += nvkm/engine/disp/coregm200.o -nvkm-y += nvkm/engine/disp/coregp100.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/ovlygt215.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/cursg84.o -nvkm-y += nvkm/engine/disp/cursgt215.o nvkm-y += nvkm/engine/disp/cursgf119.o -nvkm-y += nvkm/engine/disp/cursgk104.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/oimmg84.o -nvkm-y += nvkm/engine/disp/oimmgt215.o nvkm-y += nvkm/engine/disp/oimmgf119.o -nvkm-y += nvkm/engine/disp/oimmgk104.o nvkm-y += nvkm/engine/disp/oimmgp102.o diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/base.c index 93a75e5b2791..32fa94a9773f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/base.c @@ -220,6 +220,9 @@ nvkm_disp_fini(struct nvkm_engine *engine, bool suspend) struct nvkm_conn *conn; struct nvkm_outp *outp; + if (disp->func->fini) + disp->func->fini(disp); + list_for_each_entry(outp, &disp->outp, head) { nvkm_outp_fini(outp); } @@ -237,6 +240,7 @@ nvkm_disp_init(struct nvkm_engine *engine) struct nvkm_disp *disp = nvkm_disp(engine); struct nvkm_conn *conn; struct nvkm_outp *outp; + struct nvkm_ior *ior; list_for_each_entry(conn, &disp->conn, head) { nvkm_conn_init(conn); @@ -246,6 +250,19 @@ nvkm_disp_init(struct nvkm_engine *engine) nvkm_outp_init(outp); } + if (disp->func->init) { + int ret = disp->func->init(disp); + if (ret) + return ret; + } + + /* Set 'normal' (ie. when it's attached to a head) state for + * each output resource to 'fully enabled'. + */ + list_for_each_entry(ior, &disp->ior, head) { + ior->func->power(ior, true, true, true, true, true); + } + return 0; } @@ -376,6 +393,12 @@ nvkm_disp_oneinit(struct nvkm_engine *engine) if (ret) return ret; + if (disp->func->oneinit) { + ret = disp->func->oneinit(disp); + if (ret) + return ret; + } + i = 0; list_for_each_entry(head, &disp->head, head) i = max(i, head->id + 1); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/baseg84.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/baseg84.c index 6d17630a3dee..01253f4a9946 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/baseg84.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/baseg84.c @@ -21,10 +21,7 @@ * * Authors: Ben Skeggs */ -#include "dmacnv50.h" -#include "rootnv50.h" - -#include <nvif/class.h> +#include "channv50.h" static const struct nv50_disp_mthd_list g84_disp_base_mthd_base = { @@ -56,8 +53,8 @@ g84_disp_base_mthd_base = { } }; -const struct nv50_disp_chan_mthd -g84_disp_base_chan_mthd = { +static const struct nv50_disp_chan_mthd +g84_disp_base_mthd = { .name = "Base", .addr = 0x000540, .prev = 0x000004, @@ -68,13 +65,10 @@ g84_disp_base_chan_mthd = { } }; -const struct nv50_disp_dmac_oclass -g84_disp_base_oclass = { - .base.oclass = G82_DISP_BASE_CHANNEL_DMA, - .base.minver = 0, - .base.maxver = 0, - .ctor = nv50_disp_base_new, - .func = &nv50_disp_dmac_func, - .mthd = &g84_disp_base_chan_mthd, - .chid = 1, -}; +int +g84_disp_base_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, + struct nv50_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 index ebcb925e9d90..389e19dfc514 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/basegf119.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/basegf119.c @@ -21,10 +21,7 @@ * * Authors: Ben Skeggs */ -#include "dmacnv50.h" -#include "rootnv50.h" - -#include <nvif/class.h> +#include "channv50.h" static const struct nv50_disp_mthd_list gf119_disp_base_mthd_base = { @@ -91,7 +88,7 @@ gf119_disp_base_mthd_image = { }; const struct nv50_disp_chan_mthd -gf119_disp_base_chan_mthd = { +gf119_disp_base_mthd = { .name = "Base", .addr = 0x001000, .prev = -0x020000, @@ -102,13 +99,10 @@ gf119_disp_base_chan_mthd = { } }; -const struct nv50_disp_dmac_oclass -gf119_disp_base_oclass = { - .base.oclass = GF110_DISP_BASE_CHANNEL_DMA, - .base.minver = 0, - .base.maxver = 0, - .ctor = nv50_disp_base_new, - .func = &gf119_disp_dmac_func, - .mthd = &gf119_disp_base_chan_mthd, - .chid = 1, -}; +int +gf119_disp_base_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, + struct nv50_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/basegk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/basegk104.c deleted file mode 100644 index 780a1d973634..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/basegk104.c +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2015 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 "dmacnv50.h" -#include "rootnv50.h" - -#include <nvif/class.h> - -const struct nv50_disp_dmac_oclass -gk104_disp_base_oclass = { - .base.oclass = GK104_DISP_BASE_CHANNEL_DMA, - .base.minver = 0, - .base.maxver = 0, - .ctor = nv50_disp_base_new, - .func = &gf119_disp_dmac_func, - .mthd = &gf119_disp_base_chan_mthd, - .chid = 1, -}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/basegk110.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/basegk110.c deleted file mode 100644 index d8bdd246c8ed..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/basegk110.c +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2015 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 "dmacnv50.h" -#include "rootnv50.h" - -#include <nvif/class.h> - -const struct nv50_disp_dmac_oclass -gk110_disp_base_oclass = { - .base.oclass = GK110_DISP_BASE_CHANNEL_DMA, - .base.minver = 0, - .base.maxver = 0, - .ctor = nv50_disp_base_new, - .func = &gf119_disp_dmac_func, - .mthd = &gf119_disp_base_chan_mthd, - .chid = 1, -}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/basegp102.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/basegp102.c index 8a3cdeef8d2c..0cb23d673aa0 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/basegp102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/basegp102.c @@ -21,18 +21,12 @@ * * Authors: Ben Skeggs <bskeggs@redhat.com> */ -#include "dmacnv50.h" -#include "rootnv50.h" +#include "channv50.h" -#include <nvif/class.h> - -const struct nv50_disp_dmac_oclass -gp102_disp_base_oclass = { - .base.oclass = GK110_DISP_BASE_CHANNEL_DMA, - .base.minver = 0, - .base.maxver = 0, - .ctor = nv50_disp_base_new, - .func = &gp102_disp_dmac_func, - .mthd = &gf119_disp_base_chan_mthd, - .chid = 1, -}; +int +gp102_disp_base_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, + struct nv50_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/basegt200.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/basegt200.c deleted file mode 100644 index 93451e46570c..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/basegt200.c +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2015 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 "dmacnv50.h" -#include "rootnv50.h" - -#include <nvif/class.h> - -const struct nv50_disp_dmac_oclass -gt200_disp_base_oclass = { - .base.oclass = GT200_DISP_BASE_CHANNEL_DMA, - .base.minver = 0, - .base.maxver = 0, - .ctor = nv50_disp_base_new, - .func = &nv50_disp_dmac_func, - .mthd = &g84_disp_base_chan_mthd, - .chid = 1, -}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/basegt215.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/basegt215.c deleted file mode 100644 index 08e2b1fa3806..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/basegt215.c +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2015 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 "dmacnv50.h" -#include "rootnv50.h" - -#include <nvif/class.h> - -const struct nv50_disp_dmac_oclass -gt215_disp_base_oclass = { - .base.oclass = GT214_DISP_BASE_CHANNEL_DMA, - .base.minver = 0, - .base.maxver = 0, - .ctor = nv50_disp_base_new, - .func = &nv50_disp_dmac_func, - .mthd = &g84_disp_base_chan_mthd, - .chid = 1, -}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/basenv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/basenv50.c index f1d6b820d482..19eb7dde01f2 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/basenv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/basenv50.c @@ -21,33 +21,30 @@ * * Authors: Ben Skeggs */ -#include "dmacnv50.h" +#include "channv50.h" #include "head.h" -#include "rootnv50.h" #include <core/client.h> -#include <nvif/class.h> #include <nvif/cl507c.h> #include <nvif/unpack.h> int -nv50_disp_base_new(const struct nv50_disp_dmac_func *func, - const struct nv50_disp_chan_mthd *mthd, - struct nv50_disp_root *root, int chid, - const struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +nv50_disp_base_new_(const struct nv50_disp_chan_func *func, + const struct nv50_disp_chan_mthd *mthd, + struct nv50_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 = data; + } *args = argv; struct nvkm_object *parent = oclass->parent; - struct nv50_disp *disp = root->disp; int head, ret = -ENOSYS; u64 push; - nvif_ioctl(parent, "create disp base channel dma size %d\n", size); - if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) { + 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); @@ -58,7 +55,7 @@ nv50_disp_base_new(const struct nv50_disp_dmac_func *func, } else return ret; - return nv50_disp_dmac_new_(func, mthd, root, chid + head, + return nv50_disp_dmac_new_(func, mthd, disp, chid + head, head, push, oclass, pobject); } @@ -102,7 +99,7 @@ nv50_disp_base_mthd_image = { }; static const struct nv50_disp_chan_mthd -nv50_disp_base_chan_mthd = { +nv50_disp_base_mthd = { .name = "Base", .addr = 0x000540, .prev = 0x000004, @@ -113,13 +110,10 @@ nv50_disp_base_chan_mthd = { } }; -const struct nv50_disp_dmac_oclass -nv50_disp_base_oclass = { - .base.oclass = NV50_DISP_BASE_CHANNEL_DMA, - .base.minver = 0, - .base.maxver = 0, - .ctor = nv50_disp_base_new, - .func = &nv50_disp_dmac_func, - .mthd = &nv50_disp_base_chan_mthd, - .chid = 1, -}; +int +nv50_disp_base_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, + struct nv50_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/changf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/changf119.c index 17a3d835cb42..29e6dd58ac48 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/changf119.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/changf119.c @@ -47,3 +47,16 @@ gf119_disp_chan_uevent = { .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->base.engine.subdev.device; + const u64 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/oimmg84.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/changv100.c index 5ad5d0f5db05..75247c9c7e10 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmg84.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/changv100.c @@ -1,5 +1,5 @@ /* - * Copyright 2012 Red Hat Inc. + * 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"), @@ -18,20 +18,17 @@ * 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 "rootnv50.h" - -#include <nvif/class.h> -const struct nv50_disp_pioc_oclass -g84_disp_oimm_oclass = { - .base.oclass = G82_DISP_OVERLAY, - .base.minver = 0, - .base.maxver = 0, - .ctor = nv50_disp_oimm_new, - .func = &nv50_disp_pioc_func, - .chid = { 5, 5 }, +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 index 723dcbde2ac2..57719f675eec 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.c @@ -26,6 +26,7 @@ #include <core/client.h> #include <core/notify.h> +#include <core/oproxy.h> #include <core/ramht.h> #include <engine/dma.h> @@ -65,7 +66,7 @@ nv50_disp_mthd_list(struct nv50_disp *disp, int debug, u32 base, int c, void nv50_disp_chan_mthd(struct nv50_disp_chan *chan, int debug) { - struct nv50_disp *disp = chan->root->disp; + struct nv50_disp *disp = chan->disp; struct nvkm_subdev *subdev = &disp->base.engine.subdev; const struct nv50_disp_chan_mthd *mthd = chan->mthd; const struct nv50_disp_mthd_list *list; @@ -154,13 +155,29 @@ nv50_disp_chan_uevent = { .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->base.engine.subdev.device; + const u64 mask = 0x00010001 << chan->chid.user; + const u64 data = en ? 0x00010000 : 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 nv50_disp *disp = chan->root->disp; - struct nvkm_device *device = disp->base.engine.subdev.device; - *data = nvkm_rd32(device, 0x640000 + (chan->chid.user * 0x1000) + addr); + struct nvkm_device *device = chan->disp->base.engine.subdev.device; + u64 size, base = chan->func->user(chan, &size); + *data = nvkm_rd32(device, base + addr); return 0; } @@ -168,9 +185,9 @@ static int nv50_disp_chan_wr32(struct nvkm_object *object, u64 addr, u32 data) { struct nv50_disp_chan *chan = nv50_disp_chan(object); - struct nv50_disp *disp = chan->root->disp; - struct nvkm_device *device = disp->base.engine.subdev.device; - nvkm_wr32(device, 0x640000 + (chan->chid.user * 0x1000) + addr, data); + struct nvkm_device *device = chan->disp->base.engine.subdev.device; + u64 size, base = chan->func->user(chan, &size); + nvkm_wr32(device, base + addr, data); return 0; } @@ -179,7 +196,7 @@ nv50_disp_chan_ntfy(struct nvkm_object *object, u32 type, struct nvkm_event **pevent) { struct nv50_disp_chan *chan = nv50_disp_chan(object); - struct nv50_disp *disp = chan->root->disp; + struct nv50_disp *disp = chan->disp; switch (type) { case NV50_DISP_CORE_CHANNEL_DMA_V0_NTFY_UEVENT: *pevent = &disp->uevent; @@ -195,34 +212,83 @@ 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 nv50_disp *disp = chan->root->disp; - struct nvkm_device *device = disp->base.engine.subdev.device; + struct nvkm_device *device = chan->disp->base.engine.subdev.device; + const u64 base = device->func->resource_addr(device, 0); *type = NVKM_OBJECT_MAP_IO; - *addr = device->func->resource_addr(device, 0) + - 0x640000 + (chan->chid.user * 0x1000); - *size = 0x001000; + *addr = base + chan->func->user(chan, size); return 0; } +struct nv50_disp_chan_object { + struct nvkm_oproxy oproxy; + struct nv50_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 *data, u32 size, struct nvkm_object **pobject) + void *argv, u32 argc, struct nvkm_object **pobject) { struct nv50_disp_chan *chan = nv50_disp_chan(oclass->parent); - return chan->func->child_new(chan, oclass, data, size, pobject); + struct nv50_disp *disp = chan->disp; + struct nvkm_device *device = disp->base.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 *oclass) + struct nvkm_oclass *sclass) { struct nv50_disp_chan *chan = nv50_disp_chan(object); - if (chan->func->child_get) { - int ret = chan->func->child_get(chan, index, oclass); - if (ret == 0) - oclass->ctor = nv50_disp_chan_child_new; - return ret; + struct nvkm_device *device = chan->disp->base.engine.subdev.device; + const struct nvkm_device_oclass *oclass = NULL; + + if (chan->func->bind) + sclass->engine = nvkm_device_engine(device, NVKM_ENGINE_DMAOBJ); + 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; } @@ -231,6 +297,7 @@ 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; } @@ -238,6 +305,7 @@ 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); } @@ -245,10 +313,11 @@ static void * nv50_disp_chan_dtor(struct nvkm_object *object) { struct nv50_disp_chan *chan = nv50_disp_chan(object); - struct nv50_disp *disp = chan->root->disp; + struct nv50_disp *disp = chan->disp; if (chan->chid.user >= 0) disp->chan[chan->chid.user] = NULL; - return chan->func->dtor ? chan->func->dtor(chan) : chan; + nvkm_memory_unref(&chan->memory); + return chan; } static const struct nvkm_object_func @@ -264,18 +333,22 @@ nv50_disp_chan = { }; int -nv50_disp_chan_ctor(const struct nv50_disp_chan_func *func, +nv50_disp_chan_new_(const struct nv50_disp_chan_func *func, const struct nv50_disp_chan_mthd *mthd, - struct nv50_disp_root *root, int ctrl, int user, int head, + struct nv50_disp *disp, int ctrl, int user, int head, const struct nvkm_oclass *oclass, - struct nv50_disp_chan *chan) + struct nvkm_object **pobject) { - struct nv50_disp *disp = root->disp; + 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->root = root; + chan->disp = disp; chan->chid.ctrl = ctrl; chan->chid.user = user; chan->head = head; @@ -287,20 +360,3 @@ nv50_disp_chan_ctor(const struct nv50_disp_chan_func *func, disp->chan[chan->chid.user] = chan; return 0; } - -int -nv50_disp_chan_new_(const struct nv50_disp_chan_func *func, - const struct nv50_disp_chan_mthd *mthd, - struct nv50_disp_root *root, 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; - - return nv50_disp_chan_ctor(func, mthd, root, ctrl, user, - head, oclass, chan); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.h index 40681db91a02..adc9d76d09cc 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.h @@ -4,11 +4,12 @@ #define nv50_disp_chan(p) container_of((p), struct nv50_disp_chan, object) #include <core/object.h> #include "nv50.h" +struct nv50_disp_root; struct nv50_disp_chan { const struct nv50_disp_chan_func *func; const struct nv50_disp_chan_mthd *mthd; - struct nv50_disp_root *root; + struct nv50_disp *disp; struct { int ctrl; @@ -17,36 +18,133 @@ struct nv50_disp_chan { int head; struct nvkm_object object; + + struct nvkm_memory *memory; + u64 push; }; struct nv50_disp_chan_func { - void *(*dtor)(struct nv50_disp_chan *); int (*init)(struct nv50_disp_chan *); void (*fini)(struct nv50_disp_chan *); - int (*child_get)(struct nv50_disp_chan *, int index, - struct nvkm_oclass *); - int (*child_new)(struct nv50_disp_chan *, const struct nvkm_oclass *, - void *data, u32 size, struct nvkm_object **); + 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); }; -int nv50_disp_chan_ctor(const struct nv50_disp_chan_func *, - const struct nv50_disp_chan_mthd *, - struct nv50_disp_root *, int ctrl, int user, int head, - const struct nvkm_oclass *, struct nv50_disp_chan *); int nv50_disp_chan_new_(const struct nv50_disp_chan_func *, const struct nv50_disp_chan_mthd *, - struct nv50_disp_root *, int ctrl, int user, int head, + struct nv50_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 *, + struct nv50_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 gf119_disp_pioc_func; - -extern const struct nvkm_event_func nv50_disp_chan_uevent; -int nv50_disp_chan_uevent_ctor(struct nvkm_object *, void *, u32, - struct nvkm_notify *); -void nv50_disp_chan_uevent_send(struct nv50_disp *, int); +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; -extern const struct nvkm_event_func gf119_disp_chan_uevent; +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 *, + struct nv50_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 *, + struct nv50_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 *, + struct nv50_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 *, + struct nv50_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 *, + struct nv50_disp *, int chid, + const struct nvkm_oclass *, void *argv, u32 argc, + struct nvkm_object **); + +int nv50_disp_curs_new(const struct nvkm_oclass *, void *, u32, + struct nv50_disp *, struct nvkm_object **); +int nv50_disp_oimm_new(const struct nvkm_oclass *, void *, u32, + struct nv50_disp *, struct nvkm_object **); +int nv50_disp_base_new(const struct nvkm_oclass *, void *, u32, + struct nv50_disp *, struct nvkm_object **); +int nv50_disp_core_new(const struct nvkm_oclass *, void *, u32, + struct nv50_disp *, struct nvkm_object **); +int nv50_disp_ovly_new(const struct nvkm_oclass *, void *, u32, + struct nv50_disp *, struct nvkm_object **); + +int g84_disp_base_new(const struct nvkm_oclass *, void *, u32, + struct nv50_disp *, struct nvkm_object **); +int g84_disp_core_new(const struct nvkm_oclass *, void *, u32, + struct nv50_disp *, struct nvkm_object **); +int g84_disp_ovly_new(const struct nvkm_oclass *, void *, u32, + struct nv50_disp *, struct nvkm_object **); + +int g94_disp_core_new(const struct nvkm_oclass *, void *, u32, + struct nv50_disp *, struct nvkm_object **); + +int gt200_disp_ovly_new(const struct nvkm_oclass *, void *, u32, + struct nv50_disp *, struct nvkm_object **); + +int gf119_disp_curs_new(const struct nvkm_oclass *, void *, u32, + struct nv50_disp *, struct nvkm_object **); +int gf119_disp_oimm_new(const struct nvkm_oclass *, void *, u32, + struct nv50_disp *, struct nvkm_object **); +int gf119_disp_base_new(const struct nvkm_oclass *, void *, u32, + struct nv50_disp *, struct nvkm_object **); +int gf119_disp_core_new(const struct nvkm_oclass *, void *, u32, + struct nv50_disp *, struct nvkm_object **); +int gf119_disp_ovly_new(const struct nvkm_oclass *, void *, u32, + struct nv50_disp *, struct nvkm_object **); + +int gk104_disp_core_new(const struct nvkm_oclass *, void *, u32, + struct nv50_disp *, struct nvkm_object **); +int gk104_disp_ovly_new(const struct nvkm_oclass *, void *, u32, + struct nv50_disp *, struct nvkm_object **); + +int gp102_disp_curs_new(const struct nvkm_oclass *, void *, u32, + struct nv50_disp *, struct nvkm_object **); +int gp102_disp_oimm_new(const struct nvkm_oclass *, void *, u32, + struct nv50_disp *, struct nvkm_object **); +int gp102_disp_base_new(const struct nvkm_oclass *, void *, u32, + struct nv50_disp *, struct nvkm_object **); +int gp102_disp_core_new(const struct nvkm_oclass *, void *, u32, + struct nv50_disp *, struct nvkm_object **); +int gp102_disp_ovly_new(const struct nvkm_oclass *, void *, u32, + struct nv50_disp *, struct nvkm_object **); + +int gv100_disp_curs_new(const struct nvkm_oclass *, void *, u32, + struct nv50_disp *, struct nvkm_object **); +int gv100_disp_wimm_new(const struct nvkm_oclass *, void *, u32, + struct nv50_disp *, struct nvkm_object **); +int gv100_disp_core_new(const struct nvkm_oclass *, void *, u32, + struct nv50_disp *, struct nvkm_object **); +int gv100_disp_wndw_new(const struct nvkm_oclass *, void *, u32, + struct nv50_disp *, struct nvkm_object **); struct nv50_disp_mthd_list { u32 mthd; @@ -76,64 +174,18 @@ 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 nv50_disp_chan_mthd g84_disp_core_chan_mthd; +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 nv50_disp_chan_mthd g84_disp_base_chan_mthd; -extern const struct nv50_disp_chan_mthd g84_disp_ovly_chan_mthd; -extern const struct nv50_disp_chan_mthd g94_disp_core_chan_mthd; +extern const struct nv50_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_chan_mthd; - -extern const struct nv50_disp_chan_mthd gk104_disp_core_chan_mthd; -extern const struct nv50_disp_chan_mthd gk104_disp_ovly_chan_mthd; - -struct nv50_disp_pioc_oclass { - int (*ctor)(const struct nv50_disp_chan_func *, - const struct nv50_disp_chan_mthd *, - struct nv50_disp_root *, int ctrl, int user, - const struct nvkm_oclass *, void *data, u32 size, - struct nvkm_object **); - struct nvkm_sclass base; - const struct nv50_disp_chan_func *func; - const struct nv50_disp_chan_mthd *mthd; - struct { - int ctrl; - int user; - } chid; -}; - -extern const struct nv50_disp_pioc_oclass nv50_disp_oimm_oclass; -extern const struct nv50_disp_pioc_oclass nv50_disp_curs_oclass; - -extern const struct nv50_disp_pioc_oclass g84_disp_oimm_oclass; -extern const struct nv50_disp_pioc_oclass g84_disp_curs_oclass; - -extern const struct nv50_disp_pioc_oclass gt215_disp_oimm_oclass; -extern const struct nv50_disp_pioc_oclass gt215_disp_curs_oclass; - -extern const struct nv50_disp_pioc_oclass gf119_disp_oimm_oclass; -extern const struct nv50_disp_pioc_oclass gf119_disp_curs_oclass; - -extern const struct nv50_disp_pioc_oclass gk104_disp_oimm_oclass; -extern const struct nv50_disp_pioc_oclass gk104_disp_curs_oclass; - -extern const struct nv50_disp_pioc_oclass gp102_disp_oimm_oclass; -extern const struct nv50_disp_pioc_oclass gp102_disp_curs_oclass; +extern const struct nv50_disp_chan_mthd gf119_disp_base_mthd; -int nv50_disp_curs_new(const struct nv50_disp_chan_func *, - const struct nv50_disp_chan_mthd *, - struct nv50_disp_root *, int ctrl, int user, - const struct nvkm_oclass *, void *data, u32 size, - struct nvkm_object **); -int nv50_disp_oimm_new(const struct nv50_disp_chan_func *, - const struct nv50_disp_chan_mthd *, - struct nv50_disp_root *, int ctrl, int user, - const struct nvkm_oclass *, void *data, u32 size, - struct nvkm_object **); +extern const struct nv50_disp_chan_mthd gk104_disp_core_mthd; +extern const struct nv50_disp_chan_mthd gk104_disp_ovly_mthd; #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/coreg84.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/coreg84.c index 1baa5c34b327..cfc54aad3e7c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/coreg84.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/coreg84.c @@ -21,10 +21,7 @@ * * Authors: Ben Skeggs */ -#include "dmacnv50.h" -#include "rootnv50.h" - -#include <nvif/class.h> +#include "channv50.h" const struct nv50_disp_mthd_list g84_disp_core_mthd_dac = { @@ -91,7 +88,7 @@ g84_disp_core_mthd_head = { }; const struct nv50_disp_chan_mthd -g84_disp_core_chan_mthd = { +g84_disp_core_mthd = { .name = "Core", .addr = 0x000000, .prev = 0x000004, @@ -105,13 +102,10 @@ g84_disp_core_chan_mthd = { } }; -const struct nv50_disp_dmac_oclass -g84_disp_core_oclass = { - .base.oclass = G82_DISP_CORE_CHANNEL_DMA, - .base.minver = 0, - .base.maxver = 0, - .ctor = nv50_disp_core_new, - .func = &nv50_disp_core_func, - .mthd = &g84_disp_core_chan_mthd, - .chid = 0, -}; +int +g84_disp_core_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, + struct nv50_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 index c65c9f3ff69f..e911925f1182 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/coreg94.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/coreg94.c @@ -21,10 +21,7 @@ * * Authors: Ben Skeggs */ -#include "dmacnv50.h" -#include "rootnv50.h" - -#include <nvif/class.h> +#include "channv50.h" static const struct nv50_disp_mthd_list g94_disp_core_mthd_sor = { @@ -37,7 +34,7 @@ g94_disp_core_mthd_sor = { }; const struct nv50_disp_chan_mthd -g94_disp_core_chan_mthd = { +g94_disp_core_mthd = { .name = "Core", .addr = 0x000000, .prev = 0x000004, @@ -51,13 +48,10 @@ g94_disp_core_chan_mthd = { } }; -const struct nv50_disp_dmac_oclass -g94_disp_core_oclass = { - .base.oclass = GT206_DISP_CORE_CHANNEL_DMA, - .base.minver = 0, - .base.maxver = 0, - .ctor = nv50_disp_core_new, - .func = &nv50_disp_core_func, - .mthd = &g94_disp_core_chan_mthd, - .chid = 0, -}; +int +g94_disp_core_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, + struct nv50_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 index 21fbf89b6319..d162b9cf4eac 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregf119.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregf119.c @@ -21,15 +21,10 @@ * * Authors: Ben Skeggs */ -#include "dmacnv50.h" -#include "rootnv50.h" +#include "channv50.h" -#include <core/client.h> #include <subdev/timer.h> -#include <nvif/class.h> -#include <nvif/unpack.h> - const struct nv50_disp_mthd_list gf119_disp_core_mthd_base = { .mthd = 0x0000, @@ -157,7 +152,7 @@ gf119_disp_core_mthd_head = { }; static const struct nv50_disp_chan_mthd -gf119_disp_core_chan_mthd = { +gf119_disp_core_mthd = { .name = "Core", .addr = 0x000000, .prev = -0x020000, @@ -172,10 +167,9 @@ gf119_disp_core_chan_mthd = { }; void -gf119_disp_core_fini(struct nv50_disp_dmac *chan) +gf119_disp_core_fini(struct nv50_disp_chan *chan) { - struct nv50_disp *disp = chan->base.root->disp; - struct nvkm_subdev *subdev = &disp->base.engine.subdev; + struct nvkm_subdev *subdev = &chan->disp->base.engine.subdev; struct nvkm_device *device = subdev->device; /* deactivate channel */ @@ -188,22 +182,14 @@ gf119_disp_core_fini(struct nv50_disp_dmac *chan) nvkm_error(subdev, "core fini: %08x\n", nvkm_rd32(device, 0x610490)); } - - /* disable error reporting and completion notification */ - nvkm_mask(device, 0x610090, 0x00000001, 0x00000000); - nvkm_mask(device, 0x6100a0, 0x00000001, 0x00000000); } static int -gf119_disp_core_init(struct nv50_disp_dmac *chan) +gf119_disp_core_init(struct nv50_disp_chan *chan) { - struct nv50_disp *disp = chan->base.root->disp; - struct nvkm_subdev *subdev = &disp->base.engine.subdev; + struct nvkm_subdev *subdev = &chan->disp->base.engine.subdev; struct nvkm_device *device = subdev->device; - /* enable error reporting */ - nvkm_mask(device, 0x6100a0, 0x00000001, 0x00000001); - /* initialise channel for dma command submission */ nvkm_wr32(device, 0x610494, chan->push); nvkm_wr32(device, 0x610498, 0x00010000); @@ -225,20 +211,19 @@ gf119_disp_core_init(struct nv50_disp_dmac *chan) return 0; } -const struct nv50_disp_dmac_func +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, }; -const struct nv50_disp_dmac_oclass -gf119_disp_core_oclass = { - .base.oclass = GF110_DISP_CORE_CHANNEL_DMA, - .base.minver = 0, - .base.maxver = 0, - .ctor = nv50_disp_core_new, - .func = &gf119_disp_core_func, - .mthd = &gf119_disp_core_chan_mthd, - .chid = 0, -}; +int +gf119_disp_core_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, + struct nv50_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 index 088ab222e823..5c800174e079 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregk104.c @@ -21,10 +21,7 @@ * * Authors: Ben Skeggs */ -#include "dmacnv50.h" -#include "rootnv50.h" - -#include <nvif/class.h> +#include "channv50.h" static const struct nv50_disp_mthd_list gk104_disp_core_mthd_head = { @@ -106,7 +103,7 @@ gk104_disp_core_mthd_head = { }; const struct nv50_disp_chan_mthd -gk104_disp_core_chan_mthd = { +gk104_disp_core_mthd = { .name = "Core", .addr = 0x000000, .prev = -0x020000, @@ -120,13 +117,10 @@ gk104_disp_core_chan_mthd = { } }; -const struct nv50_disp_dmac_oclass -gk104_disp_core_oclass = { - .base.oclass = GK104_DISP_CORE_CHANNEL_DMA, - .base.minver = 0, - .base.maxver = 0, - .ctor = nv50_disp_core_new, - .func = &gf119_disp_core_func, - .mthd = &gk104_disp_core_chan_mthd, - .chid = 0, -}; +int +gk104_disp_core_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, + struct nv50_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/coregk110.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregk110.c deleted file mode 100644 index df0f45c20108..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregk110.c +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2015 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 "dmacnv50.h" -#include "rootnv50.h" - -#include <nvif/class.h> - -const struct nv50_disp_dmac_oclass -gk110_disp_core_oclass = { - .base.oclass = GK110_DISP_CORE_CHANNEL_DMA, - .base.minver = 0, - .base.maxver = 0, - .ctor = nv50_disp_core_new, - .func = &gf119_disp_core_func, - .mthd = &gk104_disp_core_chan_mthd, - .chid = 0, -}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregm107.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregm107.c deleted file mode 100644 index 9e27f8fd98b6..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregm107.c +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2015 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 "dmacnv50.h" -#include "rootnv50.h" - -#include <nvif/class.h> - -const struct nv50_disp_dmac_oclass -gm107_disp_core_oclass = { - .base.oclass = GM107_DISP_CORE_CHANNEL_DMA, - .base.minver = 0, - .base.maxver = 0, - .ctor = nv50_disp_core_new, - .func = &gf119_disp_core_func, - .mthd = &gk104_disp_core_chan_mthd, - .chid = 0, -}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregm200.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregm200.c deleted file mode 100644 index bb23a8658ac0..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregm200.c +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2015 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 "dmacnv50.h" -#include "rootnv50.h" - -#include <nvif/class.h> - -const struct nv50_disp_dmac_oclass -gm200_disp_core_oclass = { - .base.oclass = GM200_DISP_CORE_CHANNEL_DMA, - .base.minver = 0, - .base.maxver = 0, - .ctor = nv50_disp_core_new, - .func = &gf119_disp_core_func, - .mthd = &gk104_disp_core_chan_mthd, - .chid = 0, -}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregp100.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregp100.c deleted file mode 100644 index d5dff6619d4d..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregp100.c +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2015 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 "dmacnv50.h" -#include "rootnv50.h" - -#include <nvif/class.h> - -const struct nv50_disp_dmac_oclass -gp100_disp_core_oclass = { - .base.oclass = GP100_DISP_CORE_CHANNEL_DMA, - .base.minver = 0, - .base.maxver = 0, - .ctor = nv50_disp_core_new, - .func = &gf119_disp_core_func, - .mthd = &gk104_disp_core_chan_mthd, - .chid = 0, -}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregp102.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregp102.c index b0df4b752b8c..5b7f993c73c7 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregp102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregp102.c @@ -21,23 +21,16 @@ * * Authors: Ben Skeggs <bskeggs@redhat.com> */ -#include "dmacnv50.h" -#include "rootnv50.h" +#include "channv50.h" #include <subdev/timer.h> -#include <nvif/class.h> - static int -gp102_disp_core_init(struct nv50_disp_dmac *chan) +gp102_disp_core_init(struct nv50_disp_chan *chan) { - struct nv50_disp *disp = chan->base.root->disp; - struct nvkm_subdev *subdev = &disp->base.engine.subdev; + struct nvkm_subdev *subdev = &chan->disp->base.engine.subdev; struct nvkm_device *device = subdev->device; - /* enable error reporting */ - nvkm_mask(device, 0x6100a0, 0x00000001, 0x00000001); - /* initialise channel for dma command submission */ nvkm_wr32(device, 0x611494, chan->push); nvkm_wr32(device, 0x611498, 0x00010000); @@ -59,20 +52,19 @@ gp102_disp_core_init(struct nv50_disp_dmac *chan) return 0; } -static const struct nv50_disp_dmac_func +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, }; -const struct nv50_disp_dmac_oclass -gp102_disp_core_oclass = { - .base.oclass = GP102_DISP_CORE_CHANNEL_DMA, - .base.minver = 0, - .base.maxver = 0, - .ctor = nv50_disp_core_new, - .func = &gp102_disp_core_func, - .mthd = &gk104_disp_core_chan_mthd, - .chid = 0, -}; +int +gp102_disp_core_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, + struct nv50_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/coregt200.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregt200.c deleted file mode 100644 index b234547708fc..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregt200.c +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2015 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 "dmacnv50.h" -#include "rootnv50.h" - -#include <nvif/class.h> - -const struct nv50_disp_dmac_oclass -gt200_disp_core_oclass = { - .base.oclass = GT200_DISP_CORE_CHANNEL_DMA, - .base.minver = 0, - .base.maxver = 0, - .ctor = nv50_disp_core_new, - .func = &nv50_disp_core_func, - .mthd = &g84_disp_core_chan_mthd, - .chid = 0, -}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregt215.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregt215.c deleted file mode 100644 index 8f5ba2018975..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregt215.c +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2015 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 "dmacnv50.h" -#include "rootnv50.h" - -#include <nvif/class.h> - -const struct nv50_disp_dmac_oclass -gt215_disp_core_oclass = { - .base.oclass = GT214_DISP_CORE_CHANNEL_DMA, - .base.minver = 0, - .base.maxver = 0, - .ctor = nv50_disp_core_new, - .func = &nv50_disp_core_func, - .mthd = &g94_disp_core_chan_mthd, - .chid = 0, -}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregv100.c new file mode 100644 index 000000000000..4592d0e69fec --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregv100.c @@ -0,0 +1,204 @@ +/* + * 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> + +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 }, + {} + } +}; + +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 }, + { 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->base.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->base.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->base.engine.subdev.device; + nvkm_mask(device, 0x6104e0, 0x00000010, 0x00000000); + gv100_disp_core_idle(chan); + nvkm_mask(device, 0x6104e0, 0x00000002, 0x00000000); +} + +static int +gv100_disp_core_init(struct nv50_disp_chan *chan) +{ + struct nvkm_subdev *subdev = &chan->disp->base.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, 0x00000000); + 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 nv50_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 index b547c8b833ca..55db9a22b4be 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/corenv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/corenv50.c @@ -21,32 +21,30 @@ * * Authors: Ben Skeggs */ -#include "dmacnv50.h" -#include "rootnv50.h" +#include "channv50.h" #include <core/client.h> #include <subdev/timer.h> -#include <nvif/class.h> #include <nvif/cl507d.h> #include <nvif/unpack.h> int -nv50_disp_core_new(const struct nv50_disp_dmac_func *func, - const struct nv50_disp_chan_mthd *mthd, - struct nv50_disp_root *root, int chid, - const struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +nv50_disp_core_new_(const struct nv50_disp_chan_func *func, + const struct nv50_disp_chan_mthd *mthd, + struct nv50_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 = data; + } *args = argv; struct nvkm_object *parent = oclass->parent; u64 push; int ret = -ENOSYS; - nvif_ioctl(parent, "create disp core channel dma size %d\n", size); - if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) { + 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); @@ -54,7 +52,7 @@ nv50_disp_core_new(const struct nv50_disp_dmac_func *func, } else return ret; - return nv50_disp_dmac_new_(func, mthd, root, chid, 0, + return nv50_disp_dmac_new_(func, mthd, disp, chid, 0, push, oclass, pobject); } @@ -151,7 +149,7 @@ nv50_disp_core_mthd_head = { }; static const struct nv50_disp_chan_mthd -nv50_disp_core_chan_mthd = { +nv50_disp_core_mthd = { .name = "Core", .addr = 0x000000, .prev = 0x000004, @@ -166,10 +164,9 @@ nv50_disp_core_chan_mthd = { }; static void -nv50_disp_core_fini(struct nv50_disp_dmac *chan) +nv50_disp_core_fini(struct nv50_disp_chan *chan) { - struct nv50_disp *disp = chan->base.root->disp; - struct nvkm_subdev *subdev = &disp->base.engine.subdev; + struct nvkm_subdev *subdev = &chan->disp->base.engine.subdev; struct nvkm_device *device = subdev->device; /* deactivate channel */ @@ -182,21 +179,14 @@ nv50_disp_core_fini(struct nv50_disp_dmac *chan) nvkm_error(subdev, "core fini: %08x\n", nvkm_rd32(device, 0x610200)); } - - /* disable error reporting and completion notifications */ - nvkm_mask(device, 0x610028, 0x00010001, 0x00000000); } static int -nv50_disp_core_init(struct nv50_disp_dmac *chan) +nv50_disp_core_init(struct nv50_disp_chan *chan) { - struct nv50_disp *disp = chan->base.root->disp; - struct nvkm_subdev *subdev = &disp->base.engine.subdev; + struct nvkm_subdev *subdev = &chan->disp->base.engine.subdev; struct nvkm_device *device = subdev->device; - /* enable error reporting */ - nvkm_mask(device, 0x610028, 0x00010000, 0x00010000); - /* attempt to unstick channel from some unknown state */ if ((nvkm_rd32(device, 0x610200) & 0x009f0000) == 0x00020000) nvkm_mask(device, 0x610200, 0x00800000, 0x00800000); @@ -224,20 +214,19 @@ nv50_disp_core_init(struct nv50_disp_dmac *chan) return 0; } -const struct nv50_disp_dmac_func +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, }; -const struct nv50_disp_dmac_oclass -nv50_disp_core_oclass = { - .base.oclass = NV50_DISP_CORE_CHANNEL_DMA, - .base.minver = 0, - .base.maxver = 0, - .ctor = nv50_disp_core_new, - .func = &nv50_disp_core_func, - .mthd = &nv50_disp_core_chan_mthd, - .chid = 0, -}; +int +nv50_disp_core_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, + struct nv50_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 index 2be6fb052c65..cdda3658dcb3 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgf119.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgf119.c @@ -22,16 +22,11 @@ * Authors: Ben Skeggs */ #include "channv50.h" -#include "rootnv50.h" -#include <nvif/class.h> - -const struct nv50_disp_pioc_oclass -gf119_disp_curs_oclass = { - .base.oclass = GF110_DISP_CURSOR, - .base.minver = 0, - .base.maxver = 0, - .ctor = nv50_disp_curs_new, - .func = &gf119_disp_pioc_func, - .chid = { 13, 13 }, -}; +int +gf119_disp_curs_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, + struct nv50_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/cursgk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgk104.c deleted file mode 100644 index 2a99db4bf8f8..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgk104.c +++ /dev/null @@ -1,37 +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 "rootnv50.h" - -#include <nvif/class.h> - -const struct nv50_disp_pioc_oclass -gk104_disp_curs_oclass = { - .base.oclass = GK104_DISP_CURSOR, - .base.minver = 0, - .base.maxver = 0, - .ctor = nv50_disp_curs_new, - .func = &gf119_disp_pioc_func, - .chid = { 13, 13 }, -}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgp102.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgp102.c index e958210d8105..1a4601f975e6 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgp102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgp102.c @@ -22,16 +22,11 @@ * Authors: Ben Skeggs <bskeggs@redhat.com> */ #include "channv50.h" -#include "rootnv50.h" -#include <nvif/class.h> - -const struct nv50_disp_pioc_oclass -gp102_disp_curs_oclass = { - .base.oclass = GK104_DISP_CURSOR, - .base.minver = 0, - .base.maxver = 0, - .ctor = nv50_disp_curs_new, - .func = &gf119_disp_pioc_func, - .chid = { 13, 17 }, -}; +int +gp102_disp_curs_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, + struct nv50_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/cursgt215.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgt215.c deleted file mode 100644 index 00a7f3564450..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgt215.c +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2015 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 "rootnv50.h" - -#include <nvif/class.h> - -const struct nv50_disp_pioc_oclass -gt215_disp_curs_oclass = { - .base.oclass = GT214_DISP_CURSOR, - .base.minver = 0, - .base.maxver = 0, - .ctor = nv50_disp_curs_new, - .func = &nv50_disp_pioc_func, - .chid = { 7, 7 }, -}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgv100.c new file mode 100644 index 000000000000..a3e4f6900245 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgv100.c @@ -0,0 +1,81 @@ +/* + * 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->base.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->base.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->base.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->base.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 nv50_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 index ab51121b7982..d29758504a5f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursnv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursnv50.c @@ -23,30 +23,26 @@ */ #include "channv50.h" #include "head.h" -#include "rootnv50.h" #include <core/client.h> -#include <nvif/class.h> #include <nvif/cl507a.h> #include <nvif/unpack.h> int -nv50_disp_curs_new(const struct nv50_disp_chan_func *func, - const struct nv50_disp_chan_mthd *mthd, - struct nv50_disp_root *root, int ctrl, int user, - const struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +nv50_disp_curs_new_(const struct nv50_disp_chan_func *func, + struct nv50_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 = data; + } *args = argv; struct nvkm_object *parent = oclass->parent; - struct nv50_disp *disp = root->disp; int head, ret = -ENOSYS; - nvif_ioctl(parent, "create disp cursor size %d\n", size); - if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) { + 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->base, args->v0.head)) @@ -55,16 +51,14 @@ nv50_disp_curs_new(const struct nv50_disp_chan_func *func, } else return ret; - return nv50_disp_chan_new_(func, mthd, root, ctrl + head, user + head, + return nv50_disp_chan_new_(func, NULL, disp, ctrl + head, user + head, head, oclass, pobject); } -const struct nv50_disp_pioc_oclass -nv50_disp_curs_oclass = { - .base.oclass = NV50_DISP_CURSOR, - .base.minver = 0, - .base.maxver = 0, - .ctor = nv50_disp_curs_new, - .func = &nv50_disp_pioc_func, - .chid = { 7, 7 }, -}; +int +nv50_disp_curs_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, + struct nv50_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 index dbd032ef352a..71a94777ea2e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dacgf119.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dacgf119.c @@ -58,8 +58,13 @@ gf119_dac = { int gf119_dac_new(struct nvkm_disp *disp, int id) { - struct nvkm_device *device = disp->engine.subdev.device; - if (!(nvkm_rd32(device, 0x612004) & (0x00000010 << id))) - return 0; 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 index 85e692b12260..558012db35f8 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dacnv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dacnv50.c @@ -109,8 +109,13 @@ nv50_dac = { int nv50_dac_new(struct nvkm_disp *disp, int id) { - struct nvkm_device *device = disp->engine.subdev.device; - if (!(nvkm_rd32(device, 0x610184) & (0x00100000 << id))) - return 0; 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 index ce7cd74fbd5d..edf7dd0d931d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgf119.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgf119.c @@ -21,29 +21,27 @@ * * Authors: Ben Skeggs */ -#include "dmacnv50.h" -#include "rootnv50.h" +#include "channv50.h" #include <core/ramht.h> #include <subdev/timer.h> int -gf119_disp_dmac_bind(struct nv50_disp_dmac *chan, +gf119_disp_dmac_bind(struct nv50_disp_chan *chan, struct nvkm_object *object, u32 handle) { - return nvkm_ramht_insert(chan->base.root->ramht, object, - chan->base.chid.user, -9, handle, - chan->base.chid.user << 27 | 0x00000001); + 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_dmac *chan) +gf119_disp_dmac_fini(struct nv50_disp_chan *chan) { - struct nv50_disp *disp = chan->base.root->disp; - struct nvkm_subdev *subdev = &disp->base.engine.subdev; + struct nvkm_subdev *subdev = &chan->disp->base.engine.subdev; struct nvkm_device *device = subdev->device; - int ctrl = chan->base.chid.ctrl; - int user = chan->base.chid.user; + int ctrl = chan->chid.ctrl; + int user = chan->chid.user; /* deactivate channel */ nvkm_mask(device, 0x610490 + (ctrl * 0x0010), 0x00001010, 0x00001000); @@ -55,23 +53,15 @@ gf119_disp_dmac_fini(struct nv50_disp_dmac *chan) nvkm_error(subdev, "ch %d fini: %08x\n", user, nvkm_rd32(device, 0x610490 + (ctrl * 0x10))); } - - /* disable error reporting and completion notification */ - nvkm_mask(device, 0x610090, 0x00000001 << user, 0x00000000); - nvkm_mask(device, 0x6100a0, 0x00000001 << user, 0x00000000); } static int -gf119_disp_dmac_init(struct nv50_disp_dmac *chan) +gf119_disp_dmac_init(struct nv50_disp_chan *chan) { - struct nv50_disp *disp = chan->base.root->disp; - struct nvkm_subdev *subdev = &disp->base.engine.subdev; + struct nvkm_subdev *subdev = &chan->disp->base.engine.subdev; struct nvkm_device *device = subdev->device; - int ctrl = chan->base.chid.ctrl; - int user = chan->base.chid.user; - - /* enable error reporting */ - nvkm_mask(device, 0x6100a0, 0x00000001 << user, 0x00000001 << user); + int ctrl = chan->chid.ctrl; + int user = chan->chid.user; /* initialise channel for dma command submission */ nvkm_wr32(device, 0x610494 + (ctrl * 0x0010), chan->push); @@ -94,9 +84,11 @@ gf119_disp_dmac_init(struct nv50_disp_dmac *chan) return 0; } -const struct nv50_disp_dmac_func +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 index cdead9500343..f21a433199aa 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgp102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgp102.c @@ -21,22 +21,17 @@ * * Authors: Ben Skeggs <bskeggs@redhat.com> */ -#include "dmacnv50.h" -#include "rootnv50.h" +#include "channv50.h" #include <subdev/timer.h> static int -gp102_disp_dmac_init(struct nv50_disp_dmac *chan) +gp102_disp_dmac_init(struct nv50_disp_chan *chan) { - struct nv50_disp *disp = chan->base.root->disp; - struct nvkm_subdev *subdev = &disp->base.engine.subdev; + struct nvkm_subdev *subdev = &chan->disp->base.engine.subdev; struct nvkm_device *device = subdev->device; - int ctrl = chan->base.chid.ctrl; - int user = chan->base.chid.user; - - /* enable error reporting */ - nvkm_mask(device, 0x6100a0, 0x00000001 << user, 0x00000001 << user); + int ctrl = chan->chid.ctrl; + int user = chan->chid.user; /* initialise channel for dma command submission */ nvkm_wr32(device, 0x611494 + (ctrl * 0x0010), chan->push); @@ -59,9 +54,11 @@ gp102_disp_dmac_init(struct nv50_disp_dmac *chan) return 0; } -const struct nv50_disp_dmac_func +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 new file mode 100644 index 000000000000..eac0e42da354 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgv100.c @@ -0,0 +1,77 @@ +/* + * Copyright 2018 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ +#include "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->base.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->base.engine.subdev.device; + 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); +} + +int +gv100_disp_dmac_init(struct nv50_disp_chan *chan) +{ + struct nvkm_subdev *subdev = &chan->disp->base.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, 0x00000000); + 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 index 070ec5e18fdb..9e8a9d7a9b68 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacnv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacnv50.c @@ -21,176 +21,68 @@ * * Authors: Ben Skeggs */ -#include "dmacnv50.h" -#include "rootnv50.h" +#include "channv50.h" #include <core/client.h> -#include <core/oproxy.h> #include <core/ramht.h> #include <subdev/fb.h> +#include <subdev/mmu.h> #include <subdev/timer.h> #include <engine/dma.h> -struct nv50_disp_dmac_object { - struct nvkm_oproxy oproxy; - struct nv50_disp_root *root; - int hash; -}; - -static void -nv50_disp_dmac_child_del_(struct nvkm_oproxy *base) -{ - struct nv50_disp_dmac_object *object = - container_of(base, typeof(*object), oproxy); - nvkm_ramht_remove(object->root->ramht, object->hash); -} - -static const struct nvkm_oproxy_func -nv50_disp_dmac_child_func_ = { - .dtor[0] = nv50_disp_dmac_child_del_, -}; - -static int -nv50_disp_dmac_child_new_(struct nv50_disp_chan *base, - const struct nvkm_oclass *oclass, - void *data, u32 size, struct nvkm_object **pobject) -{ - struct nv50_disp_dmac *chan = nv50_disp_dmac(base); - struct nv50_disp_root *root = chan->base.root; - struct nvkm_device *device = root->disp->base.engine.subdev.device; - const struct nvkm_device_oclass *sclass = oclass->priv; - struct nv50_disp_dmac_object *object; - int ret; - - if (!(object = kzalloc(sizeof(*object), GFP_KERNEL))) - return -ENOMEM; - nvkm_oproxy_ctor(&nv50_disp_dmac_child_func_, oclass, &object->oproxy); - object->root = root; - *pobject = &object->oproxy.base; - - ret = sclass->ctor(device, oclass, data, size, &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_dmac_child_get_(struct nv50_disp_chan *base, int index, - struct nvkm_oclass *sclass) -{ - struct nv50_disp_dmac *chan = nv50_disp_dmac(base); - struct nv50_disp *disp = chan->base.root->disp; - struct nvkm_device *device = disp->base.engine.subdev.device; - const struct nvkm_device_oclass *oclass = NULL; - - sclass->engine = nvkm_device_engine(device, NVKM_ENGINE_DMAOBJ); - if (sclass->engine && sclass->engine->func->base.sclass) { - sclass->engine->func->base.sclass(sclass, index, &oclass); - if (oclass) { - sclass->priv = oclass; - return 0; - } - } - - return -EINVAL; -} - -static void -nv50_disp_dmac_fini_(struct nv50_disp_chan *base) -{ - struct nv50_disp_dmac *chan = nv50_disp_dmac(base); - chan->func->fini(chan); -} - -static int -nv50_disp_dmac_init_(struct nv50_disp_chan *base) -{ - struct nv50_disp_dmac *chan = nv50_disp_dmac(base); - return chan->func->init(chan); -} - -static void * -nv50_disp_dmac_dtor_(struct nv50_disp_chan *base) -{ - return nv50_disp_dmac(base); -} - -static const struct nv50_disp_chan_func -nv50_disp_dmac_func_ = { - .dtor = nv50_disp_dmac_dtor_, - .init = nv50_disp_dmac_init_, - .fini = nv50_disp_dmac_fini_, - .child_get = nv50_disp_dmac_child_get_, - .child_new = nv50_disp_dmac_child_new_, -}; - int -nv50_disp_dmac_new_(const struct nv50_disp_dmac_func *func, +nv50_disp_dmac_new_(const struct nv50_disp_chan_func *func, const struct nv50_disp_chan_mthd *mthd, - struct nv50_disp_root *root, int chid, int head, u64 push, + struct nv50_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_dmaobj *dmaobj; - struct nv50_disp_dmac *chan; + struct nv50_disp_chan *chan; int ret; - if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL))) - return -ENOMEM; - *pobject = &chan->base.object; - chan->func = func; - - ret = nv50_disp_chan_ctor(&nv50_disp_dmac_func_, mthd, root, - chid, chid, head, oclass, &chan->base); + ret = nv50_disp_chan_new_(func, mthd, disp, chid, chid, head, oclass, + pobject); + chan = nv50_disp_chan(*pobject); if (ret) return ret; - dmaobj = nvkm_dmaobj_search(client, push); - if (IS_ERR(dmaobj)) - return PTR_ERR(dmaobj); + chan->memory = nvkm_umem_search(client, push); + if (IS_ERR(chan->memory)) + return PTR_ERR(chan->memory); - if (dmaobj->limit - dmaobj->start != 0xfff) + if (nvkm_memory_size(chan->memory) < 0x1000) return -EINVAL; - switch (dmaobj->target) { - case NV_MEM_TARGET_VRAM: - chan->push = 0x00000001 | dmaobj->start >> 8; - break; - case NV_MEM_TARGET_PCI_NOSNOOP: - chan->push = 0x00000003 | dmaobj->start >> 8; - break; + 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_dmac *chan, +nv50_disp_dmac_bind(struct nv50_disp_chan *chan, struct nvkm_object *object, u32 handle) { - return nvkm_ramht_insert(chan->base.root->ramht, object, - chan->base.chid.user, -10, handle, - chan->base.chid.user << 28 | - chan->base.chid.user); + 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_dmac *chan) +nv50_disp_dmac_fini(struct nv50_disp_chan *chan) { - struct nv50_disp *disp = chan->base.root->disp; - struct nvkm_subdev *subdev = &disp->base.engine.subdev; + struct nvkm_subdev *subdev = &chan->disp->base.engine.subdev; struct nvkm_device *device = subdev->device; - int ctrl = chan->base.chid.ctrl; - int user = chan->base.chid.user; + int ctrl = chan->chid.ctrl; + int user = chan->chid.user; /* deactivate channel */ nvkm_mask(device, 0x610200 + (ctrl * 0x0010), 0x00001010, 0x00001000); @@ -202,22 +94,15 @@ nv50_disp_dmac_fini(struct nv50_disp_dmac *chan) nvkm_error(subdev, "ch %d fini timeout, %08x\n", user, nvkm_rd32(device, 0x610200 + (ctrl * 0x10))); } - - /* disable error reporting and completion notifications */ - nvkm_mask(device, 0x610028, 0x00010001 << user, 0x00000000 << user); } static int -nv50_disp_dmac_init(struct nv50_disp_dmac *chan) +nv50_disp_dmac_init(struct nv50_disp_chan *chan) { - struct nv50_disp *disp = chan->base.root->disp; - struct nvkm_subdev *subdev = &disp->base.engine.subdev; + struct nvkm_subdev *subdev = &chan->disp->base.engine.subdev; struct nvkm_device *device = subdev->device; - int ctrl = chan->base.chid.ctrl; - int user = chan->base.chid.user; - - /* enable error reporting */ - nvkm_mask(device, 0x610028, 0x00010000 << user, 0x00010000 << user); + int ctrl = chan->chid.ctrl; + int user = chan->chid.user; /* initialise channel for dma command submission */ nvkm_wr32(device, 0x610204 + (ctrl * 0x0010), chan->push); @@ -240,9 +125,11 @@ nv50_disp_dmac_init(struct nv50_disp_dmac *chan) return 0; } -const struct nv50_disp_dmac_func +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/dmacnv50.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacnv50.h deleted file mode 100644 index f9b98211da6a..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacnv50.h +++ /dev/null @@ -1,102 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef __NV50_DISP_DMAC_H__ -#define __NV50_DISP_DMAC_H__ -#define nv50_disp_dmac(p) container_of((p), struct nv50_disp_dmac, base) -#include "channv50.h" - -struct nv50_disp_dmac { - const struct nv50_disp_dmac_func *func; - struct nv50_disp_chan base; - u32 push; -}; - -struct nv50_disp_dmac_func { - int (*init)(struct nv50_disp_dmac *); - void (*fini)(struct nv50_disp_dmac *); - int (*bind)(struct nv50_disp_dmac *, struct nvkm_object *, u32 handle); -}; - -int nv50_disp_dmac_new_(const struct nv50_disp_dmac_func *, - const struct nv50_disp_chan_mthd *, - struct nv50_disp_root *, int chid, int head, u64 push, - const struct nvkm_oclass *, struct nvkm_object **); - -extern const struct nv50_disp_dmac_func nv50_disp_dmac_func; -int nv50_disp_dmac_bind(struct nv50_disp_dmac *, struct nvkm_object *, u32); -extern const struct nv50_disp_dmac_func nv50_disp_core_func; - -extern const struct nv50_disp_dmac_func gf119_disp_dmac_func; -void gf119_disp_dmac_fini(struct nv50_disp_dmac *); -int gf119_disp_dmac_bind(struct nv50_disp_dmac *, struct nvkm_object *, u32); -extern const struct nv50_disp_dmac_func gf119_disp_core_func; -void gf119_disp_core_fini(struct nv50_disp_dmac *); - -extern const struct nv50_disp_dmac_func gp102_disp_dmac_func; - -struct nv50_disp_dmac_oclass { - int (*ctor)(const struct nv50_disp_dmac_func *, - const struct nv50_disp_chan_mthd *, - struct nv50_disp_root *, int chid, - const struct nvkm_oclass *, void *data, u32 size, - struct nvkm_object **); - struct nvkm_sclass base; - const struct nv50_disp_dmac_func *func; - const struct nv50_disp_chan_mthd *mthd; - int chid; -}; - -int nv50_disp_core_new(const struct nv50_disp_dmac_func *, - const struct nv50_disp_chan_mthd *, - struct nv50_disp_root *, int chid, - const struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **); -int nv50_disp_base_new(const struct nv50_disp_dmac_func *, - const struct nv50_disp_chan_mthd *, - struct nv50_disp_root *, int chid, - const struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **); -int nv50_disp_ovly_new(const struct nv50_disp_dmac_func *, - const struct nv50_disp_chan_mthd *, - struct nv50_disp_root *, int chid, - const struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **); - -extern const struct nv50_disp_dmac_oclass nv50_disp_core_oclass; -extern const struct nv50_disp_dmac_oclass nv50_disp_base_oclass; -extern const struct nv50_disp_dmac_oclass nv50_disp_ovly_oclass; - -extern const struct nv50_disp_dmac_oclass g84_disp_core_oclass; -extern const struct nv50_disp_dmac_oclass g84_disp_base_oclass; -extern const struct nv50_disp_dmac_oclass g84_disp_ovly_oclass; - -extern const struct nv50_disp_dmac_oclass g94_disp_core_oclass; - -extern const struct nv50_disp_dmac_oclass gt200_disp_core_oclass; -extern const struct nv50_disp_dmac_oclass gt200_disp_base_oclass; -extern const struct nv50_disp_dmac_oclass gt200_disp_ovly_oclass; - -extern const struct nv50_disp_dmac_oclass gt215_disp_core_oclass; -extern const struct nv50_disp_dmac_oclass gt215_disp_base_oclass; -extern const struct nv50_disp_dmac_oclass gt215_disp_ovly_oclass; - -extern const struct nv50_disp_dmac_oclass gf119_disp_core_oclass; -extern const struct nv50_disp_dmac_oclass gf119_disp_base_oclass; -extern const struct nv50_disp_dmac_oclass gf119_disp_ovly_oclass; - -extern const struct nv50_disp_dmac_oclass gk104_disp_core_oclass; -extern const struct nv50_disp_dmac_oclass gk104_disp_base_oclass; -extern const struct nv50_disp_dmac_oclass gk104_disp_ovly_oclass; - -extern const struct nv50_disp_dmac_oclass gk110_disp_core_oclass; -extern const struct nv50_disp_dmac_oclass gk110_disp_base_oclass; - -extern const struct nv50_disp_dmac_oclass gm107_disp_core_oclass; - -extern const struct nv50_disp_dmac_oclass gm200_disp_core_oclass; - -extern const struct nv50_disp_dmac_oclass gp100_disp_core_oclass; - -extern const struct nv50_disp_dmac_oclass gp102_disp_core_oclass; -extern const struct nv50_disp_dmac_oclass gp102_disp_base_oclass; -extern const struct nv50_disp_dmac_oclass gp102_disp_ovly_oclass; -#endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/g84.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/g84.c index 842e1b72ee42..731f188fc1ee 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/g84.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/g84.c @@ -28,18 +28,20 @@ static const struct nv50_disp_func g84_disp = { + .init = nv50_disp_init, + .fini = nv50_disp_fini, .intr = nv50_disp_intr, .uevent = &nv50_disp_chan_uevent, .super = nv50_disp_super, .root = &g84_disp_root_oclass, - .head.new = nv50_head_new, - .dac = { .nr = 3, .new = nv50_dac_new }, - .sor = { .nr = 2, .new = g84_sor_new }, - .pior = { .nr = 3, .new = nv50_pior_new }, + .head = { .cnt = nv50_head_cnt, .new = nv50_head_new }, + .dac = { .cnt = nv50_dac_cnt, .new = nv50_dac_new }, + .sor = { .cnt = nv50_sor_cnt, .new = g84_sor_new }, + .pior = { .cnt = nv50_pior_cnt, .new = nv50_pior_new }, }; int g84_disp_new(struct nvkm_device *device, int index, struct nvkm_disp **pdisp) { - return nv50_disp_new_(&g84_disp, device, index, 2, pdisp); + return nv50_disp_new_(&g84_disp, device, index, pdisp); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/g94.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/g94.c index d184e6ab8918..def54fe1951e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/g94.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/g94.c @@ -28,18 +28,20 @@ static const struct nv50_disp_func g94_disp = { + .init = nv50_disp_init, + .fini = nv50_disp_fini, .intr = nv50_disp_intr, .uevent = &nv50_disp_chan_uevent, .super = nv50_disp_super, .root = &g94_disp_root_oclass, - .head.new = nv50_head_new, - .dac = { .nr = 3, .new = nv50_dac_new }, - .sor = { .nr = 4, .new = g94_sor_new }, - .pior = { .nr = 3, .new = nv50_pior_new }, + .head = { .cnt = nv50_head_cnt, .new = nv50_head_new }, + .dac = { .cnt = nv50_dac_cnt, .new = nv50_dac_new }, + .sor = { .cnt = g94_sor_cnt, .new = g94_sor_new }, + .pior = { .cnt = nv50_pior_cnt, .new = nv50_pior_new }, }; int g94_disp_new(struct nvkm_device *device, int index, struct nvkm_disp **pdisp) { - return nv50_disp_new_(&g94_disp, device, index, 2, pdisp); + return nv50_disp_new_(&g94_disp, device, index, pdisp); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c index d8765b57180b..794e90982641 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c @@ -24,8 +24,12 @@ #include "nv50.h" #include "head.h" #include "ior.h" +#include "channv50.h" #include "rootnv50.h" +#include <core/ramht.h> +#include <subdev/timer.h> + void gf119_disp_super(struct work_struct *work) { @@ -164,28 +168,99 @@ gf119_disp_intr(struct nv50_disp *disp) } } +void +gf119_disp_fini(struct nv50_disp *disp) +{ + struct nvkm_device *device = disp->base.engine.subdev.device; + /* disable all interrupts */ + nvkm_wr32(device, 0x6100b0, 0x00000000); +} + int -gf119_disp_new_(const struct nv50_disp_func *func, struct nvkm_device *device, - int index, struct nvkm_disp **pdisp) +gf119_disp_init(struct nv50_disp *disp) { - u32 heads = nvkm_rd32(device, 0x022448); - return nv50_disp_new_(func, device, index, heads, pdisp); + struct nvkm_device *device = disp->base.engine.subdev.device; + struct nvkm_head *head; + u32 tmp; + int i; + + /* The below segments of code copying values from one register to + * another appear to inform EVO of the display capabilities or + * something similar. + */ + + /* ... CRTC caps */ + list_for_each_entry(head, &disp->base.head, head) { + const u32 hoff = head->id * 0x800; + tmp = nvkm_rd32(device, 0x616104 + hoff); + nvkm_wr32(device, 0x6101b4 + hoff, tmp); + tmp = nvkm_rd32(device, 0x616108 + hoff); + nvkm_wr32(device, 0x6101b8 + hoff, tmp); + tmp = nvkm_rd32(device, 0x61610c + hoff); + nvkm_wr32(device, 0x6101bc + hoff, tmp); + } + + /* ... DAC caps */ + for (i = 0; i < disp->dac.nr; i++) { + tmp = nvkm_rd32(device, 0x61a000 + (i * 0x800)); + nvkm_wr32(device, 0x6101c0 + (i * 0x800), tmp); + } + + /* ... SOR caps */ + for (i = 0; i < disp->sor.nr; i++) { + tmp = nvkm_rd32(device, 0x61c000 + (i * 0x800)); + nvkm_wr32(device, 0x6301c4 + (i * 0x800), tmp); + } + + /* steal display away from vbios, or something like that */ + if (nvkm_rd32(device, 0x6100ac) & 0x00000100) { + nvkm_wr32(device, 0x6100ac, 0x00000100); + nvkm_mask(device, 0x6194e8, 0x00000001, 0x00000000); + if (nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x6194e8) & 0x00000002)) + break; + ) < 0) + return -EBUSY; + } + + /* point at display engine memory area (hash table, objects) */ + nvkm_wr32(device, 0x610010, (disp->inst->addr >> 8) | 9); + + /* enable supervisor interrupts, disable everything else */ + nvkm_wr32(device, 0x610090, 0x00000000); + nvkm_wr32(device, 0x6100a0, 0x00000000); + nvkm_wr32(device, 0x6100b0, 0x00000307); + + /* disable underflow reporting, preventing an intermittent issue + * on some gk104 boards where the production vbios left this + * setting enabled by default. + * + * ftp://download.nvidia.com/open-gpu-doc/gk104-disable-underflow-reporting/1/gk104-disable-underflow-reporting.txt + */ + list_for_each_entry(head, &disp->base.head, head) { + const u32 hoff = head->id * 0x800; + nvkm_mask(device, 0x616308 + hoff, 0x00000111, 0x00000010); + } + + return 0; } static const struct nv50_disp_func gf119_disp = { + .init = gf119_disp_init, + .fini = gf119_disp_fini, .intr = gf119_disp_intr, .intr_error = gf119_disp_intr_error, .uevent = &gf119_disp_chan_uevent, .super = gf119_disp_super, .root = &gf119_disp_root_oclass, - .head.new = gf119_head_new, - .dac = { .nr = 3, .new = gf119_dac_new }, - .sor = { .nr = 4, .new = gf119_sor_new }, + .head = { .cnt = gf119_head_cnt, .new = gf119_head_new }, + .dac = { .cnt = gf119_dac_cnt, .new = gf119_dac_new }, + .sor = { .cnt = gf119_sor_cnt, .new = gf119_sor_new }, }; int gf119_disp_new(struct nvkm_device *device, int index, struct nvkm_disp **pdisp) { - return gf119_disp_new_(&gf119_disp, device, index, pdisp); + return nv50_disp_new_(&gf119_disp, device, index, pdisp); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gk104.c index e8fe9f315d64..4c3439b1a62d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gk104.c @@ -28,18 +28,20 @@ static const struct nv50_disp_func gk104_disp = { + .init = gf119_disp_init, + .fini = gf119_disp_fini, .intr = gf119_disp_intr, .intr_error = gf119_disp_intr_error, .uevent = &gf119_disp_chan_uevent, .super = gf119_disp_super, .root = &gk104_disp_root_oclass, - .head.new = gf119_head_new, - .dac = { .nr = 3, .new = gf119_dac_new }, - .sor = { .nr = 4, .new = gk104_sor_new }, + .head = { .cnt = gf119_head_cnt, .new = gf119_head_new }, + .dac = { .cnt = gf119_dac_cnt, .new = gf119_dac_new }, + .sor = { .cnt = gf119_sor_cnt, .new = gk104_sor_new }, }; int gk104_disp_new(struct nvkm_device *device, int index, struct nvkm_disp **pdisp) { - return gf119_disp_new_(&gk104_disp, device, index, pdisp); + return nv50_disp_new_(&gk104_disp, device, index, pdisp); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gk110.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gk110.c index 769687502e7a..bc6f4750c942 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gk110.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gk110.c @@ -28,18 +28,20 @@ static const struct nv50_disp_func gk110_disp = { + .init = gf119_disp_init, + .fini = gf119_disp_fini, .intr = gf119_disp_intr, .intr_error = gf119_disp_intr_error, .uevent = &gf119_disp_chan_uevent, .super = gf119_disp_super, .root = &gk110_disp_root_oclass, - .head.new = gf119_head_new, - .dac = { .nr = 3, .new = gf119_dac_new }, - .sor = { .nr = 4, .new = gk104_sor_new }, + .head = { .cnt = gf119_head_cnt, .new = gf119_head_new }, + .dac = { .cnt = gf119_dac_cnt, .new = gf119_dac_new }, + .sor = { .cnt = gf119_sor_cnt, .new = gk104_sor_new }, }; int gk110_disp_new(struct nvkm_device *device, int index, struct nvkm_disp **pdisp) { - return gf119_disp_new_(&gk110_disp, device, index, pdisp); + return nv50_disp_new_(&gk110_disp, device, index, pdisp); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm107.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm107.c index ede70e5d188e..031cf6b03a76 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm107.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm107.c @@ -28,18 +28,20 @@ static const struct nv50_disp_func gm107_disp = { + .init = gf119_disp_init, + .fini = gf119_disp_fini, .intr = gf119_disp_intr, .intr_error = gf119_disp_intr_error, .uevent = &gf119_disp_chan_uevent, .super = gf119_disp_super, .root = &gm107_disp_root_oclass, - .head.new = gf119_head_new, - .dac = { .nr = 3, .new = gf119_dac_new }, - .sor = { .nr = 4, .new = gm107_sor_new }, + .head = { .cnt = gf119_head_cnt, .new = gf119_head_new }, + .dac = { .cnt = gf119_dac_cnt, .new = gf119_dac_new }, + .sor = { .cnt = gf119_sor_cnt, .new = gm107_sor_new }, }; int gm107_disp_new(struct nvkm_device *device, int index, struct nvkm_disp **pdisp) { - return gf119_disp_new_(&gm107_disp, device, index, pdisp); + return nv50_disp_new_(&gm107_disp, device, index, pdisp); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm200.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm200.c index 292d3b5f9704..ec9c33a5162d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm200.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm200.c @@ -28,18 +28,20 @@ static const struct nv50_disp_func gm200_disp = { + .init = gf119_disp_init, + .fini = gf119_disp_fini, .intr = gf119_disp_intr, .intr_error = gf119_disp_intr_error, .uevent = &gf119_disp_chan_uevent, .super = gf119_disp_super, .root = &gm200_disp_root_oclass, - .head.new = gf119_head_new, - .dac = { .nr = 3, .new = gf119_dac_new }, - .sor = { .nr = 4, .new = gm200_sor_new }, + .head = { .cnt = gf119_head_cnt, .new = gf119_head_new }, + .dac = { .cnt = gf119_dac_cnt, .new = gf119_dac_new }, + .sor = { .cnt = gf119_sor_cnt, .new = gm200_sor_new }, }; int gm200_disp_new(struct nvkm_device *device, int index, struct nvkm_disp **pdisp) { - return gf119_disp_new_(&gm200_disp, device, index, pdisp); + return nv50_disp_new_(&gm200_disp, device, index, pdisp); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gp100.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gp100.c index 39eb98b2c3a2..fd6216684f6d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gp100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gp100.c @@ -28,17 +28,19 @@ static const struct nv50_disp_func gp100_disp = { + .init = gf119_disp_init, + .fini = gf119_disp_fini, .intr = gf119_disp_intr, .intr_error = gf119_disp_intr_error, .uevent = &gf119_disp_chan_uevent, .super = gf119_disp_super, .root = &gp100_disp_root_oclass, - .head.new = gf119_head_new, - .sor = { .nr = 4, .new = gm200_sor_new }, + .head = { .cnt = gf119_head_cnt, .new = gf119_head_new }, + .sor = { .cnt = gf119_sor_cnt, .new = gm200_sor_new }, }; int gp100_disp_new(struct nvkm_device *device, int index, struct nvkm_disp **pdisp) { - return gf119_disp_new_(&gp100_disp, device, index, pdisp); + return nv50_disp_new_(&gp100_disp, device, index, pdisp); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gp102.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gp102.c index 91d70fe18275..3468ddec1270 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gp102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gp102.c @@ -24,6 +24,7 @@ #include "nv50.h" #include "head.h" #include "ior.h" +#include "channv50.h" #include "rootnv50.h" static void @@ -54,17 +55,19 @@ gp102_disp_intr_error(struct nv50_disp *disp, int chid) static const struct nv50_disp_func gp102_disp = { + .init = gf119_disp_init, + .fini = gf119_disp_fini, .intr = gf119_disp_intr, .intr_error = gp102_disp_intr_error, .uevent = &gf119_disp_chan_uevent, .super = gf119_disp_super, .root = &gp102_disp_root_oclass, - .head.new = gf119_head_new, - .sor = { .nr = 4, .new = gm200_sor_new }, + .head = { .cnt = gf119_head_cnt, .new = gf119_head_new }, + .sor = { .cnt = gf119_sor_cnt, .new = gm200_sor_new }, }; int gp102_disp_new(struct nvkm_device *device, int index, struct nvkm_disp **pdisp) { - return gf119_disp_new_(&gp102_disp, device, index, pdisp); + return nv50_disp_new_(&gp102_disp, device, index, pdisp); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gt200.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gt200.c index bf00c4e3be3a..f80183701f44 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gt200.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gt200.c @@ -28,18 +28,20 @@ static const struct nv50_disp_func gt200_disp = { + .init = nv50_disp_init, + .fini = nv50_disp_fini, .intr = nv50_disp_intr, .uevent = &nv50_disp_chan_uevent, .super = nv50_disp_super, .root = >200_disp_root_oclass, - .head.new = nv50_head_new, - .dac = { .nr = 3, .new = nv50_dac_new }, - .sor = { .nr = 2, .new = g84_sor_new }, - .pior = { .nr = 3, .new = nv50_pior_new }, + .head = { .cnt = nv50_head_cnt, .new = nv50_head_new }, + .dac = { .cnt = nv50_dac_cnt, .new = nv50_dac_new }, + .sor = { .cnt = nv50_sor_cnt, .new = g84_sor_new }, + .pior = { .cnt = nv50_pior_cnt, .new = nv50_pior_new }, }; int gt200_disp_new(struct nvkm_device *device, int index, struct nvkm_disp **pdisp) { - return nv50_disp_new_(>200_disp, device, index, 2, pdisp); + return nv50_disp_new_(>200_disp, device, index, pdisp); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gt215.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gt215.c index 2cdd4d7a98d3..7581efc1357e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gt215.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gt215.c @@ -28,18 +28,20 @@ static const struct nv50_disp_func gt215_disp = { + .init = nv50_disp_init, + .fini = nv50_disp_fini, .intr = nv50_disp_intr, .uevent = &nv50_disp_chan_uevent, .super = nv50_disp_super, .root = >215_disp_root_oclass, - .head.new = nv50_head_new, - .dac = { .nr = 3, .new = nv50_dac_new }, - .sor = { .nr = 4, .new = gt215_sor_new }, - .pior = { .nr = 3, .new = nv50_pior_new }, + .head = { .cnt = nv50_head_cnt, .new = nv50_head_new }, + .dac = { .cnt = nv50_dac_cnt, .new = nv50_dac_new }, + .sor = { .cnt = g94_sor_cnt, .new = gt215_sor_new }, + .pior = { .cnt = nv50_pior_cnt, .new = nv50_pior_new }, }; int gt215_disp_new(struct nvkm_device *device, int index, struct nvkm_disp **pdisp) { - return nv50_disp_new_(>215_disp, device, index, 2, pdisp); + return nv50_disp_new_(>215_disp, device, index, pdisp); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gv100.c new file mode 100644 index 000000000000..d0a7e3456da1 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gv100.c @@ -0,0 +1,427 @@ +/* + * Copyright 2018 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ +#include "nv50.h" +#include "head.h" +#include "ior.h" +#include "channv50.h" +#include "rootnv50.h" + +#include <core/gpuobj.h> +#include <subdev/timer.h> + +static int +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 void +gv100_disp_super(struct work_struct *work) +{ + struct nv50_disp *disp = + container_of(work, struct nv50_disp, supervisor); + struct nvkm_subdev *subdev = &disp->base.engine.subdev; + struct nvkm_device *device = subdev->device; + struct nvkm_head *head; + u32 stat = nvkm_rd32(device, 0x6107a8); + u32 mask[4]; + + nvkm_debug(subdev, "supervisor %d: %08x\n", ffs(disp->super), stat); + list_for_each_entry(head, &disp->base.head, head) { + mask[head->id] = nvkm_rd32(device, 0x6107ac + (head->id * 4)); + HEAD_DBG(head, "%08x", mask[head->id]); + } + + if (disp->super & 0x00000001) { + nv50_disp_chan_mthd(disp->chan[0], NV_DBG_DEBUG); + nv50_disp_super_1(disp); + list_for_each_entry(head, &disp->base.head, head) { + if (!(mask[head->id] & 0x00001000)) + continue; + nv50_disp_super_1_0(disp, head); + } + } else + if (disp->super & 0x00000002) { + list_for_each_entry(head, &disp->base.head, head) { + if (!(mask[head->id] & 0x00001000)) + continue; + nv50_disp_super_2_0(disp, head); + } + nvkm_outp_route(&disp->base); + list_for_each_entry(head, &disp->base.head, head) { + if (!(mask[head->id] & 0x00010000)) + continue; + nv50_disp_super_2_1(disp, head); + } + list_for_each_entry(head, &disp->base.head, head) { + if (!(mask[head->id] & 0x00001000)) + continue; + nv50_disp_super_2_2(disp, head); + } + } else + if (disp->super & 0x00000004) { + list_for_each_entry(head, &disp->base.head, head) { + if (!(mask[head->id] & 0x00001000)) + continue; + nv50_disp_super_3_0(disp, head); + } + } + + list_for_each_entry(head, &disp->base.head, head) + nvkm_wr32(device, 0x6107ac + (head->id * 4), 0x00000000); + nvkm_wr32(device, 0x6107a8, 0x80000000); +} + +static void +gv100_disp_exception(struct nv50_disp *disp, int chid) +{ + struct nvkm_subdev *subdev = &disp->base.engine.subdev; + struct nvkm_device *device = subdev->device; + u32 stat = nvkm_rd32(device, 0x611020 + (chid * 12)); + u32 type = (stat & 0x00007000) >> 12; + u32 mthd = (stat & 0x00000fff) << 2; + u32 data = nvkm_rd32(device, 0x611024 + (chid * 12)); + u32 code = nvkm_rd32(device, 0x611028 + (chid * 12)); + + nvkm_error(subdev, "chid %d %08x [type %d mthd %04x] " + "data %08x code %08x\n", + chid, stat, type, mthd, data, code); + + if (chid < ARRAY_SIZE(disp->chan) && disp->chan[chid]) { + switch (mthd) { + case 0x0200: + nv50_disp_chan_mthd(disp->chan[chid], NV_DBG_ERROR); + break; + default: + break; + } + } + + nvkm_wr32(device, 0x611020 + (chid * 12), 0x90000000); +} + +static void +gv100_disp_intr_ctrl_disp(struct nv50_disp *disp) +{ + struct nvkm_subdev *subdev = &disp->base.engine.subdev; + struct nvkm_device *device = subdev->device; + u32 stat = nvkm_rd32(device, 0x611c30); + + if (stat & 0x00000007) { + disp->super = (stat & 0x00000007); + queue_work(disp->wq, &disp->supervisor); + nvkm_wr32(device, 0x611860, disp->super); + stat &= ~0x00000007; + } + + /*TODO: I would guess this is VBIOS_RELEASE, however, NFI how to + * ACK it, nor does RM appear to bother. + */ + if (stat & 0x00000008) + stat &= ~0x00000008; + + if (stat & 0x00000100) { + unsigned long wndws = nvkm_rd32(device, 0x611858); + unsigned long other = nvkm_rd32(device, 0x61185c); + int wndw; + + nvkm_wr32(device, 0x611858, wndws); + nvkm_wr32(device, 0x61185c, other); + + /* AWAKEN_OTHER_CORE. */ + if (other & 0x00000001) + nv50_disp_chan_uevent_send(disp, 0); + + /* AWAKEN_WIN_CH(n). */ + for_each_set_bit(wndw, &wndws, disp->wndw.nr) { + nv50_disp_chan_uevent_send(disp, 1 + wndw); + } + } + + if (stat) + nvkm_warn(subdev, "ctrl %08x\n", stat); +} + +static void +gv100_disp_intr_exc_other(struct nv50_disp *disp) +{ + struct nvkm_subdev *subdev = &disp->base.engine.subdev; + struct nvkm_device *device = subdev->device; + u32 stat = nvkm_rd32(device, 0x611854); + unsigned long mask; + int head; + + if (stat & 0x00000001) { + nvkm_wr32(device, 0x611854, 0x00000001); + gv100_disp_exception(disp, 0); + stat &= ~0x00000001; + } + + if ((mask = (stat & 0x00ff0000) >> 16)) { + for_each_set_bit(head, &mask, disp->wndw.nr) { + nvkm_wr32(device, 0x611854, 0x00010000 << head); + gv100_disp_exception(disp, 73 + head); + stat &= ~(0x00010000 << head); + } + } + + if (stat) { + nvkm_warn(subdev, "exception %08x\n", stat); + nvkm_wr32(device, 0x611854, stat); + } +} + +static void +gv100_disp_intr_exc_winim(struct nv50_disp *disp) +{ + struct nvkm_subdev *subdev = &disp->base.engine.subdev; + struct nvkm_device *device = subdev->device; + unsigned long stat = nvkm_rd32(device, 0x611850); + int wndw; + + for_each_set_bit(wndw, &stat, disp->wndw.nr) { + nvkm_wr32(device, 0x611850, BIT(wndw)); + gv100_disp_exception(disp, 33 + wndw); + stat &= ~BIT(wndw); + } + + if (stat) { + nvkm_warn(subdev, "wimm %08x\n", (u32)stat); + nvkm_wr32(device, 0x611850, stat); + } +} + +static void +gv100_disp_intr_exc_win(struct nv50_disp *disp) +{ + struct nvkm_subdev *subdev = &disp->base.engine.subdev; + struct nvkm_device *device = subdev->device; + unsigned long stat = nvkm_rd32(device, 0x61184c); + int wndw; + + for_each_set_bit(wndw, &stat, disp->wndw.nr) { + nvkm_wr32(device, 0x61184c, BIT(wndw)); + gv100_disp_exception(disp, 1 + wndw); + stat &= ~BIT(wndw); + } + + if (stat) { + nvkm_warn(subdev, "wndw %08x\n", (u32)stat); + nvkm_wr32(device, 0x61184c, stat); + } +} + +static void +gv100_disp_intr_head_timing(struct nv50_disp *disp, int head) +{ + struct nvkm_subdev *subdev = &disp->base.engine.subdev; + struct nvkm_device *device = subdev->device; + u32 stat = nvkm_rd32(device, 0x611800 + (head * 0x04)); + + /* LAST_DATA, LOADV. */ + if (stat & 0x00000003) { + nvkm_wr32(device, 0x611800 + (head * 0x04), stat & 0x00000003); + stat &= ~0x00000003; + } + + if (stat & 0x00000004) { + nvkm_disp_vblank(&disp->base, head); + nvkm_wr32(device, 0x611800 + (head * 0x04), 0x00000004); + stat &= ~0x00000004; + } + + if (stat) { + nvkm_warn(subdev, "head %08x\n", stat); + nvkm_wr32(device, 0x611800 + (head * 0x04), stat); + } +} + +static void +gv100_disp_intr(struct nv50_disp *disp) +{ + struct nvkm_subdev *subdev = &disp->base.engine.subdev; + struct nvkm_device *device = subdev->device; + u32 stat = nvkm_rd32(device, 0x611ec0); + unsigned long mask; + int head; + + if ((mask = (stat & 0x000000ff))) { + for_each_set_bit(head, &mask, 8) { + gv100_disp_intr_head_timing(disp, head); + stat &= ~BIT(head); + } + } + + if (stat & 0x00000200) { + gv100_disp_intr_exc_win(disp); + stat &= ~0x00000200; + } + + if (stat & 0x00000400) { + gv100_disp_intr_exc_winim(disp); + stat &= ~0x00000400; + } + + if (stat & 0x00000800) { + gv100_disp_intr_exc_other(disp); + stat &= ~0x00000800; + } + + if (stat & 0x00001000) { + gv100_disp_intr_ctrl_disp(disp); + stat &= ~0x00001000; + } + + if (stat) + nvkm_warn(subdev, "intr %08x\n", stat); +} + +static void +gv100_disp_fini(struct nv50_disp *disp) +{ + struct nvkm_device *device = disp->base.engine.subdev.device; + nvkm_wr32(device, 0x611db0, 0x00000000); +} + +static int +gv100_disp_init(struct nv50_disp *disp) +{ + struct nvkm_device *device = disp->base.engine.subdev.device; + struct nvkm_head *head; + int i, j; + u32 tmp; + + /* Claim ownership of display. */ + if (nvkm_rd32(device, 0x6254e8) & 0x00000002) { + nvkm_mask(device, 0x6254e8, 0x00000001, 0x00000000); + if (nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x6254e8) & 0x00000002)) + break; + ) < 0) + return -EBUSY; + } + + /* Lock pin capabilities. */ + tmp = nvkm_rd32(device, 0x610068); + nvkm_wr32(device, 0x640008, tmp); + + /* SOR capabilities. */ + for (i = 0; i < disp->sor.nr; i++) { + tmp = nvkm_rd32(device, 0x61c000 + (i * 0x800)); + nvkm_mask(device, 0x640000, 0x00000100 << i, 0x00000100 << i); + nvkm_wr32(device, 0x640144 + (i * 0x08), tmp); + } + + /* Head capabilities. */ + list_for_each_entry(head, &disp->base.head, head) { + const int id = head->id; + + /* RG. */ + tmp = nvkm_rd32(device, 0x616300 + (id * 0x800)); + nvkm_wr32(device, 0x640048 + (id * 0x020), tmp); + + /* POSTCOMP. */ + for (j = 0; j < 6 * 4; j += 4) { + tmp = nvkm_rd32(device, 0x616100 + (id * 0x800) + j); + nvkm_wr32(device, 0x640030 + (id * 0x20) + j, tmp); + } + } + + /* Window capabilities. */ + for (i = 0; i < disp->wndw.nr; i++) { + nvkm_mask(device, 0x640004, 1 << i, 1 << i); + for (j = 0; j < 6 * 4; j += 4) { + tmp = nvkm_rd32(device, 0x630050 + (i * 0x800) + j); + nvkm_wr32(device, 0x6401e4 + (i * 0x20) + j, tmp); + } + } + + /* IHUB capabilities. */ + for (i = 0; i < 4; i++) { + tmp = nvkm_rd32(device, 0x62e000 + (i * 0x04)); + nvkm_wr32(device, 0x640010 + (i * 0x04), tmp); + } + + nvkm_mask(device, 0x610078, 0x00000001, 0x00000001); + + /* Setup instance memory. */ + switch (nvkm_memory_target(disp->inst->memory)) { + case NVKM_MEM_TARGET_VRAM: tmp = 0x00000001; break; + case NVKM_MEM_TARGET_NCOH: tmp = 0x00000002; break; + case NVKM_MEM_TARGET_HOST: tmp = 0x00000003; break; + default: + break; + } + nvkm_wr32(device, 0x610010, 0x00000008 | tmp); + nvkm_wr32(device, 0x610014, disp->inst->addr >> 16); + + /* CTRL_DISP: AWAKEN, ERROR, SUPERVISOR[1-3]. */ + nvkm_wr32(device, 0x611cf0, 0x00000187); /* MSK. */ + nvkm_wr32(device, 0x611db0, 0x00000187); /* EN. */ + + /* EXC_OTHER: CURSn, CORE. */ + nvkm_wr32(device, 0x611cec, disp->head.mask << 16 | + 0x00000001); /* MSK. */ + nvkm_wr32(device, 0x611dac, 0x00000000); /* EN. */ + + /* EXC_WINIM. */ + nvkm_wr32(device, 0x611ce8, disp->wndw.mask); /* MSK. */ + nvkm_wr32(device, 0x611da8, 0x00000000); /* EN. */ + + /* EXC_WIN. */ + nvkm_wr32(device, 0x611ce4, disp->wndw.mask); /* MSK. */ + nvkm_wr32(device, 0x611da4, 0x00000000); /* EN. */ + + /* HEAD_TIMING(n): VBLANK. */ + list_for_each_entry(head, &disp->base.head, head) { + const u32 hoff = head->id * 4; + nvkm_wr32(device, 0x611cc0 + hoff, 0x00000004); /* MSK. */ + nvkm_wr32(device, 0x611d80 + hoff, 0x00000000); /* EN. */ + } + + /* OR. */ + nvkm_wr32(device, 0x611cf4, 0x00000000); /* MSK. */ + nvkm_wr32(device, 0x611db4, 0x00000000); /* EN. */ + return 0; +} + +static const struct nv50_disp_func +gv100_disp = { + .init = gv100_disp_init, + .fini = gv100_disp_fini, + .intr = gv100_disp_intr, + .uevent = &gv100_disp_chan_uevent, + .super = gv100_disp_super, + .root = &gv100_disp_root_oclass, + .wndw = { .cnt = gv100_disp_wndw_cnt }, + .head = { .cnt = gv100_head_cnt, .new = gv100_head_new }, + .sor = { .cnt = gv100_sor_cnt, .new = gv100_sor_new }, + .ramht_size = 0x2000, +}; + +int +gv100_disp_new(struct nvkm_device *device, int index, struct nvkm_disp **pdisp) +{ + return nv50_disp_new_(&gv100_disp, device, index, pdisp); +} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigv100.c new file mode 100644 index 000000000000..6e3c450eaace --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigv100.c @@ -0,0 +1,85 @@ +/* + * 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, 0x6f0110 + hdmi, 0x00000000); + 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 57030b3a4a75..7d55faf52fcb 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/head.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/head.h @@ -52,6 +52,14 @@ void nv50_head_rgpos(struct nvkm_head *, u16 *, u16 *); #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); + +int gf119_head_cnt(struct nvkm_disp *, unsigned long *); int gf119_head_new(struct nvkm_disp *, int id); +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); #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/headgf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/headgf119.c index 9fd7ae331308..e86298b35902 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/headgf119.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/headgf119.c @@ -39,7 +39,7 @@ gf119_head_vblank_get(struct nvkm_head *head) nvkm_mask(device, 0x6100c0 + hoff, 0x00000001, 0x00000001); } -static void +void gf119_head_rgclk(struct nvkm_head *head, int div) { struct nvkm_device *device = head->disp->engine.subdev.device; @@ -92,8 +92,13 @@ gf119_head = { int gf119_head_new(struct nvkm_disp *disp, int id) { - struct nvkm_device *device = disp->engine.subdev.device; - if (!(nvkm_rd32(device, 0x612004) & (0x00000001 << id))) - return 0; 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 new file mode 100644 index 000000000000..1a061b42ae5c --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/headgv100.c @@ -0,0 +1,105 @@ +/* + * 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/headnv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/headnv50.c index c80d06d5168f..e7d5c397cd29 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/headnv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/headnv50.c @@ -90,3 +90,10 @@ 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 4548c031b937..e0b4e0c5704e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h @@ -30,7 +30,7 @@ struct nvkm_ior { UNKNOWN } proto:3; unsigned link:2; - unsigned head:4; + unsigned head:8; } arm, asy; /* Armed DP state. */ @@ -106,7 +106,6 @@ nv50_sor_link(struct nvkm_ior *ior) return nv50_ior_base(ior) + ((ior->asy.link == 2) * 0x80); } -int nv50_sor_new_(const struct nvkm_ior_func *, struct nvkm_disp *, int id); 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 *); @@ -122,7 +121,6 @@ void g94_sor_dp_watermark(struct nvkm_ior *, int, u8); void gt215_sor_dp_audio(struct nvkm_ior *, int, bool); -int gf119_sor_new_(const struct nvkm_ior_func *, struct nvkm_disp *, int id); 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 *); @@ -135,10 +133,15 @@ void gf119_sor_dp_watermark(struct nvkm_ior *, int, 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_dp_drive(struct nvkm_ior *, int, int, int, int, int); + 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 gt215_hda_hpd(struct nvkm_ior *, int, bool); void gt215_hda_eld(struct nvkm_ior *, u8 *, u8); @@ -153,19 +156,34 @@ void gf119_hda_eld(struct nvkm_ior *, u8 *, u8); #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 gv100_sor_cnt(struct nvkm_disp *, unsigned long *); +int gv100_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 d7e0fbb12bf1..cfdce23ab83a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/mcp77.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/mcp77.c @@ -26,18 +26,20 @@ static const struct nv50_disp_func mcp77_disp = { + .init = nv50_disp_init, + .fini = nv50_disp_fini, .intr = nv50_disp_intr, .uevent = &nv50_disp_chan_uevent, .super = nv50_disp_super, .root = &g94_disp_root_oclass, - .head.new = nv50_head_new, - .dac = { .nr = 3, .new = nv50_dac_new }, - .sor = { .nr = 4, .new = mcp77_sor_new }, - .pior = { .nr = 3, .new = nv50_pior_new }, + .head = { .cnt = nv50_head_cnt, .new = nv50_head_new }, + .dac = { .cnt = nv50_dac_cnt, .new = nv50_dac_new }, + .sor = { .cnt = g94_sor_cnt, .new = mcp77_sor_new }, + .pior = { .cnt = nv50_pior_cnt, .new = nv50_pior_new }, }; int mcp77_disp_new(struct nvkm_device *device, int index, struct nvkm_disp **pdisp) { - return nv50_disp_new_(&mcp77_disp, device, index, 2, pdisp); + return nv50_disp_new_(&mcp77_disp, device, index, pdisp); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/mcp89.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/mcp89.c index 7b75c57c12ed..85d9329cfa0e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/mcp89.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/mcp89.c @@ -26,18 +26,20 @@ static const struct nv50_disp_func mcp89_disp = { + .init = nv50_disp_init, + .fini = nv50_disp_fini, .intr = nv50_disp_intr, .uevent = &nv50_disp_chan_uevent, .super = nv50_disp_super, .root = >215_disp_root_oclass, - .head.new = nv50_head_new, - .dac = { .nr = 3, .new = nv50_dac_new }, - .sor = { .nr = 4, .new = mcp89_sor_new }, - .pior = { .nr = 3, .new = nv50_pior_new }, + .head = { .cnt = nv50_head_cnt, .new = nv50_head_new }, + .dac = { .cnt = nv50_dac_cnt, .new = nv50_dac_new }, + .sor = { .cnt = g94_sor_cnt, .new = mcp89_sor_new }, + .pior = { .cnt = nv50_pior_cnt, .new = nv50_pior_new }, }; int mcp89_disp_new(struct nvkm_device *device, int index, struct nvkm_disp **pdisp) { - return nv50_disp_new_(&mcp89_disp, device, index, 2, pdisp); + return nv50_disp_new_(&mcp89_disp, device, index, pdisp); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c index 0c570dbd3021..f89c7b977aa5 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c @@ -24,11 +24,12 @@ #include "nv50.h" #include "head.h" #include "ior.h" +#include "channv50.h" #include "rootnv50.h" #include <core/client.h> #include <core/enum.h> -#include <core/gpuobj.h> +#include <core/ramht.h> #include <subdev/bios.h> #include <subdev/bios/disp.h> #include <subdev/bios/init.h> @@ -49,29 +50,115 @@ nv50_disp_intr_(struct nvkm_disp *base) disp->func->intr(disp); } +static void +nv50_disp_fini_(struct nvkm_disp *base) +{ + struct nv50_disp *disp = nv50_disp(base); + disp->func->fini(disp); +} + +static int +nv50_disp_init_(struct nvkm_disp *base) +{ + struct nv50_disp *disp = nv50_disp(base); + return disp->func->init(disp); +} + static void * nv50_disp_dtor_(struct nvkm_disp *base) { struct nv50_disp *disp = nv50_disp(base); + + 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 int +nv50_disp_oneinit_(struct nvkm_disp *base) +{ + struct nv50_disp *disp = nv50_disp(base); + const struct nv50_disp_func *func = disp->func; + struct nvkm_subdev *subdev = &disp->base.engine.subdev; + struct nvkm_device *device = subdev->device; + int ret, i; + + if (func->wndw.cnt) { + disp->wndw.nr = func->wndw.cnt(&disp->base, &disp->wndw.mask); + nvkm_debug(subdev, "Window(s): %d (%08lx)\n", + disp->wndw.nr, disp->wndw.mask); + } + + disp->head.nr = func->head.cnt(&disp->base, &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->base, i); + if (ret) + return ret; + } + + if (func->dac.cnt) { + disp->dac.nr = func->dac.cnt(&disp->base, &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->base, i); + if (ret) + return ret; + } + } + + if (func->pior.cnt) { + disp->pior.nr = func->pior.cnt(&disp->base, &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->base, i); + if (ret) + return ret; + } + } + + disp->sor.nr = func->sor.cnt(&disp->base, &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->base, 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); +} + static const struct nvkm_disp_func nv50_disp_ = { .dtor = nv50_disp_dtor_, + .oneinit = nv50_disp_oneinit_, + .init = nv50_disp_init_, + .fini = nv50_disp_fini_, .intr = nv50_disp_intr_, .root = nv50_disp_root_, }; int nv50_disp_new_(const struct nv50_disp_func *func, struct nvkm_device *device, - int index, int heads, struct nvkm_disp **pdisp) + int index, struct nvkm_disp **pdisp) { struct nv50_disp *disp; - int ret, i; + int ret; if (!(disp = kzalloc(sizeof(*disp), GFP_KERNEL))) return -ENOMEM; @@ -85,33 +172,11 @@ nv50_disp_new_(const struct nv50_disp_func *func, struct nvkm_device *device, disp->wq = create_singlethread_workqueue("nvkm-disp"); if (!disp->wq) return -ENOMEM; - INIT_WORK(&disp->supervisor, func->super); - - for (i = 0; func->head.new && i < heads; i++) { - ret = func->head.new(&disp->base, i); - if (ret) - return ret; - } - - for (i = 0; func->dac.new && i < func->dac.nr; i++) { - ret = func->dac.new(&disp->base, i); - if (ret) - return ret; - } - - for (i = 0; func->pior.new && i < func->pior.nr; i++) { - ret = func->pior.new(&disp->base, i); - if (ret) - return ret; - } - for (i = 0; func->sor.new && i < func->sor.nr; i++) { - ret = func->sor.new(&disp->base, i); - if (ret) - return ret; - } + INIT_WORK(&disp->supervisor, func->super); - return nvkm_event_init(func->uevent, 1, 1 + (heads * 4), &disp->uevent); + return nvkm_event_init(func->uevent, 1, ARRAY_SIZE(disp->chan), + &disp->uevent); } static u32 @@ -613,20 +678,96 @@ nv50_disp_intr(struct nv50_disp *disp) } } +void +nv50_disp_fini(struct nv50_disp *disp) +{ + struct nvkm_device *device = disp->base.engine.subdev.device; + /* disable all interrupts */ + nvkm_wr32(device, 0x610024, 0x00000000); + nvkm_wr32(device, 0x610020, 0x00000000); +} + +int +nv50_disp_init(struct nv50_disp *disp) +{ + struct nvkm_device *device = disp->base.engine.subdev.device; + struct nvkm_head *head; + u32 tmp; + int i; + + /* The below segments of code copying values from one register to + * another appear to inform EVO of the display capabilities or + * something similar. NFI what the 0x614004 caps are for.. + */ + tmp = nvkm_rd32(device, 0x614004); + nvkm_wr32(device, 0x610184, tmp); + + /* ... CRTC caps */ + list_for_each_entry(head, &disp->base.head, head) { + tmp = nvkm_rd32(device, 0x616100 + (head->id * 0x800)); + nvkm_wr32(device, 0x610190 + (head->id * 0x10), tmp); + tmp = nvkm_rd32(device, 0x616104 + (head->id * 0x800)); + nvkm_wr32(device, 0x610194 + (head->id * 0x10), tmp); + tmp = nvkm_rd32(device, 0x616108 + (head->id * 0x800)); + nvkm_wr32(device, 0x610198 + (head->id * 0x10), tmp); + tmp = nvkm_rd32(device, 0x61610c + (head->id * 0x800)); + nvkm_wr32(device, 0x61019c + (head->id * 0x10), tmp); + } + + /* ... DAC caps */ + for (i = 0; i < disp->dac.nr; i++) { + tmp = nvkm_rd32(device, 0x61a000 + (i * 0x800)); + nvkm_wr32(device, 0x6101d0 + (i * 0x04), tmp); + } + + /* ... SOR caps */ + for (i = 0; i < disp->sor.nr; i++) { + tmp = nvkm_rd32(device, 0x61c000 + (i * 0x800)); + nvkm_wr32(device, 0x6101e0 + (i * 0x04), tmp); + } + + /* ... PIOR caps */ + for (i = 0; i < disp->pior.nr; i++) { + tmp = nvkm_rd32(device, 0x61e000 + (i * 0x800)); + nvkm_wr32(device, 0x6101f0 + (i * 0x04), tmp); + } + + /* steal display away from vbios, or something like that */ + if (nvkm_rd32(device, 0x610024) & 0x00000100) { + nvkm_wr32(device, 0x610024, 0x00000100); + nvkm_mask(device, 0x6194e8, 0x00000001, 0x00000000); + if (nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x6194e8) & 0x00000002)) + break; + ) < 0) + return -EBUSY; + } + + /* point at display engine memory area (hash table, objects) */ + nvkm_wr32(device, 0x610010, (disp->inst->addr >> 8) | 9); + + /* enable supervisor interrupts, disable everything else */ + nvkm_wr32(device, 0x61002c, 0x00000370); + nvkm_wr32(device, 0x610028, 0x00000000); + return 0; +} + static const struct nv50_disp_func nv50_disp = { + .init = nv50_disp_init, + .fini = nv50_disp_fini, .intr = nv50_disp_intr, .uevent = &nv50_disp_chan_uevent, .super = nv50_disp_super, .root = &nv50_disp_root_oclass, - .head.new = nv50_head_new, - .dac = { .nr = 3, .new = nv50_dac_new }, - .sor = { .nr = 2, .new = nv50_sor_new }, - .pior = { .nr = 3, .new = nv50_pior_new }, + .head = { .cnt = nv50_head_cnt, .new = nv50_head_new }, + .dac = { .cnt = nv50_dac_cnt, .new = nv50_dac_new }, + .sor = { .cnt = nv50_sor_cnt, .new = nv50_sor_new }, + .pior = { .cnt = nv50_pior_cnt, .new = nv50_pior_new }, }; int nv50_disp_new(struct nvkm_device *device, int index, struct nvkm_disp **pdisp) { - return nv50_disp_new_(&nv50_disp, device, index, 2, pdisp); + return nv50_disp_new_(&nv50_disp, device, index, pdisp); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.h index eb0b8acb1c5b..8580382ab248 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.h @@ -16,14 +16,26 @@ struct nv50_disp { struct nvkm_event uevent; struct { + unsigned long mask; + int nr; + } wndw, head, dac; + + struct { + unsigned long mask; + int nr; u32 lvdsconf; } sor; struct { + unsigned long mask; + int nr; u8 type[3]; } pior; - struct nv50_disp_chan *chan[21]; + struct nvkm_gpuobj *inst; + struct nvkm_ramht *ramht; + + struct nv50_disp_chan *chan[81]; }; void nv50_disp_super_1(struct nv50_disp *); @@ -34,11 +46,11 @@ void nv50_disp_super_2_2(struct nv50_disp *, struct nvkm_head *); void nv50_disp_super_3_0(struct nv50_disp *, struct nvkm_head *); int nv50_disp_new_(const struct nv50_disp_func *, struct nvkm_device *, - int index, int heads, struct nvkm_disp **); -int gf119_disp_new_(const struct nv50_disp_func *, struct nvkm_device *, - int index, struct nvkm_disp **); + int index, struct nvkm_disp **); struct nv50_disp_func { + int (*init)(struct nv50_disp *); + void (*fini)(struct nv50_disp *); void (*intr)(struct nv50_disp *); void (*intr_error)(struct nv50_disp *, int chid); @@ -48,28 +60,20 @@ struct nv50_disp_func { const struct nvkm_disp_oclass *root; struct { + int (*cnt)(struct nvkm_disp *, unsigned long *mask); int (*new)(struct nvkm_disp *, int id); - } head; + } wndw, head, dac, sor, pior; - struct { - int nr; - int (*new)(struct nvkm_disp *, int id); - } dac; - - struct { - int nr; - int (*new)(struct nvkm_disp *, int id); - } sor; - - struct { - int nr; - int (*new)(struct nvkm_disp *, int id); - } pior; + u16 ramht_size; }; +int nv50_disp_init(struct nv50_disp *); +void nv50_disp_fini(struct nv50_disp *); void nv50_disp_intr(struct nv50_disp *); void nv50_disp_super(struct work_struct *); +int gf119_disp_init(struct nv50_disp *); +void gf119_disp_fini(struct nv50_disp *); void gf119_disp_intr(struct nv50_disp *); void gf119_disp_super(struct work_struct *); void gf119_disp_intr_error(struct nv50_disp *, int); @@ -77,4 +81,12 @@ void gf119_disp_intr_error(struct nv50_disp *, int); void nv50_disp_dptmds_war_2(struct nv50_disp *, struct dcb_output *); void nv50_disp_dptmds_war_3(struct nv50_disp *, struct dcb_output *); void nv50_disp_update_sppll1(struct nv50_disp *); + +extern const struct nvkm_event_func nv50_disp_chan_uevent; +int nv50_disp_chan_uevent_ctor(struct nvkm_object *, void *, u32, + struct nvkm_notify *); +void nv50_disp_chan_uevent_send(struct nv50_disp *, int); + +extern const struct nvkm_event_func gf119_disp_chan_uevent; +extern const struct nvkm_event_func gv100_disp_chan_uevent; #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgf119.c index 1f9fd3403f07..1ae0bcfc89b9 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgf119.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgf119.c @@ -22,16 +22,11 @@ * Authors: Ben Skeggs */ #include "channv50.h" -#include "rootnv50.h" -#include <nvif/class.h> - -const struct nv50_disp_pioc_oclass -gf119_disp_oimm_oclass = { - .base.oclass = GF110_DISP_OVERLAY, - .base.minver = 0, - .base.maxver = 0, - .ctor = nv50_disp_oimm_new, - .func = &gf119_disp_pioc_func, - .chid = { 9, 9 }, -}; +int +gf119_disp_oimm_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, + struct nv50_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/oimmgk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgk104.c deleted file mode 100644 index 0c09fe85e952..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgk104.c +++ /dev/null @@ -1,37 +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 "rootnv50.h" - -#include <nvif/class.h> - -const struct nv50_disp_pioc_oclass -gk104_disp_oimm_oclass = { - .base.oclass = GK104_DISP_OVERLAY, - .base.minver = 0, - .base.maxver = 0, - .ctor = nv50_disp_oimm_new, - .func = &gf119_disp_pioc_func, - .chid = { 9, 9 }, -}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgp102.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgp102.c index abf82365c671..30ffb1008505 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgp102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgp102.c @@ -22,16 +22,11 @@ * Authors: Ben Skeggs <bskeggs@redhat.com> */ #include "channv50.h" -#include "rootnv50.h" -#include <nvif/class.h> - -const struct nv50_disp_pioc_oclass -gp102_disp_oimm_oclass = { - .base.oclass = GK104_DISP_OVERLAY, - .base.minver = 0, - .base.maxver = 0, - .ctor = nv50_disp_oimm_new, - .func = &gf119_disp_pioc_func, - .chid = { 9, 13 }, -}; +int +gp102_disp_oimm_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, + struct nv50_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/oimmgt215.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgt215.c deleted file mode 100644 index 1281db28aebd..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgt215.c +++ /dev/null @@ -1,37 +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 "rootnv50.h" - -#include <nvif/class.h> - -const struct nv50_disp_pioc_oclass -gt215_disp_oimm_oclass = { - .base.oclass = GT214_DISP_OVERLAY, - .base.minver = 0, - .base.maxver = 0, - .ctor = nv50_disp_oimm_new, - .func = &nv50_disp_pioc_func, - .chid = { 5, 5 }, -}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmnv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmnv50.c index f3b0fa2c5924..0db99bfe9db9 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmnv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmnv50.c @@ -23,30 +23,26 @@ */ #include "channv50.h" #include "head.h" -#include "rootnv50.h" #include <core/client.h> -#include <nvif/class.h> #include <nvif/cl507b.h> #include <nvif/unpack.h> int -nv50_disp_oimm_new(const struct nv50_disp_chan_func *func, - const struct nv50_disp_chan_mthd *mthd, - struct nv50_disp_root *root, int ctrl, int user, - const struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +nv50_disp_oimm_new_(const struct nv50_disp_chan_func *func, + struct nv50_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 = data; + } *args = argv; struct nvkm_object *parent = oclass->parent; - struct nv50_disp *disp = root->disp; int head, ret = -ENOSYS; - nvif_ioctl(parent, "create disp overlay size %d\n", size); - if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) { + 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->base, args->v0.head)) @@ -55,16 +51,14 @@ nv50_disp_oimm_new(const struct nv50_disp_chan_func *func, } else return ret; - return nv50_disp_chan_new_(func, mthd, root, ctrl + head, user + head, + return nv50_disp_chan_new_(func, NULL, disp, ctrl + head, user + head, head, oclass, pobject); } -const struct nv50_disp_pioc_oclass -nv50_disp_oimm_oclass = { - .base.oclass = NV50_DISP_OVERLAY, - .base.minver = 0, - .base.maxver = 0, - .ctor = nv50_disp_oimm_new, - .func = &nv50_disp_pioc_func, - .chid = { 5, 5 }, -}; +int +nv50_disp_oimm_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, + struct nv50_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 index db6234eebc61..31b915d48699 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlyg84.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlyg84.c @@ -21,10 +21,7 @@ * * Authors: Ben Skeggs */ -#include "dmacnv50.h" -#include "rootnv50.h" - -#include <nvif/class.h> +#include "channv50.h" static const struct nv50_disp_mthd_list g84_disp_ovly_mthd_base = { @@ -54,8 +51,8 @@ g84_disp_ovly_mthd_base = { } }; -const struct nv50_disp_chan_mthd -g84_disp_ovly_chan_mthd = { +static const struct nv50_disp_chan_mthd +g84_disp_ovly_mthd = { .name = "Overlay", .addr = 0x000540, .prev = 0x000004, @@ -65,13 +62,10 @@ g84_disp_ovly_chan_mthd = { } }; -const struct nv50_disp_dmac_oclass -g84_disp_ovly_oclass = { - .base.oclass = G82_DISP_OVERLAY_CHANNEL_DMA, - .base.minver = 0, - .base.maxver = 0, - .ctor = nv50_disp_ovly_new, - .func = &nv50_disp_dmac_func, - .mthd = &g84_disp_ovly_chan_mthd, - .chid = 3, -}; +int +g84_disp_ovly_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, + struct nv50_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 index 5985879abd23..83fd534c44da 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygf119.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygf119.c @@ -21,10 +21,7 @@ * * Authors: Ben Skeggs */ -#include "dmacnv50.h" -#include "rootnv50.h" - -#include <nvif/class.h> +#include "channv50.h" static const struct nv50_disp_mthd_list gf119_disp_ovly_mthd_base = { @@ -79,7 +76,7 @@ gf119_disp_ovly_mthd_base = { }; static const struct nv50_disp_chan_mthd -gf119_disp_ovly_chan_mthd = { +gf119_disp_ovly_mthd = { .name = "Overlay", .addr = 0x001000, .prev = -0x020000, @@ -89,13 +86,10 @@ gf119_disp_ovly_chan_mthd = { } }; -const struct nv50_disp_dmac_oclass -gf119_disp_ovly_oclass = { - .base.oclass = GF110_DISP_OVERLAY_CONTROL_DMA, - .base.minver = 0, - .base.maxver = 0, - .ctor = nv50_disp_ovly_new, - .func = &gf119_disp_dmac_func, - .mthd = &gf119_disp_ovly_chan_mthd, - .chid = 5, -}; +int +gf119_disp_ovly_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, + struct nv50_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 index 2f0220b39f34..a7acacbc92c1 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygk104.c @@ -21,10 +21,7 @@ * * Authors: Ben Skeggs */ -#include "dmacnv50.h" -#include "rootnv50.h" - -#include <nvif/class.h> +#include "channv50.h" static const struct nv50_disp_mthd_list gk104_disp_ovly_mthd_base = { @@ -81,7 +78,7 @@ gk104_disp_ovly_mthd_base = { }; const struct nv50_disp_chan_mthd -gk104_disp_ovly_chan_mthd = { +gk104_disp_ovly_mthd = { .name = "Overlay", .addr = 0x001000, .prev = -0x020000, @@ -91,13 +88,10 @@ gk104_disp_ovly_chan_mthd = { } }; -const struct nv50_disp_dmac_oclass -gk104_disp_ovly_oclass = { - .base.oclass = GK104_DISP_OVERLAY_CONTROL_DMA, - .base.minver = 0, - .base.maxver = 0, - .ctor = nv50_disp_ovly_new, - .func = &gf119_disp_dmac_func, - .mthd = &gk104_disp_ovly_chan_mthd, - .chid = 5, -}; +int +gk104_disp_ovly_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, + struct nv50_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 index 589bd2f12b41..e0eca6ea914c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygp102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygp102.c @@ -21,18 +21,12 @@ * * Authors: Ben Skeggs */ -#include "dmacnv50.h" -#include "rootnv50.h" +#include "channv50.h" -#include <nvif/class.h> - -const struct nv50_disp_dmac_oclass -gp102_disp_ovly_oclass = { - .base.oclass = GK104_DISP_OVERLAY_CONTROL_DMA, - .base.minver = 0, - .base.maxver = 0, - .ctor = nv50_disp_ovly_new, - .func = &gp102_disp_dmac_func, - .mthd = &gk104_disp_ovly_chan_mthd, - .chid = 5, -}; +int +gp102_disp_ovly_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, + struct nv50_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 index f858053db83d..dc60cd00dc16 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygt200.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygt200.c @@ -21,10 +21,7 @@ * * Authors: Ben Skeggs */ -#include "dmacnv50.h" -#include "rootnv50.h" - -#include <nvif/class.h> +#include "channv50.h" static const struct nv50_disp_mthd_list gt200_disp_ovly_mthd_base = { @@ -58,7 +55,7 @@ gt200_disp_ovly_mthd_base = { }; static const struct nv50_disp_chan_mthd -gt200_disp_ovly_chan_mthd = { +gt200_disp_ovly_mthd = { .name = "Overlay", .addr = 0x000540, .prev = 0x000004, @@ -68,13 +65,10 @@ gt200_disp_ovly_chan_mthd = { } }; -const struct nv50_disp_dmac_oclass -gt200_disp_ovly_oclass = { - .base.oclass = GT200_DISP_OVERLAY_CHANNEL_DMA, - .base.minver = 0, - .base.maxver = 0, - .ctor = nv50_disp_ovly_new, - .func = &nv50_disp_dmac_func, - .mthd = >200_disp_ovly_chan_mthd, - .chid = 3, -}; +int +gt200_disp_ovly_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, + struct nv50_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/ovlygt215.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygt215.c deleted file mode 100644 index c947e1e16a37..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygt215.c +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2015 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 "dmacnv50.h" -#include "rootnv50.h" - -#include <nvif/class.h> - -const struct nv50_disp_dmac_oclass -gt215_disp_ovly_oclass = { - .base.oclass = GT214_DISP_OVERLAY_CHANNEL_DMA, - .base.minver = 0, - .base.maxver = 0, - .ctor = nv50_disp_ovly_new, - .func = &nv50_disp_dmac_func, - .mthd = &g84_disp_ovly_chan_mthd, - .chid = 3, -}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlynv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlynv50.c index 9ebaaa6e9e33..6974c12c4518 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlynv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlynv50.c @@ -21,33 +21,30 @@ * * Authors: Ben Skeggs */ -#include "dmacnv50.h" +#include "channv50.h" #include "head.h" -#include "rootnv50.h" #include <core/client.h> -#include <nvif/class.h> #include <nvif/cl507e.h> #include <nvif/unpack.h> int -nv50_disp_ovly_new(const struct nv50_disp_dmac_func *func, - const struct nv50_disp_chan_mthd *mthd, - struct nv50_disp_root *root, int chid, - const struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +nv50_disp_ovly_new_(const struct nv50_disp_chan_func *func, + const struct nv50_disp_chan_mthd *mthd, + struct nv50_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 = data; + } *args = argv; struct nvkm_object *parent = oclass->parent; - struct nv50_disp *disp = root->disp; int head, ret = -ENOSYS; u64 push; - nvif_ioctl(parent, "create disp overlay channel dma size %d\n", size); - if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) { + 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); @@ -58,7 +55,7 @@ nv50_disp_ovly_new(const struct nv50_disp_dmac_func *func, } else return ret; - return nv50_disp_dmac_new_(func, mthd, root, chid + head, + return nv50_disp_dmac_new_(func, mthd, disp, chid + head, head, push, oclass, pobject); } @@ -91,7 +88,7 @@ nv50_disp_ovly_mthd_base = { }; static const struct nv50_disp_chan_mthd -nv50_disp_ovly_chan_mthd = { +nv50_disp_ovly_mthd = { .name = "Overlay", .addr = 0x000540, .prev = 0x000004, @@ -101,13 +98,10 @@ nv50_disp_ovly_chan_mthd = { } }; -const struct nv50_disp_dmac_oclass -nv50_disp_ovly_oclass = { - .base.oclass = NV50_DISP_OVERLAY_CHANNEL_DMA, - .base.minver = 0, - .base.maxver = 0, - .ctor = nv50_disp_ovly_new, - .func = &nv50_disp_dmac_func, - .mthd = &nv50_disp_ovly_chan_mthd, - .chid = 3, -}; +int +nv50_disp_ovly_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, + struct nv50_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 index 0abaa6431943..5296e7bee813 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/piocgf119.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/piocgf119.c @@ -29,7 +29,7 @@ static void gf119_disp_pioc_fini(struct nv50_disp_chan *chan) { - struct nv50_disp *disp = chan->root->disp; + struct nv50_disp *disp = chan->disp; struct nvkm_subdev *subdev = &disp->base.engine.subdev; struct nvkm_device *device = subdev->device; int ctrl = chan->chid.ctrl; @@ -43,24 +43,17 @@ gf119_disp_pioc_fini(struct nv50_disp_chan *chan) nvkm_error(subdev, "ch %d fini: %08x\n", user, nvkm_rd32(device, 0x610490 + (ctrl * 0x10))); } - - /* disable error reporting and completion notification */ - nvkm_mask(device, 0x610090, 0x00000001 << user, 0x00000000); - nvkm_mask(device, 0x6100a0, 0x00000001 << user, 0x00000000); } static int gf119_disp_pioc_init(struct nv50_disp_chan *chan) { - struct nv50_disp *disp = chan->root->disp; + struct nv50_disp *disp = chan->disp; struct nvkm_subdev *subdev = &disp->base.engine.subdev; struct nvkm_device *device = subdev->device; int ctrl = chan->chid.ctrl; int user = chan->chid.user; - /* enable error reporting */ - nvkm_mask(device, 0x6100a0, 0x00000001 << user, 0x00000001 << user); - /* activate channel */ nvkm_wr32(device, 0x610490 + (ctrl * 0x10), 0x00000001); if (nvkm_msec(device, 2000, @@ -80,4 +73,6 @@ 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 index 0211e0e8a35f..4faed6fce682 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/piocnv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/piocnv50.c @@ -29,7 +29,7 @@ static void nv50_disp_pioc_fini(struct nv50_disp_chan *chan) { - struct nv50_disp *disp = chan->root->disp; + struct nv50_disp *disp = chan->disp; struct nvkm_subdev *subdev = &disp->base.engine.subdev; struct nvkm_device *device = subdev->device; int ctrl = chan->chid.ctrl; @@ -48,7 +48,7 @@ nv50_disp_pioc_fini(struct nv50_disp_chan *chan) static int nv50_disp_pioc_init(struct nv50_disp_chan *chan) { - struct nv50_disp *disp = chan->root->disp; + struct nv50_disp *disp = chan->disp; struct nvkm_subdev *subdev = &disp->base.engine.subdev; struct nvkm_device *device = subdev->device; int ctrl = chan->chid.ctrl; @@ -82,4 +82,6 @@ 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 index 99b3b9050635..e997a207f546 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/piornv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/piornv50.c @@ -127,8 +127,13 @@ nv50_pior = { int nv50_pior_new(struct nvkm_disp *disp, int id) { - struct nvkm_device *device = disp->engine.subdev.device; - if (!(nvkm_rd32(device, 0x610184) & (0x10000000 << id))) - return 0; 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 6c9bfff6d043..ef66c5f38ad5 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/priv.h @@ -12,6 +12,9 @@ void nvkm_disp_vblank(struct nvkm_disp *, int head); struct nvkm_disp_func { void *(*dtor)(struct nvkm_disp *); + int (*oneinit)(struct nvkm_disp *); + int (*init)(struct nvkm_disp *); + void (*fini)(struct nvkm_disp *); void (*intr)(struct nvkm_disp *); const struct nvkm_disp_oclass *(*root)(struct nvkm_disp *); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootg84.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootg84.c index 721e4f74d1fc..1ed371fd7ddf 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootg84.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootg84.c @@ -22,22 +22,19 @@ * Authors: Ben Skeggs */ #include "rootnv50.h" -#include "dmacnv50.h" +#include "channv50.h" #include <nvif/class.h> static const struct nv50_disp_root_func g84_disp_root = { - .init = nv50_disp_root_init, - .fini = nv50_disp_root_fini, - .dmac = { - &g84_disp_core_oclass, - &g84_disp_base_oclass, - &g84_disp_ovly_oclass, - }, - .pioc = { - &g84_disp_oimm_oclass, - &g84_disp_curs_oclass, + .user = { + {{0,0,G82_DISP_CURSOR }, nv50_disp_curs_new }, + {{0,0,G82_DISP_OVERLAY }, nv50_disp_oimm_new }, + {{0,0,G82_DISP_BASE_CHANNEL_DMA }, g84_disp_base_new }, + {{0,0,G82_DISP_CORE_CHANNEL_DMA }, g84_disp_core_new }, + {{0,0,G82_DISP_OVERLAY_CHANNEL_DMA}, g84_disp_ovly_new }, + {} }, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootg94.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootg94.c index 9493f6edf62b..ef579eb00238 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootg94.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootg94.c @@ -22,22 +22,19 @@ * Authors: Ben Skeggs */ #include "rootnv50.h" -#include "dmacnv50.h" +#include "channv50.h" #include <nvif/class.h> static const struct nv50_disp_root_func g94_disp_root = { - .init = nv50_disp_root_init, - .fini = nv50_disp_root_fini, - .dmac = { - &g94_disp_core_oclass, - >200_disp_base_oclass, - >200_disp_ovly_oclass, - }, - .pioc = { - &g84_disp_oimm_oclass, - &g84_disp_curs_oclass, + .user = { + {{0,0, G82_DISP_CURSOR }, nv50_disp_curs_new }, + {{0,0, G82_DISP_OVERLAY }, nv50_disp_oimm_new }, + {{0,0,GT200_DISP_BASE_CHANNEL_DMA }, g84_disp_base_new }, + {{0,0,GT206_DISP_CORE_CHANNEL_DMA }, g94_disp_core_new }, + {{0,0,GT200_DISP_OVERLAY_CHANNEL_DMA}, gt200_disp_ovly_new }, + {} }, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgf119.c index 333c8424b413..fe011165dc02 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgf119.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgf119.c @@ -22,104 +22,19 @@ * Authors: Ben Skeggs */ #include "rootnv50.h" -#include "head.h" -#include "dmacnv50.h" - -#include <core/ramht.h> -#include <subdev/timer.h> +#include "channv50.h" #include <nvif/class.h> -void -gf119_disp_root_fini(struct nv50_disp_root *root) -{ - struct nvkm_device *device = root->disp->base.engine.subdev.device; - /* disable all interrupts */ - nvkm_wr32(device, 0x6100b0, 0x00000000); -} - -int -gf119_disp_root_init(struct nv50_disp_root *root) -{ - struct nv50_disp *disp = root->disp; - struct nvkm_head *head; - struct nvkm_device *device = disp->base.engine.subdev.device; - u32 tmp; - int i; - - /* The below segments of code copying values from one register to - * another appear to inform EVO of the display capabilities or - * something similar. - */ - - /* ... CRTC caps */ - list_for_each_entry(head, &disp->base.head, head) { - const u32 hoff = head->id * 0x800; - tmp = nvkm_rd32(device, 0x616104 + hoff); - nvkm_wr32(device, 0x6101b4 + hoff, tmp); - tmp = nvkm_rd32(device, 0x616108 + hoff); - nvkm_wr32(device, 0x6101b8 + hoff, tmp); - tmp = nvkm_rd32(device, 0x61610c + hoff); - nvkm_wr32(device, 0x6101bc + hoff, tmp); - } - - /* ... DAC caps */ - for (i = 0; i < disp->func->dac.nr; i++) { - tmp = nvkm_rd32(device, 0x61a000 + (i * 0x800)); - nvkm_wr32(device, 0x6101c0 + (i * 0x800), tmp); - } - - /* ... SOR caps */ - for (i = 0; i < disp->func->sor.nr; i++) { - tmp = nvkm_rd32(device, 0x61c000 + (i * 0x800)); - nvkm_wr32(device, 0x6301c4 + (i * 0x800), tmp); - } - - /* steal display away from vbios, or something like that */ - if (nvkm_rd32(device, 0x6100ac) & 0x00000100) { - nvkm_wr32(device, 0x6100ac, 0x00000100); - nvkm_mask(device, 0x6194e8, 0x00000001, 0x00000000); - if (nvkm_msec(device, 2000, - if (!(nvkm_rd32(device, 0x6194e8) & 0x00000002)) - break; - ) < 0) - return -EBUSY; - } - - /* point at display engine memory area (hash table, objects) */ - nvkm_wr32(device, 0x610010, (root->instmem->addr >> 8) | 9); - - /* enable supervisor interrupts, disable everything else */ - nvkm_wr32(device, 0x610090, 0x00000000); - nvkm_wr32(device, 0x6100a0, 0x00000000); - nvkm_wr32(device, 0x6100b0, 0x00000307); - - /* disable underflow reporting, preventing an intermittent issue - * on some gk104 boards where the production vbios left this - * setting enabled by default. - * - * ftp://download.nvidia.com/open-gpu-doc/gk104-disable-underflow-reporting/1/gk104-disable-underflow-reporting.txt - */ - list_for_each_entry(head, &disp->base.head, head) { - const u32 hoff = head->id * 0x800; - nvkm_mask(device, 0x616308 + hoff, 0x00000111, 0x00000010); - } - - return 0; -} - static const struct nv50_disp_root_func gf119_disp_root = { - .init = gf119_disp_root_init, - .fini = gf119_disp_root_fini, - .dmac = { - &gf119_disp_core_oclass, - &gf119_disp_base_oclass, - &gf119_disp_ovly_oclass, - }, - .pioc = { - &gf119_disp_oimm_oclass, - &gf119_disp_curs_oclass, + .user = { + {{0,0,GF110_DISP_CURSOR }, gf119_disp_curs_new }, + {{0,0,GF110_DISP_OVERLAY }, gf119_disp_oimm_new }, + {{0,0,GF110_DISP_BASE_CHANNEL_DMA }, gf119_disp_base_new }, + {{0,0,GF110_DISP_CORE_CHANNEL_DMA }, gf119_disp_core_new }, + {{0,0,GF110_DISP_OVERLAY_CONTROL_DMA}, gf119_disp_ovly_new }, + {} }, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgk104.c index 0bfdb1d1c6ab..9e8ffd348b50 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgk104.c @@ -22,22 +22,19 @@ * Authors: Ben Skeggs */ #include "rootnv50.h" -#include "dmacnv50.h" +#include "channv50.h" #include <nvif/class.h> static const struct nv50_disp_root_func gk104_disp_root = { - .init = gf119_disp_root_init, - .fini = gf119_disp_root_fini, - .dmac = { - &gk104_disp_core_oclass, - &gk104_disp_base_oclass, - &gk104_disp_ovly_oclass, - }, - .pioc = { - &gk104_disp_oimm_oclass, - &gk104_disp_curs_oclass, + .user = { + {{0,0,GK104_DISP_CURSOR }, gf119_disp_curs_new }, + {{0,0,GK104_DISP_OVERLAY }, gf119_disp_oimm_new }, + {{0,0,GK104_DISP_BASE_CHANNEL_DMA }, gf119_disp_base_new }, + {{0,0,GK104_DISP_CORE_CHANNEL_DMA }, gk104_disp_core_new }, + {{0,0,GK104_DISP_OVERLAY_CONTROL_DMA}, gk104_disp_ovly_new }, + {} }, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgk110.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgk110.c index 1e8dbed8a67c..dc85cc1c9490 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgk110.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgk110.c @@ -22,22 +22,19 @@ * Authors: Ben Skeggs */ #include "rootnv50.h" -#include "dmacnv50.h" +#include "channv50.h" #include <nvif/class.h> static const struct nv50_disp_root_func gk110_disp_root = { - .init = gf119_disp_root_init, - .fini = gf119_disp_root_fini, - .dmac = { - &gk110_disp_core_oclass, - &gk110_disp_base_oclass, - &gk104_disp_ovly_oclass, - }, - .pioc = { - &gk104_disp_oimm_oclass, - &gk104_disp_curs_oclass, + .user = { + {{0,0,GK104_DISP_CURSOR }, gf119_disp_curs_new }, + {{0,0,GK104_DISP_OVERLAY }, gf119_disp_oimm_new }, + {{0,0,GK110_DISP_BASE_CHANNEL_DMA }, gf119_disp_base_new }, + {{0,0,GK110_DISP_CORE_CHANNEL_DMA }, gk104_disp_core_new }, + {{0,0,GK104_DISP_OVERLAY_CONTROL_DMA}, gk104_disp_ovly_new }, + {} }, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgm107.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgm107.c index 44c55be69e99..e0181ca08840 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgm107.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgm107.c @@ -22,22 +22,19 @@ * Authors: Ben Skeggs */ #include "rootnv50.h" -#include "dmacnv50.h" +#include "channv50.h" #include <nvif/class.h> static const struct nv50_disp_root_func gm107_disp_root = { - .init = gf119_disp_root_init, - .fini = gf119_disp_root_fini, - .dmac = { - &gm107_disp_core_oclass, - &gk110_disp_base_oclass, - &gk104_disp_ovly_oclass, - }, - .pioc = { - &gk104_disp_oimm_oclass, - &gk104_disp_curs_oclass, + .user = { + {{0,0,GK104_DISP_CURSOR }, gf119_disp_curs_new }, + {{0,0,GK104_DISP_OVERLAY }, gf119_disp_oimm_new }, + {{0,0,GK110_DISP_BASE_CHANNEL_DMA }, gf119_disp_base_new }, + {{0,0,GM107_DISP_CORE_CHANNEL_DMA }, gk104_disp_core_new }, + {{0,0,GK104_DISP_OVERLAY_CONTROL_DMA}, gk104_disp_ovly_new }, + {} }, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgm200.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgm200.c index 38f5ee1dfc58..e5e590e19f62 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgm200.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgm200.c @@ -22,22 +22,19 @@ * Authors: Ben Skeggs */ #include "rootnv50.h" -#include "dmacnv50.h" +#include "channv50.h" #include <nvif/class.h> static const struct nv50_disp_root_func gm200_disp_root = { - .init = gf119_disp_root_init, - .fini = gf119_disp_root_fini, - .dmac = { - &gm200_disp_core_oclass, - &gk110_disp_base_oclass, - &gk104_disp_ovly_oclass, - }, - .pioc = { - &gk104_disp_oimm_oclass, - &gk104_disp_curs_oclass, + .user = { + {{0,0,GK104_DISP_CURSOR }, gf119_disp_curs_new }, + {{0,0,GK104_DISP_OVERLAY }, gf119_disp_oimm_new }, + {{0,0,GK110_DISP_BASE_CHANNEL_DMA }, gf119_disp_base_new }, + {{0,0,GM200_DISP_CORE_CHANNEL_DMA }, gk104_disp_core_new }, + {{0,0,GK104_DISP_OVERLAY_CONTROL_DMA}, gk104_disp_ovly_new }, + {} }, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgp100.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgp100.c index ac8fdd728ec6..762a1a922e05 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgp100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgp100.c @@ -22,22 +22,19 @@ * Authors: Ben Skeggs <bskeggs@redhat.com> */ #include "rootnv50.h" -#include "dmacnv50.h" +#include "channv50.h" #include <nvif/class.h> static const struct nv50_disp_root_func gp100_disp_root = { - .init = gf119_disp_root_init, - .fini = gf119_disp_root_fini, - .dmac = { - &gp100_disp_core_oclass, - &gk110_disp_base_oclass, - &gk104_disp_ovly_oclass, - }, - .pioc = { - &gk104_disp_oimm_oclass, - &gk104_disp_curs_oclass, + .user = { + {{0,0,GK104_DISP_CURSOR }, gf119_disp_curs_new }, + {{0,0,GK104_DISP_OVERLAY }, gf119_disp_oimm_new }, + {{0,0,GK110_DISP_BASE_CHANNEL_DMA }, gf119_disp_base_new }, + {{0,0,GP100_DISP_CORE_CHANNEL_DMA }, gk104_disp_core_new }, + {{0,0,GK104_DISP_OVERLAY_CONTROL_DMA}, gk104_disp_ovly_new }, + {} }, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgp102.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgp102.c index 37122ca579ad..c7f00946c9af 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgp102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgp102.c @@ -22,22 +22,19 @@ * Authors: Ben Skeggs <bskeggs@redhat.com> */ #include "rootnv50.h" -#include "dmacnv50.h" +#include "channv50.h" #include <nvif/class.h> static const struct nv50_disp_root_func gp102_disp_root = { - .init = gf119_disp_root_init, - .fini = gf119_disp_root_fini, - .dmac = { - &gp102_disp_core_oclass, - &gp102_disp_base_oclass, - &gp102_disp_ovly_oclass, - }, - .pioc = { - &gp102_disp_oimm_oclass, - &gp102_disp_curs_oclass, + .user = { + {{0,0,GK104_DISP_CURSOR }, gp102_disp_curs_new }, + {{0,0,GK104_DISP_OVERLAY }, gp102_disp_oimm_new }, + {{0,0,GK110_DISP_BASE_CHANNEL_DMA }, gp102_disp_base_new }, + {{0,0,GP102_DISP_CORE_CHANNEL_DMA }, gp102_disp_core_new }, + {{0,0,GK104_DISP_OVERLAY_CONTROL_DMA}, gp102_disp_ovly_new }, + {} }, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgt200.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgt200.c index 124a0c24f92c..a6963654087c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgt200.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgt200.c @@ -22,22 +22,19 @@ * Authors: Ben Skeggs */ #include "rootnv50.h" -#include "dmacnv50.h" +#include "channv50.h" #include <nvif/class.h> static const struct nv50_disp_root_func gt200_disp_root = { - .init = nv50_disp_root_init, - .fini = nv50_disp_root_fini, - .dmac = { - >200_disp_core_oclass, - >200_disp_base_oclass, - >200_disp_ovly_oclass, - }, - .pioc = { - &g84_disp_oimm_oclass, - &g84_disp_curs_oclass, + .user = { + {{0,0, G82_DISP_CURSOR }, nv50_disp_curs_new }, + {{0,0, G82_DISP_OVERLAY }, nv50_disp_oimm_new }, + {{0,0,GT200_DISP_BASE_CHANNEL_DMA }, g84_disp_base_new }, + {{0,0,GT200_DISP_CORE_CHANNEL_DMA }, g84_disp_core_new }, + {{0,0,GT200_DISP_OVERLAY_CHANNEL_DMA}, gt200_disp_ovly_new }, + {} }, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgt215.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgt215.c index dff52f30668b..4fe0a3ae8891 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgt215.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgt215.c @@ -22,22 +22,19 @@ * Authors: Ben Skeggs */ #include "rootnv50.h" -#include "dmacnv50.h" +#include "channv50.h" #include <nvif/class.h> static const struct nv50_disp_root_func gt215_disp_root = { - .init = nv50_disp_root_init, - .fini = nv50_disp_root_fini, - .dmac = { - >215_disp_core_oclass, - >215_disp_base_oclass, - >215_disp_ovly_oclass, - }, - .pioc = { - >215_disp_oimm_oclass, - >215_disp_curs_oclass, + .user = { + {{0,0,GT214_DISP_CURSOR }, nv50_disp_curs_new }, + {{0,0,GT214_DISP_OVERLAY }, nv50_disp_oimm_new }, + {{0,0,GT214_DISP_BASE_CHANNEL_DMA }, g84_disp_base_new }, + {{0,0,GT214_DISP_CORE_CHANNEL_DMA }, g94_disp_core_new }, + {{0,0,GT214_DISP_OVERLAY_CHANNEL_DMA}, g84_disp_ovly_new }, + {} }, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursg84.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgv100.c index fa781b5a7e07..9c658d632d37 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursg84.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgv100.c @@ -1,5 +1,5 @@ /* - * Copyright 2015 Red Hat Inc. + * 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"), @@ -18,20 +18,35 @@ * 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 "rootnv50.h" +#include "channv50.h" #include <nvif/class.h> -const struct nv50_disp_pioc_oclass -g84_disp_curs_oclass = { - .base.oclass = G82_DISP_CURSOR, - .base.minver = 0, - .base.maxver = 0, - .ctor = nv50_disp_curs_new, - .func = &nv50_disp_pioc_func, - .chid = { 7, 7 }, +static const struct nv50_disp_root_func +gv100_disp_root = { + .user = { + {{0,0,GV100_DISP_CURSOR }, gv100_disp_curs_new }, + {{0,0,GV100_DISP_WINDOW_IMM_CHANNEL_DMA}, gv100_disp_wimm_new }, + {{0,0,GV100_DISP_CORE_CHANNEL_DMA }, gv100_disp_core_new }, + {{0,0,GV100_DISP_WINDOW_CHANNEL_DMA }, gv100_disp_wndw_new }, + {} + }, +}; + +static int +gv100_disp_root_new(struct nvkm_disp *disp, const struct nvkm_oclass *oclass, + void *data, u32 size, struct nvkm_object **pobject) +{ + return nv50_disp_root_new_(&gv100_disp_root, disp, oclass, + data, size, pobject); +} + +const struct nvkm_disp_oclass +gv100_disp_root_oclass = { + .base.oclass = GV100_DISP, + .base.minver = -1, + .base.maxver = -1, + .ctor = gv100_disp_root_new, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c index 1208524aae14..3aa5a2879239 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c @@ -22,14 +22,12 @@ * Authors: Ben Skeggs */ #include "rootnv50.h" -#include "dmacnv50.h" +#include "channv50.h" #include "dp.h" #include "head.h" #include "ior.h" #include <core/client.h> -#include <core/ramht.h> -#include <subdev/timer.h> #include <nvif/class.h> #include <nvif/cl5070.h> @@ -271,23 +269,12 @@ nv50_disp_root_mthd_(struct nvkm_object *object, u32 mthd, void *data, u32 size) } static int -nv50_disp_root_dmac_new_(const struct nvkm_oclass *oclass, - void *data, u32 size, struct nvkm_object **pobject) +nv50_disp_root_child_new_(const struct nvkm_oclass *oclass, + void *argv, u32 argc, struct nvkm_object **pobject) { - const struct nv50_disp_dmac_oclass *sclass = oclass->priv; - struct nv50_disp_root *root = nv50_disp_root(oclass->parent); - return sclass->ctor(sclass->func, sclass->mthd, root, sclass->chid, - oclass, data, size, pobject); -} - -static int -nv50_disp_root_pioc_new_(const struct nvkm_oclass *oclass, - void *data, u32 size, struct nvkm_object **pobject) -{ - const struct nv50_disp_pioc_oclass *sclass = oclass->priv; - struct nv50_disp_root *root = nv50_disp_root(oclass->parent); - return sclass->ctor(sclass->func, sclass->mthd, root, sclass->chid.ctrl, - sclass->chid.user, oclass, data, size, pobject); + struct nv50_disp *disp = nv50_disp_root(oclass->parent)->disp; + const struct nv50_disp_user *user = oclass->priv; + return user->ctor(oclass, argv, argc, disp, pobject); } static int @@ -296,68 +283,26 @@ nv50_disp_root_child_get_(struct nvkm_object *object, int index, { struct nv50_disp_root *root = nv50_disp_root(object); - if (index < ARRAY_SIZE(root->func->dmac)) { - sclass->base = root->func->dmac[index]->base; - sclass->priv = root->func->dmac[index]; - sclass->ctor = nv50_disp_root_dmac_new_; - return 0; - } - - index -= ARRAY_SIZE(root->func->dmac); - - if (index < ARRAY_SIZE(root->func->pioc)) { - sclass->base = root->func->pioc[index]->base; - sclass->priv = root->func->pioc[index]; - sclass->ctor = nv50_disp_root_pioc_new_; + if (root->func->user[index].ctor) { + sclass->base = root->func->user[index].base; + sclass->priv = root->func->user + index; + sclass->ctor = nv50_disp_root_child_new_; return 0; } return -EINVAL; } -static int -nv50_disp_root_fini_(struct nvkm_object *object, bool suspend) -{ - struct nv50_disp_root *root = nv50_disp_root(object); - root->func->fini(root); - return 0; -} - -static int -nv50_disp_root_init_(struct nvkm_object *object) -{ - struct nv50_disp_root *root = nv50_disp_root(object); - struct nvkm_ior *ior; - int ret; - - ret = root->func->init(root); - if (ret) - return ret; - - /* Set 'normal' (ie. when it's attached to a head) state for - * each output resource to 'fully enabled'. - */ - list_for_each_entry(ior, &root->disp->base.ior, head) { - ior->func->power(ior, true, true, true, true, true); - } - - return 0; -} - static void * nv50_disp_root_dtor_(struct nvkm_object *object) { struct nv50_disp_root *root = nv50_disp_root(object); - nvkm_ramht_del(&root->ramht); - nvkm_gpuobj_del(&root->instmem); return root; } static const struct nvkm_object_func nv50_disp_root_ = { .dtor = nv50_disp_root_dtor_, - .init = nv50_disp_root_init_, - .fini = nv50_disp_root_fini_, .mthd = nv50_disp_root_mthd_, .ntfy = nvkm_disp_ntfy, .sclass = nv50_disp_root_child_get_, @@ -370,8 +315,6 @@ nv50_disp_root_new_(const struct nv50_disp_root_func *func, { struct nv50_disp *disp = nv50_disp(base); struct nv50_disp_root *root; - struct nvkm_device *device = disp->base.engine.subdev.device; - int ret; if (!(root = kzalloc(sizeof(*root), GFP_KERNEL))) return -ENOMEM; @@ -380,102 +323,18 @@ nv50_disp_root_new_(const struct nv50_disp_root_func *func, nvkm_object_ctor(&nv50_disp_root_, oclass, &root->object); root->func = func; root->disp = disp; - - ret = nvkm_gpuobj_new(disp->base.engine.subdev.device, 0x10000, 0x10000, - false, NULL, &root->instmem); - if (ret) - return ret; - - return nvkm_ramht_new(device, 0x1000, 0, root->instmem, &root->ramht); -} - -void -nv50_disp_root_fini(struct nv50_disp_root *root) -{ - struct nvkm_device *device = root->disp->base.engine.subdev.device; - /* disable all interrupts */ - nvkm_wr32(device, 0x610024, 0x00000000); - nvkm_wr32(device, 0x610020, 0x00000000); -} - -int -nv50_disp_root_init(struct nv50_disp_root *root) -{ - struct nv50_disp *disp = root->disp; - struct nvkm_head *head; - struct nvkm_device *device = disp->base.engine.subdev.device; - u32 tmp; - int i; - - /* The below segments of code copying values from one register to - * another appear to inform EVO of the display capabilities or - * something similar. NFI what the 0x614004 caps are for.. - */ - tmp = nvkm_rd32(device, 0x614004); - nvkm_wr32(device, 0x610184, tmp); - - /* ... CRTC caps */ - list_for_each_entry(head, &disp->base.head, head) { - tmp = nvkm_rd32(device, 0x616100 + (head->id * 0x800)); - nvkm_wr32(device, 0x610190 + (head->id * 0x10), tmp); - tmp = nvkm_rd32(device, 0x616104 + (head->id * 0x800)); - nvkm_wr32(device, 0x610194 + (head->id * 0x10), tmp); - tmp = nvkm_rd32(device, 0x616108 + (head->id * 0x800)); - nvkm_wr32(device, 0x610198 + (head->id * 0x10), tmp); - tmp = nvkm_rd32(device, 0x61610c + (head->id * 0x800)); - nvkm_wr32(device, 0x61019c + (head->id * 0x10), tmp); - } - - /* ... DAC caps */ - for (i = 0; i < disp->func->dac.nr; i++) { - tmp = nvkm_rd32(device, 0x61a000 + (i * 0x800)); - nvkm_wr32(device, 0x6101d0 + (i * 0x04), tmp); - } - - /* ... SOR caps */ - for (i = 0; i < disp->func->sor.nr; i++) { - tmp = nvkm_rd32(device, 0x61c000 + (i * 0x800)); - nvkm_wr32(device, 0x6101e0 + (i * 0x04), tmp); - } - - /* ... PIOR caps */ - for (i = 0; i < disp->func->pior.nr; i++) { - tmp = nvkm_rd32(device, 0x61e000 + (i * 0x800)); - nvkm_wr32(device, 0x6101f0 + (i * 0x04), tmp); - } - - /* steal display away from vbios, or something like that */ - if (nvkm_rd32(device, 0x610024) & 0x00000100) { - nvkm_wr32(device, 0x610024, 0x00000100); - nvkm_mask(device, 0x6194e8, 0x00000001, 0x00000000); - if (nvkm_msec(device, 2000, - if (!(nvkm_rd32(device, 0x6194e8) & 0x00000002)) - break; - ) < 0) - return -EBUSY; - } - - /* point at display engine memory area (hash table, objects) */ - nvkm_wr32(device, 0x610010, (root->instmem->addr >> 8) | 9); - - /* enable supervisor interrupts, disable everything else */ - nvkm_wr32(device, 0x61002c, 0x00000370); - nvkm_wr32(device, 0x610028, 0x00000000); return 0; } static const struct nv50_disp_root_func nv50_disp_root = { - .init = nv50_disp_root_init, - .fini = nv50_disp_root_fini, - .dmac = { - &nv50_disp_core_oclass, - &nv50_disp_base_oclass, - &nv50_disp_ovly_oclass, - }, - .pioc = { - &nv50_disp_oimm_oclass, - &nv50_disp_curs_oclass, + .user = { + {{0,0,NV50_DISP_CURSOR }, nv50_disp_curs_new }, + {{0,0,NV50_DISP_OVERLAY }, nv50_disp_oimm_new }, + {{0,0,NV50_DISP_BASE_CHANNEL_DMA }, nv50_disp_base_new }, + {{0,0,NV50_DISP_CORE_CHANNEL_DMA }, nv50_disp_core_new }, + {{0,0,NV50_DISP_OVERLAY_CHANNEL_DMA}, nv50_disp_ovly_new }, + {} }, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.h index 4818fa69ae6c..6ca4f9184b51 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.h @@ -2,34 +2,27 @@ #ifndef __NV50_DISP_ROOT_H__ #define __NV50_DISP_ROOT_H__ #define nv50_disp_root(p) container_of((p), struct nv50_disp_root, object) +#include <core/object.h> #include "nv50.h" -#include "channv50.h" -#include "dmacnv50.h" struct nv50_disp_root { const struct nv50_disp_root_func *func; struct nv50_disp *disp; struct nvkm_object object; - - struct nvkm_gpuobj *instmem; - struct nvkm_ramht *ramht; }; struct nv50_disp_root_func { - int (*init)(struct nv50_disp_root *); - void (*fini)(struct nv50_disp_root *); - const struct nv50_disp_dmac_oclass *dmac[3]; - const struct nv50_disp_pioc_oclass *pioc[2]; + int blah; + struct nv50_disp_user { + struct nvkm_sclass base; + int (*ctor)(const struct nvkm_oclass *, void *argv, u32 argc, + struct nv50_disp *, struct nvkm_object **); + } user[]; }; int nv50_disp_root_new_(const struct nv50_disp_root_func *, struct nvkm_disp *, const struct nvkm_oclass *, void *data, u32 size, struct nvkm_object **); -int nv50_disp_root_init(struct nv50_disp_root *); -void nv50_disp_root_fini(struct nv50_disp_root *); - -int gf119_disp_root_init(struct nv50_disp_root *); -void gf119_disp_root_fini(struct nv50_disp_root *); extern const struct nvkm_disp_oclass nv50_disp_root_oclass; extern const struct nvkm_disp_oclass g84_disp_root_oclass; @@ -43,4 +36,5 @@ extern const struct nvkm_disp_oclass gm107_disp_root_oclass; extern const struct nvkm_disp_oclass gm200_disp_root_oclass; extern const struct nvkm_disp_oclass gp100_disp_root_oclass; extern const struct nvkm_disp_oclass gp102_disp_root_oclass; +extern const struct nvkm_disp_oclass gv100_disp_root_oclass; #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorg84.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorg84.c index f40b909b4ca2..ec3a7db08118 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorg84.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorg84.c @@ -34,5 +34,5 @@ g84_sor = { int g84_sor_new(struct nvkm_disp *disp, int id) { - return nv50_sor_new_(&g84_sor, disp, 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 index 49aeafde0031..4d59d02525d9 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorg94.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorg94.c @@ -279,5 +279,13 @@ g94_sor = { int g94_sor_new(struct nvkm_disp *disp, int id) { - return nv50_sor_new_(&g94_sor, disp, 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/sorgf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgf119.c index 700fc754f28a..e6e6dfbb1283 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgf119.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgf119.c @@ -152,15 +152,6 @@ gf119_sor_state(struct nvkm_ior *sor, struct nvkm_ior_state *state) state->head = ctrl & 0x0000000f; } -int -gf119_sor_new_(const struct nvkm_ior_func *func, struct nvkm_disp *disp, int id) -{ - struct nvkm_device *device = disp->engine.subdev.device; - if (!(nvkm_rd32(device, 0x612004) & (0x00000100 << id))) - return 0; - return nvkm_ior_new_(func, disp, SOR, id); -} - static const struct nvkm_ior_func gf119_sor = { .state = gf119_sor_state, @@ -189,5 +180,13 @@ gf119_sor = { int gf119_sor_new(struct nvkm_disp *disp, int id) { - return gf119_sor_new_(&gf119_sor, disp, 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 index a1547bdf490b..b94090edaebf 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgk104.c @@ -49,5 +49,5 @@ gk104_sor = { int gk104_sor_new(struct nvkm_disp *disp, int id) { - return gf119_sor_new_(&gk104_sor, disp, 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 index 60230957d82b..e6965dec09c9 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm107.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm107.c @@ -63,5 +63,5 @@ gm107_sor = { int gm107_sor_new(struct nvkm_disp *disp, int id) { - return gf119_sor_new_(&gm107_sor, disp, 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 index f9b8107aa2a2..d892bdf04034 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm200.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm200.c @@ -23,7 +23,7 @@ */ #include "ior.h" -static void +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; @@ -45,7 +45,7 @@ gm200_sor_dp_drive(struct nvkm_ior *sor, int ln, int pc, int dc, int pe, int pu) nvkm_wr32(device, 0x61c13c + loff, data[3] | (pc << shift)); } -static void +void gm200_sor_route_set(struct nvkm_outp *outp, struct nvkm_ior *ior) { struct nvkm_device *device = outp->disp->engine.subdev.device; @@ -62,7 +62,7 @@ gm200_sor_route_set(struct nvkm_outp *outp, struct nvkm_ior *ior) nvkm_mask(device, 0x612388 + moff, 0x0000001f, link << 4 | sor); } -static int +int gm200_sor_route_get(struct nvkm_outp *outp, int *link) { struct nvkm_device *device = outp->disp->engine.subdev.device; @@ -120,5 +120,5 @@ gm200_sor = { int gm200_sor_new(struct nvkm_disp *disp, int id) { - return gf119_sor_new_(&gm200_sor, disp, id); + return nvkm_ior_new_(&gm200_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 index da228b54b43e..54d134d4ca1d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgt215.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgt215.c @@ -65,5 +65,5 @@ gt215_sor = { int gt215_sor_new(struct nvkm_disp *disp, int id) { - return nv50_sor_new_(>215_sor, disp, 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 new file mode 100644 index 000000000000..040db8a338de --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgv100.c @@ -0,0 +1,120 @@ +/* + * Copyright 2018 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ +#include "ior.h" + +#include <subdev/timer.h> + +static 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); +} + +static 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); +} + +static 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; + ); +} + +static 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 = { + .route = { + .get = gm200_sor_route_get, + .set = gm200_sor_route_set, + }, + .state = gv100_sor_state, + .power = nv50_sor_power, + .clock = gf119_sor_clock, + .hdmi = { + .ctrl = gv100_hdmi_ctrl, + }, + .dp = { + .lanes = { 0, 1, 2, 3 }, + .links = 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, + }, +}; + +int +gv100_sor_new(struct nvkm_disp *disp, int 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 index c0179ccb956d..8a70dd25b13a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sormcp77.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sormcp77.c @@ -44,5 +44,5 @@ mcp77_sor = { int mcp77_sor_new(struct nvkm_disp *disp, int id) { - return nv50_sor_new_(&mcp77_sor, disp, 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 index 9bb01cd96697..eac9c5be9166 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sormcp89.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sormcp89.c @@ -49,5 +49,5 @@ mcp89_sor = { int mcp89_sor_new(struct nvkm_disp *disp, int id) { - return nv50_sor_new_(&mcp89_sor, disp, 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 index f3ebd0c22e7d..b4729f8798af 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sornv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sornv50.c @@ -84,15 +84,6 @@ nv50_sor_state(struct nvkm_ior *sor, struct nvkm_ior_state *state) state->head = ctrl & 0x00000003; } -int -nv50_sor_new_(const struct nvkm_ior_func *func, struct nvkm_disp *disp, int id) -{ - struct nvkm_device *device = disp->engine.subdev.device; - if (!(nvkm_rd32(device, 0x610184) & (0x01000000 << id))) - return 0; - return nvkm_ior_new_(func, disp, SOR, id); -} - static const struct nvkm_ior_func nv50_sor = { .state = nv50_sor_state, @@ -103,5 +94,13 @@ nv50_sor = { int nv50_sor_new(struct nvkm_disp *disp, int id) { - return nv50_sor_new_(&nv50_sor, disp, 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/wimmgv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/wimmgv100.c new file mode 100644 index 000000000000..89d783368b4f --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/wimmgv100.c @@ -0,0 +1,82 @@ +/* + * 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->base.engine.subdev.device; + const u32 mask = 0x00000001 << chan->head; + const u32 data = en ? mask : 0; + nvkm_mask(device, 0x611da8, mask, data); +} + +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 nv50_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 nv50_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 new file mode 100644 index 000000000000..98911805aabf --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/wndwgv100.c @@ -0,0 +1,184 @@ +/* + * 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 }, + {} + } +}; + +const struct nv50_disp_chan_mthd +gv100_disp_wndw_mthd = { + .name = "Base", + .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->base.engine.subdev.device; + const u32 mask = 0x00000001 << chan->head; + const u32 data = en ? mask : 0; + nvkm_mask(device, 0x611da4, mask, data); +} + +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 nv50_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 nv50_disp *disp, struct nvkm_object **pobject) +{ + return gv100_disp_wndw_new_(&gv100_disp_wndw, &gv100_disp_wndw_mthd, + disp, 1, oclass, argv, argc, pobject); +} |